xref: /openbmc/u-boot/lib/efi_loader/efi_runtime.c (revision 63f7e3fca391a50a499fed828fe16325fdee45f3)
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 <dm.h>
11  #include <elf.h>
12  #include <efi_loader.h>
13  #include <rtc.h>
14  
15  /* For manual relocation support */
16  DECLARE_GLOBAL_DATA_PTR;
17  
18  struct efi_runtime_mmio_list {
19  	struct list_head link;
20  	void **ptr;
21  	u64 paddr;
22  	u64 len;
23  };
24  
25  /* This list contains all runtime available mmio regions */
26  LIST_HEAD(efi_runtime_mmio);
27  
28  static efi_status_t __efi_runtime EFIAPI efi_unimplemented(void);
29  static efi_status_t __efi_runtime EFIAPI efi_device_error(void);
30  static efi_status_t __efi_runtime EFIAPI efi_invalid_parameter(void);
31  
32  /*
33   * TODO(sjg@chromium.org): These defines and structures should come from the ELF
34   * header for each architecture (or a generic header) rather than being repeated
35   * here.
36   */
37  #if defined(__aarch64__)
38  #define R_RELATIVE	R_AARCH64_RELATIVE
39  #define R_MASK		0xffffffffULL
40  #define IS_RELA		1
41  #elif defined(__arm__)
42  #define R_RELATIVE	R_ARM_RELATIVE
43  #define R_MASK		0xffULL
44  #elif defined(__i386__)
45  #define R_RELATIVE	R_386_RELATIVE
46  #define R_MASK		0xffULL
47  #elif defined(__x86_64__)
48  #define R_RELATIVE	R_X86_64_RELATIVE
49  #define R_MASK		0xffffffffULL
50  #define IS_RELA		1
51  #elif defined(__riscv)
52  #define R_RELATIVE	R_RISCV_RELATIVE
53  #define R_MASK		0xffULL
54  #define IS_RELA		1
55  
56  struct dyn_sym {
57  	ulong foo1;
58  	ulong addr;
59  	u32 foo2;
60  	u32 foo3;
61  };
62  #if (__riscv_xlen == 32)
63  #define R_ABSOLUTE	R_RISCV_32
64  #define SYM_INDEX	8
65  #elif (__riscv_xlen == 64)
66  #define R_ABSOLUTE	R_RISCV_64
67  #define SYM_INDEX	32
68  #else
69  #error unknown riscv target
70  #endif
71  #else
72  #error Need to add relocation awareness
73  #endif
74  
75  struct elf_rel {
76  	ulong *offset;
77  	ulong info;
78  };
79  
80  struct elf_rela {
81  	ulong *offset;
82  	ulong info;
83  	long addend;
84  };
85  
86  /*
87   * EFI runtime code lives in two stages. In the first stage, U-Boot and an EFI
88   * payload are running concurrently at the same time. In this mode, we can
89   * handle a good number of runtime callbacks
90   */
91  
92  /**
93   * efi_update_table_header_crc32() - Update crc32 in table header
94   *
95   * @table:	EFI table
96   */
efi_update_table_header_crc32(struct efi_table_hdr * table)97  void __efi_runtime efi_update_table_header_crc32(struct efi_table_hdr *table)
98  {
99  	table->crc32 = 0;
100  	table->crc32 = crc32(0, (const unsigned char *)table,
101  			     table->headersize);
102  }
103  
104  /**
105   * efi_reset_system_boottime() - reset system at boot time
106   *
107   * This function implements the ResetSystem() runtime service before
108   * SetVirtualAddressMap() is called.
109   *
110   * See the Unified Extensible Firmware Interface (UEFI) specification for
111   * details.
112   *
113   * @reset_type:		type of reset to perform
114   * @reset_status:	status code for the reset
115   * @data_size:		size of reset_data
116   * @reset_data:		information about the reset
117   */
efi_reset_system_boottime(enum efi_reset_type reset_type,efi_status_t reset_status,unsigned long data_size,void * reset_data)118  static void EFIAPI efi_reset_system_boottime(
119  			enum efi_reset_type reset_type,
120  			efi_status_t reset_status,
121  			unsigned long data_size, void *reset_data)
122  {
123  	struct efi_event *evt;
124  
125  	EFI_ENTRY("%d %lx %lx %p", reset_type, reset_status, data_size,
126  		  reset_data);
127  
128  	/* Notify reset */
129  	list_for_each_entry(evt, &efi_events, link) {
130  		if (evt->group &&
131  		    !guidcmp(evt->group,
132  			     &efi_guid_event_group_reset_system)) {
133  			efi_signal_event(evt, false);
134  			break;
135  		}
136  	}
137  	switch (reset_type) {
138  	case EFI_RESET_COLD:
139  	case EFI_RESET_WARM:
140  	case EFI_RESET_PLATFORM_SPECIFIC:
141  		do_reset(NULL, 0, 0, NULL);
142  		break;
143  	case EFI_RESET_SHUTDOWN:
144  #ifdef CONFIG_CMD_POWEROFF
145  		do_poweroff(NULL, 0, 0, NULL);
146  #endif
147  		break;
148  	}
149  
150  	while (1) { }
151  }
152  
153  /**
154   * efi_get_time_boottime() - get current time at boot time
155   *
156   * This function implements the GetTime runtime service before
157   * SetVirtualAddressMap() is called.
158   *
159   * See the Unified Extensible Firmware Interface (UEFI) specification
160   * for details.
161   *
162   * @time:		pointer to structure to receive current time
163   * @capabilities:	pointer to structure to receive RTC properties
164   * Returns:		status code
165   */
efi_get_time_boottime(struct efi_time * time,struct efi_time_cap * capabilities)166  static efi_status_t EFIAPI efi_get_time_boottime(
167  			struct efi_time *time,
168  			struct efi_time_cap *capabilities)
169  {
170  #ifdef CONFIG_DM_RTC
171  	efi_status_t ret = EFI_SUCCESS;
172  	int r;
173  	struct rtc_time tm;
174  	struct udevice *dev;
175  
176  	EFI_ENTRY("%p %p", time, capabilities);
177  
178  	if (!time) {
179  		ret = EFI_INVALID_PARAMETER;
180  		goto out;
181  	}
182  
183  	r = uclass_get_device(UCLASS_RTC, 0, &dev);
184  	if (!r)
185  		r = dm_rtc_get(dev, &tm);
186  	if (r) {
187  		ret = EFI_DEVICE_ERROR;
188  		goto out;
189  	}
190  
191  	memset(time, 0, sizeof(*time));
192  	time->year = tm.tm_year;
193  	time->month = tm.tm_mon;
194  	time->day = tm.tm_mday;
195  	time->hour = tm.tm_hour;
196  	time->minute = tm.tm_min;
197  	time->second = tm.tm_sec;
198  	time->daylight = EFI_TIME_ADJUST_DAYLIGHT;
199  	if (tm.tm_isdst > 0)
200  		time->daylight |= EFI_TIME_IN_DAYLIGHT;
201  	time->timezone = EFI_UNSPECIFIED_TIMEZONE;
202  
203  	if (capabilities) {
204  		/* Set reasonable dummy values */
205  		capabilities->resolution = 1;		/* 1 Hz */
206  		capabilities->accuracy = 100000000;	/* 100 ppm */
207  		capabilities->sets_to_zero = false;
208  	}
209  out:
210  	return EFI_EXIT(ret);
211  #else
212  	EFI_ENTRY("%p %p", time, capabilities);
213  	return EFI_EXIT(EFI_DEVICE_ERROR);
214  #endif
215  }
216  
217  
218  /**
219   * efi_reset_system() - reset system
220   *
221   * This function implements the ResetSystem() runtime service after
222   * SetVirtualAddressMap() is called. It only executes an endless loop.
223   * Boards may override the helpers below to implement reset functionality.
224   *
225   * See the Unified Extensible Firmware Interface (UEFI) specification for
226   * details.
227   *
228   * @reset_type:		type of reset to perform
229   * @reset_status:	status code for the reset
230   * @data_size:		size of reset_data
231   * @reset_data:		information about the reset
232   */
efi_reset_system(enum efi_reset_type reset_type,efi_status_t reset_status,unsigned long data_size,void * reset_data)233  void __weak __efi_runtime EFIAPI efi_reset_system(
234  			enum efi_reset_type reset_type,
235  			efi_status_t reset_status,
236  			unsigned long data_size, void *reset_data)
237  {
238  	/* Nothing we can do */
239  	while (1) { }
240  }
241  
242  /**
243   * efi_reset_system_init() - initialize the reset driver
244   *
245   * Boards may override this function to initialize the reset driver.
246   */
efi_reset_system_init(void)247  efi_status_t __weak efi_reset_system_init(void)
248  {
249  	return EFI_SUCCESS;
250  }
251  
252  /**
253   * efi_get_time() - get current time
254   *
255   * This function implements the GetTime runtime service after
256   * SetVirtualAddressMap() is called. As the U-Boot driver are not available
257   * anymore only an error code is returned.
258   *
259   * See the Unified Extensible Firmware Interface (UEFI) specification
260   * for details.
261   *
262   * @time:		pointer to structure to receive current time
263   * @capabilities:	pointer to structure to receive RTC properties
264   * Returns:		status code
265   */
efi_get_time(struct efi_time * time,struct efi_time_cap * capabilities)266  efi_status_t __weak __efi_runtime EFIAPI efi_get_time(
267  			struct efi_time *time,
268  			struct efi_time_cap *capabilities)
269  {
270  	/* Nothing we can do */
271  	return EFI_DEVICE_ERROR;
272  }
273  
274  struct efi_runtime_detach_list_struct {
275  	void *ptr;
276  	void *patchto;
277  };
278  
279  static const struct efi_runtime_detach_list_struct efi_runtime_detach_list[] = {
280  	{
281  		/* do_reset is gone */
282  		.ptr = &efi_runtime_services.reset_system,
283  		.patchto = efi_reset_system,
284  	}, {
285  		/* invalidate_*cache_all are gone */
286  		.ptr = &efi_runtime_services.set_virtual_address_map,
287  		.patchto = &efi_unimplemented,
288  	}, {
289  		/* RTC accessors are gone */
290  		.ptr = &efi_runtime_services.get_time,
291  		.patchto = &efi_get_time,
292  	}, {
293  		/* Clean up system table */
294  		.ptr = &systab.con_in,
295  		.patchto = NULL,
296  	}, {
297  		/* Clean up system table */
298  		.ptr = &systab.con_out,
299  		.patchto = NULL,
300  	}, {
301  		/* Clean up system table */
302  		.ptr = &systab.std_err,
303  		.patchto = NULL,
304  	}, {
305  		/* Clean up system table */
306  		.ptr = &systab.boottime,
307  		.patchto = NULL,
308  	}, {
309  		.ptr = &efi_runtime_services.get_variable,
310  		.patchto = &efi_device_error,
311  	}, {
312  		.ptr = &efi_runtime_services.get_next_variable_name,
313  		.patchto = &efi_device_error,
314  	}, {
315  		.ptr = &efi_runtime_services.set_variable,
316  		.patchto = &efi_device_error,
317  	}
318  };
319  
efi_runtime_tobedetached(void * p)320  static bool efi_runtime_tobedetached(void *p)
321  {
322  	int i;
323  
324  	for (i = 0; i < ARRAY_SIZE(efi_runtime_detach_list); i++)
325  		if (efi_runtime_detach_list[i].ptr == p)
326  			return true;
327  
328  	return false;
329  }
330  
efi_runtime_detach(ulong offset)331  static void efi_runtime_detach(ulong offset)
332  {
333  	int i;
334  	ulong patchoff = offset - (ulong)gd->relocaddr;
335  
336  	for (i = 0; i < ARRAY_SIZE(efi_runtime_detach_list); i++) {
337  		ulong patchto = (ulong)efi_runtime_detach_list[i].patchto;
338  		ulong *p = efi_runtime_detach_list[i].ptr;
339  		ulong newaddr = patchto ? (patchto + patchoff) : 0;
340  
341  		debug("%s: Setting %p to %lx\n", __func__, p, newaddr);
342  		*p = newaddr;
343  	}
344  
345  	/* Update CRC32 */
346  	efi_update_table_header_crc32(&efi_runtime_services.hdr);
347  }
348  
349  /* Relocate EFI runtime to uboot_reloc_base = offset */
efi_runtime_relocate(ulong offset,struct efi_mem_desc * map)350  void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map)
351  {
352  #ifdef IS_RELA
353  	struct elf_rela *rel = (void*)&__efi_runtime_rel_start;
354  #else
355  	struct elf_rel *rel = (void*)&__efi_runtime_rel_start;
356  	static ulong lastoff = CONFIG_SYS_TEXT_BASE;
357  #endif
358  
359  	debug("%s: Relocating to offset=%lx\n", __func__, offset);
360  	for (; (ulong)rel < (ulong)&__efi_runtime_rel_stop; rel++) {
361  		ulong base = CONFIG_SYS_TEXT_BASE;
362  		ulong *p;
363  		ulong newaddr;
364  
365  		p = (void*)((ulong)rel->offset - base) + gd->relocaddr;
366  
367  		debug("%s: rel->info=%#lx *p=%#lx rel->offset=%p\n", __func__,
368  		      rel->info, *p, rel->offset);
369  
370  		switch (rel->info & R_MASK) {
371  		case R_RELATIVE:
372  #ifdef IS_RELA
373  		newaddr = rel->addend + offset - CONFIG_SYS_TEXT_BASE;
374  #else
375  		newaddr = *p - lastoff + offset;
376  #endif
377  			break;
378  #ifdef R_ABSOLUTE
379  		case R_ABSOLUTE: {
380  			ulong symidx = rel->info >> SYM_INDEX;
381  			extern struct dyn_sym __dyn_sym_start[];
382  			newaddr = __dyn_sym_start[symidx].addr + offset;
383  #ifdef IS_RELA
384  			newaddr -= CONFIG_SYS_TEXT_BASE;
385  #endif
386  			break;
387  		}
388  #endif
389  		default:
390  			if (!efi_runtime_tobedetached(p))
391  				printf("%s: Unknown relocation type %llx\n",
392  				       __func__, rel->info & R_MASK);
393  			continue;
394  		}
395  
396  		/* Check if the relocation is inside bounds */
397  		if (map && ((newaddr < map->virtual_start) ||
398  		    newaddr > (map->virtual_start +
399  			      (map->num_pages << EFI_PAGE_SHIFT)))) {
400  			if (!efi_runtime_tobedetached(p))
401  				printf("%s: Relocation at %p is out of "
402  				       "range (%lx)\n", __func__, p, newaddr);
403  			continue;
404  		}
405  
406  		debug("%s: Setting %p to %lx\n", __func__, p, newaddr);
407  		*p = newaddr;
408  		flush_dcache_range((ulong)p & ~(EFI_CACHELINE_SIZE - 1),
409  			ALIGN((ulong)&p[1], EFI_CACHELINE_SIZE));
410  	}
411  
412  #ifndef IS_RELA
413  	lastoff = offset;
414  #endif
415  
416          invalidate_icache_all();
417  }
418  
419  /**
420   * efi_set_virtual_address_map() - change from physical to virtual mapping
421   *
422   * This function implements the SetVirtualAddressMap() runtime service.
423   *
424   * See the Unified Extensible Firmware Interface (UEFI) specification for
425   * details.
426   *
427   * @memory_map_size:	size of the virtual map
428   * @descriptor_size:	size of an entry in the map
429   * @descriptor_version:	version of the map entries
430   * @virtmap:		virtual address mapping information
431   * Return:		status code
432   */
efi_set_virtual_address_map(unsigned long memory_map_size,unsigned long descriptor_size,uint32_t descriptor_version,struct efi_mem_desc * virtmap)433  static efi_status_t EFIAPI efi_set_virtual_address_map(
434  			unsigned long memory_map_size,
435  			unsigned long descriptor_size,
436  			uint32_t descriptor_version,
437  			struct efi_mem_desc *virtmap)
438  {
439  	int n = memory_map_size / descriptor_size;
440  	int i;
441  	int rt_code_sections = 0;
442  
443  	EFI_ENTRY("%lx %lx %x %p", memory_map_size, descriptor_size,
444  		  descriptor_version, virtmap);
445  
446  	/*
447  	 * TODO:
448  	 * Further down we are cheating. While really we should implement
449  	 * SetVirtualAddressMap() events and ConvertPointer() to allow
450  	 * dynamically loaded drivers to expose runtime services, we don't
451  	 * today.
452  	 *
453  	 * So let's ensure we see exactly one single runtime section, as
454  	 * that is the built-in one. If we see more (or less), someone must
455  	 * have tried adding or removing to that which we don't support yet.
456  	 * In that case, let's better fail rather than expose broken runtime
457  	 * services.
458  	 */
459  	for (i = 0; i < n; i++) {
460  		struct efi_mem_desc *map = (void*)virtmap +
461  					   (descriptor_size * i);
462  
463  		if (map->type == EFI_RUNTIME_SERVICES_CODE)
464  			rt_code_sections++;
465  	}
466  
467  	if (rt_code_sections != 1) {
468  		/*
469  		 * We expose exactly one single runtime code section, so
470  		 * something is definitely going wrong.
471  		 */
472  		return EFI_EXIT(EFI_INVALID_PARAMETER);
473  	}
474  
475  	/* Rebind mmio pointers */
476  	for (i = 0; i < n; i++) {
477  		struct efi_mem_desc *map = (void*)virtmap +
478  					   (descriptor_size * i);
479  		struct list_head *lhandle;
480  		efi_physical_addr_t map_start = map->physical_start;
481  		efi_physical_addr_t map_len = map->num_pages << EFI_PAGE_SHIFT;
482  		efi_physical_addr_t map_end = map_start + map_len;
483  		u64 off = map->virtual_start - map_start;
484  
485  		/* Adjust all mmio pointers in this region */
486  		list_for_each(lhandle, &efi_runtime_mmio) {
487  			struct efi_runtime_mmio_list *lmmio;
488  
489  			lmmio = list_entry(lhandle,
490  					   struct efi_runtime_mmio_list,
491  					   link);
492  			if ((map_start <= lmmio->paddr) &&
493  			    (map_end >= lmmio->paddr)) {
494  				uintptr_t new_addr = lmmio->paddr + off;
495  				*lmmio->ptr = (void *)new_addr;
496  			}
497  		}
498  		if ((map_start <= (uintptr_t)systab.tables) &&
499  		    (map_end >= (uintptr_t)systab.tables)) {
500  			char *ptr = (char *)systab.tables;
501  
502  			ptr += off;
503  			systab.tables = (struct efi_configuration_table *)ptr;
504  		}
505  	}
506  
507  	/* Move the actual runtime code over */
508  	for (i = 0; i < n; i++) {
509  		struct efi_mem_desc *map;
510  
511  		map = (void*)virtmap + (descriptor_size * i);
512  		if (map->type == EFI_RUNTIME_SERVICES_CODE) {
513  			ulong new_offset = map->virtual_start -
514  					   map->physical_start + gd->relocaddr;
515  
516  			efi_runtime_relocate(new_offset, map);
517  			/* Once we're virtual, we can no longer handle
518  			   complex callbacks */
519  			efi_runtime_detach(new_offset);
520  			return EFI_EXIT(EFI_SUCCESS);
521  		}
522  	}
523  
524  	return EFI_EXIT(EFI_INVALID_PARAMETER);
525  }
526  
527  /**
528   * efi_add_runtime_mmio() - add memory-mapped IO region
529   *
530   * This function adds a memory-mapped IO region to the memory map to make it
531   * available at runtime.
532   *
533   * @mmio_ptr:		pointer to a pointer to the start of the memory-mapped
534   *			IO region
535   * @len:		size of the memory-mapped IO region
536   * Returns:		status code
537   */
efi_add_runtime_mmio(void * mmio_ptr,u64 len)538  efi_status_t efi_add_runtime_mmio(void *mmio_ptr, u64 len)
539  {
540  	struct efi_runtime_mmio_list *newmmio;
541  	u64 pages = (len + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
542  	uint64_t addr = *(uintptr_t *)mmio_ptr;
543  	uint64_t retaddr;
544  
545  	retaddr = efi_add_memory_map(addr, pages, EFI_MMAP_IO, false);
546  	if (retaddr != addr)
547  		return EFI_OUT_OF_RESOURCES;
548  
549  	newmmio = calloc(1, sizeof(*newmmio));
550  	if (!newmmio)
551  		return EFI_OUT_OF_RESOURCES;
552  	newmmio->ptr = mmio_ptr;
553  	newmmio->paddr = *(uintptr_t *)mmio_ptr;
554  	newmmio->len = len;
555  	list_add_tail(&newmmio->link, &efi_runtime_mmio);
556  
557  	return EFI_SUCCESS;
558  }
559  
560  /*
561   * In the second stage, U-Boot has disappeared. To isolate our runtime code
562   * that at this point still exists from the rest, we put it into a special
563   * section.
564   *
565   *        !!WARNING!!
566   *
567   * This means that we can not rely on any code outside of this file in any
568   * function or variable below this line.
569   *
570   * Please keep everything fully self-contained and annotated with
571   * __efi_runtime and __efi_runtime_data markers.
572   */
573  
574  /*
575   * Relocate the EFI runtime stub to a different place. We need to call this
576   * the first time we expose the runtime interface to a user and on set virtual
577   * address map calls.
578   */
579  
580  /**
581   * efi_unimplemented() - replacement function, returns EFI_UNSUPPORTED
582   *
583   * This function is used after SetVirtualAddressMap() is called as replacement
584   * for services that are not available anymore due to constraints of the U-Boot
585   * implementation.
586   *
587   * Return:	EFI_UNSUPPORTED
588   */
efi_unimplemented(void)589  static efi_status_t __efi_runtime EFIAPI efi_unimplemented(void)
590  {
591  	return EFI_UNSUPPORTED;
592  }
593  
594  /**
595   * efi_device_error() - replacement function, returns EFI_DEVICE_ERROR
596   *
597   * This function is used after SetVirtualAddressMap() is called as replacement
598   * for services that are not available anymore due to constraints of the U-Boot
599   * implementation.
600   *
601   * Return:	EFI_DEVICE_ERROR
602   */
efi_device_error(void)603  static efi_status_t __efi_runtime EFIAPI efi_device_error(void)
604  {
605  	return EFI_DEVICE_ERROR;
606  }
607  
608  /**
609   * efi_invalid_parameter() - replacement function, returns EFI_INVALID_PARAMETER
610   *
611   * This function is used after SetVirtualAddressMap() is called as replacement
612   * for services that are not available anymore due to constraints of the U-Boot
613   * implementation.
614   *
615   * Return:	EFI_INVALID_PARAMETER
616   */
efi_invalid_parameter(void)617  static efi_status_t __efi_runtime EFIAPI efi_invalid_parameter(void)
618  {
619  	return EFI_INVALID_PARAMETER;
620  }
621  
622  /**
623   * efi_update_capsule() - process information from operating system
624   *
625   * This function implements the UpdateCapsule() runtime service.
626   *
627   * See the Unified Extensible Firmware Interface (UEFI) specification for
628   * details.
629   *
630   * @capsule_header_array:	pointer to array of virtual pointers
631   * @capsule_count:		number of pointers in capsule_header_array
632   * @scatter_gather_list:	pointer to arry of physical pointers
633   * Returns:			status code
634   */
efi_update_capsule(struct efi_capsule_header ** capsule_header_array,efi_uintn_t capsule_count,u64 scatter_gather_list)635  efi_status_t __efi_runtime EFIAPI efi_update_capsule(
636  			struct efi_capsule_header **capsule_header_array,
637  			efi_uintn_t capsule_count,
638  			u64 scatter_gather_list)
639  {
640  	return EFI_UNSUPPORTED;
641  }
642  
643  /**
644   * efi_query_capsule_caps() - check if capsule is supported
645   *
646   * This function implements the QueryCapsuleCapabilities() runtime service.
647   *
648   * See the Unified Extensible Firmware Interface (UEFI) specification for
649   * details.
650   *
651   * @capsule_header_array:	pointer to array of virtual pointers
652   * @capsule_count:		number of pointers in capsule_header_array
653   * @maximum_capsule_size:	maximum capsule size
654   * @reset_type:			type of reset needed for capsule update
655   * Returns:			status code
656   */
efi_query_capsule_caps(struct efi_capsule_header ** capsule_header_array,efi_uintn_t capsule_count,u64 * maximum_capsule_size,u32 * reset_type)657  efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps(
658  			struct efi_capsule_header **capsule_header_array,
659  			efi_uintn_t capsule_count,
660  			u64 *maximum_capsule_size,
661  			u32 *reset_type)
662  {
663  	return EFI_UNSUPPORTED;
664  }
665  
666  /**
667   * efi_query_variable_info() - get information about EFI variables
668   *
669   * This function implements the QueryVariableInfo() runtime service.
670   *
671   * See the Unified Extensible Firmware Interface (UEFI) specification for
672   * details.
673   *
674   * @attributes:				bitmask to select variables to be
675   *					queried
676   * @maximum_variable_storage_size:	maximum size of storage area for the
677   *					selected variable types
678   * @remaining_variable_storage_size:	remaining size of storage are for the
679   *					selected variable types
680   * @maximum_variable_size:		maximum size of a variable of the
681   *					selected type
682   * Returns:				status code
683   */
efi_query_variable_info(u32 attributes,u64 * maximum_variable_storage_size,u64 * remaining_variable_storage_size,u64 * maximum_variable_size)684  efi_status_t __efi_runtime EFIAPI efi_query_variable_info(
685  			u32 attributes,
686  			u64 *maximum_variable_storage_size,
687  			u64 *remaining_variable_storage_size,
688  			u64 *maximum_variable_size)
689  {
690  	return EFI_UNSUPPORTED;
691  }
692  
693  struct efi_runtime_services __efi_runtime_data efi_runtime_services = {
694  	.hdr = {
695  		.signature = EFI_RUNTIME_SERVICES_SIGNATURE,
696  		.revision = EFI_SPECIFICATION_VERSION,
697  		.headersize = sizeof(struct efi_runtime_services),
698  	},
699  	.get_time = &efi_get_time_boottime,
700  	.set_time = (void *)&efi_device_error,
701  	.get_wakeup_time = (void *)&efi_unimplemented,
702  	.set_wakeup_time = (void *)&efi_unimplemented,
703  	.set_virtual_address_map = &efi_set_virtual_address_map,
704  	.convert_pointer = (void *)&efi_invalid_parameter,
705  	.get_variable = efi_get_variable,
706  	.get_next_variable_name = efi_get_next_variable_name,
707  	.set_variable = efi_set_variable,
708  	.get_next_high_mono_count = (void *)&efi_device_error,
709  	.reset_system = &efi_reset_system_boottime,
710  	.update_capsule = efi_update_capsule,
711  	.query_capsule_caps = efi_query_capsule_caps,
712  	.query_variable_info = efi_query_variable_info,
713  };
714