150149ea3SAlexander Graf /* 250149ea3SAlexander Graf * EFI application runtime services 350149ea3SAlexander Graf * 450149ea3SAlexander Graf * Copyright (c) 2016 Alexander Graf 550149ea3SAlexander Graf * 650149ea3SAlexander Graf * SPDX-License-Identifier: GPL-2.0+ 750149ea3SAlexander Graf */ 850149ea3SAlexander Graf 950149ea3SAlexander Graf #include <common.h> 1050149ea3SAlexander Graf #include <command.h> 1150149ea3SAlexander Graf #include <dm.h> 1250149ea3SAlexander Graf #include <efi_loader.h> 1350149ea3SAlexander Graf #include <rtc.h> 1450149ea3SAlexander Graf #include <asm/global_data.h> 1550149ea3SAlexander Graf 1650149ea3SAlexander Graf /* For manual relocation support */ 1750149ea3SAlexander Graf DECLARE_GLOBAL_DATA_PTR; 1850149ea3SAlexander Graf 19*80a4800eSAlexander Graf struct efi_runtime_mmio_list { 20*80a4800eSAlexander Graf struct list_head link; 21*80a4800eSAlexander Graf void **ptr; 22*80a4800eSAlexander Graf u64 paddr; 23*80a4800eSAlexander Graf u64 len; 24*80a4800eSAlexander Graf }; 25*80a4800eSAlexander Graf 26*80a4800eSAlexander Graf /* This list contains all runtime available mmio regions */ 27*80a4800eSAlexander Graf LIST_HEAD(efi_runtime_mmio); 28*80a4800eSAlexander Graf 2950149ea3SAlexander Graf static efi_status_t EFI_RUNTIME_TEXT EFIAPI efi_unimplemented(void); 3050149ea3SAlexander Graf static efi_status_t EFI_RUNTIME_TEXT EFIAPI efi_device_error(void); 3150149ea3SAlexander Graf static efi_status_t EFI_RUNTIME_TEXT EFIAPI efi_invalid_parameter(void); 3250149ea3SAlexander Graf 3336c37a84SAlexander Graf #ifdef CONFIG_SYS_CACHELINE_SIZE 3436c37a84SAlexander Graf #define EFI_CACHELINE_SIZE CONFIG_SYS_CACHELINE_SIZE 3536c37a84SAlexander Graf #else 3636c37a84SAlexander Graf /* Just use the greatest cache flush alignment requirement I'm aware of */ 3736c37a84SAlexander Graf #define EFI_CACHELINE_SIZE 128 3836c37a84SAlexander Graf #endif 3936c37a84SAlexander Graf 4050149ea3SAlexander Graf #if defined(CONFIG_ARM64) 4150149ea3SAlexander Graf #define R_RELATIVE 1027 4250149ea3SAlexander Graf #define R_MASK 0xffffffffULL 4350149ea3SAlexander Graf #define IS_RELA 1 4450149ea3SAlexander Graf #elif defined(CONFIG_ARM) 4550149ea3SAlexander Graf #define R_RELATIVE 23 4650149ea3SAlexander Graf #define R_MASK 0xffULL 4750149ea3SAlexander Graf #else 4850149ea3SAlexander Graf #error Need to add relocation awareness 4950149ea3SAlexander Graf #endif 5050149ea3SAlexander Graf 5150149ea3SAlexander Graf struct elf_rel { 5250149ea3SAlexander Graf ulong *offset; 5350149ea3SAlexander Graf ulong info; 5450149ea3SAlexander Graf }; 5550149ea3SAlexander Graf 5650149ea3SAlexander Graf struct elf_rela { 5750149ea3SAlexander Graf ulong *offset; 5850149ea3SAlexander Graf ulong info; 5950149ea3SAlexander Graf long addend; 6050149ea3SAlexander Graf }; 6150149ea3SAlexander Graf 6250149ea3SAlexander Graf /* 6350149ea3SAlexander Graf * EFI Runtime code lives in 2 stages. In the first stage, U-Boot and an EFI 6450149ea3SAlexander Graf * payload are running concurrently at the same time. In this mode, we can 6550149ea3SAlexander Graf * handle a good number of runtime callbacks 6650149ea3SAlexander Graf */ 6750149ea3SAlexander Graf 68*80a4800eSAlexander Graf static void EFIAPI efi_reset_system_boottime( 69*80a4800eSAlexander Graf enum efi_reset_type reset_type, 7050149ea3SAlexander Graf efi_status_t reset_status, 7150149ea3SAlexander Graf unsigned long data_size, void *reset_data) 7250149ea3SAlexander Graf { 7350149ea3SAlexander Graf EFI_ENTRY("%d %lx %lx %p", reset_type, reset_status, data_size, 7450149ea3SAlexander Graf reset_data); 7550149ea3SAlexander Graf 7650149ea3SAlexander Graf switch (reset_type) { 7750149ea3SAlexander Graf case EFI_RESET_COLD: 7850149ea3SAlexander Graf case EFI_RESET_WARM: 7950149ea3SAlexander Graf do_reset(NULL, 0, 0, NULL); 8050149ea3SAlexander Graf break; 8150149ea3SAlexander Graf case EFI_RESET_SHUTDOWN: 8250149ea3SAlexander Graf /* We don't have anything to map this to */ 8350149ea3SAlexander Graf break; 8450149ea3SAlexander Graf } 8550149ea3SAlexander Graf 86*80a4800eSAlexander Graf while (1) { } 8750149ea3SAlexander Graf } 8850149ea3SAlexander Graf 89*80a4800eSAlexander Graf static efi_status_t EFIAPI efi_get_time_boottime( 90*80a4800eSAlexander Graf struct efi_time *time, 9150149ea3SAlexander Graf struct efi_time_cap *capabilities) 9250149ea3SAlexander Graf { 9350149ea3SAlexander Graf #if defined(CONFIG_CMD_DATE) && defined(CONFIG_DM_RTC) 9450149ea3SAlexander Graf struct rtc_time tm; 9550149ea3SAlexander Graf int r; 9650149ea3SAlexander Graf struct udevice *dev; 9750149ea3SAlexander Graf 9850149ea3SAlexander Graf EFI_ENTRY("%p %p", time, capabilities); 9950149ea3SAlexander Graf 10050149ea3SAlexander Graf r = uclass_get_device(UCLASS_RTC, 0, &dev); 10150149ea3SAlexander Graf if (r) 10250149ea3SAlexander Graf return EFI_EXIT(EFI_DEVICE_ERROR); 10350149ea3SAlexander Graf 10450149ea3SAlexander Graf r = dm_rtc_get(dev, &tm); 10550149ea3SAlexander Graf if (r) 10650149ea3SAlexander Graf return EFI_EXIT(EFI_DEVICE_ERROR); 10750149ea3SAlexander Graf 10850149ea3SAlexander Graf memset(time, 0, sizeof(*time)); 10950149ea3SAlexander Graf time->year = tm.tm_year; 11050149ea3SAlexander Graf time->month = tm.tm_mon; 11150149ea3SAlexander Graf time->day = tm.tm_mday; 11250149ea3SAlexander Graf time->hour = tm.tm_hour; 11350149ea3SAlexander Graf time->minute = tm.tm_min; 11450149ea3SAlexander Graf time->daylight = tm.tm_isdst; 11550149ea3SAlexander Graf 11650149ea3SAlexander Graf return EFI_EXIT(EFI_SUCCESS); 11750149ea3SAlexander Graf #else 11850149ea3SAlexander Graf return EFI_DEVICE_ERROR; 11950149ea3SAlexander Graf #endif 12050149ea3SAlexander Graf } 12150149ea3SAlexander Graf 122*80a4800eSAlexander Graf /* Boards may override the helpers below to implement RTS functionality */ 123*80a4800eSAlexander Graf 124*80a4800eSAlexander Graf void __weak EFI_RUNTIME_TEXT EFIAPI efi_reset_system( 125*80a4800eSAlexander Graf enum efi_reset_type reset_type, 126*80a4800eSAlexander Graf efi_status_t reset_status, 127*80a4800eSAlexander Graf unsigned long data_size, void *reset_data) 128*80a4800eSAlexander Graf { 129*80a4800eSAlexander Graf /* Nothing we can do */ 130*80a4800eSAlexander Graf while (1) { } 131*80a4800eSAlexander Graf } 132*80a4800eSAlexander Graf 133*80a4800eSAlexander Graf void __weak efi_reset_system_init(void) 134*80a4800eSAlexander Graf { 135*80a4800eSAlexander Graf } 136*80a4800eSAlexander Graf 137*80a4800eSAlexander Graf efi_status_t __weak EFI_RUNTIME_TEXT EFIAPI efi_get_time( 138*80a4800eSAlexander Graf struct efi_time *time, 139*80a4800eSAlexander Graf struct efi_time_cap *capabilities) 140*80a4800eSAlexander Graf { 141*80a4800eSAlexander Graf /* Nothing we can do */ 142*80a4800eSAlexander Graf return EFI_DEVICE_ERROR; 143*80a4800eSAlexander Graf } 144*80a4800eSAlexander Graf 145*80a4800eSAlexander Graf void __weak efi_get_time_init(void) 146*80a4800eSAlexander Graf { 147*80a4800eSAlexander Graf } 148*80a4800eSAlexander Graf 14950149ea3SAlexander Graf struct efi_runtime_detach_list_struct { 15050149ea3SAlexander Graf void *ptr; 15150149ea3SAlexander Graf void *patchto; 15250149ea3SAlexander Graf }; 15350149ea3SAlexander Graf 15450149ea3SAlexander Graf static const struct efi_runtime_detach_list_struct efi_runtime_detach_list[] = { 15550149ea3SAlexander Graf { 15650149ea3SAlexander Graf /* do_reset is gone */ 15750149ea3SAlexander Graf .ptr = &efi_runtime_services.reset_system, 158*80a4800eSAlexander Graf .patchto = efi_reset_system, 15950149ea3SAlexander Graf }, { 16050149ea3SAlexander Graf /* invalidate_*cache_all are gone */ 16150149ea3SAlexander Graf .ptr = &efi_runtime_services.set_virtual_address_map, 16250149ea3SAlexander Graf .patchto = &efi_invalid_parameter, 16350149ea3SAlexander Graf }, { 16450149ea3SAlexander Graf /* RTC accessors are gone */ 16550149ea3SAlexander Graf .ptr = &efi_runtime_services.get_time, 166*80a4800eSAlexander Graf .patchto = &efi_get_time, 167ae874405SAlexander Graf }, { 168ae874405SAlexander Graf /* Clean up system table */ 169ae874405SAlexander Graf .ptr = &systab.con_in, 170ae874405SAlexander Graf .patchto = NULL, 171ae874405SAlexander Graf }, { 172ae874405SAlexander Graf /* Clean up system table */ 173ae874405SAlexander Graf .ptr = &systab.con_out, 174ae874405SAlexander Graf .patchto = NULL, 175ae874405SAlexander Graf }, { 176ae874405SAlexander Graf /* Clean up system table */ 177ae874405SAlexander Graf .ptr = &systab.std_err, 178ae874405SAlexander Graf .patchto = NULL, 179ae874405SAlexander Graf }, { 180ae874405SAlexander Graf /* Clean up system table */ 181ae874405SAlexander Graf .ptr = &systab.boottime, 182ae874405SAlexander Graf .patchto = NULL, 18350149ea3SAlexander Graf }, 18450149ea3SAlexander Graf }; 18550149ea3SAlexander Graf 18650149ea3SAlexander Graf static bool efi_runtime_tobedetached(void *p) 18750149ea3SAlexander Graf { 18850149ea3SAlexander Graf int i; 18950149ea3SAlexander Graf 19050149ea3SAlexander Graf for (i = 0; i < ARRAY_SIZE(efi_runtime_detach_list); i++) 19150149ea3SAlexander Graf if (efi_runtime_detach_list[i].ptr == p) 19250149ea3SAlexander Graf return true; 19350149ea3SAlexander Graf 19450149ea3SAlexander Graf return false; 19550149ea3SAlexander Graf } 19650149ea3SAlexander Graf 19750149ea3SAlexander Graf static void efi_runtime_detach(ulong offset) 19850149ea3SAlexander Graf { 19950149ea3SAlexander Graf int i; 20050149ea3SAlexander Graf ulong patchoff = offset - (ulong)gd->relocaddr; 20150149ea3SAlexander Graf 20250149ea3SAlexander Graf for (i = 0; i < ARRAY_SIZE(efi_runtime_detach_list); i++) { 20350149ea3SAlexander Graf ulong patchto = (ulong)efi_runtime_detach_list[i].patchto; 20450149ea3SAlexander Graf ulong *p = efi_runtime_detach_list[i].ptr; 20550149ea3SAlexander Graf ulong newaddr = patchto ? (patchto + patchoff) : 0; 20650149ea3SAlexander Graf 207edcef3baSAlexander Graf debug("%s: Setting %p to %lx\n", __func__, p, newaddr); 20850149ea3SAlexander Graf *p = newaddr; 20950149ea3SAlexander Graf } 21050149ea3SAlexander Graf } 21150149ea3SAlexander Graf 21250149ea3SAlexander Graf /* Relocate EFI runtime to uboot_reloc_base = offset */ 21350149ea3SAlexander Graf void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map) 21450149ea3SAlexander Graf { 21550149ea3SAlexander Graf #ifdef IS_RELA 21650149ea3SAlexander Graf struct elf_rela *rel = (void*)&__efi_runtime_rel_start; 21750149ea3SAlexander Graf #else 21850149ea3SAlexander Graf struct elf_rel *rel = (void*)&__efi_runtime_rel_start; 21950149ea3SAlexander Graf static ulong lastoff = CONFIG_SYS_TEXT_BASE; 22050149ea3SAlexander Graf #endif 22150149ea3SAlexander Graf 222edcef3baSAlexander Graf debug("%s: Relocating to offset=%lx\n", __func__, offset); 22350149ea3SAlexander Graf for (; (ulong)rel < (ulong)&__efi_runtime_rel_stop; rel++) { 22450149ea3SAlexander Graf ulong base = CONFIG_SYS_TEXT_BASE; 22550149ea3SAlexander Graf ulong *p; 22650149ea3SAlexander Graf ulong newaddr; 22750149ea3SAlexander Graf 22850149ea3SAlexander Graf p = (void*)((ulong)rel->offset - base) + gd->relocaddr; 22950149ea3SAlexander Graf 23050149ea3SAlexander Graf if ((rel->info & R_MASK) != R_RELATIVE) { 23150149ea3SAlexander Graf continue; 23250149ea3SAlexander Graf } 23350149ea3SAlexander Graf 23450149ea3SAlexander Graf #ifdef IS_RELA 23550149ea3SAlexander Graf newaddr = rel->addend + offset - CONFIG_SYS_TEXT_BASE; 23650149ea3SAlexander Graf #else 23750149ea3SAlexander Graf newaddr = *p - lastoff + offset; 23850149ea3SAlexander Graf #endif 23950149ea3SAlexander Graf 24050149ea3SAlexander Graf /* Check if the relocation is inside bounds */ 24150149ea3SAlexander Graf if (map && ((newaddr < map->virtual_start) || 24250149ea3SAlexander Graf newaddr > (map->virtual_start + (map->num_pages << 12)))) { 24350149ea3SAlexander Graf if (!efi_runtime_tobedetached(p)) 24450149ea3SAlexander Graf printf("U-Boot EFI: Relocation at %p is out of " 24550149ea3SAlexander Graf "range (%lx)\n", p, newaddr); 24650149ea3SAlexander Graf continue; 24750149ea3SAlexander Graf } 24850149ea3SAlexander Graf 249edcef3baSAlexander Graf debug("%s: Setting %p to %lx\n", __func__, p, newaddr); 25050149ea3SAlexander Graf *p = newaddr; 25136c37a84SAlexander Graf flush_dcache_range((ulong)p & ~(EFI_CACHELINE_SIZE - 1), 25236c37a84SAlexander Graf ALIGN((ulong)&p[1], EFI_CACHELINE_SIZE)); 25350149ea3SAlexander Graf } 25450149ea3SAlexander Graf 25550149ea3SAlexander Graf #ifndef IS_RELA 25650149ea3SAlexander Graf lastoff = offset; 25750149ea3SAlexander Graf #endif 25850149ea3SAlexander Graf 25950149ea3SAlexander Graf invalidate_icache_all(); 26050149ea3SAlexander Graf } 26150149ea3SAlexander Graf 26250149ea3SAlexander Graf static efi_status_t EFIAPI efi_set_virtual_address_map( 26350149ea3SAlexander Graf unsigned long memory_map_size, 26450149ea3SAlexander Graf unsigned long descriptor_size, 26550149ea3SAlexander Graf uint32_t descriptor_version, 26650149ea3SAlexander Graf struct efi_mem_desc *virtmap) 26750149ea3SAlexander Graf { 26850149ea3SAlexander Graf ulong runtime_start = (ulong)&__efi_runtime_start & ~0xfffULL; 26950149ea3SAlexander Graf int n = memory_map_size / descriptor_size; 27050149ea3SAlexander Graf int i; 27150149ea3SAlexander Graf 27250149ea3SAlexander Graf EFI_ENTRY("%lx %lx %x %p", memory_map_size, descriptor_size, 27350149ea3SAlexander Graf descriptor_version, virtmap); 27450149ea3SAlexander Graf 275*80a4800eSAlexander Graf /* Rebind mmio pointers */ 276*80a4800eSAlexander Graf for (i = 0; i < n; i++) { 277*80a4800eSAlexander Graf struct efi_mem_desc *map = (void*)virtmap + 278*80a4800eSAlexander Graf (descriptor_size * i); 279*80a4800eSAlexander Graf struct list_head *lhandle; 280*80a4800eSAlexander Graf efi_physical_addr_t map_start = map->physical_start; 281*80a4800eSAlexander Graf efi_physical_addr_t map_len = map->num_pages << EFI_PAGE_SHIFT; 282*80a4800eSAlexander Graf efi_physical_addr_t map_end = map_start + map_len; 283*80a4800eSAlexander Graf 284*80a4800eSAlexander Graf /* Adjust all mmio pointers in this region */ 285*80a4800eSAlexander Graf list_for_each(lhandle, &efi_runtime_mmio) { 286*80a4800eSAlexander Graf struct efi_runtime_mmio_list *lmmio; 287*80a4800eSAlexander Graf 288*80a4800eSAlexander Graf lmmio = list_entry(lhandle, 289*80a4800eSAlexander Graf struct efi_runtime_mmio_list, 290*80a4800eSAlexander Graf link); 291*80a4800eSAlexander Graf if ((map_start <= lmmio->paddr) && 292*80a4800eSAlexander Graf (map_end >= lmmio->paddr)) { 293*80a4800eSAlexander Graf u64 off = map->virtual_start - map_start; 294*80a4800eSAlexander Graf uintptr_t new_addr = lmmio->paddr + off; 295*80a4800eSAlexander Graf *lmmio->ptr = (void *)new_addr; 296*80a4800eSAlexander Graf } 297*80a4800eSAlexander Graf } 298*80a4800eSAlexander Graf } 299*80a4800eSAlexander Graf 300*80a4800eSAlexander Graf /* Move the actual runtime code over */ 30150149ea3SAlexander Graf for (i = 0; i < n; i++) { 30250149ea3SAlexander Graf struct efi_mem_desc *map; 30350149ea3SAlexander Graf 30450149ea3SAlexander Graf map = (void*)virtmap + (descriptor_size * i); 30550149ea3SAlexander Graf if (map->type == EFI_RUNTIME_SERVICES_CODE) { 306*80a4800eSAlexander Graf ulong new_offset = map->virtual_start - 307*80a4800eSAlexander Graf (runtime_start - gd->relocaddr); 30850149ea3SAlexander Graf 30950149ea3SAlexander Graf efi_runtime_relocate(new_offset, map); 31050149ea3SAlexander Graf /* Once we're virtual, we can no longer handle 31150149ea3SAlexander Graf complex callbacks */ 31250149ea3SAlexander Graf efi_runtime_detach(new_offset); 31350149ea3SAlexander Graf return EFI_EXIT(EFI_SUCCESS); 31450149ea3SAlexander Graf } 31550149ea3SAlexander Graf } 31650149ea3SAlexander Graf 31750149ea3SAlexander Graf return EFI_EXIT(EFI_INVALID_PARAMETER); 31850149ea3SAlexander Graf } 31950149ea3SAlexander Graf 320*80a4800eSAlexander Graf void efi_add_runtime_mmio(void *mmio_ptr, u64 len) 321*80a4800eSAlexander Graf { 322*80a4800eSAlexander Graf struct efi_runtime_mmio_list *newmmio; 323*80a4800eSAlexander Graf 324*80a4800eSAlexander Graf u64 pages = (len + EFI_PAGE_SIZE - 1) >> EFI_PAGE_SHIFT; 325*80a4800eSAlexander Graf efi_add_memory_map(*(uintptr_t *)mmio_ptr, pages, EFI_MMAP_IO, false); 326*80a4800eSAlexander Graf 327*80a4800eSAlexander Graf newmmio = calloc(1, sizeof(*newmmio)); 328*80a4800eSAlexander Graf newmmio->ptr = mmio_ptr; 329*80a4800eSAlexander Graf newmmio->paddr = *(uintptr_t *)mmio_ptr; 330*80a4800eSAlexander Graf newmmio->len = len; 331*80a4800eSAlexander Graf list_add_tail(&newmmio->link, &efi_runtime_mmio); 332*80a4800eSAlexander Graf } 333*80a4800eSAlexander Graf 33450149ea3SAlexander Graf /* 33550149ea3SAlexander Graf * In the second stage, U-Boot has disappeared. To isolate our runtime code 33650149ea3SAlexander Graf * that at this point still exists from the rest, we put it into a special 33750149ea3SAlexander Graf * section. 33850149ea3SAlexander Graf * 33950149ea3SAlexander Graf * !!WARNING!! 34050149ea3SAlexander Graf * 34150149ea3SAlexander Graf * This means that we can not rely on any code outside of this file in any 34250149ea3SAlexander Graf * function or variable below this line. 34350149ea3SAlexander Graf * 34450149ea3SAlexander Graf * Please keep everything fully self-contained and annotated with 34550149ea3SAlexander Graf * EFI_RUNTIME_TEXT and EFI_RUNTIME_DATA markers. 34650149ea3SAlexander Graf */ 34750149ea3SAlexander Graf 34850149ea3SAlexander Graf /* 34950149ea3SAlexander Graf * Relocate the EFI runtime stub to a different place. We need to call this 35050149ea3SAlexander Graf * the first time we expose the runtime interface to a user and on set virtual 35150149ea3SAlexander Graf * address map calls. 35250149ea3SAlexander Graf */ 35350149ea3SAlexander Graf 35450149ea3SAlexander Graf static efi_status_t EFI_RUNTIME_TEXT EFIAPI efi_unimplemented(void) 35550149ea3SAlexander Graf { 35650149ea3SAlexander Graf return EFI_UNSUPPORTED; 35750149ea3SAlexander Graf } 35850149ea3SAlexander Graf 35950149ea3SAlexander Graf static efi_status_t EFI_RUNTIME_TEXT EFIAPI efi_device_error(void) 36050149ea3SAlexander Graf { 36150149ea3SAlexander Graf return EFI_DEVICE_ERROR; 36250149ea3SAlexander Graf } 36350149ea3SAlexander Graf 36450149ea3SAlexander Graf static efi_status_t EFI_RUNTIME_TEXT EFIAPI efi_invalid_parameter(void) 36550149ea3SAlexander Graf { 36650149ea3SAlexander Graf return EFI_INVALID_PARAMETER; 36750149ea3SAlexander Graf } 36850149ea3SAlexander Graf 36950149ea3SAlexander Graf struct efi_runtime_services EFI_RUNTIME_DATA efi_runtime_services = { 37050149ea3SAlexander Graf .hdr = { 37150149ea3SAlexander Graf .signature = EFI_RUNTIME_SERVICES_SIGNATURE, 37250149ea3SAlexander Graf .revision = EFI_RUNTIME_SERVICES_REVISION, 37350149ea3SAlexander Graf .headersize = sizeof(struct efi_table_hdr), 37450149ea3SAlexander Graf }, 375*80a4800eSAlexander Graf .get_time = &efi_get_time_boottime, 37650149ea3SAlexander Graf .set_time = (void *)&efi_device_error, 37750149ea3SAlexander Graf .get_wakeup_time = (void *)&efi_unimplemented, 37850149ea3SAlexander Graf .set_wakeup_time = (void *)&efi_unimplemented, 37950149ea3SAlexander Graf .set_virtual_address_map = &efi_set_virtual_address_map, 38050149ea3SAlexander Graf .convert_pointer = (void *)&efi_invalid_parameter, 38150149ea3SAlexander Graf .get_variable = (void *)&efi_device_error, 38250149ea3SAlexander Graf .get_next_variable = (void *)&efi_device_error, 38350149ea3SAlexander Graf .set_variable = (void *)&efi_device_error, 38450149ea3SAlexander Graf .get_next_high_mono_count = (void *)&efi_device_error, 385*80a4800eSAlexander Graf .reset_system = &efi_reset_system_boottime, 38650149ea3SAlexander Graf }; 387