All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 0/6] efi_loader: add HII database protocol
@ 2018-11-01  4:40 AKASHI Takahiro
  2018-11-01  4:45 ` [U-Boot] [PATCH 1/6] lib: add u16_strcpy/strdup functions AKASHI Takahiro
  2018-11-01  4:47 ` [U-Boot] [PATCH 2/6] efi_loader: Initial HII database protocols AKASHI Takahiro
  0 siblings, 2 replies; 19+ messages in thread
From: AKASHI Takahiro @ 2018-11-01  4:40 UTC (permalink / raw)
  To: u-boot

HII database protocol is the last missing (major?) piece of code so that
we can run unmodified EDKII's shell and UEFI SCT on EFI-enabled u-boot.

The original code was initially written by Leif and Rob a year ago[1],
and now I'm reworking it. The implementation has not been much
enhanced from the original, but I tried to give it clearer implementation
to be able to add more functionality easily later on.
I also addressed the comments by Alex[2] and added a self test on
request of Heinrich.

HII configuration routing protocol and access protocol have only
a skeleton and should be implemented when we need to have *drivers*
that require configuration mechanism.

Concerns (if any):
* missing features (see the commit log of patch#2)
* unaligned access to *packed* structure in a package list should be
  cared?

[1] https://lists.denx.de/pipermail/u-boot/2017-October/308999.html
[2] https://lists.denx.de/pipermail/u-boot/2017-October/309116.html

AKASHI Takahiro (4):
  efi: hii: add guid package support
  efi: hii: add keyboard layout package support
  efi: hii: add HII config routing/access protocols
  efi_selftest: add HII database protocols test

Akashi, Takahiro (1):
  lib: add u16_strcpy/strdup functions

Leif Lindholm (1):
  efi_loader: Initial HII database protocols

 include/charset.h                        |   18 +
 include/efi_api.h                        |  410 +++++++++
 include/efi_loader.h                     |    8 +
 lib/charset.c                            |   29 +
 lib/efi_loader/Makefile                  |    1 +
 lib/efi_loader/efi_boottime.c            |   18 +
 lib/efi_loader/efi_hii.c                 | 1053 ++++++++++++++++++++++
 lib/efi_loader/efi_hii_config.c          |  146 +++
 lib/efi_selftest/Makefile                |    1 +
 lib/efi_selftest/efi_selftest_hii.c      |  882 ++++++++++++++++++
 lib/efi_selftest/efi_selftest_hii_data.c |  450 +++++++++
 11 files changed, 3016 insertions(+)
 create mode 100644 lib/efi_loader/efi_hii.c
 create mode 100644 lib/efi_loader/efi_hii_config.c
 create mode 100644 lib/efi_selftest/efi_selftest_hii.c
 create mode 100644 lib/efi_selftest/efi_selftest_hii_data.c

-- 
2.19.0

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 1/6] lib: add u16_strcpy/strdup functions
  2018-11-01  4:40 [U-Boot] [PATCH 0/6] efi_loader: add HII database protocol AKASHI Takahiro
@ 2018-11-01  4:45 ` AKASHI Takahiro
  2018-11-01  6:10   ` Heinrich Schuchardt
  2018-11-01  4:47 ` [U-Boot] [PATCH 2/6] efi_loader: Initial HII database protocols AKASHI Takahiro
  1 sibling, 1 reply; 19+ messages in thread
From: AKASHI Takahiro @ 2018-11-01  4:45 UTC (permalink / raw)
  To: u-boot

From: "Akashi Takahiro" <takahiro.akashi@linaro.org>

Add u16_strcpy() and u16_strdup(). The latter function will be
used later in implementing efi HII database protocol.

Signed-off-by: Akashi Takahiro <takahiro.akashi@linaro.org>
---
 include/charset.h | 18 ++++++++++++++++++
 lib/charset.c     | 29 +++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+)

diff --git a/include/charset.h b/include/charset.h
index 4d45e246e515..5807f02b1a04 100644
--- a/include/charset.h
+++ b/include/charset.h
@@ -191,6 +191,24 @@ size_t u16_strlen(const u16 *in);
  */
 size_t u16_strnlen(const u16 *in, size_t count);
 
+/* TODO: add descriptions */
+/**
+ * u16_strcpy() - copy u16 string
+ *
+ * @dest:		destination buffer
+ * @src:		source buffer (null terminated)
+ * Return:		'dest' address
+ */
+u16 *u16_strcpy(u16 *dest, const u16 *src);
+
+/**
+ * u16_strdup() - duplicate u16 string
+ *
+ * @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 10557b9e753d..5e349ed5ee45 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)
 {
-- 
2.19.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 2/6] efi_loader: Initial HII database protocols
  2018-11-01  4:40 [U-Boot] [PATCH 0/6] efi_loader: add HII database protocol AKASHI Takahiro
  2018-11-01  4:45 ` [U-Boot] [PATCH 1/6] lib: add u16_strcpy/strdup functions AKASHI Takahiro
@ 2018-11-01  4:47 ` AKASHI Takahiro
  2018-11-01  4:47   ` [U-Boot] [PATCH 3/6] efi: hii: add guid package support AKASHI Takahiro
                     ` (6 more replies)
  1 sibling, 7 replies; 19+ messages in thread
From: AKASHI Takahiro @ 2018-11-01  4:47 UTC (permalink / raw)
  To: u-boot

From: Leif Lindholm <leif.lindholm@linaro.org>

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 can handle only:
  * GUID package
  * string package
  * keyboard layout package
  (The oterh packages, exept Device path package, will be necessary
   for interactive and graphical UI.)

We'll fill in the rest once SCT is running properly so we can validate
the implementation against the conformance test suite.

Cc: Leif Lindholm <leif.lindholm@linaro.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 include/efi_api.h             | 233 +++++++++
 include/efi_loader.h          |   4 +
 lib/efi_loader/Makefile       |   1 +
 lib/efi_loader/efi_boottime.c |  12 +
 lib/efi_loader/efi_hii.c      | 886 ++++++++++++++++++++++++++++++++++
 5 files changed, 1136 insertions(+)
 create mode 100644 lib/efi_loader/efi_hii.c

diff --git a/include/efi_api.h b/include/efi_api.h
index 88a60070f6ab..ec1b759d810a 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -17,6 +17,7 @@
 #define _EFI_API_H
 
 #include <efi.h>
+#include <charset.h>
 
 #ifdef CONFIG_EFI_LOADER
 #include <asm/setjmp.h>
@@ -697,6 +698,238 @@ struct efi_device_path_utilities_protocol {
 		uint16_t node_length);
 };
 
+typedef u16 efi_string_id_t;
+
+#define EFI_HII_DATABASE_PROTOCOL_GUID	     \
+	EFI_GUID(0xef9fc172, 0xa1b2, 0x4693, \
+		 0xb3, 0x27, 0x6d, 0x32, 0xfc, 0x41, 0x60, 0x42)
+
+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 {
+	efi_key key;
+	u16 unicode;
+	u16 shifted_unicode;
+	u16 alt_gr_unicode;
+	u16 shifted_alt_gr_unicode;
+	u16 modifier;
+	u16 affected_attribute;
+};
+
+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[];
+};
+
+struct efi_hii_package_list_header {
+	efi_guid_t package_list_guid;
+	u32 package_length;
+} __packed;
+
+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_HEADER(header, field) \
+		(((header)->fields >> EFI_HII_PACKAGE_##field##_SHIFT) \
+		 & EFI_HII_PACKAGE_##field##_MASK)
+#define efi_hii_package_len(header) \
+		EFI_HII_PACKAGE_HEADER(header, LEN)
+#define efi_hii_package_type(header) \
+		EFI_HII_PACKAGE_HEADER(header, TYPE)
+
+#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
+
+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;
+}
+
+typedef void *efi_hii_handle_t;
+
+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_HII_STRING_PROTOCOL_GUID \
+	EFI_GUID(0x0fd96974, 0x23aa, 0x4cdc, \
+		 0xb9, 0xcb, 0x98, 0xd1, 0x77, 0x50, 0x32, 0x2a)
+
+typedef u32 efi_hii_font_style_t;
+
+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_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 2ec73592ff30..615314909b17 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 6703435947f2..e508481fdeeb 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 eb652e834856..b1d7f6b36f89 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -1550,6 +1550,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 000000000000..40034c27473d
--- /dev/null
+++ b/lib/efi_loader/efi_hii.c
@@ -0,0 +1,886 @@
+// 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 <common.h>
+#include <malloc.h>
+#include <efi_loader.h>
+
+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;
+
+const u32 hii_package_signature = 0x68696770; /* "higp" */
+
+static LIST_HEAD(efi_package_lists);
+
+struct efi_hii_packagelist {
+	struct list_head link;
+	u32 signature;
+	// 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 */
+};
+
+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", strings_package->header_size);
+	debug("string_info_offset: %08x\n",
+	      strings_package->string_info_offset);
+	debug("language_name: %u\n", strings_package->language_name);
+	debug("language: %s\n", strings_package->language);
+
+	/* count # of string entries: */
+	block = ((void *)strings_package) + strings_package->string_info_offset;
+	end = ((void *)strings_package)
+			+ efi_hii_package_len(&strings_package->header);
+	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 = 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) + 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++;
+			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->signature = hii_package_signature;
+	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) + package_list->package_length;
+
+	debug("package_list: %pUl (%u)\n", &package_list->package_list_guid,
+	      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 (!hii || hii->signature != hii_package_signature)
+		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 (!hii || hii->signature != hii_package_signature)
+		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,
+	      package_list->package_length);
+
+	package = ((void *)package_list) + sizeof(*package_list);
+	end = ((void *)package_list) + 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: partially destroy a package */
+		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_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)
+{
+	char *p, *endp;
+
+	p = languages;
+	while (*p) {
+		endp = strchr(p, ';');
+		if (!endp)
+			return !strcmp(language, p);
+
+		if (!strncmp(language, p, endp - p))
+			return true;
+
+		p = endp + 1;
+	}
+
+	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 (!hii || hii->signature != hii_package_signature)
+		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 (!hii || hii->signature != hii_package_signature)
+		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 (!hii || hii->signature != hii_package_signature)
+		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 (!hii || hii->signature != hii_package_signature)
+		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 += sprintf(p, ";");
+		p += sprintf(p, "%s", stbl->language);
+	}
+
+	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 (!hii || hii->signature != hii_package_signature)
+		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
+};
-- 
2.19.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 3/6] efi: hii: add guid package support
  2018-11-01  4:47 ` [U-Boot] [PATCH 2/6] efi_loader: Initial HII database protocols AKASHI Takahiro
