ArmPlatformPkg/BootMonFs: Added support for the NorFlash File System of the ARM Development Boards
This is the filesystem created by the microcontroller on NOR Flash of the ARM Versatile Express Development Board. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Olivier Martin <olivier.martin@arm.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15126 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
committed by
oliviermartin
parent
33fc8b0fec
commit
94e0955d3e
602
ArmPlatformPkg/FileSystem/BootMonFs/BootMonFsDir.c
Normal file
602
ArmPlatformPkg/FileSystem/BootMonFs/BootMonFsDir.c
Normal file
@@ -0,0 +1,602 @@
|
||||
/** @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;
|
||||
}
|
||||
|
||||
*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;
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
UINTN NameSize;
|
||||
UINTN Index;
|
||||
|
||||
if (File == Instance->RootFile) {
|
||||
NameSize = 0;
|
||||
ResultSize = SIZE_OF_EFI_FILE_INFO + sizeof (CHAR16);
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
Info = Buffer;
|
||||
|
||||
// Zero out the structure
|
||||
ZeroMem (Info, ResultSize);
|
||||
|
||||
// Fill in the structure
|
||||
Info->Size = ResultSize;
|
||||
|
||||
if (File == Instance->RootFile) {
|
||||
Info->Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY;
|
||||
Info->FileName[0] = L'\0';
|
||||
} else {
|
||||
Info->FileSize = BootMonFsGetImageLength (File);
|
||||
Info->PhysicalSize = BootMonFsGetPhysicalSize (File);
|
||||
|
||||
for (Index = 0; Index < NameSize; Index++) {
|
||||
Info->FileName[Index] = File->HwDescription.Footer.Filename[Index];
|
||||
}
|
||||
}
|
||||
|
||||
*BufferSize = ResultSize;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
SetFileName (
|
||||
IN BOOTMON_FS_FILE *File,
|
||||
IN CHAR16 *FileNameUnicode
|
||||
)
|
||||
{
|
||||
CHAR8 *FileNameAscii;
|
||||
UINT16 SavedChar;
|
||||
UINTN FileNameSize;
|
||||
BOOTMON_FS_FILE *SameFile;
|
||||
EFI_STATUS Status;
|
||||
|
||||
// EFI Shell inserts '\' in front of the filename that must be stripped
|
||||
if (FileNameUnicode[0] == L'\\') {
|
||||
FileNameUnicode++;
|
||||
}
|
||||
//
|
||||
// Convert Unicode into Ascii
|
||||
//
|
||||
SavedChar = L'\0';
|
||||
FileNameSize = StrLen (FileNameUnicode) + 1;
|
||||
FileNameAscii = AllocatePool (FileNameSize * sizeof (CHAR8));
|
||||
if (FileNameAscii == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
// If Unicode string is too long then truncate it.
|
||||
if (FileNameSize > MAX_NAME_LENGTH) {
|
||||
SavedChar = FileNameUnicode[MAX_NAME_LENGTH - 1];
|
||||
FileNameUnicode[MAX_NAME_LENGTH - 1] = L'\0';
|
||||
}
|
||||
UnicodeStrToAsciiStr (FileNameUnicode, FileNameAscii);
|
||||
// If the unicode string was truncated then restore its original content.
|
||||
if (SavedChar != L'\0') {
|
||||
FileNameUnicode[MAX_NAME_LENGTH - 1] = SavedChar;
|
||||
}
|
||||
|
||||
// If we're changing the file name
|
||||
if (AsciiStrCmp (FileNameAscii, File->HwDescription.Footer.Filename)) {
|
||||
// Check a file with that filename doesn't already exist
|
||||
if (BootMonGetFileFromAsciiFileName (
|
||||
File->Instance,
|
||||
File->HwDescription.Footer.Filename,
|
||||
&SameFile) != EFI_NOT_FOUND) {
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
} else {
|
||||
AsciiStrCpy (FileNameAscii, File->HwDescription.Footer.Filename);
|
||||
Status = EFI_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
// No change to filename
|
||||
Status = EFI_SUCCESS;
|
||||
}
|
||||
|
||||
FreePool (FileNameAscii);
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Set the file's size (NB "size", not "physical size"). If the change amounts
|
||||
// to an increase, simply do a write followed by a flush.
|
||||
// (This is a helper function for SetFileInfo.)
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
SetFileSize (
|
||||
IN BOOTMON_FS_INSTANCE *Instance,
|
||||
IN BOOTMON_FS_FILE *BootMonFsFile,
|
||||
IN UINTN Size
|
||||
)
|
||||
{
|
||||
UINT64 StoredPosition;
|
||||
EFI_STATUS Status;
|
||||
EFI_FILE_PROTOCOL *File;
|
||||
CHAR8 Buffer;
|
||||
UINTN BufferSize;
|
||||
|
||||
Buffer = 0;
|
||||
BufferSize = sizeof (Buffer);
|
||||
|
||||
File = &BootMonFsFile->File;
|
||||
|
||||
if (!(BootMonFsFile->OpenMode & EFI_FILE_MODE_WRITE)) {
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (Size <= BootMonFsFile->HwDescription.Region[0].Size) {
|
||||
BootMonFsFile->HwDescription.Region[0].Size = Size;
|
||||
} else {
|
||||
// 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.
|
||||
|
||||
// Save position
|
||||
Status = File->GetPosition (File, &StoredPosition);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = File->SetPosition (File, Size - 1);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
Status = File->Write (File, &BufferSize, &Buffer);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Restore saved position
|
||||
Status = File->SetPosition (File, Size - 1);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = File->Flush (File);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
SetFileInfo (
|
||||
IN BOOTMON_FS_INSTANCE *Instance,
|
||||
IN BOOTMON_FS_FILE *File,
|
||||
IN UINTN BufferSize,
|
||||
IN EFI_FILE_INFO *Info
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_BLOCK_IO_PROTOCOL *BlockIo;
|
||||
UINT8 *DataBuffer;
|
||||
UINTN BlockSize;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
BlockIo = Instance->BlockIo;
|
||||
|
||||
// Note that a call to this function on a file opened read-only is only
|
||||
// invalid if it actually changes fields, so we don't immediately fail if the
|
||||
// OpenMode is wrong.
|
||||
// Also note that the only fields supported are filename and size, others are
|
||||
// ignored.
|
||||
|
||||
if (File != Instance->RootFile) {
|
||||
if (!(File->OpenMode & EFI_FILE_MODE_WRITE)) {
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
SetFileName (File, Info->FileName);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Update file size
|
||||
Status = SetFileSize (Instance, File, Info->FileSize);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Update the last block
|
||||
//
|
||||
BlockSize = BlockIo->Media->BlockSize;
|
||||
DataBuffer = AllocatePool (BlockSize);
|
||||
if (DataBuffer == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
Status = BlockIo->ReadBlocks (BlockIo, Instance->Media->MediaId,
|
||||
File->HwDescription.BlockEnd, BlockSize, DataBuffer);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (DataBuffer);
|
||||
return Status;
|
||||
}
|
||||
CopyMem (DataBuffer + BlockSize - sizeof (File->HwDescription), &File->HwDescription, sizeof (File->HwDescription));
|
||||
Status = BlockIo->WriteBlocks (BlockIo, Instance->Media->MediaId,
|
||||
File->HwDescription.BlockEnd, BlockSize, DataBuffer);
|
||||
FreePool (DataBuffer);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
|
||||
if (File == NULL) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
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 {
|
||||
Status = EFI_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFIAPI
|
||||
EFI_STATUS
|
||||
BootMonFsSetInfo (
|
||||
IN EFI_FILE_PROTOCOL *This,
|
||||
IN EFI_GUID *InformationType,
|
||||
IN UINTN BufferSize,
|
||||
IN VOID *Buffer
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
BOOTMON_FS_FILE *File;
|
||||
BOOTMON_FS_INSTANCE *Instance;
|
||||
|
||||
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
|
||||
if (File == NULL) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
Instance = File->Instance;
|
||||
|
||||
if (CompareGuid (InformationType, &gEfiFileInfoGuid) != 0) {
|
||||
Status = SetFileInfo (Instance, File, BufferSize, (EFI_FILE_INFO *) Buffer);
|
||||
} else {
|
||||
// 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.
|
||||
Status = EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
Reference in New Issue
Block a user