diff options
Diffstat (limited to 'CorebootPayloadPkg/Library/PlatformBdsLib/BdsPlatform.c')
-rw-r--r-- | CorebootPayloadPkg/Library/PlatformBdsLib/BdsPlatform.c | 1016 |
1 files changed, 1016 insertions, 0 deletions
diff --git a/CorebootPayloadPkg/Library/PlatformBdsLib/BdsPlatform.c b/CorebootPayloadPkg/Library/PlatformBdsLib/BdsPlatform.c new file mode 100644 index 0000000000..fec14a3be8 --- /dev/null +++ b/CorebootPayloadPkg/Library/PlatformBdsLib/BdsPlatform.c @@ -0,0 +1,1016 @@ +/** @file
+ This file include all platform action which can be customized by IBV/OEM.
+
+Copyright (c) 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
+which 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.
+
+**/
+
+#include "BdsPlatform.h"
+
+//
+// Global data
+//
+BOOLEAN mDetectVgaOnly;
+
+
+//
+// Type definitions
+//
+
+typedef
+EFI_STATUS
+(EFIAPI *PROTOCOL_INSTANCE_CALLBACK)(
+ IN EFI_HANDLE Handle,
+ IN VOID *Instance,
+ IN VOID *Context
+ );
+
+/**
+ @param[in] Handle - Handle of PCI device instance
+ @param[in] PciIo - PCI IO protocol instance
+ @param[in] Pci - PCI Header register block
+**/
+typedef
+EFI_STATUS
+(EFIAPI *VISIT_PCI_INSTANCE_CALLBACK)(
+ IN EFI_HANDLE Handle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN PCI_TYPE00 *Pci
+ );
+
+
+//
+// Function prototypes
+//
+
+EFI_STATUS
+VisitAllInstancesOfProtocol (
+ IN EFI_GUID *Id,
+ IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,
+ IN VOID *Context
+ );
+
+EFI_STATUS
+VisitAllPciInstancesOfProtocol (
+ IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
+ );
+
+
+//
+// BDS Platform Functions
+//
+
+/**
+ Platform Bds init. Include the platform firmware vendor, revision
+ and so crc check.
+
+**/
+VOID
+EFIAPI
+PlatformBdsInit (
+ VOID
+ )
+{
+}
+
+
+EFI_STATUS
+PrepareLpcBridgeDevicePath (
+ IN EFI_HANDLE DeviceHandle
+ )
+/*++
+
+Routine Description:
+
+ Add IsaKeyboard to ConIn,
+ add IsaSerial to ConOut, ConIn, ErrOut.
+ LPC Bridge: 06 01 00
+
+Arguments:
+
+ DeviceHandle - Handle of PCIIO protocol.
+
+Returns:
+
+ EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.
+ EFI_STATUS - No LPC bridge is added.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+ CHAR16 *DevPathStr;
+
+ DevicePath = NULL;
+ Status = gBS->HandleProtocol (
+ DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID*)&DevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ TempDevicePath = DevicePath;
+
+ //
+ // Register COM1
+ //
+ DevicePath = AppendDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL *)NULL, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceVenderNode);
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
+
+ //
+ // Print Device Path
+ //
+ DevPathStr = DevicePathToStr(DevicePath);
+ DEBUG((
+ EFI_D_INFO,
+ "BdsPlatform.c+%d: COM%d DevPath: %s\n",
+ __LINE__,
+ gPnp16550ComPortDeviceNode.UID + 1,
+ DevPathStr
+ ));
+ FreePool(DevPathStr);
+
+ BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
+ BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
+ BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);
+
+ return EFI_SUCCESS;
+}
+
+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;
+
+ 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.
+ //
+#if 0
+ gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);
+#else
+ {
+ ACPI_ADR_DEVICE_PATH AcpiAdr;
+ EFI_DEVICE_PATH_PROTOCOL *MyDevicePath = NULL;
+
+ AcpiAdr.Header.Type = ACPI_DEVICE_PATH;
+ AcpiAdr.Header.SubType = ACPI_ADR_DP;
+ //AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 6, 0); //on bayleybay, CRT Device
+ AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_INTERNAL_DIGITAL, 8, 0); ; // on rambi, eDP C
+
+ SetDevicePathNodeLength (&AcpiAdr.Header, sizeof (ACPI_ADR_DEVICE_PATH));
+
+ MyDevicePath = AppendDevicePathNode(MyDevicePath, (EFI_DEVICE_PATH_PROTOCOL*)&AcpiAdr);
+
+ gBS->ConnectController (PciDeviceHandle, NULL, MyDevicePath, FALSE);
+
+ FreePool(MyDevicePath);
+ }
+#endif
+
+ 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;
+
+ //
+ // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
+ // Add the integrity GOP device path.
+ //
+ BdsLibUpdateConsoleVariable (VarConsoleOutDev, NULL, PciDevicePath);
+ BdsLibUpdateConsoleVariable (VarConsoleOutDev, TempDevicePath, NULL);
+ }
+ }
+ gBS->FreePool (GopHandleBuffer);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PreparePciVgaDevicePath (
+ IN EFI_HANDLE DeviceHandle
+ )
+/*++
+
+Routine Description:
+
+ Add PCI VGA to ConOut.
+ PCI VGA: 03 00 00
+
+Arguments:
+
+ DeviceHandle - Handle of PCIIO protocol.
+
+Returns:
+
+ EFI_SUCCESS - PCI VGA is added to ConOut.
+ EFI_STATUS - No PCI VGA device is added.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;
+
+ DevicePath = NULL;
+ Status = gBS->HandleProtocol (
+ DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID*)&DevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ GetGopDevicePath (DevicePath, &GopDevicePath);
+ DevicePath = GopDevicePath;
+
+ BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PreparePciSerialDevicePath (
+ IN EFI_HANDLE DeviceHandle
+ )
+/*++
+
+Routine Description:
+
+ Add PCI Serial to ConOut, ConIn, ErrOut.
+ PCI Serial: 07 00 02
+
+Arguments:
+
+ DeviceHandle - Handle of PCIIO protocol.
+
+Returns:
+
+ EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.
+ EFI_STATUS - No PCI Serial device is added.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ DevicePath = NULL;
+ Status = gBS->HandleProtocol (
+ DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID*)&DevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
+ DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
+
+ BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
+ BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
+ BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+VisitAllInstancesOfProtocol (
+ IN EFI_GUID *Id,
+ IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+ VOID *Instance;
+
+ //
+ // Start to check all the PciIo to find all possible device
+ //
+ HandleCount = 0;
+ HandleBuffer = NULL;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ Id,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ Status = (*CallBackFunction) (
+ HandleBuffer[Index],
+ Instance,
+ Context
+ );
+ }
+
+ gBS->FreePool (HandleBuffer);
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+VisitingAPciInstance (
+ IN EFI_HANDLE Handle,
+ IN VOID *Instance,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+
+ PciIo = (EFI_PCI_IO_PROTOCOL*) Instance;
+
+ //
+ // Check for all PCI device
+ //
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (Pci) / sizeof (UINT32),
+ &Pci
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) (
+ Handle,
+ PciIo,
+ &Pci
+ );
+
+}
+
+
+
+EFI_STATUS
+VisitAllPciInstances (
+ IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
+ )
+{
+ return VisitAllInstancesOfProtocol (
+ &gEfiPciIoProtocolGuid,
+ VisitingAPciInstance,
+ (VOID*)(UINTN) CallBackFunction
+ );
+}
+
+
+/**
+ Do platform specific PCI Device check and add them to
+ ConOut, ConIn, ErrOut.
+
+ @param[in] Handle - Handle of PCI device instance
+ @param[in] PciIo - PCI IO protocol instance
+ @param[in] Pci - PCI Header register block
+
+ @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
+ @retval EFI_STATUS - PCI Device check or Console variable update fail.
+
+**/
+EFI_STATUS
+EFIAPI
+DetectAndPreparePlatformPciDevicePath (
+ IN EFI_HANDLE Handle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN PCI_TYPE00 *Pci
+ )
+{
+ EFI_STATUS Status;
+
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ EFI_PCI_DEVICE_ENABLE,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (!mDetectVgaOnly) {
+ //
+ // Here we decide whether it is LPC Bridge
+ //
+ if ((IS_PCI_LPC (Pci)) ||
+ ((IS_PCI_ISA_PDECODE (Pci)) &&
+ (Pci->Hdr.VendorId == 0x8086)
+ )
+ ) {
+ //
+ // Add IsaKeyboard to ConIn,
+ // add IsaSerial to ConOut, ConIn, ErrOut
+ //
+ DEBUG ((EFI_D_INFO, "Found LPC Bridge device\n"));
+ PrepareLpcBridgeDevicePath (Handle);
+ return EFI_SUCCESS;
+ }
+ //
+ // Here we decide which Serial device to enable in PCI bus
+ //
+ if (IS_PCI_16550SERIAL (Pci)) {
+ //
+ // Add them to ConOut, ConIn, ErrOut.
+ //
+ DEBUG ((EFI_D_INFO, "Found PCI 16550 SERIAL device\n"));
+ PreparePciSerialDevicePath (Handle);
+ return EFI_SUCCESS;
+ }
+ }
+
+ //
+ // Here we decide which VGA device to enable in PCI bus
+ //
+ if (IS_PCI_VGA (Pci)) {
+ //
+ // Add them to ConOut.
+ //
+ DEBUG ((EFI_D_INFO, "Found PCI VGA device\n"));
+ PreparePciVgaDevicePath (Handle);
+ return EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+
+/**
+ Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
+
+ @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE.
+
+ @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
+ @retval EFI_STATUS - PCI Device check or Console variable update fail.
+
+**/
+EFI_STATUS
+DetectAndPreparePlatformPciDevicePaths (
+ BOOLEAN DetectVgaOnly
+ )
+{
+ mDetectVgaOnly = DetectVgaOnly;
+ return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);
+}
+
+/**
+ 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.
+ @return 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;
+
+ //
+ // Connect RootBridge
+ //
+ VarConout = BdsLibGetVariableAndSize (
+ VarConsoleOut,
+ &gEfiGlobalVariableGuid,
+ &DevicePathSize
+ );
+ VarConin = BdsLibGetVariableAndSize (
+ VarConsoleInp,
+ &gEfiGlobalVariableGuid,
+ &DevicePathSize
+ );
+
+ if (VarConout == NULL || VarConin == NULL) {
+ //
+ // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
+ //
+ DetectAndPreparePlatformPciDevicePaths (FALSE);
+
+ //
+ // Have chance to connect the platform default console,
+ // the platform default console is the minimue device group
+ // the platform should support
+ //
+ for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {
+ //
+ // Update the console variable with the connect type
+ //
+ if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
+ BdsLibUpdateConsoleVariable (VarConsoleInp, PlatformConsole[Index].DevicePath, NULL);
+ }
+ if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
+ BdsLibUpdateConsoleVariable (VarConsoleOut, PlatformConsole[Index].DevicePath, NULL);
+ }
+ if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
+ BdsLibUpdateConsoleVariable (VarErrorOut, PlatformConsole[Index].DevicePath, NULL);
+ }
+ }
+ } else {
+ //
+ // Only detect VGA device and add them to ConOut
+ //
+ DetectAndPreparePlatformPciDevicePaths (TRUE);
+ }
+
+ //
+ // Connect the all the default console with current cosole 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.
+**/
+VOID
+PlatformBdsConnectSequence (
+ VOID
+ )
+{
+ UINTN Index;
+
+ DEBUG ((EFI_D_INFO, "PlatformBdsConnectSequence\n"));
+ 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++;
+ }
+}
+
+/**
+ 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.
+
+**/
+VOID
+PlatformBdsGetDriverOption (
+ IN OUT LIST_ENTRY *BdsDriverLists
+ )
+{
+ UINTN Index;
+
+ Index = 0;
+
+ DEBUG ((EFI_D_INFO, "PlatformBdsGetDriverOption\n"));
+
+
+ //
+ // 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 ++;
+ }
+}
+
+/**
+ Perform the platform diagnostic, such like test memory. OEM/IBV also
+ can customize this function 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()
+
+**/
+VOID
+PlatformBdsDiagnostics (
+ IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel,
+ IN BOOLEAN QuietBoot,
+ IN BASEM_MEMORY_TEST BaseMemoryTest
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG ((EFI_D_INFO, "PlatformBdsDiagnostics\n"));
+ //
+ // 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 connect root bridge
+
+ @return EFI_SUCCESS Connect RootBridge successfully.
+
+**/
+EFI_STATUS
+ConnectRootBridge (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE RootHandle;
+
+ //
+ // 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;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ 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()
+
+**/
+VOID
+EFIAPI
+PlatformBdsPolicyBehavior (
+ IN LIST_ENTRY *DriverOptionList,
+ IN LIST_ENTRY *BootOptionList,
+ IN PROCESS_CAPSULES ProcessCapsules,
+ IN BASEM_MEMORY_TEST BaseMemoryTest
+ )
+{
+ EFI_STATUS Status;
+ UINT16 Timeout;
+ EFI_EVENT UserInputDurationTime;
+ LIST_ENTRY *Link;
+ BDS_COMMON_OPTION *BootOption;
+ UINTN Index;
+ EFI_INPUT_KEY Key;
+ EFI_TPL OldTpl;
+ EFI_BOOT_MODE BootMode;
+
+ DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior\n"));
+
+ ConnectRootBridge ();
+
+ //
+ // Init the time out value
+ //
+ Timeout = PcdGet16 (PcdPlatformBootTimeOut);
+
+ //
+ // Load the driver option as the driver option list
+ //
+ PlatformBdsGetDriverOption (DriverOptionList);
+
+ //
+ // Get current Boot Mode
+ //
+ Status = BdsLibGetBootMode (&BootMode);
+ DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode));
+
+ //
+ // Go the different platform policy with different boot mode
+ // Notes: this part code can be change with the table policy
+ //
+ ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);
+ //
+ // Connect platform console
+ //
+ Status = PlatformBdsConnectConsole (gPlatformConsole);
+ if (EFI_ERROR (Status)) {
+ //
+ // Here OEM/IBV can customize with defined action
+ //
+ PlatformBdsNoConsoleAction ();
+ }
+ //
+ // Create a 300ms duration event to ensure user has enough input time to enter Setup
+ //
+ Status = gBS->CreateEvent (
+ EVT_TIMER,
+ 0,
+ NULL,
+ NULL,
+ &UserInputDurationTime
+ );
+ ASSERT (Status == EFI_SUCCESS);
+ Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 3000000);
+ ASSERT (Status == EFI_SUCCESS);
+ //
+ // Memory test and Logo show
+ //
+ PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest);
+
+ //
+ // Perform some platform specific connect sequence
+ //
+ PlatformBdsConnectSequence ();
+
+ //
+ // In BOOT_WITH_FULL_CONFIGURATION boot mode, should always connect every device
+ // and do enumerate all the default boot options. But in development system board, the boot mode
+ // cannot be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES because the machine box
+ // is always open. So the following code only do the ConnectAll and EnumerateAll at first boot.
+ //
+ Status = BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");
+ if (EFI_ERROR(Status)) {
+ //
+ // If cannot find "BootOrder" variable, it may be first boot.
+ // Try to connect all devices and enumerate all boot options here.
+ //
+ BdsLibConnectAll ();
+ BdsLibEnumerateAllBootOption (BootOptionList);
+ }
+
+ //
+ // To give the User a chance to enter Setup here, if user set TimeOut is 0.
+ // BDS should still give user a chance to enter Setup
+ //
+ // Connect first boot option, and then check user input before exit
+ //
+ for (Link = BootOptionList->ForwardLink; Link != BootOptionList;Link = Link->ForwardLink) {
+ BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
+ if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {
+ //
+ // skip the header of the link list, becuase it has no boot option
+ //
+ continue;
+ } else {
+ //
+ // Make sure the boot option device path connected, but ignore the BBS device path
+ //
+ if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {
+ BdsLibConnectDevicePath (BootOption->DevicePath);
+ }
+ break;
+ }
+ }
+
+ //
+ // Check whether the user input after the duration time has expired
+ //
+ OldTpl = EfiGetCurrentTpl();
+ gBS->RestoreTPL (TPL_APPLICATION);
+ gBS->WaitForEvent (1, &UserInputDurationTime, &Index);
+ gBS->CloseEvent (UserInputDurationTime);
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ gBS->RaiseTPL (OldTpl);
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Enter Setup if user input
+ //
+ Timeout = 0xffff;
+ PlatformBdsEnterFrontPage (Timeout, FALSE);
+ }
+}
+
+/**
+ 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 also a platform implementation and can be customized by IBV/OEM.
+
+ @param Option Pointer to Boot Option that succeeded to boot.
+
+**/
+VOID
+EFIAPI
+PlatformBdsBootSuccess (
+ IN BDS_COMMON_OPTION *Option
+ )
+{
+ CHAR16 *TmpStr;
+ DEBUG ((EFI_D_INFO, "PlatformBdsBootSuccess\n"));
+
+ //
+ // 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.
+
+**/
+VOID
+EFIAPI
+PlatformBdsBootFail (
+ IN BDS_COMMON_OPTION *Option,
+ IN EFI_STATUS Status,
+ IN CHAR16 *ExitData,
+ IN UINTN ExitDataSize
+ )
+{
+ CHAR16 *TmpStr;
+ DEBUG ((EFI_D_INFO, "PlatformBdsBootFail\n"));
+
+ //
+ // 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);
+ }
+}
+
+/**
+ This function is remained for IBV/OEM to do some platform action,
+ if there no console device can be connected.
+
+ @return EFI_SUCCESS Direct return success now.
+
+**/
+EFI_STATUS
+PlatformBdsNoConsoleAction (
+ VOID
+ )
+{
+ DEBUG ((EFI_D_INFO, "PlatformBdsNoConsoleAction\n"));
+ return EFI_SUCCESS;
+}
+
+/**
+ This function locks platform flash that is not allowed to be updated during normal boot path.
+ The flash layout is platform specific.
+**/
+VOID
+EFIAPI
+PlatformBdsLockNonUpdatableFlash (
+ VOID
+ )
+{
+ DEBUG ((EFI_D_INFO, "PlatformBdsLockNonUpdatableFlash\n"));
+ return ;
+}
+
+
+/**
+ 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;
+}
|