2 This code produces the Smbios protocol. It also responsible for constructing
3 SMBIOS table into system table.
5 Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "SmbiosDxe.h"
20 // Since this driver will only ever produce one instance of the
21 // protocol you are not required to dynamically allocate the PrivateData.
23 SMBIOS_INSTANCE mPrivateData
;
25 UINTN mPreAllocatedPages
= 0;
26 UINTN mPre64BitAllocatedPages
= 0;
29 // Chassis for SMBIOS entry point structure that is to be installed into EFI system config table.
31 SMBIOS_TABLE_ENTRY_POINT
*EntryPointStructure
= NULL
;
32 SMBIOS_TABLE_ENTRY_POINT EntryPointStructureData
= {
43 // EntryPointStructureChecksum,TO BE FILLED
47 // EntryPointStructure Length
59 // MaxStructureSize, TO BE FILLED
77 // IntermediateAnchorString
87 // IntermediateChecksum, TO BE FILLED
91 // TableLength, TO BE FILLED
95 // TableAddress, TO BE FILLED
99 // NumberOfSmbiosStructures, TO BE FILLED
108 SMBIOS_TABLE_3_0_ENTRY_POINT
*Smbios30EntryPointStructure
= NULL
;
109 SMBIOS_TABLE_3_0_ENTRY_POINT Smbios30EntryPointStructureData
= {
111 // AnchorString _SM3_
121 // EntryPointStructureChecksum,TO BE FILLED
141 // EntryPointRevision
149 // TableMaximumSize,TO BE FILLED
153 // TableAddress,TO BE FILLED
159 Get the full size of SMBIOS structure including optional strings that follow the formatted structure.
161 @param This The EFI_SMBIOS_PROTOCOL instance.
162 @param Head Pointer to the beginning of SMBIOS structure.
163 @param Size The returned size.
164 @param NumberOfStrings The returned number of optional strings that follow the formatted structure.
166 @retval EFI_SUCCESS Size retured in Size.
167 @retval EFI_INVALID_PARAMETER Input SMBIOS structure mal-formed or Size is NULL.
172 GetSmbiosStructureSize (
173 IN CONST EFI_SMBIOS_PROTOCOL
*This
,
174 IN EFI_SMBIOS_TABLE_HEADER
*Head
,
176 OUT UINTN
*NumberOfStrings
184 if (Size
== NULL
|| NumberOfStrings
== NULL
) {
185 return EFI_INVALID_PARAMETER
;
188 FullSize
= Head
->Length
;
189 CharInStr
= (INT8
*)Head
+ Head
->Length
;
191 *NumberOfStrings
= 0;
194 // look for the two consecutive zeros, check the string limit by the way.
196 while (*CharInStr
!= 0 || *(CharInStr
+1) != 0) {
197 if (*CharInStr
== 0) {
202 if (This
->MajorVersion
< 2 || (This
->MajorVersion
== 2 && This
->MinorVersion
< 7)){
203 MaxLen
= SMBIOS_STRING_MAX_LENGTH
;
204 } else if (This
->MajorVersion
< 3) {
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.
211 MaxLen
= SMBIOS_TABLE_MAX_LENGTH
;
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.
217 MaxLen
= SMBIOS_3_0_TABLE_MAX_LENGTH
;
220 for (StrLen
= 0 ; StrLen
< MaxLen
; StrLen
++) {
221 if (*(CharInStr
+StrLen
) == 0) {
226 if (StrLen
== MaxLen
) {
227 return EFI_INVALID_PARAMETER
;
231 // forward the pointer
235 *NumberOfStrings
+= 1;
239 // count ending two zeros.
247 Determin whether an SmbiosHandle has already in use.
249 @param Head Pointer to the beginning of SMBIOS structure.
250 @param Handle A unique handle will be assigned to the SMBIOS record.
252 @retval TRUE Smbios handle already in use.
253 @retval FALSE Smbios handle is NOT used.
258 CheckSmbiosHandleExistance (
260 IN EFI_SMBIOS_HANDLE Handle
264 SMBIOS_HANDLE_ENTRY
*HandleEntry
;
266 for (Link
= Head
->ForwardLink
; Link
!= Head
; Link
= Link
->ForwardLink
) {
267 HandleEntry
= SMBIOS_HANDLE_ENTRY_FROM_LINK(Link
);
268 if (HandleEntry
->SmbiosHandle
== Handle
) {
278 Get the max SmbiosHandle that could be use.
280 @param This The EFI_SMBIOS_PROTOCOL instance.
281 @param MaxHandle The max handle that could be assigned to the SMBIOS record.
287 IN CONST EFI_SMBIOS_PROTOCOL
*This
,
288 IN OUT EFI_SMBIOS_HANDLE
*MaxHandle
291 if (This
->MajorVersion
== 2 && This
->MinorVersion
== 0) {
300 Get an SmbiosHandle that could use.
302 @param This The EFI_SMBIOS_PROTOCOL instance.
303 @param SmbiosHandle A unique handle will be assigned to the SMBIOS record.
305 @retval EFI_SUCCESS Smbios handle got.
306 @retval EFI_OUT_OF_RESOURCES Smbios handle is NOT available.
311 GetAvailableSmbiosHandle (
312 IN CONST EFI_SMBIOS_PROTOCOL
*This
,
313 IN OUT EFI_SMBIOS_HANDLE
*Handle
317 SMBIOS_INSTANCE
*Private
;
318 EFI_SMBIOS_HANDLE MaxSmbiosHandle
;
319 EFI_SMBIOS_HANDLE AvailableHandle
;
321 GetMaxSmbiosHandle(This
, &MaxSmbiosHandle
);
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
;
332 return EFI_OUT_OF_RESOURCES
;
337 Add an SMBIOS record.
339 @param This The EFI_SMBIOS_PROTOCOL instance.
340 @param ProducerHandle The handle of the controller or driver associated with the SMBIOS information. NULL
342 @param SmbiosHandle On entry, the handle of the SMBIOS record to add. If FFFEh, then a unique handle
343 will be assigned to the SMBIOS record. If the SMBIOS handle is already in use,
344 EFI_ALREADY_STARTED is returned and the SMBIOS record is not updated.
345 @param Record The data for the fixed portion of the SMBIOS record. The format of the record is
346 determined by EFI_SMBIOS_TABLE_HEADER.Type. The size of the formatted area is defined
347 by EFI_SMBIOS_TABLE_HEADER.Length and either followed by a double-null (0x0000) or
348 a set of null terminated strings and a null.
350 @retval EFI_SUCCESS Record was added.
351 @retval EFI_OUT_OF_RESOURCES Record was not added due to lack of system resources.
352 @retval EFI_ALREADY_STARTED The SmbiosHandle passed in was already in use.
358 IN CONST EFI_SMBIOS_PROTOCOL
*This
,
359 IN EFI_HANDLE ProducerHandle
, OPTIONAL
360 IN OUT EFI_SMBIOS_HANDLE
*SmbiosHandle
,
361 IN EFI_SMBIOS_TABLE_HEADER
*Record
368 UINTN NumberOfStrings
;
371 SMBIOS_INSTANCE
*Private
;
372 EFI_SMBIOS_ENTRY
*SmbiosEntry
;
373 EFI_SMBIOS_HANDLE MaxSmbiosHandle
;
374 SMBIOS_HANDLE_ENTRY
*HandleEntry
;
375 EFI_SMBIOS_RECORD_HEADER
*InternalRecord
;
376 BOOLEAN Smbios32BitTable
;
377 BOOLEAN Smbios64BitTable
;
379 if (SmbiosHandle
== NULL
) {
380 return EFI_INVALID_PARAMETER
;
383 Private
= SMBIOS_INSTANCE_FROM_THIS (This
);
385 // Check whether SmbiosHandle is already in use
387 Head
= &Private
->AllocatedHandleListHead
;
388 if (*SmbiosHandle
!= SMBIOS_HANDLE_PI_RESERVED
&& CheckSmbiosHandleExistance(Head
, *SmbiosHandle
)) {
389 return EFI_ALREADY_STARTED
;
393 // when SmbiosHandle is 0xFFFE, an available handle will be assigned
395 if (*SmbiosHandle
== SMBIOS_HANDLE_PI_RESERVED
) {
396 Status
= GetAvailableSmbiosHandle(This
, SmbiosHandle
);
397 if (EFI_ERROR(Status
)) {
402 // Check this handle validity
404 GetMaxSmbiosHandle(This
, &MaxSmbiosHandle
);
405 if (*SmbiosHandle
> MaxSmbiosHandle
) {
406 return EFI_INVALID_PARAMETER
;
411 // Calculate record size and string number
413 Status
= GetSmbiosStructureSize(This
, Record
, &StructureSize
, &NumberOfStrings
);
414 if (EFI_ERROR(Status
)) {
418 Smbios32BitTable
= FALSE
;
419 Smbios64BitTable
= FALSE
;
420 if ((This
->MajorVersion
< 0x3) ||
421 ((This
->MajorVersion
>= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod
) & BIT0
) == BIT0
))) {
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.
427 if ((EntryPointStructure
!= NULL
) &&
428 (EntryPointStructure
->TableLength
+ StructureSize
> SMBIOS_TABLE_MAX_LENGTH
)) {
429 DEBUG ((EFI_D_INFO
, "SmbiosAdd: Total length exceeds max 32-bit table length with type = %d size = 0x%x\n", Record
->Type
, StructureSize
));
431 Smbios32BitTable
= TRUE
;
432 DEBUG ((EFI_D_INFO
, "SmbiosAdd: Smbios type %d with size 0x%x is added to 32-bit table\n", Record
->Type
, StructureSize
));
437 // For SMBIOS 3.0, Structure table maximum size in Entry Point structure is DWORD field limited to 0xFFFFFFFF bytes.
439 if ((This
->MajorVersion
>= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod
) & BIT1
) == BIT1
)) {
441 // For SMBIOS 64-bit table, Structure table maximum size in SMBIOS 3.0 (64-bit) Entry Point
442 // is a DWORD field limited to 0xFFFFFFFF bytes. So the max size of 64-bit table should not exceed 0xFFFFFFFF bytes.
444 if ((Smbios30EntryPointStructure
!= NULL
) &&
445 (Smbios30EntryPointStructure
->TableMaximumSize
+ StructureSize
> SMBIOS_3_0_TABLE_MAX_LENGTH
)) {
446 DEBUG ((EFI_D_INFO
, "SmbiosAdd: Total length exceeds max 64-bit table length with type = %d size = 0x%x\n", Record
->Type
, StructureSize
));
448 DEBUG ((EFI_D_INFO
, "SmbiosAdd: Smbios type %d with size 0x%x is added to 64-bit table\n", Record
->Type
, StructureSize
));
449 Smbios64BitTable
= TRUE
;
453 if ((!Smbios32BitTable
) && (!Smbios64BitTable
)) {
455 // If both 32-bit and 64-bit table are not updated, quit
457 return EFI_OUT_OF_RESOURCES
;
461 // Enter into critical section
463 Status
= EfiAcquireLockOrFail (&Private
->DataLock
);
464 if (EFI_ERROR (Status
)) {
468 RecordSize
= sizeof (EFI_SMBIOS_RECORD_HEADER
) + StructureSize
;
469 TotalSize
= sizeof (EFI_SMBIOS_ENTRY
) + RecordSize
;
472 // Allocate internal buffer
474 SmbiosEntry
= AllocateZeroPool (TotalSize
);
475 if (SmbiosEntry
== NULL
) {
476 EfiReleaseLock (&Private
->DataLock
);
477 return EFI_OUT_OF_RESOURCES
;
479 HandleEntry
= AllocateZeroPool (sizeof(SMBIOS_HANDLE_ENTRY
));
480 if (HandleEntry
== NULL
) {
481 EfiReleaseLock (&Private
->DataLock
);
482 return EFI_OUT_OF_RESOURCES
;
486 // Build Handle Entry and insert into linked list
488 HandleEntry
->Signature
= SMBIOS_HANDLE_ENTRY_SIGNATURE
;
489 HandleEntry
->SmbiosHandle
= *SmbiosHandle
;
490 InsertTailList(&Private
->AllocatedHandleListHead
, &HandleEntry
->Link
);
492 InternalRecord
= (EFI_SMBIOS_RECORD_HEADER
*) (SmbiosEntry
+ 1);
493 Raw
= (VOID
*) (InternalRecord
+ 1);
496 // Build internal record Header
498 InternalRecord
->Version
= EFI_SMBIOS_RECORD_HEADER_VERSION
;
499 InternalRecord
->HeaderSize
= (UINT16
) sizeof (EFI_SMBIOS_RECORD_HEADER
);
500 InternalRecord
->RecordSize
= RecordSize
;
501 InternalRecord
->ProducerHandle
= ProducerHandle
;
502 InternalRecord
->NumberOfStrings
= NumberOfStrings
;
504 // Insert record into the internal linked list
506 SmbiosEntry
->Signature
= EFI_SMBIOS_ENTRY_SIGNATURE
;
507 SmbiosEntry
->RecordHeader
= InternalRecord
;
508 SmbiosEntry
->RecordSize
= TotalSize
;
509 SmbiosEntry
->Smbios32BitTable
= Smbios32BitTable
;
510 SmbiosEntry
->Smbios64BitTable
= Smbios64BitTable
;
511 InsertTailList (&Private
->DataListHead
, &SmbiosEntry
->Link
);
513 CopyMem (Raw
, Record
, StructureSize
);
514 ((EFI_SMBIOS_TABLE_HEADER
*)Raw
)->Handle
= *SmbiosHandle
;
517 // Some UEFI drivers (such as network) need some information in SMBIOS table.
518 // Here we create SMBIOS table and publish it in
519 // configuration table, so other UEFI drivers can get SMBIOS table from
520 // configuration table without depending on PI SMBIOS protocol.
522 SmbiosTableConstruction (Smbios32BitTable
, Smbios64BitTable
);
525 // Leave critical section
527 EfiReleaseLock (&Private
->DataLock
);
532 Update the string associated with an existing SMBIOS record.
534 @param This The EFI_SMBIOS_PROTOCOL instance.
535 @param SmbiosHandle SMBIOS Handle of structure that will have its string updated.
536 @param StringNumber The non-zero string number of the string to update
537 @param String Update the StringNumber string with String.
539 @retval EFI_SUCCESS SmbiosHandle had its StringNumber String updated.
540 @retval EFI_INVALID_PARAMETER SmbiosHandle does not exist.
541 @retval EFI_UNSUPPORTED String was not added because it is longer than the SMBIOS Table supports.
542 @retval EFI_NOT_FOUND The StringNumber.is not valid for this SMBIOS record.
548 IN CONST EFI_SMBIOS_PROTOCOL
*This
,
549 IN EFI_SMBIOS_HANDLE
*SmbiosHandle
,
550 IN UINTN
*StringNumber
,
557 UINTN TargetStrOffset
;
564 SMBIOS_INSTANCE
*Private
;
565 EFI_SMBIOS_ENTRY
*SmbiosEntry
;
566 EFI_SMBIOS_ENTRY
*ResizedSmbiosEntry
;
567 EFI_SMBIOS_HANDLE MaxSmbiosHandle
;
568 EFI_SMBIOS_TABLE_HEADER
*Record
;
569 EFI_SMBIOS_RECORD_HEADER
*InternalRecord
;
572 // Check args validity
574 GetMaxSmbiosHandle(This
, &MaxSmbiosHandle
);
576 if (*SmbiosHandle
> MaxSmbiosHandle
) {
577 return EFI_INVALID_PARAMETER
;
580 if (String
== NULL
) {
584 if (*StringNumber
== 0) {
585 return EFI_NOT_FOUND
;
588 InputStrLen
= AsciiStrLen(String
);
590 if (This
->MajorVersion
< 2 || (This
->MajorVersion
== 2 && This
->MinorVersion
< 7)) {
591 if (InputStrLen
> SMBIOS_STRING_MAX_LENGTH
) {
592 return EFI_UNSUPPORTED
;
594 } else if (This
->MajorVersion
< 3) {
596 // Reference SMBIOS 2.7, chapter 6.1.3, it will have no limit on the length of each individual text string.
597 // However, the length of the entire structure table (including all strings) must be reported
598 // in the Structure Table Length field of the SMBIOS Structure Table Entry Point,
599 // which is a WORD field limited to 65,535 bytes.
601 if (InputStrLen
> SMBIOS_TABLE_MAX_LENGTH
) {
602 return EFI_UNSUPPORTED
;
605 if (InputStrLen
> SMBIOS_3_0_TABLE_MAX_LENGTH
) {
607 // SMBIOS 3.0 defines the Structure table maximum size as DWORD field limited to 0xFFFFFFFF bytes.
608 // The input string length should not exceed 0xFFFFFFFF bytes.
610 return EFI_UNSUPPORTED
;
614 Private
= SMBIOS_INSTANCE_FROM_THIS (This
);
616 // Enter into critical section
618 Status
= EfiAcquireLockOrFail (&Private
->DataLock
);
619 if (EFI_ERROR (Status
)) {
623 Head
= &Private
->DataListHead
;
624 for (Link
= Head
->ForwardLink
; Link
!= Head
; Link
= Link
->ForwardLink
) {
625 SmbiosEntry
= SMBIOS_ENTRY_FROM_LINK(Link
);
626 Record
= (EFI_SMBIOS_TABLE_HEADER
*)(SmbiosEntry
->RecordHeader
+ 1);
628 if (Record
->Handle
== *SmbiosHandle
) {
630 // Find out the specified SMBIOS record
632 if (*StringNumber
> SmbiosEntry
->RecordHeader
->NumberOfStrings
) {
633 EfiReleaseLock (&Private
->DataLock
);
634 return EFI_NOT_FOUND
;
637 // Point to unformed string section
639 StrStart
= (CHAR8
*) Record
+ Record
->Length
;
641 for (StrIndex
= 1, TargetStrOffset
= 0; StrIndex
< *StringNumber
; StrStart
++, TargetStrOffset
++) {
643 // A string ends in 00h
645 if (*StrStart
== 0) {
650 // String section ends in double-null (0000h)
652 if (*StrStart
== 0 && *(StrStart
+ 1) == 0) {
653 EfiReleaseLock (&Private
->DataLock
);
654 return EFI_NOT_FOUND
;
658 if (*StrStart
== 0) {
664 // Now we get the string target
666 TargetStrLen
= AsciiStrLen(StrStart
);
667 if (InputStrLen
== TargetStrLen
) {
668 AsciiStrCpy(StrStart
, String
);
670 // Some UEFI drivers (such as network) need some information in SMBIOS table.
671 // Here we create SMBIOS table and publish it in
672 // configuration table, so other UEFI drivers can get SMBIOS table from
673 // configuration table without depending on PI SMBIOS protocol.
675 SmbiosTableConstruction (SmbiosEntry
->Smbios32BitTable
, SmbiosEntry
->Smbios64BitTable
);
676 EfiReleaseLock (&Private
->DataLock
);
680 SmbiosEntry
->Smbios32BitTable
= FALSE
;
681 SmbiosEntry
->Smbios64BitTable
= FALSE
;
682 if ((This
->MajorVersion
< 0x3) ||
683 ((This
->MajorVersion
>= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod
) & BIT0
) == BIT0
))) {
685 // 32-bit table is produced, check the valid length.
687 if ((EntryPointStructure
!= NULL
) &&
688 (EntryPointStructure
->TableLength
+ InputStrLen
- TargetStrLen
> SMBIOS_TABLE_MAX_LENGTH
)) {
690 // The length of the entire structure table (including all strings) must be reported
691 // in the Structure Table Length field of the SMBIOS Structure Table Entry Point,
692 // which is a WORD field limited to 65,535 bytes.
694 DEBUG ((EFI_D_INFO
, "SmbiosUpdateString: Total length exceeds max 32-bit table length\n"));
696 DEBUG ((EFI_D_INFO
, "SmbiosUpdateString: New smbios record add to 32-bit table\n"));
697 SmbiosEntry
->Smbios32BitTable
= TRUE
;
701 if ((This
->MajorVersion
>= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod
) & BIT1
) == BIT1
)) {
703 // 64-bit table is produced, check the valid length.
705 if ((Smbios30EntryPointStructure
!= NULL
) &&
706 (Smbios30EntryPointStructure
->TableMaximumSize
+ InputStrLen
- TargetStrLen
> SMBIOS_3_0_TABLE_MAX_LENGTH
)) {
707 DEBUG ((EFI_D_INFO
, "SmbiosUpdateString: Total length exceeds max 64-bit table length\n"));
709 DEBUG ((EFI_D_INFO
, "SmbiosUpdateString: New smbios record add to 64-bit table\n"));
710 SmbiosEntry
->Smbios64BitTable
= TRUE
;
714 if ((!SmbiosEntry
->Smbios32BitTable
) && (!SmbiosEntry
->Smbios64BitTable
)) {
715 EfiReleaseLock (&Private
->DataLock
);
716 return EFI_UNSUPPORTED
;
720 // Original string buffer size is not exactly match input string length.
721 // Re-allocate buffer is needed.
723 NewEntrySize
= SmbiosEntry
->RecordSize
+ InputStrLen
- TargetStrLen
;
724 ResizedSmbiosEntry
= AllocateZeroPool (NewEntrySize
);
726 if (ResizedSmbiosEntry
== NULL
) {
727 EfiReleaseLock (&Private
->DataLock
);
728 return EFI_OUT_OF_RESOURCES
;
731 InternalRecord
= (EFI_SMBIOS_RECORD_HEADER
*) (ResizedSmbiosEntry
+ 1);
732 Raw
= (VOID
*) (InternalRecord
+ 1);
735 // Build internal record Header
737 InternalRecord
->Version
= EFI_SMBIOS_RECORD_HEADER_VERSION
;
738 InternalRecord
->HeaderSize
= (UINT16
) sizeof (EFI_SMBIOS_RECORD_HEADER
);
739 InternalRecord
->RecordSize
= SmbiosEntry
->RecordHeader
->RecordSize
+ InputStrLen
- TargetStrLen
;
740 InternalRecord
->ProducerHandle
= SmbiosEntry
->RecordHeader
->ProducerHandle
;
741 InternalRecord
->NumberOfStrings
= SmbiosEntry
->RecordHeader
->NumberOfStrings
;
744 // Copy SMBIOS structure and optional strings.
746 CopyMem (Raw
, SmbiosEntry
->RecordHeader
+ 1, Record
->Length
+ TargetStrOffset
);
747 CopyMem ((VOID
*)((UINTN
)Raw
+ Record
->Length
+ TargetStrOffset
), String
, InputStrLen
+ 1);
748 CopyMem ((CHAR8
*)((UINTN
)Raw
+ Record
->Length
+ TargetStrOffset
+ InputStrLen
+ 1),
749 (CHAR8
*)Record
+ Record
->Length
+ TargetStrOffset
+ TargetStrLen
+ 1,
750 SmbiosEntry
->RecordHeader
->RecordSize
- sizeof (EFI_SMBIOS_RECORD_HEADER
) - Record
->Length
- TargetStrOffset
- TargetStrLen
- 1);
755 ResizedSmbiosEntry
->Signature
= EFI_SMBIOS_ENTRY_SIGNATURE
;
756 ResizedSmbiosEntry
->RecordHeader
= InternalRecord
;
757 ResizedSmbiosEntry
->RecordSize
= NewEntrySize
;
758 ResizedSmbiosEntry
->Smbios32BitTable
= SmbiosEntry
->Smbios32BitTable
;
759 ResizedSmbiosEntry
->Smbios64BitTable
= SmbiosEntry
->Smbios64BitTable
;
760 InsertTailList (Link
->ForwardLink
, &ResizedSmbiosEntry
->Link
);
765 RemoveEntryList(Link
);
766 FreePool(SmbiosEntry
);
768 // Some UEFI drivers (such as network) need some information in SMBIOS table.
769 // Here we create SMBIOS table and publish it in
770 // configuration table, so other UEFI drivers can get SMBIOS table from
771 // configuration table without depending on PI SMBIOS protocol.
773 SmbiosTableConstruction (ResizedSmbiosEntry
->Smbios32BitTable
, ResizedSmbiosEntry
->Smbios64BitTable
);
774 EfiReleaseLock (&Private
->DataLock
);
779 EfiReleaseLock (&Private
->DataLock
);
780 return EFI_INVALID_PARAMETER
;
784 Remove an SMBIOS record.
786 @param This The EFI_SMBIOS_PROTOCOL instance.
787 @param SmbiosHandle The handle of the SMBIOS record to remove.
789 @retval EFI_SUCCESS SMBIOS record was removed.
790 @retval EFI_INVALID_PARAMETER SmbiosHandle does not specify a valid SMBIOS record.
796 IN CONST EFI_SMBIOS_PROTOCOL
*This
,
797 IN EFI_SMBIOS_HANDLE SmbiosHandle
803 EFI_SMBIOS_HANDLE MaxSmbiosHandle
;
804 SMBIOS_INSTANCE
*Private
;
805 EFI_SMBIOS_ENTRY
*SmbiosEntry
;
806 SMBIOS_HANDLE_ENTRY
*HandleEntry
;
807 EFI_SMBIOS_TABLE_HEADER
*Record
;
810 // Check args validity
812 GetMaxSmbiosHandle(This
, &MaxSmbiosHandle
);
814 if (SmbiosHandle
> MaxSmbiosHandle
) {
815 return EFI_INVALID_PARAMETER
;
818 Private
= SMBIOS_INSTANCE_FROM_THIS (This
);
820 // Enter into critical section
822 Status
= EfiAcquireLockOrFail (&Private
->DataLock
);
823 if (EFI_ERROR (Status
)) {
827 Head
= &Private
->DataListHead
;
828 for (Link
= Head
->ForwardLink
; Link
!= Head
; Link
= Link
->ForwardLink
) {
829 SmbiosEntry
= SMBIOS_ENTRY_FROM_LINK(Link
);
830 Record
= (EFI_SMBIOS_TABLE_HEADER
*)(SmbiosEntry
->RecordHeader
+ 1);
831 if (Record
->Handle
== SmbiosHandle
) {
833 // Remove specified smobios record from DataList
835 RemoveEntryList(Link
);
837 // Remove this handle from AllocatedHandleList
839 Head
= &Private
->AllocatedHandleListHead
;
840 for (Link
= Head
->ForwardLink
; Link
!= Head
; Link
= Link
->ForwardLink
) {
841 HandleEntry
= SMBIOS_HANDLE_ENTRY_FROM_LINK(Link
);
842 if (HandleEntry
->SmbiosHandle
== SmbiosHandle
) {
843 RemoveEntryList(Link
);
844 FreePool(HandleEntry
);
849 // Some UEFI drivers (such as network) need some information in SMBIOS table.
850 // Here we create SMBIOS table and publish it in
851 // configuration table, so other UEFI drivers can get SMBIOS table from
852 // configuration table without depending on PI SMBIOS protocol.
854 if (SmbiosEntry
->Smbios32BitTable
) {
855 DEBUG ((EFI_D_INFO
, "SmbiosRemove: remove from 32-bit table\n"));
857 if (SmbiosEntry
->Smbios64BitTable
) {
858 DEBUG ((EFI_D_INFO
, "SmbiosRemove: remove from 64-bit table\n"));
861 // Update the whole SMBIOS table again based on which table the removed SMBIOS record is in.
863 SmbiosTableConstruction (SmbiosEntry
->Smbios32BitTable
, SmbiosEntry
->Smbios64BitTable
);
864 FreePool(SmbiosEntry
);
865 EfiReleaseLock (&Private
->DataLock
);
871 // Leave critical section
873 EfiReleaseLock (&Private
->DataLock
);
874 return EFI_INVALID_PARAMETER
;
879 Allow the caller to discover all or some of the SMBIOS records.
881 @param This The EFI_SMBIOS_PROTOCOL instance.
882 @param SmbiosHandle On entry, points to the previous handle of the SMBIOS record. On exit, points to the
883 next SMBIOS record handle. If it is FFFEh on entry, then the first SMBIOS record
884 handle will be returned. If it returns FFFEh on exit, then there are no more SMBIOS records.
885 @param Type On entry it means return the next SMBIOS record of type Type. If a NULL is passed in
886 this functionally it ignored. Type is not modified by the GetNext() function.
887 @param Record On exit, points to the SMBIOS Record consisting of the formatted area followed by
888 the unformatted area. The unformatted area optionally contains text strings.
889 @param ProducerHandle On exit, points to the ProducerHandle registered by Add(). If no ProducerHandle was passed into Add() NULL is returned.
890 If a NULL pointer is passed in no data will be returned
892 @retval EFI_SUCCESS SMBIOS record information was successfully returned in Record.
893 @retval EFI_NOT_FOUND The SMBIOS record with SmbiosHandle was the last available record.
899 IN CONST EFI_SMBIOS_PROTOCOL
*This
,
900 IN OUT EFI_SMBIOS_HANDLE
*SmbiosHandle
,
901 IN EFI_SMBIOS_TYPE
*Type
, OPTIONAL
902 OUT EFI_SMBIOS_TABLE_HEADER
**Record
,
903 OUT EFI_HANDLE
*ProducerHandle OPTIONAL
906 BOOLEAN StartPointFound
;
909 SMBIOS_INSTANCE
*Private
;
910 EFI_SMBIOS_ENTRY
*SmbiosEntry
;
911 EFI_SMBIOS_TABLE_HEADER
*SmbiosTableHeader
;
913 if (SmbiosHandle
== NULL
) {
914 return EFI_INVALID_PARAMETER
;
917 StartPointFound
= FALSE
;
918 Private
= SMBIOS_INSTANCE_FROM_THIS (This
);
919 Head
= &Private
->DataListHead
;
920 for (Link
= Head
->ForwardLink
; Link
!= Head
; Link
= Link
->ForwardLink
) {
921 SmbiosEntry
= SMBIOS_ENTRY_FROM_LINK(Link
);
922 SmbiosTableHeader
= (EFI_SMBIOS_TABLE_HEADER
*)(SmbiosEntry
->RecordHeader
+ 1);
925 // If SmbiosHandle is 0xFFFE, the first matched SMBIOS record handle will be returned
927 if (*SmbiosHandle
== SMBIOS_HANDLE_PI_RESERVED
) {
928 if ((Type
!= NULL
) && (*Type
!= SmbiosTableHeader
->Type
)) {
932 *SmbiosHandle
= SmbiosTableHeader
->Handle
;
933 *Record
=SmbiosTableHeader
;
934 if (ProducerHandle
!= NULL
) {
935 *ProducerHandle
= SmbiosEntry
->RecordHeader
->ProducerHandle
;
941 // Start this round search from the next SMBIOS handle
943 if (!StartPointFound
&& (*SmbiosHandle
== SmbiosTableHeader
->Handle
)) {
944 StartPointFound
= TRUE
;
948 if (StartPointFound
) {
949 if ((Type
!= NULL
) && (*Type
!= SmbiosTableHeader
->Type
)) {
953 *SmbiosHandle
= SmbiosTableHeader
->Handle
;
954 *Record
= SmbiosTableHeader
;
955 if (ProducerHandle
!= NULL
) {
956 *ProducerHandle
= SmbiosEntry
->RecordHeader
->ProducerHandle
;
963 *SmbiosHandle
= SMBIOS_HANDLE_PI_RESERVED
;
964 return EFI_NOT_FOUND
;
969 Allow the caller to discover all of the SMBIOS records.
971 @param This The EFI_SMBIOS_PROTOCOL instance.
972 @param CurrentSmbiosEntry On exit, points to the SMBIOS entry on the list which includes the returned SMBIOS record information.
973 If *CurrentSmbiosEntry is NULL on entry, then the first SMBIOS entry on the list will be returned.
974 @param Record On exit, points to the SMBIOS Record consisting of the formatted area followed by
975 the unformatted area. The unformatted area optionally contains text strings.
977 @retval EFI_SUCCESS SMBIOS record information was successfully returned in Record.
978 *CurrentSmbiosEntry points to the SMBIOS entry which includes the returned SMBIOS record information.
979 @retval EFI_NOT_FOUND There is no more SMBIOS entry.
984 GetNextSmbiosRecord (
985 IN CONST EFI_SMBIOS_PROTOCOL
*This
,
986 IN OUT EFI_SMBIOS_ENTRY
**CurrentSmbiosEntry
,
987 OUT EFI_SMBIOS_TABLE_HEADER
**Record
992 SMBIOS_INSTANCE
*Private
;
993 EFI_SMBIOS_ENTRY
*SmbiosEntry
;
994 EFI_SMBIOS_TABLE_HEADER
*SmbiosTableHeader
;
996 Private
= SMBIOS_INSTANCE_FROM_THIS (This
);
997 if (*CurrentSmbiosEntry
== NULL
) {
999 // Get the beginning of SMBIOS entry.
1001 Head
= &Private
->DataListHead
;
1004 // Get previous SMBIOS entry and make it as start point.
1006 Head
= &(*CurrentSmbiosEntry
)->Link
;
1009 Link
= Head
->ForwardLink
;
1011 if (Link
== &Private
->DataListHead
) {
1013 // If no more SMBIOS entry in the list, return not found.
1015 return EFI_NOT_FOUND
;
1018 SmbiosEntry
= SMBIOS_ENTRY_FROM_LINK(Link
);
1019 SmbiosTableHeader
= (EFI_SMBIOS_TABLE_HEADER
*)(SmbiosEntry
->RecordHeader
+ 1);
1020 *Record
= SmbiosTableHeader
;
1021 *CurrentSmbiosEntry
= SmbiosEntry
;
1026 Assembles SMBIOS table from the SMBIOS protocol. Produce Table
1027 Entry Point and return the pointer to it.
1029 @param TableEntryPointStructure On exit, points to the SMBIOS entrypoint structure.
1031 @retval EFI_SUCCESS Structure created sucessfully.
1032 @retval EFI_OUT_OF_RESOURCES No enough memory.
1038 OUT VOID
**TableEntryPointStructure
1041 UINT8
*BufferPointer
;
1045 EFI_SMBIOS_HANDLE SmbiosHandle
;
1046 EFI_SMBIOS_PROTOCOL
*SmbiosProtocol
;
1047 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1048 EFI_SMBIOS_TABLE_HEADER
*SmbiosRecord
;
1049 EFI_SMBIOS_TABLE_END_STRUCTURE EndStructure
;
1050 EFI_SMBIOS_ENTRY
*CurrentSmbiosEntry
;
1052 Status
= EFI_SUCCESS
;
1053 BufferPointer
= NULL
;
1055 if (EntryPointStructure
== NULL
) {
1057 // Initialize the EntryPointStructure with initial values.
1058 // It should be done only once.
1059 // Allocate memory (below 4GB).
1061 DEBUG ((EFI_D_INFO
, "SmbiosCreateTable: Initialize 32-bit entry point structure\n"));
1062 EntryPointStructureData
.MajorVersion
= mPrivateData
.Smbios
.MajorVersion
;
1063 EntryPointStructureData
.MinorVersion
= mPrivateData
.Smbios
.MinorVersion
;
1064 EntryPointStructureData
.SmbiosBcdRevision
= (UINT8
) ((PcdGet16 (PcdSmbiosVersion
) >> 4) & 0xf0) | (UINT8
) (PcdGet16 (PcdSmbiosVersion
) & 0x0f);
1065 PhysicalAddress
= 0xffffffff;
1066 Status
= gBS
->AllocatePages (
1068 EfiRuntimeServicesData
,
1069 EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT
)),
1072 if (EFI_ERROR (Status
)) {
1073 DEBUG ((EFI_D_ERROR
, "SmbiosCreateTable () could not allocate EntryPointStructure < 4GB\n"));
1074 Status
= gBS
->AllocatePages (
1076 EfiRuntimeServicesData
,
1077 EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT
)),
1080 if (EFI_ERROR (Status
)) {
1081 return EFI_OUT_OF_RESOURCES
;
1085 EntryPointStructure
= (SMBIOS_TABLE_ENTRY_POINT
*) (UINTN
) PhysicalAddress
;
1088 EntryPointStructure
,
1089 &EntryPointStructureData
,
1090 sizeof (SMBIOS_TABLE_ENTRY_POINT
)
1095 // Get Smbios protocol to traverse SMBIOS records.
1097 SmbiosProtocol
= &mPrivateData
.Smbios
;
1100 // Make some statistics about all the structures
1102 EntryPointStructure
->NumberOfSmbiosStructures
= 0;
1103 EntryPointStructure
->TableLength
= 0;
1104 EntryPointStructure
->MaxStructureSize
= 0;
1107 // Calculate EPS Table Length
1109 CurrentSmbiosEntry
= NULL
;
1111 Status
= GetNextSmbiosRecord (SmbiosProtocol
, &CurrentSmbiosEntry
, &SmbiosRecord
);
1113 if ((Status
== EFI_SUCCESS
) && (CurrentSmbiosEntry
->Smbios32BitTable
)) {
1114 GetSmbiosStructureSize(SmbiosProtocol
, SmbiosRecord
, &RecordSize
, &NumOfStr
);
1116 // Record NumberOfSmbiosStructures, TableLength and MaxStructureSize
1118 EntryPointStructure
->NumberOfSmbiosStructures
++;
1119 EntryPointStructure
->TableLength
= (UINT16
) (EntryPointStructure
->TableLength
+ RecordSize
);
1120 if (RecordSize
> EntryPointStructure
->MaxStructureSize
) {
1121 EntryPointStructure
->MaxStructureSize
= (UINT16
) RecordSize
;
1124 } while (!EFI_ERROR(Status
));
1127 // Create End-Of-Table structure
1129 GetMaxSmbiosHandle(SmbiosProtocol
, &SmbiosHandle
);
1130 EndStructure
.Header
.Type
= EFI_SMBIOS_TYPE_END_OF_TABLE
;
1131 EndStructure
.Header
.Length
= (UINT8
) sizeof (EFI_SMBIOS_TABLE_HEADER
);
1132 EndStructure
.Header
.Handle
= SmbiosHandle
;
1133 EndStructure
.Tailing
[0] = 0;
1134 EndStructure
.Tailing
[1] = 0;
1135 EntryPointStructure
->NumberOfSmbiosStructures
++;
1136 EntryPointStructure
->TableLength
= (UINT16
) (EntryPointStructure
->TableLength
+ sizeof (EndStructure
));
1137 if (sizeof (EndStructure
) > EntryPointStructure
->MaxStructureSize
) {
1138 EntryPointStructure
->MaxStructureSize
= (UINT16
) sizeof (EndStructure
);
1141 if ((UINTN
) EFI_SIZE_TO_PAGES (EntryPointStructure
->TableLength
) > mPreAllocatedPages
) {
1143 // If new SMBIOS table size exceeds the previous allocated page,
1144 // it is time to re-allocate memory (below 4GB).
1146 DEBUG ((EFI_D_ERROR
, "SmbiosCreateTable() re-allocate SMBIOS 32-bit table\n"));
1147 if (EntryPointStructure
->TableAddress
!= 0) {
1149 // Free the previous allocated page
1152 (VOID
*)(UINTN
)EntryPointStructure
->TableAddress
,
1155 EntryPointStructure
->TableAddress
= 0;
1156 mPreAllocatedPages
= 0;
1159 PhysicalAddress
= 0xffffffff;
1160 Status
= gBS
->AllocatePages (
1162 EfiRuntimeServicesData
,
1163 EFI_SIZE_TO_PAGES (EntryPointStructure
->TableLength
),
1166 if (EFI_ERROR (Status
)) {
1167 DEBUG ((EFI_D_ERROR
, "SmbiosCreateTable() could not allocate SMBIOS table < 4GB\n"));
1168 EntryPointStructure
->TableAddress
= 0;
1169 return EFI_OUT_OF_RESOURCES
;
1171 EntryPointStructure
->TableAddress
= (UINT32
) PhysicalAddress
;
1172 mPreAllocatedPages
= EFI_SIZE_TO_PAGES (EntryPointStructure
->TableLength
);
1177 // Assemble the tables
1179 ASSERT (EntryPointStructure
->TableAddress
!= 0);
1180 BufferPointer
= (UINT8
*) (UINTN
) EntryPointStructure
->TableAddress
;
1181 CurrentSmbiosEntry
= NULL
;
1183 Status
= GetNextSmbiosRecord (SmbiosProtocol
, &CurrentSmbiosEntry
, &SmbiosRecord
);
1185 if ((Status
== EFI_SUCCESS
) && (CurrentSmbiosEntry
->Smbios32BitTable
)) {
1186 GetSmbiosStructureSize(SmbiosProtocol
, SmbiosRecord
, &RecordSize
, &NumOfStr
);
1187 CopyMem (BufferPointer
, SmbiosRecord
, RecordSize
);
1188 BufferPointer
= BufferPointer
+ RecordSize
;
1190 } while (!EFI_ERROR(Status
));
1193 // Assemble End-Of-Table structure
1195 CopyMem (BufferPointer
, &EndStructure
, sizeof (EndStructure
));
1198 // Fixup checksums in the Entry Point Structure
1200 EntryPointStructure
->IntermediateChecksum
= 0;
1201 EntryPointStructure
->EntryPointStructureChecksum
= 0;
1203 EntryPointStructure
->IntermediateChecksum
=
1204 CalculateCheckSum8 ((UINT8
*) EntryPointStructure
+ 0x10, EntryPointStructure
->EntryPointLength
- 0x10);
1205 EntryPointStructure
->EntryPointStructureChecksum
=
1206 CalculateCheckSum8 ((UINT8
*) EntryPointStructure
, EntryPointStructure
->EntryPointLength
);
1209 // Returns the pointer
1211 *TableEntryPointStructure
= EntryPointStructure
;
1217 Assembles SMBIOS 64-bit table from the SMBIOS protocol. Produce Table
1218 Entry Point and return the pointer to it.
1220 @param TableEntryPointStructure On exit, points to the SMBIOS entrypoint structure.
1222 @retval EFI_SUCCESS Structure created sucessfully.
1223 @retval EFI_OUT_OF_RESOURCES No enough memory.
1228 SmbiosCreate64BitTable (
1229 OUT VOID
**TableEntryPointStructure
1232 UINT8
*BufferPointer
;
1236 EFI_SMBIOS_HANDLE SmbiosHandle
;
1237 EFI_SMBIOS_PROTOCOL
*SmbiosProtocol
;
1238 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1239 EFI_SMBIOS_TABLE_HEADER
*SmbiosRecord
;
1240 EFI_SMBIOS_TABLE_END_STRUCTURE EndStructure
;
1241 EFI_SMBIOS_ENTRY
*CurrentSmbiosEntry
;
1243 Status
= EFI_SUCCESS
;
1244 BufferPointer
= NULL
;
1246 if (Smbios30EntryPointStructure
== NULL
) {
1248 // Initialize the Smbios30EntryPointStructure with initial values.
1249 // It should be done only once.
1250 // Allocate memory at any address.
1252 DEBUG ((EFI_D_INFO
, "SmbiosCreateTable: Initialize 64-bit entry point structure\n"));
1253 Smbios30EntryPointStructureData
.MajorVersion
= mPrivateData
.Smbios
.MajorVersion
;
1254 Smbios30EntryPointStructureData
.MinorVersion
= mPrivateData
.Smbios
.MinorVersion
;
1255 Smbios30EntryPointStructureData
.DocRev
= PcdGet8 (PcdSmbiosDocRev
);
1256 Status
= gBS
->AllocatePages (
1258 EfiRuntimeServicesData
,
1259 EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_3_0_ENTRY_POINT
)),
1262 if (EFI_ERROR (Status
)) {
1263 DEBUG ((EFI_D_ERROR
, "SmbiosCreate64BitTable() could not allocate Smbios30EntryPointStructure\n"));
1264 return EFI_OUT_OF_RESOURCES
;
1267 Smbios30EntryPointStructure
= (SMBIOS_TABLE_3_0_ENTRY_POINT
*) (UINTN
) PhysicalAddress
;
1270 Smbios30EntryPointStructure
,
1271 &Smbios30EntryPointStructureData
,
1272 sizeof (SMBIOS_TABLE_3_0_ENTRY_POINT
)
1277 // Get Smbios protocol to traverse SMBIOS records.
1279 SmbiosProtocol
= &mPrivateData
.Smbios
;
1280 Smbios30EntryPointStructure
->TableMaximumSize
= 0;
1283 // Calculate EPS Table Length
1285 CurrentSmbiosEntry
= NULL
;
1287 Status
= GetNextSmbiosRecord (SmbiosProtocol
, &CurrentSmbiosEntry
, &SmbiosRecord
);
1289 if ((Status
== EFI_SUCCESS
) && (CurrentSmbiosEntry
->Smbios64BitTable
)) {
1290 GetSmbiosStructureSize(SmbiosProtocol
, SmbiosRecord
, &RecordSize
, &NumOfStr
);
1292 // Record TableMaximumSize
1294 Smbios30EntryPointStructure
->TableMaximumSize
= (UINT32
) (Smbios30EntryPointStructure
->TableMaximumSize
+ RecordSize
);
1296 } while (!EFI_ERROR(Status
));
1299 // Create End-Of-Table structure
1301 GetMaxSmbiosHandle(SmbiosProtocol
, &SmbiosHandle
);
1302 EndStructure
.Header
.Type
= EFI_SMBIOS_TYPE_END_OF_TABLE
;
1303 EndStructure
.Header
.Length
= (UINT8
) sizeof (EFI_SMBIOS_TABLE_HEADER
);
1304 EndStructure
.Header
.Handle
= SmbiosHandle
;
1305 EndStructure
.Tailing
[0] = 0;
1306 EndStructure
.Tailing
[1] = 0;
1307 Smbios30EntryPointStructure
->TableMaximumSize
= (UINT32
) (Smbios30EntryPointStructure
->TableMaximumSize
+ sizeof (EndStructure
));
1309 if ((UINTN
) EFI_SIZE_TO_PAGES (Smbios30EntryPointStructure
->TableMaximumSize
) > mPre64BitAllocatedPages
) {
1311 // If new SMBIOS table size exceeds the previous allocated page,
1312 // it is time to re-allocate memory at anywhere.
1314 DEBUG ((EFI_D_ERROR
, "SmbiosCreate64BitTable() re-allocate SMBIOS 64-bit table\n"));
1315 if (Smbios30EntryPointStructure
->TableAddress
!= 0) {
1317 // Free the previous allocated page
1320 (VOID
*)(UINTN
)Smbios30EntryPointStructure
->TableAddress
,
1321 mPre64BitAllocatedPages
1323 Smbios30EntryPointStructure
->TableAddress
= 0;
1324 mPre64BitAllocatedPages
= 0;
1327 Status
= gBS
->AllocatePages (
1329 EfiRuntimeServicesData
,
1330 EFI_SIZE_TO_PAGES (Smbios30EntryPointStructure
->TableMaximumSize
),
1333 if (EFI_ERROR (Status
)) {
1334 DEBUG ((EFI_D_ERROR
, "SmbiosCreateTable() could not allocate SMBIOS 64-bit table\n"));
1335 Smbios30EntryPointStructure
->TableAddress
= 0;
1336 return EFI_OUT_OF_RESOURCES
;
1338 Smbios30EntryPointStructure
->TableAddress
= PhysicalAddress
;
1339 mPre64BitAllocatedPages
= EFI_SIZE_TO_PAGES (Smbios30EntryPointStructure
->TableMaximumSize
);
1344 // Assemble the tables
1346 ASSERT (Smbios30EntryPointStructure
->TableAddress
!= 0);
1347 BufferPointer
= (UINT8
*) (UINTN
) Smbios30EntryPointStructure
->TableAddress
;
1348 CurrentSmbiosEntry
= NULL
;
1350 Status
= GetNextSmbiosRecord (SmbiosProtocol
, &CurrentSmbiosEntry
, &SmbiosRecord
);
1352 if ((Status
== EFI_SUCCESS
) && (CurrentSmbiosEntry
->Smbios64BitTable
)) {
1354 // This record can be added to 64-bit table
1356 GetSmbiosStructureSize(SmbiosProtocol
, SmbiosRecord
, &RecordSize
, &NumOfStr
);
1357 CopyMem (BufferPointer
, SmbiosRecord
, RecordSize
);
1358 BufferPointer
= BufferPointer
+ RecordSize
;
1360 } while (!EFI_ERROR(Status
));
1363 // Assemble End-Of-Table structure
1365 CopyMem (BufferPointer
, &EndStructure
, sizeof (EndStructure
));
1368 // Fixup checksums in the Entry Point Structure
1370 Smbios30EntryPointStructure
->EntryPointStructureChecksum
= 0;
1371 Smbios30EntryPointStructure
->EntryPointStructureChecksum
=
1372 CalculateCheckSum8 ((UINT8
*) Smbios30EntryPointStructure
, Smbios30EntryPointStructure
->EntryPointLength
);
1375 // Returns the pointer
1377 *TableEntryPointStructure
= Smbios30EntryPointStructure
;
1383 Create Smbios Table and installs the Smbios Table to the System Table.
1385 @param Smbios32BitTable The flag to update 32-bit table.
1386 @param Smbios64BitTable The flag to update 64-bit table.
1391 SmbiosTableConstruction (
1392 BOOLEAN Smbios32BitTable
,
1393 BOOLEAN Smbios64BitTable
1400 if (Smbios32BitTable
) {
1401 Status
= SmbiosCreateTable ((VOID
**) &Eps
);
1402 if (!EFI_ERROR (Status
)) {
1403 gBS
->InstallConfigurationTable (&gEfiSmbiosTableGuid
, Eps
);
1407 if (Smbios64BitTable
) {
1408 Status
= SmbiosCreate64BitTable ((VOID
**) &Eps64Bit
);
1409 if (!EFI_ERROR (Status
)) {
1410 gBS
->InstallConfigurationTable (&gEfiSmbios3TableGuid
, Eps64Bit
);
1417 Driver to produce Smbios protocol and pre-allocate 1 page for the final SMBIOS table.
1419 @param ImageHandle Module's image handle
1420 @param SystemTable Pointer of EFI_SYSTEM_TABLE
1422 @retval EFI_SUCCESS Smbios protocol installed
1423 @retval Other No protocol installed, unload driver.
1428 SmbiosDriverEntryPoint (
1429 IN EFI_HANDLE ImageHandle
,
1430 IN EFI_SYSTEM_TABLE
*SystemTable
1435 mPrivateData
.Signature
= SMBIOS_INSTANCE_SIGNATURE
;
1436 mPrivateData
.Smbios
.Add
= SmbiosAdd
;
1437 mPrivateData
.Smbios
.UpdateString
= SmbiosUpdateString
;
1438 mPrivateData
.Smbios
.Remove
= SmbiosRemove
;
1439 mPrivateData
.Smbios
.GetNext
= SmbiosGetNext
;
1440 mPrivateData
.Smbios
.MajorVersion
= (UINT8
) (PcdGet16 (PcdSmbiosVersion
) >> 8);
1441 mPrivateData
.Smbios
.MinorVersion
= (UINT8
) (PcdGet16 (PcdSmbiosVersion
) & 0x00ff);
1443 InitializeListHead (&mPrivateData
.DataListHead
);
1444 InitializeListHead (&mPrivateData
.AllocatedHandleListHead
);
1445 EfiInitializeLock (&mPrivateData
.DataLock
, TPL_NOTIFY
);
1448 // Make a new handle and install the protocol
1450 mPrivateData
.Handle
= NULL
;
1451 Status
= gBS
->InstallProtocolInterface (
1452 &mPrivateData
.Handle
,
1453 &gEfiSmbiosProtocolGuid
,
1454 EFI_NATIVE_INTERFACE
,
1455 &mPrivateData
.Smbios