1 /*        $NetBSD: efi_machdep.c,v 1.6 2023/05/22 16:28:07 riastradh Exp $      */
2 
3 /*-
4  * Copyright (c) 2016 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: efi_machdep.c,v 1.6 2023/05/22 16:28:07 riastradh Exp $");
31 
32 #include "efi.h"
33 #include "opt_efi.h"
34 
35 #include <sys/kmem.h>
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/uuid.h>
39 
40 #include <uvm/uvm_extern.h>
41 
42 #include <machine/bootinfo.h>
43 #include <machine/pmap_private.h>
44 
45 #include <x86/bus_defs.h>
46 #include <x86/bus_funcs.h>
47 #include <x86/efi.h>
48 #include <x86/fpu.h>
49 
50 #include <dev/mm.h>
51 #if NPCI > 0
52 #include <dev/pci/pcivar.h> /* for pci_mapreg_map_enable_decode */
53 #endif
54 
55 const struct uuid EFI_UUID_ACPI20 = EFI_TABLE_ACPI20;
56 const struct uuid EFI_UUID_ACPI10 = EFI_TABLE_ACPI10;
57 const struct uuid EFI_UUID_SMBIOS = EFI_TABLE_SMBIOS;
58 const struct uuid EFI_UUID_SMBIOS3 = EFI_TABLE_SMBIOS3;
59 
60 static vaddr_t      efi_getva(paddr_t);
61 static void         efi_relva(paddr_t, vaddr_t);
62 struct efi_cfgtbl *efi_getcfgtblhead(void);
63 void                efi_aprintcfgtbl(void);
64 void                efi_aprintuuid(const struct uuid *);
65 bool                efi_uuideq(const struct uuid *, const struct uuid *);
66 
67 static bool efi_is32x64 = false;
68 static paddr_t efi_systbl_pa;
69 static struct efi_systbl *efi_systbl_va = NULL;
70 static struct efi_cfgtbl *efi_cfgtblhead_va = NULL;
71 static struct efi_e820memmap {
72           struct btinfo_memmap bim;
73           struct bi_memmap_entry entry[VM_PHYSSEG_MAX - 1];
74 } efi_e820memmap;
75 
76 #ifdef EFI_RUNTIME
77 
78 #include <dev/efivar.h>
79 
80 #include <uvm/uvm_extern.h>
81 
82 #if !(NEFI > 0)
83 #error options EFI_RUNTIME makes no sense without pseudo-device efi.
84 #endif
85 
86 struct pmap *efi_runtime_pmap __read_mostly;
87 
88 static kmutex_t efi_runtime_lock __cacheline_aligned;
89 static struct efi_rt efi_rt __read_mostly;
90 static struct efi_ops efi_runtime_ops __read_mostly;
91 
92 static void efi_runtime_init(void);
93 
94 #endif
95 
96 /*
97  * Map a physical address (PA) to a newly allocated virtual address (VA).
98  * The VA must be freed using efi_relva().
99  */
100 static vaddr_t
efi_getva(paddr_t pa)101 efi_getva(paddr_t pa)
102 {
103           vaddr_t va;
104           int rv;
105 
106           rv = _x86_memio_map(x86_bus_space_mem, pa,
107               PAGE_SIZE, 0, (bus_space_handle_t *)&va);
108           if (rv != 0) {
109                     aprint_debug("efi: unable to allocate va\n");
110                     return 0;
111           }
112 
113           return va;
114 }
115 
116 /*
117  * Free a virtual address (VA) allocated using efi_getva().
118  */
119 static void
efi_relva(paddr_t pa,vaddr_t va)120 efi_relva(paddr_t pa, vaddr_t va)
121 {
122           (void)_x86_memio_unmap(x86_bus_space_mem, (bus_space_handle_t)va,
123               PAGE_SIZE, NULL);
124 }
125 
126 /*
127  * Test if 2 UUIDs matches.
128  */
129 bool
efi_uuideq(const struct uuid * a,const struct uuid * b)130 efi_uuideq(const struct uuid * a, const struct uuid * b)
131 {
132           return !memcmp(a, b, sizeof(struct uuid));
133 }
134 
135 /*
136  * Print an UUID in a human-readable manner.
137  */
138 void
efi_aprintuuid(const struct uuid * uuid)139 efi_aprintuuid(const struct uuid * uuid)
140 {
141           int i;
142 
143           aprint_debug(" %08" PRIx32 "", uuid->time_low);
144           aprint_debug("-%04" PRIx16 "", uuid->time_mid);
145           aprint_debug("-%04" PRIx16 "", uuid->time_hi_and_version);
146           aprint_debug("-%02" PRIx8 "", uuid->clock_seq_hi_and_reserved);
147           aprint_debug("%02" PRIx8 "", uuid->clock_seq_low);
148           aprint_debug("-");
149           for (i = 0; i < _UUID_NODE_LEN; i++) {
150                     aprint_debug("%02" PRIx8 "", uuid->node[i]);
151           }
152           /* If known, also print the human-readable name */
153           if (efi_uuideq(uuid, &EFI_UUID_ACPI20)) {
154                     aprint_debug(" ACPI 2.0");
155           } else if (efi_uuideq(uuid, &EFI_UUID_ACPI10)) {
156                     aprint_debug(" ACPI 1.0");
157           } else if (efi_uuideq(uuid, &EFI_UUID_SMBIOS)) {
158                     aprint_debug(" SMBIOS");
159           } else if (efi_uuideq(uuid, &EFI_UUID_SMBIOS3)) {
160                     aprint_debug(" SMBIOS3");
161           }
162 }
163 
164 /*
165  * Return the VA of the cfgtbl. Must be freed using efi_relva().
166  */
167 struct efi_cfgtbl *
efi_getcfgtblhead(void)168 efi_getcfgtblhead(void)
169 {
170           paddr_t   pa;
171           vaddr_t   va;
172 
173           if (efi_cfgtblhead_va != NULL)
174                     return efi_cfgtblhead_va;
175 
176           if (efi_is32x64) {
177 #if defined(__amd64__)
178                     struct efi_systbl32 *systbl32 = (void *) efi_systbl_va;
179                     pa = systbl32->st_cfgtbl;
180 #elif defined(__i386__)
181                     struct efi_systbl64 *systbl64 = (void *) efi_systbl_va;
182                     if (systbl64->st_cfgtbl & 0xffffffff00000000ULL)
183                               return NULL;
184                     pa = (paddr_t) systbl64->st_cfgtbl;
185 #endif
186           } else
187                     pa = (paddr_t)(u_long) efi_systbl_va->st_cfgtbl;
188           aprint_debug("efi: cfgtbl at pa %" PRIxPADDR "\n", pa);
189           va = efi_getva(pa);
190           aprint_debug("efi: cfgtbl mapped at va %" PRIxVADDR "\n", va);
191           efi_cfgtblhead_va = (struct efi_cfgtbl *) va;
192           efi_aprintcfgtbl();
193 
194           return efi_cfgtblhead_va;
195 }
196 
197 /*
198  * Print the config tables.
199  */
200 void
efi_aprintcfgtbl(void)201 efi_aprintcfgtbl(void)
202 {
203           struct efi_cfgtbl *ct;
204           unsigned long count;
205 
206           if (efi_is32x64) {
207 #if defined(__amd64__)
208                     struct efi_systbl32 *systbl32 = (void *) efi_systbl_va;
209                     struct efi_cfgtbl32 *ct32 = (void *) efi_cfgtblhead_va;
210 
211                     count = systbl32->st_entries;
212                     aprint_debug("efi: %lu cfgtbl entries:\n", count);
213                     for (; count; count--, ct32++) {
214                               aprint_debug("efi: %08" PRIx32, ct32->ct_data);
215                               efi_aprintuuid(&ct32->ct_uuid);
216                               aprint_debug("\n");
217                     }
218 #elif defined(__i386__)
219                     struct efi_systbl64 *systbl64 = (void *) efi_systbl_va;
220                     struct efi_cfgtbl64 *ct64 = (void *) efi_cfgtblhead_va;
221                     uint64_t count64 = systbl64->st_entries;
222 
223                     aprint_debug("efi: %" PRIu64 " cfgtbl entries:\n", count64);
224                     for (; count64; count64--, ct64++) {
225                               aprint_debug("efi: %016" PRIx64, ct64->ct_data);
226                               efi_aprintuuid(&ct64->ct_uuid);
227                               aprint_debug("\n");
228                     }
229 #endif
230                     return;
231           }
232 
233           ct = efi_cfgtblhead_va;
234           count = efi_systbl_va->st_entries;
235           aprint_debug("efi: %lu cfgtbl entries:\n", count);
236           for (; count; count--, ct++) {
237                     aprint_debug("efi: %p", ct->ct_data);
238                     efi_aprintuuid(&ct->ct_uuid);
239                     aprint_debug("\n");
240           }
241 }
242 
243 /*
244  * Return the VA of the config table with the given UUID if found.
245  * The VA must be freed using efi_relva().
246  */
247 void *
efi_getcfgtbl(const struct uuid * uuid)248 efi_getcfgtbl(const struct uuid * uuid)
249 {
250           paddr_t pa;
251           vaddr_t va;
252 
253           pa = efi_getcfgtblpa(uuid);
254           if (pa == 0)
255                     return NULL;
256           va = efi_getva(pa);
257           return (void *) va;
258 }
259 
260 /*
261  * Return the PA of the first config table.
262  */
263 paddr_t
efi_getcfgtblpa(const struct uuid * uuid)264 efi_getcfgtblpa(const struct uuid * uuid)
265 {
266           struct efi_cfgtbl *ct;
267           unsigned long count;
268 
269           if (efi_is32x64) {
270 #if defined(__amd64__)
271                     struct efi_systbl32 *systbl32 = (void *) efi_systbl_va;
272                     struct efi_cfgtbl32 *ct32 = (void *) efi_cfgtblhead_va;
273 
274                     count = systbl32->st_entries;
275                     for (; count; count--, ct32++)
276                               if (efi_uuideq(&ct32->ct_uuid, uuid))
277                                         return ct32->ct_data;
278 #elif defined(__i386__)
279                     struct efi_systbl64 *systbl64 = (void *) efi_systbl_va;
280                     struct efi_cfgtbl64 *ct64 = (void *) efi_cfgtblhead_va;
281                     uint64_t count64 = systbl64->st_entries;
282 
283                     for (; count64; count64--, ct64++)
284                               if (efi_uuideq(&ct64->ct_uuid, uuid))
285                                         if (!(ct64->ct_data & 0xffffffff00000000ULL))
286                                                   return ct64->ct_data;
287 #endif
288                     return 0; /* Not found. */
289           }
290 
291           ct = efi_cfgtblhead_va;
292           count = efi_systbl_va->st_entries;
293           for (; count; count--, ct++)
294                     if (efi_uuideq(&ct->ct_uuid, uuid))
295                               return (paddr_t)(u_long) ct->ct_data;
296 
297           return 0; /* Not found. */
298 }
299 
300 /* Return the PA of the EFI System Table. */
301 paddr_t
efi_getsystblpa(void)302 efi_getsystblpa(void)
303 {
304           struct btinfo_efi *bi;
305           paddr_t   pa;
306 
307           bi = lookup_bootinfo(BTINFO_EFI);
308           if (bi == NULL) {
309                     /* Unable to locate the EFI System Table. */
310                     return 0;
311           }
312           if (sizeof(paddr_t) == 4 &&   /* XXX i386 with PAE */
313               (bi->systblpa & 0xffffffff00000000ULL)) {
314                     /* Unable to access EFI System Table. */
315                     return 0;
316           }
317           if (bi->common.len > 16 && (bi->flags & BI_EFI_32BIT)) {
318                     /* boot from 32bit UEFI */
319 #if defined(__amd64__)
320                     efi_is32x64 = true;
321 #endif
322           } else {
323                     /* boot from 64bit UEFI */
324 #if defined(__i386__)
325                     efi_is32x64 = true;
326 #endif
327           }
328           pa = (paddr_t) bi->systblpa;
329           return pa;
330 }
331 
332 /*
333  * Return a pointer to the EFI System Table. The pointer must be freed using
334  * efi_relva().
335  */
336 struct efi_systbl *
efi_getsystbl(void)337 efi_getsystbl(void)
338 {
339           paddr_t pa;
340           vaddr_t va;
341           struct efi_systbl *systbl;
342 
343           if (efi_systbl_va)
344                     return efi_systbl_va;
345 
346           pa = efi_getsystblpa();
347           if (pa == 0)
348                     return NULL;
349 
350           aprint_normal("efi: systbl at pa %" PRIxPADDR "\n", pa);
351           efi_systbl_pa = pa;
352           va = efi_getva(pa);
353           aprint_debug("efi: systbl mapped at va %" PRIxVADDR "\n", va);
354 
355           if (efi_is32x64) {
356 #if defined(__amd64__)
357                     struct efi_systbl32 *systbl32 = (struct efi_systbl32 *) va;
358 
359                     /* XXX Check the signature and the CRC32 */
360                     aprint_debug("efi: signature %" PRIx64 " revision %" PRIx32
361                         " crc32 %" PRIx32 "\n", systbl32->st_hdr.th_sig,
362                         systbl32->st_hdr.th_rev, systbl32->st_hdr.th_crc32);
363                     aprint_debug("efi: firmware revision %" PRIx32 "\n",
364                         systbl32->st_fwrev);
365                     /*
366                      * XXX Also print fwvendor, which is an UCS-2 string (use
367                      * some UTF-16 routine?)
368                      */
369                     aprint_debug("efi: runtime services at pa 0x%08" PRIx32 "\n",
370                         systbl32->st_rt);
371                     aprint_debug("efi: boot services at pa 0x%08" PRIx32 "\n",
372                         systbl32->st_bs);
373 
374                     efi_systbl_va = (struct efi_systbl *) systbl32;
375 #elif defined(__i386__)
376                     struct efi_systbl64 *systbl64 = (struct efi_systbl64 *) va;
377 
378                     /* XXX Check the signature and the CRC32 */
379                     aprint_debug("efi: signature %" PRIx64 " revision %" PRIx32
380                         " crc32 %" PRIx32 "\n", systbl64->st_hdr.th_sig,
381                         systbl64->st_hdr.th_rev, systbl64->st_hdr.th_crc32);
382                     aprint_debug("efi: firmware revision %" PRIx32 "\n",
383                         systbl64->st_fwrev);
384                     /*
385                      * XXX Also print fwvendor, which is an UCS-2 string (use
386                      * some UTF-16 routine?)
387                      */
388                     aprint_debug("efi: runtime services at pa 0x%016" PRIx64 "\n",
389                         systbl64->st_rt);
390                     aprint_debug("efi: boot services at pa 0x%016" PRIx64 "\n",
391                         systbl64->st_bs);
392 
393                     efi_systbl_va = (struct efi_systbl *) systbl64;
394 #endif
395                     return efi_systbl_va;
396           }
397 
398           systbl = (struct efi_systbl *) va;
399           /* XXX Check the signature and the CRC32 */
400           aprint_debug("efi: signature %" PRIx64 " revision %" PRIx32
401               " crc32 %" PRIx32 "\n", systbl->st_hdr.th_sig,
402               systbl->st_hdr.th_rev, systbl->st_hdr.th_crc32);
403           aprint_debug("efi: firmware revision %" PRIx32 "\n", systbl->st_fwrev);
404           /*
405            * XXX Also print fwvendor, which is an UCS-2 string (use
406            * some UTF-16 routine?)
407            */
408           aprint_debug("efi: runtime services at pa %p\n", systbl->st_rt);
409           aprint_debug("efi: boot services at pa %p\n", systbl->st_bs);
410 
411           efi_systbl_va = systbl;
412           return efi_systbl_va;
413 }
414 
415 /*
416  * EFI is available if we are able to locate the EFI System Table.
417  */
418 void
efi_init(void)419 efi_init(void)
420 {
421 
422           if (efi_getsystbl() == NULL) {
423                     aprint_debug("efi: missing or invalid systbl\n");
424                     bootmethod_efi = false;
425                     return;
426           }
427           if (efi_getcfgtblhead() == NULL) {
428                     aprint_debug("efi: missing or invalid cfgtbl\n");
429                     efi_relva(efi_systbl_pa, (vaddr_t) efi_systbl_va);
430                     bootmethod_efi = false;
431                     return;
432           }
433           bootmethod_efi = true;
434 #if NPCI > 0
435           pci_mapreg_map_enable_decode = true; /* PR port-amd64/53286 */
436 #endif
437 
438 #ifdef EFI_RUNTIME
439           efi_runtime_init();
440 #endif
441 }
442 
443 bool
efi_probe(void)444 efi_probe(void)
445 {
446 
447           return bootmethod_efi;
448 }
449 
450 int
efi_getbiosmemtype(uint32_t type,uint64_t attr)451 efi_getbiosmemtype(uint32_t type, uint64_t attr)
452 {
453 
454           switch (type) {
455           case EFI_MD_TYPE_CODE:
456           case EFI_MD_TYPE_DATA:
457           case EFI_MD_TYPE_BS_CODE:
458           case EFI_MD_TYPE_BS_DATA:
459           case EFI_MD_TYPE_FREE:
460                     return (attr & EFI_MD_ATTR_WB) ? BIM_Memory : BIM_Reserved;
461 
462           case EFI_MD_TYPE_RECLAIM:
463                     return BIM_ACPI;
464 
465           case EFI_MD_TYPE_FIRMWARE:
466                     return BIM_NVS;
467 
468           case EFI_MD_TYPE_PMEM:
469                     return BIM_PMEM;
470 
471           case EFI_MD_TYPE_NULL:
472           case EFI_MD_TYPE_RT_CODE:
473           case EFI_MD_TYPE_RT_DATA:
474           case EFI_MD_TYPE_BAD:
475           case EFI_MD_TYPE_IOMEM:
476           case EFI_MD_TYPE_IOPORT:
477           case EFI_MD_TYPE_PALCODE:
478           default:
479                     return BIM_Reserved;
480           }
481 }
482 
483 const char *
efi_getmemtype_str(uint32_t type)484 efi_getmemtype_str(uint32_t type)
485 {
486           static const char *efimemtypes[] = {
487                     "Reserved",
488                     "LoaderCode",
489                     "LoaderData",
490                     "BootServicesCode",
491                     "BootServicesData",
492                     "RuntimeServicesCode",
493                     "RuntimeServicesData",
494                     "ConventionalMemory",
495                     "UnusableMemory",
496                     "ACPIReclaimMemory",
497                     "ACPIMemoryNVS",
498                     "MemoryMappedIO",
499                     "MemoryMappedIOPortSpace",
500                     "PalCode",
501                     "PersistentMemory",
502           };
503 
504           if (type < __arraycount(efimemtypes))
505                     return efimemtypes[type];
506           return "unknown";
507 }
508 
509 struct btinfo_memmap *
efi_get_e820memmap(void)510 efi_get_e820memmap(void)
511 {
512           struct btinfo_efimemmap *efimm;
513           struct bi_memmap_entry *entry;
514           struct efi_md *md;
515           uint64_t addr, size;
516           uint64_t start_addr = 0;        /* XXX gcc -Os: maybe-uninitialized */
517           uint64_t end_addr = 0;          /* XXX gcc -Os: maybe-uninitialized */
518           uint32_t i;
519           int n, type, seg_type = -1;
520 
521           if (efi_e820memmap.bim.common.type == BTINFO_MEMMAP)
522                     return &efi_e820memmap.bim;
523 
524           efimm = lookup_bootinfo(BTINFO_EFIMEMMAP);
525           if (efimm == NULL)
526                     return NULL;
527 
528           for (n = 0, i = 0; i < efimm->num; i++) {
529                     md = (struct efi_md *)(efimm->memmap + efimm->size * i);
530                     addr = md->md_phys;
531                     size = md->md_pages * EFI_PAGE_SIZE;
532                     type = efi_getbiosmemtype(md->md_type, md->md_attr);
533 
534 #ifdef DEBUG_MEMLOAD
535                     printf("MEMMAP: p0x%016" PRIx64 "-0x%016" PRIx64
536                         ", v0x%016" PRIx64 "-0x%016" PRIx64
537                         ", size=0x%016" PRIx64 ", attr=0x%016" PRIx64
538                         ", type=%d(%s)\n",
539                         addr, addr + size - 1,
540                         md->md_virt, md->md_virt + size - 1,
541                         size, md->md_attr, md->md_type,
542                         efi_getmemtype_str(md->md_type));
543 #endif
544 
545                     if (seg_type == -1) {
546                               /* first entry */
547                     } else if (seg_type == type && end_addr == addr) {
548                               /* continuous region */
549                               end_addr = addr + size;
550                               continue;
551                     } else {
552                               entry = &efi_e820memmap.bim.entry[n];
553                               entry->addr = start_addr;
554                               entry->size = end_addr - start_addr;
555                               entry->type = seg_type;
556                               if (++n == VM_PHYSSEG_MAX)
557                                         break;
558                     }
559 
560                     start_addr = addr;
561                     end_addr = addr + size;
562                     seg_type = type;
563           }
564           if (i > 0 && n < VM_PHYSSEG_MAX) {
565                     entry = &efi_e820memmap.bim.entry[n];
566                     entry->addr = start_addr;
567                     entry->size = end_addr - start_addr;
568                     entry->type = seg_type;
569                     ++n;
570           } else if (n == VM_PHYSSEG_MAX) {
571                     printf("WARNING: too many memory segments"
572                         "(increase VM_PHYSSEG_MAX)\n");
573           }
574 
575           efi_e820memmap.bim.num = n;
576           efi_e820memmap.bim.common.len =
577               (intptr_t)&efi_e820memmap.bim.entry[n] - (intptr_t)&efi_e820memmap;
578           efi_e820memmap.bim.common.type = BTINFO_MEMMAP;
579           return &efi_e820memmap.bim;
580 }
581 
582 #ifdef EFI_RUNTIME
583 
584 /*
585  * efi_runtime_init()
586  *
587  *        Set up kernel access to EFI runtime services:
588  *
589  *        - Create efi_runtime_pmap.
590  *        - Enter all the EFI runtime memory mappings into it.
591  *        - Make a copy of the EFI runtime services table in efi_rt.
592  *        - Initialize efi_runtime_lock to serialize calls.
593  *        - Register EFI runtime service operations for /dev/efi.
594  *
595  *        On failure, leaves efi_rt zero-initialized and everything else
596  *        uninitialized.
597  */
598 static void
efi_runtime_init(void)599 efi_runtime_init(void)
600 {
601           struct efi_systbl *systbl;
602           struct btinfo_efimemmap *efimm;
603           uint32_t i;
604           int error;
605 
606           /*
607            * Refuse to handle EFI runtime services with cross-word-sizes
608            * for now.  We would need logic to handle the cross table
609            * types, and logic to translate between the calling
610            * conventions -- might be easy for 32-bit EFI and 64-bit OS,
611            * but sounds painful to contemplate for 64-bit EFI and 32-bit
612            * OS.
613            */
614           if (efi_is32x64) {
615                     aprint_debug("%s: 32x64 runtime services not supported\n",
616                         __func__);
617                     return;
618           }
619 
620           /*
621            * Verify that we have an EFI system table with runtime
622            * services and an EFI memory map.
623            */
624           systbl = efi_getsystbl();
625           if (systbl->st_rt == NULL) {
626                     aprint_debug("%s: no runtime\n", __func__);
627                     return;
628           }
629           if ((efimm = lookup_bootinfo(BTINFO_EFIMEMMAP)) == NULL) {
630                     aprint_debug("%s: no efi memmap\n", __func__);
631                     return;
632           }
633 
634           /*
635            * Create a pmap for EFI runtime services and switch to it to
636            * enter all of the mappings needed for EFI runtime services
637            * according to the EFI_MEMORY_DESCRIPTOR records.
638            */
639           efi_runtime_pmap = pmap_create();
640           void *const cookie = pmap_activate_sync(efi_runtime_pmap);
641           for (i = 0; i < efimm->num; i++) {
642                     struct efi_md *md = (void *)(efimm->memmap + efimm->size * i);
643                     uint64_t j;
644                     vaddr_t va;
645                     paddr_t pa;
646                     int prot, flags;
647 
648                     /*
649                      * Only enter mappings tagged EFI_MEMORY_RUNTIME.
650                      * Ignore all others.
651                      */
652                     if ((md->md_attr & EFI_MD_ATTR_RT) == 0)
653                               continue;
654 
655                     /*
656                      * For debug boots, print the memory descriptor.
657                      */
658                     aprint_debug("%s: map %zu pages at %#"PRIxVADDR
659                         " to %#"PRIxPADDR" type %"PRIu32" attrs 0x%08"PRIx64"\n",
660                         __func__, (size_t)md->md_pages, (vaddr_t)md->md_virt,
661                         (paddr_t)md->md_phys, md->md_type, md->md_attr);
662 
663                     /*
664                      * Allow read and write access in all of the mappings.
665                      * For code mappings, also allow execution by default.
666                      *
667                      * Even code mappings must be writable, apparently.
668                      * The mappings can be marked RO or XP to prevent write
669                      * or execute, but the code mappings are usually at the
670                      * level of entire PECOFF objects containing both rw-
671                      * and r-x sections.  The EFI_MEMORY_ATTRIBUTES_TABLE
672                      * provides finer-grained mapping protections, but we
673                      * don't currently use it.
674                      *
675                      * XXX Should parse EFI_MEMORY_ATTRIBUTES_TABLE and use
676                      * it to nix W or X access when possible.
677                      */
678                     prot = VM_PROT_READ|VM_PROT_WRITE;
679                     switch (md->md_type) {
680                     case EFI_MD_TYPE_RT_CODE:
681                               prot |= VM_PROT_EXECUTE;
682                               break;
683                     }
684 
685                     /*
686                      * Additionally pass on:
687                      *
688                      *        EFI_MEMORY_UC (uncacheable) -> PMAP_NOCACHE
689                      *        EFI_MEMORY_WC (write-combining) -> PMAP_WRITE_COMBINE
690                      *        EFI_MEMORY_RO (read-only) -> clear VM_PROT_WRITE
691                      *        EFI_MEMORY_XP (exec protect) -> clear VM_PROT_EXECUTE
692                      */
693                     flags = 0;
694                     if (md->md_attr & EFI_MD_ATTR_UC)
695                               flags |= PMAP_NOCACHE;
696                     else if (md->md_attr & EFI_MD_ATTR_WC)
697                               flags |= PMAP_WRITE_COMBINE;
698                     if (md->md_attr & EFI_MD_ATTR_RO)
699                               prot &= ~VM_PROT_WRITE;
700                     if (md->md_attr & EFI_MD_ATTR_XP)
701                               prot &= ~VM_PROT_EXECUTE;
702 
703                     /*
704                      * Get the physical address, and the virtual address
705                      * that the EFI runtime services want mapped to it.
706                      *
707                      * If the requested virtual address is zero, assume
708                      * we're using physical addressing, i.e., VA is the
709                      * same as PA.
710                      *
711                      * This logic is intended to allow the bootloader to
712                      * choose whether to use physical addressing or to use
713                      * virtual addressing with RT->SetVirtualAddressMap --
714                      * the kernel should work either way (although as of
715                      * time of writing it has only been tested with
716                      * physical addressing).
717                      */
718                     pa = md->md_phys;
719                     va = md->md_virt;
720                     if (va == 0)
721                               va = pa;
722 
723                     /*
724                      * Fail if EFI runtime services want any virtual pages
725                      * of the kernel map.
726                      */
727                     if (VM_MIN_KERNEL_ADDRESS <= va &&
728                         va < VM_MAX_KERNEL_ADDRESS) {
729                               aprint_debug("%s: efi runtime overlaps kernel map"
730                                   " %"PRIxVADDR" in [%"PRIxVADDR", %"PRIxVADDR")\n",
731                                   __func__,
732                                   va,
733                                   (vaddr_t)VM_MIN_KERNEL_ADDRESS,
734                                   (vaddr_t)VM_MAX_KERNEL_ADDRESS);
735                               goto fail;
736                     }
737 
738                     /*
739                      * Fail if it would interfere with a direct map.
740                      *
741                      * (It's possible that it might happen to be identical
742                      * to the direct mapping, in which case we could skip
743                      * this entry.  Seems unlikely; let's deal with that
744                      * edge case as it comes up.)
745                      */
746 #ifdef __HAVE_DIRECT_MAP
747                     if (PMAP_DIRECT_BASE <= va && va < PMAP_DIRECT_END) {
748                               aprint_debug("%s: efi runtime overlaps direct map"
749                                   " %"PRIxVADDR" in [%"PRIxVADDR", %"PRIxVADDR")\n",
750                                   __func__,
751                                   va,
752                                   (vaddr_t)PMAP_DIRECT_BASE,
753                                   (vaddr_t)PMAP_DIRECT_END);
754                               goto fail;
755                     }
756 #endif
757 
758                     /*
759                      * Enter each page in the range of this memory
760                      * descriptor into efi_runtime_pmap.
761                      */
762                     for (j = 0; j < md->md_pages; j++) {
763                               error = pmap_enter(efi_runtime_pmap,
764                                   va + j*PAGE_SIZE, pa + j*PAGE_SIZE, prot, flags);
765                               KASSERTMSG(error == 0, "error=%d", error);
766                     }
767           }
768 
769           /*
770            * Commit the updates, make a copy of the EFI runtime services
771            * for easy determination of unsupported ones without needing
772            * the pmap, and deactivate the pmap now that we're done with
773            * it for now.
774            */
775           pmap_update(efi_runtime_pmap);
776           memcpy(&efi_rt, systbl->st_rt, sizeof(efi_rt));
777           pmap_deactivate_sync(efi_runtime_pmap, cookie);
778 
779           /*
780            * Initialize efi_runtime_lock for serializing access to the
781            * EFI runtime services from any context up to interrupts at
782            * IPL_VM.
783            */
784           mutex_init(&efi_runtime_lock, MUTEX_DEFAULT, IPL_VM);
785 
786           /*
787            * Register the EFI runtime operations for /dev/efi.
788            */
789           efi_register_ops(&efi_runtime_ops);
790 
791           return;
792 
793 fail:     /*
794            * On failure, deactivate and destroy efi_runtime_pmap -- no
795            * runtime services.
796            */
797           pmap_deactivate_sync(efi_runtime_pmap, cookie);
798           pmap_destroy(efi_runtime_pmap);
799           efi_runtime_pmap = NULL;
800           /*
801            * efi_rt is all zero, so will lead to EFI_UNSUPPORTED even if
802            * used outside efi_runtime_ops (which is now not registered)
803            */
804 }
805 
806 struct efi_runtime_cookie {
807           void      *erc_pmap_cookie;
808 };
809 
810 /*
811  * efi_runtime_enter(cookie)
812  *
813  *        Prepare to call an EFI runtime service, storing state for the
814  *        context in cookie.  Caller must call efi_runtime_exit when
815  *        done.
816  */
817 static void
efi_runtime_enter(struct efi_runtime_cookie * cookie)818 efi_runtime_enter(struct efi_runtime_cookie *cookie)
819 {
820 
821           KASSERT(efi_runtime_pmap != NULL);
822 
823           /*
824            * Serialize queries to the EFI runtime services.
825            *
826            * The UEFI spec allows some concurrency among them with rules
827            * about which calls can run in parallel with which other
828            * calls, but it is simplest if we just serialize everything --
829            * none of this is performance-critical.
830            */
831           mutex_enter(&efi_runtime_lock);
832 
833           /*
834            * EFI runtime services may use the FPU, so stash any user FPU
835            * state and enable kernel use of it.  This has the side
836            * effects of disabling preemption and of blocking interrupts
837            * at up to and including IPL_VM.
838            */
839           fpu_kern_enter();
840 
841           /*
842            * Activate the efi_runtime_pmap so that the EFI runtime
843            * services have access to the memory mappings the firmware
844            * requested, but not access to any user mappings.  They still,
845            * however, have access to all kernel mappings, so we can pass
846            * in pointers to buffers in KVA -- the EFI runtime services
847            * run privileged, which they need in order to do I/O anyway.
848            */
849           cookie->erc_pmap_cookie = pmap_activate_sync(efi_runtime_pmap);
850 }
851 
852 /*
853  * efi_runtime_exit(cookie)
854  *
855  *        Restore state prior to efi_runtime_enter as stored in cookie
856  *        for a call to an EFI runtime service.
857  */
858 static void
efi_runtime_exit(struct efi_runtime_cookie * cookie)859 efi_runtime_exit(struct efi_runtime_cookie *cookie)
860 {
861 
862           pmap_deactivate_sync(efi_runtime_pmap, cookie->erc_pmap_cookie);
863           fpu_kern_leave();
864           mutex_exit(&efi_runtime_lock);
865 }
866 
867 /*
868  * efi_runtime_gettime(tm, tmcap)
869  *
870  *        Call RT->GetTime, or return EFI_UNSUPPORTED if unsupported.
871  */
872 static efi_status
efi_runtime_gettime(struct efi_tm * tm,struct efi_tmcap * tmcap)873 efi_runtime_gettime(struct efi_tm *tm, struct efi_tmcap *tmcap)
874 {
875           efi_status status;
876           struct efi_runtime_cookie cookie;
877 
878           if (efi_rt.rt_gettime == NULL)
879                     return EFI_UNSUPPORTED;
880 
881           efi_runtime_enter(&cookie);
882           status = efi_rt.rt_gettime(tm, tmcap);
883           efi_runtime_exit(&cookie);
884 
885           return status;
886 }
887 
888 
889 /*
890  * efi_runtime_settime(tm)
891  *
892  *        Call RT->SetTime, or return EFI_UNSUPPORTED if unsupported.
893  */
894 static efi_status
efi_runtime_settime(struct efi_tm * tm)895 efi_runtime_settime(struct efi_tm *tm)
896 {
897           efi_status status;
898           struct efi_runtime_cookie cookie;
899 
900           if (efi_rt.rt_settime == NULL)
901                     return EFI_UNSUPPORTED;
902 
903           efi_runtime_enter(&cookie);
904           status = efi_rt.rt_settime(tm);
905           efi_runtime_exit(&cookie);
906 
907           return status;
908 }
909 
910 /*
911  * efi_runtime_getvar(name, vendor, attrib, datasize, data)
912  *
913  *        Call RT->GetVariable.
914  */
915 static efi_status
efi_runtime_getvar(efi_char * name,struct uuid * vendor,uint32_t * attrib,unsigned long * datasize,void * data)916 efi_runtime_getvar(efi_char *name, struct uuid *vendor, uint32_t *attrib,
917     unsigned long *datasize, void *data)
918 {
919           efi_status status;
920           struct efi_runtime_cookie cookie;
921 
922           if (efi_rt.rt_getvar == NULL)
923                     return EFI_UNSUPPORTED;
924 
925           efi_runtime_enter(&cookie);
926           status = efi_rt.rt_getvar(name, vendor, attrib, datasize, data);
927           efi_runtime_exit(&cookie);
928 
929           return status;
930 }
931 
932 /*
933  * efi_runtime_nextvar(namesize, name, vendor)
934  *
935  *        Call RT->GetNextVariableName.
936  */
937 static efi_status
efi_runtime_nextvar(unsigned long * namesize,efi_char * name,struct uuid * vendor)938 efi_runtime_nextvar(unsigned long *namesize, efi_char *name,
939     struct uuid *vendor)
940 {
941           efi_status status;
942           struct efi_runtime_cookie cookie;
943 
944           if (efi_rt.rt_scanvar == NULL)
945                     return EFI_UNSUPPORTED;
946 
947           efi_runtime_enter(&cookie);
948           status = efi_rt.rt_scanvar(namesize, name, vendor);
949           efi_runtime_exit(&cookie);
950 
951           return status;
952 }
953 
954 /*
955  * efi_runtime_setvar(name, vendor, attrib, datasize, data)
956  *
957  *        Call RT->SetVariable.
958  */
959 static efi_status
efi_runtime_setvar(efi_char * name,struct uuid * vendor,uint32_t attrib,unsigned long datasize,void * data)960 efi_runtime_setvar(efi_char *name, struct uuid *vendor, uint32_t attrib,
961     unsigned long datasize, void *data)
962 {
963           efi_status status;
964           struct efi_runtime_cookie cookie;
965 
966           if (efi_rt.rt_setvar == NULL)
967                     return EFI_UNSUPPORTED;
968 
969           efi_runtime_enter(&cookie);
970           status = efi_rt.rt_setvar(name, vendor, attrib, datasize, data);
971           efi_runtime_exit(&cookie);
972 
973           return status;
974 }
975 
976 static efi_status
efi_runtime_gettab(const struct uuid * vendor,uint64_t * addrp)977 efi_runtime_gettab(const struct uuid *vendor, uint64_t *addrp)
978 {
979           struct efi_cfgtbl *cfgtbl = efi_getcfgtblhead();
980           paddr_t pa;
981 
982           if (cfgtbl == NULL)
983                     return EFI_UNSUPPORTED;
984 
985           pa = efi_getcfgtblpa(vendor);
986           if (pa == 0)
987                     return EFI_NOT_FOUND;
988           *addrp = pa;
989           return EFI_SUCCESS;
990 }
991 
992 static struct efi_ops efi_runtime_ops = {
993           .efi_gettime = efi_runtime_gettime,
994           .efi_settime = efi_runtime_settime,
995           .efi_getvar = efi_runtime_getvar,
996           .efi_setvar = efi_runtime_setvar,
997           .efi_nextvar = efi_runtime_nextvar,
998           .efi_gettab = efi_runtime_gettab,
999 };
1000 
1001 #endif    /* EFI_RUNTIME */
1002