]> git.proxmox.com Git - mirror_edk2.git/blob - EmulatorPkg/CpuRuntimeDxe/Cpu.c
InOsEmuPkg: Rename package to EmulatorPkg & Sec to Host
[mirror_edk2.git] / EmulatorPkg / CpuRuntimeDxe / Cpu.c
1 /*++ @file
2 Emu driver to produce CPU Architectural Protocol.
3
4 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
5 Portions copyright (c) 2011, 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
51
52 //
53 // Service routines for the driver
54 //
55 EFI_STATUS
56 EFIAPI
57 EmuFlushCpuDataCache (
58 IN EFI_CPU_ARCH_PROTOCOL *This,
59 IN EFI_PHYSICAL_ADDRESS Start,
60 IN UINT64 Length,
61 IN EFI_CPU_FLUSH_TYPE FlushType
62 )
63 {
64 if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {
65 //
66 // Only WB flush is supported. We actually need do nothing on Emu emulator
67 // environment. Classify this to follow EFI spec
68 //
69 return EFI_SUCCESS;
70 }
71 //
72 // Other flush types are not supported by Emu emulator
73 //
74 return EFI_UNSUPPORTED;
75 }
76
77 EFI_STATUS
78 EFIAPI
79 EmuEnableInterrupt (
80 IN EFI_CPU_ARCH_PROTOCOL *This
81 )
82 {
83 CPU_ARCH_PROTOCOL_PRIVATE *Private;
84
85 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
86 Private->InterruptState = TRUE;
87 gEmuThunk->EnableInterrupt ();
88 return EFI_SUCCESS;
89 }
90
91 EFI_STATUS
92 EFIAPI
93 EmuDisableInterrupt (
94 IN EFI_CPU_ARCH_PROTOCOL *This
95 )
96 {
97 CPU_ARCH_PROTOCOL_PRIVATE *Private;
98
99 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
100 Private->InterruptState = FALSE;
101 gEmuThunk->DisableInterrupt ();
102 return EFI_SUCCESS;
103 }
104
105 EFI_STATUS
106 EFIAPI
107 EmuGetInterruptState (
108 IN EFI_CPU_ARCH_PROTOCOL *This,
109 OUT BOOLEAN *State
110 )
111 {
112 CPU_ARCH_PROTOCOL_PRIVATE *Private;
113
114 if (State == NULL) {
115 return EFI_INVALID_PARAMETER;
116 }
117
118 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
119 *State = Private->InterruptState;
120 return EFI_SUCCESS;
121 }
122
123 EFI_STATUS
124 EFIAPI
125 EmuInit (
126 IN EFI_CPU_ARCH_PROTOCOL *This,
127 IN EFI_CPU_INIT_TYPE InitType
128 )
129 {
130 CPU_ARCH_PROTOCOL_PRIVATE *Private;
131
132 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
133 return EFI_UNSUPPORTED;
134 }
135
136 EFI_STATUS
137 EFIAPI
138 EmuRegisterInterruptHandler (
139 IN EFI_CPU_ARCH_PROTOCOL *This,
140 IN EFI_EXCEPTION_TYPE InterruptType,
141 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
142 )
143 {
144 CPU_ARCH_PROTOCOL_PRIVATE *Private;
145
146 //
147 // Do parameter checking for EFI spec conformance
148 //
149 if (InterruptType < 0 || InterruptType > 0xff) {
150 return EFI_UNSUPPORTED;
151 }
152 //
153 // Do nothing for Emu emulation
154 //
155 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
156 return EFI_UNSUPPORTED;
157 }
158
159 EFI_STATUS
160 EFIAPI
161 EmuGetTimerValue (
162 IN EFI_CPU_ARCH_PROTOCOL *This,
163 IN UINT32 TimerIndex,
164 OUT UINT64 *TimerValue,
165 OUT UINT64 *TimerPeriod OPTIONAL
166 )
167 {
168 if (TimerValue == NULL) {
169 return EFI_INVALID_PARAMETER;
170 }
171
172 if (TimerIndex != 0) {
173 return EFI_INVALID_PARAMETER;
174 }
175
176 *TimerValue = gEmuThunk->QueryPerformanceCounter ();
177
178 if (TimerPeriod != NULL) {
179 *TimerPeriod = mTimerPeriod;
180 }
181
182 return EFI_SUCCESS;
183 }
184
185
186 EFI_STATUS
187 EFIAPI
188 EmuSetMemoryAttributes (
189 IN EFI_CPU_ARCH_PROTOCOL *This,
190 IN EFI_PHYSICAL_ADDRESS BaseAddress,
191 IN UINT64 Length,
192 IN UINT64 Attributes
193 )
194 {
195 CPU_ARCH_PROTOCOL_PRIVATE *Private;
196
197 //
198 // Check for invalid parameter for Spec conformance
199 //
200 if (Length == 0) {
201 return EFI_INVALID_PARAMETER;
202 }
203
204 //
205 // Do nothing for Nt32 emulation
206 //
207 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
208 return EFI_UNSUPPORTED;
209 }
210
211
212
213 /**
214 Logs SMBIOS record.
215
216 @param Smbios Pointer to SMBIOS protocol instance.
217 @param Buffer Pointer to the data buffer.
218
219 **/
220 VOID
221 LogSmbiosData (
222 IN EFI_SMBIOS_PROTOCOL *Smbios,
223 IN UINT8 *Buffer
224 )
225 {
226 EFI_STATUS Status;
227 EFI_SMBIOS_HANDLE SmbiosHandle;
228
229 SmbiosHandle = 0;
230 Status = Smbios->Add (
231 Smbios,
232 NULL,
233 &SmbiosHandle,
234 (EFI_SMBIOS_TABLE_HEADER*)Buffer
235 );
236 ASSERT_EFI_ERROR (Status);
237 }
238
239 VOID
240 CpuUpdateSmbios (
241 VOID
242 )
243 {
244 EFI_STATUS Status;
245 UINT32 TotalSize;
246 EFI_SMBIOS_PROTOCOL *Smbios;
247 EFI_HII_HANDLE HiiHandle;
248 STRING_REF Token;
249 UINTN CpuVerStrLen;
250 EFI_STRING CpuVerStr;
251 SMBIOS_TABLE_TYPE4 *SmbiosRecord;
252 CHAR8 *OptionalStrStart;
253
254 //
255 // Locate Smbios protocol.
256 //
257 Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **)&Smbios);
258
259 if (EFI_ERROR (Status)) {
260 return;
261 }
262
263 //
264 // Initialize strings to HII database
265 //
266 HiiHandle = HiiAddPackages (
267 &gEfiCallerIdGuid,
268 NULL,
269 CpuStrings,
270 NULL
271 );
272 ASSERT (HiiHandle != NULL);
273
274 Token = STRING_TOKEN (STR_PROCESSOR_VERSION);
275 CpuVerStr = HiiGetPackageString(&gEfiCallerIdGuid, Token, NULL);
276 CpuVerStrLen = StrLen(CpuVerStr);
277 ASSERT (CpuVerStrLen <= SMBIOS_STRING_MAX_LENGTH);
278
279 TotalSize = sizeof(SMBIOS_TABLE_TYPE4) + CpuVerStrLen + 1 + 1;
280 SmbiosRecord = AllocatePool(TotalSize);
281 ZeroMem(SmbiosRecord, TotalSize);
282
283 SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION;
284 SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE4);
285 //
286 // Make handle chosen by smbios protocol.add automatically.
287 //
288 SmbiosRecord->Hdr.Handle = 0;
289 //
290 // Processor version is the 1st string.
291 //
292 SmbiosRecord->ProcessorVersion = 1;
293 //
294 // Store CPU frequency data record to data hub - It's an emulator so make up a value
295 //
296 SmbiosRecord->CurrentSpeed = 1234;
297
298 OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
299 UnicodeStrToAsciiStr(CpuVerStr, OptionalStrStart);
300
301 //
302 // Now we have got the full smbios record, call smbios protocol to add this record.
303 //
304 LogSmbiosData(Smbios, (UINT8 *) SmbiosRecord);
305 FreePool (SmbiosRecord);
306 }
307
308
309
310 /**
311 Callback function for idle events.
312
313 @param Event Event whose notification function is being invoked.
314 @param Context The pointer to the notification function's context,
315 which is implementation-dependent.
316
317 **/
318 VOID
319 EFIAPI
320 IdleLoopEventCallback (
321 IN EFI_EVENT Event,
322 IN VOID *Context
323 )
324 {
325 gEmuThunk->CpuSleep ();
326 }
327
328
329 EFI_STATUS
330 EFIAPI
331 InitializeCpu (
332 IN EFI_HANDLE ImageHandle,
333 IN EFI_SYSTEM_TABLE *SystemTable
334 )
335 {
336 EFI_STATUS Status;
337 UINT64 Frequency;
338 EFI_EVENT IdleLoopEvent;
339
340 //
341 // Retrieve the frequency of the performance counter in Hz.
342 //
343 Frequency = gEmuThunk->QueryPerformanceFrequency ();
344
345 //
346 // Convert frequency in Hz to a clock period in femtoseconds.
347 //
348 mTimerPeriod = DivU64x64Remainder (1000000000000000ULL, Frequency, NULL);
349
350 CpuUpdateSmbios ();
351
352 CpuMpServicesInit ();
353
354 Status = gBS->CreateEventEx (
355 EVT_NOTIFY_SIGNAL,
356 TPL_NOTIFY,
357 IdleLoopEventCallback,
358 NULL,
359 &gIdleLoopEventGuid,
360 &IdleLoopEvent
361 );
362 ASSERT_EFI_ERROR (Status);
363
364
365 Status = gBS->InstallMultipleProtocolInterfaces (
366 &mCpuTemplate.Handle,
367 &gEfiCpuArchProtocolGuid, &mCpuTemplate.Cpu,
368 &gEfiCpuIo2ProtocolGuid, &mCpuTemplate.CpuIo,
369 NULL
370 );
371 ASSERT_EFI_ERROR (Status);
372
373 return Status;
374 }