/** @file\r
Platform BDS customizations.\r
\r
- Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
This program and the accompanying materials are licensed and made available\r
under the terms and conditions of the BSD License which accompanies this\r
distribution. The full text of the license may be found at\r
#include <Guid/XenInfo.h>\r
#include <Guid/RootBridgesConnectedEventGroup.h>\r
#include <Protocol/FirmwareVolume2.h>\r
+#include <Library/Tcg2PhysicalPresenceLib.h>\r
\r
\r
//\r
EFI_EVENT mEfiDevPathEvent;\r
VOID *mEmuVariableEventReg;\r
EFI_EVENT mEmuVariableEvent;\r
-BOOLEAN mDetectVgaOnly;\r
UINT16 mHostBridgeDevId;\r
\r
//\r
IN VOID *Context\r
);\r
\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+ConnectVirtioPciRng (\r
+ IN EFI_HANDLE Handle,\r
+ IN VOID *Instance,\r
+ IN VOID *Context\r
+ );\r
+\r
STATIC\r
VOID\r
SaveS3BootScript (\r
ASSERT_RETURN_ERROR (PcdStatus);\r
\r
PlatformRegisterOptionsAndKeys ();\r
+\r
+ //\r
+ // Install both VIRTIO_DEVICE_PROTOCOL and (dependent) EFI_RNG_PROTOCOL\r
+ // instances on Virtio PCI RNG devices.\r
+ //\r
+ VisitAllInstancesOfProtocol (&gEfiPciIoProtocolGuid, ConnectVirtioPciRng,\r
+ NULL);\r
}\r
\r
\r
}\r
\r
\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+ConnectVirtioPciRng (\r
+ IN EFI_HANDLE Handle,\r
+ IN VOID *Instance,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ EFI_STATUS Status;\r
+ UINT16 VendorId;\r
+ UINT16 DeviceId;\r
+ UINT8 RevisionId;\r
+ BOOLEAN Virtio10;\r
+ UINT16 SubsystemId;\r
+\r
+ PciIo = Instance;\r
+\r
+ //\r
+ // Read and check VendorId.\r
+ //\r
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, PCI_VENDOR_ID_OFFSET,\r
+ 1, &VendorId);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+ if (VendorId != VIRTIO_VENDOR_ID) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Read DeviceId and RevisionId.\r
+ //\r
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, PCI_DEVICE_ID_OFFSET,\r
+ 1, &DeviceId);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, PCI_REVISION_ID_OFFSET,\r
+ 1, &RevisionId);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+\r
+ //\r
+ // From DeviceId and RevisionId, determine whether the device is a\r
+ // modern-only Virtio 1.0 device. In case of Virtio 1.0, DeviceId can\r
+ // immediately be restricted to VIRTIO_SUBSYSTEM_ENTROPY_SOURCE, and\r
+ // SubsystemId will only play a sanity-check role. Otherwise, DeviceId can\r
+ // only be sanity-checked, and SubsystemId will decide.\r
+ //\r
+ if (DeviceId == 0x1040 + VIRTIO_SUBSYSTEM_ENTROPY_SOURCE &&\r
+ RevisionId >= 0x01) {\r
+ Virtio10 = TRUE;\r
+ } else if (DeviceId >= 0x1000 && DeviceId <= 0x103F && RevisionId == 0x00) {\r
+ Virtio10 = FALSE;\r
+ } else {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Read and check SubsystemId as dictated by Virtio10.\r
+ //\r
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16,\r
+ PCI_SUBSYSTEM_ID_OFFSET, 1, &SubsystemId);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+ if ((Virtio10 && SubsystemId >= 0x40) ||\r
+ (!Virtio10 && SubsystemId == VIRTIO_SUBSYSTEM_ENTROPY_SOURCE)) {\r
+ Status = gBS->ConnectController (\r
+ Handle, // ControllerHandle\r
+ NULL, // DriverImageHandle -- connect all drivers\r
+ NULL, // RemainingDevicePath -- produce all child handles\r
+ FALSE // Recursive -- don't follow child handles\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+ }\r
+ return EFI_SUCCESS;\r
+\r
+Error:\r
+ DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, Status));\r
+ return Status;\r
+}\r
+\r
+\r
/**\r
Add IsaKeyboard to ConIn; add IsaSerial to ConOut, ConIn, ErrOut.\r
\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
- if (!mDetectVgaOnly) {\r
+ //\r
+ // Here we decide whether it is LPC Bridge\r
+ //\r
+ if ((IS_PCI_LPC (Pci)) ||\r
+ ((IS_PCI_ISA_PDECODE (Pci)) &&\r
+ (Pci->Hdr.VendorId == 0x8086) &&\r
+ (Pci->Hdr.DeviceId == 0x7000)\r
+ )\r
+ ) {\r
//\r
- // Here we decide whether it is LPC Bridge\r
+ // Add IsaKeyboard to ConIn,\r
+ // add IsaSerial to ConOut, ConIn, ErrOut\r
//\r
- if ((IS_PCI_LPC (Pci)) ||\r
- ((IS_PCI_ISA_PDECODE (Pci)) &&\r
- (Pci->Hdr.VendorId == 0x8086) &&\r
- (Pci->Hdr.DeviceId == 0x7000)\r
- )\r
- ) {\r
- //\r
- // Add IsaKeyboard to ConIn,\r
- // add IsaSerial to ConOut, ConIn, ErrOut\r
- //\r
- DEBUG ((EFI_D_INFO, "Found LPC Bridge device\n"));\r
- PrepareLpcBridgeDevicePath (Handle);\r
- return EFI_SUCCESS;\r
- }\r
+ DEBUG ((EFI_D_INFO, "Found LPC Bridge device\n"));\r
+ PrepareLpcBridgeDevicePath (Handle);\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // Here we decide which Serial device to enable in PCI bus\r
+ //\r
+ if (IS_PCI_16550SERIAL (Pci)) {\r
//\r
- // Here we decide which Serial device to enable in PCI bus\r
+ // Add them to ConOut, ConIn, ErrOut.\r
//\r
- if (IS_PCI_16550SERIAL (Pci)) {\r
- //\r
- // Add them to ConOut, ConIn, ErrOut.\r
- //\r
- DEBUG ((EFI_D_INFO, "Found PCI 16550 SERIAL device\n"));\r
- PreparePciSerialDevicePath (Handle);\r
- return EFI_SUCCESS;\r
- }\r
+ DEBUG ((EFI_D_INFO, "Found PCI 16550 SERIAL device\n"));\r
+ PreparePciSerialDevicePath (Handle);\r
+ return EFI_SUCCESS;\r
}\r
\r
//\r
}\r
\r
\r
-/**\r
- Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut\r
-\r
- @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE.\r
-\r
- @retval EFI_SUCCESS - PCI Device check and Console variable update\r
- successfully.\r
- @retval EFI_STATUS - PCI Device check or Console variable update fail.\r
-\r
-**/\r
-EFI_STATUS\r
-DetectAndPreparePlatformPciDevicePaths (\r
- BOOLEAN DetectVgaOnly\r
- )\r
-{\r
- mDetectVgaOnly = DetectVgaOnly;\r
- return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);\r
-}\r
-\r
-\r
/**\r
Connect the predefined platform default console device.\r
\r
)\r
{\r
UINTN Index;\r
- EFI_DEVICE_PATH_PROTOCOL *VarConout;\r
- EFI_DEVICE_PATH_PROTOCOL *VarConin;\r
\r
//\r
- // Connect RootBridge\r
+ // Do platform specific PCI Device check and add them to ConOut, ConIn,\r
+ // ErrOut\r
//\r
- GetEfiGlobalVariable2 (EFI_CON_OUT_VARIABLE_NAME, (VOID **) &VarConout,\r
- NULL);\r
- GetEfiGlobalVariable2 (EFI_CON_IN_VARIABLE_NAME, (VOID **) &VarConin, NULL);\r
-\r
- if (VarConout == NULL || VarConin == NULL) {\r
- //\r
- // Do platform specific PCI Device check and add them to ConOut, ConIn,\r
- // ErrOut\r
- //\r
- DetectAndPreparePlatformPciDevicePaths (FALSE);\r
+ VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);\r
\r
+ //\r
+ // Have chance to connect the platform default console,\r
+ // the platform default console is the minimum device group\r
+ // the platform should support\r
+ //\r
+ for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {\r
//\r
- // Have chance to connect the platform default console,\r
- // the platform default console is the minimum device group\r
- // the platform should support\r
+ // Update the console variable with the connect type\r
//\r
- for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {\r
- //\r
- // Update the console variable with the connect type\r
- //\r
- if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {\r
- EfiBootManagerUpdateConsoleVariable (ConIn,\r
- PlatformConsole[Index].DevicePath, NULL);\r
- }\r
- if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {\r
- EfiBootManagerUpdateConsoleVariable (ConOut,\r
- PlatformConsole[Index].DevicePath, NULL);\r
- }\r
- if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {\r
- EfiBootManagerUpdateConsoleVariable (ErrOut,\r
- PlatformConsole[Index].DevicePath, NULL);\r
- }\r
+ if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {\r
+ EfiBootManagerUpdateConsoleVariable (ConIn,\r
+ PlatformConsole[Index].DevicePath, NULL);\r
+ }\r
+ if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {\r
+ EfiBootManagerUpdateConsoleVariable (ConOut,\r
+ PlatformConsole[Index].DevicePath, NULL);\r
+ }\r
+ if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {\r
+ EfiBootManagerUpdateConsoleVariable (ErrOut,\r
+ PlatformConsole[Index].DevicePath, NULL);\r
}\r
- } else {\r
- //\r
- // Only detect VGA device and add them to ConOut\r
- //\r
- DetectAndPreparePlatformPciDevicePaths (TRUE);\r
}\r
}\r
\r
//\r
PciAcpiInitialization ();\r
\r
+ //\r
+ // Process TPM PPI request\r
+ //\r
+ Tcg2PhysicalPresenceLibProcessRequest (NULL);\r
+\r
//\r
// Process QEMU's -kernel command line option\r
//\r
);\r
}\r
\r
+/**\r
+ The function is called when no boot option could be launched,\r
+ including platform recovery options and options pointing to applications\r
+ built into firmware volumes.\r
+\r
+ If this function returns, BDS attempts to enter an infinite loop.\r
+**/\r
+VOID\r
+EFIAPI\r
+PlatformBootManagerUnableToBoot (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_INPUT_KEY Key;\r
+ EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu;\r
+ UINTN Index;\r
+\r
+ //\r
+ // BootManagerMenu doesn't contain the correct information when return status\r
+ // is EFI_NOT_FOUND.\r
+ //\r
+ Status = EfiBootManagerGetBootManagerMenu (&BootManagerMenu);\r
+ if (EFI_ERROR (Status)) {\r
+ return;\r
+ }\r
+ //\r
+ // Normally BdsDxe does not print anything to the system console, but this is\r
+ // a last resort -- the end-user will likely not see any DEBUG messages\r
+ // logged in this situation.\r
+ //\r
+ // AsciiPrint() will NULL-check gST->ConOut internally. We check gST->ConIn\r
+ // here to see if it makes sense to request and wait for a keypress.\r
+ //\r
+ if (gST->ConIn != NULL) {\r
+ AsciiPrint (\r
+ "%a: No bootable option or device was found.\n"\r
+ "%a: Press any key to enter the Boot Manager Menu.\n",\r
+ gEfiCallerBaseName,\r
+ gEfiCallerBaseName\r
+ );\r
+ Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index);\r
+ ASSERT_EFI_ERROR (Status);\r
+ ASSERT (Index == 0);\r
+\r
+ //\r
+ // Drain any queued keys.\r
+ //\r
+ while (!EFI_ERROR (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key))) {\r
+ //\r
+ // just throw away Key\r
+ //\r
+ }\r
+ }\r
+\r
+ for (;;) {\r
+ EfiBootManagerBoot (&BootManagerMenu);\r
+ }\r
+}\r