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