Blame view
cmd/bootefi.c
18.2 KB
f739fcd83 SPDX: Convert a f... |
1 |
// SPDX-License-Identifier: GPL-2.0+ |
b9939336d efi_loader: Add "... |
2 3 4 5 |
/* * EFI application loader * * Copyright (c) 2016 Alexander Graf |
b9939336d efi_loader: Add "... |
6 7 8 |
*/ #include <common.h> |
f6c6df7eb efi_loader: refac... |
9 |
#include <charset.h> |
b9939336d efi_loader: Add "... |
10 |
#include <command.h> |
9d922450a dm: Use dm.h head... |
11 |
#include <dm.h> |
b9939336d efi_loader: Add "... |
12 |
#include <efi_loader.h> |
d78e40d65 efi_selftest: all... |
13 |
#include <efi_selftest.h> |
7b51b576d env: Move env_get... |
14 |
#include <env.h> |
b9939336d efi_loader: Add "... |
15 |
#include <errno.h> |
336d4615f dm: core: Create ... |
16 |
#include <malloc.h> |
b08c8c487 libfdt: move head... |
17 18 |
#include <linux/libfdt.h> #include <linux/libfdt_env.h> |
354264b31 efi_loader: Use m... |
19 |
#include <mapmem.h> |
ad0c1a3d2 efi_loader: Put f... |
20 |
#include <memalign.h> |
e275458c2 efi: Fix missing ... |
21 22 |
#include <asm-generic/sections.h> #include <linux/linkage.h> |
0d9d501f3 efi_loader: Use s... |
23 24 |
DECLARE_GLOBAL_DATA_PTR; |
b9939336d efi_loader: Add "... |
25 |
|
95c5553ea efi_loader: refac... |
26 27 |
static struct efi_device_path *bootefi_image_path; static struct efi_device_path *bootefi_device_path; |
b9939336d efi_loader: Add "... |
28 |
|
810371a0b efi_loader: fix f... |
29 |
/** |
d78e40d65 efi_selftest: all... |
30 31 |
* Set the load options of an image from an environment variable. * |
a3850e40e efi_loader: free ... |
32 33 34 35 |
* @handle: the image handle * @env_var: name of the environment variable * @load_options: pointer to load options (output) * Return: status code |
d78e40d65 efi_selftest: all... |
36 |
*/ |
a3850e40e efi_loader: free ... |
37 38 |
static efi_status_t set_load_options(efi_handle_t handle, const char *env_var, u16 **load_options) |
d78e40d65 efi_selftest: all... |
39 |
{ |
defa7b8ed cmd: bootefi: rew... |
40 |
struct efi_loaded_image *loaded_image_info; |
d78e40d65 efi_selftest: all... |
41 42 |
size_t size; const char *env = env_get(env_var); |
7086a71aa efi_loader: buffe... |
43 |
u16 *pos; |
defa7b8ed cmd: bootefi: rew... |
44 |
efi_status_t ret; |
a3850e40e efi_loader: free ... |
45 |
*load_options = NULL; |
defa7b8ed cmd: bootefi: rew... |
46 47 48 49 50 51 52 53 |
ret = EFI_CALL(systab.boottime->open_protocol( handle, &efi_guid_loaded_image, (void **)&loaded_image_info, efi_root, NULL, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL)); if (ret != EFI_SUCCESS) return EFI_INVALID_PARAMETER; |
d78e40d65 efi_selftest: all... |
54 55 56 57 |
loaded_image_info->load_options = NULL; loaded_image_info->load_options_size = 0; if (!env) |
defa7b8ed cmd: bootefi: rew... |
58 |
goto out; |
7086a71aa efi_loader: buffe... |
59 |
size = utf8_utf16_strlen(env) + 1; |
d78e40d65 efi_selftest: all... |
60 61 62 63 |
loaded_image_info->load_options = calloc(size, sizeof(u16)); if (!loaded_image_info->load_options) { printf("ERROR: Out of memory "); |
defa7b8ed cmd: bootefi: rew... |
64 65 66 67 |
EFI_CALL(systab.boottime->close_protocol(handle, &efi_guid_loaded_image, efi_root, NULL)); return EFI_OUT_OF_RESOURCES; |
d78e40d65 efi_selftest: all... |
68 |
} |
7086a71aa efi_loader: buffe... |
69 |
pos = loaded_image_info->load_options; |
a3850e40e efi_loader: free ... |
70 |
*load_options = pos; |
7086a71aa efi_loader: buffe... |
71 |
utf8_utf16_strcpy(&pos, env); |
d78e40d65 efi_selftest: all... |
72 |
loaded_image_info->load_options_size = size * 2; |
defa7b8ed cmd: bootefi: rew... |
73 74 75 76 77 |
out: return EFI_CALL(systab.boottime->close_protocol(handle, &efi_guid_loaded_image, efi_root, NULL)); |
d78e40d65 efi_selftest: all... |
78 |
} |
6182495e1 efi_loader: need ... |
79 |
#if !CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE) |
9dff49008 efi: sandbox: Tid... |
80 81 82 |
/** * copy_fdt() - Copy the device tree to a new location available to EFI * |
16b615d9a efi_loader: fix m... |
83 |
* The FDT is copied to a suitable location within the EFI memory map. |
c3772ca1e efi_loader: macro... |
84 |
* Additional 12 KiB are added to the space in case the device tree needs to be |
9dff49008 efi: sandbox: Tid... |
85 86 |
* expanded later with fdt_open_into(). * |
16b615d9a efi_loader: fix m... |
87 88 |
* @fdtp: On entry a pointer to the flattened device tree. * On exit a pointer to the copy of the flattened device tree. |
4574d1b3d efi_loader: memor... |
89 90 |
* FDT start * Return: status code |
9dff49008 efi: sandbox: Tid... |
91 |
*/ |
16b615d9a efi_loader: fix m... |
92 |
static efi_status_t copy_fdt(void **fdtp) |
0d9d501f3 efi_loader: Use s... |
93 |
{ |
ad0c1a3d2 efi_loader: Put f... |
94 |
unsigned long fdt_ram_start = -1L, fdt_pages; |
9dff49008 efi: sandbox: Tid... |
95 96 |
efi_status_t ret = 0; void *fdt, *new_fdt; |
ad0c1a3d2 efi_loader: Put f... |
97 |
u64 new_fdt_addr; |
9dff49008 efi: sandbox: Tid... |
98 |
uint fdt_size; |
ad0c1a3d2 efi_loader: Put f... |
99 |
int i; |
0d9d501f3 efi_loader: Use s... |
100 |
|
9dff49008 efi: sandbox: Tid... |
101 102 103 |
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { u64 ram_start = gd->bd->bi_dram[i].start; u64 ram_size = gd->bd->bi_dram[i].size; |
0d9d501f3 efi_loader: Use s... |
104 |
|
ad0c1a3d2 efi_loader: Put f... |
105 106 107 108 109 110 |
if (!ram_size) continue; if (ram_start < fdt_ram_start) fdt_ram_start = ram_start; } |
bc9a638a1 efi: Tidy up devi... |
111 |
/* |
c3772ca1e efi_loader: macro... |
112 113 |
* Give us at least 12 KiB of breathing room in case the device tree * needs to be expanded later. |
bc9a638a1 efi: Tidy up devi... |
114 |
*/ |
16b615d9a efi_loader: fix m... |
115 |
fdt = *fdtp; |
c3772ca1e efi_loader: macro... |
116 117 |
fdt_pages = efi_size_in_pages(fdt_totalsize(fdt) + 0x3000); fdt_size = fdt_pages << EFI_PAGE_SHIFT; |
ad0c1a3d2 efi_loader: Put f... |
118 |
|
16b615d9a efi_loader: fix m... |
119 120 121 122 123 124 |
/* * Safe fdt location is at 127 MiB. * On the sandbox convert from the sandbox address space. */ new_fdt_addr = (uintptr_t)map_sysmem(fdt_ram_start + 0x7f00000 + fdt_size, 0); |
9dff49008 efi: sandbox: Tid... |
125 |
ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS, |
29361ec47 Change FDT memory... |
126 |
EFI_BOOT_SERVICES_DATA, fdt_pages, |
9dff49008 efi: sandbox: Tid... |
127 128 |
&new_fdt_addr); if (ret != EFI_SUCCESS) { |
ad0c1a3d2 efi_loader: Put f... |
129 |
/* If we can't put it there, put it somewhere */ |
a44bffcc9 efi_loader: use E... |
130 |
new_fdt_addr = (ulong)memalign(EFI_PAGE_SIZE, fdt_size); |
9dff49008 efi: sandbox: Tid... |
131 |
ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS, |
29361ec47 Change FDT memory... |
132 |
EFI_BOOT_SERVICES_DATA, fdt_pages, |
9dff49008 efi: sandbox: Tid... |
133 134 |
&new_fdt_addr); if (ret != EFI_SUCCESS) { |
85a6e9b3c efi_loader: Add c... |
135 136 |
printf("ERROR: Failed to reserve space for FDT "); |
9dff49008 efi: sandbox: Tid... |
137 |
goto done; |
85a6e9b3c efi_loader: Add c... |
138 |
} |
ad0c1a3d2 efi_loader: Put f... |
139 |
} |
16b615d9a efi_loader: fix m... |
140 |
new_fdt = (void *)(uintptr_t)new_fdt_addr; |
0d9d501f3 efi_loader: Use s... |
141 142 |
memcpy(new_fdt, fdt, fdt_totalsize(fdt)); fdt_set_totalsize(new_fdt, fdt_size); |
16b615d9a efi_loader: fix m... |
143 |
*fdtp = (void *)(uintptr_t)new_fdt_addr; |
9dff49008 efi: sandbox: Tid... |
144 145 |
done: return ret; |
0d9d501f3 efi_loader: Use s... |
146 |
} |
7be64b885 cmd: bootefi: Par... |
147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
static void efi_reserve_memory(u64 addr, u64 size) { u64 pages; /* Convert from sandbox address space. */ addr = (uintptr_t)map_sysmem(addr, 0); pages = efi_size_in_pages(size + (addr & EFI_PAGE_MASK)); addr &= ~EFI_PAGE_MASK; if (efi_add_memory_map(addr, pages, EFI_RESERVED_MEMORY_TYPE, false) != EFI_SUCCESS) printf("Reserved memory mapping failed addr %llx size %llx ", addr, size); } |
810371a0b efi_loader: fix f... |
161 |
/** |
416e07e2c efi: Drop error r... |
162 163 164 165 166 167 168 169 170 |
* efi_carve_out_dt_rsv() - Carve out DT reserved memory ranges * * The mem_rsv entries of the FDT are added to the memory map. Any failures are * ignored because this is not critical and we would rather continue to try to * boot. * * @fdt: Pointer to device tree */ static void efi_carve_out_dt_rsv(void *fdt) |
806d2fa8e efi_loader: Respe... |
171 172 |
{ int nr_rsv, i; |
7be64b885 cmd: bootefi: Par... |
173 174 |
u64 addr, size; int nodeoffset, subnode; |
806d2fa8e efi_loader: Respe... |
175 176 177 178 179 180 181 |
nr_rsv = fdt_num_mem_rsv(fdt); /* Look for an existing entry and add it to the efi mem map. */ for (i = 0; i < nr_rsv; i++) { if (fdt_get_mem_rsv(fdt, i, &addr, &size) != 0) continue; |
7be64b885 cmd: bootefi: Par... |
182 183 |
efi_reserve_memory(addr, size); } |
806d2fa8e efi_loader: Respe... |
184 |
|
7be64b885 cmd: bootefi: Par... |
185 186 187 188 189 190 191 192 193 194 195 196 |
/* process reserved-memory */ nodeoffset = fdt_subnode_offset(fdt, 0, "reserved-memory"); if (nodeoffset >= 0) { subnode = fdt_first_subnode(fdt, nodeoffset); while (subnode >= 0) { /* check if this subnode has a reg property */ addr = fdtdec_get_addr_size(fdt, subnode, "reg", (fdt_size_t *)&size); /* * The /reserved-memory node may have children with * a size instead of a reg property. */ |
4ef2b0d55 efi_loader: only ... |
197 198 |
if (addr != FDT_ADDR_T_NONE && fdtdec_get_is_enabled(fdt, subnode)) |
7be64b885 cmd: bootefi: Par... |
199 200 201 |
efi_reserve_memory(addr, size); subnode = fdt_next_subnode(fdt, subnode); } |
806d2fa8e efi_loader: Respe... |
202 |
} |
806d2fa8e efi_loader: Respe... |
203 |
} |
e878e6a7d cmd: bootefi: car... |
204 |
/** |
6182495e1 efi_loader: need ... |
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
* get_config_table() - get configuration table * * @guid: GUID of the configuration table * Return: pointer to configuration table or NULL */ static void *get_config_table(const efi_guid_t *guid) { size_t i; for (i = 0; i < systab.nr_tables; i++) { if (!guidcmp(guid, &systab.tables[i].guid)) return systab.tables[i].table; } return NULL; } #endif /* !CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE) */ /** |
7a597259d efi_loader: pass ... |
224 |
* efi_install_fdt() - install device tree |
e2d82f8b2 efi_loader: comme... |
225 |
* |
7d4d551e7 efi_loader: fix e... |
226 227 228 229 |
* If fdt is not EFI_FDT_USE_INTERNAL, the device tree located at that memory * address will will be installed as configuration table, otherwise the device * tree located at the address indicated by environment variable fdt_addr or as * fallback fdtcontroladdr will be used. |
e2d82f8b2 efi_loader: comme... |
230 |
* |
7a597259d efi_loader: pass ... |
231 232 |
* On architectures using ACPI tables device trees shall not be installed as * configuration table. |
e2d82f8b2 efi_loader: comme... |
233 |
* |
7d4d551e7 efi_loader: fix e... |
234 |
* @fdt: address of device tree or EFI_FDT_USE_INTERNAL to use the |
753aa18f1 efi_loader: use h... |
235 236 237 |
* the hardware device tree as indicated by environment variable * fdt_addr or as fallback the internal device tree as indicated by * the environment variable fdtcontroladdr |
e878e6a7d cmd: bootefi: car... |
238 |
* Return: status code |
e878e6a7d cmd: bootefi: car... |
239 |
*/ |
f64f22325 efi_loader: expor... |
240 |
efi_status_t efi_install_fdt(void *fdt) |
e878e6a7d cmd: bootefi: car... |
241 |
{ |
6182495e1 efi_loader: need ... |
242 243 244 245 246 |
/* * The EBBR spec requires that we have either an FDT or an ACPI table * but not both. */ #if CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE) |
f64f22325 efi_loader: expor... |
247 |
if (fdt) { |
6182495e1 efi_loader: need ... |
248 249 250 251 252 |
printf("ERROR: can't have ACPI table and device tree. "); return EFI_LOAD_ERROR; } #else |
3ffc52fd2 cmd: bootefi: mer... |
253 |
bootm_headers_t img = { 0 }; |
e878e6a7d cmd: bootefi: car... |
254 |
efi_status_t ret; |
f64f22325 efi_loader: expor... |
255 |
if (fdt == EFI_FDT_USE_INTERNAL) { |
7a597259d efi_loader: pass ... |
256 |
const char *fdt_opt; |
f64f22325 efi_loader: expor... |
257 |
uintptr_t fdt_addr; |
7a597259d efi_loader: pass ... |
258 |
|
6182495e1 efi_loader: need ... |
259 260 261 |
/* Look for device tree that is already installed */ if (get_config_table(&efi_guid_fdt)) return EFI_SUCCESS; |
753aa18f1 efi_loader: use h... |
262 263 264 |
/* Check if there is a hardware device tree */ fdt_opt = env_get("fdt_addr"); /* Use our own device tree as fallback */ |
6182495e1 efi_loader: need ... |
265 |
if (!fdt_opt) { |
753aa18f1 efi_loader: use h... |
266 267 268 269 270 271 |
fdt_opt = env_get("fdtcontroladdr"); if (!fdt_opt) { printf("ERROR: need device tree "); return EFI_NOT_FOUND; } |
6182495e1 efi_loader: need ... |
272 273 274 |
} fdt_addr = simple_strtoul(fdt_opt, NULL, 16); if (!fdt_addr) { |
753aa18f1 efi_loader: use h... |
275 276 |
printf("ERROR: invalid $fdt_addr or $fdtcontroladdr "); |
6182495e1 efi_loader: need ... |
277 |
return EFI_LOAD_ERROR; |
3ffc52fd2 cmd: bootefi: mer... |
278 |
} |
f64f22325 efi_loader: expor... |
279 |
fdt = map_sysmem(fdt_addr, 0); |
6182495e1 efi_loader: need ... |
280 |
} |
3ffc52fd2 cmd: bootefi: mer... |
281 |
|
6182495e1 efi_loader: need ... |
282 |
/* Install device tree */ |
6182495e1 efi_loader: need ... |
283 284 285 286 287 |
if (fdt_check_header(fdt)) { printf("ERROR: invalid device tree "); return EFI_LOAD_ERROR; } |
3ffc52fd2 cmd: bootefi: mer... |
288 |
|
6182495e1 efi_loader: need ... |
289 290 291 292 293 294 295 |
/* Prepare device tree for payload */ ret = copy_fdt(&fdt); if (ret) { printf("ERROR: out of memory "); return EFI_OUT_OF_RESOURCES; } |
3ffc52fd2 cmd: bootefi: mer... |
296 |
|
6182495e1 efi_loader: need ... |
297 298 299 300 301 |
if (image_setup_libfdt(&img, fdt, 0, NULL)) { printf("ERROR: failed to process device tree "); return EFI_LOAD_ERROR; } |
fef907b2e efi_loader: creat... |
302 303 |
/* Create memory reservations as indicated by the device tree */ efi_carve_out_dt_rsv(fdt); |
6182495e1 efi_loader: need ... |
304 305 306 307 308 309 |
/* Install device tree as UEFI table */ ret = efi_install_configuration_table(&efi_guid_fdt, fdt); if (ret != EFI_SUCCESS) { printf("ERROR: failed to install device tree "); return ret; |
e878e6a7d cmd: bootefi: car... |
310 |
} |
6182495e1 efi_loader: need ... |
311 |
#endif /* GENERATE_ACPI_TABLE */ |
e878e6a7d cmd: bootefi: car... |
312 313 314 |
return EFI_SUCCESS; } |
5e2f03910 efi: Rename boote... |
315 |
/** |
c982874e9 efi_loader: refac... |
316 317 |
* do_bootefi_exec() - execute EFI binary * |
6b95b38c4 efi_loader: rewor... |
318 |
* @handle: handle of loaded image |
c982874e9 efi_loader: refac... |
319 320 321 322 |
* Return: status code * * Load the EFI binary into a newly assigned memory unwinding the relocation * information, install the loaded image protocol, and call the binary. |
b9939336d efi_loader: Add "... |
323 |
*/ |
6b95b38c4 efi_loader: rewor... |
324 |
static efi_status_t do_bootefi_exec(efi_handle_t handle) |
b9939336d efi_loader: Add "... |
325 |
{ |
45204b102 efi_loader: do_bo... |
326 |
efi_status_t ret; |
556d8dc93 efi_loader: imple... |
327 328 |
efi_uintn_t exit_data_size = 0; u16 *exit_data = NULL; |
a3850e40e efi_loader: free ... |
329 |
u16 *load_options; |
95c5553ea efi_loader: refac... |
330 |
|
3fc2b1633 cmd: bootefi: car... |
331 |
/* Transfer environment variable as load options */ |
a3850e40e efi_loader: free ... |
332 |
ret = set_load_options(handle, "bootargs", &load_options); |
8f7e2b298 efi_loader: set e... |
333 |
if (ret != EFI_SUCCESS) |
6b95b38c4 efi_loader: rewor... |
334 |
return ret; |
bf19273e8 efi_loader: Add m... |
335 |
|
b9939336d efi_loader: Add "... |
336 |
/* Call our payload! */ |
556d8dc93 efi_loader: imple... |
337 338 339 340 341 342 343 344 |
ret = EFI_CALL(efi_start_image(handle, &exit_data_size, &exit_data)); printf("## Application terminated, r = %lu ", ret & ~EFI_ERROR_MASK); if (ret && exit_data) { printf("## %ls ", exit_data); efi_free_pool(exit_data); } |
95c5553ea efi_loader: refac... |
345 |
|
3fc2b1633 cmd: bootefi: car... |
346 |
efi_restore_gd(); |
5e2f03910 efi: Rename boote... |
347 |
|
a3850e40e efi_loader: free ... |
348 |
free(load_options); |
95c5553ea efi_loader: refac... |
349 350 |
return ret; |
b9939336d efi_loader: Add "... |
351 |
} |
d6b21894d cmd: bootefi: car... |
352 |
/** |
7e92db810 efi_loader: dedup... |
353 |
* do_efibootmgr() - execute EFI boot manager |
d6b21894d cmd: bootefi: car... |
354 |
* |
d6b21894d cmd: bootefi: car... |
355 |
* Return: status code |
d6b21894d cmd: bootefi: car... |
356 |
*/ |
7e92db810 efi_loader: dedup... |
357 |
static int do_efibootmgr(void) |
cc999d58e cmd: bootefi: mov... |
358 |
{ |
6b95b38c4 efi_loader: rewor... |
359 |
efi_handle_t handle; |
d6b21894d cmd: bootefi: car... |
360 |
efi_status_t ret; |
6b95b38c4 efi_loader: rewor... |
361 362 363 364 365 366 |
ret = efi_bootmgr_load(&handle); if (ret != EFI_SUCCESS) { printf("EFI boot manager: Cannot load any image "); return CMD_RET_FAILURE; } |
cc999d58e cmd: bootefi: mov... |
367 |
|
6b95b38c4 efi_loader: rewor... |
368 |
ret = do_bootefi_exec(handle); |
cc999d58e cmd: bootefi: mov... |
369 |
|
d6b21894d cmd: bootefi: car... |
370 |
if (ret != EFI_SUCCESS) |
6b95b38c4 efi_loader: rewor... |
371 |
return CMD_RET_FAILURE; |
cc999d58e cmd: bootefi: mov... |
372 |
|
6b95b38c4 efi_loader: rewor... |
373 |
return CMD_RET_SUCCESS; |
cc999d58e cmd: bootefi: mov... |
374 |
} |
810371a0b efi_loader: fix f... |
375 |
/** |
7e92db810 efi_loader: dedup... |
376 377 378 379 |
* do_bootefi_image() - execute EFI binary * * Set up memory image for the binary to be loaded, prepare device path, and * then call do_bootefi_exec() to execute it. |
e2e4098e1 cmd: bootefi: car... |
380 381 |
* * @image_opt: string of image start address |
e2e4098e1 cmd: bootefi: car... |
382 |
* Return: status code |
e2e4098e1 cmd: bootefi: car... |
383 |
*/ |
7e92db810 efi_loader: dedup... |
384 |
static int do_bootefi_image(const char *image_opt) |
e2e4098e1 cmd: bootefi: car... |
385 |
{ |
6b95b38c4 efi_loader: rewor... |
386 |
void *image_buf; |
6b95b38c4 efi_loader: rewor... |
387 388 |
unsigned long addr, size; const char *size_str; |
e2e4098e1 cmd: bootefi: car... |
389 |
efi_status_t ret; |
e2e4098e1 cmd: bootefi: car... |
390 391 392 |
#ifdef CONFIG_CMD_BOOTEFI_HELLO if (!strcmp(image_opt, "hello")) { char *saddr; |
e2e4098e1 cmd: bootefi: car... |
393 394 |
saddr = env_get("loadaddr"); |
6b95b38c4 efi_loader: rewor... |
395 |
size = __efi_helloworld_end - __efi_helloworld_begin; |
e2e4098e1 cmd: bootefi: car... |
396 397 398 399 |
if (saddr) addr = simple_strtoul(saddr, NULL, 16); else addr = CONFIG_SYS_LOAD_ADDR; |
6b95b38c4 efi_loader: rewor... |
400 401 402 |
image_buf = map_sysmem(addr, size); memcpy(image_buf, __efi_helloworld_begin, size); |
f9ceb6ac1 efi_loader: carve... |
403 404 405 406 |
efi_free_pool(bootefi_device_path); efi_free_pool(bootefi_image_path); bootefi_device_path = NULL; bootefi_image_path = NULL; |
e2e4098e1 cmd: bootefi: car... |
407 408 409 |
} else #endif { |
6b95b38c4 efi_loader: rewor... |
410 411 412 413 414 |
size_str = env_get("filesize"); if (size_str) size = simple_strtoul(size_str, NULL, 16); else size = 0; |
e2e4098e1 cmd: bootefi: car... |
415 416 417 418 |
addr = simple_strtoul(image_opt, NULL, 16); /* Check that a numeric value was passed */ if (!addr && *image_opt != '0') return CMD_RET_USAGE; |
6b95b38c4 efi_loader: rewor... |
419 420 |
image_buf = map_sysmem(addr, size); |
e2e4098e1 cmd: bootefi: car... |
421 |
} |
f9ceb6ac1 efi_loader: carve... |
422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 |
ret = efi_run_image(image_buf, size); if (ret != EFI_SUCCESS) return CMD_RET_FAILURE; return CMD_RET_SUCCESS; } /** * efi_run_image() - run loaded UEFI image * * @source_buffer: memory address of the UEFI image * @source_size: size of the UEFI image * Return: status code */ efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size) { efi_handle_t mem_handle = NULL, handle; struct efi_device_path *file_path = NULL; efi_status_t ret; |
e2e4098e1 cmd: bootefi: car... |
442 |
|
f9ceb6ac1 efi_loader: carve... |
443 |
if (!bootefi_device_path || !bootefi_image_path) { |
6b95b38c4 efi_loader: rewor... |
444 445 446 447 448 449 |
/* * Special case for efi payload not loaded from disk, * such as 'bootefi hello' or for example payload * loaded directly into memory via JTAG, etc: */ file_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, |
f9ceb6ac1 efi_loader: carve... |
450 451 |
(uintptr_t)source_buffer, source_size); |
6b95b38c4 efi_loader: rewor... |
452 453 454 455 456 457 458 459 460 461 462 463 464 |
/* * Make sure that device for device_path exist * in load_image(). Otherwise, shell and grub will fail. */ ret = efi_create_handle(&mem_handle); if (ret != EFI_SUCCESS) goto out; ret = efi_add_protocol(mem_handle, &efi_guid_device_path, file_path); if (ret != EFI_SUCCESS) goto out; } else { |
f9ceb6ac1 efi_loader: carve... |
465 466 |
file_path = efi_dp_append(bootefi_device_path, bootefi_image_path); |
6b95b38c4 efi_loader: rewor... |
467 |
} |
f9ceb6ac1 efi_loader: carve... |
468 469 |
ret = EFI_CALL(efi_load_image(false, efi_root, file_path, source_buffer, source_size, &handle)); |
6b95b38c4 efi_loader: rewor... |
470 471 472 473 |
if (ret != EFI_SUCCESS) goto out; ret = do_bootefi_exec(handle); |
6b95b38c4 efi_loader: rewor... |
474 475 476 477 478 479 |
out: if (mem_handle) efi_delete_handle(mem_handle); if (file_path) efi_free_pool(file_path); |
f9ceb6ac1 efi_loader: carve... |
480 |
return ret; |
e2e4098e1 cmd: bootefi: car... |
481 |
} |
d9717eae3 efi: Split out te... |
482 |
#ifdef CONFIG_CMD_BOOTEFI_SELFTEST |
3fc2b1633 cmd: bootefi: car... |
483 484 485 486 487 488 489 |
static efi_status_t bootefi_run_prepare(const char *load_options_path, struct efi_device_path *device_path, struct efi_device_path *image_path, struct efi_loaded_image_obj **image_objp, struct efi_loaded_image **loaded_image_infop) { efi_status_t ret; |
a3850e40e efi_loader: free ... |
490 |
u16 *load_options; |
3fc2b1633 cmd: bootefi: car... |
491 492 493 494 495 496 497 |
ret = efi_setup_loaded_image(device_path, image_path, image_objp, loaded_image_infop); if (ret != EFI_SUCCESS) return ret; /* Transfer environment variable as load options */ |
a3850e40e efi_loader: free ... |
498 499 |
return set_load_options((efi_handle_t)*image_objp, load_options_path, &load_options); |
3fc2b1633 cmd: bootefi: car... |
500 |
} |
d9717eae3 efi: Split out te... |
501 502 503 |
/** * bootefi_test_prepare() - prepare to run an EFI test * |
1504bb0d9 efi_loader: clean... |
504 |
* Prepare to run a test as if it were provided by a loaded image. |
d9717eae3 efi: Split out te... |
505 |
* |
1504bb0d9 efi_loader: clean... |
506 507 508 509 510 511 512 |
* @image_objp: pointer to be set to the loaded image handle * @loaded_image_infop: pointer to be set to the loaded image protocol * @path: dummy file path used to construct the device path * set in the loaded image protocol * @load_options_path: name of a U-Boot environment variable. Its value is * set as load options in the loaded image protocol. * Return: status code |
d9717eae3 efi: Split out te... |
513 514 515 |
*/ static efi_status_t bootefi_test_prepare (struct efi_loaded_image_obj **image_objp, |
1504bb0d9 efi_loader: clean... |
516 517 |
struct efi_loaded_image **loaded_image_infop, const char *path, const char *load_options_path) |
d9717eae3 efi: Split out te... |
518 |
{ |
1504bb0d9 efi_loader: clean... |
519 |
efi_status_t ret; |
d9717eae3 efi: Split out te... |
520 |
/* Construct a dummy device path */ |
1504bb0d9 efi_loader: clean... |
521 |
bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, 0, 0); |
d9717eae3 efi: Split out te... |
522 523 |
if (!bootefi_device_path) return EFI_OUT_OF_RESOURCES; |
1504bb0d9 efi_loader: clean... |
524 |
|
d9717eae3 efi: Split out te... |
525 |
bootefi_image_path = efi_dp_from_file(NULL, 0, path); |
1504bb0d9 efi_loader: clean... |
526 527 528 529 530 531 532 533 534 535 |
if (!bootefi_image_path) { ret = EFI_OUT_OF_RESOURCES; goto failure; } ret = bootefi_run_prepare(load_options_path, bootefi_device_path, bootefi_image_path, image_objp, loaded_image_infop); if (ret == EFI_SUCCESS) return ret; |
d9717eae3 efi: Split out te... |
536 |
|
1504bb0d9 efi_loader: clean... |
537 538 539 540 541 542 |
efi_free_pool(bootefi_image_path); bootefi_image_path = NULL; failure: efi_free_pool(bootefi_device_path); bootefi_device_path = NULL; return ret; |
d9717eae3 efi: Split out te... |
543 |
} |
3fc2b1633 cmd: bootefi: car... |
544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 |
/** * bootefi_run_finish() - finish up after running an EFI test * * @loaded_image_info: Pointer to a struct which holds the loaded image info * @image_obj: Pointer to a struct which holds the loaded image object */ static void bootefi_run_finish(struct efi_loaded_image_obj *image_obj, struct efi_loaded_image *loaded_image_info) { efi_restore_gd(); free(loaded_image_info->load_options); efi_delete_handle(&image_obj->header); } /** |
7e92db810 efi_loader: dedup... |
559 |
* do_efi_selftest() - execute EFI selftest |
3fc2b1633 cmd: bootefi: car... |
560 |
* |
3fc2b1633 cmd: bootefi: car... |
561 |
* Return: status code |
3fc2b1633 cmd: bootefi: car... |
562 |
*/ |
7e92db810 efi_loader: dedup... |
563 |
static int do_efi_selftest(void) |
3fc2b1633 cmd: bootefi: car... |
564 565 566 567 |
{ struct efi_loaded_image_obj *image_obj; struct efi_loaded_image *loaded_image_info; efi_status_t ret; |
3fc2b1633 cmd: bootefi: car... |
568 569 570 571 572 573 574 575 576 577 578 |
ret = bootefi_test_prepare(&image_obj, &loaded_image_info, "\\selftest", "efi_selftest"); if (ret != EFI_SUCCESS) return CMD_RET_FAILURE; /* Execute the test */ ret = EFI_CALL(efi_selftest(&image_obj->header, &systab)); bootefi_run_finish(image_obj, loaded_image_info); return ret != EFI_SUCCESS; } |
d9717eae3 efi: Split out te... |
579 |
#endif /* CONFIG_CMD_BOOTEFI_SELFTEST */ |
7e92db810 efi_loader: dedup... |
580 581 582 583 584 585 586 587 588 |
/** * do_bootefi() - execute `bootefi` command * * @cmdtp: table entry describing command * @flag: bitmap indicating how the command was invoked * @argc: number of arguments * @argv: command line arguments * Return: status code */ |
b9939336d efi_loader: Add "... |
589 590 |
static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { |
7e92db810 efi_loader: dedup... |
591 |
efi_status_t ret; |
f64f22325 efi_loader: expor... |
592 |
void *fdt; |
7e92db810 efi_loader: dedup... |
593 |
|
3fc2b1633 cmd: bootefi: car... |
594 595 |
if (argc < 2) return CMD_RET_USAGE; |
d6b21894d cmd: bootefi: car... |
596 |
|
7e92db810 efi_loader: dedup... |
597 598 599 600 601 602 603 604 |
/* Initialize EFI drivers */ ret = efi_init_obj_list(); if (ret != EFI_SUCCESS) { printf("Error: Cannot initialize UEFI sub-system, r = %lu ", ret & ~EFI_ERROR_MASK); return CMD_RET_FAILURE; } |
f64f22325 efi_loader: expor... |
605 606 |
if (argc > 2) { uintptr_t fdt_addr; |
7a597259d efi_loader: pass ... |
607 |
fdt_addr = simple_strtoul(argv[2], NULL, 16); |
f64f22325 efi_loader: expor... |
608 609 610 611 612 |
fdt = map_sysmem(fdt_addr, 0); } else { fdt = EFI_FDT_USE_INTERNAL; } ret = efi_install_fdt(fdt); |
7e92db810 efi_loader: dedup... |
613 614 615 616 |
if (ret == EFI_INVALID_PARAMETER) return CMD_RET_USAGE; else if (ret != EFI_SUCCESS) return CMD_RET_FAILURE; |
d6b21894d cmd: bootefi: car... |
617 |
if (!strcmp(argv[1], "bootmgr")) |
7e92db810 efi_loader: dedup... |
618 |
return do_efibootmgr(); |
3fc2b1633 cmd: bootefi: car... |
619 620 |
#ifdef CONFIG_CMD_BOOTEFI_SELFTEST else if (!strcmp(argv[1], "selftest")) |
7e92db810 efi_loader: dedup... |
621 |
return do_efi_selftest(); |
3fc2b1633 cmd: bootefi: car... |
622 |
#endif |
7e92db810 efi_loader: dedup... |
623 |
return do_bootefi_image(argv[1]); |
b9939336d efi_loader: Add "... |
624 625 626 627 |
} #ifdef CONFIG_SYS_LONGHELP static char bootefi_help_text[] = |
1c39809b9 efi_loader: Pass ... |
628 629 630 631 632 633 |
"<image address> [fdt address] " " - boot EFI payload stored at address <image address>. " " If specified, the device tree located at <fdt address> gets " |
c7ae3dfdc efi: Add support ... |
634 635 636 |
" exposed as EFI configuration table. " #ifdef CONFIG_CMD_BOOTEFI_HELLO |
623b3a579 efi_selftest: pro... |
637 638 639 640 641 642 |
"bootefi hello " " - boot a sample Hello World application stored within U-Boot " #endif #ifdef CONFIG_CMD_BOOTEFI_SELFTEST |
bc4f9133e efi_loader: suppo... |
643 644 |
"bootefi selftest [fdt address] " |
623b3a579 efi_selftest: pro... |
645 646 |
" - boot an EFI selftest application stored within U-Boot " |
d78e40d65 efi_selftest: all... |
647 648 649 650 |
" Use environment variable efi_selftest to select a single test. " " Use 'setenv efi_selftest list' to enumerate all tests. " |
c7ae3dfdc efi: Add support ... |
651 |
#endif |
6b95b38c4 efi_loader: rewor... |
652 653 |
"bootefi bootmgr [fdt address] " |
9975fe96b efi_loader: add b... |
654 655 656 657 658 659 660 661 |
" - load and boot EFI payload based on BootOrder/BootXXXX variables. " " " " If specified, the device tree located at <fdt address> gets " " exposed as EFI configuration table. "; |
b9939336d efi_loader: Add "... |
662 663 664 |
#endif U_BOOT_CMD( |
1c39809b9 efi_loader: Pass ... |
665 |
bootefi, 3, 0, do_bootefi, |
92dfd9221 cmd: bootefi: cos... |
666 |
"Boots an EFI payload from memory", |
b9939336d efi_loader: Add "... |
667 668 |
bootefi_help_text ); |
0f4060ebc efi_loader: Pass ... |
669 |
|
810371a0b efi_loader: fix f... |
670 671 672 673 674 675 676 677 678 679 |
/** * efi_set_bootdev() - set boot device * * This function is called when a file is loaded, e.g. via the 'load' command. * We use the path to this file to inform the UEFI binary about the boot device. * * @dev: device, e.g. "MMC" * @devnr: number of the device, e.g. "1:2" * @path: path to file loaded */ |
95c5553ea efi_loader: refac... |
680 681 |
void efi_set_bootdev(const char *dev, const char *devnr, const char *path) { |
f1589ffb3 efi_loader: add e... |
682 683 |
struct efi_device_path *device, *image; efi_status_t ret; |
f9d334bdf efi_loader: disk:... |
684 |
|
79276eb24 efi_loader: memor... |
685 686 687 |
/* efi_set_bootdev is typically called repeatedly, recover memory */ efi_free_pool(bootefi_device_path); efi_free_pool(bootefi_image_path); |
9975fe96b efi_loader: add b... |
688 |
|
f1589ffb3 efi_loader: add e... |
689 690 691 |
ret = efi_dp_from_name(dev, devnr, path, &device, &image); if (ret == EFI_SUCCESS) { bootefi_device_path = device; |
6b95b38c4 efi_loader: rewor... |
692 693 694 695 696 697 698 |
if (image) { /* FIXME: image should not contain device */ struct efi_device_path *image_tmp = image; efi_dp_split_file_path(image, &device, &image); efi_free_pool(image_tmp); } |
f1589ffb3 efi_loader: add e... |
699 |
bootefi_image_path = image; |
492716662 efi_loader: Make ... |
700 |
} else { |
f1589ffb3 efi_loader: add e... |
701 702 |
bootefi_device_path = NULL; bootefi_image_path = NULL; |
492716662 efi_loader: Make ... |
703 |
} |
0f4060ebc efi_loader: Pass ... |
704 |
} |