summaryrefslogtreecommitdiff
path: root/ShellPkg/Library
diff options
context:
space:
mode:
Diffstat (limited to 'ShellPkg/Library')
-rw-r--r--ShellPkg/Library/BaseFileHandleLib/BaseFileHandleLib.c318
-rw-r--r--ShellPkg/Library/BaseFileHandleLib/BaseFileHandleLib.inf8
-rw-r--r--ShellPkg/Library/BaseSortLib/BaseSortLib.c31
-rw-r--r--ShellPkg/Library/BaseSortLib/BaseSortLib.inf10
-rw-r--r--ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c1420
-rw-r--r--ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.h142
-rw-r--r--ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf158
-rw-r--r--ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.unibin0 -> 17336 bytes
-rw-r--r--ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.c8
-rw-r--r--ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf10
-rw-r--r--ShellPkg/Library/UefiShellCommandLib/ConsistMapping.c1310
-rw-r--r--ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c1511
-rw-r--r--ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.h79
-rw-r--r--ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf61
-rw-r--r--ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.unibin0 -> 17400 bytes
-rw-r--r--ShellPkg/Library/UefiShellDriver1CommandsLib/Connect.c273
-rw-r--r--ShellPkg/Library/UefiShellDriver1CommandsLib/Devices.c164
-rw-r--r--ShellPkg/Library/UefiShellDriver1CommandsLib/OpenInfo.c243
-rw-r--r--ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.c137
-rw-r--r--ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.h71
-rw-r--r--ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf57
-rw-r--r--ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.unibin0 -> 3476 bytes
-rw-r--r--ShellPkg/Library/UefiShellLevel1CommandsLib/Exit.c81
-rw-r--r--ShellPkg/Library/UefiShellLevel1CommandsLib/For.c581
-rw-r--r--ShellPkg/Library/UefiShellLevel1CommandsLib/Goto.c92
-rw-r--r--ShellPkg/Library/UefiShellLevel1CommandsLib/If.c962
-rw-r--r--ShellPkg/Library/UefiShellLevel1CommandsLib/NoOpScriptCommand.c40
-rw-r--r--ShellPkg/Library/UefiShellLevel1CommandsLib/Shift.c63
-rw-r--r--ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.c251
-rw-r--r--ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.h182
-rw-r--r--ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf54
-rw-r--r--ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.unibin0 -> 36138 bytes
-rw-r--r--ShellPkg/Library/UefiShellLevel2CommandsLib/Attrib.c271
-rw-r--r--ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c218
-rw-r--r--ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c599
-rw-r--r--ShellPkg/Library/UefiShellLevel2CommandsLib/Load.c282
-rw-r--r--ShellPkg/Library/UefiShellLevel2CommandsLib/Ls.c564
-rw-r--r--ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c1116
-rw-r--r--ShellPkg/Library/UefiShellLevel2CommandsLib/MkDir.c128
-rw-r--r--ShellPkg/Library/UefiShellLevel2CommandsLib/Mv.c478
-rw-r--r--ShellPkg/Library/UefiShellLevel2CommandsLib/Parse.c190
-rw-r--r--ShellPkg/Library/UefiShellLevel2CommandsLib/Reset.c131
-rw-r--r--ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c296
-rw-r--r--ShellPkg/Library/UefiShellLevel2CommandsLib/Set.c169
-rw-r--r--ShellPkg/Library/UefiShellLevel2CommandsLib/TimeDate.c772
-rw-r--r--ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.c329
-rw-r--r--ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.h297
-rw-r--r--ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf82
-rw-r--r--ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.unibin0 -> 105810 bytes
-rw-r--r--ShellPkg/Library/UefiShellLevel3CommandsLib/Alias.c162
-rw-r--r--ShellPkg/Library/UefiShellLevel3CommandsLib/Cls.c135
-rw-r--r--ShellPkg/Library/UefiShellLevel3CommandsLib/Echo.c116
-rw-r--r--ShellPkg/Library/UefiShellLevel3CommandsLib/GetMtc.c101
-rw-r--r--ShellPkg/Library/UefiShellLevel3CommandsLib/Help.c183
-rw-r--r--ShellPkg/Library/UefiShellLevel3CommandsLib/Pause.c106
-rw-r--r--ShellPkg/Library/UefiShellLevel3CommandsLib/Touch.c265
-rw-r--r--ShellPkg/Library/UefiShellLevel3CommandsLib/Type.c239
-rw-r--r--ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.c94
-rw-r--r--ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.h156
-rw-r--r--ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf68
-rw-r--r--ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.unibin0 -> 42206 bytes
-rw-r--r--ShellPkg/Library/UefiShellLevel3CommandsLib/Ver.c145
-rw-r--r--ShellPkg/Library/UefiShellLib/UefiShellLib.c1079
-rw-r--r--ShellPkg/Library/UefiShellLib/UefiShellLib.inf8
-rw-r--r--ShellPkg/Library/UefiSortLib/UefiSortLib.c27
-rw-r--r--ShellPkg/Library/UefiSortLib/UefiSortLib.inf10
66 files changed, 16629 insertions, 504 deletions
diff --git a/ShellPkg/Library/BaseFileHandleLib/BaseFileHandleLib.c b/ShellPkg/Library/BaseFileHandleLib/BaseFileHandleLib.c
index fd19452cbc..bd3a4a7b52 100644
--- a/ShellPkg/Library/BaseFileHandleLib/BaseFileHandleLib.c
+++ b/ShellPkg/Library/BaseFileHandleLib/BaseFileHandleLib.c
@@ -1,7 +1,7 @@
/** @file
Provides interface to EFI_FILE_HANDLE functionality.
- Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved. <BR>
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
@@ -30,13 +30,13 @@
#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
+ 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
+ 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
+ @param FileHandle The file handle of the file for which information is
being requested.
@retval NULL information could not be retrieved.
@@ -49,7 +49,7 @@ FileHandleGetInfo (
IN EFI_FILE_HANDLE FileHandle
)
{
- EFI_FILE_INFO *pFileInfo;
+ EFI_FILE_INFO *FileInfo;
UINTN FileInfoSize;
EFI_STATUS Status;
@@ -62,51 +62,52 @@ FileHandleGetInfo (
// Get the required size to allocate
//
FileInfoSize = 0;
- pFileInfo = NULL;
- Status = FileHandle->GetInfo(FileHandle,
- &gEfiFileInfoGuid,
- &FileInfoSize,
- pFileInfo);
+ FileInfo = NULL;
+ Status = FileHandle->GetInfo(FileHandle,
+ &gEfiFileInfoGuid,
+ &FileInfoSize,
+ FileInfo);
//
// error is expected. getting size to allocate
//
ASSERT (Status == EFI_BUFFER_TOO_SMALL);
- pFileInfo = AllocateZeroPool(FileInfoSize);
- ASSERT (pFileInfo != NULL);
+ FileInfo = AllocateZeroPool(FileInfoSize);
+ ASSERT (FileInfo != NULL);
//
// now get the information
//
- Status = FileHandle->GetInfo(FileHandle,
- &gEfiFileInfoGuid,
- &FileInfoSize,
- pFileInfo);
+ Status = FileHandle->GetInfo(FileHandle,
+ &gEfiFileInfoGuid,
+ &FileInfoSize,
+ FileInfo);
//
// if we got an error free the memory and return NULL
//
if (EFI_ERROR(Status)) {
- FreePool(pFileInfo);
+ FreePool(FileInfo);
return NULL;
}
- return (pFileInfo);
+ return (FileInfo);
}
/**
- This function will set the information about the file for the opened handle
+ This function sets 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[in] FileHandle The file handle of the file for which information
+ is being set.
- @param FileInfo The infotmation to set.
+ @param[in] FileInfo The information 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_SUCCESS The information was set.
+ @retval EFI_INVALID_PARAMETER A parameter was out of range or invalid.
+ @retval EFI_UNSUPPORTED The FileHandle does not support FileInfo.
+ @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.
+ @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
@@ -115,7 +116,7 @@ FileHandleSetInfo (
IN CONST EFI_FILE_INFO *FileInfo
)
{
-
+
//
// ASSERT if the FileHandle or FileInfo is NULL
//
@@ -125,38 +126,38 @@ FileHandleSetInfo (
//
// Set the info
//
- return (FileHandle->SetInfo(FileHandle,
+ return (FileHandle->SetInfo(FileHandle,
&gEfiFileInfoGuid,
(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 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.
+ 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
+ @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
+ @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.
**/
@@ -183,11 +184,11 @@ FileHandleRead(
/**
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
+ 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
@@ -222,11 +223,11 @@ FileHandleWrite(
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
+ 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.
@@ -255,13 +256,13 @@ FileHandleClose (
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
+ 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
+ @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.
**/
@@ -286,19 +287,19 @@ FileHandleDelete (
/**
Set the current position in a file.
- This function sets the current file position for the handle to the position
+ 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
+ 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
+ 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
+ @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.
**/
@@ -319,11 +320,11 @@ FileHandleSetPosition (
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
+ 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.
@@ -341,6 +342,9 @@ FileHandleGetPosition (
OUT UINT64 *Position
)
{
+ if (Position == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
//
// ASSERT if FileHandle is NULL
//
@@ -352,7 +356,7 @@ FileHandleGetPosition (
}
/**
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
@@ -406,12 +410,12 @@ FileHandleIsDirectory (
// ASSERT if DirHandle is NULL
//
ASSERT(DirHandle != NULL);
-
+
//
// get the file information for DirHandle
//
DirInfo = FileHandleGetInfo (DirHandle);
-
+
//
// Parse DirInfo
//
@@ -420,7 +424,7 @@ FileHandleIsDirectory (
// We got nothing...
//
return (EFI_INVALID_PARAMETER);
- }
+ }
if ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0) {
//
// Attributes say this is not a directory
@@ -438,8 +442,8 @@ FileHandleIsDirectory (
/**
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
+ 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
@@ -475,15 +479,15 @@ FileHandleFindFirstFile (
Status = FileHandleIsDirectory(DirHandle);
if (EFI_ERROR(Status)) {
return (Status);
- }
+ }
//
- // reset to the begining of the directory
+ // 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
@@ -507,12 +511,12 @@ FileHandleFindFirstFile (
/**
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.
+ 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
@@ -565,13 +569,14 @@ FileHandleFindNextFile(
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
+ This function extracts the file size info from the FileHandle's EFI_FILE_INFO
data.
@param FileHandle file handle from which size is retrieved
@@ -594,7 +599,7 @@ FileHandleGetSize (
//
ASSERT (FileHandle != NULL);
ASSERT (Size != NULL);
-
+
//
// get the FileInfo structure
//
@@ -607,7 +612,7 @@ FileHandleGetSize (
// Assign the Size pointer to the correct value
//
*Size = FileInfo->FileSize;
-
+
//
// free the FileInfo memory
//
@@ -616,47 +621,98 @@ FileHandleGetSize (
return (EFI_SUCCESS);
}
+/**
+ Set the size of a file.
+
+ If FileHandle is NULL then ASSERT().
+
+ This function changes the file size info from the FileHandle's EFI_FILE_INFO
+ data.
+
+ @param FileHandle File handle whose size is to be changed.
+ @param Size New size.
+
+ @retval EFI_SUCCESS operation was completed sucessfully.
+ @retval EFI_DEVICE_ERROR cannot access the file.
+**/
+EFI_STATUS
+EFIAPI
+FileHandleSetSize (
+ IN EFI_FILE_HANDLE FileHandle,
+ IN UINT64 Size
+ )
+{
+ EFI_FILE_INFO *FileInfo;
+ EFI_STATUS Status;
+
+ //
+ // ASSERT for FileHandle or Size being NULL
+ //
+ ASSERT (FileHandle != NULL);
+
+ //
+ // get the FileInfo structure
+ //
+ FileInfo = FileHandleGetInfo(FileHandle);
+ if (FileInfo == NULL) {
+ return (EFI_DEVICE_ERROR);
+ }
+
+ //
+ // Assign the FileSize pointer to the new value
+ //
+ FileInfo->FileSize = Size;
+
+ Status = FileHandleSetInfo(FileHandle, FileInfo);
+ //
+ // free the FileInfo memory
+ //
+ FreePool(FileInfo);
+
+ return (Status);
+}
/**
- Safely append (on the left) with automatic string resizing given length of Destination and
+ Safely append (on the left) with automatic string resizing given length of Destination and
desired length of copy from Source.
- append the first D characters of Source to the end of Destination, where D is
- the lesser of Count and the StrLen() of Source. If appending those D characters
- will fit within Destination (whose Size is given as CurrentSize) and
- still leave room for a NULL terminator, then those characters are appended,
- starting at the original terminating NULL of Destination, and a new terminating
+ append the first D characters of Source to the end of Destination, where D is
+ the lesser of Count and the StrLen() of Source. If appending those D characters
+ will fit within Destination (whose Size is given as CurrentSize) and
+ still leave room for a NULL terminator, then those characters are appended,
+ starting at the original terminating NULL of Destination, and a new terminating
NULL is appended.
If appending D characters onto Destination will result in a overflow of the size
given in CurrentSize the string will be grown such that the copy can be performed
and CurrentSize will be updated to the new size.
- If Source is NULL, there is nothing to append, just return the current buffer in
+ If Source is NULL, there is nothing to append, just return the current buffer in
Destination.
if Destination is NULL, then ASSERT()
- if Destination's current length (including NULL terminator) is already more then
+ if Destination's current length (including NULL terminator) is already more then
CurrentSize, then ASSERT()
@param[in,out] Destination The String to append onto
- @param[in,out] CurrentSize on call the number of bytes in Destination. On
+ @param[in,out] CurrentSize on call the number of bytes in Destination. On
return possibly the new size (still in bytes). if NULL
then allocate whatever is needed.
@param[in] Source The String to append from
- @param[in] Count Maximum number of characters to append. if 0 then
+ @param[in] Count Maximum number of characters to append. if 0 then
all are appended.
@return Destination return the resultant string.
**/
-CHAR16*
+CHAR16*
EFIAPI
StrnCatGrowLeft (
IN OUT CHAR16 **Destination,
IN OUT UINTN *CurrentSize,
IN CONST CHAR16 *Source,
IN UINTN Count
- ){
+ )
+{
UINTN DestinationStartSize;
UINTN NewSize;
UINTN CopySize;
@@ -713,13 +769,13 @@ StrnCatGrowLeft (
}
/**
- Function to get a full filename given a EFI_FILE_HANDLE somewhere lower on the
+ Function to get a full filename given a EFI_FILE_HANDLE somewhere lower on the
directory 'stack'.
if Handle is NULL, return EFI_INVALID_PARAMETER
@param[in] Handle Handle to the Directory or File to create path to.
- @param[out] FullFileName pointer to pointer to generated full file name. It
+ @param[out] FullFileName pointer to pointer to generated full file name. It
is the responsibility of the caller to free this memory
with a call to FreePool().
@retval EFI_SUCCESS the operation was sucessful and the FullFileName is valid.
@@ -732,7 +788,8 @@ EFIAPI
FileHandleGetFileName (
IN CONST EFI_FILE_HANDLE Handle,
OUT CHAR16 **FullFileName
- ){
+ )
+{
EFI_STATUS Status;
UINTN Size;
EFI_FILE_HANDLE CurrentHandle;
@@ -749,6 +806,7 @@ FileHandleGetFileName (
}
*FullFileName = NULL;
+ CurrentHandle = NULL;
Status = Handle->Open(Handle, &CurrentHandle, L".", EFI_FILE_MODE_READ, 0);
if (!EFI_ERROR(Status)) {
@@ -766,14 +824,17 @@ FileHandleGetFileName (
//
if (StrLen (FileInfo->FileName) == 0) {
if (*FullFileName == NULL) {
+ ASSERT((*FullFileName == NULL && Size == 0) || (*FullFileName != NULL));
*FullFileName = StrnCatGrowLeft(FullFileName, &Size, L"\\", 0);
}
FreePool(FileInfo);
break;
} else {
if (*FullFileName == NULL) {
+ ASSERT((*FullFileName == NULL && Size == 0) || (*FullFileName != NULL));
*FullFileName = StrnCatGrowLeft(FullFileName, &Size, L"\\", 0);
}
+ ASSERT((*FullFileName == NULL && Size == 0) || (*FullFileName != NULL));
*FullFileName = StrnCatGrowLeft(FullFileName, &Size, FileInfo->FileName, 0);
*FullFileName = StrnCatGrowLeft(FullFileName, &Size, L"\\", 0);
FreePool(FileInfo);
@@ -790,6 +851,10 @@ FileHandleGetFileName (
FileHandleClose(CurrentHandle);
CurrentHandle = NextHigherHandle;
}
+ } else if (Status == EFI_NOT_FOUND) {
+ Status = EFI_SUCCESS;
+ ASSERT((*FullFileName == NULL && Size == 0) || (*FullFileName != NULL));
+ *FullFileName = StrnCatGrowLeft(FullFileName, &Size, L"\\", 0);
}
if (CurrentHandle != NULL) {
@@ -804,10 +869,10 @@ FileHandleGetFileName (
}
/**
- Function to read a single line from a file. The \n is not included in the returned
+ Function to read a single line from a file. The \n is not included in the returned
buffer. The returned buffer must be callee freed.
- If the position upon start is 0, then the Ascii Boolean will be set. This should be
+ If the position upon start is 0, then the Ascii Boolean will be set. This should be
maintained and not changed for all operations with the same file.
@param[in] Handle FileHandle to read from.
@@ -845,24 +910,24 @@ FileHandleReturnLine(
}
/**
- Function to read a single line (up to but not including the \n) from a file.
+ Function to read a single line (up to but not including the \n) from a EFI_FILE_HANDLE.
- If the position upon start is 0, then the Ascii Boolean will be set. This should be
+ If the position upon start is 0, then the Ascii Boolean will be set. This should be
maintained and not changed for all operations with the same file.
@param[in] Handle FileHandle to read from
@param[in,out] Buffer pointer to buffer to read into
@param[in,out] Size pointer to number of bytes in buffer
@param[in] Truncate if TRUE then allows for truncation of the line to fit.
- if FALSE will reset the position to the begining of the
+ if FALSE will reset the position to the begining of the
line if the buffer is not large enough.
@param[in,out] Ascii Boolean value for indicating whether the file is Ascii (TRUE) or UCS2 (FALSE);
- @retval EFI_SUCCESS the operation was sucessful. the line is stored in
+ @retval EFI_SUCCESS the operation was sucessful. the line is stored in
Buffer.
@retval EFI_INVALID_PARAMETER Handle was NULL.
@retval EFI_INVALID_PARAMETER Size was NULL.
- @retval EFI_BUFFER_TOO_SMALL Size was not enough space to store the line.
+ @retval EFI_BUFFER_TOO_SMALL Size was not enough space to store the line.
Size was updated to minimum space required.
@sa FileHandleRead
**/
@@ -874,7 +939,8 @@ FileHandleReadLine(
IN OUT UINTN *Size,
IN BOOLEAN Truncate,
IN OUT BOOLEAN *Ascii
- ){
+ )
+{
EFI_STATUS Status;
CHAR16 CharBuffer;
UINTN CharSize;
@@ -884,8 +950,13 @@ FileHandleReadLine(
if (Handle == NULL
||Size == NULL
- ){
- return (EFI_INVALID_PARAMETER);
+ ){
+ return (EFI_INVALID_PARAMETER);
+ }
+ if (Buffer == NULL) {
+ ASSERT(*Size == 0);
+ } else {
+ *Buffer = CHAR_NULL;
}
FileHandleGetPosition(Handle, &OriginalFilePosition);
if (OriginalFilePosition == 0) {
@@ -908,17 +979,11 @@ FileHandleReadLine(
CharSize = sizeof(CHAR16);
}
Status = FileHandleRead(Handle, &CharSize, &CharBuffer);
- if (OriginalFilePosition == 0 && *Ascii == FALSE && CountSoFar == 0) {
- //
- // we need to skip the unicode tag
- //
- continue;
- }
- if ( EFI_ERROR(Status)
- || CharSize == 0
- || (CharBuffer == L'\n' && *Ascii == FALSE)
- || (CharBuffer == '\n' && *Ascii != FALSE )
- ){
+ if ( EFI_ERROR(Status)
+ || CharSize == 0
+ || (CharBuffer == L'\n' && !(*Ascii))
+ || (CharBuffer == '\n' && *Ascii)
+ ){
break;
}
//
@@ -936,7 +1001,7 @@ FileHandleReadLine(
//
if ((CountSoFar+1)*sizeof(CHAR16) > *Size){
*Size = (CountSoFar+1)*sizeof(CHAR16);
- if (Truncate == FALSE) {
+ if (!Truncate) {
FileHandleSetPosition(Handle, OriginalFilePosition);
} else {
DEBUG((DEBUG_WARN, "The line was truncated in FileHandleReadLine"));
@@ -969,7 +1034,8 @@ EFIAPI
FileHandleWriteLine(
IN EFI_FILE_HANDLE Handle,
IN CHAR16 *Buffer
- ){
+ )
+{
EFI_STATUS Status;
UINTN Size;
@@ -1031,7 +1097,7 @@ FileHandlePrintLine(
Status = FileHandleWriteLine(Handle, Buffer);
//
- // Cleanup and return
+ // Cleanup and return
//
FreePool(Buffer);
return (Status);
@@ -1063,15 +1129,15 @@ FileHandleEof(
// ASSERT if Handle is NULL
//
ASSERT(Handle != NULL);
-
+
FileHandleGetPosition(Handle, &Pos);
Info = FileHandleGetInfo (Handle);
ASSERT(Info != NULL);
FileHandleSetPosition(Handle, Pos);
-
+
if (Info == NULL) {
return (FALSE);
- }
+ }
if (Pos == Info->FileSize) {
RetVal = TRUE;
diff --git a/ShellPkg/Library/BaseFileHandleLib/BaseFileHandleLib.inf b/ShellPkg/Library/BaseFileHandleLib/BaseFileHandleLib.inf
index ee8cbfee6f..38d9f9cce1 100644
--- a/ShellPkg/Library/BaseFileHandleLib/BaseFileHandleLib.inf
+++ b/ShellPkg/Library/BaseFileHandleLib/BaseFileHandleLib.inf
@@ -1,7 +1,7 @@
-## @file
+## @file
# Provides interface to shell functionality for shell commands and applications.
#
-# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2006 - 2010, Intel Corporation.All rights reserved. <BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
@@ -25,7 +25,7 @@
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
-[Sources]
+[Sources.common]
BaseFileHandleLib.c
[Packages]
@@ -46,5 +46,5 @@
[Guids]
gEfiFileInfoGuid # ALWAYS_CONSUMED
-[Pcd]
+[Pcd.common]
gEfiShellPkgTokenSpaceGuid.PcdShellPrintBufferSize # ALWAYS_CONSUMED
diff --git a/ShellPkg/Library/BaseSortLib/BaseSortLib.c b/ShellPkg/Library/BaseSortLib/BaseSortLib.c
index ceedc884c0..2d3f190324 100644
--- a/ShellPkg/Library/BaseSortLib/BaseSortLib.c
+++ b/ShellPkg/Library/BaseSortLib/BaseSortLib.c
@@ -1,7 +1,7 @@
/** @file
Library used for sorting routines.
- Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved. <BR>
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
@@ -62,7 +62,7 @@ QuickSortWorker (
if ( Count < 2
|| ElementSize < 1
- ){
+ ){
return;
}
@@ -80,7 +80,7 @@ QuickSortWorker (
for ( LoopCount = 0
; LoopCount < Count -1
; LoopCount++
- ){
+ ){
//
// if the element is less than the pivot
//
@@ -174,6 +174,9 @@ PerformQuickSort (
/**
Not supported in Base version.
+ @param[in] Buffer1 Ignored.
+ @param[in] Buffer2 Ignored.
+
ASSERT and return 0.
**/
INTN
@@ -209,3 +212,25 @@ StringNoCaseCompare (
}
+/**
+ Function to compare 2 strings.
+
+ @param[in] Buffer1 Pointer to String to compare (CHAR16**).
+ @param[in] Buffer2 Pointer to second String to compare (CHAR16**).
+
+ @retval 0 Buffer1 equal to Buffer2.
+ @return < 0 Buffer1 is less than Buffer2.
+ @return > 0 Buffer1 is greater than Buffer2.
+**/
+INTN
+EFIAPI
+StringCompare (
+ IN CONST VOID *Buffer1,
+ IN CONST VOID *Buffer2
+ )
+{
+ ASSERT(FALSE);
+ return 0;
+}
+
+
diff --git a/ShellPkg/Library/BaseSortLib/BaseSortLib.inf b/ShellPkg/Library/BaseSortLib/BaseSortLib.inf
index 167ae451b2..2537245912 100644
--- a/ShellPkg/Library/BaseSortLib/BaseSortLib.inf
+++ b/ShellPkg/Library/BaseSortLib/BaseSortLib.inf
@@ -1,7 +1,7 @@
-## @file
+## @file
# Library used for sorting routines.
#
-# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2009-2010, Intel Corporation.All rights reserved. <BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
@@ -19,13 +19,13 @@
FILE_GUID = 03F3331B-F12D-494f-BF37-E55A657F2497
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
- LIBRARY_CLASS = SORTLib|UEFI_APPLICATION UEFI_DRIVER
+ LIBRARY_CLASS = SortLib|UEFI_APPLICATION UEFI_DRIVER
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
-[Sources]
+[Sources.common]
BaseSortLib.c
[Packages]
@@ -42,4 +42,4 @@
[Guids]
-[Pcd]
+[Pcd.common]
diff --git a/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c b/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c
new file mode 100644
index 0000000000..c398618bbb
--- /dev/null
+++ b/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c
@@ -0,0 +1,1420 @@
+/** @file
+ Provides interface to advanced shell functionality for parsing both handle and protocol database.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiHandleParsingLib.h"
+
+
+STATIC CONST EFI_GUID mHandleParsingHiiGuid = \
+ { \
+ 0xb8969637, 0x81de, 0x43af, { 0xbc, 0x9a, 0x24, 0xd9, 0x89, 0x13, 0xf2, 0xf6 } \
+ };
+EFI_HANDLE mHandleParsingHiiHandle;
+HANDLE_INDEX_LIST mHandleList = {{{NULL,NULL},0,0},0};
+
+/**
+ Constructor for the library.
+
+ @param[in] ImageHandle Ignored.
+ @param[in] SystemTable Ignored.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+HandleParsingLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ mHandleParsingHiiHandle = HiiAddPackages (&mHandleParsingHiiGuid, gImageHandle, UefiHandleParsingLibStrings, NULL);
+ if (mHandleParsingHiiHandle == NULL) {
+ return (EFI_DEVICE_ERROR);
+ }
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Destructor for the library. free any resources.
+
+ @param[in] ImageHandle Ignored.
+ @param[in] SystemTable Ignored.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+HandleParsingLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ if (mHandleParsingHiiHandle != NULL) {
+ HiiRemovePackages(mHandleParsingHiiHandle);
+ }
+ return (EFI_SUCCESS);
+}
+
+/*
+CHAR16*
+EFIAPI
+LoadedImageProtocolDumpInformation(
+ IN CONST EFI_HANDLE TheHandle,
+ IN CONST BOOLEAN Verbose
+ )
+{
+ EFI_LOADED_IMAGE_PROTOCOL *Image;
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+ EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
+ VOID *Buffer;
+ UINTN BufferSize;
+ UINT32 AuthenticationStatus;
+ EFI_GUID *NameGuid;
+ EFI_FIRMWARE_VOLUME_PROTOCOL *FV;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FV2;
+
+ FV = NULL;
+ FV2 = NULL;
+ Buffer = NULL;
+ BufferSize = 0;
+
+ Status = HandleProtocol (
+ TheHandle,
+ &gEfiLoadedImageProtocolGuid,
+ &Image);
+ ASSERT_EFI_ERROR(Status);
+
+ DevPath = UnpackDevicePath (Image->FilePath);
+
+ if (DevPath == NULL) {
+ return NULL;
+ }
+
+ DevPathNode = DevPath;
+
+ while (!IsDevicePathEnd (DevPathNode)) {
+ //
+ // Find the Fv File path
+ //
+ NameGuid = GetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)DevPathNode);
+ if (NameGuid != NULL) {
+ Status = BS->HandleProtocol (
+ Image->DeviceHandle,
+ &gEfiFirmwareVolumeProtocolGuid,
+ &FV
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = FV->ReadSection (
+ FV,
+ NameGuid,
+ EFI_SECTION_USER_INTERFACE,
+ 0,
+ &Buffer,
+ &BufferSize,
+ &AuthenticationStatus
+ );
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+
+ Buffer = NULL;
+ } else {
+ Status = BS->HandleProtocol (
+ Image->DeviceHandle,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ &FV2
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = FV2->ReadSection (
+ FV2,
+ NameGuid,
+ EFI_SECTION_USER_INTERFACE,
+ 0,
+ &Buffer,
+ &BufferSize,
+ &AuthenticationStatus
+ );
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+
+ Buffer = NULL;
+ }
+ }
+ }
+ //
+ // Next device path node
+ //
+ DevPathNode = NextDevicePathNode (DevPathNode);
+ }
+
+ FreePool (DevPath);
+ return Buffer;
+}
+*/
+
+/**
+ Function to dump information about SimpleTextOut.
+
+ This will allocate the return buffer from boot services pool.
+
+ @param[in] TheHandle The handle that has SimpleTextOut installed.
+ @param[in] Verbose TRUE for additional information, FALSE otherwise.
+
+ @retval A poitner to a string containing the information.
+**/
+CHAR16*
+EFIAPI
+TxtOutProtocolDumpInformation(
+ IN CONST EFI_HANDLE TheHandle,
+ IN CONST BOOLEAN Verbose
+ )
+{
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Dev;
+ INTN Index;
+ UINTN Col;
+ UINTN Row;
+ EFI_STATUS Status;
+ CHAR16 *RetVal;
+ UINTN Size;
+ CHAR16 *Temp;
+ UINTN NewSize;
+
+ if (!Verbose) {
+ return (NULL);
+ }
+
+ RetVal = NULL;
+ Size = 0;
+
+ Status = gBS->HandleProtocol(
+ TheHandle,
+ &gEfiSimpleTextOutProtocolGuid,
+ (VOID**)&Dev);
+
+ ASSERT_EFI_ERROR(Status);
+ ASSERT (Dev != NULL && Dev->Mode != NULL);
+
+ Size = (Dev->Mode->MaxMode + 1) * 80;
+ RetVal = AllocateZeroPool(Size);
+
+ Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_TXT_OUT_DUMP_HEADER), NULL);
+ UnicodeSPrint(RetVal, Size, Temp, Dev, Dev->Mode->Attribute);
+ FreePool(Temp);
+
+ //
+ // Dump TextOut Info
+ //
+ Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_TXT_OUT_DUMP_LINE), NULL);
+ for (Index = 0; Index < Dev->Mode->MaxMode; Index++) {
+ Status = Dev->QueryMode (Dev, Index, &Col, &Row);
+ NewSize = Size - StrSize(RetVal);
+ UnicodeSPrint(
+ RetVal + StrLen(RetVal),
+ NewSize,
+ Temp,
+ Index == Dev->Mode->Mode ? L'*' : L' ',
+ Index,
+ !EFI_ERROR(Status)?Col:-1,
+ !EFI_ERROR(Status)?Row:-1
+ );
+ }
+ FreePool(Temp);
+ return (RetVal);
+}
+
+STATIC CONST UINTN VersionStringSize = 60;
+
+/**
+ Function to dump information about EfiDriverSupportedEfiVersion protocol.
+
+ This will allocate the return buffer from boot services pool.
+
+ @param[in] TheHandle The handle that has the protocol installed.
+ @param[in] Verbose TRUE for additional information, FALSE otherwise.
+
+ @retval A poitner to a string containing the information.
+**/
+CHAR16*
+EFIAPI
+DriverEfiVersionProtocolDumpInformation(
+ IN CONST EFI_HANDLE TheHandle,
+ IN CONST BOOLEAN Verbose
+ )
+{
+ EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL *DriverEfiVersion;
+ EFI_STATUS Status;
+ CHAR16 *RetVal;
+
+ Status = gBS->HandleProtocol(
+ TheHandle,
+ &gEfiDriverSupportedEfiVersionProtocolGuid,
+ (VOID**)&DriverEfiVersion);
+
+ ASSERT_EFI_ERROR(Status);
+
+ RetVal = AllocatePool(VersionStringSize);
+ ASSERT(RetVal != NULL);
+ UnicodeSPrint(RetVal, VersionStringSize, L"0x%08x", DriverEfiVersion->FirmwareVersion);
+ return (RetVal);
+}
+
+/**
+ Function to dump information about DevicePath protocol.
+
+ This will allocate the return buffer from boot services pool.
+
+ @param[in] TheHandle The handle that has the protocol installed.
+ @param[in] Verbose TRUE for additional information, FALSE otherwise.
+
+ @retval A poitner to a string containing the information.
+**/
+CHAR16*
+EFIAPI
+DevicePathProtocolDumpInformation(
+ IN CONST EFI_HANDLE TheHandle,
+ IN CONST BOOLEAN Verbose
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+ CHAR16 *Temp;
+ CHAR16 *Temp2;
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;
+ Temp = NULL;
+
+ Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID**)&DevPathToText);
+ if (!EFI_ERROR(Status)) {
+ Status = gBS->OpenProtocol(TheHandle, &gEfiDevicePathProtocolGuid, (VOID**)&DevPath, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (!EFI_ERROR(Status)) {
+ //
+ // I cannot decide whether to allow shortcuts here (the second BOOLEAN on the next line)
+ //
+ Temp = DevPathToText->ConvertDevicePathToText(DevPath, TRUE, TRUE);
+ gBS->CloseProtocol(TheHandle, &gEfiDevicePathProtocolGuid, gImageHandle, NULL);
+ }
+ }
+ if (Verbose && Temp != NULL && StrLen(Temp) > 30) {
+ Temp2 = NULL;
+ Temp2 = StrnCatGrow(&Temp2, NULL, Temp+(StrLen(Temp) - 30), 30);
+ FreePool(Temp);
+ Temp = Temp2;
+ }
+ return (Temp);
+}
+
+//
+// Put the information on the NT32 protocol GUIDs here so we are not dependant on the Nt32Pkg
+//
+#define LOCAL_EFI_WIN_NT_THUNK_PROTOCOL_GUID \
+ { \
+ 0x58c518b1, 0x76f3, 0x11d4, 0xbc, 0xea, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 \
+ }
+
+#define LOCAL_EFI_WIN_NT_BUS_DRIVER_IO_PROTOCOL_GUID \
+ { \
+ 0x96eb4ad6, 0xa32a, 0x11d4, 0xbc, 0xfd, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 \
+ }
+
+#define LOCAL_EFI_WIN_NT_SERIAL_PORT_GUID \
+ { \
+ 0xc95a93d, 0xa006, 0x11d4, 0xbc, 0xfa, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 \
+ }
+STATIC CONST EFI_GUID WinNtThunkProtocolGuid = LOCAL_EFI_WIN_NT_THUNK_PROTOCOL_GUID;
+STATIC CONST EFI_GUID WinNtIoProtocolGuid = LOCAL_EFI_WIN_NT_BUS_DRIVER_IO_PROTOCOL_GUID;
+STATIC CONST EFI_GUID WinNtSerialPortGuid = LOCAL_EFI_WIN_NT_SERIAL_PORT_GUID;
+
+STATIC CONST PROTOCOL_INFO_BLOCK mGuidStringListNT[] = {
+ {STRING_TOKEN(STR_WINNT_THUNK), (EFI_GUID*)&WinNtThunkProtocolGuid, NULL},
+ {STRING_TOKEN(STR_WINNT_DRIVER_IO), (EFI_GUID*)&WinNtIoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_WINNT_SERIAL_PORT), (EFI_GUID*)&WinNtSerialPortGuid, NULL},
+ {STRING_TOKEN(STR_UNKNOWN_DEVICE), NULL, NULL},
+};
+
+STATIC CONST PROTOCOL_INFO_BLOCK mGuidStringList[] = {
+ {STRING_TOKEN(STR_LOADED_IMAGE), &gEfiLoadedImageProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DEVICE_PATH), &gEfiDevicePathProtocolGuid, DevicePathProtocolDumpInformation},
+ {STRING_TOKEN(STR_IMAGE_PATH), &gEfiLoadedImageDevicePathProtocolGuid, DevicePathProtocolDumpInformation},
+ {STRING_TOKEN(STR_DEVICE_PATH_UTIL), &gEfiDevicePathUtilitiesProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DEVICE_PATH_TXT), &gEfiDevicePathToTextProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DEVICE_PATH_FTXT), &gEfiDevicePathFromTextProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DEVICE_PATH_PC), &gEfiPcAnsiGuid, NULL},
+ {STRING_TOKEN(STR_DEVICE_PATH_VT100), &gEfiVT100Guid, NULL},
+ {STRING_TOKEN(STR_DEVICE_PATH_VT100P), &gEfiVT100PlusGuid, NULL},
+ {STRING_TOKEN(STR_DEVICE_PATH_VTUTF8), &gEfiVTUTF8Guid, NULL},
+ {STRING_TOKEN(STR_DRIVER_BINDING), &gEfiDriverBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_PLATFORM_OVERRIDE), &gEfiPlatformDriverOverrideProtocolGuid, NULL},
+ {STRING_TOKEN(STR_BUS_OVERRIDE), &gEfiBusSpecificDriverOverrideProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DRIVER_DIAG), &gEfiDriverDiagnosticsProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DRIVER_DIAG2), &gEfiDriverDiagnostics2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DRIVER_CN), &gEfiComponentNameProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DRIVER_CN2), &gEfiComponentName2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_PLAT_DRV_CFG), &gEfiPlatformToDriverConfigurationProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DRIVER_VERSION), &gEfiDriverSupportedEfiVersionProtocolGuid, DriverEfiVersionProtocolDumpInformation},
+ {STRING_TOKEN(STR_TXT_IN), &gEfiSimpleTextInProtocolGuid, NULL},
+ {STRING_TOKEN(STR_TXT_IN_EX), &gEfiSimpleTextInputExProtocolGuid, NULL},
+ {STRING_TOKEN(STR_TXT_OUT), &gEfiSimpleTextOutProtocolGuid, TxtOutProtocolDumpInformation},
+ {STRING_TOKEN(STR_SIM_POINTER), &gEfiSimplePointerProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ABS_POINTER), &gEfiAbsolutePointerProtocolGuid, NULL},
+ {STRING_TOKEN(STR_SERIAL_IO), &gEfiSerialIoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_GRAPHICS_OUTPUT), &gEfiGraphicsOutputProtocolGuid, NULL},
+ {STRING_TOKEN(STR_EDID_DISCOVERED), &gEfiEdidDiscoveredProtocolGuid, NULL},
+ {STRING_TOKEN(STR_EDID_ACTIVE), &gEfiEdidActiveProtocolGuid, NULL},
+ {STRING_TOKEN(STR_EDID_OVERRIDE), &gEfiEdidOverrideProtocolGuid, NULL},
+ {STRING_TOKEN(STR_CON_IN), &gEfiConsoleInDeviceGuid, NULL},
+ {STRING_TOKEN(STR_CON_OUT), &gEfiConsoleOutDeviceGuid, NULL},
+ {STRING_TOKEN(STR_STD_ERR), &gEfiStandardErrorDeviceGuid, NULL},
+ {STRING_TOKEN(STR_LOAD_FILE), &gEfiLoadFileProtocolGuid, NULL},
+ {STRING_TOKEN(STR_LOAD_FILE2), &gEfiLoadFile2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_SIMPLE_FILE_SYS), &gEfiSimpleFileSystemProtocolGuid, NULL},
+ {STRING_TOKEN(STR_FILE_INFO), &gEfiFileInfoGuid, NULL},
+ {STRING_TOKEN(STR_FILE_SYS_INFO), &gEfiFileSystemInfoGuid, NULL},
+ {STRING_TOKEN(STR_TAPE_IO), &gEfiTapeIoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DISK_IO), &gEfiDiskIoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_BLK_IO), &gEfiBlockIoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_UC), &gEfiUnicodeCollationProtocolGuid, NULL},
+ {STRING_TOKEN(STR_UC2), &gEfiUnicodeCollation2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_PCIRB_IO), &gEfiPciRootBridgeIoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_PCI_IO), &gEfiPciIoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_SCSI_PT), &gEfiScsiPassThruProtocolGuid, NULL},
+ {STRING_TOKEN(STR_SCSI_IO), &gEfiScsiIoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_SCSI_PT_EXT), &gEfiExtScsiPassThruProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ISCSI), &gEfiIScsiInitiatorNameProtocolGuid, NULL},
+ {STRING_TOKEN(STR_USB_IO), &gEfiUsbIoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_USB_HC), &gEfiUsbHcProtocolGuid, NULL},
+ {STRING_TOKEN(STR_USB_HC2), &gEfiUsb2HcProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DEBUG_SUPPORT), &gEfiDebugSupportProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DEBUG_PORT), &gEfiDebugPortProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DECOMPRESS), &gEfiDecompressProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ACPI_TABLE), &gEfiAcpiTableProtocolGuid, NULL},
+ {STRING_TOKEN(STR_EBC_INTERPRETER), &gEfiEbcProtocolGuid, NULL},
+ {STRING_TOKEN(STR_SNP), &gEfiSimpleNetworkProtocolGuid, NULL},
+ {STRING_TOKEN(STR_NII), &gEfiNetworkInterfaceIdentifierProtocolGuid, NULL},
+ {STRING_TOKEN(STR_NII_31), &gEfiNetworkInterfaceIdentifierProtocolGuid_31, NULL},
+ {STRING_TOKEN(STR_PXE_BC), &gEfiPxeBaseCodeProtocolGuid, NULL},
+ {STRING_TOKEN(STR_PXE_CB), &gEfiPxeBaseCodeCallbackProtocolGuid, NULL},
+ {STRING_TOKEN(STR_BIS), &gEfiBisProtocolGuid, NULL},
+ {STRING_TOKEN(STR_MNP_SB), &gEfiManagedNetworkServiceBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_MNP), &gEfiManagedNetworkProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ARP_SB), &gEfiArpServiceBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ARP), &gEfiArpProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DHCPV4_SB), &gEfiDhcp4ServiceBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DHCPV4), &gEfiDhcp4ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_TCPV4_SB), &gEfiTcp4ServiceBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_TCPV4), &gEfiTcp4ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_IPV4_SB), &gEfiIp4ServiceBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_IPV4), &gEfiIp4ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_IPV4_CFG), &gEfiIp4ConfigProtocolGuid, NULL},
+ {STRING_TOKEN(STR_SHELL_PARAMETERS), &gEfiShellParametersProtocolGuid, NULL},
+ {STRING_TOKEN(STR_SHELL), &gEfiShellProtocolGuid, NULL},
+ {STRING_TOKEN(STR_EFI_GLOBAL_VARIABLE), &gEfiGlobalVariableGuid, NULL},
+ {STRING_TOKEN(STR_UDPV4_SB), &gEfiUdp4ServiceBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_UDPV4), &gEfiUdp4ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_MTFTPV4_SB), &gEfiMtftp4ServiceBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_MTFTPV4), &gEfiMtftp4ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_AUTH_INFO), &gEfiAuthenticationInfoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_HASH_SB), &gEfiHashServiceBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_HASH), &gEfiHashProtocolGuid, NULL},
+ {STRING_TOKEN(STR_HII_FONT), &gEfiHiiFontProtocolGuid, NULL},
+ {STRING_TOKEN(STR_HII_STRING), &gEfiHiiStringProtocolGuid, NULL},
+ {STRING_TOKEN(STR_HII_IMAGE), &gEfiHiiImageProtocolGuid, NULL},
+ {STRING_TOKEN(STR_HII_DATABASE), &gEfiHiiDatabaseProtocolGuid, NULL},
+ {STRING_TOKEN(STR_HII_CONFIG_ROUT), &gEfiHiiConfigRoutingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_HII_CONFIG_ACC), &gEfiHiiConfigAccessProtocolGuid, NULL},
+ {STRING_TOKEN(STR_HII_FORM_BROWSER2), &gEfiFormBrowser2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_SHELL_INTERFACE), &gEfiShellInterfaceGuid, NULL},
+ {STRING_TOKEN(STR_SHELL_ENV2), &gEfiShellEnvironment2Guid, NULL},
+ {STRING_TOKEN(STR_SHELL_ENV), &gEfiShellEnvironment2Guid, NULL},
+ {STRING_TOKEN(STR_DEVICE_IO), &gEfiDeviceIoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_UGA_DRAW), &gEfiUgaDrawProtocolGuid, NULL},
+ {STRING_TOKEN(STR_UGA_IO), &gEfiUgaIoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ESP), &gEfiPartTypeSystemPartGuid, NULL},
+ {STRING_TOKEN(STR_GPT_NBR), &gEfiPartTypeLegacyMbrGuid, NULL},
+ {STRING_TOKEN(STR_DRIVER_CONFIG), &gEfiDriverConfigurationProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DRIVER_CONFIG2), &gEfiDriverConfiguration2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_UNKNOWN_DEVICE), NULL, NULL},
+};
+
+/**
+ Function to get the node for a protocol or struct from it's GUID.
+
+ if Guid is NULL, then ASSERT.
+
+ @param[in] Guid The GUID to look for the name of.
+
+ @return The node.
+**/
+CONST PROTOCOL_INFO_BLOCK *
+EFIAPI
+InternalShellGetNodeFromGuid(
+ IN CONST EFI_GUID* Guid
+ )
+{
+ CONST PROTOCOL_INFO_BLOCK *ListWalker;
+
+ ASSERT(Guid != NULL);
+
+ if (PcdGetBool(PcdShellIncludeNtGuids)) {
+ for (ListWalker = mGuidStringListNT ; ListWalker != NULL && ListWalker->GuidId != NULL ; ListWalker++) {
+ if (CompareGuid(ListWalker->GuidId, Guid)) {
+ return (ListWalker);
+ }
+ }
+ }
+ for (ListWalker = mGuidStringList ; ListWalker != NULL && ListWalker->GuidId != NULL ; ListWalker++) {
+ if (CompareGuid(ListWalker->GuidId, Guid)) {
+ return (ListWalker);
+ }
+ }
+ return (ListWalker);
+}
+
+/**
+ Function to get the name of a protocol or struct from it's GUID.
+
+ if Guid is NULL, then ASSERT.
+
+ @param[in] Guid The GUID to look for the name of.
+ @param[in] Lang The language to use.
+
+ @return pointer to string of the name. The caller
+ is responsible to free this memory.
+**/
+CHAR16*
+EFIAPI
+GetStringNameFromGuid(
+ IN CONST EFI_GUID *Guid,
+ IN CONST CHAR8 *Lang OPTIONAL
+ )
+{
+ CONST PROTOCOL_INFO_BLOCK *Id;
+
+ Id = InternalShellGetNodeFromGuid(Guid);
+ return (HiiGetString(mHandleParsingHiiHandle, Id->StringId, Lang));
+}
+
+/**
+ Function to dump protocol information from a handle.
+
+ This function will return a allocated string buffer containing the
+ information. The caller is responsible for freeing the memory.
+
+ If Guid is NULL, ASSERT().
+ If TheHandle is NULL, ASSERT().
+
+ @param[in] TheHandle The handle to dump information from.
+ @param[in] Guid The GUID of the protocol to dump.
+ @param[in] Verbose TRUE for extra info. FALSE otherwise.
+
+ @return The pointer to string.
+ @retval NULL An error was encountered.
+**/
+CHAR16*
+EFIAPI
+GetProtocolInformationDump(
+ IN CONST EFI_HANDLE TheHandle,
+ IN CONST EFI_GUID *Guid,
+ IN CONST BOOLEAN Verbose
+ )
+{
+ CONST PROTOCOL_INFO_BLOCK *Id;
+
+ ASSERT(TheHandle != NULL);
+ ASSERT(Guid != NULL);
+
+ if (TheHandle == NULL || Guid == NULL) {
+ return (NULL);
+ }
+
+ Id = InternalShellGetNodeFromGuid(Guid);
+ if (Id != NULL && Id->DumpInfo != NULL) {
+ return (Id->DumpInfo(TheHandle, Verbose));
+ }
+ return (NULL);
+}
+
+/**
+ Function to get the Guid for a protocol or struct based on it's string name.
+
+ @param[in] Name The pointer to the string name.
+ @param[in] Lang The pointer to the language code.
+ @param[in] Guid The pointer to the Guid.
+
+ @retval EFI_SUCCESS The operation was sucessful.
+**/
+EFI_STATUS
+EFIAPI
+GetGuidFromStringName(
+ IN CONST CHAR16 *Name,
+ IN CONST CHAR8 *Lang OPTIONAL,
+ IN EFI_GUID **Guid
+ )
+{
+ CONST PROTOCOL_INFO_BLOCK *ListWalker;
+ CHAR16 *String;
+
+ ASSERT(Guid != NULL);
+ if (Guid == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+ *Guid = NULL;
+
+ if (PcdGetBool(PcdShellIncludeNtGuids)) {
+ for (ListWalker = mGuidStringListNT ; ListWalker != NULL && ListWalker->GuidId != NULL ; ListWalker++) {
+ String = HiiGetString(mHandleParsingHiiHandle, ListWalker->StringId, Lang);
+ if (Name != NULL && String != NULL && StrCmp(Name, String)==0) {
+ *Guid = ListWalker->GuidId;
+ }
+ SHELL_FREE_NON_NULL(String);
+ if (*Guid != NULL) {
+ return (EFI_SUCCESS);
+ }
+ }
+ }
+ for (ListWalker = mGuidStringList ; ListWalker != NULL && ListWalker->GuidId != NULL ; ListWalker++) {
+ String = HiiGetString(mHandleParsingHiiHandle, ListWalker->StringId, Lang);
+ if (Name != NULL && String != NULL && StrCmp(Name, String)==0) {
+ *Guid = ListWalker->GuidId;
+ }
+ SHELL_FREE_NON_NULL(String);
+ if (*Guid != NULL) {
+ return (EFI_SUCCESS);
+ }
+ }
+ return (EFI_NOT_FOUND);
+}
+
+/**
+ Function to retrieve the driver name (if possible) from the ComponentName or
+ ComponentName2 protocol
+
+ @param[in] TheHandle The driver handle to get the name of.
+ @param[in] Language The language to use.
+
+ @retval NULL The name could not be found.
+ @return A pointer to the string name. Do not de-allocate the memory.
+**/
+CONST CHAR16*
+EFIAPI
+GetStringNameFromHandle(
+ IN CONST EFI_HANDLE TheHandle,
+ IN CONST CHAR8 *Language
+ )
+{
+ EFI_COMPONENT_NAME2_PROTOCOL *CompNameStruct;
+ EFI_STATUS Status;
+ CHAR16 *RetVal;
+
+ Status = gBS->OpenProtocol(
+ TheHandle,
+ &gEfiComponentName2ProtocolGuid,
+ (VOID**)&CompNameStruct,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (!EFI_ERROR(Status)) {
+ Status = CompNameStruct->GetDriverName(CompNameStruct, (CHAR8*)Language, &RetVal);
+ if (!EFI_ERROR(Status)) {
+ return (RetVal);
+ }
+ }
+ Status = gBS->OpenProtocol(
+ TheHandle,
+ &gEfiComponentNameProtocolGuid,
+ (VOID**)&CompNameStruct,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (!EFI_ERROR(Status)) {
+ Status = CompNameStruct->GetDriverName(CompNameStruct, (CHAR8*)Language, &RetVal);
+ if (!EFI_ERROR(Status)) {
+ return (RetVal);
+ }
+ }
+ return (NULL);
+}
+
+/**
+ Function to initialize the file global mHandleList object for use in
+ vonverting handles to index and index to handle.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+InternalShellInitHandleList(
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleCount;
+ HANDLE_LIST *ListWalker;
+
+ if (mHandleList.NextIndex != 0) {
+ return EFI_SUCCESS;
+ }
+ InitializeListHead(&mHandleList.List.Link);
+ mHandleList.NextIndex = 1;
+ Status = gBS->LocateHandleBuffer (
+ AllHandles,
+ NULL,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) {
+ return (Status);
+ }
+ for (mHandleList.NextIndex = 1 ; mHandleList.NextIndex <= HandleCount ; mHandleList.NextIndex++){
+ ListWalker = AllocatePool(sizeof(HANDLE_LIST));
+ ASSERT(ListWalker != NULL);
+ ListWalker->TheHandle = HandleBuffer[mHandleList.NextIndex-1];
+ ListWalker->TheIndex = mHandleList.NextIndex;
+ InsertTailList(&mHandleList.List.Link,&ListWalker->Link);
+ }
+ FreePool(HandleBuffer);
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function to retrieve the human-friendly index of a given handle. If the handle
+ does not have a index one will be automatically assigned. The index value is valid
+ until the termination of the shell application.
+
+ @param[in] TheHandle The handle to retrieve an index for.
+
+ @retval 0 A memory allocation failed.
+ @return The index of the handle.
+
+**/
+UINTN
+EFIAPI
+ConvertHandleToHandleIndex(
+ IN CONST EFI_HANDLE TheHandle
+ )
+{
+ HANDLE_LIST *ListWalker;
+ ASSERT(TheHandle!=NULL);
+
+ InternalShellInitHandleList();
+
+ for (ListWalker = (HANDLE_LIST*)GetFirstNode(&mHandleList.List.Link)
+ ; !IsNull(&mHandleList.List.Link,&ListWalker->Link)
+ ; ListWalker = (HANDLE_LIST*)GetNextNode(&mHandleList.List.Link,&ListWalker->Link)
+ ){
+ if (ListWalker->TheHandle == TheHandle) {
+ return (ListWalker->TheIndex);
+ }
+ }
+ ListWalker = AllocatePool(sizeof(HANDLE_LIST));
+ ASSERT(ListWalker != NULL);
+ ListWalker->TheHandle = TheHandle;
+ ListWalker->TheIndex = mHandleList.NextIndex++;
+ InsertTailList(&mHandleList.List.Link,&ListWalker->Link);
+ return (ListWalker->TheIndex);
+}
+
+
+
+/**
+ Function to retrieve the EFI_HANDLE from the human-friendly index.
+
+ @param[in] TheIndex The index to retrieve the EFI_HANDLE for.
+
+ @retval NULL The index was invalid.
+ @return The EFI_HANDLE that index represents.
+
+**/
+EFI_HANDLE
+EFIAPI
+ConvertHandleIndexToHandle(
+ IN CONST UINTN TheIndex
+ )
+{
+ HANDLE_LIST *ListWalker;
+
+ InternalShellInitHandleList();
+
+ if (TheIndex >= mHandleList.NextIndex) {
+ return (NULL);
+ }
+
+ for (ListWalker = (HANDLE_LIST*)GetFirstNode(&mHandleList.List.Link)
+ ; !IsNull(&mHandleList.List.Link,&ListWalker->Link)
+ ; ListWalker = (HANDLE_LIST*)GetNextNode(&mHandleList.List.Link,&ListWalker->Link)
+ ){
+ if (ListWalker->TheIndex == TheIndex) {
+ return (ListWalker->TheHandle);
+ }
+ }
+ return (NULL);
+}
+
+/**
+ Gets all the related EFI_HANDLEs based on the mask supplied.
+
+ This function scans all EFI_HANDLES in the UEFI environment's handle database
+ and returns the ones with the specified relationship (Mask) to the specified
+ controller handle.
+
+ If both DriverBindingHandle and ControllerHandle are NULL, then ASSERT.
+ If MatchingHandleCount is NULL, then ASSERT.
+
+ If MatchingHandleBuffer is not NULL upon a successful return the memory must be
+ caller freed.
+
+ @param[in] DriverBindingHandle The handle with Driver Binding protocol on it.
+ @param[in] ControllerHandle The handle with Device Path protocol on it.
+ @param[in] MatchingHandleCount The pointer to UINTN that specifies the number of HANDLES in
+ MatchingHandleBuffer.
+ @param[out] MatchingHandleBuffer On a successful return, a buffer of MatchingHandleCount
+ EFI_HANDLEs with a terminating NULL EFI_HANDLE.
+ @param[out] HandleType An array of type information.
+
+ @retval EFI_SUCCESS The operation was successful, and any related handles
+ are in MatchingHandleBuffer.
+ @retval EFI_NOT_FOUND No matching handles were found.
+ @retval EFI_INVALID_PARAMETER A parameter was invalid or out of range.
+**/
+EFI_STATUS
+EFIAPI
+ParseHandleDatabaseByRelationshipWithType (
+ IN CONST EFI_HANDLE DriverBindingHandle OPTIONAL,
+ IN CONST EFI_HANDLE ControllerHandle OPTIONAL,
+ IN UINTN *HandleCount,
+ OUT EFI_HANDLE **HandleBuffer,
+ OUT UINTN **HandleType
+ )
+{
+ EFI_STATUS Status;
+ UINTN HandleIndex;
+ EFI_GUID **ProtocolGuidArray;
+ UINTN ArrayCount;
+ UINTN ProtocolIndex;
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;
+ UINTN OpenInfoCount;
+ UINTN OpenInfoIndex;
+ UINTN ChildIndex;
+
+ ASSERT(HandleCount != NULL);
+ ASSERT(HandleBuffer != NULL);
+ ASSERT(HandleType != NULL);
+ ASSERT(DriverBindingHandle != NULL || ControllerHandle != NULL);
+
+ *HandleCount = 0;
+ *HandleBuffer = NULL;
+ *HandleType = NULL;
+
+ //
+ // Retrieve the list of all handles from the handle database
+ //
+ Status = gBS->LocateHandleBuffer (
+ AllHandles,
+ NULL,
+ NULL,
+ HandleCount,
+ HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return (Status);
+ }
+
+ *HandleType = AllocateZeroPool (*HandleCount * sizeof (UINTN));
+ ASSERT(*HandleType != NULL);
+
+ for (HandleIndex = 0; HandleIndex < *HandleCount; HandleIndex++) {
+ //
+ // Retrieve the list of all the protocols on each handle
+ //
+ Status = gBS->ProtocolsPerHandle (
+ (*HandleBuffer)[HandleIndex],
+ &ProtocolGuidArray,
+ &ArrayCount
+ );
+ if (!EFI_ERROR (Status)) {
+
+ for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {
+
+ //
+ // Set the bit describing what this handle has
+ //
+ if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiLoadedImageProtocolGuid) ) {
+ (*HandleType)[HandleIndex] |= HR_IMAGE_HANDLE;
+ } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverBindingProtocolGuid) ) {
+ (*HandleType)[HandleIndex] |= HR_DRIVER_BINDING_HANDLE;
+ } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverConfiguration2ProtocolGuid)) {
+ (*HandleType)[HandleIndex] |= HR_DRIVER_CONFIGURATION_HANDLE;
+ } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverConfigurationProtocolGuid) ) {
+ (*HandleType)[HandleIndex] |= HR_DRIVER_CONFIGURATION_HANDLE;
+ } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverDiagnostics2ProtocolGuid) ) {
+ (*HandleType)[HandleIndex] |= HR_DRIVER_DIAGNOSTICS_HANDLE;
+ } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverDiagnosticsProtocolGuid) ) {
+ (*HandleType)[HandleIndex] |= HR_DRIVER_DIAGNOSTICS_HANDLE;
+ } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiComponentName2ProtocolGuid) ) {
+ (*HandleType)[HandleIndex] |= HR_COMPONENT_NAME_HANDLE;
+ } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiComponentNameProtocolGuid) ) {
+ (*HandleType)[HandleIndex] |= HR_COMPONENT_NAME_HANDLE;
+ } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDevicePathProtocolGuid) ) {
+ (*HandleType)[HandleIndex] |= HR_DEVICE_HANDLE;
+ } else {
+ DEBUG_CODE_BEGIN();
+ ASSERT((*HandleType)[HandleIndex] == (*HandleType)[HandleIndex]);
+ DEBUG_CODE_END();
+ }
+ //
+ // Retrieve the list of agents that have opened each protocol
+ //
+ Status = gBS->OpenProtocolInformation (
+ (*HandleBuffer)[HandleIndex],
+ ProtocolGuidArray[ProtocolIndex],
+ &OpenInfo,
+ &OpenInfoCount
+ );
+ if (!EFI_ERROR (Status)) {
+ for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
+ if (DriverBindingHandle != NULL && OpenInfo[OpenInfoIndex].AgentHandle == DriverBindingHandle) {
+ if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) == EFI_OPEN_PROTOCOL_BY_DRIVER) {
+ (*HandleType)[HandleIndex] |= (HR_DEVICE_HANDLE | HR_CONTROLLER_HANDLE);
+ }
+ if (ControllerHandle != NULL && (*HandleBuffer)[HandleIndex] == ControllerHandle) {
+ if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) == EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
+ for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) {
+ if ((*HandleBuffer)[ChildIndex] == OpenInfo[OpenInfoIndex].ControllerHandle) {
+ (*HandleType)[ChildIndex] |= (HR_DEVICE_HANDLE | HR_CHILD_HANDLE);
+ }
+ }
+ }
+ }
+ }
+ if (DriverBindingHandle == NULL && OpenInfo[OpenInfoIndex].ControllerHandle == ControllerHandle) {
+ if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) == EFI_OPEN_PROTOCOL_BY_DRIVER) {
+ for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) {
+ if ((*HandleBuffer)[ChildIndex] == OpenInfo[OpenInfoIndex].AgentHandle) {
+ (*HandleType)[ChildIndex] |= HR_DEVICE_DRIVER;
+ }
+ }
+ }
+ if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) == EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
+ (*HandleType)[HandleIndex] |= HR_PARENT_HANDLE;
+ for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) {
+ if ((*HandleBuffer)[ChildIndex] == OpenInfo[OpenInfoIndex].AgentHandle) {
+ (*HandleType)[ChildIndex] |= HR_BUS_DRIVER;
+ }
+ }
+ }
+ }
+ }
+
+ FreePool (OpenInfo);
+ }
+ }
+
+ FreePool (ProtocolGuidArray);
+ }
+ }
+
+ if (EFI_ERROR(Status)) {
+ if (*HandleType != NULL) {
+ FreePool (*HandleType);
+ }
+ if (*HandleBuffer != NULL) {
+ FreePool (*HandleBuffer);
+ }
+
+ *HandleCount = 0;
+ *HandleBuffer = NULL;
+ *HandleType = NULL;
+ }
+
+ return Status;
+}
+
+/**
+ Gets all the related EFI_HANDLEs based on the single EFI_HANDLE and the mask
+ supplied.
+
+ This function will scan all EFI_HANDLES in the UEFI environment's handle database
+ and return all the ones with the specified relationship (Mask) to the specified
+ controller handle.
+
+ If both DriverBindingHandle and ControllerHandle are NULL, then ASSERT.
+ If MatchingHandleCount is NULL, then ASSERT.
+
+ If MatchingHandleBuffer is not NULL upon a sucessful return the memory must be
+ caller freed.
+
+ @param[in] DriverBindingHandle Handle to a object with Driver Binding protocol
+ on it.
+ @param[in] ControllerHandle Handle to a device with Device Path protocol on it.
+ @param[in] Mask Mask of what relationship(s) is desired.
+ @param[in] MatchingHandleCount Poitner to UINTN specifying number of HANDLES in
+ MatchingHandleBuffer.
+ @param[out] MatchingHandleBuffer On a sucessful return a buffer of MatchingHandleCount
+ EFI_HANDLEs and a terminating NULL EFI_HANDLE.
+
+ @retval EFI_SUCCESS The operation was sucessful and any related handles
+ are in MatchingHandleBuffer;
+ @retval EFI_NOT_FOUND No matching handles were found.
+ @retval EFI_INVALID_PARAMETER A parameter was invalid or out of range.
+**/
+EFI_STATUS
+EFIAPI
+ParseHandleDatabaseByRelationship (
+ IN CONST EFI_HANDLE DriverBindingHandle OPTIONAL,
+ IN CONST EFI_HANDLE ControllerHandle OPTIONAL,
+ IN CONST UINTN Mask,
+ IN UINTN *MatchingHandleCount,
+ OUT EFI_HANDLE **MatchingHandleBuffer OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN *HandleType;
+ UINTN HandleIndex;
+
+ ASSERT(MatchingHandleCount != NULL);
+ ASSERT(DriverBindingHandle != NULL || ControllerHandle != NULL);
+
+ if ((Mask & HR_VALID_MASK) != Mask) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ if ((Mask & HR_CHILD_HANDLE) != 0 && DriverBindingHandle == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ *MatchingHandleCount = 0;
+ if (MatchingHandleBuffer != NULL) {
+ *MatchingHandleBuffer = NULL;
+ }
+
+ HandleBuffer = NULL;
+ HandleType = NULL;
+
+ Status = ParseHandleDatabaseByRelationshipWithType (
+ DriverBindingHandle,
+ ControllerHandle,
+ &HandleCount,
+ &HandleBuffer,
+ &HandleType
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Count the number of handles that match the attributes in Mask
+ //
+ for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
+ if ((HandleType[HandleIndex] & Mask) == Mask) {
+ (*MatchingHandleCount)++;
+ }
+ }
+ //
+ // If no handles match the attributes in Mask then return EFI_NOT_FOUND
+ //
+ if (*MatchingHandleCount == 0) {
+ Status = EFI_NOT_FOUND;
+ } else {
+
+ if (MatchingHandleBuffer == NULL) {
+ //
+ // Someone just wanted the count...
+ //
+ Status = EFI_SUCCESS;
+ } else {
+ //
+ // Allocate a handle buffer for the number of handles that matched the attributes in Mask
+ //
+ *MatchingHandleBuffer = AllocatePool ((*MatchingHandleCount +1)* sizeof (EFI_HANDLE));
+ ASSERT(*MatchingHandleBuffer != NULL);
+
+ for (HandleIndex = 0,*MatchingHandleCount = 0
+ ; HandleIndex < HandleCount
+ ; HandleIndex++
+ ){
+ //
+ // Fill the allocated buffer with the handles that matched the attributes in Mask
+ //
+ if ((HandleType[HandleIndex] & Mask) == Mask) {
+ (*MatchingHandleBuffer)[(*MatchingHandleCount)++] = HandleBuffer[HandleIndex];
+ }
+ }
+
+ //
+ // Make the last one NULL
+ //
+ (*MatchingHandleBuffer)[*MatchingHandleCount] = NULL;
+
+ Status = EFI_SUCCESS;
+ } // MacthingHandleBuffer == NULL (ELSE)
+ } // *MatchingHandleCount == 0 (ELSE)
+ } // no error on ParseHandleDatabaseByRelationshipWithType
+
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+
+ if (HandleType != NULL) {
+ FreePool (HandleType);
+ }
+
+ return Status;
+}
+
+/**
+ Gets handles for any child controllers of the passed in controller.
+
+ @param[in] ControllerHandle The handle of the "parent controller"
+ @param[in] MatchingHandleCount Pointer to the number of handles in
+ MatchingHandleBuffer on return.
+ @param[out] MatchingHandleBuffer Buffer containing handles on a successful
+ return.
+
+
+ @retval EFI_SUCCESS The operation was sucessful.
+**/
+EFI_STATUS
+EFIAPI
+ParseHandleDatabaseForChildControllers(
+ IN CONST EFI_HANDLE ControllerHandle,
+ IN UINTN *MatchingHandleCount,
+ OUT EFI_HANDLE **MatchingHandleBuffer OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINTN HandleIndex;
+ UINTN DriverBindingHandleCount;
+ EFI_HANDLE *DriverBindingHandleBuffer;
+ UINTN DriverBindingHandleIndex;
+ UINTN ChildControllerHandleCount;
+ EFI_HANDLE *ChildControllerHandleBuffer;
+ UINTN ChildControllerHandleIndex;
+ BOOLEAN Found;
+ EFI_HANDLE *HandleBufferForReturn;
+
+ ASSERT (MatchingHandleCount != NULL);
+
+ Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS (
+ ControllerHandle,
+ &DriverBindingHandleCount,
+ &DriverBindingHandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ HandleBufferForReturn = GetHandleListByPotocol(&gEfiDriverBindingProtocolGuid);
+ if (HandleBufferForReturn == NULL) {
+ FreePool (DriverBindingHandleBuffer);
+ return Status;
+ }
+
+ *MatchingHandleCount = 0;
+ for (DriverBindingHandleIndex = 0; DriverBindingHandleIndex < DriverBindingHandleCount; DriverBindingHandleIndex++) {
+ Status = PARSE_HANDLE_DATABASE_MANAGED_CHILDREN (
+ DriverBindingHandleBuffer[DriverBindingHandleIndex],
+ ControllerHandle,
+ &ChildControllerHandleCount,
+ &ChildControllerHandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ for (ChildControllerHandleIndex = 0;
+ ChildControllerHandleIndex < ChildControllerHandleCount;
+ ChildControllerHandleIndex++
+ ) {
+ Found = FALSE;
+ for (HandleIndex = 0; HandleBufferForReturn[HandleIndex] != NULL; HandleIndex++) {
+ if (HandleBufferForReturn[HandleIndex] == ChildControllerHandleBuffer[ChildControllerHandleIndex]) {
+ Found = TRUE;
+ break;
+ }
+ }
+
+ if (!Found) {
+ HandleBufferForReturn[(*MatchingHandleCount)++] = ChildControllerHandleBuffer[ChildControllerHandleIndex];
+ }
+ }
+
+ FreePool (ChildControllerHandleBuffer);
+ }
+
+ FreePool (DriverBindingHandleBuffer);
+
+ if (MatchingHandleBuffer != NULL) {
+ *MatchingHandleBuffer = HandleBufferForReturn;
+ } else {
+ FreePool(HandleBufferForReturn);
+ }
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Appends 1 buffer to another buffer. This will re-allocate the destination buffer
+ if necessary to fit all of the data.
+
+ If DestinationBuffer is NULL, then ASSERT().
+
+ @param[in,out] DestinationBuffer The pointer to the pointer to the buffer to append onto.
+ @param[in,out] DestinationSize The pointer to the size of DestinationBuffer.
+ @param[in] SourceBuffer The pointer to the buffer to append onto DestinationBuffer.
+ @param[in] SourceSize The number of bytes of SourceBuffer to append.
+
+ @retval NULL A memory allocation failed.
+ @retval NULL A parameter was invalid.
+ @return A pointer to (*DestinationBuffer).
+**/
+VOID*
+EFIAPI
+BuffernCatGrow (
+ IN OUT VOID **DestinationBuffer,
+ IN OUT UINTN *DestinationSize,
+ IN VOID *SourceBuffer,
+ IN UINTN SourceSize
+ )
+{
+ UINTN LocalDestinationSize;
+ UINTN LocalDestinationFinalSize;
+
+ ASSERT(DestinationBuffer != NULL);
+
+ if (SourceSize == 0 || SourceBuffer == NULL) {
+ return (*DestinationBuffer);
+ }
+
+ if (DestinationSize == NULL) {
+ LocalDestinationSize = 0;
+ } else {
+ LocalDestinationSize = *DestinationSize;
+ }
+
+ LocalDestinationFinalSize = LocalDestinationSize + SourceSize;
+
+ if (DestinationSize != NULL) {
+ *DestinationSize = LocalDestinationSize;
+ }
+
+ if (LocalDestinationSize == 0) {
+ // allcoate
+ *DestinationBuffer = AllocatePool(LocalDestinationFinalSize);
+ } else {
+ // reallocate
+ *DestinationBuffer = ReallocatePool(LocalDestinationSize, LocalDestinationFinalSize, *DestinationBuffer);
+ }
+
+ ASSERT(*DestinationBuffer != NULL);
+
+ // copy
+ return (CopyMem(((UINT8*)(*DestinationBuffer)) + LocalDestinationSize, SourceBuffer, SourceSize));
+}
+
+/**
+ Gets handles for any child devices produced by the passed in driver.
+
+ @param[in] DriverHandle The handle of the driver.
+ @param[in] MatchingHandleCount Pointer to the number of handles in
+ MatchingHandleBuffer on return.
+ @param[out] MatchingHandleBuffer Buffer containing handles on a successful
+ return.
+ @retval EFI_SUCCESS The operation was sucessful.
+ @sa ParseHandleDatabaseByRelationship
+**/
+EFI_STATUS
+EFIAPI
+ParseHandleDatabaseForChildDevices(
+ IN CONST EFI_HANDLE DriverHandle,
+ IN UINTN *MatchingHandleCount,
+ OUT EFI_HANDLE **MatchingHandleBuffer OPTIONAL
+ )
+{
+ EFI_HANDLE *Buffer;
+ EFI_HANDLE *Buffer2;
+ UINTN Count1;
+ UINTN Count2;
+ UINTN HandleIndex;
+ EFI_STATUS Status;
+ UINTN HandleBufferSize;
+
+ ASSERT(MatchingHandleCount != NULL);
+
+ HandleBufferSize = 0;
+ Buffer = NULL;
+ Buffer2 = NULL;
+ *MatchingHandleCount = 0;
+
+ Status = PARSE_HANDLE_DATABASE_DEVICES (
+ DriverHandle,
+ &Count1,
+ &Buffer
+ );
+ if (!EFI_ERROR (Status)) {
+ for (HandleIndex = 0; HandleIndex < Count1; HandleIndex++) {
+ //
+ // now find the children
+ //
+ Status = PARSE_HANDLE_DATABASE_MANAGED_CHILDREN (
+ DriverHandle,
+ Buffer[HandleIndex],
+ &Count2,
+ &Buffer2
+ );
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+ //
+ // save out required and optional data elements
+ //
+ *MatchingHandleCount += Count2;
+ if (MatchingHandleBuffer != NULL) {
+ *MatchingHandleBuffer = BuffernCatGrow((VOID**)MatchingHandleBuffer, &HandleBufferSize, Buffer2, Count2 * sizeof(Buffer2[0]));
+ }
+
+ //
+ // free the memory
+ //
+ if (Buffer2 != NULL) {
+ FreePool(Buffer2);
+ }
+ }
+ }
+
+ if (Buffer != NULL) {
+ FreePool(Buffer);
+ }
+ return (Status);
+}
+
+/**
+ Function to get all handles that support a given protocol or all handles.
+
+ @param[in] ProtocolGuid The guid of the protocol to get handles for. If NULL
+ then the function will return all handles.
+
+ @retval NULL A memory allocation failed.
+ @return A NULL terminated list of handles.
+**/
+EFI_HANDLE*
+EFIAPI
+GetHandleListByPotocol (
+ IN CONST EFI_GUID *ProtocolGuid OPTIONAL
+ )
+{
+ EFI_HANDLE *HandleList;
+ UINTN Size;
+ EFI_STATUS Status;
+
+ Size = 0;
+ HandleList = NULL;
+
+ //
+ // We cannot use LocateHandleBuffer since we need that NULL item on the ends of the list!
+ //
+ if (ProtocolGuid == NULL) {
+ Status = gBS->LocateHandle(AllHandles, NULL, NULL, &Size, HandleList);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ HandleList = AllocatePool(Size + sizeof(EFI_HANDLE));
+ Status = gBS->LocateHandle(AllHandles, NULL, NULL, &Size, HandleList);
+ HandleList[Size/sizeof(EFI_HANDLE)] = NULL;
+ }
+ } else {
+ Status = gBS->LocateHandle(ByProtocol, (EFI_GUID*)ProtocolGuid, NULL, &Size, HandleList);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ HandleList = AllocatePool(Size + sizeof(EFI_HANDLE));
+ Status = gBS->LocateHandle(ByProtocol, (EFI_GUID*)ProtocolGuid, NULL, &Size, HandleList);
+ HandleList[Size/sizeof(EFI_HANDLE)] = NULL;
+ }
+ }
+ if (EFI_ERROR(Status)) {
+ if (HandleList != NULL) {
+ FreePool(HandleList);
+ }
+ return (NULL);
+ }
+ return (HandleList);
+}
+
+/**
+ Function to get all handles that support some protocols.
+
+ @param[in] ProtocolGuids A NULL terminated list of protocol GUIDs.
+
+ @retval NULL A memory allocation failed.
+ @return A NULL terminated list of handles.
+**/
+EFI_HANDLE*
+EFIAPI
+GetHandleListByPotocolList (
+ IN CONST EFI_GUID **ProtocolGuids
+ )
+{
+ EFI_HANDLE *HandleList;
+ UINTN Size;
+ UINTN TotalSize;
+ EFI_STATUS Status;
+ CONST EFI_GUID **GuidWalker;
+ EFI_HANDLE *HandleWalker1;
+ EFI_HANDLE *HandleWalker2;
+
+ Size = 0;
+ HandleList = NULL;
+ TotalSize = sizeof(EFI_HANDLE);
+
+ for (GuidWalker = ProtocolGuids ; GuidWalker != NULL && *GuidWalker != NULL ; GuidWalker++,Size = 0){
+ Status = gBS->LocateHandle(ByProtocol, (EFI_GUID*)(*GuidWalker), NULL, &Size, NULL);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ TotalSize += Size;
+ }
+ }
+ HandleList = AllocatePool(TotalSize);
+ ASSERT(HandleList != NULL);
+ if (HandleList == NULL) {
+ return (NULL);
+ }
+
+ Size = 0;
+ for (GuidWalker = ProtocolGuids ; GuidWalker != NULL && *GuidWalker != NULL ; GuidWalker++){
+ Size = TotalSize - Size;
+ Status = gBS->LocateHandle(ByProtocol, (EFI_GUID*)(*GuidWalker), NULL, &Size, HandleList+((TotalSize - Size)/sizeof(EFI_HANDLE)));
+ ASSERT_EFI_ERROR(Status);
+ }
+ HandleList[(TotalSize/sizeof(EFI_HANDLE))-1] = NULL;
+
+ for (HandleWalker1 = HandleList ; HandleWalker1 != NULL && *HandleWalker1 != NULL ; HandleWalker1++) {
+ for (HandleWalker2 = HandleWalker1 + 1; HandleWalker2 != NULL && *HandleWalker2 != NULL ; HandleWalker2++) {
+ if (*HandleWalker1 == *HandleWalker2) {
+ //
+ // copy memory back 1 handle width.
+ //
+ CopyMem(HandleWalker2, HandleWalker2 + 1, TotalSize - ((HandleWalker2-HandleList+1)*sizeof(EFI_HANDLE)));
+ }
+ }
+ }
+
+ return (HandleList);
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.h b/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.h
new file mode 100644
index 0000000000..479c12d351
--- /dev/null
+++ b/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.h
@@ -0,0 +1,142 @@
+/** @file
+ Provides interface to advanced shell functionality for parsing both handle and protocol database.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ 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 <Uefi.h>
+
+#include <Guid/FileInfo.h>
+#include <Guid/ConsoleInDevice.h>
+#include <Guid/ConsoleOutDevice.h>
+#include <Guid/StandardErrorDevice.h>
+#include <Guid/GlobalVariable.h>
+#include <Guid/Gpt.h>
+#include <Guid/FileSystemInfo.h>
+
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/EfiShellInterface.h>
+#include <Protocol/EfiShellEnvironment2.h>
+#include <Protocol/EfiShell.h>
+#include <Protocol/EfiShellParameters.h>
+#include <Protocol/DevicePathToText.h>
+#include <Protocol/DriverBinding.h>
+#include <Protocol/DriverConfiguration2.h>
+#include <Protocol/DriverConfiguration.h>
+#include <Protocol/DriverDiagnostics2.h>
+#include <Protocol/DriverDiagnostics.h>
+#include <Protocol/ComponentName2.h>
+#include <Protocol/ComponentName.h>
+#include <Protocol/PlatformDriverOverride.h>
+#include <Protocol/DevicePathUtilities.h>
+#include <Protocol/DevicePathFromText.h>
+#include <Protocol/BusSpecificDriverOverride.h>
+#include <Protocol/PlatformToDriverConfiguration.h>
+#include <Protocol/DriverSupportedEfiVersion.h>
+#include <Protocol/SimpleTextInEx.h>
+#include <Protocol/SimplePointer.h>
+#include <Protocol/SerialIo.h>
+#include <Protocol/AbsolutePointer.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/EdidDiscovered.h>
+#include <Protocol/EdidActive.h>
+#include <Protocol/EdidOverride.h>
+#include <Protocol/LoadFile.h>
+#include <Protocol/LoadFile2.h>
+#include <Protocol/SimpleFilesystem.h>
+#include <Protocol/TapeIo.h>
+#include <Protocol/DiskIo.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/UnicodeCollation.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/ScsiPassThru.h>
+#include <Protocol/ScsiPassThruExt.h>
+#include <Protocol/ScsiIo.h>
+#include <Protocol/IScsiInitiatorName.h>
+#include <Protocol/UsbIo.h>
+#include <Protocol/UsbHostController.h>
+#include <Protocol/Usb2HostController.h>
+#include <Protocol/DebugSupport.h>
+#include <Protocol/DebugPort.h>
+#include <Protocol/Decompress.h>
+#include <Protocol/AcpiTable.h>
+#include <Protocol/Ebc.h>
+#include <Protocol/SimpleNetwork.h>
+#include <Protocol/NetworkInterfaceIdentifier.h>
+#include <Protocol/PxeBaseCode.h>
+#include <Protocol/PxeBaseCodeCallBack.h>
+#include <Protocol/Bis.h>
+#include <Protocol/ManagedNetwork.h>
+#include <Protocol/Arp.h>
+#include <Protocol/Dhcp4.h>
+#include <Protocol/Tcp4.h>
+#include <Protocol/Ip4.h>
+#include <Protocol/Ip4Config.h>
+#include <Protocol/Udp4.h>
+#include <Protocol/Mtftp4.h>
+#include <Protocol/AuthenticationInfo.h>
+#include <Protocol/Hash.h>
+#include <Protocol/HiiFont.h>
+#include <Protocol/HiiString.h>
+#include <Protocol/HiiImage.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/HiiConfigRouting.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/FormBrowser2.h>
+#include <Protocol/DeviceIo.h>
+#include <Protocol/UgaDraw.h>
+#include <Protocol/UgaIo.h>
+#include <Protocol/DriverConfiguration.h>
+#include <Protocol/DriverConfiguration2.h>
+#include <Protocol/DevicePathUtilities.h>
+//#include <Protocol/FirmwareVolume.h>
+//#include <Protocol/FirmwareVolume2.h>
+
+#include <Library/HandleParsingLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiLib.h>
+#include <Library/HiiLib.h>
+#include <Library/ShellLib.h>
+
+typedef struct {
+ LIST_ENTRY Link;
+ EFI_HANDLE TheHandle;
+ UINTN TheIndex;
+}HANDLE_LIST;
+
+typedef struct {
+ HANDLE_LIST List;
+ UINTN NextIndex;
+} HANDLE_INDEX_LIST;
+
+typedef
+CHAR16 *
+(EFIAPI *DUMP_PROTOCOL_INFO)(
+ IN CONST EFI_HANDLE TheHandle,
+ IN CONST BOOLEAN Verbose
+ );
+
+
+typedef struct {
+ EFI_STRING_ID StringId;
+ EFI_GUID *GuidId;
+ DUMP_PROTOCOL_INFO DumpInfo;
+} PROTOCOL_INFO_BLOCK;
+
diff --git a/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf b/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf
new file mode 100644
index 0000000000..a0c2c16533
--- /dev/null
+++ b/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf
@@ -0,0 +1,158 @@
+## @file
+# Provides interface to advanced shell functionality for parsing both handle and protocol database.
+# Copyright (c) 2010, Intel Corporation. All rights reserved. <BR>
+#
+# 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 = UefiHandleParsingLib
+ FILE_GUID = 3CDC7177-CC2A-4678-BA8F-1A936A093FA4
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = HandleParsingLib|UEFI_APPLICATION UEFI_DRIVER
+ CONSTRUCTOR = HandleParsingLibConstructor
+ DESTRUCTOR = HandleParsingLibDestructor
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ UefiHandleParsingLib.c
+ UefiHandleParsingLib.h
+ UefiHandleParsingLib.uni
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ ShellPkg/ShellPkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+
+[LibraryClasses]
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ DevicePathLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ FileHandleLib
+ PrintLib
+ UefiLib
+ HiiLib
+
+[Protocols]
+ gEfiSimpleFileSystemProtocolGuid # ALWAYS_CONSUMED
+
+ # shell 2.0
+ gEfiShellProtocolGuid # SOMETIMES_CONSUMED
+ gEfiShellParametersProtocolGuid # SOMETIMES_CONSUMED
+
+ # 'old' shell
+ gEfiShellEnvironment2Guid # SOMETIMES_CONSUMED
+ gEfiShellInterfaceGuid # SOMETIMES_CONSUMED
+
+ gEfiUnicodeCollation2ProtocolGuid # ALWAYS_CONSUMED
+ gEfiDevicePathToTextProtocolGuid # ALWAYS_CONSUMED
+ gEfiBusSpecificDriverOverrideProtocolGuid # ALWAYS_CONSUMED
+ gEfiDevicePathUtilitiesProtocolGuid # ALWAYS_CONSUMED
+ gEfiDevicePathFromTextProtocolGuid # ALWAYS_CONSUMED
+ gEfiPlatformDriverOverrideProtocolGuid # ALWAYS_CONSUMED
+ gEfiSimpleTextInProtocolGuid # ALWAYS_CONSUMED
+ gEfiPlatformToDriverConfigurationProtocolGuid # ALWAYS_CONSUMED
+ gEfiDriverSupportedEfiVersionProtocolGuid # ALWAYS_CONSUMED
+ gEfiLoadedImageProtocolGuid # ALWAYS_CONSUMED
+ gEfiDevicePathProtocolGuid # ALWAYS_CONSUMED
+ gEfiLoadedImageDevicePathProtocolGuid # ALWAYS_CONSUMED
+ gEfiSimpleTextOutProtocolGuid
+ gEfiSimplePointerProtocolGuid
+ gEfiAbsolutePointerProtocolGuid
+ gEfiSerialIoProtocolGuid
+ gEfiEdidDiscoveredProtocolGuid
+ gEfiEdidActiveProtocolGuid
+ gEfiEdidOverrideProtocolGuid
+ gEfiLoadFileProtocolGuid
+ gEfiLoadFile2ProtocolGuid
+ gEfiTapeIoProtocolGuid
+ gEfiDiskIoProtocolGuid
+ gEfiBlockIoProtocolGuid
+ gEfiUnicodeCollationProtocolGuid
+ gEfiUnicodeCollation2ProtocolGuid
+ gEfiPciRootBridgeIoProtocolGuid
+ gEfiPciIoProtocolGuid
+ gEfiScsiPassThruProtocolGuid
+ gEfiScsiIoProtocolGuid
+ gEfiExtScsiPassThruProtocolGuid
+ gEfiIScsiInitiatorNameProtocolGuid
+ gEfiUsbIoProtocolGuid
+ gEfiUsbHcProtocolGuid
+ gEfiUsb2HcProtocolGuid
+ gEfiDebugSupportProtocolGuid
+ gEfiDebugPortProtocolGuid
+ gEfiDecompressProtocolGuid
+ gEfiAcpiTableProtocolGuid
+ gEfiEbcProtocolGuid
+ gEfiSimpleNetworkProtocolGuid
+ gEfiNetworkInterfaceIdentifierProtocolGuid
+ gEfiNetworkInterfaceIdentifierProtocolGuid_31
+ gEfiPxeBaseCodeProtocolGuid
+ gEfiPxeBaseCodeCallbackProtocolGuid
+ gEfiBisProtocolGuid
+ gEfiManagedNetworkServiceBindingProtocolGuid
+ gEfiManagedNetworkProtocolGuid
+ gEfiArpServiceBindingProtocolGuid
+ gEfiArpProtocolGuid
+ gEfiDhcp4ServiceBindingProtocolGuid
+ gEfiDhcp4ProtocolGuid
+ gEfiTcp4ServiceBindingProtocolGuid
+ gEfiTcp4ProtocolGuid
+ gEfiIp4ServiceBindingProtocolGuid
+ gEfiIp4ProtocolGuid
+ gEfiIp4ConfigProtocolGuid
+ gEfiUdp4ServiceBindingProtocolGuid
+ gEfiUdp4ProtocolGuid
+ gEfiMtftp4ServiceBindingProtocolGuid
+ gEfiMtftp4ProtocolGuid
+ gEfiAuthenticationInfoProtocolGuid
+ gEfiHashServiceBindingProtocolGuid
+ gEfiHashProtocolGuid
+ gEfiHiiFontProtocolGuid
+ gEfiHiiStringProtocolGuid
+ gEfiHiiImageProtocolGuid
+ gEfiHiiConfigRoutingProtocolGuid
+ gEfiHiiConfigAccessProtocolGuid
+ gEfiFormBrowser2ProtocolGuid
+ gEfiDeviceIoProtocolGuid
+ gEfiUgaDrawProtocolGuid
+ gEfiUgaIoProtocolGuid
+ gEfiDriverConfigurationProtocolGuid
+ gEfiDriverConfiguration2ProtocolGuid
+ gEfiSimpleTextInputExProtocolGuid
+
+[Guids]
+ gEfiFileInfoGuid # ALWAYS_CONSUMED
+ gEfiShellEnvironment2ExtGuid # ALWAYS_CONSUMED
+ gEfiPcAnsiGuid
+ gEfiVT100Guid
+ gEfiVT100PlusGuid
+ gEfiVTUTF8Guid
+ gEfiStandardErrorDeviceGuid
+ gEfiConsoleInDeviceGuid
+ gEfiConsoleOutDeviceGuid
+ gEfiFileSystemInfoGuid
+ gEfiGlobalVariableGuid
+ gEfiPartTypeSystemPartGuid
+ gEfiPartTypeLegacyMbrGuid
+
+[Pcd.common]
+ gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize # ALWAYS_CONSUMED
+ gEfiShellPkgTokenSpaceGuid.PcdShellPrintBufferSize # ALWAYS_CONSUMED
+ gEfiShellPkgTokenSpaceGuid.PcdShellIncludeNtGuids # ALWAYS_CONSUMED \ No newline at end of file
diff --git a/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.uni b/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.uni
new file mode 100644
index 0000000000..1ac84d8a3c
--- /dev/null
+++ b/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.uni
Binary files differ
diff --git a/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.c b/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.c
index 53e50ca7de..60b15fe8a0 100644
--- a/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.c
+++ b/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.c
@@ -59,7 +59,7 @@ ShellCEntryLib (
ImageHandle,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
+ );
if (!EFI_ERROR(Status)) {
//
// use shell 2.0 interface
@@ -67,7 +67,7 @@ ShellCEntryLib (
ReturnFromMain = ShellAppMain (
EfiShellParametersProtocol->Argc,
EfiShellParametersProtocol->Argv
- );
+ );
} else {
//
// try to get shell 1.0 interface instead.
@@ -78,7 +78,7 @@ ShellCEntryLib (
ImageHandle,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
+ );
if (!EFI_ERROR(Status)) {
//
// use shell 1.0 interface
@@ -86,7 +86,7 @@ ShellCEntryLib (
ReturnFromMain = ShellAppMain (
EfiShellInterface->Argc,
EfiShellInterface->Argv
- );
+ );
} else {
ASSERT(FALSE);
}
diff --git a/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf b/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
index b55264dc27..7c06525bb8 100644
--- a/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
+++ b/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
@@ -1,7 +1,7 @@
-## @file
+## @file
# Provides interface to shell functionality for shell commands and applications.
#
-# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2006 - 2010, Intel Corporation.All rights reserved. <BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
@@ -19,13 +19,13 @@
FILE_GUID = 0e205c8a-8586-4dec-9f5c-4f9e394aefe8
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
- LIBRARY_CLASS = ShellCEntryLib|UEFI_APPLICATION
+ LIBRARY_CLASS = ShellCEntryLib|UEFI_APPLICATION UEFI_DRIVER
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
-[Sources]
+[Sources.common]
UefiShellCEntryLib.c
[Packages]
@@ -43,5 +43,5 @@
[Guids]
-[Pcd]
+[Pcd.common]
diff --git a/ShellPkg/Library/UefiShellCommandLib/ConsistMapping.c b/ShellPkg/Library/UefiShellCommandLib/ConsistMapping.c
new file mode 100644
index 0000000000..3425e9e912
--- /dev/null
+++ b/ShellPkg/Library/UefiShellCommandLib/ConsistMapping.c
@@ -0,0 +1,1310 @@
+/** @file
+ Main file for support of shell consist mapping.
+
+ Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiShellCommandLib.h"
+#include <Library/DevicePathLib.h>
+#include <Library/SortLib.h>
+
+typedef enum {
+ MTDTypeUnknown,
+ MTDTypeFloppy,
+ MTDTypeHardDisk,
+ MTDTypeCDRom,
+ MTDTypeEnd
+} MTD_TYPE;
+
+typedef struct {
+ CHAR16 *Str;
+ UINTN Len;
+} POOL_PRINT;
+
+typedef struct {
+ UINTN HI;
+ MTD_TYPE MTD;
+ POOL_PRINT CSD;
+ BOOLEAN Digital;
+} DEVICE_CONSIST_MAPPING_INFO;
+
+typedef struct {
+ MTD_TYPE MTDType;
+ CHAR16 *Name;
+} MTD_NAME;
+
+typedef struct {
+ UINT8 Type;
+ UINT8 SubType;
+ VOID (*SerialFun) (EFI_DEVICE_PATH_PROTOCOL *, DEVICE_CONSIST_MAPPING_INFO *);
+ INTN (*CompareFun) (EFI_DEVICE_PATH_PROTOCOL *, EFI_DEVICE_PATH_PROTOCOL *);
+} DEV_PATH_CONSIST_MAPPING_TABLE;
+
+
+/**
+ Concatenates a formatted unicode string to allocated pool.
+ The caller must free the resulting buffer.
+
+ @param Str Tracks the allocated pool, size in use, and amount of pool allocated.
+ @param Fmt The format string
+ @param ... The data will be printed.
+
+ @return Allocated buffer with the formatted string printed in it.
+ The caller must free the allocated buffer.
+ The buffer allocation is not packed.
+
+**/
+CHAR16 *
+EFIAPI
+CatPrint (
+ IN OUT POOL_PRINT *Str,
+ IN CHAR16 *Fmt,
+ ...
+ )
+{
+ UINT16 *AppendStr;
+ VA_LIST Args;
+ UINTN StringSize;
+
+ AppendStr = AllocateZeroPool (0x1000);
+ if (AppendStr == NULL) {
+ ASSERT(FALSE);
+ return Str->Str;
+ }
+
+ VA_START (Args, Fmt);
+ UnicodeVSPrint (AppendStr, 0x1000, Fmt, Args);
+ VA_END (Args);
+ if (NULL == Str->Str) {
+ StringSize = StrSize (AppendStr);
+ Str->Str = AllocateZeroPool (StringSize);
+ ASSERT (Str->Str != NULL);
+ } else {
+ StringSize = StrSize (AppendStr);
+ StringSize += (StrSize (Str->Str) - sizeof (UINT16));
+
+ Str->Str = ReallocatePool (
+ StrSize (Str->Str),
+ StringSize,
+ Str->Str
+ );
+ ASSERT (Str->Str != NULL);
+ }
+
+ StrCat (Str->Str, AppendStr);
+ Str->Len = StringSize;
+
+ FreePool (AppendStr);
+ return Str->Str;
+}
+
+MTD_NAME mMTDName[] = {
+ {
+ MTDTypeUnknown,
+ L"F"
+ },
+ {
+ MTDTypeFloppy,
+ L"FP"
+ },
+ {
+ MTDTypeHardDisk,
+ L"HD"
+ },
+ {
+ MTDTypeCDRom,
+ L"CD"
+ },
+ {
+ MTDTypeEnd,
+ NULL
+ }
+};
+
+VOID
+AppendCSDNum2 (
+ IN OUT POOL_PRINT *Str,
+ IN UINT64 Num
+ )
+{
+ UINT64 Result;
+ UINT32 Rem;
+
+ ASSERT(Str != NULL);
+
+ Result = DivU64x32Remainder (Num, 25, &Rem);
+ if (Result > 0) {
+ AppendCSDNum2 (Str, Result);
+ }
+
+ CatPrint (Str, L"%c", Rem + 'a');
+}
+
+VOID
+AppendCSDNum (
+ DEVICE_CONSIST_MAPPING_INFO *MappingItem,
+ UINT64 Num
+ )
+{
+ ASSERT(MappingItem != NULL);
+
+ if (MappingItem->Digital) {
+ CatPrint (&MappingItem->CSD, L"%ld", Num);
+ } else {
+ AppendCSDNum2 (&MappingItem->CSD, Num);
+ }
+
+ MappingItem->Digital = (BOOLEAN)!(MappingItem->Digital);
+}
+
+VOID
+AppendCSDStr (
+ DEVICE_CONSIST_MAPPING_INFO *MappingItem,
+ CHAR16 *Str
+ )
+{
+ CHAR16 *Index;
+
+ ASSERT(Str != NULL);
+ ASSERT(MappingItem != NULL);
+
+ if (MappingItem->Digital) {
+ //
+ // To aVOID mult-meaning, the mapping is:
+ // 0 1 2 3 4 5 6 7 8 9 a b c d e f
+ // 0 16 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ //
+ for (Index = Str; *Index != 0; Index++) {
+ switch (*Index) {
+ case '0':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ CatPrint (&MappingItem->CSD, L"%c", *Index);
+ break;
+
+ case '1':
+ CatPrint (&MappingItem->CSD, L"16");
+ break;
+
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ CatPrint (&MappingItem->CSD, L"1%c", *Index - 'a' + '0');
+ break;
+
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ CatPrint (&MappingItem->CSD, L"1%c", *Index - 'A' + '0');
+ break;
+ }
+ }
+ } else {
+ for (Index = Str; *Index != 0; Index++) {
+ //
+ // The mapping is:
+ // 0 1 2 3 4 5 6 7 8 9 a b c d e f
+ // a b c d e f g h i j k l m n o p
+ //
+ if (*Index >= '0' && *Index <= '9') {
+ CatPrint (&MappingItem->CSD, L"%c", *Index - '0' + 'a');
+ } else if (*Index >= 'a' && *Index <= 'f') {
+ CatPrint (&MappingItem->CSD, L"%c", *Index - 'a' + 'k');
+ } else if (*Index >= 'A' && *Index <= 'F') {
+ CatPrint (&MappingItem->CSD, L"%c", *Index - 'A' + 'k');
+ }
+ }
+ }
+
+ MappingItem->Digital = (BOOLEAN)!(MappingItem->Digital);
+}
+
+VOID
+AppendCSDGuid (
+ DEVICE_CONSIST_MAPPING_INFO *MappingItem,
+ EFI_GUID *Guid
+ )
+{
+ CHAR16 Buffer[64];
+ ASSERT(Guid != NULL);
+ ASSERT(MappingItem != NULL);
+
+ UnicodeSPrint (
+ Buffer,
+ 0,
+ L"%g",
+ Guid
+ );
+// StrLwr (Buffer);
+ AppendCSDStr (MappingItem, Buffer);
+}
+
+INTN
+_DevPathCompareAcpi (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2
+ )
+{
+ ACPI_HID_DEVICE_PATH *Acpi1;
+ ACPI_HID_DEVICE_PATH *Acpi2;
+
+ ASSERT(DevicePath1 != NULL);
+ ASSERT(DevicePath2 != NULL);
+
+ Acpi1 = (ACPI_HID_DEVICE_PATH *) DevicePath1;
+ Acpi2 = (ACPI_HID_DEVICE_PATH *) DevicePath2;
+ if (Acpi1->HID > Acpi2->HID || (Acpi1->HID == Acpi2->HID && Acpi1->UID > Acpi2->UID)) {
+ return 1;
+ }
+
+ if (Acpi1->HID == Acpi2->HID && Acpi1->UID == Acpi2->UID) {
+ return 0;
+ }
+
+ return -1;
+}
+
+INTN
+_DevPathComparePci (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2
+ )
+{
+ PCI_DEVICE_PATH *Pci1;
+ PCI_DEVICE_PATH *Pci2;
+
+ ASSERT(DevicePath1 != NULL);
+ ASSERT(DevicePath2 != NULL);
+
+ Pci1 = (PCI_DEVICE_PATH *) DevicePath1;
+ Pci2 = (PCI_DEVICE_PATH *) DevicePath2;
+ if (Pci1->Device > Pci2->Device || (Pci1->Device == Pci2->Device && Pci1->Function > Pci2->Function)) {
+ return 1;
+ }
+
+ if (Pci1->Device == Pci2->Device && Pci1->Function == Pci2->Function) {
+ return 0;
+ }
+
+ return -1;
+}
+
+/**
+ Do a comparison on 2 device paths.
+
+ @param[in] DevicePath1 The first device path.
+ @param[in] DevicePath2 The second device path.
+
+ @retval 0 The 2 device paths are the same.
+ @retval <0 DevicePath2 is greater than DevicePath1.
+ @retval >0 DevicePath1 is greater than DevicePath2.
+**/
+INTN
+EFIAPI
+DevPathCompareDefault (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2
+ )
+{
+ UINTN DevPathSize1;
+ UINTN DevPathSize2;
+
+ ASSERT(DevicePath1 != NULL);
+ ASSERT(DevicePath2 != NULL);
+
+ DevPathSize1 = DevicePathNodeLength (DevicePath1);
+ DevPathSize2 = DevicePathNodeLength (DevicePath2);
+ if (DevPathSize1 > DevPathSize2) {
+ return 1;
+ } else if (DevPathSize1 < DevPathSize2) {
+ return -1;
+ } else {
+ return CompareMem (DevicePath1, DevicePath2, DevPathSize1);
+ }
+}
+
+/**
+ DevicePathNode must be SerialHDD Channel type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+**/
+VOID
+EFIAPI
+DevPathSerialHardDrive (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem
+ )
+{
+ HARDDRIVE_DEVICE_PATH *Hd;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Hd = (HARDDRIVE_DEVICE_PATH *) DevicePathNode;
+ if (MappingItem->MTD == MTDTypeUnknown) {
+ MappingItem->MTD = MTDTypeHardDisk;
+ }
+
+ AppendCSDNum (MappingItem, Hd->PartitionNumber);
+}
+
+/**
+ DevicePathNode must be SerialAtapi Channel type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+**/
+VOID
+EFIAPI
+DevPathSerialAtapi (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem
+ )
+{
+ ATAPI_DEVICE_PATH *Atapi;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Atapi = (ATAPI_DEVICE_PATH *) DevicePathNode;
+ AppendCSDNum (MappingItem, (Atapi->PrimarySecondary * 2 + Atapi->SlaveMaster));
+}
+
+/**
+ DevicePathNode must be SerialCDROM Channel type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+**/
+VOID
+EFIAPI
+DevPathSerialCdRom (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem
+ )
+{
+ CDROM_DEVICE_PATH *Cd;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Cd = (CDROM_DEVICE_PATH *) DevicePathNode;
+ MappingItem->MTD = MTDTypeCDRom;
+ AppendCSDNum (MappingItem, Cd->BootEntry);
+}
+
+/**
+ DevicePathNode must be SerialFibre Channel type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+**/
+VOID
+EFIAPI
+DevPathSerialFibre (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem
+ )
+{
+ FIBRECHANNEL_DEVICE_PATH *Fibre;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Fibre = (FIBRECHANNEL_DEVICE_PATH *) DevicePathNode;
+ AppendCSDNum (MappingItem, Fibre->WWN);
+ AppendCSDNum (MappingItem, Fibre->Lun);
+}
+
+/**
+ DevicePathNode must be SerialUart type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+**/
+VOID
+EFIAPI
+DevPathSerialUart (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem
+ )
+{
+ UART_DEVICE_PATH *Uart;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Uart = (UART_DEVICE_PATH *) DevicePathNode;
+ AppendCSDNum (MappingItem, Uart->BaudRate);
+ AppendCSDNum (MappingItem, Uart->DataBits);
+ AppendCSDNum (MappingItem, Uart->Parity);
+ AppendCSDNum (MappingItem, Uart->StopBits);
+}
+
+/**
+ DevicePathNode must be SerialUSB type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+**/
+VOID
+EFIAPI
+DevPathSerialUsb (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem
+ )
+{
+ USB_DEVICE_PATH *Usb;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Usb = (USB_DEVICE_PATH *) DevicePathNode;
+ AppendCSDNum (MappingItem, Usb->ParentPortNumber);
+ AppendCSDNum (MappingItem, Usb->InterfaceNumber);
+}
+
+/**
+ DevicePathNode must be SerialVendor type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+**/
+VOID
+EFIAPI
+DevPathSerialVendor (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem
+ )
+{
+ VENDOR_DEVICE_PATH *Vendor;
+ SAS_DEVICE_PATH *Sas;
+ EFI_GUID SasVendorGuid = DEVICE_PATH_MESSAGING_SAS;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Vendor = (VENDOR_DEVICE_PATH *) DevicePathNode;
+ AppendCSDGuid (MappingItem, &Vendor->Guid);
+
+ if (CompareGuid (&SasVendorGuid, &Vendor->Guid) == 0) {
+ Sas = (SAS_DEVICE_PATH *) Vendor;
+ AppendCSDNum (MappingItem, Sas->SasAddress);
+ AppendCSDNum (MappingItem, Sas->Lun);
+ AppendCSDNum (MappingItem, Sas->DeviceTopology);
+ AppendCSDNum (MappingItem, Sas->RelativeTargetPort);
+ }
+}
+
+/**
+ DevicePathNode must be SerialLun type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+**/
+VOID
+EFIAPI
+DevPathSerialLun (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem
+ )
+{
+ DEVICE_LOGICAL_UNIT_DEVICE_PATH *Lun;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Lun = (DEVICE_LOGICAL_UNIT_DEVICE_PATH *) DevicePathNode;
+ AppendCSDNum (MappingItem, Lun->Lun);
+}
+
+/**
+ DevicePathNode must be SerialSata type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+**/
+VOID
+EFIAPI
+DevPathSerialSata (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem
+ )
+{
+ SATA_DEVICE_PATH *Sata;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Sata = (SATA_DEVICE_PATH *) DevicePathNode;
+ AppendCSDNum (MappingItem, Sata->HBAPortNumber);
+ AppendCSDNum (MappingItem, Sata->PortMultiplierPortNumber);
+ AppendCSDNum (MappingItem, Sata->Lun);
+}
+
+/**
+ DevicePathNode must be SerialSCSI type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+**/
+VOID
+EFIAPI
+DevPathSerialIScsi (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem
+ )
+{
+///@todo make this a PCD
+//
+// As CSD of ISCSI node is quite long, we comment
+// the code below to keep the consistent mapping
+// short. Uncomment if you really need it.
+//
+/*
+ ISCSI_DEVICE_PATH *IScsi;
+ UINT8 *IScsiTargetName;
+ CHAR16 *TargetName;
+ UINTN TargetNameLength;
+ UINTN Index;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ IScsi = (ISCSI_DEVICE_PATH *) DevicePathNode;
+ AppendCSDNum (MappingItem, IScsi->NetworkProtocol);
+ AppendCSDNum (MappingItem, IScsi->LoginOption);
+ AppendCSDNum (MappingItem, IScsi->Lun);
+ AppendCSDNum (MappingItem, IScsi->TargetPortalGroupTag);
+ TargetNameLength = DevicePathNodeLength (DevicePathNode) - sizeof (ISCSI_DEVICE_PATH);
+ if (TargetNameLength > 0) {
+ TargetName = AllocateZeroPool ((TargetNameLength + 1) * sizeof (CHAR16));
+ if (TargetName != NULL) {
+ IScsiTargetName = (UINT8 *) (IScsi + 1);
+ for (Index = 0; Index < TargetNameLength; Index++) {
+ TargetName[Index] = (CHAR16) IScsiTargetName[Index];
+ }
+ AppendCSDStr (MappingItem, TargetName);
+ FreePool (TargetName);
+ }
+ }
+ */
+}
+
+/**
+ DevicePathNode must be SerialI20 type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+**/
+VOID
+EFIAPI
+DevPathSerialI2O (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem
+ )
+{
+ I2O_DEVICE_PATH *I2O;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ I2O = (I2O_DEVICE_PATH *) DevicePathNode;
+ AppendCSDNum (MappingItem, I2O->Tid);
+}
+
+/**
+ DevicePathNode must be Mac Address type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+**/
+VOID
+EFIAPI
+DevPathSerialMacAddr (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem
+ )
+{
+ MAC_ADDR_DEVICE_PATH *Mac;
+ UINTN HwAddressSize;
+ UINTN Index;
+ CHAR16 Buffer[64];
+ CHAR16 *PBuffer;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Mac = (MAC_ADDR_DEVICE_PATH *) DevicePathNode;
+
+ HwAddressSize = sizeof (EFI_MAC_ADDRESS);
+ if (Mac->IfType == 0x01 || Mac->IfType == 0x00) {
+ HwAddressSize = 6;
+ }
+
+ for (Index = 0, PBuffer = Buffer; Index < HwAddressSize; Index++, PBuffer += 2) {
+ UnicodeSPrint (PBuffer, 0, L"%02x", (UINTN) Mac->MacAddress.Addr[Index]);
+ }
+
+ AppendCSDStr (MappingItem, Buffer);
+}
+
+/**
+ DevicePathNode must be InfiniBand type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+**/
+VOID
+EFIAPI
+DevPathSerialInfiniBand (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem
+ )
+{
+ INFINIBAND_DEVICE_PATH *InfiniBand;
+ UINTN Index;
+ CHAR16 Buffer[64];
+ CHAR16 *PBuffer;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ InfiniBand = (INFINIBAND_DEVICE_PATH *) DevicePathNode;
+ for (Index = 0, PBuffer = Buffer; Index < 16; Index++, PBuffer += 2) {
+ UnicodeSPrint (PBuffer, 0, L"%02x", (UINTN) InfiniBand->PortGid[Index]);
+ }
+
+ AppendCSDStr (MappingItem, Buffer);
+ AppendCSDNum (MappingItem, InfiniBand->ServiceId);
+ AppendCSDNum (MappingItem, InfiniBand->TargetPortId);
+ AppendCSDNum (MappingItem, InfiniBand->DeviceId);
+}
+
+/**
+ DevicePathNode must be IPv4 type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+**/
+VOID
+EFIAPI
+DevPathSerialIPv4 (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem
+ )
+{
+ IPv4_DEVICE_PATH *Ip;
+ CHAR16 Buffer[10];
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Ip = (IPv4_DEVICE_PATH *) DevicePathNode;
+ UnicodeSPrint (
+ Buffer,
+ 0,
+ L"%02x%02x%02x%02x",
+ (UINTN) Ip->LocalIpAddress.Addr[0],
+ (UINTN) Ip->LocalIpAddress.Addr[1],
+ (UINTN) Ip->LocalIpAddress.Addr[2],
+ (UINTN) Ip->LocalIpAddress.Addr[3]
+ );
+ AppendCSDStr (MappingItem, Buffer);
+ AppendCSDNum (MappingItem, Ip->LocalPort);
+ UnicodeSPrint (
+ Buffer,
+ 0,
+ L"%02x%02x%02x%02x",
+ (UINTN) Ip->RemoteIpAddress.Addr[0],
+ (UINTN) Ip->RemoteIpAddress.Addr[1],
+ (UINTN) Ip->RemoteIpAddress.Addr[2],
+ (UINTN) Ip->RemoteIpAddress.Addr[3]
+ );
+ AppendCSDStr (MappingItem, Buffer);
+ AppendCSDNum (MappingItem, Ip->RemotePort);
+}
+
+/**
+ DevicePathNode must be IPv6 type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+**/
+VOID
+EFIAPI
+DevPathSerialIPv6 (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem
+ )
+{
+ IPv6_DEVICE_PATH *Ip;
+ UINTN Index;
+ CHAR16 Buffer[64];
+ CHAR16 *PBuffer;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Ip = (IPv6_DEVICE_PATH *) DevicePathNode;
+ for (Index = 0, PBuffer = Buffer; Index < 16; Index++, PBuffer += 2) {
+ UnicodeSPrint (PBuffer, 0, L"%02x", (UINTN) Ip->LocalIpAddress.Addr[Index]);
+ }
+
+ AppendCSDStr (MappingItem, Buffer);
+ AppendCSDNum (MappingItem, Ip->LocalPort);
+ for (Index = 0, PBuffer = Buffer; Index < 16; Index++, PBuffer += 2) {
+ UnicodeSPrint (PBuffer, 0, L"%02x", (UINTN) Ip->RemoteIpAddress.Addr[Index]);
+ }
+
+ AppendCSDStr (MappingItem, Buffer);
+ AppendCSDNum (MappingItem, Ip->RemotePort);
+}
+
+/**
+ DevicePathNode must be SCSI type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+**/
+VOID
+EFIAPI
+DevPathSerialScsi (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem
+ )
+{
+ SCSI_DEVICE_PATH *Scsi;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Scsi = (SCSI_DEVICE_PATH *) DevicePathNode;
+ AppendCSDNum (MappingItem, Scsi->Pun);
+ AppendCSDNum (MappingItem, Scsi->Lun);
+}
+
+/**
+ DevicePathNode must be 1394 type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+**/
+VOID
+EFIAPI
+DevPathSerial1394 (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem
+ )
+{
+ F1394_DEVICE_PATH *F1394;
+ CHAR16 Buffer[20];
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ F1394 = (F1394_DEVICE_PATH *) DevicePathNode;
+ UnicodeSPrint (Buffer, 0, L"%lx", F1394->Guid);
+ AppendCSDStr (MappingItem, Buffer);
+}
+
+/**
+ If the node is floppy type then populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+**/
+VOID
+EFIAPI
+DevPathSerialAcpi (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem
+ )
+{
+ ACPI_HID_DEVICE_PATH *Acpi;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Acpi = (ACPI_HID_DEVICE_PATH *) DevicePathNode;
+ if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
+ if (EISA_ID_TO_NUM (Acpi->HID) == 0x0604) {
+ MappingItem->MTD = MTDTypeFloppy;
+ AppendCSDNum (MappingItem, Acpi->UID);
+ }
+ }
+}
+
+/**
+ Empty function used for unknown devices.
+
+ Does nothing.
+**/
+VOID
+EFIAPI
+DevPathSerialDefault (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem
+ )
+{
+}
+
+DEV_PATH_CONSIST_MAPPING_TABLE DevPathConsistMappingTable[] = {
+ HARDWARE_DEVICE_PATH,
+ HW_PCI_DP,
+ DevPathSerialDefault,
+ _DevPathComparePci,
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ DevPathSerialAcpi,
+ _DevPathCompareAcpi,
+ MESSAGING_DEVICE_PATH,
+ MSG_ATAPI_DP,
+ DevPathSerialAtapi,
+ DevPathCompareDefault,
+ MESSAGING_DEVICE_PATH,
+ MSG_SCSI_DP,
+ DevPathSerialScsi,
+ DevPathCompareDefault,
+ MESSAGING_DEVICE_PATH,
+ MSG_FIBRECHANNEL_DP,
+ DevPathSerialFibre,
+ DevPathCompareDefault,
+ MESSAGING_DEVICE_PATH,
+ MSG_1394_DP,
+ DevPathSerial1394,
+ DevPathCompareDefault,
+ MESSAGING_DEVICE_PATH,
+ MSG_USB_DP,
+ DevPathSerialUsb,
+ DevPathCompareDefault,
+ MESSAGING_DEVICE_PATH,
+ MSG_I2O_DP,
+ DevPathSerialI2O,
+ DevPathCompareDefault,
+ MESSAGING_DEVICE_PATH,
+ MSG_MAC_ADDR_DP,
+ DevPathSerialMacAddr,
+ DevPathCompareDefault,
+ MESSAGING_DEVICE_PATH,
+ MSG_IPv4_DP,
+ DevPathSerialIPv4,
+ DevPathCompareDefault,
+ MESSAGING_DEVICE_PATH,
+ MSG_IPv6_DP,
+ DevPathSerialIPv6,
+ DevPathCompareDefault,
+ MESSAGING_DEVICE_PATH,
+ MSG_INFINIBAND_DP,
+ DevPathSerialInfiniBand,
+ DevPathCompareDefault,
+ MESSAGING_DEVICE_PATH,
+ MSG_UART_DP,
+ DevPathSerialUart,
+ DevPathCompareDefault,
+ MESSAGING_DEVICE_PATH,
+ MSG_VENDOR_DP,
+ DevPathSerialVendor,
+ DevPathCompareDefault,
+ MESSAGING_DEVICE_PATH,
+ MSG_DEVICE_LOGICAL_UNIT_DP,
+ DevPathSerialLun,
+ DevPathCompareDefault,
+ MESSAGING_DEVICE_PATH,
+ MSG_SATA_DP,
+ DevPathSerialSata,
+ DevPathCompareDefault,
+ MESSAGING_DEVICE_PATH,
+ MSG_ISCSI_DP,
+ DevPathSerialIScsi,
+ DevPathCompareDefault,
+ MEDIA_DEVICE_PATH,
+ MEDIA_HARDDRIVE_DP,
+ DevPathSerialHardDrive,
+ DevPathCompareDefault,
+ MEDIA_DEVICE_PATH,
+ MEDIA_CDROM_DP,
+ DevPathSerialCdRom,
+ DevPathCompareDefault,
+ MEDIA_DEVICE_PATH,
+ MEDIA_VENDOR_DP,
+ DevPathSerialVendor,
+ DevPathCompareDefault,
+ 0,
+ 0,
+ NULL,
+ NULL
+};
+
+/**
+ Function to determine if a device path node is Hi or not.
+
+ @param[in] DevicePathNode The node to check.
+
+ @retval TRUE The node is HI.
+ @retval FALSE The node is not HI.
+**/
+BOOLEAN
+EFIAPI
+IsHIDevicePathNode (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode
+ )
+{
+ ACPI_HID_DEVICE_PATH *Acpi;
+
+ ASSERT(DevicePathNode != NULL);
+
+ if (DevicePathNode->Type == HARDWARE_DEVICE_PATH) {
+ return TRUE;
+ }
+
+ if (DevicePathNode->Type == ACPI_DEVICE_PATH) {
+ Acpi = (ACPI_HID_DEVICE_PATH *) DevicePathNode;
+ switch (EISA_ID_TO_NUM (Acpi->HID)) {
+ case 0x0301:
+ case 0x0401:
+ case 0x0501:
+ case 0x0604:
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Function to convert a standard device path structure into a HI version.
+
+ @param[in] DevicePath The device path to convert.
+
+ @return the device path portion that is HI.
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+GetHIDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ UINTN NonHIDevicePathNodeCount;
+ UINTN Index;
+ EFI_DEV_PATH Node;
+ EFI_DEVICE_PATH_PROTOCOL *HIDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+
+ ASSERT(DevicePath != NULL);
+
+ NonHIDevicePathNodeCount = 0;
+
+ HIDevicePath = AllocatePool (sizeof (EFI_DEVICE_PATH_PROTOCOL));
+ SetDevicePathEndNode (HIDevicePath);
+
+ Node.DevPath.Type = END_DEVICE_PATH_TYPE;
+ Node.DevPath.SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE;
+ Node.DevPath.Length[0] = (UINT8)sizeof (EFI_DEVICE_PATH_PROTOCOL);
+ Node.DevPath.Length[1] = 0;
+
+ while (!IsDevicePathEnd (DevicePath)) {
+ if (IsHIDevicePathNode (DevicePath)) {
+ for (Index = 0; Index < NonHIDevicePathNodeCount; Index++) {
+ TempDevicePath = AppendDevicePathNode (HIDevicePath, &Node.DevPath);
+ FreePool (HIDevicePath);
+ HIDevicePath = TempDevicePath;
+ }
+
+ TempDevicePath = AppendDevicePathNode (HIDevicePath, DevicePath);
+ FreePool (HIDevicePath);
+ HIDevicePath = TempDevicePath;
+ } else {
+ NonHIDevicePathNodeCount++;
+ }
+ //
+ // Next device path node
+ //
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (DevicePath);
+ }
+
+ return HIDevicePath;
+}
+
+/**
+ Function to walk the device path looking for a dumpable node.
+
+ @param[in] MappingItem The Item to fill with data.
+ @param[in] DevicePath The path of the item to get data on.
+
+ @return EFI_SUCCESS Always returns success.
+**/
+EFI_STATUS
+EFIAPI
+GetDeviceConsistMappingInfo (
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ VOID (*SerialFun) (EFI_DEVICE_PATH_PROTOCOL *, DEVICE_CONSIST_MAPPING_INFO *);
+
+ UINTN Index;
+
+ ASSERT(DevicePath != NULL);
+ ASSERT(MappingItem != NULL);
+
+ SetMem (&MappingItem->CSD, sizeof (POOL_PRINT), 0);
+
+ while (!IsDevicePathEnd (DevicePath)) {
+ //
+ // Find the handler to dump this device path node
+ //
+ SerialFun = NULL;
+ for (Index = 0; DevPathConsistMappingTable[Index].SerialFun != NULL; Index += 1) {
+
+ if (DevicePathType (DevicePath) == DevPathConsistMappingTable[Index].Type &&
+ DevicePathSubType (DevicePath) == DevPathConsistMappingTable[Index].SubType
+ ) {
+ SerialFun = DevPathConsistMappingTable[Index].SerialFun;
+ break;
+ }
+ }
+ //
+ // If not found, use a generic function
+ //
+ if (!SerialFun) {
+ SerialFun = DevPathSerialDefault;
+ }
+
+ SerialFun (DevicePath, MappingItem);
+
+ //
+ // Next device path node
+ //
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (DevicePath);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Function to initialize the table for creating consistent map names.
+
+ @param[out] Table The pointer to pointer to pointer to DevicePathProtocol object.
+
+ @retval EFI_SUCCESS The table was created successfully.
+**/
+EFI_STATUS
+EFIAPI
+ShellCommandConsistMappingInitialize (
+ OUT EFI_DEVICE_PATH_PROTOCOL ***Table
+ )
+{
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleNum;
+ UINTN HandleLoop;
+ EFI_DEVICE_PATH_PROTOCOL **TempTable;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *HIDevicePath;
+ UINTN Index;
+ EFI_STATUS Status;
+
+ HandleBuffer = NULL;
+
+ Status = gBS->LocateHandleBuffer (
+ AllHandles,
+ NULL,
+ NULL,
+ &HandleNum,
+ &HandleBuffer
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ TempTable = AllocateZeroPool ((HandleNum + 1) * sizeof (EFI_DEVICE_PATH_PROTOCOL *));
+ if (TempTable == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (HandleLoop = 0 ; HandleLoop < HandleNum ; HandleLoop++) {
+ DevicePath = DevicePathFromHandle (HandleBuffer[HandleLoop]);
+ if (DevicePath == NULL) {
+ continue;
+ }
+
+ HIDevicePath = GetHIDevicePath (DevicePath);
+ if (HIDevicePath == NULL) {
+ continue;
+ }
+
+ for (Index = 0; TempTable[Index] != NULL; Index++) {
+ if (DevicePathCompare (&TempTable[Index], &HIDevicePath) == 0) {
+ FreePool (HIDevicePath);
+ break;
+ }
+ }
+
+ if (TempTable[Index] == NULL) {
+ TempTable[Index] = HIDevicePath;
+ }
+ }
+
+ for (Index = 0; TempTable[Index] != NULL; Index++);
+ PerformQuickSort(TempTable, Index, sizeof(EFI_DEVICE_PATH_PROTOCOL*), DevicePathCompare);
+ *Table = TempTable;
+
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Function to uninitialize the table for creating consistent map names.
+
+ The parameter must have been received from ShellCommandConsistMappingInitialize.
+
+ @param[out] Table The pointer to pointer to DevicePathProtocol object.
+
+ @retval EFI_SUCCESS The table was deleted successfully.
+**/
+EFI_STATUS
+EFIAPI
+ShellCommandConsistMappingUnInitialize (
+ EFI_DEVICE_PATH_PROTOCOL **Table
+ )
+{
+ UINTN Index;
+
+ ASSERT(Table != NULL);
+
+ for (Index = 0; Table[Index] != NULL; Index++) {
+ FreePool (Table[Index]);
+ }
+
+ FreePool (Table);
+ return EFI_SUCCESS;
+}
+
+/**
+ Create a consistent mapped name for the device specified by DevicePath
+ based on the Table.
+
+ This must be called after ShellCommandConsistMappingInitialize() and
+ before ShellCommandConsistMappingUnInitialize() is called.
+
+ @param[in] DeviecPath The pointer to the dev path for the device.
+ @param[in] Table The Table of mapping information.
+
+ @retval NULL A consistent mapped name could not be created.
+ @return A pointer to a string allocated from pool with the device name.
+**/
+CHAR16 *
+EFIAPI
+ShellCommandConsistMappingGenMappingName (
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ EFI_DEVICE_PATH_PROTOCOL **Table
+ )
+{
+ POOL_PRINT Str;
+ DEVICE_CONSIST_MAPPING_INFO MappingInfo;
+ EFI_DEVICE_PATH_PROTOCOL *HIDevicePath;
+ UINTN Index;
+ UINTN NewSize;
+
+ ASSERT(DevicePath != NULL);
+ ASSERT(Table != NULL);
+
+ HIDevicePath = GetHIDevicePath (DevicePath);
+ if (HIDevicePath == NULL) {
+ return NULL;
+ }
+
+ for (Index = 0; Table[Index] != NULL; Index++) {
+ if (DevicePathCompare (&Table[Index], &HIDevicePath) == 0) {
+ break;
+ }
+ }
+
+ FreePool (HIDevicePath);
+ if (Table[Index] == NULL) {
+ return NULL;
+ }
+
+ MappingInfo.HI = Index;
+ MappingInfo.MTD = MTDTypeUnknown;
+ MappingInfo.Digital = FALSE;
+
+ GetDeviceConsistMappingInfo (&MappingInfo, DevicePath);
+
+ SetMem (&Str, sizeof (Str), 0);
+ for (Index = 0; mMTDName[Index].MTDType != MTDTypeEnd; Index++) {
+ if (MappingInfo.MTD == mMTDName[Index].MTDType) {
+ break;
+ }
+ }
+
+ if (mMTDName[Index].MTDType != MTDTypeEnd) {
+ CatPrint (&Str, L"%s", mMTDName[Index].Name);
+ }
+
+ CatPrint (&Str, L"%d", (UINTN) MappingInfo.HI);
+ if (MappingInfo.CSD.Str != NULL) {
+ CatPrint (&Str, L"%s", MappingInfo.CSD.Str);
+ FreePool (MappingInfo.CSD.Str);
+ }
+
+ if (Str.Str != NULL) {
+ CatPrint (&Str, L":");
+ }
+
+ NewSize = (Str.Len + 1) * sizeof (CHAR16);
+ Str.Str = ReallocatePool (Str.Len, NewSize, Str.Str);
+ Str.Str[Str.Len] = CHAR_NULL;
+ return Str.Str;
+}
+
+/**
+ Function to search the list of mappings for the node on the list based on the key.
+
+ @param[in] MapKey String Key to search for on the map
+
+ @return the node on the list.
+**/
+SHELL_MAP_LIST *
+EFIAPI
+ShellCommandFindMapItem (
+ IN CONST CHAR16 *MapKey
+ )
+{
+ SHELL_MAP_LIST *MapListItem;
+
+ for ( MapListItem = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link)
+ ; !IsNull(&gShellMapList.Link, &MapListItem->Link)
+ ; MapListItem = (SHELL_MAP_LIST *)GetNextNode(&gShellMapList.Link, &MapListItem->Link)
+ ){
+ if (gUnicodeCollation->StriColl(gUnicodeCollation,MapListItem->MapName,(CHAR16*)MapKey) == 0) {
+ return (MapListItem);
+ }
+ }
+ return (NULL);
+}
+
+
diff --git a/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c b/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c
new file mode 100644
index 0000000000..5a3739ff91
--- /dev/null
+++ b/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c
@@ -0,0 +1,1511 @@
+/** @file
+ Provides interface to shell internal functions for shell commands.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiShellCommandLib.h"
+
+/// The tag for use in identifying UNICODE files.
+/// If the file is UNICODE, the first 16 bits of the file will equal this value.
+enum {
+ UnicodeFileTag = 0xFEFF
+};
+
+// STATIC local variables
+STATIC SHELL_COMMAND_INTERNAL_LIST_ENTRY mCommandList;
+STATIC SCRIPT_FILE_LIST mScriptList;
+STATIC ALIAS_LIST mAliasList;
+STATIC BOOLEAN mEchoState;
+STATIC BOOLEAN mExitRequested;
+STATIC BOOLEAN mExitScript;
+STATIC CHAR16 *mProfileList;
+STATIC UINTN mProfileListSize;
+STATIC UINTN mFsMaxCount = 0;
+STATIC UINTN mBlkMaxCount = 0;
+STATIC BUFFER_LIST mFileHandleList;
+
+// global variables required by library class.
+EFI_SHELL_PROTOCOL *gEfiShellProtocol = NULL;
+EFI_SHELL_PARAMETERS_PROTOCOL *gEfiShellParametersProtocol = NULL;
+EFI_UNICODE_COLLATION_PROTOCOL *gUnicodeCollation = NULL;
+EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *gDevPathToText = NULL;
+SHELL_MAP_LIST gShellMapList;
+SHELL_MAP_LIST *gShellCurDir = NULL;
+
+CONST CHAR16* SupportLevel[] = {
+ L"Minimal",
+ L"Scripting",
+ L"Basic",
+ L"Interactive"
+};
+
+/**
+ Function to make sure that the global protocol pointers are valid.
+ must be called after constructor before accessing the pointers.
+**/
+EFI_STATUS
+EFIAPI
+CommandInit(
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ if (gEfiShellParametersProtocol == NULL) {
+ Status = gBS->OpenProtocol(gImageHandle,
+ &gEfiShellParametersProtocolGuid,
+ (VOID **)&gEfiShellParametersProtocol,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR(Status)) {
+ return (EFI_DEVICE_ERROR);
+ }
+ }
+ if (gEfiShellProtocol == NULL) {
+ Status = gBS->LocateProtocol(&gEfiShellProtocolGuid, NULL, (VOID**)&gEfiShellProtocol);
+ if (EFI_ERROR(Status)) {
+ return (EFI_DEVICE_ERROR);
+ }
+ }
+ if (gUnicodeCollation == NULL) {
+ Status = gBS->LocateProtocol(&gEfiUnicodeCollation2ProtocolGuid, NULL, (VOID**)&gUnicodeCollation);
+ if (EFI_ERROR(Status)) {
+ return (EFI_DEVICE_ERROR);
+ }
+ }
+ if (gDevPathToText == NULL) {
+ Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID**)&gDevPathToText);
+ if (EFI_ERROR(Status)) {
+ return (EFI_DEVICE_ERROR);
+ }
+ }
+ return (EFI_SUCCESS);
+}
+
+/**
+ Constructor for the Shell Command 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_STATUS
+EFIAPI
+ShellCommandLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ InitializeListHead(&gShellMapList.Link);
+ InitializeListHead(&mCommandList.Link);
+ InitializeListHead(&mAliasList.Link);
+ InitializeListHead(&mScriptList.Link);
+ InitializeListHead(&mFileHandleList.Link);
+ mEchoState = TRUE;
+
+ mExitRequested = FALSE;
+ mExitScript = FALSE;
+ mProfileListSize = 0;
+ mProfileList = NULL;
+
+ if (gUnicodeCollation == NULL) {
+ Status = gBS->LocateProtocol(&gEfiUnicodeCollation2ProtocolGuid, NULL, (VOID**)&gUnicodeCollation);
+ if (EFI_ERROR(Status)) {
+ return (EFI_DEVICE_ERROR);
+ }
+ }
+
+ return (RETURN_SUCCESS);
+}
+
+/**
+ Destructor for the library. free any resources.
+
+ @param ImageHandle the image handle of the process
+ @param SystemTable the EFI System Table pointer
+
+ @retval RETURN_SUCCESS this function always returns success
+**/
+RETURN_STATUS
+EFIAPI
+ShellCommandLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node;
+ COMMAND_LIST *Node2;
+ SCRIPT_FILE_LIST *Node3;
+ SHELL_MAP_LIST *MapNode;
+ //
+ // enumerate throught the list and free all the memory
+ //
+ while (!IsListEmpty (&mCommandList.Link)) {
+ Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode(&mCommandList.Link);
+ RemoveEntryList(&Node->Link);
+ SHELL_FREE_NON_NULL(Node->CommandString);
+ FreePool(Node);
+ DEBUG_CODE(Node = NULL;);
+ }
+
+ //
+ // enumerate through the init command list and free all memory
+ //
+ while (!IsListEmpty (&mAliasList.Link)) {
+ Node2 = (COMMAND_LIST *)GetFirstNode(&mAliasList.Link);
+ RemoveEntryList(&Node2->Link);
+ SHELL_FREE_NON_NULL(Node2->CommandString);
+ FreePool(Node2);
+ DEBUG_CODE(Node2 = NULL;);
+ }
+
+ //
+ // enumerate throught the list and free all the memory
+ //
+ while (!IsListEmpty (&mScriptList.Link)) {
+ Node3 = (SCRIPT_FILE_LIST *)GetFirstNode(&mScriptList.Link);
+ RemoveEntryList(&Node3->Link);
+ DeleteScriptFileStruct(Node3->Data);
+ FreePool(Node3);
+ }
+
+ //
+ // enumerate throught the mappings list and free all the memory
+ //
+ if (!IsListEmpty(&gShellMapList.Link)) {
+ for (MapNode = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link)
+ ; !IsListEmpty (&gShellMapList.Link)
+ ; MapNode = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link)
+ ){
+ ASSERT(MapNode != NULL);
+ RemoveEntryList(&MapNode->Link);
+ SHELL_FREE_NON_NULL(MapNode->DevicePath);
+ SHELL_FREE_NON_NULL(MapNode->MapName);
+ SHELL_FREE_NON_NULL(MapNode->CurrentDirectoryPath);
+ FreePool(MapNode);
+ }
+ }
+ if (!IsListEmpty(&mFileHandleList.Link)){
+ FreeBufferList(&mFileHandleList);
+ }
+
+ if (mProfileList != NULL) {
+ FreePool(mProfileList);
+ }
+
+ return (RETURN_SUCCESS);
+}
+
+/**
+ Checks if a command is already on the list.
+
+ @param[in] CommandString The command string to check for on the list.
+**/
+BOOLEAN
+EFIAPI
+ShellCommandIsCommandOnList (
+ IN CONST CHAR16 *CommandString
+ )
+{
+ SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node;
+
+ //
+ // assert for NULL parameter
+ //
+ ASSERT(CommandString != NULL);
+
+ //
+ // check for the command
+ //
+ for ( Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode(&mCommandList.Link)
+ ; !IsNull(&mCommandList.Link, &Node->Link)
+ ; Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode(&mCommandList.Link, &Node->Link)
+ ){
+ ASSERT(Node->CommandString != NULL);
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)CommandString,
+ Node->CommandString) == 0
+ ){
+ return (TRUE);
+ }
+ }
+ return (FALSE);
+}
+
+/**
+ Get the help text for a command.
+
+ @param[in] CommandString The command name.
+
+ @retval NULL No help text was found.
+ @return String of help text. Caller reuiqred to free.
+**/
+CHAR16*
+EFIAPI
+ShellCommandGetCommandHelp (
+ IN CONST CHAR16 *CommandString
+ )
+{
+ SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node;
+
+ //
+ // assert for NULL parameter
+ //
+ ASSERT(CommandString != NULL);
+
+ //
+ // check for the command
+ //
+ for ( Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode(&mCommandList.Link)
+ ; !IsNull(&mCommandList.Link, &Node->Link)
+ ; Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode(&mCommandList.Link, &Node->Link)
+ ){
+ ASSERT(Node->CommandString != NULL);
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)CommandString,
+ Node->CommandString) == 0
+ ){
+ return (HiiGetString(Node->HiiHandle, Node->ManFormatHelp, NULL));
+ }
+ }
+ return (NULL);
+}
+
+/**
+ Registers handlers of type SHELL_RUN_COMMAND and
+ SHELL_GET_MAN_FILENAME for each shell command.
+
+ If the ShellSupportLevel is greater than the value of the
+ PcdShellSupportLevel then return RETURN_UNSUPPORTED.
+
+ Registers the handlers specified by GetHelpInfoHandler and CommandHandler
+ with the command specified by CommandString. If the command named by
+ CommandString has already been registered, then return
+ RETURN_ALREADY_STARTED.
+
+ If there are not enough resources available to register the handlers then
+ RETURN_OUT_OF_RESOURCES is returned.
+
+ If CommandString is NULL, then ASSERT().
+ If GetHelpInfoHandler is NULL, then ASSERT().
+ If CommandHandler is NULL, then ASSERT().
+ If ProfileName is NULL, then ASSERT().
+
+ @param[in] CommandString Pointer to the command name. This is the
+ name to look for on the command line in
+ the shell.
+ @param[in] CommandHandler Pointer to a function that runs the
+ specified command.
+ @param[in] GetManFileName Pointer to a function that provides man
+ filename.
+ @param[in] ShellMinSupportLevel minimum Shell Support Level which has this
+ function.
+ @param[in] ProfileName profile name to require for support of this
+ function.
+ @param[in] CanAffectLE indicates whether this command's return value
+ can change the LASTERROR environment variable.
+ @param[in] HiiHandle Handle of this command's HII entry.
+ @param[in] ManFormatHelp HII locator for the help text.
+
+ @retval RETURN_SUCCESS The handlers were registered.
+ @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to
+ register the shell command.
+ @retval RETURN_UNSUPPORTED the ShellMinSupportLevel was higher than the
+ currently allowed support level.
+ @retval RETURN_ALREADY_STARTED The CommandString represents a command that
+ is already registered. Only 1 handler set for
+ a given command is allowed.
+ @sa SHELL_GET_MAN_FILENAME
+ @sa SHELL_RUN_COMMAND
+**/
+RETURN_STATUS
+EFIAPI
+ShellCommandRegisterCommandName (
+ IN CONST CHAR16 *CommandString,
+ IN SHELL_RUN_COMMAND CommandHandler,
+ IN SHELL_GET_MAN_FILENAME GetManFileName,
+ IN UINT32 ShellMinSupportLevel,
+ IN CONST CHAR16 *ProfileName,
+ IN CONST BOOLEAN CanAffectLE,
+ IN CONST EFI_HANDLE HiiHandle,
+ IN CONST EFI_STRING_ID ManFormatHelp
+ )
+{
+ SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node;
+
+ //
+ // ASSERTs for NULL parameters
+ //
+ ASSERT(CommandString != NULL);
+ ASSERT(GetManFileName != NULL);
+ ASSERT(CommandHandler != NULL);
+ ASSERT(ProfileName != NULL);
+
+ //
+ // check for shell support level
+ //
+ if (PcdGet8(PcdShellSupportLevel) < ShellMinSupportLevel) {
+ return (RETURN_UNSUPPORTED);
+ }
+
+ //
+ // check for already on the list
+ //
+ if (ShellCommandIsCommandOnList(CommandString)) {
+ return (RETURN_ALREADY_STARTED);
+ }
+
+ //
+ // allocate memory for new struct
+ //
+ Node = AllocatePool(sizeof(SHELL_COMMAND_INTERNAL_LIST_ENTRY));
+ ASSERT(Node != NULL);
+ Node->CommandString = AllocatePool(StrSize(CommandString));
+ ASSERT(Node->CommandString != NULL);
+
+ //
+ // populate the new struct
+ //
+ StrCpy(Node->CommandString, CommandString);
+
+ Node->GetManFileName = GetManFileName;
+ Node->CommandHandler = CommandHandler;
+ Node->LastError = CanAffectLE;
+ Node->HiiHandle = HiiHandle;
+ Node->ManFormatHelp = ManFormatHelp;
+
+ if ( StrLen(ProfileName)>0
+ && ((mProfileList != NULL
+ && StrStr(mProfileList, ProfileName) == NULL) || mProfileList == NULL)
+ ){
+ ASSERT((mProfileList == NULL && mProfileListSize == 0) || (mProfileList != NULL));
+ if (mProfileList == NULL) {
+ //
+ // If this is the first make a leading ';'
+ //
+ StrnCatGrow(&mProfileList, &mProfileListSize, L";", 0);
+ }
+ StrnCatGrow(&mProfileList, &mProfileListSize, ProfileName, 0);
+ StrnCatGrow(&mProfileList, &mProfileListSize, L";", 0);
+ }
+
+ //
+ // add the new struct to the list
+ //
+ InsertTailList (&mCommandList.Link, &Node->Link);
+
+ return (RETURN_SUCCESS);
+}
+
+/**
+ Function to get the current Profile string.
+
+ @retval NULL There are no installed profiles.
+ @return A semi-colon delimited list of profiles.
+**/
+CONST CHAR16 *
+EFIAPI
+ShellCommandGetProfileList (
+ VOID
+ )
+{
+ return (mProfileList);
+}
+
+/**
+ Checks if a command string has been registered for CommandString and if so it runs
+ the previously registered handler for that command with the command line.
+
+ If CommandString is NULL, then ASSERT().
+
+ If Sections is specified, then each section name listed will be compared in a casesensitive
+ manner, to the section names described in Appendix B UEFI Shell 2.0 spec. If the section exists,
+ it will be appended to the returned help text. If the section does not exist, no
+ information will be returned. If Sections is NULL, then all help text information
+ available will be returned.
+
+ @param Sections pointer to string representing which section to get help on.
+
+ @param[in] CommandString Pointer to the command name. This is the name
+ found on the command line in the shell.
+ @param[in,out] RetVal Pointer to the return vaule from the command handler.
+
+ @param[in,out] CanAffectLE indicates whether this command's return value
+ needs to be placed into LASTERROR environment variable.
+
+ @retval RETURN_SUCCESS The handler was run.
+ @retval RETURN_NOT_FOUND The CommandString did not match a registered
+ command name.
+ @sa SHELL_RUN_COMMAND
+**/
+RETURN_STATUS
+EFIAPI
+ShellCommandRunCommandHandler (
+ IN CONST CHAR16 *CommandString,
+ IN OUT SHELL_STATUS *RetVal,
+ IN OUT BOOLEAN *CanAffectLE OPTIONAL
+ )
+{
+ SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node;
+
+ //
+ // assert for NULL parameters
+ //
+ ASSERT(CommandString != NULL);
+
+ //
+ // check for the command
+ //
+ for ( Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode(&mCommandList.Link)
+ ; !IsNull(&mCommandList.Link, &Node->Link)
+ ; Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode(&mCommandList.Link, &Node->Link)
+ ){
+ ASSERT(Node->CommandString != NULL);
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)CommandString,
+ Node->CommandString) == 0
+ ){
+ if (CanAffectLE != NULL) {
+ *CanAffectLE = Node->LastError;
+ }
+ if (RetVal != NULL) {
+ *RetVal = Node->CommandHandler(NULL, gST);
+ } else {
+ Node->CommandHandler(NULL, gST);
+ }
+ return (RETURN_SUCCESS);
+ }
+ }
+ return (RETURN_NOT_FOUND);
+}
+
+/**
+ Checks if a command string has been registered for CommandString and if so it
+ returns the MAN filename specified for that command.
+
+ If CommandString is NULL, then ASSERT().
+
+ @param[in] CommandString Pointer to the command name. This is the name
+ found on the command line in the shell.\
+
+ @retval NULL the commandString was not a registered command.
+ @return other the name of the MAN file.
+ @sa SHELL_GET_MAN_FILENAME
+**/
+CONST CHAR16*
+EFIAPI
+ShellCommandGetManFileNameHandler (
+ IN CONST CHAR16 *CommandString
+ )
+{
+ SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node;
+
+ //
+ // assert for NULL parameters
+ //
+ ASSERT(CommandString != NULL);
+
+ //
+ // check for the command
+ //
+ for ( Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode(&mCommandList.Link)
+ ; !IsNull(&mCommandList.Link, &Node->Link)
+ ; Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode(&mCommandList.Link, &Node->Link)
+ ){
+ ASSERT(Node->CommandString != NULL);
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)CommandString,
+ Node->CommandString) == 0
+ ){
+ return (Node->GetManFileName());
+ }
+ }
+ return (NULL);
+}
+
+/**
+ Get the list of all available shell internal commands. This is a linked list
+ (via LIST_ENTRY structure). enumerate through it using the BaseLib linked
+ list functions. do not modify the values.
+
+ @return a Linked list of all available shell commands.
+**/
+CONST COMMAND_LIST*
+EFIAPI
+ShellCommandGetCommandList (
+ )
+{
+ return ((COMMAND_LIST*)(&mCommandList));
+}
+
+/**
+ Registers aliases to be set as part of the initialization of the shell application.
+
+ If Command is NULL, then ASSERT().
+ If Alias is NULL, then ASSERT().
+
+ @param[in] Command Pointer to the Command
+ @param[in] Alias Pointer to Alias
+
+ @retval RETURN_SUCCESS The handlers were registered.
+ @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to
+ register the shell command.
+**/
+RETURN_STATUS
+EFIAPI
+ShellCommandRegisterAlias (
+ IN CONST CHAR16 *Command,
+ IN CONST CHAR16 *Alias
+ )
+{
+ ALIAS_LIST *Node;
+
+ //
+ // Asserts for NULL
+ //
+ ASSERT(Command != NULL);
+ ASSERT(Alias != NULL);
+
+ //
+ // allocate memory for new struct
+ //
+ Node = AllocatePool(sizeof(ALIAS_LIST));
+ ASSERT(Node != NULL);
+ Node->CommandString = AllocatePool(StrSize(Command));
+ Node->Alias = AllocatePool(StrSize(Alias));
+ ASSERT(Node->CommandString != NULL);
+ ASSERT(Node->Alias != NULL);
+
+ //
+ // populate the new struct
+ //
+ StrCpy(Node->CommandString, Command);
+ StrCpy(Node->Alias , Alias );
+
+ //
+ // add the new struct to the list
+ //
+ InsertTailList (&mAliasList.Link, &Node->Link);
+
+ return (RETURN_SUCCESS);
+}
+
+/**
+ Get the list of all shell alias commands. This is a linked list
+ (via LIST_ENTRY structure). enumerate through it using the BaseLib linked
+ list functions. do not modify the values.
+
+ @return a Linked list of all requested shell alias'.
+**/
+CONST ALIAS_LIST*
+EFIAPI
+ShellCommandGetInitAliasList (
+ VOID
+ )
+{
+ return (&mAliasList);
+}
+
+/**
+ Determine if a given alias is on the list of built in alias'
+
+ @param[in] Alias The alias to test for
+
+ @retval TRUE The alias is a built in alias
+ @retval FALSE The alias is not a built in alias
+**/
+BOOLEAN
+EFIAPI
+ShellCommandIsOnAliasList(
+ IN CONST CHAR16 *Alias
+ )
+{
+ ALIAS_LIST *Node;
+
+ //
+ // assert for NULL parameter
+ //
+ ASSERT(Alias != NULL);
+
+ //
+ // check for the Alias
+ //
+ for ( Node = (ALIAS_LIST *)GetFirstNode(&mAliasList.Link)
+ ; !IsNull(&mAliasList.Link, &Node->Link)
+ ; Node = (ALIAS_LIST *)GetNextNode(&mAliasList.Link, &Node->Link)
+ ){
+ ASSERT(Node->CommandString != NULL);
+ ASSERT(Node->Alias != NULL);
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)Alias,
+ Node->CommandString) == 0
+ ){
+ return (TRUE);
+ }
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)Alias,
+ Node->Alias) == 0
+ ){
+ return (TRUE);
+ }
+ }
+ return (FALSE);
+}
+
+/**
+ Function to determine current state of ECHO. Echo determins if lines from scripts
+ and ECHO commands are enabled.
+
+ @retval TRUE Echo is currently enabled
+ @retval FALSE Echo is currently disabled
+**/
+BOOLEAN
+EFIAPI
+ShellCommandGetEchoState(
+ VOID
+ )
+{
+ return (mEchoState);
+}
+
+/**
+ Function to set current state of ECHO. Echo determins if lines from scripts
+ and ECHO commands are enabled.
+
+ If State is TRUE, Echo will be enabled.
+ If State is FALSE, Echo will be disabled.
+**/
+VOID
+EFIAPI
+ShellCommandSetEchoState(
+ IN BOOLEAN State
+ )
+{
+ mEchoState = State;
+}
+
+/**
+ Indicate that the current shell or script should exit.
+
+ @param[in] ScriptOnly TRUE if only exiting a script, FALSE othrwise.
+**/
+VOID
+EFIAPI
+ShellCommandRegisterExit (
+ IN BOOLEAN ScriptOnly
+ )
+{
+ mExitRequested = (BOOLEAN)(!mExitRequested);
+ if (mExitRequested) {
+ mExitScript = ScriptOnly;
+ } else {
+ mExitScript = FALSE;
+ }
+}
+
+/**
+ Retrieve the Exit indicator.
+
+ @retval TRUE Exit was indicated.
+ @retval FALSE Exis was not indicated.
+**/
+BOOLEAN
+EFIAPI
+ShellCommandGetExit (
+ VOID
+ )
+{
+ return (mExitRequested);
+}
+
+/**
+ Retrieve the Exit script indicator.
+
+ If ShellCommandGetExit returns FALSE than the return from this is undefined.
+
+ @retval TRUE ScriptOnly was indicated.
+ @retval FALSE ScriptOnly was not indicated.
+**/
+BOOLEAN
+EFIAPI
+ShellCommandGetScriptExit (
+ VOID
+ )
+{
+ return (mExitScript);
+}
+
+/**
+ Function to cleanup all memory from a SCRIPT_FILE structure.
+
+ @param[in] Script The pointer to the structure to cleanup.
+**/
+VOID
+EFIAPI
+DeleteScriptFileStruct (
+ IN SCRIPT_FILE *Script
+ )
+{
+ UINT8 LoopVar;
+ ASSERT(Script != NULL);
+ ASSERT(Script->ScriptName != NULL);
+ for (LoopVar = 0 ; LoopVar < Script->Argc ; LoopVar++) {
+ FreePool(Script->Argv[LoopVar]);
+ }
+ if (Script->Argv != NULL) {
+ FreePool(Script->Argv);
+ }
+ Script->CurrentCommand = NULL;
+ while (!IsListEmpty (&Script->CommandList)) {
+ Script->CurrentCommand = (SCRIPT_COMMAND_LIST *)GetFirstNode(&Script->CommandList);
+ if (Script->CurrentCommand != NULL) {
+ RemoveEntryList(&Script->CurrentCommand->Link);
+ if (Script->CurrentCommand->Cl != NULL) {
+ FreePool(Script->CurrentCommand->Cl);
+ }
+ if (Script->CurrentCommand->Data != NULL) {
+ FreePool(Script->CurrentCommand->Data);
+ }
+ FreePool(Script->CurrentCommand);
+ }
+ }
+ FreePool(Script->ScriptName);
+ FreePool(Script);
+}
+
+/**
+ Function to return a pointer to the currently running script file object.
+
+ @retval NULL A script file is not currently running.
+ @return A pointer to the current script file object.
+**/
+SCRIPT_FILE*
+EFIAPI
+ShellCommandGetCurrentScriptFile (
+ VOID
+ )
+{
+ SCRIPT_FILE_LIST *List;
+ if (IsListEmpty (&mScriptList.Link)) {
+ return (NULL);
+ }
+ List = ((SCRIPT_FILE_LIST*)GetFirstNode(&mScriptList.Link));
+ return (List->Data);
+}
+
+/**
+ Function to set a new script as the currently running one.
+
+ This function will correctly stack and unstack nested scripts.
+
+ @param[in] Script Pointer to new script information structure. if NULL
+ will remove and de-allocate the top-most Script structure.
+
+ @return A pointer to the current running script file after this
+ change. NULL if removing the final script.
+**/
+SCRIPT_FILE*
+EFIAPI
+ShellCommandSetNewScript (
+ IN SCRIPT_FILE *Script OPTIONAL
+ )
+{
+ SCRIPT_FILE_LIST *Node;
+ if (Script == NULL) {
+ if (IsListEmpty (&mScriptList.Link)) {
+ ASSERT(FALSE);
+ return (NULL);
+ }
+ Node = (SCRIPT_FILE_LIST *)GetFirstNode(&mScriptList.Link);
+ RemoveEntryList(&Node->Link);
+ DeleteScriptFileStruct(Node->Data);
+ FreePool(Node);
+ } else {
+ Node = AllocateZeroPool(sizeof(SCRIPT_FILE_LIST));
+ Node->Data = Script;
+ InsertHeadList(&mScriptList.Link, &Node->Link);
+ }
+ return (ShellCommandGetCurrentScriptFile());
+}
+
+/**
+ Function to generate the next default mapping name.
+
+ If the return value is not NULL then it must be callee freed.
+
+ @param Type What kind of mapping name to make.
+
+ @retval NULL a memory allocation failed.
+ @return a new map name string
+**/
+CHAR16*
+EFIAPI
+ShellCommandCreateNewMappingName(
+ IN CONST SHELL_MAPPING_TYPE Type
+ )
+{
+ CHAR16 *String;
+ ASSERT(Type < MappingTypeMax);
+
+ String = NULL;
+
+ String = AllocateZeroPool(PcdGet8(PcdShellMapNameLength) * sizeof(String[0]));
+ UnicodeSPrint(
+ String,
+ PcdGet8(PcdShellMapNameLength) * sizeof(String[0]),
+ Type == MappingTypeFileSystem?L"FS%d:":L"BLK%d:",
+ Type == MappingTypeFileSystem?mFsMaxCount++:mBlkMaxCount++);
+
+ return (String);
+}
+
+/**
+ Function to add a map node to the list of map items and update the "path" environment variable (optionally).
+
+ If Path is TRUE (during initialization only), the path environment variable will also be updated to include
+ default paths on the new map name...
+
+ Path should be FALSE when this function is called from the protocol SetMap function.
+
+ @param[in] Name The human readable mapped name.
+ @param[in] DevicePath The Device Path for this map.
+ @param[in] Flags The Flags attribute for this map item.
+ @param[in] Path TRUE to update path, FALSE to skip this step (should only be TRUE during initialization).
+
+ @retval EFI_SUCCESS The addition was sucessful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_INVALID_PARAMETER A parameter was invalid.
+**/
+EFI_STATUS
+EFIAPI
+ShellCommandAddMapItemAndUpdatePath(
+ IN CONST CHAR16 *Name,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN CONST UINT64 Flags,
+ IN CONST BOOLEAN Path
+ )
+{
+ EFI_STATUS Status;
+ SHELL_MAP_LIST *MapListNode;
+ CONST CHAR16 *OriginalPath;
+ CHAR16 *NewPath;
+ UINTN NewPathSize;
+
+ NewPathSize = 0;
+ NewPath = NULL;
+ OriginalPath = NULL;
+ Status = EFI_SUCCESS;
+
+ MapListNode = AllocateZeroPool(sizeof(SHELL_MAP_LIST));
+ if (MapListNode == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ MapListNode->Flags = Flags;
+ MapListNode->MapName = AllocateZeroPool(StrSize(Name));
+ MapListNode->DevicePath = DuplicateDevicePath(DevicePath);
+ if ((MapListNode->MapName == NULL) || (MapListNode->DevicePath == NULL)){
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ StrCpy(MapListNode->MapName, Name);
+ InsertTailList(&gShellMapList.Link, &MapListNode->Link);
+ }
+ }
+ if (EFI_ERROR(Status)) {
+ if (MapListNode != NULL) {
+ if (MapListNode->DevicePath != NULL) {
+ FreePool(MapListNode->DevicePath);
+ }
+ if (MapListNode->MapName != NULL) {
+ FreePool(MapListNode->MapName);
+ }
+ FreePool(MapListNode);
+ }
+ } else if (Path) {
+ //
+ // Since there was no error and Path was TRUE
+ // Now add the correct path for that mapping
+ //
+ OriginalPath = gEfiShellProtocol->GetEnv(L"path");
+ ASSERT((NewPath == NULL && NewPathSize == 0) || (NewPath != NULL));
+ if (OriginalPath != NULL) {
+ StrnCatGrow(&NewPath, &NewPathSize, OriginalPath, 0);
+ } else {
+ StrnCatGrow(&NewPath, &NewPathSize, L".\\", 0);
+ }
+ StrnCatGrow(&NewPath, &NewPathSize, L";", 0);
+ StrnCatGrow(&NewPath, &NewPathSize, Name, 0);
+ StrnCatGrow(&NewPath, &NewPathSize, L"\\efi\\tools\\;", 0);
+ StrnCatGrow(&NewPath, &NewPathSize, Name, 0);
+ StrnCatGrow(&NewPath, &NewPathSize, L"\\efi\\boot\\;", 0);
+ StrnCatGrow(&NewPath, &NewPathSize, Name, 0);
+ StrnCatGrow(&NewPath, &NewPathSize, L"\\", 0);
+
+ Status = gEfiShellProtocol->SetEnv(L"path", NewPath, TRUE);
+ ASSERT_EFI_ERROR(Status);
+ FreePool(NewPath);
+ }
+ return (Status);
+}
+
+/**
+ Creates the default map names for each device path in the system with
+ a protocol depending on the Type.
+
+ Creates the consistent map names for each device path in the system with
+ a protocol depending on the Type.
+
+ Note: This will reset all mappings in the system("map -r").
+
+ Also sets up the default path environment variable if Type is FileSystem.
+
+ @retval EFI_SUCCESS All map names were created sucessfully.
+ @retval EFI_NOT_FOUND No protocols were found in the system.
+ @return Error returned from gBS->LocateHandle().
+
+ @sa LocateHandle
+**/
+EFI_STATUS
+EFIAPI
+ShellCommandCreateInitialMappingsAndPaths(
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleList;
+ UINTN Count;
+ EFI_DEVICE_PATH_PROTOCOL **DevicePathList;
+ CHAR16 *NewDefaultName;
+ CHAR16 *NewConsistName;
+ EFI_DEVICE_PATH_PROTOCOL **ConsistMappingTable;
+ SHELL_MAP_LIST *MapListNode;
+
+ HandleList = NULL;
+
+ //
+ // Reset the static members back to zero
+ //
+ mFsMaxCount = 0;
+ mBlkMaxCount = 0;
+
+ gEfiShellProtocol->SetEnv(L"path", L"", TRUE);
+
+ //
+ // First empty out the existing list.
+ //
+ if (!IsListEmpty(&gShellMapList.Link)) {
+ for ( MapListNode = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link)
+ ; !IsListEmpty(&gShellMapList.Link)
+ ; MapListNode = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link)
+ ){
+ RemoveEntryList(&MapListNode->Link);
+ FreePool(MapListNode);
+ } // for loop
+ }
+
+ //
+ // Find each handle with Simple File System
+ //
+ HandleList = GetHandleListByPotocol(&gEfiSimpleFileSystemProtocolGuid);
+ if (HandleList != NULL) {
+ //
+ // Do a count of the handles
+ //
+ for (Count = 0 ; HandleList[Count] != NULL ; Count++);
+
+ //
+ // Get all Device Paths
+ //
+ DevicePathList = AllocatePool(sizeof(EFI_DEVICE_PATH_PROTOCOL*) * Count);
+ ASSERT(DevicePathList != NULL);
+
+ for (Count = 0 ; HandleList[Count] != NULL ; Count++) {
+ DevicePathList[Count] = DevicePathFromHandle(HandleList[Count]);
+ }
+
+ //
+ // Sort all DevicePaths
+ //
+ PerformQuickSort(DevicePathList, Count, sizeof(EFI_DEVICE_PATH_PROTOCOL*), DevicePathCompare);
+
+ ShellCommandConsistMappingInitialize(&ConsistMappingTable);
+ //
+ // Assign new Mappings to all...
+ //
+ for (Count = 0 ; HandleList[Count] != NULL ; Count++) {
+ //
+ // Get default name first
+ //
+ NewDefaultName = ShellCommandCreateNewMappingName(MappingTypeFileSystem);
+ ASSERT(NewDefaultName != NULL);
+ Status = ShellCommandAddMapItemAndUpdatePath(NewDefaultName, DevicePathList[Count], 0, TRUE);
+ ASSERT_EFI_ERROR(Status);
+ FreePool(NewDefaultName);
+
+ //
+ // Now do consistent name
+ //
+ NewConsistName = ShellCommandConsistMappingGenMappingName(DevicePathList[Count], ConsistMappingTable);
+ if (NewConsistName != NULL) {
+ Status = ShellCommandAddMapItemAndUpdatePath(NewConsistName, DevicePathList[Count], 0, FALSE);
+ ASSERT_EFI_ERROR(Status);
+ FreePool(NewConsistName);
+ }
+ }
+
+ ShellCommandConsistMappingUnInitialize(ConsistMappingTable);
+
+ SHELL_FREE_NON_NULL(HandleList);
+ SHELL_FREE_NON_NULL(DevicePathList);
+
+ HandleList = NULL;
+ } else {
+ Count = (UINTN)-1;
+ }
+
+ //
+ // Find each handle with Block Io
+ //
+ HandleList = GetHandleListByPotocol(&gEfiBlockIoProtocolGuid);
+ if (HandleList != NULL) {
+ for (Count = 0 ; HandleList[Count] != NULL ; Count++);
+
+ //
+ // Get all Device Paths
+ //
+ DevicePathList = AllocatePool(sizeof(EFI_DEVICE_PATH_PROTOCOL*) * Count);
+ ASSERT(DevicePathList != NULL);
+
+ for (Count = 0 ; HandleList[Count] != NULL ; Count++) {
+ DevicePathList[Count] = DevicePathFromHandle(HandleList[Count]);
+ }
+
+ //
+ // Sort all DevicePaths
+ //
+ PerformQuickSort(DevicePathList, Count, sizeof(EFI_DEVICE_PATH_PROTOCOL*), DevicePathCompare);
+
+ //
+ // Assign new Mappings to all...
+ //
+ for (Count = 0 ; HandleList[Count] != NULL ; Count++) {
+ //
+ // Get default name first
+ //
+ NewDefaultName = ShellCommandCreateNewMappingName(MappingTypeBlockIo);
+ ASSERT(NewDefaultName != NULL);
+ Status = ShellCommandAddMapItemAndUpdatePath(NewDefaultName, DevicePathList[Count], 0, FALSE);
+ ASSERT_EFI_ERROR(Status);
+ FreePool(NewDefaultName);
+ }
+
+ SHELL_FREE_NON_NULL(HandleList);
+ SHELL_FREE_NON_NULL(DevicePathList);
+ } else if (Count == (UINTN)-1) {
+ return (EFI_NOT_FOUND);
+ }
+
+ return (EFI_SUCCESS);
+}
+
+CHAR16*
+EFIAPI
+ShellCommandCleanPath (
+ IN OUT CHAR16 *Path
+ )
+{
+ CHAR16 *Path2;
+
+ for (Path2 = Path ; Path2 != NULL && *Path2 != CHAR_NULL ; Path2++) {
+ if (*Path2 == L'/') {
+ *Path2 = L'\\';
+ }
+ }
+
+ return (Path);
+}
+
+/**
+ Converts a SHELL_FILE_HANDLE to an EFI_FILE_PROTOCOL*.
+
+ @param[in] Handle The SHELL_FILE_HANDLE to convert.
+
+ @return a EFI_FILE_PROTOCOL* representing the same file.
+**/
+EFI_FILE_PROTOCOL*
+EFIAPI
+ConvertShellHandleToEfiFileProtocol(
+ IN CONST SHELL_FILE_HANDLE Handle
+ )
+{
+ return ((EFI_FILE_PROTOCOL*)(Handle));
+}
+
+/**
+ Converts a EFI_FILE_PROTOCOL* to an SHELL_FILE_HANDLE.
+
+ @param[in] Handle The pointer to EFI_FILE_PROTOCOL to convert.
+ @param[in] Path The path to the file for verification.
+
+ @return a SHELL_FILE_HANDLE representing the same file.
+**/
+SHELL_FILE_HANDLE
+EFIAPI
+ConvertEfiFileProtocolToShellHandle(
+ IN CONST EFI_FILE_PROTOCOL *Handle,
+ IN CONST CHAR16 *Path
+ )
+{
+ SHELL_COMMAND_FILE_HANDLE *Buffer;
+ BUFFER_LIST *NewNode;
+
+ if (Path != NULL) {
+ Buffer = AllocateZeroPool(sizeof(SHELL_COMMAND_FILE_HANDLE));
+ ASSERT(Buffer != NULL);
+ NewNode = AllocatePool(sizeof(BUFFER_LIST));
+ ASSERT(NewNode != NULL);
+ Buffer->FileHandle = (EFI_FILE_PROTOCOL*)Handle;
+ Buffer->Path = StrnCatGrow(&Buffer->Path, NULL, Path, 0);
+ NewNode->Buffer = Buffer;
+
+ InsertHeadList(&mFileHandleList.Link, &NewNode->Link);
+ }
+ return ((SHELL_FILE_HANDLE)(Handle));
+}
+
+/**
+ Find the path that was logged with the specified SHELL_FILE_HANDLE.
+
+ @param[in] Handle The SHELL_FILE_HANDLE to query on.
+
+ @return A pointer to the path for the file.
+**/
+CONST CHAR16*
+EFIAPI
+ShellFileHandleGetPath(
+ IN CONST SHELL_FILE_HANDLE Handle
+ )
+{
+ BUFFER_LIST *Node;
+
+ for (Node = (BUFFER_LIST*)GetFirstNode(&mFileHandleList.Link)
+ ; !IsNull(&mFileHandleList.Link, &Node->Link)
+ ; Node = (BUFFER_LIST*)GetNextNode(&mFileHandleList.Link, &Node->Link)
+ ){
+ if ((Node->Buffer) && (((SHELL_COMMAND_FILE_HANDLE *)Node->Buffer)->FileHandle == Handle)){
+ return (((SHELL_COMMAND_FILE_HANDLE *)Node->Buffer)->Path);
+ }
+ }
+ return (NULL);
+}
+
+/**
+ Remove a SHELL_FILE_HANDLE frmo the list of SHELL_FILE_HANDLES.
+
+ @param[in] Handle The SHELL_FILE_HANDLE to remove.
+
+ @retval TRUE The item was removed.
+ @retval FALSE The item was not found.
+**/
+BOOLEAN
+EFIAPI
+ShellFileHandleRemove(
+ IN CONST SHELL_FILE_HANDLE Handle
+ )
+{
+ BUFFER_LIST *Node;
+
+ for (Node = (BUFFER_LIST*)GetFirstNode(&mFileHandleList.Link)
+ ; !IsNull(&mFileHandleList.Link, &Node->Link)
+ ; Node = (BUFFER_LIST*)GetNextNode(&mFileHandleList.Link, &Node->Link)
+ ){
+ if ((Node->Buffer) && (((SHELL_COMMAND_FILE_HANDLE *)Node->Buffer)->FileHandle == Handle)){
+ SHELL_FREE_NON_NULL(((SHELL_COMMAND_FILE_HANDLE *)Node->Buffer)->Path);
+ RemoveEntryList(&Node->Link);
+ return (TRUE);
+ }
+ }
+ return (FALSE);
+}
+
+/**
+ Function to determine if a SHELL_FILE_HANDLE is at the end of the file.
+
+ This will NOT work on directories.
+
+ If Handle is NULL, then ASSERT.
+
+ @param[in] Handle the file handle
+
+ @retval TRUE the position is at the end of the file
+ @retval FALSE the position is not at the end of the file
+**/
+BOOLEAN
+EFIAPI
+ShellFileHandleEof(
+ IN SHELL_FILE_HANDLE Handle
+ )
+{
+ EFI_FILE_INFO *Info;
+ UINT64 Pos;
+ BOOLEAN RetVal;
+
+ //
+ // ASSERT if Handle is NULL
+ //
+ ASSERT(Handle != NULL);
+
+ gEfiShellProtocol->GetFilePosition(Handle, &Pos);
+ Info = gEfiShellProtocol->GetFileInfo (Handle);
+ ASSERT(Info != NULL);
+ gEfiShellProtocol->SetFilePosition(Handle, Pos);
+
+ if (Info == NULL) {
+ return (FALSE);
+ }
+
+ if (Pos == Info->FileSize) {
+ RetVal = TRUE;
+ } else {
+ RetVal = FALSE;
+ }
+
+ FreePool (Info);
+
+ return (RetVal);
+}
+
+/**
+ Function to read a single line from a SHELL_FILE_HANDLE. The \n is not included in the returned
+ buffer. The returned buffer must be callee freed.
+
+ If the position upon start is 0, then the Ascii Boolean will be set. This should be
+ maintained and not changed for all operations with the same file.
+
+ @param[in] Handle SHELL_FILE_HANDLE to read from.
+ @param[in,out] Ascii Boolean value for indicating whether the file is
+ Ascii (TRUE) or UCS2 (FALSE).
+
+ @return The line of text from the file.
+
+ @sa ShellFileHandleReadLine
+**/
+CHAR16*
+EFIAPI
+ShellFileHandleReturnLine(
+ IN SHELL_FILE_HANDLE Handle,
+ IN OUT BOOLEAN *Ascii
+ )
+{
+ CHAR16 *RetVal;
+ UINTN Size;
+ EFI_STATUS Status;
+
+ Size = 0;
+ RetVal = NULL;
+
+ Status = ShellFileHandleReadLine(Handle, RetVal, &Size, FALSE, Ascii);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ RetVal = AllocatePool(Size);
+ Status = ShellFileHandleReadLine(Handle, RetVal, &Size, FALSE, Ascii);
+ }
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status) && (RetVal != NULL)) {
+ FreePool(RetVal);
+ RetVal = NULL;
+ }
+ return (RetVal);
+}
+
+/**
+ Function to read a single line (up to but not including the \n) from a SHELL_FILE_HANDLE.
+
+ If the position upon start is 0, then the Ascii Boolean will be set. This should be
+ maintained and not changed for all operations with the same file.
+
+ @param[in] Handle SHELL_FILE_HANDLE to read from.
+ @param[in,out] Buffer The pointer to buffer to read into.
+ @param[in,out] Size The pointer to number of bytes in Buffer.
+ @param[in] Truncate If the buffer is large enough, this has no effect.
+ If the buffer is is too small and Truncate is TRUE,
+ the line will be truncated.
+ If the buffer is is too small and Truncate is FALSE,
+ then no read will occur.
+
+ @param[in,out] Ascii Boolean value for indicating whether the file is
+ Ascii (TRUE) or UCS2 (FALSE).
+
+ @retval EFI_SUCCESS The operation was successful. The line is stored in
+ Buffer.
+ @retval EFI_INVALID_PARAMETER Handle was NULL.
+ @retval EFI_INVALID_PARAMETER Size was NULL.
+ @retval EFI_BUFFER_TOO_SMALL Size was not large enough to store the line.
+ Size was updated to the minimum space required.
+ @sa ShellFileHandleRead
+**/
+EFI_STATUS
+EFIAPI
+ShellFileHandleReadLine(
+ IN SHELL_FILE_HANDLE Handle,
+ IN OUT CHAR16 *Buffer,
+ IN OUT UINTN *Size,
+ IN BOOLEAN Truncate,
+ IN OUT BOOLEAN *Ascii
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 CharBuffer;
+ UINTN CharSize;
+ UINTN CountSoFar;
+ UINT64 OriginalFilePosition;
+
+
+ if (Handle == NULL
+ ||Size == NULL
+ ){
+ return (EFI_INVALID_PARAMETER);
+ }
+ if (Buffer == NULL) {
+ ASSERT(*Size == 0);
+ } else {
+ *Buffer = CHAR_NULL;
+ }
+ gEfiShellProtocol->GetFilePosition(Handle, &OriginalFilePosition);
+ if (OriginalFilePosition == 0) {
+ CharSize = sizeof(CHAR16);
+ Status = gEfiShellProtocol->ReadFile(Handle, &CharSize, &CharBuffer);
+ ASSERT_EFI_ERROR(Status);
+ if (CharBuffer == UnicodeFileTag) {
+ *Ascii = FALSE;
+ } else {
+ *Ascii = TRUE;
+ gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);
+ }
+ }
+
+ for (CountSoFar = 0;;CountSoFar++){
+ CharBuffer = 0;
+ if (*Ascii) {
+ CharSize = sizeof(CHAR8);
+ } else {
+ CharSize = sizeof(CHAR16);
+ }
+ Status = gEfiShellProtocol->ReadFile(Handle, &CharSize, &CharBuffer);
+ if ( EFI_ERROR(Status)
+ || CharSize == 0
+ || (CharBuffer == L'\n' && !(*Ascii))
+ || (CharBuffer == '\n' && *Ascii)
+ ){
+ break;
+ }
+ //
+ // if we have space save it...
+ //
+ if ((CountSoFar+1)*sizeof(CHAR16) < *Size){
+ ASSERT(Buffer != NULL);
+ ((CHAR16*)Buffer)[CountSoFar] = CharBuffer;
+ ((CHAR16*)Buffer)[CountSoFar+1] = CHAR_NULL;
+ }
+ }
+
+ //
+ // if we ran out of space tell when...
+ //
+ if ((CountSoFar+1)*sizeof(CHAR16) > *Size){
+ *Size = (CountSoFar+1)*sizeof(CHAR16);
+ if (!Truncate) {
+ gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);
+ } else {
+ DEBUG((DEBUG_WARN, "The line was truncated in ShellFileHandleReadLine"));
+ }
+ return (EFI_BUFFER_TOO_SMALL);
+ }
+ while(Buffer[StrLen(Buffer)-1] == L'\r') {
+ Buffer[StrLen(Buffer)-1] = CHAR_NULL;
+ }
+
+ return (Status);
+}
+/**
+ Frees any BUFFER_LIST defined type.
+**/
+VOID
+EFIAPI
+FreeBufferList (
+ IN BUFFER_LIST *List
+ )
+{
+ BUFFER_LIST *BufferListEntry;
+
+ if (List == NULL){
+ return;
+ }
+ //
+ // enumerate through the buffer list and free all memory
+ //
+ for ( BufferListEntry = ( BUFFER_LIST *)GetFirstNode(&List->Link)
+ ; !IsListEmpty (&List->Link)
+ ; BufferListEntry = (BUFFER_LIST *)GetFirstNode(&List->Link)
+ ){
+ RemoveEntryList(&BufferListEntry->Link);
+ ASSERT(BufferListEntry->Buffer != NULL);
+ if (BufferListEntry->Buffer != NULL) {
+ FreePool(BufferListEntry->Buffer);
+ }
+ FreePool(BufferListEntry);
+ }
+}
+
+/**
+ Chops off last directory or file entry in a path leaving the trailing slash
+
+ @param[in,out] Path
+
+ @retval FALSE No directory was found to chop off.
+ @retval TRUE A directory was chopped off.
+**/
+BOOLEAN
+EFIAPI
+ChopLastSlash(
+ IN OUT CHAR16 *PathToReturn
+ )
+{
+ CHAR16 *Walker;
+ CHAR16 *LastSlash = NULL;
+ //
+ // get directory name from path... ('chop' off extra)
+ //
+ for ( Walker = PathToReturn
+ ; Walker != NULL && *Walker != CHAR_NULL
+ ; Walker++
+ ){
+ if (*Walker == L'\\' && *(Walker + 1) != CHAR_NULL) {
+ LastSlash = Walker+1;
+ }
+ }
+ if (LastSlash != NULL) {
+ *LastSlash = CHAR_NULL;
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
diff --git a/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.h b/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.h
new file mode 100644
index 0000000000..431eb53f9d
--- /dev/null
+++ b/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.h
@@ -0,0 +1,79 @@
+/** @file
+ Provides interface to shell internal functions for shell commands.
+
+ Copyright (c) 2006 - 2010, Intel Corporation.All rights reserved. <BR>
+ 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 _UEFI_COMMAND_LIB_INTERNAL_HEADER_
+#define _UEFI_COMMAND_LIB_INTERNAL_HEADER_
+
+#include <Uefi.h>
+#include <ShellBase.h>
+
+#include <Guid/FileInfo.h>
+
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/EfiShellInterface.h>
+#include <Protocol/EfiShellEnvironment2.h>
+#include <Protocol/EfiShell.h>
+#include <Protocol/EfiShellParameters.h>
+#include <Protocol/UnicodeCollation.h>
+#include <Protocol/BlockIo.h>
+
+#include <Library/DevicePathLib.h>
+#include <Library/SortLib.h>
+#include <Library/HandleParsingLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <library/ShellCommandLib.h>
+#include <Library/PrintLib.h>
+#include <Library/ShellLib.h>
+#include <Library/HiiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+typedef struct{
+ LIST_ENTRY Link;
+ CHAR16 *CommandString;
+ SHELL_GET_MAN_FILENAME GetManFileName;
+ SHELL_RUN_COMMAND CommandHandler;
+ BOOLEAN LastError;
+ EFI_HANDLE HiiHandle;
+ EFI_STRING_ID ManFormatHelp;
+} SHELL_COMMAND_INTERNAL_LIST_ENTRY;
+
+typedef struct {
+ LIST_ENTRY Link;
+ SCRIPT_FILE *Data;
+} SCRIPT_FILE_LIST;
+
+/**
+ Function to cleanup all memory from a SCRIPT_FILE structure.
+
+ @param[in] Script The pointer to the structure to cleanup.
+**/
+VOID
+EFIAPI
+DeleteScriptFileStruct (
+ IN SCRIPT_FILE *Script
+ );
+
+typedef struct {
+ EFI_FILE_PROTOCOL *FileHandle;
+ CHAR16 *Path;
+} SHELL_COMMAND_FILE_HANDLE;
+
+
+#endif //_UEFI_COMMAND_LIB_INTERNAL_HEADER_
+
diff --git a/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf b/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
new file mode 100644
index 0000000000..3c3573ffc5
--- /dev/null
+++ b/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
@@ -0,0 +1,61 @@
+## @file
+# Provides interface to shell internal functions for shell commands.
+#
+# Copyright (c) 2006 - 2010, Intel Corporation.All rights reserved. <BR>
+#
+# 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 = UefiShellCommandLib
+ FILE_GUID = 5C12F31F-EBAC-466e-A400-FCA8C9EA3A05
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ShellCommandLib|UEFI_APPLICATION UEFI_DRIVER
+ CONSTRUCTOR = ShellCommandLibConstructor
+ DESTRUCTOR = ShellCommandLibDestructor
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ UefiShellCommandLib.c
+ UefiShellCommandLib.h
+ ConsistMapping.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ PrintLib
+ UefiBootServicesTableLib
+ ShellLib
+ HiiLib
+
+[Protocols]
+ gEfiUnicodeCollation2ProtocolGuid # ALWAYS_CONSUMED
+ gEfiShellProtocolGuid # ALWAYS_CONSUMED
+ gEfiShellParametersProtocolGuid # ALWAYS_CONSUMED
+ gEfiDevicePathToTextProtocolGuid # ALWAYS_CONSUMED
+
+[Guids]
+
+
+[Pcd.common]
+ gEfiShellPkgTokenSpaceGuid.PcdShellSupportLevel ## ALWAYS_CONSUMED
+ gEfiShellPkgTokenSpaceGuid.PcdShellMapNameLength ## ALWAYS_CONSUMED
diff --git a/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.uni b/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.uni
new file mode 100644
index 0000000000..4b65ec7dc3
--- /dev/null
+++ b/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.uni
Binary files differ
diff --git a/ShellPkg/Library/UefiShellDriver1CommandsLib/Connect.c b/ShellPkg/Library/UefiShellDriver1CommandsLib/Connect.c
new file mode 100644
index 0000000000..55bdf21efe
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDriver1CommandsLib/Connect.c
@@ -0,0 +1,273 @@
+/** @file
+ Main file for connect shell Driver1 function.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiShellDriver1CommandsLib.h"
+#include <Guid/GlobalVariable.h>
+#include <Guid/ConsoleInDevice.h>
+#include <Guid/ConsoleOutDevice.h>
+
+EFI_STATUS
+EFIAPI
+ConnectControllers (
+ IN CONST EFI_HANDLE ControllerHandle,
+ IN CONST EFI_HANDLE DriverHandle,
+ IN CONST BOOLEAN Recursive,
+ IN CONST BOOLEAN Output
+ ){
+ EFI_STATUS Status;
+ EFI_HANDLE *ControllerHandleList;
+ EFI_HANDLE *DriverHandleList;
+ EFI_HANDLE *HandleWalker;
+
+ ControllerHandleList = NULL;
+ Status = EFI_NOT_FOUND;
+
+ //
+ // If we have a single handle to connect make that a 'list'
+ //
+ if (DriverHandle == NULL) {
+ DriverHandleList = NULL;
+ } else {
+ DriverHandleList = AllocatePool(2*sizeof(EFI_HANDLE));
+ DriverHandleList[0] = DriverHandle;
+ DriverHandleList[1] = NULL;
+ }
+
+ //
+ // do we connect all controllers (with a loop) or a single one...
+ // This is where we call the gBS->ConnectController function.
+ //
+ if (ControllerHandle == NULL) {
+ ControllerHandleList = GetHandleListByPotocol(&gEfiDevicePathProtocolGuid);
+ for (HandleWalker = ControllerHandleList
+ ; HandleWalker != NULL && *HandleWalker != NULL
+ ; HandleWalker++
+ ){
+ Status = gBS->ConnectController(*HandleWalker, DriverHandleList, NULL, Recursive);
+ if (Output) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_CON_RESULT), gShellDriver1HiiHandle, *HandleWalker, Status);
+ }
+ }
+ } else {
+ Status = gBS->ConnectController(ControllerHandle, DriverHandleList, NULL, Recursive);
+ ASSERT(Output == FALSE);
+ }
+
+ //
+ // Free any memory we allocated.
+ //
+ if (ControllerHandleList != NULL) {
+ FreePool(ControllerHandleList);
+ }
+ if (DriverHandleList != NULL) {
+ FreePool(DriverHandleList);
+ }
+ return (Status);
+}
+
+EFI_STATUS
+EFIAPI
+ConnectFromDevPaths (
+ IN CONST CHAR16 *Key
+ ){
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+ EFI_DEVICE_PATH_PROTOCOL *DevPathWalker;
+ UINTN Length;
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+
+ DevPath = NULL;
+ Length = 0;
+
+ //
+ // Get the DevicePath buffer from the variable...
+ //
+ Status = gRT->GetVariable((CHAR16*)Key, (EFI_GUID*)&gEfiGlobalVariableGuid, NULL, &Length, DevPath);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ DevPath = AllocatePool(Length);
+ Status = gRT->GetVariable((CHAR16*)Key, (EFI_GUID*)&gEfiGlobalVariableGuid, NULL, &Length, DevPath);
+ }
+
+ //
+ // walk the list of devices and connect them
+ //
+ for (DevPathWalker = DevPath
+ ; DevPathWalker < (DevPath + Length) && !EFI_ERROR(Status) && DevPath != NULL
+ ; DevPathWalker += GetDevicePathSize(DevPathWalker)
+ ){
+ //
+ // get the correct handle from a given device path
+ //
+ if (StrCmp(Key, L"ConInDev") == 0) {
+ Status = gBS->LocateDevicePath((EFI_GUID*)&gEfiConsoleInDeviceGuid, &DevPathWalker, &Handle);
+ } else if (StrCmp(Key, L"ConOutDev") == 0) {
+ Status = gBS->LocateDevicePath((EFI_GUID*)&gEfiConsoleOutDeviceGuid, &DevPathWalker, &Handle);
+ } else {
+ Handle = NULL;
+ Status = EFI_INVALID_PARAMETER;
+ ASSERT(FALSE);
+ }
+ if (!EFI_ERROR(Status)) {
+ Status = ConnectControllers(Handle, NULL, FALSE, FALSE);
+ }
+ }
+
+ if (DevPath != NULL) {
+ FreePool(DevPath);
+ }
+ return (Status);
+}
+
+EFI_STATUS
+EFIAPI
+ConvertAndConnectControllers (
+ IN CONST CHAR16 *StringHandle1,
+ IN CONST CHAR16 *StringHandle2 OPTIONAL,
+ IN CONST BOOLEAN Recursive,
+ IN CONST BOOLEAN Output
+ ){
+ EFI_HANDLE Handle1;
+ EFI_HANDLE Handle2;
+
+ //
+ // Convert the command line parameters to HANDLES. They must be in HEX according to spec.
+ //
+ if (StringHandle1 != NULL) {
+ Handle1 = (EFI_HANDLE)StrHexToUintn(StringHandle1);
+ } else {
+ Handle1 = NULL;
+ }
+ if (StringHandle2 != NULL) {
+ Handle2 = (EFI_HANDLE)StrHexToUintn(StringHandle2);
+ } else {
+ Handle2 = NULL;
+ }
+
+ //
+ // if only one is NULL verify it's the proper one...
+ //
+ if ( (Handle1 == NULL && Handle2 != NULL)
+ || (Handle1 != NULL && Handle2 == NULL)
+ ){
+ //
+ // Figure out which one should be NULL and move the handle to the right place.
+ // If Handle1 is NULL then test Handle2 and vise versa.
+ // The one that DOES has driver binding must be Handle2
+ //
+ if (Handle1 == NULL) {
+ if (EFI_ERROR(gBS->OpenProtocol(Handle2, &gEfiDriverBindingProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {
+ // swap
+ Handle1 = Handle2;
+ Handle2 = NULL;
+ } else {
+ // We're all good...
+ }
+ } else {
+ if (EFI_ERROR(gBS->OpenProtocol(Handle1, &gEfiDriverBindingProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {
+ // We're all good...
+ } else {
+ // swap
+ Handle2 = Handle1;
+ Handle1 = NULL;
+ }
+ }
+ }
+
+ return (ConnectControllers(Handle1, Handle2, Recursive, Output));
+}
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-c", TypeFlag},
+ {L"-r", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+SHELL_STATUS
+EFIAPI
+ShellCommandRunConnect (
+ VOID *RESERVED
+ ) {
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+
+ ShellStatus = SHELL_SUCCESS;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if EFI_ERROR(Status) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // if more than 2 'value' parameters (plus the name one) or either -r or -c with any value parameters we have too many parameters
+ //
+ if ((ShellCommandLineGetCount() > 3)
+ ||((ShellCommandLineGetFlag(Package, L"-r") != FALSE || ShellCommandLineGetFlag(Package, L"-c") != FALSE) && ShellCommandLineGetCount()!=0)
+ ){
+ //
+ // error for too many parameters
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetFlag(Package, L"-c") != FALSE) {
+ //
+ // do the conin and conout from EFI variables
+ // if the first fails dont 'loose' the error
+ //
+ Status = ConnectFromDevPaths(L"ConInDev");
+ if (EFI_ERROR(Status)) {
+ ConnectFromDevPaths(L"ConOutDev");
+ } else {
+ Status = ConnectFromDevPaths(L"ConOutDev");
+ }
+ ShellStatus = Status & (~MAX_BIT);
+ } else {
+ //
+ // 0, 1, or 2 specific handles and possibly recursive
+ //
+ if (ShellCommandLineGetRawValue(Package, 1) != NULL && CommandLibGetHandleValue(StrHexToUintn(ShellCommandLineGetRawValue(Package, 1))) == NULL){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, ShellCommandLineGetRawValue(Package, 1));
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetRawValue(Package, 2) != NULL && CommandLibGetHandleValue(StrHexToUintn(ShellCommandLineGetRawValue(Package, 2))) == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, ShellCommandLineGetRawValue(Package, 2));
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Status = ConvertAndConnectControllers(ShellCommandLineGetRawValue(Package, 1), ShellCommandLineGetRawValue(Package, 2), ShellCommandLineGetFlag(Package, L"-r"), (BOOLEAN)(ShellCommandLineGetCount()!=0));
+ ShellStatus = Status & (~MAX_BIT);
+ }
+ }
+
+ ShellCommandLineFreeVarList (Package);
+ }
+ return (ShellStatus);
+}
+
diff --git a/ShellPkg/Library/UefiShellDriver1CommandsLib/Devices.c b/ShellPkg/Library/UefiShellDriver1CommandsLib/Devices.c
new file mode 100644
index 0000000000..485458f25c
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDriver1CommandsLib/Devices.c
@@ -0,0 +1,164 @@
+/** @file
+ Main file for devices shell Driver1 function.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiShellDriver1CommandsLib.h"
+
+EFI_STATUS
+EFIAPI
+GetDeviceHandleInfo (
+ IN EFI_HANDLE TheHandle,
+ IN CHAR16 *Type,
+ IN BOOLEAN *Cfg,
+ IN BOOLEAN *Diag,
+ IN UINT8 *Parents,
+ IN UINT8 *Devices,
+ IN UINT8 *Children,
+ OUT CHAR16 **Name,
+ IN CONST CHAR8 *Language
+ ){
+ *Name = NULL;
+
+ gEfiShellProtocol->GetDeviceName(TheHandle, EFI_DEVICE_NAME_USE_COMPONENT_NAME|EFI_DEVICE_NAME_USE_DEVICE_PATH, (CHAR8*)Language, Name);
+
+
+
+
+
+
+
+
+
+
+
+
+
+ return (EFI_SUCCESS);
+}
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-l", TypeValue},
+ {NULL, TypeMax}
+ };
+
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDevices (
+ VOID *RESERVED
+ ) {
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ CHAR8 *Language;
+ EFI_HANDLE *HandleList;
+ EFI_HANDLE *HandleListWalker;
+ CHAR16 Type;
+ BOOLEAN Cfg;
+ BOOLEAN Diag;
+ UINT8 Parents;
+ UINT8 Devices;
+ UINT8 Children;
+ CHAR16 *Name;
+
+ ShellStatus = SHELL_SUCCESS;
+ Language = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if EFI_ERROR(Status) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // if more than 0 'value' parameters we have too many parameters
+ //
+ if (ShellCommandLineGetRawValue(Package, 1) != NULL){
+ //
+ // error for too many parameters
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // get the language if necessary
+ //
+ if (ShellCommandLineGetFlag(Package, L"-l") != FALSE) {
+ Language = AllocateZeroPool(StrSize(ShellCommandLineGetValue(Package, L"-l")));
+ AsciiSPrint(Language, StrSize(ShellCommandLineGetValue(Package, L"-l")), "%S", ShellCommandLineGetValue(Package, L"-l"));
+ }
+
+ //
+ // Print Header
+ //
+ ShellPrintHiiEx(-1, -1, Language, STRING_TOKEN (STR_DEVICES_HEADER_LINES), gShellDriver1HiiHandle);
+
+ //
+ // loop through each handle
+ //
+ HandleList = GetHandleListByPotocol(NULL);
+ ASSERT(HandleList != NULL);
+ for (HandleListWalker = HandleList
+ ; HandleListWalker != NULL && *HandleListWalker != NULL && !EFI_ERROR(Status)
+ ; HandleListWalker++
+ ){
+ //
+ // get all the info on each handle
+ //
+ Status = GetDeviceHandleInfo(*HandleListWalker, &Type, &Cfg, &Diag, &Parents, &Devices, &Children, &Name, Language);
+ if (Parents != 0 || Devices != 0 || Children != 0) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ Language,
+ STRING_TOKEN (STR_DEVICES_ITEM_LINE),
+ gShellDriver1HiiHandle,
+ *HandleListWalker,
+ Type,
+ Cfg!=FALSE?L'X':L'-',
+ Diag!=FALSE?L'X':L'-',
+ Parents,
+ Devices,
+ Children,
+ Name);
+ }
+ if (Name != NULL) {
+ FreePool(Name);
+ }
+ }
+
+ if (HandleList != NULL) {
+ FreePool(HandleList);
+ }
+ }
+ ShellCommandLineFreeVarList (Package);
+ }
+ return (ShellStatus);
+}
+
diff --git a/ShellPkg/Library/UefiShellDriver1CommandsLib/OpenInfo.c b/ShellPkg/Library/UefiShellDriver1CommandsLib/OpenInfo.c
new file mode 100644
index 0000000000..80683b5abe
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDriver1CommandsLib/OpenInfo.c
@@ -0,0 +1,243 @@
+/** @file
+ Main file for OpenInfo shell Driver1 function.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiShellDriver1CommandsLib.h"
+
+EFI_STATUS
+EFIAPI
+TraverseHandleDatabase (
+ IN CONST EFI_HANDLE DriverBindingHandle OPTIONAL,
+ IN CONST EFI_HANDLE ControllerHandle OPTIONAL,
+ IN UINTN *HandleCount,
+ OUT EFI_HANDLE **HandleBuffer,
+ OUT UINTN **HandleType
+ ){
+ EFI_STATUS Status;
+ UINTN HandleIndex;
+ EFI_GUID **ProtocolGuidArray;
+ UINTN ArrayCount;
+ UINTN ProtocolIndex;
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;
+ UINTN OpenInfoCount;
+ UINTN OpenInfoIndex;
+ UINTN ChildIndex;
+
+ ASSERT(HandleCount != NULL);
+ ASSERT(HandleBuffer != NULL);
+ ASSERT(HandleType != NULL);
+ ASSERT(DriverBindingHandle != NULL || ControllerHandle != NULL);
+
+ *HandleCount = 0;
+ *HandleBuffer = NULL;
+ *HandleType = NULL;
+
+ //
+ // Retrieve the list of all handles from the handle database
+ //
+ Status = gBS->LocateHandleBuffer (
+ AllHandles,
+ NULL,
+ NULL,
+ HandleCount,
+ HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return (Status);
+ }
+
+ *HandleType = AllocateZeroPool (*HandleCount * sizeof (UINTN));
+ ASSERT(*HandleType != NULL);
+
+ for (HandleIndex = 0; HandleIndex < *HandleCount; HandleIndex++) {
+ //
+ // Retrieve the list of all the protocols on each handle
+ //
+ Status = gBS->ProtocolsPerHandle (
+ (*HandleBuffer)[HandleIndex],
+ &ProtocolGuidArray,
+ &ArrayCount
+ );
+ if (!EFI_ERROR (Status)) {
+
+ for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {
+
+ //
+ // Set the bit describing what this handle has
+ //
+ if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiLoadedImageProtocolGuid) != FALSE) {
+ (*HandleType)[HandleIndex] |= HANDLE_RELATIONSHIP_IMAGE_HANDLE;
+ } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverBindingProtocolGuid) != FALSE) {
+ (*HandleType)[HandleIndex] |= HANDLE_RELATIONSHIP_DRIVER_BINDING_HANDLE;
+ } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverConfiguration2ProtocolGuid) != FALSE) {
+ (*HandleType)[HandleIndex] |= HANDLE_RELATIONSHIP_DRIVER_CONFIGURATION_HANDLE;
+ } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverConfigurationProtocolGuid) != FALSE) {
+ (*HandleType)[HandleIndex] |= HANDLE_RELATIONSHIP_DRIVER_CONFIGURATION_HANDLE;
+ } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverDiagnostics2ProtocolGuid) != FALSE) {
+ (*HandleType)[HandleIndex] |= HANDLE_RELATIONSHIP_DRIVER_DIAGNOSTICS_HANDLE;
+ } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverDiagnosticsProtocolGuid) != FALSE) {
+ (*HandleType)[HandleIndex] |= HANDLE_RELATIONSHIP_DRIVER_DIAGNOSTICS_HANDLE;
+ } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiComponentName2ProtocolGuid) != FALSE) {
+ (*HandleType)[HandleIndex] |= HANDLE_RELATIONSHIP_COMPONENT_NAME_HANDLE;
+ } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiComponentNameProtocolGuid) != FALSE) {
+ (*HandleType)[HandleIndex] |= HANDLE_RELATIONSHIP_COMPONENT_NAME_HANDLE;
+ } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDevicePathProtocolGuid) != FALSE) {
+ (*HandleType)[HandleIndex] |= HANDLE_RELATIONSHIP_DEVICE_HANDLE;
+ } else {
+ DEBUG_CODE_BEGIN();
+ ASSERT((*HandleType)[HandleIndex] == (*HandleType)[HandleIndex]);
+ DEBUG_CODE_END();
+ }
+ //
+ // Retrieve the list of agents that have opened each protocol
+ //
+ Status = gBS->OpenProtocolInformation (
+ (*HandleBuffer)[HandleIndex],
+ ProtocolGuidArray[ProtocolIndex],
+ &OpenInfo,
+ &OpenInfoCount
+ );
+ if (!EFI_ERROR (Status)) {
+ for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
+ if (DriverBindingHandle != NULL && OpenInfo[OpenInfoIndex].AgentHandle == DriverBindingHandle) {
+ if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) == EFI_OPEN_PROTOCOL_BY_DRIVER) {
+ //
+ // Mark the device handle as being managed by the driver specified by DriverBindingHandle
+ //
+ (*HandleType)[HandleIndex] |= (HANDLE_RELATIONSHIP_DEVICE_HANDLE | HANDLE_RELATIONSHIP_CONTROLLER_HANDLE);
+ }
+ if (ControllerHandle != NULL && (*HandleBuffer)[HandleIndex] == ControllerHandle) {
+ if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) == EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
+ for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) {
+ if ((*HandleBuffer)[ChildIndex] == OpenInfo[OpenInfoIndex].ControllerHandle) {
+ (*HandleType)[ChildIndex] |= (HANDLE_RELATIONSHIP_DEVICE_HANDLE | HANDLE_RELATIONSHIP_CHILD_HANDLE);
+ }
+ }
+ }
+ }
+ } else if (DriverBindingHandle == NULL && OpenInfo[OpenInfoIndex].ControllerHandle == ControllerHandle) {
+ if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) == EFI_OPEN_PROTOCOL_BY_DRIVER) {
+ for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) {
+ if ((*HandleBuffer)[ChildIndex] == OpenInfo[OpenInfoIndex].AgentHandle) {
+ //
+ // mark the handle who opened this as a device driver
+ //
+ (*HandleType)[ChildIndex] |= HANDLE_RELATIONSHIP_DEVICE_DRIVER;
+ }
+ }
+ }
+ if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) == EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
+ //
+ // this handle has people opening by child so it must be a parent
+ //
+ (*HandleType)[HandleIndex] |= HANDLE_RELATIONSHIP_PARENT_HANDLE;
+ for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) {
+ if ((*HandleBuffer)[ChildIndex] == OpenInfo[OpenInfoIndex].AgentHandle) {
+ (*HandleType)[ChildIndex] |= HANDLE_RELATIONSHIP_BUS_DRIVER;
+ }
+ }
+ }
+ }
+ }
+
+ FreePool (OpenInfo);
+ }
+ }
+
+ FreePool (ProtocolGuidArray);
+ }
+ }
+
+ if (EFI_ERROR(Status)) {
+ if (*HandleType != NULL) {
+ FreePool (*HandleType);
+ }
+ if (*HandleBuffer != NULL) {
+ FreePool (*HandleBuffer);
+ }
+
+ *HandleCount = 0;
+ *HandleBuffer = NULL;
+ *HandleType = NULL;
+ }
+
+ return Status;
+}
+
+
+SHELL_STATUS
+EFIAPI
+ShellCommandRunOpenInfo (
+ VOID *RESERVED
+ ) {
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ EFI_HANDLE theHandle;
+ EFI_HANDLE *HandleList;
+ UINTN Count;
+ UINTN *Type;
+
+ ShellStatus = SHELL_SUCCESS;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
+ if EFI_ERROR(Status) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ if (ShellCommandLineGetCount() > 2){
+ //
+ // error for too many parameters
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetCount() == 0) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDriver1HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ if (ShellCommandLineGetRawValue(Package, 1) != NULL && CommandLibGetHandleValue(StrHexToUintn(ShellCommandLineGetRawValue(Package, 1))) == NULL){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, ShellCommandLineGetRawValue(Package, 1));
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ theHandle = CommandLibGetHandleValue(StrHexToUintn(ShellCommandLineGetRawValue(Package, 1)));
+ ASSERT(theHandle != NULL);
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_OPENINFO_HEADER_LINE), gShellDriver1HiiHandle, StrHexToUintn(ShellCommandLineGetRawValue(Package, 1)), theHandle);
+ Status = TraverseHandleDatabase (NULL, theHandle, &Count, &HandleList, &Type);
+ if (EFI_ERROR(Status) == FALSE && Count > 0) {
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, ShellCommandLineGetRawValue(Package, 1));
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ }
+ }
+ }
+ return (ShellStatus);
+}
diff --git a/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.c b/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.c
new file mode 100644
index 0000000000..67a074f11b
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.c
@@ -0,0 +1,137 @@
+/** @file
+ Main file for NULL named library for level 1 shell command functions.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiShellDriver1CommandsLib.h"
+
+STATIC CONST CHAR16 mFileName[] = L"Driver1Commands";
+EFI_HANDLE gShellDriver1HiiHandle = NULL;
+CONST EFI_GUID gShellDriver1HiiGuid = \
+ { \
+ 0xaf0b742, 0x63ec, 0x45bd, {0x8d, 0xb6, 0x71, 0xad, 0x7f, 0x2f, 0xe8, 0xe8} \
+ };
+
+
+CONST CHAR16*
+EFIAPI
+ShellCommandGetManFileNameDriver1 (
+ VOID
+ ){
+ return (mFileName);
+}
+
+/**
+ Constructor for the Shell Driver1 Commands library.
+
+ @param ImageHandle the image handle of the process
+ @param SystemTable the EFI System Table pointer
+
+ @retval EFI_SUCCESS the shell command handlers were installed sucessfully
+ @retval EFI_UNSUPPORTED the shell level required was not found.
+**/
+EFI_STATUS
+EFIAPI
+UefiShellDriver1CommandsLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ ) {
+ //
+ // check or bit of the profiles mask
+ //
+ if (PcdGet8(PcdShellProfileMask) && BIT0 == 0) {
+ return (EFI_UNSUPPORTED);
+ }
+
+ //
+ // install our shell command handlers that are always installed
+ //
+ ShellCommandRegisterCommandName(L"connect", ShellCommandRunConnect , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE);
+ ShellCommandRegisterCommandName(L"devices", ShellCommandRunDevices , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE);
+ ShellCommandRegisterCommandName(L"openinfo", ShellCommandRunOpenInfo , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE);
+/*
+ ShellCommandRegisterCommandName(L"devtree", ShellCommandRunDevTree , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE);
+ ShellCommandRegisterCommandName(L"dh", ShellCommandRunDH , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE);
+ ShellCommandRegisterCommandName(L"disconnect", ShellCommandRunDisconnect , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE);
+ ShellCommandRegisterCommandName(L"drivers", ShellCommandRunDrivers , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE);
+ ShellCommandRegisterCommandName(L"drvcfg", ShellCommandRunDrvCfg , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE);
+ ShellCommandRegisterCommandName(L"drvdiag", ShellCommandRunDrvDiag , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE);
+ ShellCommandRegisterCommandName(L"reconnect", ShellCommandRunReconnect , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE);
+ ShellCommandRegisterCommandName(L"unload", ShellCommandRunUnload , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE);
+*/
+
+ //
+ // install the HII stuff.
+ //
+ gShellDriver1HiiHandle = HiiAddPackages (&gShellDriver1HiiGuid, gImageHandle, UefiShellDriver1CommandsLibStrings, NULL);
+ if (gShellDriver1HiiHandle == NULL) {
+ return (EFI_DEVICE_ERROR);
+ }
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Destructory for the library. free any resources.
+**/
+EFI_STATUS
+EFIAPI
+UefiShellDriver1CommandsLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ if (gShellDriver1HiiHandle != NULL) {
+ HiiRemovePackages(gShellDriver1HiiHandle);
+ }
+ return (EFI_SUCCESS);
+}
+
+EFI_HANDLE*
+EFIAPI
+GetHandleListByPotocol (
+ IN CONST EFI_GUID *ProtocolGuid
+ ){
+ EFI_HANDLE *HandleList;
+ UINTN Size;
+ EFI_STATUS Status;
+
+ Size = 0;
+ HandleList = NULL;
+
+ //
+ // We cannot use LocateHandleBuffer since we need that NULL item on the ends of the list!
+ //
+ if (ProtocolGuid == NULL) {
+ Status = gBS->LocateHandle(AllHandles, NULL, NULL, &Size, HandleList);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ HandleList = AllocatePool(Size + sizeof(EFI_HANDLE));
+ Status = gBS->LocateHandle(AllHandles, NULL, NULL, &Size, HandleList);
+ HandleList[Size/sizeof(EFI_HANDLE)] = NULL;
+ }
+ } else {
+ Status = gBS->LocateHandle(ByProtocol, (EFI_GUID*)ProtocolGuid, NULL, &Size, HandleList);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ HandleList = AllocatePool(Size + sizeof(EFI_HANDLE));
+ Status = gBS->LocateHandle(ByProtocol, (EFI_GUID*)ProtocolGuid, NULL, &Size, HandleList);
+ HandleList[Size/sizeof(EFI_HANDLE)] = NULL;
+ }
+ }
+ if (EFI_ERROR(Status)) {
+ if (HandleList != NULL) {
+ FreePool(HandleList);
+ }
+ return (NULL);
+ }
+ return (HandleList);
+}
+
diff --git a/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.h b/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.h
new file mode 100644
index 0000000000..4d3935e31a
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.h
@@ -0,0 +1,71 @@
+/** @file
+ Main file for NULL named library for Profile1 shell command functions.
+
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ 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 <Uefi.h>
+#include <ShellBase.h>
+
+#include <Protocol/EfiShell.h>
+#include <Protocol/EfiShellParameters.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/UnicodeCollation.h>
+#include <Protocol/DevicePathToText.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/ShellCommandLib.h>
+#include <Library/ShellLib.h>
+#include <Library/SortLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HiiLib.h>
+#include <Library/FileHandleLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PrintLib.h>
+
+
+extern EFI_HANDLE gShellDriver1HiiHandle;
+extern CONST EFI_GUID gShellDriver1HiiGuid;
+
+EFI_HANDLE*
+EFIAPI
+GetHandleListByPotocol (
+ IN CONST EFI_GUID *ProtocolGuid
+ );
+
+SHELL_STATUS
+EFIAPI
+ShellCommandRunConnect (
+ VOID *RESERVED
+ );
+
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDevices (
+ VOID *RESERVED
+ );
+
+SHELL_STATUS
+EFIAPI
+ShellCommandRunOpenInfo (
+ VOID *RESERVED
+ );
+
+
+
+
diff --git a/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf b/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf
new file mode 100644
index 0000000000..07840eca6f
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf
@@ -0,0 +1,57 @@
+#/** @file
+# Provides shell driver1 profile functions
+#
+# Copyright (c) 2010, Intel Corporation.All rights reserved. <BR>
+#
+# 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 = UefiShellDriver1CommandsLib
+ FILE_GUID = 313D3674-3ED4-48fd-BF97-7DB35D4190D1
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER
+ CONSTRUCTOR = UefiShellDriver1CommandsLibConstructor
+ DESTRUCTOR = UefiShellDriver1CommandsLibDestructor
+
+[Sources]
+ Connect.c
+ Devices.c
+ OpenInfo.c
+ UefiShellDriver1CommandsLib.c
+ UefiShellDriver1CommandsLib.h
+ UefiShellDriver1CommandsLib.uni
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ ShellCommandLib
+ ShellLib
+ UefiLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ SortLib
+ PrintLib
+
+[Pcd]
+ gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask # ALWAYS_CONSUMED
+
+[Guids]
+ gEfiGlobalVariableGuid
+ gEfiConsoleInDeviceGuid
+ gEfiConsoleOutDeviceGuid
diff --git a/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.uni b/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.uni
new file mode 100644
index 0000000000..1de8b6d4aa
--- /dev/null
+++ b/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.uni
Binary files differ
diff --git a/ShellPkg/Library/UefiShellLevel1CommandsLib/Exit.c b/ShellPkg/Library/UefiShellLevel1CommandsLib/Exit.c
new file mode 100644
index 0000000000..2f2a5bf565
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel1CommandsLib/Exit.c
@@ -0,0 +1,81 @@
+/** @file
+ Main file for exit shell level 1 function.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiShellLevel1CommandsLib.h"
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"/b", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'exit' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunExit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+
+ ShellStatus = SHELL_SUCCESS;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel1HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+
+ //
+ // If we are in a batch file and /b then pass TRUE otherwise false...
+ //
+ ShellCommandRegisterExit((BOOLEAN)(gEfiShellProtocol->BatchIsActive() && ShellCommandLineGetFlag(Package, L"/b")));
+
+ //
+ // return the specified error code
+ //
+ if (ShellCommandLineGetRawValue(Package, 1) != NULL) {
+ ShellStatus = (SHELL_STATUS)(ShellStrToUintn(ShellCommandLineGetRawValue(Package, 1)));
+ }
+
+ ShellCommandLineFreeVarList (Package);
+ }
+ return (ShellStatus);
+}
+
diff --git a/ShellPkg/Library/UefiShellLevel1CommandsLib/For.c b/ShellPkg/Library/UefiShellLevel1CommandsLib/For.c
new file mode 100644
index 0000000000..0e68119b8d
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel1CommandsLib/For.c
@@ -0,0 +1,581 @@
+/** @file
+ Main file for endfor and for shell level 1 functions.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiShellLevel1CommandsLib.h"
+#include <Library/PrintLib.h>
+
+BOOLEAN
+EFIAPI
+ShellIsValidForNumber (
+ IN CONST CHAR16 *Number
+ )
+{
+ if (Number == NULL || *Number == CHAR_NULL) {
+ return (FALSE);
+ }
+
+ if (*Number == L'-') {
+ Number++;
+ }
+
+ if (StrLen(Number) == 0) {
+ return (FALSE);
+ }
+
+ if (StrLen(Number) >= 7) {
+ if (StrStr(Number, L" ") != NULL && (StrStr(Number, L" ") - Number) >= 7) {
+ return (FALSE);
+ }
+ }
+
+ if (!ShellIsDecimalDigitCharacter(*Number)) {
+ return (FALSE);
+ }
+
+ return (TRUE);
+}
+
+/**
+ Function for 'endfor' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunEndFor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Found;
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ if (!gEfiShellProtocol->BatchIsActive()) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"EndFor");
+ return (SHELL_UNSUPPORTED);
+ }
+
+ if (gEfiShellParametersProtocol->Argc > 1) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle);
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ Found = MoveToTag(GetPreviousNode, L"for", L"endfor", NULL, ShellCommandGetCurrentScriptFile(), FALSE, FALSE, FALSE);
+
+ if (!Found) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"For", L"EndFor", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);
+ return (SHELL_NOT_FOUND);
+ }
+ return (SHELL_SUCCESS);
+}
+
+typedef struct {
+ UINT32 Signature;
+ INTN Current;
+ INTN End;
+ INTN Step;
+ CHAR16 *ReplacementName;
+ CHAR16 *CurrentValue;
+ BOOLEAN RemoveSubstAlias;
+ CHAR16 Set[1];
+ } SHELL_FOR_INFO;
+#define SIZE_OF_SHELL_FOR_INFO OFFSET_OF (SHELL_FOR_INFO, Set)
+#define SHELL_FOR_INFO_SIGNATURE SIGNATURE_32 ('S', 'F', 'I', 's')
+
+/**
+ Update the value of a given alias on the list. If the alias is not there then add it.
+
+ @param[in] Alias The alias to test for.
+ @param[in] CommandString The updated command string.
+ @param[in,out] List The list to search.
+**/
+VOID
+EFIAPI
+InternalUpdateAliasOnList(
+ IN CONST CHAR16 *Alias,
+ IN CONST CHAR16 *CommandString,
+ IN OUT LIST_ENTRY *List
+ )
+{
+ ALIAS_LIST *Node;
+ BOOLEAN Found;
+
+ //
+ // assert for NULL parameter
+ //
+ ASSERT(Alias != NULL);
+
+ //
+ // check for the Alias
+ //
+ for ( Node = (ALIAS_LIST *)GetFirstNode(List), Found = FALSE
+ ; !IsNull(List, &Node->Link)
+ ; Node = (ALIAS_LIST *)GetNextNode(List, &Node->Link)
+ ){
+ ASSERT(Node->CommandString != NULL);
+ ASSERT(Node->Alias != NULL);
+ if (StrCmp(Node->Alias, Alias)==0) {
+ FreePool(Node->CommandString);
+ Node->CommandString = NULL;
+ Node->CommandString = StrnCatGrow(&Node->CommandString, NULL, CommandString, 0);
+ Found = TRUE;
+ break;
+ }
+ }
+ if (!Found) {
+ Node = AllocateZeroPool(sizeof(ALIAS_LIST));
+ ASSERT(Node->Alias == NULL);
+ Node->Alias = StrnCatGrow(&Node->Alias, NULL, Alias, 0);
+ ASSERT(Node->CommandString == NULL);
+ Node->CommandString = StrnCatGrow(&Node->CommandString, NULL, CommandString, 0);
+ InsertTailList(List, &Node->Link);
+ }
+}
+
+/**
+ Find out if an alias is on the given list.
+
+ @param[in] Alias The alias to test for.
+ @param[in] List The list to search.
+
+ @retval TRUE The alias is on the list.
+ @retval FALSE The alias is not on the list.
+**/
+BOOLEAN
+EFIAPI
+InternalIsAliasOnList(
+ IN CONST CHAR16 *Alias,
+ IN CONST LIST_ENTRY *List
+ )
+{
+ ALIAS_LIST *Node;
+
+ //
+ // assert for NULL parameter
+ //
+ ASSERT(Alias != NULL);
+
+ //
+ // check for the Alias
+ //
+ for ( Node = (ALIAS_LIST *)GetFirstNode(List)
+ ; !IsNull(List, &Node->Link)
+ ; Node = (ALIAS_LIST *)GetNextNode(List, &Node->Link)
+ ){
+ ASSERT(Node->CommandString != NULL);
+ ASSERT(Node->Alias != NULL);
+ if (StrCmp(Node->Alias, Alias)==0) {
+ return (TRUE);
+ }
+ }
+ return (FALSE);
+}
+
+/**
+ Remove an alias from the given list.
+
+ @param[in] Alias The alias to remove.
+ @param[in,out] List The list to search.
+**/
+BOOLEAN
+EFIAPI
+InternalRemoveAliasFromList(
+ IN CONST CHAR16 *Alias,
+ IN OUT LIST_ENTRY *List
+ )
+{
+ ALIAS_LIST *Node;
+
+ //
+ // assert for NULL parameter
+ //
+ ASSERT(Alias != NULL);
+
+ //
+ // check for the Alias
+ //
+ for ( Node = (ALIAS_LIST *)GetFirstNode(List)
+ ; !IsNull(List, &Node->Link)
+ ; Node = (ALIAS_LIST *)GetNextNode(List, &Node->Link)
+ ){
+ ASSERT(Node->CommandString != NULL);
+ ASSERT(Node->Alias != NULL);
+ if (StrCmp(Node->Alias, Alias)==0) {
+ RemoveEntryList(&Node->Link);
+ FreePool(Node->Alias);
+ FreePool(Node->CommandString);
+ FreePool(Node);
+ return (TRUE);
+ }
+ }
+ return (FALSE);
+}
+
+/**
+ Function for 'for' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunFor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ SHELL_STATUS ShellStatus;
+ SCRIPT_FILE *CurrentScriptFile;
+ CHAR16 *ArgSet;
+ CHAR16 *ArgSetWalker;
+ UINTN ArgSize;
+ UINTN LoopVar;
+ SHELL_FOR_INFO *Info;
+ CHAR16 *TempString;
+ CHAR16 *TempSpot;
+ BOOLEAN FirstPass;
+ EFI_SHELL_FILE_INFO *Node;
+ EFI_SHELL_FILE_INFO *FileList;
+ UINTN NewSize;
+
+ ArgSet = NULL;
+ ArgSize = 0;
+ ShellStatus = SHELL_SUCCESS;
+ ArgSetWalker = NULL;
+ TempString = NULL;
+ FirstPass = FALSE;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ if (!gEfiShellProtocol->BatchIsActive()) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"For");
+ return (SHELL_UNSUPPORTED);
+ }
+
+ if (gEfiShellParametersProtocol->Argc < 4) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel1HiiHandle);
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ CurrentScriptFile = ShellCommandGetCurrentScriptFile();
+ ASSERT(CurrentScriptFile != NULL);
+
+ if (CurrentScriptFile->CurrentCommand->Data == NULL) {
+ FirstPass = TRUE;
+
+ //
+ // Make sure that an End exists.
+ //
+ if (!MoveToTag(GetNextNode, L"endfor", L"for", NULL, CurrentScriptFile, TRUE, TRUE, FALSE)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"EndFor", L"For", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);
+ return (SHELL_DEVICE_ERROR);
+ }
+
+ //
+ // Process the line.
+ //
+ if (gEfiShellParametersProtocol->Argv[1][0] != L'%' || gEfiShellParametersProtocol->Argv[1][2] != CHAR_NULL
+ ||!((gEfiShellParametersProtocol->Argv[1][1] >= L'a' && gEfiShellParametersProtocol->Argv[1][1] <= L'z')
+ ||(gEfiShellParametersProtocol->Argv[1][1] >= L'A' && gEfiShellParametersProtocol->Argv[1][1] <= L'Z'))
+ ) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_VAR), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[2]);
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ L"in",
+ gEfiShellParametersProtocol->Argv[2]) == 0) {
+ for (LoopVar = 0x3 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) {
+ ASSERT((ArgSet == NULL && ArgSize == 0) || (ArgSet != NULL));
+ if (ArgSet == NULL) {
+ // ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L"\"", 0);
+ } else {
+ ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" \"", 0);
+ }
+ if (StrStr(gEfiShellParametersProtocol->Argv[LoopVar], L"*") != NULL
+ ||StrStr(gEfiShellParametersProtocol->Argv[LoopVar], L"?") != NULL
+ ||StrStr(gEfiShellParametersProtocol->Argv[LoopVar], L"[") != NULL
+ ||StrStr(gEfiShellParametersProtocol->Argv[LoopVar], L"]") != NULL) {
+ FileList = NULL;
+ Status = ShellOpenFileMetaArg ((CHAR16*)gEfiShellParametersProtocol->Argv[LoopVar], EFI_FILE_MODE_READ, &FileList);
+ if (EFI_ERROR(Status) || FileList == NULL || IsListEmpty(&FileList->Link)) {
+ ArgSet = StrnCatGrow(&ArgSet, &ArgSize, gEfiShellParametersProtocol->Argv[LoopVar], 0);
+ } else {
+ for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link)
+ ; !IsNull(&FileList->Link, &Node->Link)
+ ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link)
+ ){
+ ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" \"", 0);
+ ArgSet = StrnCatGrow(&ArgSet, &ArgSize, Node->FullName, 0);
+ ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L"\"", 0);
+ }
+ ShellCloseFileMetaArg(&FileList);
+ }
+ } else {
+ ArgSet = StrnCatGrow(&ArgSet, &ArgSize, gEfiShellParametersProtocol->Argv[LoopVar], 0);
+ }
+ ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L"\"", 0);
+ }
+ //
+ // set up for an 'in' for loop
+ //
+ NewSize = StrSize(ArgSet);
+ NewSize += sizeof(SHELL_FOR_INFO)+StrSize(gEfiShellParametersProtocol->Argv[1]);
+ Info = AllocateZeroPool(NewSize);
+ ASSERT(Info != NULL);
+ Info->Signature = SHELL_FOR_INFO_SIGNATURE;
+ CopyMem(Info->Set, ArgSet, StrSize(ArgSet));
+ NewSize = StrSize(gEfiShellParametersProtocol->Argv[1]);
+ CopyMem(Info->Set+(StrSize(ArgSet)/sizeof(Info->Set[0])), gEfiShellParametersProtocol->Argv[1], NewSize);
+ Info->ReplacementName = Info->Set+StrSize(ArgSet)/sizeof(Info->Set[0]);
+ Info->CurrentValue = (CHAR16*)Info->Set;
+ Info->Step = 0;
+ Info->Current = 0;
+ Info->End = 0;
+
+ if (InternalIsAliasOnList(Info->ReplacementName, &CurrentScriptFile->SubstList)) {
+ Info->RemoveSubstAlias = FALSE;
+ } else {
+ Info->RemoveSubstAlias = TRUE;
+ }
+ CurrentScriptFile->CurrentCommand->Data = Info;
+ } else if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ L"run",
+ gEfiShellParametersProtocol->Argv[2]) == 0) {
+ for (LoopVar = 0x3 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) {
+ ASSERT((ArgSet == NULL && ArgSize == 0) || (ArgSet != NULL));
+ if (ArgSet == NULL) {
+// ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L"\"", 0);
+ } else {
+ ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" ", 0);
+ }
+ ArgSet = StrnCatGrow(&ArgSet, &ArgSize, gEfiShellParametersProtocol->Argv[LoopVar], 0);
+// ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" ", 0);
+ }
+ //
+ // set up for a 'run' for loop
+ //
+ Info = AllocateZeroPool(sizeof(SHELL_FOR_INFO)+StrSize(gEfiShellParametersProtocol->Argv[1]));
+ ASSERT(Info != NULL);
+ CopyMem(Info->Set, gEfiShellParametersProtocol->Argv[1], StrSize(gEfiShellParametersProtocol->Argv[1]));
+ Info->ReplacementName = Info->Set;
+ Info->CurrentValue = NULL;
+ ArgSetWalker = ArgSet;
+ if (ArgSetWalker[0] != L'(') {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), gShellLevel1HiiHandle, ArgSet, ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ArgSetWalker++;
+ while (ArgSetWalker != NULL && ArgSetWalker[0] == L' ') {
+ ArgSetWalker++;
+ }
+ if (!ShellIsValidForNumber(ArgSetWalker)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), gShellLevel1HiiHandle, ArgSet, ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ if (ArgSetWalker[0] == L'-') {
+ Info->Current = 0 - (INTN)ShellStrToUintn(ArgSetWalker+1);
+ } else {
+ Info->Current = (INTN)ShellStrToUintn(ArgSetWalker);
+ }
+ ArgSetWalker = StrStr(ArgSetWalker, L" ");
+ while (ArgSetWalker != NULL && ArgSetWalker[0] == L' ') {
+ ArgSetWalker++;
+ }
+ if (ArgSetWalker == NULL || *ArgSetWalker == CHAR_NULL || !ShellIsValidForNumber(ArgSetWalker)){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), gShellLevel1HiiHandle, ArgSet, ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ if (ArgSetWalker[0] == L'-') {
+ Info->End = 0 - (INTN)ShellStrToUintn(ArgSetWalker+1);
+ } else {
+ Info->End = (INTN)ShellStrToUintn(ArgSetWalker);
+ }
+ if (Info->Current < Info->End) {
+ Info->Step = 1;
+ } else {
+ Info->Step = -1;
+ }
+
+ ArgSetWalker = StrStr(ArgSetWalker, L" ");
+ while (ArgSetWalker != NULL && ArgSetWalker[0] == L' ') {
+ ArgSetWalker++;
+ }
+ if (ArgSetWalker != NULL && *ArgSetWalker != CHAR_NULL) {
+ TempSpot = StrStr(ArgSetWalker, L")");
+ if (TempSpot == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), gShellLevel1HiiHandle, ArgSet, ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ *TempSpot = CHAR_NULL;
+ if (ArgSetWalker == NULL || *ArgSetWalker == CHAR_NULL || !ShellIsValidForNumber(ArgSetWalker)){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), gShellLevel1HiiHandle, ArgSet, ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ if (*ArgSetWalker == L')') {
+ ASSERT(Info->Step == 1 || Info->Step == -1);
+ } else {
+ if (ArgSetWalker[0] == L'-') {
+ Info->Step = 0 - (INTN)ShellStrToUintn(ArgSetWalker+1);
+ } else {
+ Info->Step = (INTN)ShellStrToUintn(ArgSetWalker);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (ShellStatus == SHELL_SUCCESS) {
+ if (InternalIsAliasOnList(Info->ReplacementName, &CurrentScriptFile->SubstList)) {
+ Info->RemoveSubstAlias = FALSE;
+ } else {
+ Info->RemoveSubstAlias = TRUE;
+ }
+ }
+ CurrentScriptFile->CurrentCommand->Data = Info;
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), gShellLevel1HiiHandle, ArgSet, ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ } else {
+ //
+ // These need to be NULL since they are used to determine if this is the first pass later on...
+ //
+ ASSERT(ArgSetWalker == NULL);
+ ASSERT(ArgSet == NULL);
+ }
+
+ Info = (SHELL_FOR_INFO*)CurrentScriptFile->CurrentCommand->Data;
+ if (CurrentScriptFile->CurrentCommand->Reset) {
+ Info->CurrentValue = (CHAR16*)Info->Set;
+ FirstPass = TRUE;
+ CurrentScriptFile->CurrentCommand->Reset = FALSE;
+ }
+ if (ShellStatus == SHELL_SUCCESS) {
+ ASSERT(Info != NULL);
+ if (Info->Step != 0) {
+ //
+ // only advance if not the first pass
+ //
+ if (!FirstPass) {
+ //
+ // sequence version of for loop...
+ //
+ Info->Current += Info->Step;
+ }
+
+ TempString = AllocateZeroPool(50*sizeof(CHAR16));
+ UnicodeSPrint(TempString, 50*sizeof(CHAR16), L"%d", Info->Current);
+ InternalUpdateAliasOnList(Info->ReplacementName, TempString, &CurrentScriptFile->SubstList);
+ FreePool(TempString);
+
+ if ((Info->Step > 0 && Info->Current > Info->End) || (Info->Step < 0 && Info->Current < Info->End)) {
+ CurrentScriptFile->CurrentCommand->Data = NULL;
+ //
+ // find the matching endfor (we're done with the loop)
+ //
+ if (!MoveToTag(GetNextNode, L"endfor", L"for", NULL, CurrentScriptFile, TRUE, FALSE, FALSE)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"EndFor", L"For", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);
+ ShellStatus = SHELL_DEVICE_ERROR;
+ }
+ if (Info->RemoveSubstAlias) {
+ //
+ // remove item from list
+ //
+ InternalRemoveAliasFromList(Info->ReplacementName, &CurrentScriptFile->SubstList);
+ }
+ FreePool(Info);
+ }
+ } else {
+ //
+ // Must be in 'in' version of for loop...
+ //
+ ASSERT(Info->Set != NULL);
+ if (Info->CurrentValue != NULL && *Info->CurrentValue != CHAR_NULL) {
+ if (Info->CurrentValue[0] == L'\"') {
+ Info->CurrentValue++;
+ }
+ while (Info->CurrentValue[0] == L' ') {
+ Info->CurrentValue++;
+ }
+ if (Info->CurrentValue[0] == L'\"') {
+ Info->CurrentValue++;
+ }
+ //
+ // do the next one of the set
+ //
+ ASSERT(TempString == NULL);
+ TempString = StrnCatGrow(&TempString, NULL, Info->CurrentValue, 0);
+ TempSpot = StrStr(TempString, L"\" \"");
+ if (TempSpot != NULL) {
+ *TempSpot = CHAR_NULL;
+ }
+ while (TempString[StrLen(TempString)-1] == L'\"') {
+ TempString[StrLen(TempString)-1] = CHAR_NULL;
+ }
+ InternalUpdateAliasOnList(Info->ReplacementName, TempString, &CurrentScriptFile->SubstList);
+ Info->CurrentValue += StrLen(TempString);
+
+ if (Info->CurrentValue[0] == L'\"') {
+ Info->CurrentValue++;
+ }
+ while (Info->CurrentValue[0] == L' ') {
+ Info->CurrentValue++;
+ }
+ if (Info->CurrentValue[0] == L'\"') {
+ Info->CurrentValue++;
+ }
+ FreePool(TempString);
+
+ } else {
+ CurrentScriptFile->CurrentCommand->Data = NULL;
+ //
+ // find the matching endfor (we're done with the loop)
+ //
+ if (!MoveToTag(GetNextNode, L"endfor", L"for", NULL, CurrentScriptFile, TRUE, FALSE, FALSE)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"EndFor", L"For", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);
+ ShellStatus = SHELL_DEVICE_ERROR;
+ }
+ if (Info->RemoveSubstAlias) {
+ //
+ // remove item from list
+ //
+ InternalRemoveAliasFromList(Info->ReplacementName, &CurrentScriptFile->SubstList);
+ }
+ FreePool(Info);
+ }
+ }
+ }
+ if (ArgSet != NULL) {
+ FreePool(ArgSet);
+ }
+ return (ShellStatus);
+}
+
diff --git a/ShellPkg/Library/UefiShellLevel1CommandsLib/Goto.c b/ShellPkg/Library/UefiShellLevel1CommandsLib/Goto.c
new file mode 100644
index 0000000000..8213fae7ac
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel1CommandsLib/Goto.c
@@ -0,0 +1,92 @@
+/** @file
+ Main file for goto shell level 1 function.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiShellLevel1CommandsLib.h"
+
+/**
+ Function for 'goto' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunGoto (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ CHAR16 *CompareString;
+ UINTN Size;
+
+ ShellStatus = SHELL_SUCCESS;
+ CompareString = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ if (!gEfiShellProtocol->BatchIsActive()) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"Goto");
+ return (SHELL_UNSUPPORTED);
+ }
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel1HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ if (ShellCommandLineGetRawValue(Package, 2) != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetRawValue(Package, 1) == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel1HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Size = 0;
+ ASSERT((CompareString == NULL && Size == 0) || (CompareString != NULL));
+ CompareString = StrnCatGrow(&CompareString, &Size, L":", 0);
+ CompareString = StrnCatGrow(&CompareString, &Size, ShellCommandLineGetRawValue(Package, 1), 0);
+ //
+ // Check forwards and then backwards for a label...
+ //
+ if (!MoveToTag(GetNextNode, L"endfor", L"for", CompareString, ShellCommandGetCurrentScriptFile(), FALSE, FALSE, TRUE)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, CompareString, L"Goto", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ FreePool(CompareString);
+ }
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ return (ShellStatus);
+}
+
diff --git a/ShellPkg/Library/UefiShellLevel1CommandsLib/If.c b/ShellPkg/Library/UefiShellLevel1CommandsLib/If.c
new file mode 100644
index 0000000000..3376329622
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel1CommandsLib/If.c
@@ -0,0 +1,962 @@
+/** @file
+ Main file for If and else shell level 1 function.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiShellLevel1CommandsLib.h"
+#include <Library/PrintLib.h>
+
+
+
+
+typedef enum {
+ END_TAG_OR,
+ END_TAG_AND,
+ END_TAG_THEN,
+ END_TAG_MAX
+} END_TAG_TYPE;
+
+typedef enum {
+ OPERATOR_GT,
+ OPERATOR_LT,
+ OPERATOR_EQ,
+ OPERATOR_NE,
+ OPERATOR_GE,
+ OPERATOR_LE,
+ OPERATOR_UGT,
+ OPERATOR_ULT,
+ OPERATOR_UGE,
+ OPERATOR_ULE,
+ OPERATOR_MAX
+} BIN_OPERATOR_TYPE;
+
+BOOLEAN
+EFIAPI
+IsNextFragment (
+ IN CONST CHAR16 **Statement,
+ IN CONST CHAR16 *Fragment
+ )
+{
+ CHAR16 *Tester;
+
+ Tester = NULL;
+
+ Tester = StrnCatGrow(&Tester, NULL, *Statement, StrLen(Fragment));
+ ASSERT(Tester != NULL);
+ Tester[StrLen(Fragment)] = CHAR_NULL;
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)Fragment,
+ Tester) == 0) {
+ //
+ // increment the string pointer to the end of what we found and then chop off spaces...
+ //
+ *Statement+=StrLen(Fragment);
+ while (*Statement[0] == L' ') {
+ *Statement++;
+ }
+ FreePool(Tester);
+ return (TRUE);
+ }
+ FreePool(Tester);
+ return (FALSE);
+}
+
+BOOLEAN
+EFIAPI
+IsValidProfile (
+ IN CONST CHAR16 *String
+ )
+{
+ CONST CHAR16 *ProfilesString;
+ CONST CHAR16 *TempLocation;
+
+ ProfilesString = ShellGetEnvironmentVariable(L"profiles");
+ TempLocation = StrStr(ProfilesString, String);
+ if ((TempLocation != NULL) && (*(TempLocation-1) == L';') && (*(TempLocation+StrLen(String)) == L';')) {
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+BOOLEAN
+EFIAPI
+TestOperation (
+ IN CONST CHAR16 *Compare1,
+ IN CONST CHAR16 *Compare2,
+ IN CONST BIN_OPERATOR_TYPE BinOp,
+ IN CONST BOOLEAN CaseInsensitive,
+ IN CONST BOOLEAN ForceStringCompare
+ )
+{
+ INTN Cmp1;
+ INTN Cmp2;
+
+ //
+ // "Compare1 BinOp Compare2"
+ //
+ switch (BinOp) {
+ case OPERATOR_UGT:
+ case OPERATOR_GT:
+ if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {
+ //
+ // string compare
+ //
+ if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) > 0) || (StringCompare(&Compare1, &Compare2) > 0)) {
+ return (TRUE);
+ }
+ } else {
+ //
+ // numeric compare
+ //
+ if (Compare1[0] == L'-') {
+ Cmp1 = 0 - (INTN)StrDecimalToUintn(Compare1+1);
+ } else {
+ Cmp1 = (INTN)StrDecimalToUintn(Compare1);
+ }
+ if (Compare2[0] == L'-') {
+ Cmp2 = 0 - (INTN)StrDecimalToUintn(Compare2+1);
+ } else {
+ Cmp2 = (INTN)StrDecimalToUintn(Compare2);
+ }
+ if (BinOp == OPERATOR_GT) {
+ if (Cmp1 > Cmp2) {
+ return (TRUE);
+ }
+ } else {
+ if ((UINTN)Cmp1 > (UINTN)Cmp2) {
+ return (TRUE);
+ }
+ }
+ }
+ return (FALSE);
+ break;
+ case OPERATOR_ULT:
+ case OPERATOR_LT:
+ if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {
+ //
+ // string compare
+ //
+ if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) < 0) || (StringCompare(&Compare1, &Compare2) < 0)) {
+ return (TRUE);
+ }
+ } else {
+ //
+ // numeric compare
+ //
+ if (Compare1[0] == L'-') {
+ Cmp1 = 0 - (INTN)StrDecimalToUintn(Compare1+1);
+ } else {
+ Cmp1 = (INTN)StrDecimalToUintn(Compare1);
+ }
+ if (Compare2[0] == L'-') {
+ Cmp2 = 0 - (INTN)StrDecimalToUintn(Compare2+1);
+ } else {
+ Cmp2 = (INTN)StrDecimalToUintn(Compare2);
+ }
+ if (BinOp == OPERATOR_LT) {
+ if (Cmp1 < Cmp2) {
+ return (TRUE);
+ }
+ } else {
+ if ((UINTN)Cmp1 < (UINTN)Cmp2) {
+ return (TRUE);
+ }
+ }
+
+ }
+ return (FALSE);
+ break;
+ case OPERATOR_EQ:
+ if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {
+ //
+ // string compare
+ //
+ if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) == 0) || (StringCompare(&Compare1, &Compare2) == 0)) {
+ return (TRUE);
+ }
+ } else {
+ //
+ // numeric compare
+ //
+ if (Compare1[0] == L'-') {
+ Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1);
+ } else {
+ Cmp1 = (INTN)ShellStrToUintn(Compare1);
+ }
+ if (Compare2[0] == L'-') {
+ Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1);
+ } else {
+ Cmp2 = (INTN)ShellStrToUintn(Compare2);
+ }
+ if (Cmp1 == Cmp2) {
+ return (TRUE);
+ }
+ }
+ return (FALSE);
+ break;
+ case OPERATOR_NE:
+ if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {
+ //
+ // string compare
+ //
+ if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) != 0) || (StringCompare(&Compare1, &Compare2) != 0)) {
+ return (TRUE);
+ }
+ } else {
+ //
+ // numeric compare
+ //
+ if (Compare1[0] == L'-') {
+ Cmp1 = 0 - (INTN)StrDecimalToUintn(Compare1+1);
+ } else {
+ Cmp1 = (INTN)StrDecimalToUintn(Compare1);
+ }
+ if (Compare2[0] == L'-') {
+ Cmp2 = 0 - (INTN)StrDecimalToUintn(Compare2+1);
+ } else {
+ Cmp2 = (INTN)StrDecimalToUintn(Compare2);
+ }
+ if (Cmp1 != Cmp2) {
+ return (TRUE);
+ }
+ }
+ return (FALSE);
+ break;
+ case OPERATOR_UGE:
+ case OPERATOR_GE:
+ if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {
+ //
+ // string compare
+ //
+ if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) >= 0) || (StringCompare(&Compare1, &Compare2) >= 0)) {
+ return (TRUE);
+ }
+ } else {
+ //
+ // numeric compare
+ //
+ if (Compare1[0] == L'-') {
+ Cmp1 = 0 - (INTN)StrDecimalToUintn(Compare1+1);
+ } else {
+ Cmp1 = (INTN)StrDecimalToUintn(Compare1);
+ }
+ if (Compare2[0] == L'-') {
+ Cmp2 = 0 - (INTN)StrDecimalToUintn(Compare2+1);
+ } else {
+ Cmp2 = (INTN)StrDecimalToUintn(Compare2);
+ }
+ if (BinOp == OPERATOR_GE) {
+ if (Cmp1 >= Cmp2) {
+ return (TRUE);
+ }
+ } else {
+ if ((UINTN)Cmp1 >= (UINTN)Cmp2) {
+ return (TRUE);
+ }
+ }
+ }
+ return (FALSE);
+ break;
+ case OPERATOR_LE:
+ case OPERATOR_ULE:
+ if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {
+ //
+ // string compare
+ //
+ if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) <= 0) || (StringCompare(&Compare1, &Compare2) <= 0)) {
+ return (TRUE);
+ }
+ } else {
+ //
+ // numeric compare
+ //
+ if (Compare1[0] == L'-') {
+ Cmp1 = 0 - (INTN)StrDecimalToUintn(Compare1+1);
+ } else {
+ Cmp1 = (INTN)StrDecimalToUintn(Compare1);
+ }
+ if (Compare2[0] == L'-') {
+ Cmp2 = 0 - (INTN)StrDecimalToUintn(Compare2+1);
+ } else {
+ Cmp2 = (INTN)StrDecimalToUintn(Compare2);
+ }
+ if (BinOp == OPERATOR_LE) {
+ if (Cmp1 <= Cmp2) {
+ return (TRUE);
+ }
+ } else {
+ if ((UINTN)Cmp1 <= (UINTN)Cmp2) {
+ return (TRUE);
+ }
+ }
+ }
+ return (FALSE);
+ break;
+ }
+ ASSERT(FALSE);
+ return (FALSE);
+}
+
+EFI_STATUS
+EFIAPI
+ProcessStatement (
+ IN OUT BOOLEAN *PassingState,
+ IN UINTN StartParameterNumber,
+ IN UINTN EndParameterNumber,
+ IN CONST END_TAG_TYPE OperatorToUse,
+ IN CONST BOOLEAN CaseInsensitive,
+ IN CONST BOOLEAN ForceStringCompare
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN OperationResult;
+ BOOLEAN NotPresent;
+ CHAR16 *StatementWalker;
+ BIN_OPERATOR_TYPE BinOp;
+ CHAR16 *Compare1;
+ CHAR16 *Compare2;
+ CHAR16 HexString[20];
+ CHAR16 *TempSpot;
+
+ ASSERT((END_TAG_TYPE)OperatorToUse != END_TAG_THEN);
+
+ Status = EFI_SUCCESS;
+ BinOp = OPERATOR_MAX;
+ OperationResult = FALSE;
+ StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber];
+ if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"not")) {
+ NotPresent = TRUE;
+ StatementWalker = gEfiShellParametersProtocol->Argv[++StartParameterNumber];
+ } else {
+ NotPresent = FALSE;
+ }
+
+ //
+ // now check for 'boolfunc' operators
+ //
+ if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"isint")) {
+ if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && StatementWalker[StrLen(StatementWalker)-1] == L')') {
+ StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL;
+ OperationResult = ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE);
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"isint");
+ }
+ } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"exists") || IsNextFragment((CONST CHAR16**)(&StatementWalker), L"exist")) {
+ if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && StatementWalker[StrLen(StatementWalker)-1] == L')') {
+ StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL;
+ //
+ // is what remains a file in CWD???
+ //
+ OperationResult = (BOOLEAN)(ShellFileExists(StatementWalker)==EFI_SUCCESS);
+ } else if (StatementWalker[0] == CHAR_NULL && StartParameterNumber+1 == EndParameterNumber) {
+ OperationResult = (BOOLEAN)(ShellFileExists(gEfiShellParametersProtocol->Argv[++StartParameterNumber])==EFI_SUCCESS);
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"exist(s)");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"available")) {
+ if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && StatementWalker[StrLen(StatementWalker)-1] == L')') {
+ StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL;
+ //
+ // is what remains a file in the CWD or path???
+ //
+ OperationResult = (BOOLEAN)(ShellIsFileInPath(StatementWalker)==EFI_SUCCESS);
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"available");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"profile")) {
+ if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && StatementWalker[StrLen(StatementWalker)-1] == L')') {
+ //
+ // Chop off that ')'
+ //
+ StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL;
+ OperationResult = IsValidProfile(StatementWalker);
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"profile");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else if (StartParameterNumber+1 >= EndParameterNumber) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[StartParameterNumber]);
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ //
+ // must be 'item binop item' style
+ //
+ Compare1 = NULL;
+ Compare2 = NULL;
+ BinOp = OPERATOR_MAX;
+
+ //
+ // get the first item
+ //
+ StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber];
+ if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"efierror")) {
+ TempSpot = StrStr(StatementWalker, L")");
+ if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) {
+ *TempSpot = CHAR_NULL;
+ if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
+ UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT);
+ ASSERT(Compare1 == NULL);
+ Compare1 = StrnCatGrow(&Compare1, NULL, HexString, 0);
+ StatementWalker += StrLen(StatementWalker) + 1;
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"pierror")) {
+ TempSpot = StrStr(StatementWalker, L")");
+ if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) {
+ *TempSpot = CHAR_NULL;
+ if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
+ UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>2));
+ ASSERT(Compare1 == NULL);
+ Compare1 = StrnCatGrow(&Compare1, NULL, HexString, 0);
+ StatementWalker += StrLen(StatementWalker) + 1;
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"oemerror")) {
+ TempSpot = StrStr(StatementWalker, L")");
+ if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) {
+ TempSpot = CHAR_NULL;
+ if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
+ UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>1));
+ ASSERT(Compare1 == NULL);
+ Compare1 = StrnCatGrow(&Compare1, NULL, HexString, 0);
+ StatementWalker += StrLen(StatementWalker) + 1;
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else {
+ ASSERT(Compare1 == NULL);
+ if (EndParameterNumber - StartParameterNumber > 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_STARTING), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[StartParameterNumber+2]);
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ //
+ // must be a raw string
+ //
+ Compare1 = StrnCatGrow(&Compare1, NULL, StatementWalker, 0);
+ }
+ }
+
+ //
+ // get the operator
+ //
+ ASSERT(StartParameterNumber+1<EndParameterNumber);
+ StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber+1];
+ if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"gt")) {
+ BinOp = OPERATOR_GT;
+ } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"lt")) {
+ BinOp = OPERATOR_LT;
+ } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"eq")) {
+ BinOp = OPERATOR_EQ;
+ } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ne")) {
+ BinOp = OPERATOR_NE;
+ } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ge")) {
+ BinOp = OPERATOR_GE;
+ } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"le")) {
+ BinOp = OPERATOR_LE;
+ } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"==")) {
+ BinOp = OPERATOR_EQ;
+ } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ugt")) {
+ BinOp = OPERATOR_UGT;
+ } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ult")) {
+ BinOp = OPERATOR_ULT;
+ } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"uge")) {
+ BinOp = OPERATOR_UGE;
+ } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ule")) {
+ BinOp = OPERATOR_ULE;
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_INVALID_BINOP), gShellLevel1HiiHandle, StatementWalker);
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // get the second item
+ //
+ ASSERT(StartParameterNumber+2<=EndParameterNumber);
+ StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber+2];
+ if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"efierror")) {
+ TempSpot = StrStr(StatementWalker, L")");
+ if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) {
+ TempSpot = CHAR_NULL;
+ if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
+ UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT);
+ ASSERT(Compare2 == NULL);
+ Compare2 = StrnCatGrow(&Compare2, NULL, HexString, 0);
+ StatementWalker += StrLen(StatementWalker) + 1;
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ //
+ // can this be collapsed into the above?
+ //
+ } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"pierror")) {
+ TempSpot = StrStr(StatementWalker, L")");
+ if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) {
+ TempSpot = CHAR_NULL;
+ if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
+ UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>2));
+ ASSERT(Compare2 == NULL);
+ Compare2 = StrnCatGrow(&Compare2, NULL, HexString, 0);
+ StatementWalker += StrLen(StatementWalker) + 1;
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"oemerror")) {
+ TempSpot = StrStr(StatementWalker, L")");
+ if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) {
+ TempSpot = CHAR_NULL;
+ if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
+ UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>1));
+ ASSERT(Compare2 == NULL);
+ Compare2 = StrnCatGrow(&Compare2, NULL, HexString, 0);
+ StatementWalker += StrLen(StatementWalker) + 1;
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else {
+ //
+ // must be a raw string
+ //
+ ASSERT(Compare2 == NULL);
+ Compare2 = StrnCatGrow(&Compare2, NULL, StatementWalker, 0);
+ }
+
+ if (Compare1 != NULL && Compare2 != NULL && BinOp != OPERATOR_MAX) {
+ OperationResult = TestOperation(Compare1, Compare2, BinOp, CaseInsensitive, ForceStringCompare);
+ }
+
+ SHELL_FREE_NON_NULL(Compare1);
+ SHELL_FREE_NON_NULL(Compare2);
+ }
+
+ //
+ // done processing do result...
+ //
+
+ if (!EFI_ERROR(Status)) {
+ if (NotPresent) {
+ OperationResult = (BOOLEAN)(!OperationResult);
+ }
+ switch(OperatorToUse) {
+ case END_TAG_OR:
+ *PassingState = (BOOLEAN)(*PassingState || OperationResult);
+ break;
+ case END_TAG_AND:
+ *PassingState = (BOOLEAN)(*PassingState && OperationResult);
+ break;
+ case END_TAG_MAX:
+ *PassingState = (BOOLEAN)(OperationResult);
+ break;
+ default:
+ ASSERT(FALSE);
+ }
+ }
+ return (Status);
+}
+
+BOOLEAN
+EFIAPI
+BuildNextStatement (
+ IN UINTN ParameterNumber,
+ OUT UINTN *EndParameter,
+ OUT END_TAG_TYPE *EndTag
+ )
+{
+ CHAR16 *Buffer;
+ UINTN BufferSize;
+
+ *EndTag = END_TAG_MAX;
+
+ for(Buffer = NULL, BufferSize = 0
+ ; ParameterNumber < gEfiShellParametersProtocol->Argc
+ ; ParameterNumber++
+ ) {
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ gEfiShellParametersProtocol->Argv[ParameterNumber],
+ L"or") == 0) {
+ *EndParameter = ParameterNumber - 1;
+ *EndTag = END_TAG_OR;
+ break;
+ } else if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ gEfiShellParametersProtocol->Argv[ParameterNumber],
+ L"and") == 0) {
+ *EndParameter = ParameterNumber - 1;
+ *EndTag = END_TAG_AND;
+ break;
+ } else if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ gEfiShellParametersProtocol->Argv[ParameterNumber],
+ L"then") == 0) {
+ *EndParameter = ParameterNumber - 1;
+ *EndTag = END_TAG_THEN;
+ break;
+ }
+ }
+ if (*EndTag == END_TAG_MAX) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+BOOLEAN
+EFIAPI
+MoveToTagSpecial (
+ IN SCRIPT_FILE *ScriptFile
+ )
+{
+ SCRIPT_COMMAND_LIST *CommandNode;
+ BOOLEAN Found;
+ UINTN TargetCount;
+ CHAR16 *CommandName;
+ CHAR16 *CommandWalker;
+ CHAR16 *TempLocation;
+
+ TargetCount = 1;
+ Found = FALSE;
+
+ if (ScriptFile == NULL) {
+ return FALSE;
+ }
+
+ for (CommandNode = (SCRIPT_COMMAND_LIST *)GetNextNode(&ScriptFile->CommandList, &ScriptFile->CurrentCommand->Link), Found = FALSE
+ ; !IsNull(&ScriptFile->CommandList, &CommandNode->Link) && !Found
+ ; CommandNode = (SCRIPT_COMMAND_LIST *)GetNextNode(&ScriptFile->CommandList, &CommandNode->Link)
+ ){
+
+ //
+ // get just the first part of the command line...
+ //
+ CommandName = NULL;
+ CommandName = StrnCatGrow(&CommandName, NULL, CommandNode->Cl, 0);
+ CommandWalker = CommandName;
+ while (CommandWalker[0] == L' ') {
+ CommandWalker++;
+ }
+ TempLocation = StrStr(CommandWalker, L" ");
+
+ if (TempLocation != NULL) {
+ *TempLocation = CHAR_NULL;
+ }
+
+ //
+ // did we find a nested item ?
+ //
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)CommandWalker,
+ L"If") == 0) {
+ TargetCount++;
+ } else if (TargetCount == 1 && gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)CommandWalker,
+ (CHAR16*)L"else") == 0) {
+ //
+ // else can only decrement the last part... not an nested if
+ // hence the TargetCount compare added
+ //
+ TargetCount--;
+ } else if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)CommandWalker,
+ (CHAR16*)L"endif") == 0) {
+ TargetCount--;
+ }
+ if (TargetCount == 0) {
+ ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)GetNextNode(&ScriptFile->CommandList, &CommandNode->Link);
+ Found = TRUE;
+ }
+
+ //
+ // Free the memory for this loop...
+ //
+ SHELL_FREE_NON_NULL(CommandName);
+ }
+ return (Found);
+}
+
+EFI_STATUS
+EFIAPI
+PerformResultOperation (
+ IN CONST BOOLEAN Result
+ )
+{
+ if (Result || MoveToTagSpecial(ShellCommandGetCurrentScriptFile())) {
+ return (EFI_SUCCESS);
+ }
+ return (EFI_NOT_FOUND);
+}
+
+/**
+ Function for 'if' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunIf (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ SHELL_STATUS ShellStatus;
+ BOOLEAN CaseInsensitive;
+ BOOLEAN ForceString;
+ UINTN CurrentParameter;
+ UINTN EndParameter;
+ BOOLEAN CurrentValue;
+ END_TAG_TYPE Ending;
+ END_TAG_TYPE PreviousEnding;
+
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ if (!gEfiShellProtocol->BatchIsActive()) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"If");
+ return (SHELL_UNSUPPORTED);
+ }
+
+ if (gEfiShellParametersProtocol->Argc < 3) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel1HiiHandle);
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ //
+ // Make sure that an End exists.
+ //
+ if (!MoveToTag(GetNextNode, L"endif", L"if", NULL, ShellCommandGetCurrentScriptFile(), TRUE, TRUE, FALSE)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"EnfIf", L"If", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);
+ return (SHELL_DEVICE_ERROR);
+ }
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ CurrentParameter = 1;
+ EndParameter = 0;
+
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ gEfiShellParametersProtocol->Argv[1],
+ L"/i") == 0 ||
+ gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ gEfiShellParametersProtocol->Argv[2],
+ L"/i") == 0 ||
+ (gEfiShellParametersProtocol->Argc > 3 && gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ gEfiShellParametersProtocol->Argv[3],
+ L"/i") == 0)) {
+ CaseInsensitive = TRUE;
+ CurrentParameter++;
+ } else {
+ CaseInsensitive = FALSE;
+ }
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ gEfiShellParametersProtocol->Argv[1],
+ L"/s") == 0 ||
+ gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ gEfiShellParametersProtocol->Argv[2],
+ L"/s") == 0 ||
+ (gEfiShellParametersProtocol->Argc > 3 && gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ gEfiShellParametersProtocol->Argv[3],
+ L"/s") == 0)) {
+ ForceString = TRUE;
+ CurrentParameter++;
+ } else {
+ ForceString = FALSE;
+ }
+
+ for ( ShellStatus = SHELL_SUCCESS, CurrentValue = FALSE, Ending = END_TAG_MAX
+ ; CurrentParameter < gEfiShellParametersProtocol->Argc && ShellStatus == SHELL_SUCCESS
+ ; CurrentParameter++) {
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ gEfiShellParametersProtocol->Argv[CurrentParameter],
+ L"then") == 0) {
+ //
+ // we are at the then
+ //
+ if (CurrentParameter+1 != gEfiShellParametersProtocol->Argc) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TEXT_AFTER_THEN), gShellLevel1HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Status = PerformResultOperation(CurrentValue);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_AFTER_BAD), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[CurrentParameter]);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ }
+ } else {
+ PreviousEnding = Ending;
+ //
+ // build up the next statement for analysis
+ //
+ if (!BuildNextStatement(CurrentParameter, &EndParameter, &Ending)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"Then", L"If", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // Analyze the statement
+ //
+ Status = ProcessStatement(&CurrentValue, CurrentParameter, EndParameter, PreviousEnding, CaseInsensitive, ForceString);
+ if (EFI_ERROR(Status)) {
+// ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_STARTING), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[CurrentParameter]);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // Optomize to get out of the loop early...
+ //
+ if ((Ending == END_TAG_OR && CurrentValue) || (Ending == END_TAG_AND && !CurrentValue)) {
+ Status = PerformResultOperation(CurrentValue);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_AFTER_BAD), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[CurrentParameter]);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ break;
+ }
+ }
+ }
+ if (ShellStatus == SHELL_SUCCESS){
+ CurrentParameter = EndParameter;
+ //
+ // Skip over the or or and parameter.
+ //
+ if (Ending == END_TAG_OR || Ending == END_TAG_AND) {
+ CurrentParameter++;
+ }
+ }
+ }
+ }
+ return (ShellStatus);
+}
+
+/**
+ Function for 'else' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunElse (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ ASSERT_EFI_ERROR(CommandInit());
+
+ if (gEfiShellParametersProtocol->Argc > 1) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle);
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ if (!gEfiShellProtocol->BatchIsActive()) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"Else");
+ return (SHELL_UNSUPPORTED);
+ }
+
+
+ if (!MoveToTag(GetPreviousNode, L"if", L"endif", NULL, ShellCommandGetCurrentScriptFile(), FALSE, TRUE, FALSE)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"If", L"Else", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);
+ return (SHELL_DEVICE_ERROR);
+ }
+ if (!MoveToTag(GetPreviousNode, L"if", L"else", NULL, ShellCommandGetCurrentScriptFile(), FALSE, TRUE, FALSE)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"If", L"Else", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);
+ return (SHELL_DEVICE_ERROR);
+ }
+
+ if (!MoveToTag(GetNextNode, L"endif", L"if", NULL, ShellCommandGetCurrentScriptFile(), FALSE, FALSE, FALSE)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"EndIf", "Else", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);
+ return (SHELL_DEVICE_ERROR);
+ }
+
+ return (SHELL_SUCCESS);
+}
+
+/**
+ Function for 'endif' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunEndIf (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ ASSERT_EFI_ERROR(CommandInit());
+
+ if (gEfiShellParametersProtocol->Argc > 1) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle);
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ if (!gEfiShellProtocol->BatchIsActive()) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"Endif");
+ return (SHELL_UNSUPPORTED);
+ }
+
+ if (!MoveToTag(GetPreviousNode, L"if", L"endif", NULL, ShellCommandGetCurrentScriptFile(), FALSE, TRUE, FALSE)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"If", L"EndIf", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);
+ return (SHELL_DEVICE_ERROR);
+ }
+
+ return (SHELL_SUCCESS);
+}
diff --git a/ShellPkg/Library/UefiShellLevel1CommandsLib/NoOpScriptCommand.c b/ShellPkg/Library/UefiShellLevel1CommandsLib/NoOpScriptCommand.c
new file mode 100644
index 0000000000..85fe582579
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel1CommandsLib/NoOpScriptCommand.c
@@ -0,0 +1,40 @@
+/** @file
+ Main file for else and endif shell level 1 functions. Does nothing really...
+
+ Copyright (c) 2009-2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiShellLevel1CommandsLib.h"
+
+SHELL_STATUS
+EFIAPI
+ShellCommandRunNoOpScriptCommand (
+ VOID *RESERVED
+ )
+{
+ EFI_STATUS Status;
+ //
+ // ASSERT that we can init...
+ //
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // We best be in a script...
+ //
+ ASSERT(gEfiShellProtocol->BatchIsActive());
+
+ //
+ // Do nothing...
+ //
+ return (SHELL_SUCCESS);
+}
+
diff --git a/ShellPkg/Library/UefiShellLevel1CommandsLib/Shift.c b/ShellPkg/Library/UefiShellLevel1CommandsLib/Shift.c
new file mode 100644
index 0000000000..9abb4c31b1
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel1CommandsLib/Shift.c
@@ -0,0 +1,63 @@
+/** @file
+ Main file for Shift shell level 1 function.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiShellLevel1CommandsLib.h"
+
+/**
+ Function for 'shift' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunShift (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ SCRIPT_FILE *CurrentScriptFile;
+ UINTN LoopVar;
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ if (!gEfiShellProtocol->BatchIsActive()) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"Shift");
+ return (SHELL_UNSUPPORTED);
+ }
+
+ CurrentScriptFile = ShellCommandGetCurrentScriptFile();
+ ASSERT(CurrentScriptFile != NULL);
+
+ if (CurrentScriptFile->Argc < 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel1HiiHandle);
+ return (SHELL_UNSUPPORTED);
+ }
+
+ for (LoopVar = 0 ; LoopVar < CurrentScriptFile->Argc ; LoopVar++) {
+ if (LoopVar == 0) {
+ SHELL_FREE_NON_NULL(CurrentScriptFile->Argv[LoopVar]);
+ }
+ if (LoopVar < CurrentScriptFile->Argc -1) {
+ CurrentScriptFile->Argv[LoopVar] = CurrentScriptFile->Argv[LoopVar+1];
+ } else {
+ CurrentScriptFile->Argv[LoopVar] = NULL;
+ }
+ }
+ CurrentScriptFile->Argc--;
+ return (SHELL_SUCCESS);
+}
+
diff --git a/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.c b/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.c
new file mode 100644
index 0000000000..47b6f92864
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.c
@@ -0,0 +1,251 @@
+/** @file
+ Main file for NULL named library for level 1 shell command functions.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiShellLevel1CommandsLib.h"
+
+STATIC CONST CHAR16 mFileName[] = L"ShellCommands";
+EFI_HANDLE gShellLevel1HiiHandle = NULL;
+CONST EFI_GUID gShellLevel1HiiGuid = \
+ { \
+ 0xdec5daa4, 0x6781, 0x4820, { 0x9c, 0x63, 0xa7, 0xb0, 0xe4, 0xf1, 0xdb, 0x31 }
+ };
+
+
+CONST CHAR16*
+EFIAPI
+ShellCommandGetManFileNameLevel1 (
+ VOID
+ )
+{
+ return (mFileName);
+}
+
+/**
+ Constructor for the Shell Level 1 Commands library.
+
+ Install the handlers for level 1 UEFI Shell 2.0 commands.
+
+ @param ImageHandle the image handle of the process
+ @param SystemTable the EFI System Table pointer
+
+ @retval EFI_SUCCESS the shell command handlers were installed sucessfully
+ @retval EFI_UNSUPPORTED the shell level required was not found.
+**/
+EFI_STATUS
+EFIAPI
+ShellLevel1CommandsLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ //
+ // if shell level is less than 2 do nothing
+ //
+ if (PcdGet8(PcdShellSupportLevel) < 1) {
+ return (EFI_UNSUPPORTED);
+ }
+
+ gShellLevel1HiiHandle = HiiAddPackages (&gShellLevel1HiiGuid, gImageHandle, UefiShellLevel1CommandsLibStrings, NULL);
+ if (gShellLevel1HiiHandle == NULL) {
+ return (EFI_DEVICE_ERROR);
+ }
+
+ //
+ // install our shell command handlers that are always installed
+ //
+ ShellCommandRegisterCommandName(L"for", ShellCommandRunFor , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_FOR) ));
+ ShellCommandRegisterCommandName(L"goto", ShellCommandRunGoto , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_GOTO) ));
+ ShellCommandRegisterCommandName(L"if", ShellCommandRunIf , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_IF) ));
+ ShellCommandRegisterCommandName(L"shift", ShellCommandRunShift , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_SHIFT) ));
+ ShellCommandRegisterCommandName(L"exit", ShellCommandRunExit , ShellCommandGetManFileNameLevel1, 1, L"", TRUE , gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_EXIT) ));
+ ShellCommandRegisterCommandName(L"else", ShellCommandRunElse , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_ELSE) ));
+ ShellCommandRegisterCommandName(L"endif", ShellCommandRunEndIf , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_ENDIF) ));
+ ShellCommandRegisterCommandName(L"endfor", ShellCommandRunEndFor , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_ENDFOR)));
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Destructor for the library. free any resources.
+**/
+EFI_STATUS
+EFIAPI
+ShellLevel1CommandsLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ if (gShellLevel1HiiHandle != NULL) {
+ HiiRemovePackages(gShellLevel1HiiHandle);
+ }
+ return (EFI_SUCCESS);
+}
+
+BOOLEAN
+EFIAPI
+TestNodeForMove (
+ IN CONST LIST_MANIP_FUNC Function,
+ IN CONST CHAR16 *DecrementerTag,
+ IN CONST CHAR16 *IncrementerTag,
+ IN CONST CHAR16 *Label OPTIONAL,
+ IN SCRIPT_FILE *ScriptFile,
+ IN CONST BOOLEAN MovePast,
+ IN CONST BOOLEAN FindOnly,
+ IN CONST SCRIPT_COMMAND_LIST *CommandNode,
+ IN UINTN *TargetCount
+ )
+{
+ BOOLEAN Found;
+ CHAR16 *CommandName;
+ CHAR16 *CommandNameWalker;
+ CHAR16 *TempLocation;
+
+ Found = FALSE;
+
+ //
+ // get just the first part of the command line...
+ //
+ CommandName = NULL;
+ CommandName = StrnCatGrow(&CommandName, NULL, CommandNode->Cl, 0);
+ CommandNameWalker = CommandName;
+ while(CommandNameWalker[0] == L' ') {
+ CommandNameWalker++;
+ }
+ TempLocation = StrStr(CommandNameWalker, L" ");
+
+ if (TempLocation != NULL) {
+ *TempLocation = CHAR_NULL;
+ }
+
+ //
+ // did we find a nested item ?
+ //
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)CommandNameWalker,
+ (CHAR16*)IncrementerTag) == 0) {
+ (*TargetCount)++;
+ } else if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)CommandNameWalker,
+ (CHAR16*)DecrementerTag) == 0) {
+ if (*TargetCount > 0) {
+ (*TargetCount)--;
+ }
+ }
+
+ //
+ // did we find the matching one...
+ //
+ if (Label == NULL) {
+ if (*TargetCount == 0) {
+ Found = TRUE;
+ if (!FindOnly) {
+ if (MovePast) {
+ ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)(*Function)(&ScriptFile->CommandList, &CommandNode->Link);
+ } else {
+ ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)CommandNode;
+ }
+ }
+ }
+ } else {
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)CommandNameWalker,
+ (CHAR16*)Label) == 0
+ && (*TargetCount) == 0) {
+ Found = TRUE;
+ if (!FindOnly) {
+ //
+ // we found the target label without loops
+ //
+ if (MovePast) {
+ ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)(*Function)(&ScriptFile->CommandList, &CommandNode->Link);
+ } else {
+ ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)CommandNode;
+ }
+ }
+ }
+ }
+
+ //
+ // Free the memory for this loop...
+ //
+ FreePool(CommandName);
+ return (Found);
+}
+
+BOOLEAN
+EFIAPI
+MoveToTag (
+ IN CONST LIST_MANIP_FUNC Function,
+ IN CONST CHAR16 *DecrementerTag,
+ IN CONST CHAR16 *IncrementerTag,
+ IN CONST CHAR16 *Label OPTIONAL,
+ IN SCRIPT_FILE *ScriptFile,
+ IN CONST BOOLEAN MovePast,
+ IN CONST BOOLEAN FindOnly,
+ IN CONST BOOLEAN WrapAroundScript
+ )
+{
+ SCRIPT_COMMAND_LIST *CommandNode;
+ BOOLEAN Found;
+ UINTN TargetCount;
+
+ if (Label == NULL) {
+ TargetCount = 1;
+ } else {
+ TargetCount = 0;
+ }
+
+ if (ScriptFile == NULL) {
+ return FALSE;
+ }
+
+ for (CommandNode = (SCRIPT_COMMAND_LIST *)(*Function)(&ScriptFile->CommandList, &ScriptFile->CurrentCommand->Link), Found = FALSE
+ ; !IsNull(&ScriptFile->CommandList, &CommandNode->Link)&& !Found
+ ; CommandNode = (SCRIPT_COMMAND_LIST *)(*Function)(&ScriptFile->CommandList, &CommandNode->Link)
+ ){
+ Found = TestNodeForMove(
+ Function,
+ DecrementerTag,
+ IncrementerTag,
+ Label,
+ ScriptFile,
+ MovePast,
+ FindOnly,
+ CommandNode,
+ &TargetCount);
+ }
+
+ if (WrapAroundScript && !Found) {
+ for (CommandNode = (SCRIPT_COMMAND_LIST *)GetFirstNode(&ScriptFile->CommandList), Found = FALSE
+ ; CommandNode != ScriptFile->CurrentCommand && !Found
+ ; CommandNode = (SCRIPT_COMMAND_LIST *)(*Function)(&ScriptFile->CommandList, &CommandNode->Link)
+ ){
+ Found = TestNodeForMove(
+ Function,
+ DecrementerTag,
+ IncrementerTag,
+ Label,
+ ScriptFile,
+ MovePast,
+ FindOnly,
+ CommandNode,
+ &TargetCount);
+ }
+ }
+ return (Found);
+}
+
diff --git a/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.h b/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.h
new file mode 100644
index 0000000000..b0aa51bc1b
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.h
@@ -0,0 +1,182 @@
+/** @file
+ Main file for NULL named library for level 1 shell command functions.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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 <Uefi.h>
+#include <ShellBase.h>
+
+#include <Protocol/EfiShell.h>
+#include <Protocol/EfiShellParameters.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/UnicodeCollation.h>
+#include <Protocol/DevicePathToText.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/ShellCommandLib.h>
+#include <Library/ShellLib.h>
+#include <Library/SortLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HiiLib.h>
+#include <Library/FileHandleLib.h>
+
+extern EFI_HANDLE gShellLevel1HiiHandle;
+extern CONST EFI_GUID gShellLevel1HiiGuid;
+
+/**
+ Function for 'exit' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunExit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'endif' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunEndIf (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'for' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunFor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'endfor' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunEndFor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'if' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunIf (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'goto' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunGoto (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'shift' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunShift (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+
+/**
+ Function for 'else' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunElse (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+///
+/// Function prototype for BOTH GetNextNode and GetPreviousNode...
+/// This is used to control the MoveToTag function direction...
+///
+typedef
+LIST_ENTRY *
+(EFIAPI *LIST_MANIP_FUNC)(
+ IN CONST LIST_ENTRY *List,
+ IN CONST LIST_ENTRY *Node
+ );
+
+/**
+ Function to move to a spacified tag in a script file structure.
+
+ @param[in] Function The pointer to the function to move with.
+ @param[in] DecrementerTag The pointer to a string to decrement upon finding.
+ @param[in] IncrementerTag The pointer to a string to increment upon finding.
+ @param[in] Label A Label to look for.
+ @param[in] ScriptFile The script file structure to look in.
+ @param[in] MovePast TRUE to go to the element just after the found one. FALSE otherwise.
+ @param[in] FindOnly FALSE to change the execution point in the script file structure. TRUE otherwise.
+ @param[in] WrapAroundScript TRUE to go to begining when end is hit, or vise versa. FALSE otherwise.
+**/
+BOOLEAN
+EFIAPI
+MoveToTag (
+ IN CONST LIST_MANIP_FUNC Function,
+ IN CONST CHAR16 *DecrementerTag,
+ IN CONST CHAR16 *IncrementerTag,
+ IN CONST CHAR16 *Label OPTIONAL,
+ IN SCRIPT_FILE *ScriptFile,
+ IN CONST BOOLEAN MovePast,
+ IN CONST BOOLEAN FindOnly,
+ IN CONST BOOLEAN WrapAroundScript
+ );
+
diff --git a/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf b/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf
new file mode 100644
index 0000000000..b4697f3908
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf
@@ -0,0 +1,54 @@
+## @file
+# Provides shell level 1 functions
+#
+# Copyright (c) 2009-2010, Intel Corporation. All rights reserved. <BR>
+#
+# 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 = UefiShellLevel1CommandsLib
+ FILE_GUID = 50cb6037-1102-47af-b2dd-9944b6eb1abe
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER
+ CONSTRUCTOR = ShellLevel1CommandsLibConstructor
+ DESTRUCTOR = ShellLevel1CommandsLibDestructor
+
+[Sources.common]
+ UefiShellLevel1CommandsLib.c
+ UefiShellLevel1CommandsLib.h
+ UefiShellLevel1CommandsLib.uni
+ Exit.c
+ Goto.c
+ If.c
+ For.c
+ Shift.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ ShellCommandLib
+ ShellLib
+ UefiLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ SortLib
+ PrintLib
+
+[Pcd.common]
+ gEfiShellPkgTokenSpaceGuid.PcdShellSupportLevel # ALWAYS_CONSUMED
diff --git a/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.uni b/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.uni
new file mode 100644
index 0000000000..7043b48ad5
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.uni
Binary files differ
diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/Attrib.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/Attrib.c
new file mode 100644
index 0000000000..c891ca6afa
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/Attrib.c
@@ -0,0 +1,271 @@
+/** @file
+ Main file for attrib shell level 2 function.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiShellLevel2CommandsLib.h"
+
+STATIC CONST CHAR16 AllFiles[] = L"*";
+
+STATIC CONST SHELL_PARAM_ITEM AttribParamList[] = {
+ {L"-a", TypeFlag},
+ {L"+a", TypeFlag},
+ {L"-s", TypeFlag},
+ {L"+s", TypeFlag},
+ {L"-h", TypeFlag},
+ {L"+h", TypeFlag},
+ {L"-r", TypeFlag},
+ {L"+r", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'attrib' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunAttrib (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ UINT64 FileAttributesToAdd;
+ UINT64 FileAttributesToRemove;
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ UINTN ParamNumberCount;
+ CONST CHAR16 *FileName;
+ EFI_SHELL_FILE_INFO *ListOfFiles;
+ EFI_SHELL_FILE_INFO *FileNode;
+ EFI_FILE_INFO *FileInfo;
+
+ ListOfFiles = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ ProblemParam = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (AttribParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ } else {
+ FileAttributesToAdd = 0;
+ FileAttributesToRemove = 0;
+
+ //
+ // apply or remove each flag
+ //
+ if (ShellCommandLineGetFlag(Package, L"+a")) {
+ FileAttributesToAdd |= EFI_FILE_ARCHIVE;
+ }
+ if (ShellCommandLineGetFlag(Package, L"-a")) {
+ FileAttributesToRemove |= EFI_FILE_ARCHIVE;
+ }
+ if (ShellCommandLineGetFlag(Package, L"+s")) {
+ FileAttributesToAdd |= EFI_FILE_SYSTEM;
+ }
+ if (ShellCommandLineGetFlag(Package, L"-s")) {
+ FileAttributesToRemove |= EFI_FILE_SYSTEM;
+ }
+ if (ShellCommandLineGetFlag(Package, L"+h")) {
+ FileAttributesToAdd |= EFI_FILE_HIDDEN;
+ }
+ if (ShellCommandLineGetFlag(Package, L"-h")) {
+ FileAttributesToRemove |= EFI_FILE_HIDDEN;
+ }
+ if (ShellCommandLineGetFlag(Package, L"+r")) {
+ FileAttributesToAdd |= EFI_FILE_READ_ONLY;
+ }
+ if (ShellCommandLineGetFlag(Package, L"-r")) {
+ FileAttributesToRemove |= EFI_FILE_READ_ONLY;
+ }
+
+ if (FileAttributesToRemove == 0 && FileAttributesToAdd == 0) {
+ //
+ // Do display as we have no attributes to change
+ //
+ for ( ParamNumberCount = 1
+ ;
+ ; ParamNumberCount++
+ ){
+ FileName = ShellCommandLineGetRawValue(Package, ParamNumberCount);
+ // if we dont have anything left, move on...
+ if (FileName == NULL && ParamNumberCount == 1) {
+ FileName = (CHAR16*)AllFiles;
+ } else if (FileName == NULL) {
+ break;
+ }
+ ASSERT(ListOfFiles == NULL);
+ Status = ShellOpenFileMetaArg((CHAR16*)FileName, EFI_FILE_MODE_READ, &ListOfFiles);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, ParamNumberCount));
+ ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ for (FileNode = (EFI_SHELL_FILE_INFO*)GetFirstNode(&ListOfFiles->Link)
+ ; !IsNull(&ListOfFiles->Link, &FileNode->Link)
+ ; FileNode = (EFI_SHELL_FILE_INFO*)GetNextNode(&ListOfFiles->Link, &FileNode->Link)
+ ){
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_ATTRIB_OUTPUT_LINE),
+ gShellLevel2HiiHandle,
+ FileNode->Info->Attribute&EFI_FILE_DIRECTORY? L'D':L' ',
+ FileNode->Info->Attribute&EFI_FILE_ARCHIVE? L'A':L' ',
+ FileNode->Info->Attribute&EFI_FILE_SYSTEM? L'S':L' ',
+ FileNode->Info->Attribute&EFI_FILE_HIDDEN? L'H':L' ',
+ FileNode->Info->Attribute&EFI_FILE_READ_ONLY? L'R':L' ',
+ FileNode->FileName
+ );
+ }
+ Status = ShellCloseFileMetaArg(&ListOfFiles);
+ ListOfFiles = NULL;
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_CLOSE_FAIL), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, ParamNumberCount));
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ } // for loop for handling wildcard filenames
+ } // for loop for printing out the info
+ } else if ((FileAttributesToRemove & FileAttributesToAdd) != 0) {
+ //
+ // fail as we have conflcting params.
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // enumerate through all the files/directories and apply the attributes
+ //
+ for ( ParamNumberCount = 1
+ ;
+ ; ParamNumberCount++
+ ){
+ FileName = ShellCommandLineGetRawValue(Package, ParamNumberCount);
+ // if we dont have anything left, move on...
+ if (FileName == NULL) {
+ //
+ // make sure we are not failing on the first one we do... if yes that's an error...
+ //
+ if (ParamNumberCount == 1) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ break;
+ }
+
+ //
+ // OpenFileByName / GetFileInfo / Change attributes / SetFileInfo / CloseFile / free memory
+ // for each file or directory on the line.
+ //
+
+ //
+ // Open the file(s)
+ //
+ ASSERT(ListOfFiles == NULL);
+ Status = ShellOpenFileMetaArg((CHAR16*)FileName, EFI_FILE_MODE_READ, &ListOfFiles);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, ParamNumberCount));
+ ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ for (FileNode = (EFI_SHELL_FILE_INFO*)GetFirstNode(&ListOfFiles->Link)
+ ; !IsNull(&ListOfFiles->Link, &FileNode->Link)
+ ; FileNode = (EFI_SHELL_FILE_INFO*)GetNextNode(&ListOfFiles->Link, &FileNode->Link)
+ ){
+ //
+ // skip the directory traversing stuff...
+ //
+ if (StrCmp(FileNode->FileName, L".") == 0 || StrCmp(FileNode->FileName, L"..") == 0) {
+ continue;
+ }
+
+ FileInfo = gEfiShellProtocol->GetFileInfo(FileNode->Handle);
+
+ //
+ // if we are removing Read-Only we need to do that alone
+ //
+ if ((FileAttributesToRemove & EFI_FILE_READ_ONLY) == EFI_FILE_READ_ONLY) {
+ FileInfo->Attribute &= ~EFI_FILE_READ_ONLY;
+ //
+ // SetFileInfo
+ //
+ Status = ShellSetFileInfo(FileNode->Handle, FileInfo);
+ if (EFI_ERROR(Status)) {;
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_AD), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, ParamNumberCount));
+ ShellStatus = SHELL_ACCESS_DENIED;
+ }
+ }
+
+ //
+ // change the attribute
+ //
+ FileInfo->Attribute &= ~FileAttributesToRemove;
+ FileInfo->Attribute |= FileAttributesToAdd;
+
+ //
+ // SetFileInfo
+ //
+ Status = ShellSetFileInfo(FileNode->Handle, FileInfo);
+ if (EFI_ERROR(Status)) {;
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_AD), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, ParamNumberCount));
+ ShellStatus = SHELL_ACCESS_DENIED;
+ }
+
+ SHELL_FREE_NON_NULL(FileInfo);
+ }
+ Status = ShellCloseFileMetaArg(&ListOfFiles);
+ ListOfFiles = NULL;
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_CLOSE_FAIL), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, ParamNumberCount));
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ } // for loop for handling wildcard filenames
+ }
+ }
+ }
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+
+ //
+ // return the status
+ //
+ return (ShellStatus);
+}
diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c
new file mode 100644
index 0000000000..78403c2274
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c
@@ -0,0 +1,218 @@
+/** @file
+ Main file for attrib shell level 2 function.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiShellLevel2CommandsLib.h"
+
+/**
+ Function for 'cd' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunCd (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CONST CHAR16 *Directory;
+ CHAR16 *Path;
+ CHAR16 *Drive;
+ UINTN DriveSize;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ SHELL_FILE_HANDLE Handle;
+ CONST CHAR16 *Param1;
+
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ Drive = NULL;
+ DriveSize = 0;
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ }
+
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ } else if (ShellCommandLineGetRawValue(Package, 2) != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // remember that param 0 is the command name
+ // If there are 0 value parameters, then print the current directory
+ // else If there are 2 value parameters, then print the error message
+ // else If there is 1 value paramerer , then change the directory
+ //
+ Param1 = ShellCommandLineGetRawValue(Package, 1);
+ if (Param1 == NULL) {
+ //
+ // display the current directory
+ //
+ Directory = ShellGetCurrentDir(NULL);
+ if (Directory != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_PRINT), gShellLevel2HiiHandle, Directory);
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ } else {
+ if (StrCmp(Param1, L".") == 0) {
+ //
+ // nothing to do... change to current directory
+ //
+ } else if (StrCmp(Param1, L"..") == 0) {
+ //
+ // Change up one directory...
+ //
+ Directory = ShellGetCurrentDir(NULL);
+ if (Directory == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ Drive = GetFullyQualifiedPath(Directory);
+ ChopLastSlash(Drive);
+ }
+ if (ShellStatus == SHELL_SUCCESS && Drive != NULL) {
+ //
+ // change directory on current drive letter
+ //
+ Status = gEfiShellProtocol->SetCurDir(NULL, Drive);
+ if (Status == EFI_NOT_FOUND) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ }
+ } else if (StrCmp(Param1, L"\\") == 0) {
+ //
+ // Move to root of current drive
+ //
+ Directory = ShellGetCurrentDir(NULL);
+ if (Directory == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ Drive = GetFullyQualifiedPath(Directory);
+ while (ChopLastSlash(Drive)) ;
+ }
+ if (ShellStatus == SHELL_SUCCESS && Drive != NULL) {
+ //
+ // change directory on current drive letter
+ //
+ Status = gEfiShellProtocol->SetCurDir(NULL, Drive);
+ if (Status == EFI_NOT_FOUND) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ }
+ } else if (StrStr(Param1, L":") == NULL) {
+ if (ShellGetCurrentDir(NULL) == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ ASSERT((Drive == NULL && DriveSize == 0) || (Drive != NULL));
+ Drive = StrnCatGrow(&Drive, &DriveSize, ShellGetCurrentDir(NULL), 0);
+ if (*Param1 == L'\\') {
+ while (ChopLastSlash(Drive)) ;
+ Drive = StrnCatGrow(&Drive, &DriveSize, Param1+1, 0);
+ } else {
+ Drive = StrnCatGrow(&Drive, &DriveSize, Param1, 0);
+ }
+ //
+ // Verify that this is a valid directory
+ //
+ Status = gEfiShellProtocol->OpenFileByName(Drive, &Handle, EFI_FILE_MODE_READ);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, Drive);
+ ShellStatus = SHELL_NOT_FOUND;
+ } else if (EFI_ERROR(FileHandleIsDirectory(Handle))) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, Drive);
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ if (ShellStatus == SHELL_SUCCESS && Drive != NULL) {
+ //
+ // change directory on current drive letter
+ //
+ Status = gEfiShellProtocol->SetCurDir(NULL, Drive);
+ if (Status == EFI_NOT_FOUND) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ }
+ if (Handle != NULL) {
+ gEfiShellProtocol->CloseFile(Handle);
+ DEBUG_CODE(Handle = NULL;);
+ }
+ }
+ } else {
+ //
+ // change directory on other drive letter
+ //
+ Drive = AllocateZeroPool(StrSize(Param1));
+ Drive = StrCpy(Drive, Param1);
+ Path = StrStr(Drive, L":");
+ *(++Path) = CHAR_NULL;
+ Status = gEfiShellProtocol->SetCurDir(Drive, ++Path);
+
+ if (Status == EFI_NOT_FOUND) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle);
+ Status = SHELL_NOT_FOUND;
+ } else if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, Param1);
+ Status = SHELL_NOT_FOUND;
+ }
+ }
+ }
+ }
+
+ if (Drive != NULL) {
+ FreePool(Drive);
+ }
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+
+ //
+ // return the status
+ //
+ return (ShellStatus);
+}
+
diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c
new file mode 100644
index 0000000000..e35bf18824
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c
@@ -0,0 +1,599 @@
+/** @file
+ Main file for cp shell level 2 function.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiShellLevel2CommandsLib.h"
+
+// this is later in the file.
+SHELL_STATUS
+EFIAPI
+ValidateAndCopyFiles(
+ IN CONST EFI_SHELL_FILE_INFO *FileList,
+ IN CONST CHAR16 *DestDir,
+ IN BOOLEAN SilentMode,
+ IN BOOLEAN RecursiveMode,
+ IN VOID **Resp
+ );
+
+/**
+ Function to Copy one file to another location
+
+ If the destination exists the user will be prompted and the result put into *resp
+
+ @param[in] Source pointer to source file name
+ @param[in] Dest pointer to destination file name
+ @param[out] Resp pointer to response from question. Pass back on looped calling
+ @param[in] SilentMode whether to run in quiet mode or not
+
+ @retval SHELL_SUCCESS The source file was copied to the destination
+**/
+SHELL_STATUS
+EFIAPI
+CopySingleFile(
+ IN CONST CHAR16 *Source,
+ IN CONST CHAR16 *Dest,
+ OUT VOID **Resp,
+ IN BOOLEAN SilentMode
+ )
+{
+ VOID *Response;
+ UINTN ReadSize;
+ SHELL_FILE_HANDLE SourceHandle;
+ SHELL_FILE_HANDLE DestHandle;
+ EFI_STATUS Status;
+ VOID *Buffer;
+ CHAR16 *TempName;
+ UINTN Size;
+ EFI_SHELL_FILE_INFO *List;
+ SHELL_STATUS ShellStatus;
+
+
+ ASSERT(Resp != NULL);
+
+ SourceHandle = NULL;
+ DestHandle = NULL;
+ Response = *Resp;
+ List = NULL;
+
+ ReadSize = PcdGet16(PcdShellFileOperationSize);
+ // Why bother copying a file to itself
+ if (StrCmp(Source, Dest) == 0) {
+ return (SHELL_SUCCESS);
+ }
+
+ //
+ // Open destination file without create
+ //
+ Status = ShellOpenFileByName(Dest, &DestHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0);
+
+ //
+ // close file
+ //
+ if (DestHandle != NULL) {
+ ShellCloseFile(&DestHandle);
+ DestHandle = NULL;
+ }
+
+ //
+ // if the destination file existed check response and possibly prompt user
+ //
+ if (!EFI_ERROR(Status)) {
+ if (Response == NULL && !SilentMode) {
+ Status = ShellPromptForResponseHii(ShellPromptResponseTypeYesNoAllCancel, STRING_TOKEN (STR_CP_PROMPT), gShellLevel2HiiHandle, &Response);
+ }
+ //
+ // possibly return based on response
+ //
+ if (!SilentMode) {
+ switch (*(SHELL_PROMPT_RESPONSE*)Response) {
+ case ShellPromptResponseNo:
+ //
+ // return success here so we dont stop the process
+ //
+ return (SHELL_SUCCESS);
+ case ShellPromptResponseCancel:
+ *Resp = Response;
+ //
+ // indicate to stop everything
+ //
+ return (SHELL_ABORTED);
+ case ShellPromptResponseAll:
+ *Resp = Response;
+ case ShellPromptResponseYes:
+ break;
+ }
+ }
+ }
+
+ if (ShellIsDirectory(Source) == EFI_SUCCESS) {
+ Status = ShellCreateDirectory(Dest, &DestHandle);
+ if (EFI_ERROR(Status)) {
+ return (SHELL_ACCESS_DENIED);
+ }
+
+ //
+ // Now copy all the files under the directory...
+ //
+ TempName = NULL;
+ Size = 0;
+ StrnCatGrow(&TempName, &Size, Source, 0);
+ StrnCatGrow(&TempName, &Size, L"\\*", 0);
+ ShellOpenFileMetaArg((CHAR16*)TempName, EFI_FILE_MODE_READ, &List);
+ TempName = NULL;
+ StrnCatGrow(&TempName, &Size, Dest, 0);
+ StrnCatGrow(&TempName, &Size, L"\\", 0);
+ ShellStatus = ValidateAndCopyFiles(List, TempName, SilentMode, TRUE, Resp);
+ ShellCloseFileMetaArg(&List);
+ FreePool(TempName);
+ Size = 0;
+ } else {
+ //
+ // open file with create enabled
+ //
+ Status = ShellOpenFileByName(Dest, &DestHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
+ if (EFI_ERROR(Status)) {
+ return (SHELL_ACCESS_DENIED);
+ }
+
+ //
+ // open source file
+ //
+ Status = ShellOpenFileByName(Source, &SourceHandle, EFI_FILE_MODE_READ, 0);
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // copy data between files
+ //
+ Buffer = AllocateZeroPool(ReadSize);
+ ASSERT(Buffer != NULL);
+ while (ReadSize == PcdGet16(PcdShellFileOperationSize) && !EFI_ERROR(Status)) {
+ Status = ShellReadFile(SourceHandle, &ReadSize, Buffer);
+ ASSERT_EFI_ERROR(Status);
+ Status = ShellWriteFile(DestHandle, &ReadSize, Buffer);
+ }
+ }
+
+ //
+ // close files
+ //
+ if (DestHandle != NULL) {
+ ShellCloseFile(&DestHandle);
+ DestHandle = NULL;
+ }
+ if (SourceHandle != NULL) {
+ ShellCloseFile(&SourceHandle);
+ SourceHandle = NULL;
+ }
+
+ //
+ // return
+ //
+ return (SHELL_SUCCESS);
+}
+
+/**
+ function to take a list of files to copy and a destination location and do
+ the verification and copying of those files to that location. This function
+ will report any errors to the user and halt.
+
+ The key is to have this function called ONLY once. this allows for the parameter
+ verification to happen correctly.
+
+ @param[in] FileList A LIST_ENTRY* based list of files to move
+ @param[in] DestDir the destination location
+
+ @retval SHELL_SUCCESS the files were all moved.
+ @retval SHELL_INVALID_PARAMETER a parameter was invalid
+ @retval SHELL_SECURITY_VIOLATION a security violation ocurred
+ @retval SHELL_WRITE_PROTECTED the destination was write protected
+ @retval SHELL_OUT_OF_RESOURCES a memory allocation failed
+**/
+SHELL_STATUS
+EFIAPI
+ValidateAndCopyFiles(
+ IN CONST EFI_SHELL_FILE_INFO *FileList,
+ IN CONST CHAR16 *DestDir,
+ IN BOOLEAN SilentMode,
+ IN BOOLEAN RecursiveMode,
+ IN VOID **Resp
+ )
+{
+ CHAR16 *HiiOutput;
+ CHAR16 *HiiResultOk;
+ CONST EFI_SHELL_FILE_INFO *Node;
+ SHELL_STATUS ShellStatus;
+ CHAR16 *DestPath;
+ VOID *Response;
+ UINTN PathLen;
+ CONST CHAR16 *Cwd;
+ CONST CHAR16 *TempLocation;
+ UINTN NewSize;
+
+ if (Resp == NULL) {
+ Response = NULL;
+ } else {
+ Response = *Resp;
+ }
+
+ DestPath = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ PathLen = 0;
+ Cwd = ShellGetCurrentDir(NULL);
+
+ ASSERT(FileList != NULL);
+ ASSERT(DestDir != NULL);
+
+ //
+ // If we are trying to copy multiple files... make sure we got a directory for the target...
+ //
+ if (EFI_ERROR(ShellIsDirectory(DestDir)) && FileList->Link.ForwardLink != FileList->Link.BackLink) {
+ //
+ // Error for destination not a directory
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, DestDir);
+ return (SHELL_INVALID_PARAMETER);
+ }
+ for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link)
+ ; !IsNull(&FileList->Link, &Node->Link)
+ ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link)
+ ){
+ //
+ // skip the directory traversing stuff...
+ //
+ if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) {
+ continue;
+ }
+
+ NewSize = StrSize(DestDir);
+ NewSize += StrSize(Node->FileName);
+ NewSize += StrSize(Cwd);
+ if (NewSize > PathLen) {
+ PathLen = NewSize;
+ }
+
+ //
+ // Make sure got -r if required
+ //
+ if (!RecursiveMode && !EFI_ERROR(ShellIsDirectory(Node->FullName))) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DIR_REQ), gShellLevel2HiiHandle);
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ //
+ // make sure got dest as dir if needed
+ //
+ if (!EFI_ERROR(ShellIsDirectory(Node->FullName)) && EFI_ERROR(ShellIsDirectory(DestDir))) {
+ //
+ // Error for destination not a directory
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, DestDir);
+ return (SHELL_INVALID_PARAMETER);
+ }
+ }
+
+ HiiOutput = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_CP_OUTPUT), NULL);
+ HiiResultOk = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_GEN_RES_OK), NULL);
+ DestPath = AllocatePool(PathLen);
+
+ //
+ // Go through the list of files to copy...
+ //
+ for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link)
+ ; !IsNull(&FileList->Link, &Node->Link)
+ ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link)
+ ){
+ if (ShellGetExecutionBreakFlag()) {
+ break;
+ }
+ ASSERT(Node->FileName != NULL);
+ ASSERT(Node->FullName != NULL);
+
+ //
+ // skip the directory traversing stuff...
+ //
+ if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) {
+ continue;
+ }
+
+ if (FileList->Link.ForwardLink == FileList->Link.BackLink // 1 item
+ && EFI_ERROR(ShellIsDirectory(DestDir)) // not an existing directory
+ ) {
+ ASSERT(StrStr(DestDir, L":") == NULL);
+ //
+ // simple copy of a single file
+ //
+ StrCpy(DestPath, Cwd);
+ if (DestPath[StrLen(DestPath)-1] != L'\\' && DestDir[0] != L'\\') {
+ StrCat(DestPath, L"\\");
+ } else if (DestPath[StrLen(DestPath)-1] == L'\\' && DestDir[0] == L'\\') {
+ ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL;
+ }
+ StrCat(DestPath, DestDir);
+ } else {
+ //
+ // we have multiple files or a directory in the DestDir
+ //
+ if (StrStr(DestDir, L":") == NULL) {
+ StrCpy(DestPath, Cwd);
+ if (DestPath[StrLen(DestPath)-1] != L'\\' && DestDir[0] != L'\\') {
+ StrCat(DestPath, L"\\");
+ } else if (DestPath[StrLen(DestPath)-1] == L'\\' && DestDir[0] == L'\\') {
+ ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL;
+ }
+ StrCat(DestPath, DestDir);
+ if (DestDir[StrLen(DestDir)-1] != L'\\' && Node->FileName[0] != L'\\') {
+ StrCat(DestPath, L"\\");
+ } else if (DestDir[StrLen(DestDir)-1] == L'\\' && Node->FileName[0] == L'\\') {
+ ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL;
+ }
+ StrCat(DestPath, Node->FileName);
+
+ } else {
+ StrCpy(DestPath, DestDir);
+ if (DestDir[StrLen(DestDir)-1] != L'\\' && Node->FileName[0] != L'\\') {
+ StrCat(DestPath, L"\\");
+ } else if (DestDir[StrLen(DestDir)-1] == L'\\' && Node->FileName[0] == L'\\') {
+ ((CHAR16*)DestDir)[StrLen(DestDir)-1] = CHAR_NULL;
+ }
+ StrCat(DestPath, Node->FileName);
+ }
+ }
+
+ //
+ // Make sure the path exists
+ //
+ if (EFI_ERROR(VerifyIntermediateDirectories(DestPath))) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DIR_WNF), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_DEVICE_ERROR;
+ break;
+ }
+
+ if ( !EFI_ERROR(ShellIsDirectory(Node->FullName))
+ && !EFI_ERROR(ShellIsDirectory(DestPath))
+ && StrniCmp(Node->FullName, DestPath, StrLen(DestPath)) == NULL
+ ){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_PARENT), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ break;
+ }
+ if (StringNoCaseCompare(&Node->FullName, &DestPath) == 0) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_SAME), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ break;
+ }
+
+ if ((TempLocation = StrniCmp(Node->FullName, DestPath, StrLen(Node->FullName))) == 0
+ && (DestPath[StrLen(Node->FullName)] == CHAR_NULL || DestPath[StrLen(Node->FullName)] == L'\\')
+ ) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_SAME), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ break;
+ }
+
+ CleanPath(DestPath);
+
+ ShellPrintEx(-1, -1, HiiOutput, Node->FullName, DestPath);
+
+ //
+ // copy single file...
+ //
+ ShellStatus = CopySingleFile(Node->FullName, DestPath, &Response, SilentMode);
+ if (ShellStatus != SHELL_SUCCESS) {
+ break;
+ }
+ }
+ if (ShellStatus == SHELL_SUCCESS && Resp == NULL) {
+ ShellPrintEx(-1, -1, L"%s", HiiResultOk);
+ }
+
+ SHELL_FREE_NON_NULL(DestPath);
+ SHELL_FREE_NON_NULL(HiiOutput);
+ SHELL_FREE_NON_NULL(HiiResultOk);
+ if (Resp != NULL) {
+ SHELL_FREE_NON_NULL(Response);
+ }
+
+ return (ShellStatus);
+}
+
+SHELL_STATUS
+EFIAPI
+ProcessValidateAndCopyFiles(
+ IN EFI_SHELL_FILE_INFO *FileList,
+ IN CONST CHAR16 *DestDir,
+ IN BOOLEAN SilentMode,
+ IN BOOLEAN RecursiveMode
+ )
+{
+ SHELL_STATUS ShellStatus;
+ EFI_SHELL_FILE_INFO *List;
+ EFI_STATUS Status;
+ EFI_FILE_INFO *FileInfo;
+
+ List = NULL;
+
+ Status = ShellOpenFileMetaArg((CHAR16*)DestDir, EFI_FILE_MODE_READ, &List);
+ if (List != NULL && List->Link.ForwardLink != List->Link.BackLink) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_MARG_ERROR), gShellLevel2HiiHandle, DestDir);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ ShellCloseFileMetaArg(&List);
+ } else if (List != NULL) {
+ ASSERT(List != NULL);
+ ASSERT(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink) != NULL);
+ ASSERT(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->FullName != NULL);
+ FileInfo = NULL;
+ FileInfo = gEfiShellProtocol->GetFileInfo(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->Handle);
+ ASSERT(FileInfo != NULL);
+ if ((FileInfo->Attribute & EFI_FILE_READ_ONLY) == 0) {
+ ShellStatus = ValidateAndCopyFiles(FileList, ((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->FullName, SilentMode, RecursiveMode, NULL);
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DEST_ERROR), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_ACCESS_DENIED;
+ }
+ SHELL_FREE_NON_NULL(FileInfo);
+ ShellCloseFileMetaArg(&List);
+ } else {
+ ShellStatus = ValidateAndCopyFiles(FileList, DestDir, SilentMode, RecursiveMode, NULL);
+ }
+
+ return (ShellStatus);
+}
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-r", TypeFlag},
+ {L"-q", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'cp' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunCp (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ UINTN ParamCount;
+ UINTN LoopCounter;
+ EFI_SHELL_FILE_INFO *FileList;
+ BOOLEAN SilentMode;
+ BOOLEAN RecursiveMode;
+ CONST CHAR16 *Cwd;
+
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ ParamCount = 0;
+ FileList = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ }
+
+ //
+ // Initialize SilentMode and RecursiveMode
+ //
+ if (gEfiShellProtocol->BatchIsActive()) {
+ SilentMode = TRUE;
+ } else {
+ SilentMode = ShellCommandLineGetFlag(Package, L"-q");
+ }
+ RecursiveMode = ShellCommandLineGetFlag(Package, L"-r");
+
+ switch (ParamCount = ShellCommandLineGetCount(Package)) {
+ case 0:
+ case 1:
+ //
+ // we have insufficient parameters
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ break;
+ case 2:
+ //
+ // must have valid CWD for single parameter...
+ //
+ Cwd = ShellGetCurrentDir(NULL);
+ if (Cwd == NULL){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, 1), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);
+ if (FileList == NULL || IsListEmpty(&FileList->Link) || EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1));
+ ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ ShellStatus = ProcessValidateAndCopyFiles(FileList, Cwd, SilentMode, RecursiveMode);
+ }
+ }
+
+ break;
+ default:
+ //
+ // Make a big list of all the files...
+ //
+ for (ParamCount--, LoopCounter = 1 ; LoopCounter < ParamCount && ShellStatus == SHELL_SUCCESS ; LoopCounter++) {
+ if (ShellGetExecutionBreakFlag()) {
+ break;
+ }
+ Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, LoopCounter), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);
+ if (EFI_ERROR(Status) || FileList == NULL || IsListEmpty(&FileList->Link)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1));
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ }
+ //
+ // now copy them all...
+ //
+ if (FileList != NULL && !IsListEmpty(&FileList->Link)) {
+ ShellStatus = ProcessValidateAndCopyFiles(FileList, ShellCommandCleanPath((CHAR16*)ShellCommandLineGetRawValue(Package, ParamCount)), SilentMode, RecursiveMode);
+ Status = ShellCloseFileMetaArg(&FileList);
+ if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_FILE), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1), ShellStatus|MAX_BIT);
+ ShellStatus = SHELL_ACCESS_DENIED;
+ }
+ }
+
+ break;
+ } // switch on parameter count
+
+ if (FileList != NULL) {
+ ShellCloseFileMetaArg(&FileList);
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ if (ShellGetExecutionBreakFlag()) {
+ return (SHELL_ABORTED);
+ }
+
+ return (ShellStatus);
+}
+
diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/Load.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/Load.c
new file mode 100644
index 0000000000..1e29ad62e1
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/Load.c
@@ -0,0 +1,282 @@
+/** @file
+ Main file for attrib shell level 2 function.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiShellLevel2CommandsLib.h"
+
+// This function was from from the BdsLib implementation in
+// IntelFrameworkModulePkg\Library\GenericBdsLib\BdsConnect.c
+// function name: BdsLibConnectAllEfi
+/**
+ This function will connect all current system handles recursively. The
+ connection will finish until every handle's child handle created if it have.
+
+ @retval EFI_SUCCESS All handles and it's child handle have been
+ connected
+ @retval EFI_STATUS Return the status of gBS->LocateHandleBuffer().
+
+**/
+EFI_STATUS
+EFIAPI
+ConnectAllEfi (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+
+ Status = gBS->LocateHandleBuffer (
+ AllHandles,
+ NULL,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
+ }
+
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ function to load a .EFI driver into memory and possible connect the driver.
+
+ if FileName is NULL then ASSERT.
+
+ @param[in] FileName FileName of the driver to load
+ @param[in] Connect Whether to connect or not
+
+ @retval EFI_SUCCESS the driver was loaded and if Connect was
+ true then connect was attempted. Connection may
+ have failed.
+ @retval EFI_OUT_OF_RESOURCES there was insufficient memory
+**/
+EFI_STATUS
+EFIAPI
+LoadDriver(
+ IN CONST CHAR16 *FileName,
+ IN CONST BOOLEAN Connect
+ )
+{
+ EFI_HANDLE LoadedDriverHandle;
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *Node;
+ EFI_DEVICE_PATH_PROTOCOL *FilePath;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedDriverImage;
+
+ LoadedDriverImage = NULL;
+ FilePath = NULL;
+ Node = NULL;
+ LoadedDriverHandle = NULL;
+ Status = EFI_SUCCESS;
+
+ ASSERT (FileName != NULL);
+
+ //
+ // Fix local copies of the protocol pointers
+ //
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Convert to DEVICE_PATH
+ //
+ FilePath = gEfiShellProtocol->GetDevicePathFromFilePath(FileName);
+
+ if (FilePath == NULL) {
+ ASSERT(FALSE);
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ //
+ // Use LoadImage to get it into memory
+ //
+ Status = gBS->LoadImage(
+ FALSE,
+ gImageHandle,
+ FilePath,
+ NULL,
+ 0,
+ &LoadedDriverHandle);
+
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_NOT_IMAGE), gShellLevel2HiiHandle, FileName, Status);
+ } else {
+ //
+ // Make sure it is a driver image
+ //
+ Status = gBS->HandleProtocol (LoadedDriverHandle, &gEfiLoadedImageProtocolGuid, (VOID *) &LoadedDriverImage);
+
+ ASSERT (LoadedDriverImage != NULL);
+
+ if ( EFI_ERROR(Status)
+ || ( LoadedDriverImage->ImageCodeType != EfiBootServicesCode
+ && LoadedDriverImage->ImageCodeType != EfiRuntimeServicesCode)
+ ){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_NOT_DRIVER), gShellLevel2HiiHandle, FileName);
+
+ //
+ // Exit and unload the non-driver image
+ //
+ gBS->Exit(LoadedDriverHandle, EFI_INVALID_PARAMETER, 0, NULL);
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+
+ if (!EFI_ERROR(Status)) {
+ //
+ // Start the image
+ //
+ Status = gBS->StartImage(LoadedDriverHandle, NULL, NULL);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_ERROR), gShellLevel2HiiHandle, FileName, Status);
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_LOADED), gShellLevel2HiiHandle, FileName, LoadedDriverImage->ImageBase, Status);
+ }
+ }
+
+ if (!EFI_ERROR(Status) && Connect) {
+ //
+ // Connect it...
+ //
+ Status = ConnectAllEfi();
+ }
+
+ //
+ // clean up memory...
+ //
+ if (FilePath != NULL) {
+ FreePool(FilePath);
+ }
+
+ return (Status);
+}
+
+STATIC CONST SHELL_PARAM_ITEM LoadParamList[] = {
+ {L"-nc", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'load' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunLoad (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ UINTN ParamCount;
+ EFI_SHELL_FILE_INFO *ListHead;
+ EFI_SHELL_FILE_INFO *Node;
+
+ ListHead = NULL;
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (LoadParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ } else if (ShellCommandLineGetRawValue(Package, 1) == NULL) {
+ //
+ // we didnt get a single file to load parameter
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ for ( ParamCount = 1
+ ; ShellCommandLineGetRawValue(Package, ParamCount) != NULL
+ ; ParamCount++
+ ){
+ Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, ParamCount), EFI_FILE_MODE_READ, &ListHead);
+ if (!EFI_ERROR(Status)) {
+ for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&ListHead->Link)
+ ; !IsNull(&ListHead->Link, &Node->Link)
+ ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&ListHead->Link, &Node->Link)
+ ){
+ //
+ // once we have an error preserve that value, but finish the loop.
+ //
+ if (EFI_ERROR(Status)) {
+ LoadDriver(Node->FullName, ShellCommandLineGetFlag(Package, L"-nc"));
+ } else {
+ Status = LoadDriver(Node->FullName, ShellCommandLineGetFlag(Package, L"-nc"));
+ }
+ } // for loop for multi-open
+ if (EFI_ERROR(Status)) {
+ ShellCloseFileMetaArg(&ListHead);
+ } else {
+ Status = ShellCloseFileMetaArg(&ListHead);;
+ }
+ } else {
+ //
+ // no files found.
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, (CHAR16*)ShellCommandLineGetRawValue(Package, ParamCount));
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ } // for loop for params
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) {
+ ShellStatus = SHELL_DEVICE_ERROR;
+ }
+
+ return (ShellStatus);
+}
diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/Ls.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/Ls.c
new file mode 100644
index 0000000000..61d48977f1
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/Ls.c
@@ -0,0 +1,564 @@
+/** @file
+ Main file for ls shell level 2 function.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiShellLevel2CommandsLib.h"
+#include <Guid/FileSystemInfo.h>
+
+/**
+ print out the list of files and directories from the LS command
+
+ @param[in] Rec TRUE to automatically recurse into each found directory
+ FALSE to only list the specified directory.
+ @param[in] Attribs List of required Attribute for display.
+ If 0 then all non-system and non-hidden files will be printed.
+ @param[in] Sfo TRUE to use Standard Format Output, FALSE otherwise
+ @param[in] Path String with starting path.
+ @param[in] First TRUE for the original and FALSE for any recursion spawned instances.
+ @param[in] Count The count of bits enabled in Attribs.
+ @param[in] TimeZone The current time zone offset.
+
+ @retval SHELL_SUCCESS the printing was sucessful.
+**/
+SHELL_STATUS
+EFIAPI
+PrintLsOutput(
+ IN CONST BOOLEAN Rec,
+ IN CONST UINT64 Attribs,
+ IN CONST BOOLEAN Sfo,
+ IN CONST CHAR16 *Path,
+ IN CONST BOOLEAN First,
+ IN CONST UINTN Count,
+ IN CONST INT16 TimeZone
+ )
+{
+ EFI_STATUS Status;
+ EFI_SHELL_FILE_INFO *ListHead;
+ EFI_SHELL_FILE_INFO *Node;
+ SHELL_STATUS ShellStatus;
+ UINT64 FileCount;
+ UINT64 DirCount;
+ UINT64 FileSize;
+ CHAR16 *DirectoryName;
+ UINTN LongestPath;
+ EFI_FILE_SYSTEM_INFO *SysInfo;
+ UINTN SysInfoSize;
+ SHELL_FILE_HANDLE ShellFileHandle;
+ CHAR16 *CorrectedPath;
+ EFI_FILE_PROTOCOL *EfiFpHandle;
+
+ FileCount = 0;
+ DirCount = 0;
+ FileSize = 0;
+ ListHead = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ LongestPath = 0;
+ CorrectedPath = NULL;
+
+ CorrectedPath = StrnCatGrow(&CorrectedPath, NULL, Path, 0);
+ ASSERT(CorrectedPath != NULL);
+ ShellCommandCleanPath(CorrectedPath);
+
+ Status = ShellOpenFileMetaArg((CHAR16*)CorrectedPath, EFI_FILE_MODE_READ, &ListHead);
+ if (EFI_ERROR(Status)) {
+ return (SHELL_DEVICE_ERROR);
+ }
+ if (ListHead == NULL || IsListEmpty(&ListHead->Link)) {
+ //
+ // On the first one only we expect to find something...
+ // do we find the . and .. directories otherwise?
+ //
+ if (First) {
+ return (SHELL_NOT_FOUND);
+ }
+ return (SHELL_SUCCESS);
+ }
+
+ if (Sfo && First) {
+ //
+ // Get the first valid handle (directories)
+ //
+ for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&ListHead->Link)
+ ; !IsNull(&ListHead->Link, &Node->Link) && Node->Handle == NULL
+ ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&ListHead->Link, &Node->Link)
+ );
+
+ if (Node->Handle == NULL) {
+ DirectoryName = GetFullyQualifiedPath(((EFI_SHELL_FILE_INFO *)GetFirstNode(&ListHead->Link))->FullName);
+
+ //
+ // We need to open something up to get system information
+ //
+ Status = gEfiShellProtocol->OpenFileByName(
+ DirectoryName,
+ &ShellFileHandle,
+ EFI_FILE_MODE_READ);
+
+ ASSERT_EFI_ERROR(Status);
+ FreePool(DirectoryName);
+
+ //
+ // Get the Volume Info from ShellFileHandle
+ //
+ SysInfo = NULL;
+ SysInfoSize = 0;
+ EfiFpHandle = ConvertShellHandleToEfiFileProtocol(ShellFileHandle);
+ Status = EfiFpHandle->GetInfo(
+ EfiFpHandle,
+ &gEfiFileSystemInfoGuid,
+ &SysInfoSize,
+ SysInfo);
+
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ SysInfo = AllocateZeroPool(SysInfoSize);
+ Status = EfiFpHandle->GetInfo(
+ EfiFpHandle,
+ &gEfiFileSystemInfoGuid,
+ &SysInfoSize,
+ SysInfo);
+ }
+
+ ASSERT_EFI_ERROR(Status);
+
+ gEfiShellProtocol->CloseFile(ShellFileHandle);
+ } else {
+ //
+ // Get the Volume Info from Node->Handle
+ //
+ SysInfo = NULL;
+ SysInfoSize = 0;
+ EfiFpHandle = ConvertShellHandleToEfiFileProtocol(Node->Handle);
+ Status = EfiFpHandle->GetInfo(
+ EfiFpHandle,
+ &gEfiFileSystemInfoGuid,
+ &SysInfoSize,
+ SysInfo);
+
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ SysInfo = AllocateZeroPool(SysInfoSize);
+ Status = EfiFpHandle->GetInfo(
+ EfiFpHandle,
+ &gEfiFileSystemInfoGuid,
+ &SysInfoSize,
+ SysInfo);
+ }
+
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_GEN_SFO_HEADER),
+ gShellLevel2HiiHandle,
+ L"ls");
+ //
+ // print VolumeInfo table
+ //
+ ASSERT(SysInfo != NULL);
+ ShellPrintHiiEx (
+ 0,
+ gST->ConOut->Mode->CursorRow,
+ NULL,
+ STRING_TOKEN (STR_LS_SFO_VOLINFO),
+ gShellLevel2HiiHandle,
+ SysInfo->VolumeLabel,
+ SysInfo->VolumeSize,
+ SysInfo->ReadOnly?L"TRUE":L"FALSE",
+ SysInfo->FreeSpace,
+ SysInfo->BlockSize
+ );
+ if (SysInfo != NULL) {
+ FreePool(SysInfo);
+ }
+ }
+
+ if (!Sfo) {
+ //
+ // get directory name from path...
+ //
+ DirectoryName = GetFullyQualifiedPath(CorrectedPath);
+
+ //
+ // print header
+ //
+ ShellPrintHiiEx (
+ 0,
+ gST->ConOut->Mode->CursorRow,
+ NULL,
+ STRING_TOKEN (STR_LS_HEADER_LINE1),
+ gShellLevel2HiiHandle,
+ DirectoryName
+ );
+ FreePool(DirectoryName);
+ }
+ for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&ListHead->Link)
+ ; !IsNull(&ListHead->Link, &Node->Link)
+ ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&ListHead->Link, &Node->Link)
+ ){
+ ASSERT(Node != NULL);
+ if (LongestPath < StrSize(Node->FullName)) {
+ LongestPath = StrSize(Node->FullName);
+ }
+ ASSERT(Node->Info != NULL);
+ ASSERT((Node->Info->Attribute & EFI_FILE_VALID_ATTR) == Node->Info->Attribute);
+ if (Attribs == 0) {
+ //
+ // NOT system & NOT hidden
+ //
+ if ( (Node->Info->Attribute & EFI_FILE_SYSTEM)
+ || (Node->Info->Attribute & EFI_FILE_HIDDEN)
+ ){
+ continue;
+ }
+ } else if (Attribs != EFI_FILE_VALID_ATTR) {
+ if (Count == 1) {
+ //
+ // the bit must match
+ //
+ if ( (Node->Info->Attribute & Attribs) != Attribs) {
+ continue;
+ }
+ } else {
+ //
+ // exact match on all bits
+ //
+ if ( Node->Info->Attribute != Attribs) {
+ continue;
+ }
+ }
+ }
+
+ if (Sfo) {
+ //
+ // Print the FileInfo Table
+ //
+ ShellPrintHiiEx (
+ 0,
+ gST->ConOut->Mode->CursorRow,
+ NULL,
+ STRING_TOKEN (STR_LS_SFO_FILEINFO),
+ gShellLevel2HiiHandle,
+ Node->FullName,
+ Node->Info->FileSize,
+ Node->Info->PhysicalSize,
+ (Node->Info->Attribute & EFI_FILE_ARCHIVE) != 0?L"a":L"",
+ (Node->Info->Attribute & EFI_FILE_DIRECTORY) != 0?L"d":L"",
+ (Node->Info->Attribute & EFI_FILE_HIDDEN) != 0?L"h":L"",
+ (Node->Info->Attribute & EFI_FILE_READ_ONLY) != 0?L"r":L"",
+ (Node->Info->Attribute & EFI_FILE_SYSTEM) != 0?L"s":L"",
+ Node->Info->CreateTime.Hour,
+ Node->Info->CreateTime.Minute,
+ Node->Info->CreateTime.Second,
+ Node->Info->CreateTime.Day,
+ Node->Info->CreateTime.Month,
+ Node->Info->CreateTime.Year,
+ Node->Info->LastAccessTime.Hour,
+ Node->Info->LastAccessTime.Minute,
+ Node->Info->LastAccessTime.Second,
+ Node->Info->LastAccessTime.Day,
+ Node->Info->LastAccessTime.Month,
+ Node->Info->LastAccessTime.Year,
+ Node->Info->ModificationTime.Hour,
+ Node->Info->ModificationTime.Minute,
+ Node->Info->ModificationTime.Second,
+ Node->Info->ModificationTime.Day,
+ Node->Info->ModificationTime.Month,
+ Node->Info->ModificationTime.Year
+ );
+ } else {
+ //
+ // print this one out...
+ // first print the universal start, next print the type specific name format, last print the CRLF
+ //
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_LS_LINE_START_ALL),
+ gShellLevel2HiiHandle,
+ &Node->Info->ModificationTime,
+ (Node->Info->Attribute & EFI_FILE_DIRECTORY) != 0?L"<DIR>":L"",
+ (Node->Info->Attribute & EFI_FILE_READ_ONLY) != 0?L'r':L' ',
+ Node->Info->FileSize
+ );
+ if (Node->Info->Attribute & EFI_FILE_DIRECTORY) {
+ DirCount++;
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_LS_LINE_END_DIR),
+ gShellLevel2HiiHandle,
+ Node->FileName
+ );
+ } else {
+ FileCount++;
+ FileSize += Node->Info->FileSize;
+ if ( (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)L".nsh", (CHAR16*)&(Node->FileName[StrLen (Node->FileName) - 4])) == 0)
+ || (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)L".efi", (CHAR16*)&(Node->FileName[StrLen (Node->FileName) - 4])) == 0)
+ ){
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_LS_LINE_END_EXE),
+ gShellLevel2HiiHandle,
+ Node->FileName
+ );
+ } else {
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_LS_LINE_END_FILE),
+ gShellLevel2HiiHandle,
+ Node->FileName
+ );
+ }
+ }
+ }
+ }
+
+ if (!Sfo) {
+ //
+ // print footer
+ //
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_LS_FOOTER_LINE),
+ gShellLevel2HiiHandle,
+ FileCount,
+ FileSize,
+ DirCount
+ );
+ }
+
+ if (Rec){
+ DirectoryName = AllocatePool(LongestPath + 2*sizeof(CHAR16));
+ for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&ListHead->Link)
+ ; !IsNull(&ListHead->Link, &Node->Link)
+ ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&ListHead->Link, &Node->Link)
+ ){
+ //
+ // recurse on any directory except the traversing ones...
+ //
+ if (((Node->Info->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY)
+ && StrCmp(Node->FileName, L".") != 0
+ && StrCmp(Node->FileName, L"..") != 0
+ ){
+ StrCpy(DirectoryName, Node->FullName);
+ StrCat(DirectoryName, L"\\*");
+ PrintLsOutput(
+ Rec,
+ Attribs,
+ Sfo,
+ DirectoryName,
+ FALSE,
+ Count,
+ TimeZone);
+ }
+ }
+ FreePool(DirectoryName);
+ }
+
+ FreePool(CorrectedPath);
+ ShellCloseFileMetaArg(&ListHead);
+ FreePool(ListHead);
+ return (ShellStatus);
+}
+
+STATIC CONST SHELL_PARAM_ITEM LsParamList[] = {
+ {L"-r", TypeFlag},
+ {L"-a", TypeStart},
+ {L"-sfo", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'ls' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunLs (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ CONST CHAR16 *Attribs;
+ SHELL_STATUS ShellStatus;
+ UINT64 RequiredAttributes;
+ CONST CHAR16 *PathName;
+ CONST CHAR16 *CurDir;
+ UINTN Count;
+ CHAR16 *FullPath;
+ UINTN Size;
+ EFI_TIME theTime;
+ BOOLEAN SfoMode;
+
+ Size = 0;
+ FullPath = NULL;
+ ProblemParam = NULL;
+ Attribs = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ RequiredAttributes = 0;
+ PathName = NULL;
+ CurDir = NULL;
+ Count = 0;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Fix local copies of the protocol pointers
+ //
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (LsParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ }
+
+ if (ShellCommandLineGetCount(Package) > 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // check for -a
+ //
+ if (ShellCommandLineGetFlag(Package, L"-a")) {
+ for ( Attribs = ShellCommandLineGetValue(Package, L"-a")
+ ; Attribs != NULL && *Attribs != CHAR_NULL && ShellStatus == SHELL_SUCCESS
+ ; Attribs++
+ ){
+ switch (*Attribs) {
+ case L'a':
+ case L'A':
+ RequiredAttributes |= EFI_FILE_ARCHIVE;
+ Count++;
+ continue;
+ case L's':
+ case L'S':
+ RequiredAttributes |= EFI_FILE_SYSTEM;
+ Count++;
+ continue;
+ case L'h':
+ case L'H':
+ RequiredAttributes |= EFI_FILE_HIDDEN;
+ Count++;
+ continue;
+ case L'r':
+ case L'R':
+ RequiredAttributes |= EFI_FILE_READ_ONLY;
+ Count++;
+ continue;
+ case L'd':
+ case L'D':
+ RequiredAttributes |= EFI_FILE_DIRECTORY;
+ Count++;
+ continue;
+ default:
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ATTRIBUTE), gShellLevel2HiiHandle, ShellCommandLineGetValue(Package, L"-a"));
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ break;
+ } // switch
+ } // for loop
+ //
+ // if nothing is specified all are specified
+ //
+ if (RequiredAttributes == 0) {
+ RequiredAttributes = EFI_FILE_VALID_ATTR;
+ }
+ } // if -a present
+ if (ShellStatus == SHELL_SUCCESS) {
+ PathName = ShellCommandLineGetRawValue(Package, 1);
+ if (PathName == NULL) {
+ CurDir = gEfiShellProtocol->GetCurDir(NULL);
+ if (CurDir == NULL) {
+ ShellStatus = SHELL_NOT_FOUND;
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle);
+ }
+ }
+ if (PathName != NULL) {
+ ASSERT((FullPath == NULL && Size == 0) || (FullPath != NULL));
+ StrnCatGrow(&FullPath, &Size, PathName, 0);
+ if (ShellIsDirectory(PathName) == EFI_SUCCESS) {
+ StrnCatGrow(&FullPath, &Size, L"\\*", 0);
+ }
+ } else {
+ ASSERT(FullPath == NULL);
+ StrnCatGrow(&FullPath, NULL, L"*", 0);
+ }
+ Status = gRT->GetTime(&theTime, NULL);
+ ASSERT_EFI_ERROR(Status);
+ SfoMode = ShellCommandLineGetFlag(Package, L"-sfo");
+ if (ShellStatus == SHELL_SUCCESS) {
+ ShellStatus = PrintLsOutput(
+ ShellCommandLineGetFlag(Package, L"-r"),
+ RequiredAttributes,
+ SfoMode,
+ FullPath,
+ TRUE,
+ Count,
+ (INT16)(theTime.TimeZone==2047?0:theTime.TimeZone)
+ );
+ if (ShellStatus == SHELL_NOT_FOUND) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_FILES), gShellLevel2HiiHandle);
+ } else if (ShellStatus == SHELL_INVALID_PARAMETER) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle);
+ } else if (ShellStatus != SHELL_SUCCESS) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle);
+ }
+ }
+ }
+ }
+ }
+
+ if (FullPath != NULL) {
+ FreePool(FullPath);
+ }
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+
+ return (ShellStatus);
+}
diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c
new file mode 100644
index 0000000000..5d6a200c19
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c
@@ -0,0 +1,1116 @@
+/** @file
+ Main file for map shell level 2 command.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiShellLevel2CommandsLib.h"
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/BlockIo.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HandleParsingLib.h>
+#include <Library/SortLib.h>
+
+BOOLEAN
+EFIAPI
+SearchList(
+ IN CONST CHAR16 *List,
+ IN CONST CHAR16 *MetaTarget,
+ OUT CHAR16 **FullName OPTIONAL,
+ IN CONST BOOLEAN Meta,
+ IN CONST BOOLEAN SkipTrailingNumbers,
+ IN CONST CHAR16 *Target
+
+ )
+{
+ CHAR16 *TempList;
+ CONST CHAR16 *ListWalker;
+ BOOLEAN Result;
+ CHAR16 *TempSpot;
+
+ for (ListWalker = List , TempList = NULL
+ ; ListWalker != NULL && *ListWalker != CHAR_NULL
+ ;
+ ) {
+ TempList = StrnCatGrow(&TempList, NULL, ListWalker, 0);
+ ASSERT(TempList != NULL);
+ TempSpot = StrStr(TempList, Target);
+ if (TempSpot != NULL) {
+ *TempSpot = CHAR_NULL;
+ }
+
+ while (SkipTrailingNumbers && (ShellIsDecimalDigitCharacter(TempList[StrLen(TempList)-1]) || TempList[StrLen(TempList)-1] == L':')) {
+ TempList[StrLen(TempList)-1] = CHAR_NULL;
+ }
+
+ ListWalker = StrStr(ListWalker, Target);
+ while(ListWalker != NULL && *ListWalker == *Target) {
+ ListWalker++;
+ }
+ if (Meta) {
+ Result = gUnicodeCollation->MetaiMatch(gUnicodeCollation, (CHAR16*)TempList, (CHAR16*)MetaTarget);
+ } else {
+ Result = (BOOLEAN)(StrCmp(TempList, MetaTarget)==0);
+ }
+ if (Result) {
+ if (FullName != NULL) {
+ *FullName = TempList;
+ } else {
+ FreePool(TempList);
+ }
+ return (TRUE);
+ }
+ FreePool(TempList);
+ TempList = NULL;
+ }
+
+ return (FALSE);
+}
+
+EFI_STATUS
+EFIAPI
+UpdateMapping (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleList;
+ UINTN Count;
+ EFI_DEVICE_PATH_PROTOCOL **DevicePathList;
+ CHAR16 *NewDefaultName;
+ CHAR16 *NewConsistName;
+ EFI_DEVICE_PATH_PROTOCOL **ConsistMappingTable;
+
+ HandleList = NULL;
+ Status = EFI_SUCCESS;
+
+ //
+ // remove mappings that represent removed devices.
+ //
+
+ //
+ // Find each handle with Simple File System
+ //
+ HandleList = GetHandleListByPotocol(&gEfiSimpleFileSystemProtocolGuid);
+ if (HandleList != NULL) {
+ //
+ // Do a count of the handles
+ //
+ for (Count = 0 ; HandleList[Count] != NULL ; Count++);
+
+ //
+ // Get all Device Paths
+ //
+ DevicePathList = AllocatePool(sizeof(EFI_DEVICE_PATH_PROTOCOL*) * Count);
+ ASSERT(DevicePathList != NULL);
+
+ for (Count = 0 ; HandleList[Count] != NULL ; Count++) {
+ DevicePathList[Count] = DevicePathFromHandle(HandleList[Count]);
+ }
+
+ //
+ // Sort all DevicePaths
+ //
+ PerformQuickSort(DevicePathList, Count, sizeof(EFI_DEVICE_PATH_PROTOCOL*), DevicePathCompare);
+
+ ShellCommandConsistMappingInitialize(&ConsistMappingTable);
+
+ //
+ // Assign new Mappings to remainders
+ //
+ for (Count = 0 ; HandleList[Count] != NULL && !EFI_ERROR(Status); Count++) {
+ //
+ // Skip ones that already have
+ //
+ if (gEfiShellProtocol->GetMapFromDevicePath(&DevicePathList[Count]) != NULL) {
+ continue;
+ }
+ //
+ // Get default name
+ //
+ NewDefaultName = ShellCommandCreateNewMappingName(MappingTypeFileSystem);
+ ASSERT(NewDefaultName != NULL);
+
+ //
+ // Call shell protocol SetMap function now...
+ //
+ Status = gEfiShellProtocol->SetMap(DevicePathList[Count], NewDefaultName);
+
+ if (!EFI_ERROR(Status)) {
+ //
+ // Now do consistent name
+ //
+ NewConsistName = ShellCommandConsistMappingGenMappingName(DevicePathList[Count], ConsistMappingTable);
+ if (NewConsistName != NULL) {
+ Status = gEfiShellProtocol->SetMap(DevicePathList[Count], NewConsistName);
+ FreePool(NewConsistName);
+ }
+ }
+
+ FreePool(NewDefaultName);
+ }
+ ShellCommandConsistMappingUnInitialize(ConsistMappingTable);
+ SHELL_FREE_NON_NULL(HandleList);
+ SHELL_FREE_NON_NULL(DevicePathList);
+
+ HandleList = NULL;
+ } else {
+ Count = (UINTN)-1;
+ }
+ //
+ // Do it all over again for gEfiBlockIoProtocolGuid
+ //
+
+ return (Status);
+}
+
+CHAR16*
+EFIAPI
+GetDeviceMediaType (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ ACPI_HID_DEVICE_PATH *Acpi;
+
+ //
+ // Parse the device path:
+ // Devicepath sub type mediatype
+ // MEDIA_HANRDDRIVE_DP -> Hard Disk
+ // MEDIA_CDROM_DP -> CD Rom
+ // Acpi.HID = 0X0604 -> Floppy
+ //
+ if (NULL == DevicePath) {
+ return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_UNKNOWN), NULL);
+ }
+
+ for (;!IsDevicePathEndType (DevicePath) ;DevicePath = NextDevicePathNode (DevicePath)) {
+ if (DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) {
+ switch (DevicePathSubType (DevicePath)) {
+ case MEDIA_HARDDRIVE_DP:
+ return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_HARDDISK), NULL);
+ case MEDIA_CDROM_DP:
+ return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_CDROM), NULL);
+ }
+ } else if (DevicePathType (DevicePath) == ACPI_DEVICE_PATH) {
+ Acpi = (ACPI_HID_DEVICE_PATH *) DevicePath;
+ if (EISA_ID_TO_NUM (Acpi->HID) == 0x0604) {
+ return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_FLOPPY), NULL);
+ }
+ }
+ }
+
+ return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_UNKNOWN), NULL);
+}
+
+/**
+ Function to detemine if a handle has removable storage.
+
+ @param[in] DevicePath DevicePath to test.
+
+ @retval TRUE The handle has removable storage.
+ @retval FALSE The handle does not have removable storage.
+**/
+BOOLEAN
+EFIAPI
+IsRemoveableDevice (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ if (NULL == DevicePath) {
+ return FALSE;
+ }
+
+ while (!IsDevicePathEndType (DevicePath)) {
+ if (DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) {
+ switch (DevicePathSubType (DevicePath)) {
+ case MSG_USB_DP:
+ case MSG_SCSI_DP:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+ }
+ DevicePath = NextDevicePathNode (DevicePath);
+ }
+ return FALSE;
+}
+
+/**
+ Function to detemine if a something on the map list matches.
+
+ @param[in] MapList The pointer to the list to test.
+ @param[in] Specific The pointer to a specific name to test for.
+ @param[in] TypeString The pointer to the list of types.
+ @param[in] Normal Always show normal mappings.
+ @param[in] Consist Always show consistent mappings.
+
+ @retval TRUE The map should be displayed.
+ @retval FALSE The map should not be displayed.
+**/
+BOOLEAN
+EFIAPI
+MappingListHasType(
+ IN CONST CHAR16 *MapList,
+ IN CONST CHAR16 *Specific,
+ IN CONST CHAR16 *TypeString,
+ IN CONST BOOLEAN Normal,
+ IN CONST BOOLEAN Consist
+ )
+{
+ //
+ // specific has priority
+ //
+ if ( Specific != NULL
+ && SearchList(MapList, Specific, NULL, TRUE, FALSE, L";")) {
+ return (TRUE);
+ }
+
+ if ( Consist
+ && (SearchList(MapList, L"HD*", NULL, TRUE, TRUE, L";")
+ ||SearchList(MapList, L"CD*", NULL, TRUE, TRUE, L";")
+ ||SearchList(MapList, L"F*", NULL, TRUE, TRUE, L";")
+ ||SearchList(MapList, L"FP*", NULL, TRUE, TRUE, L";"))){
+ return (TRUE);
+ }
+
+ if ( Normal
+ && (SearchList(MapList, L"FS", NULL, FALSE, TRUE, L";")
+ ||SearchList(MapList, L"BLK", NULL, FALSE, TRUE, L";"))){
+ return (TRUE);
+ }
+
+ if (TypeString != NULL && SearchList(MapList, TypeString, NULL, TRUE, TRUE, L";")) {
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+
+VOID
+EFIAPI
+PerformSingleMappingDisplay(
+ IN CONST BOOLEAN Verbose,
+ IN CONST BOOLEAN Consist,
+ IN CONST BOOLEAN Normal,
+ IN CONST CHAR16 *TypeString,
+ IN CONST BOOLEAN SFO,
+ IN CONST CHAR16 *Specific OPTIONAL,
+ IN CONST EFI_HANDLE Handle
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+ EFI_DEVICE_PATH_PROTOCOL *DevPathCopy;
+ CONST CHAR16 *MapList;
+ CHAR16 *CurrentName;
+ CHAR16 *MediaType;
+ CHAR16 *DevPathString;
+ CHAR16 *TempSpot;
+ UINTN TempLen;
+ BOOLEAN Removable;
+ CONST CHAR16 *TempSpot2;
+
+ DevPath = DevicePathFromHandle(Handle);
+ DevPathCopy = DevPath;
+ MapList = gEfiShellProtocol->GetMapFromDevicePath(&DevPathCopy);
+ if (MapList == NULL) {
+ return;
+ }
+
+ if (!MappingListHasType(MapList, Specific, TypeString, Normal, Consist)){
+ return;
+ }
+
+ CurrentName = NULL;
+ CurrentName = StrnCatGrow(&CurrentName, 0, MapList, 0);
+ TempSpot = StrStr(CurrentName, L";");
+ if (TempSpot != NULL) {
+ *TempSpot = CHAR_NULL;
+ }
+ DevPathString = gDevPathToText->ConvertDevicePathToText(DevPath, TRUE, FALSE);
+ if (!SFO) {
+ TempLen = StrLen(CurrentName);
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_MAP_ENTRY),
+ gShellLevel2HiiHandle,
+ CurrentName,
+ TempLen < StrLen(MapList)?MapList + TempLen+1:L"",
+ DevPathString
+ );
+ if (Verbose) {
+ //
+ // also print handle, media type, removable (y/n), and current directory
+ //
+ MediaType = GetDeviceMediaType(DevPath);
+ if ((TypeString != NULL &&MediaType != NULL && StrStr(TypeString, MediaType) != NULL) || TypeString == NULL) {
+ Removable = IsRemoveableDevice(DevPath);
+ TempSpot2 = ShellGetCurrentDir(CurrentName);
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_MAP_ENTRY_VERBOSE),
+ gShellLevel2HiiHandle,
+ ConvertHandleToHandleIndex(Handle),
+ MediaType,
+ Removable?L"Yes":L"No",
+ TempSpot2
+ );
+ }
+ FreePool(MediaType);
+ }
+ } else {
+ TempLen = StrLen(CurrentName);
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_MAP_SFO_MAPPINGS),
+ gShellLevel2HiiHandle,
+ CurrentName,
+ DevPathString,
+ TempLen < StrLen(MapList)?MapList + TempLen+1:L""
+ );
+ }
+ FreePool(DevPathString);
+ FreePool(CurrentName);
+ return;
+}
+
+EFI_STATUS
+EFIAPI
+PerformSingleMappingDelete(
+ IN CONST CHAR16 *Specific,
+ IN CONST EFI_HANDLE Handle
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+ EFI_DEVICE_PATH_PROTOCOL *DevPathCopy;
+ CONST CHAR16 *MapList;
+ CHAR16 *CurrentName;
+
+ DevPath = DevicePathFromHandle(Handle);
+ DevPathCopy = DevPath;
+ MapList = gEfiShellProtocol->GetMapFromDevicePath(&DevPathCopy);
+ CurrentName = NULL;
+
+ if (MapList == NULL) {
+ return (EFI_NOT_FOUND);
+ }
+ //
+ // if there is a specific and its not on the list...
+ //
+ if (!SearchList(MapList, Specific, &CurrentName, TRUE, FALSE, L";")) {
+ return (EFI_NOT_FOUND);
+ }
+ return (gEfiShellProtocol->SetMap(NULL, CurrentName));
+}
+
+/**
+ Function to display mapping information to the user.
+
+ if Specific is specified then Consist and Normal will be ignored since information will
+ be printed for the specific item only.
+
+ @param[in] Verbose TRUE to display (extra) verbose information
+ @param[in] Consist TRUE to display consistent mappings
+ @param[in] Normal TRUE to display normal (not consist) mappings
+ @param[in] TypeString pointer to string of filter types
+ @param[in] SFO TRUE to display output in Standard Output Format
+ @param[in] Specific pointer to string for specific map to display
+
+ @retval SHELL_SUCCESS the display was printed
+ @retval SHELL_INVALID_PARAMETER one of Consist or Normal must be TRUE if no Specific
+
+**/
+CONST CHAR16 Cd[] = L"cd*";
+CONST CHAR16 Hd[] = L"hd*";
+CONST CHAR16 Fp[] = L"fp*";
+CONST CHAR16 F[] = L"F*";
+SHELL_STATUS
+EFIAPI
+PerformMappingDisplay(
+ IN CONST BOOLEAN Verbose,
+ IN CONST BOOLEAN Consist,
+ IN CONST BOOLEAN Normal,
+ IN CONST CHAR16 *TypeString,
+ IN CONST BOOLEAN SFO,
+ IN CONST CHAR16 *Specific OPTIONAL,
+ IN CONST BOOLEAN Header
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN BufferSize;
+ UINTN LoopVar;
+ CHAR16 *Test;
+
+ if (!Consist && !Normal && Specific == NULL && TypeString == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle);
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ if (TypeString != NULL) {
+ Test = (CHAR16*)Cd;
+ if (StrnCmp(TypeString, Test, StrLen(Test)-1) != 0) {
+ Test = (CHAR16*)Hd;
+ if (StrnCmp(TypeString, Test, StrLen(Test)-1) != 0) {
+ Test = (CHAR16*)Fp;
+ if (StrnCmp(TypeString, Test, StrLen(Test)-1) != 0) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, TypeString);
+ return (SHELL_INVALID_PARAMETER);
+ }
+ } else if (Test == NULL) {
+ Test = (CHAR16*)F;
+ }
+ }
+ } else {
+ Test = NULL;
+ }
+
+ if (Header) {
+ //
+ // Print the header
+ //
+ if (!SFO) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MAP_HEADER), gShellLevel2HiiHandle);
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_SFO_HEADER), gShellLevel2HiiHandle, L"map");
+ }
+ }
+
+ BufferSize = 0;
+ HandleBuffer = NULL;
+
+ //
+ // Look up all SimpleFileSystems in the platform
+ //
+ Status = gBS->LocateHandle(
+ ByProtocol,
+ &gEfiDevicePathProtocolGuid,
+ NULL,
+ &BufferSize,
+ HandleBuffer);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ HandleBuffer = AllocatePool(BufferSize);
+ Status = gBS->LocateHandle(
+ ByProtocol,
+ &gEfiDevicePathProtocolGuid,
+ NULL,
+ &BufferSize,
+ HandleBuffer);
+ }
+ ASSERT_EFI_ERROR(Status);
+ ASSERT(HandleBuffer != NULL);
+
+ //
+ // Get the map name(s) for each one.
+ //
+ for ( LoopVar = 0
+ ; LoopVar < (BufferSize / sizeof(EFI_HANDLE))
+ ; LoopVar ++
+ ){
+ PerformSingleMappingDisplay(
+ Verbose,
+ Consist,
+ Normal,
+ Test,
+ SFO,
+ Specific,
+ HandleBuffer[LoopVar]);
+ }
+
+ //
+ // Look up all BlockIo in the platform
+ //
+ Status = gBS->LocateHandle(
+ ByProtocol,
+ &gEfiBlockIoProtocolGuid,
+ NULL,
+ &BufferSize,
+ HandleBuffer);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ FreePool(HandleBuffer);
+ HandleBuffer = AllocatePool(BufferSize);
+ Status = gBS->LocateHandle(
+ ByProtocol,
+ &gEfiBlockIoProtocolGuid,
+ NULL,
+ &BufferSize,
+ HandleBuffer);
+ }
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Get the map name(s) for each one.
+ //
+ for ( LoopVar = 0
+ ; LoopVar < BufferSize / sizeof(EFI_HANDLE)
+ ; LoopVar ++
+ ){
+ //
+ // Skip any that were already done...
+ //
+ if (gBS->OpenProtocol(
+ HandleBuffer[LoopVar],
+ &gEfiDevicePathProtocolGuid,
+ NULL,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL) == EFI_SUCCESS) {
+ continue;
+ }
+ PerformSingleMappingDisplay(
+ Verbose,
+ Consist,
+ Normal,
+ Test,
+ SFO,
+ Specific,
+ HandleBuffer[LoopVar]);
+ }
+ FreePool(HandleBuffer);
+ return (SHELL_SUCCESS);
+}
+
+SHELL_STATUS
+EFIAPI
+PerformMappingDisplay2(
+ IN CONST BOOLEAN Verbose,
+ IN CONST BOOLEAN Consist,
+ IN CONST BOOLEAN Normal,
+ IN CONST CHAR16 *TypeString,
+ IN CONST BOOLEAN SFO,
+ IN CONST CHAR16 *Specific OPTIONAL
+ )
+{
+ CONST CHAR16 *TypeWalker;
+ SHELL_STATUS ShellStatus;
+ CHAR16 *Comma;
+
+
+ if (TypeString == NULL) {
+ return (PerformMappingDisplay(Verbose, Consist, Normal, NULL, SFO, Specific, TRUE));
+ }
+ ShellStatus = SHELL_SUCCESS;
+ for (TypeWalker = TypeString ; TypeWalker != NULL && *TypeWalker != CHAR_NULL ;) {
+ Comma = StrStr(TypeWalker, L",");
+ if (Comma == NULL) {
+ if (ShellStatus == SHELL_SUCCESS) {
+ ShellStatus = PerformMappingDisplay(Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString));
+ } else {
+ PerformMappingDisplay(Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString));
+ }
+ break;
+ } else {
+ *Comma = CHAR_NULL;
+ if (ShellStatus == SHELL_SUCCESS) {
+ ShellStatus = PerformMappingDisplay(Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString));
+ } else {
+ PerformMappingDisplay(Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString));
+ }
+ *Comma = L',';
+ TypeWalker = Comma + 1;
+ }
+ }
+
+ return (ShellStatus);
+}
+
+EFI_STATUS
+EFIAPI
+PerformMappingDelete(
+ IN CONST CHAR16 *Specific
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN BufferSize;
+ UINTN LoopVar;
+ BOOLEAN Deleted;
+
+ if (Specific == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ BufferSize = 0;
+ HandleBuffer = NULL;
+ Deleted = FALSE;
+
+ //
+ // Look up all SimpleFileSystems in the platform
+ //
+ Status = gBS->LocateHandle(
+ ByProtocol,
+ &gEfiDevicePathProtocolGuid,
+ NULL,
+ &BufferSize,
+ HandleBuffer);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ HandleBuffer = AllocatePool(BufferSize);
+ Status = gBS->LocateHandle(
+ ByProtocol,
+ &gEfiDevicePathProtocolGuid,
+ NULL,
+ &BufferSize,
+ HandleBuffer);
+ }
+ ASSERT_EFI_ERROR(Status);
+ ASSERT(HandleBuffer != NULL);
+
+ //
+ // Get the map name(s) for each one.
+ //
+ for ( LoopVar = 0
+ ; LoopVar < BufferSize / sizeof(EFI_HANDLE)
+ ; LoopVar ++
+ ){
+ if (PerformSingleMappingDelete(Specific,HandleBuffer[LoopVar]) == SHELL_SUCCESS) {
+ Deleted = TRUE;
+ }
+ }
+
+ //
+ // Look up all BlockIo in the platform
+ //
+ Status = gBS->LocateHandle(
+ ByProtocol,
+ &gEfiBlockIoProtocolGuid,
+ NULL,
+ &BufferSize,
+ HandleBuffer);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ FreePool(HandleBuffer);
+ HandleBuffer = AllocatePool(BufferSize);
+ Status = gBS->LocateHandle(
+ ByProtocol,
+ &gEfiBlockIoProtocolGuid,
+ NULL,
+ &BufferSize,
+ HandleBuffer);
+ }
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Get the map name(s) for each one.
+ //
+ for ( LoopVar = 0
+ ; LoopVar < BufferSize / sizeof(EFI_HANDLE)
+ ; LoopVar ++
+ ){
+ //
+ // Skip any that were already done...
+ //
+ if (gBS->OpenProtocol(
+ HandleBuffer[LoopVar],
+ &gEfiDevicePathProtocolGuid,
+ NULL,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL) == EFI_SUCCESS) {
+ continue;
+ }
+ if (PerformSingleMappingDelete(Specific,HandleBuffer[LoopVar]) == SHELL_SUCCESS) {
+ Deleted = TRUE;
+ }
+ }
+ FreePool(HandleBuffer);
+ if (!Deleted) {
+ return (EFI_NOT_FOUND);
+ }
+ return (EFI_SUCCESS);
+}
+
+/**
+ function to add a mapping from mapping.
+
+ This function will get the device path associated with the mapping and call SetMap.
+
+ @param[in] Map The Map to add a mapping for
+ @param[in] SName The name of the new mapping
+
+ @retval SHELL_SUCCESS the mapping was added
+ @retval SHELL_INVALID_PARAMETER the device path for Map could not be retrieved.
+ @return Shell version of a return value from EfiShellProtocol->SetMap
+
+**/
+SHELL_STATUS
+EFIAPI
+AddMappingFromMapping(
+ IN CONST CHAR16 *Map,
+ IN CONST CHAR16 *SName
+ )
+{
+ CONST EFI_DEVICE_PATH_PROTOCOL *DevPath;
+ EFI_STATUS Status;
+
+ if (StrStr(SName, L"*") != NULL
+ ||StrStr(SName, L"?") != NULL
+ ||StrStr(SName, L"[") != NULL
+ ||StrStr(SName, L"]") != NULL) {
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ DevPath = gEfiShellProtocol->GetDevicePathFromMap(Map);
+ if (DevPath == NULL) {
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ Status = gEfiShellProtocol->SetMap(DevPath, SName);
+ if (EFI_ERROR(Status)) {
+ return (SHELL_DEVICE_ERROR);
+ }
+ return (SHELL_SUCCESS);
+}
+
+/**
+ function to determine if a string has only numbers and letters
+
+ This is useful for such things as Map names which can only be letters and numbers
+
+ @param[in] String pointer to the string to analyze
+
+ @retval TRUE String has only numbers and letters
+ @retval FALSE String has at least one other character.
+**/
+BOOLEAN
+EFIAPI
+IsNumberLetterOnly(
+ IN CONST CHAR16 *String
+ )
+{
+ while(String != NULL && *String != CHAR_NULL) {
+ if (! ( *String >= L'a' && *String <= L'z'
+ || *String >= L'A' && *String <= L'Z'
+ || *String >= L'0' && *String <= L'9')
+ ){
+ return (FALSE);
+ }
+ String++;
+ }
+ return (TRUE);
+}
+
+/**
+ function to add a mapping from an EFI_HANDLE.
+
+ This function will get the device path associated with the Handle and call SetMap.
+
+ @param[in] Handle The handle to add a mapping for
+ @param[in] SName The name of the new mapping
+
+ @retval SHELL_SUCCESS the mapping was added
+ @retval SHELL_INVALID_PARAMETER SName was not valid for a map name.
+ @return Shell version of a return value from either
+ gBS->OpenProtocol or EfiShellProtocol->SetMap
+
+**/
+SHELL_STATUS
+EFIAPI
+AddMappingFromHandle(
+ IN CONST EFI_HANDLE Handle,
+ IN CONST CHAR16 *SName
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+ EFI_STATUS Status;
+
+ if (!IsNumberLetterOnly(SName)) {
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ Status = gBS->OpenProtocol(
+ Handle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID**)&DevPath,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR(Status)) {
+ return (SHELL_DEVICE_ERROR);
+ }
+ Status = gEfiShellProtocol->SetMap(DevPath, SName);
+ if (EFI_ERROR(Status)) {
+ return (SHELL_DEVICE_ERROR);
+ }
+ return (SHELL_SUCCESS);
+}
+
+STATIC CONST SHELL_PARAM_ITEM MapParamList[] = {
+ {L"-d", TypeValue},
+ {L"-r", TypeFlag},
+ {L"-v", TypeFlag},
+ {L"-c", TypeFlag},
+ {L"-f", TypeFlag},
+ {L"-u", TypeFlag},
+ {L"-t", TypeValue},
+ {L"-sfo", TypeValue},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'map' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunMap (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ CONST CHAR16 *SName;
+ CONST CHAR16 *Mapping;
+ EFI_HANDLE MappingAsHandle;
+ CONST EFI_DEVICE_PATH_PROTOCOL *DevPath;
+ SHELL_STATUS ShellStatus;
+ BOOLEAN SfoMode;
+ BOOLEAN ConstMode;
+ BOOLEAN NormlMode;
+ CONST CHAR16 *Param1;
+ CONST CHAR16 *TypeString;
+
+ ProblemParam = NULL;
+ Mapping = NULL;
+ SName = NULL;
+ DevPath = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ MappingAsHandle = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (MapParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ SfoMode = ShellCommandLineGetFlag(Package, L"-sfo");
+ ConstMode = ShellCommandLineGetFlag(Package, L"-c");
+ NormlMode = ShellCommandLineGetFlag(Package, L"-f");
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ } else if (ShellCommandLineGetRawValue(Package, 3) != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // Deleting a map name...
+ //
+ if (ShellCommandLineGetFlag(Package, L"-d")) {
+ if ( ShellCommandLineGetFlag(Package, L"-r")
+ || ShellCommandLineGetFlag(Package, L"-v")
+ || ConstMode
+ || NormlMode
+ || ShellCommandLineGetFlag(Package, L"-u")
+ || ShellCommandLineGetFlag(Package, L"-t")
+ ){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ SName = ShellCommandLineGetValue(Package, L"-d");
+ if (SName != NULL) {
+ Status = PerformMappingDelete(SName);
+ if (EFI_ERROR(Status)) {
+ switch (Status) {
+ case EFI_ACCESS_DENIED:
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_ACCESS_DENIED;
+ break;
+ case EFI_NOT_FOUND:
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MAP_NF), gShellLevel2HiiHandle, SName);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ break;
+ default:
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, Status);
+ ShellStatus = SHELL_UNSUPPORTED;
+ }
+ }
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ }
+ } else if ( ShellCommandLineGetFlag(Package, L"-r")
+// || ShellCommandLineGetFlag(Package, L"-v")
+ || ConstMode
+ || NormlMode
+ || ShellCommandLineGetFlag(Package, L"-u")
+ || ShellCommandLineGetFlag(Package, L"-t")
+ ){
+ if ( ShellCommandLineGetFlag(Package, L"-r")) {
+ //
+ // Do the reset
+ //
+ Status = ShellCommandCreateInitialMappingsAndPaths();
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, Status);
+ ShellStatus = SHELL_UNSUPPORTED;
+ }
+ }
+ if ( ShellStatus == SHELL_SUCCESS && ShellCommandLineGetFlag(Package, L"-u")) {
+ //
+ // Do the Update
+ //
+ Status = UpdateMapping();
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, Status);
+ ShellStatus = SHELL_UNSUPPORTED;
+ }
+ }
+ if (ShellStatus == SHELL_SUCCESS) {
+ Param1 = ShellCommandLineGetRawValue(Package, 1);
+ TypeString = ShellCommandLineGetValue(Package, L"-t");
+ if (!ConstMode
+ &&!NormlMode
+ &&TypeString == NULL
+ ) {
+ //
+ // now do the display...
+ //
+ ShellStatus = PerformMappingDisplay(
+ ShellCommandLineGetFlag(Package, L"-v"),
+ TRUE,
+ TRUE,
+ NULL,
+ SfoMode,
+ Param1,
+ TRUE
+ );
+ } else {
+ //
+ // now do the display...
+ //
+ ShellStatus = PerformMappingDisplay2(
+ ShellCommandLineGetFlag(Package, L"-v"),
+ ConstMode,
+ NormlMode,
+ TypeString,
+ SfoMode,
+ Param1
+ );
+ }
+ }
+ } else {
+ //
+ // adding or displaying (there were no flags)
+ //
+ SName = ShellCommandLineGetRawValue(Package, 1);
+ Mapping = ShellCommandLineGetRawValue(Package, 2);
+ if ( SName == NULL
+ && Mapping == NULL
+ ){
+ //
+ // display only since no flags
+ //
+ ShellStatus = PerformMappingDisplay(
+ ShellCommandLineGetFlag(Package, L"-v"),
+ TRUE,
+ TRUE,
+ NULL,
+ SfoMode,
+ NULL,
+ TRUE
+ );
+ } else if ( SName == NULL
+ || Mapping == NULL
+ ){
+ //
+ // Display only the one specified
+ //
+ ShellStatus = PerformMappingDisplay(
+ FALSE,
+ FALSE,
+ FALSE,
+ NULL,
+ SfoMode,
+ SName, // note the variable here...
+ TRUE
+ );
+ } else {
+ if (ShellIsHexOrDecimalNumber(Mapping, TRUE, FALSE)) {
+ MappingAsHandle = ConvertHandleIndexToHandle(StrHexToUintn(Mapping));
+ } else {
+ MappingAsHandle = NULL;
+ }
+ if (MappingAsHandle == NULL && Mapping[StrLen(Mapping)-1] != L':') {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, Mapping);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ if (MappingAsHandle != NULL) {
+ ShellStatus = AddMappingFromHandle(MappingAsHandle, SName);
+ } else {
+ ShellStatus = AddMappingFromMapping(Mapping, SName);
+ }
+ if (ShellStatus != SHELL_SUCCESS) {
+ switch (ShellStatus) {
+ case SHELL_ACCESS_DENIED:
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellLevel2HiiHandle);
+ break;
+ case SHELL_INVALID_PARAMETER:
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle);
+ break;
+ default:
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, ShellStatus|MAX_BIT);
+ }
+ } else {
+ //
+ // now do the display...
+ //
+ ShellStatus = PerformMappingDisplay(
+ FALSE,
+ FALSE,
+ FALSE,
+ NULL,
+ SfoMode,
+ SName,
+ TRUE
+ );
+ } // we were sucessful so do an output
+ } // got a valid map target
+ } // got 2 variables
+ } // we are adding a mapping
+ } // got valid parameters
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+
+ return (ShellStatus);
+}
+
diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/MkDir.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/MkDir.c
new file mode 100644
index 0000000000..421bd55d6f
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/MkDir.c
@@ -0,0 +1,128 @@
+/** @file
+ Main file for attrib shell level 2 function.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiShellLevel2CommandsLib.h"
+
+/**
+ Function for 'mkdir' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunMkDir (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ CONST CHAR16 *NewDirName;
+ UINTN DirCreateCount;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_FILE_HANDLE FileHandle;
+ SHELL_STATUS ShellStatus;
+
+ ShellStatus = SHELL_SUCCESS;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ }
+
+ //
+ // create a set of directories
+ //
+ if (ShellCommandLineGetRawValue(Package, 1) == NULL) {
+ //
+ // we didnt get a single parameter
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ for ( DirCreateCount = 1
+ ;
+ ; DirCreateCount++
+ ){
+ //
+ // loop through each directory specified
+ //
+
+ NewDirName = ShellCommandLineGetRawValue(Package, DirCreateCount);
+ if (NewDirName == NULL) {
+ break;
+ }
+ //
+ // check if that already exists... if yes fail
+ //
+ FileHandle = NULL;
+ Status = ShellOpenFileByName(NewDirName,
+ &FileHandle,
+ EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE,
+ EFI_FILE_DIRECTORY
+ );
+ if (!EFI_ERROR(Status)) {
+ ShellCloseFile(&FileHandle);
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MKDIR_ALREADY), gShellLevel2HiiHandle, NewDirName);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ break;
+ } else {
+ ASSERT(FileHandle == NULL);
+ //
+ // create the directory named NewDirName
+ //
+ Status = ShellCreateDirectory(NewDirName, &FileHandle);
+ if (FileHandle != NULL) {
+ gEfiShellProtocol->CloseFile(FileHandle);
+ }
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MKDIR_CREATEFAIL), gShellLevel2HiiHandle, NewDirName);
+ ShellStatus = SHELL_ACCESS_DENIED;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+
+ return (ShellStatus);
+}
+
diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/Mv.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/Mv.c
new file mode 100644
index 0000000000..adb6f99759
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/Mv.c
@@ -0,0 +1,478 @@
+/** @file
+ Main file for mv shell level 2 function.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiShellLevel2CommandsLib.h"
+
+/**
+ Function to validate that moving a specific file (FileName) to a specific
+ location (DestPath) is valid.
+
+ This function will verify that the destination is not a subdirectory of
+ FullName, that the Current working Directory is not being moved, and that
+ the directory is not read only.
+
+ if the move is invalid this function will report the error to StdOut.
+
+ @param FullName [in] The name of the file to move.
+ @param Cwd [in] The current working directory
+ @param DestPath [in] The target location to move to
+ @param Attribute[in] The Attribute of the file
+
+ @retval TRUE The move is valid
+ @retval FALSE The move is not
+**/
+BOOLEAN
+EFIAPI
+IsValidMove(
+ IN CONST CHAR16 *FullName,
+ IN CONST CHAR16 *Cwd,
+ IN CONST CHAR16 *DestPath,
+ IN CONST UINT64 Attribute
+ )
+{
+ CHAR16 *Test;
+ CHAR16 *Test1;
+ CHAR16 *TestWalker;
+ UINTN Result;
+ UINTN TempLen;
+ if (Cwd != NULL && StrCmp(FullName, Cwd) == 0) {
+ //
+ // Invalid move
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MV_INV_CWD), gShellLevel2HiiHandle);
+ return (FALSE);
+ }
+ Test = NULL;
+ Test = StrnCatGrow(&Test, NULL, DestPath, 0);
+ TestWalker = Test;
+ ASSERT(TestWalker != NULL);
+ while(*TestWalker == L'\\') {
+ TestWalker++;
+ }
+ while(TestWalker != NULL && TestWalker[StrLen(TestWalker)-1] == L'\\') {
+ TestWalker[StrLen(TestWalker)-1] = CHAR_NULL;
+ }
+ ASSERT(TestWalker != NULL);
+ ASSERT(FullName != NULL);
+ if (StrStr(FullName, TestWalker) != 0) {
+ TempLen = StrLen(FullName);
+ if (StrStr(FullName, TestWalker) != FullName // not the first items... (could below it)
+ && TempLen <= (StrLen(TestWalker) + 1)
+ && StrStr(FullName+StrLen(TestWalker) + 1, L"\\") == NULL) {
+ //
+ // Invalid move
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MV_INV_SUB), gShellLevel2HiiHandle);
+ FreePool(Test);
+ return (FALSE);
+ }
+ }
+ FreePool(Test);
+ if (StrStr(DestPath, FullName) != 0 && StrStr(DestPath, FullName) != DestPath) {
+ //
+ // Invalid move
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MV_INV_SUB), gShellLevel2HiiHandle);
+ return (FALSE);
+ }
+ if ((Attribute & EFI_FILE_READ_ONLY) != 0) {
+ //
+ // invalid to move read only
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MV_INV_RO), gShellLevel2HiiHandle);
+ return (FALSE);
+ }
+ Test = StrStr(FullName, L":");
+ Test1 = StrStr(DestPath, L":");
+ if (Test1 != NULL && Test != NULL) {
+ *Test = CHAR_NULL;
+ *Test1 = CHAR_NULL;
+ Result = StringNoCaseCompare(&FullName, &DestPath);
+ *Test = L':';
+ *Test1 = L':';
+ if (Result != 0) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MV_INV_FS), gShellLevel2HiiHandle);
+ return (FALSE);
+ }
+ }
+ return (TRUE);
+}
+
+/**
+ Function to take a destination path that might contain wildcards and verify
+ that there is only a single possible target (IE we cant have wildcards that
+ have 2 possible destination).
+
+ if the result is sucessful the caller must free *DestPathPointer.
+
+ @param[in] DestDir The original path to the destination
+ @param[in,out] DestPathPointer a pointer to the callee allocated final path.
+
+ @retval EFI_INVALID_PARAMETR the DestDir could not be resolved to a location
+ @retval EFI_INVALID_PARAMETR the DestDir could be resolved to more than 1 location
+ @retval EFI_SUCCESS the operation was sucessful
+**/
+SHELL_STATUS
+EFIAPI
+GetDestinationLocation(
+ IN CONST CHAR16 *DestDir,
+ IN OUT CHAR16 **DestPathPointer,
+ IN CONST CHAR16 *Cwd
+ )
+{
+ EFI_SHELL_FILE_INFO *DestList;
+ EFI_SHELL_FILE_INFO *Node;
+ EFI_STATUS Status;
+ CHAR16 *DestPath;
+ CHAR16 *TempLocation;
+ UINTN NewSize;
+
+ DestList = NULL;
+ DestPath = NULL;
+ //
+ // get the destination path
+ //
+ Status = ShellOpenFileMetaArg((CHAR16*)DestDir, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE, &DestList);
+ if (DestList == NULL || IsListEmpty(&DestList->Link)) {
+ //
+ // Not existing... must be renaming
+ //
+ if ((TempLocation = StrStr(DestDir, L":")) == NULL) {
+ NewSize = StrSize(Cwd);
+ NewSize += StrSize(DestDir);
+ DestPath = AllocateZeroPool(NewSize);
+ StrCpy(DestPath, Cwd);
+ if (DestPath[StrLen(DestPath)-1] != L'\\' && DestDir[0] != L'\\') {
+ StrCat(DestPath, L"\\");
+ } else if (DestPath[StrLen(DestPath)-1] == L'\\' && DestDir[0] == L'\\') {
+ ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL;
+ }
+ StrCat(DestPath, DestDir);
+ } else {
+ ASSERT(DestPath == NULL);
+ DestPath = StrnCatGrow(&DestPath, NULL, DestDir, 0);
+ }
+ } else {
+ Node = (EFI_SHELL_FILE_INFO*)GetFirstNode(&DestList->Link);
+ //
+ // Make sure there is only 1 node in the list.
+ //
+ if (!IsNodeAtEnd(&DestList->Link, &Node->Link)) {
+ ShellCloseFileMetaArg(&DestList);
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_MARG_ERROR), gShellLevel2HiiHandle, DestDir);
+ return (SHELL_INVALID_PARAMETER);
+ }
+ if (ShellIsDirectory(Node->FullName)==EFI_SUCCESS) {
+ DestPath = AllocateZeroPool(StrSize(Node->FullName)+sizeof(CHAR16));
+ StrCpy(DestPath, Node->FullName);
+ StrCat(DestPath, L"\\");
+ } else {
+ //
+ // cant move onto another file.
+ //
+ ShellCloseFileMetaArg(&DestList);
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_ERROR), gShellLevel2HiiHandle, DestDir);
+ return (SHELL_INVALID_PARAMETER);
+ }
+ }
+
+ *DestPathPointer = DestPath;
+ ShellCloseFileMetaArg(&DestList);
+
+ return (SHELL_SUCCESS);
+}
+
+/**
+ function to take a list of files to move and a destination location and do
+ the verification and moving of those files to that location. This function
+ will report any errors to the user and continue to move the rest of the files.
+
+ @param[in] FileList A LIST_ENTRY* based list of files to move
+ @param[in] DestDir the destination location
+
+ @retval SHELL_SUCCESS the files were all moved.
+ @retval SHELL_INVALID_PARAMETER a parameter was invalid
+ @retval SHELL_SECURITY_VIOLATION a security violation ocurred
+ @retval SHELL_WRITE_PROTECTED the destination was write protected
+ @retval SHELL_OUT_OF_RESOURCES a memory allocation failed
+**/
+SHELL_STATUS
+EFIAPI
+ValidateAndMoveFiles(
+ IN CONST EFI_SHELL_FILE_INFO *FileList,
+ IN CONST CHAR16 *DestDir
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *HiiOutput;
+ CHAR16 *HiiResultOk;
+ CHAR16 *DestPath;
+ CONST CHAR16 *Cwd;
+ SHELL_STATUS ShellStatus;
+ CONST EFI_SHELL_FILE_INFO *Node;
+ EFI_FILE_INFO *NewFileInfo;
+ CHAR16 *TempLocation;
+ UINTN NewSize;
+
+ ASSERT(FileList != NULL);
+ ASSERT(DestDir != NULL);
+
+ DestPath = NULL;
+ Cwd = ShellGetCurrentDir(NULL);
+
+ //
+ // Get and validate the destination location
+ //
+ ShellStatus = GetDestinationLocation(DestDir, &DestPath, Cwd);
+ if (ShellStatus != SHELL_SUCCESS) {
+ return (ShellStatus);
+ }
+
+ HiiOutput = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_MV_OUTPUT), NULL);
+ HiiResultOk = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_GEN_RES_OK), NULL);
+ ASSERT (DestPath != NULL);
+ ASSERT (HiiResultOk != NULL);
+ ASSERT (HiiOutput != NULL);
+// ASSERT (Cwd != NULL);
+
+ //
+ // Go through the list of files and directories to move...
+ //
+ for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link)
+ ; !IsNull(&FileList->Link, &Node->Link)
+ ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link)
+ ){
+ if (ShellGetExecutionBreakFlag()) {
+ break;
+ }
+ ASSERT(Node->FileName != NULL);
+ ASSERT(Node->FullName != NULL);
+
+ //
+ // skip the directory traversing stuff...
+ //
+ if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) {
+ continue;
+ }
+
+ //
+ // Validate that the move is valid
+ //
+ if (!IsValidMove(Node->FullName, Cwd, DestPath, Node->Info->Attribute)) {
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ continue;
+ }
+
+ //
+ // Chop off map info from "DestPath"
+ //
+ if ((TempLocation = StrStr(DestPath, L":")) != NULL) {
+ CopyMem(DestPath, TempLocation+1, StrSize(TempLocation+1));
+ }
+
+ //
+ // construct the new file info block
+ //
+ NewSize = StrSize(DestPath);
+ NewSize += StrSize(Node->FileName) + sizeof(EFI_FILE_INFO) + sizeof(CHAR16);
+ NewFileInfo = AllocateZeroPool(NewSize);
+ ASSERT(NewFileInfo != NULL);
+ CopyMem(NewFileInfo, Node->Info, sizeof(EFI_FILE_INFO));
+ if (DestPath[0] != L'\\') {
+ StrCpy(NewFileInfo->FileName, L"\\");
+ StrCat(NewFileInfo->FileName, DestPath);
+ } else {
+ StrCpy(NewFileInfo->FileName, DestPath);
+ }
+ if (NewFileInfo->FileName[StrLen(NewFileInfo->FileName)-1] == L'\\') {
+ if (Node->FileName[0] == L'\\') {
+ //
+ // Don't allow for double slashes. Eliminate one of them.
+ //
+ NewFileInfo->FileName[StrLen(NewFileInfo->FileName)-1] = CHAR_NULL;
+ }
+ StrCat(NewFileInfo->FileName, Node->FileName);
+ }
+ NewFileInfo->Size = sizeof(EFI_FILE_INFO) + StrSize(NewFileInfo->FileName);
+
+ ShellPrintEx(-1, -1, HiiOutput, Node->FullName, NewFileInfo->FileName);
+
+ //
+ // Perform the move operation
+ //
+ Status = ShellSetFileInfo(Node->Handle, NewFileInfo);
+
+ //
+ // Free the info object we used...
+ //
+ ASSERT (NewFileInfo != NULL);
+ FreePool(NewFileInfo);
+
+ //
+ // Check our result
+ //
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, Status);
+ //
+ // move failed
+ //
+ switch(Status){
+ default:
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ case EFI_SECURITY_VIOLATION:
+ ShellStatus = SHELL_SECURITY_VIOLATION;
+ case EFI_WRITE_PROTECTED:
+ ShellStatus = SHELL_WRITE_PROTECTED;
+ case EFI_OUT_OF_RESOURCES:
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ case EFI_DEVICE_ERROR:
+ ShellStatus = SHELL_DEVICE_ERROR;
+ case EFI_ACCESS_DENIED:
+ ShellStatus = SHELL_ACCESS_DENIED;
+ } // switch
+ } else {
+ ShellPrintEx(-1, -1, L"%s", HiiResultOk);
+ }
+ } // for loop
+
+ FreePool(DestPath);
+ FreePool(HiiOutput);
+ FreePool(HiiResultOk);
+ return (ShellStatus);
+}
+
+SHELL_STATUS
+EFIAPI
+ShellCommandRunMv (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ UINTN ParamCount;
+ UINTN LoopCounter;
+ EFI_SHELL_FILE_INFO *FileList;
+
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ ParamCount = 0;
+ FileList = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ }
+
+ switch (ParamCount = ShellCommandLineGetCount(Package)) {
+ case 0:
+ case 1:
+ //
+ // we have insufficient parameters
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ break;
+ case 2:
+ //
+ // must have valid CWD for single parameter...
+ //
+ if (ShellGetCurrentDir(NULL) == NULL){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, 1), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);
+ if (FileList == NULL || IsListEmpty(&FileList->Link) || EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1));
+ ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ //
+ // ValidateAndMoveFiles will report errors to the screen itself
+ //
+ ShellStatus = ValidateAndMoveFiles(FileList, ShellGetCurrentDir(NULL));
+ }
+ }
+
+ break;
+ default:
+ ///@todo make sure this works with error half way through and continues...
+ for (ParamCount--, LoopCounter = 1 ; LoopCounter < ParamCount && ShellStatus == SHELL_SUCCESS ; LoopCounter++) {
+ if (ShellGetExecutionBreakFlag()) {
+ break;
+ }
+ Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, LoopCounter), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);
+ if (FileList == NULL || IsListEmpty(&FileList->Link) || EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1));
+ ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ //
+ // ValidateAndMoveFiles will report errors to the screen itself
+ // Only change ShellStatus if it's sucessful
+ //
+ if (ShellStatus == SHELL_SUCCESS) {
+ ShellStatus = ValidateAndMoveFiles(FileList, ShellCommandLineGetRawValue(Package, ParamCount));
+ } else {
+ ValidateAndMoveFiles(FileList, ShellCommandLineGetRawValue(Package, ParamCount));
+ }
+ }
+ if (FileList != NULL && !IsListEmpty(&FileList->Link)) {
+ Status = ShellCloseFileMetaArg(&FileList);
+ if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_FILE), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1), ShellStatus|MAX_BIT);
+ }
+ }
+ }
+ break;
+ } // switch on parameter count
+
+ if (FileList != NULL) {
+ ShellCloseFileMetaArg(&FileList);
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ if (ShellGetExecutionBreakFlag()) {
+ return (SHELL_ABORTED);
+ }
+
+ return (ShellStatus);
+}
diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/Parse.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/Parse.c
new file mode 100644
index 0000000000..927c8d9729
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/Parse.c
@@ -0,0 +1,190 @@
+/** @file
+ Main file for Parse shell level 2 function.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiShellLevel2CommandsLib.h"
+
+SHELL_STATUS
+EFIAPI
+PerformParsing(
+ IN CONST CHAR16 *FileName,
+ IN CONST CHAR16 *TableName,
+ IN CONST UINTN ColumnIndex,
+ IN CONST UINTN TableNameInstance,
+ IN CONST UINTN ShellCommandInstance
+ )
+{
+ SHELL_FILE_HANDLE FileHandle;
+ EFI_STATUS Status;
+ BOOLEAN Ascii;
+ UINTN LoopVariable;
+ UINTN ColumnLoop;
+ CHAR16 *TempLine;
+ CHAR16 *ColumnPointer;
+ SHELL_STATUS ShellStatus;
+ CHAR16 *TempSpot;
+
+ ASSERT(FileName != NULL);
+ ASSERT(TableName != NULL);
+
+ ShellStatus = SHELL_SUCCESS;
+
+ Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_READ, 0);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel2HiiHandle, FileName);
+ ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ for (LoopVariable = 0 ; LoopVariable < ShellCommandInstance && !ShellFileHandleEof(FileHandle);) {
+ TempLine = ShellFileHandleReturnLine(FileHandle, &Ascii);
+ if (TempLine == NULL) {
+ break;
+ }
+ if (StrStr(TempLine, L"ShellCommand, \"") == TempLine) {
+ LoopVariable++;
+ }
+ SHELL_FREE_NON_NULL(TempLine);
+ }
+ if (LoopVariable == ShellCommandInstance) {
+ LoopVariable = 0;
+ while(1) {
+ TempLine = ShellFileHandleReturnLine(FileHandle, &Ascii);
+ if ( TempLine == NULL
+ || *TempLine == CHAR_NULL
+ || StrStr(TempLine, L"ShellCommand, \"") == TempLine
+ ){
+ SHELL_FREE_NON_NULL(TempLine);
+ break;
+ }
+ if (StrStr(TempLine, TableName) == TempLine) {
+ LoopVariable++;
+ }
+ if ( LoopVariable == TableNameInstance
+ || (TableNameInstance == (UINTN)-1 && StrStr(TempLine, TableName) == TempLine)
+ ){
+ for (ColumnLoop = 1, ColumnPointer = TempLine; ColumnLoop < ColumnIndex && ColumnPointer != NULL && *ColumnPointer != CHAR_NULL; ColumnLoop++) {
+ ColumnPointer = StrStr(ColumnPointer, L",");
+ if (ColumnPointer != NULL && *ColumnPointer != CHAR_NULL){
+ ColumnPointer++;
+ }
+ }
+ if (ColumnLoop == ColumnIndex) {
+ ASSERT(ColumnPointer != NULL);
+ TempSpot = StrStr(ColumnPointer, L",");
+ if (TempSpot != NULL) {
+ *TempSpot = CHAR_NULL;
+ }
+ while (ColumnPointer != NULL && *ColumnPointer != CHAR_NULL && ColumnPointer[0] == L' '){
+ ColumnPointer++;
+ }
+ if (ColumnPointer != NULL && *ColumnPointer != CHAR_NULL && ColumnPointer[0] == L'\"'){
+ ColumnPointer++;
+ }
+ if (ColumnPointer != NULL && *ColumnPointer != CHAR_NULL && ColumnPointer[StrLen(ColumnPointer)-1] == L'\"'){
+ ColumnPointer[StrLen(ColumnPointer)-1] = CHAR_NULL;
+ }
+
+ ShellPrintEx(-1, -1, L"%s\r\n", ColumnPointer);
+ }
+ }
+ SHELL_FREE_NON_NULL(TempLine);
+ }
+ }
+ }
+ return (ShellStatus);
+}
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-i", TypeValue},
+ {L"-s", TypeValue},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'parse' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunParse (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ CONST CHAR16 *FileName;
+ CONST CHAR16 *TableName;
+ CONST CHAR16 *ColumnString;
+ SHELL_STATUS ShellStatus;
+ UINTN ShellCommandInstance;
+ UINTN TableNameInstance;
+
+ ShellStatus = SHELL_SUCCESS;
+ ProblemParam = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ if (ShellCommandLineGetCount(Package) < 4) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetCount(Package) > 4) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ FileName = ShellCommandLineGetRawValue(Package, 1);
+ TableName = ShellCommandLineGetRawValue(Package, 2);
+ ColumnString = ShellCommandLineGetRawValue(Package, 3);
+
+ if (ShellCommandLineGetValue(Package, L"-i") == NULL) {
+ TableNameInstance = (UINTN)-1;
+ } else {
+ TableNameInstance = ShellStrToUintn(ShellCommandLineGetValue(Package, L"-i"));
+ }
+ if (ShellCommandLineGetValue(Package, L"-s") == NULL) {
+ ShellCommandInstance = 1;
+ } else {
+ ShellCommandInstance = ShellStrToUintn(ShellCommandLineGetValue(Package, L"-s"));
+ }
+
+ ShellStatus = PerformParsing(FileName, TableName, ShellStrToUintn(ColumnString), TableNameInstance, ShellCommandInstance);
+ }
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+
+ return (ShellStatus);
+}
+
diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/Reset.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/Reset.c
new file mode 100644
index 0000000000..d0eea8d033
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/Reset.c
@@ -0,0 +1,131 @@
+/** @file
+ Main file for attrib shell level 2 function.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiShellLevel2CommandsLib.h"
+
+STATIC CONST SHELL_PARAM_ITEM ResetParamList[] = {
+ {L"-w", TypeValue},
+ {L"-s", TypeValue},
+ {L"-c", TypeValue},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'reset' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunReset (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CONST CHAR16 *String;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+
+ ShellStatus = SHELL_SUCCESS;
+ ProblemParam = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ResetParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ return (SHELL_INVALID_PARAMETER);
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ } else if (ShellCommandLineGetRawValue(Package, 1) != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // check for cold reset flag, then shutdown reset flag, then warm (default) reset flag
+ //
+ if (ShellCommandLineGetFlag(Package, L"-c")) {
+ if (ShellCommandLineGetFlag(Package, L"-s") || ShellCommandLineGetFlag(Package, L"-w")) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ String = ShellCommandLineGetValue(Package, L"-c");
+ if (String != NULL) {
+ gRT->ResetSystem(EfiResetCold, EFI_SUCCESS, StrSize(String), (VOID*)String);
+ } else {
+ gRT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
+ }
+ }
+ } else if (ShellCommandLineGetFlag(Package, L"-s")) {
+ if (ShellCommandLineGetFlag(Package, L"-w")) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ String = ShellCommandLineGetValue(Package, L"-s");
+ DEBUG_CODE(ShellPrintEx(-1,-1,L"Reset with %s (%d bytes)", String, String!=NULL?StrSize(String):0););
+ if (String != NULL) {
+ gRT->ResetSystem(EfiResetShutdown, EFI_SUCCESS, StrSize(String), (VOID*)String);
+ } else {
+ gRT->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL);
+ }
+ }
+ } else {
+ //
+ // this is default so dont worry about flag...
+ //
+ String = ShellCommandLineGetValue(Package, L"-w");
+ if (String != NULL) {
+ gRT->ResetSystem(EfiResetWarm, EFI_SUCCESS, StrSize(String), (VOID*)String);
+ } else {
+ gRT->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL);
+ }
+ }
+ }
+ }
+
+ //
+ // we should never get here... so the free and return are for formality more than use
+ // as the ResetSystem function should not return...
+ //
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+
+ //
+ // return the status
+ //
+ return (ShellStatus);
+}
+
diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c
new file mode 100644
index 0000000000..bde710faf0
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c
@@ -0,0 +1,296 @@
+/** @file
+ Main file for attrib shell level 2 function.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiShellLevel2CommandsLib.h"
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-q", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+BOOLEAN
+EFIAPI
+IsDirectoryEmpty (
+ IN EFI_HANDLE FileHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_FILE_INFO *FileInfo;
+ BOOLEAN NoFile;
+ BOOLEAN RetVal;
+
+ RetVal = TRUE;
+ NoFile = FALSE;
+
+ for (Status = FileHandleFindFirstFile(FileHandle, &FileInfo)
+ ; !NoFile
+ ; Status = FileHandleFindNextFile(FileHandle, FileInfo, &NoFile)
+ ){
+ if (StrStr(FileInfo->FileName, L".") != FileInfo->FileName
+ &&StrStr(FileInfo->FileName, L"..") != FileInfo->FileName) {
+ RetVal = FALSE;
+ }
+ }
+ return (RetVal);
+}
+
+SHELL_STATUS
+EFIAPI
+CascadeDelete(
+ IN EFI_SHELL_FILE_INFO *Node,
+ IN CONST BOOLEAN Quiet
+ )
+{
+ SHELL_STATUS ShellStatus;
+ EFI_SHELL_FILE_INFO *List;
+ EFI_SHELL_FILE_INFO *Node2;
+ EFI_STATUS Status;
+ SHELL_PROMPT_RESPONSE *Resp;
+
+ Resp = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ List = NULL;
+ Status = EFI_SUCCESS;
+
+ if ((Node->Info->Attribute & EFI_FILE_READ_ONLY) == EFI_FILE_READ_ONLY) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DETELE_RO), gShellLevel2HiiHandle, Node->FullName);
+ return (SHELL_ACCESS_DENIED);
+ }
+
+ if ((Node->Info->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY) {
+ if (!IsDirectoryEmpty(Node->Handle)) {
+ if (!Quiet) {
+ Status = ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_RM_LOG_DELETE_CONF), gShellLevel2HiiHandle, Node->FullName);
+ Status = ShellPromptForResponse(ShellPromptResponseTypeYesNo, NULL, (VOID**)&Resp);
+ ASSERT_EFI_ERROR(Status);
+ ASSERT(Resp != NULL);
+ if (EFI_ERROR(Status) || *Resp != ShellPromptResponseYes) {
+ SHELL_FREE_NON_NULL(Resp);
+ return (SHELL_ABORTED);
+ }
+ SHELL_FREE_NON_NULL(Resp);
+ }
+ //
+ // empty out the directory
+ //
+ Status = gEfiShellProtocol->FindFilesInDir(Node->Handle, &List);
+ if (EFI_ERROR(Status)) {
+ if (List!=NULL) {
+ gEfiShellProtocol->FreeFileList(&List);
+ }
+ return (SHELL_DEVICE_ERROR);
+ }
+ for (Node2 = (EFI_SHELL_FILE_INFO *)GetFirstNode(&List->Link)
+ ; !IsNull(&List->Link, &Node2->Link)
+ ; Node2 = (EFI_SHELL_FILE_INFO *)GetNextNode(&List->Link, &Node2->Link)
+ ){
+ //
+ // skip the directory traversing stuff...
+ //
+ if (StrCmp(Node2->FileName, L".") == 0 || StrCmp(Node2->FileName, L"..") == 0) {
+ continue;
+ }
+ Node2->Status = gEfiShellProtocol->OpenFileByName (Node2->FullName, &Node2->Handle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE);
+ ShellStatus = CascadeDelete(Node2, Quiet);
+ if (ShellStatus != SHELL_SUCCESS) {
+ if (List!=NULL) {
+ gEfiShellProtocol->FreeFileList(&List);
+ }
+ return (ShellStatus);
+ }
+ }
+ if (List!=NULL) {
+ gEfiShellProtocol->FreeFileList(&List);
+ }
+ }
+ }
+
+ if (!(StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0)) {
+ //
+ // now delete the current node...
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DELETE), gShellLevel2HiiHandle, Node->FullName);
+ Status = gEfiShellProtocol->DeleteFile(Node->Handle);
+ Node->Handle = NULL;
+ }
+
+ //
+ // We cant allow for the warning here!
+ //
+ if (Status != EFI_SUCCESS){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DELETE_ERR), gShellLevel2HiiHandle, Status);
+ return (SHELL_ACCESS_DENIED);
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DELETE_COMP), gShellLevel2HiiHandle);
+ return (SHELL_SUCCESS);
+ }
+}
+
+BOOLEAN
+EFIAPI
+IsValidDeleteTarget(
+ IN CONST EFI_SHELL_FILE_INFO *List,
+ IN CONST EFI_SHELL_FILE_INFO *Node,
+ IN CONST LIST_ENTRY *Package
+ )
+{
+ CONST CHAR16 *TempLocation;
+ CHAR16 *Temp2;
+ UINTN Size;
+
+ TempLocation = StrStr(Node->FullName, L":");
+ if (StrLen(TempLocation) == 2) {
+ //
+ // Deleting the root directory is invalid.
+ //
+ return (FALSE);
+ }
+ TempLocation = ShellGetCurrentDir(NULL);
+ Size = 0;
+ Temp2 = NULL;
+ StrnCatGrow(&Temp2, &Size, TempLocation, 0);
+ if (StrStr(Temp2, Node->FullName) != NULL) {
+ FreePool(Temp2);
+ return (FALSE);
+ }
+ FreePool(Temp2);
+
+ return (TRUE);
+}
+
+/**
+ Function for 'rm' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunRm (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ CONST CHAR16 *Param;
+ SHELL_STATUS ShellStatus;
+ UINTN ParamCount;
+ EFI_SHELL_FILE_INFO *FileList;
+ EFI_SHELL_FILE_INFO *Node;
+
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ ParamCount = 0;
+ FileList = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ }
+ if (ShellCommandLineGetRawValue(Package, 1) == NULL) {
+ //
+ // we insufficient parameters
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // get a list with each file specified by parameters
+ // if parameter is a directory then add all the files below it to the list
+ //
+ for ( ParamCount = 1, Param = ShellCommandLineGetRawValue(Package, ParamCount)
+ ; Param != NULL
+ ; ParamCount++, Param = ShellCommandLineGetRawValue(Package, ParamCount)
+ ){
+ Status = ShellOpenFileMetaArg((CHAR16*)Param, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);
+ if (EFI_ERROR(Status) || FileList == NULL || IsListEmpty(&FileList->Link)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, (CHAR16*)Param);
+ ShellStatus = SHELL_NOT_FOUND;
+ break;
+ }
+ }
+
+ if (ShellStatus == SHELL_SUCCESS){
+ //
+ // loop through the list and make sure we are not aborting...
+ //
+ for ( Node = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FileList->Link)
+ ; !IsNull(&FileList->Link, &Node->Link) && !ShellGetExecutionBreakFlag()
+ ; Node = (EFI_SHELL_FILE_INFO*)GetNextNode(&FileList->Link, &Node->Link)
+ ){
+ //
+ // skip the directory traversing stuff...
+ //
+ if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) {
+ continue;
+ }
+
+ //
+ // do the deleting of nodes
+ //
+ if (EFI_ERROR(Node->Status)){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DELETE_ERR2), gShellLevel2HiiHandle, Node->Status);
+ ShellStatus = SHELL_ACCESS_DENIED;
+ break;
+ }
+ if (!IsValidDeleteTarget(FileList, Node, Package)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DELETE_ERR3), gShellLevel2HiiHandle, Node->FullName);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ break;
+ }
+
+ ShellStatus = CascadeDelete(Node, ShellCommandLineGetFlag(Package, L"-q"));
+ }
+ }
+ //
+ // Free the fileList
+ //
+ if (FileList != NULL) {
+ Status = ShellCloseFileMetaArg(&FileList);
+ }
+ FileList = NULL;
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ return (ShellStatus);
+}
+
diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/Set.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/Set.c
new file mode 100644
index 0000000000..a3452f0b62
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/Set.c
@@ -0,0 +1,169 @@
+/** @file
+ Main file for attrib shell level 2 function.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiShellLevel2CommandsLib.h"
+
+/**
+ Print out each environment variable registered with the Shell 2.0 GUID.
+
+ If you spawn a pre 2.0 shell from the Shell 2.0 the environment variable may not carry through.
+
+ @retval STATUS_SUCCESS the printout was sucessful
+ @return any return code from GetNextVariableName except EFI_NOT_FOUND
+**/
+SHELL_STATUS
+EFIAPI
+PrintAllShellEnvVars(
+ VOID
+ )
+{
+ CONST CHAR16 *Value;
+ CONST CHAR16 *ConstEnvNameList;
+
+ ConstEnvNameList = gEfiShellProtocol->GetEnv(NULL);
+ if (ConstEnvNameList == NULL) {
+ return (SHELL_SUCCESS);
+ }
+ while (*ConstEnvNameList != CHAR_NULL){
+ Value = gEfiShellProtocol->GetEnv(ConstEnvNameList);
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SET_DISP), gShellLevel2HiiHandle, ConstEnvNameList, Value);
+ ConstEnvNameList += StrLen(ConstEnvNameList)+1;
+ }
+
+ return (SHELL_SUCCESS);
+}
+
+STATIC CONST SHELL_PARAM_ITEM SetParamList[] = {
+ {L"-d", TypeValue},
+ {L"-v", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'set' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunSet (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CONST CHAR16 *KeyName;
+ CONST CHAR16 *Value;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Make sure globals are good...
+ //
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (SetParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ return (SHELL_INVALID_PARAMETER);
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ } else if (ShellCommandLineGetRawValue(Package, 3) != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetRawValue(Package, 1) != NULL && ShellCommandLineGetFlag(Package, L"-d")) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetFlag(Package, L"-d")) {
+ //
+ // delete a environment variable
+ //
+ KeyName = ShellCommandLineGetValue(Package, L"-d");
+ if (KeyName == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellLevel2HiiHandle, L"-d");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Status = ShellSetEnvironmentVariable(KeyName, L"", ShellCommandLineGetFlag(Package, L"-v"));
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SET_ND), gShellLevel2HiiHandle, KeyName, Status);
+ ShellStatus = SHELL_DEVICE_ERROR;
+ }
+ }
+ } else if (ShellCommandLineGetRawValue(Package, 1) == NULL) {
+ //
+ // print out all current environment variables
+ //
+ return(PrintAllShellEnvVars());
+ } else {
+ //
+ // we are either printing one or assigning one
+ //
+ KeyName = ShellCommandLineGetRawValue(Package, 1);
+ Value = ShellCommandLineGetRawValue(Package, 2);
+ if (KeyName != NULL && Value != NULL) {
+ //
+ // assigning one
+ //
+ Status = ShellSetEnvironmentVariable(KeyName, Value, ShellCommandLineGetFlag(Package, L"-v"));
+ } else {
+ if (KeyName != NULL) {
+ //
+ // print out value for this one only.
+ //
+ Value = ShellGetEnvironmentVariable(KeyName);
+ if (Value == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SET_NF), gShellLevel2HiiHandle, KeyName);
+ ShellStatus = SHELL_SUCCESS;
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SET_DISP), gShellLevel2HiiHandle, KeyName, Value);
+ ShellStatus = SHELL_SUCCESS;
+ }
+ } else {
+ ASSERT(FALSE);
+ }
+ }
+ }
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+
+ return (ShellStatus);
+}
diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/TimeDate.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/TimeDate.c
new file mode 100644
index 0000000000..c8de9cf066
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/TimeDate.c
@@ -0,0 +1,772 @@
+/** @file
+ Main file for time, timezone, and date shell level 2 and shell level 3 functions.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiShellLevel2CommandsLib.h"
+
+INT16
+EFIAPI
+AbsVal(
+ INT16 v
+ )
+{
+ if (v>0) {
+ return (v);
+ }
+ return ((INT16)(-v));
+}
+
+BOOLEAN
+EFIAPI
+InternalIsTimeLikeString (
+ IN CONST CHAR16 *String,
+ IN CONST CHAR16 Char,
+ IN CONST UINTN Min,
+ IN CONST UINTN Max,
+ IN CONST BOOLEAN MinusOk
+ )
+{
+ UINTN Count;
+ Count = 0;
+
+ if (MinusOk) {
+ //
+ // A single minus is ok.
+ //
+ if (*String == L'-') {
+ String++;
+ }
+ }
+
+ //
+ // the first char must be numeric.
+ //
+ if (!ShellIsDecimalDigitCharacter(*String)) {
+ return (FALSE);
+ }
+ //
+ // loop through the characters and use the lib function
+ //
+ for ( ; String != NULL && *String != CHAR_NULL ; String++){
+ if (*String == Char) {
+ Count++;
+ if (Count > Max) {
+ return (FALSE);
+ }
+ continue;
+ }
+ if (!ShellIsDecimalDigitCharacter(*String)) {
+ return (FALSE);
+ }
+ }
+ if (Count < Min) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+SHELL_STATUS
+EFIAPI
+CheckAndSetDate (
+ IN CONST CHAR16 *DateString
+ )
+{
+ EFI_TIME TheTime;
+ EFI_STATUS Status;
+ CONST CHAR16 *Walker;
+
+ if (!InternalIsTimeLikeString(DateString, L'/', 2, 2, FALSE)) {
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ Status = gRT->GetTime(&TheTime, NULL);
+ ASSERT_EFI_ERROR(Status);
+
+ Walker = DateString;
+
+ TheTime.Month = 0xFF;
+ TheTime.Day = 0xFF;
+ TheTime.Year = 0xFFFF;
+
+ TheTime.Month = (UINT8)StrDecimalToUintn (Walker);
+ Walker = StrStr(Walker, L"/");
+ if (Walker != NULL && *Walker == L'/') {
+ Walker = Walker + 1;
+ }
+ if (Walker != NULL && Walker[0] != CHAR_NULL) {
+ TheTime.Day = (UINT8)StrDecimalToUintn (Walker);
+ Walker = StrStr(Walker, L"/");
+ if (Walker != NULL && *Walker == L'/') {
+ Walker = Walker + 1;
+ }
+ if (Walker != NULL && Walker[0] != CHAR_NULL) {
+ TheTime.Year = (UINT16)StrDecimalToUintn (Walker);
+ }
+ }
+
+ if (TheTime.Year < 100) {
+ if (TheTime.Year >= 98) {
+ TheTime.Year = (UINT16)(1900 + TheTime.Year);
+ } else {
+ TheTime.Year = (UINT16)(2000 + TheTime.Year);
+ }
+ }
+
+ Status = gRT->SetTime(&TheTime);
+
+ if (!EFI_ERROR(Status)){
+ return (SHELL_SUCCESS);
+ }
+ return (SHELL_INVALID_PARAMETER);
+}
+
+/**
+ Function for 'date' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDate (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ EFI_TIME TheTime;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+
+ ShellStatus = SHELL_SUCCESS;
+ ProblemParam = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (SfoParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ } else if (ShellCommandLineGetRawValue(Package, 2) != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // If there are 0 value parameters, then print the current date
+ // else If there are any value paramerers, then print error
+ //
+ if (ShellCommandLineGetRawValue(Package, 1) == NULL) {
+ //
+ // get the current date
+ //
+ Status = gRT->GetTime(&TheTime, NULL);
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // ShellPrintEx the date in SFO or regular format
+ //
+ if (ShellCommandLineGetFlag(Package, L"-sfo")) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DATE_SFO_FORMAT), gShellLevel2HiiHandle, TheTime.Month, TheTime.Day, TheTime.Year);
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DATE_FORMAT), gShellLevel2HiiHandle, TheTime.Month, TheTime.Day, TheTime.Year);
+ }
+ } else {
+ if (PcdGet8(PcdShellSupportLevel) == 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // perform level 3 operation here.
+ //
+ ShellStatus = CheckAndSetDate(ShellCommandLineGetRawValue(Package, 1));
+ if (ShellStatus != SHELL_SUCCESS) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1));
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ }
+ }
+ }
+ }
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+
+ //
+ // return the status
+ //
+ return (ShellStatus);
+}
+
+//
+// Note "-tz" is invalid for this (non-interactive) version of 'time'.
+//
+STATIC CONST SHELL_PARAM_ITEM TimeParamList2[] = {
+ {L"-d", TypeValue},
+ {NULL, TypeMax}
+ };
+
+STATIC CONST SHELL_PARAM_ITEM TimeParamList3[] = {
+ {L"-d", TypeValue},
+ {L"-tz", TypeValue},
+ {NULL, TypeMax}
+ };
+
+SHELL_STATUS
+EFIAPI
+CheckAndSetTime (
+ IN CONST CHAR16 *TimeString,
+ IN CONST INT16 Tz,
+ IN CONST UINT8 Daylight
+ )
+{
+ EFI_TIME TheTime;
+ EFI_STATUS Status;
+ CONST CHAR16 *Walker;
+
+ if (TimeString != NULL && !InternalIsTimeLikeString(TimeString, L':', 1, 2, FALSE)) {
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ Status = gRT->GetTime(&TheTime, NULL);
+ ASSERT_EFI_ERROR(Status);
+
+ if (TimeString != NULL) {
+ Walker = TimeString;
+ TheTime.Hour = 0xFF;
+ TheTime.Minute = 0xFF;
+
+ TheTime.Hour = (UINT8)StrDecimalToUintn (Walker);
+ Walker = StrStr(Walker, L":");
+ if (Walker != NULL && *Walker == L':') {
+ Walker = Walker + 1;
+ }
+ if (Walker != NULL && Walker[0] != CHAR_NULL) {
+ TheTime.Minute = (UINT8)StrDecimalToUintn (Walker);
+ Walker = StrStr(Walker, L":");
+ if (Walker != NULL && *Walker == L':') {
+ Walker = Walker + 1;
+ }
+ if (Walker != NULL && Walker[0] != CHAR_NULL) {
+ TheTime.Second = (UINT8)StrDecimalToUintn (Walker);
+ }
+ }
+ }
+
+ if ((Tz >= -1440 && Tz <= 1440)||(Tz == 2047)) {
+ TheTime.TimeZone = Tz;
+ }
+ if (Daylight <= 3 && Daylight != 2) {
+ TheTime.Daylight = Daylight;
+ }
+ Status = gRT->SetTime(&TheTime);
+
+ if (!EFI_ERROR(Status)){
+ return (SHELL_SUCCESS);
+ }
+
+ return (SHELL_INVALID_PARAMETER);
+}
+
+/**
+ Function for 'time' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunTime (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *Message;
+ EFI_TIME TheTime;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ INT16 Tz;
+ UINT8 Daylight;
+ CONST CHAR16 *TempLocation;
+ UINTN TzMinutes;
+
+ ShellStatus = SHELL_SUCCESS;
+ ProblemParam = NULL;
+
+ //
+ // Initialize variables
+ //
+ Message = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ if (PcdGet8(PcdShellSupportLevel) == 2) {
+ Status = ShellCommandLineParseEx (TimeParamList2, &Package, &ProblemParam, TRUE, TRUE);
+ } else {
+ ASSERT(PcdGet8(PcdShellSupportLevel) == 3);
+ Status = ShellCommandLineParseEx (TimeParamList3, &Package, &ProblemParam, TRUE, TRUE);
+ }
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ Status = gRT->GetTime(&TheTime, NULL);
+ ASSERT_EFI_ERROR(Status);
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ } else if (ShellCommandLineGetRawValue(Package, 2) != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // If there are no parameters, then print the current time
+ //
+ if (ShellCommandLineGetRawValue(Package, 1) == NULL
+ && !ShellCommandLineGetFlag(Package, L"-d")
+ && !ShellCommandLineGetFlag(Package, L"-tz")) {
+ //
+ // ShellPrintEx the current time
+ //
+ if (TheTime.TimeZone == 2047) {
+ TzMinutes = 0;
+ } else {
+ TzMinutes = AbsVal(TheTime.TimeZone) % 60;
+ }
+
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_TIME_FORMAT),
+ gShellLevel2HiiHandle,
+ TheTime.Hour,
+ TheTime.Minute,
+ TheTime.Second,
+ TheTime.TimeZone==2047?L" ":(TheTime.TimeZone > 0?L"-":L"+"),
+ TheTime.TimeZone==2047?0:AbsVal(TheTime.TimeZone) / 60,
+ TzMinutes
+ );
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_CRLF), gShellLevel2HiiHandle);
+ } else if (ShellCommandLineGetFlag(Package, L"-d") && ShellCommandLineGetValue(Package, L"-d") == NULL) {
+ if (TheTime.TimeZone == 2047) {
+ TzMinutes = 0;
+ } else {
+ TzMinutes = AbsVal(TheTime.TimeZone) % 60;
+ }
+
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_TIME_FORMAT),
+ gShellLevel2HiiHandle,
+ TheTime.Hour,
+ TheTime.Minute,
+ TheTime.Second,
+ TheTime.TimeZone==2047?L" ":(TheTime.TimeZone > 0?L"-":L"+"),
+ TheTime.TimeZone==2047?0:AbsVal(TheTime.TimeZone) / 60,
+ TzMinutes
+ );
+ switch (TheTime.Daylight) {
+ case 0:
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TIME_DSTNA), gShellLevel2HiiHandle);
+ break;
+ case EFI_TIME_ADJUST_DAYLIGHT:
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TIME_DSTST), gShellLevel2HiiHandle);
+ break;
+ case EFI_TIME_IN_DAYLIGHT:
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TIME_DSTDT), gShellLevel2HiiHandle);
+ break;
+ default:
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_ERROR), gShellLevel2HiiHandle, L"gRT->GetTime", L"TheTime.Daylight", TheTime.Daylight);
+ }
+ } else {
+ if (PcdGet8(PcdShellSupportLevel) == 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // perform level 3 operation here.
+ //
+ if ((TempLocation = ShellCommandLineGetValue(Package, L"-tz")) != NULL) {
+ if (TempLocation[0] == L'-') {
+ Tz = (INT16)(0 - StrDecimalToUintn(++TempLocation));
+ } else {
+ Tz = (INT16)StrDecimalToUintn(TempLocation);
+ }
+ if (!(Tz >= -1440 && Tz <= 1440) && Tz != 2047) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"-d");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ } else {
+ //
+ // intentionally out of bounds value will prevent changing it...
+ //
+ Tz = 1441;
+ }
+ TempLocation = ShellCommandLineGetValue(Package, L"-d");
+ if (TempLocation != NULL) {
+ Daylight = (UINT8)StrDecimalToUintn(TempLocation);
+ if (Daylight != 0 && Daylight != 1 && Daylight != 3) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"-d");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ } else {
+ //
+ // invalid = will not use
+ //
+ Daylight = 0xFF;
+ }
+ if (ShellStatus == SHELL_SUCCESS) {
+ ShellStatus = CheckAndSetTime(ShellCommandLineGetRawValue(Package, 1), Tz, Daylight);
+ if (ShellStatus != SHELL_SUCCESS) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1));
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+
+ //
+ // return the status
+ //
+ return (ShellStatus);
+}
+
+typedef struct {
+ INT16 TimeZone;
+ EFI_STRING_ID StringId;
+} TIME_ZONE_ITEM;
+
+STATIC CONST SHELL_PARAM_ITEM TimeZoneParamList2[] = {
+ {L"-l", TypeFlag},
+ {L"-f", TypeFlag},
+ {NULL, TypeMax}
+ };
+STATIC CONST SHELL_PARAM_ITEM TimeZoneParamList3[] = {
+ {L"-l", TypeFlag},
+ {L"-f", TypeFlag},
+ {L"-s", TypeValue},
+ {NULL, TypeMax}
+ };
+
+ STATIC CONST TIME_ZONE_ITEM TimeZoneList[] = {
+ {720, STRING_TOKEN (STR_TIMEZONE_M12)},
+ {660, STRING_TOKEN (STR_TIMEZONE_M11)},
+ {600, STRING_TOKEN (STR_TIMEZONE_M10)},
+ {540, STRING_TOKEN (STR_TIMEZONE_M9)},
+ {480, STRING_TOKEN (STR_TIMEZONE_M8)},
+ {420, STRING_TOKEN (STR_TIMEZONE_M7)},
+ {360, STRING_TOKEN (STR_TIMEZONE_M6)},
+ {300, STRING_TOKEN (STR_TIMEZONE_M5)},
+ {270, STRING_TOKEN (STR_TIMEZONE_M430)},
+ {240, STRING_TOKEN (STR_TIMEZONE_M4)},
+ {210, STRING_TOKEN (STR_TIMEZONE_M330)},
+ {180, STRING_TOKEN (STR_TIMEZONE_M3)},
+ {120, STRING_TOKEN (STR_TIMEZONE_M2)},
+ {60 , STRING_TOKEN (STR_TIMEZONE_M1)},
+ {0 , STRING_TOKEN (STR_TIMEZONE_0)},
+ {-60 , STRING_TOKEN (STR_TIMEZONE_P1)},
+ {-120 , STRING_TOKEN (STR_TIMEZONE_P2)},
+ {-180 , STRING_TOKEN (STR_TIMEZONE_P3)},
+ {-210 , STRING_TOKEN (STR_TIMEZONE_P330)},
+ {-240 , STRING_TOKEN (STR_TIMEZONE_P4)},
+ {-270 , STRING_TOKEN (STR_TIMEZONE_P430)},
+ {-300 , STRING_TOKEN (STR_TIMEZONE_P5)},
+ {-330 , STRING_TOKEN (STR_TIMEZONE_P530)},
+ {-345 , STRING_TOKEN (STR_TIMEZONE_P545)},
+ {-360 , STRING_TOKEN (STR_TIMEZONE_P6)},
+ {-390 , STRING_TOKEN (STR_TIMEZONE_P630)},
+ {-420 , STRING_TOKEN (STR_TIMEZONE_P7)},
+ {-480 , STRING_TOKEN (STR_TIMEZONE_P8)},
+ {-540 , STRING_TOKEN (STR_TIMEZONE_P9)},
+ {-570 , STRING_TOKEN (STR_TIMEZONE_P930)},
+ {-600 , STRING_TOKEN (STR_TIMEZONE_P10)},
+ {-660 , STRING_TOKEN (STR_TIMEZONE_P11)},
+ {-720 , STRING_TOKEN (STR_TIMEZONE_P12)},
+ {-780 , STRING_TOKEN (STR_TIMEZONE_P13)},
+ {-840 , STRING_TOKEN (STR_TIMEZONE_P14)}
+ };
+
+SHELL_STATUS
+EFIAPI
+CheckAndSetTimeZone (
+ IN CONST CHAR16 *TimeZoneString
+ )
+{
+ EFI_TIME TheTime;
+ EFI_STATUS Status;
+ CONST CHAR16 *Walker;
+ UINTN LoopVar;
+
+ if (TimeZoneString == NULL) {
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ if (TimeZoneString != NULL && !InternalIsTimeLikeString(TimeZoneString, L':', 1, 1, TRUE)) {
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ Status = gRT->GetTime(&TheTime, NULL);
+ ASSERT_EFI_ERROR(Status);
+
+ Walker = TimeZoneString;
+ if (*Walker == L'-') {
+ TheTime.TimeZone = (INT16)((StrDecimalToUintn (++Walker)) * 60);
+ } else {
+ TheTime.TimeZone = (INT16)((StrDecimalToUintn (Walker)) * -60);
+ }
+ Walker = StrStr(Walker, L":");
+ if (Walker != NULL && *Walker == L':') {
+ Walker = Walker + 1;
+ }
+ if (Walker != NULL && Walker[0] != CHAR_NULL) {
+ if (TheTime.TimeZone < 0) {
+ TheTime.TimeZone = (INT16)(TheTime.TimeZone - (UINT8)StrDecimalToUintn (Walker));
+ } else {
+ TheTime.TimeZone = (INT16)(TheTime.TimeZone + (UINT8)StrDecimalToUintn (Walker));
+ }
+ }
+
+ Status = EFI_INVALID_PARAMETER;
+
+ for ( LoopVar = 0
+ ; LoopVar < sizeof(TimeZoneList) / sizeof(TimeZoneList[0])
+ ; LoopVar++
+ ){
+ if (TheTime.TimeZone == TimeZoneList[LoopVar].TimeZone) {
+ Status = gRT->SetTime(&TheTime);
+ break;
+ }
+ }
+
+ if (!EFI_ERROR(Status)){
+ return (SHELL_SUCCESS);
+ }
+ return (SHELL_INVALID_PARAMETER);
+}
+
+
+/**
+ Function for 'timezone' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunTimeZone (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ //
+ // non interactive
+ //
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ UINT8 LoopVar;
+ EFI_TIME TheTime;
+ BOOLEAN Found;
+ UINTN TzMinutes;
+
+ ShellStatus = SHELL_SUCCESS;
+ ProblemParam = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ if (PcdGet8(PcdShellSupportLevel) == 2) {
+ Status = ShellCommandLineParse (TimeZoneParamList2, &Package, &ProblemParam, FALSE);
+ } else {
+ ASSERT(PcdGet8(PcdShellSupportLevel) == 3);
+ Status = ShellCommandLineParseEx (TimeZoneParamList3, &Package, &ProblemParam, FALSE, TRUE);
+ }
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetCount(Package) > 1) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ } else if (ShellCommandLineGetFlag(Package, L"-s")) {
+ if ((ShellCommandLineGetFlag(Package, L"-l")) || (ShellCommandLineGetFlag(Package, L"-f"))) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"-l or -f");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(PcdGet8(PcdShellSupportLevel) == 3);
+ if (ShellCommandLineGetValue(Package, L"-s") == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellLevel2HiiHandle, L"-s");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // Set the time zone
+ //
+ ShellStatus = CheckAndSetTimeZone(ShellCommandLineGetValue(Package, L"-s"));
+ if (ShellStatus != SHELL_SUCCESS) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ShellCommandLineGetValue(Package, L"-s"));
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ }
+ }
+ } else if (ShellCommandLineGetFlag(Package, L"-l")) {
+ //
+ // Print a list of all time zones
+ //
+ for ( LoopVar = 0
+ ; LoopVar < sizeof(TimeZoneList) / sizeof(TimeZoneList[0])
+ ; LoopVar++
+ ){
+ ShellPrintHiiEx (-1, -1, NULL, TimeZoneList[LoopVar].StringId, gShellLevel2HiiHandle);
+ }
+ } else {
+ //
+ // Get Current Time Zone Info
+ //
+ Status = gRT->GetTime(&TheTime, NULL);
+ ASSERT_EFI_ERROR(Status);
+
+ if (TheTime.TimeZone != 2047) {
+ Found = FALSE;
+ for ( LoopVar = 0
+ ; LoopVar < sizeof(TimeZoneList) / sizeof(TimeZoneList[0])
+ ; LoopVar++
+ ){
+ if (TheTime.TimeZone == TimeZoneList[LoopVar].TimeZone) {
+ if (ShellCommandLineGetFlag(Package, L"-f")) {
+ //
+ // Print all info about current time zone
+ //
+ ShellPrintHiiEx (-1, -1, NULL, TimeZoneList[LoopVar].StringId, gShellLevel2HiiHandle);
+ } else {
+ //
+ // Print basic info only
+ //
+ if (TheTime.TimeZone == 2047) {
+ TzMinutes = 0;
+ } else {
+ TzMinutes = AbsVal(TheTime.TimeZone) % 60;
+ }
+
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN(STR_TIMEZONE_SIMPLE),
+ gShellLevel2HiiHandle,
+ TheTime.TimeZone==2047?0:(TheTime.TimeZone > 0?L"-":L"+"),
+ TheTime.TimeZone==2047?0:AbsVal(TheTime.TimeZone) / 60,
+ TzMinutes);
+ }
+ Found = TRUE;
+ break;
+ }
+ }
+ if (!Found) {
+ //
+ // Print basic info only
+ //
+ if (TheTime.TimeZone == 2047) {
+ TzMinutes = 0;
+ } else {
+ TzMinutes = AbsVal(TheTime.TimeZone) % 60;
+ }
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN(STR_TIMEZONE_SIMPLE),
+ gShellLevel2HiiHandle,
+ TheTime.TimeZone==2047?0:(TheTime.TimeZone > 0?L"-":L"+"),
+ TheTime.TimeZone==2047?0:AbsVal(TheTime.TimeZone) / 60,
+ TzMinutes);
+ if (ShellCommandLineGetFlag(Package, L"-f")) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_TIMEZONE_NI), gShellLevel2HiiHandle);
+ }
+ }
+ } else {
+ //
+ // TimeZone was 2047 (unknown) from GetTime()
+ //
+ }
+ }
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+
+ return (ShellStatus);
+}
diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.c
new file mode 100644
index 0000000000..7fe5a1102c
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.c
@@ -0,0 +1,329 @@
+/** @file
+ Main file for NULL named library for level 2 shell command functions.
+
+ these functions are:
+ attrib,
+ cd,
+ cp,
+ date*,
+ time*,
+ load,
+ ls,
+ map,
+ mkdir,
+ mv,
+ parse,
+ rm,
+ reset,
+ set,
+ timezone*
+
+ * functions are non-interactive only
+
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiShellLevel2CommandsLib.h"
+
+CONST CHAR16 mFileName[] = L"ShellCommands";
+EFI_HANDLE gShellLevel2HiiHandle = NULL;
+CONST EFI_GUID gShellLevel2HiiGuid = \
+ { \
+ 0xf95a7ccc, 0x4c55, 0x4426, { 0xa7, 0xb4, 0xdc, 0x89, 0x61, 0x95, 0xb, 0xae } \
+ };
+
+CONST CHAR16*
+EFIAPI
+ShellCommandGetManFileNameLevel2 (
+ VOID
+ )
+{
+ return (mFileName);
+}
+
+/**
+ Constructor for the Shell Level 2 Commands library.
+
+ Install the handlers for level 2 UEFI Shell 2.0 commands.
+
+ @param ImageHandle the image handle of the process
+ @param SystemTable the EFI System Table pointer
+
+ @retval EFI_SUCCESS the shell command handlers were installed sucessfully
+ @retval EFI_UNSUPPORTED the shell level required was not found.
+**/
+EFI_STATUS
+EFIAPI
+ShellLevel2CommandsLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ //
+ // if shell level is less than 2 do nothing
+ //
+ if (PcdGet8(PcdShellSupportLevel) < 2) {
+ return (EFI_UNSUPPORTED);
+ }
+
+ gShellLevel2HiiHandle = HiiAddPackages (&gShellLevel2HiiGuid, gImageHandle, UefiShellLevel2CommandsLibStrings, NULL);
+ if (gShellLevel2HiiHandle == NULL) {
+ return (EFI_DEVICE_ERROR);
+ }
+
+ //
+ // install our shell command handlers that are always installed
+ //
+ ShellCommandRegisterCommandName(L"attrib", ShellCommandRunAttrib , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_ATTRIB) );
+ ShellCommandRegisterCommandName(L"cd", ShellCommandRunCd , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_CD) );
+ ShellCommandRegisterCommandName(L"cp", ShellCommandRunCp , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_CP) );
+ ShellCommandRegisterCommandName(L"load", ShellCommandRunLoad , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_LOAD) );
+ ShellCommandRegisterCommandName(L"map", ShellCommandRunMap , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_MAP) );
+ ShellCommandRegisterCommandName(L"mkdir", ShellCommandRunMkDir , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_MKDIR) );
+ ShellCommandRegisterCommandName(L"mv", ShellCommandRunMv , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_MV) );
+ ShellCommandRegisterCommandName(L"parse", ShellCommandRunParse , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_PARSE) );
+ ShellCommandRegisterCommandName(L"reset", ShellCommandRunReset , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_RESET) );
+ ShellCommandRegisterCommandName(L"set", ShellCommandRunSet , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_SET) );
+ ShellCommandRegisterCommandName(L"ls", ShellCommandRunLs , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_LS) );
+ ShellCommandRegisterCommandName(L"rm", ShellCommandRunRm , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_RM) );
+
+ //
+ // support for permenant (built in) aliases
+ //
+ ShellCommandRegisterAlias(L"rm", L"del");
+ ShellCommandRegisterAlias(L"ls", L"dir");
+ ShellCommandRegisterAlias(L"cp", L"copy");
+ ShellCommandRegisterAlias(L"mkdir", L"md");
+ ShellCommandRegisterAlias(L"cd ..", L"cd..");
+ ShellCommandRegisterAlias(L"cd \\", L"cd\\");
+ //
+ // These are installed in level 2 or 3...
+ //
+ if (PcdGet8(PcdShellSupportLevel) == 2 || PcdGet8(PcdShellSupportLevel) == 3) {
+ ShellCommandRegisterCommandName(L"date", ShellCommandRunDate , ShellCommandGetManFileNameLevel2, PcdGet8(PcdShellSupportLevel), L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_DATE) );
+ ShellCommandRegisterCommandName(L"time", ShellCommandRunTime , ShellCommandGetManFileNameLevel2, PcdGet8(PcdShellSupportLevel), L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_TIME) );
+ ShellCommandRegisterCommandName(L"timezone", ShellCommandRunTimeZone, ShellCommandGetManFileNameLevel2, PcdGet8(PcdShellSupportLevel), L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_TIMEZONE));
+ } else {
+ DEBUG_CODE_BEGIN();
+ //
+ // we want to be able to test these so install them under a different name in debug mode...
+ //
+ ShellCommandRegisterCommandName(L"l2date", ShellCommandRunDate , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_DATE) );
+ ShellCommandRegisterCommandName(L"l2time", ShellCommandRunTime , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_TIME) );
+ ShellCommandRegisterCommandName(L"l2timezone", ShellCommandRunTimeZone, ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_TIMEZONE));
+ DEBUG_CODE_END();
+ }
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Destructor for the library. free any resources.
+
+ @param ImageHandle The image handle of the process.
+ @param SystemTable The EFI System Table pointer.
+
+ @retval EFI_SUCCESS Always returned.
+**/
+EFI_STATUS
+EFIAPI
+ShellLevel2CommandsLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ if (gShellLevel2HiiHandle != NULL) {
+ HiiRemovePackages(gShellLevel2HiiHandle);
+ }
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function to clean up paths. Removes the following items:
+ single periods in the path (no need for the current directory tag)
+ double periods in the path and removes a single parent directory.
+
+ This will be done inline and the resultant string may be be 'too big'.
+
+ @param[in] PathToReturn The pointer to the string containing the path.
+
+ @return PathToReturn is always returned.
+**/
+CHAR16*
+EFIAPI
+CleanPath(
+ IN CHAR16 *PathToReturn
+ )
+{
+ CHAR16 *TempString;
+ UINTN TempSize;
+ if (PathToReturn==NULL) {
+ return(NULL);
+ }
+ //
+ // Fix up the directory name
+ //
+ while ((TempString = StrStr(PathToReturn, L"\\..\\")) != NULL) {
+ *TempString = CHAR_NULL;
+ TempString += 4;
+ ChopLastSlash(PathToReturn);
+ TempSize = StrSize(TempString);
+ CopyMem(PathToReturn+StrLen(PathToReturn), TempString, TempSize);
+ }
+ if ((TempString = StrStr(PathToReturn, L"\\..")) != NULL && *(TempString + 3) == CHAR_NULL) {
+ *TempString = CHAR_NULL;
+ ChopLastSlash(PathToReturn);
+ }
+ while ((TempString = StrStr(PathToReturn, L"\\.\\")) != NULL) {
+ *TempString = CHAR_NULL;
+ TempString += 2;
+ TempSize = StrSize(TempString);
+ CopyMem(PathToReturn+StrLen(PathToReturn), TempString, TempSize);
+ }
+ if ((TempString = StrStr(PathToReturn, L"\\.")) != NULL && *(TempString + 2) == CHAR_NULL) {
+ *TempString = CHAR_NULL;
+ }
+ return (PathToReturn);
+}
+
+/**
+ returns a fully qualified directory (contains a map drive at the begining)
+ path from a unknown directory path.
+
+ If Path is already fully qualified this will return a duplicat otherwise this
+ will use get the current directory and use that to build the fully qualified
+ version.
+
+ if the return value is not NULL it must be caller freed.
+
+ @param[in] Path The unknown Path Value
+
+ @retval NULL A memory allocation failed
+ @retval NULL a fully qualified path could not be discovered.
+ @retval other pointer to a fuly qualified path.
+**/
+CHAR16*
+EFIAPI
+GetFullyQualifiedPath(
+ IN CONST CHAR16* Path
+ )
+{
+ CHAR16 *PathToReturn;
+ UINTN Size;
+ CONST CHAR16 *CurDir;
+
+ PathToReturn = NULL;
+ Size = 0;
+
+ ASSERT((PathToReturn == NULL && Size == 0) || (PathToReturn != NULL));
+ //
+ // convert a local path to an absolute path
+ //
+ if (StrStr(Path, L":") == NULL) {
+ CurDir = gEfiShellProtocol->GetCurDir(NULL);
+ StrnCatGrow(&PathToReturn, &Size, CurDir, 0);
+ if (*Path == L'\\') {
+ Path++;
+ }
+ }
+ StrnCatGrow(&PathToReturn, &Size, Path, 0);
+
+ CleanPath(PathToReturn);
+
+ while (PathToReturn[StrLen(PathToReturn)-1] == L'*') {
+ PathToReturn[StrLen(PathToReturn)-1] = CHAR_NULL;
+ }
+
+ return (PathToReturn);
+}
+
+/**
+ Function to verify all intermediate directories in the path.
+
+ @param[in] Path The pointer to the path to fix.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+VerifyIntermediateDirectories (
+ IN CONST CHAR16 *Path
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *PathCopy;
+ CHAR16 *TempSpot;
+ SHELL_FILE_HANDLE FileHandle;
+
+ ASSERT(Path != NULL);
+
+ Status = EFI_SUCCESS;
+ PathCopy = NULL;
+ PathCopy = StrnCatGrow(&PathCopy, NULL, Path, 0);
+ FileHandle = NULL;
+
+ for (TempSpot = &PathCopy[StrLen(PathCopy)-1] ; *TempSpot != CHAR_NULL && *TempSpot != L'\\' ; TempSpot = &PathCopy[StrLen(PathCopy)-1]){
+ *TempSpot = CHAR_NULL;
+ }
+ if (*TempSpot == L'\\') {
+ *TempSpot = CHAR_NULL;
+ }
+
+ if (PathCopy != NULL && *PathCopy != CHAR_NULL) {
+ Status = VerifyIntermediateDirectories(PathCopy);
+
+ if (PathCopy[StrLen(PathCopy)-1] != L':') {
+ if (!EFI_ERROR(Status)) {
+ Status = ShellOpenFileByName(PathCopy, &FileHandle, EFI_FILE_MODE_READ, 0);
+ if (FileHandle != NULL) {
+ ShellCloseFile(&FileHandle);
+ }
+ }
+ }
+ }
+
+ SHELL_FREE_NON_NULL(PathCopy);
+
+ return (Status);
+}
+
+// be lazy and borrow from baselib.
+CHAR16
+EFIAPI
+InternalCharToUpper (
+ IN CONST CHAR16 Char
+ );
+
+CONST CHAR16*
+EFIAPI
+StrniCmp(
+ IN CONST CHAR16 *Source,
+ IN CONST CHAR16 *Target,
+ IN CONST UINTN Count
+ )
+{
+ UINTN LoopCount;
+ CHAR16 Char1;
+ CHAR16 Char2;
+
+ ASSERT(Source != NULL);
+ ASSERT(Target != NULL);
+
+ for (LoopCount = 0 ; LoopCount < Count ; LoopCount++) {
+ Char1 = InternalCharToUpper(Source[LoopCount]);
+ Char2 = InternalCharToUpper(Target[LoopCount]);
+ if (Char1 != Char2) {
+ return (&Source[LoopCount]);
+ }
+ }
+ return (NULL);
+}
+
diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.h b/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.h
new file mode 100644
index 0000000000..c04acccf05
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.h
@@ -0,0 +1,297 @@
+/** @file
+ Main file for NULL named library for level 2 shell command functions.
+
+ these functions are:
+ attrib, cd, cp, date*, time*, rm, reset,
+ load, ls, map, mkdir, mv, parse, set, timezone*
+
+
+ * functions are non-interactive only
+
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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 <Uefi.h>
+#include <ShellBase.h>
+
+#include <Protocol/EfiShell.h>
+#include <Protocol/EfiShellParameters.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/UnicodeCollation.h>
+#include <Protocol/DevicePathToText.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/ShellCommandLib.h>
+#include <Library/ShellLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HiiLib.h>
+#include <Library/SortLib.h>
+#include <Library/FileHandleLib.h>
+
+extern CONST CHAR16 mFileName[];
+extern EFI_HANDLE gShellLevel2HiiHandle;
+extern CONST EFI_GUID gShellLevel2HiiGuid;
+
+/**
+ Function for 'attrib' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunAttrib (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'date' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDate (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'time' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunTime (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'load' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunLoad (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'ls' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunLs (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'map' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunMap (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'reset' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunReset (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'timezone' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunTimeZone (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'set' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunSet (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'mkdir' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunMkDir (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'cd' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunCd (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'cp' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunCp (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'parse' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunParse (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'rm' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunRm (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'mv' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunMv (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ returns a fully qualified directory (contains a map drive at the begining)
+ path from a unknown directory path.
+
+ If Path is already fully qualified this will return a duplicat otherwise this
+ will use get the current directory and use that to build the fully qualified
+ version.
+
+ if the return value is not NULL it must be caller freed.
+
+ @param[in] Path The unknown Path Value
+
+ @retval NULL A memory allocation failed
+ @retval NULL a fully qualified path could not be discovered.
+ @retval other pointer to a fuly qualified path.
+**/
+CHAR16*
+EFIAPI
+GetFullyQualifiedPath(
+ IN CONST CHAR16* Path
+ );
+
+/**
+ Function to verify all intermediate directories in the path.
+
+ @param[in] Path The pointer to the path to fix.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+VerifyIntermediateDirectories (
+ IN CONST CHAR16 *Path
+ );
+
+/**
+ CaseInsensitive length limited string comparison.
+
+ @param[in] Source Pointer to first string.
+ @param[in] Target Pointer to second string.
+ @param[in] Count Number of characters to compare.
+
+ @retval 0 The strings are the same.
+ @return non-zero if the strings are different.
+**/
+CONST CHAR16*
+EFIAPI
+StrniCmp(
+ IN CONST CHAR16 *Source,
+ IN CONST CHAR16 *Target,
+ IN CONST UINTN Count
+ );
diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf b/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf
new file mode 100644
index 0000000000..9280ad5cbd
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf
@@ -0,0 +1,82 @@
+## @file
+# Provides shell level 2 functions
+#
+# Copyright (c) 2009, Intel Corporation.All rights reserved. <BR>
+#
+# 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 = UefiShellLevel2CommandsLib
+ FILE_GUID = CBF3931C-A2DF-40e5-B77E-CCA9555E9755
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER
+ CONSTRUCTOR = ShellLevel2CommandsLibConstructor
+ DESTRUCTOR = ShellLevel2CommandsLibDestructor
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ UefiShellLevel2CommandsLib.c
+ UefiShellLevel2CommandsLib.h
+ UefiShellLevel2CommandsLib.uni
+ TimeDate.c
+ Load.c
+ Ls.c
+ Map.c
+ Reset.c
+ Set.c
+ MkDir.c
+ Cd.c
+ Cp.c
+ Parse.c
+ Rm.c
+ Mv.c
+ Attrib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ ShellCommandLib
+ ShellLib
+ UefiLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ PcdLib
+ HiiLib
+ HandleParsingLib
+
+[Protocols]
+ gEfiUnicodeCollation2ProtocolGuid # ALWAYS_CONSUMED
+ gEfiShellProtocolGuid # ALWAYS_CONSUMED
+ gEfiShellParametersProtocolGuid # ALWAYS_CONSUMED
+ gEfiDevicePathProtocolGuid # ALWAYS_CONSUMED
+ gEfiLoadedImageProtocolGuid # ALWAYS_CONSUMED
+ gEfiSimpleFileSystemProtocolGuid # ALWAYS_CONSUMED
+ gEfiDevicePathToTextProtocolGuid # ALWAYS_CONSUMED
+
+[Pcd.common]
+ gEfiShellPkgTokenSpaceGuid.PcdShellSupportLevel # ALWAYS_CONSUMED
+ gEfiShellPkgTokenSpaceGuid.PcdShellFileOperationSize # ALWAYS_CONSUMED
+
+[Guids]
+ gEfiFileSystemInfoGuid
+ gEfiFileInfoGuid
diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.uni b/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.uni
new file mode 100644
index 0000000000..27b1053354
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.uni
Binary files differ
diff --git a/ShellPkg/Library/UefiShellLevel3CommandsLib/Alias.c b/ShellPkg/Library/UefiShellLevel3CommandsLib/Alias.c
new file mode 100644
index 0000000000..da53af4c5c
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel3CommandsLib/Alias.c
@@ -0,0 +1,162 @@
+/** @file
+ Main file for Alias shell level 3 function.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved. <BR>
+ 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 "UefiShellLevel3CommandsLib.h"
+
+#include <Library/ShellLib.h>
+
+/**
+ Print out each alias registered with the Shell.
+
+ @retval STATUS_SUCCESS the printout was sucessful
+ @return any return code from GetNextVariableName except EFI_NOT_FOUND
+**/
+SHELL_STATUS
+EFIAPI
+PrintAllShellAlias(
+ VOID
+ )
+{
+ CONST CHAR16 *ConstAllAliasList;
+ CHAR16 *Alias;
+ CONST CHAR16 *Command;
+ CHAR16 *Walker;
+ BOOLEAN Volatile;
+
+ Volatile = FALSE;
+
+ ConstAllAliasList = gEfiShellProtocol->GetAlias(NULL, NULL);
+ if (ConstAllAliasList == NULL) {
+ return (SHELL_SUCCESS);
+ }
+ Alias = AllocateZeroPool(StrSize(ConstAllAliasList));
+ Walker = (CHAR16*)ConstAllAliasList;
+
+ do {
+ CopyMem(Alias, Walker, StrSize(Walker));
+ Walker = StrStr(Alias, L";");
+ if (Walker != NULL) {
+ Walker[0] = CHAR_NULL;
+ Walker = Walker + 1;
+ }
+ Command = gEfiShellProtocol->GetAlias(Alias, &Volatile);
+ if (ShellCommandIsOnAliasList(Alias)) {
+ Volatile = FALSE;
+ }
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_ALIAS_OUTPUT), gShellLevel3HiiHandle, !Volatile?L' ':L'*', Alias, Command);
+ } while (Walker != NULL && Walker[0] != CHAR_NULL);
+
+ FreePool(Alias);
+
+ return (SHELL_SUCCESS);
+}
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-v", TypeFlag},
+ {L"-d", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'alias' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunAlias (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ CONST CHAR16 *Param1;
+ CONST CHAR16 *Param2;
+
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ Param1 = ShellCommandLineGetRawValue(Package, 1);
+ Param2 = ShellCommandLineGetRawValue(Package, 2);
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ }
+ if (ShellCommandLineGetCount(Package) == 1) {
+ //
+ // print out alias'
+ //
+ Status = PrintAllShellAlias();
+ } else if (ShellCommandLineGetFlag(Package, L"-d")) {
+ //
+ // delete an alias
+ //
+ Status = gEfiShellProtocol->SetAlias(Param1, NULL, TRUE, FALSE);
+ } else if (ShellCommandLineGetCount(Package) == 3) {
+ //
+ // must be adding an alias
+ //
+ Status = gEfiShellProtocol->SetAlias(Param2, Param1, FALSE, ShellCommandLineGetFlag(Package, L"-v"));
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_ACCESS_DENIED) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellLevel3HiiHandle);
+ ShellStatus = SHELL_ACCESS_DENIED;
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel3HiiHandle, Status);
+ ShellStatus = SHELL_DEVICE_ERROR;
+ }
+ }
+ } else if (ShellCommandLineGetCount(Package) == 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel3HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel3HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ return (ShellStatus);
+}
diff --git a/ShellPkg/Library/UefiShellLevel3CommandsLib/Cls.c b/ShellPkg/Library/UefiShellLevel3CommandsLib/Cls.c
new file mode 100644
index 0000000000..019aaf7231
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel3CommandsLib/Cls.c
@@ -0,0 +1,135 @@
+/** @file
+ Main file for attrib shell level 2 function.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved. <BR>
+ 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 "UefiShellLevel3CommandsLib.h"
+
+/**
+ Function for 'cls' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunCls (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *Message;
+ UINTN Background;
+ UINTN ForeColor;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ CONST CHAR16 *Param1;
+
+ ShellStatus = SHELL_SUCCESS;
+ ProblemParam = NULL;
+ Background = 0;
+
+ //
+ // Initialize variables
+ //
+ Message = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ } else {
+ //
+ // If there are 0 value parameters, clear sceen
+ //
+ Param1 = ShellCommandLineGetRawValue(Package, 1);
+ if (Param1 == NULL) {
+ //
+ // clear screen
+ //
+ gST->ConOut->ClearScreen (gST->ConOut);
+ } else if (ShellCommandLineGetCount(Package) > 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel3HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ if (StrDecimalToUintn(Param1) > 7 || StrLen(Param1) > 1 || !ShellIsDecimalDigitCharacter(*Param1)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, Param1);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ switch (StrDecimalToUintn(Param1)) {
+ case 0:
+ Background = EFI_BACKGROUND_BLACK;
+ break;
+ case 1:
+ Background = EFI_BACKGROUND_BLUE;
+ break;
+ case 2:
+ Background = EFI_BACKGROUND_GREEN;
+ break;
+ case 3:
+ Background = EFI_BACKGROUND_CYAN;
+ break;
+ case 4:
+ Background = EFI_BACKGROUND_RED;
+ break;
+ case 5:
+ Background = EFI_BACKGROUND_MAGENTA;
+ break;
+ case 6:
+ Background = EFI_BACKGROUND_BROWN;
+ break;
+ case 7:
+ Background = EFI_BACKGROUND_LIGHTGRAY;
+ break;
+ }
+ ForeColor = (~StrDecimalToUintn(Param1)) & 0xF;
+ Status = gST->ConOut->SetAttribute (gST->ConOut, ForeColor | Background);
+ ASSERT_EFI_ERROR(Status);
+ Status = gST->ConOut->ClearScreen (gST->ConOut);
+ ASSERT_EFI_ERROR(Status);
+ }
+ }
+ }
+ }
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+
+ //
+ // return the status
+ //
+ return (ShellStatus);
+}
+
diff --git a/ShellPkg/Library/UefiShellLevel3CommandsLib/Echo.c b/ShellPkg/Library/UefiShellLevel3CommandsLib/Echo.c
new file mode 100644
index 0000000000..dc6bca0b8a
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel3CommandsLib/Echo.c
@@ -0,0 +1,116 @@
+/** @file
+ Main file for Echo shell level 3 function.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved. <BR>
+ 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 "UefiShellLevel3CommandsLib.h"
+
+#include <Library/ShellLib.h>
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-on", TypeFlag},
+ {L"-off", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'echo' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunEcho (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+// CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ UINTN ParamCount;
+
+// ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParseEx (ParamList, &Package, NULL, TRUE, TRUE);
+// if (EFI_ERROR(Status)) {
+// if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+// ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, ProblemParam);
+// FreePool(ProblemParam);
+// ShellStatus = SHELL_INVALID_PARAMETER;
+// } else {
+// ASSERT(FALSE);
+// }
+// } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ }
+ if (ShellCommandLineGetFlag(Package, L"-on")) {
+ //
+ // Turn it on
+ //
+ ShellCommandSetEchoState(TRUE);
+ } else if (ShellCommandLineGetFlag(Package, L"-off")) {
+ //
+ // turn it off
+ //
+ ShellCommandSetEchoState(FALSE);
+ } else if (ShellCommandLineGetRawValue(Package, 1) == NULL) {
+ //
+ // output its current state
+ //
+ if (ShellCommandGetEchoState()) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_ECHO_ON), gShellLevel3HiiHandle);
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_ECHO_OFF), gShellLevel3HiiHandle);
+ }
+ } else {
+ //
+ // print the line
+ //
+ for ( ParamCount = 1
+ ; ShellCommandLineGetRawValue(Package, ParamCount) != NULL
+ ; ParamCount++
+ ) {
+ if (ShellCommandLineGetRawValue(Package, ParamCount+1) != NULL) {
+ ShellPrintEx(-1, -1, L"%s ", ShellCommandLineGetRawValue(Package, ParamCount));
+ } else {
+ ShellPrintEx(-1, -1, L"%s", ShellCommandLineGetRawValue(Package, ParamCount));
+ }
+ }
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_CRLF), gShellLevel3HiiHandle);
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+// }
+
+ return (ShellStatus);
+}
+
diff --git a/ShellPkg/Library/UefiShellLevel3CommandsLib/GetMtc.c b/ShellPkg/Library/UefiShellLevel3CommandsLib/GetMtc.c
new file mode 100644
index 0000000000..ce1eb1fcf0
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel3CommandsLib/GetMtc.c
@@ -0,0 +1,101 @@
+/** @file
+ Main file for GetMtc shell level 3 function.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved. <BR>
+ 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 "UefiShellLevel3CommandsLib.h"
+
+#include <Library/ShellLib.h>
+
+/**
+ Function for 'getmtc' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunGetMtc (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ UINT64 Mtc;
+
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ } else if (ShellCommandLineGetRawValue(Package, 1) != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel3HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // Get the monotonic counter count
+ //
+ Status = gBS->GetNextMonotonicCount(&Mtc);
+ switch(Status) {
+ case EFI_DEVICE_ERROR:
+ ShellStatus = SHELL_DEVICE_ERROR;
+ break;
+ case EFI_SECURITY_VIOLATION:
+ ShellStatus = SHELL_SECURITY_VIOLATION;
+ break;
+ default:
+ if (EFI_ERROR(Status)) {
+ ShellStatus = SHELL_DEVICE_ERROR;
+ }
+ }
+
+ //
+ // print it...
+ //
+ if (ShellStatus == SHELL_SUCCESS) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GET_MTC_OUTPUT), gShellLevel3HiiHandle, Mtc);
+ }
+ }
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ return (ShellStatus);
+}
+
diff --git a/ShellPkg/Library/UefiShellLevel3CommandsLib/Help.c b/ShellPkg/Library/UefiShellLevel3CommandsLib/Help.c
new file mode 100644
index 0000000000..04e3d31dba
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel3CommandsLib/Help.c
@@ -0,0 +1,183 @@
+/** @file
+ Main file for Help shell level 3 function.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved. <BR>
+ 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 "UefiShellLevel3CommandsLib.h"
+
+#include <Library/ShellLib.h>
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-usage", TypeFlag},
+ {L"-section", TypeValue},
+ {L"-verbose", TypeFlag},
+ {L"-v", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'help' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunHelp (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ CHAR16 *OutText;
+ CONST COMMAND_LIST *CommandList;
+ CONST COMMAND_LIST *Node;
+ CHAR16 *CommandToGetHelpOn;
+ CHAR16 *SectionToGetHelpOn;
+ CHAR16 *HiiString;
+ BOOLEAN Found;
+
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ OutText = NULL;
+ CommandToGetHelpOn = NULL;
+ SectionToGetHelpOn = NULL;
+ Found = FALSE;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // Check for conflicting parameters.
+ //
+ if (ShellCommandLineGetFlag(Package, L"-usage")
+ &&ShellCommandLineGetFlag(Package, L"-section")
+ &&(ShellCommandLineGetFlag(Package, L"-verbose") || ShellCommandLineGetFlag(Package, L"-v"))
+ ){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellLevel3HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetRawValue(Package, 2) != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel3HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // Get the command name we are getting help on
+ //
+ ASSERT(CommandToGetHelpOn == NULL);
+ StrnCatGrow(&CommandToGetHelpOn, NULL, ShellCommandLineGetRawValue(Package, 1), 0);
+ if (CommandToGetHelpOn == NULL && ShellCommandLineGetFlag(Package, L"-?")) {
+ //
+ // If we dont have a command and we got a simple -?
+ // we are looking for help on help command.
+ //
+ StrnCatGrow(&CommandToGetHelpOn, NULL, L"help", 0);
+ }
+
+ if (CommandToGetHelpOn == NULL) {
+ StrnCatGrow(&CommandToGetHelpOn, NULL, L"*", 0);
+ ASSERT(SectionToGetHelpOn == NULL);
+ StrnCatGrow(&SectionToGetHelpOn, NULL, L"NAME", 0);
+ } else {
+ ASSERT(SectionToGetHelpOn == NULL);
+ //
+ // Get the section name for the given command name
+ //
+ if (ShellCommandLineGetFlag(Package, L"-section")) {
+ StrnCatGrow(&SectionToGetHelpOn, NULL, ShellCommandLineGetValue(Package, L"-section"), 0);
+ } else if (ShellCommandLineGetFlag(Package, L"-usage")) {
+ StrnCatGrow(&SectionToGetHelpOn, NULL, L"NAME,SYNOPSIS", 0);
+ } else if (ShellCommandLineGetFlag(Package, L"-verbose") || ShellCommandLineGetFlag(Package, L"-v")) {
+ } else {
+ StrnCatGrow(&SectionToGetHelpOn, NULL, L"NAME", 0);
+ }
+ }
+
+ if (gUnicodeCollation->StriColl(gUnicodeCollation, CommandToGetHelpOn, L"special") == 0) {
+ //
+ // we need info on the special characters
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_SC_HEADER), gShellLevel3HiiHandle);
+ HiiString = HiiGetString(gShellLevel3HiiHandle, STRING_TOKEN(STR_HELP_SC_DATA), NULL);
+ ShellPrintEx(-1, -1, L"%s", HiiString);
+ FreePool(HiiString);
+ Found = TRUE;
+ } else {
+ CommandList = ShellCommandGetCommandList();
+ ASSERT(CommandList != NULL);
+ for ( Node = (COMMAND_LIST*)GetFirstNode(&CommandList->Link)
+ ; CommandList != NULL && !IsListEmpty(&CommandList->Link) && !IsNull(&CommandList->Link, &Node->Link)
+ ; Node = (COMMAND_LIST*)GetNextNode(&CommandList->Link, &Node->Link)
+ ){
+ if (gUnicodeCollation->MetaiMatch(gUnicodeCollation, Node->CommandString, CommandToGetHelpOn)) {
+ //
+ // We have a command to look for help on.
+ //
+ Status = gEfiShellProtocol->GetHelpText(Node->CommandString, SectionToGetHelpOn, &OutText);
+ if (EFI_ERROR(Status) || OutText == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_NF), gShellLevel3HiiHandle, Node->CommandString);
+ ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ while (OutText[StrLen(OutText)-1] == L'\r' || OutText[StrLen(OutText)-1] == L'\n' || OutText[StrLen(OutText)-1] == L' ') {
+ OutText[StrLen(OutText)-1] = CHAR_NULL;
+ }
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_COMMAND), gShellLevel3HiiHandle, Node->CommandString, OutText);
+ FreePool(OutText);
+ OutText = NULL;
+ Found = TRUE;
+ }
+ }
+ }
+ }
+
+ if (!Found && ShellStatus == SHELL_SUCCESS) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_NF), gShellLevel3HiiHandle, CommandToGetHelpOn);
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+ }
+ }
+ if (CommandToGetHelpOn != NULL) {
+ FreePool(CommandToGetHelpOn);
+ }
+ if (SectionToGetHelpOn != NULL) {
+ FreePool(SectionToGetHelpOn);
+ }
+
+ return (ShellStatus);
+}
+
diff --git a/ShellPkg/Library/UefiShellLevel3CommandsLib/Pause.c b/ShellPkg/Library/UefiShellLevel3CommandsLib/Pause.c
new file mode 100644
index 0000000000..facacaac7d
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel3CommandsLib/Pause.c
@@ -0,0 +1,106 @@
+/** @file
+ Main file for Pause shell level 3 function.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved. <BR>
+ 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 "UefiShellLevel3CommandsLib.h"
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-q", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'pause' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunPause (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ SHELL_PROMPT_RESPONSE *Resp;
+
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ if (!gEfiShellProtocol->BatchIsActive()) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_SCRIPT_ONLY), gShellLevel3HiiHandle);
+ return (SHELL_UNSUPPORTED);
+ }
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ } else if (ShellCommandLineGetRawValue(Package, 1) != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel3HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ if (!ShellCommandLineGetFlag(Package, L"-q")) {
+ Status = ShellPromptForResponseHii(ShellPromptResponseTypeQuitContinue, STRING_TOKEN (STR_PAUSE_PROMPT), gShellLevel3HiiHandle, (VOID**)&Resp);
+ } else {
+ Status = ShellPromptForResponse(ShellPromptResponseTypeQuitContinue, NULL, (VOID**)&Resp);
+ }
+ ASSERT_EFI_ERROR(Status);
+
+ if (Resp == NULL || *Resp == ShellPromptResponseQuit) {
+ ShellCommandRegisterExit(TRUE);
+ ShellStatus = SHELL_ABORTED;
+ }
+
+ if (Resp != NULL) {
+ FreePool(Resp);
+ }
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+ }
+
+
+ return (ShellStatus);
+}
+
diff --git a/ShellPkg/Library/UefiShellLevel3CommandsLib/Touch.c b/ShellPkg/Library/UefiShellLevel3CommandsLib/Touch.c
new file mode 100644
index 0000000000..0252f7748d
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel3CommandsLib/Touch.c
@@ -0,0 +1,265 @@
+/** @file
+ Main file for Touch shell level 3 function.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved. <BR>
+ 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 "UefiShellLevel3CommandsLib.h"
+
+#include <Library/ShellLib.h>
+
+EFI_STATUS
+EFIAPI
+TouchFileByHandle (
+ IN EFI_HANDLE Handle
+ )
+{
+ EFI_STATUS Status;
+ EFI_FILE_INFO *FileInfo;
+
+ FileInfo = gEfiShellProtocol->GetFileInfo(Handle);
+ if ((FileInfo->Attribute & EFI_FILE_READ_ONLY) != 0){
+ return (EFI_ACCESS_DENIED);
+ }
+ Status = gRT->GetTime(&FileInfo->ModificationTime, NULL);
+ ASSERT_EFI_ERROR(Status);
+ CopyMem(&FileInfo->LastAccessTime, &FileInfo->ModificationTime, sizeof(EFI_TIME));
+
+ Status = gEfiShellProtocol->SetFileInfo(Handle, FileInfo);
+
+ FreePool(FileInfo);
+
+ return (Status);
+}
+
+EFI_STATUS
+EFIAPI
+DoTouchByHandle (
+ IN CONST CHAR16 *Name,
+ IN CHAR16 *FS,
+ IN SHELL_FILE_HANDLE Handle,
+ IN BOOLEAN Rec
+ )
+{
+ EFI_STATUS Status;
+ EFI_SHELL_FILE_INFO *FileList;
+ EFI_SHELL_FILE_INFO *Walker;
+ CHAR16 *TempSpot;
+
+ Status = EFI_SUCCESS;
+ FileList = NULL;
+ Walker = NULL;
+
+ if (FS == NULL) {
+ FS = StrnCatGrow(&FS, NULL, Name, 0);
+ TempSpot = StrStr(FS, L"\\");
+ if (TempSpot != NULL) {
+ *TempSpot = CHAR_NULL;
+ }
+ }
+
+ //
+ // do it
+ //
+ Status = TouchFileByHandle(Handle);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NO_OPEN), gShellLevel3HiiHandle, Name, Status);
+ return (Status);
+ }
+
+ //
+ // if it's a directory recurse...
+ //
+ if (FileHandleIsDirectory(Handle) == EFI_SUCCESS && Rec) {
+ //
+ // get each file under this directory
+ //
+ if (EFI_ERROR(gEfiShellProtocol->FindFilesInDir(Handle, &FileList))) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // recurse on each
+ //
+ for (Walker = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link)
+ ; FileList != NULL && !IsNull(&FileList->Link, &Walker->Link) && !EFI_ERROR(Status)
+ ; Walker = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Walker->Link)
+ ){
+ if ( (StrCmp(Walker->FileName, L".") != 0)
+ && (StrCmp(Walker->FileName, L"..") != 0)
+ ){
+ //
+ // Open the file since we need that handle.
+ //
+ Status = gEfiShellProtocol->OpenFileByName (Walker->FullName, &Walker->Handle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NO_OPEN), gShellLevel3HiiHandle, Walker->FullName, Status);
+ Status = EFI_ACCESS_DENIED;
+ } else {
+ Status = DoTouchByHandle(Walker->FullName, FS, Walker->Handle, TRUE);
+ gEfiShellProtocol->CloseFile(Walker->Handle);
+ Walker->Handle = NULL;
+ }
+ }
+ }
+
+ //
+ // free stuff
+ //
+ if (FileList != NULL && EFI_ERROR(gEfiShellProtocol->FreeFileList(&FileList))) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+
+ return (Status);
+}
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-r", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'touch' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunTouch (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ CONST CHAR16 *Param;
+ SHELL_STATUS ShellStatus;
+ UINTN ParamCount;
+ EFI_SHELL_FILE_INFO *FileList;
+ EFI_SHELL_FILE_INFO *Node;
+
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ ParamCount = 0;
+ FileList = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ }
+ if (ShellCommandLineGetRawValue(Package, 1) == NULL) {
+ //
+ // we insufficient parameters
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel3HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // get a list with each file specified by parameters
+ // if parameter is a directory then add all the files below it to the list
+ //
+ for ( ParamCount = 1, Param = ShellCommandLineGetRawValue(Package, ParamCount)
+ ; Param != NULL
+ ; ParamCount++, Param = ShellCommandLineGetRawValue(Package, ParamCount)
+ ){
+ Status = ShellOpenFileMetaArg((CHAR16*)Param, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, &FileList);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, (CHAR16*)Param);
+ ShellStatus = SHELL_NOT_FOUND;
+ break;
+ }
+ //
+ // make sure we completed the param parsing sucessfully...
+ // Also make sure that any previous action was sucessful
+ //
+ if (ShellStatus == SHELL_SUCCESS) {
+ //
+ // check that we have at least 1 file
+ //
+ if (FileList == NULL || IsListEmpty(&FileList->Link)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel3HiiHandle, Param);
+ continue;
+ } else {
+ //
+ // loop through the list and make sure we are not aborting...
+ //
+ for ( Node = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FileList->Link)
+ ; !IsNull(&FileList->Link, &Node->Link) && !ShellGetExecutionBreakFlag()
+ ; Node = (EFI_SHELL_FILE_INFO*)GetNextNode(&FileList->Link, &Node->Link)
+ ){
+ //
+ // make sure the file opened ok
+ //
+ if (EFI_ERROR(Node->Status)){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NO_OPEN), gShellLevel3HiiHandle, Node->FileName, Node->Status);
+ ShellStatus = SHELL_NOT_FOUND;
+ continue;
+ }
+
+ Status = DoTouchByHandle(Node->FullName, NULL, Node->Handle, ShellCommandLineGetFlag(Package, L"-r"));
+ if (EFI_ERROR(Status) && Status != EFI_ACCESS_DENIED) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NO_OPEN), gShellLevel3HiiHandle, Node->FileName, Status);
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ }
+ }
+ }
+ //
+ // Free the fileList
+ //
+ if (FileList != NULL && !IsListEmpty(&FileList->Link)) {
+ Status = ShellCloseFileMetaArg(&FileList);
+ ASSERT_EFI_ERROR(Status);
+ }
+ FileList = NULL;
+ }
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ if (ShellGetExecutionBreakFlag()) {
+ return (SHELL_ABORTED);
+ }
+
+ return (ShellStatus);
+}
+
diff --git a/ShellPkg/Library/UefiShellLevel3CommandsLib/Type.c b/ShellPkg/Library/UefiShellLevel3CommandsLib/Type.c
new file mode 100644
index 0000000000..05f13f0756
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel3CommandsLib/Type.c
@@ -0,0 +1,239 @@
+/** @file
+ Main file for Type shell level 3 function.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved. <BR>
+ 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 "UefiShellLevel3CommandsLib.h"
+
+#include <Library/ShellLib.h>
+
+EFI_STATUS
+EFIAPI
+TypeFileByHandle (
+ IN EFI_HANDLE Handle,
+ BOOLEAN Ascii,
+ BOOLEAN UCS2
+ )
+{
+ UINTN ReadSize;
+ VOID *Buffer;
+ EFI_STATUS Status;
+ UINTN LoopVar;
+ CHAR16 AsciiChar;
+
+ ReadSize = PcdGet16(PcdShellFileOperationSize);
+ Buffer = AllocatePool(ReadSize);
+ if (Buffer == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ Status = ShellSetFilePosition(Handle, 0);
+ ASSERT_EFI_ERROR(Status);
+
+ while (ReadSize == ((UINTN)PcdGet16(PcdShellFileOperationSize))){
+ ZeroMem(Buffer, ReadSize);
+ Status = ShellReadFile(Handle, &ReadSize, Buffer);
+ if (EFI_ERROR(Status)){
+ break;
+ }
+
+ if (!(Ascii|UCS2)){
+ if (*(UINT16*)Buffer == UnicodeFileTag) {
+ UCS2 = TRUE;
+ Buffer = ((UINT16*)Buffer) + 1;
+ } else {
+ Ascii = TRUE;
+ }
+ }
+
+ //
+ // We want to use plain Print function here! (no color support for files)
+ //
+ if (Ascii){
+ for (LoopVar = 0 ; LoopVar < ReadSize ; LoopVar++) {
+ AsciiChar = CHAR_NULL;
+ AsciiChar = ((CHAR8*)Buffer)[LoopVar];
+ if (AsciiChar == CHAR_NULL) {
+ AsciiChar = '.';
+ }
+ Print(L"%c", AsciiChar);
+ }
+ } else {
+ Print(L"%s", Buffer);
+ }
+ }
+ Status = Print(L"\r\n", Buffer);
+ return (Status);
+}
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-a", TypeFlag},
+ {L"-u", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'type' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunType (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ CONST CHAR16 *Param;
+ SHELL_STATUS ShellStatus;
+ UINTN ParamCount;
+ EFI_SHELL_FILE_INFO *FileList;
+ EFI_SHELL_FILE_INFO *Node;
+ BOOLEAN AsciiMode;
+ BOOLEAN UnicodeMode;
+
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ ParamCount = 0;
+ FileList = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ }
+ AsciiMode = ShellCommandLineGetFlag(Package, L"-a");
+ UnicodeMode = ShellCommandLineGetFlag(Package, L"-u");
+
+ if (AsciiMode && UnicodeMode) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, L"-a & -u");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetRawValue(Package, 1) == NULL) {
+ //
+ // we insufficient parameters
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel3HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // get a list with each file specified by parameters
+ // if parameter is a directory then add all the files below it to the list
+ //
+ for ( ParamCount = 1, Param = ShellCommandLineGetRawValue(Package, ParamCount)
+ ; Param != NULL
+ ; ParamCount++, Param = ShellCommandLineGetRawValue(Package, ParamCount)
+ ){
+ Status = ShellOpenFileMetaArg((CHAR16*)Param, EFI_FILE_MODE_READ, &FileList);
+ if (EFI_ERROR(Status)) {
+ ShellStatus = SHELL_NOT_FOUND;
+ break;
+ }
+ //
+ // make sure we completed the param parsing sucessfully...
+ // Also make sure that any previous action was sucessful
+ //
+ if (ShellStatus == SHELL_SUCCESS) {
+ //
+ // check that we have at least 1 file
+ //
+ if (FileList == NULL || IsListEmpty(&FileList->Link)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel3HiiHandle, Param);
+ continue;
+ } else {
+ //
+ // loop through the list and make sure we are not aborting...
+ //
+ for ( Node = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FileList->Link)
+ ; !IsNull(&FileList->Link, &Node->Link) && !ShellGetExecutionBreakFlag()
+ ; Node = (EFI_SHELL_FILE_INFO*)GetNextNode(&FileList->Link, &Node->Link)
+ ){
+ //
+ // make sure the file opened ok
+ //
+ if (EFI_ERROR(Node->Status)){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NO_OPEN), gShellLevel3HiiHandle, Node->FileName, Node->Status);
+ ShellStatus = SHELL_NOT_FOUND;
+ continue;
+ }
+
+ //
+ // make sure its not a directory
+ //
+ if (FileHandleIsDirectory(Node->Handle) == EFI_SUCCESS) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_IS_DIR), gShellLevel3HiiHandle, Node->FileName);
+ ShellStatus = SHELL_NOT_FOUND;
+ continue;
+ }
+
+ //
+ // do it
+ //
+ Status = TypeFileByHandle(Node->Handle, AsciiMode, UnicodeMode);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TYP_ERROR), gShellLevel3HiiHandle, Node->FileName, Status);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ ASSERT(ShellStatus == SHELL_SUCCESS);
+ }
+ }
+ }
+ //
+ // Free the fileList
+ //
+ if (FileList != NULL && !IsListEmpty(&FileList->Link)) {
+ Status = ShellCloseFileMetaArg(&FileList);
+ }
+ ASSERT_EFI_ERROR(Status);
+ FileList = NULL;
+ }
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ if (ShellGetExecutionBreakFlag()) {
+ return (SHELL_ABORTED);
+ }
+
+ return (ShellStatus);
+}
+
diff --git a/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.c b/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.c
new file mode 100644
index 0000000000..3ce39d7ea2
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.c
@@ -0,0 +1,94 @@
+/** @file
+ Main file for NULL named library for level 3 shell command functions.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved. <BR>
+ 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 "UefiShellLevel3CommandsLib.h"
+
+CONST CHAR16 gShellLevel3FileName[] = L"ShellCommands";
+EFI_HANDLE gShellLevel3HiiHandle = NULL;
+STATIC CONST EFI_GUID gShellLevel3HiiGuid = \
+ { \
+ 0x4344558d, 0x4ef9, 0x4725, { 0xb1, 0xe4, 0x33, 0x76, 0xe8, 0xd6, 0x97, 0x4f } \
+ };
+
+CONST CHAR16*
+EFIAPI
+ShellCommandGetManFileNameLevel3 (
+ VOID
+ )
+{
+ return (gShellLevel3FileName);
+}
+
+/**
+ Constructor for the Shell Level 3 Commands library.
+
+ Install the handlers for level 3 UEFI Shell 2.0 commands.
+
+ @param ImageHandle the image handle of the process
+ @param SystemTable the EFI System Table pointer
+
+ @retval EFI_SUCCESS the shell command handlers were installed sucessfully
+ @retval EFI_UNSUPPORTED the shell level required was not found.
+**/
+EFI_STATUS
+EFIAPI
+ShellLevel3CommandsLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ gShellLevel3HiiHandle = NULL;
+ //
+ // if shell level is less than 3 do nothing
+ //
+ if (PcdGet8(PcdShellSupportLevel) < 3) {
+ return (EFI_UNSUPPORTED);
+ }
+
+ gShellLevel3HiiHandle = HiiAddPackages (&gShellLevel3HiiGuid, gImageHandle, UefiShellLevel3CommandsLibStrings, NULL);
+ if (gShellLevel3HiiHandle == NULL) {
+ return (EFI_DEVICE_ERROR);
+ }
+ //
+ // install our shell command handlers that are always installed
+ //
+ // Note: that Time, Timezone, and Date are part of level 2 library
+ //
+ ShellCommandRegisterCommandName(L"type", ShellCommandRunType , ShellCommandGetManFileNameLevel3, 3, L"", TRUE , gShellLevel3HiiHandle, STRING_TOKEN(STR_GET_HELP_TYPE));
+ ShellCommandRegisterCommandName(L"touch", ShellCommandRunTouch , ShellCommandGetManFileNameLevel3, 3, L"", TRUE , gShellLevel3HiiHandle, STRING_TOKEN(STR_GET_HELP_TOUCH));
+ ShellCommandRegisterCommandName(L"ver", ShellCommandRunVer , ShellCommandGetManFileNameLevel3, 3, L"", TRUE , gShellLevel3HiiHandle, STRING_TOKEN(STR_GET_HELP_VER));
+ ShellCommandRegisterCommandName(L"alias", ShellCommandRunAlias , ShellCommandGetManFileNameLevel3, 3, L"", TRUE , gShellLevel3HiiHandle, STRING_TOKEN(STR_GET_HELP_ALIAS));
+ ShellCommandRegisterCommandName(L"cls", ShellCommandRunCls , ShellCommandGetManFileNameLevel3, 3, L"", TRUE , gShellLevel3HiiHandle, STRING_TOKEN(STR_GET_HELP_CLS));
+ ShellCommandRegisterCommandName(L"echo", ShellCommandRunEcho , ShellCommandGetManFileNameLevel3, 3, L"", FALSE, gShellLevel3HiiHandle, STRING_TOKEN(STR_GET_HELP_ECHO));
+ ShellCommandRegisterCommandName(L"pause", ShellCommandRunPause , ShellCommandGetManFileNameLevel3, 3, L"", TRUE , gShellLevel3HiiHandle, STRING_TOKEN(STR_GET_HELP_PAUSE));
+ ShellCommandRegisterCommandName(L"getmtc", ShellCommandRunGetMtc , ShellCommandGetManFileNameLevel3, 3, L"", TRUE , gShellLevel3HiiHandle, STRING_TOKEN(STR_GET_HELP_GETMTC));
+ ShellCommandRegisterCommandName(L"help", ShellCommandRunHelp , ShellCommandGetManFileNameLevel3, 3, L"", TRUE , gShellLevel3HiiHandle, STRING_TOKEN(STR_GET_HELP_HELP));
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Destructor for the library. free any resources.
+**/
+EFI_STATUS
+EFIAPI
+ShellLevel3CommandsLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ if (gShellLevel3HiiHandle != NULL) {
+ HiiRemovePackages(gShellLevel3HiiHandle);
+ }
+ return (EFI_SUCCESS);
+}
diff --git a/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.h b/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.h
new file mode 100644
index 0000000000..b6ac99658d
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.h
@@ -0,0 +1,156 @@
+/** @file
+ header file for NULL named library for level 3 shell command functions.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved. <BR>
+ 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 <Uefi.h>
+#include <ShellBase.h>
+
+#include <Protocol/EfiShell.h>
+#include <Protocol/EfiShellParameters.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/UnicodeCollation.h>
+#include <Protocol/DevicePathToText.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/ShellCommandLib.h>
+#include <Library/ShellLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HiiLib.h>
+#include <Library/FileHandleLib.h>
+
+extern EFI_HANDLE gShellLevel3HiiHandle;
+
+/**
+ Function for 'type' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunType (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'touch' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunTouch (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'ver' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunVer (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'alias' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunAlias (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'cls' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunCls (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'echo' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunEcho (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'pause' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunPause (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'getmtc' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunGetMtc (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'help' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunHelp (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
diff --git a/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf b/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf
new file mode 100644
index 0000000000..16c6f7a2b3
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf
@@ -0,0 +1,68 @@
+## @file
+# Provides shell level 3 functions
+# Note that the interactive versions of the time, date, and timezone functions are handled in the level 2 library.
+#
+# Copyright (c) 2009-2010, Intel Corporation. All rights reserved. <BR>
+#
+# 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 = UefiShellLevel3CommandsLib
+ FILE_GUID = 71374B42-85D7-4753-AD17-AA84C3A0EB93
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER
+ CONSTRUCTOR = ShellLevel3CommandsLibConstructor
+ DESTRUCTOR = ShellLevel3CommandsLibDestructor
+
+[Sources.common]
+# note that time, timezone, and date are part of the level 2 library
+ Type.c
+ Touch.c
+ Ver.c
+ UefiShellLevel3CommandsLib.uni
+ UefiShellLevel3CommandsLib.c
+ UefiShellLevel3CommandsLib.h
+ Cls.c
+ Alias.c
+ Echo.c
+ Pause.c
+ GetMtc.c
+ Help.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ ShellCommandLib
+ ShellLib
+ UefiLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ PcdLib
+ HiiLib
+ FileHandleLib
+
+[Guids]
+ gEfiFileInfoGuid
+
+[Pcd.common]
+ gEfiShellPkgTokenSpaceGuid.PcdShellSupportLevel
+ gEfiShellPkgTokenSpaceGuid.PcdShellFileOperationSize
+
diff --git a/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.uni b/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.uni
new file mode 100644
index 0000000000..3e4a57ac7d
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.uni
Binary files differ
diff --git a/ShellPkg/Library/UefiShellLevel3CommandsLib/Ver.c b/ShellPkg/Library/UefiShellLevel3CommandsLib/Ver.c
new file mode 100644
index 0000000000..e00f4c90f5
--- /dev/null
+++ b/ShellPkg/Library/UefiShellLevel3CommandsLib/Ver.c
@@ -0,0 +1,145 @@
+/** @file
+ Main file for Ver shell level 3 function.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ 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 "UefiShellLevel3CommandsLib.h"
+
+#include <Library/ShellLib.h>
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-s", TypeFlag},
+ {L"-terse", TypeFlag},
+ {L"-t", TypeFlag},
+ {L"-_pa", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'ver' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunVer (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ UINT8 Level;
+
+ Level = PcdGet8(PcdShellSupportLevel);
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ }
+ if (ShellCommandLineGetRawValue(Package, 1) != NULL) {
+ //
+ // we have too many parameters
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel3HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ if (ShellCommandLineGetFlag(Package, L"-s")) {
+ ShellPrintHiiEx (
+ 0,
+ gST->ConOut->Mode->CursorRow,
+ NULL,
+ STRING_TOKEN (STR_VER_OUTPUT_SIMPLE),
+ gShellLevel3HiiHandle,
+ gEfiShellProtocol->MajorVersion,
+ gEfiShellProtocol->MinorVersion
+ );
+ } else {
+ ShellPrintHiiEx (
+ 0,
+ gST->ConOut->Mode->CursorRow,
+ NULL,
+ STRING_TOKEN (STR_VER_OUTPUT_SHELL),
+ gShellLevel3HiiHandle,
+ SupportLevel[Level],
+ gEfiShellProtocol->MajorVersion,
+ gEfiShellProtocol->MinorVersion
+ );
+ if (!ShellCommandLineGetFlag(Package, L"-terse") && !ShellCommandLineGetFlag(Package, L"-t")){
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_VER_EXTRA_STRING),
+ gShellLevel3HiiHandle
+ );
+
+
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_VER_OUTPUT_UEFI),
+ gShellLevel3HiiHandle,
+ (gST->Hdr.Revision&0xffff0000)>>16,
+ (gST->Hdr.Revision&0x0000ffff),
+ gST->FirmwareVendor,
+ gST->FirmwareRevision
+ );
+ }
+ }
+ //
+ // implementation specific support for displaying processor architecture
+ //
+ if (ShellCommandLineGetFlag(Package, L"-_pa")) {
+ ShellPrintEx(-1, -1, L"%d\r\n", sizeof(UINTN)==sizeof(UINT64)?64:32);
+ }
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ return (ShellStatus);
+}
+
diff --git a/ShellPkg/Library/UefiShellLib/UefiShellLib.c b/ShellPkg/Library/UefiShellLib/UefiShellLib.c
index d3cc59e9be..1694f46378 100644
--- a/ShellPkg/Library/UefiShellLib/UefiShellLib.c
+++ b/ShellPkg/Library/UefiShellLib/UefiShellLib.c
@@ -13,38 +13,36 @@
**/
#include "UefiShellLib.h"
+#include <ShellBase.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
+// globals...
//
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;
-STATIC UINTN mTotalParameterCount;
-STATIC CHAR16 *mPostReplaceFormat;
-STATIC CHAR16 *mPostReplaceFormat2;
+SHELL_PARAM_ITEM SfoParamList[] = {
+ {L"-sfo", TypeFlag},
+ {NULL, TypeMax}
+ };
+EFI_SHELL_ENVIRONMENT2 *mEfiShellEnvironment2;
+EFI_SHELL_INTERFACE *mEfiShellInterface;
+EFI_SHELL_PROTOCOL *mEfiShellProtocol;
+EFI_SHELL_PARAMETERS_PROTOCOL *mEfiShellParametersProtocol;
+EFI_HANDLE mEfiShellEnvironment2Handle;
+FILE_HANDLE_FUNCTION_MAP FileFunctionMap;
+CHAR16 *mPostReplaceFormat;
+CHAR16 *mPostReplaceFormat2;
/**
Check if a Unicode character is a hexadecimal character.
This internal function checks if a Unicode character is a
- decimal character. The valid hexadecimal character is
+ numeric character. The valid hexadecimal characters are
L'0' to L'9', L'a' to L'f', or L'A' to L'F'.
-
@param Char The character to check against.
@retval TRUE If the Char is a hexadecmial character.
@@ -55,18 +53,45 @@ BOOLEAN
EFIAPI
ShellIsHexaDecimalDigitCharacter (
IN CHAR16 Char
- ) {
+ )
+{
return (BOOLEAN) ((Char >= L'0' && Char <= L'9') || (Char >= L'A' && Char <= L'F') || (Char >= L'a' && Char <= L'f'));
}
/**
- helper function to find ShellEnvironment2 for constructor
+ Check if a Unicode character is a decimal character.
+
+ This internal function checks if a Unicode character is a
+ decimal character. The valid characters are
+ L'0' to L'9'.
+
+
+ @param Char The character to check against.
+
+ @retval TRUE If the Char is a hexadecmial character.
+ @retval FALSE If the Char is not a hexadecmial character.
+
+**/
+BOOLEAN
+EFIAPI
+ShellIsDecimalDigitCharacter (
+ IN CHAR16 Char
+ )
+{
+ return (BOOLEAN) (Char >= L'0' && Char <= L'9');
+}
+
+/**
+ Helper function to find ShellEnvironment2 for constructor.
+
+ @param[in] ImageHandle A copy of the calling image's handle.
**/
EFI_STATUS
EFIAPI
ShellFindSE2 (
IN EFI_HANDLE ImageHandle
- ) {
+ )
+{
EFI_STATUS Status;
EFI_HANDLE *Buffer;
UINTN BufferSize;
@@ -80,11 +105,11 @@ ShellFindSE2 (
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)){
+ if (EFI_ERROR (Status) || !(CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid))){
//
// figure out how big of a buffer we need.
//
@@ -93,7 +118,7 @@ ShellFindSE2 (
NULL, // ignored for ByProtocol
&BufferSize,
Buffer
- );
+ );
//
// maybe it's not there???
//
@@ -105,7 +130,7 @@ ShellFindSE2 (
NULL, // ignored for ByProtocol
&BufferSize,
Buffer
- );
+ );
}
if (!EFI_ERROR (Status) && Buffer != NULL) {
//
@@ -119,8 +144,8 @@ ShellFindSE2 (
ImageHandle,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid) != FALSE) {
+ );
+ if (CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid)) {
mEfiShellEnvironment2Handle = Buffer[HandleIndex];
Status = EFI_SUCCESS;
break;
@@ -134,44 +159,58 @@ ShellFindSE2 (
return (Status);
}
+/*/
+ Function to do most of the work of the constructor. Allows for calling
+ multiple times without complete re-initialization.
+
+ @param[in] ImageHandle A copy of the ImageHandle.
+ @param[in] SystemTable A pointer to the SystemTable for the application.
+**/
EFI_STATUS
EFIAPI
ShellLibConstructorWorker (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
- ) {
- EFI_STATUS Status;
-
+ )
+{
+ EFI_STATUS Status;
mPostReplaceFormat = AllocateZeroPool (PcdGet16 (PcdShellPrintBufferSize));
ASSERT (mPostReplaceFormat != NULL);
mPostReplaceFormat2 = AllocateZeroPool (PcdGet16 (PcdShellPrintBufferSize));
ASSERT (mPostReplaceFormat2 != NULL);
//
- // Set the parameter count to an invalid number
- //
- mTotalParameterCount = (UINTN)(-1);
-
- //
// UEFI 2.0 shell interfaces (used preferentially)
//
- Status = gBS->OpenProtocol(ImageHandle,
- &gEfiShellProtocolGuid,
- (VOID **)&mEfiShellProtocol,
- ImageHandle,
- NULL,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
+ Status = gBS->OpenProtocol(
+ ImageHandle,
+ &gEfiShellProtocolGuid,
+ (VOID **)&mEfiShellProtocol,
+ ImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
if (EFI_ERROR(Status)) {
- mEfiShellProtocol = NULL;
+ //
+ // Search for the shell protocol
+ //
+ Status = gBS->LocateProtocol(
+ &gEfiShellProtocolGuid,
+ NULL,
+ (VOID **)&mEfiShellProtocol
+ );
+ if (EFI_ERROR(Status)) {
+ mEfiShellProtocol = NULL;
+ }
}
- Status = gBS->OpenProtocol(ImageHandle,
- &gEfiShellParametersProtocolGuid,
- (VOID **)&mEfiShellParametersProtocol,
- ImageHandle,
- NULL,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
+ Status = gBS->OpenProtocol(
+ ImageHandle,
+ &gEfiShellParametersProtocolGuid,
+ (VOID **)&mEfiShellParametersProtocol,
+ ImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
if (EFI_ERROR(Status)) {
mEfiShellParametersProtocol = NULL;
}
@@ -192,7 +231,7 @@ ShellLibConstructorWorker (
ImageHandle,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
+ );
if (EFI_ERROR(Status)) {
mEfiShellInterface = NULL;
}
@@ -202,7 +241,7 @@ ShellLibConstructorWorker (
// 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) ) {
+ (mEfiShellProtocol != NULL && mEfiShellParametersProtocol != NULL) ) {
if (mEfiShellProtocol != NULL) {
FileFunctionMap.GetFileInfo = mEfiShellProtocol->GetFileInfo;
FileFunctionMap.SetFileInfo = mEfiShellProtocol->SetFileInfo;
@@ -215,16 +254,16 @@ ShellLibConstructorWorker (
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;
+ FileFunctionMap.GetFileInfo = (EFI_SHELL_GET_FILE_INFO)FileHandleGetInfo;
+ FileFunctionMap.SetFileInfo = (EFI_SHELL_SET_FILE_INFO)FileHandleSetInfo;
+ FileFunctionMap.ReadFile = (EFI_SHELL_READ_FILE)FileHandleRead;
+ FileFunctionMap.WriteFile = (EFI_SHELL_WRITE_FILE)FileHandleWrite;
+ FileFunctionMap.CloseFile = (EFI_SHELL_CLOSE_FILE)FileHandleClose;
+ FileFunctionMap.DeleteFile = (EFI_SHELL_DELETE_FILE)FileHandleDelete;
+ FileFunctionMap.GetFilePosition = (EFI_SHELL_GET_FILE_POSITION)FileHandleGetPosition;
+ FileFunctionMap.SetFilePosition = (EFI_SHELL_SET_FILE_POSITION)FileHandleSetPosition;
+ FileFunctionMap.FlushFile = (EFI_SHELL_FLUSH_FILE)FileHandleFlush;
+ FileFunctionMap.GetFileSize = (EFI_SHELL_GET_FILE_SIZE)FileHandleGetSize;
}
return (EFI_SUCCESS);
}
@@ -246,8 +285,8 @@ EFIAPI
ShellLibConstructor (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
- ) {
-
+ )
+{
mEfiShellEnvironment2 = NULL;
mEfiShellProtocol = NULL;
mEfiShellParametersProtocol = NULL;
@@ -267,14 +306,21 @@ ShellLibConstructor (
}
/**
- Destructory for the library. free any resources.
+ Destructor for the library. free any resources.
+
+ @param[in] ImageHandle A copy of the ImageHandle.
+ @param[in] SystemTable A pointer to the SystemTable for the application.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @return An error from the CloseProtocol function.
**/
EFI_STATUS
EFIAPI
ShellLibDestructor (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
- ) {
+ )
+{
if (mEfiShellEnvironment2 != NULL) {
gBS->CloseProtocol(mEfiShellEnvironment2Handle==NULL?ImageHandle:mEfiShellEnvironment2Handle,
&gEfiShellEnvironment2Guid,
@@ -333,7 +379,8 @@ ShellLibDestructor (
EFI_STATUS
EFIAPI
ShellInitialize (
- ) {
+ )
+{
//
// if auto initialize is not false then skip
//
@@ -369,35 +416,38 @@ ShellInitialize (
EFI_FILE_INFO*
EFIAPI
ShellGetFileInfo (
- IN EFI_FILE_HANDLE FileHandle
- ) {
+ IN SHELL_FILE_HANDLE FileHandle
+ )
+{
return (FileFunctionMap.GetFileInfo(FileHandle));
}
/**
- This function will set the information about the file for the opened handle
+ This function sets 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[in] FileHandle The file handle of the file for which information
+ is being set.
- @param FileInfo The infotmation to set.
+ @param[in] FileInfo The information 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_SUCCESS The information was set.
+ @retval EFI_INVALID_PARAMETER A parameter was out of range or invalid.
+ @retval EFI_UNSUPPORTED The FileHandle does not support FileInfo.
+ @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.
+ @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 SHELL_FILE_HANDLE FileHandle,
IN EFI_FILE_INFO *FileInfo
- ) {
+ )
+{
return (FileFunctionMap.SetFileInfo(FileHandle, FileInfo));
}
@@ -426,7 +476,7 @@ ShellSetFileInfo (
@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_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.
@@ -436,14 +486,16 @@ EFIAPI
ShellOpenFileByDevicePath(
IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,
OUT EFI_HANDLE *DeviceHandle,
- OUT EFI_FILE_HANDLE *FileHandle,
+ OUT SHELL_FILE_HANDLE *FileHandle,
IN UINT64 OpenMode,
IN UINT64 Attributes
- ) {
- CHAR16 *FileName;
- EFI_STATUS Status;
+ )
+{
+ CHAR16 *FileName;
+ EFI_STATUS Status;
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol;
- EFI_FILE_HANDLE LastHandle;
+ EFI_FILE_PROTOCOL *Handle1;
+ EFI_FILE_PROTOCOL *Handle2;
//
// ASERT for FileHandle, FilePath, and DeviceHandle being NULL
@@ -486,7 +538,7 @@ ShellOpenFileByDevicePath(
if (EFI_ERROR (Status)) {
return Status;
}
- Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, FileHandle);
+ Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, &Handle1);
if (EFI_ERROR (Status)) {
FileHandle = NULL;
return Status;
@@ -501,43 +553,43 @@ ShellOpenFileByDevicePath(
//
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;
+ Handle2 = Handle1;
+ Handle1 = NULL;
//
// Try to test opening an existing file
//
- Status = LastHandle->Open (
- LastHandle,
- FileHandle,
+ Status = Handle2->Open (
+ Handle2,
+ &Handle1,
((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,
+ Status = Handle2->Open (
+ Handle2,
+ &Handle1,
((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
OpenMode,
Attributes
- );
+ );
}
//
// Close the last node
//
- LastHandle->Close (LastHandle);
+ Handle2->Close (Handle2);
if (EFI_ERROR(Status)) {
return (Status);
@@ -548,6 +600,11 @@ ShellOpenFileByDevicePath(
//
*FilePath = NextDevicePathNode (*FilePath);
}
+
+ //
+ // This is a weak spot since if the undefined SHELL_FILE_HANDLE format changes this must change also!
+ //
+ *FileHandle = (VOID*)Handle1;
return (EFI_SUCCESS);
}
@@ -586,10 +643,11 @@ EFI_STATUS
EFIAPI
ShellOpenFileByName(
IN CONST CHAR16 *FileName,
- OUT EFI_FILE_HANDLE *FileHandle,
+ OUT SHELL_FILE_HANDLE *FileHandle,
IN UINT64 OpenMode,
IN UINT64 Attributes
- ) {
+ )
+{
EFI_HANDLE DeviceHandle;
EFI_DEVICE_PATH_PROTOCOL *FilePath;
EFI_STATUS Status;
@@ -600,14 +658,21 @@ ShellOpenFileByName(
//
ASSERT(FileName != NULL);
+ if (FileName == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
if (mEfiShellProtocol != NULL) {
+ if ((OpenMode & EFI_FILE_MODE_CREATE) == EFI_FILE_MODE_CREATE && (Attributes & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY) {
+ return ShellCreateDirectory(FileName, FileHandle);
+ }
//
// Use UEFI Shell 2.0 method
//
Status = mEfiShellProtocol->OpenFileByName(FileName,
FileHandle,
OpenMode);
- if (!EFI_ERROR(Status) && ((OpenMode & EFI_FILE_MODE_CREATE) != 0)){
+ if (StrCmp(FileName, L"NUL") != 0 && !EFI_ERROR(Status) && ((OpenMode & EFI_FILE_MODE_CREATE) != 0)){
FileInfo = FileFunctionMap.GetFileInfo(*FileHandle);
ASSERT(FileInfo != NULL);
FileInfo->Attribute = Attributes;
@@ -628,7 +693,7 @@ ShellOpenFileByName(
&DeviceHandle,
FileHandle,
OpenMode,
- Attributes ));
+ Attributes));
}
return (EFI_DEVICE_ERROR);
}
@@ -664,8 +729,9 @@ EFI_STATUS
EFIAPI
ShellCreateDirectory(
IN CONST CHAR16 *DirectoryName,
- OUT EFI_FILE_HANDLE *FileHandle
- ) {
+ OUT SHELL_FILE_HANDLE *FileHandle
+ )
+{
if (mEfiShellProtocol != NULL) {
//
// Use UEFI Shell 2.0 method
@@ -673,13 +739,13 @@ ShellCreateDirectory(
return (mEfiShellProtocol->CreateFile(DirectoryName,
EFI_FILE_DIRECTORY,
FileHandle
- ));
+ ));
} else {
return (ShellOpenFileByName(DirectoryName,
FileHandle,
EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
EFI_FILE_DIRECTORY
- ));
+ ));
}
}
@@ -715,10 +781,11 @@ ShellCreateDirectory(
EFI_STATUS
EFIAPI
ShellReadFile(
- IN EFI_FILE_HANDLE FileHandle,
+ IN SHELL_FILE_HANDLE FileHandle,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
- ) {
+ )
+{
return (FileFunctionMap.ReadFile(FileHandle, BufferSize, Buffer));
}
@@ -750,10 +817,11 @@ ShellReadFile(
EFI_STATUS
EFIAPI
ShellWriteFile(
- IN EFI_FILE_HANDLE FileHandle,
+ IN SHELL_FILE_HANDLE FileHandle,
IN OUT UINTN *BufferSize,
IN VOID *Buffer
- ) {
+ )
+{
return (FileFunctionMap.WriteFile(FileHandle, BufferSize, Buffer));
}
@@ -771,8 +839,9 @@ ShellWriteFile(
EFI_STATUS
EFIAPI
ShellCloseFile (
- IN EFI_FILE_HANDLE *FileHandle
- ) {
+ IN SHELL_FILE_HANDLE *FileHandle
+ )
+{
return (FileFunctionMap.CloseFile(*FileHandle));
}
@@ -793,8 +862,9 @@ ShellCloseFile (
EFI_STATUS
EFIAPI
ShellDeleteFile (
- IN EFI_FILE_HANDLE *FileHandle
- ) {
+ IN SHELL_FILE_HANDLE *FileHandle
+ )
+{
return (FileFunctionMap.DeleteFile(*FileHandle));
}
@@ -820,9 +890,10 @@ ShellDeleteFile (
EFI_STATUS
EFIAPI
ShellSetFilePosition (
- IN EFI_FILE_HANDLE FileHandle,
+ IN SHELL_FILE_HANDLE FileHandle,
IN UINT64 Position
- ) {
+ )
+{
return (FileFunctionMap.SetFilePosition(FileHandle, Position));
}
@@ -844,9 +915,10 @@ ShellSetFilePosition (
EFI_STATUS
EFIAPI
ShellGetFilePosition (
- IN EFI_FILE_HANDLE FileHandle,
+ IN SHELL_FILE_HANDLE FileHandle,
OUT UINT64 *Position
- ) {
+ )
+{
return (FileFunctionMap.GetFilePosition(FileHandle, Position));
}
/**
@@ -866,8 +938,9 @@ ShellGetFilePosition (
EFI_STATUS
EFIAPI
ShellFlushFile (
- IN EFI_FILE_HANDLE FileHandle
- ) {
+ IN SHELL_FILE_HANDLE FileHandle
+ )
+{
return (FileFunctionMap.FlushFile(FileHandle));
}
@@ -892,9 +965,10 @@ ShellFlushFile (
EFI_STATUS
EFIAPI
ShellFindFirstFile (
- IN EFI_FILE_HANDLE DirHandle,
+ IN SHELL_FILE_HANDLE DirHandle,
OUT EFI_FILE_INFO **Buffer
- ) {
+ )
+{
//
// pass to file handle lib
//
@@ -903,7 +977,7 @@ ShellFindFirstFile (
/**
Retrieves the next file in a directory.
- To use this function, caller must call the LibFindFirstFile() to get the
+ To use this function, caller must call the ShellFindFirstFile() 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
@@ -922,10 +996,11 @@ ShellFindFirstFile (
EFI_STATUS
EFIAPI
ShellFindNextFile(
- IN EFI_FILE_HANDLE DirHandle,
+ IN SHELL_FILE_HANDLE DirHandle,
OUT EFI_FILE_INFO *Buffer,
OUT BOOLEAN *NoFile
- ) {
+ )
+{
//
// pass to file handle lib
//
@@ -949,9 +1024,10 @@ ShellFindNextFile(
EFI_STATUS
EFIAPI
ShellGetFileSize (
- IN EFI_FILE_HANDLE FileHandle,
+ IN SHELL_FILE_HANDLE FileHandle,
OUT UINT64 *Size
- ) {
+ )
+{
return (FileFunctionMap.GetFileSize(FileHandle, Size));
}
/**
@@ -1062,34 +1138,38 @@ ShellSetEnvironmentVariable (
//
return (EFI_UNSUPPORTED);
}
+
/**
- cause the shell to parse and execute a command line.
+ 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.
+ 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.
+
+ The EnvironmentVariables and Status parameters are ignored in a pre-UEFI Shell 2.0
+ environment. The values pointed to by the parameters will be unchanged by the
+ ShellExecute() function. The Output parameter has no effect in a
+ UEFI Shell 2.0 environment.
+
+ @param[in] ParentHandle The parent image starting the operation.
+ @param[in] CommandLine The pointer to a NULL terminated command line.
+ @param[in] Output True to display debug output. False to hide it.
+ @param[in] EnvironmentVariables Optional pointer to array of environment variables
+ in the form "x=y". If NULL, the current set is used.
+ @param[out] 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 (
@@ -1139,7 +1219,7 @@ ShellExecute (
CONST CHAR16*
EFIAPI
ShellGetCurrentDir (
- IN CHAR16 *DeviceName OPTIONAL
+ IN CHAR16 * CONST DeviceName OPTIONAL
)
{
//
@@ -1225,7 +1305,7 @@ typedef struct {
EFI_STATUS Status;
CHAR16 *FullName;
CHAR16 *FileName;
- EFI_FILE_HANDLE Handle;
+ SHELL_FILE_HANDLE Handle;
EFI_FILE_INFO *Info;
} EFI_SHELL_FILE_INFO_NO_CONST;
@@ -1238,7 +1318,7 @@ typedef struct {
EFI_SHELL_FILE_INFO based list. it is up to the caller to free the memory via
the ShellCloseFileMetaArg function.
- @param[in] FileList the EFI shell list type
+ @param[in] FileList the EFI shell list type
@param[in,out] ListHead the list to add to
@retval the resultant head of the double linked new format list;
@@ -1265,11 +1345,18 @@ InternalShellConvertFileListType (
//
for (Link = FileList->ForwardLink; Link != FileList; Link = Link->ForwardLink) {
OldInfo = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE);
+ ASSERT(OldInfo != NULL);
+
+ //
+ // Skip ones that failed to open...
+ //
+ if (OldInfo->Status != EFI_SUCCESS) {
+ continue;
+ }
//
// make sure the old list was valid
//
- ASSERT(OldInfo != NULL);
ASSERT(OldInfo->Info != NULL);
ASSERT(OldInfo->FullName != NULL);
ASSERT(OldInfo->FileName != NULL);
@@ -1339,8 +1426,6 @@ InternalShellConvertFileListType (
@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
@@ -1381,6 +1466,11 @@ ShellOpenFileMetaArg (
} else {
Status = mEfiShellProtocol->RemoveDupInFileList(ListHead);
}
+ if (*ListHead != NULL && IsListEmpty(&(*ListHead)->Link)) {
+ FreePool(*ListHead);
+ *ListHead = NULL;
+ return (EFI_NOT_FOUND);
+ }
return (Status);
}
@@ -1408,6 +1498,7 @@ ShellOpenFileMetaArg (
if (*ListHead == NULL) {
return (EFI_OUT_OF_RESOURCES);
}
+ InitializeListHead(&((*ListHead)->Link));
}
//
@@ -1420,16 +1511,22 @@ ShellOpenFileMetaArg (
//
mEfiShellEnvironment2->FreeFileList(&mOldStyleFileList);
+ if ((*ListHead)->Link.ForwardLink == (*ListHead)->Link.BackLink && (*ListHead)->Link.BackLink == &((*ListHead)->Link)) {
+ FreePool(*ListHead);
+ *ListHead = NULL;
+ Status = EFI_NOT_FOUND;
+ }
+
return (Status);
}
/**
- Free the linked list returned from ShellOpenFileMetaArg
+ Free the linked list returned from ShellOpenFileMetaArg.
- if ListHead is NULL then ASSERT()
+ if ListHead is NULL then ASSERT().
- @param ListHead the pointer to free
+ @param ListHead the pointer to free.
- @retval EFI_SUCCESS the operation was sucessful
+ @retval EFI_SUCCESS the operation was sucessful.
**/
EFI_STATUS
EFIAPI
@@ -1455,10 +1552,10 @@ ShellCloseFileMetaArg (
// of the list
//
for ( Node = GetFirstNode(&(*ListHead)->Link)
- ; IsListEmpty(&(*ListHead)->Link) == FALSE
+ ; *ListHead != NULL && !IsListEmpty(&(*ListHead)->Link)
; Node = GetFirstNode(&(*ListHead)->Link)) {
RemoveEntryList(Node);
- ((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Handle->Close(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Handle);
+ ((EFI_FILE_PROTOCOL*)((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);
@@ -1487,7 +1584,7 @@ ShellFindFilePath (
)
{
CONST CHAR16 *Path;
- EFI_FILE_HANDLE Handle;
+ SHELL_FILE_HANDLE Handle;
EFI_STATUS Status;
CHAR16 *RetVal;
CHAR16 *TestPath;
@@ -1497,6 +1594,21 @@ ShellFindFilePath (
RetVal = NULL;
+ //
+ // First make sure its not an absolute path.
+ //
+ Status = ShellOpenFileByName(FileName, &Handle, EFI_FILE_MODE_READ, 0);
+ if (!EFI_ERROR(Status)){
+ if (FileHandleIsDirectory(Handle) != EFI_SUCCESS) {
+ ASSERT(RetVal == NULL);
+ RetVal = StrnCatGrow(&RetVal, NULL, FileName, 0);
+ ShellCloseFile(&Handle);
+ return (RetVal);
+ } else {
+ ShellCloseFile(&Handle);
+ }
+ }
+
Path = ShellGetEnvironmentVariable(L"cwd");
if (Path != NULL) {
Size = StrSize(Path);
@@ -1510,22 +1622,23 @@ ShellFindFilePath (
StrCat(TestPath, FileName);
Status = ShellOpenFileByName(TestPath, &Handle, EFI_FILE_MODE_READ, 0);
if (!EFI_ERROR(Status)){
- RetVal = StrnCatGrow(&RetVal, NULL, TestPath, 0);
- ShellCloseFile(&Handle);
- FreePool(TestPath);
- return (RetVal);
+ if (FileHandleIsDirectory(Handle) != EFI_SUCCESS) {
+ ASSERT(RetVal == NULL);
+ RetVal = StrnCatGrow(&RetVal, NULL, TestPath, 0);
+ ShellCloseFile(&Handle);
+ FreePool(TestPath);
+ return (RetVal);
+ } else {
+ ShellCloseFile(&Handle);
+ }
}
FreePool(TestPath);
}
Path = ShellGetEnvironmentVariable(L"path");
if (Path != NULL) {
- Size = StrSize(Path);
+ Size = StrSize(Path)+sizeof(CHAR16);
Size += StrSize(FileName);
TestPath = AllocateZeroPool(Size);
- ASSERT(TestPath != NULL);
- if (TestPath == NULL) {
- return (NULL);
- }
Walker = (CHAR16*)Path;
do {
CopyMem(TestPath, Walker, StrSize(Walker));
@@ -1533,6 +1646,9 @@ ShellFindFilePath (
if (TempChar != NULL) {
*TempChar = CHAR_NULL;
}
+ if (TestPath[StrLen(TestPath)-1] != L'\\') {
+ StrCat(TestPath, L"\\");
+ }
StrCat(TestPath, FileName);
if (StrStr(Walker, L";") != NULL) {
Walker = StrStr(Walker, L";") + 1;
@@ -1541,9 +1657,14 @@ ShellFindFilePath (
}
Status = ShellOpenFileByName(TestPath, &Handle, EFI_FILE_MODE_READ, 0);
if (!EFI_ERROR(Status)){
- RetVal = StrnCatGrow(&RetVal, NULL, TestPath, 0);
- ShellCloseFile(&Handle);
- break;
+ if (FileHandleIsDirectory(Handle) != EFI_SUCCESS) {
+ ASSERT(RetVal == NULL);
+ RetVal = StrnCatGrow(&RetVal, NULL, TestPath, 0);
+ ShellCloseFile(&Handle);
+ break;
+ } else {
+ ShellCloseFile(&Handle);
+ }
}
} while (Walker != NULL && Walker[0] != CHAR_NULL);
FreePool(TestPath);
@@ -1596,9 +1717,11 @@ ShellFindFilePathEx (
if (TestPath == NULL) {
return (NULL);
}
- for (ExtensionWalker = FileExtension, TempChar2 = (CHAR16*)FileExtension; TempChar2 != NULL ; ExtensionWalker = TempChar2 + 1 ){
+ for (ExtensionWalker = FileExtension, TempChar2 = (CHAR16*)FileExtension; TempChar2 != NULL ; ExtensionWalker = TempChar2 + 1){
StrCpy(TestPath, FileName);
- StrCat(TestPath, ExtensionWalker);
+ if (ExtensionWalker != NULL) {
+ StrCat(TestPath, ExtensionWalker);
+ }
TempChar = StrStr(TestPath, L";");
if (TempChar != NULL) {
*TempChar = CHAR_NULL;
@@ -1607,6 +1730,7 @@ ShellFindFilePathEx (
if (RetVal != NULL) {
break;
}
+ ASSERT(ExtensionWalker != NULL);
TempChar2 = StrStr(ExtensionWalker, L";");
}
FreePool(TestPath);
@@ -1616,7 +1740,7 @@ ShellFindFilePathEx (
typedef struct {
LIST_ENTRY Link;
CHAR16 *Name;
- ParamType Type;
+ SHELL_PARAM_TYPE Type;
CHAR16 *Value;
UINTN OriginalPosition;
} SHELL_PARAM_PACKAGE;
@@ -1629,9 +1753,9 @@ typedef struct {
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
+ @param Type pointer to type of parameter if it was found
@retval TRUE the Parameter was found. Type is valid.
@retval FALSE the Parameter was not found. Type is not valid.
@@ -1641,8 +1765,9 @@ EFIAPI
InternalIsOnCheckList (
IN CONST CHAR16 *Name,
IN CONST SHELL_PARAM_ITEM *CheckList,
- OUT ParamType *Type
- ) {
+ OUT SHELL_PARAM_TYPE *Type
+ )
+{
SHELL_PARAM_ITEM *TempListItem;
//
@@ -1657,7 +1782,7 @@ InternalIsOnCheckList (
//
if ((StrCmp(Name, L"-?") == 0) ||
(StrCmp(Name, L"-b") == 0)
- ) {
+ ) {
return (TRUE);
}
@@ -1683,10 +1808,11 @@ InternalIsOnCheckList (
/**
Checks the string for indicators of "flag" status. this is a leading '/', '-', or '+'
- @param Name pointer to Name of parameter found
+ @param[in] Name pointer to Name of parameter found
+ @param[in] AlwaysAllowNumbers TRUE to allow numbers, FALSE to not.
@retval TRUE the Parameter is a flag.
- @retval FALSE the Parameter not a flag
+ @retval FALSE the Parameter not a flag.
**/
BOOLEAN
EFIAPI
@@ -1703,17 +1829,17 @@ InternalIsFlag (
//
// If we accept numbers then dont return TRUE. (they will be values)
//
- if (((Name[0] == L'-' || Name[0] == L'+') && ShellIsHexaDecimalDigitCharacter(Name[1])) && AlwaysAllowNumbers != FALSE) {
+ if (((Name[0] == L'-' || Name[0] == L'+') && ShellIsHexaDecimalDigitCharacter(Name[1])) && AlwaysAllowNumbers) {
return (FALSE);
}
//
- // If the Name has a / or - as the first character return TRUE
+ // 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);
@@ -1724,14 +1850,15 @@ InternalIsFlag (
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
+ @param[in] CheckList pointer to list of parameters to check
+ @param[out] CheckPackage pointer to pointer to list checked values
+ @param[out] 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
+ @param[in] AutoPageBreak will automatically set PageBreakEnabled for "b" parameter
+ @param[in] Argv pointer to array of parameters
+ @param[in] Argc Count of parameters in Argv
+ @param[in] AlwaysAllowNumbers TRUE to allow numbers always, FALSE otherwise.
@retval EFI_SUCCESS The operation completed sucessfully.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed
@@ -1743,7 +1870,6 @@ InternalIsFlag (
the invalid command line argument was returned in
ProblemParam if provided.
**/
-STATIC
EFI_STATUS
EFIAPI
InternalCommandLineParse (
@@ -1754,22 +1880,24 @@ InternalCommandLineParse (
IN CONST CHAR16 **Argv,
IN UINTN Argc,
IN BOOLEAN AlwaysAllowNumbers
- ) {
+ )
+{
UINTN LoopCounter;
- ParamType CurrentItemType;
+ SHELL_PARAM_TYPE CurrentItemType;
SHELL_PARAM_PACKAGE *CurrentItemPackage;
UINTN GetItemValue;
UINTN ValueSize;
+ UINTN Count;
CurrentItemPackage = NULL;
- mTotalParameterCount = 0;
GetItemValue = 0;
ValueSize = 0;
+ Count = 0;
//
// If there is only 1 item we dont need to do anything
//
- if (Argc <= 1) {
+ if (Argc < 1) {
*CheckPackage = NULL;
return (EFI_SUCCESS);
}
@@ -1794,7 +1922,7 @@ InternalCommandLineParse (
//
// do nothing for NULL argv
//
- } else if (InternalIsOnCheckList(Argv[LoopCounter], CheckList, &CurrentItemType) != FALSE) {
+ } else if (InternalIsOnCheckList(Argv[LoopCounter], CheckList, &CurrentItemType)) {
//
// We might have leftover if last parameter didnt have optional value
//
@@ -1841,7 +1969,7 @@ InternalCommandLineParse (
ASSERT(GetItemValue == 0);
break;
}
- } else if (GetItemValue != 0 && InternalIsFlag(Argv[LoopCounter], AlwaysAllowNumbers) == FALSE) {
+ } else if (GetItemValue != 0 && !InternalIsFlag(Argv[LoopCounter], AlwaysAllowNumbers)) {
ASSERT(CurrentItemPackage != NULL);
//
// get the item VALUE for a previous flag
@@ -1859,7 +1987,7 @@ InternalCommandLineParse (
if (GetItemValue == 0) {
InsertHeadList(*CheckPackage, &CurrentItemPackage->Link);
}
- } else if (InternalIsFlag(Argv[LoopCounter], AlwaysAllowNumbers) == FALSE) {
+ } else if (!InternalIsFlag(Argv[LoopCounter], AlwaysAllowNumbers) ){ //|| ProblemParam == NULL) {
//
// add this one as a non-flag
//
@@ -1870,9 +1998,9 @@ InternalCommandLineParse (
CurrentItemPackage->Value = AllocatePool(StrSize(Argv[LoopCounter]));
ASSERT(CurrentItemPackage->Value != NULL);
StrCpy(CurrentItemPackage->Value, Argv[LoopCounter]);
- CurrentItemPackage->OriginalPosition = mTotalParameterCount++;
+ CurrentItemPackage->OriginalPosition = Count++;
InsertHeadList(*CheckPackage, &CurrentItemPackage->Link);
- } else if (ProblemParam) {
+ } else if (ProblemParam != NULL) {
//
// this was a non-recognised flag... error!
//
@@ -1883,9 +2011,7 @@ InternalCommandLineParse (
*CheckPackage = NULL;
return (EFI_VOLUME_CORRUPTED);
} else {
- ShellCommandLineFreeVarList(*CheckPackage);
- *CheckPackage = NULL;
- return (EFI_VOLUME_CORRUPTED);
+ //ASSERT(FALSE);
}
}
if (GetItemValue != 0) {
@@ -1907,23 +2033,22 @@ InternalCommandLineParse (
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
+ @param[in] CheckList The pointer to list of parameters to check.
+ @param[out] CheckPackage The package of checked values.
+ @param[out] ProblemParam Optional pointer to pointer to unicode string for
the paramater that caused failure.
- @param AutoPageBreak will automatically set PageBreakEnabled for "b" parameter
+ @param[in] AutoPageBreak Will automatically set PageBreakEnabled.
+ @param[in] AlwaysAllowNumbers Will never fail for number based flags.
@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
+ @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.
+ @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
+ @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
@@ -1934,7 +2059,8 @@ ShellCommandLineParseEx (
OUT CHAR16 **ProblemParam OPTIONAL,
IN BOOLEAN AutoPageBreak,
IN BOOLEAN AlwaysAllowNumbers
- ) {
+ )
+{
//
// ASSERT that CheckList and CheckPackage aren't NULL
//
@@ -1983,7 +2109,8 @@ VOID
EFIAPI
ShellCommandLineFreeVarList (
IN LIST_ENTRY *CheckPackage
- ) {
+ )
+{
LIST_ENTRY *Node;
//
@@ -1997,9 +2124,9 @@ ShellCommandLineFreeVarList (
// for each node in the list
//
for ( Node = GetFirstNode(CheckPackage)
- ; IsListEmpty(CheckPackage) == FALSE
+ ; !IsListEmpty(CheckPackage)
; Node = GetFirstNode(CheckPackage)
- ){
+ ){
//
// Remove it from the list
//
@@ -2046,9 +2173,10 @@ ShellCommandLineFreeVarList (
BOOLEAN
EFIAPI
ShellCommandLineGetFlag (
- IN CONST LIST_ENTRY *CheckPackage,
- IN CHAR16 *KeyString
- ) {
+ IN CONST LIST_ENTRY * CONST CheckPackage,
+ IN CONST CHAR16 * CONST KeyString
+ )
+{
LIST_ENTRY *Node;
//
@@ -2069,7 +2197,7 @@ ShellCommandLineGetFlag (
for ( Node = GetFirstNode(CheckPackage)
; !IsNull (CheckPackage, Node)
; Node = GetNextNode(CheckPackage, Node)
- ){
+ ){
//
// If the Name matches, return TRUE (and there may be NULL name)
//
@@ -2079,7 +2207,7 @@ ShellCommandLineGetFlag (
//
if ( ((SHELL_PARAM_PACKAGE*)Node)->Type == TypeStart
&& StrnCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name, StrLen(KeyString)) == 0
- ){
+ ){
return (TRUE);
} else if (StrCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {
return (TRUE);
@@ -2089,24 +2217,25 @@ ShellCommandLineGetFlag (
return (FALSE);
}
/**
- returns value from command line argument
+ Returns value from command line argument.
- value parameters are in the form of "-<Key> value" or "/<Key> value"
+ Value parameters are in the form of "-<Key> value" or "/<Key> value".
- if CheckPackage is NULL, then return NULL;
+ 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
+ @param[in] CheckPackage The package of parsed command line arguments.
+ @param[in] 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
- **/
+ @retval NULL The flag is not on the command line.
+ @retval !=NULL The pointer to unicode string of the value.
+**/
CONST CHAR16*
EFIAPI
ShellCommandLineGetValue (
IN CONST LIST_ENTRY *CheckPackage,
IN CHAR16 *KeyString
- ) {
+ )
+{
LIST_ENTRY *Node;
//
@@ -2122,7 +2251,7 @@ ShellCommandLineGetValue (
for ( Node = GetFirstNode(CheckPackage)
; !IsNull (CheckPackage, Node)
; Node = GetNextNode(CheckPackage, Node)
- ){
+ ){
//
// If the Name matches, return the value (name can be NULL)
//
@@ -2132,7 +2261,7 @@ ShellCommandLineGetValue (
//
if ( ((SHELL_PARAM_PACKAGE*)Node)->Type == TypeStart
&& StrnCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name, StrLen(KeyString)) == 0
- ){
+ ){
//
// return the string part after the flag
//
@@ -2147,25 +2276,27 @@ ShellCommandLineGetValue (
}
return (NULL);
}
+
/**
- returns raw value from command line argument
+ Returns raw value from command line argument.
- raw value parameters are in the form of "value" in a specific position in the list
+ Raw value parameters are in the form of "value" in a specific position in the list.
- if CheckPackage is NULL, then return NULL;
+ If CheckPackage is NULL, then return NULL.
- @param CheckPackage The package of parsed command line arguments
- @param Position the position of the value
+ @param[in] CheckPackage The package of parsed command line arguments.
+ @param[in] 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
+ @retval NULL The flag is not on the command line.
+ @retval !=NULL The pointer to unicode string of the value.
**/
CONST CHAR16*
EFIAPI
ShellCommandLineGetRawValue (
- IN CONST LIST_ENTRY *CheckPackage,
- IN UINT32 Position
- ) {
+ IN CONST LIST_ENTRY * CONST CheckPackage,
+ IN UINTN Position
+ )
+{
LIST_ENTRY *Node;
//
@@ -2181,7 +2312,7 @@ ShellCommandLineGetRawValue (
for ( Node = GetFirstNode(CheckPackage)
; !IsNull (CheckPackage, Node)
; Node = GetNextNode(CheckPackage, Node)
- ){
+ ){
//
// If the position matches, return the value
//
@@ -2197,16 +2328,32 @@ ShellCommandLineGetRawValue (
this will not include flags.
+ @param[in] CheckPackage The package of parsed command line arguments.
+
@retval (UINTN)-1 No parsing has ocurred
@return other The number of value parameters found
**/
UINTN
EFIAPI
ShellCommandLineGetCount(
- VOID
+ IN CONST LIST_ENTRY *CheckPackage
)
{
- return (mTotalParameterCount);
+ LIST_ENTRY *Node1;
+ UINTN Count;
+
+ if (CheckPackage == NULL) {
+ return (0);
+ }
+ for ( Node1 = GetFirstNode(CheckPackage), Count = 0
+ ; !IsNull (CheckPackage, Node1)
+ ; Node1 = GetNextNode(CheckPackage, Node1)
+ ){
+ if (((SHELL_PARAM_PACKAGE*)Node1)->Name == NULL) {
+ Count++;
+ }
+ }
+ return (Count);
}
/**
@@ -2238,12 +2385,12 @@ ShellCommandLineCheckDuplicate (
for ( Node1 = GetFirstNode(CheckPackage)
; !IsNull (CheckPackage, Node1)
; Node1 = GetNextNode(CheckPackage, Node1)
- ){
+ ){
for ( Node2 = GetNextNode(CheckPackage, Node1)
; !IsNull (CheckPackage, Node2)
; Node2 = GetNextNode(CheckPackage, Node2)
- ){
- if (StrCmp(((SHELL_PARAM_PACKAGE*)Node1)->Name, ((SHELL_PARAM_PACKAGE*)Node2)->Name) == 0) {
+ ){
+ if ((((SHELL_PARAM_PACKAGE*)Node1)->Name != NULL) && (((SHELL_PARAM_PACKAGE*)Node2)->Name != NULL) && StrCmp(((SHELL_PARAM_PACKAGE*)Node1)->Name, ((SHELL_PARAM_PACKAGE*)Node2)->Name) == 0) {
if (Param != NULL) {
*Param = NULL;
*Param = StrnCatGrow(Param, NULL, ((SHELL_PARAM_PACKAGE*)Node1)->Name, 0);
@@ -2263,13 +2410,14 @@ ShellCommandLineCheckDuplicate (
If the string would grow bigger than NewSize it will halt and return error.
- @param[in] SourceString String with source buffer
- @param[in,out] NewString String with resultant buffer
- @param[in] NewSize Size in bytes of NewString
- @param[in] FindTarget String to look for
- @param[in[ ReplaceWith String to replace FindTarget with
+ @param[in] SourceString The string with source buffer.
+ @param[in,out] NewString The string with resultant buffer.
+ @param[in] NewSize The size in bytes of NewString.
+ @param[in] FindTarget The string to look for.
+ @param[in] ReplaceWith The string to replace FindTarget with.
@param[in] SkipPreCarrot If TRUE will skip a FindTarget that has a '^'
immediately before it.
+ @param[in] ParameterReplacing If TRUE will add "" around items with spaces.
@retval EFI_INVALID_PARAMETER SourceString was NULL.
@retval EFI_INVALID_PARAMETER NewString was NULL.
@@ -2279,54 +2427,66 @@ ShellCommandLineCheckDuplicate (
@retval EFI_INVALID_PARAMETER SourceString had length < 1.
@retval EFI_BUFFER_TOO_SMALL NewSize was less than the minimum size to hold
the new string (truncation occurred).
- @retval EFI_SUCCESS the string was sucessfully copied with replacement.
+ @retval EFI_SUCCESS The string was successfully copied with replacement.
**/
-
EFI_STATUS
EFIAPI
-ShellCopySearchAndReplace2(
+ShellCopySearchAndReplace(
IN CHAR16 CONST *SourceString,
- IN CHAR16 *NewString,
+ IN OUT CHAR16 *NewString,
IN UINTN NewSize,
IN CONST CHAR16 *FindTarget,
IN CONST CHAR16 *ReplaceWith,
- IN CONST BOOLEAN SkipPreCarrot
+ IN CONST BOOLEAN SkipPreCarrot,
+ IN CONST BOOLEAN ParameterReplacing
)
{
UINTN Size;
+ CHAR16 *Replace;
+
if ( (SourceString == NULL)
|| (NewString == NULL)
|| (FindTarget == NULL)
|| (ReplaceWith == NULL)
|| (StrLen(FindTarget) < 1)
|| (StrLen(SourceString) < 1)
- ){
+ ){
return (EFI_INVALID_PARAMETER);
}
+ Replace = NULL;
+ if (StrStr(ReplaceWith, L" ") == NULL || !ParameterReplacing) {
+ Replace = StrnCatGrow(&Replace, NULL, ReplaceWith, 0);
+ } else {
+ Replace = AllocateZeroPool(StrSize(ReplaceWith) + 2*sizeof(CHAR16));
+ UnicodeSPrint(Replace, StrSize(ReplaceWith) + 2*sizeof(CHAR16), L"\"%s\"", ReplaceWith);
+ }
NewString = SetMem16(NewString, NewSize, CHAR_NULL);
while (*SourceString != CHAR_NULL) {
//
- // if we find the FindTarget and either Skip == FALSE or Skip == TRUE and we
+ // if we find the FindTarget and either Skip == FALSE or Skip and we
// dont have a carrot do a replace...
//
if (StrnCmp(SourceString, FindTarget, StrLen(FindTarget)) == 0
- && ((SkipPreCarrot && *(SourceString-1) != L'^') || SkipPreCarrot == FALSE)
- ){
+ && ((SkipPreCarrot && *(SourceString-1) != L'^') || !SkipPreCarrot)
+ ){
SourceString += StrLen(FindTarget);
Size = StrSize(NewString);
- if ((Size + (StrLen(ReplaceWith)*sizeof(CHAR16))) > NewSize) {
+ if ((Size + (StrLen(Replace)*sizeof(CHAR16))) > NewSize) {
+ FreePool(Replace);
return (EFI_BUFFER_TOO_SMALL);
}
- StrCat(NewString, ReplaceWith);
+ StrCat(NewString, Replace);
} else {
Size = StrSize(NewString);
if (Size + sizeof(CHAR16) > NewSize) {
+ FreePool(Replace);
return (EFI_BUFFER_TOO_SMALL);
}
StrnCat(NewString, SourceString, 1);
SourceString++;
}
}
+ FreePool(Replace);
return (EFI_SUCCESS);
}
@@ -2348,15 +2508,18 @@ InternalPrintTo (
{
UINTN Size;
Size = StrSize(String) - sizeof(CHAR16);
+ if (Size == 0) {
+ return (EFI_SUCCESS);
+ }
if (mEfiShellParametersProtocol != NULL) {
- return (mEfiShellParametersProtocol->StdOut->Write(mEfiShellParametersProtocol->StdOut, &Size, (VOID*)String));
+ return (mEfiShellProtocol->WriteFile(mEfiShellParametersProtocol->StdOut, &Size, (VOID*)String));
}
if (mEfiShellInterface != NULL) {
//
// Divide in half for old shell. Must be string length not size.
//
Size /= 2;
- return ( mEfiShellInterface->StdOut->Write(mEfiShellInterface->StdOut, &Size, (VOID*)String));
+ return (mEfiShellInterface->StdOut->Write(mEfiShellInterface->StdOut, &Size, (VOID*)String));
}
ASSERT(FALSE);
return (EFI_UNSUPPORTED);
@@ -2388,10 +2551,10 @@ InternalPrintTo (
@param[in] Format the format string
@param[in] Marker the marker for the variable argument list
- @return the number of characters printed to the screen
+ @return EFI_SUCCESS The operation was successful.
+ @return EFI_DEVICE_ERROR The console device reported an error.
**/
-
-UINTN
+EFI_STATUS
EFIAPI
InternalShellPrintWorker(
IN INT32 Col OPTIONAL,
@@ -2400,37 +2563,38 @@ InternalShellPrintWorker(
VA_LIST Marker
)
{
- UINTN Return;
EFI_STATUS Status;
- UINTN NormalAttribute;
CHAR16 *ResumeLocation;
CHAR16 *FormatWalker;
+ UINTN OriginalAttribute;
+
+ Status = EFI_SUCCESS;
+ OriginalAttribute = gST->ConOut->Mode->Attribute;
//
// Back and forth each time fixing up 1 of our flags...
//
- Status = ShellLibCopySearchAndReplace(Format, mPostReplaceFormat, PcdGet16 (PcdShellPrintBufferSize), L"%N", L"%%N");
+ Status = ShellCopySearchAndReplace(Format, mPostReplaceFormat, PcdGet16 (PcdShellPrintBufferSize), L"%N", L"%%N", FALSE, FALSE);
ASSERT_EFI_ERROR(Status);
- Status = ShellLibCopySearchAndReplace(mPostReplaceFormat, mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), L"%E", L"%%E");
+ Status = ShellCopySearchAndReplace(mPostReplaceFormat, mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), L"%E", L"%%E", FALSE, FALSE);
ASSERT_EFI_ERROR(Status);
- Status = ShellLibCopySearchAndReplace(mPostReplaceFormat2, mPostReplaceFormat, PcdGet16 (PcdShellPrintBufferSize), L"%H", L"%%H");
+ Status = ShellCopySearchAndReplace(mPostReplaceFormat2, mPostReplaceFormat, PcdGet16 (PcdShellPrintBufferSize), L"%H", L"%%H", FALSE, FALSE);
ASSERT_EFI_ERROR(Status);
- Status = ShellLibCopySearchAndReplace(mPostReplaceFormat, mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), L"%B", L"%%B");
+ Status = ShellCopySearchAndReplace(mPostReplaceFormat, mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), L"%B", L"%%B", FALSE, FALSE);
ASSERT_EFI_ERROR(Status);
- Status = ShellLibCopySearchAndReplace(mPostReplaceFormat2, mPostReplaceFormat, PcdGet16 (PcdShellPrintBufferSize), L"%V", L"%%V");
+ Status = ShellCopySearchAndReplace(mPostReplaceFormat2, mPostReplaceFormat, PcdGet16 (PcdShellPrintBufferSize), L"%V", L"%%V", FALSE, FALSE);
ASSERT_EFI_ERROR(Status);
//
// Use the last buffer from replacing to print from...
//
- Return = UnicodeVSPrint (mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), mPostReplaceFormat, Marker);
+ UnicodeVSPrint (mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), mPostReplaceFormat, Marker);
if (Col != -1 && Row != -1) {
Status = gST->ConOut->SetCursorPosition(gST->ConOut, Col, Row);
ASSERT_EFI_ERROR(Status);
}
- NormalAttribute = gST->ConOut->Mode->Attribute;
FormatWalker = mPostReplaceFormat2;
while (*FormatWalker != CHAR_NULL) {
//
@@ -2443,34 +2607,41 @@ InternalShellPrintWorker(
//
// print the current FormatWalker string
//
- Status = InternalPrintTo(FormatWalker);
- ASSERT_EFI_ERROR(Status);
+ if (StrLen(FormatWalker)>0) {
+ Status = InternalPrintTo(FormatWalker);
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+ }
+
//
// update the attribute
//
if (ResumeLocation != NULL) {
switch (*(ResumeLocation+1)) {
case (L'N'):
- gST->ConOut->SetAttribute(gST->ConOut, NormalAttribute);
+ gST->ConOut->SetAttribute(gST->ConOut, OriginalAttribute);
break;
case (L'E'):
- gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_YELLOW, ((NormalAttribute&(BIT4|BIT5|BIT6))>>4)));
+ gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_YELLOW, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)));
break;
case (L'H'):
- gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_WHITE, ((NormalAttribute&(BIT4|BIT5|BIT6))>>4)));
+ gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_WHITE, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)));
break;
case (L'B'):
- gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_BLUE, ((NormalAttribute&(BIT4|BIT5|BIT6))>>4)));
+ gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_BLUE, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)));
break;
case (L'V'):
- gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_GREEN, ((NormalAttribute&(BIT4|BIT5|BIT6))>>4)));
+ gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_GREEN, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)));
break;
default:
//
// Print a simple '%' symbol
//
Status = InternalPrintTo(L"%");
- ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) {
+ break;
+ }
ResumeLocation = ResumeLocation - 1;
break;
}
@@ -2478,7 +2649,6 @@ InternalShellPrintWorker(
//
// reset to normal now...
//
- gST->ConOut->SetAttribute(gST->ConOut, NormalAttribute);
break;
}
@@ -2488,7 +2658,8 @@ InternalShellPrintWorker(
FormatWalker = ResumeLocation + 2;
}
- return (Return);
+ gST->ConOut->SetAttribute(gST->ConOut, OriginalAttribute);
+ return (Status);
}
/**
@@ -2512,14 +2683,15 @@ InternalShellPrintWorker(
Note: The background color is controlled by the shell command cls.
- @param[in] Row the row to print at
@param[in] Col the column to print at
+ @param[in] Row the row to print at
@param[in] Format the format string
+ @param[in] ... The variable argument list.
- @return the number of characters printed to the screen
+ @return EFI_SUCCESS The printing was successful.
+ @return EFI_DEVICE_ERROR The console device reported an error.
**/
-
-UINTN
+EFI_STATUS
EFIAPI
ShellPrintEx(
IN INT32 Col OPTIONAL,
@@ -2529,11 +2701,11 @@ ShellPrintEx(
)
{
VA_LIST Marker;
- EFI_STATUS Status;
+ EFI_STATUS RetVal;
VA_START (Marker, Format);
- Status = InternalShellPrintWorker(Col, Row, Format, Marker);
+ RetVal = InternalShellPrintWorker(Col, Row, Format, Marker);
VA_END(Marker);
- return(Status);
+ return(RetVal);
}
/**
@@ -2557,16 +2729,18 @@ ShellPrintEx(
Note: The background color is controlled by the shell command cls.
- @param[in] Row The row to print at.
@param[in] Col The column to print at.
+ @param[in] Row The row to print at.
@param[in] Language The language of the string to retrieve. If this parameter
is NULL, then the current platform language is used.
@param[in] HiiFormatStringId The format string Id for getting from Hii.
@param[in] HiiFormatHandle The format string Handle for getting from Hii.
+ @param[in] ... The variable argument list.
- @return the number of characters printed to the screen.
+ @return EFI_SUCCESS The printing was successful.
+ @return EFI_DEVICE_ERROR The console device reported an error.
**/
-UINTN
+EFI_STATUS
EFIAPI
ShellPrintHiiEx(
IN INT32 Col OPTIONAL,
@@ -2579,7 +2753,7 @@ ShellPrintHiiEx(
{
VA_LIST Marker;
CHAR16 *HiiFormatString;
- UINTN RetVal;
+ EFI_STATUS RetVal;
VA_START (Marker, HiiFormatHandle);
HiiFormatString = HiiGetString(HiiFormatHandle, HiiFormatStringId, Language);
@@ -2587,7 +2761,7 @@ ShellPrintHiiEx(
RetVal = InternalShellPrintWorker(Col, Row, HiiFormatString, Marker);
- FreePool(HiiFormatString);
+ SHELL_FREE_NON_NULL(HiiFormatString);
VA_END(Marker);
return (RetVal);
@@ -2609,14 +2783,38 @@ ShellIsDirectory(
)
{
EFI_STATUS Status;
- EFI_FILE_HANDLE Handle;
+ SHELL_FILE_HANDLE Handle;
+ CHAR16 *TempLocation;
ASSERT(DirName != NULL);
- Handle = NULL;
+ Handle = NULL;
+ TempLocation = NULL;
Status = ShellOpenFileByName(DirName, &Handle, EFI_FILE_MODE_READ, 0);
if (EFI_ERROR(Status)) {
+ //
+ // try good logic first.
+ //
+ if (mEfiShellProtocol != NULL) {
+ TempLocation = StrnCatGrow(&TempLocation, NULL, DirName, 0);
+ if (StrStr(TempLocation, L":") != NULL && StrLen(StrStr(TempLocation, L":")) == 2) {
+ *(StrStr(TempLocation, L":")+1) = CHAR_NULL;
+ }
+ if (mEfiShellProtocol->GetDevicePathFromMap(TempLocation) != NULL) {
+ FreePool(TempLocation);
+ return (EFI_SUCCESS);
+ }
+ FreePool(TempLocation);
+ } else {
+ //
+ // probably a map name?!?!!?
+ //
+ TempLocation = StrStr(DirName, L"\\");
+ if (TempLocation != NULL && *(TempLocation+1) == CHAR_NULL) {
+ return (EFI_SUCCESS);
+ }
+ }
return (Status);
}
@@ -2644,7 +2842,7 @@ ShellIsFile(
)
{
EFI_STATUS Status;
- EFI_FILE_HANDLE Handle;
+ SHELL_FILE_HANDLE Handle;
ASSERT(Name != NULL);
@@ -2680,12 +2878,13 @@ EFI_STATUS
EFIAPI
ShellIsFileInPath(
IN CONST CHAR16 *Name
- ) {
+ )
+{
CHAR16 *NewName;
EFI_STATUS Status;
if (!EFI_ERROR(ShellIsFile(Name))) {
- return (TRUE);
+ return (EFI_SUCCESS);
}
NewName = ShellFindFilePath(Name);
@@ -2836,10 +3035,10 @@ StrnCatGrow (
This function will display the requested question on the shell prompt and then
wait for an apropriate answer to be input from the console.
- if the SHELL_PROMPT_REQUEST_TYPE is SHELL_PROMPT_REQUEST_TYPE_YESNO, SHELL_PROMPT_REQUEST_TYPE_QUIT_CONTINUE
+ if the SHELL_PROMPT_REQUEST_TYPE is SHELL_PROMPT_REQUEST_TYPE_YESNO, ShellPromptResponseTypeQuitContinue
or SHELL_PROMPT_REQUEST_TYPE_YESNOCANCEL then *Response is of type SHELL_PROMPT_RESPONSE.
- if the SHELL_PROMPT_REQUEST_TYPE is SHELL_PROMPT_REQUEST_TYPE_FREEFORM then *Response is of type
+ if the SHELL_PROMPT_REQUEST_TYPE is ShellPromptResponseTypeFreeform then *Response is of type
CHAR16*.
In either case *Response must be callee freed if Response was not NULL;
@@ -2852,7 +3051,6 @@ StrnCatGrow (
@retval EFI_SUCCESS The operation was sucessful.
@retval EFI_UNSUPPORTED The operation is not supported as requested.
@retval EFI_INVALID_PARAMETER A parameter was invalid.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
@return other The operation failed.
**/
EFI_STATUS
@@ -2867,15 +3065,19 @@ ShellPromptForResponse (
EFI_INPUT_KEY Key;
UINTN EventIndex;
SHELL_PROMPT_RESPONSE *Resp;
+ UINTN Size;
+ CHAR16 *Buffer;
- Status = EFI_SUCCESS;
- Resp = (SHELL_PROMPT_RESPONSE*)AllocatePool(sizeof(SHELL_PROMPT_RESPONSE));
- if (Resp == NULL) {
- return EFI_OUT_OF_RESOURCES;
+ Status = EFI_UNSUPPORTED;
+ Resp = NULL;
+ Buffer = NULL;
+ Size = 0;
+ if (Type != ShellPromptResponseTypeFreeform) {
+ Resp = (SHELL_PROMPT_RESPONSE*)AllocatePool(sizeof(SHELL_PROMPT_RESPONSE));
}
switch(Type) {
- case SHELL_PROMPT_REQUEST_TYPE_QUIT_CONTINUE:
+ case ShellPromptResponseTypeQuitContinue:
if (Prompt != NULL) {
ShellPrintEx(-1, -1, L"%s", Prompt);
}
@@ -2887,20 +3089,20 @@ ShellPromptForResponse (
ASSERT_EFI_ERROR(Status);
ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);
if (Key.UnicodeChar == L'Q' || Key.UnicodeChar ==L'q') {
- *Resp = SHELL_PROMPT_RESPONSE_QUIT;
+ *Resp = ShellPromptResponseQuit;
} else {
- *Resp = SHELL_PROMPT_RESPONSE_CONTINUE;
+ *Resp = ShellPromptResponseContinue;
}
break;
- case SHELL_PROMPT_REQUEST_TYPE_YES_NO_ALL_CANCEL:
+ case ShellPromptResponseTypeYesNoCancel:
if (Prompt != NULL) {
ShellPrintEx(-1, -1, L"%s", Prompt);
}
//
// wait for valid response
//
- *Resp = SHELL_PROMPT_RESPONSE_MAX;
- while (*Resp == SHELL_PROMPT_RESPONSE_MAX) {
+ *Resp = ShellPromptResponseMax;
+ while (*Resp == ShellPromptResponseMax) {
gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);
Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
ASSERT_EFI_ERROR(Status);
@@ -2908,60 +3110,143 @@ ShellPromptForResponse (
switch (Key.UnicodeChar) {
case L'Y':
case L'y':
- *Resp = SHELL_PROMPT_RESPONSE_YES;
+ *Resp = ShellPromptResponseYes;
break;
case L'N':
case L'n':
- *Resp = SHELL_PROMPT_RESPONSE_NO;
+ *Resp = ShellPromptResponseNo;
+ break;
+ case L'C':
+ case L'c':
+ *Resp = ShellPromptResponseCancel;
+ break;
+ }
+ }
+ break; case ShellPromptResponseTypeYesNoAllCancel:
+ if (Prompt != NULL) {
+ ShellPrintEx(-1, -1, L"%s", Prompt);
+ }
+ //
+ // wait for valid response
+ //
+ *Resp = ShellPromptResponseMax;
+ while (*Resp == ShellPromptResponseMax) {
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ ASSERT_EFI_ERROR(Status);
+ ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);
+ switch (Key.UnicodeChar) {
+ case L'Y':
+ case L'y':
+ *Resp = ShellPromptResponseYes;
+ break;
+ case L'N':
+ case L'n':
+ *Resp = ShellPromptResponseNo;
break;
case L'A':
case L'a':
- *Resp = SHELL_PROMPT_RESPONSE_ALL;
+ *Resp = ShellPromptResponseAll;
break;
case L'C':
case L'c':
- *Resp = SHELL_PROMPT_RESPONSE_CANCEL;
+ *Resp = ShellPromptResponseCancel;
break;
}
}
break;
- case SHELL_PROMPT_REQUEST_TYPE_ENTER_TO_COMTINUE:
- case SHELL_PROMPT_REQUEST_TYPE_ANYKEY_TO_COMTINUE:
+ case ShellPromptResponseTypeEnterContinue:
+ case ShellPromptResponseTypeAnyKeyContinue:
if (Prompt != NULL) {
ShellPrintEx(-1, -1, L"%s", Prompt);
}
//
// wait for valid response
//
- *Resp = SHELL_PROMPT_RESPONSE_MAX;
- while (*Resp == SHELL_PROMPT_RESPONSE_MAX) {
+ *Resp = ShellPromptResponseMax;
+ while (*Resp == ShellPromptResponseMax) {
gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);
- if (Type == SHELL_PROMPT_REQUEST_TYPE_ENTER_TO_COMTINUE) {
+ if (Type == ShellPromptResponseTypeEnterContinue) {
Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
ASSERT_EFI_ERROR(Status);
ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);
if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
- *Resp = SHELL_PROMPT_RESPONSE_CONTINUE;
+ *Resp = ShellPromptResponseContinue;
break;
}
}
- if (Type == SHELL_PROMPT_REQUEST_TYPE_ANYKEY_TO_COMTINUE) {
- *Resp = SHELL_PROMPT_RESPONSE_CONTINUE;
+ if (Type == ShellPromptResponseTypeAnyKeyContinue) {
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ ASSERT_EFI_ERROR(Status);
+ *Resp = ShellPromptResponseContinue;
+ break;
+ }
+ }
+ break;
+ case ShellPromptResponseTypeYesNo:
+ if (Prompt != NULL) {
+ ShellPrintEx(-1, -1, L"%s", Prompt);
+ }
+ //
+ // wait for valid response
+ //
+ *Resp = ShellPromptResponseMax;
+ while (*Resp == ShellPromptResponseMax) {
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ ASSERT_EFI_ERROR(Status);
+ ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);
+ switch (Key.UnicodeChar) {
+ case L'Y':
+ case L'y':
+ *Resp = ShellPromptResponseYes;
+ break;
+ case L'N':
+ case L'n':
+ *Resp = ShellPromptResponseNo;
+ break;
+ }
+ }
+ break;
+ case ShellPromptResponseTypeFreeform:
+ if (Prompt != NULL) {
+ ShellPrintEx(-1, -1, L"%s", Prompt);
+ }
+ while(1) {
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ ASSERT_EFI_ERROR(Status);
+ ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
break;
}
+ ASSERT((Buffer == NULL && Size == 0) || (Buffer != NULL));
+ StrnCatGrow(&Buffer, &Size, &Key.UnicodeChar, 1);
}
break;
- ///@todo add more request types here!
+ //
+ // This is the location to add new prompt types.
+ //
default:
- Status = EFI_UNSUPPORTED;
+ ASSERT(FALSE);
}
if (Response != NULL) {
- *Response = Resp;
+ if (Resp != NULL) {
+ *Response = Resp;
+ } else if (Buffer != NULL) {
+ *Response = Buffer;
+ }
} else {
- FreePool(Resp);
+ if (Resp != NULL) {
+ FreePool(Resp);
+ }
+ if (Buffer != NULL) {
+ FreePool(Buffer);
+ }
}
+ ShellPrintEx(-1, -1, L"\r\n");
return (Status);
}
@@ -2973,8 +3258,9 @@ ShellPromptForResponse (
@param Type What type of question is asked. This is used to filter the input
to prevent invalid answers to question.
- @param Prompt Pointer to string prompt to use to request input.
- @param Response Pointer to Response which will be populated upon return.
+ @param[in] HiiFormatStringId The format string Id for getting from Hii.
+ @param[in] HiiFormatHandle The format string Handle for getting from Hii.
+ @param Response Pointer to Response which will be populated upon return.
@retval EFI_SUCCESS the operation was sucessful.
@return other the operation failed.
@@ -2999,4 +3285,107 @@ ShellPromptForResponseHii (
return (Status);
}
+/**
+ Function to determin if an entire string is a valid number.
+
+ If Hex it must be preceeded with a 0x or has ForceHex, set TRUE.
+ @param[in] String The string to evaluate.
+ @param[in] ForceHex TRUE - always assume hex.
+ @param[in] StopAtSpace TRUE to halt upon finding a space, FALSE to keep going.
+
+ @retval TRUE It is all numeric (dec/hex) characters.
+ @retval FALSE There is a non-numeric character.
+**/
+BOOLEAN
+EFIAPI
+ShellIsHexOrDecimalNumber (
+ IN CONST CHAR16 *String,
+ IN CONST BOOLEAN ForceHex,
+ IN CONST BOOLEAN StopAtSpace
+ )
+{
+ BOOLEAN Hex;
+
+ //
+ // chop off a single negative sign
+ //
+ if (String != NULL && *String == L'-') {
+ String++;
+ }
+
+ if (String == NULL) {
+ return (FALSE);
+ }
+
+ //
+ // chop leading zeroes
+ //
+ while(String != NULL && *String == L'0'){
+ String++;
+ }
+ //
+ // allow '0x' or '0X', but not 'x' or 'X'
+ //
+ if (String != NULL && (*String == L'x' || *String == L'X')) {
+ if (*(String-1) != L'0') {
+ //
+ // we got an x without a preceeding 0
+ //
+ return (FALSE);
+ }
+ String++;
+ Hex = TRUE;
+ } else if (ForceHex) {
+ Hex = TRUE;
+ } else {
+ Hex = FALSE;
+ }
+
+ //
+ // loop through the remaining characters and use the lib function
+ //
+ for ( ; String != NULL && *String != CHAR_NULL && !(StopAtSpace && *String == L' ') ; String++){
+ if (Hex) {
+ if (!ShellIsHexaDecimalDigitCharacter(*String)) {
+ return (FALSE);
+ }
+ } else {
+ if (!ShellIsDecimalDigitCharacter(*String)) {
+ return (FALSE);
+ }
+ }
+ }
+ return (TRUE);
+}
+
+/**
+ Function to determine if a given filename exists.
+
+ @param[in] Name Path to test.
+
+ @retval EFI_SUCCESS The Path represents a file.
+ @retval EFI_NOT_FOUND The Path does not represent a file.
+ @retval other The path failed to open.
+**/
+EFI_STATUS
+EFIAPI
+ShellFileExists(
+ IN CONST CHAR16 *Name
+ )
+{
+ EFI_STATUS Status;
+ EFI_SHELL_FILE_INFO *List;
+
+ ASSERT(Name != NULL);
+
+ List = NULL;
+ Status = ShellOpenFileMetaArg((CHAR16*)Name, EFI_FILE_MODE_READ, &List);
+ if (EFI_ERROR(Status)) {
+ return (Status);
+ }
+
+ ShellCloseFileMetaArg(&List);
+
+ return (EFI_SUCCESS);
+}
diff --git a/ShellPkg/Library/UefiShellLib/UefiShellLib.inf b/ShellPkg/Library/UefiShellLib/UefiShellLib.inf
index b35555bb67..bcbf9bdd7a 100644
--- a/ShellPkg/Library/UefiShellLib/UefiShellLib.inf
+++ b/ShellPkg/Library/UefiShellLib/UefiShellLib.inf
@@ -1,7 +1,7 @@
-## @file
+## @file
# Provides interface to shell functionality for shell commands and applications.
#
-# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved. <BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
@@ -27,7 +27,7 @@
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
-[Sources]
+[Sources.common]
UefiShellLib.c
UefiShellLib.h
@@ -63,6 +63,6 @@
gEfiFileInfoGuid # ALWAYS_CONSUMED
gEfiShellEnvironment2ExtGuid # ALWAYS_CONSUMED
-[Pcd]
+[Pcd.common]
gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize # ALWAYS_CONSUMED
gEfiShellPkgTokenSpaceGuid.PcdShellPrintBufferSize # ALWAYS_CONSUMED
diff --git a/ShellPkg/Library/UefiSortLib/UefiSortLib.c b/ShellPkg/Library/UefiSortLib/UefiSortLib.c
index 28313b3bbe..efeaad8c76 100644
--- a/ShellPkg/Library/UefiSortLib/UefiSortLib.c
+++ b/ShellPkg/Library/UefiSortLib/UefiSortLib.c
@@ -1,7 +1,7 @@
/** @file
Library used for sorting routines.
- Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved. <BR>
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
@@ -71,7 +71,7 @@ QuickSortWorker (
if ( Count < 2
|| ElementSize < 1
- ){
+ ){
return;
}
@@ -89,7 +89,7 @@ QuickSortWorker (
for ( LoopCount = 0
; LoopCount < Count -1
; LoopCount++
- ){
+ ){
//
// if the element is less than the pivot
//
@@ -291,3 +291,24 @@ StringNoCaseCompare (
}
+/**
+ Function to compare 2 strings.
+
+ @param[in] Buffer1 Pointer to String to compare (CHAR16**).
+ @param[in] Buffer2 Pointer to second String to compare (CHAR16**).
+
+ @retval 0 Buffer1 equal to Buffer2.
+ @return < 0 Buffer1 is less than Buffer2.
+ @return > 0 Buffer1 is greater than Buffer2.
+**/
+INTN
+EFIAPI
+StringCompare (
+ IN CONST VOID *Buffer1,
+ IN CONST VOID *Buffer2
+ )
+{
+ return (StrCmp(
+ *(CHAR16**)Buffer1,
+ *(CHAR16**)Buffer2));
+}
diff --git a/ShellPkg/Library/UefiSortLib/UefiSortLib.inf b/ShellPkg/Library/UefiSortLib/UefiSortLib.inf
index f329693436..a6dcb27516 100644
--- a/ShellPkg/Library/UefiSortLib/UefiSortLib.inf
+++ b/ShellPkg/Library/UefiSortLib/UefiSortLib.inf
@@ -1,7 +1,7 @@
-## @file
+## @file
# Library used for sorting routines.
#
-# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2009, Intel Corporation. All rights reserved. <BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
@@ -19,13 +19,13 @@
FILE_GUID = 4264A823-45A3-42db-B92C-AA078555CBD3
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
- LIBRARY_CLASS = SORTLib|UEFI_APPLICATION UEFI_DRIVER
+ LIBRARY_CLASS = SortLib|UEFI_APPLICATION UEFI_DRIVER UEFI_DRIVER
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
-[Sources]
+[Sources.common]
UefiSortLib.c
[Packages]
@@ -46,4 +46,4 @@
[Guids]
-[Pcd]
+[Pcd.common]