]> git.proxmox.com Git - mirror_edk2.git/blob - UnixPkg/CpuRuntimeDxe/Cpu.c
dc25d4d8124f10b0f40d0673fbc53af066105c32
[mirror_edk2.git] / UnixPkg / CpuRuntimeDxe / Cpu.c
1 /*++
2
3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. 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 Unix 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 #include <FrameworkDxe.h>
25 #include <Protocol/Cpu.h>
26 #include <Protocol/DataHub.h>
27 #include <Guid/DataHubRecords.h>
28 #include <Protocol/CpuIo.h>
29 #include <Protocol/FrameworkHii.h>
30
31 #include <Library/BaseLib.h>
32 #include <Library/DebugLib.h>
33 #include <Library/HiiLib.h>
34 #include <Library/UefiLib.h>
35 #include <Library/UefiDriverEntryPoint.h>
36 #include <Library/BaseMemoryLib.h>
37 #include <Library/MemoryAllocationLib.h>
38 #include <Library/UefiBootServicesTableLib.h>
39 #include "CpuDriver.h"
40 #include "UnixDxe.h"
41 #include <Protocol/UnixIo.h>
42
43 #define EFI_CPU_DATA_MAXIMUM_LENGTH 0x100
44
45 CPU_ARCH_PROTOCOL_PRIVATE mCpuTemplate = {
46 CPU_ARCH_PROT_PRIVATE_SIGNATURE,
47 NULL,
48 {
49 UnixFlushCpuDataCache,
50 UnixEnableInterrupt,
51 UnixDisableInterrupt,
52 UnixGetInterruptState,
53 UnixInit,
54 UnixRegisterInterruptHandler,
55 UnixGetTimerValue,
56 UnixSetMemoryAttributes,
57 0,
58 4
59 },
60 {
61 CpuMemoryServiceRead,
62 CpuMemoryServiceWrite,
63 CpuIoServiceRead,
64 CpuIoServiceWrite
65 },
66 0,
67 TRUE
68 };
69
70 typedef union {
71 EFI_CPU_DATA_RECORD *DataRecord;
72 UINT8 *Raw;
73 } EFI_CPU_DATA_RECORD_BUFFER;
74
75 EFI_SUBCLASS_TYPE1_HEADER mCpuDataRecordHeader = {
76 EFI_PROCESSOR_SUBCLASS_VERSION, // Version
77 sizeof (EFI_SUBCLASS_TYPE1_HEADER), // Header Size
78 0, // Instance, Initialize later
79 EFI_SUBCLASS_INSTANCE_NON_APPLICABLE, // SubInstance
80 0 // RecordType, Initialize later
81 };
82
83 //
84 // Service routines for the driver
85 //
86 EFI_STATUS
87 EFIAPI
88 UnixFlushCpuDataCache (
89 IN EFI_CPU_ARCH_PROTOCOL *This,
90 IN EFI_PHYSICAL_ADDRESS Start,
91 IN UINT64 Length,
92 IN EFI_CPU_FLUSH_TYPE FlushType
93 )
94 /*++
95
96 Routine Description:
97
98 This routine would provide support for flushing the CPU data cache.
99 In the case of UNIX emulation environment, this flushing is not necessary and
100 is thus not implemented.
101
102 Arguments:
103
104 Pointer to CPU Architectural Protocol interface
105 Start adddress in memory to flush
106 Length of memory to flush
107 Flush type
108
109 Returns:
110
111 Status
112 EFI_SUCCESS
113
114 --*/
115 // TODO: This - add argument and description to function comment
116 // TODO: FlushType - add argument and description to function comment
117 // TODO: EFI_UNSUPPORTED - add return value to function comment
118 {
119 if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {
120 //
121 // Only WB flush is supported. We actually need do nothing on UNIX emulator
122 // environment. Classify this to follow EFI spec
123 //
124 return EFI_SUCCESS;
125 }
126 //
127 // Other flush types are not supported by UNIX emulator
128 //
129 return EFI_UNSUPPORTED;
130 }
131
132 EFI_STATUS
133 EFIAPI
134 UnixEnableInterrupt (
135 IN EFI_CPU_ARCH_PROTOCOL *This
136 )
137 /*++
138
139 Routine Description:
140
141 This routine provides support for emulation of the interrupt enable of the
142 the system. For our purposes, CPU enable is just a BOOLEAN that the Timer
143 Architectural Protocol observes in order to defer behaviour while in its
144 emulated interrupt, or timer tick.
145
146 Arguments:
147
148 Pointer to CPU Architectural Protocol interface
149
150 Returns:
151
152 Status
153 EFI_SUCCESS
154
155 --*/
156 // TODO: This - add argument and description to function comment
157 {
158 CPU_ARCH_PROTOCOL_PRIVATE *Private;
159
160 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
161 Private->InterruptState = TRUE;
162 return EFI_SUCCESS;
163 }
164
165 EFI_STATUS
166 EFIAPI
167 UnixDisableInterrupt (
168 IN EFI_CPU_ARCH_PROTOCOL *This
169 )
170 /*++
171
172 Routine Description:
173
174 This routine provides support for emulation of the interrupt disable of the
175 the system. For our purposes, CPU enable is just a BOOLEAN that the Timer
176 Architectural Protocol observes in order to defer behaviour while in its
177 emulated interrupt, or timer tick.
178
179 Arguments:
180
181 Pointer to CPU Architectural Protocol interface
182
183 Returns:
184
185 Status
186 EFI_SUCCESS
187
188 --*/
189 // TODO: This - add argument and description to function comment
190 {
191 CPU_ARCH_PROTOCOL_PRIVATE *Private;
192
193 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
194 Private->InterruptState = FALSE;
195 return EFI_SUCCESS;
196 }
197
198 EFI_STATUS
199 EFIAPI
200 UnixGetInterruptState (
201 IN EFI_CPU_ARCH_PROTOCOL *This,
202 OUT BOOLEAN *State
203 )
204 /*++
205
206 Routine Description:
207
208 This routine provides support for emulation of the interrupt disable of the
209 the system. For our purposes, CPU enable is just a BOOLEAN that the Timer
210 Architectural Protocol observes in order to defer behaviour while in its
211 emulated interrupt, or timer tick.
212
213 Arguments:
214
215 Pointer to CPU Architectural Protocol interface
216
217 Returns:
218
219 Status
220 EFI_SUCCESS
221
222 --*/
223 // TODO: This - add argument and description to function comment
224 // TODO: State - add argument and description to function comment
225 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
226 {
227 CPU_ARCH_PROTOCOL_PRIVATE *Private;
228
229 if (State == NULL) {
230 return EFI_INVALID_PARAMETER;
231 }
232
233 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
234 *State = Private->InterruptState;
235 return EFI_SUCCESS;
236 }
237
238 EFI_STATUS
239 EFIAPI
240 UnixInit (
241 IN EFI_CPU_ARCH_PROTOCOL *This,
242 IN EFI_CPU_INIT_TYPE InitType
243 )
244 /*++
245
246 Routine Description:
247
248 This routine would support generation of a CPU INIT. At
249 present, this code does not provide emulation.
250
251 Arguments:
252
253 Pointer to CPU Architectural Protocol interface
254 INIT Type
255
256 Returns:
257
258 Status
259 EFI_UNSUPPORTED - not yet implemented
260
261 --*/
262 // TODO: This - add argument and description to function comment
263 // TODO: InitType - add argument and description to function comment
264 {
265 CPU_ARCH_PROTOCOL_PRIVATE *Private;
266
267 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
268 return EFI_UNSUPPORTED;
269 }
270
271 EFI_STATUS
272 EFIAPI
273 UnixRegisterInterruptHandler (
274 IN EFI_CPU_ARCH_PROTOCOL *This,
275 IN EFI_EXCEPTION_TYPE InterruptType,
276 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
277 )
278 /*++
279
280 Routine Description:
281
282 This routine would support registration of an interrupt handler. At
283 present, this code does not provide emulation.
284
285 Arguments:
286
287 Pointer to CPU Architectural Protocol interface
288 Pointer to interrupt handlers
289 Interrupt type
290
291 Returns:
292
293 Status
294 EFI_UNSUPPORTED - not yet implemented
295
296 --*/
297 // TODO: This - add argument and description to function comment
298 // TODO: InterruptType - add argument and description to function comment
299 // TODO: InterruptHandler - add argument and description to function comment
300 {
301 CPU_ARCH_PROTOCOL_PRIVATE *Private;
302
303 //
304 // Do parameter checking for EFI spec conformance
305 //
306 if (InterruptType < 0 || InterruptType > 0xff) {
307 return EFI_UNSUPPORTED;
308 }
309 //
310 // Do nothing for Nt32 emulation
311 //
312 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
313 return EFI_UNSUPPORTED;
314 }
315
316 EFI_STATUS
317 EFIAPI
318 UnixGetTimerValue (
319 IN EFI_CPU_ARCH_PROTOCOL *This,
320 IN UINT32 TimerIndex,
321 OUT UINT64 *TimerValue,
322 OUT UINT64 *TimerPeriod OPTIONAL
323 )
324 /*++
325
326 Routine Description:
327
328 This routine would support querying of an on-CPU timer. At present,
329 this code does not provide timer emulation.
330
331 Arguments:
332
333 This - Pointer to CPU Architectural Protocol interface
334 TimerIndex - Index of given CPU timer
335 TimerValue - Output of the timer
336 TimerPeriod - Output of the timer period
337
338 Returns:
339
340 EFI_UNSUPPORTED - not yet implemented
341 EFI_INVALID_PARAMETER - TimeValue is NULL
342
343 --*/
344 {
345 if (TimerValue == NULL) {
346 return EFI_INVALID_PARAMETER;
347 }
348
349 //
350 // No timer supported
351 //
352 return EFI_UNSUPPORTED;
353 }
354
355 EFI_STATUS
356 EFIAPI
357 UnixSetMemoryAttributes (
358 IN EFI_CPU_ARCH_PROTOCOL *This,
359 IN EFI_PHYSICAL_ADDRESS BaseAddress,
360 IN UINT64 Length,
361 IN UINT64 Attributes
362 )
363 /*++
364
365 Routine Description:
366
367 This routine would support querying of an on-CPU timer. At present,
368 this code does not provide timer emulation.
369
370 Arguments:
371
372 Pointer to CPU Architectural Protocol interface
373 Start address of memory region
374 The size in bytes of the memory region
375 The bit mask of attributes to set for the memory region
376
377 Returns:
378
379 Status
380 EFI_UNSUPPORTED - not yet implemented
381
382 --*/
383 // TODO: This - add argument and description to function comment
384 // TODO: BaseAddress - add argument and description to function comment
385 // TODO: Length - add argument and description to function comment
386 // TODO: Attributes - add argument and description to function comment
387 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
388 {
389 CPU_ARCH_PROTOCOL_PRIVATE *Private;
390
391 //
392 // Check for invalid parameter for Spec conformance
393 //
394 if (Length == 0) {
395 return EFI_INVALID_PARAMETER;
396 }
397
398 //
399 // Do nothing for Nt32 emulation
400 //
401 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
402 return EFI_UNSUPPORTED;
403 }
404
405 VOID
406 CpuUpdateDataHub (
407 VOID
408 )
409 /*++
410
411 Routine Description:
412 This function will log processor version and frequency data to data hub.
413
414 Arguments:
415 Event - Event whose notification function is being invoked.
416 Context - Pointer to the notification function's context.
417
418 Returns:
419 None.
420
421 --*/
422 {
423 EFI_STATUS Status;
424 EFI_CPU_DATA_RECORD_BUFFER RecordBuffer;
425 UINT32 HeaderSize;
426 UINT32 TotalSize;
427 EFI_DATA_HUB_PROTOCOL *DataHub;
428 EFI_HII_HANDLE HiiHandle;
429
430 //
431 // Locate DataHub protocol.
432 //
433 Status = gBS->LocateProtocol (&gEfiDataHubProtocolGuid, NULL, &DataHub);
434 if (EFI_ERROR (Status)) {
435 return;
436 }
437
438 //
439 // Initialize data record header
440 //
441 mCpuDataRecordHeader.Instance = 1;
442 HeaderSize = sizeof (EFI_SUBCLASS_TYPE1_HEADER);
443
444 RecordBuffer.Raw = AllocatePool (HeaderSize + EFI_CPU_DATA_MAXIMUM_LENGTH);
445 if (RecordBuffer.Raw == NULL) {
446 return ;
447 }
448
449 //
450 // Initialize strings to HII database
451 //
452 HiiHandle = HiiAddPackages (
453 &gEfiCallerIdGuid,
454 NULL,
455 CpuStrings,
456 NULL
457 );
458 ASSERT (HiiHandle != NULL);
459
460 CopyMem (RecordBuffer.Raw, &mCpuDataRecordHeader, HeaderSize);
461
462
463 RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorVersionRecordType;
464 RecordBuffer.DataRecord->VariableRecord.ProcessorVersion = STRING_TOKEN (STR_INTEL_GENUINE_PROCESSOR);
465 TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_VERSION_DATA);
466
467 Status = DataHub->LogData (
468 DataHub,
469 &gEfiProcessorSubClassGuid,
470 &gEfiCallerIdGuid,
471 EFI_DATA_RECORD_CLASS_DATA,
472 RecordBuffer.Raw,
473 TotalSize
474 );
475
476 //
477 // Store CPU frequency data record to data hub - It's an emulator so make up a value
478 //
479 RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorCoreFrequencyRecordType;
480 RecordBuffer.DataRecord->VariableRecord.ProcessorCoreFrequency.Value = 1234;
481 RecordBuffer.DataRecord->VariableRecord.ProcessorCoreFrequency.Exponent = 6;
482 TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_CORE_FREQUENCY_DATA);
483
484 Status = DataHub->LogData (
485 DataHub,
486 &gEfiProcessorSubClassGuid,
487 &gEfiCallerIdGuid,
488 EFI_DATA_RECORD_CLASS_DATA,
489 RecordBuffer.Raw,
490 TotalSize
491 );
492
493 FreePool (RecordBuffer.Raw);
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 // TODO: SystemTable - add argument and description to function comment
523 {
524 EFI_STATUS Status;
525
526 CpuUpdateDataHub ();
527
528 Status = gBS->InstallMultipleProtocolInterfaces (
529 &mCpuTemplate.Handle,
530 &gEfiCpuArchProtocolGuid, &mCpuTemplate.Cpu,
531 &gEfiCpuIoProtocolGuid, &mCpuTemplate.CpuIo,
532 NULL
533 );
534 ASSERT_EFI_ERROR (Status);
535
536 DEBUG ((EFI_D_ERROR, "CPU Architectural Protocol Loaded\n"));
537
538 return Status;
539 }