This searches for handles that produce the dynamic command protocol after searching the commands compiled into the shell.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jaben Carsey <jaben.carsey@intel.com>
Reviewed-by: Eugene Cohen <eugene@hp.com>
Reviewed-by: Erik Bjorge <erik.c.bjorge@intel.com> 

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15754 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Jaben Carsey
2014-08-05 20:09:25 +00:00
committed by jcarsey
parent 6306fd90b7
commit cf812a204c
3 changed files with 270 additions and 117 deletions

View File

@ -215,14 +215,80 @@ ShellCommandLibDestructor (
}
/**
Checks if a command is already on the list.
Find a dynamic command protocol instance given a command name string
@param CommandString the command name string
@return instance the command protocol instance, if dynamic command instance found
@retval NULL no dynamic command protocol instance found for name
**/
CONST EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *
EFIAPI
ShellCommandFindDynamicCommand (
IN CONST CHAR16 *CommandString
)
{
EFI_STATUS Status;
EFI_HANDLE *CommandHandleList;
EFI_HANDLE *NextCommand;
EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *DynamicCommand;
CommandHandleList = GetHandleListByProtocol(&gEfiShellDynamicCommandProtocolGuid);
if (CommandHandleList == NULL) {
//
// not found or out of resources
//
return NULL;
}
for (NextCommand = CommandHandleList; *NextCommand != NULL; NextCommand++) {
Status = gBS->HandleProtocol(
*NextCommand,
&gEfiShellDynamicCommandProtocolGuid,
(VOID **)&DynamicCommand
);
if (EFI_ERROR(Status)) {
continue;
}
if (gUnicodeCollation->StriColl(
gUnicodeCollation,
(CHAR16*)CommandString,
(CHAR16*)DynamicCommand->CommandName) == 0
){
FreePool(CommandHandleList);
return (DynamicCommand);
}
}
FreePool(CommandHandleList);
return (NULL);
}
/**
Checks if a command exists as a dynamic command protocol instance
@param[in] CommandString The command string to check for on the list.
**/
BOOLEAN
EFIAPI
ShellCommandIsCommandOnList (
IN CONST CHAR16 *CommandString
ShellCommandDynamicCommandExists (
IN CONST CHAR16 *CommandString
)
{
return (ShellCommandFindDynamicCommand(CommandString) != NULL);
}
/**
Checks if a command is already on the internal command list.
@param[in] CommandString The command string to check for on the list.
**/
BOOLEAN
EFIAPI
ShellCommandIsCommandOnInternalList(
IN CONST CHAR16 *CommandString
)
{
SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node;
@ -252,7 +318,52 @@ ShellCommandIsCommandOnList (
}
/**
Get the help text for a command.
Checks if a command exists, either internally or through the dynamic command protocol.
@param[in] CommandString The command string to check for on the list.
**/
BOOLEAN
EFIAPI
ShellCommandIsCommandOnList(
IN CONST CHAR16 *CommandString
)
{
if (ShellCommandIsCommandOnInternalList(CommandString)) {
return TRUE;
}
return ShellCommandDynamicCommandExists(CommandString);
}
/**
Get the help text for a dynamic command.
@param[in] CommandString The command name.
@retval NULL No help text was found.
@return String of help text. Caller required to free.
**/
CHAR16*
EFIAPI
ShellCommandGetDynamicCommandHelp(
IN CONST CHAR16 *CommandString
)
{
EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *DynamicCommand;
DynamicCommand = (EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *)ShellCommandFindDynamicCommand(CommandString);
if (DynamicCommand == NULL) {
return (NULL);
}
//
// TODO: how to get proper language?
//
return DynamicCommand->GetHelp(DynamicCommand, "en");
}
/**
Get the help text for an internal command.
@param[in] CommandString The command name.
@ -261,7 +372,7 @@ ShellCommandIsCommandOnList (
**/
CHAR16*
EFIAPI
ShellCommandGetCommandHelp (
ShellCommandGetInternalCommandHelp(
IN CONST CHAR16 *CommandString
)
{
@ -291,6 +402,31 @@ ShellCommandGetCommandHelp (
return (NULL);
}
/**
Get the help text for a command.
@param[in] CommandString The command name.
@retval NULL No help text was found.
@return String of help text.Caller reuiqred to free.
**/
CHAR16*
EFIAPI
ShellCommandGetCommandHelp (
IN CONST CHAR16 *CommandString
)
{
CHAR16 *HelpStr;
HelpStr = ShellCommandGetInternalCommandHelp(CommandString);
if (HelpStr == NULL) {
HelpStr = ShellCommandGetDynamicCommandHelp(CommandString);
}
return HelpStr;
}
/**
Registers handlers of type SHELL_RUN_COMMAND and
SHELL_GET_MAN_FILENAME for each shell command.
@ -505,7 +641,8 @@ ShellCommandRunCommandHandler (
IN OUT BOOLEAN *CanAffectLE OPTIONAL
)
{
SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node;
SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node;
EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *DynamicCommand;
//
// assert for NULL parameters
@ -524,7 +661,7 @@ ShellCommandRunCommandHandler (
gUnicodeCollation,
(CHAR16*)CommandString,
Node->CommandString) == 0
){
){
if (CanAffectLE != NULL) {
*CanAffectLE = Node->LastError;
}
@ -536,6 +673,20 @@ ShellCommandRunCommandHandler (
return (RETURN_SUCCESS);
}
}
//
// An internal command was not found, try to find a dynamic command
//
DynamicCommand = (EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *)ShellCommandFindDynamicCommand(CommandString);
if (DynamicCommand != NULL) {
if (RetVal != NULL) {
*RetVal = DynamicCommand->Handler(DynamicCommand, gST, gEfiShellParametersProtocol, gEfiShellProtocol);
} else {
DynamicCommand->Handler(DynamicCommand, gST, gEfiShellParametersProtocol, gEfiShellProtocol);
}
return (RETURN_SUCCESS);
}
return (RETURN_NOT_FOUND);
}
@ -1199,114 +1350,114 @@ ShellCommandCreateInitialMappingsAndPaths(
}
return (EFI_SUCCESS);
}
/**
Add mappings for any devices without one. Do not change any existing maps.
@retval EFI_SUCCESS The operation was successful.
**/
EFI_STATUS
EFIAPI
ShellCommandUpdateMapping (
VOID
)
{
EFI_STATUS Status;
EFI_HANDLE *HandleList;
UINTN Count;
EFI_DEVICE_PATH_PROTOCOL **DevicePathList;
CHAR16 *NewDefaultName;
CHAR16 *NewConsistName;
EFI_DEVICE_PATH_PROTOCOL **ConsistMappingTable;
HandleList = NULL;
Status = EFI_SUCCESS;
//
// remove mappings that represent removed devices.
//
//
// Find each handle with Simple File System
//
HandleList = GetHandleListByProtocol(&gEfiSimpleFileSystemProtocolGuid);
if (HandleList != NULL) {
//
// Do a count of the handles
//
for (Count = 0 ; HandleList[Count] != NULL ; Count++);
//
// Get all Device Paths
//
DevicePathList = AllocateZeroPool(sizeof(EFI_DEVICE_PATH_PROTOCOL*) * Count);
ASSERT(DevicePathList != NULL);
for (Count = 0 ; HandleList[Count] != NULL ; Count++) {
DevicePathList[Count] = DevicePathFromHandle(HandleList[Count]);
}
//
// Sort all DevicePaths
//
PerformQuickSort(DevicePathList, Count, sizeof(EFI_DEVICE_PATH_PROTOCOL*), DevicePathCompare);
ShellCommandConsistMappingInitialize(&ConsistMappingTable);
//
// Assign new Mappings to remainders
//
for (Count = 0 ; HandleList[Count] != NULL && !EFI_ERROR(Status); Count++) {
//
// Skip ones that already have
//
if (gEfiShellProtocol->GetMapFromDevicePath(&DevicePathList[Count]) != NULL) {
continue;
}
//
// Get default name
//
NewDefaultName = ShellCommandCreateNewMappingName(MappingTypeFileSystem);
ASSERT(NewDefaultName != NULL);
//
// Call shell protocol SetMap function now...
//
Status = gEfiShellProtocol->SetMap(DevicePathList[Count], NewDefaultName);
if (!EFI_ERROR(Status)) {
//
// Now do consistent name
//
NewConsistName = ShellCommandConsistMappingGenMappingName(DevicePathList[Count], ConsistMappingTable);
if (NewConsistName != NULL) {
Status = gEfiShellProtocol->SetMap(DevicePathList[Count], NewConsistName);
FreePool(NewConsistName);
}
}
FreePool(NewDefaultName);
}
ShellCommandConsistMappingUnInitialize(ConsistMappingTable);
SHELL_FREE_NON_NULL(HandleList);
SHELL_FREE_NON_NULL(DevicePathList);
HandleList = NULL;
} else {
Count = (UINTN)-1;
}
//
// Do it all over again for gEfiBlockIoProtocolGuid
//
return (Status);
}
/**
Converts a SHELL_FILE_HANDLE to an EFI_FILE_PROTOCOL*.
@param[in] Handle The SHELL_FILE_HANDLE to convert.
}
/**
Add mappings for any devices without one. Do not change any existing maps.
@retval EFI_SUCCESS The operation was successful.
**/
EFI_STATUS
EFIAPI
ShellCommandUpdateMapping (
VOID
)
{
EFI_STATUS Status;
EFI_HANDLE *HandleList;
UINTN Count;
EFI_DEVICE_PATH_PROTOCOL **DevicePathList;
CHAR16 *NewDefaultName;
CHAR16 *NewConsistName;
EFI_DEVICE_PATH_PROTOCOL **ConsistMappingTable;
HandleList = NULL;
Status = EFI_SUCCESS;
//
// remove mappings that represent removed devices.
//
//
// Find each handle with Simple File System
//
HandleList = GetHandleListByProtocol(&gEfiSimpleFileSystemProtocolGuid);
if (HandleList != NULL) {
//
// Do a count of the handles
//
for (Count = 0 ; HandleList[Count] != NULL ; Count++);
//
// Get all Device Paths
//
DevicePathList = AllocateZeroPool(sizeof(EFI_DEVICE_PATH_PROTOCOL*) * Count);
ASSERT(DevicePathList != NULL);
for (Count = 0 ; HandleList[Count] != NULL ; Count++) {
DevicePathList[Count] = DevicePathFromHandle(HandleList[Count]);
}
//
// Sort all DevicePaths
//
PerformQuickSort(DevicePathList, Count, sizeof(EFI_DEVICE_PATH_PROTOCOL*), DevicePathCompare);
ShellCommandConsistMappingInitialize(&ConsistMappingTable);
//
// Assign new Mappings to remainders
//
for (Count = 0 ; HandleList[Count] != NULL && !EFI_ERROR(Status); Count++) {
//
// Skip ones that already have
//
if (gEfiShellProtocol->GetMapFromDevicePath(&DevicePathList[Count]) != NULL) {
continue;
}
//
// Get default name
//
NewDefaultName = ShellCommandCreateNewMappingName(MappingTypeFileSystem);
ASSERT(NewDefaultName != NULL);
//
// Call shell protocol SetMap function now...
//
Status = gEfiShellProtocol->SetMap(DevicePathList[Count], NewDefaultName);
if (!EFI_ERROR(Status)) {
//
// Now do consistent name
//
NewConsistName = ShellCommandConsistMappingGenMappingName(DevicePathList[Count], ConsistMappingTable);
if (NewConsistName != NULL) {
Status = gEfiShellProtocol->SetMap(DevicePathList[Count], NewConsistName);
FreePool(NewConsistName);
}
}
FreePool(NewDefaultName);
}
ShellCommandConsistMappingUnInitialize(ConsistMappingTable);
SHELL_FREE_NON_NULL(HandleList);
SHELL_FREE_NON_NULL(DevicePathList);
HandleList = NULL;
} else {
Count = (UINTN)-1;
}
//
// Do it all over again for gEfiBlockIoProtocolGuid
//
return (Status);
}
/**
Converts a SHELL_FILE_HANDLE to an EFI_FILE_PROTOCOL*.
@param[in] Handle The SHELL_FILE_HANDLE to convert.
@return a EFI_FILE_PROTOCOL* representing the same file.
**/