mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Ahmad Fatoum <a.fatoum@pengutronix.de>
To: barebox@lists.infradead.org
Cc: Ahmad Fatoum <a.fatoum@pengutronix.de>
Subject: [PATCH v1 30/54] efi: loader: protocol: add HII support
Date: Thu, 18 Dec 2025 11:37:50 +0100	[thread overview]
Message-ID: <20251218111242.1527495-31-a.fatoum@pengutronix.de> (raw)
In-Reply-To: <20251218111242.1527495-1-a.fatoum@pengutronix.de>

Port from U-Boot its bare minium HII support, so the UEFI shell can be
run.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 efi/loader/Kconfig                |    2 +
 efi/loader/protocols/Kconfig      |   16 +
 efi/loader/protocols/Makefile     |    1 +
 efi/loader/protocols/hii.c        | 1100 +++++++++++++++++++++++++++++
 efi/loader/protocols/hii_config.c |  157 ++++
 include/efi/protocol/hii.h        |  428 +++++++++++
 6 files changed, 1704 insertions(+)
 create mode 100644 efi/loader/protocols/Kconfig
 create mode 100644 efi/loader/protocols/hii.c
 create mode 100644 efi/loader/protocols/hii_config.c
 create mode 100644 include/efi/protocol/hii.h

diff --git a/efi/loader/Kconfig b/efi/loader/Kconfig
index eaa5087b9ab8..d54783f9a084 100644
--- a/efi/loader/Kconfig
+++ b/efi/loader/Kconfig
@@ -29,3 +29,5 @@ config EFI_LOADER_SET_TIME
 	  can be used by an EFI application to adjust the real time clock.
 
 endmenu
+
+source "efi/loader/protocols/Kconfig"
diff --git a/efi/loader/protocols/Kconfig b/efi/loader/protocols/Kconfig
new file mode 100644
index 000000000000..4ed7499da4a2
--- /dev/null
+++ b/efi/loader/protocols/Kconfig
@@ -0,0 +1,16 @@
+# SPDX-License-Identifier: GPL-2.0
+
+menu "UEFI protocol support"
+
+config EFI_LOADER_HII
+	bool "HII protocols"
+	default y
+	help
+	  The Human Interface Infrastructure is a complicated framework that
+	  allows UEFI applications to draw fancy menus and hook strings using
+	  a translation framework.
+
+	  barebox implements enough of its features to be able to run the UEFI
+	  Shell, but not more than that.
+
+endmenu
diff --git a/efi/loader/protocols/Makefile b/efi/loader/protocols/Makefile
index 472dd54116c5..f4a9c0650fd9 100644
--- a/efi/loader/protocols/Makefile
+++ b/efi/loader/protocols/Makefile
@@ -4,3 +4,4 @@ obj-$(CONFIG_FS) += file.o
 obj-$(CONFIG_DISK) += disk.o
 obj-$(CONFIG_VIDEO) += gop.o
 obj-$(CONFIG_CONSOLE_FULL) += console.o
