]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c
ArmPkg: Reproduce builds across source format changes
[mirror_edk2.git] / ArmPkg / Universal / Smbios / ProcessorSubClassDxe / ProcessorSubClass.c
CommitLineData
2ba6ecef
RC
1/** @file\r
2 ProcessorSubClass.c\r
3\r
4 Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>\r
5 Copyright (c) 2015, Hisilicon Limited. All rights reserved.\r
6 Copyright (c) 2015, Linaro Limited. All rights reserved.\r
7 SPDX-License-Identifier: BSD-2-Clause-Patent\r
8\r
9**/\r
10\r
11#include <Uefi.h>\r
12#include <Protocol/Smbios.h>\r
a63914d3 13#include <IndustryStandard/ArmCache.h>\r
2ba6ecef
RC
14#include <IndustryStandard/ArmStdSmc.h>\r
15#include <IndustryStandard/SmBios.h>\r
16#include <Library/ArmLib.h>\r
17#include <Library/ArmSmcLib.h>\r
2ba6ecef
RC
18#include <Library/BaseLib.h>\r
19#include <Library/BaseMemoryLib.h>\r
20#include <Library/DebugLib.h>\r
21#include <Library/HiiLib.h>\r
22#include <Library/IoLib.h>\r
23#include <Library/MemoryAllocationLib.h>\r
24#include <Library/OemMiscLib.h>\r
25#include <Library/PcdLib.h>\r
26#include <Library/PrintLib.h>\r
27#include <Library/UefiBootServicesTableLib.h>\r
28#include <Library/UefiLib.h>\r
29\r
30#include "SmbiosProcessor.h"\r
31\r
32extern UINT8 ProcessorSubClassStrings[];\r
33\r
34#define CACHE_SOCKETED_SHIFT 3\r
35#define CACHE_LOCATION_SHIFT 5\r
36#define CACHE_ENABLED_SHIFT 7\r
37#define CACHE_OPERATION_MODE_SHIFT 8\r
38\r
39typedef enum {\r
40 CacheModeWriteThrough = 0, ///< Cache is write-through\r
41 CacheModeWriteBack, ///< Cache is write-back\r
42 CacheModeVariesWithAddress, ///< Cache mode varies by address\r
43 CacheModeUnknown, ///< Cache mode is unknown\r
44 CacheModeMax\r
45} CACHE_OPERATION_MODE;\r
46\r
47typedef enum {\r
48 CacheLocationInternal = 0, ///< Cache is internal to the processor\r
49 CacheLocationExternal, ///< Cache is external to the processor\r
50 CacheLocationReserved, ///< Reserved\r
51 CacheLocationUnknown, ///< Cache location is unknown\r
52 CacheLocationMax\r
53} CACHE_LOCATION;\r
54\r
55EFI_HII_HANDLE mHiiHandle;\r
56\r
57EFI_SMBIOS_PROTOCOL *mSmbios;\r
58\r
59SMBIOS_TABLE_TYPE4 mSmbiosProcessorTableTemplate = {\r
60 { // Hdr\r
61 EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION, // Type\r
62 sizeof (SMBIOS_TABLE_TYPE4), // Length\r
63 0 // Handle\r
64 },\r
65 1, // Socket\r
66 CentralProcessor, // ProcessorType\r
67 ProcessorFamilyIndicatorFamily2, // ProcessorFamily\r
68 2, // ProcessorManufacture\r
69 { // ProcessorId\r
70 { // Signature\r
71 0\r
72 },\r
73 { // FeatureFlags\r
74 0\r
75 }\r
76 },\r
77 3, // ProcessorVersion\r
78 { // Voltage\r
79 0\r
80 },\r
81 0, // ExternalClock\r
82 0, // MaxSpeed\r
83 0, // CurrentSpeed\r
84 0, // Status\r
85 ProcessorUpgradeUnknown, // ProcessorUpgrade\r
86 0xFFFF, // L1CacheHandle\r
87 0xFFFF, // L2CacheHandle\r
88 0xFFFF, // L3CacheHandle\r
89 4, // SerialNumber\r
90 5, // AssetTag\r
91 6, // PartNumber\r
92 0, // CoreCount\r
93 0, //EnabledCoreCount\r
94 0, // ThreadCount\r
95 0, // ProcessorCharacteristics\r
96 ProcessorFamilyARM, // ProcessorFamily2\r
97 0, // CoreCount2\r
98 0, // EnabledCoreCount2\r
99 0 // ThreadCount2\r
100};\r
101\r
102/** Sets the HII variable `StringId` is `Pcd` isn't empty.\r
103\r
104 @param Pcd The FixedAtBuild PCD that contains the string to fetch.\r
105 @param StringId The string identifier to set.\r
106**/\r
107#define SET_HII_STRING_IF_PCD_NOT_EMPTY(Pcd, StringId) \\r
108 do { \\r
109 CHAR16 *Str; \\r
110 Str = (CHAR16*)PcdGetPtr (Pcd); \\r
111 if (StrLen (Str) > 0) { \\r
112 HiiSetString (mHiiHandle, StringId, Str, NULL); \\r
113 } \\r
114 } while (0)\r
115\r
116/** Fetches the specified processor's frequency in Hz.\r
117\r
118 @param ProcessorNumber The processor number\r
119\r
120 @return The clock frequency in MHz\r
121\r
122**/\r
123UINT16\r
124GetCpuFrequency (\r
125 IN UINT8 ProcessorNumber\r
126 )\r
127{\r
128 return (UINT16)(OemGetCpuFreq (ProcessorNumber) / 1000 / 1000);\r
129}\r
130\r
131/** Gets a description of the specified cache.\r
132\r
133 @param[in] CacheLevel Zero-based cache level (e.g. L1 cache is 0).\r
134 @param[in] DataCache Cache is a data cache.\r
135 @param[in] UnifiedCache Cache is a unified cache.\r
136 @param[out] CacheSocketStr The description of the specified cache\r
137\r
138 @return The number of Unicode characters in CacheSocketStr not including the\r
139 terminating NUL.\r
140**/\r
141UINTN\r
142GetCacheSocketStr (\r
143 IN UINT8 CacheLevel,\r
144 IN BOOLEAN DataCache,\r
145 IN BOOLEAN UnifiedCache,\r
146 OUT CHAR16 *CacheSocketStr\r
147 )\r
148{\r
149 UINTN CacheSocketStrLen;\r
150\r
151 if (CacheLevel == CpuCacheL1 && !DataCache && !UnifiedCache) {\r
152 CacheSocketStrLen = UnicodeSPrint (\r
153 CacheSocketStr,\r
154 SMBIOS_STRING_MAX_LENGTH - 1,\r
155 L"L%x Instruction Cache",\r
156 CacheLevel);\r
157 } else if (CacheLevel == CpuCacheL1 && DataCache) {\r
158 CacheSocketStrLen = UnicodeSPrint (CacheSocketStr,\r
159 SMBIOS_STRING_MAX_LENGTH - 1,\r
160 L"L%x Data Cache",\r
161 CacheLevel);\r
162 } else {\r
163 CacheSocketStrLen = UnicodeSPrint (CacheSocketStr,\r
164 SMBIOS_STRING_MAX_LENGTH - 1,\r
165 L"L%x Cache",\r
166 CacheLevel);\r
167 }\r
168\r
169 return CacheSocketStrLen;\r
170}\r
171\r
172/** Fills in the Type 7 record with the cache architecture information\r
173 read from the CPU registers.\r
174\r
175 @param[in] CacheLevel Cache level (e.g. L1, L2).\r
176 @param[in] DataCache Cache is a data cache.\r
177 @param[in] UnifiedCache Cache is a unified cache.\r
178 @param[out] Type7Record The Type 7 record to fill in.\r
179\r
180**/\r
181VOID\r
182ConfigureCacheArchitectureInformation (\r
183 IN UINT8 CacheLevel,\r
184 IN BOOLEAN DataCache,\r
185 IN BOOLEAN UnifiedCache,\r
186 OUT SMBIOS_TABLE_TYPE7 *Type7Record\r
187 )\r
188{\r
189 UINT8 Associativity;\r
190 UINT32 CacheSize32;\r
191 UINT16 CacheSize16;\r
192 UINT64 CacheSize64;\r
193\r
194 if (!DataCache && !UnifiedCache) {\r
195 Type7Record->SystemCacheType = CacheTypeInstruction;\r
196 } else if (DataCache) {\r
197 Type7Record->SystemCacheType = CacheTypeData;\r
198 } else if (UnifiedCache) {\r
199 Type7Record->SystemCacheType = CacheTypeUnified;\r
200 } else {\r
201 ASSERT(FALSE);\r
202 }\r
203\r
204 CacheSize64 = SmbiosProcessorGetCacheSize (CacheLevel,\r
205 DataCache,\r
206 UnifiedCache\r
207 );\r
208\r
209 Associativity = SmbiosProcessorGetCacheAssociativity (CacheLevel,\r
210 DataCache,\r
211 UnifiedCache\r
212 );\r
213\r
214 CacheSize64 /= 1024; // Minimum granularity is 1K\r
215\r
216 // Encode the cache size into the format SMBIOS wants\r
217 if (CacheSize64 < MAX_INT16) {\r
218 CacheSize16 = CacheSize64;\r
219 CacheSize32 = CacheSize16;\r
220 } else if ((CacheSize64 / 64) < MAX_INT16) {\r
221 CacheSize16 = (1 << 15) | (CacheSize64 / 64);\r
7e43d3e0 222 CacheSize32 = (1 << 31) | (CacheSize64 / 64);\r
2ba6ecef
RC
223 } else {\r
224 if ((CacheSize64 / 1024) <= 2047) {\r
225 CacheSize32 = CacheSize64;\r
226 } else {\r
227 CacheSize32 = (1 << 31) | (CacheSize64 / 64);\r
228 }\r
229\r
230 CacheSize16 = -1;\r
231 }\r
232\r
233 Type7Record->MaximumCacheSize = CacheSize16;\r
234 Type7Record->InstalledSize = CacheSize16;\r
235 Type7Record->MaximumCacheSize2 = CacheSize32;\r
236 Type7Record->InstalledSize2 = CacheSize32;\r
237\r
238 switch (Associativity) {\r
239 case 2:\r
240 Type7Record->Associativity = CacheAssociativity2Way;\r
241 break;\r
242 case 4:\r
243 Type7Record->Associativity = CacheAssociativity4Way;\r
244 break;\r
245 case 8:\r
246 Type7Record->Associativity = CacheAssociativity8Way;\r
247 break;\r
248 case 12:\r
249 Type7Record->Associativity = CacheAssociativity12Way;\r
250 break;\r
251 case 16:\r
252 Type7Record->Associativity = CacheAssociativity16Way;\r
253 break;\r
254 case 20:\r
255 Type7Record->Associativity = CacheAssociativity20Way;\r
256 break;\r
257 case 24:\r
258 Type7Record->Associativity = CacheAssociativity24Way;\r
259 break;\r
260 case 32:\r
261 Type7Record->Associativity = CacheAssociativity32Way;\r
262 break;\r
263 case 48:\r
264 Type7Record->Associativity = CacheAssociativity48Way;\r
265 break;\r
266 case 64:\r
267 Type7Record->Associativity = CacheAssociativity64Way;\r
268 break;\r
269 default:\r
270 Type7Record->Associativity = CacheAssociativityOther;\r
271 break;\r
272 }\r
273\r
274 Type7Record->CacheConfiguration = (CacheModeUnknown << CACHE_OPERATION_MODE_SHIFT) |\r
275 (1 << CACHE_ENABLED_SHIFT) |\r
276 (CacheLocationUnknown << CACHE_LOCATION_SHIFT) |\r
277 (0 << CACHE_SOCKETED_SHIFT) |\r
278 (CacheLevel - 1);\r
279}\r
280\r
281\r
282/** Allocates and initializes an SMBIOS_TABLE_TYPE7 structure.\r
283\r
284 @param[in] CacheLevel The cache level (L1-L7).\r
285 @param[in] DataCache Cache is a data cache.\r
286 @param[in] UnifiedCache Cache is a unified cache.\r
287\r
288 @return A pointer to the Type 7 structure. Returns NULL on failure.\r
289**/\r
290SMBIOS_TABLE_TYPE7 *\r
291AllocateAndInitCacheInformation (\r
292 IN UINT8 CacheLevel,\r
293 IN BOOLEAN DataCache,\r
294 IN BOOLEAN UnifiedCache\r
295 )\r
296{\r
297 SMBIOS_TABLE_TYPE7 *Type7Record;\r
298 EFI_STRING CacheSocketStr;\r
299 UINTN CacheSocketStrLen;\r
300 UINTN StringBufferSize;\r
301 CHAR8 *OptionalStrStart;\r
302 UINTN TableSize;\r
303\r
304 // Allocate and fetch the cache description\r
305 StringBufferSize = sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH;\r
306 CacheSocketStr = AllocateZeroPool (StringBufferSize);\r
307 if (CacheSocketStr == NULL) {\r
308 return NULL;\r
309 }\r
310\r
311 CacheSocketStrLen = GetCacheSocketStr (CacheLevel,\r
312 DataCache,\r
313 UnifiedCache,\r
314 CacheSocketStr);\r
315\r
316 TableSize = sizeof (SMBIOS_TABLE_TYPE7) + CacheSocketStrLen + 1 + 1;\r
317 Type7Record = AllocateZeroPool (TableSize);\r
318 if (Type7Record == NULL) {\r
319 FreePool(CacheSocketStr);\r
320 return NULL;\r
321 }\r
322\r
323 Type7Record->Hdr.Type = EFI_SMBIOS_TYPE_CACHE_INFORMATION;\r
324 Type7Record->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE7);\r
325 Type7Record->Hdr.Handle = SMBIOS_HANDLE_PI_RESERVED;\r
326\r
327 Type7Record->SocketDesignation = 1;\r
328\r
329 Type7Record->SupportedSRAMType.Unknown = 1;\r
330 Type7Record->CurrentSRAMType.Unknown = 1;\r
331 Type7Record->CacheSpeed = 0;\r
332 Type7Record->ErrorCorrectionType = CacheErrorUnknown;\r
333\r
334 OptionalStrStart = (CHAR8 *)(Type7Record + 1);\r
335 UnicodeStrToAsciiStrS (CacheSocketStr, OptionalStrStart, CacheSocketStrLen + 1);\r
336 FreePool (CacheSocketStr);\r
337\r
338 return Type7Record;\r
339}\r
340\r
341/**\r
342 Add Type 7 SMBIOS Record for Cache Information.\r
343\r
344 @param[in] ProcessorIndex Processor number of specified processor.\r
345 @param[out] L1CacheHandle Pointer to the handle of the L1 Cache SMBIOS record.\r
346 @param[out] L2CacheHandle Pointer to the handle of the L2 Cache SMBIOS record.\r
347 @param[out] L3CacheHandle Pointer to the handle of the L3 Cache SMBIOS record.\r
348\r
349**/\r
350VOID\r
351AddSmbiosCacheTypeTable (\r
352 IN UINTN ProcessorIndex,\r
353 OUT EFI_SMBIOS_HANDLE *L1CacheHandle,\r
354 OUT EFI_SMBIOS_HANDLE *L2CacheHandle,\r
355 OUT EFI_SMBIOS_HANDLE *L3CacheHandle\r
356 )\r
357{\r
358 EFI_STATUS Status;\r
359 SMBIOS_TABLE_TYPE7 *Type7Record;\r
360 EFI_SMBIOS_HANDLE SmbiosHandle;\r
361 UINT8 CacheLevel;\r
362 UINT8 MaxCacheLevel;\r
363 BOOLEAN DataCacheType;\r
364 BOOLEAN SeparateCaches;\r
365\r
366 Status = EFI_SUCCESS;\r
367\r
368 MaxCacheLevel = 0;\r
369\r
370 // See if there's an L1 cache present.\r
371 MaxCacheLevel = SmbiosProcessorGetMaxCacheLevel ();\r
372\r
373 if (MaxCacheLevel < 1) {\r
374 return;\r
375 }\r
376\r
377 for (CacheLevel = 1; CacheLevel <= MaxCacheLevel; CacheLevel++) {\r
378 Type7Record = NULL;\r
379\r
380 SeparateCaches = SmbiosProcessorHasSeparateCaches (CacheLevel);\r
381\r
382 // At each level of cache, we can have a single type (unified, instruction or data),\r
383 // or two types - separate data and instruction caches. If we have separate\r
384 // instruction and data caches, then on the first iteration (CacheSubLevel = 0)\r
385 // process the instruction cache.\r
386 for (DataCacheType = 0; DataCacheType <= 1; DataCacheType++) {\r
387 // If there's no separate data/instruction cache, skip the second iteration\r
388 if (DataCacheType == 1 && !SeparateCaches) {\r
389 continue;\r
390 }\r
391\r
392 Type7Record = AllocateAndInitCacheInformation (CacheLevel,\r
393 DataCacheType,\r
394 !SeparateCaches\r
395 );\r
396 if (Type7Record == NULL) {\r
397 continue;\r
398 }\r
399\r
400 ConfigureCacheArchitectureInformation(CacheLevel,\r
401 DataCacheType,\r
402 !SeparateCaches,\r
403 Type7Record\r
404 );\r
405\r
406 // Allow the platform to fill in other information such as speed, SRAM type etc.\r
407 if (!OemGetCacheInformation (ProcessorIndex, CacheLevel,\r
408 DataCacheType, !SeparateCaches, Type7Record)) {\r
409 continue;\r
410 }\r
411\r
412 SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;\r
413 // Finally, install the table\r
414 Status = mSmbios->Add (mSmbios, NULL, &SmbiosHandle,\r
415 (EFI_SMBIOS_TABLE_HEADER *)Type7Record);\r
416 if (EFI_ERROR (Status)) {\r
417 continue;\r
418 }\r
419\r
420 // Config L1/L2/L3 Cache Handle\r
421 switch (CacheLevel) {\r
422 case CpuCacheL1:\r
423 *L1CacheHandle = SmbiosHandle;\r
424 break;\r
425 case CpuCacheL2:\r
426 *L2CacheHandle = SmbiosHandle;\r
427 break;\r
428 case CpuCacheL3:\r
429 *L3CacheHandle = SmbiosHandle;\r
430 break;\r
431 default:\r
432 break;\r
433 }\r
434 }\r
435 }\r
436}\r
437\r
438/** Allocates a Type 4 Processor Information structure and sets the\r
439 strings following the data fields.\r
440\r
441 @param[out] Type4Record The Type 4 structure to allocate and initialize\r
869ccd4a
RC
442 @param[in] ProcessorIndex The index of the processor\r
443 @param[in] Populated Whether the specified processor is\r
2ba6ecef
RC
444 populated.\r
445\r
446 @retval EFI_SUCCESS The Type 4 structure was successfully\r
447 allocated and the strings initialized.\r
448 @retval EFI_OUT_OF_RESOURCES Could not allocate memory needed.\r
449**/\r
450EFI_STATUS\r
451AllocateType4AndSetProcessorInformationStrings (\r
452 SMBIOS_TABLE_TYPE4 **Type4Record,\r
453 UINT8 ProcessorIndex,\r
454 BOOLEAN Populated\r
455 )\r
456{\r
457 EFI_STATUS Status;\r
458 EFI_STRING_ID ProcessorManu;\r
459 EFI_STRING_ID ProcessorVersion;\r
460 EFI_STRING_ID SerialNumber;\r
461 EFI_STRING_ID AssetTag;\r
462 EFI_STRING_ID PartNumber;\r
869ccd4a 463 EFI_STRING ProcessorStr;\r
2ba6ecef
RC
464 EFI_STRING ProcessorManuStr;\r
465 EFI_STRING ProcessorVersionStr;\r
466 EFI_STRING SerialNumberStr;\r
467 EFI_STRING AssetTagStr;\r
468 EFI_STRING PartNumberStr;\r
469 CHAR8 *OptionalStrStart;\r
470 CHAR8 *StrStart;\r
869ccd4a 471 UINTN ProcessorStrLen;\r
2ba6ecef
RC
472 UINTN ProcessorManuStrLen;\r
473 UINTN ProcessorVersionStrLen;\r
474 UINTN SerialNumberStrLen;\r
475 UINTN AssetTagStrLen;\r
476 UINTN PartNumberStrLen;\r
477 UINTN TotalSize;\r
478 UINTN StringBufferSize;\r
479\r
480 Status = EFI_SUCCESS;\r
481\r
482 ProcessorManuStr = NULL;\r
483 ProcessorVersionStr = NULL;\r
484 SerialNumberStr = NULL;\r
485 AssetTagStr = NULL;\r
486 PartNumberStr = NULL;\r
487\r
488 ProcessorManu = STRING_TOKEN (STR_PROCESSOR_MANUFACTURE);\r
489 ProcessorVersion = STRING_TOKEN (STR_PROCESSOR_VERSION);\r
490 SerialNumber = STRING_TOKEN (STR_PROCESSOR_SERIAL_NUMBER);\r
491 AssetTag = STRING_TOKEN (STR_PROCESSOR_ASSET_TAG);\r
492 PartNumber = STRING_TOKEN (STR_PROCESSOR_PART_NUMBER);\r
493\r
494 SET_HII_STRING_IF_PCD_NOT_EMPTY (PcdProcessorManufacturer, ProcessorManu);\r
495 SET_HII_STRING_IF_PCD_NOT_EMPTY (PcdProcessorVersion, ProcessorVersion);\r
496 SET_HII_STRING_IF_PCD_NOT_EMPTY (PcdProcessorSerialNumber, SerialNumber);\r
497 SET_HII_STRING_IF_PCD_NOT_EMPTY (PcdProcessorAssetTag, AssetTag);\r
498 SET_HII_STRING_IF_PCD_NOT_EMPTY (PcdProcessorPartNumber, PartNumber);\r
499\r
869ccd4a 500 // Processor Designation\r
2ba6ecef 501 StringBufferSize = sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH;\r
869ccd4a
RC
502 ProcessorStr = AllocateZeroPool (StringBufferSize);\r
503 if (ProcessorStr == NULL) {\r
2ba6ecef
RC
504 return EFI_OUT_OF_RESOURCES;\r
505 }\r
506\r
869ccd4a 507 ProcessorStrLen = UnicodeSPrint (ProcessorStr, StringBufferSize,\r
2ba6ecef
RC
508 L"CPU%02d", ProcessorIndex + 1);\r
509\r
510 // Processor Manufacture\r
511 ProcessorManuStr = HiiGetPackageString (&gEfiCallerIdGuid, ProcessorManu, NULL);\r
512 ProcessorManuStrLen = StrLen (ProcessorManuStr);\r
513\r
514 // Processor Version\r
515 ProcessorVersionStr = HiiGetPackageString (&gEfiCallerIdGuid, ProcessorVersion, NULL);\r
516 ProcessorVersionStrLen = StrLen (ProcessorVersionStr);\r
517\r
518 // Serial Number\r
519 SerialNumberStr = HiiGetPackageString (&gEfiCallerIdGuid, SerialNumber, NULL);\r
520 SerialNumberStrLen = StrLen (SerialNumberStr);\r
521\r
522 // Asset Tag\r
523 AssetTagStr = HiiGetPackageString (&gEfiCallerIdGuid, AssetTag, NULL);\r
524 AssetTagStrLen = StrLen (AssetTagStr);\r
525\r
526 // Part Number\r
527 PartNumberStr = HiiGetPackageString (&gEfiCallerIdGuid, PartNumber, NULL);\r
528 PartNumberStrLen = StrLen (PartNumberStr);\r
529\r
530 TotalSize = sizeof (SMBIOS_TABLE_TYPE4) +\r
869ccd4a 531 ProcessorStrLen + 1 +\r
2ba6ecef
RC
532 ProcessorManuStrLen + 1 +\r
533 ProcessorVersionStrLen + 1 +\r
534 SerialNumberStrLen + 1 +\r
535 AssetTagStrLen + 1 +\r
536 PartNumberStrLen + 1 + 1;\r
537\r
538 *Type4Record = AllocateZeroPool (TotalSize);\r
539 if (*Type4Record == NULL) {\r
540 Status = EFI_OUT_OF_RESOURCES;\r
541 goto Exit;\r
542 }\r
543\r
544 CopyMem (*Type4Record, &mSmbiosProcessorTableTemplate, sizeof (SMBIOS_TABLE_TYPE4));\r
545\r
546 OptionalStrStart = (CHAR8 *)(*Type4Record + 1);\r
547 UnicodeStrToAsciiStrS (\r
869ccd4a 548 ProcessorStr,\r
2ba6ecef 549 OptionalStrStart,\r
869ccd4a 550 ProcessorStrLen + 1\r
2ba6ecef
RC
551 );\r
552\r
869ccd4a 553 StrStart = OptionalStrStart + ProcessorStrLen + 1;\r
2ba6ecef
RC
554 UnicodeStrToAsciiStrS (\r
555 ProcessorManuStr,\r
556 StrStart,\r
557 ProcessorManuStrLen + 1\r
558 );\r
559\r
560 StrStart += ProcessorManuStrLen + 1;\r
561 UnicodeStrToAsciiStrS (\r
562 ProcessorVersionStr,\r
563 StrStart,\r
564 ProcessorVersionStrLen + 1\r
565 );\r
566\r
567 StrStart += ProcessorVersionStrLen + 1;\r
568 UnicodeStrToAsciiStrS (\r
569 SerialNumberStr,\r
570 StrStart,\r
571 SerialNumberStrLen + 1\r
572 );\r
573\r
574 StrStart += SerialNumberStrLen + 1;\r
575 UnicodeStrToAsciiStrS (\r
576 AssetTagStr,\r
577 StrStart,\r
578 AssetTagStrLen + 1\r
579 );\r
580\r
581 StrStart += AssetTagStrLen + 1;\r
582 UnicodeStrToAsciiStrS (\r
583 PartNumberStr,\r
584 StrStart,\r
585 PartNumberStrLen + 1\r
586 );\r
587\r
588Exit:\r
869ccd4a 589 FreePool (ProcessorStr);\r
2ba6ecef
RC
590 FreePool (ProcessorManuStr);\r
591 FreePool (ProcessorVersionStr);\r
592 FreePool (SerialNumberStr);\r
593 FreePool (AssetTagStr);\r
594 FreePool (PartNumberStr);\r
595\r
596 return Status;\r
597}\r
598\r
599/**\r
600 Add Type 4 SMBIOS Record for Processor Information.\r
601\r
602 @param[in] ProcessorIndex Processor index of specified processor.\r
603\r
604**/\r
605EFI_STATUS\r
606AddSmbiosProcessorTypeTable (\r
607 IN UINTN ProcessorIndex\r
608 )\r
609{\r
610 EFI_STATUS Status;\r
611 SMBIOS_TABLE_TYPE4 *Type4Record;\r
612 EFI_SMBIOS_HANDLE SmbiosHandle;\r
613 EFI_SMBIOS_HANDLE L1CacheHandle;\r
614 EFI_SMBIOS_HANDLE L2CacheHandle;\r
615 EFI_SMBIOS_HANDLE L3CacheHandle;\r
616 UINT8 *LegacyVoltage;\r
617 PROCESSOR_STATUS_DATA ProcessorStatus;\r
618 UINT64 *ProcessorId;\r
619 PROCESSOR_CHARACTERISTIC_FLAGS ProcessorCharacteristics;\r
620 OEM_MISC_PROCESSOR_DATA MiscProcessorData;\r
869ccd4a 621 BOOLEAN ProcessorPopulated;\r
2ba6ecef
RC
622\r
623 Type4Record = NULL;\r
624\r
625 MiscProcessorData.Voltage = 0;\r
626 MiscProcessorData.CurrentSpeed = 0;\r
627 MiscProcessorData.CoreCount = 0;\r
628 MiscProcessorData.CoresEnabled = 0;\r
629 MiscProcessorData.ThreadCount = 0;\r
630 MiscProcessorData.MaxSpeed = 0;\r
631 L1CacheHandle = 0xFFFF;\r
632 L2CacheHandle = 0xFFFF;\r
633 L3CacheHandle = 0xFFFF;\r
634\r
869ccd4a 635 ProcessorPopulated = OemIsProcessorPresent (ProcessorIndex);\r
2ba6ecef
RC
636\r
637 Status = AllocateType4AndSetProcessorInformationStrings (\r
638 &Type4Record,\r
639 ProcessorIndex,\r
869ccd4a 640 ProcessorPopulated\r
2ba6ecef
RC
641 );\r
642 if (EFI_ERROR (Status)) {\r
643 return Status;\r
644 }\r
645\r
646 OemGetProcessorInformation (ProcessorIndex,\r
647 &ProcessorStatus,\r
648 (PROCESSOR_CHARACTERISTIC_FLAGS*)\r
649 &Type4Record->ProcessorCharacteristics,\r
650 &MiscProcessorData);\r
651\r
869ccd4a 652 if (ProcessorPopulated) {\r
2ba6ecef
RC
653 AddSmbiosCacheTypeTable (ProcessorIndex, &L1CacheHandle,\r
654 &L2CacheHandle, &L3CacheHandle);\r
655 }\r
656\r
657 LegacyVoltage = (UINT8*)&Type4Record->Voltage;\r
658\r
659 *LegacyVoltage = MiscProcessorData.Voltage;\r
660 Type4Record->CurrentSpeed = MiscProcessorData.CurrentSpeed;\r
661 Type4Record->MaxSpeed = MiscProcessorData.MaxSpeed;\r
662 Type4Record->Status = ProcessorStatus.Data;\r
663 Type4Record->L1CacheHandle = L1CacheHandle;\r
664 Type4Record->L2CacheHandle = L2CacheHandle;\r
665 Type4Record->L3CacheHandle = L3CacheHandle;\r
666 Type4Record->CoreCount = MiscProcessorData.CoreCount;\r
667 Type4Record->CoreCount2 = MiscProcessorData.CoreCount;\r
668 Type4Record->EnabledCoreCount = MiscProcessorData.CoresEnabled;\r
669 Type4Record->EnabledCoreCount2 = MiscProcessorData.CoresEnabled;\r
670 Type4Record->ThreadCount = MiscProcessorData.ThreadCount;\r
671 Type4Record->ThreadCount2 = MiscProcessorData.ThreadCount;\r
672\r
673 Type4Record->CurrentSpeed = GetCpuFrequency (ProcessorIndex);\r
674 Type4Record->ExternalClock =\r
675 (UINT16)(SmbiosGetExternalClockFrequency () / 1000 / 1000);\r
676\r
677 ProcessorId = (UINT64*)&Type4Record->ProcessorId;\r
678 *ProcessorId = SmbiosGetProcessorId ();\r
679\r
680 ProcessorCharacteristics = SmbiosGetProcessorCharacteristics ();\r
681 Type4Record->ProcessorCharacteristics |= *((UINT64*)&ProcessorCharacteristics);\r
682\r
683 Type4Record->ProcessorFamily = SmbiosGetProcessorFamily ();\r
684 Type4Record->ProcessorFamily2 = SmbiosGetProcessorFamily2 ();\r
685\r
686 SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;\r
687 Status = mSmbios->Add (mSmbios, NULL, &SmbiosHandle,\r
688 (EFI_SMBIOS_TABLE_HEADER *)Type4Record);\r
689\r
690 if (EFI_ERROR (Status)) {\r
691 DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Smbios Type04 Table Log Failed! %r \n",\r
f331310a 692 __FUNCTION__, DEBUG_LINE_NUMBER, Status));\r
2ba6ecef
RC
693 }\r
694 FreePool (Type4Record);\r
695\r
696 return Status;\r
697}\r
698\r
699/**\r
700 Standard EFI driver point.\r
701\r
702 @param ImageHandle Handle for the image of this driver\r
703 @param SystemTable Pointer to the EFI System Table\r
704\r
705 @retval EFI_SUCCESS The data was successfully stored.\r
706\r
707**/\r
708EFI_STATUS\r
709EFIAPI\r
710ProcessorSubClassEntryPoint(\r
711 IN EFI_HANDLE ImageHandle,\r
712 IN EFI_SYSTEM_TABLE *SystemTable\r
713 )\r
714{\r
715 EFI_STATUS Status;\r
869ccd4a 716 UINT32 ProcessorIndex;\r
2ba6ecef
RC
717\r
718 //\r
719 // Locate dependent protocols\r
720 //\r
721 Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID**)&mSmbios);\r
722 if (EFI_ERROR (Status)) {\r
723 DEBUG ((DEBUG_ERROR, "Could not locate SMBIOS protocol. %r\n", Status));\r
724 return Status;\r
725 }\r
726\r
727 //\r
728 // Add our default strings to the HII database. They will be modified later.\r
729 //\r
730 mHiiHandle = HiiAddPackages (&gEfiCallerIdGuid,\r
731 NULL,\r
732 ProcessorSubClassStrings,\r
733 NULL,\r
734 NULL\r
735 );\r
736 if (mHiiHandle == NULL) {\r
737 return EFI_OUT_OF_RESOURCES;\r
738 }\r
739\r
740 //\r
741 // Add SMBIOS tables for populated sockets.\r
742 //\r
869ccd4a
RC
743 for (ProcessorIndex = 0; ProcessorIndex < OemGetMaxProcessors (); ProcessorIndex++) {\r
744 Status = AddSmbiosProcessorTypeTable (ProcessorIndex);\r
2ba6ecef
RC
745 if (EFI_ERROR (Status)) {\r
746 DEBUG ((DEBUG_ERROR, "Add Processor Type Table Failed! %r.\n", Status));\r
747 return Status;\r
748 }\r
749 }\r
750\r
751 return Status;\r
752}\r