REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4347 To put UiApp.inf and BootManagerMenuApp.inf to proper FV(BDSFV) Cc: Guo Dong <guo.dong@intel.com> Cc: Ray Ni <ray.ni@intel.com> Cc: Sean Rhodes <sean@starlabs.systems> Reviewed-by: James Lu <james.lu@intel.com> Reviewed-by: Gua Guo <gua.guo@intel.com> Signed-off-by: MarsX Lin <marsx.lin@intel.com>
		
			
				
	
	
		
			365 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			365 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  This file include all platform action which can be customized
 | 
						|
  by IBV/OEM.
 | 
						|
 | 
						|
Copyright (c) 2015 - 2023, Intel Corporation. All rights reserved.<BR>
 | 
						|
SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "PlatformBootManager.h"
 | 
						|
#include "PlatformConsole.h"
 | 
						|
#include <Protocol/FirmwareVolume2.h>
 | 
						|
 | 
						|
/**
 | 
						|
  Signal EndOfDxe event and install SMM Ready to lock protocol.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
InstallReadyToLock (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  EFI_HANDLE                Handle;
 | 
						|
  EFI_SMM_ACCESS2_PROTOCOL  *SmmAccess;
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "InstallReadyToLock  entering......\n"));
 | 
						|
  //
 | 
						|
  // Inform the SMM infrastructure that we're entering BDS and may run 3rd party code hereafter
 | 
						|
  // Since PI1.2.1, we need signal EndOfDxe as ExitPmAuth
 | 
						|
  //
 | 
						|
  EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);
 | 
						|
  DEBUG ((DEBUG_INFO, "All EndOfDxe callbacks have returned successfully\n"));
 | 
						|
 | 
						|
  //
 | 
						|
  // Install DxeSmmReadyToLock protocol in order to lock SMM
 | 
						|
  //
 | 
						|
  Status = gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **)&SmmAccess);
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    Handle = NULL;
 | 
						|
    Status = gBS->InstallProtocolInterface (
 | 
						|
                    &Handle,
 | 
						|
                    &gEfiDxeSmmReadyToLockProtocolGuid,
 | 
						|
                    EFI_NATIVE_INTERFACE,
 | 
						|
                    NULL
 | 
						|
                    );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "InstallReadyToLock  end\n"));
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Return the index of the load option in the load option array.
 | 
						|
 | 
						|
  The function consider two load options are equal when the
 | 
						|
  OptionType, Attributes, Description, FilePath and OptionalData are equal.
 | 
						|
 | 
						|
  @param Key    Pointer to the load option to be found.
 | 
						|
  @param Array  Pointer to the array of load options to be found.
 | 
						|
  @param Count  Number of entries in the Array.
 | 
						|
 | 
						|
  @retval -1          Key wasn't found in the Array.
 | 
						|
  @retval 0 ~ Count-1 The index of the Key in the Array.
 | 
						|
**/
 | 
						|
INTN
 | 
						|
