From a145e28decc529bf26981ae57c3fc2ffe0b946f2 Mon Sep 17 00:00:00 2001 From: Gabriel Somlo Date: Tue, 20 May 2014 16:33:19 +0000 Subject: [PATCH] OvmfPkg/SMBIOS: Add QEMU support to OVMF SMBIOS driver Locate QEMU SMBIOS data in fw_cfg and install it via the SMBIOS protocol. Starting with qemu-2.1, on pc/x86 machines of type >= 2.1, full SMBIOS tables are generated and inserted into fw_cfg (i.e., no per-field patching of locally generated structures is required). Aside from new code to extract a SMBIOS blob from fw_cfg, this patch utilizes the pre-existing infrastructure (already used by Xen) to handle final SMBIOS table creation. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Gabriel Somlo Reviewed-by: Laszlo Ersek Reviewed-by: Jordan Justen git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15542 6f19259b-4bc3-4df7-8a09-765794883524 --- OvmfPkg/SmbiosPlatformDxe/Qemu.c | 66 +++++++++++++++++++ OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c | 24 +++++-- OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.h | 13 ++++ .../SmbiosPlatformDxe/SmbiosPlatformDxe.inf | 3 + 4 files changed, 101 insertions(+), 5 deletions(-) create mode 100644 OvmfPkg/SmbiosPlatformDxe/Qemu.c 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