/** @file
  This module produces two driver health manager forms.
  One will be used by BDS core to configure the Configured Required
  driver health instances, the other will be automatically included by
  firmware setup (UI).

Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
(C) Copyright 2018 Hewlett Packard Enterprise Development LP<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent

**/

#include "DriverHealthManagerDxe.h"
#include "DriverHealthManagerVfr.h"

EFI_HII_CONFIG_ACCESS_PROTOCOL mDriverHealthManagerConfigAccess     = {
  DriverHealthManagerFakeExtractConfig,
  DriverHealthManagerFakeRouteConfig,
  DriverHealthManagerCallback
};

EFI_GUID mDriverHealthManagerForm = DRIVER_HEALTH_MANAGER_FORMSET_GUID;

FORM_DEVICE_PATH  mDriverHealthManagerFormDevicePath = {
  {
    {
      HARDWARE_DEVICE_PATH,
      HW_VENDOR_DP,
      {
        (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
      }
    },
    EFI_CALLER_ID_GUID
  },
  {
    END_DEVICE_PATH_TYPE,
    END_ENTIRE_DEVICE_PATH_SUBTYPE,
    {
      (UINT8) (END_DEVICE_PATH_LENGTH),
      (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
    }
  }
};

EFI_HII_HANDLE                       mDriverHealthManagerHiiHandle;
EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO  *mDriverHealthManagerHealthInfo     = NULL;
UINTN                                mDriverHealthManagerHealthInfoCount = 0;
EFI_HII_DATABASE_PROTOCOL            *mDriverHealthManagerDatabase;


extern UINT8 DriverHealthManagerVfrBin[];
extern UINT8 DriverHealthConfigureVfrBin[];

/**
  This function allows a caller to extract the current configuration for one
  or more named elements from the target driver.


  @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
  @param Request         A null-terminated Unicode string in <ConfigRequest> format.
  @param Progress        On return, points to a character in the Request string.
                         Points to the string's null terminator if request was successful.
                         Points to the most recent '&' before the first failing name/value
                         pair (or the beginning of the string if the failure is in the
                         first name/value pair) if the request was not successful.
  @param Results         A null-terminated Unicode string in <ConfigAltResp> format which
                         has all values filled in for the names in the Request string.
                         String to be allocated by the called function.

  @retval  EFI_SUCCESS            The Results is filled with the requested values.
  @retval  EFI_OUT_OF_RESOURCES   Not enough memory to store the results.
  @retval  EFI_INVALID_PARAMETER  Request is illegal syntax, or unknown name.
  @retval  EFI_NOT_FOUND          Routing data doesn't match any storage in this driver.

**/
EFI_STATUS
EFIAPI
DriverHealthManagerFakeExtractConfig (
  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
  IN  CONST EFI_STRING                       Request,
  OUT EFI_STRING                             *Progress,
  OUT EFI_STRING                             *Results
  )
{
  if (Progress == NULL || Results == NULL) {
    return EFI_INVALID_PARAMETER;
  }
  *Progress = Request;
  return EFI_NOT_FOUND;
}

/**
  This function processes the results of changes in configuration.


  @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
  @param Configuration   A null-terminated Unicode string in <ConfigResp> format.
  @param Progress        A pointer to a string filled in with the offset of the most
                         recent '&' before the first failing name/value pair (or the
                         beginning of the string if the failure is in the first
                         name/value pair) or the terminating NULL if all was successful.

  @retval  EFI_SUCCESS            The Results is processed successfully.
  @retval  EFI_INVALID_PARAMETER  Configuration is NULL.
  @retval  EFI_NOT_FOUND          Routing data doesn't match any storage in this driver.

**/
EFI_STATUS
EFIAPI
DriverHealthManagerFakeRouteConfig (
  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
  IN  CONST EFI_STRING                       Configuration,
  OUT EFI_STRING                             *Progress
  )
{
  if (Configuration == NULL || Progress == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  *Progress = Configuration;

  return EFI_NOT_FOUND;
}

/**

  Install the health manager forms.
  One will be used by BDS core to configure the Configured Required
  driver health instances, the other will be automatically included by
  firmware setup (UI).

  @param ImageHandle     The image handle.
  @param SystemTable     The system table.

  @retval  EFI_SUCEESS   The health manager forms are successfully installed.

**/
EFI_STATUS
EFIAPI
InitializeDriverHealthManager (
  EFI_HANDLE                 ImageHandle,
  EFI_SYSTEM_TABLE           *SystemTable
  )
{
  EFI_STATUS                  Status;
  EFI_HANDLE                  Handle;

  Status = gBS->LocateProtocol (
                  &gEfiHiiDatabaseProtocolGuid,
                  NULL,
                  (VOID **) &mDriverHealthManagerDatabase
                  );
  ASSERT_EFI_ERROR (Status);

  Handle = NULL;
  Status = gBS->InstallMultipleProtocolInterfaces (
                  &Handle,
                  &gEfiDevicePathProtocolGuid,
                  &mDriverHealthManagerFormDevicePath,
                  &gEfiHiiConfigAccessProtocolGuid,
                  &mDriverHealthManagerConfigAccess,
                  NULL
                  );
  ASSERT_EFI_ERROR (Status);


  //
  // Publish Driver Health HII data.
  //
  mDriverHealthManagerHiiHandle = HiiAddPackages (
                                    &gEfiCallerIdGuid,
                                    Handle,
                                    DriverHealthManagerVfrBin,
                                    DriverHealthConfigureVfrBin,
                                    STRING_ARRAY_NAME,
                                    NULL
                                    );
  ASSERT (mDriverHealthManagerHiiHandle != NULL);

  return EFI_SUCCESS;
}

/**

  Select the best matching language according to front page policy for best user experience.

  This function supports both ISO 639-2 and RFC 4646 language codes, but language
  code types may not be mixed in a single call to this function.

  @param  SupportedLanguages   A pointer to a Null-terminated ASCII string that
                               contains a set of language codes in the format
                               specified by Iso639Language.
  @param  Iso639Language       If TRUE, then all language codes are assumed to be
                               in ISO 639-2 format.  If FALSE, then all language
                               codes are assumed to be in RFC 4646 language format.

  @retval NULL                 The best matching language could not be found in SupportedLanguages.
  @retval NULL                 There are not enough resources available to return the best matching
                               language.
  @retval Other                A pointer to a Null-terminated ASCII string that is the best matching
                               language in SupportedLanguages.
**/
CHAR8 *
DriverHealthManagerSelectBestLanguage (
  IN CHAR8        *SupportedLanguages,
  IN BOOLEAN      Iso639Language
  )
{
  CHAR8           *LanguageVariable;
  CHAR8           *BestLanguage;

  GetEfiGlobalVariable2 (Iso639Language ? L"Lang" : L"PlatformLang", (VOID**)&LanguageVariable, NULL);

  BestLanguage = GetBestLanguage(
                   SupportedLanguages,
                   Iso639Language,
                   (LanguageVariable != NULL) ? LanguageVariable : "",
                   Iso639Language ? "eng" : "en-US",
                   NULL
                   );
  if (LanguageVariable != NULL) {
    FreePool (LanguageVariable);
  }

  return BestLanguage;
}



/**

  This is an internal worker function to get the Component Name (2) protocol interface
  and the language it supports.

  @param  ProtocolGuid         A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.
  @param  DriverBindingHandle  The handle on which the Component Name (2) protocol instance is retrieved.
  @param  ComponentName        A pointer to the Component Name (2) protocol interface.
  @param  SupportedLanguage    The best suitable language that matches the SupportedLangues interface for the
                               located Component Name (2) instance.

  @retval EFI_SUCCESS          The Component Name (2) protocol instance is successfully located and we find
                               the best matching language it support.
  @retval EFI_UNSUPPORTED      The input Language is not supported by the Component Name (2) protocol.
  @retval Other                Some error occurs when locating Component Name (2) protocol instance or finding
                               the supported language.

**/
EFI_STATUS
DriverHealthManagerGetComponentNameWorker (
  IN  EFI_GUID                    *ProtocolGuid,
  IN  EFI_HANDLE                  DriverBindingHandle,
  OUT EFI_COMPONENT_NAME_PROTOCOL **ComponentName,
  OUT CHAR8                       **SupportedLanguage
  )
{
  EFI_STATUS                      Status;

  //
  // Locate Component Name (2) protocol on the driver binging handle.
  //
  Status = gBS->OpenProtocol (
                 DriverBindingHandle,
                 ProtocolGuid,
                 (VOID **) ComponentName,
                 NULL,
                 NULL,
                 EFI_OPEN_PROTOCOL_GET_PROTOCOL
                 );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Apply shell policy to select the best language.
  //
  *SupportedLanguage = DriverHealthManagerSelectBestLanguage (
                         (*ComponentName)->SupportedLanguages,
                         (BOOLEAN) (ProtocolGuid == &gEfiComponentNameProtocolGuid)
                         );
  if (*SupportedLanguage == NULL) {
    Status = EFI_UNSUPPORTED;
  }

  return Status;
}

/**

  This is an internal worker function to get driver name from Component Name (2) protocol interface.

  @param  ProtocolGuid         A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.
  @param  DriverBindingHandle  The handle on which the Component Name (2) protocol instance is retrieved.
  @param  DriverName           A pointer to the Unicode string to return. This Unicode string is the name
                               of the driver specified by This.

  @retval EFI_SUCCESS          The driver name is successfully retrieved from Component Name (2) protocol
                               interface.
  @retval Other                The driver name cannot be retrieved from Component Name (2) protocol
                               interface.

**/
EFI_STATUS
DriverHealthManagerGetDriverNameWorker (
  IN  EFI_GUID    *ProtocolGuid,
  IN  EFI_HANDLE  DriverBindingHandle,
  OUT CHAR16      **DriverName
  )
{
  EFI_STATUS                     Status;
  CHAR8                          *BestLanguage;
  EFI_COMPONENT_NAME_PROTOCOL    *ComponentName;

  //
  // Retrieve Component Name (2) protocol instance on the driver binding handle and
  // find the best language this instance supports.
  //
  Status = DriverHealthManagerGetComponentNameWorker (
             ProtocolGuid,
             DriverBindingHandle,
             &ComponentName,
             &BestLanguage
             );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Get the driver name from Component Name (2) protocol instance on the driver binging handle.
  //
  Status = ComponentName->GetDriverName (
                            ComponentName,
                            BestLanguage,
                            DriverName
                            );
  FreePool (BestLanguage);

  return Status;
}

/**
  This function gets driver name from Component Name 2 protocol interface and Component Name protocol interface
  in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the driver name.
  If the attempt fails, it then gets the driver name from EFI 1.1 Component Name protocol for backward
  compatibility support.

  @param  DriverBindingHandle  The handle on which the Component Name (2) protocol instance is retrieved.

  @return A pointer to the Unicode string to return. This Unicode string is the name of the controller
          specified by ControllerHandle and ChildHandle.


**/
CHAR16 *
DriverHealthManagerGetDriverName (
  IN  EFI_HANDLE  DriverBindingHandle
  )
{
  EFI_STATUS      Status;
  CHAR16          *DriverName;

  //
  // Get driver name from UEFI 2.0 Component Name 2 protocol interface.
  //
  Status = DriverHealthManagerGetDriverNameWorker (&gEfiComponentName2ProtocolGuid, DriverBindingHandle, &DriverName);
  if (EFI_ERROR (Status)) {
    //
    // If it fails to get the driver name from Component Name protocol interface, we should fall back on
    // EFI 1.1 Component Name protocol interface.
    //
    Status = DriverHealthManagerGetDriverNameWorker (&gEfiComponentNameProtocolGuid, DriverBindingHandle, &DriverName);
  }

  if (!EFI_ERROR (Status)) {
    return AllocateCopyPool (StrSize (DriverName), DriverName);
  } else {
    return ConvertDevicePathToText (DevicePathFromHandle (DriverBindingHandle), FALSE, TRUE);
  }
}



/**
  This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface
  in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name.
  If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward
  compatibility support.

  @param  ProtocolGuid         A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.
  @param  DriverBindingHandle  The handle on which the Component Name (2) protocol instance is retrieved.
  @param  ControllerHandle     The handle of a controller that the driver specified by This is managing.
                               This handle specifies the controller whose name is to be returned.
  @param  ChildHandle          The handle of the child controller to retrieve the name of. This is an
                               optional parameter that may be NULL. It will be NULL for device drivers.
                               It will also be NULL for bus drivers that attempt to retrieve the name
                               of the bus controller. It will not be NULL for a bus driver that attempts
                               to retrieve the name of a child controller.
  @param  ControllerName       A pointer to the Unicode string to return. This Unicode string
                               is the name of the controller specified by ControllerHandle and ChildHandle.

  @retval  EFI_SUCCESS         The controller name is successfully retrieved from Component Name (2) protocol
                               interface.
  @retval  Other               The controller name cannot be retrieved from Component Name (2) protocol.

**/
EFI_STATUS
DriverHealthManagerGetControllerNameWorker (
  IN  EFI_GUID    *ProtocolGuid,
  IN  EFI_HANDLE  DriverBindingHandle,
  IN  EFI_HANDLE  ControllerHandle,
  IN  EFI_HANDLE  ChildHandle,
  OUT CHAR16      **ControllerName
  )
{
  EFI_STATUS                     Status;
  CHAR8                          *BestLanguage;
  EFI_COMPONENT_NAME_PROTOCOL    *ComponentName;

  //
  // Retrieve Component Name (2) protocol instance on the driver binding handle and
  // find the best language this instance supports.
  //
  Status = DriverHealthManagerGetComponentNameWorker (
             ProtocolGuid,
             DriverBindingHandle,
             &ComponentName,
             &BestLanguage
             );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Get the controller name from Component Name (2) protocol instance on the driver binging handle.
  //
  Status = ComponentName->GetControllerName (
                            ComponentName,
                            ControllerHandle,
                            ChildHandle,
                            BestLanguage,
                            ControllerName
                            );
  FreePool (BestLanguage);

  return Status;
}

/**

  This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface
  in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name.
  If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward
  compatibility support.

  @param  DriverBindingHandle  The handle on which the Component Name (2) protocol instance is retrieved.
  @param  ControllerHandle     The handle of a controller that the driver specified by DriverBindingHandle is managing.
                               This handle specifies the controller whose name is to be returned.
  @param  ChildHandle          The handle of the child controller to retrieve the name of. This is an
                               optional parameter that may be NULL. It will be NULL for device drivers.
                               It will also be NULL for bus drivers that attempt to retrieve the name
                               of the bus controller. It will not be NULL for a bus driver that attempts
                               to retrieve the name of a child controller.

  @return A pointer to the Unicode string to return. This Unicode string is the name of the controller
          specified by ControllerHandle and ChildHandle.
**/
CHAR16 *
DriverHealthManagerGetControllerName (
  IN  EFI_HANDLE  DriverBindingHandle,
  IN  EFI_HANDLE  ControllerHandle,
  IN  EFI_HANDLE  ChildHandle
  )
{
  EFI_STATUS      Status;
  CHAR16          *ControllerName;

  //
  // Get controller name from UEFI 2.0 Component Name 2 protocol interface.
  //
  Status = DriverHealthManagerGetControllerNameWorker (
             &gEfiComponentName2ProtocolGuid,
             DriverBindingHandle,
             ControllerHandle,
             ChildHandle,
             &ControllerName
             );
  if (EFI_ERROR (Status)) {
    //
    // If it fails to get the controller name from Component Name protocol interface, we should fall back on
    // EFI 1.1 Component Name protocol interface.
    //
    Status = DriverHealthManagerGetControllerNameWorker (
               &gEfiComponentNameProtocolGuid,
               DriverBindingHandle,
               ControllerHandle,
               ChildHandle,
               &ControllerName
               );
  }

  if (!EFI_ERROR (Status)) {
    return AllocateCopyPool (StrSize (ControllerName), ControllerName);
  } else {
    return ConvertDevicePathToText (DevicePathFromHandle (ChildHandle != NULL ? ChildHandle : ControllerHandle), FALSE, TRUE);
  }
}

/**
  The repair notify function.
  @param Value  A value between 0 and Limit that identifies the current progress
                of the repair operation.
  @param Limit  The maximum value of Value for the current repair operation.
                If Limit is 0, then the completion progress is indeterminate.
                For example, a driver that wants to specify progress in percent
                would use a Limit value of 100.

  @retval EFI_SUCCESS  Successfully return from the notify function.
**/
EFI_STATUS
EFIAPI
DriverHealthManagerRepairNotify (
  IN UINTN        Value,
  IN UINTN        Limit
  )
{
  DEBUG ((EFI_D_INFO, "[DriverHealthManagement]RepairNotify: %d/%d\n", Value, Limit));
  return EFI_SUCCESS;
}

/**
  Look for the formset GUID which has the gEfiHiiDriverHealthFormsetGuid class GUID in the specified HII package list.

  @param Handle         Handle to the HII package list.
  @param FormsetGuid    Return the formset GUID.

  @retval EFI_SUCCESS   The formset is found successfully.
  @retval EFI_NOT_FOUND The formset cannot be found.
**/
EFI_STATUS
DriverHealthManagerGetFormsetId (
  IN  EFI_HII_HANDLE   Handle,
  OUT EFI_GUID         *FormsetGuid
  )
{
  EFI_STATUS                   Status;
  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;
  UINTN                        BufferSize;
  UINT8                        *Package;
  UINT8                        *OpCodeData;
  UINT32                       Offset;
  UINT32                       Offset2;
  EFI_HII_PACKAGE_HEADER       PackageHeader;
  UINT8                        Index;
  UINT8                        NumberOfClassGuid;
  EFI_GUID                     *ClassGuid;

  //
  // Get HII PackageList
  //
  BufferSize     = 0;
  HiiPackageList = NULL;
  Status = mDriverHealthManagerDatabase->ExportPackageLists (mDriverHealthManagerDatabase, Handle, &BufferSize, HiiPackageList);
  if (Status == EFI_BUFFER_TOO_SMALL) {
    HiiPackageList = AllocatePool (BufferSize);
    ASSERT (HiiPackageList != NULL);

    Status = mDriverHealthManagerDatabase->ExportPackageLists (mDriverHealthManagerDatabase, Handle, &BufferSize, HiiPackageList);
  }
  if (EFI_ERROR (Status)) {
    return Status;
  }
  ASSERT (HiiPackageList != NULL);

  //
  // Get Form package from this HII package List
  //
  for (Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); Offset < ReadUnaligned32 (&HiiPackageList->PackageLength); Offset += PackageHeader.Length) {
    Package = ((UINT8 *) HiiPackageList) + Offset;
    CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));

    if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {
      //
      // Search FormSet in this Form Package
      //

      for (Offset2 = sizeof (EFI_HII_PACKAGE_HEADER); Offset2 < PackageHeader.Length; Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length) {
        OpCodeData = Package + Offset2;

        if ((((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) &&
            (((EFI_IFR_OP_HEADER *) OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags))) {
          //
          // Try to compare against formset class GUID
          //
          NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);
          ClassGuid         = (EFI_GUID *) (OpCodeData + sizeof (EFI_IFR_FORM_SET));
          for (Index = 0; Index < NumberOfClassGuid; Index++) {
            if (CompareGuid (&gEfiHiiDriverHealthFormsetGuid, &ClassGuid[Index])) {
              CopyMem (FormsetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));
              FreePool (HiiPackageList);
              return EFI_SUCCESS;
            }
          }
        }
      }
    }
  }

  //
  // Form package not found in this Package List
  //
  FreePool (HiiPackageList);
  return EFI_NOT_FOUND;
}

