This code produces the Smbios protocol. It also responsible for constructing\r
SMBIOS table into system table.\r
\r
-Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2009 - 2021, Intel Corporation. All rights reserved.<BR>\r
SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
//\r
0\r
};\r
+\r
+IS_SMBIOS_TABLE_VALID_ENTRY mIsSmbiosTableValid[] = {\r
+ {&gUniversalPayloadSmbios3TableGuid, IsValidSmbios30Table },\r
+ {&gUniversalPayloadSmbiosTableGuid, IsValidSmbios20Table }\r
+};\r
+\r
/**\r
\r
Get the full size of SMBIOS structure including optional strings that follow the formatted structure.\r
}\r
}\r
\r
+/**\r
+ Validates a SMBIOS 2.0 table entry point.\r
+\r
+ @param TableEntry The SmBios table entry to validate.\r
+ @param TableAddress On exit, point to the smbios table addres.\r
+ @param TableMaximumSize On exit, point to the maximum size of the table.\r
+\r
+ @retval TRUE SMBIOS table entry point is valid.\r
+ @retval FALSE SMBIOS table entry point is malformed.\r
+\r
+**/\r
+STATIC\r
+BOOLEAN\r
+IsValidSmbios20Table (\r
+ IN VOID *TableEntry,\r
+ OUT VOID **TableAddress,\r
+ OUT UINTN *TableMaximumSize\r
+ )\r
+{\r
+ UINT8 Checksum;\r
+ SMBIOS_TABLE_ENTRY_POINT *SmbiosTable;\r
+ SmbiosTable = (SMBIOS_TABLE_ENTRY_POINT *) TableEntry;\r
+\r
+ if (CompareMem (SmbiosTable->AnchorString, "_SM_", 4) != 0) {\r
+ return FALSE;\r
+ }\r
+\r
+ if (CompareMem (SmbiosTable->IntermediateAnchorString, "_DMI_", 5) != 0) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // The actual value of the EntryPointLength should be 1Fh.\r
+ // However, it was incorrectly stated in version 2.1 of smbios specification.\r
+ // Therefore, 0x1F and 0x1E are both accepted.\r
+ //\r
+ if (SmbiosTable->EntryPointLength != 0x1E && SmbiosTable->EntryPointLength != sizeof (SMBIOS_TABLE_ENTRY_POINT)) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // MajorVersion should not be less than 2.\r
+ //\r
+ if (SmbiosTable->MajorVersion < 2) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // The whole struct check sum should be zero\r
+ //\r
+ Checksum = CalculateSum8 (\r
+ (UINT8 *) SmbiosTable,\r
+ SmbiosTable->EntryPointLength\r
+ );\r
+ if (Checksum != 0) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // The Intermediate Entry Point Structure check sum should be zero.\r
+ //\r
+ Checksum = CalculateSum8 (\r
+ (UINT8 *) SmbiosTable + OFFSET_OF (SMBIOS_TABLE_ENTRY_POINT, IntermediateAnchorString),\r
+ SmbiosTable->EntryPointLength - OFFSET_OF (SMBIOS_TABLE_ENTRY_POINT, IntermediateAnchorString)\r
+ );\r
+ if (Checksum != 0) {\r
+ return FALSE;\r
+ }\r
+\r
+ *TableAddress = (VOID *) (UINTN) SmbiosTable->TableAddress;\r
+ *TableMaximumSize = SmbiosTable->TableLength;\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ Validates a SMBIOS 3.0 table entry point.\r
+\r
+ @param TableEntry The SmBios table entry to validate.\r
+ @param TableAddress On exit, point to the smbios table addres.\r
+ @param TableMaximumSize On exit, point to the maximum size of the table.\r
+\r
+ @retval TRUE SMBIOS table entry point is valid.\r
+ @retval FALSE SMBIOS table entry point is malformed.\r
+\r
+**/\r
+STATIC\r
+BOOLEAN\r
+IsValidSmbios30Table (\r
+ IN VOID *TableEntry,\r
+ OUT VOID **TableAddress,\r
+ OUT UINTN *TableMaximumSize\r
+ )\r
+{\r
+ UINT8 Checksum;\r
+ SMBIOS_TABLE_3_0_ENTRY_POINT *SmbiosTable;\r
+ SmbiosTable = (SMBIOS_TABLE_3_0_ENTRY_POINT *) TableEntry;\r
+\r
+ if (CompareMem (SmbiosTable->AnchorString, "_SM3_", 5) != 0) {\r
+ return FALSE;\r
+ }\r
+ if (SmbiosTable->EntryPointLength < sizeof (SMBIOS_TABLE_3_0_ENTRY_POINT)) {\r
+ return FALSE;\r
+ }\r
+ if (SmbiosTable->MajorVersion < 3) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // The whole struct check sum should be zero\r
+ //\r
+ Checksum = CalculateSum8 (\r
+ (UINT8 *) SmbiosTable,\r
+ SmbiosTable->EntryPointLength\r
+ );\r
+ if (Checksum != 0) {\r
+ return FALSE;\r
+ }\r
+\r
+ *TableAddress = (VOID *) (UINTN) SmbiosTable->TableAddress;\r
+ *TableMaximumSize = SmbiosTable->TableMaximumSize;\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ Parse an existing SMBIOS table and insert it using SmbiosAdd.\r
+\r
+ @param ImageHandle The EFI_HANDLE to this driver.\r
+ @param Smbios The SMBIOS table to parse.\r
+ @param Length The length of the SMBIOS table.\r
+\r
+ @retval EFI_SUCCESS SMBIOS table was parsed and installed.\r
+ @retval EFI_OUT_OF_RESOURCES Record was not added due to lack of system resources.\r
+ @retval EFI_INVALID_PARAMETER Smbios is not a correct smbios table\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ParseAndAddExistingSmbiosTable (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN SMBIOS_STRUCTURE_POINTER Smbios,\r
+ IN UINTN Length\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR8 *String;\r
+ EFI_SMBIOS_HANDLE SmbiosHandle;\r
+ SMBIOS_STRUCTURE_POINTER SmbiosEnd;\r
+\r
+ SmbiosEnd.Raw = Smbios.Raw + Length;\r
+\r
+ if (Smbios.Raw >= SmbiosEnd.Raw || Smbios.Raw == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ do {\r
+ //\r
+ // Make sure not to access memory beyond SmbiosEnd\r
+ //\r
+ if (Smbios.Raw + sizeof (SMBIOS_STRUCTURE) > SmbiosEnd.Raw ||\r
+ Smbios.Raw + sizeof (SMBIOS_STRUCTURE) < Smbios.Raw) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Check for end marker\r
+ //\r
+ if (Smbios.Hdr->Type == SMBIOS_TYPE_END_OF_TABLE) {\r
+ break;\r
+ }\r
+ //\r
+ // Make sure not to access memory beyond SmbiosEnd\r
+ // Each structure shall be terminated by a double-null (0000h).\r
+ //\r
+ if (Smbios.Raw + Smbios.Hdr->Length + 2 * sizeof (UINT8) > SmbiosEnd.Raw ||\r
+ Smbios.Raw + Smbios.Hdr->Length + 2 * sizeof (UINT8) < Smbios.Raw) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Install the table\r
+ //\r
+ SmbiosHandle = Smbios.Hdr->Handle;\r
+ Status = SmbiosAdd (\r
+ &mPrivateData.Smbios,\r
+ ImageHandle,\r
+ &SmbiosHandle,\r
+ Smbios.Hdr\r
+ );\r
+\r
+ ASSERT_EFI_ERROR (Status);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Go to the next SMBIOS structure. Each SMBIOS structure may include 2 parts:\r
+ // 1. Formatted section; 2. Unformatted string section. So, 2 steps are needed\r
+ // to skip one SMBIOS structure.\r
+ //\r
+\r
+ //\r
+ // Step 1: Skip over formatted section.\r
+ //\r
+ String = (CHAR8 *) (Smbios.Raw + Smbios.Hdr->Length);\r
+\r
+ //\r
+ // Step 2: Skip over unformatted string section.\r
+ //\r
+ do {\r
+ //\r
+ // Each string is terminated with a NULL(00h) BYTE and the sets of strings\r
+ // is terminated with an additional NULL(00h) BYTE.\r
+ //\r
+ for ( ; *String != 0; String++) {\r
+ if ((UINTN) String >= (UINTN) SmbiosEnd.Raw - sizeof (UINT8)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
+ if (*(UINT8 *) ++String == 0) {\r
+ //\r
+ // Pointer to the next SMBIOS structure.\r
+ //\r
+ Smbios.Raw = (UINT8 *) ++String;\r
+ break;\r
+ }\r
+ } while (TRUE);\r
+ } while (Smbios.Raw < SmbiosEnd.Raw);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Retrieve SMBIOS from Hob.\r
+ @param ImageHandle Module's image handle\r
+\r
+ @retval EFI_SUCCESS Smbios from Hob is installed.\r
+ @return EFI_NOT_FOUND Not found Smbios from Hob.\r
+ @retval Other No Smbios from Hob is installed.\r
+\r
+**/\r
+EFI_STATUS\r
+RetrieveSmbiosFromHob (\r
+ IN EFI_HANDLE ImageHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ SMBIOS_STRUCTURE_POINTER Smbios;\r
+ EFI_HOB_GUID_TYPE *GuidHob;\r
+ UNIVERSAL_PAYLOAD_SMBIOS_TABLE *SmBiosTableAdress;\r
+ UNIVERSAL_PAYLOAD_GENERIC_HEADER *GenericHeader;\r
+ VOID *TableAddress;\r
+ UINTN TableMaximumSize;\r
+\r
+ Status = EFI_NOT_FOUND;\r
+\r
+ for (Index = 0; Index < ARRAY_SIZE (mIsSmbiosTableValid); Index++) {\r
+ GuidHob = GetFirstGuidHob (mIsSmbiosTableValid[Index].Guid);\r
+ if (GuidHob == NULL) {\r
+ continue;\r
+ }\r
+ GenericHeader = (UNIVERSAL_PAYLOAD_GENERIC_HEADER *) GET_GUID_HOB_DATA (GuidHob);\r
+ if ((sizeof (UNIVERSAL_PAYLOAD_GENERIC_HEADER) <= GET_GUID_HOB_DATA_SIZE (GuidHob)) && (GenericHeader->Length <= GET_GUID_HOB_DATA_SIZE (GuidHob))) {\r
+ if (GenericHeader->Revision == UNIVERSAL_PAYLOAD_SMBIOS_TABLE_REVISION) {\r
+ //\r
+ // UNIVERSAL_PAYLOAD_SMBIOS_TABLE structure is used when Revision equals to UNIVERSAL_PAYLOAD_SMBIOS_TABLE_REVISION\r
+ //\r
+ SmBiosTableAdress = (UNIVERSAL_PAYLOAD_SMBIOS_TABLE *) GET_GUID_HOB_DATA (GuidHob);\r
+ if (GenericHeader->Length >= UNIVERSAL_PAYLOAD_SIZEOF_THROUGH_FIELD (UNIVERSAL_PAYLOAD_SMBIOS_TABLE, SmBiosEntryPoint)) {\r
+ if (mIsSmbiosTableValid[Index].IsValid ((VOID *) (UINTN )SmBiosTableAdress->SmBiosEntryPoint, &TableAddress, &TableMaximumSize)) {\r
+ Smbios.Raw = TableAddress;\r
+ Status = ParseAndAddExistingSmbiosTable (ImageHandle, Smbios, TableMaximumSize);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "RetrieveSmbiosFromHob: Failed to parse preinstalled tables from Guid Hob\n"));\r
+ Status = EFI_UNSUPPORTED;\r
+ } else {\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ return Status;\r
+}\r
+\r
/**\r
\r
Driver to produce Smbios protocol and pre-allocate 1 page for the final SMBIOS table.\r
&mPrivateData.Smbios\r
);\r
\r
+ RetrieveSmbiosFromHob (ImageHandle);\r
return Status;\r
}\r