Blame 0001-OvmfPkg-SmbiosPlatformDxe-install-legacy-QEMU-tables.patch

Gerd Hoffmann b0c3af
From 0e182f2305a84fdf62ff2631de6e363a5a881287 Mon Sep 17 00:00:00 2001
Gerd Hoffmann b0c3af
From: Laszlo Ersek <lersek@redhat.com>
Gerd Hoffmann b0c3af
Date: Wed, 5 Jun 2013 10:14:34 +0200
Gerd Hoffmann b0c3af
Subject: [PATCH 1/3] OvmfPkg/SmbiosPlatformDxe: install legacy QEMU tables and
Gerd Hoffmann b0c3af
 save fields (X86)
Gerd Hoffmann b0c3af
Gerd Hoffmann b0c3af
Introduce basic legacy SMBIOS machinery for the QEMU platform:
Gerd Hoffmann b0c3af
- Install SMBIOS tables that QEMU passes down in complete form via fw_cfg.
Gerd Hoffmann b0c3af
- Stash individual fields that QEMU passes down to override the boot
Gerd Hoffmann b0c3af
  firmware's default SMBIOS tables.
Gerd Hoffmann b0c3af
- Add helper functions that OVMF's default SMBIOS tables will need.
Gerd Hoffmann b0c3af
Gerd Hoffmann b0c3af
Contributed-under: TianoCore Contribution Agreement 1.0
Gerd Hoffmann b0c3af
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Gerd Hoffmann b0c3af
---
Gerd Hoffmann b0c3af
 OvmfPkg/SmbiosPlatformDxe/QemuLegacy.c          | 694 ++++++++++++++++++++++++
Gerd Hoffmann b0c3af
 OvmfPkg/SmbiosPlatformDxe/QemuLegacy.h          |  52 ++
Gerd Hoffmann b0c3af
 OvmfPkg/SmbiosPlatformDxe/QemuLegacyInternal.h  | 221 ++++++++
Gerd Hoffmann b0c3af
 OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c   |  17 +-
Gerd Hoffmann b0c3af
 OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf |   2 +
Gerd Hoffmann b0c3af
 5 files changed, 983 insertions(+), 3 deletions(-)
Gerd Hoffmann b0c3af
 create mode 100644 OvmfPkg/SmbiosPlatformDxe/QemuLegacy.c
Gerd Hoffmann b0c3af
 create mode 100644 OvmfPkg/SmbiosPlatformDxe/QemuLegacy.h
Gerd Hoffmann b0c3af
 create mode 100644 OvmfPkg/SmbiosPlatformDxe/QemuLegacyInternal.h
