Skip to content

Commit 338b7e5

Browse files
Ying-Chun Liu (PaulLiu)grandpaul
authored andcommitted
implement UEFI HII Database Protocol
Shell.efi from EDK2 requires this protocol to be existed. Otherwise it crashes. So we implemented a minimum set of UEFI HII Database Protocol to let the Shell.efi to run. Signed-off-by: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
1 parent e4d6522 commit 338b7e5

6 files changed

Lines changed: 394 additions & 0 deletions

File tree

lib/uefi/boot_service_provider.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <uefi/protocols/gbl_efi_image_loading_protocol.h>
2929
#include <uefi/protocols/gbl_efi_os_configuration_protocol.h>
3030
#include <uefi/protocols/loaded_image_protocol.h>
31+
#include <uefi/protocols/hii_protocol.h>
3132
#include <uefi/types.h>
3233

3334
#include "blockio2_protocols.h"
@@ -104,6 +105,15 @@ EfiStatus locate_protocol(const EfiGuid *protocol, void *registration,
104105
printf("%s(EFI_TCG2_PROTOCOL_GUID) is unsupported.\n", __FUNCTION__);
105106
return EFI_STATUS_NOT_FOUND;
106107
}
108+
if (guid_eq(protocol, EFI_HII_DATABASE_PROTOCOL_GUID)) {
109+
printf("%s(EFI_HII_DATABASE_PROTOCOL_GUID) is supported.\n",
110+
__FUNCTION__);
111+
*intf = open_hii_database_protocol();
112+
if (*intf == nullptr) {
113+
return EFI_STATUS_OUT_OF_RESOURCES;
114+
}
115+
return EFI_STATUS_SUCCESS;
116+
}
107117

108118
printf("%s(%x %x %x %llx) is unsupported\n", __FUNCTION__, protocol->data1,
109119
protocol->data2, protocol->data3,

lib/uefi/boot_service_provider.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,12 @@ static constexpr auto EFI_ERASE_BLOCK_PROTOCOL_GUID =
134134
0x4926,
135135
{0xaa, 0xef, 0x99, 0x18, 0xe7, 0x72, 0xd9, 0x87}};
136136

137+
static constexpr auto EFI_HII_DATABASE_PROTOCOL_GUID =
138+
EfiGuid{0xEF9FC172,
139+
0xA1B2,
140+
0x4693,
141+
{0xB3, 0x27, 0x6D, 0x32, 0xFC, 0x41, 0x60, 0x42}};
142+
137143
using EFI_IMAGE_UNLOAD = EfiStatus (*)(EfiHandle);
138144

139145
//******************************************************

lib/uefi/hii_protocol.cpp

