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