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