PlatformFindLoadOption (
 | 
						|
  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION  *Key,
 | 
						|
  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION  *Array,
 | 
						|
  IN UINTN                               Count
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN  Index;
 | 
						|
 | 
						|
  for (Index = 0; Index < Count; Index++) {
 | 
						|
    if ((Key->OptionType == Array[Index].OptionType) &&
 | 
						|
        (Key->Attributes == Array[Index].Attributes) &&
 | 
						|
        (StrCmp (Key->Description, Array[Index].Description) == 0) &&
 | 
						|
        (CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSize (Key->FilePath)) == 0) &&
 | 
						|
        (Key->OptionalDataSize == Array[Index].OptionalDataSize) &&
 | 
						|
        (CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->OptionalDataSize) == 0))
 | 
						|
    {
 | 
						|
      return (INTN)Index;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return -1;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get the FV device path for the shell file.
 | 
						|
 | 
						|
  @return   A pointer to device path structure.
 | 
						|
**/
 | 
						|
EFI_DEVICE_PATH_PROTOCOL *
 | 
						|
BdsGetShellFvDevicePath (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                          FvHandleCount;
 | 
						|
  EFI_HANDLE                     *FvHandleBuffer;
 | 
						|
  UINTN                          Index;
 | 
						|
  EFI_STATUS                     Status;
 | 
						|
  EFI_FIRMWARE_VOLUME2_PROTOCOL  *Fv;
 | 
						|
  UINTN                          Size;
 | 
						|
  UINT32                         AuthenticationStatus;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL       *DevicePath;
 | 
						|
  EFI_FV_FILETYPE                FoundType;
 | 
						|
  EFI_FV_FILE_ATTRIBUTES         FileAttributes;
 | 
						|
 | 
						|
  Status = EFI_SUCCESS;
 | 
						|
  gBS->LocateHandleBuffer (
 | 
						|
         ByProtocol,
 | 
						|
         &gEfiFirmwareVolume2ProtocolGuid,
 | 
						|
         NULL,
 | 
						|
         &FvHandleCount,
 | 
						|
         &FvHandleBuffer
 | 
						|
         );
 | 
						|
 | 
						|
  for (Index = 0; Index < FvHandleCount; Index++) {
 | 
						|
    Size = 0;
 | 
						|
    gBS->HandleProtocol (
 | 
						|
           FvHandleBuffer[Index],
 | 
						|
           &gEfiFirmwareVolume2ProtocolGuid,
 | 
						|
           (VOID **)&Fv
 | 
						|
           );
 | 
						|
    Status = Fv->ReadFile (
 | 
						|
                   Fv,
 | 
						|
                   &gUefiShellFileGuid,
 | 
						|
                   NULL,
 | 
						|
                   &Size,
 | 
						|
                   &FoundType,
 | 
						|
                   &FileAttributes,
 | 
						|
                   &AuthenticationStatus
 | 
						|
                   );
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      //
 | 
						|
      // Found the shell file
 | 
						|
      //
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    if (FvHandleCount) {
 | 
						|
      FreePool (FvHandleBuffer);
 | 
						|
    }
 | 
						|
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  DevicePath = DevicePathFromHandle (FvHandleBuffer[Index]);
 | 
						|
 | 
						|
  if (FvHandleCount) {
 | 
						|
    FreePool (FvHandleBuffer);
 | 
						|
  }
 | 
						|
 | 
						|
  return DevicePath;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Register a boot option using a file GUID in the FV.
 | 
						|
 | 
						|
  @param FileGuid     The file GUID name in FV.
 | 
						|
  @param Description  The boot option description.
 | 
						|
  @param Attributes   The attributes used for the boot option loading.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
PlatformRegisterFvBootOption (
 | 
						|
  EFI_GUID  *FileGuid,
 | 
						|
  CHAR16    *Description,
 | 
						|
  UINT32    Attributes
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                         Status;
 | 
						|
  UINTN                              OptionIndex;
 | 
						|
  EFI_BOOT_MANAGER_LOAD_OPTION       NewOption;
 | 
						|
  EFI_BOOT_MANAGER_LOAD_OPTION       *BootOptions;
 | 
						|
  UINTN                              BootOptionCount;
 | 
						|
  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  FileNode;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL           *DevicePath;
 | 
						|
 | 
						|
  EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);
 | 
						|
  DevicePath = AppendDevicePathNode (
 | 
						|
                 BdsGetShellFvDevicePath (),
 | 
						|
                 (EFI_DEVICE_PATH_PROTOCOL *)&FileNode
 | 
						|
                 );
 | 
						|
 | 
						|
  Status = EfiBootManagerInitializeLoadOption (
 | 
						|
             &NewOption,
 | 
						|
             LoadOptionNumberUnassigned,
 | 
						|
             LoadOptionTypeBoot,
 | 
						|
             Attributes,
 | 
						|
             Description,
 | 
						|
             DevicePath,
 | 
						|
             NULL,
 | 
						|
             0
 | 
						|
             );
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
 | 
						|
 | 
						|
    OptionIndex = PlatformFindLoadOption (&NewOption, BootOptions, BootOptionCount);
 | 
						|
 | 
						|
    if (OptionIndex == -1) {
 | 
						|
      Status = EfiBootManagerAddLoadOptionVariable (&NewOption, (UINTN)-1);
 | 
						|
      ASSERT_EFI_ERROR (Status);
 | 
						|
    }
 | 
						|
 | 
						|
    EfiBootManagerFreeLoadOption (&NewOption);
 | 
						|
    EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Do the platform specific action before the console is connected.
 | 
						|
 | 
						|
  Such as:
 | 
						|
    Update console variable;
 | 
						|
    Register new Driver#### or Boot####;
 | 
						|
    Signal ReadyToLock event.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
PlatformBootManagerBeforeConsole (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_INPUT_KEY                 Enter;
 | 
						|
  EFI_INPUT_KEY                 CustomKey;
 | 
						|
  EFI_INPUT_KEY                 Down;
 | 
						|
  EFI_BOOT_MANAGER_LOAD_OPTION  BootOption;
 | 
						|
 | 
						|
  //
 | 
						|
  // Register ENTER as CONTINUE key
 | 
						|
  //
 | 
						|
  Enter.ScanCode    = SCAN_NULL;
 | 
						|
  Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;
 | 
						|
  EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);
 | 
						|
 | 
						|
  if (FixedPcdGetBool (PcdBootManagerEscape)) {
 | 
						|
    //
 | 
						|
    // Map Esc to Boot Manager Menu
 | 
						|
    //
 | 
						|
    CustomKey.ScanCode    = SCAN_ESC;
 | 
						|
    CustomKey.UnicodeChar = CHAR_NULL;
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Map Esc to Boot Manager Menu
 | 
						|
    //
 | 
						|
    CustomKey.ScanCode    = SCAN_F2;
 | 
						|
    CustomKey.UnicodeChar = CHAR_NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  EfiBootManagerGetBootManagerMenu (&BootOption);
 | 
						|
  EfiBootManagerAddKeyOptionVariable (NULL, (UINT16)BootOption.OptionNumber, 0, &CustomKey, NULL);
 | 
						|
 | 
						|
  //
 | 
						|
  // Also add Down key to Boot Manager Menu since some serial terminals don't support F2 key.
 | 
						|
  //
 | 
						|
  Down.ScanCode    = SCAN_DOWN;
 | 
						|
  Down.UnicodeChar = CHAR_NULL;
 | 
						|
  EfiBootManagerGetBootManagerMenu (&BootOption);
 | 
						|
  EfiBootManagerAddKeyOptionVariable (NULL, (UINT16)BootOption.OptionNumber, 0, &Down, NULL);
 | 
						|
 | 
						|
  //
 | 
						|
  // Install ready to lock.
 | 
						|
  // This needs to be done before option rom dispatched.
 | 
						|
  //
 | 
						|
  InstallReadyToLock ();
 | 
						|
 | 
						|
  //
 | 
						|
  // Dispatch deferred images after EndOfDxe event and ReadyToLock installation.
 | 
						|
  //
 | 
						|
  EfiBootManagerDispatchDeferredImages ();
 | 
						|
 | 
						|
  PlatformConsoleInit ();
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Do the platform specific action after the console is connected.
 | 
						|
 | 
						|
  Such as:
 | 
						|
    Dynamically switch output mode;
 | 
						|
    Signal console ready platform customized event;
 | 
						|
    Run diagnostics like memory testing;
 | 
						|
    Connect certain devices;
 | 
						|
    Dispatch additional option roms.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
PlatformBootManagerAfterConsole (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_GRAPHICS_OUTPUT_BLT_PIXEL  Black;
 | 
						|
  EFI_GRAPHICS_OUTPUT_BLT_PIXEL  White;
 | 
						|
  EDKII_PLATFORM_LOGO_PROTOCOL   *PlatformLogo;
 | 
						|
  EFI_STATUS                     Status;
 | 
						|
 | 
						|
  Black.Blue = Black.Green = Black.Red = Black.Reserved = 0;
 | 
						|
  White.Blue = White.Green = White.Red = White.Reserved = 0xFF;
 | 
						|
 | 
						|
  Status = gBS->LocateProtocol (&gEdkiiPlatformLogoProtocolGuid, NULL, (VOID **)&PlatformLogo);
 | 
						|
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    gST->ConOut->ClearScreen (gST->ConOut);
 | 
						|
    BootLogoEnableLogo ();
 | 
						|
  }
 | 
						|
 | 
						|
  EfiBootManagerConnectAll ();
 | 
						|
  EfiBootManagerRefreshAllBootOption ();
 | 
						|
 | 
						|
  //
 | 
						|
  // Register UEFI Shell
 | 
						|
  //
 | 
						|
  PlatformRegisterFvBootOption (&gUefiShellFileGuid, L"UEFI Shell", LOAD_OPTION_ACTIVE);
 | 
						|
 | 
						|
  if (FixedPcdGetBool (PcdBootManagerEscape)) {
 | 
						|
    Print (
 | 
						|
      L"\n"
 | 
						|
      L"    Esc or Down      to enter Boot Manager Menu.\n"
 | 
						|
      L"    ENTER            to boot directly.\n"
 | 
						|
      L"\n"
 | 
						|
      );
 | 
						|
  } else {
 | 
						|
    Print (
 | 
						|
      L"\n"
 | 
						|
      L"    F2 or Down      to enter Boot Manager Menu.\n"
 | 
						|
      L"    ENTER           to boot directly.\n"
 | 
						|
      L"\n"
 | 
						|
      );
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function is called each second during the boot manager waits the timeout.
 | 
						|
 | 
						|
  @param TimeoutRemain  The remaining timeout.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
PlatformBootManagerWaitCallback (
 | 
						|
  UINT16  TimeoutRemain
 | 
						|
  )
 | 
						|
{
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
  )
 | 
						|
{
 | 
						|
  return;
 | 
						|
}
 |