*\r
**/\r
\r
+#include <Library/PathLib.h>\r
#include "BootMonFsInternal.h"\r
\r
// Clear a file's image description on storage media:\r
}\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
}\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