mirror of https://github.com/acidanthera/audk.git
ArmPlatformPkg/BootMonFs: Fix the setting of information about a file
Rework the setting of information about a file, in particular file resizing, file renaming and the returned error codes in case of error. This rework has implied a rework of the read, write, close and flush functions. To strickly separate what has been actually written to the media (flushed) from what has not been written when a file is open, an "Info" field has been added to the description of a file. The field is used to store the modifications done to the file by the means of SetInfo() like the change of the name or of the size. Such changes are written to the media only when a flush occurs. When a file is open, the information pointed to by the "Info" field is always up-to-date. This is not the case of the information stored in the "HwDescription" of the file description which from now is just a mirror of what is written on the media. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ronald Cron <Ronald.Cron@arm.com> Reviewed-by: Olivier Martin <olivier.martin@arm.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16511 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
fb08c45511
commit
95204533ad
|
@ -79,12 +79,37 @@ BootMonFsFlushDirectory (
|
||||||
IN EFI_FILE_PROTOCOL *This
|
IN EFI_FILE_PROTOCOL *This
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Flush all modified data associated with a file to a device.
|
||||||
|
|
||||||
|
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the
|
||||||
|
file handle to flush.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The data was flushed.
|
||||||
|
@retval EFI_ACCESS_DENIED The file was opened read-only.
|
||||||
|
@retval EFI_DEVICE_ERROR The device reported an error.
|
||||||
|
@retval EFI_VOLUME_FULL The volume is full.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Not enough resources were available to flush the data.
|
||||||
|
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
|
||||||
|
|
||||||
|
**/
|
||||||
EFIAPI
|
EFIAPI
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BootMonFsFlushFile (
|
BootMonFsFlushFile (
|
||||||
IN EFI_FILE_PROTOCOL *This
|
IN EFI_FILE_PROTOCOL *This
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Close a specified file handle.
|
||||||
|
|
||||||
|
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the file
|
||||||
|
handle to close.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The file was closed.
|
||||||
|
@retval EFI_INVALID_PARAMETER The parameter "This" is NULL or is not an open
|
||||||
|
file handle.
|
||||||
|
|
||||||
|
**/
|
||||||
EFIAPI
|
EFIAPI
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BootMonFsCloseFile (
|
BootMonFsCloseFile (
|
||||||
|
@ -94,7 +119,12 @@ BootMonFsCloseFile (
|
||||||
/**
|
/**
|
||||||
Open a file on the boot monitor file system.
|
Open a file on the boot monitor file system.
|
||||||
|
|
||||||
@param[in] This The EFI_FILE_PROTOCOL parent handle.
|
The boot monitor file system does not allow for sub-directories. There is only
|
||||||
|
one directory, the root one. On any attempt to create a directory, the function
|
||||||
|
returns in error with the EFI_WRITE_PROTECTED error code.
|
||||||
|
|
||||||
|
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is
|
||||||
|
the file handle to source location.
|
||||||
@param[out] NewHandle A pointer to the location to return the opened
|
@param[out] NewHandle A pointer to the location to return the opened
|
||||||
handle for the new file.
|
handle for the new file.
|
||||||
@param[in] FileName The Null-terminated string of the name of the file
|
@param[in] FileName The Null-terminated string of the name of the file
|
||||||
|
@ -108,7 +138,7 @@ BootMonFsCloseFile (
|
||||||
directory in which to create a file could not be found.
|
directory in which to create a file could not be found.
|
||||||
@retval EFI_DEVICE_ERROR The device reported an error.
|
@retval EFI_DEVICE_ERROR The device reported an error.
|
||||||
@retval EFI_WRITE_PROTECTED Attempt to create a directory. This is not possible
|
@retval EFI_WRITE_PROTECTED Attempt to create a directory. This is not possible
|
||||||
with the BootMon file system.
|
with the Boot Monitor file system.
|
||||||
@retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file.
|
@retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file.
|
||||||
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
|
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
|
||||||
|
|
||||||
|
@ -139,6 +169,7 @@ BootMonFsOpenFile (
|
||||||
reported an error while performing the read
|
reported an error while performing the read
|
||||||
operation.
|
operation.
|
||||||
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
|
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFIAPI
|
EFIAPI
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
|
@ -162,6 +193,26 @@ BootMonFsGetPosition (
|
||||||
OUT UINT64 *Position
|
OUT UINT64 *Position
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Write data to an open file.
|
||||||
|
|
||||||
|
The data is not written to the flash yet. It will be written when the file
|
||||||
|
will be either read, closed or flushed.
|
||||||
|
|
||||||
|
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that
|
||||||
|
is the file handle to write data to.
|
||||||
|
@param[in out] BufferSize On input, the size of the Buffer. On output, the
|
||||||
|
size of the data actually written. In both cases,
|
||||||
|
the size is measured in bytes.
|
||||||
|
@param[in] Buffer The buffer of data to write.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The data was written.
|
||||||
|
@retval EFI_ACCESS_DENIED The file was opened read only.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Unable to allocate the buffer to store the
|
||||||
|
data to write.
|
||||||
|
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
|
||||||
|
|
||||||
|
**/
|
||||||
EFIAPI
|
EFIAPI
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BootMonFsWriteFile (
|
BootMonFsWriteFile (
|
||||||
|
@ -176,12 +227,35 @@ BootMonFsDeleteFail (
|
||||||
IN EFI_FILE_PROTOCOL *This
|
IN EFI_FILE_PROTOCOL *This
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Close and delete a file from the boot monitor file system.
|
||||||
|
|
||||||
|
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the file
|
||||||
|
handle to delete.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The file was closed and deleted.
|
||||||
|
@retval EFI_INVALID_PARAMETER The parameter "This" is NULL or is not an open
|
||||||
|
file handle.
|
||||||
|
@retval EFI_WARN_DELETE_FAILURE The handle was closed, but the file was not deleted.
|
||||||
|
|
||||||
|
**/
|
||||||
EFIAPI
|
EFIAPI
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BootMonFsDelete (
|
BootMonFsDelete (
|
||||||
IN EFI_FILE_PROTOCOL *This
|
IN EFI_FILE_PROTOCOL *This
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set a file's current position.
|
||||||
|
|
||||||
|
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is
|
||||||
|
the file handle to set the requested position on.
|
||||||
|
@param[in] Position The byte position from the start of the file to set.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The position was set.
|
||||||
|
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
|
||||||
|
|
||||||
|
**/
|
||||||
EFIAPI
|
EFIAPI
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BootMonFsSetPosition (
|
BootMonFsSetPosition (
|
||||||
|
@ -189,6 +263,17 @@ BootMonFsSetPosition (
|
||||||
IN UINT64 Position
|
IN UINT64 Position
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return a file's current position.
|
||||||
|
|
||||||
|
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is
|
||||||
|
the file handle to get the current position on.
|
||||||
|
@param[out] Position The address to return the file's current position value.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The position was returned.
|
||||||
|
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
|
||||||
|
|
||||||
|
**/
|
||||||
EFIAPI
|
EFIAPI
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BootMonFsGetPosition(
|
BootMonFsGetPosition(
|
||||||
|
@ -207,6 +292,37 @@ BootMonFsGetPositionUnsupported (
|
||||||
OUT UINT64 *Position
|
OUT UINT64 *Position
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
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
|
EFIAPI
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BootMonFsSetInfo (
|
BootMonFsSetInfo (
|
||||||
|
@ -230,6 +346,31 @@ BootMonFsOpenDirectory (
|
||||||
//
|
//
|
||||||
// Internal API
|
// Internal API
|
||||||
//
|
//
|
||||||
|
|
||||||
|
/**
|
||||||
|
Search for a file given its name coded in Ascii.
|
||||||
|
|
||||||
|
When searching through the files of the volume, if a file is currently not
|
||||||
|
open, its name was written on the media and is kept in RAM in the
|
||||||
|
"HwDescription.Footer.Filename[]" field of the file's description.
|
||||||
|
|
||||||
|
If a file is currently open, its name might not have been written on the
|
||||||
|
media yet, and as the "HwDescription" is a mirror in RAM of what is on the
|
||||||
|
media the "HwDescription.Footer.Filename[]" might be outdated. In that case,
|
||||||
|
the up to date name of the file is stored in the "Info" field of the file's
|
||||||
|
description.
|
||||||
|
|
||||||
|
@param[in] Instance Pointer to the description of the volume in which
|
||||||
|
the file has to be search for.
|
||||||
|
@param[in] AsciiFileName Name of the file.
|
||||||
|
|
||||||
|
@param[out] File Pointer to the description of the file if the
|
||||||
|
file was found.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The file was found.
|
||||||
|
@retval EFI_NOT_FOUND The file was not found.
|
||||||
|
|
||||||
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BootMonGetFileFromAsciiFileName (
|
BootMonGetFileFromAsciiFileName (
|
||||||
IN BOOTMON_FS_INSTANCE *Instance,
|
IN BOOTMON_FS_INSTANCE *Instance,
|
||||||
|
|
|
@ -28,6 +28,8 @@ OpenBootMonFsOpenVolume (
|
||||||
return EFI_DEVICE_ERROR;
|
return EFI_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Instance->RootFile->Info->Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY;
|
||||||
|
|
||||||
*Root = &Instance->RootFile->File;
|
*Root = &Instance->RootFile->File;
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
|
@ -114,6 +116,8 @@ BootMonFsOpenDirectory (
|
||||||
|
|
||||||
return EFI_UNSUPPORTED;
|
return EFI_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
GetFileSystemVolumeLabelInfo (
|
GetFileSystemVolumeLabelInfo (
|
||||||
IN BOOTMON_FS_INSTANCE *Instance,
|
IN BOOTMON_FS_INSTANCE *Instance,
|
||||||
|
@ -178,6 +182,7 @@ ComputeFreeSpace (
|
||||||
return MediaSize - (FileSizeSum + (Media->BlockSize + NumFiles));
|
return MediaSize - (FileSizeSum + (Media->BlockSize + NumFiles));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
GetFilesystemInfo (
|
GetFilesystemInfo (
|
||||||
IN BOOTMON_FS_INSTANCE *Instance,
|
IN BOOTMON_FS_INSTANCE *Instance,
|
||||||
|
@ -199,26 +204,19 @@ GetFilesystemInfo (
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
GetFileInfo (
|
GetFileInfo (
|
||||||
IN BOOTMON_FS_INSTANCE *Instance,
|
IN BOOTMON_FS_INSTANCE *Instance,
|
||||||
IN BOOTMON_FS_FILE *File,
|
IN BOOTMON_FS_FILE *File,
|
||||||
IN OUT UINTN *BufferSize,
|
IN OUT UINTN *BufferSize,
|
||||||
OUT VOID *Buffer
|
OUT VOID *Buffer
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_FILE_INFO *Info;
|
EFI_FILE_INFO *Info;
|
||||||
UINTN ResultSize;
|
UINTN ResultSize;
|
||||||
UINTN NameSize;
|
|
||||||
UINTN Index;
|
|
||||||
|
|
||||||
if (File == Instance->RootFile) {
|
ResultSize = SIZE_OF_EFI_FILE_INFO + StrSize (File->Info->FileName);
|
||||||
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) {
|
if (*BufferSize < ResultSize) {
|
||||||
*BufferSize = ResultSize;
|
*BufferSize = ResultSize;
|
||||||
|
@ -227,24 +225,10 @@ GetFileInfo (
|
||||||
|
|
||||||
Info = Buffer;
|
Info = Buffer;
|
||||||
|
|
||||||
// Zero out the structure
|
CopyMem (Info, File->Info, ResultSize);
|
||||||
ZeroMem (Info, ResultSize);
|
// Size of the information
|
||||||
|
|
||||||
// Fill in the structure
|
|
||||||
Info->Size = ResultSize;
|
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;
|
*BufferSize = ResultSize;
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
|
@ -297,171 +281,253 @@ GetBootMonFsFileInfo (
|
||||||
return Status;
|
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
|
STATIC
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
SetFileName (
|
SetFileName (
|
||||||
IN BOOTMON_FS_FILE *File,
|
IN BOOTMON_FS_INSTANCE *Instance,
|
||||||
IN CHAR16 *FileNameUnicode
|
IN BOOTMON_FS_FILE *File,
|
||||||
|
IN CONST CHAR16 *FileName
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
CHAR8 *FileNameAscii;
|
CHAR16 TruncFileName[MAX_NAME_LENGTH];
|
||||||
UINT16 SavedChar;
|
CHAR8 AsciiFileName[MAX_NAME_LENGTH];
|
||||||
UINTN FileNameSize;
|
BOOTMON_FS_FILE *SameFile;
|
||||||
BOOTMON_FS_FILE *SameFile;
|
|
||||||
EFI_STATUS Status;
|
|
||||||
|
|
||||||
// EFI Shell inserts '\' in front of the filename that must be stripped
|
// If the file path start with a \ strip it. The EFI Shell may
|
||||||
if (FileNameUnicode[0] == L'\\') {
|
// insert a \ in front of the file name.
|
||||||
FileNameUnicode++;
|
if (FileName[0] == L'\\') {
|
||||||
}
|
FileName++;
|
||||||
//
|
|
||||||
// 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
|
StrnCpy (TruncFileName, FileName, MAX_NAME_LENGTH - 1);
|
||||||
if (AsciiStrCmp (FileNameAscii, File->HwDescription.Footer.Filename) == 0) {
|
TruncFileName[MAX_NAME_LENGTH - 1] = 0;
|
||||||
// No change to filename.
|
UnicodeStrToAsciiStr (TruncFileName, AsciiFileName);
|
||||||
Status = EFI_SUCCESS;
|
|
||||||
} else if (!(File->OpenMode & EFI_FILE_MODE_WRITE)) {
|
if (BootMonGetFileFromAsciiFileName (
|
||||||
// You can only change the filename if you open the file for write.
|
File->Instance,
|
||||||
Status = EFI_ACCESS_DENIED;
|
AsciiFileName,
|
||||||
} else if (BootMonGetFileFromAsciiFileName (
|
&SameFile
|
||||||
File->Instance,
|
) != EFI_NOT_FOUND) {
|
||||||
File->HwDescription.Footer.Filename,
|
|
||||||
&SameFile) != EFI_NOT_FOUND) {
|
|
||||||
// A file with that name already exists.
|
// A file with that name already exists.
|
||||||
Status = EFI_ACCESS_DENIED;
|
return EFI_ACCESS_DENIED;
|
||||||
} else {
|
} else {
|
||||||
// OK, change the filename.
|
// OK, change the filename.
|
||||||
AsciiStrCpy (FileNameAscii, File->HwDescription.Footer.Filename);
|
AsciiStrToUnicodeStr (AsciiFileName, File->Info->FileName);
|
||||||
Status = EFI_SUCCESS;
|
return 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.
|
Set the size of a file.
|
||||||
// (This is a helper function for SetFileInfo.)
|
|
||||||
|
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
|
STATIC
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
SetFileSize (
|
SetFileSize (
|
||||||
IN BOOTMON_FS_INSTANCE *Instance,
|
IN BOOTMON_FS_INSTANCE *Instance,
|
||||||
IN BOOTMON_FS_FILE *BootMonFsFile,
|
IN BOOTMON_FS_FILE *BootMonFsFile,
|
||||||
IN UINTN NewSize
|
IN UINTN NewSize
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UINT64 StoredPosition;
|
EFI_STATUS Status;
|
||||||
EFI_STATUS Status;
|
UINT32 OldSize;
|
||||||
EFI_FILE_PROTOCOL *File;
|
LIST_ENTRY *RegionToFlushLink;
|
||||||
CHAR8 Buffer;
|
LIST_ENTRY *NextRegionToFlushLink;
|
||||||
UINTN BufferSize;
|
BOOTMON_FS_FILE_REGION *Region;
|
||||||
UINT32 OldSize;
|
EFI_FILE_PROTOCOL *File;
|
||||||
|
CHAR8 *Buffer;
|
||||||
|
UINTN BufferSize;
|
||||||
|
UINT64 StoredPosition;
|
||||||
|
|
||||||
OldSize = BootMonFsFile->HwDescription.Region[0].Size;
|
OldSize = BootMonFsFile->Info->FileSize;
|
||||||
|
|
||||||
if (OldSize == NewSize) {
|
//
|
||||||
return EFI_SUCCESS;
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
Buffer = 0;
|
} else if (NewSize > OldSize) {
|
||||||
BufferSize = sizeof (Buffer);
|
|
||||||
|
|
||||||
File = &BootMonFsFile->File;
|
|
||||||
|
|
||||||
if (!(BootMonFsFile->OpenMode & EFI_FILE_MODE_WRITE)) {
|
|
||||||
return EFI_ACCESS_DENIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NewSize <= OldSize) {
|
|
||||||
OldSize = NewSize;
|
|
||||||
} else {
|
|
||||||
// Increasing a file's size is potentially complicated as it may require
|
// 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
|
// 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
|
// seek past the end of the file (which is valid in UEFI) and perform a
|
||||||
// Write.
|
// Write.
|
||||||
|
File = &BootMonFsFile->File;
|
||||||
|
|
||||||
// Save position
|
// Save position
|
||||||
Status = File->GetPosition (File, &StoredPosition);
|
Status = File->GetPosition (File, &StoredPosition);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
// Set position at the end of the file
|
||||||
Status = File->SetPosition (File, NewSize - 1);
|
Status = File->SetPosition (File, OldSize);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
Status = File->Write (File, &BufferSize, &Buffer);
|
|
||||||
|
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)) {
|
if (EFI_ERROR (Status)) {
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore saved position
|
// Restore saved position
|
||||||
Status = File->SetPosition (File, NewSize - 1);
|
Status = File->SetPosition (File, StoredPosition);
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = File->Flush (File);
|
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BootMonFsFile->Info->FileSize = NewSize;
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
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
|
EFI_STATUS
|
||||||
SetFileInfo (
|
SetFileInfo (
|
||||||
IN BOOTMON_FS_INSTANCE *Instance,
|
IN BOOTMON_FS_INSTANCE *Instance,
|
||||||
IN BOOTMON_FS_FILE *File,
|
IN BOOTMON_FS_FILE *File,
|
||||||
IN UINTN BufferSize,
|
IN EFI_FILE_INFO *Info
|
||||||
IN EFI_FILE_INFO *Info
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
|
BOOLEAN FileSizeIsDifferent;
|
||||||
|
BOOLEAN FileNameIsDifferent;
|
||||||
|
BOOLEAN TimeIsDifferent;
|
||||||
|
|
||||||
Status = EFI_SUCCESS;
|
//
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
// Note that a call to this function on a file opened read-only is only
|
FileSizeIsDifferent = (Info->FileSize != File->Info->FileSize);
|
||||||
// invalid if it actually changes fields, so we don't immediately fail if the
|
FileNameIsDifferent = (StrnCmp (
|
||||||
// OpenMode is wrong.
|
Info->FileName,
|
||||||
// Also note that the only fields supported are filename and size, others are
|
File->Info->FileName,
|
||||||
// ignored.
|
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;
|
||||||
|
|
||||||
if (File != Instance->RootFile) {
|
//
|
||||||
if (!(File->OpenMode & EFI_FILE_MODE_WRITE)) {
|
// 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;
|
return EFI_ACCESS_DENIED;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Status = SetFileName (File, Info->FileName);
|
if (TimeIsDifferent) {
|
||||||
if (EFI_ERROR (Status)) {
|
return EFI_WRITE_PROTECTED;
|
||||||
return Status;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Update file size
|
if (FileSizeIsDifferent) {
|
||||||
Status = SetFileSize (Instance, File, Info->FileSize);
|
Status = SetFileSize (Instance, File, Info->FileSize);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
return Status;
|
return 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
|
EFIAPI
|
||||||
|
@ -477,11 +543,17 @@ BootMonFsGetInfo (
|
||||||
BOOTMON_FS_FILE *File;
|
BOOTMON_FS_FILE *File;
|
||||||
BOOTMON_FS_INSTANCE *Instance;
|
BOOTMON_FS_INSTANCE *Instance;
|
||||||
|
|
||||||
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
|
if ((This == NULL) ||
|
||||||
if (File == NULL) {
|
(InformationType == NULL) ||
|
||||||
return EFI_DEVICE_ERROR;
|
(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;
|
Instance = File->Instance;
|
||||||
|
|
||||||
// If the instance has not been initialized yet then do it ...
|
// If the instance has not been initialized yet then do it ...
|
||||||
|
@ -509,6 +581,37 @@ BootMonFsGetInfo (
|
||||||
return Status;
|
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
|
EFIAPI
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BootMonFsSetInfo (
|
BootMonFsSetInfo (
|
||||||
|
@ -518,28 +621,56 @@ BootMonFsSetInfo (
|
||||||
IN VOID *Buffer
|
IN VOID *Buffer
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
BOOTMON_FS_FILE *File;
|
||||||
BOOTMON_FS_FILE *File;
|
EFI_FILE_INFO *Info;
|
||||||
BOOTMON_FS_INSTANCE *Instance;
|
EFI_FILE_SYSTEM_INFO *SystemInfo;
|
||||||
|
|
||||||
|
if ((This == NULL) ||
|
||||||
|
(InformationType == NULL) ||
|
||||||
|
(Buffer == NULL) ) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
|
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
|
||||||
if (File == NULL) {
|
if (File->Info == NULL) {
|
||||||
return EFI_DEVICE_ERROR;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
Instance = File->Instance;
|
if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {
|
||||||
|
Info = Buffer;
|
||||||
if (CompareGuid (InformationType, &gEfiFileInfoGuid) != 0) {
|
if (Info->Size < (SIZE_OF_EFI_FILE_INFO + StrSize (Info->FileName))) {
|
||||||
Status = SetFileInfo (Instance, File, BufferSize, (EFI_FILE_INFO *) Buffer);
|
return EFI_INVALID_PARAMETER;
|
||||||
} else {
|
}
|
||||||
// The only writable field in the other two information types
|
if (BufferSize < Info->Size) {
|
||||||
// (i.e. EFI_FILE_SYSTEM_INFO and EFI_FILE_SYSTEM_VOLUME_LABEL) is the
|
return EFI_BAD_BUFFER_SIZE;
|
||||||
// filesystem volume label. This can be retrieved with GetInfo, but it is
|
}
|
||||||
// hard-coded into this driver, not stored on media.
|
return (SetFileInfo (File->Instance, File, Info));
|
||||||
Status = EFI_UNSUPPORTED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
//
|
||||||
|
// 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
|
EFIAPI
|
||||||
|
|
|
@ -54,6 +54,30 @@ EFI_FILE_PROTOCOL mBootMonFsFileTemplate = {
|
||||||
BootMonFsFlushFile
|
BootMonFsFlushFile
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Search for a file given its name coded in Ascii.
|
||||||
|
|
||||||
|
When searching through the files of the volume, if a file is currently not
|
||||||
|
open, its name was written on the media and is kept in RAM in the
|
||||||
|
"HwDescription.Footer.Filename[]" field of the file's description.
|
||||||
|
|
||||||
|
If a file is currently open, its name might not have been written on the
|
||||||
|
media yet, and as the "HwDescription" is a mirror in RAM of what is on the
|
||||||
|
media the "HwDescription.Footer.Filename[]" might be outdated. In that case,
|
||||||
|
the up to date name of the file is stored in the "Info" field of the file's
|
||||||
|
description.
|
||||||
|
|
||||||
|
@param[in] Instance Pointer to the description of the volume in which
|
||||||
|
the file has to be search for.
|
||||||
|
@param[in] AsciiFileName Name of the file.
|
||||||
|
|
||||||
|
@param[out] File Pointer to the description of the file if the
|
||||||
|
file was found.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The file was found.
|
||||||
|
@retval EFI_NOT_FOUND The file was not found.
|
||||||
|
|
||||||
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BootMonGetFileFromAsciiFileName (
|
BootMonGetFileFromAsciiFileName (
|
||||||
IN BOOTMON_FS_INSTANCE *Instance,
|
IN BOOTMON_FS_INSTANCE *Instance,
|
||||||
|
@ -61,22 +85,26 @@ BootMonGetFileFromAsciiFileName (
|
||||||
OUT BOOTMON_FS_FILE **File
|
OUT BOOTMON_FS_FILE **File
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
LIST_ENTRY *Entry;
|
LIST_ENTRY *Entry;
|
||||||
BOOTMON_FS_FILE *FileEntry;
|
BOOTMON_FS_FILE *FileEntry;
|
||||||
|
CHAR8 OpenFileAsciiFileName[MAX_NAME_LENGTH];
|
||||||
// Remove the leading '\\'
|
CHAR8 *AsciiFileNameToCompare;
|
||||||
if (*AsciiFileName == '\\') {
|
|
||||||
AsciiFileName++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go through all the files in the list and return the file handle
|
// Go through all the files in the list and return the file handle
|
||||||
for (Entry = GetFirstNode (&Instance->RootFile->Link);
|
for (Entry = GetFirstNode (&Instance->RootFile->Link);
|
||||||
!IsNull (&Instance->RootFile->Link, Entry);
|
!IsNull (&Instance->RootFile->Link, Entry);
|
||||||
Entry = GetNextNode (&Instance->RootFile->Link, Entry)
|
Entry = GetNextNode (&Instance->RootFile->Link, Entry)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
FileEntry = BOOTMON_FS_FILE_FROM_LINK_THIS (Entry);
|
FileEntry = BOOTMON_FS_FILE_FROM_LINK_THIS (Entry);
|
||||||
if (AsciiStrCmp (FileEntry->HwDescription.Footer.Filename, AsciiFileName) == 0) {
|
if (FileEntry->Info != NULL) {
|
||||||
|
UnicodeStrToAsciiStr (FileEntry->Info->FileName, OpenFileAsciiFileName);
|
||||||
|
AsciiFileNameToCompare = OpenFileAsciiFileName;
|
||||||
|
} else {
|
||||||
|
AsciiFileNameToCompare = FileEntry->HwDescription.Footer.Filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AsciiStrCmp (AsciiFileNameToCompare, AsciiFileName) == 0) {
|
||||||
*File = FileEntry;
|
*File = FileEntry;
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -291,6 +319,7 @@ BootMonFsDriverStart (
|
||||||
BOOTMON_FS_INSTANCE *Instance;
|
BOOTMON_FS_INSTANCE *Instance;
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
UINTN VolumeNameSize;
|
UINTN VolumeNameSize;
|
||||||
|
EFI_FILE_INFO *Info;
|
||||||
|
|
||||||
Instance = AllocateZeroPool (sizeof (BOOTMON_FS_INSTANCE));
|
Instance = AllocateZeroPool (sizeof (BOOTMON_FS_INSTANCE));
|
||||||
if (Instance == NULL) {
|
if (Instance == NULL) {
|
||||||
|
@ -307,8 +336,7 @@ BootMonFsDriverStart (
|
||||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||||
);
|
);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
FreePool (Instance);
|
goto Error;
|
||||||
return Status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = gBS->OpenProtocol (
|
Status = gBS->OpenProtocol (
|
||||||
|
@ -320,8 +348,7 @@ BootMonFsDriverStart (
|
||||||
EFI_OPEN_PROTOCOL_BY_DRIVER
|
EFI_OPEN_PROTOCOL_BY_DRIVER
|
||||||
);
|
);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
FreePool (Instance);
|
goto Error;
|
||||||
return Status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -350,10 +377,16 @@ BootMonFsDriverStart (
|
||||||
// Initialize the root file
|
// Initialize the root file
|
||||||
Status = BootMonFsCreateFile (Instance, &Instance->RootFile);
|
Status = BootMonFsCreateFile (Instance, &Instance->RootFile);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
FreePool (Instance);
|
goto Error;
|
||||||
return Status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Info = AllocateZeroPool (sizeof (EFI_FILE_INFO));
|
||||||
|
if (Info == NULL) {
|
||||||
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
|
Instance->RootFile->Info = Info;
|
||||||
|
|
||||||
// Initialize the DevicePath of the Instance
|
// Initialize the DevicePath of the Instance
|
||||||
Status = gBS->OpenProtocol (
|
Status = gBS->OpenProtocol (
|
||||||
ControllerHandle,
|
ControllerHandle,
|
||||||
|
@ -364,8 +397,7 @@ BootMonFsDriverStart (
|
||||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||||
);
|
);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
FreePool (Instance);
|
goto Error;
|
||||||
return Status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -376,9 +408,24 @@ BootMonFsDriverStart (
|
||||||
&gEfiSimpleFileSystemProtocolGuid, &Instance->Fs,
|
&gEfiSimpleFileSystemProtocolGuid, &Instance->Fs,
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
|
|
||||||
InsertTailList (&mInstances, &Instance->Link);
|
InsertTailList (&mInstances, &Instance->Link);
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
|
||||||
|
Error:
|
||||||
|
|
||||||
|
if (Instance->RootFile != NULL) {
|
||||||
|
if (Instance->RootFile->Info != NULL) {
|
||||||
|
FreePool (Instance->RootFile->Info);
|
||||||
|
}
|
||||||
|
FreePool (Instance->RootFile);
|
||||||
|
}
|
||||||
|
FreePool (Instance);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -434,6 +481,10 @@ BootMonFsDriverStop (
|
||||||
&gEfiSimpleFileSystemProtocolGuid, &Instance->Fs,
|
&gEfiSimpleFileSystemProtocolGuid, &Instance->Fs,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
FreePool (Instance->RootFile->Info);
|
||||||
|
FreePool (Instance->RootFile);
|
||||||
|
FreePool (Instance);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,8 +54,14 @@ typedef struct {
|
||||||
|
|
||||||
EFI_FILE_PROTOCOL File;
|
EFI_FILE_PROTOCOL File;
|
||||||
|
|
||||||
|
//
|
||||||
|
// The following fields are relevant only if the file is open.
|
||||||
|
//
|
||||||
|
|
||||||
|
EFI_FILE_INFO *Info;
|
||||||
UINT64 Position;
|
UINT64 Position;
|
||||||
// If the file needs to be flushed then this list contain the memory buffer that creates this file
|
// If the file needs to be flushed then this list contain the memory
|
||||||
|
// buffer that creates this file
|
||||||
LIST_ENTRY RegionToFlushLink;
|
LIST_ENTRY RegionToFlushLink;
|
||||||
UINT64 OpenMode;
|
UINT64 OpenMode;
|
||||||
} BOOTMON_FS_FILE;
|
} BOOTMON_FS_FILE;
|
||||||
|
|
|
@ -39,6 +39,10 @@ InvalidateImageDescription (
|
||||||
|
|
||||||
Buffer = AllocateZeroPool (sizeof (HW_IMAGE_DESCRIPTION));
|
Buffer = AllocateZeroPool (sizeof (HW_IMAGE_DESCRIPTION));
|
||||||
|
|
||||||
|
if (Buffer == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
Status = DiskIo->WriteDisk (DiskIo,
|
Status = DiskIo->WriteDisk (DiskIo,
|
||||||
MediaId,
|
MediaId,
|
||||||
File->HwDescAddress,
|
File->HwDescAddress,
|
||||||
|
@ -51,83 +55,75 @@ InvalidateImageDescription (
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flush file data that will extend the file's length. Update and, if necessary,
|
/**
|
||||||
// move the image description.
|
Write the description of a file to storage media.
|
||||||
// We need to pass the file's starting position on media (FileStart), because
|
|
||||||
// if the file hasn't been flushed before its Description->BlockStart won't
|
This function uses DiskIo to write to the media, so call BlockIo->FlushBlocks()
|
||||||
// have been initialised.
|
after calling it to ensure the data are written on the media.
|
||||||
// FileStart must be aligned to the media's block size.
|
|
||||||
// Note that this function uses DiskIo to flush, so call BlockIo->FlushBlocks()
|
@param[in] File Description of the file whose description on the
|
||||||
// after calling it.
|
storage media has to be updated.
|
||||||
|
@param[in] FileName Name of the file. Its length is assumed to be
|
||||||
|
lower than MAX_NAME_LENGTH.
|
||||||
|
@param[in] DataSize Number of data bytes of the file.
|
||||||
|
@param[in] FileStart File's starting position on media. FileStart must
|
||||||
|
be aligned to the media's block size.
|
||||||
|
|
||||||
|
@retval EFI_WRITE_PROTECTED The device cannot be written to.
|
||||||
|
@retval EFI_DEVICE_ERROR The device reported an error while performing
|
||||||
|
the write operation.
|
||||||
|
|
||||||
|
**/
|
||||||
STATIC
|
STATIC
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
FlushAppendRegion (
|
WriteFileDescription (
|
||||||
IN BOOTMON_FS_FILE *File,
|
IN BOOTMON_FS_FILE *File,
|
||||||
IN BOOTMON_FS_FILE_REGION *Region,
|
IN CHAR8 *FileName,
|
||||||
IN UINT64 NewFileSize,
|
IN UINT32 DataSize,
|
||||||
IN UINT64 FileStart
|
IN UINT64 FileStart
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
EFI_DISK_IO_PROTOCOL *DiskIo;
|
EFI_DISK_IO_PROTOCOL *DiskIo;
|
||||||
UINTN BlockSize;
|
UINTN BlockSize;
|
||||||
HW_IMAGE_DESCRIPTION *Description;
|
UINT32 FileSize;
|
||||||
|
HW_IMAGE_DESCRIPTION *Description;
|
||||||
DiskIo = File->Instance->DiskIo;
|
|
||||||
|
|
||||||
|
DiskIo = File->Instance->DiskIo;
|
||||||
BlockSize = File->Instance->BlockIo->Media->BlockSize;
|
BlockSize = File->Instance->BlockIo->Media->BlockSize;
|
||||||
|
|
||||||
ASSERT (FileStart % BlockSize == 0);
|
ASSERT (FileStart % BlockSize == 0);
|
||||||
|
|
||||||
// Only invalidate the Image Description of files that have already been
|
//
|
||||||
// written in Flash
|
// Construct the file description
|
||||||
if (File->HwDescAddress != 0) {
|
//
|
||||||
Status = InvalidateImageDescription (File);
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
FileSize = DataSize + sizeof (HW_IMAGE_DESCRIPTION);
|
||||||
// Update File Description
|
|
||||||
//
|
|
||||||
Description = &File->HwDescription;
|
Description = &File->HwDescription;
|
||||||
Description->Attributes = 1;
|
Description->Attributes = 1;
|
||||||
Description->BlockStart = FileStart / BlockSize;
|
Description->BlockStart = FileStart / BlockSize;
|
||||||
Description->BlockEnd = Description->BlockStart + (NewFileSize / BlockSize);
|
Description->BlockEnd = Description->BlockStart + (FileSize / BlockSize);
|
||||||
|
AsciiStrCpy (Description->Footer.Filename, FileName);
|
||||||
|
|
||||||
|
#ifdef MDE_CPU_ARM
|
||||||
|
Description->Footer.Offset = HW_IMAGE_FOOTER_OFFSET;
|
||||||
|
Description->Footer.Version = HW_IMAGE_FOOTER_VERSION;
|
||||||
|
#else
|
||||||
|
Description->Footer.Offset = HW_IMAGE_FOOTER_OFFSET2;
|
||||||
|
Description->Footer.Version = HW_IMAGE_FOOTER_VERSION2;
|
||||||
|
#endif
|
||||||
Description->Footer.FooterSignature1 = HW_IMAGE_FOOTER_SIGNATURE_1;
|
Description->Footer.FooterSignature1 = HW_IMAGE_FOOTER_SIGNATURE_1;
|
||||||
Description->Footer.FooterSignature2 = HW_IMAGE_FOOTER_SIGNATURE_2;
|
Description->Footer.FooterSignature2 = HW_IMAGE_FOOTER_SIGNATURE_2;
|
||||||
#ifdef MDE_CPU_ARM
|
|
||||||
Description->Footer.Version = HW_IMAGE_FOOTER_VERSION;
|
|
||||||
Description->Footer.Offset = HW_IMAGE_FOOTER_OFFSET;
|
|
||||||
#else
|
|
||||||
Description->Footer.Version = HW_IMAGE_FOOTER_VERSION2;
|
|
||||||
Description->Footer.Offset = HW_IMAGE_FOOTER_OFFSET2;
|
|
||||||
#endif
|
|
||||||
Description->RegionCount = 1;
|
Description->RegionCount = 1;
|
||||||
Description->Region[0].Checksum = 0;
|
Description->Region[0].Checksum = 0;
|
||||||
Description->Region[0].Offset = Description->BlockStart * BlockSize;
|
Description->Region[0].Offset = Description->BlockStart * BlockSize;
|
||||||
Description->Region[0].Size = NewFileSize - sizeof (HW_IMAGE_DESCRIPTION);
|
Description->Region[0].Size = DataSize;
|
||||||
|
|
||||||
Status = BootMonFsComputeFooterChecksum (Description);
|
Status = BootMonFsComputeFooterChecksum (Description);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the new file data
|
File->HwDescAddress = ((Description->BlockEnd + 1) * BlockSize) - sizeof (HW_IMAGE_DESCRIPTION);
|
||||||
Status = DiskIo->WriteDisk (
|
|
||||||
DiskIo,
|
|
||||||
File->Instance->Media->MediaId,
|
|
||||||
FileStart + Region->Offset,
|
|
||||||
Region->Size,
|
|
||||||
Region->Buffer
|
|
||||||
);
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
|
|
||||||
// Round the file size up to the nearest block size
|
|
||||||
if ((NewFileSize % BlockSize) > 0) {
|
|
||||||
NewFileSize += BlockSize - (NewFileSize % BlockSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
File->HwDescAddress = (FileStart + NewFileSize) - sizeof (HW_IMAGE_DESCRIPTION);
|
|
||||||
|
|
||||||
// Update the file description on the media
|
// Update the file description on the media
|
||||||
Status = DiskIo->WriteDisk (
|
Status = DiskIo->WriteDisk (
|
||||||
|
@ -142,14 +138,6 @@ FlushAppendRegion (
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN
|
|
||||||
BootMonFsFileNeedFlush (
|
|
||||||
IN BOOTMON_FS_FILE *File
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return !IsListEmpty (&File->RegionToFlushLink);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find a space on media for a file that has not yet been flushed to disk.
|
// Find a space on media for a file that has not yet been flushed to disk.
|
||||||
// Just returns the first space that's big enough.
|
// Just returns the first space that's big enough.
|
||||||
// This function could easily be adapted to:
|
// This function could easily be adapted to:
|
||||||
|
@ -167,6 +155,7 @@ STATIC
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BootMonFsFindSpaceForNewFile (
|
BootMonFsFindSpaceForNewFile (
|
||||||
IN BOOTMON_FS_FILE *File,
|
IN BOOTMON_FS_FILE *File,
|
||||||
|
IN UINT64 FileSize,
|
||||||
OUT UINT64 *FileStart
|
OUT UINT64 *FileStart
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -174,26 +163,16 @@ BootMonFsFindSpaceForNewFile (
|
||||||
BOOTMON_FS_FILE *RootFile;
|
BOOTMON_FS_FILE *RootFile;
|
||||||
BOOTMON_FS_FILE *FileEntry;
|
BOOTMON_FS_FILE *FileEntry;
|
||||||
UINTN BlockSize;
|
UINTN BlockSize;
|
||||||
UINT64 FileSize;
|
|
||||||
EFI_BLOCK_IO_MEDIA *Media;
|
EFI_BLOCK_IO_MEDIA *Media;
|
||||||
|
|
||||||
Media = File->Instance->BlockIo->Media;
|
Media = File->Instance->BlockIo->Media;
|
||||||
BlockSize = Media->BlockSize;
|
BlockSize = Media->BlockSize;
|
||||||
RootFile = File->Instance->RootFile;
|
RootFile = File->Instance->RootFile;
|
||||||
|
|
||||||
if (IsListEmpty (&RootFile->Link)) {
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function must only be called for file which has not been flushed into
|
// This function must only be called for file which has not been flushed into
|
||||||
// Flash yet
|
// Flash yet
|
||||||
ASSERT (File->HwDescription.RegionCount == 0);
|
ASSERT (File->HwDescription.RegionCount == 0);
|
||||||
|
|
||||||
// Find out how big the file will be
|
|
||||||
FileSize = BootMonFsGetImageLength (File);
|
|
||||||
// Add the file header to the file
|
|
||||||
FileSize += sizeof (HW_IMAGE_DESCRIPTION);
|
|
||||||
|
|
||||||
*FileStart = 0;
|
*FileStart = 0;
|
||||||
// Go through all the files in the list
|
// Go through all the files in the list
|
||||||
for (FileLink = GetFirstNode (&RootFile->Link);
|
for (FileLink = GetFirstNode (&RootFile->Link);
|
||||||
|
@ -253,6 +232,20 @@ FreeFileRegions (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Flush all modified data associated with a file to a device.
|
||||||
|
|
||||||
|
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the
|
||||||
|
file handle to flush.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The data was flushed.
|
||||||
|
@retval EFI_ACCESS_DENIED The file was opened read-only.
|
||||||
|
@retval EFI_DEVICE_ERROR The device reported an error.
|
||||||
|
@retval EFI_VOLUME_FULL The volume is full.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Not enough resources were available to flush the data.
|
||||||
|
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
|
||||||
|
|
||||||
|
**/
|
||||||
EFIAPI
|
EFIAPI
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BootMonFsFlushFile (
|
BootMonFsFlushFile (
|
||||||
|
@ -261,52 +254,62 @@ BootMonFsFlushFile (
|
||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
BOOTMON_FS_INSTANCE *Instance;
|
BOOTMON_FS_INSTANCE *Instance;
|
||||||
|
EFI_FILE_INFO *Info;
|
||||||
|
EFI_BLOCK_IO_PROTOCOL *BlockIo;
|
||||||
|
EFI_BLOCK_IO_MEDIA *Media;
|
||||||
|
EFI_DISK_IO_PROTOCOL *DiskIo;
|
||||||
|
UINTN BlockSize;
|
||||||
|
CHAR8 AsciiFileName[MAX_NAME_LENGTH];
|
||||||
LIST_ENTRY *RegionToFlushLink;
|
LIST_ENTRY *RegionToFlushLink;
|
||||||
BOOTMON_FS_FILE *File;
|
BOOTMON_FS_FILE *File;
|
||||||
BOOTMON_FS_FILE *NextFile;
|
BOOTMON_FS_FILE *NextFile;
|
||||||
BOOTMON_FS_FILE_REGION *Region;
|
BOOTMON_FS_FILE_REGION *Region;
|
||||||
LIST_ENTRY *FileLink;
|
LIST_ENTRY *FileLink;
|
||||||
UINTN CurrentPhysicalSize;
|
UINTN CurrentPhysicalSize;
|
||||||
UINTN BlockSize;
|
|
||||||
UINT64 FileStart;
|
UINT64 FileStart;
|
||||||
UINT64 FileEnd;
|
UINT64 FileEnd;
|
||||||
UINT64 RegionStart;
|
UINT64 RegionStart;
|
||||||
UINT64 RegionEnd;
|
UINT64 RegionEnd;
|
||||||
|
UINT64 NewDataSize;
|
||||||
UINT64 NewFileSize;
|
UINT64 NewFileSize;
|
||||||
UINT64 EndOfAppendSpace;
|
UINT64 EndOfAppendSpace;
|
||||||
BOOLEAN HasSpace;
|
BOOLEAN HasSpace;
|
||||||
EFI_DISK_IO_PROTOCOL *DiskIo;
|
|
||||||
EFI_BLOCK_IO_PROTOCOL *BlockIo;
|
|
||||||
|
|
||||||
Status = EFI_SUCCESS;
|
if (This == NULL) {
|
||||||
FileStart = 0;
|
|
||||||
|
|
||||||
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
|
|
||||||
if (File == NULL) {
|
|
||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the file needs to be flushed
|
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
|
||||||
if (!BootMonFsFileNeedFlush (File)) {
|
if (File->Info == NULL) {
|
||||||
return Status;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
Instance = File->Instance;
|
if (File->OpenMode == EFI_FILE_MODE_READ) {
|
||||||
BlockIo = Instance->BlockIo;
|
return EFI_ACCESS_DENIED;
|
||||||
DiskIo = Instance->DiskIo;
|
}
|
||||||
BlockSize = BlockIo->Media->BlockSize;
|
|
||||||
|
Instance = File->Instance;
|
||||||
|
Info = File->Info;
|
||||||
|
BlockIo = Instance->BlockIo;
|
||||||
|
Media = BlockIo->Media;
|
||||||
|
DiskIo = Instance->DiskIo;
|
||||||
|
BlockSize = Media->BlockSize;
|
||||||
|
|
||||||
|
UnicodeStrToAsciiStr (Info->FileName, AsciiFileName);
|
||||||
|
|
||||||
// If the file doesn't exist then find a space for it
|
// If the file doesn't exist then find a space for it
|
||||||
if (File->HwDescription.RegionCount == 0) {
|
if (File->HwDescription.RegionCount == 0) {
|
||||||
Status = BootMonFsFindSpaceForNewFile (File, &FileStart);
|
Status = BootMonFsFindSpaceForNewFile (
|
||||||
// FileStart has changed so we need to recompute RegionEnd
|
File,
|
||||||
|
Info->FileSize + sizeof (HW_IMAGE_DESCRIPTION),
|
||||||
|
&FileStart
|
||||||
|
);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
FileStart = File->HwDescription.BlockStart * BlockSize;
|
FileStart = File->HwDescription.BlockStart * BlockSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FileEnd is the current NOR address of the end of the file's data
|
// FileEnd is the current NOR address of the end of the file's data
|
||||||
FileEnd = FileStart + File->HwDescription.Region[0].Size;
|
FileEnd = FileStart + File->HwDescription.Region[0].Size;
|
||||||
|
|
||||||
|
@ -316,17 +319,20 @@ BootMonFsFlushFile (
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Region = (BOOTMON_FS_FILE_REGION*)RegionToFlushLink;
|
Region = (BOOTMON_FS_FILE_REGION*)RegionToFlushLink;
|
||||||
|
if (Region->Size == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// RegionStart and RegionEnd are the the intended NOR address of the
|
// RegionStart and RegionEnd are the the intended NOR address of the
|
||||||
// start and end of the region
|
// start and end of the region
|
||||||
RegionStart = FileStart + Region->Offset;
|
RegionStart = FileStart + Region->Offset;
|
||||||
RegionEnd = RegionStart + Region->Size;
|
RegionEnd = RegionStart + Region->Size;
|
||||||
|
|
||||||
if (RegionEnd < FileEnd) {
|
if (RegionEnd < FileEnd) {
|
||||||
// Handle regions representing edits to existing portions of the file
|
// Handle regions representing edits to existing portions of the file
|
||||||
// Write the region data straight into the file
|
// Write the region data straight into the file
|
||||||
Status = DiskIo->WriteDisk (DiskIo,
|
Status = DiskIo->WriteDisk (DiskIo,
|
||||||
BlockIo->Media->MediaId,
|
Media->MediaId,
|
||||||
RegionStart,
|
RegionStart,
|
||||||
Region->Size,
|
Region->Size,
|
||||||
Region->Buffer
|
Region->Buffer
|
||||||
|
@ -345,7 +351,8 @@ BootMonFsFlushFile (
|
||||||
|
|
||||||
// Check if there is space to append the new region
|
// Check if there is space to append the new region
|
||||||
HasSpace = FALSE;
|
HasSpace = FALSE;
|
||||||
NewFileSize = (RegionEnd - FileStart) + sizeof (HW_IMAGE_DESCRIPTION);
|
NewDataSize = RegionEnd - FileStart;
|
||||||
|
NewFileSize = NewDataSize + sizeof (HW_IMAGE_DESCRIPTION);
|
||||||
CurrentPhysicalSize = BootMonFsGetPhysicalSize (File);
|
CurrentPhysicalSize = BootMonFsGetPhysicalSize (File);
|
||||||
if (NewFileSize <= CurrentPhysicalSize) {
|
if (NewFileSize <= CurrentPhysicalSize) {
|
||||||
HasSpace = TRUE;
|
HasSpace = TRUE;
|
||||||
|
@ -360,7 +367,7 @@ BootMonFsFlushFile (
|
||||||
EndOfAppendSpace = NextFile->HwDescription.BlockStart * BlockSize;
|
EndOfAppendSpace = NextFile->HwDescription.BlockStart * BlockSize;
|
||||||
} else {
|
} else {
|
||||||
// We are flushing the last file.
|
// We are flushing the last file.
|
||||||
EndOfAppendSpace = (BlockIo->Media->LastBlock + 1) * BlockSize;
|
EndOfAppendSpace = (Media->LastBlock + 1) * BlockSize;
|
||||||
}
|
}
|
||||||
if (EndOfAppendSpace - FileStart >= NewFileSize) {
|
if (EndOfAppendSpace - FileStart >= NewFileSize) {
|
||||||
HasSpace = TRUE;
|
HasSpace = TRUE;
|
||||||
|
@ -368,10 +375,31 @@ BootMonFsFlushFile (
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasSpace == TRUE) {
|
if (HasSpace == TRUE) {
|
||||||
Status = FlushAppendRegion (File, Region, NewFileSize, FileStart);
|
// Invalidate the current image description of the file if any.
|
||||||
|
if (File->HwDescAddress != 0) {
|
||||||
|
Status = InvalidateImageDescription (File);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the new file data
|
||||||
|
Status = DiskIo->WriteDisk (
|
||||||
|
DiskIo,
|
||||||
|
Media->MediaId,
|
||||||
|
RegionStart,
|
||||||
|
Region->Size,
|
||||||
|
Region->Buffer
|
||||||
|
);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Status = WriteFileDescription (File, AsciiFileName, NewDataSize, FileStart);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// There isn't a space for the file.
|
// There isn't a space for the file.
|
||||||
// Options here are to move the file or fragment it. However as files
|
// Options here are to move the file or fragment it. However as files
|
||||||
|
@ -385,20 +413,32 @@ BootMonFsFlushFile (
|
||||||
}
|
}
|
||||||
|
|
||||||
FreeFileRegions (File);
|
FreeFileRegions (File);
|
||||||
|
Info->PhysicalSize = BootMonFsGetPhysicalSize (File);
|
||||||
|
|
||||||
|
if ((AsciiStrCmp (AsciiFileName, File->HwDescription.Footer.Filename) != 0) ||
|
||||||
|
(Info->FileSize != File->HwDescription.Region[0].Size) ) {
|
||||||
|
Status = WriteFileDescription (File, AsciiFileName, Info->FileSize, FileStart);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Flush DiskIo Buffers (see UEFI Spec 12.7 - DiskIo buffers are flushed by
|
// Flush DiskIo Buffers (see UEFI Spec 12.7 - DiskIo buffers are flushed by
|
||||||
// calling FlushBlocks on the same device's BlockIo).
|
// calling FlushBlocks on the same device's BlockIo).
|
||||||
BlockIo->FlushBlocks (BlockIo);
|
BlockIo->FlushBlocks (BlockIo);
|
||||||
|
|
||||||
return Status;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Closes a file on the Nor Flash FS volume.
|
Close a specified file handle.
|
||||||
|
|
||||||
@param This The EFI_FILE_PROTOCOL to close.
|
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the file
|
||||||
|
handle to close.
|
||||||
|
|
||||||
@return Always returns EFI_SUCCESS.
|
@retval EFI_SUCCESS The file was closed.
|
||||||
|
@retval EFI_INVALID_PARAMETER The parameter "This" is NULL or is not an open
|
||||||
|
file handle.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFIAPI
|
EFIAPI
|
||||||
|
@ -407,44 +447,27 @@ BootMonFsCloseFile (
|
||||||
IN EFI_FILE_PROTOCOL *This
|
IN EFI_FILE_PROTOCOL *This
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Flush the file if needed
|
BOOTMON_FS_FILE *File;
|
||||||
This->Flush (This);
|
|
||||||
|
if (This == NULL) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
|
||||||
|
if (File->Info == NULL) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In the case of a file and not the root directory
|
||||||
|
if (This != &File->Instance->RootFile->File) {
|
||||||
|
This->Flush (This);
|
||||||
|
FreePool (File->Info);
|
||||||
|
File->Info = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new instance of BOOTMON_FS_FILE.
|
|
||||||
// Uses BootMonFsCreateFile to
|
|
||||||
STATIC
|
|
||||||
EFI_STATUS
|
|
||||||
CreateNewFile (
|
|
||||||
IN BOOTMON_FS_INSTANCE *Instance,
|
|
||||||
IN CHAR8* AsciiFileName,
|
|
||||||
OUT BOOTMON_FS_FILE **NewHandle
|
|
||||||
)
|
|
||||||
{
|
|
||||||
EFI_STATUS Status;
|
|
||||||
BOOTMON_FS_FILE *File;
|
|
||||||
|
|
||||||
Status = BootMonFsCreateFile (Instance, &File);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the leading '\\'
|
|
||||||
if (*AsciiFileName == '\\') {
|
|
||||||
AsciiFileName++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the file name
|
|
||||||
CopyMem (File->HwDescription.Footer.Filename, AsciiFileName, MAX_NAME_LENGTH);
|
|
||||||
|
|
||||||
// Add the file to list of files of the File System
|
|
||||||
InsertHeadList (&Instance->RootFile->Link, &File->Link);
|
|
||||||
|
|
||||||
*NewHandle = File;
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Open a file on the boot monitor file system.
|
Open a file on the boot monitor file system.
|
||||||
|
|
||||||
|
@ -490,11 +513,17 @@ BootMonFsOpenFile (
|
||||||
CHAR16 *Path;
|
CHAR16 *Path;
|
||||||
CHAR16 *Separator;
|
CHAR16 *Separator;
|
||||||
CHAR8 *AsciiFileName;
|
CHAR8 *AsciiFileName;
|
||||||
|
EFI_FILE_INFO *Info;
|
||||||
|
|
||||||
if (This == NULL) {
|
if (This == NULL) {
|
||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Directory = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
|
||||||
|
if (Directory->Info == NULL) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
if ((FileName == NULL) || (NewHandle == NULL)) {
|
if ((FileName == NULL) || (NewHandle == NULL)) {
|
||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
@ -508,11 +537,6 @@ BootMonFsOpenFile (
|
||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
Directory = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
|
|
||||||
if (Directory == NULL) {
|
|
||||||
return EFI_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
Instance = Directory->Instance;
|
Instance = Directory->Instance;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -535,6 +559,7 @@ BootMonFsOpenFile (
|
||||||
}
|
}
|
||||||
Path = (CHAR16*)Buf;
|
Path = (CHAR16*)Buf;
|
||||||
AsciiFileName = NULL;
|
AsciiFileName = NULL;
|
||||||
|
Info = NULL;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Handle single periods, double periods and convert forward slashes '/'
|
// Handle single periods, double periods and convert forward slashes '/'
|
||||||
|
@ -624,6 +649,18 @@ BootMonFsOpenFile (
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Allocate a buffer to store the characteristics of the file while the
|
||||||
|
// file is open. We allocate the maximum size to not have to reallocate
|
||||||
|
// if the file name is changed.
|
||||||
|
//
|
||||||
|
Info = AllocateZeroPool (
|
||||||
|
SIZE_OF_EFI_FILE_INFO + (sizeof (CHAR16) * MAX_NAME_LENGTH));
|
||||||
|
if (Info == NULL) {
|
||||||
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Open or create a file in the root directory.
|
// Open or create a file in the root directory.
|
||||||
//
|
//
|
||||||
|
@ -634,20 +671,32 @@ BootMonFsOpenFile (
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = CreateNewFile (Instance, AsciiFileName, &File);
|
Status = BootMonFsCreateFile (Instance, &File);
|
||||||
if (!EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
File->OpenMode = OpenMode;
|
goto Error;
|
||||||
*NewHandle = &File->File;
|
|
||||||
File->Position = 0;
|
|
||||||
}
|
}
|
||||||
|
InsertHeadList (&Instance->RootFile->Link, &File->Link);
|
||||||
|
Info->Attribute = Attributes;
|
||||||
} else {
|
} else {
|
||||||
//
|
//
|
||||||
// The file already exists.
|
// File already open, not supported yet.
|
||||||
//
|
//
|
||||||
File->OpenMode = OpenMode;
|
if (File->Info != NULL) {
|
||||||
*NewHandle = &File->File;
|
Status = EFI_UNSUPPORTED;
|
||||||
File->Position = 0;
|
goto Error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Info->FileSize = BootMonFsGetImageLength (File);
|
||||||
|
Info->PhysicalSize = BootMonFsGetPhysicalSize (File);
|
||||||
|
AsciiStrToUnicodeStr (AsciiFileName, Info->FileName);
|
||||||
|
|
||||||
|
File->Info = Info;
|
||||||
|
Info = NULL;
|
||||||
|
File->Position = 0;
|
||||||
|
File->OpenMode = OpenMode;
|
||||||
|
|
||||||
|
*NewHandle = &File->File;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error:
|
Error:
|
||||||
|
@ -656,6 +705,9 @@ Error:
|
||||||
if (AsciiFileName != NULL) {
|
if (AsciiFileName != NULL) {
|
||||||
FreePool (AsciiFileName);
|
FreePool (AsciiFileName);
|
||||||
}
|
}
|
||||||
|
if (Info != NULL) {
|
||||||
|
FreePool (Info);
|
||||||
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
@ -671,6 +723,19 @@ BootMonFsDeleteFail (
|
||||||
// You can't delete the root directory
|
// You can't delete the root directory
|
||||||
return EFI_WARN_DELETE_FAILURE;
|
return EFI_WARN_DELETE_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Close and delete a file from the boot monitor file system.
|
||||||
|
|
||||||
|
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the file
|
||||||
|
handle to delete.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The file was closed and deleted.
|
||||||
|
@retval EFI_INVALID_PARAMETER The parameter "This" is NULL or is not an open
|
||||||
|
file handle.
|
||||||
|
@retval EFI_WARN_DELETE_FAILURE The handle was closed, but the file was not deleted.
|
||||||
|
|
||||||
|
**/
|
||||||
EFIAPI
|
EFIAPI
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BootMonFsDelete (
|
BootMonFsDelete (
|
||||||
|
@ -681,23 +746,26 @@ BootMonFsDelete (
|
||||||
BOOTMON_FS_FILE *File;
|
BOOTMON_FS_FILE *File;
|
||||||
LIST_ENTRY *RegionToFlushLink;
|
LIST_ENTRY *RegionToFlushLink;
|
||||||
BOOTMON_FS_FILE_REGION *Region;
|
BOOTMON_FS_FILE_REGION *Region;
|
||||||
EFI_BLOCK_IO_PROTOCOL *BlockIo;
|
|
||||||
UINT8 *EmptyBuffer;
|
|
||||||
|
|
||||||
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
|
if (This == NULL) {
|
||||||
if (File == NULL) {
|
return EFI_INVALID_PARAMETER;
|
||||||
return EFI_DEVICE_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = EFI_SUCCESS;
|
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
|
||||||
|
if (File->Info == NULL) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
if (BootMonFsFileNeedFlush (File)) {
|
if (!IsListEmpty (&File->RegionToFlushLink)) {
|
||||||
// Free the entries from the Buffer List
|
// Free the entries from the Buffer List
|
||||||
RegionToFlushLink = GetFirstNode (&File->RegionToFlushLink);
|
RegionToFlushLink = GetFirstNode (&File->RegionToFlushLink);
|
||||||
do {
|
do {
|
||||||
Region = (BOOTMON_FS_FILE_REGION*)RegionToFlushLink;
|
Region = (BOOTMON_FS_FILE_REGION*)RegionToFlushLink;
|
||||||
|
|
||||||
// Get Next entry
|
//
|
||||||
|
// Get next element of the list before deleting the region description
|
||||||
|
// that contain the LIST_ENTRY structure.
|
||||||
|
//
|
||||||
RegionToFlushLink = RemoveEntryList (RegionToFlushLink);
|
RegionToFlushLink = RemoveEntryList (RegionToFlushLink);
|
||||||
|
|
||||||
// Free the buffers
|
// Free the buffers
|
||||||
|
@ -708,25 +776,18 @@ BootMonFsDelete (
|
||||||
|
|
||||||
// If (RegionCount is greater than 0) then the file already exists
|
// If (RegionCount is greater than 0) then the file already exists
|
||||||
if (File->HwDescription.RegionCount > 0) {
|
if (File->HwDescription.RegionCount > 0) {
|
||||||
BlockIo = File->Instance->BlockIo;
|
|
||||||
|
|
||||||
// Create an empty buffer
|
|
||||||
EmptyBuffer = AllocateZeroPool (BlockIo->Media->BlockSize);
|
|
||||||
if (EmptyBuffer == NULL) {
|
|
||||||
FreePool (File);
|
|
||||||
return EFI_OUT_OF_RESOURCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invalidate the last Block
|
// Invalidate the last Block
|
||||||
Status = InvalidateImageDescription (File);
|
Status = InvalidateImageDescription (File);
|
||||||
ASSERT_EFI_ERROR (Status);
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
FreePool (EmptyBuffer);
|
return EFI_WARN_DELETE_FAILURE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the entry from the list
|
// Remove the entry from the list
|
||||||
RemoveEntryList (&File->Link);
|
RemoveEntryList (&File->Link);
|
||||||
|
FreePool (File->Info);
|
||||||
FreePool (File);
|
FreePool (File);
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
reported an error while performing the read
|
reported an error while performing the read
|
||||||
operation.
|
operation.
|
||||||
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
|
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFIAPI
|
EFIAPI
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
|
@ -53,25 +54,30 @@ BootMonFsReadFile (
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
UINTN RemainingFileSize;
|
UINTN RemainingFileSize;
|
||||||
|
|
||||||
|
if ((This == NULL) ||
|
||||||
|
(BufferSize == NULL) ||
|
||||||
|
(Buffer == NULL) ) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
|
||||||
|
if (File->Info == NULL) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure the file has been written in Flash before reading it.
|
// Ensure the file has been written in Flash before reading it.
|
||||||
// This keeps the code simple and avoids having to manage a non-flushed file.
|
// This keeps the code simple and avoids having to manage a non-flushed file.
|
||||||
BootMonFsFlushFile (This);
|
BootMonFsFlushFile (This);
|
||||||
|
|
||||||
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
|
Instance = File->Instance;
|
||||||
if (File == NULL) {
|
DiskIo = Instance->DiskIo;
|
||||||
return EFI_INVALID_PARAMETER;
|
Media = Instance->Media;
|
||||||
}
|
|
||||||
|
|
||||||
Instance = File->Instance;
|
|
||||||
DiskIo = Instance->DiskIo;
|
|
||||||
Media = Instance->Media;
|
|
||||||
FileStart = (Media->LowestAlignedLba + File->HwDescription.BlockStart) * Media->BlockSize;
|
FileStart = (Media->LowestAlignedLba + File->HwDescription.BlockStart) * Media->BlockSize;
|
||||||
|
|
||||||
if (File->Position >= File->HwDescription.Region[0].Size) {
|
if (File->Position >= File->Info->FileSize) {
|
||||||
// The entire file has been read or the position has been
|
// The entire file has been read or the position has been
|
||||||
// set past the end of the file.
|
// set past the end of the file.
|
||||||
*BufferSize = 0;
|
*BufferSize = 0;
|
||||||
if (File->Position > File->HwDescription.Region[0].Size) {
|
if (File->Position > File->Info->FileSize) {
|
||||||
return EFI_DEVICE_ERROR;
|
return EFI_DEVICE_ERROR;
|
||||||
} else {
|
} else {
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
|
@ -79,7 +85,7 @@ BootMonFsReadFile (
|
||||||
}
|
}
|
||||||
|
|
||||||
// This driver assumes that the entire file is in region 0.
|
// This driver assumes that the entire file is in region 0.
|
||||||
RemainingFileSize = File->HwDescription.Region[0].Size - File->Position;
|
RemainingFileSize = File->Info->FileSize - File->Position;
|
||||||
|
|
||||||
// If read would go past end of file, truncate the read
|
// If read would go past end of file, truncate the read
|
||||||
if (*BufferSize > RemainingFileSize) {
|
if (*BufferSize > RemainingFileSize) {
|
||||||
|
@ -102,7 +108,26 @@ BootMonFsReadFile (
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inserts an entry into the write chain
|
/**
|
||||||
|
Write data to an open file.
|
||||||
|
|
||||||
|
The data is not written to the flash yet. It will be written when the file
|
||||||
|
will be either read, closed or flushed.
|
||||||
|
|
||||||
|
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that
|
||||||
|
is the file handle to write data to.
|
||||||
|
@param[in out] BufferSize On input, the size of the Buffer. On output, the
|
||||||
|
size of the data actually written. In both cases,
|
||||||
|
the size is measured in bytes.
|
||||||
|
@param[in] Buffer The buffer of data to write.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The data was written.
|
||||||
|
@retval EFI_ACCESS_DENIED The file was opened read only.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Unable to allocate the buffer to store the
|
||||||
|
data to write.
|
||||||
|
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
|
||||||
|
|
||||||
|
**/
|
||||||
EFIAPI
|
EFIAPI
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BootMonFsWriteFile (
|
BootMonFsWriteFile (
|
||||||
|
@ -114,38 +139,57 @@ BootMonFsWriteFile (
|
||||||
BOOTMON_FS_FILE *File;
|
BOOTMON_FS_FILE *File;
|
||||||
BOOTMON_FS_FILE_REGION *Region;
|
BOOTMON_FS_FILE_REGION *Region;
|
||||||
|
|
||||||
|
if (This == NULL) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
|
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
|
||||||
if (File == NULL) {
|
if (File->Info == NULL) {
|
||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(File->OpenMode & EFI_FILE_MODE_WRITE)) {
|
if (File->OpenMode == EFI_FILE_MODE_READ) {
|
||||||
return EFI_ACCESS_DENIED;
|
return EFI_ACCESS_DENIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate and initialize the memory region
|
// Allocate and initialize the memory region
|
||||||
Region = (BOOTMON_FS_FILE_REGION*)AllocateZeroPool (sizeof (BOOTMON_FS_FILE_REGION));
|
Region = (BOOTMON_FS_FILE_REGION*)AllocateZeroPool (sizeof (BOOTMON_FS_FILE_REGION));
|
||||||
if (Region == NULL) {
|
if (Region == NULL) {
|
||||||
|
*BufferSize = 0;
|
||||||
return EFI_OUT_OF_RESOURCES;
|
return EFI_OUT_OF_RESOURCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
Region->Buffer = AllocateCopyPool (*BufferSize, Buffer);
|
Region->Buffer = AllocateCopyPool (*BufferSize, Buffer);
|
||||||
if (Region->Buffer == NULL) {
|
if (Region->Buffer == NULL) {
|
||||||
|
*BufferSize = 0;
|
||||||
FreePool (Region);
|
FreePool (Region);
|
||||||
return EFI_OUT_OF_RESOURCES;
|
return EFI_OUT_OF_RESOURCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
Region->Size = *BufferSize;
|
Region->Size = *BufferSize;
|
||||||
|
|
||||||
Region->Offset = File->Position;
|
Region->Offset = File->Position;
|
||||||
|
|
||||||
InsertTailList (&File->RegionToFlushLink, &Region->Link);
|
InsertTailList (&File->RegionToFlushLink, &Region->Link);
|
||||||
|
|
||||||
File->Position += *BufferSize;
|
File->Position += *BufferSize;
|
||||||
|
|
||||||
|
if (File->Position > File->Info->FileSize) {
|
||||||
|
File->Info->FileSize = File->Position;
|
||||||
|
}
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set a file's current position.
|
||||||
|
|
||||||
|
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is
|
||||||
|
the file handle to set the requested position on.
|
||||||
|
@param[in] Position The byte position from the start of the file to set.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The position was set.
|
||||||
|
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
|
||||||
|
|
||||||
|
**/
|
||||||
EFIAPI
|
EFIAPI
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BootMonFsSetPosition (
|
BootMonFsSetPosition (
|
||||||
|
@ -153,33 +197,63 @@ BootMonFsSetPosition (
|
||||||
IN UINT64 Position
|
IN UINT64 Position
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
BOOTMON_FS_FILE *File;
|
BOOTMON_FS_FILE *File;
|
||||||
|
|
||||||
|
if (This == NULL) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
|
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
|
||||||
|
if (File->Info == NULL) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
// UEFI Spec section 12.5:
|
// UEFI Spec section 12.5:
|
||||||
// "Seeking to position 0xFFFFFFFFFFFFFFFF causes the current position to
|
// "Seeking to position 0xFFFFFFFFFFFFFFFF causes the current position to
|
||||||
// be set to the end of the file."
|
// be set to the end of the file."
|
||||||
|
//
|
||||||
if (Position == 0xFFFFFFFFFFFFFFFF) {
|
if (Position == 0xFFFFFFFFFFFFFFFF) {
|
||||||
File->Position = BootMonFsGetImageLength (File);
|
Position = File->Info->FileSize;
|
||||||
} else {
|
|
||||||
// NB: Seeking past the end of the file is valid.
|
|
||||||
File->Position = Position;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File->Position = Position;
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return a file's current position.
|
||||||
|
|
||||||
|
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is
|
||||||
|
the file handle to get the current position on.
|
||||||
|
@param[out] Position The address to return the file's current position value.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The position was returned.
|
||||||
|
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
|
||||||
|
|
||||||
|
**/
|
||||||
EFIAPI
|
EFIAPI
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BootMonFsGetPosition (
|
BootMonFsGetPosition (
|
||||||
IN EFI_FILE_PROTOCOL *This,
|
IN EFI_FILE_PROTOCOL *This,
|
||||||
OUT UINT64 *Position
|
OUT UINT64 *Position
|
||||||
) {
|
)
|
||||||
|
{
|
||||||
BOOTMON_FS_FILE *File;
|
BOOTMON_FS_FILE *File;
|
||||||
|
|
||||||
|
if (This == NULL) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
|
File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
|
||||||
|
if (File->Info == NULL) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Position == NULL) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
*Position = File->Position;
|
*Position = File->Position;
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue