1b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek/** @file
2b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek
3b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek  A hook-in library for MdeModulePkg/Universal/SmbiosDxe, in order to set
4b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek  gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosVersion (and possibly other PCDs)
5b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek  just before SmbiosDxe consumes them.
6b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek
7b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek  Copyright (C) 2013, 2015, Red Hat, Inc.
8b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek  Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
9b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek
10b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek  This program and the accompanying materials are licensed and made available
11b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek  under the terms and conditions of the BSD License which accompanies this
12b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek  distribution. The full text of the license may be found at
13b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek  http://opensource.org/licenses/bsd-license.php
14b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek
15b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
16b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek
18b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek**/
19b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek
20b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek#include <IndustryStandard/SmBios.h>
21b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek
22b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek#include <Base.h>
23b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek#include <Library/BaseMemoryLib.h>
24b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek#include <Library/DebugLib.h>
25b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek#include <Library/PcdLib.h>
26b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek#include <Library/QemuFwCfgLib.h>
27b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek
28b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersektypedef union {
29b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek  SMBIOS_TABLE_ENTRY_POINT     V2;
30c3db5a8c3d3acf4791844c10b89a60552ac3c350Laszlo Ersek  SMBIOS_TABLE_3_0_ENTRY_POINT V3;
31b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek} QEMU_SMBIOS_ANCHOR;
32b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek
33b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo ErsekRETURN_STATUS
34b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo ErsekEFIAPI
35b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo ErsekDetectSmbiosVersion (
36b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek  VOID
37b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek  )
38b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek{
39b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek  FIRMWARE_CONFIG_ITEM Anchor, Tables;
40b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek  UINTN                AnchorSize, TablesSize;
41b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek  QEMU_SMBIOS_ANCHOR   QemuAnchor;
42b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek  UINT16               SmbiosVersion;
43b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek
4492dc0bb23c4b8e847484cfded8dcc5146b5f5d3eLaszlo Ersek  if (PcdGetBool (PcdQemuSmbiosValidated)) {
4592dc0bb23c4b8e847484cfded8dcc5146b5f5d3eLaszlo Ersek    //
4692dc0bb23c4b8e847484cfded8dcc5146b5f5d3eLaszlo Ersek    // Some other module, linked against this library, has already performed
4792dc0bb23c4b8e847484cfded8dcc5146b5f5d3eLaszlo Ersek    // the task at hand. This should never happen, but it's easy to handle;
4892dc0bb23c4b8e847484cfded8dcc5146b5f5d3eLaszlo Ersek    // just exit early.
4992dc0bb23c4b8e847484cfded8dcc5146b5f5d3eLaszlo Ersek    //
5092dc0bb23c4b8e847484cfded8dcc5146b5f5d3eLaszlo Ersek    return RETURN_SUCCESS;
5192dc0bb23c4b8e847484cfded8dcc5146b5f5d3eLaszlo Ersek  }
5292dc0bb23c4b8e847484cfded8dcc5146b5f5d3eLaszlo Ersek
53b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek  if (RETURN_ERROR (QemuFwCfgFindFile (
54b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek                      "etc/smbios/smbios-anchor", &Anchor, &AnchorSize)) ||
55b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek      RETURN_ERROR (QemuFwCfgFindFile (
56b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek                      "etc/smbios/smbios-tables", &Tables, &TablesSize)) ||
57b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek      TablesSize == 0) {
58b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek    return RETURN_SUCCESS;
59b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek  }
60b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek
61b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek  QemuFwCfgSelectItem (Anchor);
62b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek
63b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek  switch (AnchorSize) {
64b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek  case sizeof QemuAnchor.V2:
65b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek    QemuFwCfgReadBytes (AnchorSize, &QemuAnchor);
66b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek
67b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek    if (QemuAnchor.V2.MajorVersion != 2 ||
68b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek        QemuAnchor.V2.TableLength != TablesSize ||
69b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek        CompareMem (QemuAnchor.V2.AnchorString, "_SM_", 4) != 0 ||
70b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek        CompareMem (QemuAnchor.V2.IntermediateAnchorString, "_DMI_", 5) != 0) {
71b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek      return RETURN_SUCCESS;
72b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek    }
73b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek    SmbiosVersion = (UINT16)(QemuAnchor.V2.MajorVersion << 8 |
74b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek                             QemuAnchor.V2.MinorVersion);
75b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek    break;
76b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek
77c3db5a8c3d3acf4791844c10b89a60552ac3c350Laszlo Ersek  case sizeof QemuAnchor.V3:
78c3db5a8c3d3acf4791844c10b89a60552ac3c350Laszlo Ersek    QemuFwCfgReadBytes (AnchorSize, &QemuAnchor);
79c3db5a8c3d3acf4791844c10b89a60552ac3c350Laszlo Ersek
80c3db5a8c3d3acf4791844c10b89a60552ac3c350Laszlo Ersek    if (QemuAnchor.V3.MajorVersion != 3 ||
81c3db5a8c3d3acf4791844c10b89a60552ac3c350Laszlo Ersek        QemuAnchor.V3.TableMaximumSize != TablesSize ||
82c3db5a8c3d3acf4791844c10b89a60552ac3c350Laszlo Ersek        CompareMem (QemuAnchor.V3.AnchorString, "_SM3_", 5) != 0) {
83c3db5a8c3d3acf4791844c10b89a60552ac3c350Laszlo Ersek      return RETURN_SUCCESS;
84c3db5a8c3d3acf4791844c10b89a60552ac3c350Laszlo Ersek    }
85c3db5a8c3d3acf4791844c10b89a60552ac3c350Laszlo Ersek    SmbiosVersion = (UINT16)(QemuAnchor.V3.MajorVersion << 8 |
86c3db5a8c3d3acf4791844c10b89a60552ac3c350Laszlo Ersek                             QemuAnchor.V3.MinorVersion);
87c3db5a8c3d3acf4791844c10b89a60552ac3c350Laszlo Ersek
88c3db5a8c3d3acf4791844c10b89a60552ac3c350Laszlo Ersek    DEBUG ((EFI_D_INFO, "%a: SMBIOS 3.x DocRev from QEMU: 0x%02x\n",
89c3db5a8c3d3acf4791844c10b89a60552ac3c350Laszlo Ersek      __FUNCTION__, QemuAnchor.V3.DocRev));
90c3db5a8c3d3acf4791844c10b89a60552ac3c350Laszlo Ersek    PcdSet8 (PcdSmbiosDocRev, QemuAnchor.V3.DocRev);
91c3db5a8c3d3acf4791844c10b89a60552ac3c350Laszlo Ersek    break;
92c3db5a8c3d3acf4791844c10b89a60552ac3c350Laszlo Ersek
93b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek  default:
94b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek    return RETURN_SUCCESS;
95b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek  }
96b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek
97b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek  DEBUG ((EFI_D_INFO, "%a: SMBIOS version from QEMU: 0x%04x\n", __FUNCTION__,
98b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek    SmbiosVersion));
99b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek  PcdSet16 (PcdSmbiosVersion, SmbiosVersion);
100b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek
10192dc0bb23c4b8e847484cfded8dcc5146b5f5d3eLaszlo Ersek  //
10292dc0bb23c4b8e847484cfded8dcc5146b5f5d3eLaszlo Ersek  // SMBIOS platform drivers can now fetch and install
10392dc0bb23c4b8e847484cfded8dcc5146b5f5d3eLaszlo Ersek  // "etc/smbios/smbios-tables" from QEMU.
10492dc0bb23c4b8e847484cfded8dcc5146b5f5d3eLaszlo Ersek  //
10592dc0bb23c4b8e847484cfded8dcc5146b5f5d3eLaszlo Ersek  PcdSetBool (PcdQemuSmbiosValidated, TRUE);
106b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek  return RETURN_SUCCESS;
107b265ed9284ffbd83e38599a6168e57113fd85b98Laszlo Ersek}
108