4 Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
5 Copyright (c) 2015, Hisilicon Limited. All rights reserved.
6 Copyright (c) 2015, Linaro Limited. All rights reserved.
7 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include <Protocol/Smbios.h>
13 #include <IndustryStandard/ArmCache.h>
14 #include <IndustryStandard/ArmStdSmc.h>
15 #include <IndustryStandard/SmBios.h>
16 #include <Library/ArmLib.h>
17 #include <Library/ArmSmcLib.h>
18 #include <Library/BaseLib.h>
19 #include <Library/BaseMemoryLib.h>
20 #include <Library/DebugLib.h>
21 #include <Library/HiiLib.h>
22 #include <Library/IoLib.h>
23 #include <Library/MemoryAllocationLib.h>
24 #include <Library/OemMiscLib.h>
25 #include <Library/PcdLib.h>
26 #include <Library/PrintLib.h>
27 #include <Library/UefiBootServicesTableLib.h>
28 #include <Library/UefiLib.h>
30 #include "SmbiosProcessor.h"
32 extern UINT8 ProcessorSubClassStrings
[];
34 #define CACHE_SOCKETED_SHIFT 3
35 #define CACHE_LOCATION_SHIFT 5
36 #define CACHE_ENABLED_SHIFT 7
37 #define CACHE_OPERATION_MODE_SHIFT 8
40 CacheModeWriteThrough
= 0, ///< Cache is write-through
41 CacheModeWriteBack
, ///< Cache is write-back
42 CacheModeVariesWithAddress
, ///< Cache mode varies by address
43 CacheModeUnknown
, ///< Cache mode is unknown
45 } CACHE_OPERATION_MODE
;
48 CacheLocationInternal
= 0, ///< Cache is internal to the processor
49 CacheLocationExternal
, ///< Cache is external to the processor
50 CacheLocationReserved
, ///< Reserved
51 CacheLocationUnknown
, ///< Cache location is unknown
55 EFI_HII_HANDLE mHiiHandle
;
57 EFI_SMBIOS_PROTOCOL
*mSmbios
;
59 SMBIOS_TABLE_TYPE4 mSmbiosProcessorTableTemplate
= {
61 EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION
, // Type
62 sizeof (SMBIOS_TABLE_TYPE4
), // Length
66 CentralProcessor
, // ProcessorType
67 ProcessorFamilyIndicatorFamily2
, // ProcessorFamily
68 2, // ProcessorManufacture
77 3, // ProcessorVersion
85 ProcessorUpgradeUnknown
, // ProcessorUpgrade
86 0xFFFF, // L1CacheHandle
87 0xFFFF, // L2CacheHandle
88 0xFFFF, // L3CacheHandle
95 0, // ProcessorCharacteristics
96 ProcessorFamilyARM
, // ProcessorFamily2
98 0, // EnabledCoreCount2
102 /** Sets the HII variable `StringId` is `Pcd` isn't empty.
104 @param Pcd The FixedAtBuild PCD that contains the string to fetch.
105 @param StringId The string identifier to set.
107 #define SET_HII_STRING_IF_PCD_NOT_EMPTY(Pcd, StringId) \
110 Str = (CHAR16*)PcdGetPtr (Pcd); \
111 if (StrLen (Str) > 0) { \
112 HiiSetString (mHiiHandle, StringId, Str, NULL); \
116 /** Fetches the specified processor's frequency in Hz.
118 @param ProcessorNumber The processor number
120 @return The clock frequency in MHz
125 IN UINT8 ProcessorNumber
128 return (UINT16
)(OemGetCpuFreq (ProcessorNumber
) / 1000 / 1000);
131 /** Gets a description of the specified cache.
133 @param[in] CacheLevel Zero-based cache level (e.g. L1 cache is 0).
134 @param[in] DataCache Cache is a data cache.
135 @param[in] UnifiedCache Cache is a unified cache.
136 @param[out] CacheSocketStr The description of the specified cache
138 @return The number of Unicode characters in CacheSocketStr not including the
144 IN BOOLEAN DataCache
,
145 IN BOOLEAN UnifiedCache
,
146 OUT CHAR16
*CacheSocketStr
149 UINTN CacheSocketStrLen
;
151 if (CacheLevel
== CpuCacheL1
&& !DataCache
&& !UnifiedCache
) {
152 CacheSocketStrLen
= UnicodeSPrint (
154 SMBIOS_STRING_MAX_LENGTH
- 1,
155 L
"L%x Instruction Cache",
157 } else if (CacheLevel
== CpuCacheL1
&& DataCache
) {
158 CacheSocketStrLen
= UnicodeSPrint (CacheSocketStr
,
159 SMBIOS_STRING_MAX_LENGTH
- 1,
163 CacheSocketStrLen
= UnicodeSPrint (CacheSocketStr
,
164 SMBIOS_STRING_MAX_LENGTH
- 1,
169 return CacheSocketStrLen
;
172 /** Fills in the Type 7 record with the cache architecture information
173 read from the CPU registers.
175 @param[in] CacheLevel Cache level (e.g. L1, L2).
176 @param[in] DataCache Cache is a data cache.
177 @param[in] UnifiedCache Cache is a unified cache.
178 @param[out] Type7Record The Type 7 record to fill in.
182 ConfigureCacheArchitectureInformation (
184 IN BOOLEAN DataCache
,
185 IN BOOLEAN UnifiedCache
,
186 OUT SMBIOS_TABLE_TYPE7
*Type7Record
194 if (!DataCache
&& !UnifiedCache
) {
195 Type7Record
->SystemCacheType
= CacheTypeInstruction
;
196 } else if (DataCache
) {
197 Type7Record
->SystemCacheType
= CacheTypeData
;
198 } else if (UnifiedCache
) {
199 Type7Record
->SystemCacheType
= CacheTypeUnified
;
204 CacheSize64
= SmbiosProcessorGetCacheSize (CacheLevel
,
209 Associativity
= SmbiosProcessorGetCacheAssociativity (CacheLevel
,
214 CacheSize64
/= 1024; // Minimum granularity is 1K
216 // Encode the cache size into the format SMBIOS wants
217 if (CacheSize64
< MAX_INT16
) {
218 CacheSize16
= CacheSize64
;
219 CacheSize32
= CacheSize16
;
220 } else if ((CacheSize64
/ 64) < MAX_INT16
) {
221 CacheSize16
= (1 << 15) | (CacheSize64
/ 64);
222 CacheSize32
= (1 << 31) | (CacheSize64
/ 64);
224 if ((CacheSize64
/ 1024) <= 2047) {
225 CacheSize32
= CacheSize64
;
227 CacheSize32
= (1 << 31) | (CacheSize64
/ 64);
233 Type7Record
->MaximumCacheSize
= CacheSize16
;
234 Type7Record
->InstalledSize
= CacheSize16
;
235 Type7Record
->MaximumCacheSize2
= CacheSize32
;
236 Type7Record
->InstalledSize2
= CacheSize32
;
238 switch (Associativity
) {
240 Type7Record
->Associativity
= CacheAssociativity2Way
;
243 Type7Record
->Associativity
= CacheAssociativity4Way
;
246 Type7Record
->Associativity
= CacheAssociativity8Way
;
249 Type7Record
->Associativity
= CacheAssociativity12Way
;
252 Type7Record
->Associativity
= CacheAssociativity16Way
;
255 Type7Record
->Associativity
= CacheAssociativity20Way
;
258 Type7Record
->Associativity
= CacheAssociativity24Way
;
261 Type7Record
->Associativity
= CacheAssociativity32Way
;
264 Type7Record
->Associativity
= CacheAssociativity48Way
;
267 Type7Record
->Associativity
= CacheAssociativity64Way
;
270 Type7Record
->Associativity
= CacheAssociativityOther
;
274 Type7Record
->CacheConfiguration
= (CacheModeUnknown
<< CACHE_OPERATION_MODE_SHIFT
) |
275 (1 << CACHE_ENABLED_SHIFT
) |
276 (CacheLocationUnknown
<< CACHE_LOCATION_SHIFT
) |
277 (0 << CACHE_SOCKETED_SHIFT
) |
282 /** Allocates and initializes an SMBIOS_TABLE_TYPE7 structure.
284 @param[in] CacheLevel The cache level (L1-L7).
285 @param[in] DataCache Cache is a data cache.
286 @param[in] UnifiedCache Cache is a unified cache.
288 @return A pointer to the Type 7 structure. Returns NULL on failure.
291 AllocateAndInitCacheInformation (
293 IN BOOLEAN DataCache
,
294 IN BOOLEAN UnifiedCache
297 SMBIOS_TABLE_TYPE7
*Type7Record
;
298 EFI_STRING CacheSocketStr
;
299 UINTN CacheSocketStrLen
;
300 UINTN StringBufferSize
;
301 CHAR8
*OptionalStrStart
;
304 // Allocate and fetch the cache description
305 StringBufferSize
= sizeof (CHAR16
) * SMBIOS_STRING_MAX_LENGTH
;
306 CacheSocketStr
= AllocateZeroPool (StringBufferSize
);
307 if (CacheSocketStr
== NULL
) {
311 CacheSocketStrLen
= GetCacheSocketStr (CacheLevel
,
316 TableSize
= sizeof (SMBIOS_TABLE_TYPE7
) + CacheSocketStrLen
+ 1 + 1;
317 Type7Record
= AllocateZeroPool (TableSize
);
318 if (Type7Record
== NULL
) {
319 FreePool(CacheSocketStr
);
323 Type7Record
->Hdr
.Type
= EFI_SMBIOS_TYPE_CACHE_INFORMATION
;
324 Type7Record
->Hdr
.Length
= sizeof (SMBIOS_TABLE_TYPE7
);
325 Type7Record
->Hdr
.Handle
= SMBIOS_HANDLE_PI_RESERVED
;
327 Type7Record
->SocketDesignation
= 1;
329 Type7Record
->SupportedSRAMType
.Unknown
= 1;
330 Type7Record
->CurrentSRAMType
.Unknown
= 1;
331 Type7Record
->CacheSpeed
= 0;
332 Type7Record
->ErrorCorrectionType
= CacheErrorUnknown
;
334 OptionalStrStart
= (CHAR8
*)(Type7Record
+ 1);
335 UnicodeStrToAsciiStrS (CacheSocketStr
, OptionalStrStart
, CacheSocketStrLen
+ 1);
336 FreePool (CacheSocketStr
);
342 Add Type 7 SMBIOS Record for Cache Information.
344 @param[in] ProcessorIndex Processor number of specified processor.
345 @param[out] L1CacheHandle Pointer to the handle of the L1 Cache SMBIOS record.
346 @param[out] L2CacheHandle Pointer to the handle of the L2 Cache SMBIOS record.
347 @param[out] L3CacheHandle Pointer to the handle of the L3 Cache SMBIOS record.
351 AddSmbiosCacheTypeTable (
352 IN UINTN ProcessorIndex
,
353 OUT EFI_SMBIOS_HANDLE
*L1CacheHandle
,
354 OUT EFI_SMBIOS_HANDLE
*L2CacheHandle
,
355 OUT EFI_SMBIOS_HANDLE
*L3CacheHandle
359 SMBIOS_TABLE_TYPE7
*Type7Record
;
360 EFI_SMBIOS_HANDLE SmbiosHandle
;
363 BOOLEAN DataCacheType
;
364 BOOLEAN SeparateCaches
;
366 Status
= EFI_SUCCESS
;
370 // See if there's an L1 cache present.
371 MaxCacheLevel
= SmbiosProcessorGetMaxCacheLevel ();
373 if (MaxCacheLevel
< 1) {
377 for (CacheLevel
= 1; CacheLevel
<= MaxCacheLevel
; CacheLevel
++) {
380 SeparateCaches
= SmbiosProcessorHasSeparateCaches (CacheLevel
);
382 // At each level of cache, we can have a single type (unified, instruction or data),
383 // or two types - separate data and instruction caches. If we have separate
384 // instruction and data caches, then on the first iteration (CacheSubLevel = 0)
385 // process the instruction cache.
386 for (DataCacheType
= 0; DataCacheType
<= 1; DataCacheType
++) {
387 // If there's no separate data/instruction cache, skip the second iteration
388 if (DataCacheType
== 1 && !SeparateCaches
) {
392 Type7Record
= AllocateAndInitCacheInformation (CacheLevel
,
396 if (Type7Record
== NULL
) {
400 ConfigureCacheArchitectureInformation(CacheLevel
,
406 // Allow the platform to fill in other information such as speed, SRAM type etc.
407 if (!OemGetCacheInformation (ProcessorIndex
, CacheLevel
,
408 DataCacheType
, !SeparateCaches
, Type7Record
)) {
412 SmbiosHandle
= SMBIOS_HANDLE_PI_RESERVED
;
413 // Finally, install the table
414 Status
= mSmbios
->Add (mSmbios
, NULL
, &SmbiosHandle
,
415 (EFI_SMBIOS_TABLE_HEADER
*)Type7Record
);
416 if (EFI_ERROR (Status
)) {
420 // Config L1/L2/L3 Cache Handle
421 switch (CacheLevel
) {
423 *L1CacheHandle
= SmbiosHandle
;
426 *L2CacheHandle
= SmbiosHandle
;
429 *L3CacheHandle
= SmbiosHandle
;
438 /** Allocates a Type 4 Processor Information structure and sets the
439 strings following the data fields.
441 @param[out] Type4Record The Type 4 structure to allocate and initialize
442 @param[in] ProcessorIndex The index of the processor
443 @param[in] Populated Whether the specified processor is
446 @retval EFI_SUCCESS The Type 4 structure was successfully
447 allocated and the strings initialized.
448 @retval EFI_OUT_OF_RESOURCES Could not allocate memory needed.
451 AllocateType4AndSetProcessorInformationStrings (
452 SMBIOS_TABLE_TYPE4
**Type4Record
,
453 UINT8 ProcessorIndex
,
458 EFI_STRING_ID ProcessorManu
;
459 EFI_STRING_ID ProcessorVersion
;
460 EFI_STRING_ID SerialNumber
;
461 EFI_STRING_ID AssetTag
;
462 EFI_STRING_ID PartNumber
;
463 EFI_STRING ProcessorStr
;
464 EFI_STRING ProcessorManuStr
;
465 EFI_STRING ProcessorVersionStr
;
466 EFI_STRING SerialNumberStr
;
467 EFI_STRING AssetTagStr
;
468 EFI_STRING PartNumberStr
;
469 CHAR8
*OptionalStrStart
;
471 UINTN ProcessorStrLen
;
472 UINTN ProcessorManuStrLen
;
473 UINTN ProcessorVersionStrLen
;
474 UINTN SerialNumberStrLen
;
475 UINTN AssetTagStrLen
;
476 UINTN PartNumberStrLen
;
478 UINTN StringBufferSize
;
480 Status
= EFI_SUCCESS
;
482 ProcessorManuStr
= NULL
;
483 ProcessorVersionStr
= NULL
;
484 SerialNumberStr
= NULL
;
486 PartNumberStr
= NULL
;
488 ProcessorManu
= STRING_TOKEN (STR_PROCESSOR_MANUFACTURE
);
489 ProcessorVersion
= STRING_TOKEN (STR_PROCESSOR_VERSION
);
490 SerialNumber
= STRING_TOKEN (STR_PROCESSOR_SERIAL_NUMBER
);
491 AssetTag
= STRING_TOKEN (STR_PROCESSOR_ASSET_TAG
);
492 PartNumber
= STRING_TOKEN (STR_PROCESSOR_PART_NUMBER
);
494 SET_HII_STRING_IF_PCD_NOT_EMPTY (PcdProcessorManufacturer
, ProcessorManu
);
495 SET_HII_STRING_IF_PCD_NOT_EMPTY (PcdProcessorVersion
, ProcessorVersion
);
496 SET_HII_STRING_IF_PCD_NOT_EMPTY (PcdProcessorSerialNumber
, SerialNumber
);
497 SET_HII_STRING_IF_PCD_NOT_EMPTY (PcdProcessorAssetTag
, AssetTag
);
498 SET_HII_STRING_IF_PCD_NOT_EMPTY (PcdProcessorPartNumber
, PartNumber
);
500 // Processor Designation
501 StringBufferSize
= sizeof (CHAR16
) * SMBIOS_STRING_MAX_LENGTH
;
502 ProcessorStr
= AllocateZeroPool (StringBufferSize
);
503 if (ProcessorStr
== NULL
) {
504 return EFI_OUT_OF_RESOURCES
;
507 ProcessorStrLen
= UnicodeSPrint (ProcessorStr
, StringBufferSize
,
508 L
"CPU%02d", ProcessorIndex
+ 1);
510 // Processor Manufacture
511 ProcessorManuStr
= HiiGetPackageString (&gEfiCallerIdGuid
, ProcessorManu
, NULL
);
512 ProcessorManuStrLen
= StrLen (ProcessorManuStr
);
515 ProcessorVersionStr
= HiiGetPackageString (&gEfiCallerIdGuid
, ProcessorVersion
, NULL
);
516 ProcessorVersionStrLen
= StrLen (ProcessorVersionStr
);
519 SerialNumberStr
= HiiGetPackageString (&gEfiCallerIdGuid
, SerialNumber
, NULL
);
520 SerialNumberStrLen
= StrLen (SerialNumberStr
);
523 AssetTagStr
= HiiGetPackageString (&gEfiCallerIdGuid
, AssetTag
, NULL
);
524 AssetTagStrLen
= StrLen (AssetTagStr
);
527 PartNumberStr
= HiiGetPackageString (&gEfiCallerIdGuid
, PartNumber
, NULL
);
528 PartNumberStrLen
= StrLen (PartNumberStr
);
530 TotalSize
= sizeof (SMBIOS_TABLE_TYPE4
) +
531 ProcessorStrLen
+ 1 +
532 ProcessorManuStrLen
+ 1 +
533 ProcessorVersionStrLen
+ 1 +
534 SerialNumberStrLen
+ 1 +
536 PartNumberStrLen
+ 1 + 1;
538 *Type4Record
= AllocateZeroPool (TotalSize
);
539 if (*Type4Record
== NULL
) {
540 Status
= EFI_OUT_OF_RESOURCES
;
544 CopyMem (*Type4Record
, &mSmbiosProcessorTableTemplate
, sizeof (SMBIOS_TABLE_TYPE4
));
546 OptionalStrStart
= (CHAR8
*)(*Type4Record
+ 1);
547 UnicodeStrToAsciiStrS (
553 StrStart
= OptionalStrStart
+ ProcessorStrLen
+ 1;
554 UnicodeStrToAsciiStrS (
557 ProcessorManuStrLen
+ 1
560 StrStart
+= ProcessorManuStrLen
+ 1;
561 UnicodeStrToAsciiStrS (
564 ProcessorVersionStrLen
+ 1
567 StrStart
+= ProcessorVersionStrLen
+ 1;
568 UnicodeStrToAsciiStrS (
571 SerialNumberStrLen
+ 1
574 StrStart
+= SerialNumberStrLen
+ 1;
575 UnicodeStrToAsciiStrS (
581 StrStart
+= AssetTagStrLen
+ 1;
582 UnicodeStrToAsciiStrS (
589 FreePool (ProcessorStr
);
590 FreePool (ProcessorManuStr
);
591 FreePool (ProcessorVersionStr
);
592 FreePool (SerialNumberStr
);
593 FreePool (AssetTagStr
);
594 FreePool (PartNumberStr
);
600 Add Type 4 SMBIOS Record for Processor Information.
602 @param[in] ProcessorIndex Processor index of specified processor.
606 AddSmbiosProcessorTypeTable (
607 IN UINTN ProcessorIndex
611 SMBIOS_TABLE_TYPE4
*Type4Record
;
612 EFI_SMBIOS_HANDLE SmbiosHandle
;
613 EFI_SMBIOS_HANDLE L1CacheHandle
;
614 EFI_SMBIOS_HANDLE L2CacheHandle
;
615 EFI_SMBIOS_HANDLE L3CacheHandle
;
616 UINT8
*LegacyVoltage
;
617 PROCESSOR_STATUS_DATA ProcessorStatus
;
619 PROCESSOR_CHARACTERISTIC_FLAGS ProcessorCharacteristics
;
620 OEM_MISC_PROCESSOR_DATA MiscProcessorData
;
621 BOOLEAN ProcessorPopulated
;
625 MiscProcessorData
.Voltage
= 0;
626 MiscProcessorData
.CurrentSpeed
= 0;
627 MiscProcessorData
.CoreCount
= 0;
628 MiscProcessorData
.CoresEnabled
= 0;
629 MiscProcessorData
.ThreadCount
= 0;
630 MiscProcessorData
.MaxSpeed
= 0;
631 L1CacheHandle
= 0xFFFF;
632 L2CacheHandle
= 0xFFFF;
633 L3CacheHandle
= 0xFFFF;
635 ProcessorPopulated
= OemIsProcessorPresent (ProcessorIndex
);
637 Status
= AllocateType4AndSetProcessorInformationStrings (
642 if (EFI_ERROR (Status
)) {
646 OemGetProcessorInformation (ProcessorIndex
,
648 (PROCESSOR_CHARACTERISTIC_FLAGS
*)
649 &Type4Record
->ProcessorCharacteristics
,
652 if (ProcessorPopulated
) {
653 AddSmbiosCacheTypeTable (ProcessorIndex
, &L1CacheHandle
,
654 &L2CacheHandle
, &L3CacheHandle
);
657 LegacyVoltage
= (UINT8
*)&Type4Record
->Voltage
;
659 *LegacyVoltage
= MiscProcessorData
.Voltage
;
660 Type4Record
->CurrentSpeed
= MiscProcessorData
.CurrentSpeed
;
661 Type4Record
->MaxSpeed
= MiscProcessorData
.MaxSpeed
;
662 Type4Record
->Status
= ProcessorStatus
.Data
;
663 Type4Record
->L1CacheHandle
= L1CacheHandle
;
664 Type4Record
->L2CacheHandle
= L2CacheHandle
;
665 Type4Record
->L3CacheHandle
= L3CacheHandle
;
666 Type4Record
->CoreCount
= MiscProcessorData
.CoreCount
;
667 Type4Record
->CoreCount2
= MiscProcessorData
.CoreCount
;
668 Type4Record
->EnabledCoreCount
= MiscProcessorData
.CoresEnabled
;
669 Type4Record
->EnabledCoreCount2
= MiscProcessorData
.CoresEnabled
;
670 Type4Record
->ThreadCount
= MiscProcessorData
.ThreadCount
;
671 Type4Record
->ThreadCount2
= MiscProcessorData
.ThreadCount
;
673 Type4Record
->CurrentSpeed
= GetCpuFrequency (ProcessorIndex
);
674 Type4Record
->ExternalClock
=
675 (UINT16
)(SmbiosGetExternalClockFrequency () / 1000 / 1000);
677 ProcessorId
= (UINT64
*)&Type4Record
->ProcessorId
;
678 *ProcessorId
= SmbiosGetProcessorId ();
680 ProcessorCharacteristics
= SmbiosGetProcessorCharacteristics ();
681 Type4Record
->ProcessorCharacteristics
|= *((UINT64
*)&ProcessorCharacteristics
);
683 Type4Record
->ProcessorFamily
= SmbiosGetProcessorFamily ();
684 Type4Record
->ProcessorFamily2
= SmbiosGetProcessorFamily2 ();
686 SmbiosHandle
= SMBIOS_HANDLE_PI_RESERVED
;
687 Status
= mSmbios
->Add (mSmbios
, NULL
, &SmbiosHandle
,
688 (EFI_SMBIOS_TABLE_HEADER
*)Type4Record
);
690 if (EFI_ERROR (Status
)) {
691 DEBUG ((DEBUG_ERROR
, "[%a]:[%dL] Smbios Type04 Table Log Failed! %r \n",
692 __FUNCTION__
, __LINE__
, Status
));
694 FreePool (Type4Record
);
700 Standard EFI driver point.
702 @param ImageHandle Handle for the image of this driver
703 @param SystemTable Pointer to the EFI System Table
705 @retval EFI_SUCCESS The data was successfully stored.
710 ProcessorSubClassEntryPoint(
711 IN EFI_HANDLE ImageHandle
,
712 IN EFI_SYSTEM_TABLE
*SystemTable
716 UINT32 ProcessorIndex
;
719 // Locate dependent protocols
721 Status
= gBS
->LocateProtocol (&gEfiSmbiosProtocolGuid
, NULL
, (VOID
**)&mSmbios
);
722 if (EFI_ERROR (Status
)) {
723 DEBUG ((DEBUG_ERROR
, "Could not locate SMBIOS protocol. %r\n", Status
));
728 // Add our default strings to the HII database. They will be modified later.
730 mHiiHandle
= HiiAddPackages (&gEfiCallerIdGuid
,
732 ProcessorSubClassStrings
,
736 if (mHiiHandle
== NULL
) {
737 return EFI_OUT_OF_RESOURCES
;
741 // Add SMBIOS tables for populated sockets.
743 for (ProcessorIndex
= 0; ProcessorIndex
< OemGetMaxProcessors (); ProcessorIndex
++) {
744 Status
= AddSmbiosProcessorTypeTable (ProcessorIndex
);
745 if (EFI_ERROR (Status
)) {
746 DEBUG ((DEBUG_ERROR
, "Add Processor Type Table Failed! %r.\n", Status
));