Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 22 Aug 2014 18:09:06 +0000 (UTC)
From:      Ed Maste <emaste@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r270344 - in stable/10/sys/amd64: amd64 include
Message-ID:  <201408221809.s7MI96Cc077094@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: emaste
Date: Fri Aug 22 18:09:06 2014
New Revision: 270344
URL: http://svnweb.freebsd.org/changeset/base/270344

Log:
  MFC r263822: amd64: Parse the EFI memory map if present
  
    With this change (and loader.efi from [HEAD]) we can now boot under
    qemu using the OVMF UEFI firmware image with the limitation that a
    serial console is required.
  
  Sponsored by:	The FreeBSD Foundation

Modified:
  stable/10/sys/amd64/amd64/machdep.c
  stable/10/sys/amd64/include/metadata.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/amd64/amd64/machdep.c
==============================================================================
--- stable/10/sys/amd64/amd64/machdep.c	Fri Aug 22 17:49:24 2014	(r270343)
+++ stable/10/sys/amd64/amd64/machdep.c	Fri Aug 22 18:09:06 2014	(r270344)
@@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/callout.h>
 #include <sys/cons.h>
 #include <sys/cpu.h>
+#include <sys/efi.h>
 #include <sys/eventhandler.h>
 #include <sys/exec.h>
 #include <sys/imgact.h>
@@ -1424,6 +1425,100 @@ add_smap_entries(struct bios_smap *smapb
 	}
 }
 
+#define efi_next_descriptor(ptr, size) \
+	((struct efi_md *)(((uint8_t *) ptr) + size))
+
+static void
+add_efi_map_entries(struct efi_map_header *efihdr, vm_paddr_t *physmap,
+    int *physmap_idx)
+{
+	struct efi_md *map, *p;
+	const char *type;
+	size_t efisz;
+	int ndesc, i;
+
+	static const char *types[] = {
+		"Reserved",
+		"LoaderCode",
+		"LoaderData",
+		"BootServicesCode",
+		"BootServicesData",
+		"RuntimeServicesCode",
+		"RuntimeServicesData",
+		"ConventionalMemory",
+		"UnusableMemory",
+		"ACPIReclaimMemory",
+		"ACPIMemoryNVS",
+		"MemoryMappedIO",
+		"MemoryMappedIOPortSpace",
+		"PalCode"
+	};
+
+	/*
+	 * Memory map data provided by UEFI via the GetMemoryMap
+	 * Boot Services API.
+	 */
+	efisz = (sizeof(struct efi_map_header) + 0xf) & ~0xf;
+	map = (struct efi_md *)((uint8_t *)efihdr + efisz); 
+
+	if (efihdr->descriptor_size == 0)
+		return;
+	ndesc = efihdr->memory_size / efihdr->descriptor_size;
+
+	if (boothowto & RB_VERBOSE)
+		printf("%23s %12s %12s %8s %4s\n",
+		    "Type", "Physical", "Virtual", "#Pages", "Attr");
+
+	for (i = 0, p = map; i < ndesc; i++,
+	    p = efi_next_descriptor(p, efihdr->descriptor_size)) {
+		if (boothowto & RB_VERBOSE) {
+			if (p->md_type <= EFI_MD_TYPE_PALCODE)
+				type = types[p->md_type];
+			else
+				type = "<INVALID>";
+			printf("%23s %012lx %12p %08lx ", type, p->md_phys,
+			    p->md_virt, p->md_pages);
+			if (p->md_attr & EFI_MD_ATTR_UC)
+				printf("UC ");
+			if (p->md_attr & EFI_MD_ATTR_WC)
+				printf("WC ");
+			if (p->md_attr & EFI_MD_ATTR_WT)
+				printf("WT ");
+			if (p->md_attr & EFI_MD_ATTR_WB)
+				printf("WB ");
+			if (p->md_attr & EFI_MD_ATTR_UCE)
+				printf("UCE ");
+			if (p->md_attr & EFI_MD_ATTR_WP)
+				printf("WP ");
+			if (p->md_attr & EFI_MD_ATTR_RP)
+				printf("RP ");
+			if (p->md_attr & EFI_MD_ATTR_XP)
+				printf("XP ");
+			if (p->md_attr & EFI_MD_ATTR_RT)
+				printf("RUNTIME");
+			printf("\n");
+		}
+
+		switch (p->md_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:
+			/*
+			 * We're allowed to use any entry with these types.
+			 */
+			break;
+		default:
+			continue;
+		}
+
+		if (!add_physmap_entry(p->md_phys, (p->md_pages * PAGE_SIZE),
+		    physmap, physmap_idx))
+			break;
+	}
+}
+
 /*
  * Populate the (physmap) array with base/bound pairs describing the
  * available physical memory in the system, then test this memory and
@@ -1442,18 +1537,24 @@ getmemsize(caddr_t kmdp, u_int64_t first
 	u_long physmem_start, physmem_tunable, memtest;
 	pt_entry_t *pte;
 	struct bios_smap *smapbase;
+	struct efi_map_header *efihdr;
 	quad_t dcons_addr, dcons_size;
 
 	bzero(physmap, sizeof(physmap));
 	basemem = 0;
 	physmap_idx = 0;
 
+	efihdr = (struct efi_map_header *)preload_search_info(kmdp,
+	    MODINFO_METADATA | MODINFOMD_EFI_MAP);
 	smapbase = (struct bios_smap *)preload_search_info(kmdp,
 	    MODINFO_METADATA | MODINFOMD_SMAP);
-	if (smapbase == NULL)
-		panic("No BIOS smap info from loader!");
 
-	add_smap_entries(smapbase, physmap, &physmap_idx);
+	if (efihdr != NULL)
+		add_efi_map_entries(efihdr, physmap, &physmap_idx);
+	else if (smapbase != NULL)
+		add_smap_entries(smapbase, physmap, &physmap_idx);
+	else
+		panic("No BIOS smap or EFI map info from loader!");
 
 	/*
 	 * Find the 'base memory' segment for SMP

Modified: stable/10/sys/amd64/include/metadata.h
==============================================================================
--- stable/10/sys/amd64/include/metadata.h	Fri Aug 22 17:49:24 2014	(r270343)
+++ stable/10/sys/amd64/include/metadata.h	Fri Aug 22 18:09:06 2014	(r270344)
@@ -32,5 +32,12 @@
 #define	MODINFOMD_SMAP		0x1001
 #define	MODINFOMD_SMAP_XATTR	0x1002
 #define	MODINFOMD_DTBP		0x1003
+#define	MODINFOMD_EFI_MAP	0x1004
+
+struct efi_map_header {                                                        
+	size_t		memory_size;
+	size_t		descriptor_size;
+	uint32_t	descriptor_version;
+};
 
 #endif /* !_MACHINE_METADATA_H_ */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201408221809.s7MI96Cc077094>