<div dir="ltr"><div dir="ltr"><br></div><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, May 24, 2021 at 9:13 AM Zhiguang Liu <<a href="mailto:zhiguang.liu@intel.com">zhiguang.liu@intel.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">V1:<br>
The default EfiSmbiosProtocol operates on an empty SMBIOS table.<br>
The SMBIOS tables are provided by the bootloader on UefiPayloadPkg.<br>
Scan for existing tables in SmbiosDxe and load them if they seem valid.<br>
<br>
This fixes the settings menu not showing any hardware information, instead<br>
only "0 MB RAM" was displayed.<br>
<br>
Tests showed that the OS can still see the SMBIOS tables.<br>
<br>
V2:<br>
SmbiosDxe will get the SMBIOS from a guid Hob.<br>
Aslo will keep the SmbiosHandle if it is available.<br>
<br>
Cc: Jian J Wang <<a href="mailto:jian.j.wang@intel.com" target="_blank">jian.j.wang@intel.com</a>><br>
Cc: Hao A Wu <<a href="mailto:hao.a.wu@intel.com" target="_blank">hao.a.wu@intel.com</a>><br>
Cc: Dandan Bi <<a href="mailto:dandan.bi@intel.com" target="_blank">dandan.bi@intel.com</a>><br>
Cc: Star Zeng <<a href="mailto:star.zeng@intel.com" target="_blank">star.zeng@intel.com</a>><br>
Cc: Zhichao Gao <<a href="mailto:zhichao.gao@intel.com" target="_blank">zhichao.gao@intel.com</a>><br>
Signed-off-by: Patrick Rudolph <<a href="mailto:patrick.rudolph@9elements.com" target="_blank">patrick.rudolph@9elements.com</a>><br>
Signed-off-by: Zhiguang Liu <<a href="mailto:zhiguang.liu@intel.com" target="_blank">zhiguang.liu@intel.com</a>><br>
---<br>
 MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c   | 299 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--<br>
 MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.h   |   4 +++-<br>
 MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf |   5 ++++-<br>
 3 files changed, 304 insertions(+), 4 deletions(-)<br>
<br>
diff --git a/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c b/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c<br>
index 3cdb0b1ed7..d2aa15d43f 100644<br>
--- a/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c<br>
+++ b/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c<br>
@@ -2,7 +2,7 @@<br>
   This code produces the Smbios protocol. It also responsible for constructing<br>
   SMBIOS table into system table.<br>
<br>
-Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR><br>
+Copyright (c) 2009 - 2021, Intel Corporation. All rights reserved.<BR><br>
 SPDX-License-Identifier: BSD-2-Clause-Patent<br>
<br>
 **/<br>
@@ -1408,6 +1408,300 @@ SmbiosTableConstruction (<br>
   }<br>
 }<br>
