Step to UEFI (132)RamDisk Application 例子

前面提到过 Ram Disk Protocol,这次尝试编写一个 Application 来完成创建 RamDisk 的动作。
首先看一下 Specification:

rd1
rd2

这个 Protocol 提供了2个函数,一个用来注册 RAM Disk 的Register,一个用来销毁 RAM Disk 的 Unregister。对于我们来说,注册的函数是最重要的。

rd3

注册一个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;
}

 

运行结果:
rd4

首先,可以看到系统中只有一个 Fs0:, 运行 mrd.efi 之后,系统中多了一个 Fs1,其中的内容就是 MemTest.Img的内容(使用的文件和之前的MemTest.Img 是相同的)。

编译生成的 X64 Application:
mrd

完整的代码:
MyRamDisk

发表评论

电子邮件地址不会被公开。 必填项已用*标注