REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the ArmPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Andrew Fish <afish@apple.com>
		
			
				
	
	
		
			1114 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1114 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Implementation for PlatformBootManagerLib library class interfaces.
 | 
						|
 | 
						|
  Copyright (C) 2015-2016, Red Hat, Inc.
 | 
						|
  Copyright (c) 2014 - 2021, ARM Ltd. All rights reserved.<BR>
 | 
						|
  Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
 | 
						|
  Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
 | 
						|
  Copyright (c) 2021, Semihalf All rights reserved.<BR>
 | 
						|
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include <IndustryStandard/Pci22.h>
 | 
						|
#include <Library/BootLogoLib.h>
 | 
						|
#include <Library/CapsuleLib.h>
 | 
						|
#include <Library/DevicePathLib.h>
 | 
						|
#include <Library/HobLib.h>
 | 
						|
#include <Library/PcdLib.h>
 | 
						|
#include <Library/UefiBootManagerLib.h>
 | 
						|
#include <Library/UefiLib.h>
 | 
						|
#include <Library/UefiRuntimeServicesTableLib.h>
 | 
						|
#include <Protocol/BootManagerPolicy.h>
 | 
						|
#include <Protocol/DevicePath.h>
 | 
						|
#include <Protocol/EsrtManagement.h>
 | 
						|
#include <Protocol/GraphicsOutput.h>
 | 
						|
#include <Protocol/LoadedImage.h>
 | 
						|
#include <Protocol/NonDiscoverableDevice.h>
 | 
						|
#include <Protocol/PciIo.h>
 | 
						|
#include <Protocol/PciRootBridgeIo.h>
 | 
						|
#include <Protocol/PlatformBootManager.h>
 | 
						|
#include <Guid/BootDiscoveryPolicy.h>
 | 
						|
#include <Guid/EventGroup.h>
 | 
						|
#include <Guid/NonDiscoverableDevice.h>
 | 
						|
#include <Guid/TtyTerm.h>
 | 
						|
#include <Guid/SerialPortLibVendor.h>
 | 
						|
 | 
						|
#include "PlatformBm.h"
 | 
						|
 | 
						|
#define DP_NODE_LEN(Type)  { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) }
 | 
						|
 | 
						|
#pragma pack (1)
 | 
						|
typedef struct {
 | 
						|
  VENDOR_DEVICE_PATH            SerialDxe;
 | 
						|
  UART_DEVICE_PATH              Uart;
 | 
						|
  VENDOR_DEFINED_DEVICE_PATH    TermType;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL      End;
 | 
						|
} PLATFORM_SERIAL_CONSOLE;
 | 
						|
#pragma pack ()
 | 
						|
 | 
						|
