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