]> git.proxmox.com Git - mirror_edk2.git/blame - Nt32Pkg/CpuRuntimeDxe/Cpu.c
We enabled X64 native version NT32, and made it works on Windows 7 X64 OS.
[mirror_edk2.git] / Nt32Pkg / CpuRuntimeDxe / Cpu.c
CommitLineData
6ae81428 1/**@file\r
770bcbb6 2\r
f66a43b2 3Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>\r
8f2a5f80 4This program and the accompanying materials\r
770bcbb6 5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 Cpu.c\r
15\r
16Abstract:\r
17\r
18 NT Emulation Architectural Protocol Driver as defined in Tiano.\r
19 This CPU module abstracts the interrupt subsystem of a platform and\r
20 the CPU-specific setjump/long pair. Other services are not implemented\r
21 in this driver.\r
22\r
6ae81428 23**/\r
770bcbb6 24\r
770bcbb6 25\r
26#include "CpuDriver.h"\r
27\r
831ff057 28UINT64 mTimerPeriod;\r
b397fbbb
A
29\r
30CPU_ARCH_PROTOCOL_PRIVATE mCpuTemplate = {\r
31 CPU_ARCH_PROT_PRIVATE_SIGNATURE,\r
32 NULL,\r
33 {\r
34 WinNtFlushCpuDataCache,\r
35 WinNtEnableInterrupt,\r
36 WinNtDisableInterrupt,\r
37 WinNtGetInterruptState,\r
38 WinNtInit,\r
39 WinNtRegisterInterruptHandler,\r
40 WinNtGetTimerValue,\r
41 WinNtSetMemoryAttributes,\r
831ff057 42 1,\r
b397fbbb
A
43 4\r
44 },\r
45 {\r
46 CpuMemoryServiceRead,\r
47 CpuMemoryServiceWrite,\r
48 CpuIoServiceRead,\r
49 CpuIoServiceWrite\r
50 },\r
51 0,\r
52 TRUE\r
53};\r
54\r
770bcbb6 55#define EFI_CPU_DATA_MAXIMUM_LENGTH 0x100\r
56\r
770bcbb6 57\r
770bcbb6 58\r
770bcbb6 59//\r
60// Service routines for the driver\r
61//\r
770bcbb6 62EFI_STATUS\r
63EFIAPI\r
64WinNtFlushCpuDataCache (\r
65 IN EFI_CPU_ARCH_PROTOCOL *This,\r
66 IN EFI_PHYSICAL_ADDRESS Start,\r
67 IN UINT64 Length,\r
68 IN EFI_CPU_FLUSH_TYPE FlushType\r
69 )\r
70/*++\r
71\r
72Routine Description:\r
73\r
74 This routine would provide support for flushing the CPU data cache.\r
75 In the case of NT emulation environment, this flushing is not necessary and\r
76 is thus not implemented.\r
77\r
78Arguments:\r
79\r
80 Pointer to CPU Architectural Protocol interface\r
81 Start adddress in memory to flush\r
82 Length of memory to flush\r
83 Flush type\r
84\r
85Returns:\r
86\r
87 Status\r
88 EFI_SUCCESS\r
89\r
90--*/\r
91// TODO: This - add argument and description to function comment\r
92// TODO: FlushType - add argument and description to function comment\r
93// TODO: EFI_UNSUPPORTED - add return value to function comment\r
94{\r
95 if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {\r
96 //\r
97 // Only WB flush is supported. We actually need do nothing on NT emulator\r
98 // environment. Classify this to follow EFI spec\r
99 //\r
100 return EFI_SUCCESS;\r
101 }\r
102 //\r
103 // Other flush types are not supported by NT emulator\r
104 //\r
105 return EFI_UNSUPPORTED;\r
106}\r
107\r
b397fbbb 108\r
770bcbb6 109EFI_STATUS\r
110EFIAPI\r
111WinNtEnableInterrupt (\r
112 IN EFI_CPU_ARCH_PROTOCOL *This\r
113 )\r
114/*++\r
115\r
116Routine Description:\r
117\r
118 This routine provides support for emulation of the interrupt enable of the\r
119 the system. For our purposes, CPU enable is just a BOOLEAN that the Timer\r
120 Architectural Protocol observes in order to defer behaviour while in its\r
121 emulated interrupt, or timer tick.\r
122\r
123Arguments:\r
124\r
125 Pointer to CPU Architectural Protocol interface\r
126\r
127Returns:\r
128\r
129 Status\r
130 EFI_SUCCESS\r
131\r
132--*/\r
133// TODO: This - add argument and description to function comment\r
134{\r
135 CPU_ARCH_PROTOCOL_PRIVATE *Private;\r
136\r
137 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);\r
138 Private->InterruptState = TRUE;\r
139 return EFI_SUCCESS;\r
140}\r
141\r
b397fbbb 142\r
770bcbb6 143EFI_STATUS\r
144EFIAPI\r
145WinNtDisableInterrupt (\r
146 IN EFI_CPU_ARCH_PROTOCOL *This\r
147 )\r
148/*++\r
149\r
150Routine Description:\r
151\r
152 This routine provides support for emulation of the interrupt disable of the\r
153 the system. For our purposes, CPU enable is just a BOOLEAN that the Timer\r
154 Architectural Protocol observes in order to defer behaviour while in its\r
155 emulated interrupt, or timer tick.\r
156\r
157Arguments:\r
158\r
159 Pointer to CPU Architectural Protocol interface\r
160\r
161Returns:\r
162\r
163 Status\r
164 EFI_SUCCESS\r
165\r
166--*/\r
167// TODO: This - add argument and description to function comment\r
168{\r
169 CPU_ARCH_PROTOCOL_PRIVATE *Private;\r
170\r
171 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);\r
172 Private->InterruptState = FALSE;\r
173 return EFI_SUCCESS;\r
174}\r
175\r
b397fbbb 176\r
770bcbb6 177EFI_STATUS\r
178EFIAPI\r
179WinNtGetInterruptState (\r
180 IN EFI_CPU_ARCH_PROTOCOL *This,\r
181 OUT BOOLEAN *State\r
182 )\r
183/*++\r
184\r
185Routine Description:\r
186\r
187 This routine provides support for emulation of the interrupt disable of the\r
188 the system. For our purposes, CPU enable is just a BOOLEAN that the Timer\r
189 Architectural Protocol observes in order to defer behaviour while in its\r
190 emulated interrupt, or timer tick.\r
191\r
192Arguments:\r
193\r
194 Pointer to CPU Architectural Protocol interface\r
195\r
196Returns:\r
197\r
198 Status\r
199 EFI_SUCCESS\r
200\r
201--*/\r
202// TODO: This - add argument and description to function comment\r
203// TODO: State - add argument and description to function comment\r
204// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
205{\r
206 CPU_ARCH_PROTOCOL_PRIVATE *Private;\r
207\r
208 if (State == NULL) {\r
209 return EFI_INVALID_PARAMETER;\r
210 }\r
211\r
212 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);\r
213 *State = Private->InterruptState;\r
214 return EFI_SUCCESS;\r
215}\r
216\r
b397fbbb 217\r
770bcbb6 218EFI_STATUS\r
219EFIAPI\r
220WinNtInit (\r
221 IN EFI_CPU_ARCH_PROTOCOL *This,\r
222 IN EFI_CPU_INIT_TYPE InitType\r
223 )\r
224/*++\r
225\r
226Routine Description:\r
227\r
228 This routine would support generation of a CPU INIT. At\r
229 present, this code does not provide emulation.\r
230\r
231Arguments:\r
232\r
233 Pointer to CPU Architectural Protocol interface\r
234 INIT Type\r
235\r
236Returns:\r
237\r
238 Status\r
239 EFI_UNSUPPORTED - not yet implemented\r
240\r
241--*/\r
242// TODO: This - add argument and description to function comment\r
243// TODO: InitType - add argument and description to function comment\r
244{\r
770bcbb6 245 return EFI_UNSUPPORTED;\r
246}\r
247\r
b397fbbb 248\r
770bcbb6 249EFI_STATUS\r
250EFIAPI\r
251WinNtRegisterInterruptHandler (\r
252 IN EFI_CPU_ARCH_PROTOCOL *This,\r
253 IN EFI_EXCEPTION_TYPE InterruptType,\r
254 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler\r
255 )\r
256/*++\r
257\r
258Routine Description:\r
259\r
260 This routine would support registration of an interrupt handler. At\r
261 present, this code does not provide emulation.\r
262\r
263Arguments:\r
264\r
265 Pointer to CPU Architectural Protocol interface\r
266 Pointer to interrupt handlers\r
267 Interrupt type\r
268\r
269Returns:\r
270\r
271 Status\r
272 EFI_UNSUPPORTED - not yet implemented\r
273\r
274--*/\r
275// TODO: This - add argument and description to function comment\r
276// TODO: InterruptType - add argument and description to function comment\r
277// TODO: InterruptHandler - add argument and description to function comment\r
278{\r
770bcbb6 279\r
280 //\r
281 // Do parameter checking for EFI spec conformance\r
282 //\r
283 if (InterruptType < 0 || InterruptType > 0xff) {\r
284 return EFI_UNSUPPORTED;\r
285 }\r
286 //\r
287 // Do nothing for Nt32 emulation\r
288 //\r
770bcbb6 289 return EFI_UNSUPPORTED;\r
290}\r
291\r
b397fbbb 292\r
770bcbb6 293EFI_STATUS\r
294EFIAPI\r
295WinNtGetTimerValue (\r
296 IN EFI_CPU_ARCH_PROTOCOL *This,\r
297 IN UINT32 TimerIndex,\r
298 OUT UINT64 *TimerValue,\r
299 OUT UINT64 *TimerPeriod OPTIONAL\r
300 )\r
301/*++\r
302\r
303Routine Description:\r
304\r
305 This routine would support querying of an on-CPU timer. At present,\r
306 this code does not provide timer emulation.\r
307\r
308Arguments:\r
309\r
310 This - Pointer to CPU Architectural Protocol interface\r
311 TimerIndex - Index of given CPU timer\r
312 TimerValue - Output of the timer\r
313 TimerPeriod - Output of the timer period\r
314\r
315Returns:\r
316\r
317 EFI_UNSUPPORTED - not yet implemented\r
318 EFI_INVALID_PARAMETER - TimeValue is NULL\r
319\r
320--*/\r
321{\r
322 if (TimerValue == NULL) {\r
323 return EFI_INVALID_PARAMETER;\r
324 }\r
831ff057 325 \r
326 if (TimerIndex != 0) {\r
327 return EFI_INVALID_PARAMETER;\r
328 }\r
329 \r
1b658802 330 gWinNt->QueryPerformanceCounter ((LARGE_INTEGER *)TimerValue);\r
831ff057 331 \r
332 if (TimerPeriod != NULL) {\r
333 *TimerPeriod = mTimerPeriod;\r
334 }\r
335 \r
336 return EFI_SUCCESS;\r
770bcbb6 337}\r
338\r
b397fbbb 339\r
770bcbb6 340EFI_STATUS\r
341EFIAPI\r
342WinNtSetMemoryAttributes (\r
343 IN EFI_CPU_ARCH_PROTOCOL *This,\r
344 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
345 IN UINT64 Length,\r
346 IN UINT64 Attributes\r
347 )\r
348/*++\r
349\r
350Routine Description:\r
351\r
352 This routine would support querying of an on-CPU timer. At present,\r
353 this code does not provide timer emulation.\r
354\r
355Arguments:\r
356\r
357 Pointer to CPU Architectural Protocol interface\r
358 Start address of memory region\r
359 The size in bytes of the memory region\r
360 The bit mask of attributes to set for the memory region\r
361\r
362Returns:\r
363\r
364 Status\r
365 EFI_UNSUPPORTED - not yet implemented\r
366\r
367--*/\r
368// TODO: This - add argument and description to function comment\r
369// TODO: BaseAddress - add argument and description to function comment\r
370// TODO: Length - add argument and description to function comment\r
371// TODO: Attributes - add argument and description to function comment\r
372// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
373{\r
770bcbb6 374 //\r
375 // Check for invalid parameter for Spec conformance\r
376 //\r
377 if (Length == 0) {\r
378 return EFI_INVALID_PARAMETER;\r
379 }\r
380\r
381 //\r
382 // Do nothing for Nt32 emulation\r
383 //\r
770bcbb6 384 return EFI_UNSUPPORTED;\r
385}\r
386\r
387\r
1fdd39d3 388\r
389/**\r
390 Logs SMBIOS record.\r
391\r
392 @param Smbios Pointer to SMBIOS protocol instance.\r
393 @param Buffer Pointer to the data buffer.\r
394\r
395**/\r
396VOID\r
397LogSmbiosData (\r
398 IN EFI_SMBIOS_PROTOCOL *Smbios,\r
399 IN UINT8 *Buffer\r
400 )\r
401{\r
402 EFI_STATUS Status;\r
403 EFI_SMBIOS_HANDLE SmbiosHandle;\r
404 \r
7ee85aa2 405 SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;\r
1fdd39d3 406 Status = Smbios->Add (\r
407 Smbios,\r
408 NULL,\r
409 &SmbiosHandle,\r
410 (EFI_SMBIOS_TABLE_HEADER*)Buffer\r
411 );\r
412 ASSERT_EFI_ERROR (Status);\r
413}\r
414\r
415\r
770bcbb6 416VOID\r
1fdd39d3 417CpuUpdateSmbios (\r
b397fbbb 418 VOID\r
770bcbb6 419 )\r
420/*++\r
421\r
422Routine Description:\r
1fdd39d3 423 This function will log processor version and frequency data to Smbios.\r
770bcbb6 424\r
425Arguments:\r
426 Event - Event whose notification function is being invoked.\r
427 Context - Pointer to the notification function's context.\r
428\r
429Returns:\r
430 None.\r
431\r
432--*/\r
433{\r
434 EFI_STATUS Status;\r
770bcbb6 435 UINT32 TotalSize;\r
1fdd39d3 436 EFI_SMBIOS_PROTOCOL *Smbios;\r
5fd5fcd3 437 EFI_HII_HANDLE HiiHandle;\r
1fdd39d3 438 STRING_REF Token;\r
439 UINTN CpuVerStrLen;\r
440 EFI_STRING CpuVerStr;\r
441 SMBIOS_TABLE_TYPE4 *SmbiosRecord;\r
442 CHAR8 *OptionalStrStart;\r
770bcbb6 443\r
444 //\r
1fdd39d3 445 // Locate Smbios protocol.\r
770bcbb6 446 //\r
1fdd39d3 447 Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **)&Smbios);\r
448 \r
770bcbb6 449 if (EFI_ERROR (Status)) {\r
b397fbbb 450 return;\r
770bcbb6 451 }\r
b397fbbb 452\r
b397fbbb
A
453 //\r
454 // Initialize strings to HII database\r
455 //\r
cb7d01c0 456 HiiHandle = HiiAddPackages (\r
c2bd20a5 457 &gEfiCallerIdGuid,\r
cb7d01c0 458 NULL,\r
459 CpuStrings,\r
460 NULL\r
461 );\r
462 ASSERT (HiiHandle != NULL);\r
b397fbbb 463\r
1fdd39d3 464 Token = STRING_TOKEN (STR_PROCESSOR_VERSION);\r
465 CpuVerStr = HiiGetPackageString(&gEfiCallerIdGuid, Token, NULL);\r
466 CpuVerStrLen = StrLen(CpuVerStr);\r
467 ASSERT (CpuVerStrLen <= SMBIOS_STRING_MAX_LENGTH);\r
b397fbbb 468\r
b397fbbb 469\r
f66a43b2 470 TotalSize = (UINT32)(sizeof(SMBIOS_TABLE_TYPE4) + CpuVerStrLen + 1 + 1);\r
1fdd39d3 471 SmbiosRecord = AllocatePool(TotalSize);\r
472 ZeroMem(SmbiosRecord, TotalSize);\r
b397fbbb 473\r
1fdd39d3 474 SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION;\r
475 SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE4);\r
476 //\r
477 // Make handle chosen by smbios protocol.add automatically.\r
478 //\r
479 SmbiosRecord->Hdr.Handle = 0; \r
480 //\r
481 // Processor version is the 1st string.\r
482 //\r
483 SmbiosRecord->ProcessorVersion = 1;\r
b397fbbb 484 //\r
e0f06862 485 // Store CPU frequency data record to data hub - It's an emulator so make up a value\r
b397fbbb 486 //\r
1fdd39d3 487 SmbiosRecord->CurrentSpeed = 1234;\r
488\r
489 OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);\r
490 UnicodeStrToAsciiStr(CpuVerStr, OptionalStrStart);\r
491\r
492 //\r
493 // Now we have got the full smbios record, call smbios protocol to add this record.\r
494 //\r
495 LogSmbiosData(Smbios, (UINT8 *) SmbiosRecord);\r
496 FreePool (SmbiosRecord);\r
497\r
b397fbbb
A
498}\r
499\r
500\r
501\r
502EFI_STATUS\r
503EFIAPI\r
504InitializeCpu (\r
505 IN EFI_HANDLE ImageHandle,\r
506 IN EFI_SYSTEM_TABLE *SystemTable\r
507 )\r
508/*++\r
509\r
510Routine Description:\r
511\r
512 Initialize the state information for the CPU Architectural Protocol\r
513\r
514Arguments:\r
515\r
516 ImageHandle of the loaded driver\r
517 Pointer to the System Table\r
518\r
519Returns:\r
520\r
521 Status\r
522\r
523 EFI_SUCCESS - protocol instance can be published\r
524 EFI_OUT_OF_RESOURCES - cannot allocate protocol data structure\r
525 EFI_DEVICE_ERROR - cannot create the thread\r
526\r
527--*/\r
528{\r
831ff057 529 EFI_STATUS Status;\r
530 UINT64 Frequency;\r
b397fbbb 531\r
831ff057 532 //\r
533 // Retrieve the frequency of the performance counter in Hz.\r
534 // \r
1b658802 535 gWinNt->QueryPerformanceFrequency ((LARGE_INTEGER *)&Frequency);\r
831ff057 536 \r
537 //\r
538 // Convert frequency in Hz to a clock period in femtoseconds.\r
539 //\r
540 mTimerPeriod = DivU64x64Remainder (1000000000000000, Frequency, NULL);\r
541 \r
1fdd39d3 542 CpuUpdateSmbios ();\r
b397fbbb
A
543\r
544 Status = gBS->InstallMultipleProtocolInterfaces (\r
545 &mCpuTemplate.Handle,\r
546 &gEfiCpuArchProtocolGuid, &mCpuTemplate.Cpu,\r
b8d5cb49 547 &gEfiCpuIo2ProtocolGuid, &mCpuTemplate.CpuIo,\r
b397fbbb
A
548 NULL\r
549 );\r
550 ASSERT_EFI_ERROR (Status);\r
551\r
552 return Status;\r
770bcbb6 553}\r