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