2010-09-14 07:18:09 +02:00
/** @file
Member functions of EFI_SHELL_PROTOCOL and functions for creation ,
manipulation , and initialization of EFI_SHELL_PROTOCOL .
2011-03-25 23:23:05 +01:00
Copyright ( c ) 2009 - 2011 , Intel Corporation . All rights reserved . < BR >
2010-09-14 07:18:09 +02:00
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 "Shell.h"
# include <Library/FileHandleLib.h>
/**
Close an open file handle .
This function closes a specified file handle . All " dirty " cached file data is
flushed to the device , and the file is closed . In all cases the handle is
closed .
@ param [ in ] FileHandle The file handle to close .
@ retval EFI_SUCCESS The file handle was closed successfully .
* */
EFI_STATUS
EFIAPI
EfiShellClose (
IN SHELL_FILE_HANDLE FileHandle
)
{
ShellFileHandleRemove ( FileHandle ) ;
2010-11-16 23:31:47 +01:00
return ( FileHandleClose ( ConvertShellHandleToEfiFileProtocol ( FileHandle ) ) ) ;
2010-09-14 07:18:09 +02:00
}
2011-03-25 23:23:05 +01:00
/**
Internal worker to determine whether there is a BlockIo somewhere
upon the device path specified .
@ param [ in ] DevicePath The device path to test .
@ retval TRUE gEfiBlockIoProtocolGuid was installed on a handle with this device path
@ retval FALSE gEfiBlockIoProtocolGuid was not found .
* */
BOOLEAN
EFIAPI
InternalShellProtocolIsBlockIoPresent (
IN CONST EFI_DEVICE_PATH_PROTOCOL * DevicePath
)
{
EFI_DEVICE_PATH_PROTOCOL * DevicePathCopy ;
EFI_STATUS Status ;
EFI_HANDLE Handle ;
Handle = NULL ;
DevicePathCopy = ( EFI_DEVICE_PATH_PROTOCOL * ) DevicePath ;
Status = gBS - > LocateDevicePath ( & gEfiBlockIoProtocolGuid , & DevicePathCopy , & Handle ) ;
if ( ( Handle ! = NULL ) & & ( ! EFI_ERROR ( Status ) ) ) {
return ( TRUE ) ;
}
return ( FALSE ) ;
}
2010-09-14 07:18:09 +02:00
/**
Internal worker to determine whether there is a file system somewhere
upon the device path specified .
@ param [ in ] DevicePath The device path to test .
@ retval TRUE gEfiSimpleFileSystemProtocolGuid was installed on a handle with this device path
@ retval FALSE gEfiSimpleFileSystemProtocolGuid was not found .
* */
BOOLEAN
EFIAPI
InternalShellProtocolIsSimpleFileSystemPresent (
IN CONST EFI_DEVICE_PATH_PROTOCOL * DevicePath
)
{
EFI_DEVICE_PATH_PROTOCOL * DevicePathCopy ;
EFI_STATUS Status ;
EFI_HANDLE Handle ;
Handle = NULL ;
DevicePathCopy = ( EFI_DEVICE_PATH_PROTOCOL * ) DevicePath ;
Status = gBS - > LocateDevicePath ( & gEfiSimpleFileSystemProtocolGuid , & DevicePathCopy , & Handle ) ;
if ( ( Handle ! = NULL ) & & ( ! EFI_ERROR ( Status ) ) ) {
return ( TRUE ) ;
}
return ( FALSE ) ;
}
/**
Internal worker debug helper function to print out maps as they are added .
@ param [ in ] Mapping string mapping that has been added
@ param [ in ] DevicePath pointer to device path that has been mapped .
@ retval EFI_SUCCESS the operation was successful .
@ return other an error ocurred
@ sa LocateHandle
@ sa OpenProtocol
* */
EFI_STATUS
EFIAPI
InternalShellProtocolDebugPrintMessage (
IN CONST CHAR16 * Mapping ,
IN CONST EFI_DEVICE_PATH_PROTOCOL * DevicePath
)
{
EFI_DEVICE_PATH_TO_TEXT_PROTOCOL * DevicePathToText ;
EFI_STATUS Status ;
CHAR16 * Temp ;
Status = EFI_SUCCESS ;
DEBUG_CODE_BEGIN ( ) ;
DevicePathToText = NULL ;
Status = gBS - > LocateProtocol ( & gEfiDevicePathToTextProtocolGuid ,
NULL ,
( VOID * * ) & DevicePathToText ) ;
if ( Mapping ! = NULL ) {
DEBUG ( ( EFI_D_INFO , " Added new map item: \" %S \" \r \n " , Mapping ) ) ;
}
if ( ! EFI_ERROR ( Status ) ) {
if ( DevicePath ! = NULL ) {
Temp = DevicePathToText - > ConvertDevicePathToText ( DevicePath , TRUE , TRUE ) ;
DEBUG ( ( EFI_D_INFO , " DevicePath: %S \r \n " , Temp ) ) ;
FreePool ( Temp ) ;
}
}
DEBUG_CODE_END ( ) ;
return ( Status ) ;
}
/**
This function creates a mapping for a device path .
If both DeviecPath and Mapping are NULL , this will reset the mapping to default values .
@ param DevicePath Points to the device path . If this is NULL and Mapping points to a valid mapping ,
then the mapping will be deleted .
@ param Mapping Points to the NULL - terminated mapping for the device path . Must end with a ' : '
@ retval EFI_SUCCESS Mapping created or deleted successfully .
@ retval EFI_NO_MAPPING There is no handle that corresponds exactly to DevicePath . See the
boot service function LocateDevicePath ( ) .
@ retval EFI_ACCESS_DENIED The mapping is a built - in alias .
@ retval EFI_INVALID_PARAMETER Mapping was NULL
@ retval EFI_INVALID_PARAMETER Mapping did not end with a ' : '
@ retval EFI_INVALID_PARAMETER DevicePath was not pointing at a device that had a SIMPLE_FILE_SYSTEM_PROTOCOL installed .
@ retval EFI_NOT_FOUND There was no mapping found to delete
@ retval EFI_OUT_OF_RESOURCES Memory allocation failed
* */
EFI_STATUS
EFIAPI
EfiShellSetMap (
IN CONST EFI_DEVICE_PATH_PROTOCOL * DevicePath OPTIONAL ,
IN CONST CHAR16 * Mapping
)
{
EFI_STATUS Status ;
SHELL_MAP_LIST * MapListNode ;
if ( Mapping = = NULL ) {
return ( EFI_INVALID_PARAMETER ) ;
}
if ( Mapping [ StrLen ( Mapping ) - 1 ] ! = ' : ' ) {
return ( EFI_INVALID_PARAMETER ) ;
}
//
// Delete the mapping
//
if ( DevicePath = = NULL ) {
if ( IsListEmpty ( & gShellMapList . Link ) ) {
return ( EFI_NOT_FOUND ) ;
}
for ( MapListNode = ( SHELL_MAP_LIST * ) GetFirstNode ( & gShellMapList . Link )
; ! IsNull ( & gShellMapList . Link , & MapListNode - > Link )
; MapListNode = ( SHELL_MAP_LIST * ) GetNextNode ( & gShellMapList . Link , & MapListNode - > Link )
) {
if ( StringNoCaseCompare ( & MapListNode - > MapName , & Mapping ) = = 0 ) {
RemoveEntryList ( & MapListNode - > Link ) ;
FreePool ( MapListNode ) ;
return ( EFI_SUCCESS ) ;
}
} // for loop
//
// We didnt find one to delete
//
return ( EFI_NOT_FOUND ) ;
}
//
// make sure this is a valid to add device path
//
///@todo add BlockIo to this test...
2011-03-25 23:23:05 +01:00
if ( ! InternalShellProtocolIsSimpleFileSystemPresent ( DevicePath )
& & ! InternalShellProtocolIsBlockIoPresent ( DevicePath ) ) {
2010-09-14 07:18:09 +02:00
return ( EFI_INVALID_PARAMETER ) ;
}
//
// First make sure there is no old mapping
//
Status = EfiShellSetMap ( NULL , Mapping ) ;
if ( ( Status ! = EFI_SUCCESS ) & & ( Status ! = EFI_NOT_FOUND ) ) {
return ( Status ) ;
}
//
// now add the new one.
//
Status = ShellCommandAddMapItemAndUpdatePath ( Mapping , DevicePath , 0 , FALSE ) ;
return ( Status ) ;
}
/**
Gets the device path from the mapping .
This function gets the device path associated with a mapping .
@ param Mapping A pointer to the mapping
@ retval ! = NULL Pointer to the device path that corresponds to the
device mapping . The returned pointer does not need
to be freed .
@ retval NULL There is no device path associated with the
specified mapping .
* */
CONST EFI_DEVICE_PATH_PROTOCOL *
EFIAPI
EfiShellGetDevicePathFromMap (
IN CONST CHAR16 * Mapping
)
{
SHELL_MAP_LIST * MapListItem ;
CHAR16 * NewName ;
UINTN Size ;
NewName = NULL ;
Size = 0 ;
StrnCatGrow ( & NewName , & Size , Mapping , 0 ) ;
if ( Mapping [ StrLen ( Mapping ) - 1 ] ! = L ' : ' ) {
StrnCatGrow ( & NewName , & Size , L " : " , 0 ) ;
}
MapListItem = ShellCommandFindMapItem ( NewName ) ;
FreePool ( NewName ) ;
if ( MapListItem ! = NULL ) {
return ( MapListItem - > DevicePath ) ;
}
return ( NULL ) ;
}
/**
Gets the mapping ( s ) that most closely matches the device path .
This function gets the mapping which corresponds to the device path * DevicePath . If
there is no exact match , then the mapping which most closely matches * DevicePath
is returned , and * DevicePath is updated to point to the remaining portion of the
device path . If there is an exact match , the mapping is returned and * DevicePath
points to the end - of - device - path node .
If there are multiple map names they will be semi - colon seperated in the
NULL - terminated string .
@ param DevicePath On entry , points to a device path pointer . On
exit , updates the pointer to point to the
portion of the device path after the mapping .
@ retval NULL No mapping was found .
@ return ! = NULL Pointer to NULL - terminated mapping . The buffer
is callee allocated and should be freed by the caller .
* */
CONST CHAR16 *
EFIAPI
EfiShellGetMapFromDevicePath (
IN OUT EFI_DEVICE_PATH_PROTOCOL * * DevicePath
)
{
SHELL_MAP_LIST * Node ;
CHAR16 * PathForReturn ;
UINTN PathSize ;
// EFI_HANDLE PathHandle;
// EFI_HANDLE MapHandle;
// EFI_STATUS Status;
// EFI_DEVICE_PATH_PROTOCOL *DevicePathCopy;
// EFI_DEVICE_PATH_PROTOCOL *MapPathCopy;
if ( DevicePath = = NULL | | * DevicePath = = NULL ) {
return ( NULL ) ;
}
PathForReturn = NULL ;
PathSize = 0 ;
for ( Node = ( SHELL_MAP_LIST * ) GetFirstNode ( & gShellMapList . Link )
; ! IsNull ( & gShellMapList . Link , & Node - > Link )
; Node = ( SHELL_MAP_LIST * ) GetNextNode ( & gShellMapList . Link , & Node - > Link )
) {
//
// check for exact match
//
if ( DevicePathCompare ( DevicePath , & Node - > DevicePath ) = = 0 ) {
ASSERT ( ( PathForReturn = = NULL & & PathSize = = 0 ) | | ( PathForReturn ! = NULL ) ) ;
if ( PathSize ! = 0 ) {
PathForReturn = StrnCatGrow ( & PathForReturn , & PathSize , L " ; " , 0 ) ;
}
PathForReturn = StrnCatGrow ( & PathForReturn , & PathSize , Node - > MapName , 0 ) ;
}
}
if ( PathForReturn ! = NULL ) {
while ( ! IsDevicePathEndType ( * DevicePath ) ) {
* DevicePath = NextDevicePathNode ( * DevicePath ) ;
}
SetDevicePathEndNode ( * DevicePath ) ;
}
/*
///@todo finish code for inexact matches.
if ( PathForReturn = = NULL ) {
PathSize = 0 ;
DevicePathCopy = DuplicateDevicePath ( * DevicePath ) ;
ASSERT ( DevicePathCopy ! = NULL ) ;
Status = gBS - > LocateDevicePath ( & gEfiSimpleFileSystemProtocolGuid , & DevicePathCopy , & PathHandle ) ;
ASSERT_EFI_ERROR ( Status ) ;
//
// check each of the device paths we have to get the root of the path for consist mappings
//
for ( Node = ( SHELL_MAP_LIST * ) GetFirstNode ( & gShellMapList . Link )
; ! IsNull ( & gShellMapList . Link , & Node - > Link )
; Node = ( SHELL_MAP_LIST * ) GetNextNode ( & gShellMapList . Link , & Node - > Link )
) {
if ( ( Node - > Flags & SHELL_MAP_FLAGS_CONSIST ) = = 0 ) {
continue ;
}
MapPathCopy = DuplicateDevicePath ( Node - > DevicePath ) ;
ASSERT ( MapPathCopy ! = NULL ) ;
Status = gBS - > LocateDevicePath ( & gEfiSimpleFileSystemProtocolGuid , & MapPathCopy , & MapHandle ) ;
if ( MapHandle = = PathHandle ) {
* DevicePath = DevicePathCopy ;
MapPathCopy = NULL ;
DevicePathCopy = NULL ;
PathForReturn = StrnCatGrow ( & PathForReturn , & PathSize , Node - > MapName , 0 ) ;
PathForReturn = StrnCatGrow ( & PathForReturn , & PathSize , L " ; " , 0 ) ;
break ;
}
}
//
// now add on the non-consistent mappings
//
for ( Node = ( SHELL_MAP_LIST * ) GetFirstNode ( & gShellMapList . Link )
; ! IsNull ( & gShellMapList . Link , & Node - > Link )
; Node = ( SHELL_MAP_LIST * ) GetNextNode ( & gShellMapList . Link , & Node - > Link )
) {
if ( ( Node - > Flags & SHELL_MAP_FLAGS_CONSIST ) ! = 0 ) {
continue ;
}
MapPathCopy = Node - > DevicePath ;
ASSERT ( MapPathCopy ! = NULL ) ;
Status = gBS - > LocateDevicePath ( & gEfiSimpleFileSystemProtocolGuid , & MapPathCopy , & MapHandle ) ;
if ( MapHandle = = PathHandle ) {
PathForReturn = StrnCatGrow ( & PathForReturn , & PathSize , Node - > MapName , 0 ) ;
PathForReturn = StrnCatGrow ( & PathForReturn , & PathSize , L " ; " , 0 ) ;
break ;
}
}
}
*/
return ( AddBufferToFreeList ( PathForReturn ) ) ;
}
/**
Converts a device path to a file system - style path .
This function converts a device path to a file system path by replacing part , or all , of
the device path with the file - system mapping . If there are more than one application
file system mappings , the one that most closely matches Path will be used .
@ param Path The pointer to the device path
@ retval NULL the device path could not be found .
@ return all The pointer of the NULL - terminated file path . The path
is callee - allocated and should be freed by the caller .
* */
CHAR16 *
EFIAPI
EfiShellGetFilePathFromDevicePath (
IN CONST EFI_DEVICE_PATH_PROTOCOL * Path
)
{
EFI_DEVICE_PATH_PROTOCOL * DevicePathCopy ;
EFI_DEVICE_PATH_PROTOCOL * MapPathCopy ;
SHELL_MAP_LIST * MapListItem ;
CHAR16 * PathForReturn ;
UINTN PathSize ;
EFI_HANDLE PathHandle ;
EFI_HANDLE MapHandle ;
EFI_STATUS Status ;
FILEPATH_DEVICE_PATH * FilePath ;
2010-11-24 17:12:11 +01:00
FILEPATH_DEVICE_PATH * AlignedNode ;
2010-09-14 07:18:09 +02:00
PathForReturn = NULL ;
PathSize = 0 ;
DevicePathCopy = ( EFI_DEVICE_PATH_PROTOCOL * ) Path ;
ASSERT ( DevicePathCopy ! = NULL ) ;
if ( DevicePathCopy = = NULL ) {
return ( NULL ) ;
}
///@todo BlockIo?
Status = gBS - > LocateDevicePath ( & gEfiSimpleFileSystemProtocolGuid , & DevicePathCopy , & PathHandle ) ;
if ( EFI_ERROR ( Status ) ) {
return ( NULL ) ;
}
//
// check each of the device paths we have to get the root of the path
//
for ( MapListItem = ( SHELL_MAP_LIST * ) GetFirstNode ( & gShellMapList . Link )
; ! IsNull ( & gShellMapList . Link , & MapListItem - > Link )
; MapListItem = ( SHELL_MAP_LIST * ) GetNextNode ( & gShellMapList . Link , & MapListItem - > Link )
) {
MapPathCopy = ( EFI_DEVICE_PATH_PROTOCOL * ) MapListItem - > DevicePath ;
ASSERT ( MapPathCopy ! = NULL ) ;
///@todo BlockIo?
Status = gBS - > LocateDevicePath ( & gEfiSimpleFileSystemProtocolGuid , & MapPathCopy , & MapHandle ) ;
if ( MapHandle = = PathHandle ) {
ASSERT ( ( PathForReturn = = NULL & & PathSize = = 0 ) | | ( PathForReturn ! = NULL ) ) ;
PathForReturn = StrnCatGrow ( & PathForReturn , & PathSize , MapListItem - > MapName , 0 ) ;
//
// go through all the remaining nodes in the device path
//
for ( FilePath = ( FILEPATH_DEVICE_PATH * ) DevicePathCopy
; ! IsDevicePathEnd ( & FilePath - > Header )
; FilePath = ( FILEPATH_DEVICE_PATH * ) NextDevicePathNode ( & FilePath - > Header )
) {
//
// all the rest should be file path nodes
//
if ( ( DevicePathType ( & FilePath - > Header ) ! = MEDIA_DEVICE_PATH ) | |
( DevicePathSubType ( & FilePath - > Header ) ! = MEDIA_FILEPATH_DP ) ) {
FreePool ( PathForReturn ) ;
PathForReturn = NULL ;
ASSERT ( FALSE ) ;
} else {
//
// append the path part onto the filepath.
//
ASSERT ( ( PathForReturn = = NULL & & PathSize = = 0 ) | | ( PathForReturn ! = NULL ) ) ;
PathForReturn = StrnCatGrow ( & PathForReturn , & PathSize , L " \\ " , 1 ) ;
2010-11-24 17:12:11 +01:00
AlignedNode = AllocateCopyPool ( DevicePathNodeLength ( FilePath ) , FilePath ) ;
PathForReturn = StrnCatGrow ( & PathForReturn , & PathSize , AlignedNode - > PathName , 0 ) ;
FreePool ( AlignedNode ) ;
2010-09-14 07:18:09 +02:00
}
} // for loop of remaining nodes
}
if ( PathForReturn ! = NULL ) {
break ;
}
} // for loop of paths to check
return ( PathForReturn ) ;
}
/**
Converts a file system style name to a device path .
This function converts a file system style name to a device path , by replacing any
mapping references to the associated device path .
@ param Path the pointer to the path
@ return all The pointer of the file path . The file path is callee
allocated and should be freed by the caller .
* */
EFI_DEVICE_PATH_PROTOCOL *
EFIAPI
EfiShellGetDevicePathFromFilePath (
IN CONST CHAR16 * Path
)
{
CHAR16 * MapName ;
CHAR16 * NewPath ;
CONST CHAR16 * Cwd ;
UINTN Size ;
CONST EFI_DEVICE_PATH_PROTOCOL * DevicePath ;
EFI_DEVICE_PATH_PROTOCOL * DevicePathCopy ;
EFI_DEVICE_PATH_PROTOCOL * DevicePathCopyForFree ;
EFI_DEVICE_PATH_PROTOCOL * DevicePathForReturn ;
EFI_HANDLE Handle ;
EFI_STATUS Status ;
2010-11-16 23:31:47 +01:00
if ( Path = = NULL ) {
return ( NULL ) ;
}
2010-09-14 07:18:09 +02:00
MapName = NULL ;
2010-11-16 23:31:47 +01:00
NewPath = NULL ;
2010-09-14 07:18:09 +02:00
if ( StrStr ( Path , L " : " ) = = NULL ) {
Cwd = EfiShellGetCurDir ( NULL ) ;
if ( Cwd = = NULL ) {
return ( NULL ) ;
}
Size = StrSize ( Cwd ) ;
Size + = StrSize ( Path ) ;
NewPath = AllocateZeroPool ( Size ) ;
ASSERT ( NewPath ! = NULL ) ;
StrCpy ( NewPath , Cwd ) ;
2011-03-25 23:23:05 +01:00
if ( * Path = = L ' \\ ' ) {
Path + + ;
while ( ChopLastSlash ( NewPath ) ) ;
2010-09-14 07:18:09 +02:00
}
StrCat ( NewPath , Path ) ;
DevicePathForReturn = EfiShellGetDevicePathFromFilePath ( NewPath ) ;
FreePool ( NewPath ) ;
return ( DevicePathForReturn ) ;
}
Size = 0 ;
//
// find the part before (but including) the : for the map name
//
ASSERT ( ( MapName = = NULL & & Size = = 0 ) | | ( MapName ! = NULL ) ) ;
MapName = StrnCatGrow ( & MapName , & Size , Path , ( StrStr ( Path , L " : " ) - Path + 1 ) ) ;
if ( MapName [ StrLen ( MapName ) - 1 ] ! = L ' : ' ) {
ASSERT ( FALSE ) ;
return ( NULL ) ;
}
//
// look up the device path in the map
//
DevicePath = EfiShellGetDevicePathFromMap ( MapName ) ;
if ( DevicePath = = NULL ) {
//
// Must have been a bad Mapname
//
return ( NULL ) ;
}
//
// make a copy for LocateDevicePath to modify (also save a pointer to call FreePool with)
//
DevicePathCopyForFree = DevicePathCopy = DuplicateDevicePath ( DevicePath ) ;
if ( DevicePathCopy = = NULL ) {
ASSERT ( FALSE ) ;
FreePool ( MapName ) ;
return ( NULL ) ;
}
//
// get the handle
//
///@todo BlockIo?
Status = gBS - > LocateDevicePath ( & gEfiSimpleFileSystemProtocolGuid , & DevicePathCopy , & Handle ) ;
if ( EFI_ERROR ( Status ) ) {
if ( DevicePathCopyForFree ! = NULL ) {
FreePool ( DevicePathCopyForFree ) ;
}
FreePool ( MapName ) ;
return ( NULL ) ;
}
//
// build the full device path
//
2011-03-28 23:49:17 +02:00
if ( * ( Path + StrLen ( MapName ) + 1 ) = = CHAR_NULL ) {
DevicePathForReturn = FileDevicePath ( Handle , L " \\ " ) ;
} else {
DevicePathForReturn = FileDevicePath ( Handle , Path + StrLen ( MapName ) + 1 ) ;
}
2010-09-14 07:18:09 +02:00
FreePool ( MapName ) ;
if ( DevicePathCopyForFree ! = NULL ) {
FreePool ( DevicePathCopyForFree ) ;
}
return ( DevicePathForReturn ) ;
}
/**
Gets the name of the device specified by the device handle .
This function gets the user - readable name of the device specified by the device
handle . If no user - readable name could be generated , then * BestDeviceName will be
NULL and EFI_NOT_FOUND will be returned .
If EFI_DEVICE_NAME_USE_COMPONENT_NAME is set , then the function will return the
device ' s name using the EFI_COMPONENT_NAME2_PROTOCOL , if present on
DeviceHandle .
If EFI_DEVICE_NAME_USE_DEVICE_PATH is set , then the function will return the
device ' s name using the EFI_DEVICE_PATH_PROTOCOL , if present on DeviceHandle .
If both EFI_DEVICE_NAME_USE_COMPONENT_NAME and
EFI_DEVICE_NAME_USE_DEVICE_PATH are set , then
EFI_DEVICE_NAME_USE_COMPONENT_NAME will have higher priority .
@ param DeviceHandle The handle of the device .
@ param Flags Determines the possible sources of component names .
Valid bits are :
EFI_DEVICE_NAME_USE_COMPONENT_NAME
EFI_DEVICE_NAME_USE_DEVICE_PATH
@ param Language A pointer to the language specified for the device
name , in the same format as described in the UEFI
specification , Appendix M
@ param BestDeviceName On return , points to the callee - allocated NULL -
terminated name of the device . If no device name
could be found , points to NULL . The name must be
freed by the caller . . .
@ retval EFI_SUCCESS Get the name successfully .
@ retval EFI_NOT_FOUND Fail to get the device name .
@ retval EFI_INVALID_PARAMETER Flags did not have a valid bit set .
@ retval EFI_INVALID_PARAMETER BestDeviceName was NULL
@ retval EFI_INVALID_PARAMETER DeviceHandle was NULL
* */
EFI_STATUS
EFIAPI
EfiShellGetDeviceName (
IN EFI_HANDLE DeviceHandle ,
IN EFI_SHELL_DEVICE_NAME_FLAGS Flags ,
IN CHAR8 * Language ,
OUT CHAR16 * * BestDeviceName
)
{
EFI_STATUS Status ;
EFI_COMPONENT_NAME2_PROTOCOL * CompName2 ;
EFI_DEVICE_PATH_TO_TEXT_PROTOCOL * DevicePathToText ;
EFI_DEVICE_PATH_PROTOCOL * DevicePath ;
EFI_HANDLE * HandleList ;
UINTN HandleCount ;
UINTN LoopVar ;
CHAR16 * DeviceNameToReturn ;
CHAR8 * Lang ;
CHAR8 * TempChar ;
2011-03-25 23:23:05 +01:00
UINTN ParentControllerCount ;
EFI_HANDLE * ParentControllerBuffer ;
UINTN ParentDriverCount ;
EFI_HANDLE * ParentDriverBuffer ;
2010-09-14 07:18:09 +02:00
if ( BestDeviceName = = NULL | |
DeviceHandle = = NULL
) {
return ( EFI_INVALID_PARAMETER ) ;
}
//
// make sure one of the 2 supported bits is on
//
if ( ( ( Flags & EFI_DEVICE_NAME_USE_COMPONENT_NAME ) = = 0 ) & &
( ( Flags & EFI_DEVICE_NAME_USE_DEVICE_PATH ) = = 0 ) ) {
return ( EFI_INVALID_PARAMETER ) ;
}
DeviceNameToReturn = NULL ;
* BestDeviceName = NULL ;
HandleList = NULL ;
HandleCount = 0 ;
Lang = NULL ;
if ( ( Flags & EFI_DEVICE_NAME_USE_COMPONENT_NAME ) ! = 0 ) {
Status = ParseHandleDatabaseByRelationship (
NULL ,
DeviceHandle ,
HR_DRIVER_BINDING_HANDLE | HR_DEVICE_DRIVER ,
& HandleCount ,
& HandleList ) ;
for ( LoopVar = 0 ; LoopVar < HandleCount ; LoopVar + + ) {
//
// Go through those handles until we get one that passes for GetComponentName
//
Status = gBS - > OpenProtocol (
HandleList [ LoopVar ] ,
& gEfiComponentName2ProtocolGuid ,
( VOID * * ) & CompName2 ,
gImageHandle ,
NULL ,
EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ;
if ( EFI_ERROR ( Status ) ) {
Status = gBS - > OpenProtocol (
HandleList [ LoopVar ] ,
& gEfiComponentNameProtocolGuid ,
( VOID * * ) & CompName2 ,
gImageHandle ,
NULL ,
EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ;
}
if ( EFI_ERROR ( Status ) ) {
continue ;
}
if ( Language = = NULL ) {
2011-03-25 23:23:05 +01:00
Lang = AllocateZeroPool ( AsciiStrSize ( CompName2 - > SupportedLanguages ) ) ;
2010-10-04 18:24:30 +02:00
if ( Lang = = NULL ) {
return ( EFI_OUT_OF_RESOURCES ) ;
}
2010-09-14 07:18:09 +02:00
AsciiStrCpy ( Lang , CompName2 - > SupportedLanguages ) ;
TempChar = AsciiStrStr ( Lang , " ; " ) ;
if ( TempChar ! = NULL ) {
* TempChar = CHAR_NULL ;
}
} else {
2011-03-25 23:23:05 +01:00
Lang = AllocateZeroPool ( AsciiStrSize ( Language ) ) ;
2010-10-04 18:24:30 +02:00
if ( Lang = = NULL ) {
return ( EFI_OUT_OF_RESOURCES ) ;
}
2010-09-14 07:18:09 +02:00
AsciiStrCpy ( Lang , Language ) ;
}
Status = CompName2 - > GetControllerName ( CompName2 , DeviceHandle , NULL , Lang , & DeviceNameToReturn ) ;
FreePool ( Lang ) ;
Lang = NULL ;
if ( ! EFI_ERROR ( Status ) & & DeviceNameToReturn ! = NULL ) {
break ;
}
}
if ( HandleList ! = NULL ) {
FreePool ( HandleList ) ;
}
2011-03-25 23:23:05 +01:00
//
// Now check the parent controller using this as the child.
//
if ( DeviceNameToReturn = = NULL ) {
PARSE_HANDLE_DATABASE_PARENTS ( DeviceHandle , & ParentControllerCount , & ParentControllerBuffer ) ;
for ( LoopVar = 0 ; LoopVar < ParentControllerCount ; LoopVar + + ) {
PARSE_HANDLE_DATABASE_UEFI_DRIVERS ( ParentControllerBuffer [ LoopVar ] , & ParentDriverCount , & ParentDriverBuffer ) ;
for ( HandleCount = 0 ; HandleCount < ParentDriverCount ; HandleCount + + ) {
//
// try using that driver's component name with controller and our driver as the child.
//
Status = gBS - > OpenProtocol (
ParentDriverBuffer [ HandleCount ] ,
& gEfiComponentName2ProtocolGuid ,
( VOID * * ) & CompName2 ,
gImageHandle ,
NULL ,
EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ;
if ( EFI_ERROR ( Status ) ) {
Status = gBS - > OpenProtocol (
ParentDriverBuffer [ HandleCount ] ,
& gEfiComponentNameProtocolGuid ,
( VOID * * ) & CompName2 ,
gImageHandle ,
NULL ,
EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ;
}
if ( EFI_ERROR ( Status ) ) {
continue ;
}
if ( Language = = NULL ) {
Lang = AllocateZeroPool ( AsciiStrSize ( CompName2 - > SupportedLanguages ) ) ;
if ( Lang = = NULL ) {
return ( EFI_OUT_OF_RESOURCES ) ;
}
AsciiStrCpy ( Lang , CompName2 - > SupportedLanguages ) ;
TempChar = AsciiStrStr ( Lang , " ; " ) ;
if ( TempChar ! = NULL ) {
* TempChar = CHAR_NULL ;
}
} else {
Lang = AllocateZeroPool ( AsciiStrSize ( Language ) ) ;
if ( Lang = = NULL ) {
return ( EFI_OUT_OF_RESOURCES ) ;
}
AsciiStrCpy ( Lang , Language ) ;
}
Status = CompName2 - > GetControllerName ( CompName2 , ParentControllerBuffer [ LoopVar ] , DeviceHandle , Lang , & DeviceNameToReturn ) ;
FreePool ( Lang ) ;
Lang = NULL ;
if ( ! EFI_ERROR ( Status ) & & DeviceNameToReturn ! = NULL ) {
break ;
}
}
SHELL_FREE_NON_NULL ( ParentDriverBuffer ) ;
if ( ! EFI_ERROR ( Status ) & & DeviceNameToReturn ! = NULL ) {
break ;
}
}
SHELL_FREE_NON_NULL ( ParentControllerBuffer ) ;
}
//
// dont return on fail since we will try device path if that bit is on
//
2010-09-14 07:18:09 +02:00
if ( DeviceNameToReturn ! = NULL ) {
2010-10-04 18:24:30 +02:00
ASSERT ( BestDeviceName ! = NULL ) ;
2010-09-14 07:18:09 +02:00
StrnCatGrow ( BestDeviceName , NULL , DeviceNameToReturn , 0 ) ;
return ( EFI_SUCCESS ) ;
}
}
if ( ( Flags & EFI_DEVICE_NAME_USE_DEVICE_PATH ) ! = 0 ) {
Status = gBS - > LocateProtocol (
& gEfiDevicePathToTextProtocolGuid ,
NULL ,
( VOID * * ) & DevicePathToText ) ;
//
// we now have the device path to text protocol
//
if ( ! EFI_ERROR ( Status ) ) {
Status = gBS - > OpenProtocol (
DeviceHandle ,
& gEfiDevicePathProtocolGuid ,
( VOID * * ) & DevicePath ,
gImageHandle ,
NULL ,
EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ;
if ( ! EFI_ERROR ( Status ) ) {
//
// use device path to text on the device path
//
* BestDeviceName = DevicePathToText - > ConvertDevicePathToText ( DevicePath , TRUE , TRUE ) ;
return ( EFI_SUCCESS ) ;
}
}
}
//
// none of the selected bits worked.
//
return ( EFI_NOT_FOUND ) ;
}
/**
Opens the root directory of a device on a handle
This function opens the root directory of a device and returns a file handle to it .
@ param DeviceHandle The handle of the device that contains the volume .
@ param FileHandle On exit , points to the file handle corresponding to the root directory on the
device .
@ retval EFI_SUCCESS Root opened successfully .
@ retval EFI_NOT_FOUND EFI_SIMPLE_FILE_SYSTEM could not be found or the root directory
could not be opened .
@ retval EFI_VOLUME_CORRUPTED The data structures in the volume were corrupted .
@ retval EFI_DEVICE_ERROR The device had an error
* */
EFI_STATUS
EFIAPI
EfiShellOpenRootByHandle (
IN EFI_HANDLE DeviceHandle ,
OUT SHELL_FILE_HANDLE * FileHandle
)
{
EFI_STATUS Status ;
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL * SimpleFileSystem ;
EFI_FILE_PROTOCOL * RealFileHandle ;
EFI_DEVICE_PATH_PROTOCOL * DevPath ;
//
// get the simple file system interface
//
Status = gBS - > OpenProtocol ( DeviceHandle ,
& gEfiSimpleFileSystemProtocolGuid ,
( VOID * * ) & SimpleFileSystem ,
gImageHandle ,
NULL ,
EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ;
if ( EFI_ERROR ( Status ) ) {
return ( EFI_NOT_FOUND ) ;
}
Status = gBS - > OpenProtocol ( DeviceHandle ,
& gEfiDevicePathProtocolGuid ,
( VOID * * ) & DevPath ,
gImageHandle ,
NULL ,
EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ;
if ( EFI_ERROR ( Status ) ) {
return ( EFI_NOT_FOUND ) ;
}
//
// Open the root volume now...
//
Status = SimpleFileSystem - > OpenVolume ( SimpleFileSystem , & RealFileHandle ) ;
* FileHandle = ConvertEfiFileProtocolToShellHandle ( RealFileHandle , EfiShellGetMapFromDevicePath ( & DevPath ) ) ;
return ( Status ) ;
}
/**
Opens the root directory of a device .
This function opens the root directory of a device and returns a file handle to it .
@ param DevicePath Points to the device path corresponding to the device where the
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL is installed .
@ param FileHandle On exit , points to the file handle corresponding to the root directory on the
device .
@ retval EFI_SUCCESS Root opened successfully .
@ retval EFI_NOT_FOUND EFI_SIMPLE_FILE_SYSTEM could not be found or the root directory
could not be opened .
@ retval EFI_VOLUME_CORRUPTED The data structures in the volume were corrupted .
@ retval EFI_DEVICE_ERROR The device had an error
2010-11-16 23:31:47 +01:00
@ retval EFI_INVALID_PARAMETER FileHandle is NULL .
2010-09-14 07:18:09 +02:00
* */
EFI_STATUS
EFIAPI
EfiShellOpenRoot (
IN EFI_DEVICE_PATH_PROTOCOL * DevicePath ,
OUT SHELL_FILE_HANDLE * FileHandle
)
{
EFI_STATUS Status ;
EFI_HANDLE Handle ;
2010-11-16 23:31:47 +01:00
if ( FileHandle = = NULL ) {
return ( EFI_INVALID_PARAMETER ) ;
}
2010-09-14 07:18:09 +02:00
//
// find the handle of the device with that device handle and the file system
//
///@todo BlockIo?
Status = gBS - > LocateDevicePath ( & gEfiSimpleFileSystemProtocolGuid ,
& DevicePath ,
& Handle ) ;
if ( EFI_ERROR ( Status ) ) {
return ( EFI_NOT_FOUND ) ;
}
return ( EfiShellOpenRootByHandle ( Handle , FileHandle ) ) ;
}
/**
Returns whether any script files are currently being processed .
@ retval TRUE There is at least one script file active .
@ retval FALSE No script files are active now .
* */
BOOLEAN
EFIAPI
EfiShellBatchIsActive (
VOID
)
{
if ( ShellCommandGetCurrentScriptFile ( ) = = NULL ) {
return ( FALSE ) ;
}
return ( TRUE ) ;
}
/**
Worker function to open a file based on a device path . this will open the root
of the volume and then traverse down to the file itself .
@ param DevicePath Device Path of the file .
@ param FileHandle Pointer to the file upon a successful return .
@ param OpenMode mode to open file in .
@ param Attributes the File Attributes to use when creating a new file .
@ retval EFI_SUCCESS the file is open and FileHandle is valid
@ retval EFI_UNSUPPORTED the device path cotained non - path elements
@ retval other an error ocurred .
* */
EFI_STATUS
EFIAPI
InternalOpenFileDevicePath (
IN OUT EFI_DEVICE_PATH_PROTOCOL * DevicePath ,
OUT SHELL_FILE_HANDLE * FileHandle ,
IN UINT64 OpenMode ,
IN UINT64 Attributes OPTIONAL
)
{
EFI_STATUS Status ;
FILEPATH_DEVICE_PATH * FilePathNode ;
EFI_HANDLE Handle ;
SHELL_FILE_HANDLE ShellHandle ;
EFI_FILE_PROTOCOL * Handle1 ;
EFI_FILE_PROTOCOL * Handle2 ;
EFI_DEVICE_PATH_PROTOCOL * DpCopy ;
2010-11-16 23:31:47 +01:00
FILEPATH_DEVICE_PATH * AlignedNode ;
2010-09-14 07:18:09 +02:00
2010-11-16 23:31:47 +01:00
if ( FileHandle = = NULL ) {
return ( EFI_INVALID_PARAMETER ) ;
}
* FileHandle = NULL ;
Handle1 = NULL ;
Handle2 = NULL ;
Handle = NULL ;
DpCopy = DevicePath ;
ShellHandle = NULL ;
FilePathNode = NULL ;
AlignedNode = NULL ;
2010-09-14 07:18:09 +02:00
Status = EfiShellOpenRoot ( DevicePath , & ShellHandle ) ;
if ( ! EFI_ERROR ( Status ) ) {
Handle1 = ConvertShellHandleToEfiFileProtocol ( ShellHandle ) ;
2010-12-06 19:10:34 +01:00
if ( Handle1 ! = NULL ) {
2010-09-14 07:18:09 +02:00
//
2010-12-06 19:10:34 +01:00
// chop off the begining part before the file system part...
2010-09-14 07:18:09 +02:00
//
2010-12-06 19:10:34 +01:00
///@todo BlockIo?
Status = gBS - > LocateDevicePath ( & gEfiSimpleFileSystemProtocolGuid ,
& DevicePath ,
& Handle ) ;
if ( ! EFI_ERROR ( Status ) ) {
2010-09-14 07:18:09 +02:00
//
2010-12-06 19:10:34 +01:00
// To access as a file system, the file path should only
// contain file path components. Follow the file path nodes
// and find the target file
2010-09-14 07:18:09 +02:00
//
2010-12-06 19:10:34 +01:00
for ( FilePathNode = ( FILEPATH_DEVICE_PATH * ) DevicePath
; ! IsDevicePathEnd ( & FilePathNode - > Header )
; FilePathNode = ( FILEPATH_DEVICE_PATH * ) NextDevicePathNode ( & FilePathNode - > Header )
) {
SHELL_FREE_NON_NULL ( AlignedNode ) ;
AlignedNode = AllocateCopyPool ( DevicePathNodeLength ( FilePathNode ) , FilePathNode ) ;
2010-09-14 07:18:09 +02:00
//
2010-12-06 19:10:34 +01:00
// For file system access each node should be a file path component
2010-09-14 07:18:09 +02:00
//
2010-12-06 19:10:34 +01:00
if ( DevicePathType ( & FilePathNode - > Header ) ! = MEDIA_DEVICE_PATH | |
DevicePathSubType ( & FilePathNode - > Header ) ! = MEDIA_FILEPATH_DP
) {
Status = EFI_UNSUPPORTED ;
break ;
}
2010-09-14 07:18:09 +02:00
//
2010-12-06 19:10:34 +01:00
// Open this file path node
2010-09-14 07:18:09 +02:00
//
2010-12-06 19:10:34 +01:00
Handle2 = Handle1 ;
Handle1 = NULL ;
2010-09-14 07:18:09 +02:00
//
2010-12-06 19:10:34 +01:00
// if this is the last node in the DevicePath always create (if that was requested).
2010-09-14 07:18:09 +02:00
//
2010-12-06 19:10:34 +01:00
if ( IsDevicePathEnd ( ( NextDevicePathNode ( & FilePathNode - > Header ) ) ) ) {
2010-09-14 07:18:09 +02:00
Status = Handle2 - > Open (
Handle2 ,
& Handle1 ,
2010-11-16 23:31:47 +01:00
AlignedNode - > PathName ,
2010-09-14 07:18:09 +02:00
OpenMode ,
Attributes
) ;
2010-12-06 19:10:34 +01:00
} else {
//
// This is not the last node and we dont want to 'create' existing
// directory entries...
//
//
// open without letting it create
// prevents error on existing files/directories
//
Status = Handle2 - > Open (
Handle2 ,
& Handle1 ,
AlignedNode - > PathName ,
OpenMode & ~ EFI_FILE_MODE_CREATE ,
Attributes
) ;
//
// if above failed now open and create the 'item'
// if OpenMode EFI_FILE_MODE_CREATE bit was on (but disabled above)
//
if ( ( EFI_ERROR ( Status ) ) & & ( ( OpenMode & EFI_FILE_MODE_CREATE ) ! = 0 ) ) {
Status = Handle2 - > Open (
Handle2 ,
& Handle1 ,
AlignedNode - > PathName ,
OpenMode ,
Attributes
) ;
}
2010-09-14 07:18:09 +02:00
}
2010-12-06 19:10:34 +01:00
//
// Close the last node
//
ShellInfoObject . NewEfiShellProtocol - > CloseFile ( Handle2 ) ;
2010-09-14 07:18:09 +02:00
2010-12-06 19:10:34 +01:00
//
// If there's been an error, stop
//
if ( EFI_ERROR ( Status ) ) {
break ;
}
} // for loop
}
2010-09-14 07:18:09 +02:00
}
}
2010-11-16 23:31:47 +01:00
SHELL_FREE_NON_NULL ( AlignedNode ) ;
2010-09-14 07:18:09 +02:00
if ( EFI_ERROR ( Status ) ) {
if ( Handle1 ! = NULL ) {
2010-11-16 23:31:47 +01:00
ShellInfoObject . NewEfiShellProtocol - > CloseFile ( Handle1 ) ;
2010-09-14 07:18:09 +02:00
}
} else {
* FileHandle = ConvertEfiFileProtocolToShellHandle ( Handle1 , ShellFileHandleGetPath ( ShellHandle ) ) ;
}
return ( Status ) ;
}
/**
Creates a file or directory by name .
This function creates an empty new file or directory with the specified attributes and
returns the new file ' s handle . If the file already exists and is read - only , then
EFI_INVALID_PARAMETER will be returned .
If the file already existed , it is truncated and its attributes updated . If the file is
created successfully , the FileHandle is the file ' s handle , else , the FileHandle is NULL .
If the file name begins with > v , then the file handle which is returned refers to the
shell environment variable with the specified name . If the shell environment variable
already exists and is non - volatile then EFI_INVALID_PARAMETER is returned .
@ param FileName Pointer to NULL - terminated file path
@ param FileAttribs The new file ' s attrbiutes . the different attributes are
described in EFI_FILE_PROTOCOL . Open ( ) .
@ param FileHandle On return , points to the created file handle or directory ' s handle
@ retval EFI_SUCCESS The file was opened . FileHandle points to the new file ' s handle .
@ retval EFI_INVALID_PARAMETER One of the parameters has an invalid value .
@ retval EFI_UNSUPPORTED could not open the file path
@ retval EFI_NOT_FOUND the specified file could not be found on the devide , or could not
file the file system on the device .
@ retval EFI_NO_MEDIA the device has no medium .
@ retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no
longer supported .
@ retval EFI_DEVICE_ERROR The device reported an error or can ' t get the file path according
the DirName .
@ retval EFI_VOLUME_CORRUPTED The file system structures are corrupted .
@ retval EFI_WRITE_PROTECTED An attempt was made to create a file , or open a file for write
when the media is write - protected .
@ retval EFI_ACCESS_DENIED The service denied access to the file .
@ retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file .
@ retval EFI_VOLUME_FULL The volume is full .
* */
EFI_STATUS
EFIAPI
EfiShellCreateFile (
IN CONST CHAR16 * FileName ,
IN UINT64 FileAttribs ,
OUT SHELL_FILE_HANDLE * FileHandle
)
{
EFI_DEVICE_PATH_PROTOCOL * DevicePath ;
EFI_STATUS Status ;
//
// Is this for an environment variable
// do we start with >v
//
if ( StrStr ( FileName , L " >v " ) = = FileName ) {
if ( ! IsVolatileEnv ( FileName + 2 ) ) {
return ( EFI_INVALID_PARAMETER ) ;
}
* FileHandle = CreateFileInterfaceEnv ( FileName + 2 ) ;
return ( EFI_SUCCESS ) ;
}
//
// We are opening a regular file.
//
DevicePath = EfiShellGetDevicePathFromFilePath ( FileName ) ;
if ( DevicePath = = NULL ) {
return ( EFI_NOT_FOUND ) ;
}
Status = InternalOpenFileDevicePath ( DevicePath , FileHandle , EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE , FileAttribs ) ; // 0 = no specific file attributes
FreePool ( DevicePath ) ;
return ( Status ) ;
}
/**
Opens a file or a directory by file name .
This function opens the specified file in the specified OpenMode and returns a file
handle .
If the file name begins with > v , then the file handle which is returned refers to the
shell environment variable with the specified name . If the shell environment variable
exists , is non - volatile and the OpenMode indicates EFI_FILE_MODE_WRITE , then
EFI_INVALID_PARAMETER is returned .
If the file name is > i , then the file handle which is returned refers to the standard
input . If the OpenMode indicates EFI_FILE_MODE_WRITE , then EFI_INVALID_PARAMETER
is returned .
If the file name is > o , then the file handle which is returned refers to the standard
output . If the OpenMode indicates EFI_FILE_MODE_READ , then EFI_INVALID_PARAMETER
is returned .
If the file name is > e , then the file handle which is returned refers to the standard
error . If the OpenMode indicates EFI_FILE_MODE_READ , then EFI_INVALID_PARAMETER
is returned .
If the file name is NUL , then the file handle that is returned refers to the standard NUL
file . If the OpenMode indicates EFI_FILE_MODE_READ , then EFI_INVALID_PARAMETER is
returned .
If return EFI_SUCCESS , the FileHandle is the opened file ' s handle , else , the
FileHandle is NULL .
@ param FileName Points to the NULL - terminated UCS - 2 encoded file name .
@ param FileHandle On return , points to the file handle .
@ param OpenMode File open mode . Either EFI_FILE_MODE_READ or
EFI_FILE_MODE_WRITE from section 12.4 of the UEFI
Specification .
@ retval EFI_SUCCESS The file was opened . FileHandle has the opened file ' s handle .
@ retval EFI_INVALID_PARAMETER One of the parameters has an invalid value . FileHandle is NULL .
@ retval EFI_UNSUPPORTED Could not open the file path . FileHandle is NULL .
@ retval EFI_NOT_FOUND The specified file could not be found on the device or the file
system could not be found on the device . FileHandle is NULL .
@ retval EFI_NO_MEDIA The device has no medium . FileHandle is NULL .
@ retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no
longer supported . FileHandle is NULL .
@ retval EFI_DEVICE_ERROR The device reported an error or can ' t get the file path according
the FileName . FileHandle is NULL .
@ retval EFI_VOLUME_CORRUPTED The file system structures are corrupted . FileHandle is NULL .
@ retval EFI_WRITE_PROTECTED An attempt was made to create a file , or open a file for write
when the media is write - protected . FileHandle is NULL .
@ retval EFI_ACCESS_DENIED The service denied access to the file . FileHandle is NULL .
@ retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file . FileHandle
is NULL .
@ retval EFI_VOLUME_FULL The volume is full . FileHandle is NULL .
* */
EFI_STATUS
EFIAPI
EfiShellOpenFileByName (
IN CONST CHAR16 * FileName ,
OUT SHELL_FILE_HANDLE * FileHandle ,
IN UINT64 OpenMode
)
{
EFI_DEVICE_PATH_PROTOCOL * DevicePath ;
EFI_STATUS Status ;
* FileHandle = NULL ;
//
// Is this for StdIn
//
if ( StrCmp ( FileName , L " >i " ) = = 0 ) {
//
// make sure not writing to StdIn
//
if ( ( OpenMode & EFI_FILE_MODE_WRITE ) ! = 0 ) {
return ( EFI_INVALID_PARAMETER ) ;
}
* FileHandle = ShellInfoObject . NewShellParametersProtocol - > StdIn ;
ASSERT ( * FileHandle ! = NULL ) ;
return ( EFI_SUCCESS ) ;
}
//
// Is this for StdOut
//
if ( StrCmp ( FileName , L " >o " ) = = 0 ) {
//
// make sure not writing to StdIn
//
if ( ( OpenMode & EFI_FILE_MODE_READ ) ! = 0 ) {
return ( EFI_INVALID_PARAMETER ) ;
}
* FileHandle = & FileInterfaceStdOut ;
return ( EFI_SUCCESS ) ;
}
//
// Is this for NUL file
//
if ( StrCmp ( FileName , L " NUL " ) = = 0 ) {
* FileHandle = & FileInterfaceNulFile ;
return ( EFI_SUCCESS ) ;
}
//
// Is this for StdErr
//
if ( StrCmp ( FileName , L " >e " ) = = 0 ) {
//
// make sure not writing to StdIn
//
if ( ( OpenMode & EFI_FILE_MODE_READ ) ! = 0 ) {
return ( EFI_INVALID_PARAMETER ) ;
}
* FileHandle = & FileInterfaceStdErr ;
return ( EFI_SUCCESS ) ;
}
//
// Is this for an environment variable
// do we start with >v
//
if ( StrStr ( FileName , L " >v " ) = = FileName ) {
if ( ! IsVolatileEnv ( FileName + 2 ) & &
( ( OpenMode & EFI_FILE_MODE_WRITE ) ! = 0 ) ) {
return ( EFI_INVALID_PARAMETER ) ;
}
* FileHandle = CreateFileInterfaceEnv ( FileName + 2 ) ;
return ( EFI_SUCCESS ) ;
}
//
// We are opening a regular file.
//
DevicePath = EfiShellGetDevicePathFromFilePath ( FileName ) ;
// DEBUG_CODE(InternalShellProtocolDebugPrintMessage (NULL, DevicePath););
if ( DevicePath = = NULL ) {
return ( EFI_NOT_FOUND ) ;
}
//
// Copy the device path, open the file, then free the memory
//
Status = InternalOpenFileDevicePath ( DevicePath , FileHandle , OpenMode , 0 ) ; // 0 = no specific file attributes
FreePool ( DevicePath ) ;
return ( Status ) ;
}
/**
Deletes the file specified by the file name .
This function deletes a file .
@ param FileName Points to the NULL - terminated file name .
@ retval EFI_SUCCESS The file was closed and deleted , and the handle was closed .
@ retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not deleted .
@ sa EfiShellCreateFile
* */
EFI_STATUS
EFIAPI
EfiShellDeleteFileByName (
IN CONST CHAR16 * FileName
)
{
SHELL_FILE_HANDLE FileHandle ;
EFI_STATUS Status ;
//
// get a handle to the file
//
Status = EfiShellCreateFile ( FileName ,
0 ,
& FileHandle ) ;
if ( EFI_ERROR ( Status ) ) {
return ( Status ) ;
}
//
// now delete the file
//
return ( ShellInfoObject . NewEfiShellProtocol - > DeleteFile ( FileHandle ) ) ;
}
/**
Disables the page break output mode .
* */
VOID
EFIAPI
EfiShellDisablePageBreak (
VOID
)
{
ShellInfoObject . PageBreakEnabled = FALSE ;
}
/**
Enables the page break output mode .
* */
VOID
EFIAPI
EfiShellEnablePageBreak (
VOID
)
{
ShellInfoObject . PageBreakEnabled = TRUE ;
}
/**
internal worker function to load and run an image via device path .
@ param ParentImageHandle A handle of the image that is executing the specified
command line .
@ param DevicePath device path of the file to execute
@ param CommandLine Points to the NULL - terminated UCS - 2 encoded string
containing the command line . If NULL then the command -
line will be empty .
@ param Environment Points to a NULL - terminated array of environment
variables with the format ' x = y ' , where x is the
environment variable name and y is the value . If this
is NULL , then the current shell environment is used .
@ param StatusCode Points to the status code returned by the command .
@ retval EFI_SUCCESS The command executed successfully . The status code
returned by the command is pointed to by StatusCode .
@ retval EFI_INVALID_PARAMETER The parameters are invalid .
@ retval EFI_OUT_OF_RESOURCES Out of resources .
@ retval EFI_UNSUPPORTED Nested shell invocations are not allowed .
* */
EFI_STATUS
EFIAPI
InternalShellExecuteDevicePath (
IN CONST EFI_HANDLE * ParentImageHandle ,
IN CONST EFI_DEVICE_PATH_PROTOCOL * DevicePath ,
IN CONST CHAR16 * CommandLine OPTIONAL ,
IN CONST CHAR16 * * Environment OPTIONAL ,
OUT EFI_STATUS * StatusCode OPTIONAL
)
{
EFI_STATUS Status ;
EFI_HANDLE NewHandle ;
EFI_LOADED_IMAGE_PROTOCOL * LoadedImage ;
LIST_ENTRY OrigEnvs ;
EFI_SHELL_PARAMETERS_PROTOCOL ShellParamsProtocol ;
if ( ParentImageHandle = = NULL ) {
return ( EFI_INVALID_PARAMETER ) ;
}
InitializeListHead ( & OrigEnvs ) ;
NewHandle = NULL ;
//
// Load the image with:
// FALSE - not from boot manager and NULL, 0 being not already in memory
//
Status = gBS - > LoadImage (
FALSE ,
* ParentImageHandle ,
( EFI_DEVICE_PATH_PROTOCOL * ) DevicePath ,
NULL ,
0 ,
& NewHandle ) ;
if ( EFI_ERROR ( Status ) ) {
if ( NewHandle ! = NULL ) {
gBS - > UnloadImage ( NewHandle ) ;
}
return ( Status ) ;
}
Status = gBS - > OpenProtocol (
NewHandle ,
& gEfiLoadedImageProtocolGuid ,
( VOID * * ) & LoadedImage ,
gImageHandle ,
NULL ,
EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ;
if ( ! EFI_ERROR ( Status ) ) {
ASSERT ( LoadedImage - > LoadOptionsSize = = 0 ) ;
if ( CommandLine ! = NULL ) {
LoadedImage - > LoadOptionsSize = ( UINT32 ) StrSize ( CommandLine ) ;
LoadedImage - > LoadOptions = ( VOID * ) CommandLine ;
}
//
// Save our current environment settings for later restoration if necessary
//
if ( Environment ! = NULL ) {
Status = GetEnvironmentVariableList ( & OrigEnvs ) ;
if ( ! EFI_ERROR ( Status ) ) {
Status = SetEnvironmentVariables ( Environment ) ;
}
}
//
// Initialize and install a shell parameters protocol on the image.
//
ShellParamsProtocol . StdIn = ShellInfoObject . NewShellParametersProtocol - > StdIn ;
ShellParamsProtocol . StdOut = ShellInfoObject . NewShellParametersProtocol - > StdOut ;
ShellParamsProtocol . StdErr = ShellInfoObject . NewShellParametersProtocol - > StdErr ;
Status = UpdateArgcArgv ( & ShellParamsProtocol , CommandLine , NULL , NULL ) ;
ASSERT_EFI_ERROR ( Status ) ;
Status = gBS - > InstallProtocolInterface ( & NewHandle , & gEfiShellParametersProtocolGuid , EFI_NATIVE_INTERFACE , & ShellParamsProtocol ) ;
ASSERT_EFI_ERROR ( Status ) ;
///@todo initialize and install ShellInterface protocol on the new image for compatibility if - PcdGetBool(PcdShellSupportOldProtocols)
//
// now start the image and if the caller wanted the return code pass it to them...
//
if ( ! EFI_ERROR ( Status ) ) {
if ( StatusCode ! = NULL ) {
* StatusCode = gBS - > StartImage ( NewHandle , NULL , NULL ) ;
} else {
Status = gBS - > StartImage ( NewHandle , NULL , NULL ) ;
}
}
//
// Cleanup (and dont overwrite errors)
//
if ( EFI_ERROR ( Status ) ) {
gBS - > UninstallProtocolInterface ( NewHandle , & gEfiShellParametersProtocolGuid , & ShellParamsProtocol ) ;
} else {
Status = gBS - > UninstallProtocolInterface ( NewHandle , & gEfiShellParametersProtocolGuid , & ShellParamsProtocol ) ;
ASSERT_EFI_ERROR ( Status ) ;
}
}
if ( ! IsListEmpty ( & OrigEnvs ) ) {
if ( EFI_ERROR ( Status ) ) {
SetEnvironmentVariableList ( & OrigEnvs ) ;
} else {
Status = SetEnvironmentVariableList ( & OrigEnvs ) ;
}
}
return ( Status ) ;
}
/**
Execute the 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 .
@ param ParentImageHandle A handle of the image that is executing the specified
command line .
@ param CommandLine Points to the NULL - terminated UCS - 2 encoded string
containing the command line . If NULL then the command -
line will be empty .
@ param Environment Points to a NULL - terminated array of environment
variables with the format ' x = y ' , where x is the
environment variable name and y is the value . If this
is NULL , then the current shell environment is used .
@ param StatusCode Points to the status code returned by the command .
@ retval EFI_SUCCESS The command executed successfully . The status code
returned by the command is pointed to by StatusCode .
@ retval EFI_INVALID_PARAMETER The parameters are invalid .
@ retval EFI_OUT_OF_RESOURCES Out of resources .
@ retval EFI_UNSUPPORTED Nested shell invocations are not allowed .
@ retval EFI_UNSUPPORTED The support level required for this function is not present .
@ sa InternalShellExecuteDevicePath
* */
EFI_STATUS
EFIAPI
EfiShellExecute (
IN EFI_HANDLE * ParentImageHandle ,
IN CHAR16 * CommandLine OPTIONAL ,
IN CHAR16 * * Environment OPTIONAL ,
OUT EFI_STATUS * StatusCode OPTIONAL
)
{
EFI_STATUS Status ;
CHAR16 * Temp ;
EFI_DEVICE_PATH_PROTOCOL * DevPath ;
UINTN Size ;
if ( ( PcdGet8 ( PcdShellSupportLevel ) < 1 ) ) {
return ( EFI_UNSUPPORTED ) ;
}
DevPath = AppendDevicePath ( ShellInfoObject . ImageDevPath , ShellInfoObject . FileDevPath ) ;
DEBUG_CODE_BEGIN ( ) ;
Temp = gDevPathToText - > ConvertDevicePathToText ( ShellInfoObject . FileDevPath , TRUE , TRUE ) ;
FreePool ( Temp ) ;
Temp = gDevPathToText - > ConvertDevicePathToText ( ShellInfoObject . ImageDevPath , TRUE , TRUE ) ;
FreePool ( Temp ) ;
Temp = gDevPathToText - > ConvertDevicePathToText ( DevPath , TRUE , TRUE ) ;
FreePool ( Temp ) ;
DEBUG_CODE_END ( ) ;
Temp = NULL ;
Size = 0 ;
ASSERT ( ( Temp = = NULL & & Size = = 0 ) | | ( Temp ! = NULL ) ) ;
StrnCatGrow ( & Temp , & Size , L " Shell.efi " , 0 ) ;
StrnCatGrow ( & Temp , & Size , CommandLine , 0 ) ;
Status = InternalShellExecuteDevicePath (
ParentImageHandle ,
DevPath ,
Temp ,
( CONST CHAR16 * * ) Environment ,
StatusCode ) ;
//
// de-allocate and return
//
FreePool ( DevPath ) ;
FreePool ( Temp ) ;
return ( Status ) ;
}
/**
Utility cleanup function for EFI_SHELL_FILE_INFO objects .
1 ) frees all pointers ( non - NULL )
2 ) Closes the SHELL_FILE_HANDLE
@ param FileListNode pointer to the list node to free
* */
VOID
EFIAPI
InternalFreeShellFileInfoNode (
IN EFI_SHELL_FILE_INFO * FileListNode
)
{
if ( FileListNode - > Info ! = NULL ) {
FreePool ( ( VOID * ) FileListNode - > Info ) ;
}
if ( FileListNode - > FileName ! = NULL ) {
FreePool ( ( VOID * ) FileListNode - > FileName ) ;
}
if ( FileListNode - > FullName ! = NULL ) {
FreePool ( ( VOID * ) FileListNode - > FullName ) ;
}
if ( FileListNode - > Handle ! = NULL ) {
ShellInfoObject . NewEfiShellProtocol - > CloseFile ( FileListNode - > Handle ) ;
}
FreePool ( FileListNode ) ;
}
/**
Frees the file list .
This function cleans up the file list and any related data structures . It has no
impact on the files themselves .
@ param FileList The file list to free . Type EFI_SHELL_FILE_INFO is
defined in OpenFileList ( )
@ retval EFI_SUCCESS Free the file list successfully .
@ retval EFI_INVALID_PARAMETER FileList was NULL or * FileList was NULL ;
* */
EFI_STATUS
EFIAPI
EfiShellFreeFileList (
IN EFI_SHELL_FILE_INFO * * FileList
)
{
EFI_SHELL_FILE_INFO * ShellFileListItem ;
if ( FileList = = NULL | | * FileList = = NULL ) {
return ( EFI_INVALID_PARAMETER ) ;
}
for ( ShellFileListItem = ( EFI_SHELL_FILE_INFO * ) GetFirstNode ( & ( * FileList ) - > Link )
; ! IsListEmpty ( & ( * FileList ) - > Link )
; ShellFileListItem = ( EFI_SHELL_FILE_INFO * ) GetFirstNode ( & ( * FileList ) - > Link )
) {
RemoveEntryList ( & ShellFileListItem - > Link ) ;
InternalFreeShellFileInfoNode ( ShellFileListItem ) ;
}
return ( EFI_SUCCESS ) ;
}
/**
Deletes the duplicate file names files in the given file list .
This function deletes the reduplicate files in the given file list .
@ param FileList A pointer to the first entry in the file list .
@ retval EFI_SUCCESS Always success .
@ retval EFI_INVALID_PARAMETER FileList was NULL or * FileList was NULL ;
* */
EFI_STATUS
EFIAPI
EfiShellRemoveDupInFileList (
IN EFI_SHELL_FILE_INFO * * FileList
)
{
EFI_SHELL_FILE_INFO * ShellFileListItem ;
EFI_SHELL_FILE_INFO * ShellFileListItem2 ;
if ( FileList = = NULL | | * FileList = = NULL ) {
return ( EFI_INVALID_PARAMETER ) ;
}
for ( ShellFileListItem = ( EFI_SHELL_FILE_INFO * ) GetFirstNode ( & ( * FileList ) - > Link )
; ! IsNull ( & ( * FileList ) - > Link , & ShellFileListItem - > Link )
; ShellFileListItem = ( EFI_SHELL_FILE_INFO * ) GetNextNode ( & ( * FileList ) - > Link , & ShellFileListItem - > Link )
) {
for ( ShellFileListItem2 = ( EFI_SHELL_FILE_INFO * ) GetNextNode ( & ( * FileList ) - > Link , & ShellFileListItem - > Link )
; ! IsNull ( & ( * FileList ) - > Link , & ShellFileListItem2 - > Link )
; ShellFileListItem2 = ( EFI_SHELL_FILE_INFO * ) GetNextNode ( & ( * FileList ) - > Link , & ShellFileListItem2 - > Link )
) {
if ( gUnicodeCollation - > StriColl (
gUnicodeCollation ,
( CHAR16 * ) ShellFileListItem - > FullName ,
( CHAR16 * ) ShellFileListItem2 - > FullName ) = = 0
) {
RemoveEntryList ( & ShellFileListItem2 - > Link ) ;
InternalFreeShellFileInfoNode ( ShellFileListItem2 ) ;
}
}
}
return ( EFI_SUCCESS ) ;
}
/**
Allocates and duplicates a EFI_SHELL_FILE_INFO node .
@ param [ in ] Node The node to copy from .
@ param [ in ] Save TRUE to set Node - > Handle to NULL , FALSE otherwise .
@ retval NULL a memory allocation error ocurred
@ return ! = NULL a pointer to the new node
* */
EFI_SHELL_FILE_INFO *
EFIAPI
InternalDuplicateShellFileInfo (
IN EFI_SHELL_FILE_INFO * Node ,
IN BOOLEAN Save
)
{
EFI_SHELL_FILE_INFO * NewNode ;
2011-03-25 23:23:05 +01:00
NewNode = AllocateZeroPool ( sizeof ( EFI_SHELL_FILE_INFO ) ) ;
2010-09-14 07:18:09 +02:00
if ( NewNode = = NULL ) {
return ( NULL ) ;
}
NewNode - > FullName = AllocateZeroPool ( StrSize ( Node - > FullName ) ) ;
NewNode - > FileName = AllocateZeroPool ( StrSize ( Node - > FileName ) ) ;
2011-03-25 23:23:05 +01:00
NewNode - > Info = AllocateZeroPool ( ( UINTN ) Node - > Info - > Size ) ;
2010-09-14 07:18:09 +02:00
if ( NewNode - > FullName = = NULL
| | NewNode - > FileName = = NULL
| | NewNode - > Info = = NULL
) {
return ( NULL ) ;
}
NewNode - > Status = Node - > Status ;
NewNode - > Handle = Node - > Handle ;
if ( ! Save ) {
Node - > Handle = NULL ;
}
StrCpy ( ( CHAR16 * ) NewNode - > FullName , Node - > FullName ) ;
StrCpy ( ( CHAR16 * ) NewNode - > FileName , Node - > FileName ) ;
CopyMem ( NewNode - > Info , Node - > Info , ( UINTN ) Node - > Info - > Size ) ;
return ( NewNode ) ;
}
/**
Allocates and populates a EFI_SHELL_FILE_INFO structure . if any memory operation
failed it will return NULL .
@ param [ in ] BasePath the Path to prepend onto filename for FullPath
@ param [ in ] Status Status member initial value .
@ param [ in ] FullName FullName member initial value .
@ param [ in ] FileName FileName member initial value .
@ param [ in ] Handle Handle member initial value .
@ param [ in ] Info Info struct to copy .
@ retval NULL An error ocurred .
@ return a pointer to the newly allocated structure .
* */
EFI_SHELL_FILE_INFO *
EFIAPI
CreateAndPopulateShellFileInfo (
IN CONST CHAR16 * BasePath ,
IN CONST EFI_STATUS Status ,
IN CONST CHAR16 * FullName ,
IN CONST CHAR16 * FileName ,
IN CONST SHELL_FILE_HANDLE Handle ,
IN CONST EFI_FILE_INFO * Info
)
{
EFI_SHELL_FILE_INFO * ShellFileListItem ;
CHAR16 * TempString ;
UINTN Size ;
TempString = NULL ;
Size = 0 ;
ShellFileListItem = AllocateZeroPool ( sizeof ( EFI_SHELL_FILE_INFO ) ) ;
if ( ShellFileListItem = = NULL ) {
return ( NULL ) ;
}
if ( Info ! = NULL ) {
ShellFileListItem - > Info = AllocateZeroPool ( ( UINTN ) Info - > Size ) ;
if ( ShellFileListItem - > Info = = NULL ) {
FreePool ( ShellFileListItem ) ;
return ( NULL ) ;
}
CopyMem ( ShellFileListItem - > Info , Info , ( UINTN ) Info - > Size ) ;
} else {
ShellFileListItem - > Info = NULL ;
}
if ( FileName ! = NULL ) {
ASSERT ( TempString = = NULL ) ;
ShellFileListItem - > FileName = StrnCatGrow ( & TempString , 0 , FileName , 0 ) ;
if ( ShellFileListItem - > FileName = = NULL ) {
FreePool ( ShellFileListItem - > Info ) ;
FreePool ( ShellFileListItem ) ;
return ( NULL ) ;
}
} else {
ShellFileListItem - > FileName = NULL ;
}
Size = 0 ;
TempString = NULL ;
if ( BasePath ! = NULL ) {
ASSERT ( ( TempString = = NULL & & Size = = 0 ) | | ( TempString ! = NULL ) ) ;
TempString = StrnCatGrow ( & TempString , & Size , BasePath , 0 ) ;
if ( TempString = = NULL ) {
FreePool ( ( VOID * ) ShellFileListItem - > FileName ) ;
FreePool ( ShellFileListItem - > Info ) ;
FreePool ( ShellFileListItem ) ;
return ( NULL ) ;
}
}
if ( ShellFileListItem - > FileName ! = NULL ) {
ASSERT ( ( TempString = = NULL & & Size = = 0 ) | | ( TempString ! = NULL ) ) ;
TempString = StrnCatGrow ( & TempString , & Size , ShellFileListItem - > FileName , 0 ) ;
if ( TempString = = NULL ) {
FreePool ( ( VOID * ) ShellFileListItem - > FileName ) ;
FreePool ( ShellFileListItem - > Info ) ;
FreePool ( ShellFileListItem ) ;
return ( NULL ) ;
}
}
ShellFileListItem - > FullName = TempString ;
ShellFileListItem - > Status = Status ;
ShellFileListItem - > Handle = Handle ;
return ( ShellFileListItem ) ;
}
/**
Find all files in a specified directory .
@ param FileDirHandle Handle of the directory to search .
@ param FileList On return , points to the list of files in the directory
or NULL if there are no files in the directory .
@ retval EFI_SUCCESS File information was returned successfully .
@ retval EFI_VOLUME_CORRUPTED The file system structures have been corrupted .
@ retval EFI_DEVICE_ERROR The device reported an error .
@ retval EFI_NO_MEDIA The device media is not present .
@ retval EFI_INVALID_PARAMETER The FileDirHandle was not a directory .
@ return An error from FileHandleGetFileName ( ) .
* */
EFI_STATUS
EFIAPI
EfiShellFindFilesInDir (
IN SHELL_FILE_HANDLE FileDirHandle ,
OUT EFI_SHELL_FILE_INFO * * FileList
)
{
EFI_SHELL_FILE_INFO * ShellFileList ;
EFI_SHELL_FILE_INFO * ShellFileListItem ;
EFI_FILE_INFO * FileInfo ;
EFI_STATUS Status ;
BOOLEAN NoFile ;
CHAR16 * TempString ;
CHAR16 * BasePath ;
UINTN Size ;
CHAR16 * TempSpot ;
Status = FileHandleGetFileName ( FileDirHandle , & BasePath ) ;
if ( EFI_ERROR ( Status ) ) {
return ( Status ) ;
}
if ( ShellFileHandleGetPath ( FileDirHandle ) ! = NULL ) {
TempString = NULL ;
Size = 0 ;
TempString = StrnCatGrow ( & TempString , & Size , ShellFileHandleGetPath ( FileDirHandle ) , 0 ) ;
TempSpot = StrStr ( TempString , L " ; " ) ;
if ( TempSpot ! = NULL ) {
* TempSpot = CHAR_NULL ;
}
TempString = StrnCatGrow ( & TempString , & Size , BasePath , 0 ) ;
BasePath = TempString ;
}
NoFile = FALSE ;
ShellFileList = NULL ;
ShellFileListItem = NULL ;
FileInfo = NULL ;
Status = EFI_SUCCESS ;
for ( Status = FileHandleFindFirstFile ( FileDirHandle , & FileInfo )
; ! EFI_ERROR ( Status ) & & ! NoFile
; Status = FileHandleFindNextFile ( FileDirHandle , FileInfo , & NoFile )
) {
TempString = NULL ;
Size = 0 ;
//
// allocate a new EFI_SHELL_FILE_INFO and populate it...
//
ASSERT ( ( TempString = = NULL & & Size = = 0 ) | | ( TempString ! = NULL ) ) ;
TempString = StrnCatGrow ( & TempString , & Size , BasePath , 0 ) ;
TempString = StrnCatGrow ( & TempString , & Size , FileInfo - > FileName , 0 ) ;
ShellFileListItem = CreateAndPopulateShellFileInfo (
BasePath ,
EFI_SUCCESS , // success since we didnt fail to open it...
TempString ,
FileInfo - > FileName ,
NULL , // no handle since not open
FileInfo ) ;
if ( ShellFileList = = NULL ) {
ShellFileList = ( EFI_SHELL_FILE_INFO * ) AllocateZeroPool ( sizeof ( EFI_SHELL_FILE_INFO ) ) ;
ASSERT ( ShellFileList ! = NULL ) ;
InitializeListHead ( & ShellFileList - > Link ) ;
}
InsertTailList ( & ShellFileList - > Link , & ShellFileListItem - > Link ) ;
}
if ( EFI_ERROR ( Status ) ) {
EfiShellFreeFileList ( & ShellFileList ) ;
* FileList = NULL ;
} else {
* FileList = ShellFileList ;
}
SHELL_FREE_NON_NULL ( BasePath ) ;
return ( Status ) ;
}
/**
Updates a file name to be preceeded by the mapped drive name
@ param [ in ] BasePath the Mapped drive name to prepend
@ param [ in , out ] Path pointer to pointer to the file name to update .
@ retval EFI_SUCCESS
@ retval EFI_OUT_OF_RESOURCES
* */
EFI_STATUS
EFIAPI
UpdateFileName (
IN CONST CHAR16 * BasePath ,
IN OUT CHAR16 * * Path
)
{
CHAR16 * Path2 ;
UINTN Path2Size ;
Path2Size = 0 ;
Path2 = NULL ;
ASSERT ( Path ! = NULL ) ;
ASSERT ( * Path ! = NULL ) ;
ASSERT ( BasePath ! = NULL ) ;
//
// convert a local path to an absolute path
//
if ( StrStr ( * Path , L " : " ) = = NULL ) {
ASSERT ( ( Path2 = = NULL & & Path2Size = = 0 ) | | ( Path2 ! = NULL ) ) ;
StrnCatGrow ( & Path2 , & Path2Size , BasePath , 0 ) ;
if ( Path2 = = NULL ) {
return ( EFI_OUT_OF_RESOURCES ) ;
}
ASSERT ( ( Path2 = = NULL & & Path2Size = = 0 ) | | ( Path2 ! = NULL ) ) ;
StrnCatGrow ( & Path2 , & Path2Size , ( * Path ) [ 0 ] = = L ' \\ ' ? ( * Path ) + 1 : * Path , 0 ) ;
if ( Path2 = = NULL ) {
return ( EFI_OUT_OF_RESOURCES ) ;
}
}
FreePool ( * Path ) ;
( * Path ) = Path2 ;
return ( EFI_SUCCESS ) ;
}
/**
If FileHandle is a directory then the function reads from FileHandle and reads in
each of the FileInfo structures . If one of them matches the Pattern ' s first
" level " then it opens that handle and calls itself on that handle .
If FileHandle is a file and matches all of the remaining Pattern ( which would be
on its last node ) , then add a EFI_SHELL_FILE_INFO object for this file to fileList .
Upon a EFI_SUCCESS return fromt he function any the caller is responsible to call
FreeFileList with FileList .
@ param [ in ] FilePattern The FilePattern to check against .
@ param [ in ] UnicodeCollation The pointer to EFI_UNICODE_COLLATION_PROTOCOL structure
@ param [ in ] FileHandle The FileHandle to start with
@ param [ in , out ] FileList pointer to pointer to list of found files .
@ param [ in ] ParentNode The node for the parent . Same file as identified by HANDLE .
2010-11-16 23:31:47 +01:00
@ param [ in ] MapName The file system name this file is on .
2010-09-14 07:18:09 +02:00
@ retval EFI_SUCCESS all files were found and the FileList contains a list .
@ retval EFI_NOT_FOUND no files were found
@ retval EFI_OUT_OF_RESOURCES a memory allocation failed
* */
EFI_STATUS
EFIAPI
ShellSearchHandle (
IN CONST CHAR16 * FilePattern ,
IN EFI_UNICODE_COLLATION_PROTOCOL * UnicodeCollation ,
IN SHELL_FILE_HANDLE FileHandle ,
IN OUT EFI_SHELL_FILE_INFO * * FileList ,
2010-11-16 23:31:47 +01:00
IN CONST EFI_SHELL_FILE_INFO * ParentNode OPTIONAL ,
IN CONST CHAR16 * MapName
2010-09-14 07:18:09 +02:00
)
{
EFI_STATUS Status ;
CONST CHAR16 * NextFilePatternStart ;
CHAR16 * CurrentFilePattern ;
EFI_SHELL_FILE_INFO * ShellInfo ;
EFI_SHELL_FILE_INFO * ShellInfoNode ;
EFI_SHELL_FILE_INFO * NewShellNode ;
BOOLEAN Directory ;
2010-11-16 23:31:47 +01:00
CHAR16 * NewFullName ;
UINTN Size ;
2010-09-14 07:18:09 +02:00
if ( FilePattern = = NULL
| | UnicodeCollation = = NULL
| | FileList = = NULL
) {
return ( EFI_INVALID_PARAMETER ) ;
}
ShellInfo = NULL ;
CurrentFilePattern = NULL ;
if ( * FilePattern = = L ' \\ ' ) {
FilePattern + + ;
}
for ( NextFilePatternStart = FilePattern
; * NextFilePatternStart ! = CHAR_NULL & & * NextFilePatternStart ! = L ' \\ '
; NextFilePatternStart + + ) ;
CurrentFilePattern = AllocateZeroPool ( ( NextFilePatternStart - FilePattern + 1 ) * sizeof ( CHAR16 ) ) ;
ASSERT ( CurrentFilePattern ! = NULL ) ;
StrnCpy ( CurrentFilePattern , FilePattern , NextFilePatternStart - FilePattern ) ;
if ( CurrentFilePattern [ 0 ] = = CHAR_NULL
& & NextFilePatternStart [ 0 ] = = CHAR_NULL
) {
//
// Add the current parameter FileHandle to the list, then end...
//
if ( ParentNode = = NULL ) {
Status = EFI_INVALID_PARAMETER ;
} else {
NewShellNode = InternalDuplicateShellFileInfo ( ( EFI_SHELL_FILE_INFO * ) ParentNode , TRUE ) ;
if ( NewShellNode = = NULL ) {
Status = EFI_OUT_OF_RESOURCES ;
} else {
NewShellNode - > Handle = NULL ;
if ( * FileList = = NULL ) {
2011-03-25 23:23:05 +01:00
* FileList = AllocateZeroPool ( sizeof ( EFI_SHELL_FILE_INFO ) ) ;
2010-09-14 07:18:09 +02:00
InitializeListHead ( & ( ( * FileList ) - > Link ) ) ;
}
//
// Add to the returning to use list
//
InsertTailList ( & ( * FileList ) - > Link , & NewShellNode - > Link ) ;
Status = EFI_SUCCESS ;
}
}
} else {
Status = EfiShellFindFilesInDir ( FileHandle , & ShellInfo ) ;
if ( ! EFI_ERROR ( Status ) ) {
if ( StrStr ( NextFilePatternStart , L " \\ " ) ! = NULL ) {
Directory = TRUE ;
} else {
Directory = FALSE ;
}
for ( ShellInfoNode = ( EFI_SHELL_FILE_INFO * ) GetFirstNode ( & ShellInfo - > Link )
; ! IsNull ( & ShellInfo - > Link , & ShellInfoNode - > Link )
; ShellInfoNode = ( EFI_SHELL_FILE_INFO * ) GetNextNode ( & ShellInfo - > Link , & ShellInfoNode - > Link )
) {
if ( UnicodeCollation - > MetaiMatch ( UnicodeCollation , ( CHAR16 * ) ShellInfoNode - > FileName , CurrentFilePattern ) ) {
2010-11-16 23:31:47 +01:00
if ( ShellInfoNode - > FullName ! = NULL & & StrStr ( ShellInfoNode - > FullName , L " : " ) = = NULL ) {
Size = StrSize ( ShellInfoNode - > FullName ) ;
Size + = StrSize ( MapName ) + sizeof ( CHAR16 ) ;
NewFullName = AllocateZeroPool ( Size ) ;
if ( NewFullName = = NULL ) {
Status = EFI_OUT_OF_RESOURCES ;
} else {
StrCpy ( NewFullName , MapName ) ;
StrCat ( NewFullName , ShellInfoNode - > FullName + 1 ) ;
FreePool ( ( VOID * ) ShellInfoNode - > FullName ) ;
ShellInfoNode - > FullName = NewFullName ;
}
}
2010-12-06 19:10:34 +01:00
if ( Directory & & ! EFI_ERROR ( Status ) & & ShellInfoNode - > FullName ! = NULL & & ShellInfoNode - > FileName ! = NULL ) {
2010-09-14 07:18:09 +02:00
//
// should be a directory
//
//
// don't open the . and .. directories
//
if ( ( StrCmp ( ShellInfoNode - > FileName , L " . " ) ! = 0 )
& & ( StrCmp ( ShellInfoNode - > FileName , L " .. " ) ! = 0 )
) {
//
//
//
if ( EFI_ERROR ( Status ) ) {
break ;
}
//
// Open the directory since we need that handle in the next recursion.
//
ShellInfoNode - > Status = EfiShellOpenFileByName ( ShellInfoNode - > FullName , & ShellInfoNode - > Handle , EFI_FILE_MODE_READ ) ;
//
// recurse with the next part of the pattern
//
2010-11-16 23:31:47 +01:00
Status = ShellSearchHandle ( NextFilePatternStart , UnicodeCollation , ShellInfoNode - > Handle , FileList , ShellInfoNode , MapName ) ;
2010-09-14 07:18:09 +02:00
}
2010-11-16 23:31:47 +01:00
} else if ( ! EFI_ERROR ( Status ) ) {
2010-09-14 07:18:09 +02:00
//
// should be a file
//
//
// copy the information we need into a new Node
//
NewShellNode = InternalDuplicateShellFileInfo ( ShellInfoNode , FALSE ) ;
ASSERT ( NewShellNode ! = NULL ) ;
if ( NewShellNode = = NULL ) {
Status = EFI_OUT_OF_RESOURCES ;
}
if ( * FileList = = NULL ) {
2011-03-25 23:23:05 +01:00
* FileList = AllocateZeroPool ( sizeof ( EFI_SHELL_FILE_INFO ) ) ;
2010-09-14 07:18:09 +02:00
InitializeListHead ( & ( ( * FileList ) - > Link ) ) ;
}
//
// Add to the returning to use list
//
InsertTailList ( & ( * FileList ) - > Link , & NewShellNode - > Link ) ;
}
}
if ( EFI_ERROR ( Status ) ) {
break ;
}
}
if ( EFI_ERROR ( Status ) ) {
EfiShellFreeFileList ( & ShellInfo ) ;
} else {
Status = EfiShellFreeFileList ( & ShellInfo ) ;
}
}
}
FreePool ( CurrentFilePattern ) ;
return ( Status ) ;
}
/**
Find files that match a specified pattern .
This function searches for all files and directories that match the specified
FilePattern . The FilePattern can contain wild - card characters . The resulting file
information is placed in the file list FileList .
Wildcards are processed
according to the rules specified in UEFI Shell 2.0 spec section 3.7 .1 .
The files in the file list are not opened . The OpenMode field is set to 0 and the FileInfo
field is set to NULL .
if * FileList is not NULL then it must be a pre - existing and properly initialized list .
@ param FilePattern Points to a NULL - terminated shell file path , including wildcards .
@ param FileList On return , points to the start of a file list containing the names
of all matching files or else points to NULL if no matching files
were found . only on a EFI_SUCCESS return will ; this be non - NULL .
@ retval EFI_SUCCESS Files found . FileList is a valid list .
@ retval EFI_NOT_FOUND No files found .
@ retval EFI_NO_MEDIA The device has no media
@ retval EFI_DEVICE_ERROR The device reported an error
@ retval EFI_VOLUME_CORRUPTED The file system structures are corrupted
* */
EFI_STATUS
EFIAPI
EfiShellFindFiles (
IN CONST CHAR16 * FilePattern ,
OUT EFI_SHELL_FILE_INFO * * FileList
)
{
EFI_STATUS Status ;
CHAR16 * PatternCopy ;
CHAR16 * PatternCurrentLocation ;
EFI_DEVICE_PATH_PROTOCOL * RootDevicePath ;
SHELL_FILE_HANDLE RootFileHandle ;
CHAR16 * MapName ;
UINTN Count ;
if ( FilePattern = = NULL
| | FileList = = NULL
| | StrStr ( FilePattern , L " : " ) = = NULL
) {
return ( EFI_INVALID_PARAMETER ) ;
}
Status = EFI_SUCCESS ;
RootDevicePath = NULL ;
RootFileHandle = NULL ;
MapName = NULL ;
2011-03-25 23:23:05 +01:00
PatternCopy = AllocateZeroPool ( StrSize ( FilePattern ) ) ;
2010-09-14 07:18:09 +02:00
if ( PatternCopy = = NULL ) {
return ( EFI_OUT_OF_RESOURCES ) ;
}
StrCpy ( PatternCopy , FilePattern ) ;
PatternCopy = CleanPath ( PatternCopy ) ;
Count = StrStr ( PatternCopy , L " : " ) - PatternCopy ;
Count + = 2 ;
ASSERT ( MapName = = NULL ) ;
MapName = StrnCatGrow ( & MapName , NULL , PatternCopy , Count ) ;
if ( ! EFI_ERROR ( Status ) ) {
RootDevicePath = EfiShellGetDevicePathFromFilePath ( PatternCopy ) ;
if ( RootDevicePath = = NULL ) {
Status = EFI_INVALID_PARAMETER ;
} else {
Status = EfiShellOpenRoot ( RootDevicePath , & RootFileHandle ) ;
if ( ! EFI_ERROR ( Status ) ) {
for ( PatternCurrentLocation = PatternCopy
; * PatternCurrentLocation ! = ' : '
; PatternCurrentLocation + + ) ;
PatternCurrentLocation + + ;
2010-11-16 23:31:47 +01:00
Status = ShellSearchHandle ( PatternCurrentLocation , gUnicodeCollation , RootFileHandle , FileList , NULL , MapName ) ;
2010-09-14 07:18:09 +02:00
}
FreePool ( RootDevicePath ) ;
}
}
2010-11-16 23:31:47 +01:00
SHELL_FREE_NON_NULL ( PatternCopy ) ;
SHELL_FREE_NON_NULL ( MapName ) ;
2010-09-14 07:18:09 +02:00
return ( Status ) ;
}
/**
Opens the files that match the path specified .
This function opens all of the files specified by Path . Wildcards are processed
according to the rules specified in UEFI Shell 2.0 spec section 3.7 .1 . Each
matching file has an EFI_SHELL_FILE_INFO structure created in a linked list .
@ param Path A pointer to the path string .
@ param OpenMode Specifies the mode used to open each file , EFI_FILE_MODE_READ or
EFI_FILE_MODE_WRITE .
@ param FileList Points to the start of a list of files opened .
@ retval EFI_SUCCESS Create the file list successfully .
@ return Others Can ' t create the file list .
* */
EFI_STATUS
EFIAPI
EfiShellOpenFileList (
IN CHAR16 * Path ,
IN UINT64 OpenMode ,
IN OUT EFI_SHELL_FILE_INFO * * FileList
)
{
EFI_STATUS Status ;
EFI_SHELL_FILE_INFO * ShellFileListItem ;
CHAR16 * Path2 ;
UINTN Path2Size ;
CONST CHAR16 * CurDir ;
2011-03-25 23:23:05 +01:00
BOOLEAN Found ;
2010-09-14 07:18:09 +02:00
ShellCommandCleanPath ( Path ) ;
Path2Size = 0 ;
Path2 = NULL ;
2011-03-25 23:23:05 +01:00
if ( FileList = = NULL | | * FileList = = NULL ) {
return ( EFI_INVALID_PARAMETER ) ;
}
2010-09-14 07:18:09 +02:00
if ( * Path = = L ' . ' & & * ( Path + 1 ) = = L ' \\ ' ) {
2011-03-25 23:23:05 +01:00
Path + = 2 ;
2010-09-14 07:18:09 +02:00
}
//
// convert a local path to an absolute path
//
if ( StrStr ( Path , L " : " ) = = NULL ) {
CurDir = EfiShellGetCurDir ( NULL ) ;
ASSERT ( ( Path2 = = NULL & & Path2Size = = 0 ) | | ( Path2 ! = NULL ) ) ;
StrnCatGrow ( & Path2 , & Path2Size , CurDir , 0 ) ;
if ( * Path = = L ' \\ ' ) {
Path + + ;
2011-03-25 23:23:05 +01:00
while ( ChopLastSlash ( Path2 ) ) ;
2010-09-14 07:18:09 +02:00
}
ASSERT ( ( Path2 = = NULL & & Path2Size = = 0 ) | | ( Path2 ! = NULL ) ) ;
StrnCatGrow ( & Path2 , & Path2Size , Path , 0 ) ;
} else {
ASSERT ( Path2 = = NULL ) ;
StrnCatGrow ( & Path2 , NULL , Path , 0 ) ;
}
CleanPath ( Path2 ) ;
//
// do the search
//
Status = EfiShellFindFiles ( Path2 , FileList ) ;
FreePool ( Path2 ) ;
if ( EFI_ERROR ( Status ) ) {
return ( Status ) ;
}
2011-03-25 23:23:05 +01:00
Found = FALSE ;
2010-09-14 07:18:09 +02:00
//
// We had no errors so open all the files (that are not already opened...)
//
for ( ShellFileListItem = ( EFI_SHELL_FILE_INFO * ) GetFirstNode ( & ( * FileList ) - > Link )
; ! IsNull ( & ( * FileList ) - > Link , & ShellFileListItem - > Link )
; ShellFileListItem = ( EFI_SHELL_FILE_INFO * ) GetNextNode ( & ( * FileList ) - > Link , & ShellFileListItem - > Link )
) {
if ( ShellFileListItem - > Status = = 0 & & ShellFileListItem - > Handle = = NULL ) {
ShellFileListItem - > Status = EfiShellOpenFileByName ( ShellFileListItem - > FullName , & ShellFileListItem - > Handle , OpenMode ) ;
2011-03-25 23:23:05 +01:00
Found = TRUE ;
2010-09-14 07:18:09 +02:00
}
}
2011-03-25 23:23:05 +01:00
if ( ! Found ) {
return ( EFI_NOT_FOUND ) ;
}
2010-09-14 07:18:09 +02:00
return ( EFI_SUCCESS ) ;
}
/**
This function updated with errata .
Gets either a single or list of environment variables .
If name is not NULL then this function returns the current value of the specified
environment variable .
If Name is NULL , then a list of all environment variable names is returned . Each is a
NULL terminated string with a double NULL terminating the list .
@ param Name A pointer to the environment variable name . If
Name is NULL , then the function will return all
of the defined shell environment variables . In
the case where multiple environment variables are
being returned , each variable will be terminated by
a NULL , and the list will be terminated by a double
NULL .
@ return ! = NULL A pointer to the returned string .
The returned pointer does not need to be freed by the caller .
@ retval NULL The environment variable doesn ' t exist or there are
no environment variables .
* */
CONST CHAR16 *
EFIAPI
EfiShellGetEnv (
IN CONST CHAR16 * Name
)
{
EFI_STATUS Status ;
VOID * Buffer ;
UINTN Size ;
LIST_ENTRY List ;
ENV_VAR_LIST * Node ;
CHAR16 * CurrentWriteLocation ;
Size = 0 ;
Buffer = NULL ;
if ( Name = = NULL ) {
//
// Get all our environment variables
//
InitializeListHead ( & List ) ;
Status = GetEnvironmentVariableList ( & List ) ;
if ( EFI_ERROR ( Status ) ) {
return ( NULL ) ;
}
//
// Build the semi-colon delimited list. (2 passes)
//
for ( Node = ( ENV_VAR_LIST * ) GetFirstNode ( & List )
; ! IsNull ( & List , & Node - > Link )
; Node = ( ENV_VAR_LIST * ) GetNextNode ( & List , & Node - > Link )
) {
ASSERT ( Node - > Key ! = NULL ) ;
Size + = StrSize ( Node - > Key ) ;
}
Size + = 2 * sizeof ( CHAR16 ) ;
Buffer = AllocateZeroPool ( Size ) ;
2010-10-04 18:24:30 +02:00
if ( Buffer = = NULL ) {
if ( ! IsListEmpty ( & List ) ) {
FreeEnvironmentVariableList ( & List ) ;
}
return ( NULL ) ;
}
2010-09-14 07:18:09 +02:00
CurrentWriteLocation = ( CHAR16 * ) Buffer ;
for ( Node = ( ENV_VAR_LIST * ) GetFirstNode ( & List )
; ! IsNull ( & List , & Node - > Link )
; Node = ( ENV_VAR_LIST * ) GetNextNode ( & List , & Node - > Link )
) {
ASSERT ( Node - > Key ! = NULL ) ;
StrCpy ( CurrentWriteLocation , Node - > Key ) ;
CurrentWriteLocation + = StrLen ( CurrentWriteLocation ) + 1 ;
}
//
// Free the list...
//
2010-10-04 18:24:30 +02:00
if ( ! IsListEmpty ( & List ) ) {
FreeEnvironmentVariableList ( & List ) ;
}
2010-09-14 07:18:09 +02:00
} else {
//
// We are doing a specific environment variable
//
//
// get the size we need for this EnvVariable
//
Status = SHELL_GET_ENVIRONMENT_VARIABLE ( Name , & Size , Buffer ) ;
if ( Status = = EFI_BUFFER_TOO_SMALL ) {
//
// Allocate the space and recall the get function
//
Buffer = AllocateZeroPool ( Size ) ;
ASSERT ( Buffer ! = NULL ) ;
Status = SHELL_GET_ENVIRONMENT_VARIABLE ( Name , & Size , Buffer ) ;
}
//
// we didnt get it (might not exist)
// free the memory if we allocated any and return NULL
//
if ( EFI_ERROR ( Status ) ) {
if ( Buffer ! = NULL ) {
FreePool ( Buffer ) ;
}
return ( NULL ) ;
}
}
//
// return the buffer
//
return ( AddBufferToFreeList ( Buffer ) ) ;
}
/**
Internal variable setting function . Allows for setting of the read only variables .
@ param Name Points to the NULL - terminated environment variable name .
@ param Value Points to the NULL - terminated environment variable value . If the value is an
empty string then the environment variable is deleted .
@ param Volatile Indicates whether the variable is non - volatile ( FALSE ) or volatile ( TRUE ) .
@ retval EFI_SUCCESS The environment variable was successfully updated .
* */
EFI_STATUS
EFIAPI
InternalEfiShellSetEnv (
IN CONST CHAR16 * Name ,
IN CONST CHAR16 * Value ,
IN BOOLEAN Volatile
)
{
if ( Value = = NULL | | StrLen ( Value ) = = 0 ) {
return ( SHELL_DELETE_ENVIRONMENT_VARIABLE ( Name ) ) ;
} else {
SHELL_DELETE_ENVIRONMENT_VARIABLE ( Name ) ;
if ( Volatile ) {
return ( SHELL_SET_ENVIRONMENT_VARIABLE_V ( Name , StrSize ( Value ) , Value ) ) ;
} else {
return ( SHELL_SET_ENVIRONMENT_VARIABLE_NV ( Name , StrSize ( Value ) , Value ) ) ;
}
}
}
/**
Sets the environment variable .
This function changes the current value of the specified environment variable . If the
environment variable exists and the Value is an empty string , then the environment
variable is deleted . If the environment variable exists and the Value is not an empty
string , then the value of the environment variable is changed . If the environment
variable does not exist and the Value is an empty string , there is no action . If the
environment variable does not exist and the Value is a non - empty string , then the
environment variable is created and assigned the specified value .
For a description of volatile and non - volatile environment variables , see UEFI Shell
2.0 specification section 3.6 .1 .
@ param Name Points to the NULL - terminated environment variable name .
@ param Value Points to the NULL - terminated environment variable value . If the value is an
empty string then the environment variable is deleted .
@ param Volatile Indicates whether the variable is non - volatile ( FALSE ) or volatile ( TRUE ) .
@ retval EFI_SUCCESS The environment variable was successfully updated .
* */
EFI_STATUS
EFIAPI
EfiShellSetEnv (
IN CONST CHAR16 * Name ,
IN CONST CHAR16 * Value ,
IN BOOLEAN Volatile
)
{
if ( Name = = NULL | | * Name = = CHAR_NULL ) {
return ( EFI_INVALID_PARAMETER ) ;
}
//
// Make sure we dont 'set' a predefined read only variable
//
if ( gUnicodeCollation - > StriColl (
gUnicodeCollation ,
( CHAR16 * ) Name ,
L " cwd " ) = = 0
| | gUnicodeCollation - > StriColl (
gUnicodeCollation ,
( CHAR16 * ) Name ,
L " Lasterror " ) = = 0
| | gUnicodeCollation - > StriColl (
gUnicodeCollation ,
( CHAR16 * ) Name ,
L " profiles " ) = = 0
| | gUnicodeCollation - > StriColl (
gUnicodeCollation ,
( CHAR16 * ) Name ,
L " uefishellsupport " ) = = 0
| | gUnicodeCollation - > StriColl (
gUnicodeCollation ,
( CHAR16 * ) Name ,
L " uefishellversion " ) = = 0
| | gUnicodeCollation - > StriColl (
gUnicodeCollation ,
( CHAR16 * ) Name ,
L " uefiversion " ) = = 0
) {
return ( EFI_INVALID_PARAMETER ) ;
}
return ( InternalEfiShellSetEnv ( Name , Value , Volatile ) ) ;
}
/**
Returns the current directory on the specified device .
If FileSystemMapping is NULL , it returns the current working directory . If the
FileSystemMapping is not NULL , it returns the current directory associated with the
FileSystemMapping . In both cases , the returned name includes the file system
mapping ( i . e . fs0 : \ current - dir ) .
@ param FileSystemMapping A pointer to the file system mapping . If NULL ,
then the current working directory is returned .
@ retval ! = NULL The current directory .
@ retval NULL Current directory does not exist .
* */
CONST CHAR16 *
EFIAPI
EfiShellGetCurDir (
IN CONST CHAR16 * FileSystemMapping OPTIONAL
)
{
CHAR16 * PathToReturn ;
UINTN Size ;
SHELL_MAP_LIST * MapListItem ;
if ( ! IsListEmpty ( & gShellMapList . Link ) ) {
//
// if parameter is NULL, use current
//
if ( FileSystemMapping = = NULL ) {
return ( EfiShellGetEnv ( L " cwd " ) ) ;
} else {
Size = 0 ;
PathToReturn = NULL ;
MapListItem = ShellCommandFindMapItem ( FileSystemMapping ) ;
if ( MapListItem ! = NULL ) {
ASSERT ( ( PathToReturn = = NULL & & Size = = 0 ) | | ( PathToReturn ! = NULL ) ) ;
PathToReturn = StrnCatGrow ( & PathToReturn , & Size , MapListItem - > MapName , 0 ) ;
PathToReturn = StrnCatGrow ( & PathToReturn , & Size , MapListItem - > CurrentDirectoryPath , 0 ) ;
}
}
return ( AddBufferToFreeList ( PathToReturn ) ) ;
} else {
return ( NULL ) ;
}
}
/**
Changes the current directory on the specified device .
If the FileSystem is NULL , and the directory Dir does not contain a file system ' s
mapped name , this function changes the current working directory .
If the FileSystem is NULL and the directory Dir contains a mapped name , then the
current file system and the current directory on that file system are changed .
If FileSystem is NULL , and Dir is not NULL , then this changes the current working file
system .
If FileSystem is not NULL and Dir is not NULL , then this function changes the current
directory on the specified file system .
If the current working directory or the current working file system is changed then the
% cwd % environment variable will be updated
@ param FileSystem A pointer to the file system ' s mapped name . If NULL , then the current working
directory is changed .
@ param Dir Points to the NULL - terminated directory on the device specified by FileSystem .
@ retval EFI_SUCCESS The operation was sucessful
@ retval EFI_NOT_FOUND The file system could not be found
* */
EFI_STATUS
EFIAPI
EfiShellSetCurDir (
IN CONST CHAR16 * FileSystem OPTIONAL ,
IN CONST CHAR16 * Dir
)
{
CHAR16 * MapName ;
SHELL_MAP_LIST * MapListItem ;
UINTN Size ;
EFI_STATUS Status ;
CHAR16 * TempString ;
CHAR16 * DirectoryName ;
UINTN TempLen ;
Size = 0 ;
MapName = NULL ;
MapListItem = NULL ;
TempString = NULL ;
DirectoryName = NULL ;
2010-10-04 18:24:30 +02:00
if ( ( FileSystem = = NULL & & Dir = = NULL ) | | Dir = = NULL ) {
2010-09-14 07:18:09 +02:00
return ( EFI_INVALID_PARAMETER ) ;
}
if ( IsListEmpty ( & gShellMapList . Link ) ) {
return ( EFI_NOT_FOUND ) ;
}
DirectoryName = StrnCatGrow ( & DirectoryName , NULL , Dir , 0 ) ;
ASSERT ( DirectoryName ! = NULL ) ;
CleanPath ( DirectoryName ) ;
if ( FileSystem = = NULL ) {
//
// determine the file system mapping to use
//
if ( StrStr ( DirectoryName , L " : " ) ! = NULL ) {
ASSERT ( MapName = = NULL ) ;
MapName = StrnCatGrow ( & MapName , NULL , DirectoryName , ( StrStr ( DirectoryName , L " : " ) - DirectoryName + 1 ) ) ;
}
//
// find the file system mapping's entry in the list
// or use current
//
if ( MapName ! = NULL ) {
MapListItem = ShellCommandFindMapItem ( MapName ) ;
//
// make that the current file system mapping
//
if ( MapListItem ! = NULL ) {
gShellCurDir = MapListItem ;
}
} else {
MapListItem = gShellCurDir ;
}
if ( MapListItem = = NULL ) {
return ( EFI_NOT_FOUND ) ;
}
//
// now update the MapListItem's current directory
//
if ( MapListItem - > CurrentDirectoryPath ! = NULL & & DirectoryName [ StrLen ( DirectoryName ) - 1 ] ! = L ' : ' ) {
FreePool ( MapListItem - > CurrentDirectoryPath ) ;
MapListItem - > CurrentDirectoryPath = NULL ;
}
if ( MapName ! = NULL ) {
TempLen = StrLen ( MapName ) ;
if ( TempLen ! = StrLen ( DirectoryName ) ) {
ASSERT ( ( MapListItem - > CurrentDirectoryPath = = NULL & & Size = = 0 ) | | ( MapListItem - > CurrentDirectoryPath ! = NULL ) ) ;
MapListItem - > CurrentDirectoryPath = StrnCatGrow ( & MapListItem - > CurrentDirectoryPath , & Size , DirectoryName + StrLen ( MapName ) , 0 ) ;
}
} else {
ASSERT ( ( MapListItem - > CurrentDirectoryPath = = NULL & & Size = = 0 ) | | ( MapListItem - > CurrentDirectoryPath ! = NULL ) ) ;
MapListItem - > CurrentDirectoryPath = StrnCatGrow ( & MapListItem - > CurrentDirectoryPath , & Size , DirectoryName , 0 ) ;
}
if ( ( MapListItem - > CurrentDirectoryPath ! = NULL & & MapListItem - > CurrentDirectoryPath [ StrLen ( MapListItem - > CurrentDirectoryPath ) - 1 ] ! = L ' \\ ' ) | | ( MapListItem - > CurrentDirectoryPath = = NULL ) ) {
ASSERT ( ( MapListItem - > CurrentDirectoryPath = = NULL & & Size = = 0 ) | | ( MapListItem - > CurrentDirectoryPath ! = NULL ) ) ;
MapListItem - > CurrentDirectoryPath = StrnCatGrow ( & MapListItem - > CurrentDirectoryPath , & Size , L " \\ " , 0 ) ;
}
} else {
//
// cant have a mapping in the directory...
//
if ( StrStr ( DirectoryName , L " : " ) ! = NULL ) {
return ( EFI_INVALID_PARAMETER ) ;
}
//
// FileSystem != NULL
//
MapListItem = ShellCommandFindMapItem ( FileSystem ) ;
if ( MapListItem = = NULL ) {
return ( EFI_INVALID_PARAMETER ) ;
}
// gShellCurDir = MapListItem;
if ( DirectoryName ! = NULL ) {
//
// change current dir on that file system
//
if ( MapListItem - > CurrentDirectoryPath ! = NULL ) {
FreePool ( MapListItem - > CurrentDirectoryPath ) ;
DEBUG_CODE ( MapListItem - > CurrentDirectoryPath = NULL ; ) ;
}
// ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL));
// MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, FileSystem, 0);
ASSERT ( ( MapListItem - > CurrentDirectoryPath = = NULL & & Size = = 0 ) | | ( MapListItem - > CurrentDirectoryPath ! = NULL ) ) ;
MapListItem - > CurrentDirectoryPath = StrnCatGrow ( & MapListItem - > CurrentDirectoryPath , & Size , L " \\ " , 0 ) ;
ASSERT ( ( MapListItem - > CurrentDirectoryPath = = NULL & & Size = = 0 ) | | ( MapListItem - > CurrentDirectoryPath ! = NULL ) ) ;
MapListItem - > CurrentDirectoryPath = StrnCatGrow ( & MapListItem - > CurrentDirectoryPath , & Size , DirectoryName , 0 ) ;
if ( MapListItem - > CurrentDirectoryPath [ StrLen ( MapListItem - > CurrentDirectoryPath ) - 1 ] ! = L ' \\ ' ) {
ASSERT ( ( MapListItem - > CurrentDirectoryPath = = NULL & & Size = = 0 ) | | ( MapListItem - > CurrentDirectoryPath ! = NULL ) ) ;
MapListItem - > CurrentDirectoryPath = StrnCatGrow ( & MapListItem - > CurrentDirectoryPath , & Size , L " \\ " , 0 ) ;
}
}
}
//
// if updated the current directory then update the environment variable
//
if ( MapListItem = = gShellCurDir ) {
Size = 0 ;
ASSERT ( ( TempString = = NULL & & Size = = 0 ) | | ( TempString ! = NULL ) ) ;
StrnCatGrow ( & TempString , & Size , MapListItem - > MapName , 0 ) ;
ASSERT ( ( TempString = = NULL & & Size = = 0 ) | | ( TempString ! = NULL ) ) ;
StrnCatGrow ( & TempString , & Size , MapListItem - > CurrentDirectoryPath , 0 ) ;
Status = InternalEfiShellSetEnv ( L " cwd " , TempString , TRUE ) ;
FreePool ( TempString ) ;
return ( Status ) ;
}
return ( EFI_SUCCESS ) ;
}
/**
Return help information about a specific command .
This function returns the help information for the specified command . The help text
can be internal to the shell or can be from a UEFI Shell manual page .
If Sections is specified , then each section name listed will be compared in a casesensitive
manner , to the section names described in Appendix B . 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 Command Points to the NULL - terminated UEFI Shell command name .
@ param Sections Points to the NULL - terminated comma - delimited
section names to return . If NULL , then all
sections will be returned .
@ param HelpText On return , points to a callee - allocated buffer
containing all specified help text .
@ retval EFI_SUCCESS The help text was returned .
@ retval EFI_OUT_OF_RESOURCES The necessary buffer could not be allocated to hold the
returned help text .
@ retval EFI_INVALID_PARAMETER HelpText is NULL
@ retval EFI_NOT_FOUND There is no help text available for Command .
* */
EFI_STATUS
EFIAPI
EfiShellGetHelpText (
IN CONST CHAR16 * Command ,
IN CONST CHAR16 * Sections OPTIONAL ,
OUT CHAR16 * * HelpText
)
{
CONST CHAR16 * ManFileName ;
ASSERT ( HelpText ! = NULL ) ;
ManFileName = ShellCommandGetManFileNameHandler ( Command ) ;
if ( ManFileName ! = NULL ) {
return ( ProcessManFile ( ManFileName , Command , Sections , NULL , HelpText ) ) ;
} else {
return ( ProcessManFile ( Command , Command , Sections , NULL , HelpText ) ) ;
}
}
/**
Gets the enable status of the page break output mode .
User can use this function to determine current page break mode .
@ retval TRUE The page break output mode is enabled .
@ retval FALSE The page break output mode is disabled .
* */
BOOLEAN
EFIAPI
EfiShellGetPageBreak (
VOID
)
{
return ( ShellInfoObject . PageBreakEnabled ) ;
}
/**
Judges whether the active shell is the root shell .
This function makes the user to know that whether the active Shell is the root shell .
@ retval TRUE The active Shell is the root Shell .
@ retval FALSE The active Shell is NOT the root Shell .
* */
BOOLEAN
EFIAPI
EfiShellIsRootShell (
VOID
)
{
return ( ShellInfoObject . RootShellInstance ) ;
}
/**
function to return a semi - colon delimeted list of all alias ' in the current shell
up to caller to free the memory .
@ retval NULL No alias ' were found
@ retval NULL An error ocurred getting alias '
@ return ! NULL a list of all alias '
* */
CHAR16 *
EFIAPI
InternalEfiShellGetListAlias (
)
{
UINT64 MaxStorSize ;
UINT64 RemStorSize ;
UINT64 MaxVarSize ;
EFI_STATUS Status ;
EFI_GUID Guid ;
CHAR16 * VariableName ;
UINTN NameSize ;
CHAR16 * RetVal ;
UINTN RetSize ;
CHAR16 * Alias ;
Status = gRT - > QueryVariableInfo ( EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS , & MaxStorSize , & RemStorSize , & MaxVarSize ) ;
ASSERT_EFI_ERROR ( Status ) ;
VariableName = AllocateZeroPool ( ( UINTN ) MaxVarSize ) ;
RetSize = 0 ;
RetVal = NULL ;
2010-10-04 18:24:30 +02:00
if ( VariableName = = NULL ) {
return ( NULL ) ;
}
2010-09-14 07:18:09 +02:00
VariableName [ 0 ] = CHAR_NULL ;
while ( TRUE ) {
NameSize = ( UINTN ) MaxVarSize ;
Status = gRT - > GetNextVariableName ( & NameSize , VariableName , & Guid ) ;
if ( Status = = EFI_NOT_FOUND ) {
break ;
}
ASSERT_EFI_ERROR ( Status ) ;
if ( EFI_ERROR ( Status ) ) {
break ;
}
if ( CompareGuid ( & Guid , & gShellAliasGuid ) ) {
Alias = GetVariable ( VariableName , & gShellAliasGuid ) ;
ASSERT ( ( RetVal = = NULL & & RetSize = = 0 ) | | ( RetVal ! = NULL ) ) ;
RetVal = StrnCatGrow ( & RetVal , & RetSize , VariableName , 0 ) ;
RetVal = StrnCatGrow ( & RetVal , & RetSize , L " ; " , 0 ) ;
} // compare guid
} // while
FreePool ( VariableName ) ;
return ( RetVal ) ;
}
/**
This function returns the command associated with a alias or a list of all
alias ' .
@ param [ in ] Alias Points to the NULL - terminated shell alias .
If this parameter is NULL , then all
aliases will be returned in ReturnedData .
@ param [ out ] Volatile upon return of a single command if TRUE indicates
this is stored in a volatile fashion . FALSE otherwise .
@ return If Alias is not NULL , it will return a pointer to
the NULL - terminated command for that alias .
If Alias is NULL , ReturnedData points to a ' ; '
delimited list of alias ( e . g .
ReturnedData = " dir;del;copy;mfp " ) that is NULL - terminated .
@ retval NULL an error ocurred
@ retval NULL Alias was not a valid Alias
* */
CONST CHAR16 *
EFIAPI
EfiShellGetAlias (
IN CONST CHAR16 * Alias ,
OUT BOOLEAN * Volatile OPTIONAL
)
{
CHAR16 * RetVal ;
UINTN RetSize ;
UINT32 Attribs ;
EFI_STATUS Status ;
if ( Alias ! = NULL ) {
if ( Volatile = = NULL ) {
return ( AddBufferToFreeList ( GetVariable ( ( CHAR16 * ) Alias , & gShellAliasGuid ) ) ) ;
}
RetSize = 0 ;
RetVal = NULL ;
Status = gRT - > GetVariable ( ( CHAR16 * ) Alias , & gShellAliasGuid , & Attribs , & RetSize , RetVal ) ;
if ( Status = = EFI_BUFFER_TOO_SMALL ) {
RetVal = AllocateZeroPool ( RetSize ) ;
Status = gRT - > GetVariable ( ( CHAR16 * ) Alias , & gShellAliasGuid , & Attribs , & RetSize , RetVal ) ;
}
if ( EFI_ERROR ( Status ) ) {
if ( RetVal ! = NULL ) {
FreePool ( RetVal ) ;
}
return ( NULL ) ;
}
if ( ( EFI_VARIABLE_NON_VOLATILE & Attribs ) = = EFI_VARIABLE_NON_VOLATILE ) {
* Volatile = FALSE ;
} else {
* Volatile = TRUE ;
}
return ( AddBufferToFreeList ( RetVal ) ) ;
}
return ( AddBufferToFreeList ( InternalEfiShellGetListAlias ( ) ) ) ;
}
/**
Changes a shell command alias .
This function creates an alias for a shell command or if Alias is NULL it will delete an existing alias .
this function does not check for built in alias ' .
@ param [ in ] Command Points to the NULL - terminated shell command or existing alias .
@ param [ in ] Alias Points to the NULL - terminated alias for the shell command . If this is NULL , and
Command refers to an alias , that alias will be deleted .
@ param [ in ] Volatile if TRUE the Alias being set will be stored in a volatile fashion . if FALSE the
Alias being set will be stored in a non - volatile fashion .
@ retval EFI_SUCCESS Alias created or deleted successfully .
@ retval EFI_NOT_FOUND the Alias intended to be deleted was not found
* */
EFI_STATUS
EFIAPI
InternalSetAlias (
IN CONST CHAR16 * Command ,
IN CONST CHAR16 * Alias ,
IN BOOLEAN Volatile
)
{
//
// We must be trying to remove one if Alias is NULL
//
if ( Alias = = NULL ) {
//
// remove an alias (but passed in COMMAND parameter)
//
return ( gRT - > SetVariable ( ( CHAR16 * ) Command , & gShellAliasGuid , 0 , 0 , NULL ) ) ;
} else {
//
// Add and replace are the same
//
// We dont check the error return on purpose since the variable may not exist.
gRT - > SetVariable ( ( CHAR16 * ) Command , & gShellAliasGuid , 0 , 0 , NULL ) ;
return ( gRT - > SetVariable ( ( CHAR16 * ) Alias , & gShellAliasGuid , EFI_VARIABLE_BOOTSERVICE_ACCESS | ( Volatile ? 0 : EFI_VARIABLE_NON_VOLATILE ) , StrSize ( Command ) , ( VOID * ) Command ) ) ;
}
}
/**
Changes a shell command alias .
This function creates an alias for a shell command or if Alias is NULL it will delete an existing alias .
@ param [ in ] Command Points to the NULL - terminated shell command or existing alias .
@ param [ in ] Alias Points to the NULL - terminated alias for the shell command . If this is NULL , and
Command refers to an alias , that alias will be deleted .
@ param [ in ] Replace If TRUE and the alias already exists , then the existing alias will be replaced . If
FALSE and the alias already exists , then the existing alias is unchanged and
EFI_ACCESS_DENIED is returned .
@ param [ in ] Volatile if TRUE the Alias being set will be stored in a volatile fashion . if FALSE the
Alias being set will be stored in a non - volatile fashion .
@ retval EFI_SUCCESS Alias created or deleted successfully .
@ retval EFI_NOT_FOUND the Alias intended to be deleted was not found
@ retval EFI_ACCESS_DENIED The alias is a built - in alias or already existed and Replace was set to
FALSE .
* */
EFI_STATUS
EFIAPI
EfiShellSetAlias (
IN CONST CHAR16 * Command ,
IN CONST CHAR16 * Alias ,
IN BOOLEAN Replace ,
IN BOOLEAN Volatile
)
{
//
// cant set over a built in alias
//
if ( ShellCommandIsOnAliasList ( Alias = = NULL ? Command : Alias ) ) {
return ( EFI_ACCESS_DENIED ) ;
}
if ( Command = = NULL | | * Command = = CHAR_NULL | | StrLen ( Command ) = = 0 ) {
return ( EFI_INVALID_PARAMETER ) ;
}
if ( EfiShellGetAlias ( Command , NULL ) ! = NULL & & ! Replace ) {
return ( EFI_ACCESS_DENIED ) ;
}
return ( InternalSetAlias ( Command , Alias , Volatile ) ) ;
}
// Pure FILE_HANDLE operations are passed to FileHandleLib
// these functions are indicated by the *
EFI_SHELL_PROTOCOL mShellProtocol = {
EfiShellExecute ,
EfiShellGetEnv ,
EfiShellSetEnv ,
EfiShellGetAlias ,
EfiShellSetAlias ,
EfiShellGetHelpText ,
EfiShellGetDevicePathFromMap ,
EfiShellGetMapFromDevicePath ,
EfiShellGetDevicePathFromFilePath ,
EfiShellGetFilePathFromDevicePath ,
EfiShellSetMap ,
EfiShellGetCurDir ,
EfiShellSetCurDir ,
EfiShellOpenFileList ,
EfiShellFreeFileList ,
EfiShellRemoveDupInFileList ,
EfiShellBatchIsActive ,
EfiShellIsRootShell ,
EfiShellEnablePageBreak ,
EfiShellDisablePageBreak ,
EfiShellGetPageBreak ,
EfiShellGetDeviceName ,
( EFI_SHELL_GET_FILE_INFO ) FileHandleGetInfo , //*
( EFI_SHELL_SET_FILE_INFO ) FileHandleSetInfo , //*
EfiShellOpenFileByName ,
EfiShellClose ,
EfiShellCreateFile ,
( EFI_SHELL_READ_FILE ) FileHandleRead , //*
( EFI_SHELL_WRITE_FILE ) FileHandleWrite , //*
( EFI_SHELL_DELETE_FILE ) FileHandleDelete , //*
EfiShellDeleteFileByName ,
( EFI_SHELL_GET_FILE_POSITION ) FileHandleGetPosition , //*
( EFI_SHELL_SET_FILE_POSITION ) FileHandleSetPosition , //*
( EFI_SHELL_FLUSH_FILE ) FileHandleFlush , //*
EfiShellFindFiles ,
EfiShellFindFilesInDir ,
( EFI_SHELL_GET_FILE_SIZE ) FileHandleGetSize , //*
EfiShellOpenRoot ,
EfiShellOpenRootByHandle ,
NULL ,
SHELL_MAJOR_VERSION ,
SHELL_MINOR_VERSION
} ;
/**
Function to create and install on the current handle .
Will overwrite any existing ShellProtocols in the system to be sure that
the current shell is in control .
This must be removed via calling CleanUpShellProtocol ( ) .
2010-09-17 22:09:48 +02:00
@ param [ in , out ] NewShell The pointer to the pointer to the structure
2010-09-14 07:18:09 +02:00
to install .
@ retval EFI_SUCCESS The operation was successful .
@ return An error from LocateHandle , CreateEvent , or other core function .
* */
EFI_STATUS
EFIAPI
CreatePopulateInstallShellProtocol (
IN OUT EFI_SHELL_PROTOCOL * * NewShell
)
{
EFI_STATUS Status ;
UINTN BufferSize ;
EFI_HANDLE * Buffer ;
UINTN HandleCounter ;
SHELL_PROTOCOL_HANDLE_LIST * OldProtocolNode ;
2010-11-16 23:31:47 +01:00
if ( NewShell = = NULL ) {
return ( EFI_INVALID_PARAMETER ) ;
}
2010-09-14 07:18:09 +02:00
BufferSize = 0 ;
Buffer = NULL ;
OldProtocolNode = NULL ;
InitializeListHead ( & ShellInfoObject . OldShellList . Link ) ;
//
// Initialize EfiShellProtocol object...
//
Status = gBS - > CreateEvent ( 0 ,
0 ,
NULL ,
NULL ,
& mShellProtocol . ExecutionBreak ) ;
2010-11-16 23:31:47 +01:00
if ( EFI_ERROR ( Status ) ) {
return ( Status ) ;
}
2010-09-14 07:18:09 +02:00
//
// Get the size of the buffer we need.
//
Status = gBS - > LocateHandle ( ByProtocol ,
& gEfiShellProtocolGuid ,
NULL ,
& BufferSize ,
Buffer ) ;
if ( Status = = EFI_BUFFER_TOO_SMALL ) {
//
// Allocate and recall with buffer of correct size
//
Buffer = AllocateZeroPool ( BufferSize ) ;
2010-11-16 23:31:47 +01:00
if ( Buffer = = NULL ) {
return ( EFI_OUT_OF_RESOURCES ) ;
}
2010-09-14 07:18:09 +02:00
Status = gBS - > LocateHandle ( ByProtocol ,
& gEfiShellProtocolGuid ,
NULL ,
& BufferSize ,
Buffer ) ;
2010-11-16 23:31:47 +01:00
if ( EFI_ERROR ( Status ) ) {
FreePool ( Buffer ) ;
return ( Status ) ;
}
2010-09-14 07:18:09 +02:00
//
// now overwrite each of them, but save the info to restore when we end.
//
for ( HandleCounter = 0 ; HandleCounter < ( BufferSize / sizeof ( EFI_HANDLE ) ) ; HandleCounter + + ) {
OldProtocolNode = AllocateZeroPool ( sizeof ( SHELL_PROTOCOL_HANDLE_LIST ) ) ;
ASSERT ( OldProtocolNode ! = NULL ) ;
Status = gBS - > OpenProtocol ( Buffer [ HandleCounter ] ,
& gEfiShellProtocolGuid ,
( VOID * * ) & ( OldProtocolNode - > Interface ) ,
gImageHandle ,
NULL ,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
) ;
if ( ! EFI_ERROR ( Status ) ) {
//
// reinstall over the old one...
//
OldProtocolNode - > Handle = Buffer [ HandleCounter ] ;
Status = gBS - > ReinstallProtocolInterface (
OldProtocolNode - > Handle ,
& gEfiShellProtocolGuid ,
OldProtocolNode - > Interface ,
2010-11-16 23:31:47 +01:00
( VOID * ) ( & mShellProtocol ) ) ;
2010-09-14 07:18:09 +02:00
if ( ! EFI_ERROR ( Status ) ) {
//
// we reinstalled sucessfully. log this so we can reverse it later.
//
//
// add to the list for subsequent...
//
InsertTailList ( & ShellInfoObject . OldShellList . Link , & OldProtocolNode - > Link ) ;
}
}
}
FreePool ( Buffer ) ;
} else if ( Status = = EFI_NOT_FOUND ) {
ASSERT ( IsListEmpty ( & ShellInfoObject . OldShellList . Link ) ) ;
//
// no one else published yet. just publish it ourselves.
//
Status = gBS - > InstallProtocolInterface (
& gImageHandle ,
& gEfiShellProtocolGuid ,
EFI_NATIVE_INTERFACE ,
2010-11-16 23:31:47 +01:00
( VOID * ) ( & mShellProtocol ) ) ;
2010-09-14 07:18:09 +02:00
}
if ( PcdGetBool ( PcdShellSupportOldProtocols ) ) {
///@todo support ShellEnvironment2
///@todo do we need to support ShellEnvironment (not ShellEnvironment2) also?
}
2010-11-16 23:31:47 +01:00
if ( ! EFI_ERROR ( Status ) ) {
* NewShell = & mShellProtocol ;
}
2010-09-14 07:18:09 +02:00
return ( Status ) ;
}
/**
2010-09-17 22:09:48 +02:00
Opposite of CreatePopulateInstallShellProtocol .
2010-09-14 07:18:09 +02:00
Free all memory and restore the system to the state it was in before calling
CreatePopulateInstallShellProtocol .
@ param [ in , out ] NewShell The pointer to the new shell protocol structure .
@ retval EFI_SUCCESS The operation was successful .
* */
EFI_STATUS
EFIAPI
CleanUpShellProtocol (
IN OUT EFI_SHELL_PROTOCOL * NewShell
)
{
2010-11-16 23:31:47 +01:00
EFI_STATUS Status ;
SHELL_PROTOCOL_HANDLE_LIST * Node2 ;
EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL * SimpleEx ;
2010-09-14 07:18:09 +02:00
//
// if we need to restore old protocols...
//
if ( ! IsListEmpty ( & ShellInfoObject . OldShellList . Link ) ) {
for ( Node2 = ( SHELL_PROTOCOL_HANDLE_LIST * ) GetFirstNode ( & ShellInfoObject . OldShellList . Link )
; ! IsListEmpty ( & ShellInfoObject . OldShellList . Link )
; Node2 = ( SHELL_PROTOCOL_HANDLE_LIST * ) GetFirstNode ( & ShellInfoObject . OldShellList . Link )
) {
RemoveEntryList ( & Node2 - > Link ) ;
Status = gBS - > ReinstallProtocolInterface ( Node2 - > Handle ,
& gEfiShellProtocolGuid ,
NewShell ,
Node2 - > Interface ) ;
FreePool ( Node2 ) ;
}
} else {
//
// no need to restore
//
Status = gBS - > UninstallProtocolInterface ( gImageHandle ,
& gEfiShellProtocolGuid ,
NewShell ) ;
}
Status = gBS - > CloseEvent ( NewShell - > ExecutionBreak ) ;
2010-11-16 23:31:47 +01:00
NewShell - > ExecutionBreak = NULL ;
Status = gBS - > OpenProtocol (
gST - > ConsoleInHandle ,
& gEfiSimpleTextInputExProtocolGuid ,
( VOID * * ) & SimpleEx ,
gImageHandle ,
NULL ,
EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ;
Status = SimpleEx - > UnregisterKeyNotify ( SimpleEx , ShellInfoObject . CtrlCNotifyHandle1 ) ;
Status = SimpleEx - > UnregisterKeyNotify ( SimpleEx , ShellInfoObject . CtrlCNotifyHandle2 ) ;
2011-03-25 23:23:05 +01:00
Status = SimpleEx - > UnregisterKeyNotify ( SimpleEx , ShellInfoObject . CtrlCNotifyHandle3 ) ;
Status = SimpleEx - > UnregisterKeyNotify ( SimpleEx , ShellInfoObject . CtrlCNotifyHandle4 ) ;
Status = SimpleEx - > UnregisterKeyNotify ( SimpleEx , ShellInfoObject . CtrlSNotifyHandle1 ) ;
Status = SimpleEx - > UnregisterKeyNotify ( SimpleEx , ShellInfoObject . CtrlSNotifyHandle2 ) ;
Status = SimpleEx - > UnregisterKeyNotify ( SimpleEx , ShellInfoObject . CtrlSNotifyHandle3 ) ;
Status = SimpleEx - > UnregisterKeyNotify ( SimpleEx , ShellInfoObject . CtrlSNotifyHandle4 ) ;
2010-09-14 07:18:09 +02:00
return ( Status ) ;
}
2010-11-16 23:31:47 +01:00
/**
Notification function for keystrokes .
@ param [ in ] KeyData The key that was pressed .
@ retval EFI_SUCCESS The operation was successful .
* */
EFI_STATUS
EFIAPI
NotificationFunction (
IN EFI_KEY_DATA * KeyData
)
{
2011-03-25 23:23:05 +01:00
EFI_INPUT_KEY Key ;
UINTN EventIndex ;
// ShellPrintEx(-1,-1,L" <Notify> ");
if ( ( KeyData - > Key . UnicodeChar = = L ' c ' | | KeyData - > Key . UnicodeChar = = 3 ) & &
( KeyData - > KeyState . KeyShiftState = = ( EFI_SHIFT_STATE_VALID | EFI_LEFT_CONTROL_PRESSED ) | | KeyData - > KeyState . KeyShiftState = = ( EFI_SHIFT_STATE_VALID | EFI_RIGHT_CONTROL_PRESSED ) )
) {
if ( ShellInfoObject . NewEfiShellProtocol - > ExecutionBreak = = NULL ) {
return ( EFI_UNSUPPORTED ) ;
}
return ( gBS - > SignalEvent ( ShellInfoObject . NewEfiShellProtocol - > ExecutionBreak ) ) ;
} else if ( ( KeyData - > Key . UnicodeChar = = L ' s ' ) & &
( KeyData - > KeyState . KeyShiftState = = ( EFI_SHIFT_STATE_VALID | EFI_LEFT_CONTROL_PRESSED ) | | KeyData - > KeyState . KeyShiftState = = ( EFI_SHIFT_STATE_VALID | EFI_RIGHT_CONTROL_PRESSED ) )
) {
//
// just get some key
//
gBS - > WaitForEvent ( 1 , & gST - > ConIn - > WaitForKey , & EventIndex ) ;
gST - > ConIn - > ReadKeyStroke ( gST - > ConIn , & Key ) ;
2010-11-16 23:31:47 +01:00
}
2011-03-25 23:23:05 +01:00
return ( EFI_SUCCESS ) ;
2010-11-16 23:31:47 +01:00
}
/**
Function to start monitoring for CTRL - C using SimpleTextInputEx . This
feature ' s enabled state was not known when the shell initially launched .
@ retval EFI_SUCCESS The feature is enabled .
@ retval EFI_OUT_OF_RESOURCES There is not enough mnemory available .
* */
EFI_STATUS
EFIAPI
InernalEfiShellStartMonitor (
VOID
)
{
EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL * SimpleEx ;
EFI_KEY_DATA KeyData ;
EFI_STATUS Status ;
Status = gBS - > OpenProtocol (
gST - > ConsoleInHandle ,
& gEfiSimpleTextInputExProtocolGuid ,
( VOID * * ) & SimpleEx ,
gImageHandle ,
NULL ,
EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ;
if ( EFI_ERROR ( Status ) ) {
ShellPrintHiiEx (
- 1 ,
- 1 ,
NULL ,
STRING_TOKEN ( STR_SHELL_NO_IN_EX ) ,
ShellInfoObject . HiiHandle ) ;
return ( EFI_SUCCESS ) ;
}
2010-09-14 07:18:09 +02:00
2010-11-16 23:31:47 +01:00
if ( ShellInfoObject . NewEfiShellProtocol - > ExecutionBreak = = NULL ) {
return ( EFI_UNSUPPORTED ) ;
}
KeyData . KeyState . KeyToggleState = 0 ;
KeyData . Key . ScanCode = 0 ;
KeyData . KeyState . KeyShiftState = EFI_SHIFT_STATE_VALID | EFI_LEFT_CONTROL_PRESSED ;
KeyData . Key . UnicodeChar = L ' c ' ;
Status = SimpleEx - > RegisterKeyNotify (
SimpleEx ,
& KeyData ,
NotificationFunction ,
& ShellInfoObject . CtrlCNotifyHandle1 ) ;
KeyData . KeyState . KeyShiftState = EFI_SHIFT_STATE_VALID | EFI_RIGHT_CONTROL_PRESSED ;
if ( ! EFI_ERROR ( Status ) ) {
Status = SimpleEx - > RegisterKeyNotify (
SimpleEx ,
& KeyData ,
NotificationFunction ,
& ShellInfoObject . CtrlCNotifyHandle2 ) ;
}
KeyData . KeyState . KeyShiftState = EFI_SHIFT_STATE_VALID | EFI_LEFT_CONTROL_PRESSED ;
KeyData . Key . UnicodeChar = 3 ;
if ( ! EFI_ERROR ( Status ) ) {
Status = SimpleEx - > RegisterKeyNotify (
SimpleEx ,
& KeyData ,
NotificationFunction ,
& ShellInfoObject . CtrlCNotifyHandle3 ) ;
}
KeyData . KeyState . KeyShiftState = EFI_SHIFT_STATE_VALID | EFI_RIGHT_CONTROL_PRESSED ;
if ( ! EFI_ERROR ( Status ) ) {
Status = SimpleEx - > RegisterKeyNotify (
SimpleEx ,
& KeyData ,
NotificationFunction ,
& ShellInfoObject . CtrlCNotifyHandle4 ) ;
}
return ( Status ) ;
}