/** @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 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)) {
      ShellPrintHiiDefaultEx (STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"drivers", ProblemParam);
      FreePool (ProblemParam);
      ShellStatus = SHELL_INVALID_PARAMETER;
    } else {
      ASSERT (FALSE);
    }
  } else {
    if (ShellCommandLineGetCount (Package) > 1) {
      ShellPrintHiiDefaultEx (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));
          if (Language == NULL) {
            ShellPrintHiiDefaultEx (STRING_TOKEN (STR_GEN_OUT_MEM), gShellDriver1HiiHandle, L"drivers");
            ShellCommandLineFreeVarList (Package);
            return (SHELL_OUT_OF_RESOURCES);
          }

          AsciiSPrint (Language, StrSize (Lang), "%S", Lang);
        } else {
          ASSERT (Language == NULL);
          ShellPrintHiiDefaultEx (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
          );
      }

      if (FormatString == NULL) {
        // Assume the string is present because it is hard-coded and report out of memory
        ShellPrintHiiDefaultEx (STRING_TOKEN (STR_GEN_OUT_MEM), gShellDriver1HiiHandle, L"drivers");
        ShellCommandLineFreeVarList (Package);
        return (SHELL_OUT_OF_RESOURCES);
      }

      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));
          if (TruncatedDriverName == NULL) {
            ShellPrintHiiDefaultEx (STRING_TOKEN (STR_GEN_OUT_MEM), gShellDriver1HiiHandle, L"drivers");
            ShellCommandLineFreeVarList (Package);
            return (SHELL_OUT_OF_RESOURCES);
          }

          StrnCpyS (TruncatedDriverName, MAX_LEN_DRIVER_NAME + 1, FullDriverName, MAX_LEN_DRIVER_NAME);
        }

        if (!SfoFlag) {
          ShellPrintDefaultEx (
            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 {
          ShellPrintDefaultEx (
            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);
}
