AxlRamDisk — FAT RAM disks over EFI_RAM_DISK_PROTOCOL
FAT RAM disks over EFI_RAM_DISK_PROTOCOL.
Header: <axl/axl-ramdisk.h>. A RAM disk is a block of allocated
memory registered with the firmware as a virtual block device,
FAT-formatted so the firmware binds its filesystem driver and the
volume appears as an fsN: mapping — scratch space, file staging, or
the backing store of a virtual-media feature.
This module is the create/list/destroy orchestration lifted out of the
mkrd tool (FAT16/FAT32 formatters, page allocation, Register /
Unregister, volume enumeration, the duplicate-label check) so any
consumer reuses it instead of copying ~250 lines from a tool. mkrd is
now a thin CLI over it.
// Ensure the protocol is available (firmware -> disk -> embedded
// fallback), then create a 64 MB disk labelled "SCRATCH".
axl_ramdisk_ensure_driver(NULL, 0, NULL);
void *dp = NULL;
if (axl_ramdisk_create("SCRATCH", 64, &dp) == AXL_OK) {
// ... fsN: now resolves to the new FAT volume ...
}
EFI_RAM_DISK_PROTOCOL is optional in UEFI 2.6+ and absent on some
firmware. axl_ramdisk_ensure_driver resolves it in order: already
published → a RamDiskDxe.efi found on a mounted volume → an embedded
RamDiskDxe image supplied by the caller. The embedded image is a
parameter (not baked into libaxl.a) so only binaries that want the
fallback carry the ~tens-of-KB blob; declare it with AXL_EMBED_DECLARE
the build’s blob-embedding rule and pass
AXL_EMBED_DATA/AXL_EMBED_SIZE(seetools/mkrd.c). A vendored RamDiskDxe.efi per arch lives inthird_party/edk2/.
The registered device path embeds the backing memory’s physical address
(VirtualDisk(0x...,...)), which is wherever AllocatePages lands and
varies run to run — it is not stable across boots or binaries. The
stable cross-boot handle is the FAT label, which is why
axl_ramdisk_destroy keys on it.
Registering a pre-populated image (virtual media)
axl_ramdisk_register_image registers an already-populated,
page-aligned buffer without formatting — for mounting an uploaded
.iso / .img as a virtual block device (the iDRAC “Virtual Media”
shape). AxlRamDiskKind picks the firmware-recognized type GUID:
AXL_RAMDISK_CDROM (gEfiVirtualCdGuid, an El Torito CD-ROM for a
bootable ISO) or AXL_RAMDISK_DISK (gEfiVirtualDiskGuid, a raw disk
image). It connects controllers so the firmware binds its block / FAT /
ISO9660 drivers and the device enumerates.
// Mount an uploaded ISO as a bootable virtual CD-ROM.
uint64_t pages = (size + 4095) / 4096, phys = 0;
axl_alloc_pages(pages, &phys);
void *img = (void *)(uintptr_t)phys;
// ... read the .iso bytes into img (e.g. via axl_file_view) ...
void *dp = NULL;
axl_ramdisk_register_image(img, size, AXL_RAMDISK_CDROM, &dp);
// ... device now enumerates / is bootable ...
axl_ramdisk_unregister(dp);
axl_free_pages(phys, pages); // caller owns the buffer
Ownership differs from create/destroy: the image buffer is
caller-owned and not copied, so it must stay valid until
axl_ramdisk_unregister, and the caller frees it (axl_free_pages)
afterward — unregister only detaches the device.
Scope is create / list / destroy / register-image of the device; reading
and writing its files is <axl/axl-fs.h> over the resulting fsN:.
API Reference
Create, enumerate, and destroy FAT RAM disks over EFI_RAM_DISK_PROTOCOL.
A RAM disk is a block of allocated memory registered with the firmware as a virtual block device, FAT-formatted so the firmware binds its filesystem driver and the volume appears as an fsN: mapping. Useful for scratch space, staging files a tool produces, or the backing store of a virtual-media feature.
// Make the protocol available (embedded fallback optional), then
// create a 64 MB disk labelled "SCRATCH".
axl_ramdisk_ensure_driver(NULL, 0, NULL);
void *dp = NULL;
if (axl_ramdisk_create("SCRATCH", 64, &dp) == AXL_OK) {
// ... fsN: now resolves to the new FAT volume ...
}
EFI_RAM_DISK_PROTOCOL is optional in UEFI 2.6+ and absent on some firmware; axl_ramdisk_ensure_driver loads a RamDiskDxe driver when the firmware doesn’t already publish it. The orchestration here is lifted from the mkrd tool so any consumer reuses it instead of copying the FAT formatters and the driver-ensure flow.
Scope is create / list / destroy of the device. Reading and writing the disk’s files is <axl/axl-fs.h> over the resulting fsN:.
Enums
-
enum AxlRamDiskKind
Image kind for
axl_ramdisk_register_image— the RAM-disk type GUID the firmware sees.An El Torito CD-ROM (a bootable
.iso, exposed as a CD device) or a raw hard-disk image (a.img, exposed as a block device).Values:
-
enumerator AXL_RAMDISK_DISK
gEfiVirtualDiskGuid — raw block image
-
enumerator AXL_RAMDISK_CDROM
gEfiVirtualCdGuid — El Torito CD-ROM
-
enumerator AXL_RAMDISK_DISK
Functions
-
int axl_ramdisk_ensure_driver(const unsigned char *dxe_image, size_t dxe_image_size, const char *override_name)
Ensure EFI_RAM_DISK_PROTOCOL is available.
Resolves the protocol in order: (1) already published by the firmware, (2) a RamDiskDxe driver found on a mounted volume, (3) the embedded image supplied here. Wraps
axl_driver_ensure_with_embeddedfor the RAM-disk GUID — the non-trivial firmware/disk/embedded fallback every RAM-disk consumer needs.The embedded image is a parameter rather than baked into the library so binaries that never make a RAM disk don’t carry the ~tens-of-KB RamDiskDxe.efi blob. Consumers wanting the embedded fallback declare the blob with
AXL_EMBED_DECLARE/ the build’s blob-embedding rule and passAXL_EMBED_DATA/AXL_EMBED_SIZE(see themkrdtool).When
override_nameis set, the disk search uses it and the embedded fallback is not used (matchesaxl_driver_ensure_with_embedded).- Parameters:
dxe_image – embedded RamDiskDxe.efi bytes, or NULL to skip the embedded fallback
dxe_image_size – length of
dxe_image(0 if NULL)override_name – driver filename to search instead of “RamDiskDxe.efi” (NULL for the default)
- Returns:
AXL_OK if the protocol is now available, AXL_ERR if every resolution step failed.
-
int axl_ramdisk_create(const char *label, size_t size_mb, void **dev_path_out)
Allocate, FAT-format, and register a RAM disk.
Allocates
size_mbof page-aligned memory, formats it FAT16 (size_mb <= 512) or FAT32 (larger) withlabelas the volume label, and registers it via EFI_RAM_DISK_PROTOCOL. Blocks ~0.5s for the firmware to bind its FAT driver, then refreshes the volume map so the disk is immediately enumerable and reachable asfsN:(relevant for a consumer creating one at boot).Requires the protocol — call
axl_ramdisk_ensure_driverfirst (or run on firmware that publishes it).size_mbmust be in the range 1..32768; values outside it return AXL_ERR. Idempotent on the label: if a RAM disk withlabelalready exists, returns AXL_OK without allocating again and setsdev_path_outto the existing disk’s device path.Note the registered device path embeds the backing memory’s physical address (e.g.
VirtualDisk(0x17F5D000,...)), which is wherever the allocation lands — it varies run to run, so it is not stable across boots or binaries. (The stable cross-boot handle is the label, which is whyaxl_ramdisk_destroykeys on it.) The returned device path is firmware-owned and valid until this disk is destroyed.- Parameters:
label – FAT volume label (uppercased, truncated to 11 chars)
size_mb – disk size in MB (1..32768)
dev_path_out – [out] firmware-owned device path, or NULL if unwanted (do not free)
- Returns:
AXL_OK on success (or an existing same-label disk), AXL_ERR if the protocol is unavailable,
size_mbis out of range, allocation fails, or registration fails.
-
int axl_ramdisk_destroy(const char *label)
Destroy a RAM disk by FAT label.
Unregisters the matching RAM disk and frees its backing memory. The label match is case-insensitive and ignores trailing padding;
labelis truncated to the stored 11-char FAT label before comparing, so passing the same (possibly long) label given toaxl_ramdisk_creatematches.- Parameters:
label – FAT volume label to destroy
- Returns:
AXL_OK on success, AXL_ERR if the protocol is unavailable or no RAM disk with
labelis found.
-
int axl_ramdisk_list(AxlRamDisk *out, size_t cap, size_t *count)
List the registered RAM disks.
Fills
outwith up tocapdescriptors and writes the total tocount. (out == NULL/cap == 0reports the count only.) An empty result is success with*count == 0.- Parameters:
out – output array (may be NULL to count only)
cap – capacity of
outcount – [out] number of RAM disks found
- Returns:
AXL_OK on success, AXL_ERR on bad arguments.
-
int axl_ramdisk_register_image(void *image, uint64_t size_bytes, AxlRamDiskKind kind, void **dev_path_out)
Register an already-populated, page-aligned image buffer as a typed RAM disk via EFI_RAM_DISK_PROTOCOL — WITHOUT formatting.
Unlike
axl_ramdisk_create(which allocates and FAT-formats a blank scratch disk), this registers caller-owned memory verbatim, so an uploaded OS image boots as-is: the image carries its own filesystem (ISO9660 for a CD-ROM, a partition / FAT image for a disk).kindselects the firmware-recognized type GUID — CD-ROM vs raw disk. After registering, the firmware’s controllers are connected so it binds its block / FAT / ISO9660 drivers and the device enumerates (a bootable image becomes a boot option). The connect is global (equivalent to the shell’sconnect -r) — heavier than a targeted connect, but it only binds drivers, never unbinds, so it does not disturb controllers already in use (e.g. a running server’s NICs).Ownership:
imageis caller-owned and is NOT copied — it must be page-aligned (allocate withaxl_alloc_pages) and MUST stay valid untilaxl_ramdisk_unregister. The caller frees it (withaxl_free_pages) AFTER unregistering — this call never takes ownership of the memory (contrastaxl_ramdisk_create/axl_ramdisk_destroy, which own and free the disk they allocate).Requires the protocol — call
axl_ramdisk_ensure_driverfirst (or run on firmware that publishes it). The returned device path is firmware-owned (do not free) and valid untilaxl_ramdisk_unregister. Note it embeds the backing memory’s physical address, so it is not stable across boots; it is the handle you pass back to unregister.- Parameters:
image – page-aligned image bytes (caller-owned; keep valid until unregister)
size_bytes – image length in bytes
kind – CD-ROM vs raw disk type GUID
dev_path_out – [out] firmware-owned device path (do not free), or NULL if unwanted
- Returns:
AXL_OK on success, or AXL_ERR if the protocol is unavailable,
imageis NULL,size_bytesis 0,kindis invalid, or registration fails.
-
int axl_ramdisk_unregister(void *dev_path)
Unregister a RAM disk by the device path returned from
axl_ramdisk_register_image.Unregisters the device via EFI_RAM_DISK_PROTOCOL. Does NOT free the backing memory — the caller frees its
axl_alloc_pagesbuffer afterward (the symmetric who-allocates-frees contract; contrastaxl_ramdisk_destroy, which owns and frees the FAT disk it created).- Parameters:
dev_path – device path from axl_ramdisk_register_image
- Returns:
AXL_OK on success, or AXL_ERR if
dev_pathis NULL, the protocol is unavailable, or no RAM disk matchesdev_path.
-
struct AxlRamDisk
- #include <axl-ramdisk.h>
A registered RAM disk, as reported by
axl_ramdisk_list.