1 /*
2 * Copyright (C) 2024 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 #include "boot_service_provider.h"
18
19 #include <lk/compiler.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <platform.h>
24 #include <sys/types.h>
25 #include <uefi/boot_service.h>
26 #include <uefi/protocols/block_io_protocol.h>
27 #include <uefi/protocols/dt_fixup_protocol.h>
28 #include <uefi/protocols/gbl_efi_image_loading_protocol.h>
29 #include <uefi/protocols/gbl_efi_os_configuration_protocol.h>
30 #include <uefi/protocols/loaded_image_protocol.h>
31 #include <uefi/types.h>
32
33 #include "blockio2_protocols.h"
34 #include "blockio_protocols.h"
35 #include "events.h"
36 #include "io_stack.h"
37 #include "memory_protocols.h"
38 #include "uefi_platform.h"
39
40 namespace {
41
unload(EfiHandle handle)42 EfiStatus unload(EfiHandle handle) { return SUCCESS; }
43
guid_eq(const EfiGuid * a,const EfiGuid * b)44 bool guid_eq(const EfiGuid *a, const EfiGuid *b) {
45 return memcmp(a, b, sizeof(*a)) == 0;
46 }
47
guid_eq(const EfiGuid * a,const EfiGuid & b)48 bool guid_eq(const EfiGuid *a, const EfiGuid &b) {
49 return memcmp(a, &b, sizeof(*a)) == 0;
50 }
51
handle_protocol(EfiHandle handle,const EfiGuid * protocol,void ** intf)52 EfiStatus handle_protocol(EfiHandle handle, const EfiGuid *protocol,
53 void **intf) {
54 if (guid_eq(protocol, LOADED_IMAGE_PROTOCOL_GUID)) {
55 printf("handle_protocol(%p, LOADED_IMAGE_PROTOCOL_GUID, %p);\n", handle,
56 intf);
57 const auto loaded_image = static_cast<EFI_LOADED_IMAGE_PROTOCOL *>(
58 uefi_malloc(sizeof(EFI_LOADED_IMAGE_PROTOCOL)));
59 *loaded_image = {};
60 loaded_image->Revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;
61 loaded_image->ParentHandle = nullptr;
62 loaded_image->SystemTable = nullptr;
63 loaded_image->LoadOptionsSize = 0;
64 loaded_image->LoadOptions = nullptr;
65 loaded_image->Unload = unload;
66 loaded_image->ImageBase = handle;
67
68 *intf = loaded_image;
69 return SUCCESS;
70 } else if (guid_eq(protocol, LINUX_EFI_LOADED_IMAGE_FIXED_GUID)) {
71 printf("handle_protocol(%p, LINUX_EFI_LOADED_IMAGE_FIXED_GUID, %p);\n",
72 handle, intf);
73 return SUCCESS;
74 } else {
75 printf("handle_protocol(%p, %p, %p);\n", handle, protocol, intf);
76 }
77 return UNSUPPORTED;
78 }
79
register_protocol_notify(const EfiGuid * protocol,EfiEvent event,void ** registration)80 EfiStatus register_protocol_notify(const EfiGuid *protocol, EfiEvent event,
81 void **registration) {
82 printf("%s is unsupported\n", __FUNCTION__);
83 return UNSUPPORTED;
84 }
85
locate_handle(EfiLocateHandleSearchType search_type,const EfiGuid * protocol,void * search_key,size_t * buf_size,EfiHandle * buf)86 EfiStatus locate_handle(EfiLocateHandleSearchType search_type,
87 const EfiGuid *protocol, void *search_key,
88 size_t *buf_size, EfiHandle *buf) {
89
90 printf("%s is unsupported\n", __FUNCTION__);
91 return UNSUPPORTED;
92 }
93
locate_protocol(const EfiGuid * protocol,void * registration,void ** intf)94 EfiStatus locate_protocol(const EfiGuid *protocol, void *registration,
95 void **intf) {
96 if (protocol == nullptr) {
97 return INVALID_PARAMETER;
98 }
99 if (memcmp(protocol, &EFI_RNG_PROTOCOL_GUID, sizeof(*protocol)) == 0) {
100 printf("%s(EFI_RNG_PROTOCOL_GUID) is unsupported.\n", __FUNCTION__);
101 return UNSUPPORTED;
102 }
103 if (memcmp(protocol, &EFI_TCG2_PROTOCOL_GUID, sizeof(*protocol)) == 0) {
104 printf("%s(EFI_TCG2_PROTOCOL_GUID) is unsupported.\n", __FUNCTION__);
105 return NOT_FOUND;
106 }
107
108 printf("%s(%x %x %x %llx) is unsupported\n", __FUNCTION__, protocol->data1,
109 protocol->data2, protocol->data3,
110 *reinterpret_cast<const uint64_t *>(&protocol->data4));
111 return UNSUPPORTED;
112 }
113
uninstall_multiple_protocol_interfaces(EfiHandle handle,...)114 EfiStatus uninstall_multiple_protocol_interfaces(EfiHandle handle, ...) {
115 printf("%s is unsupported\n", __FUNCTION__);
116 return UNSUPPORTED;
117 }
calculate_crc32(void * data,size_t len,uint32_t * crc32)118 EfiStatus calculate_crc32(void *data, size_t len, uint32_t *crc32) {
119 printf("%s is unsupported\n", __FUNCTION__);
120 return UNSUPPORTED;
121 }
122
uninstall_protocol_interface(EfiHandle handle,const EfiGuid * protocol,void * intf)123 EfiStatus uninstall_protocol_interface(EfiHandle handle,
124 const EfiGuid *protocol, void *intf) {
125 printf("%s is unsupported\n", __FUNCTION__);
126 return UNSUPPORTED;
127 }
128
load_image(bool boot_policy,EfiHandle parent_image_handle,EfiDevicePathProtocol * path,void * src,size_t src_size,EfiHandle * image_handle)129 EfiStatus load_image(bool boot_policy, EfiHandle parent_image_handle,
130 EfiDevicePathProtocol *path, void *src, size_t src_size,
131 EfiHandle *image_handle) {
132 printf("%s is unsupported\n", __FUNCTION__);
133 return UNSUPPORTED;
134 }
135
locate_device_path(const EfiGuid * protocol,EfiDevicePathProtocol ** path,EfiHandle * device)136 EfiStatus locate_device_path(const EfiGuid *protocol,
137 EfiDevicePathProtocol **path, EfiHandle *device) {
138 if (memcmp(protocol, &EFI_LOAD_FILE2_PROTOCOL_GUID,
139 sizeof(EFI_LOAD_FILE2_PROTOCOL_GUID)) == 0) {
140 return NOT_FOUND;
141 }
142 printf("%s is unsupported\n", __FUNCTION__);
143 return UNSUPPORTED;
144 }
145
install_configuration_table(const EfiGuid * guid,void * table)146 EfiStatus install_configuration_table(const EfiGuid *guid, void *table) {
147 printf("%s is unsupported\n", __FUNCTION__);
148 return UNSUPPORTED;
149 }
150
copy_mem(void * dest,const void * src,size_t len)151 void copy_mem(void *dest, const void *src, size_t len) {
152 memcpy(dest, src, len);
153 }
set_mem(void * buf,size_t len,uint8_t val)154 void set_mem(void *buf, size_t len, uint8_t val) { memset(buf, val, len); }
155
raise_tpl(EfiTpl new_tpl)156 EfiTpl raise_tpl(EfiTpl new_tpl) {
157 printf("%s is called %zu\n", __FUNCTION__, new_tpl);
158 return APPLICATION;
159 }
160
get_verify_partitions(struct GblEfiImageLoadingProtocol * self,size_t * NumberOfPartitions,GblEfiPartitionName * Partitions)161 EfiStatus get_verify_partitions(struct GblEfiImageLoadingProtocol *self,
162 size_t *NumberOfPartitions,
163 GblEfiPartitionName *Partitions) {
164 printf("%s is called\n", __FUNCTION__);
165 return UNSUPPORTED;
166 }
167
open_protocol(EfiHandle handle,const EfiGuid * protocol,void ** intf,EfiHandle agent_handle,EfiHandle controller_handle,EfiOpenProtocolAttributes attr)168 EfiStatus open_protocol(EfiHandle handle, const EfiGuid *protocol, void **intf,
169 EfiHandle agent_handle, EfiHandle controller_handle,
170 EfiOpenProtocolAttributes attr) {
171 if (guid_eq(protocol, LOADED_IMAGE_PROTOCOL_GUID)) {
172 auto interface = reinterpret_cast<EfiLoadedImageProtocol *>(
173 uefi_malloc(sizeof(EfiLoadedImageProtocol)));
174 memset(interface, 0, sizeof(*interface));
175 interface->parent_handle = handle;
176 interface->image_base = handle;
177 *intf = interface;
178 printf("%s(LOADED_IMAGE_PROTOCOL_GUID, handle=%p, agent_handle=%p, "
179 "controller_handle=%p, attr=0x%x)\n",
180 __FUNCTION__, handle, agent_handle, controller_handle, attr);
181 return SUCCESS;
182 } else if (guid_eq(protocol, EFI_DEVICE_PATH_PROTOCOL_GUID)) {
183 printf("%s(EFI_DEVICE_PATH_PROTOCOL_GUID, handle=%p, agent_handle=%p, "
184 "controller_handle=%p, attr=0x%x)\n",
185 __FUNCTION__, handle, agent_handle, controller_handle, attr);
186 return UNSUPPORTED;
187 } else if (guid_eq(protocol, EFI_BLOCK_IO_PROTOCOL_GUID)) {
188 printf("%s(EFI_BLOCK_IO_PROTOCOL_GUID, handle=%p, agent_handle=%p, "
189 "controller_handle=%p, attr=0x%x)\n",
190 __FUNCTION__, handle, agent_handle, controller_handle, attr);
191 return open_block_device(handle, intf);
192 } else if (guid_eq(protocol, EFI_BLOCK_IO2_PROTOCOL_GUID)) {
193 printf("%s(EFI_BLOCK_IO2_PROTOCOL_GUID, handle=%p, agent_handle=%p, "
194 "controller_handle=%p, attr=0x%x)\n",
195 __FUNCTION__, handle, agent_handle, controller_handle, attr);
196 return open_async_block_device(handle, intf);
197 } else if (guid_eq(protocol, EFI_DT_FIXUP_PROTOCOL_GUID)) {
198 printf("%s(EFI_DT_FIXUP_PROTOCOL_GUID, handle=%p, agent_handle=%p, "
199 "controller_handle=%p, attr=0x%x)\n",
200 __FUNCTION__, handle, agent_handle, controller_handle, attr);
201 if (intf != nullptr) {
202 EfiDtFixupProtocol *fixup = nullptr;
203 allocate_pool(BOOT_SERVICES_DATA, sizeof(EfiDtFixupProtocol),
204 reinterpret_cast<void **>(&fixup));
205 if (fixup == nullptr) {
206 return OUT_OF_RESOURCES;
207 }
208 fixup->revision = EFI_DT_FIXUP_PROTOCOL_REVISION;
209 fixup->fixup = efi_dt_fixup;
210 *intf = reinterpret_cast<void *>(fixup);
211 }
212 return SUCCESS;
213 } else if (guid_eq(protocol, EFI_GBL_OS_CONFIGURATION_PROTOCOL_GUID)) {
214 printf("%s(EFI_GBL_OS_CONFIGURATION_PROTOCOL_GUID, handle=%p, "
215 "agent_handle=%p, "
216 "controller_handle=%p, attr=0x%x)\n",
217 __FUNCTION__, handle, agent_handle, controller_handle, attr);
218 GblEfiOsConfigurationProtocol *config = nullptr;
219 allocate_pool(BOOT_SERVICES_DATA, sizeof(*config),
220 reinterpret_cast<void **>(&config));
221 if (config == nullptr) {
222 return OUT_OF_RESOURCES;
223 }
224 config->revision = GBL_EFI_OS_CONFIGURATION_PROTOCOL_REVISION;
225 config->fixup_bootconfig = fixup_bootconfig;
226 config->select_device_trees = select_device_trees;
227 *intf = reinterpret_cast<void *>(config);
228 return SUCCESS;
229 } else if (guid_eq(protocol, EFI_GBL_EFI_IMAGE_LOADING_PROTOCOL_GUID)) {
230 printf(
231 "%s(EFI_GBL_EFI_IMAGE_LOADING_PROTOCOL_GUID, handle=%p, "
232 "agent_handle%p, controller_handle=%p, attr=0x%x)\n",
233 __FUNCTION__, handle, agent_handle, controller_handle, attr);
234 GblEfiImageLoadingProtocol *image_loading = nullptr;
235 allocate_pool(BOOT_SERVICES_DATA, sizeof(*image_loading),
236 reinterpret_cast<void **>(&image_loading));
237 if (image_loading == nullptr) {
238 return OUT_OF_RESOURCES;
239 }
240 image_loading->revision = GBL_EFI_IMAGE_LOADING_PROTOCOL_REVISION;
241 image_loading->get_buffer = get_buffer;
242 image_loading->get_verify_partitions = get_verify_partitions;
243 *intf = reinterpret_cast<void *>(image_loading);
244 return SUCCESS;
245 } else if (guid_eq(protocol, EFI_TIMESTAMP_PROTOCOL_GUID)) {
246 printf("%s(EFI_TIMESTAMP_PROTOCOL_GUID, handle=%p, agent_handle=%p, "
247 "controller_handle=%p, attr=0x%x)\n",
248 __FUNCTION__, handle, agent_handle, controller_handle, attr);
249 EfiTimestampProtocol *ts = reinterpret_cast<EfiTimestampProtocol *>(
250 uefi_malloc(sizeof(EfiTimestampProtocol)));
251 if (ts == nullptr) {
252 return OUT_OF_RESOURCES;
253 }
254 ts->get_timestamp = get_timestamp;
255 ts->get_properties = get_timestamp_properties;
256 *intf = reinterpret_cast<void *>(ts);
257 return SUCCESS;
258 }
259 printf("%s is unsupported 0x%x 0x%x 0x%x 0x%llx\n", __FUNCTION__,
260 protocol->data1, protocol->data2, protocol->data3,
261 *(uint64_t *)&protocol->data4);
262 return UNSUPPORTED;
263 }
264
close_protocol(EfiHandle handle,const EfiGuid * protocol,EfiHandle agent_handle,EfiHandle controller_handle)265 EfiStatus close_protocol(EfiHandle handle, const EfiGuid *protocol,
266 EfiHandle agent_handle, EfiHandle controller_handle) {
267 if (guid_eq(protocol, LOADED_IMAGE_PROTOCOL_GUID)) {
268 printf("%s(LOADED_IMAGE_PROTOCOL_GUID, handle=%p, agent_handle=%p, "
269 "controller_handle=%p)\n",
270 __FUNCTION__, handle, agent_handle, controller_handle);
271 return SUCCESS;
272 } else if (guid_eq(protocol, EFI_DEVICE_PATH_PROTOCOL_GUID)) {
273 printf("%s(EFI_DEVICE_PATH_PROTOCOL_GUID, handle=%p, agent_handle=%p, "
274 "controller_handle=%p)\n",
275 __FUNCTION__, handle, agent_handle, controller_handle);
276 return SUCCESS;
277 } else if (guid_eq(protocol, EFI_BLOCK_IO_PROTOCOL_GUID)) {
278 printf("%s(EFI_BLOCK_IO_PROTOCOL_GUID, handle=%p, agent_handle=%p, "
279 "controller_handle=%p)\n",
280 __FUNCTION__, handle, agent_handle, controller_handle);
281 return SUCCESS;
282 } else if (guid_eq(protocol, EFI_DT_FIXUP_PROTOCOL_GUID)) {
283 printf("%s(EFI_DT_FIXUP_PROTOCOL_GUID, handle=%p, agent_handle=%p, "
284 "controller_handle=%p)\n",
285 __FUNCTION__, handle, agent_handle, controller_handle);
286 return SUCCESS;
287 }
288 printf("%s is called\n", __FUNCTION__);
289 return UNSUPPORTED;
290 }
291
locate_handle_buffer(EfiLocateHandleSearchType search_type,const EfiGuid * protocol,void * search_key,size_t * num_handles,EfiHandle ** buf)292 EfiStatus locate_handle_buffer(EfiLocateHandleSearchType search_type,
293 const EfiGuid *protocol, void *search_key,
294 size_t *num_handles, EfiHandle **buf) {
295 if (guid_eq(protocol, EFI_BLOCK_IO_PROTOCOL_GUID)) {
296 if (search_type == BY_PROTOCOL) {
297 return list_block_devices(num_handles, buf);
298 }
299 printf("%s(0x%x, EFI_BLOCK_IO_PROTOCOL_GUID, search_key=%p)\n",
300 __FUNCTION__, search_type, search_key);
301 return UNSUPPORTED;
302 } else if (guid_eq(protocol, EFI_TEXT_INPUT_PROTOCOL_GUID)) {
303 printf("%s(0x%x, EFI_TEXT_INPUT_PROTOCOL_GUID, search_key=%p)\n",
304 __FUNCTION__, search_type, search_key);
305 return NOT_FOUND;
306 } else if (guid_eq(protocol, EFI_GBL_OS_CONFIGURATION_PROTOCOL_GUID)) {
307 printf("%s(0x%x, EFI_GBL_OS_CONFIGURATION_PROTOCOL_GUID, search_key=%p)\n",
308 __FUNCTION__, search_type, search_key);
309 if (num_handles != nullptr) {
310 *num_handles = 1;
311 }
312 if (buf != nullptr) {
313 *buf = reinterpret_cast<EfiHandle *>(uefi_malloc(sizeof(buf)));
314 }
315 return SUCCESS;
316 } else if (guid_eq(protocol, EFI_DT_FIXUP_PROTOCOL_GUID)) {
317 printf("%s(0x%x, EFI_DT_FIXUP_PROTOCOL_GUID, search_key=%p)\n",
318 __FUNCTION__, search_type, search_key);
319 if (num_handles != nullptr) {
320 *num_handles = 1;
321 }
322 if (buf != nullptr) {
323 *buf = reinterpret_cast<EfiHandle *>(uefi_malloc(sizeof(buf)));
324 }
325 return SUCCESS;
326 } else if (guid_eq(protocol, EFI_TIMESTAMP_PROTOCOL_GUID)) {
327 printf("%s(0x%x, EFI_TIMESTAMP_PROTOCOL_GUID, search_key=%p)\n",
328 __FUNCTION__, search_type, search_key);
329 if (num_handles != nullptr) {
330 *num_handles = 1;
331 }
332 if (buf != nullptr) {
333 *buf = reinterpret_cast<EfiHandle *>(uefi_malloc(sizeof(buf)));
334 }
335 return SUCCESS;
336 }
337 printf("%s(0x%x, (0x%x 0x%x 0x%x 0x%llx), search_key=%p)\n", __FUNCTION__,
338 search_type, protocol->data1, protocol->data2, protocol->data3,
339 *(uint64_t *)&protocol->data4, search_key);
340 return UNSUPPORTED;
341 }
342
stall(size_t microseconds)343 EfiStatus stall(size_t microseconds) {
344 uint64_t end_microseconds;
345
346 end_microseconds = current_time_hires() + microseconds;
347 while (current_time_hires() < end_microseconds) {
348 thread_yield();
349 }
350
351 return SUCCESS;
352 }
353
free_pages(EfiPhysicalAddr memory,size_t pages)354 EfiStatus free_pages(EfiPhysicalAddr memory, size_t pages) {
355 return ::free_pages(reinterpret_cast<void *>(memory), pages);
356 }
357
358 } // namespace
359
setup_boot_service_table(EfiBootService * service)360 void setup_boot_service_table(EfiBootService *service) {
361 service->handle_protocol = handle_protocol;
362 service->allocate_pool = allocate_pool;
363 service->free_pool = free_pool;
364 service->get_memory_map = get_physical_memory_map;
365 service->register_protocol_notify = register_protocol_notify;
366 service->locate_handle = locate_handle;
367 service->locate_protocol = locate_protocol;
368 service->allocate_pages = allocate_pages;
369 service->free_pages = free_pages;
370 service->uninstall_multiple_protocol_interfaces =
371 uninstall_multiple_protocol_interfaces;
372 service->calculate_crc32 = calculate_crc32;
373 service->uninstall_protocol_interface = uninstall_protocol_interface;
374 service->load_image = load_image;
375 service->locate_device_path = locate_device_path;
376 service->install_configuration_table = install_configuration_table;
377 service->exit_boot_services = exit_boot_services;
378 service->copy_mem = copy_mem;
379 service->set_mem = set_mem;
380 service->open_protocol = open_protocol;
381 service->locate_handle_buffer = locate_handle_buffer;
382 service->close_protocol = close_protocol;
383 service->wait_for_event =
384 switch_stack_wrapper<size_t, EfiEvent *, size_t *, wait_for_event>();
385 service->signal_event = switch_stack_wrapper<EfiEvent, signal_event>();
386 service->check_event = switch_stack_wrapper<EfiEvent, check_event>();
387 service->create_event = create_event;
388 service->close_event = close_event;
389 service->stall = stall;
390 }
391