+obj-$(CONFIG_EFI_LOADER_HII) += hii.o hii_config.o
diff --git a/efi/loader/protocols/hii.c b/efi/loader/protocols/hii.c
new file mode 100644
index 000000000000..f35489eba283
--- /dev/null
+++ b/efi/loader/protocols/hii.c
@@ -0,0 +1,1100 @@
+// 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 <charset.h>
+#include <linux/printk.h>
+#include <efi/loader.h>
+#include <efi/guid.h>
+#include <efi/error.h>
+#include <efi/guid.h>
+#include <efi/loader/object.h>
+#include <efi/protocol/hii.h>
+#include <efi/loader/trace.h>
+#include <malloc.h>
+#include <wchar.h>
+#include <asm/unaligned.h>
+#include <init.h>
+
+static LIST_HEAD(efi_package_lists);
+static LIST_HEAD(efi_keyboard_layout_list);
+
+struct efi_hii_packagelist {
+	struct list_head link;
+	// TODO should there be an associated efi_object?
+	efi_handle_t driver_handle;
+	u32 max_string_id;
+	struct list_head string_tables;     /* list of efi_string_table */
+	struct list_head guid_list;
+	struct list_head keyboard_packages;
+
+	/* we could also track fonts, images, etc */
+};
+
+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) +
+		(wcslen(blk->string_text) + 1) * 2;
+}
+
+static int efi_hii_packagelist_exists(efi_hii_handle_t package_list)
+{
+	struct efi_hii_packagelist *hii;
+	int found = 0;
+
+	list_for_each_entry(hii, &efi_package_lists, link) {
+		if (hii == package_list) {
+			found = 1;
+			break;
+		}
+	}
+
+	return found;
+}
+
+static u32 efi_hii_package_type(struct efi_hii_package_header *header)
+{
+	u32 fields;
+
+	fields = get_unaligned_le32(&header->fields);
+
+	return (fields >> __EFI_HII_PACKAGE_TYPE_SHIFT)
+		& __EFI_HII_PACKAGE_TYPE_MASK;
+}
+
+static u32 efi_hii_package_len(struct efi_hii_package_header *header)
+{
+	u32 fields;
+
+	fields = get_unaligned_le32(&header->fields);
+
+	return (fields >> __EFI_HII_PACKAGE_LEN_SHIFT)
+		& __EFI_HII_PACKAGE_LEN_MASK;
+}
+
+struct efi_string_info {
+	efi_string_t string;
+	/* we could also track font info, etc */
+};
+
+struct efi_string_table {
+	struct list_head link;
+	efi_string_id_t language_name;
+	char *language;
+	u32 nstrings;
+	/*
+	 * NOTE:
+	 *  string id starts at 1 so value is stbl->strings[id-1],
+	 *  and strings[] is a array of stbl->nstrings elements
+	 */
+	struct efi_string_info *strings;
+};
+
+struct efi_guid_data {
+	struct list_head link;
+	struct efi_hii_guid_package package;
+};
+
+struct efi_keyboard_layout_data {
+	struct list_head link;		/* in package */
+	struct list_head link_sys;	/* in global list */
+	struct efi_hii_keyboard_layout keyboard_layout;
+};
+
+struct efi_keyboard_package_data {
+	struct list_head link;		/* in package_list */
+	struct list_head keyboard_layout_list;
+};
+
+static void free_strings_table(struct efi_string_table *stbl)
+{
+	int i;
+
+	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;
+
+	EFI_PRINT("header_size: %08x\n",
+		  get_unaligned_le32(&strings_package->header_size));
+	EFI_PRINT("string_info_offset: %08x\n",
+		  get_unaligned_le32(&strings_package->string_info_offset));
+	EFI_PRINT("language_name: %u\n",
+		  get_unaligned_le16(&strings_package->language_name));
+	EFI_PRINT("language: %s\n", strings_package->language);
+
+	/* count # of string entries: */
+	end = ((void *)strings_package)
+			+ efi_hii_package_len(&strings_package->header);
+	block = ((void *)strings_package)
+		+ get_unaligned_le32(&strings_package->string_info_offset);
+
+	while ((void *)block < end) {
+		switch (block->block_type) {
+		case EFI_HII_SIBT_STRING_UCS2: {
+			struct efi_hii_sibt_string_ucs2_block *ucs2;
+
+			ucs2 = (void *)block;
+			nstrings++;
+			block = efi_hii_sibt_string_ucs2_block_next(ucs2);
+			break;
+		}
+		case EFI_HII_SIBT_END:
+			block = end;
+			break;
+		default:
+			EFI_PRINT("unknown HII string block type: %02x\n",
+				  block->block_type);
+			return EFI_INVALID_PARAMETER;
+		}
+	}
+
+	stbl = calloc(sizeof(*stbl), 1);
+	if (!stbl) {
+		ret = EFI_OUT_OF_RESOURCES;
+		goto error;
+	}
+	stbl->strings = calloc(sizeof(stbl->strings[0]), nstrings);
+	if (!stbl->strings) {
+		ret = EFI_OUT_OF_RESOURCES;
+		goto error;
+	}
+	stbl->language_name =
+			get_unaligned_le16(&strings_package->language_name);
+	stbl->language = strdup((char *)strings_package->language);
+	if (!stbl->language) {
+		ret = EFI_OUT_OF_RESOURCES;
+		goto error;
+	}
+	stbl->nstrings = nstrings;
+
+	/* and now parse string entries and populate efi_string_table */
+	block = ((void *)strings_package)
+		+ get_unaligned_le32(&strings_package->string_info_offset);
+
+	while ((void *)block < end) {
+		switch (block->block_type) {
+		case EFI_HII_SIBT_STRING_UCS2: {
+			struct efi_hii_sibt_string_ucs2_block *ucs2;
+
+			ucs2 = (void *)block;
+			EFI_PRINT("%4u: \"%ls\"\n", idx + 1, ucs2->string_text);
+			stbl->strings[idx].string =
+				u16_strdup(ucs2->string_text);
+			if (!stbl->strings[idx].string) {
+				ret = EFI_OUT_OF_RESOURCES;
+				goto error;
+			}
+			idx++;
+			/* FIXME: accessing u16 * here */
+			block = efi_hii_sibt_string_ucs2_block_next(ucs2);
+			break;
+		}
+		case EFI_HII_SIBT_END:
+			goto out;
+		default:
+			EFI_PRINT("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);
+		while (idx > 0)
+			free(stbl->strings[--idx].string);
+		free(stbl->strings);
+	}
+	free(stbl);
+
+	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 void free_keyboard_layouts(struct efi_keyboard_package_data *package)
+{
+	struct efi_keyboard_layout_data *layout_data;
+
+	while (!list_empty(&package->keyboard_layout_list)) {
+		layout_data = list_first_entry(&package->keyboard_layout_list,
+					       struct efi_keyboard_layout_data,
+					       link);
+		list_del(&layout_data->link);
+		list_del(&layout_data->link_sys);
+		free(layout_data);
+	}
+}
+
+static void remove_keyboard_package(struct efi_hii_packagelist *hii)
+{
+	struct efi_keyboard_package_data *package;
+
+	while (!list_empty(&hii->keyboard_packages)) {
+		package = list_first_entry(&hii->keyboard_packages,
+					   struct efi_keyboard_package_data,
+					   link);
+		free_keyboard_layouts(package);
+		list_del(&package->link);
+		free(package);
+	}
+}
+
+static efi_status_t
+add_keyboard_package(struct efi_hii_packagelist *hii,
+		     struct efi_hii_keyboard_package *keyboard_package)
+{
+	struct efi_keyboard_package_data *package_data;
+	struct efi_hii_keyboard_layout *layout;
+	struct efi_keyboard_layout_data *layout_data;
+	u16 layout_count, layout_length;
+	int i;
+
+	package_data = malloc(sizeof(*package_data));
+	if (!package_data)
+		return EFI_OUT_OF_RESOURCES;
+	INIT_LIST_HEAD(&package_data->link);
+	INIT_LIST_HEAD(&package_data->keyboard_layout_list);
+
+	layout = &keyboard_package->layout[0];
+	layout_count = get_unaligned_le16(&keyboard_package->layout_count);
+	for (i = 0; i < layout_count; i++) {
+		layout_length = get_unaligned_le16(&layout->layout_length);
+		layout_data = malloc(sizeof(*layout_data) + layout_length);
+		if (!layout_data)
+			goto out;
+
+		memcpy(&layout_data->keyboard_layout, layout, layout_length);
+		list_add_tail(&layout_data->link,
+			      &package_data->keyboard_layout_list);
+		list_add_tail(&layout_data->link_sys,
+			      &efi_keyboard_layout_list);
+
+		layout += layout_length;
+	}
+
+	list_add_tail(&package_data->link, &hii->keyboard_packages);
+
+	return EFI_SUCCESS;
+
+out:
+	free_keyboard_layouts(package_data);
+	free(package_data);
+
+	return EFI_OUT_OF_RESOURCES;
+}
+
+static struct efi_hii_packagelist *new_packagelist(void)
+{
+	struct efi_hii_packagelist *hii;
+
+	hii = malloc(sizeof(*hii));
+	if (!hii)
+		return NULL;
+
+	list_add_tail(&hii->link, &efi_package_lists);
+	hii->max_string_id = 0;
+	INIT_LIST_HEAD(&hii->string_tables);
+	INIT_LIST_HEAD(&hii->guid_list);
+	INIT_LIST_HEAD(&hii->keyboard_packages);
+
+	return hii;
+}
+
+static void free_packagelist(struct efi_hii_packagelist *hii)
+{
+	remove_strings_package(hii);
+	remove_guid_package(hii);
+	remove_keyboard_package(hii);
+
+	list_del(&hii->link);
+	free(hii);
+}
+
+static efi_status_t
+add_packages(struct efi_hii_packagelist *hii,
+	     const struct efi_hii_package_list_header *package_list)
+{
+	struct efi_hii_package_header *package;
+	void *end;
+	efi_status_t ret = EFI_SUCCESS;
+
+	end = ((void *)package_list)
+		+ get_unaligned_le32(&package_list->package_length);
+
+	EFI_PRINT("package_list: %pUs (%u)\n", &package_list->package_list_guid,
+		  get_unaligned_le32(&package_list->package_length));
+
+	package = ((void *)package_list) + sizeof(*package_list);
+	while ((void *)package < end) {
+		EFI_PRINT("package=%p, package type=%x, length=%u\n", package,
+			  efi_hii_package_type(package),
+			  efi_hii_package_len(package));
+
+		switch (efi_hii_package_type(package)) {
+		case EFI_HII_PACKAGE_TYPE_GUID:
+			ret = add_guid_package(hii,
+				(struct efi_hii_guid_package *)package);
+			break;
+		case EFI_HII_PACKAGE_FORMS:
+			EFI_PRINT("Form 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:
+			EFI_PRINT("Font package not supported\n");
+			ret = EFI_INVALID_PARAMETER;
+			break;
+		case EFI_HII_PACKAGE_IMAGES:
+			EFI_PRINT("Image package not supported\n");
+			ret = EFI_INVALID_PARAMETER;
+			break;
+		case EFI_HII_PACKAGE_SIMPLE_FONTS:
+			EFI_PRINT("Simple font package not supported\n");
+			ret = EFI_INVALID_PARAMETER;
+			break;
+		case EFI_HII_PACKAGE_DEVICE_PATH:
+			EFI_PRINT("Device path package not supported\n");
+			ret = EFI_INVALID_PARAMETER;
+			break;
+		case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
+			ret = add_keyboard_package(hii,
+				(struct efi_hii_keyboard_package *)package);
+			break;
+		case EFI_HII_PACKAGE_ANIMATIONS:
+			EFI_PRINT("Animation 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;
+	*handle = hii;
+
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI
+remove_package_list(const struct efi_hii_database_protocol *this,
+		    efi_hii_handle_t handle)
+{
+	struct efi_hii_packagelist *hii = handle;
+
+	EFI_ENTRY("%p, %p", this, handle);
+
+	if (!handle || !efi_hii_packagelist_exists(handle))
+		return EFI_EXIT(EFI_NOT_FOUND);
+
+	free_packagelist(hii);
+
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI
+update_package_list(const struct efi_hii_database_protocol *this,
+		    efi_hii_handle_t handle,
+		    const struct efi_hii_package_list_header *package_list)
+{
+	struct efi_hii_packagelist *hii = handle;
+	struct efi_hii_package_header *package;
+	void *end;
+	efi_status_t ret = EFI_SUCCESS;
+
+	EFI_ENTRY("%p, %p, %p", this, handle, package_list);
+
+	if (!handle || !efi_hii_packagelist_exists(handle))
+		return EFI_EXIT(EFI_NOT_FOUND);
+
+	if (!package_list)
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	EFI_PRINT("package_list: %pUs (%u)\n", &package_list->package_list_guid,
+		  get_unaligned_le32(&package_list->package_length));
+
+	package = ((void *)package_list) + sizeof(*package_list);
+	end = ((void *)package_list)
+		+ get_unaligned_le32(&package_list->package_length);
+
+	while ((void *)package < end) {
+		EFI_PRINT("package=%p, package type=%x, length=%u\n", package,
+			  efi_hii_package_type(package),
+			  efi_hii_package_len(package));
+
+		switch (efi_hii_package_type(package)) {
+		case EFI_HII_PACKAGE_TYPE_GUID:
+			remove_guid_package(hii);
+			break;
+		case EFI_HII_PACKAGE_FORMS:
+			EFI_PRINT("Form package not supported\n");
+			ret = EFI_INVALID_PARAMETER;
+			break;
+		case EFI_HII_PACKAGE_STRINGS:
+			remove_strings_package(hii);
+			break;
+		case EFI_HII_PACKAGE_FONTS:
+			EFI_PRINT("Font package not supported\n");
+			ret = EFI_INVALID_PARAMETER;
+			break;
+		case EFI_HII_PACKAGE_IMAGES:
+			EFI_PRINT("Image package not supported\n");
+			ret = EFI_INVALID_PARAMETER;
+			break;
+		case EFI_HII_PACKAGE_SIMPLE_FONTS:
+			EFI_PRINT("Simple font package not supported\n");
+			ret = EFI_INVALID_PARAMETER;
+			break;
+		case EFI_HII_PACKAGE_DEVICE_PATH:
+			EFI_PRINT("Device path package not supported\n");
+			ret = EFI_INVALID_PARAMETER;
+			break;
+		case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
+			remove_keyboard_package(hii);
+			break;
+		case EFI_HII_PACKAGE_ANIMATIONS:
+			EFI_PRINT("Animation package not supported\n");
+			ret = EFI_INVALID_PARAMETER;
+			break;
+		case EFI_HII_PACKAGE_END:
+			goto out;
+		case EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN:
+		case EFI_HII_PACKAGE_TYPE_SYSTEM_END:
+		default:
+			break;
+		}
+
+		/* TODO: already removed some packages */
+		if (ret != EFI_SUCCESS)
+			return EFI_EXIT(ret);
+
+		package = ((void *)package)
+			  + efi_hii_package_len(package);
+	}
+out:
+	ret = add_packages(hii, package_list);
+
+	return EFI_EXIT(ret);
+}
+
+static efi_status_t EFIAPI
+list_package_lists(const struct efi_hii_database_protocol *this,
+		   u8 package_type,
+		   const efi_guid_t *package_guid,
+		   efi_uintn_t *handle_buffer_length,
+		   efi_hii_handle_t *handle)
+{
+	struct efi_hii_packagelist *hii =
+				(struct efi_hii_packagelist *)handle;
+	int package_cnt, package_max;
+	efi_status_t ret = EFI_NOT_FOUND;
+
+	EFI_ENTRY("%p, %u, %pUs, %p, %p", this, package_type, package_guid,
+		  handle_buffer_length, handle);
+
+	if (!handle_buffer_length ||
+	    (*handle_buffer_length && !handle)) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
+	if ((package_type != EFI_HII_PACKAGE_TYPE_GUID && package_guid) ||
+	    (package_type == EFI_HII_PACKAGE_TYPE_GUID && !package_guid)) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
+	EFI_PRINT("package type=%x, guid=%pUs, length=%zu\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:
+			if (!list_empty(&hii->guid_list))
+				break;
+			continue;
+		case EFI_HII_PACKAGE_STRINGS:
+			if (!list_empty(&hii->string_tables))
+				break;
+			continue;
+		case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
+			if (!list_empty(&hii->keyboard_packages))
+				break;
+			continue;
+		default:
+			continue;
+		}
+
+		package_cnt++;
+		if (package_cnt <= package_max) {
+			*handle++ = hii;
+			ret = EFI_SUCCESS;
+		} else {
+			ret = EFI_BUFFER_TOO_SMALL;
+		}
+	}
+	*handle_buffer_length = package_cnt * sizeof(*handle);
+out:
+	return EFI_EXIT(ret);
+}
+
+static efi_status_t EFIAPI
+export_package_lists(const struct efi_hii_database_protocol *this,
+		     efi_hii_handle_t handle,
+		     efi_uintn_t *buffer_size,
+		     struct efi_hii_package_list_header *buffer)
+{
+	EFI_ENTRY("%p, %p, %p, %p", this, handle, buffer_size, buffer);
+
+	if (!buffer_size || !buffer)
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	return EFI_EXIT(EFI_NOT_FOUND);
+}
+
+static efi_status_t EFIAPI
+register_package_notify(const struct efi_hii_database_protocol *this,
+			u8 package_type,
+			const efi_guid_t *package_guid,
+			const void *package_notify_fn,
+			efi_uintn_t notify_type,
+			efi_handle_t *notify_handle)
+{
+	EFI_ENTRY("%p, %u, %pUs, %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)
+{
+	struct efi_keyboard_layout_data *layout_data;
+	int package_cnt, package_max;
+	efi_status_t ret = EFI_SUCCESS;
+
+	EFI_ENTRY("%p, %p, %p", this, key_guid_buffer_length, key_guid_buffer);
+
+	if (!key_guid_buffer_length ||
+	    (*key_guid_buffer_length && !key_guid_buffer))
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	package_cnt = 0;
+	package_max = *key_guid_buffer_length / sizeof(*key_guid_buffer);
+	list_for_each_entry(layout_data, &efi_keyboard_layout_list, link_sys) {
+		package_cnt++;
+		if (package_cnt <= package_max)
+			memcpy(key_guid_buffer++,
+			       &layout_data->keyboard_layout.guid,
+			       sizeof(*key_guid_buffer));
+		else
+			ret = EFI_BUFFER_TOO_SMALL;
+	}
+	*key_guid_buffer_length = package_cnt * sizeof(*key_guid_buffer);
+
+	return EFI_EXIT(ret);
+}
+
+static efi_status_t EFIAPI
+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)
+{
+	struct efi_keyboard_layout_data *layout_data;
+	u16 layout_length;
+
+	EFI_ENTRY("%p, %pUs, %p, %p", this, key_guid, keyboard_layout_length,
+		  keyboard_layout);
+
+	if (!keyboard_layout_length ||
+	    (*keyboard_layout_length && !keyboard_layout))
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	/* TODO: no notion of current keyboard layout */
+	if (!key_guid)
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	list_for_each_entry(layout_data, &efi_keyboard_layout_list, link_sys) {
+		if (!memcmp(layout_data->keyboard_layout.guid, key_guid,
+			    sizeof(efi_guid_t)))
+			goto found;
+	}
+
+	return EFI_EXIT(EFI_NOT_FOUND);
+
+found:
+	layout_length =
+		get_unaligned_le16(&layout_data->keyboard_layout.layout_length);
+	if (*keyboard_layout_length < layout_length) {
+		*keyboard_layout_length = layout_length;
+		return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
+	}
+
+	memcpy(keyboard_layout, &layout_data->keyboard_layout, layout_length);
+
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI
+set_keyboard_layout(const struct efi_hii_database_protocol *this,
+		    efi_guid_t *key_guid)
+{
+	EFI_ENTRY("%p, %pUs", this, key_guid);
+
+	if (!key_guid)
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	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_INVALID_PARAMETER);
+}
+
+const struct efi_hii_database_protocol efi_hii_database = {
+	.new_package_list = new_package_list,
+	.remove_package_list = remove_package_list,
+	.update_package_list = update_package_list,
+	.list_package_lists = list_package_lists,
+	.export_package_lists = export_package_lists,
+	.register_package_notify = register_package_notify,
+	.unregister_package_notify = unregister_package_notify,
+	.find_keyboard_layouts = find_keyboard_layouts,
+	.get_keyboard_layout = get_keyboard_layout,
+	.set_keyboard_layout = set_keyboard_layout,
+	.get_package_list_handle = get_package_list_handle
+};
+
+/*
+ * EFI_HII_STRING_PROTOCOL
+ */
+
+static bool language_match(char *language, char *languages)
+{
+	size_t n;
+
+	n = strlen(language);
+	/* match primary language? */
+	if (!strncasecmp(language, languages, n) &&
+	    (languages[n] == ';' || languages[n] == '\0'))
+		return true;
+
+	return false;
+}
+
+static efi_status_t EFIAPI
+new_string(const struct efi_hii_string_protocol *this,
+	   efi_hii_handle_t package_list,
+	   efi_string_id_t *string_id,
+	   const u8 *language,
+	   const u16 *language_name,
+	   const efi_string_t string,
+	   const struct efi_font_info *string_font_info)
+{
+	struct efi_hii_packagelist *hii = package_list;
+	struct efi_string_table *stbl;
+
+	EFI_ENTRY("%p, %p, %p, \"%s\", %p, \"%ls\", %p", this, package_list,
+		  string_id, language, language_name, string,
+		  string_font_info);
+
+	if (!package_list || !efi_hii_packagelist_exists(package_list))
+		return EFI_EXIT(EFI_NOT_FOUND);
+
+	if (!string_id || !language || !string)
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	list_for_each_entry(stbl, &hii->string_tables, link) {
+		if (language_match((char *)language, stbl->language)) {
+			efi_string_id_t new_id;
+			void *buf;
+			efi_string_t str;
+
+			new_id = ++hii->max_string_id;
+			if (stbl->nstrings < new_id) {
+				buf = realloc(stbl->strings,
+					      sizeof(stbl->strings[0])
+						* new_id);
+				if (!buf)
+					return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+
+				memset(&stbl->strings[stbl->nstrings], 0,
+				       (new_id - stbl->nstrings)
+					 * sizeof(stbl->strings[0]));
+				stbl->strings = buf;
+				stbl->nstrings = new_id;
+			}
+
+			str = u16_strdup(string);
+			if (!str)
+				return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+
+			stbl->strings[new_id - 1].string = str;
+			*string_id = new_id;
+
+			return EFI_EXIT(EFI_SUCCESS);
+		}
+	}
+
+	return EFI_EXIT(EFI_NOT_FOUND);
+}
+
+static efi_status_t EFIAPI
+get_string(const struct efi_hii_string_protocol *this,
+	   const u8 *language,
+	   efi_hii_handle_t package_list,
+	   efi_string_id_t string_id,
+	   efi_string_t string,
+	   efi_uintn_t *string_size,
+	   struct efi_font_info **string_font_info)
+{
+	struct efi_hii_packagelist *hii = package_list;
+	struct efi_string_table *stbl;
+
+	EFI_ENTRY("%p, \"%s\", %p, %u, %p, %p, %p", this, language,
+		  package_list, string_id, string, string_size,
+		  string_font_info);
+
+	if (!package_list || !efi_hii_packagelist_exists(package_list))
+		return EFI_EXIT(EFI_NOT_FOUND);
+
+	list_for_each_entry(stbl, &hii->string_tables, link) {
+		if (language_match((char *)language, stbl->language)) {
+			efi_string_t str;
+			size_t len;
+
+			if (stbl->nstrings < string_id)
+				return EFI_EXIT(EFI_NOT_FOUND);
+
+			str = stbl->strings[string_id - 1].string;
+			if (str) {
+				len = u16_strsize(str);
+				if (*string_size < len) {
+					*string_size = len;
+
+					return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
+				}
+				memcpy(string, str, len);
+				*string_size = len;
+			} else {
+				return EFI_EXIT(EFI_NOT_FOUND);
+			}
+
+			return EFI_EXIT(EFI_SUCCESS);
+		}
+	}
+
+	return EFI_EXIT(EFI_NOT_FOUND);
+}
+
+static efi_status_t EFIAPI
+set_string(const struct efi_hii_string_protocol *this,
+	   efi_hii_handle_t package_list,
+	   efi_string_id_t string_id,
+	   const u8 *language,
+	   const efi_string_t string,
+	   const struct efi_font_info *string_font_info)
+{
+	struct efi_hii_packagelist *hii = package_list;
+	struct efi_string_table *stbl;
+
+	EFI_ENTRY("%p, %p, %u, \"%s\", \"%ls\", %p", this, package_list,
+		  string_id, language, string, string_font_info);
+
+	if (!package_list || !efi_hii_packagelist_exists(package_list))
+		return EFI_EXIT(EFI_NOT_FOUND);
+
+	if (string_id > hii->max_string_id)
+		return EFI_EXIT(EFI_NOT_FOUND);
+
+	if (!string || !language)
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	list_for_each_entry(stbl, &hii->string_tables, link) {
+		if (language_match((char *)language, stbl->language)) {
+			efi_string_t str;
+
+			if (hii->max_string_id < string_id)
+				return EFI_EXIT(EFI_NOT_FOUND);
+
+			if (stbl->nstrings < string_id) {
+				void *buf;
+
+				buf = realloc(stbl->strings,
+					      string_id
+						* sizeof(stbl->strings[0]));
+				if (!buf)
+					return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+
+				memset(&stbl->strings[string_id - 1], 0,
+				       (string_id - stbl->nstrings)
+					 * sizeof(stbl->strings[0]));
+				stbl->strings = buf;
+			}
+
+			str = u16_strdup(string);
+			if (!str)
+				return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+
+			free(stbl->strings[string_id - 1].string);
+			stbl->strings[string_id - 1].string = str;
+
+			return EFI_EXIT(EFI_SUCCESS);
+		}
+	}
+
+	return EFI_EXIT(EFI_NOT_FOUND);
+}
+
+static efi_status_t EFIAPI
+get_languages(const struct efi_hii_string_protocol *this,
+	      efi_hii_handle_t package_list,
+	      u8 *languages,
+	      efi_uintn_t *languages_size)
+{
+	struct efi_hii_packagelist *hii = package_list;
+	struct efi_string_table *stbl;
+	size_t len = 0;
+	char *p;
+
+	EFI_ENTRY("%p, %p, %p, %p", this, package_list, languages,
+		  languages_size);
+
+	if (!package_list || !efi_hii_packagelist_exists(package_list))
+		return EFI_EXIT(EFI_NOT_FOUND);
+
+	if (!languages_size ||
+	    (*languages_size && !languages))
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	/* figure out required size: */
+	list_for_each_entry(stbl, &hii->string_tables, link) {
+		len += strlen((char *)stbl->language) + 1;
+	}
+
+	if (*languages_size < len) {
+		*languages_size = len;
+
+		return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
+	}
+
+	p = (char *)languages;
+	list_for_each_entry(stbl, &hii->string_tables, link) {
+		if (p != (char *)languages)
+			*p++ = ';';
+		strcpy(p, stbl->language);
+		p += strlen((char *)stbl->language);
+	}
+	*p = '\0';
+
+	EFI_PRINT("languages: %s\n", languages);
+
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static efi_status_t EFIAPI
+get_secondary_languages(const struct efi_hii_string_protocol *this,
+			efi_hii_handle_t package_list,
+			const u8 *primary_language,
+			u8 *secondary_languages,
+			efi_uintn_t *secondary_languages_size)
+{
+	struct efi_hii_packagelist *hii = package_list;
+	struct efi_string_table *stbl;
+	bool found = false;
+
+	EFI_ENTRY("%p, %p, \"%s\", %p, %p", this, package_list,
+		  primary_language, secondary_languages,
+		  secondary_languages_size);
+
+	if (!package_list || !efi_hii_packagelist_exists(package_list))
+		return EFI_EXIT(EFI_NOT_FOUND);
+
+	if (!secondary_languages_size ||
+	    (*secondary_languages_size && !secondary_languages))
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	list_for_each_entry(stbl, &hii->string_tables, link) {
+		if (language_match((char *)primary_language, stbl->language)) {
+			found = true;
+			break;
+		}
+	}
+	if (!found)
+		return EFI_EXIT(EFI_INVALID_LANGUAGE);
+
+	/*
+	 * TODO: What is secondary language?
+	 * *secondary_languages = '\0';
+	 * *secondary_languages_size = 0;
+	 */
+
+	return EFI_EXIT(EFI_NOT_FOUND);
+}
+
+static 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
+};
+
+static int efi_hii_init(void)
+{
+	efi_add_root_node_protocol_deferred(&efi_guid_hii_string_protocol, &efi_hii_string);
+	efi_add_root_node_protocol_deferred(&efi_guid_hii_database_protocol, &efi_hii_database);
+	return 0;
+}
+device_initcall(efi_hii_init);
diff --git a/efi/loader/protocols/hii_config.c b/efi/loader/protocols/hii_config.c
new file mode 100644
index 000000000000..07dce2dae771
--- /dev/null
+++ b/efi/loader/protocols/hii_config.c
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier:     GPL-2.0+
+/*
+ * EFI Human Interface Infrastructure ... Configuration
+ *
+ * Copyright (c) 2017 Leif Lindholm
+ * Copyright (c) 2018 AKASHI Takahiro, Linaro Limited
+ */
+
+#include <linux/printk.h>
+#include <efi/loader.h>
+#include <efi/protocol/hii.h>
+#include <efi/loader/object.h>
+#include <efi/loader/trace.h>
+#include <efi/error.h>
+#include <efi/guid.h>
+#include <init.h>
+
+/*
+ * 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\", %pUs, \"%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
+ */
+
+static 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);
+};
+
+static 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);
+};
+
+static 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%zx, 0x%x, 0x%x, %p, %p", this, action,
+		  question_id, type, value, action_request);
+
+	return EFI_EXIT(EFI_DEVICE_ERROR);
+};
+
+static 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
+};
+
+static 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
+};
+
+static int efi_hii_init(void)
+{
+	efi_add_root_node_protocol_deferred(&efi_guid_hii_config_routing_protocol,
+					    &efi_hii_config_routing);
+	efi_add_root_node_protocol_deferred(&efi_guid_hii_config_access_protocol,
+					    &efi_hii_config_access);
+	return 0;
+}
+device_initcall(efi_hii_init);
diff --git a/include/efi/protocol/hii.h b/include/efi/protocol/hii.h
new file mode 100644
index 000000000000..d047467a0855
--- /dev/null
+++ b/include/efi/protocol/hii.h
@@ -0,0 +1,428 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Human Interface Infrastructure (HII)
+ */
+
+#ifndef __EFI_PROTOCOL_HII_H_
+#define __EFI_PROTOCOL_HII_H_
+
+#include <efi/types.h>
+
+typedef void *efi_hii_handle_t;
+typedef u16 *efi_string_t;
+typedef u16 efi_string_id_t;
+typedef u32 efi_hii_font_style_t;
+typedef u16 efi_question_id_t;
+typedef u16 efi_image_id_t;
+typedef u16 efi_form_id_t;
+
+struct efi_hii_package_list_header {
+	efi_guid_t package_list_guid;
+	u32 package_length;
+} __packed;
+
+/**
+ * struct efi_hii_package_header - EFI HII package header
+ *
+ * @fields:	'fields' replaces the bit-fields defined in the EFI
+ *		specification to to avoid possible compiler incompatibilities::
+ *
+ *		    u32 length:24;
+ *		    u32 type:8;
+ */
+struct efi_hii_package_header {
+	u32 fields;
+} __packed;
+
+#define __EFI_HII_PACKAGE_LEN_SHIFT	0
+#define __EFI_HII_PACKAGE_TYPE_SHIFT	24
+#define __EFI_HII_PACKAGE_LEN_MASK	0xffffff
+#define __EFI_HII_PACKAGE_TYPE_MASK	0xff
+
+#define EFI_HII_PACKAGE_TYPE_ALL          0x00
+#define EFI_HII_PACKAGE_TYPE_GUID         0x01
+#define EFI_HII_PACKAGE_FORMS             0x02
+#define EFI_HII_PACKAGE_STRINGS           0x04
+#define EFI_HII_PACKAGE_FONTS             0x05
+#define EFI_HII_PACKAGE_IMAGES            0x06
+#define EFI_HII_PACKAGE_SIMPLE_FONTS      0x07
+#define EFI_HII_PACKAGE_DEVICE_PATH       0x08
+#define EFI_HII_PACKAGE_KEYBOARD_LAYOUT   0x09
+#define EFI_HII_PACKAGE_ANIMATIONS        0x0A
+#define EFI_HII_PACKAGE_END               0xDF
+#define EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN 0xE0
+#define EFI_HII_PACKAGE_TYPE_SYSTEM_END   0xFF
+
+/*
+ * HII GUID package
+ */
+struct efi_hii_guid_package {
+	struct efi_hii_package_header header;
+	efi_guid_t guid;
+	char data[];
+} __packed;
+
+/*
+ * HII string package
+ */
+struct efi_hii_strings_package {
+	struct efi_hii_package_header header;
+	u32 header_size;
+	u32 string_info_offset;
+	u16 language_window[16];
+	efi_string_id_t language_name;
+	u8  language[];
+} __packed;
+
+struct efi_hii_string_block {
+	u8 block_type;
+	/* u8 block_body[]; */
+} __packed;
+
+#define EFI_HII_SIBT_END               0x00
+#define EFI_HII_SIBT_STRING_SCSU       0x10
+#define EFI_HII_SIBT_STRING_SCSU_FONT  0x11
+#define EFI_HII_SIBT_STRINGS_SCSU      0x12
+#define EFI_HII_SIBT_STRINGS_SCSU_FONT 0x13
+#define EFI_HII_SIBT_STRING_UCS2       0x14
+#define EFI_HII_SIBT_STRING_UCS2_FONT  0x15
+#define EFI_HII_SIBT_STRINGS_UCS2      0x16
+#define EFI_HII_SIBT_STRINGS_UCS2_FONT 0x17
+#define EFI_HII_SIBT_DUPLICATE         0x20
+#define EFI_HII_SIBT_SKIP2             0x21
+#define EFI_HII_SIBT_SKIP1             0x22
+#define EFI_HII_SIBT_EXT1              0x30
+#define EFI_HII_SIBT_EXT2              0x31
+#define EFI_HII_SIBT_EXT4              0x32
+#define EFI_HII_SIBT_FONT              0x40
+
+struct efi_hii_sibt_string_ucs2_block {
+	struct efi_hii_string_block header;
+	u16 string_text[];
+} __packed;
+
+/*
+ * HII forms package
+ * TODO: full scope of definitions
+ */
+struct efi_hii_time {
+	u8 hour;
+	u8 minute;
+	u8 second;
+};
+
+struct efi_hii_date {
+	u16 year;
+	u8 month;
+	u8 day;
+};
+
+struct efi_hii_ref {
+	efi_question_id_t question_id;
+	efi_form_id_t form_id;
+	efi_guid_t form_set_guid;
+	efi_string_id_t device_path;
+};
+
+union efi_ifr_type_value {
+	u8 u8;				// EFI_IFR_TYPE_NUM_SIZE_8
+	u16 u16;			// EFI_IFR_TYPE_NUM_SIZE_16
+	u32 u32;			// EFI_IFR_TYPE_NUM_SIZE_32
+	u64 u64;			// EFI_IFR_TYPE_NUM_SIZE_64
+	bool b;				// EFI_IFR_TYPE_BOOLEAN
+	struct efi_hii_time time;	// EFI_IFR_TYPE_TIME
+	struct efi_hii_date date;	// EFI_IFR_TYPE_DATE
+	efi_string_id_t string;		// EFI_IFR_TYPE_STRING, EFI_IFR_TYPE_ACTION
+	struct efi_hii_ref ref;		// EFI_IFR_TYPE_REF
+	// u8 buffer[];			// EFI_IFR_TYPE_BUFFER
+};
+
+#define EFI_IFR_TYPE_NUM_SIZE_8		0x00
+#define EFI_IFR_TYPE_NUM_SIZE_16	0x01
+#define EFI_IFR_TYPE_NUM_SIZE_32	0x02
+#define EFI_IFR_TYPE_NUM_SIZE_64	0x03
+#define EFI_IFR_TYPE_BOOLEAN		0x04
+#define EFI_IFR_TYPE_TIME		0x05
+#define EFI_IFR_TYPE_DATE		0x06
+#define EFI_IFR_TYPE_STRING		0x07
+#define EFI_IFR_TYPE_OTHER		0x08
+#define EFI_IFR_TYPE_UNDEFINED		0x09
+#define EFI_IFR_TYPE_ACTION		0x0A
+#define EFI_IFR_TYPE_BUFFER		0x0B
+#define EFI_IFR_TYPE_REF		0x0C
+#define EFI_IFR_OPTION_DEFAULT		0x10
+#define EFI_IFR_OPTION_DEFAULT_MFG	0x20
+
+#define EFI_IFR_ONE_OF_OPTION_OP	0x09
+
+struct efi_ifr_op_header {
+	u8 opCode;
+	u8 length:7;
+	u8 scope:1;
+};
+
+struct efi_ifr_one_of_option {
+	struct efi_ifr_op_header header;
+	efi_string_id_t option;
+	u8 flags;
+	u8 type;
+	union efi_ifr_type_value value;
+};
+
+typedef efi_uintn_t efi_browser_action_t;
+
+#define EFI_BROWSER_ACTION_REQUEST_NONE			0
+#define EFI_BROWSER_ACTION_REQUEST_RESET		1
+#define EFI_BROWSER_ACTION_REQUEST_SUBMIT		2
+#define EFI_BROWSER_ACTION_REQUEST_EXIT			3
+#define EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT	4
+#define EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT	5
+#define EFI_BROWSER_ACTION_REQUEST_FORM_APPLY		6
+#define EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD		7
+#define EFI_BROWSER_ACTION_REQUEST_RECONNECT		8
+
+typedef efi_uintn_t efi_browser_action_request_t;
+
+#define EFI_BROWSER_ACTION_CHANGING			0
+#define EFI_BROWSER_ACTION_CHANGED			1
+#define EFI_BROWSER_ACTION_RETRIEVE			2
+#define EFI_BROWSER_ACTION_FORM_OPEN			3
+#define EFI_BROWSER_ACTION_FORM_CLOSE			4
+#define EFI_BROWSER_ACTION_SUBMITTED			5
+#define EFI_BROWSER_ACTION_DEFAULT_STANDARD		0x1000
+#define EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING	0x1001
+#define EFI_BROWSER_ACTION_DEFAULT_SAFE			0x1002
+#define EFI_BROWSER_ACTION_DEFAULT_PLATFORM		0x2000
+#define EFI_BROWSER_ACTION_DEFAULT_HARDWARE		0x3000
+#define EFI_BROWSER_ACTION_DEFAULT_FIRMWARE		0x4000
+
+/*
+ * HII keyboard package
+ */
+typedef enum {
+	EFI_KEY_LCTRL, EFI_KEY_A0, EFI_KEY_LALT, EFI_KEY_SPACE_BAR,
+	EFI_KEY_A2, EFI_KEY_A3, EFI_KEY_A4, EFI_KEY_RCTRL, EFI_KEY_LEFT_ARROW,
+	EFI_KEY_DOWN_ARROW, EFI_KEY_RIGHT_ARROW, EFI_KEY_ZERO,
+	EFI_KEY_PERIOD, EFI_KEY_ENTER, EFI_KEY_LSHIFT, EFI_KEY_B0,
+	EFI_KEY_B1, EFI_KEY_B2, EFI_KEY_B3, EFI_KEY_B4, EFI_KEY_B5, EFI_KEY_B6,
+	EFI_KEY_B7, EFI_KEY_B8, EFI_KEY_B9, EFI_KEY_B10, EFI_KEY_RSHIFT,
+	EFI_KEY_UP_ARROW, EFI_KEY_ONE, EFI_KEY_TWO, EFI_KEY_THREE,
+	EFI_KEY_CAPS_LOCK, EFI_KEY_C1, EFI_KEY_C2, EFI_KEY_C3, EFI_KEY_C4,
+	EFI_KEY_C5, EFI_KEY_C6, EFI_KEY_C7, EFI_KEY_C8, EFI_KEY_C9,
+	EFI_KEY_C10, EFI_KEY_C11, EFI_KEY_C12, EFI_KEY_FOUR, EFI_KEY_FIVE,
+	EFI_KEY_SIX, EFI_KEY_PLUS, EFI_KEY_TAB, EFI_KEY_D1, EFI_KEY_D2,
+	EFI_KEY_D3, EFI_KEY_D4, EFI_KEY_D5, EFI_KEY_D6, EFI_KEY_D7, EFI_KEY_D8,
+	EFI_KEY_D9, EFI_KEY_D10, EFI_KEY_D11, EFI_KEY_D12, EFI_KEY_D13,
+	EFI_KEY_DEL, EFI_KEY_END, EFI_KEY_PG_DN, EFI_KEY_SEVEN, EFI_KEY_EIGHT,
+	EFI_KEY_NINE, EFI_KEY_E0, EFI_KEY_E1, EFI_KEY_E2, EFI_KEY_E3,
+	EFI_KEY_E4, EFI_KEY_E5, EFI_KEY_E6, EFI_KEY_E7, EFI_KEY_E8, EFI_KEY_E9,
+	EFI_KEY_E10, EFI_KEY_E11, EFI_KEY_E12, EFI_KEY_BACK_SPACE,
+	EFI_KEY_INS, EFI_KEY_HOME, EFI_KEY_PG_UP, EFI_KEY_NLCK, EFI_KEY_SLASH,
+	EFI_KEY_ASTERISK, EFI_KEY_MINUS, EFI_KEY_ESC, EFI_KEY_F1, EFI_KEY_F2,
+	EFI_KEY_F3, EFI_KEY_F4, EFI_KEY_F5, EFI_KEY_F6, EFI_KEY_F7, EFI_KEY_F8,
+	EFI_KEY_F9, EFI_KEY_F10, EFI_KEY_F11, EFI_KEY_F12, EFI_KEY_PRINT,
+	EFI_KEY_SLCK, EFI_KEY_PAUSE,
+} efi_key;
+
+struct efi_key_descriptor {
+	u32 key;
+	u16 unicode;
+	u16 shifted_unicode;
+	u16 alt_gr_unicode;
+	u16 shifted_alt_gr_unicode;
+	u16 modifier;
+	u16 affected_attribute;
+} __packed;
+
+struct efi_hii_keyboard_layout {
+	u16 layout_length;
+	/*
+	 * The EFI spec defines this as efi_guid_t.
+	 * clang and gcc both report alignment problems here.
+	 * clang with -Wunaligned-access
+	 * warning: field guid within 'struct efi_hii_keyboard_layout' is less
+	 * aligned than 'efi_guid_t' and is usually due to
+	 * 'struct efi_hii_keyboard_layout' being packed, which can lead to
+	 * unaligned accesses
+	 *
+	 * GCC with -Wpacked-not-aligned -Waddress-of-packed-member
+	 * 'efi_guid_t' offset 2 in 'struct efi_hii_keyboard_layout'
+	 * isn't aligned to 4
+	 *
+	 * Removing the alignment from efi_guid_t is not an option, since
+	 * it is also used in non-packed structs and that would break
+	 * calculations with offsetof
+	 *
+	 * This is the only place we get a report for. That happens because
+	 * all other declarations of efi_guid_t within a packed struct happens
+	 * to be 4-byte aligned.  i.e a u32, a u64 a 2 * u16 or any combination
+	 * that ends up landing efi_guid_t on a 4byte boundary precedes.
+	 *
+	 * Replace this with a 1-byte aligned counterpart of b[16].  This is a
+	 * packed struct so the memory  placement of efi_guid_t should not change
+	 *
+	 */
+	u8 guid[16];
+	u32 layout_descriptor_string_offset;
+	u8 descriptor_count;
+	/* struct efi_key_descriptor descriptors[]; follows here */
+} __packed;
+
+struct efi_hii_keyboard_package {
+	struct efi_hii_package_header header;
+	u16 layout_count;
+	struct efi_hii_keyboard_layout layout[];
+} __packed;
+
+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);
+};
+
+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);
+};
+
+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);
+};
+
+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);
+};
+
+#endif
-- 
2.47.3




  parent reply	other threads:[~2025-12-18 11:40 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-12-18 10:37 [PATCH v1 00/54] efi: implement EFI loader support in barebox Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 01/54] efi: payload: initrd: fix type mismatch on 32-bit Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 02/54] efi: loader: switch over event/memory key type to efi_uintn_t Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 03/54] lib: vsprintf: print human-readable EFI GUIDs with %pUs Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 04/54] fs: fat: don't duplicate dentries when resolving differently cased paths Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 05/54] efi: loader: add memory accounting Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 06/54] efi: loader: add pool allocator Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 07/54] efi: types: add EFI_RUNTIME_SECTION Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 08/54] resource: assign memory banks a default type and attr Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 09/54] ARM: lds: add EFI runtime service section Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 10/54] ARM: move needed assembly routines into EFI runtime section Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 11/54] crypto: crc32: implement position independent CRC32 Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 12/54] efi: loader: add support for tracing calls back into UEFI Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 13/54] efi: loader: add table utility functions Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 14/54] lib: add charset helpers Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 15/54] efi: loader: add object handling API Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 16/54] efi: loader: add devicepath support Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 17/54] efi: loader: add debug support Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 18/54] efi: loader: add boot services support Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 19/54] efi: loader: add support for runtime services before ExitBootServices Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 20/54] efi: loader: setup root node Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 21/54] efi: loader: add watchdog support Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 22/54] efi: loader: move PE implementation out of common code Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 23/54] efi: loader: protocol: add file protocol support Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 24/54] efi: loader: protocol: add Block IO support Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 25/54] efi: loader: protocol: implement efi_file_from_path Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 26/54] efi: loader: boot: implement LoadImage BootService Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 27/54] efi: loader: add EFI load option handling Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 28/54] efi: loader: protocol: add graphical output protocol support Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 29/54] efi: loader: protocol: add console support Ahmad Fatoum
