StandaloneMmCoreEntryPoint.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. /** @file
  2. Entry point to the Standalone MM Foundation when initialized during the SEC
  3. phase on ARM platforms
  4. Copyright (c) 2017 - 2021, Arm Ltd. All rights reserved.<BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include <PiMm.h>
  8. #include <Library/Arm/StandaloneMmCoreEntryPoint.h>
  9. #include <PiPei.h>
  10. #include <Guid/MmramMemoryReserve.h>
  11. #include <Guid/MpInformation.h>
  12. #include <Library/ArmMmuLib.h>
  13. #include <Library/ArmSvcLib.h>
  14. #include <Library/DebugLib.h>
  15. #include <Library/HobLib.h>
  16. #include <Library/BaseLib.h>
  17. #include <Library/BaseMemoryLib.h>
  18. #include <Library/SerialPortLib.h>
  19. #include <Library/PcdLib.h>
  20. #include <IndustryStandard/ArmStdSmc.h>
  21. #include <IndustryStandard/ArmMmSvc.h>
  22. #include <IndustryStandard/ArmFfaSvc.h>
  23. #define SPM_MAJOR_VER_MASK 0xFFFF0000
  24. #define SPM_MINOR_VER_MASK 0x0000FFFF
  25. #define SPM_MAJOR_VER_SHIFT 16
  26. #define FFA_NOT_SUPPORTED -1
  27. STATIC CONST UINT32 mSpmMajorVer = SPM_MAJOR_VERSION;
  28. STATIC CONST UINT32 mSpmMinorVer = SPM_MINOR_VERSION;
  29. STATIC CONST UINT32 mSpmMajorVerFfa = SPM_MAJOR_VERSION_FFA;
  30. STATIC CONST UINT32 mSpmMinorVerFfa = SPM_MINOR_VERSION_FFA;
  31. #define BOOT_PAYLOAD_VERSION 1
  32. PI_MM_ARM_TF_CPU_DRIVER_ENTRYPOINT CpuDriverEntryPoint = NULL;
  33. /**
  34. Retrieve a pointer to and print the boot information passed by privileged
  35. secure firmware.
  36. @param [in] SharedBufAddress The pointer memory shared with privileged
  37. firmware.
  38. **/
  39. EFI_SECURE_PARTITION_BOOT_INFO *
  40. GetAndPrintBootinformation (
  41. IN VOID *SharedBufAddress
  42. )
  43. {
  44. EFI_SECURE_PARTITION_BOOT_INFO *PayloadBootInfo;
  45. EFI_SECURE_PARTITION_CPU_INFO *PayloadCpuInfo;
  46. UINTN Index;
  47. PayloadBootInfo = (EFI_SECURE_PARTITION_BOOT_INFO *) SharedBufAddress;
  48. if (PayloadBootInfo == NULL) {
  49. DEBUG ((DEBUG_ERROR, "PayloadBootInfo NULL\n"));
  50. return NULL;
  51. }
  52. if (PayloadBootInfo->Header.Version != BOOT_PAYLOAD_VERSION) {
  53. DEBUG ((DEBUG_ERROR, "Boot Information Version Mismatch. Current=0x%x, Expected=0x%x.\n",
  54. PayloadBootInfo->Header.Version, BOOT_PAYLOAD_VERSION));
  55. return NULL;
  56. }
  57. DEBUG ((DEBUG_INFO, "NumSpMemRegions - 0x%x\n", PayloadBootInfo->NumSpMemRegions));
  58. DEBUG ((DEBUG_INFO, "SpMemBase - 0x%lx\n", PayloadBootInfo->SpMemBase));
  59. DEBUG ((DEBUG_INFO, "SpMemLimit - 0x%lx\n", PayloadBootInfo->SpMemLimit));
  60. DEBUG ((DEBUG_INFO, "SpImageBase - 0x%lx\n", PayloadBootInfo->SpImageBase));
  61. DEBUG ((DEBUG_INFO, "SpStackBase - 0x%lx\n", PayloadBootInfo->SpStackBase));
  62. DEBUG ((DEBUG_INFO, "SpHeapBase - 0x%lx\n", PayloadBootInfo->SpHeapBase));
  63. DEBUG ((DEBUG_INFO, "SpNsCommBufBase - 0x%lx\n", PayloadBootInfo->SpNsCommBufBase));
  64. DEBUG ((DEBUG_INFO, "SpSharedBufBase - 0x%lx\n", PayloadBootInfo->SpSharedBufBase));
  65. DEBUG ((DEBUG_INFO, "SpImageSize - 0x%x\n", PayloadBootInfo->SpImageSize));
  66. DEBUG ((DEBUG_INFO, "SpPcpuStackSize - 0x%x\n", PayloadBootInfo->SpPcpuStackSize));
  67. DEBUG ((DEBUG_INFO, "SpHeapSize - 0x%x\n", PayloadBootInfo->SpHeapSize));
  68. DEBUG ((DEBUG_INFO, "SpNsCommBufSize - 0x%x\n", PayloadBootInfo->SpNsCommBufSize));
  69. DEBUG ((DEBUG_INFO, "SpPcpuSharedBufSize - 0x%x\n", PayloadBootInfo->SpPcpuSharedBufSize));
  70. DEBUG ((DEBUG_INFO, "NumCpus - 0x%x\n", PayloadBootInfo->NumCpus));
  71. DEBUG ((DEBUG_INFO, "CpuInfo - 0x%p\n", PayloadBootInfo->CpuInfo));
  72. PayloadCpuInfo = (EFI_SECURE_PARTITION_CPU_INFO *) PayloadBootInfo->CpuInfo;
  73. if (PayloadCpuInfo == NULL) {
  74. DEBUG ((DEBUG_ERROR, "PayloadCpuInfo NULL\n"));
  75. return NULL;
  76. }
  77. for (Index = 0; Index < PayloadBootInfo->NumCpus; Index++) {
  78. DEBUG ((DEBUG_INFO, "Mpidr - 0x%lx\n", PayloadCpuInfo[Index].Mpidr));
  79. DEBUG ((DEBUG_INFO, "LinearId - 0x%x\n", PayloadCpuInfo[Index].LinearId));
  80. DEBUG ((DEBUG_INFO, "Flags - 0x%x\n", PayloadCpuInfo[Index].Flags));
  81. }
  82. return PayloadBootInfo;
  83. }
  84. /**
  85. A loop to delegated events.
  86. @param [in] EventCompleteSvcArgs Pointer to the event completion arguments.
  87. **/
  88. VOID
  89. EFIAPI
  90. DelegatedEventLoop (
  91. IN ARM_SVC_ARGS *EventCompleteSvcArgs
  92. )
  93. {
  94. BOOLEAN FfaEnabled;
  95. EFI_STATUS Status;
  96. UINTN SvcStatus;
  97. while (TRUE) {
  98. ArmCallSvc (EventCompleteSvcArgs);
  99. DEBUG ((DEBUG_INFO, "Received delegated event\n"));
  100. DEBUG ((DEBUG_INFO, "X0 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg0));
  101. DEBUG ((DEBUG_INFO, "X1 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg1));
  102. DEBUG ((DEBUG_INFO, "X2 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg2));
  103. DEBUG ((DEBUG_INFO, "X3 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg3));
  104. DEBUG ((DEBUG_INFO, "X4 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg4));
  105. DEBUG ((DEBUG_INFO, "X5 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg5));
  106. DEBUG ((DEBUG_INFO, "X6 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg6));
  107. DEBUG ((DEBUG_INFO, "X7 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg7));
  108. FfaEnabled = FeaturePcdGet (PcdFfaEnable);
  109. if (FfaEnabled) {
  110. Status = CpuDriverEntryPoint (
  111. EventCompleteSvcArgs->Arg0,
  112. EventCompleteSvcArgs->Arg6,
  113. EventCompleteSvcArgs->Arg3
  114. );
  115. if (EFI_ERROR (Status)) {
  116. DEBUG ((DEBUG_ERROR, "Failed delegated event 0x%x, Status 0x%x\n",
  117. EventCompleteSvcArgs->Arg3, Status));
  118. }
  119. } else {
  120. Status = CpuDriverEntryPoint (
  121. EventCompleteSvcArgs->Arg0,
  122. EventCompleteSvcArgs->Arg3,
  123. EventCompleteSvcArgs->Arg1
  124. );
  125. if (EFI_ERROR (Status)) {
  126. DEBUG ((DEBUG_ERROR, "Failed delegated event 0x%x, Status 0x%x\n",
  127. EventCompleteSvcArgs->Arg0, Status));
  128. }
  129. }
  130. switch (Status) {
  131. case EFI_SUCCESS:
  132. SvcStatus = ARM_SVC_SPM_RET_SUCCESS;
  133. break;
  134. case EFI_INVALID_PARAMETER:
  135. SvcStatus = ARM_SVC_SPM_RET_INVALID_PARAMS;
  136. break;
  137. case EFI_ACCESS_DENIED:
  138. SvcStatus = ARM_SVC_SPM_RET_DENIED;
  139. break;
  140. case EFI_OUT_OF_RESOURCES:
  141. SvcStatus = ARM_SVC_SPM_RET_NO_MEMORY;
  142. break;
  143. case EFI_UNSUPPORTED:
  144. SvcStatus = ARM_SVC_SPM_RET_NOT_SUPPORTED;
  145. break;
  146. default:
  147. SvcStatus = ARM_SVC_SPM_RET_NOT_SUPPORTED;
  148. break;
  149. }
  150. if (FfaEnabled) {
  151. EventCompleteSvcArgs->Arg0 = ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP;
  152. EventCompleteSvcArgs->Arg1 = 0;
  153. EventCompleteSvcArgs->Arg2 = 0;
  154. EventCompleteSvcArgs->Arg3 = ARM_SVC_ID_SP_EVENT_COMPLETE;
  155. EventCompleteSvcArgs->Arg4 = SvcStatus;
  156. } else {
  157. EventCompleteSvcArgs->Arg0 = ARM_SVC_ID_SP_EVENT_COMPLETE;
  158. EventCompleteSvcArgs->Arg1 = SvcStatus;
  159. }
  160. }
  161. }
  162. /**
  163. Query the SPM version, check compatibility and return success if compatible.
  164. @retval EFI_SUCCESS SPM versions compatible.
  165. @retval EFI_UNSUPPORTED SPM versions not compatible.
  166. **/
  167. STATIC
  168. EFI_STATUS
  169. GetSpmVersion (VOID)
  170. {
  171. EFI_STATUS Status;
  172. UINT16 CalleeSpmMajorVer;
  173. UINT16 CallerSpmMajorVer;
  174. UINT16 CalleeSpmMinorVer;
  175. UINT16 CallerSpmMinorVer;
  176. UINT32 SpmVersion;
  177. ARM_SVC_ARGS SpmVersionArgs;
  178. if (FeaturePcdGet (PcdFfaEnable)) {
  179. SpmVersionArgs.Arg0 = ARM_SVC_ID_FFA_VERSION_AARCH32;
  180. SpmVersionArgs.Arg1 = mSpmMajorVerFfa << SPM_MAJOR_VER_SHIFT;
  181. SpmVersionArgs.Arg1 |= mSpmMinorVerFfa;
  182. CallerSpmMajorVer = mSpmMajorVerFfa;
  183. CallerSpmMinorVer = mSpmMinorVerFfa;
  184. } else {
  185. SpmVersionArgs.Arg0 = ARM_SVC_ID_SPM_VERSION_AARCH32;
  186. CallerSpmMajorVer = mSpmMajorVer;
  187. CallerSpmMinorVer = mSpmMinorVer;
  188. }
  189. ArmCallSvc (&SpmVersionArgs);
  190. SpmVersion = SpmVersionArgs.Arg0;
  191. if (SpmVersion == FFA_NOT_SUPPORTED) {
  192. return EFI_UNSUPPORTED;
  193. }
  194. CalleeSpmMajorVer = ((SpmVersion & SPM_MAJOR_VER_MASK) >> SPM_MAJOR_VER_SHIFT);
  195. CalleeSpmMinorVer = ((SpmVersion & SPM_MINOR_VER_MASK) >> 0);
  196. // Different major revision values indicate possibly incompatible functions.
  197. // For two revisions, A and B, for which the major revision values are
  198. // identical, if the minor revision value of revision B is greater than
  199. // the minor revision value of revision A, then every function in
  200. // revision A must work in a compatible way with revision B.
  201. // However, it is possible for revision B to have a higher
  202. // function count than revision A.
  203. if ((CalleeSpmMajorVer == CallerSpmMajorVer) &&
  204. (CalleeSpmMinorVer >= CallerSpmMinorVer))
  205. {
  206. DEBUG ((DEBUG_INFO, "SPM Version: Major=0x%x, Minor=0x%x\n",
  207. CalleeSpmMajorVer, CalleeSpmMinorVer));
  208. Status = EFI_SUCCESS;
  209. }
  210. else
  211. {
  212. DEBUG ((DEBUG_INFO, "Incompatible SPM Versions.\n Callee Version: Major=0x%x, Minor=0x%x.\n Caller: Major=0x%x, Minor>=0x%x.\n",
  213. CalleeSpmMajorVer, CalleeSpmMinorVer, CallerSpmMajorVer, CallerSpmMinorVer));
  214. Status = EFI_UNSUPPORTED;
  215. }
  216. return Status;
  217. }
  218. /**
  219. Initialize parameters to be sent via SVC call.
  220. @param[out] InitMmFoundationSvcArgs Args structure
  221. @param[out] Ret Return Code
  222. **/
  223. STATIC
  224. VOID
  225. InitArmSvcArgs (
  226. OUT ARM_SVC_ARGS *InitMmFoundationSvcArgs,
  227. OUT INT32 *Ret
  228. )
  229. {
  230. if (FeaturePcdGet (PcdFfaEnable)) {
  231. InitMmFoundationSvcArgs->Arg0 = ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP;
  232. InitMmFoundationSvcArgs->Arg1 = 0;
  233. InitMmFoundationSvcArgs->Arg2 = 0;
  234. InitMmFoundationSvcArgs->Arg3 = ARM_SVC_ID_SP_EVENT_COMPLETE;
  235. InitMmFoundationSvcArgs->Arg4 = *Ret;
  236. } else {
  237. InitMmFoundationSvcArgs->Arg0 = ARM_SVC_ID_SP_EVENT_COMPLETE;
  238. InitMmFoundationSvcArgs->Arg1 = *Ret;
  239. }
  240. }
  241. /**
  242. The entry point of Standalone MM Foundation.
  243. @param [in] SharedBufAddress Pointer to the Buffer between SPM and SP.
  244. @param [in] SharedBufSize Size of the shared buffer.
  245. @param [in] cookie1 Cookie 1
  246. @param [in] cookie2 Cookie 2
  247. **/
  248. VOID
  249. EFIAPI
  250. _ModuleEntryPoint (
  251. IN VOID *SharedBufAddress,
  252. IN UINT64 SharedBufSize,
  253. IN UINT64 cookie1,
  254. IN UINT64 cookie2
  255. )
  256. {
  257. PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
  258. EFI_SECURE_PARTITION_BOOT_INFO *PayloadBootInfo;
  259. ARM_SVC_ARGS InitMmFoundationSvcArgs;
  260. EFI_STATUS Status;
  261. INT32 Ret;
  262. UINT32 SectionHeaderOffset;
  263. UINT16 NumberOfSections;
  264. VOID *HobStart;
  265. VOID *TeData;
  266. UINTN TeDataSize;
  267. EFI_PHYSICAL_ADDRESS ImageBase;
  268. // Get Secure Partition Manager Version Information
  269. Status = GetSpmVersion ();
  270. if (EFI_ERROR (Status)) {
  271. goto finish;
  272. }
  273. PayloadBootInfo = GetAndPrintBootinformation (SharedBufAddress);
  274. if (PayloadBootInfo == NULL) {
  275. Status = EFI_UNSUPPORTED;
  276. goto finish;
  277. }
  278. // Locate PE/COFF File information for the Standalone MM core module
  279. Status = LocateStandaloneMmCorePeCoffData (
  280. (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) PayloadBootInfo->SpImageBase,
  281. &TeData,
  282. &TeDataSize
  283. );
  284. if (EFI_ERROR (Status)) {
  285. goto finish;
  286. }
  287. // Obtain the PE/COFF Section information for the Standalone MM core module
  288. Status = GetStandaloneMmCorePeCoffSections (
  289. TeData,
  290. &ImageContext,
  291. &ImageBase,
  292. &SectionHeaderOffset,
  293. &NumberOfSections
  294. );
  295. if (EFI_ERROR (Status)) {
  296. goto finish;
  297. }
  298. //
  299. // ImageBase may deviate from ImageContext.ImageAddress if we are dealing
  300. // with a TE image, in which case the latter points to the actual offset
  301. // of the image, whereas ImageBase refers to the address where the image
  302. // would start if the stripped PE headers were still in place. In either
  303. // case, we need to fix up ImageBase so it refers to the actual current
  304. // load address.
  305. //
  306. ImageBase += (UINTN)TeData - ImageContext.ImageAddress;
  307. // Update the memory access permissions of individual sections in the
  308. // Standalone MM core module
  309. Status = UpdateMmFoundationPeCoffPermissions (
  310. &ImageContext,
  311. ImageBase,
  312. SectionHeaderOffset,
  313. NumberOfSections,
  314. ArmSetMemoryRegionNoExec,
  315. ArmSetMemoryRegionReadOnly,
  316. ArmClearMemoryRegionReadOnly
  317. );
  318. if (EFI_ERROR (Status)) {
  319. goto finish;
  320. }
  321. if (ImageContext.ImageAddress != (UINTN)TeData) {
  322. ImageContext.ImageAddress = (UINTN)TeData;
  323. ArmSetMemoryRegionNoExec (ImageBase, SIZE_4KB);
  324. ArmClearMemoryRegionReadOnly (ImageBase, SIZE_4KB);
  325. Status = PeCoffLoaderRelocateImage (&ImageContext);
  326. ASSERT_EFI_ERROR (Status);
  327. }
  328. //
  329. // Create Hoblist based upon boot information passed by privileged software
  330. //
  331. HobStart = CreateHobListFromBootInfo (&CpuDriverEntryPoint, PayloadBootInfo);
  332. //
  333. // Call the MM Core entry point
  334. //
  335. ProcessModuleEntryPointList (HobStart);
  336. DEBUG ((DEBUG_INFO, "Shared Cpu Driver EP %p\n", (VOID *) CpuDriverEntryPoint));
  337. finish:
  338. if (Status == RETURN_UNSUPPORTED) {
  339. Ret = -1;
  340. } else if (Status == RETURN_INVALID_PARAMETER) {
  341. Ret = -2;
  342. } else if (Status == EFI_NOT_FOUND) {
  343. Ret = -7;
  344. } else {
  345. Ret = 0;
  346. }
  347. ZeroMem (&InitMmFoundationSvcArgs, sizeof(InitMmFoundationSvcArgs));
  348. InitArmSvcArgs (&InitMmFoundationSvcArgs, &Ret);
  349. DelegatedEventLoop (&InitMmFoundationSvcArgs);
  350. }