Module Name:    src
Committed By:   riastradh
Date:           Tue Aug 30 11:03:36 UTC 2022

Modified Files:
        src/sys/arch/x86/conf: files.x86
Added Files:
        src/sys/arch/x86/x86: efi_machdep.c
Removed Files:
        src/sys/arch/x86/x86: efi.c

Log Message:
x86: Rename x86/efi.c -> x86/efi_machdep.c.

Avoid collision with dev/efi.c.


To generate a diff of this commit:
cvs rdiff -u -r1.122 -r1.123 src/sys/arch/x86/conf/files.x86
cvs rdiff -u -r1.22 -r0 src/sys/arch/x86/x86/efi.c
cvs rdiff -u -r0 -r1.1 src/sys/arch/x86/x86/efi_machdep.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/x86/conf/files.x86
diff -u src/sys/arch/x86/conf/files.x86:1.122 src/sys/arch/x86/conf/files.x86:1.123
--- src/sys/arch/x86/conf/files.x86:1.122	Wed Jul 21 23:26:15 2021
+++ src/sys/arch/x86/conf/files.x86	Tue Aug 30 11:03:36 2022
@@ -1,4 +1,4 @@
-#	$NetBSD: files.x86,v 1.122 2021/07/21 23:26:15 jmcneill Exp $
+#	$NetBSD: files.x86,v 1.123 2022/08/30 11:03:36 riastradh Exp $
 
 # options for MP configuration through the MP spec
 defflag opt_mpbios.h MPBIOS MPDEBUG MPBIOS_SCANPCI
@@ -89,7 +89,7 @@ file	arch/x86/x86/core_machdep.c	coredum
 file	arch/x86/x86/cpu_topology.c	machdep
 file	arch/x86/x86/db_memrw.c		ddb | kgdb
 file	arch/x86/x86/db_trace.c		ddb
-file	arch/x86/x86/efi.c		machdep
+file	arch/x86/x86/efi_machdep.c	machdep
 file	arch/x86/x86/errata.c		machdep
 file	arch/x86/x86/genfb_machdep.c	machdep
 file	arch/x86/x86/identcpu.c		machdep

Added files:

