diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/efi_loader/Makefile | 12 | ||||
-rw-r--r-- | lib/efi_loader/dtbdump.c (renamed from lib/efi_selftest/dtbdump.c) | 0 | ||||
-rw-r--r-- | lib/efi_loader/efi_boottime.c | 22 | ||||
-rw-r--r-- | lib/efi_loader/efi_capsule.c | 13 | ||||
-rw-r--r-- | lib/efi_loader/efi_device_path.c | 138 | ||||
-rw-r--r-- | lib/efi_loader/efi_disk.c | 31 | ||||
-rw-r--r-- | lib/efi_loader/efi_variable_tee.c | 31 | ||||
-rw-r--r-- | lib/efi_loader/initrddump.c (renamed from lib/efi_selftest/initrddump.c) | 2 | ||||
-rw-r--r-- | lib/efi_selftest/Makefile | 12 |
9 files changed, 137 insertions, 124 deletions
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index b2c664d108b..befed7144e7 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -14,12 +14,24 @@ CFLAGS_efi_boottime.o += \ -DFW_PATCHLEVEL="0x$(PATCHLEVEL)" CFLAGS_helloworld.o := $(CFLAGS_EFI) -Os -ffreestanding CFLAGS_REMOVE_helloworld.o := $(CFLAGS_NON_EFI) +CFLAGS_dtbdump.o := $(CFLAGS_EFI) -Os -ffreestanding +CFLAGS_REMOVE_dtbdump.o := $(CFLAGS_NON_EFI) +CFLAGS_initrddump_exit.o := $(CFLAGS_EFI) -Os -ffreestanding +CFLAGS_REMOVE_initrddump.o := $(CFLAGS_NON_EFI) ifneq ($(CONFIG_CMD_BOOTEFI_HELLO_COMPILE),) always += helloworld.efi targets += helloworld.o endif +ifeq ($(CONFIG_GENERATE_ACPI_TABLE),) +always += dtbdump.efi +endif + +ifdef CONFIG_EFI_LOAD_FILE2_INITRD +always += initrddump.efi +endif + obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o obj-$(CONFIG_CMD_BOOTEFI_BOOTMGR) += efi_bootmgr.o obj-y += efi_boottime.o diff --git a/lib/efi_selftest/dtbdump.c b/lib/efi_loader/dtbdump.c index 3ce2a07f9eb..3ce2a07f9eb 100644 --- a/lib/efi_selftest/dtbdump.c +++ b/lib/efi_loader/dtbdump.c diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index d0f3e05e708..5bcb8253edb 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1750,7 +1750,7 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, info->system_table = &systab; if (device_path) { - info->device_handle = efi_dp_find_obj(device_path, NULL); + info->device_handle = efi_dp_find_obj(device_path, NULL, NULL); dp = efi_dp_append(device_path, file_path); if (!dp) { @@ -1940,7 +1940,7 @@ efi_status_t efi_load_image_from_path(bool boot_policy, { efi_handle_t device; efi_status_t ret; - struct efi_device_path *dp; + struct efi_device_path *dp, *rem; struct efi_load_file_protocol *load_file_protocol = NULL; efi_uintn_t buffer_size; uint64_t addr, pages; @@ -1951,18 +1951,18 @@ efi_status_t efi_load_image_from_path(bool boot_policy, *size = 0; dp = file_path; - ret = EFI_CALL(efi_locate_device_path( - &efi_simple_file_system_protocol_guid, &dp, &device)); + device = efi_dp_find_obj(dp, NULL, &rem); + ret = efi_search_protocol(device, &efi_simple_file_system_protocol_guid, + NULL); if (ret == EFI_SUCCESS) return efi_load_image_from_file(file_path, buffer, size); - ret = EFI_CALL(efi_locate_device_path( - &efi_guid_load_file_protocol, &dp, &device)); + ret = efi_search_protocol(device, &efi_guid_load_file_protocol, NULL); if (ret == EFI_SUCCESS) { guid = &efi_guid_load_file_protocol; } else if (!boot_policy) { guid = &efi_guid_load_file2_protocol; - ret = EFI_CALL(efi_locate_device_path(guid, &dp, &device)); + ret = efi_search_protocol(device, guid, NULL); } if (ret != EFI_SUCCESS) return EFI_NOT_FOUND; @@ -1971,9 +1971,9 @@ efi_status_t efi_load_image_from_path(bool boot_policy, if (ret != EFI_SUCCESS) return EFI_NOT_FOUND; buffer_size = 0; - ret = load_file_protocol->load_file(load_file_protocol, dp, - boot_policy, &buffer_size, - NULL); + ret = EFI_CALL(load_file_protocol->load_file( + load_file_protocol, rem, boot_policy, + &buffer_size, NULL)); if (ret != EFI_BUFFER_TOO_SMALL) goto out; pages = efi_size_in_pages(buffer_size); @@ -1984,7 +1984,7 @@ efi_status_t efi_load_image_from_path(bool boot_policy, goto out; } ret = EFI_CALL(load_file_protocol->load_file( - load_file_protocol, dp, boot_policy, + load_file_protocol, rem, boot_policy, &buffer_size, (void *)(uintptr_t)addr)); if (ret != EFI_SUCCESS) efi_free_pages(addr, pages); diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index 613b531b825..f00440163d4 100644 --- a/lib/efi_loader/efi_capsule.c +++ b/lib/efi_loader/efi_capsule.c @@ -669,22 +669,29 @@ static efi_status_t get_dp_device(u16 *boot_var, /** * device_is_present_and_system_part - check if a device exists - * @dp Device path * * Check if a device pointed to by the device path, @dp, exists and is * located in UEFI system partition. * + * @dp device path * Return: true - yes, false - no */ static bool device_is_present_and_system_part(struct efi_device_path *dp) { efi_handle_t handle; + struct efi_device_path *rem; - handle = efi_dp_find_obj(dp, NULL); + /* Check device exists */ + handle = efi_dp_find_obj(dp, NULL, NULL); if (!handle) return false; - return efi_disk_is_system_part(handle); + /* Check device is on system partition */ + handle = efi_dp_find_obj(dp, &efi_system_partition_guid, &rem); + if (!handle) + return false; + + return true; } /** diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index dc787b4d3dd..0a8802903d7 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -122,20 +122,25 @@ int efi_dp_match(const struct efi_device_path *a, } } -/* +/** + * efi_dp_shorten() - shorten device-path + * * We can have device paths that start with a USB WWID or a USB Class node, * and a few other cases which don't encode the full device path with bus * hierarchy: * - * - MESSAGING:USB_WWID - * - MESSAGING:USB_CLASS - * - MEDIA:FILE_PATH - * - MEDIA:HARD_DRIVE - * - MESSAGING:URI + * * MESSAGING:USB_WWID + * * MESSAGING:USB_CLASS + * * MEDIA:FILE_PATH + * * MEDIA:HARD_DRIVE + * * MESSAGING:URI * * See UEFI spec (section 3.1.2, about short-form device-paths) + * + * @dp: original devie-path + * @Return: shortened device-path or NULL */ -static struct efi_device_path *shorten_path(struct efi_device_path *dp) +struct efi_device_path *efi_dp_shorten(struct efi_device_path *dp) { while (dp) { /* @@ -154,69 +159,90 @@ static struct efi_device_path *shorten_path(struct efi_device_path *dp) return dp; } -static struct efi_object *find_obj(struct efi_device_path *dp, bool short_path, - struct efi_device_path **rem) +/** + * find_handle() - find handle by device path and installed protocol + * + * If @rem is provided, the handle with the longest partial match is returned. + * + * @dp: device path to search + * @guid: GUID of protocol that must be installed on path or NULL + * @short_path: use short form device path for matching + * @rem: pointer to receive remaining device path + * Return: matching handle + */ +static efi_handle_t find_handle(struct efi_device_path *dp, + const efi_guid_t *guid, bool short_path, + struct efi_device_path **rem) { - struct efi_object *efiobj; - efi_uintn_t dp_size = efi_dp_instance_size(dp); + efi_handle_t handle, best_handle = NULL; + efi_uintn_t len, best_len = 0; + + len = efi_dp_instance_size(dp); - list_for_each_entry(efiobj, &efi_obj_list, link) { + list_for_each_entry(handle, &efi_obj_list, link) { struct efi_handler *handler; - struct efi_device_path *obj_dp; + struct efi_device_path *dp_current; + efi_uintn_t len_current; efi_status_t ret; - ret = efi_search_protocol(efiobj, - &efi_guid_device_path, &handler); + if (guid) { + ret = efi_search_protocol(handle, guid, &handler); + if (ret != EFI_SUCCESS) + continue; + } + ret = efi_search_protocol(handle, &efi_guid_device_path, + &handler); if (ret != EFI_SUCCESS) continue; - obj_dp = handler->protocol_interface; - - do { - if (efi_dp_match(dp, obj_dp) == 0) { - if (rem) { - /* - * Allow partial matches, but inform - * the caller. - */ - *rem = ((void *)dp) + - efi_dp_instance_size(obj_dp); - return efiobj; - } else { - /* Only return on exact matches */ - if (efi_dp_instance_size(obj_dp) == - dp_size) - return efiobj; - } - } - - obj_dp = shorten_path(efi_dp_next(obj_dp)); - } while (short_path && obj_dp); + dp_current = handler->protocol_interface; + if (short_path) { + dp_current = efi_dp_shorten(dp_current); + if (!dp_current) + continue; + } + len_current = efi_dp_instance_size(dp_current); + if (rem) { + if (len_current > len) + continue; + } else { + if (len_current != len) + continue; + } + if (memcmp(dp_current, dp, len_current)) + continue; + if (!rem) + return handle; + if (len_current > best_len) { + best_len = len_current; + best_handle = handle; + *rem = (void*)((u8 *)dp + len_current); + } } - - return NULL; + return best_handle; } -/* - * Find an efiobj from device-path, if 'rem' is not NULL, returns the - * remaining part of the device path after the matched object. +/** + * efi_dp_find_obj() - find handle by device path + * + * If @rem is provided, the handle with the longest partial match is returned. + * + * @dp: device path to search + * @guid: GUID of protocol that must be installed on path or NULL + * @rem: pointer to receive remaining device path + * Return: matching handle */ -struct efi_object *efi_dp_find_obj(struct efi_device_path *dp, - struct efi_device_path **rem) +efi_handle_t efi_dp_find_obj(struct efi_device_path *dp, + const efi_guid_t *guid, + struct efi_device_path **rem) { - struct efi_object *efiobj; - - /* Search for an exact match first */ - efiobj = find_obj(dp, false, NULL); - - /* Then for a fuzzy match */ - if (!efiobj) - efiobj = find_obj(dp, false, rem); + efi_handle_t handle; - /* And now for a fuzzy short match */ - if (!efiobj) - efiobj = find_obj(dp, true, rem); + handle = find_handle(dp, guid, false, rem); + if (!handle) + /* Match short form device path */ + handle = find_handle(dp, guid, true, rem); - return efiobj; + return handle; } /* diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index 45127d17686..c905c12abc2 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -302,7 +302,7 @@ efi_fs_from_path(struct efi_device_path *full_path) efi_free_pool(file_path); /* Get the EFI object for the partition */ - efiobj = efi_dp_find_obj(device_path, NULL); + efiobj = efi_dp_find_obj(device_path, NULL, NULL); efi_free_pool(device_path); if (!efiobj) return NULL; @@ -587,32 +587,3 @@ efi_status_t efi_disk_register(void) return EFI_SUCCESS; } - -/** - * efi_disk_is_system_part() - check if handle refers to an EFI system partition - * - * @handle: handle of partition - * - * Return: true if handle refers to an EFI system partition - */ -bool efi_disk_is_system_part(efi_handle_t handle) -{ - struct efi_handler *handler; - struct efi_disk_obj *diskobj; - struct disk_partition info; - efi_status_t ret; - int r; - - /* check if this is a block device */ - ret = efi_search_protocol(handle, &efi_block_io_guid, &handler); - if (ret != EFI_SUCCESS) - return false; - - diskobj = container_of(handle, struct efi_disk_obj, header); - - r = part_get_info(diskobj->desc, diskobj->part, &info); - if (r) - return false; - - return !!(info.bootable & PART_EFI_SYSTEM_PARTITION); -} diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c index 58931c4efd7..dfef18435df 100644 --- a/lib/efi_loader/efi_variable_tee.c +++ b/lib/efi_loader/efi_variable_tee.c @@ -368,7 +368,7 @@ efi_status_t efi_get_variable_int(const u16 *variable_name, efi_uintn_t name_size; efi_uintn_t tmp_dsize; u8 *comm_buf = NULL; - efi_status_t ret; + efi_status_t ret, tmp; if (!variable_name || !vendor || !data_size) { ret = EFI_INVALID_PARAMETER; @@ -407,23 +407,32 @@ efi_status_t efi_get_variable_int(const u16 *variable_name, /* Communicate */ ret = mm_communicate(comm_buf, payload_size); - if (ret == EFI_SUCCESS || ret == EFI_BUFFER_TOO_SMALL) { - /* Update with reported data size for trimmed case */ - *data_size = var_acc->data_size; - } - if (ret != EFI_SUCCESS) - goto out; - - ret = get_property_int(variable_name, name_size, vendor, &var_property); - if (ret != EFI_SUCCESS) + if (ret != EFI_SUCCESS && ret != EFI_BUFFER_TOO_SMALL) goto out; + /* Update with reported data size for trimmed case */ + *data_size = var_acc->data_size; + /* + * UEFI > 2.7 needs the attributes set even if the buffer is + * smaller + */ if (attributes) { + tmp = get_property_int(variable_name, name_size, vendor, + &var_property); + if (tmp != EFI_SUCCESS) { + ret = tmp; + goto out; + } *attributes = var_acc->attr; - if (var_property.property & VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY) + if (var_property.property & + VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY) *attributes |= EFI_VARIABLE_READ_ONLY; } + /* return if ret is EFI_BUFFER_TOO_SMALL */ + if (ret != EFI_SUCCESS) + goto out; + if (data) memcpy(data, (u8 *)var_acc->name + var_acc->name_size, var_acc->data_size); diff --git a/lib/efi_selftest/initrddump.c b/lib/efi_loader/initrddump.c index 4648d54b136..7de43bcfff4 100644 --- a/lib/efi_selftest/initrddump.c +++ b/lib/efi_loader/initrddump.c @@ -420,7 +420,7 @@ efi_status_t EFIAPI efi_main(efi_handle_t image_handle, cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK); cout->clear_screen(cout); cout->set_attribute(cout, EFI_WHITE | EFI_BACKGROUND_BLACK); - print(u"INITRD Dump\r\n========\r\n\r\n"); + print(u"INITRD Dump\r\n===========\r\n\r\n"); cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK); for (;;) { diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile index 9ff6e1760c6..be8040d1c7e 100644 --- a/lib/efi_selftest/Makefile +++ b/lib/efi_selftest/Makefile @@ -8,16 +8,12 @@ asflags-y += -DHOST_ARCH="$(HOST_ARCH)" ccflags-y += -DHOST_ARCH="$(HOST_ARCH)" -CFLAGS_dtbdump.o := $(CFLAGS_EFI) -Os -ffreestanding -CFLAGS_REMOVE_dtbdump.o := $(CFLAGS_NON_EFI) CFLAGS_efi_selftest_miniapp_exception.o := $(CFLAGS_EFI) -Os -ffreestanding CFLAGS_REMOVE_efi_selftest_miniapp_exception.o := $(CFLAGS_NON_EFI) CFLAGS_efi_selftest_miniapp_exit.o := $(CFLAGS_EFI) -Os -ffreestanding CFLAGS_REMOVE_efi_selftest_miniapp_exit.o := $(CFLAGS_NON_EFI) CFLAGS_efi_selftest_miniapp_return.o := $(CFLAGS_EFI) -Os -ffreestanding CFLAGS_REMOVE_efi_selftest_miniapp_return.o := $(CFLAGS_NON_EFI) -CFLAGS_initrddump_exit.o := $(CFLAGS_EFI) -Os -ffreestanding -CFLAGS_REMOVE_initrddump.o := $(CFLAGS_NON_EFI) obj-y += \ efi_selftest.o \ @@ -83,14 +79,6 @@ efi_selftest_miniapp_exception.efi \ efi_selftest_miniapp_exit.efi \ efi_selftest_miniapp_return.efi -ifeq ($(CONFIG_GENERATE_ACPI_TABLE),) -always += dtbdump.efi -endif - -ifdef CONFIG_EFI_LOAD_FILE2_INITRD -always += initrddump.efi -endif - $(obj)/efi_miniapp_file_image_exception.h: $(obj)/efi_selftest_miniapp_exception.efi $(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_exception.efi > \ $(obj)/efi_miniapp_file_image_exception.h |