]> git.proxmox.com Git - mirror_edk2.git/blame - Nt32Pkg/CpuRuntimeDxe/Cpu.c
Add build rules for asl file, asm16 file.
[mirror_edk2.git] / Nt32Pkg / CpuRuntimeDxe / Cpu.c
CommitLineData
770bcbb6 1/*++\r
2\r
3Copyright (c) 2006 - 2007, 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 NT 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\r
770bcbb6 25\r
26#include "CpuDriver.h"\r
27\r
28#define EFI_CPU_DATA_MAXIMUM_LENGTH 0x100\r
29\r
30EFI_STATUS\r
31EFIAPI\r
32InitializeCpu (\r
33 IN EFI_HANDLE ImageHandle,\r
34 IN EFI_SYSTEM_TABLE *SystemTable\r
35 );\r
36\r
37VOID\r
38EFIAPI\r
39WinNtIoProtocolNotifyFunction (\r
40 IN EFI_EVENT Event,\r
41 IN VOID *Context\r
42 );\r
43\r
44typedef union {\r
45 EFI_CPU_DATA_RECORD *DataRecord;\r
46 UINT8 *Raw;\r
47} EFI_CPU_DATA_RECORD_BUFFER;\r
48\r
49EFI_SUBCLASS_TYPE1_HEADER mCpuDataRecordHeader = {\r
50 EFI_PROCESSOR_SUBCLASS_VERSION, // Version\r
51 sizeof (EFI_SUBCLASS_TYPE1_HEADER), // Header Size\r
52 0, // Instance, Initialize later\r
53 EFI_SUBCLASS_INSTANCE_NON_APPLICABLE, // SubInstance\r
54 0 // RecordType, Initialize later\r
55};\r
56\r
57//\r
58// Service routines for the driver\r
59//\r
60STATIC\r
61EFI_STATUS\r
62EFIAPI\r
63WinNtFlushCpuDataCache (\r
64 IN EFI_CPU_ARCH_PROTOCOL *This,\r
65 IN EFI_PHYSICAL_ADDRESS Start,\r
66 IN UINT64 Length,\r
67 IN EFI_CPU_FLUSH_TYPE FlushType\r
68 )\r
69/*++\r
70\r
71Routine Description:\r
72\r
73 This routine would provide support for flushing the CPU data cache.\r
74 In the case of NT emulation environment, this flushing is not necessary and\r
75 is thus not implemented.\r
76\r
77Arguments:\r
78\r
79 Pointer to CPU Architectural Protocol interface\r
80 Start adddress in memory to flush\r
81 Length of memory to flush\r
82 Flush type\r
83\r
84Returns:\r
85\r
86 Status\r
87 EFI_SUCCESS\r
88\r
89--*/\r
90// TODO: This - add argument and description to function comment\r
91// TODO: FlushType - add argument and description to function comment\r
92// TODO: EFI_UNSUPPORTED - add return value to function comment\r
93{\r
94 if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {\r
95 //\r
96 // Only WB flush is supported. We actually need do nothing on NT emulator\r
97 // environment. Classify this to follow EFI spec\r
98 //\r
99 return EFI_SUCCESS;\r
100 }\r
101 //\r
102 // Other flush types are not supported by NT emulator\r
103 //\r
104 return EFI_UNSUPPORTED;\r
105}\r
106\r
107STATIC\r
108EFI_STATUS\r
109EFIAPI\r
110WinNtEnableInterrupt (\r
111 IN EFI_CPU_ARCH_PROTOCOL *This\r
112 )\r
113/*++\r
114\r
115Routine Description:\r
116\r
117 This routine provides support for emulation of the interrupt enable of the\r
118 the system. For our purposes, CPU enable is just a BOOLEAN that the Timer\r
119 Architectural Protocol observes in order to defer behaviour while in its\r
120 emulated interrupt, or timer tick.\r
121\r
122Arguments:\r
123\r
124 Pointer to CPU Architectural Protocol interface\r
125\r
126Returns:\r
127\r
128 Status\r
129 EFI_SUCCESS\r
130\r
131--*/\r
132// TODO: This - add argument and description to function comment\r
133{\r
134 CPU_ARCH_PROTOCOL_PRIVATE *Private;\r
135\r
136 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);\r
137 Private->InterruptState = TRUE;\r
138 return EFI_SUCCESS;\r
139}\r
140\r
141STATIC\r
142EFI_STATUS\r
143EFIAPI\r
144WinNtDisableInterrupt (\r
145 IN EFI_CPU_ARCH_PROTOCOL *This\r
146 )\r
147/*++\r
148\r
149Routine Description:\r
150\r
151 This routine provides support for emulation of the interrupt disable of the\r
152 the system. For our purposes, CPU enable is just a BOOLEAN that the Timer\r
153 Architectural Protocol observes in order to defer behaviour while in its\r
154 emulated interrupt, or timer tick.\r
155\r
156Arguments:\r
157\r
158 Pointer to CPU Architectural Protocol interface\r
159\r
160Returns:\r
161\r
162 Status\r
163 EFI_SUCCESS\r
164\r
165--*/\r
166// TODO: This - add argument and description to function comment\r
167{\r
168 CPU_ARCH_PROTOCOL_PRIVATE *Private;\r
169\r
170 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);\r
171 Private->InterruptState = FALSE;\r
172 return EFI_SUCCESS;\r
173}\r
174\r
175STATIC\r
176EFI_STATUS\r
177EFIAPI\r
178WinNtGetInterruptState (\r
179 IN EFI_CPU_ARCH_PROTOCOL *This,\r
180 OUT BOOLEAN *State\r
181 )\r
182/*++\r
183\r
184Routine Description:\r
185\r
186 This routine provides support for emulation of the interrupt disable of the\r
187 the system. For our purposes, CPU enable is just a BOOLEAN that the Timer\r
188 Architectural Protocol observes in order to defer behaviour while in its\r
189 emulated interrupt, or timer tick.\r
190\r
191Arguments:\r
192\r
193 Pointer to CPU Architectural Protocol interface\r
194\r
195Returns:\r
196\r
197 Status\r
198 EFI_SUCCESS\r
199\r
200--*/\r
201// TODO: This - add argument and description to function comment\r
202// TODO: State - add argument and description to function comment\r
203// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
204{\r
205 CPU_ARCH_PROTOCOL_PRIVATE *Private;\r
206\r
207 if (State == NULL) {\r
208 return EFI_INVALID_PARAMETER;\r
209 }\r
210\r
211 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);\r
212 *State = Private->InterruptState;\r
213 return EFI_SUCCESS;\r
214}\r
215\r
216STATIC\r
217EFI_STATUS\r
218EFIAPI\r
219WinNtInit (\r
220 IN EFI_CPU_ARCH_PROTOCOL *This,\r
221 IN EFI_CPU_INIT_TYPE InitType\r
222 )\r
223/*++\r
224\r
225Routine Description:\r
226\r
227 This routine would support generation of a CPU INIT. At\r
228 present, this code does not provide emulation.\r
229\r
230Arguments:\r
231\r
232 Pointer to CPU Architectural Protocol interface\r
233 INIT Type\r
234\r
235Returns:\r
236\r
237 Status\r
238 EFI_UNSUPPORTED - not yet implemented\r
239\r
240--*/\r
241// TODO: This - add argument and description to function comment\r
242// TODO: InitType - add argument and description to function comment\r
243{\r
244 CPU_ARCH_PROTOCOL_PRIVATE *Private;\r
245\r
246 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);\r
247 return EFI_UNSUPPORTED;\r
248}\r
249\r
250STATIC\r
251EFI_STATUS\r
252EFIAPI\r
253WinNtRegisterInterruptHandler (\r
254 IN EFI_CPU_ARCH_PROTOCOL *This,\r
255 IN EFI_EXCEPTION_TYPE InterruptType,\r
256 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler\r
257 )\r
258/*++\r
259\r
260Routine Description:\r
261\r
262 This routine would support registration of an interrupt handler. At\r
263 present, this code does not provide emulation.\r
264\r
265Arguments:\r
266\r
267 Pointer to CPU Architectural Protocol interface\r
268 Pointer to interrupt handlers\r
269 Interrupt type\r
270\r
271Returns:\r
272\r
273 Status\r
274 EFI_UNSUPPORTED - not yet implemented\r
275\r
276--*/\r
277// TODO: This - add argument and description to function comment\r
278// TODO: InterruptType - add argument and description to function comment\r
279// TODO: InterruptHandler - add argument and description to function comment\r
280{\r
281 CPU_ARCH_PROTOCOL_PRIVATE *Private;\r
282\r
283 //\r
284 // Do parameter checking for EFI spec conformance\r
285 //\r
286 if (InterruptType < 0 || InterruptType > 0xff) {\r
287 return EFI_UNSUPPORTED;\r
288 }\r
289 //\r
290 // Do nothing for Nt32 emulation\r
291 //\r
292 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);\r
293 return EFI_UNSUPPORTED;\r
294}\r
295\r
296STATIC\r
297EFI_STATUS\r
298EFIAPI\r
299WinNtGetTimerValue (\r
300 IN EFI_CPU_ARCH_PROTOCOL *This,\r
301 IN UINT32 TimerIndex,\r
302 OUT UINT64 *TimerValue,\r
303 OUT UINT64 *TimerPeriod OPTIONAL\r
304 )\r
305/*++\r
306\r
307Routine Description:\r
308\r
309 This routine would support querying of an on-CPU timer. At present,\r
310 this code does not provide timer emulation.\r
311\r
312Arguments:\r
313\r
314 This - Pointer to CPU Architectural Protocol interface\r
315 TimerIndex - Index of given CPU timer\r
316 TimerValue - Output of the timer\r
317 TimerPeriod - Output of the timer period\r
318\r
319Returns:\r
320\r
321 EFI_UNSUPPORTED - not yet implemented\r
322 EFI_INVALID_PARAMETER - TimeValue is NULL\r
323\r
324--*/\r
325{\r
326 if (TimerValue == NULL) {\r
327 return EFI_INVALID_PARAMETER;\r
328 }\r
329\r
330 //\r
331 // No timer supported\r
332 //\r
333 return EFI_UNSUPPORTED;\r
334}\r
335\r
336STATIC\r
337EFI_STATUS\r
338EFIAPI\r
339WinNtSetMemoryAttributes (\r
340 IN EFI_CPU_ARCH_PROTOCOL *This,\r
341 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
342 IN UINT64 Length,\r
343 IN UINT64 Attributes\r
344 )\r
345/*++\r
346\r
347Routine Description:\r
348\r
349 This routine would support querying of an on-CPU timer. At present,\r
350 this code does not provide timer emulation.\r
351\r
352Arguments:\r
353\r
354 Pointer to CPU Architectural Protocol interface\r
355 Start address of memory region\r
356 The size in bytes of the memory region\r
357 The bit mask of attributes to set for the memory region\r
358\r
359Returns:\r
360\r
361 Status\r
362 EFI_UNSUPPORTED - not yet implemented\r
363\r
364--*/\r
365// TODO: This - add argument and description to function comment\r
366// TODO: BaseAddress - add argument and description to function comment\r
367// TODO: Length - add argument and description to function comment\r
368// TODO: Attributes - add argument and description to function comment\r
369// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
370{\r
371 CPU_ARCH_PROTOCOL_PRIVATE *Private;\r
372\r
373 //\r
374 // Check for invalid parameter for Spec conformance\r
375 //\r
376 if (Length == 0) {\r
377 return EFI_INVALID_PARAMETER;\r
378 }\r
379\r
380 //\r
381 // Do nothing for Nt32 emulation\r
382 //\r
383 Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);\r
384 return EFI_UNSUPPORTED;\r
385}\r
386\r
387\r
388EFI_STATUS\r
389EFIAPI\r
390InitializeCpu (\r
391 IN EFI_HANDLE ImageHandle,\r
392 IN EFI_SYSTEM_TABLE *SystemTable\r
393 )\r
394/*++\r
395\r
396Routine Description:\r
397\r
398 Initialize the state information for the CPU Architectural Protocol\r
399\r
400Arguments:\r
401\r
402 ImageHandle of the loaded driver\r
403 Pointer to the System Table\r
404\r
405Returns:\r
406\r
407 Status\r
408\r
409 EFI_SUCCESS - protocol instance can be published\r
410 EFI_OUT_OF_RESOURCES - cannot allocate protocol data structure\r
411 EFI_DEVICE_ERROR - cannot create the thread\r
412\r
413--*/\r
414// TODO: SystemTable - add argument and description to function comment\r
415{\r
416 EFI_STATUS Status;\r
417 EFI_EVENT Event;\r
418 CPU_ARCH_PROTOCOL_PRIVATE *Private;\r
419 VOID *Registration;\r
420\r
421 Private = AllocatePool (sizeof (CPU_ARCH_PROTOCOL_PRIVATE));\r
422 ASSERT (Private != NULL);\r
423\r
424 Private->Signature = CPU_ARCH_PROT_PRIVATE_SIGNATURE;\r
425 Private->Cpu.FlushDataCache = WinNtFlushCpuDataCache;\r
426 Private->Cpu.EnableInterrupt = WinNtEnableInterrupt;\r
427 Private->Cpu.DisableInterrupt = WinNtDisableInterrupt;\r
428 Private->Cpu.GetInterruptState = WinNtGetInterruptState;\r
429 Private->Cpu.Init = WinNtInit;\r
430 Private->Cpu.RegisterInterruptHandler = WinNtRegisterInterruptHandler;\r
431 Private->Cpu.GetTimerValue = WinNtGetTimerValue;\r
432 Private->Cpu.SetMemoryAttributes = WinNtSetMemoryAttributes;\r
433\r
434 Private->Cpu.NumberOfTimers = 0;\r
435 Private->Cpu.DmaBufferAlignment = 4;\r
436\r
437 Private->InterruptState = TRUE;\r
438\r
439 Private->CpuIo.Mem.Read = CpuMemoryServiceRead;\r
440 Private->CpuIo.Mem.Write = CpuMemoryServiceWrite;\r
441 Private->CpuIo.Io.Read = CpuIoServiceRead;\r
442 Private->CpuIo.Io.Write = CpuIoServiceWrite;\r
443\r
444\r
445 Private->Handle = NULL;\r
446 Status = gBS->InstallMultipleProtocolInterfaces (\r
447 &Private->Handle,\r
448 &gEfiCpuArchProtocolGuid, &Private->Cpu,\r
449 &gEfiCpuIoProtocolGuid, &Private->CpuIo,\r
450 NULL\r
451 );\r
452 ASSERT_EFI_ERROR (Status);\r
453\r
454 //\r
455 // Install notify function to store processor data to HII database and data hub.\r
456 //\r
457 Status = gBS->CreateEvent (\r
458 EVT_NOTIFY_SIGNAL,\r
459 TPL_CALLBACK,\r
460 WinNtIoProtocolNotifyFunction,\r
461 ImageHandle,\r
462 &Event\r
463 );\r
464 ASSERT (!EFI_ERROR (Status));\r
465\r
466 Status = gBS->RegisterProtocolNotify (\r
467 &gEfiWinNtIoProtocolGuid,\r
468 Event,\r
469 &Registration\r
470 );\r
471 ASSERT (!EFI_ERROR (Status));\r
472\r
473 //\r
474 // Should be at EFI_D_INFO, but lets us now things are running\r
475 //\r
476 DEBUG ((EFI_D_ERROR, "CPU Architectural Protocol Loaded\n"));\r
477\r
478\r
479\r
480 return Status;\r
481}\r
482\r
483UINTN\r
484Atoi (\r
485 CHAR16 *String\r
486 )\r
487/*++\r
488\r
489Routine Description:\r
490 Convert a unicode string to a UINTN\r
491\r
492Arguments:\r
493 String - Unicode string.\r
494\r
495Returns:\r
496 UINTN of the number represented by String.\r
497\r
498--*/\r
499{\r
500 UINTN Number;\r
501 CHAR16 *Str;\r
502\r
503 //\r
504 // skip preceeding white space\r
505 //\r
506 Str = String;\r
507 while ((*Str) && (*Str == ' ' || *Str == '"')) {\r
508 Str++;\r
509 }\r
510 //\r
511 // Convert ot a Number\r
512 //\r
513 Number = 0;\r
514 while (*Str != '\0') {\r
515 if ((*Str >= '0') && (*Str <= '9')) {\r
516 Number = (Number * 10) +*Str - '0';\r
517 } else {\r
518 break;\r
519 }\r
520\r
521 Str++;\r
522 }\r
523\r
524 return Number;\r
525}\r
526\r
527VOID\r
528EFIAPI\r
529WinNtIoProtocolNotifyFunction (\r
530 IN EFI_EVENT Event,\r
531 IN VOID *Context\r
532 )\r
533/*++\r
534\r
535Routine Description:\r
536 This function will log processor version and frequency data to data hub.\r
537\r
538Arguments:\r
539 Event - Event whose notification function is being invoked.\r
540 Context - Pointer to the notification function's context.\r
541\r
542Returns:\r
543 None.\r
544\r
545--*/\r
546{\r
547 EFI_STATUS Status;\r
548 EFI_CPU_DATA_RECORD_BUFFER RecordBuffer;\r
549 EFI_DATA_RECORD_HEADER *Record;\r
550 EFI_SUBCLASS_TYPE1_HEADER *DataHeader;\r
551 UINT32 HeaderSize;\r
552 UINT32 TotalSize;\r
553 UINTN HandleCount;\r
554 UINTN HandleIndex;\r
555 UINT64 MonotonicCount;\r
556 BOOLEAN RecordFound;\r
557 EFI_HANDLE *HandleBuffer;\r
558 EFI_WIN_NT_IO_PROTOCOL *WinNtIo;\r
559 EFI_DATA_HUB_PROTOCOL *DataHub;\r
560 EFI_HII_PROTOCOL *Hii;\r
561 EFI_HII_HANDLE StringHandle;\r
562 EFI_HII_PACKAGES *PackageList;\r
563 STRING_REF Token;\r
564\r
565 DataHub = NULL;\r
566 Token = 0;\r
567 MonotonicCount = 0;\r
568 RecordFound = FALSE;\r
569\r
570 //\r
571 // Retrieve the list of all handles from the handle database\r
572 //\r
573 Status = gBS->LocateHandleBuffer (\r
574 AllHandles,\r
575 &gEfiWinNtIoProtocolGuid,\r
576 NULL,\r
577 &HandleCount,\r
578 &HandleBuffer\r
579 );\r
580 if (EFI_ERROR (Status)) {\r
581 return ;\r
582 }\r
583 //\r
584 // Locate HII protocol\r
585 //\r
586 Status = gBS->LocateProtocol (&gEfiHiiProtocolGuid, NULL, &Hii);\r
587 if (EFI_ERROR (Status)) {\r
588 return ;\r
589 }\r
590 //\r
591 // Locate DataHub protocol.\r
592 //\r
593 Status = gBS->LocateProtocol (&gEfiDataHubProtocolGuid, NULL, &DataHub);\r
594 if (EFI_ERROR (Status)) {\r
595 return ;\r
596 }\r
597 //\r
598 // Initialize data record header\r
599 //\r
600 mCpuDataRecordHeader.Instance = 1;\r
601 HeaderSize = sizeof (EFI_SUBCLASS_TYPE1_HEADER);\r
602\r
603 RecordBuffer.Raw = AllocatePool (HeaderSize + EFI_CPU_DATA_MAXIMUM_LENGTH);\r
604 if (RecordBuffer.Raw == NULL) {\r
605 return ;\r
606 }\r
607\r
608 CopyMem (RecordBuffer.Raw, &mCpuDataRecordHeader, HeaderSize);\r
609\r
610 //\r
611 // Search the Handle array to find the CPU model and speed information\r
612 //\r
613 for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {\r
614 Status = gBS->OpenProtocol (\r
615 HandleBuffer[HandleIndex],\r
616 &gEfiWinNtIoProtocolGuid,\r
617 &WinNtIo,\r
618 Context,\r
619 NULL,\r
620 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
621 );\r
622 if (EFI_ERROR (Status)) {\r
623 continue;\r
624 }\r
625\r
626 if ((WinNtIo->WinNtThunk->Signature == EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE) &&\r
627 CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtCPUModelGuid)\r
628 ) {\r
629 //\r
630 // Check if this record has been stored in data hub\r
631 //\r
632 do {\r
633 Status = DataHub->GetNextRecord (DataHub, &MonotonicCount, NULL, &Record);\r
634 if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) {\r
635 DataHeader = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1);\r
636 if (CompareGuid (&Record->DataRecordGuid, &gEfiProcessorSubClassGuid) &&\r
637 (DataHeader->RecordType == ProcessorVersionRecordType)\r
638 ) {\r
639 RecordFound = TRUE;\r
640 }\r
641 }\r
642 } while (MonotonicCount != 0);\r
643\r
644 if (RecordFound) {\r
645 RecordFound = FALSE;\r
646 continue;\r
647 }\r
648 //\r
649 // Initialize strings to HII database\r
650 //\r
651 PackageList = PreparePackages (1, &gEfiProcessorProducerGuid, CpuStrings);\r
652\r
653 Status = Hii->NewPack (Hii, PackageList, &StringHandle);\r
654 ASSERT (!EFI_ERROR (Status));\r
655\r
656 FreePool (PackageList);\r
657\r
658 //\r
659 // Store processor version data record to data hub\r
660 //\r
661 Status = Hii->NewString (Hii, NULL, StringHandle, &Token, WinNtIo->EnvString);\r
662 ASSERT (!EFI_ERROR (Status));\r
663\r
664 RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorVersionRecordType;\r
665 RecordBuffer.DataRecord->VariableRecord.ProcessorVersion = Token;\r
666 TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_VERSION_DATA);\r
667\r
668 Status = DataHub->LogData (\r
669 DataHub,\r
670 &gEfiProcessorSubClassGuid,\r
671 &gEfiProcessorProducerGuid,\r
672 EFI_DATA_RECORD_CLASS_DATA,\r
673 RecordBuffer.Raw,\r
674 TotalSize\r
675 );\r
676 }\r
677\r
678 if ((WinNtIo->WinNtThunk->Signature == EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE) &&\r
679 CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtCPUSpeedGuid)\r
680 ) {\r
681 //\r
682 // Check if this record has been stored in data hub\r
683 //\r
684 do {\r
685 Status = DataHub->GetNextRecord (DataHub, &MonotonicCount, NULL, &Record);\r
686 if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) {\r
687 DataHeader = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1);\r
688 if (CompareGuid (&Record->DataRecordGuid, &gEfiProcessorSubClassGuid) &&\r
689 (DataHeader->RecordType == ProcessorCoreFrequencyRecordType)\r
690 ) {\r
691 RecordFound = TRUE;\r
692 }\r
693 }\r
694 } while (MonotonicCount != 0);\r
695\r
696 if (RecordFound) {\r
697 RecordFound = FALSE;\r
698 continue;\r
699 }\r
700 //\r
701 // Store CPU frequency data record to data hub\r
702 //\r
703 RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorCoreFrequencyRecordType;\r
704 RecordBuffer.DataRecord->VariableRecord.ProcessorCoreFrequency.Value = (UINT16) Atoi (WinNtIo->EnvString);\r
705 RecordBuffer.DataRecord->VariableRecord.ProcessorCoreFrequency.Exponent = 6;\r
706 TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_CORE_FREQUENCY_DATA);\r
707\r
708 Status = DataHub->LogData (\r
709 DataHub,\r
710 &gEfiProcessorSubClassGuid,\r
711 &gEfiProcessorProducerGuid,\r
712 EFI_DATA_RECORD_CLASS_DATA,\r
713 RecordBuffer.Raw,\r
714 TotalSize\r
715 );\r
716\r
717 FreePool (RecordBuffer.Raw);\r
718 }\r
719\r
720 gBS->CloseProtocol (\r
721 HandleBuffer[HandleIndex],\r
722 &gEfiWinNtIoProtocolGuid,\r
723 Context,\r
724 NULL\r
725 );\r
726 }\r
727}\r