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