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