SecMain.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773
  1. /** @file
  2. RISC-V SEC phase module.
  3. Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <SecMain.h>
  7. #include <IndustryStandard/RiscVOpensbi.h>
  8. #include <Library/DebugPrintErrorLevelLib.h>
  9. #include <Library/PrintLib.h>
  10. #include <Library/RiscVEdk2SbiLib.h>
  11. #include <sbi/riscv_asm.h>
  12. #include <sbi/riscv_atomic.h>
  13. #include <sbi/sbi_console.h> // Reference to header file in opensbi
  14. #include <sbi/sbi_hart.h> // Reference to header file in opensbi
  15. #include <sbi/sbi_hartmask.h> // Reference to header file in opensbi
  16. #include <sbi/sbi_scratch.h> // Reference to header file in opensbi
  17. #include <sbi/sbi_platform.h> // Reference to header file in opensbi
  18. #include <sbi/sbi_init.h> // Reference to header file in opensbi
  19. #include <sbi/sbi_ecall.h> // Reference to header file in opensbi
  20. #include <sbi/sbi_trap.h> // Reference to header file in opensbi
  21. //
  22. // Indicates the boot hart (PcdBootHartId) OpenSBI initialization is done.
  23. //
  24. atomic_t BootHartDone = ATOMIC_INITIALIZER(0);
  25. atomic_t NonBootHartMessageLock = ATOMIC_INITIALIZER(0);
  26. typedef struct sbi_scratch *(*hartid2scratch)(ulong hartid, ulong hartindex);
  27. STATIC EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi = {
  28. TemporaryRamMigration
  29. };
  30. STATIC EFI_PEI_TEMPORARY_RAM_DONE_PPI mTemporaryRamDonePpi = {
  31. TemporaryRamDone
  32. };
  33. STATIC EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTable[] = {
  34. {
  35. EFI_PEI_PPI_DESCRIPTOR_PPI,
  36. &gEfiTemporaryRamSupportPpiGuid,
  37. &mTemporaryRamSupportPpi
  38. },
  39. {
  40. (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
  41. &gEfiTemporaryRamDonePpiGuid,
  42. &mTemporaryRamDonePpi
  43. },
  44. };
  45. /**
  46. Locates a section within a series of sections
  47. with the specified section type.
  48. The Instance parameter indicates which instance of the section
  49. type to return. (0 is first instance, 1 is second...)
  50. @param[in] Sections The sections to search
  51. @param[in] SizeOfSections Total size of all sections
  52. @param[in] SectionType The section type to locate
  53. @param[in] Instance The section instance number
  54. @param[out] FoundSection The FFS section if found
  55. @retval EFI_SUCCESS The file and section was found
  56. @retval EFI_NOT_FOUND The file and section was not found
  57. @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
  58. **/
  59. EFI_STATUS
  60. FindFfsSectionInstance (
  61. IN VOID *Sections,
  62. IN UINTN SizeOfSections,
  63. IN EFI_SECTION_TYPE SectionType,
  64. IN UINTN Instance,
  65. OUT EFI_COMMON_SECTION_HEADER **FoundSection
  66. )
  67. {
  68. EFI_PHYSICAL_ADDRESS CurrentAddress;
  69. UINT32 Size;
  70. EFI_PHYSICAL_ADDRESS EndOfSections;
  71. EFI_COMMON_SECTION_HEADER *Section;
  72. EFI_PHYSICAL_ADDRESS EndOfSection;
  73. //
  74. // Loop through the FFS file sections within the PEI Core FFS file
  75. //
  76. EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) Sections;
  77. EndOfSections = EndOfSection + SizeOfSections;
  78. for (;;) {
  79. if (EndOfSection == EndOfSections) {
  80. break;
  81. }
  82. CurrentAddress = (EndOfSection + 3) & ~(3ULL);
  83. if (CurrentAddress >= EndOfSections) {
  84. return EFI_VOLUME_CORRUPTED;
  85. }
  86. Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;
  87. Size = SECTION_SIZE (Section);
  88. if (Size < sizeof (*Section)) {
  89. return EFI_VOLUME_CORRUPTED;
  90. }
  91. EndOfSection = CurrentAddress + Size;
  92. if (EndOfSection > EndOfSections) {
  93. return EFI_VOLUME_CORRUPTED;
  94. }
  95. //
  96. // Look for the requested section type
  97. //
  98. if (Section->Type == SectionType) {
  99. if (Instance == 0) {
  100. *FoundSection = Section;
  101. return EFI_SUCCESS;
  102. } else {
  103. Instance--;
  104. }
  105. }
  106. }
  107. return EFI_NOT_FOUND;
  108. }
  109. /**
  110. Locates a section within a series of sections
  111. with the specified section type.
  112. @param[in] Sections The sections to search
  113. @param[in] SizeOfSections Total size of all sections
  114. @param[in] SectionType The section type to locate
  115. @param[out] FoundSection The FFS section if found
  116. @retval EFI_SUCCESS The file and section was found
  117. @retval EFI_NOT_FOUND The file and section was not found
  118. @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
  119. **/
  120. EFI_STATUS
  121. FindFfsSectionInSections (
  122. IN VOID *Sections,
  123. IN UINTN SizeOfSections,
  124. IN EFI_SECTION_TYPE SectionType,
  125. OUT EFI_COMMON_SECTION_HEADER **FoundSection
  126. )
  127. {
  128. return FindFfsSectionInstance (
  129. Sections,
  130. SizeOfSections,
  131. SectionType,
  132. 0,
  133. FoundSection
  134. );
  135. }
  136. /**
  137. Locates a FFS file with the specified file type and a section
  138. within that file with the specified section type.
  139. @param[in] Fv The firmware volume to search
  140. @param[in] FileType The file type to locate
  141. @param[in] SectionType The section type to locate
  142. @param[out] FoundSection The FFS section if found
  143. @retval EFI_SUCCESS The file and section was found
  144. @retval EFI_NOT_FOUND The file and section was not found
  145. @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
  146. **/
  147. EFI_STATUS
  148. FindFfsFileAndSection (
  149. IN EFI_FIRMWARE_VOLUME_HEADER *Fv,
  150. IN EFI_FV_FILETYPE FileType,
  151. IN EFI_SECTION_TYPE SectionType,
  152. OUT EFI_COMMON_SECTION_HEADER **FoundSection
  153. )
  154. {
  155. EFI_STATUS Status;
  156. EFI_PHYSICAL_ADDRESS CurrentAddress;
  157. EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;
  158. EFI_FFS_FILE_HEADER *File;
  159. UINT32 Size;
  160. EFI_PHYSICAL_ADDRESS EndOfFile;
  161. if (Fv->Signature != EFI_FVH_SIGNATURE) {
  162. DEBUG ((DEBUG_ERROR, "%a: FV at %p does not have FV header signature\n", __FUNCTION__, Fv));
  163. return EFI_VOLUME_CORRUPTED;
  164. }
  165. CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Fv;
  166. EndOfFirmwareVolume = CurrentAddress + Fv->FvLength;
  167. //
  168. // Loop through the FFS files in the Boot Firmware Volume
  169. //
  170. for (EndOfFile = CurrentAddress + Fv->HeaderLength; ; ) {
  171. CurrentAddress = (EndOfFile + 7) & ~(7ULL);
  172. if (CurrentAddress > EndOfFirmwareVolume) {
  173. return EFI_VOLUME_CORRUPTED;
  174. }
  175. File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;
  176. Size = *(UINT32*) File->Size & 0xffffff;
  177. if (Size < (sizeof (*File) + sizeof (EFI_COMMON_SECTION_HEADER))) {
  178. return EFI_VOLUME_CORRUPTED;
  179. }
  180. EndOfFile = CurrentAddress + Size;
  181. if (EndOfFile > EndOfFirmwareVolume) {
  182. return EFI_VOLUME_CORRUPTED;
  183. }
  184. //
  185. // Look for the request file type
  186. //
  187. if (File->Type != FileType) {
  188. continue;
  189. }
  190. Status = FindFfsSectionInSections (
  191. (VOID*) (File + 1),
  192. (UINTN) EndOfFile - (UINTN) (File + 1),
  193. SectionType,
  194. FoundSection
  195. );
  196. if (!EFI_ERROR (Status) || (Status == EFI_VOLUME_CORRUPTED)) {
  197. return Status;
  198. }
  199. }
  200. }
  201. /**
  202. Locates the PEI Core entry point address
  203. @param[in] Fv The firmware volume to search
  204. @param[out] PeiCoreEntryPoint The entry point of the PEI Core image
  205. @retval EFI_SUCCESS The file and section was found
  206. @retval EFI_NOT_FOUND The file and section was not found
  207. @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
  208. **/
  209. EFI_STATUS
  210. FindPeiCoreImageBaseInFv (
  211. IN EFI_FIRMWARE_VOLUME_HEADER *Fv,
  212. OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase
  213. )
  214. {
  215. EFI_STATUS Status;
  216. EFI_COMMON_SECTION_HEADER *Section;
  217. Status = FindFfsFileAndSection (
  218. Fv,
  219. EFI_FV_FILETYPE_PEI_CORE,
  220. EFI_SECTION_PE32,
  221. &Section
  222. );
  223. if (EFI_ERROR (Status)) {
  224. Status = FindFfsFileAndSection (
  225. Fv,
  226. EFI_FV_FILETYPE_PEI_CORE,
  227. EFI_SECTION_TE,
  228. &Section
  229. );
  230. if (EFI_ERROR (Status)) {
  231. DEBUG ((DEBUG_ERROR, "%a: Unable to find PEI Core image\n", __FUNCTION__));
  232. return Status;
  233. }
  234. }
  235. DEBUG ((DEBUG_INFO, "%a: PeiCoreImageBase found\n", __FUNCTION__));
  236. *PeiCoreImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(Section + 1);
  237. return EFI_SUCCESS;
  238. }
  239. /**
  240. Locates the PEI Core entry point address
  241. @param[in,out] Fv The firmware volume to search
  242. @param[out] PeiCoreEntryPoint The entry point of the PEI Core image
  243. @retval EFI_SUCCESS The file and section was found
  244. @retval EFI_NOT_FOUND The file and section was not found
  245. @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
  246. **/
  247. VOID
  248. FindPeiCoreImageBase (
  249. IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv,
  250. OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase
  251. )
  252. {
  253. *PeiCoreImageBase = 0;
  254. DEBUG ((DEBUG_INFO, "%a: Entry\n", __FUNCTION__));
  255. FindPeiCoreImageBaseInFv (*BootFv, PeiCoreImageBase);
  256. }
  257. /*
  258. Find and return Pei Core entry point.
  259. It also find SEC and PEI Core file debug inforamtion. It will report them if
  260. remote debug is enabled.
  261. **/
  262. VOID
  263. FindAndReportEntryPoints (
  264. IN EFI_FIRMWARE_VOLUME_HEADER **BootFirmwareVolumePtr,
  265. OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint
  266. )
  267. {
  268. EFI_STATUS Status;
  269. EFI_PHYSICAL_ADDRESS PeiCoreImageBase;
  270. DEBUG ((DEBUG_INFO, "%a: Entry\n", __FUNCTION__));
  271. FindPeiCoreImageBase (BootFirmwareVolumePtr, &PeiCoreImageBase);
  272. //
  273. // Find PEI Core entry point
  274. //
  275. Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, (VOID**) PeiCoreEntryPoint);
  276. if (EFI_ERROR(Status)) {
  277. *PeiCoreEntryPoint = 0;
  278. }
  279. DEBUG ((DEBUG_INFO, "%a: PeCoffLoaderGetEntryPoint success: %x\n", __FUNCTION__, *PeiCoreEntryPoint));
  280. return;
  281. }
  282. /*
  283. Print out the content of firmware context.
  284. **/
  285. VOID
  286. DebugPrintFirmwareContext (
  287. EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT *FirmwareContext
  288. )
  289. {
  290. DEBUG ((DEBUG_INFO, "%a: OpenSBI Firmware Context at 0x%x\n", __FUNCTION__, FirmwareContext));
  291. DEBUG ((DEBUG_INFO, "%a: PEI Service at 0x%x\n\n", __FUNCTION__, FirmwareContext->PeiServiceTable));
  292. }
  293. /** Temporary RAM migration function.
  294. This function migrates the data from temporary RAM to permanent
  295. memory.
  296. @param[in] PeiServices PEI service
  297. @param[in] TemporaryMemoryBase Temporary memory base address
  298. @param[in] PermanentMemoryBase Permanent memory base address
  299. @param[in] CopySize Size to copy
  300. **/
  301. EFI_STATUS
  302. EFIAPI
  303. TemporaryRamMigration (
  304. IN CONST EFI_PEI_SERVICES **PeiServices,
  305. IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
  306. IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
  307. IN UINTN CopySize
  308. )
  309. {
  310. VOID *OldHeap;
  311. VOID *NewHeap;
  312. VOID *OldStack;
  313. VOID *NewStack;
  314. EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT *FirmwareContext;
  315. DEBUG ((DEBUG_INFO,
  316. "%a: Temp Mem Base:0x%Lx, Permanent Mem Base:0x%Lx, CopySize:0x%Lx\n",
  317. __FUNCTION__,
  318. TemporaryMemoryBase,
  319. PermanentMemoryBase,
  320. (UINT64)CopySize
  321. ));
  322. OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;
  323. NewHeap = (VOID*)((UINTN)PermanentMemoryBase + (CopySize >> 1));
  324. OldStack = (VOID*)((UINTN)TemporaryMemoryBase + (CopySize >> 1));
  325. NewStack = (VOID*)(UINTN)PermanentMemoryBase;
  326. CopyMem (NewHeap, OldHeap, CopySize >> 1); // Migrate Heap
  327. CopyMem (NewStack, OldStack, CopySize >> 1); // Migrate Stack
  328. //
  329. // Reset firmware context pointer
  330. //
  331. SbiGetFirmwareContext (&FirmwareContext);
  332. FirmwareContext = (VOID *)FirmwareContext + (unsigned long)((UINTN)NewStack - (UINTN)OldStack);
  333. SbiSetFirmwareContext (FirmwareContext);
  334. //
  335. // Relocate PEI Service **
  336. //
  337. FirmwareContext->PeiServiceTable += (unsigned long)((UINTN)NewStack - (UINTN)OldStack);
  338. DEBUG ((DEBUG_INFO, "%a: OpenSBI Firmware Context is relocated to 0x%x\n", __FUNCTION__, FirmwareContext));
  339. DebugPrintFirmwareContext ((EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT *)FirmwareContext);
  340. register uintptr_t a0 asm ("a0") = (uintptr_t)((UINTN)NewStack - (UINTN)OldStack);
  341. asm volatile ("add sp, sp, a0"::"r"(a0):);
  342. return EFI_SUCCESS;
  343. }
  344. /** Temprary RAM done function.
  345. **/
  346. EFI_STATUS EFIAPI TemporaryRamDone (
  347. VOID
  348. )
  349. {
  350. DEBUG ((DEBUG_INFO, "%a: 2nd time PEI core, temporary ram done.\n", __FUNCTION__));
  351. return EFI_SUCCESS;
  352. }
  353. /**
  354. Handles SBI calls of EDK2's SBI FW extension.
  355. The return value is the error code returned by the SBI call.
  356. @param[in] ExtId The extension ID of the FW extension.
  357. @param[in] FuncId The called function ID.
  358. @param[in] Args The args to the function.
  359. @param[out] OutVal The value the function returns to the caller.
  360. @param[out] OutTrap Trap info for trapping further, see OpenSBI code.
  361. Is ignored if return value is not SBI_ETRAP.
  362. @retval SBI_OK If the handler succeeds.
  363. @retval SBI_ENOTSUPP If there's no function with the given ID.
  364. @retval SBI_ETRAP If the called SBI functions wants to trap further.
  365. **/
  366. STATIC int SbiEcallFirmwareHandler (
  367. IN unsigned long ExtId,
  368. IN unsigned long FuncId,
  369. IN CONST struct sbi_trap_regs *TrapRegs,
  370. OUT unsigned long *OutVal,
  371. OUT struct sbi_trap_info *OutTrap
  372. )
  373. {
  374. int Ret = SBI_OK;
  375. switch (FuncId) {
  376. case SBI_EXT_FW_MSCRATCH_FUNC:
  377. *OutVal = (unsigned long) sbi_scratch_thishart_ptr();
  378. break;
  379. case SBI_EXT_FW_MSCRATCH_HARTID_FUNC:
  380. *OutVal = (unsigned long) sbi_hartid_to_scratch (TrapRegs->a0);
  381. break;
  382. default:
  383. Ret = SBI_ENOTSUPP;
  384. DEBUG ((DEBUG_ERROR, "%a: Called SBI firmware ecall with invalid function ID\n", __FUNCTION__));
  385. ASSERT (FALSE);
  386. };
  387. return Ret;
  388. }
  389. struct sbi_ecall_extension FirmwareEcall = {
  390. .extid_start = SBI_EDK2_FW_EXT,
  391. .extid_end = SBI_EDK2_FW_EXT,
  392. .handle = SbiEcallFirmwareHandler,
  393. };
  394. /** Register EDK2's SBI extension with OpenSBI
  395. This function returns EFI_STATUS, even though it only ever returns
  396. EFI_SUCCESS. On error it ASSERTs. Looking at OpenSBI code it appears that
  397. registering an extension can only fail if the extension ID is invalid or was
  398. already registered. Failure is therefore an error of the programmer.
  399. @retval EFI_SUCCESS If the extension was successfully registered.
  400. **/
  401. EFI_STATUS
  402. EFIAPI
  403. RegisterFirmwareSbiExtension (
  404. VOID
  405. )
  406. {
  407. UINTN Ret;
  408. Ret = sbi_ecall_register_extension(&FirmwareEcall);
  409. if (Ret) {
  410. //
  411. // Only fails if the extension ID is invalid or already is registered.
  412. //
  413. DEBUG ((DEBUG_ERROR, "Failed to register SBI Firmware Extension for EDK2\n"));
  414. ASSERT(FALSE);
  415. }
  416. return EFI_SUCCESS;
  417. }
  418. /** Transion from SEC phase to PEI phase.
  419. This function transits to S-mode PEI phase from M-mode SEC phase.
  420. @param[in] BootHartId Hardware thread ID of boot hart.
  421. @param[in] Scratch Pointer to sbi_scratch structure.
  422. **/
  423. VOID EFIAPI PeiCore (
  424. IN UINTN BootHartId,
  425. IN struct sbi_scratch *Scratch
  426. )
  427. {
  428. EFI_SEC_PEI_HAND_OFF SecCoreData;
  429. EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint;
  430. EFI_FIRMWARE_VOLUME_HEADER *BootFv = (EFI_FIRMWARE_VOLUME_HEADER *)FixedPcdGet32(PcdRiscVPeiFvBase);
  431. EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT FirmwareContext;
  432. struct sbi_scratch *ScratchSpace;
  433. struct sbi_platform *ThisSbiPlatform;
  434. UINT32 HartId;
  435. FindAndReportEntryPoints (&BootFv, &PeiCoreEntryPoint);
  436. SecCoreData.DataSize = sizeof(EFI_SEC_PEI_HAND_OFF);
  437. SecCoreData.BootFirmwareVolumeBase = BootFv;
  438. SecCoreData.BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;
  439. SecCoreData.TemporaryRamBase = (VOID*)(UINT64) FixedPcdGet32(PcdTemporaryRamBase);
  440. SecCoreData.TemporaryRamSize = (UINTN) FixedPcdGet32(PcdTemporaryRamSize);
  441. SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
  442. SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1;
  443. SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + (SecCoreData.TemporaryRamSize >> 1);
  444. SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1;
  445. //
  446. // Print out scratch address of each hart
  447. //
  448. DEBUG ((DEBUG_INFO, "%a: OpenSBI scratch address for each hart:\n", __FUNCTION__));
  449. for (HartId = 0; HartId < SBI_HARTMASK_MAX_BITS; HartId ++) {
  450. ScratchSpace = sbi_hartid_to_scratch (HartId);
  451. if(ScratchSpace != NULL) {
  452. DEBUG((DEBUG_INFO, " Hart %d: 0x%x\n", HartId, ScratchSpace));
  453. }
  454. }
  455. //
  456. // Set up OpepSBI firmware context pointer on boot hart OpenSbi scratch.
  457. // Firmware context residents in stack and will be switched to memory when
  458. // temporary RAM migration.
  459. //
  460. ZeroMem ((VOID *)&FirmwareContext, sizeof (EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT));
  461. ThisSbiPlatform = (struct sbi_platform *)sbi_platform_ptr(Scratch);
  462. if (ThisSbiPlatform->opensbi_version > OPENSBI_VERSION) {
  463. DEBUG ((DEBUG_ERROR, "%a: OpenSBI platform table version 0x%x is newer than OpenSBI version 0x%x.\n"
  464. "There maybe be some backward compatable issues.\n",
  465. __FUNCTION__,
  466. ThisSbiPlatform->opensbi_version,
  467. OPENSBI_VERSION
  468. ));
  469. ASSERT(FALSE);
  470. }
  471. DEBUG ((DEBUG_INFO, "%a: OpenSBI platform table at address: 0x%x\nFirmware Context is located at 0x%x\n",
  472. __FUNCTION__,
  473. ThisSbiPlatform,
  474. &FirmwareContext
  475. ));
  476. ThisSbiPlatform->firmware_context = (unsigned long)&FirmwareContext;
  477. //
  478. // Save Flattened Device tree in firmware context
  479. //
  480. FirmwareContext.FlattenedDeviceTree = Scratch->next_arg1;
  481. //
  482. // Set firmware context Hart-specific pointer
  483. //
  484. for (HartId = 0; HartId < SBI_HARTMASK_MAX_BITS; HartId ++) {
  485. ScratchSpace = sbi_hartid_to_scratch (HartId);
  486. if (ScratchSpace != NULL) {
  487. FirmwareContext.HartSpecific[HartId] =
  488. (EFI_RISCV_FIRMWARE_CONTEXT_HART_SPECIFIC *)((UINT8 *)ScratchSpace - FIRMWARE_CONTEXT_HART_SPECIFIC_SIZE);
  489. DEBUG ((DEBUG_INFO, "%a: OpenSBI Hart %d Firmware Context Hart-specific at address: 0x%x\n",
  490. __FUNCTION__,
  491. HartId,
  492. FirmwareContext.HartSpecific [HartId]
  493. ));
  494. }
  495. }
  496. //
  497. // Set supervisor translation mode to Bare mode
  498. //
  499. DEBUG ((DEBUG_INFO, "%a: Set Supervisor address mode to Bare-mode.\n", __FUNCTION__));
  500. RiscVSetSupervisorAddressTranslationRegister ((UINT64)RISCV_SATP_MODE_OFF << RISCV_SATP_MODE_BIT_POSITION);
  501. //
  502. // Transfer the control to the PEI core
  503. //
  504. Scratch->next_addr = (UINTN)(*PeiCoreEntryPoint);
  505. Scratch->next_mode = PRV_S;
  506. DEBUG ((DEBUG_INFO, "%a: Initializing OpenSBI library for booting hart %d\n", __FUNCTION__, BootHartId));
  507. sbi_init(Scratch);
  508. (*PeiCoreEntryPoint) (&SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTable);
  509. }
  510. /**
  511. Register firmware SBI extension and launch PeiCore to the mode specified in
  512. PcdPeiCorePrivilegeMode;
  513. To register the SBI extension we stay in M-Mode and then transition here,
  514. rather than before in sbi_init.
  515. @param[in] ThisHartId Hardware thread ID.
  516. @param[in] Scratch Pointer to sbi_scratch structure.
  517. **/
  518. VOID
  519. EFIAPI
  520. LaunchPeiCore (
  521. IN UINTN ThisHartId,
  522. IN struct sbi_scratch *Scratch
  523. )
  524. {
  525. RegisterFirmwareSbiExtension ();
  526. PeiCore (ThisHartId, Scratch);
  527. }
  528. /**
  529. Interface to invoke internal mode switch function.
  530. To register the SBI extension we stay in M-Mode and then transition here,
  531. rather than before in sbi_init.
  532. @param[in] FuncArg0 Arg0 to pass to next phase entry point address.
  533. @param[in] FuncArg1 Arg1 to pass to next phase entry point address.
  534. @param[in] NextAddr Entry point of next phase.
  535. @param[in] NextMode Privilege mode of next phase.
  536. @param[in] NextVirt Next phase is in virtualiztion.
  537. **/
  538. VOID
  539. EFIAPI
  540. RiscVOpenSbiHartSwitchMode (
  541. IN UINTN FuncArg0,
  542. IN UINTN FuncArg1,
  543. IN UINTN NextAddr,
  544. IN UINTN NextMode,
  545. IN BOOLEAN NextVirt
  546. )
  547. {
  548. sbi_hart_switch_mode(FuncArg0, FuncArg1, NextAddr, NextMode, NextVirt);
  549. }
  550. /**
  551. Get device tree address
  552. @retval The address of Device Tree binary.
  553. **/
  554. VOID *
  555. EFIAPI
  556. GetDeviceTreeAddress (
  557. VOID
  558. )
  559. {
  560. EFI_STATUS Status;
  561. EFI_COMMON_SECTION_HEADER *FoundSection;
  562. if (FixedPcdGet32 (PcdDeviceTreeAddress)) {
  563. return (VOID *)*((unsigned long *)FixedPcdGet32 (PcdDeviceTreeAddress));
  564. } else if (FixedPcdGet32 (PcdRiscVDtbFvBase)) {
  565. Status = FindFfsFileAndSection (
  566. (EFI_FIRMWARE_VOLUME_HEADER *)FixedPcdGet32 (PcdRiscVDtbFvBase),
  567. EFI_FV_FILETYPE_FREEFORM,
  568. EFI_SECTION_RAW,
  569. &FoundSection
  570. );
  571. if (EFI_ERROR(Status)) {
  572. DEBUG ((DEBUG_ERROR, "Platform Device Tree is not found from FV.\n"));
  573. return NULL;
  574. }
  575. FoundSection ++;
  576. return (VOID *)FoundSection;
  577. } else {
  578. DEBUG ((DEBUG_ERROR, "Must use DTB either from memory or compiled in FW. PCDs configured incorrectly.\n"));
  579. ASSERT (FALSE);
  580. }
  581. return NULL;
  582. }
  583. /**
  584. This function initilizes hart specific information and SBI.
  585. For the boot hart, it boots system through PEI core and initial SBI in the DXE IPL.
  586. For others, it goes to initial SBI and halt.
  587. the lay out of memory region for each hart is as below delineates,
  588. _ ____
  589. |----Scratch ends | |
  590. | | sizeof (sbi_scratch) |
  591. | _| |
  592. |----Scratch buffer starts <----- *Scratch |
  593. |----Firmware Context Hart-specific ends _ |
  594. | | |
  595. | | FIRMWARE_CONTEXT_HART_SPECIFIC_SIZE |
  596. | | | PcdOpenSbiStackSize
  597. | _| |
  598. |----Firmware Context Hart-specific starts <----- **HartFirmwareContext |
  599. |----Hart stack top _ |
  600. | | |
  601. | | |
  602. | | Stack |
  603. | | |
  604. | _| ____|
  605. |----Hart stack bottom
  606. @param[in] HartId Hardware thread ID.
  607. @param[in] Scratch Pointer to sbi_scratch structure.
  608. **/
  609. VOID EFIAPI SecCoreStartUpWithStack(
  610. IN UINTN HartId,
  611. IN struct sbi_scratch *Scratch
  612. )
  613. {
  614. UINT64 BootHartDoneSbiInit;
  615. UINT64 NonBootHartMessageLockValue;
  616. EFI_RISCV_FIRMWARE_CONTEXT_HART_SPECIFIC *HartFirmwareContext;
  617. Scratch->next_arg1 = (unsigned long)GetDeviceTreeAddress ();
  618. if (Scratch->next_arg1 == (unsigned long)NULL) {
  619. DEBUG ((DEBUG_ERROR, "Platform Device Tree is not found\n"));
  620. ASSERT (FALSE);
  621. }
  622. DEBUG ((DEBUG_INFO, "DTB address: 0x%08x\n", Scratch->next_arg1));
  623. //
  624. // Setup EFI_RISCV_FIRMWARE_CONTEXT_HART_SPECIFIC for each hart.
  625. //
  626. HartFirmwareContext = (EFI_RISCV_FIRMWARE_CONTEXT_HART_SPECIFIC *)((UINT8 *)Scratch - FIRMWARE_CONTEXT_HART_SPECIFIC_SIZE);
  627. HartFirmwareContext->IsaExtensionSupported = RiscVReadMachineIsa ();
  628. HartFirmwareContext->MachineVendorId.Value64_L = RiscVReadMachineVendorId ();
  629. HartFirmwareContext->MachineVendorId.Value64_H = 0;
  630. HartFirmwareContext->MachineArchId.Value64_L = RiscVReadMachineArchitectureId ();
  631. HartFirmwareContext->MachineArchId.Value64_H = 0;
  632. HartFirmwareContext->MachineImplId.Value64_L = RiscVReadMachineImplementId ();
  633. HartFirmwareContext->MachineImplId.Value64_H = 0;
  634. HartFirmwareContext->HartSwitchMode = RiscVOpenSbiHartSwitchMode;
  635. if (HartId == FixedPcdGet32(PcdBootHartId)) {
  636. LaunchPeiCore (HartId, Scratch);
  637. }
  638. //
  639. // Initialize the non boot harts
  640. //
  641. do {
  642. BootHartDoneSbiInit = atomic_read (&BootHartDone);
  643. //
  644. // Below leave some memory cycles to boot hart
  645. // for updating BootHartDone.
  646. //
  647. CpuPause ();
  648. CpuPause ();
  649. CpuPause ();
  650. } while (BootHartDoneSbiInit != (UINT64)TRUE);
  651. NonBootHartMessageLockValue = atomic_xchg(&NonBootHartMessageLock, TRUE);
  652. while (NonBootHartMessageLockValue == TRUE) {
  653. CpuPause ();
  654. CpuPause ();
  655. CpuPause ();
  656. NonBootHartMessageLockValue = atomic_xchg(&NonBootHartMessageLock, TRUE);
  657. };
  658. DEBUG((DEBUG_INFO, "%a: Non boot hart %d initialization.\n", __FUNCTION__, HartId));
  659. NonBootHartMessageLockValue = atomic_xchg(&NonBootHartMessageLock, FALSE);
  660. //
  661. // Non boot hart wiil be halted waiting for SBI_HART_STARTING.
  662. // Use HSM ecall to start non boot hart (SBI_EXT_HSM_HART_START) later on,
  663. //
  664. sbi_init(Scratch);
  665. }