summaryrefslogtreecommitdiff
path: root/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c
diff options
context:
space:
mode:
Diffstat (limited to 'ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c')
-rw-r--r--ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c381
1 files changed, 266 insertions, 115 deletions
diff --git a/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c b/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c
index 18ae9f3384..ef5acd7da8 100644
--- a/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c
+++ b/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c
@@ -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
)
{
@@ -292,6 +403,31 @@ ShellCommandGetCommandHelp (
}
/**
+ 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.
**/