diff --git a/sys/arm64/arm64/machdep.c b/sys/arm64/arm64/machdep.c --- a/sys/arm64/arm64/machdep.c +++ b/sys/arm64/arm64/machdep.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -457,172 +458,6 @@ return (false); } -typedef void (*efi_map_entry_cb)(struct efi_md *, void *argp); - -static void -foreach_efi_map_entry(struct efi_map_header *efihdr, efi_map_entry_cb cb, void *argp) -{ - struct efi_md *map, *p; - size_t efisz; - int ndesc, i; - - /* - * 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; - - for (i = 0, p = map; i < ndesc; i++, - p = efi_next_descriptor(p, efihdr->descriptor_size)) { - cb(p, argp); - } -} - -/* - * Handle the EFI memory map list. - * - * We will make two passes at this, the first (exclude == false) to populate - * physmem with valid physical memory ranges from recognized map entry types. - * In the second pass we will exclude memory ranges from physmem which must not - * be used for general allocations, either because they are used by runtime - * firmware or otherwise reserved. - * - * Adding the runtime-reserved memory ranges to physmem and excluding them - * later ensures that they are included in the DMAP, but excluded from - * phys_avail[]. - * - * Entry types not explicitly listed here are ignored and not mapped. - */ -static void -handle_efi_map_entry(struct efi_md *p, void *argp) -{ - bool exclude = *(bool *)argp; - - switch (p->md_type) { - case EFI_MD_TYPE_RECLAIM: - /* - * The recomended location for ACPI tables. Map into the - * DMAP so we can access them from userspace via /dev/mem. - */ - case EFI_MD_TYPE_RT_CODE: - /* - * Some UEFI implementations put the system table in the - * runtime code section. Include it in the DMAP, but will - * be excluded from phys_avail. - */ - case EFI_MD_TYPE_RT_DATA: - /* - * Runtime data will be excluded after the DMAP - * region is created to stop it from being added - * to phys_avail. - */ - if (exclude) { - physmem_exclude_region(p->md_phys, - p->md_pages * EFI_PAGE_SIZE, EXFLAG_NOALLOC); - break; - } - /* FALLTHROUGH */ - 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. - */ - if (!exclude) - physmem_hardware_region(p->md_phys, - p->md_pages * EFI_PAGE_SIZE); - break; - default: - /* Other types shall not be handled by physmem. */ - break; - } -} - -static void -add_efi_map_entries(struct efi_map_header *efihdr) -{ - bool exclude = false; - foreach_efi_map_entry(efihdr, handle_efi_map_entry, &exclude); -} - -static void -exclude_efi_map_entries(struct efi_map_header *efihdr) -{ - bool exclude = true; - foreach_efi_map_entry(efihdr, handle_efi_map_entry, &exclude); -} - -static void -print_efi_map_entry(struct efi_md *p, void *argp __unused) -{ - const char *type; - static const char *types[] = { - "Reserved", - "LoaderCode", - "LoaderData", - "BootServicesCode", - "BootServicesData", - "RuntimeServicesCode", - "RuntimeServicesData", - "ConventionalMemory", - "UnusableMemory", - "ACPIReclaimMemory", - "ACPIMemoryNVS", - "MemoryMappedIO", - "MemoryMappedIOPortSpace", - "PalCode", - "PersistentMemory" - }; - - if (p->md_type < nitems(types)) - type = types[p->md_type]; - else - type = ""; - printf("%23s %012lx %012lx %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_NV) - printf("NV "); - if (p->md_attr & EFI_MD_ATTR_MORE_RELIABLE) - printf("MORE_RELIABLE "); - if (p->md_attr & EFI_MD_ATTR_RO) - printf("RO "); - if (p->md_attr & EFI_MD_ATTR_RT) - printf("RUNTIME"); - printf("\n"); -} - -static void -print_efi_map_entries(struct efi_map_header *efihdr) -{ - - printf("%23s %12s %12s %8s %4s\n", - "Type", "Physical", "Virtual", "#Pages", "Attr"); - foreach_efi_map_entry(efihdr, print_efi_map_entry, NULL); -} - /* * Map the passed in VA in EFI space to a void * using the efi memory table to * find the PA and return it in the DMAP, if it exists. We're used between the @@ -659,7 +494,7 @@ { struct early_map_data emd = { .va = va }; - foreach_efi_map_entry(efihdr, efi_early_map_entry, &emd); + efi_map_foreach_entry(efihdr, efi_early_map_entry, &emd); if (emd.pa == 0) return NULL; return (void *)PHYS_TO_DMAP(emd.pa); @@ -942,7 +777,7 @@ efihdr = (struct efi_map_header *)preload_search_info(preload_kmdp, MODINFO_METADATA | MODINFOMD_EFI_MAP); if (efihdr != NULL) - add_efi_map_entries(efihdr); + efi_map_add_entries(efihdr); #ifdef FDT else { /* Grab physical memory regions information from device tree. */ @@ -972,7 +807,7 @@ pmap_bootstrap(lastaddr - KERNBASE); /* Exclude entries needed in the DMAP region, but not phys_avail */ if (efihdr != NULL) - exclude_efi_map_entries(efihdr); + efi_map_exclude_entries(efihdr); /* Do the same for reserve entries in the EFI MEMRESERVE table */ if (efi_systbl_phys != 0) exclude_efi_memreserve(efi_systbl_phys); @@ -1051,7 +886,7 @@ if (boothowto & RB_VERBOSE) { if (efihdr != NULL) - print_efi_map_entries(efihdr); + efi_map_print_entries(efihdr); physmem_print_tables(); } diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64 --- a/sys/conf/files.arm64 +++ b/sys/conf/files.arm64 @@ -6,6 +6,7 @@ kern/msi_if.m optional intrng kern/pic_if.m optional intrng kern/subr_devmap.c standard +kern/subr_efi_map.c standard kern/subr_intr.c optional intrng kern/subr_physmem.c standard libkern/strlen.c standard diff --git a/sys/kern/subr_efi_map.c b/sys/kern/subr_efi_map.c new file mode 100644 --- /dev/null +++ b/sys/kern/subr_efi_map.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2014 The FreeBSD Foundation + * Copyright (c) 2018 Andrew Turner + * + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include +#include +#include +#include + +#include +#include + +void +efi_map_foreach_entry(struct efi_map_header *efihdr, efi_map_entry_cb cb, void *argp) +{ + struct efi_md *map, *p; + size_t efisz; + int ndesc, i; + + /* + * 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; + + for (i = 0, p = map; i < ndesc; i++, + p = efi_next_descriptor(p, efihdr->descriptor_size)) { + cb(p, argp); + } +} + +/* + * Handle the EFI memory map list. + * + * We will make two passes at this, the first (exclude == false) to populate + * physmem with valid physical memory ranges from recognized map entry types. + * In the second pass we will exclude memory ranges from physmem which must not + * be used for general allocations, either because they are used by runtime + * firmware or otherwise reserved. + * + * Adding the runtime-reserved memory ranges to physmem and excluding them + * later ensures that they are included in the DMAP, but excluded from + * phys_avail[]. + * + * Entry types not explicitly listed here are ignored and not mapped. + */ +static void +handle_efi_map_entry(struct efi_md *p, void *argp) +{ + bool exclude = *(bool *)argp; + + switch (p->md_type) { + case EFI_MD_TYPE_RECLAIM: + /* + * The recomended location for ACPI tables. Map into the + * DMAP so we can access them from userspace via /dev/mem. + */ + case EFI_MD_TYPE_RT_CODE: + /* + * Some UEFI implementations put the system table in the + * runtime code section. Include it in the DMAP, but will + * be excluded from phys_avail. + */ + case EFI_MD_TYPE_RT_DATA: + /* + * Runtime data will be excluded after the DMAP + * region is created to stop it from being added + * to phys_avail. + */ + if (exclude) { + physmem_exclude_region(p->md_phys, + p->md_pages * EFI_PAGE_SIZE, EXFLAG_NOALLOC); + break; + } + /* FALLTHROUGH */ + 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. + */ + if (!exclude) + physmem_hardware_region(p->md_phys, + p->md_pages * EFI_PAGE_SIZE); + break; + default: + /* Other types shall not be handled by physmem. */ + break; + } +} + +void +efi_map_add_entries(struct efi_map_header *efihdr) +{ + bool exclude = false; + efi_map_foreach_entry(efihdr, handle_efi_map_entry, &exclude); +} + +void +efi_map_exclude_entries(struct efi_map_header *efihdr) +{ + bool exclude = true; + efi_map_foreach_entry(efihdr, handle_efi_map_entry, &exclude); +} + +static void +print_efi_map_entry(struct efi_md *p, void *argp __unused) +{ + const char *type; + static const char *types[] = { + "Reserved", + "LoaderCode", + "LoaderData", + "BootServicesCode", + "BootServicesData", + "RuntimeServicesCode", + "RuntimeServicesData", + "ConventionalMemory", + "UnusableMemory", + "ACPIReclaimMemory", + "ACPIMemoryNVS", + "MemoryMappedIO", + "MemoryMappedIOPortSpace", + "PalCode", + "PersistentMemory" + }; + + if (p->md_type < nitems(types)) + type = types[p->md_type]; + else + type = ""; + printf("%23s %012lx %012lx %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_NV) + printf("NV "); + if (p->md_attr & EFI_MD_ATTR_MORE_RELIABLE) + printf("MORE_RELIABLE "); + if (p->md_attr & EFI_MD_ATTR_RO) + printf("RO "); + if (p->md_attr & EFI_MD_ATTR_RT) + printf("RUNTIME"); + printf("\n"); +} + +void +efi_map_print_entries(struct efi_map_header *efihdr) +{ + + printf("%23s %12s %12s %8s %4s\n", + "Type", "Physical", "Virtual", "#Pages", "Attr"); + efi_map_foreach_entry(efihdr, print_efi_map_entry, NULL); +} diff --git a/sys/sys/efi_map.h b/sys/sys/efi_map.h new file mode 100644 --- /dev/null +++ b/sys/sys/efi_map.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2014 The FreeBSD Foundation + * Copyright (c) 2018 Andrew Turner + * + * SPDX-License-Identifier: BSD-2-Clause + */ +#ifndef _SYS_EFI_MAP_H_ +#define _SYS_EFI_MAP_H_ + +#include +#include + +typedef void (*efi_map_entry_cb)(struct efi_md *, void *argp); + +void efi_map_foreach_entry(struct efi_map_header *efihdr, efi_map_entry_cb cb, + void *argp); + +void efi_map_add_entries(struct efi_map_header *efihdr); +void efi_map_exclude_entries(struct efi_map_header *efihdr); +void efi_map_print_entries(struct efi_map_header *efihdr); + +#endif /* !_SYS_EFI_MAP_H_ */