ArmPkg/SemihostFs: Make the driver more compliant with the UEFI specification

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Olivier Martin <olivier.martin@arm.com>



git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@14262 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
oliviermartin
2013-04-14 09:24:44 +00:00
parent 6bc77e7a21
commit 09f2cf8295

View File

@@ -18,6 +18,7 @@
#include <Guid/FileInfo.h> #include <Guid/FileInfo.h>
#include <Guid/FileSystemInfo.h> #include <Guid/FileSystemInfo.h>
#include <Guid/FileSystemVolumeLabelInfo.h>
#include <Library/BaseLib.h> #include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h> #include <Library/BaseMemoryLib.h>
@@ -32,6 +33,9 @@
#include "SemihostFs.h" #include "SemihostFs.h"
#define DEFAULT_SEMIHOST_FS_LABEL L"SemihostFs"
STATIC CHAR16 *mSemihostFsLabel;
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL gSemihostFs = { EFI_SIMPLE_FILE_SYSTEM_PROTOCOL gSemihostFs = {
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION, EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION,
@@ -73,9 +77,11 @@ typedef struct {
UINT64 Signature; UINT64 Signature;
EFI_FILE File; EFI_FILE File;
CHAR8 *FileName; CHAR8 *FileName;
UINT64 OpenMode;
UINT32 Position; UINT32 Position;
UINTN SemihostHandle; UINTN SemihostHandle;
BOOLEAN IsRoot; BOOLEAN IsRoot;
EFI_FILE_INFO Info;
} SEMIHOST_FCB; } SEMIHOST_FCB;
#define SEMIHOST_FCB_SIGNATURE SIGNATURE_32( 'S', 'H', 'F', 'C' ) #define SEMIHOST_FCB_SIGNATURE SIGNATURE_32( 'S', 'H', 'F', 'C' )
@@ -134,6 +140,7 @@ VolumeOpen (
} }
RootFcb->IsRoot = TRUE; RootFcb->IsRoot = TRUE;
RootFcb->Info.Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY;
InsertTailList (&gFileList, &RootFcb->Link); InsertTailList (&gFileList, &RootFcb->Link);
@@ -157,11 +164,17 @@ FileOpen (
CHAR8 *AsciiFileName; CHAR8 *AsciiFileName;
UINT32 SemihostMode; UINT32 SemihostMode;
BOOLEAN IsRoot; BOOLEAN IsRoot;
UINTN Length;
if ((FileName == NULL) || (NewHandle == NULL)) { if ((FileName == NULL) || (NewHandle == NULL)) {
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
} }
// Semihosting does not support directories
if (Attributes & EFI_FILE_DIRECTORY) {
return EFI_UNSUPPORTED;
}
// Semihost interface requires ASCII filenames // Semihost interface requires ASCII filenames
AsciiFileName = AllocatePool ((StrLen (FileName) + 1) * sizeof (CHAR8)); AsciiFileName = AllocatePool ((StrLen (FileName) + 1) * sizeof (CHAR8));
if (AsciiFileName == NULL) { if (AsciiFileName == NULL) {
@@ -213,6 +226,18 @@ FileOpen (
FileFcb->SemihostHandle = SemihostHandle; FileFcb->SemihostHandle = SemihostHandle;
FileFcb->Position = 0; FileFcb->Position = 0;
FileFcb->IsRoot = IsRoot; FileFcb->IsRoot = IsRoot;
FileFcb->OpenMode = OpenMode;
if (!IsRoot) {
Status = SemihostFileLength (SemihostHandle, &Length);
if (EFI_ERROR(Status)) {
return Status;
}
FileFcb->Info.FileSize = Length;
FileFcb->Info.PhysicalSize = Length;
FileFcb->Info.Attribute = Attributes;
}
InsertTailList (&gFileList, &FileFcb->Link); InsertTailList (&gFileList, &FileFcb->Link);
@@ -271,8 +296,11 @@ FileDelete (
// Call the semihost interface to delete the file. // Call the semihost interface to delete the file.
Status = SemihostFileRemove (FileName); Status = SemihostFileRemove (FileName);
if (EFI_ERROR(Status)) {
Status = EFI_WARN_DELETE_FAILURE;
}
} else { } else {
Status = EFI_UNSUPPORTED; Status = EFI_WARN_DELETE_FAILURE;
} }
return Status; return Status;
@@ -316,6 +344,11 @@ FileWrite (
Fcb = SEMIHOST_FCB_FROM_THIS(File); Fcb = SEMIHOST_FCB_FROM_THIS(File);
// We cannot write a read-only file
if (Fcb->OpenMode & EFI_FILE_READ_ONLY) {
return EFI_ACCESS_DENIED;
}
Status = SemihostFileWrite (Fcb->SemihostHandle, &WriteSize, Buffer); Status = SemihostFileWrite (Fcb->SemihostHandle, &WriteSize, Buffer);
if (!EFI_ERROR(Status)) { if (!EFI_ERROR(Status)) {
@@ -388,8 +421,6 @@ GetFileInfo (
UINTN NameSize = 0; UINTN NameSize = 0;
UINTN ResultSize; UINTN ResultSize;
UINTN Index; UINTN Index;
UINTN Length;
EFI_STATUS Status;
if (Fcb->IsRoot == TRUE) { if (Fcb->IsRoot == TRUE) {
ResultSize = SIZE_OF_EFI_FILE_INFO + sizeof(CHAR16); ResultSize = SIZE_OF_EFI_FILE_INFO + sizeof(CHAR16);
@@ -405,30 +436,20 @@ GetFileInfo (
Info = Buffer; Info = Buffer;
// Zero out the structure // Copy the current file info
ZeroMem (Info, SIZE_OF_EFI_FILE_INFO); CopyMem (Info, &Fcb->Info, SIZE_OF_EFI_FILE_INFO);
// Fill in the structure // Fill in the structure
Info->Size = ResultSize; Info->Size = ResultSize;
if (Fcb->IsRoot == TRUE) { if (Fcb->IsRoot == TRUE) {
Info->Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY;
Info->FileName[0] = L'\0'; Info->FileName[0] = L'\0';
} else { } else {
Status = SemihostFileLength (Fcb->SemihostHandle, &Length);
if (EFI_ERROR(Status)) {
return Status;
}
Info->FileSize = Length;
Info->PhysicalSize = Length;
for (Index = 0; Index < NameSize; Index++) { for (Index = 0; Index < NameSize; Index++) {
Info->FileName[Index] = Fcb->FileName[Index]; Info->FileName[Index] = Fcb->FileName[Index];
} }
} }
*BufferSize = ResultSize; *BufferSize = ResultSize;
return EFI_SUCCESS; return EFI_SUCCESS;
@@ -444,8 +465,7 @@ GetFilesystemInfo (
{ {
EFI_FILE_SYSTEM_INFO *Info = NULL; EFI_FILE_SYSTEM_INFO *Info = NULL;
EFI_STATUS Status; EFI_STATUS Status;
STATIC CHAR16 Label[] = L"SemihostFs"; UINTN ResultSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (mSemihostFsLabel);
UINTN ResultSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize(Label);
if (*BufferSize >= ResultSize) { if (*BufferSize >= ResultSize) {
ZeroMem (Buffer, ResultSize); ZeroMem (Buffer, ResultSize);
@@ -459,7 +479,7 @@ GetFilesystemInfo (
Info->FreeSpace = 0; Info->FreeSpace = 0;
Info->BlockSize = 0; Info->BlockSize = 0;
StrCpy (Info->VolumeLabel, Label); StrCpy (Info->VolumeLabel, mSemihostFsLabel);
} else { } else {
Status = EFI_BUFFER_TOO_SMALL; Status = EFI_BUFFER_TOO_SMALL;
} }
@@ -476,8 +496,9 @@ FileGetInfo (
OUT VOID *Buffer OUT VOID *Buffer
) )
{ {
SEMIHOST_FCB *Fcb = NULL; SEMIHOST_FCB *Fcb;
EFI_STATUS Status = EFI_UNSUPPORTED; EFI_STATUS Status;
UINTN ResultSize;
Fcb = SEMIHOST_FCB_FROM_THIS(File); Fcb = SEMIHOST_FCB_FROM_THIS(File);
@@ -485,6 +506,19 @@ FileGetInfo (
Status = GetFilesystemInfo (Fcb, BufferSize, Buffer); Status = GetFilesystemInfo (Fcb, BufferSize, Buffer);
} else if (CompareGuid (InformationType, &gEfiFileInfoGuid) != 0) { } else if (CompareGuid (InformationType, &gEfiFileInfoGuid) != 0) {
Status = GetFileInfo (Fcb, BufferSize, Buffer); Status = GetFileInfo (Fcb, BufferSize, Buffer);
} else if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid) != 0) {
ResultSize = StrSize (mSemihostFsLabel);
if (*BufferSize >= ResultSize) {
StrCpy (Buffer, mSemihostFsLabel);
Status = EFI_SUCCESS;
} else {
Status = EFI_BUFFER_TOO_SMALL;
}
*BufferSize = ResultSize;
} else {
Status = EFI_UNSUPPORTED;
} }
return Status; return Status;
@@ -498,7 +532,27 @@ FileSetInfo (
IN VOID *Buffer IN VOID *Buffer
) )
{ {
return EFI_UNSUPPORTED; EFI_STATUS Status;
if (Buffer == NULL) {
return EFI_INVALID_PARAMETER;
}
Status = EFI_UNSUPPORTED;
if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid) != 0) {
//Status = SetFilesystemInfo (Fcb, BufferSize, Buffer);
} else if (CompareGuid (InformationType, &gEfiFileInfoGuid) != 0) {
//Status = SetFileInfo (Fcb, BufferSize, Buffer);
} else if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid) != 0) {
if (StrSize (Buffer) > 0) {
FreePool (mSemihostFsLabel);
mSemihostFsLabel = AllocateCopyPool (StrSize (Buffer), Buffer);
Status = EFI_SUCCESS;
}
}
return Status;
} }
EFI_STATUS EFI_STATUS
@@ -506,7 +560,19 @@ FileFlush (
IN EFI_FILE *File IN EFI_FILE *File
) )
{ {
SEMIHOST_FCB *Fcb;
Fcb = SEMIHOST_FCB_FROM_THIS(File);
if (Fcb->IsRoot) {
return EFI_SUCCESS; return EFI_SUCCESS;
} else {
if (Fcb->Info.Attribute & EFI_FILE_READ_ONLY) {
return EFI_ACCESS_DENIED;
} else {
return EFI_SUCCESS;
}
}
} }
EFI_STATUS EFI_STATUS
@@ -515,17 +581,27 @@ SemihostFsEntryPoint (
IN EFI_SYSTEM_TABLE *SystemTable IN EFI_SYSTEM_TABLE *SystemTable
) )
{ {
EFI_STATUS Status = EFI_NOT_FOUND; EFI_STATUS Status;
Status = EFI_NOT_FOUND;
if (SemihostConnectionSupported ()) { if (SemihostConnectionSupported ()) {
mSemihostFsLabel = AllocateCopyPool (StrSize (DEFAULT_SEMIHOST_FS_LABEL), DEFAULT_SEMIHOST_FS_LABEL);
if (mSemihostFsLabel == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Status = gBS->InstallMultipleProtocolInterfaces ( Status = gBS->InstallMultipleProtocolInterfaces (
&gInstallHandle, &gInstallHandle,
&gEfiSimpleFileSystemProtocolGuid, &gSemihostFs, &gEfiSimpleFileSystemProtocolGuid, &gSemihostFs,
&gEfiDevicePathProtocolGuid, &gDevicePath, &gEfiDevicePathProtocolGuid, &gDevicePath,
NULL NULL
); );
if (EFI_ERROR(Status)) {
FreePool (mSemihostFsLabel);
}
} }
return Status; return Status;
} }