]> git.sur5r.net Git - u-boot/blob - lib/efi_loader/efi_boottime.c
efi_loader: Add console interface
[u-boot] / lib / efi_loader / efi_boottime.c
1 /*
2  *  EFI application boot time services
3  *
4  *  Copyright (c) 2016 Alexander Graf
5  *
6  *  SPDX-License-Identifier:     GPL-2.0+
7  */
8
9 /* #define DEBUG_EFI */
10
11 #include <common.h>
12 #include <efi_loader.h>
13 #include <malloc.h>
14 #include <asm/global_data.h>
15 #include <libfdt_env.h>
16 #include <u-boot/crc.h>
17 #include <bootm.h>
18 #include <inttypes.h>
19 #include <watchdog.h>
20
21 DECLARE_GLOBAL_DATA_PTR;
22
23 /* This list contains all the EFI objects our payload has access to */
24 LIST_HEAD(efi_obj_list);
25
26 /*
27  * If we're running on nasty systems (32bit ARM booting into non-EFI Linux)
28  * we need to do trickery with caches. Since we don't want to break the EFI
29  * aware boot path, only apply hacks when loading exiting directly (breaking
30  * direct Linux EFI booting along the way - oh well).
31  */
32 static bool efi_is_direct_boot = true;
33
34 /*
35  * EFI can pass arbitrary additional "tables" containing vendor specific
36  * information to the payload. One such table is the FDT table which contains
37  * a pointer to a flattened device tree blob.
38  *
39  * In most cases we want to pass an FDT to the payload, so reserve one slot of
40  * config table space for it. The pointer gets populated by do_bootefi_exec().
41  */
42 static struct efi_configuration_table efi_conf_table[1];
43
44 /*
45  * The "gd" pointer lives in a register on ARM and AArch64 that we declare
46  * fixed when compiling U-Boot. However, the payload does not know about that
47  * restriction so we need to manually swap its and our view of that register on
48  * EFI callback entry/exit.
49  */
50 static volatile void *efi_gd, *app_gd;
51
52 /* Called from do_bootefi_exec() */
53 void efi_save_gd(void)
54 {
55         efi_gd = gd;
56 }
57
58 /* Called on every callback entry */
59 void efi_restore_gd(void)
60 {
61         /* Only restore if we're already in EFI context */
62         if (!efi_gd)
63                 return;
64
65         if (gd != efi_gd)
66                 app_gd = gd;
67         gd = efi_gd;
68 }
69
70 /* Called on every callback exit */
71 efi_status_t efi_exit_func(efi_status_t ret)
72 {
73         gd = app_gd;
74         return ret;
75 }
76
77 static efi_status_t efi_unsupported(const char *funcname)
78 {
79 #ifdef DEBUG_EFI
80         printf("EFI: App called into unimplemented function %s\n", funcname);
81 #endif
82         return EFI_EXIT(EFI_UNSUPPORTED);
83 }
84
85 static int guidcmp(const efi_guid_t *g1, const efi_guid_t *g2)
86 {
87         return memcmp(g1, g2, sizeof(efi_guid_t));
88 }
89
90 static unsigned long EFIAPI efi_raise_tpl(unsigned long new_tpl)
91 {
92         EFI_ENTRY("0x%lx", new_tpl);
93         return EFI_EXIT(0);
94 }
95
96 static void EFIAPI efi_restore_tpl(unsigned long old_tpl)
97 {
98         EFI_ENTRY("0x%lx", old_tpl);
99         EFI_EXIT(efi_unsupported(__func__));
100 }
101
102 efi_status_t EFIAPI efi_allocate_pages_ext(int type, int memory_type,
103                                            unsigned long pages,
104                                            uint64_t *memory)
105 {
106         efi_status_t r;
107
108         EFI_ENTRY("%d, %d, 0x%lx, %p", type, memory_type, pages, memory);
109         r = efi_allocate_pages(type, memory_type, pages, memory);
110         return EFI_EXIT(r);
111 }
112
113 efi_status_t EFIAPI efi_free_pages_ext(uint64_t memory, unsigned long pages)
114 {
115         efi_status_t r;
116
117         EFI_ENTRY("%"PRIx64", 0x%lx", memory, pages);
118         r = efi_free_pages(memory, pages);
119         return EFI_EXIT(r);
120 }
121
122 efi_status_t EFIAPI efi_get_memory_map_ext(unsigned long *memory_map_size,
123                                            struct efi_mem_desc *memory_map,
124                                            unsigned long *map_key,
125                                            unsigned long *descriptor_size,
126                                            uint32_t *descriptor_version)
127 {
128         efi_status_t r;
129
130         EFI_ENTRY("%p, %p, %p, %p, %p", memory_map_size, memory_map,
131                   map_key, descriptor_size, descriptor_version);
132         r = efi_get_memory_map(memory_map_size, memory_map, map_key,
133                                descriptor_size, descriptor_version);
134         return EFI_EXIT(r);
135 }
136
137 static efi_status_t EFIAPI efi_allocate_pool(int pool_type, unsigned long size,
138                                              void **buffer)
139 {
140         return efi_allocate_pages(0, pool_type, (size + 0xfff) >> 12, (void*)buffer);
141 }
142
143 static efi_status_t EFIAPI efi_free_pool(void *buffer)
144 {
145         return efi_free_pages((ulong)buffer, 0);
146 }
147
148 /*
149  * Our event capabilities are very limited. Only support a single
150  * event to exist, so we don't need to maintain lists.
151  */
152 static struct {
153         enum efi_event_type type;
154         u32 trigger_type;
155         u32 trigger_time;
156         u64 trigger_next;
157         unsigned long notify_tpl;
158         void (*notify_function) (void *event, void *context);
159         void *notify_context;
160 } efi_event = {
161         /* Disable timers on bootup */
162         .trigger_next = -1ULL,
163 };
164
165 static efi_status_t EFIAPI efi_create_event(
166                         enum efi_event_type type, ulong notify_tpl,
167                         void (*notify_function) (void *event, void *context),
168                         void *notify_context, void **event)
169 {
170         EFI_ENTRY("%d, 0x%lx, %p, %p", type, notify_tpl, notify_function,
171                   notify_context);
172         if (efi_event.notify_function) {
173                 /* We only support one event at a time */
174                 return EFI_EXIT(EFI_OUT_OF_RESOURCES);
175         }
176
177         efi_event.type = type;
178         efi_event.notify_tpl = notify_tpl;
179         efi_event.notify_function = notify_function;
180         efi_event.notify_context = notify_context;
181         *event = &efi_event;
182
183         return EFI_EXIT(EFI_SUCCESS);
184 }
185
186 /*
187  * Our timers have to work without interrupts, so we check whenever keyboard
188  * input or disk accesses happen if enough time elapsed for it to fire.
189  */
190 void efi_timer_check(void)
191 {
192         u64 now = timer_get_us();
193
194         if (now >= efi_event.trigger_next) {
195                 /* Triggering! */
196                 if (efi_event.trigger_type == EFI_TIMER_PERIODIC)
197                         efi_event.trigger_next += efi_event.trigger_time / 10;
198                 efi_event.notify_function(&efi_event, efi_event.notify_context);
199         }
200
201         WATCHDOG_RESET();
202 }
203
204 static efi_status_t EFIAPI efi_set_timer(void *event, int type,
205                                          uint64_t trigger_time)
206 {
207         /* We don't have 64bit division available everywhere, so limit timer
208          * distances to 32bit bits. */
209         u32 trigger32 = trigger_time;
210
211         EFI_ENTRY("%p, %d, %"PRIx64, event, type, trigger_time);
212
213         if (trigger32 < trigger_time) {
214                 printf("WARNING: Truncating timer from %"PRIx64" to %x\n",
215                        trigger_time, trigger32);
216         }
217
218         if (event != &efi_event) {
219                 /* We only support one event at a time */
220                 return EFI_EXIT(EFI_INVALID_PARAMETER);
221         }
222
223         switch (type) {
224         case EFI_TIMER_STOP:
225                 efi_event.trigger_next = -1ULL;
226                 break;
227         case EFI_TIMER_PERIODIC:
228         case EFI_TIMER_RELATIVE:
229                 efi_event.trigger_next = timer_get_us() + (trigger32 / 10);
230                 break;
231         default:
232                 return EFI_EXIT(EFI_INVALID_PARAMETER);
233         }
234         efi_event.trigger_type = type;
235         efi_event.trigger_time = trigger_time;
236
237         return EFI_EXIT(EFI_SUCCESS);
238 }
239
240 static efi_status_t EFIAPI efi_wait_for_event(unsigned long num_events,
241                                               void *event, unsigned long *index)
242 {
243         u64 now;
244
245         EFI_ENTRY("%ld, %p, %p", num_events, event, index);
246
247         now = timer_get_us();
248         while (now < efi_event.trigger_next) { }
249         efi_timer_check();
250
251         return EFI_EXIT(EFI_SUCCESS);
252 }
253
254 static efi_status_t EFIAPI efi_signal_event(void *event)
255 {
256         EFI_ENTRY("%p", event);
257         return EFI_EXIT(EFI_SUCCESS);
258 }
259
260 static efi_status_t EFIAPI efi_close_event(void *event)
261 {
262         EFI_ENTRY("%p", event);
263         efi_event.trigger_next = -1ULL;
264         return EFI_EXIT(EFI_SUCCESS);
265 }
266
267 static efi_status_t EFIAPI efi_check_event(void *event)
268 {
269         EFI_ENTRY("%p", event);
270         return EFI_EXIT(EFI_NOT_READY);
271 }
272
273 static efi_status_t EFIAPI efi_install_protocol_interface(void **handle,
274                         efi_guid_t *protocol, int protocol_interface_type,
275                         void *protocol_interface)
276 {
277         EFI_ENTRY("%p, %p, %d, %p", handle, protocol, protocol_interface_type,
278                   protocol_interface);
279         return EFI_EXIT(EFI_OUT_OF_RESOURCES);
280 }
281 static efi_status_t EFIAPI efi_reinstall_protocol_interface(void *handle,
282                         efi_guid_t *protocol, void *old_interface,
283                         void *new_interface)
284 {
285         EFI_ENTRY("%p, %p, %p, %p", handle, protocol, old_interface,
286                   new_interface);
287         return EFI_EXIT(EFI_ACCESS_DENIED);
288 }
289
290 static efi_status_t EFIAPI efi_uninstall_protocol_interface(void *handle,
291                         efi_guid_t *protocol, void *protocol_interface)
292 {
293         EFI_ENTRY("%p, %p, %p", handle, protocol, protocol_interface);
294         return EFI_EXIT(EFI_NOT_FOUND);
295 }
296
297 static efi_status_t EFIAPI efi_register_protocol_notify(efi_guid_t *protocol,
298                                                         void *event,
299                                                         void **registration)
300 {
301         EFI_ENTRY("%p, %p, %p", protocol, event, registration);
302         return EFI_EXIT(EFI_OUT_OF_RESOURCES);
303 }
304
305 static int efi_search(enum efi_locate_search_type search_type,
306                       efi_guid_t *protocol, void *search_key,
307                       struct efi_object *efiobj)
308 {
309         int i;
310
311         switch (search_type) {
312         case all_handles:
313                 return 0;
314         case by_register_notify:
315                 return -1;
316         case by_protocol:
317                 for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) {
318                         const efi_guid_t *guid = efiobj->protocols[i].guid;
319                         if (guid && !guidcmp(guid, protocol))
320                                 return 0;
321                 }
322                 return -1;
323         }
324
325         return -1;
326 }
327
328 static efi_status_t EFIAPI efi_locate_handle(
329                         enum efi_locate_search_type search_type,
330                         efi_guid_t *protocol, void *search_key,
331                         unsigned long *buffer_size, efi_handle_t *buffer)
332 {
333         struct list_head *lhandle;
334         unsigned long size = 0;
335
336         EFI_ENTRY("%d, %p, %p, %p, %p", search_type, protocol, search_key,
337                   buffer_size, buffer);
338
339         /* Count how much space we need */
340         list_for_each(lhandle, &efi_obj_list) {
341                 struct efi_object *efiobj;
342                 efiobj = list_entry(lhandle, struct efi_object, link);
343                 if (!efi_search(search_type, protocol, search_key, efiobj)) {
344                         size += sizeof(void*);
345                 }
346         }
347
348         if (*buffer_size < size) {
349                 *buffer_size = size;
350                 return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
351         }
352
353         /* Then fill the array */
354         list_for_each(lhandle, &efi_obj_list) {
355                 struct efi_object *efiobj;
356                 efiobj = list_entry(lhandle, struct efi_object, link);
357                 if (!efi_search(search_type, protocol, search_key, efiobj)) {
358                         *(buffer++) = efiobj->handle;
359                 }
360         }
361
362         *buffer_size = size;
363         return EFI_EXIT(EFI_SUCCESS);
364 }
365
366 static efi_status_t EFIAPI efi_locate_device_path(efi_guid_t *protocol,
367                         struct efi_device_path **device_path,
368                         efi_handle_t *device)
369 {
370         EFI_ENTRY("%p, %p, %p", protocol, device_path, device);
371         return EFI_EXIT(EFI_NOT_FOUND);
372 }
373
374 static efi_status_t EFIAPI efi_install_configuration_table(efi_guid_t *guid,
375                                                            void *table)
376 {
377         int i;
378
379         EFI_ENTRY("%p, %p", guid, table);
380
381         /* Check for guid override */
382         for (i = 0; i < systab.nr_tables; i++) {
383                 if (!guidcmp(guid, &efi_conf_table[i].guid)) {
384                         efi_conf_table[i].table = table;
385                         return EFI_EXIT(EFI_SUCCESS);
386                 }
387         }
388
389         /* No override, check for overflow */
390         if (i >= ARRAY_SIZE(efi_conf_table))
391                 return EFI_EXIT(EFI_OUT_OF_RESOURCES);
392
393         /* Add a new entry */
394         memcpy(&efi_conf_table[i].guid, guid, sizeof(*guid));
395         efi_conf_table[i].table = table;
396         systab.nr_tables = i;
397
398         return EFI_EXIT(EFI_SUCCESS);
399 }
400
401 static efi_status_t EFIAPI efi_load_image(bool boot_policy,
402                                           efi_handle_t parent_image,
403                                           struct efi_device_path *file_path,
404                                           void *source_buffer,
405                                           unsigned long source_size,
406                                           efi_handle_t *image_handle)
407 {
408         static struct efi_object loaded_image_info_obj = {
409                 .protocols = {
410                         {
411                                 .guid = &efi_guid_loaded_image,
412                                 .open = &efi_return_handle,
413                         },
414                 },
415         };
416         struct efi_loaded_image *info;
417         struct efi_object *obj;
418
419         EFI_ENTRY("%d, %p, %p, %p, %ld, %p", boot_policy, parent_image,
420                   file_path, source_buffer, source_size, image_handle);
421         info = malloc(sizeof(*info));
422         obj = malloc(sizeof(loaded_image_info_obj));
423         memset(info, 0, sizeof(*info));
424         memcpy(obj, &loaded_image_info_obj, sizeof(loaded_image_info_obj));
425         obj->handle = info;
426         info->file_path = file_path;
427         info->reserved = efi_load_pe(source_buffer, info);
428         if (!info->reserved) {
429                 free(info);
430                 free(obj);
431                 return EFI_EXIT(EFI_UNSUPPORTED);
432         }
433
434         *image_handle = info;
435         list_add_tail(&obj->link, &efi_obj_list);
436
437         return EFI_EXIT(EFI_SUCCESS);
438 }
439
440 static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
441                                            unsigned long *exit_data_size,
442                                            s16 **exit_data)
443 {
444         ulong (*entry)(void *image_handle, struct efi_system_table *st);
445         struct efi_loaded_image *info = image_handle;
446
447         EFI_ENTRY("%p, %p, %p", image_handle, exit_data_size, exit_data);
448         entry = info->reserved;
449
450         efi_is_direct_boot = false;
451
452         /* call the image! */
453         entry(image_handle, &systab);
454
455         /* Should usually never get here */
456         return EFI_EXIT(EFI_SUCCESS);
457 }
458
459 static efi_status_t EFIAPI efi_exit(void *image_handle, long exit_status,
460                                     unsigned long exit_data_size,
461                                     uint16_t *exit_data)
462 {
463         EFI_ENTRY("%p, %ld, %ld, %p", image_handle, exit_status,
464                   exit_data_size, exit_data);
465         return EFI_EXIT(efi_unsupported(__func__));
466 }
467
468 static struct efi_object *efi_search_obj(void *handle)
469 {
470         struct list_head *lhandle;
471
472         list_for_each(lhandle, &efi_obj_list) {
473                 struct efi_object *efiobj;
474                 efiobj = list_entry(lhandle, struct efi_object, link);
475                 if (efiobj->handle == handle)
476                         return efiobj;
477         }
478
479         return NULL;
480 }
481
482 static efi_status_t EFIAPI efi_unload_image(void *image_handle)
483 {
484         struct efi_object *efiobj;
485
486         EFI_ENTRY("%p", image_handle);
487         efiobj = efi_search_obj(image_handle);
488         if (efiobj)
489                 list_del(&efiobj->link);
490
491         return EFI_EXIT(EFI_SUCCESS);
492 }
493
494 static void efi_exit_caches(void)
495 {
496 #if defined(CONFIG_ARM) && !defined(CONFIG_ARM64)
497         /*
498          * Grub on 32bit ARM needs to have caches disabled before jumping into
499          * a zImage, but does not know of all cache layers. Give it a hand.
500          */
501         if (efi_is_direct_boot)
502                 cleanup_before_linux();
503 #endif
504 }
505
506 static efi_status_t EFIAPI efi_exit_boot_services(void *image_handle,
507                                                   unsigned long map_key)
508 {
509         EFI_ENTRY("%p, %ld", image_handle, map_key);
510
511         /* Fix up caches for EFI payloads if necessary */
512         efi_exit_caches();
513
514         /* This stops all lingering devices */
515         bootm_disable_interrupts();
516
517         /* Give the payload some time to boot */
518         WATCHDOG_RESET();
519
520         return EFI_EXIT(EFI_SUCCESS);
521 }
522
523 static efi_status_t EFIAPI efi_get_next_monotonic_count(uint64_t *count)
524 {
525         static uint64_t mono = 0;
526         EFI_ENTRY("%p", count);
527         *count = mono++;
528         return EFI_EXIT(EFI_SUCCESS);
529 }
530
531 static efi_status_t EFIAPI efi_stall(unsigned long microseconds)
532 {
533         EFI_ENTRY("%ld", microseconds);
534         udelay(microseconds);
535         return EFI_EXIT(EFI_SUCCESS);
536 }
537
538 static efi_status_t EFIAPI efi_set_watchdog_timer(unsigned long timeout,
539                                                   uint64_t watchdog_code,
540                                                   unsigned long data_size,
541                                                   uint16_t *watchdog_data)
542 {
543         EFI_ENTRY("%ld, 0x%"PRIx64", %ld, %p", timeout, watchdog_code,
544                   data_size, watchdog_data);
545         return EFI_EXIT(efi_unsupported(__func__));
546 }
547
548 static efi_status_t EFIAPI efi_connect_controller(
549                         efi_handle_t controller_handle,
550                         efi_handle_t *driver_image_handle,
551                         struct efi_device_path *remain_device_path,
552                         bool recursive)
553 {
554         EFI_ENTRY("%p, %p, %p, %d", controller_handle, driver_image_handle,
555                   remain_device_path, recursive);
556         return EFI_EXIT(EFI_NOT_FOUND);
557 }
558
559 static efi_status_t EFIAPI efi_disconnect_controller(void *controller_handle,
560                                                      void *driver_image_handle,
561                                                      void *child_handle)
562 {
563         EFI_ENTRY("%p, %p, %p", controller_handle, driver_image_handle,
564                   child_handle);
565         return EFI_EXIT(EFI_INVALID_PARAMETER);
566 }
567
568 static efi_status_t EFIAPI efi_close_protocol(void *handle,
569                                               efi_guid_t *protocol,
570                                               void *agent_handle,
571                                               void *controller_handle)
572 {
573         EFI_ENTRY("%p, %p, %p, %p", handle, protocol, agent_handle,
574                   controller_handle);
575         return EFI_EXIT(EFI_NOT_FOUND);
576 }
577
578 static efi_status_t EFIAPI efi_open_protocol_information(efi_handle_t handle,
579                         efi_guid_t *protocol,
580                         struct efi_open_protocol_info_entry **entry_buffer,
581                         unsigned long *entry_count)
582 {
583         EFI_ENTRY("%p, %p, %p, %p", handle, protocol, entry_buffer,
584                   entry_count);
585         return EFI_EXIT(EFI_NOT_FOUND);
586 }
587
588 static efi_status_t EFIAPI efi_protocols_per_handle(void *handle,
589                         efi_guid_t ***protocol_buffer,
590                         unsigned long *protocol_buffer_count)
591 {
592         EFI_ENTRY("%p, %p, %p", handle, protocol_buffer,
593                   protocol_buffer_count);
594         return EFI_EXIT(EFI_OUT_OF_RESOURCES);
595 }
596
597 static efi_status_t EFIAPI efi_locate_handle_buffer(
598                         enum efi_locate_search_type search_type,
599                         efi_guid_t *protocol, void *search_key,
600                         unsigned long *no_handles, efi_handle_t **buffer)
601 {
602         EFI_ENTRY("%d, %p, %p, %p, %p", search_type, protocol, search_key,
603                   no_handles, buffer);
604         return EFI_EXIT(EFI_NOT_FOUND);
605 }
606
607 static struct efi_class_map efi_class_maps[] = {
608         {
609                 .guid = &efi_guid_console_control,
610                 .interface = &efi_console_control
611         },
612 };
613
614 static efi_status_t EFIAPI efi_locate_protocol(efi_guid_t *protocol,
615                                                void *registration,
616                                                void **protocol_interface)
617 {
618         int i;
619
620         EFI_ENTRY("%p, %p, %p", protocol, registration, protocol_interface);
621         for (i = 0; i < ARRAY_SIZE(efi_class_maps); i++) {
622                 struct efi_class_map *curmap = &efi_class_maps[i];
623                 if (!guidcmp(protocol, curmap->guid)) {
624                         *protocol_interface = (void*)curmap->interface;
625                         return EFI_EXIT(EFI_SUCCESS);
626                 }
627         }
628
629         return EFI_EXIT(EFI_NOT_FOUND);
630 }
631
632 static efi_status_t EFIAPI efi_install_multiple_protocol_interfaces(
633                         void **handle, ...)
634 {
635         EFI_ENTRY("%p", handle);
636         return EFI_EXIT(EFI_OUT_OF_RESOURCES);
637 }
638
639 static efi_status_t EFIAPI efi_uninstall_multiple_protocol_interfaces(
640                         void *handle, ...)
641 {
642         EFI_ENTRY("%p", handle);
643         return EFI_EXIT(EFI_INVALID_PARAMETER);
644 }
645
646 static efi_status_t EFIAPI efi_calculate_crc32(void *data,
647                                                unsigned long data_size,
648                                                uint32_t *crc32_p)
649 {
650         EFI_ENTRY("%p, %ld", data, data_size);
651         *crc32_p = crc32(0, data, data_size);
652         return EFI_EXIT(EFI_SUCCESS);
653 }
654
655 static void EFIAPI efi_copy_mem(void *destination, void *source,
656                                 unsigned long length)
657 {
658         EFI_ENTRY("%p, %p, %ld", destination, source, length);
659         memcpy(destination, source, length);
660 }
661
662 static void EFIAPI efi_set_mem(void *buffer, unsigned long size, uint8_t value)
663 {
664         EFI_ENTRY("%p, %ld, 0x%x", buffer, size, value);
665         memset(buffer, value, size);
666 }
667
668 static efi_status_t EFIAPI efi_open_protocol(
669                         void *handle, efi_guid_t *protocol,
670                         void **protocol_interface, void *agent_handle,
671                         void *controller_handle, uint32_t attributes)
672 {
673         struct list_head *lhandle;
674         int i;
675         efi_status_t r = EFI_UNSUPPORTED;
676
677         EFI_ENTRY("%p, %p, %p, %p, %p, 0x%x", handle, protocol,
678                   protocol_interface, agent_handle, controller_handle,
679                   attributes);
680         list_for_each(lhandle, &efi_obj_list) {
681                 struct efi_object *efiobj;
682                 efiobj = list_entry(lhandle, struct efi_object, link);
683
684                 if (efiobj->handle != handle)
685                         continue;
686
687                 for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) {
688                         struct efi_handler *handler = &efiobj->protocols[i];
689                         const efi_guid_t *hprotocol = handler->guid;
690                         if (!hprotocol)
691                                 break;
692                         if (!guidcmp(hprotocol, protocol)) {
693                                 r = handler->open(handle, protocol,
694                                     protocol_interface, agent_handle,
695                                     controller_handle, attributes);
696                                 goto out;
697                         }
698                 }
699         }
700
701 out:
702         return EFI_EXIT(r);
703 }
704
705 static efi_status_t EFIAPI efi_handle_protocol(void *handle,
706                                                efi_guid_t *protocol,
707                                                void **protocol_interface)
708 {
709         EFI_ENTRY("%p, %p, %p", handle, protocol, protocol_interface);
710         return efi_open_protocol(handle, protocol, protocol_interface,
711                                  NULL, NULL, 0);
712 }
713
714 static const struct efi_boot_services efi_boot_services = {
715         .hdr = {
716                 .headersize = sizeof(struct efi_table_hdr),
717         },
718         .raise_tpl = efi_raise_tpl,
719         .restore_tpl = efi_restore_tpl,
720         .allocate_pages = efi_allocate_pages_ext,
721         .free_pages = efi_free_pages_ext,
722         .get_memory_map = efi_get_memory_map_ext,
723         .allocate_pool = efi_allocate_pool,
724         .free_pool = efi_free_pool,
725         .create_event = efi_create_event,
726         .set_timer = efi_set_timer,
727         .wait_for_event = efi_wait_for_event,
728         .signal_event = efi_signal_event,
729         .close_event = efi_close_event,
730         .check_event = efi_check_event,
731         .install_protocol_interface = efi_install_protocol_interface,
732         .reinstall_protocol_interface = efi_reinstall_protocol_interface,
733         .uninstall_protocol_interface = efi_uninstall_protocol_interface,
734         .handle_protocol = efi_handle_protocol,
735         .reserved = NULL,
736         .register_protocol_notify = efi_register_protocol_notify,
737         .locate_handle = efi_locate_handle,
738         .locate_device_path = efi_locate_device_path,
739         .install_configuration_table = efi_install_configuration_table,
740         .load_image = efi_load_image,
741         .start_image = efi_start_image,
742         .exit = (void*)efi_exit,
743         .unload_image = efi_unload_image,
744         .exit_boot_services = efi_exit_boot_services,
745         .get_next_monotonic_count = efi_get_next_monotonic_count,
746         .stall = efi_stall,
747         .set_watchdog_timer = efi_set_watchdog_timer,
748         .connect_controller = efi_connect_controller,
749         .disconnect_controller = efi_disconnect_controller,
750         .open_protocol = efi_open_protocol,
751         .close_protocol = efi_close_protocol,
752         .open_protocol_information = efi_open_protocol_information,
753         .protocols_per_handle = efi_protocols_per_handle,
754         .locate_handle_buffer = efi_locate_handle_buffer,
755         .locate_protocol = efi_locate_protocol,
756         .install_multiple_protocol_interfaces = efi_install_multiple_protocol_interfaces,
757         .uninstall_multiple_protocol_interfaces = efi_uninstall_multiple_protocol_interfaces,
758         .calculate_crc32 = efi_calculate_crc32,
759         .copy_mem = efi_copy_mem,
760         .set_mem = efi_set_mem,
761 };
762
763
764 static uint16_t firmware_vendor[] =
765         { 'D','a','s',' ','U','-','b','o','o','t',0 };
766
767 struct efi_system_table systab = {
768         .hdr = {
769                 .signature = EFI_SYSTEM_TABLE_SIGNATURE,
770                 .revision = 0x20005, /* 2.5 */
771                 .headersize = sizeof(struct efi_table_hdr),
772         },
773         .fw_vendor = (long)firmware_vendor,
774         .con_in = (void*)&efi_con_in,
775         .con_out = (void*)&efi_con_out,
776         .std_err = (void*)&efi_con_out,
777         .runtime = (void*)&efi_runtime_services,
778         .boottime = (void*)&efi_boot_services,
779         .nr_tables = 0,
780         .tables = (void*)efi_conf_table,
781 };