예제 #1
0
/**
  Helper function to read a file.

  The data returned depends on the type of the underlying FV file:
  - For executable types, the first section found that contains executable code is returned.
  - For files of type FREEFORM, the driver attempts to return the first section of type RAW.
    If none is found, the entire contents of the FV file are returned.
  - On all other files the entire contents of the FV file is returned, as by
    EFI_FIRMWARE_VOLUME2_PROTOCOL.ReadFile.

  @param  FvProtocol                  A pointer to the EFI_FIRMWARE_VOLUME2_PROTOCOL instance.
  @param  FvFileInfo                  A pointer to the FV_FILESYSTEM_FILE_INFO instance that is a struct
                                      representing a file's info.
  @param  BufferSize                  Pointer to a caller-allocated UINTN. It indicates the size of
                                      the memory represented by *Buffer.
  @param  Buffer                      Pointer to a pointer to a data buffer to contain file content.

  @retval EFI_SUCCESS                 The call completed successfully.
  @retval EFI_WARN_BUFFER_TOO_SMALL   The buffer is too small to contain the requested output.
  @retval EFI_ACCESS_DENIED           The firmware volume is configured to disallow reads.
  @retval EFI_NOT_FOUND               The requested file was not found in the firmware volume.
  @retval EFI_DEVICE_ERROR            A hardware error occurred when attempting toaccess the firmware volume.

**/
EFI_STATUS
FvFsReadFile (
    IN     EFI_FIRMWARE_VOLUME2_PROTOCOL     *FvProtocol,
    IN     FV_FILESYSTEM_FILE_INFO           *FvFileInfo,
    IN OUT UINTN                             *BufferSize,
    IN OUT VOID                              **Buffer
)
{
    UINT32                         AuthenticationStatus;
    EFI_FV_FILETYPE                FoundType;
    EFI_FV_FILE_ATTRIBUTES         Attributes;
    EFI_STATUS                     Status;

    if (FV_FILETYPE_IS_EXECUTABLE (FvFileInfo->Type)) {
        //
        // Read the first executable section out of the file.
        //
        Status = FvFsFindExecutableSection (FvProtocol, FvFileInfo, BufferSize, Buffer);
    } else if (FvFileInfo->Type == EFI_FV_FILETYPE_FREEFORM) {
        //
        // Try to read a raw section out of the file
        //
        Status = FvProtocol->ReadSection (
                     FvProtocol,
                     &FvFileInfo->NameGuid,
                     EFI_SECTION_RAW,
                     0,
                     Buffer,
                     BufferSize,
                     &AuthenticationStatus
                 );
        if (EFI_ERROR (Status)) {
            //
            // Didn't find a raw section, just return the whole file.
            //
            Status = FvProtocol->ReadFile (
                         FvProtocol,
                         &FvFileInfo->NameGuid,
                         Buffer,
                         BufferSize,
                         &FoundType,
                         &Attributes,
                         &AuthenticationStatus
                     );
        }
    } else {
        //
        // Read the entire file
        //
        Status = FvProtocol->ReadFile (
                     FvProtocol,
                     &FvFileInfo->NameGuid,
                     Buffer,
                     BufferSize,
                     &FoundType,
                     &Attributes,
                     &AuthenticationStatus
                 );
    }

    return Status;
}
/**
  Open the root directory on a volume.

  @param  This     A pointer to the volume to open the root directory.
  @param  RootFile A pointer to the location to return the opened file handle for the
                   root directory.

  @retval EFI_SUCCESS          The device was opened.
  @retval EFI_UNSUPPORTED      This volume does not support the requested file system type.
  @retval EFI_NO_MEDIA         The device has no medium.
  @retval EFI_DEVICE_ERROR     The device reported an error.
  @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
  @retval EFI_ACCESS_DENIED    The service denied access to the file.
  @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.
  @retval EFI_MEDIA_CHANGED    The device has a different medium in it or the medium is no
                               longer supported. Any existing file handles for this volume are
                               no longer valid. To access the files on the new medium, the
                               volume must be reopened with OpenVolume().

**/
EFI_STATUS
EFIAPI
FvSimpleFileSystemOpenVolume (
  IN     EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
     OUT EFI_FILE_PROTOCOL               **RootFile
  )
{
  EFI_STATUS                      Status;
  FV_FILESYSTEM_FILE              *Root;
  CHAR16                          *UiSection;
  EFI_GUID                        NameGuid;
  EFI_FV_FILE_ATTRIBUTES          Attributes;
  UINT32                          Authentication;
  UINTN                           Key;
  EFI_FV_FILETYPE                 FileType;
  UINTN                           Size;
  FV_FILESYSTEM_INSTANCE          *Instance;
  FV_FILESYSTEM_FILE_INFO         *FvFileInfo;
  EFI_FIRMWARE_VOLUME2_PROTOCOL   *FvProtocol;
  CHAR16                          *Name;
  UINTN                           NameLen;
  UINTN                           NumChars;
  UINTN                           DestMax;

  Instance = FVFS_INSTANCE_FROM_SIMPLE_FS_THIS (This);
  Status = EFI_SUCCESS;

  if (Instance->Root == NULL) {
    //
    // Allocate file structure for root file
    //
    Root = AllocateZeroPool (sizeof (FV_FILESYSTEM_FILE));
    if (Root == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }

    Instance->Root  = Root;
    Root->Instance  = Instance;
    Root->Signature = FVFS_FILE_SIGNATURE;
    CopyMem (&Root->FileProtocol, &mFileSystemTemplate, sizeof (mFileSystemTemplate));
    Root->FvFileInfo = AllocateZeroPool (sizeof (FV_FILESYSTEM_FILE_INFO));
    if (Root->FvFileInfo == NULL) {
        return EFI_OUT_OF_RESOURCES;
    }
    Root->FvFileInfo->FileInfo.Size      = sizeof (EFI_FILE_INFO);
    Root->FvFileInfo->FileInfo.Attribute = EFI_FILE_DIRECTORY | EFI_FILE_READ_ONLY;

    //
    // Populate the instance's list of files. We consider anything a file that
    // has a UI_SECTION, which we consider to be its filename.
    //
    FvProtocol = Instance->FvProtocol;
    //
    // Allocate Key
    //
    Key = 0;

    do {
      FileType = EFI_FV_FILETYPE_ALL;

      Status = FvProtocol->GetNextFile (
                             FvProtocol,
                             &Key,
                             &FileType,
                             &NameGuid,
                             &Attributes,
                             &Size
                             );
      if (EFI_ERROR (Status)) {
        ASSERT (Status == EFI_NOT_FOUND);
        break;
      }

      //
      // Get a file's name: If it has a UI section, use that, otherwise use
      // its NameGuid.
      //
      UiSection = NULL;
      Status = FvProtocol->ReadSection (
                             FvProtocol,
                             &NameGuid,
                             EFI_SECTION_USER_INTERFACE,
                             0,
                             (VOID **)&UiSection,
                             &Size,
                             &Authentication
                             );
      if (!EFI_ERROR (Status)) {
        Name = UiSection;
      } else {
        Name = AllocateZeroPool (GUID_STRING_SIZE);
        if (Name == NULL) {
          return EFI_OUT_OF_RESOURCES;
        }
        NumChars = UnicodeSPrint (Name, GUID_STRING_SIZE, L"%g", &NameGuid);
        ASSERT ((NumChars + 1) * sizeof (CHAR16) == GUID_STRING_SIZE);
      }

      //
      // Found a file.
      // Allocate a file structure and populate it.
      //
      NameLen = StrSize (Name);
      if (FV_FILETYPE_IS_EXECUTABLE (FileType)) {
        NameLen += StrSize (L".efi") - sizeof (CHAR16);
      }

      FvFileInfo = AllocateZeroPool (sizeof (FV_FILESYSTEM_FILE_INFO) + NameLen - sizeof (CHAR16));
      if (FvFileInfo == NULL) {
        return EFI_OUT_OF_RESOURCES;
      }

      FvFileInfo->Signature = FVFS_FILE_INFO_SIGNATURE;
      InitializeListHead (&FvFileInfo->Link);
      CopyMem (&FvFileInfo->NameGuid, &NameGuid, sizeof (EFI_GUID));
      FvFileInfo->Type = FileType;

      //
      // Add ".efi" to filenames of drivers and applications.
      //
      DestMax = NameLen / sizeof (CHAR16);
      Status  = StrnCpyS (&FvFileInfo->FileInfo.FileName[0], DestMax, Name, StrLen (Name));
      ASSERT_EFI_ERROR (Status);

      if (FV_FILETYPE_IS_EXECUTABLE (FileType)) {
        Status  = StrnCatS (&FvFileInfo->FileInfo.FileName[0], DestMax, L".efi", StrLen (L".efi"));
        ASSERT_EFI_ERROR (Status);
      }

      FvFileInfo->FileInfo.Size     = sizeof (EFI_FILE_INFO) + NameLen - sizeof (CHAR16);
      Status = FvFsGetFileSize (FvProtocol, FvFileInfo);
      ASSERT_EFI_ERROR (Status);
      FvFileInfo->FileInfo.PhysicalSize = FvFileInfo->FileInfo.FileSize;
      FvFileInfo->FileInfo.Attribute    = EFI_FILE_READ_ONLY;

      InsertHeadList (&Instance->FileInfoHead, &FvFileInfo->Link);

      FreePool (Name);

    } while (TRUE);

    if (Status == EFI_NOT_FOUND) {
      Status = EFI_SUCCESS;
    }
  }

  Instance->Root->DirReadNext = FVFS_GET_FIRST_FILE_INFO (Instance);
  *RootFile = &Instance->Root->FileProtocol;
  return Status;
}
예제 #3
0
/**
  Get the size of the buffer that will be returned by FvFsReadFile.

  @param  FvProtocol                  A pointer to the EFI_FIRMWARE_VOLUME2_PROTOCOL instance.
  @param  FvFileInfo                  A pointer to the FV_FILESYSTEM_FILE_INFO instance that is a struct
                                      representing a file's info.

  @retval EFI_SUCCESS                 The file size was gotten correctly.
  @retval Others                      The file size wasn't gotten correctly.

**/
EFI_STATUS
FvFsGetFileSize (
    IN     EFI_FIRMWARE_VOLUME2_PROTOCOL     *FvProtocol,
    IN OUT FV_FILESYSTEM_FILE_INFO           *FvFileInfo
)
{
    UINT32                         AuthenticationStatus;
    EFI_FV_FILETYPE                FoundType;
    EFI_FV_FILE_ATTRIBUTES         Attributes;
    EFI_STATUS                     Status;
    UINT8                          IgnoredByte;
    VOID                           *IgnoredPtr;

    //
    // To get the size of a section, we pass 0 for BufferSize. But we can't pass
    // NULL for Buffer, as that will cause a return of INVALID_PARAMETER, and we
    // can't pass NULL for *Buffer, as that will cause the callee to allocate
    // a buffer of the sections size.
    //
    IgnoredPtr = &IgnoredByte;
    FvFileInfo->FileInfo.FileSize = 0;

    if (FV_FILETYPE_IS_EXECUTABLE (FvFileInfo->Type)) {
        //
        // Get the size of the first executable section out of the file.
        //
        Status = FvFsFindExecutableSection (FvProtocol, FvFileInfo, (UINTN*)&FvFileInfo->FileInfo.FileSize, &IgnoredPtr);
        if (Status == EFI_WARN_BUFFER_TOO_SMALL) {
            return EFI_SUCCESS;
        }
    } else if (FvFileInfo->Type == EFI_FV_FILETYPE_FREEFORM) {
        //
        // Try to get the size of a raw section out of the file
        //
        Status = FvProtocol->ReadSection (
                     FvProtocol,
                     &FvFileInfo->NameGuid,
                     EFI_SECTION_RAW,
                     0,
                     &IgnoredPtr,
                     (UINTN*)&FvFileInfo->FileInfo.FileSize,
                     &AuthenticationStatus
                 );
        if (Status == EFI_WARN_BUFFER_TOO_SMALL) {
            return EFI_SUCCESS;
        }
        if (EFI_ERROR (Status)) {
            //
            // Didn't find a raw section, just return the whole file's size.
            //
            return FvProtocol->ReadFile (
                       FvProtocol,
                       &FvFileInfo->NameGuid,
                       NULL,
                       (UINTN*)&FvFileInfo->FileInfo.FileSize,
                       &FoundType,
                       &Attributes,
                       &AuthenticationStatus
                   );
        }
    } else {
        //
        // Get the size of the entire file
        //
        return FvProtocol->ReadFile (
                   FvProtocol,
                   &FvFileInfo->NameGuid,
                   NULL,
                   (UINTN*)&FvFileInfo->FileInfo.FileSize,
                   &FoundType,
                   &Attributes,
                   &AuthenticationStatus
               );
    }

    return Status;
}