/**
  Processes a single controller using the EFI Driver Health Protocol associated with
  that controller.

  @param DriverHealth       A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance.
  @param ControllerHandle   The class guid specifies which form set will be displayed.
  @param ChildHandle        The handle of the child controller to retrieve the health
                            status on.  This is an optional parameter that may be NULL.
  @param HealthStatus       The health status of the controller.
  @param MessageList        An array of warning or error messages associated
                            with the controller specified by ControllerHandle and
                            ChildHandle.  This is an optional parameter that may be NULL.
  @param FormHiiHandle      The HII handle for an HII form associated with the
                            controller specified by ControllerHandle and ChildHandle.
**/
VOID
DriverHealthManagerProcessSingleControllerHealth (
  IN  EFI_DRIVER_HEALTH_PROTOCOL         *DriverHealth,
  IN  EFI_HANDLE                         ControllerHandle, OPTIONAL
  IN  EFI_HANDLE                         ChildHandle,      OPTIONAL
  IN  EFI_DRIVER_HEALTH_STATUS           HealthStatus,
  IN  EFI_DRIVER_HEALTH_HII_MESSAGE      **MessageList,    OPTIONAL
  IN  EFI_HII_HANDLE                     FormHiiHandle
  )
{
  EFI_STATUS                         Status;

  ASSERT (HealthStatus != EfiDriverHealthStatusConfigurationRequired);
  //
  // If the module need to be repaired or reconfiguration,  will process it until
  // reach a terminal status. The status from EfiDriverHealthStatusRepairRequired after repair
  // will be in (Health, Failed, Configuration Required).
  //
  switch (HealthStatus) {

  case EfiDriverHealthStatusRepairRequired:
    Status = DriverHealth->Repair (
                             DriverHealth,
                             ControllerHandle,
                             ChildHandle,
                             DriverHealthManagerRepairNotify
                             );
    break;

  case EfiDriverHealthStatusRebootRequired:
    gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
    break;

  case EfiDriverHealthStatusReconnectRequired:
    Status = gBS->DisconnectController (ControllerHandle, NULL, NULL);
    if (EFI_ERROR (Status)) {
      //
      // Disconnect failed.  Need to promote reconnect to a reboot.
      //
      gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
    } else {
      gBS->ConnectController (ControllerHandle, NULL, NULL, TRUE);
    }
    break;

  default:
    break;
  }
}

