| /** @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); | |
| } |