How Ventoy Chain-Boots WIM, IMG, and VHD Files Using the VDiskChain Mechanism
Ventoy creates an in-memory virtual block device containing a chain header and image chunks, presenting it to firmware as a physical disk so standard bootloaders can boot WIM, IMG, and VHD files without extraction.
The ventoy/Ventoy project enables booting from disk image files without unpackaging them. At the core of this capability lies the VDiskChain mechanism, which constructs a virtual disk device that chain-boots Windows Imaging Format (WIM), raw IMG, and Virtual Hard Disk (VHD/VHDX) files. This article examines the source code to explain how Ventoy transforms these file formats into bootable virtual block devices.
Architecture Overview of the VDiskChain Mechanism
Ventoy does not mount WIM, IMG, or VHD files as loopback devices. Instead, it builds a virtual block device composed of a chain header (ventoy_chain_head) and a series of image chunks (ventoy_img_chunk). This virtual device is registered with the UEFI firmware via a Block-IO protocol, allowing the firmware to treat the memory buffer as a physical disk. Any downstream bootloader—such as the Windows wimboot loader, GRUB, or a VHD-boot driver—reads the file exactly as if it were a physical drive.
The process follows three distinct stages:
- Detection and Preparation: Parsing the
vdisk=command line and loading the raw image data. - Chain Construction: Allocating the chain header, filling OS parameters, and mapping image chunks.
- Block-IO Installation: Registering the virtual device with the UEFI firmware and launching the boot file.
Stage 1: Image Detection and Preparation
When a user selects a .wim, .img, or .vhd file, Ventoy parses the command line argument vdisk= (or the internal flag set by GRUB commands vt_load_vhdboot or vt_load_wimboot). The system loads the raw image data into memory through the function vdisk_get_vdisk_raw.
In EDK2/…/VDiskChain/VDiskChain.c (lines 300–340), the vdisk_parse_cmdline function extracts the image path. If the image is compressed, vdisk_decompress_vdisk handles decompression. For WIM files, vdisk_patch_vdisk_path prepares the path string for later injection into the bootloader.
Stage 2: Building the Chain Header and Image Chunks
The core data structure is ventoy_chain_head, defined in include/ventoy.h (lines 17–38). This header stores:
- OS parameter block: Used by UEFI for boot services.
- Disk geometry:
disk_driveanddisk_sector_size. - Image metadata: Real and virtual image sizes.
- Chunk offsets: Pointers to
img_chunk,override_chunk, andvirt_chunkarrays.
In GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c, the function ventoy_alloc_chain allocates memory for the header plus the chunk array. The function ventoy_fill_os_param populates the UEFI OS parameters. The following code snippet from ventoy_cmd_load_wimboot illustrates this construction:
/* ventoy_cmd.c – part of vt_load_wimboot */
grub_err_t ventoy_cmd_load_wimboot (grub_extcmd_context_t ctxt,
int argc, char **args)
{
/* args[0] = path to the WIM file */
grub_file_t file = ventoy_grub_file_open (VENTOY_FILE_TYPE, "%s", args[0]);
/* Build the chain header */
size_t img_chunk_size = g_img_chunk_list.cur_chunk * sizeof (ventoy_img_chunk);
size_t chain_size = sizeof (ventoy_chain_head) + img_chunk_size;
ventoy_chain_head *chain = ventoy_alloc_chain (chain_size);
/* Fill OS parameter and geometry */
ventoy_fill_os_param (file, &(chain->os_param));
chain->disk_drive = file->device->disk->id;
chain->disk_sector_size = (1 << file->device->disk->log_sector_size);
chain->real_img_size_in_bytes = file->size;
chain->img_chunk_offset = sizeof (ventoy_chain_head);
chain->img_chunk_num = g_img_chunk_list.cur_chunk;
memcpy ((char *)chain + chain->img_chunk_offset,
g_img_chunk_list.chunk, img_chunk_size);
/* Export the chain address to the VDisk driver */
ventoy_memfile_env_set ("vtoy_chain_mem", chain, (ulonglong)chain_size);
grub_env_export ("vtoy_chain_mem_addr");
return GRUB_ERR_NONE;
}
Override chunks enable on-the-fly patching. For example, Ventoy injects the wimboot binary into a WIM file by creating an override chunk that patches the original image to reference the injected loader.
Stage 3: Virtual Block Device Installation
Once the chain is built, the UEFI-side driver installs the virtual block device. In VDiskChain.c, the function vdisk_install_blockio (lines 449–452) registers a Block-IO protocol and a Device-Path protocol with the firmware.
/* VDiskChain.c – called from VDiskChainEfiMain */
EFI_STATUS EFIAPI vdisk_install_blockio (EFI_HANDLE ImageHandle,
UINT64 ImgSize)
{
gVDiskBlockData.Media.BlockSize = 512;
gVDiskBlockData.Media.LastBlock = (ImgSize / 512) - 1;
gVDiskBlockData.Media.ReadOnly = TRUE;
/* Register the BlockIo and DevicePath protocols */
return gBS->InstallMultipleProtocolInterfaces (
&gVDiskBlockData.Handle,
&gEfiBlockIoProtocolGuid, &gVDiskBlockData.BlockIo,
&gEfiDevicePathProtocolGuid,gVDiskBlockData.Path,
NULL);
}
After installation, vdisk_boot searches for standard EFI boot files (bootx64.efi, grubx64.efi) on the virtual disk and launches them via gBS->StartImage. When the OS hands over control, Ventoy disconnects and uninstalls the virtual device.
Image-Type Specific Implementation
The VDiskChain mechanism adapts its behavior based on the file extension and content type.
WIM Files and wimboot Integration
For WIM files, Ventoy uses the wimboot loader (located in the wimboot/wimboot-2.7.3/src/ directory). The chain contains a VDisk-image of the wimboot binary plus an override chunk that patches the original WIM to reference wimboot. The function vdisk_patch_vdisk_path searches for the marker 0x59595959 (the string YYYY…Y inside wimboot) and overwrites it with the actual WIM path:
/* VDiskChain.c – vdisk_patch_vdisk_path */
STATIC EFI_STATUS vdisk_patch_vdisk_path (CHAR16 *pos)
{
/* The command line contains: vdisk=... .vtoy */
CHAR16 *end = StrStr (pos, L".vtoy");
end += 5; /* skip ".vtoy" */
CHAR8 *buf = (CHAR8 *)g_disk_buf_addr;
/* Locate the 32‑byte marker "YYYY...Y" and replace the
placeholder with the real WIM path. */
for (UINTN i = 0; i < g_disk_buf_size; ++i) {
if (*(UINT32 *)(buf + i) == 0x59595959) { /* "YYYY" */
CopyMem (buf + i, pos, (end - pos) * sizeof(CHAR16));
break;
}
}
return EFI_SUCCESS;
}
When the virtual disk boots, the firmware loads wimboot, which extracts the Windows image and hands control to bootmgr.exe.
Raw IMG Files
For IMG files, Ventoy presents the raw disk image directly without additional loaders. The first sector of the IMG typically contains a bootloader (such as SYSLINUX or GRUB) that executes directly from the virtual block device.
VHD and VHDX Files
For VHD/VHDX files, Ventoy uses vhdboot implemented in ventoy_vhd.c. The code parses the VHD footer, builds the partition table in memory, and patches the boot sector so the firmware can start Windows directly from the virtual hard disk. The chain holds the VHD file as a virtual block device, with override chunks fixing the BCD file and boot sector prior to handoff.
Key Source Files in ventoy/Ventoy
| File | Role |
|---|---|
EDK2/…/VDiskChain/VDiskChain.c |
Core UEFI driver: parses vdisk= command line, decompresses VDisk payload, patches paths, installs Block-IO and Device-Path protocols, and boots the first EFI file. |
EDK2/…/VDiskChain/VDiskChain.h |
Declarations for the driver-side API including vdisk_install_blockio and vdisk_get_vdisk_raw. |
EDK2/…/VDiskChain/VDiskRawData.c |
Stub replaced at runtime with raw wimboot/vhdboot binary data (the VDisk payload). |
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c |
GRUB command implementation (vt_load_wimboot, vt_load_vhdboot, ventoy_raw_chain_data) that allocates and populates ventoy_chain_head. |
GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_vhd.c |
VHD-specific handling: parses VHD footer, builds override chunks, and creates chains for VHD boot. |
wimboot/wimboot-2.7.3/src/* |
The wimboot loader source code used for WIM image extraction and boot. |
include/ventoy.h |
Shared structure definitions (ventoy_chain_head, ventoy_img_chunk, ventoy_override_chunk) used by both bootloader and VDisk driver. |
Summary
- VDiskChain creates a virtual block device in memory, eliminating the need to extract WIM, IMG, or VHD files to physical media.
- The
ventoy_chain_headstructure manages disk geometry, OS parameters, and pointers to image chunks stored in memory. - Block-IO protocol installation in
VDiskChain.cregisters the virtual device with UEFI firmware, enabling standard boot file loading. - Override chunks allow runtime patching—for example, injecting
wimbootinto WIM files or fixing VHD boot sectors—before the OS takes control. - The implementation spans both GRUB modules (
ventoy_cmd.c) and UEFI drivers (VDiskChain.c), with image-specific logic inventoy_vhd.cand thewimbootsub-project.
Frequently Asked Questions
What is the VDiskChain mechanism in Ventoy?
The VDiskChain mechanism is Ventoy's method for booting disk image files by constructing an in-memory virtual block device. It combines a chain header (ventoy_chain_head) with image chunks and registers the result as a UEFI Block-IO device, allowing the firmware to boot WIM, IMG, and VHD files as if they were physical disks.
How does Ventoy boot WIM files without extracting them?
Ventoy injects the wimboot loader into the WIM file using an override chunk. The vdisk_patch_vdisk_path function patches the wimboot binary with the actual WIM path, then registers the combination as a virtual disk. When booted, wimboot mounts the WIM internally and launches Windows, all without extracting the image to the USB drive.
What is the difference between IMG and VHD handling in VDiskChain?
IMG files are passed through as raw disk images—their first sector contains a bootloader that executes directly. VHD/VHDX files require additional processing: Ventoy parses the VHD footer, constructs a partition table in memory, and patches the boot sector via ventoy_vhd.c before presenting the virtual disk to the firmware.
Which source files contain the VDiskChain implementation?
The core implementation resides in EDK2/…/VDiskChain/VDiskChain.c (UEFI driver) and GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c (GRUB module). Structure definitions are in include/ventoy.h, while VHD-specific logic is in ventoy_vhd.c. The wimboot loader source is located in wimboot/wimboot-2.7.3/src/.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →