slimbootloader/BootloaderCommonPkg/Library/FileSystemLib/FileSystemLib.c

412 lines
12 KiB
C

/** @file
File system level API library interface
Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <PiPei.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/FileSystemLib.h>
#include <Library/PcdLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/FatLib.h>
#include <Library/Ext23Lib.h>
#define FILE_SYSTEM_CB_SIGNATURE SIGNATURE_32( 'F', 'S', 'C', 'B' )
#define FILE_CB_SIGNATURE SIGNATURE_32( 'F', 'I', 'C', 'B' )
typedef struct {
UINTN Signature;
EFI_HANDLE FsHandle;
LIST_ENTRY OpenFiles;
} FILE_SYSTEM_CONTROL_BLOCK;
typedef struct {
LIST_ENTRY Link;
UINTN Signature;
EFI_HANDLE FileHandle;
EFI_HANDLE FileSystemControlBlock;
} FILE_CONTROL_BLOCK;
STATIC BOOLEAN mFileSystemRegistered = FALSE;
STATIC FILE_SYSTEM_FUNC mFileSystemFuncs[EnumFileSystemTypeAuto];
STATIC
VOID
RegisterFileSystems (
VOID
)
{
OS_FILE_SYSTEM_TYPE FsType;
if (mFileSystemRegistered == FALSE) {
ZeroMem (&mFileSystemFuncs, sizeof (mFileSystemFuncs));
FsType = EnumFileSystemTypeFat;
if (FixedPcdGet32 (PcdSupportedFileSystemMask) & (1 << FsType)) {
mFileSystemFuncs[FsType].InitFileSystem = FatInitFileSystem;
mFileSystemFuncs[FsType].CloseFileSystem = FatCloseFileSystem;
mFileSystemFuncs[FsType].OpenFile = FatFsOpenFile;
mFileSystemFuncs[FsType].GetFileSize = FatFsGetFileSize;
mFileSystemFuncs[FsType].ReadFile = FatFsReadFile;
mFileSystemFuncs[FsType].CloseFile = FatFsCloseFile;
}
FsType = EnumFileSystemTypeExt2;
if (FixedPcdGet32 (PcdSupportedFileSystemMask) & (1 << FsType)) {
mFileSystemFuncs[FsType].InitFileSystem = ExtInitFileSystem;
mFileSystemFuncs[FsType].CloseFileSystem = ExtCloseFileSystem;
mFileSystemFuncs[FsType].OpenFile = ExtFsOpenFile;
mFileSystemFuncs[FsType].GetFileSize = ExtFsGetFileSize;
mFileSystemFuncs[FsType].ReadFile = ExtFsReadFile;
mFileSystemFuncs[FsType].CloseFile = ExtFsCloseFile;
}
mFileSystemRegistered = TRUE;
}
}
STATIC
OS_FILE_SYSTEM_TYPE
EFIAPI
GetFileSystemType (
IN EFI_HANDLE FsHandle
)
{
UINTN Signature;
OS_FILE_SYSTEM_TYPE FsType;
FsType = EnumFileSystemMax;
if (FsHandle != NULL) {
Signature = *(UINTN *)FsHandle;
if (Signature == FS_FAT_SIGNATURE) {
FsType = EnumFileSystemTypeFat;
} else if (Signature == FS_EXT_SIGNATURE) {
FsType = EnumFileSystemTypeExt2;
}
}
return FsType;
}
/**
Initialize file systems.
@param[in] SwPart Software partition index.
@param[in] FsType Filesystem type.
@param[in] PartHandle Partition handle.
@param[out] FsHandle FAT file system handle.
@retval EFI_SUCCESS The file system was initialized successfully.
@retval EFI_INVALID_PARAMETER Parameter is not valid.
@retval EFI_NOT_FOUND FAT file system was not detected on this partition.
@retval EFI_OUT_OF_RESOURCES Insufficant memory resource pool.
**/
EFI_STATUS
EFIAPI
InitFileSystem (
IN UINT32 SwPart,
IN UINT32 FsType,
IN EFI_HANDLE PartHandle,
OUT EFI_HANDLE *FsHandle
)
{
EFI_STATUS Status;
UINT32 Type;
EFI_HANDLE Handle;
FILE_SYSTEM_CONTROL_BLOCK *FileSystemControlBlock;
Status = EFI_INVALID_PARAMETER;
if (FsType >= EnumFileSystemMax) {
return Status;
}
RegisterFileSystems ();
for (Type = EnumFileSystemTypeFat; Type < EnumFileSystemTypeAuto; Type++) {
if (mFileSystemFuncs[Type].InitFileSystem == NULL) {
continue;
}
if ((FsType == EnumFileSystemTypeAuto) || (FsType == Type)) {
Handle = NULL;
Status = mFileSystemFuncs[Type].InitFileSystem (SwPart, PartHandle, &Handle);
if (!EFI_ERROR (Status)) {
break;
}
if (Handle != NULL) {
mFileSystemFuncs[Type].CloseFileSystem (Handle);
}
}
}
if (!EFI_ERROR (Status)) {
FileSystemControlBlock = (FILE_SYSTEM_CONTROL_BLOCK *) AllocatePool (sizeof (FILE_SYSTEM_CONTROL_BLOCK));
FileSystemControlBlock->Signature = FILE_SYSTEM_CB_SIGNATURE;
FileSystemControlBlock->FsHandle = Handle;
InitializeListHead (&FileSystemControlBlock->OpenFiles);
*FsHandle = (EFI_HANDLE)FileSystemControlBlock;
}
return Status;
}
/**
Clean-up allocated memory/etc. for file system
@param[in] FsHandle File system handle to clean-up.
@retval none
**/
VOID
EFIAPI
CloseFileSystem (
IN EFI_HANDLE FsHandle
)
{
OS_FILE_SYSTEM_TYPE FsType;
FILE_SYSTEM_CONTROL_BLOCK *FileSystemControlBlock;
FILE_CONTROL_BLOCK *FileControlBlock;
LIST_ENTRY *Node;
FileSystemControlBlock = (FILE_SYSTEM_CONTROL_BLOCK *)FsHandle;
if (FileSystemControlBlock == NULL) {
return;
}
FsType = GetFileSystemType (FileSystemControlBlock->FsHandle);
if (FsType >= EnumFileSystemTypeAuto) {
return;
}
Node = GetFirstNode (&FileSystemControlBlock->OpenFiles);
while (!IsNull (&FileSystemControlBlock->OpenFiles, Node)) {
FileControlBlock = (FILE_CONTROL_BLOCK *)Node;
if (FileControlBlock->Signature == FILE_CB_SIGNATURE) {
DEBUG ((DEBUG_INFO, " Close file handle 0x%p\n", FileControlBlock->FileHandle));
CloseFile (FileControlBlock);
}
Node = GetNextNode (&FileSystemControlBlock->OpenFiles, Node);
}
if (mFileSystemFuncs[FsType].CloseFileSystem == NULL) {
return;
}
mFileSystemFuncs[FsType].CloseFileSystem (FileSystemControlBlock->FsHandle);
FreePool (FileSystemControlBlock);
DEBUG ((DEBUG_INFO, "CloseFileSystem: FsType %d\n", FsType));
}
/**
Open a file by its name and return its file handle.
@param[in] FsHandle file system handle.
@param[in] FileName The file name to get.
@param[out] FileHandle file handle
@retval EFI_SUCCESS The file opened correctly.
@retval EFI_INVALID_PARAMETER Parameter is not valid.
@retval EFI_DEVICE_ERROR A device error occurred.
@retval EFI_NOT_FOUND A requested file cannot be found.
@retval EFI_OUT_OF_RESOURCES Insufficant memory resource pool.
**/
EFI_STATUS
EFIAPI
OpenFile (
IN EFI_HANDLE FsHandle,
IN CHAR16 *FileName,
OUT EFI_HANDLE *FileHandle
)
{
EFI_STATUS Status;
OS_FILE_SYSTEM_TYPE FsType;
EFI_HANDLE FsFileHandle;
FILE_SYSTEM_CONTROL_BLOCK *FileSystemControlBlock;
FILE_CONTROL_BLOCK *FileControlBlock;
FileSystemControlBlock = (FILE_SYSTEM_CONTROL_BLOCK *)FsHandle;
ASSERT (FileSystemControlBlock != NULL);
if (FileSystemControlBlock == NULL) {
return EFI_INVALID_PARAMETER;
}
FsType = GetFileSystemType (FileSystemControlBlock->FsHandle);
if (FsType >= EnumFileSystemTypeAuto) {
return EFI_NOT_READY;
}
if (mFileSystemFuncs[FsType].OpenFile == NULL) {
return EFI_UNSUPPORTED;
}
Status = mFileSystemFuncs[FsType].OpenFile (FileSystemControlBlock->FsHandle, FileName, &FsFileHandle);
if (EFI_ERROR (Status)) {
return Status;
}
FileControlBlock = (FILE_CONTROL_BLOCK *) AllocatePool (sizeof (FILE_CONTROL_BLOCK));
if (FileControlBlock == NULL) {
return EFI_OUT_OF_RESOURCES;
}
FileControlBlock->Signature = FILE_CB_SIGNATURE;
FileControlBlock->FileHandle = FsFileHandle;
FileControlBlock->FileSystemControlBlock = FileSystemControlBlock;
InsertTailList (&FileSystemControlBlock->OpenFiles, &FileControlBlock->Link);
*FileHandle = (EFI_HANDLE) FileControlBlock;
return Status;
}
/**
Get file size by opened file handle.
@param[in] FileHandle file handle
@param[out] FileSize Pointer to file buffer size.
@retval EFI_SUCCESS The file was loaded correctly.
@retval EFI_INVALID_PARAMETER Parameter is not valid.
**/
EFI_STATUS
EFIAPI
GetFileSize (
IN EFI_HANDLE FileHandle,
OUT UINTN *FileSize
)
{
OS_FILE_SYSTEM_TYPE FsType;
FILE_SYSTEM_CONTROL_BLOCK *FileSystemControlBlock;
FILE_CONTROL_BLOCK *FileControlBlock;
FileControlBlock = (FILE_CONTROL_BLOCK *)FileHandle;
ASSERT (FileControlBlock != NULL);
if (FileControlBlock == NULL) {
return EFI_INVALID_PARAMETER;
}
ASSERT (FileControlBlock->Signature == FILE_CB_SIGNATURE);
FileSystemControlBlock = (FILE_SYSTEM_CONTROL_BLOCK *)FileControlBlock->FileSystemControlBlock;
ASSERT (FileSystemControlBlock->Signature == FILE_SYSTEM_CB_SIGNATURE);
FsType = GetFileSystemType (FileSystemControlBlock->FsHandle);
if (FsType >= EnumFileSystemTypeAuto) {
return EFI_NOT_READY;
}
if (mFileSystemFuncs[FsType].GetFileSize == NULL) {
return EFI_UNSUPPORTED;
}
return mFileSystemFuncs[FsType].GetFileSize (FileControlBlock->FileHandle, FileSize);
}
/**
Read file into memory by opened file handle.
@param[in] FileHandle file handle
@param[out] FileBufferPtr Allocated file buffer pointer.
@param[out] FileSize Pointer to file buffer size.
@retval EFI_SUCCESS The file was loaded correctly.
@retval EFI_INVALID_PARAMETER Parameter is not valid.
@retval EFI_DEVICE_ERROR A device error occurred.
@retval EFI_NOT_FOUND A requested file cannot be found.
@retval EFI_OUT_OF_RESOURCES Insufficant memory resource pool.
@retval EFI_BUFFER_TOO_SMALL Buffer size is too small.
**/
EFI_STATUS
EFIAPI
ReadFile (
IN EFI_HANDLE FileHandle,
OUT VOID **FileBuffer,
OUT UINTN *FileSize
)
{
OS_FILE_SYSTEM_TYPE FsType;
FILE_SYSTEM_CONTROL_BLOCK *FileSystemControlBlock;
FILE_CONTROL_BLOCK *FileControlBlock;
ASSERT (FileHandle != NULL);
if (FileHandle == NULL) {
return EFI_INVALID_PARAMETER;
}
ASSERT (*FileBuffer != NULL);
if (*FileBuffer == NULL) {
return EFI_INVALID_PARAMETER;
}
FileControlBlock = (FILE_CONTROL_BLOCK *)FileHandle;
ASSERT (FileControlBlock->Signature == FILE_CB_SIGNATURE);
FileSystemControlBlock = (FILE_SYSTEM_CONTROL_BLOCK *)FileControlBlock->FileSystemControlBlock;
ASSERT (FileSystemControlBlock->Signature == FILE_SYSTEM_CB_SIGNATURE);
FsType = GetFileSystemType (FileSystemControlBlock->FsHandle);
if (FsType >= EnumFileSystemTypeAuto) {
return EFI_NOT_READY;
}
if (mFileSystemFuncs[FsType].ReadFile == NULL) {
return EFI_UNSUPPORTED;
}
return mFileSystemFuncs[FsType].ReadFile (FileSystemControlBlock->FsHandle, FileControlBlock->FileHandle, FileBuffer, FileSize);
}
/**
Close a file by opened file handle
@param[in] FileHandle file handle
@retval none
**/
VOID
EFIAPI
CloseFile (
IN EFI_HANDLE FileHandle
)
{
OS_FILE_SYSTEM_TYPE FsType;
FILE_SYSTEM_CONTROL_BLOCK *FileSystemControlBlock;
FILE_CONTROL_BLOCK *FileControlBlock;
FileControlBlock = (FILE_CONTROL_BLOCK *)FileHandle;
ASSERT (FileControlBlock != NULL);
ASSERT (FileControlBlock->Signature == FILE_CB_SIGNATURE);
if (FileControlBlock == NULL || FileControlBlock->Signature != FILE_CB_SIGNATURE) {
return;
}
FileSystemControlBlock = (FILE_SYSTEM_CONTROL_BLOCK *)FileControlBlock->FileSystemControlBlock;
ASSERT (FileSystemControlBlock != NULL);
ASSERT (FileSystemControlBlock->Signature == FILE_SYSTEM_CB_SIGNATURE);
if (FileSystemControlBlock == NULL) {
return;
}
FsType = GetFileSystemType (FileSystemControlBlock->FsHandle);
if (FsType >= EnumFileSystemTypeAuto) {
return;
}
if (mFileSystemFuncs[FsType].CloseFile == NULL) {
return;
}
RemoveEntryList (&FileControlBlock->Link);
mFileSystemFuncs[FsType].CloseFile (FileControlBlock->FileHandle);
FreePool (FileControlBlock);
}