]>
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 | |
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 | 32 | extern 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 |
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 | |
429309e0 | 55 | EFI_HII_HANDLE mHiiHandle;\r |
2ba6ecef RC |
56 | \r |
57 | EFI_SMBIOS_PROTOCOL *mSmbios;\r | |
58 | \r | |
429309e0 MK |
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 | |
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 | |
123 | UINT16\r | |
124 | GetCpuFrequency (\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 | |
141 | UINTN\r | |
142 | GetCacheSocketStr (\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 | |
186 | VOID\r | |
187 | ConfigureCacheArchitectureInformation (\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 | |
296 | SMBIOS_TABLE_TYPE7 *\r | |
297 | AllocateAndInitCacheInformation (\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 | |
358 | VOID\r | |
359 | AddSmbiosCacheTypeTable (\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 | |
470 | EFI_STATUS\r | |
471 | AllocateType4AndSetProcessorInformationStrings (\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 | |
612 | Exit:\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 | |
629 | EFI_STATUS\r | |
630 | AddSmbiosProcessorTypeTable (\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 | |
748 | EFI_STATUS\r | |
749 | EFIAPI\r | |
429309e0 MK |
750 | ProcessorSubClassEntryPoint (\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 |