diff --git a/ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.c b/ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.c index b04e866a99..5f1159d81a 100644 --- a/ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.c +++ b/ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.c @@ -2,7 +2,7 @@ Support a Semi Host file system over a debuggers JTAG Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
- Portions copyright (c) 2011-2013, ARM Ltd. All rights reserved.
+ Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -32,6 +33,9 @@ #include "SemihostFs.h" +#define DEFAULT_SEMIHOST_FS_LABEL L"SemihostFs" + +STATIC CHAR16 *mSemihostFsLabel; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL gSemihostFs = { EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION, @@ -69,13 +73,15 @@ SEMIHOST_DEVICE_PATH gDevicePath = { }; typedef struct { - LIST_ENTRY Link; - UINT64 Signature; - EFI_FILE File; - CHAR8 *FileName; - UINT32 Position; - UINTN SemihostHandle; - BOOLEAN IsRoot; + LIST_ENTRY Link; + UINT64 Signature; + EFI_FILE File; + CHAR8 *FileName; + UINT64 OpenMode; + UINT32 Position; + UINTN SemihostHandle; + BOOLEAN IsRoot; + EFI_FILE_INFO Info; } SEMIHOST_FCB; #define SEMIHOST_FCB_SIGNATURE SIGNATURE_32( 'S', 'H', 'F', 'C' ) @@ -134,6 +140,7 @@ VolumeOpen ( } RootFcb->IsRoot = TRUE; + RootFcb->Info.Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY; InsertTailList (&gFileList, &RootFcb->Link); @@ -157,11 +164,17 @@ FileOpen ( CHAR8 *AsciiFileName; UINT32 SemihostMode; BOOLEAN IsRoot; + UINTN Length; if ((FileName == NULL) || (NewHandle == NULL)) { return EFI_INVALID_PARAMETER; } + // Semihosting does not support directories + if (Attributes & EFI_FILE_DIRECTORY) { + return EFI_UNSUPPORTED; + } + // Semihost interface requires ASCII filenames AsciiFileName = AllocatePool ((StrLen (FileName) + 1) * sizeof (CHAR8)); if (AsciiFileName == NULL) { @@ -213,6 +226,18 @@ FileOpen ( FileFcb->SemihostHandle = SemihostHandle; FileFcb->Position = 0; 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); @@ -271,8 +296,11 @@ FileDelete ( // Call the semihost interface to delete the file. Status = SemihostFileRemove (FileName); + if (EFI_ERROR(Status)) { + Status = EFI_WARN_DELETE_FAILURE; + } } else { - Status = EFI_UNSUPPORTED; + Status = EFI_WARN_DELETE_FAILURE; } return Status; @@ -316,6 +344,11 @@ FileWrite ( 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); if (!EFI_ERROR(Status)) { @@ -388,8 +421,6 @@ GetFileInfo ( UINTN NameSize = 0; UINTN ResultSize; UINTN Index; - UINTN Length; - EFI_STATUS Status; if (Fcb->IsRoot == TRUE) { ResultSize = SIZE_OF_EFI_FILE_INFO + sizeof(CHAR16); @@ -405,30 +436,20 @@ GetFileInfo ( Info = Buffer; - // Zero out the structure - ZeroMem (Info, SIZE_OF_EFI_FILE_INFO); + // Copy the current file info + CopyMem (Info, &Fcb->Info, SIZE_OF_EFI_FILE_INFO); // Fill in the structure Info->Size = ResultSize; if (Fcb->IsRoot == TRUE) { - Info->Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY; Info->FileName[0] = L'\0'; } else { - Status = SemihostFileLength (Fcb->SemihostHandle, &Length); - if (EFI_ERROR(Status)) { - return Status; - } - - Info->FileSize = Length; - Info->PhysicalSize = Length; - for (Index = 0; Index < NameSize; Index++) { Info->FileName[Index] = Fcb->FileName[Index]; } } - *BufferSize = ResultSize; return EFI_SUCCESS; @@ -444,10 +465,9 @@ GetFilesystemInfo ( { EFI_FILE_SYSTEM_INFO *Info = NULL; EFI_STATUS Status; - STATIC CHAR16 Label[] = L"SemihostFs"; - UINTN ResultSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize(Label); + UINTN ResultSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (mSemihostFsLabel); - if(*BufferSize >= ResultSize) { + if (*BufferSize >= ResultSize) { ZeroMem (Buffer, ResultSize); Status = EFI_SUCCESS; @@ -459,7 +479,7 @@ GetFilesystemInfo ( Info->FreeSpace = 0; Info->BlockSize = 0; - StrCpy (Info->VolumeLabel, Label); + StrCpy (Info->VolumeLabel, mSemihostFsLabel); } else { Status = EFI_BUFFER_TOO_SMALL; } @@ -476,17 +496,31 @@ FileGetInfo ( OUT VOID *Buffer ) { - SEMIHOST_FCB *Fcb = NULL; - EFI_STATUS Status = EFI_UNSUPPORTED; + SEMIHOST_FCB *Fcb; + EFI_STATUS Status; + UINTN ResultSize; Fcb = SEMIHOST_FCB_FROM_THIS(File); - if (CompareGuid(InformationType, &gEfiFileSystemInfoGuid) != 0) { - Status = GetFilesystemInfo(Fcb, BufferSize, Buffer); - } else if (CompareGuid(InformationType, &gEfiFileInfoGuid) != 0) { - Status = GetFileInfo(Fcb, BufferSize, Buffer); + if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid) != 0) { + Status = GetFilesystemInfo (Fcb, BufferSize, Buffer); + } else if (CompareGuid (InformationType, &gEfiFileInfoGuid) != 0) { + 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; } @@ -498,7 +532,27 @@ FileSetInfo ( 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 @@ -506,7 +560,19 @@ FileFlush ( 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 @@ -515,17 +581,27 @@ SemihostFsEntryPoint ( IN EFI_SYSTEM_TABLE *SystemTable ) { - EFI_STATUS Status = EFI_NOT_FOUND; + EFI_STATUS Status; + + Status = EFI_NOT_FOUND; if (SemihostConnectionSupported ()) { + mSemihostFsLabel = AllocateCopyPool (StrSize (DEFAULT_SEMIHOST_FS_LABEL), DEFAULT_SEMIHOST_FS_LABEL); + if (mSemihostFsLabel == NULL) { + return EFI_OUT_OF_RESOURCES; + } + Status = gBS->InstallMultipleProtocolInterfaces ( &gInstallHandle, &gEfiSimpleFileSystemProtocolGuid, &gSemihostFs, &gEfiDevicePathProtocolGuid, &gDevicePath, NULL ); + + if (EFI_ERROR(Status)) { + FreePool (mSemihostFsLabel); + } } return Status; } -