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