Gerd Hoffmann b0c3af
Gerd Hoffmann b0c3af
diff --git a/OvmfPkg/SmbiosPlatformDxe/QemuLegacy.c b/OvmfPkg/SmbiosPlatformDxe/QemuLegacy.c
Gerd Hoffmann b0c3af
new file mode 100644
Gerd Hoffmann b0c3af
index 0000000..9c57558
Gerd Hoffmann b0c3af
--- /dev/null
Gerd Hoffmann b0c3af
+++ b/OvmfPkg/SmbiosPlatformDxe/QemuLegacy.c
Gerd Hoffmann b0c3af
@@ -0,0 +1,694 @@
Gerd Hoffmann b0c3af
+/** @file
Gerd Hoffmann b0c3af
+  This file fetches and installs SMBIOS tables on the QEMU hypervisor.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  Copyright (C) 2013, Red Hat, Inc.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  This program and the accompanying materials are licensed and made available
Gerd Hoffmann b0c3af
+  under the terms and conditions of the BSD License which accompanies this
Gerd Hoffmann b0c3af
+  distribution.  The full text of the license may be found at
Gerd Hoffmann b0c3af
+  http://opensource.org/licenses/bsd-license.php
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
Gerd Hoffmann b0c3af
+  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Gerd Hoffmann b0c3af
+**/
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+#include <Library/MemoryAllocationLib.h>
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+#include "QemuLegacy.h"
Gerd Hoffmann b0c3af
+#include "QemuLegacyInternal.h"
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+//
Gerd Hoffmann b0c3af
+// An SMBIOS entry exported by QEMU over fw_cfg can have one of the following
Gerd Hoffmann b0c3af
+// types.
Gerd Hoffmann b0c3af
+//
Gerd Hoffmann b0c3af
+typedef enum
Gerd Hoffmann b0c3af
+{
Gerd Hoffmann b0c3af
+  ET_FIELD, // defines one field in some SMBIOS table
Gerd Hoffmann b0c3af
+  ET_TABLE  // defines an SMBIOS table instance in entirety
Gerd Hoffmann b0c3af
+} FW_CFG_SMBIOS_ENTRY_TYPE;
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+//
Gerd Hoffmann b0c3af
+// Header type introducing each entry in the QemuFwCfgItemX86SmbiosTables
Gerd Hoffmann b0c3af
+// fw_cfg blob.
Gerd Hoffmann b0c3af
+//
Gerd Hoffmann b0c3af
+#pragma pack(1)
Gerd Hoffmann b0c3af
+typedef struct {
Gerd Hoffmann b0c3af
+  UINT16 Size; // including payload and this header
Gerd Hoffmann b0c3af
+  UINT8  Type; // value from FW_CFG_SMBIOS_ENTRY_TYPE
Gerd Hoffmann b0c3af
+} FW_CFG_SMBIOS_ENTRY_HDR;
Gerd Hoffmann b0c3af
+#pragma pack()
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+//
Gerd Hoffmann b0c3af
+// Fields included at the beginning of the the payload in QEMU SMBIOS entries
Gerd Hoffmann b0c3af
+// with ET_FIELD type.
Gerd Hoffmann b0c3af
+//
Gerd Hoffmann b0c3af
+#pragma pack(1)
Gerd Hoffmann b0c3af
+typedef struct {
Gerd Hoffmann b0c3af
+  UINT8  TableType; // SMBIOS table type to patch
Gerd Hoffmann b0c3af
+  UINT16 Offset;    // offset of a field in the formatted area
Gerd Hoffmann b0c3af
+} FW_CFG_SMBIOS_FIELD;
Gerd Hoffmann b0c3af
+#pragma pack()
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+/**
Gerd Hoffmann b0c3af
+  Initialize a context object tracking SMBIOS table installation and patches
Gerd Hoffmann b0c3af
+  for fields.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  @param[out] Context  A BUILD_CONTEXT object allocated dynamically and
Gerd Hoffmann b0c3af
+                       initialized.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
Gerd Hoffmann b0c3af
+  @retval EFI_SUCCESS           Allocation and initialization successful.
Gerd Hoffmann b0c3af
+**/
Gerd Hoffmann b0c3af
+STATIC
Gerd Hoffmann b0c3af
+EFI_STATUS
Gerd Hoffmann b0c3af
+EFIAPI
Gerd Hoffmann b0c3af
+InitSmbiosContext (
Gerd Hoffmann b0c3af
+  OUT BUILD_CONTEXT **Context
Gerd Hoffmann b0c3af
+  )
Gerd Hoffmann b0c3af
+{
Gerd Hoffmann b0c3af
+  *Context = AllocateZeroPool (sizeof **Context);
Gerd Hoffmann b0c3af
+  if (*Context == NULL) {
Gerd Hoffmann b0c3af
+    DEBUG ((DEBUG_ERROR, "%a: out of memory\n", __FUNCTION__));
Gerd Hoffmann b0c3af
+    return EFI_OUT_OF_RESOURCES;
Gerd Hoffmann b0c3af
+  }
Gerd Hoffmann b0c3af
+  return EFI_SUCCESS;
Gerd Hoffmann b0c3af
+}
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+/**
Gerd Hoffmann b0c3af
+  Release a context object tracking SMBIOS table installation and patches for
Gerd Hoffmann b0c3af
+  fields.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  @param[in,out] Context  The BUILD_CONTEXT object to tear down.
Gerd Hoffmann b0c3af
+**/
Gerd Hoffmann b0c3af
+STATIC
Gerd Hoffmann b0c3af
+VOID
Gerd Hoffmann b0c3af
+EFIAPI
Gerd Hoffmann b0c3af
+UninitSmbiosContext (
Gerd Hoffmann b0c3af
+  IN OUT BUILD_CONTEXT *Context
Gerd Hoffmann b0c3af
+  )
Gerd Hoffmann b0c3af
+{
Gerd Hoffmann b0c3af
+  INT32 Type;
Gerd Hoffmann b0c3af
+  INT32 Idx;
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  //
Gerd Hoffmann b0c3af
+  // free all patches
Gerd Hoffmann b0c3af
+  //
Gerd Hoffmann b0c3af
+  for (Type = 0; Type < TABLE_TYPE_LIMIT; ++Type) {
Gerd Hoffmann b0c3af
+    for (Idx = 0; Idx < PATCH_SUBSCRIPT_LIMIT; ++Idx) {
Gerd Hoffmann b0c3af
+      PATCH *Patch;
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+      Patch = &Context->Table[Type].Patch[Idx];
Gerd Hoffmann b0c3af
+      if (Patch->Base != NULL) {
Gerd Hoffmann b0c3af
+        FreePool (Patch->Base);
Gerd Hoffmann b0c3af
+      }
Gerd Hoffmann b0c3af
+    }
Gerd Hoffmann b0c3af
+  }
Gerd Hoffmann b0c3af
+  FreePool (Context);
Gerd Hoffmann b0c3af
+}
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+/**
Gerd Hoffmann b0c3af
+  Save a patch targeting an SMBIOS field in dynamically allocated memory.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  @param[in,out] Context      The initialized BUILD_CONTEXT object to save the
Gerd Hoffmann b0c3af
+                              patch in.
Gerd Hoffmann b0c3af
+  @param[in]     TableType    The patch to be saved targets this table type.
Gerd Hoffmann b0c3af
+                              Patches for table types equal to or greater than
Gerd Hoffmann b0c3af
+                              TABLE_TYPE_LIMIT are ignored.
Gerd Hoffmann b0c3af
+  @param[in]     FieldOffset  The patch to be saved targets the field that
Gerd Hoffmann b0c3af
+                              begins at offset FieldOffset in SMBIOS table type
Gerd Hoffmann b0c3af
+                              TableType. FieldOffset is enforced not to point
Gerd Hoffmann b0c3af
+                              into the SMBIOS table header. A FieldOffset value
Gerd Hoffmann b0c3af
+                              equal to or greater than 255 is rejected, since
Gerd Hoffmann b0c3af
+                              the formatted area of an SMBIOS table never
Gerd Hoffmann b0c3af
+                              exceeds 255 bytes. FieldOffset is not validated
Gerd Hoffmann b0c3af
+                              against actual field offsets here, it is only
Gerd Hoffmann b0c3af
+                              saved for later lookup.
Gerd Hoffmann b0c3af
+  @param[in]     PatchData    Byte array constituting the patch body.
Gerd Hoffmann b0c3af
+  @param[in]     PatchSize    Number of bytes in PatchData.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  @retval EFI_SUCCESS            Patch has been either ignored due to not
Gerd Hoffmann b0c3af
+                                 meeting the criterion on TableType, or it has
Gerd Hoffmann b0c3af
+                                 been saved successfully.
Gerd Hoffmann b0c3af
+  @retval EFI_INVALID_PARAMETER  FieldOffset is invalid.
Gerd Hoffmann b0c3af
+  @retval EFI_OUT_OF_RESOURCES   Couldn't allocate memory for the patch.
Gerd Hoffmann b0c3af
+**/
Gerd Hoffmann b0c3af
+STATIC
Gerd Hoffmann b0c3af
+EFI_STATUS
Gerd Hoffmann b0c3af
+EFIAPI
Gerd Hoffmann b0c3af
+SaveSmbiosPatch (
Gerd Hoffmann b0c3af
+  IN OUT BUILD_CONTEXT *Context,
Gerd Hoffmann b0c3af
+  IN     UINT8         TableType,
Gerd Hoffmann b0c3af
+  IN     UINT16        FieldOffset,
Gerd Hoffmann b0c3af
+  IN     UINT8         *PatchData,
Gerd Hoffmann b0c3af
+  IN     UINT16        PatchSize
Gerd Hoffmann b0c3af
+)
Gerd Hoffmann b0c3af
+{
Gerd Hoffmann b0c3af
+  UINT8 *NewBase;
Gerd Hoffmann b0c3af
+  PATCH *Patch;
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  if (TableType >= TABLE_TYPE_LIMIT) {
Gerd Hoffmann b0c3af
+    DEBUG ((DEBUG_VERBOSE,
Gerd Hoffmann b0c3af
+      "%a: ignoring patch for unsupported table type %d\n",
Gerd Hoffmann b0c3af
+      __FUNCTION__, TableType));
Gerd Hoffmann b0c3af
+    return EFI_SUCCESS;
Gerd Hoffmann b0c3af
+  }
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  if (FieldOffset < FIELD_OFFSET_MINIMUM
Gerd Hoffmann b0c3af
+      || FieldOffset - FIELD_OFFSET_MINIMUM >= PATCH_SUBSCRIPT_LIMIT) {
Gerd Hoffmann b0c3af
+    DEBUG ((DEBUG_ERROR,
Gerd Hoffmann b0c3af
+      "%a: invalid patch for table type %d field offset %d\n",
Gerd Hoffmann b0c3af
+      __FUNCTION__, TableType, FieldOffset));
Gerd Hoffmann b0c3af
+    return EFI_INVALID_PARAMETER;
Gerd Hoffmann b0c3af
+  }
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  NewBase = AllocateCopyPool (PatchSize, PatchData);
Gerd Hoffmann b0c3af
+  if (PatchSize > 0 && NewBase == NULL) {
Gerd Hoffmann b0c3af
+    DEBUG ((DEBUG_ERROR, "%a: table type %d field offset %d: out of memory\n",
Gerd Hoffmann b0c3af
+      __FUNCTION__, TableType, FieldOffset));
Gerd Hoffmann b0c3af
+    return EFI_OUT_OF_RESOURCES;
Gerd Hoffmann b0c3af
+  }
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  Patch = &Context->Table[TableType].Patch[FieldOffset - FIELD_OFFSET_MINIMUM];
Gerd Hoffmann b0c3af
+  //
Gerd Hoffmann b0c3af
+  // replace previous patch if it exists
Gerd Hoffmann b0c3af
+  //
Gerd Hoffmann b0c3af
+  if (Patch->Base != NULL) {
Gerd Hoffmann b0c3af
+    DEBUG ((DEBUG_VERBOSE,
Gerd Hoffmann b0c3af
+      "%a: replacing prior patch for table type %d field offset %d\n",
Gerd Hoffmann b0c3af
+      __FUNCTION__, TableType, FieldOffset));
Gerd Hoffmann b0c3af
+    FreePool (Patch->Base);
Gerd Hoffmann b0c3af
+  }
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  Patch->Base = NewBase;
Gerd Hoffmann b0c3af
+  Patch->Size = PatchSize;
Gerd Hoffmann b0c3af
+  return EFI_SUCCESS;
Gerd Hoffmann b0c3af
+}
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+/**
Gerd Hoffmann b0c3af
+  Apply a saved patch to a field located in the formatted are of a not yet
Gerd Hoffmann b0c3af
+  installed SMBIOS table.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  The patch is looked up based on (Context, TableType, FieldOffset).
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  @param[in]  Context      The BUILD_CONTEXT object storing saved patches.
Gerd Hoffmann b0c3af
+  @param[in]  TableType    Selects the table type for which the patch has been
Gerd Hoffmann b0c3af
+                           saved. It is assumed that the caller has validated
Gerd Hoffmann b0c3af
+                           TableType against TABLE_TYPE_LIMIT (upper
Gerd Hoffmann b0c3af
+                           exclusive).
Gerd Hoffmann b0c3af
+  @param[in]  FieldOffset  Selects the SMBIOS field for which the patch has
Gerd Hoffmann b0c3af
+                           been saved. It is assumed that the caller has
Gerd Hoffmann b0c3af
+                           validated FieldOffset against FIELD_OFFSET_MINIMUM
Gerd Hoffmann b0c3af
+                           (lower inclusive) and 255 (upper exclusive).
Gerd Hoffmann b0c3af
+  @param[in]  FieldSize    The caller supplies the size of the field to patch
Gerd Hoffmann b0c3af
+                           in FieldSize. The patch saved for
Gerd Hoffmann b0c3af
+                           TableType:FieldOffset, if any, is only applied if
Gerd Hoffmann b0c3af
+                           its size equals FieldSize.
Gerd Hoffmann b0c3af
+  @param[out] TableBase    Base of the SMBIOS table of type TableType in which
Gerd Hoffmann b0c3af
+                           the field starting at FieldOffset needs to be
Gerd Hoffmann b0c3af
+                           patched.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  @retval EFI_NOT_FOUND          No patch found for TableType:FieldOffset in
Gerd Hoffmann b0c3af
+                                 Context. This return value is considered
Gerd Hoffmann b0c3af
+                                 informative (ie. non-fatal).
Gerd Hoffmann b0c3af
+  @retval EFI_INVALID_PARAMETER  Patch found for TableType:FieldOffset, but its
Gerd Hoffmann b0c3af
+                                 size doesn't match FieldSize. This result is
Gerd Hoffmann b0c3af
+                                 considered a fatal error of the patch origin.
Gerd Hoffmann b0c3af
+  @retval EFI_SUCCESS            The SMBIOS table at TableBase has been patched
Gerd Hoffmann b0c3af
+                                 starting at FieldOffset for a length of
Gerd Hoffmann b0c3af
+                                 FieldSize.
Gerd Hoffmann b0c3af
+**/
Gerd Hoffmann b0c3af
+EFI_STATUS
Gerd Hoffmann b0c3af
+EFIAPI
Gerd Hoffmann b0c3af
+PatchSmbiosFormatted (
Gerd Hoffmann b0c3af
+  IN  BUILD_CONTEXT *Context,
Gerd Hoffmann b0c3af
+  IN  UINT8         TableType,
Gerd Hoffmann b0c3af
+  IN  UINT16        FieldOffset,
Gerd Hoffmann b0c3af
+  IN  UINT16        FieldSize,
Gerd Hoffmann b0c3af
+  OUT UINT8         *TableBase
Gerd Hoffmann b0c3af
+  )
Gerd Hoffmann b0c3af
+{
Gerd Hoffmann b0c3af
+  PATCH *Patch;
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  ASSERT (TableType < TABLE_TYPE_LIMIT);
Gerd Hoffmann b0c3af
+  ASSERT (FieldOffset >= FIELD_OFFSET_MINIMUM);
Gerd Hoffmann b0c3af
+  ASSERT (FieldOffset - FIELD_OFFSET_MINIMUM < PATCH_SUBSCRIPT_LIMIT);
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  Patch = &Context->Table[TableType].Patch[FieldOffset - FIELD_OFFSET_MINIMUM];
Gerd Hoffmann b0c3af
+  if (Patch->Base == NULL) {
Gerd Hoffmann b0c3af
+    return EFI_NOT_FOUND;
Gerd Hoffmann b0c3af
+  }
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  if (Patch->Size != FieldSize) {
Gerd Hoffmann b0c3af
+    DEBUG ((DEBUG_ERROR, "%a: table type %d, field offset %d: "
Gerd Hoffmann b0c3af
+      "patch size %d doesn't match field size %d\n",
Gerd Hoffmann b0c3af
+      __FUNCTION__, TableType, FieldOffset, Patch->Size, FieldSize));
Gerd Hoffmann b0c3af
+    return EFI_INVALID_PARAMETER;
Gerd Hoffmann b0c3af
+  }
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  CopyMem (TableBase + FieldOffset, Patch->Base, FieldSize);
Gerd Hoffmann b0c3af
+  return EFI_SUCCESS;
Gerd Hoffmann b0c3af
+}
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+/**
Gerd Hoffmann b0c3af
+  Apply a saved patch to a text string located in the unformatted area of an
Gerd Hoffmann b0c3af
+  already installed SMBIOS table.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  The patch is looked up based on (Context, TableType, FieldOffset).
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  @param[in]  Smbios        The EFI_SMBIOS_PROTOCOL instance used previously
Gerd Hoffmann b0c3af
+                            for installing the SMBIOS table.
Gerd Hoffmann b0c3af
+  @param[in]  SmbiosHandle  The EFI_SMBIOS_HANDLE previously returned by
Gerd Hoffmann b0c3af
+                            Smbios->Add().
Gerd Hoffmann b0c3af
+  @param[in]  Context       The BUILD_CONTEXT object storing saved patches.
Gerd Hoffmann b0c3af
+  @param[in]  TableType     Selects the table type for which the patch has been
Gerd Hoffmann b0c3af
+                            saved. It is assumed that the caller has validated
Gerd Hoffmann b0c3af
+                            TableType against TABLE_TYPE_LIMIT (upper
Gerd Hoffmann b0c3af
+                            exclusive).
Gerd Hoffmann b0c3af
+  @param[in]  FieldOffset   Selects the SMBIOS field for which the patch has
Gerd Hoffmann b0c3af
+                            been saved. It is assumed that the caller has
Gerd Hoffmann b0c3af
+                            validated FieldOffset against FIELD_OFFSET_MINIMUM
Gerd Hoffmann b0c3af
+                            (lower inclusive) and 255 (upper exclusive).
Gerd Hoffmann b0c3af
+                            It is also assumed that TableBase[FieldOffset]
Gerd Hoffmann b0c3af
+                            accesses a field of type SMBIOS_TABLE_STRING, ie. a
Gerd Hoffmann b0c3af
+                            field in the formatted area that identifies an
Gerd Hoffmann b0c3af
+                            existent text string in the unformatted area. Text
Gerd Hoffmann b0c3af
+                            string identifiers are one-based.
Gerd Hoffmann b0c3af
+  @param[out] TableBase     Base of the SMBIOS table of type TableType in which
Gerd Hoffmann b0c3af
+                            the SMBIOS_TABLE_STRING field at FieldOffset
Gerd Hoffmann b0c3af
+                            identifies the existent text string to update.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  @retval EFI_NOT_FOUND          No patch found for TableType:FieldOffset in
Gerd Hoffmann b0c3af
+                                 Context. This return value is considered
Gerd Hoffmann b0c3af
+                                 informative (ie. non-fatal).
Gerd Hoffmann b0c3af
+  @retval EFI_INVALID_PARAMETER  Patch found for TableType:FieldOffset, but it
Gerd Hoffmann b0c3af
+                                 doesn't end with a NUL character. This result
Gerd Hoffmann b0c3af
+                                 is considered a fatal error of the patch
Gerd Hoffmann b0c3af
+                                 origin.
Gerd Hoffmann b0c3af
+  @retval EFI_SUCCESS            The text string identified by
Gerd Hoffmann b0c3af
+                                 TableBase[FieldOffset] has been replaced in
Gerd Hoffmann b0c3af
+                                 the installed SMBIOS table under SmbiosHandle.
Gerd Hoffmann b0c3af
+  @return                        Error codes returned by
Gerd Hoffmann b0c3af
+                                 Smbios->UpdateString(). EFI_NOT_FOUND shall
Gerd Hoffmann b0c3af
+                                 not be returned.
Gerd Hoffmann b0c3af
+**/
Gerd Hoffmann b0c3af
+EFI_STATUS
Gerd Hoffmann b0c3af
+EFIAPI
Gerd Hoffmann b0c3af
+PatchSmbiosUnformatted (
Gerd Hoffmann b0c3af
+  IN  EFI_SMBIOS_PROTOCOL *Smbios,
Gerd Hoffmann b0c3af
+  IN  EFI_SMBIOS_HANDLE   SmbiosHandle,
Gerd Hoffmann b0c3af
+  IN  BUILD_CONTEXT       *Context,
Gerd Hoffmann b0c3af
+  IN  UINT8               TableType,
Gerd Hoffmann b0c3af
+  IN  UINT16              FieldOffset,
Gerd Hoffmann b0c3af
+  IN  UINT8               *TableBase
Gerd Hoffmann b0c3af
+  )
Gerd Hoffmann b0c3af
+{
Gerd Hoffmann b0c3af
+  PATCH      *Patch;
Gerd Hoffmann b0c3af
+  UINTN      StringNumber;
Gerd Hoffmann b0c3af
+  EFI_STATUS Status;
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  ASSERT (TableType < TABLE_TYPE_LIMIT);
Gerd Hoffmann b0c3af
+  ASSERT (FieldOffset >= FIELD_OFFSET_MINIMUM);
Gerd Hoffmann b0c3af
+  ASSERT (FieldOffset - FIELD_OFFSET_MINIMUM < PATCH_SUBSCRIPT_LIMIT);
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  Patch = &Context->Table[TableType].Patch[FieldOffset - FIELD_OFFSET_MINIMUM];
Gerd Hoffmann b0c3af
+  if (Patch->Base == NULL) {
Gerd Hoffmann b0c3af
+    return EFI_NOT_FOUND;
Gerd Hoffmann b0c3af
+  }
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  if (Patch->Size == 0 || Patch->Base[Patch->Size - 1] != '\0') {
Gerd Hoffmann b0c3af
+    DEBUG ((DEBUG_ERROR, "%a: table type %d, field offset %d: "
Gerd Hoffmann b0c3af
+      "missing terminator, or trailing garbage\n",
Gerd Hoffmann b0c3af
+      __FUNCTION__, TableType, FieldOffset));
Gerd Hoffmann b0c3af
+    return EFI_INVALID_PARAMETER;
Gerd Hoffmann b0c3af
+  }
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  StringNumber = TableBase[FieldOffset];
Gerd Hoffmann b0c3af
+  ASSERT (StringNumber != 0);
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  Status = Smbios->UpdateString (Smbios, &SmbiosHandle, &StringNumber,
Gerd Hoffmann b0c3af
+                     (CHAR8 *)Patch->Base);
Gerd Hoffmann b0c3af
+  if (EFI_ERROR (Status)) {
Gerd Hoffmann b0c3af
+    ASSERT (Status != EFI_NOT_FOUND);
Gerd Hoffmann b0c3af
+    DEBUG ((DEBUG_ERROR, "%a: table type %d, field offset %d, "
Gerd Hoffmann b0c3af
+      "string number %d: Smbios->UpdateString(): %r\n", __FUNCTION__,
Gerd Hoffmann b0c3af
+      TableType, FieldOffset, TableBase[FieldOffset], Status));
Gerd Hoffmann b0c3af
+    return Status;
Gerd Hoffmann b0c3af
+  }
Gerd Hoffmann b0c3af
+  return EFI_SUCCESS;
Gerd Hoffmann b0c3af
+}
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+/**
Gerd Hoffmann b0c3af
+  Process an SMBIOS firmware configuration entry with ET_FIELD type, exported
Gerd Hoffmann b0c3af
+  by QEMU under QemuFwCfgItemX86SmbiosTables.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  Such entries describe patches to be saved with SaveSmbiosPatch().
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  @param[in,out] Context      The BUILD_CONTEXT object tracking saved patches.
Gerd Hoffmann b0c3af
+  @param[in]     Payload      Points to the buffer to parse as
Gerd Hoffmann b0c3af
+                              FW_CFG_SMBIOS_FIELD.
Gerd Hoffmann b0c3af
+  @param[in]     PayloadSize  Number of bytes in Payload.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  @retval EFI_INVALID_PARAMETER  PayloadSize is less than the size of
Gerd Hoffmann b0c3af
+                                 FW_CFG_SMBIOS_FIELD -- fields describing
Gerd Hoffmann b0c3af
+                                 the patch are incomplete.
Gerd Hoffmann b0c3af
+  @retval EFI_SUCCESS            Payload has been parsed and patch has been
Gerd Hoffmann b0c3af
+                                 saved successfully.
Gerd Hoffmann b0c3af
+  @return                        Error codes returned by SaveSmbiosPatch().
Gerd Hoffmann b0c3af
+**/
Gerd Hoffmann b0c3af
+STATIC
Gerd Hoffmann b0c3af
+EFI_STATUS
Gerd Hoffmann b0c3af
+EFIAPI
Gerd Hoffmann b0c3af
+VisitSmbiosField (
Gerd Hoffmann b0c3af
+  IN OUT BUILD_CONTEXT *Context,
Gerd Hoffmann b0c3af
+  IN     UINT8         *Payload,
Gerd Hoffmann b0c3af
+  IN     UINT16        PayloadSize
Gerd Hoffmann b0c3af
+  )
Gerd Hoffmann b0c3af
+{
Gerd Hoffmann b0c3af
+  FW_CFG_SMBIOS_FIELD *Field;
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  if (PayloadSize < (INT32) sizeof *Field) {
Gerd Hoffmann b0c3af
+    DEBUG ((DEBUG_ERROR, "%a: required minimum size %d, available %d\n",
Gerd Hoffmann b0c3af
+      __FUNCTION__, (INT32) sizeof *Field, PayloadSize));
Gerd Hoffmann b0c3af
+    return EFI_INVALID_PARAMETER;
Gerd Hoffmann b0c3af
+  }
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  Field = (FW_CFG_SMBIOS_FIELD *) Payload;
Gerd Hoffmann b0c3af
+  return SaveSmbiosPatch (Context, Field->TableType, Field->Offset,
Gerd Hoffmann b0c3af
+           Payload + sizeof *Field, (UINT16) (PayloadSize - sizeof *Field));
Gerd Hoffmann b0c3af
+}
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+/**
Gerd Hoffmann b0c3af
+  Process an SMBIOS firmware configuration entry with ET_TABLE type, exported
Gerd Hoffmann b0c3af
+  by QEMU under QemuFwCfgItemX86SmbiosTables.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  Such entries describe entire SMBIOS table instances to install verbatim. This
Gerd Hoffmann b0c3af
+  module never overrides tables installed in this manner with default tables.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  @param[in]     Smbios          The EFI_SMBIOS_PROTOCOL instance used for
Gerd Hoffmann b0c3af
+                                 installing SMBIOS tables.
Gerd Hoffmann b0c3af
+  @param[in]     ProducerHandle  Passed on to Smbios->Add(), ProducerHandle
Gerd Hoffmann b0c3af
+                                 tracks the origin of installed SMBIOS tables.
Gerd Hoffmann b0c3af
+  @param[in,out] Context         The BUILD_CONTEXT object tracking installed
Gerd Hoffmann b0c3af
+                                 tables.
Gerd Hoffmann b0c3af
+  @param[in]     Payload         Points to the buffer to install as an SMBIOS
Gerd Hoffmann b0c3af
+                                 table.
Gerd Hoffmann b0c3af
+  @param[in]     PayloadSize     Number of bytes in Payload.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  @retval EFI_INVALID_PARAMETER  The buffer at Payload, interpreted as an
Gerd Hoffmann b0c3af
+                                 SMBIOS table, failed basic sanity checks.
Gerd Hoffmann b0c3af
+  @retval EFI_SUCCESS            Payload has been installed successfully as an
Gerd Hoffmann b0c3af
+                                 SMBIOS table.
Gerd Hoffmann b0c3af
+  @return                        Error codes returned by Smbios->Add().
Gerd Hoffmann b0c3af
+**/
Gerd Hoffmann b0c3af
+STATIC
Gerd Hoffmann b0c3af
+EFI_STATUS
Gerd Hoffmann b0c3af
+EFIAPI
Gerd Hoffmann b0c3af
+VisitSmbiosTable (
Gerd Hoffmann b0c3af
+  IN     EFI_SMBIOS_PROTOCOL *Smbios,
Gerd Hoffmann b0c3af
+  IN     EFI_HANDLE          ProducerHandle,
Gerd Hoffmann b0c3af
+  IN OUT BUILD_CONTEXT       *Context,
Gerd Hoffmann b0c3af
+  IN     UINT8               *Payload,
Gerd Hoffmann b0c3af
+  IN     UINT16              PayloadSize
Gerd Hoffmann b0c3af
+  )
Gerd Hoffmann b0c3af
+{
Gerd Hoffmann b0c3af
+  SMBIOS_STRUCTURE  *SmbiosHeader;
Gerd Hoffmann b0c3af
+  UINT16            MinimumSize;
Gerd Hoffmann b0c3af
+  EFI_SMBIOS_HANDLE SmbiosHandle;
Gerd Hoffmann b0c3af
+  EFI_STATUS        Status;
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  //
Gerd Hoffmann b0c3af
+  // Basic sanity checks only in order to help debugging and to catch blatantly
Gerd Hoffmann b0c3af
+  // invalid data passed with "-smbios file=binary_file" on the QEMU command
Gerd Hoffmann b0c3af
+  // line. Beyond these we don't enforce correct, type-specific SMBIOS table
Gerd Hoffmann b0c3af
+  // formatting.
Gerd Hoffmann b0c3af
+  //
Gerd Hoffmann b0c3af
+  if (PayloadSize < (INT32) sizeof *SmbiosHeader) {
Gerd Hoffmann b0c3af
+    DEBUG ((DEBUG_ERROR, "%a: required minimum size %d, available %d\n",
Gerd Hoffmann b0c3af
+      __FUNCTION__, (INT32) sizeof *SmbiosHeader, PayloadSize));
Gerd Hoffmann b0c3af
+    return EFI_INVALID_PARAMETER;
Gerd Hoffmann b0c3af
+  }
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  SmbiosHeader = (SMBIOS_STRUCTURE *) Payload;
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  if (SmbiosHeader->Length < (INT32) sizeof *SmbiosHeader) {
Gerd Hoffmann b0c3af
+    DEBUG ((DEBUG_ERROR, "%a: required minimum size %d, stated %d\n",
Gerd Hoffmann b0c3af
+      __FUNCTION__, (INT32) sizeof *SmbiosHeader, SmbiosHeader->Length));
Gerd Hoffmann b0c3af
+    return EFI_INVALID_PARAMETER;
Gerd Hoffmann b0c3af
+  }
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  MinimumSize = (UINT16) (SmbiosHeader->Length + 2);
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  if (PayloadSize < MinimumSize) {
Gerd Hoffmann b0c3af
+    DEBUG ((DEBUG_ERROR,
Gerd Hoffmann b0c3af
+      "%a: minimum for formatted area plus terminator is %d, available %d\n",
Gerd Hoffmann b0c3af
+      __FUNCTION__, MinimumSize, PayloadSize));
Gerd Hoffmann b0c3af
+    return EFI_INVALID_PARAMETER;
Gerd Hoffmann b0c3af
+  }
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  if (Payload[PayloadSize - 2] != '\0' ||
Gerd Hoffmann b0c3af
+      Payload[PayloadSize - 1] != '\0') {
Gerd Hoffmann b0c3af
+    DEBUG ((DEBUG_ERROR, "%a: missing terminator, or trailing garbage\n",
Gerd Hoffmann b0c3af
+      __FUNCTION__));
Gerd Hoffmann b0c3af
+    return EFI_INVALID_PARAMETER;
Gerd Hoffmann b0c3af
+  }
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  //
Gerd Hoffmann b0c3af
+  // request unique handle
Gerd Hoffmann b0c3af
+  //
Gerd Hoffmann b0c3af
+  SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
Gerd Hoffmann b0c3af
+  Status = Smbios->Add (Smbios, ProducerHandle, &SmbiosHandle,
Gerd Hoffmann b0c3af
+                     (EFI_SMBIOS_TABLE_HEADER *) SmbiosHeader);
Gerd Hoffmann b0c3af
+  if (EFI_ERROR (Status)) {
Gerd Hoffmann b0c3af
+    DEBUG ((DEBUG_ERROR, "%a: Smbios->Add(): %r\n", __FUNCTION__, Status));
Gerd Hoffmann b0c3af
+    return Status;
Gerd Hoffmann b0c3af
+  }
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  //
Gerd Hoffmann b0c3af
+  // track known tables
Gerd Hoffmann b0c3af
+  //
Gerd Hoffmann b0c3af
+  if (SmbiosHeader->Type < TABLE_TYPE_LIMIT) {
Gerd Hoffmann b0c3af
+    Context->Table[SmbiosHeader->Type].Installed = TRUE;
Gerd Hoffmann b0c3af
+  }
Gerd Hoffmann b0c3af
+  return EFI_SUCCESS;
Gerd Hoffmann b0c3af
+}
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+/**
Gerd Hoffmann b0c3af
+  Traverse the SMBIOS firmware configuration blob exported by QEMU under
Gerd Hoffmann b0c3af
+  QemuFwCfgItemX86SmbiosTables, processing each entry in turn.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  Entries with ET_FIELD type are parsed as patches for the SMBIOS tables this
Gerd Hoffmann b0c3af
+  module installs as fallbacks, while entries of type ET_TABLE are parsed and
Gerd Hoffmann b0c3af
+  installed as verbatim SMBIOS tables.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  Unknown entry types are silently skipped. Any error encountered during
Gerd Hoffmann b0c3af
+  traversal (for example, a recognized but malformed entry) aborts the
Gerd Hoffmann b0c3af
+  iteration, leaving the function with a possibly incomplete set of installed
Gerd Hoffmann b0c3af
+  tables.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  @param[in]     Smbios          The EFI_SMBIOS_PROTOCOL instance used for
Gerd Hoffmann b0c3af
+                                 installing SMBIOS tables.
Gerd Hoffmann b0c3af
+  @param[in]     ProducerHandle  Passed on to Smbios->Add(), ProducerHandle
Gerd Hoffmann b0c3af
+                                 tracks the origin of installed SMBIOS tables.
Gerd Hoffmann b0c3af
+  @param[in,out] Context         The BUILD_CONTEXT object tracking installed
Gerd Hoffmann b0c3af
+                                 tables and saved patches.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  @retval EFI_SUCCESS            The firmware configuration interface is
Gerd Hoffmann b0c3af
+                                 unavailable (no patches saved, no tables
Gerd Hoffmann b0c3af
+                                 installed).
Gerd Hoffmann b0c3af
+  @retval EFI_SUCCESS            Traversal complete. Tables provided by QEMU
Gerd Hoffmann b0c3af
+                                 have been installed. Patches have been saved
Gerd Hoffmann b0c3af
+                                 for any default tables that will be necessary.
Gerd Hoffmann b0c3af
+  @retval EFI_INVALID_PARAMETER  Encountered a corrupt entry in the SMBIOS
Gerd Hoffmann b0c3af
+                                 firmware configuration blob.
Gerd Hoffmann b0c3af
+  @retval EFI_OUT_OF_RESOURCES   Memory allocation failed.
Gerd Hoffmann b0c3af
+  @return                        Error codes returned by VisitSmbiosField() and
Gerd Hoffmann b0c3af
+                                 VisitSmbiosTable().
Gerd Hoffmann b0c3af
+**/
Gerd Hoffmann b0c3af
+STATIC
Gerd Hoffmann b0c3af
+EFI_STATUS
Gerd Hoffmann b0c3af
+EFIAPI
Gerd Hoffmann b0c3af
+ScanQemuSmbios (
Gerd Hoffmann b0c3af
+  IN     EFI_SMBIOS_PROTOCOL *Smbios,
Gerd Hoffmann b0c3af
+  IN     EFI_HANDLE          ProducerHandle,
Gerd Hoffmann b0c3af
+  IN OUT BUILD_CONTEXT       *Context
Gerd Hoffmann b0c3af
+  )
Gerd Hoffmann b0c3af
+{
Gerd Hoffmann b0c3af
+  EFI_STATUS Status;
Gerd Hoffmann b0c3af
+  UINT16     NumEntries;
Gerd Hoffmann b0c3af
+  UINT16     CurEntry;
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  Status = EFI_SUCCESS;
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  if (!QemuFwCfgIsAvailable ()) {
Gerd Hoffmann b0c3af
+    return Status;
Gerd Hoffmann b0c3af
+  }
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  QemuFwCfgSelectItem (QemuFwCfgItemX86SmbiosTables);
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  NumEntries = QemuFwCfgRead16 ();
Gerd Hoffmann b0c3af
+  for (CurEntry = 0; CurEntry < NumEntries && !EFI_ERROR (Status);
Gerd Hoffmann b0c3af
+       ++CurEntry) {
Gerd Hoffmann b0c3af
+    FW_CFG_SMBIOS_ENTRY_HDR Header;
Gerd Hoffmann b0c3af
+    UINT16                  PayloadSize;
Gerd Hoffmann b0c3af
+    UINT8                   *Payload;
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+    QemuFwCfgReadBytes (sizeof Header, &Header);
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+    if (Header.Size < (INT32) sizeof Header) {
Gerd Hoffmann b0c3af
+      DEBUG ((DEBUG_ERROR, "%a: invalid header size %d in entry %d\n",
Gerd Hoffmann b0c3af
+        __FUNCTION__, Header.Size, CurEntry));
Gerd Hoffmann b0c3af
+      return EFI_INVALID_PARAMETER;
Gerd Hoffmann b0c3af
+    }
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+    PayloadSize = (UINT16) (Header.Size - sizeof Header);
Gerd Hoffmann b0c3af
+    Payload = AllocatePool (PayloadSize);
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+    if (PayloadSize > 0 && Payload == NULL) {
Gerd Hoffmann b0c3af
+      DEBUG ((DEBUG_ERROR, "%a: failed to allocate %d bytes for entry %d\n",
Gerd Hoffmann b0c3af
+        __FUNCTION__, PayloadSize, CurEntry));
Gerd Hoffmann b0c3af
+      return EFI_OUT_OF_RESOURCES;
Gerd Hoffmann b0c3af
+    }
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+    QemuFwCfgReadBytes (PayloadSize, Payload);
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+    //
Gerd Hoffmann b0c3af
+    // dump the payload
Gerd Hoffmann b0c3af
+    //
Gerd Hoffmann b0c3af
+    DEBUG_CODE (
Gerd Hoffmann b0c3af
+      UINT16 Idx;
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+      DEBUG ((DEBUG_VERBOSE,
Gerd Hoffmann b0c3af
+        "%a: entry %d, type %d, payload size %d, payload hex dump follows:",
Gerd Hoffmann b0c3af
+        __FUNCTION__, CurEntry, Header.Type, PayloadSize));
Gerd Hoffmann b0c3af
+      for (Idx = 0; Idx < PayloadSize; ++Idx) {
Gerd Hoffmann b0c3af
+        switch (Idx % 16) {
Gerd Hoffmann b0c3af
+          case 0:
Gerd Hoffmann b0c3af
+            DEBUG ((DEBUG_VERBOSE, "\n%04X:", Idx));
Gerd Hoffmann b0c3af
+            break;
Gerd Hoffmann b0c3af
+          case 8:
Gerd Hoffmann b0c3af
+            DEBUG ((DEBUG_VERBOSE, " "));
Gerd Hoffmann b0c3af
+            break;
Gerd Hoffmann b0c3af
+          default:
Gerd Hoffmann b0c3af
+            ;
Gerd Hoffmann b0c3af
+        }
Gerd Hoffmann b0c3af
+        DEBUG ((DEBUG_VERBOSE, " %02X", Payload[Idx]));
Gerd Hoffmann b0c3af
+      }
Gerd Hoffmann b0c3af
+      DEBUG ((DEBUG_VERBOSE, "\n"));
Gerd Hoffmann b0c3af
+    );
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+    switch (Header.Type) {
Gerd Hoffmann b0c3af
+    case ET_FIELD:
Gerd Hoffmann b0c3af
+      Status = VisitSmbiosField (Context, Payload, PayloadSize);
Gerd Hoffmann b0c3af
+      break;
Gerd Hoffmann b0c3af
+    case ET_TABLE:
Gerd Hoffmann b0c3af
+      Status = VisitSmbiosTable (Smbios, ProducerHandle, Context, Payload,
Gerd Hoffmann b0c3af
+                 PayloadSize);
Gerd Hoffmann b0c3af
+      break;
Gerd Hoffmann b0c3af
+    default:
Gerd Hoffmann b0c3af
+      ;
Gerd Hoffmann b0c3af
+    }
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+    FreePool (Payload);
Gerd Hoffmann b0c3af
+  }
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  return Status;
Gerd Hoffmann b0c3af
+}
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+/**
Gerd Hoffmann b0c3af
+  Install some of the default SMBIOS tables for table types that QEMU hasn't
Gerd Hoffmann b0c3af
+  provided under QemuFwCfgItemX86SmbiosTables, but are required by the
Gerd Hoffmann b0c3af
+  SMBIOS-2.7.1 specification.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  @param[in]     Smbios          The EFI_SMBIOS_PROTOCOL instance used for
Gerd Hoffmann b0c3af
+                                 installing SMBIOS tables.
Gerd Hoffmann b0c3af
+  @param[in]     ProducerHandle  Passed on to Smbios->Add(), ProducerHandle
Gerd Hoffmann b0c3af
+                                 tracks the origin of installed SMBIOS tables.
Gerd Hoffmann b0c3af
+  @param[in,out] Context         The BUILD_CONTEXT object tracking installed
Gerd Hoffmann b0c3af
+                                 tables and saved patches.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  @return  Status codes returned by the InstallSmbiosTypeXX() functions,
Gerd Hoffmann b0c3af
+           including the final EFI_SUCCESS if all such calls succeed.
Gerd Hoffmann b0c3af
+**/
Gerd Hoffmann b0c3af
+STATIC
Gerd Hoffmann b0c3af
+EFI_STATUS
Gerd Hoffmann b0c3af
+EFIAPI
Gerd Hoffmann b0c3af
+InstallDefaultTables (
Gerd Hoffmann b0c3af
+  IN     EFI_SMBIOS_PROTOCOL *Smbios,
Gerd Hoffmann b0c3af
+  IN     EFI_HANDLE          ProducerHandle,
Gerd Hoffmann b0c3af
+  IN OUT BUILD_CONTEXT       *Context
Gerd Hoffmann b0c3af
+  )
Gerd Hoffmann b0c3af
+{
Gerd Hoffmann b0c3af
+  return EFI_SUCCESS;
Gerd Hoffmann b0c3af
+}
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+/**
Gerd Hoffmann b0c3af
+  Fetch and install SMBIOS tables on the QEMU hypervisor.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  First, tables provided by QEMU in entirety are installed verbatim.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  Then the function prepares some of the remaining tables required by the
Gerd Hoffmann b0c3af
+  SMBIOS-2.7.1 specification. For each such table,
Gerd Hoffmann b0c3af
+  - if QEMU provides any fields for the table, they take effect verbatim,
Gerd Hoffmann b0c3af
+  - remaining fields are set by this function.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  @param[in] Smbios       The EFI_SMBIOS_PROTOCOL instance used for installing
Gerd Hoffmann b0c3af
+                          the SMBIOS tables.
Gerd Hoffmann b0c3af
+  @param[in] ImageHandle  The image handle of the calling module, passed as
Gerd Hoffmann b0c3af
+                          ProducerHandle to the Smbios->Add() call.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  @retval EFI_SUCCESS            All tables have been installed.
Gerd Hoffmann b0c3af
+  @retval EFI_UNSUPPORTED        The pair (Smbios->MajorVersion,
Gerd Hoffmann b0c3af
+                                 Smbios->MinorVersion) precedes (2, 3)
Gerd Hoffmann b0c3af
+                                 lexicographically.
Gerd Hoffmann b0c3af
+  @return                        Error codes returned by Smbios->Add() or
Gerd Hoffmann b0c3af
+                                 internal functions. Some tables may not have
Gerd Hoffmann b0c3af
+                                 been installed or fully patched.
Gerd Hoffmann b0c3af
+**/
Gerd Hoffmann b0c3af
+EFI_STATUS
Gerd Hoffmann b0c3af
+EFIAPI
Gerd Hoffmann b0c3af
+InstallQemuSmbiosTables (
Gerd Hoffmann b0c3af
+  IN EFI_SMBIOS_PROTOCOL *Smbios,
Gerd Hoffmann b0c3af
+  IN EFI_HANDLE          ImageHandle
Gerd Hoffmann b0c3af
+  )
Gerd Hoffmann b0c3af
+{
Gerd Hoffmann b0c3af
+  EFI_STATUS    Status;
Gerd Hoffmann b0c3af
+  BUILD_CONTEXT *Context;
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  if (Smbios->MajorVersion < 2 || Smbios->MinorVersion < 3) {
Gerd Hoffmann b0c3af
+    DEBUG ((DEBUG_ERROR, "%a: unsupported Smbios version %d.%d\n",
Gerd Hoffmann b0c3af
+      __FUNCTION__, Smbios->MajorVersion, Smbios->MinorVersion));
Gerd Hoffmann b0c3af
+    return EFI_UNSUPPORTED;
Gerd Hoffmann b0c3af
+  }
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  Status = InitSmbiosContext (&Context);
Gerd Hoffmann b0c3af
+  if (EFI_ERROR (Status)) {
Gerd Hoffmann b0c3af
+    return Status;
Gerd Hoffmann b0c3af
+  }
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  //
Gerd Hoffmann b0c3af
+  // <IndustryStandard/SmBios.h> and <Protocol/Smbios.h> must agree.
Gerd Hoffmann b0c3af
+  //
Gerd Hoffmann b0c3af
+  ASSERT (sizeof(SMBIOS_STRUCTURE) == sizeof(EFI_SMBIOS_TABLE_HEADER));
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  Status = ScanQemuSmbios (Smbios, ImageHandle, Context);
Gerd Hoffmann b0c3af
+  if (EFI_ERROR (Status)) {
Gerd Hoffmann b0c3af
+    goto Cleanup;
Gerd Hoffmann b0c3af
+  }
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  Status = InstallDefaultTables (Smbios, ImageHandle, Context);
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+Cleanup:
Gerd Hoffmann b0c3af
+  UninitSmbiosContext (Context);
Gerd Hoffmann b0c3af
+  return Status;
Gerd Hoffmann b0c3af
+}
Gerd Hoffmann b0c3af
diff --git a/OvmfPkg/SmbiosPlatformDxe/QemuLegacy.h b/OvmfPkg/SmbiosPlatformDxe/QemuLegacy.h
Gerd Hoffmann b0c3af
new file mode 100644
Gerd Hoffmann b0c3af
index 0000000..40d5ad3
Gerd Hoffmann b0c3af
--- /dev/null
Gerd Hoffmann b0c3af
+++ b/OvmfPkg/SmbiosPlatformDxe/QemuLegacy.h
Gerd Hoffmann b0c3af
@@ -0,0 +1,52 @@
Gerd Hoffmann b0c3af
+/** @file
Gerd Hoffmann b0c3af
+  This header file provides QEMU-specific public prototypes for the main driver
Gerd Hoffmann b0c3af
+  file, "SmbiosPlatformDxe.c".
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  Copyright (C) 2013, Red Hat, Inc.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  This program and the accompanying materials are licensed and made available
Gerd Hoffmann b0c3af
+  under the terms and conditions of the BSD License which accompanies this
Gerd Hoffmann b0c3af
+  distribution.  The full text of the license may be found at
Gerd Hoffmann b0c3af
+  http://opensource.org/licenses/bsd-license.php
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
Gerd Hoffmann b0c3af
+  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Gerd Hoffmann b0c3af
+**/
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+#ifndef _QEMU_LEGACY_H_
Gerd Hoffmann b0c3af
+#define _QEMU_LEGACY_H_
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+#include <Protocol/Smbios.h>
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+/**
Gerd Hoffmann b0c3af
+  Fetch and install SMBIOS tables on the QEMU hypervisor.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  First, tables provided by QEMU in entirety are installed verbatim.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  Then the function prepares some of the remaining tables required by the
Gerd Hoffmann b0c3af
+  SMBIOS-2.7.1 specification. For each such table,
Gerd Hoffmann b0c3af
+  - if QEMU provides any fields for the table, they take effect verbatim,
Gerd Hoffmann b0c3af
+  - remaining fields are set by this function.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  @param[in] Smbios       The EFI_SMBIOS_PROTOCOL instance used for installing
Gerd Hoffmann b0c3af
+                          the SMBIOS tables.
Gerd Hoffmann b0c3af
+  @param[in] ImageHandle  The image handle of the calling module, passed as
Gerd Hoffmann b0c3af
+                          ProducerHandle to the Smbios->Add() call.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  @retval EFI_SUCCESS            All tables have been installed.
Gerd Hoffmann b0c3af
+  @retval EFI_UNSUPPORTED        The pair (Smbios->MajorVersion,
Gerd Hoffmann b0c3af
+                                 Smbios->MinorVersion) precedes (2, 3)
Gerd Hoffmann b0c3af
+                                 lexicographically.
Gerd Hoffmann b0c3af
+  @return                        Error codes returned by Smbios->Add() or
Gerd Hoffmann b0c3af
+                                 internal functions. Some tables may not have
Gerd Hoffmann b0c3af
+                                 been installed or fully patched.
Gerd Hoffmann b0c3af
+**/
Gerd Hoffmann b0c3af
+EFI_STATUS
Gerd Hoffmann b0c3af
+EFIAPI
Gerd Hoffmann b0c3af
+InstallQemuSmbiosTables (
Gerd Hoffmann b0c3af
+  IN EFI_SMBIOS_PROTOCOL *Smbios,
Gerd Hoffmann b0c3af
+  IN EFI_HANDLE          ImageHandle
Gerd Hoffmann b0c3af
+  );
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+#endif
Gerd Hoffmann b0c3af
diff --git a/OvmfPkg/SmbiosPlatformDxe/QemuLegacyInternal.h b/OvmfPkg/SmbiosPlatformDxe/QemuLegacyInternal.h
Gerd Hoffmann b0c3af
new file mode 100644
Gerd Hoffmann b0c3af
index 0000000..8613407
Gerd Hoffmann b0c3af
--- /dev/null
Gerd Hoffmann b0c3af
+++ b/OvmfPkg/SmbiosPlatformDxe/QemuLegacyInternal.h
Gerd Hoffmann b0c3af
@@ -0,0 +1,221 @@
Gerd Hoffmann b0c3af
+/** @file
Gerd Hoffmann b0c3af
+  This header provides common includes, and communicates internal types,
Gerd Hoffmann b0c3af
+  function prototypes and macros between "Qemu.c" and "QemuTypeXX.c", that
Gerd Hoffmann b0c3af
+  relate to the installation and patching of SMBIOS tables on the QEMU
Gerd Hoffmann b0c3af
+  platform.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  Copyright (C) 2013, Red Hat, Inc.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  This program and the accompanying materials are licensed and made available
Gerd Hoffmann b0c3af
+  under the terms and conditions of the BSD License which accompanies this
Gerd Hoffmann b0c3af
+  distribution.  The full text of the license may be found at
Gerd Hoffmann b0c3af
+  http://opensource.org/licenses/bsd-license.php
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
Gerd Hoffmann b0c3af
+  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Gerd Hoffmann b0c3af
+**/
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+#ifndef _QEMU_LEGACY_INTERNAL_H_
Gerd Hoffmann b0c3af
+#define _QEMU_LEGACY_INTERNAL_H_
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+#include <IndustryStandard/SmBios.h>
Gerd Hoffmann b0c3af
+#include <Library/BaseLib.h>
Gerd Hoffmann b0c3af
+#include <Library/BaseMemoryLib.h>
Gerd Hoffmann b0c3af
+#include <Library/DebugLib.h>
Gerd Hoffmann b0c3af
+#include <Library/QemuFwCfgLib.h>
Gerd Hoffmann b0c3af
+#include <Protocol/Smbios.h>
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+//
Gerd Hoffmann b0c3af
+// Type identifiers of all tables mandated by the SMBIOS-2.7.1 specification
Gerd Hoffmann b0c3af
+// fall strictly under this limit.
Gerd Hoffmann b0c3af
+//
Gerd Hoffmann b0c3af
+#define TABLE_TYPE_LIMIT (EFI_SMBIOS_TYPE_SYSTEM_BOOT_INFORMATION + 1)
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+//
Gerd Hoffmann b0c3af
+// Track a patch in dynamic memory, originating from a QEMU SMBIOS firmware
Gerd Hoffmann b0c3af
+// configuration entry with ET_FIELD type.
Gerd Hoffmann b0c3af
+//
Gerd Hoffmann b0c3af
+typedef struct {
Gerd Hoffmann b0c3af
+  UINT8  *Base;
Gerd Hoffmann b0c3af
+  UINT16 Size;
Gerd Hoffmann b0c3af
+} PATCH;
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+#define FIELD_OFFSET_MINIMUM  ((INT32) sizeof(SMBIOS_STRUCTURE))
Gerd Hoffmann b0c3af
+#define PATCH_SUBSCRIPT_LIMIT (255 - FIELD_OFFSET_MINIMUM)
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+//
Gerd Hoffmann b0c3af
+// The following structure tracks the installation of each SMBIOS table with a
Gerd Hoffmann b0c3af
+// type below TABLE_TYPE_LIMIT, and captures QEMU SMBIOS firmware configuration
Gerd Hoffmann b0c3af
+// entries with ET_FIELD type that target the default table for the same type.
Gerd Hoffmann b0c3af
+//
Gerd Hoffmann b0c3af
+typedef struct {
Gerd Hoffmann b0c3af
+  BOOLEAN Installed; // at least one instance of the type has been installed
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  PATCH Patch[PATCH_SUBSCRIPT_LIMIT]; // Patches indexed by the field offset
Gerd Hoffmann b0c3af
+                                      // that they target in this specific
Gerd Hoffmann b0c3af
+                                      // table type. Patching the SMBIOS table
Gerd Hoffmann b0c3af
+                                      // header is not allowed, hence we can
Gerd Hoffmann b0c3af
+                                      // shift down field offsets. An unused
Gerd Hoffmann b0c3af
+                                      // element has zeroed-out fields.
Gerd Hoffmann b0c3af
+} TABLE_CONTEXT;
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+//
Gerd Hoffmann b0c3af
+// Track the installation of, and stored patches for, all table types below
Gerd Hoffmann b0c3af
+// TABLE_TYPE_LIMIT.
Gerd Hoffmann b0c3af
+//
Gerd Hoffmann b0c3af
+typedef struct {
Gerd Hoffmann b0c3af
+  TABLE_CONTEXT Table[TABLE_TYPE_LIMIT];
Gerd Hoffmann b0c3af
+} BUILD_CONTEXT;
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+//
Gerd Hoffmann b0c3af
+// Convenience / safety macro for defining C structure types for default SMBIOS
Gerd Hoffmann b0c3af
+// tables.
Gerd Hoffmann b0c3af
+//
Gerd Hoffmann b0c3af
+// Rules of use:
Gerd Hoffmann b0c3af
+// - Use only within #pragma pack(1).
Gerd Hoffmann b0c3af
+// - This macro depends on the macro
Gerd Hoffmann b0c3af
+//   "OVMF_TYPE ## TableType ## _STRINGS" specifying the text strings
Gerd Hoffmann b0c3af
+//   (unformatted area) for TableType. Each "QemuTypeXX.c" file needs to
Gerd Hoffmann b0c3af
+//   provide said macro before using the one below.
Gerd Hoffmann b0c3af
+//
Gerd Hoffmann b0c3af
+#define OVMF_SMBIOS(TableType)                                                \
Gerd Hoffmann b0c3af
+          typedef struct {                                                    \
Gerd Hoffmann b0c3af
+            SMBIOS_TABLE_TYPE##TableType Base;                                \
Gerd Hoffmann b0c3af
+            UINT8             Strings[sizeof OVMF_TYPE##TableType##_STRINGS]; \
Gerd Hoffmann b0c3af
+          } OVMF_TYPE##TableType
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+//
Gerd Hoffmann b0c3af
+// Convenience / safety macro for patching a field in the formatted area of
Gerd Hoffmann b0c3af
+// an SMBIOS table.
Gerd Hoffmann b0c3af
+//
Gerd Hoffmann b0c3af
+#define PATCH_FORMATTED(Context, TableType, OvmfTablePtr, FieldName)      \
Gerd Hoffmann b0c3af
+          PatchSmbiosFormatted (                                          \
Gerd Hoffmann b0c3af
+            Context,                                                      \
Gerd Hoffmann b0c3af
+            TableType,                                                    \
Gerd Hoffmann b0c3af
+            (UINT16) OFFSET_OF (SMBIOS_TABLE_TYPE##TableType, FieldName), \
Gerd Hoffmann b0c3af
+            (UINT16) sizeof (OvmfTablePtr)->Base.FieldName,               \
Gerd Hoffmann b0c3af
+            (UINT8 *) (OvmfTablePtr)                                      \
Gerd Hoffmann b0c3af
+            )
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+/**
Gerd Hoffmann b0c3af
+  Apply a saved patch to a field located in the formatted are of a not yet
Gerd Hoffmann b0c3af
+  installed SMBIOS table.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  The patch is looked up based on (Context, TableType, FieldOffset).
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  @param[in]  Context      The BUILD_CONTEXT object storing saved patches.
Gerd Hoffmann b0c3af
+  @param[in]  TableType    Selects the table type for which the patch has been
Gerd Hoffmann b0c3af
+                           saved. It is assumed that the caller has validated
Gerd Hoffmann b0c3af
+                           TableType against TABLE_TYPE_LIMIT (upper
Gerd Hoffmann b0c3af
+                           exclusive).
Gerd Hoffmann b0c3af
+  @param[in]  FieldOffset  Selects the SMBIOS field for which the patch has
Gerd Hoffmann b0c3af
+                           been saved. It is assumed that the caller has
Gerd Hoffmann b0c3af
+                           validated FieldOffset against FIELD_OFFSET_MINIMUM
Gerd Hoffmann b0c3af
+                           (lower inclusive) and 255 (upper exclusive).
Gerd Hoffmann b0c3af
+  @param[in]  FieldSize    The caller supplies the size of the field to patch
Gerd Hoffmann b0c3af
+                           in FieldSize. The patch saved for
Gerd Hoffmann b0c3af
+                           TableType:FieldOffset, if any, is only applied if
Gerd Hoffmann b0c3af
+                           its size equals FieldSize.
Gerd Hoffmann b0c3af
+  @param[out] TableBase    Base of the SMBIOS table of type TableType in which
Gerd Hoffmann b0c3af
+                           the field starting at FieldOffset needs to be
Gerd Hoffmann b0c3af
+                           patched.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  @retval EFI_NOT_FOUND          No patch found for TableType:FieldOffset in
Gerd Hoffmann b0c3af
+                                 Context. This return value is considered
Gerd Hoffmann b0c3af
+                                 informative (ie. non-fatal).
Gerd Hoffmann b0c3af
+  @retval EFI_INVALID_PARAMETER  Patch found for TableType:FieldOffset, but its
Gerd Hoffmann b0c3af
+                                 size doesn't match FieldSize. This result is
Gerd Hoffmann b0c3af
+                                 considered a fatal error of the patch origin.
Gerd Hoffmann b0c3af
+  @retval EFI_SUCCESS            The SMBIOS table at TableBase has been patched
Gerd Hoffmann b0c3af
+                                 starting at FieldOffset for a length of
Gerd Hoffmann b0c3af
+                                 FieldSize.
Gerd Hoffmann b0c3af
+**/
Gerd Hoffmann b0c3af
+EFI_STATUS
Gerd Hoffmann b0c3af
+EFIAPI
Gerd Hoffmann b0c3af
+PatchSmbiosFormatted (
Gerd Hoffmann b0c3af
+  IN  BUILD_CONTEXT *Context,
Gerd Hoffmann b0c3af
+  IN  UINT8         TableType,
Gerd Hoffmann b0c3af
+  IN  UINT16        FieldOffset,
Gerd Hoffmann b0c3af
+  IN  UINT16        FieldSize,
Gerd Hoffmann b0c3af
+  OUT UINT8         *TableBase
Gerd Hoffmann b0c3af
+  );
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+//
Gerd Hoffmann b0c3af
+// Convenience / safety macro for patching a string in the unformatted area of
Gerd Hoffmann b0c3af
+// an SMBIOS table.
Gerd Hoffmann b0c3af
+//
Gerd Hoffmann b0c3af
+#define PATCH_UNFORMATTED(Smbios, SmbiosHandle, Context, TableType,       \
Gerd Hoffmann b0c3af
+          OvmfTablePtr, FieldName)                                        \
Gerd Hoffmann b0c3af
+                                                                          \
Gerd Hoffmann b0c3af
+          PatchSmbiosUnformatted (                                        \
Gerd Hoffmann b0c3af
+            Smbios,                                                       \
Gerd Hoffmann b0c3af
+            SmbiosHandle,                                                 \
Gerd Hoffmann b0c3af
+            Context,                                                      \
Gerd Hoffmann b0c3af
+            TableType,                                                    \
Gerd Hoffmann b0c3af
+            (UINT16) OFFSET_OF (SMBIOS_TABLE_TYPE##TableType, FieldName), \
Gerd Hoffmann b0c3af
+            (UINT8 *) (OvmfTablePtr)                                      \
Gerd Hoffmann b0c3af
+            )
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+/**
Gerd Hoffmann b0c3af
+  Apply a saved patch to a text string located in the unformatted area of an
Gerd Hoffmann b0c3af
+  already installed SMBIOS table.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  The patch is looked up based on (Context, TableType, FieldOffset).
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  @param[in]  Smbios        The EFI_SMBIOS_PROTOCOL instance used previously
Gerd Hoffmann b0c3af
+                            for installing the SMBIOS table.
Gerd Hoffmann b0c3af
+  @param[in]  SmbiosHandle  The EFI_SMBIOS_HANDLE previously returned by
Gerd Hoffmann b0c3af
+                            Smbios->Add().
Gerd Hoffmann b0c3af
+  @param[in]  Context       The BUILD_CONTEXT object storing saved patches.
Gerd Hoffmann b0c3af
+  @param[in]  TableType     Selects the table type for which the patch has been
Gerd Hoffmann b0c3af
+                            saved. It is assumed that the caller has validated
Gerd Hoffmann b0c3af
+                            TableType against TABLE_TYPE_LIMIT (upper
Gerd Hoffmann b0c3af
+                            exclusive).
Gerd Hoffmann b0c3af
+  @param[in]  FieldOffset   Selects the SMBIOS field for which the patch has
Gerd Hoffmann b0c3af
+                            been saved. It is assumed that the caller has
Gerd Hoffmann b0c3af
+                            validated FieldOffset against FIELD_OFFSET_MINIMUM
Gerd Hoffmann b0c3af
+                            (lower inclusive) and 255 (upper exclusive).
Gerd Hoffmann b0c3af
+                            It is also assumed that TableBase[FieldOffset]
Gerd Hoffmann b0c3af
+                            accesses a field of type SMBIOS_TABLE_STRING, ie. a
Gerd Hoffmann b0c3af
+                            field in the formatted area that identifies an
Gerd Hoffmann b0c3af
+                            existent text string in the unformatted area. Text
Gerd Hoffmann b0c3af
+                            string identifiers are one-based.
Gerd Hoffmann b0c3af
+  @param[out] TableBase     Base of the SMBIOS table of type TableType in which
Gerd Hoffmann b0c3af
+                            the SMBIOS_TABLE_STRING field at FieldOffset
Gerd Hoffmann b0c3af
+                            identifies the existent text string to update.
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+  @retval EFI_NOT_FOUND          No patch found for TableType:FieldOffset in
Gerd Hoffmann b0c3af
+                                 Context. This return value is considered
Gerd Hoffmann b0c3af
+                                 informative (ie. non-fatal).
Gerd Hoffmann b0c3af
+  @retval EFI_INVALID_PARAMETER  Patch found for TableType:FieldOffset, but it
Gerd Hoffmann b0c3af
+                                 doesn't end with a NUL character. This result
Gerd Hoffmann b0c3af
+                                 is considered a fatal error of the patch
Gerd Hoffmann b0c3af
+                                 origin.
Gerd Hoffmann b0c3af
+  @retval EFI_SUCCESS            The text string identified by
Gerd Hoffmann b0c3af
+                                 TableBase[FieldOffset] has been replaced in
Gerd Hoffmann b0c3af
+                                 the installed SMBIOS table under SmbiosHandle.
Gerd Hoffmann b0c3af
+  @return                        Error codes returned by
Gerd Hoffmann b0c3af
+                                 Smbios->UpdateString(). EFI_NOT_FOUND shall
Gerd Hoffmann b0c3af
+                                 not be returned.
Gerd Hoffmann b0c3af
+**/
Gerd Hoffmann b0c3af
+EFI_STATUS
Gerd Hoffmann b0c3af
+EFIAPI
Gerd Hoffmann b0c3af
+PatchSmbiosUnformatted (
Gerd Hoffmann b0c3af
+  IN  EFI_SMBIOS_PROTOCOL *Smbios,
Gerd Hoffmann b0c3af
+  IN  EFI_SMBIOS_HANDLE   SmbiosHandle,
Gerd Hoffmann b0c3af
+  IN  BUILD_CONTEXT       *Context,
Gerd Hoffmann b0c3af
+  IN  UINT8               TableType,
Gerd Hoffmann b0c3af
+  IN  UINT16              FieldOffset,
Gerd Hoffmann b0c3af
+  IN  UINT8               *TableBase
Gerd Hoffmann b0c3af
+  );
Gerd Hoffmann b0c3af
+
Gerd Hoffmann b0c3af
+#endif
Gerd Hoffmann b0c3af
diff --git a/OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c b/OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c
Gerd Hoffmann b0c3af
index 29948a4..b7c1d0d 100644
Gerd Hoffmann b0c3af
--- a/OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c
Gerd Hoffmann b0c3af
+++ b/OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c
Gerd Hoffmann b0c3af
@@ -1,6 +1,7 @@
Gerd Hoffmann b0c3af
 /** @file
Gerd Hoffmann b0c3af
   This driver installs SMBIOS information for OVMF
Gerd Hoffmann b0c3af
 
Gerd Hoffmann b0c3af
+  Copyright (C) 2013, Red Hat, Inc.
Gerd Hoffmann b0c3af
   Copyright (c) 2011, Bei Guan <gbtju85@gmail.com>
Gerd Hoffmann b0c3af
   Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.
Gerd Hoffmann b0c3af
 
Gerd Hoffmann b0c3af
@@ -15,6 +16,9 @@
Gerd Hoffmann b0c3af
 **/
Gerd Hoffmann b0c3af
 
Gerd Hoffmann b0c3af
 #include "SmbiosPlatformDxe.h"
Gerd Hoffmann b0c3af
+#if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64)
Gerd Hoffmann b0c3af
+#include "QemuLegacy.h"
Gerd Hoffmann b0c3af
+#endif
Gerd Hoffmann b0c3af
 
Gerd Hoffmann b0c3af
 #define TYPE0_STRINGS \
Gerd Hoffmann b0c3af
   "EFI Development Kit II / OVMF\0"     /* Vendor */ \
Gerd Hoffmann b0c3af
@@ -27,10 +31,10 @@
Gerd Hoffmann b0c3af
 typedef struct {
Gerd Hoffmann b0c3af
   SMBIOS_TABLE_TYPE0 Base;
Gerd Hoffmann b0c3af
   UINT8              Strings[sizeof(TYPE0_STRINGS)];
Gerd Hoffmann b0c3af
-} OVMF_TYPE0;
Gerd Hoffmann b0c3af
+} OVMF_DEFAULT_TYPE0;
Gerd Hoffmann b0c3af
 #pragma pack()
Gerd Hoffmann b0c3af
 
Gerd Hoffmann b0c3af
-STATIC CONST OVMF_TYPE0 mOvmfDefaultType0 = {
Gerd Hoffmann b0c3af
+STATIC CONST OVMF_DEFAULT_TYPE0 mOvmfDefaultType0 = {
Gerd Hoffmann b0c3af
   {
Gerd Hoffmann b0c3af
     // SMBIOS_STRUCTURE Hdr
Gerd Hoffmann b0c3af
     {
Gerd Hoffmann b0c3af
@@ -202,7 +206,14 @@ SmbiosTablePublishEntry (
Gerd Hoffmann b0c3af
     SmbiosTables = GetQemuSmbiosTables ();
Gerd Hoffmann b0c3af
   }
Gerd Hoffmann b0c3af
 
Gerd Hoffmann b0c3af
-  if (SmbiosTables != NULL) {
Gerd Hoffmann b0c3af
+  if (SmbiosTables == NULL) {
Gerd Hoffmann b0c3af
+#if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64)
Gerd Hoffmann b0c3af
+    //
Gerd Hoffmann b0c3af
+    // Handle QEMU's legacy SMBIOS interface.
Gerd Hoffmann b0c3af
+    //
Gerd Hoffmann b0c3af
+    Status = InstallQemuSmbiosTables (Smbios, ImageHandle);
Gerd Hoffmann b0c3af
+#endif
Gerd Hoffmann b0c3af
+  } else {
Gerd Hoffmann b0c3af
     Status = InstallAllStructures (Smbios, SmbiosTables);
Gerd Hoffmann b0c3af
 
Gerd Hoffmann b0c3af
     //
Gerd Hoffmann b0c3af
diff --git a/OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf b/OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
Gerd Hoffmann b0c3af
index 3b90aac..8c9f43c 100644
Gerd Hoffmann b0c3af
--- a/OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
Gerd Hoffmann b0c3af
+++ b/OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
Gerd Hoffmann b0c3af
@@ -1,6 +1,7 @@
Gerd Hoffmann b0c3af
 ## @file
Gerd Hoffmann b0c3af
 #  This driver installs SMBIOS information for OVMF
Gerd Hoffmann b0c3af
 #
Gerd Hoffmann b0c3af
+#  Copyright (C) 2013, Red Hat, Inc.
Gerd Hoffmann b0c3af
 #  Copyright (c) 2011, Bei Guan <gbtju85@gmail.com>
Gerd Hoffmann b0c3af
 #  Copyright (c) 2011, Intel Corporation. All rights reserved.
Gerd Hoffmann b0c3af
 #
Gerd Hoffmann b0c3af
@@ -35,6 +36,7 @@
Gerd Hoffmann b0c3af
 
Gerd Hoffmann b0c3af
 [Sources.IA32, Sources.X64]
Gerd Hoffmann b0c3af
   X86Xen.c
Gerd Hoffmann b0c3af
+  QemuLegacy.c
Gerd Hoffmann b0c3af
 
Gerd Hoffmann b0c3af
 [Sources.ARM, Sources.AARCH64]
Gerd Hoffmann b0c3af
   ArmXen.c
Gerd Hoffmann b0c3af
-- 
Gerd Hoffmann b0c3af
1.8.3.1
Gerd Hoffmann b0c3af