]> git.proxmox.com Git - mirror_edk2.git/commitdiff
ArmPlatformPkg/BootMonFs: Fix error codes returned by Open() and Read()
authorRonald Cron <Ronald.Cron@arm.com>
Fri, 12 Dec 2014 19:03:30 +0000 (19:03 +0000)
committeroliviermartin <oliviermartin@Edk2>
Fri, 12 Dec 2014 19:03:30 +0000 (19:03 +0000)
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ronald Cron <Ronald.Cron@arm.com>
Reviewed-by: Olivier Martin <olivier.martin@arm.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16510 6f19259b-4bc3-4df7-8a09-765794883524

ArmPlatformPkg/ArmVExpressPkg/ArmVExpress.dsc.inc
ArmPlatformPkg/FileSystem/BootMonFs/BootMonFs.inf
ArmPlatformPkg/FileSystem/BootMonFs/BootMonFsApi.h
ArmPlatformPkg/FileSystem/BootMonFs/BootMonFsOpenClose.c
ArmPlatformPkg/FileSystem/BootMonFs/BootMonFsReadWrite.c

index f9af2a39e05a02d4df1f043f85289fed0fd12e39..ac17436ef26a5f257b88e1075b61361e135d4af6 100644 (file)
@@ -23,6 +23,7 @@
   DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf\r
 \r
   BaseLib|MdePkg/Library/BaseLib/BaseLib.inf\r
+  BasePathLib|MdeModulePkg/Library/BasePathLib/BasePathLib.inf\r
   SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf\r
   PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf\r
   PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf\r
index 94e8916e1bba0a34ed08c0a667d66db9164a2310..c7694621811a571f1414373c69ec6293be649aa4 100644 (file)
 [Packages]\r
   ArmPlatformPkg/ArmPlatformPkg.dec\r
   MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
 \r
 [LibraryClasses]\r
   BaseLib\r
+  BasePathLib\r
   DevicePathLib\r
   MemoryAllocationLib\r
   PrintLib\r
index 9c1daa523bd3c64aed214330c89d0ba1ef8ecece..affc510931f464603dde0a2bc775568e8215c9d9 100644 (file)
@@ -91,6 +91,28 @@ BootMonFsCloseFile (
   IN EFI_FILE_PROTOCOL  *This\r
   );\r
 \r
