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