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