]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c
ArmPkg/Smbios: Fix max cache size 2 wrong issue
[mirror_edk2.git] / ArmPkg / Universal / Smbios / ProcessorSubClassDxe / ProcessorSubClass.c
1 /** @file
2 ProcessorSubClass.c
3
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
8
9 **/
10
11 #include <Uefi.h>
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>
29
30 #include "SmbiosProcessor.h"
31
32 extern UINT8 ProcessorSubClassStrings[];
33
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
38
39 typedef enum {
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
44 CacheModeMax
45 } CACHE_OPERATION_MODE;
46
47 typedef enum {
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
52 CacheLocationMax
53 } CACHE_LOCATION;
54
55 EFI_HII_HANDLE mHiiHandle;
56
57 EFI_SMBIOS_PROTOCOL *mSmbios;
58
59 SMBIOS_TABLE_TYPE4 mSmbiosProcessorTableTemplate = {
60 { // Hdr
61 EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION, // Type
62 sizeof (SMBIOS_TABLE_TYPE4), // Length
63 0 // Handle
64 },
65 1, // Socket
66 CentralProcessor, // ProcessorType
67 ProcessorFamilyIndicatorFamily2, // ProcessorFamily
68 2, // ProcessorManufacture
69 { // ProcessorId
70 { // Signature
71 0
72 },
73 { // FeatureFlags
74 0
75 }
76 },
77 3, // ProcessorVersion
78 { // Voltage
79 0
80 },
81 0, // ExternalClock
82 0, // MaxSpeed
83 0, // CurrentSpeed
84 0, // Status
85 ProcessorUpgradeUnknown, // ProcessorUpgrade
86 0xFFFF, // L1CacheHandle
87 0xFFFF, // L2CacheHandle
88 0xFFFF, // L3CacheHandle
89 4, // SerialNumber
90 5, // AssetTag
91 6, // PartNumber
92 0, // CoreCount
93 0, //EnabledCoreCount
94 0, // ThreadCount
95 0, // ProcessorCharacteristics
96 ProcessorFamilyARM, // ProcessorFamily2
97 0, // CoreCount2
98 0, // EnabledCoreCount2
99 0 // ThreadCount2
100 };
101
102 /** Sets the HII variable `StringId` is `Pcd` isn't empty.
103
104 @param Pcd The FixedAtBuild PCD that contains the string to fetch.
105 @param StringId The string identifier to set.
106 **/
107 #define SET_HII_STRING_IF_PCD_NOT_EMPTY(Pcd, StringId) \
108 do { \
109 CHAR16 *Str; \
110 Str = (CHAR16*)PcdGetPtr (Pcd); \
111 if (StrLen (Str) > 0) { \
112 HiiSetString (mHiiHandle, StringId, Str, NULL); \
113 } \
114 } while (0)
115
116 /** Fetches the specified processor's frequency in Hz.
117
118 @param ProcessorNumber The processor number
119
120 @return The clock frequency in MHz
121
122 **/
123 UINT16
124 GetCpuFrequency (
125 IN UINT8 ProcessorNumber
126 )
127 {
128 return (UINT16)(OemGetCpuFreq (ProcessorNumber) / 1000 / 1000);
129 }
130
131 /** Gets a description of the specified cache.
132
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
137
138 @return The number of Unicode characters in CacheSocketStr not including the
139 terminating NUL.
140 **/
141 UINTN
142 GetCacheSocketStr (
143 IN UINT8 CacheLevel,
144 IN BOOLEAN DataCache,
145 IN BOOLEAN UnifiedCache,
146 OUT CHAR16 *CacheSocketStr
147 )
148 {
149 UINTN CacheSocketStrLen;
150
151 if (CacheLevel == CpuCacheL1 && !DataCache && !UnifiedCache) {
152 CacheSocketStrLen = UnicodeSPrint (
153 CacheSocketStr,
154 SMBIOS_STRING_MAX_LENGTH - 1,
155 L"L%x Instruction Cache",
156 CacheLevel);
157 } else if (CacheLevel == CpuCacheL1 && DataCache) {
158 CacheSocketStrLen = UnicodeSPrint (CacheSocketStr,
159 SMBIOS_STRING_MAX_LENGTH - 1,
160 L"L%x Data Cache",
161 CacheLevel);
162 } else {
163 CacheSocketStrLen = UnicodeSPrint (CacheSocketStr,
164 SMBIOS_STRING_MAX_LENGTH - 1,
165 L"L%x Cache",
166 CacheLevel);
167 }
168
169 return CacheSocketStrLen;
170 }
171
172 /** Fills in the Type 7 record with the cache architecture information
173 read from the CPU registers.
174
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.
179
180 **/
181 VOID
182 ConfigureCacheArchitectureInformation (
183 IN UINT8 CacheLevel,
184 IN BOOLEAN DataCache,
185 IN BOOLEAN UnifiedCache,
186 OUT SMBIOS_TABLE_TYPE7 *Type7Record
187 )
188 {
189 UINT8 Associativity;
190 UINT32 CacheSize32;
191 UINT16 CacheSize16;
192 UINT64 CacheSize64;
193
194 if (!DataCache && !UnifiedCache) {
195 Type7Record->SystemCacheType = CacheTypeInstruction;
196 } else if (DataCache) {
197 Type7Record->SystemCacheType = CacheTypeData;
198 } else if (UnifiedCache) {
199 Type7Record->SystemCacheType = CacheTypeUnified;
200 } else {
201 ASSERT(FALSE);
202 }
203
204 CacheSize64 = SmbiosProcessorGetCacheSize (CacheLevel,
205 DataCache,
206 UnifiedCache
207 );
208
209 Associativity = SmbiosProcessorGetCacheAssociativity (CacheLevel,
210 DataCache,
211 UnifiedCache
212 );
213
214 CacheSize64 /= 1024; // Minimum granularity is 1K
215
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);
223 } else {
224 if ((CacheSize64 / 1024) <= 2047) {
225 CacheSize32 = CacheSize64;
226 } else {
227 CacheSize32 = (1 << 31) | (CacheSize64 / 64);
228 }
229
230 CacheSize16 = -1;
231 }
232
233 Type7Record->MaximumCacheSize = CacheSize16;
234 Type7Record->InstalledSize = CacheSize16;
235 Type7Record->MaximumCacheSize2 = CacheSize32;
236 Type7Record->InstalledSize2 = CacheSize32;
237
238 switch (Associativity) {
239 case 2:
240 Type7Record->Associativity = CacheAssociativity2Way;
241 break;
242 case 4:
243 Type7Record->Associativity = CacheAssociativity4Way;
244 break;
245 case 8:
246 Type7Record->Associativity = CacheAssociativity8Way;
247 break;
248 case 12:
249 Type7Record->Associativity = CacheAssociativity12Way;
250 break;
251 case 16:
252 Type7Record->Associativity = CacheAssociativity16Way;
253 break;
254 case 20:
255 Type7Record->Associativity = CacheAssociativity20Way;
256 break;
257 case 24:
258 Type7Record->Associativity = CacheAssociativity24Way;
259 break;
260 case 32:
261 Type7Record->Associativity = CacheAssociativity32Way;
262 break;
263 case 48:
264 Type7Record->Associativity = CacheAssociativity48Way;
265 break;
266 case 64:
267 Type7Record->Associativity = CacheAssociativity64Way;
268 break;
269 default:
270 Type7Record->Associativity = CacheAssociativityOther;
271 break;
272 }
273
274 Type7Record->CacheConfiguration = (CacheModeUnknown << CACHE_OPERATION_MODE_SHIFT) |
275 (1 << CACHE_ENABLED_SHIFT) |
276 (CacheLocationUnknown << CACHE_LOCATION_SHIFT) |
277 (0 << CACHE_SOCKETED_SHIFT) |
278 (CacheLevel - 1);
279 }
280
281
282 /** Allocates and initializes an SMBIOS_TABLE_TYPE7 structure.
283
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.
287
288 @return A pointer to the Type 7 structure. Returns NULL on failure.
289 **/
290 SMBIOS_TABLE_TYPE7 *
291 AllocateAndInitCacheInformation (
292 IN UINT8 CacheLevel,
293 IN BOOLEAN DataCache,
294 IN BOOLEAN UnifiedCache
295 )
296 {
297 SMBIOS_TABLE_TYPE7 *Type7Record;
298 EFI_STRING CacheSocketStr;
299 UINTN CacheSocketStrLen;
300 UINTN StringBufferSize;
301 CHAR8 *OptionalStrStart;
302 UINTN TableSize;
303
304 // Allocate and fetch the cache description
305 StringBufferSize = sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH;
306 CacheSocketStr = AllocateZeroPool (StringBufferSize);
307 if (CacheSocketStr == NULL) {
308 return NULL;
309 }
310
311 CacheSocketStrLen = GetCacheSocketStr (CacheLevel,
312 DataCache,
313 UnifiedCache,
314 CacheSocketStr);
315
316 TableSize = sizeof (SMBIOS_TABLE_TYPE7) + CacheSocketStrLen + 1 + 1;
317 Type7Record = AllocateZeroPool (TableSize);
318 if (Type7Record == NULL) {
319 FreePool(CacheSocketStr);
320 return NULL;
321 }
322
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;
326
327 Type7Record->SocketDesignation = 1;
328
329 Type7Record->SupportedSRAMType.Unknown = 1;
330 Type7Record->CurrentSRAMType.Unknown = 1;
331 Type7Record->CacheSpeed = 0;
332 Type7Record->ErrorCorrectionType = CacheErrorUnknown;
333
334 OptionalStrStart = (CHAR8 *)(Type7Record + 1);
335 UnicodeStrToAsciiStrS (CacheSocketStr, OptionalStrStart, CacheSocketStrLen + 1);
336 FreePool (CacheSocketStr);
337
338 return Type7Record;
339 }
340
341 /**
342 Add Type 7 SMBIOS Record for Cache Information.
343
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.
348
349 **/
350 VOID
351 AddSmbiosCacheTypeTable (
352 IN UINTN ProcessorIndex,
353 OUT EFI_SMBIOS_HANDLE *L1CacheHandle,
354 OUT EFI_SMBIOS_HANDLE *L2CacheHandle,
355 OUT EFI_SMBIOS_HANDLE *L3CacheHandle
356 )
357 {
358 EFI_STATUS Status;
359 SMBIOS_TABLE_TYPE7 *Type7Record;
360 EFI_SMBIOS_HANDLE SmbiosHandle;
361 UINT8 CacheLevel;
362 UINT8 MaxCacheLevel;
363 BOOLEAN DataCacheType;
364 BOOLEAN SeparateCaches;
365
366 Status = EFI_SUCCESS;
367
368 MaxCacheLevel = 0;
369
370 // See if there's an L1 cache present.
371 MaxCacheLevel = SmbiosProcessorGetMaxCacheLevel ();
372
373 if (MaxCacheLevel < 1) {
374 return;
375 }
376
377 for (CacheLevel = 1; CacheLevel <= MaxCacheLevel; CacheLevel++) {
378 Type7Record = NULL;
379
380 SeparateCaches = SmbiosProcessorHasSeparateCaches (CacheLevel);
381
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) {
389 continue;
390 }
391
392 Type7Record = AllocateAndInitCacheInformation (CacheLevel,
393 DataCacheType,
394 !SeparateCaches
395 );
396 if (Type7Record == NULL) {
397 continue;
398 }
399
400 ConfigureCacheArchitectureInformation(CacheLevel,
401 DataCacheType,
402 !SeparateCaches,
403 Type7Record
404 );
405
406 // Allow the platform to fill in other information such as speed, SRAM type etc.
407 if (!OemGetCacheInformation (ProcessorIndex, CacheLevel,
408 DataCacheType, !SeparateCaches, Type7Record)) {
409 continue;
410 }
411
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)) {
417 continue;
418 }
419
420 // Config L1/L2/L3 Cache Handle
421 switch (CacheLevel) {
422 case CpuCacheL1:
423 *L1CacheHandle = SmbiosHandle;
424 break;
425 case CpuCacheL2:
426 *L2CacheHandle = SmbiosHandle;
427 break;
428 case CpuCacheL3:
429 *L3CacheHandle = SmbiosHandle;
430 break;
431 default:
432 break;
433 }
434 }
435 }
436 }
437
438 /** Allocates a Type 4 Processor Information structure and sets the
439 strings following the data fields.
440
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
444 populated.
445
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.
449 **/
450 EFI_STATUS
451 AllocateType4AndSetProcessorInformationStrings (
452 SMBIOS_TABLE_TYPE4 **Type4Record,
453 UINT8 ProcessorIndex,
454 BOOLEAN Populated
455 )
456 {
457 EFI_STATUS Status;
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;
470 CHAR8 *StrStart;
471 UINTN ProcessorStrLen;
472 UINTN ProcessorManuStrLen;
473 UINTN ProcessorVersionStrLen;
474 UINTN SerialNumberStrLen;
475 UINTN AssetTagStrLen;
476 UINTN PartNumberStrLen;
477 UINTN TotalSize;
478 UINTN StringBufferSize;
479
480 Status = EFI_SUCCESS;
481
482 ProcessorManuStr = NULL;
483 ProcessorVersionStr = NULL;
484 SerialNumberStr = NULL;
485 AssetTagStr = NULL;
486 PartNumberStr = NULL;
487
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);
493
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);
499
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;
505 }
506
507 ProcessorStrLen = UnicodeSPrint (ProcessorStr, StringBufferSize,
508 L"CPU%02d", ProcessorIndex + 1);
509
510 // Processor Manufacture
511 ProcessorManuStr = HiiGetPackageString (&gEfiCallerIdGuid, ProcessorManu, NULL);
512 ProcessorManuStrLen = StrLen (ProcessorManuStr);
513
514 // Processor Version
515 ProcessorVersionStr = HiiGetPackageString (&gEfiCallerIdGuid, ProcessorVersion, NULL);
516 ProcessorVersionStrLen = StrLen (ProcessorVersionStr);
517
518 // Serial Number
519 SerialNumberStr = HiiGetPackageString (&gEfiCallerIdGuid, SerialNumber, NULL);
520 SerialNumberStrLen = StrLen (SerialNumberStr);
521
522 // Asset Tag
523 AssetTagStr = HiiGetPackageString (&gEfiCallerIdGuid, AssetTag, NULL);
524 AssetTagStrLen = StrLen (AssetTagStr);
525
526 // Part Number
527 PartNumberStr = HiiGetPackageString (&gEfiCallerIdGuid, PartNumber, NULL);
528 PartNumberStrLen = StrLen (PartNumberStr);
529
530 TotalSize = sizeof (SMBIOS_TABLE_TYPE4) +
531 ProcessorStrLen + 1 +
532 ProcessorManuStrLen + 1 +
533 ProcessorVersionStrLen + 1 +
534 SerialNumberStrLen + 1 +
535 AssetTagStrLen + 1 +
536 PartNumberStrLen + 1 + 1;
537
538 *Type4Record = AllocateZeroPool (TotalSize);
539 if (*Type4Record == NULL) {
540 Status = EFI_OUT_OF_RESOURCES;
541 goto Exit;
542 }
543
544 CopyMem (*Type4Record, &mSmbiosProcessorTableTemplate, sizeof (SMBIOS_TABLE_TYPE4));
545
546 OptionalStrStart = (CHAR8 *)(*Type4Record + 1);
547 UnicodeStrToAsciiStrS (
548 ProcessorStr,
549 OptionalStrStart,
550 ProcessorStrLen + 1
551 );
552
553 StrStart = OptionalStrStart + ProcessorStrLen + 1;
554 UnicodeStrToAsciiStrS (
555 ProcessorManuStr,
556 StrStart,
557 ProcessorManuStrLen + 1
558 );
559
560 StrStart += ProcessorManuStrLen + 1;
561 UnicodeStrToAsciiStrS (
562 ProcessorVersionStr,
563 StrStart,
564 ProcessorVersionStrLen + 1
565 );
566
567 StrStart += ProcessorVersionStrLen + 1;
568 UnicodeStrToAsciiStrS (
569 SerialNumberStr,
570 StrStart,
571 SerialNumberStrLen + 1
572 );
573
574 StrStart += SerialNumberStrLen + 1;
575 UnicodeStrToAsciiStrS (
576 AssetTagStr,
577 StrStart,
578 AssetTagStrLen + 1
579 );
580
581 StrStart += AssetTagStrLen + 1;
582 UnicodeStrToAsciiStrS (
583 PartNumberStr,
584 StrStart,
585 PartNumberStrLen + 1
586 );
587
588 Exit:
589 FreePool (ProcessorStr);
590 FreePool (ProcessorManuStr);
591 FreePool (ProcessorVersionStr);
592 FreePool (SerialNumberStr);
593 FreePool (AssetTagStr);
594 FreePool (PartNumberStr);
595
596 return Status;
597 }
598
599 /**
600 Add Type 4 SMBIOS Record for Processor Information.
601
602 @param[in] ProcessorIndex Processor index of specified processor.
603
604 **/
605 EFI_STATUS
606 AddSmbiosProcessorTypeTable (
607 IN UINTN ProcessorIndex
608 )
609 {
610 EFI_STATUS Status;
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;
618 UINT64 *ProcessorId;
619 PROCESSOR_CHARACTERISTIC_FLAGS ProcessorCharacteristics;
620 OEM_MISC_PROCESSOR_DATA MiscProcessorData;
621 BOOLEAN ProcessorPopulated;
622
623 Type4Record = NULL;
624
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;
634
635 ProcessorPopulated = OemIsProcessorPresent (ProcessorIndex);
636
637 Status = AllocateType4AndSetProcessorInformationStrings (
638 &Type4Record,
639 ProcessorIndex,
640 ProcessorPopulated
641 );
642 if (EFI_ERROR (Status)) {
643 return Status;
644 }
645
646 OemGetProcessorInformation (ProcessorIndex,
647 &ProcessorStatus,
648 (PROCESSOR_CHARACTERISTIC_FLAGS*)
649 &Type4Record->ProcessorCharacteristics,
650 &MiscProcessorData);
651
652 if (ProcessorPopulated) {
653 AddSmbiosCacheTypeTable (ProcessorIndex, &L1CacheHandle,
654 &L2CacheHandle, &L3CacheHandle);
655 }
656
657 LegacyVoltage = (UINT8*)&Type4Record->Voltage;
658
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;
672
673 Type4Record->CurrentSpeed = GetCpuFrequency (ProcessorIndex);
674 Type4Record->ExternalClock =
675 (UINT16)(SmbiosGetExternalClockFrequency () / 1000 / 1000);
676
677 ProcessorId = (UINT64*)&Type4Record->ProcessorId;
678 *ProcessorId = SmbiosGetProcessorId ();
679
680 ProcessorCharacteristics = SmbiosGetProcessorCharacteristics ();
681 Type4Record->ProcessorCharacteristics |= *((UINT64*)&ProcessorCharacteristics);
682
683 Type4Record->ProcessorFamily = SmbiosGetProcessorFamily ();
684 Type4Record->ProcessorFamily2 = SmbiosGetProcessorFamily2 ();
685
686 SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
687 Status = mSmbios->Add (mSmbios, NULL, &SmbiosHandle,
688 (EFI_SMBIOS_TABLE_HEADER *)Type4Record);
689
690 if (EFI_ERROR (Status)) {
691 DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Smbios Type04 Table Log Failed! %r \n",
692 __FUNCTION__, __LINE__, Status));
693 }
694 FreePool (Type4Record);
695
696 return Status;
697 }
698
699 /**
700 Standard EFI driver point.
701
702 @param ImageHandle Handle for the image of this driver
703 @param SystemTable Pointer to the EFI System Table
704
705 @retval EFI_SUCCESS The data was successfully stored.
706
707 **/
708 EFI_STATUS
709 EFIAPI
710 ProcessorSubClassEntryPoint(
711 IN EFI_HANDLE ImageHandle,
712 IN EFI_SYSTEM_TABLE *SystemTable
713 )
714 {
715 EFI_STATUS Status;
716 UINT32 ProcessorIndex;
717
718 //
719 // Locate dependent protocols
720 //
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));
724 return Status;
725 }
726
727 //
728 // Add our default strings to the HII database. They will be modified later.
729 //
730 mHiiHandle = HiiAddPackages (&gEfiCallerIdGuid,
731 NULL,
732 ProcessorSubClassStrings,
733 NULL,
734 NULL
735 );
736 if (mHiiHandle == NULL) {
737 return EFI_OUT_OF_RESOURCES;
738 }
739
740 //
741 // Add SMBIOS tables for populated sockets.
742 //
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));
747 return Status;
748 }
749 }
750
751 return Status;
752 }