<br>
+/**<br>
+  Validates a SMBIOS 2.0 table entry point.<br>
+<br>
+  @param  SmbiosTable   The SMBIOS_TABLE_ENTRY_POINT to validate.<br>
+<br>
+  @retval TRUE           SMBIOS table entry point is valid.<br>
+  @retval FALSE          SMBIOS table entry point is malformed.<br>
+<br>
+**/<br>
+STATIC<br>
+BOOLEAN<br>
+IsValidSmbios20Table (<br>
+  IN SMBIOS_TABLE_ENTRY_POINT      *SmbiosTable<br>
+  )<br>
+{<br>
+  UINT8 Checksum;<br>
+<br>
+  if (CompareMem (SmbiosTable->AnchorString, "_SM_", 4) != 0) {<br>
+    return FALSE;<br>
+  }<br>
+<br>
+  //<br>
+  // The actual value of the EntryPointLength should be 1Fh.<br>
+  // However, it was incorrectly stated in version 2.1 of smbios specification.<br>
+  // Therefore, 0x1F and 0x1E are both accepted.<br>
+  //<br>
+  if (SmbiosTable->EntryPointLength != 0x1E || SmbiosTable->EntryPointLength != sizeof (SMBIOS_TABLE_ENTRY_POINT)) {<br>
+    return FALSE;<br>
+  }<br>
+<br></blockquote><div><br></div><div>This is not correct, it should be <br></div><div><br></div><div> if (SmbiosTable->EntryPointLength != 0x1E && SmbiosTable->EntryPointLength != sizeof (SMBIOS_TABLE_ENTRY_POINT)) {</div><div><br></div><div>otherwise the table wouldn't be recognized as valid.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+  //<br>
+  // MajorVersion should be 2.<br>
+  //<br>
+  if (SmbiosTable->MajorVersion != 2) {<br>
+    return FALSE;<br>
+  }<br>
+<br>
+  //<br>
+  // The whole struct check sum should be zero<br>
+  //<br>
+  Checksum = CalculateSum8 (<br>
+               (UINT8 *) SmbiosTable,<br>
+               SmbiosTable->EntryPointLength<br>
+               );<br>
+  if (Checksum != 0) {<br>
+    return FALSE;<br>
+  }<br>
+<br>
+  //<br>
+  // The Intermediate Entry Point Structure check sum should be zero.<br>
+  //<br>
+  Checksum = CalculateSum8 (<br>
+               (UINT8 *) SmbiosTable + OFFSET_OF (SMBIOS_TABLE_ENTRY_POINT, IntermediateAnchorString),<br>
+               SmbiosTable->EntryPointLength - OFFSET_OF (SMBIOS_TABLE_ENTRY_POINT, IntermediateAnchorString)<br>
+               );<br>
+  return (BOOLEAN) (Checksum == 0);<br>
+}<br>
+<br>
+/**<br>
+  Validates a SMBIOS 3.0 table entry point.<br>
+<br>
+  @param  SmbiosTable   The SMBIOS_TABLE_3_0_ENTRY_POINT to validate.<br>
+<br>
+  @retval TRUE           SMBIOS table entry point is valid.<br>
+  @retval FALSE          SMBIOS table entry point is malformed.<br>
+<br>
+**/<br>
+STATIC<br>
+BOOLEAN<br>
+IsValidSmbios30Table (<br>
+  IN SMBIOS_TABLE_3_0_ENTRY_POINT  *SmbiosTable<br>
+  )<br>
+{<br>
+  UINT8 Checksum;<br>
+<br>
+  if (CompareMem (SmbiosTable->AnchorString, "_SM3_", 5) != 0) {<br>
+    return FALSE;<br>
+  }<br>
+  if (SmbiosTable->EntryPointLength < sizeof (SMBIOS_TABLE_3_0_ENTRY_POINT)) {<br>
+    return FALSE;<br>
+  }<br>
+  if (SmbiosTable->MajorVersion < 3) {<br>
+    return FALSE;<br>
+  }<br>
+<br>
+  //<br>
+  // The whole struct check sum should be zero<br>
+  //<br>
+  Checksum = CalculateSum8 (<br>
+               (UINT8 *) SmbiosTable,<br>
+               SmbiosTable->EntryPointLength<br>
+               );<br>
+  if (Checksum != 0) {<br>
+    return FALSE;<br>
+  }<br>
+  return TRUE;<br>
+}<br>
+<br>
+/**<br>
+  Parse an existing SMBIOS table and insert it using SmbiosAdd.<br>
+<br>
+  @param  ImageHandle           The EFI_HANDLE to this driver.<br>
+  @param  Smbios                The SMBIOS table to parse.<br>
+  @param  Length                The length of the SMBIOS table.<br>
+<br>
+  @retval EFI_SUCCESS           SMBIOS table was parsed and installed.<br>
+  @retval EFI_OUT_OF_RESOURCES  Record was not added due to lack of system resources.<br>
+  @retval EFI_INVALID_PARAMETER Smbios is not a correct smbios table<br>
+<br>
+**/<br>
+STATIC<br>
+EFI_STATUS<br>
+ParseAndAddExistingSmbiosTable (<br>
+  IN EFI_HANDLE                    ImageHandle,<br>
+  IN SMBIOS_STRUCTURE_POINTER      Smbios,<br>
+  IN UINTN                         Length<br>
+  )<br>
+{<br>
+  EFI_STATUS                    Status;<br>
+  CHAR8                         *String;<br>
+  EFI_SMBIOS_HANDLE             SmbiosHandle;<br>
+  SMBIOS_STRUCTURE_POINTER      SmbiosEnd;<br>
+<br>
+  SmbiosEnd.Raw = Smbios.Raw + Length;<br>
+<br>
+  if (Smbios.Raw >= SmbiosEnd.Raw || Smbios.Raw == NULL) {<br>
+    return EFI_INVALID_PARAMETER;<br>
+  }<br>
+<br>
+  do {<br>
+    //<br>
+    // Make sure not to access memory beyond SmbiosEnd<br>
+    //<br>
+    if (Smbios.Raw + sizeof (SMBIOS_STRUCTURE) > SmbiosEnd.Raw ||<br>
+      Smbios.Raw + sizeof (SMBIOS_STRUCTURE) < Smbios.Raw) {<br>
+      return EFI_INVALID_PARAMETER;<br>
+    }<br>
+    //<br>
+    // Check for end marker<br>
+    //<br>
+    if (Smbios.Hdr->Type == SMBIOS_TYPE_END_OF_TABLE) {<br>
+      break;<br>
+    }<br>
+    //<br>
+    // Make sure not to access memory beyond SmbiosEnd<br>
+    // Each structure shall be terminated by a double-null (0000h).<br>
+    //<br>
+    if (Smbios.Raw + Smbios.Hdr->Length + 2 * sizeof (UINT8) > SmbiosEnd.Raw ||<br>
+      Smbios.Raw + Smbios.Hdr->Length + 2 * sizeof (UINT8) < Smbios.Raw) {<br>
+      return EFI_INVALID_PARAMETER;<br>
+    }<br>
+    //<br>
+    // Install the table<br>
+    //<br>
+    SmbiosHandle = Smbios.Hdr->Handle;<br>
+    Status = SmbiosAdd (<br>
+               &mPrivateData.Smbios,<br>
+               ImageHandle,<br>
+               &SmbiosHandle,<br>
+               Smbios.Hdr<br>
+               );<br>
+<br>
+    ASSERT_EFI_ERROR (Status);<br>
+    if (EFI_ERROR (Status)) {<br>
+      return Status;<br>
+    }<br>
+    //<br>
+    // Go to the next SMBIOS structure. Each SMBIOS structure may include 2 parts:<br>
+    // 1. Formatted section; 2. Unformatted string section. So, 2 steps are needed<br>
+    // to skip one SMBIOS structure.<br>
+    //<br>
+<br>
+    //<br>
+    // Step 1: Skip over formatted section.<br>
+    //<br>
+    String = (CHAR8 *) (Smbios.Raw + Smbios.Hdr->Length);<br>
+<br>
+    //<br>
+    // Step 2: Skip over unformatted string section.<br>
+    //<br>
+    do {<br>
+      //<br>
+      // Each string is terminated with a NULL(00h) BYTE and the sets of strings<br>
+      // is terminated with an additional NULL(00h) BYTE.<br>
+      //<br>
+      for ( ; *String != 0; String++) {<br>
+        if ((UINTN) String >= (UINTN) SmbiosEnd.Raw - sizeof (UINT8)) {<br>
+          return EFI_INVALID_PARAMETER;<br>
+        }<br>
+      }<br>
+<br>
+      if (*(UINT8 *) ++String == 0) {<br>
+        //<br>
+        // Pointer to the next SMBIOS structure.<br>
+        //<br>
+        Smbios.Raw = (UINT8 *) ++String;<br>
+        break;<br>
+      }<br>
+    } while (TRUE);<br>
+  } while (Smbios.Raw < SmbiosEnd.Raw);<br>
+<br>
+  return EFI_SUCCESS;<br>
+}<br>
+<br>
+<br>
+/**<br>
+  Retrieve SMBIOS from Hob.<br>
+  @param ImageHandle     Module's image handle<br>
+<br>
+  @retval EFI_SUCCESS    Smbios from Hob is installed.<br>
+  @return EFI_NOT_FOUND  Not found Smbios from Hob.<br>
+  @retval Other          No Smbios from Hob is installed.<br>
+<br>
+**/<br>
+EFI_STATUS<br>
+EFIAPI<br>
+RetrieveSmbiosFromHob (<br>
+  IN EFI_HANDLE           ImageHandle<br>
+  )<br>
+{<br>
+  EFI_STATUS                    Status;<br>
+  SMBIOS_TABLE_ENTRY_POINT      *SmbiosTable;<br>
+  SMBIOS_TABLE_3_0_ENTRY_POINT  *Smbios30Table;<br>
+  SMBIOS_STRUCTURE_POINTER      Smbios;<br>
+  EFI_HOB_GUID_TYPE             *GuidHob;<br>
+  PLD_SMBIOS_TABLE              *SmBiosTableAdress;<br>
+  PLD_GENERIC_HEADER            *GenericHeader;<br>
+<br>
+  Status = EFI_NOT_FOUND;<br>
+  //<br>
+  // Scan for existing SMBIOS tables from gPldSmbios3TableGuid Guid Hob<br>
+  //<br>
+  GuidHob = GetFirstGuidHob (&gPldSmbios3TableGuid);<br>
+  if (GuidHob != NULL) {<br>
+    GenericHeader = (PLD_GENERIC_HEADER *) GET_GUID_HOB_DATA (GuidHob);<br>
+    if ((sizeof (PLD_GENERIC_HEADER) <= GET_GUID_HOB_DATA_SIZE (GuidHob)) && (GenericHeader->Length <= GET_GUID_HOB_DATA_SIZE (GuidHob))) {<br>
+      if (GenericHeader->Revision == PLD_SMBIOS_TABLE_REVISION) {<br>
+        //<br>
+        // PLD_SMBIOS_TABLE structure is used when Revision equals to PLD_SMBIOS_TABLE_REVISION<br>
+        //<br>
+        SmBiosTableAdress = (PLD_SMBIOS_TABLE *) GET_GUID_HOB_DATA (GuidHob);<br>
+        if (GenericHeader->Length >= PLD_SIZEOF_THROUGH_FIELD (PLD_SMBIOS_TABLE, SmBiosEntryPoint)) {<br>
+          Smbios30Table = (SMBIOS_TABLE_3_0_ENTRY_POINT *) (UINTN) SmBiosTableAdress->SmBiosEntryPoint;<br>
+          if (IsValidSmbios30Table (Smbios30Table)) {<br>
+            Smbios.Raw = (UINT8 *) (UINTN) Smbios30Table->TableAddress;<br>
+            Status = ParseAndAddExistingSmbiosTable (ImageHandle, Smbios, Smbios30Table->TableMaximumSize);<br>
+            if (EFI_ERROR (Status)) {<br>
+              DEBUG ((DEBUG_ERROR, "RetrieveSmbiosFromHob: Failed to parse preinstalled tables from gPldSmbios3TableGuid Guid Hob\n"));<br>
+              Status = EFI_UNSUPPORTED;<br>
+            } else {<br>
+              return EFI_SUCCESS;<br>
+            }<br>
+          }<br>
+        }<br>
+      } else {<br>
+        Status = EFI_UNSUPPORTED;<br>
+      }<br>
+    }<br>
+  }<br>
+<br>
+  //<br>
+  // Scan for existing SMBIOS tables from gPldSmbiosTableGuid Guid Hob,<br>
+  // if gPldSmbios3TableGuid Hob doesn't exist or parsing gPldSmbios3TableGuid failed<br>
+  //<br>
+  GuidHob = GetFirstGuidHob (&gPldSmbiosTableGuid);<br>
+  <br>
+  if (GuidHob != NULL) {<br>
+    GenericHeader = (PLD_GENERIC_HEADER *) GET_GUID_HOB_DATA (GuidHob);<br>
+    if ((sizeof (PLD_GENERIC_HEADER) <= GET_GUID_HOB_DATA_SIZE (GuidHob)) && (GenericHeader->Length <= GET_GUID_HOB_DATA_SIZE (GuidHob))) {<br>
+      if (GenericHeader->Revision == PLD_SMBIOS_TABLE_REVISION) {<br>
+        //<br>
+        // PLD_SMBIOS_TABLE structure is used when Revision equals to PLD_SMBIOS_TABLE_REVISION<br>
+        //<br>
+        SmBiosTableAdress = (PLD_SMBIOS_TABLE *) GET_GUID_HOB_DATA (GuidHob);<br>
+        if (GenericHeader->Length >= PLD_SIZEOF_THROUGH_FIELD (PLD_SMBIOS_TABLE, SmBiosEntryPoint)) {<br>
+          SmbiosTable = (SMBIOS_TABLE_ENTRY_POINT *) (UINTN) SmBiosTableAdress->SmBiosEntryPoint;<br>
+          if (IsValidSmbios20Table (SmbiosTable)) {<br>
+            Smbios.Raw = (UINT8 *) (UINTN) SmbiosTable->TableAddress;<br>
+            Status = ParseAndAddExistingSmbiosTable (ImageHandle, Smbios, SmbiosTable->TableLength);<br>
+            if (EFI_ERROR (Status)) {<br>
+              DEBUG ((DEBUG_ERROR, "RetrieveSmbiosFromHob: Failed to parse preinstalled tables from gPldSmbiosTableGuid Guid Hob\n"));<br>
+              Status = EFI_UNSUPPORTED;<br>
+            }<br>
+            return EFI_SUCCESS;<br>
+          }<br>
+        }<br>
+      } else {<br>
+        Status = EFI_UNSUPPORTED;<br>
+      }<br>
+    }<br>
+  }<br>
+  return Status;<br>
+}<br>
+<br>
 /**<br>
<br>
   Driver to produce Smbios protocol and pre-allocate 1 page for the final SMBIOS table.<br>
@@ -1451,5 +1745,6 @@ SmbiosDriverEntryPoint (<br>
                   &mPrivateData.Smbios<br>
                   );<br>
<br>
-  return Status;<br>
+  RetrieveSmbiosFromHob (ImageHandle);<br>
+  return EFI_SUCCESS;<br>
 }<br>
diff --git a/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.h b/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.h<br>
index f97c85ae40..a260cf695e 100644<br>
--- a/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.h<br>
+++ b/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.h<br>
@@ -1,7 +1,7 @@<br>
 /** @file<br>
   This code supports the implementation of the Smbios protocol<br>
<br>
-Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR><br>
+Copyright (c) 2009 - 2021, Intel Corporation. All rights reserved.<BR><br>
 SPDX-License-Identifier: BSD-2-Clause-Patent<br>
<br>
 **/<br>
@@ -24,6 +24,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent<br>
 #include <Library/MemoryAllocationLib.h><br>
 #include <Library/UefiBootServicesTableLib.h><br>
 #include <Library/PcdLib.h><br>
+#include <Library/HobLib.h><br>
+#include <UniversalPayload/SmbiosTable.h><br>
<br>
 #define SMBIOS_INSTANCE_SIGNATURE SIGNATURE_32 ('S', 'B', 'i', 's')<br>
 typedef struct {<br>
diff --git a/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf b/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf<br>
index f6c036e1dc..3286575098 100644<br>
--- a/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf<br>
+++ b/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf<br>
@@ -1,7 +1,7 @@<br>
 ## @file<br>
 # This driver initializes and installs the SMBIOS protocol, constructs SMBIOS table into system configuration table.<br>
 #<br>
-# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR><br>
+# Copyright (c) 2009 - 2021, Intel Corporation. All rights reserved.<BR><br>
 #<br>
 #  SPDX-License-Identifier: BSD-2-Clause-Patent<br>
 #<br>
@@ -41,6 +41,7 @@<br>
   UefiDriverEntryPoint<br>
   DebugLib<br>
   PcdLib<br>
+  HobLib<br>
<br>
 [Protocols]<br>
   gEfiSmbiosProtocolGuid                            ## PRODUCES<br>
@@ -48,6 +49,8 @@<br>
 [Guids]<br>
   gEfiSmbiosTableGuid                               ## SOMETIMES_PRODUCES ## SystemTable<br>
   gEfiSmbios3TableGuid                              ## SOMETIMES_PRODUCES ## SystemTable<br>
+  gPldSmbios3TableGuid<br>
+  gPldSmbiosTableGuid<br>
<br>
 [Pcd]<br>
   gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosVersion   ## CONSUMES<br>
-- <br>
2.30.0.windows.2<br>
<br>
<br>
<br>
------------<br>
Groups.io Links: You receive all messages sent to this group.<br>
View/Reply Online (#75489): <a href="https://edk2.groups.io/g/devel/message/75489" rel="noreferrer" target="_blank">https://edk2.groups.io/g/devel/message/75489</a><br>
Mute This Topic: <a href="https://groups.io/mt/83045509/2917327" rel="noreferrer" target="_blank">https://groups.io/mt/83045509/2917327</a><br>
Group Owner: <a href="mailto:devel%2Bowner@edk2.groups.io" target="_blank">devel+owner@edk2.groups.io</a><br>
Unsubscribe: <a href="https://edk2.groups.io/g/devel/unsub" rel="noreferrer" target="_blank">https://edk2.groups.io/g/devel/unsub</a> [<a href="mailto:patrick.rudolph@9elements.com" target="_blank">patrick.rudolph@9elements.com</a>]<br>
------------<br>
<br>
<br>
</blockquote></div></div>


 <div width="1" style="color:white;clear:both">_._,_._,_</div> <hr>   Groups.io Links:<p>   You receive all messages sent to this group.    <p> <a target="_blank" href="https://edk2.groups.io/g/devel/message/75661">View/Reply Online (#75661)</a> |    |  <a target="_blank" href="https://groups.io/mt/83045509/1813853">Mute This Topic</a>  | <a href="https://edk2.groups.io/g/devel/post">New Topic</a><br>    <a href="https://edk2.groups.io/g/devel/editsub/1813853">Your Subscription</a> | <a href="mailto:devel+owner@edk2.groups.io">Contact Group Owner</a> |  <a href="https://edk2.groups.io/g/devel/unsub">Unsubscribe</a>  [edk2-devel-archive@redhat.com]<br> <div width="1" style="color:white;clear:both">_._,_._,_</div>