summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
authoremaste <emaste@FreeBSD.org>2014-08-22 18:09:06 +0000
committeremaste <emaste@FreeBSD.org>2014-08-22 18:09:06 +0000
commiteb659bdb8318a564631af5dd10ad234d804974e1 (patch)
tree42d36e6b9887fcd48be161dd9ceb42d5f5d71af9 /sys/amd64
parentdf42e806cb6116755002afbea27aeee87bea245d (diff)
downloadFreeBSD-src-eb659bdb8318a564631af5dd10ad234d804974e1.zip
FreeBSD-src-eb659bdb8318a564631af5dd10ad234d804974e1.tar.gz
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
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/amd64/machdep.c107
-rw-r--r--sys/amd64/include/metadata.h7
2 files changed, 111 insertions, 3 deletions
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index aea1036..df26e7e 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -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 *smapbase, vm_paddr_t *physmap,
}
}
+#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
diff --git a/sys/amd64/include/metadata.h b/sys/amd64/include/metadata.h
index 73c9207..9d17424 100644
--- a/sys/amd64/include/metadata.h
+++ b/sys/amd64/include/metadata.h
@@ -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_ */
OpenPOWER on IntegriCloud