2 * EFI application boot time services
4 * Copyright (c) 2016 Alexander Graf
6 * SPDX-License-Identifier: GPL-2.0+
10 #include <efi_loader.h>
12 #include <asm/global_data.h>
13 #include <libfdt_env.h>
14 #include <u-boot/crc.h>
19 DECLARE_GLOBAL_DATA_PTR;
21 /* This list contains all the EFI objects our payload has access to */
22 LIST_HEAD(efi_obj_list);
25 * If we're running on nasty systems (32bit ARM booting into non-EFI Linux)
26 * we need to do trickery with caches. Since we don't want to break the EFI
27 * aware boot path, only apply hacks when loading exiting directly (breaking
28 * direct Linux EFI booting along the way - oh well).
30 static bool efi_is_direct_boot = true;
33 * EFI can pass arbitrary additional "tables" containing vendor specific
34 * information to the payload. One such table is the FDT table which contains
35 * a pointer to a flattened device tree blob.
37 * In most cases we want to pass an FDT to the payload, so reserve one slot of
38 * config table space for it. The pointer gets populated by do_bootefi_exec().
40 static struct efi_configuration_table __efi_runtime_data efi_conf_table[2];
44 * The "gd" pointer lives in a register on ARM and AArch64 that we declare
45 * fixed when compiling U-Boot. However, the payload does not know about that
46 * restriction so we need to manually swap its and our view of that register on
47 * EFI callback entry/exit.
49 static volatile void *efi_gd, *app_gd;
52 /* Called from do_bootefi_exec() */
53 void efi_save_gd(void)
60 /* Called on every callback entry */
61 void efi_restore_gd(void)
64 /* Only restore if we're already in EFI context */
74 /* Called on every callback exit */
75 efi_status_t efi_exit_func(efi_status_t ret)
84 static efi_status_t efi_unsupported(const char *funcname)
86 debug("EFI: App called into unimplemented function %s\n", funcname);
87 return EFI_EXIT(EFI_UNSUPPORTED);
90 static int guidcmp(const efi_guid_t *g1, const efi_guid_t *g2)
92 return memcmp(g1, g2, sizeof(efi_guid_t));
95 static unsigned long EFIAPI efi_raise_tpl(unsigned long new_tpl)
97 EFI_ENTRY("0x%lx", new_tpl);
101 static void EFIAPI efi_restore_tpl(unsigned long old_tpl)
103 EFI_ENTRY("0x%lx", old_tpl);
104 EFI_EXIT(efi_unsupported(__func__));
107 static efi_status_t EFIAPI efi_allocate_pages_ext(int type, int memory_type,
113 EFI_ENTRY("%d, %d, 0x%lx, %p", type, memory_type, pages, memory);
114 r = efi_allocate_pages(type, memory_type, pages, memory);
118 static efi_status_t EFIAPI efi_free_pages_ext(uint64_t memory,
123 EFI_ENTRY("%"PRIx64", 0x%lx", memory, pages);
124 r = efi_free_pages(memory, pages);
128 static efi_status_t EFIAPI efi_get_memory_map_ext(
129 unsigned long *memory_map_size,
130 struct efi_mem_desc *memory_map,
131 unsigned long *map_key,
132 unsigned long *descriptor_size,
133 uint32_t *descriptor_version)
137 EFI_ENTRY("%p, %p, %p, %p, %p", memory_map_size, memory_map,
138 map_key, descriptor_size, descriptor_version);
139 r = efi_get_memory_map(memory_map_size, memory_map, map_key,
140 descriptor_size, descriptor_version);
144 static efi_status_t EFIAPI efi_allocate_pool_ext(int pool_type,
150 EFI_ENTRY("%d, %ld, %p", pool_type, size, buffer);
151 r = efi_allocate_pool(pool_type, size, buffer);
155 static efi_status_t EFIAPI efi_free_pool_ext(void *buffer)
159 EFI_ENTRY("%p", buffer);
160 r = efi_free_pool(buffer);
165 * Our event capabilities are very limited. Only support a single
166 * event to exist, so we don't need to maintain lists.
168 static struct efi_event {
169 enum efi_event_type type;
173 unsigned long notify_tpl;
174 void (EFIAPI *notify_function) (struct efi_event *event,
176 void *notify_context;
178 /* Disable timers on bootup */
179 .trigger_next = -1ULL,
182 static efi_status_t EFIAPI efi_create_event(
183 enum efi_event_type type, ulong notify_tpl,
184 void (EFIAPI *notify_function) (
185 struct efi_event *event,
187 void *notify_context, struct efi_event **event)
189 EFI_ENTRY("%d, 0x%lx, %p, %p", type, notify_tpl, notify_function,
191 if (efi_event.notify_function) {
192 /* We only support one event at a time */
193 return EFI_EXIT(EFI_OUT_OF_RESOURCES);
197 return EFI_EXIT(EFI_INVALID_PARAMETER);
199 if ((type & EVT_NOTIFY_SIGNAL) && (type & EVT_NOTIFY_WAIT))
200 return EFI_EXIT(EFI_INVALID_PARAMETER);
202 if ((type & (EVT_NOTIFY_SIGNAL|EVT_NOTIFY_WAIT)) &&
203 notify_function == NULL)
204 return EFI_EXIT(EFI_INVALID_PARAMETER);
206 efi_event.type = type;
207 efi_event.notify_tpl = notify_tpl;
208 efi_event.notify_function = notify_function;
209 efi_event.notify_context = notify_context;
212 return EFI_EXIT(EFI_SUCCESS);
216 * Our timers have to work without interrupts, so we check whenever keyboard
217 * input or disk accesses happen if enough time elapsed for it to fire.
219 void efi_timer_check(void)
221 u64 now = timer_get_us();
223 if (now >= efi_event.trigger_next) {
225 if (efi_event.trigger_type == EFI_TIMER_PERIODIC)
226 efi_event.trigger_next += efi_event.trigger_time / 10;
227 if (efi_event.type & (EVT_NOTIFY_WAIT | EVT_NOTIFY_SIGNAL))
228 efi_event.notify_function(&efi_event,
229 efi_event.notify_context);
235 static efi_status_t EFIAPI efi_set_timer(struct efi_event *event, int type,
236 uint64_t trigger_time)
238 /* We don't have 64bit division available everywhere, so limit timer
239 * distances to 32bit bits. */
240 u32 trigger32 = trigger_time;
242 EFI_ENTRY("%p, %d, %"PRIx64, event, type, trigger_time);
244 if (trigger32 < trigger_time) {
245 printf("WARNING: Truncating timer from %"PRIx64" to %x\n",
246 trigger_time, trigger32);
249 if (event != &efi_event) {
250 /* We only support one event at a time */
251 return EFI_EXIT(EFI_INVALID_PARAMETER);
256 efi_event.trigger_next = -1ULL;
258 case EFI_TIMER_PERIODIC:
259 case EFI_TIMER_RELATIVE:
260 efi_event.trigger_next = timer_get_us() + (trigger32 / 10);
263 return EFI_EXIT(EFI_INVALID_PARAMETER);
265 efi_event.trigger_type = type;
266 efi_event.trigger_time = trigger_time;
268 return EFI_EXIT(EFI_SUCCESS);
271 static efi_status_t EFIAPI efi_wait_for_event(unsigned long num_events,
272 struct efi_event **event,
273 unsigned long *index)
277 EFI_ENTRY("%ld, %p, %p", num_events, event, index);
279 now = timer_get_us();
280 while (now < efi_event.trigger_next) { }
283 return EFI_EXIT(EFI_SUCCESS);
286 static efi_status_t EFIAPI efi_signal_event(struct efi_event *event)
288 EFI_ENTRY("%p", event);
289 return EFI_EXIT(EFI_SUCCESS);
292 static efi_status_t EFIAPI efi_close_event(struct efi_event *event)
294 EFI_ENTRY("%p", event);
295 efi_event.trigger_next = -1ULL;
296 return EFI_EXIT(EFI_SUCCESS);
299 static efi_status_t EFIAPI efi_check_event(struct efi_event *event)
301 EFI_ENTRY("%p", event);
302 return EFI_EXIT(EFI_NOT_READY);
305 static efi_status_t EFIAPI efi_install_protocol_interface(void **handle,
306 efi_guid_t *protocol, int protocol_interface_type,
307 void *protocol_interface)
309 struct list_head *lhandle;
313 if (!handle || !protocol ||
314 protocol_interface_type != EFI_NATIVE_INTERFACE) {
315 r = EFI_INVALID_PARAMETER;
319 /* Create new handle if requested. */
321 r = EFI_OUT_OF_RESOURCES;
325 list_for_each(lhandle, &efi_obj_list) {
326 struct efi_object *efiobj;
327 efiobj = list_entry(lhandle, struct efi_object, link);
329 if (efiobj->handle != *handle)
331 /* Check if protocol is already installed on the handle. */
332 for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) {
333 struct efi_handler *handler = &efiobj->protocols[i];
337 if (!guidcmp(handler->guid, protocol)) {
338 r = EFI_INVALID_PARAMETER;
342 /* Install protocol in first empty slot. */
343 for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) {
344 struct efi_handler *handler = &efiobj->protocols[i];
349 handler->guid = protocol;
350 handler->protocol_interface = protocol_interface;
354 r = EFI_OUT_OF_RESOURCES;
357 r = EFI_INVALID_PARAMETER;
362 static efi_status_t EFIAPI efi_install_protocol_interface_ext(void **handle,
363 efi_guid_t *protocol, int protocol_interface_type,
364 void *protocol_interface)
366 EFI_ENTRY("%p, %p, %d, %p", handle, protocol, protocol_interface_type,
369 return EFI_EXIT(efi_install_protocol_interface(handle, protocol,
370 protocol_interface_type,
371 protocol_interface));
374 static efi_status_t EFIAPI efi_reinstall_protocol_interface(void *handle,
375 efi_guid_t *protocol, void *old_interface,
378 EFI_ENTRY("%p, %p, %p, %p", handle, protocol, old_interface,
380 return EFI_EXIT(EFI_ACCESS_DENIED);
383 static efi_status_t EFIAPI efi_uninstall_protocol_interface(void *handle,
384 efi_guid_t *protocol, void *protocol_interface)
386 struct list_head *lhandle;
388 efi_status_t r = EFI_NOT_FOUND;
390 if (!handle || !protocol) {
391 r = EFI_INVALID_PARAMETER;
395 list_for_each(lhandle, &efi_obj_list) {
396 struct efi_object *efiobj;
397 efiobj = list_entry(lhandle, struct efi_object, link);
399 if (efiobj->handle != handle)
402 for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) {
403 struct efi_handler *handler = &efiobj->protocols[i];
404 const efi_guid_t *hprotocol = handler->guid;
408 if (!guidcmp(hprotocol, protocol)) {
409 if (handler->protocol_interface) {
410 r = EFI_ACCESS_DENIED;
424 static efi_status_t EFIAPI efi_uninstall_protocol_interface_ext(void *handle,
425 efi_guid_t *protocol, void *protocol_interface)
427 EFI_ENTRY("%p, %p, %p", handle, protocol, protocol_interface);
429 return EFI_EXIT(efi_uninstall_protocol_interface(handle, protocol,
430 protocol_interface));
433 static efi_status_t EFIAPI efi_register_protocol_notify(efi_guid_t *protocol,
434 struct efi_event *event,
437 EFI_ENTRY("%p, %p, %p", protocol, event, registration);
438 return EFI_EXIT(EFI_OUT_OF_RESOURCES);
441 static int efi_search(enum efi_locate_search_type search_type,
442 efi_guid_t *protocol, void *search_key,
443 struct efi_object *efiobj)
447 switch (search_type) {
450 case by_register_notify:
453 for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) {
454 const efi_guid_t *guid = efiobj->protocols[i].guid;
455 if (guid && !guidcmp(guid, protocol))
464 static efi_status_t EFIAPI efi_locate_handle(
465 enum efi_locate_search_type search_type,
466 efi_guid_t *protocol, void *search_key,
467 unsigned long *buffer_size, efi_handle_t *buffer)
469 struct list_head *lhandle;
470 unsigned long size = 0;
472 /* Count how much space we need */
473 list_for_each(lhandle, &efi_obj_list) {
474 struct efi_object *efiobj;
475 efiobj = list_entry(lhandle, struct efi_object, link);
476 if (!efi_search(search_type, protocol, search_key, efiobj)) {
477 size += sizeof(void*);
481 if (*buffer_size < size) {
483 return EFI_BUFFER_TOO_SMALL;
486 /* Then fill the array */
487 list_for_each(lhandle, &efi_obj_list) {
488 struct efi_object *efiobj;
489 efiobj = list_entry(lhandle, struct efi_object, link);
490 if (!efi_search(search_type, protocol, search_key, efiobj)) {
491 *(buffer++) = efiobj->handle;
499 static efi_status_t EFIAPI efi_locate_handle_ext(
500 enum efi_locate_search_type search_type,
501 efi_guid_t *protocol, void *search_key,
502 unsigned long *buffer_size, efi_handle_t *buffer)
504 EFI_ENTRY("%d, %p, %p, %p, %p", search_type, protocol, search_key,
505 buffer_size, buffer);
507 return EFI_EXIT(efi_locate_handle(search_type, protocol, search_key,
508 buffer_size, buffer));
511 static efi_status_t EFIAPI efi_locate_device_path(efi_guid_t *protocol,
512 struct efi_device_path **device_path,
513 efi_handle_t *device)
515 EFI_ENTRY("%p, %p, %p", protocol, device_path, device);
516 return EFI_EXIT(EFI_NOT_FOUND);
519 efi_status_t efi_install_configuration_table(const efi_guid_t *guid, void *table)
523 /* Check for guid override */
524 for (i = 0; i < systab.nr_tables; i++) {
525 if (!guidcmp(guid, &efi_conf_table[i].guid)) {
526 efi_conf_table[i].table = table;
531 /* No override, check for overflow */
532 if (i >= ARRAY_SIZE(efi_conf_table))
533 return EFI_OUT_OF_RESOURCES;
535 /* Add a new entry */
536 memcpy(&efi_conf_table[i].guid, guid, sizeof(*guid));
537 efi_conf_table[i].table = table;
538 systab.nr_tables = i + 1;
543 static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid,
546 EFI_ENTRY("%p, %p", guid, table);
547 return EFI_EXIT(efi_install_configuration_table(guid, table));
550 static efi_status_t EFIAPI efi_load_image(bool boot_policy,
551 efi_handle_t parent_image,
552 struct efi_device_path *file_path,
554 unsigned long source_size,
555 efi_handle_t *image_handle)
557 static struct efi_object loaded_image_info_obj = {
560 .guid = &efi_guid_loaded_image,
564 struct efi_loaded_image *info;
565 struct efi_object *obj;
567 EFI_ENTRY("%d, %p, %p, %p, %ld, %p", boot_policy, parent_image,
568 file_path, source_buffer, source_size, image_handle);
569 info = malloc(sizeof(*info));
570 loaded_image_info_obj.protocols[0].protocol_interface = info;
571 obj = malloc(sizeof(loaded_image_info_obj));
572 memset(info, 0, sizeof(*info));
573 memcpy(obj, &loaded_image_info_obj, sizeof(loaded_image_info_obj));
575 info->file_path = file_path;
576 info->reserved = efi_load_pe(source_buffer, info);
577 if (!info->reserved) {
580 return EFI_EXIT(EFI_UNSUPPORTED);
583 *image_handle = info;
584 list_add_tail(&obj->link, &efi_obj_list);
586 return EFI_EXIT(EFI_SUCCESS);
589 static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
590 unsigned long *exit_data_size,
593 ulong (*entry)(void *image_handle, struct efi_system_table *st);
594 struct efi_loaded_image *info = image_handle;
596 EFI_ENTRY("%p, %p, %p", image_handle, exit_data_size, exit_data);
597 entry = info->reserved;
599 efi_is_direct_boot = false;
601 /* call the image! */
602 if (setjmp(&info->exit_jmp)) {
603 /* We returned from the child image */
604 return EFI_EXIT(info->exit_status);
607 entry(image_handle, &systab);
609 /* Should usually never get here */
610 return EFI_EXIT(EFI_SUCCESS);
613 static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle,
614 efi_status_t exit_status, unsigned long exit_data_size,
617 struct efi_loaded_image *loaded_image_info = (void*)image_handle;
619 EFI_ENTRY("%p, %ld, %ld, %p", image_handle, exit_status,
620 exit_data_size, exit_data);
622 loaded_image_info->exit_status = exit_status;
623 longjmp(&loaded_image_info->exit_jmp, 1);
625 panic("EFI application exited");
628 static struct efi_object *efi_search_obj(void *handle)
630 struct list_head *lhandle;
632 list_for_each(lhandle, &efi_obj_list) {
633 struct efi_object *efiobj;
634 efiobj = list_entry(lhandle, struct efi_object, link);
635 if (efiobj->handle == handle)
642 static efi_status_t EFIAPI efi_unload_image(void *image_handle)
644 struct efi_object *efiobj;
646 EFI_ENTRY("%p", image_handle);
647 efiobj = efi_search_obj(image_handle);
649 list_del(&efiobj->link);
651 return EFI_EXIT(EFI_SUCCESS);
654 static void efi_exit_caches(void)
656 #if defined(CONFIG_ARM) && !defined(CONFIG_ARM64)
658 * Grub on 32bit ARM needs to have caches disabled before jumping into
659 * a zImage, but does not know of all cache layers. Give it a hand.
661 if (efi_is_direct_boot)
662 cleanup_before_linux();
666 static efi_status_t EFIAPI efi_exit_boot_services(void *image_handle,
667 unsigned long map_key)
669 EFI_ENTRY("%p, %ld", image_handle, map_key);
671 board_quiesce_devices();
673 /* Fix up caches for EFI payloads if necessary */
676 /* This stops all lingering devices */
677 bootm_disable_interrupts();
679 /* Give the payload some time to boot */
682 return EFI_EXIT(EFI_SUCCESS);
685 static efi_status_t EFIAPI efi_get_next_monotonic_count(uint64_t *count)
687 static uint64_t mono = 0;
688 EFI_ENTRY("%p", count);
690 return EFI_EXIT(EFI_SUCCESS);
693 static efi_status_t EFIAPI efi_stall(unsigned long microseconds)
695 EFI_ENTRY("%ld", microseconds);
696 udelay(microseconds);
697 return EFI_EXIT(EFI_SUCCESS);
700 static efi_status_t EFIAPI efi_set_watchdog_timer(unsigned long timeout,
701 uint64_t watchdog_code,
702 unsigned long data_size,
703 uint16_t *watchdog_data)
705 EFI_ENTRY("%ld, 0x%"PRIx64", %ld, %p", timeout, watchdog_code,
706 data_size, watchdog_data);
707 return EFI_EXIT(efi_unsupported(__func__));
710 static efi_status_t EFIAPI efi_connect_controller(
711 efi_handle_t controller_handle,
712 efi_handle_t *driver_image_handle,
713 struct efi_device_path *remain_device_path,
716 EFI_ENTRY("%p, %p, %p, %d", controller_handle, driver_image_handle,
717 remain_device_path, recursive);
718 return EFI_EXIT(EFI_NOT_FOUND);
721 static efi_status_t EFIAPI efi_disconnect_controller(void *controller_handle,
722 void *driver_image_handle,
725 EFI_ENTRY("%p, %p, %p", controller_handle, driver_image_handle,
727 return EFI_EXIT(EFI_INVALID_PARAMETER);
730 static efi_status_t EFIAPI efi_close_protocol(void *handle,
731 efi_guid_t *protocol,
733 void *controller_handle)
735 EFI_ENTRY("%p, %p, %p, %p", handle, protocol, agent_handle,
737 return EFI_EXIT(EFI_NOT_FOUND);
740 static efi_status_t EFIAPI efi_open_protocol_information(efi_handle_t handle,
741 efi_guid_t *protocol,
742 struct efi_open_protocol_info_entry **entry_buffer,
743 unsigned long *entry_count)
745 EFI_ENTRY("%p, %p, %p, %p", handle, protocol, entry_buffer,
747 return EFI_EXIT(EFI_NOT_FOUND);
750 static efi_status_t EFIAPI efi_protocols_per_handle(void *handle,
751 efi_guid_t ***protocol_buffer,
752 unsigned long *protocol_buffer_count)
754 EFI_ENTRY("%p, %p, %p", handle, protocol_buffer,
755 protocol_buffer_count);
756 return EFI_EXIT(EFI_OUT_OF_RESOURCES);
759 static efi_status_t EFIAPI efi_locate_handle_buffer(
760 enum efi_locate_search_type search_type,
761 efi_guid_t *protocol, void *search_key,
762 unsigned long *no_handles, efi_handle_t **buffer)
765 unsigned long buffer_size = 0;
767 EFI_ENTRY("%d, %p, %p, %p, %p", search_type, protocol, search_key,
770 if (!no_handles || !buffer) {
771 r = EFI_INVALID_PARAMETER;
776 r = efi_locate_handle(search_type, protocol, search_key, &buffer_size,
778 if (r != EFI_BUFFER_TOO_SMALL)
780 r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, buffer_size,
782 if (r != EFI_SUCCESS)
784 r = efi_locate_handle(search_type, protocol, search_key, &buffer_size,
786 if (r == EFI_SUCCESS)
787 *no_handles = buffer_size / sizeof(void *);
792 static efi_status_t EFIAPI efi_locate_protocol(efi_guid_t *protocol,
794 void **protocol_interface)
796 struct list_head *lhandle;
799 EFI_ENTRY("%p, %p, %p", protocol, registration, protocol_interface);
801 if (!protocol || !protocol_interface)
802 return EFI_EXIT(EFI_INVALID_PARAMETER);
804 list_for_each(lhandle, &efi_obj_list) {
805 struct efi_object *efiobj;
807 efiobj = list_entry(lhandle, struct efi_object, link);
808 for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) {
809 struct efi_handler *handler = &efiobj->protocols[i];
813 if (!guidcmp(handler->guid, protocol)) {
814 *protocol_interface =
815 handler->protocol_interface;
816 return EFI_EXIT(EFI_SUCCESS);
820 *protocol_interface = NULL;
822 return EFI_EXIT(EFI_NOT_FOUND);
825 static efi_status_t EFIAPI efi_install_multiple_protocol_interfaces(
828 EFI_ENTRY("%p", handle);
831 efi_guid_t *protocol;
832 void *protocol_interface;
833 efi_status_t r = EFI_SUCCESS;
837 return EFI_EXIT(EFI_INVALID_PARAMETER);
839 va_start(argptr, handle);
841 protocol = va_arg(argptr, efi_guid_t*);
844 protocol_interface = va_arg(argptr, void*);
845 r = efi_install_protocol_interface(handle, protocol,
846 EFI_NATIVE_INTERFACE,
848 if (r != EFI_SUCCESS)
853 if (r == EFI_SUCCESS)
856 /* If an error occured undo all changes. */
857 va_start(argptr, handle);
859 protocol = va_arg(argptr, efi_guid_t*);
860 protocol_interface = va_arg(argptr, void*);
861 efi_uninstall_protocol_interface(handle, protocol,
869 static efi_status_t EFIAPI efi_uninstall_multiple_protocol_interfaces(
872 EFI_ENTRY("%p", handle);
873 return EFI_EXIT(EFI_INVALID_PARAMETER);
876 static efi_status_t EFIAPI efi_calculate_crc32(void *data,
877 unsigned long data_size,
880 EFI_ENTRY("%p, %ld", data, data_size);
881 *crc32_p = crc32(0, data, data_size);
882 return EFI_EXIT(EFI_SUCCESS);
885 static void EFIAPI efi_copy_mem(void *destination, void *source,
886 unsigned long length)
888 EFI_ENTRY("%p, %p, %ld", destination, source, length);
889 memcpy(destination, source, length);
892 static void EFIAPI efi_set_mem(void *buffer, unsigned long size, uint8_t value)
894 EFI_ENTRY("%p, %ld, 0x%x", buffer, size, value);
895 memset(buffer, value, size);
898 static efi_status_t EFIAPI efi_open_protocol(
899 void *handle, efi_guid_t *protocol,
900 void **protocol_interface, void *agent_handle,
901 void *controller_handle, uint32_t attributes)
903 struct list_head *lhandle;
905 efi_status_t r = EFI_INVALID_PARAMETER;
907 EFI_ENTRY("%p, %p, %p, %p, %p, 0x%x", handle, protocol,
908 protocol_interface, agent_handle, controller_handle,
911 if (!handle || !protocol ||
912 (!protocol_interface && attributes !=
913 EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) {
917 switch (attributes) {
918 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL:
919 case EFI_OPEN_PROTOCOL_GET_PROTOCOL:
920 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL:
922 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER:
923 if (controller_handle == handle)
925 case EFI_OPEN_PROTOCOL_BY_DRIVER:
926 case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE:
927 if (controller_handle == NULL)
929 case EFI_OPEN_PROTOCOL_EXCLUSIVE:
930 if (agent_handle == NULL)
937 list_for_each(lhandle, &efi_obj_list) {
938 struct efi_object *efiobj;
939 efiobj = list_entry(lhandle, struct efi_object, link);
941 if (efiobj->handle != handle)
944 for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) {
945 struct efi_handler *handler = &efiobj->protocols[i];
946 const efi_guid_t *hprotocol = handler->guid;
949 if (!guidcmp(hprotocol, protocol)) {
951 EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {
952 *protocol_interface =
953 handler->protocol_interface;
968 static efi_status_t EFIAPI efi_handle_protocol(void *handle,
969 efi_guid_t *protocol,
970 void **protocol_interface)
972 return efi_open_protocol(handle, protocol, protocol_interface, NULL,
973 NULL, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL);
976 static const struct efi_boot_services efi_boot_services = {
978 .headersize = sizeof(struct efi_table_hdr),
980 .raise_tpl = efi_raise_tpl,
981 .restore_tpl = efi_restore_tpl,
982 .allocate_pages = efi_allocate_pages_ext,
983 .free_pages = efi_free_pages_ext,
984 .get_memory_map = efi_get_memory_map_ext,
985 .allocate_pool = efi_allocate_pool_ext,
986 .free_pool = efi_free_pool_ext,
987 .create_event = efi_create_event,
988 .set_timer = efi_set_timer,
989 .wait_for_event = efi_wait_for_event,
990 .signal_event = efi_signal_event,
991 .close_event = efi_close_event,
992 .check_event = efi_check_event,
993 .install_protocol_interface = efi_install_protocol_interface_ext,
994 .reinstall_protocol_interface = efi_reinstall_protocol_interface,
995 .uninstall_protocol_interface = efi_uninstall_protocol_interface_ext,
996 .handle_protocol = efi_handle_protocol,
998 .register_protocol_notify = efi_register_protocol_notify,
999 .locate_handle = efi_locate_handle_ext,
1000 .locate_device_path = efi_locate_device_path,
1001 .install_configuration_table = efi_install_configuration_table_ext,
1002 .load_image = efi_load_image,
1003 .start_image = efi_start_image,
1005 .unload_image = efi_unload_image,
1006 .exit_boot_services = efi_exit_boot_services,
1007 .get_next_monotonic_count = efi_get_next_monotonic_count,
1009 .set_watchdog_timer = efi_set_watchdog_timer,
1010 .connect_controller = efi_connect_controller,
1011 .disconnect_controller = efi_disconnect_controller,
1012 .open_protocol = efi_open_protocol,
1013 .close_protocol = efi_close_protocol,
1014 .open_protocol_information = efi_open_protocol_information,
1015 .protocols_per_handle = efi_protocols_per_handle,
1016 .locate_handle_buffer = efi_locate_handle_buffer,
1017 .locate_protocol = efi_locate_protocol,
1018 .install_multiple_protocol_interfaces = efi_install_multiple_protocol_interfaces,
1019 .uninstall_multiple_protocol_interfaces = efi_uninstall_multiple_protocol_interfaces,
1020 .calculate_crc32 = efi_calculate_crc32,
1021 .copy_mem = efi_copy_mem,
1022 .set_mem = efi_set_mem,
1026 static uint16_t __efi_runtime_data firmware_vendor[] =
1027 { 'D','a','s',' ','U','-','b','o','o','t',0 };
1029 struct efi_system_table __efi_runtime_data systab = {
1031 .signature = EFI_SYSTEM_TABLE_SIGNATURE,
1032 .revision = 0x20005, /* 2.5 */
1033 .headersize = sizeof(struct efi_table_hdr),
1035 .fw_vendor = (long)firmware_vendor,
1036 .con_in = (void*)&efi_con_in,
1037 .con_out = (void*)&efi_con_out,
1038 .std_err = (void*)&efi_con_out,
1039 .runtime = (void*)&efi_runtime_services,
1040 .boottime = (void*)&efi_boot_services,
1042 .tables = (void*)efi_conf_table,