/** @file | |
* | |
* Copyright (c) 2012-2014, ARM Limited. All rights reserved. | |
* | |
* 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.php | |
* | |
* 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 "BootMonFsInternal.h" | |
EFIAPI | |
EFI_STATUS | |
OpenBootMonFsOpenVolume ( | |
IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, | |
OUT EFI_FILE_PROTOCOL **Root | |
) | |
{ | |
BOOTMON_FS_INSTANCE *Instance; | |
Instance = BOOTMON_FS_FROM_FS_THIS (This); | |
if (Instance == NULL) { | |
return EFI_DEVICE_ERROR; | |
} | |
Instance->RootFile->Info->Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY; | |
*Root = &Instance->RootFile->File; | |
return EFI_SUCCESS; | |
} | |
UINT32 | |
BootMonFsGetImageLength ( | |
IN BOOTMON_FS_FILE *File | |
) | |
{ | |
UINT32 Index; | |
UINT32 FileSize; | |
LIST_ENTRY *RegionToFlushLink; | |
BOOTMON_FS_FILE_REGION *Region; | |
FileSize = 0; | |
// Look at all Flash areas to determine file size | |
for (Index = 0; Index < HW_IMAGE_DESCRIPTION_REGION_MAX; Index++) { | |
FileSize += File->HwDescription.Region[Index].Size; | |
} | |
// Add the regions that have not been flushed yet | |
for (RegionToFlushLink = GetFirstNode (&File->RegionToFlushLink); | |
!IsNull (&File->RegionToFlushLink, RegionToFlushLink); | |
RegionToFlushLink = GetNextNode (&File->RegionToFlushLink, RegionToFlushLink) | |
) | |
{ | |
Region = (BOOTMON_FS_FILE_REGION*)RegionToFlushLink; | |
if (Region->Offset + Region->Size > FileSize) { | |
FileSize += Region->Offset + Region->Size; | |
} | |
} | |
return FileSize; | |
} | |
UINTN | |
BootMonFsGetPhysicalSize ( | |
IN BOOTMON_FS_FILE* File | |
) | |
{ | |
// Return 0 for files that haven't yet been flushed to media | |
if (File->HwDescription.RegionCount == 0) { | |
return 0; | |
} | |
return ((File->HwDescription.BlockEnd - File->HwDescription.BlockStart) + 1 ) | |
* File->Instance->Media->BlockSize; | |
} | |
EFIAPI | |
EFI_STATUS | |
BootMonFsSetDirPosition ( | |
IN EFI_FILE_PROTOCOL *This, | |
IN UINT64 Position | |
) | |
{ | |
BOOTMON_FS_FILE *File; | |
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This); | |
if (File == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
// UEFI Spec section 12.5: | |
// "The seek request for nonzero is not valid on open directories." | |
if (Position != 0) { | |
return EFI_UNSUPPORTED; | |
} | |
File->Position = Position; | |
return EFI_SUCCESS; | |
} | |
EFI_STATUS | |
BootMonFsOpenDirectory ( | |
OUT EFI_FILE_PROTOCOL **NewHandle, | |
IN CHAR16 *FileName, | |
IN BOOTMON_FS_INSTANCE *Volume | |
) | |
{ | |
ASSERT(0); | |
return EFI_UNSUPPORTED; | |
} | |
STATIC | |
EFI_STATUS | |
GetFileSystemVolumeLabelInfo ( | |
IN BOOTMON_FS_INSTANCE *Instance, | |
IN OUT UINTN *BufferSize, | |
OUT VOID *Buffer | |
) | |
{ | |
UINTN Size; | |
EFI_FILE_SYSTEM_VOLUME_LABEL *Label; | |
EFI_STATUS Status; | |
Label = Buffer; | |
// Value returned by StrSize includes null terminator. | |
Size = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL | |
+ StrSize (Instance->FsInfo.VolumeLabel); | |
if (*BufferSize >= Size) { | |
CopyMem (&Label->VolumeLabel, &Instance->FsInfo.VolumeLabel, Size); | |
Status = EFI_SUCCESS; | |
} else { | |
Status = EFI_BUFFER_TOO_SMALL; | |
} | |
*BufferSize = Size; | |
return Status; | |
} | |
// Helper function that calculates a rough "free space" by: | |
// - Taking the media size | |
// - Subtracting the sum of all file sizes | |
// - Subtracting the block size times the number of files | |
// (To account for the blocks containing the HW_IMAGE_INFO | |
STATIC | |
UINT64 | |
ComputeFreeSpace ( | |
IN BOOTMON_FS_INSTANCE *Instance | |
) | |
{ | |
LIST_ENTRY *FileLink; | |
UINT64 FileSizeSum; | |
UINT64 MediaSize; | |
UINTN NumFiles; | |
EFI_BLOCK_IO_MEDIA *Media; | |
BOOTMON_FS_FILE *File; | |
Media = Instance->BlockIo->Media; | |
MediaSize = Media->BlockSize * (Media->LastBlock + 1); | |
NumFiles = 0; | |
FileSizeSum = 0; | |
for (FileLink = GetFirstNode (&Instance->RootFile->Link); | |
!IsNull (&Instance->RootFile->Link, FileLink); | |
FileLink = GetNextNode (&Instance->RootFile->Link, FileLink) | |
) | |
{ | |
File = BOOTMON_FS_FILE_FROM_LINK_THIS (FileLink); | |
FileSizeSum += BootMonFsGetImageLength (File); | |
NumFiles++; | |
} | |
return MediaSize - (FileSizeSum + (Media->BlockSize + NumFiles)); | |
} | |
STATIC | |
EFI_STATUS | |
GetFilesystemInfo ( | |
IN BOOTMON_FS_INSTANCE *Instance, | |
IN OUT UINTN *BufferSize, | |
OUT VOID *Buffer | |
) | |
{ | |
EFI_STATUS Status; | |
if (*BufferSize >= Instance->FsInfo.Size) { | |
Instance->FsInfo.FreeSpace = ComputeFreeSpace (Instance); | |
CopyMem (Buffer, &Instance->FsInfo, Instance->FsInfo.Size); | |
Status = EFI_SUCCESS; | |
} else { | |
Status = EFI_BUFFER_TOO_SMALL; | |
} | |
*BufferSize = Instance->FsInfo.Size; | |
return Status; | |
} | |
STATIC | |
EFI_STATUS | |
GetFileInfo ( | |
IN BOOTMON_FS_INSTANCE *Instance, | |
IN BOOTMON_FS_FILE *File, | |
IN OUT UINTN *BufferSize, | |
OUT VOID *Buffer | |
) | |
{ | |
EFI_FILE_INFO *Info; | |
UINTN ResultSize; | |
ResultSize = SIZE_OF_EFI_FILE_INFO + StrSize (File->Info->FileName); | |
if (*BufferSize < ResultSize) { | |
*BufferSize = ResultSize; | |
return EFI_BUFFER_TOO_SMALL; | |
} | |
Info = Buffer; | |
CopyMem (Info, File->Info, ResultSize); | |
// Size of the information | |
Info->Size = ResultSize; | |
*BufferSize = ResultSize; | |
return EFI_SUCCESS; | |
} | |
STATIC | |
EFI_STATUS | |
GetBootMonFsFileInfo ( | |
IN BOOTMON_FS_INSTANCE *Instance, | |
IN BOOTMON_FS_FILE *File, | |
IN OUT UINTN *BufferSize, | |
OUT VOID *Buffer | |
) | |
{ | |
EFI_STATUS Status; | |
BOOTMON_FS_FILE_INFO *Info; | |
UINTN ResultSize; | |
UINTN Index; | |
if (File == Instance->RootFile) { | |
Status = EFI_UNSUPPORTED; | |
} else { | |
ResultSize = SIZE_OF_BOOTMON_FS_FILE_INFO; | |
if (*BufferSize < ResultSize) { | |
*BufferSize = ResultSize; | |
Status = EFI_BUFFER_TOO_SMALL; | |
} else { | |
Info = Buffer; | |
// Zero out the structure | |
ZeroMem (Info, ResultSize); | |
// Fill in the structure | |
Info->Size = ResultSize; | |
Info->EntryPoint = File->HwDescription.EntryPoint; | |
Info->RegionCount = File->HwDescription.RegionCount; | |
for (Index = 0; Index < File->HwDescription.RegionCount; Index++) { | |
Info->Region[Index].LoadAddress = File->HwDescription.Region[Index].LoadAddress; | |
Info->Region[Index].Size = File->HwDescription.Region[Index].Size; | |
Info->Region[Index].Offset = File->HwDescription.Region[Index].Offset; | |
Info->Region[Index].Checksum = File->HwDescription.Region[Index].Checksum; | |
} | |
*BufferSize = ResultSize; | |
Status = EFI_SUCCESS; | |
} | |
} | |
return Status; | |
} | |
/** | |
Set the name of a file. | |
This is a helper function for SetFileInfo(). | |
@param[in] Instance A pointer to the description of the volume | |
the file belongs to. | |
@param[in] File A pointer to the description of the file. | |
@param[in] FileName A pointer to the new name of the file. | |
@retval EFI_SUCCESS The name was set. | |
@retval EFI_ACCESS_DENIED An attempt is made to change the name of a file | |
to a file that is already present. | |
**/ | |
STATIC | |
EFI_STATUS | |
SetFileName ( | |
IN BOOTMON_FS_INSTANCE *Instance, | |
IN BOOTMON_FS_FILE *File, | |
IN CONST CHAR16 *FileName | |
) | |
{ | |
CHAR16 TruncFileName[MAX_NAME_LENGTH]; | |
CHAR8 AsciiFileName[MAX_NAME_LENGTH]; | |
BOOTMON_FS_FILE *SameFile; | |
// If the file path start with a \ strip it. The EFI Shell may | |
// insert a \ in front of the file name. | |
if (FileName[0] == L'\\') { | |
FileName++; | |
} | |
StrnCpy (TruncFileName, FileName, MAX_NAME_LENGTH - 1); | |
TruncFileName[MAX_NAME_LENGTH - 1] = 0; | |
UnicodeStrToAsciiStr (TruncFileName, AsciiFileName); | |
if (BootMonGetFileFromAsciiFileName ( | |
File->Instance, | |
AsciiFileName, | |
&SameFile | |
) != EFI_NOT_FOUND) { | |
// A file with that name already exists. | |
return EFI_ACCESS_DENIED; | |
} else { | |
// OK, change the filename. | |
AsciiStrToUnicodeStr (AsciiFileName, File->Info->FileName); | |
return EFI_SUCCESS; | |
} | |
} | |
/** | |
Set the size of a file. | |
This is a helper function for SetFileInfo(). | |
@param[in] Instance A pointer to the description of the volume | |
the file belongs to. | |
@param[in] File A pointer to the description of the file. | |
@param[in] NewSize The requested new size for the file. | |
@retval EFI_SUCCESS The size was set. | |
@retval EFI_OUT_OF_RESOURCES An allocation needed to process the request failed. | |
**/ | |
STATIC | |
EFI_STATUS | |
SetFileSize ( | |
IN BOOTMON_FS_INSTANCE *Instance, | |
IN BOOTMON_FS_FILE *BootMonFsFile, | |
IN UINTN NewSize | |
) | |
{ | |
EFI_STATUS Status; | |
UINT32 OldSize; | |
LIST_ENTRY *RegionToFlushLink; | |
LIST_ENTRY *NextRegionToFlushLink; | |
BOOTMON_FS_FILE_REGION *Region; | |
EFI_FILE_PROTOCOL *File; | |
CHAR8 *Buffer; | |
UINTN BufferSize; | |
UINT64 StoredPosition; | |
OldSize = BootMonFsFile->Info->FileSize; | |
// | |
// In case of file truncation, force the regions waiting for writing to | |
// not overflow the new size of the file. | |
// | |
if (NewSize < OldSize) { | |
for (RegionToFlushLink = GetFirstNode (&BootMonFsFile->RegionToFlushLink); | |
!IsNull (&BootMonFsFile->RegionToFlushLink, RegionToFlushLink); | |
) | |
{ | |
NextRegionToFlushLink = GetNextNode (&BootMonFsFile->RegionToFlushLink, RegionToFlushLink); | |
Region = (BOOTMON_FS_FILE_REGION*)RegionToFlushLink; | |
if (Region->Offset > NewSize) { | |
RemoveEntryList (RegionToFlushLink); | |
FreePool (Region->Buffer); | |
FreePool (Region); | |
} else { | |
Region->Size = MIN (Region->Size, NewSize - Region->Offset); | |
} | |
RegionToFlushLink = NextRegionToFlushLink; | |
} | |
} else if (NewSize > OldSize) { | |
// Increasing a file's size is potentially complicated as it may require | |
// moving the image description on media. The simplest way to do it is to | |
// seek past the end of the file (which is valid in UEFI) and perform a | |
// Write. | |
File = &BootMonFsFile->File; | |
// Save position | |
Status = File->GetPosition (File, &StoredPosition); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
// Set position at the end of the file | |
Status = File->SetPosition (File, OldSize); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
BufferSize = NewSize - OldSize; | |
Buffer = AllocateZeroPool (BufferSize); | |
if (Buffer == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
Status = File->Write (File, &BufferSize, Buffer); | |
FreePool (Buffer); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
// Restore saved position | |
Status = File->SetPosition (File, StoredPosition); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
} | |
BootMonFsFile->Info->FileSize = NewSize; | |
return EFI_SUCCESS; | |
} | |
/** | |
Set information about a file. | |
@param[in] Instance A pointer to the description of the volume | |
the file belongs to. | |
@param[in] File A pointer to the description of the file. | |
@param[in] Info A pointer to the file information to write. | |
@retval EFI_SUCCESS The information was set. | |
@retval EFI_ACCESS_DENIED An attempt is being made to change the | |
EFI_FILE_DIRECTORY Attribute. | |
@retval EFI_ACCESS_DENIED The file was opened in read-only mode and an | |
attempt is being made to modify a field other | |
than Attribute. | |
@retval EFI_ACCESS_DENIED An attempt is made to change the name of a file | |
to a file that is already present. | |
@retval EFI_WRITE_PROTECTED An attempt is being made to modify a read-only | |
attribute. | |
@retval EFI_OUT_OF_RESOURCES An allocation needed to process the request | |
failed. | |
**/ | |
STATIC | |
EFI_STATUS | |
SetFileInfo ( | |
IN BOOTMON_FS_INSTANCE *Instance, | |
IN BOOTMON_FS_FILE *File, | |
IN EFI_FILE_INFO *Info | |
) | |
{ | |
EFI_STATUS Status; | |
BOOLEAN FileSizeIsDifferent; | |
BOOLEAN FileNameIsDifferent; | |
BOOLEAN TimeIsDifferent; | |
// | |
// A directory can not be changed to a file and a file can | |
// not be changed to a directory. | |
// | |
if ((Info->Attribute & EFI_FILE_DIRECTORY) != | |
(File->Info->Attribute & EFI_FILE_DIRECTORY) ) { | |
return EFI_ACCESS_DENIED; | |
} | |
FileSizeIsDifferent = (Info->FileSize != File->Info->FileSize); | |
FileNameIsDifferent = (StrnCmp ( | |
Info->FileName, | |
File->Info->FileName, | |
MAX_NAME_LENGTH - 1 | |
) != 0); | |
// | |
// Check if the CreateTime, LastAccess or ModificationTime | |
// have been changed. The file system does not support file | |
// timestamps thus the three times in "File->Info" are | |
// always equal to zero. The following comparison actually | |
// checks if all three times are still equal to 0 or not. | |
// | |
TimeIsDifferent = CompareMem ( | |
&Info->CreateTime, | |
&File->Info->CreateTime, | |
3 * sizeof (EFI_TIME) | |
) != 0; | |
// | |
// For a file opened in read-only mode, only the Attribute field can be | |
// modified. The root directory open mode is forced to read-only at opening | |
// thus the following test protects the root directory to be somehow modified. | |
// | |
if (File->OpenMode == EFI_FILE_MODE_READ) { | |
if (FileSizeIsDifferent || FileNameIsDifferent || TimeIsDifferent) { | |
return EFI_ACCESS_DENIED; | |
} | |
} | |
if (TimeIsDifferent) { | |
return EFI_WRITE_PROTECTED; | |
} | |
if (FileSizeIsDifferent) { | |
Status = SetFileSize (Instance, File, Info->FileSize); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
} | |
// | |
// Note down in RAM the Attribute field but we can not | |
// ask to store it in flash for the time being. | |
// | |
File->Info->Attribute = Info->Attribute; | |
if (FileNameIsDifferent) { | |
Status = SetFileName (Instance, File, Info->FileName); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
} | |
return EFI_SUCCESS; | |
} | |
EFIAPI | |
EFI_STATUS | |
BootMonFsGetInfo ( | |
IN EFI_FILE_PROTOCOL *This, | |
IN EFI_GUID *InformationType, | |
IN OUT UINTN *BufferSize, | |
OUT VOID *Buffer | |
) | |
{ | |
EFI_STATUS Status; | |
BOOTMON_FS_FILE *File; | |
BOOTMON_FS_INSTANCE *Instance; | |
if ((This == NULL) || | |
(InformationType == NULL) || | |
(BufferSize == NULL) || | |
((Buffer == NULL) && (*BufferSize > 0)) ) { | |
return EFI_INVALID_PARAMETER; | |
} | |
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This); | |
if (File->Info == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
Instance = File->Instance; | |
// If the instance has not been initialized yet then do it ... | |
if (!Instance->Initialized) { | |
Status = BootMonFsInitialize (Instance); | |
} else { | |
Status = EFI_SUCCESS; | |
} | |
if (!EFI_ERROR (Status)) { | |
if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid) | |
!= 0) { | |
Status = GetFileSystemVolumeLabelInfo (Instance, BufferSize, Buffer); | |
} else if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid) != 0) { | |
Status = GetFilesystemInfo (Instance, BufferSize, Buffer); | |
} else if (CompareGuid (InformationType, &gEfiFileInfoGuid) != 0) { | |
Status = GetFileInfo (Instance, File, BufferSize, Buffer); | |
} else if (CompareGuid (InformationType, &gArmBootMonFsFileInfoGuid) != 0) { | |
Status = GetBootMonFsFileInfo (Instance, File, BufferSize, Buffer); | |
} else { | |
Status = EFI_UNSUPPORTED; | |
} | |
} | |
return Status; | |
} | |
/** | |
Set information about a file or a volume. | |
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that | |
is the file handle the information is for. | |
@param[in] InformationType The type identifier for the information being set : | |
EFI_FILE_INFO_ID or EFI_FILE_SYSTEM_INFO_ID or | |
EFI_FILE_SYSTEM_VOLUME_LABEL_ID | |
@param[in] BufferSize The size, in bytes, of Buffer. | |
@param[in] Buffer A pointer to the data buffer to write. The type of the | |
data inside the buffer is indicated by InformationType. | |
@retval EFI_SUCCESS The information was set. | |
@retval EFI_UNSUPPORTED The InformationType is not known. | |
@retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed. | |
@retval EFI_ACCESS_DENIED An attempt is made to change the name of a file | |
to a file that is already present. | |
@retval EFI_ACCESS_DENIED An attempt is being made to change the | |
EFI_FILE_DIRECTORY Attribute. | |
@retval EFI_ACCESS_DENIED InformationType is EFI_FILE_INFO_ID and | |
the file was opened in read-only mode and an | |
attempt is being made to modify a field other | |
than Attribute. | |
@retval EFI_WRITE_PROTECTED An attempt is being made to modify a read-only | |
attribute. | |
@retval EFI_BAD_BUFFER_SIZE The size of the buffer is lower than that indicated by | |
the data inside the buffer. | |
@retval EFI_OUT_OF_RESOURCES A allocation needed to process the request failed. | |
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid. | |
**/ | |
EFIAPI | |
EFI_STATUS | |
BootMonFsSetInfo ( | |
IN EFI_FILE_PROTOCOL *This, | |
IN EFI_GUID *InformationType, | |
IN UINTN BufferSize, | |
IN VOID *Buffer | |
) | |
{ | |
BOOTMON_FS_FILE *File; | |
EFI_FILE_INFO *Info; | |
EFI_FILE_SYSTEM_INFO *SystemInfo; | |
if ((This == NULL) || | |
(InformationType == NULL) || | |
(Buffer == NULL) ) { | |
return EFI_INVALID_PARAMETER; | |
} | |
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This); | |
if (File->Info == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
if (CompareGuid (InformationType, &gEfiFileInfoGuid)) { | |
Info = Buffer; | |
if (Info->Size < (SIZE_OF_EFI_FILE_INFO + StrSize (Info->FileName))) { | |
return EFI_INVALID_PARAMETER; | |
} | |
if (BufferSize < Info->Size) { | |
return EFI_BAD_BUFFER_SIZE; | |
} | |
return (SetFileInfo (File->Instance, File, Info)); | |
} | |
// | |
// The only writable field in the other two information types | |
// (i.e. EFI_FILE_SYSTEM_INFO and EFI_FILE_SYSTEM_VOLUME_LABEL) is the | |
// filesystem volume label. This can be retrieved with GetInfo, but it is | |
// hard-coded into this driver, not stored on media. | |
// | |
if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) { | |
SystemInfo = Buffer; | |
if (SystemInfo->Size < | |
(SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (SystemInfo->VolumeLabel))) { | |
return EFI_INVALID_PARAMETER; | |
} | |
if (BufferSize < SystemInfo->Size) { | |
return EFI_BAD_BUFFER_SIZE; | |
} | |
return EFI_WRITE_PROTECTED; | |
} | |
if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) { | |
return EFI_WRITE_PROTECTED; | |
} | |
return EFI_UNSUPPORTED; | |
} | |
EFIAPI | |
EFI_STATUS | |
BootMonFsReadDirectory ( | |
IN EFI_FILE_PROTOCOL *This, | |
IN OUT UINTN *BufferSize, | |
OUT VOID *Buffer | |
) | |
{ | |
BOOTMON_FS_INSTANCE *Instance; | |
BOOTMON_FS_FILE *RootFile; | |
BOOTMON_FS_FILE *File; | |
EFI_FILE_INFO *Info; | |
UINTN NameSize; | |
UINTN ResultSize; | |
EFI_STATUS Status; | |
UINTN Index; | |
RootFile = BOOTMON_FS_FILE_FROM_FILE_THIS (This); | |
if (RootFile == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
Instance = RootFile->Instance; | |
Status = BootMonGetFileFromPosition (Instance, RootFile->Position, &File); | |
if (EFI_ERROR (Status)) { | |
// No more file | |
*BufferSize = 0; | |
return EFI_SUCCESS; | |
} | |
NameSize = AsciiStrLen (File->HwDescription.Footer.Filename) + 1; | |
ResultSize = SIZE_OF_EFI_FILE_INFO + (NameSize * sizeof (CHAR16)); | |
if (*BufferSize < ResultSize) { | |
*BufferSize = ResultSize; | |
return EFI_BUFFER_TOO_SMALL; | |
} | |
// Zero out the structure | |
Info = Buffer; | |
ZeroMem (Info, ResultSize); | |
// Fill in the structure | |
Info->Size = ResultSize; | |
Info->FileSize = BootMonFsGetImageLength (File); | |
Info->PhysicalSize = BootMonFsGetPhysicalSize (File); | |
for (Index = 0; Index < NameSize; Index++) { | |
Info->FileName[Index] = File->HwDescription.Footer.Filename[Index]; | |
} | |
*BufferSize = ResultSize; | |
RootFile->Position++; | |
return EFI_SUCCESS; | |
} | |
EFIAPI | |
EFI_STATUS | |
BootMonFsFlushDirectory ( | |
IN EFI_FILE_PROTOCOL *This | |
) | |
{ | |
BOOTMON_FS_FILE *RootFile; | |
LIST_ENTRY *ListFiles; | |
LIST_ENTRY *Link; | |
BOOTMON_FS_FILE *File; | |
RootFile = BOOTMON_FS_FILE_FROM_FILE_THIS (This); | |
if (RootFile == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
ListFiles = &RootFile->Link; | |
if (IsListEmpty (ListFiles)) { | |
return EFI_SUCCESS; | |
} | |
// | |
// Flush all the files that need to be flushed | |
// | |
// Go through all the list of files to flush them | |
for (Link = GetFirstNode (ListFiles); | |
!IsNull (ListFiles, Link); | |
Link = GetNextNode (ListFiles, Link) | |
) | |
{ | |
File = BOOTMON_FS_FILE_FROM_LINK_THIS (Link); | |
File->File.Flush (&File->File); | |
} | |
return EFI_SUCCESS; | |
} |