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;
}
-