@ 2018-11-01  4:47   ` AKASHI Takahiro
  2018-11-01  4:47   ` [U-Boot] [PATCH 4/6] efi: hii: add keyboard layout " AKASHI Takahiro
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 19+ messages in thread
From: AKASHI Takahiro @ 2018-11-01  4:47 UTC (permalink / raw)
  To: u-boot

Allow for handling GUID package in HII database protocol.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 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 ec1b759d810a..c51b83ca4ec7 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -826,6 +826,15 @@ efi_hii_sibt_string_ucs2_block_next(struct efi_hii_sibt_string_ucs2_block *blk)
 		(u16_strlen(blk->string_text) + 1) * 2;
 }
 
+/*
+ * Guid package
+ */
+struct efi_hii_guid_package {
+	struct efi_hii_package_header header;
+	efi_guid_t guid;
+	char data[];
+} __packed;
+
 typedef void *efi_hii_handle_t;
 
 struct efi_hii_database_protocol {
diff --git a/lib/efi_loader/efi_hii.c b/lib/efi_loader/efi_hii.c
index 40034c27473d..036aa8eac956 100644
--- a/lib/efi_loader/efi_hii.c
+++ b/lib/efi_loader/efi_hii.c
@@ -25,6 +25,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 */
 };
@@ -47,6 +48,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;
@@ -178,6 +184,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;
@@ -186,6 +221,7 @@ static struct efi_hii_packagelist *new_packagelist(void)
 	hii->signature = hii_package_signature;
 	hii->max_string_id = 0;
 	INIT_LIST_HEAD(&hii->string_tables);
+	INIT_LIST_HEAD(&hii->guid_list);
 
 	return hii;
 }
@@ -193,6 +229,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);
@@ -219,8 +256,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");
@@ -355,8 +392,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");
@@ -442,8 +478,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");
-- 
2.19.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 4/6] efi: hii: add keyboard layout package support
  2018-11-01  4:47 ` [U-Boot] [PATCH 2/6] efi_loader: Initial HII database protocols AKASHI Takahiro
  2018-11-01  4:47   ` [U-Boot] [PATCH 3/6] efi: hii: add guid package support AKASHI Takahiro
@ 2018-11-01  4:47   ` AKASHI Takahiro
  2018-11-01  4:47   ` [U-Boot] [PATCH 5/6] efi: hii: add HII config routing/access protocols AKASHI Takahiro
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 19+ messages in thread
From: AKASHI Takahiro @ 2018-11-01  4:47 UTC (permalink / raw)
  To: u-boot

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 <takahiro.akashi@linaro.org>
---
 include/efi_api.h        |  11 +++
 lib/efi_loader/efi_hii.c | 141 +++++++++++++++++++++++++++++++++++++--
 2 files changed, 147 insertions(+), 5 deletions(-)

diff --git a/include/efi_api.h b/include/efi_api.h
index c51b83ca4ec7..36764a5c6bbb 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -835,6 +835,17 @@ struct efi_hii_guid_package {
 	char data[];
 } __packed;
 
+/*
+ * Keyboard layout package
+ */
+
+struct efi_hii_keyboard_layout_package {
+	struct efi_hii_package_header header;
+	u8 layout_count;
+	u8 __pad;
+	struct efi_hii_keyboard_layout layout[];
+} __packed;
+
 typedef void *efi_hii_handle_t;
 
 struct efi_hii_database_protocol {
diff --git a/lib/efi_loader/efi_hii.c b/lib/efi_loader/efi_hii.c
index 036aa8eac956..fefe3a861387 100644
--- a/lib/efi_loader/efi_hii.c
+++ b/lib/efi_loader/efi_hii.c
@@ -17,6 +17,7 @@ const efi_guid_t efi_guid_hii_string_protocol = EFI_HII_STRING_PROTOCOL_GUID;
 const u32 hii_package_signature = 0x68696770; /* "higp" */
 
 static LIST_HEAD(efi_package_lists);
+static LIST_HEAD(efi_kb_layout_list);
 
 struct efi_hii_packagelist {
 	struct list_head link;
@@ -26,6 +27,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 kb_layout_packages;
 
 	/* we could also track fonts, images, etc */
 };
@@ -53,6 +55,17 @@ struct efi_guid_data {
 	struct efi_hii_guid_package package;
 };
 
+struct efi_kb_layout_data {
+	struct list_head link;		/* in package */
+	struct list_head link_sys;	/* in global list */
+	struct efi_hii_keyboard_layout kb_layout;
+};
+
+struct efi_kb_layout_package_data {
+	struct list_head link;		/* in package_list */
+	struct list_head kb_layout_list;
+};
+
 static void free_strings_table(struct efi_string_table *stbl)
 {
 	int i;
@@ -213,6 +226,74 @@ add_guid_package(struct efi_hii_packagelist *hii,
 	return EFI_SUCCESS;
 }
 
+static void free_keyboard_layouts(struct efi_kb_layout_package_data *package)
+{
+	struct efi_kb_layout_data *data;
+
+	while (!list_empty(&package->kb_layout_list)) {
+		data = list_first_entry(&package->kb_layout_list,
+					struct efi_kb_layout_data,
+					link);
+		list_del(&data->link);
+		list_del(&data->link_sys);
+		free(data);
+	}
+}
+
+static void remove_keyboard_layout_package(struct efi_hii_packagelist *hii)
+{
+	struct efi_kb_layout_package_data *package;
+
+	while (!list_empty(&hii->kb_layout_packages)) {
+		package = list_first_entry(&hii->kb_layout_packages,
+					   struct efi_kb_layout_package_data,
+					   link);
+		free_keyboard_layouts(package);
+		list_del(&package->link);
+		free(package);
+	}
+}
+
+static efi_status_t
+add_keyboard_layout_package(struct efi_hii_packagelist *hii,
+			    struct efi_hii_keyboard_layout_package
+				*kb_layout_package)
+{
+	struct efi_kb_layout_package_data *package;
+	struct efi_hii_keyboard_layout *layout;
+	struct efi_kb_layout_data *data;
+	int i;
+
+	package = malloc(sizeof(*package));
+	if (!package)
+		return EFI_OUT_OF_RESOURCES;
+	INIT_LIST_HEAD(&package->link);
+	INIT_LIST_HEAD(&package->kb_layout_list);
+
+	layout = &kb_layout_package->layout[0];
+	for (i = 0; i < kb_layout_package->layout_count; i++) {
+		data = malloc(sizeof(*data) + layout->layout_length);
+		if (!data)
+			goto out;
+
+		memcpy(&data->kb_layout, layout, layout->layout_length);
+		list_add_tail(&data->link, &package->kb_layout_list);
+		list_add_tail(&data->link_sys, &efi_kb_layout_list);
+
+		layout += layout->layout_length;
+	}
+
+	list_add_tail(&package->link, &hii->kb_layout_packages);
+
+	return EFI_SUCCESS;
+
+out:
+	free_keyboard_layouts(package);
+	free(package);
+
+	return EFI_OUT_OF_RESOURCES;
+}
+
 static struct efi_hii_packagelist *new_packagelist(void)
 {
 	struct efi_hii_packagelist *hii;
@@ -222,6 +303,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->kb_layout_packages);
 
 	return hii;
 }
@@ -230,6 +312,7 @@ static void free_packagelist(struct efi_hii_packagelist *hii)
 {
 	remove_strings_package(hii);
 	remove_guid_package(hii);
+	remove_keyboard_layout_package(hii);
 
 	list_del(&hii->link);
 	free(hii);
@@ -284,8 +367,9 @@ 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_layout_package(hii,
+				(struct efi_hii_keyboard_layout_package *)
+				  package);
 			break;
 		case EFI_HII_PACKAGE_ANIMATIONS:
 			printf("\tAnimation package not supported\n");
@@ -418,7 +502,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_layout_package(hii);
 			break;
 		case EFI_HII_PACKAGE_ANIMATIONS:
 			printf("\tAnimation package not supported\n");
@@ -506,7 +590,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->kb_layout_packages))
+				break;
 			continue;
 		case EFI_HII_PACKAGE_ANIMATIONS:
 			printf("\tAnimation package not supported\n");
