/** 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; }
/** 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; }