From 4b05fe9c550ba4941e973c1bc389555d73747ed4 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 16 Dec 2018 11:16:03 +0100 Subject: efi_loader: efi_guid_t must be 64-bit aligned The UEFI Specification Version 2.7 Errata A defines: "EFI_GUID 128-bit buffer containing a unique identifier value. Unless otherwise specified, aligned on a 64-bit boundary." Before this patch efi_guid_t was 8-bit aligned. Signed-off-by: Heinrich Schuchardt Acked-by: Ard Biesheuvel Signed-off-by: Alexander Graf --- include/efi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/efi.h b/include/efi.h index b5e2c64f38b..d98441ab19d 100644 --- a/include/efi.h +++ b/include/efi.h @@ -49,7 +49,7 @@ struct efi_device_path; typedef struct { u8 b[16]; -} efi_guid_t; +} efi_guid_t __attribute__((aligned(8))); #define EFI_BITS_PER_LONG (sizeof(long) * 8) -- cgit v1.2.3 From 2859f446b081db62336c32a832af026d37ab00b4 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Tue, 18 Dec 2018 00:06:05 +0100 Subject: efi_loader: struct efi_configuration_table Commit 393fccdf6c73 ("efi_loader: efi_guid_t must be 64-bit aligned") has changed the alignment of efi_guid_t. This changed the size of struct efi_configuration_table on 32-bit systems form 20 to 24 bytes. As an array of this type is pointed to by the system table this breaks compatibility with existing versions of GRUB and Linux. Let's get back the original size by using the attribute __packed. Fixes: 393fccdf6c73 ("efi_loader: efi_guid_t must be 64-bit aligned") Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- include/efi_api.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/efi_api.h b/include/efi_api.h index aef77b6319d..0e5c6e92d0d 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -299,7 +299,7 @@ struct efi_runtime_services { struct efi_configuration_table { efi_guid_t guid; void *table; -}; +} __packed; #define EFI_SYSTEM_TABLE_SIGNATURE ((u64)0x5453595320494249ULL) -- cgit v1.2.3 From 2a3537ae2272d9699312a0855a7b72472d1719c5 Mon Sep 17 00:00:00 2001 From: Akashi, Takahiro Date: Fri, 14 Dec 2018 19:10:38 +0900 Subject: lib: add u16_strcpy/strdup functions Add u16_strcpy() and u16_strdup(). The latter function will be used later in implementing efi HII database protocol. Signed-off-by: Akashi Takahiro Reviewed-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- include/charset.h | 23 +++++++++++++++++++++++ lib/charset.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/include/charset.h b/include/charset.h index 4d45e246e51..65087f76d1f 100644 --- a/include/charset.h +++ b/include/charset.h @@ -191,6 +191,29 @@ size_t u16_strlen(const u16 *in); */ size_t u16_strnlen(const u16 *in, size_t count); +/** + * u16_strcpy() - copy u16 string + * + * Copy u16 string pointed to by src, including terminating null word, to + * the buffer pointed to by dest. + * + * @dest: destination buffer + * @src: source buffer (null terminated) + * Return: 'dest' address + */ +u16 *u16_strcpy(u16 *dest, const u16 *src); + +/** + * u16_strdup() - duplicate u16 string + * + * Copy u16 string pointed to by src, including terminating null word, to a + * newly allocated buffer. + * + * @src: source buffer (null terminated) + * Return: allocated new buffer on success, NULL on failure + */ +u16 *u16_strdup(const u16 *src); + /** * utf16_to_utf8() - Convert an utf16 string to utf8 * diff --git a/lib/charset.c b/lib/charset.c index 10557b9e753..5e349ed5ee4 100644 --- a/lib/charset.c +++ b/lib/charset.c @@ -349,6 +349,35 @@ size_t u16_strnlen(const u16 *in, size_t count) return i; } +u16 *u16_strcpy(u16 *dest, const u16 *src) +{ + u16 *tmp = dest; + + for (;; dest++, src++) { + *dest = *src; + if (!*src) + break; + } + + return tmp; +} + +u16 *u16_strdup(const u16 *src) +{ + u16 *new; + + if (!src) + return NULL; + + new = malloc((u16_strlen(src) + 1) * sizeof(u16)); + if (!new) + return NULL; + + u16_strcpy(new, src); + + return new; +} + /* Convert UTF-16 to UTF-8. */ uint8_t *utf16_to_utf8(uint8_t *dest, const uint16_t *src, size_t size) { -- cgit v1.2.3 From abb93cb0e548fbf3b6d88e044b52bb8bc8773577 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 14 Dec 2018 22:00:37 +0100 Subject: test: tests for u16_strdup() and u16_strcpy() Provide unit tests for u16_strdup() and u16_strcpy(). Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- test/unicode_ut.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/unicode_ut.c b/test/unicode_ut.c index b115d18afd3..84fc9a3b537 100644 --- a/test/unicode_ut.c +++ b/test/unicode_ut.c @@ -50,6 +50,29 @@ static const char j1[] = {0x6a, 0x31, 0xa1, 0x6c, 0x00}; static const char j2[] = {0x6a, 0x32, 0xc3, 0xc3, 0x6c, 0x00}; static const char j3[] = {0x6a, 0x33, 0xf0, 0x90, 0xf0, 0x00}; +static int ut_u16_strdup(struct unit_test_state *uts) +{ + u16 *copy = u16_strdup(c4); + + ut_assert(copy != c4); + ut_assert(!memcmp(copy, c4, sizeof(c4))); + free(copy); + return 0; +} +UNICODE_TEST(ut_u16_strdup); + +static int ut_u16_strcpy(struct unit_test_state *uts) +{ + u16 *r; + u16 copy[10]; + + r = u16_strcpy(copy, c1); + ut_assert(r == copy); + ut_assert(!memcmp(copy, c1, sizeof(c1))); + return 0; +} +UNICODE_TEST(ut_u16_strcpy); + /* U-Boot uses UTF-16 strings in the EFI context only. */ #if CONFIG_IS_ENABLED(EFI_LOADER) && !defined(API_BUILD) static int ut_string16(struct unit_test_state *uts) -- cgit v1.2.3 From 9493e39cd4efef1dcd8420235685b90a0190f752 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 21 Dec 2018 02:18:16 +0100 Subject: distro_bootcmd: add NVME support Some boards support NVME drives. We should be able to use them as boot devices. NVME access requires running 'nvme scan'. Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass Signed-off-by: Alexander Graf --- include/config_distro_bootcmd.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h index 555efb7433f..fa0e017b56e 100644 --- a/include/config_distro_bootcmd.h +++ b/include/config_distro_bootcmd.h @@ -178,6 +178,31 @@ BOOT_TARGET_DEVICES_references_SATA_without_CONFIG_SATA #endif +#ifdef CONFIG_NVME +#define BOOTENV_RUN_NVME_INIT "run nvme_init; " +#define BOOTENV_SET_NVME_NEED_INIT "setenv nvme_need_init; " +#define BOOTENV_SHARED_NVME \ + "nvme_init=" \ + "if ${nvme_need_init}; then " \ + "setenv nvme_need_init false; " \ + "nvme scan; " \ + "fi\0" \ + \ + "nvme_boot=" \ + BOOTENV_RUN_NVME_INIT \ + BOOTENV_SHARED_BLKDEV_BODY(nvme) +#define BOOTENV_DEV_NVME BOOTENV_DEV_BLKDEV +#define BOOTENV_DEV_NAME_NVME BOOTENV_DEV_NAME_BLKDEV +#else +#define BOOTENV_RUN_NVME_INIT +#define BOOTENV_SET_NVME_NEED_INIT +#define BOOTENV_SHARED_NVME +#define BOOTENV_DEV_NVME \ + BOOT_TARGET_DEVICES_references_NVME_without_CONFIG_NVME +#define BOOTENV_DEV_NAME_NVME \ + BOOT_TARGET_DEVICES_references_NVME_without_CONFIG_NVME +#endif + #ifdef CONFIG_SCSI #define BOOTENV_RUN_SCSI_INIT "run scsi_init; " #define BOOTENV_SET_SCSI_NEED_INIT "setenv scsi_need_init; " @@ -359,6 +384,7 @@ BOOTENV_SHARED_USB \ BOOTENV_SHARED_SATA \ BOOTENV_SHARED_SCSI \ + BOOTENV_SHARED_NVME \ BOOTENV_SHARED_IDE \ BOOTENV_SHARED_UBIFS \ BOOTENV_SHARED_EFI \ @@ -423,6 +449,7 @@ BOOT_TARGET_DEVICES(BOOTENV_DEV) \ \ "distro_bootcmd=" BOOTENV_SET_SCSI_NEED_INIT \ + BOOTENV_SET_NVME_NEED_INIT \ "for target in ${boot_targets}; do " \ "run bootcmd_${target}; " \ "done\0" -- cgit v1.2.3 From fb34f298e6095f14895739d24c5c901594030506 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 23 Dec 2018 02:35:13 +0100 Subject: efi_loader: efi_add_runtime_mmio() The first parameter of efi_add_runtime_mmio() is a pointer to a pointer. This should be reflected in the documentation. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/efi_runtime.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index fff93f0960b..636dfdab39d 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -530,7 +530,8 @@ static efi_status_t EFIAPI efi_set_virtual_address_map( * 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 + * @mmio_ptr: pointer to a pointer to the start of the memory-mapped + * IO region * @len: size of the memory-mapped IO region * Returns: status code */ -- cgit v1.2.3 From d178836bd21ed1436ec612c8a8b5b4e1ca792087 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 9 Dec 2018 16:39:20 +0100 Subject: efi_loader: efi_connect_controller() use %pD EFI_ENTRY in efi_connect_controller() should use %pD to print the remaining device path. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/efi_boottime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index cc9efbb0cbf..f592e4083ff 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -2825,7 +2825,7 @@ static efi_status_t EFIAPI efi_connect_controller( efi_status_t ret = EFI_NOT_FOUND; struct efi_object *efiobj; - EFI_ENTRY("%p, %p, %p, %d", controller_handle, driver_image_handle, + EFI_ENTRY("%p, %p, %pD, %d", controller_handle, driver_image_handle, remain_device_path, recursive); efiobj = efi_search_obj(controller_handle); -- cgit v1.2.3 From 13dd6665ed18f72380ca596931d609bc108d4b82 Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Tue, 4 Dec 2018 15:46:55 +0900 Subject: distro: not taint environment variables if possible The aim of this patch is not to have temporary variables used in distro_bootcmd left as environment variables after run something. See the discussion[1]. Without this patch, saveenv command also saves those variables, too. While they are apparently safe, scsi_need_init can be harmful. Please note that, in most cases, a variable should be converted to hush's local variable, while "devplist" cannot because it is created by "part" command as an environment variable. [1] https://lists.denx.de/pipermail/u-boot/2018-December/350209.html Signed-off-by: AKASHI Takahiro Signed-off-by: Alexander Graf --- include/config_distro_bootcmd.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h index fa0e017b56e..4993303f4d9 100644 --- a/include/config_distro_bootcmd.h +++ b/include/config_distro_bootcmd.h @@ -27,7 +27,7 @@ #define BOOTENV_SHARED_BLKDEV_BODY(devtypel) \ "if " #devtypel " dev ${devnum}; then " \ - "setenv devtype " #devtypel "; " \ + "devtype=" #devtypel "; " \ "run scan_dev_for_boot_part; " \ "fi\0" @@ -37,7 +37,7 @@ #define BOOTENV_DEV_BLKDEV(devtypeu, devtypel, instance) \ "bootcmd_" #devtypel #instance "=" \ - "setenv devnum " #instance "; " \ + "devnum=" #instance "; " \ "run " #devtypel "_boot\0" #define BOOTENV_DEV_NAME_BLKDEV(devtypeu, devtypel, instance) \ @@ -77,7 +77,7 @@ "if ubi part ${bootubipart} && " \ "ubifsmount ubi${devnum}:${bootubivol}; " \ "then " \ - "setenv devtype ubi; " \ + "devtype=ubi; " \ "run scan_dev_for_boot; " \ "fi\0" #define BOOTENV_DEV_UBIFS BOOTENV_DEV_BLKDEV @@ -205,11 +205,11 @@ #ifdef CONFIG_SCSI #define BOOTENV_RUN_SCSI_INIT "run scsi_init; " -#define BOOTENV_SET_SCSI_NEED_INIT "setenv scsi_need_init; " +#define BOOTENV_SET_SCSI_NEED_INIT "scsi_need_init=; " #define BOOTENV_SHARED_SCSI \ "scsi_init=" \ "if ${scsi_need_init}; then " \ - "setenv scsi_need_init false; " \ + "scsi_need_init=false; " \ "scsi scan; " \ "fi\0" \ \ @@ -444,7 +444,8 @@ "bootfstype; then " \ "run scan_dev_for_boot; " \ "fi; " \ - "done\0" \ + "done; " \ + "setenv devplist\0" \ \ BOOT_TARGET_DEVICES(BOOTENV_DEV) \ \ -- cgit v1.2.3 From 0a76ba65568435e3cf630e146c4a630e9ee8db1f Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 26 Dec 2018 22:23:00 +0100 Subject: efi_loader: use named constant for efi_dp_from_mem() When calling efi_dp_from_mem() use a named constant for the memory type. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- cmd/bootefi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 38679ffc56a..cc0f2923dcf 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -386,7 +386,7 @@ static efi_status_t do_bootefi_exec(void *efi, if (!device_path && !image_path) { printf("WARNING: using memory device/image path, this may confuse some payloads!\n"); /* actual addresses filled in after efi_load_pe() */ - memdp = efi_dp_from_mem(0, 0, 0); + memdp = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, 0, 0); device_path = image_path = memdp; /* * Grub expects that the device path of the loaded image is -- cgit v1.2.3 From 0ea8741ff65e2b1cf86763b1f6392499df286ce1 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 30 Dec 2018 10:11:14 +0100 Subject: efi_loader: CMD_BOOTEFI_HELLO_COMPILE in configs It should not be necessary to adjust CMD_BOOTEFI_HELLO_COMPILE in config files. arch/arm/lib/crt0_arm_efi.S cannot be compiled in thumbs mode. We can disable CMD_BOOTEFI_HELLO_COMPILE for CONFIG_CPU_V7M. So there is no longer a need to disable it in stm32 configs. helloworld.efi can be built without problems on x86_64. So there is no need to disable it in chromebook_link64_defconfig and qemu-x86_64_defconfig. Same is true for ARM V7A. So do not disable CMD_BOOTEFI_HELLO_COMPILE in kp_imx6q_tpc_defconfig. Some architecture checks are already make for EFI_LOADER. There is no need to repeat them for CMD_BOOTEFI_HELLO_COMPILE Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass Reviewed-by: Patrice.Chotard@st.com Signed-off-by: Alexander Graf --- cmd/Kconfig | 2 +- configs/chromebook_link64_defconfig | 1 - configs/kp_imx6q_tpc_defconfig | 1 - configs/qemu-x86_64_defconfig | 1 - configs/stm32f429-discovery_defconfig | 1 - configs/stm32f429-evaluation_defconfig | 1 - configs/stm32f469-discovery_defconfig | 1 - 7 files changed, 1 insertion(+), 7 deletions(-) diff --git a/cmd/Kconfig b/cmd/Kconfig index ea1a325eb30..3ea42e42561 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -226,7 +226,7 @@ config CMD_BOOTEFI config CMD_BOOTEFI_HELLO_COMPILE bool "Compile a standard EFI hello world binary for testing" - depends on CMD_BOOTEFI && (ARM || X86 || RISCV) + depends on CMD_BOOTEFI && !CPU_V7M && !SANDBOX default y help This compiles a standard EFI hello world application with U-Boot so diff --git a/configs/chromebook_link64_defconfig b/configs/chromebook_link64_defconfig index 074d333dd4e..12f26570af7 100644 --- a/configs/chromebook_link64_defconfig +++ b/configs/chromebook_link64_defconfig @@ -38,7 +38,6 @@ CONFIG_SPL_PCH_SUPPORT=y CONFIG_SPL_RTC_SUPPORT=y CONFIG_HUSH_PARSER=y CONFIG_CMD_CPU=y -# CONFIG_CMD_BOOTEFI_HELLO_COMPILE is not set # CONFIG_CMD_FLASH is not set CONFIG_CMD_GPIO=y CONFIG_CMD_SF=y diff --git a/configs/kp_imx6q_tpc_defconfig b/configs/kp_imx6q_tpc_defconfig index da07d9c7723..cb58ed6678b 100644 --- a/configs/kp_imx6q_tpc_defconfig +++ b/configs/kp_imx6q_tpc_defconfig @@ -21,7 +21,6 @@ CONFIG_SPL_RAW_IMAGE_SUPPORT=y CONFIG_SPL_WATCHDOG_SUPPORT=y CONFIG_AUTOBOOT_KEYED=y CONFIG_AUTOBOOT_STOP_STR="." -# CONFIG_CMD_BOOTEFI_HELLO_COMPILE is not set # CONFIG_CMD_ELF is not set # CONFIG_CMD_FLASH is not set CONFIG_CMD_GPIO=y diff --git a/configs/qemu-x86_64_defconfig b/configs/qemu-x86_64_defconfig index 8d43acd4802..34acc09317d 100644 --- a/configs/qemu-x86_64_defconfig +++ b/configs/qemu-x86_64_defconfig @@ -36,7 +36,6 @@ CONFIG_SPL_PCH_SUPPORT=y CONFIG_SPL_RTC_SUPPORT=y CONFIG_HUSH_PARSER=y CONFIG_CMD_CPU=y -# CONFIG_CMD_BOOTEFI_HELLO_COMPILE is not set CONFIG_CMD_BOOTEFI_SELFTEST=y # CONFIG_CMD_FLASH is not set CONFIG_CMD_IDE=y diff --git a/configs/stm32f429-discovery_defconfig b/configs/stm32f429-discovery_defconfig index 265b1ec0682..fe3176cac01 100644 --- a/configs/stm32f429-discovery_defconfig +++ b/configs/stm32f429-discovery_defconfig @@ -15,7 +15,6 @@ CONFIG_MISC_INIT_R=y CONFIG_BOARD_EARLY_INIT_F=y CONFIG_HUSH_PARSER=y CONFIG_SYS_PROMPT="U-Boot > " -# CONFIG_CMD_BOOTEFI_HELLO_COMPILE is not set CONFIG_CMD_IMLS=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_TIMER=y diff --git a/configs/stm32f429-evaluation_defconfig b/configs/stm32f429-evaluation_defconfig index 9f1a7680ad0..041f0423832 100644 --- a/configs/stm32f429-evaluation_defconfig +++ b/configs/stm32f429-evaluation_defconfig @@ -12,7 +12,6 @@ CONFIG_MISC_INIT_R=y # CONFIG_DISPLAY_CPUINFO is not set CONFIG_BOARD_EARLY_INIT_F=y CONFIG_SYS_PROMPT="U-Boot > " -# CONFIG_CMD_BOOTEFI_HELLO_COMPILE is not set CONFIG_CMD_IMLS=y CONFIG_CMD_GPT=y # CONFIG_RANDOM_UUID is not set diff --git a/configs/stm32f469-discovery_defconfig b/configs/stm32f469-discovery_defconfig index 801af6bb618..c2b600025e8 100644 --- a/configs/stm32f469-discovery_defconfig +++ b/configs/stm32f469-discovery_defconfig @@ -12,7 +12,6 @@ CONFIG_MISC_INIT_R=y # CONFIG_DISPLAY_CPUINFO is not set CONFIG_BOARD_EARLY_INIT_F=y CONFIG_SYS_PROMPT="U-Boot > " -# CONFIG_CMD_BOOTEFI_HELLO_COMPILE is not set CONFIG_CMD_IMLS=y CONFIG_CMD_GPT=y # CONFIG_RANDOM_UUID is not set -- cgit v1.2.3 From 23f5f4abf7d04690e43ab5c58f0b6d5b955ffd97 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 5 Jan 2019 23:41:36 +0100 Subject: efi_loader: fix memory allocation on sandbox Commit 7b78d6438a2b ("efi_loader: Reserve unaccessible memory") introduced a comparison between RAM top and RAM start that was not known at the time when the patch of commit 49759743bf09 ("efi_loader: eliminate sandbox addresses") was written. The sandbox uses an address space that is only relevant in the sandbox context. We have to map ram_top from the sandbox address space to the physical address space before using it in the EFI subsystem. Fixes: 49759743bf09 ("efi_loader: eliminate sandbox addresses") Fixes: 7b78d6438a2b ("efi_loader: Reserve unaccessible memory") Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass Signed-off-by: Alexander Graf --- lib/efi_loader/efi_memory.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index 4bb517473e4..ebd2b36c03d 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -554,6 +554,12 @@ __weak void efi_add_known_memory(void) u64 ram_top = board_get_usable_ram_top(0) & ~EFI_PAGE_MASK; int i; + /* + * ram_top is just outside mapped memory. So use an offset of one for + * mapping the sandbox address. + */ + ram_top = (uintptr_t)map_sysmem(ram_top - 1, 0) + 1; + /* Fix for 32bit targets with ram_top at 4G */ if (!ram_top) ram_top = 0x100000000ULL; -- cgit v1.2.3 From c6d876fa2d7f9fde0fae9203ec1f047df9bc1f59 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 28 Dec 2018 12:41:14 +0100 Subject: efi_loader: avoid unnecessary pointer to long conversion debug() support supports %p to print pointers. The debug message is unique. So there is not need to write a possibly distracting line number. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- cmd/bootefi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/bootefi.c b/cmd/bootefi.c index cc0f2923dcf..7ab08382faf 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -428,7 +428,7 @@ static efi_status_t do_bootefi_exec(void *efi, "{ro,boot}(blob)0000000000000000"); /* Call our payload! */ - debug("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry); + debug("%s: Jumping to 0x%p\n", __func__, entry); if (setjmp(&image_obj->exit_jmp)) { ret = image_obj->exit_status; -- cgit v1.2.3 From cc8e34178b5f141ed997843e86248e4d53f37298 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 28 Dec 2018 12:41:15 +0100 Subject: efi_loader: signature of StartImage and Exit We use u16* for Unicode strings and efi_uintn_t for UINTN. Correct the signature of efi_exit() and efi_start_image(). Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- include/efi_api.h | 6 +++--- lib/efi_loader/efi_boottime.c | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/efi_api.h b/include/efi_api.h index 0e5c6e92d0d..4389dbeddcb 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -115,11 +115,11 @@ struct efi_boot_services { struct efi_device_path *file_path, void *source_buffer, efi_uintn_t source_size, efi_handle_t *image); efi_status_t (EFIAPI *start_image)(efi_handle_t handle, - unsigned long *exitdata_size, - s16 **exitdata); + efi_uintn_t *exitdata_size, + u16 **exitdata); efi_status_t (EFIAPI *exit)(efi_handle_t handle, efi_status_t exit_status, - unsigned long exitdata_size, s16 *exitdata); + efi_uintn_t exitdata_size, u16 *exitdata); efi_status_t (EFIAPI *unload_image)(efi_handle_t image_handle); efi_status_t (EFIAPI *exit_boot_services)(efi_handle_t, unsigned long); diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index f592e4083ff..88386ff6760 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1706,8 +1706,8 @@ error: * Return: status code */ static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, - unsigned long *exit_data_size, - s16 **exit_data) + efi_uintn_t *exit_data_size, + u16 **exit_data) { struct efi_loaded_image_obj *image_obj = (struct efi_loaded_image_obj *)image_handle; @@ -1773,8 +1773,8 @@ static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, */ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, efi_status_t exit_status, - unsigned long exit_data_size, - int16_t *exit_data) + efi_uintn_t exit_data_size, + u16 *exit_data) { /* * TODO: We should call the unload procedure of the loaded @@ -1783,7 +1783,7 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, struct efi_loaded_image_obj *image_obj = (struct efi_loaded_image_obj *)image_handle; - EFI_ENTRY("%p, %ld, %ld, %p", image_handle, exit_status, + EFI_ENTRY("%p, %ld, %zu, %p", image_handle, exit_status, exit_data_size, exit_data); /* Make sure entry/exit counts for EFI world cross-overs match */ -- cgit v1.2.3 From e4fd69564532018a4124c6f9d8ba76da766629bd Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 30 Dec 2018 10:52:41 +0100 Subject: efi_selftest: allow building on ARMv7-M ARMv7-M only supports the Thumb instruction set. Our current crt0 code does not support it. With the patch we can build all unit tests of the EFI subsystem that do not require crt0. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- arch/arm/lib/Makefile | 6 +++++- lib/efi_selftest/Makefile | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index 655727f4312..48ee6c3c603 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -106,5 +106,9 @@ CFLAGS_$(EFI_RELOC) := $(CFLAGS_EFI) CFLAGS_REMOVE_$(EFI_RELOC) := $(CFLAGS_NON_EFI) extra-$(CONFIG_CMD_BOOTEFI_HELLO_COMPILE) += $(EFI_CRT0) $(EFI_RELOC) -extra-$(CONFIG_CMD_BOOTEFI_SELFTEST) += $(EFI_CRT0) $(EFI_RELOC) +# TODO: As of v2019.01 the relocation code for the EFI application cannot +# be built on ARMv7-M. +ifndef CONFIG_CPU_V7M +#extra-$(CONFIG_CMD_BOOTEFI_SELFTEST) += $(EFI_CRT0) $(EFI_RELOC) +endif extra-$(CONFIG_EFI) += $(EFI_CRT0) $(EFI_RELOC) diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile index 743b4820449..5b804692aac 100644 --- a/lib/efi_selftest/Makefile +++ b/lib/efi_selftest/Makefile @@ -45,9 +45,9 @@ ifeq ($(CONFIG_BLK)$(CONFIG_PARTITIONS),yy) obj-y += efi_selftest_block_device.o endif -# TODO: As of v2018.01 the relocation code for the EFI application cannot -# be built on x86_64. -ifeq ($(CONFIG_X86_64)$(CONFIG_SANDBOX),) +# TODO: As of v2019.01 the relocation code for the EFI application cannot +# be built on ARMv7-M, Sandbox, and x86_64. +ifeq ($(CONFIG_SANDBOX)$(CONFIG_CPU_V7M)$(CONFIG_X86_64),) obj-y += \ efi_selftest_startimage_exit.o \ -- cgit v1.2.3 From 4f3cb4d578f6848b0c00d3badbe69e1da805760b Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 30 Dec 2018 12:54:36 +0100 Subject: doc: README.uefi: fix typos %s/specfication/specification/ %s/selftest/self-test/ %s/little endian/little-endian/ Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- doc/README.uefi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/README.uefi b/doc/README.uefi index 6b9759cfede..0982fad92e9 100644 --- a/doc/README.uefi +++ b/doc/README.uefi @@ -14,7 +14,7 @@ and boot loaders like GRUB or the FreeBSD loader can be executed. ## Building for UEFI -The UEFI standard supports only little endian systems. The UEFI support can be +The UEFI standard supports only little-endian systems. The UEFI support can be activated for ARM and x86 by specifying CONFIG_CMD_BOOTEFI=y @@ -53,7 +53,7 @@ arguments. ### Executing the boot manager -The UEFI specfication foresees to define boot entries and boot sequence via UEFI +The UEFI specification foresees to define boot entries and boot sequence via UEFI variables. Booting according to these variables is possible via bootefi bootmgr [fdt address] @@ -90,14 +90,14 @@ Below you find the output of an example session. The environment variable fdtcontroladdr points to U-Boot's internal device tree (if available). -### Executing the built-in selftest +### Executing the built-in self-test -An UEFI selftest suite can be embedded in U-Boot by building with +An UEFI self-test suite can be embedded in U-Boot by building with CONFIG_CMD_BOOTEFI_SELFTEST=y For testing the UEFI implementation the bootefi command can be used to start the -selftest. +self-test. bootefi selftest [fdt address] -- cgit v1.2.3 From 056b45bc50c11a57363b7b958297f13506a2508b Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Sun, 30 Dec 2018 15:16:55 +0100 Subject: efi_loader: move efi_init_obj_list() to a new efi_setup.c The function, efi_init_obj_list(), can be shared in different pseudo efi applications, like bootefi/bootmgr as well as my efishell. Moreover, it will be utilized to extend efi initialization, for example, my "removable disk support" patch and "capsule-on-disk support" patch in the future. So with this patch, it will be moved to a new file, efi_setup.c, under lib/efi_loader and exported, making no changes in functionality. Signed-off-by: AKASHI Takahiro Remove lines deactivated by #if 1 #else Reviewed-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- cmd/bootefi.c | 77 ----------------------------------------- include/efi_loader.h | 2 ++ lib/efi_loader/Makefile | 1 + lib/efi_loader/efi_setup.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 89 insertions(+), 77 deletions(-) create mode 100644 lib/efi_loader/efi_setup.c diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 7ab08382faf..bcdd29ebed0 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -28,86 +28,9 @@ DECLARE_GLOBAL_DATA_PTR; -#define OBJ_LIST_NOT_INITIALIZED 1 - -static efi_status_t efi_obj_list_initialized = OBJ_LIST_NOT_INITIALIZED; - static struct efi_device_path *bootefi_image_path; static struct efi_device_path *bootefi_device_path; -/* Initialize and populate EFI object list */ -efi_status_t efi_init_obj_list(void) -{ - efi_status_t ret = EFI_SUCCESS; - - /* - * On the ARM architecture gd is mapped to a fixed register (r9 or x18). - * As this register may be overwritten by an EFI payload we save it here - * and restore it on every callback entered. - */ - efi_save_gd(); - - /* Initialize once only */ - if (efi_obj_list_initialized != OBJ_LIST_NOT_INITIALIZED) - return efi_obj_list_initialized; - - /* Initialize system table */ - ret = efi_initialize_system_table(); - if (ret != EFI_SUCCESS) - goto out; - - /* Initialize root node */ - ret = efi_root_node_register(); - if (ret != EFI_SUCCESS) - goto out; - - /* Initialize EFI driver uclass */ - ret = efi_driver_init(); - if (ret != EFI_SUCCESS) - goto out; - - ret = efi_console_register(); - if (ret != EFI_SUCCESS) - goto out; -#ifdef CONFIG_PARTITIONS - ret = efi_disk_register(); - if (ret != EFI_SUCCESS) - goto out; -#endif -#if defined(CONFIG_LCD) || defined(CONFIG_DM_VIDEO) - ret = efi_gop_register(); - if (ret != EFI_SUCCESS) - goto out; -#endif -#ifdef CONFIG_NET - ret = efi_net_register(); - if (ret != EFI_SUCCESS) - goto out; -#endif -#ifdef CONFIG_GENERATE_ACPI_TABLE - ret = efi_acpi_register(); - if (ret != EFI_SUCCESS) - goto out; -#endif -#ifdef CONFIG_GENERATE_SMBIOS_TABLE - ret = efi_smbios_register(); - if (ret != EFI_SUCCESS) - goto out; -#endif - ret = efi_watchdog_register(); - if (ret != EFI_SUCCESS) - goto out; - - /* Initialize EFI runtime services */ - ret = efi_reset_system_init(); - if (ret != EFI_SUCCESS) - goto out; - -out: - efi_obj_list_initialized = ret; - return ret; -} - /* * Allow unaligned memory access. * diff --git a/include/efi_loader.h b/include/efi_loader.h index 53f08161ab6..6323686f9d3 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -244,6 +244,8 @@ extern struct list_head efi_obj_list; /* List of all events */ extern struct list_head efi_events; +/* Initialize efi execution environment */ +efi_status_t efi_init_obj_list(void); /* Called by bootefi to initialize root node */ efi_status_t efi_root_node_register(void); /* Called by bootefi to initialize runtime */ diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index 6703435947f..a7bba58d412 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -28,6 +28,7 @@ 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-y += efi_variable.o obj-y += efi_watchdog.o diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c new file mode 100644 index 00000000000..8266d06c2ef --- /dev/null +++ b/lib/efi_loader/efi_setup.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * EFI setup code + * + * Copyright (c) 2016-2018 Alexander Graf et al. + */ + +#include +#include + +#define OBJ_LIST_NOT_INITIALIZED 1 + +static efi_status_t efi_obj_list_initialized = OBJ_LIST_NOT_INITIALIZED; + +/* Initialize and populate EFI object list */ +efi_status_t efi_init_obj_list(void) +{ + efi_status_t ret = EFI_SUCCESS; + + /* + * On the ARM architecture gd is mapped to a fixed register (r9 or x18). + * As this register may be overwritten by an EFI payload we save it here + * and restore it on every callback entered. + */ + efi_save_gd(); + + /* Initialize once only */ + if (efi_obj_list_initialized != OBJ_LIST_NOT_INITIALIZED) + return efi_obj_list_initialized; + + /* Initialize system table */ + ret = efi_initialize_system_table(); + if (ret != EFI_SUCCESS) + goto out; + + /* Initialize root node */ + ret = efi_root_node_register(); + if (ret != EFI_SUCCESS) + goto out; + + /* Initialize EFI driver uclass */ + ret = efi_driver_init(); + if (ret != EFI_SUCCESS) + goto out; + + ret = efi_console_register(); + if (ret != EFI_SUCCESS) + goto out; +#ifdef CONFIG_PARTITIONS + ret = efi_disk_register(); + if (ret != EFI_SUCCESS) + goto out; +#endif +#if defined(CONFIG_LCD) || defined(CONFIG_DM_VIDEO) + ret = efi_gop_register(); + if (ret != EFI_SUCCESS) + goto out; +#endif +#ifdef CONFIG_NET + ret = efi_net_register(); + if (ret != EFI_SUCCESS) + goto out; +#endif +#ifdef CONFIG_GENERATE_ACPI_TABLE + ret = efi_acpi_register(); + if (ret != EFI_SUCCESS) + goto out; +#endif +#ifdef CONFIG_GENERATE_SMBIOS_TABLE + ret = efi_smbios_register(); + if (ret != EFI_SUCCESS) + goto out; +#endif + ret = efi_watchdog_register(); + if (ret != EFI_SUCCESS) + goto out; + + /* Initialize EFI runtime services */ + ret = efi_reset_system_init(); + if (ret != EFI_SUCCESS) + goto out; + +out: + efi_obj_list_initialized = ret; + return ret; +} -- cgit v1.2.3 From 0bda81bfdc5c67341e51c2b412a2271099861e6e Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 30 Dec 2018 20:53:51 +0100 Subject: efi_loader: use const efi_guid_t * for variable services The runtime variable services never change GUIDs. So we should declare the GUID parameters as constant. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- include/efi_api.h | 8 +++++--- include/efi_loader.h | 14 +++++++------- lib/efi_loader/efi_variable.c | 16 ++++++++-------- lib/efi_selftest/efi_selftest_variables.c | 4 ++-- 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/include/efi_api.h b/include/efi_api.h index 4389dbeddcb..83fd12b685d 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -221,13 +221,15 @@ struct efi_runtime_services { struct efi_mem_desc *virtmap); efi_status_t (*convert_pointer)(unsigned long dbg, void **address); efi_status_t (EFIAPI *get_variable)(u16 *variable_name, - efi_guid_t *vendor, u32 *attributes, + const efi_guid_t *vendor, + u32 *attributes, efi_uintn_t *data_size, void *data); efi_status_t (EFIAPI *get_next_variable_name)( efi_uintn_t *variable_name_size, - u16 *variable_name, efi_guid_t *vendor); + u16 *variable_name, const efi_guid_t *vendor); efi_status_t (EFIAPI *set_variable)(u16 *variable_name, - efi_guid_t *vendor, u32 attributes, + const efi_guid_t *vendor, + u32 attributes, efi_uintn_t data_size, void *data); efi_status_t (EFIAPI *get_next_high_mono_count)( uint32_t *high_count); diff --git a/include/efi_loader.h b/include/efi_loader.h index 6323686f9d3..5420c99e0c3 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -510,15 +510,15 @@ efi_status_t EFIAPI efi_selftest(efi_handle_t image_handle, struct efi_system_table *systab); #endif -efi_status_t EFIAPI efi_get_variable(u16 *variable_name, efi_guid_t *vendor, - u32 *attributes, efi_uintn_t *data_size, - void *data); +efi_status_t EFIAPI efi_get_variable(u16 *variable_name, + const efi_guid_t *vendor, u32 *attributes, + efi_uintn_t *data_size, void *data); efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size, u16 *variable_name, - efi_guid_t *vendor); -efi_status_t EFIAPI efi_set_variable(u16 *variable_name, efi_guid_t *vendor, - u32 attributes, efi_uintn_t data_size, - void *data); + const efi_guid_t *vendor); +efi_status_t EFIAPI efi_set_variable(u16 *variable_name, + const efi_guid_t *vendor, u32 attributes, + efi_uintn_t data_size, void *data); /* * See section 3.1.3 in the v2.7 UEFI spec for more details on diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index 19d9cb865f2..4e6a04e6145 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -99,7 +99,7 @@ static char *mem2hex(char *hexstr, const u8 *mem, int count) } static efi_status_t efi_to_native(char **native, const u16 *variable_name, - efi_guid_t *vendor) + const efi_guid_t *vendor) { size_t len; char *pos; @@ -163,9 +163,9 @@ static const char *parse_attr(const char *str, u32 *attrp) } /* http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#GetVariable.28.29 */ -efi_status_t EFIAPI efi_get_variable(u16 *variable_name, efi_guid_t *vendor, - u32 *attributes, efi_uintn_t *data_size, - void *data) +efi_status_t EFIAPI efi_get_variable(u16 *variable_name, + const efi_guid_t *vendor, u32 *attributes, + efi_uintn_t *data_size, void *data) { char *native_name; efi_status_t ret; @@ -244,7 +244,7 @@ efi_status_t EFIAPI efi_get_variable(u16 *variable_name, efi_guid_t *vendor, /* http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#GetNextVariableName.28.29 */ efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size, u16 *variable_name, - efi_guid_t *vendor) + const efi_guid_t *vendor) { EFI_ENTRY("%p \"%ls\" %pUl", variable_name_size, variable_name, vendor); @@ -252,9 +252,9 @@ efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size, } /* http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#SetVariable.28.29 */ -efi_status_t EFIAPI efi_set_variable(u16 *variable_name, efi_guid_t *vendor, - u32 attributes, efi_uintn_t data_size, - void *data) +efi_status_t EFIAPI efi_set_variable(u16 *variable_name, + const efi_guid_t *vendor, u32 attributes, + efi_uintn_t data_size, void *data) { char *native_name = NULL, *val = NULL, *s; efi_status_t ret = EFI_SUCCESS; diff --git a/lib/efi_selftest/efi_selftest_variables.c b/lib/efi_selftest/efi_selftest_variables.c index e4c389a872f..ffc8cad3295 100644 --- a/lib/efi_selftest/efi_selftest_variables.c +++ b/lib/efi_selftest/efi_selftest_variables.c @@ -15,10 +15,10 @@ static struct efi_boot_services *boottime; static struct efi_runtime_services *runtime; -static efi_guid_t guid_vendor0 = +static const efi_guid_t guid_vendor0 = EFI_GUID(0x67029eb5, 0x0af2, 0xf6b1, 0xda, 0x53, 0xfc, 0xb5, 0x66, 0xdd, 0x1c, 0xe6); -static efi_guid_t guid_vendor1 = +static const efi_guid_t guid_vendor1 = EFI_GUID(0xff629290, 0x1fc1, 0xd73f, 0x8f, 0xb1, 0x32, 0xf9, 0x0c, 0xa0, 0x42, 0xea); -- cgit v1.2.3 From 452257a34a2e8d06af37ad30c7dd742920ff6dc5 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 30 Dec 2018 21:03:15 +0100 Subject: efi_loader: efi_set_variable use const void * The SetVariable() runtime service does not change the data passed to it. So mark the parameter as constant. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- include/efi_api.h | 3 ++- include/efi_loader.h | 2 +- lib/efi_loader/efi_variable.c | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/efi_api.h b/include/efi_api.h index 83fd12b685d..1d3774729de 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -230,7 +230,8 @@ struct efi_runtime_services { efi_status_t (EFIAPI *set_variable)(u16 *variable_name, const efi_guid_t *vendor, u32 attributes, - efi_uintn_t data_size, void *data); + efi_uintn_t data_size, + const void *data); efi_status_t (EFIAPI *get_next_high_mono_count)( uint32_t *high_count); void (EFIAPI *reset_system)(enum efi_reset_type reset_type, diff --git a/include/efi_loader.h b/include/efi_loader.h index 5420c99e0c3..b44678169aa 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -518,7 +518,7 @@ efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size, const efi_guid_t *vendor); efi_status_t EFIAPI efi_set_variable(u16 *variable_name, const efi_guid_t *vendor, u32 attributes, - efi_uintn_t data_size, void *data); + efi_uintn_t data_size, const void *data); /* * See section 3.1.3 in the v2.7 UEFI spec for more details on diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index 4e6a04e6145..c302dbd2fe0 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -254,7 +254,7 @@ efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size, /* http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#SetVariable.28.29 */ efi_status_t EFIAPI efi_set_variable(u16 *variable_name, const efi_guid_t *vendor, u32 attributes, - efi_uintn_t data_size, void *data) + efi_uintn_t data_size, const void *data) { char *native_name = NULL, *val = NULL, *s; efi_status_t ret = EFI_SUCCESS; -- cgit v1.2.3 From 8a42641a3e1c24709ad36d34119c59d19dd2a0eb Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 5 Jan 2019 23:50:41 +0100 Subject: efi_selftest: SNP unit test on sandbox Running the simple network protocol test on the sandbox requires setting the environment variable ethact to a network interface connected to a DHCP server and ethrotate to 'no'. So let's make it an on-request test on the sandbox (selectable by setting environment variable efi_selftest). Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_selftest/efi_selftest_snp.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/efi_selftest/efi_selftest_snp.c b/lib/efi_selftest/efi_selftest_snp.c index e10a34ba645..f1e23c4921c 100644 --- a/lib/efi_selftest/efi_selftest_snp.c +++ b/lib/efi_selftest/efi_selftest_snp.c @@ -427,4 +427,12 @@ EFI_UNIT_TEST(snp) = { .setup = setup, .execute = execute, .teardown = teardown, +#ifdef CONFIG_SANDBOX + /* + * Running this test on the sandbox requires setting environment + * variable ethact to a network interface connected to a DHCP server and + * ethrotate to 'no'. + */ + .on_request = true, +#endif }; -- cgit v1.2.3 From 1309a159ceb6c423db53f79cb4c5b8a69dc47f36 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 6 Jan 2019 16:38:57 +0100 Subject: efi_selftest: events unit test, check return values For some API calls checks for the return values are missing. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_selftest/efi_selftest_events.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/efi_selftest/efi_selftest_events.c b/lib/efi_selftest/efi_selftest_events.c index ed99a538045..1077cbdf9e6 100644 --- a/lib/efi_selftest/efi_selftest_events.c +++ b/lib/efi_selftest/efi_selftest_events.c @@ -147,20 +147,20 @@ static int execute(void) return EFI_ST_FAILURE; } ret = boottime->set_timer(event_notify, EFI_TIMER_STOP, 0); - if (index != 0) { + if (ret != EFI_SUCCESS) { efi_st_error("Could not cancel timer\n"); return EFI_ST_FAILURE; } /* Set 10 ms timer */ timer_ticks = 0; ret = boottime->set_timer(event_notify, EFI_TIMER_RELATIVE, 100000); - if (index != 0) { + if (ret != EFI_SUCCESS) { efi_st_error("Could not set timer\n"); return EFI_ST_FAILURE; } /* Set 100 ms timer */ ret = boottime->set_timer(event_wait, EFI_TIMER_PERIODIC, 1000000); - if (index != 0) { + if (ret != EFI_SUCCESS) { efi_st_error("Could not set timer\n"); return EFI_ST_FAILURE; } -- cgit v1.2.3 From 44e7c62a826b8df34ea5f1f040cceb2455559295 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 6 Jan 2019 16:44:16 +0100 Subject: efi_selftest: tpl unit test, check return values For some API calls checks for the return values are missing. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_selftest/efi_selftest_tpl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/efi_selftest/efi_selftest_tpl.c b/lib/efi_selftest/efi_selftest_tpl.c index 97d256abe4f..70a355eae6b 100644 --- a/lib/efi_selftest/efi_selftest_tpl.c +++ b/lib/efi_selftest/efi_selftest_tpl.c @@ -151,7 +151,7 @@ static int execute(void) return EFI_ST_FAILURE; } ret = boottime->set_timer(event_notify, EFI_TIMER_STOP, 0); - if (index != 0) { + if (ret != EFI_SUCCESS) { efi_st_error("Could not cancel timer\n"); return EFI_ST_FAILURE; } @@ -164,7 +164,7 @@ static int execute(void) /* Set 10 ms timer */ notification_count = 0; ret = boottime->set_timer(event_notify, EFI_TIMER_PERIODIC, 100000); - if (index != 0) { + if (ret != EFI_SUCCESS) { efi_st_error("Could not set timer\n"); return EFI_ST_FAILURE; } -- cgit v1.2.3 From b4f471f18e68b340e5b968e2d611b83f709a78ce Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 6 Jan 2019 17:12:43 +0100 Subject: efi_driver: simplify error message Stating the function module is sufficient. We don't need file and line number. Anyway the format code for the line number was incorrect (should be %d). Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_driver/efi_uclass.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/efi_driver/efi_uclass.c b/lib/efi_driver/efi_uclass.c index bb86ffd399c..7cdf81f40c1 100644 --- a/lib/efi_driver/efi_uclass.c +++ b/lib/efi_driver/efi_uclass.c @@ -233,8 +233,7 @@ static efi_status_t EFIAPI efi_uc_stop( } ret = EFI_CALL(systab.boottime->free_pool(entry_buffer)); if (ret != EFI_SUCCESS) - printf("%s(%u) %s: ERROR: Cannot free pool\n", - __FILE__, __LINE__, __func__); + printf("%s: ERROR: Cannot free pool\n", __func__); /* Detach driver from controller */ ret = EFI_CALL(systab.boottime->close_protocol( -- cgit v1.2.3 From f6c6df7ebc12fdaab252c5869732cef6fa48d864 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Tue, 8 Jan 2019 18:13:06 +0100 Subject: efi_loader: refactor switch to non-secure mode Refactor the switch from supervisor to hypervisor to a new function called at the beginning of do_bootefi(). Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- arch/arm/cpu/armv7/Makefile | 1 + arch/arm/cpu/armv7/exception_level.c | 56 ++++++++++++++++++++++++++++ arch/arm/cpu/armv8/Makefile | 1 + arch/arm/cpu/armv8/exception_level.c | 55 ++++++++++++++++++++++++++++ cmd/bootefi.c | 71 ++---------------------------------- common/bootm.c | 10 +++++ include/bootm.h | 5 +++ 7 files changed, 132 insertions(+), 67 deletions(-) create mode 100644 arch/arm/cpu/armv7/exception_level.c create mode 100644 arch/arm/cpu/armv8/exception_level.c diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile index 4f4647c90ac..8c955d0d528 100644 --- a/arch/arm/cpu/armv7/Makefile +++ b/arch/arm/cpu/armv7/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_SYS_ARM_MPU) += mpu_v7r.o ifneq ($(CONFIG_SPL_BUILD),y) obj-$(CONFIG_EFI_LOADER) += sctlr.o +obj-$(CONFIG_ARMV7_NONSEC) += exception_level.o endif ifneq ($(CONFIG_SKIP_LOWLEVEL_INIT),y) diff --git a/arch/arm/cpu/armv7/exception_level.c b/arch/arm/cpu/armv7/exception_level.c new file mode 100644 index 00000000000..274f03d8bbb --- /dev/null +++ b/arch/arm/cpu/armv7/exception_level.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Switch to non-secure mode + * + * Copyright (c) 2018 Heinrich Schuchardt + * + * This module contains the ARMv7 specific code required for leaving the + * secure mode before booting an operating system. + */ + +#include +#include +#include +#include +#include + +/** + * entry_non_secure() - entry point when switching to non-secure mode + * + * When switching to non-secure mode switch_to_non_secure_mode() calls this + * function passing a jump buffer. We use this jump buffer to restore the + * original stack and register state. + * + * @non_secure_jmp: jump buffer for restoring stack and registers + */ +static void entry_non_secure(struct jmp_buf_data *non_secure_jmp) +{ + dcache_enable(); + debug("Reached non-secure mode\n"); + + /* Restore stack and registers saved in switch_to_non_secure_mode() */ + longjmp(non_secure_jmp, 1); +} + +/** + * switch_to_non_secure_mode() - switch to non-secure mode + * + * Operating systems may expect to run in non-secure mode. Here we check if + * we are running in secure mode and switch to non-secure mode if necessary. + */ +void switch_to_non_secure_mode(void) +{ + static bool is_nonsec; + struct jmp_buf_data non_secure_jmp; + + if (armv7_boot_nonsec() && !is_nonsec) { + if (setjmp(&non_secure_jmp)) + return; + dcache_disable(); /* flush cache before switch to HYP */ + armv7_init_nonsec(); + is_nonsec = true; + secure_ram_addr(_do_nonsec_entry)(entry_non_secure, + (uintptr_t)&non_secure_jmp, + 0, 0); + } +} diff --git a/arch/arm/cpu/armv8/Makefile b/arch/arm/cpu/armv8/Makefile index 4c4b13c9e75..a5f54330e38 100644 --- a/arch/arm/cpu/armv8/Makefile +++ b/arch/arm/cpu/armv8/Makefile @@ -14,6 +14,7 @@ ifdef CONFIG_SPL_BUILD obj-$(CONFIG_ARMV8_SPL_EXCEPTION_VECTORS) += exceptions.o else obj-y += exceptions.o +obj-y += exception_level.o endif obj-y += cache.o obj-y += tlb.o diff --git a/arch/arm/cpu/armv8/exception_level.c b/arch/arm/cpu/armv8/exception_level.c new file mode 100644 index 00000000000..57824eb2ac8 --- /dev/null +++ b/arch/arm/cpu/armv8/exception_level.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Switch to non-secure mode + * + * Copyright (c) 2018 Heinrich Schuchardt + * + * This module contains the ARMv8 specific code required to adjust the exception + * level before booting an operating system. + */ + +#include +#include +#include + +/** + * entry_non_secure() - entry point when switching to non-secure mode + * + * When switching to non-secure mode switch_to_non_secure_mode() calls this + * function passing a jump buffer. We use this jump buffer to restore the + * original stack and register state. + * + * @non_secure_jmp: jump buffer for restoring stack and registers + */ +static void entry_non_secure(struct jmp_buf_data *non_secure_jmp) +{ + dcache_enable(); + debug("Reached non-secure mode\n"); + + /* Restore stack and registers saved in switch_to_non_secure_mode() */ + longjmp(non_secure_jmp, 1); +} + +/** + * switch_to_non_secure_mode() - switch to non-secure mode + * + * Exception level EL3 is meant to be used by the secure monitor only (ARM + * trusted firmware being one embodiment). The operating system shall be + * started at exception level EL2. So here we check the exception level + * and switch it if necessary. + */ +void switch_to_non_secure_mode(void) +{ + struct jmp_buf_data non_secure_jmp; + + /* On AArch64 we need to make sure we call our payload in < EL3 */ + if (current_el() == 3) { + if (setjmp(&non_secure_jmp)) + return; + dcache_disable(); /* flush cache before switch to EL2 */ + + /* Move into EL2 and keep running there */ + armv8_switch_to_el2((uintptr_t)&non_secure_jmp, 0, 0, 0, + (uintptr_t)entry_non_secure, ES_TO_AARCH64); + } +} diff --git a/cmd/bootefi.c b/cmd/bootefi.c index bcdd29ebed0..ee685d8644e 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -5,8 +5,9 @@ * Copyright (c) 2016 Alexander Graf */ -#include #include +#include +#include #include #include #include @@ -21,11 +22,6 @@ #include #include -#ifdef CONFIG_ARMV7_NONSEC -#include -#include -#endif - DECLARE_GLOBAL_DATA_PTR; static struct efi_device_path *bootefi_image_path; @@ -151,34 +147,6 @@ static efi_status_t efi_do_enter( return ret; } -#ifdef CONFIG_ARM64 -static efi_status_t efi_run_in_el2(EFIAPI efi_status_t (*entry)( - efi_handle_t image_handle, struct efi_system_table *st), - efi_handle_t image_handle, struct efi_system_table *st) -{ - /* Enable caches again */ - dcache_enable(); - - return efi_do_enter(image_handle, st, entry); -} -#endif - -#ifdef CONFIG_ARMV7_NONSEC -static bool is_nonsec; - -static efi_status_t efi_run_in_hyp(EFIAPI efi_status_t (*entry)( - efi_handle_t image_handle, struct efi_system_table *st), - efi_handle_t image_handle, struct efi_system_table *st) -{ - /* Enable caches again */ - dcache_enable(); - - is_nonsec = true; - - return efi_do_enter(image_handle, st, entry); -} -#endif - /* * efi_carve_out_dt_rsv() - Carve out DT reserved memory ranges * @@ -358,39 +326,6 @@ static efi_status_t do_bootefi_exec(void *efi, goto err_prepare; } -#ifdef CONFIG_ARM64 - /* On AArch64 we need to make sure we call our payload in < EL3 */ - if (current_el() == 3) { - smp_kick_all_cpus(); - dcache_disable(); /* flush cache before switch to EL2 */ - - /* Move into EL2 and keep running there */ - armv8_switch_to_el2((ulong)entry, - (ulong)&image_obj->header, - (ulong)&systab, 0, (ulong)efi_run_in_el2, - ES_TO_AARCH64); - - /* Should never reach here, efi exits with longjmp */ - while (1) { } - } -#endif - -#ifdef CONFIG_ARMV7_NONSEC - if (armv7_boot_nonsec() && !is_nonsec) { - dcache_disable(); /* flush cache before switch to HYP */ - - armv7_init_nonsec(); - secure_ram_addr(_do_nonsec_entry)( - efi_run_in_hyp, - (uintptr_t)entry, - (uintptr_t)&image_obj->header, - (uintptr_t)&systab); - - /* Should never reach here, efi exits with longjmp */ - while (1) { } - } -#endif - ret = efi_do_enter(&image_obj->header, &systab, entry); err_prepare: @@ -476,6 +411,8 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) /* Allow unaligned memory access */ allow_unaligned(); + switch_to_non_secure_mode(); + /* Initialize EFI drivers */ r = efi_init_obj_list(); if (r != EFI_SUCCESS) { diff --git a/common/bootm.c b/common/bootm.c index 7c7505f0920..3adbceaa38e 100644 --- a/common/bootm.c +++ b/common/bootm.c @@ -912,6 +912,16 @@ static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, return buf; } + +/** + * switch_to_non_secure_mode() - switch to non-secure mode + * + * This routine is overridden by architectures requiring this feature. + */ +void __weak switch_to_non_secure_mode(void) +{ +} + #else /* USE_HOSTCC */ void memmove_wd(void *to, void *from, size_t len, ulong chunksz) diff --git a/include/bootm.h b/include/bootm.h index dbd6f49c2df..e2cc6d4b99a 100644 --- a/include/bootm.h +++ b/include/bootm.h @@ -82,4 +82,9 @@ int bootm_decomp_image(int comp, ulong load, ulong image_start, int type, */ void board_quiesce_devices(void); +/** + * switch_to_non_secure_mode() - switch to non-secure mode + */ +void switch_to_non_secure_mode(void); + #endif -- cgit v1.2.3 From 0bc81a717d1ce90008f9f8ae8b3c086d4405a295 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 9 Jan 2019 21:41:13 +0100 Subject: efi_loader: fix CopyMem() CopyMem() must support overlapping buffers. So replace memcpy() by memmove(). Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/efi_boottime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 88386ff6760..dbf0d56c1d3 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -2483,7 +2483,7 @@ static void EFIAPI efi_copy_mem(void *destination, const void *source, size_t length) { EFI_ENTRY("%p, %p, %ld", destination, source, (unsigned long)length); - memcpy(destination, source, length); + memmove(destination, source, length); EFI_EXIT(EFI_SUCCESS); } -- cgit v1.2.3 From c82f8f600a34d540f95a04e9cb3c49a9e6b3ae83 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 12 Jan 2019 12:02:33 +0100 Subject: efi_loader: use u16* for file name UTF-16 strings in our code should all be u16 *. Fix an inconsistency for file names which may lead to a warning for printf("%ls", ). Reviewed-by: Simon Glass Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- include/efi_api.h | 2 +- lib/efi_loader/efi_file.c | 14 +++++++------- lib/efi_selftest/efi_selftest_block_device.c | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/efi_api.h b/include/efi_api.h index 1d3774729de..d899af5e487 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -909,7 +909,7 @@ struct efi_file_handle { u64 rev; efi_status_t (EFIAPI *open)(struct efi_file_handle *file, struct efi_file_handle **new_handle, - s16 *file_name, u64 open_mode, u64 attributes); + u16 *file_name, u64 open_mode, u64 attributes); efi_status_t (EFIAPI *close)(struct efi_file_handle *file); efi_status_t (EFIAPI *delete)(struct efi_file_handle *file); efi_status_t (EFIAPI *read)(struct efi_file_handle *file, diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c index 8a4f3a9f408..9d709a8db02 100644 --- a/lib/efi_loader/efi_file.c +++ b/lib/efi_loader/efi_file.c @@ -148,7 +148,7 @@ static int sanitize_path(char *path) * Returns: handle to the opened file or NULL */ static struct efi_file_handle *file_open(struct file_system *fs, - struct file_handle *parent, s16 *file_name, u64 mode, + struct file_handle *parent, u16 *file_name, u64 mode, u64 attributes) { struct file_handle *fh; @@ -157,8 +157,8 @@ static struct efi_file_handle *file_open(struct file_system *fs, int flen = 0; if (file_name) { - utf16_to_utf8((u8 *)f0, (u16 *)file_name, 1); - flen = u16_strlen((u16 *)file_name); + utf16_to_utf8((u8 *)f0, file_name, 1); + flen = u16_strlen(file_name); } /* we could have a parent, but also an absolute path: */ @@ -183,7 +183,7 @@ static struct efi_file_handle *file_open(struct file_system *fs, *p++ = '/'; } - utf16_to_utf8((u8 *)p, (u16 *)file_name, flen); + utf16_to_utf8((u8 *)p, file_name, flen); if (sanitize_path(fh->path)) goto error; @@ -216,7 +216,7 @@ error: static efi_status_t EFIAPI efi_file_open(struct efi_file_handle *file, struct efi_file_handle **new_handle, - s16 *file_name, u64 open_mode, u64 attributes) + u16 *file_name, u64 open_mode, u64 attributes) { struct file_handle *fh = to_fh(file); efi_status_t ret; @@ -375,7 +375,7 @@ static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size, if (dent->type == FS_DT_DIR) info->attribute |= EFI_FILE_DIRECTORY; - ascii2unicode((u16 *)info->file_name, dent->name); + ascii2unicode(info->file_name, dent->name); fh->offset++; @@ -666,7 +666,7 @@ struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp) return NULL; } - EFI_CALL(ret = f->open(f, &f2, (s16 *)fdp->str, + EFI_CALL(ret = f->open(f, &f2, fdp->str, EFI_FILE_MODE_READ, 0)); if (ret != EFI_SUCCESS) return NULL; diff --git a/lib/efi_selftest/efi_selftest_block_device.c b/lib/efi_selftest/efi_selftest_block_device.c index f038da9f190..1cdd8307f4f 100644 --- a/lib/efi_selftest/efi_selftest_block_device.c +++ b/lib/efi_selftest/efi_selftest_block_device.c @@ -387,7 +387,7 @@ static int execute(void) } /* Read file */ - ret = root->open(root, &file, (s16 *)L"hello.txt", EFI_FILE_MODE_READ, + ret = root->open(root, &file, L"hello.txt", EFI_FILE_MODE_READ, 0); if (ret != EFI_SUCCESS) { efi_st_error("Failed to open file\n"); @@ -431,7 +431,7 @@ static int execute(void) #ifdef CONFIG_FAT_WRITE /* Write file */ - ret = root->open(root, &file, (s16 *)L"u-boot.txt", EFI_FILE_MODE_READ | + ret = root->open(root, &file, 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"); @@ -463,7 +463,7 @@ static int execute(void) /* Verify file */ boottime->set_mem(buf, sizeof(buf), 0); - ret = root->open(root, &file, (s16 *)L"u-boot.txt", EFI_FILE_MODE_READ, + ret = root->open(root, &file, L"u-boot.txt", EFI_FILE_MODE_READ, 0); if (ret != EFI_SUCCESS) { efi_st_error("Failed to open file\n"); -- cgit v1.2.3 From 0e3dc01eb7692e2f1ff8831a89d298dc8588e937 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 12 Jan 2019 15:32:06 +0100 Subject: efi_loader: consistent build flags for EFI applications At the same time adding and removing the -Os flag does not make any sense. Actually it leads to -Os not being used. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/Makefile | 2 +- lib/efi_selftest/Makefile | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index a7bba58d412..e2e6da3ea4c 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -10,7 +10,7 @@ CFLAGS_efi_boottime.o += \ -DFW_VERSION="0x$(VERSION)" \ -DFW_PATCHLEVEL="0x$(PATCHLEVEL)" CFLAGS_helloworld.o := $(CFLAGS_EFI) -Os -ffreestanding -CFLAGS_REMOVE_helloworld.o := $(CFLAGS_NON_EFI) -Os +CFLAGS_REMOVE_helloworld.o := $(CFLAGS_NON_EFI) ifneq ($(CONFIG_CMD_BOOTEFI_HELLO_COMPILE),) always += helloworld.efi diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile index 5b804692aac..b3d3dadf597 100644 --- a/lib/efi_selftest/Makefile +++ b/lib/efi_selftest/Makefile @@ -6,9 +6,9 @@ # object inclusion implicitly depends on it CFLAGS_efi_selftest_miniapp_exit.o := $(CFLAGS_EFI) -Os -ffreestanding -CFLAGS_REMOVE_efi_selftest_miniapp_exit.o := $(CFLAGS_NON_EFI) -Os +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) -Os +CFLAGS_REMOVE_efi_selftest_miniapp_return.o := $(CFLAGS_NON_EFI) obj-y += \ efi_selftest.o \ -- cgit v1.2.3 From bc867951a25737b9599591bd1dd09352ef7791df Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Tue, 15 Jan 2019 05:44:56 +0100 Subject: efi_loader: remove duplicate GUID definition Remove duplicate definition o EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- include/efi_api.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/efi_api.h b/include/efi_api.h index d899af5e487..6af52bcb866 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -929,9 +929,6 @@ struct efi_file_handle { efi_status_t (EFIAPI *flush)(struct efi_file_handle *file); }; -#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID \ - EFI_GUID(0x964e5b22, 0x6459, 0x11d2, \ - 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b) #define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION 0x00010000 struct efi_simple_file_system_protocol { -- cgit v1.2.3 From 6e37fa2293a344ab20f79498ac097fb8f12a1183 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 18 Jan 2019 12:31:54 +0100 Subject: efi_loader: eliminate duplicate function hex2mem() Use existing inline function hex2bin() instead of defining a new one. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/efi_variable.c | 44 +++---------------------------------------- 1 file changed, 3 insertions(+), 41 deletions(-) diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index c302dbd2fe0..eea7f68b857 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -8,6 +8,7 @@ #include #include #include +#include #define READ_ONLY BIT(31) @@ -46,45 +47,6 @@ #define PREFIX_LEN (strlen("efi_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx_")) -static int hex(int ch) -{ - if (ch >= 'a' && ch <= 'f') - return ch-'a'+10; - if (ch >= '0' && ch <= '9') - return ch-'0'; - if (ch >= 'A' && ch <= 'F') - return ch-'A'+10; - return -1; -} - -static int hex2mem(u8 *mem, const char *hexstr, int size) -{ - int nibble; - int i; - - for (i = 0; i < size; i++) { - if (*hexstr == '\0') - break; - - nibble = hex(*hexstr); - if (nibble < 0) - return -1; - - *mem = nibble; - hexstr++; - - nibble = hex(*hexstr); - if (nibble < 0) - return -1; - - *mem = (*mem << 4) | nibble; - hexstr++; - mem++; - } - - return i; -} - static char *mem2hex(char *hexstr, const u8 *mem, int count) { static const char hexchars[] = "0123456789abcdef"; @@ -195,7 +157,7 @@ efi_status_t EFIAPI efi_get_variable(u16 *variable_name, in_size = *data_size; if ((s = prefix(val, "(blob)"))) { - unsigned len = strlen(s); + size_t len = strlen(s); /* number of hexadecimal digits must be even */ if (len & 1) @@ -211,7 +173,7 @@ efi_status_t EFIAPI efi_get_variable(u16 *variable_name, if (!data) return EFI_EXIT(EFI_INVALID_PARAMETER); - if (hex2mem(data, s, len) != len) + if (hex2bin(data, s, len)) return EFI_EXIT(EFI_DEVICE_ERROR); debug("%s: got value: \"%s\"\n", __func__, s); -- cgit v1.2.3 From 8377ee36d6a6cfdad56649e2cec64cfb97e3ae68 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 18 Jan 2019 18:54:26 +0100 Subject: efi_loader: remove duplicate function mem2hex() Replace duplicate function mem2hex() by inline function bin2hex(). Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/efi_variable.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index eea7f68b857..2ac27731fe5 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -47,19 +47,6 @@ #define PREFIX_LEN (strlen("efi_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx_")) -static char *mem2hex(char *hexstr, const u8 *mem, int count) -{ - static const char hexchars[] = "0123456789abcdef"; - - while (count-- > 0) { - u8 ch = *mem++; - *hexstr++ = hexchars[ch >> 4]; - *hexstr++ = hexchars[ch & 0xf]; - } - - return hexstr; -} - static efi_status_t efi_to_native(char **native, const u16 *variable_name, const efi_guid_t *vendor) { @@ -282,7 +269,7 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name, /* store payload: */ s += sprintf(s, "(blob)"); - s = mem2hex(s, data, data_size); + s = bin2hex(s, data, data_size); *s = '\0'; debug("%s: setting: %s=%s\n", __func__, native_name, val); -- cgit v1.2.3 From 77d4d396563c47a0cd74ea31fc8f906157c94b39 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 18 Jan 2019 19:52:05 +0100 Subject: efi_loader: comments for variable services Comment the functions implementing the runtime variable services. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/efi_variable.c | 86 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 81 insertions(+), 5 deletions(-) diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index 2ac27731fe5..cfb3168e779 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -47,6 +47,19 @@ #define PREFIX_LEN (strlen("efi_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx_")) +/** + * efi_to_native() - convert the UEFI variable name and vendor GUID to U-Boot + * variable name + * + * The U-Boot variable name is a concatenation of prefix 'efi', the hexstring + * encoded vendor GUID, and the UTF-8 encoded UEFI variable name separated by + * underscores, e.g. 'efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_BootOrder'. + * + * @native: pointer to pointer to U-Boot variable name + * @variable_name: UEFI variable name + * @vendor: vendor GUID + * Return: status code + */ static efi_status_t efi_to_native(char **native, const u16 *variable_name, const efi_guid_t *vendor) { @@ -65,6 +78,15 @@ static efi_status_t efi_to_native(char **native, const u16 *variable_name, return EFI_SUCCESS; } +/** + * prefix() - skip over prefix + * + * Skip over a prefix string. + * + * @str: string with prefix + * @prefix: prefix string + * Return: string without prefix, or NULL if prefix not found + */ static const char *prefix(const char *str, const char *prefix) { size_t n = strlen(prefix); @@ -73,7 +95,16 @@ static const char *prefix(const char *str, const char *prefix) return NULL; } -/* parse attributes part of variable value, if present: */ +/** + * parse_attr() - decode attributes part of variable value + * + * Convert the string encoded attributes of a UEFI variable to a bit mask. + * TODO: Several attributes are not supported. + * + * @str: value of U-Boot variable + * @attrp: pointer to UEFI attributes + * Return: pointer to remainder of U-Boot variable value + */ static const char *parse_attr(const char *str, u32 *attrp) { u32 attr = 0; @@ -111,7 +142,21 @@ static const char *parse_attr(const char *str, u32 *attrp) return str; } -/* http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#GetVariable.28.29 */ +/** + * efi_efi_get_variable() - retrieve value of a UEFI variable + * + * This function implements the GetVariable runtime service. + * + * See the Unified Extensible Firmware Interface (UEFI) specification for + * details. + * + * @variable_name: name of the variable + * @vendor: vendor GUID + * @attributes: attributes of the variable + * @data_size: size of the buffer to which the variable value is copied + * @data: buffer to which the variable value is copied + * Return: status code + */ efi_status_t EFIAPI efi_get_variable(u16 *variable_name, const efi_guid_t *vendor, u32 *attributes, efi_uintn_t *data_size, void *data) @@ -190,7 +235,21 @@ efi_status_t EFIAPI efi_get_variable(u16 *variable_name, return EFI_EXIT(EFI_SUCCESS); } -/* http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#GetNextVariableName.28.29 */ +/** + * efi_efi_get_next_variable() - get next UEFI variable + * + * This function implements the GetNextVariable runtime service. + * + * See the Unified Extensible Firmware Interface (UEFI) specification for + * details. + * + * @variable_name_size: on entry size of the buffer for the variable name, on + * exit the length of the name of the next variable + * @variable_name: on entry name of the current variable, on exit the name + * of the next variable + * @vendor: vendor GUID + * Return: status code + */ efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size, u16 *variable_name, const efi_guid_t *vendor) @@ -200,7 +259,21 @@ efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size, return EFI_EXIT(EFI_DEVICE_ERROR); } -/* http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#SetVariable.28.29 */ +/** + * efi_efi_set_variable() - set value of a UEFI variable + * + * This function implements the SetVariable runtime service. + * + * See the Unified Extensible Firmware Interface (UEFI) specification for + * details. + * + * @variable_name: name of the variable + * @vendor: vendor GUID + * @attributes: attributes of the variable + * @data_size: size of the buffer with the variable value + * @data: buffer with the variable value + * Return: status code + */ efi_status_t EFIAPI efi_set_variable(u16 *variable_name, const efi_guid_t *vendor, u32 attributes, efi_uintn_t data_size, const void *data) @@ -250,7 +323,10 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name, s = val; - /* store attributes: */ + /* + * store attributes + * TODO: several attributes are not supported + */ attributes &= (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS); s += sprintf(s, "{"); while (attributes) { -- cgit v1.2.3 From d99a87f84b7593263bd0bfadce8ec0d59e430cdf Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Mon, 21 Jan 2019 12:43:13 +0100 Subject: efi_loader: implement GetNextVariableName() The current GetNextVariableName() is a placeholder. With this patch, it works well as expected. Signed-off-by: AKASHI Takahiro rebased on efi-next Reviewed-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/efi_variable.c | 156 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 146 insertions(+), 10 deletions(-) diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index cfb3168e779..d94a5f69748 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -9,6 +9,9 @@ #include #include #include +#include +#include +#include #define READ_ONLY BIT(31) @@ -235,28 +238,161 @@ efi_status_t EFIAPI efi_get_variable(u16 *variable_name, return EFI_EXIT(EFI_SUCCESS); } +static char *efi_variables_list; +static char *efi_cur_variable; + /** - * efi_efi_get_next_variable() - get next UEFI variable + * parse_uboot_variable() - parse a u-boot variable and get uefi-related + * information + * @variable: whole data of u-boot variable (ie. name=value) + * @variable_name_size: size of variable_name buffer in byte + * @variable_name: name of uefi variable in u16, null-terminated + * @vendor: vendor's guid + * @attributes: attributes * - * This function implements the GetNextVariable runtime service. + * A uefi variable is encoded into a u-boot variable as described above. + * This function parses such a u-boot variable and retrieve uefi-related + * information into respective parameters. In return, variable_name_size + * is the size of variable name including NULL. + * + * Return: EFI_SUCCESS if parsing is OK, EFI_NOT_FOUND when + the entire variable list has been returned, + otherwise non-zero status code + */ +static efi_status_t parse_uboot_variable(char *variable, + efi_uintn_t *variable_name_size, + u16 *variable_name, + const efi_guid_t *vendor, + u32 *attributes) +{ + char *guid, *name, *end, c; + unsigned long name_len; + u16 *p; + + guid = strchr(variable, '_'); + if (!guid) + return EFI_INVALID_PARAMETER; + guid++; + name = strchr(guid, '_'); + if (!name) + return EFI_INVALID_PARAMETER; + name++; + end = strchr(name, '='); + if (!end) + return EFI_INVALID_PARAMETER; + + name_len = end - name; + if (*variable_name_size < (name_len + 1)) { + *variable_name_size = name_len + 1; + return EFI_BUFFER_TOO_SMALL; + } + end++; /* point to value */ + + /* variable name */ + p = variable_name; + utf8_utf16_strncpy(&p, name, name_len); + variable_name[name_len] = 0; + *variable_name_size = name_len + 1; + + /* guid */ + c = *(name - 1); + *(name - 1) = '\0'; /* guid need be null-terminated here */ + uuid_str_to_bin(guid, (unsigned char *)vendor, UUID_STR_FORMAT_GUID); + *(name - 1) = c; + + /* attributes */ + parse_attr(end, attributes); + + return EFI_SUCCESS; +} + +/** + * efi_get_next_variable_name() - enumerate the current variable names + * @variable_name_size: size of variable_name buffer in byte + * @variable_name: name of uefi variable's name in u16 + * @vendor: vendor's guid + * + * This function implements the GetNextVariableName service. * * See the Unified Extensible Firmware Interface (UEFI) specification for - * details. + * details: http://wiki.phoenix.com/wiki/index.php/ + * EFI_RUNTIME_SERVICES#GetNextVariableName.28.29 * - * @variable_name_size: on entry size of the buffer for the variable name, on - * exit the length of the name of the next variable - * @variable_name: on entry name of the current variable, on exit the name - * of the next variable - * @vendor: vendor GUID - * Return: status code + * Return: status code */ efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size, u16 *variable_name, const efi_guid_t *vendor) { + char *native_name, *variable; + ssize_t name_len, list_len; + char regex[256]; + char * const regexlist[] = {regex}; + u32 attributes; + int i; + efi_status_t ret; + EFI_ENTRY("%p \"%ls\" %pUl", variable_name_size, variable_name, vendor); - return EFI_EXIT(EFI_DEVICE_ERROR); + if (!variable_name_size || !variable_name || !vendor) + EFI_EXIT(EFI_INVALID_PARAMETER); + + if (variable_name[0]) { + /* check null-terminated string */ + for (i = 0; i < *variable_name_size; i++) + if (!variable_name[i]) + break; + if (i >= *variable_name_size) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + /* search for the last-returned variable */ + ret = efi_to_native(&native_name, variable_name, vendor); + if (ret) + return EFI_EXIT(ret); + + name_len = strlen(native_name); + for (variable = efi_variables_list; variable && *variable;) { + if (!strncmp(variable, native_name, name_len) && + variable[name_len] == '=') + break; + + variable = strchr(variable, '\n'); + if (variable) + variable++; + } + + free(native_name); + if (!(variable && *variable)) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + /* next variable */ + variable = strchr(variable, '\n'); + if (variable) + variable++; + if (!(variable && *variable)) + return EFI_EXIT(EFI_NOT_FOUND); + } else { + /* + *new search: free a list used in the previous search + */ + free(efi_variables_list); + efi_variables_list = NULL; + efi_cur_variable = NULL; + + snprintf(regex, 256, "efi_.*-.*-.*-.*-.*_.*"); + list_len = hexport_r(&env_htab, '\n', + H_MATCH_REGEX | H_MATCH_KEY, + &efi_variables_list, 0, 1, regexlist); + if (list_len <= 0) + return EFI_EXIT(EFI_NOT_FOUND); + + variable = efi_variables_list; + } + + ret = parse_uboot_variable(variable, variable_name_size, variable_name, + vendor, &attributes); + + return EFI_EXIT(ret); } /** -- cgit v1.2.3 From 1170fee695197783185b1fa0c398945b248fb397 Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Mon, 21 Jan 2019 12:43:14 +0100 Subject: efi_selftest: fix variables test for GetNextVariableName() There is a bug in efi variables test. Fix it with some cosmetic improvements. Please note that efi variables test still fails at QueryVariableInfo() and GetVariable(), but this is not due to a change in this patch. ==8<== Testing EFI API implementation Selected test: 'variables' Setting up 'variables' Setting up 'variables' succeeded Executing 'variables' .../u-boot/lib/efi_selftest/efi_selftest_variables.c(60): TODO: QueryVariableInfo failed .../u-boot/lib/efi_selftest/efi_selftest_variables.c(131): TODO: GetVariable returned wrong length 7 .../u-boot/lib/efi_selftest/efi_selftest_variables.c(133): TODO: GetVariable returned wrong value Executing 'variables' succeeded Boot services terminated Summary: 0 failures ==>8== Signed-off-by: AKASHI Takahiro Reviewed-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_selftest/efi_selftest_variables.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/efi_selftest/efi_selftest_variables.c b/lib/efi_selftest/efi_selftest_variables.c index ffc8cad3295..47a8e7fb95c 100644 --- a/lib/efi_selftest/efi_selftest_variables.c +++ b/lib/efi_selftest/efi_selftest_variables.c @@ -141,19 +141,22 @@ static int execute(void) if (ret == EFI_NOT_FOUND) break; if (ret != EFI_SUCCESS) { - efi_st_todo("GetNextVariableName failed\n"); - break; + efi_st_error("GetNextVariableName failed (%u)\n", + (unsigned int)ret); + return EFI_ST_FAILURE; } if (!efi_st_memcmp(&guid, &guid_vendor0, sizeof(efi_guid_t)) && !efi_st_strcmp_16_8(varname, "efi_st_var0")) - flag |= 2; + flag |= 1; if (!efi_st_memcmp(&guid, &guid_vendor1, sizeof(efi_guid_t)) && !efi_st_strcmp_16_8(varname, "efi_st_var1")) flag |= 2; } - if (flag != 3) - efi_st_todo( + if (flag != 3) { + efi_st_error( "GetNextVariableName did not return all variables\n"); + return EFI_ST_FAILURE; + } /* Delete variable 1 */ ret = runtime->set_variable(L"efi_st_var1", &guid_vendor1, 0, 0, NULL); -- cgit v1.2.3 From f51a226436a874ad4a9fda48dfab169155a48d49 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 20 Jan 2019 08:20:30 +0100 Subject: efi_loader: provide freestanding library GCC requires that freestanding programs provide memcpy(), memmove(), memset(), and memcmp(). Provide the required library functions. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/efi_freestanding.c | 90 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 lib/efi_loader/efi_freestanding.c diff --git a/lib/efi_loader/efi_freestanding.c b/lib/efi_loader/efi_freestanding.c new file mode 100644 index 00000000000..bd9da5bbc86 --- /dev/null +++ b/lib/efi_loader/efi_freestanding.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Library for freestanding binary + * + * Copyright 2019, Heinrich Schuchardt + * + * GCC requires that freestanding programs provide memcpy(), memmove(), + * memset(), and memcmp(). + */ + +#include + +/** + * memcmp() - compare memory areas + * + * @s1: pointer to first area + * @s2: pointer to second area + * @n: number of bytes to compare + * Return: 0 if both memory areas are the same, otherwise the sign of the + * result value is the same as the sign of the difference between + * the first differing pair of bytes taken as u8. + */ +int memcmp(const void *s1, const void *s2, size_t n) +{ + const u8 *pos1 = s1; + const u8 *pos2 = s2; + + for (; n; --n) { + if (*pos1 != *pos2) + return *pos1 - *pos2; + ++pos1; + ++pos2; + } + return 0; +} + +/** + * memcpy() - copy memory area + * + * @dest: destination buffer + * @src: source buffer + * @n: number of bytes to copy + * Return: pointer to destination buffer + */ +void *memmove(void *dest, const void *src, size_t n) +{ + u8 *d = dest; + const u8 *s = src; + + if (d >= s) { + for (; n; --n) + *d++ = *s++; + } else { + d += n; + s += n; + for (; n; --n) + *--d = *--s; + } + return dest; +} + +/** + * memcpy() - copy memory area + * + * @dest: destination buffer + * @src: source buffer + * @n: number of bytes to copy + * Return: pointer to destination buffer + */ +void *memcpy(void *dest, const void *src, size_t n) +{ + return memmove(dest, src, n); +} + +/** + * memset() - fill memory with a constant byte + * + * @s: destination buffer + * @c: byte value + * @n: number of bytes to set + * Return: pointer to destination buffer + */ +void *memset(void *s, int c, size_t n) +{ + u8 *d = s; + + for (; n; --n) + *d++ = c; + return s; +} -- cgit v1.2.3 From 2013c6850e169bfd5ef662a5fb49fdba2860c4f1 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 20 Jan 2019 08:20:31 +0100 Subject: efi_loader: use freestanding library for efi apps GCC requires that freestanding programs provide memcpy(), memmove(), memset(), and memcmp(). Add the library functions when building a *.efi files. The EFI selftests might use other compilation flags. So use a symbolic link to provide lib/efi_selftest/efi_freestanding.c and compile it separately. Reported-by: Alexander Graf Fixes: 5be444d14b38 ("efi_loader: consistent build flags for EFI applications") Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_selftest/efi_freestanding.c | 1 + scripts/Makefile.lib | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 120000 lib/efi_selftest/efi_freestanding.c diff --git a/lib/efi_selftest/efi_freestanding.c b/lib/efi_selftest/efi_freestanding.c new file mode 120000 index 00000000000..4b7edd52bd9 --- /dev/null +++ b/lib/efi_selftest/efi_freestanding.c @@ -0,0 +1 @@ +../efi_loader/efi_freestanding.c \ No newline at end of file diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index a5b57fc6b98..4facb76aceb 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -389,7 +389,7 @@ $(obj)/efi_reloc.o: $(srctree)/arch/$(ARCH)/lib/$(EFI_RELOC:.o=.c) $(recordmcoun $(call cmd,force_checksrc) $(call if_changed_rule,cc_o_c) -$(obj)/%_efi.so: $(obj)/%.o $(obj)/efi_crt0.o $(obj)/efi_reloc.o +$(obj)/%_efi.so: $(obj)/%.o $(obj)/efi_crt0.o $(obj)/efi_reloc.o $(obj)/efi_freestanding.o $(call cmd,efi_ld) # ACPI -- cgit v1.2.3 From 6446304460a63b46ce2ffebafc332b20a76e5ef6 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 20 Jan 2019 08:20:32 +0100 Subject: efi_loader: use library memcpy() in helloworld.efi Helloworld does not need its own memcpy() implementation anymore. Use the one provided in efi_freestanding.c. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/helloworld.c | 36 ++++++------------------------------ 1 file changed, 6 insertions(+), 30 deletions(-) diff --git a/lib/efi_loader/helloworld.c b/lib/efi_loader/helloworld.c index 2905479e658..426f276361a 100644 --- a/lib/efi_loader/helloworld.c +++ b/lib/efi_loader/helloworld.c @@ -17,30 +17,6 @@ static const efi_guid_t fdt_guid = EFI_FDT_GUID; static const efi_guid_t acpi_guid = EFI_ACPI_TABLE_GUID; static const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID; -/** - * hw_memcmp() - compare memory areas - * - * @buf1: pointer to first area - * @buf2: pointer to second area - * @length: number of bytes to compare - * Return: 0 if both memory areas are the same, otherwise the sign of the - * result value is the same as the sign of ghe difference between - * the first differing pair of bytes taken as u8. - */ -static int hw_memcmp(const void *buf1, const void *buf2, size_t length) -{ - const u8 *pos1 = buf1; - const u8 *pos2 = buf2; - - for (; length; --length) { - if (*pos1 != *pos2) - return *pos1 - *pos2; - ++pos1; - ++pos2; - } - return 0; -} - /** * efi_main() - entry point of the EFI application. * @@ -88,16 +64,16 @@ efi_status_t EFIAPI efi_main(efi_handle_t handle, } /* Find configuration tables */ for (i = 0; i < systable->nr_tables; ++i) { - if (!hw_memcmp(&systable->tables[i].guid, &fdt_guid, - sizeof(efi_guid_t))) + if (!memcmp(&systable->tables[i].guid, &fdt_guid, + sizeof(efi_guid_t))) con_out->output_string (con_out, L"Have device tree\r\n"); - if (!hw_memcmp(&systable->tables[i].guid, &acpi_guid, - sizeof(efi_guid_t))) + if (!memcmp(&systable->tables[i].guid, &acpi_guid, + sizeof(efi_guid_t))) con_out->output_string (con_out, L"Have ACPI 2.0 table\r\n"); - if (!hw_memcmp(&systable->tables[i].guid, &smbios_guid, - sizeof(efi_guid_t))) + if (!memcmp(&systable->tables[i].guid, &smbios_guid, + sizeof(efi_guid_t))) con_out->output_string (con_out, L"Have SMBIOS table\r\n"); } -- cgit v1.2.3 From 6c75db07f4115904a460540c8956db2087cceb1f Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Mon, 21 Jan 2019 19:30:42 +0100 Subject: efi_loader: do not use symbolic links Symbolic links are not supported on all file systems, e.g. not on FAT. So it is not wise to use them in our source tree. Use a qualified path to refer to lib/efi_loader/efi_freestanding.c in scripts/Makefile.lib instead. Reported-by: Alexander Graf Signed-off-by: Heinrich Schuchardt [agraf: Fix build with O=] Signed-off-by: Alexander Graf --- lib/efi_selftest/efi_freestanding.c | 1 - scripts/Makefile.lib | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 120000 lib/efi_selftest/efi_freestanding.c diff --git a/lib/efi_selftest/efi_freestanding.c b/lib/efi_selftest/efi_freestanding.c deleted file mode 120000 index 4b7edd52bd9..00000000000 --- a/lib/efi_selftest/efi_freestanding.c +++ /dev/null @@ -1 +0,0 @@ -../efi_loader/efi_freestanding.c \ No newline at end of file diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 4facb76aceb..66e5015d8d7 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -389,7 +389,7 @@ $(obj)/efi_reloc.o: $(srctree)/arch/$(ARCH)/lib/$(EFI_RELOC:.o=.c) $(recordmcoun $(call cmd,force_checksrc) $(call if_changed_rule,cc_o_c) -$(obj)/%_efi.so: $(obj)/%.o $(obj)/efi_crt0.o $(obj)/efi_reloc.o $(obj)/efi_freestanding.o +$(obj)/%_efi.so: $(obj)/%.o $(obj)/efi_crt0.o $(obj)/efi_reloc.o $(obj)/../efi_loader/efi_freestanding.o $(call cmd,efi_ld) # ACPI -- cgit v1.2.3 From eefb790e9010282fb5c430cb18986f3838181c6d Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Tue, 22 Jan 2019 20:10:46 +0100 Subject: efi_loader: fix GetNextVariableName Our current implementation of GetNextVariableName() first collects all EFI variables. If none is found at all hexport_r() returns a zero length string terminated by \0 and the value 1 as number of bytes in the returned buffer. In this case GetNextVariableName() has to return EFI_NOT_FOUND. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/efi_variable.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index d94a5f69748..e0d7f5736db 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -383,7 +383,8 @@ efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size, list_len = hexport_r(&env_htab, '\n', H_MATCH_REGEX | H_MATCH_KEY, &efi_variables_list, 0, 1, regexlist); - if (list_len <= 0) + /* 1 indicates that no match was found */ + if (list_len <= 1) return EFI_EXIT(EFI_NOT_FOUND); variable = efi_variables_list; -- cgit v1.2.3 From dba5148049c8e7d1863dfebaa0cb5dcb0e472db8 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Tue, 22 Jan 2019 21:35:23 +0100 Subject: efi_loader: GetNextVariableName() relies on REGEX Our implementation of GetNextVariableName() relies on CONFIG_REGEX=y. So EFI_LOADER has to select it. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index b921ea88215..f5de005ff8b 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -8,6 +8,7 @@ config EFI_LOADER default y select LIB_UUID select HAVE_BLOCK_DEVICE + select REGEX imply CFB_CONSOLE_ANSI help Select this option if you want to run EFI applications (like grub2) -- cgit v1.2.3 From 6b59607f10c038b37ca216d17516256e2ac467d2 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 23 Jan 2019 02:42:39 +0100 Subject: x86: do not use i386 code for x86_64 memory functions arch/x86/lib/string.c contains assembler implementations of memcpy(), memmove(), and memset() written for i386. Don't use it on x86_64. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- arch/x86/include/asm/string.h | 31 +++++++++++++++++++++++-------- arch/x86/lib/Makefile | 2 +- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/arch/x86/include/asm/string.h b/arch/x86/include/asm/string.h index 38afd236843..c15b264a5c0 100644 --- a/arch/x86/include/asm/string.h +++ b/arch/x86/include/asm/string.h @@ -9,22 +9,37 @@ extern char *strncpy(char *__dest, __const__ char *__src, __kernel_size_t __n); #undef __HAVE_ARCH_STRRCHR -extern char * strrchr(const char * s, int c); +extern char *strrchr(const char *s, int c); #undef __HAVE_ARCH_STRCHR -extern char * strchr(const char * s, int c); +extern char *strchr(const char *s, int c); + +#ifdef CONFIG_X86_64 + +#undef __HAVE_ARCH_MEMCPY +extern void *memcpy(void *, const void *, __kernel_size_t); + +#undef __HAVE_ARCH_MEMMOVE +extern void *memmove(void *, const void *, __kernel_size_t); + +#undef __HAVE_ARCH_MEMSET +extern void *memset(void *, int, __kernel_size_t); + +#else #define __HAVE_ARCH_MEMCPY -extern void * memcpy(void *, const void *, __kernel_size_t); +extern void *memcpy(void *, const void *, __kernel_size_t); #define __HAVE_ARCH_MEMMOVE -extern void * memmove(void *, const void *, __kernel_size_t); - -#undef __HAVE_ARCH_MEMCHR -extern void * memchr(const void *, int, __kernel_size_t); +extern void *memmove(void *, const void *, __kernel_size_t); #define __HAVE_ARCH_MEMSET -extern void * memset(void *, int, __kernel_size_t); +extern void *memset(void *, int, __kernel_size_t); + +#endif /* CONFIG_X86_64 */ + +#undef __HAVE_ARCH_MEMCHR +extern void *memchr(const void *, int, __kernel_size_t); #undef __HAVE_ARCH_MEMZERO extern void memzero(void *ptr, __kernel_size_t n); diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 1e8efcc44f9..56fd680033b 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -7,6 +7,7 @@ ifndef CONFIG_X86_64 obj-y += bios.o obj-y += bios_asm.o obj-y += bios_interrupts.o +obj-y += string.o endif ifndef CONFIG_SPL_BUILD obj-$(CONFIG_CMD_BOOTM) += bootm.o @@ -32,7 +33,6 @@ obj-$(CONFIG_X86_RAMTEST) += ramtest.o obj-$(CONFIG_INTEL_MID) += scu.o obj-y += sections.o obj-y += sfi.o -obj-y += string.o obj-y += acpi.o obj-$(CONFIG_HAVE_ACPI_RESUME) += acpi_s3.o ifndef CONFIG_QEMU -- cgit v1.2.3 From c9bfb22296b09de84fba3f027d5d88842360ddcd Mon Sep 17 00:00:00 2001 From: Leif Lindholm Date: Mon, 21 Jan 2019 12:12:57 +0900 Subject: efi_loader: Initial HII database protocols This patch provides enough implementation of the following protocols to run EDKII's Shell.efi and UEFI SCT: * EfiHiiDatabaseProtocol * EfiHiiStringProtocol Not implemented are: * ExportPackageLists() * RegisterPackageNotify()/UnregisterPackageNotify() * SetKeyboardLayout() (i.e. *current* keyboard layout) HII database protocol in this patch series can handle only: * GUID package * string package * keyboard layout package (The other packages, except Device path package, will be necessary for interactive and graphical UI.) Signed-off-by: Leif Lindholm Signed-off-by: Rob Clark Signed-off-by: AKASHI Takahiro Signed-off-by: Alexander Graf --- include/efi_api.h | 245 ++++++++++- include/efi_loader.h | 4 + lib/efi_loader/Makefile | 1 + lib/efi_loader/efi_boottime.c | 12 + lib/efi_loader/efi_hii.c | 922 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 1183 insertions(+), 1 deletion(-) create mode 100644 lib/efi_loader/efi_hii.c diff --git a/include/efi_api.h b/include/efi_api.h index 6af52bcb866..347c7333c5e 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -17,6 +17,7 @@ #define _EFI_API_H #include +#include #ifdef CONFIG_EFI_LOADER #include @@ -34,7 +35,10 @@ enum efi_timer_delay { #define efi_intn_t ssize_t #define efi_uintn_t size_t -typedef uint16_t *efi_string_t; +typedef void *efi_hii_handle_t; +typedef u16 *efi_string_t; +typedef u16 efi_string_id_t; +typedef u32 efi_hii_font_style_t; #define EVT_TIMER 0x80000000 #define EVT_RUNTIME 0x40000000 @@ -700,6 +704,245 @@ struct efi_device_path_utilities_protocol { uint16_t node_length); }; +/* + * Human Interface Infrastructure (HII) + */ +struct efi_hii_package_list_header { + efi_guid_t package_list_guid; + u32 package_length; +} __packed; + +/** + * struct efi_hii_package_header - EFI HII package header + * + * @fields: 'fields' replaces the bit-fields defined in the EFI + * specification to to avoid possible compiler incompatibilities:: + * + * u32 length:24; + * u32 type:8; + */ +struct efi_hii_package_header { + u32 fields; +} __packed; + +#define __EFI_HII_PACKAGE_LEN_SHIFT 0 +#define __EFI_HII_PACKAGE_TYPE_SHIFT 24 +#define __EFI_HII_PACKAGE_LEN_MASK 0xffffff +#define __EFI_HII_PACKAGE_TYPE_MASK 0xff + +#define EFI_HII_PACKAGE_TYPE_ALL 0x00 +#define EFI_HII_PACKAGE_TYPE_GUID 0x01 +#define EFI_HII_PACKAGE_FORMS 0x02 +#define EFI_HII_PACKAGE_STRINGS 0x04 +#define EFI_HII_PACKAGE_FONTS 0x05 +#define EFI_HII_PACKAGE_IMAGES 0x06 +#define EFI_HII_PACKAGE_SIMPLE_FONTS 0x07 +#define EFI_HII_PACKAGE_DEVICE_PATH 0x08 +#define EFI_HII_PACKAGE_KEYBOARD_LAYOUT 0x09 +#define EFI_HII_PACKAGE_ANIMATIONS 0x0A +#define EFI_HII_PACKAGE_END 0xDF +#define EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN 0xE0 +#define EFI_HII_PACKAGE_TYPE_SYSTEM_END 0xFF + +/* + * HII string package + */ +struct efi_hii_strings_package { + struct efi_hii_package_header header; + u32 header_size; + u32 string_info_offset; + u16 language_window[16]; + efi_string_id_t language_name; + u8 language[]; +} __packed; + +struct efi_hii_string_block { + u8 block_type; + /* u8 block_body[]; */ +} __packed; + +#define EFI_HII_SIBT_END 0x00 +#define EFI_HII_SIBT_STRING_SCSU 0x10 +#define EFI_HII_SIBT_STRING_SCSU_FONT 0x11 +#define EFI_HII_SIBT_STRINGS_SCSU 0x12 +#define EFI_HII_SIBT_STRINGS_SCSU_FONT 0x13 +#define EFI_HII_SIBT_STRING_UCS2 0x14 +#define EFI_HII_SIBT_STRING_UCS2_FONT 0x15 +#define EFI_HII_SIBT_STRINGS_UCS2 0x16 +#define EFI_HII_SIBT_STRINGS_UCS2_FONT 0x17 +#define EFI_HII_SIBT_DUPLICATE 0x20 +#define EFI_HII_SIBT_SKIP2 0x21 +#define EFI_HII_SIBT_SKIP1 0x22 +#define EFI_HII_SIBT_EXT1 0x30 +#define EFI_HII_SIBT_EXT2 0x31 +#define EFI_HII_SIBT_EXT4 0x32 +#define EFI_HII_SIBT_FONT 0x40 + +struct efi_hii_sibt_string_ucs2_block { + struct efi_hii_string_block header; + u16 string_text[]; +} __packed; + +static inline struct efi_hii_string_block * +efi_hii_sibt_string_ucs2_block_next(struct efi_hii_sibt_string_ucs2_block *blk) +{ + return ((void *)blk) + sizeof(*blk) + + (u16_strlen(blk->string_text) + 1) * 2; +} + +/* + * HII keyboard package + */ +typedef enum { + EFI_KEY_LCTRL, EFI_KEY_A0, EFI_KEY_LALT, EFI_KEY_SPACE_BAR, + EFI_KEY_A2, EFI_KEY_A3, EFI_KEY_A4, EFI_KEY_RCTRL, EFI_KEY_LEFT_ARROW, + EFI_KEY_DOWN_ARROW, EFI_KEY_RIGHT_ARROW, EFI_KEY_ZERO, + EFI_KEY_PERIOD, EFI_KEY_ENTER, EFI_KEY_LSHIFT, EFI_KEY_B0, + EFI_KEY_B1, EFI_KEY_B2, EFI_KEY_B3, EFI_KEY_B4, EFI_KEY_B5, EFI_KEY_B6, + EFI_KEY_B7, EFI_KEY_B8, EFI_KEY_B9, EFI_KEY_B10, EFI_KEY_RSHIFT, + EFI_KEY_UP_ARROW, EFI_KEY_ONE, EFI_KEY_TWO, EFI_KEY_THREE, + EFI_KEY_CAPS_LOCK, EFI_KEY_C1, EFI_KEY_C2, EFI_KEY_C3, EFI_KEY_C4, + EFI_KEY_C5, EFI_KEY_C6, EFI_KEY_C7, EFI_KEY_C8, EFI_KEY_C9, + EFI_KEY_C10, EFI_KEY_C11, EFI_KEY_C12, EFI_KEY_FOUR, EFI_KEY_FIVE, + EFI_KEY_SIX, EFI_KEY_PLUS, EFI_KEY_TAB, EFI_KEY_D1, EFI_KEY_D2, + EFI_KEY_D3, EFI_KEY_D4, EFI_KEY_D5, EFI_KEY_D6, EFI_KEY_D7, EFI_KEY_D8, + EFI_KEY_D9, EFI_KEY_D10, EFI_KEY_D11, EFI_KEY_D12, EFI_KEY_D13, + EFI_KEY_DEL, EFI_KEY_END, EFI_KEY_PG_DN, EFI_KEY_SEVEN, EFI_KEY_EIGHT, + EFI_KEY_NINE, EFI_KEY_E0, EFI_KEY_E1, EFI_KEY_E2, EFI_KEY_E3, + EFI_KEY_E4, EFI_KEY_E5, EFI_KEY_E6, EFI_KEY_E7, EFI_KEY_E8, EFI_KEY_E9, + EFI_KEY_E10, EFI_KEY_E11, EFI_KEY_E12, EFI_KEY_BACK_SPACE, + EFI_KEY_INS, EFI_KEY_HOME, EFI_KEY_PG_UP, EFI_KEY_NLCK, EFI_KEY_SLASH, + EFI_KEY_ASTERISK, EFI_KEY_MINUS, EFI_KEY_ESC, EFI_KEY_F1, EFI_KEY_F2, + EFI_KEY_F3, EFI_KEY_F4, EFI_KEY_F5, EFI_KEY_F6, EFI_KEY_F7, EFI_KEY_F8, + EFI_KEY_F9, EFI_KEY_F10, EFI_KEY_F11, EFI_KEY_F12, EFI_KEY_PRINT, + EFI_KEY_SLCK, EFI_KEY_PAUSE, +} efi_key; + +struct efi_key_descriptor { + u32 key; + u16 unicode; + u16 shifted_unicode; + u16 alt_gr_unicode; + u16 shifted_alt_gr_unicode; + u16 modifier; + u16 affected_attribute; +} __packed; + +struct efi_hii_keyboard_layout { + u16 layout_length; + efi_guid_t guid; + u32 layout_descriptor_string_offset; + u8 descriptor_count; + struct efi_key_descriptor descriptors[]; +} __packed; + +/* + * HII protocols + */ +#define EFI_HII_STRING_PROTOCOL_GUID \ + EFI_GUID(0x0fd96974, 0x23aa, 0x4cdc, \ + 0xb9, 0xcb, 0x98, 0xd1, 0x77, 0x50, 0x32, 0x2a) + +struct efi_font_info { + efi_hii_font_style_t font_style; + u16 font_size; + u16 font_name[1]; +}; + +struct efi_hii_string_protocol { + efi_status_t(EFIAPI *new_string)( + const struct efi_hii_string_protocol *this, + efi_hii_handle_t package_list, + efi_string_id_t *string_id, + const u8 *language, + const u16 *language_name, + const efi_string_t string, + const struct efi_font_info *string_font_info); + efi_status_t(EFIAPI *get_string)( + const struct efi_hii_string_protocol *this, + const u8 *language, + efi_hii_handle_t package_list, + efi_string_id_t string_id, + efi_string_t string, + efi_uintn_t *string_size, + struct efi_font_info **string_font_info); + efi_status_t(EFIAPI *set_string)( + const struct efi_hii_string_protocol *this, + efi_hii_handle_t package_list, + efi_string_id_t string_id, + const u8 *language, + const efi_string_t string, + const struct efi_font_info *string_font_info); + efi_status_t(EFIAPI *get_languages)( + const struct efi_hii_string_protocol *this, + efi_hii_handle_t package_list, + u8 *languages, + efi_uintn_t *languages_size); + efi_status_t(EFIAPI *get_secondary_languages)( + const struct efi_hii_string_protocol *this, + efi_hii_handle_t package_list, + const u8 *primary_language, + u8 *secondary_languages, + efi_uintn_t *secondary_languages_size); +}; + +#define EFI_HII_DATABASE_PROTOCOL_GUID \ + EFI_GUID(0xef9fc172, 0xa1b2, 0x4693, \ + 0xb3, 0x27, 0x6d, 0x32, 0xfc, 0x41, 0x60, 0x42) + +struct efi_hii_database_protocol { + efi_status_t(EFIAPI *new_package_list)( + const struct efi_hii_database_protocol *this, + const struct efi_hii_package_list_header *package_list, + const efi_handle_t driver_handle, + efi_hii_handle_t *handle); + efi_status_t(EFIAPI *remove_package_list)( + const struct efi_hii_database_protocol *this, + efi_hii_handle_t handle); + efi_status_t(EFIAPI *update_package_list)( + const struct efi_hii_database_protocol *this, + efi_hii_handle_t handle, + const struct efi_hii_package_list_header *package_list); + efi_status_t(EFIAPI *list_package_lists)( + const struct efi_hii_database_protocol *this, + u8 package_type, + const efi_guid_t *package_guid, + efi_uintn_t *handle_buffer_length, + efi_hii_handle_t *handle); + efi_status_t(EFIAPI *export_package_lists)( + const struct efi_hii_database_protocol *this, + efi_hii_handle_t handle, + efi_uintn_t *buffer_size, + struct efi_hii_package_list_header *buffer); + efi_status_t(EFIAPI *register_package_notify)( + const struct efi_hii_database_protocol *this, + u8 package_type, + const efi_guid_t *package_guid, + const void *package_notify_fn, + efi_uintn_t notify_type, + efi_handle_t *notify_handle); + efi_status_t(EFIAPI *unregister_package_notify)( + const struct efi_hii_database_protocol *this, + efi_handle_t notification_handle + ); + efi_status_t(EFIAPI *find_keyboard_layouts)( + const struct efi_hii_database_protocol *this, + u16 *key_guid_buffer_length, + efi_guid_t *key_guid_buffer); + efi_status_t(EFIAPI *get_keyboard_layout)( + const struct efi_hii_database_protocol *this, + efi_guid_t *key_guid, + u16 *keyboard_layout_length, + struct efi_hii_keyboard_layout *keyboard_layout); + efi_status_t(EFIAPI *set_keyboard_layout)( + const struct efi_hii_database_protocol *this, + efi_guid_t *key_guid); + efi_status_t(EFIAPI *get_package_list_handle)( + const struct efi_hii_database_protocol *this, + efi_hii_handle_t package_list_handle, + efi_handle_t *driver_handle); +}; + #define EFI_GOP_GUID \ EFI_GUID(0x9042a9de, 0x23dc, 0x4a38, \ 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a) diff --git a/include/efi_loader.h b/include/efi_loader.h index b44678169aa..206f724bd9c 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -106,6 +106,8 @@ extern const struct efi_device_path_utilities_protocol /* Implementation of the EFI_UNICODE_COLLATION_PROTOCOL */ extern const struct efi_unicode_collation_protocol efi_unicode_collation_protocol; +extern const struct efi_hii_database_protocol efi_hii_database; +extern const struct efi_hii_string_protocol efi_hii_string; uint16_t *efi_dp_str(struct efi_device_path *dp); @@ -139,6 +141,8 @@ extern const efi_guid_t efi_file_system_info_guid; extern const efi_guid_t efi_guid_device_path_utilities_protocol; /* GUID of the Unicode collation protocol */ extern const efi_guid_t efi_guid_unicode_collation_protocol; +extern const efi_guid_t efi_guid_hii_database_protocol; +extern const efi_guid_t efi_guid_hii_string_protocol; extern unsigned int __efi_runtime_start, __efi_runtime_stop; extern unsigned int __efi_runtime_rel_start, __efi_runtime_rel_stop; diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index e2e6da3ea4c..00128d417b9 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -24,6 +24,7 @@ obj-y += efi_device_path.o obj-y += efi_device_path_to_text.o obj-y += efi_device_path_utilities.o obj-y += efi_file.o +obj-y += efi_hii.o obj-y += efi_image_loader.o obj-y += efi_memory.o obj-y += efi_root_node.o diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index dbf0d56c1d3..73af490377c 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1558,6 +1558,18 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, if (ret != EFI_SUCCESS) goto failure; + ret = efi_add_protocol(&obj->header, + &efi_guid_hii_string_protocol, + (void *)&efi_hii_string); + if (ret != EFI_SUCCESS) + goto failure; + + ret = efi_add_protocol(&obj->header, + &efi_guid_hii_database_protocol, + (void *)&efi_hii_database); + if (ret != EFI_SUCCESS) + goto failure; + return ret; failure: printf("ERROR: Failure to install protocols for loaded image\n"); diff --git a/lib/efi_loader/efi_hii.c b/lib/efi_loader/efi_hii.c new file mode 100644 index 00000000000..d6dba5719cd --- /dev/null +++ b/lib/efi_loader/efi_hii.c @@ -0,0 +1,922 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * EFI Human Interface Infrastructure ... database and packages + * + * Copyright (c) 2017 Leif Lindholm + * Copyright (c) 2018 AKASHI Takahiro, Linaro Limited + */ + +#include +#include +#include +#include + +const efi_guid_t efi_guid_hii_database_protocol + = EFI_HII_DATABASE_PROTOCOL_GUID; +const efi_guid_t efi_guid_hii_string_protocol = EFI_HII_STRING_PROTOCOL_GUID; + +static LIST_HEAD(efi_package_lists); + +struct efi_hii_packagelist { + struct list_head link; + // TODO should there be an associated efi_object? + efi_handle_t driver_handle; + u32 max_string_id; + struct list_head string_tables; /* list of efi_string_table */ + + /* we could also track fonts, images, etc */ +}; + +static int efi_hii_packagelist_exists(efi_hii_handle_t package_list) +{ + struct efi_hii_packagelist *hii; + int found = 0; + + list_for_each_entry(hii, &efi_package_lists, link) { + if (hii == package_list) { + found = 1; + break; + } + } + + return found; +} + +static u32 efi_hii_package_type(struct efi_hii_package_header *header) +{ + u32 fields; + + fields = get_unaligned_le32(&header->fields); + + return (fields >> __EFI_HII_PACKAGE_TYPE_SHIFT) + & __EFI_HII_PACKAGE_TYPE_MASK; +} + +static u32 efi_hii_package_len(struct efi_hii_package_header *header) +{ + u32 fields; + + fields = get_unaligned_le32(&header->fields); + + return (fields >> __EFI_HII_PACKAGE_LEN_SHIFT) + & __EFI_HII_PACKAGE_LEN_MASK; +} + +struct efi_string_info { + efi_string_t string; + /* we could also track font info, etc */ +}; + +struct efi_string_table { + struct list_head link; + efi_string_id_t language_name; + char *language; + u32 nstrings; + /* + * NOTE: + * string id starts at 1 so value is stbl->strings[id-1], + * and strings[] is a array of stbl->nstrings elements + */ + struct efi_string_info *strings; +}; + +static void free_strings_table(struct efi_string_table *stbl) +{ + int i; + + for (i = 0; i < stbl->nstrings; i++) + free(stbl->strings[i].string); + free(stbl->strings); + free(stbl->language); + free(stbl); +} + +static void remove_strings_package(struct efi_hii_packagelist *hii) +{ + while (!list_empty(&hii->string_tables)) { + struct efi_string_table *stbl; + + stbl = list_first_entry(&hii->string_tables, + struct efi_string_table, link); + list_del(&stbl->link); + free_strings_table(stbl); + } +} + +static efi_status_t +add_strings_package(struct efi_hii_packagelist *hii, + struct efi_hii_strings_package *strings_package) +{ + struct efi_hii_string_block *block; + void *end; + u32 nstrings = 0, idx = 0; + struct efi_string_table *stbl = NULL; + efi_status_t ret; + + debug("header_size: %08x\n", + get_unaligned_le32(&strings_package->header_size)); + debug("string_info_offset: %08x\n", + get_unaligned_le32(&strings_package->string_info_offset)); + debug("language_name: %u\n", + get_unaligned_le16(&strings_package->language_name)); + debug("language: %s\n", strings_package->language); + + /* count # of string entries: */ + end = ((void *)strings_package) + + efi_hii_package_len(&strings_package->header); + block = ((void *)strings_package) + + get_unaligned_le32(&strings_package->string_info_offset); + + while ((void *)block < end) { + switch (block->block_type) { + case EFI_HII_SIBT_STRING_UCS2: { + struct efi_hii_sibt_string_ucs2_block *ucs2; + + ucs2 = (void *)block; + nstrings++; + block = efi_hii_sibt_string_ucs2_block_next(ucs2); + break; + } + case EFI_HII_SIBT_END: + block = end; + break; + default: + debug("unknown HII string block type: %02x\n", + block->block_type); + return EFI_INVALID_PARAMETER; + } + } + + stbl = calloc(sizeof(*stbl), 1); + if (!stbl) { + ret = EFI_OUT_OF_RESOURCES; + goto error; + } + stbl->strings = calloc(sizeof(stbl->strings[0]), nstrings); + if (!stbl->strings) { + ret = EFI_OUT_OF_RESOURCES; + goto error; + } + stbl->language_name = + get_unaligned_le16(&strings_package->language_name); + stbl->language = strdup((char *)strings_package->language); + if (!stbl->language) { + ret = EFI_OUT_OF_RESOURCES; + goto error; + } + stbl->nstrings = nstrings; + + /* and now parse string entries and populate efi_string_table */ + block = ((void *)strings_package) + + get_unaligned_le32(&strings_package->string_info_offset); + + while ((void *)block < end) { + switch (block->block_type) { + case EFI_HII_SIBT_STRING_UCS2: { + struct efi_hii_sibt_string_ucs2_block *ucs2; + + ucs2 = (void *)block; + debug("%4u: \"%ls\"\n", idx + 1, ucs2->string_text); + stbl->strings[idx].string = + u16_strdup(ucs2->string_text); + if (!stbl->strings[idx].string) { + ret = EFI_OUT_OF_RESOURCES; + goto error; + } + idx++; + /* FIXME: accessing u16 * here */ + block = efi_hii_sibt_string_ucs2_block_next(ucs2); + break; + } + case EFI_HII_SIBT_END: + goto out; + default: + debug("unknown HII string block type: %02x\n", + block->block_type); + ret = EFI_INVALID_PARAMETER; + goto error; + } + } + +out: + list_add(&stbl->link, &hii->string_tables); + if (hii->max_string_id < nstrings) + hii->max_string_id = nstrings; + + return EFI_SUCCESS; + +error: + if (stbl) { + free(stbl->language); + if (idx > 0) + while (--idx >= 0) + free(stbl->strings[idx].string); + free(stbl->strings); + } + free(stbl); + + return ret; +} + +static struct efi_hii_packagelist *new_packagelist(void) +{ + struct efi_hii_packagelist *hii; + + hii = malloc(sizeof(*hii)); + hii->max_string_id = 0; + INIT_LIST_HEAD(&hii->string_tables); + + return hii; +} + +static void free_packagelist(struct efi_hii_packagelist *hii) +{ + remove_strings_package(hii); + + list_del(&hii->link); + free(hii); +} + +static efi_status_t +add_packages(struct efi_hii_packagelist *hii, + const struct efi_hii_package_list_header *package_list) +{ + struct efi_hii_package_header *package; + void *end; + efi_status_t ret = EFI_SUCCESS; + + end = ((void *)package_list) + + get_unaligned_le32(&package_list->package_length); + + debug("package_list: %pUl (%u)\n", &package_list->package_list_guid, + get_unaligned_le32(&package_list->package_length)); + + package = ((void *)package_list) + sizeof(*package_list); + while ((void *)package < end) { + debug("package=%p, package type=%x, length=%u\n", package, + efi_hii_package_type(package), + efi_hii_package_len(package)); + + switch (efi_hii_package_type(package)) { + case EFI_HII_PACKAGE_TYPE_GUID: + printf("\tGuid package not supported\n"); + ret = EFI_INVALID_PARAMETER; + break; + case EFI_HII_PACKAGE_FORMS: + printf("\tForm package not supported\n"); + ret = EFI_INVALID_PARAMETER; + break; + case EFI_HII_PACKAGE_STRINGS: + ret = add_strings_package(hii, + (struct efi_hii_strings_package *)package); + break; + case EFI_HII_PACKAGE_FONTS: + printf("\tFont package not supported\n"); + ret = EFI_INVALID_PARAMETER; + break; + case EFI_HII_PACKAGE_IMAGES: + printf("\tImage package not supported\n"); + ret = EFI_INVALID_PARAMETER; + break; + case EFI_HII_PACKAGE_SIMPLE_FONTS: + printf("\tSimple font package not supported\n"); + ret = EFI_INVALID_PARAMETER; + break; + case EFI_HII_PACKAGE_DEVICE_PATH: + printf("\tDevice path package not supported\n"); + ret = EFI_INVALID_PARAMETER; + break; + case EFI_HII_PACKAGE_KEYBOARD_LAYOUT: + printf("\tKeyboard layout package not supported\n"); + ret = EFI_INVALID_PARAMETER; + break; + case EFI_HII_PACKAGE_ANIMATIONS: + printf("\tAnimation package not supported\n"); + ret = EFI_INVALID_PARAMETER; + break; + case EFI_HII_PACKAGE_END: + goto out; + case EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN: + case EFI_HII_PACKAGE_TYPE_SYSTEM_END: + default: + break; + } + + if (ret != EFI_SUCCESS) + return ret; + + package = (void *)package + efi_hii_package_len(package); + } +out: + // TODO in theory there is some notifications that should be sent.. + return EFI_SUCCESS; +} + +/* + * EFI_HII_DATABASE_PROTOCOL + */ + +static efi_status_t EFIAPI +new_package_list(const struct efi_hii_database_protocol *this, + const struct efi_hii_package_list_header *package_list, + const efi_handle_t driver_handle, + efi_hii_handle_t *handle) +{ + struct efi_hii_packagelist *hii; + efi_status_t ret; + + EFI_ENTRY("%p, %p, %p, %p", this, package_list, driver_handle, handle); + + if (!package_list || !handle) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + hii = new_packagelist(); + if (!hii) + return EFI_EXIT(EFI_OUT_OF_RESOURCES); + + ret = add_packages(hii, package_list); + if (ret != EFI_SUCCESS) { + free_packagelist(hii); + return EFI_EXIT(ret); + } + + hii->driver_handle = driver_handle; + list_add_tail(&hii->link, &efi_package_lists); + *handle = hii; + + return EFI_EXIT(EFI_SUCCESS); +} + +static efi_status_t EFIAPI +remove_package_list(const struct efi_hii_database_protocol *this, + efi_hii_handle_t handle) +{ + struct efi_hii_packagelist *hii = handle; + + EFI_ENTRY("%p, %p", this, handle); + + if (!handle || !efi_hii_packagelist_exists(handle)) + return EFI_EXIT(EFI_NOT_FOUND); + + free_packagelist(hii); + + return EFI_EXIT(EFI_SUCCESS); +} + +static efi_status_t EFIAPI +update_package_list(const struct efi_hii_database_protocol *this, + efi_hii_handle_t handle, + const struct efi_hii_package_list_header *package_list) +{ + struct efi_hii_packagelist *hii = handle; + struct efi_hii_package_header *package; + void *end; + efi_status_t ret = EFI_SUCCESS; + + EFI_ENTRY("%p, %p, %p", this, handle, package_list); + + if (!handle || !efi_hii_packagelist_exists(handle)) + return EFI_EXIT(EFI_NOT_FOUND); + + if (!package_list) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + debug("package_list: %pUl (%u)\n", &package_list->package_list_guid, + get_unaligned_le32(&package_list->package_length)); + + package = ((void *)package_list) + sizeof(*package_list); + end = ((void *)package_list) + + get_unaligned_le32(&package_list->package_length); + + while ((void *)package < end) { + debug("package=%p, package type=%x, length=%u\n", package, + efi_hii_package_type(package), + efi_hii_package_len(package)); + + switch (efi_hii_package_type(package)) { + case EFI_HII_PACKAGE_TYPE_GUID: + printf("\tGuid package not supported\n"); + ret = EFI_INVALID_PARAMETER; + break; + case EFI_HII_PACKAGE_FORMS: + printf("\tForm package not supported\n"); + ret = EFI_INVALID_PARAMETER; + break; + case EFI_HII_PACKAGE_STRINGS: + remove_strings_package(hii); + break; + case EFI_HII_PACKAGE_FONTS: + printf("\tFont package not supported\n"); + ret = EFI_INVALID_PARAMETER; + break; + case EFI_HII_PACKAGE_IMAGES: + printf("\tImage package not supported\n"); + ret = EFI_INVALID_PARAMETER; + break; + case EFI_HII_PACKAGE_SIMPLE_FONTS: + printf("\tSimple font package not supported\n"); + ret = EFI_INVALID_PARAMETER; + break; + case EFI_HII_PACKAGE_DEVICE_PATH: + printf("\tDevice path package not supported\n"); + ret = EFI_INVALID_PARAMETER; + break; + case EFI_HII_PACKAGE_KEYBOARD_LAYOUT: + printf("\tKeyboard layout package not supported\n"); + break; + case EFI_HII_PACKAGE_ANIMATIONS: + printf("\tAnimation package not supported\n"); + ret = EFI_INVALID_PARAMETER; + break; + case EFI_HII_PACKAGE_END: + goto out; + case EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN: + case EFI_HII_PACKAGE_TYPE_SYSTEM_END: + default: + break; + } + + /* TODO: already removed some packages */ + if (ret != EFI_SUCCESS) + return EFI_EXIT(ret); + + package = ((void *)package) + + efi_hii_package_len(package); + } +out: + ret = add_packages(hii, package_list); + + return EFI_EXIT(ret); +} + +static efi_status_t EFIAPI +list_package_lists(const struct efi_hii_database_protocol *this, + u8 package_type, + const efi_guid_t *package_guid, + efi_uintn_t *handle_buffer_length, + efi_hii_handle_t *handle) +{ + struct efi_hii_packagelist *hii = + (struct efi_hii_packagelist *)handle; + int package_cnt, package_max; + efi_status_t ret = EFI_SUCCESS; + + EFI_ENTRY("%p, %u, %pUl, %p, %p", this, package_type, package_guid, + handle_buffer_length, handle); + + if (!handle_buffer_length || + (*handle_buffer_length && !handle)) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + if ((package_type != EFI_HII_PACKAGE_TYPE_GUID && package_guid) || + (package_type == EFI_HII_PACKAGE_TYPE_GUID && !package_guid)) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + debug("package type=%x, guid=%pUl, length=%lu\n", (int)package_type, + package_guid, *handle_buffer_length); + + package_cnt = 0; + package_max = *handle_buffer_length / sizeof(*handle); + list_for_each_entry(hii, &efi_package_lists, link) { + switch (package_type) { + case EFI_HII_PACKAGE_TYPE_ALL: + break; + case EFI_HII_PACKAGE_TYPE_GUID: + printf("\tGuid package not supported\n"); + ret = EFI_INVALID_PARAMETER; + continue; + case EFI_HII_PACKAGE_FORMS: + printf("\tForm package not supported\n"); + ret = EFI_INVALID_PARAMETER; + continue; + case EFI_HII_PACKAGE_STRINGS: + if (!list_empty(&hii->string_tables)) + break; + continue; + case EFI_HII_PACKAGE_FONTS: + printf("\tFont package not supported\n"); + ret = EFI_INVALID_PARAMETER; + continue; + case EFI_HII_PACKAGE_IMAGES: + printf("\tImage package not supported\n"); + ret = EFI_INVALID_PARAMETER; + continue; + case EFI_HII_PACKAGE_SIMPLE_FONTS: + printf("\tSimple font package not supported\n"); + ret = EFI_INVALID_PARAMETER; + continue; + case EFI_HII_PACKAGE_DEVICE_PATH: + printf("\tDevice path package not supported\n"); + ret = EFI_INVALID_PARAMETER; + continue; + case EFI_HII_PACKAGE_KEYBOARD_LAYOUT: + printf("\tKeyboard layout package not supported\n"); + continue; + case EFI_HII_PACKAGE_ANIMATIONS: + printf("\tAnimation package not supported\n"); + ret = EFI_INVALID_PARAMETER; + continue; + case EFI_HII_PACKAGE_END: + case EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN: + case EFI_HII_PACKAGE_TYPE_SYSTEM_END: + default: + continue; + } + + package_cnt++; + if (package_cnt <= package_max) + *handle++ = hii; + else + ret = EFI_BUFFER_TOO_SMALL; + } + *handle_buffer_length = package_cnt * sizeof(*handle); + + return EFI_EXIT(ret); +} + +static efi_status_t EFIAPI +export_package_lists(const struct efi_hii_database_protocol *this, + efi_hii_handle_t handle, + efi_uintn_t *buffer_size, + struct efi_hii_package_list_header *buffer) +{ + EFI_ENTRY("%p, %p, %p, %p", this, handle, buffer_size, buffer); + + if (!buffer_size || !buffer) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + return EFI_EXIT(EFI_NOT_FOUND); +} + +static efi_status_t EFIAPI +register_package_notify(const struct efi_hii_database_protocol *this, + u8 package_type, + const efi_guid_t *package_guid, + const void *package_notify_fn, + efi_uintn_t notify_type, + efi_handle_t *notify_handle) +{ + EFI_ENTRY("%p, %u, %pUl, %p, %zu, %p", this, package_type, + package_guid, package_notify_fn, notify_type, + notify_handle); + + if (!notify_handle) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + if ((package_type != EFI_HII_PACKAGE_TYPE_GUID && package_guid) || + (package_type == EFI_HII_PACKAGE_TYPE_GUID && !package_guid)) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + return EFI_EXIT(EFI_OUT_OF_RESOURCES); +} + +static efi_status_t EFIAPI +unregister_package_notify(const struct efi_hii_database_protocol *this, + efi_handle_t notification_handle) +{ + EFI_ENTRY("%p, %p", this, notification_handle); + + return EFI_EXIT(EFI_NOT_FOUND); +} + +static efi_status_t EFIAPI +find_keyboard_layouts(const struct efi_hii_database_protocol *this, + u16 *key_guid_buffer_length, + efi_guid_t *key_guid_buffer) +{ + EFI_ENTRY("%p, %p, %p", this, key_guid_buffer_length, key_guid_buffer); + + return EFI_EXIT(EFI_NOT_FOUND); +} + +static efi_status_t EFIAPI +get_keyboard_layout(const struct efi_hii_database_protocol *this, + efi_guid_t *key_guid, + u16 *keyboard_layout_length, + struct efi_hii_keyboard_layout *keyboard_layout) +{ + EFI_ENTRY("%p, %pUl, %p, %p", this, key_guid, keyboard_layout_length, + keyboard_layout); + + return EFI_EXIT(EFI_NOT_FOUND); +} + +static efi_status_t EFIAPI +set_keyboard_layout(const struct efi_hii_database_protocol *this, + efi_guid_t *key_guid) +{ + EFI_ENTRY("%p, %pUl", this, key_guid); + + return EFI_EXIT(EFI_NOT_FOUND); +} + +static efi_status_t EFIAPI +get_package_list_handle(const struct efi_hii_database_protocol *this, + efi_hii_handle_t package_list_handle, + efi_handle_t *driver_handle) +{ + struct efi_hii_packagelist *hii; + + EFI_ENTRY("%p, %p, %p", this, package_list_handle, driver_handle); + + if (!driver_handle) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + list_for_each_entry(hii, &efi_package_lists, link) { + if (hii == package_list_handle) { + *driver_handle = hii->driver_handle; + return EFI_EXIT(EFI_SUCCESS); + } + } + + return EFI_EXIT(EFI_NOT_FOUND); +} + +const struct efi_hii_database_protocol efi_hii_database = { + .new_package_list = new_package_list, + .remove_package_list = remove_package_list, + .update_package_list = update_package_list, + .list_package_lists = list_package_lists, + .export_package_lists = export_package_lists, + .register_package_notify = register_package_notify, + .unregister_package_notify = unregister_package_notify, + .find_keyboard_layouts = find_keyboard_layouts, + .get_keyboard_layout = get_keyboard_layout, + .set_keyboard_layout = set_keyboard_layout, + .get_package_list_handle = get_package_list_handle +}; + +/* + * EFI_HII_STRING_PROTOCOL + */ + +static bool language_match(char *language, char *languages) +{ + size_t n; + + n = strlen(language); + /* match primary language? */ + if (!strncasecmp(language, languages, n) && + (languages[n] == ';' || languages[n] == '\0')) + return true; + + return false; +} + +static efi_status_t EFIAPI +new_string(const struct efi_hii_string_protocol *this, + efi_hii_handle_t package_list, + efi_string_id_t *string_id, + const u8 *language, + const u16 *language_name, + const efi_string_t string, + const struct efi_font_info *string_font_info) +{ + struct efi_hii_packagelist *hii = package_list; + struct efi_string_table *stbl; + + EFI_ENTRY("%p, %p, %p, \"%s\", %p, \"%ls\", %p", this, package_list, + string_id, language, language_name, string, + string_font_info); + + if (!package_list || !efi_hii_packagelist_exists(package_list)) + return EFI_EXIT(EFI_NOT_FOUND); + + if (!string_id || !language || !string) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + list_for_each_entry(stbl, &hii->string_tables, link) { + if (language_match((char *)language, stbl->language)) { + efi_string_id_t new_id; + void *buf; + efi_string_t str; + + new_id = ++hii->max_string_id; + if (stbl->nstrings < new_id) { + buf = realloc(stbl->strings, + sizeof(stbl->strings[0]) + * new_id); + if (!buf) + return EFI_EXIT(EFI_OUT_OF_RESOURCES); + + memset(&stbl->strings[stbl->nstrings], 0, + (new_id - stbl->nstrings) + * sizeof(stbl->strings[0])); + stbl->strings = buf; + stbl->nstrings = new_id; + } + + str = u16_strdup(string); + if (!str) + return EFI_EXIT(EFI_OUT_OF_RESOURCES); + + stbl->strings[new_id - 1].string = str; + *string_id = new_id; + + return EFI_EXIT(EFI_SUCCESS); + } + } + + return EFI_EXIT(EFI_NOT_FOUND); +} + +static efi_status_t EFIAPI +get_string(const struct efi_hii_string_protocol *this, + const u8 *language, + efi_hii_handle_t package_list, + efi_string_id_t string_id, + efi_string_t string, + efi_uintn_t *string_size, + struct efi_font_info **string_font_info) +{ + struct efi_hii_packagelist *hii = package_list; + struct efi_string_table *stbl; + + EFI_ENTRY("%p, \"%s\", %p, %u, %p, %p, %p", this, language, + package_list, string_id, string, string_size, + string_font_info); + + if (!package_list || !efi_hii_packagelist_exists(package_list)) + return EFI_EXIT(EFI_NOT_FOUND); + + list_for_each_entry(stbl, &hii->string_tables, link) { + if (language_match((char *)language, stbl->language)) { + efi_string_t str; + size_t len; + + if (stbl->nstrings < string_id) + return EFI_EXIT(EFI_NOT_FOUND); + + str = stbl->strings[string_id - 1].string; + if (str) { + len = (u16_strlen(str) + 1) * sizeof(u16); + if (*string_size < len) { + *string_size = len; + + return EFI_EXIT(EFI_BUFFER_TOO_SMALL); + } + memcpy(string, str, len); + *string_size = len; + } else { + return EFI_EXIT(EFI_NOT_FOUND); + } + + return EFI_EXIT(EFI_SUCCESS); + } + } + + return EFI_EXIT(EFI_NOT_FOUND); +} + +static efi_status_t EFIAPI +set_string(const struct efi_hii_string_protocol *this, + efi_hii_handle_t package_list, + efi_string_id_t string_id, + const u8 *language, + const efi_string_t string, + const struct efi_font_info *string_font_info) +{ + struct efi_hii_packagelist *hii = package_list; + struct efi_string_table *stbl; + + EFI_ENTRY("%p, %p, %u, \"%s\", \"%ls\", %p", this, package_list, + string_id, language, string, string_font_info); + + if (!package_list || !efi_hii_packagelist_exists(package_list)) + return EFI_EXIT(EFI_NOT_FOUND); + + if (string_id > hii->max_string_id) + return EFI_EXIT(EFI_NOT_FOUND); + + if (!string || !language) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + list_for_each_entry(stbl, &hii->string_tables, link) { + if (language_match((char *)language, stbl->language)) { + efi_string_t str; + + if (hii->max_string_id < string_id) + return EFI_EXIT(EFI_NOT_FOUND); + + if (stbl->nstrings < string_id) { + void *buf; + + buf = realloc(stbl->strings, + string_id + * sizeof(stbl->strings[0])); + if (!buf) + return EFI_EXIT(EFI_OUT_OF_RESOURCES); + + memset(&stbl->strings[string_id - 1], 0, + (string_id - stbl->nstrings) + * sizeof(stbl->strings[0])); + stbl->strings = buf; + } + + str = u16_strdup(string); + if (!str) + return EFI_EXIT(EFI_OUT_OF_RESOURCES); + + free(stbl->strings[string_id - 1].string); + stbl->strings[string_id - 1].string = str; + + return EFI_EXIT(EFI_SUCCESS); + } + } + + return EFI_EXIT(EFI_NOT_FOUND); +} + +static efi_status_t EFIAPI +get_languages(const struct efi_hii_string_protocol *this, + efi_hii_handle_t package_list, + u8 *languages, + efi_uintn_t *languages_size) +{ + struct efi_hii_packagelist *hii = package_list; + struct efi_string_table *stbl; + size_t len = 0; + char *p; + + EFI_ENTRY("%p, %p, %p, %p", this, package_list, languages, + languages_size); + + if (!package_list || !efi_hii_packagelist_exists(package_list)) + return EFI_EXIT(EFI_NOT_FOUND); + + if (!languages_size || + (*languages_size && !languages)) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + /* figure out required size: */ + list_for_each_entry(stbl, &hii->string_tables, link) { + len += strlen((char *)stbl->language) + 1; + } + + if (*languages_size < len) { + *languages_size = len; + + return EFI_EXIT(EFI_BUFFER_TOO_SMALL); + } + + p = (char *)languages; + list_for_each_entry(stbl, &hii->string_tables, link) { + if (p != (char *)languages) + *p++ = ';'; + strcpy(p, stbl->language); + p += strlen((char *)stbl->language); + } + *p = '\0'; + + debug("languages: %s\n", languages); + + return EFI_EXIT(EFI_SUCCESS); +} + +static efi_status_t EFIAPI +get_secondary_languages(const struct efi_hii_string_protocol *this, + efi_hii_handle_t package_list, + const u8 *primary_language, + u8 *secondary_languages, + efi_uintn_t *secondary_languages_size) +{ + struct efi_hii_packagelist *hii = package_list; + struct efi_string_table *stbl; + bool found = false; + + EFI_ENTRY("%p, %p, \"%s\", %p, %p", this, package_list, + primary_language, secondary_languages, + secondary_languages_size); + + if (!package_list || !efi_hii_packagelist_exists(package_list)) + return EFI_EXIT(EFI_NOT_FOUND); + + if (!secondary_languages_size || + (*secondary_languages_size && !secondary_languages)) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + list_for_each_entry(stbl, &hii->string_tables, link) { + if (language_match((char *)primary_language, stbl->language)) { + found = true; + break; + } + } + if (!found) + return EFI_EXIT(EFI_INVALID_LANGUAGE); + + /* + * TODO: What is secondary language? + * *secondary_languages = '\0'; + * *secondary_languages_size = 0; + */ + + return EFI_EXIT(EFI_NOT_FOUND); +} + +const struct efi_hii_string_protocol efi_hii_string = { + .new_string = new_string, + .get_string = get_string, + .set_string = set_string, + .get_languages = get_languages, + .get_secondary_languages = get_secondary_languages +}; -- cgit v1.2.3 From 9ab0bdd9fe13d311269ddda60191cbc37136f998 Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Mon, 21 Jan 2019 12:12:58 +0900 Subject: efi: hii: add guid package support Allow for handling GUID package in HII database protocol. Signed-off-by: AKASHI Takahiro Signed-off-by: Alexander Graf --- include/efi_api.h | 9 +++++++++ lib/efi_loader/efi_hii.c | 48 ++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/include/efi_api.h b/include/efi_api.h index 347c7333c5e..6728f9a3270 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -744,6 +744,15 @@ struct efi_hii_package_header { #define EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN 0xE0 #define EFI_HII_PACKAGE_TYPE_SYSTEM_END 0xFF +/* + * HII GUID package + */ +struct efi_hii_guid_package { + struct efi_hii_package_header header; + efi_guid_t guid; + char data[]; +} __packed; + /* * HII string package */ diff --git a/lib/efi_loader/efi_hii.c b/lib/efi_loader/efi_hii.c index d6dba5719cd..d7cd0c4f0fc 100644 --- a/lib/efi_loader/efi_hii.c +++ b/lib/efi_loader/efi_hii.c @@ -23,6 +23,7 @@ struct efi_hii_packagelist { efi_handle_t driver_handle; u32 max_string_id; struct list_head string_tables; /* list of efi_string_table */ + struct list_head guid_list; /* we could also track fonts, images, etc */ }; @@ -80,6 +81,11 @@ struct efi_string_table { struct efi_string_info *strings; }; +struct efi_guid_data { + struct list_head link; + struct efi_hii_guid_package package; +}; + static void free_strings_table(struct efi_string_table *stbl) { int i; @@ -218,6 +224,35 @@ error: return ret; } +static void remove_guid_package(struct efi_hii_packagelist *hii) +{ + struct efi_guid_data *data; + + while (!list_empty(&hii->guid_list)) { + data = list_first_entry(&hii->guid_list, + struct efi_guid_data, link); + list_del(&data->link); + free(data); + } +} + +static efi_status_t +add_guid_package(struct efi_hii_packagelist *hii, + struct efi_hii_guid_package *package) +{ + struct efi_guid_data *data; + + data = calloc(sizeof(*data), 1); + if (!data) + return EFI_OUT_OF_RESOURCES; + + /* TODO: we don't know any about data field */ + memcpy(&data->package, package, sizeof(*package)); + list_add_tail(&data->link, &hii->guid_list); + + return EFI_SUCCESS; +} + static struct efi_hii_packagelist *new_packagelist(void) { struct efi_hii_packagelist *hii; @@ -225,6 +260,7 @@ static struct efi_hii_packagelist *new_packagelist(void) hii = malloc(sizeof(*hii)); hii->max_string_id = 0; INIT_LIST_HEAD(&hii->string_tables); + INIT_LIST_HEAD(&hii->guid_list); return hii; } @@ -232,6 +268,7 @@ static struct efi_hii_packagelist *new_packagelist(void) static void free_packagelist(struct efi_hii_packagelist *hii) { remove_strings_package(hii); + remove_guid_package(hii); list_del(&hii->link); free(hii); @@ -259,8 +296,8 @@ add_packages(struct efi_hii_packagelist *hii, switch (efi_hii_package_type(package)) { case EFI_HII_PACKAGE_TYPE_GUID: - printf("\tGuid package not supported\n"); - ret = EFI_INVALID_PARAMETER; + ret = add_guid_package(hii, + (struct efi_hii_guid_package *)package); break; case EFI_HII_PACKAGE_FORMS: printf("\tForm package not supported\n"); @@ -395,8 +432,7 @@ update_package_list(const struct efi_hii_database_protocol *this, switch (efi_hii_package_type(package)) { case EFI_HII_PACKAGE_TYPE_GUID: - printf("\tGuid package not supported\n"); - ret = EFI_INVALID_PARAMETER; + remove_guid_package(hii); break; case EFI_HII_PACKAGE_FORMS: printf("\tForm package not supported\n"); @@ -482,8 +518,8 @@ list_package_lists(const struct efi_hii_database_protocol *this, case EFI_HII_PACKAGE_TYPE_ALL: break; case EFI_HII_PACKAGE_TYPE_GUID: - printf("\tGuid package not supported\n"); - ret = EFI_INVALID_PARAMETER; + if (!list_empty(&hii->guid_list)) + break; continue; case EFI_HII_PACKAGE_FORMS: printf("\tForm package not supported\n"); -- cgit v1.2.3 From 8d3b77e36e10a94195642b351d4a85daab9e5fc5 Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Mon, 21 Jan 2019 12:12:59 +0900 Subject: efi: hii: add keyboard layout package support Allow for handling keyboard layout package in HII database protocol. A package can be added or deleted in HII database protocol, but we don't set 'current' keyboard layout as there is no driver that requests a keyboard layout. Signed-off-by: AKASHI Takahiro Signed-off-by: Alexander Graf --- include/efi_api.h | 6 ++ lib/efi_loader/efi_hii.c | 147 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 148 insertions(+), 5 deletions(-) diff --git a/include/efi_api.h b/include/efi_api.h index 6728f9a3270..03e95ec28ed 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -845,6 +845,12 @@ struct efi_hii_keyboard_layout { struct efi_key_descriptor descriptors[]; } __packed; +struct efi_hii_keyboard_package { + struct efi_hii_package_header header; + u16 layout_count; + struct efi_hii_keyboard_layout layout[]; +} __packed; + /* * HII protocols */ diff --git a/lib/efi_loader/efi_hii.c b/lib/efi_loader/efi_hii.c index d7cd0c4f0fc..89e1a6c2369 100644 --- a/lib/efi_loader/efi_hii.c +++ b/lib/efi_loader/efi_hii.c @@ -16,6 +16,7 @@ const efi_guid_t efi_guid_hii_database_protocol const efi_guid_t efi_guid_hii_string_protocol = EFI_HII_STRING_PROTOCOL_GUID; static LIST_HEAD(efi_package_lists); +static LIST_HEAD(efi_keyboard_layout_list); struct efi_hii_packagelist { struct list_head link; @@ -24,6 +25,7 @@ struct efi_hii_packagelist { u32 max_string_id; struct list_head string_tables; /* list of efi_string_table */ struct list_head guid_list; + struct list_head keyboard_packages; /* we could also track fonts, images, etc */ }; @@ -86,6 +88,17 @@ struct efi_guid_data { struct efi_hii_guid_package package; }; +struct efi_keyboard_layout_data { + struct list_head link; /* in package */ + struct list_head link_sys; /* in global list */ + struct efi_hii_keyboard_layout keyboard_layout; +}; + +struct efi_keyboard_package_data { + struct list_head link; /* in package_list */ + struct list_head keyboard_layout_list; +}; + static void free_strings_table(struct efi_string_table *stbl) { int i; @@ -253,6 +266,78 @@ add_guid_package(struct efi_hii_packagelist *hii, return EFI_SUCCESS; } +static void free_keyboard_layouts(struct efi_keyboard_package_data *package) +{ + struct efi_keyboard_layout_data *layout_data; + + while (!list_empty(&package->keyboard_layout_list)) { + layout_data = list_first_entry(&package->keyboard_layout_list, + struct efi_keyboard_layout_data, + link); + list_del(&layout_data->link); + list_del(&layout_data->link_sys); + free(layout_data); + } +} + +static void remove_keyboard_package(struct efi_hii_packagelist *hii) +{ + struct efi_keyboard_package_data *package; + + while (!list_empty(&hii->keyboard_packages)) { + package = list_first_entry(&hii->keyboard_packages, + struct efi_keyboard_package_data, + link); + free_keyboard_layouts(package); + list_del(&package->link); + free(package); + } +} + +static efi_status_t +add_keyboard_package(struct efi_hii_packagelist *hii, + struct efi_hii_keyboard_package *keyboard_package) +{ + struct efi_keyboard_package_data *package_data; + struct efi_hii_keyboard_layout *layout; + struct efi_keyboard_layout_data *layout_data; + u16 layout_count, layout_length; + int i; + + package_data = malloc(sizeof(*package_data)); + if (!package_data) + return EFI_OUT_OF_RESOURCES; + INIT_LIST_HEAD(&package_data->link); + INIT_LIST_HEAD(&package_data->keyboard_layout_list); + + layout = &keyboard_package->layout[0]; + layout_count = get_unaligned_le16(&keyboard_package->layout_count); + for (i = 0; i < layout_count; i++) { + layout_length = get_unaligned_le16(&layout->layout_length); + layout_data = malloc(sizeof(*layout_data) + layout_length); + if (!layout_data) + goto out; + + memcpy(&layout_data->keyboard_layout, layout, layout_length); + list_add_tail(&layout_data->link, + &package_data->keyboard_layout_list); + list_add_tail(&layout_data->link_sys, + &efi_keyboard_layout_list); + + layout += layout_length; + } + + list_add_tail(&package_data->link, &hii->keyboard_packages); + + return EFI_SUCCESS; + +out: + free_keyboard_layouts(package_data); + free(package_data); + + return EFI_OUT_OF_RESOURCES; +} + static struct efi_hii_packagelist *new_packagelist(void) { struct efi_hii_packagelist *hii; @@ -261,6 +346,7 @@ static struct efi_hii_packagelist *new_packagelist(void) hii->max_string_id = 0; INIT_LIST_HEAD(&hii->string_tables); INIT_LIST_HEAD(&hii->guid_list); + INIT_LIST_HEAD(&hii->keyboard_packages); return hii; } @@ -269,6 +355,7 @@ static void free_packagelist(struct efi_hii_packagelist *hii) { remove_strings_package(hii); remove_guid_package(hii); + remove_keyboard_package(hii); list_del(&hii->link); free(hii); @@ -324,8 +411,8 @@ add_packages(struct efi_hii_packagelist *hii, ret = EFI_INVALID_PARAMETER; break; case EFI_HII_PACKAGE_KEYBOARD_LAYOUT: - printf("\tKeyboard layout package not supported\n"); - ret = EFI_INVALID_PARAMETER; + ret = add_keyboard_package(hii, + (struct efi_hii_keyboard_package *)package); break; case EFI_HII_PACKAGE_ANIMATIONS: printf("\tAnimation package not supported\n"); @@ -458,7 +545,7 @@ update_package_list(const struct efi_hii_database_protocol *this, ret = EFI_INVALID_PARAMETER; break; case EFI_HII_PACKAGE_KEYBOARD_LAYOUT: - printf("\tKeyboard layout package not supported\n"); + remove_keyboard_package(hii); break; case EFI_HII_PACKAGE_ANIMATIONS: printf("\tAnimation package not supported\n"); @@ -546,7 +633,8 @@ list_package_lists(const struct efi_hii_database_protocol *this, ret = EFI_INVALID_PARAMETER; continue; case EFI_HII_PACKAGE_KEYBOARD_LAYOUT: - printf("\tKeyboard layout package not supported\n"); + if (!list_empty(&hii->keyboard_packages)) + break; continue; case EFI_HII_PACKAGE_ANIMATIONS: printf("\tAnimation package not supported\n"); @@ -620,9 +708,30 @@ find_keyboard_layouts(const struct efi_hii_database_protocol *this, u16 *key_guid_buffer_length, efi_guid_t *key_guid_buffer) { + struct efi_keyboard_layout_data *layout_data; + int package_cnt, package_max; + efi_status_t ret = EFI_SUCCESS; + EFI_ENTRY("%p, %p, %p", this, key_guid_buffer_length, key_guid_buffer); - return EFI_EXIT(EFI_NOT_FOUND); + if (!key_guid_buffer_length || + (*key_guid_buffer_length && !key_guid_buffer)) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + package_cnt = 0; + package_max = *key_guid_buffer_length / sizeof(*key_guid_buffer); + list_for_each_entry(layout_data, &efi_keyboard_layout_list, link_sys) { + package_cnt++; + if (package_cnt <= package_max) + memcpy(key_guid_buffer++, + &layout_data->keyboard_layout.guid, + sizeof(*key_guid_buffer)); + else + ret = EFI_BUFFER_TOO_SMALL; + } + *key_guid_buffer_length = package_cnt * sizeof(*key_guid_buffer); + + return EFI_EXIT(ret); } static efi_status_t EFIAPI @@ -631,10 +740,38 @@ get_keyboard_layout(const struct efi_hii_database_protocol *this, u16 *keyboard_layout_length, struct efi_hii_keyboard_layout *keyboard_layout) { + struct efi_keyboard_layout_data *layout_data; + u16 layout_length; + EFI_ENTRY("%p, %pUl, %p, %p", this, key_guid, keyboard_layout_length, keyboard_layout); + if (!keyboard_layout_length || + (*keyboard_layout_length && !keyboard_layout)) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + /* TODO: no notion of current keyboard layout */ + if (!key_guid) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + list_for_each_entry(layout_data, &efi_keyboard_layout_list, link_sys) { + if (!guidcmp(&layout_data->keyboard_layout.guid, key_guid)) + goto found; + } + return EFI_EXIT(EFI_NOT_FOUND); + +found: + layout_length = + get_unaligned_le16(&layout_data->keyboard_layout.layout_length); + if (*keyboard_layout_length < layout_length) { + *keyboard_layout_length = layout_length; + return EFI_EXIT(EFI_BUFFER_TOO_SMALL); + } + + memcpy(keyboard_layout, &layout_data->keyboard_layout, layout_length); + + return EFI_EXIT(EFI_SUCCESS); } static efi_status_t EFIAPI -- cgit v1.2.3 From cb728e51a77e515659f4834c2829a956b9f5c9f0 Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Mon, 21 Jan 2019 12:13:00 +0900 Subject: efi: hii: add HII config routing/access protocols This patch is a place holder for HII configuration routing protocol and HII configuration access protocol. Signed-off-by: AKASHI Takahiro Signed-off-by: Alexander Graf --- include/efi_api.h | 161 ++++++++++++++++++++++++++++++++++++++++ include/efi_loader.h | 4 + lib/efi_loader/Makefile | 2 +- lib/efi_loader/efi_boottime.c | 6 ++ lib/efi_loader/efi_hii_config.c | 146 ++++++++++++++++++++++++++++++++++++ 5 files changed, 318 insertions(+), 1 deletion(-) create mode 100644 lib/efi_loader/efi_hii_config.c diff --git a/include/efi_api.h b/include/efi_api.h index 03e95ec28ed..45ca05e8ac6 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -39,6 +39,9 @@ typedef void *efi_hii_handle_t; typedef u16 *efi_string_t; typedef u16 efi_string_id_t; typedef u32 efi_hii_font_style_t; +typedef u16 efi_question_id_t; +typedef u16 efi_image_id_t; +typedef u16 efi_form_id_t; #define EVT_TIMER 0x80000000 #define EVT_RUNTIME 0x40000000 @@ -799,6 +802,101 @@ efi_hii_sibt_string_ucs2_block_next(struct efi_hii_sibt_string_ucs2_block *blk) (u16_strlen(blk->string_text) + 1) * 2; } +/* + * HII forms package + * TODO: full scope of definitions + */ +struct efi_hii_time { + u8 hour; + u8 minute; + u8 second; +}; + +struct efi_hii_date { + u16 year; + u8 month; + u8 day; +}; + +struct efi_hii_ref { + efi_question_id_t question_id; + efi_form_id_t form_id; + efi_guid_t form_set_guid; + efi_string_id_t device_path; +}; + +union efi_ifr_type_value { + u8 u8; // EFI_IFR_TYPE_NUM_SIZE_8 + u16 u16; // EFI_IFR_TYPE_NUM_SIZE_16 + u32 u32; // EFI_IFR_TYPE_NUM_SIZE_32 + u64 u64; // EFI_IFR_TYPE_NUM_SIZE_64 + bool b; // EFI_IFR_TYPE_BOOLEAN + struct efi_hii_time time; // EFI_IFR_TYPE_TIME + struct efi_hii_date date; // EFI_IFR_TYPE_DATE + efi_string_id_t string; // EFI_IFR_TYPE_STRING, EFI_IFR_TYPE_ACTION + struct efi_hii_ref ref; // EFI_IFR_TYPE_REF + // u8 buffer[]; // EFI_IFR_TYPE_BUFFER +}; + +#define EFI_IFR_TYPE_NUM_SIZE_8 0x00 +#define EFI_IFR_TYPE_NUM_SIZE_16 0x01 +#define EFI_IFR_TYPE_NUM_SIZE_32 0x02 +#define EFI_IFR_TYPE_NUM_SIZE_64 0x03 +#define EFI_IFR_TYPE_BOOLEAN 0x04 +#define EFI_IFR_TYPE_TIME 0x05 +#define EFI_IFR_TYPE_DATE 0x06 +#define EFI_IFR_TYPE_STRING 0x07 +#define EFI_IFR_TYPE_OTHER 0x08 +#define EFI_IFR_TYPE_UNDEFINED 0x09 +#define EFI_IFR_TYPE_ACTION 0x0A +#define EFI_IFR_TYPE_BUFFER 0x0B +#define EFI_IFR_TYPE_REF 0x0C +#define EFI_IFR_OPTION_DEFAULT 0x10 +#define EFI_IFR_OPTION_DEFAULT_MFG 0x20 + +#define EFI_IFR_ONE_OF_OPTION_OP 0x09 + +struct efi_ifr_op_header { + u8 opCode; + u8 length:7; + u8 scope:1; +}; + +struct efi_ifr_one_of_option { + struct efi_ifr_op_header header; + efi_string_id_t option; + u8 flags; + u8 type; + union efi_ifr_type_value value; +}; + +typedef efi_uintn_t efi_browser_action_t; + +#define EFI_BROWSER_ACTION_REQUEST_NONE 0 +#define EFI_BROWSER_ACTION_REQUEST_RESET 1 +#define EFI_BROWSER_ACTION_REQUEST_SUBMIT 2 +#define EFI_BROWSER_ACTION_REQUEST_EXIT 3 +#define EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT 4 +#define EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT 5 +#define EFI_BROWSER_ACTION_REQUEST_FORM_APPLY 6 +#define EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD 7 +#define EFI_BROWSER_ACTION_REQUEST_RECONNECT 8 + +typedef efi_uintn_t efi_browser_action_request_t; + +#define EFI_BROWSER_ACTION_CHANGING 0 +#define EFI_BROWSER_ACTION_CHANGED 1 +#define EFI_BROWSER_ACTION_RETRIEVE 2 +#define EFI_BROWSER_ACTION_FORM_OPEN 3 +#define EFI_BROWSER_ACTION_FORM_CLOSE 4 +#define EFI_BROWSER_ACTION_SUBMITTED 5 +#define EFI_BROWSER_ACTION_DEFAULT_STANDARD 0x1000 +#define EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING 0x1001 +#define EFI_BROWSER_ACTION_DEFAULT_SAFE 0x1002 +#define EFI_BROWSER_ACTION_DEFAULT_PLATFORM 0x2000 +#define EFI_BROWSER_ACTION_DEFAULT_HARDWARE 0x3000 +#define EFI_BROWSER_ACTION_DEFAULT_FIRMWARE 0x4000 + /* * HII keyboard package */ @@ -958,6 +1056,69 @@ struct efi_hii_database_protocol { efi_handle_t *driver_handle); }; +#define EFI_HII_CONFIG_ROUTING_PROTOCOL_GUID \ + EFI_GUID(0x587e72d7, 0xcc50, 0x4f79, \ + 0x82, 0x09, 0xca, 0x29, 0x1f, 0xc1, 0xa1, 0x0f) + +struct efi_hii_config_routing_protocol { + efi_status_t(EFIAPI *extract_config)( + const struct efi_hii_config_routing_protocol *this, + const efi_string_t request, + efi_string_t *progress, + efi_string_t *results); + efi_status_t(EFIAPI *export_config)( + const struct efi_hii_config_routing_protocol *this, + efi_string_t *results); + efi_status_t(EFIAPI *route_config)( + const struct efi_hii_config_routing_protocol *this, + const efi_string_t configuration, + efi_string_t *progress); + efi_status_t(EFIAPI *block_to_config)( + const struct efi_hii_config_routing_protocol *this, + const efi_string_t config_request, + const uint8_t *block, + const efi_uintn_t block_size, + efi_string_t *config, + efi_string_t *progress); + efi_status_t(EFIAPI *config_to_block)( + const struct efi_hii_config_routing_protocol *this, + const efi_string_t config_resp, + const uint8_t *block, + const efi_uintn_t *block_size, + efi_string_t *progress); + efi_status_t(EFIAPI *get_alt_config)( + const struct efi_hii_config_routing_protocol *this, + const efi_string_t config_resp, + const efi_guid_t *guid, + const efi_string_t name, + const struct efi_device_path *device_path, + const efi_string_t alt_cfg_id, + efi_string_t *alt_cfg_resp); +}; + +#define EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID \ + EFI_GUID(0x330d4706, 0xf2a0, 0x4e4f, \ + 0xa3, 0x69, 0xb6, 0x6f, 0xa8, 0xd5, 0x43, 0x85) + +struct efi_hii_config_access_protocol { + efi_status_t(EFIAPI *extract_config_access)( + const struct efi_hii_config_access_protocol *this, + const efi_string_t request, + efi_string_t *progress, + efi_string_t *results); + efi_status_t(EFIAPI *route_config_access)( + const struct efi_hii_config_access_protocol *this, + const efi_string_t configuration, + efi_string_t *progress); + efi_status_t(EFIAPI *form_callback)( + const struct efi_hii_config_access_protocol *this, + efi_browser_action_t action, + efi_question_id_t question_id, + u8 type, + union efi_ifr_type_value *value, + efi_browser_action_request_t *action_request); +}; + #define EFI_GOP_GUID \ EFI_GUID(0x9042a9de, 0x23dc, 0x4a38, \ 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a) diff --git a/include/efi_loader.h b/include/efi_loader.h index 206f724bd9c..9dd933dae74 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -106,6 +106,8 @@ extern const struct efi_device_path_utilities_protocol /* Implementation of the EFI_UNICODE_COLLATION_PROTOCOL */ extern const struct efi_unicode_collation_protocol efi_unicode_collation_protocol; +extern const struct efi_hii_config_routing_protocol efi_hii_config_routing; +extern const struct efi_hii_config_access_protocol efi_hii_config_access; extern const struct efi_hii_database_protocol efi_hii_database; extern const struct efi_hii_string_protocol efi_hii_string; @@ -141,6 +143,8 @@ extern const efi_guid_t efi_file_system_info_guid; extern const efi_guid_t efi_guid_device_path_utilities_protocol; /* GUID of the Unicode collation protocol */ extern const efi_guid_t efi_guid_unicode_collation_protocol; +extern const efi_guid_t efi_guid_hii_config_routing_protocol; +extern const efi_guid_t efi_guid_hii_config_access_protocol; extern const efi_guid_t efi_guid_hii_database_protocol; extern const efi_guid_t efi_guid_hii_string_protocol; diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index 00128d417b9..4e90a35896c 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -24,7 +24,7 @@ obj-y += efi_device_path.o obj-y += efi_device_path_to_text.o obj-y += efi_device_path_utilities.o obj-y += efi_file.o -obj-y += efi_hii.o +obj-y += efi_hii.o efi_hii_config.o obj-y += efi_image_loader.o obj-y += efi_memory.o obj-y += efi_root_node.o diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 73af490377c..fc26d6adc11 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1570,6 +1570,12 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, if (ret != EFI_SUCCESS) goto failure; + ret = efi_add_protocol(&obj->header, + &efi_guid_hii_config_routing_protocol, + (void *)&efi_hii_config_routing); + if (ret != EFI_SUCCESS) + goto failure; + return ret; failure: printf("ERROR: Failure to install protocols for loaded image\n"); diff --git a/lib/efi_loader/efi_hii_config.c b/lib/efi_loader/efi_hii_config.c new file mode 100644 index 00000000000..f4b1f026c1b --- /dev/null +++ b/lib/efi_loader/efi_hii_config.c @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * EFI Human Interface Infrastructure ... Configuration + * + * Copyright (c) 2017 Leif Lindholm + * Copyright (c) 2018 AKASHI Takahiro, Linaro Limited + */ + +#include +#include + +const efi_guid_t efi_guid_hii_config_routing_protocol + = EFI_HII_CONFIG_ROUTING_PROTOCOL_GUID; +const efi_guid_t efi_guid_hii_config_access_protocol + = EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID; + +/* + * EFI_HII_CONFIG_ROUTING_PROTOCOL + */ + +static efi_status_t EFIAPI +extract_config(const struct efi_hii_config_routing_protocol *this, + const efi_string_t request, + efi_string_t *progress, + efi_string_t *results) +{ + EFI_ENTRY("%p, \"%ls\", %p, %p", this, request, progress, results); + + return EFI_EXIT(EFI_OUT_OF_RESOURCES); +} + +static efi_status_t EFIAPI +export_config(const struct efi_hii_config_routing_protocol *this, + efi_string_t *results) +{ + EFI_ENTRY("%p, %p", this, results); + + return EFI_EXIT(EFI_OUT_OF_RESOURCES); +} + +static efi_status_t EFIAPI +route_config(const struct efi_hii_config_routing_protocol *this, + const efi_string_t configuration, + efi_string_t *progress) +{ + EFI_ENTRY("%p, \"%ls\", %p", this, configuration, progress); + + return EFI_EXIT(EFI_OUT_OF_RESOURCES); +} + +static efi_status_t EFIAPI +block_to_config(const struct efi_hii_config_routing_protocol *this, + const efi_string_t config_request, + const u8 *block, + const efi_uintn_t block_size, + efi_string_t *config, + efi_string_t *progress) +{ + EFI_ENTRY("%p, \"%ls\", %p, %zu, %p, %p", this, config_request, + block, block_size, config, progress); + + return EFI_EXIT(EFI_OUT_OF_RESOURCES); +} + +static efi_status_t EFIAPI +config_to_block(const struct efi_hii_config_routing_protocol *this, + const efi_string_t config_resp, + const u8 *block, + const efi_uintn_t *block_size, + efi_string_t *progress) +{ + EFI_ENTRY("%p, \"%ls\", %p, %p, %p", this, config_resp, + block, block_size, progress); + + return EFI_EXIT(EFI_OUT_OF_RESOURCES); +} + +static efi_status_t EFIAPI +get_alt_config(const struct efi_hii_config_routing_protocol *this, + const efi_string_t config_resp, + const efi_guid_t *guid, + const efi_string_t name, + const struct efi_device_path *device_path, + const efi_string_t alt_cfg_id, + efi_string_t *alt_cfg_resp) +{ + EFI_ENTRY("%p, \"%ls\", %pUl, \"%ls\", %p, \"%ls\", %p", + this, config_resp, guid, name, device_path, + alt_cfg_id, alt_cfg_resp); + + return EFI_EXIT(EFI_OUT_OF_RESOURCES); +} + +/* + * EFI_HII_ACCESS_PROTOCOL + */ + +efi_status_t EFIAPI +extract_config_access(const struct efi_hii_config_access_protocol *this, + const efi_string_t request, + efi_string_t *progress, + efi_string_t *results) +{ + EFI_ENTRY("%p, \"%ls\", %p, %p", this, request, progress, results); + + return EFI_EXIT(EFI_OUT_OF_RESOURCES); +}; + +efi_status_t EFIAPI +route_config_access(const struct efi_hii_config_access_protocol *this, + const efi_string_t configuration, + efi_string_t *progress) +{ + EFI_ENTRY("%p, \"%ls\", %p", this, configuration, progress); + + return EFI_EXIT(EFI_OUT_OF_RESOURCES); +}; + +efi_status_t EFIAPI +form_callback(const struct efi_hii_config_access_protocol *this, + efi_browser_action_t action, + efi_question_id_t question_id, + u8 type, + union efi_ifr_type_value *value, + efi_browser_action_request_t *action_request) +{ + EFI_ENTRY("%p, 0x%lx, 0x%x, 0x%x, %p, %p", this, action, + question_id, type, value, action_request); + + return EFI_EXIT(EFI_DEVICE_ERROR); +}; + +const struct efi_hii_config_routing_protocol efi_hii_config_routing = { + .extract_config = extract_config, + .export_config = export_config, + .route_config = route_config, + .block_to_config = block_to_config, + .config_to_block = config_to_block, + .get_alt_config = get_alt_config +}; + +const struct efi_hii_config_access_protocol efi_hii_config_access = { + .extract_config_access = extract_config_access, + .route_config_access = route_config_access, + .form_callback = form_callback +}; -- cgit v1.2.3 From 4c4fb10da294ab46196c6f1daf8621f2451c88a5 Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Mon, 21 Jan 2019 12:13:01 +0900 Subject: efi_selftest: add HII database protocols test This efi_selftest tests HII database protocol and HII string protocol. Signed-off-by: AKASHI Takahiro Signed-off-by: Alexander Graf --- lib/efi_selftest/Makefile | 1 + lib/efi_selftest/efi_selftest_hii.c | 1046 ++++++++++++++++++++++++++++++ lib/efi_selftest/efi_selftest_hii_data.c | 453 +++++++++++++ 3 files changed, 1500 insertions(+) create mode 100644 lib/efi_selftest/efi_selftest_hii.c create mode 100644 lib/efi_selftest/efi_selftest_hii_data.c diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile index b3d3dadf597..779f5499406 100644 --- a/lib/efi_selftest/Makefile +++ b/lib/efi_selftest/Makefile @@ -25,6 +25,7 @@ efi_selftest_exception.o \ efi_selftest_exitbootservices.o \ efi_selftest_fdt.o \ efi_selftest_gop.o \ +efi_selftest_hii.o \ efi_selftest_loaded_image.o \ efi_selftest_manageprotocols.o \ efi_selftest_memory.o \ diff --git a/lib/efi_selftest/efi_selftest_hii.c b/lib/efi_selftest/efi_selftest_hii.c new file mode 100644 index 00000000000..16d7b608297 --- /dev/null +++ b/lib/efi_selftest/efi_selftest_hii.c @@ -0,0 +1,1046 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * efi_selftest_hii + * + * Copyright (c) 2018 AKASHI Takahiro, Linaro Limited + * + * Test HII database protocols + */ + +#include +#include +#include "efi_selftest_hii_data.c" + +#define PRINT_TESTNAME efi_st_printf("%s:\n", __func__) + +static struct efi_boot_services *boottime; + +static const efi_guid_t hii_database_protocol_guid = + EFI_HII_DATABASE_PROTOCOL_GUID; +static const efi_guid_t hii_string_protocol_guid = + EFI_HII_STRING_PROTOCOL_GUID; + +static struct efi_hii_database_protocol *hii_database_protocol; +static struct efi_hii_string_protocol *hii_string_protocol; + +/* + * Setup unit test. + * + * @handle: handle of the loaded image + * @systable: system table + * + * @return: EFI_ST_SUCCESS for success + */ +static int setup(const efi_handle_t handle, + const struct efi_system_table *systable) +{ + efi_status_t ret; + + boottime = systable->boottime; + + /* HII database protocol */ + ret = boottime->locate_protocol(&hii_database_protocol_guid, NULL, + (void **)&hii_database_protocol); + if (ret != EFI_SUCCESS) { + hii_database_protocol = NULL; + efi_st_error("HII database protocol is not available.\n"); + return EFI_ST_FAILURE; + } + + /* HII string protocol */ + ret = boottime->locate_protocol(&hii_string_protocol_guid, NULL, + (void **)&hii_string_protocol); + if (ret != EFI_SUCCESS) { + hii_string_protocol = NULL; + efi_st_error("HII string protocol is not available.\n"); + return EFI_ST_FAILURE; + } + + return EFI_ST_SUCCESS; +} + +/* + * HII database protocol tests + */ + +/** + * test_hii_database_new_package_list() - test creation and removal of + * package list + * + * This test adds a new package list and then tries to remove it using + * the provided handle. + * + * @Return: status code + */ +static int test_hii_database_new_package_list(void) +{ + efi_hii_handle_t handle; + efi_status_t ret; + + PRINT_TESTNAME; + ret = hii_database_protocol->new_package_list(hii_database_protocol, + (struct efi_hii_package_list_header *)packagelist1, + NULL, &handle); + if (ret != EFI_SUCCESS || !handle) { + efi_st_error("new_package_list returned %u\n", + (unsigned int)ret); + return EFI_ST_FAILURE; + } + + ret = hii_database_protocol->remove_package_list(hii_database_protocol, + handle); + if (ret != EFI_SUCCESS) { + efi_st_error("remove_package_list returned %u\n", + (unsigned int)ret); + return EFI_ST_FAILURE; + } + + return EFI_ST_SUCCESS; +} + +/** + * test_hii_database_update_package_list() - test update of package list + * + * This test adds a new package list and then tries to update it using + * another package list. + * + * @Return: status code + */ +static int test_hii_database_update_package_list(void) +{ + efi_hii_handle_t handle = NULL; + efi_status_t ret; + int result = EFI_ST_FAILURE; + + PRINT_TESTNAME; + ret = hii_database_protocol->new_package_list(hii_database_protocol, + (struct efi_hii_package_list_header *)packagelist1, + NULL, &handle); + if (ret != EFI_SUCCESS || !handle) { + efi_st_error("new_package_list returned %u\n", + (unsigned int)ret); + return EFI_ST_FAILURE; + } + + ret = hii_database_protocol->update_package_list(hii_database_protocol, + handle, + (struct efi_hii_package_list_header *)packagelist2); + if (ret != EFI_SUCCESS || !handle) { + efi_st_error("new_package_list returned %u\n", + (unsigned int)ret); + goto out; + } + + result = EFI_ST_SUCCESS; + +out: + if (handle) { + ret = hii_database_protocol->remove_package_list( + hii_database_protocol, handle); + if (ret != EFI_SUCCESS) { + efi_st_error("remove_package_list returned %u\n", + (unsigned int)ret); + return EFI_ST_FAILURE; + } + } + + return result; +} + +/** + * test_hii_database_list_package_lists() - test listing of package lists + * + * This test adds two package lists and then tries to enumerate them + * against different package types. We will get an array of handles. + * + * @Return: status code + */ +static int test_hii_database_list_package_lists(void) +{ + efi_hii_handle_t handle1 = NULL, handle2 = NULL, *handles; + efi_uintn_t handles_size; + efi_status_t ret; + int result = EFI_ST_FAILURE; + + PRINT_TESTNAME; + ret = hii_database_protocol->new_package_list(hii_database_protocol, + (struct efi_hii_package_list_header *)packagelist1, + NULL, &handle1); + if (ret != EFI_SUCCESS || !handle1) { + efi_st_error("new_package_list returned %u\n", + (unsigned int)ret); + goto out; + } + + ret = hii_database_protocol->new_package_list(hii_database_protocol, + (struct efi_hii_package_list_header *)packagelist2, + NULL, &handle2); + if (ret != EFI_SUCCESS || !handle2) { + efi_st_error("new_package_list returned %u\n", + (unsigned int)ret); + goto out; + } + + /* TYPE_ALL */ + handles = NULL; + handles_size = 0; + ret = hii_database_protocol->list_package_lists(hii_database_protocol, + EFI_HII_PACKAGE_TYPE_ALL, NULL, + &handles_size, handles); + if (ret != EFI_BUFFER_TOO_SMALL) { + efi_st_error("list_package_lists returned %u\n", + (unsigned int)ret); + goto out; + } + handles = malloc(handles_size); + if (!handles) { + efi_st_error("malloc failed\n"); + goto out; + } + ret = hii_database_protocol->list_package_lists(hii_database_protocol, + EFI_HII_PACKAGE_TYPE_ALL, NULL, + &handles_size, handles); + if (ret != EFI_SUCCESS) { + efi_st_error("list_package_lists returned %u\n", + (unsigned int)ret); + goto out; + } + efi_st_printf("list_package_lists returned %ld handles\n", + handles_size / sizeof(*handles)); + free(handles); + + /* STRINGS */ + handles = NULL; + handles_size = 0; + ret = hii_database_protocol->list_package_lists(hii_database_protocol, + EFI_HII_PACKAGE_STRINGS, NULL, + &handles_size, handles); + if (ret != EFI_BUFFER_TOO_SMALL) { + efi_st_error("list_package_lists returned %u\n", + (unsigned int)ret); + ret = EFI_ST_FAILURE; + goto out; + } + handles = malloc(handles_size); + if (!handles) { + efi_st_error("malloc failed\n"); + ret = EFI_ST_FAILURE; + goto out; + } + ret = hii_database_protocol->list_package_lists(hii_database_protocol, + EFI_HII_PACKAGE_STRINGS, NULL, + &handles_size, handles); + if (ret != EFI_SUCCESS) { + efi_st_error("list_package_lists returned %u\n", + (unsigned int)ret); + ret = EFI_ST_FAILURE; + goto out; + } + efi_st_printf("list_package_lists returned %ld strings handles\n", + handles_size / sizeof(*handles)); + free(handles); + + /* GUID */ + handles = NULL; + handles_size = 0; + ret = hii_database_protocol->list_package_lists(hii_database_protocol, + EFI_HII_PACKAGE_TYPE_GUID, &package_guid, + &handles_size, handles); + if (ret != EFI_BUFFER_TOO_SMALL) { + efi_st_error("list_package_lists returned %u\n", + (unsigned int)ret); + ret = EFI_ST_FAILURE; + goto out; + } + handles = malloc(handles_size); + if (!handles) { + efi_st_error("malloc failed\n"); + ret = EFI_ST_FAILURE; + goto out; + } + ret = hii_database_protocol->list_package_lists(hii_database_protocol, + EFI_HII_PACKAGE_TYPE_GUID, &package_guid, + &handles_size, handles); + if (ret != EFI_SUCCESS) { + efi_st_error("list_package_lists returned %u\n", + (unsigned int)ret); + ret = EFI_ST_FAILURE; + goto out; + } + efi_st_printf("list_package_lists returned %ld guid handles\n", + handles_size / sizeof(*handles)); + free(handles); + + /* KEYBOARD_LAYOUT */ + handles = NULL; + handles_size = 0; + ret = hii_database_protocol->list_package_lists(hii_database_protocol, + EFI_HII_PACKAGE_KEYBOARD_LAYOUT, NULL, + &handles_size, handles); + if (ret != EFI_BUFFER_TOO_SMALL) { + efi_st_error("list_package_lists returned %u\n", + (unsigned int)ret); + ret = EFI_ST_FAILURE; + goto out; + } + handles = malloc(handles_size); + if (!handles) { + efi_st_error("malloc failed\n"); + ret = EFI_ST_FAILURE; + goto out; + } + ret = hii_database_protocol->list_package_lists(hii_database_protocol, + EFI_HII_PACKAGE_KEYBOARD_LAYOUT, NULL, + &handles_size, handles); + if (ret != EFI_SUCCESS) { + efi_st_error("list_package_lists returned %u\n", + (unsigned int)ret); + ret = EFI_ST_FAILURE; + goto out; + } + efi_st_printf("list_package_lists returned %ld keyboard layout handles\n", + handles_size / sizeof(*handles)); + free(handles); + + result = EFI_ST_SUCCESS; + +out: + if (handle1) { + ret = hii_database_protocol->remove_package_list( + hii_database_protocol, handle1); + if (ret != EFI_SUCCESS) + efi_st_error("remove_package_list returned %u\n", + (unsigned int)ret); + } + if (handle2) { + ret = hii_database_protocol->remove_package_list( + hii_database_protocol, handle2); + if (ret != EFI_SUCCESS) + efi_st_error("remove_package_list returned %u\n", + (unsigned int)ret); + } + + return result; +} + +/** + * test_hii_database_export_package_lists() - test export of package lists + * + * @Return: status code + */ +static int test_hii_database_export_package_lists(void) +{ + PRINT_TESTNAME; + /* export_package_lists() not implemented yet */ + return EFI_ST_SUCCESS; +} + +/** + * test_hii_database_register_package_notify() - test registration of + * notification function + * + * @Return: status code + */ +static int test_hii_database_register_package_notify(void) +{ + PRINT_TESTNAME; + /* register_package_notify() not implemented yet */ + return EFI_ST_SUCCESS; +} + +/** + * test_hii_database_unregister_package_notify() - test removal of + * notification function + * + * @Return: status code + */ +static int test_hii_database_unregister_package_notify(void) +{ + PRINT_TESTNAME; + /* unregsiter_package_notify() not implemented yet */ + return EFI_ST_SUCCESS; +} + +/** + * test_hii_database_find_keyboard_layouts() - test listing of + * all the keyboard layouts in the system + * + * This test adds two package lists, each of which has two keyboard layouts + * and then tries to enumerate them. We will get an array of handles. + * + * @Return: status code + */ +static int test_hii_database_find_keyboard_layouts(void) +{ + efi_hii_handle_t handle1 = NULL, handle2 = NULL; + efi_guid_t *guids; + u16 guids_size; + efi_status_t ret; + int result = EFI_ST_FAILURE; + + PRINT_TESTNAME; + ret = hii_database_protocol->new_package_list(hii_database_protocol, + (struct efi_hii_package_list_header *)packagelist1, + NULL, &handle1); + if (ret != EFI_SUCCESS || !handle1) { + efi_st_error("new_package_list returned %u\n", + (unsigned int)ret); + goto out; + } + + ret = hii_database_protocol->new_package_list(hii_database_protocol, + (struct efi_hii_package_list_header *)packagelist2, + NULL, &handle2); + if (ret != EFI_SUCCESS || !handle2) { + efi_st_error("new_package_list returned %u\n", + (unsigned int)ret); + goto out; + } + + guids = NULL; + guids_size = 0; + ret = hii_database_protocol->find_keyboard_layouts( + hii_database_protocol, &guids_size, guids); + if (ret != EFI_BUFFER_TOO_SMALL) { + efi_st_error("find_keyboard_layouts returned %u\n", + (unsigned int)ret); + goto out; + } + guids = malloc(guids_size); + if (!guids) { + efi_st_error("malloc failed\n"); + goto out; + } + ret = hii_database_protocol->find_keyboard_layouts( + hii_database_protocol, &guids_size, guids); + if (ret != EFI_SUCCESS) { + efi_st_error("find_keyboard_layouts returned %u\n", + (unsigned int)ret); + goto out; + } + free(guids); + + efi_st_printf("find_keyboard_layouts returned %ld guids\n", + guids_size / sizeof(*guids)); + + result = EFI_ST_SUCCESS; + +out: + if (handle1) { + ret = hii_database_protocol->remove_package_list( + hii_database_protocol, handle1); + if (ret != EFI_SUCCESS) + efi_st_error("remove_package_list returned %u\n", + (unsigned int)ret); + } + if (handle2) { + ret = hii_database_protocol->remove_package_list( + hii_database_protocol, handle2); + if (ret != EFI_SUCCESS) + efi_st_error("remove_package_list returned %u\n", + (unsigned int)ret); + } + + return result; +} + +/** + * test_hii_database_get_keyboard_layout() - test retrieval of keyboard layout + * + * This test adds two package lists, each of which has two keyboard layouts + * and then tries to get a handle to keyboard layout with a specific guid + * and the current one. + * + * @Return: status code + */ +static int test_hii_database_get_keyboard_layout(void) +{ + efi_hii_handle_t handle1 = NULL, handle2 = NULL; + struct efi_hii_keyboard_layout *kb_layout; + u16 kb_layout_size; + efi_status_t ret; + int result = EFI_ST_FAILURE; + + PRINT_TESTNAME; + ret = hii_database_protocol->new_package_list(hii_database_protocol, + (struct efi_hii_package_list_header *)packagelist1, + NULL, &handle1); + if (ret != EFI_SUCCESS || !handle1) { + efi_st_error("new_package_list returned %u\n", + (unsigned int)ret); + goto out; + } + + ret = hii_database_protocol->new_package_list(hii_database_protocol, + (struct efi_hii_package_list_header *)packagelist2, + NULL, &handle2); + if (ret != EFI_SUCCESS || !handle2) { + efi_st_error("new_package_list returned %u\n", + (unsigned int)ret); + goto out; + } + + /* specific keyboard_layout(guid11) */ + kb_layout = NULL; + kb_layout_size = 0; + ret = hii_database_protocol->get_keyboard_layout(hii_database_protocol, + &kb_layout_guid11, &kb_layout_size, kb_layout); + if (ret != EFI_BUFFER_TOO_SMALL) { + efi_st_error("get_keyboard_layout returned %u\n", + (unsigned int)ret); + goto out; + } + kb_layout = malloc(kb_layout_size); + if (!kb_layout) { + efi_st_error("malloc failed\n"); + goto out; + } + ret = hii_database_protocol->get_keyboard_layout(hii_database_protocol, + &kb_layout_guid11, &kb_layout_size, kb_layout); + if (ret != EFI_SUCCESS) { + efi_st_error("get_keyboard_layout returned %u\n", + (unsigned int)ret); + goto out; + } + free(kb_layout); + + /* current */ + kb_layout = NULL; + kb_layout_size = 0; + ret = hii_database_protocol->get_keyboard_layout(hii_database_protocol, + NULL, &kb_layout_size, kb_layout); + if (ret != EFI_INVALID_PARAMETER) { + efi_st_error("get_keyboard_layout returned %u\n", + (unsigned int)ret); + goto out; + } + + result = EFI_ST_SUCCESS; + +out: + if (handle1) { + ret = hii_database_protocol->remove_package_list( + hii_database_protocol, handle1); + if (ret != EFI_SUCCESS) + efi_st_error("remove_package_list returned %u\n", + (unsigned int)ret); + } + if (handle2) { + ret = hii_database_protocol->remove_package_list( + hii_database_protocol, handle2); + if (ret != EFI_SUCCESS) + efi_st_error("remove_package_list returned %u\n", + (unsigned int)ret); + } + + return result; +} + +/** + * test_hii_database_set_keyboard_layout() - test change of + * current keyboard layout + * + * @Return: status code + */ +static int test_hii_database_set_keyboard_layout(void) +{ + PRINT_TESTNAME; + /* set_keyboard_layout() not implemented yet */ + return EFI_ST_SUCCESS; +} + +/** + * test_hii_database_get_package_list_handle() - test retrieval of + * driver associated with a package list + * + * This test adds a package list, and then tries to get a handle to driver + * which is associated with a package list. + * + * @Return: status code + */ +static int test_hii_database_get_package_list_handle(void) +{ + efi_hii_handle_t handle = NULL; + efi_handle_t driver_handle; + efi_status_t ret; + int result = EFI_ST_FAILURE; + + PRINT_TESTNAME; + driver_handle = (efi_handle_t)0x12345678; /* dummy */ + ret = hii_database_protocol->new_package_list(hii_database_protocol, + (struct efi_hii_package_list_header *)packagelist1, + driver_handle, &handle); + if (ret != EFI_SUCCESS || !handle) { + efi_st_error("new_package_list returned %u\n", + (unsigned int)ret); + return EFI_ST_FAILURE; + } + + driver_handle = NULL; + ret = hii_database_protocol->get_package_list_handle( + hii_database_protocol, handle, &driver_handle); + if (ret != EFI_SUCCESS || driver_handle != (efi_handle_t)0x12345678) { + efi_st_error("get_package_list_handle returned %u, driver:%p\n", + (unsigned int)ret, driver_handle); + goto out; + } + + result = EFI_ST_SUCCESS; + +out: + if (handle) { + ret = hii_database_protocol->remove_package_list( + hii_database_protocol, handle); + if (ret != EFI_SUCCESS) { + efi_st_error("remove_package_list returned %u\n", + (unsigned int)ret); + return EFI_ST_FAILURE; + } + } + + return result; +} + +static int test_hii_database_protocol(void) +{ + int ret; + + ret = test_hii_database_new_package_list(); + if (ret != EFI_ST_SUCCESS) + return EFI_ST_FAILURE; + + ret = test_hii_database_update_package_list(); + if (ret != EFI_ST_SUCCESS) + return EFI_ST_FAILURE; + + ret = test_hii_database_list_package_lists(); + if (ret != EFI_ST_SUCCESS) + return EFI_ST_FAILURE; + + ret = test_hii_database_export_package_lists(); + if (ret != EFI_ST_SUCCESS) + return EFI_ST_FAILURE; + + ret = test_hii_database_register_package_notify(); + if (ret != EFI_ST_SUCCESS) + return EFI_ST_FAILURE; + + ret = test_hii_database_unregister_package_notify(); + if (ret != EFI_ST_SUCCESS) + return EFI_ST_FAILURE; + + ret = test_hii_database_find_keyboard_layouts(); + if (ret != EFI_ST_SUCCESS) + return EFI_ST_FAILURE; + + ret = test_hii_database_get_keyboard_layout(); + if (ret != EFI_ST_SUCCESS) + return EFI_ST_FAILURE; + + ret = test_hii_database_set_keyboard_layout(); + if (ret != EFI_ST_SUCCESS) + return EFI_ST_FAILURE; + + ret = test_hii_database_get_package_list_handle(); + if (ret != EFI_ST_SUCCESS) + return EFI_ST_FAILURE; + + return EFI_ST_SUCCESS; +} + +/* + * HII string protocol tests + */ + +/** + * test_hii_string_new_string() - test creation of a new string entry + * + * This test adds a package list, and then tries to add a new string + * entry for a specific language. + * + * @Return: status code + */ +static int test_hii_string_new_string(void) +{ + efi_hii_handle_t handle = NULL; + efi_string_id_t id; + efi_status_t ret; + int result = EFI_ST_FAILURE; + + PRINT_TESTNAME; + ret = hii_database_protocol->new_package_list(hii_database_protocol, + (struct efi_hii_package_list_header *)packagelist1, + NULL, &handle); + if (ret != EFI_SUCCESS || !handle) { + efi_st_error("new_package_list returned %u\n", + (unsigned int)ret); + return EFI_ST_FAILURE; + } + + ret = hii_string_protocol->new_string(hii_string_protocol, handle, + &id, (u8 *)"en-US", + L"Japanese", L"Japanese", NULL); + if (ret != EFI_SUCCESS) { + efi_st_error("new_string returned %u\n", + (unsigned int)ret); + goto out; + } + efi_st_printf("new string id is %u\n", id); + + result = EFI_ST_SUCCESS; + +out: + if (handle) { + ret = hii_database_protocol->remove_package_list( + hii_database_protocol, handle); + if (ret != EFI_SUCCESS) { + efi_st_error("remove_package_list returned %u\n", + (unsigned int)ret); + return EFI_ST_FAILURE; + } + } + + return result; +} + +/** + * test_hii_string_get_string() - test retrieval of a string entry + * + * This test adds a package list, create a new string entry and then tries + * to get it with its string id. + * + * @Return: status code + */ +static int test_hii_string_get_string(void) +{ + efi_hii_handle_t handle = NULL; + efi_string_id_t id; + efi_string_t string; + efi_uintn_t string_len; + efi_status_t ret; + int result = EFI_ST_FAILURE; + + PRINT_TESTNAME; + ret = hii_database_protocol->new_package_list(hii_database_protocol, + (struct efi_hii_package_list_header *)packagelist1, + NULL, &handle); + if (ret != EFI_SUCCESS || !handle) { + efi_st_error("new_package_list returned %u\n", + (unsigned int)ret); + return EFI_ST_FAILURE; + } + + ret = hii_string_protocol->new_string(hii_string_protocol, handle, + &id, (u8 *)"en-US", + L"Japanese", L"Japanese", NULL); + if (ret != EFI_SUCCESS) { + efi_st_error("new_string returned %u\n", + (unsigned int)ret); + goto out; + } + + string = NULL; + string_len = 0; + ret = hii_string_protocol->get_string(hii_string_protocol, + (u8 *)"en-US", handle, id, string, &string_len, NULL); + if (ret != EFI_BUFFER_TOO_SMALL) { + efi_st_error("get_string returned %u\n", + (unsigned int)ret); + goto out; + } + string_len += sizeof(u16); + string = malloc(string_len); + if (!string) { + efi_st_error("malloc failed\n"); + goto out; + } + ret = hii_string_protocol->get_string(hii_string_protocol, + (u8 *)"en-US", handle, id, string, &string_len, NULL); + if (ret != EFI_SUCCESS) { + efi_st_error("get_string returned %u\n", + (unsigned int)ret); + goto out; + } + +#if 1 + u16 *c1, *c2; + + for (c1 = string, c2 = L"Japanese"; *c1 == *c2; c1++, c2++) + ; + if (!*c1 && !*c2) + result = EFI_ST_SUCCESS; + else + result = EFI_ST_FAILURE; +#else + /* TODO: %ls */ + efi_st_printf("got string is %s (can be wrong)\n", string); +#endif + + result = EFI_ST_SUCCESS; + +out: + if (handle) { + ret = hii_database_protocol->remove_package_list( + hii_database_protocol, handle); + if (ret != EFI_SUCCESS) { + efi_st_error("remove_package_list returned %u\n", + (unsigned int)ret); + return EFI_ST_FAILURE; + } + } + + return result; +} + +/** + * test_hii_string_set_string() - test change of a string entry + * + * This test adds a package list, create a new string entry and then tries + * to modify it. + * + * @Return: status code + */ +static int test_hii_string_set_string(void) +{ + efi_hii_handle_t handle = NULL; + efi_string_id_t id; + efi_status_t ret; + int result = EFI_ST_FAILURE; + + PRINT_TESTNAME; + ret = hii_database_protocol->new_package_list(hii_database_protocol, + (struct efi_hii_package_list_header *)packagelist1, + NULL, &handle); + if (ret != EFI_SUCCESS || !handle) { + efi_st_error("new_package_list returned %u\n", + (unsigned int)ret); + return EFI_ST_FAILURE; + } + + ret = hii_string_protocol->new_string(hii_string_protocol, handle, + &id, (u8 *)"en-US", + L"Japanese", L"Japanese", NULL); + if (ret != EFI_SUCCESS) { + efi_st_error("new_string returned %u\n", + (unsigned int)ret); + goto out; + } + + ret = hii_string_protocol->set_string(hii_string_protocol, handle, + id, (u8 *)"en-US", + L"Nihongo", NULL); + if (ret != EFI_SUCCESS) { + efi_st_error("set_string returned %u\n", + (unsigned int)ret); + goto out; + } + + result = EFI_ST_SUCCESS; + +out: + if (handle) { + ret = hii_database_protocol->remove_package_list( + hii_database_protocol, handle); + if (ret != EFI_SUCCESS) { + efi_st_error("remove_package_list returned %u\n", + (unsigned int)ret); + return EFI_ST_FAILURE; + } + } + + return result; +} + +/** + * test_hii_string_get_languages() - test listing of languages + * + * This test adds a package list, and then tries to enumerate languages + * in it. We will get an string of language names. + * + * @Return: status code + */ +static int test_hii_string_get_languages(void) +{ + efi_hii_handle_t handle = NULL; + u8 *languages; + efi_uintn_t languages_len; + efi_status_t ret; + int result = EFI_ST_FAILURE; + + PRINT_TESTNAME; + ret = hii_database_protocol->new_package_list(hii_database_protocol, + (struct efi_hii_package_list_header *)packagelist1, + NULL, &handle); + if (ret != EFI_SUCCESS || !handle) { + efi_st_error("new_package_list returned %u\n", + (unsigned int)ret); + return EFI_ST_FAILURE; + } + + languages = NULL; + languages_len = 0; + ret = hii_string_protocol->get_languages(hii_string_protocol, handle, + languages, &languages_len); + if (ret != EFI_BUFFER_TOO_SMALL) { + efi_st_error("get_languages returned %u\n", + (unsigned int)ret); + goto out; + } + languages = malloc(languages_len); + if (!languages) { + efi_st_error("malloc failed\n"); + goto out; + } + ret = hii_string_protocol->get_languages(hii_string_protocol, handle, + languages, &languages_len); + if (ret != EFI_SUCCESS) { + efi_st_error("get_languages returned %u\n", + (unsigned int)ret); + goto out; + } + + efi_st_printf("got languages are %s\n", languages); + + result = EFI_ST_SUCCESS; + +out: + if (handle) { + ret = hii_database_protocol->remove_package_list( + hii_database_protocol, handle); + if (ret != EFI_SUCCESS) { + efi_st_error("remove_package_list returned %u\n", + (unsigned int)ret); + return EFI_ST_FAILURE; + } + } + + return result; +} + +/** + * test_hii_string_get_secondary_languages() - test listing of secondary + * languages + * + * This test adds a package list, and then tries to enumerate secondary + * languages with a specific language. We will get an string of language names. + * + * @Return: status code + */ +static int test_hii_string_get_secondary_languages(void) +{ + efi_hii_handle_t handle = NULL; + u8 *languages; + efi_uintn_t languages_len; + efi_status_t ret; + int result = EFI_ST_FAILURE; + + PRINT_TESTNAME; + ret = hii_database_protocol->new_package_list(hii_database_protocol, + (struct efi_hii_package_list_header *)packagelist1, + NULL, &handle); + if (ret != EFI_SUCCESS || !handle) { + efi_st_error("new_package_list returned %u\n", + (unsigned int)ret); + return EFI_ST_FAILURE; + } + + languages = NULL; + languages_len = 0; + ret = hii_string_protocol->get_secondary_languages(hii_string_protocol, + handle, (u8 *)"en-US", languages, &languages_len); + if (ret == EFI_NOT_FOUND) { + efi_st_printf("no secondary languages\n"); + result = EFI_ST_SUCCESS; + goto out; + } + if (ret != EFI_BUFFER_TOO_SMALL) { + efi_st_error("get_secondary_languages returned %u\n", + (unsigned int)ret); + goto out; + } + languages = malloc(languages_len); + if (!languages) { + efi_st_error("malloc failed\n"); + goto out; + } + ret = hii_string_protocol->get_secondary_languages(hii_string_protocol, + handle, (u8 *)"en-US", languages, &languages_len); + if (ret != EFI_SUCCESS) { + efi_st_error("get_secondary_languages returned %u\n", + (unsigned int)ret); + goto out; + } + + efi_st_printf("got secondary languages are %s\n", languages); + + result = EFI_ST_SUCCESS; + +out: + if (handle) { + ret = hii_database_protocol->remove_package_list( + hii_database_protocol, handle); + if (ret != EFI_SUCCESS) { + efi_st_error("remove_package_list returned %u\n", + (unsigned int)ret); + return EFI_ST_FAILURE; + } + } + + return result; +} + +static int test_hii_string_protocol(void) +{ + int ret; + + ret = test_hii_string_new_string(); + if (ret != EFI_ST_SUCCESS) + return EFI_ST_FAILURE; + + ret = test_hii_string_get_string(); + if (ret != EFI_ST_SUCCESS) + return EFI_ST_FAILURE; + + ret = test_hii_string_set_string(); + if (ret != EFI_ST_SUCCESS) + return EFI_ST_FAILURE; + + ret = test_hii_string_get_languages(); + if (ret != EFI_ST_SUCCESS) + return EFI_ST_FAILURE; + + ret = test_hii_string_get_secondary_languages(); + if (ret != EFI_ST_SUCCESS) + return EFI_ST_FAILURE; + + return EFI_ST_SUCCESS; +} + +/* + * Execute unit test. + * + * @return: EFI_ST_SUCCESS for success, EFI_ST_FAILURE for failure + */ +static int execute(void) +{ + int ret; + + /* HII database protocol */ + ret = test_hii_database_protocol(); + if (ret != EFI_ST_SUCCESS) + return EFI_ST_FAILURE; + + /* HII string protocol */ + ret = test_hii_string_protocol(); + if (ret != EFI_ST_SUCCESS) + return EFI_ST_FAILURE; + + return EFI_ST_SUCCESS; +} + +EFI_UNIT_TEST(hii) = { + .name = "HII database protocols", + .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, + .setup = setup, + .execute = execute, +}; diff --git a/lib/efi_selftest/efi_selftest_hii_data.c b/lib/efi_selftest/efi_selftest_hii_data.c new file mode 100644 index 00000000000..d19f0682afd --- /dev/null +++ b/lib/efi_selftest/efi_selftest_hii_data.c @@ -0,0 +1,453 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * This file's test data is derived from UEFI SCT. + * The original copyright is attached below. + */ + +/* + * Copyright 2006 - 2016 Unified EFI, Inc.
+ * Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.
+ * + * This program and the accompanying materials + * are licensed and made available under the terms and conditions of the BSD + * License which accompanies this distribution. The full text of the license + * may be found at + * http://opensource.org/licenses/bsd-license.php + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + */ + +#include + +#ifdef NOT_USED +/* + * TODO: These macro's are not used as they appear only in + * "#ifdef NOT_USED" clauses. In the future, define them elsewhere. + */ + +/* HII form */ +#define EFI_IFR_AND_OP 0x15 +#define EFI_IFR_END_OP 0x29 +#define EFI_IFR_BITWISE_AND_OP 0x35 + +/* HII image */ +#define EFI_HII_IIBT_END 0x00 +#define EFI_HII_IIBT_IMAGE_1BIT 0x10 +#endif + +/* HII keyboard layout */ +#define EFI_NULL_MODIFIER 0x0000 + +u8 packagelist1[] = { + // EFI_HII_PACKAGE_LIST_HEADER, length = 20 + // SimpleFont, Font, GUID, Form, String, Image, DevicePath, + // (74) (110) 20 (8) 78 (67) (8) + // KeyboardLayout, End + // 192 4 + + 0x89, 0xcd, 0xab, 0x03, 0xf4, 0x03, 0x44, 0x70, + 0x81, 0xde, 0x99, 0xb1, 0x81, 0x20, 0xf7, 0x68, //16: guid + 0x3a, 0x01, 0x00, 0x00, // 4: total 314(0x13a) +#ifdef NOT_USED /* TODO: simple font package not implemented yet */ + // + // Simple Font Package 1, length = 74 + // + 0x4A, 0x00, 0x00, + EFI_HII_PACKAGE_SIMPLE_FONTS, + 1, 0, + 1, 0, + 0x55, 0x0, 0x1, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 0x77, 0x0, 0x2, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 0, 0, 0, + // + // Font Package 1, length = 110 + // + 0x6e, 0x00, 0x00, // 3 + EFI_HII_PACKAGE_FONTS, // 1 + 0x5c, 0x00, 0x00, 0x00, // 4: size of header + 0x5c, 0x00, 0x00, 0x00, // 4: offset + 0xf1, 0x00, 0xf2, 0x00, 0xf3, 0x00, 0xf4, 0x00, + 0xf5, 0x00, 0xec, 0xec, //10+2(pads) + 0xff, 0x33, 0xff, 0x44, // 4: font style + 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, //64 + // + // Glyph block 1, length = 18 + // + EFI_HII_GIBT_GLYPH_DEFAULT, // 1 + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x99, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, //16: BitMapData + EFI_HII_GIBT_END, // 1 +#endif + // + // Guid Package 1, length = 20 + // + 0x14, 0x00, 0x00, // 3 + EFI_HII_PACKAGE_TYPE_GUID, // 1 + 0x5a, 0xc9, 0x87, 0x03, 0x3, 0xd7, 0x46, 0x23, + 0xb2, 0xab, 0xd0, 0xc7, 0xdd, 0x90, 0x44, 0xf8, //16: guid +#ifdef NOT_USED /* TODO: form package not implemented yet */ + // + // EFI_HII_PACKAGE_FORMS, length = 8 + // + 0x08, 0x00, 0x00, // 3 + EFI_HII_PACKAGE_FORMS, // 1 + // + // Opcode 1, length = 4 + // + EFI_IFR_AND_OP, + 0x82, + EFI_IFR_END_OP, + 0x02, + // +#endif + // EFI_HII_PACKAGE_STRINGS, length = 78 + // + 0x4e, 0x00, 0x00, // 3: length(header) + EFI_HII_PACKAGE_STRINGS, // 1: type(header) + 0x3c, 0x00, 0x00, 0x00, // 4: header_size + 0x3c, 0x00, 0x00, 0x00, // 4: string_offset + 0x00, 0x00, 0x11, 0x22, 0x44, 0x55, 0x77, 0x89, //32: language_window + 0x11, 0x00, 0x11, 0x22, 0x44, 0x55, 0x87, 0x89, + 0x22, 0x00, 0x11, 0x22, 0x44, 0x55, 0x77, 0x89, + 0x33, 0x00, 0x11, 0x22, 0x44, 0x55, 0x77, 0x89, + 0x01, 0x00, // 2: language name + 0x65, 0x6e, 0x2d, 0x55, 0x53, 0x3b, 0x7a, 0x68, //14: language + 0x2d, 0x48, 0x61, 0x6e, 0x74, 0x00, // "en-US;zh-Hant" + EFI_HII_SIBT_STRING_UCS2, // 1 + 0x45, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x6C, 0x00, + 0x69, 0x00, 0x73, 0x00, 0x68, 0x00, 0x00, 0x00, //16: "English" + EFI_HII_SIBT_END, // 1 +#ifdef NOT_USED /* TODO: image package not implemented yet */ + // + // EFI_HII_PACKAGE_IMAGES, length = 67 + // + 0x43, 0x00, 0x00, // 3 + EFI_HII_PACKAGE_IMAGES, // 1 + 0x0c, 0x00, 0x00, 0x00, // 4: image info offset + 0x39, 0x00, 0x00, 0x00, // 4: palette info offset + EFI_HII_IIBT_IMAGE_1BIT, // 1 + 0x01, + 0x0b, 0x00, + 0x13, 0x00, + 0x80, 0x00, + 0xc0, 0x00, + 0xe0, 0x00, + 0xf0, 0x00, + 0xf8, 0x00, + 0xfc, 0x00, + 0xfe, 0x00, + 0xff, 0x00, + 0xff, 0x80, + 0xff, 0xc0, + 0xff, 0xe0, + 0xfe, 0x00, + 0xef, 0x00, + 0xcf, 0x00, + 0x87, 0x80, + 0x07, 0x80, + 0x03, 0xc0, + 0x03, 0xc0, + 0x01, 0x80, //43 + EFI_HII_IIBT_END, // 1 + 0x01, 0x00, + 0x06, 0x00, + 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, //10 + // + // EFI_HII_PACKAGE_DEVICE_PATH, length = 8 + // + 0x08, 0x00, 0x00, // 3 + EFI_HII_PACKAGE_DEVICE_PATH, // 1 + 0x01, 0x23, 0x45, 0x66, // 4: dummy device path protocol + // instance address +#endif + // + // Keyboard layout package 1, length = 192 + 0xc0, 0x00, 0x00, // 3: length(header) + EFI_HII_PACKAGE_KEYBOARD_LAYOUT, // 1: type(header) + 0x02, 0x00, // 2: LayoutCount + // + // Layout 1, length = 93 + // + 0x5d, 0x00, // 2: layout_length + 0x95, 0xe4, 0x40, 0x8d, 0xaa, 0xe2, 0x6f, 0x4c, + 0x89, 0x70, 0x68, 0x85, 0x09, 0xee, 0xc7, 0xd2, //16: guid + 0x37, 0x00, 0x00, 0x00, // 4: layout_descriptor_ + // string_offset + 0x02, // 1: descriptor_count + // + // Descriptor 1, length = 16 + // + 49, 0x00, 0x00, 0x00, // 4: key (EfiKeyD1) + 'q', 0x00, // 2: unicode + 'Q', 0x00, // 2: shifted_unicode + 0x00, 0x00, // 2: alt_gr_unicode + 0x00, 0x00, // 2: shifted_alt_gr_unicode + EFI_NULL_MODIFIER, 0x00, // 2: modifier + 0x03, 0x00, // 2: affected_attribute + // + // Descriptor 2, length = 16 + // + 50, 0x00, 0x00, 0x00, // 4: key (EfiKeyD2) + 'w', 0x00, // 2: unicode + 'W', 0x00, // 2: shifted_unicode + 0x00, 0x00, // 2: alt_gr_unicode + 0x00, 0x00, // 2: shifted_alt_gr_unicode + EFI_NULL_MODIFIER, 0x00, // 2: modifier + 0x3, 0x0, // 2: affected_attribute + // + // EFI_DESCRIPTOR_STRING_BUNDLE, length = 38 + // + 0x01, 0x00, // 2: DescriptionCount + 'e', 0x0, 'n', 0x0, '-', 0x0, 'U', 0x0, 'S', 0x0, + //10: RFC3066 language code + ' ', 0x0, // 2: Space + 'S', 0x0, 'i', 0x0, 'm', 0x0, 'p', 0x0, 'l', 0x0, 'e', 0x0, + '1', 0x0, 'o', 0x0, 'n', 0x0, 'l', 0x0, 'y', 0x0, '\0', 0x0, + //24: DescriptionString + // + // Layout 2, length = 93 + // + 0x5d, 0x00, // 2: layout_length + 0x3e, 0x0b, 0xe6, 0x2a, 0xd6, 0xb9, 0xd8, 0x49, + 0x9a, 0x16, 0xc2, 0x48, 0xf1, 0xeb, 0xa8, 0xdb, //16: guid + 0x37, 0x00, 0x00, 0x00, // 4: layout_descriptor_ + // string_offset + 0x02, // 1 Descriptor count + // + // Descriptor 1, length = 16 + // + 51, 0x0, 0x0, 0x0, // 4: key (EfiKeyD3) + 'e', 0x00, // 2: unicode + 'E', 0x00, // 2: shifted_unicode + 0x00, 0x00, // 2: alt_gr_unicode + 0x00, 0x00, // 2: shifted_alt_gr_unicode + EFI_NULL_MODIFIER, 0x0, // 2: modifier + 0x3, 0x0, // 2: affected_attribute + // + // Descriptor 2, length = 16 + // + 52, 0x0, 0x0, 0x0, // 4: key (EfiKeyD4) + 'r', 0x00, // 2: unicode + 'R', 0x00, // 2: shifted_unicode + 0x00, 0x00, // 2: alt_gr_unicode + 0x00, 0x00, // 2: shifted_alt_gr_unicode + EFI_NULL_MODIFIER, 0x0, // 2: modifier + 0x3, 0x0, // 2: affected_attribute + // + // EFI_DESCRIPTOR_STRING_BUNDLE, length = 38 + // + 0x01, 0x00, // 2: DescriptionCount + 'e', 0x0, 'n', 0x0, '-', 0x0, 'U', 0x0, 'S', 0x0, + //10: RFC3066 language code + ' ', 0x0, // 2: Space + 'S', 0x0, 'i', 0x0, 'm', 0x0, 'p', 0x0, 'l', 0x0, 'e', 0x0, + '2', 0x0, 'o', 0x0, 'n', 0x0, 'l', 0x0, 'y', 0x0, '\0', 0x0, + //24: DescriptionString + // + // End of package list, length = 4 + // + 0x4, 0x00, 0x00, + EFI_HII_PACKAGE_END +}; + +u8 packagelist2[] = { + // EFI_HII_PACKAGE_LIST_HEADER, length = 20 + // SimpleFont, Font, GUID, KeyboardLayout, Form, End + // (74) (122) 20 192 (8) 4 + 0xd3, 0xde, 0x85, 0x86, 0xce, 0x1b, 0xf3, 0x43, + 0xa2, 0x0c, 0xa3, 0x06, 0xec, 0x69, 0x72, 0xdd, //16 + 0xec, 0x00, 0x00, 0x00, // 4: total 236(0xec) + +#ifdef NOT_USED /* TODO: simple font package not implemented yet */ + // + // Simple Font Package 2, length = 74 + // + 0x4A, 0x00, 0x00, // 3 + EFI_HII_PACKAGE_SIMPLE_FONTS, // 1 + 1, 0, // 2 + 1, 0, // 2 + 0x33, 0x0, 0, 1, 2, 3, 4, 5, 0, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, //22 + 0x44, 0x0, 0x2, 2, 3, 4, 5, 6, 0, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, //22 + 3, 4, 5, 6, 7, 8, 9, 10, 11, 9, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 0, 0, 0, //22 + // + // Font Package 2, length = 122 + // + 0x7A, 0x00, 0x00, // 3 + EFI_HII_PACKAGE_FONTS, // 1 + 0x5C, 0x00, 0x00, 0x00, // 4: size of header + 0x5C, 0x00, 0x00, 0x00, // 4: dummy offset + 0xf1, 0x00, 0xf2, 0x00, 0xf3, 0x00, 0xf4, 0x00, + 0xf5, 0x00, 0xec, 0xec, //10+2(pads) + 0xff, 0x11, 0xff, 0x22, // 4: font style + 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, //64 + // + // Glyph block 1, length = 30 + // + EFI_HII_GIBT_GLYPH, // 1 + 0xf1, 0x00, 0xf2, 0x00, 0xf3, 0x00, 0xf4, 0x00, + 0xf5, 0x00, //10 + 0xff, 0x01, // 2 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, //16: BitMapData + EFI_HII_GIBT_END, // 1 +#endif + // + // Guid Package 1, length = 20 + // + 0x14, 0x00, 0x00, // 3 + EFI_HII_PACKAGE_TYPE_GUID, // 1 + 0x5a, 0xc9, 0x87, 0x03, 0x3, 0xd7, 0x46, 0x23, + 0xb2, 0xab, 0xd0, 0xc7, 0xdd, 0x90, 0x44, 0xf8, //16: guid + // + // Keyboard layout package 2, length = 192 + 0xc0, 0x00, 0x00, // 3 + EFI_HII_PACKAGE_KEYBOARD_LAYOUT, // 1 + 0x02, 0x00, //0xec, 0xec, // 2: LayoutCount + // + // Layout 1, length = 93 + // + 0x5d, 0x00, // 2: layout_length + 0x1f, 0x6a, 0xf5, 0xe0, 0x6b, 0xdf, 0x7e, 0x4a, + 0xa3, 0x9a, 0xe7, 0xa5, 0x19, 0x15, 0x45, 0xd6,//16: guid + 0x37, 0x00, 0x00, 0x00, // 4: layout_descriptor + // string offset + 0x02, // 1: descriptor_count + // + // Descriptor 1, length = 16 + // + 32, 0x00, 0x00, 0x00, // 4: key (EfiKeyC1) + 'a', 0x00, // 2: unicode + 'A', 0x00, // 2: shifted_unicode + 0x00, 0x00, // 2: alt_gr_unicode + 0x00, 0x00, // 2: shifted_alt_gr_unic + EFI_NULL_MODIFIER, 0x00, // 2: modifier + 0x03, 0x00, // 2: affected_attribute + // + // Descriptor 2, length = 16 + // + 33 /*EfiKeyC2*/, 0x00, 0x00, 0x00, + 's', 0x00, + 'S', 0x00, + 0x00, 0x00, + 0x00, 0x00, + EFI_NULL_MODIFIER, 0x00, + 0x3, 0x0, + // + // EFI_DESCRIPTOR_STRING_BUNDLE, length = 38 + // + 0x01, 0x00, // 2: DescriptionCount + 'e', 0x0, 'n', 0x0, '-', 0x0, 'U', 0x0, 'S', 0x0, + //10: RFC3066 language code + ' ', 0x0, // 2: Space + 'S', 0x0, 'i', 0x0, 'm', 0x0, 'p', 0x0, 'l', 0x0, 'e', 0x0, + '3', 0x0, 'o', 0x0, 'n', 0x0, 'l', 0x0, 'y', 0x0, '\0', 0x0, + //24: DescriptionString + // + // Layout 2, length = 93 + // + 0x5d, 0x00, // 2: layout_length + 0xc9, 0x6a, 0xbe, 0x47, 0xcc, 0x54, 0xf9, 0x46, + 0xa2, 0x62, 0xd5, 0x3b, 0x25, 0x6a, 0xc, 0x34, //16: guid + 0x37, 0x00, 0x00, 0x00, // 4: layout_descriptor + // string_offset + 0x02, // 1: descriptor_count + // + // Descriptor 1, length = 16 + // + 34 /*EfiKeyC3*/, 0x0, 0x0, 0x0, + 'd', 0x00, + 'D', 0x00, + 0x00, 0x00, + 0x00, 0x00, + EFI_NULL_MODIFIER, 0x0, + 0x3, 0x0, + // + // Descriptor 2, length = 16 + // + 35 /*EfiKeyC4*/, 0x0, 0x0, 0x0, + 'e', 0x00, + 'E', 0x00, + 0x00, 0x00, + 0x00, 0x00, + EFI_NULL_MODIFIER, 0x0, + 0x3, 0x0, + // + // EFI_DESCRIPTOR_STRING_BUNDLE, length = 38 + // + 0x01, 0x00, // 2: DescriptionCount + 'e', 0x0, 'n', 0x0, '-', 0x0, 'U', 0x0, 'S', 0x0, + //10: RFC3066 language code + ' ', 0x0, // 2: Space + 'S', 0x0, 'i', 0x0, 'm', 0x0, 'p', 0x0, 'l', 0x0, 'e', 0x0, + '4', 0x0, 'o', 0x0, 'n', 0x0, 'l', 0x0, 'y', 0x0, '\0', 0x0, + //24: DescriptionString +#ifdef NOT_USED /* TODO: form package not implemented yet */ + // + // EFI_HII_PACKAGE_FORMS, length = 8 + // + 0x08, 0x00, 0x00, // 3 + EFI_HII_PACKAGE_FORMS, // 1 + // + // Opcode 1 + // + EFI_IFR_BITWISE_AND_OP, // 1 + 0x02, // 1 + EFI_IFR_END_OP, // 1 + 0x02, // 1 +#endif + // + // End of package list, length = 4 + // + 0x4, 0x00, 0x00, // 3 + EFI_HII_PACKAGE_END // 1 +}; + +efi_guid_t packagelist_guid1 = + EFI_GUID(0x03abcd89, 0x03f4, 0x7044, + 0x81, 0xde, 0x99, 0xb1, 0x81, 0x20, 0xf7, 0x68); + +efi_guid_t packagelist_guid2 = + EFI_GUID(0x8685ded3, 0x1bce, 0x43f3, + 0xa2, 0x0c, 0xa3, 0x06, 0xec, 0x69, 0x72, 0xdd); + +efi_guid_t kb_layout_guid11 = + EFI_GUID(0x8d40e495, 0xe2aa, 0x4c6f, + 0x89, 0x70, 0x68, 0x85, 0x09, 0xee, 0xc7, 0xd2); + +efi_guid_t kb_layout_guid12 = + EFI_GUID(0x2ae60b3e, 0xb9d6, 0x49d8, + 0x9a, 0x16, 0xc2, 0x48, 0xf1, 0xeb, 0xa8, 0xdb); + +efi_guid_t kb_layout_guid21 = + EFI_GUID(0xe0f56a1f, 0xdf6b, 0x4a7e, + 0xa3, 0x9a, 0xe7, 0xa5, 0x19, 0x15, 0x45, 0xd6); + +efi_guid_t kb_layout_guid22 = + EFI_GUID(0x47be6ac9, 0x54cc, 0x46f9, + 0xa2, 0x62, 0xd5, 0x3b, 0x25, 0x6a, 0x0c, 0x34); + +efi_guid_t package_guid = + EFI_GUID(0x0387c95a, 0xd703, 0x2346, + 0xb2, 0xab, 0xd0, 0xc7, 0xdd, 0x90, 0x44, 0xf8); -- cgit v1.2.3 From f38753d2ef5dabcca78b1a70f2903e7f49d5d846 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 23 Jan 2019 20:36:27 +0100 Subject: efi_selftest: fix HII tests efi_st_printf() does not support format code %ld. Anyway the format code for size_t would be %zu which isn't supported either. We do not want any divisions to avoid invalid references to integer arithmetic routines, cf. https://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html. As a simple remedy remove the noisy messages from the output. They are not relevant for automated testing. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_selftest/efi_selftest_hii.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/lib/efi_selftest/efi_selftest_hii.c b/lib/efi_selftest/efi_selftest_hii.c index 16d7b608297..e38af7dbf85 100644 --- a/lib/efi_selftest/efi_selftest_hii.c +++ b/lib/efi_selftest/efi_selftest_hii.c @@ -205,8 +205,6 @@ static int test_hii_database_list_package_lists(void) (unsigned int)ret); goto out; } - efi_st_printf("list_package_lists returned %ld handles\n", - handles_size / sizeof(*handles)); free(handles); /* STRINGS */ @@ -236,8 +234,6 @@ static int test_hii_database_list_package_lists(void) ret = EFI_ST_FAILURE; goto out; } - efi_st_printf("list_package_lists returned %ld strings handles\n", - handles_size / sizeof(*handles)); free(handles); /* GUID */ @@ -267,8 +263,6 @@ static int test_hii_database_list_package_lists(void) ret = EFI_ST_FAILURE; goto out; } - efi_st_printf("list_package_lists returned %ld guid handles\n", - handles_size / sizeof(*handles)); free(handles); /* KEYBOARD_LAYOUT */ @@ -298,8 +292,6 @@ static int test_hii_database_list_package_lists(void) ret = EFI_ST_FAILURE; goto out; } - efi_st_printf("list_package_lists returned %ld keyboard layout handles\n", - handles_size / sizeof(*handles)); free(handles); result = EFI_ST_SUCCESS; @@ -420,9 +412,6 @@ static int test_hii_database_find_keyboard_layouts(void) } free(guids); - efi_st_printf("find_keyboard_layouts returned %ld guids\n", - guids_size / sizeof(*guids)); - result = EFI_ST_SUCCESS; out: -- cgit v1.2.3 From 6f8f4217e75d2e651b29c065e111da22658f7e07 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 23 Jan 2019 22:55:36 +0100 Subject: efi_loader: debug output for HII protocols For correct indention use EFI_PRINT() instead of debug(). For printing efi_uintn_t or size_t use the %zu or %zx format code. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/efi_hii.c | 50 ++++++++++++++++++++--------------------- lib/efi_loader/efi_hii_config.c | 2 +- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/lib/efi_loader/efi_hii.c b/lib/efi_loader/efi_hii.c index 89e1a6c2369..d63d2d84184 100644 --- a/lib/efi_loader/efi_hii.c +++ b/lib/efi_loader/efi_hii.c @@ -132,13 +132,13 @@ add_strings_package(struct efi_hii_packagelist *hii, struct efi_string_table *stbl = NULL; efi_status_t ret; - debug("header_size: %08x\n", - get_unaligned_le32(&strings_package->header_size)); - debug("string_info_offset: %08x\n", - get_unaligned_le32(&strings_package->string_info_offset)); - debug("language_name: %u\n", - get_unaligned_le16(&strings_package->language_name)); - debug("language: %s\n", strings_package->language); + EFI_PRINT("header_size: %08x\n", + get_unaligned_le32(&strings_package->header_size)); + EFI_PRINT("string_info_offset: %08x\n", + get_unaligned_le32(&strings_package->string_info_offset)); + EFI_PRINT("language_name: %u\n", + get_unaligned_le16(&strings_package->language_name)); + EFI_PRINT("language: %s\n", strings_package->language); /* count # of string entries: */ end = ((void *)strings_package) @@ -160,8 +160,8 @@ add_strings_package(struct efi_hii_packagelist *hii, block = end; break; default: - debug("unknown HII string block type: %02x\n", - block->block_type); + EFI_PRINT("unknown HII string block type: %02x\n", + block->block_type); return EFI_INVALID_PARAMETER; } } @@ -195,7 +195,7 @@ add_strings_package(struct efi_hii_packagelist *hii, struct efi_hii_sibt_string_ucs2_block *ucs2; ucs2 = (void *)block; - debug("%4u: \"%ls\"\n", idx + 1, ucs2->string_text); + EFI_PRINT("%4u: \"%ls\"\n", idx + 1, ucs2->string_text); stbl->strings[idx].string = u16_strdup(ucs2->string_text); if (!stbl->strings[idx].string) { @@ -210,8 +210,8 @@ add_strings_package(struct efi_hii_packagelist *hii, case EFI_HII_SIBT_END: goto out; default: - debug("unknown HII string block type: %02x\n", - block->block_type); + EFI_PRINT("unknown HII string block type: %02x\n", + block->block_type); ret = EFI_INVALID_PARAMETER; goto error; } @@ -372,14 +372,14 @@ add_packages(struct efi_hii_packagelist *hii, end = ((void *)package_list) + get_unaligned_le32(&package_list->package_length); - debug("package_list: %pUl (%u)\n", &package_list->package_list_guid, - get_unaligned_le32(&package_list->package_length)); + EFI_PRINT("package_list: %pUl (%u)\n", &package_list->package_list_guid, + get_unaligned_le32(&package_list->package_length)); package = ((void *)package_list) + sizeof(*package_list); while ((void *)package < end) { - debug("package=%p, package type=%x, length=%u\n", package, - efi_hii_package_type(package), - efi_hii_package_len(package)); + EFI_PRINT("package=%p, package type=%x, length=%u\n", package, + efi_hii_package_type(package), + efi_hii_package_len(package)); switch (efi_hii_package_type(package)) { case EFI_HII_PACKAGE_TYPE_GUID: @@ -505,17 +505,17 @@ update_package_list(const struct efi_hii_database_protocol *this, if (!package_list) return EFI_EXIT(EFI_INVALID_PARAMETER); - debug("package_list: %pUl (%u)\n", &package_list->package_list_guid, - get_unaligned_le32(&package_list->package_length)); + EFI_PRINT("package_list: %pUl (%u)\n", &package_list->package_list_guid, + get_unaligned_le32(&package_list->package_length)); package = ((void *)package_list) + sizeof(*package_list); end = ((void *)package_list) + get_unaligned_le32(&package_list->package_length); while ((void *)package < end) { - debug("package=%p, package type=%x, length=%u\n", package, - efi_hii_package_type(package), - efi_hii_package_len(package)); + EFI_PRINT("package=%p, package type=%x, length=%u\n", package, + efi_hii_package_type(package), + efi_hii_package_len(package)); switch (efi_hii_package_type(package)) { case EFI_HII_PACKAGE_TYPE_GUID: @@ -595,8 +595,8 @@ list_package_lists(const struct efi_hii_database_protocol *this, (package_type == EFI_HII_PACKAGE_TYPE_GUID && !package_guid)) return EFI_EXIT(EFI_INVALID_PARAMETER); - debug("package type=%x, guid=%pUl, length=%lu\n", (int)package_type, - package_guid, *handle_buffer_length); + EFI_PRINT("package type=%x, guid=%pUl, length=%zu\n", (int)package_type, + package_guid, *handle_buffer_length); package_cnt = 0; package_max = *handle_buffer_length / sizeof(*handle); @@ -1041,7 +1041,7 @@ get_languages(const struct efi_hii_string_protocol *this, } *p = '\0'; - debug("languages: %s\n", languages); + EFI_PRINT("languages: %s\n", languages); return EFI_EXIT(EFI_SUCCESS); } diff --git a/lib/efi_loader/efi_hii_config.c b/lib/efi_loader/efi_hii_config.c index f4b1f026c1b..26ea4b9bc0a 100644 --- a/lib/efi_loader/efi_hii_config.c +++ b/lib/efi_loader/efi_hii_config.c @@ -124,7 +124,7 @@ form_callback(const struct efi_hii_config_access_protocol *this, union efi_ifr_type_value *value, efi_browser_action_request_t *action_request) { - EFI_ENTRY("%p, 0x%lx, 0x%x, 0x%x, %p, %p", this, action, + EFI_ENTRY("%p, 0x%zx, 0x%x, 0x%x, %p, %p", this, action, question_id, type, value, action_request); return EFI_EXIT(EFI_DEVICE_ERROR); -- cgit v1.2.3 From 2f8ab1218f74dbaeffffb0a53094ead58bee41c5 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 11 Feb 2019 15:07:17 +0100 Subject: arm: Leave smccc calls in .text when efi_loader=n Commit 81ea00838c6 ("efi_loader: PSCI reset and shutdown") put the SMCCC assembly code into the efi specific code section. This is wrong when we do not have EFI_LOADER enabled, as that strips efi runtime sections from the output binary Reported-by: Michal Simek Reported-by: Siva Durga Prasad Paladugu Tested-by: Michal Simek Fixes: 81ea00838c6 ("efi_loader: PSCI reset and shutdown") Signed-off-by: Alexander Graf --- arch/arm/cpu/armv7/smccc-call.S | 2 ++ arch/arm/cpu/armv8/smccc-call.S | 2 ++ 2 files changed, 4 insertions(+) diff --git a/arch/arm/cpu/armv7/smccc-call.S b/arch/arm/cpu/armv7/smccc-call.S index eae69e36c3c..f70728f2c4a 100644 --- a/arch/arm/cpu/armv7/smccc-call.S +++ b/arch/arm/cpu/armv7/smccc-call.S @@ -7,7 +7,9 @@ #include #include +#ifdef CONFIG_EFI_LOADER .section .text.efi_runtime +#endif #define UNWIND(x...) /* diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S index 86de4b4089d..dc92b28777c 100644 --- a/arch/arm/cpu/armv8/smccc-call.S +++ b/arch/arm/cpu/armv8/smccc-call.S @@ -6,7 +6,9 @@ #include #include +#ifdef CONFIG_EFI_LOADER .section .text.efi_runtime +#endif .macro SMCCC instr .cfi_startproc -- cgit v1.2.3 From 5fbb28958becc2e725d2ee14a35c3b2f0918c62f Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Mon, 11 Feb 2019 15:24:00 +0100 Subject: efi_loader: Make HII a config option Heinrich ran into issues with HII and iPXE which lead to #SErrors on his Odroid-C2 system. We definitely do not want to regress just yet, so let's not expose the HII protocols by default. Instead, let's make it a config option that people can play with This way, we can stabilize the code in tree without breaking any users. Once someone figures out, why this breaks iPXE (probably a NULL dereference), we can enable it by default. Reported-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- v1 -> v2: - Remove HII selftest as well v2 -> v3: - Make config option --- lib/efi_loader/Kconfig | 15 +++++++++++++++ lib/efi_loader/efi_boottime.c | 2 ++ lib/efi_selftest/Makefile | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index f5de005ff8b..23487b8130e 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -34,3 +34,18 @@ config EFI_LOADER_BOUNCE_BUFFER 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 n + 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. The code is experimental still, so + beware that your system might break with HII enabled. + + If unsure, say n. diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index fc26d6adc11..f74f989e0ae 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1558,6 +1558,7 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, if (ret != EFI_SUCCESS) goto failure; +#if CONFIG_IS_ENABLED(EFI_LOADER_HII) ret = efi_add_protocol(&obj->header, &efi_guid_hii_string_protocol, (void *)&efi_hii_string); @@ -1575,6 +1576,7 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, (void *)&efi_hii_config_routing); if (ret != EFI_SUCCESS) goto failure; +#endif return ret; failure: diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile index 779f5499406..7f4eafb2fef 100644 --- a/lib/efi_selftest/Makefile +++ b/lib/efi_selftest/Makefile @@ -25,7 +25,6 @@ efi_selftest_exception.o \ efi_selftest_exitbootservices.o \ efi_selftest_fdt.o \ efi_selftest_gop.o \ -efi_selftest_hii.o \ efi_selftest_loaded_image.o \ efi_selftest_manageprotocols.o \ efi_selftest_memory.o \ @@ -41,6 +40,7 @@ efi_selftest_variables.o \ efi_selftest_watchdog.o obj-$(CONFIG_CPU_V7) += efi_selftest_unaligned.o +obj-$(CONFIG_EFI_LOADER_HII) += efi_selftest_hii.o ifeq ($(CONFIG_BLK)$(CONFIG_PARTITIONS),yy) obj-y += efi_selftest_block_device.o -- cgit v1.2.3 From 0e66c10a7d808062898f9a19f0c95f04d8dd85ed Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 10 Feb 2019 11:11:26 +0100 Subject: lib: vsprintf: avoid overflow printing UTF16 strings We have to ensure while printing UTF16 strings that we do not exceed the end of the print buffer. Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass Signed-off-by: Alexander Graf --- lib/vsprintf.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 4213441fbf7..de5db1aa5c7 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -279,13 +279,17 @@ static char *string(char *buf, char *end, char *s, int field_width, static char *string16(char *buf, char *end, u16 *s, int field_width, int precision, int flags) { - u16 *str = s ? s : L""; - ssize_t len = utf16_strnlen(str, precision); + const u16 *str = s ? s : L""; + ssize_t i, len = utf16_strnlen(str, precision); if (!(flags & LEFT)) for (; len < field_width; --field_width) ADDCH(buf, ' '); - utf16_utf8_strncpy(&buf, str, len); + for (i = 0; i < len && buf + utf16_utf8_strnlen(str, 1) <= end; ++i) { + s32 s = utf16_get(&str); + + utf8_put(s, &buf); + } for (; len < field_width; --field_width) ADDCH(buf, ' '); return buf; -- cgit v1.2.3 From 823c233b7ab95169ea4428b2821b72b8887b47b0 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 9 Feb 2019 22:23:48 +0100 Subject: efi_loader: fix EFI_FILE_PROTOCOL.GetInfo() We check the existence of files with fs_exist(). This function calls fs_close(). If we do not set the active block device again fs_opendir() fails and we do not set the flag EFI_FILE_DIRECTORY. Due to this error the `cd` command in the EFI shell fails. So let's add the missing set_blk_dev(fh) call. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/efi_file.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c index 9d709a8db02..4b4422205dd 100644 --- a/lib/efi_loader/efi_file.c +++ b/lib/efi_loader/efi_file.c @@ -200,6 +200,10 @@ static struct efi_file_handle *file_open(struct file_system *fs, fs_exists(fh->path))) goto error; + /* fs_exists() calls fs_close(), so open file system again */ + if (set_blk_dev(fh)) + goto error; + /* figure out if file is a directory: */ fh->isdir = is_dir(fh); } else { -- cgit v1.2.3