2 This code produces the Smbios protocol. It also responsible for constructing
3 SMBIOS table into system table.
5 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "SmbiosDxe.h"
14 // Since this driver will only ever produce one instance of the
15 // protocol you are not required to dynamically allocate the PrivateData.
17 SMBIOS_INSTANCE mPrivateData
;
19 UINTN mPreAllocatedPages
= 0;
20 UINTN mPre64BitAllocatedPages
= 0;
23 // Chassis for SMBIOS entry point structure that is to be installed into EFI system config table.
25 SMBIOS_TABLE_ENTRY_POINT
*EntryPointStructure
= NULL
;
26 SMBIOS_TABLE_ENTRY_POINT EntryPointStructureData
= {
37 // EntryPointStructureChecksum,TO BE FILLED
41 // EntryPointStructure Length
53 // MaxStructureSize, TO BE FILLED
71 // IntermediateAnchorString
81 // IntermediateChecksum, TO BE FILLED
85 // TableLength, TO BE FILLED
89 // TableAddress, TO BE FILLED
93 // NumberOfSmbiosStructures, TO BE FILLED
102 SMBIOS_TABLE_3_0_ENTRY_POINT
*Smbios30EntryPointStructure
= NULL
;
103 SMBIOS_TABLE_3_0_ENTRY_POINT Smbios30EntryPointStructureData
= {
105 // AnchorString _SM3_
115 // EntryPointStructureChecksum,TO BE FILLED
135 // EntryPointRevision
143 // TableMaximumSize,TO BE FILLED
147 // TableAddress,TO BE FILLED
153 Get the full size of SMBIOS structure including optional strings that follow the formatted structure.
155 @param This The EFI_SMBIOS_PROTOCOL instance.
156 @param Head Pointer to the beginning of SMBIOS structure.
157 @param Size The returned size.
158 @param NumberOfStrings The returned number of optional strings that follow the formatted structure.
160 @retval EFI_SUCCESS Size retured in Size.
161 @retval EFI_INVALID_PARAMETER Input SMBIOS structure mal-formed or Size is NULL.
166 GetSmbiosStructureSize (
167 IN CONST EFI_SMBIOS_PROTOCOL
*This
,
168 IN EFI_SMBIOS_TABLE_HEADER
*Head
,
170 OUT UINTN
*NumberOfStrings
178 if (Size
== NULL
|| NumberOfStrings
== NULL
) {
179 return EFI_INVALID_PARAMETER
;
182 FullSize
= Head
->Length
;
183 CharInStr
= (INT8
*)Head
+ Head
->Length
;
185 *NumberOfStrings
= 0;
188 // look for the two consecutive zeros, check the string limit by the way.
190 while (*CharInStr
!= 0 || *(CharInStr
+1) != 0) {
191 if (*CharInStr
== 0) {
196 if (This
->MajorVersion
< 2 || (This
->MajorVersion
== 2 && This
->MinorVersion
< 7)){
197 MaxLen
= SMBIOS_STRING_MAX_LENGTH
;
198 } else if (This
->MajorVersion
< 3) {
200 // Reference SMBIOS 2.7, chapter 6.1.3, it will have no limit on the length of each individual text string.
201 // However, the length of the entire structure table (including all strings) must be reported
202 // in the Structure Table Length field of the SMBIOS Structure Table Entry Point,
203 // which is a WORD field limited to 65,535 bytes.
205 MaxLen
= SMBIOS_TABLE_MAX_LENGTH
;
208 // SMBIOS 3.0 defines the Structure table maximum size as DWORD field limited to 0xFFFFFFFF bytes.
209 // Locate the end of string as long as possible.
211 MaxLen
= SMBIOS_3_0_TABLE_MAX_LENGTH
;
214 for (StrLen
= 0 ; StrLen
< MaxLen
; StrLen
++) {
215 if (*(CharInStr
+StrLen
) == 0) {
220 if (StrLen
== MaxLen
) {
221 return EFI_INVALID_PARAMETER
;
225 // forward the pointer
229 *NumberOfStrings
+= 1;
233 // count ending two zeros.
241 Determin whether an SmbiosHandle has already in use.
243 @param Head Pointer to the beginning of SMBIOS structure.
244 @param Handle A unique handle will be assigned to the SMBIOS record.
246 @retval TRUE Smbios handle already in use.
247 @retval FALSE Smbios handle is NOT used.
252 CheckSmbiosHandleExistance (
254 IN EFI_SMBIOS_HANDLE Handle
258 SMBIOS_HANDLE_ENTRY
*HandleEntry
;
260 for (Link
= Head
->ForwardLink
; Link
!= Head
; Link
= Link
->ForwardLink
) {
261 HandleEntry
= SMBIOS_HANDLE_ENTRY_FROM_LINK(Link
);
262 if (HandleEntry
->SmbiosHandle
== Handle
) {
272 Get the max SmbiosHandle that could be use.
274 @param This The EFI_SMBIOS_PROTOCOL instance.
275 @param MaxHandle The max handle that could be assigned to the SMBIOS record.
281 IN CONST EFI_SMBIOS_PROTOCOL
*This
,
282 IN OUT EFI_SMBIOS_HANDLE
*MaxHandle
285 if (This
->MajorVersion
== 2 && This
->MinorVersion
== 0) {
294 Get an SmbiosHandle that could use.
296 @param This The EFI_SMBIOS_PROTOCOL instance.
297 @param SmbiosHandle A unique handle will be assigned to the SMBIOS record.
299 @retval EFI_SUCCESS Smbios handle got.
300 @retval EFI_OUT_OF_RESOURCES Smbios handle is NOT available.
305 GetAvailableSmbiosHandle (
306 IN CONST EFI_SMBIOS_PROTOCOL
*This
,
307 IN OUT EFI_SMBIOS_HANDLE
*Handle
311 SMBIOS_INSTANCE
*Private
;
312 EFI_SMBIOS_HANDLE MaxSmbiosHandle
;
313 EFI_SMBIOS_HANDLE AvailableHandle
;
315 GetMaxSmbiosHandle(This
, &MaxSmbiosHandle
);
317 Private
= SMBIOS_INSTANCE_FROM_THIS (This
);
318 Head
= &Private
->AllocatedHandleListHead
;
319 for (AvailableHandle
= 0; AvailableHandle
< MaxSmbiosHandle
; AvailableHandle
++) {
320 if (!CheckSmbiosHandleExistance(Head
, AvailableHandle
)) {
321 *Handle
= AvailableHandle
;
326 return EFI_OUT_OF_RESOURCES
;
331 Add an SMBIOS record.
333 @param This The EFI_SMBIOS_PROTOCOL instance.
334 @param ProducerHandle The handle of the controller or driver associated with the SMBIOS information. NULL
336 @param SmbiosHandle On entry, the handle of the SMBIOS record to add. If FFFEh, then a unique handle
337 will be assigned to the SMBIOS record. If the SMBIOS handle is already in use,
338 EFI_ALREADY_STARTED is returned and the SMBIOS record is not updated.
339 @param Record The data for the fixed portion of the SMBIOS record. The format of the record is
340 determined by EFI_SMBIOS_TABLE_HEADER.Type. The size of the formatted area is defined
341 by EFI_SMBIOS_TABLE_HEADER.Length and either followed by a double-null (0x0000) or
342 a set of null terminated strings and a null.
344 @retval EFI_SUCCESS Record was added.
345 @retval EFI_OUT_OF_RESOURCES Record was not added due to lack of system resources.
346 @retval EFI_ALREADY_STARTED The SmbiosHandle passed in was already in use.
352 IN CONST EFI_SMBIOS_PROTOCOL
*This
,
353 IN EFI_HANDLE ProducerHandle
, OPTIONAL
354 IN OUT EFI_SMBIOS_HANDLE
*SmbiosHandle
,
355 IN EFI_SMBIOS_TABLE_HEADER
*Record
362 UINTN NumberOfStrings
;
365 SMBIOS_INSTANCE
*Private
;
366 EFI_SMBIOS_ENTRY
*SmbiosEntry
;
367 EFI_SMBIOS_HANDLE MaxSmbiosHandle
;
368 SMBIOS_HANDLE_ENTRY
*HandleEntry
;
369 EFI_SMBIOS_RECORD_HEADER
*InternalRecord
;
370 BOOLEAN Smbios32BitTable
;
371 BOOLEAN Smbios64BitTable
;
373 if (SmbiosHandle
== NULL
) {
374 return EFI_INVALID_PARAMETER
;
377 Private
= SMBIOS_INSTANCE_FROM_THIS (This
);
379 // Check whether SmbiosHandle is already in use
381 Head
= &Private
->AllocatedHandleListHead
;
382 if (*SmbiosHandle
!= SMBIOS_HANDLE_PI_RESERVED
&& CheckSmbiosHandleExistance(Head
, *SmbiosHandle
)) {
383 return EFI_ALREADY_STARTED
;
387 // when SmbiosHandle is 0xFFFE, an available handle will be assigned
389 if (*SmbiosHandle
== SMBIOS_HANDLE_PI_RESERVED
) {
390 Status
= GetAvailableSmbiosHandle(This
, SmbiosHandle
);
391 if (EFI_ERROR(Status
)) {
396 // Check this handle validity
398 GetMaxSmbiosHandle(This
, &MaxSmbiosHandle
);
399 if (*SmbiosHandle
> MaxSmbiosHandle
) {
400 return EFI_INVALID_PARAMETER
;
405 // Calculate record size and string number
407 Status
= GetSmbiosStructureSize(This
, Record
, &StructureSize
, &NumberOfStrings
);
408 if (EFI_ERROR(Status
)) {
412 Smbios32BitTable
= FALSE
;
413 Smbios64BitTable
= FALSE
;
414 if ((This
->MajorVersion
< 0x3) ||
415 ((This
->MajorVersion
>= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod
) & BIT0
) == BIT0
))) {
417 // For SMBIOS 32-bit table, the length of the entire structure table (including all strings) must be reported
418 // in the Structure Table Length field of the SMBIOS Structure Table Entry Point,
419 // which is a WORD field limited to 65,535 bytes. So the max size of 32-bit table should not exceed 65,535 bytes.
421 if ((EntryPointStructure
!= NULL
) &&
422 (EntryPointStructure
->TableLength
+ StructureSize
> SMBIOS_TABLE_MAX_LENGTH
)) {
423 DEBUG ((EFI_D_INFO
, "SmbiosAdd: Total length exceeds max 32-bit table length with type = %d size = 0x%x\n", Record
->Type
, StructureSize
));
425 Smbios32BitTable
= TRUE
;
426 DEBUG ((EFI_D_INFO
, "SmbiosAdd: Smbios type %d with size 0x%x is added to 32-bit table\n", Record
->Type
, StructureSize
));
431 // For SMBIOS 3.0, Structure table maximum size in Entry Point structure is DWORD field limited to 0xFFFFFFFF bytes.
433 if ((This
->MajorVersion
>= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod
) & BIT1
) == BIT1
)) {
435 // For SMBIOS 64-bit table, Structure table maximum size in SMBIOS 3.0 (64-bit) Entry Point
436 // is a DWORD field limited to 0xFFFFFFFF bytes. So the max size of 64-bit table should not exceed 0xFFFFFFFF bytes.
438 if ((Smbios30EntryPointStructure
!= NULL
) &&
439 (Smbios30EntryPointStructure
->TableMaximumSize
+ StructureSize
> SMBIOS_3_0_TABLE_MAX_LENGTH
)) {
440 DEBUG ((EFI_D_INFO
, "SmbiosAdd: Total length exceeds max 64-bit table length with type = %d size = 0x%x\n", Record
->Type
, StructureSize
));
442 DEBUG ((EFI_D_INFO
, "SmbiosAdd: Smbios type %d with size 0x%x is added to 64-bit table\n", Record
->Type
, StructureSize
));
443 Smbios64BitTable
= TRUE
;
447 if ((!Smbios32BitTable
) && (!Smbios64BitTable
)) {
449 // If both 32-bit and 64-bit table are not updated, quit
451 return EFI_OUT_OF_RESOURCES
;
455 // Enter into critical section
457 Status
= EfiAcquireLockOrFail (&Private
->DataLock
);
458 if (EFI_ERROR (Status
)) {
462 RecordSize
= sizeof (EFI_SMBIOS_RECORD_HEADER
) + StructureSize
;
463 TotalSize
= sizeof (EFI_SMBIOS_ENTRY
) + RecordSize
;
466 // Allocate internal buffer
468 SmbiosEntry
= AllocateZeroPool (TotalSize
);
469 if (SmbiosEntry
== NULL
) {
470 EfiReleaseLock (&Private
->DataLock
);
471 return EFI_OUT_OF_RESOURCES
;
473 HandleEntry
= AllocateZeroPool (sizeof(SMBIOS_HANDLE_ENTRY
));
474 if (HandleEntry
== NULL
) {
475 EfiReleaseLock (&Private
->DataLock
);
476 return EFI_OUT_OF_RESOURCES
;
480 // Build Handle Entry and insert into linked list
482 HandleEntry
->Signature
= SMBIOS_HANDLE_ENTRY_SIGNATURE
;
483 HandleEntry
->SmbiosHandle
= *SmbiosHandle
;
484 InsertTailList(&Private
->AllocatedHandleListHead
, &HandleEntry
->Link
);
486 InternalRecord
= (EFI_SMBIOS_RECORD_HEADER
*) (SmbiosEntry
+ 1);
487 Raw
= (VOID
*) (InternalRecord
+ 1);
490 // Build internal record Header
492 InternalRecord
->Version
= EFI_SMBIOS_RECORD_HEADER_VERSION
;
493 InternalRecord
->HeaderSize
= (UINT16
) sizeof (EFI_SMBIOS_RECORD_HEADER
);
494 InternalRecord
->RecordSize
= RecordSize
;
495 InternalRecord
->ProducerHandle
= ProducerHandle
;
496 InternalRecord
->NumberOfStrings
= NumberOfStrings
;
498 // Insert record into the internal linked list
500 SmbiosEntry
->Signature
= EFI_SMBIOS_ENTRY_SIGNATURE
;
501 SmbiosEntry
->RecordHeader
= InternalRecord
;
502 SmbiosEntry
->RecordSize
= TotalSize
;
503 SmbiosEntry
->Smbios32BitTable
= Smbios32BitTable
;
504 SmbiosEntry
->Smbios64BitTable
= Smbios64BitTable
;
505 InsertTailList (&Private
->DataListHead
, &SmbiosEntry
->Link
);
507 CopyMem (Raw
, Record
, StructureSize
);
508 ((EFI_SMBIOS_TABLE_HEADER
*)Raw
)->Handle
= *SmbiosHandle
;
511 // Some UEFI drivers (such as network) need some information in SMBIOS table.
512 // Here we create SMBIOS table and publish it in
513 // configuration table, so other UEFI drivers can get SMBIOS table from
514 // configuration table without depending on PI SMBIOS protocol.
516 SmbiosTableConstruction (Smbios32BitTable
, Smbios64BitTable
);
519 // Leave critical section
521 EfiReleaseLock (&Private
->DataLock
);
526 Update the string associated with an existing SMBIOS record.
528 @param This The EFI_SMBIOS_PROTOCOL instance.
529 @param SmbiosHandle SMBIOS Handle of structure that will have its string updated.
530 @param StringNumber The non-zero string number of the string to update
531 @param String Update the StringNumber string with String.
533 @retval EFI_SUCCESS SmbiosHandle had its StringNumber String updated.
534 @retval EFI_INVALID_PARAMETER SmbiosHandle does not exist.
535 @retval EFI_UNSUPPORTED String was not added because it is longer than the SMBIOS Table supports.
536 @retval EFI_NOT_FOUND The StringNumber.is not valid for this SMBIOS record.
542 IN CONST EFI_SMBIOS_PROTOCOL
*This
,
543 IN EFI_SMBIOS_HANDLE
*SmbiosHandle
,
544 IN UINTN
*StringNumber
,
551 UINTN TargetStrOffset
;
558 SMBIOS_INSTANCE
*Private
;
559 EFI_SMBIOS_ENTRY
*SmbiosEntry
;
560 EFI_SMBIOS_ENTRY
*ResizedSmbiosEntry
;
561 EFI_SMBIOS_HANDLE MaxSmbiosHandle
;
562 EFI_SMBIOS_TABLE_HEADER
*Record
;
563 EFI_SMBIOS_RECORD_HEADER
*InternalRecord
;
566 // Check args validity
568 GetMaxSmbiosHandle(This
, &MaxSmbiosHandle
);
570 if (*SmbiosHandle
> MaxSmbiosHandle
) {
571 return EFI_INVALID_PARAMETER
;
574 if (String
== NULL
) {
578 if (*StringNumber
== 0) {
579 return EFI_NOT_FOUND
;
582 InputStrLen
= AsciiStrLen(String
);
584 if (This
->MajorVersion
< 2 || (This
->MajorVersion
== 2 && This
->MinorVersion
< 7)) {
585 if (InputStrLen
> SMBIOS_STRING_MAX_LENGTH
) {
586 return EFI_UNSUPPORTED
;
588 } else if (This
->MajorVersion
< 3) {
590 // Reference SMBIOS 2.7, chapter 6.1.3, it will have no limit on the length of each individual text string.
591 // However, the length of the entire structure table (including all strings) must be reported
592 // in the Structure Table Length field of the SMBIOS Structure Table Entry Point,
593 // which is a WORD field limited to 65,535 bytes.
595 if (InputStrLen
> SMBIOS_TABLE_MAX_LENGTH
) {
596 return EFI_UNSUPPORTED
;
599 if (InputStrLen
> SMBIOS_3_0_TABLE_MAX_LENGTH
) {
601 // SMBIOS 3.0 defines the Structure table maximum size as DWORD field limited to 0xFFFFFFFF bytes.
602 // The input string length should not exceed 0xFFFFFFFF bytes.
604 return EFI_UNSUPPORTED
;
608 Private
= SMBIOS_INSTANCE_FROM_THIS (This
);
610 // Enter into critical section
612 Status
= EfiAcquireLockOrFail (&Private
->DataLock
);
613 if (EFI_ERROR (Status
)) {
617 Head
= &Private
->DataListHead
;
618 for (Link
= Head
->ForwardLink
; Link
!= Head
; Link
= Link
->ForwardLink
) {
619 SmbiosEntry
= SMBIOS_ENTRY_FROM_LINK(Link
);
620 Record
= (EFI_SMBIOS_TABLE_HEADER
*)(SmbiosEntry
->RecordHeader
+ 1);
622 if (Record
->Handle
== *SmbiosHandle
) {
624 // Find out the specified SMBIOS record
626 if (*StringNumber
> SmbiosEntry
->RecordHeader
->NumberOfStrings
) {
627 EfiReleaseLock (&Private
->DataLock
);
628 return EFI_NOT_FOUND
;
631 // Point to unformed string section
633 StrStart
= (CHAR8
*) Record
+ Record
->Length
;
635 for (StrIndex
= 1, TargetStrOffset
= 0; StrIndex
< *StringNumber
; StrStart
++, TargetStrOffset
++) {
637 // A string ends in 00h
639 if (*StrStart
== 0) {
644 // String section ends in double-null (0000h)
646 if (*StrStart
== 0 && *(StrStart
+ 1) == 0) {
647 EfiReleaseLock (&Private
->DataLock
);
648 return EFI_NOT_FOUND
;
652 if (*StrStart
== 0) {
658 // Now we get the string target
660 TargetStrLen
= AsciiStrLen(StrStart
);
661 if (InputStrLen
== TargetStrLen
) {
662 AsciiStrCpyS(StrStart
, TargetStrLen
+ 1, String
);
664 // Some UEFI drivers (such as network) need some information in SMBIOS table.
665 // Here we create SMBIOS table and publish it in
666 // configuration table, so other UEFI drivers can get SMBIOS table from
667 // configuration table without depending on PI SMBIOS protocol.
669 SmbiosTableConstruction (SmbiosEntry
->Smbios32BitTable
, SmbiosEntry
->Smbios64BitTable
);
670 EfiReleaseLock (&Private
->DataLock
);
674 SmbiosEntry
->Smbios32BitTable
= FALSE
;
675 SmbiosEntry
->Smbios64BitTable
= FALSE
;
676 if ((This
->MajorVersion
< 0x3) ||
677 ((This
->MajorVersion
>= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod
) & BIT0
) == BIT0
))) {
679 // 32-bit table is produced, check the valid length.
681 if ((EntryPointStructure
!= NULL
) &&
682 (EntryPointStructure
->TableLength
+ InputStrLen
- TargetStrLen
> SMBIOS_TABLE_MAX_LENGTH
)) {
684 // The length of the entire structure table (including all strings) must be reported
685 // in the Structure Table Length field of the SMBIOS Structure Table Entry Point,
686 // which is a WORD field limited to 65,535 bytes.
688 DEBUG ((EFI_D_INFO
, "SmbiosUpdateString: Total length exceeds max 32-bit table length\n"));
690 DEBUG ((EFI_D_INFO
, "SmbiosUpdateString: New smbios record add to 32-bit table\n"));
691 SmbiosEntry
->Smbios32BitTable
= TRUE
;
695 if ((This
->MajorVersion
>= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod
) & BIT1
) == BIT1
)) {
697 // 64-bit table is produced, check the valid length.
699 if ((Smbios30EntryPointStructure
!= NULL
) &&
700 (Smbios30EntryPointStructure
->TableMaximumSize
+ InputStrLen
- TargetStrLen
> SMBIOS_3_0_TABLE_MAX_LENGTH
)) {
701 DEBUG ((EFI_D_INFO
, "SmbiosUpdateString: Total length exceeds max 64-bit table length\n"));
703 DEBUG ((EFI_D_INFO
, "SmbiosUpdateString: New smbios record add to 64-bit table\n"));
704 SmbiosEntry
->Smbios64BitTable
= TRUE
;
708 if ((!SmbiosEntry
->Smbios32BitTable
) && (!SmbiosEntry
->Smbios64BitTable
)) {
709 EfiReleaseLock (&Private
->DataLock
);
710 return EFI_UNSUPPORTED
;
714 // Original string buffer size is not exactly match input string length.
715 // Re-allocate buffer is needed.
717 NewEntrySize
= SmbiosEntry
->RecordSize
+ InputStrLen
- TargetStrLen
;
718 ResizedSmbiosEntry
= AllocateZeroPool (NewEntrySize
);
720 if (ResizedSmbiosEntry
== NULL
) {
721 EfiReleaseLock (&Private
->DataLock
);
722 return EFI_OUT_OF_RESOURCES
;
725 InternalRecord
= (EFI_SMBIOS_RECORD_HEADER
*) (ResizedSmbiosEntry
+ 1);
726 Raw
= (VOID
*) (InternalRecord
+ 1);
729 // Build internal record Header
731 InternalRecord
->Version
= EFI_SMBIOS_RECORD_HEADER_VERSION
;
732 InternalRecord
->HeaderSize
= (UINT16
) sizeof (EFI_SMBIOS_RECORD_HEADER
);
733 InternalRecord
->RecordSize
= SmbiosEntry
->RecordHeader
->RecordSize
+ InputStrLen
- TargetStrLen
;
734 InternalRecord
->ProducerHandle
= SmbiosEntry
->RecordHeader
->ProducerHandle
;
735 InternalRecord
->NumberOfStrings
= SmbiosEntry
->RecordHeader
->NumberOfStrings
;
738 // Copy SMBIOS structure and optional strings.
740 CopyMem (Raw
, SmbiosEntry
->RecordHeader
+ 1, Record
->Length
+ TargetStrOffset
);
741 CopyMem ((VOID
*)((UINTN
)Raw
+ Record
->Length
+ TargetStrOffset
), String
, InputStrLen
+ 1);
742 CopyMem ((CHAR8
*)((UINTN
)Raw
+ Record
->Length
+ TargetStrOffset
+ InputStrLen
+ 1),
743 (CHAR8
*)Record
+ Record
->Length
+ TargetStrOffset
+ TargetStrLen
+ 1,
744 SmbiosEntry
->RecordHeader
->RecordSize
- sizeof (EFI_SMBIOS_RECORD_HEADER
) - Record
->Length
- TargetStrOffset
- TargetStrLen
- 1);
749 ResizedSmbiosEntry
->Signature
= EFI_SMBIOS_ENTRY_SIGNATURE
;
750 ResizedSmbiosEntry
->RecordHeader
= InternalRecord
;
751 ResizedSmbiosEntry
->RecordSize
= NewEntrySize
;
752 ResizedSmbiosEntry
->Smbios32BitTable
= SmbiosEntry
->Smbios32BitTable
;
753 ResizedSmbiosEntry
->Smbios64BitTable
= SmbiosEntry
->Smbios64BitTable
;
754 InsertTailList (Link
->ForwardLink
, &ResizedSmbiosEntry
->Link
);
759 RemoveEntryList(Link
);
760 FreePool(SmbiosEntry
);
762 // Some UEFI drivers (such as network) need some information in SMBIOS table.
763 // Here we create SMBIOS table and publish it in
764 // configuration table, so other UEFI drivers can get SMBIOS table from
765 // configuration table without depending on PI SMBIOS protocol.
767 SmbiosTableConstruction (ResizedSmbiosEntry
->Smbios32BitTable
, ResizedSmbiosEntry
->Smbios64BitTable
);
768 EfiReleaseLock (&Private
->DataLock
);
773 EfiReleaseLock (&Private
->DataLock
);
774 return EFI_INVALID_PARAMETER
;
778 Remove an SMBIOS record.
780 @param This The EFI_SMBIOS_PROTOCOL instance.
781 @param SmbiosHandle The handle of the SMBIOS record to remove.
783 @retval EFI_SUCCESS SMBIOS record was removed.
784 @retval EFI_INVALID_PARAMETER SmbiosHandle does not specify a valid SMBIOS record.
790 IN CONST EFI_SMBIOS_PROTOCOL
*This
,
791 IN EFI_SMBIOS_HANDLE SmbiosHandle
797 EFI_SMBIOS_HANDLE MaxSmbiosHandle
;
798 SMBIOS_INSTANCE
*Private
;
799 EFI_SMBIOS_ENTRY
*SmbiosEntry
;
800 SMBIOS_HANDLE_ENTRY
*HandleEntry
;
801 EFI_SMBIOS_TABLE_HEADER
*Record
;
804 // Check args validity
806 GetMaxSmbiosHandle(This
, &MaxSmbiosHandle
);
808 if (SmbiosHandle
> MaxSmbiosHandle
) {
809 return EFI_INVALID_PARAMETER
;
812 Private
= SMBIOS_INSTANCE_FROM_THIS (This
);
814 // Enter into critical section
816 Status
= EfiAcquireLockOrFail (&Private
->DataLock
);
817 if (EFI_ERROR (Status
)) {
821 Head
= &Private
->DataListHead
;
822 for (Link
= Head
->ForwardLink
; Link
!= Head
; Link
= Link
->ForwardLink
) {
823 SmbiosEntry
= SMBIOS_ENTRY_FROM_LINK(Link
);
824 Record
= (EFI_SMBIOS_TABLE_HEADER
*)(SmbiosEntry
->RecordHeader
+ 1);
825 if (Record
->Handle
== SmbiosHandle
) {
827 // Remove specified smobios record from DataList
829 RemoveEntryList(Link
);
831 // Remove this handle from AllocatedHandleList
833 Head
= &Private
->AllocatedHandleListHead
;
834 for (Link
= Head
->ForwardLink
; Link
!= Head
; Link
= Link
->ForwardLink
) {
835 HandleEntry
= SMBIOS_HANDLE_ENTRY_FROM_LINK(Link
);
836 if (HandleEntry
->SmbiosHandle
== SmbiosHandle
) {
837 RemoveEntryList(Link
);
838 FreePool(HandleEntry
);
843 // Some UEFI drivers (such as network) need some information in SMBIOS table.
844 // Here we create SMBIOS table and publish it in
845 // configuration table, so other UEFI drivers can get SMBIOS table from
846 // configuration table without depending on PI SMBIOS protocol.
848 if (SmbiosEntry
->Smbios32BitTable
) {
849 DEBUG ((EFI_D_INFO
, "SmbiosRemove: remove from 32-bit table\n"));
851 if (SmbiosEntry
->Smbios64BitTable
) {
852 DEBUG ((EFI_D_INFO
, "SmbiosRemove: remove from 64-bit table\n"));
855 // Update the whole SMBIOS table again based on which table the removed SMBIOS record is in.
857 SmbiosTableConstruction (SmbiosEntry
->Smbios32BitTable
, SmbiosEntry
->Smbios64BitTable
);
858 FreePool(SmbiosEntry
);
859 EfiReleaseLock (&Private
->DataLock
);
865 // Leave critical section
867 EfiReleaseLock (&Private
->DataLock
);
868 return EFI_INVALID_PARAMETER
;
873 Allow the caller to discover all or some of the SMBIOS records.
875 @param This The EFI_SMBIOS_PROTOCOL instance.
876 @param SmbiosHandle On entry, points to the previous handle of the SMBIOS record. On exit, points to the
877 next SMBIOS record handle. If it is FFFEh on entry, then the first SMBIOS record
878 handle will be returned. If it returns FFFEh on exit, then there are no more SMBIOS records.
879 @param Type On entry it means return the next SMBIOS record of type Type. If a NULL is passed in
880 this functionally it ignored. Type is not modified by the GetNext() function.
881 @param Record On exit, points to the SMBIOS Record consisting of the formatted area followed by
882 the unformatted area. The unformatted area optionally contains text strings.
883 @param ProducerHandle On exit, points to the ProducerHandle registered by Add(). If no ProducerHandle was passed into Add() NULL is returned.
884 If a NULL pointer is passed in no data will be returned
886 @retval EFI_SUCCESS SMBIOS record information was successfully returned in Record.
887 @retval EFI_NOT_FOUND The SMBIOS record with SmbiosHandle was the last available record.
893 IN CONST EFI_SMBIOS_PROTOCOL
*This
,
894 IN OUT EFI_SMBIOS_HANDLE
*SmbiosHandle
,
895 IN EFI_SMBIOS_TYPE
*Type
, OPTIONAL
896 OUT EFI_SMBIOS_TABLE_HEADER
**Record
,
897 OUT EFI_HANDLE
*ProducerHandle OPTIONAL
900 BOOLEAN StartPointFound
;
903 SMBIOS_INSTANCE
*Private
;
904 EFI_SMBIOS_ENTRY
*SmbiosEntry
;
905 EFI_SMBIOS_TABLE_HEADER
*SmbiosTableHeader
;
907 if (SmbiosHandle
== NULL
) {
908 return EFI_INVALID_PARAMETER
;
911 StartPointFound
= FALSE
;
912 Private
= SMBIOS_INSTANCE_FROM_THIS (This
);
913 Head
= &Private
->DataListHead
;
914 for (Link
= Head
->ForwardLink
; Link
!= Head
; Link
= Link
->ForwardLink
) {
915 SmbiosEntry
= SMBIOS_ENTRY_FROM_LINK(Link
);
916 SmbiosTableHeader
= (EFI_SMBIOS_TABLE_HEADER
*)(SmbiosEntry
->RecordHeader
+ 1);
919 // If SmbiosHandle is 0xFFFE, the first matched SMBIOS record handle will be returned
921 if (*SmbiosHandle
== SMBIOS_HANDLE_PI_RESERVED
) {
922 if ((Type
!= NULL
) && (*Type
!= SmbiosTableHeader
->Type
)) {
926 *SmbiosHandle
= SmbiosTableHeader
->Handle
;
927 *Record
=SmbiosTableHeader
;
928 if (ProducerHandle
!= NULL
) {
929 *ProducerHandle
= SmbiosEntry
->RecordHeader
->ProducerHandle
;
935 // Start this round search from the next SMBIOS handle
937 if (!StartPointFound
&& (*SmbiosHandle
== SmbiosTableHeader
->Handle
)) {
938 StartPointFound
= TRUE
;
942 if (StartPointFound
) {
943 if ((Type
!= NULL
) && (*Type
!= SmbiosTableHeader
->Type
)) {
947 *SmbiosHandle
= SmbiosTableHeader
->Handle
;
948 *Record
= SmbiosTableHeader
;
949 if (ProducerHandle
!= NULL
) {
950 *ProducerHandle
= SmbiosEntry
->RecordHeader
->ProducerHandle
;
957 *SmbiosHandle
= SMBIOS_HANDLE_PI_RESERVED
;
958 return EFI_NOT_FOUND
;
963 Allow the caller to discover all of the SMBIOS records.
965 @param This The EFI_SMBIOS_PROTOCOL instance.
966 @param CurrentSmbiosEntry On exit, points to the SMBIOS entry on the list which includes the returned SMBIOS record information.
967 If *CurrentSmbiosEntry is NULL on entry, then the first SMBIOS entry on the list will be returned.
968 @param Record On exit, points to the SMBIOS Record consisting of the formatted area followed by
969 the unformatted area. The unformatted area optionally contains text strings.
971 @retval EFI_SUCCESS SMBIOS record information was successfully returned in Record.
972 *CurrentSmbiosEntry points to the SMBIOS entry which includes the returned SMBIOS record information.
973 @retval EFI_NOT_FOUND There is no more SMBIOS entry.
978 GetNextSmbiosRecord (
979 IN CONST EFI_SMBIOS_PROTOCOL
*This
,
980 IN OUT EFI_SMBIOS_ENTRY
**CurrentSmbiosEntry
,
981 OUT EFI_SMBIOS_TABLE_HEADER
**Record
986 SMBIOS_INSTANCE
*Private
;
987 EFI_SMBIOS_ENTRY
*SmbiosEntry
;
988 EFI_SMBIOS_TABLE_HEADER
*SmbiosTableHeader
;
990 Private
= SMBIOS_INSTANCE_FROM_THIS (This
);
991 if (*CurrentSmbiosEntry
== NULL
) {
993 // Get the beginning of SMBIOS entry.
995 Head
= &Private
->DataListHead
;
998 // Get previous SMBIOS entry and make it as start point.
1000 Head
= &(*CurrentSmbiosEntry
)->Link
;
1003 Link
= Head
->ForwardLink
;
1005 if (Link
== &Private
->DataListHead
) {
1007 // If no more SMBIOS entry in the list, return not found.
1009 return EFI_NOT_FOUND
;
1012 SmbiosEntry
= SMBIOS_ENTRY_FROM_LINK(Link
);
1013 SmbiosTableHeader
= (EFI_SMBIOS_TABLE_HEADER
*)(SmbiosEntry
->RecordHeader
+ 1);
1014 *Record
= SmbiosTableHeader
;
1015 *CurrentSmbiosEntry
= SmbiosEntry
;
1020 Assembles SMBIOS table from the SMBIOS protocol. Produce Table
1021 Entry Point and return the pointer to it.
1023 @param TableEntryPointStructure On exit, points to the SMBIOS entrypoint structure.
1025 @retval EFI_SUCCESS Structure created sucessfully.
1026 @retval EFI_OUT_OF_RESOURCES No enough memory.
1032 OUT VOID
**TableEntryPointStructure
1035 UINT8
*BufferPointer
;
1039 EFI_SMBIOS_HANDLE SmbiosHandle
;
1040 EFI_SMBIOS_PROTOCOL
*SmbiosProtocol
;
1041 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1042 EFI_SMBIOS_TABLE_HEADER
*SmbiosRecord
;
1043 EFI_SMBIOS_TABLE_END_STRUCTURE EndStructure
;
1044 EFI_SMBIOS_ENTRY
*CurrentSmbiosEntry
;
1046 Status
= EFI_SUCCESS
;
1047 BufferPointer
= NULL
;
1049 if (EntryPointStructure
== NULL
) {
1051 // Initialize the EntryPointStructure with initial values.
1052 // It should be done only once.
1053 // Allocate memory (below 4GB).
1055 DEBUG ((EFI_D_INFO
, "SmbiosCreateTable: Initialize 32-bit entry point structure\n"));
1056 EntryPointStructureData
.MajorVersion
= mPrivateData
.Smbios
.MajorVersion
;
1057 EntryPointStructureData
.MinorVersion
= mPrivateData
.Smbios
.MinorVersion
;
1058 EntryPointStructureData
.SmbiosBcdRevision
= (UINT8
) ((PcdGet16 (PcdSmbiosVersion
) >> 4) & 0xf0) | (UINT8
) (PcdGet16 (PcdSmbiosVersion
) & 0x0f);
1059 PhysicalAddress
= 0xffffffff;
1060 Status
= gBS
->AllocatePages (
1062 EfiRuntimeServicesData
,
1063 EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT
)),
1066 if (EFI_ERROR (Status
)) {
1067 DEBUG ((EFI_D_ERROR
, "SmbiosCreateTable () could not allocate EntryPointStructure < 4GB\n"));
1068 Status
= gBS
->AllocatePages (
1070 EfiRuntimeServicesData
,
1071 EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT
)),
1074 if (EFI_ERROR (Status
)) {
1075 return EFI_OUT_OF_RESOURCES
;
1079 EntryPointStructure
= (SMBIOS_TABLE_ENTRY_POINT
*) (UINTN
) PhysicalAddress
;
1082 EntryPointStructure
,
1083 &EntryPointStructureData
,
1084 sizeof (SMBIOS_TABLE_ENTRY_POINT
)
1089 // Get Smbios protocol to traverse SMBIOS records.
1091 SmbiosProtocol
= &mPrivateData
.Smbios
;
1094 // Make some statistics about all the structures
1096 EntryPointStructure
->NumberOfSmbiosStructures
= 0;
1097 EntryPointStructure
->TableLength
= 0;
1098 EntryPointStructure
->MaxStructureSize
= 0;
1101 // Calculate EPS Table Length
1103 CurrentSmbiosEntry
= NULL
;
1105 Status
= GetNextSmbiosRecord (SmbiosProtocol
, &CurrentSmbiosEntry
, &SmbiosRecord
);
1107 if ((Status
== EFI_SUCCESS
) && (CurrentSmbiosEntry
->Smbios32BitTable
)) {
1108 GetSmbiosStructureSize(SmbiosProtocol
, SmbiosRecord
, &RecordSize
, &NumOfStr
);
1110 // Record NumberOfSmbiosStructures, TableLength and MaxStructureSize
1112 EntryPointStructure
->NumberOfSmbiosStructures
++;
1113 EntryPointStructure
->TableLength
= (UINT16
) (EntryPointStructure
->TableLength
+ RecordSize
);
1114 if (RecordSize
> EntryPointStructure
->MaxStructureSize
) {
1115 EntryPointStructure
->MaxStructureSize
= (UINT16
) RecordSize
;
1118 } while (!EFI_ERROR(Status
));
1121 // Create End-Of-Table structure
1123 GetMaxSmbiosHandle(SmbiosProtocol
, &SmbiosHandle
);
1124 EndStructure
.Header
.Type
= SMBIOS_TYPE_END_OF_TABLE
;
1125 EndStructure
.Header
.Length
= (UINT8
) sizeof (EFI_SMBIOS_TABLE_HEADER
);
1126 EndStructure
.Header
.Handle
= SmbiosHandle
;
1127 EndStructure
.Tailing
[0] = 0;
1128 EndStructure
.Tailing
[1] = 0;
1129 EntryPointStructure
->NumberOfSmbiosStructures
++;
1130 EntryPointStructure
->TableLength
= (UINT16
) (EntryPointStructure
->TableLength
+ sizeof (EndStructure
));
1131 if (sizeof (EndStructure
) > EntryPointStructure
->MaxStructureSize
) {
1132 EntryPointStructure
->MaxStructureSize
= (UINT16
) sizeof (EndStructure
);
1135 if (EFI_SIZE_TO_PAGES ((UINT32
) EntryPointStructure
->TableLength
) > mPreAllocatedPages
) {
1137 // If new SMBIOS table size exceeds the previous allocated page,
1138 // it is time to re-allocate memory (below 4GB).
1140 DEBUG ((EFI_D_INFO
, "%a() re-allocate SMBIOS 32-bit table\n",
1142 if (EntryPointStructure
->TableAddress
!= 0) {
1144 // Free the previous allocated page
1147 (VOID
*)(UINTN
)EntryPointStructure
->TableAddress
,
1150 EntryPointStructure
->TableAddress
= 0;
1151 mPreAllocatedPages
= 0;
1154 PhysicalAddress
= 0xffffffff;
1155 Status
= gBS
->AllocatePages (
1157 EfiRuntimeServicesData
,
1158 EFI_SIZE_TO_PAGES (EntryPointStructure
->TableLength
),
1161 if (EFI_ERROR (Status
)) {
1162 DEBUG ((EFI_D_ERROR
, "SmbiosCreateTable() could not allocate SMBIOS table < 4GB\n"));
1163 EntryPointStructure
->TableAddress
= 0;
1164 return EFI_OUT_OF_RESOURCES
;
1166 EntryPointStructure
->TableAddress
= (UINT32
) PhysicalAddress
;
1167 mPreAllocatedPages
= EFI_SIZE_TO_PAGES (EntryPointStructure
->TableLength
);
1172 // Assemble the tables
1174 ASSERT (EntryPointStructure
->TableAddress
!= 0);
1175 BufferPointer
= (UINT8
*) (UINTN
) EntryPointStructure
->TableAddress
;
1176 CurrentSmbiosEntry
= NULL
;
1178 Status
= GetNextSmbiosRecord (SmbiosProtocol
, &CurrentSmbiosEntry
, &SmbiosRecord
);
1180 if ((Status
== EFI_SUCCESS
) && (CurrentSmbiosEntry
->Smbios32BitTable
)) {
1181 GetSmbiosStructureSize(SmbiosProtocol
, SmbiosRecord
, &RecordSize
, &NumOfStr
);
1182 CopyMem (BufferPointer
, SmbiosRecord
, RecordSize
);
1183 BufferPointer
= BufferPointer
+ RecordSize
;
1185 } while (!EFI_ERROR(Status
));
1188 // Assemble End-Of-Table structure
1190 CopyMem (BufferPointer
, &EndStructure
, sizeof (EndStructure
));
1193 // Fixup checksums in the Entry Point Structure
1195 EntryPointStructure
->IntermediateChecksum
= 0;
1196 EntryPointStructure
->EntryPointStructureChecksum
= 0;
1198 EntryPointStructure
->IntermediateChecksum
=
1199 CalculateCheckSum8 ((UINT8
*) EntryPointStructure
+ 0x10, EntryPointStructure
->EntryPointLength
- 0x10);
1200 EntryPointStructure
->EntryPointStructureChecksum
=
1201 CalculateCheckSum8 ((UINT8
*) EntryPointStructure
, EntryPointStructure
->EntryPointLength
);
1204 // Returns the pointer
1206 *TableEntryPointStructure
= EntryPointStructure
;
1212 Assembles SMBIOS 64-bit table from the SMBIOS protocol. Produce Table
1213 Entry Point and return the pointer to it.
1215 @param TableEntryPointStructure On exit, points to the SMBIOS entrypoint structure.
1217 @retval EFI_SUCCESS Structure created sucessfully.
1218 @retval EFI_OUT_OF_RESOURCES No enough memory.
1223 SmbiosCreate64BitTable (
1224 OUT VOID
**TableEntryPointStructure
1227 UINT8
*BufferPointer
;
1231 EFI_SMBIOS_HANDLE SmbiosHandle
;
1232 EFI_SMBIOS_PROTOCOL
*SmbiosProtocol
;
1233 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
1234 EFI_SMBIOS_TABLE_HEADER
*SmbiosRecord
;
1235 EFI_SMBIOS_TABLE_END_STRUCTURE EndStructure
;
1236 EFI_SMBIOS_ENTRY
*CurrentSmbiosEntry
;
1238 Status
= EFI_SUCCESS
;
1239 BufferPointer
= NULL
;
1241 if (Smbios30EntryPointStructure
== NULL
) {
1243 // Initialize the Smbios30EntryPointStructure with initial values.
1244 // It should be done only once.
1245 // Allocate memory at any address.
1247 DEBUG ((EFI_D_INFO
, "SmbiosCreateTable: Initialize 64-bit entry point structure\n"));
1248 Smbios30EntryPointStructureData
.MajorVersion
= mPrivateData
.Smbios
.MajorVersion
;
1249 Smbios30EntryPointStructureData
.MinorVersion
= mPrivateData
.Smbios
.MinorVersion
;
1250 Smbios30EntryPointStructureData
.DocRev
= PcdGet8 (PcdSmbiosDocRev
);
1251 Status
= gBS
->AllocatePages (
1253 EfiRuntimeServicesData
,
1254 EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_3_0_ENTRY_POINT
)),
1257 if (EFI_ERROR (Status
)) {
1258 DEBUG ((EFI_D_ERROR
, "SmbiosCreate64BitTable() could not allocate Smbios30EntryPointStructure\n"));
1259 return EFI_OUT_OF_RESOURCES
;
1262 Smbios30EntryPointStructure
= (SMBIOS_TABLE_3_0_ENTRY_POINT
*) (UINTN
) PhysicalAddress
;
1265 Smbios30EntryPointStructure
,
1266 &Smbios30EntryPointStructureData
,
1267 sizeof (SMBIOS_TABLE_3_0_ENTRY_POINT
)
1272 // Get Smbios protocol to traverse SMBIOS records.
1274 SmbiosProtocol
= &mPrivateData
.Smbios
;
1275 Smbios30EntryPointStructure
->TableMaximumSize
= 0;
1278 // Calculate EPS Table Length
1280 CurrentSmbiosEntry
= NULL
;
1282 Status
= GetNextSmbiosRecord (SmbiosProtocol
, &CurrentSmbiosEntry
, &SmbiosRecord
);
1284 if ((Status
== EFI_SUCCESS
) && (CurrentSmbiosEntry
->Smbios64BitTable
)) {
1285 GetSmbiosStructureSize(SmbiosProtocol
, SmbiosRecord
, &RecordSize
, &NumOfStr
);
1287 // Record TableMaximumSize
1289 Smbios30EntryPointStructure
->TableMaximumSize
= (UINT32
) (Smbios30EntryPointStructure
->TableMaximumSize
+ RecordSize
);
1291 } while (!EFI_ERROR(Status
));
1294 // Create End-Of-Table structure
1296 GetMaxSmbiosHandle(SmbiosProtocol
, &SmbiosHandle
);
1297 EndStructure
.Header
.Type
= SMBIOS_TYPE_END_OF_TABLE
;
1298 EndStructure
.Header
.Length
= (UINT8
) sizeof (EFI_SMBIOS_TABLE_HEADER
);
1299 EndStructure
.Header
.Handle
= SmbiosHandle
;
1300 EndStructure
.Tailing
[0] = 0;
1301 EndStructure
.Tailing
[1] = 0;
1302 Smbios30EntryPointStructure
->TableMaximumSize
= (UINT32
) (Smbios30EntryPointStructure
->TableMaximumSize
+ sizeof (EndStructure
));
1304 if (EFI_SIZE_TO_PAGES (Smbios30EntryPointStructure
->TableMaximumSize
) > mPre64BitAllocatedPages
) {
1306 // If new SMBIOS table size exceeds the previous allocated page,
1307 // it is time to re-allocate memory at anywhere.
1309 DEBUG ((EFI_D_INFO
, "%a() re-allocate SMBIOS 64-bit table\n",
1311 if (Smbios30EntryPointStructure
->TableAddress
!= 0) {
1313 // Free the previous allocated page
1316 (VOID
*)(UINTN
)Smbios30EntryPointStructure
->TableAddress
,
1317 mPre64BitAllocatedPages
1319 Smbios30EntryPointStructure
->TableAddress
= 0;
1320 mPre64BitAllocatedPages
= 0;
1323 Status
= gBS
->AllocatePages (
1325 EfiRuntimeServicesData
,
1326 EFI_SIZE_TO_PAGES (Smbios30EntryPointStructure
->TableMaximumSize
),
1329 if (EFI_ERROR (Status
)) {
1330 DEBUG ((EFI_D_ERROR
, "SmbiosCreateTable() could not allocate SMBIOS 64-bit table\n"));
1331 Smbios30EntryPointStructure
->TableAddress
= 0;
1332 return EFI_OUT_OF_RESOURCES
;
1334 Smbios30EntryPointStructure
->TableAddress
= PhysicalAddress
;
1335 mPre64BitAllocatedPages
= EFI_SIZE_TO_PAGES (Smbios30EntryPointStructure
->TableMaximumSize
);
1340 // Assemble the tables
1342 ASSERT (Smbios30EntryPointStructure
->TableAddress
!= 0);
1343 BufferPointer
= (UINT8
*) (UINTN
) Smbios30EntryPointStructure
->TableAddress
;
1344 CurrentSmbiosEntry
= NULL
;
1346 Status
= GetNextSmbiosRecord (SmbiosProtocol
, &CurrentSmbiosEntry
, &SmbiosRecord
);
1348 if ((Status
== EFI_SUCCESS
) && (CurrentSmbiosEntry
->Smbios64BitTable
)) {
1350 // This record can be added to 64-bit table
1352 GetSmbiosStructureSize(SmbiosProtocol
, SmbiosRecord
, &RecordSize
, &NumOfStr
);
1353 CopyMem (BufferPointer
, SmbiosRecord
, RecordSize
);
1354 BufferPointer
= BufferPointer
+ RecordSize
;
1356 } while (!EFI_ERROR(Status
));
1359 // Assemble End-Of-Table structure
1361 CopyMem (BufferPointer
, &EndStructure
, sizeof (EndStructure
));
1364 // Fixup checksums in the Entry Point Structure
1366 Smbios30EntryPointStructure
->EntryPointStructureChecksum
= 0;
1367 Smbios30EntryPointStructure
->EntryPointStructureChecksum
=
1368 CalculateCheckSum8 ((UINT8
*) Smbios30EntryPointStructure
, Smbios30EntryPointStructure
->EntryPointLength
);
1371 // Returns the pointer
1373 *TableEntryPointStructure
= Smbios30EntryPointStructure
;
1379 Create Smbios Table and installs the Smbios Table to the System Table.
1381 @param Smbios32BitTable The flag to update 32-bit table.
1382 @param Smbios64BitTable The flag to update 64-bit table.
1387 SmbiosTableConstruction (
1388 BOOLEAN Smbios32BitTable
,
1389 BOOLEAN Smbios64BitTable
1396 if (Smbios32BitTable
) {
1397 Status
= SmbiosCreateTable ((VOID
**) &Eps
);
1398 if (!EFI_ERROR (Status
)) {
1399 gBS
->InstallConfigurationTable (&gEfiSmbiosTableGuid
, Eps
);
1403 if (Smbios64BitTable
) {
1404 Status
= SmbiosCreate64BitTable ((VOID
**) &Eps64Bit
);
1405 if (!EFI_ERROR (Status
)) {
1406 gBS
->InstallConfigurationTable (&gEfiSmbios3TableGuid
, Eps64Bit
);
1413 Driver to produce Smbios protocol and pre-allocate 1 page for the final SMBIOS table.
1415 @param ImageHandle Module's image handle
1416 @param SystemTable Pointer of EFI_SYSTEM_TABLE
1418 @retval EFI_SUCCESS Smbios protocol installed
1419 @retval Other No protocol installed, unload driver.
1424 SmbiosDriverEntryPoint (
1425 IN EFI_HANDLE ImageHandle
,
1426 IN EFI_SYSTEM_TABLE
*SystemTable
1431 mPrivateData
.Signature
= SMBIOS_INSTANCE_SIGNATURE
;
1432 mPrivateData
.Smbios
.Add
= SmbiosAdd
;
1433 mPrivateData
.Smbios
.UpdateString
= SmbiosUpdateString
;
1434 mPrivateData
.Smbios
.Remove
= SmbiosRemove
;
1435 mPrivateData
.Smbios
.GetNext
= SmbiosGetNext
;
1436 mPrivateData
.Smbios
.MajorVersion
= (UINT8
) (PcdGet16 (PcdSmbiosVersion
) >> 8);
1437 mPrivateData
.Smbios
.MinorVersion
= (UINT8
) (PcdGet16 (PcdSmbiosVersion
) & 0x00ff);
1439 InitializeListHead (&mPrivateData
.DataListHead
);
1440 InitializeListHead (&mPrivateData
.AllocatedHandleListHead
);
1441 EfiInitializeLock (&mPrivateData
.DataLock
, TPL_NOTIFY
);
1444 // Make a new handle and install the protocol
1446 mPrivateData
.Handle
= NULL
;
1447 Status
= gBS
->InstallProtocolInterface (
1448 &mPrivateData
.Handle
,
1449 &gEfiSmbiosProtocolGuid
,
1450 EFI_NATIVE_INTERFACE
,
1451 &mPrivateData
.Smbios