@@ -580,9 +665,29 @@ find_keyboard_layouts(const struct efi_hii_database_protocol *this,
 		      u16 *key_guid_buffer_length,
 		      efi_guid_t *key_guid_buffer)
 {
+	struct efi_kb_layout_data *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(data, &efi_kb_layout_list, link_sys) {
+		package_cnt++;
+		if (package_cnt <= package_max)
+			memcpy(key_guid_buffer++, &data->kb_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
@@ -591,10 +696,36 @@ get_keyboard_layout(const struct efi_hii_database_protocol *this,
 		    u16 *keyboard_layout_length,
 		    struct efi_hii_keyboard_layout *keyboard_layout)
 {
+	struct efi_kb_layout_data *data;
+
 	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(data, &efi_kb_layout_list, link_sys) {
+		if (!guidcmp(&data->kb_layout.guid, key_guid))
+			goto found;
+	}
+
 	return EFI_EXIT(EFI_NOT_FOUND);
+
+found:
+	if (*keyboard_layout_length < data->kb_layout.layout_length) {
+		*keyboard_layout_length = data->kb_layout.layout_length;
+		return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
+	}
+
+	memcpy(keyboard_layout, &data->kb_layout,
+	       sizeof(data->kb_layout.layout_length));
+
+	return EFI_EXIT(EFI_SUCCESS);
 }
 
 static efi_status_t EFIAPI
-- 
2.19.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 5/6] efi: hii: add HII config routing/access protocols
  2018-11-01  4:47 ` [U-Boot] [PATCH 2/6] efi_loader: Initial HII database protocols AKASHI Takahiro
  2018-11-01  4:47   ` [U-Boot] [PATCH 3/6] efi: hii: add guid package support AKASHI Takahiro
  2018-11-01  4:47   ` [U-Boot] [PATCH 4/6] efi: hii: add keyboard layout " AKASHI Takahiro
@ 2018-11-01  4:47   ` AKASHI Takahiro
  2018-11-01  4:47   ` [U-Boot] [PATCH 6/6] efi_selftest: add HII database protocols test AKASHI Takahiro
                     ` (3 subsequent siblings)
  6 siblings, 0 replies; 19+ messages in thread
From: AKASHI Takahiro @ 2018-11-01  4:47 UTC (permalink / raw)
  To: u-boot

This patch is a place holder for HII configuration routing protocol and
HII configuration access protocol.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 include/efi_api.h               | 157 ++++++++++++++++++++++++++++++++
 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, 314 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 36764a5c6bbb..a7b917e59bda 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -699,6 +699,163 @@ struct efi_device_path_utilities_protocol {
 };
 
 typedef u16 efi_string_id_t;
+typedef u16 efi_question_id_t;
+typedef u16 efi_image_id_t;
+typedef u16 efi_form_id_t;
+
+#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_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
+
+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_HII_DATABASE_PROTOCOL_GUID	     \
 	EFI_GUID(0xef9fc172, 0xa1b2, 0x4693, \
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 615314909b17..ce0f420b5004 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 e508481fdeeb..26b999bf7c51 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 b1d7f6b36f89..8a43a5a84091 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -1562,6 +1562,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 000000000000..f4b1f026c1bd
--- /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 <common.h>
+#include <efi_loader.h>
+
+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
+};
-- 
2.19.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 6/6] efi_selftest: add HII database protocols test
  2018-11-01  4:47 ` [U-Boot] [PATCH 2/6] efi_loader: Initial HII database protocols AKASHI Takahiro
                     ` (2 preceding siblings ...)
  2018-11-01  4:47   ` [U-Boot] [PATCH 5/6] efi: hii: add HII config routing/access protocols AKASHI Takahiro
@ 2018-11-01  4:47   ` AKASHI Takahiro
  2018-11-01  7:33     ` Heinrich Schuchardt
  2018-11-01  7:09   ` [U-Boot] [PATCH 2/6] efi_loader: Initial HII database protocols Heinrich Schuchardt
                     ` (2 subsequent siblings)
  6 siblings, 1 reply; 19+ messages in thread
From: AKASHI Takahiro @ 2018-11-01  4:47 UTC (permalink / raw)
  To: u-boot

This efi_selftest tests HII database protocol and HII string protocol.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 lib/efi_selftest/Makefile                |   1 +
 lib/efi_selftest/efi_selftest_hii.c      | 882 +++++++++++++++++++++++
 lib/efi_selftest/efi_selftest_hii_data.c | 450 ++++++++++++
 3 files changed, 1333 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 4b1c0bb84b18..1209b54b07cd 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_rtc.o \
diff --git a/lib/efi_selftest/efi_selftest_hii.c b/lib/efi_selftest/efi_selftest_hii.c
new file mode 100644
index 000000000000..2d5fe095a9b2
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_hii.c
@@ -0,0 +1,882 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_hii
+ *
+ * Copyright (c) 2018 AKASHI Takahiro, Linaro Limited
+ *
+ * Test HII database protocols
+ */
+
+#include <efi_selftest.h>
+#include <malloc.h>
+#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
+ */
+
+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", (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", (int)ret);
+		return EFI_ST_FAILURE;
+	}
+
+	return EFI_ST_SUCCESS;
+}
+
+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", (int)(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", (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",
+				     (int)ret);
+			return EFI_ST_FAILURE;
+		}
+	}
+
+	return result;
+}
+
+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", (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", (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", (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", (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", (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", (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", (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", (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", (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", (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",
+				     (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",
+				     (int)ret);
+	}
+
+	return result;
+}
+
+static int test_hii_database_export_package_lists(void)
+{
+	PRINT_TESTNAME;
+	/* export_package_lists() not implemented yet */
+	return EFI_ST_SUCCESS;
+}
+
+static int test_hii_database_register_package_notify(void)
+{
+	PRINT_TESTNAME;
+	/* register_package_notify() not implemented yet */
+	return EFI_ST_SUCCESS;
+}
+
+static int test_hii_database_unregister_package_notify(void)
+{
+	PRINT_TESTNAME;
+	/* unregsiter_package_notify() not implemented yet */
+	return EFI_ST_SUCCESS;
+}
+
+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", (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", (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", (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", (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",
+				     (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",
+				     (int)ret);
+	}
+
+	return result;
+}
+
+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", (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", (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", (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", (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", (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",
+				     (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",
+				     (int)ret);
+	}
+
+	return result;
+}
+
+static int test_hii_database_set_keyboard_layout(void)
+{
+	PRINT_TESTNAME;
+	/* set_keyboard_layout() not implemented yet */
+	return EFI_ST_SUCCESS;
+}
+
+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", (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",
+			     (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",
+				     (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
+ */
+
+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", (int)ret);
+		return EFI_ST_FAILURE;
+	}
+
+	ret = hii_string_protocol->new_string(hii_string_protocol, handle,
+					      &id, (uint8_t *)"en-US",
+					      L"Japanese", L"Japanese", NULL);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("new_string returned %u\n", (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",
+				     (int)ret);
+			return EFI_ST_FAILURE;
+		}
+	}
+
+	return result;
+}
+
+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", (int)ret);
+		return EFI_ST_FAILURE;
+	}
+
+	ret = hii_string_protocol->new_string(hii_string_protocol, handle,
+					      &id, (uint8_t *)"en-US",
+					      L"Japanese", L"Japanese", NULL);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("new_string returned %u\n", (int)ret);
+		goto out;
+	}
+
+	string = NULL;
+	string_len = 0;
+	ret = hii_string_protocol->get_string(hii_string_protocol,
+			(uint8_t *)"en-US", handle, id, string, &string_len,
+			NULL);
+	if (ret != EFI_BUFFER_TOO_SMALL) {
+		efi_st_error("get_string returned %u\n", (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,
+			(uint8_t *)"en-US", handle, id, string, &string_len,
+			NULL);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("get_string returned %u\n", (int)ret);
+		goto out;
+	}
+
+	/* TODO: %ls */
+	efi_st_printf("got string is %s\n", string);
+
+	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",
+				     (int)ret);
+			return EFI_ST_FAILURE;
+		}
+	}
+
+	return result;
+}
+
+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", (int)ret);
+		return EFI_ST_FAILURE;
+	}
+
+	ret = hii_string_protocol->new_string(hii_string_protocol, handle,
+					      &id, (uint8_t *)"en-US",
+					      L"Japanese", L"Japanese", NULL);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("new_string returned %u\n", (int)ret);
+		goto out;
+	}
+
+	ret = hii_string_protocol->set_string(hii_string_protocol, handle,
+					      id, (uint8_t *)"en-US",
+					      L"Nihongo", NULL);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("set_string returned %u\n", (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",
+				     (int)ret);
+			return EFI_ST_FAILURE;
+		}
+	}
+
+	return result;
+}
+
+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", (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", (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", (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",
+				     (int)ret);
+			return EFI_ST_FAILURE;
+		}
+	}
+
+	return result;
+}
+
+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", (int)ret);
+		return EFI_ST_FAILURE;
+	}
+
+	languages = NULL;
+	languages_len = 0;
+	ret = hii_string_protocol->get_secondary_languages(hii_string_protocol,
+			handle, (uint8_t *)"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", (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, (uint8_t *)"en-US", languages, &languages_len);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("get_secondary_languages returned %u\n", (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",
+				     (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 000000000000..2000a9315960
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_hii_data.c
@@ -0,0 +1,450 @@
+// SPDX-License-Identifier:     GPL-2.0+
+/*
+ * This file's test data is derived from UEFI SCT.
+ * The original copyright is attached below.
+ */
+
+/** @file
+
+  Copyright 2006 - 2016 Unified EFI, Inc.<BR>
+  Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
+
+  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 <efi.h>
+
+/* FIXME: define them elsewhere */
+#if 0
+/* 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)
+#if 0
+	//
+	// 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
+#if 0
+	//
+	// 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
+#if 0
+	//
+	// 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 /*EfiKeyD1*/, 0x00, 0x00, 0x00,	// 4: key
+	'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 /*EfiKeyD2*/, 0x00, 0x00, 0x00,	// 4: key
+	'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 /*EfiKeyD3*/, 0x0, 0x0, 0x0,		// 4: key
+	'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 /*EfiKeyD4*/, 0x0, 0x0, 0x0,		// 4: key
+	'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)
+
+#if 0
+	//
+	// 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 /*EfiKeyC1*/, 0x00, 0x00, 0x00,	// 4: key
+	'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
+#if 0
+	//
+	// 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);
-- 
2.19.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 1/6] lib: add u16_strcpy/strdup functions
  2018-11-01  4:45 ` [U-Boot] [PATCH 1/6] lib: add u16_strcpy/strdup functions AKASHI Takahiro
@ 2018-11-01  6:10   ` Heinrich Schuchardt
  2018-11-02  0:12     ` AKASHI Takahiro
  0 siblings, 1 reply; 19+ messages in thread
From: Heinrich Schuchardt @ 2018-11-01  6:10 UTC (permalink / raw)
  To: u-boot

On 11/01/2018 05:45 AM, AKASHI Takahiro wrote:
> From: "Akashi Takahiro" <takahiro.akashi@linaro.org>
> 
> Add u16_strcpy() and u16_strdup(). The latter function will be
> used later in implementing efi HII database protocol.
> 
> Signed-off-by: Akashi Takahiro <takahiro.akashi@linaro.org>
> ---
>  include/charset.h | 18 ++++++++++++++++++
>  lib/charset.c     | 29 +++++++++++++++++++++++++++++
>  2 files changed, 47 insertions(+)
> 
> diff --git a/include/charset.h b/include/charset.h
> index 4d45e246e515..5807f02b1a04 100644
> --- a/include/charset.h
> +++ b/include/charset.h
> @@ -191,6 +191,24 @@ size_t u16_strlen(const u16 *in);
>   */
>  size_t u16_strnlen(const u16 *in, size_t count);
>  
> +/* TODO: add descriptions */

You could use the descriptions below.

> +/**
> + * 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 10557b9e753d..5e349ed5ee45 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)
>  {
> 

For everything I added to charset.c I implemented tests in
test/unicode_ut.c.

Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 2/6] efi_loader: Initial HII database protocols
  2018-11-01  4:47 ` [U-Boot] [PATCH 2/6] efi_loader: Initial HII database protocols AKASHI Takahiro
                     ` (3 preceding siblings ...)
  2018-11-01  4:47   ` [U-Boot] [PATCH 6/6] efi_selftest: add HII database protocols test AKASHI Takahiro
@ 2018-11-01  7:09   ` Heinrich Schuchardt
  2018-11-02  2:03     ` AKASHI Takahiro
  2018-11-01  7:39   ` Heinrich Schuchardt
  2018-11-01  8:42   ` Heinrich Schuchardt
  6 siblings, 1 reply; 19+ messages in thread
From: Heinrich Schuchardt @ 2018-11-01  7:09 UTC (permalink / raw)
  To: u-boot

On 11/01/2018 05:47 AM, AKASHI Takahiro wrote:
> From: Leif Lindholm <leif.lindholm@linaro.org>
> 
> 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 can handle only:
>   * GUID package
>   * string package
>   * keyboard layout package
>   (The oterh packages, exept Device path package, will be necessary
>    for interactive and graphical UI.)
> 
> We'll fill in the rest once SCT is running properly so we can validate
> the implementation against the conformance test suite.
> 
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Signed-off-by: Rob Clark <robdclark@gmail.com>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>  include/efi_api.h             | 233 +++++++++
>  include/efi_loader.h          |   4 +
>  lib/efi_loader/Makefile       |   1 +
>  lib/efi_loader/efi_boottime.c |  12 +
>  lib/efi_loader/efi_hii.c      | 886 ++++++++++++++++++++++++++++++++++
>  5 files changed, 1136 insertions(+)
>  create mode 100644 lib/efi_loader/efi_hii.c
> 
> diff --git a/include/efi_api.h b/include/efi_api.h
> index 88a60070f6ab..ec1b759d810a 100644
> --- a/include/efi_api.h
> +++ b/include/efi_api.h
> @@ -17,6 +17,7 @@
>  #define _EFI_API_H
>  
>  #include <efi.h>
> +#include <charset.h>
>  
>  #ifdef CONFIG_EFI_LOADER
>  #include <asm/setjmp.h>
> @@ -697,6 +698,238 @@ struct efi_device_path_utilities_protocol {
>  		uint16_t node_length);
>  };
>  
> +typedef u16 efi_string_id_t;
> +
> +#define EFI_HII_DATABASE_PROTOCOL_GUID	     \
> +	EFI_GUID(0xef9fc172, 0xa1b2, 0x4693, \
> +		 0xb3, 0x27, 0x6d, 0x32, 0xfc, 0x41, 0x60, 0x42)
> +
> +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 {
> +	efi_key key;
> +	u16 unicode;
> +	u16 shifted_unicode;
> +	u16 alt_gr_unicode;
> +	u16 shifted_alt_gr_unicode;
> +	u16 modifier;
> +	u16 affected_attribute;
> +};
> +
> +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[];
> +};
> +
> +struct efi_hii_package_list_header {
> +	efi_guid_t package_list_guid;
> +	u32 package_length;
> +} __packed;
> +

Here you are taking Alex's comment into account where he recommended to
avoid bit-fields.

Please, add a comment indicating the sub-fields hidden in 'fields', e.g.

/**
 * 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;
 */

(The double colon :: is the Sphinx indicator for preformatted text.)

> +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
> +

These macros are U-Boot specific. Please, describe them.

> +#define EFI_HII_PACKAGE_HEADER(header, field) \
> +		(((header)->fields >> EFI_HII_PACKAGE_##field##_SHIFT) \
> +		 & EFI_HII_PACKAGE_##field##_MASK)
> +#define efi_hii_package_len(header) \
> +		EFI_HII_PACKAGE_HEADER(header, LEN)
> +#define efi_hii_package_type(header) \
> +		EFI_HII_PACKAGE_HEADER(header, TYPE)
> +

Best regards

Heinrich

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 6/6] efi_selftest: add HII database protocols test
  2018-11-01  4:47   ` [U-Boot] [PATCH 6/6] efi_selftest: add HII database protocols test AKASHI Takahiro
@ 2018-11-01  7:33     ` Heinrich Schuchardt
  2018-11-02  0:55       ` AKASHI Takahiro
  0 siblings, 1 reply; 19+ messages in thread
From: Heinrich Schuchardt @ 2018-11-01  7:33 UTC (permalink / raw)
  To: u-boot

On 11/01/2018 05:47 AM, AKASHI Takahiro wrote:
> This efi_selftest tests HII database protocol and HII string protocol.
> 
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>  lib/efi_selftest/Makefile                |   1 +
>  lib/efi_selftest/efi_selftest_hii.c      | 882 +++++++++++++++++++++++
>  lib/efi_selftest/efi_selftest_hii_data.c | 450 ++++++++++++
>  3 files changed, 1333 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 4b1c0bb84b18..1209b54b07cd 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_rtc.o \
> diff --git a/lib/efi_selftest/efi_selftest_hii.c b/lib/efi_selftest/efi_selftest_hii.c
> new file mode 100644
> index 000000000000..2d5fe095a9b2
> --- /dev/null
> +++ b/lib/efi_selftest/efi_selftest_hii.c
> @@ -0,0 +1,882 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * efi_selftest_hii
> + *
> + * Copyright (c) 2018 AKASHI Takahiro, Linaro Limited
> + *
> + * Test HII database protocols
> + */
> +
> +#include <efi_selftest.h>
> +#include <malloc.h>
> +#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

Thanks a lot for providing unit tests for the protocols.

%s/Tests/tests/

> + */
> +

Please, add a comment to each test describing what it is doing, e.g.

/**
 * test_hii_database_new_package_list() - test creation and removal of
package lists
 *
 * 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", (int)ret);

%s/int/unsigned int/

> +		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", (int)ret);

%s/int/unsigned int/

Same change needed all over the file.

Best regards

Heinrich

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 2/6] efi_loader: Initial HII database protocols
  2018-11-01  4:47 ` [U-Boot] [PATCH 2/6] efi_loader: Initial HII database protocols AKASHI Takahiro
                     ` (4 preceding siblings ...)
  2018-11-01  7:09   ` [U-Boot] [PATCH 2/6] efi_loader: Initial HII database protocols Heinrich Schuchardt
@ 2018-11-01  7:39   ` Heinrich Schuchardt
  2018-11-02  0:32     ` AKASHI Takahiro
  2018-11-01  8:42   ` Heinrich Schuchardt
  6 siblings, 1 reply; 19+ messages in thread
From: Heinrich Schuchardt @ 2018-11-01  7:39 UTC (permalink / raw)
  To: u-boot

On 11/01/2018 05:47 AM, AKASHI Takahiro wrote:
> From: Leif Lindholm <leif.lindholm@linaro.org>
> 
> 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)
> 

<snip />

> +		case EFI_HII_PACKAGE_STRINGS:
> +			ret = add_strings_package(hii,
> +				(struct efi_hii_strings_package *)package);

scripts/checkpatch.pl:

CHECK: Alignment should match open parenthesis
#583: FILE: lib/efi_loader/efi_hii.c:231:
+                       ret = add_strings_package(hii,
+                               (struct efi_hii_strings_package *)package);

Please, adjust the alignment.

Best regards

Heinrich

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 2/6] efi_loader: Initial HII database protocols
  2018-11-01  4:47 ` [U-Boot] [PATCH 2/6] efi_loader: Initial HII database protocols AKASHI Takahiro
                     ` (5 preceding siblings ...)
  2018-11-01  7:39   ` Heinrich Schuchardt
@ 2018-11-01  8:42   ` Heinrich Schuchardt
  2018-11-02  0:17     ` AKASHI Takahiro
  6 siblings, 1 reply; 19+ messages in thread
From: Heinrich Schuchardt @ 2018-11-01  8:42 UTC (permalink / raw)
  To: u-boot

On 11/01/2018 05:47 AM, AKASHI Takahiro wrote:
> From: Leif Lindholm <leif.lindholm@linaro.org>
> 
> 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 can handle only:
>   * GUID package
>   * string package
>   * keyboard layout package
>   (The oterh packages, exept Device path package, will be necessary

You can use aspell for spell checking.

>    for interactive and graphical UI.)
> 
> We'll fill in the rest once SCT is running properly so we can validate
> the implementation against the conformance test suite.
> 

Why do you introduce per package type coding in functions like
UpdatePackageList()?

The HII data base protocol keeps track of package lists. There is
nothing package type specific. You can walk through all packages in a
list starting at the header because each package has a length field
irrespective of the type.

You do not want to copy any part of the package list because you need
the original byte sequence in ExportPackageLists.

The only package type that is a bit special is the GUID package. When
walking through a package list the GUID is part of the package type
specification. So you have to consider it in UpdatePacketList() when
doing notifications and deletions.

Best regards

Heinrich

> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Signed-off-by: Rob Clark <robdclark@gmail.com>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>  include/efi_api.h             | 233 +++++++++
>  include/efi_loader.h          |   4 +
>  lib/efi_loader/Makefile       |   1 +
>  lib/efi_loader/efi_boottime.c |  12 +
>  lib/efi_loader/efi_hii.c      | 886 ++++++++++++++++++++++++++++++++++
>  5 files changed, 1136 insertions(+)
>  create mode 100644 lib/efi_loader/efi_hii.c
> 
> diff --git a/include/efi_api.h b/include/efi_api.h
> index 88a60070f6ab..ec1b759d810a 100644
> --- a/include/efi_api.h
> +++ b/include/efi_api.h
> @@ -17,6 +17,7 @@
>  #define _EFI_API_H
>  
>  #include <efi.h>
> +#include <charset.h>
>  
>  #ifdef CONFIG_EFI_LOADER
>  #include <asm/setjmp.h>
> @@ -697,6 +698,238 @@ struct efi_device_path_utilities_protocol {
>  		uint16_t node_length);
>  };
>  
> +typedef u16 efi_string_id_t;
> +
> +#define EFI_HII_DATABASE_PROTOCOL_GUID	     \
> +	EFI_GUID(0xef9fc172, 0xa1b2, 0x4693, \
> +		 0xb3, 0x27, 0x6d, 0x32, 0xfc, 0x41, 0x60, 0x42)
> +
> +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 {
> +	efi_key key;
> +	u16 unicode;
> +	u16 shifted_unicode;
> +	u16 alt_gr_unicode;
> +	u16 shifted_alt_gr_unicode;
> +	u16 modifier;
> +	u16 affected_attribute;
> +};
> +
> +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[];
> +};
> +
> +struct efi_hii_package_list_header {
> +	efi_guid_t package_list_guid;
> +	u32 package_length;
> +} __packed;
> +
> +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_HEADER(header, field) \
> +		(((header)->fields >> EFI_HII_PACKAGE_##field##_SHIFT) \
> +		 & EFI_HII_PACKAGE_##field##_MASK)
> +#define efi_hii_package_len(header) \
> +		EFI_HII_PACKAGE_HEADER(header, LEN)
> +#define efi_hii_package_type(header) \
> +		EFI_HII_PACKAGE_HEADER(header, TYPE)
> +
> +#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
> +
> +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;
> +}
> +
> +typedef void *efi_hii_handle_t;
> +
> +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_HII_STRING_PROTOCOL_GUID \
> +	EFI_GUID(0x0fd96974, 0x23aa, 0x4cdc, \
> +		 0xb9, 0xcb, 0x98, 0xd1, 0x77, 0x50, 0x32, 0x2a)
> +
> +typedef u32 efi_hii_font_style_t;
> +
> +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_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 2ec73592ff30..615314909b17 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 6703435947f2..e508481fdeeb 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 eb652e834856..b1d7f6b36f89 100644
> --- a/lib/efi_loader/efi_boottime.c
> +++ b/lib/efi_loader/efi_boottime.c
> @@ -1550,6 +1550,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 000000000000..40034c27473d
> --- /dev/null
> +++ b/lib/efi_loader/efi_hii.c
> @@ -0,0 +1,886 @@
> +// 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 <common.h>
> +#include <malloc.h>
> +#include <efi_loader.h>
> +
> +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;
> +
> +const u32 hii_package_signature = 0x68696770; /* "higp" */
> +
> +static LIST_HEAD(efi_package_lists);
> +
> +struct efi_hii_packagelist {
> +	struct list_head link;
> +	u32 signature;
> +	// 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 */
> +};
> +
> +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", strings_package->header_size);
> +	debug("string_info_offset: %08x\n",
> +	      strings_package->string_info_offset);
> +	debug("language_name: %u\n", strings_package->language_name);
> +	debug("language: %s\n", strings_package->language);
> +
> +	/* count # of string entries: */
> +	block = ((void *)strings_package) + strings_package->string_info_offset;
> +	end = ((void *)strings_package)
> +			+ efi_hii_package_len(&strings_package->header);
> +	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 = 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) + 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++;
> +			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->signature = hii_package_signature;
> +	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) + package_list->package_length;
> +
> +	debug("package_list: %pUl (%u)\n", &package_list->package_list_guid,
> +	      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 (!hii || hii->signature != hii_package_signature)
> +		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 (!hii || hii->signature != hii_package_signature)
> +		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,
> +	      package_list->package_length);
> +
> +	package = ((void *)package_list) + sizeof(*package_list);
> +	end = ((void *)package_list) + 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: partially destroy a package */
> +		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_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)
> +{
> +	char *p, *endp;
> +
> +	p = languages;
> +	while (*p) {
> +		endp = strchr(p, ';');
> +		if (!endp)
> +			return !strcmp(language, p);
> +
> +		if (!strncmp(language, p, endp - p))
> +			return true;
> +
> +		p = endp + 1;
> +	}
> +
> +	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 (!hii || hii->signature != hii_package_signature)
> +		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 (!hii || hii->signature != hii_package_signature)
> +		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 (!hii || hii->signature != hii_package_signature)
> +		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 (!hii || hii->signature != hii_package_signature)
> +		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 += sprintf(p, ";");
> +		p += sprintf(p, "%s", stbl->language);
> +	}
> +
> +	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 (!hii || hii->signature != hii_package_signature)
> +		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
> +};
> 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 1/6] lib: add u16_strcpy/strdup functions
  2018-11-01  6:10   ` Heinrich Schuchardt
@ 2018-11-02  0:12     ` AKASHI Takahiro
  0 siblings, 0 replies; 19+ messages in thread
