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