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 LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER
*)&mCpuSmbiosType4
, mCpuSmbiosType4Strings
);
247 // Service routines for the driver
251 EmuFlushCpuDataCache (
252 IN EFI_CPU_ARCH_PROTOCOL
*This
,
253 IN EFI_PHYSICAL_ADDRESS Start
,
255 IN EFI_CPU_FLUSH_TYPE FlushType
258 if (FlushType
== EfiCpuFlushTypeWriteBackInvalidate
) {
260 // Only WB flush is supported. We actually need do nothing on Emu emulator
261 // environment. Classify this to follow EFI spec
266 // Other flush types are not supported by Emu emulator
268 return EFI_UNSUPPORTED
;
274 IN EFI_CPU_ARCH_PROTOCOL
*This
277 CPU_ARCH_PROTOCOL_PRIVATE
*Private
;
279 Private
= CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This
);
280 Private
->InterruptState
= TRUE
;
281 gEmuThunk
->EnableInterrupt ();
287 EmuDisableInterrupt (
288 IN EFI_CPU_ARCH_PROTOCOL
*This
291 CPU_ARCH_PROTOCOL_PRIVATE
*Private
;
293 Private
= CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This
);
294 Private
->InterruptState
= FALSE
;
295 gEmuThunk
->DisableInterrupt ();
301 EmuGetInterruptState (
302 IN EFI_CPU_ARCH_PROTOCOL
*This
,
306 CPU_ARCH_PROTOCOL_PRIVATE
*Private
;
309 return EFI_INVALID_PARAMETER
;
312 Private
= CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This
);
313 *State
= Private
->InterruptState
;
320 IN EFI_CPU_ARCH_PROTOCOL
*This
,
321 IN EFI_CPU_INIT_TYPE InitType
324 return EFI_UNSUPPORTED
;
329 EmuRegisterInterruptHandler (
330 IN EFI_CPU_ARCH_PROTOCOL
*This
,
331 IN EFI_EXCEPTION_TYPE InterruptType
,
332 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
336 // Do parameter checking for EFI spec conformance
338 if (InterruptType
< 0 || InterruptType
> 0xff) {
339 return EFI_UNSUPPORTED
;
342 // Do nothing for Emu emulation
344 return EFI_UNSUPPORTED
;
350 IN EFI_CPU_ARCH_PROTOCOL
*This
,
351 IN UINT32 TimerIndex
,
352 OUT UINT64
*TimerValue
,
353 OUT UINT64
*TimerPeriod OPTIONAL
356 if (TimerValue
== NULL
) {
357 return EFI_INVALID_PARAMETER
;
360 if (TimerIndex
!= 0) {
361 return EFI_INVALID_PARAMETER
;
364 *TimerValue
= gEmuThunk
->QueryPerformanceCounter ();
366 if (TimerPeriod
!= NULL
) {
367 *TimerPeriod
= mTimerPeriod
;
376 EmuSetMemoryAttributes (
377 IN EFI_CPU_ARCH_PROTOCOL
*This
,
378 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
384 // Check for invalid parameter for Spec conformance
387 return EFI_INVALID_PARAMETER
;
391 // Do nothing for Nt32 emulation
393 return EFI_UNSUPPORTED
;
400 Callback function for idle events.
402 @param Event Event whose notification function is being invoked.
403 @param Context The pointer to the notification function's context,
404 which is implementation-dependent.
409 IdleLoopEventCallback (
414 gEmuThunk
->CpuSleep ();
421 IN EFI_HANDLE ImageHandle
,
422 IN EFI_SYSTEM_TABLE
*SystemTable
427 EFI_EVENT IdleLoopEvent
;
431 // Retrieve the frequency of the performance counter in Hz.
433 Frequency
= gEmuThunk
->QueryPerformanceFrequency ();
436 // Convert frequency in Hz to a clock period in femtoseconds.
438 mTimerPeriod
= DivU64x64Remainder (1000000000000000ULL, Frequency
, NULL
);
440 CpuMpServicesInit (&MaxCpu
);
442 CpuUpdateSmbios (MaxCpu
);
445 Status
= gBS
->CreateEventEx (
448 IdleLoopEventCallback
,
453 ASSERT_EFI_ERROR (Status
);
456 Status
= gBS
->InstallMultipleProtocolInterfaces (
457 &mCpuTemplate
.Handle
,
458 &gEfiCpuArchProtocolGuid
, &mCpuTemplate
.Cpu
,
459 &gEfiCpuIo2ProtocolGuid
, &mCpuTemplate
.CpuIo
,
462 ASSERT_EFI_ERROR (Status
);