From: AKASHI Takahiro @ 2018-11-02  0:12 UTC (permalink / raw)
  To: u-boot

On Thu, Nov 01, 2018 at 07:10:59AM +0100, Heinrich Schuchardt wrote:
> On 11/01/2018 05:45 AM, AKASHI Takahiro wrote:
> > From: "Akashi Takahiro" <takahiro.akashi@linaro.org>
> > 
> > Add u16_strcpy() and u16_strdup(). The latter function will be
> > used later in implementing efi HII database protocol.
> > 
> > Signed-off-by: Akashi Takahiro <takahiro.akashi@linaro.org>
> > ---
> >  include/charset.h | 18 ++++++++++++++++++
> >  lib/charset.c     | 29 +++++++++++++++++++++++++++++
> >  2 files changed, 47 insertions(+)
> > 
> > diff --git a/include/charset.h b/include/charset.h
> > index 4d45e246e515..5807f02b1a04 100644
> > --- a/include/charset.h
> > +++ b/include/charset.h
> > @@ -191,6 +191,24 @@ size_t u16_strlen(const u16 *in);
> >   */
> >  size_t u16_strnlen(const u16 *in, size_t count);
> >  
> > +/* TODO: add descriptions */
> 
> You could use the descriptions below.

Thanks. Actually I forgot to delete this line :)
I will take your description anyway.

