]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c
0b9af9bd7e1c63b0e05906f25a3eeffc92855da7
[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 (PcdProcessorAssetTag, AssetTag);
517
518 if (StrLen ((CHAR16 *)FixedPcdGetPtr (PcdProcessorSerialNumber)) > 0) {
519 HiiSetString (mHiiHandle, SerialNumber, (CHAR16 *)FixedPcdGetPtr (PcdProcessorSerialNumber), NULL);
520 } else {
521 OemUpdateSmbiosInfo (mHiiHandle, SerialNumber, ProcessorSerialNumType04);
522 }
523
524 if (StrLen ((CHAR16 *)FixedPcdGetPtr (PcdProcessorPartNumber)) > 0) {
525 HiiSetString (mHiiHandle, PartNumber, (CHAR16 *)FixedPcdGetPtr (PcdProcessorPartNumber), NULL);
526 } else {
527 OemUpdateSmbiosInfo (mHiiHandle, PartNumber, ProcessorPartNumType04);
528 }
529
530 // Processor Designation
531 StringBufferSize = sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH;
532 ProcessorStr = AllocateZeroPool (StringBufferSize);
533 if (ProcessorStr == NULL) {
534 return EFI_OUT_OF_RESOURCES;
535 }
536
537 ProcessorStrLen = UnicodeSPrint (
538 ProcessorStr,
539 StringBufferSize,
540 L"CPU%02d",
541 ProcessorIndex + 1
542 );
543
544 // Processor Manufacture
545 ProcessorManuStr = HiiGetPackageString (&gEfiCallerIdGuid, ProcessorManu, NULL);
546 ProcessorManuStrLen = StrLen (ProcessorManuStr);
547
548 // Processor Version
549 ProcessorVersionStr = HiiGetPackageString (&gEfiCallerIdGuid, ProcessorVersion, NULL);
550 ProcessorVersionStrLen = StrLen (ProcessorVersionStr);
551
552 // Serial Number
553 SerialNumberStr = HiiGetPackageString (&gEfiCallerIdGuid, SerialNumber, NULL);
554 SerialNumberStrLen = StrLen (SerialNumberStr);
555
556 // Asset Tag
557 AssetTagStr = HiiGetPackageString (&gEfiCallerIdGuid, AssetTag, NULL);
558 AssetTagStrLen = StrLen (AssetTagStr);
559
560 // Part Number
561 PartNumberStr = HiiGetPackageString (&gEfiCallerIdGuid, PartNumber, NULL);
562 PartNumberStrLen = StrLen (PartNumberStr);
563
564 TotalSize = sizeof (SMBIOS_TABLE_TYPE4) +
565 ProcessorStrLen + 1 +
566 ProcessorManuStrLen + 1 +
567 ProcessorVersionStrLen + 1 +
568 SerialNumberStrLen + 1 +
569 AssetTagStrLen + 1 +
570 PartNumberStrLen + 1 + 1;
571
572 *Type4Record = AllocateZeroPool (TotalSize);
573 if (*Type4Record == NULL) {
574 Status = EFI_OUT_OF_RESOURCES;
575 goto Exit;
576 }
577
578 CopyMem (*Type4Record, &mSmbiosProcessorTableTemplate, sizeof (SMBIOS_TABLE_TYPE4));
579
580 OptionalStrStart = (CHAR8 *)(*Type4Record + 1);
581 UnicodeStrToAsciiStrS (
582 ProcessorStr,
583 OptionalStrStart,
584 ProcessorStrLen + 1
585 );
586
587 StrStart = OptionalStrStart + ProcessorStrLen + 1;
588 UnicodeStrToAsciiStrS (
589 ProcessorManuStr,
590 StrStart,
591 ProcessorManuStrLen + 1
592 );
593
594 StrStart += ProcessorManuStrLen + 1;
595 UnicodeStrToAsciiStrS (
596 ProcessorVersionStr,
597 StrStart,
598 ProcessorVersionStrLen + 1
599 );
600
601 StrStart += ProcessorVersionStrLen + 1;
602 UnicodeStrToAsciiStrS (
603 SerialNumberStr,
604 StrStart,
605 SerialNumberStrLen + 1
606 );
607
608 StrStart += SerialNumberStrLen + 1;
609 UnicodeStrToAsciiStrS (
610 AssetTagStr,
611 StrStart,
612 AssetTagStrLen + 1
613 );
614
615 StrStart += AssetTagStrLen + 1;
616 UnicodeStrToAsciiStrS (
617 PartNumberStr,
618 StrStart,
619 PartNumberStrLen + 1
620 );
621
622 Exit:
623 FreePool (ProcessorStr);
624 FreePool (ProcessorManuStr);
625 FreePool (ProcessorVersionStr);
626 FreePool (SerialNumberStr);
627 FreePool (AssetTagStr);
628 FreePool (PartNumberStr);
629
630 return Status;
631 }
632
633 /**
634 Add Type 4 SMBIOS Record for Processor Information.
635
636 @param[in] ProcessorIndex Processor index of specified processor.
637
638 **/
639 EFI_STATUS
640 AddSmbiosProcessorTypeTable (
641 IN UINTN ProcessorIndex
642 )
643 {
644 EFI_STATUS Status;
645 SMBIOS_TABLE_TYPE4 *Type4Record;
646 EFI_SMBIOS_HANDLE SmbiosHandle;
647 EFI_SMBIOS_HANDLE L1CacheHandle;
648 EFI_SMBIOS_HANDLE L2CacheHandle;
649 EFI_SMBIOS_HANDLE L3CacheHandle;
650 UINT8 *LegacyVoltage;
651 PROCESSOR_STATUS_DATA ProcessorStatus;
652 UINT64 *ProcessorId;
653 PROCESSOR_CHARACTERISTIC_FLAGS ProcessorCharacteristics;
654 OEM_MISC_PROCESSOR_DATA MiscProcessorData;
655 BOOLEAN ProcessorPopulated;
656
657 Type4Record = NULL;
658
659 MiscProcessorData.Voltage = 0;
660 MiscProcessorData.CurrentSpeed = 0;
661 MiscProcessorData.CoreCount = 0;
662 MiscProcessorData.CoresEnabled = 0;
663 MiscProcessorData.ThreadCount = 0;
664 MiscProcessorData.MaxSpeed = 0;
665 L1CacheHandle = 0xFFFF;
666 L2CacheHandle = 0xFFFF;
667 L3CacheHandle = 0xFFFF;
668
669 ProcessorPopulated = OemIsProcessorPresent (ProcessorIndex);
670
671 Status = AllocateType4AndSetProcessorInformationStrings (
672 &Type4Record,
673 ProcessorIndex,
674 ProcessorPopulated
675 );
676 if (EFI_ERROR (Status)) {
677 return Status;
678 }
679
680 OemGetProcessorInformation (
681 ProcessorIndex,
682 &ProcessorStatus,
683 (PROCESSOR_CHARACTERISTIC_FLAGS *)
684 &Type4Record->ProcessorCharacteristics,
685 &MiscProcessorData
686 );
687
688 if (ProcessorPopulated) {
689 AddSmbiosCacheTypeTable (
690 ProcessorIndex,
691 &L1CacheHandle,
692 &L2CacheHandle,
693 &L3CacheHandle
694 );
695 }
696
697 LegacyVoltage = (UINT8 *)&Type4Record->Voltage;
698
699 *LegacyVoltage = MiscProcessorData.Voltage;
700 Type4Record->CurrentSpeed = MiscProcessorData.CurrentSpeed;
701 Type4Record->MaxSpeed = MiscProcessorData.MaxSpeed;
702 Type4Record->Status = ProcessorStatus.Data;
703 Type4Record->L1CacheHandle = L1CacheHandle;
704 Type4Record->L2CacheHandle = L2CacheHandle;
705 Type4Record->L3CacheHandle = L3CacheHandle;
706 Type4Record->CoreCount = MiscProcessorData.CoreCount;
707 Type4Record->CoreCount2 = MiscProcessorData.CoreCount;
708 Type4Record->EnabledCoreCount = MiscProcessorData.CoresEnabled;
709 Type4Record->EnabledCoreCount2 = MiscProcessorData.CoresEnabled;
710 Type4Record->ThreadCount = MiscProcessorData.ThreadCount;
711 Type4Record->ThreadCount2 = MiscProcessorData.ThreadCount;
712
713 Type4Record->CurrentSpeed = GetCpuFrequency (ProcessorIndex);
714 Type4Record->ExternalClock =
715 (UINT16)(SmbiosGetExternalClockFrequency () / 1000 / 1000);
716
717 ProcessorId = (UINT64 *)&Type4Record->ProcessorId;
718 *ProcessorId = SmbiosGetProcessorId ();
719
720 ProcessorCharacteristics = SmbiosGetProcessorCharacteristics ();
721 Type4Record->ProcessorCharacteristics |= *((UINT64 *)&ProcessorCharacteristics);
722
723 Type4Record->ProcessorFamily = SmbiosGetProcessorFamily ();
724 Type4Record->ProcessorFamily2 = SmbiosGetProcessorFamily2 ();
725
726 SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
727 Status = mSmbios->Add (
728 mSmbios,
729 NULL,
730 &SmbiosHandle,
731 (EFI_SMBIOS_TABLE_HEADER *)Type4Record
732 );
733
734 if (EFI_ERROR (Status)) {
735 DEBUG ((
736 DEBUG_ERROR,
737 "[%a]:[%dL] Smbios Type04 Table Log Failed! %r \n",
738 __FUNCTION__,
739 DEBUG_LINE_NUMBER,
740 Status
741 ));
742 }
743
744 FreePool (Type4Record);
745
746 return Status;
747 }
748
749 /**
750 Standard EFI driver point.
751
752 @param ImageHandle Handle for the image of this driver
753 @param SystemTable Pointer to the EFI System Table
754
755 @retval EFI_SUCCESS The data was successfully stored.
756
757 **/
758 EFI_STATUS
759 EFIAPI
760 ProcessorSubClassEntryPoint (
761 IN EFI_HANDLE ImageHandle,
762 IN EFI_SYSTEM_TABLE *SystemTable
763 )
764 {
765 EFI_STATUS Status;
766 UINT32 ProcessorIndex;
767
768 //
769 // Locate dependent protocols
770 //
771 Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **)&mSmbios);
772 if (EFI_ERROR (Status)) {
773 DEBUG ((DEBUG_ERROR, "Could not locate SMBIOS protocol. %r\n", Status));
774 return Status;
775 }
776
777 //
778 // Add our default strings to the HII database. They will be modified later.
779 //
780 mHiiHandle = HiiAddPackages (
781 &gEfiCallerIdGuid,
782 NULL,
783 ProcessorSubClassStrings,
784 NULL,
785 NULL
786 );
787 if (mHiiHandle == NULL) {
788 return EFI_OUT_OF_RESOURCES;
789 }
790
791 //
792 // Add SMBIOS tables for populated sockets.
793 //
794 for (ProcessorIndex = 0; ProcessorIndex < OemGetMaxProcessors (); ProcessorIndex++) {
795 Status = AddSmbiosProcessorTypeTable (ProcessorIndex);
796 if (EFI_ERROR (Status)) {
797 DEBUG ((DEBUG_ERROR, "Add Processor Type Table Failed! %r.\n", Status));
798 return Status;
799 }
800 }
801
802 return Status;
803 }