PeiMpLib.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760
  1. /** @file
  2. MP initialize support functions for PEI phase.
  3. Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "MpLib.h"
  7. #include <Library/PeiServicesLib.h>
  8. #include <Guid/S3SmmInitDone.h>
  9. #include <Ppi/ShadowMicrocode.h>
  10. STATIC UINT64 mSevEsPeiWakeupBuffer = BASE_1MB;
  11. /**
  12. S3 SMM Init Done notification function.
  13. @param PeiServices Indirect reference to the PEI Services Table.
  14. @param NotifyDesc Address of the notification descriptor data structure.
  15. @param InvokePpi Address of the PPI that was invoked.
  16. @retval EFI_SUCCESS The function completes successfully.
  17. **/
  18. EFI_STATUS
  19. EFIAPI
  20. NotifyOnS3SmmInitDonePpi (
  21. IN EFI_PEI_SERVICES **PeiServices,
  22. IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
  23. IN VOID *InvokePpi
  24. );
  25. //
  26. // Global function
  27. //
  28. EFI_PEI_NOTIFY_DESCRIPTOR mS3SmmInitDoneNotifyDesc = {
  29. EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
  30. &gEdkiiS3SmmInitDoneGuid,
  31. NotifyOnS3SmmInitDonePpi
  32. };
  33. /**
  34. S3 SMM Init Done notification function.
  35. @param PeiServices Indirect reference to the PEI Services Table.
  36. @param NotifyDesc Address of the notification descriptor data structure.
  37. @param InvokePpi Address of the PPI that was invoked.
  38. @retval EFI_SUCCESS The function completes successfully.
  39. **/
  40. EFI_STATUS
  41. EFIAPI
  42. NotifyOnS3SmmInitDonePpi (
  43. IN EFI_PEI_SERVICES **PeiServices,
  44. IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
  45. IN VOID *InvokePpi
  46. )
  47. {
  48. CPU_MP_DATA *CpuMpData;
  49. CpuMpData = GetCpuMpData ();
  50. //
  51. // PiSmmCpuDxeSmm driver hardcode change the loop mode to HLT mode.
  52. // So in this notify function, code need to check the current loop
  53. // mode, if it is not HLT mode, code need to change loop mode back
  54. // to the original mode.
  55. //
  56. if (CpuMpData->ApLoopMode != ApInHltLoop) {
  57. CpuMpData->WakeUpByInitSipiSipi = TRUE;
  58. }
  59. return EFI_SUCCESS;
  60. }
  61. /**
  62. Enable Debug Agent to support source debugging on AP function.
  63. **/
  64. VOID
  65. EnableDebugAgent (
  66. VOID
  67. )
  68. {
  69. }
  70. /**
  71. Get pointer to CPU MP Data structure.
  72. For BSP, the pointer is retrieved from HOB.
  73. For AP, the structure is just after IDT.
  74. @return The pointer to CPU MP Data structure.
  75. **/
  76. CPU_MP_DATA *
  77. GetCpuMpData (
  78. VOID
  79. )
  80. {
  81. CPU_MP_DATA *CpuMpData;
  82. MSR_IA32_APIC_BASE_REGISTER ApicBaseMsr;
  83. IA32_DESCRIPTOR Idtr;
  84. ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE);
  85. if (ApicBaseMsr.Bits.BSP == 1) {
  86. CpuMpData = GetCpuMpDataFromGuidedHob ();
  87. ASSERT (CpuMpData != NULL);
  88. } else {
  89. AsmReadIdtr (&Idtr);
  90. CpuMpData = (CPU_MP_DATA *)(Idtr.Base + Idtr.Limit + 1);
  91. }
  92. return CpuMpData;
  93. }
  94. /**
  95. Save the pointer to CPU MP Data structure.
  96. @param[in] CpuMpData The pointer to CPU MP Data structure will be saved.
  97. **/
  98. VOID
  99. SaveCpuMpData (
  100. IN CPU_MP_DATA *CpuMpData
  101. )
  102. {
  103. UINT64 Data64;
  104. //
  105. // Build location of CPU MP DATA buffer in HOB
  106. //
  107. Data64 = (UINT64)(UINTN)CpuMpData;
  108. BuildGuidDataHob (
  109. &mCpuInitMpLibHobGuid,
  110. (VOID *)&Data64,
  111. sizeof (UINT64)
  112. );
  113. }
  114. /**
  115. Check if AP wakeup buffer is overlapped with existing allocated buffer.
  116. @param[in] WakeupBufferStart AP wakeup buffer start address.
  117. @param[in] WakeupBufferEnd AP wakeup buffer end address.
  118. @retval TRUE There is overlap.
  119. @retval FALSE There is no overlap.
  120. **/
  121. BOOLEAN
  122. CheckOverlapWithAllocatedBuffer (
  123. IN UINT64 WakeupBufferStart,
  124. IN UINT64 WakeupBufferEnd
  125. )
  126. {
  127. EFI_PEI_HOB_POINTERS Hob;
  128. EFI_HOB_MEMORY_ALLOCATION *MemoryHob;
  129. BOOLEAN Overlapped;
  130. UINT64 MemoryStart;
  131. UINT64 MemoryEnd;
  132. Overlapped = FALSE;
  133. //
  134. // Get the HOB list for processing
  135. //
  136. Hob.Raw = GetHobList ();
  137. //
  138. // Collect memory ranges
  139. //
  140. while (!END_OF_HOB_LIST (Hob)) {
  141. if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
  142. MemoryHob = Hob.MemoryAllocation;
  143. MemoryStart = MemoryHob->AllocDescriptor.MemoryBaseAddress;
  144. MemoryEnd = MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength;
  145. if (!((WakeupBufferStart >= MemoryEnd) || (WakeupBufferEnd <= MemoryStart))) {
  146. Overlapped = TRUE;
  147. break;
  148. }
  149. }
  150. Hob.Raw = GET_NEXT_HOB (Hob);
  151. }
  152. return Overlapped;
  153. }
  154. /**
  155. Get available system memory below 1MB by specified size.
  156. @param[in] WakeupBufferSize Wakeup buffer size required
  157. @retval other Return wakeup buffer address below 1MB.
  158. @retval -1 Cannot find free memory below 1MB.
  159. **/
  160. UINTN
  161. GetWakeupBuffer (
  162. IN UINTN WakeupBufferSize
  163. )
  164. {
  165. EFI_PEI_HOB_POINTERS Hob;
  166. UINT64 WakeupBufferStart;
  167. UINT64 WakeupBufferEnd;
  168. WakeupBufferSize = (WakeupBufferSize + SIZE_4KB - 1) & ~(SIZE_4KB - 1);
  169. //
  170. // Get the HOB list for processing
  171. //
  172. Hob.Raw = GetHobList ();
  173. //
  174. // Collect memory ranges
  175. //
  176. while (!END_OF_HOB_LIST (Hob)) {
  177. if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
  178. if ((Hob.ResourceDescriptor->PhysicalStart < BASE_1MB) &&
  179. (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&
  180. ((Hob.ResourceDescriptor->ResourceAttribute &
  181. (EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED |
  182. EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED |
  183. EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED
  184. )) == 0)
  185. )
  186. {
  187. //
  188. // Need memory under 1MB to be collected here
  189. //
  190. WakeupBufferEnd = Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength;
  191. if (PcdGetBool (PcdSevEsIsEnabled) &&
  192. (WakeupBufferEnd > mSevEsPeiWakeupBuffer))
  193. {
  194. //
  195. // SEV-ES Wakeup buffer should be under 1MB and under any previous one
  196. //
  197. WakeupBufferEnd = mSevEsPeiWakeupBuffer;
  198. } else if (WakeupBufferEnd > BASE_1MB) {
  199. //
  200. // Wakeup buffer should be under 1MB
  201. //
  202. WakeupBufferEnd = BASE_1MB;
  203. }
  204. while (WakeupBufferEnd > WakeupBufferSize) {
  205. //
  206. // Wakeup buffer should be aligned on 4KB
  207. //
  208. WakeupBufferStart = (WakeupBufferEnd - WakeupBufferSize) & ~(SIZE_4KB - 1);
  209. if (WakeupBufferStart < Hob.ResourceDescriptor->PhysicalStart) {
  210. break;
  211. }
  212. if (CheckOverlapWithAllocatedBuffer (WakeupBufferStart, WakeupBufferEnd)) {
  213. //
  214. // If this range is overlapped with existing allocated buffer, skip it
  215. // and find the next range
  216. //
  217. WakeupBufferEnd -= WakeupBufferSize;
  218. continue;
  219. }
  220. DEBUG ((
  221. DEBUG_INFO,
  222. "WakeupBufferStart = %x, WakeupBufferSize = %x\n",
  223. WakeupBufferStart,
  224. WakeupBufferSize
  225. ));
  226. if (PcdGetBool (PcdSevEsIsEnabled)) {
  227. //
  228. // Next SEV-ES wakeup buffer allocation must be below this
  229. // allocation
  230. //
  231. mSevEsPeiWakeupBuffer = WakeupBufferStart;
  232. }
  233. return (UINTN)WakeupBufferStart;
  234. }
  235. }
  236. }
  237. //
  238. // Find the next HOB
  239. //
  240. Hob.Raw = GET_NEXT_HOB (Hob);
  241. }
  242. return (UINTN)-1;
  243. }
  244. /**
  245. Get available EfiBootServicesCode memory below 4GB by specified size.
  246. This buffer is required to safely transfer AP from real address mode to
  247. protected mode or long mode, due to the fact that the buffer returned by
  248. GetWakeupBuffer() may be marked as non-executable.
  249. @param[in] BufferSize Wakeup transition buffer size.
  250. @retval other Return wakeup transition buffer address below 4GB.
  251. @retval 0 Cannot find free memory below 4GB.
  252. **/
  253. UINTN
  254. GetModeTransitionBuffer (
  255. IN UINTN BufferSize
  256. )
  257. {
  258. //
  259. // PEI phase doesn't need to do such transition. So simply return 0.
  260. //
  261. return 0;
  262. }
  263. /**
  264. Return the address of the SEV-ES AP jump table.
  265. This buffer is required in order for an SEV-ES guest to transition from
  266. UEFI into an OS.
  267. @return Return SEV-ES AP jump table buffer
  268. **/
  269. UINTN
  270. GetSevEsAPMemory (
  271. VOID
  272. )
  273. {
  274. //
  275. // PEI phase doesn't need to do such transition. So simply return 0.
  276. //
  277. return 0;
  278. }
  279. /**
  280. Checks APs status and updates APs status if needed.
  281. **/
  282. VOID
  283. CheckAndUpdateApsStatus (
  284. VOID
  285. )
  286. {
  287. }
  288. /**
  289. Build the microcode patch HOB that contains the base address and size of the
  290. microcode patch stored in the memory.
  291. @param[in] CpuMpData Pointer to the CPU_MP_DATA structure.
  292. **/
  293. VOID
  294. BuildMicrocodeCacheHob (
  295. IN CPU_MP_DATA *CpuMpData
  296. )
  297. {
  298. EDKII_MICROCODE_PATCH_HOB *MicrocodeHob;
  299. UINTN HobDataLength;
  300. UINT32 Index;
  301. HobDataLength = sizeof (EDKII_MICROCODE_PATCH_HOB) +
  302. sizeof (UINT64) * CpuMpData->CpuCount;
  303. MicrocodeHob = AllocatePool (HobDataLength);
  304. if (MicrocodeHob == NULL) {
  305. ASSERT (FALSE);
  306. return;
  307. }
  308. //
  309. // Store the information of the memory region that holds the microcode patches.
  310. //
  311. MicrocodeHob->MicrocodePatchAddress = CpuMpData->MicrocodePatchAddress;
  312. MicrocodeHob->MicrocodePatchRegionSize = CpuMpData->MicrocodePatchRegionSize;
  313. //
  314. // Store the detected microcode patch for each processor as well.
  315. //
  316. MicrocodeHob->ProcessorCount = CpuMpData->CpuCount;
  317. for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
  318. if (CpuMpData->CpuData[Index].MicrocodeEntryAddr != 0) {
  319. MicrocodeHob->ProcessorSpecificPatchOffset[Index] =
  320. CpuMpData->CpuData[Index].MicrocodeEntryAddr - CpuMpData->MicrocodePatchAddress;
  321. } else {
  322. MicrocodeHob->ProcessorSpecificPatchOffset[Index] = MAX_UINT64;
  323. }
  324. }
  325. BuildGuidDataHob (
  326. &gEdkiiMicrocodePatchHobGuid,
  327. MicrocodeHob,
  328. HobDataLength
  329. );
  330. return;
  331. }
  332. /**
  333. Initialize global data for MP support.
  334. @param[in] CpuMpData The pointer to CPU MP Data structure.
  335. **/
  336. VOID
  337. InitMpGlobalData (
  338. IN CPU_MP_DATA *CpuMpData
  339. )
  340. {
  341. EFI_STATUS Status;
  342. BuildMicrocodeCacheHob (CpuMpData);
  343. SaveCpuMpData (CpuMpData);
  344. ///
  345. /// Install Notify
  346. ///
  347. Status = PeiServicesNotifyPpi (&mS3SmmInitDoneNotifyDesc);
  348. ASSERT_EFI_ERROR (Status);
  349. }
  350. /**
  351. This service executes a caller provided function on all enabled APs.
  352. @param[in] Procedure A pointer to the function to be run on
  353. enabled APs of the system. See type
  354. EFI_AP_PROCEDURE.
  355. @param[in] SingleThread If TRUE, then all the enabled APs execute
  356. the function specified by Procedure one by
  357. one, in ascending order of processor handle
  358. number. If FALSE, then all the enabled APs
  359. execute the function specified by Procedure
  360. simultaneously.
  361. @param[in] WaitEvent The event created by the caller with CreateEvent()
  362. service. If it is NULL, then execute in
  363. blocking mode. BSP waits until all APs finish
  364. or TimeoutInMicroSeconds expires. If it's
  365. not NULL, then execute in non-blocking mode.
  366. BSP requests the function specified by
  367. Procedure to be started on all the enabled
  368. APs, and go on executing immediately. If
  369. all return from Procedure, or TimeoutInMicroSeconds
  370. expires, this event is signaled. The BSP
  371. can use the CheckEvent() or WaitForEvent()
  372. services to check the state of event. Type
  373. EFI_EVENT is defined in CreateEvent() in
  374. the Unified Extensible Firmware Interface
  375. Specification.
  376. @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
  377. APs to return from Procedure, either for
  378. blocking or non-blocking mode. Zero means
  379. infinity. If the timeout expires before
  380. all APs return from Procedure, then Procedure
  381. on the failed APs is terminated. All enabled
  382. APs are available for next function assigned
  383. by MpInitLibStartupAllAPs() or
  384. MPInitLibStartupThisAP().
  385. If the timeout expires in blocking mode,
  386. BSP returns EFI_TIMEOUT. If the timeout
  387. expires in non-blocking mode, WaitEvent
  388. is signaled with SignalEvent().
  389. @param[in] ProcedureArgument The parameter passed into Procedure for
  390. all APs.
  391. @param[out] FailedCpuList If NULL, this parameter is ignored. Otherwise,
  392. if all APs finish successfully, then its
  393. content is set to NULL. If not all APs
  394. finish before timeout expires, then its
  395. content is set to address of the buffer
  396. holding handle numbers of the failed APs.
  397. The buffer is allocated by MP Initialization
  398. library, and it's the caller's responsibility to
  399. free the buffer with FreePool() service.
  400. In blocking mode, it is ready for consumption
  401. when the call returns. In non-blocking mode,
  402. it is ready when WaitEvent is signaled. The
  403. list of failed CPU is terminated by
  404. END_OF_CPU_LIST.
  405. @retval EFI_SUCCESS In blocking mode, all APs have finished before
  406. the timeout expired.
  407. @retval EFI_SUCCESS In non-blocking mode, function has been dispatched
  408. to all enabled APs.
  409. @retval EFI_UNSUPPORTED A non-blocking mode request was made after the
  410. UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
  411. signaled.
  412. @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not
  413. supported.
  414. @retval EFI_DEVICE_ERROR Caller processor is AP.
  415. @retval EFI_NOT_STARTED No enabled APs exist in the system.
  416. @retval EFI_NOT_READY Any enabled APs are busy.
  417. @retval EFI_NOT_READY MP Initialize Library is not initialized.
  418. @retval EFI_TIMEOUT In blocking mode, the timeout expired before
  419. all enabled APs have finished.
  420. @retval EFI_INVALID_PARAMETER Procedure is NULL.
  421. **/
  422. EFI_STATUS
  423. EFIAPI
  424. MpInitLibStartupAllAPs (
  425. IN EFI_AP_PROCEDURE Procedure,
  426. IN BOOLEAN SingleThread,
  427. IN EFI_EVENT WaitEvent OPTIONAL,
  428. IN UINTN TimeoutInMicroseconds,
  429. IN VOID *ProcedureArgument OPTIONAL,
  430. OUT UINTN **FailedCpuList OPTIONAL
  431. )
  432. {
  433. if (WaitEvent != NULL) {
  434. return EFI_UNSUPPORTED;
  435. }
  436. return StartupAllCPUsWorker (
  437. Procedure,
  438. SingleThread,
  439. TRUE,
  440. NULL,
  441. TimeoutInMicroseconds,
  442. ProcedureArgument,
  443. FailedCpuList
  444. );
  445. }
  446. /**
  447. This service lets the caller get one enabled AP to execute a caller-provided
  448. function.
  449. @param[in] Procedure A pointer to the function to be run on the
  450. designated AP of the system. See type
  451. EFI_AP_PROCEDURE.
  452. @param[in] ProcessorNumber The handle number of the AP. The range is
  453. from 0 to the total number of logical
  454. processors minus 1. The total number of
  455. logical processors can be retrieved by
  456. MpInitLibGetNumberOfProcessors().
  457. @param[in] WaitEvent The event created by the caller with CreateEvent()
  458. service. If it is NULL, then execute in
  459. blocking mode. BSP waits until this AP finish
  460. or TimeoutInMicroSeconds expires. If it's
  461. not NULL, then execute in non-blocking mode.
  462. BSP requests the function specified by
  463. Procedure to be started on this AP,
  464. and go on executing immediately. If this AP
  465. return from Procedure or TimeoutInMicroSeconds
  466. expires, this event is signaled. The BSP
  467. can use the CheckEvent() or WaitForEvent()
  468. services to check the state of event. Type
  469. EFI_EVENT is defined in CreateEvent() in
  470. the Unified Extensible Firmware Interface
  471. Specification.
  472. @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for
  473. this AP to finish this Procedure, either for
  474. blocking or non-blocking mode. Zero means
  475. infinity. If the timeout expires before
  476. this AP returns from Procedure, then Procedure
  477. on the AP is terminated. The
  478. AP is available for next function assigned
  479. by MpInitLibStartupAllAPs() or
  480. MpInitLibStartupThisAP().
  481. If the timeout expires in blocking mode,
  482. BSP returns EFI_TIMEOUT. If the timeout
  483. expires in non-blocking mode, WaitEvent
  484. is signaled with SignalEvent().
  485. @param[in] ProcedureArgument The parameter passed into Procedure on the
  486. specified AP.
  487. @param[out] Finished If NULL, this parameter is ignored. In
  488. blocking mode, this parameter is ignored.
  489. In non-blocking mode, if AP returns from
  490. Procedure before the timeout expires, its
  491. content is set to TRUE. Otherwise, the
  492. value is set to FALSE. The caller can
  493. determine if the AP returned from Procedure
  494. by evaluating this value.
  495. @retval EFI_SUCCESS In blocking mode, specified AP finished before
  496. the timeout expires.
  497. @retval EFI_SUCCESS In non-blocking mode, the function has been
  498. dispatched to specified AP.
  499. @retval EFI_UNSUPPORTED A non-blocking mode request was made after the
  500. UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
  501. signaled.
  502. @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not
  503. supported.
  504. @retval EFI_DEVICE_ERROR The calling processor is an AP.
  505. @retval EFI_TIMEOUT In blocking mode, the timeout expired before
  506. the specified AP has finished.
  507. @retval EFI_NOT_READY The specified AP is busy.
  508. @retval EFI_NOT_READY MP Initialize Library is not initialized.
  509. @retval EFI_NOT_FOUND The processor with the handle specified by
  510. ProcessorNumber does not exist.
  511. @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.
  512. @retval EFI_INVALID_PARAMETER Procedure is NULL.
  513. **/
  514. EFI_STATUS
  515. EFIAPI
  516. MpInitLibStartupThisAP (
  517. IN EFI_AP_PROCEDURE Procedure,
  518. IN UINTN ProcessorNumber,
  519. IN EFI_EVENT WaitEvent OPTIONAL,
  520. IN UINTN TimeoutInMicroseconds,
  521. IN VOID *ProcedureArgument OPTIONAL,
  522. OUT BOOLEAN *Finished OPTIONAL
  523. )
  524. {
  525. if (WaitEvent != NULL) {
  526. return EFI_UNSUPPORTED;
  527. }
  528. return StartupThisAPWorker (
  529. Procedure,
  530. ProcessorNumber,
  531. NULL,
  532. TimeoutInMicroseconds,
  533. ProcedureArgument,
  534. Finished
  535. );
  536. }
  537. /**
  538. This service switches the requested AP to be the BSP from that point onward.
  539. This service changes the BSP for all purposes. This call can only be performed
  540. by the current BSP.
  541. @param[in] ProcessorNumber The handle number of AP that is to become the new
  542. BSP. The range is from 0 to the total number of
  543. logical processors minus 1. The total number of
  544. logical processors can be retrieved by
  545. MpInitLibGetNumberOfProcessors().
  546. @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an
  547. enabled AP. Otherwise, it will be disabled.
  548. @retval EFI_SUCCESS BSP successfully switched.
  549. @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to
  550. this service returning.
  551. @retval EFI_UNSUPPORTED Switching the BSP is not supported.
  552. @retval EFI_DEVICE_ERROR The calling processor is an AP.
  553. @retval EFI_NOT_FOUND The processor with the handle specified by
  554. ProcessorNumber does not exist.
  555. @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or
  556. a disabled AP.
  557. @retval EFI_NOT_READY The specified AP is busy.
  558. @retval EFI_NOT_READY MP Initialize Library is not initialized.
  559. **/
  560. EFI_STATUS
  561. EFIAPI
  562. MpInitLibSwitchBSP (
  563. IN UINTN ProcessorNumber,
  564. IN BOOLEAN EnableOldBSP
  565. )
  566. {
  567. return SwitchBSPWorker (ProcessorNumber, EnableOldBSP);
  568. }
  569. /**
  570. This service lets the caller enable or disable an AP from this point onward.
  571. This service may only be called from the BSP.
  572. @param[in] ProcessorNumber The handle number of AP.
  573. The range is from 0 to the total number of
  574. logical processors minus 1. The total number of
  575. logical processors can be retrieved by
  576. MpInitLibGetNumberOfProcessors().
  577. @param[in] EnableAP Specifies the new state for the processor for
  578. enabled, FALSE for disabled.
  579. @param[in] HealthFlag If not NULL, a pointer to a value that specifies
  580. the new health status of the AP. This flag
  581. corresponds to StatusFlag defined in
  582. EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). Only
  583. the PROCESSOR_HEALTH_STATUS_BIT is used. All other
  584. bits are ignored. If it is NULL, this parameter
  585. is ignored.
  586. @retval EFI_SUCCESS The specified AP was enabled or disabled successfully.
  587. @retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed
  588. prior to this service returning.
  589. @retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported.
  590. @retval EFI_DEVICE_ERROR The calling processor is an AP.
  591. @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber
  592. does not exist.
  593. @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP.
  594. @retval EFI_NOT_READY MP Initialize Library is not initialized.
  595. **/
  596. EFI_STATUS
  597. EFIAPI
  598. MpInitLibEnableDisableAP (
  599. IN UINTN ProcessorNumber,
  600. IN BOOLEAN EnableAP,
  601. IN UINT32 *HealthFlag OPTIONAL
  602. )
  603. {
  604. return EnableDisableApWorker (ProcessorNumber, EnableAP, HealthFlag);
  605. }
  606. /**
  607. This funtion will try to invoke platform specific microcode shadow logic to
  608. relocate microcode update patches into memory.
  609. @param[in, out] CpuMpData The pointer to CPU MP Data structure.
  610. @retval EFI_SUCCESS Shadow microcode success.
  611. @retval EFI_OUT_OF_RESOURCES No enough resource to complete the operation.
  612. @retval EFI_UNSUPPORTED Can't find platform specific microcode shadow
  613. PPI/Protocol.
  614. **/
  615. EFI_STATUS
  616. PlatformShadowMicrocode (
  617. IN OUT CPU_MP_DATA *CpuMpData
  618. )
  619. {
  620. EFI_STATUS Status;
  621. EDKII_PEI_SHADOW_MICROCODE_PPI *ShadowMicrocodePpi;
  622. UINTN CpuCount;
  623. EDKII_PEI_MICROCODE_CPU_ID *MicrocodeCpuId;
  624. UINTN Index;
  625. UINTN BufferSize;
  626. VOID *Buffer;
  627. Status = PeiServicesLocatePpi (
  628. &gEdkiiPeiShadowMicrocodePpiGuid,
  629. 0,
  630. NULL,
  631. (VOID **)&ShadowMicrocodePpi
  632. );
  633. if (EFI_ERROR (Status)) {
  634. return EFI_UNSUPPORTED;
  635. }
  636. CpuCount = CpuMpData->CpuCount;
  637. MicrocodeCpuId = (EDKII_PEI_MICROCODE_CPU_ID *)AllocateZeroPool (sizeof (EDKII_PEI_MICROCODE_CPU_ID) * CpuCount);
  638. if (MicrocodeCpuId == NULL) {
  639. return EFI_OUT_OF_RESOURCES;
  640. }
  641. for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
  642. MicrocodeCpuId[Index].ProcessorSignature = CpuMpData->CpuData[Index].ProcessorSignature;
  643. MicrocodeCpuId[Index].PlatformId = CpuMpData->CpuData[Index].PlatformId;
  644. }
  645. Status = ShadowMicrocodePpi->ShadowMicrocode (
  646. ShadowMicrocodePpi,
  647. CpuCount,
  648. MicrocodeCpuId,
  649. &BufferSize,
  650. &Buffer
  651. );
  652. FreePool (MicrocodeCpuId);
  653. if (EFI_ERROR (Status)) {
  654. return EFI_NOT_FOUND;
  655. }
  656. CpuMpData->MicrocodePatchAddress = (UINTN)Buffer;
  657. CpuMpData->MicrocodePatchRegionSize = BufferSize;
  658. DEBUG ((
  659. DEBUG_INFO,
  660. "%a: Required microcode patches have been loaded at 0x%lx, with size 0x%lx.\n",
  661. __FUNCTION__,
  662. CpuMpData->MicrocodePatchAddress,
  663. CpuMpData->MicrocodePatchRegionSize
  664. ));
  665. return EFI_SUCCESS;
  666. }