-Takahiro Akashi

> > +/**
> > + * 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 10557b9e753d..5e349ed5ee45 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)
> >  {
> > 
> 
> For everything I added to charset.c I implemented tests in
> test/unicode_ut.c.
> 
> Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 2/6] efi_loader: Initial HII database protocols
  2018-11-01  8:42   ` Heinrich Schuchardt
@ 2018-11-02  0:17     ` AKASHI Takahiro
  0 siblings, 0 replies; 19+ messages in thread
From: AKASHI Takahiro @ 2018-11-02  0:17 UTC (permalink / raw)
  To: u-boot

On Thu, Nov 01, 2018 at 09:42:25AM +0100, Heinrich Schuchardt wrote:
> On 11/01/2018 05:47 AM, AKASHI Takahiro wrote:
> > From: Leif Lindholm <leif.lindholm@linaro.org>
> > 
> > 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 can handle only:
> >   * GUID package
> >   * string package
> >   * keyboard layout package
> >   (The oterh packages, exept Device path package, will be necessary
> 
> You can use aspell for spell checking.

This line was added after spell check :)

> >    for interactive and graphical UI.)
> > 
> > We'll fill in the rest once SCT is running properly so we can validate
> > the implementation against the conformance test suite.
> > 
> 
> Why do you introduce per package type coding in functions like
> UpdatePackageList()?
> 
> The HII data base protocol keeps track of package lists. There is
> nothing package type specific. You can walk through all packages in a
> list starting at the header because each package has a length field
> irrespective of the type.
> 
> You do not want to copy any part of the package list because you need
> the original byte sequence in ExportPackageLists.
> 
> The only package type that is a bit special is the GUID package. When
> walking through a package list the GUID is part of the package type
> specification. So you have to consider it in UpdatePacketList() when
> doing notifications and deletions.

I don't agree with you.
We should de-serialize the contents of a package list for later use.
You can easily understand this when you look at a strings package
and a keyboard layout package.

-Takahiro Akashi

> Best regards
> 
> Heinrich
> 
> > Cc: Leif Lindholm <leif.lindholm@linaro.org>
> > Signed-off-by: Rob Clark <robdclark@gmail.com>
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > ---
> >  include/efi_api.h             | 233 +++++++++
> >  include/efi_loader.h          |   4 +
> >  lib/efi_loader/Makefile       |   1 +
> >  lib/efi_loader/efi_boottime.c |  12 +
> >  lib/efi_loader/efi_hii.c      | 886 ++++++++++++++++++++++++++++++++++
> >  5 files changed, 1136 insertions(+)
> >  create mode 100644 lib/efi_loader/efi_hii.c
> > 
> > diff --git a/include/efi_api.h b/include/efi_api.h
> > index 88a60070f6ab..ec1b759d810a 100644
> > --- a/include/efi_api.h
> > +++ b/include/efi_api.h
> > @@ -17,6 +17,7 @@
> >  #define _EFI_API_H
> >  
> >  #include <efi.h>
> > +#include <charset.h>
> >  
> >  #ifdef CONFIG_EFI_LOADER
> >  #include <asm/setjmp.h>
> > @@ -697,6 +698,238 @@ struct efi_device_path_utilities_protocol {
> >  		uint16_t node_length);
> >  };
> >  
> > +typedef u16 efi_string_id_t;
> > +
> > +#define EFI_HII_DATABASE_PROTOCOL_GUID	     \
> > +	EFI_GUID(0xef9fc172, 0xa1b2, 0x4693, \
> > +		 0xb3, 0x27, 0x6d, 0x32, 0xfc, 0x41, 0x60, 0x42)
> > +
> > +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 {
> > +	efi_key key;
> > +	u16 unicode;
> > +	u16 shifted_unicode;
> > +	u16 alt_gr_unicode;
> > +	u16 shifted_alt_gr_unicode;
> > +	u16 modifier;
> > +	u16 affected_attribute;
> > +};
> > +
> > +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[];
> > +};
> > +
> > +struct efi_hii_package_list_header {
> > +	efi_guid_t package_list_guid;
> > +	u32 package_length;
> > +} __packed;
> > +
> > +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_HEADER(header, field) \
> > +		(((header)->fields >> EFI_HII_PACKAGE_##field##_SHIFT) \
> > +		 & EFI_HII_PACKAGE_##field##_MASK)
> > +#define efi_hii_package_len(header) \
> > +		EFI_HII_PACKAGE_HEADER(header, LEN)
> > +#define efi_hii_package_type(header) \
> > +		EFI_HII_PACKAGE_HEADER(header, TYPE)
> > +
> > +#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
> > +
> > +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;
> > +}
> > +
> > +typedef void *efi_hii_handle_t;
> > +
> > +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_HII_STRING_PROTOCOL_GUID \
> > +	EFI_GUID(0x0fd96974, 0x23aa, 0x4cdc, \
> > +		 0xb9, 0xcb, 0x98, 0xd1, 0x77, 0x50, 0x32, 0x2a)
> > +
> > +typedef u32 efi_hii_font_style_t;
> > +
> > +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_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 2ec73592ff30..615314909b17 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 6703435947f2..e508481fdeeb 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 eb652e834856..b1d7f6b36f89 100644
> > --- a/lib/efi_loader/efi_boottime.c
> > +++ b/lib/efi_loader/efi_boottime.c
> > @@ -1550,6 +1550,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 000000000000..40034c27473d
> > --- /dev/null
> > +++ b/lib/efi_loader/efi_hii.c
> > @@ -0,0 +1,886 @@
> > +// 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 <common.h>
> > +#include <malloc.h>
> > +#include <efi_loader.h>
> > +
> > +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;
> > +
> > +const u32 hii_package_signature = 0x68696770; /* "higp" */
> > +
> > +static LIST_HEAD(efi_package_lists);
> > +
> > +struct efi_hii_packagelist {
> > +	struct list_head link;
> > +	u32 signature;
> > +	// 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 */
> > +};
> > +
> > +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", strings_package->header_size);
> > +	debug("string_info_offset: %08x\n",
> > +	      strings_package->string_info_offset);
> > +	debug("language_name: %u\n", strings_package->language_name);
> > +	debug("language: %s\n", strings_package->language);
> > +
> > +	/* count # of string entries: */
> > +	block = ((void *)strings_package) + strings_package->string_info_offset;
> > +	end = ((void *)strings_package)
> > +			+ efi_hii_package_len(&strings_package->header);
> > +	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 = 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) + 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++;
> > +			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->signature = hii_package_signature;
> > +	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) + package_list->package_length;
> > +
> > +	debug("package_list: %pUl (%u)\n", &package_list->package_list_guid,
> > +	      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 (!hii || hii->signature != hii_package_signature)
> > +		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 (!hii || hii->signature != hii_package_signature)
> > +		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,
> > +	      package_list->package_length);
> > +
> > +	package = ((void *)package_list) + sizeof(*package_list);
> > +	end = ((void *)package_list) + 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: partially destroy a package */
> > +		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_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)
> > +{
> > +	char *p, *endp;
> > +
> > +	p = languages;
> > +	while (*p) {
> > +		endp = strchr(p, ';');
> > +		if (!endp)
> > +			return !strcmp(language, p);
> > +
> > +		if (!strncmp(language, p, endp - p))
> > +			return true;
> > +
> > +		p = endp + 1;
> > +	}
> > +
> > +	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 (!hii || hii->signature != hii_package_signature)
> > +		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 (!hii || hii->signature != hii_package_signature)
> > +		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 (!hii || hii->signature != hii_package_signature)
> > +		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 (!hii || hii->signature != hii_package_signature)
> > +		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 += sprintf(p, ";");
> > +		p += sprintf(p, "%s", stbl->language);
> > +	}
> > +
> > +	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 (!hii || hii->signature != hii_package_signature)
> > +		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
> > +};
> > 
> 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 2/6] efi_loader: Initial HII database protocols
  2018-11-01  7:39   ` Heinrich Schuchardt
@ 2018-11-02  0:32     ` AKASHI Takahiro
  2018-11-02  8:15       ` Heinrich Schuchardt
  0 siblings, 1 reply; 19+ messages in thread
From: AKASHI Takahiro @ 2018-11-02  0:32 UTC (permalink / raw)
  To: u-boot

On Thu, Nov 01, 2018 at 08:39:04AM +0100, Heinrich Schuchardt wrote:
> On 11/01/2018 05:47 AM, AKASHI Takahiro wrote:
> > From: Leif Lindholm <leif.lindholm@linaro.org>
> > 
> > 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)
> > 
> 
> <snip />
> 
> > +		case EFI_HII_PACKAGE_STRINGS:
> > +			ret = add_strings_package(hii,
> > +				(struct efi_hii_strings_package *)package);
> 
> scripts/checkpatch.pl:
> 
> CHECK: Alignment should match open parenthesis
> #583: FILE: lib/efi_loader/efi_hii.c:231:
> +                       ret = add_strings_package(hii,
> +                               (struct efi_hii_strings_package *)package);

I've noticed this warning as well as another type of warning, such as

CHECK: Lines should not end with a '('
#186: FILE: include/efi_api.h:832:
+       efi_status_t(EFIAPI *new_package_list)(

CHECK: spaces preferred around that '*' (ctx:WxV)
#186: FILE: include/efi_api.h:832:
+       efi_status_t(EFIAPI *new_package_list)(

Those are quite difficult to fix without sacrificing readability
or introducing another warning.
If you have any solution, please let me know.

|        case EFI_HII_PACKAGE_STRINGS:
|               struct efi_hii_strings_package *strings_package;
|
|               strings_package = (struct efi_hii_strings_package *)package);
|               ret = add_strings_package(hii, strings_package);
|                       

This kinda fix is a non-sense, I believe.

-Takahiro Akashi


> Please, adjust the alignment.
> 
> Best regards
> 
> Heinrich

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 6/6] efi_selftest: add HII database protocols test
  2018-11-01  7:33     ` Heinrich Schuchardt