/**
  Update the form to include the driver health instances.

  @param ConfigureOnly  Only include the configure required driver health instances
                        when TRUE, include all the driver health instances otherwise.
**/
VOID
DriverHealthManagerUpdateForm (
  BOOLEAN                     ConfigureOnly
  )
{
  EFI_STATUS                  Status;
  EFI_IFR_GUID_LABEL          *StartLabel;
  EFI_IFR_GUID_LABEL          *EndLabel;
  VOID                        *StartOpCodeHandle;
  VOID                        *EndOpCodeHandle;
  UINTN                       Index;
  EFI_STRING_ID               Prompt;
  EFI_STRING_ID               Help;
  CHAR16                      String[512];
  UINTN                       StringCount;
  EFI_STRING                  TmpString;
  EFI_STRING                  DriverName;
  EFI_STRING                  ControllerName;
  UINTN                       MessageIndex;
  EFI_HANDLE                  DriverHandle;
  EFI_STRING_ID               DevicePath;
  EFI_GUID                    FormsetGuid;

  EfiBootManagerFreeDriverHealthInfo (mDriverHealthManagerHealthInfo, mDriverHealthManagerHealthInfoCount);
  mDriverHealthManagerHealthInfo = EfiBootManagerGetDriverHealthInfo (&mDriverHealthManagerHealthInfoCount);

  //
  // Allocate space for creation of UpdateData Buffer
  //
  StartOpCodeHandle = HiiAllocateOpCodeHandle ();
  ASSERT (StartOpCodeHandle != NULL);

  EndOpCodeHandle = HiiAllocateOpCodeHandle ();
  ASSERT (EndOpCodeHandle != NULL);

  //
  // Create Hii Extend Label OpCode as the start opcode
  //
  StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
  StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
  StartLabel->Number       = LABEL_BEGIN;

  //
  // Create Hii Extend Label OpCode as the end opcode
  //
  EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
  EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
  EndLabel->Number       = LABEL_END;

  for (Index = 0; Index < mDriverHealthManagerHealthInfoCount; Index++) {
    if (ConfigureOnly && mDriverHealthManagerHealthInfo[Index].HealthStatus != EfiDriverHealthStatusConfigurationRequired) {
      continue;
    }
    DriverName = DriverHealthManagerGetDriverName (mDriverHealthManagerHealthInfo[Index].DriverHealthHandle);
    ASSERT (DriverName != NULL);

    if (mDriverHealthManagerHealthInfo[Index].ControllerHandle == NULL) {
      //
      // The ControllerHandle is set to NULL and the HealthStatus is set to EfiDriverHealthStatusHealthy
      // if all the controllers managed by the driver are in healthy state.
      //
      ASSERT (mDriverHealthManagerHealthInfo[Index].HealthStatus == EfiDriverHealthStatusHealthy);
      UnicodeSPrint (String, sizeof (String), L"%s", DriverName);
    } else {
      ControllerName = DriverHealthManagerGetControllerName (
                         mDriverHealthManagerHealthInfo[Index].DriverHealthHandle,
                         mDriverHealthManagerHealthInfo[Index].ControllerHandle,
                         mDriverHealthManagerHealthInfo[Index].ChildHandle
                         );
      ASSERT (ControllerName != NULL);
      UnicodeSPrint (String, sizeof (String), L"%s    %s", DriverName, ControllerName);
      FreePool (ControllerName);
    }
    FreePool (DriverName);

    Prompt = HiiSetString (mDriverHealthManagerHiiHandle, 0, String, NULL);

    switch(mDriverHealthManagerHealthInfo[Index].HealthStatus) {
    case EfiDriverHealthStatusRepairRequired:
      TmpString = HiiGetString (mDriverHealthManagerHiiHandle, STRING_TOKEN (STR_REPAIR_REQUIRED), NULL);
      break;
    case EfiDriverHealthStatusConfigurationRequired:
      TmpString = HiiGetString (mDriverHealthManagerHiiHandle, STRING_TOKEN (STR_CONFIGURATION_REQUIRED), NULL);
      break;
    case EfiDriverHealthStatusFailed:
      TmpString = HiiGetString (mDriverHealthManagerHiiHandle, STRING_TOKEN (STR_FAILED), NULL);
      break;
    case EfiDriverHealthStatusReconnectRequired:
      TmpString = HiiGetString (mDriverHealthManagerHiiHandle, STRING_TOKEN (STR_RECONNECT_REQUIRED), NULL);
      break;
    case EfiDriverHealthStatusRebootRequired:
      TmpString = HiiGetString (mDriverHealthManagerHiiHandle, STRING_TOKEN (STR_REBOOT_REQUIRED), NULL);
      break;
    default:
      ASSERT (mDriverHealthManagerHealthInfo[Index].HealthStatus == EfiDriverHealthStatusHealthy);
      TmpString = HiiGetString (mDriverHealthManagerHiiHandle, STRING_TOKEN (STR_HEALTHY), NULL);
      break;
    }
    StringCount = UnicodeSPrint (String, sizeof (String), L"%s\n", TmpString);
    FreePool (TmpString);

    //
    // Add the message of the Module itself provided as the help.
    //
    if (mDriverHealthManagerHealthInfo[Index].MessageList != NULL) {
      for (MessageIndex = 0; mDriverHealthManagerHealthInfo[Index].MessageList[MessageIndex].HiiHandle != NULL; MessageIndex++) {
        TmpString = HiiGetString (
                      mDriverHealthManagerHealthInfo[Index].MessageList[MessageIndex].HiiHandle,
                      mDriverHealthManagerHealthInfo[Index].MessageList[MessageIndex].StringId,
                      NULL
                      );
        StringCount += UnicodeSPrint (String + StringCount, sizeof (String) - sizeof (String[0]) * StringCount, L"\n%s", TmpString);
        FreePool (TmpString);
      }
    }
    Help = HiiSetString (mDriverHealthManagerHiiHandle, 0, String, NULL);

    switch (mDriverHealthManagerHealthInfo[Index].HealthStatus) {
    case EfiDriverHealthStatusConfigurationRequired:
      Status = mDriverHealthManagerDatabase->GetPackageListHandle (
                                               mDriverHealthManagerDatabase,
                                               mDriverHealthManagerHealthInfo[Index].HiiHandle,
                                               &DriverHandle
                                               );
      ASSERT_EFI_ERROR (Status);
      TmpString  = ConvertDevicePathToText (DevicePathFromHandle (DriverHandle), FALSE, TRUE);
      DevicePath = HiiSetString (mDriverHealthManagerHiiHandle, 0, TmpString, NULL);
      FreePool (TmpString);

      Status = DriverHealthManagerGetFormsetId (mDriverHealthManagerHealthInfo[Index].HiiHandle, &FormsetGuid);
      ASSERT_EFI_ERROR (Status);

      HiiCreateGotoExOpCode (
        StartOpCodeHandle,
        0,
        Prompt,
        Help,
        0,
        0,
        0,
        &FormsetGuid,
        DevicePath
        );
      break;

    case EfiDriverHealthStatusRepairRequired:
    case EfiDriverHealthStatusReconnectRequired:
    case EfiDriverHealthStatusRebootRequired:
      HiiCreateActionOpCode (
        StartOpCodeHandle,
        (EFI_QUESTION_ID) (Index + QUESTION_ID_DRIVER_HEALTH_BASE),
        Prompt,
        Help,
        EFI_IFR_FLAG_CALLBACK,
        0
        );
      break;

    default:
      ASSERT (mDriverHealthManagerHealthInfo[Index].HealthStatus == EfiDriverHealthStatusHealthy ||
              mDriverHealthManagerHealthInfo[Index].HealthStatus == EfiDriverHealthStatusFailed);
      HiiCreateTextOpCode (
        StartOpCodeHandle,
        Prompt,
        Help,
        0
        );
      break;
    }
  }

  Status = HiiUpdateForm (
             mDriverHealthManagerHiiHandle,
             ConfigureOnly ? PcdGetPtr (PcdDriverHealthConfigureForm) : &mDriverHealthManagerForm,
             DRIVER_HEALTH_FORM_ID,
             StartOpCodeHandle,
             EndOpCodeHandle
             );
  ASSERT_EFI_ERROR (Status);

  HiiFreeOpCodeHandle (StartOpCodeHandle);
  HiiFreeOpCodeHandle (EndOpCodeHandle);
}

