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. @param[in] CommandString The command string to check for on the list.
**/ **/
BOOLEAN BOOLEAN
EFIAPI EFIAPI
ShellCommandIsCommandOnList ( ShellCommandDynamicCommandExists (
IN CONST CHAR16 *CommandString 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; 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. @param[in] CommandString The command name.
@ -261,7 +372,7 @@ ShellCommandIsCommandOnList (
**/ **/
CHAR16* CHAR16*
EFIAPI EFIAPI
ShellCommandGetCommandHelp ( ShellCommandGetInternalCommandHelp(
IN CONST CHAR16 *CommandString IN CONST CHAR16 *CommandString
) )
{ {
@ -291,6 +402,31 @@ ShellCommandGetCommandHelp (
return (NULL); 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 Registers handlers of type SHELL_RUN_COMMAND and
SHELL_GET_MAN_FILENAME for each shell command. SHELL_GET_MAN_FILENAME for each shell command.
@ -505,7 +641,8 @@ ShellCommandRunCommandHandler (
IN OUT BOOLEAN *CanAffectLE OPTIONAL 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 // assert for NULL parameters
@ -524,7 +661,7 @@ ShellCommandRunCommandHandler (
gUnicodeCollation, gUnicodeCollation,
(CHAR16*)CommandString, (CHAR16*)CommandString,
Node->CommandString) == 0 Node->CommandString) == 0
){ ){
if (CanAffectLE != NULL) { if (CanAffectLE != NULL) {
*CanAffectLE = Node->LastError; *CanAffectLE = Node->LastError;
} }
@ -536,6 +673,20 @@ ShellCommandRunCommandHandler (
return (RETURN_SUCCESS); 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); return (RETURN_NOT_FOUND);
} }
@ -1199,114 +1350,114 @@ ShellCommandCreateInitialMappingsAndPaths(
} }
return (EFI_SUCCESS); return (EFI_SUCCESS);
} }
/** /**
Add mappings for any devices without one. Do not change any existing maps. Add mappings for any devices without one. Do not change any existing maps.
@retval EFI_SUCCESS The operation was successful. @retval EFI_SUCCESS The operation was successful.
**/ **/
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
ShellCommandUpdateMapping ( ShellCommandUpdateMapping (
VOID VOID
) )
{ {
EFI_STATUS Status; EFI_STATUS Status;
EFI_HANDLE *HandleList; EFI_HANDLE *HandleList;
UINTN Count; UINTN Count;
EFI_DEVICE_PATH_PROTOCOL **DevicePathList; EFI_DEVICE_PATH_PROTOCOL **DevicePathList;
CHAR16 *NewDefaultName; CHAR16 *NewDefaultName;
CHAR16 *NewConsistName; CHAR16 *NewConsistName;
EFI_DEVICE_PATH_PROTOCOL **ConsistMappingTable; EFI_DEVICE_PATH_PROTOCOL **ConsistMappingTable;
HandleList = NULL; HandleList = NULL;
Status = EFI_SUCCESS; Status = EFI_SUCCESS;
// //
// remove mappings that represent removed devices. // remove mappings that represent removed devices.
// //
// //
// Find each handle with Simple File System // Find each handle with Simple File System
// //
HandleList = GetHandleListByProtocol(&gEfiSimpleFileSystemProtocolGuid); HandleList = GetHandleListByProtocol(&gEfiSimpleFileSystemProtocolGuid);
if (HandleList != NULL) { if (HandleList != NULL) {
// //
// Do a count of the handles // Do a count of the handles
// //
for (Count = 0 ; HandleList[Count] != NULL ; Count++); for (Count = 0 ; HandleList[Count] != NULL ; Count++);
// //
// Get all Device Paths // Get all Device Paths
// //
DevicePathList = AllocateZeroPool(sizeof(EFI_DEVICE_PATH_PROTOCOL*) * Count); DevicePathList = AllocateZeroPool(sizeof(EFI_DEVICE_PATH_PROTOCOL*) * Count);
ASSERT(DevicePathList != NULL); ASSERT(DevicePathList != NULL);
for (Count = 0 ; HandleList[Count] != NULL ; Count++) { for (Count = 0 ; HandleList[Count] != NULL ; Count++) {
DevicePathList[Count] = DevicePathFromHandle(HandleList[Count]); DevicePathList[Count] = DevicePathFromHandle(HandleList[Count]);
} }
// //
// Sort all DevicePaths // Sort all DevicePaths
// //
PerformQuickSort(DevicePathList, Count, sizeof(EFI_DEVICE_PATH_PROTOCOL*), DevicePathCompare); PerformQuickSort(DevicePathList, Count, sizeof(EFI_DEVICE_PATH_PROTOCOL*), DevicePathCompare);
ShellCommandConsistMappingInitialize(&ConsistMappingTable); ShellCommandConsistMappingInitialize(&ConsistMappingTable);
// //
// Assign new Mappings to remainders // Assign new Mappings to remainders
// //
for (Count = 0 ; HandleList[Count] != NULL && !EFI_ERROR(Status); Count++) { for (Count = 0 ; HandleList[Count] != NULL && !EFI_ERROR(Status); Count++) {
// //
// Skip ones that already have // Skip ones that already have
// //
if (gEfiShellProtocol->GetMapFromDevicePath(&DevicePathList[Count]) != NULL) { if (gEfiShellProtocol->GetMapFromDevicePath(&DevicePathList[Count]) != NULL) {
continue; continue;
} }
// //
// Get default name // Get default name
// //
NewDefaultName = ShellCommandCreateNewMappingName(MappingTypeFileSystem); NewDefaultName = ShellCommandCreateNewMappingName(MappingTypeFileSystem);
ASSERT(NewDefaultName != NULL); ASSERT(NewDefaultName != NULL);
// //
// Call shell protocol SetMap function now... // Call shell protocol SetMap function now...
// //
Status = gEfiShellProtocol->SetMap(DevicePathList[Count], NewDefaultName); Status = gEfiShellProtocol->SetMap(DevicePathList[Count], NewDefaultName);
if (!EFI_ERROR(Status)) { if (!EFI_ERROR(Status)) {
// //
// Now do consistent name // Now do consistent name
// //
NewConsistName = ShellCommandConsistMappingGenMappingName(DevicePathList[Count], ConsistMappingTable); NewConsistName = ShellCommandConsistMappingGenMappingName(DevicePathList[Count], ConsistMappingTable);
if (NewConsistName != NULL) { if (NewConsistName != NULL) {
Status = gEfiShellProtocol->SetMap(DevicePathList[Count], NewConsistName); Status = gEfiShellProtocol->SetMap(DevicePathList[Count], NewConsistName);
FreePool(NewConsistName); FreePool(NewConsistName);
} }
} }
FreePool(NewDefaultName); FreePool(NewDefaultName);
} }
ShellCommandConsistMappingUnInitialize(ConsistMappingTable); ShellCommandConsistMappingUnInitialize(ConsistMappingTable);
SHELL_FREE_NON_NULL(HandleList); SHELL_FREE_NON_NULL(HandleList);
SHELL_FREE_NON_NULL(DevicePathList); SHELL_FREE_NON_NULL(DevicePathList);
HandleList = NULL; HandleList = NULL;
} else { } else {
Count = (UINTN)-1; Count = (UINTN)-1;
} }
// //
// Do it all over again for gEfiBlockIoProtocolGuid // Do it all over again for gEfiBlockIoProtocolGuid
// //
return (Status); return (Status);
} }
/** /**
Converts a SHELL_FILE_HANDLE to an EFI_FILE_PROTOCOL*. Converts a SHELL_FILE_HANDLE to an EFI_FILE_PROTOCOL*.
@param[in] Handle The SHELL_FILE_HANDLE to convert. @param[in] Handle The SHELL_FILE_HANDLE to convert.
@return a EFI_FILE_PROTOCOL* representing the same file. @return a EFI_FILE_PROTOCOL* representing the same file.
**/ **/

View File

@ -1,7 +1,7 @@
/** @file /** @file
Provides interface to shell internal functions for shell commands. Provides interface to shell internal functions for shell commands.
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved. <BR> Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved. <BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License 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 which accompanies this distribution. The full text of the license may be found at
@ -28,6 +28,7 @@
#include <Protocol/EfiShellParameters.h> #include <Protocol/EfiShellParameters.h>
#include <Protocol/UnicodeCollation.h> #include <Protocol/UnicodeCollation.h>
#include <Protocol/BlockIo.h> #include <Protocol/BlockIo.h>
#include <Protocol/EfiShellDynamicCommand.h>
#include <Library/DevicePathLib.h> #include <Library/DevicePathLib.h>
#include <Library/SortLib.h> #include <Library/SortLib.h>

View File

@ -1,7 +1,7 @@
## @file ## @file
# Provides interface to shell internal functions for shell commands. # Provides interface to shell internal functions for shell commands.
# #
# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved. <BR> # Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved. <BR>
# #
# This program and the accompanying materials # This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License # are licensed and made available under the terms and conditions of the BSD License
@ -52,6 +52,7 @@
gEfiUnicodeCollation2ProtocolGuid # ALWAYS_CONSUMED gEfiUnicodeCollation2ProtocolGuid # ALWAYS_CONSUMED
gEfiShellProtocolGuid # ALWAYS_CONSUMED gEfiShellProtocolGuid # ALWAYS_CONSUMED
gEfiShellParametersProtocolGuid # ALWAYS_CONSUMED gEfiShellParametersProtocolGuid # ALWAYS_CONSUMED
gEfiShellDynamicCommandProtocolGuid # SOMETIMES_CONSUMED
[Guids] [Guids]
gEfiSasDevicePathGuid # ALWAYS_CONSUMED gEfiSasDevicePathGuid # ALWAYS_CONSUMED