]>
Commit | Line | Data |
---|---|---|
310b04e6 | 1 | /** @file\r |
d1102dba | 2 | This code produces the Smbios protocol. It also responsible for constructing\r |
310b04e6 | 3 | SMBIOS table into system table.\r |
d1102dba | 4 | \r |
70e8c9c3 | 5 | Copyright (c) 2009 - 2021, Intel Corporation. All rights reserved.<BR>\r |
9d510e61 | 6 | SPDX-License-Identifier: BSD-2-Clause-Patent\r |
310b04e6 | 7 | \r |
8 | **/\r | |
9 | \r | |
10 | #include "SmbiosDxe.h"\r | |
11 | \r | |
12 | //\r | |
13 | // Module Global:\r | |
14 | // Since this driver will only ever produce one instance of the\r | |
15 | // protocol you are not required to dynamically allocate the PrivateData.\r | |
16 | //\r | |
1436aea4 | 17 | SMBIOS_INSTANCE mPrivateData;\r |
310b04e6 | 18 | \r |
1436aea4 MK |
19 | UINTN mPreAllocatedPages = 0;\r |
20 | UINTN mPre64BitAllocatedPages = 0;\r | |
4233bf70 | 21 | \r |
310b04e6 | 22 | //\r |
23 | // Chassis for SMBIOS entry point structure that is to be installed into EFI system config table.\r | |
24 | //\r | |
1436aea4 MK |
25 | SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure = NULL;\r |
26 | SMBIOS_TABLE_ENTRY_POINT EntryPointStructureData = {\r | |
310b04e6 | 27 | //\r |
28 | // AnchorString\r | |
29 | //\r | |
30 | {\r | |
31 | 0x5f,\r | |
32 | 0x53,\r | |
33 | 0x4d,\r | |
34 | 0x5f\r | |
35 | },\r | |
36 | //\r | |
37 | // EntryPointStructureChecksum,TO BE FILLED\r | |
38 | //\r | |
39 | 0,\r | |
40 | //\r | |
41 | // EntryPointStructure Length\r | |
42 | //\r | |
43 | 0x1f,\r | |
44 | //\r | |
9f7d5b46 | 45 | // MajorVersion\r |
310b04e6 | 46 | //\r |
fe781940 | 47 | 0,\r |
310b04e6 | 48 | //\r |
9f7d5b46 | 49 | // MinorVersion\r |
310b04e6 | 50 | //\r |
fe781940 | 51 | 0,\r |
310b04e6 | 52 | //\r |
53 | // MaxStructureSize, TO BE FILLED\r | |
54 | //\r | |
55 | 0,\r | |
56 | //\r | |
57 | // EntryPointRevision\r | |
58 | //\r | |
59 | 0,\r | |
60 | //\r | |
61 | // FormattedArea\r | |
62 | //\r | |
63 | {\r | |
64 | 0,\r | |
65 | 0,\r | |
66 | 0,\r | |
67 | 0,\r | |
68 | 0\r | |
69 | },\r | |
70 | //\r | |
71 | // IntermediateAnchorString\r | |
72 | //\r | |
73 | {\r | |
74 | 0x5f,\r | |
75 | 0x44,\r | |
76 | 0x4d,\r | |
77 | 0x49,\r | |
78 | 0x5f\r | |
79 | },\r | |
80 | //\r | |
81 | // IntermediateChecksum, TO BE FILLED\r | |
82 | //\r | |
83 | 0,\r | |
84 | //\r | |
f49146e8 | 85 | // TableLength, TO BE FILLED\r |
310b04e6 | 86 | //\r |
87 | 0,\r | |
88 | //\r | |
f49146e8 | 89 | // TableAddress, TO BE FILLED\r |
310b04e6 | 90 | //\r |
91 | 0,\r | |
92 | //\r | |
93 | // NumberOfSmbiosStructures, TO BE FILLED\r | |
94 | //\r | |
95 | 0,\r | |
96 | //\r | |
97 | // SmbiosBcdRevision\r | |
98 | //\r | |
fe781940 | 99 | 0\r |
310b04e6 | 100 | };\r |
101 | \r | |
1436aea4 MK |
102 | SMBIOS_TABLE_3_0_ENTRY_POINT *Smbios30EntryPointStructure = NULL;\r |
103 | SMBIOS_TABLE_3_0_ENTRY_POINT Smbios30EntryPointStructureData = {\r | |
e63f3308 EL |
104 | //\r |
105 | // AnchorString _SM3_\r | |
106 | //\r | |
107 | {\r | |
108 | 0x5f,\r | |
109 | 0x53,\r | |
110 | 0x4d,\r | |
111 | 0x33,\r | |
112 | 0x5f,\r | |
113 | },\r | |
114 | //\r | |
115 | // EntryPointStructureChecksum,TO BE FILLED\r | |
116 | //\r | |
117 | 0,\r | |
118 | //\r | |
119 | // EntryPointLength\r | |
120 | //\r | |
121 | 0x18,\r | |
122 | //\r | |
123 | // MajorVersion\r | |
124 | //\r | |
125 | 0,\r | |
126 | //\r | |
127 | // MinorVersion\r | |
128 | //\r | |
129 | 0,\r | |
130 | //\r | |
131 | // DocRev\r | |
132 | //\r | |
133 | 0,\r | |
134 | //\r | |
135 | // EntryPointRevision\r | |
136 | //\r | |
137 | 0x01,\r | |
138 | //\r | |
139 | // Reserved\r | |
140 | //\r | |
141 | 0,\r | |
142 | //\r | |
143 | // TableMaximumSize,TO BE FILLED\r | |
144 | //\r | |
145 | 0,\r | |
146 | //\r | |
147 | // TableAddress,TO BE FILLED\r | |
148 | //\r | |
149 | 0\r | |
150 | };\r | |
70e8c9c3 | 151 | \r |
1436aea4 MK |
152 | IS_SMBIOS_TABLE_VALID_ENTRY mIsSmbiosTableValid[] = {\r |
153 | { &gUniversalPayloadSmbios3TableGuid, IsValidSmbios30Table },\r | |
154 | { &gUniversalPayloadSmbiosTableGuid, IsValidSmbios20Table }\r | |
70e8c9c3 ZL |
155 | };\r |
156 | \r | |
310b04e6 | 157 | /**\r |
158 | \r | |
0ddd8553 | 159 | Get the full size of SMBIOS structure including optional strings that follow the formatted structure.\r |
310b04e6 | 160 | \r |
afe3969c | 161 | @param This The EFI_SMBIOS_PROTOCOL instance.\r |
0ddd8553 | 162 | @param Head Pointer to the beginning of SMBIOS structure.\r |
310b04e6 | 163 | @param Size The returned size.\r |
164 | @param NumberOfStrings The returned number of optional strings that follow the formatted structure.\r | |
165 | \r | |
166 | @retval EFI_SUCCESS Size retured in Size.\r | |
0ddd8553 | 167 | @retval EFI_INVALID_PARAMETER Input SMBIOS structure mal-formed or Size is NULL.\r |
d1102dba | 168 | \r |
310b04e6 | 169 | **/\r |
170 | EFI_STATUS\r | |
171 | EFIAPI\r | |
172 | GetSmbiosStructureSize (\r | |
1436aea4 MK |
173 | IN CONST EFI_SMBIOS_PROTOCOL *This,\r |
174 | IN EFI_SMBIOS_TABLE_HEADER *Head,\r | |
175 | OUT UINTN *Size,\r | |
176 | OUT UINTN *NumberOfStrings\r | |
310b04e6 | 177 | )\r |
178 | {\r | |
179 | UINTN FullSize;\r | |
2d97e71f | 180 | UINTN StrLen;\r |
4233bf70 | 181 | UINTN MaxLen;\r |
1436aea4 | 182 | INT8 *CharInStr;\r |
d1102dba | 183 | \r |
1436aea4 | 184 | if ((Size == NULL) || (NumberOfStrings == NULL)) {\r |
310b04e6 | 185 | return EFI_INVALID_PARAMETER;\r |
186 | }\r | |
187 | \r | |
1436aea4 MK |
188 | FullSize = Head->Length;\r |
189 | CharInStr = (INT8 *)Head + Head->Length;\r | |
190 | *Size = FullSize;\r | |
310b04e6 | 191 | *NumberOfStrings = 0;\r |
1436aea4 | 192 | StrLen = 0;\r |
310b04e6 | 193 | //\r |
194 | // look for the two consecutive zeros, check the string limit by the way.\r | |
195 | //\r | |
d1102dba | 196 | while (*CharInStr != 0 || *(CharInStr+1) != 0) {\r |
310b04e6 | 197 | if (*CharInStr == 0) {\r |
310b04e6 | 198 | *Size += 1;\r |
199 | CharInStr++;\r | |
200 | }\r | |
201 | \r | |
1436aea4 | 202 | if ((This->MajorVersion < 2) || ((This->MajorVersion == 2) && (This->MinorVersion < 7))) {\r |
4233bf70 | 203 | MaxLen = SMBIOS_STRING_MAX_LENGTH;\r |
e63f3308 | 204 | } else if (This->MajorVersion < 3) {\r |
afe3969c | 205 | //\r |
4233bf70 SZ |
206 | // Reference SMBIOS 2.7, chapter 6.1.3, it will have no limit on the length of each individual text string.\r |
207 | // However, the length of the entire structure table (including all strings) must be reported\r | |
208 | // in the Structure Table Length field of the SMBIOS Structure Table Entry Point,\r | |
209 | // which is a WORD field limited to 65,535 bytes.\r | |
afe3969c | 210 | //\r |
4233bf70 | 211 | MaxLen = SMBIOS_TABLE_MAX_LENGTH;\r |
e63f3308 EL |
212 | } else {\r |
213 | //\r | |
214 | // SMBIOS 3.0 defines the Structure table maximum size as DWORD field limited to 0xFFFFFFFF bytes.\r | |
215 | // Locate the end of string as long as possible.\r | |
216 | //\r | |
217 | MaxLen = SMBIOS_3_0_TABLE_MAX_LENGTH;\r | |
4233bf70 SZ |
218 | }\r |
219 | \r | |
1436aea4 | 220 | for (StrLen = 0; StrLen < MaxLen; StrLen++) {\r |
4233bf70 SZ |
221 | if (*(CharInStr+StrLen) == 0) {\r |
222 | break;\r | |
afe3969c | 223 | }\r |
310b04e6 | 224 | }\r |
afe3969c | 225 | \r |
4233bf70 SZ |
226 | if (StrLen == MaxLen) {\r |
227 | return EFI_INVALID_PARAMETER;\r | |
228 | }\r | |
229 | \r | |
310b04e6 | 230 | //\r |
231 | // forward the pointer\r | |
232 | //\r | |
1436aea4 MK |
233 | CharInStr += StrLen;\r |
234 | *Size += StrLen;\r | |
310b04e6 | 235 | *NumberOfStrings += 1;\r |
236 | }\r | |
f8ee20c9 | 237 | \r |
310b04e6 | 238 | //\r |
239 | // count ending two zeros.\r | |
240 | //\r | |
241 | *Size += 2;\r | |
afe3969c | 242 | return EFI_SUCCESS;\r |
310b04e6 | 243 | }\r |
244 | \r | |
245 | /**\r | |
246 | \r | |
247 | Determin whether an SmbiosHandle has already in use.\r | |
248 | \r | |
0ddd8553 | 249 | @param Head Pointer to the beginning of SMBIOS structure.\r |
310b04e6 | 250 | @param Handle A unique handle will be assigned to the SMBIOS record.\r |
251 | \r | |
252 | @retval TRUE Smbios handle already in use.\r | |
253 | @retval FALSE Smbios handle is NOT used.\r | |
d1102dba | 254 | \r |
310b04e6 | 255 | **/\r |
256 | BOOLEAN\r | |
257 | EFIAPI\r | |
258 | CheckSmbiosHandleExistance (\r | |
1436aea4 MK |
259 | IN LIST_ENTRY *Head,\r |
260 | IN EFI_SMBIOS_HANDLE Handle\r | |
310b04e6 | 261 | )\r |
262 | {\r | |
1436aea4 MK |
263 | LIST_ENTRY *Link;\r |
264 | SMBIOS_HANDLE_ENTRY *HandleEntry;\r | |
d1102dba | 265 | \r |
310b04e6 | 266 | for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r |
1436aea4 | 267 | HandleEntry = SMBIOS_HANDLE_ENTRY_FROM_LINK (Link);\r |
310b04e6 | 268 | if (HandleEntry->SmbiosHandle == Handle) {\r |
269 | return TRUE;\r | |
270 | }\r | |
271 | }\r | |
272 | \r | |
273 | return FALSE;\r | |
274 | }\r | |
275 | \r | |
276 | /**\r | |
277 | \r | |
278 | Get the max SmbiosHandle that could be use.\r | |
279 | \r | |
280 | @param This The EFI_SMBIOS_PROTOCOL instance.\r | |
281 | @param MaxHandle The max handle that could be assigned to the SMBIOS record.\r | |
282 | \r | |
283 | **/\r | |
284 | VOID\r | |
285 | EFIAPI\r | |
286 | GetMaxSmbiosHandle (\r | |
1436aea4 MK |
287 | IN CONST EFI_SMBIOS_PROTOCOL *This,\r |
288 | IN OUT EFI_SMBIOS_HANDLE *MaxHandle\r | |
d1102dba | 289 | )\r |
310b04e6 | 290 | {\r |
1436aea4 | 291 | if ((This->MajorVersion == 2) && (This->MinorVersion == 0)) {\r |
310b04e6 | 292 | *MaxHandle = 0xFFFE;\r |
293 | } else {\r | |
294 | *MaxHandle = 0xFEFF;\r | |
295 | }\r | |
296 | }\r | |
297 | \r | |
298 | /**\r | |
299 | \r | |
300 | Get an SmbiosHandle that could use.\r | |
301 | \r | |
302 | @param This The EFI_SMBIOS_PROTOCOL instance.\r | |
303 | @param SmbiosHandle A unique handle will be assigned to the SMBIOS record.\r | |
304 | \r | |
305 | @retval EFI_SUCCESS Smbios handle got.\r | |
306 | @retval EFI_OUT_OF_RESOURCES Smbios handle is NOT available.\r | |
d1102dba | 307 | \r |
310b04e6 | 308 | **/\r |
309 | EFI_STATUS\r | |
310 | EFIAPI\r | |
311 | GetAvailableSmbiosHandle (\r | |
1436aea4 MK |
312 | IN CONST EFI_SMBIOS_PROTOCOL *This,\r |
313 | IN OUT EFI_SMBIOS_HANDLE *Handle\r | |
310b04e6 | 314 | )\r |
315 | {\r | |
1436aea4 MK |
316 | LIST_ENTRY *Head;\r |
317 | SMBIOS_INSTANCE *Private;\r | |
318 | EFI_SMBIOS_HANDLE MaxSmbiosHandle;\r | |
319 | EFI_SMBIOS_HANDLE AvailableHandle;\r | |
310b04e6 | 320 | \r |
1436aea4 | 321 | GetMaxSmbiosHandle (This, &MaxSmbiosHandle);\r |
310b04e6 | 322 | \r |
323 | Private = SMBIOS_INSTANCE_FROM_THIS (This);\r | |
1436aea4 | 324 | Head = &Private->AllocatedHandleListHead;\r |
4659816a | 325 | for (AvailableHandle = 0; AvailableHandle < MaxSmbiosHandle; AvailableHandle++) {\r |
1436aea4 | 326 | if (!CheckSmbiosHandleExistance (Head, AvailableHandle)) {\r |
310b04e6 | 327 | *Handle = AvailableHandle;\r |
328 | return EFI_SUCCESS;\r | |
329 | }\r | |
330 | }\r | |
331 | \r | |
332 | return EFI_OUT_OF_RESOURCES;\r | |
333 | }\r | |
334 | \r | |
310b04e6 | 335 | /**\r |
336 | Add an SMBIOS record.\r | |
337 | \r | |
338 | @param This The EFI_SMBIOS_PROTOCOL instance.\r | |
339 | @param ProducerHandle The handle of the controller or driver associated with the SMBIOS information. NULL\r | |
340 | means no handle.\r | |
4659816a SZ |
341 | @param SmbiosHandle On entry, the handle of the SMBIOS record to add. If FFFEh, then a unique handle\r |
342 | will be assigned to the SMBIOS record. If the SMBIOS handle is already in use,\r | |
310b04e6 | 343 | EFI_ALREADY_STARTED is returned and the SMBIOS record is not updated.\r |
344 | @param Record The data for the fixed portion of the SMBIOS record. The format of the record is\r | |
d1102dba LG |
345 | determined by EFI_SMBIOS_TABLE_HEADER.Type. The size of the formatted area is defined\r |
346 | by EFI_SMBIOS_TABLE_HEADER.Length and either followed by a double-null (0x0000) or\r | |
310b04e6 | 347 | a set of null terminated strings and a null.\r |
348 | \r | |
349 | @retval EFI_SUCCESS Record was added.\r | |
350 | @retval EFI_OUT_OF_RESOURCES Record was not added due to lack of system resources.\r | |
351 | @retval EFI_ALREADY_STARTED The SmbiosHandle passed in was already in use.\r | |
352 | \r | |
353 | **/\r | |
354 | EFI_STATUS\r | |
355 | EFIAPI\r | |
356 | SmbiosAdd (\r | |
357 | IN CONST EFI_SMBIOS_PROTOCOL *This,\r | |
e3917e22 | 358 | IN EFI_HANDLE ProducerHandle OPTIONAL,\r |
310b04e6 | 359 | IN OUT EFI_SMBIOS_HANDLE *SmbiosHandle,\r |
360 | IN EFI_SMBIOS_TABLE_HEADER *Record\r | |
361 | )\r | |
362 | {\r | |
1436aea4 MK |
363 | VOID *Raw;\r |
364 | UINTN TotalSize;\r | |
365 | UINTN RecordSize;\r | |
366 | UINTN StructureSize;\r | |
367 | UINTN NumberOfStrings;\r | |
368 | EFI_STATUS Status;\r | |
369 | LIST_ENTRY *Head;\r | |
370 | SMBIOS_INSTANCE *Private;\r | |
371 | EFI_SMBIOS_ENTRY *SmbiosEntry;\r | |
372 | EFI_SMBIOS_HANDLE MaxSmbiosHandle;\r | |
373 | SMBIOS_HANDLE_ENTRY *HandleEntry;\r | |
374 | EFI_SMBIOS_RECORD_HEADER *InternalRecord;\r | |
375 | BOOLEAN Smbios32BitTable;\r | |
376 | BOOLEAN Smbios64BitTable;\r | |
d1102dba | 377 | \r |
310b04e6 | 378 | if (SmbiosHandle == NULL) {\r |
379 | return EFI_INVALID_PARAMETER;\r | |
380 | }\r | |
d1102dba | 381 | \r |
310b04e6 | 382 | Private = SMBIOS_INSTANCE_FROM_THIS (This);\r |
383 | //\r | |
384 | // Check whether SmbiosHandle is already in use\r | |
385 | //\r | |
386 | Head = &Private->AllocatedHandleListHead;\r | |
1436aea4 | 387 | if ((*SmbiosHandle != SMBIOS_HANDLE_PI_RESERVED) && CheckSmbiosHandleExistance (Head, *SmbiosHandle)) {\r |
310b04e6 | 388 | return EFI_ALREADY_STARTED;\r |
389 | }\r | |
390 | \r | |
391 | //\r | |
4659816a | 392 | // when SmbiosHandle is 0xFFFE, an available handle will be assigned\r |
310b04e6 | 393 | //\r |
4659816a | 394 | if (*SmbiosHandle == SMBIOS_HANDLE_PI_RESERVED) {\r |
1436aea4 MK |
395 | Status = GetAvailableSmbiosHandle (This, SmbiosHandle);\r |
396 | if (EFI_ERROR (Status)) {\r | |
310b04e6 | 397 | return Status;\r |
398 | }\r | |
399 | } else {\r | |
400 | //\r | |
401 | // Check this handle validity\r | |
402 | //\r | |
1436aea4 | 403 | GetMaxSmbiosHandle (This, &MaxSmbiosHandle);\r |
310b04e6 | 404 | if (*SmbiosHandle > MaxSmbiosHandle) {\r |
405 | return EFI_INVALID_PARAMETER;\r | |
406 | }\r | |
407 | }\r | |
408 | \r | |
409 | //\r | |
410 | // Calculate record size and string number\r | |
411 | //\r | |
1436aea4 MK |
412 | Status = GetSmbiosStructureSize (This, Record, &StructureSize, &NumberOfStrings);\r |
413 | if (EFI_ERROR (Status)) {\r | |
310b04e6 | 414 | return Status;\r |
415 | }\r | |
416 | \r | |
e63f3308 EL |
417 | Smbios32BitTable = FALSE;\r |
418 | Smbios64BitTable = FALSE;\r | |
d1102dba | 419 | if ((This->MajorVersion < 0x3) ||\r |
1436aea4 MK |
420 | ((This->MajorVersion >= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod) & BIT0) == BIT0)))\r |
421 | {\r | |
4233bf70 | 422 | //\r |
e63f3308 | 423 | // For SMBIOS 32-bit table, the length of the entire structure table (including all strings) must be reported\r |
4233bf70 | 424 | // in the Structure Table Length field of the SMBIOS Structure Table Entry Point,\r |
e63f3308 EL |
425 | // which is a WORD field limited to 65,535 bytes. So the max size of 32-bit table should not exceed 65,535 bytes.\r |
426 | //\r | |
d1102dba | 427 | if ((EntryPointStructure != NULL) &&\r |
1436aea4 MK |
428 | (EntryPointStructure->TableLength + StructureSize > SMBIOS_TABLE_MAX_LENGTH))\r |
429 | {\r | |
87000d77 | 430 | DEBUG ((DEBUG_INFO, "SmbiosAdd: Total length exceeds max 32-bit table length with type = %d size = 0x%x\n", Record->Type, StructureSize));\r |
e63f3308 EL |
431 | } else {\r |
432 | Smbios32BitTable = TRUE;\r | |
87000d77 | 433 | DEBUG ((DEBUG_INFO, "SmbiosAdd: Smbios type %d with size 0x%x is added to 32-bit table\n", Record->Type, StructureSize));\r |
e63f3308 EL |
434 | }\r |
435 | }\r | |
d1102dba | 436 | \r |
e63f3308 EL |
437 | //\r |
438 | // For SMBIOS 3.0, Structure table maximum size in Entry Point structure is DWORD field limited to 0xFFFFFFFF bytes.\r | |
439 | //\r | |
440 | if ((This->MajorVersion >= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod) & BIT1) == BIT1)) {\r | |
441 | //\r | |
442 | // For SMBIOS 64-bit table, Structure table maximum size in SMBIOS 3.0 (64-bit) Entry Point\r | |
443 | // is a DWORD field limited to 0xFFFFFFFF bytes. So the max size of 64-bit table should not exceed 0xFFFFFFFF bytes.\r | |
444 | //\r | |
d1102dba | 445 | if ((Smbios30EntryPointStructure != NULL) &&\r |
1436aea4 MK |
446 | (Smbios30EntryPointStructure->TableMaximumSize + StructureSize > SMBIOS_3_0_TABLE_MAX_LENGTH))\r |
447 | {\r | |
87000d77 | 448 | DEBUG ((DEBUG_INFO, "SmbiosAdd: Total length exceeds max 64-bit table length with type = %d size = 0x%x\n", Record->Type, StructureSize));\r |
e63f3308 | 449 | } else {\r |
87000d77 | 450 | DEBUG ((DEBUG_INFO, "SmbiosAdd: Smbios type %d with size 0x%x is added to 64-bit table\n", Record->Type, StructureSize));\r |
e63f3308 EL |
451 | Smbios64BitTable = TRUE;\r |
452 | }\r | |
453 | }\r | |
454 | \r | |
455 | if ((!Smbios32BitTable) && (!Smbios64BitTable)) {\r | |
456 | //\r | |
457 | // If both 32-bit and 64-bit table are not updated, quit\r | |
4233bf70 SZ |
458 | //\r |
459 | return EFI_OUT_OF_RESOURCES;\r | |
460 | }\r | |
461 | \r | |
310b04e6 | 462 | //\r |
463 | // Enter into critical section\r | |
d1102dba | 464 | //\r |
310b04e6 | 465 | Status = EfiAcquireLockOrFail (&Private->DataLock);\r |
466 | if (EFI_ERROR (Status)) {\r | |
467 | return Status;\r | |
468 | }\r | |
d1102dba | 469 | \r |
1436aea4 MK |
470 | RecordSize = sizeof (EFI_SMBIOS_RECORD_HEADER) + StructureSize;\r |
471 | TotalSize = sizeof (EFI_SMBIOS_ENTRY) + RecordSize;\r | |
310b04e6 | 472 | \r |
473 | //\r | |
474 | // Allocate internal buffer\r | |
475 | //\r | |
0d34b1cf | 476 | SmbiosEntry = AllocateZeroPool (TotalSize);\r |
310b04e6 | 477 | if (SmbiosEntry == NULL) {\r |
478 | EfiReleaseLock (&Private->DataLock);\r | |
479 | return EFI_OUT_OF_RESOURCES;\r | |
480 | }\r | |
1436aea4 MK |
481 | \r |
482 | HandleEntry = AllocateZeroPool (sizeof (SMBIOS_HANDLE_ENTRY));\r | |
310b04e6 | 483 | if (HandleEntry == NULL) {\r |
484 | EfiReleaseLock (&Private->DataLock);\r | |
485 | return EFI_OUT_OF_RESOURCES;\r | |
486 | }\r | |
487 | \r | |
488 | //\r | |
489 | // Build Handle Entry and insert into linked list\r | |
490 | //\r | |
1436aea4 MK |
491 | HandleEntry->Signature = SMBIOS_HANDLE_ENTRY_SIGNATURE;\r |
492 | HandleEntry->SmbiosHandle = *SmbiosHandle;\r | |
493 | InsertTailList (&Private->AllocatedHandleListHead, &HandleEntry->Link);\r | |
310b04e6 | 494 | \r |
1436aea4 MK |
495 | InternalRecord = (EFI_SMBIOS_RECORD_HEADER *)(SmbiosEntry + 1);\r |
496 | Raw = (VOID *)(InternalRecord + 1);\r | |
310b04e6 | 497 | \r |
498 | //\r | |
499 | // Build internal record Header\r | |
500 | //\r | |
1436aea4 MK |
501 | InternalRecord->Version = EFI_SMBIOS_RECORD_HEADER_VERSION;\r |
502 | InternalRecord->HeaderSize = (UINT16)sizeof (EFI_SMBIOS_RECORD_HEADER);\r | |
503 | InternalRecord->RecordSize = RecordSize;\r | |
504 | InternalRecord->ProducerHandle = ProducerHandle;\r | |
310b04e6 | 505 | InternalRecord->NumberOfStrings = NumberOfStrings;\r |
506 | //\r | |
507 | // Insert record into the internal linked list\r | |
508 | //\r | |
1436aea4 MK |
509 | SmbiosEntry->Signature = EFI_SMBIOS_ENTRY_SIGNATURE;\r |
510 | SmbiosEntry->RecordHeader = InternalRecord;\r | |
511 | SmbiosEntry->RecordSize = TotalSize;\r | |
e63f3308 EL |
512 | SmbiosEntry->Smbios32BitTable = Smbios32BitTable;\r |
513 | SmbiosEntry->Smbios64BitTable = Smbios64BitTable;\r | |
310b04e6 | 514 | InsertTailList (&Private->DataListHead, &SmbiosEntry->Link);\r |
515 | \r | |
516 | CopyMem (Raw, Record, StructureSize);\r | |
1436aea4 | 517 | ((EFI_SMBIOS_TABLE_HEADER *)Raw)->Handle = *SmbiosHandle;\r |
310b04e6 | 518 | \r |
0ddd8553 | 519 | //\r |
520 | // Some UEFI drivers (such as network) need some information in SMBIOS table.\r | |
521 | // Here we create SMBIOS table and publish it in\r | |
522 | // configuration table, so other UEFI drivers can get SMBIOS table from\r | |
523 | // configuration table without depending on PI SMBIOS protocol.\r | |
524 | //\r | |
e63f3308 | 525 | SmbiosTableConstruction (Smbios32BitTable, Smbios64BitTable);\r |
d1102dba | 526 | \r |
310b04e6 | 527 | //\r |
528 | // Leave critical section\r | |
529 | //\r | |
530 | EfiReleaseLock (&Private->DataLock);\r | |
531 | return EFI_SUCCESS;\r | |
532 | }\r | |
533 | \r | |
534 | /**\r | |
535 | Update the string associated with an existing SMBIOS record.\r | |
536 | \r | |
537 | @param This The EFI_SMBIOS_PROTOCOL instance.\r | |
538 | @param SmbiosHandle SMBIOS Handle of structure that will have its string updated.\r | |
539 | @param StringNumber The non-zero string number of the string to update\r | |
540 | @param String Update the StringNumber string with String.\r | |
541 | \r | |
542 | @retval EFI_SUCCESS SmbiosHandle had its StringNumber String updated.\r | |
543 | @retval EFI_INVALID_PARAMETER SmbiosHandle does not exist.\r | |
4659816a | 544 | @retval EFI_UNSUPPORTED String was not added because it is longer than the SMBIOS Table supports.\r |
310b04e6 | 545 | @retval EFI_NOT_FOUND The StringNumber.is not valid for this SMBIOS record.\r |
546 | \r | |
547 | **/\r | |
548 | EFI_STATUS\r | |
549 | EFIAPI\r | |
550 | SmbiosUpdateString (\r | |
1436aea4 MK |
551 | IN CONST EFI_SMBIOS_PROTOCOL *This,\r |
552 | IN EFI_SMBIOS_HANDLE *SmbiosHandle,\r | |
553 | IN UINTN *StringNumber,\r | |
554 | IN CHAR8 *String\r | |
310b04e6 | 555 | )\r |
556 | {\r | |
557 | UINTN InputStrLen;\r | |
558 | UINTN TargetStrLen;\r | |
559 | UINTN StrIndex;\r | |
560 | UINTN TargetStrOffset;\r | |
561 | UINTN NewEntrySize;\r | |
562 | CHAR8 *StrStart;\r | |
563 | VOID *Raw;\r | |
564 | LIST_ENTRY *Link;\r | |
565 | LIST_ENTRY *Head;\r | |
566 | EFI_STATUS Status;\r | |
567 | SMBIOS_INSTANCE *Private;\r | |
568 | EFI_SMBIOS_ENTRY *SmbiosEntry;\r | |
569 | EFI_SMBIOS_ENTRY *ResizedSmbiosEntry;\r | |
570 | EFI_SMBIOS_HANDLE MaxSmbiosHandle;\r | |
571 | EFI_SMBIOS_TABLE_HEADER *Record;\r | |
572 | EFI_SMBIOS_RECORD_HEADER *InternalRecord;\r | |
d1102dba | 573 | \r |
310b04e6 | 574 | //\r |
575 | // Check args validity\r | |
576 | //\r | |
1436aea4 | 577 | GetMaxSmbiosHandle (This, &MaxSmbiosHandle);\r |
310b04e6 | 578 | \r |
579 | if (*SmbiosHandle > MaxSmbiosHandle) {\r | |
580 | return EFI_INVALID_PARAMETER;\r | |
581 | }\r | |
582 | \r | |
583 | if (String == NULL) {\r | |
584 | return EFI_ABORTED;\r | |
585 | }\r | |
586 | \r | |
587 | if (*StringNumber == 0) {\r | |
588 | return EFI_NOT_FOUND;\r | |
589 | }\r | |
590 | \r | |
1436aea4 | 591 | InputStrLen = AsciiStrLen (String);\r |
afe3969c | 592 | \r |
1436aea4 | 593 | if ((This->MajorVersion < 2) || ((This->MajorVersion == 2) && (This->MinorVersion < 7))) {\r |
afe3969c SZ |
594 | if (InputStrLen > SMBIOS_STRING_MAX_LENGTH) {\r |
595 | return EFI_UNSUPPORTED;\r | |
596 | }\r | |
e63f3308 | 597 | } else if (This->MajorVersion < 3) {\r |
4233bf70 SZ |
598 | //\r |
599 | // Reference SMBIOS 2.7, chapter 6.1.3, it will have no limit on the length of each individual text string.\r | |
d1102dba | 600 | // However, the length of the entire structure table (including all strings) must be reported\r |
4233bf70 SZ |
601 | // in the Structure Table Length field of the SMBIOS Structure Table Entry Point,\r |
602 | // which is a WORD field limited to 65,535 bytes.\r | |
603 | //\r | |
604 | if (InputStrLen > SMBIOS_TABLE_MAX_LENGTH) {\r | |
605 | return EFI_UNSUPPORTED;\r | |
606 | }\r | |
e63f3308 EL |
607 | } else {\r |
608 | if (InputStrLen > SMBIOS_3_0_TABLE_MAX_LENGTH) {\r | |
609 | //\r | |
610 | // SMBIOS 3.0 defines the Structure table maximum size as DWORD field limited to 0xFFFFFFFF bytes.\r | |
611 | // The input string length should not exceed 0xFFFFFFFF bytes.\r | |
d1102dba | 612 | //\r |
e63f3308 EL |
613 | return EFI_UNSUPPORTED;\r |
614 | }\r | |
310b04e6 | 615 | }\r |
616 | \r | |
617 | Private = SMBIOS_INSTANCE_FROM_THIS (This);\r | |
618 | //\r | |
619 | // Enter into critical section\r | |
d1102dba | 620 | //\r |
310b04e6 | 621 | Status = EfiAcquireLockOrFail (&Private->DataLock);\r |
622 | if (EFI_ERROR (Status)) {\r | |
623 | return Status;\r | |
624 | }\r | |
625 | \r | |
626 | Head = &Private->DataListHead;\r | |
627 | for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r | |
1436aea4 MK |
628 | SmbiosEntry = SMBIOS_ENTRY_FROM_LINK (Link);\r |
629 | Record = (EFI_SMBIOS_TABLE_HEADER *)(SmbiosEntry->RecordHeader + 1);\r | |
310b04e6 | 630 | \r |
afe3969c | 631 | if (Record->Handle == *SmbiosHandle) {\r |
310b04e6 | 632 | //\r |
0ddd8553 | 633 | // Find out the specified SMBIOS record\r |
310b04e6 | 634 | //\r |
635 | if (*StringNumber > SmbiosEntry->RecordHeader->NumberOfStrings) {\r | |
636 | EfiReleaseLock (&Private->DataLock);\r | |
637 | return EFI_NOT_FOUND;\r | |
638 | }\r | |
1436aea4 | 639 | \r |
310b04e6 | 640 | //\r |
641 | // Point to unformed string section\r | |
642 | //\r | |
1436aea4 | 643 | StrStart = (CHAR8 *)Record + Record->Length;\r |
d1102dba | 644 | \r |
310b04e6 | 645 | for (StrIndex = 1, TargetStrOffset = 0; StrIndex < *StringNumber; StrStart++, TargetStrOffset++) {\r |
646 | //\r | |
647 | // A string ends in 00h\r | |
648 | //\r | |
649 | if (*StrStart == 0) {\r | |
650 | StrIndex++;\r | |
651 | }\r | |
d1102dba | 652 | \r |
310b04e6 | 653 | //\r |
654 | // String section ends in double-null (0000h)\r | |
655 | //\r | |
1436aea4 | 656 | if ((*StrStart == 0) && (*(StrStart + 1) == 0)) {\r |
310b04e6 | 657 | EfiReleaseLock (&Private->DataLock);\r |
658 | return EFI_NOT_FOUND;\r | |
d1102dba | 659 | }\r |
310b04e6 | 660 | }\r |
661 | \r | |
f8ee20c9 | 662 | if (*StrStart == 0) {\r |
afe3969c SZ |
663 | StrStart++;\r |
664 | TargetStrOffset++;\r | |
f8ee20c9 | 665 | }\r |
d1102dba | 666 | \r |
310b04e6 | 667 | //\r |
668 | // Now we get the string target\r | |
669 | //\r | |
1436aea4 | 670 | TargetStrLen = AsciiStrLen (StrStart);\r |
310b04e6 | 671 | if (InputStrLen == TargetStrLen) {\r |
1436aea4 | 672 | AsciiStrCpyS (StrStart, TargetStrLen + 1, String);\r |
0ddd8553 | 673 | //\r |
674 | // Some UEFI drivers (such as network) need some information in SMBIOS table.\r | |
675 | // Here we create SMBIOS table and publish it in\r | |
676 | // configuration table, so other UEFI drivers can get SMBIOS table from\r | |
677 | // configuration table without depending on PI SMBIOS protocol.\r | |
678 | //\r | |
e63f3308 | 679 | SmbiosTableConstruction (SmbiosEntry->Smbios32BitTable, SmbiosEntry->Smbios64BitTable);\r |
310b04e6 | 680 | EfiReleaseLock (&Private->DataLock);\r |
681 | return EFI_SUCCESS;\r | |
682 | }\r | |
d1102dba | 683 | \r |
e63f3308 EL |
684 | SmbiosEntry->Smbios32BitTable = FALSE;\r |
685 | SmbiosEntry->Smbios64BitTable = FALSE;\r | |
d1102dba | 686 | if ((This->MajorVersion < 0x3) ||\r |
1436aea4 MK |
687 | ((This->MajorVersion >= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod) & BIT0) == BIT0)))\r |
688 | {\r | |
e63f3308 EL |
689 | //\r |
690 | // 32-bit table is produced, check the valid length.\r | |
691 | //\r | |
d1102dba | 692 | if ((EntryPointStructure != NULL) &&\r |
1436aea4 MK |
693 | (EntryPointStructure->TableLength + InputStrLen - TargetStrLen > SMBIOS_TABLE_MAX_LENGTH))\r |
694 | {\r | |
e63f3308 EL |
695 | //\r |
696 | // The length of the entire structure table (including all strings) must be reported\r | |
697 | // in the Structure Table Length field of the SMBIOS Structure Table Entry Point,\r | |
698 | // which is a WORD field limited to 65,535 bytes.\r | |
699 | //\r | |
87000d77 | 700 | DEBUG ((DEBUG_INFO, "SmbiosUpdateString: Total length exceeds max 32-bit table length\n"));\r |
e63f3308 | 701 | } else {\r |
87000d77 | 702 | DEBUG ((DEBUG_INFO, "SmbiosUpdateString: New smbios record add to 32-bit table\n"));\r |
e63f3308 EL |
703 | SmbiosEntry->Smbios32BitTable = TRUE;\r |
704 | }\r | |
d1102dba | 705 | }\r |
310b04e6 | 706 | \r |
e63f3308 | 707 | if ((This->MajorVersion >= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod) & BIT1) == BIT1)) {\r |
4233bf70 | 708 | //\r |
e63f3308 | 709 | // 64-bit table is produced, check the valid length.\r |
4233bf70 | 710 | //\r |
d1102dba | 711 | if ((Smbios30EntryPointStructure != NULL) &&\r |
1436aea4 MK |
712 | (Smbios30EntryPointStructure->TableMaximumSize + InputStrLen - TargetStrLen > SMBIOS_3_0_TABLE_MAX_LENGTH))\r |
713 | {\r | |
87000d77 | 714 | DEBUG ((DEBUG_INFO, "SmbiosUpdateString: Total length exceeds max 64-bit table length\n"));\r |
e63f3308 | 715 | } else {\r |
87000d77 | 716 | DEBUG ((DEBUG_INFO, "SmbiosUpdateString: New smbios record add to 64-bit table\n"));\r |
e63f3308 EL |
717 | SmbiosEntry->Smbios64BitTable = TRUE;\r |
718 | }\r | |
719 | }\r | |
720 | \r | |
721 | if ((!SmbiosEntry->Smbios32BitTable) && (!SmbiosEntry->Smbios64BitTable)) {\r | |
722 | EfiReleaseLock (&Private->DataLock);\r | |
4233bf70 SZ |
723 | return EFI_UNSUPPORTED;\r |
724 | }\r | |
725 | \r | |
310b04e6 | 726 | //\r |
727 | // Original string buffer size is not exactly match input string length.\r | |
728 | // Re-allocate buffer is needed.\r | |
729 | //\r | |
1436aea4 | 730 | NewEntrySize = SmbiosEntry->RecordSize + InputStrLen - TargetStrLen;\r |
0d34b1cf | 731 | ResizedSmbiosEntry = AllocateZeroPool (NewEntrySize);\r |
310b04e6 | 732 | \r |
733 | if (ResizedSmbiosEntry == NULL) {\r | |
734 | EfiReleaseLock (&Private->DataLock);\r | |
735 | return EFI_OUT_OF_RESOURCES;\r | |
736 | }\r | |
737 | \r | |
1436aea4 MK |
738 | InternalRecord = (EFI_SMBIOS_RECORD_HEADER *)(ResizedSmbiosEntry + 1);\r |
739 | Raw = (VOID *)(InternalRecord + 1);\r | |
310b04e6 | 740 | \r |
741 | //\r | |
742 | // Build internal record Header\r | |
743 | //\r | |
1436aea4 MK |
744 | InternalRecord->Version = EFI_SMBIOS_RECORD_HEADER_VERSION;\r |
745 | InternalRecord->HeaderSize = (UINT16)sizeof (EFI_SMBIOS_RECORD_HEADER);\r | |
746 | InternalRecord->RecordSize = SmbiosEntry->RecordHeader->RecordSize + InputStrLen - TargetStrLen;\r | |
747 | InternalRecord->ProducerHandle = SmbiosEntry->RecordHeader->ProducerHandle;\r | |
310b04e6 | 748 | InternalRecord->NumberOfStrings = SmbiosEntry->RecordHeader->NumberOfStrings;\r |
749 | \r | |
750 | //\r | |
0ddd8553 | 751 | // Copy SMBIOS structure and optional strings.\r |
310b04e6 | 752 | //\r |
f8ee20c9 | 753 | CopyMem (Raw, SmbiosEntry->RecordHeader + 1, Record->Length + TargetStrOffset);\r |
1436aea4 MK |
754 | CopyMem ((VOID *)((UINTN)Raw + Record->Length + TargetStrOffset), String, InputStrLen + 1);\r |
755 | CopyMem (\r | |
756 | (CHAR8 *)((UINTN)Raw + Record->Length + TargetStrOffset + InputStrLen + 1),\r | |
757 | (CHAR8 *)Record + Record->Length + TargetStrOffset + TargetStrLen + 1,\r | |
758 | SmbiosEntry->RecordHeader->RecordSize - sizeof (EFI_SMBIOS_RECORD_HEADER) - Record->Length - TargetStrOffset - TargetStrLen - 1\r | |
759 | );\r | |
310b04e6 | 760 | \r |
761 | //\r | |
762 | // Insert new record\r | |
763 | //\r | |
1436aea4 MK |
764 | ResizedSmbiosEntry->Signature = EFI_SMBIOS_ENTRY_SIGNATURE;\r |
765 | ResizedSmbiosEntry->RecordHeader = InternalRecord;\r | |
766 | ResizedSmbiosEntry->RecordSize = NewEntrySize;\r | |
e63f3308 EL |
767 | ResizedSmbiosEntry->Smbios32BitTable = SmbiosEntry->Smbios32BitTable;\r |
768 | ResizedSmbiosEntry->Smbios64BitTable = SmbiosEntry->Smbios64BitTable;\r | |
310b04e6 | 769 | InsertTailList (Link->ForwardLink, &ResizedSmbiosEntry->Link);\r |
770 | \r | |
771 | //\r | |
772 | // Remove old record\r | |
773 | //\r | |
1436aea4 MK |
774 | RemoveEntryList (Link);\r |
775 | FreePool (SmbiosEntry);\r | |
0ddd8553 | 776 | //\r |
777 | // Some UEFI drivers (such as network) need some information in SMBIOS table.\r | |
778 | // Here we create SMBIOS table and publish it in\r | |
779 | // configuration table, so other UEFI drivers can get SMBIOS table from\r | |
780 | // configuration table without depending on PI SMBIOS protocol.\r | |
781 | //\r | |
e63f3308 | 782 | SmbiosTableConstruction (ResizedSmbiosEntry->Smbios32BitTable, ResizedSmbiosEntry->Smbios64BitTable);\r |
310b04e6 | 783 | EfiReleaseLock (&Private->DataLock);\r |
784 | return EFI_SUCCESS;\r | |
785 | }\r | |
786 | }\r | |
787 | \r | |
788 | EfiReleaseLock (&Private->DataLock);\r | |
789 | return EFI_INVALID_PARAMETER;\r | |
790 | }\r | |
791 | \r | |
792 | /**\r | |
793 | Remove an SMBIOS record.\r | |
794 | \r | |
795 | @param This The EFI_SMBIOS_PROTOCOL instance.\r | |
796 | @param SmbiosHandle The handle of the SMBIOS record to remove.\r | |
797 | \r | |
798 | @retval EFI_SUCCESS SMBIOS record was removed.\r | |
799 | @retval EFI_INVALID_PARAMETER SmbiosHandle does not specify a valid SMBIOS record.\r | |
800 | \r | |
801 | **/\r | |
802 | EFI_STATUS\r | |
803 | EFIAPI\r | |
804 | SmbiosRemove (\r | |
1436aea4 MK |
805 | IN CONST EFI_SMBIOS_PROTOCOL *This,\r |
806 | IN EFI_SMBIOS_HANDLE SmbiosHandle\r | |
310b04e6 | 807 | )\r |
808 | {\r | |
1436aea4 MK |
809 | LIST_ENTRY *Link;\r |
810 | LIST_ENTRY *Head;\r | |
811 | EFI_STATUS Status;\r | |
812 | EFI_SMBIOS_HANDLE MaxSmbiosHandle;\r | |
813 | SMBIOS_INSTANCE *Private;\r | |
814 | EFI_SMBIOS_ENTRY *SmbiosEntry;\r | |
815 | SMBIOS_HANDLE_ENTRY *HandleEntry;\r | |
816 | EFI_SMBIOS_TABLE_HEADER *Record;\r | |
310b04e6 | 817 | \r |
818 | //\r | |
819 | // Check args validity\r | |
820 | //\r | |
1436aea4 | 821 | GetMaxSmbiosHandle (This, &MaxSmbiosHandle);\r |
310b04e6 | 822 | \r |
823 | if (SmbiosHandle > MaxSmbiosHandle) {\r | |
824 | return EFI_INVALID_PARAMETER;\r | |
825 | }\r | |
826 | \r | |
827 | Private = SMBIOS_INSTANCE_FROM_THIS (This);\r | |
828 | //\r | |
829 | // Enter into critical section\r | |
d1102dba | 830 | //\r |
310b04e6 | 831 | Status = EfiAcquireLockOrFail (&Private->DataLock);\r |
832 | if (EFI_ERROR (Status)) {\r | |
833 | return Status;\r | |
834 | }\r | |
835 | \r | |
836 | Head = &Private->DataListHead;\r | |
837 | for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r | |
1436aea4 MK |
838 | SmbiosEntry = SMBIOS_ENTRY_FROM_LINK (Link);\r |
839 | Record = (EFI_SMBIOS_TABLE_HEADER *)(SmbiosEntry->RecordHeader + 1);\r | |
afe3969c | 840 | if (Record->Handle == SmbiosHandle) {\r |
310b04e6 | 841 | //\r |
842 | // Remove specified smobios record from DataList\r | |
843 | //\r | |
1436aea4 | 844 | RemoveEntryList (Link);\r |
d1102dba | 845 | //\r |
310b04e6 | 846 | // Remove this handle from AllocatedHandleList\r |
847 | //\r | |
848 | Head = &Private->AllocatedHandleListHead;\r | |
849 | for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r | |
1436aea4 | 850 | HandleEntry = SMBIOS_HANDLE_ENTRY_FROM_LINK (Link);\r |
afe3969c | 851 | if (HandleEntry->SmbiosHandle == SmbiosHandle) {\r |
1436aea4 MK |
852 | RemoveEntryList (Link);\r |
853 | FreePool (HandleEntry);\r | |
310b04e6 | 854 | break;\r |
855 | }\r | |
856 | }\r | |
1436aea4 | 857 | \r |
0ddd8553 | 858 | //\r |
859 | // Some UEFI drivers (such as network) need some information in SMBIOS table.\r | |
860 | // Here we create SMBIOS table and publish it in\r | |
861 | // configuration table, so other UEFI drivers can get SMBIOS table from\r | |
862 | // configuration table without depending on PI SMBIOS protocol.\r | |
863 | //\r | |
e63f3308 | 864 | if (SmbiosEntry->Smbios32BitTable) {\r |
87000d77 | 865 | DEBUG ((DEBUG_INFO, "SmbiosRemove: remove from 32-bit table\n"));\r |
e63f3308 | 866 | }\r |
1436aea4 | 867 | \r |
e63f3308 | 868 | if (SmbiosEntry->Smbios64BitTable) {\r |
87000d77 | 869 | DEBUG ((DEBUG_INFO, "SmbiosRemove: remove from 64-bit table\n"));\r |
e63f3308 | 870 | }\r |
1436aea4 | 871 | \r |
e63f3308 EL |
872 | //\r |
873 | // Update the whole SMBIOS table again based on which table the removed SMBIOS record is in.\r | |
874 | //\r | |
875 | SmbiosTableConstruction (SmbiosEntry->Smbios32BitTable, SmbiosEntry->Smbios64BitTable);\r | |
1436aea4 | 876 | FreePool (SmbiosEntry);\r |
310b04e6 | 877 | EfiReleaseLock (&Private->DataLock);\r |
878 | return EFI_SUCCESS;\r | |
879 | }\r | |
880 | }\r | |
881 | \r | |
882 | //\r | |
883 | // Leave critical section\r | |
884 | //\r | |
885 | EfiReleaseLock (&Private->DataLock);\r | |
886 | return EFI_INVALID_PARAMETER;\r | |
310b04e6 | 887 | }\r |
888 | \r | |
889 | /**\r | |
890 | Allow the caller to discover all or some of the SMBIOS records.\r | |
891 | \r | |
892 | @param This The EFI_SMBIOS_PROTOCOL instance.\r | |
893 | @param SmbiosHandle On entry, points to the previous handle of the SMBIOS record. On exit, points to the\r | |
4659816a SZ |
894 | next SMBIOS record handle. If it is FFFEh on entry, then the first SMBIOS record\r |
895 | handle will be returned. If it returns FFFEh on exit, then there are no more SMBIOS records.\r | |
d1102dba | 896 | @param Type On entry it means return the next SMBIOS record of type Type. If a NULL is passed in\r |
310b04e6 | 897 | this functionally it ignored. Type is not modified by the GetNext() function.\r |
898 | @param Record On exit, points to the SMBIOS Record consisting of the formatted area followed by\r | |
899 | the unformatted area. The unformatted area optionally contains text strings.\r | |
d1102dba LG |
900 | @param ProducerHandle On exit, points to the ProducerHandle registered by Add(). If no ProducerHandle was passed into Add() NULL is returned.\r |
901 | If a NULL pointer is passed in no data will be returned\r | |
902 | \r | |
310b04e6 | 903 | @retval EFI_SUCCESS SMBIOS record information was successfully returned in Record.\r |
310b04e6 | 904 | @retval EFI_NOT_FOUND The SMBIOS record with SmbiosHandle was the last available record.\r |
905 | \r | |
906 | **/\r | |
907 | EFI_STATUS\r | |
908 | EFIAPI\r | |
909 | SmbiosGetNext (\r | |
1436aea4 MK |
910 | IN CONST EFI_SMBIOS_PROTOCOL *This,\r |
911 | IN OUT EFI_SMBIOS_HANDLE *SmbiosHandle,\r | |
912 | IN EFI_SMBIOS_TYPE *Type OPTIONAL,\r | |
913 | OUT EFI_SMBIOS_TABLE_HEADER **Record,\r | |
914 | OUT EFI_HANDLE *ProducerHandle OPTIONAL\r | |
310b04e6 | 915 | )\r |
916 | {\r | |
917 | BOOLEAN StartPointFound;\r | |
918 | LIST_ENTRY *Link;\r | |
919 | LIST_ENTRY *Head;\r | |
920 | SMBIOS_INSTANCE *Private;\r | |
921 | EFI_SMBIOS_ENTRY *SmbiosEntry;\r | |
922 | EFI_SMBIOS_TABLE_HEADER *SmbiosTableHeader;\r | |
923 | \r | |
924 | if (SmbiosHandle == NULL) {\r | |
925 | return EFI_INVALID_PARAMETER;\r | |
926 | }\r | |
927 | \r | |
928 | StartPointFound = FALSE;\r | |
1436aea4 MK |
929 | Private = SMBIOS_INSTANCE_FROM_THIS (This);\r |
930 | Head = &Private->DataListHead;\r | |
310b04e6 | 931 | for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r |
1436aea4 MK |
932 | SmbiosEntry = SMBIOS_ENTRY_FROM_LINK (Link);\r |
933 | SmbiosTableHeader = (EFI_SMBIOS_TABLE_HEADER *)(SmbiosEntry->RecordHeader + 1);\r | |
310b04e6 | 934 | \r |
935 | //\r | |
4659816a | 936 | // If SmbiosHandle is 0xFFFE, the first matched SMBIOS record handle will be returned\r |
310b04e6 | 937 | //\r |
4659816a | 938 | if (*SmbiosHandle == SMBIOS_HANDLE_PI_RESERVED) {\r |
310b04e6 | 939 | if ((Type != NULL) && (*Type != SmbiosTableHeader->Type)) {\r |
d1102dba | 940 | continue;\r |
310b04e6 | 941 | }\r |
942 | \r | |
943 | *SmbiosHandle = SmbiosTableHeader->Handle;\r | |
1436aea4 | 944 | *Record = SmbiosTableHeader;\r |
310b04e6 | 945 | if (ProducerHandle != NULL) {\r |
946 | *ProducerHandle = SmbiosEntry->RecordHeader->ProducerHandle;\r | |
947 | }\r | |
1436aea4 | 948 | \r |
310b04e6 | 949 | return EFI_SUCCESS;\r |
950 | }\r | |
951 | \r | |
952 | //\r | |
0ddd8553 | 953 | // Start this round search from the next SMBIOS handle\r |
310b04e6 | 954 | //\r |
955 | if (!StartPointFound && (*SmbiosHandle == SmbiosTableHeader->Handle)) {\r | |
956 | StartPointFound = TRUE;\r | |
957 | continue;\r | |
958 | }\r | |
959 | \r | |
960 | if (StartPointFound) {\r | |
961 | if ((Type != NULL) && (*Type != SmbiosTableHeader->Type)) {\r | |
d1102dba | 962 | continue;\r |
310b04e6 | 963 | }\r |
d1102dba | 964 | \r |
310b04e6 | 965 | *SmbiosHandle = SmbiosTableHeader->Handle;\r |
1436aea4 | 966 | *Record = SmbiosTableHeader;\r |
310b04e6 | 967 | if (ProducerHandle != NULL) {\r |
968 | *ProducerHandle = SmbiosEntry->RecordHeader->ProducerHandle;\r | |
969 | }\r | |
970 | \r | |
d1102dba | 971 | return EFI_SUCCESS;\r |
310b04e6 | 972 | }\r |
973 | }\r | |
974 | \r | |
4659816a | 975 | *SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;\r |
310b04e6 | 976 | return EFI_NOT_FOUND;\r |
310b04e6 | 977 | }\r |
978 | \r | |
0ddd8553 | 979 | /**\r |
980 | Allow the caller to discover all of the SMBIOS records.\r | |
981 | \r | |
982 | @param This The EFI_SMBIOS_PROTOCOL instance.\r | |
d1102dba LG |
983 | @param CurrentSmbiosEntry On exit, points to the SMBIOS entry on the list which includes the returned SMBIOS record information.\r |
984 | If *CurrentSmbiosEntry is NULL on entry, then the first SMBIOS entry on the list will be returned.\r | |
0ddd8553 | 985 | @param Record On exit, points to the SMBIOS Record consisting of the formatted area followed by\r |
986 | the unformatted area. The unformatted area optionally contains text strings.\r | |
d1102dba | 987 | \r |
0ddd8553 | 988 | @retval EFI_SUCCESS SMBIOS record information was successfully returned in Record.\r |
989 | *CurrentSmbiosEntry points to the SMBIOS entry which includes the returned SMBIOS record information.\r | |
990 | @retval EFI_NOT_FOUND There is no more SMBIOS entry.\r | |
991 | \r | |
992 | **/\r | |
993 | EFI_STATUS\r | |
994 | EFIAPI\r | |
995 | GetNextSmbiosRecord (\r | |
1436aea4 MK |
996 | IN CONST EFI_SMBIOS_PROTOCOL *This,\r |
997 | IN OUT EFI_SMBIOS_ENTRY **CurrentSmbiosEntry,\r | |
998 | OUT EFI_SMBIOS_TABLE_HEADER **Record\r | |
0ddd8553 | 999 | )\r |
1000 | {\r | |
1001 | LIST_ENTRY *Link;\r | |
1002 | LIST_ENTRY *Head;\r | |
1003 | SMBIOS_INSTANCE *Private;\r | |
1004 | EFI_SMBIOS_ENTRY *SmbiosEntry;\r | |
1005 | EFI_SMBIOS_TABLE_HEADER *SmbiosTableHeader;\r | |
1006 | \r | |
1007 | Private = SMBIOS_INSTANCE_FROM_THIS (This);\r | |
1008 | if (*CurrentSmbiosEntry == NULL) {\r | |
1009 | //\r | |
1010 | // Get the beginning of SMBIOS entry.\r | |
1011 | //\r | |
1012 | Head = &Private->DataListHead;\r | |
1013 | } else {\r | |
1014 | //\r | |
1015 | // Get previous SMBIOS entry and make it as start point.\r | |
1016 | //\r | |
1017 | Head = &(*CurrentSmbiosEntry)->Link;\r | |
1018 | }\r | |
d1102dba | 1019 | \r |
1436aea4 | 1020 | Link = Head->ForwardLink;\r |
d1102dba | 1021 | \r |
0ddd8553 | 1022 | if (Link == &Private->DataListHead) {\r |
1023 | //\r | |
1024 | // If no more SMBIOS entry in the list, return not found.\r | |
1025 | //\r | |
1026 | return EFI_NOT_FOUND;\r | |
1027 | }\r | |
d1102dba | 1028 | \r |
1436aea4 MK |
1029 | SmbiosEntry = SMBIOS_ENTRY_FROM_LINK (Link);\r |
1030 | SmbiosTableHeader = (EFI_SMBIOS_TABLE_HEADER *)(SmbiosEntry->RecordHeader + 1);\r | |
1031 | *Record = SmbiosTableHeader;\r | |
0ddd8553 | 1032 | *CurrentSmbiosEntry = SmbiosEntry;\r |
d1102dba | 1033 | return EFI_SUCCESS;\r |
0ddd8553 | 1034 | }\r |
310b04e6 | 1035 | \r |
1036 | /**\r | |
0ddd8553 | 1037 | Assembles SMBIOS table from the SMBIOS protocol. Produce Table\r |
310b04e6 | 1038 | Entry Point and return the pointer to it.\r |
d1102dba | 1039 | \r |
310b04e6 | 1040 | @param TableEntryPointStructure On exit, points to the SMBIOS entrypoint structure.\r |
d1102dba | 1041 | \r |
310b04e6 | 1042 | @retval EFI_SUCCESS Structure created sucessfully.\r |
310b04e6 | 1043 | @retval EFI_OUT_OF_RESOURCES No enough memory.\r |
d1102dba | 1044 | \r |
310b04e6 | 1045 | **/\r |
1046 | EFI_STATUS\r | |
1047 | EFIAPI\r | |
1048 | SmbiosCreateTable (\r | |
1436aea4 | 1049 | OUT VOID **TableEntryPointStructure\r |
310b04e6 | 1050 | )\r |
1051 | {\r | |
310b04e6 | 1052 | UINT8 *BufferPointer;\r |
310b04e6 | 1053 | UINTN RecordSize;\r |
1054 | UINTN NumOfStr;\r | |
1055 | EFI_STATUS Status;\r | |
1056 | EFI_SMBIOS_HANDLE SmbiosHandle;\r | |
1057 | EFI_SMBIOS_PROTOCOL *SmbiosProtocol;\r | |
1058 | EFI_PHYSICAL_ADDRESS PhysicalAddress;\r | |
1059 | EFI_SMBIOS_TABLE_HEADER *SmbiosRecord;\r | |
1060 | EFI_SMBIOS_TABLE_END_STRUCTURE EndStructure;\r | |
0ddd8553 | 1061 | EFI_SMBIOS_ENTRY *CurrentSmbiosEntry;\r |
d1102dba | 1062 | \r |
1436aea4 MK |
1063 | Status = EFI_SUCCESS;\r |
1064 | BufferPointer = NULL;\r | |
310b04e6 | 1065 | \r |
e63f3308 EL |
1066 | if (EntryPointStructure == NULL) {\r |
1067 | //\r | |
1068 | // Initialize the EntryPointStructure with initial values.\r | |
1069 | // It should be done only once.\r | |
1070 | // Allocate memory (below 4GB).\r | |
1071 | //\r | |
87000d77 | 1072 | DEBUG ((DEBUG_INFO, "SmbiosCreateTable: Initialize 32-bit entry point structure\n"));\r |
1436aea4 MK |
1073 | EntryPointStructureData.MajorVersion = mPrivateData.Smbios.MajorVersion;\r |
1074 | EntryPointStructureData.MinorVersion = mPrivateData.Smbios.MinorVersion;\r | |
1075 | EntryPointStructureData.SmbiosBcdRevision = (UINT8)((PcdGet16 (PcdSmbiosVersion) >> 4) & 0xf0) | (UINT8)(PcdGet16 (PcdSmbiosVersion) & 0x0f);\r | |
1076 | PhysicalAddress = 0xffffffff;\r | |
1077 | Status = gBS->AllocatePages (\r | |
1078 | AllocateMaxAddress,\r | |
1079 | EfiRuntimeServicesData,\r | |
1080 | EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT)),\r | |
1081 | &PhysicalAddress\r | |
1082 | );\r | |
e63f3308 | 1083 | if (EFI_ERROR (Status)) {\r |
87000d77 | 1084 | DEBUG ((DEBUG_ERROR, "SmbiosCreateTable () could not allocate EntryPointStructure < 4GB\n"));\r |
e63f3308 EL |
1085 | Status = gBS->AllocatePages (\r |
1086 | AllocateAnyPages,\r | |
1087 | EfiRuntimeServicesData,\r | |
1088 | EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT)),\r | |
1089 | &PhysicalAddress\r | |
1090 | );\r | |
1436aea4 | 1091 | if (EFI_ERROR (Status)) {\r |
e63f3308 EL |
1092 | return EFI_OUT_OF_RESOURCES;\r |
1093 | }\r | |
1094 | }\r | |
d1102dba | 1095 | \r |
1436aea4 | 1096 | EntryPointStructure = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)PhysicalAddress;\r |
d1102dba | 1097 | \r |
e63f3308 EL |
1098 | CopyMem (\r |
1099 | EntryPointStructure,\r | |
1100 | &EntryPointStructureData,\r | |
1101 | sizeof (SMBIOS_TABLE_ENTRY_POINT)\r | |
1102 | );\r | |
1103 | }\r | |
1104 | \r | |
310b04e6 | 1105 | //\r |
0ddd8553 | 1106 | // Get Smbios protocol to traverse SMBIOS records.\r |
310b04e6 | 1107 | //\r |
0ddd8553 | 1108 | SmbiosProtocol = &mPrivateData.Smbios;\r |
310b04e6 | 1109 | \r |
310b04e6 | 1110 | //\r |
1111 | // Make some statistics about all the structures\r | |
1112 | //\r | |
1113 | EntryPointStructure->NumberOfSmbiosStructures = 0;\r | |
1114 | EntryPointStructure->TableLength = 0;\r | |
1115 | EntryPointStructure->MaxStructureSize = 0;\r | |
310b04e6 | 1116 | \r |
1117 | //\r | |
1118 | // Calculate EPS Table Length\r | |
1119 | //\r | |
0ddd8553 | 1120 | CurrentSmbiosEntry = NULL;\r |
310b04e6 | 1121 | do {\r |
0ddd8553 | 1122 | Status = GetNextSmbiosRecord (SmbiosProtocol, &CurrentSmbiosEntry, &SmbiosRecord);\r |
d1102dba | 1123 | \r |
e63f3308 | 1124 | if ((Status == EFI_SUCCESS) && (CurrentSmbiosEntry->Smbios32BitTable)) {\r |
1436aea4 | 1125 | GetSmbiosStructureSize (SmbiosProtocol, SmbiosRecord, &RecordSize, &NumOfStr);\r |
310b04e6 | 1126 | //\r |
1127 | // Record NumberOfSmbiosStructures, TableLength and MaxStructureSize\r | |
1128 | //\r | |
afe3969c | 1129 | EntryPointStructure->NumberOfSmbiosStructures++;\r |
1436aea4 | 1130 | EntryPointStructure->TableLength = (UINT16)(EntryPointStructure->TableLength + RecordSize);\r |
310b04e6 | 1131 | if (RecordSize > EntryPointStructure->MaxStructureSize) {\r |
1436aea4 | 1132 | EntryPointStructure->MaxStructureSize = (UINT16)RecordSize;\r |
310b04e6 | 1133 | }\r |
1134 | }\r | |
1436aea4 | 1135 | } while (!EFI_ERROR (Status));\r |
d1102dba | 1136 | \r |
310b04e6 | 1137 | //\r |
1138 | // Create End-Of-Table structure\r | |
1139 | //\r | |
1436aea4 MK |
1140 | GetMaxSmbiosHandle (SmbiosProtocol, &SmbiosHandle);\r |
1141 | EndStructure.Header.Type = SMBIOS_TYPE_END_OF_TABLE;\r | |
1142 | EndStructure.Header.Length = (UINT8)sizeof (EFI_SMBIOS_TABLE_HEADER);\r | |
310b04e6 | 1143 | EndStructure.Header.Handle = SmbiosHandle;\r |
1436aea4 MK |
1144 | EndStructure.Tailing[0] = 0;\r |
1145 | EndStructure.Tailing[1] = 0;\r | |
310b04e6 | 1146 | EntryPointStructure->NumberOfSmbiosStructures++;\r |
1436aea4 | 1147 | EntryPointStructure->TableLength = (UINT16)(EntryPointStructure->TableLength + sizeof (EndStructure));\r |
310b04e6 | 1148 | if (sizeof (EndStructure) > EntryPointStructure->MaxStructureSize) {\r |
1436aea4 | 1149 | EntryPointStructure->MaxStructureSize = (UINT16)sizeof (EndStructure);\r |
310b04e6 | 1150 | }\r |
310b04e6 | 1151 | \r |
1436aea4 | 1152 | if (EFI_SIZE_TO_PAGES ((UINT32)EntryPointStructure->TableLength) > mPreAllocatedPages) {\r |
0ddd8553 | 1153 | //\r |
d1102dba | 1154 | // If new SMBIOS table size exceeds the previous allocated page,\r |
0ddd8553 | 1155 | // it is time to re-allocate memory (below 4GB).\r |
d1102dba | 1156 | //\r |
1436aea4 MK |
1157 | DEBUG ((\r |
1158 | DEBUG_INFO,\r | |
1159 | "%a() re-allocate SMBIOS 32-bit table\n",\r | |
1160 | __FUNCTION__\r | |
1161 | ));\r | |
0ddd8553 | 1162 | if (EntryPointStructure->TableAddress != 0) {\r |
1163 | //\r | |
e63f3308 | 1164 | // Free the previous allocated page\r |
d1102dba | 1165 | //\r |
0ddd8553 | 1166 | FreePages (\r |
1436aea4 MK |
1167 | (VOID *)(UINTN)EntryPointStructure->TableAddress,\r |
1168 | mPreAllocatedPages\r | |
1169 | );\r | |
0ddd8553 | 1170 | EntryPointStructure->TableAddress = 0;\r |
1436aea4 | 1171 | mPreAllocatedPages = 0;\r |
0ddd8553 | 1172 | }\r |
d1102dba | 1173 | \r |
0ddd8553 | 1174 | PhysicalAddress = 0xffffffff;\r |
1436aea4 MK |
1175 | Status = gBS->AllocatePages (\r |
1176 | AllocateMaxAddress,\r | |
1177 | EfiRuntimeServicesData,\r | |
1178 | EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength),\r | |
1179 | &PhysicalAddress\r | |
1180 | );\r | |
0ddd8553 | 1181 | if (EFI_ERROR (Status)) {\r |
87000d77 | 1182 | DEBUG ((DEBUG_ERROR, "SmbiosCreateTable() could not allocate SMBIOS table < 4GB\n"));\r |
c7ce5169 | 1183 | EntryPointStructure->TableAddress = 0;\r |
0ddd8553 | 1184 | return EFI_OUT_OF_RESOURCES;\r |
c7ce5169 | 1185 | } else {\r |
1436aea4 MK |
1186 | EntryPointStructure->TableAddress = (UINT32)PhysicalAddress;\r |
1187 | mPreAllocatedPages = EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength);\r | |
0ddd8553 | 1188 | }\r |
0ddd8553 | 1189 | }\r |
d1102dba | 1190 | \r |
310b04e6 | 1191 | //\r |
1192 | // Assemble the tables\r | |
1193 | //\r | |
f63085f5 | 1194 | ASSERT (EntryPointStructure->TableAddress != 0);\r |
1436aea4 | 1195 | BufferPointer = (UINT8 *)(UINTN)EntryPointStructure->TableAddress;\r |
0ddd8553 | 1196 | CurrentSmbiosEntry = NULL;\r |
310b04e6 | 1197 | do {\r |
0ddd8553 | 1198 | Status = GetNextSmbiosRecord (SmbiosProtocol, &CurrentSmbiosEntry, &SmbiosRecord);\r |
1199 | \r | |
e63f3308 | 1200 | if ((Status == EFI_SUCCESS) && (CurrentSmbiosEntry->Smbios32BitTable)) {\r |
1436aea4 | 1201 | GetSmbiosStructureSize (SmbiosProtocol, SmbiosRecord, &RecordSize, &NumOfStr);\r |
310b04e6 | 1202 | CopyMem (BufferPointer, SmbiosRecord, RecordSize);\r |
1203 | BufferPointer = BufferPointer + RecordSize;\r | |
1204 | }\r | |
1436aea4 | 1205 | } while (!EFI_ERROR (Status));\r |
d1102dba | 1206 | \r |
310b04e6 | 1207 | //\r |
1208 | // Assemble End-Of-Table structure\r | |
1209 | //\r | |
1210 | CopyMem (BufferPointer, &EndStructure, sizeof (EndStructure));\r | |
1211 | \r | |
1212 | //\r | |
1213 | // Fixup checksums in the Entry Point Structure\r | |
1214 | //\r | |
1436aea4 | 1215 | EntryPointStructure->IntermediateChecksum = 0;\r |
47f8d0f3 JY |
1216 | EntryPointStructure->EntryPointStructureChecksum = 0;\r |
1217 | \r | |
afe3969c | 1218 | EntryPointStructure->IntermediateChecksum =\r |
1436aea4 | 1219 | CalculateCheckSum8 ((UINT8 *)EntryPointStructure + 0x10, EntryPointStructure->EntryPointLength - 0x10);\r |
afe3969c | 1220 | EntryPointStructure->EntryPointStructureChecksum =\r |
1436aea4 | 1221 | CalculateCheckSum8 ((UINT8 *)EntryPointStructure, EntryPointStructure->EntryPointLength);\r |
310b04e6 | 1222 | \r |
1223 | //\r | |
1224 | // Returns the pointer\r | |
1225 | //\r | |
1226 | *TableEntryPointStructure = EntryPointStructure;\r | |
1227 | \r | |
1228 | return EFI_SUCCESS;\r | |
1229 | }\r | |
1230 | \r | |
310b04e6 | 1231 | /**\r |
e63f3308 EL |
1232 | Assembles SMBIOS 64-bit table from the SMBIOS protocol. Produce Table\r |
1233 | Entry Point and return the pointer to it.\r | |
1234 | \r | |
1235 | @param TableEntryPointStructure On exit, points to the SMBIOS entrypoint structure.\r | |
1236 | \r | |
1237 | @retval EFI_SUCCESS Structure created sucessfully.\r | |
1238 | @retval EFI_OUT_OF_RESOURCES No enough memory.\r | |
1239 | \r | |
1240 | **/\r | |
1241 | EFI_STATUS\r | |
1242 | EFIAPI\r | |
1243 | SmbiosCreate64BitTable (\r | |
1436aea4 | 1244 | OUT VOID **TableEntryPointStructure\r |
e63f3308 EL |
1245 | )\r |
1246 | {\r | |
1247 | UINT8 *BufferPointer;\r | |
1248 | UINTN RecordSize;\r | |
1249 | UINTN NumOfStr;\r | |
1250 | EFI_STATUS Status;\r | |
1251 | EFI_SMBIOS_HANDLE SmbiosHandle;\r | |
1252 | EFI_SMBIOS_PROTOCOL *SmbiosProtocol;\r | |
1253 | EFI_PHYSICAL_ADDRESS PhysicalAddress;\r | |
1254 | EFI_SMBIOS_TABLE_HEADER *SmbiosRecord;\r | |
1255 | EFI_SMBIOS_TABLE_END_STRUCTURE EndStructure;\r | |
1256 | EFI_SMBIOS_ENTRY *CurrentSmbiosEntry;\r | |
d1102dba | 1257 | \r |
1436aea4 MK |
1258 | Status = EFI_SUCCESS;\r |
1259 | BufferPointer = NULL;\r | |
e63f3308 EL |
1260 | \r |
1261 | if (Smbios30EntryPointStructure == NULL) {\r | |
1262 | //\r | |
1263 | // Initialize the Smbios30EntryPointStructure with initial values.\r | |
1264 | // It should be done only once.\r | |
1265 | // Allocate memory at any address.\r | |
1266 | //\r | |
87000d77 | 1267 | DEBUG ((DEBUG_INFO, "SmbiosCreateTable: Initialize 64-bit entry point structure\n"));\r |
1436aea4 MK |
1268 | Smbios30EntryPointStructureData.MajorVersion = mPrivateData.Smbios.MajorVersion;\r |
1269 | Smbios30EntryPointStructureData.MinorVersion = mPrivateData.Smbios.MinorVersion;\r | |
1270 | Smbios30EntryPointStructureData.DocRev = PcdGet8 (PcdSmbiosDocRev);\r | |
1271 | Status = gBS->AllocatePages (\r | |
1272 | AllocateAnyPages,\r | |
1273 | EfiRuntimeServicesData,\r | |
1274 | EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_3_0_ENTRY_POINT)),\r | |
1275 | &PhysicalAddress\r | |
1276 | );\r | |
e63f3308 | 1277 | if (EFI_ERROR (Status)) {\r |
87000d77 | 1278 | DEBUG ((DEBUG_ERROR, "SmbiosCreate64BitTable() could not allocate Smbios30EntryPointStructure\n"));\r |
e63f3308 EL |
1279 | return EFI_OUT_OF_RESOURCES;\r |
1280 | }\r | |
d1102dba | 1281 | \r |
1436aea4 | 1282 | Smbios30EntryPointStructure = (SMBIOS_TABLE_3_0_ENTRY_POINT *)(UINTN)PhysicalAddress;\r |
d1102dba | 1283 | \r |
e63f3308 EL |
1284 | CopyMem (\r |
1285 | Smbios30EntryPointStructure,\r | |
1286 | &Smbios30EntryPointStructureData,\r | |
1287 | sizeof (SMBIOS_TABLE_3_0_ENTRY_POINT)\r | |
1288 | );\r | |
1289 | }\r | |
1290 | \r | |
1291 | //\r | |
1292 | // Get Smbios protocol to traverse SMBIOS records.\r | |
1293 | //\r | |
1436aea4 | 1294 | SmbiosProtocol = &mPrivateData.Smbios;\r |
e63f3308 EL |
1295 | Smbios30EntryPointStructure->TableMaximumSize = 0;\r |
1296 | \r | |
1297 | //\r | |
1298 | // Calculate EPS Table Length\r | |
1299 | //\r | |
1300 | CurrentSmbiosEntry = NULL;\r | |
1301 | do {\r | |
1302 | Status = GetNextSmbiosRecord (SmbiosProtocol, &CurrentSmbiosEntry, &SmbiosRecord);\r | |
d1102dba | 1303 | \r |
e63f3308 | 1304 | if ((Status == EFI_SUCCESS) && (CurrentSmbiosEntry->Smbios64BitTable)) {\r |
1436aea4 | 1305 | GetSmbiosStructureSize (SmbiosProtocol, SmbiosRecord, &RecordSize, &NumOfStr);\r |
e63f3308 EL |
1306 | //\r |
1307 | // Record TableMaximumSize\r | |
1308 | //\r | |
1436aea4 | 1309 | Smbios30EntryPointStructure->TableMaximumSize = (UINT32)(Smbios30EntryPointStructure->TableMaximumSize + RecordSize);\r |
e63f3308 | 1310 | }\r |
1436aea4 | 1311 | } while (!EFI_ERROR (Status));\r |
e63f3308 EL |
1312 | \r |
1313 | //\r | |
1314 | // Create End-Of-Table structure\r | |
1315 | //\r | |
1436aea4 MK |
1316 | GetMaxSmbiosHandle (SmbiosProtocol, &SmbiosHandle);\r |
1317 | EndStructure.Header.Type = SMBIOS_TYPE_END_OF_TABLE;\r | |
1318 | EndStructure.Header.Length = (UINT8)sizeof (EFI_SMBIOS_TABLE_HEADER);\r | |
1319 | EndStructure.Header.Handle = SmbiosHandle;\r | |
1320 | EndStructure.Tailing[0] = 0;\r | |
1321 | EndStructure.Tailing[1] = 0;\r | |
1322 | Smbios30EntryPointStructure->TableMaximumSize = (UINT32)(Smbios30EntryPointStructure->TableMaximumSize + sizeof (EndStructure));\r | |
e63f3308 | 1323 | \r |
16f69227 | 1324 | if (EFI_SIZE_TO_PAGES (Smbios30EntryPointStructure->TableMaximumSize) > mPre64BitAllocatedPages) {\r |
e63f3308 | 1325 | //\r |
d1102dba | 1326 | // If new SMBIOS table size exceeds the previous allocated page,\r |
e63f3308 EL |
1327 | // it is time to re-allocate memory at anywhere.\r |
1328 | //\r | |
1436aea4 MK |
1329 | DEBUG ((\r |
1330 | DEBUG_INFO,\r | |
1331 | "%a() re-allocate SMBIOS 64-bit table\n",\r | |
1332 | __FUNCTION__\r | |
1333 | ));\r | |
e63f3308 EL |
1334 | if (Smbios30EntryPointStructure->TableAddress != 0) {\r |
1335 | //\r | |
1336 | // Free the previous allocated page\r | |
d1102dba | 1337 | //\r |
e63f3308 | 1338 | FreePages (\r |
1436aea4 MK |
1339 | (VOID *)(UINTN)Smbios30EntryPointStructure->TableAddress,\r |
1340 | mPre64BitAllocatedPages\r | |
1341 | );\r | |
e63f3308 | 1342 | Smbios30EntryPointStructure->TableAddress = 0;\r |
1436aea4 | 1343 | mPre64BitAllocatedPages = 0;\r |
e63f3308 EL |
1344 | }\r |
1345 | \r | |
1346 | Status = gBS->AllocatePages (\r | |
1347 | AllocateAnyPages,\r | |
1348 | EfiRuntimeServicesData,\r | |
1349 | EFI_SIZE_TO_PAGES (Smbios30EntryPointStructure->TableMaximumSize),\r | |
1350 | &PhysicalAddress\r | |
1351 | );\r | |
1352 | if (EFI_ERROR (Status)) {\r | |
87000d77 | 1353 | DEBUG ((DEBUG_ERROR, "SmbiosCreateTable() could not allocate SMBIOS 64-bit table\n"));\r |
e63f3308 EL |
1354 | Smbios30EntryPointStructure->TableAddress = 0;\r |
1355 | return EFI_OUT_OF_RESOURCES;\r | |
1356 | } else {\r | |
1357 | Smbios30EntryPointStructure->TableAddress = PhysicalAddress;\r | |
1436aea4 | 1358 | mPre64BitAllocatedPages = EFI_SIZE_TO_PAGES (Smbios30EntryPointStructure->TableMaximumSize);\r |
e63f3308 EL |
1359 | }\r |
1360 | }\r | |
1361 | \r | |
1362 | //\r | |
1363 | // Assemble the tables\r | |
1364 | //\r | |
1365 | ASSERT (Smbios30EntryPointStructure->TableAddress != 0);\r | |
1436aea4 | 1366 | BufferPointer = (UINT8 *)(UINTN)Smbios30EntryPointStructure->TableAddress;\r |
e63f3308 EL |
1367 | CurrentSmbiosEntry = NULL;\r |
1368 | do {\r | |
1369 | Status = GetNextSmbiosRecord (SmbiosProtocol, &CurrentSmbiosEntry, &SmbiosRecord);\r | |
1370 | \r | |
1371 | if ((Status == EFI_SUCCESS) && (CurrentSmbiosEntry->Smbios64BitTable)) {\r | |
1372 | //\r | |
1373 | // This record can be added to 64-bit table\r | |
1374 | //\r | |
1436aea4 | 1375 | GetSmbiosStructureSize (SmbiosProtocol, SmbiosRecord, &RecordSize, &NumOfStr);\r |
e63f3308 EL |
1376 | CopyMem (BufferPointer, SmbiosRecord, RecordSize);\r |
1377 | BufferPointer = BufferPointer + RecordSize;\r | |
1378 | }\r | |
1436aea4 | 1379 | } while (!EFI_ERROR (Status));\r |
e63f3308 EL |
1380 | \r |
1381 | //\r | |
1382 | // Assemble End-Of-Table structure\r | |
1383 | //\r | |
1384 | CopyMem (BufferPointer, &EndStructure, sizeof (EndStructure));\r | |
1385 | \r | |
1386 | //\r | |
1387 | // Fixup checksums in the Entry Point Structure\r | |
1388 | //\r | |
1389 | Smbios30EntryPointStructure->EntryPointStructureChecksum = 0;\r | |
1390 | Smbios30EntryPointStructure->EntryPointStructureChecksum =\r | |
1436aea4 | 1391 | CalculateCheckSum8 ((UINT8 *)Smbios30EntryPointStructure, Smbios30EntryPointStructure->EntryPointLength);\r |
e63f3308 EL |
1392 | \r |
1393 | //\r | |
1394 | // Returns the pointer\r | |
1395 | //\r | |
1396 | *TableEntryPointStructure = Smbios30EntryPointStructure;\r | |
1397 | \r | |
1398 | return EFI_SUCCESS;\r | |
1399 | }\r | |
1400 | \r | |
1401 | /**\r | |
1402 | Create Smbios Table and installs the Smbios Table to the System Table.\r | |
d1102dba | 1403 | \r |
e63f3308 EL |
1404 | @param Smbios32BitTable The flag to update 32-bit table.\r |
1405 | @param Smbios64BitTable The flag to update 64-bit table.\r | |
1406 | \r | |
310b04e6 | 1407 | **/\r |
1408 | VOID\r | |
1409 | EFIAPI\r | |
1410 | SmbiosTableConstruction (\r | |
1436aea4 MK |
1411 | BOOLEAN Smbios32BitTable,\r |
1412 | BOOLEAN Smbios64BitTable\r | |
310b04e6 | 1413 | )\r |
1414 | {\r | |
1415 | UINT8 *Eps;\r | |
e63f3308 | 1416 | UINT8 *Eps64Bit;\r |
310b04e6 | 1417 | EFI_STATUS Status;\r |
1418 | \r | |
e63f3308 | 1419 | if (Smbios32BitTable) {\r |
1436aea4 | 1420 | Status = SmbiosCreateTable ((VOID **)&Eps);\r |
e63f3308 EL |
1421 | if (!EFI_ERROR (Status)) {\r |
1422 | gBS->InstallConfigurationTable (&gEfiSmbiosTableGuid, Eps);\r | |
1423 | }\r | |
1424 | }\r | |
1425 | \r | |
1426 | if (Smbios64BitTable) {\r | |
1436aea4 | 1427 | Status = SmbiosCreate64BitTable ((VOID **)&Eps64Bit);\r |
e63f3308 EL |
1428 | if (!EFI_ERROR (Status)) {\r |
1429 | gBS->InstallConfigurationTable (&gEfiSmbios3TableGuid, Eps64Bit);\r | |
1430 | }\r | |
310b04e6 | 1431 | }\r |
1432 | }\r | |
1433 | \r | |
70e8c9c3 ZL |
1434 | /**\r |
1435 | Validates a SMBIOS 2.0 table entry point.\r | |
1436 | \r | |
1437 | @param TableEntry The SmBios table entry to validate.\r | |
1438 | @param TableAddress On exit, point to the smbios table addres.\r | |
1439 | @param TableMaximumSize On exit, point to the maximum size of the table.\r | |
1440 | \r | |
1441 | @retval TRUE SMBIOS table entry point is valid.\r | |
1442 | @retval FALSE SMBIOS table entry point is malformed.\r | |
1443 | \r | |
1444 | **/\r | |
1445 | STATIC\r | |
1446 | BOOLEAN\r | |
1447 | IsValidSmbios20Table (\r | |
1436aea4 MK |
1448 | IN VOID *TableEntry,\r |
1449 | OUT VOID **TableAddress,\r | |
1450 | OUT UINTN *TableMaximumSize\r | |
70e8c9c3 ZL |
1451 | )\r |
1452 | {\r | |
1436aea4 MK |
1453 | UINT8 Checksum;\r |
1454 | SMBIOS_TABLE_ENTRY_POINT *SmbiosTable;\r | |
1455 | \r | |
1456 | SmbiosTable = (SMBIOS_TABLE_ENTRY_POINT *)TableEntry;\r | |
70e8c9c3 ZL |
1457 | \r |
1458 | if (CompareMem (SmbiosTable->AnchorString, "_SM_", 4) != 0) {\r | |
1459 | return FALSE;\r | |
1460 | }\r | |
1461 | \r | |
1462 | if (CompareMem (SmbiosTable->IntermediateAnchorString, "_DMI_", 5) != 0) {\r | |
1463 | return FALSE;\r | |
1464 | }\r | |
1465 | \r | |
1466 | //\r | |
1467 | // The actual value of the EntryPointLength should be 1Fh.\r | |
1468 | // However, it was incorrectly stated in version 2.1 of smbios specification.\r | |
1469 | // Therefore, 0x1F and 0x1E are both accepted.\r | |
1470 | //\r | |
1436aea4 | 1471 | if ((SmbiosTable->EntryPointLength != 0x1E) && (SmbiosTable->EntryPointLength != sizeof (SMBIOS_TABLE_ENTRY_POINT))) {\r |
70e8c9c3 ZL |
1472 | return FALSE;\r |
1473 | }\r | |
1474 | \r | |
1475 | //\r | |
1476 | // MajorVersion should not be less than 2.\r | |
1477 | //\r | |
1478 | if (SmbiosTable->MajorVersion < 2) {\r | |
1479 | return FALSE;\r | |
1480 | }\r | |
1481 | \r | |
1482 | //\r | |
1483 | // The whole struct check sum should be zero\r | |
1484 | //\r | |
1485 | Checksum = CalculateSum8 (\r | |
1436aea4 | 1486 | (UINT8 *)SmbiosTable,\r |
70e8c9c3 ZL |
1487 | SmbiosTable->EntryPointLength\r |
1488 | );\r | |
1489 | if (Checksum != 0) {\r | |
1490 | return FALSE;\r | |
1491 | }\r | |
1492 | \r | |
1493 | //\r | |
1494 | // The Intermediate Entry Point Structure check sum should be zero.\r | |
1495 | //\r | |
1496 | Checksum = CalculateSum8 (\r | |
1436aea4 | 1497 | (UINT8 *)SmbiosTable + OFFSET_OF (SMBIOS_TABLE_ENTRY_POINT, IntermediateAnchorString),\r |
70e8c9c3 ZL |
1498 | SmbiosTable->EntryPointLength - OFFSET_OF (SMBIOS_TABLE_ENTRY_POINT, IntermediateAnchorString)\r |
1499 | );\r | |
1500 | if (Checksum != 0) {\r | |
1501 | return FALSE;\r | |
1502 | }\r | |
1503 | \r | |
1436aea4 | 1504 | *TableAddress = (VOID *)(UINTN)SmbiosTable->TableAddress;\r |
70e8c9c3 ZL |
1505 | *TableMaximumSize = SmbiosTable->TableLength;\r |
1506 | return TRUE;\r | |
1507 | }\r | |
1508 | \r | |
1509 | /**\r | |
1510 | Validates a SMBIOS 3.0 table entry point.\r | |
1511 | \r | |
1512 | @param TableEntry The SmBios table entry to validate.\r | |
1513 | @param TableAddress On exit, point to the smbios table addres.\r | |
1514 | @param TableMaximumSize On exit, point to the maximum size of the table.\r | |
1515 | \r | |
1516 | @retval TRUE SMBIOS table entry point is valid.\r | |
1517 | @retval FALSE SMBIOS table entry point is malformed.\r | |
1518 | \r | |
1519 | **/\r | |
1520 | STATIC\r | |
1521 | BOOLEAN\r | |
1522 | IsValidSmbios30Table (\r | |
1436aea4 MK |
1523 | IN VOID *TableEntry,\r |
1524 | OUT VOID **TableAddress,\r | |
1525 | OUT UINTN *TableMaximumSize\r | |
70e8c9c3 ZL |
1526 | )\r |
1527 | {\r | |
1436aea4 MK |
1528 | UINT8 Checksum;\r |
1529 | SMBIOS_TABLE_3_0_ENTRY_POINT *SmbiosTable;\r | |
1530 | \r | |
1531 | SmbiosTable = (SMBIOS_TABLE_3_0_ENTRY_POINT *)TableEntry;\r | |
70e8c9c3 ZL |
1532 | \r |
1533 | if (CompareMem (SmbiosTable->AnchorString, "_SM3_", 5) != 0) {\r | |
1534 | return FALSE;\r | |
1535 | }\r | |
1436aea4 | 1536 | \r |
70e8c9c3 ZL |
1537 | if (SmbiosTable->EntryPointLength < sizeof (SMBIOS_TABLE_3_0_ENTRY_POINT)) {\r |
1538 | return FALSE;\r | |
1539 | }\r | |
1436aea4 | 1540 | \r |
70e8c9c3 ZL |
1541 | if (SmbiosTable->MajorVersion < 3) {\r |
1542 | return FALSE;\r | |
1543 | }\r | |
1544 | \r | |
1545 | //\r | |
1546 | // The whole struct check sum should be zero\r | |
1547 | //\r | |
1548 | Checksum = CalculateSum8 (\r | |
1436aea4 | 1549 | (UINT8 *)SmbiosTable,\r |
70e8c9c3 ZL |
1550 | SmbiosTable->EntryPointLength\r |
1551 | );\r | |
1552 | if (Checksum != 0) {\r | |
1553 | return FALSE;\r | |
1554 | }\r | |
1555 | \r | |
1436aea4 | 1556 | *TableAddress = (VOID *)(UINTN)SmbiosTable->TableAddress;\r |
70e8c9c3 ZL |
1557 | *TableMaximumSize = SmbiosTable->TableMaximumSize;\r |
1558 | return TRUE;\r | |
1559 | }\r | |
1560 | \r | |
1561 | /**\r | |
1562 | Parse an existing SMBIOS table and insert it using SmbiosAdd.\r | |
1563 | \r | |
1564 | @param ImageHandle The EFI_HANDLE to this driver.\r | |
1565 | @param Smbios The SMBIOS table to parse.\r | |
1566 | @param Length The length of the SMBIOS table.\r | |
1567 | \r | |
1568 | @retval EFI_SUCCESS SMBIOS table was parsed and installed.\r | |
1569 | @retval EFI_OUT_OF_RESOURCES Record was not added due to lack of system resources.\r | |
1570 | @retval EFI_INVALID_PARAMETER Smbios is not a correct smbios table\r | |
1571 | \r | |
1572 | **/\r | |
1573 | STATIC\r | |
1574 | EFI_STATUS\r | |
1575 | ParseAndAddExistingSmbiosTable (\r | |
1436aea4 MK |
1576 | IN EFI_HANDLE ImageHandle,\r |
1577 | IN SMBIOS_STRUCTURE_POINTER Smbios,\r | |
1578 | IN UINTN Length\r | |
70e8c9c3 ZL |
1579 | )\r |
1580 | {\r | |
1436aea4 MK |
1581 | EFI_STATUS Status;\r |
1582 | CHAR8 *String;\r | |
1583 | EFI_SMBIOS_HANDLE SmbiosHandle;\r | |
1584 | SMBIOS_STRUCTURE_POINTER SmbiosEnd;\r | |
70e8c9c3 ZL |
1585 | \r |
1586 | SmbiosEnd.Raw = Smbios.Raw + Length;\r | |
1587 | \r | |
1436aea4 | 1588 | if ((Smbios.Raw >= SmbiosEnd.Raw) || (Smbios.Raw == NULL)) {\r |
70e8c9c3 ZL |
1589 | return EFI_INVALID_PARAMETER;\r |
1590 | }\r | |
1591 | \r | |
1592 | do {\r | |
1593 | //\r | |
1594 | // Make sure not to access memory beyond SmbiosEnd\r | |
1595 | //\r | |
1436aea4 MK |
1596 | if ((Smbios.Raw + sizeof (SMBIOS_STRUCTURE) > SmbiosEnd.Raw) ||\r |
1597 | (Smbios.Raw + sizeof (SMBIOS_STRUCTURE) < Smbios.Raw))\r | |
1598 | {\r | |
70e8c9c3 ZL |
1599 | return EFI_INVALID_PARAMETER;\r |
1600 | }\r | |
1436aea4 | 1601 | \r |
70e8c9c3 ZL |
1602 | //\r |
1603 | // Check for end marker\r | |
1604 | //\r | |
1605 | if (Smbios.Hdr->Type == SMBIOS_TYPE_END_OF_TABLE) {\r | |
1606 | break;\r | |
1607 | }\r | |
1436aea4 | 1608 | \r |
70e8c9c3 ZL |
1609 | //\r |
1610 | // Make sure not to access memory beyond SmbiosEnd\r | |
1611 | // Each structure shall be terminated by a double-null (0000h).\r | |
1612 | //\r | |
1436aea4 MK |
1613 | if ((Smbios.Raw + Smbios.Hdr->Length + 2 * sizeof (UINT8) > SmbiosEnd.Raw) ||\r |
1614 | (Smbios.Raw + Smbios.Hdr->Length + 2 * sizeof (UINT8) < Smbios.Raw))\r | |
1615 | {\r | |
70e8c9c3 ZL |
1616 | return EFI_INVALID_PARAMETER;\r |
1617 | }\r | |
1436aea4 | 1618 | \r |
70e8c9c3 ZL |
1619 | //\r |
1620 | // Install the table\r | |
1621 | //\r | |
1622 | SmbiosHandle = Smbios.Hdr->Handle;\r | |
1436aea4 MK |
1623 | Status = SmbiosAdd (\r |
1624 | &mPrivateData.Smbios,\r | |
1625 | ImageHandle,\r | |
1626 | &SmbiosHandle,\r | |
1627 | Smbios.Hdr\r | |
1628 | );\r | |
70e8c9c3 ZL |
1629 | \r |
1630 | ASSERT_EFI_ERROR (Status);\r | |
1631 | if (EFI_ERROR (Status)) {\r | |
1632 | return Status;\r | |
1633 | }\r | |
1436aea4 | 1634 | \r |
70e8c9c3 ZL |
1635 | //\r |
1636 | // Go to the next SMBIOS structure. Each SMBIOS structure may include 2 parts:\r | |
1637 | // 1. Formatted section; 2. Unformatted string section. So, 2 steps are needed\r | |
1638 | // to skip one SMBIOS structure.\r | |
1639 | //\r | |
1640 | \r | |
1641 | //\r | |
1642 | // Step 1: Skip over formatted section.\r | |
1643 | //\r | |
1436aea4 | 1644 | String = (CHAR8 *)(Smbios.Raw + Smbios.Hdr->Length);\r |
70e8c9c3 ZL |
1645 | \r |
1646 | //\r | |
1647 | // Step 2: Skip over unformatted string section.\r | |
1648 | //\r | |
1649 | do {\r | |
1650 | //\r | |
1651 | // Each string is terminated with a NULL(00h) BYTE and the sets of strings\r | |
1652 | // is terminated with an additional NULL(00h) BYTE.\r | |
1653 | //\r | |
1654 | for ( ; *String != 0; String++) {\r | |
1436aea4 | 1655 | if ((UINTN)String >= (UINTN)SmbiosEnd.Raw - sizeof (UINT8)) {\r |
70e8c9c3 ZL |
1656 | return EFI_INVALID_PARAMETER;\r |
1657 | }\r | |
1658 | }\r | |
1659 | \r | |
1436aea4 | 1660 | if (*(UINT8 *)++String == 0) {\r |
70e8c9c3 ZL |
1661 | //\r |
1662 | // Pointer to the next SMBIOS structure.\r | |
1663 | //\r | |
1436aea4 | 1664 | Smbios.Raw = (UINT8 *)++String;\r |
70e8c9c3 ZL |
1665 | break;\r |
1666 | }\r | |
1667 | } while (TRUE);\r | |
1668 | } while (Smbios.Raw < SmbiosEnd.Raw);\r | |
1669 | \r | |
1670 | return EFI_SUCCESS;\r | |
1671 | }\r | |
1672 | \r | |
1673 | /**\r | |
1674 | Retrieve SMBIOS from Hob.\r | |
1675 | @param ImageHandle Module's image handle\r | |
1676 | \r | |
1677 | @retval EFI_SUCCESS Smbios from Hob is installed.\r | |
1678 | @return EFI_NOT_FOUND Not found Smbios from Hob.\r | |
1679 | @retval Other No Smbios from Hob is installed.\r | |
1680 | \r | |
1681 | **/\r | |
1682 | EFI_STATUS\r | |
1683 | RetrieveSmbiosFromHob (\r | |
1436aea4 | 1684 | IN EFI_HANDLE ImageHandle\r |
70e8c9c3 ZL |
1685 | )\r |
1686 | {\r | |
1436aea4 MK |
1687 | EFI_STATUS Status;\r |
1688 | UINTN Index;\r | |
1689 | SMBIOS_STRUCTURE_POINTER Smbios;\r | |
1690 | EFI_HOB_GUID_TYPE *GuidHob;\r | |
1691 | UNIVERSAL_PAYLOAD_SMBIOS_TABLE *SmBiosTableAdress;\r | |
1692 | UNIVERSAL_PAYLOAD_GENERIC_HEADER *GenericHeader;\r | |
1693 | VOID *TableAddress;\r | |
1694 | UINTN TableMaximumSize;\r | |
70e8c9c3 ZL |
1695 | \r |
1696 | Status = EFI_NOT_FOUND;\r | |
1697 | \r | |
1698 | for (Index = 0; Index < ARRAY_SIZE (mIsSmbiosTableValid); Index++) {\r | |
1699 | GuidHob = GetFirstGuidHob (mIsSmbiosTableValid[Index].Guid);\r | |
1700 | if (GuidHob == NULL) {\r | |
1701 | continue;\r | |
1702 | }\r | |
1436aea4 MK |
1703 | \r |
1704 | GenericHeader = (UNIVERSAL_PAYLOAD_GENERIC_HEADER *)GET_GUID_HOB_DATA (GuidHob);\r | |
70e8c9c3 ZL |
1705 | if ((sizeof (UNIVERSAL_PAYLOAD_GENERIC_HEADER) <= GET_GUID_HOB_DATA_SIZE (GuidHob)) && (GenericHeader->Length <= GET_GUID_HOB_DATA_SIZE (GuidHob))) {\r |
1706 | if (GenericHeader->Revision == UNIVERSAL_PAYLOAD_SMBIOS_TABLE_REVISION) {\r | |
1707 | //\r | |
1708 | // UNIVERSAL_PAYLOAD_SMBIOS_TABLE structure is used when Revision equals to UNIVERSAL_PAYLOAD_SMBIOS_TABLE_REVISION\r | |
1709 | //\r | |
1436aea4 | 1710 | SmBiosTableAdress = (UNIVERSAL_PAYLOAD_SMBIOS_TABLE *)GET_GUID_HOB_DATA (GuidHob);\r |
70e8c9c3 | 1711 | if (GenericHeader->Length >= UNIVERSAL_PAYLOAD_SIZEOF_THROUGH_FIELD (UNIVERSAL_PAYLOAD_SMBIOS_TABLE, SmBiosEntryPoint)) {\r |
1436aea4 | 1712 | if (mIsSmbiosTableValid[Index].IsValid ((VOID *)(UINTN)SmBiosTableAdress->SmBiosEntryPoint, &TableAddress, &TableMaximumSize)) {\r |
70e8c9c3 | 1713 | Smbios.Raw = TableAddress;\r |
1436aea4 | 1714 | Status = ParseAndAddExistingSmbiosTable (ImageHandle, Smbios, TableMaximumSize);\r |
70e8c9c3 ZL |
1715 | if (EFI_ERROR (Status)) {\r |
1716 | DEBUG ((DEBUG_ERROR, "RetrieveSmbiosFromHob: Failed to parse preinstalled tables from Guid Hob\n"));\r | |
1717 | Status = EFI_UNSUPPORTED;\r | |
1718 | } else {\r | |
1719 | return EFI_SUCCESS;\r | |
1720 | }\r | |
1721 | }\r | |
1722 | }\r | |
1723 | }\r | |
1724 | }\r | |
1725 | }\r | |
1436aea4 | 1726 | \r |
70e8c9c3 ZL |
1727 | return Status;\r |
1728 | }\r | |
1729 | \r | |
310b04e6 | 1730 | /**\r |
1731 | \r | |
d1102dba | 1732 | Driver to produce Smbios protocol and pre-allocate 1 page for the final SMBIOS table.\r |
310b04e6 | 1733 | \r |
1734 | @param ImageHandle Module's image handle\r | |
1735 | @param SystemTable Pointer of EFI_SYSTEM_TABLE\r | |
1736 | \r | |
1737 | @retval EFI_SUCCESS Smbios protocol installed\r | |
1738 | @retval Other No protocol installed, unload driver.\r | |
1739 | \r | |
1740 | **/\r | |
1741 | EFI_STATUS\r | |
1742 | EFIAPI\r | |
1743 | SmbiosDriverEntryPoint (\r | |
1436aea4 MK |
1744 | IN EFI_HANDLE ImageHandle,\r |
1745 | IN EFI_SYSTEM_TABLE *SystemTable\r | |
310b04e6 | 1746 | )\r |
1747 | {\r | |
1436aea4 | 1748 | EFI_STATUS Status;\r |
310b04e6 | 1749 | \r |
1436aea4 MK |
1750 | mPrivateData.Signature = SMBIOS_INSTANCE_SIGNATURE;\r |
1751 | mPrivateData.Smbios.Add = SmbiosAdd;\r | |
1752 | mPrivateData.Smbios.UpdateString = SmbiosUpdateString;\r | |
1753 | mPrivateData.Smbios.Remove = SmbiosRemove;\r | |
1754 | mPrivateData.Smbios.GetNext = SmbiosGetNext;\r | |
1755 | mPrivateData.Smbios.MajorVersion = (UINT8)(PcdGet16 (PcdSmbiosVersion) >> 8);\r | |
1756 | mPrivateData.Smbios.MinorVersion = (UINT8)(PcdGet16 (PcdSmbiosVersion) & 0x00ff);\r | |
310b04e6 | 1757 | \r |
1758 | InitializeListHead (&mPrivateData.DataListHead);\r | |
1759 | InitializeListHead (&mPrivateData.AllocatedHandleListHead);\r | |
1760 | EfiInitializeLock (&mPrivateData.DataLock, TPL_NOTIFY);\r | |
d1102dba | 1761 | \r |
310b04e6 | 1762 | //\r |
1763 | // Make a new handle and install the protocol\r | |
1764 | //\r | |
1765 | mPrivateData.Handle = NULL;\r | |
1436aea4 MK |
1766 | Status = gBS->InstallProtocolInterface (\r |
1767 | &mPrivateData.Handle,\r | |
1768 | &gEfiSmbiosProtocolGuid,\r | |
1769 | EFI_NATIVE_INTERFACE,\r | |
1770 | &mPrivateData.Smbios\r | |
1771 | );\r | |
310b04e6 | 1772 | \r |
70e8c9c3 | 1773 | RetrieveSmbiosFromHob (ImageHandle);\r |
310b04e6 | 1774 | return Status;\r |
1775 | }\r |