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