diff options
| author | Warner Losh <imp@FreeBSD.org> | 2026-06-26 14:47:31 +0000 |
|---|---|---|
| committer | Warner Losh <imp@FreeBSD.org> | 2026-06-26 14:54:36 +0000 |
| commit | 59219fc76a4bde45039695373a662ad59432d451 (patch) | |
| tree | cf97766b6e96632e3fc22fbfc51c85eba61bd555 | |
| parent | 3e3fd1fde8e168910edc538966111c0b5f03cd5f (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.h | 1 | ||||
| -rw-r--r-- | stand/efi/libefi/efipart.c | 44 |
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); + } +} |
