/** @file
A hook-in library for MdeModulePkg/Universal/SmbiosDxe, in order to set
gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosVersion (and possibly other PCDs)
just before SmbiosDxe consumes them.
Copyright (C) 2013, 2015, Red Hat, Inc.
Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include
#include
#include
#include
#include
#include
typedef union {
SMBIOS_TABLE_ENTRY_POINT V2;
SMBIOS_TABLE_3_0_ENTRY_POINT V3;
} QEMU_SMBIOS_ANCHOR;
RETURN_STATUS
EFIAPI
DetectSmbiosVersion (
VOID
)
{
FIRMWARE_CONFIG_ITEM Anchor, Tables;
UINTN AnchorSize, TablesSize;
QEMU_SMBIOS_ANCHOR QemuAnchor;
UINT16 SmbiosVersion;
RETURN_STATUS PcdStatus;
if (PcdGetBool (PcdQemuSmbiosValidated)) {
//
// Some other module, linked against this library, has already performed
// the task at hand. This should never happen, but it's easy to handle;
// just exit early.
//
return RETURN_SUCCESS;
}
if (RETURN_ERROR (
QemuFwCfgFindFile (
"etc/smbios/smbios-anchor",
&Anchor,
&AnchorSize
)
) ||
RETURN_ERROR (
QemuFwCfgFindFile (
"etc/smbios/smbios-tables",
&Tables,
&TablesSize
)
) ||
(TablesSize == 0))
{
return RETURN_SUCCESS;
}
QemuFwCfgSelectItem (Anchor);
switch (AnchorSize) {
case sizeof QemuAnchor.V2:
QemuFwCfgReadBytes (AnchorSize, &QemuAnchor);
if ((QemuAnchor.V2.MajorVersion != 2) ||
(QemuAnchor.V2.TableLength != TablesSize) ||
(CompareMem (QemuAnchor.V2.AnchorString, "_SM_", 4) != 0) ||
(CompareMem (QemuAnchor.V2.IntermediateAnchorString, "_DMI_", 5) != 0))
{
return RETURN_SUCCESS;
}
SmbiosVersion = (UINT16)(QemuAnchor.V2.MajorVersion << 8 |
QemuAnchor.V2.MinorVersion);
break;
case sizeof QemuAnchor.V3:
QemuFwCfgReadBytes (AnchorSize, &QemuAnchor);
if ((QemuAnchor.V3.MajorVersion != 3) ||
(QemuAnchor.V3.TableMaximumSize != TablesSize) ||
(CompareMem (QemuAnchor.V3.AnchorString, "_SM3_", 5) != 0))
{
return RETURN_SUCCESS;
}
SmbiosVersion = (UINT16)(QemuAnchor.V3.MajorVersion << 8 |
QemuAnchor.V3.MinorVersion);
DEBUG ((
DEBUG_INFO,
"%a: SMBIOS 3.x DocRev from QEMU: 0x%02x\n",
__func__,
QemuAnchor.V3.DocRev
));
PcdStatus = PcdSet8S (PcdSmbiosDocRev, QemuAnchor.V3.DocRev);
ASSERT_RETURN_ERROR (PcdStatus);
break;
default:
return RETURN_SUCCESS;
}
DEBUG ((
DEBUG_INFO,
"%a: SMBIOS version from QEMU: 0x%04x\n",
__func__,
SmbiosVersion
));
PcdStatus = PcdSet16S (PcdSmbiosVersion, SmbiosVersion);
ASSERT_RETURN_ERROR (PcdStatus);
//
// SMBIOS platform drivers can now fetch and install
// "etc/smbios/smbios-tables" from QEMU.
//
PcdStatus = PcdSetBoolS (PcdQemuSmbiosValidated, TRUE);
ASSERT_RETURN_ERROR (PcdStatus);
return RETURN_SUCCESS;
}