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