diff --git a/disk/part.c b/disk/part.c index 98cc54db20..862078f3e7 100644 --- a/disk/part.c +++ b/disk/part.c @@ -103,17 +103,17 @@ typedef lbaint_t lba512_t; #endif /* - * Overflowless variant of (block_count * mul_by / div_by) + * Overflowless variant of (block_count * mul_by / 2**div_by) * when div_by > mul_by */ -static lba512_t lba512_muldiv(lba512_t block_count, lba512_t mul_by, lba512_t div_by) +static lba512_t lba512_muldiv(lba512_t block_count, lba512_t mul_by, int div_by) { lba512_t bc_quot, bc_rem; /* x * m / d == x / d * m + (x % d) * m / d */ - bc_quot = block_count / div_by; - bc_rem = block_count - div_by * bc_quot; - return bc_quot * mul_by + (bc_rem * mul_by) / div_by; + bc_quot = block_count >> div_by; + bc_rem = block_count - (bc_quot << div_by); + return bc_quot * mul_by + ((bc_rem * mul_by) >> div_by); } void dev_print (struct blk_desc *dev_desc) @@ -193,7 +193,7 @@ void dev_print (struct blk_desc *dev_desc) lba512 = (lba * (dev_desc->blksz/512)); /* round to 1 digit */ /* 2048 = (1024 * 1024) / 512 MB */ - mb = lba512_muldiv(lba512, 10, 2048); + mb = lba512_muldiv(lba512, 10, 11); mb_quot = mb / 10; mb_rem = mb - (10 * mb_quot); diff --git a/include/efi_api.h b/include/efi_api.h index 65584dd2d8..d7d95edd4d 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 f0e1313f93..b07155cecb 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_boottime.c b/lib/efi_loader/efi_boottime.c index fa01bbda70..b26291b919 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; @@ -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; } @@ -1940,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; @@ -1997,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); } /** @@ -2870,6 +2866,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)); diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index 2fc25e118f..706e6ad31e 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; @@ -358,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 @@ -378,6 +362,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) @@ -387,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); diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index 8d76851234..27379381e8 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; diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index 432551d0c8..40fdc0ea92 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 * @@ -342,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; } /** diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index 8691d686d2..bfb57836fa 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) diff --git a/lib/efi_loader/efi_unicode_collation.c b/lib/efi_loader/efi_unicode_collation.c index f293b42397..243c51a8db 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. @@ -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 (; *s && *p; ++s, ++p) { - switch (*p) { + for (; *string && *pattern;) { + const u16 *string_old = string; + + s = next_lower(&string); + p = next_lower(&pattern); + + 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; } diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index e56053194d..1d1b23b0e5 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;