2025-12-18 10:37 ` Ahmad Fatoum [this message]
2025-12-18 10:37 ` [PATCH v1 31/54] efi: loader: protocol: add unicode collation support Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 32/54] efi: loader: protocol: add random number generator protocol Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 33/54] efi: loader: protocol: add device_path_utilities Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 34/54] efi: loader: support formatting only first device path node to text Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 35/54] efi: loader: protocol: add efi_device_path_to_text support Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 36/54] restart: allow drivers to register runtime restart handler Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 37/54] poweroff: allow drivers to register runtime poweroff handler Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 38/54] ARM: psci: client: register runtime service " Ahmad Fatoum
2025-12-18 10:37 ` [PATCH v1 39/54] ARM: psci: client: register runtime service restart handler Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 40/54] hardening: disable some features when EFI runtime support is enabled Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 41/54] filetype: add new filetype for efi-stubbed ARM zImages Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 42/54] bootm: add global.bootm.efi toggle Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 43/54] efi: loader: add ESP boot entry provider Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 44/54] efi: loader: add rudimentary EFI boot manager Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 45/54] efi: loader: implement bootm handler Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 46/54] efi: runtime: add EFI variable support Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 47/54] efi: loader: populate OsIndicationsSupported/PlatformLang variables Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 48/54] ARM: don't disable MMU when EFI booting Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 49/54] efi: runtime: add runtime service support after ExitBootServices Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 50/54] efi: runtime: add relocation check Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 51/54] efi: loader: CONFIG_EFI_RT_VOLATILE_STORE Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 52/54] efi: loader: support ExitBootServices Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 53/54] efi: loader: pass along SMBIOS table Ahmad Fatoum
2025-12-18 10:38 ` [PATCH v1 54/54] ARM: configs: add multi_v7/8_efiloader_defconfig Ahmad Fatoum

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251218111242.1527495-31-a.fatoum@pengutronix.de \
    --to=a.fatoum@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox