Add a sysctl to export the EFI memory map along with a handler in the

sysctl(8) binary to format it.

Reviewed by:	emaste
MFC after:	2 weeks
Differential Revision:	https://reviews.freebsd.org/D771
This commit is contained in:
jhb 2014-09-13 03:10:02 +00:00
parent f5cfeab277
commit 9741565697
2 changed files with 114 additions and 0 deletions

View File

@ -48,6 +48,11 @@ static const char rcsid[] =
#include <sys/sysctl.h>
#include <sys/vmmeter.h>
#ifdef __amd64__
#include <sys/efi.h>
#include <machine/metadata.h>
#endif
#if defined(__amd64__) || defined(__i386__)
#include <machine/pc/bios.h>
#endif
@ -545,6 +550,91 @@ S_vmtotal(size_t l2, void *p)
return (0);
}
#ifdef __amd64__
#define efi_next_descriptor(ptr, size) \
((struct efi_md *)(((uint8_t *) ptr) + size))
static int
S_efi_map(size_t l2, void *p)
{
struct efi_map_header *efihdr;
struct efi_md *map;
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.
*/
if (l2 < sizeof(*efihdr)) {
warnx("S_efi_map length less than header");
return (1);
}
efihdr = p;
efisz = (sizeof(struct efi_map_header) + 0xf) & ~0xf;
map = (struct efi_md *)((uint8_t *)efihdr + efisz);
if (efihdr->descriptor_size == 0)
return (0);
if (l2 != efisz + efihdr->memory_size) {
warnx("S_efi_map length mismatch %zu vs %zu", l2, efisz +
efihdr->memory_size);
return (1);
}
ndesc = efihdr->memory_size / efihdr->descriptor_size;
printf("\n%23s %12s %12s %8s %4s",
"Type", "Physical", "Virtual", "#Pages", "Attr");
for (i = 0; i < ndesc; i++,
map = efi_next_descriptor(map, efihdr->descriptor_size)) {
if (map->md_type <= EFI_MD_TYPE_PALCODE)
type = types[map->md_type];
else
type = "<INVALID>";
printf("\n%23s %012lx %12p %08lx ", type, map->md_phys,
map->md_virt, map->md_pages);
if (map->md_attr & EFI_MD_ATTR_UC)
printf("UC ");
if (map->md_attr & EFI_MD_ATTR_WC)
printf("WC ");
if (map->md_attr & EFI_MD_ATTR_WT)
printf("WT ");
if (map->md_attr & EFI_MD_ATTR_WB)
printf("WB ");
if (map->md_attr & EFI_MD_ATTR_UCE)
printf("UCE ");
if (map->md_attr & EFI_MD_ATTR_WP)
printf("WP ");
if (map->md_attr & EFI_MD_ATTR_RP)
printf("RP ");
if (map->md_attr & EFI_MD_ATTR_XP)
printf("XP ");
if (map->md_attr & EFI_MD_ATTR_RT)
printf("RUNTIME");
}
return (0);
}
#endif
#if defined(__amd64__) || defined(__i386__)
static int
S_bios_smap_xattr(size_t l2, void *p)
@ -818,6 +908,10 @@ show_var(int *oid, int nlen)
func = S_loadavg;
else if (strcmp(fmt, "S,vmtotal") == 0)
func = S_vmtotal;
#ifdef __amd64__
else if (strcmp(fmt, "S,efi_map_header") == 0)
func = S_efi_map;
#endif
#if defined(__amd64__) || defined(__i386__)
else if (strcmp(fmt, "S,bios_smap_xattr") == 0)
func = S_bios_smap_xattr;

View File

@ -2124,6 +2124,26 @@ smap_sysctl_handler(SYSCTL_HANDLER_ARGS)
SYSCTL_PROC(_machdep, OID_AUTO, smap, CTLTYPE_OPAQUE|CTLFLAG_RD, NULL, 0,
smap_sysctl_handler, "S,bios_smap_xattr", "Raw BIOS SMAP data");
static int
efi_map_sysctl_handler(SYSCTL_HANDLER_ARGS)
{
struct efi_map_header *efihdr;
caddr_t kmdp;
uint32_t efisize;
kmdp = preload_search_by_type("elf kernel");
if (kmdp == NULL)
kmdp = preload_search_by_type("elf64 kernel");
efihdr = (struct efi_map_header *)preload_search_info(kmdp,
MODINFO_METADATA | MODINFOMD_EFI_MAP);
if (efihdr == NULL)
return (0);
efisize = *((uint32_t *)efihdr - 1);
return (SYSCTL_OUT(req, efihdr, efisize));
}
SYSCTL_PROC(_machdep, OID_AUTO, efi_map, CTLTYPE_OPAQUE|CTLFLAG_RD, NULL, 0,
efi_map_sysctl_handler, "S,efi_map_header", "Raw EFI Memory Map");
void
spinlock_enter(void)
{