/**
  Called when the form is closing to remove the dynamicly added string from the HII package list.
**/
VOID
DriverHealthManagerCleanDynamicString (
  VOID
  )
{
  EFI_STATUS                   Status;
  EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;
  UINTN                        BufferSize;
  EFI_HII_PACKAGE_HEADER       *PackageHeader;
  UINT32                       FixedStringSize;

  FixedStringSize = *(UINT32 *) &STRING_ARRAY_NAME - sizeof (UINT32);
  BufferSize      = sizeof (EFI_HII_PACKAGE_LIST_HEADER) + FixedStringSize + sizeof (EFI_HII_PACKAGE_HEADER);
  HiiPackageList  = AllocatePool (BufferSize);
  ASSERT (HiiPackageList != NULL);

  HiiPackageList->PackageLength = (UINT32) BufferSize;
  CopyMem (&HiiPackageList->PackageListGuid, &gEfiCallerIdGuid, sizeof (EFI_GUID));

  PackageHeader = (EFI_HII_PACKAGE_HEADER *) (HiiPackageList + 1);
  CopyMem (PackageHeader, STRING_ARRAY_NAME + sizeof (UINT32), FixedStringSize);

  PackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageHeader + PackageHeader->Length);
  PackageHeader->Type   = EFI_HII_PACKAGE_END;
  PackageHeader->Length = sizeof (EFI_HII_PACKAGE_HEADER);

  Status = mDriverHealthManagerDatabase->UpdatePackageList (
                                           mDriverHealthManagerDatabase,
                                           mDriverHealthManagerHiiHandle,
                                           HiiPackageList
                                           );
  ASSERT_EFI_ERROR (Status);

  //
  // Form package not found in this Package List
  //
  FreePool (HiiPackageList);
}

