xref: /openbmc/u-boot/lib/efi_loader/efi_hii.c (revision 66c433ed)
1c9bfb222SLeif Lindholm // SPDX-License-Identifier:     GPL-2.0+
2c9bfb222SLeif Lindholm /*
3c9bfb222SLeif Lindholm  *  EFI Human Interface Infrastructure ... database and packages
4c9bfb222SLeif Lindholm  *
5c9bfb222SLeif Lindholm  *  Copyright (c) 2017 Leif Lindholm
6c9bfb222SLeif Lindholm  *  Copyright (c) 2018 AKASHI Takahiro, Linaro Limited
7c9bfb222SLeif Lindholm  */
8c9bfb222SLeif Lindholm 
9c9bfb222SLeif Lindholm #include <common.h>
10c9bfb222SLeif Lindholm #include <efi_loader.h>
11c9bfb222SLeif Lindholm #include <malloc.h>
12c9bfb222SLeif Lindholm #include <asm/unaligned.h>
13c9bfb222SLeif Lindholm 
14c9bfb222SLeif Lindholm const efi_guid_t efi_guid_hii_database_protocol
15c9bfb222SLeif Lindholm 		= EFI_HII_DATABASE_PROTOCOL_GUID;
16c9bfb222SLeif Lindholm const efi_guid_t efi_guid_hii_string_protocol = EFI_HII_STRING_PROTOCOL_GUID;
17c9bfb222SLeif Lindholm 
18c9bfb222SLeif Lindholm static LIST_HEAD(efi_package_lists);
198d3b77e3SAKASHI Takahiro static LIST_HEAD(efi_keyboard_layout_list);
20c9bfb222SLeif Lindholm 
21c9bfb222SLeif Lindholm struct efi_hii_packagelist {
22c9bfb222SLeif Lindholm 	struct list_head link;
23c9bfb222SLeif Lindholm 	// TODO should there be an associated efi_object?
24c9bfb222SLeif Lindholm 	efi_handle_t driver_handle;
25c9bfb222SLeif Lindholm 	u32 max_string_id;
26c9bfb222SLeif Lindholm 	struct list_head string_tables;     /* list of efi_string_table */
279ab0bdd9SAKASHI Takahiro 	struct list_head guid_list;
288d3b77e3SAKASHI Takahiro 	struct list_head keyboard_packages;
29c9bfb222SLeif Lindholm 
30c9bfb222SLeif Lindholm 	/* we could also track fonts, images, etc */
31c9bfb222SLeif Lindholm };
32c9bfb222SLeif Lindholm 
efi_hii_packagelist_exists(efi_hii_handle_t package_list)33c9bfb222SLeif Lindholm static int efi_hii_packagelist_exists(efi_hii_handle_t package_list)
34c9bfb222SLeif Lindholm {
35c9bfb222SLeif Lindholm 	struct efi_hii_packagelist *hii;
36c9bfb222SLeif Lindholm 	int found = 0;
37c9bfb222SLeif Lindholm 
38c9bfb222SLeif Lindholm 	list_for_each_entry(hii, &efi_package_lists, link) {
39c9bfb222SLeif Lindholm 		if (hii == package_list) {
40c9bfb222SLeif Lindholm 			found = 1;
41c9bfb222SLeif Lindholm 			break;
42c9bfb222SLeif Lindholm 		}
43c9bfb222SLeif Lindholm 	}
44c9bfb222SLeif Lindholm 
45c9bfb222SLeif Lindholm 	return found;
46c9bfb222SLeif Lindholm }
47c9bfb222SLeif Lindholm 
efi_hii_package_type(struct efi_hii_package_header * header)48c9bfb222SLeif Lindholm static u32 efi_hii_package_type(struct efi_hii_package_header *header)
49c9bfb222SLeif Lindholm {
50c9bfb222SLeif Lindholm 	u32 fields;
51c9bfb222SLeif Lindholm 
52c9bfb222SLeif Lindholm 	fields = get_unaligned_le32(&header->fields);
53c9bfb222SLeif Lindholm 
54c9bfb222SLeif Lindholm 	return (fields >> __EFI_HII_PACKAGE_TYPE_SHIFT)
55c9bfb222SLeif Lindholm 		& __EFI_HII_PACKAGE_TYPE_MASK;
56c9bfb222SLeif Lindholm }
57c9bfb222SLeif Lindholm 
efi_hii_package_len(struct efi_hii_package_header * header)58c9bfb222SLeif Lindholm static u32 efi_hii_package_len(struct efi_hii_package_header *header)
59c9bfb222SLeif Lindholm {
60c9bfb222SLeif Lindholm 	u32 fields;
61c9bfb222SLeif Lindholm 
62c9bfb222SLeif Lindholm 	fields = get_unaligned_le32(&header->fields);
63c9bfb222SLeif Lindholm 
64c9bfb222SLeif Lindholm 	return (fields >> __EFI_HII_PACKAGE_LEN_SHIFT)
65c9bfb222SLeif Lindholm 		& __EFI_HII_PACKAGE_LEN_MASK;
66c9bfb222SLeif Lindholm }
67c9bfb222SLeif Lindholm 
68c9bfb222SLeif Lindholm struct efi_string_info {
69c9bfb222SLeif Lindholm 	efi_string_t string;
70c9bfb222SLeif Lindholm 	/* we could also track font info, etc */
71c9bfb222SLeif Lindholm };
72c9bfb222SLeif Lindholm 
73c9bfb222SLeif Lindholm struct efi_string_table {
74c9bfb222SLeif Lindholm 	struct list_head link;
75c9bfb222SLeif Lindholm 	efi_string_id_t language_name;
76c9bfb222SLeif Lindholm 	char *language;
77c9bfb222SLeif Lindholm 	u32 nstrings;
78c9bfb222SLeif Lindholm 	/*
79c9bfb222SLeif Lindholm 	 * NOTE:
80c9bfb222SLeif Lindholm 	 *  string id starts at 1 so value is stbl->strings[id-1],
81c9bfb222SLeif Lindholm 	 *  and strings[] is a array of stbl->nstrings elements
82c9bfb222SLeif Lindholm 	 */
83c9bfb222SLeif Lindholm 	struct efi_string_info *strings;
84c9bfb222SLeif Lindholm };
85c9bfb222SLeif Lindholm 
869ab0bdd9SAKASHI Takahiro struct efi_guid_data {
879ab0bdd9SAKASHI Takahiro 	struct list_head link;
889ab0bdd9SAKASHI Takahiro 	struct efi_hii_guid_package package;
899ab0bdd9SAKASHI Takahiro };
909ab0bdd9SAKASHI Takahiro 
918d3b77e3SAKASHI Takahiro struct efi_keyboard_layout_data {
928d3b77e3SAKASHI Takahiro 	struct list_head link;		/* in package */
938d3b77e3SAKASHI Takahiro 	struct list_head link_sys;	/* in global list */
948d3b77e3SAKASHI Takahiro 	struct efi_hii_keyboard_layout keyboard_layout;
958d3b77e3SAKASHI Takahiro };
968d3b77e3SAKASHI Takahiro 
978d3b77e3SAKASHI Takahiro struct efi_keyboard_package_data {
988d3b77e3SAKASHI Takahiro 	struct list_head link;		/* in package_list */
998d3b77e3SAKASHI Takahiro 	struct list_head keyboard_layout_list;
1008d3b77e3SAKASHI Takahiro };
1018d3b77e3SAKASHI Takahiro 
free_strings_table(struct efi_string_table * stbl)102c9bfb222SLeif Lindholm static void free_strings_table(struct efi_string_table *stbl)
103c9bfb222SLeif Lindholm {
104c9bfb222SLeif Lindholm 	int i;
105c9bfb222SLeif Lindholm 
106c9bfb222SLeif Lindholm 	for (i = 0; i < stbl->nstrings; i++)
107c9bfb222SLeif Lindholm 		free(stbl->strings[i].string);
108c9bfb222SLeif Lindholm 	free(stbl->strings);
109c9bfb222SLeif Lindholm 	free(stbl->language);
110c9bfb222SLeif Lindholm 	free(stbl);
111c9bfb222SLeif Lindholm }
112c9bfb222SLeif Lindholm 
remove_strings_package(struct efi_hii_packagelist * hii)113c9bfb222SLeif Lindholm static void remove_strings_package(struct efi_hii_packagelist *hii)
114c9bfb222SLeif Lindholm {
115c9bfb222SLeif Lindholm 	while (!list_empty(&hii->string_tables)) {
116c9bfb222SLeif Lindholm 		struct efi_string_table *stbl;
117c9bfb222SLeif Lindholm 
118c9bfb222SLeif Lindholm 		stbl = list_first_entry(&hii->string_tables,
119c9bfb222SLeif Lindholm 					struct efi_string_table, link);
120c9bfb222SLeif Lindholm 		list_del(&stbl->link);
121c9bfb222SLeif Lindholm 		free_strings_table(stbl);
122c9bfb222SLeif Lindholm 	}
123c9bfb222SLeif Lindholm }
124c9bfb222SLeif Lindholm 
125c9bfb222SLeif Lindholm static efi_status_t
add_strings_package(struct efi_hii_packagelist * hii,struct efi_hii_strings_package * strings_package)126c9bfb222SLeif Lindholm add_strings_package(struct efi_hii_packagelist *hii,
127c9bfb222SLeif Lindholm 		    struct efi_hii_strings_package *strings_package)
128c9bfb222SLeif Lindholm {
129c9bfb222SLeif Lindholm 	struct efi_hii_string_block *block;
130c9bfb222SLeif Lindholm 	void *end;
131c9bfb222SLeif Lindholm 	u32 nstrings = 0, idx = 0;
132c9bfb222SLeif Lindholm 	struct efi_string_table *stbl = NULL;
133c9bfb222SLeif Lindholm 	efi_status_t ret;
134c9bfb222SLeif Lindholm 
1356f8f4217SHeinrich Schuchardt 	EFI_PRINT("header_size: %08x\n",
136c9bfb222SLeif Lindholm 		  get_unaligned_le32(&strings_package->header_size));
1376f8f4217SHeinrich Schuchardt 	EFI_PRINT("string_info_offset: %08x\n",
138c9bfb222SLeif Lindholm 		  get_unaligned_le32(&strings_package->string_info_offset));
1396f8f4217SHeinrich Schuchardt 	EFI_PRINT("language_name: %u\n",
140c9bfb222SLeif Lindholm 		  get_unaligned_le16(&strings_package->language_name));
1416f8f4217SHeinrich Schuchardt 	EFI_PRINT("language: %s\n", strings_package->language);
142c9bfb222SLeif Lindholm 
143c9bfb222SLeif Lindholm 	/* count # of string entries: */
144c9bfb222SLeif Lindholm 	end = ((void *)strings_package)
145c9bfb222SLeif Lindholm 			+ efi_hii_package_len(&strings_package->header);
146c9bfb222SLeif Lindholm 	block = ((void *)strings_package)
147c9bfb222SLeif Lindholm 		+ get_unaligned_le32(&strings_package->string_info_offset);
148c9bfb222SLeif Lindholm 
149c9bfb222SLeif Lindholm 	while ((void *)block < end) {
150c9bfb222SLeif Lindholm 		switch (block->block_type) {
151c9bfb222SLeif Lindholm 		case EFI_HII_SIBT_STRING_UCS2: {
152c9bfb222SLeif Lindholm 			struct efi_hii_sibt_string_ucs2_block *ucs2;
153c9bfb222SLeif Lindholm 
154c9bfb222SLeif Lindholm 			ucs2 = (void *)block;
155c9bfb222SLeif Lindholm 			nstrings++;
156c9bfb222SLeif Lindholm 			block = efi_hii_sibt_string_ucs2_block_next(ucs2);
157c9bfb222SLeif Lindholm 			break;
158c9bfb222SLeif Lindholm 		}
159c9bfb222SLeif Lindholm 		case EFI_HII_SIBT_END:
160c9bfb222SLeif Lindholm 			block = end;
161c9bfb222SLeif Lindholm 			break;
162c9bfb222SLeif Lindholm 		default:
1636f8f4217SHeinrich Schuchardt 			EFI_PRINT("unknown HII string block type: %02x\n",
164c9bfb222SLeif Lindholm 				  block->block_type);
165c9bfb222SLeif Lindholm 			return EFI_INVALID_PARAMETER;
166c9bfb222SLeif Lindholm 		}
167c9bfb222SLeif Lindholm 	}
168c9bfb222SLeif Lindholm 
169c9bfb222SLeif Lindholm 	stbl = calloc(sizeof(*stbl), 1);
170c9bfb222SLeif Lindholm 	if (!stbl) {
171c9bfb222SLeif Lindholm 		ret = EFI_OUT_OF_RESOURCES;
172c9bfb222SLeif Lindholm 		goto error;
173c9bfb222SLeif Lindholm 	}
174c9bfb222SLeif Lindholm 	stbl->strings = calloc(sizeof(stbl->strings[0]), nstrings);
175c9bfb222SLeif Lindholm 	if (!stbl->strings) {
176c9bfb222SLeif Lindholm 		ret = EFI_OUT_OF_RESOURCES;
177c9bfb222SLeif Lindholm 		goto error;
178c9bfb222SLeif Lindholm 	}
179c9bfb222SLeif Lindholm 	stbl->language_name =
180c9bfb222SLeif Lindholm 			get_unaligned_le16(&strings_package->language_name);
181c9bfb222SLeif Lindholm 	stbl->language = strdup((char *)strings_package->language);
182c9bfb222SLeif Lindholm 	if (!stbl->language) {
183c9bfb222SLeif Lindholm 		ret = EFI_OUT_OF_RESOURCES;
184c9bfb222SLeif Lindholm 		goto error;
185c9bfb222SLeif Lindholm 	}
186c9bfb222SLeif Lindholm 	stbl->nstrings = nstrings;
187c9bfb222SLeif Lindholm 
188c9bfb222SLeif Lindholm 	/* and now parse string entries and populate efi_string_table */
189c9bfb222SLeif Lindholm 	block = ((void *)strings_package)
190c9bfb222SLeif Lindholm 		+ get_unaligned_le32(&strings_package->string_info_offset);
191c9bfb222SLeif Lindholm 
192c9bfb222SLeif Lindholm 	while ((void *)block < end) {
193c9bfb222SLeif Lindholm 		switch (block->block_type) {
194c9bfb222SLeif Lindholm 		case EFI_HII_SIBT_STRING_UCS2: {
195c9bfb222SLeif Lindholm 			struct efi_hii_sibt_string_ucs2_block *ucs2;
196c9bfb222SLeif Lindholm 
197c9bfb222SLeif Lindholm 			ucs2 = (void *)block;
1986f8f4217SHeinrich Schuchardt 			EFI_PRINT("%4u: \"%ls\"\n", idx + 1, ucs2->string_text);
199c9bfb222SLeif Lindholm 			stbl->strings[idx].string =
200c9bfb222SLeif Lindholm 				u16_strdup(ucs2->string_text);
201c9bfb222SLeif Lindholm 			if (!stbl->strings[idx].string) {
202c9bfb222SLeif Lindholm 				ret = EFI_OUT_OF_RESOURCES;
203c9bfb222SLeif Lindholm 				goto error;
204c9bfb222SLeif Lindholm 			}
205c9bfb222SLeif Lindholm 			idx++;
206c9bfb222SLeif Lindholm 			/* FIXME: accessing u16 * here */
207c9bfb222SLeif Lindholm 			block = efi_hii_sibt_string_ucs2_block_next(ucs2);
208c9bfb222SLeif Lindholm 			break;
209c9bfb222SLeif Lindholm 		}
210c9bfb222SLeif Lindholm 		case EFI_HII_SIBT_END:
211c9bfb222SLeif Lindholm 			goto out;
212c9bfb222SLeif Lindholm 		default:
2136f8f4217SHeinrich Schuchardt 			EFI_PRINT("unknown HII string block type: %02x\n",
214c9bfb222SLeif Lindholm 				  block->block_type);
215c9bfb222SLeif Lindholm 			ret = EFI_INVALID_PARAMETER;
216c9bfb222SLeif Lindholm 			goto error;
217c9bfb222SLeif Lindholm 		}
218c9bfb222SLeif Lindholm 	}
219c9bfb222SLeif Lindholm 
220c9bfb222SLeif Lindholm out:
221c9bfb222SLeif Lindholm 	list_add(&stbl->link, &hii->string_tables);
222c9bfb222SLeif Lindholm 	if (hii->max_string_id < nstrings)
223c9bfb222SLeif Lindholm 		hii->max_string_id = nstrings;
224c9bfb222SLeif Lindholm 
225c9bfb222SLeif Lindholm 	return EFI_SUCCESS;
226c9bfb222SLeif Lindholm 
227c9bfb222SLeif Lindholm error:
228c9bfb222SLeif Lindholm 	if (stbl) {
229c9bfb222SLeif Lindholm 		free(stbl->language);
230*bd3b7478SHeinrich Schuchardt 		while (idx > 0)
231*bd3b7478SHeinrich Schuchardt 			free(stbl->strings[--idx].string);
232c9bfb222SLeif Lindholm 		free(stbl->strings);
233c9bfb222SLeif Lindholm 	}
234c9bfb222SLeif Lindholm 	free(stbl);
235c9bfb222SLeif Lindholm 
236c9bfb222SLeif Lindholm 	return ret;
237c9bfb222SLeif Lindholm }
238c9bfb222SLeif Lindholm 
remove_guid_package(struct efi_hii_packagelist * hii)2399ab0bdd9SAKASHI Takahiro static void remove_guid_package(struct efi_hii_packagelist *hii)
2409ab0bdd9SAKASHI Takahiro {
2419ab0bdd9SAKASHI Takahiro 	struct efi_guid_data *data;
2429ab0bdd9SAKASHI Takahiro 
2439ab0bdd9SAKASHI Takahiro 	while (!list_empty(&hii->guid_list)) {
2449ab0bdd9SAKASHI Takahiro 		data = list_first_entry(&hii->guid_list,
2459ab0bdd9SAKASHI Takahiro 					struct efi_guid_data, link);
2469ab0bdd9SAKASHI Takahiro 		list_del(&data->link);
2479ab0bdd9SAKASHI Takahiro 		free(data);
2489ab0bdd9SAKASHI Takahiro 	}
2499ab0bdd9SAKASHI Takahiro }
2509ab0bdd9SAKASHI Takahiro 
2519ab0bdd9SAKASHI Takahiro static efi_status_t
add_guid_package(struct efi_hii_packagelist * hii,struct efi_hii_guid_package * package)2529ab0bdd9SAKASHI Takahiro add_guid_package(struct efi_hii_packagelist *hii,
2539ab0bdd9SAKASHI Takahiro 		 struct efi_hii_guid_package *package)
2549ab0bdd9SAKASHI Takahiro {
2559ab0bdd9SAKASHI Takahiro 	struct efi_guid_data *data;
2569ab0bdd9SAKASHI Takahiro 
2579ab0bdd9SAKASHI Takahiro 	data = calloc(sizeof(*data), 1);
2589ab0bdd9SAKASHI Takahiro 	if (!data)
2599ab0bdd9SAKASHI Takahiro 		return EFI_OUT_OF_RESOURCES;
2609ab0bdd9SAKASHI Takahiro 
2619ab0bdd9SAKASHI Takahiro 	/* TODO: we don't know any about data field */
2629ab0bdd9SAKASHI Takahiro 	memcpy(&data->package, package, sizeof(*package));
2639ab0bdd9SAKASHI Takahiro 	list_add_tail(&data->link, &hii->guid_list);
2649ab0bdd9SAKASHI Takahiro 
2659ab0bdd9SAKASHI Takahiro 	return EFI_SUCCESS;
2669ab0bdd9SAKASHI Takahiro }
2679ab0bdd9SAKASHI Takahiro 
free_keyboard_layouts(struct efi_keyboard_package_data * package)2688d3b77e3SAKASHI Takahiro static void free_keyboard_layouts(struct efi_keyboard_package_data *package)
2698d3b77e3SAKASHI Takahiro {
2708d3b77e3SAKASHI Takahiro 	struct efi_keyboard_layout_data *layout_data;
2718d3b77e3SAKASHI Takahiro 
2728d3b77e3SAKASHI Takahiro 	while (!list_empty(&package->keyboard_layout_list)) {
2738d3b77e3SAKASHI Takahiro 		layout_data = list_first_entry(&package->keyboard_layout_list,
2748d3b77e3SAKASHI Takahiro 					       struct efi_keyboard_layout_data,
2758d3b77e3SAKASHI Takahiro 					       link);
2768d3b77e3SAKASHI Takahiro 		list_del(&layout_data->link);
2778d3b77e3SAKASHI Takahiro 		list_del(&layout_data->link_sys);
2788d3b77e3SAKASHI Takahiro 		free(layout_data);
2798d3b77e3SAKASHI Takahiro 	}
2808d3b77e3SAKASHI Takahiro }
2818d3b77e3SAKASHI Takahiro 
remove_keyboard_package(struct efi_hii_packagelist * hii)2828d3b77e3SAKASHI Takahiro static void remove_keyboard_package(struct efi_hii_packagelist *hii)
2838d3b77e3SAKASHI Takahiro {
2848d3b77e3SAKASHI Takahiro 	struct efi_keyboard_package_data *package;
2858d3b77e3SAKASHI Takahiro 
2868d3b77e3SAKASHI Takahiro 	while (!list_empty(&hii->keyboard_packages)) {
2878d3b77e3SAKASHI Takahiro 		package = list_first_entry(&hii->keyboard_packages,
2888d3b77e3SAKASHI Takahiro 					   struct efi_keyboard_package_data,
2898d3b77e3SAKASHI Takahiro 					   link);
2908d3b77e3SAKASHI Takahiro 		free_keyboard_layouts(package);
2918d3b77e3SAKASHI Takahiro 		list_del(&package->link);
2928d3b77e3SAKASHI Takahiro 		free(package);
2938d3b77e3SAKASHI Takahiro 	}
2948d3b77e3SAKASHI Takahiro }
2958d3b77e3SAKASHI Takahiro 
2968d3b77e3SAKASHI Takahiro static efi_status_t
add_keyboard_package(struct efi_hii_packagelist * hii,struct efi_hii_keyboard_package * keyboard_package)2978d3b77e3SAKASHI Takahiro add_keyboard_package(struct efi_hii_packagelist *hii,
2988d3b77e3SAKASHI Takahiro 		     struct efi_hii_keyboard_package *keyboard_package)
2998d3b77e3SAKASHI Takahiro {
3008d3b77e3SAKASHI Takahiro 	struct efi_keyboard_package_data *package_data;
3018d3b77e3SAKASHI Takahiro 	struct efi_hii_keyboard_layout *layout;
3028d3b77e3SAKASHI Takahiro 	struct efi_keyboard_layout_data *layout_data;
3038d3b77e3SAKASHI Takahiro 	u16 layout_count, layout_length;
3048d3b77e3SAKASHI Takahiro 	int i;
3058d3b77e3SAKASHI Takahiro 
3068d3b77e3SAKASHI Takahiro 	package_data = malloc(sizeof(*package_data));
3078d3b77e3SAKASHI Takahiro 	if (!package_data)
3088d3b77e3SAKASHI Takahiro 		return EFI_OUT_OF_RESOURCES;
3098d3b77e3SAKASHI Takahiro 	INIT_LIST_HEAD(&package_data->link);
3108d3b77e3SAKASHI Takahiro 	INIT_LIST_HEAD(&package_data->keyboard_layout_list);
3118d3b77e3SAKASHI Takahiro 
3128d3b77e3SAKASHI Takahiro 	layout = &keyboard_package->layout[0];
3138d3b77e3SAKASHI Takahiro 	layout_count = get_unaligned_le16(&keyboard_package->layout_count);
3148d3b77e3SAKASHI Takahiro 	for (i = 0; i < layout_count; i++) {
3158d3b77e3SAKASHI Takahiro 		layout_length = get_unaligned_le16(&layout->layout_length);
3168d3b77e3SAKASHI Takahiro 		layout_data = malloc(sizeof(*layout_data) + layout_length);
3178d3b77e3SAKASHI Takahiro 		if (!layout_data)
3188d3b77e3SAKASHI Takahiro 			goto out;
3198d3b77e3SAKASHI Takahiro 
3208d3b77e3SAKASHI Takahiro 		memcpy(&layout_data->keyboard_layout, layout, layout_length);
3218d3b77e3SAKASHI Takahiro 		list_add_tail(&layout_data->link,
3228d3b77e3SAKASHI Takahiro 			      &package_data->keyboard_layout_list);
3238d3b77e3SAKASHI Takahiro 		list_add_tail(&layout_data->link_sys,
3248d3b77e3SAKASHI Takahiro 			      &efi_keyboard_layout_list);
3258d3b77e3SAKASHI Takahiro 
3268d3b77e3SAKASHI Takahiro 		layout += layout_length;
3278d3b77e3SAKASHI Takahiro 	}
3288d3b77e3SAKASHI Takahiro 
3298d3b77e3SAKASHI Takahiro 	list_add_tail(&package_data->link, &hii->keyboard_packages);
3308d3b77e3SAKASHI Takahiro 
3318d3b77e3SAKASHI Takahiro 	return EFI_SUCCESS;
3328d3b77e3SAKASHI Takahiro 
3338d3b77e3SAKASHI Takahiro out:
3348d3b77e3SAKASHI Takahiro 	free_keyboard_layouts(package_data);
3358d3b77e3SAKASHI Takahiro 	free(package_data);
3368d3b77e3SAKASHI Takahiro 
3378d3b77e3SAKASHI Takahiro 	return EFI_OUT_OF_RESOURCES;
3388d3b77e3SAKASHI Takahiro }
3398d3b77e3SAKASHI Takahiro 
new_packagelist(void)340c9bfb222SLeif Lindholm static struct efi_hii_packagelist *new_packagelist(void)
341c9bfb222SLeif Lindholm {
342c9bfb222SLeif Lindholm 	struct efi_hii_packagelist *hii;
343c9bfb222SLeif Lindholm 
344c9bfb222SLeif Lindholm 	hii = malloc(sizeof(*hii));
345fdef2983SHeinrich Schuchardt 	list_add_tail(&hii->link, &efi_package_lists);
346c9bfb222SLeif Lindholm 	hii->max_string_id = 0;
347c9bfb222SLeif Lindholm 	INIT_LIST_HEAD(&hii->string_tables);
3489ab0bdd9SAKASHI Takahiro 	INIT_LIST_HEAD(&hii->guid_list);
3498d3b77e3SAKASHI Takahiro 	INIT_LIST_HEAD(&hii->keyboard_packages);
350c9bfb222SLeif Lindholm 
351c9bfb222SLeif Lindholm 	return hii;
352c9bfb222SLeif Lindholm }
353c9bfb222SLeif Lindholm 
free_packagelist(struct efi_hii_packagelist * hii)354c9bfb222SLeif Lindholm static void free_packagelist(struct efi_hii_packagelist *hii)
355c9bfb222SLeif Lindholm {
356c9bfb222SLeif Lindholm 	remove_strings_package(hii);
3579ab0bdd9SAKASHI Takahiro 	remove_guid_package(hii);
3588d3b77e3SAKASHI Takahiro 	remove_keyboard_package(hii);
359c9bfb222SLeif Lindholm 
360c9bfb222SLeif Lindholm 	list_del(&hii->link);
361c9bfb222SLeif Lindholm 	free(hii);
362c9bfb222SLeif Lindholm }
363c9bfb222SLeif Lindholm 
364c9bfb222SLeif Lindholm static efi_status_t
add_packages(struct efi_hii_packagelist * hii,const struct efi_hii_package_list_header * package_list)365c9bfb222SLeif Lindholm add_packages(struct efi_hii_packagelist *hii,
366c9bfb222SLeif Lindholm 	     const struct efi_hii_package_list_header *package_list)
367c9bfb222SLeif Lindholm {
368c9bfb222SLeif Lindholm 	struct efi_hii_package_header *package;
369c9bfb222SLeif Lindholm 	void *end;
370c9bfb222SLeif Lindholm 	efi_status_t ret = EFI_SUCCESS;
371c9bfb222SLeif Lindholm 
372c9bfb222SLeif Lindholm 	end = ((void *)package_list)
373c9bfb222SLeif Lindholm 		+ get_unaligned_le32(&package_list->package_length);
374c9bfb222SLeif Lindholm 
3756f8f4217SHeinrich Schuchardt 	EFI_PRINT("package_list: %pUl (%u)\n", &package_list->package_list_guid,
376c9bfb222SLeif Lindholm 		  get_unaligned_le32(&package_list->package_length));
377c9bfb222SLeif Lindholm 
378c9bfb222SLeif Lindholm 	package = ((void *)package_list) + sizeof(*package_list);
379c9bfb222SLeif Lindholm 	while ((void *)package < end) {
3806f8f4217SHeinrich Schuchardt 		EFI_PRINT("package=%p, package type=%x, length=%u\n", package,
381c9bfb222SLeif Lindholm 			  efi_hii_package_type(package),
382c9bfb222SLeif Lindholm 			  efi_hii_package_len(package));
383c9bfb222SLeif Lindholm 
384c9bfb222SLeif Lindholm 		switch (efi_hii_package_type(package)) {
385c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_TYPE_GUID:
3869ab0bdd9SAKASHI Takahiro 			ret = add_guid_package(hii,
3879ab0bdd9SAKASHI Takahiro 				(struct efi_hii_guid_package *)package);
388c9bfb222SLeif Lindholm 			break;
389c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_FORMS:
3901a9fce50SHeinrich Schuchardt 			EFI_PRINT("Form package not supported\n");
391c9bfb222SLeif Lindholm 			ret = EFI_INVALID_PARAMETER;
392c9bfb222SLeif Lindholm 			break;
393c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_STRINGS:
394c9bfb222SLeif Lindholm 			ret = add_strings_package(hii,
395c9bfb222SLeif Lindholm 				(struct efi_hii_strings_package *)package);
396c9bfb222SLeif Lindholm 			break;
397c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_FONTS:
3981a9fce50SHeinrich Schuchardt 			EFI_PRINT("Font package not supported\n");
399c9bfb222SLeif Lindholm 			ret = EFI_INVALID_PARAMETER;
400c9bfb222SLeif Lindholm 			break;
401c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_IMAGES:
4021a9fce50SHeinrich Schuchardt 			EFI_PRINT("Image package not supported\n");
403c9bfb222SLeif Lindholm 			ret = EFI_INVALID_PARAMETER;
404c9bfb222SLeif Lindholm 			break;
405c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_SIMPLE_FONTS:
4061a9fce50SHeinrich Schuchardt 			EFI_PRINT("Simple font package not supported\n");
407c9bfb222SLeif Lindholm 			ret = EFI_INVALID_PARAMETER;
408c9bfb222SLeif Lindholm 			break;
409c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_DEVICE_PATH:
4101a9fce50SHeinrich Schuchardt 			EFI_PRINT("Device path package not supported\n");
411c9bfb222SLeif Lindholm 			ret = EFI_INVALID_PARAMETER;
412c9bfb222SLeif Lindholm 			break;
413c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
4148d3b77e3SAKASHI Takahiro 			ret = add_keyboard_package(hii,
4158d3b77e3SAKASHI Takahiro 				(struct efi_hii_keyboard_package *)package);
416c9bfb222SLeif Lindholm 			break;
417c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_ANIMATIONS:
4181a9fce50SHeinrich Schuchardt 			EFI_PRINT("Animation package not supported\n");
419c9bfb222SLeif Lindholm 			ret = EFI_INVALID_PARAMETER;
420c9bfb222SLeif Lindholm 			break;
421c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_END:
422c9bfb222SLeif Lindholm 			goto out;
423c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN:
424c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_TYPE_SYSTEM_END:
425c9bfb222SLeif Lindholm 		default:
426c9bfb222SLeif Lindholm 			break;
427c9bfb222SLeif Lindholm 		}
428c9bfb222SLeif Lindholm 
429c9bfb222SLeif Lindholm 		if (ret != EFI_SUCCESS)
430c9bfb222SLeif Lindholm 			return ret;
431c9bfb222SLeif Lindholm 
432c9bfb222SLeif Lindholm 		package = (void *)package + efi_hii_package_len(package);
433c9bfb222SLeif Lindholm 	}
434c9bfb222SLeif Lindholm out:
435c9bfb222SLeif Lindholm 	// TODO in theory there is some notifications that should be sent..
436c9bfb222SLeif Lindholm 	return EFI_SUCCESS;
437c9bfb222SLeif Lindholm }
438c9bfb222SLeif Lindholm 
439c9bfb222SLeif Lindholm /*
440c9bfb222SLeif Lindholm  * EFI_HII_DATABASE_PROTOCOL
441c9bfb222SLeif Lindholm  */
442c9bfb222SLeif Lindholm 
443c9bfb222SLeif Lindholm 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)444c9bfb222SLeif Lindholm new_package_list(const struct efi_hii_database_protocol *this,
445c9bfb222SLeif Lindholm 		 const struct efi_hii_package_list_header *package_list,
446c9bfb222SLeif Lindholm 		 const efi_handle_t driver_handle,
447c9bfb222SLeif Lindholm 		 efi_hii_handle_t *handle)
448c9bfb222SLeif Lindholm {
449c9bfb222SLeif Lindholm 	struct efi_hii_packagelist *hii;
450c9bfb222SLeif Lindholm 	efi_status_t ret;
451c9bfb222SLeif Lindholm 
452c9bfb222SLeif Lindholm 	EFI_ENTRY("%p, %p, %p, %p", this, package_list, driver_handle, handle);
453c9bfb222SLeif Lindholm 
454c9bfb222SLeif Lindholm 	if (!package_list || !handle)
455c9bfb222SLeif Lindholm 		return EFI_EXIT(EFI_INVALID_PARAMETER);
456c9bfb222SLeif Lindholm 
457c9bfb222SLeif Lindholm 	hii = new_packagelist();
458c9bfb222SLeif Lindholm 	if (!hii)
459c9bfb222SLeif Lindholm 		return EFI_EXIT(EFI_OUT_OF_RESOURCES);
460c9bfb222SLeif Lindholm 
461c9bfb222SLeif Lindholm 	ret = add_packages(hii, package_list);
462c9bfb222SLeif Lindholm 	if (ret != EFI_SUCCESS) {
463c9bfb222SLeif Lindholm 		free_packagelist(hii);
464c9bfb222SLeif Lindholm 		return EFI_EXIT(ret);
465c9bfb222SLeif Lindholm 	}
466c9bfb222SLeif Lindholm 
467c9bfb222SLeif Lindholm 	hii->driver_handle = driver_handle;
468c9bfb222SLeif Lindholm 	*handle = hii;
469c9bfb222SLeif Lindholm 
470c9bfb222SLeif Lindholm 	return EFI_EXIT(EFI_SUCCESS);
471c9bfb222SLeif Lindholm }
472c9bfb222SLeif Lindholm 
473c9bfb222SLeif Lindholm static efi_status_t EFIAPI
remove_package_list(const struct efi_hii_database_protocol * this,efi_hii_handle_t handle)474c9bfb222SLeif Lindholm remove_package_list(const struct efi_hii_database_protocol *this,
475c9bfb222SLeif Lindholm 		    efi_hii_handle_t handle)
476c9bfb222SLeif Lindholm {
477c9bfb222SLeif Lindholm 	struct efi_hii_packagelist *hii = handle;
478c9bfb222SLeif Lindholm 
479c9bfb222SLeif Lindholm 	EFI_ENTRY("%p, %p", this, handle);
480c9bfb222SLeif Lindholm 
481c9bfb222SLeif Lindholm 	if (!handle || !efi_hii_packagelist_exists(handle))
482c9bfb222SLeif Lindholm 		return EFI_EXIT(EFI_NOT_FOUND);
483c9bfb222SLeif Lindholm 
484c9bfb222SLeif Lindholm 	free_packagelist(hii);
485c9bfb222SLeif Lindholm 
486c9bfb222SLeif Lindholm 	return EFI_EXIT(EFI_SUCCESS);
487c9bfb222SLeif Lindholm }
488c9bfb222SLeif Lindholm 
489c9bfb222SLeif Lindholm 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)490c9bfb222SLeif Lindholm update_package_list(const struct efi_hii_database_protocol *this,
491c9bfb222SLeif Lindholm 		    efi_hii_handle_t handle,
492c9bfb222SLeif Lindholm 		    const struct efi_hii_package_list_header *package_list)
493c9bfb222SLeif Lindholm {
494c9bfb222SLeif Lindholm 	struct efi_hii_packagelist *hii = handle;
495c9bfb222SLeif Lindholm 	struct efi_hii_package_header *package;
496c9bfb222SLeif Lindholm 	void *end;
497c9bfb222SLeif Lindholm 	efi_status_t ret = EFI_SUCCESS;
498c9bfb222SLeif Lindholm 
499c9bfb222SLeif Lindholm 	EFI_ENTRY("%p, %p, %p", this, handle, package_list);
500c9bfb222SLeif Lindholm 
501c9bfb222SLeif Lindholm 	if (!handle || !efi_hii_packagelist_exists(handle))
502c9bfb222SLeif Lindholm 		return EFI_EXIT(EFI_NOT_FOUND);
503c9bfb222SLeif Lindholm 
504c9bfb222SLeif Lindholm 	if (!package_list)
505c9bfb222SLeif Lindholm 		return EFI_EXIT(EFI_INVALID_PARAMETER);
506c9bfb222SLeif Lindholm 
5076f8f4217SHeinrich Schuchardt 	EFI_PRINT("package_list: %pUl (%u)\n", &package_list->package_list_guid,
508c9bfb222SLeif Lindholm 		  get_unaligned_le32(&package_list->package_length));
509c9bfb222SLeif Lindholm 
510c9bfb222SLeif Lindholm 	package = ((void *)package_list) + sizeof(*package_list);
511c9bfb222SLeif Lindholm 	end = ((void *)package_list)
512c9bfb222SLeif Lindholm 		+ get_unaligned_le32(&package_list->package_length);
513c9bfb222SLeif Lindholm 
514c9bfb222SLeif Lindholm 	while ((void *)package < end) {
5156f8f4217SHeinrich Schuchardt 		EFI_PRINT("package=%p, package type=%x, length=%u\n", package,
516c9bfb222SLeif Lindholm 			  efi_hii_package_type(package),
517c9bfb222SLeif Lindholm 			  efi_hii_package_len(package));
518c9bfb222SLeif Lindholm 
519c9bfb222SLeif Lindholm 		switch (efi_hii_package_type(package)) {
520c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_TYPE_GUID:
5219ab0bdd9SAKASHI Takahiro 			remove_guid_package(hii);
522c9bfb222SLeif Lindholm 			break;
523c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_FORMS:
5241a9fce50SHeinrich Schuchardt 			EFI_PRINT("Form package not supported\n");
525c9bfb222SLeif Lindholm 			ret = EFI_INVALID_PARAMETER;
526c9bfb222SLeif Lindholm 			break;
527c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_STRINGS:
528c9bfb222SLeif Lindholm 			remove_strings_package(hii);
529c9bfb222SLeif Lindholm 			break;
530c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_FONTS:
5311a9fce50SHeinrich Schuchardt 			EFI_PRINT("Font package not supported\n");
532c9bfb222SLeif Lindholm 			ret = EFI_INVALID_PARAMETER;
533c9bfb222SLeif Lindholm 			break;
534c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_IMAGES:
5351a9fce50SHeinrich Schuchardt 			EFI_PRINT("Image package not supported\n");
536c9bfb222SLeif Lindholm 			ret = EFI_INVALID_PARAMETER;
537c9bfb222SLeif Lindholm 			break;
538c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_SIMPLE_FONTS:
5391a9fce50SHeinrich Schuchardt 			EFI_PRINT("Simple font package not supported\n");
540c9bfb222SLeif Lindholm 			ret = EFI_INVALID_PARAMETER;
541c9bfb222SLeif Lindholm 			break;
542c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_DEVICE_PATH:
5431a9fce50SHeinrich Schuchardt 			EFI_PRINT("Device path package not supported\n");
544c9bfb222SLeif Lindholm 			ret = EFI_INVALID_PARAMETER;
545c9bfb222SLeif Lindholm 			break;
546c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
5478d3b77e3SAKASHI Takahiro 			remove_keyboard_package(hii);
548c9bfb222SLeif Lindholm 			break;
549c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_ANIMATIONS:
5501a9fce50SHeinrich Schuchardt 			EFI_PRINT("Animation package not supported\n");
551c9bfb222SLeif Lindholm 			ret = EFI_INVALID_PARAMETER;
552c9bfb222SLeif Lindholm 			break;
553c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_END:
554c9bfb222SLeif Lindholm 			goto out;
555c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN:
556c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_TYPE_SYSTEM_END:
557c9bfb222SLeif Lindholm 		default:
558c9bfb222SLeif Lindholm 			break;
559c9bfb222SLeif Lindholm 		}
560c9bfb222SLeif Lindholm 
561c9bfb222SLeif Lindholm 		/* TODO: already removed some packages */
562c9bfb222SLeif Lindholm 		if (ret != EFI_SUCCESS)
563c9bfb222SLeif Lindholm 			return EFI_EXIT(ret);
564c9bfb222SLeif Lindholm 
565c9bfb222SLeif Lindholm 		package = ((void *)package)
566c9bfb222SLeif Lindholm 			  + efi_hii_package_len(package);
567c9bfb222SLeif Lindholm 	}
568c9bfb222SLeif Lindholm out:
569c9bfb222SLeif Lindholm 	ret = add_packages(hii, package_list);
570c9bfb222SLeif Lindholm 
571c9bfb222SLeif Lindholm 	return EFI_EXIT(ret);
572c9bfb222SLeif Lindholm }
573c9bfb222SLeif Lindholm 
574c9bfb222SLeif Lindholm 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)575c9bfb222SLeif Lindholm list_package_lists(const struct efi_hii_database_protocol *this,
576c9bfb222SLeif Lindholm 		   u8 package_type,
577c9bfb222SLeif Lindholm 		   const efi_guid_t *package_guid,
578c9bfb222SLeif Lindholm 		   efi_uintn_t *handle_buffer_length,
579c9bfb222SLeif Lindholm 		   efi_hii_handle_t *handle)
580c9bfb222SLeif Lindholm {
581c9bfb222SLeif Lindholm 	struct efi_hii_packagelist *hii =
582c9bfb222SLeif Lindholm 				(struct efi_hii_packagelist *)handle;
583c9bfb222SLeif Lindholm 	int package_cnt, package_max;
584c9bfb222SLeif Lindholm 	efi_status_t ret = EFI_SUCCESS;
585c9bfb222SLeif Lindholm 
586c9bfb222SLeif Lindholm 	EFI_ENTRY("%p, %u, %pUl, %p, %p", this, package_type, package_guid,
587c9bfb222SLeif Lindholm 		  handle_buffer_length, handle);
588c9bfb222SLeif Lindholm 
589c9bfb222SLeif Lindholm 	if (!handle_buffer_length ||
590c9bfb222SLeif Lindholm 	    (*handle_buffer_length && !handle))
591c9bfb222SLeif Lindholm 		return EFI_EXIT(EFI_INVALID_PARAMETER);
592c9bfb222SLeif Lindholm 
593c9bfb222SLeif Lindholm 	if ((package_type != EFI_HII_PACKAGE_TYPE_GUID && package_guid) ||
594c9bfb222SLeif Lindholm 	    (package_type == EFI_HII_PACKAGE_TYPE_GUID && !package_guid))
595c9bfb222SLeif Lindholm 		return EFI_EXIT(EFI_INVALID_PARAMETER);
596c9bfb222SLeif Lindholm 
5976f8f4217SHeinrich Schuchardt 	EFI_PRINT("package type=%x, guid=%pUl, length=%zu\n", (int)package_type,
598c9bfb222SLeif Lindholm 		  package_guid, *handle_buffer_length);
599c9bfb222SLeif Lindholm 
600c9bfb222SLeif Lindholm 	package_cnt = 0;
601c9bfb222SLeif Lindholm 	package_max = *handle_buffer_length / sizeof(*handle);
602c9bfb222SLeif Lindholm 	list_for_each_entry(hii, &efi_package_lists, link) {
603c9bfb222SLeif Lindholm 		switch (package_type) {
604c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_TYPE_ALL:
605c9bfb222SLeif Lindholm 			break;
606c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_TYPE_GUID:
6079ab0bdd9SAKASHI Takahiro 			if (!list_empty(&hii->guid_list))
6089ab0bdd9SAKASHI Takahiro 				break;
609c9bfb222SLeif Lindholm 			continue;
610c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_FORMS:
6111a9fce50SHeinrich Schuchardt 			EFI_PRINT("Form package not supported\n");
612c9bfb222SLeif Lindholm 			ret = EFI_INVALID_PARAMETER;
613c9bfb222SLeif Lindholm 			continue;
614c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_STRINGS:
615c9bfb222SLeif Lindholm 			if (!list_empty(&hii->string_tables))
616c9bfb222SLeif Lindholm 				break;
617c9bfb222SLeif Lindholm 			continue;
618c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_FONTS:
6191a9fce50SHeinrich Schuchardt 			EFI_PRINT("Font package not supported\n");
620c9bfb222SLeif Lindholm 			ret = EFI_INVALID_PARAMETER;
621c9bfb222SLeif Lindholm 			continue;
622c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_IMAGES:
6231a9fce50SHeinrich Schuchardt 			EFI_PRINT("Image package not supported\n");
624c9bfb222SLeif Lindholm 			ret = EFI_INVALID_PARAMETER;
625c9bfb222SLeif Lindholm 			continue;
626c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_SIMPLE_FONTS:
6271a9fce50SHeinrich Schuchardt 			EFI_PRINT("Simple font package not supported\n");
628c9bfb222SLeif Lindholm 			ret = EFI_INVALID_PARAMETER;
629c9bfb222SLeif Lindholm 			continue;
630c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_DEVICE_PATH:
6311a9fce50SHeinrich Schuchardt 			EFI_PRINT("Device path package not supported\n");
632c9bfb222SLeif Lindholm 			ret = EFI_INVALID_PARAMETER;
633c9bfb222SLeif Lindholm 			continue;
634c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
6358d3b77e3SAKASHI Takahiro 			if (!list_empty(&hii->keyboard_packages))
6368d3b77e3SAKASHI Takahiro 				break;
637c9bfb222SLeif Lindholm 			continue;
638c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_ANIMATIONS:
6391a9fce50SHeinrich Schuchardt 			EFI_PRINT("Animation package not supported\n");
640c9bfb222SLeif Lindholm 			ret = EFI_INVALID_PARAMETER;
641c9bfb222SLeif Lindholm 			continue;
642c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_END:
643c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN:
644c9bfb222SLeif Lindholm 		case EFI_HII_PACKAGE_TYPE_SYSTEM_END:
645c9bfb222SLeif Lindholm 		default:
646c9bfb222SLeif Lindholm 			continue;
647c9bfb222SLeif Lindholm 		}
648c9bfb222SLeif Lindholm 
649c9bfb222SLeif Lindholm 		package_cnt++;
650c9bfb222SLeif Lindholm 		if (package_cnt <= package_max)
651c9bfb222SLeif Lindholm 			*handle++ = hii;
652c9bfb222SLeif Lindholm 		else
653c9bfb222SLeif Lindholm 			ret = EFI_BUFFER_TOO_SMALL;
654c9bfb222SLeif Lindholm 	}
655c9bfb222SLeif Lindholm 	*handle_buffer_length = package_cnt * sizeof(*handle);
656c9bfb222SLeif Lindholm 
657c9bfb222SLeif Lindholm 	return EFI_EXIT(ret);
658c9bfb222SLeif Lindholm }
659c9bfb222SLeif Lindholm 
660c9bfb222SLeif Lindholm 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)661c9bfb222SLeif Lindholm export_package_lists(const struct efi_hii_database_protocol *this,
662c9bfb222SLeif Lindholm 		     efi_hii_handle_t handle,
663c9bfb222SLeif Lindholm 		     efi_uintn_t *buffer_size,
664c9bfb222SLeif Lindholm 		     struct efi_hii_package_list_header *buffer)
665c9bfb222SLeif Lindholm {
666c9bfb222SLeif Lindholm 	EFI_ENTRY("%p, %p, %p, %p", this, handle, buffer_size, buffer);
667c9bfb222SLeif Lindholm 
668c9bfb222SLeif Lindholm 	if (!buffer_size || !buffer)
669c9bfb222SLeif Lindholm 		return EFI_EXIT(EFI_INVALID_PARAMETER);
670c9bfb222SLeif Lindholm 
671c9bfb222SLeif Lindholm 	return EFI_EXIT(EFI_NOT_FOUND);
672c9bfb222SLeif Lindholm }
673c9bfb222SLeif Lindholm 
674c9bfb222SLeif Lindholm 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)675c9bfb222SLeif Lindholm register_package_notify(const struct efi_hii_database_protocol *this,
676c9bfb222SLeif Lindholm 			u8 package_type,
677c9bfb222SLeif Lindholm 			const efi_guid_t *package_guid,
678c9bfb222SLeif Lindholm 			const void *package_notify_fn,
679c9bfb222SLeif Lindholm 			efi_uintn_t notify_type,
680c9bfb222SLeif Lindholm 			efi_handle_t *notify_handle)
681c9bfb222SLeif Lindholm {
682c9bfb222SLeif Lindholm 	EFI_ENTRY("%p, %u, %pUl, %p, %zu, %p", this, package_type,
683c9bfb222SLeif Lindholm 		  package_guid, package_notify_fn, notify_type,
684c9bfb222SLeif Lindholm 		  notify_handle);
685c9bfb222SLeif Lindholm 
686c9bfb222SLeif Lindholm 	if (!notify_handle)
687c9bfb222SLeif Lindholm 		return EFI_EXIT(EFI_INVALID_PARAMETER);
688c9bfb222SLeif Lindholm 
689c9bfb222SLeif Lindholm 	if ((package_type != EFI_HII_PACKAGE_TYPE_GUID && package_guid) ||
690c9bfb222SLeif Lindholm 	    (package_type == EFI_HII_PACKAGE_TYPE_GUID && !package_guid))
691c9bfb222SLeif Lindholm 		return EFI_EXIT(EFI_INVALID_PARAMETER);
692c9bfb222SLeif Lindholm 
693c9bfb222SLeif Lindholm 	return EFI_EXIT(EFI_OUT_OF_RESOURCES);
694c9bfb222SLeif Lindholm }
695c9bfb222SLeif Lindholm 
696c9bfb222SLeif Lindholm static efi_status_t EFIAPI
unregister_package_notify(const struct efi_hii_database_protocol * this,efi_handle_t notification_handle)697c9bfb222SLeif Lindholm unregister_package_notify(const struct efi_hii_database_protocol *this,
698c9bfb222SLeif Lindholm 			  efi_handle_t notification_handle)
699c9bfb222SLeif Lindholm {
700c9bfb222SLeif Lindholm 	EFI_ENTRY("%p, %p", this, notification_handle);
701c9bfb222SLeif Lindholm 
702c9bfb222SLeif Lindholm 	return EFI_EXIT(EFI_NOT_FOUND);
703c9bfb222SLeif Lindholm }
704c9bfb222SLeif Lindholm 
705c9bfb222SLeif Lindholm 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)706c9bfb222SLeif Lindholm find_keyboard_layouts(const struct efi_hii_database_protocol *this,
707c9bfb222SLeif Lindholm 		      u16 *key_guid_buffer_length,
708c9bfb222SLeif Lindholm 		      efi_guid_t *key_guid_buffer)
709c9bfb222SLeif Lindholm {
7108d3b77e3SAKASHI Takahiro 	struct efi_keyboard_layout_data *layout_data;
7118d3b77e3SAKASHI Takahiro 	int package_cnt, package_max;
7128d3b77e3SAKASHI Takahiro 	efi_status_t ret = EFI_SUCCESS;
7138d3b77e3SAKASHI Takahiro 
714c9bfb222SLeif Lindholm 	EFI_ENTRY("%p, %p, %p", this, key_guid_buffer_length, key_guid_buffer);
715c9bfb222SLeif Lindholm 
7168d3b77e3SAKASHI Takahiro 	if (!key_guid_buffer_length ||
7178d3b77e3SAKASHI Takahiro 	    (*key_guid_buffer_length && !key_guid_buffer))
7188d3b77e3SAKASHI Takahiro 		return EFI_EXIT(EFI_INVALID_PARAMETER);
7198d3b77e3SAKASHI Takahiro 
7208d3b77e3SAKASHI Takahiro 	package_cnt = 0;
7218d3b77e3SAKASHI Takahiro 	package_max = *key_guid_buffer_length / sizeof(*key_guid_buffer);
7228d3b77e3SAKASHI Takahiro 	list_for_each_entry(layout_data, &efi_keyboard_layout_list, link_sys) {
7238d3b77e3SAKASHI Takahiro 		package_cnt++;
7248d3b77e3SAKASHI Takahiro 		if (package_cnt <= package_max)
7258d3b77e3SAKASHI Takahiro 			memcpy(key_guid_buffer++,
7268d3b77e3SAKASHI Takahiro 			       &layout_data->keyboard_layout.guid,
7278d3b77e3SAKASHI Takahiro 			       sizeof(*key_guid_buffer));
7288d3b77e3SAKASHI Takahiro 		else
7298d3b77e3SAKASHI Takahiro 			ret = EFI_BUFFER_TOO_SMALL;
7308d3b77e3SAKASHI Takahiro 	}
7318d3b77e3SAKASHI Takahiro 	*key_guid_buffer_length = package_cnt * sizeof(*key_guid_buffer);
7328d3b77e3SAKASHI Takahiro 
7338d3b77e3SAKASHI Takahiro 	return EFI_EXIT(ret);
734c9bfb222SLeif Lindholm }
735c9bfb222SLeif Lindholm 
736c9bfb222SLeif Lindholm 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)737c9bfb222SLeif Lindholm get_keyboard_layout(const struct efi_hii_database_protocol *this,
738c9bfb222SLeif Lindholm 		    efi_guid_t *key_guid,
739c9bfb222SLeif Lindholm 		    u16 *keyboard_layout_length,
740c9bfb222SLeif Lindholm 		    struct efi_hii_keyboard_layout *keyboard_layout)
741c9bfb222SLeif Lindholm {
7428d3b77e3SAKASHI Takahiro 	struct efi_keyboard_layout_data *layout_data;
7438d3b77e3SAKASHI Takahiro 	u16 layout_length;
7448d3b77e3SAKASHI Takahiro 
745c9bfb222SLeif Lindholm 	EFI_ENTRY("%p, %pUl, %p, %p", this, key_guid, keyboard_layout_length,
746c9bfb222SLeif Lindholm 		  keyboard_layout);
747c9bfb222SLeif Lindholm 
7488d3b77e3SAKASHI Takahiro 	if (!keyboard_layout_length ||
7498d3b77e3SAKASHI Takahiro 	    (*keyboard_layout_length && !keyboard_layout))
7508d3b77e3SAKASHI Takahiro 		return EFI_EXIT(EFI_INVALID_PARAMETER);
7518d3b77e3SAKASHI Takahiro 
7528d3b77e3SAKASHI Takahiro 	/* TODO: no notion of current keyboard layout */
7538d3b77e3SAKASHI Takahiro 	if (!key_guid)
7548d3b77e3SAKASHI Takahiro 		return EFI_EXIT(EFI_INVALID_PARAMETER);
7558d3b77e3SAKASHI Takahiro 
7568d3b77e3SAKASHI Takahiro 	list_for_each_entry(layout_data, &efi_keyboard_layout_list, link_sys) {
7578d3b77e3SAKASHI Takahiro 		if (!guidcmp(&layout_data->keyboard_layout.guid, key_guid))
7588d3b77e3SAKASHI Takahiro 			goto found;
7598d3b77e3SAKASHI Takahiro 	}
7608d3b77e3SAKASHI Takahiro 
761c9bfb222SLeif Lindholm 	return EFI_EXIT(EFI_NOT_FOUND);
7628d3b77e3SAKASHI Takahiro 
7638d3b77e3SAKASHI Takahiro found:
7648d3b77e3SAKASHI Takahiro 	layout_length =
7658d3b77e3SAKASHI Takahiro 		get_unaligned_le16(&layout_data->keyboard_layout.layout_length);
7668d3b77e3SAKASHI Takahiro 	if (*keyboard_layout_length < layout_length) {
7678d3b77e3SAKASHI Takahiro 		*keyboard_layout_length = layout_length;
7688d3b77e3SAKASHI Takahiro 		return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
7698d3b77e3SAKASHI Takahiro 	}
7708d3b77e3SAKASHI Takahiro 
7718d3b77e3SAKASHI Takahiro 	memcpy(keyboard_layout, &layout_data->keyboard_layout, layout_length);
7728d3b77e3SAKASHI Takahiro 
7738d3b77e3SAKASHI Takahiro 	return EFI_EXIT(EFI_SUCCESS);
774c9bfb222SLeif Lindholm }
775c9bfb222SLeif Lindholm 
776c9bfb222SLeif Lindholm static efi_status_t EFIAPI
set_keyboard_layout(const struct efi_hii_database_protocol * this,efi_guid_t * key_guid)777c9bfb222SLeif Lindholm set_keyboard_layout(const struct efi_hii_database_protocol *this,
778c9bfb222SLeif Lindholm 		    efi_guid_t *key_guid)
779c9bfb222SLeif Lindholm {
780c9bfb222SLeif Lindholm 	EFI_ENTRY("%p, %pUl", this, key_guid);
781c9bfb222SLeif Lindholm 
782c9bfb222SLeif Lindholm 	return EFI_EXIT(EFI_NOT_FOUND);
783c9bfb222SLeif Lindholm }
784c9bfb222SLeif Lindholm 
785c9bfb222SLeif Lindholm 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)786c9bfb222SLeif Lindholm get_package_list_handle(const struct efi_hii_database_protocol *this,
787c9bfb222SLeif Lindholm 			efi_hii_handle_t package_list_handle,
788c9bfb222SLeif Lindholm 			efi_handle_t *driver_handle)
789c9bfb222SLeif Lindholm {
790c9bfb222SLeif Lindholm 	struct efi_hii_packagelist *hii;
791c9bfb222SLeif Lindholm 
792c9bfb222SLeif Lindholm 	EFI_ENTRY("%p, %p, %p", this, package_list_handle, driver_handle);
793c9bfb222SLeif Lindholm 
794c9bfb222SLeif Lindholm 	if (!driver_handle)
795c9bfb222SLeif Lindholm 		return EFI_EXIT(EFI_INVALID_PARAMETER);
796c9bfb222SLeif Lindholm 
797c9bfb222SLeif Lindholm 	list_for_each_entry(hii, &efi_package_lists, link) {
798c9bfb222SLeif Lindholm 		if (hii == package_list_handle) {
799c9bfb222SLeif Lindholm 			*driver_handle = hii->driver_handle;
800c9bfb222SLeif Lindholm 			return EFI_EXIT(EFI_SUCCESS);
801c9bfb222SLeif Lindholm 		}
802c9bfb222SLeif Lindholm 	}
803c9bfb222SLeif Lindholm 
804c9bfb222SLeif Lindholm 	return EFI_EXIT(EFI_NOT_FOUND);
805c9bfb222SLeif Lindholm }
806c9bfb222SLeif Lindholm 
807c9bfb222SLeif Lindholm const struct efi_hii_database_protocol efi_hii_database = {
808c9bfb222SLeif Lindholm 	.new_package_list = new_package_list,
809c9bfb222SLeif Lindholm 	.remove_package_list = remove_package_list,
810c9bfb222SLeif Lindholm 	.update_package_list = update_package_list,
811c9bfb222SLeif Lindholm 	.list_package_lists = list_package_lists,
812c9bfb222SLeif Lindholm 	.export_package_lists = export_package_lists,
813c9bfb222SLeif Lindholm 	.register_package_notify = register_package_notify,
814c9bfb222SLeif Lindholm 	.unregister_package_notify = unregister_package_notify,
815c9bfb222SLeif Lindholm 	.find_keyboard_layouts = find_keyboard_layouts,
816c9bfb222SLeif Lindholm 	.get_keyboard_layout = get_keyboard_layout,
817c9bfb222SLeif Lindholm 	.set_keyboard_layout = set_keyboard_layout,
818c9bfb222SLeif Lindholm 	.get_package_list_handle = get_package_list_handle
819c9bfb222SLeif Lindholm };
820c9bfb222SLeif Lindholm 
821c9bfb222SLeif Lindholm /*
822c9bfb222SLeif Lindholm  * EFI_HII_STRING_PROTOCOL
823c9bfb222SLeif Lindholm  */
824c9bfb222SLeif Lindholm 
language_match(char * language,char * languages)825c9bfb222SLeif Lindholm static bool language_match(char *language, char *languages)
826c9bfb222SLeif Lindholm {
827c9bfb222SLeif Lindholm 	size_t n;
828c9bfb222SLeif Lindholm 
829c9bfb222SLeif Lindholm 	n = strlen(language);
830c9bfb222SLeif Lindholm 	/* match primary language? */
831c9bfb222SLeif Lindholm 	if (!strncasecmp(language, languages, n) &&
832c9bfb222SLeif Lindholm 	    (languages[n] == ';' || languages[n] == '\0'))
833c9bfb222SLeif Lindholm 		return true;
834c9bfb222SLeif Lindholm 
835c9bfb222SLeif Lindholm 	return false;
836c9bfb222SLeif Lindholm }
837c9bfb222SLeif Lindholm 
838c9bfb222SLeif Lindholm 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)839c9bfb222SLeif Lindholm new_string(const struct efi_hii_string_protocol *this,
840c9bfb222SLeif Lindholm 	   efi_hii_handle_t package_list,
841c9bfb222SLeif Lindholm 	   efi_string_id_t *string_id,
842c9bfb222SLeif Lindholm 	   const u8 *language,
843c9bfb222SLeif Lindholm 	   const u16 *language_name,
844c9bfb222SLeif Lindholm 	   const efi_string_t string,
845c9bfb222SLeif Lindholm 	   const struct efi_font_info *string_font_info)
846c9bfb222SLeif Lindholm {
847c9bfb222SLeif Lindholm 	struct efi_hii_packagelist *hii = package_list;
848c9bfb222SLeif Lindholm 	struct efi_string_table *stbl;
849c9bfb222SLeif Lindholm 
850c9bfb222SLeif Lindholm 	EFI_ENTRY("%p, %p, %p, \"%s\", %p, \"%ls\", %p", this, package_list,
851c9bfb222SLeif Lindholm 		  string_id, language, language_name, string,
852c9bfb222SLeif Lindholm 		  string_font_info);
853c9bfb222SLeif Lindholm 
854c9bfb222SLeif Lindholm 	if (!package_list || !efi_hii_packagelist_exists(package_list))
855c9bfb222SLeif Lindholm 		return EFI_EXIT(EFI_NOT_FOUND);
856c9bfb222SLeif Lindholm 
857c9bfb222SLeif Lindholm 	if (!string_id || !language || !string)
858c9bfb222SLeif Lindholm 		return EFI_EXIT(EFI_INVALID_PARAMETER);
859c9bfb222SLeif Lindholm 
860c9bfb222SLeif Lindholm 	list_for_each_entry(stbl, &hii->string_tables, link) {
861c9bfb222SLeif Lindholm 		if (language_match((char *)language, stbl->language)) {
862c9bfb222SLeif Lindholm 			efi_string_id_t new_id;
863c9bfb222SLeif Lindholm 			void *buf;
864c9bfb222SLeif Lindholm 			efi_string_t str;
865c9bfb222SLeif Lindholm 
866c9bfb222SLeif Lindholm 			new_id = ++hii->max_string_id;
867c9bfb222SLeif Lindholm 			if (stbl->nstrings < new_id) {
868c9bfb222SLeif Lindholm 				buf = realloc(stbl->strings,
869c9bfb222SLeif Lindholm 					      sizeof(stbl->strings[0])
870c9bfb222SLeif Lindholm 						* new_id);
871c9bfb222SLeif Lindholm 				if (!buf)
872c9bfb222SLeif Lindholm 					return EFI_EXIT(EFI_OUT_OF_RESOURCES);
873c9bfb222SLeif Lindholm 
874c9bfb222SLeif Lindholm 				memset(&stbl->strings[stbl->nstrings], 0,
875c9bfb222SLeif Lindholm 				       (new_id - stbl->nstrings)
876c9bfb222SLeif Lindholm 					 * sizeof(stbl->strings[0]));
877c9bfb222SLeif Lindholm 				stbl->strings = buf;
878c9bfb222SLeif Lindholm 				stbl->nstrings = new_id;
879c9bfb222SLeif Lindholm 			}
880c9bfb222SLeif Lindholm 
881c9bfb222SLeif Lindholm 			str = u16_strdup(string);
882c9bfb222SLeif Lindholm 			if (!str)
883c9bfb222SLeif Lindholm 				return EFI_EXIT(EFI_OUT_OF_RESOURCES);
884c9bfb222SLeif Lindholm 
885c9bfb222SLeif Lindholm 			stbl->strings[new_id - 1].string = str;
886c9bfb222SLeif Lindholm 			*string_id = new_id;
887c9bfb222SLeif Lindholm 
888c9bfb222SLeif Lindholm 			return EFI_EXIT(EFI_SUCCESS);
889c9bfb222SLeif Lindholm 		}
890c9bfb222SLeif Lindholm 	}
891c9bfb222SLeif Lindholm 
892c9bfb222SLeif Lindholm 	return EFI_EXIT(EFI_NOT_FOUND);
893c9bfb222SLeif Lindholm }
894c9bfb222SLeif Lindholm 
895c9bfb222SLeif Lindholm 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)896c9bfb222SLeif Lindholm get_string(const struct efi_hii_string_protocol *this,
897c9bfb222SLeif Lindholm 	   const u8 *language,
898c9bfb222SLeif Lindholm 	   efi_hii_handle_t package_list,
899c9bfb222SLeif Lindholm 	   efi_string_id_t string_id,
900c9bfb222SLeif Lindholm 	   efi_string_t string,
901c9bfb222SLeif Lindholm 	   efi_uintn_t *string_size,
902c9bfb222SLeif Lindholm 	   struct efi_font_info **string_font_info)
903c9bfb222SLeif Lindholm {
904c9bfb222SLeif Lindholm 	struct efi_hii_packagelist *hii = package_list;
905c9bfb222SLeif Lindholm 	struct efi_string_table *stbl;
906c9bfb222SLeif Lindholm 
907c9bfb222SLeif Lindholm 	EFI_ENTRY("%p, \"%s\", %p, %u, %p, %p, %p", this, language,
908c9bfb222SLeif Lindholm 		  package_list, string_id, string, string_size,
909c9bfb222SLeif Lindholm 		  string_font_info);
910c9bfb222SLeif Lindholm 
911c9bfb222SLeif Lindholm 	if (!package_list || !efi_hii_packagelist_exists(package_list))
912c9bfb222SLeif Lindholm 		return EFI_EXIT(EFI_NOT_FOUND);
913c9bfb222SLeif Lindholm 
914c9bfb222SLeif Lindholm 	list_for_each_entry(stbl, &hii->string_tables, link) {
915c9bfb222SLeif Lindholm 		if (language_match((char *)language, stbl->language)) {
916c9bfb222SLeif Lindholm 			efi_string_t str;
917c9bfb222SLeif Lindholm 			size_t len;
918c9bfb222SLeif Lindholm 
919c9bfb222SLeif Lindholm 			if (stbl->nstrings < string_id)
920c9bfb222SLeif Lindholm 				return EFI_EXIT(EFI_NOT_FOUND);
921c9bfb222SLeif Lindholm 
922c9bfb222SLeif Lindholm 			str = stbl->strings[string_id - 1].string;
923c9bfb222SLeif Lindholm 			if (str) {
924c9bfb222SLeif Lindholm 				len = (u16_strlen(str) + 1) * sizeof(u16);
925c9bfb222SLeif Lindholm 				if (*string_size < len) {
926c9bfb222SLeif Lindholm 					*string_size = len;
927c9bfb222SLeif Lindholm 
928c9bfb222SLeif Lindholm 					return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
929c9bfb222SLeif Lindholm 				}
930c9bfb222SLeif Lindholm 				memcpy(string, str, len);
931c9bfb222SLeif Lindholm 				*string_size = len;
932c9bfb222SLeif Lindholm 			} else {
933c9bfb222SLeif Lindholm 				return EFI_EXIT(EFI_NOT_FOUND);
934c9bfb222SLeif Lindholm 			}
935c9bfb222SLeif Lindholm 
936c9bfb222SLeif Lindholm 			return EFI_EXIT(EFI_SUCCESS);
937c9bfb222SLeif Lindholm 		}
938c9bfb222SLeif Lindholm 	}
939c9bfb222SLeif Lindholm 
940c9bfb222SLeif Lindholm 	return EFI_EXIT(EFI_NOT_FOUND);
941c9bfb222SLeif Lindholm }
942c9bfb222SLeif Lindholm 
943c9bfb222SLeif Lindholm 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)944c9bfb222SLeif Lindholm set_string(const struct efi_hii_string_protocol *this,
945c9bfb222SLeif Lindholm 	   efi_hii_handle_t package_list,
946c9bfb222SLeif Lindholm 	   efi_string_id_t string_id,
947c9bfb222SLeif Lindholm 	   const u8 *language,
948c9bfb222SLeif Lindholm 	   const efi_string_t string,
949c9bfb222SLeif Lindholm 	   const struct efi_font_info *string_font_info)
950c9bfb222SLeif Lindholm {
951c9bfb222SLeif Lindholm 	struct efi_hii_packagelist *hii = package_list;
952c9bfb222SLeif Lindholm 	struct efi_string_table *stbl;
953c9bfb222SLeif Lindholm 
954c9bfb222SLeif Lindholm 	EFI_ENTRY("%p, %p, %u, \"%s\", \"%ls\", %p", this, package_list,
955c9bfb222SLeif Lindholm 		  string_id, language, string, string_font_info);
956c9bfb222SLeif Lindholm 
957c9bfb222SLeif Lindholm 	if (!package_list || !efi_hii_packagelist_exists(package_list))
958c9bfb222SLeif Lindholm 		return EFI_EXIT(EFI_NOT_FOUND);
959c9bfb222SLeif Lindholm 
960c9bfb222SLeif Lindholm 	if (string_id > hii->max_string_id)
961c9bfb222SLeif Lindholm 		return EFI_EXIT(EFI_NOT_FOUND);
962c9bfb222SLeif Lindholm 
963c9bfb222SLeif Lindholm 	if (!string || !language)
964c9bfb222SLeif Lindholm 		return EFI_EXIT(EFI_INVALID_PARAMETER);
965c9bfb222SLeif Lindholm 
966c9bfb222SLeif Lindholm 	list_for_each_entry(stbl, &hii->string_tables, link) {
967c9bfb222SLeif Lindholm 		if (language_match((char *)language, stbl->language)) {
968c9bfb222SLeif Lindholm 			efi_string_t str;
969c9bfb222SLeif Lindholm 
970c9bfb222SLeif Lindholm 			if (hii->max_string_id < string_id)
971c9bfb222SLeif Lindholm 				return EFI_EXIT(EFI_NOT_FOUND);
972c9bfb222SLeif Lindholm 
973c9bfb222SLeif Lindholm 			if (stbl->nstrings < string_id) {
974c9bfb222SLeif Lindholm 				void *buf;
975c9bfb222SLeif Lindholm 
976c9bfb222SLeif Lindholm 				buf = realloc(stbl->strings,
977c9bfb222SLeif Lindholm 					      string_id
978c9bfb222SLeif Lindholm 						* sizeof(stbl->strings[0]));
979c9bfb222SLeif Lindholm 				if (!buf)
980c9bfb222SLeif Lindholm 					return EFI_EXIT(EFI_OUT_OF_RESOURCES);
981c9bfb222SLeif Lindholm 
982c9bfb222SLeif Lindholm 				memset(&stbl->strings[string_id - 1], 0,
983c9bfb222SLeif Lindholm 				       (string_id - stbl->nstrings)
984c9bfb222SLeif Lindholm 					 * sizeof(stbl->strings[0]));
985c9bfb222SLeif Lindholm 				stbl->strings = buf;
986c9bfb222SLeif Lindholm 			}
987c9bfb222SLeif Lindholm 
988c9bfb222SLeif Lindholm 			str = u16_strdup(string);
989c9bfb222SLeif Lindholm 			if (!str)
990c9bfb222SLeif Lindholm 				return EFI_EXIT(EFI_OUT_OF_RESOURCES);
991c9bfb222SLeif Lindholm 
992c9bfb222SLeif Lindholm 			free(stbl->strings[string_id - 1].string);
993c9bfb222SLeif Lindholm 			stbl->strings[string_id - 1].string = str;
994c9bfb222SLeif Lindholm 
995c9bfb222SLeif Lindholm 			return EFI_EXIT(EFI_SUCCESS);
996c9bfb222SLeif Lindholm 		}
997c9bfb222SLeif Lindholm 	}
998c9bfb222SLeif Lindholm 
999c9bfb222SLeif Lindholm 	return EFI_EXIT(EFI_NOT_FOUND);
1000c9bfb222SLeif Lindholm }
1001c9bfb222SLeif Lindholm 
1002c9bfb222SLeif Lindholm 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)1003c9bfb222SLeif Lindholm get_languages(const struct efi_hii_string_protocol *this,
1004c9bfb222SLeif Lindholm 	      efi_hii_handle_t package_list,
1005c9bfb222SLeif Lindholm 	      u8 *languages,
1006c9bfb222SLeif Lindholm 	      efi_uintn_t *languages_size)
1007c9bfb222SLeif Lindholm {
1008c9bfb222SLeif Lindholm 	struct efi_hii_packagelist *hii = package_list;
1009c9bfb222SLeif Lindholm 	struct efi_string_table *stbl;
1010c9bfb222SLeif Lindholm 	size_t len = 0;
1011c9bfb222SLeif Lindholm 	char *p;
1012c9bfb222SLeif Lindholm 
1013c9bfb222SLeif Lindholm 	EFI_ENTRY("%p, %p, %p, %p", this, package_list, languages,
1014c9bfb222SLeif Lindholm 		  languages_size);
1015c9bfb222SLeif Lindholm 
1016c9bfb222SLeif Lindholm 	if (!package_list || !efi_hii_packagelist_exists(package_list))
1017c9bfb222SLeif Lindholm 		return EFI_EXIT(EFI_NOT_FOUND);
1018c9bfb222SLeif Lindholm 
1019c9bfb222SLeif Lindholm 	if (!languages_size ||
1020c9bfb222SLeif Lindholm 	    (*languages_size && !languages))
1021c9bfb222SLeif Lindholm 		return EFI_EXIT(EFI_INVALID_PARAMETER);
1022c9bfb222SLeif Lindholm 
1023c9bfb222SLeif Lindholm 	/* figure out required size: */
1024c9bfb222SLeif Lindholm 	list_for_each_entry(stbl, &hii->string_tables, link) {
1025c9bfb222SLeif Lindholm 		len += strlen((char *)stbl->language) + 1;
1026c9bfb222SLeif Lindholm 	}
1027c9bfb222SLeif Lindholm 
1028c9bfb222SLeif Lindholm 	if (*languages_size < len) {
1029c9bfb222SLeif Lindholm 		*languages_size = len;
1030c9bfb222SLeif Lindholm 
1031c9bfb222SLeif Lindholm 		return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
1032c9bfb222SLeif Lindholm 	}
1033c9bfb222SLeif Lindholm 
1034c9bfb222SLeif Lindholm 	p = (char *)languages;
1035c9bfb222SLeif Lindholm 	list_for_each_entry(stbl, &hii->string_tables, link) {
1036c9bfb222SLeif Lindholm 		if (p != (char *)languages)
1037c9bfb222SLeif Lindholm 			*p++ = ';';
1038c9bfb222SLeif Lindholm 		strcpy(p, stbl->language);
1039c9bfb222SLeif Lindholm 		p += strlen((char *)stbl->language);
1040c9bfb222SLeif Lindholm 	}
1041c9bfb222SLeif Lindholm 	*p = '\0';
1042c9bfb222SLeif Lindholm 
10436f8f4217SHeinrich Schuchardt 	EFI_PRINT("languages: %s\n", languages);
1044c9bfb222SLeif Lindholm 
1045c9bfb222SLeif Lindholm 	return EFI_EXIT(EFI_SUCCESS);
1046c9bfb222SLeif Lindholm }
1047c9bfb222SLeif Lindholm 
1048c9bfb222SLeif Lindholm 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)1049c9bfb222SLeif Lindholm get_secondary_languages(const struct efi_hii_string_protocol *this,
1050c9bfb222SLeif Lindholm 			efi_hii_handle_t package_list,
1051c9bfb222SLeif Lindholm 			const u8 *primary_language,
1052c9bfb222SLeif Lindholm 			u8 *secondary_languages,
1053c9bfb222SLeif Lindholm 			efi_uintn_t *secondary_languages_size)
1054c9bfb222SLeif Lindholm {
1055c9bfb222SLeif Lindholm 	struct efi_hii_packagelist *hii = package_list;
1056c9bfb222SLeif Lindholm 	struct efi_string_table *stbl;
1057c9bfb222SLeif Lindholm 	bool found = false;
1058c9bfb222SLeif Lindholm 
1059c9bfb222SLeif Lindholm 	EFI_ENTRY("%p, %p, \"%s\", %p, %p", this, package_list,
1060c9bfb222SLeif Lindholm 		  primary_language, secondary_languages,
1061c9bfb222SLeif Lindholm 		  secondary_languages_size);
1062c9bfb222SLeif Lindholm 
1063c9bfb222SLeif Lindholm 	if (!package_list || !efi_hii_packagelist_exists(package_list))
1064c9bfb222SLeif Lindholm 		return EFI_EXIT(EFI_NOT_FOUND);
1065c9bfb222SLeif Lindholm 
1066c9bfb222SLeif Lindholm 	if (!secondary_languages_size ||
1067c9bfb222SLeif Lindholm 	    (*secondary_languages_size && !secondary_languages))
1068c9bfb222SLeif Lindholm 		return EFI_EXIT(EFI_INVALID_PARAMETER);
1069c9bfb222SLeif Lindholm 
1070c9bfb222SLeif Lindholm 	list_for_each_entry(stbl, &hii->string_tables, link) {
1071c9bfb222SLeif Lindholm 		if (language_match((char *)primary_language, stbl->language)) {
1072c9bfb222SLeif Lindholm 			found = true;
1073c9bfb222SLeif Lindholm 			break;
1074c9bfb222SLeif Lindholm 		}
1075c9bfb222SLeif Lindholm 	}
1076c9bfb222SLeif Lindholm 	if (!found)
1077c9bfb222SLeif Lindholm 		return EFI_EXIT(EFI_INVALID_LANGUAGE);
1078c9bfb222SLeif Lindholm 
1079c9bfb222SLeif Lindholm 	/*
1080c9bfb222SLeif Lindholm 	 * TODO: What is secondary language?
1081c9bfb222SLeif Lindholm 	 * *secondary_languages = '\0';
1082c9bfb222SLeif Lindholm 	 * *secondary_languages_size = 0;
1083c9bfb222SLeif Lindholm 	 */
1084c9bfb222SLeif Lindholm 
1085c9bfb222SLeif Lindholm 	return EFI_EXIT(EFI_NOT_FOUND);
1086c9bfb222SLeif Lindholm }
1087c9bfb222SLeif Lindholm 
1088c9bfb222SLeif Lindholm const struct efi_hii_string_protocol efi_hii_string = {
1089c9bfb222SLeif Lindholm 	.new_string = new_string,
1090c9bfb222SLeif Lindholm 	.get_string = get_string,
1091c9bfb222SLeif Lindholm 	.set_string = set_string,
1092c9bfb222SLeif Lindholm 	.get_languages = get_languages,
1093c9bfb222SLeif Lindholm 	.get_secondary_languages = get_secondary_languages
1094c9bfb222SLeif Lindholm };
1095