@ 2018-11-02  0:55       ` AKASHI Takahiro
  2018-11-02  8:12         ` Heinrich Schuchardt
  0 siblings, 1 reply; 19+ messages in thread
From: AKASHI Takahiro @ 2018-11-02  0:55 UTC (permalink / raw)
  To: u-boot

On Thu, Nov 01, 2018 at 08:33:09AM +0100, Heinrich Schuchardt wrote:
> On 11/01/2018 05:47 AM, AKASHI Takahiro wrote:
> > This efi_selftest tests HII database protocol and HII string protocol.
> > 
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > ---
> >  lib/efi_selftest/Makefile                |   1 +
> >  lib/efi_selftest/efi_selftest_hii.c      | 882 +++++++++++++++++++++++
> >  lib/efi_selftest/efi_selftest_hii_data.c | 450 ++++++++++++
> >  3 files changed, 1333 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 4b1c0bb84b18..1209b54b07cd 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_rtc.o \
> > diff --git a/lib/efi_selftest/efi_selftest_hii.c b/lib/efi_selftest/efi_selftest_hii.c
> > new file mode 100644
> > index 000000000000..2d5fe095a9b2
> > --- /dev/null
> > +++ b/lib/efi_selftest/efi_selftest_hii.c
> > @@ -0,0 +1,882 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * efi_selftest_hii
> > + *
> > + * Copyright (c) 2018 AKASHI Takahiro, Linaro Limited
> > + *
> > + * Test HII database protocols
> > + */
> > +
> > +#include <efi_selftest.h>
> > +#include <malloc.h>
> > +#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
> 
> Thanks a lot for providing unit tests for the protocols.
> 
> %s/Tests/tests/

