xref: /rk3399_rockchip-uboot/lib/efi_loader/efi_runtime.c (revision 80a4800ee1526a4a46cd02b3ea2fd37eebb77504)
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