Index: src/sys/arch/x86/x86/efi_machdep.c
diff -u /dev/null src/sys/arch/x86/x86/efi_machdep.c:1.1
--- /dev/null	Tue Aug 30 11:03:36 2022
+++ src/sys/arch/x86/x86/efi_machdep.c	Tue Aug 30 11:03:36 2022
@@ -0,0 +1,550 @@
+/*	$NetBSD: efi_machdep.c,v 1.1 2022/08/30 11:03:36 riastradh Exp $	*/
+
+/*-
+ * Copyright (c) 2016 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: efi_machdep.c,v 1.1 2022/08/30 11:03:36 riastradh Exp $");
+
+#include <sys/kmem.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/uuid.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/bootinfo.h>
+#include <x86/bus_defs.h>
+#include <x86/bus_funcs.h>
+#include <x86/efi.h>
+
+#include <dev/mm.h>
+#if NPCI > 0
+#include <dev/pci/pcivar.h> /* for pci_mapreg_map_enable_decode */
+#endif
+
+const struct uuid EFI_UUID_ACPI20 = EFI_TABLE_ACPI20;
+const struct uuid EFI_UUID_ACPI10 = EFI_TABLE_ACPI10;
+const struct uuid EFI_UUID_SMBIOS = EFI_TABLE_SMBIOS;
+const struct uuid EFI_UUID_SMBIOS3 = EFI_TABLE_SMBIOS3;
+
+static vaddr_t	efi_getva(paddr_t);
+static void	efi_relva(paddr_t, vaddr_t);
+struct efi_cfgtbl *efi_getcfgtblhead(void);
+void		efi_aprintcfgtbl(void);
+void		efi_aprintuuid(const struct uuid *);
+bool		efi_uuideq(const struct uuid *, const struct uuid *);
+
+static bool efi_is32x64 = false;
+static paddr_t efi_systbl_pa;
+static struct efi_systbl *efi_systbl_va = NULL;
+static struct efi_cfgtbl *efi_cfgtblhead_va = NULL;
+static struct efi_e820memmap {
+	struct btinfo_memmap bim;
+	struct bi_memmap_entry entry[VM_PHYSSEG_MAX - 1];
+} efi_e820memmap;
+
+/*
+ * Map a physical address (PA) to a newly allocated virtual address (VA).
+ * The VA must be freed using efi_relva().
+ */
+static vaddr_t
+efi_getva(paddr_t pa)
+{
+	vaddr_t va;
+	int rv;
+
+	rv = _x86_memio_map(x86_bus_space_mem, pa,
+	    PAGE_SIZE, 0, (bus_space_handle_t *)&va);
+	if (rv != 0) {
+		aprint_debug("efi: unable to allocate va\n");
+		return 0;
+	}
+
+	return va;
+}
+
+/*
+ * Free a virtual address (VA) allocated using efi_getva().
+ */
+static void
+efi_relva(paddr_t pa, vaddr_t va)
+{
+	(void)_x86_memio_unmap(x86_bus_space_mem, (bus_space_handle_t)va,
+	    PAGE_SIZE, NULL);
+}
+
+/*
+ * Test if 2 UUIDs matches.
+ */
+bool
+efi_uuideq(const struct uuid * a, const struct uuid * b)
+{
+	return !memcmp(a, b, sizeof(struct uuid));
+}
+
+/*
+ * Print an UUID in a human-readable manner.
+ */
+void
+efi_aprintuuid(const struct uuid * uuid)
+{
+	int i;
+
+	aprint_debug(" %08" PRIx32 "", uuid->time_low);
+	aprint_debug("-%04" PRIx16 "", uuid->time_mid);
+	aprint_debug("-%04" PRIx16 "", uuid->time_hi_and_version);
+	aprint_debug("-%02" PRIx8 "", uuid->clock_seq_hi_and_reserved);
+	aprint_debug("-%02" PRIx8 "", uuid->clock_seq_low);
+	aprint_debug("-");
+	for (i = 0; i < _UUID_NODE_LEN; i++) {
+		aprint_debug("%02" PRIx8 "", uuid->node[i]);
+	}
+	/* If known, also print the human-readable name */
+	if (efi_uuideq(uuid, &EFI_UUID_ACPI20)) {
+		aprint_debug(" ACPI 2.0");
+	} else if (efi_uuideq(uuid, &EFI_UUID_ACPI10)) {
+		aprint_debug(" ACPI 1.0");
+	} else if (efi_uuideq(uuid, &EFI_UUID_SMBIOS)) {
+		aprint_debug(" SMBIOS");
+	} else if (efi_uuideq(uuid, &EFI_UUID_SMBIOS3)) {
+		aprint_debug(" SMBIOS3");
+	}
+}
+
+/*
+ * Return the VA of the cfgtbl. Must be freed using efi_relva().
+ */
+struct efi_cfgtbl *
+efi_getcfgtblhead(void)
+{
+	paddr_t	pa;
+	vaddr_t	va;
+
+	if (efi_cfgtblhead_va != NULL)
+		return efi_cfgtblhead_va;
+
+	if (efi_is32x64) {
+#if defined(__amd64__)
+		struct efi_systbl32 *systbl32 = (void *) efi_systbl_va;
+		pa = systbl32->st_cfgtbl;
+#elif defined(__i386__)
+		struct efi_systbl64 *systbl64 = (void *) efi_systbl_va;
+		if (systbl64->st_cfgtbl & 0xffffffff00000000ULL)
+			return NULL;
+		pa = (paddr_t) systbl64->st_cfgtbl;
+#endif
+	} else
+		pa = (paddr_t)(u_long) efi_systbl_va->st_cfgtbl;
+	aprint_debug("efi: cfgtbl at pa %" PRIxPADDR "\n", pa);
+	va = efi_getva(pa);
+	aprint_debug("efi: cfgtbl mapped at va %" PRIxVADDR "\n", va);
+	efi_cfgtblhead_va = (struct efi_cfgtbl *) va;
+	efi_aprintcfgtbl();
+
+	return efi_cfgtblhead_va;
+}
+
+/*
+ * Print the config tables.
+ */
+void
+efi_aprintcfgtbl(void)
+{
+	struct efi_cfgtbl *ct;
+	unsigned long count;
+
+	if (efi_is32x64) {
+#if defined(__amd64__)
+		struct efi_systbl32 *systbl32 = (void *) efi_systbl_va;
+		struct efi_cfgtbl32 *ct32 = (void *) efi_cfgtblhead_va;
+
+		count = systbl32->st_entries;
+		aprint_debug("efi: %lu cfgtbl entries:\n", count);
+		for (; count; count--, ct32++) {
+			aprint_debug("efi: %08" PRIx32, ct32->ct_data);
+			efi_aprintuuid(&ct32->ct_uuid);
+			aprint_debug("\n");
+		}
+#elif defined(__i386__)
+		struct efi_systbl64 *systbl64 = (void *) efi_systbl_va;
+		struct efi_cfgtbl64 *ct64 = (void *) efi_cfgtblhead_va;
+		uint64_t count64 = systbl64->st_entries;
+
+		aprint_debug("efi: %" PRIu64 " cfgtbl entries:\n", count64);
+		for (; count64; count64--, ct64++) {
+			aprint_debug("efi: %016" PRIx64, ct64->ct_data);
+			efi_aprintuuid(&ct64->ct_uuid);
+			aprint_debug("\n");
+		}
+#endif
+		return;
+	}
+
+	ct = efi_cfgtblhead_va;
+	count = efi_systbl_va->st_entries;
+	aprint_debug("efi: %lu cfgtbl entries:\n", count);
+	for (; count; count--, ct++) {
+		aprint_debug("efi: %p", ct->ct_data);
+		efi_aprintuuid(&ct->ct_uuid);
+		aprint_debug("\n");
+	}
+}
+
+/*
+ * Return the VA of the config table with the given UUID if found.
+ * The VA must be freed using efi_relva().
+ */
+void *
+efi_getcfgtbl(const struct uuid * uuid)
+{
+	paddr_t pa;
+	vaddr_t va;
+
+	pa = efi_getcfgtblpa(uuid);
+	if (pa == 0)
+		return NULL;
+	va = efi_getva(pa);
+	return (void *) va;
+}
+
+/*
+ * Return the PA of the first config table.
+ */
+paddr_t
+efi_getcfgtblpa(const struct uuid * uuid)
+{
+	struct efi_cfgtbl *ct;
+	unsigned long count;
+
+	if (efi_is32x64) {
+#if defined(__amd64__)
+		struct efi_systbl32 *systbl32 = (void *) efi_systbl_va;
+		struct efi_cfgtbl32 *ct32 = (void *) efi_cfgtblhead_va;
+
+		count = systbl32->st_entries;
+		for (; count; count--, ct32++)
+			if (efi_uuideq(&ct32->ct_uuid, uuid))
+				return ct32->ct_data;
+#elif defined(__i386__)
+		struct efi_systbl64 *systbl64 = (void *) efi_systbl_va;
+		struct efi_cfgtbl64 *ct64 = (void *) efi_cfgtblhead_va;
+		uint64_t count64 = systbl64->st_entries;
+
+		for (; count64; count64--, ct64++)
+			if (efi_uuideq(&ct64->ct_uuid, uuid))
+				if (!(ct64->ct_data & 0xffffffff00000000ULL))
+					return ct64->ct_data;
+#endif
+		return 0;	/* Not found. */
+	}
+
+	ct = efi_cfgtblhead_va;
+	count = efi_systbl_va->st_entries;
+	for (; count; count--, ct++)
+		if (efi_uuideq(&ct->ct_uuid, uuid))
+			return (paddr_t)(u_long) ct->ct_data;
+
+	return 0;	/* Not found. */
+}
+
+/* Return the PA of the EFI System Table. */
+paddr_t
+efi_getsystblpa(void)
+{
+	struct btinfo_efi *bi;
+	paddr_t	pa;
+
+	bi = lookup_bootinfo(BTINFO_EFI);
+	if (bi == NULL) {
+		/* Unable to locate the EFI System Table. */
+		return 0;
+	}
+	if (sizeof(paddr_t) == 4 &&	/* XXX i386 with PAE */
+	    (bi->systblpa & 0xffffffff00000000ULL)) {
+		/* Unable to access EFI System Table. */
+		return 0;
+	}
+	if (bi->common.len > 16 && (bi->flags & BI_EFI_32BIT)) {
+		/* boot from 32bit UEFI */
+#if defined(__amd64__)
+		efi_is32x64 = true;
+#endif
+	} else {
+		/* boot from 64bit UEFI */
+#if defined(__i386__)
+		efi_is32x64 = true;
+#endif
+	}
+	pa = (paddr_t) bi->systblpa;
+	return pa;
+}
+
+/*
+ * Return a pointer to the EFI System Table. The pointer must be freed using
+ * efi_relva().
+ */
+struct efi_systbl *
+efi_getsystbl(void)
+{
+	paddr_t pa;
+	vaddr_t va;
+	struct efi_systbl *systbl;
+
+	if (efi_systbl_va)
+		return efi_systbl_va;
+
+	pa = efi_getsystblpa();
+	if (pa == 0)
+		return NULL;
+
+	aprint_normal("efi: systbl at pa %" PRIxPADDR "\n", pa);
+	efi_systbl_pa = pa;
+	va = efi_getva(pa);
+	aprint_debug("efi: systbl mapped at va %" PRIxVADDR "\n", va);
+
+	if (efi_is32x64) {
+#if defined(__amd64__)
+		struct efi_systbl32 *systbl32 = (struct efi_systbl32 *) va;
+
+		/* XXX Check the signature and the CRC32 */
+		aprint_debug("efi: signature %" PRIx64 " revision %" PRIx32
+		    " crc32 %" PRIx32 "\n", systbl32->st_hdr.th_sig,
+		    systbl32->st_hdr.th_rev, systbl32->st_hdr.th_crc32);
+		aprint_debug("efi: firmware revision %" PRIx32 "\n",
+		    systbl32->st_fwrev);
+		/*
+		 * XXX Also print fwvendor, which is an UCS-2 string (use
+		 * some UTF-16 routine?)
+		 */
+		aprint_debug("efi: runtime services at pa 0x%08" PRIx32 "\n",
+		    systbl32->st_rt);
+		aprint_debug("efi: boot services at pa 0x%08" PRIx32 "\n",
+		    systbl32->st_bs);
+
+		efi_systbl_va = (struct efi_systbl *) systbl32;
+#elif defined(__i386__)
+		struct efi_systbl64 *systbl64 = (struct efi_systbl64 *) va;
+
+		/* XXX Check the signature and the CRC32 */
+		aprint_debug("efi: signature %" PRIx64 " revision %" PRIx32
+		    " crc32 %" PRIx32 "\n", systbl64->st_hdr.th_sig,
+		    systbl64->st_hdr.th_rev, systbl64->st_hdr.th_crc32);
+		aprint_debug("efi: firmware revision %" PRIx32 "\n",
+		    systbl64->st_fwrev);
+		/*
+		 * XXX Also print fwvendor, which is an UCS-2 string (use
+		 * some UTF-16 routine?)
+		 */
+		aprint_debug("efi: runtime services at pa 0x%016" PRIx64 "\n",
+		    systbl64->st_rt);
+		aprint_debug("efi: boot services at pa 0x%016" PRIx64 "\n",
+		    systbl64->st_bs);
+
+		efi_systbl_va = (struct efi_systbl *) systbl64;
+#endif
+		return efi_systbl_va;
+	}
+
+	systbl = (struct efi_systbl *) va;
+	/* XXX Check the signature and the CRC32 */
+	aprint_debug("efi: signature %" PRIx64 " revision %" PRIx32
+	    " crc32 %" PRIx32 "\n", systbl->st_hdr.th_sig,
+	    systbl->st_hdr.th_rev, systbl->st_hdr.th_crc32);
+	aprint_debug("efi: firmware revision %" PRIx32 "\n", systbl->st_fwrev);
+	/*
+	 * XXX Also print fwvendor, which is an UCS-2 string (use
+	 * some UTF-16 routine?)
+	 */
+	aprint_debug("efi: runtime services at pa %p\n", systbl->st_rt);
+	aprint_debug("efi: boot services at pa %p\n", systbl->st_bs);
+
+	efi_systbl_va = systbl;
+	return efi_systbl_va;
+}
+
+/*
+ * EFI is available if we are able to locate the EFI System Table.
+ */
+void
+efi_init(void)
+{
+
+	if (efi_getsystbl() == NULL) {
+		aprint_debug("efi: missing or invalid systbl\n");
+		bootmethod_efi = false;
+		return;
+	}
+	if (efi_getcfgtblhead() == NULL) {
+		aprint_debug("efi: missing or invalid cfgtbl\n");
+		efi_relva(efi_systbl_pa, (vaddr_t) efi_systbl_va);
+		bootmethod_efi = false;
+		return;
+	}
+	bootmethod_efi = true;
+#if NPCI > 0
+	pci_mapreg_map_enable_decode = true; /* PR port-amd64/53286 */
+#endif
+}
+
+bool
+efi_probe(void)
+{
+
+	return bootmethod_efi;
+}
+
+int
+efi_getbiosmemtype(uint32_t type, uint64_t attr)
+{
+
+	switch (type) {
+	case EFI_MD_TYPE_CODE:
+	case EFI_MD_TYPE_DATA:
+	case EFI_MD_TYPE_BS_CODE:
+	case EFI_MD_TYPE_BS_DATA:
+	case EFI_MD_TYPE_FREE:
+		return (attr & EFI_MD_ATTR_WB) ? BIM_Memory : BIM_Reserved;
+
+	case EFI_MD_TYPE_RECLAIM:
+		return BIM_ACPI;
+
+	case EFI_MD_TYPE_FIRMWARE:
+		return BIM_NVS;
+
+	case EFI_MD_TYPE_PMEM:
+		return BIM_PMEM;
+
+	case EFI_MD_TYPE_NULL:
+	case EFI_MD_TYPE_RT_CODE:
+	case EFI_MD_TYPE_RT_DATA:
+	case EFI_MD_TYPE_BAD:
+	case EFI_MD_TYPE_IOMEM:
+	case EFI_MD_TYPE_IOPORT:
+	case EFI_MD_TYPE_PALCODE:
+	default:
+		return BIM_Reserved;
+	}
+}
+
+const char *
+efi_getmemtype_str(uint32_t type)
+{
+	static const char *efimemtypes[] = {
+		"Reserved",
+		"LoaderCode",
+		"LoaderData",
+		"BootServicesCode",
+		"BootServicesData",
+		"RuntimeServicesCode",
+		"RuntimeServicesData",
+		"ConventionalMemory",
+		"UnusableMemory",
+		"ACPIReclaimMemory",
+		"ACPIMemoryNVS",
+		"MemoryMappedIO",
+		"MemoryMappedIOPortSpace",
+		"PalCode",
+		"PersistentMemory",
+	};
+
+	if (type < __arraycount(efimemtypes))
+		return efimemtypes[type];
+	return "unknown";
+}
+
+struct btinfo_memmap *
+efi_get_e820memmap(void)
+{
+	struct btinfo_efimemmap *efimm;
+	struct bi_memmap_entry *entry;
+	struct efi_md *md;
+	uint64_t addr, size;
+	uint64_t start_addr = 0;        /* XXX gcc -Os: maybe-uninitialized */
+	uint64_t end_addr = 0;          /* XXX gcc -Os: maybe-uninitialized */
+	uint32_t i;
+	int n, type, seg_type = -1;
+
+	if (efi_e820memmap.bim.common.type == BTINFO_MEMMAP)
+		return &efi_e820memmap.bim;
+
+	efimm = lookup_bootinfo(BTINFO_EFIMEMMAP);
+	if (efimm == NULL)
+		return NULL;
+
+	for (n = 0, i = 0; i < efimm->num; i++) {
+		md = (struct efi_md *)(efimm->memmap + efimm->size * i);
+		addr = md->md_phys;
+		size = md->md_pages * EFI_PAGE_SIZE;
+		type = efi_getbiosmemtype(md->md_type, md->md_attr);
+
+#ifdef DEBUG_MEMLOAD
+		printf("MEMMAP: p0x%016" PRIx64 "-0x%016" PRIx64
+		    ", v0x%016" PRIx64 "-0x%016" PRIx64
+		    ", size=0x%016" PRIx64 ", attr=0x%016" PRIx64
+		    ", type=%d(%s)\n",
+		    addr, addr + size - 1,
+		    md->md_virt, md->md_virt + size - 1,
+		    size, md->md_attr, md->md_type,
+		    efi_getmemtype_str(md->md_type));
+#endif
+
+		if (seg_type == -1) {
+			/* first entry */
+		} else if (seg_type == type && end_addr == addr) {
+			/* continuous region */
+			end_addr = addr + size;
+			continue;
+		} else {
+			entry = &efi_e820memmap.bim.entry[n];
+			entry->addr = start_addr;
+			entry->size = end_addr - start_addr;
+			entry->type = seg_type;
+			if (++n == VM_PHYSSEG_MAX)
+				break;
+		}
+
+		start_addr = addr;
+		end_addr = addr + size;
+		seg_type = type;
+	}
+	if (i > 0 && n < VM_PHYSSEG_MAX) {
+		entry = &efi_e820memmap.bim.entry[n];
+		entry->addr = start_addr;
+		entry->size = end_addr - start_addr;
+		entry->type = seg_type;
+		++n;
+	} else if (n == VM_PHYSSEG_MAX) {
+		printf("WARNING: too many memory segments"
+		    "(increase VM_PHYSSEG_MAX)\n");
+	}
+
+	efi_e820memmap.bim.num = n;
+	efi_e820memmap.bim.common.len =
+	    (intptr_t)&efi_e820memmap.bim.entry[n] - (intptr_t)&efi_e820memmap;
+	efi_e820memmap.bim.common.type = BTINFO_MEMMAP;
+	return &efi_e820memmap.bim;
+}

Reply via email to