]> Git Repo - u-boot.git/blob - lib/efi/efi_app.c
common: Drop asm/global_data.h from common header
[u-boot.git] / lib / efi / efi_app.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2015 Google, Inc
4  *
5  * EFI information obtained here:
6  * http://wiki.phoenix.com/wiki/index.php/EFI_BOOT_SERVICES
7  *
8  * This file implements U-Boot running as an EFI application.
9  */
10
11 #include <common.h>
12 #include <cpu_func.h>
13 #include <debug_uart.h>
14 #include <dm.h>
15 #include <errno.h>
16 #include <init.h>
17 #include <malloc.h>
18 #include <asm/global_data.h>
19 #include <linux/err.h>
20 #include <linux/types.h>
21 #include <efi.h>
22 #include <efi_api.h>
23 #include <sysreset.h>
24
25 DECLARE_GLOBAL_DATA_PTR;
26
27 static struct efi_priv *global_priv;
28
29 struct efi_system_table *efi_get_sys_table(void)
30 {
31         return global_priv->sys_table;
32 }
33
34 unsigned long efi_get_ram_base(void)
35 {
36         return global_priv->ram_base;
37 }
38
39 static efi_status_t setup_memory(struct efi_priv *priv)
40 {
41         struct efi_boot_services *boot = priv->boot;
42         efi_physical_addr_t addr;
43         efi_status_t ret;
44         int pages;
45
46         /*
47          * Use global_data_ptr instead of gd since it is an assignment. There
48          * are very few assignments to global_data in U-Boot and this makes
49          * it easier to find them.
50          */
51         global_data_ptr = efi_malloc(priv, sizeof(struct global_data), &ret);
52         if (!global_data_ptr)
53                 return ret;
54         memset(gd, '\0', sizeof(*gd));
55
56         gd->malloc_base = (ulong)efi_malloc(priv, CONFIG_VAL(SYS_MALLOC_F_LEN),
57                                             &ret);
58         if (!gd->malloc_base)
59                 return ret;
60         pages = CONFIG_EFI_RAM_SIZE >> 12;
61
62         /*
63          * Don't allocate any memory above 4GB. U-Boot is a 32-bit application
64          * so we want it to load below 4GB.
65          */
66         addr = 1ULL << 32;
67         ret = boot->allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
68                                    priv->image_data_type, pages, &addr);
69         if (ret) {
70                 printf("(using pool %lx) ", ret);
71                 priv->ram_base = (ulong)efi_malloc(priv, CONFIG_EFI_RAM_SIZE,
72                                                    &ret);
73                 if (!priv->ram_base)
74                         return ret;
75                 priv->use_pool_for_malloc = true;
76         } else {
77                 priv->ram_base = addr;
78         }
79         gd->ram_size = pages << 12;
80
81         return 0;
82 }
83
84 static void free_memory(struct efi_priv *priv)
85 {
86         struct efi_boot_services *boot = priv->boot;
87
88         if (priv->use_pool_for_malloc)
89                 efi_free(priv, (void *)priv->ram_base);
90         else
91                 boot->free_pages(priv->ram_base, gd->ram_size >> 12);
92
93         efi_free(priv, (void *)gd->malloc_base);
94         efi_free(priv, gd);
95         global_data_ptr = NULL;
96 }
97
98 /**
99  * efi_main() - Start an EFI image
100  *
101  * This function is called by our EFI start-up code. It handles running
102  * U-Boot. If it returns, EFI will continue. Another way to get back to EFI
103  * is via reset_cpu().
104  */
105 efi_status_t EFIAPI efi_main(efi_handle_t image,
106                              struct efi_system_table *sys_table)
107 {
108         struct efi_priv local_priv, *priv = &local_priv;
109         efi_status_t ret;
110
111         /* Set up access to EFI data structures */
112         efi_init(priv, "App", image, sys_table);
113
114         global_priv = priv;
115
116         /*
117          * Set up the EFI debug UART so that printf() works. This is
118          * implemented in the EFI serial driver, serial_efi.c. The application
119          * can use printf() freely.
120          */
121         debug_uart_init();
122
123         ret = setup_memory(priv);
124         if (ret) {
125                 printf("Failed to set up memory: ret=%lx\n", ret);
126                 return ret;
127         }
128
129         printf("starting\n");
130
131         board_init_f(GD_FLG_SKIP_RELOC);
132         board_init_r(NULL, 0);
133         free_memory(priv);
134
135         return EFI_SUCCESS;
136 }
137
138 static void efi_exit(void)
139 {
140         struct efi_priv *priv = global_priv;
141
142         free_memory(priv);
143         printf("U-Boot EFI exiting\n");
144         priv->boot->exit(priv->parent_image, EFI_SUCCESS, 0, NULL);
145 }
146
147 static int efi_sysreset_request(struct udevice *dev, enum sysreset_t type)
148 {
149         efi_exit();
150
151         return -EINPROGRESS;
152 }
153
154 static const struct udevice_id efi_sysreset_ids[] = {
155         { .compatible = "efi,reset" },
156         { }
157 };
158
159 static struct sysreset_ops efi_sysreset_ops = {
160         .request = efi_sysreset_request,
161 };
162
163 U_BOOT_DRIVER(efi_sysreset) = {
164         .name = "efi-sysreset",
165         .id = UCLASS_SYSRESET,
166         .of_match = efi_sysreset_ids,
167         .ops = &efi_sysreset_ops,
168 };
This page took 0.035333 seconds and 4 git commands to generate.