uboot/lib/efi_loader/efi_runtime.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 *  EFI application runtime services
   4 *
   5 *  Copyright (c) 2016 Alexander Graf
   6 */
   7
   8#include <common.h>
   9#include <command.h>
  10#include <cpu_func.h>
  11#include <dm.h>
  12#include <elf.h>
  13#include <efi_loader.h>
  14#include <log.h>
  15#include <malloc.h>
  16#include <rtc.h>
  17#include <asm/global_data.h>
  18#include <u-boot/crc.h>
  19
  20/* For manual relocation support */
  21DECLARE_GLOBAL_DATA_PTR;
  22
  23/* GUID of the runtime properties table */
  24static const efi_guid_t efi_rt_properties_table_guid =
  25                                EFI_RT_PROPERTIES_TABLE_GUID;
  26
  27struct efi_runtime_mmio_list {
  28        struct list_head link;
  29        void **ptr;
  30        u64 paddr;
  31        u64 len;
  32};
  33
  34/* This list contains all runtime available mmio regions */
  35LIST_HEAD(efi_runtime_mmio);
  36
  37static efi_status_t __efi_runtime EFIAPI efi_unimplemented(void);
  38
  39/*
  40 * TODO(sjg@chromium.org): These defines and structures should come from the ELF
  41 * header for each architecture (or a generic header) rather than being repeated
  42 * here.
  43 */
  44#if defined(__aarch64__)
  45#define R_RELATIVE      R_AARCH64_RELATIVE
  46#define R_MASK          0xffffffffULL
  47#define IS_RELA         1
  48#elif defined(__arm__)
  49#define R_RELATIVE      R_ARM_RELATIVE
  50#define R_MASK          0xffULL
  51#elif defined(__i386__)
  52#define R_RELATIVE      R_386_RELATIVE
  53#define R_MASK          0xffULL
  54#elif defined(__x86_64__)
  55#define R_RELATIVE      R_X86_64_RELATIVE
  56#define R_MASK          0xffffffffULL
  57#define IS_RELA         1
  58#elif defined(__riscv)
  59#define R_RELATIVE      R_RISCV_RELATIVE
  60#define R_MASK          0xffULL
  61#define IS_RELA         1
  62
  63struct dyn_sym {
  64        ulong foo1;
  65        ulong addr;
  66        u32 foo2;
  67        u32 foo3;
  68};
  69#if (__riscv_xlen == 32)
  70#define R_ABSOLUTE      R_RISCV_32
  71#define SYM_INDEX       8
  72#elif (__riscv_xlen == 64)
  73#define R_ABSOLUTE      R_RISCV_64
  74#define SYM_INDEX       32
  75#else
  76#error unknown riscv target
  77#endif
  78#else
  79#error Need to add relocation awareness
  80#endif
  81
  82struct elf_rel {
  83        ulong *offset;
  84        ulong info;
  85};
  86
  87struct elf_rela {
  88        ulong *offset;
  89        ulong info;
  90        long addend;
  91};
  92
  93static __efi_runtime_data struct efi_mem_desc *efi_virtmap;
  94static __efi_runtime_data efi_uintn_t efi_descriptor_count;
  95static __efi_runtime_data efi_uintn_t efi_descriptor_size;
  96
  97/*
  98 * EFI runtime code lives in two stages. In the first stage, U-Boot and an EFI
  99 * payload are running concurrently at the same time. In this mode, we can
 100 * handle a good number of runtime callbacks
 101 */
 102
 103/**
 104 * efi_init_runtime_supported() - create runtime properties table
 105 *
 106 * Create a configuration table specifying which services are available at
 107 * runtime.
 108 *
 109 * Return:      status code
 110 */
 111efi_status_t efi_init_runtime_supported(void)
 112{
 113        efi_status_t ret;
 114        struct efi_rt_properties_table *rt_table;
 115
 116        ret = efi_allocate_pool(EFI_RUNTIME_SERVICES_DATA,
 117                                sizeof(struct efi_rt_properties_table),
 118                                (void **)&rt_table);
 119        if (ret != EFI_SUCCESS)
 120                return ret;
 121
 122        rt_table->version = EFI_RT_PROPERTIES_TABLE_VERSION;
 123        rt_table->length = sizeof(struct efi_rt_properties_table);
 124        rt_table->runtime_services_supported =
 125                                EFI_RT_SUPPORTED_GET_VARIABLE |
 126                                EFI_RT_SUPPORTED_GET_NEXT_VARIABLE_NAME |
 127                                EFI_RT_SUPPORTED_SET_VIRTUAL_ADDRESS_MAP |
 128                                EFI_RT_SUPPORTED_CONVERT_POINTER;
 129
 130        /*
 131         * This value must be synced with efi_runtime_detach_list
 132         * as well as efi_runtime_services.
 133         */
 134#ifdef CONFIG_EFI_HAVE_RUNTIME_RESET
 135        rt_table->runtime_services_supported |= EFI_RT_SUPPORTED_RESET_SYSTEM;
 136#endif
 137
 138        ret = efi_install_configuration_table(&efi_rt_properties_table_guid,
 139                                              rt_table);
 140        return ret;
 141}
 142
 143/**
 144 * efi_memcpy_runtime() - copy memory area
 145 *
 146 * At runtime memcpy() is not available.
 147 *
 148 * Overlapping memory areas can be copied safely if src >= dest.
 149 *
 150 * @dest:       destination buffer
 151 * @src:        source buffer
 152 * @n:          number of bytes to copy
 153 * Return:      pointer to destination buffer
 154 */
 155void __efi_runtime efi_memcpy_runtime(void *dest, const void *src, size_t n)
 156{
 157        u8 *d = dest;
 158        const u8 *s = src;
 159
 160        for (; n; --n)
 161                *d++ = *s++;
 162}
 163
 164/**
 165 * efi_update_table_header_crc32() - Update crc32 in table header
 166 *
 167 * @table:      EFI table
 168 */
 169void __efi_runtime efi_update_table_header_crc32(struct efi_table_hdr *table)
 170{
 171        table->crc32 = 0;
 172        table->crc32 = crc32(0, (const unsigned char *)table,
 173                             table->headersize);
 174}
 175
 176/**
 177 * efi_reset_system_boottime() - reset system at boot time
 178 *
 179 * This function implements the ResetSystem() runtime service before
 180 * SetVirtualAddressMap() is called.
 181 *
 182 * See the Unified Extensible Firmware Interface (UEFI) specification for
 183 * details.
 184 *
 185 * @reset_type:         type of reset to perform
 186 * @reset_status:       status code for the reset
 187 * @data_size:          size of reset_data
 188 * @reset_data:         information about the reset
 189 */
 190static void EFIAPI efi_reset_system_boottime(
 191                        enum efi_reset_type reset_type,
 192                        efi_status_t reset_status,
 193                        unsigned long data_size, void *reset_data)
 194{
 195        struct efi_event *evt;
 196
 197        EFI_ENTRY("%d %lx %lx %p", reset_type, reset_status, data_size,
 198                  reset_data);
 199
 200        /* Notify reset */
 201        list_for_each_entry(evt, &efi_events, link) {
 202                if (evt->group &&
 203                    !guidcmp(evt->group,
 204                             &efi_guid_event_group_reset_system)) {
 205                        efi_signal_event(evt);
 206                        break;
 207                }
 208        }
 209        switch (reset_type) {
 210        case EFI_RESET_COLD:
 211        case EFI_RESET_WARM:
 212        case EFI_RESET_PLATFORM_SPECIFIC:
 213                do_reset(NULL, 0, 0, NULL);
 214                break;
 215        case EFI_RESET_SHUTDOWN:
 216#ifdef CONFIG_CMD_POWEROFF
 217                do_poweroff(NULL, 0, 0, NULL);
 218#endif
 219                break;
 220        }
 221
 222        while (1) { }
 223}
 224
 225/**
 226 * efi_get_time_boottime() - get current time at boot time
 227 *
 228 * This function implements the GetTime runtime service before
 229 * SetVirtualAddressMap() is called.
 230 *
 231 * See the Unified Extensible Firmware Interface (UEFI) specification
 232 * for details.
 233 *
 234 * @time:               pointer to structure to receive current time
 235 * @capabilities:       pointer to structure to receive RTC properties
 236 * Returns:             status code
 237 */
 238static efi_status_t EFIAPI efi_get_time_boottime(
 239                        struct efi_time *time,
 240                        struct efi_time_cap *capabilities)
 241{
 242#ifdef CONFIG_EFI_GET_TIME
 243        efi_status_t ret = EFI_SUCCESS;
 244        struct rtc_time tm;
 245        struct udevice *dev;
 246
 247        EFI_ENTRY("%p %p", time, capabilities);
 248
 249        if (!time) {
 250                ret = EFI_INVALID_PARAMETER;
 251                goto out;
 252        }
 253        if (uclass_get_device(UCLASS_RTC, 0, &dev) ||
 254            dm_rtc_get(dev, &tm)) {
 255                ret = EFI_UNSUPPORTED;
 256                goto out;
 257        }
 258        if (dm_rtc_get(dev, &tm)) {
 259                ret = EFI_DEVICE_ERROR;
 260                goto out;
 261        }
 262
 263        memset(time, 0, sizeof(*time));
 264        time->year = tm.tm_year;
 265        time->month = tm.tm_mon;
 266        time->day = tm.tm_mday;
 267        time->hour = tm.tm_hour;
 268        time->minute = tm.tm_min;
 269        time->second = tm.tm_sec;
 270        if (tm.tm_isdst > 0)
 271                time->daylight =
 272                        EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT;
 273        else if (!tm.tm_isdst)
 274                time->daylight = EFI_TIME_ADJUST_DAYLIGHT;
 275        else
 276                time->daylight = 0;
 277        time->timezone = EFI_UNSPECIFIED_TIMEZONE;
 278
 279        if (capabilities) {
 280                /* Set reasonable dummy values */
 281                capabilities->resolution = 1;           /* 1 Hz */
 282                capabilities->accuracy = 100000000;     /* 100 ppm */
 283                capabilities->sets_to_zero = false;
 284        }
 285out:
 286        return EFI_EXIT(ret);
 287#else
 288        EFI_ENTRY("%p %p", time, capabilities);
 289        return EFI_EXIT(EFI_UNSUPPORTED);
 290#endif
 291}
 292
 293#ifdef CONFIG_EFI_SET_TIME
 294
 295/**
 296 * efi_validate_time() - checks if timestamp is valid
 297 *
 298 * @time:       timestamp to validate
 299 * Returns:     0 if timestamp is valid, 1 otherwise
 300 */
 301static int efi_validate_time(struct efi_time *time)
 302{
 303        return (!time ||
 304                time->year < 1900 || time->year > 9999 ||
 305                !time->month || time->month > 12 || !time->day ||
 306                time->day > rtc_month_days(time->month - 1, time->year) ||
 307                time->hour > 23 || time->minute > 59 || time->second > 59 ||
 308                time->nanosecond > 999999999 ||
 309                time->daylight &
 310                ~(EFI_TIME_IN_DAYLIGHT | EFI_TIME_ADJUST_DAYLIGHT) ||
 311                ((time->timezone < -1440 || time->timezone > 1440) &&
 312                time->timezone != EFI_UNSPECIFIED_TIMEZONE));
 313}
 314
 315#endif
 316
 317/**
 318 * efi_set_time_boottime() - set current time
 319 *
 320 * This function implements the SetTime() runtime service before
 321 * SetVirtualAddressMap() is called.
 322 *
 323 * See the Unified Extensible Firmware Interface (UEFI) specification
 324 * for details.
 325 *
 326 * @time:               pointer to structure to with current time
 327 * Returns:             status code
 328 */
 329static efi_status_t EFIAPI efi_set_time_boottime(struct efi_time *time)
 330{
 331#ifdef CONFIG_EFI_SET_TIME
 332        efi_status_t ret = EFI_SUCCESS;
 333        struct rtc_time tm;
 334        struct udevice *dev;
 335
 336        EFI_ENTRY("%p", time);
 337
 338        if (efi_validate_time(time)) {
 339                ret = EFI_INVALID_PARAMETER;
 340                goto out;
 341        }
 342
 343        if (uclass_get_device(UCLASS_RTC, 0, &dev)) {
 344                ret = EFI_UNSUPPORTED;
 345                goto out;
 346        }
 347
 348        memset(&tm, 0, sizeof(tm));
 349        tm.tm_year = time->year;
 350        tm.tm_mon = time->month;
 351        tm.tm_mday = time->day;
 352        tm.tm_hour = time->hour;
 353        tm.tm_min = time->minute;
 354        tm.tm_sec = time->second;
 355        switch (time->daylight) {
 356        case EFI_TIME_ADJUST_DAYLIGHT:
 357                tm.tm_isdst = 0;
 358                break;
 359        case EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT:
 360                tm.tm_isdst = 1;
 361                break;
 362        default:
 363                tm.tm_isdst = -1;
 364                break;
 365        }
 366        /* Calculate day of week */
 367        rtc_calc_weekday(&tm);
 368
 369        if (dm_rtc_set(dev, &tm))
 370                ret = EFI_DEVICE_ERROR;
 371out:
 372        return EFI_EXIT(ret);
 373#else
 374        EFI_ENTRY("%p", time);
 375        return EFI_EXIT(EFI_UNSUPPORTED);
 376#endif
 377}
 378/**
 379 * efi_reset_system() - reset system
 380 *
 381 * This function implements the ResetSystem() runtime service after
 382 * SetVirtualAddressMap() is called. As this placeholder cannot reset the
 383 * system it simply return to the caller.
 384 *
 385 * Boards may override the helpers below to implement reset functionality.
 386 *
 387 * See the Unified Extensible Firmware Interface (UEFI) specification for
 388 * details.
 389 *
 390 * @reset_type:         type of reset to perform
 391 * @reset_status:       status code for the reset
 392 * @data_size:          size of reset_data
 393 * @reset_data:         information about the reset
 394 */
 395void __weak __efi_runtime EFIAPI efi_reset_system(
 396                        enum efi_reset_type reset_type,
 397                        efi_status_t reset_status,
 398                        unsigned long data_size, void *reset_data)
 399{
 400        return;
 401}
 402
 403/**
 404 * efi_reset_system_init() - initialize the reset driver
 405 *
 406 * Boards may override this function to initialize the reset driver.
 407 */
 408efi_status_t __weak efi_reset_system_init(void)
 409{
 410        return EFI_SUCCESS;
 411}
 412
 413/**
 414 * efi_get_time() - get current time
 415 *
 416 * This function implements the GetTime runtime service after
 417 * SetVirtualAddressMap() is called. As the U-Boot driver are not available
 418 * anymore only an error code is returned.
 419 *
 420 * See the Unified Extensible Firmware Interface (UEFI) specification
 421 * for details.
 422 *
 423 * @time:               pointer to structure to receive current time
 424 * @capabilities:       pointer to structure to receive RTC properties
 425 * Returns:             status code
 426 */
 427efi_status_t __weak __efi_runtime EFIAPI efi_get_time(
 428                        struct efi_time *time,
 429                        struct efi_time_cap *capabilities)
 430{
 431        return EFI_UNSUPPORTED;
 432}
 433
 434/**
 435 * efi_set_time() - set current time
 436 *
 437 * This function implements the SetTime runtime service after
 438 * SetVirtualAddressMap() is called. As the U-Boot driver are not available
 439 * anymore only an error code is returned.
 440 *
 441 * See the Unified Extensible Firmware Interface (UEFI) specification
 442 * for details.
 443 *
 444 * @time:               pointer to structure to with current time
 445 * Returns:             status code
 446 */
 447efi_status_t __weak __efi_runtime EFIAPI efi_set_time(struct efi_time *time)
 448{
 449        return EFI_UNSUPPORTED;
 450}
 451
 452/**
 453 * efi_update_capsule_unsupported() - process information from operating system
 454 *
 455 * This function implements the UpdateCapsule() runtime service.
 456 *
 457 * See the Unified Extensible Firmware Interface (UEFI) specification for
 458 * details.
 459 *
 460 * @capsule_header_array:       pointer to array of virtual pointers
 461 * @capsule_count:              number of pointers in capsule_header_array
 462 * @scatter_gather_list:        pointer to array of physical pointers
 463 * Returns:                     status code
 464 */
 465efi_status_t __efi_runtime EFIAPI efi_update_capsule_unsupported(
 466                        struct efi_capsule_header **capsule_header_array,
 467                        efi_uintn_t capsule_count,
 468                        u64 scatter_gather_list)
 469{
 470        return EFI_UNSUPPORTED;
 471}
 472
 473/**
 474 * efi_query_capsule_caps_unsupported() - check if capsule is supported
 475 *
 476 * This function implements the QueryCapsuleCapabilities() runtime service.
 477 *
 478 * See the Unified Extensible Firmware Interface (UEFI) specification for
 479 * details.
 480 *
 481 * @capsule_header_array:       pointer to array of virtual pointers
 482 * @capsule_count:              number of pointers in capsule_header_array
 483 * @maximum_capsule_size:       maximum capsule size
 484 * @reset_type:                 type of reset needed for capsule update
 485 * Returns:                     status code
 486 */
 487efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps_unsupported(
 488                        struct efi_capsule_header **capsule_header_array,
 489                        efi_uintn_t capsule_count,
 490                        u64 *maximum_capsule_size,
 491                        u32 *reset_type)
 492{
 493        return EFI_UNSUPPORTED;
 494}
 495
 496/**
 497 * efi_is_runtime_service_pointer() - check if pointer points to runtime table
 498 *
 499 * @p:          pointer to check
 500 * Return:      true if the pointer points to a service function pointer in the
 501 *              runtime table
 502 */
 503static bool efi_is_runtime_service_pointer(void *p)
 504{
 505        return (p >= (void *)&efi_runtime_services.get_time &&
 506                p <= (void *)&efi_runtime_services.query_variable_info) ||
 507               p == (void *)&efi_events.prev ||
 508               p == (void *)&efi_events.next;
 509}
 510
 511/**
 512 * efi_runtime_detach() - detach unimplemented runtime functions
 513 */
 514void efi_runtime_detach(void)
 515{
 516        efi_runtime_services.reset_system = efi_reset_system;
 517        efi_runtime_services.get_time = efi_get_time;
 518        efi_runtime_services.set_time = efi_set_time;
 519        if (IS_ENABLED(CONFIG_EFI_RUNTIME_UPDATE_CAPSULE)) {
 520                /* won't support at runtime */
 521                efi_runtime_services.update_capsule =
 522                                efi_update_capsule_unsupported;
 523                efi_runtime_services.query_capsule_caps =
 524                                efi_query_capsule_caps_unsupported;
 525        }
 526
 527        /* Update CRC32 */
 528        efi_update_table_header_crc32(&efi_runtime_services.hdr);
 529}
 530
 531/**
 532 * efi_set_virtual_address_map_runtime() - change from physical to virtual
 533 *                                         mapping
 534 *
 535 * This function implements the SetVirtualAddressMap() runtime service after
 536 * it is first called.
 537 *
 538 * See the Unified Extensible Firmware Interface (UEFI) specification for
 539 * details.
 540 *
 541 * @memory_map_size:    size of the virtual map
 542 * @descriptor_size:    size of an entry in the map
 543 * @descriptor_version: version of the map entries
 544 * @virtmap:            virtual address mapping information
 545 * Return:              status code EFI_UNSUPPORTED
 546 */
 547static __efi_runtime efi_status_t EFIAPI efi_set_virtual_address_map_runtime(
 548                        efi_uintn_t memory_map_size,
 549                        efi_uintn_t descriptor_size,
 550                        uint32_t descriptor_version,
 551                        struct efi_mem_desc *virtmap)
 552{
 553        return EFI_UNSUPPORTED;
 554}
 555
 556/**
 557 * efi_convert_pointer_runtime() - convert from physical to virtual pointer
 558 *
 559 * This function implements the ConvertPointer() runtime service after
 560 * the first call to SetVirtualAddressMap().
 561 *
 562 * See the Unified Extensible Firmware Interface (UEFI) specification for
 563 * details.
 564 *
 565 * @debug_disposition:  indicates if pointer may be converted to NULL
 566 * @address:            pointer to be converted
 567 * Return:              status code EFI_UNSUPPORTED
 568 */
 569static __efi_runtime efi_status_t EFIAPI efi_convert_pointer_runtime(
 570                        efi_uintn_t debug_disposition, void **address)
 571{
 572        return EFI_UNSUPPORTED;
 573}
 574
 575/**
 576 * efi_convert_pointer() - convert from physical to virtual pointer
 577 *
 578 * This function implements the ConvertPointer() runtime service until
 579 * the first call to SetVirtualAddressMap().
 580 *
 581 * See the Unified Extensible Firmware Interface (UEFI) specification for
 582 * details.
 583 *
 584 * @debug_disposition:  indicates if pointer may be converted to NULL
 585 * @address:            pointer to be converted
 586 * Return:              status code
 587 */
 588__efi_runtime efi_status_t EFIAPI
 589efi_convert_pointer(efi_uintn_t debug_disposition, void **address)
 590{
 591        efi_physical_addr_t addr;
 592        efi_uintn_t i;
 593        efi_status_t ret = EFI_NOT_FOUND;
 594
 595        if (!efi_virtmap) {
 596                ret = EFI_UNSUPPORTED;
 597                goto out;
 598        }
 599
 600        if (!address) {
 601                ret = EFI_INVALID_PARAMETER;
 602                goto out;
 603        }
 604        if (!*address) {
 605                if (debug_disposition & EFI_OPTIONAL_PTR)
 606                        return EFI_SUCCESS;
 607                else
 608                        return EFI_INVALID_PARAMETER;
 609        }
 610
 611        addr = (uintptr_t)*address;
 612        for (i = 0; i < efi_descriptor_count; i++) {
 613                struct efi_mem_desc *map = (void *)efi_virtmap +
 614                                           (efi_descriptor_size * i);
 615
 616                if (addr >= map->physical_start &&
 617                    (addr < map->physical_start
 618                            + (map->num_pages << EFI_PAGE_SHIFT))) {
 619                        *address = (void *)(uintptr_t)
 620                                   (addr + map->virtual_start -
 621                                    map->physical_start);
 622
 623                        ret = EFI_SUCCESS;
 624                        break;
 625                }
 626        }
 627
 628out:
 629        return ret;
 630}
 631
 632static __efi_runtime void efi_relocate_runtime_table(ulong offset)
 633{
 634        ulong patchoff;
 635        void **pos;
 636
 637        /* Relocate the runtime services pointers */
 638        patchoff = offset - gd->relocaddr;
 639        for (pos = (void **)&efi_runtime_services.get_time;
 640             pos <= (void **)&efi_runtime_services.query_variable_info; ++pos) {
 641                if (*pos)
 642                        *pos += patchoff;
 643        }
 644
 645        /*
 646         * The entry for SetVirtualAddress() must point to a physical address.
 647         * After the first execution the service must return EFI_UNSUPPORTED.
 648         */
 649        efi_runtime_services.set_virtual_address_map =
 650                        &efi_set_virtual_address_map_runtime;
 651
 652        /*
 653         * The entry for ConvertPointer() must point to a physical address.
 654         * The service is not usable after SetVirtualAddress().
 655         */
 656        efi_runtime_services.convert_pointer = &efi_convert_pointer_runtime;
 657
 658        /*
 659         * TODO: Update UEFI variable RuntimeServicesSupported removing flags
 660         * EFI_RT_SUPPORTED_SET_VIRTUAL_ADDRESS_MAP and
 661         * EFI_RT_SUPPORTED_CONVERT_POINTER as required by the UEFI spec 2.8.
 662         */
 663
 664        /* Update CRC32 */
 665        efi_update_table_header_crc32(&efi_runtime_services.hdr);
 666}
 667
 668/* Relocate EFI runtime to uboot_reloc_base = offset */
 669void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map)
 670{
 671#ifdef IS_RELA
 672        struct elf_rela *rel = (void*)&__efi_runtime_rel_start;
 673#else
 674        struct elf_rel *rel = (void*)&__efi_runtime_rel_start;
 675        static ulong lastoff = CONFIG_SYS_TEXT_BASE;
 676#endif
 677
 678        debug("%s: Relocating to offset=%lx\n", __func__, offset);
 679        for (; (ulong)rel < (ulong)&__efi_runtime_rel_stop; rel++) {
 680                ulong base = CONFIG_SYS_TEXT_BASE;
 681                ulong *p;
 682                ulong newaddr;
 683
 684                p = (void*)((ulong)rel->offset - base) + gd->relocaddr;
 685
 686                /*
 687                 * The runtime services table is updated in
 688                 * efi_relocate_runtime_table()
 689                 */
 690                if (map && efi_is_runtime_service_pointer(p))
 691                        continue;
 692
 693                debug("%s: rel->info=%#lx *p=%#lx rel->offset=%p\n", __func__,
 694                      rel->info, *p, rel->offset);
 695
 696                switch (rel->info & R_MASK) {
 697                case R_RELATIVE:
 698#ifdef IS_RELA
 699                newaddr = rel->addend + offset - CONFIG_SYS_TEXT_BASE;
 700#else
 701                newaddr = *p - lastoff + offset;
 702#endif
 703                        break;
 704#ifdef R_ABSOLUTE
 705                case R_ABSOLUTE: {
 706                        ulong symidx = rel->info >> SYM_INDEX;
 707                        extern struct dyn_sym __dyn_sym_start[];
 708                        newaddr = __dyn_sym_start[symidx].addr + offset;
 709#ifdef IS_RELA
 710                        newaddr -= CONFIG_SYS_TEXT_BASE;
 711#endif
 712                        break;
 713                }
 714#endif
 715                default:
 716                        printf("%s: Unknown relocation type %llx\n",
 717                               __func__, rel->info & R_MASK);
 718                        continue;
 719                }
 720
 721                /* Check if the relocation is inside bounds */
 722                if (map && ((newaddr < map->virtual_start) ||
 723                    newaddr > (map->virtual_start +
 724                              (map->num_pages << EFI_PAGE_SHIFT)))) {
 725                        printf("%s: Relocation at %p is out of range (%lx)\n",
 726                               __func__, p, newaddr);
 727                        continue;
 728                }
 729
 730                debug("%s: Setting %p to %lx\n", __func__, p, newaddr);
 731                *p = newaddr;
 732                flush_dcache_range((ulong)p & ~(EFI_CACHELINE_SIZE - 1),
 733                        ALIGN((ulong)&p[1], EFI_CACHELINE_SIZE));
 734        }
 735
 736#ifndef IS_RELA
 737        lastoff = offset;
 738#endif
 739
 740        invalidate_icache_all();
 741}
 742
 743/**
 744 * efi_set_virtual_address_map() - change from physical to virtual mapping
 745 *
 746 * This function implements the SetVirtualAddressMap() runtime service.
 747 *
 748 * See the Unified Extensible Firmware Interface (UEFI) specification for
 749 * details.
 750 *
 751 * @memory_map_size:    size of the virtual map
 752 * @descriptor_size:    size of an entry in the map
 753 * @descriptor_version: version of the map entries
 754 * @virtmap:            virtual address mapping information
 755 * Return:              status code
 756 */
 757static efi_status_t EFIAPI efi_set_virtual_address_map(
 758                        efi_uintn_t memory_map_size,
 759                        efi_uintn_t descriptor_size,
 760                        uint32_t descriptor_version,
 761                        struct efi_mem_desc *virtmap)
 762{
 763        efi_uintn_t n = memory_map_size / descriptor_size;
 764        efi_uintn_t i;
 765        efi_status_t ret = EFI_INVALID_PARAMETER;
 766        int rt_code_sections = 0;
 767        struct efi_event *event;
 768
 769        EFI_ENTRY("%zx %zx %x %p", memory_map_size, descriptor_size,
 770                  descriptor_version, virtmap);
 771
 772        if (descriptor_version != EFI_MEMORY_DESCRIPTOR_VERSION ||
 773            descriptor_size < sizeof(struct efi_mem_desc))
 774                goto out;
 775
 776        efi_virtmap = virtmap;
 777        efi_descriptor_size = descriptor_size;
 778        efi_descriptor_count = n;
 779
 780        /*
 781         * TODO:
 782         * Further down we are cheating. While really we should implement
 783         * SetVirtualAddressMap() events and ConvertPointer() to allow
 784         * dynamically loaded drivers to expose runtime services, we don't
 785         * today.
 786         *
 787         * So let's ensure we see exactly one single runtime section, as
 788         * that is the built-in one. If we see more (or less), someone must
 789         * have tried adding or removing to that which we don't support yet.
 790         * In that case, let's better fail rather than expose broken runtime
 791         * services.
 792         */
 793        for (i = 0; i < n; i++) {
 794                struct efi_mem_desc *map = (void*)virtmap +
 795                                           (descriptor_size * i);
 796
 797                if (map->type == EFI_RUNTIME_SERVICES_CODE)
 798                        rt_code_sections++;
 799        }
 800
 801        if (rt_code_sections != 1) {
 802                /*
 803                 * We expose exactly one single runtime code section, so
 804                 * something is definitely going wrong.
 805                 */
 806                goto out;
 807        }
 808
 809        /* Notify EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE */
 810        list_for_each_entry(event, &efi_events, link) {
 811                if (event->notify_function)
 812                        EFI_CALL_VOID(event->notify_function(
 813                                        event, event->notify_context));
 814        }
 815
 816        /* Rebind mmio pointers */
 817        for (i = 0; i < n; i++) {
 818                struct efi_mem_desc *map = (void*)virtmap +
 819                                           (descriptor_size * i);
 820                struct list_head *lhandle;
 821                efi_physical_addr_t map_start = map->physical_start;
 822                efi_physical_addr_t map_len = map->num_pages << EFI_PAGE_SHIFT;
 823                efi_physical_addr_t map_end = map_start + map_len;
 824                u64 off = map->virtual_start - map_start;
 825
 826                /* Adjust all mmio pointers in this region */
 827                list_for_each(lhandle, &efi_runtime_mmio) {
 828                        struct efi_runtime_mmio_list *lmmio;
 829
 830                        lmmio = list_entry(lhandle,
 831                                           struct efi_runtime_mmio_list,
 832                                           link);
 833                        if ((map_start <= lmmio->paddr) &&
 834                            (map_end >= lmmio->paddr)) {
 835                                uintptr_t new_addr = lmmio->paddr + off;
 836                                *lmmio->ptr = (void *)new_addr;
 837                        }
 838                }
 839                if ((map_start <= (uintptr_t)systab.tables) &&
 840                    (map_end >= (uintptr_t)systab.tables)) {
 841                        char *ptr = (char *)systab.tables;
 842
 843                        ptr += off;
 844                        systab.tables = (struct efi_configuration_table *)ptr;
 845                }
 846        }
 847
 848        /* Relocate the runtime. See TODO above */
 849        for (i = 0; i < n; i++) {
 850                struct efi_mem_desc *map;
 851
 852                map = (void*)virtmap + (descriptor_size * i);
 853                if (map->type == EFI_RUNTIME_SERVICES_CODE) {
 854                        ulong new_offset = map->virtual_start -
 855                                           map->physical_start + gd->relocaddr;
 856
 857                        efi_relocate_runtime_table(new_offset);
 858                        efi_runtime_relocate(new_offset, map);
 859                        ret = EFI_SUCCESS;
 860                        goto out;
 861                }
 862        }
 863
 864out:
 865        return EFI_EXIT(ret);
 866}
 867
 868/**
 869 * efi_add_runtime_mmio() - add memory-mapped IO region
 870 *
 871 * This function adds a memory-mapped IO region to the memory map to make it
 872 * available at runtime.
 873 *
 874 * @mmio_ptr:           pointer to a pointer to the start of the memory-mapped
 875 *                      IO region
 876 * @len:                size of the memory-mapped IO region
 877 * Returns:             status code
 878 */
 879efi_status_t efi_add_runtime_mmio(void *mmio_ptr, u64 len)
 880{
 881        struct efi_runtime_mmio_list *newmmio;
 882        uint64_t addr = *(uintptr_t *)mmio_ptr;
 883        efi_status_t ret;
 884
 885        ret = efi_add_memory_map(addr, len, EFI_MMAP_IO);
 886        if (ret != EFI_SUCCESS)
 887                return EFI_OUT_OF_RESOURCES;
 888
 889        newmmio = calloc(1, sizeof(*newmmio));
 890        if (!newmmio)
 891                return EFI_OUT_OF_RESOURCES;
 892        newmmio->ptr = mmio_ptr;
 893        newmmio->paddr = *(uintptr_t *)mmio_ptr;
 894        newmmio->len = len;
 895        list_add_tail(&newmmio->link, &efi_runtime_mmio);
 896
 897        return EFI_SUCCESS;
 898}
 899
 900/*
 901 * In the second stage, U-Boot has disappeared. To isolate our runtime code
 902 * that at this point still exists from the rest, we put it into a special
 903 * section.
 904 *
 905 *        !!WARNING!!
 906 *
 907 * This means that we can not rely on any code outside of this file in any
 908 * function or variable below this line.
 909 *
 910 * Please keep everything fully self-contained and annotated with
 911 * __efi_runtime and __efi_runtime_data markers.
 912 */
 913
 914/*
 915 * Relocate the EFI runtime stub to a different place. We need to call this
 916 * the first time we expose the runtime interface to a user and on set virtual
 917 * address map calls.
 918 */
 919
 920/**
 921 * efi_unimplemented() - replacement function, returns EFI_UNSUPPORTED
 922 *
 923 * This function is used after SetVirtualAddressMap() is called as replacement
 924 * for services that are not available anymore due to constraints of the U-Boot
 925 * implementation.
 926 *
 927 * Return:      EFI_UNSUPPORTED
 928 */
 929static efi_status_t __efi_runtime EFIAPI efi_unimplemented(void)
 930{
 931        return EFI_UNSUPPORTED;
 932}
 933
 934struct efi_runtime_services __efi_runtime_data efi_runtime_services = {
 935        .hdr = {
 936                .signature = EFI_RUNTIME_SERVICES_SIGNATURE,
 937                .revision = EFI_SPECIFICATION_VERSION,
 938                .headersize = sizeof(struct efi_runtime_services),
 939        },
 940        .get_time = &efi_get_time_boottime,
 941        .set_time = &efi_set_time_boottime,
 942        .get_wakeup_time = (void *)&efi_unimplemented,
 943        .set_wakeup_time = (void *)&efi_unimplemented,
 944        .set_virtual_address_map = &efi_set_virtual_address_map,
 945        .convert_pointer = efi_convert_pointer,
 946        .get_variable = efi_get_variable,
 947        .get_next_variable_name = efi_get_next_variable_name,
 948        .set_variable = efi_set_variable,
 949        .get_next_high_mono_count = (void *)&efi_unimplemented,
 950        .reset_system = &efi_reset_system_boottime,
 951#ifdef CONFIG_EFI_RUNTIME_UPDATE_CAPSULE
 952        .update_capsule = efi_update_capsule,
 953        .query_capsule_caps = efi_query_capsule_caps,
 954#else
 955        .update_capsule = efi_update_capsule_unsupported,
 956        .query_capsule_caps = efi_query_capsule_caps_unsupported,
 957#endif
 958        .query_variable_info = efi_query_variable_info,
 959};
 960