diff options
| author | Tom Rini <[email protected]> | 2019-05-13 07:13:28 -0400 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2019-05-13 07:13:28 -0400 |
| commit | 90176e3be63802bc8630bab651d169993f0f0763 (patch) | |
| tree | e60a40154429aeb1bfcdae87649456ee2683bd4a /lib/efi_loader | |
| parent | d2d8f73da4b648ad21b1afb481f0bcd035ebe029 (diff) | |
| parent | e2d82f8b2a91fb3fa78345f935a93a6db575effa (diff) | |
Merge tag 'efi-2019-07-rc3' of git://git.denx.de/u-boot-efi
Pull request for UEFI sub-system for v2019.07-rc3
The development target for the UEFI sub-system is EBBR compliance. We have
already implemented some further protocols to enable running the UEFI Shell
and the UEFI SCT test suite.
As some boards are severely memory constrained make some of these extras
customizable.
Provide bug fixes. The most prominent ones let us pass the UEFI SCT memory
allocation tests.
Diffstat (limited to 'lib/efi_loader')
| -rw-r--r-- | lib/efi_loader/Kconfig | 69 | ||||
| -rw-r--r-- | lib/efi_loader/Makefile | 6 | ||||
| -rw-r--r-- | lib/efi_loader/efi_boottime.c | 16 | ||||
| -rw-r--r-- | lib/efi_loader/efi_device_path_to_text.c | 6 | ||||
| -rw-r--r-- | lib/efi_loader/efi_memory.c | 92 | ||||
| -rw-r--r-- | lib/efi_loader/efi_root_node.c | 4 |
6 files changed, 128 insertions, 65 deletions
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 50b050159c3..6501ee56aaf 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -1,5 +1,5 @@ config EFI_LOADER - bool "Support running EFI Applications in U-Boot" + bool "Support running UEFI applications" depends on (ARM || X86 || RISCV || SANDBOX) && OF_LIBFDT # We need EFI_STUB_64BIT to be set on x86_64 with EFI_STUB depends on !EFI_STUB || !X86_64 || EFI_STUB_64BIT @@ -11,14 +11,42 @@ config EFI_LOADER select REGEX imply CFB_CONSOLE_ANSI help - Select this option if you want to run EFI applications (like grub2) - on top of U-Boot. If this option is enabled, U-Boot will expose EFI - interfaces to a loaded EFI application, enabling it to reuse U-Boot's - device drivers. + Select this option if you want to run UEFI applications (like GNU + GRUB or iPXE) on top of U-Boot. If this option is enabled, U-Boot + will expose the UEFI API to a loaded application, enabling it to + reuse U-Boot's device drivers. + +if EFI_LOADER + +config EFI_DEVICE_PATH_TO_TEXT + bool "Device path to text protocol" + default y + help + The device path to text protocol converts device nodes and paths to + human readable strings. + +config EFI_LOADER_HII + bool "HII protocols" + default y + help + The Human Interface Infrastructure is a complicated framework that + allows UEFI applications to draw fancy menus and hook strings using + a translation framework. + + U-Boot implements enough of its features to be able to run the UEFI + Shell, but not more than that. + +config EFI_UNICODE_COLLATION_PROTOCOL + bool "Unicode collation protocol" + default y + help + The Unicode collation protocol is used for lexical comparisons. It is + required to run the UEFI shell. + +if EFI_UNICODE_COLLATION_PROTOCOL config EFI_UNICODE_CAPITALIZATION bool "Support Unicode capitalization" - depends on EFI_LOADER default y help Select this option to enable correct handling of the capitalization of @@ -26,33 +54,24 @@ config EFI_UNICODE_CAPITALIZATION set, only the the correct handling of the letters of the codepage used by the FAT file system is ensured. -config EFI_PLATFORM_LANG_CODES - string "Language codes supported by firmware" - depends on EFI_LOADER - default "en-US" - help - This value is used to initialize the PlatformLangCodes variable. Its - value is a semicolon (;) separated list of language codes in native - RFC 4646 format, e.g. "en-US;de-DE". The first language code is used - to initialize the PlatformLang variable. +endif config EFI_LOADER_BOUNCE_BUFFER bool "EFI Applications use bounce buffers for DMA operations" - depends on EFI_LOADER && ARM64 + depends on ARM64 default n help Some hardware does not support DMA to full 64bit addresses. For this hardware we can create a bounce buffer so that payloads don't have to worry about platform details. -config EFI_LOADER_HII - bool "Expose HII protocols to EFI applications" - depends on EFI_LOADER - default y +config EFI_PLATFORM_LANG_CODES + string "Language codes supported by firmware" + default "en-US" help - The Human Interface Infrastructure is a complicated framework that - allows UEFI applications to draw fancy menus and hook strings using - a translation framework. + This value is used to initialize the PlatformLangCodes variable. Its + value is a semicolon (;) separated list of language codes in native + RFC 4646 format, e.g. "en-US;de-DE". The first language code is used + to initialize the PlatformLang variable. - U-Boot implements enough of its features to be able to run the UEFI - Shell, but not more than that. +endif diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index 4e90a35896c..f3d6773bf6b 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -21,16 +21,16 @@ obj-y += efi_bootmgr.o obj-y += efi_boottime.o obj-y += efi_console.o obj-y += efi_device_path.o -obj-y += efi_device_path_to_text.o +obj-$(CONFIG_EFI_DEVICE_PATH_TO_TEXT) += efi_device_path_to_text.o obj-y += efi_device_path_utilities.o obj-y += efi_file.o -obj-y += efi_hii.o efi_hii_config.o +obj-$(CONFIG_EFI_LOADER_HII) += efi_hii.o efi_hii_config.o obj-y += efi_image_loader.o obj-y += efi_memory.o obj-y += efi_root_node.o obj-y += efi_runtime.o obj-y += efi_setup.o -obj-y += efi_unicode_collation.o +obj-$(CONFIG_EFI_UNICODE_COLLATION_PROTOCOL) += efi_unicode_collation.o obj-y += efi_variable.o obj-y += efi_watchdog.o obj-$(CONFIG_LCD) += efi_gop.o diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index b97d55cb451..ec6f5758ded 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -181,10 +181,12 @@ static void efi_queue_event(struct efi_event *event, bool check_tpl) /* Check TPL */ if (check_tpl && efi_tpl >= event->notify_tpl) return; + event->is_queued = false; EFI_CALL_VOID(event->notify_function(event, event->notify_context)); + } else { + event->is_queued = false; } - event->is_queued = false; } /** @@ -513,10 +515,8 @@ efi_status_t efi_remove_protocol(const efi_handle_t handle, ret = efi_search_protocol(handle, protocol, &handler); if (ret != EFI_SUCCESS) return ret; - if (guidcmp(handler->guid, protocol)) - return EFI_INVALID_PARAMETER; if (handler->protocol_interface != protocol_interface) - return EFI_INVALID_PARAMETER; + return EFI_NOT_FOUND; list_del(&handler->link); free(handler); return EFI_SUCCESS; @@ -1439,7 +1439,7 @@ static efi_status_t efi_locate_handle( *buffer_size = size; - /* The buffer size is sufficient but there is not buffer */ + /* The buffer size is sufficient but there is no buffer */ if (!buffer) return EFI_INVALID_PARAMETER; @@ -2261,7 +2261,7 @@ static efi_status_t EFIAPI efi_locate_device_path( EFI_ENTRY("%pUl, %p, %p", protocol, device_path, device); - if (!protocol || !device_path || !*device_path || !device) { + if (!protocol || !device_path || !*device_path) { ret = EFI_INVALID_PARAMETER; goto out; } @@ -2294,6 +2294,10 @@ static efi_status_t EFIAPI efi_locate_device_path( /* Check if dp is a subpath of device_path */ if (memcmp(*device_path, dp, len_dp)) continue; + if (!device) { + ret = EFI_INVALID_PARAMETER; + goto out; + } *device = handles[i]; len_best = len_dp; } diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c index e219f84b28d..f3a95790766 100644 --- a/lib/efi_loader/efi_device_path_to_text.c +++ b/lib/efi_loader/efi_device_path_to_text.c @@ -78,9 +78,9 @@ static char *dp_acpi(char *s, struct efi_device_path *dp) case DEVICE_PATH_SUB_TYPE_ACPI_DEVICE: { struct efi_device_path_acpi_path *adp = (struct efi_device_path_acpi_path *)dp; - s += sprintf(s, "Acpi(PNP%04x", EISA_PNP_NUM(adp->hid)); - if (adp->uid) - s += sprintf(s, ",%d", adp->uid); + + s += sprintf(s, "Acpi(PNP%04X", EISA_PNP_NUM(adp->hid)); + s += sprintf(s, ",%d", adp->uid); s += sprintf(s, ")"); break; } diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index 776077cc35a..76dcaa48f49 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -318,6 +318,44 @@ uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type, return start; } +/** + * efi_check_allocated() - validate address to be freed + * + * Check that the address is within allocated memory: + * + * * The address cannot be NULL. + * * The address must be in a range of the memory map. + * * The address may not point to EFI_CONVENTIONAL_MEMORY. + * + * Page alignment is not checked as this is not a requirement of + * efi_free_pool(). + * + * @addr: address of page to be freed + * @must_be_allocated: return success if the page is allocated + * Return: status code + */ +static efi_status_t efi_check_allocated(u64 addr, bool must_be_allocated) +{ + struct efi_mem_list *item; + + if (!addr) + return EFI_INVALID_PARAMETER; + list_for_each_entry(item, &efi_mem, link) { + u64 start = item->desc.physical_start; + u64 end = start + (item->desc.num_pages << EFI_PAGE_SHIFT); + + if (addr >= start && addr < end) { + if (must_be_allocated ^ + (item->desc.type == EFI_CONVENTIONAL_MEMORY)) + return EFI_SUCCESS; + else + return EFI_NOT_FOUND; + } + } + + return EFI_NOT_FOUND; +} + static uint64_t efi_find_free_memory(uint64_t len, uint64_t max_addr) { struct list_head *lhandle; @@ -373,7 +411,7 @@ efi_status_t efi_allocate_pages(int type, int memory_type, efi_uintn_t pages, uint64_t *memory) { u64 len = pages << EFI_PAGE_SHIFT; - efi_status_t r = EFI_SUCCESS; + efi_status_t ret; uint64_t addr; /* Check import parameters */ @@ -387,43 +425,35 @@ efi_status_t efi_allocate_pages(int type, int memory_type, case EFI_ALLOCATE_ANY_PAGES: /* Any page */ addr = efi_find_free_memory(len, -1ULL); - if (!addr) { - r = EFI_NOT_FOUND; - break; - } + if (!addr) + return EFI_OUT_OF_RESOURCES; break; case EFI_ALLOCATE_MAX_ADDRESS: /* Max address */ addr = efi_find_free_memory(len, *memory); - if (!addr) { - r = EFI_NOT_FOUND; - break; - } + if (!addr) + return EFI_OUT_OF_RESOURCES; break; case EFI_ALLOCATE_ADDRESS: /* Exact address, reserve it. The addr is already in *memory. */ + ret = efi_check_allocated(*memory, false); + if (ret != EFI_SUCCESS) + return EFI_NOT_FOUND; addr = *memory; break; default: /* UEFI doesn't specify other allocation types */ - r = EFI_INVALID_PARAMETER; - break; + return EFI_INVALID_PARAMETER; } - if (r == EFI_SUCCESS) { - uint64_t ret; + /* Reserve that map in our memory maps */ + if (efi_add_memory_map(addr, pages, memory_type, true) != addr) + /* Map would overlap, bail out */ + return EFI_OUT_OF_RESOURCES; - /* Reserve that map in our memory maps */ - ret = efi_add_memory_map(addr, pages, memory_type, true); - if (ret == addr) { - *memory = addr; - } else { - /* Map would overlap, bail out */ - r = EFI_OUT_OF_RESOURCES; - } - } + *memory = addr; - return r; + return EFI_SUCCESS; } void *efi_alloc(uint64_t len, int memory_type) @@ -450,6 +480,11 @@ void *efi_alloc(uint64_t len, int memory_type) efi_status_t efi_free_pages(uint64_t memory, efi_uintn_t pages) { uint64_t r = 0; + efi_status_t ret; + + ret = efi_check_allocated(memory, true); + if (ret != EFI_SUCCESS) + return ret; /* Sanity check */ if (!memory || (memory & EFI_PAGE_MASK) || !pages) { @@ -511,11 +546,12 @@ efi_status_t efi_allocate_pool(int pool_type, efi_uintn_t size, void **buffer) */ efi_status_t efi_free_pool(void *buffer) { - efi_status_t r; + efi_status_t ret; struct efi_pool_allocation *alloc; - if (buffer == NULL) - return EFI_INVALID_PARAMETER; + ret = efi_check_allocated((uintptr_t)buffer, true); + if (ret != EFI_SUCCESS) + return ret; alloc = container_of(buffer, struct efi_pool_allocation, data); @@ -528,9 +564,9 @@ efi_status_t efi_free_pool(void *buffer) /* Avoid double free */ alloc->checksum = 0; - r = efi_free_pages((uintptr_t)alloc, alloc->num_pages); + ret = efi_free_pages((uintptr_t)alloc, alloc->num_pages); - return r; + return ret; } /* diff --git a/lib/efi_loader/efi_root_node.c b/lib/efi_loader/efi_root_node.c index 38514e08209..d8496cc3c27 100644 --- a/lib/efi_loader/efi_root_node.c +++ b/lib/efi_loader/efi_root_node.c @@ -52,15 +52,19 @@ efi_status_t efi_root_node_register(void) (&efi_root, /* Device path protocol */ &efi_guid_device_path, dp, +#if CONFIG_IS_ENABLED(EFI_DEVICE_PATH_TO_TEXT) /* Device path to text protocol */ &efi_guid_device_path_to_text_protocol, (void *)&efi_device_path_to_text, +#endif /* Device path utilities protocol */ &efi_guid_device_path_utilities_protocol, (void *)&efi_device_path_utilities, +#if CONFIG_IS_ENABLED(EFI_UNICODE_COLLATION_PROTOCOL) /* Unicode collation protocol */ &efi_guid_unicode_collation_protocol, (void *)&efi_unicode_collation_protocol, +#endif #if CONFIG_IS_ENABLED(EFI_LOADER_HII) /* HII string protocol */ &efi_guid_hii_string_protocol, |
