mirror of https://github.com/acidanthera/audk.git
3094 lines
87 KiB
C
3094 lines
87 KiB
C
/** @file
|
|
|
|
Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
|
|
|
|
This program and the accompanying materials are licensed and made available under
|
|
the terms and conditions of the BSD License that accompanies this distribution.
|
|
The full text of the license may be found at
|
|
http://opensource.org/licenses/bsd-license.php.
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
|
|
|
|
|
|
Module Name:
|
|
|
|
BdsPlatform.c
|
|
|
|
Abstract:
|
|
|
|
This file include all platform action which can be customized
|
|
by IBV/OEM.
|
|
|
|
--*/
|
|
|
|
#include "BdsPlatform.h"
|
|
#include "SetupMode.h"
|
|
#include <Guid/SetupVariable.h>
|
|
#include <Library/TcgPhysicalPresenceLib.h>
|
|
#include <Library/TrEEPhysicalPresenceLib.h>
|
|
#include <Protocol/I2cMasterMcg.h>
|
|
#include <TianoApi.h>
|
|
#include <PlatformBaseAddresses.h>
|
|
#include <Protocol/GlobalNvsArea.h>
|
|
#include <Library/DxeServicesTableLib.h>
|
|
#include <Protocol/BlockIo.h>
|
|
#include <PchRegs/PchRegsPcu.h>
|
|
#include <Library/S3BootScriptLib.h>
|
|
#include "PchAccess.h"
|
|
#include "PchRegs/PchRegsSata.h"
|
|
#include <Library/SerialPortLib.h>
|
|
#include <Library/DebugLib.h>
|
|
|
|
#include <Library/GenericBdsLib/InternalBdsLib.h>
|
|
#include <Library/GenericBdsLib/String.h>
|
|
#include <Library/NetLib.h>
|
|
|
|
#include <Library/CapsuleLib.h>
|
|
#include <Protocol/EsrtManagement.h>
|
|
|
|
EFI_GUID *ConnectDriverTable[] = {
|
|
&gEfiMmioDeviceProtocolGuid,
|
|
&gEfiI2cMasterProtocolGuid,
|
|
&gEfiI2cHostProtocolGuid
|
|
};
|
|
|
|
#define SHELL_ENVIRONMENT_INTERFACE_PROTOCOL \
|
|
{ \
|
|
0x47c7b221, 0xc42a, 0x11d2, 0x8e, 0x57, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b \
|
|
}
|
|
VOID *mShellImageCallbackReg = NULL;
|
|
|
|
|
|
|
|
EFI_USER_PROFILE_HANDLE mCurrentUser = NULL;
|
|
EFI_EVENT mHotKeyTimerEvent = NULL;
|
|
EFI_EVENT mHitHotkeyEvent = NULL;
|
|
EFI_EVENT mUsbKeyboardConnectEvent = NULL;
|
|
BOOLEAN mHotKeyPressed = FALSE;
|
|
VOID *mHitHotkeyRegistration;
|
|
#define KEYBOARD_TIMER_INTERVAL 20000 // 0.02s
|
|
|
|
VOID
|
|
ConnectUSBController (
|
|
VOID
|
|
);
|
|
|
|
EFI_STATUS
|
|
PlatformBdsConnectSimpleConsole (
|
|
IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole
|
|
);
|
|
|
|
VOID
|
|
BootIntoFirmwareInterface(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
EFIAPI
|
|
PlatformBdsInitHotKeyEvent (
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
EFIAPI
|
|
DisableAhciCtlr (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
UINT32 PmcDisableAddress;
|
|
UINT8 SataStorageAmount;
|
|
UINT32 SataBase;
|
|
UINT16 SataPortStatus;
|
|
|
|
|
|
DEBUG ((EFI_D_INFO, "Disable AHCI event is signalled\n"));
|
|
SataStorageAmount = 0;
|
|
SataBase = *(UINT32*) Context;
|
|
|
|
//
|
|
// BayTrail-M EDS chapter 16 ---- PCI IO Register Offset 92 (SATA Port Control and Status)
|
|
//
|
|
SataPortStatus = MmioRead16 (SataBase + R_PCH_SATA_PCS);
|
|
|
|
//
|
|
// Bit 8 EN: Port 0 Present
|
|
//
|
|
if ((SataPortStatus & 0x100) == 0x100) {
|
|
SataStorageAmount++;
|
|
}
|
|
|
|
//
|
|
// Bit 9 EN: Port 1 Present
|
|
//
|
|
if ((SataPortStatus & 0x200) == 0x200) {
|
|
SataStorageAmount++;
|
|
}
|
|
|
|
//
|
|
// Disable SATA controller when it sets to AHCI mode without carrying any devices
|
|
// in order to prevent AHCI yellow bang under Win device manager.
|
|
//
|
|
if (SataStorageAmount == 0) {
|
|
PmcDisableAddress = (MmioRead32 ((PCH_PCI_EXPRESS_BASE_ADDRESS + (UINT32) (31 << 15)) + R_PCH_LPC_PMC_BASE) & B_PCH_LPC_PMC_BASE_BAR) + R_PCH_PMC_FUNC_DIS;
|
|
MmioOr32 (PmcDisableAddress, B_PCH_PMC_FUNC_DIS_SATA);
|
|
S3BootScriptSaveMemWrite (
|
|
EfiBootScriptWidthUint32,
|
|
(UINTN) PmcDisableAddress,
|
|
1,
|
|
(VOID *) (UINTN) PmcDisableAddress
|
|
);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
InstallReadyToLock (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_HANDLE Handle;
|
|
EFI_SMM_ACCESS2_PROTOCOL *SmmAccess;
|
|
EFI_ACPI_S3_SAVE_PROTOCOL *AcpiS3Save;
|
|
|
|
//
|
|
// Install DxeSmmReadyToLock protocol prior to the processing of boot options
|
|
//
|
|
Status = gBS->LocateProtocol (
|
|
&gEfiSmmAccess2ProtocolGuid,
|
|
NULL,
|
|
(VOID **) &SmmAccess
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
|
|
//
|
|
// Prepare S3 information, this MUST be done before DxeSmmReadyToLock
|
|
//
|
|
Status = gBS->LocateProtocol (
|
|
&gEfiAcpiS3SaveProtocolGuid,
|
|
NULL,
|
|
(VOID **)&AcpiS3Save
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
AcpiS3Save->S3Save (AcpiS3Save, NULL);
|
|
}
|
|
|
|
Handle = NULL;
|
|
Status = gBS->InstallProtocolInterface (
|
|
&Handle,
|
|
&gExitPmAuthProtocolGuid,
|
|
EFI_NATIVE_INTERFACE,
|
|
NULL
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
//
|
|
// Signal EndOfDxe PI Event
|
|
//
|
|
EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);
|
|
|
|
Handle = NULL;
|
|
Status = gBS->InstallProtocolInterface (
|
|
&Handle,
|
|
&gEfiDxeSmmReadyToLockProtocolGuid,
|
|
EFI_NATIVE_INTERFACE,
|
|
NULL
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
VOID
|
|
EFIAPI
|
|
ShellImageCallback (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
BdsSetConsoleMode (TRUE);
|
|
DEBUG ((EFI_D_INFO, "BdsEntry ShellImageCallback \n"));
|
|
}
|
|
|
|
//
|
|
// BDS Platform Functions
|
|
//
|
|
/**
|
|
Platform Bds init. Include the platform firmware vendor, revision
|
|
and so crc check.
|
|
|
|
@param VOID
|
|
|
|
@retval None.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
PlatformBdsInit (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_EVENT ShellImageEvent;
|
|
EFI_GUID ShellEnvProtocol = SHELL_ENVIRONMENT_INTERFACE_PROTOCOL;
|
|
|
|
#ifdef __GNUC__
|
|
SerialPortWrite((UINT8 *)">>>>BdsEntry[GCC]\r\n", 19);
|
|
#else
|
|
SerialPortWrite((UINT8 *)">>>>BdsEntry\r\n", 14);
|
|
#endif
|
|
BdsLibSaveMemoryTypeInformation ();
|
|
|
|
//
|
|
// Before user authentication, the user identification devices need be connected
|
|
// from the platform customized device paths
|
|
//
|
|
PlatformBdsConnectAuthDevice ();
|
|
|
|
//
|
|
// As console is not ready, the auto logon user will be identified.
|
|
//
|
|
BdsLibUserIdentify (&mCurrentUser);
|
|
|
|
//
|
|
// Change Gop mode when boot into Shell
|
|
//
|
|
if (mShellImageCallbackReg == NULL) {
|
|
Status = gBS->CreateEvent (
|
|
EFI_EVENT_NOTIFY_SIGNAL,
|
|
EFI_TPL_CALLBACK,
|
|
ShellImageCallback,
|
|
NULL,
|
|
&ShellImageEvent
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
Status = gBS->RegisterProtocolNotify (
|
|
&ShellEnvProtocol,
|
|
ShellImageEvent,
|
|
&mShellImageCallbackReg
|
|
);
|
|
|
|
DEBUG ((EFI_D_INFO, "BdsEntry ShellImageCallback \n"));
|
|
}
|
|
}
|
|
}
|
|
|
|
EFI_STATUS
|
|
GetGopDevicePath (
|
|
IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,
|
|
OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath
|
|
)
|
|
{
|
|
UINTN Index;
|
|
EFI_STATUS Status;
|
|
EFI_HANDLE PciDeviceHandle;
|
|
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
|
|
EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath;
|
|
UINTN GopHandleCount;
|
|
EFI_HANDLE *GopHandleBuffer;
|
|
|
|
UINTN VarSize;
|
|
SYSTEM_CONFIGURATION mSystemConfiguration;
|
|
|
|
if (PciDevicePath == NULL || GopDevicePath == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Initialize the GopDevicePath to be PciDevicePath
|
|
//
|
|
*GopDevicePath = PciDevicePath;
|
|
TempPciDevicePath = PciDevicePath;
|
|
|
|
Status = gBS->LocateDevicePath (
|
|
&gEfiDevicePathProtocolGuid,
|
|
&TempPciDevicePath,
|
|
&PciDeviceHandle
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Try to connect this handle, so that GOP driver could start on this
|
|
// device and create child handles with GraphicsOutput Protocol installed
|
|
// on them, then we get device paths of these child handles and select
|
|
// them as possible console device.
|
|
//
|
|
|
|
//
|
|
// Select display devices
|
|
//
|
|
VarSize = sizeof(SYSTEM_CONFIGURATION);
|
|
Status = gRT->GetVariable(
|
|
L"Setup",
|
|
&gEfiNormalSetupGuid,
|
|
NULL,
|
|
&VarSize,
|
|
&mSystemConfiguration
|
|
);
|
|
if (EFI_ERROR (Status) || VarSize != sizeof(SYSTEM_CONFIGURATION)) {
|
|
//The setup variable is corrupted
|
|
VarSize = sizeof(SYSTEM_CONFIGURATION);
|
|
Status = gRT->GetVariable(
|
|
L"SetupRecovery",
|
|
&gEfiNormalSetupGuid,
|
|
NULL,
|
|
&VarSize,
|
|
&mSystemConfiguration
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
if(mSystemConfiguration.BootDisplayDevice != 0x0)
|
|
{
|
|
ACPI_ADR_DEVICE_PATH AcpiAdr;
|
|
EFI_DEVICE_PATH_PROTOCOL *MyDevicePath = NULL;
|
|
|
|
AcpiAdr.Header.Type = ACPI_DEVICE_PATH;
|
|
AcpiAdr.Header.SubType = ACPI_ADR_DP;
|
|
|
|
switch (mSystemConfiguration.BootDisplayDevice) {
|
|
case 1:
|
|
AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, PORT_CRT, 0); //CRT Device
|
|
break;
|
|
case 2:
|
|
AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL, PORT_B_HDMI, 0); //HDMI Device Port B
|
|
break;
|
|
case 3:
|
|
AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL, PORT_B_DP, 0); //DP PortB
|
|
break;
|
|
case 4:
|
|
AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL, PORT_C_DP, 0); //DP PortC
|
|
break;
|
|
case 5:
|
|
AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_INTERNAL_DIGITAL, PORT_C_DP, 0); //eDP Port C
|
|
break;
|
|
case 6:
|
|
AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_INTERNAL_DIGITAL, PORT_MIPI_A, 0); //DSI Port A
|
|
break;
|
|
case 7:
|
|
AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_INTERNAL_DIGITAL, PORT_MIPI_C, 0); //DSI Port C
|
|
break;
|
|
default:
|
|
AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, PORT_CRT, 0);
|
|
break;
|
|
}
|
|
|
|
SetDevicePathNodeLength (&AcpiAdr.Header, sizeof (ACPI_ADR_DEVICE_PATH));
|
|
|
|
MyDevicePath = AppendDevicePathNode(MyDevicePath, (EFI_DEVICE_PATH_PROTOCOL*)&AcpiAdr);
|
|
|
|
gBS->ConnectController (
|
|
PciDeviceHandle,
|
|
NULL,
|
|
MyDevicePath,
|
|
FALSE
|
|
);
|
|
|
|
FreePool(MyDevicePath);
|
|
}
|
|
else
|
|
{
|
|
gBS->ConnectController (
|
|
PciDeviceHandle,
|
|
NULL,
|
|
NULL,
|
|
FALSE
|
|
);
|
|
}
|
|
|
|
Status = gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
&gEfiGraphicsOutputProtocolGuid,
|
|
NULL,
|
|
&GopHandleCount,
|
|
&GopHandleBuffer
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
//
|
|
// Add all the child handles as possible Console Device
|
|
//
|
|
for (Index = 0; Index < GopHandleCount; Index++) {
|
|
Status = gBS->HandleProtocol (
|
|
GopHandleBuffer[Index],
|
|
&gEfiDevicePathProtocolGuid,
|
|
(VOID**)&TempDevicePath
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
if (CompareMem (
|
|
PciDevicePath,
|
|
TempDevicePath,
|
|
GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH
|
|
) == 0) {
|
|
//
|
|
// In current implementation, we only enable one of the child handles
|
|
// as console device, i.e. sotre one of the child handle's device
|
|
// path to variable "ConOut"
|
|
// In future, we could select all child handles to be console device
|
|
//
|
|
*GopDevicePath = TempDevicePath;
|
|
}
|
|
}
|
|
gBS->FreePool (GopHandleBuffer);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
|
|
Search out all the platform pci or agp video device. The function may will
|
|
find multiple video device, and return all enabled device path.
|
|
|
|
@param PlugInPciVgaDevicePath Return the platform plug in pci video device
|
|
path if the system have plug in pci video device.
|
|
@param OnboardPciVgaDevicePath Return the platform active agp video device path
|
|
if the system have plug in agp video device or on
|
|
chip agp device.
|
|
|
|
@retval EFI_SUCCSS Get all platform active video device path.
|
|
@retval EFI_STATUS Return the status of gBS->LocateDevicePath (),
|
|
gBS->ConnectController (),
|
|
and gBS->LocateHandleBuffer ().
|
|
|
|
**/
|
|
EFI_STATUS
|
|
GetPlugInPciVgaDevicePath (
|
|
IN OUT EFI_DEVICE_PATH_PROTOCOL **PlugInPciVgaDevicePath,
|
|
IN OUT EFI_DEVICE_PATH_PROTOCOL **OnboardPciVgaDevicePath
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_HANDLE RootHandle;
|
|
UINTN HandleCount;
|
|
EFI_HANDLE *HandleBuffer;
|
|
UINTN Index;
|
|
UINTN Index1;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
BOOLEAN PlugInPciVga;
|
|
EFI_PCI_IO_PROTOCOL *PciIo;
|
|
PCI_TYPE00 Pci;
|
|
|
|
DevicePath = NULL;
|
|
PlugInPciVga = TRUE;
|
|
HandleCount = 0;
|
|
HandleBuffer = NULL;
|
|
|
|
//
|
|
// Make all the PCI_IO protocols on PCI Seg 0 show up
|
|
//
|
|
BdsLibConnectDevicePath (gPlatformRootBridges[0]);
|
|
|
|
Status = gBS->LocateDevicePath (
|
|
&gEfiDevicePathProtocolGuid,
|
|
&gPlatformRootBridges[0],
|
|
&RootHandle
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = gBS->ConnectController (
|
|
RootHandle,
|
|
NULL,
|
|
NULL,
|
|
FALSE
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Start to check all the pci io to find all possible VGA device
|
|
//
|
|
HandleCount = 0;
|
|
HandleBuffer = NULL;
|
|
Status = gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
&gEfiPciIoProtocolGuid,
|
|
NULL,
|
|
&HandleCount,
|
|
&HandleBuffer
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
for (Index = 0; Index < HandleCount; Index++) {
|
|
Status = gBS->HandleProtocol (
|
|
HandleBuffer[Index],
|
|
&gEfiPciIoProtocolGuid,
|
|
(VOID**)&PciIo
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
|
|
//
|
|
// Check for all VGA device
|
|
//
|
|
Status = PciIo->Pci.Read (
|
|
PciIo,
|
|
EfiPciIoWidthUint32,
|
|
0,
|
|
sizeof (Pci) / sizeof (UINT32),
|
|
&Pci
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Here we decide which VGA device to enable in PCI bus
|
|
//
|
|
// The first plugin PCI VGA card device will be present as PCI VGA
|
|
// The onchip AGP or AGP card will be present as AGP VGA
|
|
//
|
|
if (!IS_PCI_VGA (&Pci)) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Set the device as the possible console out device,
|
|
//
|
|
// Below code will make every VGA device to be one
|
|
// of the possibe console out device
|
|
//
|
|
PlugInPciVga = TRUE;
|
|
gBS->HandleProtocol (
|
|
HandleBuffer[Index],
|
|
&gEfiDevicePathProtocolGuid,
|
|
(VOID**)&DevicePath
|
|
);
|
|
|
|
Index1 = 0;
|
|
|
|
while (gPlatformAllPossiblePciVgaConsole[Index1] != NULL) {
|
|
if (CompareMem (
|
|
DevicePath,
|
|
gPlatformAllPossiblePciVgaConsole[Index1],
|
|
GetDevicePathSize (gPlatformAllPossiblePciVgaConsole[Index1])
|
|
) == 0) {
|
|
|
|
//
|
|
// This device is an AGP device
|
|
//
|
|
*OnboardPciVgaDevicePath = DevicePath;
|
|
PlugInPciVga = FALSE;
|
|
break;
|
|
}
|
|
|
|
Index1 ++;
|
|
}
|
|
|
|
if (PlugInPciVga) {
|
|
*PlugInPciVgaDevicePath = DevicePath;
|
|
}
|
|
}
|
|
}
|
|
|
|
FreePool (HandleBuffer);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
|
|
Find the platform active vga, and base on the policy to enable the vga as
|
|
the console out device. The policy is driven by one setup variable "VBIOS".
|
|
|
|
None.
|
|
|
|
@param EFI_UNSUPPORTED There is no active vga device
|
|
|
|
@retval EFI_STATUS Return the status of BdsLibGetVariableAndSize ()
|
|
|
|
**/
|
|
EFI_STATUS
|
|
PlatformBdsForceActiveVga (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_DEVICE_PATH_PROTOCOL *PlugInPciVgaDevicePath;
|
|
EFI_DEVICE_PATH_PROTOCOL *OnboardPciVgaDevicePath;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevicePathFirst;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevicePathSecond;
|
|
EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;
|
|
UINTN VarSize;
|
|
SYSTEM_CONFIGURATION mSystemConfiguration;
|
|
|
|
Status = EFI_SUCCESS;
|
|
PlugInPciVgaDevicePath = NULL;
|
|
OnboardPciVgaDevicePath = NULL;
|
|
|
|
//
|
|
// Check the policy which is the first enabled VGA
|
|
//
|
|
GetPlugInPciVgaDevicePath (&PlugInPciVgaDevicePath, &OnboardPciVgaDevicePath);
|
|
|
|
if (PlugInPciVgaDevicePath == NULL && OnboardPciVgaDevicePath == NULL) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
VarSize = sizeof(SYSTEM_CONFIGURATION);
|
|
Status = gRT->GetVariable(
|
|
L"Setup",
|
|
&gEfiNormalSetupGuid,
|
|
NULL,
|
|
&VarSize,
|
|
&mSystemConfiguration
|
|
);
|
|
if (EFI_ERROR (Status) || VarSize != sizeof(SYSTEM_CONFIGURATION)) {
|
|
//The setup variable is corrupted
|
|
VarSize = sizeof(SYSTEM_CONFIGURATION);
|
|
Status = gRT->GetVariable(
|
|
L"SetupRecovery",
|
|
&gEfiNormalSetupGuid,
|
|
NULL,
|
|
&VarSize,
|
|
&mSystemConfiguration
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
|
|
if ((PlugInPciVgaDevicePath == NULL && OnboardPciVgaDevicePath != NULL) ) {
|
|
DEBUG ((EFI_D_ERROR,"Update onboard PCI VGA ...\n"));
|
|
DevicePathFirst = OnboardPciVgaDevicePath;
|
|
DevicePathSecond = PlugInPciVgaDevicePath;
|
|
goto UpdateConOut;
|
|
}
|
|
if(OnboardPciVgaDevicePath != NULL && mSystemConfiguration.PrimaryVideoAdaptor == 0) {
|
|
DEBUG ((EFI_D_ERROR,"Update onboard PCI VGA When set primary!!!...\n"));
|
|
DevicePathFirst = OnboardPciVgaDevicePath;
|
|
DevicePathSecond = PlugInPciVgaDevicePath;
|
|
goto UpdateConOut;
|
|
}
|
|
|
|
DEBUG ((EFI_D_ERROR,"Update plug in PCI VGA ...\n"));
|
|
DevicePathFirst = PlugInPciVgaDevicePath;
|
|
DevicePathSecond = OnboardPciVgaDevicePath;
|
|
|
|
UpdateConOut:
|
|
GetGopDevicePath (DevicePathFirst, &GopDevicePath);
|
|
DevicePathFirst = GopDevicePath;
|
|
|
|
Status = BdsLibUpdateConsoleVariable (
|
|
L"ConOut",
|
|
DevicePathFirst,
|
|
DevicePathSecond
|
|
);
|
|
|
|
return Status;
|
|
}
|
|
|
|
VOID
|
|
UpdateConsoleResolution(
|
|
VOID
|
|
)
|
|
{
|
|
UINT32 HorizontalResolution;
|
|
UINT32 VerticalResolution;
|
|
SYSTEM_CONFIGURATION SystemConfiguration;
|
|
UINTN VarSize;
|
|
EFI_STATUS Status;
|
|
|
|
|
|
HorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution);
|
|
VerticalResolution = PcdGet32 (PcdSetupVideoVerticalResolution);
|
|
|
|
VarSize = sizeof(SYSTEM_CONFIGURATION);
|
|
Status = gRT->GetVariable(
|
|
L"Setup",
|
|
&gEfiNormalSetupGuid,
|
|
NULL,
|
|
&VarSize,
|
|
&SystemConfiguration
|
|
);
|
|
if (EFI_ERROR (Status) || VarSize != sizeof(SYSTEM_CONFIGURATION)) {
|
|
//The setup variable is corrupted
|
|
VarSize = sizeof(SYSTEM_CONFIGURATION);
|
|
Status = gRT->GetVariable(
|
|
L"SetupRecovery",
|
|
&gEfiNormalSetupGuid,
|
|
NULL,
|
|
&VarSize,
|
|
&SystemConfiguration
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
switch (SystemConfiguration.IgdFlatPanel) {
|
|
|
|
case 0:
|
|
//
|
|
// Use the detault PCD values.
|
|
//
|
|
break;
|
|
|
|
case 1:
|
|
HorizontalResolution = 640;
|
|
VerticalResolution = 480;
|
|
break;
|
|
|
|
case 2:
|
|
HorizontalResolution = 800;
|
|
VerticalResolution = 600;
|
|
break;
|
|
|
|
case 3:
|
|
HorizontalResolution = 1024;
|
|
VerticalResolution = 768;
|
|
break;
|
|
|
|
case 4:
|
|
HorizontalResolution = 1280;
|
|
VerticalResolution = 1024;
|
|
break;
|
|
|
|
case 5:
|
|
HorizontalResolution = 1366;
|
|
VerticalResolution = 768;
|
|
break;
|
|
|
|
case 6:
|
|
HorizontalResolution = 1680;
|
|
VerticalResolution = 1050;
|
|
break;
|
|
|
|
case 7:
|
|
HorizontalResolution = 1920;
|
|
VerticalResolution = 1200;
|
|
break;
|
|
|
|
case 8:
|
|
HorizontalResolution = 1280;
|
|
VerticalResolution = 800;
|
|
break;
|
|
}
|
|
|
|
PcdSet32 (PcdSetupVideoHorizontalResolution, HorizontalResolution);
|
|
PcdSet32 (PcdSetupVideoVerticalResolution, VerticalResolution);
|
|
DEBUG ((EFI_D_ERROR, "HorizontalResolution = %x; VerticalResolution = %x", HorizontalResolution, VerticalResolution));
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
Connect the predefined platform default console device. Always try to find
|
|
and enable the vga device if have.
|
|
|
|
@param PlatformConsole Predefined platform default console device array.
|
|
|
|
@retval EFI_SUCCESS Success connect at least one ConIn and ConOut
|
|
device, there must have one ConOut device is
|
|
active vga device.
|
|
|
|
@retval EFI_STATUS Return the status of
|
|
BdsLibConnectAllDefaultConsoles ()
|
|
|
|
**/
|
|
EFI_STATUS
|
|
PlatformBdsConnectConsole (
|
|
IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN Index;
|
|
EFI_DEVICE_PATH_PROTOCOL *VarConout;
|
|
EFI_DEVICE_PATH_PROTOCOL *VarConin;
|
|
UINTN DevicePathSize;
|
|
|
|
UpdateConsoleResolution();
|
|
|
|
Index = 0;
|
|
Status = EFI_SUCCESS;
|
|
DevicePathSize = 0;
|
|
VarConout = BdsLibGetVariableAndSize (
|
|
L"ConOut",
|
|
&gEfiGlobalVariableGuid,
|
|
&DevicePathSize
|
|
);
|
|
VarConin = BdsLibGetVariableAndSize (
|
|
L"ConIn",
|
|
&gEfiGlobalVariableGuid,
|
|
&DevicePathSize
|
|
);
|
|
if (VarConout == NULL || VarConin == NULL) {
|
|
//
|
|
// Have chance to connect the platform default console,
|
|
// the platform default console is the minimum device group
|
|
// the platform should support
|
|
//
|
|
while (PlatformConsole[Index].DevicePath != NULL) {
|
|
|
|
//
|
|
// Update the console variable with the connect type
|
|
//
|
|
if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
|
|
BdsLibUpdateConsoleVariable (L"ConIn", PlatformConsole[Index].DevicePath, NULL);
|
|
}
|
|
|
|
if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
|
|
BdsLibUpdateConsoleVariable (L"ConOut", PlatformConsole[Index].DevicePath, NULL);
|
|
}
|
|
|
|
if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
|
|
BdsLibUpdateConsoleVariable (L"ErrOut", PlatformConsole[Index].DevicePath, NULL);
|
|
}
|
|
|
|
Index ++;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Make sure we have at least one active VGA, and have the right
|
|
// active VGA in console variable
|
|
//
|
|
Status = PlatformBdsForceActiveVga ();
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
DEBUG ((EFI_D_INFO, "DISPLAY INIT DONE\n"));
|
|
|
|
//
|
|
// Connect the all the default console with current console variable
|
|
//
|
|
Status = BdsLibConnectAllDefaultConsoles ();
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Connect with predefined platform connect sequence,
|
|
the OEM/IBV can customize with their own connect sequence.
|
|
|
|
@param None.
|
|
|
|
@retval None.
|
|
|
|
**/
|
|
VOID
|
|
PlatformBdsConnectSequence (
|
|
VOID
|
|
)
|
|
{
|
|
UINTN Index;
|
|
|
|
Index = 0;
|
|
|
|
//
|
|
// Here we can get the customized platform connect sequence
|
|
// Notes: we can connect with new variable which record the
|
|
// last time boots connect device path sequence
|
|
//
|
|
while (gPlatformConnectSequence[Index] != NULL) {
|
|
|
|
//
|
|
// Build the platform boot option
|
|
//
|
|
BdsLibConnectDevicePath (gPlatformConnectSequence[Index]);
|
|
Index ++;
|
|
}
|
|
|
|
//
|
|
// Just use the simple policy to connect all devices
|
|
// There should be no difference between debug tip and release tip, or it will be extremely hard to debug.
|
|
//
|
|
// There is case that IdeController driver will write boot script in driver model Start() function. It will be rejected by boot script save.
|
|
// It is only found when DEBUG disabled, because we are using BdsLibConnectAll() when DEBUG enabled.
|
|
//
|
|
// So we use BdsLibConnectAll() here to make sure IdeController.Start() is invoked before InstallReadyToLock().
|
|
// We may also consider to connect SataController only later if needed.
|
|
//
|
|
BdsLibConnectAll ();
|
|
}
|
|
|
|
/**
|
|
|
|
Load the predefined driver option, OEM/IBV can customize this
|
|
to load their own drivers
|
|
|
|
@param BdsDriverLists The header of the driver option link list.
|
|
|
|
@retval None.
|
|
|
|
**/
|
|
VOID
|
|
PlatformBdsGetDriverOption (
|
|
IN OUT LIST_ENTRY *BdsDriverLists
|
|
)
|
|
{
|
|
UINTN Index;
|
|
|
|
Index = 0;
|
|
|
|
//
|
|
// Here we can get the customized platform driver option
|
|
//
|
|
while (gPlatformDriverOption[Index] != NULL) {
|
|
|
|
//
|
|
// Build the platform boot option
|
|
//
|
|
BdsLibRegisterNewOption (BdsDriverLists, gPlatformDriverOption[Index], NULL, L"DriverOrder");
|
|
Index ++;
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
This function is used for some critical time if the the system
|
|
have no any boot option, and there is no time out for user to add
|
|
the new boot option. This can also treat as the platform default
|
|
boot option.
|
|
|
|
@param BdsBootOptionList The header of the boot option link list.
|
|
|
|
@retval None.
|
|
|
|
**/
|
|
VOID
|
|
PlatformBdsPredictBootOption (
|
|
IN OUT LIST_ENTRY *BdsBootOptionList
|
|
)
|
|
{
|
|
UINTN Index;
|
|
|
|
Index = 0;
|
|
|
|
//
|
|
// Here give chance to get platform boot option data
|
|
//
|
|
while (gPlatformBootOption[Index] != NULL) {
|
|
|
|
//
|
|
// Build the platform boot option
|
|
//
|
|
BdsLibRegisterNewOption (BdsBootOptionList, gPlatformBootOption[Index], NULL, L"BootOrder");
|
|
Index ++;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Perform the platform diagnostic, such like test memory. OEM/IBV also
|
|
can customize this fuction to support specific platform diagnostic.
|
|
|
|
@param MemoryTestLevel The memory test intensive level
|
|
@param QuietBoot Indicate if need to enable the quiet boot
|
|
@param BaseMemoryTest A pointer to BdsMemoryTest()
|
|
|
|
@retval None.
|
|
|
|
**/
|
|
VOID
|
|
PlatformBdsDiagnostics (
|
|
IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel,
|
|
IN BOOLEAN QuietBoot,
|
|
IN BASEM_MEMORY_TEST BaseMemoryTest
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
//
|
|
// Here we can decide if we need to show
|
|
// the diagnostics screen
|
|
// Notes: this quiet boot code should be remove
|
|
// from the graphic lib
|
|
//
|
|
if (QuietBoot) {
|
|
EnableQuietBoot (PcdGetPtr(PcdLogoFile));
|
|
|
|
//
|
|
// Perform system diagnostic
|
|
//
|
|
Status = BaseMemoryTest (MemoryTestLevel);
|
|
if (EFI_ERROR (Status)) {
|
|
DisableQuietBoot ();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Perform system diagnostic
|
|
//
|
|
Status = BaseMemoryTest (MemoryTestLevel);
|
|
}
|
|
|
|
|
|
/**
|
|
For EFI boot option, BDS separate them as six types:
|
|
1. Network - The boot option points to the SimpleNetworkProtocol device.
|
|
Bds will try to automatically create this type boot option when enumerate.
|
|
2. Shell - The boot option points to internal flash shell.
|
|
Bds will try to automatically create this type boot option when enumerate.
|
|
3. Removable BlockIo - The boot option only points to the removable media
|
|
device, like USB flash disk, DVD, Floppy etc.
|
|
These device should contain a *removable* blockIo
|
|
protocol in their device handle.
|
|
Bds will try to automatically create this type boot option
|
|
when enumerate.
|
|
4. Fixed BlockIo - The boot option only points to a Fixed blockIo device,
|
|
like HardDisk.
|
|
These device should contain a *fixed* blockIo
|
|
protocol in their device handle.
|
|
BDS will skip fixed blockIo devices, and NOT
|
|
automatically create boot option for them. But BDS
|
|
will help to delete those fixed blockIo boot option,
|
|
whose description rule conflict with other auto-created
|
|
boot options.
|
|
5. Non-BlockIo Simplefile - The boot option points to a device whose handle
|
|
has SimpleFileSystem Protocol, but has no blockio
|
|
protocol. These devices do not offer blockIo
|
|
protocol, but BDS still can get the
|
|
\EFI\BOOT\boot{machinename}.EFI by SimpleFileSystem
|
|
Protocol.
|
|
6. File - The boot option points to a file. These boot options are usually
|
|
created by user manually or OS loader. BDS will not delete or modify
|
|
these boot options.
|
|
|
|
This function will enumerate all possible boot device in the system, and
|
|
automatically create boot options for Network, Shell, Removable BlockIo,
|
|
and Non-BlockIo Simplefile devices.
|
|
It will only execute once of every boot.
|
|
|
|
@param BdsBootOptionList The header of the link list which indexed all
|
|
current boot options
|
|
|
|
@retval EFI_SUCCESS Finished all the boot device enumerate and create
|
|
the boot option base on that boot device
|
|
|
|
@retval EFI_OUT_OF_RESOURCES Failed to enumerate the boot device and create the boot option list
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PlatformBdsLibEnumerateAllBootOption (
|
|
IN OUT LIST_ENTRY *BdsBootOptionList
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT16 FloppyNumber;
|
|
UINT16 HarddriveNumber;
|
|
UINT16 CdromNumber;
|
|
UINT16 UsbNumber;
|
|
UINT16 MiscNumber;
|
|
UINT16 ScsiNumber;
|
|
UINT16 NonBlockNumber;
|
|
UINTN NumberBlockIoHandles;
|
|
EFI_HANDLE *BlockIoHandles;
|
|
EFI_BLOCK_IO_PROTOCOL *BlkIo;
|
|
BOOLEAN Removable[2];
|
|
UINTN RemovableIndex;
|
|
UINTN Index;
|
|
UINTN NumOfLoadFileHandles;
|
|
EFI_HANDLE *LoadFileHandles;
|
|
UINTN FvHandleCount;
|
|
EFI_HANDLE *FvHandleBuffer;
|
|
EFI_FV_FILETYPE Type;
|
|
UINTN Size;
|
|
EFI_FV_FILE_ATTRIBUTES Attributes;
|
|
UINT32 AuthenticationStatus;
|
|
EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
UINTN DevicePathType;
|
|
CHAR16 Buffer[40];
|
|
EFI_HANDLE *FileSystemHandles;
|
|
UINTN NumberFileSystemHandles;
|
|
BOOLEAN NeedDelete;
|
|
EFI_IMAGE_DOS_HEADER DosHeader;
|
|
CHAR8 *PlatLang;
|
|
CHAR8 *LastLang;
|
|
EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData;
|
|
EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
|
|
CHAR16 *MacStr;
|
|
CHAR16 *IPverStr;
|
|
EFI_HANDLE *NetworkHandles;
|
|
UINTN BufferSize;
|
|
|
|
FloppyNumber = 0;
|
|
HarddriveNumber = 0;
|
|
CdromNumber = 0;
|
|
UsbNumber = 0;
|
|
MiscNumber = 0;
|
|
ScsiNumber = 0;
|
|
PlatLang = NULL;
|
|
LastLang = NULL;
|
|
ZeroMem (Buffer, sizeof (Buffer));
|
|
|
|
//
|
|
// If the boot device enumerate happened, just get the boot
|
|
// device from the boot order variable
|
|
//
|
|
if (mEnumBootDevice) {
|
|
GetVariable2 (LAST_ENUM_LANGUAGE_VARIABLE_NAME, &gLastEnumLangGuid, (VOID**)&LastLang, NULL);
|
|
GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&PlatLang, NULL);
|
|
ASSERT (PlatLang != NULL);
|
|
if ((LastLang != NULL) && (AsciiStrCmp (LastLang, PlatLang) == 0)) {
|
|
Status = BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");
|
|
FreePool (LastLang);
|
|
FreePool (PlatLang);
|
|
return Status;
|
|
} else {
|
|
Status = gRT->SetVariable (
|
|
LAST_ENUM_LANGUAGE_VARIABLE_NAME,
|
|
&gLastEnumLangGuid,
|
|
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
|
|
AsciiStrSize (PlatLang),
|
|
PlatLang
|
|
);
|
|
//
|
|
// Failure to set the variable only impacts the performance next time enumerating the boot options.
|
|
//
|
|
|
|
if (LastLang != NULL) {
|
|
FreePool (LastLang);
|
|
}
|
|
FreePool (PlatLang);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Notes: this dirty code is to get the legacy boot option from the
|
|
// BBS table and create to variable as the EFI boot option, it should
|
|
// be removed after the CSM can provide legacy boot option directly
|
|
//
|
|
REFRESH_LEGACY_BOOT_OPTIONS;
|
|
|
|
//
|
|
// Delete invalid boot option
|
|
//
|
|
BdsDeleteAllInvalidEfiBootOption ();
|
|
|
|
//
|
|
// Parse removable media followed by fixed media.
|
|
// The Removable[] array is used by the for-loop below to create removable media boot options
|
|
// at first, and then to create fixed media boot options.
|
|
//
|
|
Removable[0] = FALSE;
|
|
Removable[1] = TRUE;
|
|
|
|
gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
&gEfiBlockIoProtocolGuid,
|
|
NULL,
|
|
&NumberBlockIoHandles,
|
|
&BlockIoHandles
|
|
);
|
|
|
|
for (RemovableIndex = 0; RemovableIndex < 2; RemovableIndex++) {
|
|
for (Index = 0; Index < NumberBlockIoHandles; Index++) {
|
|
Status = gBS->HandleProtocol (
|
|
BlockIoHandles[Index],
|
|
&gEfiBlockIoProtocolGuid,
|
|
(VOID **) &BlkIo
|
|
);
|
|
//
|
|
// skip the logical partition
|
|
//
|
|
if (EFI_ERROR (Status) || BlkIo->Media->LogicalPartition) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// firstly fixed block io then the removable block io
|
|
//
|
|
if (BlkIo->Media->RemovableMedia == Removable[RemovableIndex]) {
|
|
continue;
|
|
}
|
|
DevicePath = DevicePathFromHandle (BlockIoHandles[Index]);
|
|
DevicePathType = BdsGetBootTypeFromDevicePath (DevicePath);
|
|
|
|
switch (DevicePathType) {
|
|
case BDS_EFI_ACPI_FLOPPY_BOOT:
|
|
if (FloppyNumber != 0) {
|
|
UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_FLOPPY)), FloppyNumber);
|
|
} else {
|
|
UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_FLOPPY)));
|
|
}
|
|
BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);
|
|
FloppyNumber++;
|
|
break;
|
|
|
|
//
|
|
// Assume a removable SATA device should be the DVD/CD device, a fixed SATA device should be the Hard Drive device.
|
|
//
|
|
case BDS_EFI_MESSAGE_ATAPI_BOOT:
|
|
case BDS_EFI_MESSAGE_SATA_BOOT:
|
|
if (BlkIo->Media->RemovableMedia) {
|
|
if (CdromNumber != 0) {
|
|
UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_CD_DVD)), CdromNumber);
|
|
} else {
|
|
UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_CD_DVD)));
|
|
}
|
|
CdromNumber++;
|
|
} else {
|
|
if (HarddriveNumber != 0) {
|
|
UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_HARDDRIVE)), HarddriveNumber);
|
|
} else {
|
|
UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_HARDDRIVE)));
|
|
}
|
|
HarddriveNumber++;
|
|
}
|
|
DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Buffer: %S\n", Buffer));
|
|
BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);
|
|
break;
|
|
|
|
case BDS_EFI_MESSAGE_USB_DEVICE_BOOT:
|
|
if (UsbNumber != 0) {
|
|
UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_USB)), UsbNumber);
|
|
} else {
|
|
UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_USB)));
|
|
}
|
|
BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);
|
|
UsbNumber++;
|
|
break;
|
|
|
|
case BDS_EFI_MESSAGE_SCSI_BOOT:
|
|
if (ScsiNumber != 0) {
|
|
UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_SCSI)), ScsiNumber);
|
|
} else {
|
|
UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_SCSI)));
|
|
}
|
|
BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);
|
|
ScsiNumber++;
|
|
break;
|
|
|
|
case BDS_EFI_MESSAGE_MISC_BOOT:
|
|
default:
|
|
if (MiscNumber != 0) {
|
|
UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_MISC)), MiscNumber);
|
|
} else {
|
|
UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_MISC)));
|
|
}
|
|
BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);
|
|
MiscNumber++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (NumberBlockIoHandles != 0) {
|
|
FreePool (BlockIoHandles);
|
|
}
|
|
|
|
//
|
|
// If there is simple file protocol which does not consume block Io protocol, create a boot option for it here.
|
|
//
|
|
NonBlockNumber = 0;
|
|
gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
&gEfiSimpleFileSystemProtocolGuid,
|
|
NULL,
|
|
&NumberFileSystemHandles,
|
|
&FileSystemHandles
|
|
);
|
|
for (Index = 0; Index < NumberFileSystemHandles; Index++) {
|
|
Status = gBS->HandleProtocol (
|
|
FileSystemHandles[Index],
|
|
&gEfiBlockIoProtocolGuid,
|
|
(VOID **) &BlkIo
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
//
|
|
// Skip if the file system handle supports a BlkIo protocol,
|
|
//
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Do the removable Media thing. \EFI\BOOT\boot{machinename}.EFI
|
|
// machinename is ia32, ia64, x64, ...
|
|
//
|
|
Hdr.Union = &HdrData;
|
|
NeedDelete = TRUE;
|
|
Status = BdsLibGetImageHeader (
|
|
FileSystemHandles[Index],
|
|
EFI_REMOVABLE_MEDIA_FILE_NAME,
|
|
&DosHeader,
|
|
Hdr
|
|
);
|
|
if (!EFI_ERROR (Status) &&
|
|
EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Hdr.Pe32->FileHeader.Machine) &&
|
|
Hdr.Pe32->OptionalHeader.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {
|
|
NeedDelete = FALSE;
|
|
}
|
|
|
|
if (NeedDelete) {
|
|
//
|
|
// No such file or the file is not a EFI application, delete this boot option
|
|
//
|
|
BdsLibDeleteOptionFromHandle (FileSystemHandles[Index]);
|
|
} else {
|
|
if (NonBlockNumber != 0) {
|
|
UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NON_BLOCK)), NonBlockNumber);
|
|
} else {
|
|
UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NON_BLOCK)));
|
|
}
|
|
BdsLibBuildOptionFromHandle (FileSystemHandles[Index], BdsBootOptionList, Buffer);
|
|
NonBlockNumber++;
|
|
}
|
|
}
|
|
|
|
if (NumberFileSystemHandles != 0) {
|
|
FreePool (FileSystemHandles);
|
|
}
|
|
|
|
//
|
|
// Check if we have on flash shell
|
|
//
|
|
gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
&gEfiFirmwareVolume2ProtocolGuid,
|
|
NULL,
|
|
&FvHandleCount,
|
|
&FvHandleBuffer
|
|
);
|
|
for (Index = 0; Index < FvHandleCount; Index++) {
|
|
gBS->HandleProtocol (
|
|
FvHandleBuffer[Index],
|
|
&gEfiFirmwareVolume2ProtocolGuid,
|
|
(VOID **) &Fv
|
|
);
|
|
|
|
Status = Fv->ReadFile (
|
|
Fv,
|
|
PcdGetPtr(PcdShellFile),
|
|
NULL,
|
|
&Size,
|
|
&Type,
|
|
&Attributes,
|
|
&AuthenticationStatus
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
//
|
|
// Skip if no shell file in the FV
|
|
//
|
|
continue;
|
|
}
|
|
//
|
|
// Build the shell boot option
|
|
//
|
|
BdsLibBuildOptionFromShell (FvHandleBuffer[Index], BdsBootOptionList);
|
|
}
|
|
|
|
if (FvHandleCount != 0) {
|
|
FreePool (FvHandleBuffer);
|
|
}
|
|
|
|
//
|
|
// Parse Network Boot Device
|
|
//
|
|
NumOfLoadFileHandles = 0;
|
|
//
|
|
// Search Load File protocol for PXE boot option.
|
|
//
|
|
gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
&gEfiLoadFileProtocolGuid,
|
|
NULL,
|
|
&NumOfLoadFileHandles,
|
|
&LoadFileHandles
|
|
);
|
|
|
|
for (Index = 0; Index < NumOfLoadFileHandles; Index++) {
|
|
|
|
//
|
|
//Locate EFI_DEVICE_PATH_PROTOCOL to dynamically get IPv4/IPv6 protocol information.
|
|
//
|
|
|
|
Status = gBS->HandleProtocol (
|
|
LoadFileHandles[Index],
|
|
&gEfiDevicePathProtocolGuid,
|
|
(VOID **) &DevicePath
|
|
);
|
|
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
while (!IsDevicePathEnd (DevicePath)) {
|
|
if ((DevicePath->Type == MESSAGING_DEVICE_PATH) &&
|
|
(DevicePath->SubType == MSG_IPv4_DP)) {
|
|
|
|
//
|
|
//Get handle infomation
|
|
//
|
|
BufferSize = 0;
|
|
NetworkHandles = NULL;
|
|
Status = gBS->LocateHandle (
|
|
ByProtocol,
|
|
&gEfiSimpleNetworkProtocolGuid,
|
|
NULL,
|
|
&BufferSize,
|
|
NetworkHandles
|
|
);
|
|
|
|
if (Status == EFI_BUFFER_TOO_SMALL) {
|
|
NetworkHandles = AllocateZeroPool(BufferSize);
|
|
if (NetworkHandles == NULL) {
|
|
return (EFI_OUT_OF_RESOURCES);
|
|
}
|
|
Status = gBS->LocateHandle(
|
|
ByProtocol,
|
|
&gEfiSimpleNetworkProtocolGuid,
|
|
NULL,
|
|
&BufferSize,
|
|
NetworkHandles
|
|
);
|
|
}
|
|
|
|
//
|
|
//Get the MAC string
|
|
//
|
|
Status = NetLibGetMacString (
|
|
*NetworkHandles,
|
|
NULL,
|
|
&MacStr
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
IPverStr = L" IPv4";
|
|
UnicodeSPrint (Buffer, sizeof (Buffer), L"%s%s%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NETWORK)),MacStr,IPverStr);
|
|
break;
|
|
}
|
|
if((DevicePath->Type == MESSAGING_DEVICE_PATH) &&
|
|
(DevicePath->SubType == MSG_IPv6_DP)) {
|
|
|
|
//
|
|
//Get handle infomation
|
|
//
|
|
BufferSize = 0;
|
|
NetworkHandles = NULL;
|
|
Status = gBS->LocateHandle (
|
|
ByProtocol,
|
|
&gEfiSimpleNetworkProtocolGuid,
|
|
NULL,
|
|
&BufferSize,
|
|
NetworkHandles
|
|
);
|
|
|
|
if (Status == EFI_BUFFER_TOO_SMALL) {
|
|
NetworkHandles = AllocateZeroPool(BufferSize);
|
|
if (NetworkHandles == NULL) {
|
|
return (EFI_OUT_OF_RESOURCES);
|
|
}
|
|
Status = gBS->LocateHandle(
|
|
ByProtocol,
|
|
&gEfiSimpleNetworkProtocolGuid,
|
|
NULL,
|
|
&BufferSize,
|
|
NetworkHandles
|
|
);
|
|
}
|
|
|
|
//
|
|
//Get the MAC string
|
|
//
|
|
Status = NetLibGetMacString (
|
|
*NetworkHandles,
|
|
NULL,
|
|
&MacStr
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
IPverStr = L" IPv6";
|
|
UnicodeSPrint (Buffer, sizeof (Buffer), L"%s%s%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NETWORK)),MacStr,IPverStr);
|
|
break;
|
|
}
|
|
DevicePath = NextDevicePathNode (DevicePath);
|
|
}
|
|
|
|
BdsLibBuildOptionFromHandle (LoadFileHandles[Index], BdsBootOptionList, Buffer);
|
|
}
|
|
|
|
if (NumOfLoadFileHandles != 0) {
|
|
FreePool (LoadFileHandles);
|
|
}
|
|
|
|
//
|
|
// Check if we have on flash shell
|
|
//
|
|
/* gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
&gEfiFirmwareVolume2ProtocolGuid,
|
|
NULL,
|
|
&FvHandleCount,
|
|
&FvHandleBuffer
|
|
);
|
|
for (Index = 0; Index < FvHandleCount; Index++) {
|
|
gBS->HandleProtocol (
|
|
FvHandleBuffer[Index],
|
|
&gEfiFirmwareVolume2ProtocolGuid,
|
|
(VOID **) &Fv
|
|
);
|
|
|
|
Status = Fv->ReadFile (
|
|
Fv,
|
|
PcdGetPtr(PcdShellFile),
|
|
NULL,
|
|
&Size,
|
|
&Type,
|
|
&Attributes,
|
|
&AuthenticationStatus
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
//
|
|
// Skip if no shell file in the FV
|
|
//
|
|
continue;
|
|
}
|
|
//
|
|
// Build the shell boot option
|
|
//
|
|
BdsLibBuildOptionFromShell (FvHandleBuffer[Index], BdsBootOptionList);
|
|
}
|
|
|
|
if (FvHandleCount != 0) {
|
|
FreePool (FvHandleBuffer);
|
|
} */
|
|
|
|
//
|
|
// Make sure every boot only have one time
|
|
// boot device enumerate
|
|
//
|
|
Status = BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");
|
|
mEnumBootDevice = TRUE;
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
The function will execute with as the platform policy, current policy
|
|
is driven by boot mode. IBV/OEM can customize this code for their specific
|
|
policy action.
|
|
|
|
@param DriverOptionList - The header of the driver option link list
|
|
@param BootOptionList - The header of the boot option link list
|
|
@param ProcessCapsules - A pointer to ProcessCapsules()
|
|
@param BaseMemoryTest - A pointer to BaseMemoryTest()
|
|
|
|
@retval None.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
PlatformBdsPolicyBehavior (
|
|
IN OUT LIST_ENTRY *DriverOptionList,
|
|
IN OUT LIST_ENTRY *BootOptionList,
|
|
IN PROCESS_CAPSULES BdsProcessCapsules,
|
|
IN BASEM_MEMORY_TEST BaseMemoryTest
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT16 Timeout;
|
|
EFI_BOOT_MODE BootMode;
|
|
BOOLEAN DeferredImageExist;
|
|
UINTN Index;
|
|
SYSTEM_CONFIGURATION SystemConfiguration;
|
|
UINTN VarSize;
|
|
PLATFORM_PCI_DEVICE_PATH *EmmcBootDevPath;
|
|
EFI_GLOBAL_NVS_AREA_PROTOCOL *GlobalNvsArea;
|
|
EFI_HANDLE FvProtocolHandle;
|
|
UINTN HandleCount;
|
|
EFI_HANDLE *HandleBuffer;
|
|
UINTN Index1;
|
|
UINTN SataPciRegBase = 0;
|
|
UINT16 SataModeSelect = 0;
|
|
VOID *RegistrationExitPmAuth = NULL;
|
|
EFI_EVENT Event;
|
|
BOOLEAN IsFirstBoot;
|
|
UINT16 *BootOrder;
|
|
UINTN BootOrderSize;
|
|
ESRT_MANAGEMENT_PROTOCOL *EsrtManagement;
|
|
|
|
Timeout = PcdGet16 (PcdPlatformBootTimeOut);
|
|
if (Timeout > 10 ) {
|
|
//we think the Timeout variable is corrupted
|
|
Timeout = 10;
|
|
}
|
|
|
|
VarSize = sizeof(SYSTEM_CONFIGURATION);
|
|
Status = gRT->GetVariable(
|
|
NORMAL_SETUP_NAME,
|
|
&gEfiNormalSetupGuid,
|
|
NULL,
|
|
&VarSize,
|
|
&SystemConfiguration
|
|
);
|
|
|
|
if (EFI_ERROR (Status) || VarSize != sizeof(SYSTEM_CONFIGURATION)) {
|
|
//The setup variable is corrupted
|
|
VarSize = sizeof(SYSTEM_CONFIGURATION);
|
|
Status = gRT->GetVariable(
|
|
L"SetupRecovery",
|
|
&gEfiNormalSetupGuid,
|
|
NULL,
|
|
&VarSize,
|
|
&SystemConfiguration
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
//
|
|
// Load the driver option as the driver option list
|
|
//
|
|
PlatformBdsGetDriverOption (DriverOptionList);
|
|
|
|
//
|
|
// Get current Boot Mode
|
|
//
|
|
BootMode = GetBootModeHob();
|
|
|
|
//
|
|
// No deferred images exist by default
|
|
//
|
|
DeferredImageExist = FALSE;
|
|
if ((BootMode != BOOT_WITH_MINIMAL_CONFIGURATION) && (PcdGet32(PcdFlashFvShellSize) > 0)){
|
|
gDS->ProcessFirmwareVolume (
|
|
(VOID *)(UINTN)PcdGet32(PcdFlashFvShellBase),
|
|
PcdGet32(PcdFlashFvShellSize),
|
|
&FvProtocolHandle
|
|
);
|
|
}
|
|
|
|
if (SystemConfiguration.FastBoot == 1) {
|
|
BootOrder = BdsLibGetVariableAndSize (
|
|
L"BootOrder",
|
|
&gEfiGlobalVariableGuid,
|
|
&BootOrderSize
|
|
);
|
|
if ((BootOrder != NULL) && (BootMode != BOOT_ON_FLASH_UPDATE)) {
|
|
//
|
|
// BootOrder exist, it means system has boot before. We can do fast boot.
|
|
//
|
|
BootMode = BOOT_WITH_MINIMAL_CONFIGURATION;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Use eMMC to boot OS and turn on AHCI, when SATA HDD is diconnected,
|
|
// SATA AHCI CTLR device will show yellow bang, implement this solution to solve it.
|
|
//
|
|
SataPciRegBase = MmPciAddress (0, 0, PCI_DEVICE_NUMBER_PCH_SATA, 0, 0);
|
|
SataModeSelect = MmioRead16 (SataPciRegBase + R_PCH_SATA_MAP) & B_PCH_SATA_MAP_SMS_MASK;
|
|
Status = EFI_SUCCESS;
|
|
if (SataModeSelect != V_PCH_SATA_MAP_SMS_IDE) {
|
|
Status = gBS->CreateEvent (
|
|
EVT_NOTIFY_SIGNAL,
|
|
TPL_CALLBACK,
|
|
DisableAhciCtlr,
|
|
&SataPciRegBase,
|
|
&Event
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
Status = gBS->RegisterProtocolNotify (
|
|
&gExitPmAuthProtocolGuid,
|
|
Event,
|
|
&RegistrationExitPmAuth
|
|
);
|
|
}
|
|
}
|
|
|
|
Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtManagement);
|
|
if (EFI_ERROR(Status)) {
|
|
EsrtManagement = NULL;
|
|
}
|
|
|
|
switch (BootMode) {
|
|
|
|
case BOOT_WITH_MINIMAL_CONFIGURATION:
|
|
PlatformBdsInitHotKeyEvent ();
|
|
PlatformBdsConnectSimpleConsole (gPlatformSimpleConsole);
|
|
|
|
|
|
//
|
|
// Check to see if it's needed to dispatch more DXE drivers.
|
|
//
|
|
for (Index = 0; Index < sizeof(ConnectDriverTable)/sizeof(EFI_GUID *); Index++) {
|
|
Status = gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
ConnectDriverTable[Index],
|
|
NULL,
|
|
&HandleCount,
|
|
&HandleBuffer
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
for (Index1 = 0; Index1 < HandleCount; Index1++) {
|
|
gBS->ConnectController (
|
|
HandleBuffer[Index1],
|
|
NULL,
|
|
NULL,
|
|
TRUE
|
|
);
|
|
}
|
|
}
|
|
|
|
if (HandleBuffer != NULL) {
|
|
FreePool (HandleBuffer);
|
|
}
|
|
|
|
gDS->Dispatch ();
|
|
}
|
|
|
|
//
|
|
// Locate the Global NVS Protocol.
|
|
//
|
|
Status = gBS->LocateProtocol (
|
|
&gEfiGlobalNvsAreaProtocolGuid,
|
|
NULL,
|
|
(void **)&GlobalNvsArea
|
|
);
|
|
if (GlobalNvsArea->Area->emmcVersion == 0){
|
|
EmmcBootDevPath = (PLATFORM_PCI_DEVICE_PATH *)gPlatformSimpleBootOption[0];
|
|
EmmcBootDevPath->PciDevice.Device = 0x10;
|
|
}
|
|
|
|
//
|
|
// Connect boot device here to give time to read keyboard.
|
|
//
|
|
BdsLibConnectDevicePath (gPlatformSimpleBootOption[0]);
|
|
|
|
//
|
|
// This is a workround for dectecting hotkey from USB keyboard.
|
|
//
|
|
gBS->Stall(KEYBOARD_TIMER_INTERVAL);
|
|
|
|
if (mHotKeyTimerEvent != NULL) {
|
|
gBS->SetTimer (
|
|
mHotKeyTimerEvent,
|
|
TimerCancel,
|
|
0
|
|
);
|
|
gBS->CloseEvent (mHotKeyTimerEvent);
|
|
mHotKeyTimerEvent = NULL;
|
|
}
|
|
if (mHotKeyPressed) {
|
|
//
|
|
// Skip show progress count down
|
|
//
|
|
Timeout = 0xFFFF;
|
|
goto FULL_CONFIGURATION;
|
|
}
|
|
|
|
if (SystemConfiguration.QuietBoot) {
|
|
EnableQuietBoot (PcdGetPtr(PcdLogoFile));
|
|
} else {
|
|
PlatformBdsDiagnostics (IGNORE, FALSE, BaseMemoryTest);
|
|
}
|
|
|
|
|
|
#ifdef TPM_ENABLED
|
|
TcgPhysicalPresenceLibProcessRequest();
|
|
#endif
|
|
#ifdef FTPM_ENABLE
|
|
TrEEPhysicalPresenceLibProcessRequest(NULL);
|
|
#endif
|
|
|
|
if (EsrtManagement != NULL) {
|
|
EsrtManagement->LockEsrtRepository();
|
|
}
|
|
|
|
//
|
|
// Close boot script and install ready to lock
|
|
//
|
|
InstallReadyToLock ();
|
|
|
|
//
|
|
// Give one chance to enter the setup if we
|
|
// select Gummiboot "Reboot Into Firmware Interface" and Fast Boot is enabled.
|
|
//
|
|
BootIntoFirmwareInterface();
|
|
break;
|
|
|
|
case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES:
|
|
|
|
//
|
|
// In no-configuration boot mode, we can connect the
|
|
// console directly.
|
|
//
|
|
BdsLibConnectAllDefaultConsoles ();
|
|
PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest);
|
|
|
|
//
|
|
// Perform some platform specific connect sequence
|
|
//
|
|
PlatformBdsConnectSequence ();
|
|
|
|
//
|
|
// As console is ready, perform user identification again.
|
|
//
|
|
if (mCurrentUser == NULL) {
|
|
PlatformBdsUserIdentify (&mCurrentUser, &DeferredImageExist);
|
|
if (DeferredImageExist) {
|
|
//
|
|
// After user authentication, the deferred drivers was loaded again.
|
|
// Here, need to ensure the deferred images are connected.
|
|
//
|
|
BdsLibConnectAllDefaultConsoles ();
|
|
PlatformBdsConnectSequence ();
|
|
}
|
|
}
|
|
|
|
if (EsrtManagement != NULL) {
|
|
EsrtManagement->LockEsrtRepository();
|
|
}
|
|
|
|
//
|
|
// Close boot script and install ready to lock
|
|
//
|
|
InstallReadyToLock ();
|
|
|
|
//
|
|
// Notes: current time out = 0 can not enter the
|
|
// front page
|
|
//
|
|
PlatformBdsEnterFrontPageWithHotKey (Timeout, FALSE);
|
|
|
|
//
|
|
// Check the boot option with the boot option list
|
|
//
|
|
BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");
|
|
break;
|
|
|
|
case BOOT_ON_FLASH_UPDATE:
|
|
|
|
//
|
|
// Boot with the specific configuration
|
|
//
|
|
PlatformBdsConnectConsole (gPlatformConsole);
|
|
PlatformBdsDiagnostics (EXTENSIVE, FALSE, BaseMemoryTest);
|
|
|
|
DEBUG((DEBUG_INFO, "ProcessCapsules Before EndOfDxe......\n"));
|
|
ProcessCapsules ();
|
|
DEBUG((DEBUG_INFO, "ProcessCapsules Done\n"));
|
|
|
|
//
|
|
// Close boot script and install ready to lock
|
|
//
|
|
InstallReadyToLock ();
|
|
|
|
BdsLibConnectAll ();
|
|
|
|
//
|
|
// Perform user identification
|
|
//
|
|
if (mCurrentUser == NULL) {
|
|
PlatformBdsUserIdentify (&mCurrentUser, &DeferredImageExist);
|
|
if (DeferredImageExist) {
|
|
//
|
|
// After user authentication, the deferred drivers was loaded again.
|
|
// Here, need to ensure the deferred images are connected.
|
|
//
|
|
BdsLibConnectAll ();
|
|
}
|
|
}
|
|
|
|
if (EsrtManagement != NULL) {
|
|
EsrtManagement->SyncEsrtFmp();
|
|
}
|
|
|
|
DEBUG((DEBUG_INFO, "ProcessCapsules After ConnectAll......\n"));
|
|
ProcessCapsules();
|
|
DEBUG((DEBUG_INFO, "ProcessCapsules Done\n"));
|
|
break;
|
|
|
|
case BOOT_IN_RECOVERY_MODE:
|
|
|
|
//
|
|
// In recovery mode, just connect platform console
|
|
// and show up the front page
|
|
//
|
|
PlatformBdsConnectConsole (gPlatformConsole);
|
|
PlatformBdsDiagnostics (EXTENSIVE, FALSE, BaseMemoryTest);
|
|
BdsLibConnectAll ();
|
|
|
|
//
|
|
// Perform user identification
|
|
//
|
|
if (mCurrentUser == NULL) {
|
|
PlatformBdsUserIdentify (&mCurrentUser, &DeferredImageExist);
|
|
if (DeferredImageExist) {
|
|
//
|
|
// After user authentication, the deferred drivers was loaded again.
|
|
// Here, need to ensure the deferred drivers are connected.
|
|
//
|
|
BdsLibConnectAll ();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Close boot script and install ready to lock
|
|
//
|
|
InstallReadyToLock ();
|
|
|
|
//
|
|
// In recovery boot mode, we still enter to the
|
|
// frong page now
|
|
//
|
|
PlatformBdsEnterFrontPageWithHotKey (Timeout, FALSE);
|
|
break;
|
|
|
|
FULL_CONFIGURATION:
|
|
case BOOT_WITH_FULL_CONFIGURATION:
|
|
case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS:
|
|
case BOOT_WITH_DEFAULT_SETTINGS:
|
|
default:
|
|
|
|
//
|
|
// Connect platform console
|
|
//
|
|
Status = PlatformBdsConnectConsole (gPlatformConsole);
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
//
|
|
// Here OEM/IBV can customize with defined action
|
|
//
|
|
PlatformBdsNoConsoleAction ();
|
|
}
|
|
|
|
//
|
|
// Chenyunh[TODO]: This is Workgroud to show the fs for uSDcard,
|
|
// Need to root cause this issue.
|
|
//
|
|
DEBUG ((DEBUG_ERROR, "Start to reconnect all driver.\n"));
|
|
BdsLibDisconnectAllEfi();
|
|
BdsLibConnectAll ();
|
|
DEBUG ((DEBUG_ERROR, "End to reconnect all driver.\n"));
|
|
|
|
//
|
|
// Perform some platform specific connect sequence
|
|
//
|
|
PlatformBdsConnectSequence ();
|
|
if (SystemConfiguration.QuietBoot) {
|
|
EnableQuietBoot (PcdGetPtr(PcdLogoFile));
|
|
} else {
|
|
PlatformBdsDiagnostics (IGNORE, FALSE, BaseMemoryTest);
|
|
}
|
|
|
|
//
|
|
// Do a pre-delay so Hard Disk can spin up and see more logo.
|
|
//
|
|
gBS->Stall(SystemConfiguration.HddPredelay * 1000000);
|
|
|
|
//
|
|
// Perform user identification
|
|
//
|
|
if (mCurrentUser == NULL) {
|
|
PlatformBdsUserIdentify (&mCurrentUser, &DeferredImageExist);
|
|
if (DeferredImageExist) {
|
|
//
|
|
// After user authentication, the deferred drivers was loaded again.
|
|
// Here, need to ensure the deferred drivers are connected.
|
|
//
|
|
Status = PlatformBdsConnectConsole (gPlatformConsole);
|
|
if (EFI_ERROR (Status)) {
|
|
PlatformBdsNoConsoleAction ();
|
|
}
|
|
PlatformBdsConnectSequence ();
|
|
}
|
|
}
|
|
#ifdef TPM_ENABLED
|
|
TcgPhysicalPresenceLibProcessRequest();
|
|
#endif
|
|
#ifdef FTPM_ENABLE
|
|
TrEEPhysicalPresenceLibProcessRequest(NULL);
|
|
#endif
|
|
|
|
if (EsrtManagement != NULL) {
|
|
EsrtManagement->SyncEsrtFmp();
|
|
}
|
|
//
|
|
// Close boot script and install ready to lock
|
|
//
|
|
InstallReadyToLock ();
|
|
|
|
//
|
|
// Here we have enough time to do the enumeration of boot device
|
|
//
|
|
PlatformBdsLibEnumerateAllBootOption (BootOptionList);
|
|
|
|
//
|
|
// Give one chance to enter the setup if we
|
|
// have the time out
|
|
//
|
|
PlatformBdsEnterFrontPageWithHotKey (Timeout, FALSE);
|
|
|
|
//
|
|
// Give one chance to enter the setup if we
|
|
// select Gummiboot "Reboot Into Firmware Interface"
|
|
//
|
|
BootIntoFirmwareInterface();
|
|
|
|
//
|
|
// In default boot mode, always find all boot
|
|
// option and do enumerate all the default boot option
|
|
//
|
|
if (Timeout == 0) {
|
|
BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");
|
|
if (IsListEmpty(BootOptionList)) {
|
|
PlatformBdsPredictBootOption (BootOptionList);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
IsFirstBoot = PcdGetBool(PcdBootState);
|
|
if (IsFirstBoot) {
|
|
PcdSetBool(PcdBootState, FALSE);
|
|
}
|
|
return;
|
|
|
|
}
|
|
|
|
/**
|
|
Hook point after a boot attempt succeeds. We don't expect a boot option to
|
|
return, so the UEFI 2.0 specification defines that you will default to an
|
|
interactive mode and stop processing the BootOrder list in this case. This
|
|
is alos a platform implementation and can be customized by IBV/OEM.
|
|
|
|
@param Option Pointer to Boot Option that succeeded to boot.
|
|
|
|
@retval None.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
PlatformBdsBootSuccess (
|
|
IN BDS_COMMON_OPTION *Option
|
|
)
|
|
{
|
|
CHAR16 *TmpStr;
|
|
|
|
//
|
|
// If Boot returned with EFI_SUCCESS and there is not in the boot device
|
|
// select loop then we need to pop up a UI and wait for user input.
|
|
//
|
|
TmpStr = Option->StatusString;
|
|
if (TmpStr != NULL) {
|
|
BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
|
|
FreePool(TmpStr);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Hook point after a boot attempt fails.
|
|
|
|
@param Option - Pointer to Boot Option that failed to boot.
|
|
@param Status - Status returned from failed boot.
|
|
@param ExitData - Exit data returned from failed boot.
|
|
@param ExitDataSize - Exit data size returned from failed boot.
|
|
|
|
@retval None.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
PlatformBdsBootFail (
|
|
IN BDS_COMMON_OPTION *Option,
|
|
IN EFI_STATUS Status,
|
|
IN CHAR16 *ExitData,
|
|
IN UINTN ExitDataSize
|
|
)
|
|
{
|
|
CHAR16 *TmpStr;
|
|
EFI_HANDLE FvProtocolHandle;
|
|
|
|
//
|
|
// If Boot returned with failed status then we need to pop up a UI and wait
|
|
// for user input.
|
|
//
|
|
TmpStr = Option->StatusString;
|
|
if (TmpStr != NULL) {
|
|
BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
|
|
FreePool(TmpStr);
|
|
}
|
|
if (PcdGet32(PcdFlashFvShellSize) > 0){
|
|
gDS->ProcessFirmwareVolume (
|
|
(VOID *)(UINTN)PcdGet32(PcdFlashFvShellBase),
|
|
PcdGet32(PcdFlashFvShellSize),
|
|
&FvProtocolHandle
|
|
);
|
|
}
|
|
PlatformBdsConnectSequence ();
|
|
}
|
|
|
|
/**
|
|
This function is remained for IBV/OEM to do some platform action,
|
|
if there no console device can be connected.
|
|
|
|
@param None.
|
|
|
|
@retval EFI_SUCCESS Direct return success now.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
PlatformBdsNoConsoleAction (
|
|
VOID
|
|
)
|
|
{
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
This function locks the block
|
|
|
|
@param Base The base address flash region to be locked.
|
|
|
|
**/
|
|
VOID
|
|
BdsLockFv (
|
|
IN EFI_PHYSICAL_ADDRESS Base
|
|
)
|
|
{
|
|
EFI_FV_BLOCK_MAP_ENTRY *BlockMap;
|
|
EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
|
|
EFI_PHYSICAL_ADDRESS BaseAddress;
|
|
UINT32 BlockLength;
|
|
UINTN Index;
|
|
|
|
BaseAddress = Base - 0x400000 + 2;
|
|
FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) (Base));
|
|
BlockMap = &(FvHeader->BlockMap[0]);
|
|
|
|
while ((BlockMap->NumBlocks != 0) && (BlockMap->Length != 0)) {
|
|
BlockLength = BlockMap->Length;
|
|
for (Index = 0; Index < BlockMap->NumBlocks; Index++) {
|
|
MmioOr8 ((UINTN) BaseAddress, 0x03);
|
|
BaseAddress += BlockLength;
|
|
}
|
|
BlockMap++;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
EFIAPI
|
|
PlatformBdsLockNonUpdatableFlash (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_PHYSICAL_ADDRESS Base;
|
|
|
|
Base = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashFvMainBase);
|
|
if (Base > 0) {
|
|
BdsLockFv (Base);
|
|
}
|
|
|
|
Base = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashFvRecoveryBase);
|
|
if (Base > 0) {
|
|
BdsLockFv (Base);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Lock the ConsoleIn device in system table. All key
|
|
presses will be ignored until the Password is typed in. The only way to
|
|
disable the password is to type it in to a ConIn device.
|
|
|
|
@param Password Password used to lock ConIn device.
|
|
|
|
@retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.
|
|
@retval EFI_UNSUPPORTED Password not found
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
LockKeyboards (
|
|
IN CHAR16 *Password
|
|
)
|
|
{
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
/**
|
|
Connect the predefined platform default authentication devices.
|
|
|
|
This function connects the predefined device path for authentication device,
|
|
and if the predefined device path has child device path, the child handle will
|
|
be connected too. But the child handle of the child will not be connected.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
PlatformBdsConnectAuthDevice (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN Index;
|
|
UINTN HandleIndex;
|
|
UINTN HandleCount;
|
|
EFI_HANDLE *HandleBuffer;
|
|
EFI_DEVICE_PATH_PROTOCOL *ChildDevicePath;
|
|
EFI_USER_MANAGER_PROTOCOL *Manager;
|
|
|
|
Status = gBS->LocateProtocol (
|
|
&gEfiUserManagerProtocolGuid,
|
|
NULL,
|
|
(VOID **) &Manager
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
//
|
|
// As user manager protocol is not installed, the authentication devices
|
|
// should not be connected.
|
|
//
|
|
return ;
|
|
}
|
|
|
|
Index = 0;
|
|
while (gUserAuthenticationDevice[Index] != NULL) {
|
|
//
|
|
// Connect the platform customized device paths
|
|
//
|
|
BdsLibConnectDevicePath (gUserAuthenticationDevice[Index]);
|
|
Index++;
|
|
}
|
|
|
|
//
|
|
// Find and connect the child device paths of the platform customized device paths
|
|
//
|
|
HandleBuffer = NULL;
|
|
for (Index = 0; gUserAuthenticationDevice[Index] != NULL; Index++) {
|
|
HandleCount = 0;
|
|
Status = gBS->LocateHandleBuffer (
|
|
AllHandles,
|
|
NULL,
|
|
NULL,
|
|
&HandleCount,
|
|
&HandleBuffer
|
|
);
|
|
ASSERT (!EFI_ERROR (Status));
|
|
|
|
//
|
|
// Find and connect the child device paths of gUserIdentificationDevice[Index]
|
|
//
|
|
for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
|
|
ChildDevicePath = NULL;
|
|
Status = gBS->HandleProtocol (
|
|
HandleBuffer[HandleIndex],
|
|
&gEfiDevicePathProtocolGuid,
|
|
(VOID **) &ChildDevicePath
|
|
);
|
|
if (EFI_ERROR (Status) || ChildDevicePath == NULL) {
|
|
continue;
|
|
}
|
|
|
|
if (CompareMem (
|
|
ChildDevicePath,
|
|
gUserAuthenticationDevice[Index],
|
|
(GetDevicePathSize (gUserAuthenticationDevice[Index]) - sizeof (EFI_DEVICE_PATH_PROTOCOL))
|
|
) != 0) {
|
|
continue;
|
|
}
|
|
gBS->ConnectController (
|
|
HandleBuffer[HandleIndex],
|
|
NULL,
|
|
NULL,
|
|
TRUE
|
|
);
|
|
}
|
|
}
|
|
|
|
if (HandleBuffer != NULL) {
|
|
FreePool (HandleBuffer);
|
|
}
|
|
}
|
|
|
|
/**
|
|
This function is to identify a user, and return whether deferred images exist.
|
|
|
|
@param[out] User Point to user profile handle.
|
|
@param[out] DeferredImageExist On return, points to TRUE if the deferred image
|
|
exist or FALSE if it did not exist.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
PlatformBdsUserIdentify (
|
|
OUT EFI_USER_PROFILE_HANDLE *User,
|
|
OUT BOOLEAN *DeferredImageExist
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_DEFERRED_IMAGE_LOAD_PROTOCOL *DeferredImage;
|
|
UINTN HandleCount;
|
|
EFI_HANDLE *HandleBuf;
|
|
UINTN Index;
|
|
UINTN DriverIndex;
|
|
EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath;
|
|
VOID *DriverImage;
|
|
UINTN ImageSize;
|
|
BOOLEAN BootOption;
|
|
|
|
//
|
|
// Perform user identification
|
|
//
|
|
do {
|
|
Status = BdsLibUserIdentify (User);
|
|
} while (EFI_ERROR (Status));
|
|
|
|
//
|
|
// After user authentication now, try to find whether deferred image exists
|
|
//
|
|
HandleCount = 0;
|
|
HandleBuf = NULL;
|
|
*DeferredImageExist = FALSE;
|
|
Status = gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
&gEfiDeferredImageLoadProtocolGuid,
|
|
NULL,
|
|
&HandleCount,
|
|
&HandleBuf
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return ;
|
|
}
|
|
|
|
for (Index = 0; Index < HandleCount; Index++) {
|
|
Status = gBS->HandleProtocol (
|
|
HandleBuf[Index],
|
|
&gEfiDeferredImageLoadProtocolGuid,
|
|
(VOID **) &DeferredImage
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
//
|
|
// Find whether deferred image exists in this instance.
|
|
//
|
|
DriverIndex = 0;
|
|
Status = DeferredImage->GetImageInfo(
|
|
DeferredImage,
|
|
DriverIndex,
|
|
&ImageDevicePath,
|
|
(VOID **) &DriverImage,
|
|
&ImageSize,
|
|
&BootOption
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
//
|
|
// The deferred image is found.
|
|
//
|
|
FreePool (HandleBuf);
|
|
*DeferredImageExist = TRUE;
|
|
return ;
|
|
}
|
|
}
|
|
}
|
|
|
|
FreePool (HandleBuf);
|
|
}
|
|
|
|
UINTN gHotKey = 0;
|
|
|
|
|
|
EFI_STATUS
|
|
ShowProgressHotKey (
|
|
IN UINT16 TimeoutDefault
|
|
)
|
|
{
|
|
CHAR16 *TmpStr;
|
|
UINT16 TimeoutRemain;
|
|
EFI_STATUS Status;
|
|
EFI_INPUT_KEY Key;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;
|
|
UINT32 GpioValue;
|
|
CHAR16 *TmpStr1;
|
|
CHAR16 *TmpStr2;
|
|
CHAR16 *TmpStr3;
|
|
UINTN TmpStrSize;
|
|
VOID *Buffer;
|
|
UINTN Size;
|
|
|
|
if (TimeoutDefault == 0) {
|
|
return EFI_TIMEOUT;
|
|
}
|
|
|
|
gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
|
|
|
|
if (DebugAssertEnabled())
|
|
{
|
|
DEBUG ((EFI_D_INFO, "\n\nStart showing progress bar... Press any key to stop it, or press <F2> or <DEL> to enter setup page! ...Zzz....\n"));
|
|
}
|
|
else
|
|
{
|
|
#ifdef __GNUC__
|
|
SerialPortWrite((UINT8 *)"\n\n>>>>Start boot option, Press <F2> or <DEL> to enter setup page(5 Sec)[GCC]", 76);
|
|
#else
|
|
SerialPortWrite((UINT8 *)"\n\n>>>>Start boot option, Press <F2> or <DEL> to enter setup page(5 Sec)", 71);
|
|
#endif
|
|
}
|
|
SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
|
|
SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
|
|
SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
|
|
|
|
TmpStr2 = NULL;
|
|
TmpStr3 = NULL;
|
|
|
|
//
|
|
// Check if the platform is using test key.
|
|
//
|
|
Status = GetSectionFromAnyFv(
|
|
PcdGetPtr(PcdEdkiiRsa2048Sha256TestPublicKeyFileGuid),
|
|
EFI_SECTION_RAW,
|
|
0,
|
|
&Buffer,
|
|
&Size
|
|
);
|
|
if (!EFI_ERROR(Status)) {
|
|
if ((Size == PcdGetSize(PcdRsa2048Sha256PublicKeyBuffer)) &&
|
|
(CompareMem(Buffer, PcdGetPtr(PcdRsa2048Sha256PublicKeyBuffer), Size) == 0)) {
|
|
TmpStr2 = L"WARNING: Recovery Test Key is used.\r\n";
|
|
if (DebugAssertEnabled()) {
|
|
DEBUG ((DEBUG_INFO, "\n\nWARNING: Recovery Test Key is used.\n"));
|
|
} else {
|
|
SerialPortWrite((UINT8 *)"\n\nWARNING: Recovery Test Key is used.", sizeof("\n\nWARNING: Recovery Test Key is used."));
|
|
}
|
|
PcdSetBoolS(PcdTestKeyUsed, TRUE);
|
|
}
|
|
FreePool(Buffer);
|
|
}
|
|
Status = GetSectionFromAnyFv(
|
|
PcdGetPtr(PcdEdkiiPkcs7TestPublicKeyFileGuid),
|
|
EFI_SECTION_RAW,
|
|
0,
|
|
&Buffer,
|
|
&Size
|
|
);
|
|
if (!EFI_ERROR(Status)) {
|
|
if ((Size == PcdGetSize(PcdPkcs7CertBuffer)) &&
|
|
(CompareMem(Buffer, PcdGetPtr(PcdPkcs7CertBuffer), Size) == 0)) {
|
|
TmpStr3 = L"WARNING: Capsule Test Key is used.\r\n";
|
|
if (DebugAssertEnabled()) {
|
|
DEBUG ((DEBUG_INFO, "\n\nWARNING: Capsule Test Key is used.\r\n"));
|
|
} else {
|
|
SerialPortWrite((UINT8 *)"\n\nWARNING: Capsule Test Key is used.", sizeof("\n\nWARNING: Capsule Test Key is used."));
|
|
}
|
|
PcdSetBoolS(PcdTestKeyUsed, TRUE);
|
|
}
|
|
FreePool(Buffer);
|
|
}
|
|
|
|
//
|
|
// Clear the progress status bar first
|
|
//
|
|
TmpStr1 = L"Start boot option, Press <F2> or <DEL> to enter setup page.\r\n";
|
|
TmpStrSize = StrSize(TmpStr1);
|
|
if (TmpStr2 != NULL) {
|
|
TmpStrSize += StrSize(TmpStr2);
|
|
}
|
|
if (TmpStr3 != NULL) {
|
|
TmpStrSize += StrSize(TmpStr3);
|
|
}
|
|
TmpStr = AllocatePool (TmpStrSize);
|
|
if (TmpStr == NULL) {
|
|
TmpStr = TmpStr1;
|
|
} else {
|
|
StrCpyS(TmpStr, TmpStrSize/sizeof(CHAR16), TmpStr1);
|
|
if (TmpStr2 != NULL) {
|
|
StrCatS(TmpStr, TmpStrSize/sizeof(CHAR16), TmpStr2);
|
|
}
|
|
if (TmpStr3 != NULL) {
|
|
StrCatS(TmpStr, TmpStrSize/sizeof(CHAR16), TmpStr3);
|
|
}
|
|
}
|
|
PlatformBdsShowProgress (Foreground, Background, TmpStr, Color, 0, 0);
|
|
|
|
TimeoutRemain = TimeoutDefault;
|
|
while (TimeoutRemain != 0) {
|
|
if (DebugAssertEnabled())
|
|
{
|
|
DEBUG ((EFI_D_INFO, "Showing progress bar...Remaining %d second!\n", TimeoutRemain));
|
|
}
|
|
else
|
|
{
|
|
SerialPortWrite ((UINT8 *)".", 1);
|
|
}
|
|
Status = WaitForSingleEvent (gST->ConIn->WaitForKey, ONE_SECOND);
|
|
if (Status != EFI_TIMEOUT) {
|
|
break;
|
|
}
|
|
TimeoutRemain--;
|
|
|
|
//
|
|
// Show progress
|
|
//
|
|
if (TmpStr != NULL) {
|
|
PlatformBdsShowProgress (
|
|
Foreground,
|
|
Background,
|
|
TmpStr,
|
|
Color,
|
|
((TimeoutDefault - TimeoutRemain) * 100 / TimeoutDefault),
|
|
0
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Timeout expired
|
|
//
|
|
if (TimeoutRemain == 0) {
|
|
if (DebugAssertEnabled())
|
|
{
|
|
}
|
|
else
|
|
{
|
|
SerialPortWrite ((UINT8 *)"\r\n", 2);
|
|
}
|
|
return EFI_TIMEOUT;
|
|
}
|
|
|
|
//
|
|
// User pressed some key
|
|
//
|
|
Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Check Volume Up Key to enter Setup
|
|
//
|
|
GpioValue = MmioRead32 (IO_BASE_ADDRESS + 0x0668); // The value of GPIOC_5
|
|
if (((GpioValue & BIT0) == 0) && (Key.ScanCode == SCAN_UP)) {
|
|
gHotKey = 0;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
|
|
//
|
|
// User pressed enter, equivalent to select "continue"
|
|
//
|
|
return EFI_TIMEOUT;
|
|
}
|
|
|
|
//
|
|
//F2 -- Front Page
|
|
//F5 -- Device Manager
|
|
//F7 -- Boot Manager
|
|
// do not use F8. generally people assume it is windows safe mode key.
|
|
//F9 -- Boot order
|
|
//
|
|
DEBUG ((EFI_D_INFO, "[Key Pressed]: ScanCode 0x%x\n", Key.ScanCode));
|
|
switch(Key.ScanCode) {
|
|
case SCAN_F2:
|
|
gHotKey = 0;
|
|
break;
|
|
|
|
case SCAN_DELETE:
|
|
gHotKey = 0;
|
|
break;
|
|
|
|
case SCAN_F5:
|
|
gHotKey = FRONT_PAGE_KEY_DEVICE_MANAGER;
|
|
break;
|
|
|
|
case SCAN_F7:
|
|
gHotKey = FRONT_PAGE_KEY_BOOT_MANAGER;
|
|
break;
|
|
|
|
case SCAN_F9:
|
|
gHotKey = FRONT_PAGE_KEY_BOOT_MAINTAIN;
|
|
break;
|
|
|
|
default:
|
|
//set gHotKey to continue so that flow will not go into CallFrontPage
|
|
gHotKey = FRONT_PAGE_KEY_CONTINUE;
|
|
return EFI_TIMEOUT;
|
|
break;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
This function is the main entry of the platform setup entry.
|
|
The function will present the main menu of the system setup,
|
|
this is the platform reference part and can be customize.
|
|
|
|
|
|
@param TimeoutDefault The fault time out value before the system
|
|
continue to boot.
|
|
@param ConnectAllHappened The indicater to check if the connect all have
|
|
already happened.
|
|
|
|
**/
|
|
VOID
|
|
PlatformBdsEnterFrontPageWithHotKey (
|
|
IN UINT16 TimeoutDefault,
|
|
IN BOOLEAN ConnectAllHappened
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
|
|
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut;
|
|
UINTN BootTextColumn;
|
|
UINTN BootTextRow;
|
|
|
|
GraphicsOutput = NULL;
|
|
SimpleTextOut = NULL;
|
|
|
|
PERF_START (NULL, "BdsTimeOut", "BDS", 0);
|
|
|
|
//
|
|
// Indicate if we need connect all in the platform setup
|
|
//
|
|
if (ConnectAllHappened) {
|
|
gConnectAllHappened = TRUE;
|
|
}
|
|
|
|
if (!mModeInitialized) {
|
|
//
|
|
// After the console is ready, get current video resolution
|
|
// and text mode before launching setup at first time.
|
|
//
|
|
Status = gBS->HandleProtocol (
|
|
gST->ConsoleOutHandle,
|
|
&gEfiGraphicsOutputProtocolGuid,
|
|
(VOID**)&GraphicsOutput
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
GraphicsOutput = NULL;
|
|
}
|
|
|
|
Status = gBS->HandleProtocol (
|
|
gST->ConsoleOutHandle,
|
|
&gEfiSimpleTextOutProtocolGuid,
|
|
(VOID**)&SimpleTextOut
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
SimpleTextOut = NULL;
|
|
}
|
|
|
|
if (GraphicsOutput != NULL) {
|
|
//
|
|
// Get current video resolution and text mode.
|
|
//
|
|
mBootHorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution;
|
|
mBootVerticalResolution = GraphicsOutput->Mode->Info->VerticalResolution;
|
|
}
|
|
|
|
if (SimpleTextOut != NULL) {
|
|
Status = SimpleTextOut->QueryMode (
|
|
SimpleTextOut,
|
|
SimpleTextOut->Mode->Mode,
|
|
&BootTextColumn,
|
|
&BootTextRow
|
|
);
|
|
mBootTextModeColumn = (UINT32)BootTextColumn;
|
|
mBootTextModeRow = (UINT32)BootTextRow;
|
|
}
|
|
|
|
//
|
|
// Get user defined text mode for setup.
|
|
//
|
|
mSetupHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution);
|
|
mSetupVerticalResolution = PcdGet32 (PcdSetupVideoVerticalResolution);
|
|
mSetupTextModeColumn = PcdGet32 (PcdSetupConOutColumn);
|
|
mSetupTextModeRow = PcdGet32 (PcdSetupConOutRow);
|
|
|
|
mModeInitialized = TRUE;
|
|
}
|
|
|
|
if (TimeoutDefault != 0xffff) {
|
|
Status = ShowProgressHotKey (TimeoutDefault);
|
|
|
|
//
|
|
// Ensure screen is clear when switch Console from Graphics mode to Text mode
|
|
//
|
|
gST->ConOut->EnableCursor (gST->ConOut, TRUE);
|
|
gST->ConOut->ClearScreen (gST->ConOut);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
//
|
|
// Timeout or user press enter to continue
|
|
//
|
|
goto Exit;
|
|
}
|
|
}
|
|
//
|
|
// Install BM HiiPackages.
|
|
// Keep BootMaint HiiPackage, so that it can be covered by global setting.
|
|
//
|
|
InitBMPackage ();
|
|
do {
|
|
|
|
BdsSetConsoleMode (TRUE);
|
|
|
|
InitializeFrontPage (FALSE);
|
|
|
|
//
|
|
// Update Front Page strings
|
|
//
|
|
UpdateFrontPageStrings ();
|
|
|
|
Status = EFI_SUCCESS;
|
|
gCallbackKey = 0;
|
|
if (gHotKey == 0) {
|
|
Status = CallFrontPage ();
|
|
} else {
|
|
gCallbackKey = gHotKey;
|
|
gHotKey = 0;
|
|
}
|
|
|
|
//
|
|
// If gCallbackKey is greater than 1 and less or equal to 5,
|
|
// it will launch configuration utilities.
|
|
// 2 = set language
|
|
// 3 = boot manager
|
|
// 4 = device manager
|
|
// 5 = boot maintenance manager
|
|
//
|
|
if (gCallbackKey != 0) {
|
|
REPORT_STATUS_CODE (
|
|
EFI_PROGRESS_CODE,
|
|
(EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_USER_SETUP)
|
|
);
|
|
}
|
|
|
|
//
|
|
// Based on the key that was set, we can determine what to do
|
|
//
|
|
switch (gCallbackKey) {
|
|
//
|
|
// The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can
|
|
// describe to their customers in documentation how to find their setup information (namely
|
|
// under the device manager and specific buckets)
|
|
//
|
|
// These entries consist of the Continue, Select language, Boot Manager, and Device Manager
|
|
//
|
|
case FRONT_PAGE_KEY_CONTINUE:
|
|
|
|
//
|
|
// User hit continue
|
|
//
|
|
break;
|
|
|
|
case FRONT_PAGE_KEY_LANGUAGE:
|
|
|
|
//
|
|
// User made a language setting change - display front page again
|
|
//
|
|
break;
|
|
|
|
case FRONT_PAGE_KEY_BOOT_MANAGER:
|
|
//
|
|
// Remove the installed BootMaint HiiPackages when exit.
|
|
//
|
|
FreeBMPackage ();
|
|
|
|
//
|
|
// User chose to run the Boot Manager
|
|
//
|
|
CallBootManager ();
|
|
|
|
//
|
|
// Reinstall BootMaint HiiPackages after exiting from Boot Manager.
|
|
//
|
|
InitBMPackage ();
|
|
break;
|
|
|
|
case FRONT_PAGE_KEY_DEVICE_MANAGER:
|
|
|
|
//
|
|
// Display the Device Manager
|
|
//
|
|
do {
|
|
CallDeviceManager ();
|
|
} while (gCallbackKey == FRONT_PAGE_KEY_DEVICE_MANAGER);
|
|
break;
|
|
|
|
case FRONT_PAGE_KEY_BOOT_MAINTAIN:
|
|
|
|
//
|
|
// Display the Boot Maintenance Manager
|
|
//
|
|
BdsStartBootMaint ();
|
|
break;
|
|
}
|
|
|
|
} while (((UINTN)gCallbackKey) != FRONT_PAGE_KEY_CONTINUE);
|
|
|
|
//
|
|
//Will leave browser, check any reset required change is applied? if yes, reset system
|
|
//
|
|
SetupResetReminder ();
|
|
//
|
|
// Remove the installed BootMaint HiiPackages when exit.
|
|
//
|
|
FreeBMPackage ();
|
|
|
|
Exit:
|
|
//
|
|
// Automatically load current entry
|
|
// Note: The following lines of code only execute when Auto boot
|
|
// takes affect
|
|
//
|
|
PERF_END (NULL, "BdsTimeOut", "BDS", 0);
|
|
}
|
|
|
|
|
|
VOID
|
|
BootIntoFirmwareInterface(
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN DataSize;
|
|
UINT16 Timeout;
|
|
UINT64 OsIndication;
|
|
|
|
|
|
OsIndication = 0;
|
|
DataSize = sizeof(UINT64);
|
|
Status = gRT->GetVariable (
|
|
L"OsIndications",
|
|
&gEfiGlobalVariableGuid,
|
|
NULL,
|
|
&DataSize,
|
|
&OsIndication
|
|
);
|
|
|
|
DEBUG ((EFI_D_INFO, "OSIndication Variable Value %d\n", OsIndication));
|
|
//
|
|
//Goto FrontPage directly when bit EFI_OS_INDICATIONS_BOOT_TO_FW_UI in OSIndication Variable is setted.
|
|
//
|
|
if (!EFI_ERROR(Status) && (OsIndication != 0)) {
|
|
Timeout = 0xffff;
|
|
PlatformBdsEnterFrontPage (Timeout, FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
EFI_STATUS
|
|
PlatformBdsConnectSimpleConsole (
|
|
IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN Index;
|
|
EFI_DEVICE_PATH_PROTOCOL *VarConout;
|
|
EFI_DEVICE_PATH_PROTOCOL *VarConin;
|
|
UINTN DevicePathSize;
|
|
|
|
|
|
Index = 0;
|
|
Status = EFI_SUCCESS;
|
|
DevicePathSize = 0;
|
|
VarConout = BdsLibGetVariableAndSize (
|
|
L"ConOut",
|
|
&gEfiGlobalVariableGuid,
|
|
&DevicePathSize
|
|
);
|
|
VarConin = BdsLibGetVariableAndSize (
|
|
L"ConIn",
|
|
&gEfiGlobalVariableGuid,
|
|
&DevicePathSize
|
|
);
|
|
if (VarConout == NULL || VarConin == NULL) {
|
|
//
|
|
// Have chance to connect the platform default console,
|
|
// the platform default console is the minimum device group
|
|
// the platform should support
|
|
//
|
|
while (PlatformConsole[Index].DevicePath != NULL) {
|
|
|
|
//
|
|
// Update the console variable with the connect type
|
|
//
|
|
if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
|
|
BdsLibUpdateConsoleVariable (L"ConIn", PlatformConsole[Index].DevicePath, NULL);
|
|
}
|
|
|
|
if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
|
|
BdsLibUpdateConsoleVariable (L"ConOut", PlatformConsole[Index].DevicePath, NULL);
|
|
}
|
|
|
|
if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
|
|
BdsLibUpdateConsoleVariable (L"ErrOut", PlatformConsole[Index].DevicePath, NULL);
|
|
}
|
|
|
|
Index ++;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Connect ConIn first to give keyboard time to parse hot key event.
|
|
//
|
|
Status = BdsLibConnectConsoleVariable (L"ConIn");
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Make sure we have at least one active VGA, and have the right
|
|
// active VGA in console variable
|
|
//
|
|
Status = PlatformBdsForceActiveVga ();
|
|
|
|
//
|
|
// It seems impossible not to have any ConOut device on platform,
|
|
// so we check the status here.
|
|
//
|
|
Status = BdsLibConnectConsoleVariable (L"ConOut");
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
Timer handler to convert the key from USB.
|
|
|
|
@param Event Indicates the event that invoke this function.
|
|
@param Context Indicates the calling context.
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
HotKeyTimerHandler (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_INPUT_KEY Key;
|
|
|
|
Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
|
|
if (EFI_ERROR (Status)) {
|
|
return;
|
|
}
|
|
|
|
switch(Key.ScanCode) {
|
|
case SCAN_F2:
|
|
gHotKey = 0;
|
|
mHotKeyPressed = TRUE;
|
|
break;
|
|
|
|
case SCAN_F5:
|
|
gHotKey = FRONT_PAGE_KEY_DEVICE_MANAGER;
|
|
mHotKeyPressed = TRUE;
|
|
break;
|
|
|
|
case SCAN_F7:
|
|
gHotKey = FRONT_PAGE_KEY_BOOT_MANAGER;
|
|
mHotKeyPressed = TRUE;
|
|
break;
|
|
|
|
case SCAN_F9:
|
|
gHotKey = FRONT_PAGE_KEY_BOOT_MAINTAIN;
|
|
mHotKeyPressed = TRUE;
|
|
break;
|
|
}
|
|
|
|
if (mHotKeyPressed) {
|
|
gBS->SetTimer (
|
|
mHotKeyTimerEvent,
|
|
TimerCancel,
|
|
0
|
|
);
|
|
gBS->CloseEvent (mHotKeyTimerEvent);
|
|
mHotKeyTimerEvent = NULL;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/**
|
|
Callback function for SimpleTextInEx protocol install events
|
|
|
|
@param Event the event that is signaled.
|
|
@param Context not used here.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
HitHotkeyEvent (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
Status = gBS->CloseEvent(mHitHotkeyEvent);
|
|
if (EFI_ERROR (Status)) {
|
|
return;
|
|
}
|
|
Status = gBS->CreateEvent (
|
|
EVT_TIMER | EVT_NOTIFY_SIGNAL,
|
|
TPL_NOTIFY,
|
|
HotKeyTimerHandler,
|
|
NULL,
|
|
&mHotKeyTimerEvent
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return;
|
|
}
|
|
Status = gBS->SetTimer (
|
|
mHotKeyTimerEvent,
|
|
TimerPeriodic,
|
|
KEYBOARD_TIMER_INTERVAL
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
EFIAPI
|
|
PlatformBdsInitHotKeyEvent (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
//
|
|
// Register Protocol notify for Hotkey service
|
|
//
|
|
Status = gBS->CreateEvent (
|
|
EVT_NOTIFY_SIGNAL,
|
|
TPL_CALLBACK,
|
|
HitHotkeyEvent,
|
|
NULL,
|
|
&mHitHotkeyEvent
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
//
|
|
// Register for protocol notifications on this event
|
|
//
|
|
Status = gBS->RegisterProtocolNotify (
|
|
&gEfiSimpleTextInputExProtocolGuid,
|
|
mHitHotkeyEvent,
|
|
&mHitHotkeyRegistration
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|