git: 988ee1cc6858 - main - kboot: Method to populate the avail array from EFI map

From: Warner Losh <imp_at_FreeBSD.org>
Date: Thu, 17 Apr 2025 21:59:16 UTC
The branch main has been updated by imp:

URL: https://cgit.FreeBSD.org/src/commit/?id=988ee1cc6858136298008df674c13fa17e943f1b

commit 988ee1cc6858136298008df674c13fa17e943f1b
Author:     Warner Losh <imp@FreeBSD.org>
AuthorDate: 2025-04-17 04:04:24 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2025-04-17 21:56:46 +0000

    kboot: Method to populate the avail array from EFI map
    
    If we can get an efi memory map, populate_avail_from_efi will create an
    avail array. We only use the regiions marked as 'free' to find a place
    for the kernel to land. The other regions are also eligible, but usually
    too small to materially affect where we'd put the kernel (not to worry,
    the kernel will use that memory).
    
    Sponsored by:           Netflix
    Reviewed by:            kevans, jhibbits
    Differential Revision:  https://reviews.freebsd.org/D49862
---
 stand/kboot/include/efi.h  |  1 +
 stand/kboot/libkboot/efi.c | 37 +++++++++++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+)

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
@@ -15,3 +15,4 @@ 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
@@ -7,6 +7,7 @@
 #include <sys/param.h>
 #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)
@@ -32,6 +33,7 @@ foreach_efi_map_entry(struct efi_map_header *efihdr, efi_map_entry_cb cb, void *
 	}
 }
 
+/* XXX REFACTOR WITH KERNEL */
 static void
 print_efi_map_entry(struct efi_md *p, void *argp __unused)
 {
@@ -95,3 +97,38 @@ print_efi_map(struct efi_map_header *efihdr)
 
 	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;
+}