diff options
author | Tom Rini | 2022-03-28 12:36:49 -0400 |
---|---|---|
committer | Tom Rini | 2022-03-28 12:36:49 -0400 |
commit | 34d2b7f20369d62c0f091d6572a8c0ea4655cf14 (patch) | |
tree | 0591ee99c118e0e196730b6ec6582986200e6313 /lib | |
parent | 7f0826c169ff14d62e92d02f85d33d0030d45c12 (diff) | |
parent | e893e8ea6a5d3af312747d00f93587559193a426 (diff) |
Merge tag 'v2022.04-rc5' into next
Prepare v2022.04-rc5
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) | 93 | ||||
-rw-r--r-- | lib/efi_selftest/Makefile | 12 |
9 files changed, 215 insertions, 137 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..0542aaae16c 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 device-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..98721069816 100644 --- a/lib/efi_selftest/initrddump.c +++ b/lib/efi_loader/initrddump.c @@ -4,6 +4,9 @@ * * initrddump.efi saves the initial RAM disk provided via the * EFI_LOAD_FILE2_PROTOCOL. + * + * Specifying 'nocolor' as load option data suppresses colored output and + * clearing of the screen. */ #include <common.h> @@ -25,6 +28,7 @@ static const efi_guid_t guid_simple_file_system_protocol = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; static const efi_guid_t load_file2_guid = EFI_LOAD_FILE2_PROTOCOL_GUID; static efi_handle_t handle; +static bool nocolor; /* * Device path defined by Linux to identify the handle providing the @@ -47,6 +51,17 @@ static const struct efi_initrd_dp initrd_dp = { }; /** + * color() - set foreground color + * + * @color: foreground color + */ +static void color(u8 color) +{ + if (!nocolor) + cout->set_attribute(cout, color | EFI_BACKGROUND_BLACK); +} + +/** * print() - print string * * @string: text @@ -57,15 +72,26 @@ static void print(u16 *string) } /** + * cls() - clear screen + */ +static void cls(void) +{ + if (nocolor) + print(u"\r\n"); + else + cout->clear_screen(cout); +} + +/** * error() - print error string * * @string: error text */ static void error(u16 *string) { - cout->set_attribute(cout, EFI_LIGHTRED | EFI_BACKGROUND_BLACK); + color(EFI_LIGHTRED); print(string); - cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK); + color(EFI_LIGHTBLUE); } /* @@ -95,6 +121,14 @@ static void printx(u64 val, u32 prec) } /** + * efi_drain_input() - drain console input + */ +static void efi_drain_input(void) +{ + cin->reset(cin, true); +} + +/** * efi_input_yn() - get answer to yes/no question * * Return: @@ -111,8 +145,6 @@ static efi_status_t efi_input_yn(void) efi_uintn_t index; efi_status_t ret; - /* Drain the console input */ - ret = cin->reset(cin, true); for (;;) { ret = bs->wait_for_event(1, &cin->wait_for_key, &index); if (ret != EFI_SUCCESS) @@ -153,8 +185,6 @@ static efi_status_t efi_input(u16 *buffer, efi_uintn_t buffer_size) u16 outbuf[2] = u" "; efi_status_t ret; - /* Drain the console input */ - ret = cin->reset(cin, true); *buffer = 0; for (;;) { ret = bs->wait_for_event(1, &cin->wait_for_key, &index); @@ -215,10 +245,13 @@ static u16 *skip_whitespace(u16 *pos) * * @string: string to search for keyword * @keyword: keyword to be searched - * Return: true fi @string starts with the keyword + * Return: true if @string starts with the keyword */ static bool starts_with(u16 *string, u16 *keyword) { + if (!string || !keyword) + return false; + for (; *keyword; ++string, ++keyword) { if (*string != *keyword) return false; @@ -364,6 +397,7 @@ static efi_status_t do_save(u16 *filename) ret = root->open(root, &file, filename, EFI_FILE_MODE_READ, 0); if (ret == EFI_SUCCESS) { file->close(file); + efi_drain_input(); print(u"Overwrite existing file (y/n)? "); ret = efi_input_yn(); print(u"\r\n"); @@ -401,6 +435,30 @@ out: } /** + * get_load_options() - get load options + * + * Return: load options or NULL + */ +u16 *get_load_options(void) +{ + efi_status_t ret; + struct efi_loaded_image *loaded_image; + + ret = bs->open_protocol(handle, &loaded_image_guid, + (void **)&loaded_image, NULL, NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (ret != EFI_SUCCESS) { + error(u"Loaded image protocol not found\r\n"); + return NULL; + } + + if (!loaded_image->load_options_size || !loaded_image->load_options) + return NULL; + + return loaded_image->load_options; +} + +/** * efi_main() - entry point of the EFI application. * * @handle: handle of the loaded image @@ -410,24 +468,30 @@ out: efi_status_t EFIAPI efi_main(efi_handle_t image_handle, struct efi_system_table *systab) { + u16 *load_options; + handle = image_handle; systable = systab; cerr = systable->std_err; cout = systable->con_out; cin = systable->con_in; bs = systable->boottime; + load_options = get_load_options(); - 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"); - cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK); + if (starts_with(load_options, u"nocolor")) + nocolor = true; + + color(EFI_WHITE); + cls(); + print(u"INITRD Dump\r\n===========\r\n\r\n"); + color(EFI_LIGHTBLUE); for (;;) { u16 command[BUFFER_SIZE]; u16 *pos; efi_uintn_t ret; + efi_drain_input(); print(u"=> "); ret = efi_input(command, sizeof(command)); if (ret == EFI_ABORTED) @@ -443,7 +507,8 @@ efi_status_t EFIAPI efi_main(efi_handle_t image_handle, do_help(); } - cout->set_attribute(cout, EFI_LIGHTGRAY | EFI_BACKGROUND_BLACK); - cout->clear_screen(cout); + color(EFI_LIGHTGRAY); + cls(); + return EFI_SUCCESS; } 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 |