Lines changed: 268 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
/*
2+
* Copyright (C) 2025 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
#include <stdio.h>
19+
#include <stdint.h>
20+
#include <string.h>
21+
#include <malloc.h>
22+
#include <uefi/protocols/hii_protocol.h>
23+
24+
namespace {
25+
const int EFI_HII_PACKAGE_TYPE_SHIFT = 24;
26+
const uint32_t EFI_HII_PACKAGE_TYPE_MASK = 0xff;
27+
const int EFI_HII_PACKAGE_LEN_SHIFT = 0;
28+
const uint32_t EFI_HII_PACKAGE_LEN_MASK = 0xffffff;
29+
30+
struct efi_string_info {
31+
uint16_t *string;
32+
};
33+
34+
struct efi_string_table {
35+
struct list_node node;
36+
uint16_t language_name;
37+
char *language;
38+
uint32_t nstrings;
39+
struct efi_string_info *strings;
40+
};
41+
42+
struct efi_hii_packagelist {
43+
struct list_node node;
44+
EfiHandle driver_handle;
45+
uint32_t max_string_id;
46+
struct list_node string_tables; /* list of efi_string_table */
47+
};
48+
49+
list_node efi_package_lists = LIST_INITIAL_VALUE(efi_package_lists);
50+
51+
static uint32_t efi_hii_package_type(const EfiHiiPackageHeader *header) {
52+
uint32_t fields;
53+
54+
fields = header->fields;
55+
56+
return (fields >> EFI_HII_PACKAGE_TYPE_SHIFT) & EFI_HII_PACKAGE_TYPE_MASK;
57+
}
58+
59+
static uint32_t efi_hii_package_len(const EfiHiiPackageHeader *header) {
60+
uint32_t fields;
61+
62+
fields = header->fields;
63+
64+
return (fields >> EFI_HII_PACKAGE_LEN_SHIFT) & EFI_HII_PACKAGE_LEN_MASK;
65+
}
66+
67+
struct efi_hii_packagelist *new_packagelist(void) {
68+
struct efi_hii_packagelist *hii;
69+
70+
hii = reinterpret_cast<struct efi_hii_packagelist *>(malloc(sizeof(struct efi_hii_packagelist)));
71+
if (!hii)
72+
return nullptr;
73+
memset(hii, 0, sizeof(struct efi_hii_packagelist));
74+
hii->node = LIST_INITIAL_CLEARED_VALUE;
75+
list_add_tail(&efi_package_lists, &hii->node);
76+
hii->string_tables = LIST_INITIAL_VALUE(hii->string_tables);
77+
78+
return hii;
79+
}
80+
81+
static void free_strings_table(struct efi_string_table *stbl) {
82+
for (uint32_t i = 0; i < stbl->nstrings; i++)
83+
free(stbl->strings[i].string);
84+
free(stbl->strings);
85+
free(stbl->language);
86+
free(stbl);
87+
}
88+
89+
static void remove_strings_package(struct efi_hii_packagelist *hii) {
90+
while (true) {
91+
struct efi_string_table *stbl;
92+
93+
stbl = reinterpret_cast<struct efi_string_table *>(list_remove_head(&(hii->string_tables)));
94+
if (!stbl) {
95+
break;
96+
}
97+
98+
free_strings_table(stbl);
99+
}
100+
}
101+
102+
static void free_packagelist(struct efi_hii_packagelist *hii) {
103+
remove_strings_package(hii);
104+
105+
list_delete(&hii->node);
106+
free(hii);
107+
}
108+
109+
EfiStatus add_packages(struct efi_hii_packagelist *hii,
110+
const struct EfiHiiPackageListHeader *package_list) {
111+
struct EfiHiiPackageHeader *package;
112+
void *end;
113+
EfiStatus ret = EFI_STATUS_SUCCESS;
114+
115+
end = ((char *)package_list) + package_list->package_length;
116+
117+
package = reinterpret_cast<struct EfiHiiPackageHeader *>(((char *)package_list) + sizeof(*package_list));
118+
while ((void *)package < end) {
119+
switch (efi_hii_package_type(package)) {
120+
case EFI_HII_PACKAGE_END:
121+
goto out;
122+
default:
123+
break;
124+
}
125+
126+
package = reinterpret_cast<struct EfiHiiPackageHeader *>((char *)package + efi_hii_package_len(package));
127+
}
128+
out:
129+
return ret;
130+
}
131+
132+
static bool efi_hii_packagelist_exists(EfiHiiHandle package_list) {
133+
struct efi_hii_packagelist *hii = nullptr;
134+
bool found = false;
135+
list_for_every_entry(&efi_package_lists, hii, struct efi_hii_packagelist, node) {
136+
if (hii == package_list) {
137+
found = true;
138+
break;
139+
}
140+
}
141+
142+
return found;
143+
}
144+
145+
EfiStatus new_package_list(EfiHiiDatabaseProtocol *self,
146+
const struct EfiHiiPackageListHeader *package_list,
147+
const EfiHandle driver_handle,
148+
EfiHiiHandle *handle) {
149+
struct efi_hii_packagelist *hii;
150+
EfiStatus ret;
151+
152+
if (!package_list || !handle)
153+
return EFI_STATUS_INVALID_PARAMETER;
154+
155+
hii = new_packagelist();
156+
if (!hii)
157+
return EFI_STATUS_OUT_OF_RESOURCES;
158+
159+
ret = add_packages(hii, package_list);
160+
if (ret != EFI_STATUS_SUCCESS) {
161+
free_packagelist(hii);
162+
return ret;
163+
}
164+
165+
hii->driver_handle = driver_handle;
166+
*handle = hii;
167+
168+
return EFI_STATUS_SUCCESS;
169+
}
170+
171+
EfiStatus remove_package_list(struct EfiHiiDatabaseProtocol *self,
172+
EfiHiiHandle handle) {
173+
struct efi_hii_packagelist *hii = reinterpret_cast<struct efi_hii_packagelist *>(handle);
174+
175+
if (!handle || !efi_hii_packagelist_exists(handle))
176+
return EFI_STATUS_NOT_FOUND;
177+
178+
free_packagelist(hii);
179+
180+
return EFI_STATUS_SUCCESS;
181+
}
182+
183+
EfiStatus update_package_list(struct EfiHiiDatabaseProtocol *self,
184+
EfiHiiHandle handle,
185+
const struct EfiHiiPackageListHeader *package_list) {
186+
printf("UEFI: Hii: update_package_list is not supported\n");
187+
return EFI_STATUS_UNSUPPORTED;
188+
}
189+
190+
EfiStatus list_package_lists(struct EfiHiiDatabaseProtocol *self,
191+
uint8_t package_type,
192+
const EfiGuid *package_guid,
193+
size_t *buffer_size,
194+
EfiHiiHandle *handle) {
195+
printf("UEFI: Hii: list_package_lists is not supported\n");
196+
return EFI_STATUS_UNSUPPORTED;
197+
}
198+
199+
EfiStatus export_package_lists(struct EfiHiiDatabaseProtocol *self,
200+
EfiHiiHandle handle,
201+
size_t *buffer_size,
202+
struct EfiHiiPackageListHeader *buffer) {
203+
printf("UEFI: Hii: export_package_lists is not supported\n");
204+
return EFI_STATUS_UNSUPPORTED;
205+
}
206+
207+
EfiStatus register_package_notify(struct EfiHiiDatabaseProtocol *self,
208+
uint8_t package_type,
209+
const EfiGuid *package_guid,
210+
const void *package_notify_fn,
211+
size_t notify_type,
212+
EfiHandle *notify_handle) {
213+
printf("UEFI: Hii: register_package_notify is not supported\n");
214+
return EFI_STATUS_UNSUPPORTED;
215+
}
216+
217+
EfiStatus unregister_package_notify(struct EfiHiiDatabaseProtocol *self,
218+
EfiHandle notification_handle) {
219+
printf("UEFI: Hii: unregister_package_notify is not supported\n");
220+
return EFI_STATUS_UNSUPPORTED;
221+
}
222+
223+
EfiStatus find_keyboard_layouts(struct EfiHiiDatabaseProtocol *self,
224+
uint16_t *key_guid_buffer_length,
225+
EfiGuid *key_guid_buffer) {
226+
printf("UEFI: Hii: find_keyboard_layouts is not supported\n");
227+
return EFI_STATUS_UNSUPPORTED;
228+
}
229+
230+
EfiStatus get_keyboard_layout(struct EfiHiiDatabaseProtocol *self,
231+
EfiGuid *key_guid,
232+
uint16_t *keyboard_layout_length,
233+
struct EfiHiiKeyboardLayout *keyboard_layout) {
234+
printf("UEFI: Hii: get_keyboard_layout is not supported\n");
235+
return EFI_STATUS_UNSUPPORTED;
236+
}
237+
238+
EfiStatus set_keyboard_layout(struct EfiHiiDatabaseProtocol *self,
239+
EfiGuid *key_guid) {
240+
printf("UEFI: Hii: set_keyboard_layout is not supported");
241+
return EFI_STATUS_UNSUPPORTED;
242+
}
243+
244+
EfiStatus get_package_list_handle(struct EfiHiiDatabaseProtocol *self,
245+
EfiHiiHandle package_list_handle,
246+
EfiHandle *driver_handle) {
247+
printf("UEFI: Hii: get_package_list_handle is not supported\n");
248+
return EFI_STATUS_UNSUPPORTED;
249+
}
250+
251+
}
252+
253+
__WEAK EfiHiiDatabaseProtocol* open_hii_database_protocol() {
254+
static EfiHiiDatabaseProtocol protocol = {
255+
.new_package_list = new_package_list,
256+
.remove_package_list = remove_package_list,
257+
.update_package_list = update_package_list,
258+
.list_package_lists = list_package_lists,
259+
.export_package_lists = export_package_lists,
260+
.register_package_notify = register_package_notify,
261+
.unregister_package_notify = unregister_package_notify,
262+
.find_keyboard_layouts = find_keyboard_layouts,
263+
.get_keyboard_layout = get_keyboard_layout,
264+
.set_keyboard_layout = set_keyboard_layout,
265+
.get_package_list_handle = get_package_list_handle
266+
};
267+
return &protocol;
268+
}

0 commit comments

Comments
 (0)