Fixed.

> > + */
> > +
> 
> Please, add a comment to each test describing what it is doing, e.g.

OK, but it's a quite painful task.

> /**
>  * test_hii_database_new_package_list() - test creation and removal of
> package lists
>  *
>  * 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", (int)ret);
> 
> %s/int/unsigned int/
> 
> > +		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", (int)ret);
> 
> %s/int/unsigned int/
> 
> Same change needed all over the file.

OK, but the root issue is that efi_st_printf/error() doesn't support
'l' specifier in "%lx" format.

-Takahiro Akashi

> Best regards
> 
> Heinrich

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 2/6] efi_loader: Initial HII database protocols
  2018-11-01  7:09   ` [U-Boot] [PATCH 2/6] efi_loader: Initial HII database protocols Heinrich Schuchardt
@ 2018-11-02  2:03     ` AKASHI Takahiro
  0 siblings, 0 replies; 19+ messages in thread
From: AKASHI Takahiro @ 2018-11-02  2:03 UTC (permalink / raw)
  To: u-boot

On Thu, Nov 01, 2018 at 08:09:45AM +0100, Heinrich Schuchardt wrote:
> On 11/01/2018 05:47 AM, AKASHI Takahiro wrote:
> > From: Leif Lindholm <leif.lindholm@linaro.org>
> > 
> > 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 can handle only:
> >   * GUID package
> >   * string package
> >   * keyboard layout package
> >   (The oterh packages, exept Device path package, will be necessary
> >    for interactive and graphical UI.)
> > 
> > We'll fill in the rest once SCT is running properly so we can validate
> > the implementation against the conformance test suite.
> > 
> > Cc: Leif Lindholm <leif.lindholm@linaro.org>
> > Signed-off-by: Rob Clark <robdclark@gmail.com>
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > ---
> >  include/efi_api.h             | 233 +++++++++
> >  include/efi_loader.h          |   4 +
> >  lib/efi_loader/Makefile       |   1 +
> >  lib/efi_loader/efi_boottime.c |  12 +
> >  lib/efi_loader/efi_hii.c      | 886 ++++++++++++++++++++++++++++++++++
> >  5 files changed, 1136 insertions(+)
> >  create mode 100644 lib/efi_loader/efi_hii.c
> > 
> > diff --git a/include/efi_api.h b/include/efi_api.h
> > index 88a60070f6ab..ec1b759d810a 100644
> > --- a/include/efi_api.h
> > +++ b/include/efi_api.h
> > @@ -17,6 +17,7 @@
> >  #define _EFI_API_H
> >  
> >  #include <efi.h>
> > +#include <charset.h>
> >  
> >  #ifdef CONFIG_EFI_LOADER
> >  #include <asm/setjmp.h>
> > @@ -697,6 +698,238 @@ struct efi_device_path_utilities_protocol {
> >  		uint16_t node_length);
> >  };
> >  
> > +typedef u16 efi_string_id_t;
> > +
> > +#define EFI_HII_DATABASE_PROTOCOL_GUID	     \
> > +	EFI_GUID(0xef9fc172, 0xa1b2, 0x4693, \
> > +		 0xb3, 0x27, 0x6d, 0x32, 0xfc, 0x41, 0x60, 0x42)
> > +
> > +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 {
> > +	efi_key key;
> > +	u16 unicode;
> > +	u16 shifted_unicode;
> > +	u16 alt_gr_unicode;
> > +	u16 shifted_alt_gr_unicode;
> > +	u16 modifier;
> > +	u16 affected_attribute;
> > +};
> > +
> > +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[];
> > +};
> > +
> > +struct efi_hii_package_list_header {
> > +	efi_guid_t package_list_guid;
> > +	u32 package_length;
> > +} __packed;
> > +
> 
> Here you are taking Alex's comment into account where he recommended to
> avoid bit-fields.
> 
> Please, add a comment indicating the sub-fields hidden in 'fields', e.g.

Sure.

> /**
>  * 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;
>  */
> 
> (The double colon :: is the Sphinx indicator for preformatted text.)
> 
> > +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
> > +
> 
> These macros are U-Boot specific. Please, describe them.

