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