前面提到过 Ram Disk Protocol,这次尝试编写一个 Application 来完成创建 RamDisk 的动作。
首先看一下 Specification:
这个 Protocol 提供了2个函数,一个用来注册 RAM Disk 的Register,一个用来销毁 RAM Disk 的 Unregister。对于我们来说,注册的函数是最重要的。
注册一个Ram Disk 需要给定:
RamDiskBase: 新的 Ram Disk 的基地址
RamDiskSize: 新的 Ram Disk 的大小
RamDiskType: 新的 Ram Disk 的类型(似乎可以定义 ISO/RAW之类的)
ParentDevicePath: 指向父设备的 Device Path(不明白这个功能有什么意义)。如果没有可以设置为 NULL
DevicePath: 返回的创建的 Ram Disk 的 Device Path
有了上面的信息,我们即可完成创建工作。
编写一个测试代码,步骤如下:
1. 查找 RamDiskProtocol
2. 读取 “”MemTest.Img”到内存中
3. 用 RamDiskProtocol 的 Register 函数将上面的内存注册为 Ram Disk
完整代码:
/** @file A simple, basic, application showing how the Hello application could be built using the "Standard C Libraries" from StdLib. Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR> This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license. THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ #include <Library/BaseLib.h> #include <Uefi.h> #include <Library/UefiLib.h> #include <Library/PrintLib.h> #include <Library/ShellCEntryLib.h> #include <Protocol/RamDisk.h> #include <Protocol/DevicePathToText.h> #include <Protocol/EfiShell.h> #include <Library/ShellLib.h> extern EFI_BOOT_SERVICES *gBS; /* EFI_GUID gEfiVirtualDiskGuid = { 0x77AB535A, 0x45FC, 0x624B, {0x55, 0x60, 0xF7, 0xB2, 0x81, 0xD1, 0xF9, 0x6E }}; */ /*** Demonstrates basic workings of the main() function by displaying a welcoming message. Note that the UEFI command line is composed of 16-bit UCS2 wide characters. The easiest way to access the command line parameters is to cast Argv as: wchar_t **wArgv = (wchar_t **)Argv; @param[in] Argc Number of argument tokens pointed to by Argv. @param[in] Argv Array of Argc pointers to command line tokens. @retval 0 The application exited normally. @retval Other An error occurred. ***/ int main ( IN int Argc, IN char **Argv ) { EFI_STATUS Status; EFI_RAM_DISK_PROTOCOL *MyRamDisk; UINT64 *StartingAddr; EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_FILE_HANDLE FileHandle; EFI_FILE_INFO *FileInfo; UINTN ReadSize; // Look for Ram Disk Protocol Status = gBS->LocateProtocol ( &gEfiRamDiskProtocolGuid, NULL, &MyRamDisk ); if (EFI_ERROR (Status)) { Print(L"Couldn't find RamDiskProtocol\n"); return EFI_ALREADY_STARTED; } //Open one Image and load it to the memory //Open the file given by the parameter Status = ShellOpenFileByName( L"MemTest.IMG", (SHELL_FILE_HANDLE *)&FileHandle, EFI_FILE_MODE_READ, 0); if(EFI_ERROR (Status)) { Print(L"OpenFile failed! Error=[%r]\n",Status); return EFI_SUCCESS; } //Get file size FileInfo = ShellGetFileInfo((SHELL_FILE_HANDLE)FileHandle); //Allocate a memory for Image Status = gBS->AllocatePool ( EfiReservedMemoryType, (UINTN)FileInfo-> FileSize, (VOID**)&StartingAddr ); if(EFI_ERROR (Status)) { Print(L"Allocate Memory failed!\n"); return EFI_SUCCESS; } //Load the whole file to the buffer Status = ShellReadFile(FileHandle,&ReadSize,StartingAddr); if(EFI_ERROR (Status)) { Print(L"Read file failed!\n"); return EFI_SUCCESS; } // // Register the newly created RAM disk. // Status = MyRamDisk->Register ( ((UINT64)(UINTN) StartingAddr), FileInfo-> FileSize, &gEfiVirtualDiskGuid, NULL, &DevicePath ); if (EFI_ERROR (Status)) { Print(L"Can't create RAM Disk!\n"); return EFI_SUCCESS; } //Show RamDisk DevicePath { EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* Device2TextProtocol; CHAR16* TextDevicePath = 0; Status = gBS->LocateProtocol( &gEfiDevicePathToTextProtocolGuid, NULL, (VOID**)&Device2TextProtocol ); TextDevicePath = Device2TextProtocol->ConvertDevicePathToText(DevicePath, FALSE, TRUE); Print(L"DevicePath=%s\n", TextDevicePath); Print(L"Disk Size =%d Bytes\n", FileInfo-> FileSize); if(TextDevicePath)gBS->FreePool(TextDevicePath); } Print(L"Creat Ram Disk success!\n"); return 0; }
首先,可以看到系统中只有一个 Fs0:, 运行 mrd.efi 之后,系统中多了一个 Fs1,其中的内容就是 MemTest.Img的内容(使用的文件和之前的MemTest.Img 是相同的)。
编译生成的 X64 Application:
mrd
完整的代码:
MyRamDisk