diff --git a/ShellPkg/Application/ShellLibTestApp/sa3.c b/ShellPkg/Application/ShellLibTestApp/sa3.c index ae677b4dfa..135590bed1 100644 --- a/ShellPkg/Application/ShellLibTestApp/sa3.c +++ b/ShellPkg/Application/ShellLibTestApp/sa3.c @@ -52,7 +52,7 @@ UefiMain ( EFI_FILE_INFO *pFileInfo; UINT64 Size; BOOLEAN NoFile; - EFI_SHELL_FILE_INFO *pShellFileInfo, *pShellFileInfo2; + EFI_SHELL_FILE_INFO *pShellFileInfo; LIST_ENTRY *List; FileHandle = NULL; @@ -97,7 +97,6 @@ UefiMain ( FreePool(pFileInfo); pFileInfo = NULL; Status = ShellCloseFile(&FileHandle); - ASSERT(FileHandle == NULL); ASSERT_EFI_ERROR(Status); Print(L"read, write, create, getinfo - pass\r\n"); @@ -125,7 +124,6 @@ UefiMain ( ASSERT(Size == 0x20); ASSERT_EFI_ERROR(Status); Status = ShellCloseFile(&FileHandle); - ASSERT(FileHandle == NULL); ASSERT_EFI_ERROR(Status); Print(L"setinfo and change size, getsize - pass\r\n"); @@ -145,7 +143,6 @@ UefiMain ( FreePool(pFileInfo); pFileInfo = NULL; Status = ShellDeleteFile(&FileHandle); - ASSERT(FileHandle == NULL); ASSERT_EFI_ERROR(Status); Print(L"reopen file - pass\r\n"); @@ -163,7 +160,6 @@ UefiMain ( ASSERT((pFileInfo->Attribute&EFI_FILE_DIRECTORY)==0); FreePool(pFileInfo); Status = ShellDeleteFile(&FileHandle); - ASSERT(FileHandle == NULL); ASSERT_EFI_ERROR(Status); Print(L"size of empty - pass\r\n"); @@ -183,7 +179,6 @@ UefiMain ( ASSERT(StrCmp(pFileInfo->FileName, FileName) == 0); ASSERT(pFileInfo->Attribute&EFI_FILE_DIRECTORY); Status = ShellDeleteFile(&FileHandle); - ASSERT(FileHandle == NULL); ASSERT_EFI_ERROR(Status); Print(L"Directory create - pass\r\n"); @@ -206,7 +201,7 @@ UefiMain ( 0 ); ASSERT_EFI_ERROR(Status); - Status = ShellFindFirstFile(FileHandle, pFileInfo); + Status = ShellFindFirstFile(FileHandle, &pFileInfo); ASSERT_EFI_ERROR(Status); Status = ShellFindNextFile(FileHandle, pFileInfo, &NoFile); ASSERT_EFI_ERROR(Status); @@ -218,7 +213,6 @@ UefiMain ( ASSERT_EFI_ERROR(Status); /// @todo - why is NoFile never set? limitation of NT32 file system? Status = ShellDeleteFile(&FileHandle); - ASSERT(FileHandle == NULL); ASSERT(Status == RETURN_WARN_DELETE_FAILURE); Print(L"FindFirst - pass\r\n"); Print(L"FindNext - Verify with real EFI system. Cant verify NoFile under NT32\r\n"); @@ -233,10 +227,7 @@ UefiMain ( ASSERT(pShellFileInfo->Info->FileSize == 0); ASSERT(StrCmp(pShellFileInfo->Info->FileName, L"File.txt") == 0); ASSERT(pShellFileInfo->Info->Attribute == 0); - pShellFileInfo2 = (EFI_SHELL_FILE_INFO*)0x12345678; - Status = ShellOpenFileMetaArg(L"testDir\\*.*", EFI_FILE_MODE_READ, &pShellFileInfo2); - ASSERT(pShellFileInfo2 == NULL); - ASSERT(Status == EFI_UNSUPPORTED); + Status = ShellCloseFileMetaArg(&pShellFileInfo); ASSERT_EFI_ERROR(Status); Print(L"Open/Close Meta Arg - pass\r\n"); @@ -250,7 +241,6 @@ UefiMain ( ); ASSERT_EFI_ERROR(Status); Status = ShellDeleteFile(&FileHandle); - ASSERT(FileHandle == NULL); StrCpy(FileName, L"testDir"); ASSERT_EFI_ERROR(Status); Status = ShellOpenFileByName(FileName, @@ -259,7 +249,6 @@ UefiMain ( 0 ); Status = ShellDeleteFile(&FileHandle); - ASSERT(FileHandle == NULL); ASSERT_EFI_ERROR(Status); // get environment variable @@ -286,7 +275,7 @@ UefiMain ( ASSERT(ShellCommandLineGetFlag(List, L"/Param5") == FALSE); ASSERT(ShellCommandLineGetFlag(List, L"/Param1") != FALSE); ASSERT(StrCmp(ShellCommandLineGetValue(List, L"/Param2"), L"Val1")==0); - ASSERT(StrCmp(ShellCommandLineGetRawValue(List, 0), L"SimpleApplication")==0); + ASSERT(StrCmp(ShellCommandLineGetRawValue(List, 0), L"SimpleApplication.efi")==0); ShellCommandLineFreeVarList(List); } else { diff --git a/ShellPkg/Include/Guid/ShellEnvironment2Ext.h b/ShellPkg/Include/Guid/ShellEnvironment2Ext.h new file mode 100644 index 0000000000..49770057be --- /dev/null +++ b/ShellPkg/Include/Guid/ShellEnvironment2Ext.h @@ -0,0 +1,25 @@ +/** @file + GUID for EFI shell Environment2 Extension + + Copyright (c) 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. + +**/ + +#ifndef _SHELLPKG_SHELL_ENV2_EXT_GUID_H +#define _SHELLPKG_SHELL_ENV2_EXT_GUID_H + +#define SHELLPKG_SHELL_ENV2_EXT_GUID \ +{ \ + 0xd2c18636, 0x40e5, 0x4eb5, {0xa3, 0x1b, 0x36, 0x69, 0x5f, 0xd4, 0x2c, 0x87} \ +}; + +extern EFI_GUID gEfiShellEnvironment2ExtGuid; + +#endif diff --git a/ShellPkg/Include/Guid/ShellPkgTokenSpace.h b/ShellPkg/Include/Guid/ShellPkgTokenSpace.h new file mode 100644 index 0000000000..9803e9c4aa --- /dev/null +++ b/ShellPkg/Include/Guid/ShellPkgTokenSpace.h @@ -0,0 +1,25 @@ +/** @file + GUID for ShellPkg PCD Token Space + + Copyright (c) 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. + +**/ + +#ifndef _SHELLPKG_TOKEN_SPACE_GUID_H_ +#define _SHELLPKG_TOKEN_SPACE_GUID_H_ + +#define SHELLPKG_TOKEN_SPACE_GUID \ +{ \ + 0x171e9188, 0x31d3, 0x40f5, { 0xb1, 0xc, 0x53, 0x9b, 0x2d, 0xb9, 0x40, 0xcd } \ +}; + +extern EFI_GUID gEfiShellPkgTokenSpaceGuid; + +#endif diff --git a/ShellPkg/Include/Library/FileHandleLib.h b/ShellPkg/Include/Library/FileHandleLib.h new file mode 100644 index 0000000000..8140dae32f --- /dev/null +++ b/ShellPkg/Include/Library/FileHandleLib.h @@ -0,0 +1,331 @@ +/** @file + Provides interface to EFI_FILE_HANDLE functionality. + +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 + +/** + 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 +FileHandleGetInfo ( + IN EFI_FILE_HANDLE 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 +FileHandleSetInfo ( + IN EFI_FILE_HANDLE FileHandle, + IN CONST EFI_FILE_INFO *FileInfo + ); + +/** + 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 +FileHandleRead( + IN EFI_FILE_HANDLE FileHandle, + IN OUT UINTN *BufferSize, + OUT VOID *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 +FileHandleWrite( + IN EFI_FILE_HANDLE FileHandle, + IN OUT UINTN *BufferSize, + IN VOID *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 +FileHandleClose ( + IN EFI_FILE_HANDLE 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 +FileHandleDelete ( + IN EFI_FILE_HANDLE 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 +FileHandleSetPosition ( + IN EFI_FILE_HANDLE FileHandle, + IN UINT64 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 +FileHandleGetPosition ( + IN EFI_FILE_HANDLE FileHandle, + OUT UINT64 *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 +FileHandleFlush ( + IN EFI_FILE_HANDLE FileHandle + ); + +/** + function to determine if a given handle is a directory handle + + if DirHandle is NULL then ASSERT() + + open the file information on the DirHandle and verify that the Attribute + includes EFI_FILE_DIRECTORY bit set. + + @param DirHandle Handle to open file + + @retval EFI_SUCCESS DirHandle is a directory + @retval EFI_INVALID_PARAMETER DirHandle did not have EFI_FILE_INFO available + @retval EFI_NOT_FOUND DirHandle is not a directory +**/ +EFI_STATUS +EFIAPI +FileHandleIsDirectory ( + IN EFI_FILE_HANDLE DirHandle + ); + +/** + 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 FileHandleFindNextFile() 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 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 FileHandleGetInfo, FileHandleSetPosition, + or FileHandleRead +**/ +EFI_STATUS +EFIAPI +FileHandleFindFirstFile ( + IN EFI_FILE_HANDLE DirHandle, + OUT EFI_FILE_INFO **Buffer + ); +/** + Retrieves the next file in a directory. + + To use this function, caller must call the FileHandleFindFirstFile() 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 FileHandleFindNextFile() 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 +FileHandleFindNextFile( + IN EFI_FILE_HANDLE DirHandle, + OUT EFI_FILE_INFO *Buffer, + OUT BOOLEAN *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 +FileHandleGetSize ( + IN EFI_FILE_HANDLE FileHandle, + OUT UINT64 *Size + ); \ No newline at end of file diff --git a/ShellPkg/Include/Library/ShellLib.h b/ShellPkg/Include/Library/ShellLib.h index f5e5ba60de..5614d7174f 100644 --- a/ShellPkg/Include/Library/ShellLib.h +++ b/ShellPkg/Include/Library/ShellLib.h @@ -16,7 +16,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #define __SHELL_LIB__ #include -#include #include /** @@ -363,8 +362,10 @@ ShellFlushFile ( in the directory's info. Caller can use ShellFindNextFile() to get subsequent files. + Caller must use FreePool on *Buffer opon completion of all file searching. + @param DirHandle The file handle of the directory to search - @param Buffer Pointer to buffer for file's information + @param Buffer Pointer to pointer to buffer for file's information @retval EFI_SUCCESS Found the first file. @retval EFI_NOT_FOUND Cannot find the directory. @@ -377,7 +378,7 @@ EFI_STATUS EFIAPI ShellFindFirstFile ( IN EFI_FILE_HANDLE DirHandle, - OUT EFI_FILE_INFO *Buffer + OUT EFI_FILE_INFO **Buffer ); /** @@ -613,6 +614,10 @@ typedef struct { ParamType Type; } SHELL_PARAM_ITEM; + +/// Helper structure for no parameters (besides -? and -b) +extern SHELL_PARAM_ITEM EmptyParamList[]; + /** Checks the command line arguments passed against the list of valid ones. Optionally removes NULL values first. @@ -726,4 +731,22 @@ ShellCommandLineGetRawValue ( IN UINT32 Position ); +/** + 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 ( + ); + #endif // __SHELL_LIB__ \ No newline at end of file diff --git a/ShellPkg/Include/Protocol/EfiShell.h b/ShellPkg/Include/Protocol/EfiShell.h index 8421056145..bd0aebe1d8 100644 --- a/ShellPkg/Include/Protocol/EfiShell.h +++ b/ShellPkg/Include/Protocol/EfiShell.h @@ -23,13 +23,10 @@ 0x6302d008, 0x7f9b, 0x4f30, { 0x87, 0xac, 0x60, 0xc9, 0xfe, 0xf5, 0xda, 0x4e } \ } -typedef struct _EFI_LIST_ENTRY { - struct _EFI_LIST_ENTRY *Flink; - struct _EFI_LIST_ENTRY *Blink; -} EFI_LIST_ENTRY; - +// replaced EFI_LIST_ENTRY with LIST_ENTRY for simplicity. +// they are identical outside of the name. typedef struct { - EFI_LIST_ENTRY Link; + LIST_ENTRY Link; EFI_STATUS Status; CONST CHAR16 *FullName; CONST CHAR16 *FileName; @@ -317,6 +314,16 @@ typedef UINT32 EFI_SHELL_DEVICE_NAME_FLAGS; handle. If no user-readable name could be generated, then *BestDeviceName will be NULL and EFI_NOT_FOUND will be returned. + If EFI_DEVICE_NAME_USE_COMPONENT_NAME is set, then the function will return the + device’s name using the EFI_COMPONENT_NAME2_PROTOCOL, if present on + DeviceHandle. + + If EFI_DEVICE_NAME_USE_DEVICE_PATH is set, then the function will return the + device’s name using the EFI_DEVICE_PATH_PROTOCOL, if present on DeviceHandle. + If both EFI_DEVICE_NAME_USE_COMPONENT_NAME and + EFI_DEVICE_NAME_USE_DEVICE_PATH are set, then + EFI_DEVICE_NAME_USE_COMPONENT_NAME will have higher priority. + @param DeviceHandle The handle of the device. @param Flags Determines the possible sources of component names. @param Language A pointer to the language specified for the device @@ -946,4 +953,9 @@ typedef struct _EFI_SHELL_PROTOCOL { extern EFI_GUID gEfiShellProtocolGuid; +enum ShellVersion { + SHELL_MAJOR_VERSION = 2, + SHELL_MINOR_VERSION = 0 +}; + #endif diff --git a/ShellPkg/Include/Protocol/EfiShellEnvironment2.h b/ShellPkg/Include/Protocol/EfiShellEnvironment2.h index 537b916071..cafecb0cf3 100644 --- a/ShellPkg/Include/Protocol/EfiShellEnvironment2.h +++ b/ShellPkg/Include/Protocol/EfiShellEnvironment2.h @@ -82,7 +82,7 @@ EFI_STATUS **/ typedef struct { UINT32 Signature; ///< SHELL_FILE_ARG_SIGNATURE - EFI_LIST_ENTRY Link; ///< linked list helper + LIST_ENTRY Link; ///< linked list helper EFI_STATUS Status; ///< File's status EFI_FILE_HANDLE Parent; ///< what is the Parent file of this file @@ -270,7 +270,7 @@ CHAR16* support for wildcard characters ('?' and '*') in the Arg path. if there are any wildcard characters in the path this function will find any and all files that match the wildcards. the return is a double linked list based on the - EFI_LIST_ENTRY linked list structure. use this in conjunction with the + LIST_ENTRY linked list structure. use this in conjunction with the SHELL_FILE_ARG_SIGNATURE to get the SHELL_FILE_ARG structures that are returned. The memory allocated by the callee for this list is freed by making a call to SHELLENV_FREE_FILE_LIST. @@ -288,7 +288,7 @@ CHAR16* EFI_STATUS (EFIAPI *SHELLENV_FILE_META_ARG) ( IN CHAR16 *Arg, - IN OUT EFI_LIST_ENTRY *ListHead + IN OUT LIST_ENTRY *ListHead ); /** @@ -301,7 +301,7 @@ EFI_STATUS typedef EFI_STATUS (EFIAPI *SHELLENV_FREE_FILE_LIST) ( - IN OUT EFI_LIST_ENTRY *ListHead + IN OUT LIST_ENTRY *ListHead ); /** @@ -618,7 +618,7 @@ typedef struct { **/ typedef struct { UINTN Signature; ///< PROTOCOL_INFO_SIGNATURE - EFI_LIST_ENTRY Link; ///< standard lined list helper member + LIST_ENTRY Link; ///< standard lined list helper member // // parsing info for the protocol // @@ -845,7 +845,7 @@ EFI_STATUS support the wildcard characters ('?' and '*') in the Arg path. if there are any wildcard characters in the path this function will return EFI_INVALID_PARAMETER. the return is a double linked list based on the - EFI_LIST_ENTRY linked list structure. use this in conjunction with the + LIST_ENTRY linked list structure. use this in conjunction with the SHELL_FILE_ARG_SIGNATURE to get the SHELL_FILE_ARG structures that are returned. The memory allocated by the callee for this list is freed by making a call to SHELLENV_FREE_FILE_LIST. @@ -864,7 +864,7 @@ typedef EFI_STATUS (EFIAPI *SHELLENV_FILE_META_ARG_NO_WILDCARD) ( IN CHAR16 *Arg, - IN OUT EFI_LIST_ENTRY *ListHead + IN OUT LIST_ENTRY *ListHead ); /** @@ -885,7 +885,7 @@ EFI_STATUS typedef EFI_STATUS (EFIAPI *SHELLENV_DEL_DUP_FILE) ( - IN EFI_LIST_ENTRY * ListHead + IN LIST_ENTRY * ListHead ); /** diff --git a/ShellPkg/Library/BaseFileHandleLib/BaseFileHandleLib.c b/ShellPkg/Library/BaseFileHandleLib/BaseFileHandleLib.c new file mode 100644 index 0000000000..6822b748b4 --- /dev/null +++ b/ShellPkg/Library/BaseFileHandleLib/BaseFileHandleLib.c @@ -0,0 +1,623 @@ +/** @file + Provides interface to EFI_FILE_HANDLE functionality. + +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 + +#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 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 +FileHandleGetInfo ( + IN EFI_FILE_HANDLE FileHandle + ) +{ + EFI_GUID FileInfoGuid; + EFI_FILE_INFO *pFileInfo; + UINTN FileInfoSize; + EFI_STATUS Status; + + // + // ASSERT if FileHandle is NULL + // + ASSERT (FileHandle != NULL); + + // + // Get the required size to allocate + // + FileInfoGuid = gEfiFileInfoGuid; + FileInfoSize = 0; + pFileInfo = NULL; + Status = FileHandle->GetInfo(FileHandle, + &FileInfoGuid, + &FileInfoSize, + pFileInfo); + // + // error is expected. getting size to allocate + // + ASSERT (Status == EFI_BUFFER_TOO_SMALL); + pFileInfo = AllocateZeroPool(FileInfoSize); + ASSERT (pFileInfo != NULL); + // + // now get the information + // + Status = FileHandle->GetInfo(FileHandle, + &FileInfoGuid, + &FileInfoSize, + pFileInfo); + // + // if we got an error free the memory and return NULL + // + if (EFI_ERROR(Status)) { + FreePool(pFileInfo); + return NULL; + } + return (pFileInfo); +} + +/** + 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 +FileHandleSetInfo ( + IN EFI_FILE_HANDLE FileHandle, + IN CONST EFI_FILE_INFO *FileInfo + ) +{ + EFI_GUID FileInfoGuid; + + // + // ASSERT if the FileHandle or FileInfo is NULL + // + ASSERT (FileHandle != NULL); + ASSERT (FileInfo != NULL); + + FileInfoGuid = gEfiFileInfoGuid; + // + // Set the info + // + return (FileHandle->SetInfo(FileHandle, + &FileInfoGuid, + (UINTN)FileInfo->Size, + (EFI_FILE_INFO*)FileInfo)); +} + +/** + 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 +FileHandleRead( + IN EFI_FILE_HANDLE FileHandle, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + // + // ASSERT if FileHandle is NULL + // + ASSERT (FileHandle != NULL); + + // + // Perform the read based on EFI_FILE_PROTOCOL + // + return (FileHandle->Read(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 +FileHandleWrite( + IN EFI_FILE_HANDLE FileHandle, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + // + // ASSERT if FileHandle is NULL + // + ASSERT (FileHandle != NULL); + // + // Perform the write based on EFI_FILE_PROTOCOL + // + return (FileHandle->Write(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 +FileHandleClose ( + IN EFI_FILE_HANDLE FileHandle + ) +{ + EFI_STATUS Status; + // + // ASSERT if FileHandle is NULL + // + ASSERT (FileHandle != NULL); + // + // Perform the Close based on EFI_FILE_PROTOCOL + // + Status = FileHandle->Close(FileHandle); + return Status; +} + +/** + 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 +FileHandleDelete ( + IN EFI_FILE_HANDLE FileHandle + ) +{ + EFI_STATUS Status; + // + // ASSERT if FileHandle is NULL + // + ASSERT (FileHandle != NULL); + // + // Perform the Delete based on EFI_FILE_PROTOCOL + // + Status = FileHandle->Delete(FileHandle); + return Status; +} + +/** + 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 +FileHandleSetPosition ( + IN EFI_FILE_HANDLE FileHandle, + IN UINT64 Position + ) +{ + // + // ASSERT if FileHandle is NULL + // + ASSERT (FileHandle != NULL); + // + // Perform the SetPosition based on EFI_FILE_PROTOCOL + // + return (FileHandle->SetPosition(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 +FileHandleGetPosition ( + IN EFI_FILE_HANDLE FileHandle, + OUT UINT64 *Position + ) +{ + // + // ASSERT if FileHandle is NULL + // + ASSERT (FileHandle != NULL); + // + // Perform the GetPosition based on EFI_FILE_PROTOCOL + // + return (FileHandle->GetPosition(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 +FileHandleFlush ( + IN EFI_FILE_HANDLE FileHandle + ) +{ + // + // ASSERT if FileHandle is NULL + // + ASSERT (FileHandle != NULL); + // + // Perform the Flush based on EFI_FILE_PROTOCOL + // + return (FileHandle->Flush(FileHandle)); +} + +/** + function to determine if a given handle is a directory handle + + if DirHandle is NULL then ASSERT() + + open the file information on the DirHandle and verify that the Attribute + includes EFI_FILE_DIRECTORY bit set. + + @param DirHandle Handle to open file + + @retval EFI_SUCCESS DirHandle is a directory + @retval EFI_INVALID_PARAMETER DirHandle did not have EFI_FILE_INFO available + @retval EFI_NOT_FOUND DirHandle is not a directory +**/ +EFI_STATUS +EFIAPI +FileHandleIsDirectory ( + IN EFI_FILE_HANDLE DirHandle + ) +{ + EFI_FILE_INFO *DirInfo; + + // + // ASSERT if DirHandle is NULL + // + ASSERT(DirHandle != NULL); + + // + // get the file information for DirHandle + // + DirInfo = FileHandleGetInfo (DirHandle); + + // + // Parse DirInfo + // + if (DirInfo == NULL) { + // + // We got nothing... + // + return (EFI_INVALID_PARAMETER); + } + if ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0) { + // + // Attributes say this is not a directory + // + FreePool (DirInfo); + return (EFI_NOT_FOUND); + } + // + // all good... + // + FreePool (DirInfo); + return (EFI_SUCCESS); +} + +/** + 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 FileHandleFindNextFile() 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 FileHandleGetInfo, FileHandleSetPosition, + or FileHandleRead +**/ +EFI_STATUS +EFIAPI +FileHandleFindFirstFile ( + IN EFI_FILE_HANDLE DirHandle, + OUT EFI_FILE_INFO **Buffer + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + + // + // ASSERTs + // + ASSERT (DirHandle != NULL); + ASSERT (Buffer != NULL); + + // + // verify that DirHandle is a directory + // + Status = FileHandleIsDirectory(DirHandle); + if (EFI_ERROR(Status)) { + return (Status); + } + + // + // reset to the begining of the directory + // + Status = FileHandleSetPosition(DirHandle, 0); + if (EFI_ERROR(Status)) { + return (Status); + } + + // + // Allocate a buffer sized to struct size + enough for the string at the end + // + BufferSize = FIND_XXXXX_FILE_BUFFER_SIZE; + *Buffer = AllocateZeroPool(BufferSize); + ASSERT (*Buffer != NULL); + + // + // read in the info about the first file + // + Status = FileHandleRead (DirHandle, &BufferSize, *Buffer); + ASSERT(Status != EFI_BUFFER_TOO_SMALL); + if (EFI_ERROR(Status)) { + FreePool(*Buffer); + *Buffer = NULL; + return (Status); + } + return (EFI_SUCCESS); +} +/** + Retrieves the next file in a directory. + + To use this function, caller must call the FileHandleFindFirstFile() 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 FileHandleFindNextFile() 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 +FileHandleFindNextFile( + IN EFI_FILE_HANDLE DirHandle, + OUT EFI_FILE_INFO *Buffer, + OUT BOOLEAN *NoFile + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + + // + // ASSERTs for DirHandle or Buffer or NoFile poitners being NULL + // + ASSERT (DirHandle != NULL); + ASSERT (Buffer != NULL); + ASSERT (NoFile != NULL); + + // + // verify that DirHandle is a directory + // + Status = FileHandleIsDirectory(DirHandle); + if (EFI_ERROR(Status)) { + return (Status); + } + + // + // This BufferSize MUST stay equal to the originally allocated one in GetFirstFile + // + BufferSize = FIND_XXXXX_FILE_BUFFER_SIZE; + + // + // read in the info about the next file + // + Status = FileHandleRead (DirHandle, &BufferSize, Buffer); + ASSERT(Status != EFI_BUFFER_TOO_SMALL); + if (EFI_ERROR(Status)) { + return (Status); + } + + // + // If we read 0 bytes (but did not have erros) we already read in the last file. + // + if (BufferSize == 0) { + FreePool(Buffer); + *NoFile = TRUE; + } + + return (EFI_SUCCESS); +} +/** + 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 +FileHandleGetSize ( + IN EFI_FILE_HANDLE FileHandle, + OUT UINT64 *Size + ) +{ + EFI_FILE_INFO *FileInfo; + + // + // ASSERT for FileHandle or Size being NULL + // + ASSERT (FileHandle != NULL); + ASSERT (Size != NULL); + + // + // get the FileInfo structure + // + FileInfo = FileHandleGetInfo(FileHandle); + if (FileInfo == NULL) { + return (EFI_DEVICE_ERROR); + } + + // + // Assign the Size pointer to the correct value + // + *Size = FileInfo->FileSize; + + // + // free the FileInfo memory + // + FreePool(FileInfo); + + return (EFI_SUCCESS); +} \ No newline at end of file diff --git a/ShellPkg/Library/BaseFileHandleLib/BaseFileHandleLib.inf b/ShellPkg/Library/BaseFileHandleLib/BaseFileHandleLib.inf new file mode 100644 index 0000000000..48489b405a --- /dev/null +++ b/ShellPkg/Library/BaseFileHandleLib/BaseFileHandleLib.inf @@ -0,0 +1,49 @@ +#/** @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 = BaseFileHandleLib + FILE_GUID = 9495D344-9D8A-41f3-8D17-E2FD238C4E71 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = FileHandleLib|UEFI_APPLICATION UEFI_DRIVER + +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources.common] + BaseFileHandleLib.c + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + +[LibraryClasses] + UefiBootServicesTableLib + MemoryAllocationLib + DevicePathLib + BaseLib + BaseMemoryLib + DebugLib + +[Protocols] + +[Guids] + gEfiFileInfoGuid # ALWAYS_CONSUMED + +[Pcd.common] + diff --git a/ShellPkg/Library/BaseShellLib/BaseShellLib.c b/ShellPkg/Library/BaseShellLib/BaseShellLib.c index 205974d519..a0e2e492e1 100644 --- a/ShellPkg/Library/BaseShellLib/BaseShellLib.c +++ b/ShellPkg/Library/BaseShellLib/BaseShellLib.c @@ -20,21 +20,35 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #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) -EFI_SHELL_ENVIRONMENT2 *mEfiShellEnvironment2; -EFI_SHELL_INTERFACE *mEfiShellInterface; -EFI_SHELL_PROTOCOL *mEfiShellProtocol; -EFI_SHELL_PARAMETERS_PROTOCOL *mEfiShellParametersProtocol; -EFI_HANDLE mEfiShellEnvironment2Handle; -EFI_LIST_ENTRY *mOldStyleFileList; +// +// 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 @@ -112,36 +126,14 @@ ShellFindSE2 ( return (Status); } -/** - 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 ( +ShellLibConstructorWorker ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable - ) -{ +){ EFI_STATUS Status; - ASSERT(SystemTable != NULL); - ASSERT(gBS != NULL); - - mEfiShellEnvironment2 = NULL; - mEfiShellProtocol = NULL; - mEfiShellParametersProtocol = NULL; - mEfiShellInterface = NULL; - mEfiShellEnvironment2Handle = NULL; - mOldStyleFileList = NULL; - // // UEFI 2.0 shell interfaces (used preferentially) // @@ -192,10 +184,69 @@ ShellLibConstructor ( // 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. @@ -212,27 +263,68 @@ ShellLibDestructor ( &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); + 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. @@ -253,47 +345,7 @@ ShellGetFileInfo ( IN EFI_FILE_HANDLE FileHandle ) { - EFI_GUID FileInfoGuid; - EFI_FILE_INFO *pFileInfo; - UINTN FileInfoSize; - EFI_STATUS Status; - - // - // ASSERT if FileHandle is NULL - // - ASSERT (FileHandle != NULL); - - // - // Get the required size to allocate - // - FileInfoGuid = gEfiFileInfoGuid; - FileInfoSize = 0; - pFileInfo = NULL; - Status = FileHandle->GetInfo(FileHandle, - &FileInfoGuid, - &FileInfoSize, - pFileInfo); - // - // error is expected. getting size to allocate - // - ASSERT (Status == EFI_BUFFER_TOO_SMALL); - pFileInfo = AllocateZeroPool(FileInfoSize); - ASSERT (pFileInfo != NULL); - // - // now get the information - // - Status = FileHandle->GetInfo(FileHandle, - &FileInfoGuid, - &FileInfoSize, - pFileInfo); - // - // if we got an error free the memory and return NULL - // - if (EFI_ERROR(Status)) { - FreePool(pFileInfo); - return NULL; - } - return (pFileInfo); + return (FileFunctionMap.GetFileInfo(FileHandle)); } /** @@ -321,22 +373,7 @@ ShellSetFileInfo ( IN EFI_FILE_INFO *FileInfo ) { - EFI_GUID FileInfoGuid; - - // - // ASSERT if the FileHandle or FileInfo is NULL - // - ASSERT (FileHandle != NULL); - ASSERT (FileInfo != NULL); - - FileInfoGuid = gEfiFileInfoGuid; - // - // Set the info - // - return (FileHandle->SetInfo(FileHandle, - &FileInfoGuid, - (UINTN)FileInfo->Size, - FileInfo)); + return (FileFunctionMap.SetFileInfo(FileHandle, FileInfo)); } /** @@ -404,89 +441,90 @@ ShellOpenFileByDevicePath( Status = ShellOpenFileByName(FileName, FileHandle, OpenMode, Attributes); FreePool(FileName); return (Status); - } else { + } + + + // + // use old shell method. + // + Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, + FilePath, + DeviceHandle); + if (EFI_ERROR (Status)) { + return Status; + } + Status = gBS->OpenProtocol(*DeviceHandle, + &gEfiSimpleFileSystemProtocolGuid, + &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)) { // - // use old shell method. + // For file system access each node should be a file path component // - Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, - FilePath, - DeviceHandle); - if (EFI_ERROR (Status)) { - return Status; - } - Status = gBS->OpenProtocol(*DeviceHandle, - &gEfiSimpleFileSystemProtocolGuid, - &EfiSimpleFileSystemProtocol, - gImageHandle, - NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL); - if (EFI_ERROR (Status)) { - return Status; - } - Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, FileHandle); - if (EFI_ERROR (Status)) { + if (DevicePathType (*FilePath) != MEDIA_DEVICE_PATH || + DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP + ) { FileHandle = NULL; - return Status; + return (EFI_INVALID_PARAMETER); } + // + // Open this file path node + // + LastHandle = *FileHandle; + *FileHandle = NULL; // - // go down directories one node at a time. + // Try to test opening an existing file // - 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; + Status = LastHandle->Open ( + LastHandle, + FileHandle, + ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName, + OpenMode &~EFI_FILE_MODE_CREATE, + 0 + ); - // - // Try to test opening an existing file - // + // + // 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 &~EFI_FILE_MODE_CREATE, - 0 + OpenMode, + Attributes ); - - // - // 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); + // + // Close the last node + // + LastHandle->Close (LastHandle); + + if (EFI_ERROR(Status)) { + return (Status); + } + + // + // Get the next node + // + *FilePath = NextDevicePathNode (*FilePath); } + return (EFI_SUCCESS); } /** @@ -544,6 +582,8 @@ ShellOpenFileByName( return (mEfiShellProtocol->OpenFileByName(FileName, FileHandle, OpenMode)); + + ///@todo add the attributes } // // Using EFI Shell version @@ -643,15 +683,7 @@ ShellReadFile( OUT VOID *Buffer ) { - // - // ASSERT if FileHandle is NULL - // - ASSERT (FileHandle != NULL); - - // - // Perform the read based on EFI_FILE_PROTOCOL - // - return (FileHandle->Read(FileHandle, BufferSize, Buffer)); + return (FileFunctionMap.ReadFile(FileHandle, BufferSize, Buffer)); } @@ -687,14 +719,7 @@ ShellWriteFile( IN VOID *Buffer ) { - // - // ASSERT if FileHandle is NULL - // - ASSERT (FileHandle != NULL); - // - // Perform the write based on EFI_FILE_PROTOCOL - // - return (FileHandle->Write(FileHandle, BufferSize, Buffer)); + return (FileFunctionMap.WriteFile(FileHandle, BufferSize, Buffer)); } /** @@ -714,18 +739,7 @@ ShellCloseFile ( IN EFI_FILE_HANDLE *FileHandle ) { - EFI_STATUS Status; - // - // ASSERT if FileHandle is NULL - // - ASSERT (FileHandle != NULL); - ASSERT (*FileHandle != NULL); - // - // Perform the Close based on EFI_FILE_PROTOCOL - // - Status = (*FileHandle)->Close(*FileHandle); - *FileHandle = NULL; - return Status; + return (FileFunctionMap.CloseFile(*FileHandle)); } /** @@ -748,18 +762,7 @@ ShellDeleteFile ( IN EFI_FILE_HANDLE *FileHandle ) { - EFI_STATUS Status; - // - // ASSERT if FileHandle is NULL - // - ASSERT (FileHandle != NULL); - ASSERT (*FileHandle != NULL); - // - // Perform the Delete based on EFI_FILE_PROTOCOL - // - Status = (*FileHandle)->Delete(*FileHandle); - *FileHandle = NULL; - return Status; + return (FileFunctionMap.DeleteFile(*FileHandle)); } /** @@ -788,14 +791,7 @@ ShellSetFilePosition ( IN UINT64 Position ) { - // - // ASSERT if FileHandle is NULL - // - ASSERT (FileHandle != NULL); - // - // Perform the SetPosition based on EFI_FILE_PROTOCOL - // - return (FileHandle->SetPosition(FileHandle, Position)); + return (FileFunctionMap.SetFilePosition(FileHandle, Position)); } /** @@ -820,14 +816,7 @@ ShellGetFilePosition ( OUT UINT64 *Position ) { - // - // ASSERT if FileHandle is NULL - // - ASSERT (FileHandle != NULL); - // - // Perform the GetPosition based on EFI_FILE_PROTOCOL - // - return (FileHandle->GetPosition(FileHandle, Position)); + return (FileFunctionMap.GetFilePosition(FileHandle, Position)); } /** Flushes data on a file @@ -849,69 +838,7 @@ ShellFlushFile ( IN EFI_FILE_HANDLE FileHandle ) { - // - // ASSERT if FileHandle is NULL - // - ASSERT (FileHandle != NULL); - // - // Perform the Flush based on EFI_FILE_PROTOCOL - // - return (FileHandle->Flush(FileHandle)); -} - -/** - function to determine if a given handle is a directory handle - - if DirHandle is NULL then ASSERT() - - open the file information on the DirHandle and verify that the Attribute - includes EFI_FILE_DIRECTORY bit set. - - @param DirHandle Handle to open file - - @retval EFI_SUCCESS DirHandle is a directory - @retval EFI_INVALID_PARAMETER DirHandle did not have EFI_FILE_INFO available - @retval EFI_NOT_FOUND DirHandle is not a directory -**/ -EFI_STATUS -EFIAPI -InternalShellIsDirectory ( - IN EFI_FILE_HANDLE DirHandle - ) -{ - EFI_FILE_INFO *DirInfo; - - // - // ASSERT if DirHandle is NULL - // - ASSERT(DirHandle != NULL); - - // - // get the file information for DirHandle - // - DirInfo = ShellGetFileInfo (DirHandle); - - // - // Parse DirInfo - // - if (DirInfo == NULL) { - // - // We got nothing... - // - return (EFI_INVALID_PARAMETER); - } - if ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0) { - // - // Attributes say this is not a directory - // - FreePool (DirInfo); - return (EFI_NOT_FOUND); - } - // - // all good... - // - FreePool (DirInfo); - return (EFI_SUCCESS); + return (FileFunctionMap.FlushFile(FileHandle)); } /** @@ -936,49 +863,13 @@ EFI_STATUS EFIAPI ShellFindFirstFile ( IN EFI_FILE_HANDLE DirHandle, - OUT EFI_FILE_INFO *Buffer + OUT EFI_FILE_INFO **Buffer ) { - EFI_STATUS Status; - UINTN BufferSize; - // - // ASSERT if DirHandle is NULL + // pass to file handle lib // - ASSERT (DirHandle != NULL); - - // - // verify that DirHandle is a directory - // - Status = InternalShellIsDirectory(DirHandle); - if (EFI_ERROR(Status)) { - return (Status); - } - - // - // reset to the begining of the directory - // - Status = ShellSetFilePosition (DirHandle, 0); - if (EFI_ERROR(Status)) { - return (Status); - } - - // - // Allocate a buffer sized to struct size + enough for the string at the end - // - BufferSize = FIND_XXXXX_FILE_BUFFER_SIZE; - Buffer = AllocateZeroPool(BufferSize); - ASSERT (Buffer != NULL); - - // - // read in the info about the first file - // - Status = ShellReadFile (DirHandle, &BufferSize, Buffer); - ASSERT(Status != EFI_BUFFER_TOO_SMALL); - if (EFI_ERROR(Status)) { - return (Status); - } - return (EFI_SUCCESS); + return (FileHandleFindFirstFile(DirHandle, Buffer)); } /** Retrieves the next file in a directory. @@ -1007,47 +898,10 @@ ShellFindNextFile( OUT BOOLEAN *NoFile ) { - EFI_STATUS Status; - UINTN BufferSize; - // - // ASSERTs for DirHandle or Buffer or NoFile poitners being NULL + // pass to file handle lib // - ASSERT (DirHandle != NULL); - ASSERT (Buffer != NULL); - ASSERT (NoFile != NULL); - - // - // verify that DirHandle is a directory - // - Status = InternalShellIsDirectory(DirHandle); - if (EFI_ERROR(Status)) { - return (Status); - } - - // - // This BufferSize MUST stay equal to the originally allocated one in GetFirstFile - // - BufferSize = FIND_XXXXX_FILE_BUFFER_SIZE; - - // - // read in the info about the next file - // - Status = ShellReadFile (DirHandle, &BufferSize, Buffer); - ASSERT(Status != EFI_BUFFER_TOO_SMALL); - if (EFI_ERROR(Status)) { - return (Status); - } - - // - // If we read 0 bytes (but did not have erros) we already read in the last file. - // - if (BufferSize == 0) { - FreePool(Buffer); - *NoFile = TRUE; - } - - return (EFI_SUCCESS); + return (FileHandleFindNextFile(DirHandle, Buffer, NoFile)); } /** Retrieve the size of a file. @@ -1071,33 +925,7 @@ ShellGetFileSize ( OUT UINT64 *Size ) { - EFI_FILE_INFO *FileInfo; - - // - // ASSERT for FileHandle or Size being NULL - // - ASSERT (FileHandle != NULL); - ASSERT (Size != NULL); - - // - // get the FileInfo structure - // - FileInfo = ShellGetFileInfo(FileHandle); - if (FileInfo == NULL) { - return (EFI_DEVICE_ERROR); - } - - // - // Assign the Size pointer to the correct value - // - *Size = FileInfo->FileSize; - - // - // free the FileInfo memory - // - FreePool(FileInfo); - - return (EFI_SUCCESS); + return (FileFunctionMap.GetFileSize(FileHandle, Size)); } /** Retrieves the status of the break execution flag @@ -1366,7 +1194,7 @@ ShellSetPageBreakMode ( /// This allows for the struct to be populated. /// typedef struct { - EFI_LIST_ENTRY Link; + LIST_ENTRY Link; EFI_STATUS Status; CHAR16 *FullName; CHAR16 *FileName; @@ -1390,12 +1218,12 @@ typedef struct { LIST_ENTRY* EFIAPI InternalShellConvertFileListType ( - EFI_LIST_ENTRY *FileList + LIST_ENTRY *FileList ) { LIST_ENTRY *ListHead; SHELL_FILE_ARG *OldInfo; - EFI_LIST_ENTRY *Link; + LIST_ENTRY *Link; EFI_SHELL_FILE_INFO_NO_CONST *NewInfo; // @@ -1406,14 +1234,14 @@ InternalShellConvertFileListType ( // // Allocate our list head and initialize the list // - ListHead = AllocateZeroPool(sizeof(EFI_LIST_ENTRY)); + ListHead = AllocateZeroPool(sizeof(LIST_ENTRY)); ASSERT (ListHead != NULL); ListHead = InitializeListHead (ListHead); // // enumerate through each member of the old list and copy // - for (Link = FileList->Flink; Link != FileList; Link = Link->Flink) { + for (Link = FileList->ForwardLink; Link != FileList; Link = Link->ForwardLink) { OldInfo = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE); // @@ -1435,6 +1263,9 @@ InternalShellConvertFileListType ( 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 // @@ -1497,15 +1328,8 @@ ShellOpenFileMetaArg ( { EFI_STATUS Status; LIST_ENTRY *EmptyNode; - - // - // make sure we have no outstanding list - // - if (mOldStyleFileList != NULL) { - *ListHead = NULL; - return (EFI_UNSUPPORTED); - } - + LIST_ENTRY *mOldStyleFileList; + // // ASSERT that Arg and ListHead are not NULL // @@ -1529,7 +1353,7 @@ ShellOpenFileMetaArg ( // // allocate memory for old list head // - mOldStyleFileList = (EFI_LIST_ENTRY*)AllocatePool(sizeof(EFI_LIST_ENTRY)); + mOldStyleFileList = (LIST_ENTRY*)AllocatePool(sizeof(LIST_ENTRY)); ASSERT(mOldStyleFileList != NULL); // @@ -1551,6 +1375,13 @@ ShellOpenFileMetaArg ( // 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 // @@ -1587,19 +1418,13 @@ ShellCloseFileMetaArg ( if (mEfiShellProtocol != NULL) { return (mEfiShellProtocol->FreeFileList(ListHead)); } else { - // - // Free the EFI Shell version that was converted. - // - ASSERT_EFI_ERROR(mEfiShellEnvironment2->FreeFileList(mOldStyleFileList)); - FreePool(mOldStyleFileList); - mOldStyleFileList = NULL; - // // 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); @@ -1610,7 +1435,7 @@ ShellCloseFileMetaArg ( } typedef struct { - EFI_LIST_ENTRY List; + LIST_ENTRY List; CHAR16 *Name; ParamType Type; CHAR16 *Value; @@ -1634,7 +1459,7 @@ typedef struct { **/ BOOLEAN EFIAPI -IsCheckList ( +InternalIsOnCheckList ( IN CONST CHAR16 *Name, IN CONST SHELL_PARAM_ITEM *CheckList, OUT ParamType *Type @@ -1649,6 +1474,15 @@ IsCheckList ( 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 // @@ -1664,7 +1498,7 @@ IsCheckList ( return (FALSE); } /** - Checks the string for indicators of "flag" status. this is a leading '/' or '-' + Checks the string for indicators of "flag" status. this is a leading '/', '-', or '+' @param Name pointer to Name of parameter found @@ -1673,7 +1507,7 @@ IsCheckList ( **/ BOOLEAN EFIAPI -IsFlag ( +InternalIsFlag ( IN CONST CHAR16 *Name ) { @@ -1685,7 +1519,10 @@ IsFlag ( // // If the Name has a / or - as the first character return TRUE // - if ((Name[0] == L'/') || (Name[0] == L'-') ) { + if ((Name[0] == L'/') || + (Name[0] == L'-') || + (Name[0] == L'+') + ) { return (TRUE); } return (FALSE); @@ -1699,7 +1536,8 @@ IsFlag ( @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. + 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 @@ -1774,7 +1612,7 @@ InternalCommandLineParse ( ASSERT(CurrentItemPackage->Value != NULL); StrCpy(CurrentItemPackage->Value, Argv[LoopCounter]); InsertTailList(*CheckPackage, (LIST_ENTRY*)CurrentItemPackage); - } else if (IsFlag(Argv[LoopCounter]) == FALSE) { + } else if (InternalIsFlag(Argv[LoopCounter]) == FALSE) { // // add this one as a non-flag // @@ -1787,7 +1625,7 @@ InternalCommandLineParse ( StrCpy(CurrentItemPackage->Value, Argv[LoopCounter]); CurrentItemPackage->OriginalPosition = Count++; InsertTailList(*CheckPackage, (LIST_ENTRY*)CurrentItemPackage); - } else if (IsCheckList(Argv[LoopCounter], CheckList, &CurrentItemType) == TRUE) { + } else if (InternalIsOnCheckList(Argv[LoopCounter], CheckList, &CurrentItemType) == TRUE) { // // this is a flag // @@ -1818,7 +1656,9 @@ InternalCommandLineParse ( // // this was a non-recognised flag... error! // - *ProblemParam = (CHAR16*)Argv[LoopCounter]; + *ProblemParam = AllocatePool(StrSize(Argv[LoopCounter])); + ASSERT(*ProblemParam != NULL); + StrCpy(*ProblemParam, Argv[LoopCounter]); ShellCommandLineFreeVarList(*CheckPackage); *CheckPackage = NULL; return (EFI_VOLUME_CORRUPTED); diff --git a/ShellPkg/Library/BaseShellLib/BaseShellLib.h b/ShellPkg/Library/BaseShellLib/BaseShellLib.h new file mode 100644 index 0000000000..1620641648 --- /dev/null +++ b/ShellPkg/Library/BaseShellLib/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/BaseShellLib/BaseShellLib.inf b/ShellPkg/Library/BaseShellLib/BaseShellLib.inf index 8a2c33b8a1..71c68cb280 100644 --- a/ShellPkg/Library/BaseShellLib/BaseShellLib.inf +++ b/ShellPkg/Library/BaseShellLib/BaseShellLib.inf @@ -29,6 +29,7 @@ [Sources.common] BaseShellLib.c + BaseShellLib.h [Packages] MdePkg/MdePkg.dec @@ -41,6 +42,7 @@ BaseLib BaseMemoryLib DebugLib + FileHandleLib [Protocols] gEfiSimpleFileSystemProtocolGuid # ALWAYS_CONSUMED @@ -58,4 +60,4 @@ gEfiShellEnvironment2ExtGuid # ALWAYS_CONSUMED [Pcd.common] - + gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize # ALWAYS_CONSUMED diff --git a/ShellPkg/ShellPkg.dec b/ShellPkg/ShellPkg.dec index 922ad5e8ad..65b62a0827 100644 --- a/ShellPkg/ShellPkg.dec +++ b/ShellPkg/ShellPkg.dec @@ -20,7 +20,7 @@ DEC_SPECIFICATION = 0x00010005 PACKAGE_NAME = ShellPkg PACKAGE_GUID = 9FB7587C-93F7-40a7-9C04-FD7BA94EE646 - PACKAGE_VERSION = 0.1 + PACKAGE_VERSION = 0.2 [Includes.common] @@ -32,8 +32,15 @@ ## ShellLib|Include/Library/ShellLib.h + ## @libraryclass provides EFI_FILE_HANDLE services + ## used by Shell and ShellLib + ## + FileHandleLib|Include/Library/FileHandleLib.h + + [Guids.common] gEfiShellEnvironment2ExtGuid = {0xd2c18636, 0x40e5, 0x4eb5, {0xa3, 0x1b, 0x36, 0x69, 0x5f, 0xd4, 0x2c, 0x87}} + gEfiShellPkgTokenSpaceGuid = {0x171e9188, 0x31d3, 0x40f5, {0xb1, 0x0c, 0x53, 0x9b, 0x2d, 0xb9, 0x40, 0xcd}} [Protocols.common] gEfiShellProtocolGuid = {0x6302d008, 0x7f9b, 0x4f30, {0x87, 0xac, 0x60, 0xc9, 0xfe, 0xf5, 0xda, 0x4e}} @@ -41,10 +48,7 @@ gEfiShellEnvironment2Guid = {0x47c7b221, 0xc42a, 0x11d2, {0x8e, 0x57, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b}} gEfiShellInterfaceGuid = {0x47c7b223, 0xc42a, 0x11d2, {0x8e, 0x57, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b}} -[PcdsFeatureFlag.common] - -[PcdsFixedAtBuild.common] - -[PcdsPatchableInModule.common] - -[PcdsDynamic.common] \ No newline at end of file +[PcdsFixedAtBuild,PcdsPatchableInModule,PcdsDynamic] + ## This flag is used to control initialization of the shell library + ## This should be FALSE for compiling the shell application itself onlty. + gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|TRUE|BOOLEAN|0x00000005 \ No newline at end of file diff --git a/ShellPkg/ShellPkg.dsc b/ShellPkg/ShellPkg.dsc index ebe872aa7b..787c374270 100644 --- a/ShellPkg/ShellPkg.dsc +++ b/ShellPkg/ShellPkg.dsc @@ -1,8 +1,5 @@ #/** @file # Shell Package -# This is the first release of the Shell package. Please be aware that there will -# probably be higher than usual numbers of changes as the package gets used and issues, -# enhancements, and bugs are found and fixed. # # Copyright (c) 2007 - 2008, Intel Corporation # @@ -19,8 +16,8 @@ [Defines] PLATFORM_NAME = Shell PLATFORM_GUID = E1DC9BF8-7013-4c99-9437-795DAA45F3BD - PLATFORM_VERSION = 0.1 - DSC_SPECIFICATION = 0x00010005 + PLATFORM_VERSION = 0.2 + DSC_SPECIFICATION = 0x00010006 OUTPUT_DIRECTORY = Build/Shell SUPPORTED_ARCHITECTURES = IA32|IPF|X64|EBC BUILD_TARGETS = DEBUG|RELEASE @@ -35,14 +32,15 @@ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf UefiLib|MdePkg/Library/UefiLib/UefiLib.inf BaseLib|MdePkg/Library/BaseLib/BaseLib.inf - BaseMemoryLib|MdePkg/Library/BaseMemoryLibOptDxe/BaseMemoryLibOptDxe.inf + BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf PrintLib|MdeModulePkg/Library/DxePrintLibPrint2Protocol/DxePrintLibPrint2Protocol.inf UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + ShellLib|ShellPkg/Library/BaseShellLib/BaseShellLib.inf + FileHandleLib|ShellPkg/Library/BaseFileHandleLib/BaseFileHandleLib.inf [PcdsFixedAtBuild.common] [Components.common] - ShellPkg/Library/BaseShellLib/BaseShellLib.inf ShellPkg/Application/ShellExecTestApp/SA.inf ShellPkg/Application/ShellLibTestApp/SA3.inf \ No newline at end of file