From 18e684dd4ca46a7a1bccc4e30ab47e92315e59c1 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 7 Aug 2018 00:29:01 +0200 Subject: [PATCH 01/16] sandbox: Move BSS after EFI sections Something went wrong when writing the sandbox linker scripts and so we ended up with a .bss section marker right before the efi runtime sections. That obviously is a terrible idea, as it may result in overwriting efi runtime code and data. So let's move the .bss identifier behind the efi sections. Signed-off-by: Alexander Graf --- arch/sandbox/cpu/u-boot.lds | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/sandbox/cpu/u-boot.lds b/arch/sandbox/cpu/u-boot.lds index 727bcc3598..40c2214301 100644 --- a/arch/sandbox/cpu/u-boot.lds +++ b/arch/sandbox/cpu/u-boot.lds @@ -17,9 +17,7 @@ SECTIONS _u_boot_sandbox_getopt : { *(.u_boot_sandbox_getopt) } __u_boot_sandbox_option_end = .; - __bss_start = .; - - .__efi_runtime_start : { + .__efi_runtime_start : { *(.__efi_runtime_start) } @@ -48,6 +46,7 @@ SECTIONS *(.__efi_runtime_rel_stop) } + __bss_start = .; } INSERT BEFORE .data; From ccfc78b820e5e431c5bd73b072e7536a972e1710 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 2 Aug 2018 11:45:57 -0600 Subject: [PATCH 02/16] Revert "efi_loader: efi_allocate_pages is too restrictive" This reverts commit aa909462d01866354f4cd4534db5f571c2cf1fbb. This change caused "dhcp filename" to crash the system on p2371-2180 (Jetson TX1), for example when running test/py. Reverting this change isn't optimal, but at least restores TX1 to a working state. In the future, we should: a) Fix whatever problem causes the crash with this patch applied. This needs further discussion, so isn't something we can immediately do. b) Undo the revert; re-apply the original patch to efi_allocate_pages. Signed-off-by: Stephen Warren Reviewed-by: Simon Glass Signed-off-by: Alexander Graf --- lib/efi_loader/efi_memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index 967c3f733e..4b6269f35e 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -305,7 +305,7 @@ efi_status_t efi_allocate_pages(int type, int memory_type, switch (type) { case EFI_ALLOCATE_ANY_PAGES: /* Any page */ - addr = efi_find_free_memory(len, -1ULL); + addr = efi_find_free_memory(len, gd->start_addr_sp); if (!addr) { r = EFI_NOT_FOUND; break; From 07240da293379cc3e50fef1615b14225d7d583af Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 4 Aug 2018 23:16:06 +0200 Subject: [PATCH 03/16] efi_loader: relocate pointer to tables When applying a virtual memory map we have to update the pointer to the list of configuration tables. Fixes: 4182a129ef73 ("efi_loader: allocate configuration table array") Reported-by: Mark Kettenis Signed-off-by: Heinrich Schuchardt Tested-by: Mark Kettenis Signed-off-by: Alexander Graf --- lib/efi_loader/efi_runtime.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index 06958f23fa..45b7809dec 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -360,6 +360,7 @@ static efi_status_t EFIAPI efi_set_virtual_address_map( efi_physical_addr_t map_start = map->physical_start; efi_physical_addr_t map_len = map->num_pages << EFI_PAGE_SHIFT; efi_physical_addr_t map_end = map_start + map_len; + u64 off = map->virtual_start - map_start; /* Adjust all mmio pointers in this region */ list_for_each(lhandle, &efi_runtime_mmio) { @@ -370,11 +371,17 @@ static efi_status_t EFIAPI efi_set_virtual_address_map( link); if ((map_start <= lmmio->paddr) && (map_end >= lmmio->paddr)) { - u64 off = map->virtual_start - map_start; uintptr_t new_addr = lmmio->paddr + off; *lmmio->ptr = (void *)new_addr; } } + if ((map_start <= (uintptr_t)systab.tables) && + (map_end >= (uintptr_t)systab.tables)) { + char *ptr = (char *)systab.tables; + + ptr += off; + systab.tables = (struct efi_configuration_table *)ptr; + } } /* Move the actual runtime code over */ From 6331cb21650f097d2310de432647b2fbe66935c3 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 20 Aug 2018 14:17:41 +0200 Subject: [PATCH 04/16] x86: Include bss subsections in linker script When we build with -fdata-sections we may end up with bss subsections. Our linker script explicitly lists only a single consecutive bss section though. Adapt the statement to also include subsections. This fixes booting efi-x86_app_defconfig. Signed-off-by: Alexander Graf --- arch/x86/cpu/u-boot-64.lds | 2 +- arch/x86/cpu/u-boot.lds | 2 +- arch/x86/lib/elf_ia32_efi.lds | 2 +- arch/x86/lib/elf_x86_64_efi.lds | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/cpu/u-boot-64.lds b/arch/x86/cpu/u-boot-64.lds index 862aa2d35e..98c7f8e9c5 100644 --- a/arch/x86/cpu/u-boot-64.lds +++ b/arch/x86/cpu/u-boot-64.lds @@ -95,7 +95,7 @@ SECTIONS .bss __rel_dyn_start (OVERLAY) : { __bss_start = .; - *(.bss) + *(.bss*) *(COM*) . = ALIGN(4); __bss_end = .; diff --git a/arch/x86/cpu/u-boot.lds b/arch/x86/cpu/u-boot.lds index a1cc19ce4c..a283c290ee 100644 --- a/arch/x86/cpu/u-boot.lds +++ b/arch/x86/cpu/u-boot.lds @@ -94,7 +94,7 @@ SECTIONS .bss __rel_dyn_start (OVERLAY) : { __bss_start = .; - *(.bss) + *(.bss*) *(COM*) . = ALIGN(4); __bss_end = .; diff --git a/arch/x86/lib/elf_ia32_efi.lds b/arch/x86/lib/elf_ia32_efi.lds index 983fabbc4d..aad61e7f81 100644 --- a/arch/x86/lib/elf_ia32_efi.lds +++ b/arch/x86/lib/elf_ia32_efi.lds @@ -46,7 +46,7 @@ SECTIONS *(.sbss) *(.scommon) *(.dynbss) - *(.bss) + *(.bss*) *(COMMON) /* U-Boot lists and device tree */ diff --git a/arch/x86/lib/elf_x86_64_efi.lds b/arch/x86/lib/elf_x86_64_efi.lds index 7cad70a2e4..b436429b33 100644 --- a/arch/x86/lib/elf_x86_64_efi.lds +++ b/arch/x86/lib/elf_x86_64_efi.lds @@ -44,7 +44,7 @@ SECTIONS *(.sbss) *(.scommon) *(.dynbss) - *(.bss) + *(.bss*) *(COMMON) *(.rel.local) From 1acbd0ea99e7ebd98a78ffcce4ee174f943cab26 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 20 Aug 2018 14:20:51 +0200 Subject: [PATCH 05/16] x86: Enable -fdata-sections always We left -fdata-sections disabled for x86_64 before because we encountered random bugs that were at that time inexplicable. Turns out this really was just side effects of missing .bss* statements in the linker scripts. With those fixed, we can enable data sections for all targets. Signed-off-by: Alexander Graf --- arch/x86/config.mk | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/x86/config.mk b/arch/x86/config.mk index 586e11a0dd..5b04febd68 100644 --- a/arch/x86/config.mk +++ b/arch/x86/config.mk @@ -23,13 +23,11 @@ endif ifeq ($(IS_32BIT),y) PLATFORM_CPPFLAGS += -march=i386 -m32 -# TODO: These break on x86_64; need to debug further -PLATFORM_RELFLAGS += -fdata-sections else PLATFORM_CPPFLAGS += $(if $(CONFIG_SPL_BUILD),,-fpic) -fno-common -m64 endif -PLATFORM_RELFLAGS += -ffunction-sections -fvisibility=hidden +PLATFORM_RELFLAGS += -fdata-sections -ffunction-sections -fvisibility=hidden PLATFORM_LDFLAGS += -Bsymbolic -Bsymbolic-functions PLATFORM_LDFLAGS += -m $(if $(IS_32BIT),elf_i386,elf_x86_64) From 122347f3663e454d73760b4f7ca5c39e680e1e18 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 20 Aug 2018 14:25:49 +0200 Subject: [PATCH 06/16] riscv: Include bss subsections in linker script When we build with -fdata-sections we may end up with bss subsections. Our linker script explicitly lists only a single consecutive bss section though. Adapt the statement to also include subsections. Signed-off-by: Alexander Graf --- arch/riscv/cpu/ax25/u-boot.lds | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/riscv/cpu/ax25/u-boot.lds b/arch/riscv/cpu/ax25/u-boot.lds index 3cc89746b1..c50b9642f1 100644 --- a/arch/riscv/cpu/ax25/u-boot.lds +++ b/arch/riscv/cpu/ax25/u-boot.lds @@ -82,7 +82,7 @@ SECTIONS .bss : { __bss_start = .; - *(.bss) + *(.bss*) . = ALIGN(4); __bss_end = .; } From 3748ed908fd478b36bf698839632b2514c450513 Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Fri, 10 Aug 2018 15:36:32 +0900 Subject: [PATCH 07/16] efi_loader: fix a parameter check at CreateEvent() The commit 21b3edfc9644 ("efi_loader: check parameters of CreateEvent") enforces a strict parameter check at CreateEvent(). On the other hand, UEFI specification version 2.7, section 7.1, says: The EVT_NOTIFY_WAIT and EVT_NOTIFY_SIGNAL flags are exclusive. If neither flag is specified, the caller does not require any notification concerning the event and the NotifyTpl, NotifyFunction, and NotifyContext parameters are ignored. So the check should be mitigated so as to comply with the specification. Without this patch, EDK2's Shell.efi won't be started. Fixes: 21b3edfc9644 ("efi_loader: check parameters of CreateEvent") Signed-off-by: AKASHI Takahiro Reviewed-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/efi_boottime.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index b9e54f551a..1192bdb5f5 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -627,7 +627,8 @@ efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl, return EFI_INVALID_PARAMETER; } - if (is_valid_tpl(notify_tpl) != EFI_SUCCESS) + if ((type & (EVT_NOTIFY_WAIT | EVT_NOTIFY_SIGNAL)) && + (is_valid_tpl(notify_tpl) != EFI_SUCCESS)) return EFI_INVALID_PARAMETER; evt = calloc(1, sizeof(struct efi_event)); From fa995d0d9471b630d2d1942000d5a4f065c5cdd5 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Mon, 6 Aug 2018 22:28:18 +0200 Subject: [PATCH 08/16] efi_loader: avoid NULL dereference in efi_get_memory_map() We should only dereference parameter memory_map_size after checking that it is valid. Fixes: 8e835554b36b ("efi_loader: check parameters of GetMemoryMap") Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/efi_memory.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index 4b6269f35e..3ee1079e75 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -457,11 +457,13 @@ efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size, efi_uintn_t map_size = 0; int map_entries = 0; struct list_head *lhandle; - efi_uintn_t provided_map_size = *memory_map_size; + efi_uintn_t provided_map_size; if (!memory_map_size) return EFI_INVALID_PARAMETER; + provided_map_size = *memory_map_size; + list_for_each(lhandle, &efi_mem) map_entries++; From 483dbab9f9318149e5ea97daacbfae320f53e35a Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 29 Jul 2018 09:49:03 +0200 Subject: [PATCH 09/16] lib: crc32: mark function crc32() as __efi_runtime The function crc32() is needed by the EFI subsystem at runtime. So it has to be linked into the runtime section together with all dependencies. Eliminate empty defines local and ZEXPORT. Mark variables as static which are not exported. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/crc32.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/lib/crc32.c b/lib/crc32.c index 7f545fde4a..71e27df78e 100644 --- a/lib/crc32.c +++ b/lib/crc32.c @@ -12,6 +12,7 @@ #include #else #include +#include #endif #include #include @@ -21,16 +22,18 @@ #endif #include "u-boot/zlib.h" -#define local static -#define ZEXPORT /* empty */ +#ifdef USE_HOSTCC +#define __efi_runtime +#define __efi_runtime_data +#endif #define tole(x) cpu_to_le32(x) #ifdef CONFIG_DYNAMIC_CRC_TABLE -local int crc_table_empty = 1; -local uint32_t crc_table[256]; -local void make_crc_table OF((void)); +static int __efi_runtime_data crc_table_empty = 1; +static uint32_t __efi_runtime_data crc_table[256]; +static void __efi_runtime make_crc_table OF((void)); /* Generate a table for a byte-wise 32-bit CRC calculation on the polynomial: @@ -56,7 +59,7 @@ local void make_crc_table OF((void)); the information needed to generate CRC's on data a byte at a time for all combinations of CRC register values and incoming bytes. */ -local void make_crc_table() +static void __efi_runtime make_crc_table(void) { uint32_t c; int n, k; @@ -83,7 +86,7 @@ local void make_crc_table() * Table of CRC-32's of all single-byte values (made by make_crc_table) */ -local const uint32_t crc_table[256] = { +static const uint32_t __efi_runtime_data crc_table[256] = { tole(0x00000000L), tole(0x77073096L), tole(0xee0e612cL), tole(0x990951baL), tole(0x076dc419L), tole(0x706af48fL), tole(0xe963a535L), tole(0x9e6495a3L), tole(0x0edb8832L), tole(0x79dcb8a4L), tole(0xe0d5e91eL), tole(0x97d2d988L), @@ -176,7 +179,7 @@ const uint32_t * ZEXPORT get_crc_table() /* No ones complement version. JFFS2 (and other things ?) * don't use ones compliment in their CRC calculations. */ -uint32_t ZEXPORT crc32_no_comp(uint32_t crc, const Bytef *buf, uInt len) +uint32_t __efi_runtime crc32_no_comp(uint32_t crc, const Bytef *buf, uInt len) { const uint32_t *tab = crc_table; const uint32_t *b =(const uint32_t *)buf; @@ -218,7 +221,7 @@ uint32_t ZEXPORT crc32_no_comp(uint32_t crc, const Bytef *buf, uInt len) } #undef DO_CRC -uint32_t ZEXPORT crc32 (uint32_t crc, const Bytef *p, uInt len) +uint32_t __efi_runtime crc32(uint32_t crc, const Bytef *p, uInt len) { return crc32_no_comp(crc ^ 0xffffffffL, p, len) ^ 0xffffffffL; } @@ -227,9 +230,8 @@ uint32_t ZEXPORT crc32 (uint32_t crc, const Bytef *p, uInt len) * Calculate the crc32 checksum triggering the watchdog every 'chunk_sz' bytes * of input. */ -uint32_t ZEXPORT crc32_wd (uint32_t crc, - const unsigned char *buf, - uInt len, uInt chunk_sz) +uint32_t crc32_wd(uint32_t crc, const unsigned char *buf, uInt len, + uInt chunk_sz) { #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) const unsigned char *end, *curr; From a39f39cdd8be5cd3e7a8b696a463b621e3d827e0 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 29 Jul 2018 09:49:04 +0200 Subject: [PATCH 10/16] efi_loader: update runtime services table crc32 The crc32 of the runtime services table must be updated after detaching. efi_update_table_header_crc32() must be __efi_runtime. So move it to efi_runtime.c Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- include/efi_loader.h | 3 +++ lib/efi_loader/efi_boottime.c | 12 ------------ lib/efi_loader/efi_runtime.c | 15 +++++++++++++++ 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/include/efi_loader.h b/include/efi_loader.h index 57ca550272..f162adfff7 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -417,6 +417,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"))) +/* Update CRC32 in table header */ +void __efi_runtime efi_update_table_header_crc32(struct efi_table_hdr *table); + /* Call this with mmio_ptr as the _pointer_ to a pointer to an MMIO region * to make it available at runtime */ efi_status_t efi_add_runtime_mmio(void *mmio_ptr, u64 len); diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 1192bdb5f5..3935e4f1ce 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -153,18 +153,6 @@ const char *__efi_nesting_dec(void) return indent_string(--nesting_level); } -/** - * efi_update_table_header_crc32() - Update CRC32 in table header - * - * @table: EFI table - */ -static void efi_update_table_header_crc32(struct efi_table_hdr *table) -{ - table->crc32 = 0; - table->crc32 = crc32(0, (const unsigned char *)table, - table->headersize); -} - /** * efi_queue_event() - queue an EFI event * @event: event to signal diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index 45b7809dec..633e4cc3e5 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -84,6 +84,18 @@ struct elf_rela { * handle a good number of runtime callbacks */ +/** + * efi_update_table_header_crc32() - Update crc32 in table header + * + * @table: EFI table + */ +void __efi_runtime efi_update_table_header_crc32(struct efi_table_hdr *table) +{ + table->crc32 = 0; + table->crc32 = crc32(0, (const unsigned char *)table, + table->headersize); +} + static void EFIAPI efi_reset_system_boottime( enum efi_reset_type reset_type, efi_status_t reset_status, @@ -273,6 +285,9 @@ static void efi_runtime_detach(ulong offset) debug("%s: Setting %p to %lx\n", __func__, p, newaddr); *p = newaddr; } + + /* Update crc32 */ + efi_update_table_header_crc32(&efi_runtime_services.hdr); } /* Relocate EFI runtime to uboot_reloc_base = offset */ From bcfb0e22a8add1fcc99b63adfe2147802f2e1c77 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 29 Jul 2018 15:10:11 +0200 Subject: [PATCH 11/16] efi_loader: document runtime functions Add comments for runtime service functions. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/efi_runtime.c | 153 ++++++++++++++++++++++++++++++++++- 1 file changed, 149 insertions(+), 4 deletions(-) diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index 633e4cc3e5..27136cbedd 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -96,6 +96,20 @@ void __efi_runtime efi_update_table_header_crc32(struct efi_table_hdr *table) table->headersize); } +/** + * efi_reset_system_boottime() - reset system at boottime + * + * This function implements the ResetSystem() runtime service before + * SetVirtualAddressMap() is called. + * + * See the Unified Extensible Firmware Interface (UEFI) specification for + * details. + * + * @reset_type: type of reset to perform + * @reset_status: status code for the reset + * @data_size: size of reset_data + * @reset_data: information about the reset + */ static void EFIAPI efi_reset_system_boottime( enum efi_reset_type reset_type, efi_status_t reset_status, @@ -130,15 +144,17 @@ static void EFIAPI efi_reset_system_boottime( } /** - * efi_get_time_boottime - get current time + * efi_get_time_boottime() - get current time at boottime + * + * This function implements the GetTime runtime service before + * SetVirtualAddressMap() is called. * - * This function implements the GetTime runtime service. * See the Unified Extensible Firmware Interface (UEFI) specification * for details. * * @time: pointer to structure to receive current time * @capabilities: pointer to structure to receive RTC properties - * Return Value: status code + * Returns: status code */ static efi_status_t EFIAPI efi_get_time_boottime( struct efi_time *time, @@ -191,8 +207,22 @@ out: #endif } -/* Boards may override the helpers below to implement RTS functionality */ +/** + * efi_reset_system() - reset system + * + * This function implements the ResetSystem() runtime service after + * SetVirtualAddressMap() is called. It only executes an endless loop. + * Boards may override the helpers below to implement reset functionality. + * + * See the Unified Extensible Firmware Interface (UEFI) specification for + * details. + * + * @reset_type: type of reset to perform + * @reset_status: status code for the reset + * @data_size: size of reset_data + * @reset_data: information about the reset + */ void __weak __efi_runtime EFIAPI efi_reset_system( enum efi_reset_type reset_type, efi_status_t reset_status, @@ -202,11 +232,30 @@ void __weak __efi_runtime EFIAPI efi_reset_system( while (1) { } } +/** + * efi_reset_system_init() - initialize the reset driver + * + * Boards may override this function to initialize the reset driver. + */ efi_status_t __weak efi_reset_system_init(void) { return EFI_SUCCESS; } +/** + * efi_get_time() - get current time + * + * This function implements the GetTime runtime service after + * SetVirtualAddressMap() is called. As the U-Boot driver are not available + * anymore only an error code is returned. + * + * See the Unified Extensible Firmware Interface (UEFI) specification + * for details. + * + * @time: pointer to structure to receive current time + * @capabilities: pointer to structure to receive RTC properties + * Returns: status code + */ efi_status_t __weak __efi_runtime EFIAPI efi_get_time( struct efi_time *time, struct efi_time_cap *capabilities) @@ -353,6 +402,20 @@ void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map) invalidate_icache_all(); } +/** + * efi_set_virtual_address_map() - change from physical to virtual mapping + * + * This function implements the SetVirtualAddressMap() runtime service. + * + * See the Unified Extensible Firmware Interface (UEFI) specification for + * details. + * + * @memory_map_size: size of the virtual map + * @descriptor_size: size of an entry in the map + * @descriptor_version: version of the map entries + * @virtmap: virtual address mapping information + * Return: status code + */ static efi_status_t EFIAPI efi_set_virtual_address_map( unsigned long memory_map_size, unsigned long descriptor_size, @@ -419,6 +482,16 @@ static efi_status_t EFIAPI efi_set_virtual_address_map( return EFI_EXIT(EFI_INVALID_PARAMETER); } +/** + * efi_add_runtime_mmio() - add memory-mapped IO region + * + * This function adds a memory-mapped IO region to the memory map to make it + * available at runtime. + * + * @mmio_ptr: address of the memory-mapped IO region + * @len: size of thememory-mapped IO region + * Returns: status code + */ efi_status_t efi_add_runtime_mmio(void *mmio_ptr, u64 len) { struct efi_runtime_mmio_list *newmmio; @@ -461,21 +534,61 @@ efi_status_t efi_add_runtime_mmio(void *mmio_ptr, u64 len) * address map calls. */ +/** + * efi_unimplemented() - replacement function, returns EFI_UNSUPPORTED + * + * This function is used after SetVirtualAddressMap() is called as replacement + * for services that are not available anymore due to constraints of the U-Boot + * implementation. + * + * Return: EFI_UNSUPPORTED + */ static efi_status_t __efi_runtime EFIAPI efi_unimplemented(void) { return EFI_UNSUPPORTED; } +/** + * efi_device_error() - replacement function, returns EFI_DEVICE_ERROR + * + * This function is used after SetVirtualAddressMap() is called as replacement + * for services that are not available anymore due to constraints of the U-Boot + * implementation. + * + * Return: EFI_DEVICE_ERROR + */ static efi_status_t __efi_runtime EFIAPI efi_device_error(void) { return EFI_DEVICE_ERROR; } +/** + * efi_invalid_parameter() - replacement function, returns EFI_INVALID_PARAMETER + * + * This function is used after SetVirtualAddressMap() is called as replacement + * for services that are not available anymore due to constraints of the U-Boot + * implementation. + * + * Return: EFI_INVALID_PARAMETER + */ static efi_status_t __efi_runtime EFIAPI efi_invalid_parameter(void) { return EFI_INVALID_PARAMETER; } +/** + * efi_update_capsule() - process information from operating system + * + * This function implements the UpdateCapsule() runtime service. + * + * See the Unified Extensible Firmware Interface (UEFI) specification for + * details. + * + * @capsule_header_array: pointer to array of virtual pointers + * @capsule_count: number of pointers in capsule_header_array + * @scatter_gather_list: pointer to arry of physical pointers + * Returns: status code + */ efi_status_t __efi_runtime EFIAPI efi_update_capsule( struct efi_capsule_header **capsule_header_array, efi_uintn_t capsule_count, @@ -484,6 +597,20 @@ efi_status_t __efi_runtime EFIAPI efi_update_capsule( return EFI_UNSUPPORTED; } +/** + * efi_query_capsule_caps() - check if capsule is supported + * + * This function implements the QueryCapsuleCapabilities() runtime service. + * + * See the Unified Extensible Firmware Interface (UEFI) specification for + * details. + * + * @capsule_header_array: pointer to array of virtual pointers + * @capsule_count: number of pointers in capsule_header_array + * @capsule_size: maximum capsule size + * @reset_type: type of reset needed for capsule update + * Returns: status code + */ efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps( struct efi_capsule_header **capsule_header_array, efi_uintn_t capsule_count, @@ -493,6 +620,24 @@ efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps( return EFI_UNSUPPORTED; } +/** + * efi_query_variable_info() - get information about EFI variables + * + * This function implements the QueryVariableInfo() runtime service. + * + * See the Unified Extensible Firmware Interface (UEFI) specification for + * details. + * + * @attributes: bitmask to select variables to be + * queried + * @maximum_variable_storage_size: maximum size of storage area for the + * selected variable types + * @remaining_variable_storage_size: remaining size of storage are for the + * selected variable types + * @maximum_variable_size: maximum size of a variable of the + * selected type + * Returns: status code + */ efi_status_t __efi_runtime EFIAPI efi_query_variable_info( u32 attributes, u64 *maximum_variable_storage_size, From 54bfba2704f89290a68c27561098963d6bea0a92 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 22 Jul 2018 08:06:57 +0200 Subject: [PATCH 12/16] efi_selftest: correct block device unit test The UEFI specification mandates that the create flag is only used in conjunction with both the read and the write flag. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_selftest/efi_selftest_block_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/efi_selftest/efi_selftest_block_device.c b/lib/efi_selftest/efi_selftest_block_device.c index b82e405030..1cd13042e9 100644 --- a/lib/efi_selftest/efi_selftest_block_device.c +++ b/lib/efi_selftest/efi_selftest_block_device.c @@ -415,7 +415,7 @@ static int execute(void) #ifdef CONFIG_FAT_WRITE /* Write file */ - ret = root->open(root, &file, (s16 *)L"u-boot.txt", + ret = root->open(root, &file, (s16 *)L"u-boot.txt", EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0); if (ret != EFI_SUCCESS) { efi_st_error("Failed to open file\n"); From 9d12daff6c3c12a6c30c01a1937305c2e63fae8b Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 5 Jul 2018 19:58:07 +0200 Subject: [PATCH 13/16] efi_loader: EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.Reset() Implement the reset service of the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL. This should resolve the error reported by the SCT in Protocol/SimpleTextOut/BlackBoxTest/SimpleTextOutBBTestFunction_uefi.c:639 Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/efi_console.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index 3fd0d2fd51..b487288785 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -105,14 +105,6 @@ static int term_read_reply(int *n, int num, char end_char) return 0; } -static efi_status_t EFIAPI efi_cout_reset( - struct efi_simple_text_output_protocol *this, - char extended_verification) -{ - EFI_ENTRY("%p, %d", this, extended_verification); - return EFI_EXIT(EFI_UNSUPPORTED); -} - static efi_status_t EFIAPI efi_cout_output_string( struct efi_simple_text_output_protocol *this, const efi_string_t string) @@ -341,6 +333,20 @@ static efi_status_t EFIAPI efi_cout_clear_screen( return EFI_EXIT(EFI_SUCCESS); } +static efi_status_t EFIAPI efi_cout_reset( + struct efi_simple_text_output_protocol *this, + char extended_verification) +{ + EFI_ENTRY("%p, %d", this, extended_verification); + + /* Clear screen */ + EFI_CALL(efi_cout_clear_screen(this)); + /* Set default colors */ + printf(ESC "[0;37;40m"); + + return EFI_EXIT(EFI_SUCCESS); +} + static efi_status_t EFIAPI efi_cout_set_cursor_position( struct efi_simple_text_output_protocol *this, unsigned long column, unsigned long row) From 9b89183b97f3d906a8df1050707d48a74e35caed Mon Sep 17 00:00:00 2001 From: Eugeniu Rosca Date: Sat, 14 Jul 2018 22:53:30 +0200 Subject: [PATCH 14/16] efi: Fix truncation of constant value Starting with commit 867a6ac86dd8 ("efi: Add start-up library code"), sparse constantly complains about truncated constant value in efi.h: include/efi.h:176:35: warning: cast truncates bits from constant value (8000000000000000 becomes 0) This can get quite noisy, preventing real issues to be noticed: $ make defconfig *** Default configuration is based on 'sandbox_defconfig' $ make C=2 -j12 2>&1 | grep truncates | wc -l 441 After the patch is applied: $ make C=2 -j12 2>&1 | grep truncates | wc -l 0 $ sparse --version v0.5.2 Following the suggestion of Heinrich Schuchardt, instead of only fixing the root-cause, I replaced the whole enum of _SHIFT values by ULL defines. This matches both the UEFI 2.7 spec and the Linux kernel implementation. Some ELF size comparison before and after the patch (gcc 7.3.0): efi-x86_payload64_defconfig: text data bss dec hex filename 407174 29432 278676 715282 aea12 u-boot.old 407152 29464 278676 715292 aea1c u-boot.new -22 +32 0 +10 efi-x86_payload32_defconfig: text data bss dec hex filename 447075 30308 280076 757459 b8ed3 u-boot.old 447053 30340 280076 757469 b8edd u-boot.new -22 +32 0 +10 Fixes: 867a6ac86dd8 ("efi: Add start-up library code") Suggested-by: Heinrich Schuchardt Signed-off-by: Eugeniu Rosca Reviewed-by: Heinrich Schuchardt Reviewed-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- cmd/efi.c | 22 +++++++++++----------- include/efi.h | 24 ++++++++++-------------- lib/efi_loader/efi_memory.c | 7 +++---- 3 files changed, 24 insertions(+), 29 deletions(-) diff --git a/cmd/efi.c b/cmd/efi.c index 6c1eb88424..92a565f713 100644 --- a/cmd/efi.c +++ b/cmd/efi.c @@ -28,18 +28,18 @@ static const char *const type_name[] = { }; static struct attr_info { - int shift; + u64 val; const char *name; } mem_attr[] = { - { EFI_MEMORY_UC_SHIFT, "uncached" }, - { EFI_MEMORY_WC_SHIFT, "write-coalescing" }, - { EFI_MEMORY_WT_SHIFT, "write-through" }, - { EFI_MEMORY_WB_SHIFT, "write-back" }, - { EFI_MEMORY_UCE_SHIFT, "uncached & exported" }, - { EFI_MEMORY_WP_SHIFT, "write-protect" }, - { EFI_MEMORY_RP_SHIFT, "read-protect" }, - { EFI_MEMORY_XP_SHIFT, "execute-protect" }, - { EFI_MEMORY_RUNTIME_SHIFT, "needs runtime mapping" } + { EFI_MEMORY_UC, "uncached" }, + { EFI_MEMORY_WC, "write-coalescing" }, + { EFI_MEMORY_WT, "write-through" }, + { EFI_MEMORY_WB, "write-back" }, + { EFI_MEMORY_UCE, "uncached & exported" }, + { EFI_MEMORY_WP, "write-protect" }, + { EFI_MEMORY_RP, "read-protect" }, + { EFI_MEMORY_XP, "execute-protect" }, + { EFI_MEMORY_RUNTIME, "needs runtime mapping" } }; /* Maximum different attribute values we can track */ @@ -173,7 +173,7 @@ static void efi_print_mem_table(struct efi_entry_memmap *map, printf("%c%llx: ", attr & EFI_MEMORY_RUNTIME ? 'r' : ' ', attr & ~EFI_MEMORY_RUNTIME); for (j = 0, first = true; j < ARRAY_SIZE(mem_attr); j++) { - if (attr & (1ULL << mem_attr[j].shift)) { + if (attr & mem_attr[j].val) { if (first) first = false; else diff --git a/include/efi.h b/include/efi.h index 41530a7537..cfdccd7693 100644 --- a/include/efi.h +++ b/include/efi.h @@ -170,20 +170,16 @@ enum efi_mem_type { }; /* Attribute values */ -enum { - EFI_MEMORY_UC_SHIFT = 0, /* uncached */ - EFI_MEMORY_WC_SHIFT = 1, /* write-coalescing */ - EFI_MEMORY_WT_SHIFT = 2, /* write-through */ - EFI_MEMORY_WB_SHIFT = 3, /* write-back */ - EFI_MEMORY_UCE_SHIFT = 4, /* uncached, exported */ - EFI_MEMORY_WP_SHIFT = 12, /* write-protect */ - EFI_MEMORY_RP_SHIFT = 13, /* read-protect */ - EFI_MEMORY_XP_SHIFT = 14, /* execute-protect */ - EFI_MEMORY_RUNTIME_SHIFT = 63, /* range requires runtime mapping */ - - EFI_MEMORY_RUNTIME = 1ULL << EFI_MEMORY_RUNTIME_SHIFT, - EFI_MEM_DESC_VERSION = 1, -}; +#define EFI_MEMORY_UC ((u64)0x0000000000000001ULL) /* uncached */ +#define EFI_MEMORY_WC ((u64)0x0000000000000002ULL) /* write-coalescing */ +#define EFI_MEMORY_WT ((u64)0x0000000000000004ULL) /* write-through */ +#define EFI_MEMORY_WB ((u64)0x0000000000000008ULL) /* write-back */ +#define EFI_MEMORY_UCE ((u64)0x0000000000000010ULL) /* uncached, exported */ +#define EFI_MEMORY_WP ((u64)0x0000000000001000ULL) /* write-protect */ +#define EFI_MEMORY_RP ((u64)0x0000000000002000ULL) /* read-protect */ +#define EFI_MEMORY_XP ((u64)0x0000000000004000ULL) /* execute-protect */ +#define EFI_MEMORY_RUNTIME ((u64)0x8000000000000000ULL) /* range requires runtime mapping */ +#define EFI_MEM_DESC_VERSION 1 #define EFI_PAGE_SHIFT 12 #define EFI_PAGE_SIZE (1UL << EFI_PAGE_SHIFT) diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index 3ee1079e75..e2b40aa85b 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -178,14 +178,13 @@ uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type, switch (memory_type) { case EFI_RUNTIME_SERVICES_CODE: case EFI_RUNTIME_SERVICES_DATA: - newlist->desc.attribute = (1 << EFI_MEMORY_WB_SHIFT) | - (1ULL << EFI_MEMORY_RUNTIME_SHIFT); + newlist->desc.attribute = EFI_MEMORY_WB | EFI_MEMORY_RUNTIME; break; case EFI_MMAP_IO: - newlist->desc.attribute = 1ULL << EFI_MEMORY_RUNTIME_SHIFT; + newlist->desc.attribute = EFI_MEMORY_RUNTIME; break; default: - newlist->desc.attribute = 1 << EFI_MEMORY_WB_SHIFT; + newlist->desc.attribute = EFI_MEMORY_WB; break; } From c3a40cce2a9765de6776e2c099d59879e49dfe4b Mon Sep 17 00:00:00 2001 From: Eugeniu Rosca Date: Sat, 14 Jul 2018 22:53:31 +0200 Subject: [PATCH 15/16] efi: Add EFI_MEMORY_{NV, MORE_RELIABLE, RO} attributes With this update, the memory attributes are in sync with Linux kernel v4.18-rc4. They also match page 190 of UEFI 2.7 spec [1]. [1] http://www.uefi.org/sites/default/files/resources/UEFI_Spec_2_7.pdf Suggested-by: Heinrich Schuchardt Signed-off-by: Eugeniu Rosca Reviewed-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- cmd/efi.c | 3 +++ include/efi.h | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/cmd/efi.c b/cmd/efi.c index 92a565f713..366a79a964 100644 --- a/cmd/efi.c +++ b/cmd/efi.c @@ -39,6 +39,9 @@ static struct attr_info { { EFI_MEMORY_WP, "write-protect" }, { EFI_MEMORY_RP, "read-protect" }, { EFI_MEMORY_XP, "execute-protect" }, + { EFI_MEMORY_NV, "non-volatile" }, + { EFI_MEMORY_MORE_RELIABLE, "higher reliability" }, + { EFI_MEMORY_RO, "read-only" }, { EFI_MEMORY_RUNTIME, "needs runtime mapping" } }; diff --git a/include/efi.h b/include/efi.h index cfdccd7693..7e7c1cafc2 100644 --- a/include/efi.h +++ b/include/efi.h @@ -178,6 +178,10 @@ enum efi_mem_type { #define EFI_MEMORY_WP ((u64)0x0000000000001000ULL) /* write-protect */ #define EFI_MEMORY_RP ((u64)0x0000000000002000ULL) /* read-protect */ #define EFI_MEMORY_XP ((u64)0x0000000000004000ULL) /* execute-protect */ +#define EFI_MEMORY_NV ((u64)0x0000000000008000ULL) /* non-volatile */ +#define EFI_MEMORY_MORE_RELIABLE \ + ((u64)0x0000000000010000ULL) /* higher reliability */ +#define EFI_MEMORY_RO ((u64)0x0000000000020000ULL) /* read-only */ #define EFI_MEMORY_RUNTIME ((u64)0x8000000000000000ULL) /* range requires runtime mapping */ #define EFI_MEM_DESC_VERSION 1 From dbb148b22cbf242156edf53cca6d661cd320cb83 Mon Sep 17 00:00:00 2001 From: Eugeniu Rosca Date: Sat, 14 Jul 2018 22:53:32 +0200 Subject: [PATCH 16/16] cmd: efi: Clarify calculation precedence for '&' and '?' Fix cppcheck complaint: [cmd/efi.c:173]: (style) Clarify calculation precedence for '&' and '?'. Fixes: f1a0bafb5802 ("efi: Add a command to display the memory map") Signed-off-by: Eugeniu Rosca Reviewed-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- cmd/efi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/efi.c b/cmd/efi.c index 366a79a964..919cb2fcfd 100644 --- a/cmd/efi.c +++ b/cmd/efi.c @@ -173,7 +173,7 @@ static void efi_print_mem_table(struct efi_entry_memmap *map, bool first; int j; - printf("%c%llx: ", attr & EFI_MEMORY_RUNTIME ? 'r' : ' ', + printf("%c%llx: ", (attr & EFI_MEMORY_RUNTIME) ? 'r' : ' ', attr & ~EFI_MEMORY_RUNTIME); for (j = 0, first = true; j < ARRAY_SIZE(mem_attr); j++) { if (attr & mem_attr[j].val) {