SecMain.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. /** @file
  2. C functions in SEC
  3. Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "SecMain.h"
  7. EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI gSecTemporaryRamSupportPpi = {
  8. SecTemporaryRamSupport
  9. };
  10. EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformationPpi[] = {
  11. {
  12. (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
  13. &gEfiTemporaryRamSupportPpiGuid,
  14. &gSecTemporaryRamSupportPpi
  15. }
  16. };
  17. //
  18. // These are IDT entries pointing to 10:FFFFFFE4h.
  19. //
  20. UINT64 mIdtEntryTemplate = 0xffff8e000010ffe4ULL;
  21. /**
  22. Caller provided function to be invoked at the end of InitializeDebugAgent().
  23. Entry point to the C language phase of SEC. After the SEC assembly
  24. code has initialized some temporary memory and set up the stack,
  25. the control is transferred to this function.
  26. @param[in] Context The first input parameter of InitializeDebugAgent().
  27. **/
  28. VOID
  29. EFIAPI
  30. SecStartupPhase2(
  31. IN VOID *Context
  32. );
  33. /**
  34. Entry point to the C language phase of SEC. After the SEC assembly
  35. code has initialized some temporary memory and set up the stack,
  36. the control is transferred to this function.
  37. @param SizeOfRam Size of the temporary memory available for use.
  38. @param TempRamBase Base address of temporary ram
  39. @param BootFirmwareVolume Base address of the Boot Firmware Volume.
  40. **/
  41. VOID
  42. EFIAPI
  43. SecStartup (
  44. IN UINT32 SizeOfRam,
  45. IN UINT32 TempRamBase,
  46. IN VOID *BootFirmwareVolume
  47. )
  48. {
  49. EFI_SEC_PEI_HAND_OFF SecCoreData;
  50. IA32_DESCRIPTOR IdtDescriptor;
  51. SEC_IDT_TABLE IdtTableInStack;
  52. UINT32 Index;
  53. UINT32 PeiStackSize;
  54. PeiStackSize = (SizeOfRam >> 1);
  55. ASSERT (PeiStackSize < SizeOfRam);
  56. //
  57. // Process all libraries constructor function linked to SecCore.
  58. //
  59. ProcessLibraryConstructorList ();
  60. //
  61. // Initialize floating point operating environment
  62. // to be compliant with UEFI spec.
  63. //
  64. InitializeFloatingPointUnits ();
  65. // |-------------------|---->
  66. // |Idt Table |
  67. // |-------------------|
  68. // |PeiService Pointer | PeiStackSize
  69. // |-------------------|
  70. // | |
  71. // | Stack |
  72. // |-------------------|---->
  73. // | |
  74. // | |
  75. // | Heap | PeiTemporaryRamSize
  76. // | |
  77. // | |
  78. // |-------------------|----> TempRamBase
  79. IdtTableInStack.PeiService = 0;
  80. for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) {
  81. CopyMem ((VOID*)&IdtTableInStack.IdtTable[Index], (VOID*)&mIdtEntryTemplate, sizeof (UINT64));
  82. }
  83. IdtDescriptor.Base = (UINTN) &IdtTableInStack.IdtTable;
  84. IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);
  85. AsmWriteIdtr (&IdtDescriptor);
  86. //
  87. // Update the base address and length of Pei temporary memory
  88. //
  89. SecCoreData.DataSize = (UINT16) sizeof (EFI_SEC_PEI_HAND_OFF);
  90. SecCoreData.BootFirmwareVolumeBase = BootFirmwareVolume;
  91. SecCoreData.BootFirmwareVolumeSize = (UINTN)(0x100000000ULL - (UINTN) BootFirmwareVolume);
  92. SecCoreData.TemporaryRamBase = (VOID*)(UINTN) TempRamBase;
  93. SecCoreData.TemporaryRamSize = SizeOfRam;
  94. SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
  95. SecCoreData.PeiTemporaryRamSize = SizeOfRam - PeiStackSize;
  96. SecCoreData.StackBase = (VOID*)(UINTN)(TempRamBase + SecCoreData.PeiTemporaryRamSize);
  97. SecCoreData.StackSize = PeiStackSize;
  98. //
  99. // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.
  100. //
  101. InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2);
  102. }
  103. /**
  104. Caller provided function to be invoked at the end of InitializeDebugAgent().
  105. Entry point to the C language phase of SEC. After the SEC assembly
  106. code has initialized some temporary memory and set up the stack,
  107. the control is transferred to this function.
  108. @param[in] Context The first input parameter of InitializeDebugAgent().
  109. **/
  110. VOID
  111. EFIAPI
  112. SecStartupPhase2(
  113. IN VOID *Context
  114. )
  115. {
  116. EFI_SEC_PEI_HAND_OFF *SecCoreData;
  117. EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint;
  118. SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context;
  119. //
  120. // Find Pei Core entry point. It will report SEC and Pei Core debug information if remote debug
  121. // is enabled.
  122. //
  123. FindAndReportEntryPoints ((EFI_FIRMWARE_VOLUME_HEADER *) SecCoreData->BootFirmwareVolumeBase, &PeiCoreEntryPoint);
  124. if (PeiCoreEntryPoint == NULL)
  125. {
  126. CpuDeadLoop ();
  127. }
  128. //
  129. // Transfer the control to the PEI core
  130. //
  131. ASSERT (PeiCoreEntryPoint != NULL);
  132. (*PeiCoreEntryPoint) (SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPeiSecPlatformInformationPpi);
  133. //
  134. // Should not come here.
  135. //
  136. return ;
  137. }
  138. /**
  139. This service of the TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into
  140. permanent memory.
  141. @param PeiServices Pointer to the PEI Services Table.
  142. @param TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the
  143. Temporary RAM contents.
  144. @param PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the
  145. Temporary RAM contents.
  146. @param CopySize Amount of memory to migrate from temporary to permanent memory.
  147. @retval EFI_SUCCESS The data was successfully returned.
  148. @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when
  149. TemporaryMemoryBase > PermanentMemoryBase.
  150. **/
  151. EFI_STATUS
  152. EFIAPI
  153. SecTemporaryRamSupport (
  154. IN CONST EFI_PEI_SERVICES **PeiServices,
  155. IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
  156. IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
  157. IN UINTN CopySize
  158. )
  159. {
  160. IA32_DESCRIPTOR IdtDescriptor;
  161. VOID* OldHeap;
  162. VOID* NewHeap;
  163. VOID* OldStack;
  164. VOID* NewStack;
  165. DEBUG_AGENT_CONTEXT_POSTMEM_SEC DebugAgentContext;
  166. BOOLEAN OldStatus;
  167. UINTN PeiStackSize;
  168. PeiStackSize = (CopySize >> 1);
  169. ASSERT (PeiStackSize < CopySize);
  170. //
  171. // |-------------------|---->
  172. // | Stack | PeiStackSize
  173. // |-------------------|---->
  174. // | Heap | PeiTemporaryRamSize
  175. // |-------------------|----> TempRamBase
  176. //
  177. // |-------------------|---->
  178. // | Heap | PeiTemporaryRamSize
  179. // |-------------------|---->
  180. // | Stack | PeiStackSize
  181. // |-------------------|----> PermanentMemoryBase
  182. //
  183. OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;
  184. NewHeap = (VOID*)((UINTN)PermanentMemoryBase + PeiStackSize);
  185. OldStack = (VOID*)((UINTN)TemporaryMemoryBase + CopySize - PeiStackSize);
  186. NewStack = (VOID*)(UINTN)PermanentMemoryBase;
  187. DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap;
  188. DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack;
  189. OldStatus = SaveAndSetDebugTimerInterrupt (FALSE);
  190. //
  191. // Initialize Debug Agent to support source level debug in PEI phase after memory ready.
  192. // It will build HOB and fix up the pointer in IDT table.
  193. //
  194. InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *) &DebugAgentContext, NULL);
  195. //
  196. // Migrate Heap
  197. //
  198. CopyMem (NewHeap, OldHeap, CopySize - PeiStackSize);
  199. //
  200. // Migrate Stack
  201. //
  202. CopyMem (NewStack, OldStack, PeiStackSize);
  203. //
  204. // We need *not* fix the return address because currently,
  205. // The PeiCore is executed in flash.
  206. //
  207. //
  208. // Rebase IDT table in permanent memory
  209. //
  210. AsmReadIdtr (&IdtDescriptor);
  211. IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;
  212. AsmWriteIdtr (&IdtDescriptor);
  213. //
  214. // Program MTRR
  215. //
  216. //
  217. // SecSwitchStack function must be invoked after the memory migration
  218. // immediately, also we need fixup the stack change caused by new call into
  219. // permanent memory.
  220. //
  221. SecSwitchStack (
  222. (UINT32) (UINTN) OldStack,
  223. (UINT32) (UINTN) NewStack
  224. );
  225. SaveAndSetDebugTimerInterrupt (OldStatus);
  226. return EFI_SUCCESS;
  227. }