BIOS实战之读取文件---获取文件路径+最终读取

接上一节,获取文件路径实际上也是获取当前这个APP的路径,怎么获取这个APP的路径,这里需要用到一个EFI_LOADED_IMAGE_PROTOCOL,原理如下:

根据当前 Application 的 ImageHandle 取得对应的 Handle。
使用 HandleProtcol 直接打开加载在Application 上面的 EFI_LOADED_IMAGE_PROTOCOL。
在这个 Protocol上有 FilePath,就是当前 Image 的 Device Path Protocol

通过引用看下面的代码一目了然:

EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;

  Status = gBS->HandleProtocol(
                  gImageHandle, 
                  &gEfiLoadedImageProtocolGuid,
                  (void **)&LoadedImage
                  );
  if(EFI_ERROR(Status)) {
    Print(L"Application path error!\n");
    return Status;
  }

  EFI_DEVICE_PATH_PROTOCOL  *ptFilePath;

  ptFilePath  = LoadedImage->FilePath;

  if(!ptFilePath) {
    Print(L"Unkown media!\n");
    return Status;
  }

ok,又到了Device Path Protocol的环节,在设备路径,找到我们放置APP的设备:

while(!IsDevicePathEnd(ptFilePath)){
    if(DevicePathType(ptFilePath)==MEDIA_DEVICE_PATH && DevicePathSubType(ptFilePath)==MEDIA_FILEPATH_DP){
      break;
    }
    ptFilePath = NextDevicePathNode(ptFilePath);    
  }
  TmpPath = ((FILEPATH_DEVICE_PATH*)ptFilePath)->PathName;

那么这个TmpPath就是app的路径了,如\xxx\xxx\xxx\xx.efi,但是我们只需要路径,不需要app的名字,那么咱们就可以通过判断‘\’来将这个app名字去掉,那么最终的函数如下:

EFI_STATUS
GetAPPFolderPathStr(CHAR16 **Path)
{
  EFI_STATUS                Status;
  EFI_DEVICE_PATH_PROTOCOL  *ptFilePath;
  CHAR16                    *PathName, *TmpPath;
  UINTN                     StrSize;

  Status = EFI_SUCCESS;  
  PathName    = NULL;
   
  EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;

  Status = gBS->HandleProtocol(
                  gImageHandle, 
                  &gEfiLoadedImageProtocolGuid,
                  (void **)&LoadedImage
                  );
  if(EFI_ERROR(Status)) {
    Print(L"Application path error!\n");
    return Status;
  }
  ptFilePath  = LoadedImage->FilePath;

  if(!ptFilePath) {
    Print(L"Unkown media!\n");
    return Status;
  }
  
  while(!IsDevicePathEnd(ptFilePath)){
    if(DevicePathType(ptFilePath)==MEDIA_DEVICE_PATH && DevicePathSubType(ptFilePath)==MEDIA_FILEPATH_DP){
      break;
    }
    ptFilePath = NextDevicePathNode(ptFilePath);    
  }
  TmpPath = ((FILEPATH_DEVICE_PATH*)ptFilePath)->PathName;

  while ((TmpPath = StrStr (TmpPath+1, L"\\")) != NULL) {
    PathName = TmpPath;
  }

  if(PathName != NULL){
    StrSize = (PathName - ((FILEPATH_DEVICE_PATH*)ptFilePath)->PathName)*sizeof(CHAR16);
  }else{
    StrSize = 2;
  }

  PathName = (CHAR16 *)AllocateZeroPool(StrSize + 2);
  if(PathName==NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto ProcExit; 
  }

  TmpPath = ((FILEPATH_DEVICE_PATH*)ptFilePath)->PathName;
  CopyMem (PathName, TmpPath, StrSize);

  if(PathName[0] != L'\\'){
    Status = EFI_UNSUPPORTED;
    goto ProcExit;
  }
  *Path = PathName;

ProcExit:
  if(EFI_ERROR(Status) && PathName != NULL){
    FreePool(PathName);
    PathName = NULL; 
  }
  return Status;
}

获取这个路径之后咱们还需要将文件的名字加上,这个才是最终需要的:

EFI_STATUS
GetFullPathBaseOnAPPFolder (
  IN       CHAR16 *FileName,
  IN OUT   CHAR16 **FullPath
  )
{
  EFI_STATUS  Status;
  CHAR16      *AppFolder;
  UINTN       FullPathSize;
  CHAR16      *AppFullPath;
  CHAR16      Slash = L'\\';

  Status      = EFI_SUCCESS;
  AppFolder   = NULL;
  AppFullPath = NULL;

  if(FileName == NULL || FullPath == NULL){
    Status = EFI_INVALID_PARAMETER;
    goto ProcExit;
  }

  GetAPPFolderPathStr(&AppFolder);//上个函数的返回路径
  if (AppFolder == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto ProcExit;
  }
  FullPathSize = strsize(AppFolder) + strsize(FileName);
  AppFullPath  = AllocateZeroPool(FullPathSize);
  if(AppFullPath == NULL){
    Status = EFI_OUT_OF_RESOURCES;
    goto ProcExit;
  }
  if (strsize(AppFolder) > 4) { // '\' and '\0'
    CopyMem (AppFullPath, AppFolder, strsize(AppFolder) - 2); // skip '\0'
    CopyMem (AppFullPath + strsize(AppFolder)/2 - 1, &Slash, 2);
    CopyMem (AppFullPath + strsize(AppFolder)/2, FileName, strsize(FileName));
  } else {
    CopyMem (AppFullPath, FileName, strsize(FileName));
  }
  *FullPath = AppFullPath;

这个AppFullPath的内容就是xxx\xx\xxx.bmp

最终的读取函数,我们就可以把上述的函数串联起来:

EFI_STATUS
ReadFile (
  IN     CHAR16  *FileName,
  IN OUT UINT8   **FileBuffer,
  OUT    UINTN   *FileSize
)
{
  EFI_STATUS  Status;
  CHAR16      *FullPath;

  // get File full path
  Status = GetFullPathBaseOnAPPFolder(FileName, &FullPath);
  if(EFI_ERROR(Status)) {
    return Status;
  }

  Status = ReadFileInFS(FullPath, FileBuffer, FileSize);
  FreePool (FullPath);

  return Status;
}

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值