--- /dev/null
+/** @file\r
+ Library to add SMBIOS data records from HOB to SMBIOS table.\r
+\r
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
+\r
+ This program and the accompanying materials are licensed and made available under\r
+ the terms and conditions of the BSD License which accompanies this distribution.\r
+ The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+ @par Specification Reference:\r
+ System Management BIOS (SMBIOS) Reference Specification v3.0.0\r
+ dated 2015-Feb-12 (DSP0134)\r
+ http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.0.0.pdf\r
+\r
+**/\r
+#include <IndustryStandard/SmBios.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Protocol/Smbios.h>\r
+\r
+/**\r
+\r
+ Get the full size of SMBIOS structure including optional strings that follow the formatted structure.\r
+ @note: This function is copy from SmbiosDxe in MdeModulePkg.\r
+\r
+ @param[in] This The EFI_SMBIOS_PROTOCOL instance.\r
+ @param[in] Head Pointer to the beginning of SMBIOS structure.\r
+ @param[out] Size The returned size.\r
+ @param[out] NumberOfStrings The returned number of optional strings that follow the formatted structure.\r
+\r
+ @retval EFI_SUCCESS Size returned in Size.\r
+ @retval EFI_INVALID_PARAMETER Input SMBIOS structure mal-formed or Size is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetSmbiosStructureSize (\r
+ IN CONST EFI_SMBIOS_PROTOCOL *This,\r
+ IN EFI_SMBIOS_TABLE_HEADER *Head,\r
+ OUT UINTN *Size,\r
+ OUT UINTN *NumberOfStrings\r
+ )\r
+{\r
+ UINTN FullSize;\r
+ UINTN StrLen;\r
+ UINTN MaxLen;\r
+ INT8* CharInStr;\r
+\r
+ if (Size == NULL || NumberOfStrings == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ FullSize = Head->Length;\r
+ CharInStr = (INT8*)Head + Head->Length;\r
+ *Size = FullSize;\r
+ *NumberOfStrings = 0;\r
+ StrLen = 0;\r
+\r
+ //\r
+ // look for the two consecutive zeros, check the string limit by the way.\r
+ //\r
+ while (*CharInStr != 0 || *(CharInStr+1) != 0) {\r
+ if (*CharInStr == 0) {\r
+ *Size += 1;\r
+ CharInStr++;\r
+ }\r
+\r
+ if (This->MajorVersion < 2 || (This->MajorVersion == 2 && This->MinorVersion < 7)) {\r
+ MaxLen = SMBIOS_STRING_MAX_LENGTH;\r
+ } else if (This->MajorVersion < 3) {\r
+ //\r
+ // Reference SMBIOS 2.7, chapter 6.1.3, it will have no limit on the length of each individual text string.\r
+ // However, the length of the entire structure table (including all strings) must be reported\r
+ // in the Structure Table Length field of the SMBIOS Structure Table Entry Point,\r
+ // which is a WORD field limited to 65,535 bytes.\r
+ //\r
+ MaxLen = SMBIOS_TABLE_MAX_LENGTH;\r
+ } else {\r
+ //\r
+ // SMBIOS 3.0 defines the Structure table maximum size as DWORD field limited to 0xFFFFFFFF bytes.\r
+ // Locate the end of string as long as possible.\r
+ //\r
+ MaxLen = SMBIOS_3_0_TABLE_MAX_LENGTH;\r
+ }\r
+\r
+ for (StrLen = 0 ; StrLen < MaxLen; StrLen++) {\r
+ if (*(CharInStr+StrLen) == 0) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (StrLen == MaxLen) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // forward the pointer\r
+ //\r
+ CharInStr += StrLen;\r
+ *Size += StrLen;\r
+ *NumberOfStrings += 1;\r
+ }\r
+\r
+ //\r
+ // count ending two zeros.\r
+ //\r
+ *Size += 2;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Adds SMBIOS records to tables\r
+\r
+ @param[in] ImageHandle Image handle of this driver.\r
+ @param[in] SystemTable Global system service table.\r
+\r
+ @retval EFI_UNSUPPORTED - Could not locate SMBIOS protocol\r
+ @retval EFI_OUT_OF_RESOURCES - Failed to allocate memory for SMBIOS HOB type.\r
+ @retval EFI_SUCCESS - Successfully added SMBIOS records based on HOB.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DxeSmbiosDataHobLibConstructor (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_PEI_HOB_POINTERS Hob;\r
+ EFI_SMBIOS_HANDLE SmbiosHandle;\r
+ EFI_SMBIOS_PROTOCOL *Smbios;\r
+ EFI_STATUS Status;\r
+ UINTN InstalledPayloadSize;\r
+ UINTN MaxPayloadSize;\r
+ UINT8 *RecordPtr;\r
+ UINT16 RecordCount;\r
+ UINTN StructureSize;\r
+ UINTN NumberOfStrings;\r
+\r
+ RecordCount = 0;\r
+\r
+ DEBUG ((DEBUG_INFO, "Adding SMBIOS records from HOB..\n"));\r
+\r
+ Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **)&Smbios);\r
+ if (Smbios == NULL) {\r
+ DEBUG ((DEBUG_WARN, " Can't locate SMBIOS protocol\n"));\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ ///\r
+ /// Get SMBIOS HOB data\r
+ ///\r
+ for (Hob.Raw = GetHobList (); !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {\r
+ if ((GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_GUID_EXTENSION) && (CompareGuid (&Hob.Guid->Name, &gIntelSmbiosDataHobGuid))) {\r
+ RecordPtr = (UINT8 *)Hob.Raw + sizeof (EFI_HOB_GUID_TYPE);\r
+ MaxPayloadSize = Hob.Guid->Header.HobLength - sizeof (EFI_HOB_GUID_TYPE);\r
+\r
+ InstalledPayloadSize = 0;\r
+ do {\r
+ StructureSize = 0;\r
+ Status = GetSmbiosStructureSize (Smbios, (EFI_SMBIOS_TABLE_HEADER *)RecordPtr, &StructureSize, &NumberOfStrings);\r
+ if ((Status == EFI_SUCCESS) && (InstalledPayloadSize + StructureSize <= MaxPayloadSize)) {\r
+ InstalledPayloadSize += StructureSize;\r
+\r
+ ///\r
+ /// Add generic SMBIOS HOB to SMBIOS table\r
+ ///\r
+ DEBUG ((DEBUG_VERBOSE, " Add SMBIOS record type: %x\n", ((EFI_SMBIOS_TABLE_HEADER *) RecordPtr)->Type));\r
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;\r
+ Status = Smbios->Add (Smbios, NULL, &SmbiosHandle, (EFI_SMBIOS_TABLE_HEADER *) RecordPtr);\r
+ if (!EFI_ERROR (Status)) {\r
+ RecordPtr += StructureSize;\r
+ RecordCount++;\r
+ }\r
+ } else {\r
+ break;\r
+ }\r
+ } while (TRUE);\r
+ }\r
+ }\r
+ DEBUG ((DEBUG_INFO, " Found %d Records and added to SMBIOS table.\n", RecordCount));\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r