]> git.proxmox.com Git - mirror_edk2.git/commitdiff
ArmPkg/SemihostFs: Make the driver more compliant with the UEFI specification
authoroliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524>
Sun, 14 Apr 2013 09:24:44 +0000 (09:24 +0000)
committeroliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524>
Sun, 14 Apr 2013 09:24:44 +0000 (09:24 +0000)
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

ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.c

index b04e866a995f405f131961b86bb8e6e8a9fcd803..5f1159d81a74060d10faae0a430d4aae06b2a4ed 100644 (file)
@@ -2,7 +2,7 @@
   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
@@ -18,6 +18,7 @@
 \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
@@ -32,6 +33,9 @@
 \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
@@ -69,13 +73,15 @@ SEMIHOST_DEVICE_PATH gDevicePath = {
 };\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
@@ -134,6 +140,7 @@ VolumeOpen (
   }\r
   \r
   RootFcb->IsRoot = TRUE;\r
+  RootFcb->Info.Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY;\r
 \r
   InsertTailList (&gFileList, &RootFcb->Link);\r
 \r
@@ -157,11 +164,17 @@ FileOpen (
   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
@@ -213,6 +226,18 @@ FileOpen (
   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
@@ -271,8 +296,11 @@ FileDelete (
 \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
@@ -316,6 +344,11 @@ FileWrite (
 \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
@@ -388,8 +421,6 @@ GetFileInfo (
   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
@@ -405,30 +436,20 @@ GetFileInfo (
 \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
@@ -444,10 +465,9 @@ GetFilesystemInfo (
 {\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
@@ -459,7 +479,7 @@ GetFilesystemInfo (
     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
@@ -476,17 +496,31 @@ FileGetInfo (
   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
@@ -498,7 +532,27 @@ FileSetInfo (
   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
@@ -506,7 +560,19 @@ FileFlush (
   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
@@ -515,17 +581,27 @@ SemihostFsEntryPoint (
   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