]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c
ArmPkg: Apply uncrustify changes
[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 );
158 } else if ((CacheLevel == CpuCacheL1) && DataCache) {
159 CacheSocketStrLen = UnicodeSPrint (
160 CacheSocketStr,
161 SMBIOS_STRING_MAX_LENGTH - 1,
162 L"L%x Data Cache",
163 CacheLevel
164 );
165 } else {
166 CacheSocketStrLen = UnicodeSPrint (
167 CacheSocketStr,
168 SMBIOS_STRING_MAX_LENGTH - 1,
169 L"L%x Cache",
170 CacheLevel
171 );
172 }
173
174 return CacheSocketStrLen;
175 }
176
177 /** Fills in the Type 7 record with the cache architecture information
178 read from the CPU registers.
179
180 @param[in] CacheLevel Cache level (e.g. L1, L2).
181 @param[in] DataCache Cache is a data cache.
182 @param[in] UnifiedCache Cache is a unified cache.
183 @param[out] Type7Record The Type 7 record to fill in.
184
185 **/
186 VOID
187 ConfigureCacheArchitectureInformation (
188 IN UINT8 CacheLevel,
189 IN BOOLEAN DataCache,
190 IN BOOLEAN UnifiedCache,
191 OUT SMBIOS_TABLE_TYPE7 *Type7Record
192 )
193 {
194 UINT8 Associativity;
195 UINT32 CacheSize32;
196 UINT16 CacheSize16;
197 UINT64 CacheSize64;
198
199 if (!DataCache && !UnifiedCache) {
200 Type7Record->SystemCacheType = CacheTypeInstruction;
201 } else if (DataCache) {
202 Type7Record->SystemCacheType = CacheTypeData;
203 } else if (UnifiedCache) {
204 Type7Record->SystemCacheType = CacheTypeUnified;
205 } else {
206 ASSERT (FALSE);
207 }
208
209 CacheSize64 = SmbiosProcessorGetCacheSize (
210 CacheLevel,
211 DataCache,
212 UnifiedCache
213 );
214
215 Associativity = SmbiosProcessorGetCacheAssociativity (
216 CacheLevel,
217 DataCache,
218 UnifiedCache
219 );
220
221 CacheSize64 /= 1024; // Minimum granularity is 1K
222
223 // Encode the cache size into the format SMBIOS wants
224 if (CacheSize64 < MAX_INT16) {
225 CacheSize16 = CacheSize64;
226 CacheSize32 = CacheSize16;
227 } else if ((CacheSize64 / 64) < MAX_INT16) {
228 CacheSize16 = (1 << 15) | (CacheSize64 / 64);
229 CacheSize32 = (1 << 31) | (CacheSize64 / 64);
230 } else {
231 if ((CacheSize64 / 1024) <= 2047) {
232 CacheSize32 = CacheSize64;
233 } else {
234 CacheSize32 = (1 << 31) | (CacheSize64 / 64);
235 }
236
237 CacheSize16 = -1;
238 }
239
240 Type7Record->MaximumCacheSize = CacheSize16;
241 Type7Record->InstalledSize = CacheSize16;
242 Type7Record->MaximumCacheSize2 = CacheSize32;
243 Type7Record->InstalledSize2 = CacheSize32;
244
245 switch (Associativity) {
246 case 2:
247 Type7Record->Associativity = CacheAssociativity2Way;
248 break;
249 case 4:
250 Type7Record->Associativity = CacheAssociativity4Way;
251 break;
252 case 8:
253 Type7Record->Associativity = CacheAssociativity8Way;
254 break;
255 case 12:
256 Type7Record->Associativity = CacheAssociativity12Way;
257 break;
258 case 16:
259 Type7Record->Associativity = CacheAssociativity16Way;
260 break;
261 case 20:
262 Type7Record->Associativity = CacheAssociativity20Way;
263 break;
264 case 24:
265 Type7Record->Associativity = CacheAssociativity24Way;
266 break;
267 case 32:
268 Type7Record->Associativity = CacheAssociativity32Way;
269 break;
270 case 48:
271 Type7Record->Associativity = CacheAssociativity48Way;
272 break;
273 case 64:
274 Type7Record->Associativity = CacheAssociativity64Way;
275 break;
276 default:
277 Type7Record->Associativity = CacheAssociativityOther;
278 break;
279 }
280
281 Type7Record->CacheConfiguration = (CacheModeUnknown << CACHE_OPERATION_MODE_SHIFT) |
282 (1 << CACHE_ENABLED_SHIFT) |
283 (CacheLocationUnknown << CACHE_LOCATION_SHIFT) |
284 (0 << CACHE_SOCKETED_SHIFT) |
285 (CacheLevel - 1);
286 }
287
288 /** Allocates and initializes an SMBIOS_TABLE_TYPE7 structure.
289
290 @param[in] CacheLevel The cache level (L1-L7).
291 @param[in] DataCache Cache is a data cache.
292 @param[in] UnifiedCache Cache is a unified cache.
293
294 @return A pointer to the Type 7 structure. Returns NULL on failure.
295 **/
296 SMBIOS_TABLE_TYPE7 *
297 AllocateAndInitCacheInformation (
298 IN UINT8 CacheLevel,
299 IN BOOLEAN DataCache,
300 IN BOOLEAN UnifiedCache
301 )
302 {
303 SMBIOS_TABLE_TYPE7 *Type7Record;
304 EFI_STRING CacheSocketStr;
305 UINTN CacheSocketStrLen;
306 UINTN StringBufferSize;
307 CHAR8 *OptionalStrStart;
308 UINTN TableSize;
309
310 // Allocate and fetch the cache description
311 StringBufferSize = sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH;
312 CacheSocketStr = AllocateZeroPool (StringBufferSize);
313 if (CacheSocketStr == NULL) {
314 return NULL;
315 }
316
317 CacheSocketStrLen = GetCacheSocketStr (
318 CacheLevel,
319 DataCache,
320 UnifiedCache,
321 CacheSocketStr
322 );
323
324 TableSize = sizeof (SMBIOS_TABLE_TYPE7) + CacheSocketStrLen + 1 + 1;
325 Type7Record = AllocateZeroPool (TableSize);
326 if (Type7Record == NULL) {
327 FreePool (CacheSocketStr);
328 return NULL;
329 }
330
331 Type7Record->Hdr.Type = EFI_SMBIOS_TYPE_CACHE_INFORMATION;
332 Type7Record->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE7);
333 Type7Record->Hdr.Handle = SMBIOS_HANDLE_PI_RESERVED;
334
335 Type7Record->SocketDesignation = 1;
336
337 Type7Record->SupportedSRAMType.Unknown = 1;
338 Type7Record->CurrentSRAMType.Unknown = 1;
339 Type7Record->CacheSpeed = 0;
340 Type7Record->ErrorCorrectionType = CacheErrorUnknown;
341
342 OptionalStrStart = (CHAR8 *)(Type7Record + 1);
343 UnicodeStrToAsciiStrS (CacheSocketStr, OptionalStrStart, CacheSocketStrLen + 1);
344 FreePool (CacheSocketStr);
345
346 return Type7Record;
347 }
348
349 /**
350 Add Type 7 SMBIOS Record for Cache Information.
351
352 @param[in] ProcessorIndex Processor number of specified processor.
353 @param[out] L1CacheHandle Pointer to the handle of the L1 Cache SMBIOS record.
354 @param[out] L2CacheHandle Pointer to the handle of the L2 Cache SMBIOS record.
355 @param[out] L3CacheHandle Pointer to the handle of the L3 Cache SMBIOS record.
356
357 **/
358 VOID
359 AddSmbiosCacheTypeTable (
360 IN UINTN ProcessorIndex,
361 OUT EFI_SMBIOS_HANDLE *L1CacheHandle,
362 OUT EFI_SMBIOS_HANDLE *L2CacheHandle,
363 OUT EFI_SMBIOS_HANDLE *L3CacheHandle
364 )
365 {
366 EFI_STATUS Status;
367 SMBIOS_TABLE_TYPE7 *Type7Record;
368 EFI_SMBIOS_HANDLE SmbiosHandle;
369 UINT8 CacheLevel;
370 UINT8 MaxCacheLevel;
371 BOOLEAN DataCacheType;
372 BOOLEAN SeparateCaches;
373
374 Status = EFI_SUCCESS;
375
376 MaxCacheLevel = 0;
377
378 // See if there's an L1 cache present.
379 MaxCacheLevel = SmbiosProcessorGetMaxCacheLevel ();
380
381 if (MaxCacheLevel < 1) {
382 return;
383 }
384
385 for (CacheLevel = 1; CacheLevel <= MaxCacheLevel; CacheLevel++) {
386 Type7Record = NULL;
387
388 SeparateCaches = SmbiosProcessorHasSeparateCaches (CacheLevel);
389
390 // At each level of cache, we can have a single type (unified, instruction or data),
391 // or two types - separate data and instruction caches. If we have separate
392 // instruction and data caches, then on the first iteration (CacheSubLevel = 0)
393 // process the instruction cache.
394 for (DataCacheType = 0; DataCacheType <= 1; DataCacheType++) {
395 // If there's no separate data/instruction cache, skip the second iteration
396 if ((DataCacheType == 1) && !SeparateCaches) {
397 continue;
398 }
399
400 Type7Record = AllocateAndInitCacheInformation (
401 CacheLevel,
402 DataCacheType,
403 !SeparateCaches
404 );
405 if (Type7Record == NULL) {
406 continue;
407 }
408
409 ConfigureCacheArchitectureInformation (
410 CacheLevel,
411 DataCacheType,
412 !SeparateCaches,
413 Type7Record
414 );
415
416 // Allow the platform to fill in other information such as speed, SRAM type etc.
417 if (!OemGetCacheInformation (
418 ProcessorIndex,
419 CacheLevel,
420 DataCacheType,
421 !SeparateCaches,
422 Type7Record
423 ))
424 {
425 continue;
426 }
427
428 SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
429 // Finally, install the table
430 Status = mSmbios->Add (
431 mSmbios,
432 NULL,
433 &SmbiosHandle,
434 (EFI_SMBIOS_TABLE_HEADER *)Type7Record
435 );
436 if (EFI_ERROR (Status)) {
437 continue;
438 }
439
440 // Config L1/L2/L3 Cache Handle
441 switch (CacheLevel) {
442 case CpuCacheL1:
443 *L1CacheHandle = SmbiosHandle;
444 break;
445 case CpuCacheL2:
446 *L2CacheHandle = SmbiosHandle;
447 break;
448 case CpuCacheL3:
449 *L3CacheHandle = SmbiosHandle;
450 break;
451 default:
452 break;
453 }
454 }
455 }
456 }
457
458 /** Allocates a Type 4 Processor Information structure and sets the
459 strings following the data fields.
460
461 @param[out] Type4Record The Type 4 structure to allocate and initialize
462 @param[in] ProcessorIndex The index of the processor
463 @param[in] Populated Whether the specified processor is
464 populated.
465
466 @retval EFI_SUCCESS The Type 4 structure was successfully
467 allocated and the strings initialized.
468 @retval EFI_OUT_OF_RESOURCES Could not allocate memory needed.
469 **/
470 EFI_STATUS
471 AllocateType4AndSetProcessorInformationStrings (
472 SMBIOS_TABLE_TYPE4 **Type4Record,
473 UINT8 ProcessorIndex,
474 BOOLEAN Populated
475 )
476 {
477 EFI_STATUS Status;
478 EFI_STRING_ID ProcessorManu;
479 EFI_STRING_ID ProcessorVersion;
480 EFI_STRING_ID SerialNumber;
481 EFI_STRING_ID AssetTag;
482 EFI_STRING_ID PartNumber;
483 EFI_STRING ProcessorStr;
484 EFI_STRING ProcessorManuStr;
485 EFI_STRING ProcessorVersionStr;
486 EFI_STRING SerialNumberStr;
487 EFI_STRING AssetTagStr;
488 EFI_STRING PartNumberStr;
489 CHAR8 *OptionalStrStart;
490 CHAR8 *StrStart;
491 UINTN ProcessorStrLen;
492 UINTN ProcessorManuStrLen;
493 UINTN ProcessorVersionStrLen;
494 UINTN SerialNumberStrLen;
495 UINTN AssetTagStrLen;
496 UINTN PartNumberStrLen;
497 UINTN TotalSize;
498 UINTN StringBufferSize;
499
500 Status = EFI_SUCCESS;
501
502 ProcessorManuStr = NULL;
503 ProcessorVersionStr = NULL;
504 SerialNumberStr = NULL;
505 AssetTagStr = NULL;
506 PartNumberStr = NULL;
507
508 ProcessorManu = STRING_TOKEN (STR_PROCESSOR_MANUFACTURE);
509 ProcessorVersion = STRING_TOKEN (STR_PROCESSOR_VERSION);
510 SerialNumber = STRING_TOKEN (STR_PROCESSOR_SERIAL_NUMBER);
511 AssetTag = STRING_TOKEN (STR_PROCESSOR_ASSET_TAG);
512 PartNumber = STRING_TOKEN (STR_PROCESSOR_PART_NUMBER);
513
514 SET_HII_STRING_IF_PCD_NOT_EMPTY (PcdProcessorManufacturer, ProcessorManu);
515 SET_HII_STRING_IF_PCD_NOT_EMPTY (PcdProcessorVersion, ProcessorVersion);
516 SET_HII_STRING_IF_PCD_NOT_EMPTY (PcdProcessorSerialNumber, SerialNumber);
517 SET_HII_STRING_IF_PCD_NOT_EMPTY (PcdProcessorAssetTag, AssetTag);
518 SET_HII_STRING_IF_PCD_NOT_EMPTY (PcdProcessorPartNumber, PartNumber);
519
520 // Processor Designation
521 StringBufferSize = sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH;
522 ProcessorStr = AllocateZeroPool (StringBufferSize);
523 if (ProcessorStr == NULL) {
524 return EFI_OUT_OF_RESOURCES;
525 }
526
527 ProcessorStrLen = UnicodeSPrint (
528 ProcessorStr,
529 StringBufferSize,
530 L"CPU%02d",
531 ProcessorIndex + 1
532 );
533
534 // Processor Manufacture
535 ProcessorManuStr = HiiGetPackageString (&gEfiCallerIdGuid, ProcessorManu, NULL);
536 ProcessorManuStrLen = StrLen (ProcessorManuStr);
537
538 // Processor Version
539 ProcessorVersionStr = HiiGetPackageString (&gEfiCallerIdGuid, ProcessorVersion, NULL);
540 ProcessorVersionStrLen = StrLen (ProcessorVersionStr);
541
542 // Serial Number
543 SerialNumberStr = HiiGetPackageString (&gEfiCallerIdGuid, SerialNumber, NULL);
544 SerialNumberStrLen = StrLen (SerialNumberStr);
545
546 // Asset Tag
547 AssetTagStr = HiiGetPackageString (&gEfiCallerIdGuid, AssetTag, NULL);
548 AssetTagStrLen = StrLen (AssetTagStr);
549
550 // Part Number
551 PartNumberStr = HiiGetPackageString (&gEfiCallerIdGuid, PartNumber, NULL);
552 PartNumberStrLen = StrLen (PartNumberStr);
553
554 TotalSize = sizeof (SMBIOS_TABLE_TYPE4) +
555 ProcessorStrLen + 1 +
556 ProcessorManuStrLen + 1 +
557 ProcessorVersionStrLen + 1 +
558 SerialNumberStrLen + 1 +
559 AssetTagStrLen + 1 +
560 PartNumberStrLen + 1 + 1;
561
562 *Type4Record = AllocateZeroPool (TotalSize);
563 if (*Type4Record == NULL) {
564 Status = EFI_OUT_OF_RESOURCES;
565 goto Exit;
566 }
567
568 CopyMem (*Type4Record, &mSmbiosProcessorTableTemplate, sizeof (SMBIOS_TABLE_TYPE4));
569
570 OptionalStrStart = (CHAR8 *)(*Type4Record + 1);
571 UnicodeStrToAsciiStrS (
572 ProcessorStr,
573 OptionalStrStart,
574 ProcessorStrLen + 1
575 );
576
577 StrStart = OptionalStrStart + ProcessorStrLen + 1;
578 UnicodeStrToAsciiStrS (
579 ProcessorManuStr,
580 StrStart,
581 ProcessorManuStrLen + 1
582 );
583
584 StrStart += ProcessorManuStrLen + 1;
585 UnicodeStrToAsciiStrS (
586 ProcessorVersionStr,
587 StrStart,
588 ProcessorVersionStrLen + 1
589 );
590
591 StrStart += ProcessorVersionStrLen + 1;
592 UnicodeStrToAsciiStrS (
593 SerialNumberStr,
594 StrStart,
595 SerialNumberStrLen + 1
596 );
597
598 StrStart += SerialNumberStrLen + 1;
599 UnicodeStrToAsciiStrS (
600 AssetTagStr,
601 StrStart,
602 AssetTagStrLen + 1
603 );
604
605 StrStart += AssetTagStrLen + 1;
606 UnicodeStrToAsciiStrS (
607 PartNumberStr,
608 StrStart,
609 PartNumberStrLen + 1
610 );
611
612 Exit:
613 FreePool (ProcessorStr);
614 FreePool (ProcessorManuStr);
615 FreePool (ProcessorVersionStr);
616 FreePool (SerialNumberStr);
617 FreePool (AssetTagStr);
618 FreePool (PartNumberStr);
619
620 return Status;
621 }
622
623 /**
624 Add Type 4 SMBIOS Record for Processor Information.
625
626 @param[in] ProcessorIndex Processor index of specified processor.
627
628 **/
629 EFI_STATUS
630 AddSmbiosProcessorTypeTable (
631 IN UINTN ProcessorIndex
632 )
633 {
634 EFI_STATUS Status;
635 SMBIOS_TABLE_TYPE4 *Type4Record;
636 EFI_SMBIOS_HANDLE SmbiosHandle;
637 EFI_SMBIOS_HANDLE L1CacheHandle;
638 EFI_SMBIOS_HANDLE L2CacheHandle;
639 EFI_SMBIOS_HANDLE L3CacheHandle;
640 UINT8 *LegacyVoltage;
641 PROCESSOR_STATUS_DATA ProcessorStatus;
642 UINT64 *ProcessorId;
643 PROCESSOR_CHARACTERISTIC_FLAGS ProcessorCharacteristics;
644 OEM_MISC_PROCESSOR_DATA MiscProcessorData;
645 BOOLEAN ProcessorPopulated;
646
647 Type4Record = NULL;
648
649 MiscProcessorData.Voltage = 0;
650 MiscProcessorData.CurrentSpeed = 0;
651 MiscProcessorData.CoreCount = 0;
652 MiscProcessorData.CoresEnabled = 0;
653 MiscProcessorData.ThreadCount = 0;
654 MiscProcessorData.MaxSpeed = 0;
655 L1CacheHandle = 0xFFFF;
656 L2CacheHandle = 0xFFFF;
657 L3CacheHandle = 0xFFFF;
658
659 ProcessorPopulated = OemIsProcessorPresent (ProcessorIndex);
660
661 Status = AllocateType4AndSetProcessorInformationStrings (
662 &Type4Record,
663 ProcessorIndex,
664 ProcessorPopulated
665 );
666 if (EFI_ERROR (Status)) {
667 return Status;
668 }
669
670 OemGetProcessorInformation (
671 ProcessorIndex,
672 &ProcessorStatus,
673 (PROCESSOR_CHARACTERISTIC_FLAGS *)
674 &Type4Record->ProcessorCharacteristics,
675 &MiscProcessorData
676 );
677
678 if (ProcessorPopulated) {
679 AddSmbiosCacheTypeTable (
680 ProcessorIndex,
681 &L1CacheHandle,
682 &L2CacheHandle,
683 &L3CacheHandle
684 );
685 }
686
687 LegacyVoltage = (UINT8 *)&Type4Record->Voltage;
688
689 *LegacyVoltage = MiscProcessorData.Voltage;
690 Type4Record->CurrentSpeed = MiscProcessorData.CurrentSpeed;
691 Type4Record->MaxSpeed = MiscProcessorData.MaxSpeed;
692 Type4Record->Status = ProcessorStatus.Data;
693 Type4Record->L1CacheHandle = L1CacheHandle;
694 Type4Record->L2CacheHandle = L2CacheHandle;
695 Type4Record->L3CacheHandle = L3CacheHandle;
696 Type4Record->CoreCount = MiscProcessorData.CoreCount;
697 Type4Record->CoreCount2 = MiscProcessorData.CoreCount;
698 Type4Record->EnabledCoreCount = MiscProcessorData.CoresEnabled;
699 Type4Record->EnabledCoreCount2 = MiscProcessorData.CoresEnabled;
700 Type4Record->ThreadCount = MiscProcessorData.ThreadCount;
701 Type4Record->ThreadCount2 = MiscProcessorData.ThreadCount;
702
703 Type4Record->CurrentSpeed = GetCpuFrequency (ProcessorIndex);
704 Type4Record->ExternalClock =
705 (UINT16)(SmbiosGetExternalClockFrequency () / 1000 / 1000);
706
707 ProcessorId = (UINT64 *)&Type4Record->ProcessorId;
708 *ProcessorId = SmbiosGetProcessorId ();
709
710 ProcessorCharacteristics = SmbiosGetProcessorCharacteristics ();
711 Type4Record->ProcessorCharacteristics |= *((UINT64 *)&ProcessorCharacteristics);
712
713 Type4Record->ProcessorFamily = SmbiosGetProcessorFamily ();
714 Type4Record->ProcessorFamily2 = SmbiosGetProcessorFamily2 ();
715
716 SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
717 Status = mSmbios->Add (
718 mSmbios,
719 NULL,
720 &SmbiosHandle,
721 (EFI_SMBIOS_TABLE_HEADER *)Type4Record
722 );
723
724 if (EFI_ERROR (Status)) {
725 DEBUG ((
726 DEBUG_ERROR,
727 "[%a]:[%dL] Smbios Type04 Table Log Failed! %r \n",
728 __FUNCTION__,
729 DEBUG_LINE_NUMBER,
730 Status
731 ));
732 }
733
734 FreePool (Type4Record);
735
736 return Status;
737 }
738
739 /**
740 Standard EFI driver point.
741
742 @param ImageHandle Handle for the image of this driver
743 @param SystemTable Pointer to the EFI System Table
744
745 @retval EFI_SUCCESS The data was successfully stored.
746
747 **/
748 EFI_STATUS
749 EFIAPI
750 ProcessorSubClassEntryPoint (
751 IN EFI_HANDLE ImageHandle,
752 IN EFI_SYSTEM_TABLE *SystemTable
753 )
754 {
755 EFI_STATUS Status;
756 UINT32 ProcessorIndex;
757
758 //
759 // Locate dependent protocols
760 //
761 Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **)&mSmbios);
762 if (EFI_ERROR (Status)) {
763 DEBUG ((DEBUG_ERROR, "Could not locate SMBIOS protocol. %r\n", Status));
764 return Status;
765 }
766
767 //
768 // Add our default strings to the HII database. They will be modified later.
769 //
770 mHiiHandle = HiiAddPackages (
771 &gEfiCallerIdGuid,
772 NULL,
773 ProcessorSubClassStrings,
774 NULL,
775 NULL
776 );
777 if (mHiiHandle == NULL) {
778 return EFI_OUT_OF_RESOURCES;
779 }
780
781 //
782 // Add SMBIOS tables for populated sockets.
783 //
784 for (ProcessorIndex = 0; ProcessorIndex < OemGetMaxProcessors (); ProcessorIndex++) {
785 Status = AddSmbiosProcessorTypeTable (ProcessorIndex);
786 if (EFI_ERROR (Status)) {
787 DEBUG ((DEBUG_ERROR, "Add Processor Type Table Failed! %r.\n", Status));
788 return Status;
789 }
790 }
791
792 return Status;
793 }