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
17EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI gSecTemporaryRamSupportPpi = {
18  SecTemporaryRamSupport
19};
20
21EFI_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//
32UINT64  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 temporary 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**/
51VOID
52EFIAPI
53SecStartup (
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**/
151EFI_STATUS
152EFIAPI
153SecTemporaryRamSupport (
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  // immediately, also we need fixup the stack change caused by new call into
204  // permanent memory.
205  //
206  SecSwitchStack (
207    (UINT32) (UINTN) OldStack,
208    (UINT32) (UINTN) NewStack
209    );
210
211  return EFI_SUCCESS;
212}
213