/** @file Main file for Drivers shell Driver1 function. (C) Copyright 2012-2015 Hewlett-Packard Development Company, L.P.
Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "UefiShellDriver1CommandsLib.h" #define MAX_LEN_DRIVER_NAME 35 STATIC CONST SHELL_PARAM_ITEM ParamList[] = { { L"-sfo", TypeFlag }, { L"-l", TypeValue }, { NULL, TypeMax } }; /** Get a device path (in text format) for a given handle. @param[in] TheHandle The handle to get the device path for. @retval NULL An error occurred. @return A pointer to the driver path as a string. The callee must free this memory. **/ CHAR16 * GetDevicePathTextForHandle ( IN EFI_HANDLE TheHandle ) { EFI_STATUS Status; EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath; EFI_DEVICE_PATH_PROTOCOL *FinalPath; CHAR16 *RetVal; FinalPath = NULL; Status = gBS->OpenProtocol ( TheHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&LoadedImage, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (!EFI_ERROR (Status)) { Status = gBS->OpenProtocol ( LoadedImage->DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&ImageDevicePath, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (!EFI_ERROR (Status)) { FinalPath = AppendDevicePath (ImageDevicePath, LoadedImage->FilePath); gBS->CloseProtocol ( LoadedImage->DeviceHandle, &gEfiDevicePathProtocolGuid, gImageHandle, NULL ); } gBS->CloseProtocol ( TheHandle, &gEfiLoadedImageProtocolGuid, gImageHandle, NULL ); } if (FinalPath == NULL) { return (NULL); } RetVal = gEfiShellProtocol->GetFilePathFromDevicePath (FinalPath); if (RetVal == NULL) { RetVal = ConvertDevicePathToText (FinalPath, TRUE, TRUE); } FreePool (FinalPath); return (RetVal); } /** Determine if the given handle has Driver Configuration protocol. @param[in] TheHandle The handle to the driver to test. @retval TRUE The driver does have Driver Configuration. @retval FALSE The driver does not have Driver Configuration. **/ BOOLEAN ReturnDriverConfig ( IN CONST EFI_HANDLE TheHandle ) { EFI_STATUS Status; Status = gBS->OpenProtocol ((EFI_HANDLE)TheHandle, &gEfiDriverConfigurationProtocolGuid, NULL, gImageHandle, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL); if (EFI_ERROR (Status)) { return (FALSE); } return (TRUE); } /** Determine if the given handle has DriverDiagnostics protocol. @param[in] TheHandle The handle to the driver to test. @retval TRUE The driver does have Driver Diasgnostics. @retval FALSE The driver does not have Driver Diagnostics. **/ BOOLEAN ReturnDriverDiag ( IN CONST EFI_HANDLE TheHandle ) { EFI_STATUS Status; Status = gBS->OpenProtocol ((EFI_HANDLE)TheHandle, &gEfiDriverDiagnostics2ProtocolGuid, NULL, gImageHandle, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL); if (EFI_ERROR (Status)) { Status = gBS->OpenProtocol ((EFI_HANDLE)TheHandle, &gEfiDriverDiagnosticsProtocolGuid, NULL, gImageHandle, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL); if (EFI_ERROR (Status)) { return (FALSE); } } return (TRUE); } /** Finds and returns the version of the driver specified by TheHandle. @param[in] TheHandle The driver handle to get the version of. @return The version of the driver. @retval 0xFFFFFFFF An error ocurred. **/ UINT32 ReturnDriverVersion ( IN CONST EFI_HANDLE TheHandle ) { EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; EFI_STATUS Status; UINT32 RetVal; RetVal = (UINT32)-1; Status = gBS->OpenProtocol ((EFI_HANDLE)TheHandle, &gEfiDriverBindingProtocolGuid, (VOID **)&DriverBinding, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); if (!EFI_ERROR (Status)) { RetVal = DriverBinding->Version; gBS->CloseProtocol (TheHandle, &gEfiDriverBindingProtocolGuid, gImageHandle, NULL); } return (RetVal); } /** Get image name from Image Handle. @param[in] Handle Image Handle @return A pointer to the image name as a string. **/ CHAR16 * GetImageNameFromHandle ( IN CONST EFI_HANDLE Handle ) { EFI_STATUS Status; EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; EFI_DEVICE_PATH_PROTOCOL *DevPathNode; EFI_GUID *NameGuid; CHAR16 *ImageName; UINTN BufferSize; UINT32 AuthenticationStatus; EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv2; LoadedImage = NULL; DriverBinding = NULL; ImageName = NULL; Status = gBS->OpenProtocol ( Handle, &gEfiDriverBindingProtocolGuid, (VOID **)&DriverBinding, NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { return NULL; } Status = gBS->OpenProtocol ( DriverBinding->ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&LoadedImage, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (!EFI_ERROR (Status)) { DevPathNode = LoadedImage->FilePath; if (DevPathNode == NULL) { return NULL; } while (!IsDevicePathEnd (DevPathNode)) { NameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)DevPathNode); if (NameGuid != NULL) { Status = gBS->HandleProtocol ( LoadedImage->DeviceHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv2 ); if (!EFI_ERROR (Status)) { Status = Fv2->ReadSection ( Fv2, NameGuid, EFI_SECTION_USER_INTERFACE, 0, (VOID **)&ImageName, &BufferSize, &AuthenticationStatus ); if (!EFI_ERROR (Status)) { break; } ImageName = NULL; } } // // Next device path node // DevPathNode = NextDevicePathNode (DevPathNode); } if (ImageName == NULL) { ImageName = ConvertDevicePathToText (LoadedImage->FilePath, TRUE, TRUE); } } return ImageName; } /** Function for 'drivers' 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 ShellCommandRunDrivers ( 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; EFI_HANDLE *HandleList; EFI_HANDLE *HandleWalker; UINTN ChildCount; UINTN DeviceCount; CHAR16 ChildCountStr[21]; CHAR16 DeviceCountStr[21]; CHAR16 *Temp2; CONST CHAR16 *FullDriverName; CHAR16 *TruncatedDriverName; CHAR16 *ImageName; CHAR16 *FormatString; UINT32 DriverVersion; BOOLEAN DriverConfig; BOOLEAN DriverDiag; BOOLEAN SfoFlag; ShellStatus = SHELL_SUCCESS; Status = EFI_SUCCESS; Language = NULL; FormatString = NULL; SfoFlag = FALSE; // // initialize the shell lib (we must be in non-auto-init...) // Status = ShellInitialize (); ASSERT_EFI_ERROR (Status); Status = CommandInit (); ASSERT_EFI_ERROR (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"drivers", ProblemParam); FreePool (ProblemParam); ShellStatus = SHELL_INVALID_PARAMETER; } else { ASSERT (FALSE); } } else { if (ShellCommandLineGetCount (Package) > 1) { ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"drivers"); ShellStatus = SHELL_INVALID_PARAMETER; } else { 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"drivers", L"-l"); ShellCommandLineFreeVarList (Package); return (SHELL_INVALID_PARAMETER); } } if (ShellCommandLineGetFlag (Package, L"-sfo")) { SfoFlag = TRUE; FormatString = HiiGetString (gShellDriver1HiiHandle, STRING_TOKEN (STR_DRIVERS_ITEM_LINE_SFO), Language); // // print the SFO header // ShellPrintHiiEx ( -1, -1, Language, STRING_TOKEN (STR_GEN_SFO_HEADER), gShellDriver1HiiHandle, L"drivers" ); } else { FormatString = HiiGetString (gShellDriver1HiiHandle, STRING_TOKEN (STR_DRIVERS_ITEM_LINE), Language); // // print the header row // ShellPrintHiiEx ( -1, -1, Language, STRING_TOKEN (STR_DRIVERS_HEADER_LINES), gShellDriver1HiiHandle ); } HandleList = GetHandleListByProtocol (&gEfiDriverBindingProtocolGuid); for (HandleWalker = HandleList; HandleWalker != NULL && *HandleWalker != NULL; HandleWalker++) { ChildCount = 0; DeviceCount = 0; Status = ParseHandleDatabaseForChildDevices (*HandleWalker, &ChildCount, NULL); Status = PARSE_HANDLE_DATABASE_DEVICES (*HandleWalker, &DeviceCount, NULL); Temp2 = GetDevicePathTextForHandle (*HandleWalker); DriverVersion = ReturnDriverVersion (*HandleWalker); DriverConfig = ReturnDriverConfig (*HandleWalker); DriverDiag = ReturnDriverDiag (*HandleWalker); FullDriverName = GetStringNameFromHandle (*HandleWalker, Language); ImageName = GetImageNameFromHandle (*HandleWalker); UnicodeValueToStringS (ChildCountStr, sizeof (ChildCountStr), 0, ChildCount, 0); UnicodeValueToStringS (DeviceCountStr, sizeof (DeviceCountStr), 0, DeviceCount, 0); TruncatedDriverName = NULL; if (!SfoFlag && (FullDriverName != NULL)) { TruncatedDriverName = AllocateZeroPool ((MAX_LEN_DRIVER_NAME + 1) * sizeof (CHAR16)); StrnCpyS (TruncatedDriverName, MAX_LEN_DRIVER_NAME + 1, FullDriverName, MAX_LEN_DRIVER_NAME); } if (!SfoFlag) { ShellPrintEx ( -1, -1, FormatString, ConvertHandleToHandleIndex (*HandleWalker), DriverVersion, ChildCount > 0 ? L'B' : (DeviceCount > 0 ? L'D' : L'?'), DriverConfig ? L'X' : L'-', DriverDiag ? L'X' : L'-', DeviceCount > 0 ? DeviceCountStr : L"-", ChildCount > 0 ? ChildCountStr : L"-", TruncatedDriverName, ImageName == NULL ? L"" : ImageName ); } else { ShellPrintEx ( -1, -1, FormatString, ConvertHandleToHandleIndex (*HandleWalker), DriverVersion, ChildCount > 0 ? L'B' : (DeviceCount > 0 ? L'D' : L'?'), DriverConfig ? L'Y' : L'N', DriverDiag ? L'Y' : L'N', DeviceCount, ChildCount, FullDriverName, Temp2 == NULL ? L"" : Temp2 ); } if (TruncatedDriverName != NULL) { FreePool (TruncatedDriverName); } if (Temp2 != NULL) { FreePool (Temp2); } if (ImageName != NULL) { FreePool (ImageName); } if (ShellGetExecutionBreakFlag ()) { ShellStatus = SHELL_ABORTED; break; } } } SHELL_FREE_NON_NULL (Language); ShellCommandLineFreeVarList (Package); SHELL_FREE_NON_NULL (FormatString); } return (ShellStatus); }