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 - 2014, ARM Ltd. All rights reserved.<BR>\r
+ Portions copyright (c) 2011 - 2021, Arm Limited. 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
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include <Guid/FileSystemVolumeLabelInfo.h>\r
\r
#include <Library/BaseLib.h>\r
-#include <Library/BaseMemoryLib.h> \r
+#include <Library/BaseMemoryLib.h>\r
#include <Library/DebugLib.h>\r
#include <Library/MemoryAllocationLib.h>\r
#include <Library/SemihostLib.h>\r
};\r
\r
//\r
-// Device path for SemiHosting. It contains our autogened Caller ID GUID.\r
+// Device path for semi-hosting. It contains our autogened Caller ID GUID.\r
//\r
typedef struct {\r
VENDOR_DEVICE_PATH Guid;\r
\r
SEMIHOST_DEVICE_PATH gDevicePath = {\r
{\r
- { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof (VENDOR_DEVICE_PATH), 0 },\r
+ { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, { sizeof (VENDOR_DEVICE_PATH), 0 } },\r
EFI_CALLER_ID_GUID\r
},\r
- { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, sizeof (EFI_DEVICE_PATH_PROTOCOL), 0}\r
+ { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 } }\r
};\r
\r
typedef struct {\r
)\r
{\r
SEMIHOST_FCB *RootFcb = NULL;\r
- \r
+\r
if (Root == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
if (RootFcb == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
- \r
+\r
RootFcb->IsRoot = TRUE;\r
RootFcb->Info.Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY;\r
\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ Open a file on the host system by means of the semihosting interface.\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 Only valid for EFI_FILE_MODE_CREATE, in which case these\r
+ are the attribute bits for the newly created file. The\r
+ mnemonics of the attribute bits are : EFI_FILE_READ_ONLY,\r
+ EFI_FILE_HIDDEN, EFI_FILE_SYSTEM, EFI_FILE_RESERVED,\r
+ EFI_FILE_DIRECTORY and EFI_FILE_ARCHIVE.\r
+\r
+ @retval EFI_SUCCESS The file was open.\r
+ @retval EFI_NOT_FOUND The specified file could not be found.\r
+ @retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed.\r
+ @retval EFI_WRITE_PROTECTED Attempt to create a directory. This is not possible\r
+ with the semi-hosting interface.\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
EFI_STATUS\r
FileOpen (\r
- IN EFI_FILE *File,\r
- OUT EFI_FILE **NewHandle,\r
- IN CHAR16 *FileName,\r
- IN UINT64 OpenMode,\r
- IN UINT64 Attributes\r
+ IN EFI_FILE *This,\r
+ OUT EFI_FILE **NewHandle,\r
+ IN CHAR16 *FileName,\r
+ IN UINT64 OpenMode,\r
+ IN UINT64 Attributes\r
)\r
{\r
- SEMIHOST_FCB *FileFcb = NULL;\r
- EFI_STATUS Status = EFI_SUCCESS;\r
- UINTN SemihostHandle;\r
- CHAR8 *AsciiFileName;\r
- UINT32 SemihostMode;\r
- BOOLEAN IsRoot;\r
- UINTN Length;\r
+ SEMIHOST_FCB *FileFcb;\r
+ RETURN_STATUS Return;\r
+ EFI_STATUS Status;\r
+ UINTN SemihostHandle;\r
+ CHAR8 *AsciiFileName;\r
+ UINT32 SemihostMode;\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
+ 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
+ if (((OpenMode & EFI_FILE_MODE_CREATE) != 0) &&\r
+ ((Attributes & EFI_FILE_DIRECTORY) != 0)) {\r
+ return EFI_WRITE_PROTECTED;\r
}\r
\r
- // Semihost interface requires ASCII filenames\r
- AsciiFileName = AllocatePool ((StrLen (FileName) + 1) * sizeof (CHAR8));\r
+ Length = StrLen (FileName) + 1;\r
+ AsciiFileName = AllocatePool (Length);\r
if (AsciiFileName == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
- UnicodeStrToAsciiStr (FileName, AsciiFileName);\r
+ UnicodeStrToAsciiStrS (FileName, AsciiFileName, Length);\r
\r
+ // Opening '/', '\', '.', or the NULL pathname is trying to open the root directory\r
if ((AsciiStrCmp (AsciiFileName, "\\") == 0) ||\r
(AsciiStrCmp (AsciiFileName, "/") == 0) ||\r
(AsciiStrCmp (AsciiFileName, "") == 0) ||\r
- (AsciiStrCmp (AsciiFileName, ".") == 0)) {\r
- // Opening '/', '\', '.', or the NULL pathname is trying to open the root directory\r
- IsRoot = TRUE;\r
-\r
- // Root directory node doesn't have a name.\r
+ (AsciiStrCmp (AsciiFileName, ".") == 0) ) {\r
FreePool (AsciiFileName);\r
- AsciiFileName = NULL;\r
+ return (VolumeOpen (&gSemihostFs, NewHandle));\r
+ }\r
+\r
+ //\r
+ // No control is done here concerning the file path. It is passed\r
+ // as it is to the host operating system through the semi-hosting\r
+ // interface. We first try to open the file in the read or update\r
+ // mode even if the file creation has been asked for. That way, if\r
+ // the file already exists, it is not truncated to zero length. In\r
+ // write mode (bit SEMIHOST_FILE_MODE_WRITE up), if the file already\r
+ // exists, it is reset to an empty file.\r
+ //\r
+ if (OpenMode == EFI_FILE_MODE_READ) {\r
+ SemihostMode = SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY;\r
} else {\r
- // Translate EFI_FILE_MODE into Semihosting mode\r
- if (OpenMode & EFI_FILE_MODE_WRITE) {\r
- SemihostMode = SEMIHOST_FILE_MODE_WRITE | SEMIHOST_FILE_MODE_BINARY;\r
- } else if (OpenMode & EFI_FILE_MODE_READ) {\r
- SemihostMode = SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY;\r
+ SemihostMode = SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY | SEMIHOST_FILE_MODE_UPDATE;\r
+ }\r
+ Return = SemihostFileOpen (AsciiFileName, SemihostMode, &SemihostHandle);\r
+\r
+ if (RETURN_ERROR (Return)) {\r
+ if ((OpenMode & EFI_FILE_MODE_CREATE) != 0) {\r
+ //\r
+ // In the create if does not exist case, if the opening in update\r
+ // mode failed, create it and open it in update mode. The update\r
+ // mode allows for both read and write from and to the file.\r
+ //\r
+ Return = SemihostFileOpen (\r
+ AsciiFileName,\r
+ SEMIHOST_FILE_MODE_WRITE | SEMIHOST_FILE_MODE_BINARY | SEMIHOST_FILE_MODE_UPDATE,\r
+ &SemihostHandle\r
+ );\r
+ if (RETURN_ERROR (Return)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Error;\r
+ }\r
} else {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- // Add the creation flag if necessary\r
- if (OpenMode & EFI_FILE_MODE_CREATE) {\r
- SemihostMode |= SEMIHOST_FILE_MODE_CREATE;\r
- }\r
-\r
- // Call the semihosting interface to open the file.\r
- Status = SemihostFileOpen (AsciiFileName, SemihostMode, &SemihostHandle);\r
- if (EFI_ERROR(Status)) {\r
- return Status;\r
+ Status = EFI_NOT_FOUND;\r
+ goto Error;\r
}\r
- \r
- IsRoot = FALSE;\r
}\r
\r
// Allocate a control block and fill it\r
FileFcb = AllocateFCB ();\r
if (FileFcb == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Error;\r
}\r
\r
FileFcb->FileName = AsciiFileName;\r
FileFcb->SemihostHandle = SemihostHandle;\r
FileFcb->Position = 0;\r
- FileFcb->IsRoot = IsRoot;\r
+ FileFcb->IsRoot = 0;\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
+ Return = SemihostFileLength (SemihostHandle, &Length);\r
+ if (RETURN_ERROR (Return)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ FreeFCB (FileFcb);\r
+ goto Error;\r
}\r
\r
+ FileFcb->Info.FileSize = Length;\r
+ FileFcb->Info.PhysicalSize = Length;\r
+ FileFcb->Info.Attribute = ((OpenMode & EFI_FILE_MODE_CREATE) != 0) ?\r
+ Attributes : 0;\r
+\r
InsertTailList (&gFileList, &FileFcb->Link);\r
\r
*NewHandle = &FileFcb->File;\r
\r
+ return EFI_SUCCESS;\r
+\r
+Error:\r
+\r
+ FreePool (AsciiFileName);\r
+\r
return Status;\r
}\r
\r
+/**\r
+ Worker function that truncate a file specified by its name to a given size.\r
+\r
+ @param[in] FileName The Null-terminated string of the name of the file to be opened.\r
+ @param[in] Size The target size for the file.\r
+\r
+ @retval EFI_SUCCESS The file was truncated.\r
+ @retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+TruncateFile (\r
+ IN CHAR8 *FileName,\r
+ IN UINTN Size\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ RETURN_STATUS Return;\r
+ UINTN FileHandle;\r
+ UINT8 *Buffer;\r
+ UINTN Remaining;\r
+ UINTN Read;\r
+ UINTN ToRead;\r
+\r
+ Status = EFI_DEVICE_ERROR;\r
+ FileHandle = 0;\r
+ Buffer = NULL;\r
+\r
+ Return = SemihostFileOpen (\r
+ FileName,\r
+ SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY,\r
+ &FileHandle\r
+ );\r
+ if (RETURN_ERROR (Return)) {\r
+ goto Error;\r
+ }\r
+\r
+ Buffer = AllocatePool (Size);\r
+ if (Buffer == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Error;\r
+ }\r
+\r
+ Read = 0;\r
+ Remaining = Size;\r
+ while (Remaining > 0) {\r
+ ToRead = Remaining;\r
+ Return = SemihostFileRead (FileHandle, &ToRead, Buffer + Read);\r
+ if (RETURN_ERROR (Return)) {\r
+ goto Error;\r
+ }\r
+ Remaining -= ToRead;\r
+ Read += ToRead;\r
+ }\r
+\r
+ Return = SemihostFileClose (FileHandle);\r
+ FileHandle = 0;\r
+ if (RETURN_ERROR (Return)) {\r
+ goto Error;\r
+ }\r
+\r
+ Return = SemihostFileOpen (\r
+ FileName,\r
+ SEMIHOST_FILE_MODE_WRITE | SEMIHOST_FILE_MODE_BINARY,\r
+ &FileHandle\r
+ );\r
+ if (RETURN_ERROR (Return)) {\r
+ goto Error;\r
+ }\r
+\r
+ if (Size > 0) {\r
+ Return = SemihostFileWrite (FileHandle, &Size, Buffer);\r
+ if (RETURN_ERROR (Return)) {\r
+ goto Error;\r
+ }\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+Error:\r
+\r
+ if (FileHandle != 0) {\r
+ SemihostFileClose (FileHandle);\r
+ }\r
+ if (Buffer != NULL) {\r
+ FreePool (Buffer);\r
+ }\r
+\r
+ return (Status);\r
+\r
+}\r
+\r
+/**\r
+ Close a specified file handle.\r
+\r
+ @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the file\r
+ handle to close.\r
+\r
+ @retval EFI_SUCCESS The file was closed.\r
+ @retval EFI_INVALID_PARAMETER The parameter "This" is NULL.\r
\r
+**/\r
EFI_STATUS\r
FileClose (\r
- IN EFI_FILE *File\r
+ IN EFI_FILE *This\r
)\r
{\r
- SEMIHOST_FCB *Fcb = NULL;\r
- EFI_STATUS Status = EFI_SUCCESS;\r
+ SEMIHOST_FCB *Fcb;\r
\r
- Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
\r
- if (Fcb->IsRoot == TRUE) {\r
- FreeFCB (Fcb);\r
- Status = EFI_SUCCESS;\r
- } else {\r
- Status = SemihostFileClose (Fcb->SemihostHandle);\r
- if (!EFI_ERROR(Status)) {\r
- FreePool (Fcb->FileName);\r
- FreeFCB (Fcb);\r
+ Fcb = SEMIHOST_FCB_FROM_THIS(This);\r
+\r
+ if (!Fcb->IsRoot) {\r
+ SemihostFileClose (Fcb->SemihostHandle);\r
+ //\r
+ // The file size might have been reduced from its actual\r
+ // size on the host file system with FileSetInfo(). In\r
+ // that case, the file has to be truncated.\r
+ //\r
+ if (Fcb->Info.FileSize < Fcb->Info.PhysicalSize) {\r
+ TruncateFile (Fcb->FileName, Fcb->Info.FileSize);\r
}\r
+ FreePool (Fcb->FileName);\r
}\r
- \r
- return Status;\r
+\r
+ FreeFCB (Fcb);\r
+\r
+ return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ Close and delete a file.\r
+\r
+ @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the file\r
+ handle to delete.\r
+\r
+ @retval EFI_SUCCESS The file was closed and deleted.\r
+ @retval EFI_WARN_DELETE_FAILURE The handle was closed, but the file was not deleted.\r
+ @retval EFI_INVALID_PARAMETER The parameter "This" is NULL.\r
+\r
+**/\r
EFI_STATUS\r
FileDelete (\r
- IN EFI_FILE *File\r
+ IN EFI_FILE *This\r
)\r
{\r
- SEMIHOST_FCB *Fcb = NULL;\r
- EFI_STATUS Status;\r
- CHAR8 *FileName;\r
- UINTN NameSize;\r
+ SEMIHOST_FCB *Fcb;\r
+ RETURN_STATUS Return;\r
+ CHAR8 *FileName;\r
+ UINTN NameSize;\r
\r
- Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Fcb = SEMIHOST_FCB_FROM_THIS (This);\r
\r
if (!Fcb->IsRoot) {\r
// Get the filename from the Fcb\r
NameSize = AsciiStrLen (Fcb->FileName);\r
FileName = AllocatePool (NameSize + 1);\r
\r
- AsciiStrCpy (FileName, Fcb->FileName);\r
+ AsciiStrCpyS (FileName, NameSize + 1, Fcb->FileName);\r
\r
// Close the file if it's open. Disregard return status,\r
// since it might give an error if the file isn't open.\r
- File->Close (File);\r
+ This->Close (This);\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
+ Return = SemihostFileRemove (FileName);\r
+ if (RETURN_ERROR (Return)) {\r
+ return EFI_WARN_DELETE_FAILURE;\r
}\r
+ return EFI_SUCCESS;\r
} else {\r
- Status = EFI_WARN_DELETE_FAILURE;\r
+ return EFI_WARN_DELETE_FAILURE;\r
}\r
-\r
- return Status;\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 semi-hosting\r
+ interface reported an error while performing the\r
+ read operation.\r
+ @retval EFI_INVALID_PARAMETER At least one of the three input pointers is NULL.\r
+\r
+**/\r
EFI_STATUS\r
FileRead (\r
- IN EFI_FILE *File,\r
- IN OUT UINTN *BufferSize,\r
- OUT VOID *Buffer\r
+ IN EFI_FILE *This,\r
+ IN OUT UINTN *BufferSize,\r
+ OUT VOID *Buffer\r
)\r
{\r
- SEMIHOST_FCB *Fcb = NULL;\r
- EFI_STATUS Status;\r
+ SEMIHOST_FCB *Fcb;\r
+ EFI_STATUS Status;\r
+ RETURN_STATUS Return;\r
\r
- Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
+ if ((This == NULL) || (BufferSize == NULL) || (Buffer == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Fcb = SEMIHOST_FCB_FROM_THIS (This);\r
\r
- if (Fcb->IsRoot == TRUE) {\r
- // By design, the Semihosting feature does not allow to list files on the host machine.\r
+ if (Fcb->IsRoot) {\r
+ // The semi-hosting interface does not allow to list files on the host machine.\r
Status = EFI_UNSUPPORTED;\r
} else {\r
- Status = SemihostFileRead (Fcb->SemihostHandle, BufferSize, Buffer);\r
- if (!EFI_ERROR (Status)) {\r
- Fcb->Position += *BufferSize;\r
+ Status = EFI_SUCCESS;\r
+ if (Fcb->Position >= Fcb->Info.FileSize) {\r
+ *BufferSize = 0;\r
+ if (Fcb->Position > Fcb->Info.FileSize) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ }\r
+ } else {\r
+ Return = SemihostFileRead (Fcb->SemihostHandle, BufferSize, Buffer);\r
+ if (RETURN_ERROR (Return)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ } else {\r
+ Fcb->Position += *BufferSize;\r
+ }\r
}\r
}\r
\r
return Status;\r
}\r
\r
+/**\r
+ Worker function that extends the size of an open file.\r
+\r
+ The extension is filled with zeros.\r
+\r
+ @param[in] Fcb Internal description of the opened file\r
+ @param[in] Size The number of bytes, the file has to be extended.\r
+\r
+ @retval EFI_SUCCESS The file was extended.\r
+ @retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ExtendFile (\r
+ IN SEMIHOST_FCB *Fcb,\r
+ IN UINTN Size\r
+ )\r
+{\r
+ RETURN_STATUS Return;\r
+ UINTN Remaining;\r
+ CHAR8 WriteBuffer[128];\r
+ UINTN WriteNb;\r
+ UINTN WriteSize;\r
+\r
+ Return = SemihostFileSeek (Fcb->SemihostHandle, Fcb->Info.FileSize);\r
+ if (RETURN_ERROR (Return)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ Remaining = Size;\r
+ SetMem (WriteBuffer, 0, sizeof(WriteBuffer));\r
+ while (Remaining > 0) {\r
+ WriteNb = MIN (Remaining, sizeof(WriteBuffer));\r
+ WriteSize = WriteNb;\r
+ Return = SemihostFileWrite (Fcb->SemihostHandle, &WriteSize, WriteBuffer);\r
+ if (RETURN_ERROR (Return)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ Remaining -= WriteNb;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Write data to an open file.\r
+\r
+ @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that\r
+ is the file handle to write data to.\r
+ @param[in out] BufferSize On input, the size of the Buffer. On output, the\r
+ size of the data actually written. In both cases,\r
+ the size is measured in bytes.\r
+ @param[in] Buffer The buffer of data to write.\r
+\r
+ @retval EFI_SUCCESS The data was written.\r
+ @retval EFI_ACCESS_DENIED Attempt to write into a read only file or\r
+ in a file opened in read only mode.\r
+ @retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed.\r
+ @retval EFI_INVALID_PARAMETER At least one of the three input pointers is NULL.\r
+\r
+**/\r
EFI_STATUS\r
FileWrite (\r
- IN EFI_FILE *File,\r
+ IN EFI_FILE *This,\r
IN OUT UINTN *BufferSize,\r
IN VOID *Buffer\r
)\r
{\r
- SEMIHOST_FCB *Fcb = NULL;\r
- EFI_STATUS Status;\r
- UINTN WriteSize = *BufferSize;\r
+ SEMIHOST_FCB *Fcb;\r
+ EFI_STATUS Status;\r
+ UINTN WriteSize;\r
+ RETURN_STATUS Return;\r
+ UINTN Length;\r
\r
- Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
+ if ((This == NULL) || (BufferSize == NULL) || (Buffer == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Fcb = SEMIHOST_FCB_FROM_THIS (This);\r
\r
// We cannot write a read-only file\r
if ((Fcb->Info.Attribute & EFI_FILE_READ_ONLY)\r
return EFI_ACCESS_DENIED;\r
}\r
\r
- Status = SemihostFileWrite (Fcb->SemihostHandle, &WriteSize, Buffer);\r
+ //\r
+ // If the position has been set past the end of the file, first grow the\r
+ // file from its current size "Fcb->Info.FileSize" to "Fcb->Position"\r
+ // size, filling the gap with zeros.\r
+ //\r
+ if (Fcb->Position > Fcb->Info.FileSize) {\r
+ Status = ExtendFile (Fcb, Fcb->Position - Fcb->Info.FileSize);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Fcb->Info.FileSize = Fcb->Position;\r
+ }\r
\r
- if (!EFI_ERROR(Status)) {\r
- // Semihost write return the number of bytes *NOT* written.\r
- *BufferSize -= WriteSize;\r
- Fcb->Position += *BufferSize;\r
+ WriteSize = *BufferSize;\r
+ Return = SemihostFileWrite (Fcb->SemihostHandle, &WriteSize, Buffer);\r
+ if (RETURN_ERROR (Return)) {\r
+ return EFI_DEVICE_ERROR;\r
}\r
- \r
- return Status;\r
+\r
+ Fcb->Position += *BufferSize;\r
+ if (Fcb->Position > Fcb->Info.FileSize) {\r
+ Fcb->Info.FileSize = Fcb->Position;\r
+ }\r
+\r
+ Return = SemihostFileLength (Fcb->SemihostHandle, &Length);\r
+ if (RETURN_ERROR (Return)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ Fcb->Info.PhysicalSize = Length;\r
+\r
+ return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ Return a file's current position.\r
+\r
+ @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is\r
+ the file handle to get the current position on.\r
+ @param[out] Position The address to return the file's current position value.\r
+\r
+ @retval EFI_SUCCESS The position was returned.\r
+ @retval EFI_INVALID_PARAMETER The parameter "This" or "Position" is NULL.\r
+\r
+**/\r
EFI_STATUS\r
FileGetPosition (\r
- IN EFI_FILE *File,\r
+ IN EFI_FILE *This,\r
OUT UINT64 *Position\r
)\r
{\r
- SEMIHOST_FCB *Fcb = NULL;\r
- \r
- if (Position == NULL) {\r
+ SEMIHOST_FCB *Fcb;\r
+\r
+ if ((This == NULL) || (Position == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
+ Fcb = SEMIHOST_FCB_FROM_THIS(This);\r
\r
*Position = Fcb->Position;\r
\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ Set a file's current position.\r
+\r
+ @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is\r
+ the file handle to set the requested position on.\r
+ @param[in] Position The byte position from the start of the file to set.\r
+\r
+ @retval EFI_SUCCESS The position was set.\r
+ @retval EFI_DEVICE_ERROR The semi-hosting positioning operation failed.\r
+ @retval EFI_UNSUPPORTED The seek request for nonzero is not valid on open\r
+ directories.\r
+ @retval EFI_INVALID_PARAMETER The parameter "This" is NULL.\r
+\r
+**/\r
EFI_STATUS\r
FileSetPosition (\r
- IN EFI_FILE *File,\r
+ IN EFI_FILE *This,\r
IN UINT64 Position\r
)\r
{\r
- SEMIHOST_FCB *Fcb = NULL;\r
- UINTN Length;\r
- EFI_STATUS Status;\r
+ SEMIHOST_FCB *Fcb;\r
+ RETURN_STATUS Return;\r
\r
- Fcb = SEMIHOST_FCB_FROM_THIS(File);\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
\r
- if (!Fcb->IsRoot) {\r
- Status = SemihostFileLength (Fcb->SemihostHandle, &Length);\r
- if (!EFI_ERROR(Status) && (Length < Position)) {\r
- Position = Length;\r
- }\r
+ Fcb = SEMIHOST_FCB_FROM_THIS (This);\r
\r
- Status = SemihostFileSeek (Fcb->SemihostHandle, (UINT32)Position);\r
- if (!EFI_ERROR(Status)) {\r
- Fcb->Position = Position;\r
+ if (Fcb->IsRoot) {\r
+ if (Position != 0) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+ else {\r
+ //\r
+ // UEFI Spec section 12.5:\r
+ // "Seeking to position 0xFFFFFFFFFFFFFFFF causes the current position to\r
+ // be set to the end of the file."\r
+ //\r
+ if (Position == 0xFFFFFFFFFFFFFFFF) {\r
+ Position = Fcb->Info.FileSize;\r
+ }\r
+ Return = SemihostFileSeek (Fcb->SemihostHandle, MIN (Position, Fcb->Info.FileSize));\r
+ if (RETURN_ERROR (Return)) {\r
+ return EFI_DEVICE_ERROR;\r
}\r
- } else {\r
- Fcb->Position = Position;\r
- Status = EFI_SUCCESS;\r
}\r
\r
- return Status;\r
+ Fcb->Position = Position;\r
+\r
+ return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ Return information about a file.\r
+\r
+ @param[in] Fcb A pointer to the description of an open file.\r
+ @param[in out] BufferSize The size, in bytes, of Buffer.\r
+ @param[out] Buffer A pointer to the data buffer to return. Not NULL if\r
+ "*BufferSize" is greater than 0.\r
+\r
+ @retval EFI_SUCCESS The information was returned.\r
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to return the information.\r
+ BufferSize has been updated with the size needed to\r
+ complete the request.\r
+**/\r
STATIC\r
EFI_STATUS\r
GetFileInfo (\r
IN SEMIHOST_FCB *Fcb,\r
- IN OUT UINTN *BufferSize,\r
- OUT VOID *Buffer\r
+ IN OUT UINTN *BufferSize,\r
+ OUT VOID *Buffer\r
)\r
{\r
EFI_FILE_INFO *Info = NULL;\r
UINTN ResultSize;\r
UINTN Index;\r
\r
- if (Fcb->IsRoot == TRUE) {\r
+ if (Fcb->IsRoot) {\r
ResultSize = SIZE_OF_EFI_FILE_INFO + sizeof(CHAR16);\r
} else {\r
NameSize = AsciiStrLen (Fcb->FileName) + 1;\r
// Fill in the structure\r
Info->Size = ResultSize;\r
\r
- if (Fcb->IsRoot == TRUE) {\r
+ if (Fcb->IsRoot) {\r
Info->FileName[0] = L'\0';\r
} else {\r
for (Index = 0; Index < NameSize; Index++) {\r
- Info->FileName[Index] = Fcb->FileName[Index]; \r
+ Info->FileName[Index] = Fcb->FileName[Index];\r
}\r
}\r
\r
- *BufferSize = ResultSize; \r
+ *BufferSize = ResultSize;\r
\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ Return information about a file system.\r
+\r
+ @param[in] Fcb A pointer to the description of an open file\r
+ which belongs to the file system, the information\r
+ is requested for.\r
+ @param[in out] BufferSize The size, in bytes, of Buffer.\r
+ @param[out] Buffer A pointer to the data buffer to return. Not NULL if\r
+ "*BufferSize" is greater than 0.\r
+\r
+ @retval EFI_SUCCESS The information was returned.\r
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to return the information.\r
+ BufferSize has been updated with the size needed to\r
+ complete the request.\r
+\r
+**/\r
STATIC\r
EFI_STATUS\r
GetFilesystemInfo (\r
OUT VOID *Buffer\r
)\r
{\r
- EFI_FILE_SYSTEM_INFO *Info = NULL;\r
- EFI_STATUS Status;\r
- UINTN ResultSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (mSemihostFsLabel);\r
- \r
+ EFI_FILE_SYSTEM_INFO *Info;\r
+ EFI_STATUS Status;\r
+ UINTN ResultSize;\r
+ UINTN StringSize;\r
+\r
+ StringSize = StrSize (mSemihostFsLabel);\r
+ ResultSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StringSize;\r
+\r
if (*BufferSize >= ResultSize) {\r
ZeroMem (Buffer, ResultSize);\r
Status = EFI_SUCCESS;\r
- \r
+\r
Info = Buffer;\r
\r
Info->Size = ResultSize;\r
Info->FreeSpace = 0;\r
Info->BlockSize = 0;\r
\r
- StrCpy (Info->VolumeLabel, mSemihostFsLabel);\r
+ CopyMem (Info->VolumeLabel, mSemihostFsLabel, StringSize);\r
} else {\r
Status = EFI_BUFFER_TOO_SMALL;\r
}\r
\r
- *BufferSize = ResultSize; \r
+ *BufferSize = ResultSize;\r
return Status;\r
}\r
\r
+/**\r
+ Return information about a file or a file system.\r
+\r
+ @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that\r
+ is the file handle the requested information is for.\r
+ @param[in] InformationType The type identifier for the information being requested :\r
+ EFI_FILE_INFO_ID or EFI_FILE_SYSTEM_INFO_ID or\r
+ EFI_FILE_SYSTEM_VOLUME_LABEL_ID\r
+ @param[in out] BufferSize The size, in bytes, of Buffer.\r
+ @param[out] Buffer A pointer to the data buffer to return. The type of the\r
+ data inside the buffer is indicated by InformationType.\r
+\r
+ @retval EFI_SUCCESS The information was returned.\r
+ @retval EFI_UNSUPPORTED The InformationType is not known.\r
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to return the information.\r
+ BufferSize has been updated with the size needed to\r
+ complete the request.\r
+ @retval EFI_INVALID_PARAMETER The parameter "This" or "InformationType" or "BufferSize"\r
+ is NULL or "Buffer" is NULL and "*Buffersize" is greater\r
+ than 0.\r
+\r
+**/\r
EFI_STATUS\r
FileGetInfo (\r
- IN EFI_FILE *File,\r
- IN EFI_GUID *InformationType,\r
- IN OUT UINTN *BufferSize,\r
- OUT VOID *Buffer\r
+ IN EFI_FILE *This,\r
+ IN EFI_GUID *InformationType,\r
+ IN OUT UINTN *BufferSize,\r
+ OUT VOID *Buffer\r
)\r
{\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
+\r
+ if ((This == NULL) ||\r
+ (InformationType == NULL) ||\r
+ (BufferSize == NULL) ||\r
+ ((Buffer == NULL) && (*BufferSize > 0)) ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Fcb = SEMIHOST_FCB_FROM_THIS(This);\r
+\r
+ if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {\r
Status = GetFilesystemInfo (Fcb, BufferSize, Buffer);\r
- } else if (CompareGuid (InformationType, &gEfiFileInfoGuid) != 0) {\r
+ } else if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {\r
Status = GetFileInfo (Fcb, BufferSize, Buffer);\r
- } else if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid) != 0) {\r
+ } else if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {\r
ResultSize = StrSize (mSemihostFsLabel);\r
\r
if (*BufferSize >= ResultSize) {\r
- StrCpy (Buffer, mSemihostFsLabel);\r
+ CopyMem (Buffer, mSemihostFsLabel, ResultSize);\r
Status = EFI_SUCCESS;\r
} else {\r
Status = EFI_BUFFER_TOO_SMALL;\r
return Status;\r
}\r
\r
+/**\r
+ Set information about a file.\r
+\r
+ @param[in] Fcb A pointer to the description of the open file.\r
+ @param[in] Info A pointer to the file information to write.\r
+\r
+ @retval EFI_SUCCESS The information was set.\r
+ @retval EFI_ACCESS_DENIED An attempt is made to change the name of a file\r
+ to a file that is already present.\r
+ @retval EFI_ACCESS_DENIED An attempt is being made to change the\r
+ EFI_FILE_DIRECTORY Attribute.\r
+ @retval EFI_ACCESS_DENIED The file is a read-only file or has been\r
+ opened in read-only mode and an attempt is\r
+ being made to modify a field other than\r
+ Attribute.\r
+ @retval EFI_WRITE_PROTECTED An attempt is being made to modify a\r
+ read-only attribute.\r
+ @retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed.\r
+ @retval EFI_OUT_OF_RESOURCES A allocation needed to process the request failed.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+SetFileInfo (\r
+ IN SEMIHOST_FCB *Fcb,\r
+ IN EFI_FILE_INFO *Info\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ RETURN_STATUS Return;\r
+ BOOLEAN FileSizeIsDifferent;\r
+ BOOLEAN FileNameIsDifferent;\r
+ BOOLEAN ReadOnlyIsDifferent;\r
+ CHAR8 *AsciiFileName;\r
+ UINTN FileSize;\r
+ UINTN Length;\r
+ UINTN SemihostHandle;\r
+\r
+ //\r
+ // A directory can not be changed to a file and a file can\r
+ // not be changed to a directory.\r
+ //\r
+ if (((Info->Attribute & EFI_FILE_DIRECTORY) != 0) != Fcb->IsRoot) {\r
+ return EFI_ACCESS_DENIED;\r
+ }\r
+\r
+ Length = StrLen (Info->FileName) + 1;\r
+ AsciiFileName = AllocatePool (Length);\r
+ if (AsciiFileName == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ UnicodeStrToAsciiStrS (Info->FileName, AsciiFileName, Length);\r
+\r
+ FileSizeIsDifferent = (Info->FileSize != Fcb->Info.FileSize);\r
+ FileNameIsDifferent = (AsciiStrCmp (AsciiFileName, Fcb->FileName) != 0);\r
+ ReadOnlyIsDifferent = CompareMem (\r
+ &Info->CreateTime,\r
+ &Fcb->Info.CreateTime,\r
+ 3 * sizeof (EFI_TIME)\r
+ ) != 0;\r
+\r
+ //\r
+ // For a read-only file or a file opened in read-only mode, only\r
+ // the Attribute field can be modified. As the root directory is\r
+ // read-only (i.e. VolumeOpen()), this protects the root directory\r
+ // description.\r
+ //\r
+ if ((Fcb->OpenMode == EFI_FILE_MODE_READ) ||\r
+ (Fcb->Info.Attribute & EFI_FILE_READ_ONLY) ) {\r
+ if (FileSizeIsDifferent || FileNameIsDifferent || ReadOnlyIsDifferent) {\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto Error;\r
+ }\r
+ }\r
+\r
+ if (ReadOnlyIsDifferent) {\r
+ Status = EFI_WRITE_PROTECTED;\r
+ goto Error;\r
+ }\r
+\r
+ Status = EFI_DEVICE_ERROR;\r
+\r
+ if (FileSizeIsDifferent) {\r
+ FileSize = Info->FileSize;\r
+ if (Fcb->Info.FileSize < FileSize) {\r
+ Status = ExtendFile (Fcb, FileSize - Fcb->Info.FileSize);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+ //\r
+ // The read/write position from the host file system point of view\r
+ // is at the end of the file. If the position from this module\r
+ // point of view is smaller than the new file size, then\r
+ // ask the host file system to move to that position.\r
+ //\r
+ if (Fcb->Position < FileSize) {\r
+ FileSetPosition (&Fcb->File, Fcb->Position);\r
+ }\r
+ }\r
+ Fcb->Info.FileSize = FileSize;\r
+\r
+ Return = SemihostFileLength (Fcb->SemihostHandle, &Length);\r
+ if (RETURN_ERROR (Return)) {\r
+ goto Error;\r
+ }\r
+ Fcb->Info.PhysicalSize = Length;\r
+ }\r
+\r
+ //\r
+ // Note down in RAM the Attribute field but we can not ask\r
+ // for its modification to the host file system as the\r
+ // semi-host interface does not provide this feature.\r
+ //\r
+ Fcb->Info.Attribute = Info->Attribute;\r
+\r
+ if (FileNameIsDifferent) {\r
+ Return = SemihostFileOpen (\r
+ AsciiFileName,\r
+ SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY,\r
+ &SemihostHandle\r
+ );\r
+ if (!RETURN_ERROR (Return)) {\r
+ SemihostFileClose (SemihostHandle);\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto Error;\r
+ }\r
+\r
+ Return = SemihostFileRename (Fcb->FileName, AsciiFileName);\r
+ if (RETURN_ERROR (Return)) {\r
+ goto Error;\r
+ }\r
+ FreePool (Fcb->FileName);\r
+ Fcb->FileName = AsciiFileName;\r
+ AsciiFileName = NULL;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+Error:\r
+ if (AsciiFileName != NULL) {\r
+ FreePool (AsciiFileName);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Set information about a file or a file system.\r
+\r
+ @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that\r
+ is the file handle the information is for.\r
+ @param[in] InformationType The type identifier for the information being set :\r
+ EFI_FILE_INFO_ID or EFI_FILE_SYSTEM_INFO_ID or\r
+ EFI_FILE_SYSTEM_VOLUME_LABEL_ID\r
+ @param[in] BufferSize The size, in bytes, of Buffer.\r
+ @param[in] Buffer A pointer to the data buffer to write. The type of the\r
+ data inside the buffer is indicated by InformationType.\r
+\r
+ @retval EFI_SUCCESS The information was set.\r
+ @retval EFI_UNSUPPORTED The InformationType is not known.\r
+ @retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed.\r
+ @retval EFI_ACCESS_DENIED An attempt is being made to change the\r
+ EFI_FILE_DIRECTORY Attribute.\r
+ @retval EFI_ACCESS_DENIED InformationType is EFI_FILE_INFO_ID and\r
+ the file is a read-only file or has been\r
+ opened in read-only mode and an attempt is\r
+ being made to modify a field other than\r
+ Attribute.\r
+ @retval EFI_ACCESS_DENIED An attempt is made to change the name of a file\r
+ to a file that is already present.\r
+ @retval EFI_WRITE_PROTECTED An attempt is being made to modify a\r
+ read-only attribute.\r
+ @retval EFI_BAD_BUFFER_SIZE The size of the buffer is lower than that indicated by\r
+ the data inside the buffer.\r
+ @retval EFI_OUT_OF_RESOURCES An allocation needed to process the request failed.\r
+ @retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.\r
+\r
+**/\r
EFI_STATUS\r
FileSetInfo (\r
- IN EFI_FILE *File,\r
- IN EFI_GUID *InformationType,\r
- IN UINTN BufferSize,\r
- IN VOID *Buffer\r
+ IN EFI_FILE *This,\r
+ IN EFI_GUID *InformationType,\r
+ IN UINTN BufferSize,\r
+ IN VOID *Buffer\r
)\r
{\r
- EFI_STATUS Status;\r
+ SEMIHOST_FCB *Fcb;\r
+ EFI_FILE_INFO *Info;\r
+ EFI_FILE_SYSTEM_INFO *SystemInfo;\r
+ CHAR16 *VolumeLabel;\r
\r
- if (Buffer == NULL) {\r
+ if ((This == NULL) || (InformationType == NULL) || (Buffer == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- Status = EFI_UNSUPPORTED;\r
+ Fcb = SEMIHOST_FCB_FROM_THIS (This);\r
+\r
+ if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {\r
+ Info = Buffer;\r
+ if (Info->Size < (SIZE_OF_EFI_FILE_INFO + StrSize (Info->FileName))) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (BufferSize < Info->Size) {\r
+ return EFI_BAD_BUFFER_SIZE;\r
+ }\r
+ return SetFileInfo (Fcb, Info);\r
+ } else if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {\r
+ SystemInfo = Buffer;\r
+ if (SystemInfo->Size <\r
+ (SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (SystemInfo->VolumeLabel))) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (BufferSize < SystemInfo->Size) {\r
+ return EFI_BAD_BUFFER_SIZE;\r
+ }\r
+ Buffer = SystemInfo->VolumeLabel;\r
\r
- if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid) != 0) {\r
- //Status = SetFilesystemInfo (Fcb, BufferSize, Buffer);\r
- } else if (CompareGuid (InformationType, &gEfiFileInfoGuid) != 0) {\r
- // Semihosting does not give us access to setting file info, but\r
- // if we fail here we cannot create new files.\r
- Status = EFI_SUCCESS;\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
+ VolumeLabel = AllocateCopyPool (StrSize (Buffer), Buffer);\r
+ if (VolumeLabel != NULL) {\r
+ FreePool (mSemihostFsLabel);\r
+ mSemihostFsLabel = VolumeLabel;\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ } else {\r
+ return EFI_INVALID_PARAMETER;\r
}\r
+ } else if (!CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {\r
+ return EFI_UNSUPPORTED;\r
+ } else {\r
+ return EFI_UNSUPPORTED;\r
}\r
-\r
- return Status;\r
}\r
\r
EFI_STATUS\r
}\r
\r
Status = gBS->InstallMultipleProtocolInterfaces (\r
- &gInstallHandle, \r
- &gEfiSimpleFileSystemProtocolGuid, &gSemihostFs, \r
+ &gInstallHandle,\r
+ &gEfiSimpleFileSystemProtocolGuid, &gSemihostFs,\r
&gEfiDevicePathProtocolGuid, &gDevicePath,\r
NULL\r
);\r
FreePool (mSemihostFsLabel);\r
}\r
}\r
- \r
+\r
return Status;\r
}\r