diff --git a/stand/kboot/include/efi.h b/stand/kboot/include/efi.h index 10368bd4a829..f75a9ea055d3 100644 --- a/stand/kboot/include/efi.h +++ b/stand/kboot/include/efi.h @@ -1,17 +1,18 @@ /*- * Copyright (c) 2024, Netflix, Inc. * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include /* Note, we mix and match FreeBSD types and EFI standard defined types */ typedef void (*efi_map_entry_cb)(struct efi_md *, void *argp); void foreach_efi_map_entry(struct efi_map_header *efihdr, efi_map_entry_cb cb, void *argp); void print_efi_map(struct efi_map_header *efihdr); +bool populate_avail_from_efi(struct efi_map_header *efihdr); diff --git a/stand/kboot/libkboot/efi.c b/stand/kboot/libkboot/efi.c index 1f7f28093819..1c1d9a34d297 100644 --- a/stand/kboot/libkboot/efi.c +++ b/stand/kboot/libkboot/efi.c @@ -1,97 +1,134 @@ /* * Copyright (c) 2024 Netflix, Inc * * SPDX-License-Identifier: BSD-2-Clause */ #include #include "stand.h" #include "efi.h" +#include "seg.h" 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 = roundup2(sizeof(struct efi_map_header), 16); 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); } } +/* XXX REFACTOR WITH KERNEL */ 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 print_efi_map(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); } + +static void +efi_map_entry_add_avail(struct efi_md *p, void *argp) +{ + bool *retval = argp; + + /* + * The kernel itself uses a lot more types as memory it can use. Be + * conservative here so we don't overwrite anything during the reboot + * process which copies the new kernel (so we can't use the Linux kenrel + * space for example). Anything that's not free, we simply don't add to + * the system ram space. We just need to find a big enough place we can + * land the kernel, and most of the other types we might use are + * typically too small anyway, even if we could safely use them. + */ + if (p->md_type != EFI_MD_TYPE_FREE) + return; + + /* + * The memory map is always disjoint, so we never have to remove avail. + */ + add_avail(p->md_phys, p->md_phys + p->md_pages * EFI_PAGE_SIZE - 1, + SYSTEM_RAM); + *retval = true; +} + +bool +populate_avail_from_efi(struct efi_map_header *efihdr) +{ + bool retval = false; + + init_avail(); + foreach_efi_map_entry(efihdr, efi_map_entry_add_avail, &retval); + return retval; +}