#include <Library/DebugLib.h>\r
#include <Library/MemoryAllocationLib.h>\r
#include <Library/DevicePathLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/FileHandleLib.h>\r
#include <Protocol/EfiShellEnvironment2.h>\r
#include <Protocol/EfiShellInterface.h>\r
#include <Protocol/EfiShell.h>\r
#include <Protocol/EfiShellParameters.h>\r
#include <Protocol/SimpleFileSystem.h>\r
\r
+#include "BaseShellLib.h"\r
+\r
#define MAX_FILE_NAME_LEN 522 // (20 * (6+5+2))+1) unicode characters from EFI FAT spec (doubled for bytes)\r
#define FIND_XXXXX_FILE_BUFFER_SIZE (SIZE_OF_EFI_FILE_INFO + MAX_FILE_NAME_LEN)\r
\r
-EFI_SHELL_ENVIRONMENT2 *mEfiShellEnvironment2;\r
-EFI_SHELL_INTERFACE *mEfiShellInterface;\r
-EFI_SHELL_PROTOCOL *mEfiShellProtocol;\r
-EFI_SHELL_PARAMETERS_PROTOCOL *mEfiShellParametersProtocol;\r
-EFI_HANDLE mEfiShellEnvironment2Handle;\r
-EFI_LIST_ENTRY *mOldStyleFileList;\r
+//\r
+// This is not static since it's extern in the .h file\r
+//\r
+SHELL_PARAM_ITEM EmptyParamList[] = {\r
+ {NULL, TypeMax}\r
+ };\r
+\r
+//\r
+// Static file globals for the shell library\r
+//\r
+STATIC EFI_SHELL_ENVIRONMENT2 *mEfiShellEnvironment2;\r
+STATIC EFI_SHELL_INTERFACE *mEfiShellInterface;\r
+STATIC EFI_SHELL_PROTOCOL *mEfiShellProtocol;\r
+STATIC EFI_SHELL_PARAMETERS_PROTOCOL *mEfiShellParametersProtocol;\r
+STATIC EFI_HANDLE mEfiShellEnvironment2Handle;\r
+STATIC FILE_HANDLE_FUNCTION_MAP FileFunctionMap;\r
\r
/**\r
helper function to find ShellEnvironment2 for constructor\r
return (Status);\r
}\r
\r
-/**\r
- Constructor for the Shell library.\r
-\r
- Initialize the library and determine if the underlying is a UEFI Shell 2.0 or an EFI shell.\r
-\r
- @param ImageHandle the image handle of the process\r
- @param SystemTable the EFI System Table pointer\r
-\r
- @retval EFI_SUCCESS the initialization was complete sucessfully\r
- @return others an error ocurred during initialization\r
-**/\r
EFI_STATUS\r
EFIAPI\r
-ShellLibConstructor (\r
+ShellLibConstructorWorker (\r
IN EFI_HANDLE ImageHandle,\r
IN EFI_SYSTEM_TABLE *SystemTable\r
- )\r
-{\r
+){\r
EFI_STATUS Status;\r
\r
- ASSERT(SystemTable != NULL);\r
- ASSERT(gBS != NULL);\r
-\r
- mEfiShellEnvironment2 = NULL;\r
- mEfiShellProtocol = NULL;\r
- mEfiShellParametersProtocol = NULL;\r
- mEfiShellInterface = NULL;\r
- mEfiShellEnvironment2Handle = NULL;\r
- mOldStyleFileList = NULL;\r
-\r
//\r
// UEFI 2.0 shell interfaces (used preferentially)\r
//\r
//\r
if ((mEfiShellEnvironment2 != NULL && mEfiShellInterface != NULL) || \r
(mEfiShellProtocol != NULL && mEfiShellParametersProtocol != NULL) ) {\r
+ if (mEfiShellProtocol != NULL) {\r
+ FileFunctionMap.GetFileInfo = mEfiShellProtocol->GetFileInfo;\r
+ FileFunctionMap.SetFileInfo = mEfiShellProtocol->SetFileInfo;\r
+ FileFunctionMap.ReadFile = mEfiShellProtocol->ReadFile;\r
+ FileFunctionMap.WriteFile = mEfiShellProtocol->WriteFile;\r
+ FileFunctionMap.CloseFile = mEfiShellProtocol->CloseFile;\r
+ FileFunctionMap.DeleteFile = mEfiShellProtocol->DeleteFile;\r
+ FileFunctionMap.GetFilePosition = mEfiShellProtocol->GetFilePosition;\r
+ FileFunctionMap.SetFilePosition = mEfiShellProtocol->SetFilePosition;\r
+ FileFunctionMap.FlushFile = mEfiShellProtocol->FlushFile;\r
+ FileFunctionMap.GetFileSize = mEfiShellProtocol->GetFileSize;\r
+ } else {\r
+ FileFunctionMap.GetFileInfo = FileHandleGetInfo;\r
+ FileFunctionMap.SetFileInfo = FileHandleSetInfo;\r
+ FileFunctionMap.ReadFile = FileHandleRead;\r
+ FileFunctionMap.WriteFile = FileHandleWrite;\r
+ FileFunctionMap.CloseFile = FileHandleClose;\r
+ FileFunctionMap.DeleteFile = FileHandleDelete;\r
+ FileFunctionMap.GetFilePosition = FileHandleGetPosition;\r
+ FileFunctionMap.SetFilePosition = FileHandleSetPosition;\r
+ FileFunctionMap.FlushFile = FileHandleFlush;\r
+ FileFunctionMap.GetFileSize = FileHandleGetSize;\r
+ }\r
return (EFI_SUCCESS);\r
}\r
return (EFI_NOT_FOUND);\r
}\r
+/**\r
+ Constructor for the Shell library.\r
+\r
+ Initialize the library and determine if the underlying is a UEFI Shell 2.0 or an EFI shell.\r
+\r
+ @param ImageHandle the image handle of the process\r
+ @param SystemTable the EFI System Table pointer\r
+\r
+ @retval EFI_SUCCESS the initialization was complete sucessfully\r
+ @return others an error ocurred during initialization\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellLibConstructor (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+\r
+\r
+ mEfiShellEnvironment2 = NULL;\r
+ mEfiShellProtocol = NULL;\r
+ mEfiShellParametersProtocol = NULL;\r
+ mEfiShellInterface = NULL;\r
+ mEfiShellEnvironment2Handle = NULL;\r
+\r
+ ///@todo make a worker constructor so initialize function works\r
+ //\r
+ // verify that auto initialize is not set false\r
+ // \r
+ if (PcdGetBool(PcdShellLibAutoInitialize) == 0) {\r
+ return (EFI_SUCCESS);\r
+ }\r
+ \r
+ return (ShellLibConstructorWorker(ImageHandle, SystemTable));\r
+}\r
\r
/**\r
Destructory for the library. free any resources.\r
&gEfiShellEnvironment2Guid,\r
ImageHandle,\r
NULL);\r
+ mEfiShellEnvironment2 = NULL;\r
}\r
if (mEfiShellInterface != NULL) {\r
gBS->CloseProtocol(ImageHandle,\r
&gEfiShellInterfaceGuid,\r
ImageHandle,\r
NULL); \r
+ mEfiShellInterface = NULL;\r
}\r
if (mEfiShellProtocol != NULL) {\r
gBS->CloseProtocol(ImageHandle,\r
&gEfiShellProtocolGuid,\r
ImageHandle,\r
- NULL); \r
+ NULL); \r
+ mEfiShellProtocol = NULL;\r
}\r
if (mEfiShellParametersProtocol != NULL) {\r
gBS->CloseProtocol(ImageHandle,\r
&gEfiShellParametersProtocolGuid,\r
ImageHandle,\r
NULL); \r
+ mEfiShellParametersProtocol = NULL;\r
}\r
+ mEfiShellEnvironment2Handle = NULL;\r
return (EFI_SUCCESS);\r
}\r
+\r
+/**\r
+ This function causes the shell library to initialize itself. If the shell library\r
+ is already initialized it will de-initialize all the current protocol poitners and\r
+ re-populate them again.\r
+\r
+ When the library is used with PcdShellLibAutoInitialize set to true this function\r
+ will return EFI_SUCCESS and perform no actions.\r
+\r
+ This function is intended for internal access for shell commands only.\r
+\r
+ @retval EFI_SUCCESS the initialization was complete sucessfully\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellInitialize (\r
+ ) {\r
+ //\r
+ // if auto initialize is not false then skip\r
+ //\r
+ if (PcdGetBool(PcdShellLibAutoInitialize) != 0) {\r
+ return (EFI_SUCCESS);\r
+ }\r
+\r
+ //\r
+ // deinit the current stuff\r
+ //\r
+ ASSERT_EFI_ERROR(ShellLibDestructor(gImageHandle, gST));\r
+\r
+ //\r
+ // init the new stuff\r
+ //\r
+ return (ShellLibConstructorWorker(gImageHandle, gST));\r
+}\r
+\r
/**\r
This function will retrieve the information about the file for the handle \r
specified and store it in allocated pool memory.\r
IN EFI_FILE_HANDLE FileHandle\r
)\r
{\r
- EFI_GUID FileInfoGuid;\r
- EFI_FILE_INFO *pFileInfo;\r
- UINTN FileInfoSize;\r
- EFI_STATUS Status;\r
-\r
- //\r
- // ASSERT if FileHandle is NULL\r
- //\r
- ASSERT (FileHandle != NULL);\r
-\r
- //\r
- // Get the required size to allocate\r
- //\r
- FileInfoGuid = gEfiFileInfoGuid;\r
- FileInfoSize = 0;\r
- pFileInfo = NULL;\r
- Status = FileHandle->GetInfo(FileHandle, \r
- &FileInfoGuid, \r
- &FileInfoSize, \r
- pFileInfo);\r
- //\r
- // error is expected. getting size to allocate\r
- //\r
- ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
- pFileInfo = AllocateZeroPool(FileInfoSize);\r
- ASSERT (pFileInfo != NULL);\r
- //\r
- // now get the information\r
- //\r
- Status = FileHandle->GetInfo(FileHandle, \r
- &FileInfoGuid, \r
- &FileInfoSize, \r
- pFileInfo);\r
- //\r
- // if we got an error free the memory and return NULL\r
- //\r
- if (EFI_ERROR(Status)) {\r
- FreePool(pFileInfo);\r
- return NULL;\r
- }\r
- return (pFileInfo);\r
+ return (FileFunctionMap.GetFileInfo(FileHandle));\r
}\r
\r
/**\r
IN EFI_FILE_INFO *FileInfo\r
)\r
{\r
- EFI_GUID FileInfoGuid;\r
- \r
- //\r
- // ASSERT if the FileHandle or FileInfo is NULL\r
- //\r
- ASSERT (FileHandle != NULL);\r
- ASSERT (FileInfo != NULL);\r
-\r
- FileInfoGuid = gEfiFileInfoGuid;\r
- //\r
- // Set the info\r
- //\r
- return (FileHandle->SetInfo(FileHandle, \r
- &FileInfoGuid,\r
- (UINTN)FileInfo->Size,\r
- FileInfo));\r
+ return (FileFunctionMap.SetFileInfo(FileHandle, FileInfo));\r
} \r
\r
/**\r
Status = ShellOpenFileByName(FileName, FileHandle, OpenMode, Attributes);\r
FreePool(FileName);\r
return (Status);\r
- } else {\r
+ } \r
+\r
+\r
+ //\r
+ // use old shell method.\r
+ //\r
+ Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, \r
+ FilePath, \r
+ DeviceHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = gBS->OpenProtocol(*DeviceHandle,\r
+ &gEfiSimpleFileSystemProtocolGuid,\r
+ &EfiSimpleFileSystemProtocol,\r
+ gImageHandle,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, FileHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ FileHandle = NULL;\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // go down directories one node at a time.\r
+ //\r
+ while (!IsDevicePathEnd (*FilePath)) {\r
//\r
- // use old shell method.\r
+ // For file system access each node should be a file path component\r
//\r
- Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, \r
- FilePath, \r
- DeviceHandle);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- Status = gBS->OpenProtocol(*DeviceHandle,\r
- &gEfiSimpleFileSystemProtocolGuid,\r
- &EfiSimpleFileSystemProtocol,\r
- gImageHandle,\r
- NULL,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, FileHandle);\r
- if (EFI_ERROR (Status)) {\r
+ if (DevicePathType (*FilePath) != MEDIA_DEVICE_PATH ||\r
+ DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP\r
+ ) {\r
FileHandle = NULL;\r
- return Status;\r
+ return (EFI_INVALID_PARAMETER);\r
}\r
+ //\r
+ // Open this file path node\r
+ //\r
+ LastHandle = *FileHandle;\r
+ *FileHandle = NULL;\r
\r
//\r
- // go down directories one node at a time.\r
+ // Try to test opening an existing file\r
//\r
- while (!IsDevicePathEnd (*FilePath)) {\r
- //\r
- // For file system access each node should be a file path component\r
- //\r
- if (DevicePathType (*FilePath) != MEDIA_DEVICE_PATH ||\r
- DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP\r
- ) {\r
- FileHandle = NULL;\r
- return (EFI_INVALID_PARAMETER);\r
- }\r
- //\r
- // Open this file path node\r
- //\r
- LastHandle = *FileHandle;\r
- *FileHandle = NULL;\r
+ Status = LastHandle->Open (\r
+ LastHandle,\r
+ FileHandle,\r
+ ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,\r
+ OpenMode &~EFI_FILE_MODE_CREATE,\r
+ 0\r
+ );\r
\r
- //\r
- // Try to test opening an existing file\r
- //\r
+ //\r
+ // see if the error was that it needs to be created\r
+ //\r
+ if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) {\r
Status = LastHandle->Open (\r
LastHandle,\r
FileHandle,\r
((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,\r
- OpenMode &~EFI_FILE_MODE_CREATE,\r
- 0\r
+ OpenMode,\r
+ Attributes\r
);\r
+ }\r
+ //\r
+ // Close the last node\r
+ //\r
+ LastHandle->Close (LastHandle);\r
\r
- //\r
- // see if the error was that it needs to be created\r
- //\r
- if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) {\r
- Status = LastHandle->Open (\r
- LastHandle,\r
- FileHandle,\r
- ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,\r
- OpenMode,\r
- Attributes\r
- );\r
- }\r
- //\r
- // Close the last node\r
- //\r
- LastHandle->Close (LastHandle);\r
-\r
- if (EFI_ERROR(Status)) {\r
- return (Status);\r
- }\r
-\r
- //\r
- // Get the next node\r
- //\r
- *FilePath = NextDevicePathNode (*FilePath);\r
+ if (EFI_ERROR(Status)) {\r
+ return (Status);\r
}\r
- return (EFI_SUCCESS);\r
+\r
+ //\r
+ // Get the next node\r
+ //\r
+ *FilePath = NextDevicePathNode (*FilePath);\r
}\r
+ return (EFI_SUCCESS);\r
}\r
\r
/**\r
return (mEfiShellProtocol->OpenFileByName(FileName,\r
FileHandle,\r
OpenMode));\r
+\r
+ ///@todo add the attributes\r
} \r
//\r
// Using EFI Shell version\r
OUT VOID *Buffer\r
)\r
{\r
- //\r
- // ASSERT if FileHandle is NULL\r
- //\r
- ASSERT (FileHandle != NULL);\r
-\r
- //\r
- // Perform the read based on EFI_FILE_PROTOCOL\r
- //\r
- return (FileHandle->Read(FileHandle, BufferSize, Buffer));\r
+ return (FileFunctionMap.ReadFile(FileHandle, BufferSize, Buffer));\r
}\r
\r
\r
IN VOID *Buffer\r
)\r
{\r
- //\r
- // ASSERT if FileHandle is NULL\r
- //\r
- ASSERT (FileHandle != NULL);\r
- //\r
- // Perform the write based on EFI_FILE_PROTOCOL\r
- //\r
- return (FileHandle->Write(FileHandle, BufferSize, Buffer));\r
+ return (FileFunctionMap.WriteFile(FileHandle, BufferSize, Buffer));\r
}\r
\r
/** \r
IN EFI_FILE_HANDLE *FileHandle\r
)\r
{\r
- EFI_STATUS Status;\r
- //\r
- // ASSERT if FileHandle is NULL\r
- //\r
- ASSERT (FileHandle != NULL);\r
- ASSERT (*FileHandle != NULL);\r
- //\r
- // Perform the Close based on EFI_FILE_PROTOCOL\r
- //\r
- Status = (*FileHandle)->Close(*FileHandle);\r
- *FileHandle = NULL;\r
- return Status;\r
+ return (FileFunctionMap.CloseFile(*FileHandle));\r
}\r
\r
/**\r
IN EFI_FILE_HANDLE *FileHandle\r
)\r
{\r
- EFI_STATUS Status;\r
- //\r
- // ASSERT if FileHandle is NULL\r
- //\r
- ASSERT (FileHandle != NULL);\r
- ASSERT (*FileHandle != NULL);\r
- //\r
- // Perform the Delete based on EFI_FILE_PROTOCOL\r
- //\r
- Status = (*FileHandle)->Delete(*FileHandle);\r
- *FileHandle = NULL;\r
- return Status;\r
+ return (FileFunctionMap.DeleteFile(*FileHandle));\r
}\r
\r
/**\r
IN UINT64 Position\r
)\r
{\r
- //\r
- // ASSERT if FileHandle is NULL\r
- //\r
- ASSERT (FileHandle != NULL);\r
- //\r
- // Perform the SetPosition based on EFI_FILE_PROTOCOL\r
- //\r
- return (FileHandle->SetPosition(FileHandle, Position));\r
+ return (FileFunctionMap.SetFilePosition(FileHandle, Position));\r
}\r
\r
/** \r
OUT UINT64 *Position\r
)\r
{\r
- //\r
- // ASSERT if FileHandle is NULL\r
- //\r
- ASSERT (FileHandle != NULL);\r
- //\r
- // Perform the GetPosition based on EFI_FILE_PROTOCOL\r
- //\r
- return (FileHandle->GetPosition(FileHandle, Position));\r
+ return (FileFunctionMap.GetFilePosition(FileHandle, Position));\r
}\r
/**\r
Flushes data on a file\r
IN EFI_FILE_HANDLE FileHandle\r
)\r
{\r
- //\r
- // ASSERT if FileHandle is NULL\r
- //\r
- ASSERT (FileHandle != NULL);\r
- //\r
- // Perform the Flush based on EFI_FILE_PROTOCOL\r
- //\r
- return (FileHandle->Flush(FileHandle));\r
-}\r
-\r
-/**\r
- function to determine if a given handle is a directory handle\r
-\r
- if DirHandle is NULL then ASSERT()\r
-\r
- open the file information on the DirHandle and verify that the Attribute\r
- includes EFI_FILE_DIRECTORY bit set.\r
-\r
- @param DirHandle Handle to open file\r
-\r
- @retval EFI_SUCCESS DirHandle is a directory\r
- @retval EFI_INVALID_PARAMETER DirHandle did not have EFI_FILE_INFO available\r
- @retval EFI_NOT_FOUND DirHandle is not a directory\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-InternalShellIsDirectory (\r
- IN EFI_FILE_HANDLE DirHandle\r
- )\r
-{\r
- EFI_FILE_INFO *DirInfo;\r
-\r
- //\r
- // ASSERT if DirHandle is NULL\r
- //\r
- ASSERT(DirHandle != NULL);\r
- \r
- //\r
- // get the file information for DirHandle\r
- //\r
- DirInfo = ShellGetFileInfo (DirHandle);\r
- \r
- //\r
- // Parse DirInfo\r
- //\r
- if (DirInfo == NULL) {\r
- //\r
- // We got nothing...\r
- //\r
- return (EFI_INVALID_PARAMETER);\r
- } \r
- if ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0) {\r
- //\r
- // Attributes say this is not a directory\r
- //\r
- FreePool (DirInfo);\r
- return (EFI_NOT_FOUND);\r
- }\r
- //\r
- // all good...\r
- //\r
- FreePool (DirInfo);\r
- return (EFI_SUCCESS);\r
+ return (FileFunctionMap.FlushFile(FileHandle));\r
}\r
\r
/**\r
EFIAPI\r
ShellFindFirstFile (\r
IN EFI_FILE_HANDLE DirHandle,\r
- OUT EFI_FILE_INFO *Buffer\r
+ OUT EFI_FILE_INFO **Buffer\r
)\r
{\r
- EFI_STATUS Status;\r
- UINTN BufferSize;\r
-\r
- //\r
- // ASSERT if DirHandle is NULL\r
- //\r
- ASSERT (DirHandle != NULL);\r
- \r
- //\r
- // verify that DirHandle is a directory\r
- //\r
- Status = InternalShellIsDirectory(DirHandle);\r
- if (EFI_ERROR(Status)) {\r
- return (Status);\r
- } \r
-\r
- //\r
- // reset to the begining of the directory \r
- //\r
- Status = ShellSetFilePosition (DirHandle, 0);\r
- if (EFI_ERROR(Status)) {\r
- return (Status);\r
- } \r
-\r
//\r
- // Allocate a buffer sized to struct size + enough for the string at the end\r
+ // pass to file handle lib\r
//\r
- BufferSize = FIND_XXXXX_FILE_BUFFER_SIZE;\r
- Buffer = AllocateZeroPool(BufferSize);\r
- ASSERT (Buffer != NULL);\r
-\r
- //\r
- // read in the info about the first file\r
- //\r
- Status = ShellReadFile (DirHandle, &BufferSize, Buffer);\r
- ASSERT(Status != EFI_BUFFER_TOO_SMALL);\r
- if (EFI_ERROR(Status)) {\r
- return (Status);\r
- }\r
- return (EFI_SUCCESS);\r
+ return (FileHandleFindFirstFile(DirHandle, Buffer));\r
}\r
/**\r
Retrieves the next file in a directory.\r
OUT BOOLEAN *NoFile\r
)\r
{\r
- EFI_STATUS Status;\r
- UINTN BufferSize;\r
-\r
//\r
- // ASSERTs for DirHandle or Buffer or NoFile poitners being NULL\r
+ // pass to file handle lib\r
//\r
- ASSERT (DirHandle != NULL);\r
- ASSERT (Buffer != NULL);\r
- ASSERT (NoFile != NULL);\r
- \r
- //\r
- // verify that DirHandle is a directory\r
- //\r
- Status = InternalShellIsDirectory(DirHandle);\r
- if (EFI_ERROR(Status)) {\r
- return (Status);\r
- } \r
-\r
- //\r
- // This BufferSize MUST stay equal to the originally allocated one in GetFirstFile\r
- //\r
- BufferSize = FIND_XXXXX_FILE_BUFFER_SIZE;\r
-\r
- //\r
- // read in the info about the next file\r
- //\r
- Status = ShellReadFile (DirHandle, &BufferSize, Buffer);\r
- ASSERT(Status != EFI_BUFFER_TOO_SMALL);\r
- if (EFI_ERROR(Status)) {\r
- return (Status);\r
- }\r
-\r
- //\r
- // If we read 0 bytes (but did not have erros) we already read in the last file.\r
- //\r
- if (BufferSize == 0) {\r
- FreePool(Buffer);\r
- *NoFile = TRUE;\r
- }\r
-\r
- return (EFI_SUCCESS);\r
+ return (FileHandleFindNextFile(DirHandle, Buffer, NoFile));\r
}\r
/**\r
Retrieve the size of a file.\r
OUT UINT64 *Size\r
)\r
{\r
- EFI_FILE_INFO *FileInfo;\r
-\r
- //\r
- // ASSERT for FileHandle or Size being NULL\r
- //\r
- ASSERT (FileHandle != NULL);\r
- ASSERT (Size != NULL);\r
- \r
- //\r
- // get the FileInfo structure\r
- //\r
- FileInfo = ShellGetFileInfo(FileHandle);\r
- if (FileInfo == NULL) {\r
- return (EFI_DEVICE_ERROR);\r
- }\r
-\r
- //\r
- // Assign the Size pointer to the correct value\r
- //\r
- *Size = FileInfo->FileSize;\r
- \r
- //\r
- // free the FileInfo memory\r
- //\r
- FreePool(FileInfo);\r
-\r
- return (EFI_SUCCESS);\r
+ return (FileFunctionMap.GetFileSize(FileHandle, Size));\r
}\r
/**\r
Retrieves the status of the break execution flag\r
/// This allows for the struct to be populated.\r
///\r
typedef struct {\r
- EFI_LIST_ENTRY Link;\r
+ LIST_ENTRY Link;\r
EFI_STATUS Status;\r
CHAR16 *FullName;\r
CHAR16 *FileName;\r
LIST_ENTRY*\r
EFIAPI\r
InternalShellConvertFileListType (\r
- EFI_LIST_ENTRY *FileList\r
+ LIST_ENTRY *FileList\r
)\r
{\r
LIST_ENTRY *ListHead;\r
SHELL_FILE_ARG *OldInfo;\r
- EFI_LIST_ENTRY *Link;\r
+ LIST_ENTRY *Link;\r
EFI_SHELL_FILE_INFO_NO_CONST *NewInfo;\r
\r
//\r
//\r
// Allocate our list head and initialize the list\r
//\r
- ListHead = AllocateZeroPool(sizeof(EFI_LIST_ENTRY));\r
+ ListHead = AllocateZeroPool(sizeof(LIST_ENTRY));\r
ASSERT (ListHead != NULL);\r
ListHead = InitializeListHead (ListHead);\r
\r
//\r
// enumerate through each member of the old list and copy\r
//\r
- for (Link = FileList->Flink; Link != FileList; Link = Link->Flink) {\r
+ for (Link = FileList->ForwardLink; Link != FileList; Link = Link->ForwardLink) {\r
OldInfo = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE);\r
\r
//\r
NewInfo->Handle = OldInfo->Handle;\r
NewInfo->Status = OldInfo->Status;\r
\r
+ // old shell checks for 0 not NULL\r
+ OldInfo->Handle = 0;\r
+\r
//\r
// allocate new space to copy strings and structure\r
//\r
{\r
EFI_STATUS Status;\r
LIST_ENTRY *EmptyNode;\r
-\r
- //\r
- // make sure we have no outstanding list\r
- //\r
- if (mOldStyleFileList != NULL) {\r
- *ListHead = NULL;\r
- return (EFI_UNSUPPORTED);\r
- }\r
-\r
+ LIST_ENTRY *mOldStyleFileList;\r
+ \r
//\r
// ASSERT that Arg and ListHead are not NULL\r
//\r
//\r
// allocate memory for old list head\r
//\r
- mOldStyleFileList = (EFI_LIST_ENTRY*)AllocatePool(sizeof(EFI_LIST_ENTRY));\r
+ mOldStyleFileList = (LIST_ENTRY*)AllocatePool(sizeof(LIST_ENTRY));\r
ASSERT(mOldStyleFileList != NULL);\r
\r
//\r
//\r
EmptyNode = InternalShellConvertFileListType(mOldStyleFileList);\r
\r
+ //\r
+ // Free the EFI Shell version that was converted.\r
+ //\r
+ ASSERT_EFI_ERROR(mEfiShellEnvironment2->FreeFileList(mOldStyleFileList));\r
+ FreePool(mOldStyleFileList);\r
+ mOldStyleFileList = NULL;\r
+\r
//\r
// remove the empty head of the list\r
//\r
if (mEfiShellProtocol != NULL) {\r
return (mEfiShellProtocol->FreeFileList(ListHead));\r
} else {\r
- //\r
- // Free the EFI Shell version that was converted.\r
- //\r
- ASSERT_EFI_ERROR(mEfiShellEnvironment2->FreeFileList(mOldStyleFileList));\r
- FreePool(mOldStyleFileList);\r
- mOldStyleFileList = NULL;\r
-\r
//\r
// Since this is EFI Shell version we need to free our internally made copy \r
// of the list\r
//\r
for (Node = GetFirstNode((LIST_ENTRY*)*ListHead) ; IsListEmpty((LIST_ENTRY*)*ListHead) == FALSE ; Node = GetFirstNode((LIST_ENTRY*)*ListHead)) {\r
RemoveEntryList(Node);\r
+ ((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Handle->Close(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Handle);\r
FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->FullName);\r
FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->FileName);\r
FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Info);\r
}\r
\r
typedef struct {\r
- EFI_LIST_ENTRY List;\r
+ LIST_ENTRY List;\r
CHAR16 *Name;\r
ParamType Type;\r
CHAR16 *Value;\r
**/\r
BOOLEAN\r
EFIAPI\r
-IsCheckList (\r
+InternalIsOnCheckList (\r
IN CONST CHAR16 *Name,\r
IN CONST SHELL_PARAM_ITEM *CheckList,\r
OUT ParamType *Type\r
ASSERT(Type != NULL);\r
ASSERT(Name != NULL);\r
\r
+ //\r
+ // question mark and page break mode are always supported\r
+ //\r
+ if ((StrCmp(Name, L"-?") == 0) ||\r
+ (StrCmp(Name, L"-b") == 0)\r
+ ) {\r
+ return (TRUE);\r
+ }\r
+\r
//\r
// Enumerate through the list\r
//\r
return (FALSE);\r
}\r
/**\r
- Checks the string for indicators of "flag" status. this is a leading '/' or '-'\r
+ Checks the string for indicators of "flag" status. this is a leading '/', '-', or '+'\r
\r
@param Name pointer to Name of parameter found\r
\r
**/\r
BOOLEAN\r
EFIAPI\r
-IsFlag (\r
+InternalIsFlag (\r
IN CONST CHAR16 *Name\r
)\r
{\r
//\r
// If the Name has a / or - as the first character return TRUE\r
//\r
- if ((Name[0] == L'/') || (Name[0] == L'-') ) {\r
+ if ((Name[0] == L'/') || \r
+ (Name[0] == L'-') ||\r
+ (Name[0] == L'+')\r
+ ) {\r
return (TRUE);\r
}\r
return (FALSE);\r
@param CheckList pointer to list of parameters to check\r
@param CheckPackage pointer to pointer to list checked values\r
@param ProblemParam optional pointer to pointer to unicode string for \r
- the paramater that caused failure.\r
+ the paramater that caused failure. If used then the\r
+ caller is responsible for freeing the memory.\r
@param AutoPageBreak will automatically set PageBreakEnabled for "b" parameter\r
@param Argc Count of parameters in Argv\r
@param Argv pointer to array of parameters\r
ASSERT(CurrentItemPackage->Value != NULL);\r
StrCpy(CurrentItemPackage->Value, Argv[LoopCounter]);\r
InsertTailList(*CheckPackage, (LIST_ENTRY*)CurrentItemPackage);\r
- } else if (IsFlag(Argv[LoopCounter]) == FALSE) {\r
+ } else if (InternalIsFlag(Argv[LoopCounter]) == FALSE) {\r
//\r
// add this one as a non-flag\r
//\r
StrCpy(CurrentItemPackage->Value, Argv[LoopCounter]);\r
CurrentItemPackage->OriginalPosition = Count++;\r
InsertTailList(*CheckPackage, (LIST_ENTRY*)CurrentItemPackage);\r
- } else if (IsCheckList(Argv[LoopCounter], CheckList, &CurrentItemType) == TRUE) {\r
+ } else if (InternalIsOnCheckList(Argv[LoopCounter], CheckList, &CurrentItemType) == TRUE) {\r
//\r
// this is a flag\r
//\r
//\r
// this was a non-recognised flag... error!\r
//\r
- *ProblemParam = (CHAR16*)Argv[LoopCounter];\r
+ *ProblemParam = AllocatePool(StrSize(Argv[LoopCounter]));\r
+ ASSERT(*ProblemParam != NULL);\r
+ StrCpy(*ProblemParam, Argv[LoopCounter]);\r
ShellCommandLineFreeVarList(*CheckPackage);\r
*CheckPackage = NULL;\r
return (EFI_VOLUME_CORRUPTED);\r