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