REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1941 The two CHAR16 array ChildCountStr and DeviceCountStr is defined to hold the decimal string data of UINTN. The max of UINTN is 18446744073709551615 and it contain 20 characters. So make their size to 21 CHAR16s to hold the string data with a null-terminate. UnicodeValueToStringS regard the value input as INT64, and 21 CHARs is enough to hold the lowest value with minus '-'. Although the value shouldn't be such big. Cc: Jaben Carsey <jaben.carsey@intel.com> Cc: Ray Ni <ray.ni@intel.com> Cc: Oleksiy <oleksiyy@ami.com> Signed-off-by: Zhichao Gao <zhichao.gao@intel.com> Reviewed-by: Linson Augustine <Linson.augustine@intel.com> Reviewed-by: Jaben Carsey <jaben.carsey@intel.com>
		
			
				
	
	
		
			424 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			424 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Main file for Drivers shell Driver1 function.
 | 
						|
 | 
						|
  (C) Copyright 2012-2015 Hewlett-Packard Development Company, L.P.<BR>
 | 
						|
  Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
 | 
						|
  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);
 | 
						|
}
 |