From e4afcb2876eeeddd2376c8b07808276b75862498 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Tue, 11 Jun 2019 18:52:33 +0200 Subject: efi_loader: LoadImage w/o SourceBuffer and DevicePath If both SourceBuffer and DevicePath are NULL, LoadImage() must return EFI_INVALID_PARAMETER. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_boottime.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index fa01bbda700..7bb0fc2e521 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1856,17 +1856,10 @@ efi_status_t EFIAPI efi_load_image(bool boot_policy, EFI_ENTRY("%d, %p, %pD, %p, %zd, %p", boot_policy, parent_image, file_path, source_buffer, source_size, image_handle); - if (!image_handle || !efi_search_obj(parent_image)) { - ret = EFI_INVALID_PARAMETER; - goto error; - } - - if (!source_buffer && !file_path) { - ret = EFI_NOT_FOUND; - goto error; - } - /* The parent image handle must refer to a loaded image */ - if (!parent_image->type) { + if (!image_handle || (!source_buffer && !file_path) || + !efi_search_obj(parent_image) || + /* The parent image handle must refer to a loaded image */ + !parent_image->type) { ret = EFI_INVALID_PARAMETER; goto error; } -- cgit v1.3.1 From 200000387c2d16fa069af6e176d1fcb886024f4d Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Tue, 11 Jun 2019 19:00:56 +0200 Subject: efi_loader: LoadImage must return EFI_NOT_FOUND If the file path does not relate to an existing file, LoadImage() must return EFI_NOT_FOUND. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_boottime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 7bb0fc2e521..251dfc4ecc4 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1779,7 +1779,7 @@ efi_status_t efi_load_image_from_path(struct efi_device_path *file_path, /* Open file */ f = efi_file_from_path(file_path); if (!f) - return EFI_DEVICE_ERROR; + return EFI_NOT_FOUND; /* Get file size */ bs = 0; -- cgit v1.3.1 From 1d3e8dc7920d7fa32d4df76adea4809890a6de6c Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Tue, 11 Jun 2019 19:35:20 +0200 Subject: efi_loader: loaded images cannot be started twice If an image already has been started, return EFI_INVALID_PARAMETER when StartImage() is called for the same handle again. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_boottime.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib') diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 251dfc4ecc4..275850a1a8f 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -2863,6 +2863,9 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, EFI_ENTRY("%p, %p, %p", image_handle, exit_data_size, exit_data); /* Check parameters */ + if (image_obj->header.type != EFI_OBJECT_TYPE_LOADED_IMAGE) + return EFI_EXIT(EFI_INVALID_PARAMETER); + ret = EFI_CALL(efi_open_protocol(image_handle, &efi_guid_loaded_image, &info, NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL)); -- cgit v1.3.1 From 98967379b645d7232d4eca22c3b80eaa94a7d7d7 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Tue, 11 Jun 2019 20:05:40 +0200 Subject: efi_loader: correct ExitBootServices() Always use EFI_EXIT() to return from the function. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_boottime.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 275850a1a8f..b26291b919c 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1933,16 +1933,19 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle, efi_uintn_t map_key) { struct efi_event *evt; + efi_status_t ret = EFI_SUCCESS; EFI_ENTRY("%p, %zx", image_handle, map_key); /* Check that the caller has read the current memory map */ - if (map_key != efi_memory_map_key) - return EFI_INVALID_PARAMETER; + if (map_key != efi_memory_map_key) { + ret = EFI_INVALID_PARAMETER; + goto out; + } /* Check if ExitBootServices has already been called */ if (!systab.boottime) - return EFI_EXIT(EFI_SUCCESS); + goto out; /* Stop all timer related activities */ timers_enabled = false; @@ -1990,8 +1993,8 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle, /* Give the payload some time to boot */ efi_set_watchdog(0); WATCHDOG_RESET(); - - return EFI_EXIT(EFI_SUCCESS); +out: + return EFI_EXIT(ret); } /** -- cgit v1.3.1 From 0e22c7cbebefae3a01ea2f10ba1772ba693ee1eb Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 12 Jun 2019 07:17:04 +0200 Subject: efi_loader: AllocatePages() must accept addr == 0 It must be possible to allocate memory at address 0 with AllocatePages(). Move a NULL pointer check. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_memory.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index 8d768512343..27379381e87 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -334,7 +334,6 @@ uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type, * * 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. * @@ -349,8 +348,6 @@ 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); @@ -560,6 +557,9 @@ efi_status_t efi_free_pool(void *buffer) efi_status_t ret; struct efi_pool_allocation *alloc; + if (!buffer) + return EFI_INVALID_PARAMETER; + ret = efi_check_allocated((uintptr_t)buffer, true); if (ret != EFI_SUCCESS) return ret; -- cgit v1.3.1 From 336476a959b9ecac75ba3f6de344829563e213ca Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 12 Jun 2019 19:18:24 +0200 Subject: efi_loader: MetaiMatch() must be case insensitive The MetaiMatch() service of the UnicodeCollationProtocol2 must be case insensitive. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_unicode_collation.c | 65 +++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 24 deletions(-) (limited to 'lib') diff --git a/lib/efi_loader/efi_unicode_collation.c b/lib/efi_loader/efi_unicode_collation.c index f293b423975..4fe23625558 100644 --- a/lib/efi_loader/efi_unicode_collation.c +++ b/lib/efi_loader/efi_unicode_collation.c @@ -73,11 +73,22 @@ out: return ret; } +/** + * next_lower() - get next codepoint converted to lower case + * + * @string: pointer to u16 string, on return advanced by one codepoint + * Return: first codepoint of string converted to lower case + */ +static s32 next_lower(const u16 **string) +{ + return utf_to_lower(utf16_get(string)); +} + /** * metai_match() - compare utf-16 string with a pattern string case-insenitively * - * @s: string to compare - * @p: pattern string + * @string: string to compare + * @pattern: pattern string * * The pattern string may use these: * - * matches >= 0 characters @@ -93,61 +104,67 @@ out: * * Return: true if the string is matched. */ -static bool metai_match(const u16 *s, const u16 *p) +static bool metai_match(const u16 *string, const u16 *pattern) { - u16 first; + s32 first, s, p; + + for (; *string && *pattern;) { + const u16 *string_old = string; + + s = next_lower(&string); + p = next_lower(&pattern); - for (; *s && *p; ++s, ++p) { - switch (*p) { + switch (p) { case '*': /* Match 0 or more characters */ - ++p; - for (;; ++s) { - if (metai_match(s, p)) + for (;; s = next_lower(&string)) { + if (metai_match(string_old, pattern)) return true; - if (!*s) + if (!s) return false; + string_old = string; } case '?': /* Match any one character */ break; case '[': /* Match any character in the set */ - ++p; - first = *p; + p = next_lower(&pattern); + first = p; if (first == ']') /* Empty set */ return false; - ++p; - if (*p == '-') { + p = next_lower(&pattern); + if (p == '-') { /* Range */ - ++p; - if (*s < first || *s > *p) + p = next_lower(&pattern); + if (s < first || s > p) return false; - ++p; - if (*p != ']') + p = next_lower(&pattern); + if (p != ']') return false; } else { /* Set */ bool hit = false; - if (*s == first) + if (s == first) hit = true; - for (; *p && *p != ']'; ++p) { - if (*p == *s) + for (; p && p != ']'; + p = next_lower(&pattern)) { + if (p == s) hit = true; } - if (!hit || *p != ']') + if (!hit || p != ']') return false; } break; default: /* Match one character */ - if (*p != *s) + if (p != s) return false; } } - if (!*p && !*s) + if (!*pattern && !*string) return true; return false; } -- cgit v1.3.1 From 3796156a80739031b5c540ded2483dd87fef8083 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 12 Jun 2019 21:06:28 +0200 Subject: efi_loader: legal characters in StrToFat() The UEFI specification does not specify if the characters that have to be replaced by underscore in function StrToFat() of the Unicode collation protocol are those forbidden in FAT long names or those in FAT short names. EDK2 and UEFI SCT assume it is those forbidden in FAT 8.3 short names. Adjust the list of forbidden characters. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_unicode_collation.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/efi_loader/efi_unicode_collation.c b/lib/efi_loader/efi_unicode_collation.c index 4fe23625558..243c51a8dbe 100644 --- a/lib/efi_loader/efi_unicode_collation.c +++ b/lib/efi_loader/efi_unicode_collation.c @@ -11,8 +11,8 @@ #include #include -/* Characters that may not be used in file names */ -static const char illegal[] = "<>:\"/\\|?*\x7f"; +/* Characters that may not be used in FAT 8.3 file names */ +static const char illegal[] = "+,<=>:;\"/\\|?*[]\x7f"; /* * EDK2 assumes codepage 1250 when creating FAT 8.3 file names. -- cgit v1.3.1 From c77d8e9d893ea06082e3ea0f609895b306db1623 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 12 Jun 2019 23:28:42 +0200 Subject: efi_loader: parameter checks SetVariable() Return EFI_INVALID_PARAMETER if the variable name has zero length or the variable has runtime access but not boottime access. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_variable.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index e56053194da..1d1b23b0e55 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -430,7 +430,9 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name, data_size, data); /* TODO: implement APPEND_WRITE */ - if (!variable_name || !vendor || + if (!variable_name || !*variable_name || !vendor || + ((attributes & EFI_VARIABLE_RUNTIME_ACCESS) && + !(attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS)) || (attributes & EFI_VARIABLE_APPEND_WRITE)) { ret = EFI_INVALID_PARAMETER; goto out; -- cgit v1.3.1 From e771b4b39e8c52f7093ec1126a59daf072ac773b Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Wed, 5 Jun 2019 13:21:38 +0900 Subject: efi_loader: add RuntimeServicesSupported variable This variable is defined in UEFI specification 2.8, section 8.1. Its value should be updated whenever we add any usable runtime services function. Currently we only support SetVirtualAddress() for all systems and ResetSystem() for some. Signed-off-by: AKASHI Takahiro Reviewed-by: Heinrich Schuchardt --- include/efi_api.h | 15 +++++++++++++++ include/efi_loader.h | 3 +++ lib/efi_loader/efi_runtime.c | 24 ++++++++++++++++++++++++ lib/efi_loader/efi_setup.c | 5 +++++ 4 files changed, 47 insertions(+) (limited to 'lib') diff --git a/include/efi_api.h b/include/efi_api.h index 65584dd2d82..d7d95edd4df 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -213,6 +213,21 @@ struct efi_capsule_header { u32 capsule_image_size; }; +#define EFI_RT_SUPPORTED_GET_TIME 0x0001 +#define EFI_RT_SUPPORTED_SET_TIME 0x0002 +#define EFI_RT_SUPPORTED_GET_WAKEUP_TIME 0x0004 +#define EFI_RT_SUPPORTED_SET_WAKEUP_TIME 0x0008 +#define EFI_RT_SUPPORTED_GET_VARIABLE 0x0010 +#define EFI_RT_SUPPORTED_GET_NEXT_VARIABLE_NAME 0x0020 +#define EFI_RT_SUPPORTED_SET_VARIABLE 0x0040 +#define EFI_RT_SUPPORTED_SET_VIRTUAL_ADDRESS_MAP 0x0080 +#define EFI_RT_SUPPORTED_CONVERT_POINTER 0x0100 +#define EFI_RT_SUPPORTED_GET_NEXT_HIGH_MONOTONIC_COUNT 0x0200 +#define EFI_RT_SUPPORTED_RESET_SYSTEM 0x0400 +#define EFI_RT_SUPPORTED_UPDATE_CAPSULE 0x0800 +#define EFI_RT_SUPPORTED_QUERY_CAPSULE_CAPABILITIES 0x1000 +#define EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO 0x2000 + struct efi_runtime_services { struct efi_table_hdr hdr; efi_status_t (EFIAPI *get_time)(struct efi_time *time, diff --git a/include/efi_loader.h b/include/efi_loader.h index f0e1313f934..b07155cecb7 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -573,6 +573,9 @@ static inline int guidcmp(const efi_guid_t *g1, const efi_guid_t *g2) #define __efi_runtime_data __attribute__ ((section (".data.efi_runtime"))) #define __efi_runtime __attribute__ ((section (".text.efi_runtime"))) +/* Indicate supported runtime services */ +efi_status_t efi_init_runtime_supported(void); + /* Update CRC32 in table header */ void __efi_runtime efi_update_table_header_crc32(struct efi_table_hdr *table); diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index 432551d0c8c..0c57d0abd76 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -89,6 +89,30 @@ struct elf_rela { * handle a good number of runtime callbacks */ +efi_status_t efi_init_runtime_supported(void) +{ + u16 efi_runtime_services_supported = 0; + + /* + * This value must be synced with efi_runtime_detach_list + * as well as efi_runtime_services. + */ +#if CONFIG_IS_ENABLED(ARCH_BCM283X) || \ + CONFIG_IS_ENABLED(FSL_LAYERSCAPE) || \ + CONFIG_IS_ENABLED(SYSRESET_X86) || \ + CONFIG_IS_ENABLED(PSCI_RESET) + efi_runtime_services_supported |= EFI_RT_SUPPORTED_RESET_SYSTEM; +#endif + efi_runtime_services_supported |= + EFI_RT_SUPPORTED_SET_VIRTUAL_ADDRESS_MAP; + return EFI_CALL(efi_set_variable(L"RuntimeServicesSupported", + &efi_global_variable_guid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + sizeof(efi_runtime_services_supported), + &efi_runtime_services_supported)); +} + /** * efi_update_table_header_crc32() - Update crc32 in table header * diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index 8691d686d29..bfb57836fa9 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -117,6 +117,11 @@ efi_status_t efi_init_obj_list(void) if (ret != EFI_SUCCESS) goto out; + /* Indicate supported runtime services */ + ret = efi_init_runtime_supported(); + if (ret != EFI_SUCCESS) + goto out; + /* Initialize system table */ ret = efi_initialize_system_table(); if (ret != EFI_SUCCESS) -- cgit v1.3.1 From c5b63bec2f885e2b0a475aca33c7696c59ae6965 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 13 Jun 2019 18:42:40 +0200 Subject: efi_loader: GetTime() must return EFI_UNSUPPORTED If the GetTime() runtime service is not supported, EFI_UNSUPPORTED has to be returned. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_runtime.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index 0c57d0abd76..40fdc0ea928 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -366,8 +366,7 @@ efi_status_t __weak __efi_runtime EFIAPI efi_get_time( struct efi_time *time, struct efi_time_cap *capabilities) { - /* Nothing we can do */ - return EFI_DEVICE_ERROR; + return EFI_UNSUPPORTED; } /** -- cgit v1.3.1 From 2ad238fcc48367b415625b8f0fcacb6eef83985a Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 14 Jun 2019 07:20:51 +0200 Subject: efi_loader: fix SetMode() Correct the check of the mode number in SetMode() service of the simple text output protocol. Clear the screen in SetMode(). Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_console.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) (limited to 'lib') diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index 2fc25e118f2..fef0b2e1e25 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -316,23 +316,6 @@ static efi_status_t EFIAPI efi_cout_query_mode( return EFI_EXIT(EFI_SUCCESS); } -static efi_status_t EFIAPI efi_cout_set_mode( - struct efi_simple_text_output_protocol *this, - unsigned long mode_number) -{ - EFI_ENTRY("%p, %ld", this, mode_number); - - - if (mode_number > efi_con_mode.max_mode) - return EFI_EXIT(EFI_UNSUPPORTED); - - efi_con_mode.mode = mode_number; - efi_con_mode.cursor_column = 0; - efi_con_mode.cursor_row = 0; - - return EFI_EXIT(EFI_SUCCESS); -} - static const struct { unsigned int fg; unsigned int bg; @@ -378,6 +361,20 @@ static efi_status_t EFIAPI efi_cout_clear_screen( return EFI_EXIT(EFI_SUCCESS); } +static efi_status_t EFIAPI efi_cout_set_mode( + struct efi_simple_text_output_protocol *this, + unsigned long mode_number) +{ + EFI_ENTRY("%p, %ld", this, mode_number); + + if (mode_number >= efi_con_mode.max_mode) + return EFI_EXIT(EFI_UNSUPPORTED); + efi_con_mode.mode = mode_number; + EFI_CALL(efi_cout_clear_screen(this)); + + return EFI_EXIT(EFI_SUCCESS); +} + static efi_status_t EFIAPI efi_cout_reset( struct efi_simple_text_output_protocol *this, char extended_verification) -- cgit v1.3.1 From 3950f0f8563acab248214df36053bb6c57b91940 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 14 Jun 2019 07:16:57 +0200 Subject: efi_loader: fix SetAttribute() The SetAttribute() service and the Reset() service of the simple text output protocol must update the attribute value in the mode information. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_console.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index fef0b2e1e25..706e6ad31ea 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -341,6 +341,7 @@ static efi_status_t EFIAPI efi_cout_set_attribute( EFI_ENTRY("%p, %lx", this, attribute); + efi_con_mode.attribute = attribute; if (attribute) printf(ESC"[%u;%u;%um", bold, color[fg].fg, color[bg].bg); else @@ -384,6 +385,7 @@ static efi_status_t EFIAPI efi_cout_reset( /* Clear screen */ EFI_CALL(efi_cout_clear_screen(this)); /* Set default colors */ + efi_con_mode.attribute = 0x07; printf(ESC "[0;37;40m"); return EFI_EXIT(EFI_SUCCESS); -- cgit v1.3.1