/** @file Main file for Dh shell Driver1 function. (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
(C) Copyright 2017 Hewlett Packard Enterprise Development LP
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ #include "UefiShellDriver1CommandsLib.h" STATIC CONST SHELL_PARAM_ITEM ParamList[] = { {L"-p", TypeValue}, {L"-d", TypeFlag}, {L"-v", TypeFlag}, {L"-verbose", TypeFlag}, {L"-sfo", TypeFlag}, {L"-l", TypeValue}, {NULL, TypeMax} }; STATIC CONST EFI_GUID *UefiDriverModelProtocolsGuidArray[] = { &gEfiDriverBindingProtocolGuid, &gEfiPlatformDriverOverrideProtocolGuid, &gEfiBusSpecificDriverOverrideProtocolGuid, &gEfiDriverDiagnosticsProtocolGuid, &gEfiDriverDiagnostics2ProtocolGuid, &gEfiComponentNameProtocolGuid, &gEfiComponentName2ProtocolGuid, &gEfiPlatformToDriverConfigurationProtocolGuid, &gEfiDriverSupportedEfiVersionProtocolGuid, &gEfiDriverFamilyOverrideProtocolGuid, &gEfiDriverHealthProtocolGuid, &gEfiLoadedImageProtocolGuid, NULL }; UINTN mGuidDataLen[] = {8, 4, 4, 4, 12}; /** Function to determine if the string can convert to a GUID. The string must be restricted as "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" format. @param[in] String The string to test. @retval TRUE The string can convert to a GUID. @retval FALSE The string can't convert to a GUID. **/ BOOLEAN IsValidGuidString( IN CONST CHAR16 *String ) { CONST CHAR16 *Walker; CONST CHAR16 *PrevWalker; UINTN Index; if (String == NULL) { return FALSE; } Walker = String; PrevWalker = String; Index = 0; while (Walker != NULL && *Walker != CHAR_NULL) { if ( (*Walker >= '0' && *Walker <= '9') || (*Walker >= 'a' && *Walker <= 'f') || (*Walker >= 'A' && *Walker <= 'F') ) { Walker++; } else { if (*Walker == L'-' && (((UINTN)Walker - (UINTN)PrevWalker) / sizeof (CHAR16)) == mGuidDataLen[Index]) { Walker++; PrevWalker = Walker; Index++; } else { return FALSE; } } } if ((((UINTN)Walker - (UINTN)PrevWalker) / sizeof (CHAR16)) == mGuidDataLen[Index]) { return TRUE; } else { return FALSE; } } /** Convert a hex-character to decimal value. This internal function only deal with Unicode character which maps to a valid hexadecimal ASII character, i.e. L'0' to L'9', L'a' to L'f' or L'A' to L'F'. For other Unicode character, the value returned does not make sense. @param[in] Char The character to convert. @retval The numerical value converted. **/ UINTN HexCharToDecimal( IN CHAR16 Char ) { if (Char >= '0' && Char <= '9') { return Char - L'0'; } else if (Char >= 'a' && Char <= 'f') { return Char - L'a' + 10; } else { return Char - L'A' + 10; } } /** Function try to convert a string to GUID format. @param[in] String The string will be converted. @param[out] Guid Save the result convert from string. @retval EFI_SUCCESS The string was successfully converted to a GUID. @retval EFI_UNSUPPORTED The input string is not in registry format. **/ EFI_STATUS ConvertStrToGuid( IN CONST CHAR16 *String, OUT GUID *Guid ) { CONST CHAR16 *Walker; UINT8 TempValue; UINTN Index; if (String == NULL || !IsValidGuidString (String)) { return EFI_UNSUPPORTED; } Index = 0; Walker = String; Guid->Data1 = (UINT32)StrHexToUint64 (Walker); Walker += 9; Guid->Data2 = (UINT16)StrHexToUint64 (Walker); Walker += 5; Guid->Data3 = (UINT16)StrHexToUint64 (Walker); Walker += 5; while (Walker != NULL && *Walker != CHAR_NULL) { if (*Walker == L'-') { Walker++; } else { TempValue = (UINT8)HexCharToDecimal (*Walker); TempValue = (UINT8)LShiftU64 (TempValue, 4); Walker++; TempValue += (UINT8)HexCharToDecimal (*Walker); Walker++; Guid->Data4[Index] = TempValue; Index++; } } return EFI_SUCCESS; } /** Get the name of a driver by it's handle. If a name is found the memory must be callee freed. @param[in] TheHandle The driver's handle. @param[in] Language The language to use. @param[in] NameFound Upon a successful return the name found. @retval EFI_SUCCESS The name was found. **/ EFI_STATUS GetDriverName ( IN EFI_HANDLE TheHandle, IN CONST CHAR8 *Language, IN CHAR16 **NameFound ) { CHAR8 *Lang; EFI_STATUS Status; EFI_COMPONENT_NAME2_PROTOCOL *CompName2; CHAR16 *NameToReturn; // // Go through those handles until we get one that passes for GetComponentName // Status = gBS->OpenProtocol( TheHandle, &gEfiComponentName2ProtocolGuid, (VOID**)&CompName2, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); if (EFI_ERROR(Status)) { Status = gBS->OpenProtocol( TheHandle, &gEfiComponentNameProtocolGuid, (VOID**)&CompName2, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); } if (EFI_ERROR(Status)) { return (EFI_NOT_FOUND); } Lang = GetBestLanguageForDriver (CompName2->SupportedLanguages, Language, FALSE); Status = CompName2->GetDriverName(CompName2, Lang, &NameToReturn); FreePool(Lang); if (!EFI_ERROR(Status) && NameToReturn != NULL) { *NameFound = NULL; StrnCatGrow(NameFound, NULL, NameToReturn, 0); } return (Status); } /** Discover if a protocol guid is one of the UEFI Driver Model Protocols. @param[in] Guid The guid to test. @retval TRUE The guid does represent a driver model protocol. @retval FALSE The guid does not represent a driver model protocol. **/ BOOLEAN IsDriverProt ( IN CONST EFI_GUID *Guid ) { CONST EFI_GUID **GuidWalker; BOOLEAN GuidFound; GuidFound = FALSE; for (GuidWalker = UefiDriverModelProtocolsGuidArray ; GuidWalker != NULL && *GuidWalker != NULL ; GuidWalker++ ){ if (CompareGuid(*GuidWalker, Guid)) { GuidFound = TRUE; break; } } return (GuidFound); } /** Get information for a handle. @param[in] TheHandle The handles to show info on. @param[in] Language Language string per UEFI specification. @param[in] Separator Separator string between information blocks. @param[in] Verbose TRUE for extra info, FALSE otherwise. @param[in] ExtraInfo TRUE for extra info, FALSE otherwise. @retval SHELL_SUCCESS The operation was successful. @retval SHELL_INVALID_PARAMETER ProtocolName was NULL or invalid. **/ CHAR16* GetProtocolInfoString( IN CONST EFI_HANDLE TheHandle, IN CONST CHAR8 *Language, IN CONST CHAR16 *Separator, IN CONST BOOLEAN Verbose, IN CONST BOOLEAN ExtraInfo ) { EFI_GUID **ProtocolGuidArray; UINTN ArrayCount; UINTN ProtocolIndex; EFI_STATUS Status; CHAR16 *RetVal; UINTN Size; CHAR16 *Temp; CHAR16 GuidStr[40]; VOID *Instance; CHAR16 InstanceStr[17]; ProtocolGuidArray = NULL; RetVal = NULL; Size = 0; Status = gBS->ProtocolsPerHandle ( TheHandle, &ProtocolGuidArray, &ArrayCount ); if (!EFI_ERROR (Status)) { for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) { Temp = GetStringNameFromGuid(ProtocolGuidArray[ProtocolIndex], Language); // ASSERT((RetVal == NULL && Size == 0) || (RetVal != NULL)); if (Size != 0) { StrnCatGrow(&RetVal, &Size, Separator, 0); } StrnCatGrow(&RetVal, &Size, L"%H", 0); if (Temp == NULL) { UnicodeSPrint (GuidStr, sizeof (GuidStr), L"%g", ProtocolGuidArray[ProtocolIndex]); StrnCatGrow (&RetVal, &Size, GuidStr, 0); } else { StrnCatGrow(&RetVal, &Size, Temp, 0); FreePool(Temp); } StrnCatGrow(&RetVal, &Size, L"%N", 0); if(Verbose) { Status = gBS->HandleProtocol (TheHandle, ProtocolGuidArray[ProtocolIndex], &Instance); if (!EFI_ERROR (Status)) { StrnCatGrow (&RetVal, &Size, L"(%H", 0); UnicodeSPrint (InstanceStr, sizeof (InstanceStr), L"%x", Instance); StrnCatGrow (&RetVal, &Size, InstanceStr, 0); StrnCatGrow (&RetVal, &Size, L"%N)", 0); } } if (ExtraInfo) { Temp = GetProtocolInformationDump(TheHandle, ProtocolGuidArray[ProtocolIndex], Verbose); if (Temp != NULL) { // ASSERT((RetVal == NULL && Size == 0) || (RetVal != NULL)); if (!Verbose) { StrnCatGrow(&RetVal, &Size, L"(", 0); StrnCatGrow(&RetVal, &Size, Temp, 0); StrnCatGrow(&RetVal, &Size, L")", 0); } else { StrnCatGrow(&RetVal, &Size, Separator, 0); StrnCatGrow(&RetVal, &Size, Temp, 0); } FreePool(Temp); } } } } SHELL_FREE_NON_NULL(ProtocolGuidArray); if (RetVal == NULL) { return (NULL); } // ASSERT((RetVal == NULL && Size == 0) || (RetVal != NULL)); StrnCatGrow(&RetVal, &Size, Separator, 0); return (RetVal); } /** Gets the name of the loaded image. @param[in] TheHandle The handle of the driver to get info on. @param[out] Name The pointer to the pointer. Valid upon a successful return. @retval EFI_SUCCESS The operation was successful. **/ EFI_STATUS GetDriverImageName ( IN EFI_HANDLE TheHandle, OUT CHAR16 **Name ) { // get loaded image and devicepathtotext on image->Filepath EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *DevicePath; if (TheHandle == NULL || Name == NULL) { return (EFI_INVALID_PARAMETER); } Status = gBS->OpenProtocol ( TheHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &LoadedImage, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR(Status)) { return (Status); } DevicePath = LoadedImage->FilePath; *Name = ConvertDevicePathToText(DevicePath, TRUE, TRUE); return (EFI_SUCCESS); } /** Display driver model information for a given handle. @param[in] Handle The handle to display info on. @param[in] BestName Use the best name? @param[in] Language The language to output in. **/ EFI_STATUS DisplayDriverModelHandle ( IN EFI_HANDLE Handle, IN BOOLEAN BestName, IN CONST CHAR8 *Language OPTIONAL ) { EFI_STATUS Status; BOOLEAN ConfigurationStatus; BOOLEAN DiagnosticsStatus; UINTN DriverBindingHandleCount; EFI_HANDLE *DriverBindingHandleBuffer; UINTN ParentControllerHandleCount; EFI_HANDLE *ParentControllerHandleBuffer; UINTN ChildControllerHandleCount; EFI_HANDLE *ChildControllerHandleBuffer; CHAR16 *TempStringPointer; EFI_DEVICE_PATH_PROTOCOL *DevicePath; UINTN Index; CHAR16 *DriverName; EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; UINTN NumberOfChildren; UINTN HandleIndex; UINTN ControllerHandleCount; EFI_HANDLE *ControllerHandleBuffer; UINTN ChildIndex; BOOLEAN Image; DriverName = NULL; // // See if Handle is a device handle and display its details. // DriverBindingHandleBuffer = NULL; /*Status = */PARSE_HANDLE_DATABASE_UEFI_DRIVERS ( Handle, &DriverBindingHandleCount, &DriverBindingHandleBuffer ); ParentControllerHandleBuffer = NULL; /*Status = */PARSE_HANDLE_DATABASE_PARENTS ( Handle, &ParentControllerHandleCount, &ParentControllerHandleBuffer ); ChildControllerHandleBuffer = NULL; /*Status = */ParseHandleDatabaseForChildControllers ( Handle, &ChildControllerHandleCount, &ChildControllerHandleBuffer ); DiagnosticsStatus = FALSE; ConfigurationStatus = FALSE; if (!EFI_ERROR(gBS->OpenProtocol(Handle, &gEfiDriverConfigurationProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) { ConfigurationStatus = TRUE; } if (!EFI_ERROR(gBS->OpenProtocol(Handle, &gEfiDriverConfiguration2ProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) { ConfigurationStatus = TRUE; } if (!EFI_ERROR(gBS->OpenProtocol(Handle, &gEfiDriverDiagnosticsProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) { DiagnosticsStatus = TRUE; } if (!EFI_ERROR(gBS->OpenProtocol(Handle, &gEfiDriverDiagnostics2ProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) { DiagnosticsStatus = TRUE; } Status = EFI_SUCCESS; if (DriverBindingHandleCount > 0 || ParentControllerHandleCount > 0 || ChildControllerHandleCount > 0) { DevicePath = NULL; TempStringPointer = NULL; /*Status = */gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID**)&DevicePath); Status = gEfiShellProtocol->GetDeviceName(Handle, EFI_DEVICE_NAME_USE_COMPONENT_NAME|EFI_DEVICE_NAME_USE_DEVICE_PATH, (CHAR8*)Language, &TempStringPointer); ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_DRIVER1), gShellDriver1HiiHandle, TempStringPointer!=NULL?TempStringPointer:L""); SHELL_FREE_NON_NULL(TempStringPointer); TempStringPointer = ConvertDevicePathToText(DevicePath, TRUE, FALSE); ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_DRIVER2), gShellDriver1HiiHandle, TempStringPointer!=NULL?TempStringPointer:L"", ParentControllerHandleCount == 0?L"ROOT":(ChildControllerHandleCount > 0)?L"BUS":L"DEVICE", ConfigurationStatus?L"YES":L"NO", DiagnosticsStatus?L"YES":L"NO" ); SHELL_FREE_NON_NULL(TempStringPointer); if (DriverBindingHandleCount == 0) { ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_DRIVER3), gShellDriver1HiiHandle, L"" ); } else { ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_DRIVER3), gShellDriver1HiiHandle, L"" ); for (Index = 0; Index < DriverBindingHandleCount; Index++) { Image = FALSE; Status = GetDriverName ( DriverBindingHandleBuffer[Index], Language, &DriverName ); if (EFI_ERROR (Status)) { Status = GetDriverImageName ( DriverBindingHandleBuffer[Index], &DriverName ); if (EFI_ERROR (Status)) { DriverName = NULL; } } if (Image) { ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_DRIVER4A), gShellDriver1HiiHandle, ConvertHandleToHandleIndex (DriverBindingHandleBuffer[Index]), DriverName!=NULL?DriverName:L"" ); } else { ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_DRIVER4B), gShellDriver1HiiHandle, ConvertHandleToHandleIndex (DriverBindingHandleBuffer[Index]), DriverName!=NULL?DriverName:L"" ); } SHELL_FREE_NON_NULL(DriverName); } } if (ParentControllerHandleCount == 0) { ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_DRIVER5), gShellDriver1HiiHandle, L"" ); } else { ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_DRIVER5), gShellDriver1HiiHandle, L"" ); for (Index = 0; Index < ParentControllerHandleCount; Index++) { Status = gEfiShellProtocol->GetDeviceName(ParentControllerHandleBuffer[Index], EFI_DEVICE_NAME_USE_COMPONENT_NAME|EFI_DEVICE_NAME_USE_DEVICE_PATH, (CHAR8*)Language, &TempStringPointer); ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_DRIVER5B), gShellDriver1HiiHandle, ConvertHandleToHandleIndex (ParentControllerHandleBuffer[Index]), TempStringPointer!=NULL?TempStringPointer:L"" ); SHELL_FREE_NON_NULL(TempStringPointer); } } if (ChildControllerHandleCount == 0) { ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_DRIVER6), gShellDriver1HiiHandle, L"" ); } else { ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_DRIVER6), gShellDriver1HiiHandle, L"" ); for (Index = 0; Index < ChildControllerHandleCount; Index++) { Status = gEfiShellProtocol->GetDeviceName(ChildControllerHandleBuffer[Index], EFI_DEVICE_NAME_USE_COMPONENT_NAME|EFI_DEVICE_NAME_USE_DEVICE_PATH, (CHAR8*)Language, &TempStringPointer); ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_DRIVER6B), gShellDriver1HiiHandle, ConvertHandleToHandleIndex (ChildControllerHandleBuffer[Index]), TempStringPointer!=NULL?TempStringPointer:L"" ); SHELL_FREE_NON_NULL(TempStringPointer); } } } SHELL_FREE_NON_NULL(DriverBindingHandleBuffer); SHELL_FREE_NON_NULL(ParentControllerHandleBuffer); SHELL_FREE_NON_NULL(ChildControllerHandleBuffer); if (EFI_ERROR (Status)) { return Status; } // // See if Handle is a driver binding handle and display its details. // Status = gBS->OpenProtocol ( Handle, &gEfiDriverBindingProtocolGuid, (VOID **) &DriverBinding, NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { return EFI_SUCCESS; } NumberOfChildren = 0; ControllerHandleBuffer = NULL; Status = PARSE_HANDLE_DATABASE_DEVICES ( Handle, &ControllerHandleCount, &ControllerHandleBuffer ); if (ControllerHandleCount > 0) { for (HandleIndex = 0; HandleIndex < ControllerHandleCount; HandleIndex++) { Status = PARSE_HANDLE_DATABASE_MANAGED_CHILDREN ( Handle, ControllerHandleBuffer[HandleIndex], &ChildControllerHandleCount, NULL ); NumberOfChildren += ChildControllerHandleCount; } } Status = GetDriverName (Handle, Language, &DriverName); if (EFI_ERROR (Status)) { DriverName = NULL; } ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_DRIVER7), gShellDriver1HiiHandle, ConvertHandleToHandleIndex(Handle), DriverName!=NULL?DriverName:L"" ); SHELL_FREE_NON_NULL(DriverName); Status = GetDriverImageName ( Handle, &DriverName ); if (EFI_ERROR (Status)) { DriverName = NULL; } ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_DRIVER7B), gShellDriver1HiiHandle, DriverName!=NULL?DriverName:L"" ); SHELL_FREE_NON_NULL(DriverName); ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_DRIVER8), gShellDriver1HiiHandle, DriverBinding->Version, NumberOfChildren > 0?L"Bus":ControllerHandleCount > 0?L"Device":L"", ConfigurationStatus?L"YES":L"NO", DiagnosticsStatus?L"YES":L"NO" ); if (ControllerHandleCount == 0) { ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_DRIVER9), gShellDriver1HiiHandle, L"None" ); } else { ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_DRIVER9), gShellDriver1HiiHandle, L"" ); for (HandleIndex = 0; HandleIndex < ControllerHandleCount; HandleIndex++) { /*Status = */ gEfiShellProtocol->GetDeviceName(ControllerHandleBuffer[HandleIndex], EFI_DEVICE_NAME_USE_COMPONENT_NAME|EFI_DEVICE_NAME_USE_DEVICE_PATH, (CHAR8*)Language, &TempStringPointer); ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_DRIVER9B), gShellDriver1HiiHandle, ConvertHandleToHandleIndex(ControllerHandleBuffer[HandleIndex]), TempStringPointer!=NULL?TempStringPointer:L"" ); SHELL_FREE_NON_NULL(TempStringPointer); Status = PARSE_HANDLE_DATABASE_MANAGED_CHILDREN ( Handle, ControllerHandleBuffer[HandleIndex], &ChildControllerHandleCount, &ChildControllerHandleBuffer ); if (!EFI_ERROR (Status)) { for (ChildIndex = 0; ChildIndex < ChildControllerHandleCount; ChildIndex++) { Status = gEfiShellProtocol->GetDeviceName(ChildControllerHandleBuffer[ChildIndex], EFI_DEVICE_NAME_USE_COMPONENT_NAME|EFI_DEVICE_NAME_USE_DEVICE_PATH, (CHAR8*)Language, &TempStringPointer); ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_DRIVER6C), gShellDriver1HiiHandle, ConvertHandleToHandleIndex(ChildControllerHandleBuffer[ChildIndex]), TempStringPointer!=NULL?TempStringPointer:L"" ); SHELL_FREE_NON_NULL(TempStringPointer); } SHELL_FREE_NON_NULL (ChildControllerHandleBuffer); } } SHELL_FREE_NON_NULL (ControllerHandleBuffer); } return EFI_SUCCESS; } /** Display information for a handle. @param[in] TheHandle The handles to show info on. @param[in] Verbose TRUE for extra info, FALSE otherwise. @param[in] Sfo TRUE to output in standard format output (spec). @param[in] Language Language string per UEFI specification. @param[in] DriverInfo TRUE to show all info about the handle. @param[in] Multiple TRUE indicates more than will be output, FALSE for a single one. **/ VOID DoDhByHandle( IN CONST EFI_HANDLE TheHandle, IN CONST BOOLEAN Verbose, IN CONST BOOLEAN Sfo, IN CONST CHAR8 *Language, IN CONST BOOLEAN DriverInfo, IN CONST BOOLEAN Multiple ) { CHAR16 *ProtocolInfoString; ProtocolInfoString = NULL; if (!Sfo) { if (Multiple) { ProtocolInfoString = GetProtocolInfoString(TheHandle, Language, L" ", Verbose, TRUE); ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT), gShellDriver1HiiHandle, ConvertHandleToHandleIndex(TheHandle), ProtocolInfoString==NULL?L"":ProtocolInfoString ); } else { ProtocolInfoString = GetProtocolInfoString(TheHandle, Language, Verbose ? L"\r\n" : L" ", Verbose, TRUE); if (Verbose) { ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_SINGLE), gShellDriver1HiiHandle, ConvertHandleToHandleIndex(TheHandle), TheHandle, ProtocolInfoString==NULL?L"":ProtocolInfoString ); } else { ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_SINGLE_D), gShellDriver1HiiHandle, ConvertHandleToHandleIndex(TheHandle), ProtocolInfoString==NULL?L"":ProtocolInfoString ); } } if (DriverInfo) { DisplayDriverModelHandle ((EFI_HANDLE)TheHandle, TRUE, Language); } } else { ProtocolInfoString = GetProtocolInfoString(TheHandle, Language, L";", FALSE, FALSE); ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_SFO), gShellDriver1HiiHandle, Multiple ?L"HandlesInfo":L"HandleInfo", L"DriverName", L"ControllerName", ConvertHandleToHandleIndex(TheHandle), L"DevPath", ProtocolInfoString==NULL?L"":ProtocolInfoString ); } if (ProtocolInfoString != NULL) { FreePool(ProtocolInfoString); } } /** Display information for all handles on a list. @param[in] HandleList The NULL-terminated list of handles. @param[in] Verbose TRUE for extra info, FALSE otherwise. @param[in] Sfo TRUE to output in standard format output (spec). @param[in] Language Language string per UEFI specification. @param[in] DriverInfo TRUE to show all info about the handle. @retval SHELL_SUCCESS The operation was successful. @retval SHELL_ABORTED The operation was aborted. **/ SHELL_STATUS DoDhForHandleList( IN CONST EFI_HANDLE *HandleList, IN CONST BOOLEAN Verbose, IN CONST BOOLEAN Sfo, IN CONST CHAR8 *Language, IN CONST BOOLEAN DriverInfo ) { CONST EFI_HANDLE *HandleWalker; SHELL_STATUS ShellStatus; ShellStatus = SHELL_SUCCESS; for (HandleWalker = HandleList; HandleWalker != NULL && *HandleWalker != NULL; HandleWalker++) { DoDhByHandle (*HandleWalker, Verbose, Sfo, Language, DriverInfo, TRUE); if (ShellGetExecutionBreakFlag ()) { ShellStatus = SHELL_ABORTED; break; } } return (ShellStatus); } /** Display information for a GUID of protocol. @param[in] Guid The pointer to the name of the protocol. @param[in] Verbose TRUE for extra info, FALSE otherwise. @param[in] Sfo TRUE to output in standard format output (spec). @param[in] Language Language string per UEFI specification. @param[in] DriverInfo TRUE to show all info about the handle. @retval SHELL_SUCCESS The operation was successful. @retval SHELL_NOT_FOUND The GUID was not found. @retval SHELL_INVALID_PARAMETER ProtocolName was NULL or invalid. **/ SHELL_STATUS DoDhByProtocolGuid( IN CONST GUID *Guid, IN CONST BOOLEAN Verbose, IN CONST BOOLEAN Sfo, IN CONST CHAR8 *Language, IN CONST BOOLEAN DriverInfo ) { CHAR16 *Name; SHELL_STATUS ShellStatus; EFI_HANDLE *HandleList; if (!Sfo) { if (Guid == NULL) { ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_ALL_HEADER), gShellDriver1HiiHandle); } else { Name = GetStringNameFromGuid (Guid, NULL); if (Name == NULL) { ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_GUID_HEADER), gShellDriver1HiiHandle, Guid); } else { ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_NAME_HEADER), gShellDriver1HiiHandle, Name); } } } HandleList = GetHandleListByProtocol(Guid); ShellStatus = DoDhForHandleList(HandleList, Verbose, Sfo, Language, DriverInfo); SHELL_FREE_NON_NULL(HandleList); return ShellStatus; } /** Function to determine use which method to print information. If Protocol is NULL, The function will print all information. @param[in] Protocol The pointer to the name or GUID of protocol or NULL. @param[in] Verbose TRUE for extra info, FALSE otherwise. @param[in] Sfo TRUE to output in standard format output (spec). @param[in] Language Language string per UEFI specification. @param[in] DriverInfo TRUE to show all info about the handle. @retval SHELL_SUCCESS The operation was successful. @retval SHELL_NOT_FOUND The protocol was not found. @retval SHELL_INVALID_PARAMETER Protocol is invalid parameter. **/ SHELL_STATUS DoDhByProtocol ( IN CONST CHAR16 *Protocol, IN CONST BOOLEAN Verbose, IN CONST BOOLEAN Sfo, IN CONST CHAR8 *Language, IN CONST BOOLEAN DriverInfo ) { EFI_GUID Guid; EFI_GUID *GuidPtr; EFI_STATUS Status; if (Protocol == NULL) { return DoDhByProtocolGuid (NULL, Verbose, Sfo, Language, DriverInfo); } else { Status = ConvertStrToGuid (Protocol, &Guid); if (!EFI_ERROR (Status)) { GuidPtr = &Guid; } else { // // Protocol is a Name, convert it to GUID // Status = GetGuidFromStringName (Protocol, Language, &GuidPtr); if (EFI_ERROR(Status)) { ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DH_NO_NAME_FOUND), gShellDriver1HiiHandle, Protocol); return (SHELL_NOT_FOUND); } } return DoDhByProtocolGuid (GuidPtr, Verbose, Sfo, Language, DriverInfo); } } /** Function to display decode information by Protocol. The parameter Protocol is either a GUID or the name of protocol. If the parameter Protocol is NULL, the function will print all decode information. @param[in] Protocol The pointer to the name or GUID of protocol. @param[in] Language Language string per UEFI specification. @retval SHELL_SUCCESS The operation was successful. @retval SHELL_OUT_OT_RESOURCES A memory allocation failed. **/ SHELL_STATUS DoDecodeByProtocol( IN CONST CHAR16 *Protocol, IN CONST CHAR8 *Language ) { EFI_STATUS Status; EFI_GUID *Guids; EFI_GUID Guid; UINTN Counts; UINTN Index; CHAR16 *Name; if (Protocol == NULL) { Counts = 0; Status = GetAllMappingGuids (NULL, &Counts); if (Status == EFI_BUFFER_TOO_SMALL) { Guids = AllocatePool (Counts * sizeof(EFI_GUID)); if (Guids == NULL) { return SHELL_OUT_OF_RESOURCES; } Status = GetAllMappingGuids (Guids, &Counts); if (Status == EFI_SUCCESS) { for (Index = 0; Index < Counts; Index++) { Name = GetStringNameFromGuid (&Guids[Index], Language); if (Name != NULL) { ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_DECODE), gShellDriver1HiiHandle, Name, &Guids[Index]); } else { ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DH_NO_GUID_FOUND), gShellDriver1HiiHandle, &Guids[Index]); } SHELL_FREE_NON_NULL (Name); } } FreePool (Guids); } } else { if (ConvertStrToGuid (Protocol, &Guid) == EFI_SUCCESS) { Name = GetStringNameFromGuid (&Guid, Language); if (Name != NULL) { ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_DECODE), gShellDriver1HiiHandle, Name, &Guid); } else { ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DH_NO_GUID_FOUND), gShellDriver1HiiHandle, &Guid); } SHELL_FREE_NON_NULL(Name); } else { Status = GetGuidFromStringName (Protocol, Language, &Guids); if (Status == EFI_SUCCESS) { ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_DECODE), gShellDriver1HiiHandle, Protocol, Guids); } else { ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DH_NO_NAME_FOUND), gShellDriver1HiiHandle, Protocol); } } } return SHELL_SUCCESS; } /** Function for 'dh' command. @param[in] ImageHandle Handle to the Image (NULL if Internal). @param[in] SystemTable Pointer to the System Table (NULL if Internal). **/ SHELL_STATUS EFIAPI ShellCommandRunDh ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; LIST_ENTRY *Package; CHAR16 *ProblemParam; SHELL_STATUS ShellStatus; CHAR8 *Language; CONST CHAR16 *Lang; CONST CHAR16 *RawValue; CONST CHAR16 *ProtocolVal; BOOLEAN SfoFlag; BOOLEAN DriverFlag; BOOLEAN VerboseFlag; UINT64 Intermediate; EFI_HANDLE Handle; ShellStatus = SHELL_SUCCESS; // Status = EFI_SUCCESS; Language = NULL; // // initialize the shell lib (we must be in non-auto-init...) // Status = ShellInitialize(); // ASSERT_EFI_ERROR(Status); if (EFI_ERROR(Status)) { return Status; } Status = CommandInit(); // ASSERT_EFI_ERROR(Status); if (EFI_ERROR(Status)) { return Status; } // // parse the command line // Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); if (EFI_ERROR(Status)) { if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"dh", ProblemParam); FreePool(ProblemParam); ShellStatus = SHELL_INVALID_PARAMETER; }/* else { ASSERT(FALSE); } */ } else { if (ShellCommandLineGetCount(Package) > 2) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"dh"); ShellCommandLineFreeVarList (Package); return (SHELL_INVALID_PARAMETER); } if (ShellCommandLineGetFlag(Package, L"-l")) { Lang = ShellCommandLineGetValue(Package, L"-l"); if (Lang != NULL) { Language = AllocateZeroPool(StrSize(Lang)); AsciiSPrint(Language, StrSize(Lang), "%S", Lang); } else { ASSERT(Language == NULL); ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"dh", L"-l"); ShellCommandLineFreeVarList(Package); return (SHELL_INVALID_PARAMETER); } } else { Language = AllocateZeroPool(10); AsciiSPrint(Language, 10, "en-us"); } SfoFlag = ShellCommandLineGetFlag (Package, L"-sfo"); DriverFlag = ShellCommandLineGetFlag (Package, L"-d"); VerboseFlag = (BOOLEAN)(ShellCommandLineGetFlag (Package, L"-v") || ShellCommandLineGetFlag (Package, L"-verbose")); RawValue = ShellCommandLineGetRawValue (Package, 1); ProtocolVal = ShellCommandLineGetValue (Package, L"-p"); if (RawValue == NULL) { if (ShellCommandLineGetFlag (Package, L"-p") && (ProtocolVal == NULL)) { ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"dh", L"-p"); ShellStatus = SHELL_INVALID_PARAMETER; } else { // // Print information by protocol, The ProtocolVal maybe is name or GUID or NULL. // ShellStatus = DoDhByProtocol (ProtocolVal, VerboseFlag, SfoFlag, Language, DriverFlag); } } else if ((RawValue != NULL) && (gUnicodeCollation->StriColl(gUnicodeCollation, L"decode", (CHAR16 *) RawValue) == 0)) { if (ShellCommandLineGetFlag (Package, L"-p") && (ProtocolVal == NULL)) { ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"dh", L"-p"); ShellStatus = SHELL_INVALID_PARAMETER; } else { // // Print decode informatino by protocol. // ShellStatus = DoDecodeByProtocol (ProtocolVal, Language); } } else { if (ShellCommandLineGetFlag (Package, L"-p")) { ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"dh"); ShellStatus = SHELL_INVALID_PARAMETER; } else { Status = ShellConvertStringToUint64 (RawValue, &Intermediate, TRUE, FALSE); if (EFI_ERROR(Status)) { ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"dh", RawValue); ShellStatus = SHELL_INVALID_PARAMETER; } else { Handle = ConvertHandleIndexToHandle ((UINTN) Intermediate); if (Handle == NULL) { ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"dh", RawValue); ShellStatus = SHELL_INVALID_PARAMETER; } else { // // Print information by handle. // DoDhByHandle (Handle, VerboseFlag, SfoFlag, Language, DriverFlag, FALSE); } } } } ShellCommandLineFreeVarList (Package); SHELL_FREE_NON_NULL(Language); } return (ShellStatus); }