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 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "CpuDriver.h"
14 CPU_ARCH_PROTOCOL_PRIVATE mCpuTemplate
= {
15 CPU_ARCH_PROT_PRIVATE_SIGNATURE
,
23 EmuRegisterInterruptHandler
,
25 EmuSetMemoryAttributes
,
42 #define EFI_CPU_DATA_MAXIMUM_LENGTH 0x100
44 SMBIOS_TABLE_TYPE4 mCpuSmbiosType4
= {
45 { EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION
, sizeof (SMBIOS_TABLE_TYPE4
), 0},
47 ProcessorOther
, // ProcessorType; ///< The enumeration value from PROCESSOR_TYPE_DATA.
48 ProcessorFamilyOther
, // ProcessorFamily; ///< The enumeration value from PROCESSOR_FAMILY_DATA.
49 2, // ProcessorManufacture String;
51 { // PROCESSOR_SIGNATURE
52 0, // ProcessorSteppingId:4;
53 0, // ProcessorModel: 4;
54 0, // ProcessorFamily: 4;
55 0, // ProcessorType: 2;
56 0, // ProcessorReserved1: 2;
57 0, // ProcessorXModel: 4;
58 0, // ProcessorXFamily: 8;
59 0, // ProcessorReserved2: 4;
61 { // PROCESSOR_FEATURE_FLAGS
62 0, // ProcessorFpu :1;
63 0, // ProcessorVme :1;
65 0, // ProcessorPse :1;
66 0, // ProcessorTsc :1;
67 0, // ProcessorMsr :1;
68 0, // ProcessorPae :1;
69 0, // ProcessorMce :1;
70 0, // ProcessorCx8 :1;
71 0, // ProcessorApic :1;
72 0, // ProcessorReserved1 :1;
73 0, // ProcessorSep :1;
74 0, // ProcessorMtrr :1;
75 0, // ProcessorPge :1;
76 0, // ProcessorMca :1;
77 0, // ProcessorCmov :1;
78 0, // ProcessorPat :1;
79 0, // ProcessorPse36 :1;
80 0, // ProcessorPsn :1;
81 0, // ProcessorClfsh :1;
82 0, // ProcessorReserved2 :1;
84 0, // ProcessorAcpi :1;
85 0, // ProcessorMmx :1;
86 0, // ProcessorFxsr :1;
87 0, // ProcessorSse :1;
88 0, // ProcessorSse2 :1;
90 0, // ProcessorReserved3 :1;
92 0, // ProcessorReserved4 :2;
95 3, // ProcessorVersion String;
97 1, // ProcessorVoltageCapability5V :1;
98 1, // ProcessorVoltageCapability3_3V :1;
99 1, // ProcessorVoltageCapability2_9V :1;
100 0, // ProcessorVoltageCapabilityReserved :1; ///< Bit 3, must be zero.
101 0, // ProcessorVoltageReserved :3; ///< Bits 4-6, must be zero.
102 0 // ProcessorVoltageIndicateLegacy :1;
108 ProcessorUpgradeOther
, // ProcessorUpgrade; ///< The enumeration value from PROCESSOR_UPGRADE.
116 0, // EnabledCoreCount;
118 0, // ProcessorCharacteristics;
119 0, // ProcessorFamily2;
122 CHAR8
*mCpuSmbiosType4Strings
[] = {
124 "http://www.tianocore.org/edk2/",
125 "Emulated Processor",
134 Create SMBIOS record.
136 Converts a fixed SMBIOS structure and an array of pointers to strings into
137 an SMBIOS record where the strings are cat'ed on the end of the fixed record
138 and terminated via a double NULL and add to SMBIOS table.
140 SMBIOS_TABLE_TYPE32 gSmbiosType12 = {
141 { EFI_SMBIOS_TYPE_SYSTEM_CONFIGURATION_OPTIONS, sizeof (SMBIOS_TABLE_TYPE12), 0 },
144 CHAR8 *gSmbiosType12Strings[] = {
151 (EFI_SMBIOS_TABLE_HEADER*)&gSmbiosType12,
155 @param Template Fixed SMBIOS structure, required.
156 @param StringArray Array of strings to convert to an SMBIOS string pack.
162 IN EFI_SMBIOS_TABLE_HEADER
*Template
,
163 IN CHAR8
**StringPack
167 EFI_SMBIOS_PROTOCOL
*Smbios
;
168 EFI_SMBIOS_HANDLE SmbiosHandle
;
169 EFI_SMBIOS_TABLE_HEADER
*Record
;
176 // Locate Smbios protocol.
178 Status
= gBS
->LocateProtocol (&gEfiSmbiosProtocolGuid
, NULL
, (VOID
**)&Smbios
);
179 if (EFI_ERROR (Status
)) {
183 // Calculate the size of the fixed record and optional string pack
184 Size
= Template
->Length
;
185 if (StringPack
== NULL
) {
186 // At least a double null is required
189 for (Index
= 0; StringPack
[Index
] != NULL
; Index
++) {
190 StringSize
= AsciiStrSize (StringPack
[Index
]);
193 if (StringPack
[0] == NULL
) {
194 // At least a double null is required
197 // Don't forget the terminating double null
201 // Copy over Template
202 Record
= (EFI_SMBIOS_TABLE_HEADER
*)AllocateZeroPool (Size
);
203 if (Record
== NULL
) {
204 return EFI_OUT_OF_RESOURCES
;
206 CopyMem (Record
, Template
, Template
->Length
);
208 // Append string pack
209 Str
= ((CHAR8
*)Record
) + Record
->Length
;
210 for (Index
= 0; StringPack
[Index
] != NULL
; Index
++) {
211 StringSize
= AsciiStrSize (StringPack
[Index
]);
212 CopyMem (Str
, StringPack
[Index
], StringSize
);
217 SmbiosHandle
= SMBIOS_HANDLE_PI_RESERVED
;
218 Status
= Smbios
->Add (
224 ASSERT_EFI_ERROR (Status
);
238 mCpuSmbiosType4
.CoreCount
= (UINT8
) MaxCpus
;
239 mCpuSmbiosType4
.EnabledCoreCount
= (UINT8
) MaxCpus
;
240 mCpuSmbiosType4
.ThreadCount
= (UINT8
) MaxCpus
;
242 // The value of 1234 is fake value for CPU frequency
244 mCpuSmbiosType4
.CurrentSpeed
= 1234;
245 LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER
*)&mCpuSmbiosType4
, mCpuSmbiosType4Strings
);
250 // Service routines for the driver
254 EmuFlushCpuDataCache (
255 IN EFI_CPU_ARCH_PROTOCOL
*This
,
256 IN EFI_PHYSICAL_ADDRESS Start
,
258 IN EFI_CPU_FLUSH_TYPE FlushType
261 if (FlushType
== EfiCpuFlushTypeWriteBackInvalidate
) {
263 // Only WB flush is supported. We actually need do nothing on Emu emulator
264 // environment. Classify this to follow EFI spec
269 // Other flush types are not supported by Emu emulator
271 return EFI_UNSUPPORTED
;
277 IN EFI_CPU_ARCH_PROTOCOL
*This
280 CPU_ARCH_PROTOCOL_PRIVATE
*Private
;
282 Private
= CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This
);
283 Private
->InterruptState
= TRUE
;
284 gEmuThunk
->EnableInterrupt ();
290 EmuDisableInterrupt (
291 IN EFI_CPU_ARCH_PROTOCOL
*This
294 CPU_ARCH_PROTOCOL_PRIVATE
*Private
;
296 Private
= CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This
);
297 Private
->InterruptState
= FALSE
;
298 gEmuThunk
->DisableInterrupt ();
304 EmuGetInterruptState (
305 IN EFI_CPU_ARCH_PROTOCOL
*This
,
309 CPU_ARCH_PROTOCOL_PRIVATE
*Private
;
312 return EFI_INVALID_PARAMETER
;
315 Private
= CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This
);
316 *State
= Private
->InterruptState
;
323 IN EFI_CPU_ARCH_PROTOCOL
*This
,
324 IN EFI_CPU_INIT_TYPE InitType
327 return EFI_UNSUPPORTED
;
332 EmuRegisterInterruptHandler (
333 IN EFI_CPU_ARCH_PROTOCOL
*This
,
334 IN EFI_EXCEPTION_TYPE InterruptType
,
335 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
339 // Do parameter checking for EFI spec conformance
341 if (InterruptType
< 0 || InterruptType
> 0xff) {
342 return EFI_UNSUPPORTED
;
345 // Do nothing for Emu emulation
347 return EFI_UNSUPPORTED
;
353 IN EFI_CPU_ARCH_PROTOCOL
*This
,
354 IN UINT32 TimerIndex
,
355 OUT UINT64
*TimerValue
,
356 OUT UINT64
*TimerPeriod OPTIONAL
359 if (TimerValue
== NULL
) {
360 return EFI_INVALID_PARAMETER
;
363 if (TimerIndex
!= 0) {
364 return EFI_INVALID_PARAMETER
;
367 *TimerValue
= gEmuThunk
->QueryPerformanceCounter ();
369 if (TimerPeriod
!= NULL
) {
370 *TimerPeriod
= mTimerPeriod
;
379 EmuSetMemoryAttributes (
380 IN EFI_CPU_ARCH_PROTOCOL
*This
,
381 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
387 // Check for invalid parameter for Spec conformance
390 return EFI_INVALID_PARAMETER
;
394 // Do nothing for Nt32 emulation
396 return EFI_UNSUPPORTED
;
403 Callback function for idle events.
405 @param Event Event whose notification function is being invoked.
406 @param Context The pointer to the notification function's context,
407 which is implementation-dependent.
412 IdleLoopEventCallback (
417 gEmuThunk
->CpuSleep ();
424 IN EFI_HANDLE ImageHandle
,
425 IN EFI_SYSTEM_TABLE
*SystemTable
430 EFI_EVENT IdleLoopEvent
;
434 // Retrieve the frequency of the performance counter in Hz.
436 Frequency
= gEmuThunk
->QueryPerformanceFrequency ();
439 // Convert frequency in Hz to a clock period in femtoseconds.
441 mTimerPeriod
= DivU64x64Remainder (1000000000000000ULL, Frequency
, NULL
);
443 CpuMpServicesInit (&MaxCpu
);
445 CpuUpdateSmbios (MaxCpu
);
448 Status
= gBS
->CreateEventEx (
451 IdleLoopEventCallback
,
456 ASSERT_EFI_ERROR (Status
);
459 Status
= gBS
->InstallMultipleProtocolInterfaces (
460 &mCpuTemplate
.Handle
,
461 &gEfiCpuArchProtocolGuid
, &mCpuTemplate
.Cpu
,
462 &gEfiCpuIo2ProtocolGuid
, &mCpuTemplate
.CpuIo
,
465 ASSERT_EFI_ERROR (Status
);