2 Common filling functions used in translating Datahub's record
5 Copyright (c) 2009 - 2010, 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.
19 Field Filling Function for Cache SubClass record type 5&6 -- Cache SRAM type.
22 @param StructureNode Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
23 @param Offset Offset of SMBIOS record which RecordData will be filled.
24 @param RecordData RecordData buffer will be filled.
25 @param RecordDataSize The size of RecordData buffer.
27 @retval EFI_SUCCESS Success fill RecordData into SMBIOS's record buffer.
31 IN OUT SMBIOS_STRUCTURE_NODE
*StructureNode
,
34 IN UINT32 RecordDataSize
37 EFI_CACHE_SRAM_TYPE_DATA SramData
;
40 SramData
= *(EFI_CACHE_SRAM_TYPE_DATA
*)RecordData
;
43 // Swap two fields because of inconsistency between smbios and datahub specs
45 Temp
= SramData
.Asynchronous
;
46 SramData
.Asynchronous
= SramData
.Synchronous
;
47 SramData
.Synchronous
= Temp
;
50 // Truncate the data to word
53 (UINT8
*) (StructureNode
->Structure
) + Offset
,
54 (EFI_CACHE_SRAM_TYPE_DATA
*) &SramData
,
62 Field Filling Function for Cache SubClass record type 10 -- Cache Config.
65 @param StructureNode Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
66 @param Offset Offset of SMBIOS record which RecordData will be filled.
67 @param RecordData RecordData buffer will be filled.
68 @param RecordDataSize The size of RecordData buffer.
70 @retval EFI_SUCCESS Success fill RecordData into SMBIOS's record buffer.
73 SmbiosFldCacheType10 (
74 IN OUT SMBIOS_STRUCTURE_NODE
*StructureNode
,
77 IN UINT32 RecordDataSize
83 CopyMem (&CacheConfig
, RecordData
, 2);
85 if ((CacheConfig
& 0x07) == 0) {
86 return EFI_INVALID_PARAMETER
;
89 // Truncate the data to 2 bytes and make cache level zero-based.
93 (UINT8
*) (StructureNode
->Structure
) + Offset
,
102 Enlarge the structure buffer of a structure node in SMBIOS database.
103 The function maybe lead the structure pointer for SMBIOS record changed.
105 @param StructureNode The structure node whose structure buffer is to be enlarged.
106 @param NewLength The new length of SMBIOS record which does not include unformat area.
107 @param OldBufferSize The old size of SMBIOS record buffer.
108 @param NewBufferSize The new size is targeted for enlarged.
110 @retval EFI_OUT_OF_RESOURCES No more memory to allocate new record
111 @retval EFI_SUCCESS Success to enlarge the record buffer size.
114 SmbiosEnlargeStructureBuffer (
115 IN OUT SMBIOS_STRUCTURE_NODE
*StructureNode
,
121 EFI_SMBIOS_TABLE_HEADER
*NewRecord
;
122 EFI_SMBIOS_PROTOCOL
*Smbios
;
127 Smbios
= GetSmbiosProtocol();
128 ASSERT (Smbios
!= NULL
);
130 NewRecord
= (EFI_SMBIOS_TABLE_HEADER
*) AllocateZeroPool (NewBufferSize
);
131 if (NewRecord
== NULL
) {
132 return EFI_OUT_OF_RESOURCES
;
134 CopyMem (NewRecord
, StructureNode
->Structure
, OldBufferSize
);
137 Status
= Smbios
->Remove (Smbios
, StructureNode
->SmbiosHandle
);
138 ASSERT_EFI_ERROR (Status
);
141 // try to use original handle to enlarge the buffer.
143 NewRecord
->Length
= NewLength
;
144 Status
= Smbios
->Add (Smbios
, NULL
, &StructureNode
->SmbiosHandle
, NewRecord
);
145 ASSERT_EFI_ERROR (Status
);
146 FreePool (NewRecord
);
148 StructureNode
->Structure
= GetSmbiosBufferFromHandle (
149 StructureNode
->SmbiosHandle
,
150 StructureNode
->SmbiosType
,
153 GetSmbiosStructureSize (
154 StructureNode
->Structure
,
155 &StructureNode
->StructureSize
,
162 Update the structure buffer of a structure node in SMBIOS database.
163 The function lead the structure pointer for SMBIOS record changed.
165 @param StructureNode The structure node whose structure buffer is to be enlarged.
166 @param NewRecord The new SMBIOS record.
170 SmbiosUpdateStructureBuffer (
171 IN OUT SMBIOS_STRUCTURE_NODE
*StructureNode
,
172 IN EFI_SMBIOS_TABLE_HEADER
*NewRecord
175 EFI_SMBIOS_PROTOCOL
*Smbios
;
179 Smbios
= GetSmbiosProtocol();
180 ASSERT (Smbios
!= NULL
);
182 Status
= Smbios
->Remove (Smbios
, StructureNode
->SmbiosHandle
);
183 ASSERT_EFI_ERROR (Status
);
186 // try to use original handle to enlarge the buffer.
188 Status
= Smbios
->Add (Smbios
, NULL
, &StructureNode
->SmbiosHandle
, NewRecord
);
189 ASSERT_EFI_ERROR (Status
);
191 StructureNode
->Structure
= GetSmbiosBufferFromHandle (
192 StructureNode
->SmbiosHandle
,
193 StructureNode
->SmbiosType
,
196 GetSmbiosStructureSize (
197 StructureNode
->Structure
,
198 &StructureNode
->StructureSize
,
205 Fill a standard Smbios string field.
207 This function will convert the unicode string to single byte chars, and only
208 English language is supported.
209 This function changes the Structure pointer value of the structure node,
210 which should be noted by Caller.
212 @param StructureNode Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
213 @param Offset Offset of SMBIOS record which RecordData will be filled.
214 @param RecordData RecordData buffer will be filled.
215 @param RecordDataSize The size of RecordData buffer.
217 @retval EFI_INVALID_PARAMETER RecordDataSize is too larger
218 @retval EFI_OUT_OF_RESOURCES No memory to allocate new buffer for string
219 @retval EFI_SUCCESS Sucess append string for a SMBIOS record.
223 IN OUT SMBIOS_STRUCTURE_NODE
*StructureNode
,
226 IN UINT32 RecordDataSize
231 CHAR8 AsciiData
[SMBIOS_STRING_MAX_LENGTH
];
232 UINT8 CountOfStrings
;
233 UINTN OrigStringNumber
;
234 EFI_SMBIOS_PROTOCOL
*Smbios
;
235 EFI_SMBIOS_HANDLE SmbiosHandle
;
236 UINT32 OrigStructureSize
;
237 UINTN NewStructureSize
;
238 EFI_SMBIOS_TABLE_HEADER
*NewRecord
;
241 Status
= EFI_SUCCESS
;
242 OrigStringNumber
= 0;
243 OrigStructureSize
= 0;
246 // if we have a NULL token,
248 if (0 == *((STRING_REF
*) RecordData
)) {
249 *(UINT8
*) ((UINT8
*) (StructureNode
->Structure
) + Offset
) = 0;
254 // Get the String from the Hii Database
256 Data
= HiiGetPackageString (
257 &(StructureNode
->ProducerName
),
258 *((EFI_STRING_ID
*) RecordData
),
262 return EFI_INVALID_PARAMETER
;
265 StringLength
= (UINT32
)StrLen (Data
);
267 // Count the string size including the terminating 0.
269 if (StringLength
== 0) {
270 *(UINT8
*) ((UINT8
*) (StructureNode
->Structure
) + Offset
) = 0;
275 if (StringLength
> SMBIOS_STRING_MAX_LENGTH
) {
280 return EFI_INVALID_PARAMETER
;
283 Smbios
= GetSmbiosProtocol();
284 ASSERT (Smbios
!= NULL
);
287 // Convert Unicode string to Ascii string which only supported by SMBIOS.
289 ZeroMem (AsciiData
, SMBIOS_STRING_MAX_LENGTH
);
290 UnicodeStrToAsciiStr (Data
, AsciiData
);
293 // if the field at offset is already filled with some value,
294 // find out the string it points to
296 OrigStringNumber
= *(UINT8
*) ((UINT8
*) (StructureNode
->Structure
) + Offset
);
297 if (OrigStringNumber
!= 0) {
298 DEBUG ((EFI_D_ERROR
, "[SMBIOSThunk] Update %dth string for type[%d],offset[0x%x],handle[0x%x] to [%s]\n",
299 OrigStringNumber
, StructureNode
->SmbiosType
, Offset
, StructureNode
->SmbiosHandle
, AsciiData
));
302 // If original string number is not zero, just update string
304 Status
= Smbios
->UpdateString (Smbios
, &StructureNode
->SmbiosHandle
, &OrigStringNumber
, AsciiData
);
305 if (EFI_ERROR (Status
)) {
306 DEBUG ((EFI_D_ERROR
, "[SMBIOSThunk] Fail to update %dth string in offset 0x%x for handle:0x%x type:0x%x\n",
307 OrigStringNumber
, Offset
, StructureNode
->SmbiosHandle
, StructureNode
->SmbiosType
));
308 ASSERT_EFI_ERROR (Status
);
313 // If the string has not been filled in SMBIOS database, remove it and add again
314 // with string appended.
316 Status
= GetSmbiosStructureSize (StructureNode
->Structure
, &OrigStructureSize
, &CountOfStrings
);
317 ASSERT_EFI_ERROR (Status
);
319 if (CountOfStrings
== 0) {
320 NewStructureSize
= OrigStructureSize
+ StringLength
;
322 NewStructureSize
= OrigStructureSize
+ StringLength
+ 1;
325 NewRecord
= AllocateZeroPool (NewStructureSize
);
326 if (NewRecord
== NULL
) {
327 return EFI_OUT_OF_RESOURCES
;
329 CopyMem (NewRecord
, StructureNode
->Structure
, OrigStructureSize
);
332 // Copy new string into tail of original SMBIOS record buffer.
334 if (CountOfStrings
== 0) {
335 AsciiStrCpy ((CHAR8
*)NewRecord
+ OrigStructureSize
- 2, AsciiData
);
337 AsciiStrCpy ((CHAR8
*)NewRecord
+ OrigStructureSize
- 1, AsciiData
);
339 DEBUG ((EFI_D_ERROR
, "[SMBIOSThunk] Type(%d) offset(0x%x) StringNumber:%d\n",
340 StructureNode
->SmbiosType
, Offset
, CountOfStrings
+ 1));
342 // Update string reference number
344 *(UINT8
*) ((UINT8
*) NewRecord
+ Offset
) = (UINT8
) (CountOfStrings
+ 1);
345 SmbiosHandle
= StructureNode
->SmbiosHandle
;
348 // Remove original SMBIOS record and add new one
350 Status
= Smbios
->Remove (Smbios
, StructureNode
->SmbiosHandle
);
351 ASSERT_EFI_ERROR (Status
);
354 // Add new SMBIOS record
356 Status
= Smbios
->Add (Smbios
, NULL
, &SmbiosHandle
, NewRecord
);
357 ASSERT_EFI_ERROR (Status
);
359 StructureNode
->SmbiosHandle
= SmbiosHandle
;
361 FreePool (NewRecord
);
365 // The SMBIOS record buffer maybe re-allocated in SMBIOS database,
366 // so update cached buffer pointer in DataHub structure list.
368 StructureNode
->Structure
= GetSmbiosBufferFromHandle (
369 StructureNode
->SmbiosHandle
,
370 StructureNode
->SmbiosType
,
373 ASSERT (StructureNode
->Structure
!= NULL
);
376 // The string update action maybe lead the record is re-allocated in SMBIOS database
377 // so update cached record pointer
379 Status
= GetSmbiosStructureSize (StructureNode
->Structure
, &StructureNode
->StructureSize
, &CountOfStrings
);
380 ASSERT_EFI_ERROR (Status
);
386 Find a handle that matches the Link Data and the target Smbios type.
388 @param TargetType the Smbios type
389 @param SubClass the SubClass
390 @param LinkData Specifies Instance, SubInstance and ProducerName
391 @param Handle the HandleNum found
393 @retval EFI_NOT_FOUND Can not find the record according to handle
394 @retval EFI_SUCCESS Success to find the handle
399 IN EFI_GUID
*SubClass
,
400 IN EFI_INTER_LINK_DATA
*LinkData
,
401 IN OUT UINT16
*HandleNum
405 SMBIOS_STRUCTURE_NODE
*StructureNode
;
407 StructureNode
= NULL
;
410 // Find out the matching handle
412 for (Link
= mStructureList
.ForwardLink
; Link
!= &mStructureList
; Link
= Link
->ForwardLink
) {
413 StructureNode
= CR (Link
, SMBIOS_STRUCTURE_NODE
, Link
, SMBIOS_STRUCTURE_NODE_SIGNATURE
);
414 if (StructureNode
->Structure
->Type
== TargetType
&&
415 CompareGuid (&(StructureNode
->SubClass
), SubClass
) &&
416 StructureNode
->Instance
== LinkData
->Instance
&&
417 StructureNode
->SubInstance
== LinkData
->SubInstance
423 if (Link
== &mStructureList
|| StructureNode
== NULL
) {
424 return EFI_NOT_FOUND
;
426 *HandleNum
= StructureNode
->Structure
->Handle
;
432 Fill the inter link field for a SMBIOS recorder.
434 Some SMBIOS recorder need to reference the handle of another SMBIOS record. But
435 maybe another SMBIOS record has not been added, so put the InterLink request into
436 a linked list and the interlink will be fixedup when a new SMBIOS record is added.
438 @param StructureNode Point to SMBIOS_STRUCTURE_NODE which reference another record's handle
439 @param LinkSmbiosNodeOffset The offset in this record for holding the handle of another SMBIOS record
440 @param LinkSmbiosType The type of SMBIOS record want to be linked.
441 @param InterLink Point to EFI_INTER_LINK_DATA will be put linked list.
442 @param SubClassGuid The guid of subclass for linked SMBIOS record.
444 @retval EFI_SUCESS The linked record is found and no need fixup in future.
445 @retval !EFI_SUCESS The linked record can not be found and InterLink is put a fixing-p linked list.
449 IN OUT SMBIOS_STRUCTURE_NODE
*StructureNode
,
450 IN UINT16 LinkSmbiosNodeOffset
,
451 IN UINT8 LinkSmbiosType
,
452 IN EFI_INTER_LINK_DATA
*InterLink
,
453 IN EFI_GUID
*SubClassGuid
457 SMBIOS_LINK_DATA_FIXUP_NODE
*LinkDataFixupNode
;
458 UINT16 StructureHandle
;
460 Status
= EFI_SUCCESS
;
461 LinkDataFixupNode
= NULL
;
463 Status
= SmbiosFindHandle (
464 LinkSmbiosType
, // Smbios type
469 if (!EFI_ERROR (Status
)) {
474 (UINT8
*) (StructureNode
->Structure
) + LinkSmbiosNodeOffset
,
476 sizeof (EFI_SMBIOS_HANDLE
)
480 // Hang this in the link data fixup node
482 LinkDataFixupNode
= AllocateZeroPool (sizeof (SMBIOS_LINK_DATA_FIXUP_NODE
));
483 if (LinkDataFixupNode
== NULL
) {
484 return EFI_OUT_OF_RESOURCES
;
487 LinkDataFixupNode
->Signature
= SMBIOS_LINK_DATA_FIXUP_NODE_SIGNATURE
;
488 LinkDataFixupNode
->Offset
= LinkSmbiosNodeOffset
;
489 LinkDataFixupNode
->TargetType
= LinkSmbiosType
;
491 &LinkDataFixupNode
->SubClass
,
496 &LinkDataFixupNode
->LinkData
,
498 sizeof (EFI_INTER_LINK_DATA
)
501 &StructureNode
->LinkDataFixup
,
502 &(LinkDataFixupNode
->Link
)
510 Field Filling Function. Transform an EFI_EXP_BASE10_DATA to a word, with 'Mega'
513 @param StructureNode Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
514 @param Offset Offset of SMBIOS record which RecordData will be filled.
515 @param RecordData RecordData buffer will be filled.
516 @param RecordDataSize The size of RecordData buffer.
518 @retval EFI_INVALID_PARAMETER RecordDataSize is invalid.
519 @retval EFI_SUCCESS RecordData is successed to be filled into given SMBIOS record.
522 SmbiosFldBase10ToWordWithMega (
523 IN OUT SMBIOS_STRUCTURE_NODE
*StructureNode
,
526 IN UINT32 RecordDataSize
529 EFI_EXP_BASE10_DATA
*Base10Data
;
533 if (RecordDataSize
!= sizeof (EFI_EXP_BASE10_DATA
)) {
534 return EFI_INVALID_PARAMETER
;
537 Base10Data
= RecordData
;
538 Value
= Base10Data
->Value
;
539 Exponent
= Base10Data
->Exponent
;
542 while (Exponent
!= 0) {
544 Value
= (INT16
) (Value
* 10);
547 Value
= (INT16
) (Value
/ 10);
553 (UINT8
*) (StructureNode
->Structure
) + Offset
,
562 Field Filling Function. Transform an EFI_EXP_BASE2_DATA to a word, with 'Kilo'
563 as the unit. Granularity implemented for Cache Size.
565 @param StructureNode Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
566 @param Offset Offset of SMBIOS record which RecordData will be filled.
567 @param RecordData RecordData buffer will be filled.
568 @param RecordDataSize The size of RecordData buffer.
570 @retval EFI_INVALID_PARAMETER RecordDataSize is invalid.
571 @retval EFI_SUCCESS RecordData is successed to be filled into given SMBIOS record.
574 SmbiosFldBase2ToWordWithKilo (
575 IN OUT SMBIOS_STRUCTURE_NODE
*StructureNode
,
578 IN UINT32 RecordDataSize
581 EFI_EXP_BASE2_DATA
*Base2Data
;
585 if (RecordDataSize
!= sizeof (EFI_EXP_BASE2_DATA
)) {
586 return EFI_INVALID_PARAMETER
;
589 Base2Data
= RecordData
;
590 Value
= Base2Data
->Value
;
591 Exponent
= Base2Data
->Exponent
;
597 // Implement cache size granularity
599 if(Value
>= 0x8000) {
605 (UINT8
*) (StructureNode
->Structure
) + Offset
,
614 Field Filling Function. Transform an EFI_EXP_BASE2_DATA to a byte, with '64k'
617 @param StructureNode Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
618 @param Offset Offset of SMBIOS record which RecordData will be filled.
619 @param RecordData RecordData buffer will be filled.
620 @param RecordDataSize The size of RecordData buffer.
622 @retval EFI_INVALID_PARAMETER RecordDataSize is invalid.
623 @retval EFI_SUCCESS RecordData is successed to be filled into given SMBIOS record.
626 SmbiosFldBase2ToByteWith64K (
627 IN OUT SMBIOS_STRUCTURE_NODE
*StructureNode
,
630 IN UINT32 RecordDataSize
633 EFI_EXP_BASE2_DATA
*Base2Data
;
637 if (RecordDataSize
!= sizeof (EFI_EXP_BASE2_DATA
)) {
638 return EFI_INVALID_PARAMETER
;
641 Base2Data
= RecordData
;
642 Value
= Base2Data
->Value
;
643 Exponent
= Base2Data
->Exponent
;
648 (UINT8
*) (StructureNode
->Structure
) + Offset
,
657 Field Filling Function. Transform an EFI_EXP_BASE2_DATA to a word, with 10exp-9
660 @param StructureNode Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
661 @param Offset Offset of SMBIOS record which RecordData will be filled.
662 @param RecordData RecordData buffer will be filled.
663 @param RecordDataSize The size of RecordData buffer.
665 @retval EFI_INVALID_PARAMETER RecordDataSize is invalid.
666 @retval EFI_SUCCESS RecordData is successed to be filled into given SMBIOS record.
669 SmbiosFldBase10ToByteWithNano (
670 IN OUT SMBIOS_STRUCTURE_NODE
*StructureNode
,
673 IN UINT32 RecordDataSize
676 EFI_EXP_BASE10_DATA
*Base10Data
;
680 if (RecordDataSize
!= sizeof (EFI_EXP_BASE2_DATA
)) {
681 return EFI_INVALID_PARAMETER
;
684 Base10Data
= RecordData
;
685 Value
= Base10Data
->Value
;
686 Exponent
= Base10Data
->Exponent
;
689 while (Exponent
!= 0) {
691 Value
= (INT16
) (Value
* 10);
694 Value
= (INT16
) (Value
/ 10);
699 * (UINT8
*) ((UINT8
*) (StructureNode
->Structure
) + Offset
) = (UINT8
) Value
;
705 Field Filling Function: truncate record data to byte and fill in the
706 field as indicated by Offset.
708 @param StructureNode Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
709 @param Offset Offset of SMBIOS record which RecordData will be filled.
710 @param RecordData RecordData buffer will be filled.
711 @param RecordDataSize The size of RecordData buffer.
713 @retval EFI_INVALID_PARAMETER RecordDataSize is invalid.
714 @retval EFI_SUCCESS RecordData is successed to be filled into given SMBIOS record.
717 SmbiosFldTruncateToByte (
718 IN OUT SMBIOS_STRUCTURE_NODE
*StructureNode
,
721 IN UINT32 RecordDataSize
726 Status
= EFI_SUCCESS
;
729 // Truncate the data to 8 bits
731 *(UINT8
*) ((UINT8
*) (StructureNode
->Structure
) + Offset
) = (UINT8
) (*(UINT8
*) RecordData
);
737 Field Filling Function: truncate record data to byte and fill in the
738 field as indicated by Offset.
740 @param StructureNode Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
741 @param Offset Offset of SMBIOS record which RecordData will be filled.
742 @param RecordData RecordData buffer will be filled.
743 @param RecordDataSize The size of RecordData buffer.
745 @retval EFI_INVALID_PARAMETER RecordDataSize is invalid.
746 @retval EFI_SUCCESS RecordData is successed to be filled into given SMBIOS record.
749 SmbiosFldTruncateToWord (
750 IN OUT SMBIOS_STRUCTURE_NODE
*StructureNode
,
753 IN UINT32 RecordDataSize
758 Status
= EFI_SUCCESS
;
761 // Truncate the data to 8 bits
764 (UINT8
*) (StructureNode
->Structure
) + Offset
,
773 Check if OEM structure has included 2 trailing 0s in data record.
775 @param RecordData Point to record data will be checked.
776 @param RecordDataSize The size of record data.
778 @retval 0 2 trailing 0s exist in unformatted section
779 @retval 1 1 trailing 0 exists at the end of unformatted section
780 @retval -1 There is no 0 at the end of unformatted section
783 SmbiosCheckTrailingZero (
785 IN UINT32 RecordDataSize
788 SMBIOS_STRUCTURE
*Smbios
;
792 Smbios
= (SMBIOS_STRUCTURE
*) RecordData
;
795 // Skip over formatted section
797 Start
= (CHAR8
*) ((UINT8
*) Smbios
+ Smbios
->Length
);
798 End
= (CHAR8
*) RecordData
+ RecordDataSize
;
801 // Unformatted section exists
803 while (Start
< End
- 1) {
805 // Avoid unaligned issue on IPF
807 if ((*Start
== 0) && (*(Start
+ 1) == 0)) {
809 // 2 trailing 0s exist in unformatted section
816 if (Start
== End
- 1) {
818 // Check if there has been already 1 trailing 0
826 // There is no 0 at the end of unformatted section