/**
  This function is invoked if user selected a interactive opcode from Driver Health's
  Formset.

  @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
  @param Action          Specifies the type of action taken by the browser.
  @param QuestionId      A unique value which is sent to the original exporting driver
                         so that it can identify the type of data to expect.
  @param Type            The type of value for the question.
  @param Value           A pointer to the data being sent to the original exporting driver.
  @param ActionRequest   On return, points to the action requested by the callback function.

  @retval  EFI_SUCCESS           The callback successfully handled the action.
  @retval  EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.

**/
EFI_STATUS
EFIAPI
DriverHealthManagerCallback (
  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
  IN  EFI_BROWSER_ACTION                     Action,
  IN  EFI_QUESTION_ID                        QuestionId,
  IN  UINT8                                  Type,
  IN  EFI_IFR_TYPE_VALUE                     *Value,
  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest
  )
{
  UINTN                                      Index;

  if (QuestionId == QUESTION_ID_REFRESH_MANAGER || QuestionId == QUESTION_ID_REFRESH_CONFIGURE) {
    if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {
      DriverHealthManagerUpdateForm ((BOOLEAN) (QuestionId == QUESTION_ID_REFRESH_CONFIGURE));
    } else if (Action == EFI_BROWSER_ACTION_FORM_CLOSE) {
      DriverHealthManagerCleanDynamicString ();
    }
    return EFI_SUCCESS;
  }

  if (Action != EFI_BROWSER_ACTION_CHANGED) {
    //
    // Do nothing for other UEFI Action. Only do call back when data is changed.
    //
    return EFI_UNSUPPORTED;
  }

  if ((Value == NULL) || (ActionRequest == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  DEBUG ((EFI_D_ERROR, "QuestionId = %x\n", QuestionId));

  //
  // We will have returned from processing a callback - user either hit ESC to exit, or selected
  // a target to display.
  // Process the diver health status states here.
  //
  Index = QuestionId - QUESTION_ID_DRIVER_HEALTH_BASE;
  ASSERT (Index < mDriverHealthManagerHealthInfoCount);
  //
  // Process the driver's healthy status for the specify module
  //
  DriverHealthManagerProcessSingleControllerHealth (
    mDriverHealthManagerHealthInfo[Index].DriverHealth,
    mDriverHealthManagerHealthInfo[Index].ControllerHandle,
    mDriverHealthManagerHealthInfo[Index].ChildHandle,
    mDriverHealthManagerHealthInfo[Index].HealthStatus,
    &(mDriverHealthManagerHealthInfo[Index].MessageList),
    mDriverHealthManagerHealthInfo[Index].HiiHandle
    );

  DriverHealthManagerUpdateForm ((BOOLEAN) (QuestionId == QUESTION_ID_REFRESH_CONFIGURE));

  return EFI_SUCCESS;
}