STATIC PLATFORM_SERIAL_CONSOLE  mSerialConsole = {
 | 
						|
  //
 | 
						|
  // VENDOR_DEVICE_PATH SerialDxe
 | 
						|
  //
 | 
						|
  {
 | 
						|
    { HARDWARE_DEVICE_PATH,  HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) },
 | 
						|
    EDKII_SERIAL_PORT_LIB_VENDOR_GUID
 | 
						|
  },
 | 
						|
 | 
						|
  //
 | 
						|
  // UART_DEVICE_PATH Uart
 | 
						|
  //
 | 
						|
  {
 | 
						|
    { MESSAGING_DEVICE_PATH, MSG_UART_DP,  DP_NODE_LEN (UART_DEVICE_PATH)   },
 | 
						|
    0,                                      // Reserved
 | 
						|
    FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate
 | 
						|
    FixedPcdGet8 (PcdUartDefaultDataBits),  // DataBits
 | 
						|
    FixedPcdGet8 (PcdUartDefaultParity),    // Parity
 | 
						|
    FixedPcdGet8 (PcdUartDefaultStopBits)   // StopBits
 | 
						|
  },
 | 
						|
 | 
						|
  //
 | 
						|
  // VENDOR_DEFINED_DEVICE_PATH TermType
 | 
						|
  //
 | 
						|
  {
 | 
						|
    {
 | 
						|
      MESSAGING_DEVICE_PATH, MSG_VENDOR_DP,
 | 
						|
      DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH)
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Guid to be filled in dynamically
 | 
						|
    //
 | 
						|
  },
 | 
						|
 | 
						|
  //
 | 
						|
  // EFI_DEVICE_PATH_PROTOCOL End
 | 
						|
  //
 | 
						|
  {
 | 
						|
    END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,
 | 
						|
    DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
#pragma pack (1)
 | 
						|
typedef struct {
 | 
						|
  USB_CLASS_DEVICE_PATH       Keyboard;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL    End;
 | 
						|
} PLATFORM_USB_KEYBOARD;
 | 
						|
#pragma pack ()
 | 
						|
 | 
						|
STATIC PLATFORM_USB_KEYBOARD  mUsbKeyboard = {
 | 
						|
  //
 | 
						|
  // USB_CLASS_DEVICE_PATH Keyboard
 | 
						|
  //
 | 
						|
  {
 | 
						|
    {
 | 
						|
      MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP,
 | 
						|
      DP_NODE_LEN (USB_CLASS_DEVICE_PATH)
 | 
						|
    },
 | 
						|
    0xFFFF, // VendorId: any
 | 
						|
    0xFFFF, // ProductId: any
 | 
						|
    3,      // DeviceClass: HID
 | 
						|
    1,      // DeviceSubClass: boot
 | 
						|
    1       // DeviceProtocol: keyboard
 | 
						|
  },
 | 
						|
 | 
						|
  //
 | 
						|
  // EFI_DEVICE_PATH_PROTOCOL End
 | 
						|
  //
 | 
						|
  {
 | 
						|
    END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,
 | 
						|
    DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
  Check if the handle satisfies a particular condition.
 | 
						|
 | 
						|
  @param[in] Handle      The handle to check.
 | 
						|
  @param[in] ReportText  A caller-allocated string passed in for reporting
 | 
						|
                         purposes. It must never be NULL.
 | 
						|
 | 
						|
  @retval TRUE   The condition is satisfied.
 | 
						|
  @retval FALSE  Otherwise. This includes the case when the condition could not
 | 
						|
                 be fully evaluated due to an error.
 | 
						|
**/
 | 
						|
typedef
 | 
						|
BOOLEAN
 | 
						|
(EFIAPI *FILTER_FUNCTION)(
 | 
						|
  IN EFI_HANDLE   Handle,
 | 
						|
  IN CONST CHAR16 *ReportText
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Process a handle.
 | 
						|
 | 
						|
  @param[in] Handle      The handle to process.
 | 
						|
  @param[in] ReportText  A caller-allocated string passed in for reporting
 | 
						|
                         purposes. It must never be NULL.
 | 
						|
**/
 | 
						|
typedef
 | 
						|
VOID
 | 
						|
(EFIAPI *CALLBACK_FUNCTION)(
 | 
						|
  IN EFI_HANDLE   Handle,
 | 
						|
  IN CONST CHAR16 *ReportText
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Locate all handles that carry the specified protocol, filter them with a
 | 
						|
  callback function, and pass each handle that passes the filter to another
 | 
						|
  callback.
 | 
						|
 | 
						|
  @param[in] ProtocolGuid  The protocol to look for.
 | 
						|
 | 
						|
  @param[in] Filter        The filter function to pass each handle to. If this
 | 
						|
                           parameter is NULL, then all handles are processed.
 | 
						|
 | 
						|
  @param[in] Process       The callback function to pass each handle to that
 | 
						|
                           clears the filter.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
FilterAndProcess (
 | 
						|
  IN EFI_GUID           *ProtocolGuid,
 | 
						|
  IN FILTER_FUNCTION    Filter         OPTIONAL,
 | 
						|
  IN CALLBACK_FUNCTION  Process
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  EFI_HANDLE  *Handles;
 | 
						|
  UINTN       NoHandles;
 | 
						|
  UINTN       Idx;
 | 
						|
 | 
						|
  Status = gBS->LocateHandleBuffer (
 | 
						|
                  ByProtocol,
 | 
						|
                  ProtocolGuid,
 | 
						|
                  NULL /* SearchKey */,
 | 
						|
                  &NoHandles,
 | 
						|
                  &Handles
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    //
 | 
						|
    // This is not an error, just an informative condition.
 | 
						|
    //
 | 
						|
    DEBUG ((
 | 
						|
      DEBUG_VERBOSE,
 | 
						|
      "%a: %g: %r\n",
 | 
						|
      __FUNCTION__,
 | 
						|
      ProtocolGuid,
 | 
						|
      Status
 | 
						|
      ));
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  ASSERT (NoHandles > 0);
 | 
						|
  for (Idx = 0; Idx < NoHandles; ++Idx) {
 | 
						|
    CHAR16         *DevicePathText;
 | 
						|
    STATIC CHAR16  Fallback[] = L"<device path unavailable>";
 | 
						|
 | 
						|
    //
 | 
						|
    // The ConvertDevicePathToText() function handles NULL input transparently.
 | 
						|
    //
 | 
						|
    DevicePathText = ConvertDevicePathToText (
 | 
						|
                       DevicePathFromHandle (Handles[Idx]),
 | 
						|
                       FALSE, // DisplayOnly
 | 
						|
                       FALSE  // AllowShortcuts
 | 
						|
                       );
 | 
						|
    if (DevicePathText == NULL) {
 | 
						|
      DevicePathText = Fallback;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((Filter == NULL) || Filter (Handles[Idx], DevicePathText)) {
 | 
						|
      Process (Handles[Idx], DevicePathText);
 | 
						|
    }
 | 
						|
 | 
						|
    if (DevicePathText != Fallback) {
 | 
						|
      FreePool (DevicePathText);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  gBS->FreePool (Handles);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This FILTER_FUNCTION checks if a handle corresponds to a PCI display device.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
BOOLEAN
 | 
						|
EFIAPI
 | 
						|
IsPciDisplay (
 | 
						|
  IN EFI_HANDLE    Handle,
 | 
						|
  IN CONST CHAR16  *ReportText
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS           Status;
 | 
						|
  EFI_PCI_IO_PROTOCOL  *PciIo;
 | 
						|
  PCI_TYPE00           Pci;
 | 
						|
 | 
						|
  Status = gBS->HandleProtocol (
 | 
						|
                  Handle,
 | 
						|
                  &gEfiPciIoProtocolGuid,
 | 
						|
                  (VOID **)&PciIo
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    //
 | 
						|
    // This is not an error worth reporting.
 | 
						|
    //
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = PciIo->Pci.Read (
 | 
						|
                        PciIo,
 | 
						|
                        EfiPciIoWidthUint32,
 | 
						|
                        0 /* Offset */,
 | 
						|
                        sizeof Pci / sizeof (UINT32),
 | 
						|
                        &Pci
 | 
						|
                        );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "%a: %s: %r\n", __FUNCTION__, ReportText, Status));
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  return IS_PCI_DISPLAY (&Pci);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This FILTER_FUNCTION checks if a handle corresponds to a non-discoverable
 | 
						|
  USB host controller.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
BOOLEAN
 | 
						|
EFIAPI
 | 
						|
IsUsbHost (
 | 
						|
  IN EFI_HANDLE    Handle,
 | 
						|
  IN CONST CHAR16  *ReportText
 | 
						|
  )
 | 
						|
{
 | 
						|
  NON_DISCOVERABLE_DEVICE  *Device;
 | 
						|
  EFI_STATUS               Status;
 | 
						|
 | 
						|
  Status = gBS->HandleProtocol (
 | 
						|
                  Handle,
 | 
						|
                  &gEdkiiNonDiscoverableDeviceProtocolGuid,
 | 
						|
                  (VOID **)&Device
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  if (CompareGuid (Device->Type, &gEdkiiNonDiscoverableUhciDeviceGuid) ||
 | 
						|
      CompareGuid (Device->Type, &gEdkiiNonDiscoverableEhciDeviceGuid) ||
 | 
						|
      CompareGuid (Device->Type, &gEdkiiNonDiscoverableXhciDeviceGuid))
 | 
						|
  {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking
 | 
						|
  the matching driver to produce all first-level child handles.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
Connect (
 | 
						|
  IN EFI_HANDLE    Handle,
 | 
						|
  IN CONST CHAR16  *ReportText
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  Status = gBS->ConnectController (
 | 
						|
                  Handle, // ControllerHandle
 | 
						|
                  NULL,   // DriverImageHandle
 | 
						|
                  NULL,   // RemainingDevicePath -- produce all children
 | 
						|
                  FALSE   // Recursive
 | 
						|
                  );
 | 
						|
  DEBUG ((
 | 
						|
    EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE,
 | 
						|
    "%a: %s: %r\n",
 | 
						|
    __FUNCTION__,
 | 
						|
    ReportText,
 | 
						|
    Status
 | 
						|
    ));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the
 | 
						|
  handle, and adds it to ConOut and ErrOut.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
AddOutput (
 | 
						|
  IN EFI_HANDLE    Handle,
 | 
						|
  IN CONST CHAR16  *ReportText
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
 | 
						|
 | 
						|
  DevicePath = DevicePathFromHandle (Handle);
 | 
						|
  if (DevicePath == NULL) {
 | 
						|
    DEBUG ((
 | 
						|
      DEBUG_ERROR,
 | 
						|
      "%a: %s: handle %p: device path not found\n",
 | 
						|
      __FUNCTION__,
 | 
						|
      ReportText,
 | 
						|
      Handle
 | 
						|
      ));
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((
 | 
						|
      DEBUG_ERROR,
 | 
						|
      "%a: %s: adding to ConOut: %r\n",
 | 
						|
      __FUNCTION__,
 | 
						|
      ReportText,
 | 
						|
      Status
 | 
						|
      ));
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((
 | 
						|
      DEBUG_ERROR,
 | 
						|
      "%a: %s: adding to ErrOut: %r\n",
 | 
						|
      __FUNCTION__,
 | 
						|
      ReportText,
 | 
						|
      Status
 | 
						|
      ));
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((
 | 
						|
    DEBUG_VERBOSE,
 | 
						|
    "%a: %s: added to ConOut and ErrOut\n",
 | 
						|
    __FUNCTION__,
 | 
						|
    ReportText
 | 
						|
    ));
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
PlatformRegisterFvBootOption (
 | 
						|
  CONST EFI_GUID  *FileGuid,
 | 
						|
  CHAR16          *Description,
 | 
						|
  UINT32          Attributes,
 | 
						|
  EFI_INPUT_KEY   *Key
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                         Status;
 | 
						|
  INTN                               OptionIndex;
 | 
						|
  EFI_BOOT_MANAGER_LOAD_OPTION       NewOption;
 | 
						|
  EFI_BOOT_MANAGER_LOAD_OPTION       *BootOptions;
 | 
						|
  UINTN                              BootOptionCount;
 | 
						|
  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  FileNode;
 | 
						|
  EFI_LOADED_IMAGE_PROTOCOL          *LoadedImage;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL           *DevicePath;
 | 
						|
 | 
						|
  Status = gBS->HandleProtocol (
 | 
						|
                  gImageHandle,
 | 
						|
                  &gEfiLoadedImageProtocolGuid,
 | 
						|
                  (VOID **)&LoadedImage
 | 
						|
                  );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);
 | 
						|
  DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle);
 | 
						|
  ASSERT (DevicePath != NULL);
 | 
						|
  DevicePath = AppendDevicePathNode (
 | 
						|
                 DevicePath,
 | 
						|
                 (EFI_DEVICE_PATH_PROTOCOL *)&FileNode
 | 
						|
                 );
 | 
						|
  ASSERT (DevicePath != NULL);
 | 
						|
 | 
						|
  Status = EfiBootManagerInitializeLoadOption (
 | 
						|
             &NewOption,
 | 
						|
             LoadOptionNumberUnassigned,
 | 
						|
             LoadOptionTypeBoot,
 | 
						|
             Attributes,
 | 
						|
             Description,
 | 
						|
             DevicePath,
 | 
						|
             NULL,
 | 
						|
             0
 | 
						|
             );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
  FreePool (DevicePath);
 | 
						|
 | 
						|
  BootOptions = EfiBootManagerGetLoadOptions (
 | 
						|
                  &BootOptionCount,
 | 
						|
                  LoadOptionTypeBoot
 | 
						|
                  );
 | 
						|
 | 
						|
  OptionIndex = EfiBootManagerFindLoadOption (
 | 
						|
                  &NewOption,
 | 
						|
                  BootOptions,
 | 
						|
                  BootOptionCount
 | 
						|
                  );
 | 
						|
 | 
						|
  if (OptionIndex == -1) {
 | 
						|
    Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN);
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
    Status = EfiBootManagerAddKeyOptionVariable (
 | 
						|
               NULL,
 | 
						|
               (UINT16)NewOption.OptionNumber,
 | 
						|
               0,
 | 
						|
               Key,
 | 
						|
               NULL
 | 
						|
               );
 | 
						|
    ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
 | 
						|
  }
 | 
						|
 | 
						|
  EfiBootManagerFreeLoadOption (&NewOption);
 | 
						|
  EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
GetPlatformOptions (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                      Status;
 | 
						|
  EFI_BOOT_MANAGER_LOAD_OPTION    *CurrentBootOptions;
 | 
						|
  EFI_BOOT_MANAGER_LOAD_OPTION    *BootOptions;
 | 
						|
  EFI_INPUT_KEY                   *BootKeys;
 | 
						|
  PLATFORM_BOOT_MANAGER_PROTOCOL  *PlatformBootManager;
 | 
						|
  UINTN                           CurrentBootOptionCount;
 | 
						|
  UINTN                           Index;
 | 
						|
  UINTN                           BootCount;
 | 
						|
 | 
						|
  Status = gBS->LocateProtocol (
 | 
						|
                  &gPlatformBootManagerProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  (VOID **)&PlatformBootManager
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = PlatformBootManager->GetPlatformBootOptionsAndKeys (
 | 
						|
                                  &BootCount,
 | 
						|
                                  &BootOptions,
 | 
						|
                                  &BootKeys
 | 
						|
                                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Fetch the existent boot options. If there are none, CurrentBootCount
 | 
						|
  // will be zeroed.
 | 
						|
  //
 | 
						|
  CurrentBootOptions = EfiBootManagerGetLoadOptions (
 | 
						|
                         &CurrentBootOptionCount,
 | 
						|
                         LoadOptionTypeBoot
 | 
						|
                         );
 | 
						|
  //
 | 
						|
  // Process the platform boot options.
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < BootCount; Index++) {
 | 
						|
    INTN   Match;
 | 
						|
    UINTN  BootOptionNumber;
 | 
						|
 | 
						|
    //
 | 
						|
    // If there are any preexistent boot options, and the subject platform boot
 | 
						|
    // option is already among them, then don't try to add it. Just get its
 | 
						|
    // assigned boot option number so we can associate a hotkey with it. Note
 | 
						|
    // that EfiBootManagerFindLoadOption() deals fine with (CurrentBootOptions
 | 
						|
    // == NULL) if (CurrentBootCount == 0).
 | 
						|
    //
 | 
						|
    Match = EfiBootManagerFindLoadOption (
 | 
						|
              &BootOptions[Index],
 | 
						|
              CurrentBootOptions,
 | 
						|
              CurrentBootOptionCount
 | 
						|
              );
 | 
						|
    if (Match >= 0) {
 | 
						|
      BootOptionNumber = CurrentBootOptions[Match].OptionNumber;
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // Add the platform boot options as a new one, at the end of the boot
 | 
						|
      // order. Note that if the platform provided this boot option with an
 | 
						|
      // unassigned option number, then the below function call will assign a
 | 
						|
      // number.
 | 
						|
      //
 | 
						|
      Status = EfiBootManagerAddLoadOptionVariable (
 | 
						|
                 &BootOptions[Index],
 | 
						|
                 MAX_UINTN
 | 
						|
                 );
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        DEBUG ((
 | 
						|
          DEBUG_ERROR,
 | 
						|
          "%a: failed to register \"%s\": %r\n",
 | 
						|
          __FUNCTION__,
 | 
						|
          BootOptions[Index].Description,
 | 
						|
          Status
 | 
						|
          ));
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
 | 
						|
      BootOptionNumber = BootOptions[Index].OptionNumber;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Register a hotkey with the boot option, if requested.
 | 
						|
    //
 | 
						|
    if (BootKeys[Index].UnicodeChar == L'\0') {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = EfiBootManagerAddKeyOptionVariable (
 | 
						|
               NULL,
 | 
						|
               BootOptionNumber,
 | 
						|
               0,
 | 
						|
               &BootKeys[Index],
 | 
						|
               NULL
 | 
						|
               );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((
 | 
						|
        DEBUG_ERROR,
 | 
						|
        "%a: failed to register hotkey for \"%s\": %r\n",
 | 
						|
        __FUNCTION__,
 | 
						|
        BootOptions[Index].Description,
 | 
						|
        Status
 | 
						|
        ));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  EfiBootManagerFreeLoadOptions (CurrentBootOptions, CurrentBootOptionCount);
 | 
						|
  EfiBootManagerFreeLoadOptions (BootOptions, BootCount);
 | 
						|
  FreePool (BootKeys);
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
PlatformRegisterOptionsAndKeys (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                    Status;
 | 
						|
  EFI_INPUT_KEY                 Enter;
 | 
						|
  EFI_INPUT_KEY                 F2;
 | 
						|
  EFI_INPUT_KEY                 Esc;
 | 
						|
  EFI_BOOT_MANAGER_LOAD_OPTION  BootOption;
 | 
						|
 | 
						|
  GetPlatformOptions ();
 | 
						|
 | 
						|
  //
 | 
						|
  // Register ENTER as CONTINUE key
 | 
						|
  //
 | 
						|
  Enter.ScanCode    = SCAN_NULL;
 | 
						|
  Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;
 | 
						|
  Status            = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  //
 | 
						|
  // Map F2 and ESC to Boot Manager Menu
 | 
						|
  //
 | 
						|
  F2.ScanCode     = SCAN_F2;
 | 
						|
  F2.UnicodeChar  = CHAR_NULL;
 | 
						|
  Esc.ScanCode    = SCAN_ESC;
 | 
						|
  Esc.UnicodeChar = CHAR_NULL;
 | 
						|
  Status          = EfiBootManagerGetBootManagerMenu (&BootOption);
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
  Status = EfiBootManagerAddKeyOptionVariable (
 | 
						|
             NULL,
 | 
						|
             (UINT16)BootOption.OptionNumber,
 | 
						|
             0,
 | 
						|
             &F2,
 | 
						|
             NULL
 | 
						|
             );
 | 
						|
  ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
 | 
						|
  Status = EfiBootManagerAddKeyOptionVariable (
 | 
						|
             NULL,
 | 
						|
             (UINT16)BootOption.OptionNumber,
 | 
						|
             0,
 | 
						|
             &Esc,
 | 
						|
             NULL
 | 
						|
             );
 | 
						|
  ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// BDS Platform Functions
 | 
						|
//
 | 
						|
 | 
						|
/**
 | 
						|
  Do the platform init, can be customized by OEM/IBV
 | 
						|
  Possible things that can be done in PlatformBootManagerBeforeConsole:
 | 
						|
  > Update console variable: 1. include hot-plug devices;
 | 
						|
  >                          2. Clear ConIn and add SOL for AMT
 | 
						|
  > Register new Driver#### or Boot####
 | 
						|
  > Register new Key####: e.g.: F12
 | 
						|
  > Signal ReadyToLock event
 | 
						|
  > Authentication action: 1. connect Auth devices;
 | 
						|
  >                        2. Identify auto logon user.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
PlatformBootManagerBeforeConsole (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // Signal EndOfDxe PI Event
 | 
						|
  //
 | 
						|
  EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);
 | 
						|
 | 
						|
  //
 | 
						|
  // Dispatch deferred images after EndOfDxe event.
 | 
						|
  //
 | 
						|
  EfiBootManagerDispatchDeferredImages ();
 | 
						|
 | 
						|
  //
 | 
						|
  // Locate the PCI root bridges and make the PCI bus driver connect each,
 | 
						|
  // non-recursively. This will produce a number of child handles with PciIo on
 | 
						|
  // them.
 | 
						|
  //
 | 
						|
  FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid, NULL, Connect);
 | 
						|
 | 
						|
  //
 | 
						|
  // Find all display class PCI devices (using the handles from the previous
 | 
						|
  // step), and connect them non-recursively. This should produce a number of
 | 
						|
  // child handles with GOPs on them.
 | 
						|
  //
 | 
						|
  FilterAndProcess (&gEfiPciIoProtocolGuid, IsPciDisplay, Connect);
 | 
						|
 | 
						|
  //
 | 
						|
  // Now add the device path of all handles with GOP on them to ConOut and
 | 
						|
  // ErrOut.
 | 
						|
  //
 | 
						|
  FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput);
 | 
						|
 | 
						|
  //
 | 
						|
  // The core BDS code connects short-form USB device paths by explicitly
 | 
						|
  // looking for handles with PCI I/O installed, and checking the PCI class
 | 
						|
  // code whether it matches the one for a USB host controller. This means
 | 
						|
  // non-discoverable USB host controllers need to have the non-discoverable
 | 
						|
  // PCI driver attached first.
 | 
						|
  //
 | 
						|
  FilterAndProcess (&gEdkiiNonDiscoverableDeviceProtocolGuid, IsUsbHost, Connect);
 | 
						|
 | 
						|
  //
 | 
						|
  // Add the hardcoded short-form USB keyboard device path to ConIn.
 | 
						|
  //
 | 
						|
  EfiBootManagerUpdateConsoleVariable (
 | 
						|
    ConIn,
 | 
						|
    (EFI_DEVICE_PATH_PROTOCOL *)&mUsbKeyboard,
 | 
						|
    NULL
 | 
						|
    );
 | 
						|
 | 
						|
  //
 | 
						|
  // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut.
 | 
						|
  //
 | 
						|
  STATIC_ASSERT (
 | 
						|
    FixedPcdGet8 (PcdDefaultTerminalType) == 4,
 | 
						|
    "PcdDefaultTerminalType must be TTYTERM"
 | 
						|
    );
 | 
						|
  STATIC_ASSERT (
 | 
						|
    FixedPcdGet8 (PcdUartDefaultParity) != 0,
 | 
						|
    "PcdUartDefaultParity must be set to an actual value, not 'default'"
 | 
						|
    );
 | 
						|
  STATIC_ASSERT (
 | 
						|
    FixedPcdGet8 (PcdUartDefaultStopBits) != 0,
 | 
						|
    "PcdUartDefaultStopBits must be set to an actual value, not 'default'"
 | 
						|
    );
 | 
						|
 | 
						|
  CopyGuid (&mSerialConsole.TermType.Guid, &gEfiTtyTermGuid);
 | 
						|
 | 
						|
  EfiBootManagerUpdateConsoleVariable (
 | 
						|
    ConIn,
 | 
						|
    (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole,
 | 
						|
    NULL
 | 
						|
    );
 | 
						|
  EfiBootManagerUpdateConsoleVariable (
 | 
						|
    ConOut,
 | 
						|
    (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole,
 | 
						|
    NULL
 | 
						|
    );
 | 
						|
  EfiBootManagerUpdateConsoleVariable (
 | 
						|
    ErrOut,
 | 
						|
    (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole,
 | 
						|
    NULL
 | 
						|
    );
 | 
						|
 | 
						|
  //
 | 
						|
  // Register platform-specific boot options and keyboard shortcuts.
 | 
						|
  //
 | 
						|
  PlatformRegisterOptionsAndKeys ();
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
HandleCapsules (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  ESRT_MANAGEMENT_PROTOCOL  *EsrtManagement;
 | 
						|
  EFI_PEI_HOB_POINTERS      HobPointer;
 | 
						|
  EFI_CAPSULE_HEADER        *CapsuleHeader;
 | 
						|
  BOOLEAN                   NeedReset;
 | 
						|
  EFI_STATUS                Status;
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "%a: processing capsules ...\n", __FUNCTION__));
 | 
						|
 | 
						|
  Status = gBS->LocateProtocol (
 | 
						|
                  &gEsrtManagementProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  (VOID **)&EsrtManagement
 | 
						|
                  );
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    EsrtManagement->SyncEsrtFmp ();
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Find all capsule images from hob
 | 
						|
  //
 | 
						|
  HobPointer.Raw = GetHobList ();
 | 
						|
  NeedReset      = FALSE;
 | 
						|
  while ((HobPointer.Raw = GetNextHob (
 | 
						|
                             EFI_HOB_TYPE_UEFI_CAPSULE,
 | 
						|
                             HobPointer.Raw
 | 
						|
                             )) != NULL)
 | 
						|
  {
 | 
						|
    CapsuleHeader = (VOID *)(UINTN)HobPointer.Capsule->BaseAddress;
 | 
						|
 | 
						|
    Status = ProcessCapsuleImage (CapsuleHeader);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((
 | 
						|
        DEBUG_ERROR,
 | 
						|
        "%a: failed to process capsule %p - %r\n",
 | 
						|
        __FUNCTION__,
 | 
						|
        CapsuleHeader,
 | 
						|
        Status
 | 
						|
        ));
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    NeedReset      = TRUE;
 | 
						|
    HobPointer.Raw = GET_NEXT_HOB (HobPointer);
 | 
						|
  }
 | 
						|
 | 
						|
  if (NeedReset) {
 | 
						|
    DEBUG ((
 | 
						|
      DEBUG_WARN,
 | 
						|
      "%a: capsule update successful, resetting ...\n",
 | 
						|
      __FUNCTION__
 | 
						|
      ));
 | 
						|
 | 
						|
    gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
 | 
						|
    CpuDeadLoop ();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
#define VERSION_STRING_PREFIX  L"Tianocore/EDK2 firmware version "
 | 
						|
 | 
						|
/**
 | 
						|
  This functions checks the value of BootDiscoverPolicy variable and
 | 
						|
  connect devices of class specified by that variable. Then it refreshes
 | 
						|
  Boot order for newly discovered boot device.
 | 
						|
 | 
						|
  @retval  EFI_SUCCESS  Devices connected successfully or connection
 | 
						|
                        not required.
 | 
						|
  @retval  others       Return values from GetVariable(), LocateProtocol()
 | 
						|
                        and ConnectDeviceClass().
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
BootDiscoveryPolicyHandler (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  UINT32                            DiscoveryPolicy;
 | 
						|
  UINT32                            DiscoveryPolicyOld;
 | 
						|
  UINTN                             Size;
 | 
						|
  EFI_BOOT_MANAGER_POLICY_PROTOCOL  *BMPolicy;
 | 
						|
  EFI_GUID                          *Class;
 | 
						|
 | 
						|
  Size   = sizeof (DiscoveryPolicy);
 | 
						|
  Status = gRT->GetVariable (
 | 
						|
                  BOOT_DISCOVERY_POLICY_VAR,
 | 
						|
                  &gBootDiscoveryPolicyMgrFormsetGuid,
 | 
						|
                  NULL,
 | 
						|
                  &Size,
 | 
						|
                  &DiscoveryPolicy
 | 
						|
                  );
 | 
						|
  if (Status == EFI_NOT_FOUND) {
 | 
						|
    DiscoveryPolicy = PcdGet32 (PcdBootDiscoveryPolicy);
 | 
						|
    Status          = PcdSet32S (PcdBootDiscoveryPolicy, DiscoveryPolicy);
 | 
						|
    if (Status == EFI_NOT_FOUND) {
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    } else if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  } else if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  if (DiscoveryPolicy == BDP_CONNECT_MINIMAL) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  switch (DiscoveryPolicy) {
 | 
						|
    case BDP_CONNECT_NET:
 | 
						|
      Class = &gEfiBootManagerPolicyNetworkGuid;
 | 
						|
      break;
 | 
						|
    case BDP_CONNECT_ALL:
 | 
						|
      Class = &gEfiBootManagerPolicyConnectAllGuid;
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      DEBUG ((
 | 
						|
        DEBUG_INFO,
 | 
						|
        "%a - Unexpected DiscoveryPolicy (0x%x). Run Minimal Discovery Policy\n",
 | 
						|
        __FUNCTION__,
 | 
						|
        DiscoveryPolicy
 | 
						|
        ));
 | 
						|
      return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->LocateProtocol (
 | 
						|
                  &gEfiBootManagerPolicyProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  (VOID **)&BMPolicy
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((
 | 
						|
      DEBUG_INFO,
 | 
						|
      "%a - Failed to locate gEfiBootManagerPolicyProtocolGuid."
 | 
						|
      "Driver connect will be skipped.\n",
 | 
						|
      __FUNCTION__
 | 
						|
      ));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = BMPolicy->ConnectDeviceClass (BMPolicy, Class);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "%a - ConnectDeviceClass returns - %r\n", __FUNCTION__, Status));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Refresh Boot Options if Boot Discovery Policy has been changed
 | 
						|
  //
 | 
						|
  Size   = sizeof (DiscoveryPolicyOld);
 | 
						|
  Status = gRT->GetVariable (
 | 
						|
                  BOOT_DISCOVERY_POLICY_OLD_VAR,
 | 
						|
                  &gBootDiscoveryPolicyMgrFormsetGuid,
 | 
						|
                  NULL,
 | 
						|
                  &Size,
 | 
						|
                  &DiscoveryPolicyOld
 | 
						|
                  );
 | 
						|
  if ((Status == EFI_NOT_FOUND) || (DiscoveryPolicyOld != DiscoveryPolicy)) {
 | 
						|
    EfiBootManagerRefreshAllBootOption ();
 | 
						|
 | 
						|
    Status = gRT->SetVariable (
 | 
						|
                    BOOT_DISCOVERY_POLICY_OLD_VAR,
 | 
						|
                    &gBootDiscoveryPolicyMgrFormsetGuid,
 | 
						|
                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
 | 
						|
                    sizeof (DiscoveryPolicyOld),
 | 
						|
                    &DiscoveryPolicy
 | 
						|
                    );
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Do the platform specific action after the console is ready
 | 
						|
  Possible things that can be done in PlatformBootManagerAfterConsole:
 | 
						|
  > Console post action:
 | 
						|
    > Dynamically switch output mode from 100x31 to 80x25 for certain scenario
 | 
						|
    > Signal console ready platform customized event
 | 
						|
  > Run diagnostics like memory testing
 | 
						|
  > Connect certain devices
 | 
						|
  > Dispatch additional option roms
 | 
						|
  > Special boot: e.g.: USB boot, enter UI
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
PlatformBootManagerAfterConsole (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                    Status;
 | 
						|
  EFI_GRAPHICS_OUTPUT_PROTOCOL  *GraphicsOutput;
 | 
						|
  UINTN                         FirmwareVerLength;
 | 
						|
  UINTN                         PosX;
 | 
						|
  UINTN                         PosY;
 | 
						|
  EFI_INPUT_KEY                 Key;
 | 
						|
 | 
						|
  FirmwareVerLength = StrLen (PcdGetPtr (PcdFirmwareVersionString));
 | 
						|
 | 
						|
  //
 | 
						|
  // Show the splash screen.
 | 
						|
  //
 | 
						|
  Status = BootLogoEnableLogo ();
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    if (FirmwareVerLength > 0) {
 | 
						|
      Print (
 | 
						|
        VERSION_STRING_PREFIX L"%s\n",
 | 
						|
        PcdGetPtr (PcdFirmwareVersionString)
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    Print (L"Press ESCAPE for boot options ");
 | 
						|
  } else if (FirmwareVerLength > 0) {
 | 
						|
    Status = gBS->HandleProtocol (
 | 
						|
                    gST->ConsoleOutHandle,
 | 
						|
                    &gEfiGraphicsOutputProtocolGuid,
 | 
						|
                    (VOID **)&GraphicsOutput
 | 
						|
                    );
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      PosX = (GraphicsOutput->Mode->Info->HorizontalResolution -
 | 
						|
              (StrLen (VERSION_STRING_PREFIX) + FirmwareVerLength) *
 | 
						|
              EFI_GLYPH_WIDTH) / 2;
 | 
						|
      PosY = 0;
 | 
						|
 | 
						|
      PrintXY (
 | 
						|
        PosX,
 | 
						|
        PosY,
 | 
						|
        NULL,
 | 
						|
        NULL,
 | 
						|
        VERSION_STRING_PREFIX L"%s",
 | 
						|
        PcdGetPtr (PcdFirmwareVersionString)
 | 
						|
        );
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Connect device specified by BootDiscoverPolicy variable and
 | 
						|
  // refresh Boot order for newly discovered boot devices
 | 
						|
  //
 | 
						|
  BootDiscoveryPolicyHandler ();
 | 
						|
 | 
						|
  //
 | 
						|
  // On ARM, there is currently no reason to use the phased capsule
 | 
						|
  // update approach where some capsules are dispatched before EndOfDxe
 | 
						|
  // and some are dispatched after. So just handle all capsules here,
 | 
						|
  // when the console is up and we can actually give the user some
 | 
						|
  // feedback about what is going on.
 | 
						|
  //
 | 
						|
  HandleCapsules ();
 | 
						|
 | 
						|
  //
 | 
						|
  // Register UEFI Shell
 | 
						|
  //
 | 
						|
  Key.ScanCode    = SCAN_NULL;
 | 
						|
  Key.UnicodeChar = L's';
 | 
						|
  PlatformRegisterFvBootOption (&gUefiShellFileGuid, L"UEFI Shell", 0, &Key);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function is called each second during the boot manager waits the
 | 
						|
  timeout.
 | 
						|
 | 
						|
  @param TimeoutRemain  The remaining timeout.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
PlatformBootManagerWaitCallback (
 | 
						|
  UINT16  TimeoutRemain
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION  Black;
 | 
						|
  EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION  White;
 | 
						|
  UINT16                               Timeout;
 | 
						|
  EFI_STATUS                           Status;
 | 
						|
 | 
						|
  Timeout = PcdGet16 (PcdPlatformBootTimeOut);
 | 
						|
 | 
						|
  Black.Raw = 0x00000000;
 | 
						|
  White.Raw = 0x00FFFFFF;
 | 
						|
 | 
						|
  Status = BootLogoUpdateProgress (
 | 
						|
             White.Pixel,
 | 
						|
             Black.Pixel,
 | 
						|
             L"Press ESCAPE for boot options",
 | 
						|
             White.Pixel,
 | 
						|
             (Timeout - TimeoutRemain) * 100 / Timeout,
 | 
						|
             0
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Print (L".");
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  The function is called when no boot option could be launched,
 | 
						|
  including platform recovery options and options pointing to applications
 | 
						|
  built into firmware volumes.
 | 
						|
 | 
						|
  If this function returns, BDS attempts to enter an infinite loop.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
PlatformBootManagerUnableToBoot (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                    Status;
 | 
						|
  EFI_BOOT_MANAGER_LOAD_OPTION  BootManagerMenu;
 | 
						|
  EFI_BOOT_MANAGER_LOAD_OPTION  *BootOptions;
 | 
						|
  UINTN                         OldBootOptionCount;
 | 
						|
  UINTN                         NewBootOptionCount;
 | 
						|
 | 
						|
  //
 | 
						|
  // Record the total number of boot configured boot options
 | 
						|
  //
 | 
						|
  BootOptions = EfiBootManagerGetLoadOptions (
 | 
						|
                  &OldBootOptionCount,
 | 
						|
                  LoadOptionTypeBoot
 | 
						|
                  );
 | 
						|
  EfiBootManagerFreeLoadOptions (BootOptions, OldBootOptionCount);
 | 
						|
 | 
						|
  //
 | 
						|
  // Connect all devices, and regenerate all boot options
 | 
						|
  //
 | 
						|
  EfiBootManagerConnectAll ();
 | 
						|
  EfiBootManagerRefreshAllBootOption ();
 | 
						|
 | 
						|
  //
 | 
						|
  // Record the updated number of boot configured boot options
 | 
						|
  //
 | 
						|
  BootOptions = EfiBootManagerGetLoadOptions (
 | 
						|
                  &NewBootOptionCount,
 | 
						|
                  LoadOptionTypeBoot
 | 
						|
                  );
 | 
						|
  EfiBootManagerFreeLoadOptions (BootOptions, NewBootOptionCount);
 | 
						|
 | 
						|
  //
 | 
						|
  // If the number of configured boot options has changed, reboot
 | 
						|
  // the system so the new boot options will be taken into account
 | 
						|
  // while executing the ordinary BDS bootflow sequence.
 | 
						|
  // *Unless* persistent varstore is being emulated, since we would
 | 
						|
  // then end up in an endless reboot loop.
 | 
						|
  //
 | 
						|
  if (!PcdGetBool (PcdEmuVariableNvModeEnable)) {
 | 
						|
    if (NewBootOptionCount != OldBootOptionCount) {
 | 
						|
      DEBUG ((
 | 
						|
        DEBUG_WARN,
 | 
						|
        "%a: rebooting after refreshing all boot options\n",
 | 
						|
        __FUNCTION__
 | 
						|
        ));
 | 
						|
      gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  Status = EfiBootManagerGetBootManagerMenu (&BootManagerMenu);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  for ( ; ;) {
 | 
						|
    EfiBootManagerBoot (&BootManagerMenu);
 | 
						|
  }
 | 
						|
}
 |