[Packages]\r
MdePkg/MdePkg.dec\r
MdeModulePkg/MdeModulePkg.dec\r
- OvmfPkg/Bhyve/BhyvePkg.dec\r
+ OvmfPkg/OvmfPkg.dec\r
UefiCpuPkg/UefiCpuPkg.dec\r
\r
[LibraryClasses]\r
[Defines]\r
INF_VERSION = 0x00010005\r
BASE_NAME = PlatformAcpiTables\r
- FILE_GUID = 7E374E25-8E01-4FEE-87F2-390C23C606CD\r
+ FILE_GUID = B4BA6241-936C-4485-A483-9FA832C758CA\r
MODULE_TYPE = USER_DEFINED\r
VERSION_STRING = 1.0\r
\r
+++ /dev/null
-#\r
-# Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>\r
-# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>\r
-# Copyright (c) 2014, Pluribus Networks, Inc.\r
-#\r
-# SPDX-License-Identifier: BSD-2-Clause-Patent\r
-#\r
-##\r
-\r
-[Defines]\r
- DEC_SPECIFICATION = 0x00010005\r
- PACKAGE_NAME = BhyvePkg\r
- PACKAGE_GUID = 178345e1-6ac0-439d-a3df-9abf70dccd57\r
- PACKAGE_VERSION = 0.1\r
-\r
-[Includes]\r
- Include\r
- ../Include\r
-\r
-[LibraryClasses]\r
- ## @libraryclass Save and restore variables using a file\r
- #\r
- NvVarsFileLib|Include/Library/NvVarsFileLib.h\r
-\r
- ## @libraryclass Provides services to work with PCI capabilities in PCI\r
- # config space.\r
- PciCapLib|Include/Library/PciCapLib.h\r
-\r
- ## @libraryclass Layered on top of PciCapLib, allows clients to plug an\r
- # EFI_PCI_IO_PROTOCOL backend into PciCapLib, for config\r
- # space access.\r
- PciCapPciIoLib|Include/Library/PciCapPciIoLib.h\r
-\r
- ## @libraryclass Layered on top of PciCapLib, allows clients to plug a\r
- # PciSegmentLib backend into PciCapLib, for config space\r
- # access.\r
- PciCapPciSegmentLib|Include/Library/PciCapPciSegmentLib.h\r
-\r
- ## @libraryclass Register a status code handler for printing the Boot\r
- # Manager's LoadImage() and StartImage() preparations, and\r
- # return codes, to the UEFI console.\r
- PlatformBmPrintScLib|Include/Library/PlatformBmPrintScLib.h\r
-\r
- ## @libraryclass Serialize (and deserialize) variables\r
- #\r
- SerializeVariablesLib|Include/Library/SerializeVariablesLib.h\r
-\r
- ## @libraryclass Access bhyve's firmware control interface\r
- #\r
- BhyveFwCtlLib|Include/Library/BhyveFwCtlLib.h\r
-\r
-[Guids]\r
- gUefiOvmfPkgTokenSpaceGuid = {0x93bb96af, 0xb9f2, 0x4eb8, {0x94, 0x62, 0xe0, 0xba, 0x74, 0x56, 0x42, 0x36}}\r
- gOvmfPlatformConfigGuid = {0x7235c51c, 0x0c80, 0x4cab, {0x87, 0xac, 0x3b, 0x08, 0x4a, 0x63, 0x04, 0xb1}}\r
- gVirtioMmioTransportGuid = {0x837dca9e, 0xe874, 0x4d82, {0xb2, 0x9a, 0x23, 0xfe, 0x0e, 0x23, 0xd1, 0xe2}}\r
- gRootBridgesConnectedEventGroupGuid = {0x24a2d66f, 0xeedd, 0x4086, {0x90, 0x42, 0xf2, 0x6e, 0x47, 0x97, 0xee, 0x69}}\r
-\r
-[Protocols]\r
- gVirtioDeviceProtocolGuid = {0xfa920010, 0x6785, 0x4941, {0xb6, 0xec, 0x49, 0x8c, 0x57, 0x9f, 0x16, 0x0a}}\r
- gIoMmuAbsentProtocolGuid = {0xf8775d50, 0x8abd, 0x4adf, {0x92, 0xac, 0x85, 0x3e, 0x51, 0xf6, 0xc8, 0xdc}}\r
-\r
-[PcdsFixedAtBuild]\r
- gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|0x0|UINT32|0\r
- gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize|0x0|UINT32|1\r
- gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase|0x0|UINT32|0x15\r
- gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize|0x0|UINT32|0x16\r
-\r
- ## This flag is used to control the destination port for PlatformDebugLibIoPort\r
- gUefiOvmfPkgTokenSpaceGuid.PcdDebugIoPort|0x2F8|UINT16|4\r
-\r
- ## When VirtioScsiDxe is instantiated for a HBA, the numbers of targets and\r
- # LUNs are retrieved from the host during virtio-scsi setup.\r
- # MdeModulePkg/Bus/Scsi/ScsiBusDxe then scans all MaxTarget * MaxLun\r
- # possible devices. This can take extremely long, for example with\r
- # MaxTarget=255 and MaxLun=16383. The *inclusive* constants below limit\r
- # MaxTarget and MaxLun, independently, should the host report higher values,\r
- # so that scanning the number of devices given by their product is still\r
- # acceptably fast.\r
- gUefiOvmfPkgTokenSpaceGuid.PcdVirtioScsiMaxTargetLimit|31|UINT16|6\r
- gUefiOvmfPkgTokenSpaceGuid.PcdVirtioScsiMaxLunLimit|7|UINT32|7\r
-\r
- gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase|0x0|UINT32|0x8\r
- gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize|0x0|UINT32|0x9\r
- gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize|0x0|UINT32|0xa\r
- gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareBlockSize|0|UINT32|0xb\r
- gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageVariableBase|0x0|UINT32|0xc\r
- gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageFtwSpareBase|0x0|UINT32|0xd\r
- gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageFtwWorkingBase|0x0|UINT32|0xe\r
- gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFdBaseAddress|0x0|UINT32|0xf\r
- gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase|0x0|UINT32|0x11\r
- gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize|0x0|UINT32|0x12\r
- gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|0x0|UINT32|0x13\r
- gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize|0x0|UINT32|0x14\r
- gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageBase|0x0|UINT32|0x18\r
- gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageSize|0x0|UINT32|0x19\r
- gUefiOvmfPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize|0x0|UINT32|0x1a\r
- gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDecompressionScratchEnd|0x0|UINT32|0x1f\r
-\r
- ## Pcd8259LegacyModeMask defines the default mask value for platform. This\r
- # value is determined.\r
- # 1) If platform only support pure UEFI, value should be set to 0xFFFF or\r
- # 0xFFFE; Because only clock interrupt is allowed in legacy mode in pure\r
- # UEFI platform.\r
- # 2) If platform install CSM and use thunk module:\r
- # a) If thunk call provided by CSM binary requires some legacy interrupt\r
- # support, the corresponding bit should be opened as 0.\r
- # For example, if keyboard interfaces provided CSM binary use legacy\r
- # keyboard interrupt in 8259 bit 1, then the value should be set to\r
- # 0xFFFC.\r
- # b) If all thunk call provied by CSM binary do not require legacy\r
- # interrupt support, value should be set to 0xFFFF or 0xFFFE.\r
- #\r
- # The default value of legacy mode mask could be changed by\r
- # EFI_LEGACY_8259_PROTOCOL->SetMask(). But it is rarely need change it\r
- # except some special cases such as when initializing the CSM binary, it\r
- # should be set to 0xFFFF to mask all legacy interrupt. Please restore the\r
- # original legacy mask value if changing is made for these special case.\r
- gUefiOvmfPkgTokenSpaceGuid.Pcd8259LegacyModeMask|0xFFFF|UINT16|0x3\r
-\r
- ## Pcd8259LegacyModeEdgeLevel defines the default edge level for legacy\r
- # mode's interrrupt controller.\r
- # For the corresponding bits, 0 = Edge triggered and 1 = Level triggered.\r
- gUefiOvmfPkgTokenSpaceGuid.Pcd8259LegacyModeEdgeLevel|0x0000|UINT16|0x5\r
-\r
-\r
-\r
-[PcdsDynamic, PcdsDynamicEx]\r
- gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2\r
- gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10\r
- gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId|0|UINT16|0x1b\r
- gUefiOvmfPkgTokenSpaceGuid.PcdQemuSmbiosValidated|FALSE|BOOLEAN|0x21\r
-\r
- ## The IO port aperture shared by all PCI root bridges.\r
- #\r
- gUefiOvmfPkgTokenSpaceGuid.PcdPciIoBase|0x0|UINT64|0x22\r
- gUefiOvmfPkgTokenSpaceGuid.PcdPciIoSize|0x0|UINT64|0x23\r
-\r
- ## The 32-bit MMIO aperture shared by all PCI root bridges.\r
- #\r
- gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio32Base|0x0|UINT64|0x24\r
- gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio32Size|0x0|UINT64|0x25\r
-\r
- ## The 64-bit MMIO aperture shared by all PCI root bridges.\r
- #\r
- gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Base|0x0|UINT64|0x26\r
- gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Size|0x0|UINT64|0x27\r
-\r
- ## The following setting controls how many megabytes we configure as TSEG on\r
- # Q35, for SMRAM purposes. Permitted defaults are: 1, 2, 8. Other defaults\r
- # cause undefined behavior. During boot, the PCD is updated by PlatformPei\r
- # to reflect the extended TSEG size, if one is advertized by QEMU.\r
- #\r
- # This PCD is only accessed if PcdSmmSmramRequire is TRUE (see below).\r
- gUefiOvmfPkgTokenSpaceGuid.PcdQ35TsegMbytes|8|UINT16|0x20\r
-\r
-[PcdsFeatureFlag]\r
- gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderPciTranslation|TRUE|BOOLEAN|0x1c\r
- gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderMmioTranslation|FALSE|BOOLEAN|0x1d\r
-\r
- ## This feature flag enables SMM/SMRAM support. Note that it also requires\r
- # such support from the underlying QEMU instance; if that support is not\r
- # present, the firmware will reject continuing after a certain point.\r
- #\r
- # The flag also acts as a general "security switch"; when TRUE, many\r
- # components will change behavior, with the goal of preventing a malicious\r
- # runtime OS from tampering with firmware structures (special memory ranges\r
- # used by OVMF, the varstore pflash chip, LockBox etc).\r
- gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire|FALSE|BOOLEAN|0x1e\r
-\r
-[Protocols]\r
-gEfiLegacyBiosProtocolGuid = {0xdb9a1e3d, 0x45cb, 0x4abb, {0x85, 0x3b, 0xe5, 0x38, 0x7f, 0xdb, 0x2e, 0x2d}}\r
SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf\r
QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibNull.inf\r
QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/BaseQemuFwCfgS3LibNull.inf\r
- BhyveFwCtlLib|OvmfPkg/Bhyve/Library/BhyveFwCtlLib/BhyveFwCtlLib.inf\r
+ BhyveFwCtlLib|OvmfPkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.inf\r
VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf\r
MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf\r
LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf\r
!else\r
DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf\r
!endif\r
- PlatformBootManagerLib|OvmfPkg/Bhyve/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf\r
+ PlatformBootManagerLib|OvmfPkg/Library/PlatformBootManagerLibBhyve/PlatformBootManagerLibBhyve.inf\r
PlatformBmPrintScLib|OvmfPkg/Library/PlatformBmPrintScLib/PlatformBmPrintScLib.inf\r
CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf\r
LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxDxeLib.inf\r
gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand|FALSE\r
\r
gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVendor|L"BHYVE"\r
+ gUefiOvmfPkgTokenSpaceGuid.PcdDebugIoPort|0x2F8\r
\r
################################################################################\r
#\r
}\r
\r
[Rule.Common.USER_DEFINED.ACPITABLE]\r
- FILE FREEFORM = $(NAMED_GUID) {\r
+ FILE FREEFORM = 7E374E25-8E01-4FEE-87F2-390C23C606CD {\r
RAW ACPI |.acpi\r
RAW ASL |.aml\r
}\r
\r
[Packages]\r
MdePkg/MdePkg.dec\r
- OvmfPkg/Bhyve/BhyvePkg.dec\r
+ OvmfPkg/OvmfPkg.dec\r
MdeModulePkg/MdeModulePkg.dec\r
\r
\r
+++ /dev/null
-/** @file\r
- bhyve firmware configuration access\r
-\r
- Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>\r
- Copyright (c) 2015 Nahanni Systems\r
-\r
- SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#ifndef __BHYVE_FW_CTL_LIB__\r
-#define __BHYVE_FW_CTL_LIB__\r
-\r
-/**\r
- Sysctl-like interface to read host information via a dot-separated\r
- ASCII OID.\r
-\r
- The information is copied into the buffer specified by Item. The\r
- size of the buffer is given by the location specified by Size\r
- before the call, and that location gives the amount of data copied\r
- after a successfull call, and after a call that returns a truncated\r
- value with an error return of RETURN_BUFFER_TOO_SMALL.\r
-\r
- The size of the available data can be determined by passing a NULL\r
- argument for Item. The size will be returned in the location pointed\r
- to by Size.\r
-\r
- @param[] Name - ASCII OID name\r
- @param[] Data - return buffer pointer\r
- @param[] Size - pointer to length\r
-\r
- @return RETURN_SUCCESS Valid data/len returned.\r
- RETURN_UNSUPPORTED f/w interface not present.\r
- RETURN_NOT_FOUND OID not found.\r
- RETURN_BUFFER_TOO_SMALL Return message truncated.\r
- RETURN_INVALID_PARAMETER Buffer too large\r
- RETURN_PROTOCOL_ERROR Unknown error from host\r
- **/\r
-RETURN_STATUS\r
-EFIAPI\r
-BhyveFwCtlGet (\r
- IN CONST CHAR8 *Name,\r
- OUT VOID *Item,\r
- IN OUT UINTN *Size\r
- );\r
-\r
-#endif\r
+++ /dev/null
-/** @file\r
-\r
- Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>\r
- Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>\r
- Copyright (C) 2013, Red Hat, Inc.\r
- Copyright (c) 2015, Nahanni Systems.\r
-\r
- SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include "Uefi.h"\r
-#include <Library/BaseLib.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/IoLib.h>\r
-#include <Library/BhyveFwCtlLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-\r
-#define FW_PORT 0x510\r
-#define FW_IPORT 0x511\r
-\r
-/* Transport protocol basic operations */\r
-#define OP_NULL 1\r
-#define OP_ECHO 2\r
-#define OP_GET 3\r
-#define OP_GET_LEN 4\r
-#define OP_SET 5\r
-\r
-/* Transport protocol error returns */\r
-#define T_ESUCCESS 0\r
-#define T_ENOENT 2\r
-#define T_E2BIG 7\r
-#define T_EMSGSIZE 40\r
-\r
-#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y))\r
-\r
-STATIC CONST CHAR8 mBhyveSig[4] = { 'B', 'H', 'Y', 'V' };\r
-\r
-STATIC BOOLEAN mBhyveFwCtlSupported = FALSE;\r
-\r
-STATIC INTN mBhyveFwCtlTxid = 0xa5;\r
-\r
-/* XXX Maybe a better inbuilt version of this ? */\r
-struct BIoVec {\r
- VOID *Base;\r
- UINTN Len;\r
-};\r
-\r
-struct MsgRxHdr {\r
- UINT32 Sz;\r
- UINT32 Op;\r
- UINT32 TxId;\r
- UINT32 Err;\r
-};\r
-\r
-STATIC\r
-RETURN_STATUS\r
-EFIAPI\r
-BhyveFwCtl_CvtErr (\r
- IN UINT32 errno\r
- )\r
-{\r
- RETURN_STATUS Status;\r
-\r
- switch (errno) {\r
- case T_ESUCCESS:\r
- Status = RETURN_SUCCESS;\r
- break;\r
- case T_ENOENT:\r
- Status = RETURN_NOT_FOUND;\r
- break;\r
- case T_E2BIG:\r
- Status = RETURN_INVALID_PARAMETER;\r
- break;\r
- case T_EMSGSIZE:\r
- Status = RETURN_BUFFER_TOO_SMALL;\r
- break;\r
- default:\r
- Status = RETURN_PROTOCOL_ERROR;\r
- break;\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-STATIC\r
-UINTN\r
-EFIAPI\r
-BIov_WLen (\r
- IN struct BIoVec b[]\r
- )\r
-{\r
- UINTN i;\r
- UINTN tLen;\r
-\r
- tLen = 0;\r
-\r
- if (b != NULL) {\r
- for (i = 0; b[i].Base != NULL; i++)\r
- tLen += ROUNDUP (b[i].Len, sizeof(UINT32));\r
- }\r
-\r
- return tLen;\r
-}\r
-\r
-/**\r
- Utility to send 1-3 bhyes of input as a 4-byte value\r
- with trailing zeroes.\r
- **/\r
-STATIC\r
-UINT32\r
-BIov_Send_Rem (\r
- IN UINT32 *Data,\r
- IN UINTN Len\r
- )\r
-{\r
- union {\r
- UINT8 c[4];\r
- UINT32 w;\r
- } u;\r
- UINT8 *cdata;\r
- UINTN i;\r
-\r
- cdata = (UINT8 *)Data;\r
- u.w = 0;\r
-\r
- for (i = 0; i < Len; i++)\r
- u.c[i] = *cdata++;\r
-\r
- return u.w;\r
-}\r
-\r
-/**\r
- Send a block of data out the i/o port as 4-byte quantities,\r
- appending trailing zeroes on the last if required.\r
- **/\r
-STATIC\r
-VOID\r
-BIov_Send (\r
- IN char *Data,\r
- IN UINTN Len\r
- )\r
-{\r
- UINT32 *LData;\r
-\r
- LData = (UINT32 *)Data;\r
-\r
- while (Len > sizeof(UINT32)) {\r
- IoWrite32 (FW_PORT, *LData++);\r
- Len -= sizeof(UINT32);\r
- }\r
-\r
- if (Len > 0) {\r
- IoWrite32 (FW_PORT, BIov_Send_Rem (LData, Len));\r
- }\r
-}\r
-\r
-/**\r
- Send data described by an array of iovecs out the i/o port.\r
- **/\r
-STATIC\r
-VOID\r
-BIov_SendAll (\r
- IN struct BIoVec b[]\r
- )\r
-{\r
- INTN i;\r
-\r
- if (b != NULL) {\r
- for (i = 0; b[i].Base; i++) {\r
- BIov_Send (b[i].Base, b[i].Len);\r
- }\r
- }\r
-}\r
-\r
-/**\r
- Prepend the transport header to a block of data and send.\r
- **/\r
-STATIC\r
-VOID\r
-EFIAPI\r
-BhyveFwCtl_MsgSend(\r
- IN UINTN OpCode,\r
- IN struct BIoVec Data[]\r
- )\r
-{\r
- struct BIoVec hIov[4];\r
- UINT32 Hdr[3];\r
- UINTN i;\r
-\r
- /* Set up header as an iovec */\r
- for (i = 0; i < 3; i++) {\r
- hIov[i].Base = &Hdr[i];\r
- hIov[i].Len = sizeof(Hdr[0]);\r
- }\r
- hIov[i].Base = NULL;\r
- hIov[i].Len = 0;\r
-\r
- /* Initialize header */\r
- Hdr[0] = BIov_WLen (hIov) + BIov_WLen (Data);\r
- Hdr[1] = OpCode;\r
- Hdr[2] = mBhyveFwCtlTxid;\r
-\r
- /* Send header and data */\r
- BIov_SendAll (hIov);\r
- BIov_SendAll (Data);\r
-}\r
-\r
-/**\r
- Read a transport response and optional data from the i/o port.\r
- **/\r
-STATIC\r
-RETURN_STATUS\r
-EFIAPI\r
-BhyveFwCtl_MsgRecv(\r
- OUT struct MsgRxHdr *Rhdr,\r
- OUT struct BIoVec Data[]\r
- )\r
-{\r
- RETURN_STATUS Status;\r
- UINT32 *Dp;\r
- UINT32 Rd;\r
- UINTN remLen;\r
- INTN oLen, xLen;\r
-\r
- Rd = IoRead32 (FW_PORT);\r
- if (Rd < sizeof(struct MsgRxHdr)) {\r
- ;\r
- }\r
-\r
- /* Read in header and setup initial error */\r
- Rhdr->Sz = Rd;\r
- Rhdr->Op = IoRead32 (FW_PORT);\r
- Rhdr->TxId = IoRead32 (FW_PORT);\r
- Rhdr->Err = IoRead32 (FW_PORT);\r
-\r
- /* Convert transport errno into UEFI error status */\r
- Status = BhyveFwCtl_CvtErr(Rhdr->Err);\r
-\r
- remLen = Rd - sizeof(struct MsgRxHdr);\r
- xLen = 0;\r
-\r
- /*\r
- * A few cases to handle:\r
- * - the user didn't supply a read buffer\r
- * - the buffer is too small for the response\r
- * - the response is zero-length\r
- */\r
- if (Data != NULL) {\r
- Dp = (UINT32 *)Data[0].Base;\r
- oLen = remLen;\r
- if (remLen > Data[0].Len) {\r
- Status = RETURN_BUFFER_TOO_SMALL;\r
- xLen = remLen - Data[0].Len;\r
- oLen = remLen = Data[0].Len;\r
- }\r
- while (remLen > 0) {\r
- *Dp++ = IoRead32 (FW_PORT);\r
- remLen -= sizeof(UINT32);\r
- }\r
- Data[0].Len = oLen;\r
- } else {\r
- /* No user data, but data returned - drop */\r
- if (remLen > 0) {\r
- Status = RETURN_BUFFER_TOO_SMALL;\r
- xLen = remLen;\r
- }\r
- }\r
-\r
- /* Drop additional data */\r
- while (xLen > 0) {\r
- (void) IoRead32 (FW_PORT);\r
- xLen -= sizeof(UINT32);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-\r
-STATIC\r
-RETURN_STATUS\r
-EFIAPI\r
-BhyveFwCtl_Msg(\r
- IN UINTN OpCode,\r
- IN struct BIoVec Sdata[],\r
- OUT struct BIoVec Rdata[]\r
- )\r
-{\r
- struct MsgRxHdr Rh;\r
- RETURN_STATUS Status;\r
-\r
- Status = RETURN_SUCCESS;\r
-\r
- BhyveFwCtl_MsgSend (OpCode, Sdata);\r
- Status = BhyveFwCtl_MsgRecv (&Rh, Rdata);\r
-\r
- mBhyveFwCtlTxid++;\r
-\r
- return Status;\r
-}\r
-\r
-STATIC\r
-RETURN_STATUS\r
-EFIAPI\r
-BhyveFwCtlGetLen (\r
- IN CONST CHAR8 *Name,\r
- IN OUT UINTN *Size\r
- )\r
-{\r
- struct BIoVec Req[2], Resp[2];\r
- RETURN_STATUS Status;\r
-\r
- Req[0].Base = (VOID *)Name;\r
- Req[0].Len = AsciiStrLen (Name) + 1;\r
- Req[1].Base = NULL;\r
-\r
- Resp[0].Base = Size;\r
- Resp[0].Len = sizeof(UINTN);\r
- Resp[1].Base = NULL;\r
-\r
- Status = BhyveFwCtl_Msg (OP_GET_LEN, Req, Resp);\r
-\r
- return Status;\r
-}\r
-\r
-#define FMAXSZ 1024\r
-STATIC struct {\r
- UINT64 fSize;\r
- UINT32 fData[FMAXSZ];\r
-} FwGetvalBuf;\r
-\r
-STATIC\r
-RETURN_STATUS\r
-EFIAPI\r
-BhyveFwCtlGetVal (\r
- IN CONST CHAR8 *Name,\r
- OUT VOID *Item,\r
- IN OUT UINTN *Size\r
- )\r
-{\r
- struct BIoVec Req[2], Resp[2];\r
- RETURN_STATUS Status;\r
-\r
- /* Make sure temp buffer is larger than passed-in size */\r
- if (*Size > sizeof(FwGetvalBuf.fData))\r
- return RETURN_INVALID_PARAMETER;\r
-\r
- Req[0].Base = (VOID *)Name;\r
- Req[0].Len = AsciiStrLen(Name) + 1;\r
- Req[1].Base = NULL;\r
-\r
- Resp[0].Base = &FwGetvalBuf;\r
- Resp[0].Len = sizeof(UINT64) + *Size;\r
- Resp[1].Base = NULL;\r
-\r
- Status = BhyveFwCtl_Msg (OP_GET, Req, Resp);\r
-\r
- /*\r
- * Copy out data on success (or on a truncated message).\r
- * XXX This step can be eliminted with Msg() supporting\r
- * multiple iovecs.\r
- */\r
- if ((Status == RETURN_SUCCESS) || (Status == RETURN_BUFFER_TOO_SMALL)) {\r
- *Size = FwGetvalBuf.fSize;\r
- CopyMem (Item, FwGetvalBuf.fData, *Size);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Front end to the internal GET_LEN and GET protocols\r
- **/\r
-RETURN_STATUS\r
-EFIAPI\r
-BhyveFwCtlGet (\r
- IN CONST CHAR8 *Name,\r
- OUT VOID *Item,\r
- IN OUT UINTN *Size\r
- )\r
-{\r
- RETURN_STATUS Status;\r
-\r
- if (mBhyveFwCtlSupported == FALSE)\r
- return RETURN_UNSUPPORTED;\r
-\r
- if (Item == NULL) {\r
- Status = BhyveFwCtlGetLen (Name, Size);\r
- } else {\r
- Status = BhyveFwCtlGetVal (Name, Item, Size);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Library initialization. Probe the host to see if the f/w ctl\r
- interface is supported.\r
- **/\r
-RETURN_STATUS\r
-EFIAPI\r
-BhyveFwCtlInitialize (\r
- VOID\r
- )\r
-{\r
- UINTN i;\r
- UINT8 ch;\r
-\r
- DEBUG ((DEBUG_INFO, "FwCtlInitialize\n"));\r
-\r
- IoWrite16 (FW_PORT, 0x0000);\r
- for (i = 0; i < 4; i++) {\r
- ch = IoRead8 (FW_IPORT);\r
- if (ch != mBhyveSig[i]) {\r
- DEBUG ((DEBUG_INFO, "Host f/w sig mismatch %c/%c\n", ch, mBhyveSig[i]));\r
- return RETURN_SUCCESS;\r
- }\r
- }\r
-\r
- mBhyveFwCtlSupported = TRUE;\r
-\r
- return RETURN_SUCCESS;\r
-}\r
+++ /dev/null
-## @file\r
-#\r
-# Copyright (C) 2020, Rebecca Cran <rebecca@bsdio.com>\r
-# Copyright (C) 2015 Nahanni Systems\r
-# Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>\r
-#\r
-# SPDX-License-Identifier: BSD-2-Clause-Patent\r
-#\r
-##\r
-\r
-[Defines]\r
- INF_VERSION = 0x00010005\r
- BASE_NAME = BhyveFwCtlLib\r
- FILE_GUID = fd982666-67f9-11e5-a42a-0025908602f6\r
- MODULE_TYPE = BASE\r
- VERSION_STRING = 1.0\r
- LIBRARY_CLASS = BhyveFwCtlLib|PEIM DXE_DRIVER DXE_RUNTIME_DRIVER\r
-\r
- CONSTRUCTOR = BhyveFwCtlInitialize\r
-\r
-#\r
-# The following information is for reference only and not required by the build tools.\r
-#\r
-# VALID_ARCHITECTURES = X64\r
-#\r
-\r
-[Sources]\r
- BhyveFwCtlLib.c\r
-\r
-[Packages]\r
- MdePkg/MdePkg.dec\r
- OvmfPkg/Bhyve/BhyvePkg.dec\r
-\r
-[LibraryClasses]\r
- BaseLib\r
- BaseMemoryLib\r
- DebugLib\r
- IoLib\r
- MemoryAllocationLib\r
- IntrinsicLib\r
-\r
+++ /dev/null
-/** @file\r
- Platform BDS customizations.\r
-\r
- Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>\r
- Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>\r
- SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include "BdsPlatform.h"\r
-#include <Guid/RootBridgesConnectedEventGroup.h>\r
-#include <Protocol/FirmwareVolume2.h>\r
-#include <Library/PlatformBmPrintScLib.h>\r
-#include <Library/Tcg2PhysicalPresenceLib.h>\r
-\r
-#include <Protocol/BlockIo.h>\r
-\r
-//\r
-// Global data\r
-//\r
-\r
-VOID *mEfiDevPathNotifyReg;\r
-EFI_EVENT mEfiDevPathEvent;\r
-VOID *mEmuVariableEventReg;\r
-EFI_EVENT mEmuVariableEvent;\r
-UINT16 mHostBridgeDevId;\r
-\r
-//\r
-// Table of host IRQs matching PCI IRQs A-D\r
-// (for configuring PCI Interrupt Line register)\r
-//\r
-CONST UINT8 PciHostIrqs[] = {\r
- 0x0a, 0x0a, 0x0b, 0x0b\r
-};\r
-\r
-//\r
-// Type definitions\r
-//\r
-\r
-typedef\r
-EFI_STATUS\r
-(EFIAPI *PROTOCOL_INSTANCE_CALLBACK)(\r
- IN EFI_HANDLE Handle,\r
- IN VOID *Instance,\r
- IN VOID *Context\r
- );\r
-\r
-/**\r
- @param[in] Handle - Handle of PCI device instance\r
- @param[in] PciIo - PCI IO protocol instance\r
- @param[in] Pci - PCI Header register block\r
-**/\r
-typedef\r
-EFI_STATUS\r
-(EFIAPI *VISIT_PCI_INSTANCE_CALLBACK)(\r
- IN EFI_HANDLE Handle,\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN PCI_TYPE00 *Pci\r
- );\r
-\r
-\r
-//\r
-// Function prototypes\r
-//\r
-\r
-EFI_STATUS\r
-VisitAllInstancesOfProtocol (\r
- IN EFI_GUID *Id,\r
- IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,\r
- IN VOID *Context\r
- );\r
-\r
-EFI_STATUS\r
-VisitAllPciInstancesOfProtocol (\r
- IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction\r
- );\r
-\r
-VOID\r
-InstallDevicePathCallback (\r
- VOID\r
- );\r
-\r
-VOID\r
-PlatformRegisterFvBootOption (\r
- EFI_GUID *FileGuid,\r
- CHAR16 *Description,\r
- UINT32 Attributes\r
- )\r
-{\r
- EFI_STATUS Status;\r
- INTN OptionIndex;\r
- EFI_BOOT_MANAGER_LOAD_OPTION NewOption;\r
- EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;\r
- UINTN BootOptionCount;\r
- MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;\r
- EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
-\r
- Status = gBS->HandleProtocol (\r
- gImageHandle,\r
- &gEfiLoadedImageProtocolGuid,\r
- (VOID **) &LoadedImage\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);\r
- DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle);\r
- ASSERT (DevicePath != NULL);\r
- DevicePath = AppendDevicePathNode (\r
- DevicePath,\r
- (EFI_DEVICE_PATH_PROTOCOL *) &FileNode\r
- );\r
- ASSERT (DevicePath != NULL);\r
-\r
- Status = EfiBootManagerInitializeLoadOption (\r
- &NewOption,\r
- LoadOptionNumberUnassigned,\r
- LoadOptionTypeBoot,\r
- Attributes,\r
- Description,\r
- DevicePath,\r
- NULL,\r
- 0\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- FreePool (DevicePath);\r
-\r
- BootOptions = EfiBootManagerGetLoadOptions (\r
- &BootOptionCount, LoadOptionTypeBoot\r
- );\r
-\r
- OptionIndex = EfiBootManagerFindLoadOption (\r
- &NewOption, BootOptions, BootOptionCount\r
- );\r
-\r
- if (OptionIndex == -1) {\r
- Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN);\r
- ASSERT_EFI_ERROR (Status);\r
- }\r
- EfiBootManagerFreeLoadOption (&NewOption);\r
- EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);\r
-}\r
-\r
-/**\r
- Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options\r
- whose device paths do not resolve exactly to an FvFile in the system.\r
-\r
- This removes any boot options that point to binaries built into the firmware\r
- and have become stale due to any of the following:\r
- - DXEFV's base address or size changed (historical),\r
- - DXEFV's FvNameGuid changed,\r
- - the FILE_GUID of the pointed-to binary changed,\r
- - the referenced binary is no longer built into the firmware.\r
-\r
- EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only\r
- avoids exact duplicates.\r
-**/\r
-VOID\r
-RemoveStaleFvFileOptions (\r
- VOID\r
- )\r
-{\r
- EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;\r
- UINTN BootOptionCount;\r
- UINTN Index;\r
-\r
- BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount,\r
- LoadOptionTypeBoot);\r
-\r
- for (Index = 0; Index < BootOptionCount; ++Index) {\r
- EFI_DEVICE_PATH_PROTOCOL *Node1, *Node2, *SearchNode;\r
- EFI_STATUS Status;\r
- EFI_HANDLE FvHandle;\r
-\r
- //\r
- // If the device path starts with neither MemoryMapped(...) nor Fv(...),\r
- // then keep the boot option.\r
- //\r
- Node1 = BootOptions[Index].FilePath;\r
- if (!(DevicePathType (Node1) == HARDWARE_DEVICE_PATH &&\r
- DevicePathSubType (Node1) == HW_MEMMAP_DP) &&\r
- !(DevicePathType (Node1) == MEDIA_DEVICE_PATH &&\r
- DevicePathSubType (Node1) == MEDIA_PIWG_FW_VOL_DP)) {\r
- continue;\r
- }\r
-\r
- //\r
- // If the second device path node is not FvFile(...), then keep the boot\r
- // option.\r
- //\r
- Node2 = NextDevicePathNode (Node1);\r
- if (DevicePathType (Node2) != MEDIA_DEVICE_PATH ||\r
- DevicePathSubType (Node2) != MEDIA_PIWG_FW_FILE_DP) {\r
- continue;\r
- }\r
-\r
- //\r
- // Locate the Firmware Volume2 protocol instance that is denoted by the\r
- // boot option. If this lookup fails (i.e., the boot option references a\r
- // firmware volume that doesn't exist), then we'll proceed to delete the\r
- // boot option.\r
- //\r
- SearchNode = Node1;\r
- Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid,\r
- &SearchNode, &FvHandle);\r
-\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // The firmware volume was found; now let's see if it contains the FvFile\r
- // identified by GUID.\r
- //\r
- EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;\r
- MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFileNode;\r
- UINTN BufferSize;\r
- EFI_FV_FILETYPE FoundType;\r
- EFI_FV_FILE_ATTRIBUTES FileAttributes;\r
- UINT32 AuthenticationStatus;\r
-\r
- Status = gBS->HandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid,\r
- (VOID **)&FvProtocol);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- FvFileNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)Node2;\r
- //\r
- // Buffer==NULL means we request metadata only: BufferSize, FoundType,\r
- // FileAttributes.\r
- //\r
- Status = FvProtocol->ReadFile (\r
- FvProtocol,\r
- &FvFileNode->FvFileName, // NameGuid\r
- NULL, // Buffer\r
- &BufferSize,\r
- &FoundType,\r
- &FileAttributes,\r
- &AuthenticationStatus\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // The FvFile was found. Keep the boot option.\r
- //\r
- continue;\r
- }\r
- }\r
-\r
- //\r
- // Delete the boot option.\r
- //\r
- Status = EfiBootManagerDeleteLoadOptionVariable (\r
- BootOptions[Index].OptionNumber, LoadOptionTypeBoot);\r
- DEBUG_CODE (\r
- CHAR16 *DevicePathString;\r
-\r
- DevicePathString = ConvertDevicePathToText(BootOptions[Index].FilePath,\r
- FALSE, FALSE);\r
- DEBUG ((\r
- EFI_ERROR (Status) ? EFI_D_WARN : DEBUG_VERBOSE,\r
- "%a: removing stale Boot#%04x %s: %r\n",\r
- __FUNCTION__,\r
- (UINT32)BootOptions[Index].OptionNumber,\r
- DevicePathString == NULL ? L"<unavailable>" : DevicePathString,\r
- Status\r
- ));\r
- if (DevicePathString != NULL) {\r
- FreePool (DevicePathString);\r
- }\r
- );\r
- }\r
-\r
- EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);\r
-}\r
-\r
-VOID\r
-PlatformRegisterOptionsAndKeys (\r
- VOID\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_INPUT_KEY Enter;\r
- EFI_INPUT_KEY F2;\r
- EFI_INPUT_KEY Esc;\r
- EFI_BOOT_MANAGER_LOAD_OPTION BootOption;\r
-\r
- //\r
- // Register ENTER as CONTINUE key\r
- //\r
- Enter.ScanCode = SCAN_NULL;\r
- Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;\r
- Status = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- //\r
- // Map F2 to Boot Manager Menu\r
- //\r
- F2.ScanCode = SCAN_F2;\r
- F2.UnicodeChar = CHAR_NULL;\r
- Esc.ScanCode = SCAN_ESC;\r
- Esc.UnicodeChar = CHAR_NULL;\r
- Status = EfiBootManagerGetBootManagerMenu (&BootOption);\r
- ASSERT_EFI_ERROR (Status);\r
- Status = EfiBootManagerAddKeyOptionVariable (\r
- NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL\r
- );\r
- ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);\r
- Status = EfiBootManagerAddKeyOptionVariable (\r
- NULL, (UINT16) BootOption.OptionNumber, 0, &Esc, NULL\r
- );\r
- ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-ConnectRootBridge (\r
- IN EFI_HANDLE RootBridgeHandle,\r
- IN VOID *Instance,\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
- VOID\r
- );\r
-\r
-//\r
-// BDS Platform Functions\r
-//\r
-/**\r
- Do the platform init, can be customized by OEM/IBV\r
-\r
- Possible things that can be done in PlatformBootManagerBeforeConsole:\r
-\r
- > Update console variable: 1. include hot-plug devices;\r
- > 2. Clear ConIn and add SOL for AMT\r
- > Register new Driver#### or Boot####\r
- > Register new Key####: e.g.: F12\r
- > Signal ReadyToLock event\r
- > Authentication action: 1. connect Auth devices;\r
- > 2. Identify auto logon user.\r
-**/\r
-VOID\r
-EFIAPI\r
-PlatformBootManagerBeforeConsole (\r
- VOID\r
- )\r
-{\r
- EFI_HANDLE Handle;\r
- EFI_STATUS Status;\r
-\r
- DEBUG ((DEBUG_INFO, "PlatformBootManagerBeforeConsole\n"));\r
- InstallDevicePathCallback ();\r
-\r
- VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid,\r
- ConnectRootBridge, NULL);\r
-\r
- //\r
- // Signal the ACPI platform driver that it can download QEMU ACPI tables.\r
- //\r
- EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid);\r
-\r
- //\r
- // We can't signal End-of-Dxe earlier than this. Namely, End-of-Dxe triggers\r
- // the preparation of S3 system information. That logic has a hard dependency\r
- // on the presence of the FACS ACPI table. Since our ACPI tables are only\r
- // installed after PCI enumeration completes, we must not trigger the S3 save\r
- // earlier, hence we can't signal End-of-Dxe earlier.\r
- //\r
- EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);\r
-\r
- //\r
- // Prevent further changes to LockBoxes or SMRAM.\r
- //\r
- Handle = NULL;\r
- Status = gBS->InstallProtocolInterface (&Handle,\r
- &gEfiDxeSmmReadyToLockProtocolGuid, EFI_NATIVE_INTERFACE,\r
- NULL);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- //\r
- // Dispatch deferred images after EndOfDxe event and ReadyToLock\r
- // installation.\r
- //\r
- EfiBootManagerDispatchDeferredImages ();\r
-\r
- PlatformInitializeConsole (gPlatformConsole);\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
-EFI_STATUS\r
-EFIAPI\r
-ConnectRootBridge (\r
- IN EFI_HANDLE RootBridgeHandle,\r
- IN VOID *Instance,\r
- IN VOID *Context\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- //\r
- // Make the PCI bus driver connect the root bridge, non-recursively. This\r
- // will produce a number of child handles with PciIo on them.\r
- //\r
- Status = gBS->ConnectController (\r
- RootBridgeHandle, // ControllerHandle\r
- NULL, // DriverImageHandle\r
- NULL, // RemainingDevicePath -- produce all\r
- // children\r
- FALSE // Recursive\r
- );\r
- return Status;\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
- @param[in] DeviceHandle Handle of the LPC Bridge device.\r
-\r
- @retval EFI_SUCCESS Console devices on the LPC bridge have been added to\r
- ConOut, ConIn, and ErrOut.\r
-\r
- @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing\r
- from DeviceHandle.\r
-**/\r
-EFI_STATUS\r
-PrepareLpcBridgeDevicePath (\r
- IN EFI_HANDLE DeviceHandle\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
- EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
- CHAR16 *DevPathStr;\r
-\r
- DevicePath = NULL;\r
- Status = gBS->HandleProtocol (\r
- DeviceHandle,\r
- &gEfiDevicePathProtocolGuid,\r
- (VOID*)&DevicePath\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- TempDevicePath = DevicePath;\r
-\r
- //\r
- // Register Keyboard\r
- //\r
- DevicePath = AppendDevicePathNode (DevicePath,\r
- (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);\r
-\r
- EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);\r
-\r
- //\r
- // Register COM1\r
- //\r
- DevicePath = TempDevicePath;\r
- gPnp16550ComPortDeviceNode.UID = 0;\r
-\r
- DevicePath = AppendDevicePathNode (DevicePath,\r
- (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);\r
- DevicePath = AppendDevicePathNode (DevicePath,\r
- (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r
- DevicePath = AppendDevicePathNode (DevicePath,\r
- (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r
-\r
- //\r
- // Print Device Path\r
- //\r
- DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);\r
- if (DevPathStr != NULL) {\r
- DEBUG((\r
- DEBUG_INFO,\r
- "BdsPlatform.c+%d: COM%d DevPath: %s\n",\r
- __LINE__,\r
- gPnp16550ComPortDeviceNode.UID + 1,\r
- DevPathStr\r
- ));\r
- FreePool(DevPathStr);\r
- }\r
-\r
- EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);\r
- EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);\r
- EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);\r
-\r
- // Don't register COM2 which can be used for DBG instead so keep it clean\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-GetGopDevicePath (\r
- IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,\r
- OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath\r
- )\r
-{\r
- UINTN Index;\r
- EFI_STATUS Status;\r
- EFI_HANDLE PciDeviceHandle;\r
- EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
- EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath;\r
- UINTN GopHandleCount;\r
- EFI_HANDLE *GopHandleBuffer;\r
-\r
- if (PciDevicePath == NULL || GopDevicePath == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // Initialize the GopDevicePath to be PciDevicePath\r
- //\r
- *GopDevicePath = PciDevicePath;\r
- TempPciDevicePath = PciDevicePath;\r
-\r
- Status = gBS->LocateDevicePath (\r
- &gEfiDevicePathProtocolGuid,\r
- &TempPciDevicePath,\r
- &PciDeviceHandle\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Try to connect this handle, so that GOP driver could start on this\r
- // device and create child handles with GraphicsOutput Protocol installed\r
- // on them, then we get device paths of these child handles and select\r
- // them as possible console device.\r
- //\r
- gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);\r
-\r
- Status = gBS->LocateHandleBuffer (\r
- ByProtocol,\r
- &gEfiGraphicsOutputProtocolGuid,\r
- NULL,\r
- &GopHandleCount,\r
- &GopHandleBuffer\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // Add all the child handles as possible Console Device\r
- //\r
- for (Index = 0; Index < GopHandleCount; Index++) {\r
- Status = gBS->HandleProtocol (GopHandleBuffer[Index],\r
- &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);\r
- if (EFI_ERROR (Status)) {\r
- continue;\r
- }\r
- if (CompareMem (\r
- PciDevicePath,\r
- TempDevicePath,\r
- GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH\r
- ) == 0) {\r
- //\r
- // In current implementation, we only enable one of the child handles\r
- // as console device, i.e. sotre one of the child handle's device\r
- // path to variable "ConOut"\r
- // In future, we could select all child handles to be console device\r
- //\r
-\r
- *GopDevicePath = TempDevicePath;\r
-\r
- //\r
- // Delete the PCI device's path that added by\r
- // GetPlugInPciVgaDevicePath(). Add the integrity GOP device path.\r
- //\r
- EfiBootManagerUpdateConsoleVariable (ConOutDev, NULL, PciDevicePath);\r
- EfiBootManagerUpdateConsoleVariable (ConOutDev, TempDevicePath, NULL);\r
- }\r
- }\r
- gBS->FreePool (GopHandleBuffer);\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Add PCI display to ConOut.\r
-\r
- @param[in] DeviceHandle Handle of the PCI display device.\r
-\r
- @retval EFI_SUCCESS The PCI display device has been added to ConOut.\r
-\r
- @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing\r
- from DeviceHandle.\r
-**/\r
-EFI_STATUS\r
-PreparePciDisplayDevicePath (\r
- IN EFI_HANDLE DeviceHandle\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
- EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;\r
-\r
- DevicePath = NULL;\r
- GopDevicePath = NULL;\r
- Status = gBS->HandleProtocol (\r
- DeviceHandle,\r
- &gEfiDevicePathProtocolGuid,\r
- (VOID*)&DevicePath\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- GetGopDevicePath (DevicePath, &GopDevicePath);\r
- DevicePath = GopDevicePath;\r
-\r
- EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Add PCI Serial to ConOut, ConIn, ErrOut.\r
-\r
- @param[in] DeviceHandle Handle of the PCI serial device.\r
-\r
- @retval EFI_SUCCESS The PCI serial device has been added to ConOut, ConIn,\r
- ErrOut.\r
-\r
- @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing\r
- from DeviceHandle.\r
-**/\r
-EFI_STATUS\r
-PreparePciSerialDevicePath (\r
- IN EFI_HANDLE DeviceHandle\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
-\r
- DevicePath = NULL;\r
- Status = gBS->HandleProtocol (\r
- DeviceHandle,\r
- &gEfiDevicePathProtocolGuid,\r
- (VOID*)&DevicePath\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- DevicePath = AppendDevicePathNode (DevicePath,\r
- (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r
- DevicePath = AppendDevicePathNode (DevicePath,\r
- (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r
-\r
- EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);\r
- EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);\r
- EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-VisitAllInstancesOfProtocol (\r
- IN EFI_GUID *Id,\r
- IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,\r
- IN VOID *Context\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN HandleCount;\r
- EFI_HANDLE *HandleBuffer;\r
- UINTN Index;\r
- VOID *Instance;\r
-\r
- //\r
- // Start to check all the PciIo to find all possible device\r
- //\r
- HandleCount = 0;\r
- HandleBuffer = NULL;\r
- Status = gBS->LocateHandleBuffer (\r
- ByProtocol,\r
- Id,\r
- NULL,\r
- &HandleCount,\r
- &HandleBuffer\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- for (Index = 0; Index < HandleCount; Index++) {\r
- Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);\r
- if (EFI_ERROR (Status)) {\r
- continue;\r
- }\r
-\r
- Status = (*CallBackFunction) (\r
- HandleBuffer[Index],\r
- Instance,\r
- Context\r
- );\r
- }\r
-\r
- gBS->FreePool (HandleBuffer);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-VisitingAPciInstance (\r
- IN EFI_HANDLE Handle,\r
- IN VOID *Instance,\r
- IN VOID *Context\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
- PCI_TYPE00 Pci;\r
-\r
- PciIo = (EFI_PCI_IO_PROTOCOL*) Instance;\r
-\r
- //\r
- // Check for all PCI device\r
- //\r
- Status = PciIo->Pci.Read (\r
- PciIo,\r
- EfiPciIoWidthUint32,\r
- 0,\r
- sizeof (Pci) / sizeof (UINT32),\r
- &Pci\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) (\r
- Handle,\r
- PciIo,\r
- &Pci\r
- );\r
-\r
-}\r
-\r
-\r
-\r
-EFI_STATUS\r
-VisitAllPciInstances (\r
- IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction\r
- )\r
-{\r
- return VisitAllInstancesOfProtocol (\r
- &gEfiPciIoProtocolGuid,\r
- VisitingAPciInstance,\r
- (VOID*)(UINTN) CallBackFunction\r
- );\r
-}\r
-\r
-\r
-/**\r
- Do platform specific PCI Device check and add them to\r
- ConOut, ConIn, ErrOut.\r
-\r
- @param[in] Handle - Handle of PCI device instance\r
- @param[in] PciIo - PCI IO protocol instance\r
- @param[in] Pci - PCI Header register block\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
-EFIAPI\r
-DetectAndPreparePlatformPciDevicePath (\r
- IN EFI_HANDLE Handle,\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN PCI_TYPE00 *Pci\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- Status = PciIo->Attributes (\r
- PciIo,\r
- EfiPciIoAttributeOperationEnable,\r
- EFI_PCI_DEVICE_ENABLE,\r
- NULL\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\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
- // Add IsaKeyboard to ConIn,\r
- // add IsaSerial to ConOut, ConIn, ErrOut\r
- //\r
- DEBUG ((DEBUG_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
- // Add them to ConOut, ConIn, ErrOut.\r
- //\r
- DEBUG ((DEBUG_INFO, "Found PCI 16550 SERIAL device\n"));\r
- PreparePciSerialDevicePath (Handle);\r
- return EFI_SUCCESS;\r
- }\r
-\r
- //\r
- // Here we decide which display device to enable in PCI bus\r
- //\r
- if (IS_PCI_DISPLAY (Pci)) {\r
- //\r
- // Add them to ConOut.\r
- //\r
- DEBUG ((DEBUG_INFO, "Found PCI display device\n"));\r
- PreparePciDisplayDevicePath (Handle);\r
- return EFI_SUCCESS;\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Connect the predefined platform default console device.\r
-\r
- Always try to find and enable PCI display devices.\r
-\r
- @param[in] PlatformConsole Predefined platform default console device array.\r
-**/\r
-VOID\r
-PlatformInitializeConsole (\r
- IN PLATFORM_CONSOLE_CONNECT_ENTRY *PlatformConsole\r
- )\r
-{\r
- UINTN Index;\r
-\r
- //\r
- // Do platform specific PCI Device check and add them to ConOut, ConIn,\r
- // ErrOut\r
- //\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
- // 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
- }\r
-}\r
-\r
-\r
-/**\r
- Configure PCI Interrupt Line register for applicable devices\r
- Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()\r
-\r
- @param[in] Handle - Handle of PCI device instance\r
- @param[in] PciIo - PCI IO protocol instance\r
- @param[in] PciHdr - PCI Header register block\r
-\r
- @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-SetPciIntLine (\r
- IN EFI_HANDLE Handle,\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN PCI_TYPE00 *PciHdr\r
- )\r
-{\r
- EFI_DEVICE_PATH_PROTOCOL *DevPathNode;\r
- EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
- UINTN RootSlot;\r
- UINTN Idx;\r
- UINT8 IrqLine;\r
- EFI_STATUS Status;\r
- UINT32 RootBusNumber;\r
-\r
- Status = EFI_SUCCESS;\r
-\r
- if (PciHdr->Device.InterruptPin != 0) {\r
-\r
- DevPathNode = DevicePathFromHandle (Handle);\r
- ASSERT (DevPathNode != NULL);\r
- DevPath = DevPathNode;\r
-\r
- RootBusNumber = 0;\r
- if (DevicePathType (DevPathNode) == ACPI_DEVICE_PATH &&\r
- DevicePathSubType (DevPathNode) == ACPI_DP &&\r
- ((ACPI_HID_DEVICE_PATH *)DevPathNode)->HID == EISA_PNP_ID(0x0A03)) {\r
- RootBusNumber = ((ACPI_HID_DEVICE_PATH *)DevPathNode)->UID;\r
- }\r
-\r
- //\r
- // Compute index into PciHostIrqs[] table by walking\r
- // the device path and adding up all device numbers\r
- //\r
- Status = EFI_NOT_FOUND;\r
- RootSlot = 0;\r
- Idx = PciHdr->Device.InterruptPin - 1;\r
- while (!IsDevicePathEnd (DevPathNode)) {\r
- if (DevicePathType (DevPathNode) == HARDWARE_DEVICE_PATH &&\r
- DevicePathSubType (DevPathNode) == HW_PCI_DP) {\r
-\r
- Idx += ((PCI_DEVICE_PATH *)DevPathNode)->Device;\r
-\r
- //\r
- // Unlike SeaBIOS, which starts climbing from the leaf device\r
- // up toward the root, we traverse the device path starting at\r
- // the root moving toward the leaf node.\r
- // The slot number of the top-level parent bridge is needed for\r
- // Q35 cases with more than 24 slots on the root bus.\r
- //\r
- if (Status != EFI_SUCCESS) {\r
- Status = EFI_SUCCESS;\r
- RootSlot = ((PCI_DEVICE_PATH *)DevPathNode)->Device;\r
- }\r
- }\r
-\r
- DevPathNode = NextDevicePathNode (DevPathNode);\r
- }\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- if (RootBusNumber == 0 && RootSlot == 0) {\r
- DEBUG((\r
- DEBUG_ERROR,\r
- "%a: PCI host bridge (00:00.0) should have no interrupts!\n",\r
- __FUNCTION__\r
- ));\r
- ASSERT (FALSE);\r
- }\r
-\r
- //\r
- // Final PciHostIrqs[] index calculation depends on the platform\r
- // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()\r
- //\r
- switch (mHostBridgeDevId) {\r
- case 0x1275: // BHYVE\r
- case INTEL_82441_DEVICE_ID:\r
- Idx -= 1;\r
- break;\r
- case INTEL_Q35_MCH_DEVICE_ID:\r
- //\r
- // SeaBIOS contains the following comment:\r
- // "Slots 0-24 rotate slot:pin mapping similar to piix above, but\r
- // with a different starting index - see q35-acpi-dsdt.dsl.\r
- //\r
- // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"\r
- //\r
- if (RootSlot > 24) {\r
- //\r
- // in this case, subtract back out RootSlot from Idx\r
- // (SeaBIOS never adds it to begin with, but that would make our\r
- // device path traversal loop above too awkward)\r
- //\r
- Idx -= RootSlot;\r
- }\r
- break;\r
- default:\r
- ASSERT (FALSE); // should never get here\r
- }\r
- Idx %= ARRAY_SIZE (PciHostIrqs);\r
- IrqLine = PciHostIrqs[Idx];\r
-\r
- DEBUG_CODE_BEGIN ();\r
- {\r
- CHAR16 *DevPathString;\r
- STATIC CHAR16 Fallback[] = L"<failed to convert>";\r
- UINTN Segment, Bus, Device, Function;\r
-\r
- DevPathString = ConvertDevicePathToText (DevPath, FALSE, FALSE);\r
- if (DevPathString == NULL) {\r
- DevPathString = Fallback;\r
- }\r
- Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- DEBUG ((DEBUG_VERBOSE, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__,\r
- (UINT32)Bus, (UINT32)Device, (UINT32)Function, DevPathString,\r
- IrqLine));\r
-\r
- if (DevPathString != Fallback) {\r
- FreePool (DevPathString);\r
- }\r
- }\r
- DEBUG_CODE_END ();\r
-\r
- //\r
- // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]\r
- //\r
- Status = PciIo->Pci.Write (\r
- PciIo,\r
- EfiPciIoWidthUint8,\r
- PCI_INT_LINE_OFFSET,\r
- 1,\r
- &IrqLine\r
- );\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-\r
-VOID\r
-PciAcpiInitialization (\r
- )\r
-{\r
- UINTN Pmba;\r
-\r
- //\r
- // Query Host Bridge DID to determine platform type\r
- //\r
- mHostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId);\r
- switch (mHostBridgeDevId) {\r
- case 0x1275: // BHYVE\r
- case INTEL_82441_DEVICE_ID:\r
- Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);\r
- //\r
- // 00:01.0 ISA Bridge (PIIX4) LNK routing targets\r
- //\r
- PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A\r
- PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B\r
- PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C\r
- PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D\r
- break;\r
- case INTEL_Q35_MCH_DEVICE_ID:\r
- Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);\r
- //\r
- // 00:1f.0 LPC Bridge (Q35) LNK routing targets\r
- //\r
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A\r
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B\r
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C\r
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D\r
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E\r
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F\r
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G\r
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H\r
- break;\r
- default:\r
- DEBUG ((DEBUG_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",\r
- __FUNCTION__, mHostBridgeDevId));\r
- ASSERT (FALSE);\r
- return;\r
- }\r
-\r
- //\r
- // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices\r
- //\r
- VisitAllPciInstances (SetPciIntLine);\r
-\r
- //\r
- // Set ACPI SCI_EN bit in PMCNTRL\r
- //\r
- IoOr16 ((PciRead32 (Pmba) & ~BIT0) + 4, BIT0);\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-ConnectRecursivelyIfPciMassStorage (\r
- IN EFI_HANDLE Handle,\r
- IN EFI_PCI_IO_PROTOCOL *Instance,\r
- IN PCI_TYPE00 *PciHeader\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
- CHAR16 *DevPathStr;\r
-\r
- //\r
- // Recognize PCI Mass Storage, and Xen PCI devices\r
- //\r
- if (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE)) {\r
- DevicePath = NULL;\r
- Status = gBS->HandleProtocol (\r
- Handle,\r
- &gEfiDevicePathProtocolGuid,\r
- (VOID*)&DevicePath\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Print Device Path\r
- //\r
- DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);\r
- if (DevPathStr != NULL) {\r
- DEBUG((\r
- DEBUG_INFO,\r
- "Found %s device: %s\n",\r
- (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE) ?\r
- L"Mass Storage" :\r
- L"Xen"\r
- ),\r
- DevPathStr\r
- ));\r
- FreePool(DevPathStr);\r
- }\r
-\r
- Status = gBS->ConnectController (Handle, NULL, NULL, TRUE);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- This notification function is invoked when the\r
- EMU Variable FVB has been changed.\r
-\r
- @param Event The event that occurred\r
- @param Context For EFI compatibility. Not used.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-EmuVariablesUpdatedCallback (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-{\r
- DEBUG ((DEBUG_INFO, "EmuVariablesUpdatedCallback\n"));\r
- UpdateNvVarsOnFileSystem ();\r
-}\r
-\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-VisitingFileSystemInstance (\r
- IN EFI_HANDLE Handle,\r
- IN VOID *Instance,\r
- IN VOID *Context\r
- )\r
-{\r
- EFI_STATUS Status;\r
- STATIC BOOLEAN ConnectedToFileSystem = FALSE;\r
- RETURN_STATUS PcdStatus;\r
-\r
- if (ConnectedToFileSystem) {\r
- return EFI_ALREADY_STARTED;\r
- }\r
-\r
- Status = ConnectNvVarsToFileSystem (Handle);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- ConnectedToFileSystem = TRUE;\r
- mEmuVariableEvent =\r
- EfiCreateProtocolNotifyEvent (\r
- &gEfiDevicePathProtocolGuid,\r
- TPL_CALLBACK,\r
- EmuVariablesUpdatedCallback,\r
- NULL,\r
- &mEmuVariableEventReg\r
- );\r
- PcdStatus = PcdSet64S (PcdEmuVariableEvent,\r
- (UINT64)(UINTN) mEmuVariableEvent);\r
- ASSERT_RETURN_ERROR (PcdStatus);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-VOID\r
-PlatformBdsRestoreNvVarsFromHardDisk (\r
- )\r
-{\r
- VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage);\r
- VisitAllInstancesOfProtocol (\r
- &gEfiSimpleFileSystemProtocolGuid,\r
- VisitingFileSystemInstance,\r
- NULL\r
- );\r
-\r
-}\r
-\r
-/**\r
- Connect with predefined platform connect sequence.\r
-\r
- The OEM/IBV can customize with their own connect sequence.\r
-**/\r
-VOID\r
-PlatformBdsConnectSequence (\r
- VOID\r
- )\r
-{\r
- UINTN Index;\r
-\r
- DEBUG ((DEBUG_INFO, "PlatformBdsConnectSequence\n"));\r
-\r
- Index = 0;\r
-\r
- //\r
- // Here we can get the customized platform connect sequence\r
- // Notes: we can connect with new variable which record the\r
- // last time boots connect device path sequence\r
- //\r
- while (gPlatformConnectSequence[Index] != NULL) {\r
- //\r
- // Build the platform boot option\r
- //\r
- EfiBootManagerConnectDevicePath (gPlatformConnectSequence[Index], NULL);\r
- Index++;\r
- }\r
-\r
- //\r
- // Just use the simple policy to connect all devices\r
- //\r
- DEBUG ((DEBUG_INFO, "EfiBootManagerConnectAll\n"));\r
- EfiBootManagerConnectAll ();\r
-}\r
-\r
-/**\r
- Save the S3 boot script.\r
-\r
- Note that DxeSmmReadyToLock must be signaled after this function returns;\r
- otherwise the script wouldn't be saved actually.\r
-**/\r
-#if defined(__GNUC__)\r
-__attribute__((unused))\r
-#endif\r
-STATIC\r
-VOID\r
-SaveS3BootScript (\r
- VOID\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_S3_SAVE_STATE_PROTOCOL *BootScript;\r
- STATIC CONST UINT8 Info[] = { 0xDE, 0xAD, 0xBE, 0xEF };\r
-\r
- Status = gBS->LocateProtocol (&gEfiS3SaveStateProtocolGuid, NULL,\r
- (VOID **) &BootScript);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- //\r
- // Despite the opcode documentation in the PI spec, the protocol\r
- // implementation embeds a deep copy of the info in the boot script, rather\r
- // than storing just a pointer to runtime or NVS storage.\r
- //\r
- Status = BootScript->Write(BootScript, EFI_BOOT_SCRIPT_INFORMATION_OPCODE,\r
- (UINT32) sizeof Info,\r
- (EFI_PHYSICAL_ADDRESS)(UINTN) &Info);\r
- ASSERT_EFI_ERROR (Status);\r
-}\r
-\r
-\r
-/**\r
- Do the platform specific action after the console is ready\r
-\r
- Possible things that can be done in PlatformBootManagerAfterConsole:\r
-\r
- > Console post action:\r
- > Dynamically switch output mode from 100x31 to 80x25 for certain senarino\r
- > Signal console ready platform customized event\r
- > Run diagnostics like memory testing\r
- > Connect certain devices\r
- > Dispatch aditional option roms\r
- > Special boot: e.g.: USB boot, enter UI\r
-**/\r
-VOID\r
-EFIAPI\r
-PlatformBootManagerAfterConsole (\r
- VOID\r
- )\r
-{\r
- EFI_BOOT_MODE BootMode;\r
-\r
- DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole\n"));\r
-\r
- if (PcdGetBool (PcdOvmfFlashVariablesEnable)) {\r
- DEBUG ((DEBUG_INFO, "PlatformBdsPolicyBehavior: not restoring NvVars "\r
- "from disk since flash variables appear to be supported.\n"));\r
- } else {\r
- //\r
- // Try to restore variables from the hard disk early so\r
- // they can be used for the other BDS connect operations.\r
- //\r
- /* XXX Calling this causes Keyboard to be removed from ConIn which\r
- results in unresponsive guest boot loaders in the GUI. Restore it\r
- when we figure out what is needed to get NvVars storage done\r
- properly.\r
- */\r
- /*PlatformBdsRestoreNvVarsFromHardDisk ();*/\r
- }\r
-\r
- //\r
- // Get current Boot Mode\r
- //\r
- BootMode = GetBootModeHob ();\r
- DEBUG ((DEBUG_INFO, "Boot Mode:%x\n", BootMode));\r
-\r
- //\r
- // Go the different platform policy with different boot mode\r
- // Notes: this part code can be change with the table policy\r
- //\r
- ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);\r
-\r
- //\r
- // Logo show\r
- //\r
- BootLogoEnableLogo ();\r
-\r
- //\r
- // Set PCI Interrupt Line registers and ACPI SCI_EN\r
- //\r
- PciAcpiInitialization ();\r
-\r
- //\r
- // Process TPM PPI request\r
- //\r
- Tcg2PhysicalPresenceLibProcessRequest (NULL);\r
-\r
- //\r
- // Perform some platform specific connect sequence\r
- //\r
- PlatformBdsConnectSequence ();\r
-\r
- EfiBootManagerRefreshAllBootOption ();\r
-\r
- //\r
- // Register UEFI Shell\r
- //\r
- PlatformRegisterFvBootOption (\r
- &gUefiShellFileGuid, L"EFI Internal Shell", LOAD_OPTION_ACTIVE\r
- );\r
-\r
- RemoveStaleFvFileOptions ();\r
-\r
- PlatformBmPrintScRegisterHandler ();\r
-}\r
-\r
-/**\r
- This notification function is invoked when an instance of the\r
- EFI_DEVICE_PATH_PROTOCOL is produced.\r
-\r
- @param Event The event that occurred\r
- @param Context For EFI compatibility. Not used.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-NotifyDevPath (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-{\r
- EFI_HANDLE Handle;\r
- EFI_STATUS Status;\r
- UINTN BufferSize;\r
- EFI_DEVICE_PATH_PROTOCOL *DevPathNode;\r
- ATAPI_DEVICE_PATH *Atapi;\r
-\r
- //\r
- // Examine all new handles\r
- //\r
- for (;;) {\r
- //\r
- // Get the next handle\r
- //\r
- BufferSize = sizeof (Handle);\r
- Status = gBS->LocateHandle (\r
- ByRegisterNotify,\r
- NULL,\r
- mEfiDevPathNotifyReg,\r
- &BufferSize,\r
- &Handle\r
- );\r
-\r
- //\r
- // If not found, we're done\r
- //\r
- if (EFI_NOT_FOUND == Status) {\r
- break;\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- continue;\r
- }\r
-\r
- //\r
- // Get the DevicePath protocol on that handle\r
- //\r
- Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid,\r
- (VOID **)&DevPathNode);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- while (!IsDevicePathEnd (DevPathNode)) {\r
- //\r
- // Find the handler to dump this device path node\r
- //\r
- if (\r
- (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) &&\r
- (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP)\r
- ) {\r
- Atapi = (ATAPI_DEVICE_PATH*) DevPathNode;\r
- PciOr16 (\r
- PCI_LIB_ADDRESS (\r
- 0,\r
- 1,\r
- 1,\r
- (Atapi->PrimarySecondary == 1) ? 0x42: 0x40\r
- ),\r
- BIT15\r
- );\r
- }\r
-\r
- //\r
- // Next device path node\r
- //\r
- DevPathNode = NextDevicePathNode (DevPathNode);\r
- }\r
- }\r
-\r
- return;\r
-}\r
-\r
-\r
-VOID\r
-InstallDevicePathCallback (\r
- VOID\r
- )\r
-{\r
- DEBUG ((DEBUG_INFO, "Registered NotifyDevPath Event\n"));\r
- mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (\r
- &gEfiDevicePathProtocolGuid,\r
- TPL_CALLBACK,\r
- NotifyDevPath,\r
- NULL,\r
- &mEfiDevPathNotifyReg\r
- );\r
-}\r
-\r
-/**\r
- This function is called each second during the boot manager waits the\r
- timeout.\r
-\r
- @param TimeoutRemain The remaining timeout.\r
-**/\r
-VOID\r
-EFIAPI\r
-PlatformBootManagerWaitCallback (\r
- UINT16 TimeoutRemain\r
- )\r
-{\r
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black;\r
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White;\r
- UINT16 Timeout;\r
-\r
- Timeout = PcdGet16 (PcdPlatformBootTimeOut);\r
-\r
- Black.Raw = 0x00000000;\r
- White.Raw = 0x00FFFFFF;\r
-\r
- BootLogoUpdateProgress (\r
- White.Pixel,\r
- Black.Pixel,\r
- L"Start boot option",\r
- White.Pixel,\r
- (Timeout - TimeoutRemain) * 100 / Timeout,\r
- 0\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
+++ /dev/null
-/** @file\r
- Platform BDS customizations include file.\r
-\r
- Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>\r
- Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
- SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-Module Name:\r
-\r
- BdsPlatform.h\r
-\r
-Abstract:\r
-\r
- Head file for BDS Platform specific code\r
-\r
-**/\r
-\r
-#ifndef _PLATFORM_SPECIFIC_BDS_PLATFORM_H_\r
-#define _PLATFORM_SPECIFIC_BDS_PLATFORM_H_\r
-\r
-\r
-#include <PiDxe.h>\r
-\r
-#include <IndustryStandard/Pci.h>\r
-#include <IndustryStandard/Acpi.h>\r
-#include <IndustryStandard/SmBios.h>\r
-#include <IndustryStandard/PeImage.h>\r
-#include <IndustryStandard/Virtio095.h>\r
-\r
-#include <Library/DebugLib.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/UefiRuntimeServicesTableLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Library/BaseLib.h>\r
-#include <Library/PcdLib.h>\r
-#include <Library/PciLib.h>\r
-#include <Library/UefiBootManagerLib.h>\r
-#include <Library/BootLogoLib.h>\r
-#include <Library/HobLib.h>\r
-#include <Library/UefiLib.h>\r
-#include <Library/DxeServicesTableLib.h>\r
-#include <Library/DevicePathLib.h>\r
-#include <Library/IoLib.h>\r
-#include <Library/NvVarsFileLib.h>\r
-#include <Library/QemuFwCfgLib.h>\r
-#include <Library/QemuFwCfgS3Lib.h>\r
-#include <Library/QemuBootOrderLib.h>\r
-\r
-#include <Protocol/Decompress.h>\r
-#include <Protocol/PciIo.h>\r
-#include <Protocol/FirmwareVolume2.h>\r
-#include <Protocol/SimpleFileSystem.h>\r
-#include <Protocol/PciRootBridgeIo.h>\r
-#include <Protocol/S3SaveState.h>\r
-#include <Protocol/DxeSmmReadyToLock.h>\r
-#include <Protocol/LoadedImage.h>\r
-\r
-#include <Guid/Acpi.h>\r
-#include <Guid/SmBios.h>\r
-#include <Guid/HobList.h>\r
-#include <Guid/GlobalVariable.h>\r
-#include <Guid/EventGroup.h>\r
-#include <Guid/DebugAgentGuid.h>\r
-\r
-#include <OvmfPlatforms.h>\r
-\r
-extern EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence[];\r
-extern ACPI_HID_DEVICE_PATH gPnpPs2KeyboardDeviceNode;\r
-extern ACPI_HID_DEVICE_PATH gPnp16550ComPortDeviceNode;\r
-extern UART_DEVICE_PATH gUartDeviceNode;\r
-extern VENDOR_DEVICE_PATH gTerminalTypeDeviceNode;\r
-\r
-#define PCI_DEVICE_PATH_NODE(Func, Dev) \\r
- { \\r
- { \\r
- HARDWARE_DEVICE_PATH, \\r
- HW_PCI_DP, \\r
- { \\r
- (UINT8) (sizeof (PCI_DEVICE_PATH)), \\r
- (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) \\r
- } \\r
- }, \\r
- (Func), \\r
- (Dev) \\r
- }\r
-\r
-#define PNPID_DEVICE_PATH_NODE(PnpId) \\r
- { \\r
- { \\r
- ACPI_DEVICE_PATH, \\r
- ACPI_DP, \\r
- { \\r
- (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \\r
- (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \\r
- }, \\r
- }, \\r
- EISA_PNP_ID((PnpId)), \\r
- 0 \\r
- }\r
-\r
-#define gPciIsaBridge \\r
- PCI_DEVICE_PATH_NODE(0, 0x1f)\r
-\r
-#define gP2PBridge \\r
- PCI_DEVICE_PATH_NODE(0, 0x1e)\r
-\r
-#define gPnpPs2Keyboard \\r
- PNPID_DEVICE_PATH_NODE(0x0303)\r
-\r
-#define gPnp16550ComPort \\r
- PNPID_DEVICE_PATH_NODE(0x0501)\r
-\r
-#define gUart \\r
- { \\r
- { \\r
- MESSAGING_DEVICE_PATH, \\r
- MSG_UART_DP, \\r
- { \\r
- (UINT8) (sizeof (UART_DEVICE_PATH)), \\r
- (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8) \\r
- } \\r
- }, \\r
- 0, \\r
- 115200, \\r
- 8, \\r
- 1, \\r
- 1 \\r
- }\r
-\r
-#define gPcAnsiTerminal \\r
- { \\r
- { \\r
- MESSAGING_DEVICE_PATH, \\r
- MSG_VENDOR_DP, \\r
- { \\r
- (UINT8) (sizeof (VENDOR_DEVICE_PATH)), \\r
- (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) \\r
- } \\r
- }, \\r
- DEVICE_PATH_MESSAGING_PC_ANSI \\r
- }\r
-\r
-#define gEndEntire \\r
- { \\r
- END_DEVICE_PATH_TYPE, \\r
- END_ENTIRE_DEVICE_PATH_SUBTYPE, \\r
- { \\r
- END_DEVICE_PATH_LENGTH, \\r
- 0 \\r
- } \\r
- }\r
-\r
-#define PCI_CLASS_SCC 0x07\r
-#define PCI_SUBCLASS_SERIAL 0x00\r
-#define PCI_IF_16550 0x02\r
-#define IS_PCI_16550SERIAL(_p) IS_CLASS3 (_p, PCI_CLASS_SCC, PCI_SUBCLASS_SERIAL, PCI_IF_16550)\r
-#define IS_PCI_ISA_PDECODE(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE, 0)\r
-\r
-typedef struct {\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
- UINTN ConnectType;\r
-} PLATFORM_CONSOLE_CONNECT_ENTRY;\r
-\r
-#define CONSOLE_OUT BIT0\r
-#define CONSOLE_IN BIT1\r
-#define STD_ERROR BIT2\r
-extern PLATFORM_CONSOLE_CONNECT_ENTRY gPlatformConsole[];\r
-\r
-//\r
-// Platform BDS Functions\r
-//\r
-\r
-VOID\r
-PlatformInitializeConsole (\r
- IN PLATFORM_CONSOLE_CONNECT_ENTRY *PlatformConsole\r
- );\r
-\r
-/**\r
- Loads and boots UEFI Linux via the FwCfg interface.\r
-\r
- @retval EFI_NOT_FOUND - The Linux kernel was not found\r
-\r
-**/\r
-EFI_STATUS\r
-TryRunningQemuKernel (\r
- VOID\r
- );\r
-\r
-#endif // _PLATFORM_SPECIFIC_BDS_PLATFORM_H_\r
+++ /dev/null
-## @file\r
-# Platform BDS customizations library.\r
-#\r
-# Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>\r
-# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
-#\r
-# SPDX-License-Identifier: BSD-2-Clause-Patent\r
-#\r
-##\r
-\r
-[Defines]\r
- INF_VERSION = 0x00010005\r
- BASE_NAME = PlatformBootManagerLib\r
- FILE_GUID = b0de5f0d-f676-42da-8d00-86997ee0dbb4\r
- MODULE_TYPE = DXE_DRIVER\r
- VERSION_STRING = 1.0\r
- LIBRARY_CLASS = PlatformBootManagerLib|DXE_DRIVER\r
-\r
-#\r
-# The following information is for reference only and not required by the build tools.\r
-#\r
-# VALID_ARCHITECTURES = IA32 X64 EBC\r
-#\r
-\r
-[Sources]\r
- BdsPlatform.c\r
- PlatformData.c\r
- BdsPlatform.h\r
-\r
-[Packages]\r
- MdePkg/MdePkg.dec\r
- MdeModulePkg/MdeModulePkg.dec\r
- SourceLevelDebugPkg/SourceLevelDebugPkg.dec\r
- OvmfPkg/OvmfPkg.dec\r
- SecurityPkg/SecurityPkg.dec\r
- ShellPkg/ShellPkg.dec\r
-\r
-[LibraryClasses]\r
- BaseLib\r
- MemoryAllocationLib\r
- UefiBootServicesTableLib\r
- BaseMemoryLib\r
- DebugLib\r
- PcdLib\r
- UefiBootManagerLib\r
- BootLogoLib\r
- DevicePathLib\r
- PciLib\r
- NvVarsFileLib\r
- ReportStatusCodeLib\r
- UefiLib\r
- PlatformBmPrintScLib\r
- Tcg2PhysicalPresenceLib\r
-\r
-[Pcd]\r
- gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent\r
- gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable\r
- gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId\r
- gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut\r
-\r
-[Pcd.IA32, Pcd.X64]\r
- gEfiMdePkgTokenSpaceGuid.PcdFSBClock\r
-\r
-[Protocols]\r
- gEfiDecompressProtocolGuid\r
- gEfiPciRootBridgeIoProtocolGuid\r
- gEfiS3SaveStateProtocolGuid # PROTOCOL SOMETIMES_CONSUMED\r
- gEfiDxeSmmReadyToLockProtocolGuid # PROTOCOL SOMETIMES_PRODUCED\r
- gEfiLoadedImageProtocolGuid # PROTOCOL SOMETIMES_PRODUCED\r
- gEfiFirmwareVolume2ProtocolGuid # PROTOCOL SOMETIMES_CONSUMED\r
-\r
-[Guids]\r
- gEfiEndOfDxeEventGroupGuid\r
- gRootBridgesConnectedEventGroupGuid\r
- gUefiShellFileGuid\r
+++ /dev/null
-/** @file\r
- Defined the platform specific device path which will be used by\r
- platform Bbd to perform the platform policy connect.\r
-\r
- Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>\r
- Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>\r
- SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include "BdsPlatform.h"\r
-#include <Guid/QemuRamfb.h>\r
-\r
-//\r
-// Debug Agent UART Device Path structure\r
-//\r
-#pragma pack(1)\r
-typedef struct {\r
- VENDOR_DEVICE_PATH VendorHardware;\r
- UART_DEVICE_PATH Uart;\r
- VENDOR_DEVICE_PATH TerminalType;\r
- EFI_DEVICE_PATH_PROTOCOL End;\r
-} VENDOR_UART_DEVICE_PATH;\r
-#pragma pack()\r
-\r
-//\r
-// USB Keyboard Device Path structure\r
-//\r
-#pragma pack (1)\r
-typedef struct {\r
- USB_CLASS_DEVICE_PATH Keyboard;\r
- EFI_DEVICE_PATH_PROTOCOL End;\r
-} USB_KEYBOARD_DEVICE_PATH;\r
-#pragma pack ()\r
-\r
-//\r
-// QemuRamfb Device Path structure\r
-//\r
-#pragma pack (1)\r
-typedef struct {\r
- VENDOR_DEVICE_PATH Vendor;\r
- ACPI_ADR_DEVICE_PATH AcpiAdr;\r
- EFI_DEVICE_PATH_PROTOCOL End;\r
-} VENDOR_RAMFB_DEVICE_PATH;\r
-#pragma pack ()\r
-\r
-ACPI_HID_DEVICE_PATH gPnpPs2KeyboardDeviceNode = gPnpPs2Keyboard;\r
-ACPI_HID_DEVICE_PATH gPnp16550ComPortDeviceNode = gPnp16550ComPort;\r
-UART_DEVICE_PATH gUartDeviceNode = gUart;\r
-VENDOR_DEVICE_PATH gTerminalTypeDeviceNode = gPcAnsiTerminal;\r
-\r
-//\r
-// Platform specific keyboard device path\r
-//\r
-\r
-\r
-//\r
-// Debug Agent UART Device Path\r
-//\r
-VENDOR_UART_DEVICE_PATH gDebugAgentUartDevicePath = {\r
- {\r
- {\r
- HARDWARE_DEVICE_PATH,\r
- HW_VENDOR_DP,\r
- {\r
- (UINT8) (sizeof (VENDOR_DEVICE_PATH)),\r
- (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
- }\r
- },\r
- EFI_DEBUG_AGENT_GUID,\r
- },\r
- {\r
- {\r
- MESSAGING_DEVICE_PATH,\r
- MSG_UART_DP,\r
- {\r
- (UINT8) (sizeof (UART_DEVICE_PATH)),\r
- (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8)\r
- }\r
- },\r
- 0, // Reserved\r
- 0, // BaudRate - Default\r
- 0, // DataBits - Default\r
- 0, // Parity - Default\r
- 0, // StopBits - Default\r
- },\r
- gPcAnsiTerminal,\r
- gEndEntire\r
-};\r
-\r
-STATIC USB_KEYBOARD_DEVICE_PATH gUsbKeyboardDevicePath = {\r
- {\r
- {\r
- MESSAGING_DEVICE_PATH,\r
- MSG_USB_CLASS_DP,\r
- {\r
- (UINT8)sizeof (USB_CLASS_DEVICE_PATH),\r
- (UINT8)(sizeof (USB_CLASS_DEVICE_PATH) >> 8)\r
- }\r
- },\r
- 0xFFFF, // VendorId: any\r
- 0xFFFF, // ProductId: any\r
- 3, // DeviceClass: HID\r
- 1, // DeviceSubClass: boot\r
- 1 // DeviceProtocol: keyboard\r
- },\r
- gEndEntire\r
-};\r
-\r
-STATIC VENDOR_RAMFB_DEVICE_PATH gQemuRamfbDevicePath = {\r
- {\r
- {\r
- HARDWARE_DEVICE_PATH,\r
- HW_VENDOR_DP,\r
- {\r
- (UINT8) (sizeof (VENDOR_DEVICE_PATH)),\r
- (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
- }\r
- },\r
- QEMU_RAMFB_GUID,\r
- },\r
- {\r
- {\r
- ACPI_DEVICE_PATH,\r
- ACPI_ADR_DP,\r
- {\r
- (UINT8) (sizeof (ACPI_ADR_DEVICE_PATH)),\r
- (UINT8) ((sizeof (ACPI_ADR_DEVICE_PATH)) >> 8)\r
- }\r
- },\r
- ACPI_DISPLAY_ADR (\r
- 1, // DeviceIdScheme\r
- 0, // HeadId\r
- 0, // NonVgaOutput\r
- 1, // BiosCanDetect\r
- 0, // VendorInfo\r
- ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL, // Type\r
- 0, // Port\r
- 0 // Index\r
- ),\r
- },\r
- gEndEntire\r
-};\r
-\r
-//\r
-// Predefined platform default console device path\r
-//\r
-PLATFORM_CONSOLE_CONNECT_ENTRY gPlatformConsole[] = {\r
- {\r
- (EFI_DEVICE_PATH_PROTOCOL *) &gDebugAgentUartDevicePath,\r
- (CONSOLE_OUT | CONSOLE_IN | STD_ERROR)\r
- },\r
- {\r
- (EFI_DEVICE_PATH_PROTOCOL *)&gUsbKeyboardDevicePath,\r
- CONSOLE_IN\r
- },\r
- {\r
- (EFI_DEVICE_PATH_PROTOCOL *)&gQemuRamfbDevicePath,\r
- CONSOLE_OUT\r
- },\r
- {\r
- NULL,\r
- 0\r
- }\r
-};\r
-\r
-//\r
-// Predefined platform connect sequence\r
-//\r
-EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence[] = { NULL };\r
-\r
--- /dev/null
+/** @file\r
+ bhyve firmware configuration access\r
+\r
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>\r
+ Copyright (c) 2015 Nahanni Systems\r
+\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#ifndef __BHYVE_FW_CTL_LIB__\r
+#define __BHYVE_FW_CTL_LIB__\r
+\r
+/**\r
+ Sysctl-like interface to read host information via a dot-separated\r
+ ASCII OID.\r
+\r
+ The information is copied into the buffer specified by Item. The\r
+ size of the buffer is given by the location specified by Size\r
+ before the call, and that location gives the amount of data copied\r
+ after a successfull call, and after a call that returns a truncated\r
+ value with an error return of RETURN_BUFFER_TOO_SMALL.\r
+\r
+ The size of the available data can be determined by passing a NULL\r
+ argument for Item. The size will be returned in the location pointed\r
+ to by Size.\r
+\r
+ @param[] Name - ASCII OID name\r
+ @param[] Data - return buffer pointer\r
+ @param[] Size - pointer to length\r
+\r
+ @return RETURN_SUCCESS Valid data/len returned.\r
+ RETURN_UNSUPPORTED f/w interface not present.\r
+ RETURN_NOT_FOUND OID not found.\r
+ RETURN_BUFFER_TOO_SMALL Return message truncated.\r
+ RETURN_INVALID_PARAMETER Buffer too large\r
+ RETURN_PROTOCOL_ERROR Unknown error from host\r
+ **/\r
+RETURN_STATUS\r
+EFIAPI\r
+BhyveFwCtlGet (\r
+ IN CONST CHAR8 *Name,\r
+ OUT VOID *Item,\r
+ IN OUT UINTN *Size\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+\r
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>\r
+ Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (C) 2013, Red Hat, Inc.\r
+ Copyright (c) 2015, Nahanni Systems.\r
+\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include "Uefi.h"\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/BhyveFwCtlLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+\r
+#define FW_PORT 0x510\r
+#define FW_IPORT 0x511\r
+\r
+/* Transport protocol basic operations */\r
+#define OP_NULL 1\r
+#define OP_ECHO 2\r
+#define OP_GET 3\r
+#define OP_GET_LEN 4\r
+#define OP_SET 5\r
+\r
+/* Transport protocol error returns */\r
+#define T_ESUCCESS 0\r
+#define T_ENOENT 2\r
+#define T_E2BIG 7\r
+#define T_EMSGSIZE 40\r
+\r
+#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y))\r
+\r
+STATIC CONST CHAR8 mBhyveSig[4] = { 'B', 'H', 'Y', 'V' };\r
+\r
+STATIC BOOLEAN mBhyveFwCtlSupported = FALSE;\r
+\r
+STATIC INTN mBhyveFwCtlTxid = 0xa5;\r
+\r
+/* XXX Maybe a better inbuilt version of this ? */\r
+struct BIoVec {\r
+ VOID *Base;\r
+ UINTN Len;\r
+};\r
+\r
+struct MsgRxHdr {\r
+ UINT32 Sz;\r
+ UINT32 Op;\r
+ UINT32 TxId;\r
+ UINT32 Err;\r
+};\r
+\r
+STATIC\r
+RETURN_STATUS\r
+EFIAPI\r
+BhyveFwCtl_CvtErr (\r
+ IN UINT32 errno\r
+ )\r
+{\r
+ RETURN_STATUS Status;\r
+\r
+ switch (errno) {\r
+ case T_ESUCCESS:\r
+ Status = RETURN_SUCCESS;\r
+ break;\r
+ case T_ENOENT:\r
+ Status = RETURN_NOT_FOUND;\r
+ break;\r
+ case T_E2BIG:\r
+ Status = RETURN_INVALID_PARAMETER;\r
+ break;\r
+ case T_EMSGSIZE:\r
+ Status = RETURN_BUFFER_TOO_SMALL;\r
+ break;\r
+ default:\r
+ Status = RETURN_PROTOCOL_ERROR;\r
+ break;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+STATIC\r
+UINTN\r
+EFIAPI\r
+BIov_WLen (\r
+ IN struct BIoVec b[]\r
+ )\r
+{\r
+ UINTN i;\r
+ UINTN tLen;\r
+\r
+ tLen = 0;\r
+\r
+ if (b != NULL) {\r
+ for (i = 0; b[i].Base != NULL; i++)\r
+ tLen += ROUNDUP (b[i].Len, sizeof(UINT32));\r
+ }\r
+\r
+ return tLen;\r
+}\r
+\r
+/**\r
+ Utility to send 1-3 bhyes of input as a 4-byte value\r
+ with trailing zeroes.\r
+ **/\r
+STATIC\r
+UINT32\r
+BIov_Send_Rem (\r
+ IN UINT32 *Data,\r
+ IN UINTN Len\r
+ )\r
+{\r
+ union {\r
+ UINT8 c[4];\r
+ UINT32 w;\r
+ } u;\r
+ UINT8 *cdata;\r
+ UINTN i;\r
+\r
+ cdata = (UINT8 *)Data;\r
+ u.w = 0;\r
+\r
+ for (i = 0; i < Len; i++)\r
+ u.c[i] = *cdata++;\r
+\r
+ return u.w;\r
+}\r
+\r
+/**\r
+ Send a block of data out the i/o port as 4-byte quantities,\r
+ appending trailing zeroes on the last if required.\r
+ **/\r
+STATIC\r
+VOID\r
+BIov_Send (\r
+ IN char *Data,\r
+ IN UINTN Len\r
+ )\r
+{\r
+ UINT32 *LData;\r
+\r
+ LData = (UINT32 *)Data;\r
+\r
+ while (Len > sizeof(UINT32)) {\r
+ IoWrite32 (FW_PORT, *LData++);\r
+ Len -= sizeof(UINT32);\r
+ }\r
+\r
+ if (Len > 0) {\r
+ IoWrite32 (FW_PORT, BIov_Send_Rem (LData, Len));\r
+ }\r
+}\r
+\r
+/**\r
+ Send data described by an array of iovecs out the i/o port.\r
+ **/\r
+STATIC\r
+VOID\r
+BIov_SendAll (\r
+ IN struct BIoVec b[]\r
+ )\r
+{\r
+ INTN i;\r
+\r
+ if (b != NULL) {\r
+ for (i = 0; b[i].Base; i++) {\r
+ BIov_Send (b[i].Base, b[i].Len);\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Prepend the transport header to a block of data and send.\r
+ **/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+BhyveFwCtl_MsgSend(\r
+ IN UINTN OpCode,\r
+ IN struct BIoVec Data[]\r
+ )\r
+{\r
+ struct BIoVec hIov[4];\r
+ UINT32 Hdr[3];\r
+ UINTN i;\r
+\r
+ /* Set up header as an iovec */\r
+ for (i = 0; i < 3; i++) {\r
+ hIov[i].Base = &Hdr[i];\r
+ hIov[i].Len = sizeof(Hdr[0]);\r
+ }\r
+ hIov[i].Base = NULL;\r
+ hIov[i].Len = 0;\r
+\r
+ /* Initialize header */\r
+ Hdr[0] = BIov_WLen (hIov) + BIov_WLen (Data);\r
+ Hdr[1] = OpCode;\r
+ Hdr[2] = mBhyveFwCtlTxid;\r
+\r
+ /* Send header and data */\r
+ BIov_SendAll (hIov);\r
+ BIov_SendAll (Data);\r
+}\r
+\r
+/**\r
+ Read a transport response and optional data from the i/o port.\r
+ **/\r
+STATIC\r
+RETURN_STATUS\r
+EFIAPI\r
+BhyveFwCtl_MsgRecv(\r
+ OUT struct MsgRxHdr *Rhdr,\r
+ OUT struct BIoVec Data[]\r
+ )\r
+{\r
+ RETURN_STATUS Status;\r
+ UINT32 *Dp;\r
+ UINT32 Rd;\r
+ UINTN remLen;\r
+ INTN oLen, xLen;\r
+\r
+ Rd = IoRead32 (FW_PORT);\r
+ if (Rd < sizeof(struct MsgRxHdr)) {\r
+ ;\r
+ }\r
+\r
+ /* Read in header and setup initial error */\r
+ Rhdr->Sz = Rd;\r
+ Rhdr->Op = IoRead32 (FW_PORT);\r
+ Rhdr->TxId = IoRead32 (FW_PORT);\r
+ Rhdr->Err = IoRead32 (FW_PORT);\r
+\r
+ /* Convert transport errno into UEFI error status */\r
+ Status = BhyveFwCtl_CvtErr(Rhdr->Err);\r
+\r
+ remLen = Rd - sizeof(struct MsgRxHdr);\r
+ xLen = 0;\r
+\r
+ /*\r
+ * A few cases to handle:\r
+ * - the user didn't supply a read buffer\r
+ * - the buffer is too small for the response\r
+ * - the response is zero-length\r
+ */\r
+ if (Data != NULL) {\r
+ Dp = (UINT32 *)Data[0].Base;\r
+ oLen = remLen;\r
+ if (remLen > Data[0].Len) {\r
+ Status = RETURN_BUFFER_TOO_SMALL;\r
+ xLen = remLen - Data[0].Len;\r
+ oLen = remLen = Data[0].Len;\r
+ }\r
+ while (remLen > 0) {\r
+ *Dp++ = IoRead32 (FW_PORT);\r
+ remLen -= sizeof(UINT32);\r
+ }\r
+ Data[0].Len = oLen;\r
+ } else {\r
+ /* No user data, but data returned - drop */\r
+ if (remLen > 0) {\r
+ Status = RETURN_BUFFER_TOO_SMALL;\r
+ xLen = remLen;\r
+ }\r
+ }\r
+\r
+ /* Drop additional data */\r
+ while (xLen > 0) {\r
+ (void) IoRead32 (FW_PORT);\r
+ xLen -= sizeof(UINT32);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+STATIC\r
+RETURN_STATUS\r
+EFIAPI\r
+BhyveFwCtl_Msg(\r
+ IN UINTN OpCode,\r
+ IN struct BIoVec Sdata[],\r
+ OUT struct BIoVec Rdata[]\r
+ )\r
+{\r
+ struct MsgRxHdr Rh;\r
+ RETURN_STATUS Status;\r
+\r
+ Status = RETURN_SUCCESS;\r
+\r
+ BhyveFwCtl_MsgSend (OpCode, Sdata);\r
+ Status = BhyveFwCtl_MsgRecv (&Rh, Rdata);\r
+\r
+ mBhyveFwCtlTxid++;\r
+\r
+ return Status;\r
+}\r
+\r
+STATIC\r
+RETURN_STATUS\r
+EFIAPI\r
+BhyveFwCtlGetLen (\r
+ IN CONST CHAR8 *Name,\r
+ IN OUT UINTN *Size\r
+ )\r
+{\r
+ struct BIoVec Req[2], Resp[2];\r
+ RETURN_STATUS Status;\r
+\r
+ Req[0].Base = (VOID *)Name;\r
+ Req[0].Len = AsciiStrLen (Name) + 1;\r
+ Req[1].Base = NULL;\r
+\r
+ Resp[0].Base = Size;\r
+ Resp[0].Len = sizeof(UINTN);\r
+ Resp[1].Base = NULL;\r
+\r
+ Status = BhyveFwCtl_Msg (OP_GET_LEN, Req, Resp);\r
+\r
+ return Status;\r
+}\r
+\r
+#define FMAXSZ 1024\r
+STATIC struct {\r
+ UINT64 fSize;\r
+ UINT32 fData[FMAXSZ];\r
+} FwGetvalBuf;\r
+\r
+STATIC\r
+RETURN_STATUS\r
+EFIAPI\r
+BhyveFwCtlGetVal (\r
+ IN CONST CHAR8 *Name,\r
+ OUT VOID *Item,\r
+ IN OUT UINTN *Size\r
+ )\r
+{\r
+ struct BIoVec Req[2], Resp[2];\r
+ RETURN_STATUS Status;\r
+\r
+ /* Make sure temp buffer is larger than passed-in size */\r
+ if (*Size > sizeof(FwGetvalBuf.fData))\r
+ return RETURN_INVALID_PARAMETER;\r
+\r
+ Req[0].Base = (VOID *)Name;\r
+ Req[0].Len = AsciiStrLen(Name) + 1;\r
+ Req[1].Base = NULL;\r
+\r
+ Resp[0].Base = &FwGetvalBuf;\r
+ Resp[0].Len = sizeof(UINT64) + *Size;\r
+ Resp[1].Base = NULL;\r
+\r
+ Status = BhyveFwCtl_Msg (OP_GET, Req, Resp);\r
+\r
+ /*\r
+ * Copy out data on success (or on a truncated message).\r
+ * XXX This step can be eliminted with Msg() supporting\r
+ * multiple iovecs.\r
+ */\r
+ if ((Status == RETURN_SUCCESS) || (Status == RETURN_BUFFER_TOO_SMALL)) {\r
+ *Size = FwGetvalBuf.fSize;\r
+ CopyMem (Item, FwGetvalBuf.fData, *Size);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Front end to the internal GET_LEN and GET protocols\r
+ **/\r
+RETURN_STATUS\r
+EFIAPI\r
+BhyveFwCtlGet (\r
+ IN CONST CHAR8 *Name,\r
+ OUT VOID *Item,\r
+ IN OUT UINTN *Size\r
+ )\r
+{\r
+ RETURN_STATUS Status;\r
+\r
+ if (mBhyveFwCtlSupported == FALSE)\r
+ return RETURN_UNSUPPORTED;\r
+\r
+ if (Item == NULL) {\r
+ Status = BhyveFwCtlGetLen (Name, Size);\r
+ } else {\r
+ Status = BhyveFwCtlGetVal (Name, Item, Size);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Library initialization. Probe the host to see if the f/w ctl\r
+ interface is supported.\r
+ **/\r
+RETURN_STATUS\r
+EFIAPI\r
+BhyveFwCtlInitialize (\r
+ VOID\r
+ )\r
+{\r
+ UINTN i;\r
+ UINT8 ch;\r
+\r
+ DEBUG ((DEBUG_INFO, "FwCtlInitialize\n"));\r
+\r
+ IoWrite16 (FW_PORT, 0x0000);\r
+ for (i = 0; i < 4; i++) {\r
+ ch = IoRead8 (FW_IPORT);\r
+ if (ch != mBhyveSig[i]) {\r
+ DEBUG ((DEBUG_INFO, "Host f/w sig mismatch %c/%c\n", ch, mBhyveSig[i]));\r
+ return RETURN_SUCCESS;\r
+ }\r
+ }\r
+\r
+ mBhyveFwCtlSupported = TRUE;\r
+\r
+ return RETURN_SUCCESS;\r
+}\r
--- /dev/null
+## @file\r
+#\r
+# Copyright (C) 2020, Rebecca Cran <rebecca@bsdio.com>\r
+# Copyright (C) 2015 Nahanni Systems\r
+# Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# SPDX-License-Identifier: BSD-2-Clause-Patent\r
+#\r
+##\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = BhyveFwCtlLib\r
+ FILE_GUID = fd982666-67f9-11e5-a42a-0025908602f6\r
+ MODULE_TYPE = BASE\r
+ VERSION_STRING = 1.0\r
+ LIBRARY_CLASS = BhyveFwCtlLib|PEIM DXE_DRIVER DXE_RUNTIME_DRIVER\r
+\r
+ CONSTRUCTOR = BhyveFwCtlInitialize\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = X64\r
+#\r
+\r
+[Sources]\r
+ BhyveFwCtlLib.c\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ OvmfPkg/OvmfPkg.dec\r
+\r
+[LibraryClasses]\r
+ BaseLib\r
+ BaseMemoryLib\r
+ DebugLib\r
+ IoLib\r
+ MemoryAllocationLib\r
+ IntrinsicLib\r
+\r
--- /dev/null
+/** @file\r
+ Platform BDS customizations.\r
+\r
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>\r
+ Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include "BdsPlatform.h"\r
+#include <Guid/RootBridgesConnectedEventGroup.h>\r
+#include <Protocol/FirmwareVolume2.h>\r
+#include <Library/PlatformBmPrintScLib.h>\r
+#include <Library/Tcg2PhysicalPresenceLib.h>\r
+\r
+#include <Protocol/BlockIo.h>\r
+\r
+//\r
+// Global data\r
+//\r
+\r
+VOID *mEfiDevPathNotifyReg;\r
+EFI_EVENT mEfiDevPathEvent;\r
+VOID *mEmuVariableEventReg;\r
+EFI_EVENT mEmuVariableEvent;\r
+UINT16 mHostBridgeDevId;\r
+\r
+//\r
+// Table of host IRQs matching PCI IRQs A-D\r
+// (for configuring PCI Interrupt Line register)\r
+//\r
+CONST UINT8 PciHostIrqs[] = {\r
+ 0x0a, 0x0a, 0x0b, 0x0b\r
+};\r
+\r
+//\r
+// Type definitions\r
+//\r
+\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *PROTOCOL_INSTANCE_CALLBACK)(\r
+ IN EFI_HANDLE Handle,\r
+ IN VOID *Instance,\r
+ IN VOID *Context\r
+ );\r
+\r
+/**\r
+ @param[in] Handle - Handle of PCI device instance\r
+ @param[in] PciIo - PCI IO protocol instance\r
+ @param[in] Pci - PCI Header register block\r
+**/\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *VISIT_PCI_INSTANCE_CALLBACK)(\r
+ IN EFI_HANDLE Handle,\r
+ IN EFI_PCI_IO_PROTOCOL *PciIo,\r
+ IN PCI_TYPE00 *Pci\r
+ );\r
+\r
+\r
+//\r
+// Function prototypes\r
+//\r
+\r
+EFI_STATUS\r
+VisitAllInstancesOfProtocol (\r
+ IN EFI_GUID *Id,\r
+ IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,\r
+ IN VOID *Context\r
+ );\r
+\r
+EFI_STATUS\r
+VisitAllPciInstancesOfProtocol (\r
+ IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction\r
+ );\r
+\r
+VOID\r
+InstallDevicePathCallback (\r
+ VOID\r
+ );\r
+\r
+VOID\r
+PlatformRegisterFvBootOption (\r
+ EFI_GUID *FileGuid,\r
+ CHAR16 *Description,\r
+ UINT32 Attributes\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ INTN OptionIndex;\r
+ EFI_BOOT_MANAGER_LOAD_OPTION NewOption;\r
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;\r
+ UINTN BootOptionCount;\r
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;\r
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+\r
+ Status = gBS->HandleProtocol (\r
+ gImageHandle,\r
+ &gEfiLoadedImageProtocolGuid,\r
+ (VOID **) &LoadedImage\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);\r
+ DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle);\r
+ ASSERT (DevicePath != NULL);\r
+ DevicePath = AppendDevicePathNode (\r
+ DevicePath,\r
+ (EFI_DEVICE_PATH_PROTOCOL *) &FileNode\r
+ );\r
+ ASSERT (DevicePath != NULL);\r
+\r
+ Status = EfiBootManagerInitializeLoadOption (\r
+ &NewOption,\r
+ LoadOptionNumberUnassigned,\r
+ LoadOptionTypeBoot,\r
+ Attributes,\r
+ Description,\r
+ DevicePath,\r
+ NULL,\r
+ 0\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ FreePool (DevicePath);\r
+\r
+ BootOptions = EfiBootManagerGetLoadOptions (\r
+ &BootOptionCount, LoadOptionTypeBoot\r
+ );\r
+\r
+ OptionIndex = EfiBootManagerFindLoadOption (\r
+ &NewOption, BootOptions, BootOptionCount\r
+ );\r
+\r
+ if (OptionIndex == -1) {\r
+ Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN);\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+ EfiBootManagerFreeLoadOption (&NewOption);\r
+ EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);\r
+}\r
+\r
+/**\r
+ Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options\r
+ whose device paths do not resolve exactly to an FvFile in the system.\r
+\r
+ This removes any boot options that point to binaries built into the firmware\r
+ and have become stale due to any of the following:\r
+ - DXEFV's base address or size changed (historical),\r
+ - DXEFV's FvNameGuid changed,\r
+ - the FILE_GUID of the pointed-to binary changed,\r
+ - the referenced binary is no longer built into the firmware.\r
+\r
+ EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only\r
+ avoids exact duplicates.\r
+**/\r
+VOID\r
+RemoveStaleFvFileOptions (\r
+ VOID\r
+ )\r
+{\r
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;\r
+ UINTN BootOptionCount;\r
+ UINTN Index;\r
+\r
+ BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount,\r
+ LoadOptionTypeBoot);\r
+\r
+ for (Index = 0; Index < BootOptionCount; ++Index) {\r
+ EFI_DEVICE_PATH_PROTOCOL *Node1, *Node2, *SearchNode;\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE FvHandle;\r
+\r
+ //\r
+ // If the device path starts with neither MemoryMapped(...) nor Fv(...),\r
+ // then keep the boot option.\r
+ //\r
+ Node1 = BootOptions[Index].FilePath;\r
+ if (!(DevicePathType (Node1) == HARDWARE_DEVICE_PATH &&\r
+ DevicePathSubType (Node1) == HW_MEMMAP_DP) &&\r
+ !(DevicePathType (Node1) == MEDIA_DEVICE_PATH &&\r
+ DevicePathSubType (Node1) == MEDIA_PIWG_FW_VOL_DP)) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // If the second device path node is not FvFile(...), then keep the boot\r
+ // option.\r
+ //\r
+ Node2 = NextDevicePathNode (Node1);\r
+ if (DevicePathType (Node2) != MEDIA_DEVICE_PATH ||\r
+ DevicePathSubType (Node2) != MEDIA_PIWG_FW_FILE_DP) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Locate the Firmware Volume2 protocol instance that is denoted by the\r
+ // boot option. If this lookup fails (i.e., the boot option references a\r
+ // firmware volume that doesn't exist), then we'll proceed to delete the\r
+ // boot option.\r
+ //\r
+ SearchNode = Node1;\r
+ Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid,\r
+ &SearchNode, &FvHandle);\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // The firmware volume was found; now let's see if it contains the FvFile\r
+ // identified by GUID.\r
+ //\r
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;\r
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFileNode;\r
+ UINTN BufferSize;\r
+ EFI_FV_FILETYPE FoundType;\r
+ EFI_FV_FILE_ATTRIBUTES FileAttributes;\r
+ UINT32 AuthenticationStatus;\r
+\r
+ Status = gBS->HandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid,\r
+ (VOID **)&FvProtocol);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ FvFileNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)Node2;\r
+ //\r
+ // Buffer==NULL means we request metadata only: BufferSize, FoundType,\r
+ // FileAttributes.\r
+ //\r
+ Status = FvProtocol->ReadFile (\r
+ FvProtocol,\r
+ &FvFileNode->FvFileName, // NameGuid\r
+ NULL, // Buffer\r
+ &BufferSize,\r
+ &FoundType,\r
+ &FileAttributes,\r
+ &AuthenticationStatus\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // The FvFile was found. Keep the boot option.\r
+ //\r
+ continue;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Delete the boot option.\r
+ //\r
+ Status = EfiBootManagerDeleteLoadOptionVariable (\r
+ BootOptions[Index].OptionNumber, LoadOptionTypeBoot);\r
+ DEBUG_CODE (\r
+ CHAR16 *DevicePathString;\r
+\r
+ DevicePathString = ConvertDevicePathToText(BootOptions[Index].FilePath,\r
+ FALSE, FALSE);\r
+ DEBUG ((\r
+ EFI_ERROR (Status) ? EFI_D_WARN : DEBUG_VERBOSE,\r
+ "%a: removing stale Boot#%04x %s: %r\n",\r
+ __FUNCTION__,\r
+ (UINT32)BootOptions[Index].OptionNumber,\r
+ DevicePathString == NULL ? L"<unavailable>" : DevicePathString,\r
+ Status\r
+ ));\r
+ if (DevicePathString != NULL) {\r
+ FreePool (DevicePathString);\r
+ }\r
+ );\r
+ }\r
+\r
+ EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);\r
+}\r
+\r
+VOID\r
+PlatformRegisterOptionsAndKeys (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_INPUT_KEY Enter;\r
+ EFI_INPUT_KEY F2;\r
+ EFI_INPUT_KEY Esc;\r
+ EFI_BOOT_MANAGER_LOAD_OPTION BootOption;\r
+\r
+ //\r
+ // Register ENTER as CONTINUE key\r
+ //\r
+ Enter.ScanCode = SCAN_NULL;\r
+ Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;\r
+ Status = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Map F2 to Boot Manager Menu\r
+ //\r
+ F2.ScanCode = SCAN_F2;\r
+ F2.UnicodeChar = CHAR_NULL;\r
+ Esc.ScanCode = SCAN_ESC;\r
+ Esc.UnicodeChar = CHAR_NULL;\r
+ Status = EfiBootManagerGetBootManagerMenu (&BootOption);\r
+ ASSERT_EFI_ERROR (Status);\r
+ Status = EfiBootManagerAddKeyOptionVariable (\r
+ NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL\r
+ );\r
+ ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);\r
+ Status = EfiBootManagerAddKeyOptionVariable (\r
+ NULL, (UINT16) BootOption.OptionNumber, 0, &Esc, NULL\r
+ );\r
+ ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConnectRootBridge (\r
+ IN EFI_HANDLE RootBridgeHandle,\r
+ IN VOID *Instance,\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
+ VOID\r
+ );\r
+\r
+//\r
+// BDS Platform Functions\r
+//\r
+/**\r
+ Do the platform init, can be customized by OEM/IBV\r
+\r
+ Possible things that can be done in PlatformBootManagerBeforeConsole:\r
+\r
+ > Update console variable: 1. include hot-plug devices;\r
+ > 2. Clear ConIn and add SOL for AMT\r
+ > Register new Driver#### or Boot####\r
+ > Register new Key####: e.g.: F12\r
+ > Signal ReadyToLock event\r
+ > Authentication action: 1. connect Auth devices;\r
+ > 2. Identify auto logon user.\r
+**/\r
+VOID\r
+EFIAPI\r
+PlatformBootManagerBeforeConsole (\r
+ VOID\r
+ )\r
+{\r
+ EFI_HANDLE Handle;\r
+ EFI_STATUS Status;\r
+\r
+ DEBUG ((DEBUG_INFO, "PlatformBootManagerBeforeConsole\n"));\r
+ InstallDevicePathCallback ();\r
+\r
+ VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid,\r
+ ConnectRootBridge, NULL);\r
+\r
+ //\r
+ // Signal the ACPI platform driver that it can download QEMU ACPI tables.\r
+ //\r
+ EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid);\r
+\r
+ //\r
+ // We can't signal End-of-Dxe earlier than this. Namely, End-of-Dxe triggers\r
+ // the preparation of S3 system information. That logic has a hard dependency\r
+ // on the presence of the FACS ACPI table. Since our ACPI tables are only\r
+ // installed after PCI enumeration completes, we must not trigger the S3 save\r
+ // earlier, hence we can't signal End-of-Dxe earlier.\r
+ //\r
+ EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);\r
+\r
+ //\r
+ // Prevent further changes to LockBoxes or SMRAM.\r
+ //\r
+ Handle = NULL;\r
+ Status = gBS->InstallProtocolInterface (&Handle,\r
+ &gEfiDxeSmmReadyToLockProtocolGuid, EFI_NATIVE_INTERFACE,\r
+ NULL);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Dispatch deferred images after EndOfDxe event and ReadyToLock\r
+ // installation.\r
+ //\r
+ EfiBootManagerDispatchDeferredImages ();\r
+\r
+ PlatformInitializeConsole (gPlatformConsole);\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
+EFI_STATUS\r
+EFIAPI\r
+ConnectRootBridge (\r
+ IN EFI_HANDLE RootBridgeHandle,\r
+ IN VOID *Instance,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Make the PCI bus driver connect the root bridge, non-recursively. This\r
+ // will produce a number of child handles with PciIo on them.\r
+ //\r
+ Status = gBS->ConnectController (\r
+ RootBridgeHandle, // ControllerHandle\r
+ NULL, // DriverImageHandle\r
+ NULL, // RemainingDevicePath -- produce all\r
+ // children\r
+ FALSE // Recursive\r
+ );\r
+ return Status;\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
+ @param[in] DeviceHandle Handle of the LPC Bridge device.\r
+\r
+ @retval EFI_SUCCESS Console devices on the LPC bridge have been added to\r
+ ConOut, ConIn, and ErrOut.\r
+\r
+ @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing\r
+ from DeviceHandle.\r
+**/\r
+EFI_STATUS\r
+PrepareLpcBridgeDevicePath (\r
+ IN EFI_HANDLE DeviceHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
+ CHAR16 *DevPathStr;\r
+\r
+ DevicePath = NULL;\r
+ Status = gBS->HandleProtocol (\r
+ DeviceHandle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID*)&DevicePath\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ TempDevicePath = DevicePath;\r
+\r
+ //\r
+ // Register Keyboard\r
+ //\r
+ DevicePath = AppendDevicePathNode (DevicePath,\r
+ (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);\r
+\r
+ EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);\r
+\r
+ //\r
+ // Register COM1\r
+ //\r
+ DevicePath = TempDevicePath;\r
+ gPnp16550ComPortDeviceNode.UID = 0;\r
+\r
+ DevicePath = AppendDevicePathNode (DevicePath,\r
+ (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);\r
+ DevicePath = AppendDevicePathNode (DevicePath,\r
+ (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r
+ DevicePath = AppendDevicePathNode (DevicePath,\r
+ (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r
+\r
+ //\r
+ // Print Device Path\r
+ //\r
+ DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);\r
+ if (DevPathStr != NULL) {\r
+ DEBUG((\r
+ DEBUG_INFO,\r
+ "BdsPlatform.c+%d: COM%d DevPath: %s\n",\r
+ __LINE__,\r
+ gPnp16550ComPortDeviceNode.UID + 1,\r
+ DevPathStr\r
+ ));\r
+ FreePool(DevPathStr);\r
+ }\r
+\r
+ EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);\r
+ EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);\r
+ EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);\r
+\r
+ // Don't register COM2 which can be used for DBG instead so keep it clean\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+GetGopDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,\r
+ OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath\r
+ )\r
+{\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE PciDeviceHandle;\r
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath;\r
+ UINTN GopHandleCount;\r
+ EFI_HANDLE *GopHandleBuffer;\r
+\r
+ if (PciDevicePath == NULL || GopDevicePath == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Initialize the GopDevicePath to be PciDevicePath\r
+ //\r
+ *GopDevicePath = PciDevicePath;\r
+ TempPciDevicePath = PciDevicePath;\r
+\r
+ Status = gBS->LocateDevicePath (\r
+ &gEfiDevicePathProtocolGuid,\r
+ &TempPciDevicePath,\r
+ &PciDeviceHandle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Try to connect this handle, so that GOP driver could start on this\r
+ // device and create child handles with GraphicsOutput Protocol installed\r
+ // on them, then we get device paths of these child handles and select\r
+ // them as possible console device.\r
+ //\r
+ gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);\r
+\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiGraphicsOutputProtocolGuid,\r
+ NULL,\r
+ &GopHandleCount,\r
+ &GopHandleBuffer\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Add all the child handles as possible Console Device\r
+ //\r
+ for (Index = 0; Index < GopHandleCount; Index++) {\r
+ Status = gBS->HandleProtocol (GopHandleBuffer[Index],\r
+ &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+ if (CompareMem (\r
+ PciDevicePath,\r
+ TempDevicePath,\r
+ GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH\r
+ ) == 0) {\r
+ //\r
+ // In current implementation, we only enable one of the child handles\r
+ // as console device, i.e. sotre one of the child handle's device\r
+ // path to variable "ConOut"\r
+ // In future, we could select all child handles to be console device\r
+ //\r
+\r
+ *GopDevicePath = TempDevicePath;\r
+\r
+ //\r
+ // Delete the PCI device's path that added by\r
+ // GetPlugInPciVgaDevicePath(). Add the integrity GOP device path.\r
+ //\r
+ EfiBootManagerUpdateConsoleVariable (ConOutDev, NULL, PciDevicePath);\r
+ EfiBootManagerUpdateConsoleVariable (ConOutDev, TempDevicePath, NULL);\r
+ }\r
+ }\r
+ gBS->FreePool (GopHandleBuffer);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Add PCI display to ConOut.\r
+\r
+ @param[in] DeviceHandle Handle of the PCI display device.\r
+\r
+ @retval EFI_SUCCESS The PCI display device has been added to ConOut.\r
+\r
+ @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing\r
+ from DeviceHandle.\r
+**/\r
+EFI_STATUS\r
+PreparePciDisplayDevicePath (\r
+ IN EFI_HANDLE DeviceHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;\r
+\r
+ DevicePath = NULL;\r
+ GopDevicePath = NULL;\r
+ Status = gBS->HandleProtocol (\r
+ DeviceHandle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID*)&DevicePath\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ GetGopDevicePath (DevicePath, &GopDevicePath);\r
+ DevicePath = GopDevicePath;\r
+\r
+ EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Add PCI Serial to ConOut, ConIn, ErrOut.\r
+\r
+ @param[in] DeviceHandle Handle of the PCI serial device.\r
+\r
+ @retval EFI_SUCCESS The PCI serial device has been added to ConOut, ConIn,\r
+ ErrOut.\r
+\r
+ @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing\r
+ from DeviceHandle.\r
+**/\r
+EFI_STATUS\r
+PreparePciSerialDevicePath (\r
+ IN EFI_HANDLE DeviceHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+\r
+ DevicePath = NULL;\r
+ Status = gBS->HandleProtocol (\r
+ DeviceHandle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID*)&DevicePath\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ DevicePath = AppendDevicePathNode (DevicePath,\r
+ (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r
+ DevicePath = AppendDevicePathNode (DevicePath,\r
+ (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r
+\r
+ EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);\r
+ EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);\r
+ EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+VisitAllInstancesOfProtocol (\r
+ IN EFI_GUID *Id,\r
+ IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN HandleCount;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN Index;\r
+ VOID *Instance;\r
+\r
+ //\r
+ // Start to check all the PciIo to find all possible device\r
+ //\r
+ HandleCount = 0;\r
+ HandleBuffer = NULL;\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ Id,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ Status = (*CallBackFunction) (\r
+ HandleBuffer[Index],\r
+ Instance,\r
+ Context\r
+ );\r
+ }\r
+\r
+ gBS->FreePool (HandleBuffer);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VisitingAPciInstance (\r
+ IN EFI_HANDLE Handle,\r
+ IN VOID *Instance,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ PCI_TYPE00 Pci;\r
+\r
+ PciIo = (EFI_PCI_IO_PROTOCOL*) Instance;\r
+\r
+ //\r
+ // Check for all PCI device\r
+ //\r
+ Status = PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0,\r
+ sizeof (Pci) / sizeof (UINT32),\r
+ &Pci\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) (\r
+ Handle,\r
+ PciIo,\r
+ &Pci\r
+ );\r
+\r
+}\r
+\r
+\r
+\r
+EFI_STATUS\r
+VisitAllPciInstances (\r
+ IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction\r
+ )\r
+{\r
+ return VisitAllInstancesOfProtocol (\r
+ &gEfiPciIoProtocolGuid,\r
+ VisitingAPciInstance,\r
+ (VOID*)(UINTN) CallBackFunction\r
+ );\r
+}\r
+\r
+\r
+/**\r
+ Do platform specific PCI Device check and add them to\r
+ ConOut, ConIn, ErrOut.\r
+\r
+ @param[in] Handle - Handle of PCI device instance\r
+ @param[in] PciIo - PCI IO protocol instance\r
+ @param[in] Pci - PCI Header register block\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
+EFIAPI\r
+DetectAndPreparePlatformPciDevicePath (\r
+ IN EFI_HANDLE Handle,\r
+ IN EFI_PCI_IO_PROTOCOL *PciIo,\r
+ IN PCI_TYPE00 *Pci\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationEnable,\r
+ EFI_PCI_DEVICE_ENABLE,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\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
+ // Add IsaKeyboard to ConIn,\r
+ // add IsaSerial to ConOut, ConIn, ErrOut\r
+ //\r
+ DEBUG ((DEBUG_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
+ // Add them to ConOut, ConIn, ErrOut.\r
+ //\r
+ DEBUG ((DEBUG_INFO, "Found PCI 16550 SERIAL device\n"));\r
+ PreparePciSerialDevicePath (Handle);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Here we decide which display device to enable in PCI bus\r
+ //\r
+ if (IS_PCI_DISPLAY (Pci)) {\r
+ //\r
+ // Add them to ConOut.\r
+ //\r
+ DEBUG ((DEBUG_INFO, "Found PCI display device\n"));\r
+ PreparePciDisplayDevicePath (Handle);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Connect the predefined platform default console device.\r
+\r
+ Always try to find and enable PCI display devices.\r
+\r
+ @param[in] PlatformConsole Predefined platform default console device array.\r
+**/\r
+VOID\r
+PlatformInitializeConsole (\r
+ IN PLATFORM_CONSOLE_CONNECT_ENTRY *PlatformConsole\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ //\r
+ // Do platform specific PCI Device check and add them to ConOut, ConIn,\r
+ // ErrOut\r
+ //\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
+ // 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
+ }\r
+}\r
+\r
+\r
+/**\r
+ Configure PCI Interrupt Line register for applicable devices\r
+ Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()\r
+\r
+ @param[in] Handle - Handle of PCI device instance\r
+ @param[in] PciIo - PCI IO protocol instance\r
+ @param[in] PciHdr - PCI Header register block\r
+\r
+ @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SetPciIntLine (\r
+ IN EFI_HANDLE Handle,\r
+ IN EFI_PCI_IO_PROTOCOL *PciIo,\r
+ IN PCI_TYPE00 *PciHdr\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *DevPathNode;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
+ UINTN RootSlot;\r
+ UINTN Idx;\r
+ UINT8 IrqLine;\r
+ EFI_STATUS Status;\r
+ UINT32 RootBusNumber;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ if (PciHdr->Device.InterruptPin != 0) {\r
+\r
+ DevPathNode = DevicePathFromHandle (Handle);\r
+ ASSERT (DevPathNode != NULL);\r
+ DevPath = DevPathNode;\r
+\r
+ RootBusNumber = 0;\r
+ if (DevicePathType (DevPathNode) == ACPI_DEVICE_PATH &&\r
+ DevicePathSubType (DevPathNode) == ACPI_DP &&\r
+ ((ACPI_HID_DEVICE_PATH *)DevPathNode)->HID == EISA_PNP_ID(0x0A03)) {\r
+ RootBusNumber = ((ACPI_HID_DEVICE_PATH *)DevPathNode)->UID;\r
+ }\r
+\r
+ //\r
+ // Compute index into PciHostIrqs[] table by walking\r
+ // the device path and adding up all device numbers\r
+ //\r
+ Status = EFI_NOT_FOUND;\r
+ RootSlot = 0;\r
+ Idx = PciHdr->Device.InterruptPin - 1;\r
+ while (!IsDevicePathEnd (DevPathNode)) {\r
+ if (DevicePathType (DevPathNode) == HARDWARE_DEVICE_PATH &&\r
+ DevicePathSubType (DevPathNode) == HW_PCI_DP) {\r
+\r
+ Idx += ((PCI_DEVICE_PATH *)DevPathNode)->Device;\r
+\r
+ //\r
+ // Unlike SeaBIOS, which starts climbing from the leaf device\r
+ // up toward the root, we traverse the device path starting at\r
+ // the root moving toward the leaf node.\r
+ // The slot number of the top-level parent bridge is needed for\r
+ // Q35 cases with more than 24 slots on the root bus.\r
+ //\r
+ if (Status != EFI_SUCCESS) {\r
+ Status = EFI_SUCCESS;\r
+ RootSlot = ((PCI_DEVICE_PATH *)DevPathNode)->Device;\r
+ }\r
+ }\r
+\r
+ DevPathNode = NextDevicePathNode (DevPathNode);\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ if (RootBusNumber == 0 && RootSlot == 0) {\r
+ DEBUG((\r
+ DEBUG_ERROR,\r
+ "%a: PCI host bridge (00:00.0) should have no interrupts!\n",\r
+ __FUNCTION__\r
+ ));\r
+ ASSERT (FALSE);\r
+ }\r
+\r
+ //\r
+ // Final PciHostIrqs[] index calculation depends on the platform\r
+ // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()\r
+ //\r
+ switch (mHostBridgeDevId) {\r
+ case 0x1275: // BHYVE\r
+ case INTEL_82441_DEVICE_ID:\r
+ Idx -= 1;\r
+ break;\r
+ case INTEL_Q35_MCH_DEVICE_ID:\r
+ //\r
+ // SeaBIOS contains the following comment:\r
+ // "Slots 0-24 rotate slot:pin mapping similar to piix above, but\r
+ // with a different starting index - see q35-acpi-dsdt.dsl.\r
+ //\r
+ // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"\r
+ //\r
+ if (RootSlot > 24) {\r
+ //\r
+ // in this case, subtract back out RootSlot from Idx\r
+ // (SeaBIOS never adds it to begin with, but that would make our\r
+ // device path traversal loop above too awkward)\r
+ //\r
+ Idx -= RootSlot;\r
+ }\r
+ break;\r
+ default:\r
+ ASSERT (FALSE); // should never get here\r
+ }\r
+ Idx %= ARRAY_SIZE (PciHostIrqs);\r
+ IrqLine = PciHostIrqs[Idx];\r
+\r
+ DEBUG_CODE_BEGIN ();\r
+ {\r
+ CHAR16 *DevPathString;\r
+ STATIC CHAR16 Fallback[] = L"<failed to convert>";\r
+ UINTN Segment, Bus, Device, Function;\r
+\r
+ DevPathString = ConvertDevicePathToText (DevPath, FALSE, FALSE);\r
+ if (DevPathString == NULL) {\r
+ DevPathString = Fallback;\r
+ }\r
+ Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ DEBUG ((DEBUG_VERBOSE, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__,\r
+ (UINT32)Bus, (UINT32)Device, (UINT32)Function, DevPathString,\r
+ IrqLine));\r
+\r
+ if (DevPathString != Fallback) {\r
+ FreePool (DevPathString);\r
+ }\r
+ }\r
+ DEBUG_CODE_END ();\r
+\r
+ //\r
+ // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]\r
+ //\r
+ Status = PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint8,\r
+ PCI_INT_LINE_OFFSET,\r
+ 1,\r
+ &IrqLine\r
+ );\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+VOID\r
+PciAcpiInitialization (\r
+ )\r
+{\r
+ UINTN Pmba;\r
+\r
+ //\r
+ // Query Host Bridge DID to determine platform type\r
+ //\r
+ mHostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId);\r
+ switch (mHostBridgeDevId) {\r
+ case 0x1275: // BHYVE\r
+ case INTEL_82441_DEVICE_ID:\r
+ Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);\r
+ //\r
+ // 00:01.0 ISA Bridge (PIIX4) LNK routing targets\r
+ //\r
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A\r
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B\r
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C\r
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D\r
+ break;\r
+ case INTEL_Q35_MCH_DEVICE_ID:\r
+ Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);\r
+ //\r
+ // 00:1f.0 LPC Bridge (Q35) LNK routing targets\r
+ //\r
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A\r
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B\r
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C\r
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D\r
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E\r
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F\r
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G\r
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H\r
+ break;\r
+ default:\r
+ DEBUG ((DEBUG_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",\r
+ __FUNCTION__, mHostBridgeDevId));\r
+ ASSERT (FALSE);\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices\r
+ //\r
+ VisitAllPciInstances (SetPciIntLine);\r
+\r
+ //\r
+ // Set ACPI SCI_EN bit in PMCNTRL\r
+ //\r
+ IoOr16 ((PciRead32 (Pmba) & ~BIT0) + 4, BIT0);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConnectRecursivelyIfPciMassStorage (\r
+ IN EFI_HANDLE Handle,\r
+ IN EFI_PCI_IO_PROTOCOL *Instance,\r
+ IN PCI_TYPE00 *PciHeader\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ CHAR16 *DevPathStr;\r
+\r
+ //\r
+ // Recognize PCI Mass Storage, and Xen PCI devices\r
+ //\r
+ if (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE)) {\r
+ DevicePath = NULL;\r
+ Status = gBS->HandleProtocol (\r
+ Handle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID*)&DevicePath\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Print Device Path\r
+ //\r
+ DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);\r
+ if (DevPathStr != NULL) {\r
+ DEBUG((\r
+ DEBUG_INFO,\r
+ "Found %s device: %s\n",\r
+ (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE) ?\r
+ L"Mass Storage" :\r
+ L"Xen"\r
+ ),\r
+ DevPathStr\r
+ ));\r
+ FreePool(DevPathStr);\r
+ }\r
+\r
+ Status = gBS->ConnectController (Handle, NULL, NULL, TRUE);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This notification function is invoked when the\r
+ EMU Variable FVB has been changed.\r
+\r
+ @param Event The event that occurred\r
+ @param Context For EFI compatibility. Not used.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+EmuVariablesUpdatedCallback (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ DEBUG ((DEBUG_INFO, "EmuVariablesUpdatedCallback\n"));\r
+ UpdateNvVarsOnFileSystem ();\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VisitingFileSystemInstance (\r
+ IN EFI_HANDLE Handle,\r
+ IN VOID *Instance,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ STATIC BOOLEAN ConnectedToFileSystem = FALSE;\r
+ RETURN_STATUS PcdStatus;\r
+\r
+ if (ConnectedToFileSystem) {\r
+ return EFI_ALREADY_STARTED;\r
+ }\r
+\r
+ Status = ConnectNvVarsToFileSystem (Handle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ ConnectedToFileSystem = TRUE;\r
+ mEmuVariableEvent =\r
+ EfiCreateProtocolNotifyEvent (\r
+ &gEfiDevicePathProtocolGuid,\r
+ TPL_CALLBACK,\r
+ EmuVariablesUpdatedCallback,\r
+ NULL,\r
+ &mEmuVariableEventReg\r
+ );\r
+ PcdStatus = PcdSet64S (PcdEmuVariableEvent,\r
+ (UINT64)(UINTN) mEmuVariableEvent);\r
+ ASSERT_RETURN_ERROR (PcdStatus);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+VOID\r
+PlatformBdsRestoreNvVarsFromHardDisk (\r
+ )\r
+{\r
+ VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage);\r
+ VisitAllInstancesOfProtocol (\r
+ &gEfiSimpleFileSystemProtocolGuid,\r
+ VisitingFileSystemInstance,\r
+ NULL\r
+ );\r
+\r
+}\r
+\r
+/**\r
+ Connect with predefined platform connect sequence.\r
+\r
+ The OEM/IBV can customize with their own connect sequence.\r
+**/\r
+VOID\r
+PlatformBdsConnectSequence (\r
+ VOID\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ DEBUG ((DEBUG_INFO, "PlatformBdsConnectSequence\n"));\r
+\r
+ Index = 0;\r
+\r
+ //\r
+ // Here we can get the customized platform connect sequence\r
+ // Notes: we can connect with new variable which record the\r
+ // last time boots connect device path sequence\r
+ //\r
+ while (gPlatformConnectSequence[Index] != NULL) {\r
+ //\r
+ // Build the platform boot option\r
+ //\r
+ EfiBootManagerConnectDevicePath (gPlatformConnectSequence[Index], NULL);\r
+ Index++;\r
+ }\r
+\r
+ //\r
+ // Just use the simple policy to connect all devices\r
+ //\r
+ DEBUG ((DEBUG_INFO, "EfiBootManagerConnectAll\n"));\r
+ EfiBootManagerConnectAll ();\r
+}\r
+\r
+/**\r
+ Save the S3 boot script.\r
+\r
+ Note that DxeSmmReadyToLock must be signaled after this function returns;\r
+ otherwise the script wouldn't be saved actually.\r
+**/\r
+#if defined(__GNUC__)\r
+__attribute__((unused))\r
+#endif\r
+STATIC\r
+VOID\r
+SaveS3BootScript (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_S3_SAVE_STATE_PROTOCOL *BootScript;\r
+ STATIC CONST UINT8 Info[] = { 0xDE, 0xAD, 0xBE, 0xEF };\r
+\r
+ Status = gBS->LocateProtocol (&gEfiS3SaveStateProtocolGuid, NULL,\r
+ (VOID **) &BootScript);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Despite the opcode documentation in the PI spec, the protocol\r
+ // implementation embeds a deep copy of the info in the boot script, rather\r
+ // than storing just a pointer to runtime or NVS storage.\r
+ //\r
+ Status = BootScript->Write(BootScript, EFI_BOOT_SCRIPT_INFORMATION_OPCODE,\r
+ (UINT32) sizeof Info,\r
+ (EFI_PHYSICAL_ADDRESS)(UINTN) &Info);\r
+ ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+\r
+/**\r
+ Do the platform specific action after the console is ready\r
+\r
+ Possible things that can be done in PlatformBootManagerAfterConsole:\r
+\r
+ > Console post action:\r
+ > Dynamically switch output mode from 100x31 to 80x25 for certain senarino\r
+ > Signal console ready platform customized event\r
+ > Run diagnostics like memory testing\r
+ > Connect certain devices\r
+ > Dispatch aditional option roms\r
+ > Special boot: e.g.: USB boot, enter UI\r
+**/\r
+VOID\r
+EFIAPI\r
+PlatformBootManagerAfterConsole (\r
+ VOID\r
+ )\r
+{\r
+ EFI_BOOT_MODE BootMode;\r
+\r
+ DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole\n"));\r
+\r
+ if (PcdGetBool (PcdOvmfFlashVariablesEnable)) {\r
+ DEBUG ((DEBUG_INFO, "PlatformBdsPolicyBehavior: not restoring NvVars "\r
+ "from disk since flash variables appear to be supported.\n"));\r
+ } else {\r
+ //\r
+ // Try to restore variables from the hard disk early so\r
+ // they can be used for the other BDS connect operations.\r
+ //\r
+ /* XXX Calling this causes Keyboard to be removed from ConIn which\r
+ results in unresponsive guest boot loaders in the GUI. Restore it\r
+ when we figure out what is needed to get NvVars storage done\r
+ properly.\r
+ */\r
+ /*PlatformBdsRestoreNvVarsFromHardDisk ();*/\r
+ }\r
+\r
+ //\r
+ // Get current Boot Mode\r
+ //\r
+ BootMode = GetBootModeHob ();\r
+ DEBUG ((DEBUG_INFO, "Boot Mode:%x\n", BootMode));\r
+\r
+ //\r
+ // Go the different platform policy with different boot mode\r
+ // Notes: this part code can be change with the table policy\r
+ //\r
+ ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);\r
+\r
+ //\r
+ // Logo show\r
+ //\r
+ BootLogoEnableLogo ();\r
+\r
+ //\r
+ // Set PCI Interrupt Line registers and ACPI SCI_EN\r
+ //\r
+ PciAcpiInitialization ();\r
+\r
+ //\r
+ // Process TPM PPI request\r
+ //\r
+ Tcg2PhysicalPresenceLibProcessRequest (NULL);\r
+\r
+ //\r
+ // Perform some platform specific connect sequence\r
+ //\r
+ PlatformBdsConnectSequence ();\r
+\r
+ EfiBootManagerRefreshAllBootOption ();\r
+\r
+ //\r
+ // Register UEFI Shell\r
+ //\r
+ PlatformRegisterFvBootOption (\r
+ &gUefiShellFileGuid, L"EFI Internal Shell", LOAD_OPTION_ACTIVE\r
+ );\r
+\r
+ RemoveStaleFvFileOptions ();\r
+\r
+ PlatformBmPrintScRegisterHandler ();\r
+}\r
+\r
+/**\r
+ This notification function is invoked when an instance of the\r
+ EFI_DEVICE_PATH_PROTOCOL is produced.\r
+\r
+ @param Event The event that occurred\r
+ @param Context For EFI compatibility. Not used.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+NotifyDevPath (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_HANDLE Handle;\r
+ EFI_STATUS Status;\r
+ UINTN BufferSize;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevPathNode;\r
+ ATAPI_DEVICE_PATH *Atapi;\r
+\r
+ //\r
+ // Examine all new handles\r
+ //\r
+ for (;;) {\r
+ //\r
+ // Get the next handle\r
+ //\r
+ BufferSize = sizeof (Handle);\r
+ Status = gBS->LocateHandle (\r
+ ByRegisterNotify,\r
+ NULL,\r
+ mEfiDevPathNotifyReg,\r
+ &BufferSize,\r
+ &Handle\r
+ );\r
+\r
+ //\r
+ // If not found, we're done\r
+ //\r
+ if (EFI_NOT_FOUND == Status) {\r
+ break;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Get the DevicePath protocol on that handle\r
+ //\r
+ Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid,\r
+ (VOID **)&DevPathNode);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ while (!IsDevicePathEnd (DevPathNode)) {\r
+ //\r
+ // Find the handler to dump this device path node\r
+ //\r
+ if (\r
+ (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) &&\r
+ (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP)\r
+ ) {\r
+ Atapi = (ATAPI_DEVICE_PATH*) DevPathNode;\r
+ PciOr16 (\r
+ PCI_LIB_ADDRESS (\r
+ 0,\r
+ 1,\r
+ 1,\r
+ (Atapi->PrimarySecondary == 1) ? 0x42: 0x40\r
+ ),\r
+ BIT15\r
+ );\r
+ }\r
+\r
+ //\r
+ // Next device path node\r
+ //\r
+ DevPathNode = NextDevicePathNode (DevPathNode);\r
+ }\r
+ }\r
+\r
+ return;\r
+}\r
+\r
+\r
+VOID\r
+InstallDevicePathCallback (\r
+ VOID\r
+ )\r
+{\r
+ DEBUG ((DEBUG_INFO, "Registered NotifyDevPath Event\n"));\r
+ mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (\r
+ &gEfiDevicePathProtocolGuid,\r
+ TPL_CALLBACK,\r
+ NotifyDevPath,\r
+ NULL,\r
+ &mEfiDevPathNotifyReg\r
+ );\r
+}\r
+\r
+/**\r
+ This function is called each second during the boot manager waits the\r
+ timeout.\r
+\r
+ @param TimeoutRemain The remaining timeout.\r
+**/\r
+VOID\r
+EFIAPI\r
+PlatformBootManagerWaitCallback (\r
+ UINT16 TimeoutRemain\r
+ )\r
+{\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White;\r
+ UINT16 Timeout;\r
+\r
+ Timeout = PcdGet16 (PcdPlatformBootTimeOut);\r
+\r
+ Black.Raw = 0x00000000;\r
+ White.Raw = 0x00FFFFFF;\r
+\r
+ BootLogoUpdateProgress (\r
+ White.Pixel,\r
+ Black.Pixel,\r
+ L"Start boot option",\r
+ White.Pixel,\r
+ (Timeout - TimeoutRemain) * 100 / Timeout,\r
+ 0\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
--- /dev/null
+/** @file\r
+ Platform BDS customizations include file.\r
+\r
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>\r
+ Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+Module Name:\r
+\r
+ BdsPlatform.h\r
+\r
+Abstract:\r
+\r
+ Head file for BDS Platform specific code\r
+\r
+**/\r
+\r
+#ifndef _PLATFORM_SPECIFIC_BDS_PLATFORM_H_\r
+#define _PLATFORM_SPECIFIC_BDS_PLATFORM_H_\r
+\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <IndustryStandard/Pci.h>\r
+#include <IndustryStandard/Acpi.h>\r
+#include <IndustryStandard/SmBios.h>\r
+#include <IndustryStandard/PeImage.h>\r
+#include <IndustryStandard/Virtio095.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/PciLib.h>\r
+#include <Library/UefiBootManagerLib.h>\r
+#include <Library/BootLogoLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/DxeServicesTableLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/NvVarsFileLib.h>\r
+#include <Library/QemuFwCfgLib.h>\r
+#include <Library/QemuFwCfgS3Lib.h>\r
+#include <Library/QemuBootOrderLib.h>\r
+\r
+#include <Protocol/Decompress.h>\r
+#include <Protocol/PciIo.h>\r
+#include <Protocol/FirmwareVolume2.h>\r
+#include <Protocol/SimpleFileSystem.h>\r
+#include <Protocol/PciRootBridgeIo.h>\r
+#include <Protocol/S3SaveState.h>\r
+#include <Protocol/DxeSmmReadyToLock.h>\r
+#include <Protocol/LoadedImage.h>\r
+\r
+#include <Guid/Acpi.h>\r
+#include <Guid/SmBios.h>\r
+#include <Guid/HobList.h>\r
+#include <Guid/GlobalVariable.h>\r
+#include <Guid/EventGroup.h>\r
+#include <Guid/DebugAgentGuid.h>\r
+\r
+#include <OvmfPlatforms.h>\r
+\r
+extern EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence[];\r
+extern ACPI_HID_DEVICE_PATH gPnpPs2KeyboardDeviceNode;\r
+extern ACPI_HID_DEVICE_PATH gPnp16550ComPortDeviceNode;\r
+extern UART_DEVICE_PATH gUartDeviceNode;\r
+extern VENDOR_DEVICE_PATH gTerminalTypeDeviceNode;\r
+\r
+#define PCI_DEVICE_PATH_NODE(Func, Dev) \\r
+ { \\r
+ { \\r
+ HARDWARE_DEVICE_PATH, \\r
+ HW_PCI_DP, \\r
+ { \\r
+ (UINT8) (sizeof (PCI_DEVICE_PATH)), \\r
+ (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) \\r
+ } \\r
+ }, \\r
+ (Func), \\r
+ (Dev) \\r
+ }\r
+\r
+#define PNPID_DEVICE_PATH_NODE(PnpId) \\r
+ { \\r
+ { \\r
+ ACPI_DEVICE_PATH, \\r
+ ACPI_DP, \\r
+ { \\r
+ (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \\r
+ (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \\r
+ }, \\r
+ }, \\r
+ EISA_PNP_ID((PnpId)), \\r
+ 0 \\r
+ }\r
+\r
+#define gPciIsaBridge \\r
+ PCI_DEVICE_PATH_NODE(0, 0x1f)\r
+\r
+#define gP2PBridge \\r
+ PCI_DEVICE_PATH_NODE(0, 0x1e)\r
+\r
+#define gPnpPs2Keyboard \\r
+ PNPID_DEVICE_PATH_NODE(0x0303)\r
+\r
+#define gPnp16550ComPort \\r
+ PNPID_DEVICE_PATH_NODE(0x0501)\r
+\r
+#define gUart \\r
+ { \\r
+ { \\r
+ MESSAGING_DEVICE_PATH, \\r
+ MSG_UART_DP, \\r
+ { \\r
+ (UINT8) (sizeof (UART_DEVICE_PATH)), \\r
+ (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8) \\r
+ } \\r
+ }, \\r
+ 0, \\r
+ 115200, \\r
+ 8, \\r
+ 1, \\r
+ 1 \\r
+ }\r
+\r
+#define gPcAnsiTerminal \\r
+ { \\r
+ { \\r
+ MESSAGING_DEVICE_PATH, \\r
+ MSG_VENDOR_DP, \\r
+ { \\r
+ (UINT8) (sizeof (VENDOR_DEVICE_PATH)), \\r
+ (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) \\r
+ } \\r
+ }, \\r
+ DEVICE_PATH_MESSAGING_PC_ANSI \\r
+ }\r
+\r
+#define gEndEntire \\r
+ { \\r
+ END_DEVICE_PATH_TYPE, \\r
+ END_ENTIRE_DEVICE_PATH_SUBTYPE, \\r
+ { \\r
+ END_DEVICE_PATH_LENGTH, \\r
+ 0 \\r
+ } \\r
+ }\r
+\r
+#define PCI_CLASS_SCC 0x07\r
+#define PCI_SUBCLASS_SERIAL 0x00\r
+#define PCI_IF_16550 0x02\r
+#define IS_PCI_16550SERIAL(_p) IS_CLASS3 (_p, PCI_CLASS_SCC, PCI_SUBCLASS_SERIAL, PCI_IF_16550)\r
+#define IS_PCI_ISA_PDECODE(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE, 0)\r
+\r
+typedef struct {\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ UINTN ConnectType;\r
+} PLATFORM_CONSOLE_CONNECT_ENTRY;\r
+\r
+#define CONSOLE_OUT BIT0\r
+#define CONSOLE_IN BIT1\r
+#define STD_ERROR BIT2\r
+extern PLATFORM_CONSOLE_CONNECT_ENTRY gPlatformConsole[];\r
+\r
+//\r
+// Platform BDS Functions\r
+//\r
+\r
+VOID\r
+PlatformInitializeConsole (\r
+ IN PLATFORM_CONSOLE_CONNECT_ENTRY *PlatformConsole\r
+ );\r
+\r
+/**\r
+ Loads and boots UEFI Linux via the FwCfg interface.\r
+\r
+ @retval EFI_NOT_FOUND - The Linux kernel was not found\r
+\r
+**/\r
+EFI_STATUS\r
+TryRunningQemuKernel (\r
+ VOID\r
+ );\r
+\r
+#endif // _PLATFORM_SPECIFIC_BDS_PLATFORM_H_\r
--- /dev/null
+## @file\r
+# Platform BDS customizations library.\r
+#\r
+# Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>\r
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# SPDX-License-Identifier: BSD-2-Clause-Patent\r
+#\r
+##\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = PlatformBootManagerLibBhyve\r
+ FILE_GUID = b0de5f0d-f676-42da-8d00-86997ee0dbb4\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ LIBRARY_CLASS = PlatformBootManagerLib|DXE_DRIVER\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 EBC\r
+#\r
+\r
+[Sources]\r
+ BdsPlatform.c\r
+ PlatformData.c\r
+ BdsPlatform.h\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ SourceLevelDebugPkg/SourceLevelDebugPkg.dec\r
+ OvmfPkg/OvmfPkg.dec\r
+ SecurityPkg/SecurityPkg.dec\r
+ ShellPkg/ShellPkg.dec\r
+\r
+[LibraryClasses]\r
+ BaseLib\r
+ MemoryAllocationLib\r
+ UefiBootServicesTableLib\r
+ BaseMemoryLib\r
+ DebugLib\r
+ PcdLib\r
+ UefiBootManagerLib\r
+ BootLogoLib\r
+ DevicePathLib\r
+ PciLib\r
+ NvVarsFileLib\r
+ ReportStatusCodeLib\r
+ UefiLib\r
+ PlatformBmPrintScLib\r
+ Tcg2PhysicalPresenceLib\r
+\r
+[Pcd]\r
+ gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent\r
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable\r
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId\r
+ gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut\r
+\r
+[Pcd.IA32, Pcd.X64]\r
+ gEfiMdePkgTokenSpaceGuid.PcdFSBClock\r
+\r
+[Protocols]\r
+ gEfiDecompressProtocolGuid\r
+ gEfiPciRootBridgeIoProtocolGuid\r
+ gEfiS3SaveStateProtocolGuid # PROTOCOL SOMETIMES_CONSUMED\r
+ gEfiDxeSmmReadyToLockProtocolGuid # PROTOCOL SOMETIMES_PRODUCED\r
+ gEfiLoadedImageProtocolGuid # PROTOCOL SOMETIMES_PRODUCED\r
+ gEfiFirmwareVolume2ProtocolGuid # PROTOCOL SOMETIMES_CONSUMED\r
+\r
+[Guids]\r
+ gEfiEndOfDxeEventGroupGuid\r
+ gRootBridgesConnectedEventGroupGuid\r
+ gUefiShellFileGuid\r
--- /dev/null
+/** @file\r
+ Defined the platform specific device path which will be used by\r
+ platform Bbd to perform the platform policy connect.\r
+\r
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>\r
+ Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include "BdsPlatform.h"\r
+#include <Guid/QemuRamfb.h>\r
+\r
+//\r
+// Debug Agent UART Device Path structure\r
+//\r
+#pragma pack(1)\r
+typedef struct {\r
+ VENDOR_DEVICE_PATH VendorHardware;\r
+ UART_DEVICE_PATH Uart;\r
+ VENDOR_DEVICE_PATH TerminalType;\r
+ EFI_DEVICE_PATH_PROTOCOL End;\r
+} VENDOR_UART_DEVICE_PATH;\r
+#pragma pack()\r
+\r
+//\r
+// USB Keyboard Device Path structure\r
+//\r
+#pragma pack (1)\r
+typedef struct {\r
+ USB_CLASS_DEVICE_PATH Keyboard;\r
+ EFI_DEVICE_PATH_PROTOCOL End;\r
+} USB_KEYBOARD_DEVICE_PATH;\r
+#pragma pack ()\r
+\r
+//\r
+// QemuRamfb Device Path structure\r
+//\r
+#pragma pack (1)\r
+typedef struct {\r
+ VENDOR_DEVICE_PATH Vendor;\r
+ ACPI_ADR_DEVICE_PATH AcpiAdr;\r
+ EFI_DEVICE_PATH_PROTOCOL End;\r
+} VENDOR_RAMFB_DEVICE_PATH;\r
+#pragma pack ()\r
+\r
+ACPI_HID_DEVICE_PATH gPnpPs2KeyboardDeviceNode = gPnpPs2Keyboard;\r
+ACPI_HID_DEVICE_PATH gPnp16550ComPortDeviceNode = gPnp16550ComPort;\r
+UART_DEVICE_PATH gUartDeviceNode = gUart;\r
+VENDOR_DEVICE_PATH gTerminalTypeDeviceNode = gPcAnsiTerminal;\r
+\r
+//\r
+// Platform specific keyboard device path\r
+//\r
+\r
+\r
+//\r
+// Debug Agent UART Device Path\r
+//\r
+VENDOR_UART_DEVICE_PATH gDebugAgentUartDevicePath = {\r
+ {\r
+ {\r
+ HARDWARE_DEVICE_PATH,\r
+ HW_VENDOR_DP,\r
+ {\r
+ (UINT8) (sizeof (VENDOR_DEVICE_PATH)),\r
+ (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
+ }\r
+ },\r
+ EFI_DEBUG_AGENT_GUID,\r
+ },\r
+ {\r
+ {\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_UART_DP,\r
+ {\r
+ (UINT8) (sizeof (UART_DEVICE_PATH)),\r
+ (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8)\r
+ }\r
+ },\r
+ 0, // Reserved\r
+ 0, // BaudRate - Default\r
+ 0, // DataBits - Default\r
+ 0, // Parity - Default\r
+ 0, // StopBits - Default\r
+ },\r
+ gPcAnsiTerminal,\r
+ gEndEntire\r
+};\r
+\r
+STATIC USB_KEYBOARD_DEVICE_PATH gUsbKeyboardDevicePath = {\r
+ {\r
+ {\r
+ MESSAGING_DEVICE_PATH,\r
+ MSG_USB_CLASS_DP,\r
+ {\r
+ (UINT8)sizeof (USB_CLASS_DEVICE_PATH),\r
+ (UINT8)(sizeof (USB_CLASS_DEVICE_PATH) >> 8)\r
+ }\r
+ },\r
+ 0xFFFF, // VendorId: any\r
+ 0xFFFF, // ProductId: any\r
+ 3, // DeviceClass: HID\r
+ 1, // DeviceSubClass: boot\r
+ 1 // DeviceProtocol: keyboard\r
+ },\r
+ gEndEntire\r
+};\r
+\r
+STATIC VENDOR_RAMFB_DEVICE_PATH gQemuRamfbDevicePath = {\r
+ {\r
+ {\r
+ HARDWARE_DEVICE_PATH,\r
+ HW_VENDOR_DP,\r
+ {\r
+ (UINT8) (sizeof (VENDOR_DEVICE_PATH)),\r
+ (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
+ }\r
+ },\r
+ QEMU_RAMFB_GUID,\r
+ },\r
+ {\r
+ {\r
+ ACPI_DEVICE_PATH,\r
+ ACPI_ADR_DP,\r
+ {\r
+ (UINT8) (sizeof (ACPI_ADR_DEVICE_PATH)),\r
+ (UINT8) ((sizeof (ACPI_ADR_DEVICE_PATH)) >> 8)\r
+ }\r
+ },\r
+ ACPI_DISPLAY_ADR (\r
+ 1, // DeviceIdScheme\r
+ 0, // HeadId\r
+ 0, // NonVgaOutput\r
+ 1, // BiosCanDetect\r
+ 0, // VendorInfo\r
+ ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL, // Type\r
+ 0, // Port\r
+ 0 // Index\r
+ ),\r
+ },\r
+ gEndEntire\r
+};\r
+\r
+//\r
+// Predefined platform default console device path\r
+//\r
+PLATFORM_CONSOLE_CONNECT_ENTRY gPlatformConsole[] = {\r
+ {\r
+ (EFI_DEVICE_PATH_PROTOCOL *) &gDebugAgentUartDevicePath,\r
+ (CONSOLE_OUT | CONSOLE_IN | STD_ERROR)\r
+ },\r
+ {\r
+ (EFI_DEVICE_PATH_PROTOCOL *)&gUsbKeyboardDevicePath,\r
+ CONSOLE_IN\r
+ },\r
+ {\r
+ (EFI_DEVICE_PATH_PROTOCOL *)&gQemuRamfbDevicePath,\r
+ CONSOLE_OUT\r
+ },\r
+ {\r
+ NULL,\r
+ 0\r
+ }\r
+};\r
+\r
+//\r
+// Predefined platform connect sequence\r
+//\r
+EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence[] = { NULL };\r
+\r
## @file\r
# EFI/Framework Open Virtual Machine Firmware (OVMF) platform\r
#\r
+# Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>\r
# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2014, Pluribus Networks, Inc.\r
#\r
# SPDX-License-Identifier: BSD-2-Clause-Patent\r
#\r
Csm/Include\r
\r
[LibraryClasses]\r
+ ## @libraryclass Access bhyve's firmware control interface.\r
+ BhyveFwCtlLib|Include/Library/BhyveFwCtlLib.h\r
+\r
## @libraryclass Loads and boots a Linux kernel image\r
#\r
LoadLinuxLib|Include/Library/LoadLinuxLib.h\r