]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFspPkg/FspSecCore/SecFsp.c
IntelFspPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / IntelFspPkg / FspSecCore / SecFsp.c
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 "SecFsp.h"
9
10 /**
11
12 Calculate the FSP IDT gate descriptor.
13
14 @param[in] IdtEntryTemplate IDT gate descriptor template.
15
16 @return FSP specific IDT gate descriptor.
17
18 **/
19 UINT64
20 FspGetExceptionHandler(
21 IN UINT64 IdtEntryTemplate
22 )
23 {
24 UINT32 Entry;
25 UINT64 ExceptionHandler;
26 IA32_IDT_GATE_DESCRIPTOR *IdtGateDescriptor;
27 FSP_INFO_HEADER *FspInfoHeader;
28
29 FspInfoHeader = (FSP_INFO_HEADER *)AsmGetFspInfoHeader();
30 ExceptionHandler = IdtEntryTemplate;
31 IdtGateDescriptor = (IA32_IDT_GATE_DESCRIPTOR *)&ExceptionHandler;
32 Entry = (IdtGateDescriptor->Bits.OffsetHigh << 16) | IdtGateDescriptor->Bits.OffsetLow;
33 Entry = FspInfoHeader->ImageBase + FspInfoHeader->ImageSize - (~Entry + 1);
34 IdtGateDescriptor->Bits.OffsetHigh = (UINT16)(Entry >> 16);
35 IdtGateDescriptor->Bits.OffsetLow = (UINT16)Entry;
36
37 return ExceptionHandler;
38 }
39
40 /**
41 This function gets the FSP UPD region offset in flash.
42
43 @return the offset of the UPD region.
44
45 **/
46 UINT32
47 EFIAPI
48 GetFspUpdRegionOffset (
49 VOID
50 )
51 {
52 FSP_GLOBAL_DATA *FspData;
53 UINT32 *Offset;
54
55 FspData = GetFspGlobalDataPointer ();
56
57 //
58 // It is required to put PcdUpdRegionOffset at offset 0x000C
59 // for all FSPs.
60 // gPlatformFspPkgTokenSpaceGuid.PcdUpdRegionOffset | 0x000C | 0x12345678
61 //
62 Offset = (UINT32 *)(FspData->FspInfoHeader->ImageBase + \
63 FspData->FspInfoHeader->CfgRegionOffset + 0x0C);
64
65 return *Offset;
66 }
67
68 /**
69 This interface fills platform specific data.
70
71 @param[in,out] FspData Pointer to the FSP global data.
72
73 **/
74 VOID
75 EFIAPI
76 SecGetPlatformData (
77 IN OUT FSP_GLOBAL_DATA *FspData
78 )
79 {
80 FSP_PLAT_DATA *FspPlatformData;
81 UINT32 TopOfCar;
82 UINT32 *StackPtr;
83 UINT32 DwordSize;
84
85 FspPlatformData = &FspData->PlatformData;
86
87 //
88 // The entries of platform information, together with the number of them,
89 // reside in the bottom of stack, left untouched by normal stack operation.
90 //
91 TopOfCar = PcdGet32 (PcdTemporaryRamBase) + PcdGet32 (PcdTemporaryRamSize);
92
93 FspPlatformData->DataPtr = NULL;
94 FspPlatformData->MicrocodeRegionBase = 0;
95 FspPlatformData->MicrocodeRegionSize = 0;
96 FspPlatformData->CodeRegionBase = 0;
97 FspPlatformData->CodeRegionSize = 0;
98
99 //
100 // Pointer to the size field
101 //
102 StackPtr = (UINT32 *)(TopOfCar - sizeof(UINT32));
103
104 while (*StackPtr != 0) {
105 if (*(StackPtr - 1) == FSP_MCUD_SIGNATURE) {
106 //
107 // This following data was pushed onto stack after TempRamInit API
108 //
109 DwordSize = 4;
110 StackPtr = StackPtr - 1 - DwordSize;
111 CopyMem (&(FspPlatformData->MicrocodeRegionBase), StackPtr, (DwordSize << 2));
112 StackPtr--;
113 } else if (*(StackPtr - 1) == FSP_PER0_SIGNATURE) {
114 //
115 // This is the performance data for InitTempMemory API entry/exit
116 //
117 DwordSize = 4;
118 StackPtr = StackPtr - 1 - DwordSize;
119 CopyMem (FspData->PerfData, StackPtr, (DwordSize << 2));
120 ((UINT8 *)(&FspData->PerfData[0]))[7] = FSP_PERF_ID_API_TMPRAMINIT_ENTRY;
121 ((UINT8 *)(&FspData->PerfData[1]))[7] = FSP_PERF_ID_API_TMPRAMINIT_EXIT;
122 StackPtr--;
123 } else {
124 StackPtr -= (*StackPtr);
125 }
126 }
127 }
128
129 /**
130
131 Initialize the FSP global data region.
132 It needs to be done as soon as possible after the stack is setup.
133
134 @param[in,out] PeiFspData Pointer of the FSP global data.
135 @param[in] BootLoaderStack BootLoader stack.
136 @param[in] ApiIdx The index of the FSP API.
137
138 **/
139 VOID
140 FspGlobalDataInit (
141 IN OUT FSP_GLOBAL_DATA *PeiFspData,
142 IN UINT32 BootLoaderStack,
143 IN UINT8 ApiIdx
144 )
145 {
146 VOID *UpdDataRgnPtr;
147 FSP_INIT_PARAMS *FspInitParams;
148 CHAR8 ImageId[9];
149 UINTN Idx;
150
151 //
152 // Init PCIE_BAR with value and set global FSP data pointer.
153 // PciExpress Base should have been programmed by platform already.
154 //
155 SetFspGlobalDataPointer (PeiFspData);
156 ZeroMem ((VOID *)PeiFspData, sizeof(FSP_GLOBAL_DATA));
157
158 PeiFspData->Signature = FSP_GLOBAL_DATA_SIGNATURE;
159 PeiFspData->CoreStack = BootLoaderStack;
160 PeiFspData->PerfIdx = 2;
161
162 SetFspMeasurePoint (FSP_PERF_ID_API_FSPINIT_ENTRY);
163
164 //
165 // Get FSP Header offset
166 // It may have multiple FVs, so look into the last one for FSP header
167 //
168 PeiFspData->FspInfoHeader = (FSP_INFO_HEADER *)AsmGetFspInfoHeader();
169 SecGetPlatformData (PeiFspData);
170
171 //
172 // Set API calling mode
173 //
174 SetFspApiCallingMode (ApiIdx == 1 ? 0 : 1);
175
176 //
177 // Initialize UPD pointer.
178 //
179 FspInitParams = (FSP_INIT_PARAMS *)GetFspApiParameter ();
180 UpdDataRgnPtr = ((FSP_INIT_RT_COMMON_BUFFER *)FspInitParams->RtBufferPtr)->UpdDataRgnPtr;
181 if (UpdDataRgnPtr == NULL) {
182 UpdDataRgnPtr = (VOID *)(PeiFspData->FspInfoHeader->ImageBase + GetFspUpdRegionOffset());
183 }
184 SetFspUpdDataPointer (UpdDataRgnPtr);
185
186 //
187 // Initialize serial port
188 // It might have been done in ProcessLibraryConstructorList(), however,
189 // the FSP global data is not initialized at that time. So do it again
190 // for safe.
191 //
192 SerialPortInitialize ();
193
194 //
195 // Ensure the golbal data pointer is valid
196 //
197 ASSERT (GetFspGlobalDataPointer () == PeiFspData);
198
199 for (Idx = 0; Idx < 8; Idx++) {
200 ImageId[Idx] = PeiFspData->FspInfoHeader->ImageId[Idx];
201 }
202 ImageId[Idx] = 0;
203
204 DEBUG ((DEBUG_INFO | DEBUG_INIT, "\n============= PEIM FSP v1.%x (%a v%x.%x.%x.%x) =============\n", \
205 PeiFspData->FspInfoHeader->HeaderRevision - 1, \
206 ImageId, \
207 (PeiFspData->FspInfoHeader->ImageRevision >> 24) & 0xff, \
208 (PeiFspData->FspInfoHeader->ImageRevision >> 16) & 0xff, \
209 (PeiFspData->FspInfoHeader->ImageRevision >> 8) & 0xff, \
210 (PeiFspData->FspInfoHeader->ImageRevision >> 0) & 0xff));
211
212 }
213
214 /**
215
216 Adjust the FSP data pointers after the stack is migrated to memory.
217
218 @param[in] OffsetGap The offset gap between the old stack and the new stack.
219
220 **/
221 VOID
222 FspDataPointerFixUp (
223 IN UINT32 OffsetGap
224 )
225 {
226 FSP_GLOBAL_DATA *NewFspData;
227
228 NewFspData = (FSP_GLOBAL_DATA *)((UINTN)GetFspGlobalDataPointer() + (UINTN)OffsetGap);
229 SetFspGlobalDataPointer (NewFspData);
230 }
231
232 /**
233 This function check the FSP API calling condition.
234
235 @param[in] ApiIdx Internal index of the FSP API.
236 @param[in] ApiParam Parameter of the FSP API.
237
238 **/
239 EFI_STATUS
240 EFIAPI
241 FspApiCallingCheck (
242 IN UINT32 ApiIdx,
243 IN VOID *ApiParam
244 )
245 {
246 EFI_STATUS Status;
247 FSP_GLOBAL_DATA *FspData;
248 FSP_INIT_PARAMS *FspInitParams;
249 FSP_INIT_RT_COMMON_BUFFER *FspRtBuffer;
250
251 FspInitParams = (FSP_INIT_PARAMS *) ApiParam;
252 FspRtBuffer = ((FSP_INIT_RT_COMMON_BUFFER *)FspInitParams->RtBufferPtr);
253
254 Status = EFI_SUCCESS;
255 FspData = GetFspGlobalDataPointer ();
256 if (ApiIdx == 1) {
257 //
258 // FspInit check
259 //
260 if ((UINT32)FspData != 0xFFFFFFFF) {
261 Status = EFI_UNSUPPORTED;
262 } else if ((FspRtBuffer == NULL) || ((FspRtBuffer->BootLoaderTolumSize % EFI_PAGE_SIZE) != 0) || (EFI_ERROR(FspUpdSignatureCheck(ApiIdx, ApiParam)))) {
263 Status = EFI_INVALID_PARAMETER;
264 }
265 } else if (ApiIdx == 2) {
266 //
267 // NotifyPhase check
268 //
269 if ((FspData == NULL) || ((UINT32)FspData == 0xFFFFFFFF)) {
270 Status = EFI_UNSUPPORTED;
271 } else {
272 if (FspData->Signature != FSP_GLOBAL_DATA_SIGNATURE) {
273 Status = EFI_UNSUPPORTED;
274 }
275 }
276 } else if (ApiIdx == 3) {
277 //
278 // FspMemoryInit check
279 //
280 if ((UINT32)FspData != 0xFFFFFFFF) {
281 Status = EFI_UNSUPPORTED;
282 } else if ((FspRtBuffer == NULL) || ((FspRtBuffer->BootLoaderTolumSize % EFI_PAGE_SIZE) != 0) || (EFI_ERROR(FspUpdSignatureCheck(ApiIdx, ApiParam)))) {
283 Status = EFI_INVALID_PARAMETER;
284 }
285 } else if (ApiIdx == 4) {
286 //
287 // TempRamExit check
288 //
289 if ((FspData == NULL) || ((UINT32)FspData == 0xFFFFFFFF)) {
290 Status = EFI_UNSUPPORTED;
291 } else {
292 if (FspData->Signature != FSP_GLOBAL_DATA_SIGNATURE) {
293 Status = EFI_UNSUPPORTED;
294 }
295 }
296 } else if (ApiIdx == 5) {
297 //
298 // FspSiliconInit check
299 //
300 if ((FspData == NULL) || ((UINT32)FspData == 0xFFFFFFFF)) {
301 Status = EFI_UNSUPPORTED;
302 } else {
303 if (FspData->Signature != FSP_GLOBAL_DATA_SIGNATURE) {
304 Status = EFI_UNSUPPORTED;
305 } else if (EFI_ERROR(FspUpdSignatureCheck(ApiIdx, ApiParam))) {
306 Status = EFI_INVALID_PARAMETER;
307 }
308 }
309 } else {
310 Status = EFI_UNSUPPORTED;
311 }
312
313 return Status;
314 }
315
316 /**
317 This function gets the boot FV offset in FSP.
318 @return the boot firmware volumen offset inside FSP binary
319
320 **/
321 UINT32
322 EFIAPI
323 GetBootFirmwareVolumeOffset (
324 VOID
325 )
326 {
327 return PcdGet32 (PcdFspBootFirmwareVolumeBase) - PcdGet32 (PcdFspAreaBaseAddress);
328 }