I think that the meanings will be trivial with a description above.
Or do you mean that we should say clearly that those are u-boot specific?

Thanks,
-Takahiro Akashi

> > +#define EFI_HII_PACKAGE_HEADER(header, field) \
> > +		(((header)->fields >> EFI_HII_PACKAGE_##field##_SHIFT) \
> > +		 & EFI_HII_PACKAGE_##field##_MASK)
> > +#define efi_hii_package_len(header) \
> > +		EFI_HII_PACKAGE_HEADER(header, LEN)
> > +#define efi_hii_package_type(header) \
> > +		EFI_HII_PACKAGE_HEADER(header, TYPE)
> > +
> 
> Best regards
> 
> Heinrich

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 6/6] efi_selftest: add HII database protocols test
  2018-11-02  0:55       ` AKASHI Takahiro
@ 2018-11-02  8:12         ` Heinrich Schuchardt
  0 siblings, 0 replies; 19+ messages in thread
From: Heinrich Schuchardt @ 2018-11-02  8:12 UTC (permalink / raw)
  To: u-boot

On 11/02/2018 01:55 AM, AKASHI Takahiro wrote:
> On Thu, Nov 01, 2018 at 08:33:09AM +0100, Heinrich Schuchardt wrote:
>> On 11/01/2018 05:47 AM, AKASHI Takahiro wrote:
>>> This efi_selftest tests HII database protocol and HII string protocol.
>>>

<snip />

> 
> OK, but the root issue is that efi_st_printf/error() doesn't support
> 'l' specifier in "%lx" format.

You could use efi_st_error("remove_package_list returned %p\n",
(void *)ret);

Regards

Heinrich

> 
> -Takahiro Akashi
> 
>> Best regards
>>
>> Heinrich
> 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 2/6] efi_loader: Initial HII database protocols
  2018-11-02  0:32     ` AKASHI Takahiro
@ 2018-11-02  8:15       ` Heinrich Schuchardt
  0 siblings, 0 replies; 19+ messages in thread
From: Heinrich Schuchardt @ 2018-11-02  8:15 UTC (permalink / raw)
  To: u-boot

On 11/02/2018 01:32 AM, AKASHI Takahiro wrote:
> On Thu, Nov 01, 2018 at 08:39:04AM +0100, Heinrich Schuchardt wrote:
>> On 11/01/2018 05:47 AM, AKASHI Takahiro wrote:
>>> From: Leif Lindholm <leif.lindholm@linaro.org>
>>>
>>> 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)
>>>
>>
>> <snip />
>>
>>> +		case EFI_HII_PACKAGE_STRINGS:
>>> +			ret = add_strings_package(hii,
>>> +				(struct efi_hii_strings_package *)package);
>>
>> scripts/checkpatch.pl:
>>
>> CHECK: Alignment should match open parenthesis
>> #583: FILE: lib/efi_loader/efi_hii.c:231:
>> +                       ret = add_strings_package(hii,
>> +                               (struct efi_hii_strings_package *)package);
> 
> I've noticed this warning as well as another type of warning, such as
> 
> CHECK: Lines should not end with a '('
> #186: FILE: include/efi_api.h:832:
> +       efi_status_t(EFIAPI *new_package_list)(
> 
> CHECK: spaces preferred around that '*' (ctx:WxV)
> #186: FILE: include/efi_api.h:832:
> +       efi_status_t(EFIAPI *new_package_list)(
> 

These you can ignore. This is a bug you could report to the upstream
maintainer of checkpatch.pl (at kernel.org).

Regards

Heinrich

> Those are quite difficult to fix without sacrificing readability
> or introducing another warning.
> If you have any solution, please let me know.
> 
> |        case EFI_HII_PACKAGE_STRINGS:
> |               struct efi_hii_strings_package *strings_package;
> |
> |               strings_package = (struct efi_hii_strings_package *)package);
> |               ret = add_strings_package(hii, strings_package);
> |                       
> 
> This kinda fix is a non-sense, I believe.
> 
> -Takahiro Akashi
> 
> 
>> Please, adjust the alignment.
>>
>> Best regards
>>
>> Heinrich
> 

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2018-11-02  8:15 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-01  4:40 [U-Boot] [PATCH 0/6] efi_loader: add HII database protocol AKASHI Takahiro
2018-11-01  4:45 ` [U-Boot] [PATCH 1/6] lib: add u16_strcpy/strdup functions AKASHI Takahiro
2018-11-01  6:10   ` Heinrich Schuchardt
2018-11-02  0:12     ` AKASHI Takahiro
2018-11-01  4:47 ` [U-Boot] [PATCH 2/6] efi_loader: Initial HII database protocols AKASHI Takahiro
2018-11-01  4:47   ` [U-Boot] [PATCH 3/6] efi: hii: add guid package support AKASHI Takahiro
2018-11-01  4:47   ` [U-Boot] [PATCH 4/6] efi: hii: add keyboard layout " AKASHI Takahiro
2018-11-01  4:47   ` [U-Boot] [PATCH 5/6] efi: hii: add HII config routing/access protocols AKASHI Takahiro
2018-11-01  4:47   ` [U-Boot] [PATCH 6/6] efi_selftest: add HII database protocols test AKASHI Takahiro
2018-11-01  7:33     ` Heinrich Schuchardt
2018-11-02  0:55       ` AKASHI Takahiro
2018-11-02  8:12         ` Heinrich Schuchardt
2018-11-01  7:09   ` [U-Boot] [PATCH 2/6] efi_loader: Initial HII database protocols Heinrich Schuchardt
2018-11-02  2:03     ` AKASHI Takahiro
2018-11-01  7:39   ` Heinrich Schuchardt
2018-11-02  0:32     ` AKASHI Takahiro
2018-11-02  8:15       ` Heinrich Schuchardt
2018-11-01  8:42   ` Heinrich Schuchardt
2018-11-02  0:17     ` AKASHI Takahiro

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.