]>
Commit | Line | Data |
---|---|---|
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 | |
13 | #include <IndustryStandard/ArmStdSmc.h>\r | |
14 | #include <IndustryStandard/SmBios.h>\r | |
15 | #include <Library/ArmLib.h>\r | |
16 | #include <Library/ArmSmcLib.h>\r | |
17 | #include <Library/ArmLib/ArmLibPrivate.h>\r | |
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 | |
32 | extern 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 | |
39 | typedef 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 | |
47 | typedef 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 | |
55 | EFI_HII_HANDLE mHiiHandle;\r | |
56 | \r | |
57 | EFI_SMBIOS_PROTOCOL *mSmbios;\r | |
58 | \r | |
59 | SMBIOS_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 | |
123 | UINT16\r | |
124 | GetCpuFrequency (\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 | |
141 | UINTN\r | |
142 | GetCacheSocketStr (\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 | |
181 | VOID\r | |
182 | ConfigureCacheArchitectureInformation (\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 | |
222 | CacheSize32 = CacheSize16;\r | |
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 | |
290 | SMBIOS_TABLE_TYPE7 *\r | |
291 | AllocateAndInitCacheInformation (\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 | |
350 | VOID\r | |
351 | AddSmbiosCacheTypeTable (\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 | |
442 | @param[in] ProcessorIndex The index of the processor socket\r | |
443 | @param[in] Populated Whether the specified processor socket is\r | |
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 | |
450 | EFI_STATUS\r | |
451 | AllocateType4AndSetProcessorInformationStrings (\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 | |
463 | EFI_STRING ProcessorSocketStr;\r | |
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 | |
471 | UINTN ProcessorSocketStrLen;\r | |
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 | |
500 | // Processor Socket Designation\r | |
501 | StringBufferSize = sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH;\r | |
502 | ProcessorSocketStr = AllocateZeroPool (StringBufferSize);\r | |
503 | if (ProcessorSocketStr == NULL) {\r | |
504 | return EFI_OUT_OF_RESOURCES;\r | |
505 | }\r | |
506 | \r | |
507 | ProcessorSocketStrLen = UnicodeSPrint (ProcessorSocketStr, StringBufferSize,\r | |
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 | |
531 | ProcessorSocketStrLen + 1 +\r | |
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 | |
548 | ProcessorSocketStr,\r | |
549 | OptionalStrStart,\r | |
550 | ProcessorSocketStrLen + 1\r | |
551 | );\r | |
552 | \r | |
553 | StrStart = OptionalStrStart + ProcessorSocketStrLen + 1;\r | |
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 | |
588 | Exit:\r | |
589 | FreePool (ProcessorSocketStr);\r | |
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 | |
605 | EFI_STATUS\r | |
606 | AddSmbiosProcessorTypeTable (\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 | |
621 | BOOLEAN SocketPopulated;\r | |
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 | |
635 | SocketPopulated = OemIsSocketPresent(ProcessorIndex);\r | |
636 | \r | |
637 | Status = AllocateType4AndSetProcessorInformationStrings (\r | |
638 | &Type4Record,\r | |
639 | ProcessorIndex,\r | |
640 | SocketPopulated\r | |
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 | |
652 | if (SocketPopulated) {\r | |
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 | |
692 | __FUNCTION__, __LINE__, Status));\r | |
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 | |
708 | EFI_STATUS\r | |
709 | EFIAPI\r | |
710 | ProcessorSubClassEntryPoint(\r | |
711 | IN EFI_HANDLE ImageHandle,\r | |
712 | IN EFI_SYSTEM_TABLE *SystemTable\r | |
713 | )\r | |
714 | {\r | |
715 | EFI_STATUS Status;\r | |
716 | UINT32 SocketIndex;\r | |
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 | |
743 | for (SocketIndex = 0; SocketIndex < OemGetProcessorMaxSockets(); SocketIndex++) {\r | |
744 | Status = AddSmbiosProcessorTypeTable (SocketIndex);\r | |
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 |