/** @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 occured. @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); }