From faea1041054c355752dc61403fc885079daf015b Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 26 Sep 2018 05:27:54 +0200 Subject: efi_loader: typedef struct efi_object *efi_handle_t All our handles point to a struct efi_object. So let's define the efi_handle_t accordingly. This helps us to discover coding errors much more easily. This becomes evident by the corrections to the usage of handles in this patch. Rename variable image_handle to image_obj where applicable. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- cmd/bootefi.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'cmd') diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 4d68d80748..faa00f75c2 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -345,7 +345,7 @@ static efi_status_t do_bootefi_exec(void *efi, efi_handle_t mem_handle = NULL; struct efi_device_path *memdp = NULL; efi_status_t ret; - struct efi_loaded_image_obj *image_handle = NULL; + struct efi_loaded_image_obj *image_obj = NULL; struct efi_loaded_image *loaded_image_info = NULL; EFIAPI efi_status_t (*entry)(efi_handle_t image_handle, @@ -376,7 +376,7 @@ static efi_status_t do_bootefi_exec(void *efi, assert(device_path && image_path); } - ret = efi_setup_loaded_image(device_path, image_path, &image_handle, + ret = efi_setup_loaded_image(device_path, image_path, &image_obj, &loaded_image_info); if (ret != EFI_SUCCESS) goto exit; @@ -384,7 +384,7 @@ static efi_status_t do_bootefi_exec(void *efi, /* Transfer environment variable bootargs as load options */ set_load_options(loaded_image_info, "bootargs"); /* Load the EFI payload */ - entry = efi_load_pe(image_handle, efi, loaded_image_info); + entry = efi_load_pe(image_obj, efi, loaded_image_info); if (!entry) { ret = EFI_LOAD_ERROR; goto exit; @@ -405,8 +405,8 @@ static efi_status_t do_bootefi_exec(void *efi, /* Call our payload! */ debug("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry); - if (setjmp(&image_handle->exit_jmp)) { - ret = image_handle->exit_status; + if (setjmp(&image_obj->exit_jmp)) { + ret = image_obj->exit_status; goto exit; } @@ -418,7 +418,7 @@ static efi_status_t do_bootefi_exec(void *efi, /* Move into EL2 and keep running there */ armv8_switch_to_el2((ulong)entry, - (ulong)image_handle, + (ulong)&image_obj->parent, (ulong)&systab, 0, (ulong)efi_run_in_el2, ES_TO_AARCH64); @@ -435,7 +435,7 @@ static efi_status_t do_bootefi_exec(void *efi, secure_ram_addr(_do_nonsec_entry)( efi_run_in_hyp, (uintptr_t)entry, - (uintptr_t)image_handle, + (uintptr_t)&image_obj->parent, (uintptr_t)&systab); /* Should never reach here, efi exits with longjmp */ @@ -443,12 +443,12 @@ static efi_status_t do_bootefi_exec(void *efi, } #endif - ret = efi_do_enter(image_handle, &systab, entry); + ret = efi_do_enter(&image_obj->parent, &systab, entry); exit: /* image has returned, loaded-image obj goes *poof*: */ - if (image_handle) - efi_delete_handle(&image_handle->parent); + if (image_obj) + efi_delete_handle(&image_obj->parent); if (mem_handle) efi_delete_handle(mem_handle); @@ -527,7 +527,7 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) #endif #ifdef CONFIG_CMD_BOOTEFI_SELFTEST if (!strcmp(argv[1], "selftest")) { - struct efi_loaded_image_obj *image_handle; + struct efi_loaded_image_obj *image_obj; struct efi_loaded_image *loaded_image_info; /* Construct a dummy device path. */ @@ -537,7 +537,7 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) bootefi_image_path = efi_dp_from_file(NULL, 0, "\\selftest"); r = efi_setup_loaded_image(bootefi_device_path, - bootefi_image_path, &image_handle, + bootefi_image_path, &image_obj, &loaded_image_info); if (r != EFI_SUCCESS) return CMD_RET_FAILURE; @@ -546,10 +546,10 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) /* Transfer environment variable efi_selftest as load options */ set_load_options(loaded_image_info, "efi_selftest"); /* Execute the test */ - r = efi_selftest(image_handle, &systab); + r = efi_selftest(&image_obj->parent, &systab); efi_restore_gd(); free(loaded_image_info->load_options); - efi_delete_handle(&image_handle->parent); + efi_delete_handle(&image_obj->parent); return r != EFI_SUCCESS; } else #endif -- cgit v1.2.3 From d39646a38b504c377b5bcf282a2a9407f99b5f57 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 26 Sep 2018 05:27:56 +0200 Subject: efi_loader: rename parent to header Rename the component parent of some EFI objects to header. This avoids misunderstandings. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- cmd/bootefi.c | 12 ++++++------ include/efi_loader.h | 9 +++++++-- lib/efi_loader/efi_boottime.c | 6 +++--- lib/efi_loader/efi_disk.c | 38 +++++++++++++++++++++----------------- lib/efi_loader/efi_gop.c | 21 ++++++++++++++------- lib/efi_loader/efi_net.c | 22 ++++++++++++++-------- 6 files changed, 65 insertions(+), 43 deletions(-) (limited to 'cmd') diff --git a/cmd/bootefi.c b/cmd/bootefi.c index faa00f75c2..a1650d6cd1 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -418,7 +418,7 @@ static efi_status_t do_bootefi_exec(void *efi, /* Move into EL2 and keep running there */ armv8_switch_to_el2((ulong)entry, - (ulong)&image_obj->parent, + (ulong)&image_obj->header, (ulong)&systab, 0, (ulong)efi_run_in_el2, ES_TO_AARCH64); @@ -435,7 +435,7 @@ static efi_status_t do_bootefi_exec(void *efi, secure_ram_addr(_do_nonsec_entry)( efi_run_in_hyp, (uintptr_t)entry, - (uintptr_t)&image_obj->parent, + (uintptr_t)&image_obj->header, (uintptr_t)&systab); /* Should never reach here, efi exits with longjmp */ @@ -443,12 +443,12 @@ static efi_status_t do_bootefi_exec(void *efi, } #endif - ret = efi_do_enter(&image_obj->parent, &systab, entry); + ret = efi_do_enter(&image_obj->header, &systab, entry); exit: /* image has returned, loaded-image obj goes *poof*: */ if (image_obj) - efi_delete_handle(&image_obj->parent); + efi_delete_handle(&image_obj->header); if (mem_handle) efi_delete_handle(mem_handle); @@ -546,10 +546,10 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) /* Transfer environment variable efi_selftest as load options */ set_load_options(loaded_image_info, "efi_selftest"); /* Execute the test */ - r = efi_selftest(&image_obj->parent, &systab); + r = efi_selftest(&image_obj->header, &systab); efi_restore_gd(); free(loaded_image_info->load_options); - efi_delete_handle(&image_obj->parent); + efi_delete_handle(&image_obj->header); return r != EFI_SUCCESS; } else #endif diff --git a/include/efi_loader.h b/include/efi_loader.h index 1c79905aac..7a8aa2913a 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -193,10 +193,15 @@ struct efi_object { /** * struct efi_loaded_image_obj - handle of a loaded image + * + * @header: EFI object header + * @reloc_base: base address for the relocated image + * @reloc_size: size of the relocated image + * @exit_jmp: long jump buffer for returning form started image + * @entry: entry address of the relocated image */ struct efi_loaded_image_obj { - /* Generic EFI object parent class data */ - struct efi_object parent; + struct efi_object header; void *reloc_base; aligned_u64 reloc_size; efi_status_t exit_status; diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 397647073c..e3d911fad6 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1518,7 +1518,7 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, } /* Add internal object to object list */ - efi_add_handle(&obj->parent); + efi_add_handle(&obj->header); if (info_ptr) *info_ptr = info; @@ -1535,7 +1535,7 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, * When asking for the device path interface, return * bootefi_device_path */ - ret = efi_add_protocol(&obj->parent, + ret = efi_add_protocol(&obj->header, &efi_guid_device_path, device_path); if (ret != EFI_SUCCESS) goto failure; @@ -1545,7 +1545,7 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, * When asking for the loaded_image interface, just * return handle which points to loaded_image_info */ - ret = efi_add_protocol(&obj->parent, + ret = efi_add_protocol(&obj->header, &efi_guid_loaded_image, info); if (ret != EFI_SUCCESS) goto failure; diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index e861feee4a..c037526ad2 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -14,26 +14,30 @@ const efi_guid_t efi_block_io_guid = BLOCK_IO_GUID; +/** + * struct efi_disk_obj - EFI disk object + * + * @header: EFI object header + * @ops: EFI disk I/O protocol interface + * @ifname: interface name for block device + * @dev_index: device index of block device + * @media: block I/O media information + * @dp: device path to the block device + * @part: partition + * @volume: simple file system protocol of the partition + * @offset: offset into disk for simple partition + * @desc: internal block device descriptor + */ struct efi_disk_obj { - /* Generic EFI object parent class data */ - struct efi_object parent; - /* EFI Interface callback struct for block I/O */ + struct efi_object header; struct efi_block_io ops; - /* U-Boot ifname for block device */ const char *ifname; - /* U-Boot dev_index for block device */ int dev_index; - /* EFI Interface Media descriptor struct, referenced by ops */ struct efi_block_io_media media; - /* EFI device path to this block device */ struct efi_device_path *dp; - /* partition # */ unsigned int part; - /* handle to filesys proto (for partition objects) */ struct efi_simple_file_system_protocol *volume; - /* Offset into disk for simple partitions */ lbaint_t offset; - /* Internal block device */ struct blk_desc *desc; }; @@ -246,7 +250,7 @@ static efi_status_t efi_disk_add_dev( return EFI_OUT_OF_RESOURCES; /* Hook up to the device list */ - efi_add_handle(&diskobj->parent); + efi_add_handle(&diskobj->header); /* Fill in object data */ if (part) { @@ -258,18 +262,18 @@ static efi_status_t efi_disk_add_dev( diskobj->dp = efi_dp_from_part(desc, part); } diskobj->part = part; - ret = efi_add_protocol(&diskobj->parent, &efi_block_io_guid, + ret = efi_add_protocol(&diskobj->header, &efi_block_io_guid, &diskobj->ops); if (ret != EFI_SUCCESS) return ret; - ret = efi_add_protocol(&diskobj->parent, &efi_guid_device_path, + ret = efi_add_protocol(&diskobj->header, &efi_guid_device_path, diskobj->dp); if (ret != EFI_SUCCESS) return ret; if (part >= 1) { diskobj->volume = efi_simple_file_system(desc, part, diskobj->dp); - ret = efi_add_protocol(&diskobj->parent, + ret = efi_add_protocol(&diskobj->header, &efi_simple_file_system_protocol_guid, diskobj->volume); if (ret != EFI_SUCCESS) @@ -381,7 +385,7 @@ efi_status_t efi_disk_register(void) /* Partitions show up as block devices in EFI */ disks += efi_disk_create_partitions( - &disk->parent, desc, if_typename, + &disk->header, desc, if_typename, desc->devnum, dev->name); } #else @@ -427,7 +431,7 @@ efi_status_t efi_disk_register(void) /* Partitions show up as block devices in EFI */ disks += efi_disk_create_partitions - (&disk->parent, desc, + (&disk->header, desc, if_typename, i, devname); } } diff --git a/lib/efi_loader/efi_gop.c b/lib/efi_loader/efi_gop.c index a13c626f6f..fbd5d97de9 100644 --- a/lib/efi_loader/efi_gop.c +++ b/lib/efi_loader/efi_gop.c @@ -16,15 +16,22 @@ DECLARE_GLOBAL_DATA_PTR; static const efi_guid_t efi_gop_guid = EFI_GOP_GUID; +/** + * struct efi_gop_obj - graphical output protocol object + * + * @header: EFI object header + * @ops: graphical output protocol interface + * @info: graphical output mode information + * @mode: graphical output mode + * @bpix: bits per pixel + * @fb: frame buffer + */ struct efi_gop_obj { - /* Generic EFI object parent class data */ - struct efi_object parent; - /* EFI Interface callback struct for gop */ + struct efi_object header; struct efi_gop ops; - /* The only mode we support */ struct efi_gop_mode_info info; struct efi_gop_mode mode; - /* Fields we only have acces to during init */ + /* Fields we only have access to during init */ u32 bpix; void *fb; }; @@ -439,10 +446,10 @@ efi_status_t efi_gop_register(void) } /* Hook up to the device list */ - efi_add_handle(&gopobj->parent); + efi_add_handle(&gopobj->header); /* Fill in object data */ - ret = efi_add_protocol(&gopobj->parent, &efi_gop_guid, + ret = efi_add_protocol(&gopobj->header, &efi_gop_guid, &gopobj->ops); if (ret != EFI_SUCCESS) { printf("ERROR: Failure adding gop protocol\n"); diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c index ecc05f258c..c4f35cd50d 100644 --- a/lib/efi_loader/efi_net.c +++ b/lib/efi_loader/efi_net.c @@ -24,13 +24,19 @@ static struct efi_event *network_timer_event; */ static struct efi_event *wait_for_packet; +/** + * struct efi_net_obj - EFI object representing a network interface + * + * @header: EFI object header + * @net: simple network protocol interface + * @net_mode: status of the network interface + * @pxe: PXE base code protocol interface + * @pxe_mode: status of the PXE base code protocol + */ struct efi_net_obj { - /* Generic EFI object parent class data */ - struct efi_object parent; - /* EFI Interface callback struct for network */ + struct efi_object header; struct efi_simple_network net; struct efi_simple_network_mode net_mode; - /* PXE struct to transmit dhcp data */ struct efi_pxe pxe; struct efi_pxe_mode pxe_mode; }; @@ -325,18 +331,18 @@ efi_status_t efi_net_register(void) } /* Hook net up to the device list */ - efi_add_handle(&netobj->parent); + efi_add_handle(&netobj->header); /* Fill in object data */ - r = efi_add_protocol(&netobj->parent, &efi_net_guid, + r = efi_add_protocol(&netobj->header, &efi_net_guid, &netobj->net); if (r != EFI_SUCCESS) goto failure_to_add_protocol; - r = efi_add_protocol(&netobj->parent, &efi_guid_device_path, + r = efi_add_protocol(&netobj->header, &efi_guid_device_path, efi_dp_from_eth()); if (r != EFI_SUCCESS) goto failure_to_add_protocol; - r = efi_add_protocol(&netobj->parent, &efi_pxe_guid, + r = efi_add_protocol(&netobj->header, &efi_pxe_guid, &netobj->pxe); if (r != EFI_SUCCESS) goto failure_to_add_protocol; -- cgit v1.2.3 From f1589ffb33a798ddb9391dcbab0ddaea2643c2c8 Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Wed, 17 Oct 2018 16:32:03 +0900 Subject: efi_loader: add efi_dp_from_name() Factor out efi_set_bootdev() and extract efi_dp_from_name(). This function will be used to set a boot device in efishell command. Signed-off-by: AKASHI Takahiro Signed-off-by: Alexander Graf --- cmd/bootefi.c | 42 +++++++---------------------------- include/efi_loader.h | 4 ++++ lib/efi_loader/efi_device_path.c | 47 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 34 deletions(-) (limited to 'cmd') diff --git a/cmd/bootefi.c b/cmd/bootefi.c index a1650d6cd1..78f126f1c6 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -608,45 +608,19 @@ U_BOOT_CMD( void efi_set_bootdev(const char *dev, const char *devnr, const char *path) { - char filename[32] = { 0 }; /* dp->str is u16[32] long */ - char *s; + struct efi_device_path *device, *image; + efi_status_t ret; /* efi_set_bootdev is typically called repeatedly, recover memory */ efi_free_pool(bootefi_device_path); efi_free_pool(bootefi_image_path); - /* If blk_get_device_part_str fails, avoid duplicate free. */ - bootefi_device_path = NULL; - bootefi_image_path = NULL; - - if (strcmp(dev, "Net")) { - struct blk_desc *desc; - disk_partition_t fs_partition; - int part; - - part = blk_get_device_part_str(dev, devnr, &desc, &fs_partition, - 1); - if (part < 0) - return; - - bootefi_device_path = efi_dp_from_part(desc, part); - } else { -#ifdef CONFIG_NET - bootefi_device_path = efi_dp_from_eth(); -#endif - } - - if (!path) - return; - if (strcmp(dev, "Net")) { - /* Add leading / to fs paths, because they're absolute */ - snprintf(filename, sizeof(filename), "/%s", path); + ret = efi_dp_from_name(dev, devnr, path, &device, &image); + if (ret == EFI_SUCCESS) { + bootefi_device_path = device; + bootefi_image_path = image; } else { - snprintf(filename, sizeof(filename), "%s", path); + bootefi_device_path = NULL; + bootefi_image_path = NULL; } - /* DOS style file path: */ - s = filename; - while ((s = strchr(s, '/'))) - *s++ = '\\'; - bootefi_image_path = efi_dp_from_file(NULL, 0, filename); } diff --git a/include/efi_loader.h b/include/efi_loader.h index 7a8aa2913a..f399e99506 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -432,6 +432,10 @@ const struct efi_device_path *efi_dp_last_node( efi_status_t efi_dp_split_file_path(struct efi_device_path *full_path, struct efi_device_path **device_path, struct efi_device_path **file_path); +efi_status_t efi_dp_from_name(const char *dev, const char *devnr, + const char *path, + struct efi_device_path **device, + struct efi_device_path **file); #define EFI_DP_TYPE(_dp, _type, _subtype) \ (((_dp)->type == DEVICE_PATH_TYPE_##_type) && \ diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index 2b5d067104..adb9938d45 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -941,3 +941,50 @@ efi_status_t efi_dp_split_file_path(struct efi_device_path *full_path, *file_path = fp; return EFI_SUCCESS; } + +efi_status_t efi_dp_from_name(const char *dev, const char *devnr, + const char *path, + struct efi_device_path **device, + struct efi_device_path **file) +{ + int is_net; + struct blk_desc *desc = NULL; + disk_partition_t fs_partition; + int part = 0; + char filename[32] = { 0 }; /* dp->str is u16[32] long */ + char *s; + + if (!device || (path && !file)) + return EFI_INVALID_PARAMETER; + + is_net = !strcmp(dev, "Net"); + if (!is_net) { + part = blk_get_device_part_str(dev, devnr, &desc, &fs_partition, + 1); + if (part < 0) + return EFI_INVALID_PARAMETER; + + *device = efi_dp_from_part(desc, part); + } else { +#ifdef CONFIG_NET + *device = efi_dp_from_eth(); +#endif + } + + if (!path) + return EFI_SUCCESS; + + if (!is_net) { + /* Add leading / to fs paths, because they're absolute */ + snprintf(filename, sizeof(filename), "/%s", path); + } else { + snprintf(filename, sizeof(filename), "%s", path); + } + /* DOS style file path: */ + s = filename; + while ((s = strchr(s, '/'))) + *s++ = '\\'; + *file = efi_dp_from_file(NULL, 0, filename); + + return EFI_SUCCESS; +} -- cgit v1.2.3 From e1fec152fe53ca8ee922fd0ed4d2c197d4f641bf Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 18 Oct 2018 21:51:38 +0200 Subject: efi_loader: fix typos Fix typos in EFI subsystem comments. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- cmd/bootefi.c | 2 +- lib/efi_loader/efi_bootmgr.c | 2 +- lib/efi_loader/efi_console.c | 4 ++-- lib/efi_loader/efi_device_path_to_text.c | 8 ++++---- lib/efi_loader/efi_gop.c | 11 +++++++---- lib/efi_loader/efi_net.c | 8 ++++---- 6 files changed, 19 insertions(+), 16 deletions(-) (limited to 'cmd') diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 78f126f1c6..3605c3ff96 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -354,7 +354,7 @@ static efi_status_t do_bootefi_exec(void *efi, /* * Special case for efi payload not loaded from disk, such as * 'bootefi hello' or for example payload loaded directly into - * memory via jtag, etc: + * memory via JTAG, etc: */ if (!device_path && !image_path) { printf("WARNING: using memory device/image path, this may confuse some payloads!\n"); diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index 0c5764db12..2aae12e154 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * EFI utils + * EFI boot manager * * Copyright (c) 2017 Rob Clark */ diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index 7274d75204..66c33a551d 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -205,7 +205,7 @@ static int query_console_serial(int *rows, int *cols) /* * Not all terminals understand CSI [18t for querying the console size. * We should adhere to escape sequences documented in the console_codes - * manpage and the ECMA-48 standard. + * man page and the ECMA-48 standard. * * So here we follow a different approach. We position the cursor to the * bottom right and query its position. Before leaving the function we @@ -480,7 +480,7 @@ void set_shift_mask(int mod, struct efi_key_state *key_state) * * This gets called when we have already parsed CSI. * - * @modifiers: bitmask (shift, alt, ctrl) + * @modifiers: bit mask (shift, alt, ctrl) * @return: the unmodified code */ static int analyze_modifiers(struct efi_key_state *key_state) diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c index 0082236359..e219f84b28 100644 --- a/lib/efi_loader/efi_device_path_to_text.c +++ b/lib/efi_loader/efi_device_path_to_text.c @@ -269,9 +269,9 @@ static char *efi_convert_single_device_node_to_text( * for details. * * device_node device node to be converted - * display_only true if the shorter text represenation shall be used + * display_only true if the shorter text representation shall be used * allow_shortcuts true if shortcut forms may be used - * @return text represenation of the device path + * @return text representation of the device path * NULL if out of memory of device_path is NULL */ static uint16_t EFIAPI *efi_convert_device_node_to_text( @@ -302,9 +302,9 @@ out: * for details. * * device_path device path to be converted - * display_only true if the shorter text represenation shall be used + * display_only true if the shorter text representation shall be used * allow_shortcuts true if shortcut forms may be used - * @return text represenation of the device path + * @return text representation of the device path * NULL if out of memory of device_path is NULL */ static uint16_t EFIAPI *efi_convert_device_path_to_text( diff --git a/lib/efi_loader/efi_gop.c b/lib/efi_loader/efi_gop.c index fbd5d97de9..d62ce45912 100644 --- a/lib/efi_loader/efi_gop.c +++ b/lib/efi_loader/efi_gop.c @@ -243,12 +243,12 @@ static efi_uintn_t gop_get_bpp(struct efi_gop *this) } /* - * Gcc can't optimize our BLT function well, but we need to make sure that + * GCC can't optimize our BLT function well, but we need to make sure that * our 2-dimensional loop gets executed very quickly, otherwise the system * will feel slow. * * By manually putting all obvious branch targets into functions which call - * our generic blt function with constants, the compiler can successfully + * our generic BLT function with constants, the compiler can successfully * optimize for speed. */ static efi_status_t gop_blt_video_fill(struct efi_gop *this, @@ -452,7 +452,7 @@ efi_status_t efi_gop_register(void) ret = efi_add_protocol(&gopobj->header, &efi_gop_guid, &gopobj->ops); if (ret != EFI_SUCCESS) { - printf("ERROR: Failure adding gop protocol\n"); + printf("ERROR: Failure adding GOP protocol\n"); return ret; } gopobj->ops.query_mode = gop_query_mode; @@ -470,7 +470,10 @@ efi_status_t efi_gop_register(void) if (bpix == LCD_COLOR32) #endif { - /* With 32bit color space we can directly expose the fb */ + /* + * With 32bit color space we can directly expose the frame + * buffer + */ gopobj->mode.fb_base = fb_base; gopobj->mode.fb_size = fb_size; } diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c index c4f35cd50d..a64c603ed3 100644 --- a/lib/efi_loader/efi_net.c +++ b/lib/efi_loader/efi_net.c @@ -269,7 +269,7 @@ static efi_status_t EFIAPI efi_net_receive(struct efi_simple_network *this, if (protocol) *protocol = protlen; if (*buffer_size < net_rx_packet_len) { - /* Packet doesn't fit, try again with bigger buf */ + /* Packet doesn't fit, try again with bigger buffer */ *buffer_size = net_rx_packet_len; return EFI_EXIT(EFI_BUFFER_TOO_SMALL); } @@ -319,11 +319,11 @@ efi_status_t efi_net_register(void) efi_status_t r; if (!eth_get_dev()) { - /* No eth device active, don't expose any */ + /* No network device active, don't expose any */ return EFI_SUCCESS; } - /* We only expose the "active" eth device, so one is enough */ + /* We only expose the "active" network device, so one is enough */ netobj = calloc(1, sizeof(*netobj)); if (!netobj) { printf("ERROR: Out of memory\n"); @@ -397,7 +397,7 @@ efi_status_t efi_net_register(void) printf("ERROR: Failed to register network event\n"); return r; } - /* Network is time critical, create event in every timer cyle */ + /* Network is time critical, create event in every timer cycle */ r = efi_set_timer(network_timer_event, EFI_TIMER_PERIODIC, 0); if (r != EFI_SUCCESS) { printf("ERROR: Failed to set network timer\n"); -- cgit v1.2.3 From 4574d1b3d1b1aca761ad48cf67db44f3b97c4d1b Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Mon, 12 Nov 2018 18:55:22 +0100 Subject: efi_loader: memory reservation for fdt In copy_fdt() we allocate EFI pages for the fdt plus extra 12 KiB as EFI_RUNTIME_SERVICES_DATA. Afterwards in efi_install_fdt() we overwrite part of this memory allocation by marking it as EFI_BOOT_SERVICES_DATA. Remove the code marking the fdt as EFI_BOOT_SERVICES_DATA. Cf. commit 17ff6f02f5ad ("efi_loader: store DT in EFI_RUNTIME_SERVICES_DATA memory") Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- cmd/bootefi.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) (limited to 'cmd') diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 3605c3ff96..8c4049b7db 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -152,12 +152,11 @@ static void set_load_options(struct efi_loaded_image *loaded_image_info, * An additional 12KB is added to the space in case the device tree needs to be * expanded later with fdt_open_into(). * - * @fdt_addr: On entry, address of start of FDT. On exit, address of relocated - * FDT start - * @fdt_sizep: Returns new size of FDT, including - * @return new relocated address of FDT + * @fdt_addr: On entry, address of start of FDT. On exit, address of relocated + * FDT start + * Return: status code */ -static efi_status_t copy_fdt(ulong *fdt_addrp, ulong *fdt_sizep) +static efi_status_t copy_fdt(ulong *fdt_addrp) { unsigned long fdt_ram_start = -1L, fdt_pages; efi_status_t ret = 0; @@ -209,7 +208,6 @@ static efi_status_t copy_fdt(ulong *fdt_addrp, ulong *fdt_sizep) fdt_set_totalsize(new_fdt, fdt_size); *fdt_addrp = new_fdt_addr; - *fdt_sizep = fdt_size; done: return ret; } @@ -287,7 +285,6 @@ static void efi_carve_out_dt_rsv(void *fdt) static efi_status_t efi_install_fdt(ulong fdt_addr) { bootm_headers_t img = { 0 }; - ulong fdt_pages, fdt_size, fdt_start; efi_status_t ret; void *fdt; @@ -298,13 +295,12 @@ static efi_status_t efi_install_fdt(ulong fdt_addr) } /* Prepare fdt for payload */ - ret = copy_fdt(&fdt_addr, &fdt_size); + ret = copy_fdt(&fdt_addr); if (ret) return ret; unmap_sysmem(fdt); fdt = map_sysmem(fdt_addr, 0); - fdt_size = fdt_totalsize(fdt); if (image_setup_libfdt(&img, fdt, 0, NULL)) { printf("ERROR: failed to process device tree\n"); return EFI_LOAD_ERROR; @@ -317,13 +313,6 @@ static efi_status_t efi_install_fdt(ulong fdt_addr) if (ret != EFI_SUCCESS) return EFI_OUT_OF_RESOURCES; - /* And reserve the space in the memory map */ - fdt_start = fdt_addr; - fdt_pages = fdt_size >> EFI_PAGE_SHIFT; - - ret = efi_add_memory_map(fdt_start, fdt_pages, - EFI_BOOT_SERVICES_DATA, true); - return ret; } -- cgit v1.2.3 From 23fd84b3eccb1af51699d49368e257a5b0a78593 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Mon, 12 Nov 2018 18:55:23 +0100 Subject: efi_loader: carving out memory reservations The "Devicetree Specification 0.2" does not prescribe that memory reservations must be EFI page aligned. So let's not make such an assumption in our code. Do not carve out the pages for the device tree. This memory area is already marked as EFI_RUNTIME_SERVICES_DATA. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- cmd/bootefi.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'cmd') diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 8c4049b7db..3e37805ea1 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -275,7 +275,16 @@ static void efi_carve_out_dt_rsv(void *fdt) if (fdt_get_mem_rsv(fdt, i, &addr, &size) != 0) continue; - pages = ALIGN(size, EFI_PAGE_SIZE) >> EFI_PAGE_SHIFT; + /* + * Do not carve out the device tree. It is already marked as + * EFI_RUNTIME_SERVICES_DATA + */ + if (addr == (uintptr_t)fdt) + continue; + + pages = ALIGN(size + (addr & EFI_PAGE_MASK), EFI_PAGE_SIZE) >> + EFI_PAGE_SHIFT; + addr &= ~EFI_PAGE_MASK; if (!efi_add_memory_map(addr, pages, EFI_RESERVED_MEMORY_TYPE, false)) printf("FDT memrsv map %d: Failed to add to map\n", i); -- cgit v1.2.3 From 2ab7ef74cd90a6d60df6aad7dac24b6a2bb1fe85 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 25 Nov 2018 20:14:36 -0700 Subject: efi: Check for failure to create objects in selftest At present a few error conditions are not checked. Before refactoring this code, add some basic checks. Note that this code still leaks memory in the event of error. This will be tackled after the refactor. Signed-off-by: Simon Glass Signed-off-by: Alexander Graf --- cmd/bootefi.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'cmd') diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 3e37805ea1..5be10c9b83 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -532,7 +532,12 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, (uintptr_t)&efi_selftest, (uintptr_t)&efi_selftest); + if (!bootefi_device_path) + return CMD_RET_FAILURE; + bootefi_image_path = efi_dp_from_file(NULL, 0, "\\selftest"); + if (!bootefi_image_path) + return CMD_RET_FAILURE; r = efi_setup_loaded_image(bootefi_device_path, bootefi_image_path, &image_obj, -- cgit v1.2.3 From d9717eae316d4ffd84146257dd7674c2ff6406f9 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 25 Nov 2018 20:14:37 -0700 Subject: efi: Split out test init/uninit into functions The functions in bootefi are very long because they mix high-level code and control with the low-level implementation. To help with this, create functions which handle preparing for running the test and cleaning up afterwards. Also shorten the awfully long variable names here. Signed-off-by: Simon Glass Signed-off-by: Alexander Graf --- cmd/bootefi.c | 85 ++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 21 deletions(-) (limited to 'cmd') diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 5be10c9b83..666d90e4b7 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -453,6 +453,66 @@ exit: return ret; } +#ifdef CONFIG_CMD_BOOTEFI_SELFTEST +/** + * bootefi_test_prepare() - prepare to run an EFI test + * + * This sets things up so we can call EFI functions. This involves preparing + * the 'gd' pointer and setting up the load ed image data structures. + * + * @image_objp: loaded_image_infop: Pointer to a struct which will hold the + * loaded image object. This struct will be inited by this function before + * use. + * @loaded_image_infop: Pointer to a struct which will hold the loaded image + * info. This struct will be inited by this function before use. + * @path: File path to the test being run (often just the test name with a + * backslash before it + * @test_func: Address of the test function that is being run + * @return 0 if OK, -ve on error + */ +static efi_status_t bootefi_test_prepare + (struct efi_loaded_image_obj **image_objp, + struct efi_loaded_image **loaded_image_infop, + const char *path, + ulong test_func) +{ + efi_status_t r; + + /* Construct a dummy device path */ + bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, + (uintptr_t)test_func, + (uintptr_t)test_func); + if (!bootefi_device_path) + return EFI_OUT_OF_RESOURCES; + bootefi_image_path = efi_dp_from_file(NULL, 0, path); + if (!bootefi_image_path) + return EFI_OUT_OF_RESOURCES; + r = efi_setup_loaded_image(bootefi_device_path, bootefi_image_path, + image_objp, loaded_image_infop); + if (r) + return r; + + /* Transfer environment variable efi_selftest as load options */ + set_load_options(*loaded_image_infop, "efi_selftest"); + + return 0; +} + +/** + * bootefi_test_finish() - finish up after running an EFI test + * + * @image_obj: Pointer to a struct which holds the loaded image object + * @loaded_image_info: Pointer to a struct which holds the loaded image info + */ +static void bootefi_test_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); +} +#endif /* CONFIG_CMD_BOOTEFI_SELFTEST */ + static int do_bootefi_bootmgr_exec(void) { struct efi_device_path *device_path, *file_path; @@ -528,31 +588,14 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) struct efi_loaded_image_obj *image_obj; struct efi_loaded_image *loaded_image_info; - /* Construct a dummy device path. */ - bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, - (uintptr_t)&efi_selftest, - (uintptr_t)&efi_selftest); - if (!bootefi_device_path) - return CMD_RET_FAILURE; - - bootefi_image_path = efi_dp_from_file(NULL, 0, "\\selftest"); - if (!bootefi_image_path) + if (bootefi_test_prepare(&image_obj, &loaded_image_info, + "\\selftest", + (uintptr_t)&efi_selftest)) return CMD_RET_FAILURE; - r = efi_setup_loaded_image(bootefi_device_path, - bootefi_image_path, &image_obj, - &loaded_image_info); - if (r != EFI_SUCCESS) - return CMD_RET_FAILURE; - - efi_save_gd(); - /* Transfer environment variable efi_selftest as load options */ - set_load_options(loaded_image_info, "efi_selftest"); /* Execute the test */ r = efi_selftest(&image_obj->header, &systab); - efi_restore_gd(); - free(loaded_image_info->load_options); - efi_delete_handle(&image_obj->header); + bootefi_test_finish(image_obj, loaded_image_info); return r != EFI_SUCCESS; } else #endif -- cgit v1.2.3 From f4f0f7cb6e0a61f4a3ae0f2aadbe95654df602b5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 25 Nov 2018 20:14:38 -0700 Subject: efi: Create a function to set up for running EFI code There is still duplicated code in efi_loader for tests and normal operation. Add a new bootefi_run_prepare() function which holds common code used to set up U-Boot to run EFI code. Make use of this from the existing bootefi_test_prepare() function, as well as do_bootefi_exec(). Also shorten a few variable names. Signed-off-by: Simon Glass Signed-off-by: Alexander Graf --- cmd/bootefi.c | 52 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 21 deletions(-) (limited to 'cmd') diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 666d90e4b7..ca6693a245 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -325,6 +325,25 @@ static efi_status_t efi_install_fdt(ulong fdt_addr) return ret; } +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; + + 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 */ + set_load_options(*loaded_image_infop, load_options_path); + + return 0; +} + /** * do_bootefi_exec() - execute EFI binary * @@ -374,13 +393,11 @@ static efi_status_t do_bootefi_exec(void *efi, assert(device_path && image_path); } - ret = efi_setup_loaded_image(device_path, image_path, &image_obj, - &loaded_image_info); - if (ret != EFI_SUCCESS) - goto exit; + ret = bootefi_run_prepare("bootargs", device_path, image_path, + &image_obj, &loaded_image_info); + if (ret) + return ret; - /* Transfer environment variable bootargs as load options */ - set_load_options(loaded_image_info, "bootargs"); /* Load the EFI payload */ entry = efi_load_pe(image_obj, efi, loaded_image_info); if (!entry) { @@ -468,16 +485,14 @@ exit: * @path: File path to the test being run (often just the test name with a * backslash before it * @test_func: Address of the test function that is being run + * @load_options_path: U-Boot environment variable to use as load options * @return 0 if OK, -ve on error */ static efi_status_t bootefi_test_prepare (struct efi_loaded_image_obj **image_objp, - struct efi_loaded_image **loaded_image_infop, - const char *path, - ulong test_func) + struct efi_loaded_image **loaded_image_infop, const char *path, + ulong test_func, const char *load_options_path) { - efi_status_t r; - /* Construct a dummy device path */ bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, (uintptr_t)test_func, @@ -487,15 +502,10 @@ static efi_status_t bootefi_test_prepare bootefi_image_path = efi_dp_from_file(NULL, 0, path); if (!bootefi_image_path) return EFI_OUT_OF_RESOURCES; - r = efi_setup_loaded_image(bootefi_device_path, bootefi_image_path, - image_objp, loaded_image_infop); - if (r) - return r; - /* Transfer environment variable efi_selftest as load options */ - set_load_options(*loaded_image_infop, "efi_selftest"); - - return 0; + return bootefi_run_prepare(load_options_path, bootefi_device_path, + bootefi_image_path, image_objp, + loaded_image_infop); } /** @@ -589,8 +599,8 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) struct efi_loaded_image *loaded_image_info; if (bootefi_test_prepare(&image_obj, &loaded_image_info, - "\\selftest", - (uintptr_t)&efi_selftest)) + "\\selftest", (uintptr_t)&efi_selftest, + "efi_selftest")) return CMD_RET_FAILURE; /* Execute the test */ -- cgit v1.2.3 From 5e2f03910731e825b964452356414ab2e99df4d2 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 25 Nov 2018 20:14:39 -0700 Subject: efi: Rename bootefi_test_finish() to bootefi_run_finish() This function can be used from do_bootefi_exec() so that we use mostly the same code for a normal EFI application and an EFI test. Rename the function and use it in both places. Signed-off-by: Simon Glass Signed-off-by: Alexander Graf --- cmd/bootefi.c | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) (limited to 'cmd') diff --git a/cmd/bootefi.c b/cmd/bootefi.c index ca6693a245..eadfd934b7 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -344,6 +344,20 @@ static efi_status_t bootefi_run_prepare(const char *load_options_path, return 0; } +/** + * bootefi_run_finish() - finish up after running an EFI test + * + * @loaded_image_info: Pointer to a struct which holds the loaded image info + * @image_objj: 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); +} + /** * do_bootefi_exec() - execute EFI binary * @@ -384,11 +398,11 @@ static efi_status_t do_bootefi_exec(void *efi, */ ret = efi_create_handle(&mem_handle); if (ret != EFI_SUCCESS) - goto exit; + return ret; /* TODO: leaks device_path */ ret = efi_add_protocol(mem_handle, &efi_guid_device_path, device_path); if (ret != EFI_SUCCESS) - goto exit; + goto err_add_protocol; } else { assert(device_path && image_path); } @@ -396,13 +410,13 @@ static efi_status_t do_bootefi_exec(void *efi, ret = bootefi_run_prepare("bootargs", device_path, image_path, &image_obj, &loaded_image_info); if (ret) - return ret; + goto err_prepare; /* Load the EFI payload */ entry = efi_load_pe(image_obj, efi, loaded_image_info); if (!entry) { ret = EFI_LOAD_ERROR; - goto exit; + goto err_prepare; } if (memdp) { @@ -422,7 +436,7 @@ static efi_status_t do_bootefi_exec(void *efi, if (setjmp(&image_obj->exit_jmp)) { ret = image_obj->exit_status; - goto exit; + goto err_prepare; } #ifdef CONFIG_ARM64 @@ -460,10 +474,11 @@ static efi_status_t do_bootefi_exec(void *efi, ret = efi_do_enter(&image_obj->header, &systab, entry); -exit: +err_prepare: /* image has returned, loaded-image obj goes *poof*: */ - if (image_obj) - efi_delete_handle(&image_obj->header); + bootefi_run_finish(image_obj, loaded_image_info); + +err_add_protocol: if (mem_handle) efi_delete_handle(mem_handle); @@ -508,19 +523,6 @@ static efi_status_t bootefi_test_prepare loaded_image_infop); } -/** - * bootefi_test_finish() - finish up after running an EFI test - * - * @image_obj: Pointer to a struct which holds the loaded image object - * @loaded_image_info: Pointer to a struct which holds the loaded image info - */ -static void bootefi_test_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); -} #endif /* CONFIG_CMD_BOOTEFI_SELFTEST */ static int do_bootefi_bootmgr_exec(void) @@ -605,7 +607,7 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) /* Execute the test */ r = efi_selftest(&image_obj->header, &systab); - bootefi_test_finish(image_obj, loaded_image_info); + bootefi_run_finish(image_obj, loaded_image_info); return r != EFI_SUCCESS; } else #endif -- cgit v1.2.3 From c3772ca1e38f36f2486b44c27094421442414e5e Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 18 Nov 2018 17:58:49 +0100 Subject: efi_loader: macro efi_size_in_pages() When allocating EFI memory pages the size in bytes has to be converted to pages. Provide a macro efi_size_in_pages() for this conversion. Use it in the EFI subsystem and correct related comments. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- cmd/bootefi.c | 15 ++++++--------- include/efi_loader.h | 11 ++++++++++- lib/efi_loader/efi_memory.c | 6 +++--- 3 files changed, 19 insertions(+), 13 deletions(-) (limited to 'cmd') diff --git a/cmd/bootefi.c b/cmd/bootefi.c index eadfd934b7..a57b0b4fe4 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -149,7 +149,7 @@ static void set_load_options(struct efi_loaded_image *loaded_image_info, * copy_fdt() - Copy the device tree to a new location available to EFI * * The FDT is relocated into a suitable location within the EFI memory map. - * An additional 12KB is added to the space in case the device tree needs to be + * Additional 12 KiB are added to the space in case the device tree needs to be * expanded later with fdt_open_into(). * * @fdt_addr: On entry, address of start of FDT. On exit, address of relocated @@ -177,14 +177,12 @@ static efi_status_t copy_fdt(ulong *fdt_addrp) } /* - * Give us at least 4KB of breathing room in case the device tree needs - * to be expanded later. Round up to the nearest EFI page boundary. + * Give us at least 12 KiB of breathing room in case the device tree + * needs to be expanded later. */ fdt = map_sysmem(*fdt_addrp, 0); - fdt_size = fdt_totalsize(fdt); - fdt_size += 4096 * 3; - fdt_size = ALIGN(fdt_size + EFI_PAGE_SIZE - 1, EFI_PAGE_SIZE); - fdt_pages = fdt_size >> EFI_PAGE_SHIFT; + fdt_pages = efi_size_in_pages(fdt_totalsize(fdt) + 0x3000); + fdt_size = fdt_pages << EFI_PAGE_SHIFT; /* Safe fdt location is at 127MB */ new_fdt_addr = fdt_ram_start + (127 * 1024 * 1024) + fdt_size; @@ -282,8 +280,7 @@ static void efi_carve_out_dt_rsv(void *fdt) if (addr == (uintptr_t)fdt) continue; - pages = ALIGN(size + (addr & EFI_PAGE_MASK), EFI_PAGE_SIZE) >> - EFI_PAGE_SHIFT; + 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)) diff --git a/include/efi_loader.h b/include/efi_loader.h index f399e99506..3c90515fef 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -344,7 +344,16 @@ struct efi_simple_file_system_protocol *efi_simple_file_system( /* open file from device-path: */ struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp); - +/** + * efi_size_in_pages() - convert size in bytes to size in pages + * + * This macro returns the number of EFI memory pages required to hold 'size' + * bytes. + * + * @size: size in bytes + * Return: size in pages + */ +#define efi_size_in_pages(size) ((size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT) /* Generic EFI memory allocator, call this to get memory */ void *efi_alloc(uint64_t len, int memory_type); /* More specific EFI memory allocator, called by EFI payloads */ diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index 307e6f77ab..5359118b4d 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -397,7 +397,7 @@ efi_status_t efi_allocate_pages(int type, int memory_type, void *efi_alloc(uint64_t len, int memory_type) { uint64_t ret = 0; - uint64_t pages = (len + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT; + uint64_t pages = efi_size_in_pages(len); efi_status_t r; r = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES, memory_type, pages, @@ -440,8 +440,8 @@ efi_status_t efi_allocate_pool(int pool_type, efi_uintn_t size, void **buffer) { efi_status_t r; struct efi_pool_allocation *alloc; - u64 num_pages = (size + sizeof(struct efi_pool_allocation) + - EFI_PAGE_MASK) >> EFI_PAGE_SHIFT; + u64 num_pages = efi_size_in_pages(size + + sizeof(struct efi_pool_allocation)); if (!buffer) return EFI_INVALID_PARAMETER; -- cgit v1.2.3 From 16b615d9abd006fb69930860f23e7785a48d040a Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 18 Nov 2018 17:58:52 +0100 Subject: efi_loader: fix memory mapping for sandbox The sandbox is using a virtual address space which is neither the physical address space of the operating system nor the virtual address space in which Linux aplications live. The addresses used insided the flattened device tree use this sandbox virtual address space. The EFI subsystem uses the virtual address space of the operating system and this is where the fdt is stored. Fix all incorrect addresses for the fdt in cmd/bootefi.cmd. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- cmd/bootefi.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) (limited to 'cmd') diff --git a/cmd/bootefi.c b/cmd/bootefi.c index a57b0b4fe4..ad97a9c019 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -148,15 +148,16 @@ static void set_load_options(struct efi_loaded_image *loaded_image_info, /** * copy_fdt() - Copy the device tree to a new location available to EFI * - * The FDT is relocated into a suitable location within the EFI memory map. + * The FDT is copied to a suitable location within the EFI memory map. * Additional 12 KiB are added to the space in case the device tree needs to be * expanded later with fdt_open_into(). * - * @fdt_addr: On entry, address of start of FDT. On exit, address of relocated + * @fdtp: On entry a pointer to the flattened device tree. + * On exit a pointer to the copy of the flattened device tree. * FDT start * Return: status code */ -static efi_status_t copy_fdt(ulong *fdt_addrp) +static efi_status_t copy_fdt(void **fdtp) { unsigned long fdt_ram_start = -1L, fdt_pages; efi_status_t ret = 0; @@ -180,12 +181,16 @@ static efi_status_t copy_fdt(ulong *fdt_addrp) * Give us at least 12 KiB of breathing room in case the device tree * needs to be expanded later. */ - fdt = map_sysmem(*fdt_addrp, 0); + fdt = *fdtp; fdt_pages = efi_size_in_pages(fdt_totalsize(fdt) + 0x3000); fdt_size = fdt_pages << EFI_PAGE_SHIFT; - /* Safe fdt location is at 127MB */ - new_fdt_addr = fdt_ram_start + (127 * 1024 * 1024) + fdt_size; + /* + * 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); ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS, EFI_RUNTIME_SERVICES_DATA, fdt_pages, &new_fdt_addr); @@ -200,12 +205,11 @@ static efi_status_t copy_fdt(ulong *fdt_addrp) goto done; } } - - new_fdt = map_sysmem(new_fdt_addr, fdt_size); + new_fdt = (void *)(uintptr_t)new_fdt_addr; memcpy(new_fdt, fdt, fdt_totalsize(fdt)); fdt_set_totalsize(new_fdt, fdt_size); - *fdt_addrp = new_fdt_addr; + *fdtp = (void *)(uintptr_t)new_fdt_addr; done: return ret; } @@ -273,6 +277,9 @@ static void efi_carve_out_dt_rsv(void *fdt) if (fdt_get_mem_rsv(fdt, i, &addr, &size) != 0) continue; + /* Convert from sandbox address space. */ + addr = (uintptr_t)map_sysmem(addr, 0); + /* * Do not carve out the device tree. It is already marked as * EFI_RUNTIME_SERVICES_DATA @@ -301,12 +308,10 @@ static efi_status_t efi_install_fdt(ulong fdt_addr) } /* Prepare fdt for payload */ - ret = copy_fdt(&fdt_addr); + ret = copy_fdt(&fdt); if (ret) return ret; - unmap_sysmem(fdt); - fdt = map_sysmem(fdt_addr, 0); if (image_setup_libfdt(&img, fdt, 0, NULL)) { printf("ERROR: failed to process device tree\n"); return EFI_LOAD_ERROR; -- cgit v1.2.3 From 0c9ac06a2894ea08488b5f8f5d1e5cbd57808900 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 18 Nov 2018 17:58:53 +0100 Subject: efi_loader: create fdt reservation before copy When copying the device we must ensure that the copy does not fall into a memory area reserved by the same. So let's change the sequence: first create memory reservations and then copy the device tree. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- cmd/bootefi.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'cmd') diff --git a/cmd/bootefi.c b/cmd/bootefi.c index ad97a9c019..38679ffc56 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -280,13 +280,6 @@ static void efi_carve_out_dt_rsv(void *fdt) /* Convert from sandbox address space. */ addr = (uintptr_t)map_sysmem(addr, 0); - /* - * Do not carve out the device tree. It is already marked as - * EFI_RUNTIME_SERVICES_DATA - */ - if (addr == (uintptr_t)fdt) - continue; - 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, @@ -307,6 +300,9 @@ static efi_status_t efi_install_fdt(ulong fdt_addr) return EFI_INVALID_PARAMETER; } + /* Create memory reservation as indicated by the device tree */ + efi_carve_out_dt_rsv(fdt); + /* Prepare fdt for payload */ ret = copy_fdt(&fdt); if (ret) @@ -317,8 +313,6 @@ static efi_status_t efi_install_fdt(ulong fdt_addr) return EFI_LOAD_ERROR; } - efi_carve_out_dt_rsv(fdt); - /* Link to it in the efi tables */ ret = efi_install_configuration_table(&efi_guid_fdt, fdt); if (ret != EFI_SUCCESS) -- cgit v1.2.3