From: jcarsey Date: Mon, 15 Jun 2009 23:43:34 +0000 (+0000) Subject: git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@8562 6f19259b... X-Git-Tag: edk2-stable201903~17741 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=614326e62b61f71663ae7e8c6bf9b7c7b4221483;hp=08d7f8e83d17646d6170819fcb9ae1e17eb6199a git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@8562 6f19259b-4bc3-4df7-8a09-765794883524 --- diff --git a/ShellPkg/Library/BaseShellLib/BaseShellLib.c b/ShellPkg/Library/BaseShellLib/BaseShellLib.c deleted file mode 100644 index 1ddff9a2a0..0000000000 --- a/ShellPkg/Library/BaseShellLib/BaseShellLib.c +++ /dev/null @@ -1,1939 +0,0 @@ -/** @file - Provides interface to shell functionality for shell commands and applications. - -Copyright (c) 2006 - 2009, Intel Corporation -All rights reserved. This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "BaseShellLib.h" - -#define MAX_FILE_NAME_LEN 522 // (20 * (6+5+2))+1) unicode characters from EFI FAT spec (doubled for bytes) -#define FIND_XXXXX_FILE_BUFFER_SIZE (SIZE_OF_EFI_FILE_INFO + MAX_FILE_NAME_LEN) - -// -// This is not static since it's extern in the .h file -// -SHELL_PARAM_ITEM EmptyParamList[] = { - {NULL, TypeMax} - }; - -// -// Static file globals for the shell library -// -STATIC EFI_SHELL_ENVIRONMENT2 *mEfiShellEnvironment2; -STATIC EFI_SHELL_INTERFACE *mEfiShellInterface; -STATIC EFI_SHELL_PROTOCOL *mEfiShellProtocol; -STATIC EFI_SHELL_PARAMETERS_PROTOCOL *mEfiShellParametersProtocol; -STATIC EFI_HANDLE mEfiShellEnvironment2Handle; -STATIC FILE_HANDLE_FUNCTION_MAP FileFunctionMap; - -/** - helper function to find ShellEnvironment2 for constructor -**/ -EFI_STATUS -EFIAPI -ShellFindSE2 ( - IN EFI_HANDLE ImageHandle - ) -{ - EFI_STATUS Status; - EFI_HANDLE *Buffer; - UINTN BufferSize; - UINTN HandleIndex; - - BufferSize = 0; - Buffer = NULL; - Status = gBS->OpenProtocol(ImageHandle, - &gEfiShellEnvironment2Guid, - (VOID **)&mEfiShellEnvironment2, - ImageHandle, - NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - // - // look for the mEfiShellEnvironment2 protocol at a higher level - // - if (EFI_ERROR (Status) || !(CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid) != FALSE && - (mEfiShellEnvironment2->MajorVersion > EFI_SHELL_MAJOR_VER || - (mEfiShellEnvironment2->MajorVersion == EFI_SHELL_MAJOR_VER && mEfiShellEnvironment2->MinorVersion >= EFI_SHELL_MINOR_VER)))) { - // - // figure out how big of a buffer we need. - // - Status = gBS->LocateHandle (ByProtocol, - &gEfiShellEnvironment2Guid, - NULL, // ignored for ByProtocol - &BufferSize, - Buffer - ); - ASSERT(Status == EFI_BUFFER_TOO_SMALL); - Buffer = (EFI_HANDLE*)AllocatePool(BufferSize); - ASSERT(Buffer != NULL); - Status = gBS->LocateHandle (ByProtocol, - &gEfiShellEnvironment2Guid, - NULL, // ignored for ByProtocol - &BufferSize, - Buffer - ); - if (!EFI_ERROR (Status)) { - // - // now parse the list of returned handles - // - Status = EFI_NOT_FOUND; - for (HandleIndex = 0; HandleIndex < (BufferSize/sizeof(Buffer[0])); HandleIndex++) { - Status = gBS->OpenProtocol(Buffer[HandleIndex], - &gEfiShellEnvironment2Guid, - (VOID **)&mEfiShellEnvironment2, - ImageHandle, - NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid) != FALSE && - (mEfiShellEnvironment2->MajorVersion > EFI_SHELL_MAJOR_VER || - (mEfiShellEnvironment2->MajorVersion == EFI_SHELL_MAJOR_VER && mEfiShellEnvironment2->MinorVersion >= EFI_SHELL_MINOR_VER))) { - mEfiShellEnvironment2Handle = Buffer[HandleIndex]; - Status = EFI_SUCCESS; - break; - } - } - } - } - if (Buffer != NULL) { - FreePool (Buffer); - } - return (Status); -} - -EFI_STATUS -EFIAPI -ShellLibConstructorWorker ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable -){ - EFI_STATUS Status; - - // - // UEFI 2.0 shell interfaces (used preferentially) - // - Status = gBS->OpenProtocol(ImageHandle, - &gEfiShellProtocolGuid, - (VOID **)&mEfiShellProtocol, - ImageHandle, - NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR(Status)) { - mEfiShellProtocol = NULL; - } - Status = gBS->OpenProtocol(ImageHandle, - &gEfiShellParametersProtocolGuid, - (VOID **)&mEfiShellParametersProtocol, - ImageHandle, - NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR(Status)) { - mEfiShellParametersProtocol = NULL; - } - - if (mEfiShellParametersProtocol == NULL || mEfiShellProtocol == NULL) { - // - // Moved to seperate function due to complexity - // - Status = ShellFindSE2(ImageHandle); - - if (EFI_ERROR(Status)) { - DEBUG((DEBUG_ERROR, "Status: 0x%08x\r\n", Status)); - mEfiShellEnvironment2 = NULL; - } - Status = gBS->OpenProtocol(ImageHandle, - &gEfiShellInterfaceGuid, - (VOID **)&mEfiShellInterface, - ImageHandle, - NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR(Status)) { - mEfiShellInterface = NULL; - } - } - // - // only success getting 2 of either the old or new, but no 1/2 and 1/2 - // - if ((mEfiShellEnvironment2 != NULL && mEfiShellInterface != NULL) || - (mEfiShellProtocol != NULL && mEfiShellParametersProtocol != NULL) ) { - if (mEfiShellProtocol != NULL) { - FileFunctionMap.GetFileInfo = mEfiShellProtocol->GetFileInfo; - FileFunctionMap.SetFileInfo = mEfiShellProtocol->SetFileInfo; - FileFunctionMap.ReadFile = mEfiShellProtocol->ReadFile; - FileFunctionMap.WriteFile = mEfiShellProtocol->WriteFile; - FileFunctionMap.CloseFile = mEfiShellProtocol->CloseFile; - FileFunctionMap.DeleteFile = mEfiShellProtocol->DeleteFile; - FileFunctionMap.GetFilePosition = mEfiShellProtocol->GetFilePosition; - FileFunctionMap.SetFilePosition = mEfiShellProtocol->SetFilePosition; - FileFunctionMap.FlushFile = mEfiShellProtocol->FlushFile; - FileFunctionMap.GetFileSize = mEfiShellProtocol->GetFileSize; - } else { - FileFunctionMap.GetFileInfo = FileHandleGetInfo; - FileFunctionMap.SetFileInfo = FileHandleSetInfo; - FileFunctionMap.ReadFile = FileHandleRead; - FileFunctionMap.WriteFile = FileHandleWrite; - FileFunctionMap.CloseFile = FileHandleClose; - FileFunctionMap.DeleteFile = FileHandleDelete; - FileFunctionMap.GetFilePosition = FileHandleGetPosition; - FileFunctionMap.SetFilePosition = FileHandleSetPosition; - FileFunctionMap.FlushFile = FileHandleFlush; - FileFunctionMap.GetFileSize = FileHandleGetSize; - } - return (EFI_SUCCESS); - } - return (EFI_NOT_FOUND); -} -/** - Constructor for the Shell library. - - Initialize the library and determine if the underlying is a UEFI Shell 2.0 or an EFI shell. - - @param ImageHandle the image handle of the process - @param SystemTable the EFI System Table pointer - - @retval EFI_SUCCESS the initialization was complete sucessfully - @return others an error ocurred during initialization -**/ -EFI_STATUS -EFIAPI -ShellLibConstructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - - - mEfiShellEnvironment2 = NULL; - mEfiShellProtocol = NULL; - mEfiShellParametersProtocol = NULL; - mEfiShellInterface = NULL; - mEfiShellEnvironment2Handle = NULL; - - ///@todo make a worker constructor so initialize function works - // - // verify that auto initialize is not set false - // - if (PcdGetBool(PcdShellLibAutoInitialize) == 0) { - return (EFI_SUCCESS); - } - - return (ShellLibConstructorWorker(ImageHandle, SystemTable)); -} - -/** - Destructory for the library. free any resources. -**/ -EFI_STATUS -EFIAPI -ShellLibDestructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - if (mEfiShellEnvironment2 != NULL) { - gBS->CloseProtocol(mEfiShellEnvironment2Handle==NULL?ImageHandle:mEfiShellEnvironment2Handle, - &gEfiShellEnvironment2Guid, - ImageHandle, - NULL); - mEfiShellEnvironment2 = NULL; - } - if (mEfiShellInterface != NULL) { - gBS->CloseProtocol(ImageHandle, - &gEfiShellInterfaceGuid, - ImageHandle, - NULL); - mEfiShellInterface = NULL; - } - if (mEfiShellProtocol != NULL) { - gBS->CloseProtocol(ImageHandle, - &gEfiShellProtocolGuid, - ImageHandle, - NULL); - mEfiShellProtocol = NULL; - } - if (mEfiShellParametersProtocol != NULL) { - gBS->CloseProtocol(ImageHandle, - &gEfiShellParametersProtocolGuid, - ImageHandle, - NULL); - mEfiShellParametersProtocol = NULL; - } - mEfiShellEnvironment2Handle = NULL; - return (EFI_SUCCESS); -} - -/** - This function causes the shell library to initialize itself. If the shell library - is already initialized it will de-initialize all the current protocol poitners and - re-populate them again. - - When the library is used with PcdShellLibAutoInitialize set to true this function - will return EFI_SUCCESS and perform no actions. - - This function is intended for internal access for shell commands only. - - @retval EFI_SUCCESS the initialization was complete sucessfully - -**/ -EFI_STATUS -EFIAPI -ShellInitialize ( - ) { - // - // if auto initialize is not false then skip - // - if (PcdGetBool(PcdShellLibAutoInitialize) != 0) { - return (EFI_SUCCESS); - } - - // - // deinit the current stuff - // - ASSERT_EFI_ERROR(ShellLibDestructor(gImageHandle, gST)); - - // - // init the new stuff - // - return (ShellLibConstructorWorker(gImageHandle, gST)); -} - -/** - This function will retrieve the information about the file for the handle - specified and store it in allocated pool memory. - - This function allocates a buffer to store the file's information. It is the - caller's responsibility to free the buffer - - @param FileHandle The file handle of the file for which information is - being requested. - - @retval NULL information could not be retrieved. - - @return the information about the file -**/ -EFI_FILE_INFO* -EFIAPI -ShellGetFileInfo ( - IN EFI_FILE_HANDLE FileHandle - ) -{ - return (FileFunctionMap.GetFileInfo(FileHandle)); -} - -/** - This function will set the information about the file for the opened handle - specified. - - @param FileHandle The file handle of the file for which information - is being set - - @param FileInfo The infotmation to set. - - @retval EFI_SUCCESS The information was set. - @retval EFI_UNSUPPORTED The InformationType is not known. - @retval EFI_NO_MEDIA The device has no medium. - @retval EFI_DEVICE_ERROR The device reported an error. - @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. - @retval EFI_WRITE_PROTECTED The file or medium is write protected. - @retval EFI_ACCESS_DENIED The file was opened read only. - @retval EFI_VOLUME_FULL The volume is full. -**/ -EFI_STATUS -EFIAPI -ShellSetFileInfo ( - IN EFI_FILE_HANDLE FileHandle, - IN EFI_FILE_INFO *FileInfo - ) -{ - return (FileFunctionMap.SetFileInfo(FileHandle, FileInfo)); -} - - /** - This function will open a file or directory referenced by DevicePath. - - This function opens a file with the open mode according to the file path. The - Attributes is valid only for EFI_FILE_MODE_CREATE. - - @param FilePath on input the device path to the file. On output - the remaining device path. - @param DeviceHandle pointer to the system device handle. - @param FileHandle pointer to the file handle. - @param OpenMode the mode to open the file with. - @param Attributes the file's file attributes. - - @retval EFI_SUCCESS The information was set. - @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. - @retval EFI_UNSUPPORTED Could not open the file path. - @retval EFI_NOT_FOUND The specified file could not be found on the - device or the file system could not be found on - the device. - @retval EFI_NO_MEDIA The device has no medium. - @retval EFI_MEDIA_CHANGED The device has a different medium in it or the - medium is no longer supported. - @retval EFI_DEVICE_ERROR The device reported an error. - @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. - @retval EFI_WRITE_PROTECTED The file or medium is write protected. - @retval EFI_ACCESS_DENIED The file was opened read only. - @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the - file. - @retval EFI_VOLUME_FULL The volume is full. -**/ -EFI_STATUS -EFIAPI -ShellOpenFileByDevicePath( - IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath, - OUT EFI_HANDLE *DeviceHandle, - OUT EFI_FILE_HANDLE *FileHandle, - IN UINT64 OpenMode, - IN UINT64 Attributes - ) -{ - CHAR16 *FileName; - EFI_STATUS Status; - EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol; - EFI_FILE_HANDLE LastHandle; - - // - // ASERT for FileHandle, FilePath, and DeviceHandle being NULL - // - ASSERT(FilePath != NULL); - ASSERT(FileHandle != NULL); - ASSERT(DeviceHandle != NULL); - // - // which shell interface should we use - // - if (mEfiShellProtocol != NULL) { - // - // use UEFI Shell 2.0 method. - // - FileName = mEfiShellProtocol->GetFilePathFromDevicePath(*FilePath); - if (FileName == NULL) { - return (EFI_INVALID_PARAMETER); - } - Status = ShellOpenFileByName(FileName, FileHandle, OpenMode, Attributes); - FreePool(FileName); - return (Status); - } - - - // - // use old shell method. - // - Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, - FilePath, - DeviceHandle); - if (EFI_ERROR (Status)) { - return Status; - } - Status = gBS->OpenProtocol(*DeviceHandle, - &gEfiSimpleFileSystemProtocolGuid, - (VOID**) &EfiSimpleFileSystemProtocol, - gImageHandle, - NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL); - if (EFI_ERROR (Status)) { - return Status; - } - Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, FileHandle); - if (EFI_ERROR (Status)) { - FileHandle = NULL; - return Status; - } - - // - // go down directories one node at a time. - // - while (!IsDevicePathEnd (*FilePath)) { - // - // For file system access each node should be a file path component - // - if (DevicePathType (*FilePath) != MEDIA_DEVICE_PATH || - DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP - ) { - FileHandle = NULL; - return (EFI_INVALID_PARAMETER); - } - // - // Open this file path node - // - LastHandle = *FileHandle; - *FileHandle = NULL; - - // - // Try to test opening an existing file - // - Status = LastHandle->Open ( - LastHandle, - FileHandle, - ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName, - OpenMode &~EFI_FILE_MODE_CREATE, - 0 - ); - - // - // see if the error was that it needs to be created - // - if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) { - Status = LastHandle->Open ( - LastHandle, - FileHandle, - ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName, - OpenMode, - Attributes - ); - } - // - // Close the last node - // - LastHandle->Close (LastHandle); - - if (EFI_ERROR(Status)) { - return (Status); - } - - // - // Get the next node - // - *FilePath = NextDevicePathNode (*FilePath); - } - return (EFI_SUCCESS); -} - -/** - This function will open a file or directory referenced by filename. - - If return is EFI_SUCCESS, the Filehandle is the opened file's handle; - otherwise, the Filehandle is NULL. The Attributes is valid only for - EFI_FILE_MODE_CREATE. - - if FileNAme is NULL then ASSERT() - - @param FileName pointer to file name - @param FileHandle pointer to the file handle. - @param OpenMode the mode to open the file with. - @param Attributes the file's file attributes. - - @retval EFI_SUCCESS The information was set. - @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. - @retval EFI_UNSUPPORTED Could not open the file path. - @retval EFI_NOT_FOUND The specified file could not be found on the - device or the file system could not be found - on the device. - @retval EFI_NO_MEDIA The device has no medium. - @retval EFI_MEDIA_CHANGED The device has a different medium in it or the - medium is no longer supported. - @retval EFI_DEVICE_ERROR The device reported an error. - @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. - @retval EFI_WRITE_PROTECTED The file or medium is write protected. - @retval EFI_ACCESS_DENIED The file was opened read only. - @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the - file. - @retval EFI_VOLUME_FULL The volume is full. -**/ -EFI_STATUS -EFIAPI -ShellOpenFileByName( - IN CHAR16 *FileName, - OUT EFI_FILE_HANDLE *FileHandle, - IN UINT64 OpenMode, - IN UINT64 Attributes - ) -{ - EFI_HANDLE DeviceHandle; - EFI_DEVICE_PATH_PROTOCOL *FilePath; - - // - // ASSERT if FileName is NULL - // - ASSERT(FileName != NULL); - - if (mEfiShellProtocol != NULL) { - // - // Use UEFI Shell 2.0 method - // - return (mEfiShellProtocol->OpenFileByName(FileName, - FileHandle, - OpenMode)); - - ///@todo add the attributes - } - // - // Using EFI Shell version - // this means convert name to path and call that function - // since this will use EFI method again that will open it. - // - ASSERT(mEfiShellEnvironment2 != NULL); - FilePath = mEfiShellEnvironment2->NameToPath (FileName); - if (FileDevicePath != NULL) { - return (ShellOpenFileByDevicePath(&FilePath, - &DeviceHandle, - FileHandle, - OpenMode, - Attributes )); - } - return (EFI_DEVICE_ERROR); -} -/** - This function create a directory - - If return is EFI_SUCCESS, the Filehandle is the opened directory's handle; - otherwise, the Filehandle is NULL. If the directory already existed, this - function opens the existing directory. - - @param DirectoryName pointer to directory name - @param FileHandle pointer to the file handle. - - @retval EFI_SUCCESS The information was set. - @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. - @retval EFI_UNSUPPORTED Could not open the file path. - @retval EFI_NOT_FOUND The specified file could not be found on the - device or the file system could not be found - on the device. - @retval EFI_NO_MEDIA The device has no medium. - @retval EFI_MEDIA_CHANGED The device has a different medium in it or the - medium is no longer supported. - @retval EFI_DEVICE_ERROR The device reported an error. - @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. - @retval EFI_WRITE_PROTECTED The file or medium is write protected. - @retval EFI_ACCESS_DENIED The file was opened read only. - @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the - file. - @retval EFI_VOLUME_FULL The volume is full. - @sa ShellOpenFileByName -**/ -EFI_STATUS -EFIAPI -ShellCreateDirectory( - IN CHAR16 *DirectoryName, - OUT EFI_FILE_HANDLE *FileHandle - ) -{ - // - // this is a pass thru to the open file function with sepcific open mode and attributes - // - return (ShellOpenFileByName(DirectoryName, - FileHandle, - EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, - EFI_FILE_DIRECTORY - )); -} - -/** - This function reads information from an opened file. - - If FileHandle is not a directory, the function reads the requested number of - bytes from the file at the file's current position and returns them in Buffer. - If the read goes beyond the end of the file, the read length is truncated to the - end of the file. The file's current position is increased by the number of bytes - returned. If FileHandle is a directory, the function reads the directory entry - at the file's current position and returns the entry in Buffer. If the Buffer - is not large enough to hold the current directory entry, then - EFI_BUFFER_TOO_SMALL is returned and the current file position is not updated. - BufferSize is set to be the size of the buffer needed to read the entry. On - success, the current position is updated to the next directory entry. If there - are no more directory entries, the read returns a zero-length buffer. - EFI_FILE_INFO is the structure returned as the directory entry. - - @param FileHandle the opened file handle - @param BufferSize on input the size of buffer in bytes. on return - the number of bytes written. - @param Buffer the buffer to put read data into. - - @retval EFI_SUCCESS Data was read. - @retval EFI_NO_MEDIA The device has no media. - @retval EFI_DEVICE_ERROR The device reported an error. - @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. - @retval EFI_BUFFER_TO_SMALL Buffer is too small. ReadSize contains required - size. - -**/ -EFI_STATUS -EFIAPI -ShellReadFile( - IN EFI_FILE_HANDLE FileHandle, - IN OUT UINTN *BufferSize, - OUT VOID *Buffer - ) -{ - return (FileFunctionMap.ReadFile(FileHandle, BufferSize, Buffer)); -} - - -/** - Write data to a file. - - This function writes the specified number of bytes to the file at the current - file position. The current file position is advanced the actual number of bytes - written, which is returned in BufferSize. Partial writes only occur when there - has been a data error during the write attempt (such as "volume space full"). - The file is automatically grown to hold the data if required. Direct writes to - opened directories are not supported. - - @param FileHandle The opened file for writing - @param BufferSize on input the number of bytes in Buffer. On output - the number of bytes written. - @param Buffer the buffer containing data to write is stored. - - @retval EFI_SUCCESS Data was written. - @retval EFI_UNSUPPORTED Writes to an open directory are not supported. - @retval EFI_NO_MEDIA The device has no media. - @retval EFI_DEVICE_ERROR The device reported an error. - @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. - @retval EFI_WRITE_PROTECTED The device is write-protected. - @retval EFI_ACCESS_DENIED The file was open for read only. - @retval EFI_VOLUME_FULL The volume is full. -**/ -EFI_STATUS -EFIAPI -ShellWriteFile( - IN EFI_FILE_HANDLE FileHandle, - IN OUT UINTN *BufferSize, - IN VOID *Buffer - ) -{ - return (FileFunctionMap.WriteFile(FileHandle, BufferSize, Buffer)); -} - -/** - Close an open file handle. - - This function closes a specified file handle. All "dirty" cached file data is - flushed to the device, and the file is closed. In all cases the handle is - closed. - -@param FileHandle the file handle to close. - -@retval EFI_SUCCESS the file handle was closed sucessfully. -**/ -EFI_STATUS -EFIAPI -ShellCloseFile ( - IN EFI_FILE_HANDLE *FileHandle - ) -{ - return (FileFunctionMap.CloseFile(*FileHandle)); -} - -/** - Delete a file and close the handle - - This function closes and deletes a file. In all cases the file handle is closed. - If the file cannot be deleted, the warning code EFI_WARN_DELETE_FAILURE is - returned, but the handle is still closed. - - @param FileHandle the file handle to delete - - @retval EFI_SUCCESS the file was closed sucessfully - @retval EFI_WARN_DELETE_FAILURE the handle was closed, but the file was not - deleted - @retval INVALID_PARAMETER One of the parameters has an invalid value. -**/ -EFI_STATUS -EFIAPI -ShellDeleteFile ( - IN EFI_FILE_HANDLE *FileHandle - ) -{ - return (FileFunctionMap.DeleteFile(*FileHandle)); -} - -/** - Set the current position in a file. - - This function sets the current file position for the handle to the position - supplied. With the exception of seeking to position 0xFFFFFFFFFFFFFFFF, only - absolute positioning is supported, and seeking past the end of the file is - allowed (a subsequent write would grow the file). Seeking to position - 0xFFFFFFFFFFFFFFFF causes the current position to be set to the end of the file. - If FileHandle is a directory, the only position that may be set is zero. This - has the effect of starting the read process of the directory entries over. - - @param FileHandle The file handle on which the position is being set - @param Position Byte position from begining of file - - @retval EFI_SUCCESS Operation completed sucessfully. - @retval EFI_UNSUPPORTED the seek request for non-zero is not valid on - directories. - @retval INVALID_PARAMETER One of the parameters has an invalid value. -**/ -EFI_STATUS -EFIAPI -ShellSetFilePosition ( - IN EFI_FILE_HANDLE FileHandle, - IN UINT64 Position - ) -{ - return (FileFunctionMap.SetFilePosition(FileHandle, Position)); -} - -/** - Gets a file's current position - - This function retrieves the current file position for the file handle. For - directories, the current file position has no meaning outside of the file - system driver and as such the operation is not supported. An error is returned - if FileHandle is a directory. - - @param FileHandle The open file handle on which to get the position. - @param Position Byte position from begining of file. - - @retval EFI_SUCCESS the operation completed sucessfully. - @retval INVALID_PARAMETER One of the parameters has an invalid value. - @retval EFI_UNSUPPORTED the request is not valid on directories. -**/ -EFI_STATUS -EFIAPI -ShellGetFilePosition ( - IN EFI_FILE_HANDLE FileHandle, - OUT UINT64 *Position - ) -{ - return (FileFunctionMap.GetFilePosition(FileHandle, Position)); -} -/** - Flushes data on a file - - This function flushes all modified data associated with a file to a device. - - @param FileHandle The file handle on which to flush data - - @retval EFI_SUCCESS The data was flushed. - @retval EFI_NO_MEDIA The device has no media. - @retval EFI_DEVICE_ERROR The device reported an error. - @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. - @retval EFI_WRITE_PROTECTED The file or medium is write protected. - @retval EFI_ACCESS_DENIED The file was opened for read only. -**/ -EFI_STATUS -EFIAPI -ShellFlushFile ( - IN EFI_FILE_HANDLE FileHandle - ) -{ - return (FileFunctionMap.FlushFile(FileHandle)); -} - -/** - Retrieves the first file from a directory - - This function opens a directory and gets the first file's info in the - directory. Caller can use ShellFindNextFile() to get other files. When - complete the caller is responsible for calling FreePool() on Buffer. - - @param DirHandle The file handle of the directory to search - @param Buffer Pointer to buffer for file's information - - @retval EFI_SUCCESS Found the first file. - @retval EFI_NOT_FOUND Cannot find the directory. - @retval EFI_NO_MEDIA The device has no media. - @retval EFI_DEVICE_ERROR The device reported an error. - @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. - @return Others status of ShellGetFileInfo, ShellSetFilePosition, - or ShellReadFile -**/ -EFI_STATUS -EFIAPI -ShellFindFirstFile ( - IN EFI_FILE_HANDLE DirHandle, - OUT EFI_FILE_INFO **Buffer - ) -{ - // - // pass to file handle lib - // - return (FileHandleFindFirstFile(DirHandle, Buffer)); -} -/** - Retrieves the next file in a directory. - - To use this function, caller must call the LibFindFirstFile() to get the - first file, and then use this function get other files. This function can be - called for several times to get each file's information in the directory. If - the call of ShellFindNextFile() got the last file in the directory, the next - call of this function has no file to get. *NoFile will be set to TRUE and the - Buffer memory will be automatically freed. - - @param DirHandle the file handle of the directory - @param Buffer pointer to buffer for file's information - @param NoFile pointer to boolean when last file is found - - @retval EFI_SUCCESS Found the next file, or reached last file - @retval EFI_NO_MEDIA The device has no media. - @retval EFI_DEVICE_ERROR The device reported an error. - @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. -**/ -EFI_STATUS -EFIAPI -ShellFindNextFile( - IN EFI_FILE_HANDLE DirHandle, - OUT EFI_FILE_INFO *Buffer, - OUT BOOLEAN *NoFile - ) -{ - // - // pass to file handle lib - // - return (FileHandleFindNextFile(DirHandle, Buffer, NoFile)); -} -/** - Retrieve the size of a file. - - if FileHandle is NULL then ASSERT() - if Size is NULL then ASSERT() - - This function extracts the file size info from the FileHandle's EFI_FILE_INFO - data. - - @param FileHandle file handle from which size is retrieved - @param Size pointer to size - - @retval EFI_SUCCESS operation was completed sucessfully - @retval EFI_DEVICE_ERROR cannot access the file -**/ -EFI_STATUS -EFIAPI -ShellGetFileSize ( - IN EFI_FILE_HANDLE FileHandle, - OUT UINT64 *Size - ) -{ - return (FileFunctionMap.GetFileSize(FileHandle, Size)); -} -/** - Retrieves the status of the break execution flag - - this function is useful to check whether the application is being asked to halt by the shell. - - @retval TRUE the execution break is enabled - @retval FALSE the execution break is not enabled -**/ -BOOLEAN -EFIAPI -ShellGetExecutionBreakFlag( - VOID - ) -{ - // - // Check for UEFI Shell 2.0 protocols - // - if (mEfiShellProtocol != NULL) { - - // - // We are using UEFI Shell 2.0; see if the event has been triggered - // - if (gBS->CheckEvent(mEfiShellProtocol->ExecutionBreak) != EFI_SUCCESS) { - return (FALSE); - } - return (TRUE); - } - - // - // using EFI Shell; call the function to check - // - ASSERT(mEfiShellEnvironment2 != NULL); - return (mEfiShellEnvironment2->GetExecutionBreak()); -} -/** - return the value of an environment variable - - this function gets the value of the environment variable set by the - ShellSetEnvironmentVariable function - - @param EnvKey The key name of the environment variable. - - @retval NULL the named environment variable does not exist. - @return != NULL pointer to the value of the environment variable -**/ -CONST CHAR16* -EFIAPI -ShellGetEnvironmentVariable ( - IN CHAR16 *EnvKey - ) -{ - // - // Check for UEFI Shell 2.0 protocols - // - if (mEfiShellProtocol != NULL) { - return (mEfiShellProtocol->GetEnv(EnvKey)); - } - - // - // ASSERT that we must have EFI shell - // - ASSERT(mEfiShellEnvironment2 != NULL); - - // - // using EFI Shell - // - return (mEfiShellEnvironment2->GetEnv(EnvKey)); -} -/** - set the value of an environment variable - -This function changes the current value of the specified environment variable. If the -environment variable exists and the Value is an empty string, then the environment -variable is deleted. If the environment variable exists and the Value is not an empty -string, then the value of the environment variable is changed. If the environment -variable does not exist and the Value is an empty string, there is no action. If the -environment variable does not exist and the Value is a non-empty string, then the -environment variable is created and assigned the specified value. - - This is not supported pre-UEFI Shell 2.0. - - @param EnvKey The key name of the environment variable. - @param EnvVal The Value of the environment variable - @param Volatile Indicates whether the variable is non-volatile (FALSE) or volatile (TRUE). - - @retval EFI_SUCCESS the operation was completed sucessfully - @retval EFI_UNSUPPORTED This operation is not allowed in pre UEFI 2.0 Shell environments -**/ -EFI_STATUS -EFIAPI -ShellSetEnvironmentVariable ( - IN CONST CHAR16 *EnvKey, - IN CONST CHAR16 *EnvVal, - IN BOOLEAN Volatile - ) -{ - // - // Check for UEFI Shell 2.0 protocols - // - if (mEfiShellProtocol != NULL) { - return (mEfiShellProtocol->SetEnv(EnvKey, EnvVal, Volatile)); - } - - // - // This feature does not exist under EFI shell - // - return (EFI_UNSUPPORTED); -} -/** - cause the shell to parse and execute a command line. - - This function creates a nested instance of the shell and executes the specified -command (CommandLine) with the specified environment (Environment). Upon return, -the status code returned by the specified command is placed in StatusCode. -If Environment is NULL, then the current environment is used and all changes made -by the commands executed will be reflected in the current environment. If the -Environment is non-NULL, then the changes made will be discarded. -The CommandLine is executed from the current working directory on the current -device. - -EnvironmentVariables and Status are only supported for UEFI Shell 2.0. -Output is only supported for pre-UEFI Shell 2.0 - - @param ImageHandle Parent image that is starting the operation - @param CommandLine pointer to null terminated command line. - @param Output true to display debug output. false to hide it. - @param EnvironmentVariables optional pointer to array of environment variables - in the form "x=y". if NULL current set is used. - @param Status the status of the run command line. - - @retval EFI_SUCCESS the operation completed sucessfully. Status - contains the status code returned. - @retval EFI_INVALID_PARAMETER a parameter contains an invalid value - @retval EFI_OUT_OF_RESOURCES out of resources - @retval EFI_UNSUPPORTED the operation is not allowed. -**/ -EFI_STATUS -EFIAPI -ShellExecute ( - IN EFI_HANDLE *ParentHandle, - IN CHAR16 *CommandLine OPTIONAL, - IN BOOLEAN Output OPTIONAL, - IN CHAR16 **EnvironmentVariables OPTIONAL, - OUT EFI_STATUS *Status OPTIONAL - ) -{ - // - // Check for UEFI Shell 2.0 protocols - // - if (mEfiShellProtocol != NULL) { - // - // Call UEFI Shell 2.0 version (not using Output parameter) - // - return (mEfiShellProtocol->Execute(ParentHandle, - CommandLine, - EnvironmentVariables, - Status)); - } - // - // ASSERT that we must have EFI shell - // - ASSERT(mEfiShellEnvironment2 != NULL); - // - // Call EFI Shell version (not using EnvironmentVariables or Status parameters) - // Due to oddity in the EFI shell we want to dereference the ParentHandle here - // - return (mEfiShellEnvironment2->Execute(*ParentHandle, - CommandLine, - Output)); -} -/** - Retreives the current directory path - - If the DeviceName is NULL, it returns the current device's current directory - name. If the DeviceName is not NULL, it returns the current directory name - on specified drive. - - @param DeviceName the name of the drive to get directory on - - @retval NULL the directory does not exist - @return != NULL the directory -**/ -CONST CHAR16* -EFIAPI -ShellGetCurrentDir ( - IN CHAR16 *DeviceName OPTIONAL - ) -{ - // - // Check for UEFI Shell 2.0 protocols - // - if (mEfiShellProtocol != NULL) { - return (mEfiShellProtocol->GetCurDir(DeviceName)); - } - // - // ASSERT that we must have EFI shell - // - ASSERT(mEfiShellEnvironment2 != NULL); - return (mEfiShellEnvironment2->CurDir(DeviceName)); -} -/** - sets (enabled or disabled) the page break mode - - when page break mode is enabled the screen will stop scrolling - and wait for operator input before scrolling a subsequent screen. - - @param CurrentState TRUE to enable and FALSE to disable -**/ -VOID -EFIAPI -ShellSetPageBreakMode ( - IN BOOLEAN CurrentState - ) -{ - // - // check for enabling - // - if (CurrentState != 0x00) { - // - // check for UEFI Shell 2.0 - // - if (mEfiShellProtocol != NULL) { - // - // Enable with UEFI 2.0 Shell - // - mEfiShellProtocol->EnablePageBreak(); - return; - } else { - // - // ASSERT that must have EFI Shell - // - ASSERT(mEfiShellEnvironment2 != NULL); - // - // Enable with EFI Shell - // - mEfiShellEnvironment2->EnablePageBreak (DEFAULT_INIT_ROW, DEFAULT_AUTO_LF); - return; - } - } else { - // - // check for UEFI Shell 2.0 - // - if (mEfiShellProtocol != NULL) { - // - // Disable with UEFI 2.0 Shell - // - mEfiShellProtocol->DisablePageBreak(); - return; - } else { - // - // ASSERT that must have EFI Shell - // - ASSERT(mEfiShellEnvironment2 != NULL); - // - // Disable with EFI Shell - // - mEfiShellEnvironment2->DisablePageBreak (); - return; - } - } -} - -/// -/// version of EFI_SHELL_FILE_INFO struct, except has no CONST pointers. -/// This allows for the struct to be populated. -/// -typedef struct { - LIST_ENTRY Link; - EFI_STATUS Status; - CHAR16 *FullName; - CHAR16 *FileName; - EFI_FILE_HANDLE Handle; - EFI_FILE_INFO *Info; -} EFI_SHELL_FILE_INFO_NO_CONST; - -/** - Converts a EFI shell list of structures to the coresponding UEFI Shell 2.0 type of list. - - if OldStyleFileList is NULL then ASSERT() - - this function will convert a SHELL_FILE_ARG based list into a callee allocated - EFI_SHELL_FILE_INFO based list. it is up to the caller to free the memory via - the ShellCloseFileMetaArg function. - - @param FileList the EFI shell list type - - @retval the resultant head of the double linked new format list; -**/ -LIST_ENTRY* -EFIAPI -InternalShellConvertFileListType ( - LIST_ENTRY *FileList - ) -{ - LIST_ENTRY *ListHead; - SHELL_FILE_ARG *OldInfo; - LIST_ENTRY *Link; - EFI_SHELL_FILE_INFO_NO_CONST *NewInfo; - - // - // ASSERT that FileList is not NULL - // - ASSERT(FileList != NULL); - - // - // Allocate our list head and initialize the list - // - ListHead = AllocateZeroPool(sizeof(LIST_ENTRY)); - ASSERT (ListHead != NULL); - ListHead = InitializeListHead (ListHead); - - // - // enumerate through each member of the old list and copy - // - for (Link = FileList->ForwardLink; Link != FileList; Link = Link->ForwardLink) { - OldInfo = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE); - - // - // make sure the old list was valid - // - ASSERT(OldInfo != NULL); - ASSERT(OldInfo->Info != NULL); - ASSERT(OldInfo->FullName != NULL); - ASSERT(OldInfo->FileName != NULL); - - // - // allocate a new EFI_SHELL_FILE_INFO object - // - NewInfo = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO)); - - // - // copy the simple items - // - NewInfo->Handle = OldInfo->Handle; - NewInfo->Status = OldInfo->Status; - - // old shell checks for 0 not NULL - OldInfo->Handle = 0; - - // - // allocate new space to copy strings and structure - // - NewInfo->FullName = AllocateZeroPool(StrSize(OldInfo->FullName)); - NewInfo->FileName = AllocateZeroPool(StrSize(OldInfo->FileName)); - NewInfo->Info = AllocateZeroPool((UINTN)OldInfo->Info->Size); - - // - // make sure all the memory allocations were sucessful - // - ASSERT(NewInfo->FullName != NULL); - ASSERT(NewInfo->FileName != NULL); - ASSERT(NewInfo->Info != NULL); - - // - // Copt the strings and structure - // - StrCpy(NewInfo->FullName, OldInfo->FullName); - StrCpy(NewInfo->FileName, OldInfo->FileName); - gBS->CopyMem (NewInfo->Info, OldInfo->Info, (UINTN)OldInfo->Info->Size); - - // - // add that to the list - // - InsertTailList(ListHead, (LIST_ENTRY*)NewInfo); - } - return (ListHead); -} -/** - Opens a group of files based on a path. - - This function uses the Arg to open all the matching files. Each matched - file has a SHELL_FILE_ARG structure to record the file information. These - structures are placed on the list ListHead. Users can get the SHELL_FILE_ARG - structures from ListHead to access each file. This function supports wildcards - and will process '?' and '*' as such. the list must be freed with a call to - ShellCloseFileMetaArg(). - - This function will fail if called sequentially without freeing the list in the middle. - - @param Arg pointer to path string - @param OpenMode mode to open files with - @param ListHead head of linked list of results - - @retval EFI_SUCCESS the operation was sucessful and the list head - contains the list of opened files - #retval EFI_UNSUPPORTED a previous ShellOpenFileMetaArg must be closed first. - *ListHead is set to NULL. - @return != EFI_SUCCESS the operation failed - - @sa InternalShellConvertFileListType -**/ -EFI_STATUS -EFIAPI -ShellOpenFileMetaArg ( - IN CHAR16 *Arg, - IN UINT64 OpenMode, - IN OUT EFI_SHELL_FILE_INFO **ListHead - ) -{ - EFI_STATUS Status; - LIST_ENTRY *EmptyNode; - LIST_ENTRY *mOldStyleFileList; - - // - // ASSERT that Arg and ListHead are not NULL - // - ASSERT(Arg != NULL); - ASSERT(ListHead != NULL); - - // - // Check for UEFI Shell 2.0 protocols - // - if (mEfiShellProtocol != NULL) { - return (mEfiShellProtocol->OpenFileList(Arg, - OpenMode, - ListHead)); - } - - // - // ASSERT that we must have EFI shell - // - ASSERT(mEfiShellEnvironment2 != NULL); - - // - // allocate memory for old list head - // - mOldStyleFileList = (LIST_ENTRY*)AllocatePool(sizeof(LIST_ENTRY)); - ASSERT(mOldStyleFileList != NULL); - - // - // make sure the list head is initialized - // - InitializeListHead((LIST_ENTRY*)mOldStyleFileList); - - // - // Get the EFI Shell list of files - // - Status = mEfiShellEnvironment2->FileMetaArg(Arg, mOldStyleFileList); - if (EFI_ERROR(Status)) { - *ListHead = NULL; - return (Status); - } - - // - // Convert that to equivalent of UEFI Shell 2.0 structure - // - EmptyNode = InternalShellConvertFileListType(mOldStyleFileList); - - // - // Free the EFI Shell version that was converted. - // - ASSERT_EFI_ERROR(mEfiShellEnvironment2->FreeFileList(mOldStyleFileList)); - FreePool(mOldStyleFileList); - mOldStyleFileList = NULL; - - // - // remove the empty head of the list - // - *ListHead = (EFI_SHELL_FILE_INFO*)RemoveEntryList(EmptyNode); - FreePool(EmptyNode); - - return (Status); -} -/** - Free the linked list returned from ShellOpenFileMetaArg - - if ListHead is NULL then ASSERT() - - @param ListHead the pointer to free - - @retval EFI_SUCCESS the operation was sucessful -**/ -EFI_STATUS -EFIAPI -ShellCloseFileMetaArg ( - IN OUT EFI_SHELL_FILE_INFO **ListHead - ) -{ - LIST_ENTRY *Node; - - // - // ASSERT that ListHead is not NULL - // - ASSERT(ListHead != NULL); - - // - // Check for UEFI Shell 2.0 protocols - // - if (mEfiShellProtocol != NULL) { - return (mEfiShellProtocol->FreeFileList(ListHead)); - } else { - // - // Since this is EFI Shell version we need to free our internally made copy - // of the list - // - for (Node = GetFirstNode((LIST_ENTRY*)*ListHead) ; IsListEmpty((LIST_ENTRY*)*ListHead) == FALSE ; Node = GetFirstNode((LIST_ENTRY*)*ListHead)) { - RemoveEntryList(Node); - ((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Handle->Close(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Handle); - FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->FullName); - FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->FileName); - FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Info); - FreePool((EFI_SHELL_FILE_INFO_NO_CONST*)Node); - } - return EFI_SUCCESS; - } -} - -typedef struct { - LIST_ENTRY List; - CHAR16 *Name; - ParamType Type; - CHAR16 *Value; - UINTN OriginalPosition; -} SHELL_PARAM_PACKAGE; - -/** - Checks the list of valid arguments and returns TRUE if the item was found. If the - return value is TRUE then the type parameter is set also. - - if CheckList is NULL then ASSERT(); - if Name is NULL then ASSERT(); - if Type is NULL then ASSERT(); - - @param Type pointer to type of parameter if it was found - @param Name pointer to Name of parameter found - @param CheckList List to check against - - @retval TRUE the Parameter was found. Type is valid. - @retval FALSE the Parameter was not found. Type is not valid. -**/ -BOOLEAN -EFIAPI -InternalIsOnCheckList ( - IN CONST CHAR16 *Name, - IN CONST SHELL_PARAM_ITEM *CheckList, - OUT ParamType *Type - ) -{ - SHELL_PARAM_ITEM *TempListItem; - - // - // ASSERT that all 3 pointer parameters aren't NULL - // - ASSERT(CheckList != NULL); - ASSERT(Type != NULL); - ASSERT(Name != NULL); - - // - // question mark and page break mode are always supported - // - if ((StrCmp(Name, L"-?") == 0) || - (StrCmp(Name, L"-b") == 0) - ) { - return (TRUE); - } - - // - // Enumerate through the list - // - for (TempListItem = (SHELL_PARAM_ITEM*)CheckList ; TempListItem->Name != NULL ; TempListItem++) { - // - // If the Name matches set the type and return TRUE - // - if (StrCmp(Name, TempListItem->Name) == 0) { - *Type = TempListItem->Type; - return (TRUE); - } - } - return (FALSE); -} -/** - Checks the string for indicators of "flag" status. this is a leading '/', '-', or '+' - - @param Name pointer to Name of parameter found - - @retval TRUE the Parameter is a flag. - @retval FALSE the Parameter not a flag -**/ -BOOLEAN -EFIAPI -InternalIsFlag ( - IN CONST CHAR16 *Name - ) -{ - // - // ASSERT that Name isn't NULL - // - ASSERT(Name != NULL); - - // - // If the Name has a / or - as the first character return TRUE - // - if ((Name[0] == L'/') || - (Name[0] == L'-') || - (Name[0] == L'+') - ) { - return (TRUE); - } - return (FALSE); -} - -/** - Checks the command line arguments passed against the list of valid ones. - - If no initialization is required, then return RETURN_SUCCESS. - - @param CheckList pointer to list of parameters to check - @param CheckPackage pointer to pointer to list checked values - @param ProblemParam optional pointer to pointer to unicode string for - the paramater that caused failure. If used then the - caller is responsible for freeing the memory. - @param AutoPageBreak will automatically set PageBreakEnabled for "b" parameter - @param Argc Count of parameters in Argv - @param Argv pointer to array of parameters - - @retval EFI_SUCCESS The operation completed sucessfully. - @retval EFI_OUT_OF_RESOURCES A memory allocation failed - @retval EFI_INVALID_PARAMETER A parameter was invalid - @retval EFI_VOLUME_CORRUPTED the command line was corrupt. an argument was - duplicated. the duplicated command line argument - was returned in ProblemParam if provided. - @retval EFI_NOT_FOUND a argument required a value that was missing. - the invalid command line argument was returned in - ProblemParam if provided. -**/ -EFI_STATUS -EFIAPI -InternalCommandLineParse ( - IN CONST SHELL_PARAM_ITEM *CheckList, - OUT LIST_ENTRY **CheckPackage, - OUT CHAR16 **ProblemParam OPTIONAL, - IN BOOLEAN AutoPageBreak, - IN CONST CHAR16 **Argv, - IN UINTN Argc - ) -{ - UINTN LoopCounter; - UINTN Count; - ParamType CurrentItemType; - SHELL_PARAM_PACKAGE *CurrentItemPackage; - BOOLEAN GetItemValue; - - CurrentItemPackage = NULL; - - // - // ASSERTs - // - ASSERT(CheckList != NULL); - ASSERT(Argv != NULL); - - Count = 0; - GetItemValue = FALSE; - - // - // If there is only 1 item we dont need to do anything - // - if (Argc <= 1) { - *CheckPackage = NULL; - return (EFI_SUCCESS); - } - - // - // initialize the linked list - // - *CheckPackage = (LIST_ENTRY*)AllocateZeroPool(sizeof(LIST_ENTRY)); - InitializeListHead(*CheckPackage); - - // - // loop through each of the arguments - // - for (LoopCounter = 0 ; LoopCounter < Argc ; ++LoopCounter) { - if (Argv[LoopCounter] == NULL) { - // - // do nothing for NULL argv - // - } else if (GetItemValue == TRUE) { - ASSERT(CurrentItemPackage != NULL); - // - // get the item VALUE for the previous flag - // - GetItemValue = FALSE; - CurrentItemPackage->Value = AllocateZeroPool(StrSize(Argv[LoopCounter])); - ASSERT(CurrentItemPackage->Value != NULL); - StrCpy(CurrentItemPackage->Value, Argv[LoopCounter]); - InsertTailList(*CheckPackage, (LIST_ENTRY*)CurrentItemPackage); - } else if (InternalIsFlag(Argv[LoopCounter]) == FALSE) { - // - // add this one as a non-flag - // - CurrentItemPackage = AllocatePool(sizeof(SHELL_PARAM_PACKAGE)); - ASSERT(CurrentItemPackage != NULL); - CurrentItemPackage->Name = NULL; - CurrentItemPackage->Type = TypePosition; - CurrentItemPackage->Value = AllocatePool(StrSize(Argv[LoopCounter])); - ASSERT(CurrentItemPackage->Value != NULL); - StrCpy(CurrentItemPackage->Value, Argv[LoopCounter]); - CurrentItemPackage->OriginalPosition = Count++; - InsertTailList(*CheckPackage, (LIST_ENTRY*)CurrentItemPackage); - } else if (InternalIsOnCheckList(Argv[LoopCounter], CheckList, &CurrentItemType) == TRUE) { - // - // this is a flag - // - CurrentItemPackage = AllocatePool(sizeof(SHELL_PARAM_PACKAGE)); - ASSERT(CurrentItemPackage != NULL); - CurrentItemPackage->Name = AllocatePool(StrSize(Argv[LoopCounter])); - ASSERT(CurrentItemPackage->Name != NULL); - StrCpy(CurrentItemPackage->Name, Argv[LoopCounter]); - CurrentItemPackage->Type = CurrentItemType; - CurrentItemPackage->OriginalPosition = (UINTN)(-1); - - // - // Does this flag require a value - // - if (CurrentItemPackage->Type == TypeValue) { - // - // trigger the next loop to populate the value of this item - // - GetItemValue = TRUE; - } else { - // - // this item has no value expected; we are done - // - CurrentItemPackage->Value = NULL; - InsertTailList(*CheckPackage, (LIST_ENTRY*)CurrentItemPackage); - } - } else if (ProblemParam) { - // - // this was a non-recognised flag... error! - // - *ProblemParam = AllocatePool(StrSize(Argv[LoopCounter])); - ASSERT(*ProblemParam != NULL); - StrCpy(*ProblemParam, Argv[LoopCounter]); - ShellCommandLineFreeVarList(*CheckPackage); - *CheckPackage = NULL; - return (EFI_VOLUME_CORRUPTED); - } else { - ShellCommandLineFreeVarList(*CheckPackage); - *CheckPackage = NULL; - return (EFI_VOLUME_CORRUPTED); - } - } - // - // support for AutoPageBreak - // - if (AutoPageBreak && ShellCommandLineGetFlag(*CheckPackage, L"-b")) { - ShellSetPageBreakMode(TRUE); - } - return (EFI_SUCCESS); -} - -/** - Checks the command line arguments passed against the list of valid ones. - Optionally removes NULL values first. - - If no initialization is required, then return RETURN_SUCCESS. - - @param CheckList pointer to list of parameters to check - @param CheckPackage pointer to pointer to list checked values - @param ProblemParam optional pointer to pointer to unicode string for - the paramater that caused failure. - @param AutoPageBreak will automatically set PageBreakEnabled for "b" parameter - - @retval EFI_SUCCESS The operation completed sucessfully. - @retval EFI_OUT_OF_RESOURCES A memory allocation failed - @retval EFI_INVALID_PARAMETER A parameter was invalid - @retval EFI_VOLUME_CORRUPTED the command line was corrupt. an argument was - duplicated. the duplicated command line argument - was returned in ProblemParam if provided. - @retval EFI_DEVICE_ERROR the commands contained 2 opposing arguments. one - of the command line arguments was returned in - ProblemParam if provided. - @retval EFI_NOT_FOUND a argument required a value that was missing. - the invalid command line argument was returned in - ProblemParam if provided. -**/ -EFI_STATUS -EFIAPI -ShellCommandLineParse ( - IN CONST SHELL_PARAM_ITEM *CheckList, - OUT LIST_ENTRY **CheckPackage, - OUT CHAR16 **ProblemParam OPTIONAL, - IN BOOLEAN AutoPageBreak - ) -{ - // - // ASSERT that CheckList and CheckPackage aren't NULL - // - ASSERT(CheckList != NULL); - ASSERT(CheckPackage != NULL); - - // - // Check for UEFI Shell 2.0 protocols - // - if (mEfiShellParametersProtocol != NULL) { - return (InternalCommandLineParse(CheckList, - CheckPackage, - ProblemParam, - AutoPageBreak, - (CONST CHAR16**) mEfiShellParametersProtocol->Argv, - mEfiShellParametersProtocol->Argc )); - } - - // - // ASSERT That EFI Shell is not required - // - ASSERT (mEfiShellInterface != NULL); - return (InternalCommandLineParse(CheckList, - CheckPackage, - ProblemParam, - AutoPageBreak, - (CONST CHAR16**) mEfiShellInterface->Argv, - mEfiShellInterface->Argc )); -} - -/** - Frees shell variable list that was returned from ShellCommandLineParse. - - This function will free all the memory that was used for the CheckPackage - list of postprocessed shell arguments. - - this function has no return value. - - if CheckPackage is NULL, then return - - @param CheckPackage the list to de-allocate - **/ -VOID -EFIAPI -ShellCommandLineFreeVarList ( - IN LIST_ENTRY *CheckPackage - ) -{ - LIST_ENTRY *Node; - - // - // check for CheckPackage == NULL - // - if (CheckPackage == NULL) { - return; - } - - // - // for each node in the list - // - for (Node = GetFirstNode(CheckPackage); Node != CheckPackage ; Node = GetFirstNode(CheckPackage)) { - // - // Remove it from the list - // - RemoveEntryList(Node); - - // - // if it has a name free the name - // - if (((SHELL_PARAM_PACKAGE*)Node)->Name != NULL) { - FreePool(((SHELL_PARAM_PACKAGE*)Node)->Name); - } - - // - // if it has a value free the value - // - if (((SHELL_PARAM_PACKAGE*)Node)->Value != NULL) { - FreePool(((SHELL_PARAM_PACKAGE*)Node)->Value); - } - - // - // free the node structure - // - FreePool((SHELL_PARAM_PACKAGE*)Node); - } - // - // free the list head node - // - FreePool(CheckPackage); -} -/** - Checks for presence of a flag parameter - - flag arguments are in the form of "-" or "/", but do not have a value following the key - - if CheckPackage is NULL then return FALSE. - if KeyString is NULL then ASSERT() - - @param CheckPackage The package of parsed command line arguments - @param KeyString the Key of the command line argument to check for - - @retval TRUE the flag is on the command line - @retval FALSE the flag is not on the command line - **/ -BOOLEAN -EFIAPI -ShellCommandLineGetFlag ( - IN CONST LIST_ENTRY *CheckPackage, - IN CHAR16 *KeyString - ) -{ - LIST_ENTRY *Node; - - // - // ASSERT that both CheckPackage and KeyString aren't NULL - // - ASSERT(KeyString != NULL); - - // - // return FALSE for no package - // - if (CheckPackage == NULL) { - return (FALSE); - } - - // - // enumerate through the list of parametrs - // - for (Node = GetFirstNode(CheckPackage) ; !IsNull (CheckPackage, Node) ; Node = GetNextNode(CheckPackage, Node) ) { - // - // If the Name matches, return TRUE (and there may be NULL name) - // - if (((SHELL_PARAM_PACKAGE*)Node)->Name != NULL) { - if (StrCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) { - return (TRUE); - } - } - } - return (FALSE); -} -/** - returns value from command line argument - - value parameters are in the form of "- value" or "/ value" - - if CheckPackage is NULL, then return NULL; - - @param CheckPackage The package of parsed command line arguments - @param KeyString the Key of the command line argument to check for - - @retval NULL the flag is not on the command line - @return !=NULL pointer to unicode string of the value - **/ -CONST CHAR16* -EFIAPI -ShellCommandLineGetValue ( - IN CONST LIST_ENTRY *CheckPackage, - IN CHAR16 *KeyString - ) -{ - LIST_ENTRY *Node; - - // - // check for CheckPackage == NULL - // - if (CheckPackage == NULL) { - return (NULL); - } - - // - // enumerate through the list of parametrs - // - for (Node = GetFirstNode(CheckPackage) ; !IsNull (CheckPackage, Node) ; Node = GetNextNode(CheckPackage, Node) ) { - // - // If the Name matches, return the value (name can be NULL) - // - if (((SHELL_PARAM_PACKAGE*)Node)->Name != NULL) { - if (StrCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) { - return (((SHELL_PARAM_PACKAGE*)Node)->Value); - } - } - } - return (NULL); -} -/** - returns raw value from command line argument - - raw value parameters are in the form of "value" in a specific position in the list - - if CheckPackage is NULL, then return NULL; - - @param CheckPackage The package of parsed command line arguments - @param Position the position of the value - - @retval NULL the flag is not on the command line - @return !=NULL pointer to unicode string of the value - **/ -CONST CHAR16* -EFIAPI -ShellCommandLineGetRawValue ( - IN CONST LIST_ENTRY *CheckPackage, - IN UINT32 Position - ) -{ - LIST_ENTRY *Node; - - // - // check for CheckPackage == NULL - // - if (CheckPackage == NULL) { - return (NULL); - } - - // - // enumerate through the list of parametrs - // - for (Node = GetFirstNode(CheckPackage) ; !IsNull (CheckPackage, Node) ; Node = GetNextNode(CheckPackage, Node) ) { - // - // If the position matches, return the value - // - if (((SHELL_PARAM_PACKAGE*)Node)->OriginalPosition == Position) { - return (((SHELL_PARAM_PACKAGE*)Node)->Value); - } - } - return (NULL); -} \ No newline at end of file diff --git a/ShellPkg/Library/BaseShellLib/BaseShellLib.h b/ShellPkg/Library/BaseShellLib/BaseShellLib.h deleted file mode 100644 index 1620641648..0000000000 --- a/ShellPkg/Library/BaseShellLib/BaseShellLib.h +++ /dev/null @@ -1,26 +0,0 @@ -/** @file - Provides interface to shell functionality for shell commands and applications. - -Copyright (c) 2006 - 2009, Intel Corporation -All rights reserved. This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -typedef struct { - EFI_SHELL_GET_FILE_INFO GetFileInfo; - EFI_SHELL_SET_FILE_INFO SetFileInfo; - EFI_SHELL_READ_FILE ReadFile; - EFI_SHELL_WRITE_FILE WriteFile; - EFI_SHELL_CLOSE_FILE CloseFile; - EFI_SHELL_DELETE_FILE DeleteFile; - EFI_SHELL_GET_FILE_POSITION GetFilePosition; - EFI_SHELL_SET_FILE_POSITION SetFilePosition; - EFI_SHELL_FLUSH_FILE FlushFile; - EFI_SHELL_GET_FILE_SIZE GetFileSize; -} FILE_HANDLE_FUNCTION_MAP; diff --git a/ShellPkg/Library/BaseShellLib/BaseShellLib.inf b/ShellPkg/Library/BaseShellLib/BaseShellLib.inf deleted file mode 100644 index 71c68cb280..0000000000 --- a/ShellPkg/Library/BaseShellLib/BaseShellLib.inf +++ /dev/null @@ -1,63 +0,0 @@ -#/** @file -# Provides interface to shell functionality for shell commands and applications. -# -# Copyright (c) 2006 - 2009, Intel Corporation. -# -# All rights reserved. This program and the accompanying materials -# are licensed and made available under the terms and conditions of the BSD License -# which accompanies this distribution. The full text of the license may be found at -# http://opensource.org/licenses/bsd-license.php -# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -# -# -#**/ - -[Defines] - INF_VERSION = 0x00010006 - BASE_NAME = BaseShellLib - FILE_GUID = 449D0F00-2148-4a43-9836-F10B3980ECF5 - MODULE_TYPE = UEFI_DRIVER - VERSION_STRING = 1.0 - LIBRARY_CLASS = ShellLib|UEFI_APPLICATION UEFI_DRIVER - CONSTRUCTOR = ShellLibConstructor - DESTRUCTOR = ShellLibDestructor - -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# - -[Sources.common] - BaseShellLib.c - BaseShellLib.h - -[Packages] - MdePkg/MdePkg.dec - ShellPkg/ShellPkg.dec - -[LibraryClasses] - UefiBootServicesTableLib - MemoryAllocationLib - DevicePathLib - BaseLib - BaseMemoryLib - DebugLib - FileHandleLib - -[Protocols] - gEfiSimpleFileSystemProtocolGuid # ALWAYS_CONSUMED - - # shell 2.0 - gEfiShellProtocolGuid # SOMETIMES_CONSUMED - gEfiShellParametersProtocolGuid # SOMETIMES_CONSUMED - - # 'old' shell - gEfiShellEnvironment2Guid # SOMETIMES_CONSUMED - gEfiShellInterfaceGuid # SOMETIMES_CONSUMED - -[Guids] - gEfiFileInfoGuid # ALWAYS_CONSUMED - gEfiShellEnvironment2ExtGuid # ALWAYS_CONSUMED - -[Pcd.common] - gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize # ALWAYS_CONSUMED diff --git a/ShellPkg/Library/UefiShellLib/BaseShellLib.c b/ShellPkg/Library/UefiShellLib/BaseShellLib.c new file mode 100644 index 0000000000..1ddff9a2a0 --- /dev/null +++ b/ShellPkg/Library/UefiShellLib/BaseShellLib.c @@ -0,0 +1,1939 @@ +/** @file + Provides interface to shell functionality for shell commands and applications. + +Copyright (c) 2006 - 2009, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "BaseShellLib.h" + +#define MAX_FILE_NAME_LEN 522 // (20 * (6+5+2))+1) unicode characters from EFI FAT spec (doubled for bytes) +#define FIND_XXXXX_FILE_BUFFER_SIZE (SIZE_OF_EFI_FILE_INFO + MAX_FILE_NAME_LEN) + +// +// This is not static since it's extern in the .h file +// +SHELL_PARAM_ITEM EmptyParamList[] = { + {NULL, TypeMax} + }; + +// +// Static file globals for the shell library +// +STATIC EFI_SHELL_ENVIRONMENT2 *mEfiShellEnvironment2; +STATIC EFI_SHELL_INTERFACE *mEfiShellInterface; +STATIC EFI_SHELL_PROTOCOL *mEfiShellProtocol; +STATIC EFI_SHELL_PARAMETERS_PROTOCOL *mEfiShellParametersProtocol; +STATIC EFI_HANDLE mEfiShellEnvironment2Handle; +STATIC FILE_HANDLE_FUNCTION_MAP FileFunctionMap; + +/** + helper function to find ShellEnvironment2 for constructor +**/ +EFI_STATUS +EFIAPI +ShellFindSE2 ( + IN EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + EFI_HANDLE *Buffer; + UINTN BufferSize; + UINTN HandleIndex; + + BufferSize = 0; + Buffer = NULL; + Status = gBS->OpenProtocol(ImageHandle, + &gEfiShellEnvironment2Guid, + (VOID **)&mEfiShellEnvironment2, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + // + // look for the mEfiShellEnvironment2 protocol at a higher level + // + if (EFI_ERROR (Status) || !(CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid) != FALSE && + (mEfiShellEnvironment2->MajorVersion > EFI_SHELL_MAJOR_VER || + (mEfiShellEnvironment2->MajorVersion == EFI_SHELL_MAJOR_VER && mEfiShellEnvironment2->MinorVersion >= EFI_SHELL_MINOR_VER)))) { + // + // figure out how big of a buffer we need. + // + Status = gBS->LocateHandle (ByProtocol, + &gEfiShellEnvironment2Guid, + NULL, // ignored for ByProtocol + &BufferSize, + Buffer + ); + ASSERT(Status == EFI_BUFFER_TOO_SMALL); + Buffer = (EFI_HANDLE*)AllocatePool(BufferSize); + ASSERT(Buffer != NULL); + Status = gBS->LocateHandle (ByProtocol, + &gEfiShellEnvironment2Guid, + NULL, // ignored for ByProtocol + &BufferSize, + Buffer + ); + if (!EFI_ERROR (Status)) { + // + // now parse the list of returned handles + // + Status = EFI_NOT_FOUND; + for (HandleIndex = 0; HandleIndex < (BufferSize/sizeof(Buffer[0])); HandleIndex++) { + Status = gBS->OpenProtocol(Buffer[HandleIndex], + &gEfiShellEnvironment2Guid, + (VOID **)&mEfiShellEnvironment2, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid) != FALSE && + (mEfiShellEnvironment2->MajorVersion > EFI_SHELL_MAJOR_VER || + (mEfiShellEnvironment2->MajorVersion == EFI_SHELL_MAJOR_VER && mEfiShellEnvironment2->MinorVersion >= EFI_SHELL_MINOR_VER))) { + mEfiShellEnvironment2Handle = Buffer[HandleIndex]; + Status = EFI_SUCCESS; + break; + } + } + } + } + if (Buffer != NULL) { + FreePool (Buffer); + } + return (Status); +} + +EFI_STATUS +EFIAPI +ShellLibConstructorWorker ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable +){ + EFI_STATUS Status; + + // + // UEFI 2.0 shell interfaces (used preferentially) + // + Status = gBS->OpenProtocol(ImageHandle, + &gEfiShellProtocolGuid, + (VOID **)&mEfiShellProtocol, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR(Status)) { + mEfiShellProtocol = NULL; + } + Status = gBS->OpenProtocol(ImageHandle, + &gEfiShellParametersProtocolGuid, + (VOID **)&mEfiShellParametersProtocol, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR(Status)) { + mEfiShellParametersProtocol = NULL; + } + + if (mEfiShellParametersProtocol == NULL || mEfiShellProtocol == NULL) { + // + // Moved to seperate function due to complexity + // + Status = ShellFindSE2(ImageHandle); + + if (EFI_ERROR(Status)) { + DEBUG((DEBUG_ERROR, "Status: 0x%08x\r\n", Status)); + mEfiShellEnvironment2 = NULL; + } + Status = gBS->OpenProtocol(ImageHandle, + &gEfiShellInterfaceGuid, + (VOID **)&mEfiShellInterface, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR(Status)) { + mEfiShellInterface = NULL; + } + } + // + // only success getting 2 of either the old or new, but no 1/2 and 1/2 + // + if ((mEfiShellEnvironment2 != NULL && mEfiShellInterface != NULL) || + (mEfiShellProtocol != NULL && mEfiShellParametersProtocol != NULL) ) { + if (mEfiShellProtocol != NULL) { + FileFunctionMap.GetFileInfo = mEfiShellProtocol->GetFileInfo; + FileFunctionMap.SetFileInfo = mEfiShellProtocol->SetFileInfo; + FileFunctionMap.ReadFile = mEfiShellProtocol->ReadFile; + FileFunctionMap.WriteFile = mEfiShellProtocol->WriteFile; + FileFunctionMap.CloseFile = mEfiShellProtocol->CloseFile; + FileFunctionMap.DeleteFile = mEfiShellProtocol->DeleteFile; + FileFunctionMap.GetFilePosition = mEfiShellProtocol->GetFilePosition; + FileFunctionMap.SetFilePosition = mEfiShellProtocol->SetFilePosition; + FileFunctionMap.FlushFile = mEfiShellProtocol->FlushFile; + FileFunctionMap.GetFileSize = mEfiShellProtocol->GetFileSize; + } else { + FileFunctionMap.GetFileInfo = FileHandleGetInfo; + FileFunctionMap.SetFileInfo = FileHandleSetInfo; + FileFunctionMap.ReadFile = FileHandleRead; + FileFunctionMap.WriteFile = FileHandleWrite; + FileFunctionMap.CloseFile = FileHandleClose; + FileFunctionMap.DeleteFile = FileHandleDelete; + FileFunctionMap.GetFilePosition = FileHandleGetPosition; + FileFunctionMap.SetFilePosition = FileHandleSetPosition; + FileFunctionMap.FlushFile = FileHandleFlush; + FileFunctionMap.GetFileSize = FileHandleGetSize; + } + return (EFI_SUCCESS); + } + return (EFI_NOT_FOUND); +} +/** + Constructor for the Shell library. + + Initialize the library and determine if the underlying is a UEFI Shell 2.0 or an EFI shell. + + @param ImageHandle the image handle of the process + @param SystemTable the EFI System Table pointer + + @retval EFI_SUCCESS the initialization was complete sucessfully + @return others an error ocurred during initialization +**/ +EFI_STATUS +EFIAPI +ShellLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + + + mEfiShellEnvironment2 = NULL; + mEfiShellProtocol = NULL; + mEfiShellParametersProtocol = NULL; + mEfiShellInterface = NULL; + mEfiShellEnvironment2Handle = NULL; + + ///@todo make a worker constructor so initialize function works + // + // verify that auto initialize is not set false + // + if (PcdGetBool(PcdShellLibAutoInitialize) == 0) { + return (EFI_SUCCESS); + } + + return (ShellLibConstructorWorker(ImageHandle, SystemTable)); +} + +/** + Destructory for the library. free any resources. +**/ +EFI_STATUS +EFIAPI +ShellLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + if (mEfiShellEnvironment2 != NULL) { + gBS->CloseProtocol(mEfiShellEnvironment2Handle==NULL?ImageHandle:mEfiShellEnvironment2Handle, + &gEfiShellEnvironment2Guid, + ImageHandle, + NULL); + mEfiShellEnvironment2 = NULL; + } + if (mEfiShellInterface != NULL) { + gBS->CloseProtocol(ImageHandle, + &gEfiShellInterfaceGuid, + ImageHandle, + NULL); + mEfiShellInterface = NULL; + } + if (mEfiShellProtocol != NULL) { + gBS->CloseProtocol(ImageHandle, + &gEfiShellProtocolGuid, + ImageHandle, + NULL); + mEfiShellProtocol = NULL; + } + if (mEfiShellParametersProtocol != NULL) { + gBS->CloseProtocol(ImageHandle, + &gEfiShellParametersProtocolGuid, + ImageHandle, + NULL); + mEfiShellParametersProtocol = NULL; + } + mEfiShellEnvironment2Handle = NULL; + return (EFI_SUCCESS); +} + +/** + This function causes the shell library to initialize itself. If the shell library + is already initialized it will de-initialize all the current protocol poitners and + re-populate them again. + + When the library is used with PcdShellLibAutoInitialize set to true this function + will return EFI_SUCCESS and perform no actions. + + This function is intended for internal access for shell commands only. + + @retval EFI_SUCCESS the initialization was complete sucessfully + +**/ +EFI_STATUS +EFIAPI +ShellInitialize ( + ) { + // + // if auto initialize is not false then skip + // + if (PcdGetBool(PcdShellLibAutoInitialize) != 0) { + return (EFI_SUCCESS); + } + + // + // deinit the current stuff + // + ASSERT_EFI_ERROR(ShellLibDestructor(gImageHandle, gST)); + + // + // init the new stuff + // + return (ShellLibConstructorWorker(gImageHandle, gST)); +} + +/** + This function will retrieve the information about the file for the handle + specified and store it in allocated pool memory. + + This function allocates a buffer to store the file's information. It is the + caller's responsibility to free the buffer + + @param FileHandle The file handle of the file for which information is + being requested. + + @retval NULL information could not be retrieved. + + @return the information about the file +**/ +EFI_FILE_INFO* +EFIAPI +ShellGetFileInfo ( + IN EFI_FILE_HANDLE FileHandle + ) +{ + return (FileFunctionMap.GetFileInfo(FileHandle)); +} + +/** + This function will set the information about the file for the opened handle + specified. + + @param FileHandle The file handle of the file for which information + is being set + + @param FileInfo The infotmation to set. + + @retval EFI_SUCCESS The information was set. + @retval EFI_UNSUPPORTED The InformationType is not known. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The file or medium is write protected. + @retval EFI_ACCESS_DENIED The file was opened read only. + @retval EFI_VOLUME_FULL The volume is full. +**/ +EFI_STATUS +EFIAPI +ShellSetFileInfo ( + IN EFI_FILE_HANDLE FileHandle, + IN EFI_FILE_INFO *FileInfo + ) +{ + return (FileFunctionMap.SetFileInfo(FileHandle, FileInfo)); +} + + /** + This function will open a file or directory referenced by DevicePath. + + This function opens a file with the open mode according to the file path. The + Attributes is valid only for EFI_FILE_MODE_CREATE. + + @param FilePath on input the device path to the file. On output + the remaining device path. + @param DeviceHandle pointer to the system device handle. + @param FileHandle pointer to the file handle. + @param OpenMode the mode to open the file with. + @param Attributes the file's file attributes. + + @retval EFI_SUCCESS The information was set. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_UNSUPPORTED Could not open the file path. + @retval EFI_NOT_FOUND The specified file could not be found on the + device or the file system could not be found on + the device. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or the + medium is no longer supported. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The file or medium is write protected. + @retval EFI_ACCESS_DENIED The file was opened read only. + @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the + file. + @retval EFI_VOLUME_FULL The volume is full. +**/ +EFI_STATUS +EFIAPI +ShellOpenFileByDevicePath( + IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath, + OUT EFI_HANDLE *DeviceHandle, + OUT EFI_FILE_HANDLE *FileHandle, + IN UINT64 OpenMode, + IN UINT64 Attributes + ) +{ + CHAR16 *FileName; + EFI_STATUS Status; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol; + EFI_FILE_HANDLE LastHandle; + + // + // ASERT for FileHandle, FilePath, and DeviceHandle being NULL + // + ASSERT(FilePath != NULL); + ASSERT(FileHandle != NULL); + ASSERT(DeviceHandle != NULL); + // + // which shell interface should we use + // + if (mEfiShellProtocol != NULL) { + // + // use UEFI Shell 2.0 method. + // + FileName = mEfiShellProtocol->GetFilePathFromDevicePath(*FilePath); + if (FileName == NULL) { + return (EFI_INVALID_PARAMETER); + } + Status = ShellOpenFileByName(FileName, FileHandle, OpenMode, Attributes); + FreePool(FileName); + return (Status); + } + + + // + // use old shell method. + // + Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, + FilePath, + DeviceHandle); + if (EFI_ERROR (Status)) { + return Status; + } + Status = gBS->OpenProtocol(*DeviceHandle, + &gEfiSimpleFileSystemProtocolGuid, + (VOID**) &EfiSimpleFileSystemProtocol, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR (Status)) { + return Status; + } + Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, FileHandle); + if (EFI_ERROR (Status)) { + FileHandle = NULL; + return Status; + } + + // + // go down directories one node at a time. + // + while (!IsDevicePathEnd (*FilePath)) { + // + // For file system access each node should be a file path component + // + if (DevicePathType (*FilePath) != MEDIA_DEVICE_PATH || + DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP + ) { + FileHandle = NULL; + return (EFI_INVALID_PARAMETER); + } + // + // Open this file path node + // + LastHandle = *FileHandle; + *FileHandle = NULL; + + // + // Try to test opening an existing file + // + Status = LastHandle->Open ( + LastHandle, + FileHandle, + ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName, + OpenMode &~EFI_FILE_MODE_CREATE, + 0 + ); + + // + // see if the error was that it needs to be created + // + if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) { + Status = LastHandle->Open ( + LastHandle, + FileHandle, + ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName, + OpenMode, + Attributes + ); + } + // + // Close the last node + // + LastHandle->Close (LastHandle); + + if (EFI_ERROR(Status)) { + return (Status); + } + + // + // Get the next node + // + *FilePath = NextDevicePathNode (*FilePath); + } + return (EFI_SUCCESS); +} + +/** + This function will open a file or directory referenced by filename. + + If return is EFI_SUCCESS, the Filehandle is the opened file's handle; + otherwise, the Filehandle is NULL. The Attributes is valid only for + EFI_FILE_MODE_CREATE. + + if FileNAme is NULL then ASSERT() + + @param FileName pointer to file name + @param FileHandle pointer to the file handle. + @param OpenMode the mode to open the file with. + @param Attributes the file's file attributes. + + @retval EFI_SUCCESS The information was set. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_UNSUPPORTED Could not open the file path. + @retval EFI_NOT_FOUND The specified file could not be found on the + device or the file system could not be found + on the device. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or the + medium is no longer supported. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The file or medium is write protected. + @retval EFI_ACCESS_DENIED The file was opened read only. + @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the + file. + @retval EFI_VOLUME_FULL The volume is full. +**/ +EFI_STATUS +EFIAPI +ShellOpenFileByName( + IN CHAR16 *FileName, + OUT EFI_FILE_HANDLE *FileHandle, + IN UINT64 OpenMode, + IN UINT64 Attributes + ) +{ + EFI_HANDLE DeviceHandle; + EFI_DEVICE_PATH_PROTOCOL *FilePath; + + // + // ASSERT if FileName is NULL + // + ASSERT(FileName != NULL); + + if (mEfiShellProtocol != NULL) { + // + // Use UEFI Shell 2.0 method + // + return (mEfiShellProtocol->OpenFileByName(FileName, + FileHandle, + OpenMode)); + + ///@todo add the attributes + } + // + // Using EFI Shell version + // this means convert name to path and call that function + // since this will use EFI method again that will open it. + // + ASSERT(mEfiShellEnvironment2 != NULL); + FilePath = mEfiShellEnvironment2->NameToPath (FileName); + if (FileDevicePath != NULL) { + return (ShellOpenFileByDevicePath(&FilePath, + &DeviceHandle, + FileHandle, + OpenMode, + Attributes )); + } + return (EFI_DEVICE_ERROR); +} +/** + This function create a directory + + If return is EFI_SUCCESS, the Filehandle is the opened directory's handle; + otherwise, the Filehandle is NULL. If the directory already existed, this + function opens the existing directory. + + @param DirectoryName pointer to directory name + @param FileHandle pointer to the file handle. + + @retval EFI_SUCCESS The information was set. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_UNSUPPORTED Could not open the file path. + @retval EFI_NOT_FOUND The specified file could not be found on the + device or the file system could not be found + on the device. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or the + medium is no longer supported. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The file or medium is write protected. + @retval EFI_ACCESS_DENIED The file was opened read only. + @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the + file. + @retval EFI_VOLUME_FULL The volume is full. + @sa ShellOpenFileByName +**/ +EFI_STATUS +EFIAPI +ShellCreateDirectory( + IN CHAR16 *DirectoryName, + OUT EFI_FILE_HANDLE *FileHandle + ) +{ + // + // this is a pass thru to the open file function with sepcific open mode and attributes + // + return (ShellOpenFileByName(DirectoryName, + FileHandle, + EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, + EFI_FILE_DIRECTORY + )); +} + +/** + This function reads information from an opened file. + + If FileHandle is not a directory, the function reads the requested number of + bytes from the file at the file's current position and returns them in Buffer. + If the read goes beyond the end of the file, the read length is truncated to the + end of the file. The file's current position is increased by the number of bytes + returned. If FileHandle is a directory, the function reads the directory entry + at the file's current position and returns the entry in Buffer. If the Buffer + is not large enough to hold the current directory entry, then + EFI_BUFFER_TOO_SMALL is returned and the current file position is not updated. + BufferSize is set to be the size of the buffer needed to read the entry. On + success, the current position is updated to the next directory entry. If there + are no more directory entries, the read returns a zero-length buffer. + EFI_FILE_INFO is the structure returned as the directory entry. + + @param FileHandle the opened file handle + @param BufferSize on input the size of buffer in bytes. on return + the number of bytes written. + @param Buffer the buffer to put read data into. + + @retval EFI_SUCCESS Data was read. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_BUFFER_TO_SMALL Buffer is too small. ReadSize contains required + size. + +**/ +EFI_STATUS +EFIAPI +ShellReadFile( + IN EFI_FILE_HANDLE FileHandle, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + return (FileFunctionMap.ReadFile(FileHandle, BufferSize, Buffer)); +} + + +/** + Write data to a file. + + This function writes the specified number of bytes to the file at the current + file position. The current file position is advanced the actual number of bytes + written, which is returned in BufferSize. Partial writes only occur when there + has been a data error during the write attempt (such as "volume space full"). + The file is automatically grown to hold the data if required. Direct writes to + opened directories are not supported. + + @param FileHandle The opened file for writing + @param BufferSize on input the number of bytes in Buffer. On output + the number of bytes written. + @param Buffer the buffer containing data to write is stored. + + @retval EFI_SUCCESS Data was written. + @retval EFI_UNSUPPORTED Writes to an open directory are not supported. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The device is write-protected. + @retval EFI_ACCESS_DENIED The file was open for read only. + @retval EFI_VOLUME_FULL The volume is full. +**/ +EFI_STATUS +EFIAPI +ShellWriteFile( + IN EFI_FILE_HANDLE FileHandle, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + return (FileFunctionMap.WriteFile(FileHandle, BufferSize, Buffer)); +} + +/** + Close an open file handle. + + This function closes a specified file handle. All "dirty" cached file data is + flushed to the device, and the file is closed. In all cases the handle is + closed. + +@param FileHandle the file handle to close. + +@retval EFI_SUCCESS the file handle was closed sucessfully. +**/ +EFI_STATUS +EFIAPI +ShellCloseFile ( + IN EFI_FILE_HANDLE *FileHandle + ) +{ + return (FileFunctionMap.CloseFile(*FileHandle)); +} + +/** + Delete a file and close the handle + + This function closes and deletes a file. In all cases the file handle is closed. + If the file cannot be deleted, the warning code EFI_WARN_DELETE_FAILURE is + returned, but the handle is still closed. + + @param FileHandle the file handle to delete + + @retval EFI_SUCCESS the file was closed sucessfully + @retval EFI_WARN_DELETE_FAILURE the handle was closed, but the file was not + deleted + @retval INVALID_PARAMETER One of the parameters has an invalid value. +**/ +EFI_STATUS +EFIAPI +ShellDeleteFile ( + IN EFI_FILE_HANDLE *FileHandle + ) +{ + return (FileFunctionMap.DeleteFile(*FileHandle)); +} + +/** + Set the current position in a file. + + This function sets the current file position for the handle to the position + supplied. With the exception of seeking to position 0xFFFFFFFFFFFFFFFF, only + absolute positioning is supported, and seeking past the end of the file is + allowed (a subsequent write would grow the file). Seeking to position + 0xFFFFFFFFFFFFFFFF causes the current position to be set to the end of the file. + If FileHandle is a directory, the only position that may be set is zero. This + has the effect of starting the read process of the directory entries over. + + @param FileHandle The file handle on which the position is being set + @param Position Byte position from begining of file + + @retval EFI_SUCCESS Operation completed sucessfully. + @retval EFI_UNSUPPORTED the seek request for non-zero is not valid on + directories. + @retval INVALID_PARAMETER One of the parameters has an invalid value. +**/ +EFI_STATUS +EFIAPI +ShellSetFilePosition ( + IN EFI_FILE_HANDLE FileHandle, + IN UINT64 Position + ) +{ + return (FileFunctionMap.SetFilePosition(FileHandle, Position)); +} + +/** + Gets a file's current position + + This function retrieves the current file position for the file handle. For + directories, the current file position has no meaning outside of the file + system driver and as such the operation is not supported. An error is returned + if FileHandle is a directory. + + @param FileHandle The open file handle on which to get the position. + @param Position Byte position from begining of file. + + @retval EFI_SUCCESS the operation completed sucessfully. + @retval INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_UNSUPPORTED the request is not valid on directories. +**/ +EFI_STATUS +EFIAPI +ShellGetFilePosition ( + IN EFI_FILE_HANDLE FileHandle, + OUT UINT64 *Position + ) +{ + return (FileFunctionMap.GetFilePosition(FileHandle, Position)); +} +/** + Flushes data on a file + + This function flushes all modified data associated with a file to a device. + + @param FileHandle The file handle on which to flush data + + @retval EFI_SUCCESS The data was flushed. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The file or medium is write protected. + @retval EFI_ACCESS_DENIED The file was opened for read only. +**/ +EFI_STATUS +EFIAPI +ShellFlushFile ( + IN EFI_FILE_HANDLE FileHandle + ) +{ + return (FileFunctionMap.FlushFile(FileHandle)); +} + +/** + Retrieves the first file from a directory + + This function opens a directory and gets the first file's info in the + directory. Caller can use ShellFindNextFile() to get other files. When + complete the caller is responsible for calling FreePool() on Buffer. + + @param DirHandle The file handle of the directory to search + @param Buffer Pointer to buffer for file's information + + @retval EFI_SUCCESS Found the first file. + @retval EFI_NOT_FOUND Cannot find the directory. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @return Others status of ShellGetFileInfo, ShellSetFilePosition, + or ShellReadFile +**/ +EFI_STATUS +EFIAPI +ShellFindFirstFile ( + IN EFI_FILE_HANDLE DirHandle, + OUT EFI_FILE_INFO **Buffer + ) +{ + // + // pass to file handle lib + // + return (FileHandleFindFirstFile(DirHandle, Buffer)); +} +/** + Retrieves the next file in a directory. + + To use this function, caller must call the LibFindFirstFile() to get the + first file, and then use this function get other files. This function can be + called for several times to get each file's information in the directory. If + the call of ShellFindNextFile() got the last file in the directory, the next + call of this function has no file to get. *NoFile will be set to TRUE and the + Buffer memory will be automatically freed. + + @param DirHandle the file handle of the directory + @param Buffer pointer to buffer for file's information + @param NoFile pointer to boolean when last file is found + + @retval EFI_SUCCESS Found the next file, or reached last file + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. +**/ +EFI_STATUS +EFIAPI +ShellFindNextFile( + IN EFI_FILE_HANDLE DirHandle, + OUT EFI_FILE_INFO *Buffer, + OUT BOOLEAN *NoFile + ) +{ + // + // pass to file handle lib + // + return (FileHandleFindNextFile(DirHandle, Buffer, NoFile)); +} +/** + Retrieve the size of a file. + + if FileHandle is NULL then ASSERT() + if Size is NULL then ASSERT() + + This function extracts the file size info from the FileHandle's EFI_FILE_INFO + data. + + @param FileHandle file handle from which size is retrieved + @param Size pointer to size + + @retval EFI_SUCCESS operation was completed sucessfully + @retval EFI_DEVICE_ERROR cannot access the file +**/ +EFI_STATUS +EFIAPI +ShellGetFileSize ( + IN EFI_FILE_HANDLE FileHandle, + OUT UINT64 *Size + ) +{ + return (FileFunctionMap.GetFileSize(FileHandle, Size)); +} +/** + Retrieves the status of the break execution flag + + this function is useful to check whether the application is being asked to halt by the shell. + + @retval TRUE the execution break is enabled + @retval FALSE the execution break is not enabled +**/ +BOOLEAN +EFIAPI +ShellGetExecutionBreakFlag( + VOID + ) +{ + // + // Check for UEFI Shell 2.0 protocols + // + if (mEfiShellProtocol != NULL) { + + // + // We are using UEFI Shell 2.0; see if the event has been triggered + // + if (gBS->CheckEvent(mEfiShellProtocol->ExecutionBreak) != EFI_SUCCESS) { + return (FALSE); + } + return (TRUE); + } + + // + // using EFI Shell; call the function to check + // + ASSERT(mEfiShellEnvironment2 != NULL); + return (mEfiShellEnvironment2->GetExecutionBreak()); +} +/** + return the value of an environment variable + + this function gets the value of the environment variable set by the + ShellSetEnvironmentVariable function + + @param EnvKey The key name of the environment variable. + + @retval NULL the named environment variable does not exist. + @return != NULL pointer to the value of the environment variable +**/ +CONST CHAR16* +EFIAPI +ShellGetEnvironmentVariable ( + IN CHAR16 *EnvKey + ) +{ + // + // Check for UEFI Shell 2.0 protocols + // + if (mEfiShellProtocol != NULL) { + return (mEfiShellProtocol->GetEnv(EnvKey)); + } + + // + // ASSERT that we must have EFI shell + // + ASSERT(mEfiShellEnvironment2 != NULL); + + // + // using EFI Shell + // + return (mEfiShellEnvironment2->GetEnv(EnvKey)); +} +/** + set the value of an environment variable + +This function changes the current value of the specified environment variable. If the +environment variable exists and the Value is an empty string, then the environment +variable is deleted. If the environment variable exists and the Value is not an empty +string, then the value of the environment variable is changed. If the environment +variable does not exist and the Value is an empty string, there is no action. If the +environment variable does not exist and the Value is a non-empty string, then the +environment variable is created and assigned the specified value. + + This is not supported pre-UEFI Shell 2.0. + + @param EnvKey The key name of the environment variable. + @param EnvVal The Value of the environment variable + @param Volatile Indicates whether the variable is non-volatile (FALSE) or volatile (TRUE). + + @retval EFI_SUCCESS the operation was completed sucessfully + @retval EFI_UNSUPPORTED This operation is not allowed in pre UEFI 2.0 Shell environments +**/ +EFI_STATUS +EFIAPI +ShellSetEnvironmentVariable ( + IN CONST CHAR16 *EnvKey, + IN CONST CHAR16 *EnvVal, + IN BOOLEAN Volatile + ) +{ + // + // Check for UEFI Shell 2.0 protocols + // + if (mEfiShellProtocol != NULL) { + return (mEfiShellProtocol->SetEnv(EnvKey, EnvVal, Volatile)); + } + + // + // This feature does not exist under EFI shell + // + return (EFI_UNSUPPORTED); +} +/** + cause the shell to parse and execute a command line. + + This function creates a nested instance of the shell and executes the specified +command (CommandLine) with the specified environment (Environment). Upon return, +the status code returned by the specified command is placed in StatusCode. +If Environment is NULL, then the current environment is used and all changes made +by the commands executed will be reflected in the current environment. If the +Environment is non-NULL, then the changes made will be discarded. +The CommandLine is executed from the current working directory on the current +device. + +EnvironmentVariables and Status are only supported for UEFI Shell 2.0. +Output is only supported for pre-UEFI Shell 2.0 + + @param ImageHandle Parent image that is starting the operation + @param CommandLine pointer to null terminated command line. + @param Output true to display debug output. false to hide it. + @param EnvironmentVariables optional pointer to array of environment variables + in the form "x=y". if NULL current set is used. + @param Status the status of the run command line. + + @retval EFI_SUCCESS the operation completed sucessfully. Status + contains the status code returned. + @retval EFI_INVALID_PARAMETER a parameter contains an invalid value + @retval EFI_OUT_OF_RESOURCES out of resources + @retval EFI_UNSUPPORTED the operation is not allowed. +**/ +EFI_STATUS +EFIAPI +ShellExecute ( + IN EFI_HANDLE *ParentHandle, + IN CHAR16 *CommandLine OPTIONAL, + IN BOOLEAN Output OPTIONAL, + IN CHAR16 **EnvironmentVariables OPTIONAL, + OUT EFI_STATUS *Status OPTIONAL + ) +{ + // + // Check for UEFI Shell 2.0 protocols + // + if (mEfiShellProtocol != NULL) { + // + // Call UEFI Shell 2.0 version (not using Output parameter) + // + return (mEfiShellProtocol->Execute(ParentHandle, + CommandLine, + EnvironmentVariables, + Status)); + } + // + // ASSERT that we must have EFI shell + // + ASSERT(mEfiShellEnvironment2 != NULL); + // + // Call EFI Shell version (not using EnvironmentVariables or Status parameters) + // Due to oddity in the EFI shell we want to dereference the ParentHandle here + // + return (mEfiShellEnvironment2->Execute(*ParentHandle, + CommandLine, + Output)); +} +/** + Retreives the current directory path + + If the DeviceName is NULL, it returns the current device's current directory + name. If the DeviceName is not NULL, it returns the current directory name + on specified drive. + + @param DeviceName the name of the drive to get directory on + + @retval NULL the directory does not exist + @return != NULL the directory +**/ +CONST CHAR16* +EFIAPI +ShellGetCurrentDir ( + IN CHAR16 *DeviceName OPTIONAL + ) +{ + // + // Check for UEFI Shell 2.0 protocols + // + if (mEfiShellProtocol != NULL) { + return (mEfiShellProtocol->GetCurDir(DeviceName)); + } + // + // ASSERT that we must have EFI shell + // + ASSERT(mEfiShellEnvironment2 != NULL); + return (mEfiShellEnvironment2->CurDir(DeviceName)); +} +/** + sets (enabled or disabled) the page break mode + + when page break mode is enabled the screen will stop scrolling + and wait for operator input before scrolling a subsequent screen. + + @param CurrentState TRUE to enable and FALSE to disable +**/ +VOID +EFIAPI +ShellSetPageBreakMode ( + IN BOOLEAN CurrentState + ) +{ + // + // check for enabling + // + if (CurrentState != 0x00) { + // + // check for UEFI Shell 2.0 + // + if (mEfiShellProtocol != NULL) { + // + // Enable with UEFI 2.0 Shell + // + mEfiShellProtocol->EnablePageBreak(); + return; + } else { + // + // ASSERT that must have EFI Shell + // + ASSERT(mEfiShellEnvironment2 != NULL); + // + // Enable with EFI Shell + // + mEfiShellEnvironment2->EnablePageBreak (DEFAULT_INIT_ROW, DEFAULT_AUTO_LF); + return; + } + } else { + // + // check for UEFI Shell 2.0 + // + if (mEfiShellProtocol != NULL) { + // + // Disable with UEFI 2.0 Shell + // + mEfiShellProtocol->DisablePageBreak(); + return; + } else { + // + // ASSERT that must have EFI Shell + // + ASSERT(mEfiShellEnvironment2 != NULL); + // + // Disable with EFI Shell + // + mEfiShellEnvironment2->DisablePageBreak (); + return; + } + } +} + +/// +/// version of EFI_SHELL_FILE_INFO struct, except has no CONST pointers. +/// This allows for the struct to be populated. +/// +typedef struct { + LIST_ENTRY Link; + EFI_STATUS Status; + CHAR16 *FullName; + CHAR16 *FileName; + EFI_FILE_HANDLE Handle; + EFI_FILE_INFO *Info; +} EFI_SHELL_FILE_INFO_NO_CONST; + +/** + Converts a EFI shell list of structures to the coresponding UEFI Shell 2.0 type of list. + + if OldStyleFileList is NULL then ASSERT() + + this function will convert a SHELL_FILE_ARG based list into a callee allocated + EFI_SHELL_FILE_INFO based list. it is up to the caller to free the memory via + the ShellCloseFileMetaArg function. + + @param FileList the EFI shell list type + + @retval the resultant head of the double linked new format list; +**/ +LIST_ENTRY* +EFIAPI +InternalShellConvertFileListType ( + LIST_ENTRY *FileList + ) +{ + LIST_ENTRY *ListHead; + SHELL_FILE_ARG *OldInfo; + LIST_ENTRY *Link; + EFI_SHELL_FILE_INFO_NO_CONST *NewInfo; + + // + // ASSERT that FileList is not NULL + // + ASSERT(FileList != NULL); + + // + // Allocate our list head and initialize the list + // + ListHead = AllocateZeroPool(sizeof(LIST_ENTRY)); + ASSERT (ListHead != NULL); + ListHead = InitializeListHead (ListHead); + + // + // enumerate through each member of the old list and copy + // + for (Link = FileList->ForwardLink; Link != FileList; Link = Link->ForwardLink) { + OldInfo = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE); + + // + // make sure the old list was valid + // + ASSERT(OldInfo != NULL); + ASSERT(OldInfo->Info != NULL); + ASSERT(OldInfo->FullName != NULL); + ASSERT(OldInfo->FileName != NULL); + + // + // allocate a new EFI_SHELL_FILE_INFO object + // + NewInfo = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO)); + + // + // copy the simple items + // + NewInfo->Handle = OldInfo->Handle; + NewInfo->Status = OldInfo->Status; + + // old shell checks for 0 not NULL + OldInfo->Handle = 0; + + // + // allocate new space to copy strings and structure + // + NewInfo->FullName = AllocateZeroPool(StrSize(OldInfo->FullName)); + NewInfo->FileName = AllocateZeroPool(StrSize(OldInfo->FileName)); + NewInfo->Info = AllocateZeroPool((UINTN)OldInfo->Info->Size); + + // + // make sure all the memory allocations were sucessful + // + ASSERT(NewInfo->FullName != NULL); + ASSERT(NewInfo->FileName != NULL); + ASSERT(NewInfo->Info != NULL); + + // + // Copt the strings and structure + // + StrCpy(NewInfo->FullName, OldInfo->FullName); + StrCpy(NewInfo->FileName, OldInfo->FileName); + gBS->CopyMem (NewInfo->Info, OldInfo->Info, (UINTN)OldInfo->Info->Size); + + // + // add that to the list + // + InsertTailList(ListHead, (LIST_ENTRY*)NewInfo); + } + return (ListHead); +} +/** + Opens a group of files based on a path. + + This function uses the Arg to open all the matching files. Each matched + file has a SHELL_FILE_ARG structure to record the file information. These + structures are placed on the list ListHead. Users can get the SHELL_FILE_ARG + structures from ListHead to access each file. This function supports wildcards + and will process '?' and '*' as such. the list must be freed with a call to + ShellCloseFileMetaArg(). + + This function will fail if called sequentially without freeing the list in the middle. + + @param Arg pointer to path string + @param OpenMode mode to open files with + @param ListHead head of linked list of results + + @retval EFI_SUCCESS the operation was sucessful and the list head + contains the list of opened files + #retval EFI_UNSUPPORTED a previous ShellOpenFileMetaArg must be closed first. + *ListHead is set to NULL. + @return != EFI_SUCCESS the operation failed + + @sa InternalShellConvertFileListType +**/ +EFI_STATUS +EFIAPI +ShellOpenFileMetaArg ( + IN CHAR16 *Arg, + IN UINT64 OpenMode, + IN OUT EFI_SHELL_FILE_INFO **ListHead + ) +{ + EFI_STATUS Status; + LIST_ENTRY *EmptyNode; + LIST_ENTRY *mOldStyleFileList; + + // + // ASSERT that Arg and ListHead are not NULL + // + ASSERT(Arg != NULL); + ASSERT(ListHead != NULL); + + // + // Check for UEFI Shell 2.0 protocols + // + if (mEfiShellProtocol != NULL) { + return (mEfiShellProtocol->OpenFileList(Arg, + OpenMode, + ListHead)); + } + + // + // ASSERT that we must have EFI shell + // + ASSERT(mEfiShellEnvironment2 != NULL); + + // + // allocate memory for old list head + // + mOldStyleFileList = (LIST_ENTRY*)AllocatePool(sizeof(LIST_ENTRY)); + ASSERT(mOldStyleFileList != NULL); + + // + // make sure the list head is initialized + // + InitializeListHead((LIST_ENTRY*)mOldStyleFileList); + + // + // Get the EFI Shell list of files + // + Status = mEfiShellEnvironment2->FileMetaArg(Arg, mOldStyleFileList); + if (EFI_ERROR(Status)) { + *ListHead = NULL; + return (Status); + } + + // + // Convert that to equivalent of UEFI Shell 2.0 structure + // + EmptyNode = InternalShellConvertFileListType(mOldStyleFileList); + + // + // Free the EFI Shell version that was converted. + // + ASSERT_EFI_ERROR(mEfiShellEnvironment2->FreeFileList(mOldStyleFileList)); + FreePool(mOldStyleFileList); + mOldStyleFileList = NULL; + + // + // remove the empty head of the list + // + *ListHead = (EFI_SHELL_FILE_INFO*)RemoveEntryList(EmptyNode); + FreePool(EmptyNode); + + return (Status); +} +/** + Free the linked list returned from ShellOpenFileMetaArg + + if ListHead is NULL then ASSERT() + + @param ListHead the pointer to free + + @retval EFI_SUCCESS the operation was sucessful +**/ +EFI_STATUS +EFIAPI +ShellCloseFileMetaArg ( + IN OUT EFI_SHELL_FILE_INFO **ListHead + ) +{ + LIST_ENTRY *Node; + + // + // ASSERT that ListHead is not NULL + // + ASSERT(ListHead != NULL); + + // + // Check for UEFI Shell 2.0 protocols + // + if (mEfiShellProtocol != NULL) { + return (mEfiShellProtocol->FreeFileList(ListHead)); + } else { + // + // Since this is EFI Shell version we need to free our internally made copy + // of the list + // + for (Node = GetFirstNode((LIST_ENTRY*)*ListHead) ; IsListEmpty((LIST_ENTRY*)*ListHead) == FALSE ; Node = GetFirstNode((LIST_ENTRY*)*ListHead)) { + RemoveEntryList(Node); + ((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Handle->Close(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Handle); + FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->FullName); + FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->FileName); + FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Info); + FreePool((EFI_SHELL_FILE_INFO_NO_CONST*)Node); + } + return EFI_SUCCESS; + } +} + +typedef struct { + LIST_ENTRY List; + CHAR16 *Name; + ParamType Type; + CHAR16 *Value; + UINTN OriginalPosition; +} SHELL_PARAM_PACKAGE; + +/** + Checks the list of valid arguments and returns TRUE if the item was found. If the + return value is TRUE then the type parameter is set also. + + if CheckList is NULL then ASSERT(); + if Name is NULL then ASSERT(); + if Type is NULL then ASSERT(); + + @param Type pointer to type of parameter if it was found + @param Name pointer to Name of parameter found + @param CheckList List to check against + + @retval TRUE the Parameter was found. Type is valid. + @retval FALSE the Parameter was not found. Type is not valid. +**/ +BOOLEAN +EFIAPI +InternalIsOnCheckList ( + IN CONST CHAR16 *Name, + IN CONST SHELL_PARAM_ITEM *CheckList, + OUT ParamType *Type + ) +{ + SHELL_PARAM_ITEM *TempListItem; + + // + // ASSERT that all 3 pointer parameters aren't NULL + // + ASSERT(CheckList != NULL); + ASSERT(Type != NULL); + ASSERT(Name != NULL); + + // + // question mark and page break mode are always supported + // + if ((StrCmp(Name, L"-?") == 0) || + (StrCmp(Name, L"-b") == 0) + ) { + return (TRUE); + } + + // + // Enumerate through the list + // + for (TempListItem = (SHELL_PARAM_ITEM*)CheckList ; TempListItem->Name != NULL ; TempListItem++) { + // + // If the Name matches set the type and return TRUE + // + if (StrCmp(Name, TempListItem->Name) == 0) { + *Type = TempListItem->Type; + return (TRUE); + } + } + return (FALSE); +} +/** + Checks the string for indicators of "flag" status. this is a leading '/', '-', or '+' + + @param Name pointer to Name of parameter found + + @retval TRUE the Parameter is a flag. + @retval FALSE the Parameter not a flag +**/ +BOOLEAN +EFIAPI +InternalIsFlag ( + IN CONST CHAR16 *Name + ) +{ + // + // ASSERT that Name isn't NULL + // + ASSERT(Name != NULL); + + // + // If the Name has a / or - as the first character return TRUE + // + if ((Name[0] == L'/') || + (Name[0] == L'-') || + (Name[0] == L'+') + ) { + return (TRUE); + } + return (FALSE); +} + +/** + Checks the command line arguments passed against the list of valid ones. + + If no initialization is required, then return RETURN_SUCCESS. + + @param CheckList pointer to list of parameters to check + @param CheckPackage pointer to pointer to list checked values + @param ProblemParam optional pointer to pointer to unicode string for + the paramater that caused failure. If used then the + caller is responsible for freeing the memory. + @param AutoPageBreak will automatically set PageBreakEnabled for "b" parameter + @param Argc Count of parameters in Argv + @param Argv pointer to array of parameters + + @retval EFI_SUCCESS The operation completed sucessfully. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed + @retval EFI_INVALID_PARAMETER A parameter was invalid + @retval EFI_VOLUME_CORRUPTED the command line was corrupt. an argument was + duplicated. the duplicated command line argument + was returned in ProblemParam if provided. + @retval EFI_NOT_FOUND a argument required a value that was missing. + the invalid command line argument was returned in + ProblemParam if provided. +**/ +EFI_STATUS +EFIAPI +InternalCommandLineParse ( + IN CONST SHELL_PARAM_ITEM *CheckList, + OUT LIST_ENTRY **CheckPackage, + OUT CHAR16 **ProblemParam OPTIONAL, + IN BOOLEAN AutoPageBreak, + IN CONST CHAR16 **Argv, + IN UINTN Argc + ) +{ + UINTN LoopCounter; + UINTN Count; + ParamType CurrentItemType; + SHELL_PARAM_PACKAGE *CurrentItemPackage; + BOOLEAN GetItemValue; + + CurrentItemPackage = NULL; + + // + // ASSERTs + // + ASSERT(CheckList != NULL); + ASSERT(Argv != NULL); + + Count = 0; + GetItemValue = FALSE; + + // + // If there is only 1 item we dont need to do anything + // + if (Argc <= 1) { + *CheckPackage = NULL; + return (EFI_SUCCESS); + } + + // + // initialize the linked list + // + *CheckPackage = (LIST_ENTRY*)AllocateZeroPool(sizeof(LIST_ENTRY)); + InitializeListHead(*CheckPackage); + + // + // loop through each of the arguments + // + for (LoopCounter = 0 ; LoopCounter < Argc ; ++LoopCounter) { + if (Argv[LoopCounter] == NULL) { + // + // do nothing for NULL argv + // + } else if (GetItemValue == TRUE) { + ASSERT(CurrentItemPackage != NULL); + // + // get the item VALUE for the previous flag + // + GetItemValue = FALSE; + CurrentItemPackage->Value = AllocateZeroPool(StrSize(Argv[LoopCounter])); + ASSERT(CurrentItemPackage->Value != NULL); + StrCpy(CurrentItemPackage->Value, Argv[LoopCounter]); + InsertTailList(*CheckPackage, (LIST_ENTRY*)CurrentItemPackage); + } else if (InternalIsFlag(Argv[LoopCounter]) == FALSE) { + // + // add this one as a non-flag + // + CurrentItemPackage = AllocatePool(sizeof(SHELL_PARAM_PACKAGE)); + ASSERT(CurrentItemPackage != NULL); + CurrentItemPackage->Name = NULL; + CurrentItemPackage->Type = TypePosition; + CurrentItemPackage->Value = AllocatePool(StrSize(Argv[LoopCounter])); + ASSERT(CurrentItemPackage->Value != NULL); + StrCpy(CurrentItemPackage->Value, Argv[LoopCounter]); + CurrentItemPackage->OriginalPosition = Count++; + InsertTailList(*CheckPackage, (LIST_ENTRY*)CurrentItemPackage); + } else if (InternalIsOnCheckList(Argv[LoopCounter], CheckList, &CurrentItemType) == TRUE) { + // + // this is a flag + // + CurrentItemPackage = AllocatePool(sizeof(SHELL_PARAM_PACKAGE)); + ASSERT(CurrentItemPackage != NULL); + CurrentItemPackage->Name = AllocatePool(StrSize(Argv[LoopCounter])); + ASSERT(CurrentItemPackage->Name != NULL); + StrCpy(CurrentItemPackage->Name, Argv[LoopCounter]); + CurrentItemPackage->Type = CurrentItemType; + CurrentItemPackage->OriginalPosition = (UINTN)(-1); + + // + // Does this flag require a value + // + if (CurrentItemPackage->Type == TypeValue) { + // + // trigger the next loop to populate the value of this item + // + GetItemValue = TRUE; + } else { + // + // this item has no value expected; we are done + // + CurrentItemPackage->Value = NULL; + InsertTailList(*CheckPackage, (LIST_ENTRY*)CurrentItemPackage); + } + } else if (ProblemParam) { + // + // this was a non-recognised flag... error! + // + *ProblemParam = AllocatePool(StrSize(Argv[LoopCounter])); + ASSERT(*ProblemParam != NULL); + StrCpy(*ProblemParam, Argv[LoopCounter]); + ShellCommandLineFreeVarList(*CheckPackage); + *CheckPackage = NULL; + return (EFI_VOLUME_CORRUPTED); + } else { + ShellCommandLineFreeVarList(*CheckPackage); + *CheckPackage = NULL; + return (EFI_VOLUME_CORRUPTED); + } + } + // + // support for AutoPageBreak + // + if (AutoPageBreak && ShellCommandLineGetFlag(*CheckPackage, L"-b")) { + ShellSetPageBreakMode(TRUE); + } + return (EFI_SUCCESS); +} + +/** + Checks the command line arguments passed against the list of valid ones. + Optionally removes NULL values first. + + If no initialization is required, then return RETURN_SUCCESS. + + @param CheckList pointer to list of parameters to check + @param CheckPackage pointer to pointer to list checked values + @param ProblemParam optional pointer to pointer to unicode string for + the paramater that caused failure. + @param AutoPageBreak will automatically set PageBreakEnabled for "b" parameter + + @retval EFI_SUCCESS The operation completed sucessfully. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed + @retval EFI_INVALID_PARAMETER A parameter was invalid + @retval EFI_VOLUME_CORRUPTED the command line was corrupt. an argument was + duplicated. the duplicated command line argument + was returned in ProblemParam if provided. + @retval EFI_DEVICE_ERROR the commands contained 2 opposing arguments. one + of the command line arguments was returned in + ProblemParam if provided. + @retval EFI_NOT_FOUND a argument required a value that was missing. + the invalid command line argument was returned in + ProblemParam if provided. +**/ +EFI_STATUS +EFIAPI +ShellCommandLineParse ( + IN CONST SHELL_PARAM_ITEM *CheckList, + OUT LIST_ENTRY **CheckPackage, + OUT CHAR16 **ProblemParam OPTIONAL, + IN BOOLEAN AutoPageBreak + ) +{ + // + // ASSERT that CheckList and CheckPackage aren't NULL + // + ASSERT(CheckList != NULL); + ASSERT(CheckPackage != NULL); + + // + // Check for UEFI Shell 2.0 protocols + // + if (mEfiShellParametersProtocol != NULL) { + return (InternalCommandLineParse(CheckList, + CheckPackage, + ProblemParam, + AutoPageBreak, + (CONST CHAR16**) mEfiShellParametersProtocol->Argv, + mEfiShellParametersProtocol->Argc )); + } + + // + // ASSERT That EFI Shell is not required + // + ASSERT (mEfiShellInterface != NULL); + return (InternalCommandLineParse(CheckList, + CheckPackage, + ProblemParam, + AutoPageBreak, + (CONST CHAR16**) mEfiShellInterface->Argv, + mEfiShellInterface->Argc )); +} + +/** + Frees shell variable list that was returned from ShellCommandLineParse. + + This function will free all the memory that was used for the CheckPackage + list of postprocessed shell arguments. + + this function has no return value. + + if CheckPackage is NULL, then return + + @param CheckPackage the list to de-allocate + **/ +VOID +EFIAPI +ShellCommandLineFreeVarList ( + IN LIST_ENTRY *CheckPackage + ) +{ + LIST_ENTRY *Node; + + // + // check for CheckPackage == NULL + // + if (CheckPackage == NULL) { + return; + } + + // + // for each node in the list + // + for (Node = GetFirstNode(CheckPackage); Node != CheckPackage ; Node = GetFirstNode(CheckPackage)) { + // + // Remove it from the list + // + RemoveEntryList(Node); + + // + // if it has a name free the name + // + if (((SHELL_PARAM_PACKAGE*)Node)->Name != NULL) { + FreePool(((SHELL_PARAM_PACKAGE*)Node)->Name); + } + + // + // if it has a value free the value + // + if (((SHELL_PARAM_PACKAGE*)Node)->Value != NULL) { + FreePool(((SHELL_PARAM_PACKAGE*)Node)->Value); + } + + // + // free the node structure + // + FreePool((SHELL_PARAM_PACKAGE*)Node); + } + // + // free the list head node + // + FreePool(CheckPackage); +} +/** + Checks for presence of a flag parameter + + flag arguments are in the form of "-" or "/", but do not have a value following the key + + if CheckPackage is NULL then return FALSE. + if KeyString is NULL then ASSERT() + + @param CheckPackage The package of parsed command line arguments + @param KeyString the Key of the command line argument to check for + + @retval TRUE the flag is on the command line + @retval FALSE the flag is not on the command line + **/ +BOOLEAN +EFIAPI +ShellCommandLineGetFlag ( + IN CONST LIST_ENTRY *CheckPackage, + IN CHAR16 *KeyString + ) +{ + LIST_ENTRY *Node; + + // + // ASSERT that both CheckPackage and KeyString aren't NULL + // + ASSERT(KeyString != NULL); + + // + // return FALSE for no package + // + if (CheckPackage == NULL) { + return (FALSE); + } + + // + // enumerate through the list of parametrs + // + for (Node = GetFirstNode(CheckPackage) ; !IsNull (CheckPackage, Node) ; Node = GetNextNode(CheckPackage, Node) ) { + // + // If the Name matches, return TRUE (and there may be NULL name) + // + if (((SHELL_PARAM_PACKAGE*)Node)->Name != NULL) { + if (StrCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) { + return (TRUE); + } + } + } + return (FALSE); +} +/** + returns value from command line argument + + value parameters are in the form of "- value" or "/ value" + + if CheckPackage is NULL, then return NULL; + + @param CheckPackage The package of parsed command line arguments + @param KeyString the Key of the command line argument to check for + + @retval NULL the flag is not on the command line + @return !=NULL pointer to unicode string of the value + **/ +CONST CHAR16* +EFIAPI +ShellCommandLineGetValue ( + IN CONST LIST_ENTRY *CheckPackage, + IN CHAR16 *KeyString + ) +{ + LIST_ENTRY *Node; + + // + // check for CheckPackage == NULL + // + if (CheckPackage == NULL) { + return (NULL); + } + + // + // enumerate through the list of parametrs + // + for (Node = GetFirstNode(CheckPackage) ; !IsNull (CheckPackage, Node) ; Node = GetNextNode(CheckPackage, Node) ) { + // + // If the Name matches, return the value (name can be NULL) + // + if (((SHELL_PARAM_PACKAGE*)Node)->Name != NULL) { + if (StrCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) { + return (((SHELL_PARAM_PACKAGE*)Node)->Value); + } + } + } + return (NULL); +} +/** + returns raw value from command line argument + + raw value parameters are in the form of "value" in a specific position in the list + + if CheckPackage is NULL, then return NULL; + + @param CheckPackage The package of parsed command line arguments + @param Position the position of the value + + @retval NULL the flag is not on the command line + @return !=NULL pointer to unicode string of the value + **/ +CONST CHAR16* +EFIAPI +ShellCommandLineGetRawValue ( + IN CONST LIST_ENTRY *CheckPackage, + IN UINT32 Position + ) +{ + LIST_ENTRY *Node; + + // + // check for CheckPackage == NULL + // + if (CheckPackage == NULL) { + return (NULL); + } + + // + // enumerate through the list of parametrs + // + for (Node = GetFirstNode(CheckPackage) ; !IsNull (CheckPackage, Node) ; Node = GetNextNode(CheckPackage, Node) ) { + // + // If the position matches, return the value + // + if (((SHELL_PARAM_PACKAGE*)Node)->OriginalPosition == Position) { + return (((SHELL_PARAM_PACKAGE*)Node)->Value); + } + } + return (NULL); +} \ No newline at end of file diff --git a/ShellPkg/Library/UefiShellLib/BaseShellLib.h b/ShellPkg/Library/UefiShellLib/BaseShellLib.h new file mode 100644 index 0000000000..1620641648 --- /dev/null +++ b/ShellPkg/Library/UefiShellLib/BaseShellLib.h @@ -0,0 +1,26 @@ +/** @file + Provides interface to shell functionality for shell commands and applications. + +Copyright (c) 2006 - 2009, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +typedef struct { + EFI_SHELL_GET_FILE_INFO GetFileInfo; + EFI_SHELL_SET_FILE_INFO SetFileInfo; + EFI_SHELL_READ_FILE ReadFile; + EFI_SHELL_WRITE_FILE WriteFile; + EFI_SHELL_CLOSE_FILE CloseFile; + EFI_SHELL_DELETE_FILE DeleteFile; + EFI_SHELL_GET_FILE_POSITION GetFilePosition; + EFI_SHELL_SET_FILE_POSITION SetFilePosition; + EFI_SHELL_FLUSH_FILE FlushFile; + EFI_SHELL_GET_FILE_SIZE GetFileSize; +} FILE_HANDLE_FUNCTION_MAP; diff --git a/ShellPkg/Library/UefiShellLib/BaseShellLib.inf b/ShellPkg/Library/UefiShellLib/BaseShellLib.inf new file mode 100644 index 0000000000..71c68cb280 --- /dev/null +++ b/ShellPkg/Library/UefiShellLib/BaseShellLib.inf @@ -0,0 +1,63 @@ +#/** @file +# Provides interface to shell functionality for shell commands and applications. +# +# Copyright (c) 2006 - 2009, Intel Corporation. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = BaseShellLib + FILE_GUID = 449D0F00-2148-4a43-9836-F10B3980ECF5 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = ShellLib|UEFI_APPLICATION UEFI_DRIVER + CONSTRUCTOR = ShellLibConstructor + DESTRUCTOR = ShellLibDestructor + +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources.common] + BaseShellLib.c + BaseShellLib.h + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + +[LibraryClasses] + UefiBootServicesTableLib + MemoryAllocationLib + DevicePathLib + BaseLib + BaseMemoryLib + DebugLib + FileHandleLib + +[Protocols] + gEfiSimpleFileSystemProtocolGuid # ALWAYS_CONSUMED + + # shell 2.0 + gEfiShellProtocolGuid # SOMETIMES_CONSUMED + gEfiShellParametersProtocolGuid # SOMETIMES_CONSUMED + + # 'old' shell + gEfiShellEnvironment2Guid # SOMETIMES_CONSUMED + gEfiShellInterfaceGuid # SOMETIMES_CONSUMED + +[Guids] + gEfiFileInfoGuid # ALWAYS_CONSUMED + gEfiShellEnvironment2ExtGuid # ALWAYS_CONSUMED + +[Pcd.common] + gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize # ALWAYS_CONSUMED