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