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