IntelSiliconPkg: Add DxeSmbiosDataHobLib
[mirror_edk2.git] / IntelSiliconPkg / Library / DxeSmbiosDataHobLib / DxeSmbiosDataHobLib.c
1 /** @file
2 Library to add SMBIOS data records from HOB to SMBIOS table.
3
4 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
5
6 This program and the accompanying materials are licensed and made available under
7 the terms and conditions of the BSD License which accompanies this distribution.
8 The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 @par Specification Reference:
15 System Management BIOS (SMBIOS) Reference Specification v3.0.0
16 dated 2015-Feb-12 (DSP0134)
17 http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.0.0.pdf
18
19 **/
20 #include <IndustryStandard/SmBios.h>
21 #include <Library/UefiLib.h>
22 #include <Library/BaseLib.h>
23 #include <Library/BaseMemoryLib.h>
24 #include <Library/MemoryAllocationLib.h>
25 #include <Library/DebugLib.h>
26 #include <Library/HobLib.h>
27 #include <Library/UefiBootServicesTableLib.h>
28 #include <Protocol/Smbios.h>
29
30 /**
31
32 Get the full size of SMBIOS structure including optional strings that follow the formatted structure.
33 @note: This function is copy from SmbiosDxe in MdeModulePkg.
34
35 @param[in] This The EFI_SMBIOS_PROTOCOL instance.
36 @param[in] Head Pointer to the beginning of SMBIOS structure.
37 @param[out] Size The returned size.
38 @param[out] NumberOfStrings The returned number of optional strings that follow the formatted structure.
39
40 @retval EFI_SUCCESS Size returned in Size.
41 @retval EFI_INVALID_PARAMETER Input SMBIOS structure mal-formed or Size is NULL.
42
43 **/
44 EFI_STATUS
45 EFIAPI
46 GetSmbiosStructureSize (
47 IN CONST EFI_SMBIOS_PROTOCOL *This,
48 IN EFI_SMBIOS_TABLE_HEADER *Head,
49 OUT UINTN *Size,
50 OUT UINTN *NumberOfStrings
51 )
52 {
53 UINTN FullSize;
54 UINTN StrLen;
55 UINTN MaxLen;
56 INT8* CharInStr;
57
58 if (Size == NULL || NumberOfStrings == NULL) {
59 return EFI_INVALID_PARAMETER;
60 }
61
62 FullSize = Head->Length;
63 CharInStr = (INT8*)Head + Head->Length;
64 *Size = FullSize;
65 *NumberOfStrings = 0;
66 StrLen = 0;
67
68 //
69 // look for the two consecutive zeros, check the string limit by the way.
70 //
71 while (*CharInStr != 0 || *(CharInStr+1) != 0) {
72 if (*CharInStr == 0) {
73 *Size += 1;
74 CharInStr++;
75 }
76
77 if (This->MajorVersion < 2 || (This->MajorVersion == 2 && This->MinorVersion < 7)) {
78 MaxLen = SMBIOS_STRING_MAX_LENGTH;
79 } else if (This->MajorVersion < 3) {
80 //
81 // Reference SMBIOS 2.7, chapter 6.1.3, it will have no limit on the length of each individual text string.
82 // However, the length of the entire structure table (including all strings) must be reported
83 // in the Structure Table Length field of the SMBIOS Structure Table Entry Point,
84 // which is a WORD field limited to 65,535 bytes.
85 //
86 MaxLen = SMBIOS_TABLE_MAX_LENGTH;
87 } else {
88 //
89 // SMBIOS 3.0 defines the Structure table maximum size as DWORD field limited to 0xFFFFFFFF bytes.
90 // Locate the end of string as long as possible.
91 //
92 MaxLen = SMBIOS_3_0_TABLE_MAX_LENGTH;
93 }
94
95 for (StrLen = 0 ; StrLen < MaxLen; StrLen++) {
96 if (*(CharInStr+StrLen) == 0) {
97 break;
98 }
99 }
100
101 if (StrLen == MaxLen) {
102 return EFI_INVALID_PARAMETER;
103 }
104
105 //
106 // forward the pointer
107 //
108 CharInStr += StrLen;
109 *Size += StrLen;
110 *NumberOfStrings += 1;
111 }
112
113 //
114 // count ending two zeros.
115 //
116 *Size += 2;
117 return EFI_SUCCESS;
118 }
119
120 /**
121 Adds SMBIOS records to tables
122
123 @param[in] ImageHandle Image handle of this driver.
124 @param[in] SystemTable Global system service table.
125
126 @retval EFI_UNSUPPORTED - Could not locate SMBIOS protocol
127 @retval EFI_OUT_OF_RESOURCES - Failed to allocate memory for SMBIOS HOB type.
128 @retval EFI_SUCCESS - Successfully added SMBIOS records based on HOB.
129 **/
130 EFI_STATUS
131 EFIAPI
132 DxeSmbiosDataHobLibConstructor (
133 IN EFI_HANDLE ImageHandle,
134 IN EFI_SYSTEM_TABLE *SystemTable
135 )
136 {
137 EFI_PEI_HOB_POINTERS Hob;
138 EFI_SMBIOS_HANDLE SmbiosHandle;
139 EFI_SMBIOS_PROTOCOL *Smbios;
140 EFI_STATUS Status;
141 UINTN InstalledPayloadSize;
142 UINTN MaxPayloadSize;
143 UINT8 *RecordPtr;
144 UINT16 RecordCount;
145 UINTN StructureSize;
146 UINTN NumberOfStrings;
147
148 RecordCount = 0;
149
150 DEBUG ((DEBUG_INFO, "Adding SMBIOS records from HOB..\n"));
151
152 Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **)&Smbios);
153 if (Smbios == NULL) {
154 DEBUG ((DEBUG_WARN, " Can't locate SMBIOS protocol\n"));
155 return EFI_UNSUPPORTED;
156 }
157
158 ///
159 /// Get SMBIOS HOB data
160 ///
161 for (Hob.Raw = GetHobList (); !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
162 if ((GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_GUID_EXTENSION) && (CompareGuid (&Hob.Guid->Name, &gIntelSmbiosDataHobGuid))) {
163 RecordPtr = (UINT8 *)Hob.Raw + sizeof (EFI_HOB_GUID_TYPE);
164 MaxPayloadSize = Hob.Guid->Header.HobLength - sizeof (EFI_HOB_GUID_TYPE);
165
166 InstalledPayloadSize = 0;
167 do {
168 StructureSize = 0;
169 Status = GetSmbiosStructureSize (Smbios, (EFI_SMBIOS_TABLE_HEADER *)RecordPtr, &StructureSize, &NumberOfStrings);
170 if ((Status == EFI_SUCCESS) && (InstalledPayloadSize + StructureSize <= MaxPayloadSize)) {
171 InstalledPayloadSize += StructureSize;
172
173 ///
174 /// Add generic SMBIOS HOB to SMBIOS table
175 ///
176 DEBUG ((DEBUG_VERBOSE, " Add SMBIOS record type: %x\n", ((EFI_SMBIOS_TABLE_HEADER *) RecordPtr)->Type));
177 SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
178 Status = Smbios->Add (Smbios, NULL, &SmbiosHandle, (EFI_SMBIOS_TABLE_HEADER *) RecordPtr);
179 if (!EFI_ERROR (Status)) {
180 RecordPtr += StructureSize;
181 RecordCount++;
182 }
183 } else {
184 break;
185 }
186 } while (TRUE);
187 }
188 }
189 DEBUG ((DEBUG_INFO, " Found %d Records and added to SMBIOS table.\n", RecordCount));
190
191 return EFI_SUCCESS;
192 }
193