__FUNCTION__ is a pre-standard extension that gcc and Visual C++ among others support, while __func__ was standardized in C99. Since it's more standard, replace __FUNCTION__ with __func__ throughout MdeModulePkg. Signed-off-by: Rebecca Cran <rebecca@bsdio.com> Reviewed-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
		
			
				
	
	
		
			596 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			596 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Library functions which relates with driver health.
 | 
						|
 | 
						|
Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
 | 
						|
(C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
 | 
						|
(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
 | 
						|
SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "InternalBm.h"
 | 
						|
 | 
						|
GLOBAL_REMOVE_IF_UNREFERENCED
 | 
						|
CHAR16  *mBmHealthStatusText[] = {
 | 
						|
  L"Healthy",
 | 
						|
  L"Repair Required",
 | 
						|
  L"Configuration Required",
 | 
						|
  L"Failed",
 | 
						|
  L"Reconnect Required",
 | 
						|
  L"Reboot Required"
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
  Return the controller name.
 | 
						|
 | 
						|
  @param DriverHealthHandle  The handle on which the Driver Health 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 *
 | 
						|
BmGetControllerName (
 | 
						|
  IN  EFI_HANDLE  DriverHealthHandle,
 | 
						|
  IN  EFI_HANDLE  ControllerHandle,
 | 
						|
  IN  EFI_HANDLE  ChildHandle
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                   Status;
 | 
						|
  CHAR16                       *ControllerName;
 | 
						|
  CHAR8                        *LanguageVariable;
 | 
						|
  CHAR8                        *BestLanguage;
 | 
						|
  BOOLEAN                      Iso639Language;
 | 
						|
  EFI_COMPONENT_NAME_PROTOCOL  *ComponentName;
 | 
						|
 | 
						|
  ControllerName = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Locate Component Name (2) protocol on the driver binging handle.
 | 
						|
  //
 | 
						|
  Iso639Language = FALSE;
 | 
						|
  Status         = gBS->HandleProtocol (
 | 
						|
                          DriverHealthHandle,
 | 
						|
                          &gEfiComponentName2ProtocolGuid,
 | 
						|
                          (VOID **)&ComponentName
 | 
						|
                          );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = gBS->HandleProtocol (
 | 
						|
                    DriverHealthHandle,
 | 
						|
                    &gEfiComponentNameProtocolGuid,
 | 
						|
                    (VOID **)&ComponentName
 | 
						|
                    );
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      Iso639Language = TRUE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    GetEfiGlobalVariable2 (Iso639Language ? L"Lang" : L"PlatformLang", (VOID **)&LanguageVariable, NULL);
 | 
						|
    BestLanguage = GetBestLanguage (
 | 
						|
                     ComponentName->SupportedLanguages,
 | 
						|
                     Iso639Language,
 | 
						|
                     (LanguageVariable != NULL) ? LanguageVariable : "",
 | 
						|
                     Iso639Language ? "eng" : "en-US",
 | 
						|
                     NULL
 | 
						|
                     );
 | 
						|
    if (LanguageVariable != NULL) {
 | 
						|
      FreePool (LanguageVariable);
 | 
						|
    }
 | 
						|
 | 
						|
    Status = ComponentName->GetControllerName (
 | 
						|
                              ComponentName,
 | 
						|
                              ControllerHandle,
 | 
						|
                              ChildHandle,
 | 
						|
                              BestLanguage,
 | 
						|
                              &ControllerName
 | 
						|
                              );
 | 
						|
  }
 | 
						|
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    return AllocateCopyPool (StrSize (ControllerName), ControllerName);
 | 
						|
  } else {
 | 
						|
    return ConvertDevicePathToText (
 | 
						|
             DevicePathFromHandle (ChildHandle != NULL ? ChildHandle : ControllerHandle),
 | 
						|
             FALSE,
 | 
						|
             FALSE
 | 
						|
             );
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Display a set of messages returned by the GetHealthStatus () service of the EFI Driver Health Protocol
 | 
						|
 | 
						|
  @param DriverHealthInfo  Pointer to the Driver Health information entry.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
BmDisplayMessages (
 | 
						|
  IN  EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO  *DriverHealthInfo
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN       Index;
 | 
						|
  EFI_STRING  String;
 | 
						|
  CHAR16      *ControllerName;
 | 
						|
 | 
						|
  if ((DriverHealthInfo->MessageList == NULL) ||
 | 
						|
      (DriverHealthInfo->MessageList[0].HiiHandle == NULL))
 | 
						|
  {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  ControllerName = BmGetControllerName (
 | 
						|
                     DriverHealthInfo->DriverHealthHandle,
 | 
						|
                     DriverHealthInfo->ControllerHandle,
 | 
						|
                     DriverHealthInfo->ChildHandle
 | 
						|
                     );
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "Controller: %s\n", ControllerName));
 | 
						|
  Print (L"Controller: %s\n", ControllerName);
 | 
						|
  for (Index = 0; DriverHealthInfo->MessageList[Index].HiiHandle != NULL; Index++) {
 | 
						|
    String = HiiGetString (
 | 
						|
               DriverHealthInfo->MessageList[Index].HiiHandle,
 | 
						|
               DriverHealthInfo->MessageList[Index].StringId,
 | 
						|
               NULL
 | 
						|
               );
 | 
						|
    if (String != NULL) {
 | 
						|
      Print (L"  %s\n", String);
 | 
						|
      DEBUG ((DEBUG_INFO, "  %s\n", String));
 | 
						|
      FreePool (String);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (ControllerName != NULL) {
 | 
						|
    FreePool (ControllerName);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
BmRepairNotify (
 | 
						|
  IN UINTN  Value,
 | 
						|
  IN UINTN  Limit
 | 
						|
  )
 | 
						|
{
 | 
						|
  DEBUG ((DEBUG_INFO, "[BDS]RepairNotify: %d/%d\n", Value, Limit));
 | 
						|
  Print (L"[BDS]RepairNotify: %d/%d\n", Value, Limit);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Collect the Driver Health status of a single controller.
 | 
						|
 | 
						|
  @param DriverHealthInfo        A pointer to the array containing all of the platform driver health information.
 | 
						|
  @param Count                   Return the updated array count.
 | 
						|
  @param DriverHealthHandle      The handle on which the Driver Health protocol instance is retrieved.
 | 
						|
  @param ControllerHandle        The handle of the controller..
 | 
						|
  @param ChildHandle             The handle of the child controller to retrieve the health
 | 
						|
                                 status on.  This is an optional parameter that may be NULL.
 | 
						|
 | 
						|
  @retval Status                 The status returned from GetHealthStatus.
 | 
						|
  @retval EFI_ABORTED            The health status is healthy so no further query is needed.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
BmGetSingleControllerHealthStatus (
 | 
						|
  IN OUT EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO  **DriverHealthInfo,
 | 
						|
  IN OUT UINTN                                *Count,
 | 
						|
  IN  EFI_HANDLE                              DriverHealthHandle,
 | 
						|
  IN  EFI_HANDLE                              ControllerHandle   OPTIONAL,
 | 
						|
  IN  EFI_HANDLE                              ChildHandle        OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                     Status;
 | 
						|
  EFI_DRIVER_HEALTH_PROTOCOL     *DriverHealth;
 | 
						|
  EFI_DRIVER_HEALTH_HII_MESSAGE  *MessageList;
 | 
						|
  EFI_HII_HANDLE                 FormHiiHandle;
 | 
						|
  EFI_DRIVER_HEALTH_STATUS       HealthStatus;
 | 
						|
 | 
						|
  ASSERT (DriverHealthHandle != NULL);
 | 
						|
  //
 | 
						|
  // Retrieve the Driver Health Protocol from DriverHandle
 | 
						|
  //
 | 
						|
  Status = gBS->HandleProtocol (
 | 
						|
                  DriverHealthHandle,
 | 
						|
                  &gEfiDriverHealthProtocolGuid,
 | 
						|
                  (VOID **)&DriverHealth
 | 
						|
                  );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  if (ControllerHandle == NULL) {
 | 
						|
    //
 | 
						|
    // If ControllerHandle is NULL, the return the cumulative health status of the driver
 | 
						|
    //
 | 
						|
    Status = DriverHealth->GetHealthStatus (DriverHealth, NULL, NULL, &HealthStatus, NULL, NULL);
 | 
						|
    if (!EFI_ERROR (Status) && (HealthStatus == EfiDriverHealthStatusHealthy)) {
 | 
						|
      *DriverHealthInfo = ReallocatePool (
 | 
						|
                            (*Count)     * sizeof (EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO),
 | 
						|
                            (*Count + 1) * sizeof (EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO),
 | 
						|
                            *DriverHealthInfo
 | 
						|
                            );
 | 
						|
      ASSERT (*DriverHealthInfo != NULL);
 | 
						|
 | 
						|
      (*DriverHealthInfo)[*Count].DriverHealthHandle = DriverHealthHandle;
 | 
						|
      (*DriverHealthInfo)[*Count].DriverHealth       = DriverHealth;
 | 
						|
      (*DriverHealthInfo)[*Count].HealthStatus       = HealthStatus;
 | 
						|
 | 
						|
      *Count = *Count + 1;
 | 
						|
 | 
						|
      Status = EFI_ABORTED;
 | 
						|
    }
 | 
						|
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  MessageList   = NULL;
 | 
						|
  FormHiiHandle = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Collect the health status with the optional HII message list
 | 
						|
  //
 | 
						|
  Status = DriverHealth->GetHealthStatus (DriverHealth, ControllerHandle, ChildHandle, &HealthStatus, &MessageList, &FormHiiHandle);
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    *DriverHealthInfo = ReallocatePool (
 | 
						|
                          (*Count)     * sizeof (EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO),
 | 
						|
                          (*Count + 1) * sizeof (EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO),
 | 
						|
                          *DriverHealthInfo
 | 
						|
                          );
 | 
						|
    ASSERT (*DriverHealthInfo != NULL);
 | 
						|
    (*DriverHealthInfo)[*Count].DriverHealth       = DriverHealth;
 | 
						|
    (*DriverHealthInfo)[*Count].DriverHealthHandle = DriverHealthHandle;
 | 
						|
    (*DriverHealthInfo)[*Count].ControllerHandle   = ControllerHandle;
 | 
						|
    (*DriverHealthInfo)[*Count].ChildHandle        = ChildHandle;
 | 
						|
    (*DriverHealthInfo)[*Count].HiiHandle          = FormHiiHandle;
 | 
						|
    (*DriverHealthInfo)[*Count].MessageList        = MessageList;
 | 
						|
    (*DriverHealthInfo)[*Count].HealthStatus       = HealthStatus;
 | 
						|
 | 
						|
    *Count = *Count + 1;
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Return all the Driver Health information.
 | 
						|
 | 
						|
  When the cumulative health status of all the controllers managed by the
 | 
						|
  driver who produces the EFI_DRIVER_HEALTH_PROTOCOL is healthy, only one
 | 
						|
  EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO entry is created for such
 | 
						|
  EFI_DRIVER_HEALTH_PROTOCOL instance.
 | 
						|
  Otherwise, every controller creates one EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO
 | 
						|
  entry. Additionally every child controller creates one
 | 
						|
  EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO entry if the driver is a bus driver.
 | 
						|
 | 
						|
  @param Count      Return the count of the Driver Health information.
 | 
						|
 | 
						|
  @retval NULL      No Driver Health information is returned.
 | 
						|
  @retval !NULL     Pointer to the Driver Health information array.
 | 
						|
**/
 | 
						|
EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *
 | 
						|
EFIAPI
 | 
						|
EfiBootManagerGetDriverHealthInfo (
 | 
						|
  UINTN  *Count
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                           Status;
 | 
						|
  UINTN                                NumHandles;
 | 
						|
  EFI_HANDLE                           *DriverHealthHandles;
 | 
						|
  UINTN                                DriverHealthIndex;
 | 
						|
  EFI_HANDLE                           *Handles;
 | 
						|
  UINTN                                HandleCount;
 | 
						|
  UINTN                                ControllerIndex;
 | 
						|
  UINTN                                ChildIndex;
 | 
						|
  EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO  *DriverHealthInfo;
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize local variables
 | 
						|
  //
 | 
						|
  *Count              = 0;
 | 
						|
  DriverHealthInfo    = NULL;
 | 
						|
  Handles             = NULL;
 | 
						|
  DriverHealthHandles = NULL;
 | 
						|
  NumHandles          = 0;
 | 
						|
  HandleCount         = 0;
 | 
						|
 | 
						|
  Status = gBS->LocateHandleBuffer (
 | 
						|
                  ByProtocol,
 | 
						|
                  &gEfiDriverHealthProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  &NumHandles,
 | 
						|
                  &DriverHealthHandles
 | 
						|
                  );
 | 
						|
 | 
						|
  if ((Status == EFI_NOT_FOUND) || (NumHandles == 0)) {
 | 
						|
    //
 | 
						|
    // If there are no Driver Health Protocols handles, then return EFI_NOT_FOUND
 | 
						|
    //
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
  ASSERT (DriverHealthHandles != NULL);
 | 
						|
 | 
						|
  //
 | 
						|
  // Check the health status of all controllers in the platform
 | 
						|
  // Start by looping through all the Driver Health Protocol handles in the handle database
 | 
						|
  //
 | 
						|
  for (DriverHealthIndex = 0; DriverHealthIndex < NumHandles; DriverHealthIndex++) {
 | 
						|
    //
 | 
						|
    // Get the cumulative health status of the driver
 | 
						|
    //
 | 
						|
    Status = BmGetSingleControllerHealthStatus (&DriverHealthInfo, Count, DriverHealthHandles[DriverHealthIndex], NULL, NULL);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // See if the list of all handles in the handle database has been retrieved
 | 
						|
    //
 | 
						|
    //
 | 
						|
    if (Handles == NULL) {
 | 
						|
      //
 | 
						|
      // Retrieve the list of all handles from the handle database
 | 
						|
      //
 | 
						|
      Status = gBS->LocateHandleBuffer (
 | 
						|
                      AllHandles,
 | 
						|
                      NULL,
 | 
						|
                      NULL,
 | 
						|
                      &HandleCount,
 | 
						|
                      &Handles
 | 
						|
                      );
 | 
						|
      ASSERT_EFI_ERROR (Status);
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Loop through all the controller handles in the handle database
 | 
						|
    //
 | 
						|
    for (ControllerIndex = 0; ControllerIndex < HandleCount; ControllerIndex++) {
 | 
						|
      Status = BmGetSingleControllerHealthStatus (&DriverHealthInfo, Count, DriverHealthHandles[DriverHealthIndex], Handles[ControllerIndex], NULL);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // Loop through all the child handles in the handle database
 | 
						|
      //
 | 
						|
      for (ChildIndex = 0; ChildIndex < HandleCount; ChildIndex++) {
 | 
						|
        Status = BmGetSingleControllerHealthStatus (&DriverHealthInfo, Count, DriverHealthHandles[DriverHealthIndex], Handles[ControllerIndex], Handles[ChildIndex]);
 | 
						|
        if (EFI_ERROR (Status)) {
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  Status = EFI_SUCCESS;
 | 
						|
 | 
						|
  if (Handles != NULL) {
 | 
						|
    FreePool (Handles);
 | 
						|
  }
 | 
						|
 | 
						|
  if (DriverHealthHandles != NULL) {
 | 
						|
    FreePool (DriverHealthHandles);
 | 
						|
  }
 | 
						|
 | 
						|
  return DriverHealthInfo;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Free the Driver Health information array.
 | 
						|
 | 
						|
  @param DriverHealthInfo       Pointer to array of the Driver Health information.
 | 
						|
  @param Count                  Count of the array.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The array is freed.
 | 
						|
  @retval EFI_INVALID_PARAMETER The array is NULL.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EfiBootManagerFreeDriverHealthInfo (
 | 
						|
  EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO  *DriverHealthInfo,
 | 
						|
  UINTN                                Count
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN  Index;
 | 
						|
 | 
						|
  for (Index = 0; Index < Count; Index++) {
 | 
						|
    if (DriverHealthInfo[Index].MessageList != NULL) {
 | 
						|
      FreePool (DriverHealthInfo[Index].MessageList);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return gBS->FreePool (DriverHealthInfo);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Repair all the controllers according to the Driver Health status queried.
 | 
						|
 | 
						|
  @param ReconnectRepairCount     To record the number of recursive call of
 | 
						|
                                  this function itself.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
BmRepairAllControllers (
 | 
						|
  UINTN  ReconnectRepairCount
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                           Status;
 | 
						|
  EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO  *DriverHealthInfo;
 | 
						|
  EFI_DRIVER_HEALTH_STATUS             HealthStatus;
 | 
						|
  UINTN                                Count;
 | 
						|
  UINTN                                Index;
 | 
						|
  BOOLEAN                              RepairRequired;
 | 
						|
  BOOLEAN                              ConfigurationRequired;
 | 
						|
  BOOLEAN                              ReconnectRequired;
 | 
						|
  BOOLEAN                              RebootRequired;
 | 
						|
  EFI_HII_HANDLE                       *HiiHandles;
 | 
						|
  EFI_FORM_BROWSER2_PROTOCOL           *FormBrowser2;
 | 
						|
  UINT32                               MaxRepairCount;
 | 
						|
  UINT32                               RepairCount;
 | 
						|
 | 
						|
  //
 | 
						|
  // Configure PcdDriverHealthConfigureForm to ZeroGuid to disable driver health check.
 | 
						|
  //
 | 
						|
  if (IsZeroGuid (PcdGetPtr (PcdDriverHealthConfigureForm))) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **)&FormBrowser2);
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  MaxRepairCount = PcdGet32 (PcdMaxRepairCount);
 | 
						|
  RepairCount    = 0;
 | 
						|
 | 
						|
  do {
 | 
						|
    RepairRequired        = FALSE;
 | 
						|
    ConfigurationRequired = FALSE;
 | 
						|
 | 
						|
    //
 | 
						|
    // Deal with Repair Required
 | 
						|
    //
 | 
						|
    DriverHealthInfo = EfiBootManagerGetDriverHealthInfo (&Count);
 | 
						|
    for (Index = 0; Index < Count; Index++) {
 | 
						|
      if (DriverHealthInfo[Index].HealthStatus == EfiDriverHealthStatusConfigurationRequired) {
 | 
						|
        ConfigurationRequired = TRUE;
 | 
						|
      }
 | 
						|
 | 
						|
      if (DriverHealthInfo[Index].HealthStatus == EfiDriverHealthStatusRepairRequired) {
 | 
						|
        RepairRequired = TRUE;
 | 
						|
 | 
						|
        BmDisplayMessages (&DriverHealthInfo[Index]);
 | 
						|
 | 
						|
        Status = DriverHealthInfo[Index].DriverHealth->Repair (
 | 
						|
                                                         DriverHealthInfo[Index].DriverHealth,
 | 
						|
                                                         DriverHealthInfo[Index].ControllerHandle,
 | 
						|
                                                         DriverHealthInfo[Index].ChildHandle,
 | 
						|
                                                         BmRepairNotify
 | 
						|
                                                         );
 | 
						|
        if (!EFI_ERROR (Status) && !ConfigurationRequired) {
 | 
						|
          Status = DriverHealthInfo[Index].DriverHealth->GetHealthStatus (
 | 
						|
                                                           DriverHealthInfo[Index].DriverHealth,
 | 
						|
                                                           DriverHealthInfo[Index].ControllerHandle,
 | 
						|
                                                           DriverHealthInfo[Index].ChildHandle,
 | 
						|
                                                           &HealthStatus,
 | 
						|
                                                           NULL,
 | 
						|
                                                           NULL
 | 
						|
                                                           );
 | 
						|
          if (!EFI_ERROR (Status) && (HealthStatus == EfiDriverHealthStatusConfigurationRequired)) {
 | 
						|
            ConfigurationRequired = TRUE;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (ConfigurationRequired) {
 | 
						|
      HiiHandles = HiiGetHiiHandles (NULL);
 | 
						|
      if (HiiHandles != NULL) {
 | 
						|
        for (Index = 0; HiiHandles[Index] != NULL; Index++) {
 | 
						|
          Status = FormBrowser2->SendForm (
 | 
						|
                                   FormBrowser2,
 | 
						|
                                   &HiiHandles[Index],
 | 
						|
                                   1,
 | 
						|
                                   PcdGetPtr (PcdDriverHealthConfigureForm),
 | 
						|
                                   0,
 | 
						|
                                   NULL,
 | 
						|
                                   NULL
 | 
						|
                                   );
 | 
						|
          if (!EFI_ERROR (Status)) {
 | 
						|
            break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        FreePool (HiiHandles);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    EfiBootManagerFreeDriverHealthInfo (DriverHealthInfo, Count);
 | 
						|
    RepairCount++;
 | 
						|
  } while ((RepairRequired || ConfigurationRequired) && ((MaxRepairCount == 0) || (RepairCount < MaxRepairCount)));
 | 
						|
 | 
						|
  RebootRequired    = FALSE;
 | 
						|
  ReconnectRequired = FALSE;
 | 
						|
  DriverHealthInfo  = EfiBootManagerGetDriverHealthInfo (&Count);
 | 
						|
  for (Index = 0; Index < Count; Index++) {
 | 
						|
    BmDisplayMessages (&DriverHealthInfo[Index]);
 | 
						|
 | 
						|
    if (DriverHealthInfo[Index].HealthStatus == EfiDriverHealthStatusReconnectRequired) {
 | 
						|
      Status = gBS->DisconnectController (DriverHealthInfo[Index].ControllerHandle, NULL, NULL);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        //
 | 
						|
        // Disconnect failed. Need to promote reconnect to a reboot.
 | 
						|
        //
 | 
						|
        RebootRequired = TRUE;
 | 
						|
      } else {
 | 
						|
        gBS->ConnectController (DriverHealthInfo[Index].ControllerHandle, NULL, NULL, TRUE);
 | 
						|
        ReconnectRequired = TRUE;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (DriverHealthInfo[Index].HealthStatus == EfiDriverHealthStatusRebootRequired) {
 | 
						|
      RebootRequired = TRUE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  EfiBootManagerFreeDriverHealthInfo (DriverHealthInfo, Count);
 | 
						|
 | 
						|
  DEBUG_CODE_BEGIN ();
 | 
						|
  CHAR16  *ControllerName;
 | 
						|
 | 
						|
  DriverHealthInfo = EfiBootManagerGetDriverHealthInfo (&Count);
 | 
						|
  for (Index = 0; Index < Count; Index++) {
 | 
						|
    ControllerName = BmGetControllerName (
 | 
						|
                       DriverHealthInfo[Index].DriverHealthHandle,
 | 
						|
                       DriverHealthInfo[Index].ControllerHandle,
 | 
						|
                       DriverHealthInfo[Index].ChildHandle
 | 
						|
                       );
 | 
						|
    DEBUG ((
 | 
						|
      DEBUG_INFO,
 | 
						|
      "%02d: %s - %s\n",
 | 
						|
      Index,
 | 
						|
      ControllerName,
 | 
						|
      mBmHealthStatusText[DriverHealthInfo[Index].HealthStatus]
 | 
						|
      ));
 | 
						|
    if (ControllerName != NULL) {
 | 
						|
      FreePool (ControllerName);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  EfiBootManagerFreeDriverHealthInfo (DriverHealthInfo, Count);
 | 
						|
  DEBUG_CODE_END ();
 | 
						|
 | 
						|
  if (ReconnectRequired) {
 | 
						|
    if (ReconnectRepairCount < MAX_RECONNECT_REPAIR) {
 | 
						|
      BmRepairAllControllers (ReconnectRepairCount + 1);
 | 
						|
    } else {
 | 
						|
      DEBUG ((
 | 
						|
        DEBUG_ERROR,
 | 
						|
        "[%a:%d] Repair failed after %d retries.\n",
 | 
						|
        __func__,
 | 
						|
        DEBUG_LINE_NUMBER,
 | 
						|
        ReconnectRepairCount
 | 
						|
        ));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (RebootRequired) {
 | 
						|
    DEBUG ((DEBUG_INFO, "[BDS] One of the Driver Health instances requires rebooting.\n"));
 | 
						|
    gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
 | 
						|
  }
 | 
						|
}
 |