2 Common filling functions used in translating Datahub's record
5 Copyright (c) 2009, Intel Corporation
6 All rights reserved. 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 Fill a standard Smbios string field.
164 This function will convert the unicode string to single byte chars, and only
165 English language is supported.
166 This function changes the Structure pointer value of the structure node,
167 which should be noted by Caller.
169 @param StructureNode Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
170 @param Offset Offset of SMBIOS record which RecordData will be filled.
171 @param RecordData RecordData buffer will be filled.
172 @param RecordDataSize The size of RecordData buffer.
174 @retval EFI_INVALID_PARAMETER RecordDataSize is too larger
175 @retval EFI_OUT_OF_RESOURCES No memory to allocate new buffer for string
176 @retval EFI_SUCCESS Sucess append string for a SMBIOS record.
180 IN OUT SMBIOS_STRUCTURE_NODE
*StructureNode
,
183 IN UINT32 RecordDataSize
188 CHAR8 AsciiData
[SMBIOS_STRING_MAX_LENGTH
];
189 UINT8 CountOfStrings
;
190 UINTN OrigStringNumber
;
191 EFI_SMBIOS_PROTOCOL
*Smbios
;
192 EFI_SMBIOS_HANDLE SmbiosHandle
;
193 UINT32 OrigStructureSize
;
194 UINTN NewStructureSize
;
195 EFI_SMBIOS_TABLE_HEADER
*NewRecord
;
198 Status
= EFI_SUCCESS
;
199 OrigStringNumber
= 0;
200 OrigStructureSize
= 0;
203 // if we have a NULL token,
205 if (0 == *((STRING_REF
*) RecordData
)) {
206 *(UINT8
*) ((UINT8
*) (StructureNode
->Structure
) + Offset
) = 0;
211 // Get the String from the Hii Database
213 Data
= HiiGetPackageString (
214 &(StructureNode
->ProducerName
),
215 *((EFI_STRING_ID
*) RecordData
),
219 return EFI_INVALID_PARAMETER
;
222 StringLength
= (UINT32
)StrLen (Data
);
224 // Count the string size including the terminating 0.
226 if (StringLength
== 0) {
227 *(UINT8
*) ((UINT8
*) (StructureNode
->Structure
) + Offset
) = 0;
232 if (StringLength
> SMBIOS_STRING_MAX_LENGTH
) {
237 return EFI_INVALID_PARAMETER
;
240 Smbios
= GetSmbiosProtocol();
241 ASSERT (Smbios
!= NULL
);
244 // Convert Unicode string to Ascii string which only supported by SMBIOS.
246 ZeroMem (AsciiData
, SMBIOS_STRING_MAX_LENGTH
);
247 UnicodeStrToAsciiStr (Data
, AsciiData
);
250 // if the field at offset is already filled with some value,
251 // find out the string it points to
253 OrigStringNumber
= *(UINT8
*) ((UINT8
*) (StructureNode
->Structure
) + Offset
);
254 if (OrigStringNumber
!= 0) {
255 DEBUG ((EFI_D_ERROR
, "[SMBIOSThunk] Update %dth string for type[%d],offset[0x%x],handle[0x%x] to [%s]\n",
256 OrigStringNumber
, StructureNode
->SmbiosType
, Offset
, StructureNode
->SmbiosHandle
, AsciiData
));
259 // If original string number is not zero, just update string
261 Status
= Smbios
->UpdateString (Smbios
, &StructureNode
->SmbiosHandle
, &OrigStringNumber
, AsciiData
);
262 if (EFI_ERROR (Status
)) {
263 DEBUG ((EFI_D_ERROR
, "[SMBIOSThunk] Fail to update %dth string in offset 0x%x for handle:0x%x type:0x%x\n",
264 OrigStringNumber
, Offset
, StructureNode
->SmbiosHandle
, StructureNode
->SmbiosType
));
265 ASSERT_EFI_ERROR (Status
);
270 // If the string has not been filled in SMBIOS database, remove it and add again
271 // with string appended.
273 Status
= GetSmbiosStructureSize (StructureNode
->Structure
, &OrigStructureSize
, &CountOfStrings
);
274 ASSERT_EFI_ERROR (Status
);
276 if (CountOfStrings
== 0) {
277 NewStructureSize
= OrigStructureSize
+ StringLength
;
279 NewStructureSize
= OrigStructureSize
+ StringLength
+ 1;
282 NewRecord
= AllocateZeroPool (NewStructureSize
);
283 if (NewRecord
== NULL
) {
284 return EFI_OUT_OF_RESOURCES
;
286 CopyMem (NewRecord
, StructureNode
->Structure
, OrigStructureSize
);
289 // Copy new string into tail of original SMBIOS record buffer.
291 if (CountOfStrings
== 0) {
292 AsciiStrCpy ((CHAR8
*)NewRecord
+ OrigStructureSize
- 2, AsciiData
);
294 AsciiStrCpy ((CHAR8
*)NewRecord
+ OrigStructureSize
- 1, AsciiData
);
296 DEBUG ((EFI_D_ERROR
, "[SMBIOSThunk] Type(%d) offset(0x%x) StringNumber:%d\n",
297 StructureNode
->SmbiosType
, Offset
, CountOfStrings
+ 1));
299 // Update string reference number
301 *(UINT8
*) ((UINT8
*) NewRecord
+ Offset
) = (UINT8
) (CountOfStrings
+ 1);
302 SmbiosHandle
= StructureNode
->SmbiosHandle
;
305 // Remove original SMBIOS record and add new one
307 Status
= Smbios
->Remove (Smbios
, StructureNode
->SmbiosHandle
);
308 ASSERT_EFI_ERROR (Status
);
311 // Add new SMBIOS record
313 Status
= Smbios
->Add (Smbios
, NULL
, &SmbiosHandle
, NewRecord
);
314 ASSERT_EFI_ERROR (Status
);
316 StructureNode
->SmbiosHandle
= SmbiosHandle
;
318 FreePool (NewRecord
);
322 // The SMBIOS record buffer maybe re-allocated in SMBIOS database,
323 // so update cached buffer pointer in DataHub structure list.
325 StructureNode
->Structure
= GetSmbiosBufferFromHandle (
326 StructureNode
->SmbiosHandle
,
327 StructureNode
->SmbiosType
,
330 ASSERT (StructureNode
->Structure
!= NULL
);
333 // The string update action maybe lead the record is re-allocated in SMBIOS database
334 // so update cached record pointer
336 Status
= GetSmbiosStructureSize (StructureNode
->Structure
, &StructureNode
->StructureSize
, &CountOfStrings
);
337 ASSERT_EFI_ERROR (Status
);
343 Find a handle that matches the Link Data and the target Smbios type.
345 @param TargetType the Smbios type
346 @param SubClass the SubClass
347 @param LinkData Specifies Instance, SubInstance and ProducerName
348 @param Handle the HandleNum found
350 @retval EFI_NOT_FOUND Can not find the record according to handle
351 @retval EFI_SUCCESS Success to find the handle
356 IN EFI_GUID
*SubClass
,
357 IN EFI_INTER_LINK_DATA
*LinkData
,
358 IN OUT UINT16
*HandleNum
362 SMBIOS_STRUCTURE_NODE
*StructureNode
;
364 StructureNode
= NULL
;
367 // Find out the matching handle
369 for (Link
= mStructureList
.ForwardLink
; Link
!= &mStructureList
; Link
= Link
->ForwardLink
) {
370 StructureNode
= CR (Link
, SMBIOS_STRUCTURE_NODE
, Link
, SMBIOS_STRUCTURE_NODE_SIGNATURE
);
371 if (StructureNode
->Structure
->Type
== TargetType
&&
372 CompareGuid (&(StructureNode
->SubClass
), SubClass
) &&
373 StructureNode
->Instance
== LinkData
->Instance
&&
374 StructureNode
->SubInstance
== LinkData
->SubInstance
380 if (Link
== &mStructureList
) {
381 return EFI_NOT_FOUND
;
383 *HandleNum
= StructureNode
->Structure
->Handle
;
389 Fill the inter link field for a SMBIOS recorder.
391 Some SMBIOS recorder need to reference the handle of another SMBIOS record. But
392 maybe another SMBIOS record has not been added, so put the InterLink request into
393 a linked list and the interlink will be fixedup when a new SMBIOS record is added.
395 @param StructureNode Point to SMBIOS_STRUCTURE_NODE which reference another record's handle
396 @param LinkSmbiosNodeOffset The offset in this record for holding the handle of another SMBIOS record
397 @param LinkSmbiosType The type of SMBIOS record want to be linked.
398 @param InterLink Point to EFI_INTER_LINK_DATA will be put linked list.
399 @param SubClassGuid The guid of subclass for linked SMBIOS record.
401 @retval EFI_SUCESS The linked record is found and no need fixup in future.
402 @retval !EFI_SUCESS The linked record can not be found and InterLink is put a fixing-p linked list.
406 IN OUT SMBIOS_STRUCTURE_NODE
*StructureNode
,
407 IN UINT16 LinkSmbiosNodeOffset
,
408 IN UINT8 LinkSmbiosType
,
409 IN EFI_INTER_LINK_DATA
*InterLink
,
410 IN EFI_GUID
*SubClassGuid
414 SMBIOS_LINK_DATA_FIXUP_NODE
*LinkDataFixupNode
;
415 UINT16 StructureHandle
;
417 Status
= EFI_SUCCESS
;
418 LinkDataFixupNode
= NULL
;
420 Status
= SmbiosFindHandle (
421 LinkSmbiosType
, // Smbios type
426 if (!EFI_ERROR (Status
)) {
431 (UINT8
*) (StructureNode
->Structure
) + LinkSmbiosNodeOffset
,
433 sizeof (EFI_SMBIOS_HANDLE
)
437 // Hang this in the link data fixup node
439 LinkDataFixupNode
= AllocateZeroPool (sizeof (SMBIOS_LINK_DATA_FIXUP_NODE
));
440 if (LinkDataFixupNode
== NULL
) {
441 return EFI_OUT_OF_RESOURCES
;
444 LinkDataFixupNode
->Signature
= SMBIOS_LINK_DATA_FIXUP_NODE_SIGNATURE
;
445 LinkDataFixupNode
->Offset
= LinkSmbiosNodeOffset
;
446 LinkDataFixupNode
->TargetType
= LinkSmbiosType
;
448 &LinkDataFixupNode
->SubClass
,
453 &LinkDataFixupNode
->LinkData
,
455 sizeof (EFI_INTER_LINK_DATA
)
458 &StructureNode
->LinkDataFixup
,
459 &(LinkDataFixupNode
->Link
)
467 Field Filling Function. Transform an EFI_EXP_BASE10_DATA to a word, with 'Mega'
470 @param StructureNode Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
471 @param Offset Offset of SMBIOS record which RecordData will be filled.
472 @param RecordData RecordData buffer will be filled.
473 @param RecordDataSize The size of RecordData buffer.
475 @retval EFI_INVALID_PARAMETER RecordDataSize is invalid.
476 @retval EFI_SUCCESS RecordData is successed to be filled into given SMBIOS record.
479 SmbiosFldBase10ToWordWithMega (
480 IN OUT SMBIOS_STRUCTURE_NODE
*StructureNode
,
483 IN UINT32 RecordDataSize
486 EFI_EXP_BASE10_DATA
*Base10Data
;
490 if (RecordDataSize
!= sizeof (EFI_EXP_BASE10_DATA
)) {
491 return EFI_INVALID_PARAMETER
;
494 Base10Data
= RecordData
;
495 Value
= Base10Data
->Value
;
496 Exponent
= Base10Data
->Exponent
;
499 while (Exponent
!= 0) {
501 Value
= (INT16
) (Value
* 10);
504 Value
= (INT16
) (Value
/ 10);
510 (UINT8
*) (StructureNode
->Structure
) + Offset
,
519 Field Filling Function. Transform an EFI_EXP_BASE2_DATA to a word, with 'Kilo'
520 as the unit. Granularity implemented for Cache Size.
522 @param StructureNode Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
523 @param Offset Offset of SMBIOS record which RecordData will be filled.
524 @param RecordData RecordData buffer will be filled.
525 @param RecordDataSize The size of RecordData buffer.
527 @retval EFI_INVALID_PARAMETER RecordDataSize is invalid.
528 @retval EFI_SUCCESS RecordData is successed to be filled into given SMBIOS record.
531 SmbiosFldBase2ToWordWithKilo (
532 IN OUT SMBIOS_STRUCTURE_NODE
*StructureNode
,
535 IN UINT32 RecordDataSize
538 EFI_EXP_BASE2_DATA
*Base2Data
;
542 if (RecordDataSize
!= sizeof (EFI_EXP_BASE2_DATA
)) {
543 return EFI_INVALID_PARAMETER
;
546 Base2Data
= RecordData
;
547 Value
= Base2Data
->Value
;
548 Exponent
= Base2Data
->Exponent
;
554 // Implement cache size granularity
556 if(Value
>= 0x8000) {
562 (UINT8
*) (StructureNode
->Structure
) + Offset
,
571 Field Filling Function. Transform an EFI_EXP_BASE2_DATA to a byte, with '64k'
574 @param StructureNode Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
575 @param Offset Offset of SMBIOS record which RecordData will be filled.
576 @param RecordData RecordData buffer will be filled.
577 @param RecordDataSize The size of RecordData buffer.
579 @retval EFI_INVALID_PARAMETER RecordDataSize is invalid.
580 @retval EFI_SUCCESS RecordData is successed to be filled into given SMBIOS record.
583 SmbiosFldBase2ToByteWith64K (
584 IN OUT SMBIOS_STRUCTURE_NODE
*StructureNode
,
587 IN UINT32 RecordDataSize
590 EFI_EXP_BASE2_DATA
*Base2Data
;
594 if (RecordDataSize
!= sizeof (EFI_EXP_BASE2_DATA
)) {
595 return EFI_INVALID_PARAMETER
;
598 Base2Data
= RecordData
;
599 Value
= Base2Data
->Value
;
600 Exponent
= Base2Data
->Exponent
;
605 (UINT8
*) (StructureNode
->Structure
) + Offset
,
614 Field Filling Function. Transform an EFI_EXP_BASE2_DATA to a word, with 10exp-9
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 SmbiosFldBase10ToByteWithNano (
627 IN OUT SMBIOS_STRUCTURE_NODE
*StructureNode
,
630 IN UINT32 RecordDataSize
633 EFI_EXP_BASE10_DATA
*Base10Data
;
637 if (RecordDataSize
!= sizeof (EFI_EXP_BASE2_DATA
)) {
638 return EFI_INVALID_PARAMETER
;
641 Base10Data
= RecordData
;
642 Value
= Base10Data
->Value
;
643 Exponent
= Base10Data
->Exponent
;
646 while (Exponent
!= 0) {
648 Value
= (INT16
) (Value
* 10);
651 Value
= (INT16
) (Value
/ 10);
656 * (UINT8
*) ((UINT8
*) (StructureNode
->Structure
) + Offset
) = (UINT8
) Value
;
662 Field Filling Function: truncate record data to byte and fill in the
663 field as indicated by Offset.
665 @param StructureNode Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
666 @param Offset Offset of SMBIOS record which RecordData will be filled.
667 @param RecordData RecordData buffer will be filled.
668 @param RecordDataSize The size of RecordData buffer.
670 @retval EFI_INVALID_PARAMETER RecordDataSize is invalid.
671 @retval EFI_SUCCESS RecordData is successed to be filled into given SMBIOS record.
674 SmbiosFldTruncateToByte (
675 IN OUT SMBIOS_STRUCTURE_NODE
*StructureNode
,
678 IN UINT32 RecordDataSize
683 Status
= EFI_SUCCESS
;
686 // Truncate the data to 8 bits
688 *(UINT8
*) ((UINT8
*) (StructureNode
->Structure
) + Offset
) = (UINT8
) (*(UINT8
*) RecordData
);
694 Field Filling Function: truncate record data to byte and fill in the
695 field as indicated by Offset.
697 @param StructureNode Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
698 @param Offset Offset of SMBIOS record which RecordData will be filled.
699 @param RecordData RecordData buffer will be filled.
700 @param RecordDataSize The size of RecordData buffer.
702 @retval EFI_INVALID_PARAMETER RecordDataSize is invalid.
703 @retval EFI_SUCCESS RecordData is successed to be filled into given SMBIOS record.
706 SmbiosFldTruncateToWord (
707 IN OUT SMBIOS_STRUCTURE_NODE
*StructureNode
,
710 IN UINT32 RecordDataSize
715 Status
= EFI_SUCCESS
;
718 // Truncate the data to 8 bits
721 (UINT8
*) (StructureNode
->Structure
) + Offset
,
730 Check if OEM structure has included 2 trailing 0s in data record.
732 @param RecordData Point to record data will be checked.
733 @param RecordDataSize The size of record data.
735 @retval 0 2 trailing 0s exist in unformatted section
736 @retval 1 1 trailing 0 exists at the end of unformatted section
737 @retval -1 There is no 0 at the end of unformatted section
740 SmbiosCheckTrailingZero (
742 IN UINT32 RecordDataSize
745 SMBIOS_STRUCTURE
*Smbios
;
749 Smbios
= (SMBIOS_STRUCTURE
*) RecordData
;
752 // Skip over formatted section
754 Start
= (CHAR8
*) ((UINT8
*) Smbios
+ Smbios
->Length
);
755 End
= (CHAR8
*) RecordData
+ RecordDataSize
;
758 // Unformatted section exists
760 while (Start
< End
- 1) {
762 // Avoid unaligned issue on IPF
764 if ((*Start
== 0) && (*(Start
+ 1) == 0)) {
766 // 2 trailing 0s exist in unformatted section
773 if (Start
== End
- 1) {
775 // Check if there has been already 1 trailing 0
783 // There is no 0 at the end of unformatted section