]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c
Enhance SmbiosDxe driver:
[mirror_edk2.git] / MdeModulePkg / Universal / SmbiosDxe / SmbiosDxe.c
CommitLineData
310b04e6 1/** @file\r
2 This code produces the Smbios protocol. It also responsible for constructing \r
3 SMBIOS table into system table.\r
4 \r
2d97e71f 5Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 6This program and the accompanying materials \r
310b04e6 7are licensed and made available under the terms and conditions of the BSD License \r
8which accompanies this distribution. The full text of the license may be found at \r
9http://opensource.org/licenses/bsd-license.php \r
10 \r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
13\r
14**/\r
15\r
16#include "SmbiosDxe.h"\r
17\r
18//\r
19// Module Global:\r
20// Since this driver will only ever produce one instance of the\r
21// protocol you are not required to dynamically allocate the PrivateData.\r
22//\r
23SMBIOS_INSTANCE mPrivateData;\r
24\r
4233bf70
SZ
25UINTN mPreAllocatedPages = 0;\r
26\r
310b04e6 27//\r
28// Chassis for SMBIOS entry point structure that is to be installed into EFI system config table.\r
29//\r
30SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure = NULL;\r
31SMBIOS_TABLE_ENTRY_POINT EntryPointStructureData = {\r
32 //\r
33 // AnchorString\r
34 //\r
35 {\r
36 0x5f,\r
37 0x53,\r
38 0x4d,\r
39 0x5f\r
40 },\r
41 //\r
42 // EntryPointStructureChecksum,TO BE FILLED\r
43 //\r
44 0,\r
45 //\r
46 // EntryPointStructure Length\r
47 //\r
48 0x1f,\r
49 //\r
9f7d5b46 50 // MajorVersion\r
310b04e6 51 //\r
9f7d5b46 52 (UINT8) (FixedPcdGet16 (PcdSmbiosVersion) >> 8),\r
310b04e6 53 //\r
9f7d5b46 54 // MinorVersion\r
310b04e6 55 //\r
9f7d5b46 56 (UINT8) (FixedPcdGet16 (PcdSmbiosVersion) & 0x00ff),\r
310b04e6 57 //\r
58 // MaxStructureSize, TO BE FILLED\r
59 //\r
60 0,\r
61 //\r
62 // EntryPointRevision\r
63 //\r
64 0,\r
65 //\r
66 // FormattedArea\r
67 //\r
68 {\r
69 0,\r
70 0,\r
71 0,\r
72 0,\r
73 0\r
74 },\r
75 //\r
76 // IntermediateAnchorString\r
77 //\r
78 {\r
79 0x5f,\r
80 0x44,\r
81 0x4d,\r
82 0x49,\r
83 0x5f\r
84 },\r
85 //\r
86 // IntermediateChecksum, TO BE FILLED\r
87 //\r
88 0,\r
89 //\r
90 // StructureTableLength, TO BE FILLED\r
91 //\r
92 0,\r
93 //\r
94 // StructureTableAddress, TO BE FILLED\r
95 //\r
96 0,\r
97 //\r
98 // NumberOfSmbiosStructures, TO BE FILLED\r
99 //\r
100 0,\r
101 //\r
102 // SmbiosBcdRevision\r
103 //\r
104 0 \r
105};\r
106\r
107\r
c7ce5169 108\r
310b04e6 109/**\r
110\r
0ddd8553 111 Get the full size of SMBIOS structure including optional strings that follow the formatted structure.\r
310b04e6 112\r
afe3969c 113 @param This The EFI_SMBIOS_PROTOCOL instance.\r
0ddd8553 114 @param Head Pointer to the beginning of SMBIOS structure.\r
310b04e6 115 @param Size The returned size.\r
116 @param NumberOfStrings The returned number of optional strings that follow the formatted structure.\r
117\r
118 @retval EFI_SUCCESS Size retured in Size.\r
0ddd8553 119 @retval EFI_INVALID_PARAMETER Input SMBIOS structure mal-formed or Size is NULL.\r
310b04e6 120 \r
121**/\r
122EFI_STATUS\r
123EFIAPI\r
124GetSmbiosStructureSize (\r
afe3969c 125 IN CONST EFI_SMBIOS_PROTOCOL *This,\r
310b04e6 126 IN EFI_SMBIOS_TABLE_HEADER *Head,\r
127 OUT UINTN *Size,\r
128 OUT UINTN *NumberOfStrings\r
129 )\r
130{\r
131 UINTN FullSize;\r
2d97e71f 132 UINTN StrLen;\r
4233bf70 133 UINTN MaxLen;\r
310b04e6 134 INT8* CharInStr;\r
135 \r
136 if (Size == NULL || NumberOfStrings == NULL) {\r
137 return EFI_INVALID_PARAMETER;\r
138 }\r
139\r
140 FullSize = Head->Length;\r
141 CharInStr = (INT8*)Head + Head->Length;\r
142 *Size = FullSize;\r
143 *NumberOfStrings = 0;\r
144 StrLen = 0;\r
145 //\r
146 // look for the two consecutive zeros, check the string limit by the way.\r
147 //\r
148 while (*CharInStr != 0 || *(CharInStr+1) != 0) { \r
149 if (*CharInStr == 0) {\r
310b04e6 150 *Size += 1;\r
151 CharInStr++;\r
152 }\r
153\r
afe3969c 154 if (This->MajorVersion < 2 || (This->MajorVersion == 2 && This->MinorVersion < 7)){\r
4233bf70 155 MaxLen = SMBIOS_STRING_MAX_LENGTH;\r
afe3969c
SZ
156 } else {\r
157 //\r
4233bf70
SZ
158 // Reference SMBIOS 2.7, chapter 6.1.3, it will have no limit on the length of each individual text string.\r
159 // However, the length of the entire structure table (including all strings) must be reported\r
160 // in the Structure Table Length field of the SMBIOS Structure Table Entry Point,\r
161 // which is a WORD field limited to 65,535 bytes.\r
afe3969c 162 //\r
4233bf70
SZ
163 MaxLen = SMBIOS_TABLE_MAX_LENGTH;\r
164 }\r
165\r
166 for (StrLen = 0 ; StrLen < MaxLen; StrLen++) {\r
167 if (*(CharInStr+StrLen) == 0) {\r
168 break;\r
afe3969c 169 }\r
310b04e6 170 }\r
afe3969c 171\r
4233bf70
SZ
172 if (StrLen == MaxLen) {\r
173 return EFI_INVALID_PARAMETER;\r
174 }\r
175\r
310b04e6 176 //\r
177 // forward the pointer\r
178 //\r
179 CharInStr += StrLen;\r
180 *Size += StrLen;\r
310b04e6 181 *NumberOfStrings += 1;\r
182 }\r
f8ee20c9 183\r
310b04e6 184 //\r
185 // count ending two zeros.\r
186 //\r
187 *Size += 2;\r
afe3969c 188 return EFI_SUCCESS;\r
310b04e6 189}\r
190\r
191/**\r
192\r
193 Determin whether an SmbiosHandle has already in use.\r
194\r
0ddd8553 195 @param Head Pointer to the beginning of SMBIOS structure.\r
310b04e6 196 @param Handle A unique handle will be assigned to the SMBIOS record.\r
197\r
198 @retval TRUE Smbios handle already in use.\r
199 @retval FALSE Smbios handle is NOT used.\r
200 \r
201**/\r
202BOOLEAN\r
203EFIAPI\r
204CheckSmbiosHandleExistance (\r
205 IN LIST_ENTRY *Head,\r
206 IN EFI_SMBIOS_HANDLE Handle\r
207 )\r
208{\r
209 LIST_ENTRY *Link;\r
210 SMBIOS_HANDLE_ENTRY *HandleEntry;\r
211 \r
212 for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r
213 HandleEntry = SMBIOS_HANDLE_ENTRY_FROM_LINK(Link);\r
214 if (HandleEntry->SmbiosHandle == Handle) {\r
215 return TRUE;\r
216 }\r
217 }\r
218\r
219 return FALSE;\r
220}\r
221\r
222/**\r
223\r
224 Get the max SmbiosHandle that could be use.\r
225\r
226 @param This The EFI_SMBIOS_PROTOCOL instance.\r
227 @param MaxHandle The max handle that could be assigned to the SMBIOS record.\r
228\r
229**/\r
230VOID\r
231EFIAPI\r
232GetMaxSmbiosHandle (\r
233 IN CONST EFI_SMBIOS_PROTOCOL *This,\r
234 IN OUT EFI_SMBIOS_HANDLE *MaxHandle\r
235 ) \r
236{\r
237 if (This->MajorVersion == 2 && This->MinorVersion == 0) {\r
238 *MaxHandle = 0xFFFE;\r
239 } else {\r
240 *MaxHandle = 0xFEFF;\r
241 }\r
242}\r
243\r
244/**\r
245\r
246 Get an SmbiosHandle that could use.\r
247\r
248 @param This The EFI_SMBIOS_PROTOCOL instance.\r
249 @param SmbiosHandle A unique handle will be assigned to the SMBIOS record.\r
250\r
251 @retval EFI_SUCCESS Smbios handle got.\r
252 @retval EFI_OUT_OF_RESOURCES Smbios handle is NOT available.\r
253 \r
254**/\r
255EFI_STATUS\r
256EFIAPI\r
257GetAvailableSmbiosHandle (\r
258 IN CONST EFI_SMBIOS_PROTOCOL *This,\r
259 IN OUT EFI_SMBIOS_HANDLE *Handle\r
260 )\r
261{\r
262 LIST_ENTRY *Head;\r
263 SMBIOS_INSTANCE *Private;\r
264 EFI_SMBIOS_HANDLE MaxSmbiosHandle;\r
265 EFI_SMBIOS_HANDLE AvailableHandle;\r
266\r
267 GetMaxSmbiosHandle(This, &MaxSmbiosHandle);\r
268\r
269 Private = SMBIOS_INSTANCE_FROM_THIS (This);\r
270 Head = &Private->AllocatedHandleListHead;\r
4659816a 271 for (AvailableHandle = 0; AvailableHandle < MaxSmbiosHandle; AvailableHandle++) {\r
310b04e6 272 if (!CheckSmbiosHandleExistance(Head, AvailableHandle)) {\r
273 *Handle = AvailableHandle;\r
274 return EFI_SUCCESS;\r
275 }\r
276 }\r
277\r
278 return EFI_OUT_OF_RESOURCES;\r
279}\r
280\r
281\r
282/**\r
283 Add an SMBIOS record.\r
284\r
285 @param This The EFI_SMBIOS_PROTOCOL instance.\r
286 @param ProducerHandle The handle of the controller or driver associated with the SMBIOS information. NULL\r
287 means no handle.\r
4659816a
SZ
288 @param SmbiosHandle On entry, the handle of the SMBIOS record to add. If FFFEh, then a unique handle\r
289 will be assigned to the SMBIOS record. If the SMBIOS handle is already in use,\r
310b04e6 290 EFI_ALREADY_STARTED is returned and the SMBIOS record is not updated.\r
291 @param Record The data for the fixed portion of the SMBIOS record. The format of the record is\r
292 determined by EFI_SMBIOS_TABLE_HEADER.Type. The size of the formatted area is defined \r
293 by EFI_SMBIOS_TABLE_HEADER.Length and either followed by a double-null (0x0000) or \r
294 a set of null terminated strings and a null.\r
295\r
296 @retval EFI_SUCCESS Record was added.\r
297 @retval EFI_OUT_OF_RESOURCES Record was not added due to lack of system resources.\r
298 @retval EFI_ALREADY_STARTED The SmbiosHandle passed in was already in use.\r
299\r
300**/\r
301EFI_STATUS\r
302EFIAPI\r
303SmbiosAdd (\r
304 IN CONST EFI_SMBIOS_PROTOCOL *This,\r
305 IN EFI_HANDLE ProducerHandle, OPTIONAL\r
306 IN OUT EFI_SMBIOS_HANDLE *SmbiosHandle,\r
307 IN EFI_SMBIOS_TABLE_HEADER *Record\r
308 )\r
309{\r
310 VOID *Raw;\r
311 UINTN TotalSize;\r
312 UINTN RecordSize;\r
313 UINTN StructureSize;\r
314 UINTN NumberOfStrings;\r
315 EFI_STATUS Status;\r
316 LIST_ENTRY *Head;\r
317 SMBIOS_INSTANCE *Private;\r
318 EFI_SMBIOS_ENTRY *SmbiosEntry;\r
319 EFI_SMBIOS_HANDLE MaxSmbiosHandle;\r
320 SMBIOS_HANDLE_ENTRY *HandleEntry;\r
321 EFI_SMBIOS_RECORD_HEADER *InternalRecord;\r
322 \r
323 if (SmbiosHandle == NULL) {\r
324 return EFI_INVALID_PARAMETER;\r
325 }\r
326 \r
327 Private = SMBIOS_INSTANCE_FROM_THIS (This);\r
328 //\r
329 // Check whether SmbiosHandle is already in use\r
330 //\r
331 Head = &Private->AllocatedHandleListHead;\r
4659816a 332 if (*SmbiosHandle != SMBIOS_HANDLE_PI_RESERVED && CheckSmbiosHandleExistance(Head, *SmbiosHandle)) {\r
310b04e6 333 return EFI_ALREADY_STARTED;\r
334 }\r
335\r
336 //\r
4659816a 337 // when SmbiosHandle is 0xFFFE, an available handle will be assigned\r
310b04e6 338 //\r
4659816a 339 if (*SmbiosHandle == SMBIOS_HANDLE_PI_RESERVED) {\r
310b04e6 340 Status = GetAvailableSmbiosHandle(This, SmbiosHandle);\r
341 if (EFI_ERROR(Status)) {\r
342 return Status;\r
343 }\r
344 } else {\r
345 //\r
346 // Check this handle validity\r
347 //\r
348 GetMaxSmbiosHandle(This, &MaxSmbiosHandle);\r
349 if (*SmbiosHandle > MaxSmbiosHandle) {\r
350 return EFI_INVALID_PARAMETER;\r
351 }\r
352 }\r
353\r
354 //\r
355 // Calculate record size and string number\r
356 //\r
afe3969c 357 Status = GetSmbiosStructureSize(This, Record, &StructureSize, &NumberOfStrings);\r
310b04e6 358 if (EFI_ERROR(Status)) {\r
359 return Status;\r
360 }\r
361\r
4233bf70
SZ
362 if (EntryPointStructure->TableLength + StructureSize > SMBIOS_TABLE_MAX_LENGTH) {\r
363 //\r
364 // The length of the entire structure table (including all strings) must be reported\r
365 // in the Structure Table Length field of the SMBIOS Structure Table Entry Point,\r
366 // which is a WORD field limited to 65,535 bytes.\r
367 //\r
368 return EFI_OUT_OF_RESOURCES;\r
369 }\r
370\r
310b04e6 371 //\r
372 // Enter into critical section\r
373 // \r
374 Status = EfiAcquireLockOrFail (&Private->DataLock);\r
375 if (EFI_ERROR (Status)) {\r
376 return Status;\r
377 }\r
378 \r
379 RecordSize = sizeof (EFI_SMBIOS_RECORD_HEADER) + StructureSize;\r
380 TotalSize = sizeof (EFI_SMBIOS_ENTRY) + RecordSize;\r
381\r
382 //\r
383 // Allocate internal buffer\r
384 //\r
0d34b1cf 385 SmbiosEntry = AllocateZeroPool (TotalSize);\r
310b04e6 386 if (SmbiosEntry == NULL) {\r
387 EfiReleaseLock (&Private->DataLock);\r
388 return EFI_OUT_OF_RESOURCES;\r
389 }\r
0d34b1cf 390 HandleEntry = AllocateZeroPool (sizeof(SMBIOS_HANDLE_ENTRY));\r
310b04e6 391 if (HandleEntry == NULL) {\r
392 EfiReleaseLock (&Private->DataLock);\r
393 return EFI_OUT_OF_RESOURCES;\r
394 }\r
395\r
396 //\r
397 // Build Handle Entry and insert into linked list\r
398 //\r
310b04e6 399 HandleEntry->Signature = SMBIOS_HANDLE_ENTRY_SIGNATURE;\r
400 HandleEntry->SmbiosHandle = *SmbiosHandle;\r
401 InsertTailList(&Private->AllocatedHandleListHead, &HandleEntry->Link);\r
402\r
310b04e6 403 InternalRecord = (EFI_SMBIOS_RECORD_HEADER *) (SmbiosEntry + 1);\r
404 Raw = (VOID *) (InternalRecord + 1);\r
405\r
406 //\r
407 // Build internal record Header\r
408 //\r
409 InternalRecord->Version = EFI_SMBIOS_RECORD_HEADER_VERSION;\r
c9325700 410 InternalRecord->HeaderSize = (UINT16) sizeof (EFI_SMBIOS_RECORD_HEADER);\r
310b04e6 411 InternalRecord->RecordSize = RecordSize;\r
412 InternalRecord->ProducerHandle = ProducerHandle;\r
413 InternalRecord->NumberOfStrings = NumberOfStrings;\r
414 //\r
415 // Insert record into the internal linked list\r
416 //\r
417 SmbiosEntry->Signature = EFI_SMBIOS_ENTRY_SIGNATURE;\r
418 SmbiosEntry->RecordHeader = InternalRecord;\r
419 SmbiosEntry->RecordSize = TotalSize;\r
420 InsertTailList (&Private->DataListHead, &SmbiosEntry->Link);\r
421\r
422 CopyMem (Raw, Record, StructureSize);\r
423 ((EFI_SMBIOS_TABLE_HEADER*)Raw)->Handle = *SmbiosHandle;\r
424\r
0ddd8553 425 //\r
426 // Some UEFI drivers (such as network) need some information in SMBIOS table.\r
427 // Here we create SMBIOS table and publish it in\r
428 // configuration table, so other UEFI drivers can get SMBIOS table from\r
429 // configuration table without depending on PI SMBIOS protocol.\r
430 //\r
431 SmbiosTableConstruction ();\r
432 \r
310b04e6 433 //\r
434 // Leave critical section\r
435 //\r
436 EfiReleaseLock (&Private->DataLock);\r
437 return EFI_SUCCESS;\r
438}\r
439\r
440/**\r
441 Update the string associated with an existing SMBIOS record.\r
442\r
443 @param This The EFI_SMBIOS_PROTOCOL instance.\r
444 @param SmbiosHandle SMBIOS Handle of structure that will have its string updated.\r
445 @param StringNumber The non-zero string number of the string to update\r
446 @param String Update the StringNumber string with String.\r
447\r
448 @retval EFI_SUCCESS SmbiosHandle had its StringNumber String updated.\r
449 @retval EFI_INVALID_PARAMETER SmbiosHandle does not exist.\r
4659816a 450 @retval EFI_UNSUPPORTED String was not added because it is longer than the SMBIOS Table supports.\r
310b04e6 451 @retval EFI_NOT_FOUND The StringNumber.is not valid for this SMBIOS record.\r
452\r
453**/\r
454EFI_STATUS\r
455EFIAPI\r
456SmbiosUpdateString (\r
457 IN CONST EFI_SMBIOS_PROTOCOL *This,\r
458 IN EFI_SMBIOS_HANDLE *SmbiosHandle,\r
459 IN UINTN *StringNumber,\r
460 IN CHAR8 *String\r
461 )\r
462{\r
463 UINTN InputStrLen;\r
464 UINTN TargetStrLen;\r
465 UINTN StrIndex;\r
466 UINTN TargetStrOffset;\r
467 UINTN NewEntrySize;\r
468 CHAR8 *StrStart;\r
469 VOID *Raw;\r
470 LIST_ENTRY *Link;\r
471 LIST_ENTRY *Head;\r
472 EFI_STATUS Status;\r
473 SMBIOS_INSTANCE *Private;\r
474 EFI_SMBIOS_ENTRY *SmbiosEntry;\r
475 EFI_SMBIOS_ENTRY *ResizedSmbiosEntry;\r
476 EFI_SMBIOS_HANDLE MaxSmbiosHandle;\r
477 EFI_SMBIOS_TABLE_HEADER *Record;\r
478 EFI_SMBIOS_RECORD_HEADER *InternalRecord;\r
479 \r
480 //\r
481 // Check args validity\r
482 //\r
483 GetMaxSmbiosHandle(This, &MaxSmbiosHandle);\r
484\r
485 if (*SmbiosHandle > MaxSmbiosHandle) {\r
486 return EFI_INVALID_PARAMETER;\r
487 }\r
488\r
489 if (String == NULL) {\r
490 return EFI_ABORTED;\r
491 }\r
492\r
493 if (*StringNumber == 0) {\r
494 return EFI_NOT_FOUND;\r
495 }\r
496\r
497 InputStrLen = AsciiStrLen(String);\r
afe3969c 498\r
afe3969c
SZ
499 if (This->MajorVersion < 2 || (This->MajorVersion == 2 && This->MinorVersion < 7)) {\r
500 if (InputStrLen > SMBIOS_STRING_MAX_LENGTH) {\r
501 return EFI_UNSUPPORTED;\r
502 }\r
4233bf70
SZ
503 } else {\r
504 //\r
505 // Reference SMBIOS 2.7, chapter 6.1.3, it will have no limit on the length of each individual text string.\r
506 // However, the length of the entire structure table (including all strings) must be reported \r
507 // in the Structure Table Length field of the SMBIOS Structure Table Entry Point,\r
508 // which is a WORD field limited to 65,535 bytes.\r
509 //\r
510 if (InputStrLen > SMBIOS_TABLE_MAX_LENGTH) {\r
511 return EFI_UNSUPPORTED;\r
512 }\r
310b04e6 513 }\r
514\r
515 Private = SMBIOS_INSTANCE_FROM_THIS (This);\r
516 //\r
517 // Enter into critical section\r
518 // \r
519 Status = EfiAcquireLockOrFail (&Private->DataLock);\r
520 if (EFI_ERROR (Status)) {\r
521 return Status;\r
522 }\r
523\r
524 Head = &Private->DataListHead;\r
525 for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r
526 SmbiosEntry = SMBIOS_ENTRY_FROM_LINK(Link);\r
527 Record = (EFI_SMBIOS_TABLE_HEADER*)(SmbiosEntry->RecordHeader + 1);\r
528\r
afe3969c 529 if (Record->Handle == *SmbiosHandle) {\r
310b04e6 530 //\r
0ddd8553 531 // Find out the specified SMBIOS record\r
310b04e6 532 //\r
533 if (*StringNumber > SmbiosEntry->RecordHeader->NumberOfStrings) {\r
534 EfiReleaseLock (&Private->DataLock);\r
535 return EFI_NOT_FOUND;\r
536 }\r
537 //\r
538 // Point to unformed string section\r
539 //\r
afe3969c 540 StrStart = (CHAR8 *) Record + Record->Length;\r
310b04e6 541 \r
542 for (StrIndex = 1, TargetStrOffset = 0; StrIndex < *StringNumber; StrStart++, TargetStrOffset++) {\r
543 //\r
544 // A string ends in 00h\r
545 //\r
546 if (*StrStart == 0) {\r
547 StrIndex++;\r
548 }\r
549 \r
550 //\r
551 // String section ends in double-null (0000h)\r
552 //\r
553 if (*StrStart == 0 && *(StrStart + 1) == 0) {\r
554 EfiReleaseLock (&Private->DataLock);\r
555 return EFI_NOT_FOUND;\r
556 } \r
557 }\r
558\r
f8ee20c9 559 if (*StrStart == 0) {\r
afe3969c
SZ
560 StrStart++;\r
561 TargetStrOffset++;\r
f8ee20c9 562 }\r
563 \r
310b04e6 564 //\r
565 // Now we get the string target\r
566 //\r
567 TargetStrLen = AsciiStrLen(StrStart);\r
568 if (InputStrLen == TargetStrLen) {\r
569 AsciiStrCpy(StrStart, String);\r
0ddd8553 570 //\r
571 // Some UEFI drivers (such as network) need some information in SMBIOS table.\r
572 // Here we create SMBIOS table and publish it in\r
573 // configuration table, so other UEFI drivers can get SMBIOS table from\r
574 // configuration table without depending on PI SMBIOS protocol.\r
575 //\r
576 SmbiosTableConstruction ();\r
310b04e6 577 EfiReleaseLock (&Private->DataLock);\r
578 return EFI_SUCCESS;\r
579 }\r
580\r
4233bf70
SZ
581 if (EntryPointStructure->TableLength + InputStrLen - TargetStrLen > SMBIOS_TABLE_MAX_LENGTH) {\r
582 //\r
583 // The length of the entire structure table (including all strings) must be reported\r
584 // in the Structure Table Length field of the SMBIOS Structure Table Entry Point,\r
585 // which is a WORD field limited to 65,535 bytes.\r
586 //\r
587 return EFI_UNSUPPORTED;\r
588 }\r
589\r
310b04e6 590 //\r
591 // Original string buffer size is not exactly match input string length.\r
592 // Re-allocate buffer is needed.\r
593 //\r
594 NewEntrySize = SmbiosEntry->RecordSize + InputStrLen - TargetStrLen;\r
0d34b1cf 595 ResizedSmbiosEntry = AllocateZeroPool (NewEntrySize);\r
310b04e6 596\r
597 if (ResizedSmbiosEntry == NULL) {\r
598 EfiReleaseLock (&Private->DataLock);\r
599 return EFI_OUT_OF_RESOURCES;\r
600 }\r
601\r
310b04e6 602 InternalRecord = (EFI_SMBIOS_RECORD_HEADER *) (ResizedSmbiosEntry + 1);\r
603 Raw = (VOID *) (InternalRecord + 1);\r
604\r
605 //\r
606 // Build internal record Header\r
607 //\r
608 InternalRecord->Version = EFI_SMBIOS_RECORD_HEADER_VERSION;\r
c9325700 609 InternalRecord->HeaderSize = (UINT16) sizeof (EFI_SMBIOS_RECORD_HEADER);\r
310b04e6 610 InternalRecord->RecordSize = SmbiosEntry->RecordHeader->RecordSize + InputStrLen - TargetStrLen;\r
611 InternalRecord->ProducerHandle = SmbiosEntry->RecordHeader->ProducerHandle;\r
612 InternalRecord->NumberOfStrings = SmbiosEntry->RecordHeader->NumberOfStrings;\r
613\r
614 //\r
0ddd8553 615 // Copy SMBIOS structure and optional strings.\r
310b04e6 616 //\r
f8ee20c9 617 CopyMem (Raw, SmbiosEntry->RecordHeader + 1, Record->Length + TargetStrOffset);\r
618 CopyMem ((VOID*)((UINTN)Raw + Record->Length + TargetStrOffset), String, InputStrLen + 1);\r
619 CopyMem ((CHAR8*)((UINTN)Raw + Record->Length + TargetStrOffset + InputStrLen + 1),\r
620 (CHAR8*)Record + Record->Length + TargetStrOffset + TargetStrLen + 1,\r
621 SmbiosEntry->RecordHeader->RecordSize - sizeof (EFI_SMBIOS_RECORD_HEADER) - Record->Length - TargetStrOffset - TargetStrLen - 1);\r
310b04e6 622\r
623 //\r
624 // Insert new record\r
625 //\r
626 ResizedSmbiosEntry->Signature = EFI_SMBIOS_ENTRY_SIGNATURE;\r
627 ResizedSmbiosEntry->RecordHeader = InternalRecord;\r
628 ResizedSmbiosEntry->RecordSize = NewEntrySize;\r
629 InsertTailList (Link->ForwardLink, &ResizedSmbiosEntry->Link);\r
630\r
631 //\r
632 // Remove old record\r
633 //\r
634 RemoveEntryList(Link);\r
635 FreePool(SmbiosEntry);\r
0ddd8553 636 //\r
637 // Some UEFI drivers (such as network) need some information in SMBIOS table.\r
638 // Here we create SMBIOS table and publish it in\r
639 // configuration table, so other UEFI drivers can get SMBIOS table from\r
640 // configuration table without depending on PI SMBIOS protocol.\r
641 //\r
642 SmbiosTableConstruction ();\r
310b04e6 643 EfiReleaseLock (&Private->DataLock);\r
644 return EFI_SUCCESS;\r
645 }\r
646 }\r
647\r
648 EfiReleaseLock (&Private->DataLock);\r
649 return EFI_INVALID_PARAMETER;\r
650}\r
651\r
652/**\r
653 Remove an SMBIOS record.\r
654\r
655 @param This The EFI_SMBIOS_PROTOCOL instance.\r
656 @param SmbiosHandle The handle of the SMBIOS record to remove.\r
657\r
658 @retval EFI_SUCCESS SMBIOS record was removed.\r
659 @retval EFI_INVALID_PARAMETER SmbiosHandle does not specify a valid SMBIOS record.\r
660\r
661**/\r
662EFI_STATUS\r
663EFIAPI\r
664SmbiosRemove (\r
665 IN CONST EFI_SMBIOS_PROTOCOL *This,\r
666 IN EFI_SMBIOS_HANDLE SmbiosHandle\r
667 )\r
668{\r
669 LIST_ENTRY *Link;\r
670 LIST_ENTRY *Head;\r
671 EFI_STATUS Status;\r
672 EFI_SMBIOS_HANDLE MaxSmbiosHandle;\r
673 SMBIOS_INSTANCE *Private;\r
674 EFI_SMBIOS_ENTRY *SmbiosEntry;\r
675 SMBIOS_HANDLE_ENTRY *HandleEntry;\r
676 EFI_SMBIOS_TABLE_HEADER *Record;\r
677\r
678 //\r
679 // Check args validity\r
680 //\r
681 GetMaxSmbiosHandle(This, &MaxSmbiosHandle);\r
682\r
683 if (SmbiosHandle > MaxSmbiosHandle) {\r
684 return EFI_INVALID_PARAMETER;\r
685 }\r
686\r
687 Private = SMBIOS_INSTANCE_FROM_THIS (This);\r
688 //\r
689 // Enter into critical section\r
690 // \r
691 Status = EfiAcquireLockOrFail (&Private->DataLock);\r
692 if (EFI_ERROR (Status)) {\r
693 return Status;\r
694 }\r
695\r
696 Head = &Private->DataListHead;\r
697 for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r
698 SmbiosEntry = SMBIOS_ENTRY_FROM_LINK(Link);\r
699 Record = (EFI_SMBIOS_TABLE_HEADER*)(SmbiosEntry->RecordHeader + 1);\r
afe3969c 700 if (Record->Handle == SmbiosHandle) {\r
310b04e6 701 //\r
702 // Remove specified smobios record from DataList\r
703 //\r
704 RemoveEntryList(Link);\r
705 FreePool(SmbiosEntry);\r
706 // \r
707 // Remove this handle from AllocatedHandleList\r
708 //\r
709 Head = &Private->AllocatedHandleListHead;\r
710 for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r
711 HandleEntry = SMBIOS_HANDLE_ENTRY_FROM_LINK(Link);\r
afe3969c 712 if (HandleEntry->SmbiosHandle == SmbiosHandle) {\r
310b04e6 713 RemoveEntryList(Link);\r
714 FreePool(HandleEntry);\r
715 break;\r
716 }\r
717 }\r
0ddd8553 718 //\r
719 // Some UEFI drivers (such as network) need some information in SMBIOS table.\r
720 // Here we create SMBIOS table and publish it in\r
721 // configuration table, so other UEFI drivers can get SMBIOS table from\r
722 // configuration table without depending on PI SMBIOS protocol.\r
723 //\r
724 SmbiosTableConstruction ();\r
310b04e6 725 EfiReleaseLock (&Private->DataLock);\r
726 return EFI_SUCCESS;\r
727 }\r
728 }\r
729\r
730 //\r
731 // Leave critical section\r
732 //\r
733 EfiReleaseLock (&Private->DataLock);\r
734 return EFI_INVALID_PARAMETER;\r
735 \r
736}\r
737\r
738/**\r
739 Allow the caller to discover all or some of the SMBIOS records.\r
740\r
741 @param This The EFI_SMBIOS_PROTOCOL instance.\r
742 @param SmbiosHandle On entry, points to the previous handle of the SMBIOS record. On exit, points to the\r
4659816a
SZ
743 next SMBIOS record handle. If it is FFFEh on entry, then the first SMBIOS record\r
744 handle will be returned. If it returns FFFEh on exit, then there are no more SMBIOS records.\r
310b04e6 745 @param Type On entry it means return the next SMBIOS record of type Type. If a NULL is passed in \r
746 this functionally it ignored. Type is not modified by the GetNext() function.\r
747 @param Record On exit, points to the SMBIOS Record consisting of the formatted area followed by\r
748 the unformatted area. The unformatted area optionally contains text strings.\r
749 @param ProducerHandle On exit, points to the ProducerHandle registered by Add(). If no ProducerHandle was passed into Add() NULL is returned. \r
750 If a NULL pointer is passed in no data will be returned \r
751 \r
752 @retval EFI_SUCCESS SMBIOS record information was successfully returned in Record.\r
310b04e6 753 @retval EFI_NOT_FOUND The SMBIOS record with SmbiosHandle was the last available record.\r
754\r
755**/\r
756EFI_STATUS\r
757EFIAPI\r
758SmbiosGetNext (\r
759 IN CONST EFI_SMBIOS_PROTOCOL *This,\r
760 IN OUT EFI_SMBIOS_HANDLE *SmbiosHandle,\r
761 IN EFI_SMBIOS_TYPE *Type, OPTIONAL\r
762 OUT EFI_SMBIOS_TABLE_HEADER **Record,\r
763 OUT EFI_HANDLE *ProducerHandle OPTIONAL\r
764 )\r
765{\r
766 BOOLEAN StartPointFound;\r
767 LIST_ENTRY *Link;\r
768 LIST_ENTRY *Head;\r
769 SMBIOS_INSTANCE *Private;\r
770 EFI_SMBIOS_ENTRY *SmbiosEntry;\r
771 EFI_SMBIOS_TABLE_HEADER *SmbiosTableHeader;\r
772\r
773 if (SmbiosHandle == NULL) {\r
774 return EFI_INVALID_PARAMETER;\r
775 }\r
776\r
777 StartPointFound = FALSE;\r
778 Private = SMBIOS_INSTANCE_FROM_THIS (This);\r
779 Head = &Private->DataListHead;\r
780 for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r
781 SmbiosEntry = SMBIOS_ENTRY_FROM_LINK(Link);\r
782 SmbiosTableHeader = (EFI_SMBIOS_TABLE_HEADER*)(SmbiosEntry->RecordHeader + 1); \r
783\r
784 //\r
4659816a 785 // If SmbiosHandle is 0xFFFE, the first matched SMBIOS record handle will be returned\r
310b04e6 786 //\r
4659816a 787 if (*SmbiosHandle == SMBIOS_HANDLE_PI_RESERVED) {\r
310b04e6 788 if ((Type != NULL) && (*Type != SmbiosTableHeader->Type)) {\r
789 continue; \r
790 }\r
791\r
792 *SmbiosHandle = SmbiosTableHeader->Handle;\r
793 *Record =SmbiosTableHeader;\r
794 if (ProducerHandle != NULL) {\r
795 *ProducerHandle = SmbiosEntry->RecordHeader->ProducerHandle;\r
796 }\r
797 return EFI_SUCCESS;\r
798 }\r
799\r
800 //\r
0ddd8553 801 // Start this round search from the next SMBIOS handle\r
310b04e6 802 //\r
803 if (!StartPointFound && (*SmbiosHandle == SmbiosTableHeader->Handle)) {\r
804 StartPointFound = TRUE;\r
805 continue;\r
806 }\r
807\r
808 if (StartPointFound) {\r
809 if ((Type != NULL) && (*Type != SmbiosTableHeader->Type)) {\r
810 continue; \r
811 }\r
812 \r
813 *SmbiosHandle = SmbiosTableHeader->Handle;\r
814 *Record = SmbiosTableHeader; \r
815 if (ProducerHandle != NULL) {\r
816 *ProducerHandle = SmbiosEntry->RecordHeader->ProducerHandle;\r
817 }\r
818\r
819 return EFI_SUCCESS; \r
820 }\r
821 }\r
822\r
4659816a 823 *SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;\r
310b04e6 824 return EFI_NOT_FOUND;\r
825 \r
826}\r
827\r
0ddd8553 828/**\r
829 Allow the caller to discover all of the SMBIOS records.\r
830\r
831 @param This The EFI_SMBIOS_PROTOCOL instance.\r
832 @param CurrentSmbiosEntry On exit, points to the SMBIOS entry on the list which includes the returned SMBIOS record information. \r
833 If *CurrentSmbiosEntry is NULL on entry, then the first SMBIOS entry on the list will be returned. \r
834 @param Record On exit, points to the SMBIOS Record consisting of the formatted area followed by\r
835 the unformatted area. The unformatted area optionally contains text strings.\r
836 \r
837 @retval EFI_SUCCESS SMBIOS record information was successfully returned in Record.\r
838 *CurrentSmbiosEntry points to the SMBIOS entry which includes the returned SMBIOS record information.\r
839 @retval EFI_NOT_FOUND There is no more SMBIOS entry.\r
840\r
841**/\r
842EFI_STATUS\r
843EFIAPI\r
844GetNextSmbiosRecord (\r
845 IN CONST EFI_SMBIOS_PROTOCOL *This,\r
846 IN OUT EFI_SMBIOS_ENTRY **CurrentSmbiosEntry,\r
847 OUT EFI_SMBIOS_TABLE_HEADER **Record\r
848 )\r
849{\r
850 LIST_ENTRY *Link;\r
851 LIST_ENTRY *Head;\r
852 SMBIOS_INSTANCE *Private;\r
853 EFI_SMBIOS_ENTRY *SmbiosEntry;\r
854 EFI_SMBIOS_TABLE_HEADER *SmbiosTableHeader;\r
855\r
856 Private = SMBIOS_INSTANCE_FROM_THIS (This);\r
857 if (*CurrentSmbiosEntry == NULL) {\r
858 //\r
859 // Get the beginning of SMBIOS entry.\r
860 //\r
861 Head = &Private->DataListHead;\r
862 } else {\r
863 //\r
864 // Get previous SMBIOS entry and make it as start point.\r
865 //\r
866 Head = &(*CurrentSmbiosEntry)->Link;\r
867 }\r
868 \r
869 Link = Head->ForwardLink;\r
870 \r
871 if (Link == &Private->DataListHead) {\r
872 //\r
873 // If no more SMBIOS entry in the list, return not found.\r
874 //\r
875 return EFI_NOT_FOUND;\r
876 }\r
877 \r
878 SmbiosEntry = SMBIOS_ENTRY_FROM_LINK(Link);\r
879 SmbiosTableHeader = (EFI_SMBIOS_TABLE_HEADER*)(SmbiosEntry->RecordHeader + 1);\r
880 *Record = SmbiosTableHeader; \r
881 *CurrentSmbiosEntry = SmbiosEntry;\r
882 return EFI_SUCCESS; \r
883}\r
310b04e6 884\r
885/**\r
0ddd8553 886 Assembles SMBIOS table from the SMBIOS protocol. Produce Table\r
310b04e6 887 Entry Point and return the pointer to it.\r
888 \r
889 @param TableEntryPointStructure On exit, points to the SMBIOS entrypoint structure.\r
890 \r
891 @retval EFI_SUCCESS Structure created sucessfully.\r
892 @retval EFI_NOT_READY Some of The SMBIOS records was not available yet.\r
893 @retval EFI_OUT_OF_RESOURCES No enough memory.\r
894 \r
895**/\r
896EFI_STATUS\r
897EFIAPI\r
898SmbiosCreateTable (\r
899 OUT VOID **TableEntryPointStructure\r
900 )\r
901{\r
310b04e6 902 UINT8 *BufferPointer;\r
310b04e6 903 UINTN RecordSize;\r
904 UINTN NumOfStr;\r
905 EFI_STATUS Status;\r
906 EFI_SMBIOS_HANDLE SmbiosHandle;\r
907 EFI_SMBIOS_PROTOCOL *SmbiosProtocol;\r
908 EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
909 EFI_SMBIOS_TABLE_HEADER *SmbiosRecord;\r
910 EFI_SMBIOS_TABLE_END_STRUCTURE EndStructure;\r
0ddd8553 911 EFI_SMBIOS_ENTRY *CurrentSmbiosEntry;\r
310b04e6 912 \r
913 Status = EFI_SUCCESS;\r
914 BufferPointer = NULL;\r
310b04e6 915\r
916 //\r
0ddd8553 917 // Get Smbios protocol to traverse SMBIOS records.\r
310b04e6 918 //\r
0ddd8553 919 SmbiosProtocol = &mPrivateData.Smbios;\r
310b04e6 920\r
310b04e6 921 //\r
922 // Make some statistics about all the structures\r
923 //\r
924 EntryPointStructure->NumberOfSmbiosStructures = 0;\r
925 EntryPointStructure->TableLength = 0;\r
926 EntryPointStructure->MaxStructureSize = 0;\r
310b04e6 927\r
928 //\r
929 // Calculate EPS Table Length\r
930 //\r
0ddd8553 931 CurrentSmbiosEntry = NULL;\r
310b04e6 932 do {\r
0ddd8553 933 Status = GetNextSmbiosRecord (SmbiosProtocol, &CurrentSmbiosEntry, &SmbiosRecord);\r
310b04e6 934 \r
935 if (Status == EFI_SUCCESS) {\r
afe3969c 936 GetSmbiosStructureSize(SmbiosProtocol, SmbiosRecord, &RecordSize, &NumOfStr);\r
310b04e6 937 //\r
938 // Record NumberOfSmbiosStructures, TableLength and MaxStructureSize\r
939 //\r
afe3969c 940 EntryPointStructure->NumberOfSmbiosStructures++;\r
310b04e6 941 EntryPointStructure->TableLength = (UINT16) (EntryPointStructure->TableLength + RecordSize);\r
942 if (RecordSize > EntryPointStructure->MaxStructureSize) {\r
943 EntryPointStructure->MaxStructureSize = (UINT16) RecordSize;\r
944 }\r
945 }\r
946 } while (!EFI_ERROR(Status));\r
947 \r
948 //\r
949 // Create End-Of-Table structure\r
950 //\r
951 GetMaxSmbiosHandle(SmbiosProtocol, &SmbiosHandle);\r
952 EndStructure.Header.Type = EFI_SMBIOS_TYPE_END_OF_TABLE;\r
c9325700 953 EndStructure.Header.Length = (UINT8) sizeof (EFI_SMBIOS_TABLE_HEADER);\r
310b04e6 954 EndStructure.Header.Handle = SmbiosHandle;\r
955 EndStructure.Tailing[0] = 0;\r
956 EndStructure.Tailing[1] = 0;\r
957 EntryPointStructure->NumberOfSmbiosStructures++;\r
958 EntryPointStructure->TableLength = (UINT16) (EntryPointStructure->TableLength + sizeof (EndStructure));\r
959 if (sizeof (EndStructure) > EntryPointStructure->MaxStructureSize) {\r
960 EntryPointStructure->MaxStructureSize = (UINT16) sizeof (EndStructure);\r
961 }\r
310b04e6 962\r
4233bf70 963 if ((UINTN) EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength) > mPreAllocatedPages) {\r
0ddd8553 964 //\r
965 // If new SMBIOS talbe size exceeds the original pre-allocated page, \r
966 // it is time to re-allocate memory (below 4GB).\r
967 // \r
968 if (EntryPointStructure->TableAddress != 0) {\r
969 //\r
970 // Free the original pre-allocated page\r
971 // \r
972 FreePages (\r
973 (VOID*)(UINTN)EntryPointStructure->TableAddress,\r
4233bf70 974 mPreAllocatedPages\r
0ddd8553 975 );\r
976 EntryPointStructure->TableAddress = 0;\r
4233bf70 977 mPreAllocatedPages = 0;\r
0ddd8553 978 }\r
979 \r
980 PhysicalAddress = 0xffffffff;\r
981 Status = gBS->AllocatePages (\r
982 AllocateMaxAddress,\r
983 EfiReservedMemoryType,\r
984 EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength),\r
985 &PhysicalAddress\r
986 );\r
987 if (EFI_ERROR (Status)) {\r
c7ce5169 988 DEBUG ((EFI_D_ERROR, "SmbiosCreateTable() could not allocate SMBIOS table < 4GB\n"));\r
989 EntryPointStructure->TableAddress = 0;\r
0ddd8553 990 return EFI_OUT_OF_RESOURCES;\r
c7ce5169 991 } else {\r
992 EntryPointStructure->TableAddress = (UINT32) PhysicalAddress;\r
4233bf70 993 mPreAllocatedPages = EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength);\r
0ddd8553 994 }\r
0ddd8553 995 }\r
310b04e6 996 \r
997 //\r
998 // Assemble the tables\r
999 //\r
f63085f5 1000 ASSERT (EntryPointStructure->TableAddress != 0);\r
0ddd8553 1001 BufferPointer = (UINT8 *) (UINTN) EntryPointStructure->TableAddress;\r
1002 CurrentSmbiosEntry = NULL;\r
310b04e6 1003 do {\r
0ddd8553 1004 Status = GetNextSmbiosRecord (SmbiosProtocol, &CurrentSmbiosEntry, &SmbiosRecord);\r
1005\r
310b04e6 1006 if (Status == EFI_SUCCESS) {\r
afe3969c 1007 GetSmbiosStructureSize(SmbiosProtocol, SmbiosRecord, &RecordSize, &NumOfStr);\r
310b04e6 1008 CopyMem (BufferPointer, SmbiosRecord, RecordSize);\r
1009 BufferPointer = BufferPointer + RecordSize;\r
1010 }\r
1011 } while (!EFI_ERROR(Status));\r
1012 \r
1013 //\r
1014 // Assemble End-Of-Table structure\r
1015 //\r
1016 CopyMem (BufferPointer, &EndStructure, sizeof (EndStructure));\r
1017\r
1018 //\r
1019 // Fixup checksums in the Entry Point Structure\r
1020 //\r
47f8d0f3
JY
1021 EntryPointStructure->IntermediateChecksum = 0;\r
1022 EntryPointStructure->EntryPointStructureChecksum = 0;\r
1023\r
afe3969c
SZ
1024 EntryPointStructure->IntermediateChecksum =\r
1025 CalculateCheckSum8 ((UINT8 *) EntryPointStructure + 0x10, EntryPointStructure->EntryPointLength - 0x10);\r
1026 EntryPointStructure->EntryPointStructureChecksum =\r
1027 CalculateCheckSum8 ((UINT8 *) EntryPointStructure, EntryPointStructure->EntryPointLength);\r
310b04e6 1028\r
1029 //\r
1030 // Returns the pointer\r
1031 //\r
1032 *TableEntryPointStructure = EntryPointStructure;\r
1033\r
1034 return EFI_SUCCESS;\r
1035}\r
1036\r
310b04e6 1037/**\r
0ddd8553 1038 Create SMBIOS Table and install it to the System Table.\r
310b04e6 1039**/\r
1040VOID\r
1041EFIAPI\r
1042SmbiosTableConstruction (\r
0ddd8553 1043 VOID\r
310b04e6 1044 )\r
1045{\r
1046 UINT8 *Eps;\r
1047 EFI_STATUS Status;\r
1048\r
1049 Status = SmbiosCreateTable ((VOID **) &Eps);\r
1050 if (!EFI_ERROR (Status)) {\r
1051 gBS->InstallConfigurationTable (&gEfiSmbiosTableGuid, Eps);\r
1052 }\r
1053}\r
1054\r
310b04e6 1055/**\r
1056\r
0ddd8553 1057 Driver to produce Smbios protocol and pre-allocate 1 page for the final SMBIOS table. \r
310b04e6 1058\r
1059 @param ImageHandle Module's image handle\r
1060 @param SystemTable Pointer of EFI_SYSTEM_TABLE\r
1061\r
1062 @retval EFI_SUCCESS Smbios protocol installed\r
1063 @retval Other No protocol installed, unload driver.\r
1064\r
1065**/\r
1066EFI_STATUS\r
1067EFIAPI\r
1068SmbiosDriverEntryPoint (\r
1069 IN EFI_HANDLE ImageHandle,\r
1070 IN EFI_SYSTEM_TABLE *SystemTable\r
1071 )\r
1072{\r
1073 EFI_STATUS Status;\r
0ddd8553 1074 EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
310b04e6 1075\r
1076 mPrivateData.Signature = SMBIOS_INSTANCE_SIGNATURE;\r
1077 mPrivateData.Smbios.Add = SmbiosAdd;\r
1078 mPrivateData.Smbios.UpdateString = SmbiosUpdateString;\r
1079 mPrivateData.Smbios.Remove = SmbiosRemove;\r
1080 mPrivateData.Smbios.GetNext = SmbiosGetNext;\r
9f7d5b46 1081 mPrivateData.Smbios.MajorVersion = (UINT8) (FixedPcdGet16 (PcdSmbiosVersion) >> 8);\r
1082 mPrivateData.Smbios.MinorVersion = (UINT8) (FixedPcdGet16 (PcdSmbiosVersion) & 0x00ff);\r
310b04e6 1083\r
1084 InitializeListHead (&mPrivateData.DataListHead);\r
1085 InitializeListHead (&mPrivateData.AllocatedHandleListHead);\r
1086 EfiInitializeLock (&mPrivateData.DataLock, TPL_NOTIFY);\r
0ddd8553 1087\r
1088 //\r
1089 // Initialize the EntryPointStructure with initial values.\r
1090 // Allocate memory (below 4GB).\r
1091 //\r
1092 PhysicalAddress = 0xffffffff;\r
1093 Status = gBS->AllocatePages (\r
1094 AllocateMaxAddress,\r
1095 EfiReservedMemoryType,\r
1096 EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT)),\r
1097 &PhysicalAddress\r
1098 );\r
1099 if (EFI_ERROR (Status)) {\r
c7ce5169 1100 DEBUG ((EFI_D_ERROR, "SmbiosDriverEntryPoint() could not allocate EntryPointStructure < 4GB\n"));\r
1101 Status = gBS->AllocatePages (\r
1102 AllocateAnyPages,\r
1103 EfiReservedMemoryType,\r
1104 EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT)),\r
1105 &PhysicalAddress\r
1106 );\r
1107 if (EFI_ERROR (Status)) { \r
1108 return EFI_OUT_OF_RESOURCES;\r
1109 }\r
0ddd8553 1110 }\r
1111\r
1112 EntryPointStructure = (SMBIOS_TABLE_ENTRY_POINT *) (UINTN) PhysicalAddress;\r
310b04e6 1113 \r
0ddd8553 1114 CopyMem (\r
1115 EntryPointStructure,\r
1116 &EntryPointStructureData,\r
1117 sizeof (SMBIOS_TABLE_ENTRY_POINT)\r
1118 );\r
1119\r
1120 //\r
1121 // Pre-allocate 1 page for SMBIOS table below 4GB.\r
1122 // SMBIOS table will be updated when new SMBIOS type is added or \r
1123 // existing SMBIOS type is updated. If the total size of SMBIOS table exceeds 1 page,\r
1124 // we will re-allocate new memory when creating whole SMBIOS table.\r
1125 //\r
1126 PhysicalAddress = 0xffffffff;\r
1127 Status = gBS->AllocatePages (\r
1128 AllocateMaxAddress,\r
1129 EfiReservedMemoryType,\r
1130 1,\r
1131 &PhysicalAddress\r
1132 );\r
1133 if (EFI_ERROR (Status)) {\r
c7ce5169 1134 DEBUG ((EFI_D_ERROR, "SmbiosDriverEntryPoint() could not allocate SMBIOS table < 4GB\n"));\r
1135 EntryPointStructure->TableAddress = 0;\r
c7ce5169 1136 } else {\r
1137 EntryPointStructure->TableAddress = (UINT32) PhysicalAddress;\r
4233bf70 1138 mPreAllocatedPages = 1;\r
0ddd8553 1139 }\r
4233bf70
SZ
1140\r
1141 //\r
1142 // Init TableLength to the length of End-Of-Table structure for SmbiosAdd() called at the first time\r
1143 // to check the TableLength limitation.\r
1144 //\r
1145 EntryPointStructure->TableLength = sizeof (EFI_SMBIOS_TABLE_END_STRUCTURE);\r
c7ce5169 1146 \r
310b04e6 1147 //\r
1148 // Make a new handle and install the protocol\r
1149 //\r
1150 mPrivateData.Handle = NULL;\r
1151 Status = gBS->InstallProtocolInterface (\r
1152 &mPrivateData.Handle,\r
1153 &gEfiSmbiosProtocolGuid,\r
1154 EFI_NATIVE_INTERFACE,\r
1155 &mPrivateData.Smbios\r
1156 );\r
1157\r
310b04e6 1158 return Status;\r
1159}\r