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