RETURN_STATUS EFIAPI QemuFwCfgInitialize ( VOID ) { UINT32 Signature; UINT32 Revision; // // Enable the access routines while probing to see if it is supported. // mQemuFwCfgSupported = TRUE; QemuFwCfgSelectItem (QemuFwCfgItemSignature); Signature = QemuFwCfgRead32 (); DEBUG ((EFI_D_INFO, "FW CFG Signature: 0x%x\n", Signature)); QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion); Revision = QemuFwCfgRead32 (); DEBUG ((EFI_D_INFO, "FW CFG Revision: 0x%x\n", Revision)); if ((Signature != SIGNATURE_32 ('Q', 'E', 'M', 'U')) || (Revision < 1) ) { DEBUG ((EFI_D_INFO, "QemuFwCfg interface not supported.\n")); mQemuFwCfgSupported = FALSE; return RETURN_SUCCESS; } DEBUG ((EFI_D_INFO, "QemuFwCfg interface is supported.\n")); return RETURN_SUCCESS; }
/** Returns a boolean indicating if the firmware configuration interface is available or not. This function may change fw_cfg state. @retval TRUE The interface is available @retval FALSE The interface is not available **/ BOOLEAN EFIAPI QemuFwCfgIsAvailable ( VOID ) { UINT32 Signature; UINT32 Revision; QemuFwCfgSelectItem (QemuFwCfgItemSignature); Signature = QemuFwCfgRead32 (); DEBUG ((EFI_D_INFO, "FW CFG Signature: 0x%x\n", Signature)); QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion); Revision = QemuFwCfgRead32 (); DEBUG ((EFI_D_INFO, "FW CFG Revision: 0x%x\n", Revision)); if ((Signature != SIGNATURE_32 ('Q', 'E', 'M', 'U')) || (Revision < 1) ) { DEBUG ((EFI_D_INFO, "QemuFwCfg interface not supported.\n")); return FALSE; } DEBUG ((EFI_D_INFO, "QemuFwCfg interface is supported.\n")); return TRUE; }
RETURN_STATUS EFIAPI QemuFwCfgInitialize ( VOID ) { UINT32 Signature; UINT32 Revision; // // Enable the access routines while probing to see if it is supported. // For probing we always use the IO Port (IoReadFifo8()) access method. // mQemuFwCfgSupported = TRUE; mQemuFwCfgDmaSupported = FALSE; QemuFwCfgSelectItem (QemuFwCfgItemSignature); Signature = QemuFwCfgRead32 (); DEBUG ((EFI_D_INFO, "FW CFG Signature: 0x%x\n", Signature)); QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion); Revision = QemuFwCfgRead32 (); DEBUG ((EFI_D_INFO, "FW CFG Revision: 0x%x\n", Revision)); if ((Signature != SIGNATURE_32 ('Q', 'E', 'M', 'U')) || (Revision < 1) ) { DEBUG ((EFI_D_INFO, "QemuFwCfg interface not supported.\n")); mQemuFwCfgSupported = FALSE; return RETURN_SUCCESS; } if ((Revision & FW_CFG_F_DMA) == 0) { DEBUG ((DEBUG_INFO, "QemuFwCfg interface (IO Port) is supported.\n")); } else { mQemuFwCfgDmaSupported = TRUE; DEBUG ((DEBUG_INFO, "QemuFwCfg interface (DMA) is supported.\n")); } if (mQemuFwCfgDmaSupported && MemEncryptSevIsEnabled ()) { EFI_STATUS Status; // // IoMmuDxe driver must have installed the IOMMU protocol. If we are not // able to locate the protocol then something must have gone wrong. // Status = gBS->LocateProtocol (&gEdkiiIoMmuProtocolGuid, NULL, (VOID **)&mIoMmuProtocol); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "QemuFwCfgSevDma %a:%a Failed to locate IOMMU protocol.\n", gEfiCallerBaseName, __FUNCTION__)); ASSERT (FALSE); CpuDeadLoop (); } } return RETURN_SUCCESS; }
RETURN_STATUS EFIAPI QemuFwCfgInitialize ( VOID ) { UINT32 Signature; UINT32 Revision; // // Enable the access routines while probing to see if it is supported. // For probing we always use the IO Port (IoReadFifo8()) access method. // mQemuFwCfgSupported = TRUE; mQemuFwCfgDmaSupported = FALSE; QemuFwCfgSelectItem (QemuFwCfgItemSignature); Signature = QemuFwCfgRead32 (); DEBUG ((EFI_D_INFO, "FW CFG Signature: 0x%x\n", Signature)); QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion); Revision = QemuFwCfgRead32 (); DEBUG ((EFI_D_INFO, "FW CFG Revision: 0x%x\n", Revision)); if ((Signature != SIGNATURE_32 ('Q', 'E', 'M', 'U')) || (Revision < 1) ) { DEBUG ((EFI_D_INFO, "QemuFwCfg interface not supported.\n")); mQemuFwCfgSupported = FALSE; return RETURN_SUCCESS; } if ((Revision & FW_CFG_F_DMA) == 0) { DEBUG ((DEBUG_INFO, "QemuFwCfg interface (IO Port) is supported.\n")); } else { // // If SEV is enabled then we do not support DMA operations in PEI phase. // This is mainly because DMA in SEV guest requires using bounce buffer // (which need to allocate dynamic memory and allocating a PAGE size'd // buffer can be challenge in PEI phase) // if (MemEncryptSevIsEnabled ()) { DEBUG ((DEBUG_INFO, "SEV: QemuFwCfg fallback to IO Port interface.\n")); } else { mQemuFwCfgDmaSupported = TRUE; DEBUG ((DEBUG_INFO, "QemuFwCfg interface (DMA) is supported.\n")); } } return RETURN_SUCCESS; }
RETURN_STATUS EFIAPI QemuFwCfgInitialize ( VOID ) { EFI_STATUS Status; FDT_CLIENT_PROTOCOL *FdtClient; CONST UINT64 *Reg; UINT32 RegSize; UINTN AddressCells, SizeCells; UINT64 FwCfgSelectorAddress; UINT64 FwCfgSelectorSize; UINT64 FwCfgDataAddress; UINT64 FwCfgDataSize; UINT64 FwCfgDmaAddress; UINT64 FwCfgDmaSize; Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL, (VOID **)&FdtClient); ASSERT_EFI_ERROR (Status); Status = FdtClient->FindCompatibleNodeReg (FdtClient, "qemu,fw-cfg-mmio", (CONST VOID **)&Reg, &AddressCells, &SizeCells, &RegSize); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_WARN, "%a: No 'qemu,fw-cfg-mmio' compatible DT node found (Status == %r)\n", __FUNCTION__, Status)); return EFI_SUCCESS; } ASSERT (AddressCells == 2); ASSERT (SizeCells == 2); ASSERT (RegSize == 2 * sizeof (UINT64)); FwCfgDataAddress = SwapBytes64 (Reg[0]); FwCfgDataSize = 8; FwCfgSelectorAddress = FwCfgDataAddress + FwCfgDataSize; FwCfgSelectorSize = 2; // // The following ASSERT()s express // // Address + Size - 1 <= MAX_UINTN // // for both registers, that is, that the last byte in each MMIO range is // expressible as a MAX_UINTN. The form below is mathematically // equivalent, and it also prevents any unsigned overflow before the // comparison. // ASSERT (FwCfgSelectorAddress <= MAX_UINTN - FwCfgSelectorSize + 1); ASSERT (FwCfgDataAddress <= MAX_UINTN - FwCfgDataSize + 1); mFwCfgSelectorAddress = FwCfgSelectorAddress; mFwCfgDataAddress = FwCfgDataAddress; DEBUG ((EFI_D_INFO, "Found FwCfg @ 0x%Lx/0x%Lx\n", FwCfgSelectorAddress, FwCfgDataAddress)); if (SwapBytes64 (Reg[1]) >= 0x18) { FwCfgDmaAddress = FwCfgDataAddress + 0x10; FwCfgDmaSize = 0x08; // // See explanation above. // ASSERT (FwCfgDmaAddress <= MAX_UINTN - FwCfgDmaSize + 1); DEBUG ((EFI_D_INFO, "Found FwCfg DMA @ 0x%Lx\n", FwCfgDmaAddress)); } else { FwCfgDmaAddress = 0; } if (InternalQemuFwCfgIsAvailable ()) { UINT32 Signature; QemuFwCfgSelectItem (QemuFwCfgItemSignature); Signature = QemuFwCfgRead32 (); if (Signature == SIGNATURE_32 ('Q', 'E', 'M', 'U')) { // // For DMA support, we require the DTB to advertise the register, and the // feature bitmap (which we read without DMA) to confirm the feature. // if (FwCfgDmaAddress != 0) { UINT32 Features; QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion); Features = QemuFwCfgRead32 (); if ((Features & BIT1) != 0) { mFwCfgDmaAddress = FwCfgDmaAddress; InternalQemuFwCfgReadBytes = DmaReadBytes; } } } else { mFwCfgSelectorAddress = 0; mFwCfgDataAddress = 0; } } return RETURN_SUCCESS; }
/** Install default (fallback) table for SMBIOS Type 1. In case QEMU has provided no Type 1 SMBIOS table in whole, prepare one here, patch it with any referring saved patches, and install it. @param[in] Smbios The EFI_SMBIOS_PROTOCOL instance used for installing SMBIOS tables. @param[in] ProducerHandle Passed on to Smbios->Add(), ProducerHandle tracks the origin of installed SMBIOS tables. @param[in,out] Context The BUILD_CONTEXT object tracking installed tables and saved patches. @retval EFI_SUCCESS A Type 1 table has already been installed from the SMBIOS firmware configuration blob. @retval EFI_SUCCESS No Type 1 table was installed previously, and installing the default here has succeeded. @return Error codes from the PATCH_FORMATTED() and PATCH_UNFORMATTED() macros, except EFI_NOT_FOUND, which is only an informative result of theirs. **/ EFI_STATUS EFIAPI InstallSmbiosType1 ( IN EFI_SMBIOS_PROTOCOL *Smbios, IN EFI_HANDLE ProducerHandle, IN OUT BUILD_CONTEXT *Context ) { TABLE_CONTEXT *Table; OVMF_TYPE1 OvmfType1; EFI_STATUS Status; EFI_SMBIOS_HANDLE SmbiosHandle; Table = &Context->Table[1]; if (Table->Installed) { return EFI_SUCCESS; } CopyMem (&OvmfType1, &mOvmfType1, sizeof OvmfType1); QemuFwCfgSelectItem (QemuFwCfgItemSystemUuid); OvmfType1.Base.Uuid.Data1 = SwapBytes32 (QemuFwCfgRead32 ()); OvmfType1.Base.Uuid.Data2 = SwapBytes16 (QemuFwCfgRead16 ()); OvmfType1.Base.Uuid.Data3 = SwapBytes16 (QemuFwCfgRead16 ()); QemuFwCfgReadBytes (sizeof OvmfType1.Base.Uuid.Data4, &OvmfType1.Base.Uuid.Data4); // // Default contents ready. Formatted fields must be patched before installing // the table, while strings in the unformatted area will be patched // afterwards. // Status = PATCH_FORMATTED (Context, 1, &OvmfType1, Uuid); switch (Status) { case EFI_NOT_FOUND: break; case EFI_SUCCESS: OvmfType1.Base.Uuid.Data1 = SwapBytes32 (OvmfType1.Base.Uuid.Data1); OvmfType1.Base.Uuid.Data2 = SwapBytes16 (OvmfType1.Base.Uuid.Data2); OvmfType1.Base.Uuid.Data3 = SwapBytes16 (OvmfType1.Base.Uuid.Data3); break; default: return Status; } Status = PATCH_FORMATTED (Context, 1, &OvmfType1, WakeUpType); if (Status != EFI_NOT_FOUND && Status != EFI_SUCCESS) { return Status; } // // Install SMBIOS table with patched formatted area and default strings. // SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; Status = Smbios->Add (Smbios, ProducerHandle, &SmbiosHandle, (EFI_SMBIOS_TABLE_HEADER *) &OvmfType1); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a: Smbios->Add(): %r\n", __FUNCTION__, Status)); return Status; } Table->Installed = TRUE; // // Patch strings in the unformatted area of the installed table. // Status = PATCH_UNFORMATTED (Smbios, SmbiosHandle, Context, 1, &OvmfType1, Manufacturer); if (Status != EFI_NOT_FOUND && Status != EFI_SUCCESS) { return Status; } Status = PATCH_UNFORMATTED (Smbios, SmbiosHandle, Context, 1, &OvmfType1, ProductName); if (Status != EFI_NOT_FOUND && Status != EFI_SUCCESS) { return Status; } Status = PATCH_UNFORMATTED (Smbios, SmbiosHandle, Context, 1, &OvmfType1, Version); if (Status != EFI_NOT_FOUND && Status != EFI_SUCCESS) { return Status; } Status = PATCH_UNFORMATTED (Smbios, SmbiosHandle, Context, 1, &OvmfType1, SerialNumber); if (Status != EFI_NOT_FOUND && Status != EFI_SUCCESS) { return Status; } Status = PATCH_UNFORMATTED (Smbios, SmbiosHandle, Context, 1, &OvmfType1, SKUNumber); if (Status != EFI_NOT_FOUND && Status != EFI_SUCCESS) { return Status; } Status = PATCH_UNFORMATTED (Smbios, SmbiosHandle, Context, 1, &OvmfType1, Family); if (Status != EFI_NOT_FOUND && Status != EFI_SUCCESS) { return Status; } return EFI_SUCCESS; }