mirror of https://github.com/acidanthera/audk.git
1017 lines
27 KiB
C
1017 lines
27 KiB
C
/** @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;
|
|
}
|