aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWarner Losh <imp@FreeBSD.org>2026-06-26 14:47:31 +0000
committerWarner Losh <imp@FreeBSD.org>2026-06-26 14:54:36 +0000
commit59219fc76a4bde45039695373a662ad59432d451 (patch)
treecf97766b6e96632e3fc22fbfc51c85eba61bd555
parent3e3fd1fde8e168910edc538966111c0b5f03cd5f (diff)
loader.efi: efiblk_memdisk_preload passes the VirtualDisks to FreeBSD
Set hint.md.%d.physaddr and hint.md.%d.len for each of the VirtualDisks. The memory for these remains after we exit boot services so FreeBSD can use them. This leverages the BIOS work we did for memdisks. In hindsight, I should have passed this in via metadata, but it's been in a release. Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D57806
-rw-r--r--stand/efi/include/efilib.h1
-rw-r--r--stand/efi/libefi/efipart.c44
2 files changed, 45 insertions, 0 deletions
diff --git a/stand/efi/include/efilib.h b/stand/efi/include/efilib.h
index a387c808fe64..96de2a6344a2 100644
--- a/stand/efi/include/efilib.h
+++ b/stand/efi/include/efilib.h
@@ -68,6 +68,7 @@ pdinfo_list_t *efiblk_get_pdinfo_list(struct devsw *dev);
pdinfo_t *efiblk_get_pdinfo(struct devdesc *dev);
pdinfo_t *efiblk_get_pdinfo_by_handle(EFI_HANDLE h);
pdinfo_t *efiblk_get_pdinfo_by_device_path(EFI_DEVICE_PATH *path);
+void efiblk_memdisk_preload(void);
/* libefi.c */
void *efi_get_table(EFI_GUID *tbl);
diff --git a/stand/efi/libefi/efipart.c b/stand/efi/libefi/efipart.c
index c61a7fce2a47..e02993064d26 100644
--- a/stand/efi/libefi/efipart.c
+++ b/stand/efi/libefi/efipart.c
@@ -1250,3 +1250,47 @@ error:
free(blkbuf);
return (rc);
}
+
+/*
+ * Predicate: is this a VirtualDisk as far as UEFI is concerned?
+ */
+static bool
+testmd(pdinfo_t *hd, pdinfo_t *data __unused)
+{
+ EFI_DEVICE_PATH *node;
+
+ node = efi_devpath_last_node(hd->pd_devpath);
+ if (node == NULL)
+ return (false);
+ if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
+ DevicePathSubType(node) == MEDIA_RAM_DISK_DP)
+ return (true);
+
+ return (false);
+}
+
+/*
+ * Passes all the VirtualDisk instances to FreeBSD as a preloaded memory disk.
+ */
+void
+efiblk_memdisk_preload(void)
+{
+ MEDIA_RAM_DISK_DEVICE_PATH *ram;
+ uint64_t start, end;
+ pdinfo_t *md;
+ char key[32], value[32];
+ int i;
+
+ while ((md = efipart_get_pd(&pdinfo, testmd, NULL)) != NULL) {
+ ram = (MEDIA_RAM_DISK_DEVICE_PATH *)efi_devpath_last_node(md->pd_devpath);
+ i = ram->Instance;
+ start = ((uint64_t)ram->StartingAddr[1] << 32) | ram->StartingAddr[0];
+ end = ((uint64_t)ram->EndingAddr[1] << 32) | ram->EndingAddr[0];
+ snprintf(key, sizeof(key), "hint.md.%d.physaddr", i);
+ snprintf(value, sizeof(value), "0x%016x", start);
+ setenv(key, value, 1);
+ snprintf(key, sizeof(key), "hint.md.%d.len", i);
+ snprintf(value, sizeof(value), "0x%016x", end - start);
+ setenv(key, value, 1);
+ }
+}