+/**\r
+  Open a file on the boot monitor file system.\r
+\r
+  @param[in]   This        The EFI_FILE_PROTOCOL parent handle.\r
+  @param[out]  NewHandle   A pointer to the location to return the opened\r
+                           handle for the new file.\r
+  @param[in]   FileName    The Null-terminated string of the name of the file\r
+                           to be opened.\r
+  @param[in]   OpenMode    The mode to open the file : Read or Read/Write or\r
+                           Read/Write/Create\r
+  @param[in]   Attributes  Attributes of the file in case of a file creation\r
+\r
+  @retval  EFI_SUCCESS            The file was open.\r
+  @retval  EFI_NOT_FOUND          The specified file could not be found or the specified\r
+                                  directory in which to create a file could not be found.\r
+  @retval  EFI_DEVICE_ERROR       The device reported an error.\r
+  @retval  EFI_WRITE_PROTECTED    Attempt to create a directory. This is not possible\r
+                                  with the BootMon file system.\r
+  @retval  EFI_OUT_OF_RESOURCES   Not enough resources were available to open the file.\r
+  @retval  EFI_INVALID_PARAMETER  At least one of the parameters is invalid.\r
+\r
+**/\r
 EFIAPI\r
 EFI_STATUS\r
 BootMonFsOpenFile (\r
@@ -101,7 +123,23 @@ BootMonFsOpenFile (
   IN UINT64             Attributes\r
   );\r
 \r
+/**\r
+  Read data from an open file.\r
 \r
+  @param[in]      This        A pointer to the EFI_FILE_PROTOCOL instance that\r
+                              is the file handle to read data from.\r
+  @param[in out]  BufferSize  On input, the size of the Buffer. On output, the\r
+                              amount of data returned in Buffer. In both cases,\r
+                              the size is measured in bytes.\r
+  @param[out]     Buffer      The buffer into which the data is read.\r
+\r
+  @retval  EFI_SUCCESS            The data was read.\r
+  @retval  EFI_DEVICE_ERROR       On entry, the current file position is\r
+                                  beyond the end of the file, or the device\r
+                                  reported an error while performing the read\r
+                                  operation.\r
+  @retval  EFI_INVALID_PARAMETER  At least one of the parameters is invalid.\r
+**/\r
 EFIAPI\r
 EFI_STATUS\r
 BootMonFsReadFile (\r
index 6616b4f694f550863a1f9040c14db536bc768dd2..45ac89026f966105816dc7aa5527320e5f558837 100644 (file)
@@ -12,6 +12,7 @@
 *\r
 **/\r
 \r
+#include <Library/PathLib.h>\r
 #include "BootMonFsInternal.h"\r
 \r
 // Clear a file's image description on storage media:\r
@@ -445,59 +446,78 @@ CreateNewFile (
 }\r
 \r
 /**\r
-  Opens a file on the Nor Flash FS volume\r
-\r
-  Calls BootMonFsGetFileFromAsciiFilename to search the list of tracked files.\r
-\r
-  @param  This  The EFI_FILE_PROTOCOL parent handle.\r
-  @param  NewHandle Double-pointer to the newly created protocol.\r
-  @param  FileName The name of the image/metadata on flash\r
-  @param  OpenMode Read,write,append etc\r
-  @param  Attributes ?\r
-\r
-  @return EFI_STATUS\r
-  OUT_OF_RESOURCES\r
-    Run out of space to keep track of the allocated structures\r
-  DEVICE_ERROR\r
-    Unable to locate the volume associated with the parent file handle\r
-  NOT_FOUND\r
-    Filename wasn't found on flash\r
-  SUCCESS\r
+  Open a file on the boot monitor file system.\r
+\r
+  The boot monitor file system does not allow for sub-directories. There is only\r
+  one directory, the root one. On any attempt to create a directory, the function\r
+  returns in error with the EFI_WRITE_PROTECTED error code.\r
+\r
+  @param[in]   This        A pointer to the EFI_FILE_PROTOCOL instance that is\r
+                           the file handle to source location.\r
+  @param[out]  NewHandle   A pointer to the location to return the opened\r
+                           handle for the new file.\r
+  @param[in]   FileName    The Null-terminated string of the name of the file\r
+                           to be opened.\r
+  @param[in]   OpenMode    The mode to open the file : Read or Read/Write or\r
+                           Read/Write/Create\r
+  @param[in]   Attributes  Attributes of the file in case of a file creation\r
+\r
+  @retval  EFI_SUCCESS            The file was open.\r
+  @retval  EFI_NOT_FOUND          The specified file could not be found or the specified\r
+                                  directory in which to create a file could not be found.\r
+  @retval  EFI_DEVICE_ERROR       The device reported an error.\r
+  @retval  EFI_WRITE_PROTECTED    Attempt to create a directory. This is not possible\r
+                                  with the Boot Monitor file system.\r
+  @retval  EFI_OUT_OF_RESOURCES   Not enough resources were available to open the file.\r
+  @retval  EFI_INVALID_PARAMETER  At least one of the parameters is invalid.\r
 \r
 **/\r
 EFIAPI\r
 EFI_STATUS\r
 BootMonFsOpenFile (\r
-  IN EFI_FILE_PROTOCOL  *This,\r
-  OUT EFI_FILE_PROTOCOL **NewHandle,\r
-  IN CHAR16             *FileName,\r
-  IN UINT64             OpenMode,\r
-  IN UINT64             Attributes\r
+  IN EFI_FILE_PROTOCOL   *This,\r
+  OUT EFI_FILE_PROTOCOL  **NewHandle,\r
+  IN CHAR16              *FileName,\r
+  IN UINT64              OpenMode,\r
+  IN UINT64              Attributes\r
   )\r
 {\r
-  BOOTMON_FS_FILE     *Directory;\r
-  BOOTMON_FS_FILE     *File;\r
-  BOOTMON_FS_INSTANCE *Instance;\r
-  CHAR8*               AsciiFileName;\r
   EFI_STATUS           Status;\r
+  BOOTMON_FS_FILE      *Directory;\r
+  BOOTMON_FS_FILE      *File;\r
+  BOOTMON_FS_INSTANCE  *Instance;\r
+  CHAR8                *Buf;\r
+  CHAR16               *Path;\r
+  CHAR16               *Separator;\r
+  CHAR8                *AsciiFileName;\r
+\r
+  if (This == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
 \r
   if ((FileName == NULL) || (NewHandle == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  //\r
   // The only valid modes are read, read/write, and read/write/create\r
-  if (!(OpenMode & EFI_FILE_MODE_READ) || ((OpenMode & EFI_FILE_MODE_CREATE)  && !(OpenMode & EFI_FILE_MODE_WRITE))) {\r
+  //\r
+  if ( (OpenMode != EFI_FILE_MODE_READ) &&\r
+       (OpenMode != (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE)) &&\r
+       (OpenMode != (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE)) ) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
   Directory = BOOTMON_FS_FILE_FROM_FILE_THIS (This);\r
   if (Directory == NULL) {\r
-    return EFI_DEVICE_ERROR;\r
+    return EFI_INVALID_PARAMETER;\r
   }\r
 \r
   Instance = Directory->Instance;\r
 \r
-  // If the instance has not been initialized it yet then do it ...\r
+  //\r
+  // If the instance has not been initialized yet then do it ...\r
+  //\r
   if (!Instance->Initialized) {\r
     Status = BootMonFsInitialize (Instance);\r
     if (EFI_ERROR (Status)) {\r
@@ -505,58 +525,137 @@ BootMonFsOpenFile (
     }\r
   }\r
 \r
+  //\r
+  // Copy the file path to be able to work on it. We do not want to\r
+  // modify the input file name string "FileName".\r
+  //\r
+  Buf = AllocateCopyPool (StrSize (FileName), FileName);\r
+  if (Buf == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  Path = (CHAR16*)Buf;\r
+  AsciiFileName = NULL;\r
+\r
+  //\r
+  // Handle single periods, double periods and convert forward slashes '/'\r
+  // to backward '\' ones. Does not handle a '.' at the beginning of the\r
+  // path for the time being.\r
+  //\r
+  if (PathCleanUpDirectories (Path) == NULL) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Error;\r
+  }\r
+\r
+  //\r
+  // Detect if the first component of the path refers to a directory.\r
+  // This is done to return the correct error code when trying to\r
+  // access or create a directory other than the root directory.\r
+  //\r
+\r
+  //\r
+  // Search for the '\\' sequence and if found return in error\r
+  // with the EFI_INVALID_PARAMETER error code. ere in the path.\r
+  //\r
+  if (StrStr (Path, L"\\\\") != NULL) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Error;\r
+  }\r
+  //\r
+  // Get rid of the leading '\' if any.\r
+  //\r
+  Path += (Path[0] == L'\\');\r
+\r
+  //\r
+  // Look for a '\' in the file path. If one is found then\r
+  // the first component of the path refers to a directory\r
+  // that is not the root directory.\r
+  //\r
+  Separator = StrStr (Path, L"\\");\r
+  if (Separator != NULL) {\r
+    //\r
+    // In the case '<dir name>\' and a creation, return\r
+    // EFI_WRITE_PROTECTED if this is for a directory\r
+    // creation, EFI_INVALID_PARAMETER otherwise.\r
+    //\r
+    if ((*(Separator + 1) == '\0') && ((OpenMode & EFI_FILE_MODE_CREATE) != 0)) {\r
+      if (Attributes & EFI_FILE_DIRECTORY) {\r
+        Status = EFI_WRITE_PROTECTED;\r
+      } else {\r
+        Status = EFI_INVALID_PARAMETER;\r
+      }\r
+    } else {\r
+      //\r
+      // Attempt to open a file or a directory that is not in the\r
+      // root directory or to open without creation a directory\r
+      // located in the root directory, returns EFI_NOT_FOUND.\r
+      //\r
+      Status = EFI_NOT_FOUND;\r
+    }\r
+    goto Error;\r
+  }\r
+\r
+  //\r
   // BootMonFs interface requires ASCII filenames\r
-  AsciiFileName = AllocatePool ((StrLen (FileName) + 1) * sizeof (CHAR8));\r
+  //\r
+  AsciiFileName = AllocatePool (StrLen (Path) + 1);\r
   if (AsciiFileName == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Error;\r
+  }\r
+  UnicodeStrToAsciiStr (Path, AsciiFileName);\r
+  if (AsciiStrSize (AsciiFileName) > MAX_NAME_LENGTH) {\r
+   AsciiFileName[MAX_NAME_LENGTH - 1] = '\0';\r
   }\r
-  UnicodeStrToAsciiStr (FileName, AsciiFileName);\r
 \r
-  if ((AsciiStrCmp (AsciiFileName, "\\") == 0) ||\r
-      (AsciiStrCmp (AsciiFileName, "/")  == 0) ||\r
-      (AsciiStrCmp (AsciiFileName, "")   == 0) ||\r
-      (AsciiStrCmp (AsciiFileName, ".")  == 0))\r
-  {\r
+  if ((AsciiFileName[0] == '\0') ||\r
+      (AsciiFileName[0] == '.' )    ) {\r
     //\r
-    // Opening '/', '\', '.', or the NULL pathname is trying to open the root directory\r
+    // Opening the root directory\r
     //\r
 \r
     *NewHandle = &Instance->RootFile->File;\r
     Instance->RootFile->Position = 0;\r
     Status = EFI_SUCCESS;\r
   } else {\r
+\r
+    if ((OpenMode & EFI_FILE_MODE_CREATE) &&\r
+        (Attributes & EFI_FILE_DIRECTORY)    ) {\r
+      Status = EFI_WRITE_PROTECTED;\r
+      goto Error;\r
+    }\r
+\r
     //\r
-    // Open or Create a regular file\r
+    // Open or create a file in the root directory.\r
     //\r
 \r
-    // Check if the file already exists\r
     Status = BootMonGetFileFromAsciiFileName (Instance, AsciiFileName, &File);\r
     if (Status == EFI_NOT_FOUND) {\r
-      // The file doesn't exist.\r
-      if (OpenMode & EFI_FILE_MODE_CREATE) {\r
-        // If the file does not exist but is required then create it.\r
-        if (Attributes & EFI_FILE_DIRECTORY) {\r
-          // BootMonFS doesn't support subdirectories\r
-          Status = EFI_UNSUPPORTED;\r
-        } else {\r
-          // Create a new file\r
-          Status = CreateNewFile (Instance, AsciiFileName, &File);\r
-          if (!EFI_ERROR (Status)) {\r
-            File->OpenMode = OpenMode;\r
-            *NewHandle = &File->File;\r
-            File->Position = 0;\r
-          }\r
-        }\r
+      if ((OpenMode & EFI_FILE_MODE_CREATE) == 0) {\r
+        goto Error;\r
       }\r
-    } else if (Status == EFI_SUCCESS) {\r
-      // The file exists\r
+\r
+      Status = CreateNewFile (Instance, AsciiFileName, &File);\r
+      if (!EFI_ERROR (Status)) {\r
+        File->OpenMode = OpenMode;\r
+        *NewHandle = &File->File;\r
+        File->Position = 0;\r
+      }\r
+    } else {\r
+      //\r
+      // The file already exists.\r
+      //\r
       File->OpenMode = OpenMode;\r
       *NewHandle = &File->File;\r
       File->Position = 0;\r
     }\r
   }\r
 \r
-  FreePool (AsciiFileName);\r
+Error:\r
+\r
+  FreePool (Buf);\r
+  if (AsciiFileName != NULL) {\r
+    FreePool (AsciiFileName);\r
+  }\r
 \r
   return Status;\r
 }\r
index 653b2c507c7e5d1f02a81f6926188d3d167e72bd..358332d6582f2bbe3f9fbdf8abda95ed68c024c3 100644 (file)
 \r
 #include "BootMonFsInternal.h"\r
 \r
+/**\r
+  Read data from an open file.\r
+\r
+  @param[in]      This        A pointer to the EFI_FILE_PROTOCOL instance that\r
+                              is the file handle to read data from.\r
+  @param[in out]  BufferSize  On input, the size of the Buffer. On output, the\r
+                              amount of data returned in Buffer. In both cases,\r
+                              the size is measured in bytes.\r
+  @param[out]     Buffer      The buffer into which the data is read.\r
+\r
+  @retval  EFI_SUCCESS            The data was read.\r
+  @retval  EFI_DEVICE_ERROR       On entry, the current file position is\r
+                                  beyond the end of the file, or the device\r
+                                  reported an error while performing the read\r
+                                  operation.\r
+  @retval  EFI_INVALID_PARAMETER  At least one of the parameters is invalid.\r
+**/\r
 EFIAPI\r
 EFI_STATUS\r
 BootMonFsReadFile (\r
@@ -51,9 +68,14 @@ BootMonFsReadFile (
   FileStart = (Media->LowestAlignedLba + File->HwDescription.BlockStart) * Media->BlockSize;\r
 \r
   if (File->Position >= File->HwDescription.Region[0].Size) {\r
-    // The entire file has been read\r
+    // The entire file has been read or the position has been\r
+    // set past the end of the file.\r
     *BufferSize = 0;\r
-    return EFI_DEVICE_ERROR;\r
+    if (File->Position > File->HwDescription.Region[0].Size) {\r
+      return EFI_DEVICE_ERROR;\r
+    } else {\r
+      return EFI_SUCCESS;\r
+    }\r
   }\r
 \r
   // This driver assumes that the entire file is in region 0.\r