2 This code produces the Smbios protocol. It also responsible for constructing
3 SMBIOS table into system table.
5 Copyright (c) 2009 - 2011, 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
;
26 // Chassis for SMBIOS entry point structure that is to be installed into EFI system config table.
28 SMBIOS_TABLE_ENTRY_POINT
*EntryPointStructure
= NULL
;
29 SMBIOS_TABLE_ENTRY_POINT EntryPointStructureData
= {
40 // EntryPointStructureChecksum,TO BE FILLED
44 // EntryPointStructure Length
50 (UINT8
) (FixedPcdGet16 (PcdSmbiosVersion
) >> 8),
54 (UINT8
) (FixedPcdGet16 (PcdSmbiosVersion
) & 0x00ff),
56 // MaxStructureSize, TO BE FILLED
74 // IntermediateAnchorString
84 // IntermediateChecksum, TO BE FILLED
88 // StructureTableLength, TO BE FILLED
92 // StructureTableAddress, TO BE FILLED
96 // NumberOfSmbiosStructures, TO BE FILLED
108 Get the full size of smbios structure including optional strings that follow the formatted structure.
110 @param This The EFI_SMBIOS_PROTOCOL instance.
111 @param Head Pointer to the beginning of smbios structure.
112 @param Size The returned size.
113 @param NumberOfStrings The returned number of optional strings that follow the formatted structure.
115 @retval EFI_SUCCESS Size retured in Size.
116 @retval EFI_INVALID_PARAMETER Input smbios structure mal-formed or Size is NULL.
121 GetSmbiosStructureSize (
122 IN CONST EFI_SMBIOS_PROTOCOL
*This
,
123 IN EFI_SMBIOS_TABLE_HEADER
*Head
,
125 OUT UINTN
*NumberOfStrings
132 if (Size
== NULL
|| NumberOfStrings
== NULL
) {
133 return EFI_INVALID_PARAMETER
;
136 FullSize
= Head
->Length
;
137 CharInStr
= (INT8
*)Head
+ Head
->Length
;
139 *NumberOfStrings
= 0;
142 // look for the two consecutive zeros, check the string limit by the way.
144 while (*CharInStr
!= 0 || *(CharInStr
+1) != 0) {
145 if (*CharInStr
== 0) {
150 if (This
->MajorVersion
< 2 || (This
->MajorVersion
== 2 && This
->MinorVersion
< 7)){
151 for (StrLen
= 0 ; StrLen
< SMBIOS_STRING_MAX_LENGTH
; StrLen
++) {
152 if (*(CharInStr
+StrLen
) == 0) {
157 if (StrLen
== SMBIOS_STRING_MAX_LENGTH
) {
158 return EFI_INVALID_PARAMETER
;
162 // Reference SMBIOS 2.7, chapter 6.1.3, it will have no limit on the length of each individual text string
164 for (StrLen
= 0 ;; StrLen
++) {
165 if (*(CharInStr
+StrLen
) == 0) {
172 // forward the pointer
176 *NumberOfStrings
+= 1;
180 // count ending two zeros.
188 Determin whether an SmbiosHandle has already in use.
190 @param Head Pointer to the beginning of smbios structure.
191 @param Handle A unique handle will be assigned to the SMBIOS record.
193 @retval TRUE Smbios handle already in use.
194 @retval FALSE Smbios handle is NOT used.
199 CheckSmbiosHandleExistance (
201 IN EFI_SMBIOS_HANDLE Handle
205 SMBIOS_HANDLE_ENTRY
*HandleEntry
;
207 for (Link
= Head
->ForwardLink
; Link
!= Head
; Link
= Link
->ForwardLink
) {
208 HandleEntry
= SMBIOS_HANDLE_ENTRY_FROM_LINK(Link
);
209 if (HandleEntry
->SmbiosHandle
== Handle
) {
219 Get the max SmbiosHandle that could be use.
221 @param This The EFI_SMBIOS_PROTOCOL instance.
222 @param MaxHandle The max handle that could be assigned to the SMBIOS record.
228 IN CONST EFI_SMBIOS_PROTOCOL
*This
,
229 IN OUT EFI_SMBIOS_HANDLE
*MaxHandle
232 if (This
->MajorVersion
== 2 && This
->MinorVersion
== 0) {
241 Get an SmbiosHandle that could use.
243 @param This The EFI_SMBIOS_PROTOCOL instance.
244 @param SmbiosHandle A unique handle will be assigned to the SMBIOS record.
246 @retval EFI_SUCCESS Smbios handle got.
247 @retval EFI_OUT_OF_RESOURCES Smbios handle is NOT available.
252 GetAvailableSmbiosHandle (
253 IN CONST EFI_SMBIOS_PROTOCOL
*This
,
254 IN OUT EFI_SMBIOS_HANDLE
*Handle
258 SMBIOS_INSTANCE
*Private
;
259 EFI_SMBIOS_HANDLE MaxSmbiosHandle
;
260 EFI_SMBIOS_HANDLE AvailableHandle
;
262 GetMaxSmbiosHandle(This
, &MaxSmbiosHandle
);
264 Private
= SMBIOS_INSTANCE_FROM_THIS (This
);
265 Head
= &Private
->AllocatedHandleListHead
;
266 for (AvailableHandle
= 1; AvailableHandle
< MaxSmbiosHandle
; AvailableHandle
++) {
267 if (!CheckSmbiosHandleExistance(Head
, AvailableHandle
)) {
268 *Handle
= AvailableHandle
;
273 return EFI_OUT_OF_RESOURCES
;
278 Add an SMBIOS record.
280 @param This The EFI_SMBIOS_PROTOCOL instance.
281 @param ProducerHandle The handle of the controller or driver associated with the SMBIOS information. NULL
283 @param SmbiosHandle On entry, if non-zero, the handle of the SMBIOS record. If zero, then a unique handle
284 will be assigned to the SMBIOS record. If the SMBIOS handle is already in use
285 EFI_ALREADY_STARTED is returned and the SMBIOS record is not updated.
286 @param Record The data for the fixed portion of the SMBIOS record. The format of the record is
287 determined by EFI_SMBIOS_TABLE_HEADER.Type. The size of the formatted area is defined
288 by EFI_SMBIOS_TABLE_HEADER.Length and either followed by a double-null (0x0000) or
289 a set of null terminated strings and a null.
291 @retval EFI_SUCCESS Record was added.
292 @retval EFI_OUT_OF_RESOURCES Record was not added due to lack of system resources.
293 @retval EFI_ALREADY_STARTED The SmbiosHandle passed in was already in use.
299 IN CONST EFI_SMBIOS_PROTOCOL
*This
,
300 IN EFI_HANDLE ProducerHandle
, OPTIONAL
301 IN OUT EFI_SMBIOS_HANDLE
*SmbiosHandle
,
302 IN EFI_SMBIOS_TABLE_HEADER
*Record
309 UINTN NumberOfStrings
;
312 SMBIOS_INSTANCE
*Private
;
313 EFI_SMBIOS_ENTRY
*SmbiosEntry
;
314 EFI_SMBIOS_HANDLE MaxSmbiosHandle
;
315 SMBIOS_HANDLE_ENTRY
*HandleEntry
;
316 EFI_SMBIOS_RECORD_HEADER
*InternalRecord
;
318 if (SmbiosHandle
== NULL
) {
319 return EFI_INVALID_PARAMETER
;
322 Private
= SMBIOS_INSTANCE_FROM_THIS (This
);
324 // Check whether SmbiosHandle is already in use
326 Head
= &Private
->AllocatedHandleListHead
;
327 if (*SmbiosHandle
!= 0 && CheckSmbiosHandleExistance(Head
, *SmbiosHandle
)) {
328 return EFI_ALREADY_STARTED
;
332 // when SmbiosHandle is zero, an available handle will be assigned
334 if (*SmbiosHandle
== 0) {
335 Status
= GetAvailableSmbiosHandle(This
, SmbiosHandle
);
336 if (EFI_ERROR(Status
)) {
341 // Check this handle validity
343 GetMaxSmbiosHandle(This
, &MaxSmbiosHandle
);
344 if (*SmbiosHandle
> MaxSmbiosHandle
) {
345 return EFI_INVALID_PARAMETER
;
350 // Calculate record size and string number
352 Status
= GetSmbiosStructureSize(This
, Record
, &StructureSize
, &NumberOfStrings
);
353 if (EFI_ERROR(Status
)) {
358 // Enter into critical section
360 Status
= EfiAcquireLockOrFail (&Private
->DataLock
);
361 if (EFI_ERROR (Status
)) {
365 RecordSize
= sizeof (EFI_SMBIOS_RECORD_HEADER
) + StructureSize
;
366 TotalSize
= sizeof (EFI_SMBIOS_ENTRY
) + RecordSize
;
369 // Allocate internal buffer
371 SmbiosEntry
= AllocateZeroPool (TotalSize
);
372 if (SmbiosEntry
== NULL
) {
373 EfiReleaseLock (&Private
->DataLock
);
374 return EFI_OUT_OF_RESOURCES
;
376 HandleEntry
= AllocateZeroPool (sizeof(SMBIOS_HANDLE_ENTRY
));
377 if (HandleEntry
== NULL
) {
378 EfiReleaseLock (&Private
->DataLock
);
379 return EFI_OUT_OF_RESOURCES
;
383 // Build Handle Entry and insert into linked list
385 HandleEntry
->Signature
= SMBIOS_HANDLE_ENTRY_SIGNATURE
;
386 HandleEntry
->SmbiosHandle
= *SmbiosHandle
;
387 InsertTailList(&Private
->AllocatedHandleListHead
, &HandleEntry
->Link
);
389 InternalRecord
= (EFI_SMBIOS_RECORD_HEADER
*) (SmbiosEntry
+ 1);
390 Raw
= (VOID
*) (InternalRecord
+ 1);
393 // Build internal record Header
395 InternalRecord
->Version
= EFI_SMBIOS_RECORD_HEADER_VERSION
;
396 InternalRecord
->HeaderSize
= (UINT16
) sizeof (EFI_SMBIOS_RECORD_HEADER
);
397 InternalRecord
->RecordSize
= RecordSize
;
398 InternalRecord
->ProducerHandle
= ProducerHandle
;
399 InternalRecord
->NumberOfStrings
= NumberOfStrings
;
401 // Insert record into the internal linked list
403 SmbiosEntry
->Signature
= EFI_SMBIOS_ENTRY_SIGNATURE
;
404 SmbiosEntry
->RecordHeader
= InternalRecord
;
405 SmbiosEntry
->RecordSize
= TotalSize
;
406 InsertTailList (&Private
->DataListHead
, &SmbiosEntry
->Link
);
408 CopyMem (Raw
, Record
, StructureSize
);
409 ((EFI_SMBIOS_TABLE_HEADER
*)Raw
)->Handle
= *SmbiosHandle
;
412 // Leave critical section
414 EfiReleaseLock (&Private
->DataLock
);
419 Update the string associated with an existing SMBIOS record.
421 @param This The EFI_SMBIOS_PROTOCOL instance.
422 @param SmbiosHandle SMBIOS Handle of structure that will have its string updated.
423 @param StringNumber The non-zero string number of the string to update
424 @param String Update the StringNumber string with String.
426 @retval EFI_SUCCESS SmbiosHandle had its StringNumber String updated.
427 @retval EFI_INVALID_PARAMETER SmbiosHandle does not exist.
428 @retval EFI_UNSUPPORTED String was not added since it's longer than 64 significant characters.
429 @retval EFI_NOT_FOUND The StringNumber.is not valid for this SMBIOS record.
435 IN CONST EFI_SMBIOS_PROTOCOL
*This
,
436 IN EFI_SMBIOS_HANDLE
*SmbiosHandle
,
437 IN UINTN
*StringNumber
,
444 UINTN TargetStrOffset
;
451 SMBIOS_INSTANCE
*Private
;
452 EFI_SMBIOS_ENTRY
*SmbiosEntry
;
453 EFI_SMBIOS_ENTRY
*ResizedSmbiosEntry
;
454 EFI_SMBIOS_HANDLE MaxSmbiosHandle
;
455 EFI_SMBIOS_TABLE_HEADER
*Record
;
456 EFI_SMBIOS_RECORD_HEADER
*InternalRecord
;
459 // Check args validity
461 GetMaxSmbiosHandle(This
, &MaxSmbiosHandle
);
463 if (*SmbiosHandle
> MaxSmbiosHandle
) {
464 return EFI_INVALID_PARAMETER
;
467 if (String
== NULL
) {
471 if (*StringNumber
== 0) {
472 return EFI_NOT_FOUND
;
475 InputStrLen
= AsciiStrLen(String
);
478 // Reference SMBIOS 2.7, chapter 6.1.3, it will have no limit on the length of each individual text string
480 if (This
->MajorVersion
< 2 || (This
->MajorVersion
== 2 && This
->MinorVersion
< 7)) {
481 if (InputStrLen
> SMBIOS_STRING_MAX_LENGTH
) {
482 return EFI_UNSUPPORTED
;
486 Private
= SMBIOS_INSTANCE_FROM_THIS (This
);
488 // Enter into critical section
490 Status
= EfiAcquireLockOrFail (&Private
->DataLock
);
491 if (EFI_ERROR (Status
)) {
495 Head
= &Private
->DataListHead
;
496 for (Link
= Head
->ForwardLink
; Link
!= Head
; Link
= Link
->ForwardLink
) {
497 SmbiosEntry
= SMBIOS_ENTRY_FROM_LINK(Link
);
498 Record
= (EFI_SMBIOS_TABLE_HEADER
*)(SmbiosEntry
->RecordHeader
+ 1);
500 if (Record
->Handle
== *SmbiosHandle
) {
502 // Find out the specified Smbios record
504 if (*StringNumber
> SmbiosEntry
->RecordHeader
->NumberOfStrings
) {
505 EfiReleaseLock (&Private
->DataLock
);
506 return EFI_NOT_FOUND
;
509 // Point to unformed string section
511 StrStart
= (CHAR8
*) Record
+ Record
->Length
;
513 for (StrIndex
= 1, TargetStrOffset
= 0; StrIndex
< *StringNumber
; StrStart
++, TargetStrOffset
++) {
515 // A string ends in 00h
517 if (*StrStart
== 0) {
522 // String section ends in double-null (0000h)
524 if (*StrStart
== 0 && *(StrStart
+ 1) == 0) {
525 EfiReleaseLock (&Private
->DataLock
);
526 return EFI_NOT_FOUND
;
530 if (*StrStart
== 0) {
536 // Now we get the string target
538 TargetStrLen
= AsciiStrLen(StrStart
);
539 if (InputStrLen
== TargetStrLen
) {
540 AsciiStrCpy(StrStart
, String
);
541 EfiReleaseLock (&Private
->DataLock
);
546 // Original string buffer size is not exactly match input string length.
547 // Re-allocate buffer is needed.
549 NewEntrySize
= SmbiosEntry
->RecordSize
+ InputStrLen
- TargetStrLen
;
550 ResizedSmbiosEntry
= AllocateZeroPool (NewEntrySize
);
552 if (ResizedSmbiosEntry
== NULL
) {
553 EfiReleaseLock (&Private
->DataLock
);
554 return EFI_OUT_OF_RESOURCES
;
557 InternalRecord
= (EFI_SMBIOS_RECORD_HEADER
*) (ResizedSmbiosEntry
+ 1);
558 Raw
= (VOID
*) (InternalRecord
+ 1);
561 // Build internal record Header
563 InternalRecord
->Version
= EFI_SMBIOS_RECORD_HEADER_VERSION
;
564 InternalRecord
->HeaderSize
= (UINT16
) sizeof (EFI_SMBIOS_RECORD_HEADER
);
565 InternalRecord
->RecordSize
= SmbiosEntry
->RecordHeader
->RecordSize
+ InputStrLen
- TargetStrLen
;
566 InternalRecord
->ProducerHandle
= SmbiosEntry
->RecordHeader
->ProducerHandle
;
567 InternalRecord
->NumberOfStrings
= SmbiosEntry
->RecordHeader
->NumberOfStrings
;
570 // Copy smbios structure and optional strings.
572 CopyMem (Raw
, SmbiosEntry
->RecordHeader
+ 1, Record
->Length
+ TargetStrOffset
);
573 CopyMem ((VOID
*)((UINTN
)Raw
+ Record
->Length
+ TargetStrOffset
), String
, InputStrLen
+ 1);
574 CopyMem ((CHAR8
*)((UINTN
)Raw
+ Record
->Length
+ TargetStrOffset
+ InputStrLen
+ 1),
575 (CHAR8
*)Record
+ Record
->Length
+ TargetStrOffset
+ TargetStrLen
+ 1,
576 SmbiosEntry
->RecordHeader
->RecordSize
- sizeof (EFI_SMBIOS_RECORD_HEADER
) - Record
->Length
- TargetStrOffset
- TargetStrLen
- 1);
581 ResizedSmbiosEntry
->Signature
= EFI_SMBIOS_ENTRY_SIGNATURE
;
582 ResizedSmbiosEntry
->RecordHeader
= InternalRecord
;
583 ResizedSmbiosEntry
->RecordSize
= NewEntrySize
;
584 InsertTailList (Link
->ForwardLink
, &ResizedSmbiosEntry
->Link
);
589 RemoveEntryList(Link
);
590 FreePool(SmbiosEntry
);
591 EfiReleaseLock (&Private
->DataLock
);
596 EfiReleaseLock (&Private
->DataLock
);
597 return EFI_INVALID_PARAMETER
;
601 Remove an SMBIOS record.
603 @param This The EFI_SMBIOS_PROTOCOL instance.
604 @param SmbiosHandle The handle of the SMBIOS record to remove.
606 @retval EFI_SUCCESS SMBIOS record was removed.
607 @retval EFI_INVALID_PARAMETER SmbiosHandle does not specify a valid SMBIOS record.
613 IN CONST EFI_SMBIOS_PROTOCOL
*This
,
614 IN EFI_SMBIOS_HANDLE SmbiosHandle
620 EFI_SMBIOS_HANDLE MaxSmbiosHandle
;
621 SMBIOS_INSTANCE
*Private
;
622 EFI_SMBIOS_ENTRY
*SmbiosEntry
;
623 SMBIOS_HANDLE_ENTRY
*HandleEntry
;
624 EFI_SMBIOS_TABLE_HEADER
*Record
;
627 // Check args validity
629 GetMaxSmbiosHandle(This
, &MaxSmbiosHandle
);
631 if (SmbiosHandle
> MaxSmbiosHandle
) {
632 return EFI_INVALID_PARAMETER
;
635 Private
= SMBIOS_INSTANCE_FROM_THIS (This
);
637 // Enter into critical section
639 Status
= EfiAcquireLockOrFail (&Private
->DataLock
);
640 if (EFI_ERROR (Status
)) {
644 Head
= &Private
->DataListHead
;
645 for (Link
= Head
->ForwardLink
; Link
!= Head
; Link
= Link
->ForwardLink
) {
646 SmbiosEntry
= SMBIOS_ENTRY_FROM_LINK(Link
);
647 Record
= (EFI_SMBIOS_TABLE_HEADER
*)(SmbiosEntry
->RecordHeader
+ 1);
648 if (Record
->Handle
== SmbiosHandle
) {
650 // Remove specified smobios record from DataList
652 RemoveEntryList(Link
);
653 FreePool(SmbiosEntry
);
655 // Remove this handle from AllocatedHandleList
657 Head
= &Private
->AllocatedHandleListHead
;
658 for (Link
= Head
->ForwardLink
; Link
!= Head
; Link
= Link
->ForwardLink
) {
659 HandleEntry
= SMBIOS_HANDLE_ENTRY_FROM_LINK(Link
);
660 if (HandleEntry
->SmbiosHandle
== SmbiosHandle
) {
661 RemoveEntryList(Link
);
662 FreePool(HandleEntry
);
666 EfiReleaseLock (&Private
->DataLock
);
672 // Leave critical section
674 EfiReleaseLock (&Private
->DataLock
);
675 return EFI_INVALID_PARAMETER
;
680 Allow the caller to discover all or some of the SMBIOS records.
682 @param This The EFI_SMBIOS_PROTOCOL instance.
683 @param SmbiosHandle On entry, points to the previous handle of the SMBIOS record. On exit, points to the
684 next SMBIOS record handle. If it is zero on entry, then the first SMBIOS record
685 handle will be returned. If it returns zero on exit, then there are no more SMBIOS records.
686 @param Type On entry it means return the next SMBIOS record of type Type. If a NULL is passed in
687 this functionally it ignored. Type is not modified by the GetNext() function.
688 @param Record On exit, points to the SMBIOS Record consisting of the formatted area followed by
689 the unformatted area. The unformatted area optionally contains text strings.
690 @param ProducerHandle On exit, points to the ProducerHandle registered by Add(). If no ProducerHandle was passed into Add() NULL is returned.
691 If a NULL pointer is passed in no data will be returned
693 @retval EFI_SUCCESS SMBIOS record information was successfully returned in Record.
694 SmbiosHandle is the handle of the current SMBIOS record
695 @retval EFI_NOT_FOUND The SMBIOS record with SmbiosHandle was the last available record.
701 IN CONST EFI_SMBIOS_PROTOCOL
*This
,
702 IN OUT EFI_SMBIOS_HANDLE
*SmbiosHandle
,
703 IN EFI_SMBIOS_TYPE
*Type
, OPTIONAL
704 OUT EFI_SMBIOS_TABLE_HEADER
**Record
,
705 OUT EFI_HANDLE
*ProducerHandle OPTIONAL
708 BOOLEAN StartPointFound
;
711 SMBIOS_INSTANCE
*Private
;
712 EFI_SMBIOS_ENTRY
*SmbiosEntry
;
713 EFI_SMBIOS_TABLE_HEADER
*SmbiosTableHeader
;
715 if (SmbiosHandle
== NULL
) {
716 return EFI_INVALID_PARAMETER
;
719 StartPointFound
= FALSE
;
720 Private
= SMBIOS_INSTANCE_FROM_THIS (This
);
721 Head
= &Private
->DataListHead
;
722 for (Link
= Head
->ForwardLink
; Link
!= Head
; Link
= Link
->ForwardLink
) {
723 SmbiosEntry
= SMBIOS_ENTRY_FROM_LINK(Link
);
724 SmbiosTableHeader
= (EFI_SMBIOS_TABLE_HEADER
*)(SmbiosEntry
->RecordHeader
+ 1);
727 // If SmbiosHandle is zero, the first matched SMBIOS record handle will be returned
729 if (*SmbiosHandle
== 0) {
730 if ((Type
!= NULL
) && (*Type
!= SmbiosTableHeader
->Type
)) {
734 *SmbiosHandle
= SmbiosTableHeader
->Handle
;
735 *Record
=SmbiosTableHeader
;
736 if (ProducerHandle
!= NULL
) {
737 *ProducerHandle
= SmbiosEntry
->RecordHeader
->ProducerHandle
;
743 // Start this round search from the next Smbios handle
745 if (!StartPointFound
&& (*SmbiosHandle
== SmbiosTableHeader
->Handle
)) {
746 StartPointFound
= TRUE
;
750 if (StartPointFound
) {
751 if ((Type
!= NULL
) && (*Type
!= SmbiosTableHeader
->Type
)) {
755 *SmbiosHandle
= SmbiosTableHeader
->Handle
;
756 *Record
= SmbiosTableHeader
;
757 if (ProducerHandle
!= NULL
) {
758 *ProducerHandle
= SmbiosEntry
->RecordHeader
->ProducerHandle
;
766 return EFI_NOT_FOUND
;
772 Assembles Smbios table from the SMBIOS protocol. Produce Table
773 Entry Point and return the pointer to it.
775 @param TableEntryPointStructure On exit, points to the SMBIOS entrypoint structure.
777 @retval EFI_SUCCESS Structure created sucessfully.
778 @retval EFI_NOT_READY Some of The SMBIOS records was not available yet.
779 @retval EFI_OUT_OF_RESOURCES No enough memory.
785 OUT VOID
**TableEntryPointStructure
788 UINT8
*BufferPointer
;
792 EFI_SMBIOS_HANDLE SmbiosHandle
;
793 EFI_SMBIOS_PROTOCOL
*SmbiosProtocol
;
794 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
795 EFI_SMBIOS_TABLE_HEADER
*SmbiosRecord
;
796 EFI_SMBIOS_TABLE_END_STRUCTURE EndStructure
;
798 Status
= EFI_SUCCESS
;
799 BufferPointer
= NULL
;
802 // Initialize the EntryPointStructure with initial values.
804 if (EntryPointStructure
== NULL
) {
806 // Allocate memory (below 4GB)
808 PhysicalAddress
= 0xffffffff;
809 Status
= gBS
->AllocatePages (
811 EfiReservedMemoryType
,
812 EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT
)),
815 if (EFI_ERROR (Status
)) {
816 return EFI_OUT_OF_RESOURCES
;
819 EntryPointStructure
= (SMBIOS_TABLE_ENTRY_POINT
*) (UINTN
) PhysicalAddress
;
823 &EntryPointStructureData
,
824 sizeof (SMBIOS_TABLE_ENTRY_POINT
)
829 // Free the original image
831 if (EntryPointStructure
->TableAddress
!= 0) {
833 (VOID
*)(UINTN
)EntryPointStructure
->TableAddress
,
834 EFI_SIZE_TO_PAGES (EntryPointStructure
->TableLength
)
836 EntryPointStructure
->TableAddress
= 0;
840 // Locate smbios protocol to traverse smbios records.
842 Status
= gBS
->LocateProtocol (&gEfiSmbiosProtocolGuid
, NULL
, (VOID
**) &SmbiosProtocol
);
843 ASSERT_EFI_ERROR (Status
);
844 ASSERT (SmbiosProtocol
!= NULL
);
847 // Make some statistics about all the structures
849 EntryPointStructure
->NumberOfSmbiosStructures
= 0;
850 EntryPointStructure
->TableLength
= 0;
851 EntryPointStructure
->MaxStructureSize
= 0;
855 // Calculate EPS Table Length
858 Status
= SmbiosProtocol
->GetNext (
866 if (Status
== EFI_SUCCESS
) {
867 GetSmbiosStructureSize(SmbiosProtocol
, SmbiosRecord
, &RecordSize
, &NumOfStr
);
869 // Record NumberOfSmbiosStructures, TableLength and MaxStructureSize
871 EntryPointStructure
->NumberOfSmbiosStructures
++;
872 EntryPointStructure
->TableLength
= (UINT16
) (EntryPointStructure
->TableLength
+ RecordSize
);
873 if (RecordSize
> EntryPointStructure
->MaxStructureSize
) {
874 EntryPointStructure
->MaxStructureSize
= (UINT16
) RecordSize
;
877 } while (!EFI_ERROR(Status
));
880 // Create End-Of-Table structure
882 GetMaxSmbiosHandle(SmbiosProtocol
, &SmbiosHandle
);
883 EndStructure
.Header
.Type
= EFI_SMBIOS_TYPE_END_OF_TABLE
;
884 EndStructure
.Header
.Length
= (UINT8
) sizeof (EFI_SMBIOS_TABLE_HEADER
);
885 EndStructure
.Header
.Handle
= SmbiosHandle
;
886 EndStructure
.Tailing
[0] = 0;
887 EndStructure
.Tailing
[1] = 0;
888 EntryPointStructure
->NumberOfSmbiosStructures
++;
889 EntryPointStructure
->TableLength
= (UINT16
) (EntryPointStructure
->TableLength
+ sizeof (EndStructure
));
890 if (sizeof (EndStructure
) > EntryPointStructure
->MaxStructureSize
) {
891 EntryPointStructure
->MaxStructureSize
= (UINT16
) sizeof (EndStructure
);
895 // Allocate memory (below 4GB)
897 PhysicalAddress
= 0xffffffff;
898 Status
= gBS
->AllocatePages (
900 EfiReservedMemoryType
,
901 EFI_SIZE_TO_PAGES (EntryPointStructure
->TableLength
),
904 if (EFI_ERROR (Status
)) {
905 FreePages ((VOID
*) EntryPointStructure
, EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT
)));
906 EntryPointStructure
= NULL
;
907 return EFI_OUT_OF_RESOURCES
;
910 EntryPointStructure
->TableAddress
= (UINT32
) PhysicalAddress
;
913 // Assemble the tables
915 BufferPointer
= (UINT8
*) (UINTN
) PhysicalAddress
;
918 Status
= SmbiosProtocol
->GetNext (
925 if (Status
== EFI_SUCCESS
) {
926 GetSmbiosStructureSize(SmbiosProtocol
, SmbiosRecord
, &RecordSize
, &NumOfStr
);
927 CopyMem (BufferPointer
, SmbiosRecord
, RecordSize
);
928 BufferPointer
= BufferPointer
+ RecordSize
;
930 } while (!EFI_ERROR(Status
));
933 // Assemble End-Of-Table structure
935 CopyMem (BufferPointer
, &EndStructure
, sizeof (EndStructure
));
938 // Fixup checksums in the Entry Point Structure
940 EntryPointStructure
->IntermediateChecksum
=
941 CalculateCheckSum8 ((UINT8
*) EntryPointStructure
+ 0x10, EntryPointStructure
->EntryPointLength
- 0x10);
942 EntryPointStructure
->EntryPointStructureChecksum
=
943 CalculateCheckSum8 ((UINT8
*) EntryPointStructure
, EntryPointStructure
->EntryPointLength
);
946 // Returns the pointer
948 *TableEntryPointStructure
= EntryPointStructure
;
956 Installs the Smbios Table to the System Table. This function gets called
957 when the EFI_EVENT_SIGNAL_READY_TO_BOOT gets signaled
959 @param Event The event to signal
960 @param Context Event contex
965 SmbiosTableConstruction (
973 Status
= SmbiosCreateTable ((VOID
**) &Eps
);
974 if (!EFI_ERROR (Status
)) {
975 gBS
->InstallConfigurationTable (&gEfiSmbiosTableGuid
, Eps
);
982 Driver to produce Smbios protocol and register event for constructing SMBIOS table.
984 @param ImageHandle Module's image handle
985 @param SystemTable Pointer of EFI_SYSTEM_TABLE
987 @retval EFI_SUCCESS Smbios protocol installed
988 @retval Other No protocol installed, unload driver.
993 SmbiosDriverEntryPoint (
994 IN EFI_HANDLE ImageHandle
,
995 IN EFI_SYSTEM_TABLE
*SystemTable
999 EFI_EVENT ReadyToBootEvent
;
1001 mPrivateData
.Signature
= SMBIOS_INSTANCE_SIGNATURE
;
1002 mPrivateData
.Smbios
.Add
= SmbiosAdd
;
1003 mPrivateData
.Smbios
.UpdateString
= SmbiosUpdateString
;
1004 mPrivateData
.Smbios
.Remove
= SmbiosRemove
;
1005 mPrivateData
.Smbios
.GetNext
= SmbiosGetNext
;
1006 mPrivateData
.Smbios
.MajorVersion
= (UINT8
) (FixedPcdGet16 (PcdSmbiosVersion
) >> 8);
1007 mPrivateData
.Smbios
.MinorVersion
= (UINT8
) (FixedPcdGet16 (PcdSmbiosVersion
) & 0x00ff);
1009 InitializeListHead (&mPrivateData
.DataListHead
);
1010 InitializeListHead (&mPrivateData
.AllocatedHandleListHead
);
1011 EfiInitializeLock (&mPrivateData
.DataLock
, TPL_NOTIFY
);
1014 // Make a new handle and install the protocol
1016 mPrivateData
.Handle
= NULL
;
1017 Status
= gBS
->InstallProtocolInterface (
1018 &mPrivateData
.Handle
,
1019 &gEfiSmbiosProtocolGuid
,
1020 EFI_NATIVE_INTERFACE
,
1021 &mPrivateData
.Smbios
1024 if (EFI_ERROR(Status
)) {
1028 // Register the event to install SMBIOS Table into EFI System Table
1030 Status
= gBS
->CreateEventEx (
1033 SmbiosTableConstruction
,
1035 &gEfiEventReadyToBootGuid
,