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

@@ -2,7 +2,7 @@
Support a Semi Host file system over a debuggers JTAG Support a Semi Host file system over a debuggers JTAG
Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR> Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
Portions copyright (c) 2011-2013, ARM Ltd. All rights reserved.<BR> Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License are licensed and made available under the terms and conditions of the BSD License
@@ -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,
@@ -69,13 +73,15 @@ SEMIHOST_DEVICE_PATH gDevicePath = {
}; };
typedef struct { typedef struct {
LIST_ENTRY Link; LIST_ENTRY Link;
UINT64 Signature; UINT64 Signature;
EFI_FILE File; EFI_FILE File;
CHAR8 *FileName; CHAR8 *FileName;
UINT32 Position; UINT64 OpenMode;
UINTN SemihostHandle; UINT32 Position;
BOOLEAN IsRoot; UINTN SemihostHandle;
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,10 +465,9 @@ 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);
Status = EFI_SUCCESS; Status = EFI_SUCCESS;
@@ -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,17 +496,31 @@ 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);
if (CompareGuid(InformationType, &gEfiFileSystemInfoGuid) != 0) { if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid) != 0) {
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
) )
{ {
return EFI_SUCCESS; SEMIHOST_FCB *Fcb;
Fcb = SEMIHOST_FCB_FROM_THIS(File);
if (Fcb->IsRoot) {
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;
} }