|
@@ -0,0 +1,1400 @@
|
|
|
+/** @file
|
|
|
+ This library registers Bds callbacks. It is a default library
|
|
|
+ implementation instance of the BDS hook library
|
|
|
+
|
|
|
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
|
|
|
+ Copyright (c) 2021, American Megatrends International LLC.<BR>
|
|
|
+ SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
+
|
|
|
+**/
|
|
|
+
|
|
|
+#include <Guid/EventGroup.h>
|
|
|
+
|
|
|
+#include <Library/IoLib.h>
|
|
|
+#include <Library/PciLib.h>
|
|
|
+#include <Library/UefiBootManagerLib.h>
|
|
|
+#include <Library/Tcg2PhysicalPresenceLib.h>
|
|
|
+
|
|
|
+#include <Protocol/BlockIo.h>
|
|
|
+#include <Protocol/UsbIo.h>
|
|
|
+#include <Protocol/PciEnumerationComplete.h>
|
|
|
+
|
|
|
+#include "BoardBdsHook.h"
|
|
|
+
|
|
|
+#define IS_FIRST_BOOT_VAR_NAME L"IsFirstBoot"
|
|
|
+
|
|
|
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_BOOT_MODE gBootMode;
|
|
|
+BOOLEAN gPPRequireUIConfirm;
|
|
|
+extern UINTN mBootMenuOptionNumber;
|
|
|
+
|
|
|
+
|
|
|
+GLOBAL_REMOVE_IF_UNREFERENCED USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath = {
|
|
|
+ {
|
|
|
+ {
|
|
|
+ MESSAGING_DEVICE_PATH,
|
|
|
+ MSG_USB_CLASS_DP,
|
|
|
+ {
|
|
|
+ (UINT8) (sizeof (USB_CLASS_DEVICE_PATH)),
|
|
|
+ (UINT8) ((sizeof (USB_CLASS_DEVICE_PATH)) >> 8)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ 0xffff, // VendorId
|
|
|
+ 0xffff, // ProductId
|
|
|
+ CLASS_HID, // DeviceClass
|
|
|
+ SUBCLASS_BOOT, // DeviceSubClass
|
|
|
+ PROTOCOL_KEYBOARD // DeviceProtocol
|
|
|
+ },
|
|
|
+ gEndEntire
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+// BDS Platform Functions
|
|
|
+//
|
|
|
+BOOLEAN
|
|
|
+IsMorBitSet (
|
|
|
+ VOID
|
|
|
+ )
|
|
|
+{
|
|
|
+ UINTN MorControl;
|
|
|
+ EFI_STATUS Status;
|
|
|
+ UINTN DataSize;
|
|
|
+
|
|
|
+ //
|
|
|
+ // Check if the MOR bit is set.
|
|
|
+ //
|
|
|
+ DataSize = sizeof (MorControl);
|
|
|
+ Status = gRT->GetVariable (
|
|
|
+ MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
|
|
|
+ &gEfiMemoryOverwriteControlDataGuid,
|
|
|
+ NULL,
|
|
|
+ &DataSize,
|
|
|
+ &MorControl
|
|
|
+ );
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ DEBUG ((DEBUG_INFO, " gEfiMemoryOverwriteControlDataGuid doesn't exist!!***\n"));
|
|
|
+ MorControl = 0;
|
|
|
+ } else {
|
|
|
+ DEBUG ((DEBUG_INFO, " Get the gEfiMemoryOverwriteControlDataGuid = %x!!***\n", MorControl));
|
|
|
+ }
|
|
|
+
|
|
|
+ return (BOOLEAN) (MorControl & 0x01);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ Prints device paths.
|
|
|
+ @param Name The device name.
|
|
|
+ @param DevicePath The device path to be printed
|
|
|
+**/
|
|
|
+VOID
|
|
|
+EFIAPI
|
|
|
+DumpDevicePath (
|
|
|
+ IN CHAR16 *Name,
|
|
|
+ IN EFI_DEVICE_PATH *DevicePath
|
|
|
+ )
|
|
|
+{
|
|
|
+ CHAR16 *Str;
|
|
|
+ Str = ConvertDevicePathToText (DevicePath, TRUE, TRUE);
|
|
|
+ DEBUG ((DEBUG_INFO, "%s: %s\n", Name, Str));
|
|
|
+ if (Str != NULL) {
|
|
|
+ FreePool (Str);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ Return whether the device is trusted console.
|
|
|
+
|
|
|
+ @param Device The device to be tested.
|
|
|
+
|
|
|
+ @retval TRUE The device can be trusted.
|
|
|
+ @retval FALSE The device cannot be trusted.
|
|
|
+**/
|
|
|
+BOOLEAN
|
|
|
+IsTrustedConsole (
|
|
|
+ IN CONSOLE_TYPE ConsoleType,
|
|
|
+ IN EFI_DEVICE_PATH_PROTOCOL *Device
|
|
|
+ )
|
|
|
+{
|
|
|
+ VOID *TrustedConsoleDevicepath;
|
|
|
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
|
|
|
+ EFI_DEVICE_PATH_PROTOCOL *Instance;
|
|
|
+ UINTN Size;
|
|
|
+ EFI_DEVICE_PATH_PROTOCOL *ConsoleDevice;
|
|
|
+
|
|
|
+ if (Device == NULL) {
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ ConsoleDevice = DuplicateDevicePath (Device);
|
|
|
+
|
|
|
+ TrustedConsoleDevicepath = NULL;
|
|
|
+
|
|
|
+ switch (ConsoleType) {
|
|
|
+ case ConIn:
|
|
|
+ TrustedConsoleDevicepath = PcdGetPtr (PcdTrustedConsoleInputDevicePath);
|
|
|
+ break;
|
|
|
+ case ConOut:
|
|
|
+ //
|
|
|
+ // Check GOP and remove last node
|
|
|
+ //
|
|
|
+ TempDevicePath = ConsoleDevice;
|
|
|
+ while (!IsDevicePathEndType (TempDevicePath)) {
|
|
|
+ if (DevicePathType (TempDevicePath) == ACPI_DEVICE_PATH &&
|
|
|
+ DevicePathSubType (TempDevicePath) == ACPI_ADR_DP) {
|
|
|
+ SetDevicePathEndNode (TempDevicePath);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ TempDevicePath = NextDevicePathNode (TempDevicePath);
|
|
|
+ }
|
|
|
+
|
|
|
+ TrustedConsoleDevicepath = PcdGetPtr (PcdTrustedConsoleOutputDevicePath);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ ASSERT (FALSE);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ TempDevicePath = TrustedConsoleDevicepath;
|
|
|
+ do {
|
|
|
+ Instance = GetNextDevicePathInstance (&TempDevicePath, &Size);
|
|
|
+ if (Instance == NULL) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (CompareMem (ConsoleDevice, Instance, Size - END_DEVICE_PATH_LENGTH) == 0) {
|
|
|
+ FreePool (Instance);
|
|
|
+ FreePool (ConsoleDevice);
|
|
|
+ return TRUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ FreePool (Instance);
|
|
|
+ } while (TempDevicePath != NULL);
|
|
|
+
|
|
|
+ FreePool (ConsoleDevice);
|
|
|
+
|
|
|
+ return FALSE;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ Return whether the USB device path is in a short form.
|
|
|
+
|
|
|
+ @param DevicePath The device path to be tested.
|
|
|
+
|
|
|
+ @retval TRUE The device path is in short form.
|
|
|
+ @retval FALSE The device path is not in short form.
|
|
|
+**/
|
|
|
+BOOLEAN
|
|
|
+IsUsbShortForm (
|
|
|
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
|
|
|
+ )
|
|
|
+{
|
|
|
+ if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) &&
|
|
|
+ ((DevicePathSubType (DevicePath) == MSG_USB_CLASS_DP) ||
|
|
|
+ (DevicePathSubType (DevicePath) == MSG_USB_WWID_DP)) ) {
|
|
|
+ return TRUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ return FALSE;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ Connect the USB short form device path.
|
|
|
+
|
|
|
+ @param DevicePath USB short form device path
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS Successfully connected the USB device
|
|
|
+ @retval EFI_NOT_FOUND Cannot connect the USB device
|
|
|
+ @retval EFI_INVALID_PARAMETER The device path is invalid.
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+ConnectUsbShortFormDevicePath (
|
|
|
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_STATUS Status;
|
|
|
+ EFI_HANDLE *Handles;
|
|
|
+ UINTN HandleCount;
|
|
|
+ UINTN Index;
|
|
|
+ EFI_PCI_IO_PROTOCOL *PciIo;
|
|
|
+ UINT8 Class[3];
|
|
|
+ BOOLEAN AtLeastOneConnected;
|
|
|
+
|
|
|
+ //
|
|
|
+ // Check the passed in parameters
|
|
|
+ //
|
|
|
+ if (DevicePath == NULL) {
|
|
|
+ return EFI_INVALID_PARAMETER;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!IsUsbShortForm (DevicePath)) {
|
|
|
+ return EFI_INVALID_PARAMETER;
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // Find the usb host controller firstly, then connect with the remaining device path
|
|
|
+ //
|
|
|
+ AtLeastOneConnected = FALSE;
|
|
|
+ Status = gBS->LocateHandleBuffer (
|
|
|
+ ByProtocol,
|
|
|
+ &gEfiPciIoProtocolGuid,
|
|
|
+ NULL,
|
|
|
+ &HandleCount,
|
|
|
+ &Handles
|
|
|
+ );
|
|
|
+ for (Index = 0; Index < HandleCount; Index++) {
|
|
|
+ Status = gBS->HandleProtocol (
|
|
|
+ Handles[Index],
|
|
|
+ &gEfiPciIoProtocolGuid,
|
|
|
+ (VOID **) &PciIo
|
|
|
+ );
|
|
|
+ if (!EFI_ERROR (Status)) {
|
|
|
+ //
|
|
|
+ // Check whether the Pci device is the wanted usb host controller
|
|
|
+ //
|
|
|
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class);
|
|
|
+ if (!EFI_ERROR (Status) &&
|
|
|
+ ((PCI_CLASS_SERIAL == Class[2]) && (PCI_CLASS_SERIAL_USB == Class[1]))) {
|
|
|
+ Status = gBS->ConnectController (
|
|
|
+ Handles[Index],
|
|
|
+ NULL,
|
|
|
+ DevicePath,
|
|
|
+ FALSE
|
|
|
+ );
|
|
|
+ if (!EFI_ERROR(Status)) {
|
|
|
+ AtLeastOneConnected = TRUE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return AtLeastOneConnected ? EFI_SUCCESS : EFI_NOT_FOUND;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ Return whether the Handle is a vga handle.
|
|
|
+
|
|
|
+ @param Handle The handle to be tested.
|
|
|
+
|
|
|
+ @retval TRUE The handle is a vga handle.
|
|
|
+ @retval FALSE The handle is not a vga handle..
|
|
|
+**/
|
|
|
+BOOLEAN
|
|
|
+IsVgaHandle (
|
|
|
+ IN EFI_HANDLE Handle
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_PCI_IO_PROTOCOL *PciIo;
|
|
|
+ PCI_TYPE00 Pci;
|
|
|
+ EFI_STATUS Status;
|
|
|
+
|
|
|
+ Status = gBS->HandleProtocol (
|
|
|
+ Handle,
|
|
|
+ &gEfiPciIoProtocolGuid,
|
|
|
+ (VOID **)&PciIo
|
|
|
+ );
|
|
|
+ if (!EFI_ERROR (Status)) {
|
|
|
+ Status = PciIo->Pci.Read (
|
|
|
+ PciIo,
|
|
|
+ EfiPciIoWidthUint32,
|
|
|
+ 0,
|
|
|
+ sizeof (Pci) / sizeof (UINT32),
|
|
|
+ &Pci
|
|
|
+ );
|
|
|
+ if (!EFI_ERROR (Status)) {
|
|
|
+ if (IS_PCI_VGA (&Pci) || IS_PCI_OLD_VGA (&Pci)) {
|
|
|
+ return TRUE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return FALSE;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ Return whether the device path points to a video controller.
|
|
|
+
|
|
|
+ @param DevicePath The device path to be tested.
|
|
|
+
|
|
|
+ @retval TRUE The device path points to a video controller.
|
|
|
+ @retval FALSE The device path does not point to a video controller.
|
|
|
+**/
|
|
|
+EFI_HANDLE
|
|
|
+IsVideoController (
|
|
|
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_DEVICE_PATH_PROTOCOL *DupDevicePath;
|
|
|
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
|
|
|
+ EFI_STATUS Status;
|
|
|
+ EFI_HANDLE DeviceHandle;
|
|
|
+
|
|
|
+ DupDevicePath = DuplicateDevicePath (DevicePath);
|
|
|
+ ASSERT (DupDevicePath != NULL);
|
|
|
+ if (DupDevicePath == NULL) {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ TempDevicePath = DupDevicePath;
|
|
|
+ Status = gBS->LocateDevicePath (
|
|
|
+ &gEfiDevicePathProtocolGuid,
|
|
|
+ &TempDevicePath,
|
|
|
+ &DeviceHandle
|
|
|
+ );
|
|
|
+ FreePool (DupDevicePath);
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (IsVgaHandle (DeviceHandle)) {
|
|
|
+ return DeviceHandle;
|
|
|
+ } else {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ Return whether the device path is a GOP device path.
|
|
|
+
|
|
|
+ @param DevicePath The device path to be tested.
|
|
|
+
|
|
|
+ @retval TRUE The device path is a GOP device path.
|
|
|
+ @retval FALSE The device on the device path is not a GOP device path.
|
|
|
+**/
|
|
|
+BOOLEAN
|
|
|
+IsGopDevicePath (
|
|
|
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
|
|
|
+ )
|
|
|
+{
|
|
|
+ while (!IsDevicePathEndType (DevicePath)) {
|
|
|
+ if (DevicePathType (DevicePath) == ACPI_DEVICE_PATH &&
|
|
|
+ DevicePathSubType (DevicePath) == ACPI_ADR_DP) {
|
|
|
+ return TRUE;
|
|
|
+ }
|
|
|
+ DevicePath = NextDevicePathNode (DevicePath);
|
|
|
+ }
|
|
|
+ return FALSE;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ Remove all GOP device path instance from DevicePath and add the Gop to the DevicePath.
|
|
|
+
|
|
|
+ @param DevicePath The device path to be removed
|
|
|
+ @param Gop The device path to be added.
|
|
|
+
|
|
|
+ @retval Return The updated device path.
|
|
|
+**/
|
|
|
+EFI_DEVICE_PATH_PROTOCOL *
|
|
|
+UpdateGopDevicePath (
|
|
|
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath,
|
|
|
+ EFI_DEVICE_PATH_PROTOCOL *Gop
|
|
|
+ )
|
|
|
+{
|
|
|
+ UINTN Size;
|
|
|
+ UINTN GopSize;
|
|
|
+ EFI_DEVICE_PATH_PROTOCOL *Temp;
|
|
|
+ EFI_DEVICE_PATH_PROTOCOL *Return;
|
|
|
+ EFI_DEVICE_PATH_PROTOCOL *Instance;
|
|
|
+ BOOLEAN Exist;
|
|
|
+
|
|
|
+ Exist = FALSE;
|
|
|
+ Return = NULL;
|
|
|
+ GopSize = GetDevicePathSize (Gop);
|
|
|
+ do {
|
|
|
+ Instance = GetNextDevicePathInstance (&DevicePath, &Size);
|
|
|
+ if (Instance == NULL) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (!IsGopDevicePath (Instance) ||
|
|
|
+ (Size == GopSize && CompareMem (Instance, Gop, GopSize) == 0)
|
|
|
+ ) {
|
|
|
+ if (Size == GopSize && CompareMem (Instance, Gop, GopSize) == 0) {
|
|
|
+ Exist = TRUE;
|
|
|
+ }
|
|
|
+ Temp = Return;
|
|
|
+ Return = AppendDevicePathInstance (Return, Instance);
|
|
|
+ if (Temp != NULL) {
|
|
|
+ FreePool (Temp);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ FreePool (Instance);
|
|
|
+ } while (DevicePath != NULL);
|
|
|
+
|
|
|
+ if (!Exist) {
|
|
|
+ Temp = Return;
|
|
|
+ Return = AppendDevicePathInstance (Return, Gop);
|
|
|
+ if (Temp != NULL) {
|
|
|
+ FreePool (Temp);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return Return;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ Get Graphics Controller Handle.
|
|
|
+
|
|
|
+ @param NeedTrustedConsole The flag to determine if trusted console
|
|
|
+ or non trusted console should be returned
|
|
|
+
|
|
|
+ @retval NULL Console not found
|
|
|
+ @retval PciHandles Successfully located
|
|
|
+**/
|
|
|
+EFI_HANDLE
|
|
|
+EFIAPI
|
|
|
+GetGraphicsController (
|
|
|
+ IN BOOLEAN NeedTrustedConsole
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_STATUS Status;
|
|
|
+ UINTN Index;
|
|
|
+ EFI_HANDLE *PciHandles;
|
|
|
+ UINTN PciHandlesSize;
|
|
|
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
|
+
|
|
|
+ Status = gBS->LocateHandleBuffer (
|
|
|
+ ByProtocol,
|
|
|
+ &gEfiPciIoProtocolGuid,
|
|
|
+ NULL,
|
|
|
+ &PciHandlesSize,
|
|
|
+ &PciHandles
|
|
|
+ );
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (Index = 0; Index < PciHandlesSize; Index++) {
|
|
|
+ Status = gBS->HandleProtocol (
|
|
|
+ PciHandles[Index],
|
|
|
+ &gEfiDevicePathProtocolGuid,
|
|
|
+ (VOID **) &DevicePath
|
|
|
+ );
|
|
|
+ if (EFI_ERROR(Status)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (!IsVgaHandle (PciHandles[Index])) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if ((NeedTrustedConsole && IsTrustedConsole (ConOut, DevicePath)) ||
|
|
|
+ ((!NeedTrustedConsole) && (!IsTrustedConsole (ConOut, DevicePath)))) {
|
|
|
+ return PciHandles[Index];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ Updates Graphic ConOut variable.
|
|
|
+
|
|
|
+ @param NeedTrustedConsole The flag that determines if trusted console
|
|
|
+ or non trusted console should be returned
|
|
|
+**/
|
|
|
+VOID
|
|
|
+UpdateGraphicConOut (
|
|
|
+ IN BOOLEAN NeedTrustedConsole
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_HANDLE GraphicsControllerHandle;
|
|
|
+ EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;
|
|
|
+ EFI_DEVICE_PATH_PROTOCOL *ConOutDevicePath;
|
|
|
+ EFI_DEVICE_PATH_PROTOCOL *UpdatedConOutDevicePath;
|
|
|
+
|
|
|
+ //
|
|
|
+ // Update ConOut variable
|
|
|
+ //
|
|
|
+ GraphicsControllerHandle = GetGraphicsController (NeedTrustedConsole);
|
|
|
+ if (GraphicsControllerHandle != NULL) {
|
|
|
+ //
|
|
|
+ // Connect the GOP driver
|
|
|
+ //
|
|
|
+ gBS->ConnectController (GraphicsControllerHandle, NULL, NULL, TRUE);
|
|
|
+
|
|
|
+ //
|
|
|
+ // Get the GOP device path
|
|
|
+ // NOTE: We may get a device path that contains Controller node in it.
|
|
|
+ //
|
|
|
+ GopDevicePath = EfiBootManagerGetGopDevicePath (GraphicsControllerHandle);
|
|
|
+ if (GopDevicePath != NULL) {
|
|
|
+ GetEfiGlobalVariable2 (L"ConOut", (VOID **)&ConOutDevicePath, NULL);
|
|
|
+ UpdatedConOutDevicePath = UpdateGopDevicePath (ConOutDevicePath, GopDevicePath);
|
|
|
+ if (ConOutDevicePath != NULL) {
|
|
|
+ FreePool (ConOutDevicePath);
|
|
|
+ }
|
|
|
+ FreePool (GopDevicePath);
|
|
|
+ gRT->SetVariable (
|
|
|
+ L"ConOut",
|
|
|
+ &gEfiGlobalVariableGuid,
|
|
|
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
|
|
|
+ GetDevicePathSize (UpdatedConOutDevicePath),
|
|
|
+ UpdatedConOutDevicePath
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ The function connects the trusted consoles.
|
|
|
+**/
|
|
|
+VOID
|
|
|
+ConnectTrustedConsole (
|
|
|
+ VOID
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_DEVICE_PATH_PROTOCOL *Consoles;
|
|
|
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
|
|
|
+ EFI_DEVICE_PATH_PROTOCOL *Instance;
|
|
|
+ EFI_DEVICE_PATH_PROTOCOL *Next;
|
|
|
+ UINTN Size;
|
|
|
+ UINTN Index;
|
|
|
+ EFI_HANDLE Handle;
|
|
|
+ EFI_STATUS Status;
|
|
|
+ CHAR16 *ConsoleVar[] = {L"ConIn", L"ConOut"};
|
|
|
+ VOID *TrustedConsoleDevicepath;
|
|
|
+
|
|
|
+ TrustedConsoleDevicepath = PcdGetPtr (PcdTrustedConsoleInputDevicePath);
|
|
|
+ DumpDevicePath (L"TrustedConsoleIn", TrustedConsoleDevicepath);
|
|
|
+ TrustedConsoleDevicepath = PcdGetPtr (PcdTrustedConsoleOutputDevicePath);
|
|
|
+ DumpDevicePath (L"TrustedConsoleOut", TrustedConsoleDevicepath);
|
|
|
+
|
|
|
+ for (Index = 0; Index < sizeof (ConsoleVar) / sizeof (ConsoleVar[0]); Index++) {
|
|
|
+
|
|
|
+ GetEfiGlobalVariable2 (ConsoleVar[Index], (VOID **)&Consoles, NULL);
|
|
|
+
|
|
|
+ TempDevicePath = Consoles;
|
|
|
+ do {
|
|
|
+ Instance = GetNextDevicePathInstance (&TempDevicePath, &Size);
|
|
|
+ if (Instance == NULL) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (IsTrustedConsole (Index, Instance)) {
|
|
|
+ if (IsUsbShortForm (Instance)) {
|
|
|
+ ConnectUsbShortFormDevicePath (Instance);
|
|
|
+ } else {
|
|
|
+ for (Next = Instance; !IsDevicePathEnd (Next); Next = NextDevicePathNode (Next)) {
|
|
|
+ if (DevicePathType (Next) == ACPI_DEVICE_PATH && DevicePathSubType (Next) == ACPI_ADR_DP) {
|
|
|
+ break;
|
|
|
+ } else if (DevicePathType (Next) == HARDWARE_DEVICE_PATH &&
|
|
|
+ DevicePathSubType (Next) == HW_CONTROLLER_DP &&
|
|
|
+ DevicePathType (NextDevicePathNode (Next)) == ACPI_DEVICE_PATH &&
|
|
|
+ DevicePathSubType (NextDevicePathNode (Next)) == ACPI_ADR_DP
|
|
|
+ ) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!IsDevicePathEnd (Next)) {
|
|
|
+ SetDevicePathEndNode (Next);
|
|
|
+ Status = EfiBootManagerConnectDevicePath (Instance, &Handle);
|
|
|
+ if (!EFI_ERROR (Status)) {
|
|
|
+ gBS->ConnectController (Handle, NULL, NULL, TRUE);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ EfiBootManagerConnectDevicePath (Instance, NULL);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ FreePool (Instance);
|
|
|
+ } while (TempDevicePath != NULL);
|
|
|
+
|
|
|
+ if (Consoles != NULL) {
|
|
|
+ FreePool (Consoles);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ The function connects the trusted Storages.
|
|
|
+**/
|
|
|
+VOID
|
|
|
+ConnectTrustedStorage (
|
|
|
+ VOID
|
|
|
+ )
|
|
|
+{
|
|
|
+ VOID *TrustedStorageDevicepath;
|
|
|
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
|
|
|
+ EFI_DEVICE_PATH_PROTOCOL *Instance;
|
|
|
+ UINTN Size;
|
|
|
+ EFI_DEVICE_PATH_PROTOCOL *TempStorageDevicePath;
|
|
|
+ EFI_STATUS Status;
|
|
|
+ EFI_HANDLE DeviceHandle;
|
|
|
+
|
|
|
+ TrustedStorageDevicepath = PcdGetPtr (PcdTrustedStorageDevicePath);
|
|
|
+ DumpDevicePath (L"TrustedStorage", TrustedStorageDevicepath);
|
|
|
+
|
|
|
+ TempDevicePath = TrustedStorageDevicepath;
|
|
|
+ do {
|
|
|
+ Instance = GetNextDevicePathInstance (&TempDevicePath, &Size);
|
|
|
+ if (Instance == NULL) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ EfiBootManagerConnectDevicePath (Instance, NULL);
|
|
|
+
|
|
|
+ TempStorageDevicePath = Instance;
|
|
|
+
|
|
|
+ Status = gBS->LocateDevicePath (
|
|
|
+ &gEfiDevicePathProtocolGuid,
|
|
|
+ &TempStorageDevicePath,
|
|
|
+ &DeviceHandle
|
|
|
+ );
|
|
|
+ if (!EFI_ERROR (Status)) {
|
|
|
+ gBS->ConnectController (DeviceHandle, NULL, NULL, FALSE);
|
|
|
+ }
|
|
|
+
|
|
|
+ FreePool (Instance);
|
|
|
+ } while (TempDevicePath != NULL);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ Check if current BootCurrent variable is internal shell boot option.
|
|
|
+
|
|
|
+ @retval TRUE BootCurrent is internal shell.
|
|
|
+ @retval FALSE BootCurrent is not internal shell.
|
|
|
+**/
|
|
|
+BOOLEAN
|
|
|
+BootCurrentIsInternalShell (
|
|
|
+ VOID
|
|
|
+ )
|
|
|
+{
|
|
|
+ UINTN VarSize;
|
|
|
+ UINT16 BootCurrent;
|
|
|
+ CHAR16 BootOptionName[16];
|
|
|
+ UINT8 *BootOption;
|
|
|
+ UINT8 *Ptr;
|
|
|
+ BOOLEAN Result;
|
|
|
+ EFI_STATUS Status;
|
|
|
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
|
|
|
+ EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode;
|
|
|
+ EFI_GUID *GuidPoint;
|
|
|
+
|
|
|
+ BootOption = NULL;
|
|
|
+ Result = FALSE;
|
|
|
+
|
|
|
+ //
|
|
|
+ // Get BootCurrent variable
|
|
|
+ //
|
|
|
+ VarSize = sizeof (UINT16);
|
|
|
+ Status = gRT->GetVariable (
|
|
|
+ L"BootCurrent",
|
|
|
+ &gEfiGlobalVariableGuid,
|
|
|
+ NULL,
|
|
|
+ &VarSize,
|
|
|
+ &BootCurrent
|
|
|
+ );
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // Create boot option Bootxxxx from BootCurrent
|
|
|
+ //
|
|
|
+ UnicodeSPrint (BootOptionName, sizeof(BootOptionName), L"Boot%04X", BootCurrent);
|
|
|
+
|
|
|
+ GetEfiGlobalVariable2 (BootOptionName, (VOID **) &BootOption, &VarSize);
|
|
|
+ if (BootOption == NULL || VarSize == 0) {
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ Ptr = BootOption;
|
|
|
+ Ptr += sizeof (UINT32);
|
|
|
+ Ptr += sizeof (UINT16);
|
|
|
+ Ptr += StrSize ((CHAR16 *) Ptr);
|
|
|
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
|
|
|
+ LastDeviceNode = TempDevicePath;
|
|
|
+ while (!IsDevicePathEnd (TempDevicePath)) {
|
|
|
+ LastDeviceNode = TempDevicePath;
|
|
|
+ TempDevicePath = NextDevicePathNode (TempDevicePath);
|
|
|
+ }
|
|
|
+ GuidPoint = EfiGetNameGuidFromFwVolDevicePathNode (
|
|
|
+ (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode
|
|
|
+ );
|
|
|
+ if ((GuidPoint != NULL) &&
|
|
|
+ ((CompareGuid (GuidPoint, &gUefiShellFileGuid)))) {
|
|
|
+ //
|
|
|
+ // if this option is internal shell, return TRUE
|
|
|
+ //
|
|
|
+ Result = TRUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (BootOption != NULL) {
|
|
|
+ FreePool (BootOption);
|
|
|
+ BootOption = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ return Result;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ This function will change video resolution and text mode
|
|
|
+ for internl shell when internal shell is launched.
|
|
|
+
|
|
|
+ @param None.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS Mode is changed successfully.
|
|
|
+ @retval Others Mode failed to changed.
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+ChangeModeForInternalShell (
|
|
|
+ VOID
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
|
|
|
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut;
|
|
|
+ UINTN SizeOfInfo;
|
|
|
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
|
|
|
+ UINT32 MaxGopMode;
|
|
|
+ UINT32 MaxTextMode;
|
|
|
+ UINT32 ModeNumber;
|
|
|
+ UINTN HandleCount;
|
|
|
+ EFI_HANDLE *HandleBuffer;
|
|
|
+ EFI_STATUS Status;
|
|
|
+ UINTN Index;
|
|
|
+ UINTN CurrentColumn;
|
|
|
+ UINTN CurrentRow;
|
|
|
+
|
|
|
+ //
|
|
|
+ // Internal shell mode
|
|
|
+ //
|
|
|
+ UINT32 mShellModeColumn;
|
|
|
+ UINT32 mShellModeRow;
|
|
|
+ UINT32 mShellHorizontalResolution;
|
|
|
+ UINT32 mShellVerticalResolution;
|
|
|
+
|
|
|
+
|
|
|
+ //
|
|
|
+ // Get user defined text mode for internal shell only once.
|
|
|
+ //
|
|
|
+ mShellHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution);
|
|
|
+ mShellVerticalResolution = PcdGet32 (PcdSetupVideoVerticalResolution);
|
|
|
+ mShellModeColumn = PcdGet32 (PcdSetupConOutColumn);
|
|
|
+ mShellModeRow = PcdGet32 (PcdSetupConOutRow);
|
|
|
+
|
|
|
+
|
|
|
+ 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) || (SimpleTextOut == NULL)) {
|
|
|
+ return EFI_UNSUPPORTED;
|
|
|
+ }
|
|
|
+
|
|
|
+ MaxGopMode = GraphicsOutput->Mode->MaxMode;
|
|
|
+ MaxTextMode = SimpleTextOut->Mode->MaxMode;
|
|
|
+
|
|
|
+ //
|
|
|
+ // 1. If current video resolution is same with new video resolution,
|
|
|
+ // video resolution need not be changed.
|
|
|
+ // 1.1. If current text mode is same with new text mode, text mode need not be change.
|
|
|
+ // 1.2. If current text mode is different with new text mode, text mode need be change to new text mode.
|
|
|
+ // 2. If current video resolution is different with new video resolution, we need restart whole console drivers.
|
|
|
+ //
|
|
|
+ for (ModeNumber = 0; ModeNumber < MaxGopMode; ModeNumber++) {
|
|
|
+ Status = GraphicsOutput->QueryMode (
|
|
|
+ GraphicsOutput,
|
|
|
+ ModeNumber,
|
|
|
+ &SizeOfInfo,
|
|
|
+ &Info
|
|
|
+ );
|
|
|
+ if (!EFI_ERROR (Status)) {
|
|
|
+ if ((Info->HorizontalResolution == mShellHorizontalResolution) &&
|
|
|
+ (Info->VerticalResolution == mShellVerticalResolution)) {
|
|
|
+ if ((GraphicsOutput->Mode->Info->HorizontalResolution == mShellHorizontalResolution) &&
|
|
|
+ (GraphicsOutput->Mode->Info->VerticalResolution == mShellVerticalResolution)) {
|
|
|
+ //
|
|
|
+ // If current video resolution is same with new resolution,
|
|
|
+ // then check if current text mode is same with new text mode.
|
|
|
+ //
|
|
|
+ Status = SimpleTextOut->QueryMode (SimpleTextOut, SimpleTextOut->Mode->Mode, &CurrentColumn, &CurrentRow);
|
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
|
+ if (CurrentColumn == mShellModeColumn && CurrentRow == mShellModeRow) {
|
|
|
+ //
|
|
|
+ // Current text mode is same with new text mode, text mode need not be change.
|
|
|
+ //
|
|
|
+ FreePool (Info);
|
|
|
+ return EFI_SUCCESS;
|
|
|
+ } else {
|
|
|
+ //
|
|
|
+ // Current text mode is different with new text mode, text mode need be change to new text mode.
|
|
|
+ //
|
|
|
+ for (Index = 0; Index < MaxTextMode; Index++) {
|
|
|
+ Status = SimpleTextOut->QueryMode (SimpleTextOut, Index, &CurrentColumn, &CurrentRow);
|
|
|
+ if (!EFI_ERROR(Status)) {
|
|
|
+ if ((CurrentColumn == mShellModeColumn) && (CurrentRow == mShellModeRow)) {
|
|
|
+ //
|
|
|
+ // New text mode is supported, set it.
|
|
|
+ //
|
|
|
+ Status = SimpleTextOut->SetMode (SimpleTextOut, Index);
|
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
|
+ //
|
|
|
+ // Update text mode PCD.
|
|
|
+ //
|
|
|
+ Status = PcdSet32S (PcdConOutColumn, mShellModeColumn);
|
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
|
+
|
|
|
+ Status = PcdSet32S (PcdConOutRow, mShellModeRow);
|
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
|
+
|
|
|
+ FreePool (Info);
|
|
|
+ return EFI_SUCCESS;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (Index == MaxTextMode) {
|
|
|
+ //
|
|
|
+ // If new text mode is not supported, return error.
|
|
|
+ //
|
|
|
+ FreePool (Info);
|
|
|
+ return EFI_UNSUPPORTED;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ FreePool (Info);
|
|
|
+ //
|
|
|
+ // If current video resolution is not same with the new one, set new video resolution.
|
|
|
+ // In this case, the driver which produces simple text out need be restarted.
|
|
|
+ //
|
|
|
+ Status = GraphicsOutput->SetMode (GraphicsOutput, ModeNumber);
|
|
|
+ if (!EFI_ERROR (Status)) {
|
|
|
+ //
|
|
|
+ // Set PCD to restart GraphicsConsole and Consplitter to change video resolution
|
|
|
+ // and produce new text mode based on new resolution.
|
|
|
+ //
|
|
|
+ Status = PcdSet32S (PcdVideoHorizontalResolution, mShellHorizontalResolution);
|
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
|
+
|
|
|
+ Status = PcdSet32S (PcdVideoVerticalResolution, mShellVerticalResolution);
|
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
|
+
|
|
|
+ Status = PcdSet32S (PcdConOutColumn, mShellModeColumn);
|
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
|
+
|
|
|
+ Status = PcdSet32S (PcdConOutRow, mShellModeRow);
|
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
|
+
|
|
|
+ Status = gBS->LocateHandleBuffer (
|
|
|
+ ByProtocol,
|
|
|
+ &gEfiSimpleTextOutProtocolGuid,
|
|
|
+ NULL,
|
|
|
+ &HandleCount,
|
|
|
+ &HandleBuffer
|
|
|
+ );
|
|
|
+ if (!EFI_ERROR (Status)) {
|
|
|
+ for (Index = 0; Index < HandleCount; Index++) {
|
|
|
+ gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
|
|
|
+ }
|
|
|
+ for (Index = 0; Index < HandleCount; Index++) {
|
|
|
+ gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
|
|
|
+ }
|
|
|
+ if (HandleBuffer != NULL) {
|
|
|
+ FreePool (HandleBuffer);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ FreePool (Info);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ModeNumber == MaxGopMode) {
|
|
|
+ //
|
|
|
+ // If the new resolution is not supported, return error.
|
|
|
+ //
|
|
|
+ return EFI_UNSUPPORTED;
|
|
|
+ }
|
|
|
+
|
|
|
+ return EFI_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ The function connects the trusted consoles and then call the PP processing library interface.
|
|
|
+**/
|
|
|
+VOID
|
|
|
+ProcessTcgPp (
|
|
|
+ VOID
|
|
|
+ )
|
|
|
+{
|
|
|
+ gPPRequireUIConfirm |= Tcg2PhysicalPresenceLibNeedUserConfirm();
|
|
|
+
|
|
|
+ if (gPPRequireUIConfirm) {
|
|
|
+ ConnectTrustedConsole ();
|
|
|
+ }
|
|
|
+
|
|
|
+ Tcg2PhysicalPresenceLibProcessRequest (NULL);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ The function connects the trusted storage to perform TPerReset.
|
|
|
+**/
|
|
|
+VOID
|
|
|
+ProcessTcgMor (
|
|
|
+ VOID
|
|
|
+ )
|
|
|
+{
|
|
|
+ if (IsMorBitSet ()) {
|
|
|
+ ConnectTrustedConsole();
|
|
|
+ ConnectTrustedStorage();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ Update the ConIn variable with USB Keyboard device path,if its not already exists in ConIn
|
|
|
+**/
|
|
|
+VOID
|
|
|
+EnumUsbKeyboard (
|
|
|
+ VOID
|
|
|
+ )
|
|
|
+{
|
|
|
+ DEBUG ((DEBUG_INFO, "[EnumUsbKeyboard]\n"));
|
|
|
+ EfiBootManagerUpdateConsoleVariable (ConIn, (EFI_DEVICE_PATH_PROTOCOL *) &gUsbClassKeyboardDevicePath, NULL);
|
|
|
+ //
|
|
|
+ // Append Usb Keyboard short form DevicePath into "ConInDev"
|
|
|
+ //
|
|
|
+ EfiBootManagerUpdateConsoleVariable (ConInDev, (EFI_DEVICE_PATH_PROTOCOL *) &gUsbClassKeyboardDevicePath, NULL);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ Connect with predeined platform connect sequence,
|
|
|
+ the OEM/IBV can customize with their own connect sequence.
|
|
|
+
|
|
|
+ @param[in] BootMode Boot mode of this boot.
|
|
|
+**/
|
|
|
+VOID
|
|
|
+ConnectSequence (
|
|
|
+ IN EFI_BOOT_MODE BootMode
|
|
|
+ )
|
|
|
+{
|
|
|
+ EfiBootManagerConnectAll ();
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ Connects Root Bridge
|
|
|
+ **/
|
|
|
+VOID
|
|
|
+ConnectRootBridge (
|
|
|
+ BOOLEAN Recursive
|
|
|
+ )
|
|
|
+{
|
|
|
+ UINTN RootBridgeHandleCount;
|
|
|
+ EFI_HANDLE *RootBridgeHandleBuffer;
|
|
|
+ UINTN RootBridgeIndex;
|
|
|
+
|
|
|
+ RootBridgeHandleCount = 0;
|
|
|
+ gBS->LocateHandleBuffer (
|
|
|
+ ByProtocol,
|
|
|
+ &gEfiPciRootBridgeIoProtocolGuid,
|
|
|
+ NULL,
|
|
|
+ &RootBridgeHandleCount,
|
|
|
+ &RootBridgeHandleBuffer
|
|
|
+ );
|
|
|
+ for (RootBridgeIndex = 0; RootBridgeIndex < RootBridgeHandleCount; RootBridgeIndex++) {
|
|
|
+ gBS->ConnectController (RootBridgeHandleBuffer[RootBridgeIndex], NULL, NULL, Recursive);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+VOID
|
|
|
+AddConsoleVariable (
|
|
|
+ IN CONSOLE_TYPE ConsoleType,
|
|
|
+ IN EFI_DEVICE_PATH *ConsoleDevicePath
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_DEVICE_PATH *TempDevicePath;
|
|
|
+ EFI_DEVICE_PATH *Instance;
|
|
|
+ UINTN Size;
|
|
|
+ EFI_HANDLE GraphicsControllerHandle;
|
|
|
+ EFI_DEVICE_PATH *GopDevicePath;
|
|
|
+
|
|
|
+ TempDevicePath = ConsoleDevicePath;
|
|
|
+ do {
|
|
|
+ Instance = GetNextDevicePathInstance (&TempDevicePath, &Size);
|
|
|
+ if (Instance == NULL) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ switch (ConsoleType) {
|
|
|
+ case ConIn:
|
|
|
+ if (IsUsbShortForm (Instance)) {
|
|
|
+ //
|
|
|
+ // Append Usb Keyboard short form DevicePath into "ConInDev"
|
|
|
+ //
|
|
|
+ EfiBootManagerUpdateConsoleVariable (ConInDev, Instance, NULL);
|
|
|
+ }
|
|
|
+ EfiBootManagerUpdateConsoleVariable (ConsoleType, Instance, NULL);
|
|
|
+ break;
|
|
|
+ case ConOut:
|
|
|
+ GraphicsControllerHandle = IsVideoController (Instance);
|
|
|
+ if (GraphicsControllerHandle == NULL) {
|
|
|
+ EfiBootManagerUpdateConsoleVariable (ConsoleType, Instance, NULL);
|
|
|
+ } else {
|
|
|
+ //
|
|
|
+ // Connect the GOP driver
|
|
|
+ //
|
|
|
+ gBS->ConnectController (GraphicsControllerHandle, NULL, NULL, TRUE);
|
|
|
+ //
|
|
|
+ // Get the GOP device path
|
|
|
+ // NOTE: We may get a device path that contains Controller node in it.
|
|
|
+ //
|
|
|
+ GopDevicePath = EfiBootManagerGetGopDevicePath (GraphicsControllerHandle);
|
|
|
+ if (GopDevicePath != NULL) {
|
|
|
+ EfiBootManagerUpdateConsoleVariable (ConsoleType, GopDevicePath, NULL);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ ASSERT(FALSE);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ FreePool (Instance);
|
|
|
+ } while (TempDevicePath != NULL);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ This is the callback function for PCI ENUMERATION COMPLETE.
|
|
|
+
|
|
|
+ @param[in] Event The Event this notify function registered to.
|
|
|
+ @param[in] Context Pointer to the context data registered to the Event.
|
|
|
+**/
|
|
|
+VOID
|
|
|
+EFIAPI
|
|
|
+BdsPciEnumCompleteCallback (
|
|
|
+ IN EFI_EVENT Event,
|
|
|
+ IN VOID *Context
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_STATUS Status;
|
|
|
+ VOID *ProtocolPointer;
|
|
|
+ EFI_DEVICE_PATH_PROTOCOL *VarConOut;
|
|
|
+ EFI_DEVICE_PATH_PROTOCOL *VarConIn;
|
|
|
+
|
|
|
+ Status = EFI_SUCCESS;
|
|
|
+
|
|
|
+ //
|
|
|
+ // Check if this is first time called by EfiCreateProtocolNotifyEvent() or not,
|
|
|
+ // if it is, we will skip it until real event is triggered
|
|
|
+ //
|
|
|
+ Status = gBS->LocateProtocol (&gEfiPciEnumerationCompleteProtocolGuid, NULL, (VOID **) &ProtocolPointer);
|
|
|
+ if (EFI_SUCCESS != Status) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //gBS->CloseEvent (Event);
|
|
|
+
|
|
|
+ if (PcdGetBool (PcdUpdateConsoleInBds) == TRUE) {
|
|
|
+
|
|
|
+ DEBUG ((DEBUG_INFO, "Event BdsPciEnumCompleteCallback callback starts\n"));
|
|
|
+
|
|
|
+ gBootMode = GetBootModeHob ();
|
|
|
+
|
|
|
+ //
|
|
|
+ // Fill ConIn/ConOut in Full Configuration boot mode
|
|
|
+ //
|
|
|
+ DEBUG ((DEBUG_INFO, "PlatformBootManagerInit - %x\n", gBootMode));
|
|
|
+
|
|
|
+
|
|
|
+ if (gBootMode == BOOT_WITH_FULL_CONFIGURATION ||
|
|
|
+ gBootMode == BOOT_WITH_DEFAULT_SETTINGS ||
|
|
|
+ gBootMode == BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS ||
|
|
|
+ gBootMode == BOOT_IN_RECOVERY_MODE) {
|
|
|
+
|
|
|
+ GetEfiGlobalVariable2 (L"ConOut", (VOID **)&VarConOut, NULL);
|
|
|
+ if (VarConOut != NULL) {
|
|
|
+ FreePool (VarConOut);
|
|
|
+ }
|
|
|
+
|
|
|
+ GetEfiGlobalVariable2 (L"ConIn", (VOID **)&VarConIn, NULL);
|
|
|
+ if (VarConIn != NULL) {
|
|
|
+ FreePool (VarConIn);
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // Only fill ConIn/ConOut when ConIn/ConOut is empty because we may drop to Full Configuration boot mode in non-first boot
|
|
|
+ //
|
|
|
+ if (VarConOut == NULL || VarConIn == NULL) {
|
|
|
+ if (PcdGetSize (PcdTrustedConsoleOutputDevicePath) >= sizeof(EFI_DEVICE_PATH_PROTOCOL)) {
|
|
|
+ AddConsoleVariable (ConOut, PcdGetPtr (PcdTrustedConsoleOutputDevicePath));
|
|
|
+ }
|
|
|
+ if (PcdGetSize (PcdTrustedConsoleInputDevicePath) >= sizeof(EFI_DEVICE_PATH_PROTOCOL)) {
|
|
|
+ AddConsoleVariable (ConIn, PcdGetPtr (PcdTrustedConsoleInputDevicePath));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // Enumerate USB keyboard
|
|
|
+ //
|
|
|
+ EnumUsbKeyboard ();
|
|
|
+
|
|
|
+ //
|
|
|
+ // For trusted console it must be handled here.
|
|
|
+ //
|
|
|
+ UpdateGraphicConOut (TRUE);
|
|
|
+
|
|
|
+ //
|
|
|
+ // Register Boot Options
|
|
|
+ //
|
|
|
+ RegisterDefaultBootOption ();
|
|
|
+
|
|
|
+ //
|
|
|
+ // Register Static Hot keys
|
|
|
+ //
|
|
|
+ RegisterStaticHotkey ();
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // Process Physical Preo
|
|
|
+ //
|
|
|
+ PERF_START_EX(NULL,"EventRec", NULL, AsmReadTsc(), 0x7010);
|
|
|
+ if (PcdGetBool (PcdTpm2Enable)) {
|
|
|
+ ProcessTcgPp ();
|
|
|
+ ProcessTcgMor ();
|
|
|
+ }
|
|
|
+ PERF_END_EX(NULL,"EventRec", NULL, AsmReadTsc(), 0x7011);
|
|
|
+
|
|
|
+ //
|
|
|
+ // Perform memory test
|
|
|
+ // We should make all UEFI memory and GCD information populated before ExitPmAuth.
|
|
|
+ // SMM may consume these information.
|
|
|
+ //
|
|
|
+ MemoryTest((EXTENDMEM_COVERAGE_LEVEL) PcdGet32 (PcdPlatformMemoryCheckLevel));
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ This is the callback function for Smm Ready To Lock.
|
|
|
+
|
|
|
+ @param[in] Event The Event this notify function registered to.
|
|
|
+ @param[in] Context Pointer to the context data registered to the Event.
|
|
|
+**/
|
|
|
+VOID
|
|
|
+EFIAPI
|
|
|
+BdsSmmReadyToLockCallback (
|
|
|
+ IN EFI_EVENT Event,
|
|
|
+ IN VOID *Context
|
|
|
+ )
|
|
|
+{
|
|
|
+ VOID *ProtocolPointer;
|
|
|
+ EFI_STATUS Status;
|
|
|
+ //
|
|
|
+ // Check if this is first time called by EfiCreateProtocolNotifyEvent() or not,
|
|
|
+ // if it is, we will skip it until real event is triggered
|
|
|
+ //
|
|
|
+ Status = gBS->LocateProtocol (&gEfiDxeSmmReadyToLockProtocolGuid, NULL, (VOID **) &ProtocolPointer);
|
|
|
+ if (EFI_SUCCESS != Status) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ DEBUG ((DEBUG_INFO, "Event gEfiDxeSmmReadyToLockProtocolGuid callback starts\n"));
|
|
|
+
|
|
|
+ //
|
|
|
+ // Dispatch the deferred 3rd party images.
|
|
|
+ //
|
|
|
+ EfiBootManagerDispatchDeferredImages ();
|
|
|
+
|
|
|
+ if (PcdGetBool (PcdUpdateConsoleInBds) == TRUE) {
|
|
|
+ //
|
|
|
+ // For non-trusted console it must be handled here.
|
|
|
+ //
|
|
|
+ UpdateGraphicConOut (FALSE);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ ReadyToBoot callback to set video and text mode for internal shell boot.
|
|
|
+ That will not connect USB controller while CSM and FastBoot are disabled, we need to connect them
|
|
|
+ before booting to Shell for showing USB devices in Shell.
|
|
|
+
|
|
|
+ When FastBoot is enabled and Windows Console is the chosen Console behavior, input devices will not be connected
|
|
|
+ by default. Hence, when booting to EFI shell, connecting input consoles are required.
|
|
|
+
|
|
|
+ @param Event Pointer to this event
|
|
|
+ @param Context Event hanlder private data
|
|
|
+
|
|
|
+ @retval None.
|
|
|
+**/
|
|
|
+VOID
|
|
|
+EFIAPI
|
|
|
+BdsReadyToBootCallback (
|
|
|
+ IN EFI_EVENT Event,
|
|
|
+ IN VOID *Context
|
|
|
+ )
|
|
|
+{
|
|
|
+ DEBUG ((DEBUG_INFO, "BdsReadyToBootCallback\n"));
|
|
|
+
|
|
|
+ if (BootCurrentIsInternalShell ()) {
|
|
|
+
|
|
|
+ ChangeModeForInternalShell ();
|
|
|
+ EfiBootManagerConnectAllDefaultConsoles ();
|
|
|
+ gDS->Dispatch ();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ Before console after trusted console event callback
|
|
|
+
|
|
|
+ @param[in] Event The Event this notify function registered to.
|
|
|
+ @param[in] Context Pointer to the context data registered to the Event.
|
|
|
+**/
|
|
|
+VOID
|
|
|
+BdsBeforeConsoleAfterTrustedConsoleCallback (
|
|
|
+ IN EFI_EVENT Event,
|
|
|
+ IN VOID *Context
|
|
|
+ )
|
|
|
+{
|
|
|
+ DEBUG ((DEBUG_INFO, "Event gBdsEventBeforeConsoleBeforeEndOfDxeGuid callback starts\n"));
|
|
|
+
|
|
|
+ //
|
|
|
+ // Connect Root Bridge to make PCI BAR resource allocated and all PciIo created
|
|
|
+ //
|
|
|
+ ConnectRootBridge (FALSE);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ Before console before end of DXE event callback
|
|
|
+
|
|
|
+ @param[in] Event The Event this notify function registered to.
|
|
|
+ @param[in] Context Pointer to the context data registered to the Event.
|
|
|
+**/
|
|
|
+VOID
|
|
|
+BdsBeforeConsoleBeforeEndOfDxeGuidCallback (
|
|
|
+ IN EFI_EVENT Event,
|
|
|
+ IN VOID *Context
|
|
|
+ )
|
|
|
+{
|
|
|
+ DEBUG ((DEBUG_INFO, "Event gBdsBeforeConsoleBeforeEndOfDxeGuid callback starts\n"));
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ After console ready before boot option event callback
|
|
|
+
|
|
|
+ @param[in] Event The Event this notify function registered to.
|
|
|
+ @param[in] Context Pointer to the context data registered to the Event.
|
|
|
+**/
|
|
|
+VOID
|
|
|
+BdsAfterConsoleReadyBeforeBootOptionCallback (
|
|
|
+ IN EFI_EVENT Event,
|
|
|
+ IN VOID *Context
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_BOOT_MODE LocalBootMode;
|
|
|
+ EFI_STATUS Status;
|
|
|
+ BOOLEAN IsFirstBoot;
|
|
|
+ UINTN DataSize;
|
|
|
+
|
|
|
+ DEBUG ((DEBUG_INFO, "Event gBdsAfterConsoleReadyBeforeBootOptionEvent callback starts\n"));
|
|
|
+ //
|
|
|
+ // Get current Boot Mode
|
|
|
+ //
|
|
|
+ LocalBootMode = gBootMode;
|
|
|
+ DEBUG ((DEBUG_INFO, "Current local bootmode - %x\n", LocalBootMode));
|
|
|
+
|
|
|
+ //
|
|
|
+ // Go the different platform policy with different boot mode
|
|
|
+ // Notes: this part code can be change with the table policy
|
|
|
+ //
|
|
|
+ switch (LocalBootMode) {
|
|
|
+ case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES:
|
|
|
+ case BOOT_WITH_MINIMAL_CONFIGURATION:
|
|
|
+ case BOOT_ON_S4_RESUME:
|
|
|
+ //
|
|
|
+ // Perform some platform specific connect sequence
|
|
|
+ //
|
|
|
+ if (PcdGetBool (PcdFastBoot) == FALSE) {
|
|
|
+ PERF_START_EX(NULL,"EventRec", NULL, AsmReadTsc(), 0x7050);
|
|
|
+ ConnectSequence (LocalBootMode);
|
|
|
+ PERF_END_EX(NULL,"EventRec", NULL, AsmReadTsc(), 0x7051);
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case BOOT_WITH_FULL_CONFIGURATION:
|
|
|
+ case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS:
|
|
|
+ case BOOT_WITH_DEFAULT_SETTINGS:
|
|
|
+ default:
|
|
|
+ //
|
|
|
+ // Perform some platform specific connect sequence
|
|
|
+ //
|
|
|
+ ConnectSequence (LocalBootMode);
|
|
|
+
|
|
|
+ //
|
|
|
+ // Only in Full Configuration boot mode we do the enumeration of boot device
|
|
|
+ //
|
|
|
+ //
|
|
|
+ // Dispatch all but Storage Oprom explicitly, because we assume Int13Thunk driver is there.
|
|
|
+ //
|
|
|
+
|
|
|
+ //
|
|
|
+ // PXE boot option may appear after boot option enumeration
|
|
|
+ //
|
|
|
+
|
|
|
+ EfiBootManagerRefreshAllBootOption ();
|
|
|
+ DataSize = sizeof (BOOLEAN);
|
|
|
+ Status = gRT->GetVariable (
|
|
|
+ IS_FIRST_BOOT_VAR_NAME,
|
|
|
+ &gEfiCallerIdGuid,
|
|
|
+ NULL,
|
|
|
+ &DataSize,
|
|
|
+ &IsFirstBoot
|
|
|
+ );
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ //
|
|
|
+ // If can't find the variable, see it as the first boot
|
|
|
+ //
|
|
|
+ IsFirstBoot = TRUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (IsFirstBoot) {
|
|
|
+ //
|
|
|
+ // In the first boot, sort the boot option
|
|
|
+ //
|
|
|
+ EfiBootManagerSortLoadOptionVariable (LoadOptionTypeBoot, CompareBootOption);
|
|
|
+ IsFirstBoot = FALSE;
|
|
|
+ Status = gRT->SetVariable (
|
|
|
+ IS_FIRST_BOOT_VAR_NAME,
|
|
|
+ &gEfiCallerIdGuid,
|
|
|
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
|
|
|
+ sizeof (BOOLEAN),
|
|
|
+ &IsFirstBoot
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (PcdGetBool (PcdFastBoot) == FALSE) {
|
|
|
+ Print (L"Press F2 for Setup, or F7 for BootMenu!\n");
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|