2 Emu driver to produce CPU Architectural Protocol.
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
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.
16 #include "CpuDriver.h"
20 CPU_ARCH_PROTOCOL_PRIVATE mCpuTemplate
= {
21 CPU_ARCH_PROT_PRIVATE_SIGNATURE
,
29 EmuRegisterInterruptHandler
,
31 EmuSetMemoryAttributes
,
48 #define EFI_CPU_DATA_MAXIMUM_LENGTH 0x100
50 SMBIOS_TABLE_TYPE4 mCpuSmbiosType4
= {
51 { EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION
, sizeof (SMBIOS_TABLE_TYPE4
), 0},
53 ProcessorOther
, // ProcessorType; ///< The enumeration value from PROCESSOR_TYPE_DATA.
54 ProcessorFamilyOther
, // ProcessorFamily; ///< The enumeration value from PROCESSOR_FAMILY_DATA.
55 2, // ProcessorManufacture String;
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;
67 { // PROCESSOR_FEATURE_FLAGS
68 0, // ProcessorFpu :1;
69 0, // ProcessorVme :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;
90 0, // ProcessorAcpi :1;
91 0, // ProcessorMmx :1;
92 0, // ProcessorFxsr :1;
93 0, // ProcessorSse :1;
94 0, // ProcessorSse2 :1;
96 0, // ProcessorReserved3 :1;
98 0, // ProcessorReserved4 :2;
101 3, // ProcessorVersion String;
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;
114 ProcessorUpgradeOther
, // ProcessorUpgrade; ///< The enumeration value from PROCESSOR_UPGRADE.
122 0, // EnabledCoreCount;
124 0, // ProcessorCharacteristics;
125 0, // ProcessorFamily2;
128 CHAR8
*mCpuSmbiosType4Strings
[] = {
130 "edk2.svn.sourceforge.net",
131 "Emulated Processor",
140 Create SMBIOS record.
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.
146 SMBIOS_TABLE_TYPE32 gSmbiosType12 = {
147 { EFI_SMBIOS_TYPE_SYSTEM_CONFIGURATION_OPTIONS, sizeof (SMBIOS_TABLE_TYPE12), 0 },
150 CHAR8 *gSmbiosType12Strings[] = {
157 (EFI_SMBIOS_TABLE_HEADER*)&gSmbiosType12,
161 @param Template Fixed SMBIOS structure, required.
162 @param StringArray Array of strings to convert to an SMBIOS string pack.
168 IN EFI_SMBIOS_TABLE_HEADER
*Template
,
169 IN CHAR8
**StringPack
173 EFI_SMBIOS_PROTOCOL
*Smbios
;
174 EFI_SMBIOS_HANDLE SmbiosHandle
;
175 EFI_SMBIOS_TABLE_HEADER
*Record
;
182 // Locate Smbios protocol.
184 Status
= gBS
->LocateProtocol (&gEfiSmbiosProtocolGuid
, NULL
, (VOID
**)&Smbios
);
185 if (EFI_ERROR (Status
)) {
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
195 for (Index
= 0; StringPack
[Index
] != NULL
; Index
++) {
196 StringSize
= AsciiStrSize (StringPack
[Index
]);
199 if (StringPack
[0] == NULL
) {
200 // At least a double null is required
203 // Don't forget the terminating double null
207 // Copy over Template
208 Record
= (EFI_SMBIOS_TABLE_HEADER
*)AllocateZeroPool (Size
);
209 if (Record
== NULL
) {
210 return EFI_OUT_OF_RESOURCES
;
212 CopyMem (Record
, Template
, Template
->Length
);
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
);
223 SmbiosHandle
= SMBIOS_HANDLE_PI_RESERVED
;
224 Status
= Smbios
->Add (
230 ASSERT_EFI_ERROR (Status
);
244 mCpuSmbiosType4
.CoreCount
= (UINT8
) MaxCpus
;
245 mCpuSmbiosType4
.EnabledCoreCount
= (UINT8
) MaxCpus
;
246 mCpuSmbiosType4
.ThreadCount
= (UINT8
) MaxCpus
;
248 LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER
*)&mCpuSmbiosType4
, mCpuSmbiosType4Strings
);
253 // Service routines for the driver
257 EmuFlushCpuDataCache (
258 IN EFI_CPU_ARCH_PROTOCOL
*This
,
259 IN EFI_PHYSICAL_ADDRESS Start
,
261 IN EFI_CPU_FLUSH_TYPE FlushType
264 if (FlushType
== EfiCpuFlushTypeWriteBackInvalidate
) {
266 // Only WB flush is supported. We actually need do nothing on Emu emulator
267 // environment. Classify this to follow EFI spec
272 // Other flush types are not supported by Emu emulator
274 return EFI_UNSUPPORTED
;
280 IN EFI_CPU_ARCH_PROTOCOL
*This
283 CPU_ARCH_PROTOCOL_PRIVATE
*Private
;
285 Private
= CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This
);
286 Private
->InterruptState
= TRUE
;
287 gEmuThunk
->EnableInterrupt ();
293 EmuDisableInterrupt (
294 IN EFI_CPU_ARCH_PROTOCOL
*This
297 CPU_ARCH_PROTOCOL_PRIVATE
*Private
;
299 Private
= CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This
);
300 Private
->InterruptState
= FALSE
;
301 gEmuThunk
->DisableInterrupt ();
307 EmuGetInterruptState (
308 IN EFI_CPU_ARCH_PROTOCOL
*This
,
312 CPU_ARCH_PROTOCOL_PRIVATE
*Private
;
315 return EFI_INVALID_PARAMETER
;
318 Private
= CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This
);
319 *State
= Private
->InterruptState
;
326 IN EFI_CPU_ARCH_PROTOCOL
*This
,
327 IN EFI_CPU_INIT_TYPE InitType
330 CPU_ARCH_PROTOCOL_PRIVATE
*Private
;
332 Private
= CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This
);
333 return EFI_UNSUPPORTED
;
338 EmuRegisterInterruptHandler (
339 IN EFI_CPU_ARCH_PROTOCOL
*This
,
340 IN EFI_EXCEPTION_TYPE InterruptType
,
341 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
344 CPU_ARCH_PROTOCOL_PRIVATE
*Private
;
347 // Do parameter checking for EFI spec conformance
349 if (InterruptType
< 0 || InterruptType
> 0xff) {
350 return EFI_UNSUPPORTED
;
353 // Do nothing for Emu emulation
355 Private
= CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This
);
356 return EFI_UNSUPPORTED
;
362 IN EFI_CPU_ARCH_PROTOCOL
*This
,
363 IN UINT32 TimerIndex
,
364 OUT UINT64
*TimerValue
,
365 OUT UINT64
*TimerPeriod OPTIONAL
368 if (TimerValue
== NULL
) {
369 return EFI_INVALID_PARAMETER
;
372 if (TimerIndex
!= 0) {
373 return EFI_INVALID_PARAMETER
;
376 *TimerValue
= gEmuThunk
->QueryPerformanceCounter ();
378 if (TimerPeriod
!= NULL
) {
379 *TimerPeriod
= mTimerPeriod
;
388 EmuSetMemoryAttributes (
389 IN EFI_CPU_ARCH_PROTOCOL
*This
,
390 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
395 CPU_ARCH_PROTOCOL_PRIVATE
*Private
;
398 // Check for invalid parameter for Spec conformance
401 return EFI_INVALID_PARAMETER
;
405 // Do nothing for Nt32 emulation
407 Private
= CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This
);
408 return EFI_UNSUPPORTED
;
415 Callback function for idle events.
417 @param Event Event whose notification function is being invoked.
418 @param Context The pointer to the notification function's context,
419 which is implementation-dependent.
424 IdleLoopEventCallback (
429 gEmuThunk
->CpuSleep ();
436 IN EFI_HANDLE ImageHandle
,
437 IN EFI_SYSTEM_TABLE
*SystemTable
442 EFI_EVENT IdleLoopEvent
;
446 // Retrieve the frequency of the performance counter in Hz.
448 Frequency
= gEmuThunk
->QueryPerformanceFrequency ();
451 // Convert frequency in Hz to a clock period in femtoseconds.
453 mTimerPeriod
= DivU64x64Remainder (1000000000000000ULL, Frequency
, NULL
);
455 CpuMpServicesInit (&MaxCpu
);
457 CpuUpdateSmbios (MaxCpu
);
460 Status
= gBS
->CreateEventEx (
463 IdleLoopEventCallback
,
468 ASSERT_EFI_ERROR (Status
);
471 Status
= gBS
->InstallMultipleProtocolInterfaces (
472 &mCpuTemplate
.Handle
,
473 &gEfiCpuArchProtocolGuid
, &mCpuTemplate
.Cpu
,
474 &gEfiCpuIo2ProtocolGuid
, &mCpuTemplate
.CpuIo
,
477 ASSERT_EFI_ERROR (Status
);