Support a Semi Host file system over a debuggers JTAG\r
\r
Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
- Portions copyright (c) 2011-2013, ARM Ltd. All rights reserved.<BR>\r
+ Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>\r
\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
\r
#include <Guid/FileInfo.h>\r
#include <Guid/FileSystemInfo.h>\r
+#include <Guid/FileSystemVolumeLabelInfo.h>\r
\r
#include <Library/BaseLib.h>\r
#include <Library/BaseMemoryLib.h> \r
\r
#include "SemihostFs.h"\r
\r
+#define DEFAULT_SEMIHOST_FS_LABEL L"SemihostFs"\r
+\r
+STATIC CHAR16 *mSemihostFsLabel;\r
\r
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL gSemihostFs = {\r
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION,\r
};\r
\r
typedef struct {\r
- LIST_ENTRY Link;\r
- UINT64 Signature;\r
- EFI_FILE File;\r
- CHAR8 *FileName;\r
- UINT32 Position;\r
- UINTN SemihostHandle;\r
- BOOLEAN IsRoot;\r
+ LIST_ENTRY Link;\r
+ UINT64 Signature;\r
+ EFI_FILE File;\r
+ CHAR8 *FileName;\r
+ UINT64 OpenMode;\r
+ UINT32 Position;\r
+ UINTN SemihostHandle;\r
+ BOOLEAN IsRoot;\r
+ EFI_FILE_INFO Info;\r
} SEMIHOST_FCB;\r
\r
#define SEMIHOST_FCB_SIGNATURE SIGNATURE_32( 'S', 'H', 'F', 'C' )\r
}\r
\r
RootFcb->IsRoot = TRUE;\r
+ RootFcb->Info.Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY;\r
\r
InsertTailList (&gFileList, &RootFcb->Link);\r
\r
CHAR8 *AsciiFileName;\r
UINT32 SemihostMode;\r
BOOLEAN IsRoot;\r
+ UINTN Length;\r
\r
if ((FileName == NULL) || (NewHandle == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
+ // Semihosting does not support directories\r
+ if (Attributes & EFI_FILE_DIRECTORY) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
// Semihost interface requires ASCII filenames\r
AsciiFileName = AllocatePool ((StrLen (FileName) + 1) * sizeof (CHAR8));\r
if (AsciiFileName == NULL) {\r
FileFcb->SemihostHandle = SemihostHandle;\r
FileFcb->Position = 0;\r
FileFcb->IsRoot = IsRoot;\r
+ FileFcb->OpenMode = OpenMode;\r
+\r
+ if (!IsRoot) {\r
+ Status = SemihostFileLength (SemihostHandle, &Length);\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+\r
+ FileFcb->Info.FileSize = Length;\r
+ FileFcb->Info.PhysicalSize = Length;\r
+ FileFcb->Info.Attribute = Attributes;\r
+ }\r
\r
InsertTailList (&gFileList, &FileFcb->Link);\r
\r
\r
// Call the semihost interface to delete the file.\r
Status = SemihostFileRemove (FileName);\r
+ if (EFI_ERROR(Status)) {\r
+ Status = EFI_WARN_DELETE_FAILURE;\r
+ }\r
} else {\r
- Status = EFI_UNSUPPORTED;\r
+ Status = EFI_WARN_DELETE_FAILURE;\r
}\r
\r
return Status;\r
\r
Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
\r
+ // We cannot write a read-only file\r
+ if (Fcb->OpenMode & EFI_FILE_READ_ONLY) {\r
+ return EFI_ACCESS_DENIED;\r
+ }\r
+\r
Status = SemihostFileWrite (Fcb->SemihostHandle, &WriteSize, Buffer);\r
\r
if (!EFI_ERROR(Status)) {\r
UINTN NameSize = 0;\r
UINTN ResultSize;\r
UINTN Index;\r
- UINTN Length;\r
- EFI_STATUS Status;\r
\r
if (Fcb->IsRoot == TRUE) {\r
ResultSize = SIZE_OF_EFI_FILE_INFO + sizeof(CHAR16);\r
\r
Info = Buffer;\r
\r
- // Zero out the structure\r
- ZeroMem (Info, SIZE_OF_EFI_FILE_INFO);\r
+ // Copy the current file info\r
+ CopyMem (Info, &Fcb->Info, SIZE_OF_EFI_FILE_INFO);\r
\r
// Fill in the structure\r
Info->Size = ResultSize;\r
\r
if (Fcb->IsRoot == TRUE) {\r
- Info->Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY;\r
Info->FileName[0] = L'\0';\r
} else {\r
- Status = SemihostFileLength (Fcb->SemihostHandle, &Length);\r
- if (EFI_ERROR(Status)) {\r
- return Status;\r
- }\r
-\r
- Info->FileSize = Length;\r
- Info->PhysicalSize = Length;\r
-\r
for (Index = 0; Index < NameSize; Index++) {\r
Info->FileName[Index] = Fcb->FileName[Index]; \r
}\r
}\r
\r
-\r
*BufferSize = ResultSize; \r
\r
return EFI_SUCCESS;\r
{\r
EFI_FILE_SYSTEM_INFO *Info = NULL;\r
EFI_STATUS Status;\r
- STATIC CHAR16 Label[] = L"SemihostFs";\r
- UINTN ResultSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize(Label);\r
+ UINTN ResultSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (mSemihostFsLabel);\r
\r
- if(*BufferSize >= ResultSize) {\r
+ if (*BufferSize >= ResultSize) {\r
ZeroMem (Buffer, ResultSize);\r
Status = EFI_SUCCESS;\r
\r
Info->FreeSpace = 0;\r
Info->BlockSize = 0;\r
\r
- StrCpy (Info->VolumeLabel, Label);\r
+ StrCpy (Info->VolumeLabel, mSemihostFsLabel);\r
} else {\r
Status = EFI_BUFFER_TOO_SMALL;\r
}\r
OUT VOID *Buffer\r
)\r
{\r
- SEMIHOST_FCB *Fcb = NULL;\r
- EFI_STATUS Status = EFI_UNSUPPORTED;\r
+ SEMIHOST_FCB *Fcb;\r
+ EFI_STATUS Status;\r
+ UINTN ResultSize;\r
\r
Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
\r
- if (CompareGuid(InformationType, &gEfiFileSystemInfoGuid) != 0) {\r
- Status = GetFilesystemInfo(Fcb, BufferSize, Buffer); \r
- } else if (CompareGuid(InformationType, &gEfiFileInfoGuid) != 0) {\r
- Status = GetFileInfo(Fcb, BufferSize, Buffer); \r
+ if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid) != 0) {\r
+ Status = GetFilesystemInfo (Fcb, BufferSize, Buffer);\r
+ } else if (CompareGuid (InformationType, &gEfiFileInfoGuid) != 0) {\r
+ Status = GetFileInfo (Fcb, BufferSize, Buffer);\r
+ } else if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid) != 0) {\r
+ ResultSize = StrSize (mSemihostFsLabel);\r
+\r
+ if (*BufferSize >= ResultSize) {\r
+ StrCpy (Buffer, mSemihostFsLabel);\r
+ Status = EFI_SUCCESS;\r
+ } else {\r
+ Status = EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ *BufferSize = ResultSize;\r
+ } else {\r
+ Status = EFI_UNSUPPORTED;\r
}\r
- \r
+\r
return Status;\r
}\r
\r
IN VOID *Buffer\r
)\r
{\r
- return EFI_UNSUPPORTED;\r
+ EFI_STATUS Status;\r
+\r
+ if (Buffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_UNSUPPORTED;\r
+\r
+ if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid) != 0) {\r
+ //Status = SetFilesystemInfo (Fcb, BufferSize, Buffer);\r
+ } else if (CompareGuid (InformationType, &gEfiFileInfoGuid) != 0) {\r
+ //Status = SetFileInfo (Fcb, BufferSize, Buffer);\r
+ } else if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid) != 0) {\r
+ if (StrSize (Buffer) > 0) {\r
+ FreePool (mSemihostFsLabel);\r
+ mSemihostFsLabel = AllocateCopyPool (StrSize (Buffer), Buffer);\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return Status;\r
}\r
\r
EFI_STATUS\r
IN EFI_FILE *File\r
)\r
{\r
- return EFI_SUCCESS;\r
+ SEMIHOST_FCB *Fcb;\r
+\r
+ Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
+\r
+ if (Fcb->IsRoot) {\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ if (Fcb->Info.Attribute & EFI_FILE_READ_ONLY) {\r
+ return EFI_ACCESS_DENIED;\r
+ } else {\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
}\r
\r
EFI_STATUS\r
IN EFI_SYSTEM_TABLE *SystemTable\r
)\r
{\r
- EFI_STATUS Status = EFI_NOT_FOUND;\r
+ EFI_STATUS Status;\r
+\r
+ Status = EFI_NOT_FOUND;\r
\r
if (SemihostConnectionSupported ()) {\r
+ mSemihostFsLabel = AllocateCopyPool (StrSize (DEFAULT_SEMIHOST_FS_LABEL), DEFAULT_SEMIHOST_FS_LABEL);\r
+ if (mSemihostFsLabel == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
Status = gBS->InstallMultipleProtocolInterfaces (\r
&gInstallHandle, \r
&gEfiSimpleFileSystemProtocolGuid, &gSemihostFs, \r
&gEfiDevicePathProtocolGuid, &gDevicePath,\r
NULL\r
);\r
+\r
+ if (EFI_ERROR(Status)) {\r
+ FreePool (mSemihostFsLabel);\r
+ }\r
}\r
\r
return Status;\r
}\r
-\r