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