diff --git a/OvmfPkg/SmbiosPlatformDxe/Qemu.c b/OvmfPkg/SmbiosPlatformDxe/Qemu.c new file mode 100644 index 0000000000..f7ace4f1de --- /dev/null +++ b/OvmfPkg/SmbiosPlatformDxe/Qemu.c @@ -0,0 +1,66 @@ +/** @file + Find and extract QEMU SMBIOS data from fw_cfg. + + Copyright (C) 2014, Gabriel L. Somlo + + This program and the accompanying materials are licensed and made + available under the terms and conditions of the BSD License which + accompanies this distribution. The full text of the license may + be found at http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#include "SmbiosPlatformDxe.h" +#include +#include + +/** + Locates and extracts the QEMU SMBIOS data if present in fw_cfg + + @return Address of extracted QEMU SMBIOS data + +**/ +UINT8 * +GetQemuSmbiosTables ( + VOID + ) +{ + SMBIOS_TABLE_ENTRY_POINT QemuAnchor; + FIRMWARE_CONFIG_ITEM Anchor, Tables; + UINTN AnchorSize, TablesSize; + UINT8 *QemuTables; + + if (EFI_ERROR (QemuFwCfgFindFile ( + "etc/smbios/smbios-anchor", &Anchor, &AnchorSize)) || + EFI_ERROR (QemuFwCfgFindFile ( + "etc/smbios/smbios-tables", &Tables, &TablesSize)) || + AnchorSize != sizeof (QemuAnchor) || + TablesSize == 0) { + return NULL; + } + + // + // We copy the entry point structure to perform some additional checks, + // but discard it upon return. + // + QemuFwCfgSelectItem (Anchor); + QemuFwCfgReadBytes (AnchorSize, &QemuAnchor); + + if (AsciiStrnCmp ((CHAR8 *)QemuAnchor.AnchorString, "_SM_", 4) || + AsciiStrnCmp ((CHAR8 *)QemuAnchor.IntermediateAnchorString, "_DMI_", 5) || + TablesSize != QemuAnchor.TableLength) { + return NULL; + } + + QemuTables = AllocatePool (TablesSize); + if (QemuTables == NULL) { + return NULL; + } + + QemuFwCfgSelectItem (Tables); + QemuFwCfgReadBytes (TablesSize, QemuTables); + + return QemuTables; +} diff --git a/OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c b/OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c index ac48fb7208..626f7dbbfb 100644 --- a/OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c +++ b/OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c @@ -84,20 +84,20 @@ SmbiosTableLength ( Install all structures from the given SMBIOS structures block @param Smbios SMBIOS protocol - @param EntryPointStructure SMBIOS entry point structures block + @param TableAddress SMBIOS tables starting address **/ EFI_STATUS InstallAllStructures ( IN EFI_SMBIOS_PROTOCOL *Smbios, - IN SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure + IN UINT8 *TableAddress ) { EFI_STATUS Status; SMBIOS_STRUCTURE_POINTER SmbiosTable; EFI_SMBIOS_HANDLE SmbiosHandle; - SmbiosTable.Raw = (UINT8*)(UINTN) EntryPointStructure->TableAddress; + SmbiosTable.Raw = TableAddress; if (SmbiosTable.Raw == NULL) { return EFI_INVALID_PARAMETER; } @@ -145,6 +145,7 @@ SmbiosTablePublishEntry ( EFI_STATUS Status; EFI_SMBIOS_PROTOCOL *Smbios; SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure; + UINT8 *SmbiosTables; // // Find the SMBIOS protocol @@ -159,11 +160,24 @@ SmbiosTablePublishEntry ( } // - // Add Xen SMBIOS data if found + // Add Xen or QEMU SMBIOS data if found // EntryPointStructure = GetXenSmbiosTables (); if (EntryPointStructure != NULL) { - Status = InstallAllStructures (Smbios, EntryPointStructure); + SmbiosTables = (UINT8*)(UINTN)EntryPointStructure->TableAddress; + } else { + SmbiosTables = GetQemuSmbiosTables (); + } + + if (SmbiosTables != NULL) { + Status = InstallAllStructures (Smbios, SmbiosTables); + + // + // Free SmbiosTables if allocated by Qemu (i.e., NOT by Xen): + // + if (EntryPointStructure == NULL) { + FreePool (SmbiosTables); + } } return Status; diff --git a/OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.h b/OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.h index bf99e43ba3..e2606e1de8 100644 --- a/OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.h +++ b/OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.h @@ -25,6 +25,7 @@ #include #include #include +#include /** @@ -39,6 +40,18 @@ GetXenSmbiosTables ( ); +/** + Locates and extracts the QEMU SMBIOS table data if present in fw_cfg + + @return Address of extracted QEMU SMBIOS data + +**/ +UINT8 * +GetQemuSmbiosTables ( + VOID + ); + + /** Validates the SMBIOS entry point structure diff --git a/OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf b/OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf index 7058284944..6596392095 100644 --- a/OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf +++ b/OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf @@ -32,6 +32,7 @@ SmbiosPlatformDxe.h SmbiosPlatformDxe.c Xen.c + Qemu.c [Packages] MdePkg/MdePkg.dec @@ -45,6 +46,8 @@ UefiDriverEntryPoint DebugLib HobLib + QemuFwCfgLib + MemoryAllocationLib [Protocols] gEfiSmbiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED