我在UEFI的DXE阶段需要做一个RAM Disk。从 UEFI 规范的 2.6 版开始,有一个 RAM Disk 协议。我已经成功地使用它来制作 RAM 磁盘。此 RAM Disk 上还必须有 FAT32 系统。
我正在以编程方式构建这个 FAT32 分区 before 我安装 RAM 磁盘。从阅读规范来看,似乎firmware(即黑魔法),“..自动将 EFI_DISK_IO_PROTOCOL 添加到生成的任何 EFI_BLOCK_IO_PROTOCOL 接口。” (这在本段中讨论。)深入研究 RAM 磁盘 DXE 驱动程序,情况是固件为任何实例化的 RAM 磁盘生成 BLOCK_IO_PROTOCOL。
因此,从规范来看,似乎如果受支持的块设备或磁盘 I/O 设备上存在可识别的文件系统格式,固件应为此自动关联必要的协议。这不是正在发生的事情。使用 QEMU 测试我的固件卷,当 UEFI Shell 启动时,我有块设备的映射但没有 FSn 映射:
BLK1: Alias(s):
VirtualDisk(0x38B74018,0x3BB74017,0)
BLK2: Alias(s):
VirtualDisk(0x38B74018,0x3BB74017,0)/HD(1,GPT,CF0C3344-CAF3-46C5-A72B-920DFD878FB2,0x800,0x17000)
...
我正在实例化我的 RAM 磁盘
EFI_STATUS
EFIAPI
RegisterMyRd()
{
EFI_STATUS stat;
EFI_RAM_DISK_PROTOCOL *pRdProto;
EFI_DEVICE_PATH_PROTOCOL *pRdPathProto;
/* There is a static EFI_PHYSICAL_ADDRESS *pRamDisk for this compilation unit */
stat = gBS->LocateProtocol(
&gEfiRamDiskProtocolGuid,
NULL,
(VOID**)&pRdProto);
ASSERT_EFI_ERROR(stat);
stat = pRdProto->Register(
(UINT64)pRamDisk,
(UINT64)RAM_DISK_SIZE, /* a define for 1024 * 1024 * 48 */
&gEfiVirtualDiskGuid,
NULL,
&pRdPathProto);
ASSERT_EFI_ERROR(stat);
return stat;
}
所以,我的 RAM Disk 制作完成,甚至发现了 GUID 分区表。实例化了 BLOCK_IO_PROTOCOL(s),但由于某种原因,当调用 Shell 并提供映射时,没有预期的任何文件系统对象。虽然 48MiB RD 有点小,但使用与 QEMU 大小相同的“磁盘”就可以了,即
我必须将 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL 添加到 RAM 磁盘的设备句柄上吗?这是否意味着为
qemu-system-x86_64 ... -hda my_disk.img
实现我自己的功能,然后为
FS0:
实现许多功能?
为了完整起见,我正在回答我自己的问题。除了评论之外,对此没有任何吸引力。我确实找到了解决方案。我对规范的解释是正确的。当布局正确时,固件
简而言之,我让 FAT32 系统与有关它所在位置的信息不一致。现在是更深入的答案。
UEFI(又名固件)为整个驱动器和 GPT 中定义的分区制定块 I/O 协议有关详细信息,请参阅本节
。这是第二块未对齐的块。我正在为整个 RAM 磁盘和 GUID 分区表获取OpenVolume()
将 FAT32 结构(见规范
)放入 GUID 分区阵列条目声称的 LBA 后,出现预期的文件系统映射
EFI_FILE_PROTOCOL
.传递给VM的“硬盘”(用
FS0
和parted
制作的文件)。
感谢@MiSimon 提出关于
mkdosfs -F 32
对象是否在 RAM 磁盘上的问题。这个问题帮助我指明了正确的方向。