]> git.proxmox.com Git - mirror_edk2.git/blame - EmulatorPkg/CpuRuntimeDxe/Cpu.c
Remove Framework concepts and fully port to PI. Remove the use of Hii for hard coded...
[mirror_edk2.git] / EmulatorPkg / CpuRuntimeDxe / Cpu.c
CommitLineData
949f388f 1/*++ @file\r
2 Emu driver to produce CPU Architectural Protocol.\r
d18d8a1d 3\r
949f388f 4Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
a0af6b27 5Portions copyright (c) 2011 - 2012, Apple Inc. All rights reserved.\r
949f388f 6This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "CpuDriver.h"\r
17\r
18UINT64 mTimerPeriod;\r
19\r
20CPU_ARCH_PROTOCOL_PRIVATE mCpuTemplate = {\r
21 CPU_ARCH_PROT_PRIVATE_SIGNATURE,\r
22 NULL,\r
23 {\r
24 EmuFlushCpuDataCache,\r
25 EmuEnableInterrupt,\r
26 EmuDisableInterrupt,\r
27 EmuGetInterruptState,\r
28 EmuInit,\r
29 EmuRegisterInterruptHandler,\r
30 EmuGetTimerValue,\r
31 EmuSetMemoryAttributes,\r
32 0,\r
33 4\r
34 },\r
35 {\r
36 {\r
37 CpuMemoryServiceRead,\r
38 CpuMemoryServiceWrite\r
39 },\r
40 {\r
41 CpuIoServiceRead,\r
42 CpuIoServiceWrite\r
43 }\r
44 },\r
45 TRUE\r
46};\r
47\r
48#define EFI_CPU_DATA_MAXIMUM_LENGTH 0x100\r
49\r
a0af6b27 50SMBIOS_TABLE_TYPE4 mCpuSmbiosType4 = {\r
51 { EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION, sizeof (SMBIOS_TABLE_TYPE4), 0},\r
52 1, // Socket String\r
53 ProcessorOther, // ProcessorType; ///< The enumeration value from PROCESSOR_TYPE_DATA.\r
54 ProcessorFamilyOther, // ProcessorFamily; ///< The enumeration value from PROCESSOR_FAMILY_DATA.\r
55 2, // ProcessorManufacture String;\r
56 { // ProcessorId;\r
57 { // PROCESSOR_SIGNATURE\r
58 0, // ProcessorSteppingId:4;\r
59 0, // ProcessorModel: 4;\r
60 0, // ProcessorFamily: 4;\r
61 0, // ProcessorType: 2;\r
62 0, // ProcessorReserved1: 2;\r
63 0, // ProcessorXModel: 4;\r
64 0, // ProcessorXFamily: 8;\r
65 0, // ProcessorReserved2: 4;\r
66 }, \r
67 { // PROCESSOR_FEATURE_FLAGS\r
68 0, // ProcessorFpu :1;\r
69 0, // ProcessorVme :1;\r
70 0, // ProcessorDe :1;\r
71 0, // ProcessorPse :1;\r
72 0, // ProcessorTsc :1;\r
73 0, // ProcessorMsr :1;\r
74 0, // ProcessorPae :1;\r
75 0, // ProcessorMce :1;\r
76 0, // ProcessorCx8 :1;\r
77 0, // ProcessorApic :1;\r
78 0, // ProcessorReserved1 :1;\r
79 0, // ProcessorSep :1;\r
80 0, // ProcessorMtrr :1;\r
81 0, // ProcessorPge :1;\r
82 0, // ProcessorMca :1;\r
83 0, // ProcessorCmov :1;\r
84 0, // ProcessorPat :1;\r
85 0, // ProcessorPse36 :1;\r
86 0, // ProcessorPsn :1;\r
87 0, // ProcessorClfsh :1;\r
88 0, // ProcessorReserved2 :1;\r
89 0, // ProcessorDs :1;\r
90 0, // ProcessorAcpi :1;\r
91 0, // ProcessorMmx :1;\r
92 0, // ProcessorFxsr :1;\r
93 0, // ProcessorSse :1;\r
94 0, // ProcessorSse2 :1;\r
95 0, // ProcessorSs :1;\r
96 0, // ProcessorReserved3 :1;\r
97 0, // ProcessorTm :1;\r
98 0, // ProcessorReserved4 :2;\r
99 }\r
100 },\r
101 3, // ProcessorVersion String;\r
102 { // Voltage;\r
103 1, // ProcessorVoltageCapability5V :1; \r
104 1, // ProcessorVoltageCapability3_3V :1; \r
105 1, // ProcessorVoltageCapability2_9V :1; \r
106 0, // ProcessorVoltageCapabilityReserved :1; ///< Bit 3, must be zero.\r
107 0, // ProcessorVoltageReserved :3; ///< Bits 4-6, must be zero.\r
108 0 // ProcessorVoltageIndicateLegacy :1;\r
109 }, \r
110 0, // ExternalClock;\r
111 0, // MaxSpeed;\r
112 0, // CurrentSpeed;\r
113 0x41, // Status;\r
114 ProcessorUpgradeOther, // ProcessorUpgrade; ///< The enumeration value from PROCESSOR_UPGRADE.\r
115 0, // L1CacheHandle;\r
116 0, // L2CacheHandle;\r
117 0, // L3CacheHandle;\r
118 4, // SerialNumber;\r
119 5, // AssetTag;\r
120 6, // PartNumber;\r
121 0, // CoreCount;\r
122 0, // EnabledCoreCount;\r
123 0, // ThreadCount;\r
124 0, // ProcessorCharacteristics;\r
125 0, // ProcessorFamily2;\r
126};\r
127\r
128CHAR8 *mCpuSmbiosType4Strings[] = {\r
129 "Socket",\r
130 "edk2.svn.sourceforge.net",\r
131 "Emulated Processor",\r
132 "1.0",\r
133 "1.0",\r
134 "1.0",\r
135 NULL\r
136};\r
137\r
138\r
139/**\r
140 Logs SMBIOS record.\r
141\r
142 Note: This should be a genric library function.\r
143\r
144 @param Template Fixed SMBIOS structure\r
145 @param StringPack Array of strings to convert to an SMBIOS string pack. \r
146\r
147**/\r
148EFI_STATUS\r
149LogSmbiosData (\r
150 IN EFI_SMBIOS_TABLE_HEADER *Template,\r
151 IN CHAR8 **StringPack \r
152 )\r
153{\r
154 EFI_STATUS Status;\r
155 EFI_SMBIOS_PROTOCOL *Smbios; \r
156 EFI_SMBIOS_HANDLE SmbiosHandle;\r
157 EFI_SMBIOS_TABLE_HEADER *Record;\r
158 UINTN Index;\r
159 UINTN StringSize;\r
160 UINTN Size;\r
161 CHAR8 *Str;\r
162\r
163 //\r
164 // Locate Smbios protocol.\r
165 //\r
166 Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **)&Smbios);\r
167 if (EFI_ERROR (Status)) {\r
168 return Status;\r
169 }\r
170\r
171 // Calculate the size of the fixed record and optional string pack\r
172 Size = Template->Length;\r
173 for (Index = 0; StringPack[Index] != NULL; Index++) {\r
174 StringSize = AsciiStrSize (StringPack[Index]);\r
175 Size += StringSize;\r
176 }\r
177 // Don't forget the terminating double null\r
178 Size += 1;\r
179\r
180 // Copy over Template\r
181 Record = (EFI_SMBIOS_TABLE_HEADER *)AllocateZeroPool (Size);\r
182 if (Record == NULL) {\r
183 return EFI_OUT_OF_RESOURCES;\r
184 }\r
185 CopyMem (Record, Template, Template->Length);\r
186\r
187 // Append string pack\r
188 Str = ((CHAR8 *)Record) + Record->Length;\r
189 for (Index = 0; StringPack[Index] != NULL; Index++) {\r
190 StringSize = AsciiStrSize (StringPack[Index]);\r
191 CopyMem (Str, StringPack[Index], StringSize);\r
192 Str += StringSize;\r
193 }\r
194 *Str = 0;\r
195 \r
196 SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;\r
197 Status = Smbios->Add (\r
198 Smbios,\r
199 gImageHandle,\r
200 &SmbiosHandle,\r
201 Record\r
202 );\r
203 ASSERT_EFI_ERROR (Status);\r
204 \r
205 FreePool (Record);\r
206 return Status;\r
207}\r
208\r
209\r
210\r
211\r
212VOID\r
213CpuUpdateSmbios (\r
214 IN UINTN MaxCpus\r
215 )\r
216{\r
217 mCpuSmbiosType4.CoreCount = MaxCpus;\r
218 mCpuSmbiosType4.EnabledCoreCount = MaxCpus;\r
219 mCpuSmbiosType4.ThreadCount = MaxCpus;\r
220\r
221 LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER *)&mCpuSmbiosType4, mCpuSmbiosType4Strings);\r
222}\r
949f388f 223\r
224\r
225//\r
226// Service routines for the driver\r
227//\r
228EFI_STATUS\r
229EFIAPI\r
230EmuFlushCpuDataCache (\r
231 IN EFI_CPU_ARCH_PROTOCOL *This,\r
232 IN EFI_PHYSICAL_ADDRESS Start,\r
233 IN UINT64 Length,\r
234 IN EFI_CPU_FLUSH_TYPE FlushType\r
235 )\r
236{\r
237 if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {\r
238 //\r
239 // Only WB flush is supported. We actually need do nothing on Emu emulator\r
240 // environment. Classify this to follow EFI spec\r
241 //\r
242 return EFI_SUCCESS;\r
243 }\r
244 //\r
245 // Other flush types are not supported by Emu emulator\r
246 //\r
247 return EFI_UNSUPPORTED;\r
248}\r
249\r
250EFI_STATUS\r
251EFIAPI\r
252EmuEnableInterrupt (\r
253 IN EFI_CPU_ARCH_PROTOCOL *This\r
254 )\r
255{\r
256 CPU_ARCH_PROTOCOL_PRIVATE *Private;\r
257\r
258 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);\r
259 Private->InterruptState = TRUE;\r
260 gEmuThunk->EnableInterrupt ();\r
261 return EFI_SUCCESS;\r
262}\r
263\r
264EFI_STATUS\r
265EFIAPI\r
266EmuDisableInterrupt (\r
267 IN EFI_CPU_ARCH_PROTOCOL *This\r
268 )\r
269{\r
270 CPU_ARCH_PROTOCOL_PRIVATE *Private;\r
271\r
272 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);\r
273 Private->InterruptState = FALSE;\r
274 gEmuThunk->DisableInterrupt ();\r
275 return EFI_SUCCESS;\r
276}\r
277\r
278EFI_STATUS\r
279EFIAPI\r
280EmuGetInterruptState (\r
281 IN EFI_CPU_ARCH_PROTOCOL *This,\r
282 OUT BOOLEAN *State\r
283 )\r
284{\r
285 CPU_ARCH_PROTOCOL_PRIVATE *Private;\r
286\r
287 if (State == NULL) {\r
288 return EFI_INVALID_PARAMETER;\r
289 }\r
290\r
291 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);\r
292 *State = Private->InterruptState;\r
293 return EFI_SUCCESS;\r
294}\r
295\r
296EFI_STATUS\r
297EFIAPI\r
298EmuInit (\r
299 IN EFI_CPU_ARCH_PROTOCOL *This,\r
300 IN EFI_CPU_INIT_TYPE InitType\r
301 )\r
302{\r
a0af6b27 303 CPU_ARCH_PROTOCOL_PRIVATE *Private;\r
304\r
305 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);\r
949f388f 306 return EFI_UNSUPPORTED;\r
307}\r
308\r
309EFI_STATUS\r
310EFIAPI\r
311EmuRegisterInterruptHandler (\r
312 IN EFI_CPU_ARCH_PROTOCOL *This,\r
313 IN EFI_EXCEPTION_TYPE InterruptType,\r
314 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler\r
315 )\r
316{\r
a0af6b27 317 CPU_ARCH_PROTOCOL_PRIVATE *Private;\r
318\r
949f388f 319 //\r
320 // Do parameter checking for EFI spec conformance\r
321 //\r
322 if (InterruptType < 0 || InterruptType > 0xff) {\r
323 return EFI_UNSUPPORTED;\r
324 }\r
325 //\r
326 // Do nothing for Emu emulation\r
327 //\r
a0af6b27 328 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);\r
949f388f 329 return EFI_UNSUPPORTED;\r
330}\r
331\r
332EFI_STATUS\r
333EFIAPI\r
334EmuGetTimerValue (\r
335 IN EFI_CPU_ARCH_PROTOCOL *This,\r
336 IN UINT32 TimerIndex,\r
337 OUT UINT64 *TimerValue,\r
338 OUT UINT64 *TimerPeriod OPTIONAL\r
339 )\r
340{\r
341 if (TimerValue == NULL) {\r
342 return EFI_INVALID_PARAMETER;\r
343 }\r
344\r
345 if (TimerIndex != 0) {\r
346 return EFI_INVALID_PARAMETER;\r
347 }\r
d18d8a1d 348\r
949f388f 349 *TimerValue = gEmuThunk->QueryPerformanceCounter ();\r
d18d8a1d 350\r
949f388f 351 if (TimerPeriod != NULL) {\r
352 *TimerPeriod = mTimerPeriod;\r
d18d8a1d 353 }\r
949f388f 354\r
355 return EFI_SUCCESS;\r
356}\r
357\r
358\r
359EFI_STATUS\r
360EFIAPI\r
361EmuSetMemoryAttributes (\r
362 IN EFI_CPU_ARCH_PROTOCOL *This,\r
363 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
364 IN UINT64 Length,\r
365 IN UINT64 Attributes\r
366 )\r
367{\r
a0af6b27 368 CPU_ARCH_PROTOCOL_PRIVATE *Private;\r
369\r
949f388f 370 //\r
371 // Check for invalid parameter for Spec conformance\r
372 //\r
373 if (Length == 0) {\r
374 return EFI_INVALID_PARAMETER;\r
375 }\r
376\r
377 //\r
378 // Do nothing for Nt32 emulation\r
379 //\r
a0af6b27 380 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);\r
949f388f 381 return EFI_UNSUPPORTED;\r
382}\r
383\r
384\r
385\r
57c7d70f 386\r
387/**\r
388 Callback function for idle events.\r
d18d8a1d 389\r
57c7d70f 390 @param Event Event whose notification function is being invoked.\r
391 @param Context The pointer to the notification function's context,\r
392 which is implementation-dependent.\r
393\r
394**/\r
395VOID\r
396EFIAPI\r
397IdleLoopEventCallback (\r
398 IN EFI_EVENT Event,\r
399 IN VOID *Context\r
400 )\r
401{\r
402 gEmuThunk->CpuSleep ();\r
403}\r
404\r
405\r
949f388f 406EFI_STATUS\r
407EFIAPI\r
408InitializeCpu (\r
409 IN EFI_HANDLE ImageHandle,\r
410 IN EFI_SYSTEM_TABLE *SystemTable\r
411 )\r
412{\r
413 EFI_STATUS Status;\r
414 UINT64 Frequency;\r
57c7d70f 415 EFI_EVENT IdleLoopEvent;\r
a0af6b27 416 UINTN MaxCpu;\r
949f388f 417\r
418 //\r
419 // Retrieve the frequency of the performance counter in Hz.\r
d18d8a1d 420 //\r
949f388f 421 Frequency = gEmuThunk->QueryPerformanceFrequency ();\r
d18d8a1d 422\r
949f388f 423 //\r
424 // Convert frequency in Hz to a clock period in femtoseconds.\r
425 //\r
7e284acb 426 mTimerPeriod = DivU64x64Remainder (1000000000000000ULL, Frequency, NULL);\r
949f388f 427\r
a0af6b27 428 CpuMpServicesInit (&MaxCpu);\r
429\r
430 CpuUpdateSmbios (MaxCpu);\r
d18d8a1d 431\r
d18d8a1d 432\r
57c7d70f 433 Status = gBS->CreateEventEx (\r
434 EVT_NOTIFY_SIGNAL,\r
435 TPL_NOTIFY,\r
436 IdleLoopEventCallback,\r
437 NULL,\r
438 &gIdleLoopEventGuid,\r
439 &IdleLoopEvent\r
440 );\r
441 ASSERT_EFI_ERROR (Status);\r
442\r
949f388f 443\r
444 Status = gBS->InstallMultipleProtocolInterfaces (\r
445 &mCpuTemplate.Handle,\r
446 &gEfiCpuArchProtocolGuid, &mCpuTemplate.Cpu,\r
447 &gEfiCpuIo2ProtocolGuid, &mCpuTemplate.CpuIo,\r
448 NULL\r
449 );\r
450 ASSERT_EFI_ERROR (Status);\r
451\r
452 return Status;\r
453}\r