--- /dev/null
+/** @file\r
+ Provides interface to shell functionality for shell commands and applications.\r
+\r
+Copyright (c) 2006 - 2009, Intel Corporation\r
+All rights reserved. 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
+\r
+**/\r
+\r
+#include <Uefi.h>\r
+#include <Library/ShellLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DevicePathLib.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
+#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
+/**\r
+ helper function to find ShellEnvironment2 for constructor\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellFindSE2 (\r
+ IN EFI_HANDLE ImageHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE *Buffer;\r
+ UINTN BufferSize;\r
+ UINTN HandleIndex;\r
+\r
+ BufferSize = 0;\r
+ Buffer = NULL;\r
+ Status = gBS->OpenProtocol(ImageHandle, \r
+ &gEfiShellEnvironment2Guid,\r
+ (VOID **)&mEfiShellEnvironment2,\r
+ ImageHandle,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ //\r
+ // look for the mEfiShellEnvironment2 protocol at a higher level\r
+ //\r
+ if (EFI_ERROR (Status) || !(CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid) != FALSE &&\r
+ (mEfiShellEnvironment2->MajorVersion > EFI_SHELL_MAJOR_VER ||\r
+ (mEfiShellEnvironment2->MajorVersion == EFI_SHELL_MAJOR_VER && mEfiShellEnvironment2->MinorVersion >= EFI_SHELL_MINOR_VER)))) {\r
+ //\r
+ // figure out how big of a buffer we need.\r
+ //\r
+ Status = gBS->LocateHandle (ByProtocol,\r
+ &gEfiShellEnvironment2Guid,\r
+ NULL, // ignored for ByProtocol\r
+ &BufferSize,\r
+ Buffer\r
+ );\r
+ ASSERT(Status == EFI_BUFFER_TOO_SMALL);\r
+ Buffer = (EFI_HANDLE*)AllocatePool(BufferSize);\r
+ ASSERT(Buffer != NULL);\r
+ Status = gBS->LocateHandle (ByProtocol,\r
+ &gEfiShellEnvironment2Guid,\r
+ NULL, // ignored for ByProtocol\r
+ &BufferSize,\r
+ Buffer\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // now parse the list of returned handles\r
+ //\r
+ Status = EFI_NOT_FOUND;\r
+ for (HandleIndex = 0; HandleIndex < (BufferSize/sizeof(Buffer[0])); HandleIndex++) {\r
+ Status = gBS->OpenProtocol(Buffer[HandleIndex], \r
+ &gEfiShellEnvironment2Guid,\r
+ (VOID **)&mEfiShellEnvironment2,\r
+ ImageHandle,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid) != FALSE &&\r
+ (mEfiShellEnvironment2->MajorVersion > EFI_SHELL_MAJOR_VER ||\r
+ (mEfiShellEnvironment2->MajorVersion == EFI_SHELL_MAJOR_VER && mEfiShellEnvironment2->MinorVersion >= EFI_SHELL_MINOR_VER))) {\r
+ mEfiShellEnvironment2Handle = Buffer[HandleIndex];\r
+ Status = EFI_SUCCESS;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ if (Buffer != NULL) {\r
+ FreePool (Buffer);\r
+ }\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
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\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
+ Status = gBS->OpenProtocol(ImageHandle, \r
+ &gEfiShellProtocolGuid,\r
+ (VOID **)&mEfiShellProtocol,\r
+ ImageHandle,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ mEfiShellProtocol = NULL;\r
+ }\r
+ Status = gBS->OpenProtocol(ImageHandle, \r
+ &gEfiShellParametersProtocolGuid,\r
+ (VOID **)&mEfiShellParametersProtocol,\r
+ ImageHandle,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ mEfiShellParametersProtocol = NULL;\r
+ }\r
+\r
+ if (mEfiShellParametersProtocol == NULL || mEfiShellProtocol == NULL) {\r
+ //\r
+ // Moved to seperate function due to complexity\r
+ //\r
+ Status = ShellFindSE2(ImageHandle);\r
+\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((DEBUG_ERROR, "Status: 0x%08x\r\n", Status));\r
+ mEfiShellEnvironment2 = NULL;\r
+ }\r
+ Status = gBS->OpenProtocol(ImageHandle, \r
+ &gEfiShellInterfaceGuid,\r
+ (VOID **)&mEfiShellInterface,\r
+ ImageHandle,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ mEfiShellInterface = NULL;\r
+ }\r
+ }\r
+ //\r
+ // only success getting 2 of either the old or new, but no 1/2 and 1/2\r
+ //\r
+ if ((mEfiShellEnvironment2 != NULL && mEfiShellInterface != NULL) || \r
+ (mEfiShellProtocol != NULL && mEfiShellParametersProtocol != NULL) ) {\r
+ return (EFI_SUCCESS);\r
+ }\r
+ return (EFI_NOT_FOUND);\r
+}\r
+\r
+/**\r
+ Destructory for the library. free any resources.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellLibDestructor (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ if (mEfiShellEnvironment2 != NULL) {\r
+ gBS->CloseProtocol(mEfiShellEnvironment2Handle==NULL?ImageHandle:mEfiShellEnvironment2Handle,\r
+ &gEfiShellEnvironment2Guid,\r
+ ImageHandle,\r
+ NULL);\r
+ }\r
+ if (mEfiShellInterface != NULL) {\r
+ gBS->CloseProtocol(ImageHandle,\r
+ &gEfiShellInterfaceGuid,\r
+ ImageHandle,\r
+ NULL); \r
+ }\r
+ if (mEfiShellProtocol != NULL) {\r
+ gBS->CloseProtocol(ImageHandle,\r
+ &gEfiShellProtocolGuid,\r
+ ImageHandle,\r
+ NULL); \r
+ }\r
+ if (mEfiShellParametersProtocol != NULL) {\r
+ gBS->CloseProtocol(ImageHandle,\r
+ &gEfiShellParametersProtocolGuid,\r
+ ImageHandle,\r
+ NULL); \r
+ }\r
+ return (EFI_SUCCESS);\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
+\r
+ This function allocates a buffer to store the file\92s information. It is the \r
+ caller\92s responsibility to free the buffer\r
+\r
+ @param FileHandle The file handle of the file for which information is \r
+ being requested.\r
+\r
+ @retval NULL information could not be retrieved.\r
+\r
+ @return the information about the file\r
+**/\r
+EFI_FILE_INFO*\r
+EFIAPI\r
+ShellGetFileInfo (\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
+}\r
+\r
+/**\r
+ This function will set the information about the file for the opened handle \r
+ specified.\r
+\r
+ @param FileHandle The file handle of the file for which information \r
+ is being set\r
+\r
+ @param FileInfo The infotmation to set.\r
+\r
+ @retval EFI_SUCCESS The information was set.\r
+ @retval EFI_UNSUPPORTED The InformationType is not known.\r
+ @retval EFI_NO_MEDIA The device has no medium.\r
+ @retval EFI_DEVICE_ERROR The device reported an error.\r
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+ @retval EFI_WRITE_PROTECTED The file or medium is write protected.\r
+ @retval EFI_ACCESS_DENIED The file was opened read only.\r
+ @retval EFI_VOLUME_FULL The volume is full.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellSetFileInfo (\r
+ IN EFI_FILE_HANDLE FileHandle,\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
+} \r
+ \r
+ /**\r
+ This function will open a file or directory referenced by DevicePath.\r
+\r
+ This function opens a file with the open mode according to the file path. The \r
+ Attributes is valid only for EFI_FILE_MODE_CREATE.\r
+\r
+ @param FilePath on input the device path to the file. On output \r
+ the remaining device path.\r
+ @param DeviceHandle pointer to the system device handle.\r
+ @param FileHandle pointer to the file handle.\r
+ @param OpenMode the mode to open the file with.\r
+ @param Attributes the file's file attributes.\r
+\r
+ @retval EFI_SUCCESS The information was set.\r
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
+ @retval EFI_UNSUPPORTED Could not open the file path. \r
+ @retval EFI_NOT_FOUND The specified file could not be found on the \r
+ device or the file system could not be found on \r
+ the device.\r
+ @retval EFI_NO_MEDIA The device has no medium.\r
+ @retval EFI_MEDIA_CHANGED The device has a different medium in it or the \r
+ medium is no longer supported.\r
+ @retval EFI_DEVICE_ERROR The device reported an error.\r
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+ @retval EFI_WRITE_PROTECTED The file or medium is write protected.\r
+ @retval EFI_ACCESS_DENIED The file was opened read only.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the \r
+ file.\r
+ @retval EFI_VOLUME_FULL The volume is full.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellOpenFileByDevicePath(\r
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,\r
+ OUT EFI_HANDLE *DeviceHandle,\r
+ OUT EFI_FILE_HANDLE *FileHandle,\r
+ IN UINT64 OpenMode,\r
+ IN UINT64 Attributes\r
+ )\r
+{\r
+ CHAR16 *FileName;\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol;\r
+ EFI_FILE_HANDLE LastHandle;\r
+\r
+ //\r
+ // ASERT for FileHandle, FilePath, and DeviceHandle being NULL\r
+ //\r
+ ASSERT(FilePath != NULL);\r
+ ASSERT(FileHandle != NULL);\r
+ ASSERT(DeviceHandle != NULL);\r
+ // \r
+ // which shell interface should we use\r
+ //\r
+ if (mEfiShellProtocol != NULL) {\r
+ //\r
+ // use UEFI Shell 2.0 method.\r
+ //\r
+ FileName = mEfiShellProtocol->GetFilePathFromDevicePath(*FilePath);\r
+ if (FileName == NULL) {\r
+ return (EFI_INVALID_PARAMETER);\r
+ }\r
+ Status = ShellOpenFileByName(FileName, FileHandle, OpenMode, Attributes);\r
+ FreePool(FileName);\r
+ return (Status);\r
+ } else {\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
+ // 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
+\r
+ //\r
+ // Try to test opening an existing file\r
+ //\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
+ // 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
+ }\r
+ return (EFI_SUCCESS);\r
+ }\r
+}\r
+\r
+/**\r
+ This function will open a file or directory referenced by filename.\r
+\r
+ If return is EFI_SUCCESS, the Filehandle is the opened file\92s handle; \r
+ otherwise, the Filehandle is NULL. The Attributes is valid only for \r
+ EFI_FILE_MODE_CREATE.\r
+\r
+ if FileNAme is NULL then ASSERT()\r
+\r
+ @param FileName pointer to file name\r
+ @param FileHandle pointer to the file handle.\r
+ @param OpenMode the mode to open the file with.\r
+ @param Attributes the file's file attributes.\r
+\r
+ @retval EFI_SUCCESS The information was set.\r
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
+ @retval EFI_UNSUPPORTED Could not open the file path. \r
+ @retval EFI_NOT_FOUND The specified file could not be found on the \r
+ device or the file system could not be found \r
+ on the device.\r
+ @retval EFI_NO_MEDIA The device has no medium.\r
+ @retval EFI_MEDIA_CHANGED The device has a different medium in it or the \r
+ medium is no longer supported.\r
+ @retval EFI_DEVICE_ERROR The device reported an error.\r
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+ @retval EFI_WRITE_PROTECTED The file or medium is write protected.\r
+ @retval EFI_ACCESS_DENIED The file was opened read only.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the \r
+ file.\r
+ @retval EFI_VOLUME_FULL The volume is full.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellOpenFileByName(\r
+ IN CHAR16 *FileName,\r
+ OUT EFI_FILE_HANDLE *FileHandle,\r
+ IN UINT64 OpenMode,\r
+ IN UINT64 Attributes\r
+ )\r
+{\r
+ EFI_HANDLE DeviceHandle;\r
+ EFI_DEVICE_PATH_PROTOCOL *FilePath;\r
+\r
+ //\r
+ // ASSERT if FileName is NULL\r
+ //\r
+ ASSERT(FileName != NULL);\r
+\r
+ if (mEfiShellProtocol != NULL) {\r
+ //\r
+ // Use UEFI Shell 2.0 method\r
+ //\r
+ return (mEfiShellProtocol->OpenFileByName(FileName,\r
+ FileHandle,\r
+ OpenMode));\r
+ } \r
+ //\r
+ // Using EFI Shell version\r
+ // this means convert name to path and call that function\r
+ // since this will use EFI method again that will open it.\r
+ //\r
+ ASSERT(mEfiShellEnvironment2 != NULL);\r
+ FilePath = mEfiShellEnvironment2->NameToPath (FileName);\r
+ if (FileDevicePath != NULL) {\r
+ return (ShellOpenFileByDevicePath(&FilePath,\r
+ &DeviceHandle,\r
+ FileHandle,\r
+ OpenMode,\r
+ Attributes ));\r
+ }\r
+ return (EFI_DEVICE_ERROR);\r
+}\r
+/**\r
+ This function create a directory\r
+\r
+ If return is EFI_SUCCESS, the Filehandle is the opened directory's handle; \r
+ otherwise, the Filehandle is NULL. If the directory already existed, this \r
+ function opens the existing directory.\r
+\r
+ @param DirectoryName pointer to directory name\r
+ @param FileHandle pointer to the file handle.\r
+\r
+ @retval EFI_SUCCESS The information was set.\r
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
+ @retval EFI_UNSUPPORTED Could not open the file path. \r
+ @retval EFI_NOT_FOUND The specified file could not be found on the \r
+ device or the file system could not be found \r
+ on the device.\r
+ @retval EFI_NO_MEDIA The device has no medium.\r
+ @retval EFI_MEDIA_CHANGED The device has a different medium in it or the \r
+ medium is no longer supported.\r
+ @retval EFI_DEVICE_ERROR The device reported an error.\r
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+ @retval EFI_WRITE_PROTECTED The file or medium is write protected.\r
+ @retval EFI_ACCESS_DENIED The file was opened read only.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the \r
+ file.\r
+ @retval EFI_VOLUME_FULL The volume is full.\r
+ @sa ShellOpenFileByName\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellCreateDirectory(\r
+ IN CHAR16 *DirectoryName,\r
+ OUT EFI_FILE_HANDLE *FileHandle\r
+ )\r
+{\r
+ //\r
+ // this is a pass thru to the open file function with sepcific open mode and attributes\r
+ //\r
+ return (ShellOpenFileByName(DirectoryName,\r
+ FileHandle,\r
+ EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,\r
+ EFI_FILE_DIRECTORY\r
+ ));\r
+}\r
+\r
+/**\r
+ This function reads information from an opened file.\r
+\r
+ If FileHandle is not a directory, the function reads the requested number of \r
+ bytes from the file at the file\92s current position and returns them in Buffer. \r
+ If the read goes beyond the end of the file, the read length is truncated to the\r
+ end of the file. The file\92s current position is increased by the number of bytes \r
+ returned. If FileHandle is a directory, the function reads the directory entry \r
+ at the file\92s current position and returns the entry in Buffer. If the Buffer \r
+ is not large enough to hold the current directory entry, then \r
+ EFI_BUFFER_TOO_SMALL is returned and the current file position is not updated. \r
+ BufferSize is set to be the size of the buffer needed to read the entry. On \r
+ success, the current position is updated to the next directory entry. If there \r
+ are no more directory entries, the read returns a zero-length buffer. \r
+ EFI_FILE_INFO is the structure returned as the directory entry.\r
+\r
+ @param FileHandle the opened file handle\r
+ @param BufferSize on input the size of buffer in bytes. on return \r
+ the number of bytes written.\r
+ @param Buffer the buffer to put read data into.\r
+\r
+ @retval EFI_SUCCESS Data was read.\r
+ @retval EFI_NO_MEDIA The device has no media.\r
+ @retval EFI_DEVICE_ERROR The device reported an error.\r
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+ @retval EFI_BUFFER_TO_SMALL Buffer is too small. ReadSize contains required \r
+ size.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellReadFile(\r
+ IN EFI_FILE_HANDLE FileHandle,\r
+ IN OUT UINTN *BufferSize,\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
+}\r
+\r
+\r
+/**\r
+ Write data to a file.\r
+\r
+ This function writes the specified number of bytes to the file at the current \r
+ file position. The current file position is advanced the actual number of bytes \r
+ written, which is returned in BufferSize. Partial writes only occur when there \r
+ has been a data error during the write attempt (such as \93volume space full\94). \r
+ The file is automatically grown to hold the data if required. Direct writes to \r
+ opened directories are not supported.\r
+\r
+ @param FileHandle The opened file for writing\r
+ @param BufferSize on input the number of bytes in Buffer. On output\r
+ the number of bytes written.\r
+ @param Buffer the buffer containing data to write is stored.\r
+\r
+ @retval EFI_SUCCESS Data was written.\r
+ @retval EFI_UNSUPPORTED Writes to an open directory are not supported.\r
+ @retval EFI_NO_MEDIA The device has no media.\r
+ @retval EFI_DEVICE_ERROR The device reported an error.\r
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+ @retval EFI_WRITE_PROTECTED The device is write-protected.\r
+ @retval EFI_ACCESS_DENIED The file was open for read only.\r
+ @retval EFI_VOLUME_FULL The volume is full.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellWriteFile(\r
+ IN EFI_FILE_HANDLE FileHandle,\r
+ IN OUT UINTN *BufferSize,\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
+}\r
+\r
+/** \r
+ Close an open file handle.\r
+\r
+ This function closes a specified file handle. All \93dirty\94 cached file data is \r
+ flushed to the device, and the file is closed. In all cases the handle is \r
+ closed.\r
+\r
+@param FileHandle the file handle to close.\r
+\r
+@retval EFI_SUCCESS the file handle was closed sucessfully.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellCloseFile (\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
+}\r
+\r
+/**\r
+ Delete a file and close the handle\r
+\r
+ This function closes and deletes a file. In all cases the file handle is closed.\r
+ If the file cannot be deleted, the warning code EFI_WARN_DELETE_FAILURE is \r
+ returned, but the handle is still closed.\r
+\r
+ @param FileHandle the file handle to delete\r
+\r
+ @retval EFI_SUCCESS the file was closed sucessfully\r
+ @retval EFI_WARN_DELETE_FAILURE the handle was closed, but the file was not \r
+ deleted\r
+ @retval INVALID_PARAMETER One of the parameters has an invalid value.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellDeleteFile (\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
+}\r
+\r
+/**\r
+ Set the current position in a file.\r
+\r
+ This function sets the current file position for the handle to the position \r
+ supplied. With the exception of seeking to position 0xFFFFFFFFFFFFFFFF, only\r
+ absolute positioning is supported, and seeking past the end of the file is \r
+ allowed (a subsequent write would grow the file). Seeking to position \r
+ 0xFFFFFFFFFFFFFFFF causes the current position to be set to the end of the file.\r
+ If FileHandle is a directory, the only position that may be set is zero. This \r
+ has the effect of starting the read process of the directory entries over.\r
+\r
+ @param FileHandle The file handle on which the position is being set\r
+ @param Position Byte position from begining of file\r
+\r
+ @retval EFI_SUCCESS Operation completed sucessfully.\r
+ @retval EFI_UNSUPPORTED the seek request for non-zero is not valid on \r
+ directories.\r
+ @retval INVALID_PARAMETER One of the parameters has an invalid value.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellSetFilePosition (\r
+ IN EFI_FILE_HANDLE FileHandle,\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
+}\r
+\r
+/** \r
+ Gets a file's current position\r
+\r
+ This function retrieves the current file position for the file handle. For \r
+ directories, the current file position has no meaning outside of the file \r
+ system driver and as such the operation is not supported. An error is returned\r
+ if FileHandle is a directory.\r
+\r
+ @param FileHandle The open file handle on which to get the position.\r
+ @param Position Byte position from begining of file.\r
+\r
+ @retval EFI_SUCCESS the operation completed sucessfully.\r
+ @retval INVALID_PARAMETER One of the parameters has an invalid value.\r
+ @retval EFI_UNSUPPORTED the request is not valid on directories.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellGetFilePosition (\r
+ IN EFI_FILE_HANDLE FileHandle,\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
+}\r
+/**\r
+ Flushes data on a file\r
+ \r
+ This function flushes all modified data associated with a file to a device.\r
+\r
+ @param FileHandle The file handle on which to flush data\r
+\r
+ @retval EFI_SUCCESS The data was flushed.\r
+ @retval EFI_NO_MEDIA The device has no media.\r
+ @retval EFI_DEVICE_ERROR The device reported an error.\r
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+ @retval EFI_WRITE_PROTECTED The file or medium is write protected.\r
+ @retval EFI_ACCESS_DENIED The file was opened for read only.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellFlushFile (\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
+}\r
+\r
+/**\r
+ Retrieves the first file from a directory\r
+\r
+ This function opens a directory and gets the first file\92s info in the \r
+ directory. Caller can use ShellFindNextFile() to get other files. When \r
+ complete the caller is responsible for calling FreePool() on Buffer.\r
+\r
+ @param DirHandle The file handle of the directory to search\r
+ @param Buffer Pointer to buffer for file's information\r
+\r
+ @retval EFI_SUCCESS Found the first file.\r
+ @retval EFI_NOT_FOUND Cannot find the directory.\r
+ @retval EFI_NO_MEDIA The device has no media.\r
+ @retval EFI_DEVICE_ERROR The device reported an error.\r
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+ @return Others status of ShellGetFileInfo, ShellSetFilePosition,\r
+ or ShellReadFile\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellFindFirstFile (\r
+ IN EFI_FILE_HANDLE DirHandle,\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
+ //\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
+}\r
+/**\r
+ Retrieves the next file in a directory.\r
+\r
+ To use this function, caller must call the LibFindFirstFile() to get the \r
+ first file, and then use this function get other files. This function can be \r
+ called for several times to get each file's information in the directory. If \r
+ the call of ShellFindNextFile() got the last file in the directory, the next \r
+ call of this function has no file to get. *NoFile will be set to TRUE and the \r
+ Buffer memory will be automatically freed. \r
+\r
+ @param DirHandle the file handle of the directory\r
+ @param Buffer pointer to buffer for file's information\r
+ @param NoFile pointer to boolean when last file is found\r
+\r
+ @retval EFI_SUCCESS Found the next file, or reached last file\r
+ @retval EFI_NO_MEDIA The device has no media.\r
+ @retval EFI_DEVICE_ERROR The device reported an error.\r
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellFindNextFile(\r
+ IN EFI_FILE_HANDLE DirHandle,\r
+ OUT EFI_FILE_INFO *Buffer,\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
+ //\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
+}\r
+/**\r
+ Retrieve the size of a file.\r
+\r
+ if FileHandle is NULL then ASSERT()\r
+ if Size is NULL then ASSERT()\r
+\r
+ This function extracts the file size info from the FileHandle\92s EFI_FILE_INFO \r
+ data.\r
+\r
+ @param FileHandle file handle from which size is retrieved\r
+ @param Size pointer to size\r
+\r
+ @retval EFI_SUCCESS operation was completed sucessfully\r
+ @retval EFI_DEVICE_ERROR cannot access the file\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellGetFileSize (\r
+ IN EFI_FILE_HANDLE FileHandle,\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
+}\r
+/**\r
+ Retrieves the status of the break execution flag\r
+\r
+ this function is useful to check whether the application is being asked to halt by the shell.\r
+\r
+ @retval TRUE the execution break is enabled\r
+ @retval FALSE the execution break is not enabled\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+ShellGetExecutionBreakFlag(\r
+ VOID\r
+ )\r
+{\r
+ // \r
+ // Check for UEFI Shell 2.0 protocols\r
+ //\r
+ if (mEfiShellProtocol != NULL) {\r
+\r
+ //\r
+ // We are using UEFI Shell 2.0; see if the event has been triggered\r
+ //\r
+ if (gBS->CheckEvent(mEfiShellProtocol->ExecutionBreak) != EFI_SUCCESS) {\r
+ return (FALSE);\r
+ }\r
+ return (TRUE);\r
+ } \r
+\r
+ //\r
+ // using EFI Shell; call the function to check\r
+ //\r
+ ASSERT(mEfiShellEnvironment2 != NULL);\r
+ return (mEfiShellEnvironment2->GetExecutionBreak());\r
+}\r
+/**\r
+ return the value of an environment variable\r
+\r
+ this function gets the value of the environment variable set by the \r
+ ShellSetEnvironmentVariable function\r
+\r
+ @param EnvKey The key name of the environment variable.\r
+\r
+ @retval NULL the named environment variable does not exist.\r
+ @return != NULL pointer to the value of the environment variable\r
+**/\r
+CONST CHAR16*\r
+EFIAPI\r
+ShellGetEnvironmentVariable (\r
+ IN CHAR16 *EnvKey\r
+ )\r
+{\r
+ // \r
+ // Check for UEFI Shell 2.0 protocols\r
+ //\r
+ if (mEfiShellProtocol != NULL) {\r
+ return (mEfiShellProtocol->GetEnv(EnvKey));\r
+ }\r
+\r
+ //\r
+ // ASSERT that we must have EFI shell\r
+ //\r
+ ASSERT(mEfiShellEnvironment2 != NULL);\r
+\r
+ //\r
+ // using EFI Shell\r
+ //\r
+ return (mEfiShellEnvironment2->GetEnv(EnvKey));\r
+}\r
+/**\r
+ set the value of an environment variable\r
+\r
+This function changes the current value of the specified environment variable. If the\r
+environment variable exists and the Value is an empty string, then the environment\r
+variable is deleted. If the environment variable exists and the Value is not an empty\r
+string, then the value of the environment variable is changed. If the environment\r
+variable does not exist and the Value is an empty string, there is no action. If the\r
+environment variable does not exist and the Value is a non-empty string, then the\r
+environment variable is created and assigned the specified value.\r
+\r
+ This is not supported pre-UEFI Shell 2.0.\r
+\r
+ @param EnvKey The key name of the environment variable.\r
+ @param EnvVal The Value of the environment variable\r
+ @param Volatile Indicates whether the variable is non-volatile (FALSE) or volatile (TRUE).\r
+\r
+ @retval EFI_SUCCESS the operation was completed sucessfully\r
+ @retval EFI_UNSUPPORTED This operation is not allowed in pre UEFI 2.0 Shell environments\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellSetEnvironmentVariable (\r
+ IN CONST CHAR16 *EnvKey,\r
+ IN CONST CHAR16 *EnvVal,\r
+ IN BOOLEAN Volatile\r
+ )\r
+{\r
+ // \r
+ // Check for UEFI Shell 2.0 protocols\r
+ //\r
+ if (mEfiShellProtocol != NULL) {\r
+ return (mEfiShellProtocol->SetEnv(EnvKey, EnvVal, Volatile));\r
+ } \r
+\r
+ //\r
+ // This feature does not exist under EFI shell\r
+ //\r
+ return (EFI_UNSUPPORTED);\r
+}\r
+/**\r
+ cause the shell to parse and execute a command line.\r
+\r
+ This function creates a nested instance of the shell and executes the specified\r
+command (CommandLine) with the specified environment (Environment). Upon return,\r
+the status code returned by the specified command is placed in StatusCode.\r
+If Environment is NULL, then the current environment is used and all changes made\r
+by the commands executed will be reflected in the current environment. If the\r
+Environment is non-NULL, then the changes made will be discarded.\r
+The CommandLine is executed from the current working directory on the current\r
+device.\r
+\r
+EnvironmentVariables and Status are only supported for UEFI Shell 2.0.\r
+Output is only supported for pre-UEFI Shell 2.0\r
+\r
+ @param ImageHandle Parent image that is starting the operation\r
+ @param CommandLine pointer to null terminated command line.\r
+ @param Output true to display debug output. false to hide it.\r
+ @param EnvironmentVariables optional pointer to array of environment variables\r
+ in the form "x=y". if NULL current set is used.\r
+ @param Status the status of the run command line.\r
+\r
+ @retval EFI_SUCCESS the operation completed sucessfully. Status\r
+ contains the status code returned.\r
+ @retval EFI_INVALID_PARAMETER a parameter contains an invalid value\r
+ @retval EFI_OUT_OF_RESOURCES out of resources\r
+ @retval EFI_UNSUPPORTED the operation is not allowed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellExecute (\r
+ IN EFI_HANDLE *ParentHandle,\r
+ IN CHAR16 *CommandLine OPTIONAL,\r
+ IN BOOLEAN Output OPTIONAL,\r
+ IN CHAR16 **EnvironmentVariables OPTIONAL,\r
+ OUT EFI_STATUS *Status OPTIONAL\r
+ )\r
+{\r
+ // \r
+ // Check for UEFI Shell 2.0 protocols\r
+ //\r
+ if (mEfiShellProtocol != NULL) {\r
+ //\r
+ // Call UEFI Shell 2.0 version (not using Output parameter)\r
+ //\r
+ return (mEfiShellProtocol->Execute(ParentHandle,\r
+ CommandLine,\r
+ EnvironmentVariables,\r
+ Status));\r
+ } \r
+ //\r
+ // ASSERT that we must have EFI shell\r
+ //\r
+ ASSERT(mEfiShellEnvironment2 != NULL);\r
+ //\r
+ // Call EFI Shell version (not using EnvironmentVariables or Status parameters)\r
+ // Due to oddity in the EFI shell we want to dereference the ParentHandle here\r
+ //\r
+ return (mEfiShellEnvironment2->Execute(*ParentHandle, \r
+ CommandLine, \r
+ Output));\r
+}\r
+/**\r
+ Retreives the current directory path\r
+\r
+ If the DeviceName is NULL, it returns the current device\92s current directory \r
+ name. If the DeviceName is not NULL, it returns the current directory name \r
+ on specified drive.\r
+\r
+ @param DeviceName the name of the drive to get directory on\r
+\r
+ @retval NULL the directory does not exist\r
+ @return != NULL the directory\r
+**/\r
+CONST CHAR16*\r
+EFIAPI\r
+ShellGetCurrentDir (\r
+ IN CHAR16 *DeviceName OPTIONAL\r
+ )\r
+{\r
+ // \r
+ // Check for UEFI Shell 2.0 protocols\r
+ //\r
+ if (mEfiShellProtocol != NULL) {\r
+ return (mEfiShellProtocol->GetCurDir(DeviceName));\r
+ } \r
+ //\r
+ // ASSERT that we must have EFI shell\r
+ //\r
+ ASSERT(mEfiShellEnvironment2 != NULL);\r
+ return (mEfiShellEnvironment2->CurDir(DeviceName));\r
+}\r
+/**\r
+ sets (enabled or disabled) the page break mode\r
+\r
+ when page break mode is enabled the screen will stop scrolling \r
+ and wait for operator input before scrolling a subsequent screen.\r
+\r
+ @param CurrentState TRUE to enable and FALSE to disable\r
+**/\r
+VOID \r
+EFIAPI\r
+ShellSetPageBreakMode (\r
+ IN BOOLEAN CurrentState\r
+ )\r
+{\r
+ //\r
+ // check for enabling\r
+ //\r
+ if (CurrentState != 0x00) {\r
+ // \r
+ // check for UEFI Shell 2.0\r
+ //\r
+ if (mEfiShellProtocol != NULL) {\r
+ //\r
+ // Enable with UEFI 2.0 Shell\r
+ //\r
+ mEfiShellProtocol->EnablePageBreak();\r
+ return;\r
+ } else {\r
+ // \r
+ // ASSERT that must have EFI Shell\r
+ //\r
+ ASSERT(mEfiShellEnvironment2 != NULL);\r
+ //\r
+ // Enable with EFI Shell\r
+ //\r
+ mEfiShellEnvironment2->EnablePageBreak (DEFAULT_INIT_ROW, DEFAULT_AUTO_LF);\r
+ return;\r
+ }\r
+ } else {\r
+ // \r
+ // check for UEFI Shell 2.0\r
+ //\r
+ if (mEfiShellProtocol != NULL) {\r
+ //\r
+ // Disable with UEFI 2.0 Shell\r
+ //\r
+ mEfiShellProtocol->DisablePageBreak();\r
+ return;\r
+ } else {\r
+ // \r
+ // ASSERT that must have EFI Shell\r
+ //\r
+ ASSERT(mEfiShellEnvironment2 != NULL);\r
+ //\r
+ // Disable with EFI Shell\r
+ //\r
+ mEfiShellEnvironment2->DisablePageBreak ();\r
+ return;\r
+ }\r
+ }\r
+}\r
+\r
+///\r
+/// version of EFI_SHELL_FILE_INFO struct, except has no CONST pointers.\r
+/// This allows for the struct to be populated.\r
+///\r
+typedef struct {\r
+ EFI_LIST_ENTRY Link;\r
+ EFI_STATUS Status;\r
+ CHAR16 *FullName;\r
+ CHAR16 *FileName;\r
+ EFI_FILE_HANDLE Handle;\r
+ EFI_FILE_INFO *Info;\r
+} EFI_SHELL_FILE_INFO_NO_CONST;\r
+\r
+/**\r
+ Converts a EFI shell list of structures to the coresponding UEFI Shell 2.0 type of list.\r
+\r
+ if OldStyleFileList is NULL then ASSERT()\r
+\r
+ this function will convert a SHELL_FILE_ARG based list into a callee allocated \r
+ EFI_SHELL_FILE_INFO based list. it is up to the caller to free the memory via\r
+ the ShellCloseFileMetaArg function.\r
+\r
+ @param FileList the EFI shell list type\r
+\r
+ @retval the resultant head of the double linked new format list;\r
+**/\r
+LIST_ENTRY*\r
+EFIAPI\r
+InternalShellConvertFileListType (\r
+ EFI_LIST_ENTRY *FileList\r
+ )\r
+{\r
+ LIST_ENTRY *ListHead;\r
+ SHELL_FILE_ARG *OldInfo;\r
+ EFI_LIST_ENTRY *Link;\r
+ EFI_SHELL_FILE_INFO_NO_CONST *NewInfo;\r
+\r
+ //\r
+ // ASSERT that FileList is not NULL\r
+ //\r
+ ASSERT(FileList != NULL);\r
+\r
+ //\r
+ // Allocate our list head and initialize the list\r
+ //\r
+ ListHead = AllocateZeroPool(sizeof(EFI_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
+ OldInfo = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE);\r
+\r
+ //\r
+ // make sure the old list was valid\r
+ //\r
+ ASSERT(OldInfo != NULL); \r
+ ASSERT(OldInfo->Info != NULL);\r
+ ASSERT(OldInfo->FullName != NULL);\r
+ ASSERT(OldInfo->FileName != NULL);\r
+\r
+ //\r
+ // allocate a new EFI_SHELL_FILE_INFO object\r
+ //\r
+ NewInfo = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));\r
+ \r
+ // \r
+ // copy the simple items\r
+ //\r
+ NewInfo->Handle = OldInfo->Handle;\r
+ NewInfo->Status = OldInfo->Status;\r
+\r
+ //\r
+ // allocate new space to copy strings and structure\r
+ //\r
+ NewInfo->FullName = AllocateZeroPool(StrSize(OldInfo->FullName));\r
+ NewInfo->FileName = AllocateZeroPool(StrSize(OldInfo->FileName));\r
+ NewInfo->Info = AllocateZeroPool((UINTN)OldInfo->Info->Size);\r
+ \r
+ //\r
+ // make sure all the memory allocations were sucessful\r
+ //\r
+ ASSERT(NewInfo->FullName != NULL);\r
+ ASSERT(NewInfo->FileName != NULL);\r
+ ASSERT(NewInfo->Info != NULL);\r
+\r
+ //\r
+ // Copt the strings and structure\r
+ //\r
+ StrCpy(NewInfo->FullName, OldInfo->FullName);\r
+ StrCpy(NewInfo->FileName, OldInfo->FileName);\r
+ gBS->CopyMem (NewInfo->Info, OldInfo->Info, (UINTN)OldInfo->Info->Size);\r
+\r
+ //\r
+ // add that to the list\r
+ //\r
+ InsertTailList(ListHead, (LIST_ENTRY*)NewInfo);\r
+ }\r
+ return (ListHead);\r
+}\r
+/**\r
+ Opens a group of files based on a path.\r
+\r
+ This function uses the Arg to open all the matching files. Each matched \r
+ file has a SHELL_FILE_ARG structure to record the file information. These \r
+ structures are placed on the list ListHead. Users can get the SHELL_FILE_ARG \r
+ structures from ListHead to access each file. This function supports wildcards\r
+ and will process '?' and '*' as such. the list must be freed with a call to \r
+ ShellCloseFileMetaArg().\r
+\r
+ This function will fail if called sequentially without freeing the list in the middle.\r
+\r
+ @param Arg pointer to path string\r
+ @param OpenMode mode to open files with\r
+ @param ListHead head of linked list of results\r
+\r
+ @retval EFI_SUCCESS the operation was sucessful and the list head \r
+ contains the list of opened files\r
+ #retval EFI_UNSUPPORTED a previous ShellOpenFileMetaArg must be closed first.\r
+ *ListHead is set to NULL.\r
+ @return != EFI_SUCCESS the operation failed\r
+\r
+ @sa InternalShellConvertFileListType\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellOpenFileMetaArg (\r
+ IN CHAR16 *Arg,\r
+ IN UINT64 OpenMode,\r
+ IN OUT EFI_SHELL_FILE_INFO **ListHead\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
+ //\r
+ // ASSERT that Arg and ListHead are not NULL\r
+ //\r
+ ASSERT(Arg != NULL);\r
+ ASSERT(ListHead != NULL);\r
+\r
+ // \r
+ // Check for UEFI Shell 2.0 protocols\r
+ //\r
+ if (mEfiShellProtocol != NULL) {\r
+ return (mEfiShellProtocol->OpenFileList(Arg, \r
+ OpenMode, \r
+ ListHead));\r
+ } \r
+\r
+ //\r
+ // ASSERT that we must have EFI shell\r
+ //\r
+ ASSERT(mEfiShellEnvironment2 != NULL);\r
+\r
+ //\r
+ // allocate memory for old list head\r
+ //\r
+ mOldStyleFileList = (EFI_LIST_ENTRY*)AllocatePool(sizeof(EFI_LIST_ENTRY));\r
+ ASSERT(mOldStyleFileList != NULL);\r
+\r
+ //\r
+ // make sure the list head is initialized\r
+ //\r
+ InitializeListHead((LIST_ENTRY*)mOldStyleFileList);\r
+\r
+ //\r
+ // Get the EFI Shell list of files\r
+ //\r
+ Status = mEfiShellEnvironment2->FileMetaArg(Arg, mOldStyleFileList);\r
+ if (EFI_ERROR(Status)) {\r
+ *ListHead = NULL;\r
+ return (Status);\r
+ }\r
+\r
+ //\r
+ // Convert that to equivalent of UEFI Shell 2.0 structure\r
+ //\r
+ EmptyNode = InternalShellConvertFileListType(mOldStyleFileList);\r
+\r
+ //\r
+ // remove the empty head of the list\r
+ //\r
+ *ListHead = (EFI_SHELL_FILE_INFO*)RemoveEntryList(EmptyNode);\r
+ FreePool(EmptyNode); \r
+\r
+ return (Status);\r
+}\r
+/**\r
+ Free the linked list returned from ShellOpenFileMetaArg\r
+\r
+ if ListHead is NULL then ASSERT()\r
+\r
+ @param ListHead the pointer to free\r
+\r
+ @retval EFI_SUCCESS the operation was sucessful\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellCloseFileMetaArg (\r
+ IN OUT EFI_SHELL_FILE_INFO **ListHead\r
+ )\r
+{\r
+ LIST_ENTRY *Node;\r
+\r
+ //\r
+ // ASSERT that ListHead is not NULL\r
+ //\r
+ ASSERT(ListHead != NULL);\r
+\r
+ // \r
+ // Check for UEFI Shell 2.0 protocols\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
+ 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
+ FreePool((EFI_SHELL_FILE_INFO_NO_CONST*)Node);\r
+ }\r
+ return EFI_SUCCESS;\r
+ }\r
+}\r
+\r
+typedef struct {\r
+ EFI_LIST_ENTRY List;\r
+ CHAR16 *Name;\r
+ ParamType Type;\r
+ CHAR16 *Value;\r
+ UINTN OriginalPosition;\r
+} SHELL_PARAM_PACKAGE;\r
+\r
+/**\r
+ Checks the list of valid arguments and returns TRUE if the item was found. If the \r
+ return value is TRUE then the type parameter is set also.\r
+ \r
+ if CheckList is NULL then ASSERT();\r
+ if Name is NULL then ASSERT();\r
+ if Type is NULL then ASSERT();\r
+\r
+ @param Type pointer to type of parameter if it was found\r
+ @param Name pointer to Name of parameter found\r
+ @param CheckList List to check against\r
+\r
+ @retval TRUE the Parameter was found. Type is valid.\r
+ @retval FALSE the Parameter was not found. Type is not valid.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsCheckList (\r
+ IN CONST CHAR16 *Name,\r
+ IN CONST SHELL_PARAM_ITEM *CheckList,\r
+ OUT ParamType *Type\r
+ )\r
+{\r
+ SHELL_PARAM_ITEM *TempListItem;\r
+\r
+ //\r
+ // ASSERT that all 3 pointer parameters aren't NULL\r
+ //\r
+ ASSERT(CheckList != NULL);\r
+ ASSERT(Type != NULL);\r
+ ASSERT(Name != NULL);\r
+\r
+ //\r
+ // Enumerate through the list\r
+ //\r
+ for (TempListItem = (SHELL_PARAM_ITEM*)CheckList ; TempListItem->Name != NULL ; TempListItem++) {\r
+ //\r
+ // If the Name matches set the type and return TRUE\r
+ //\r
+ if (StrCmp(Name, TempListItem->Name) == 0) {\r
+ *Type = TempListItem->Type;\r
+ return (TRUE);\r
+ }\r
+ }\r
+ return (FALSE);\r
+}\r
+/**\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
+ @retval TRUE the Parameter is a flag.\r
+ @retval FALSE the Parameter not a flag\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsFlag (\r
+ IN CONST CHAR16 *Name\r
+ )\r
+{\r
+ //\r
+ // ASSERT that Name isn't NULL\r
+ //\r
+ ASSERT(Name != NULL);\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
+ return (TRUE);\r
+ }\r
+ return (FALSE);\r
+}\r
+\r
+/**\r
+ Checks the command line arguments passed against the list of valid ones. \r
+\r
+ If no initialization is required, then return RETURN_SUCCESS.\r
+ \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
+ @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
+\r
+ @retval EFI_SUCCESS The operation completed sucessfully.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed\r
+ @retval EFI_INVALID_PARAMETER A parameter was invalid\r
+ @retval EFI_VOLUME_CORRUPTED the command line was corrupt. an argument was \r
+ duplicated. the duplicated command line argument \r
+ was returned in ProblemParam if provided.\r
+ @retval EFI_NOT_FOUND a argument required a value that was missing. \r
+ the invalid command line argument was returned in\r
+ ProblemParam if provided.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InternalCommandLineParse (\r
+ IN CONST SHELL_PARAM_ITEM *CheckList,\r
+ OUT LIST_ENTRY **CheckPackage,\r
+ OUT CHAR16 **ProblemParam OPTIONAL,\r
+ IN BOOLEAN AutoPageBreak,\r
+ IN CONST CHAR16 **Argv,\r
+ IN UINTN Argc\r
+ )\r
+{\r
+ UINTN LoopCounter;\r
+ UINTN Count;\r
+ ParamType CurrentItemType;\r
+ SHELL_PARAM_PACKAGE *CurrentItemPackage;\r
+ BOOLEAN GetItemValue;\r
+\r
+ CurrentItemPackage = NULL;\r
+\r
+ //\r
+ // ASSERTs\r
+ //\r
+ ASSERT(CheckList != NULL);\r
+ ASSERT(Argv != NULL);\r
+\r
+ Count = 0;\r
+ GetItemValue = FALSE;\r
+\r
+ //\r
+ // If there is only 1 item we dont need to do anything\r
+ //\r
+ if (Argc <= 1) {\r
+ *CheckPackage = NULL;\r
+ return (EFI_SUCCESS);\r
+ }\r
+\r
+ //\r
+ // initialize the linked list\r
+ //\r
+ *CheckPackage = (LIST_ENTRY*)AllocateZeroPool(sizeof(LIST_ENTRY));\r
+ InitializeListHead(*CheckPackage);\r
+\r
+ //\r
+ // loop through each of the arguments\r
+ //\r
+ for (LoopCounter = 0 ; LoopCounter < Argc ; ++LoopCounter) {\r
+ if (Argv[LoopCounter] == NULL) {\r
+ //\r
+ // do nothing for NULL argv\r
+ //\r
+ } else if (GetItemValue == TRUE) {\r
+ ASSERT(CurrentItemPackage != NULL);\r
+ //\r
+ // get the item VALUE for the previous flag\r
+ //\r
+ GetItemValue = FALSE;\r
+ CurrentItemPackage->Value = AllocateZeroPool(StrSize(Argv[LoopCounter]));\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
+ //\r
+ // add this one as a non-flag\r
+ //\r
+ CurrentItemPackage = AllocatePool(sizeof(SHELL_PARAM_PACKAGE));\r
+ ASSERT(CurrentItemPackage != NULL);\r
+ CurrentItemPackage->Name = NULL;\r
+ CurrentItemPackage->Type = TypePosition;\r
+ CurrentItemPackage->Value = AllocatePool(StrSize(Argv[LoopCounter]));\r
+ ASSERT(CurrentItemPackage->Value != NULL);\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
+ //\r
+ // this is a flag\r
+ //\r
+ CurrentItemPackage = AllocatePool(sizeof(SHELL_PARAM_PACKAGE));\r
+ ASSERT(CurrentItemPackage != NULL);\r
+ CurrentItemPackage->Name = AllocatePool(StrSize(Argv[LoopCounter]));\r
+ ASSERT(CurrentItemPackage->Name != NULL);\r
+ StrCpy(CurrentItemPackage->Name, Argv[LoopCounter]);\r
+ CurrentItemPackage->Type = CurrentItemType;\r
+ CurrentItemPackage->OriginalPosition = (UINTN)(-1);\r
+\r
+ //\r
+ // Does this flag require a value\r
+ //\r
+ if (CurrentItemPackage->Type == TypeValue) {\r
+ //\r
+ // trigger the next loop to populate the value of this item\r
+ //\r
+ GetItemValue = TRUE; \r
+ } else {\r
+ //\r
+ // this item has no value expected; we are done\r
+ //\r
+ CurrentItemPackage->Value = NULL;\r
+ InsertTailList(*CheckPackage, (LIST_ENTRY*)CurrentItemPackage);\r
+ }\r
+ } else if (ProblemParam) {\r
+ //\r
+ // this was a non-recognised flag... error!\r
+ //\r
+ *ProblemParam = (CHAR16*)Argv[LoopCounter];\r
+ ShellCommandLineFreeVarList(*CheckPackage);\r
+ *CheckPackage = NULL;\r
+ return (EFI_VOLUME_CORRUPTED);\r
+ } else {\r
+ ShellCommandLineFreeVarList(*CheckPackage);\r
+ *CheckPackage = NULL;\r
+ return (EFI_VOLUME_CORRUPTED);\r
+ }\r
+ }\r
+ //\r
+ // support for AutoPageBreak\r
+ //\r
+ if (AutoPageBreak && ShellCommandLineGetFlag(*CheckPackage, L"-b")) {\r
+ ShellSetPageBreakMode(TRUE);\r
+ }\r
+ return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+ Checks the command line arguments passed against the list of valid ones. \r
+ Optionally removes NULL values first.\r
+ \r
+ If no initialization is required, then return RETURN_SUCCESS.\r
+ \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
+ @param AutoPageBreak will automatically set PageBreakEnabled for "b" parameter\r
+\r
+ @retval EFI_SUCCESS The operation completed sucessfully.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed\r
+ @retval EFI_INVALID_PARAMETER A parameter was invalid\r
+ @retval EFI_VOLUME_CORRUPTED the command line was corrupt. an argument was \r
+ duplicated. the duplicated command line argument \r
+ was returned in ProblemParam if provided.\r
+ @retval EFI_DEVICE_ERROR the commands contained 2 opposing arguments. one\r
+ of the command line arguments was returned in \r
+ ProblemParam if provided.\r
+ @retval EFI_NOT_FOUND a argument required a value that was missing. \r
+ the invalid command line argument was returned in\r
+ ProblemParam if provided.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellCommandLineParse (\r
+ IN CONST SHELL_PARAM_ITEM *CheckList,\r
+ OUT LIST_ENTRY **CheckPackage,\r
+ OUT CHAR16 **ProblemParam OPTIONAL,\r
+ IN BOOLEAN AutoPageBreak\r
+ )\r
+{\r
+ // \r
+ // ASSERT that CheckList and CheckPackage aren't NULL\r
+ //\r
+ ASSERT(CheckList != NULL);\r
+ ASSERT(CheckPackage != NULL);\r
+\r
+ // \r
+ // Check for UEFI Shell 2.0 protocols\r
+ //\r
+ if (mEfiShellParametersProtocol != NULL) {\r
+ return (InternalCommandLineParse(CheckList, \r
+ CheckPackage, \r
+ ProblemParam, \r
+ AutoPageBreak, \r
+ mEfiShellParametersProtocol->Argv,\r
+ mEfiShellParametersProtocol->Argc ));\r
+ }\r
+\r
+ // \r
+ // ASSERT That EFI Shell is not required\r
+ //\r
+ ASSERT (mEfiShellInterface != NULL);\r
+ return (InternalCommandLineParse(CheckList, \r
+ CheckPackage, \r
+ ProblemParam, \r
+ AutoPageBreak, \r
+ mEfiShellInterface->Argv,\r
+ mEfiShellInterface->Argc ));\r
+}\r
+\r
+/**\r
+ Frees shell variable list that was returned from ShellCommandLineParse.\r
+\r
+ This function will free all the memory that was used for the CheckPackage\r
+ list of postprocessed shell arguments.\r
+\r
+ this function has no return value.\r
+\r
+ if CheckPackage is NULL, then return\r
+\r
+ @param CheckPackage the list to de-allocate\r
+ **/\r
+VOID\r
+EFIAPI\r
+ShellCommandLineFreeVarList (\r
+ IN LIST_ENTRY *CheckPackage\r
+ )\r
+{\r
+ LIST_ENTRY *Node;\r
+\r
+ //\r
+ // check for CheckPackage == NULL\r
+ //\r
+ if (CheckPackage == NULL) {\r
+ return;\r
+ }\r
+\r
+ //\r
+ // for each node in the list\r
+ //\r
+ for (Node = GetFirstNode(CheckPackage); Node != CheckPackage ; Node = GetFirstNode(CheckPackage)) {\r
+ //\r
+ // Remove it from the list\r
+ //\r
+ RemoveEntryList(Node);\r
+\r
+ //\r
+ // if it has a name free the name\r
+ //\r
+ if (((SHELL_PARAM_PACKAGE*)Node)->Name != NULL) {\r
+ FreePool(((SHELL_PARAM_PACKAGE*)Node)->Name);\r
+ }\r
+\r
+ //\r
+ // if it has a value free the value\r
+ //\r
+ if (((SHELL_PARAM_PACKAGE*)Node)->Value != NULL) {\r
+ FreePool(((SHELL_PARAM_PACKAGE*)Node)->Value);\r
+ }\r
+ \r
+ //\r
+ // free the node structure\r
+ //\r
+ FreePool((SHELL_PARAM_PACKAGE*)Node);\r
+ }\r
+ //\r
+ // free the list head node\r
+ //\r
+ FreePool(CheckPackage);\r
+}\r
+/**\r
+ Checks for presence of a flag parameter\r
+\r
+ flag arguments are in the form of "-<Key>" or "/<Key>", but do not have a value following the key\r
+\r
+ if CheckPackage is NULL then return FALSE.\r
+ if KeyString is NULL then ASSERT()\r
+ \r
+ @param CheckPackage The package of parsed command line arguments\r
+ @param KeyString the Key of the command line argument to check for\r
+\r
+ @retval TRUE the flag is on the command line\r
+ @retval FALSE the flag is not on the command line\r
+ **/\r
+BOOLEAN\r
+EFIAPI\r
+ShellCommandLineGetFlag (\r
+ IN CONST LIST_ENTRY *CheckPackage,\r
+ IN CHAR16 *KeyString\r
+ )\r
+{\r
+ LIST_ENTRY *Node;\r
+\r
+ //\r
+ // ASSERT that both CheckPackage and KeyString aren't NULL\r
+ //\r
+ ASSERT(KeyString != NULL);\r
+\r
+ //\r
+ // return FALSE for no package\r
+ //\r
+ if (CheckPackage == NULL) {\r
+ return (FALSE);\r
+ }\r
+\r
+ //\r
+ // enumerate through the list of parametrs\r
+ //\r
+ for (Node = GetFirstNode(CheckPackage) ; Node != CheckPackage ; Node = GetNextNode(CheckPackage, Node) ) {\r
+ //\r
+ // If the Name matches, return TRUE (and there may be NULL name)\r
+ //\r
+ if (((SHELL_PARAM_PACKAGE*)Node)->Name != NULL) {\r
+ if (StrCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {\r
+ return (TRUE);\r
+ }\r
+ }\r
+ }\r
+ return (FALSE);\r
+}\r
+/**\r
+ returns value from command line argument\r
+\r
+ value parameters are in the form of "-<Key> value" or "/<Key> value"\r
+ \r
+ if CheckPackage is NULL, then return NULL;\r
+\r
+ @param CheckPackage The package of parsed command line arguments\r
+ @param KeyString the Key of the command line argument to check for\r
+\r
+ @retval NULL the flag is not on the command line\r
+ @return !=NULL pointer to unicode string of the value\r
+ **/\r
+CONST CHAR16*\r
+EFIAPI\r
+ShellCommandLineGetValue (\r
+ IN CONST LIST_ENTRY *CheckPackage,\r
+ IN CHAR16 *KeyString\r
+ )\r
+{\r
+ LIST_ENTRY *Node;\r
+\r
+ //\r
+ // check for CheckPackage == NULL\r
+ //\r
+ if (CheckPackage == NULL) {\r
+ return (NULL);\r
+ }\r
+\r
+ //\r
+ // enumerate through the list of parametrs\r
+ //\r
+ for (Node = GetFirstNode(CheckPackage) ; Node != NULL ; Node = GetNextNode(CheckPackage, Node) ) {\r
+ //\r
+ // If the Name matches, return the value (name can be NULL)\r
+ //\r
+ if (((SHELL_PARAM_PACKAGE*)Node)->Name != NULL) {\r
+ if (StrCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {\r
+ return (((SHELL_PARAM_PACKAGE*)Node)->Value);\r
+ }\r
+ }\r
+ }\r
+ return (NULL);\r
+}\r
+/**\r
+ returns raw value from command line argument\r
+\r
+ raw value parameters are in the form of "value" in a specific position in the list\r
+ \r
+ if CheckPackage is NULL, then return NULL;\r
+\r
+ @param CheckPackage The package of parsed command line arguments\r
+ @param Position the position of the value \r
+\r
+ @retval NULL the flag is not on the command line\r
+ @return !=NULL pointer to unicode string of the value\r
+ **/\r
+CONST CHAR16*\r
+EFIAPI\r
+ShellCommandLineGetRawValue (\r
+ IN CONST LIST_ENTRY *CheckPackage,\r
+ IN UINT32 Position\r
+ )\r
+{\r
+ LIST_ENTRY *Node;\r
+\r
+ //\r
+ // check for CheckPackage == NULL\r
+ //\r
+ if (CheckPackage == NULL) {\r
+ return (NULL);\r
+ }\r
+\r
+ //\r
+ // enumerate through the list of parametrs\r
+ //\r
+ for (Node = GetFirstNode(CheckPackage) ; Node != NULL ; Node = GetNextNode(CheckPackage, Node) ) {\r
+ //\r
+ // If the position matches, return the value\r
+ //\r
+ if (((SHELL_PARAM_PACKAGE*)Node)->OriginalPosition == Position) {\r
+ return (((SHELL_PARAM_PACKAGE*)Node)->Value);\r
+ }\r
+ }\r
+ return (NULL);\r
+}
\ No newline at end of file