summaryrefslogtreecommitdiffstats
path: root/Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c
diff options
context:
space:
mode:
Diffstat (limited to 'Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c')
-rw-r--r--Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c2399
1 files changed, 2399 insertions, 0 deletions
diff --git a/Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c b/Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c
new file mode 100644
index 0000000000..b0ada79f02
--- /dev/null
+++ b/Vlv2TbltDevicePkg/Library/PlatformBdsLib/BdsPlatform.c
@@ -0,0 +1,2399 @@
+/** @file
+
+ Copyright (c) 2004 - 2014, 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>
+
+
+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);
+
+ 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. Incude 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 dirver 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
+ );
+ 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 futhure, 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
+ );
+ 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
+ );
+ 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 Predfined 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 minimue 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 predeined 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);
+}
+
+
+/**
+
+ The function will excute 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 ProcessCapsules,
+ IN BASEM_MEMORY_TEST BaseMemoryTest
+ )
+{
+ EFI_STATUS Status;
+ UINT16 Timeout;
+ EFI_BOOT_MODE BootMode;
+ BOOLEAN DeferredImageExist;
+ UINTN Index;
+ CHAR16 CapsuleVarName[36];
+ CHAR16 *TempVarName;
+ SYSTEM_CONFIGURATION SystemConfiguration;
+ UINTN VarSize;
+ BOOLEAN SetVariableFlag;
+ 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;
+
+ Timeout = PcdGet16 (PcdPlatformBootTimeOut);
+ VarSize = sizeof(SYSTEM_CONFIGURATION);
+ Status = gRT->GetVariable(
+ NORMAL_SETUP_NAME,
+ &gEfiNormalSetupGuid,
+ NULL,
+ &VarSize,
+ &SystemConfiguration
+ );
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ //
+ // Load the driver option as the driver option list
+ //
+ PlatformBdsGetDriverOption (DriverOptionList);
+
+ //
+ // Get current Boot Mode
+ //
+ BootMode = GetBootModeHob();
+
+ //
+ // Clear all the capsule variables CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...
+ // as early as possible which will avoid the next time boot after the capsule update
+ // will still into the capsule loop
+ //
+ StrCpy (CapsuleVarName, EFI_CAPSULE_VARIABLE_NAME);
+ TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
+ Index = 0;
+ SetVariableFlag = TRUE;
+ while (SetVariableFlag) {
+ if (Index > 0) {
+ UnicodeValueToString (TempVarName, 0, Index, 0);
+ }
+ Status = gRT->SetVariable (
+ CapsuleVarName,
+ &gEfiCapsuleVendorGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ 0,
+ (VOID *)NULL
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // There is no capsule variables, quit
+ //
+ SetVariableFlag = FALSE;
+ continue;
+ }
+ Index++;
+ }
+
+ //
+ // 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
+ );
+ }
+ }
+
+ 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
+
+ //
+ // 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 ();
+ }
+ }
+
+ //
+ // 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);
+ 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 ();
+ }
+ }
+
+ //
+ // Close boot script and install ready to lock
+ //
+ InstallReadyToLock ();
+
+ ProcessCapsules (BOOT_ON_FLASH_UPDATE);
+ 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
+
+ //
+ // Close boot script and install ready to lock
+ //
+ InstallReadyToLock ();
+
+ //
+ // 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;
+ }
+
+ //
+ // Here we have enough time to do the enumeration of boot device
+ //
+ BdsLibEnumerateAllBootOption (BootOptionList);
+ 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;
+ UINT8 Data;
+ 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++) {
+ Data = 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;
+
+ if (TimeoutDefault == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ 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);
+
+ //
+ // Clear the progress status bar first
+ //
+ TmpStr = L"Start boot option, Press <F2> or <DEL> to enter setup page.";
+ 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;
+ }
+ }
+
+ 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:
+
+ //
+ // User chose to run the Boot Manager
+ //
+ CallBootManager ();
+ 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 ();
+
+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 minimue 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);
+}