]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/Library/MpInitLib/MpLib.c
UefiCpuPkg/MpInitLib: Fill MP_CPU_EXCHANGE_INFO fields
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / MpLib.c
1 /** @file
2 CPU MP Initialize Library common functions.
3
4 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "MpLib.h"
16
17 EFI_GUID mCpuInitMpLibHobGuid = CPU_INIT_MP_LIB_HOB_GUID;
18
19 /**
20 The function will check if BSP Execute Disable is enabled.
21 DxeIpl may have enabled Execute Disable for BSP,
22 APs need to get the status and sync up the settings.
23
24 @retval TRUE BSP Execute Disable is enabled.
25 @retval FALSE BSP Execute Disable is not enabled.
26 **/
27 BOOLEAN
28 IsBspExecuteDisableEnabled (
29 VOID
30 )
31 {
32 UINT32 Eax;
33 CPUID_EXTENDED_CPU_SIG_EDX Edx;
34 MSR_IA32_EFER_REGISTER EferMsr;
35 BOOLEAN Enabled;
36
37 Enabled = FALSE;
38 AsmCpuid (CPUID_EXTENDED_FUNCTION, &Eax, NULL, NULL, NULL);
39 if (Eax >= CPUID_EXTENDED_CPU_SIG) {
40 AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &Edx.Uint32);
41 //
42 // CPUID 0x80000001
43 // Bit 20: Execute Disable Bit available.
44 //
45 if (Edx.Bits.NX != 0) {
46 EferMsr.Uint64 = AsmReadMsr64 (MSR_IA32_EFER);
47 //
48 // MSR 0xC0000080
49 // Bit 11: Execute Disable Bit enable.
50 //
51 if (EferMsr.Bits.NXE != 0) {
52 Enabled = TRUE;
53 }
54 }
55 }
56
57 return Enabled;
58 }
59
60 /**
61 Get the Application Processors state.
62
63 @param[in] CpuData The pointer to CPU_AP_DATA of specified AP
64
65 @return The AP status
66 **/
67 CPU_STATE
68 GetApState (
69 IN CPU_AP_DATA *CpuData
70 )
71 {
72 return CpuData->State;
73 }
74
75 /**
76 Set the Application Processors state.
77
78 @param[in] CpuData The pointer to CPU_AP_DATA of specified AP
79 @param[in] State The AP status
80 **/
81 VOID
82 SetApState (
83 IN CPU_AP_DATA *CpuData,
84 IN CPU_STATE State
85 )
86 {
87 AcquireSpinLock (&CpuData->ApLock);
88 CpuData->State = State;
89 ReleaseSpinLock (&CpuData->ApLock);
90 }
91
92 /**
93 Save the volatile registers required to be restored following INIT IPI.
94
95 @param[out] VolatileRegisters Returns buffer saved the volatile resisters
96 **/
97 VOID
98 SaveVolatileRegisters (
99 OUT CPU_VOLATILE_REGISTERS *VolatileRegisters
100 )
101 {
102 CPUID_VERSION_INFO_EDX VersionInfoEdx;
103
104 VolatileRegisters->Cr0 = AsmReadCr0 ();
105 VolatileRegisters->Cr3 = AsmReadCr3 ();
106 VolatileRegisters->Cr4 = AsmReadCr4 ();
107
108 AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &VersionInfoEdx.Uint32);
109 if (VersionInfoEdx.Bits.DE != 0) {
110 //
111 // If processor supports Debugging Extensions feature
112 // by CPUID.[EAX=01H]:EDX.BIT2
113 //
114 VolatileRegisters->Dr0 = AsmReadDr0 ();
115 VolatileRegisters->Dr1 = AsmReadDr1 ();
116 VolatileRegisters->Dr2 = AsmReadDr2 ();
117 VolatileRegisters->Dr3 = AsmReadDr3 ();
118 VolatileRegisters->Dr6 = AsmReadDr6 ();
119 VolatileRegisters->Dr7 = AsmReadDr7 ();
120 }
121 }
122
123 /**
124 Restore the volatile registers following INIT IPI.
125
126 @param[in] VolatileRegisters Pointer to volatile resisters
127 @param[in] IsRestoreDr TRUE: Restore DRx if supported
128 FALSE: Do not restore DRx
129 **/
130 VOID
131 RestoreVolatileRegisters (
132 IN CPU_VOLATILE_REGISTERS *VolatileRegisters,
133 IN BOOLEAN IsRestoreDr
134 )
135 {
136 CPUID_VERSION_INFO_EDX VersionInfoEdx;
137
138 AsmWriteCr0 (VolatileRegisters->Cr0);
139 AsmWriteCr3 (VolatileRegisters->Cr3);
140 AsmWriteCr4 (VolatileRegisters->Cr4);
141
142 if (IsRestoreDr) {
143 AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &VersionInfoEdx.Uint32);
144 if (VersionInfoEdx.Bits.DE != 0) {
145 //
146 // If processor supports Debugging Extensions feature
147 // by CPUID.[EAX=01H]:EDX.BIT2
148 //
149 AsmWriteDr0 (VolatileRegisters->Dr0);
150 AsmWriteDr1 (VolatileRegisters->Dr1);
151 AsmWriteDr2 (VolatileRegisters->Dr2);
152 AsmWriteDr3 (VolatileRegisters->Dr3);
153 AsmWriteDr6 (VolatileRegisters->Dr6);
154 AsmWriteDr7 (VolatileRegisters->Dr7);
155 }
156 }
157 }
158
159 /**
160 Detect whether Mwait-monitor feature is supported.
161
162 @retval TRUE Mwait-monitor feature is supported.
163 @retval FALSE Mwait-monitor feature is not supported.
164 **/
165 BOOLEAN
166 IsMwaitSupport (
167 VOID
168 )
169 {
170 CPUID_VERSION_INFO_ECX VersionInfoEcx;
171
172 AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, &VersionInfoEcx.Uint32, NULL);
173 return (VersionInfoEcx.Bits.MONITOR == 1) ? TRUE : FALSE;
174 }
175
176 /**
177 Get AP loop mode.
178
179 @param[out] MonitorFilterSize Returns the largest monitor-line size in bytes.
180
181 @return The AP loop mode.
182 **/
183 UINT8
184 GetApLoopMode (
185 OUT UINT32 *MonitorFilterSize
186 )
187 {
188 UINT8 ApLoopMode;
189 CPUID_MONITOR_MWAIT_EBX MonitorMwaitEbx;
190
191 ASSERT (MonitorFilterSize != NULL);
192
193 ApLoopMode = PcdGet8 (PcdCpuApLoopMode);
194 ASSERT (ApLoopMode >= ApInHltLoop && ApLoopMode <= ApInRunLoop);
195 if (ApLoopMode == ApInMwaitLoop) {
196 if (!IsMwaitSupport ()) {
197 //
198 // If processor does not support MONITOR/MWAIT feature,
199 // force AP in Hlt-loop mode
200 //
201 ApLoopMode = ApInHltLoop;
202 }
203 }
204
205 if (ApLoopMode != ApInMwaitLoop) {
206 *MonitorFilterSize = sizeof (UINT32);
207 } else {
208 //
209 // CPUID.[EAX=05H]:EBX.BIT0-15: Largest monitor-line size in bytes
210 // CPUID.[EAX=05H].EDX: C-states supported using MWAIT
211 //
212 AsmCpuid (CPUID_MONITOR_MWAIT, NULL, &MonitorMwaitEbx.Uint32, NULL, NULL);
213 *MonitorFilterSize = MonitorMwaitEbx.Bits.LargestMonitorLineSize;
214 }
215
216 return ApLoopMode;
217 }
218
219 /**
220 Do sync on APs.
221
222 @param[in, out] Buffer Pointer to private data buffer.
223 **/
224 VOID
225 EFIAPI
226 ApInitializeSync (
227 IN OUT VOID *Buffer
228 )
229 {
230 CPU_MP_DATA *CpuMpData;
231
232 CpuMpData = (CPU_MP_DATA *) Buffer;
233 //
234 // Sync BSP's MTRR table to AP
235 //
236 MtrrSetAllMtrrs (&CpuMpData->MtrrTable);
237 //
238 // Load microcode on AP
239 //
240 MicrocodeDetect (CpuMpData);
241 }
242
243 /**
244 Find the current Processor number by APIC ID.
245
246 @param[in] CpuMpData Pointer to PEI CPU MP Data
247 @param[in] ProcessorNumber Return the pocessor number found
248
249 @retval EFI_SUCCESS ProcessorNumber is found and returned.
250 @retval EFI_NOT_FOUND ProcessorNumber is not found.
251 **/
252 EFI_STATUS
253 GetProcessorNumber (
254 IN CPU_MP_DATA *CpuMpData,
255 OUT UINTN *ProcessorNumber
256 )
257 {
258 UINTN TotalProcessorNumber;
259 UINTN Index;
260
261 TotalProcessorNumber = CpuMpData->CpuCount;
262 for (Index = 0; Index < TotalProcessorNumber; Index ++) {
263 if (CpuMpData->CpuData[Index].ApicId == GetApicId ()) {
264 *ProcessorNumber = Index;
265 return EFI_SUCCESS;
266 }
267 }
268 return EFI_NOT_FOUND;
269 }
270
271 /*
272 Initialize CPU AP Data when AP is wakeup at the first time.
273
274 @param[in, out] CpuMpData Pointer to PEI CPU MP Data
275 @param[in] ProcessorNumber The handle number of processor
276 @param[in] BistData Processor BIST data
277
278 **/
279 VOID
280 InitializeApData (
281 IN OUT CPU_MP_DATA *CpuMpData,
282 IN UINTN ProcessorNumber,
283 IN UINT32 BistData
284 )
285 {
286 CpuMpData->CpuData[ProcessorNumber].Waiting = FALSE;
287 CpuMpData->CpuData[ProcessorNumber].Health = BistData;
288 CpuMpData->CpuData[ProcessorNumber].CpuHealthy = (BistData == 0) ? TRUE : FALSE;
289 CpuMpData->CpuData[ProcessorNumber].ApicId = GetApicId ();
290 CpuMpData->CpuData[ProcessorNumber].InitialApicId = GetInitialApicId ();
291 if (CpuMpData->CpuData[ProcessorNumber].InitialApicId >= 0xFF) {
292 //
293 // Set x2APIC mode if there are any logical processor reporting
294 // an Initial APIC ID of 255 or greater.
295 //
296 AcquireSpinLock(&CpuMpData->MpLock);
297 CpuMpData->X2ApicEnable = TRUE;
298 ReleaseSpinLock(&CpuMpData->MpLock);
299 }
300
301 InitializeSpinLock(&CpuMpData->CpuData[ProcessorNumber].ApLock);
302 SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateIdle);
303 }
304
305 /**
306 This function will be called from AP reset code if BSP uses WakeUpAP.
307
308 @param[in] ExchangeInfo Pointer to the MP exchange info buffer
309 @param[in] NumApsExecuting Number of current executing AP
310 **/
311 VOID
312 EFIAPI
313 ApWakeupFunction (
314 IN MP_CPU_EXCHANGE_INFO *ExchangeInfo,
315 IN UINTN NumApsExecuting
316 )
317 {
318 CPU_MP_DATA *CpuMpData;
319 UINTN ProcessorNumber;
320 EFI_AP_PROCEDURE Procedure;
321 VOID *Parameter;
322 UINT32 BistData;
323 volatile UINT32 *ApStartupSignalBuffer;
324
325 //
326 // AP finished assembly code and begin to execute C code
327 //
328 CpuMpData = ExchangeInfo->CpuMpData;
329
330 ProgramVirtualWireMode ();
331
332 while (TRUE) {
333 if (CpuMpData->InitFlag == ApInitConfig) {
334 //
335 // Add CPU number
336 //
337 InterlockedIncrement ((UINT32 *) &CpuMpData->CpuCount);
338 ProcessorNumber = NumApsExecuting;
339 //
340 // This is first time AP wakeup, get BIST information from AP stack
341 //
342 BistData = *(UINT32 *) (CpuMpData->Buffer + ProcessorNumber * CpuMpData->CpuApStackSize - sizeof (UINTN));
343 //
344 // Do some AP initialize sync
345 //
346 ApInitializeSync (CpuMpData);
347 //
348 // Sync BSP's Control registers to APs
349 //
350 RestoreVolatileRegisters (&CpuMpData->CpuData[0].VolatileRegisters, FALSE);
351 InitializeApData (CpuMpData, ProcessorNumber, BistData);
352 ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal;
353 } else {
354 //
355 // Execute AP function if AP is ready
356 //
357 GetProcessorNumber (CpuMpData, &ProcessorNumber);
358 //
359 // Clear AP start-up signal when AP waken up
360 //
361 ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal;
362 InterlockedCompareExchange32 (
363 (UINT32 *) ApStartupSignalBuffer,
364 WAKEUP_AP_SIGNAL,
365 0
366 );
367 if (CpuMpData->ApLoopMode == ApInHltLoop) {
368 //
369 // Restore AP's volatile registers saved
370 //
371 RestoreVolatileRegisters (&CpuMpData->CpuData[ProcessorNumber].VolatileRegisters, TRUE);
372 }
373
374 if (GetApState (&CpuMpData->CpuData[ProcessorNumber]) == CpuStateReady) {
375 Procedure = (EFI_AP_PROCEDURE)CpuMpData->CpuData[ProcessorNumber].ApFunction;
376 Parameter = (VOID *) CpuMpData->CpuData[ProcessorNumber].ApFunctionArgument;
377 if (Procedure != NULL) {
378 SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateBusy);
379 //
380 // Invoke AP function here
381 //
382 Procedure (Parameter);
383 //
384 // Re-get the CPU APICID and Initial APICID
385 //
386 CpuMpData->CpuData[ProcessorNumber].ApicId = GetApicId ();
387 CpuMpData->CpuData[ProcessorNumber].InitialApicId = GetInitialApicId ();
388 }
389 SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateFinished);
390 }
391 }
392
393 //
394 // AP finished executing C code
395 //
396 InterlockedIncrement ((UINT32 *) &CpuMpData->FinishedCount);
397
398 //
399 // Place AP is specified loop mode
400 //
401 if (CpuMpData->ApLoopMode == ApInHltLoop) {
402 //
403 // Save AP volatile registers
404 //
405 SaveVolatileRegisters (&CpuMpData->CpuData[ProcessorNumber].VolatileRegisters);
406 //
407 // Place AP in HLT-loop
408 //
409 while (TRUE) {
410 DisableInterrupts ();
411 CpuSleep ();
412 CpuPause ();
413 }
414 }
415 while (TRUE) {
416 DisableInterrupts ();
417 if (CpuMpData->ApLoopMode == ApInMwaitLoop) {
418 //
419 // Place AP in MWAIT-loop
420 //
421 AsmMonitor ((UINTN) ApStartupSignalBuffer, 0, 0);
422 if (*ApStartupSignalBuffer != WAKEUP_AP_SIGNAL) {
423 //
424 // Check AP start-up signal again.
425 // If AP start-up signal is not set, place AP into
426 // the specified C-state
427 //
428 AsmMwait (CpuMpData->ApTargetCState << 4, 0);
429 }
430 } else if (CpuMpData->ApLoopMode == ApInRunLoop) {
431 //
432 // Place AP in Run-loop
433 //
434 CpuPause ();
435 } else {
436 ASSERT (FALSE);
437 }
438
439 //
440 // If AP start-up signal is written, AP is waken up
441 // otherwise place AP in loop again
442 //
443 if (*ApStartupSignalBuffer == WAKEUP_AP_SIGNAL) {
444 break;
445 }
446 }
447 }
448 }
449
450 /**
451 This function will fill the exchange info structure.
452
453 @param[in] CpuMpData Pointer to CPU MP Data
454
455 **/
456 VOID
457 FillExchangeInfoData (
458 IN CPU_MP_DATA *CpuMpData
459 )
460 {
461 volatile MP_CPU_EXCHANGE_INFO *ExchangeInfo;
462
463 ExchangeInfo = CpuMpData->MpCpuExchangeInfo;
464 ExchangeInfo->Lock = 0;
465 ExchangeInfo->StackStart = CpuMpData->Buffer;
466 ExchangeInfo->StackSize = CpuMpData->CpuApStackSize;
467 ExchangeInfo->BufferStart = CpuMpData->WakeupBuffer;
468 ExchangeInfo->ModeOffset = CpuMpData->AddressMap.ModeEntryOffset;
469
470 ExchangeInfo->CodeSegment = AsmReadCs ();
471 ExchangeInfo->DataSegment = AsmReadDs ();
472
473 ExchangeInfo->Cr3 = AsmReadCr3 ();
474
475 ExchangeInfo->CFunction = (UINTN) ApWakeupFunction;
476 ExchangeInfo->NumApsExecuting = 0;
477 ExchangeInfo->CpuMpData = CpuMpData;
478
479 ExchangeInfo->EnableExecuteDisable = IsBspExecuteDisableEnabled ();
480
481 //
482 // Get the BSP's data of GDT and IDT
483 //
484 AsmReadGdtr ((IA32_DESCRIPTOR *) &ExchangeInfo->GdtrProfile);
485 AsmReadIdtr ((IA32_DESCRIPTOR *) &ExchangeInfo->IdtrProfile);
486 }
487
488 /**
489 MP Initialize Library initialization.
490
491 This service will allocate AP reset vector and wakeup all APs to do APs
492 initialization.
493
494 This service must be invoked before all other MP Initialize Library
495 service are invoked.
496
497 @retval EFI_SUCCESS MP initialization succeeds.
498 @retval Others MP initialization fails.
499
500 **/
501 EFI_STATUS
502 EFIAPI
503 MpInitLibInitialize (
504 VOID
505 )
506 {
507 UINT32 MaxLogicalProcessorNumber;
508 UINT32 ApStackSize;
509 MP_ASSEMBLY_ADDRESS_MAP AddressMap;
510 UINTN BufferSize;
511 UINT32 MonitorFilterSize;
512 VOID *MpBuffer;
513 UINTN Buffer;
514 CPU_MP_DATA *CpuMpData;
515 UINT8 ApLoopMode;
516 UINT8 *MonitorBuffer;
517 UINTN Index;
518 UINTN ApResetVectorSize;
519 UINTN BackupBufferAddr;
520 MaxLogicalProcessorNumber = PcdGet32(PcdCpuMaxLogicalProcessorNumber);
521
522 AsmGetAddressMap (&AddressMap);
523 ApResetVectorSize = AddressMap.RendezvousFunnelSize + sizeof (MP_CPU_EXCHANGE_INFO);
524 ApStackSize = PcdGet32(PcdCpuApStackSize);
525 ApLoopMode = GetApLoopMode (&MonitorFilterSize);
526
527 BufferSize = ApStackSize * MaxLogicalProcessorNumber;
528 BufferSize += MonitorFilterSize * MaxLogicalProcessorNumber;
529 BufferSize += sizeof (CPU_MP_DATA);
530 BufferSize += ApResetVectorSize;
531 BufferSize += (sizeof (CPU_AP_DATA) + sizeof (CPU_INFO_IN_HOB))* MaxLogicalProcessorNumber;
532 MpBuffer = AllocatePages (EFI_SIZE_TO_PAGES (BufferSize));
533 ASSERT (MpBuffer != NULL);
534 ZeroMem (MpBuffer, BufferSize);
535 Buffer = (UINTN) MpBuffer;
536
537 MonitorBuffer = (UINT8 *) (Buffer + ApStackSize * MaxLogicalProcessorNumber);
538 BackupBufferAddr = (UINTN) MonitorBuffer + MonitorFilterSize * MaxLogicalProcessorNumber;
539 CpuMpData = (CPU_MP_DATA *) (BackupBufferAddr + ApResetVectorSize);
540 CpuMpData->Buffer = Buffer;
541 CpuMpData->CpuApStackSize = ApStackSize;
542 CpuMpData->BackupBuffer = BackupBufferAddr;
543 CpuMpData->BackupBufferSize = ApResetVectorSize;
544 CpuMpData->EndOfPeiFlag = FALSE;
545 CpuMpData->WakeupBuffer = (UINTN) -1;
546 CpuMpData->CpuCount = 1;
547 CpuMpData->BspNumber = 0;
548 CpuMpData->WaitEvent = NULL;
549 CpuMpData->CpuData = (CPU_AP_DATA *) (CpuMpData + 1);
550 CpuMpData->CpuInfoInHob = (UINT64) (UINTN) (CpuMpData->CpuData + MaxLogicalProcessorNumber);
551 InitializeSpinLock(&CpuMpData->MpLock);
552 //
553 // Save BSP's Control registers to APs
554 //
555 SaveVolatileRegisters (&CpuMpData->CpuData[0].VolatileRegisters);
556 //
557 // Set BSP basic information
558 //
559 InitializeApData (CpuMpData, 0, 0);
560 //
561 // Save assembly code information
562 //
563 CopyMem (&CpuMpData->AddressMap, &AddressMap, sizeof (MP_ASSEMBLY_ADDRESS_MAP));
564 //
565 // Finally set AP loop mode
566 //
567 CpuMpData->ApLoopMode = ApLoopMode;
568 DEBUG ((DEBUG_INFO, "AP Loop Mode is %d\n", CpuMpData->ApLoopMode));
569 //
570 // Set up APs wakeup signal buffer
571 //
572 for (Index = 0; Index < MaxLogicalProcessorNumber; Index++) {
573 CpuMpData->CpuData[Index].StartupApSignal =
574 (UINT32 *)(MonitorBuffer + MonitorFilterSize * Index);
575 }
576 //
577 // Load Microcode on BSP
578 //
579 MicrocodeDetect (CpuMpData);
580 //
581 // Store BSP's MTRR setting
582 //
583 MtrrGetAllMtrrs (&CpuMpData->MtrrTable);
584
585
586 //
587 // Initialize global data for MP support
588 //
589 InitMpGlobalData (CpuMpData);
590
591 return EFI_SUCCESS;
592 }
593
594 /**
595 Gets detailed MP-related information on the requested processor at the
596 instant this call is made. This service may only be called from the BSP.
597
598 @param[in] ProcessorNumber The handle number of processor.
599 @param[out] ProcessorInfoBuffer A pointer to the buffer where information for
600 the requested processor is deposited.
601 @param[out] HealthData Return processor health data.
602
603 @retval EFI_SUCCESS Processor information was returned.
604 @retval EFI_DEVICE_ERROR The calling processor is an AP.
605 @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL.
606 @retval EFI_NOT_FOUND The processor with the handle specified by
607 ProcessorNumber does not exist in the platform.
608 @retval EFI_NOT_READY MP Initialize Library is not initialized.
609
610 **/
611 EFI_STATUS
612 EFIAPI
613 MpInitLibGetProcessorInfo (
614 IN UINTN ProcessorNumber,
615 OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer,
616 OUT EFI_HEALTH_FLAGS *HealthData OPTIONAL
617 )
618 {
619 return EFI_UNSUPPORTED;
620 }
621 /**
622 This return the handle number for the calling processor. This service may be
623 called from the BSP and APs.
624
625 @param[out] ProcessorNumber Pointer to the handle number of AP.
626 The range is from 0 to the total number of
627 logical processors minus 1. The total number of
628 logical processors can be retrieved by
629 MpInitLibGetNumberOfProcessors().
630
631 @retval EFI_SUCCESS The current processor handle number was returned
632 in ProcessorNumber.
633 @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL.
634 @retval EFI_NOT_READY MP Initialize Library is not initialized.
635
636 **/
637 EFI_STATUS
638 EFIAPI
639 MpInitLibWhoAmI (
640 OUT UINTN *ProcessorNumber
641 )
642 {
643 return EFI_UNSUPPORTED;
644 }
645 /**
646 Retrieves the number of logical processor in the platform and the number of
647 those logical processors that are enabled on this boot. This service may only
648 be called from the BSP.
649
650 @param[out] NumberOfProcessors Pointer to the total number of logical
651 processors in the system, including the BSP
652 and disabled APs.
653 @param[out] NumberOfEnabledProcessors Pointer to the number of enabled logical
654 processors that exist in system, including
655 the BSP.
656
657 @retval EFI_SUCCESS The number of logical processors and enabled
658 logical processors was retrieved.
659 @retval EFI_DEVICE_ERROR The calling processor is an AP.
660 @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL and NumberOfEnabledProcessors
661 is NULL.
662 @retval EFI_NOT_READY MP Initialize Library is not initialized.
663
664 **/
665 EFI_STATUS
666 EFIAPI
667 MpInitLibGetNumberOfProcessors (
668 OUT UINTN *NumberOfProcessors, OPTIONAL
669 OUT UINTN *NumberOfEnabledProcessors OPTIONAL
670 )
671 {
672 return EFI_UNSUPPORTED;
673 }
674 /**
675 Get pointer to CPU MP Data structure from GUIDed HOB.
676
677 @return The pointer to CPU MP Data structure.
678 **/
679 CPU_MP_DATA *
680 GetCpuMpDataFromGuidedHob (
681 VOID
682 )
683 {
684 EFI_HOB_GUID_TYPE *GuidHob;
685 VOID *DataInHob;
686 CPU_MP_DATA *CpuMpData;
687
688 CpuMpData = NULL;
689 GuidHob = GetFirstGuidHob (&mCpuInitMpLibHobGuid);
690 if (GuidHob != NULL) {
691 DataInHob = GET_GUID_HOB_DATA (GuidHob);
692 CpuMpData = (CPU_MP_DATA *) (*(UINTN *) DataInHob);
693 }
694 return CpuMpData;
695 }