]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
MdeModulePkg/PeiCore: Enable T-RAM evacuation in PeiCore (CVE-2019-11098)
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Dispatcher / Dispatcher.c
CommitLineData
615c6dd0 1/** @file\r
b1f6a7c6 2 EFI PEI Core dispatch services\r
d1102dba 3\r
d39d1260 4Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
d7bd924f 5(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
9d510e61 6SPDX-License-Identifier: BSD-2-Clause-Patent\r
192f6d4c 7\r
615c6dd0 8**/\r
192f6d4c 9\r
0d516397 10#include "PeiMain.h"\r
192f6d4c 11\r
b1f6a7c6 12/**\r
b0d803fe 13\r
d39d1260 14 Discover all PEIMs and optional Apriori file in one FV. There is at most one\r
b0d803fe 15 Apriori file in one FV.\r
16\r
b0d803fe 17\r
3b428ade 18 @param Private Pointer to the private data passed in from caller\r
19 @param CoreFileHandle The instance of PEI_CORE_FV_HANDLE.\r
b0d803fe 20\r
b1f6a7c6 21**/\r
22VOID\r
23DiscoverPeimsAndOrderWithApriori (\r
24 IN PEI_CORE_INSTANCE *Private,\r
3b428ade 25 IN PEI_CORE_FV_HANDLE *CoreFileHandle\r
b1f6a7c6 26 )\r
b0d803fe 27{\r
28 EFI_STATUS Status;\r
890e5417 29 EFI_PEI_FILE_HANDLE FileHandle;\r
177aabe6 30 EFI_PEI_FILE_HANDLE AprioriFileHandle;\r
b0d803fe 31 EFI_GUID *Apriori;\r
32 UINTN Index;\r
33 UINTN Index2;\r
34 UINTN PeimIndex;\r
35 UINTN PeimCount;\r
36 EFI_GUID *Guid;\r
fe781940 37 EFI_PEI_FILE_HANDLE *TempFileHandles;\r
b62fe570 38 EFI_GUID *TempFileGuid;\r
3b428ade 39 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;\r
40 EFI_FV_FILE_INFO FileInfo;\r
d1102dba 41\r
3b428ade 42 FvPpi = CoreFileHandle->FvPpi;\r
d1102dba 43\r
b0d803fe 44 //\r
45 // Walk the FV and find all the PEIMs and the Apriori file.\r
46 //\r
47 AprioriFileHandle = NULL;\r
b62fe570 48 Private->CurrentFvFileHandles = NULL;\r
b0d803fe 49 Guid = NULL;\r
b0d803fe 50\r
51 //\r
d39d1260 52 // If the current FV has been scanned, directly get its cached records.\r
b0d803fe 53 //\r
b62fe570
SZ
54 if (CoreFileHandle->ScanFv) {\r
55 Private->CurrentFvFileHandles = CoreFileHandle->FvFileHandles;\r
b0d803fe 56 return;\r
57 }\r
58\r
b62fe570
SZ
59 TempFileHandles = Private->TempFileHandles;\r
60 TempFileGuid = Private->TempFileGuid;\r
61\r
b0d803fe 62 //\r
d39d1260 63 // Go ahead to scan this FV, get PeimCount and cache FileHandles within it to TempFileHandles.\r
b0d803fe 64 //\r
b62fe570
SZ
65 PeimCount = 0;\r
66 FileHandle = NULL;\r
67 do {\r
3b428ade 68 Status = FvPpi->FindFileByType (FvPpi, PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE, CoreFileHandle->FvHandle, &FileHandle);\r
b62fe570
SZ
69 if (!EFI_ERROR (Status)) {\r
70 if (PeimCount >= Private->TempPeimCount) {\r
71 //\r
72 // Run out of room, grow the buffer.\r
73 //\r
74 TempFileHandles = AllocatePool (\r
75 sizeof (EFI_PEI_FILE_HANDLE) * (Private->TempPeimCount + TEMP_FILE_GROWTH_STEP));\r
76 ASSERT (TempFileHandles != NULL);\r
77 CopyMem (\r
78 TempFileHandles,\r
79 Private->TempFileHandles,\r
80 sizeof (EFI_PEI_FILE_HANDLE) * Private->TempPeimCount\r
81 );\r
82 Private->TempFileHandles = TempFileHandles;\r
83 TempFileGuid = AllocatePool (\r
84 sizeof (EFI_GUID) * (Private->TempPeimCount + TEMP_FILE_GROWTH_STEP));\r
85 ASSERT (TempFileGuid != NULL);\r
86 CopyMem (\r
87 TempFileGuid,\r
88 Private->TempFileGuid,\r
89 sizeof (EFI_GUID) * Private->TempPeimCount\r
90 );\r
91 Private->TempFileGuid = TempFileGuid;\r
92 Private->TempPeimCount = Private->TempPeimCount + TEMP_FILE_GROWTH_STEP;\r
93 }\r
94\r
95 TempFileHandles[PeimCount++] = FileHandle;\r
b0d803fe 96 }\r
b62fe570
SZ
97 } while (!EFI_ERROR (Status));\r
98\r
99 DEBUG ((\r
100 DEBUG_INFO,\r
101 "%a(): Found 0x%x PEI FFS files in the %dth FV\n",\r
102 __FUNCTION__,\r
103 PeimCount,\r
104 Private->CurrentPeimFvCount\r
105 ));\r
58dcdada 106\r
b62fe570
SZ
107 if (PeimCount == 0) {\r
108 //\r
109 // No PEIM FFS file is found, set ScanFv flag and return.\r
110 //\r
111 CoreFileHandle->ScanFv = TRUE;\r
112 return;\r
b0d803fe 113 }\r
9b8e61be 114\r
97b2c9b5 115 //\r
b62fe570 116 // Record PeimCount, allocate buffer for PeimState and FvFileHandles.\r
97b2c9b5 117 //\r
b62fe570
SZ
118 CoreFileHandle->PeimCount = PeimCount;\r
119 CoreFileHandle->PeimState = AllocateZeroPool (sizeof (UINT8) * PeimCount);\r
120 ASSERT (CoreFileHandle->PeimState != NULL);\r
121 CoreFileHandle->FvFileHandles = AllocateZeroPool (sizeof (EFI_PEI_FILE_HANDLE) * PeimCount);\r
122 ASSERT (CoreFileHandle->FvFileHandles != NULL);\r
b0d803fe 123\r
3b428ade 124 //\r
125 // Get Apriori File handle\r
126 //\r
58dcdada 127 Private->AprioriCount = 0;\r
3b428ade 128 Status = FvPpi->FindFileByName (FvPpi, &gPeiAprioriFileNameGuid, &CoreFileHandle->FvHandle, &AprioriFileHandle);\r
129 if (!EFI_ERROR(Status) && AprioriFileHandle != NULL) {\r
b0d803fe 130 //\r
131 // Read the Apriori file\r
132 //\r
3b428ade 133 Status = FvPpi->FindSectionByType (FvPpi, EFI_SECTION_RAW, AprioriFileHandle, (VOID **) &Apriori);\r
b0d803fe 134 if (!EFI_ERROR (Status)) {\r
135 //\r
b62fe570 136 // Calculate the number of PEIMs in the Apriori file\r
b0d803fe 137 //\r
3b428ade 138 Status = FvPpi->GetFileInfo (FvPpi, AprioriFileHandle, &FileInfo);\r
139 ASSERT_EFI_ERROR (Status);\r
890e5417
SZ
140 Private->AprioriCount = FileInfo.BufferSize;\r
141 if (IS_SECTION2 (FileInfo.Buffer)) {\r
142 Private->AprioriCount -= sizeof (EFI_COMMON_SECTION_HEADER2);\r
143 } else {\r
144 Private->AprioriCount -= sizeof (EFI_COMMON_SECTION_HEADER);\r
145 }\r
b0d803fe 146 Private->AprioriCount /= sizeof (EFI_GUID);\r
58dcdada 147\r
b0d803fe 148 for (Index = 0; Index < PeimCount; Index++) {\r
149 //\r
d39d1260 150 // Make an array of file name GUIDs that matches the FileHandle array so we can convert\r
b0d803fe 151 // quickly from file name to file handle\r
152 //\r
b62fe570
SZ
153 Status = FvPpi->GetFileInfo (FvPpi, TempFileHandles[Index], &FileInfo);\r
154 ASSERT_EFI_ERROR (Status);\r
155 CopyMem (&TempFileGuid[Index], &FileInfo.FileName, sizeof(EFI_GUID));\r
b0d803fe 156 }\r
157\r
158 //\r
d39d1260 159 // Walk through TempFileGuid array to find out who is invalid PEIM GUID in Apriori file.\r
b62fe570 160 // Add available PEIMs in Apriori file into FvFileHandles array.\r
b0d803fe 161 //\r
b62fe570
SZ
162 Index = 0;\r
163 for (Index2 = 0; Index2 < Private->AprioriCount; Index2++) {\r
164 Guid = ScanGuid (TempFileGuid, PeimCount * sizeof (EFI_GUID), &Apriori[Index2]);\r
165 if (Guid != NULL) {\r
166 PeimIndex = ((UINTN)Guid - (UINTN)&TempFileGuid[0])/sizeof (EFI_GUID);\r
167 CoreFileHandle->FvFileHandles[Index++] = TempFileHandles[PeimIndex];\r
b0d803fe 168\r
b62fe570
SZ
169 //\r
170 // Since we have copied the file handle we can remove it from this list.\r
171 //\r
172 TempFileHandles[PeimIndex] = NULL;\r
173 }\r
b0d803fe 174 }\r
175\r
176 //\r
b62fe570 177 // Update valid AprioriCount\r
b0d803fe 178 //\r
179 Private->AprioriCount = Index;\r
58dcdada 180\r
b0d803fe 181 //\r
182 // Add in any PEIMs not in the Apriori file\r
183 //\r
b62fe570
SZ
184 for (Index2 = 0; Index2 < PeimCount; Index2++) {\r
185 if (TempFileHandles[Index2] != NULL) {\r
186 CoreFileHandle->FvFileHandles[Index++] = TempFileHandles[Index2];\r
187 TempFileHandles[Index2] = NULL;\r
b0d803fe 188 }\r
189 }\r
b62fe570 190 ASSERT (Index == PeimCount);\r
b0d803fe 191 }\r
b62fe570
SZ
192 } else {\r
193 CopyMem (CoreFileHandle->FvFileHandles, TempFileHandles, sizeof (EFI_PEI_FILE_HANDLE) * PeimCount);\r
b0d803fe 194 }\r
b62fe570 195\r
b0d803fe 196 //\r
d39d1260
MK
197 // The current FV File Handles have been cached. So that we don't have to scan the FV again.\r
198 // Instead, we can retrieve the file handles within this FV from cached records.\r
b0d803fe 199 //\r
b62fe570
SZ
200 CoreFileHandle->ScanFv = TRUE;\r
201 Private->CurrentFvFileHandles = CoreFileHandle->FvFileHandles;\r
58dcdada 202}\r
203\r
54ea99a7 204//\r
205// This is the minimum memory required by DxeCore initialization. When LMFA feature enabled,\r
d1102dba 206// This part of memory still need reserved on the very top of memory so that the DXE Core could\r
54ea99a7 207// use these memory for data initialization. This macro should be sync with the same marco\r
208// defined in DXE Core.\r
209//\r
210#define MINIMUM_INITIAL_MEMORY_SIZE 0x10000\r
9bfb4940 211/**\r
d1102dba
LG
212 This function is to test if the memory range described in resource HOB is available or not.\r
213\r
214 This function should only be invoked when Loading Module at Fixed Address(LMFA) feature is enabled. Some platform may allocate the\r
9bfb4940 215 memory before PeiLoadFixAddressHook in invoked. so this function is to test if the memory range described by the input resource HOB is\r
216 available or not.\r
217\r
218 @param PrivateData Pointer to the private data passed in from caller\r
219 @param ResourceHob Pointer to a resource HOB which described the memory range described by the input resource HOB\r
220**/\r
221BOOLEAN\r
222PeiLoadFixAddressIsMemoryRangeAvailable (\r
223 IN PEI_CORE_INSTANCE *PrivateData,\r
224 IN EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob\r
225 )\r
226{\r
d1102dba
LG
227 EFI_HOB_MEMORY_ALLOCATION *MemoryHob;\r
228 BOOLEAN IsAvailable;\r
229 EFI_PEI_HOB_POINTERS Hob;\r
230\r
9bfb4940 231 IsAvailable = TRUE;\r
d1102dba
LG
232 if (PrivateData == NULL || ResourceHob == NULL) {\r
233 return FALSE;\r
234 }\r
235 //\r
9bfb4940 236 // test if the memory range describe in the HOB is already allocated.\r
237 //\r
238 for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
9bfb4940 239 //\r
d1102dba
LG
240 // See if this is a memory allocation HOB\r
241 //\r
242 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {\r
9bfb4940 243 MemoryHob = Hob.MemoryAllocation;\r
d1102dba 244 if(MemoryHob->AllocDescriptor.MemoryBaseAddress == ResourceHob->PhysicalStart &&\r
9bfb4940 245 MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength == ResourceHob->PhysicalStart + ResourceHob->ResourceLength) {\r
246 IsAvailable = FALSE;\r
d1102dba 247 break;\r
9bfb4940 248 }\r
249 }\r
250 }\r
d1102dba 251\r
9bfb4940 252 return IsAvailable;\r
d1102dba 253\r
9bfb4940 254}\r
54ea99a7 255/**\r
256 Hook function for Loading Module at Fixed Address feature\r
d1102dba 257\r
54ea99a7 258 This function should only be invoked when Loading Module at Fixed Address(LMFA) feature is enabled. When feature is\r
d1102dba 259 configured as Load Modules at Fix Absolute Address, this function is to validate the top address assigned by user. When\r
93b8ed68 260 feature is configured as Load Modules at Fixed Offset, the function is to find the top address which is TOLM-TSEG in general.\r
d1102dba 261 And also the function will re-install PEI memory.\r
b0d803fe 262\r
54ea99a7 263 @param PrivateData Pointer to the private data passed in from caller\r
264\r
265**/\r
266VOID\r
267PeiLoadFixAddressHook(\r
268 IN PEI_CORE_INSTANCE *PrivateData\r
269 )\r
270{\r
271 EFI_PHYSICAL_ADDRESS TopLoadingAddress;\r
272 UINT64 PeiMemorySize;\r
273 UINT64 TotalReservedMemorySize;\r
274 UINT64 MemoryRangeEnd;\r
d1102dba 275 EFI_PHYSICAL_ADDRESS HighAddress;\r
54ea99a7 276 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;\r
277 EFI_HOB_RESOURCE_DESCRIPTOR *NextResourceHob;\r
278 EFI_HOB_RESOURCE_DESCRIPTOR *CurrentResourceHob;\r
279 EFI_PEI_HOB_POINTERS CurrentHob;\r
280 EFI_PEI_HOB_POINTERS Hob;\r
281 EFI_PEI_HOB_POINTERS NextHob;\r
9bfb4940 282 EFI_HOB_MEMORY_ALLOCATION *MemoryHob;\r
54ea99a7 283 //\r
284 // Initialize Local Variables\r
285 //\r
286 CurrentResourceHob = NULL;\r
287 ResourceHob = NULL;\r
288 NextResourceHob = NULL;\r
54ea99a7 289 HighAddress = 0;\r
290 TopLoadingAddress = 0;\r
291 MemoryRangeEnd = 0;\r
292 CurrentHob.Raw = PrivateData->HobList.Raw;\r
293 PeiMemorySize = PrivateData->PhysicalMemoryLength;\r
294 //\r
295 // The top reserved memory include 3 parts: the topest range is for DXE core initialization with the size MINIMUM_INITIAL_MEMORY_SIZE\r
296 // then RuntimeCodePage range and Boot time code range.\r
d1102dba 297 //\r
e18fa167 298 TotalReservedMemorySize = MINIMUM_INITIAL_MEMORY_SIZE + EFI_PAGES_TO_SIZE(PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber));\r
d1102dba 299 TotalReservedMemorySize+= EFI_PAGES_TO_SIZE(PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber)) ;\r
54ea99a7 300 //\r
301 // PEI memory range lies below the top reserved memory\r
d1102dba 302 //\r
54ea99a7 303 TotalReservedMemorySize += PeiMemorySize;\r
d1102dba 304\r
852081fc 305 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressRuntimeCodePageNumber= 0x%x.\n", PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber)));\r
306 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressBootTimeCodePageNumber= 0x%x.\n", PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber)));\r
d1102dba 307 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressPeiCodePageNumber= 0x%x.\n", PcdGet32(PcdLoadFixAddressPeiCodePageNumber)));\r
852081fc 308 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: Total Reserved Memory Size = 0x%lx.\n", TotalReservedMemorySize));\r
54ea99a7 309 //\r
d39d1260 310 // Loop through the system memory typed HOB to merge the adjacent memory range\r
54ea99a7 311 //\r
312 for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
d1102dba
LG
313 //\r
314 // See if this is a resource descriptor HOB\r
54ea99a7 315 //\r
316 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
d1102dba
LG
317\r
318 ResourceHob = Hob.ResourceDescriptor;\r
54ea99a7 319 //\r
d39d1260 320 // If range described in this HOB is not system memory or higher than MAX_ADDRESS, ignored.\r
54ea99a7 321 //\r
63e70348 322 if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY ||\r
54ea99a7 323 ResourceHob->PhysicalStart + ResourceHob->ResourceLength > MAX_ADDRESS) {\r
324 continue;\r
d1102dba
LG
325 }\r
326\r
327 for (NextHob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(NextHob); NextHob.Raw = GET_NEXT_HOB(NextHob)) {\r
54ea99a7 328 if (NextHob.Raw == Hob.Raw){\r
329 continue;\r
d1102dba 330 }\r
54ea99a7 331 //\r
332 // See if this is a resource descriptor HOB\r
333 //\r
334 if (GET_HOB_TYPE (NextHob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
d1102dba 335\r
54ea99a7 336 NextResourceHob = NextHob.ResourceDescriptor;\r
337 //\r
338 // test if range described in this NextResourceHob is system memory and have the same attribute.\r
339 // Note: Here is a assumption that system memory should always be healthy even without test.\r
d1102dba 340 //\r
54ea99a7 341 if (NextResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&\r
342 (((NextResourceHob->ResourceAttribute^ResourceHob->ResourceAttribute)&(~EFI_RESOURCE_ATTRIBUTE_TESTED)) == 0)){\r
d1102dba 343\r
54ea99a7 344 //\r
345 // See if the memory range described in ResourceHob and NextResourceHob is adjacent\r
346 //\r
d1102dba
LG
347 if ((ResourceHob->PhysicalStart <= NextResourceHob->PhysicalStart &&\r
348 ResourceHob->PhysicalStart + ResourceHob->ResourceLength >= NextResourceHob->PhysicalStart)||\r
54ea99a7 349 (ResourceHob->PhysicalStart >= NextResourceHob->PhysicalStart&&\r
350 ResourceHob->PhysicalStart <= NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength)) {\r
d1102dba 351\r
54ea99a7 352 MemoryRangeEnd = ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength)>(NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength)) ?\r
353 (ResourceHob->PhysicalStart + ResourceHob->ResourceLength):(NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength);\r
d1102dba
LG
354\r
355 ResourceHob->PhysicalStart = (ResourceHob->PhysicalStart < NextResourceHob->PhysicalStart) ?\r
54ea99a7 356 ResourceHob->PhysicalStart : NextResourceHob->PhysicalStart;\r
d1102dba
LG
357\r
358\r
54ea99a7 359 ResourceHob->ResourceLength = (MemoryRangeEnd - ResourceHob->PhysicalStart);\r
d1102dba 360\r
54ea99a7 361 ResourceHob->ResourceAttribute = ResourceHob->ResourceAttribute & (~EFI_RESOURCE_ATTRIBUTE_TESTED);\r
362 //\r
363 // Delete the NextResourceHob by marking it as unused.\r
364 //\r
365 GET_HOB_TYPE (NextHob) = EFI_HOB_TYPE_UNUSED;\r
d1102dba 366\r
54ea99a7 367 }\r
368 }\r
d1102dba 369 }\r
54ea99a7 370 }\r
d1102dba 371 }\r
54ea99a7 372 }\r
9bfb4940 373 //\r
374 // Some platform is already allocated pages before the HOB re-org. Here to build dedicated resource HOB to describe\r
375 // the allocated memory range\r
376 //\r
377 for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
d1102dba
LG
378 //\r
379 // See if this is a memory allocation HOB\r
9bfb4940 380 //\r
381 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {\r
382 MemoryHob = Hob.MemoryAllocation;\r
383 for (NextHob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(NextHob); NextHob.Raw = GET_NEXT_HOB(NextHob)) {\r
384 //\r
385 // See if this is a resource descriptor HOB\r
386 //\r
387 if (GET_HOB_TYPE (NextHob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
d1102dba 388 NextResourceHob = NextHob.ResourceDescriptor;\r
9bfb4940 389 //\r
d39d1260 390 // If range described in this HOB is not system memory or higher than MAX_ADDRESS, ignored.\r
9bfb4940 391 //\r
63e70348 392 if (NextResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY || NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength > MAX_ADDRESS) {\r
9bfb4940 393 continue;\r
394 }\r
395 //\r
d39d1260 396 // If the range describe in memory allocation HOB belongs to the memory range described by the resource HOB\r
d1102dba
LG
397 //\r
398 if (MemoryHob->AllocDescriptor.MemoryBaseAddress >= NextResourceHob->PhysicalStart &&\r
9bfb4940 399 MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength <= NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength) {\r
400 //\r
d39d1260 401 // Build separate resource HOB for this allocated range\r
d1102dba 402 //\r
9bfb4940 403 if (MemoryHob->AllocDescriptor.MemoryBaseAddress > NextResourceHob->PhysicalStart) {\r
404 BuildResourceDescriptorHob (\r
d1102dba 405 EFI_RESOURCE_SYSTEM_MEMORY,\r
9bfb4940 406 NextResourceHob->ResourceAttribute,\r
d1102dba
LG
407 NextResourceHob->PhysicalStart,\r
408 (MemoryHob->AllocDescriptor.MemoryBaseAddress - NextResourceHob->PhysicalStart)\r
9bfb4940 409 );\r
410 }\r
411 if (MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength < NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength) {\r
412 BuildResourceDescriptorHob (\r
d1102dba 413 EFI_RESOURCE_SYSTEM_MEMORY,\r
9bfb4940 414 NextResourceHob->ResourceAttribute,\r
d1102dba
LG
415 MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength,\r
416 (NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength -(MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength))\r
9bfb4940 417 );\r
418 }\r
419 NextResourceHob->PhysicalStart = MemoryHob->AllocDescriptor.MemoryBaseAddress;\r
420 NextResourceHob->ResourceLength = MemoryHob->AllocDescriptor.MemoryLength;\r
421 break;\r
422 }\r
423 }\r
424 }\r
425 }\r
426 }\r
427\r
54ea99a7 428 //\r
429 // Try to find and validate the TOP address.\r
d1102dba 430 //\r
852081fc 431 if ((INT64)PcdGet64(PcdLoadModuleAtFixAddressEnable) > 0 ) {\r
54ea99a7 432 //\r
433 // The LMFA feature is enabled as load module at fixed absolute address.\r
434 //\r
852081fc 435 TopLoadingAddress = (EFI_PHYSICAL_ADDRESS)PcdGet64(PcdLoadModuleAtFixAddressEnable);\r
54ea99a7 436 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: Loading module at fixed absolute address.\n"));\r
437 //\r
438 // validate the Address. Loop the resource descriptor HOB to make sure the address is in valid memory range\r
439 //\r
440 if ((TopLoadingAddress & EFI_PAGE_MASK) != 0) {\r
d1102dba
LG
441 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:Top Address 0x%lx is invalid since top address should be page align. \n", TopLoadingAddress));\r
442 ASSERT (FALSE);\r
54ea99a7 443 }\r
444 //\r
d1102dba 445 // Search for a memory region that is below MAX_ADDRESS and in which TopLoadingAddress lies\r
54ea99a7 446 //\r
447 for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
448 //\r
449 // See if this is a resource descriptor HOB\r
450 //\r
451 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
452\r
453 ResourceHob = Hob.ResourceDescriptor;\r
454 //\r
d39d1260 455 // See if this resource descriptor HOB describes tested system memory below MAX_ADDRESS\r
d1102dba 456 //\r
54ea99a7 457 if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&\r
458 ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS) {\r
459 //\r
460 // See if Top address specified by user is valid.\r
461 //\r
d1102dba
LG
462 if (ResourceHob->PhysicalStart + TotalReservedMemorySize < TopLoadingAddress &&\r
463 (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MINIMUM_INITIAL_MEMORY_SIZE) >= TopLoadingAddress &&\r
9bfb4940 464 PeiLoadFixAddressIsMemoryRangeAvailable(PrivateData, ResourceHob)) {\r
d1102dba 465 CurrentResourceHob = ResourceHob;\r
54ea99a7 466 CurrentHob = Hob;\r
467 break;\r
9bfb4940 468 }\r
54ea99a7 469 }\r
d1102dba
LG
470 }\r
471 }\r
54ea99a7 472 if (CurrentResourceHob != NULL) {\r
852081fc 473 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO:Top Address 0x%lx is valid \n", TopLoadingAddress));\r
d1102dba 474 TopLoadingAddress += MINIMUM_INITIAL_MEMORY_SIZE;\r
54ea99a7 475 } else {\r
d1102dba
LG
476 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:Top Address 0x%lx is invalid \n", TopLoadingAddress));\r
477 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:The recommended Top Address for the platform is: \n"));\r
54ea99a7 478 //\r
d39d1260 479 // Print the recommended Top address range.\r
d1102dba 480 //\r
54ea99a7 481 for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
482 //\r
483 // See if this is a resource descriptor HOB\r
484 //\r
485 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
d1102dba 486\r
54ea99a7 487 ResourceHob = Hob.ResourceDescriptor;\r
488 //\r
d39d1260 489 // See if this resource descriptor HOB describes tested system memory below MAX_ADDRESS\r
d1102dba 490 //\r
54ea99a7 491 if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&\r
492 ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS) {\r
493 //\r
494 // See if Top address specified by user is valid.\r
495 //\r
9bfb4940 496 if (ResourceHob->ResourceLength > TotalReservedMemorySize && PeiLoadFixAddressIsMemoryRangeAvailable(PrivateData, ResourceHob)) {\r
d1102dba
LG
497 DEBUG ((EFI_D_INFO, "(0x%lx, 0x%lx)\n",\r
498 (ResourceHob->PhysicalStart + TotalReservedMemorySize -MINIMUM_INITIAL_MEMORY_SIZE),\r
499 (ResourceHob->PhysicalStart + ResourceHob->ResourceLength -MINIMUM_INITIAL_MEMORY_SIZE)\r
500 ));\r
54ea99a7 501 }\r
502 }\r
503 }\r
d1102dba 504 }\r
54ea99a7 505 //\r
d1102dba 506 // Assert here\r
54ea99a7 507 //\r
d1102dba
LG
508 ASSERT (FALSE);\r
509 return;\r
510 }\r
54ea99a7 511 } else {\r
512 //\r
513 // The LMFA feature is enabled as load module at fixed offset relative to TOLM\r
514 // Parse the Hob list to find the topest available memory. Generally it is (TOLM - TSEG)\r
515 //\r
516 //\r
517 // Search for a tested memory region that is below MAX_ADDRESS\r
518 //\r
519 for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
520 //\r
d1102dba 521 // See if this is a resource descriptor HOB\r
54ea99a7 522 //\r
523 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
d1102dba
LG
524\r
525 ResourceHob = Hob.ResourceDescriptor;\r
54ea99a7 526 //\r
d39d1260 527 // See if this resource descriptor HOB describes tested system memory below MAX_ADDRESS\r
54ea99a7 528 //\r
d1102dba 529 if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&\r
54ea99a7 530 ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS &&\r
9bfb4940 531 ResourceHob->ResourceLength > TotalReservedMemorySize && PeiLoadFixAddressIsMemoryRangeAvailable(PrivateData, ResourceHob)) {\r
54ea99a7 532 //\r
533 // See if this is the highest largest system memory region below MaxAddress\r
534 //\r
535 if (ResourceHob->PhysicalStart > HighAddress) {\r
536 CurrentResourceHob = ResourceHob;\r
537 CurrentHob = Hob;\r
538 HighAddress = CurrentResourceHob->PhysicalStart;\r
539 }\r
540 }\r
d1102dba 541 }\r
54ea99a7 542 }\r
543 if (CurrentResourceHob == NULL) {\r
d1102dba 544 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:The System Memory is too small\n"));\r
54ea99a7 545 //\r
d1102dba 546 // Assert here\r
54ea99a7 547 //\r
9bfb4940 548 ASSERT (FALSE);\r
d1102dba 549 return;\r
54ea99a7 550 } else {\r
d1102dba
LG
551 TopLoadingAddress = CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength ;\r
552 }\r
54ea99a7 553 }\r
d1102dba 554\r
54ea99a7 555 if (CurrentResourceHob != NULL) {\r
556 //\r
d39d1260 557 // rebuild resource HOB for PEI memory and reserved memory\r
54ea99a7 558 //\r
559 BuildResourceDescriptorHob (\r
d1102dba 560 EFI_RESOURCE_SYSTEM_MEMORY,\r
54ea99a7 561 (\r
562 EFI_RESOURCE_ATTRIBUTE_PRESENT |\r
563 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |\r
564 EFI_RESOURCE_ATTRIBUTE_TESTED |\r
565 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |\r
566 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |\r
567 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |\r
568 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE\r
569 ),\r
d1102dba
LG
570 (TopLoadingAddress - TotalReservedMemorySize),\r
571 TotalReservedMemorySize\r
54ea99a7 572 );\r
573 //\r
9bfb4940 574 // rebuild resource for the remain memory if necessary\r
54ea99a7 575 //\r
576 if (CurrentResourceHob->PhysicalStart < TopLoadingAddress - TotalReservedMemorySize) {\r
577 BuildResourceDescriptorHob (\r
d1102dba 578 EFI_RESOURCE_SYSTEM_MEMORY,\r
54ea99a7 579 (\r
580 EFI_RESOURCE_ATTRIBUTE_PRESENT |\r
581 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |\r
582 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |\r
583 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |\r
584 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |\r
585 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE\r
586 ),\r
d1102dba
LG
587 CurrentResourceHob->PhysicalStart,\r
588 (TopLoadingAddress - TotalReservedMemorySize - CurrentResourceHob->PhysicalStart)\r
54ea99a7 589 );\r
590 }\r
591 if (CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength > TopLoadingAddress ) {\r
592 BuildResourceDescriptorHob (\r
d1102dba 593 EFI_RESOURCE_SYSTEM_MEMORY,\r
54ea99a7 594 (\r
595 EFI_RESOURCE_ATTRIBUTE_PRESENT |\r
596 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |\r
597 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |\r
598 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |\r
599 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |\r
600 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE\r
601 ),\r
d1102dba
LG
602 TopLoadingAddress,\r
603 (CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength - TopLoadingAddress)\r
54ea99a7 604 );\r
605 }\r
606 //\r
93b8ed68 607 // Delete CurrentHob by marking it as unused since the memory range described by is rebuilt.\r
54ea99a7 608 //\r
d1102dba 609 GET_HOB_TYPE (CurrentHob) = EFI_HOB_TYPE_UNUSED;\r
54ea99a7 610 }\r
611\r
612 //\r
613 // Cache the top address for Loading Module at Fixed Address feature\r
614 //\r
615 PrivateData->LoadModuleAtFixAddressTopAddress = TopLoadingAddress - MINIMUM_INITIAL_MEMORY_SIZE;\r
d1102dba 616 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: Top address = 0x%lx\n", PrivateData->LoadModuleAtFixAddressTopAddress));\r
54ea99a7 617 //\r
618 // reinstall the PEI memory relative to TopLoadingAddress\r
619 //\r
620 PrivateData->PhysicalMemoryBegin = TopLoadingAddress - TotalReservedMemorySize;\r
621 PrivateData->FreePhysicalMemoryTop = PrivateData->PhysicalMemoryBegin + PeiMemorySize;\r
622}\r
0f9ebb32
LG
623\r
624/**\r
625 This routine is invoked in switch stack as PeiCore Entry.\r
626\r
627 @param SecCoreData Points to a data structure containing information about the PEI core's operating\r
628 environment, such as the size and location of temporary RAM, the stack location and\r
629 the BFV location.\r
630 @param Private Pointer to old core data that is used to initialize the\r
631 core's data areas.\r
632**/\r
633VOID\r
634EFIAPI\r
635PeiCoreEntry (\r
636 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,\r
637 IN PEI_CORE_INSTANCE *Private\r
638 )\r
639{\r
640 //\r
641 // Entry PEI Phase 2\r
642 //\r
643 PeiCore (SecCoreData, NULL, Private);\r
644}\r
645\r
bfb685da
SZ
646/**\r
647 Check SwitchStackSignal and switch stack if SwitchStackSignal is TRUE.\r
648\r
649 @param[in] SecCoreData Points to a data structure containing information about the PEI core's operating\r
650 environment, such as the size and location of temporary RAM, the stack location and\r
651 the BFV location.\r
652 @param[in] Private Pointer to the private data passed in from caller.\r
653\r
654**/\r
655VOID\r
656PeiCheckAndSwitchStack (\r
657 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,\r
658 IN PEI_CORE_INSTANCE *Private\r
659 )\r
660{\r
661 VOID *LoadFixPeiCodeBegin;\r
662 EFI_STATUS Status;\r
663 CONST EFI_PEI_SERVICES **PeiServices;\r
664 UINT64 NewStackSize;\r
665 EFI_PHYSICAL_ADDRESS TopOfOldStack;\r
666 EFI_PHYSICAL_ADDRESS TopOfNewStack;\r
667 UINTN StackOffset;\r
668 BOOLEAN StackOffsetPositive;\r
669 EFI_PHYSICAL_ADDRESS TemporaryRamBase;\r
670 UINTN TemporaryRamSize;\r
671 UINTN TemporaryStackSize;\r
672 VOID *TemporaryStackBase;\r
673 UINTN PeiTemporaryRamSize;\r
674 VOID *PeiTemporaryRamBase;\r
675 EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI *TemporaryRamSupportPpi;\r
676 EFI_PHYSICAL_ADDRESS BaseOfNewHeap;\r
677 EFI_PHYSICAL_ADDRESS HoleMemBase;\r
678 UINTN HoleMemSize;\r
679 UINTN HeapTemporaryRamSize;\r
680 EFI_PHYSICAL_ADDRESS TempBase1;\r
681 UINTN TempSize1;\r
682 EFI_PHYSICAL_ADDRESS TempBase2;\r
683 UINTN TempSize2;\r
684 UINTN Index;\r
685\r
686 PeiServices = (CONST EFI_PEI_SERVICES **) &Private->Ps;\r
687\r
688 if (Private->SwitchStackSignal) {\r
689 //\r
6393d9c8
GL
690 // Before switch stack from temporary memory to permanent memory, calculate the heap and stack\r
691 // usage in temporary memory for debugging.\r
bfb685da
SZ
692 //\r
693 DEBUG_CODE_BEGIN ();\r
aa57c0f0
SZ
694 UINT32 *StackPointer;\r
695 EFI_PEI_HOB_POINTERS Hob;\r
bfb685da
SZ
696\r
697 for (StackPointer = (UINT32*)SecCoreData->StackBase;\r
698 (StackPointer < (UINT32*)((UINTN)SecCoreData->StackBase + SecCoreData->StackSize)) \\r
98127071 699 && (*StackPointer == PcdGet32 (PcdInitValueInTempStack));\r
be18cb03
LG
700 StackPointer ++) {\r
701 }\r
bfb685da 702\r
b2374cec
SZ
703 DEBUG ((DEBUG_INFO, "Temp Stack : BaseAddress=0x%p Length=0x%X\n", SecCoreData->StackBase, (UINT32)SecCoreData->StackSize));\r
704 DEBUG ((DEBUG_INFO, "Temp Heap : BaseAddress=0x%p Length=0x%X\n", SecCoreData->PeiTemporaryRamBase, (UINT32)SecCoreData->PeiTemporaryRamSize));\r
705 DEBUG ((DEBUG_INFO, "Total temporary memory: %d bytes.\n", (UINT32)SecCoreData->TemporaryRamSize));\r
706 DEBUG ((DEBUG_INFO, " temporary memory stack ever used: %d bytes.\n",\r
df56e808
AF
707 (UINT32)(SecCoreData->StackSize - ((UINTN) StackPointer - (UINTN)SecCoreData->StackBase))\r
708 ));\r
b2374cec 709 DEBUG ((DEBUG_INFO, " temporary memory heap used for HobList: %d bytes.\n",\r
df56e808
AF
710 (UINT32)((UINTN)Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - (UINTN)Private->HobList.Raw)\r
711 ));\r
aa57c0f0
SZ
712 DEBUG ((DEBUG_INFO, " temporary memory heap occupied by memory pages: %d bytes.\n",\r
713 (UINT32)(UINTN)(Private->HobList.HandoffInformationTable->EfiMemoryTop - Private->HobList.HandoffInformationTable->EfiFreeMemoryTop)\r
714 ));\r
715 for (Hob.Raw = Private->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
716 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {\r
717 DEBUG ((DEBUG_INFO, "Memory Allocation 0x%08x 0x%0lx - 0x%0lx\n", \\r
718 Hob.MemoryAllocation->AllocDescriptor.MemoryType, \\r
719 Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress, \\r
720 Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress + Hob.MemoryAllocation->AllocDescriptor.MemoryLength - 1));\r
721 }\r
722 }\r
bfb685da
SZ
723 DEBUG_CODE_END ();\r
724\r
725 if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0 && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
726 //\r
727 // Loading Module at Fixed Address is enabled\r
728 //\r
729 PeiLoadFixAddressHook (Private);\r
730\r
731 //\r
732 // If Loading Module at Fixed Address is enabled, Allocating memory range for Pei code range.\r
733 //\r
734 LoadFixPeiCodeBegin = AllocatePages((UINTN)PcdGet32(PcdLoadFixAddressPeiCodePageNumber));\r
735 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PeiCodeBegin = 0x%lX, PeiCodeTop= 0x%lX\n", (UINT64)(UINTN)LoadFixPeiCodeBegin, (UINT64)((UINTN)LoadFixPeiCodeBegin + PcdGet32(PcdLoadFixAddressPeiCodePageNumber) * EFI_PAGE_SIZE)));\r
736 }\r
737\r
738 //\r
739 // Reserve the size of new stack at bottom of physical memory\r
740 //\r
6393d9c8 741 // The size of new stack in permanent memory must be the same size\r
bfb685da
SZ
742 // or larger than the size of old stack in temporary memory.\r
743 // But if new stack is smaller than the size of old stack, we also reserve\r
6393d9c8 744 // the size of old stack at bottom of permanent memory.\r
bfb685da
SZ
745 //\r
746 NewStackSize = RShiftU64 (Private->PhysicalMemoryLength, 1);\r
747 NewStackSize = ALIGN_VALUE (NewStackSize, EFI_PAGE_SIZE);\r
748 NewStackSize = MIN (PcdGet32(PcdPeiCoreMaxPeiStackSize), NewStackSize);\r
749 DEBUG ((EFI_D_INFO, "Old Stack size %d, New stack size %d\n", (UINT32)SecCoreData->StackSize, (UINT32)NewStackSize));\r
750 ASSERT (NewStackSize >= SecCoreData->StackSize);\r
751\r
752 //\r
d39d1260 753 // Calculate stack offset and heap offset between temporary memory and new permanent\r
93b8ed68 754 // memory separately.\r
bfb685da
SZ
755 //\r
756 TopOfOldStack = (UINTN)SecCoreData->StackBase + SecCoreData->StackSize;\r
757 TopOfNewStack = Private->PhysicalMemoryBegin + NewStackSize;\r
758 if (TopOfNewStack >= TopOfOldStack) {\r
759 StackOffsetPositive = TRUE;\r
760 StackOffset = (UINTN)(TopOfNewStack - TopOfOldStack);\r
761 } else {\r
762 StackOffsetPositive = FALSE;\r
763 StackOffset = (UINTN)(TopOfOldStack - TopOfNewStack);\r
764 }\r
765 Private->StackOffsetPositive = StackOffsetPositive;\r
766 Private->StackOffset = StackOffset;\r
767\r
768 //\r
769 // Build Stack HOB that describes the permanent memory stack\r
770 //\r
771 DEBUG ((EFI_D_INFO, "Stack Hob: BaseAddress=0x%lX Length=0x%lX\n", TopOfNewStack - NewStackSize, NewStackSize));\r
772 BuildStackHob (TopOfNewStack - NewStackSize, NewStackSize);\r
773\r
774 //\r
775 // Cache information from SecCoreData into locals before SecCoreData is converted to a permanent memory address\r
776 //\r
777 TemporaryRamBase = (EFI_PHYSICAL_ADDRESS)(UINTN)SecCoreData->TemporaryRamBase;\r
778 TemporaryRamSize = SecCoreData->TemporaryRamSize;\r
779 TemporaryStackSize = SecCoreData->StackSize;\r
780 TemporaryStackBase = SecCoreData->StackBase;\r
781 PeiTemporaryRamSize = SecCoreData->PeiTemporaryRamSize;\r
782 PeiTemporaryRamBase = SecCoreData->PeiTemporaryRamBase;\r
783\r
784 //\r
785 // TemporaryRamSupportPpi is produced by platform's SEC\r
786 //\r
787 Status = PeiServicesLocatePpi (\r
788 &gEfiTemporaryRamSupportPpiGuid,\r
789 0,\r
790 NULL,\r
791 (VOID**)&TemporaryRamSupportPpi\r
792 );\r
793 if (!EFI_ERROR (Status)) {\r
794 //\r
795 // Heap Offset\r
796 //\r
797 BaseOfNewHeap = TopOfNewStack;\r
798 if (BaseOfNewHeap >= (UINTN)SecCoreData->PeiTemporaryRamBase) {\r
799 Private->HeapOffsetPositive = TRUE;\r
800 Private->HeapOffset = (UINTN)(BaseOfNewHeap - (UINTN)SecCoreData->PeiTemporaryRamBase);\r
801 } else {\r
802 Private->HeapOffsetPositive = FALSE;\r
803 Private->HeapOffset = (UINTN)((UINTN)SecCoreData->PeiTemporaryRamBase - BaseOfNewHeap);\r
804 }\r
805\r
806 DEBUG ((EFI_D_INFO, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (UINT64) Private->HeapOffset, (UINT64) Private->StackOffset));\r
807\r
808 //\r
809 // Calculate new HandOffTable and PrivateData address in permanent memory's stack\r
810 //\r
811 if (StackOffsetPositive) {\r
812 SecCoreData = (CONST EFI_SEC_PEI_HAND_OFF *)((UINTN)(VOID *)SecCoreData + StackOffset);\r
813 Private = (PEI_CORE_INSTANCE *)((UINTN)(VOID *)Private + StackOffset);\r
814 } else {\r
815 SecCoreData = (CONST EFI_SEC_PEI_HAND_OFF *)((UINTN)(VOID *)SecCoreData - StackOffset);\r
816 Private = (PEI_CORE_INSTANCE *)((UINTN)(VOID *)Private - StackOffset);\r
817 }\r
818\r
819 //\r
d1102dba 820 // Temporary Ram Support PPI is provided by platform, it will copy\r
6393d9c8 821 // temporary memory to permanent memory and do stack switching.\r
d1102dba 822 // After invoking Temporary Ram Support PPI, the following code's\r
bfb685da
SZ
823 // stack is in permanent memory.\r
824 //\r
825 TemporaryRamSupportPpi->TemporaryRamMigration (\r
826 PeiServices,\r
827 TemporaryRamBase,\r
828 (EFI_PHYSICAL_ADDRESS)(UINTN)(TopOfNewStack - TemporaryStackSize),\r
829 TemporaryRamSize\r
830 );\r
831\r
b2374cec
SZ
832 //\r
833 // Migrate memory pages allocated in pre-memory phase.\r
834 // It could not be called before calling TemporaryRamSupportPpi->TemporaryRamMigration()\r
835 // as the migrated memory pages may be overridden by TemporaryRamSupportPpi->TemporaryRamMigration().\r
836 //\r
837 MigrateMemoryPages (Private, TRUE);\r
838\r
bfb685da
SZ
839 //\r
840 // Entry PEI Phase 2\r
841 //\r
842 PeiCore (SecCoreData, NULL, Private);\r
843 } else {\r
b2374cec
SZ
844 //\r
845 // Migrate memory pages allocated in pre-memory phase.\r
846 //\r
847 MigrateMemoryPages (Private, FALSE);\r
848\r
bfb685da
SZ
849 //\r
850 // Migrate the PEI Services Table pointer from temporary RAM to permanent RAM.\r
851 //\r
852 MigratePeiServicesTablePointer ();\r
b2374cec 853\r
bfb685da
SZ
854 //\r
855 // Heap Offset\r
856 //\r
857 BaseOfNewHeap = TopOfNewStack;\r
858 HoleMemBase = TopOfNewStack;\r
859 HoleMemSize = TemporaryRamSize - PeiTemporaryRamSize - TemporaryStackSize;\r
860 if (HoleMemSize != 0) {\r
861 //\r
862 // Make sure HOB List start address is 8 byte alignment.\r
863 //\r
864 BaseOfNewHeap = ALIGN_VALUE (BaseOfNewHeap + HoleMemSize, 8);\r
865 }\r
866 if (BaseOfNewHeap >= (UINTN)SecCoreData->PeiTemporaryRamBase) {\r
867 Private->HeapOffsetPositive = TRUE;\r
868 Private->HeapOffset = (UINTN)(BaseOfNewHeap - (UINTN)SecCoreData->PeiTemporaryRamBase);\r
869 } else {\r
870 Private->HeapOffsetPositive = FALSE;\r
871 Private->HeapOffset = (UINTN)((UINTN)SecCoreData->PeiTemporaryRamBase - BaseOfNewHeap);\r
872 }\r
873\r
874 DEBUG ((EFI_D_INFO, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (UINT64) Private->HeapOffset, (UINT64) Private->StackOffset));\r
875\r
876 //\r
877 // Migrate Heap\r
878 //\r
879 HeapTemporaryRamSize = (UINTN) (Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - Private->HobList.HandoffInformationTable->EfiMemoryBottom);\r
880 ASSERT (BaseOfNewHeap + HeapTemporaryRamSize <= Private->FreePhysicalMemoryTop);\r
b2374cec 881 CopyMem ((UINT8 *) (UINTN) BaseOfNewHeap, PeiTemporaryRamBase, HeapTemporaryRamSize);\r
bfb685da
SZ
882\r
883 //\r
884 // Migrate Stack\r
885 //\r
886 CopyMem ((UINT8 *) (UINTN) (TopOfNewStack - TemporaryStackSize), TemporaryStackBase, TemporaryStackSize);\r
887\r
888 //\r
889 // Copy Hole Range Data\r
bfb685da
SZ
890 //\r
891 if (HoleMemSize != 0) {\r
892 //\r
893 // Prepare Hole\r
894 //\r
895 if (PeiTemporaryRamBase < TemporaryStackBase) {\r
896 TempBase1 = (EFI_PHYSICAL_ADDRESS) (UINTN) PeiTemporaryRamBase;\r
897 TempSize1 = PeiTemporaryRamSize;\r
898 TempBase2 = (EFI_PHYSICAL_ADDRESS) (UINTN) TemporaryStackBase;\r
899 TempSize2 = TemporaryStackSize;\r
900 } else {\r
901 TempBase1 = (EFI_PHYSICAL_ADDRESS) (UINTN) TemporaryStackBase;\r
902 TempSize1 = TemporaryStackSize;\r
903 TempBase2 =(EFI_PHYSICAL_ADDRESS) (UINTN) PeiTemporaryRamBase;\r
904 TempSize2 = PeiTemporaryRamSize;\r
905 }\r
906 if (TemporaryRamBase < TempBase1) {\r
907 Private->HoleData[0].Base = TemporaryRamBase;\r
908 Private->HoleData[0].Size = (UINTN) (TempBase1 - TemporaryRamBase);\r
909 }\r
910 if (TempBase1 + TempSize1 < TempBase2) {\r
911 Private->HoleData[1].Base = TempBase1 + TempSize1;\r
912 Private->HoleData[1].Size = (UINTN) (TempBase2 - TempBase1 - TempSize1);\r
913 }\r
914 if (TempBase2 + TempSize2 < TemporaryRamBase + TemporaryRamSize) {\r
915 Private->HoleData[2].Base = TempBase2 + TempSize2;\r
916 Private->HoleData[2].Size = (UINTN) (TemporaryRamBase + TemporaryRamSize - TempBase2 - TempSize2);\r
917 }\r
918\r
919 //\r
920 // Copy Hole Range data.\r
921 //\r
922 for (Index = 0; Index < HOLE_MAX_NUMBER; Index ++) {\r
923 if (Private->HoleData[Index].Size > 0) {\r
924 if (HoleMemBase > Private->HoleData[Index].Base) {\r
925 Private->HoleData[Index].OffsetPositive = TRUE;\r
926 Private->HoleData[Index].Offset = (UINTN) (HoleMemBase - Private->HoleData[Index].Base);\r
927 } else {\r
928 Private->HoleData[Index].OffsetPositive = FALSE;\r
929 Private->HoleData[Index].Offset = (UINTN) (Private->HoleData[Index].Base - HoleMemBase);\r
930 }\r
931 CopyMem ((VOID *) (UINTN) HoleMemBase, (VOID *) (UINTN) Private->HoleData[Index].Base, Private->HoleData[Index].Size);\r
932 HoleMemBase = HoleMemBase + Private->HoleData[Index].Size;\r
933 }\r
934 }\r
935 }\r
936\r
937 //\r
938 // Switch new stack\r
939 //\r
940 SwitchStack (\r
941 (SWITCH_STACK_ENTRY_POINT)(UINTN)PeiCoreEntry,\r
942 (VOID *) SecCoreData,\r
943 (VOID *) Private,\r
944 (VOID *) (UINTN) TopOfNewStack\r
945 );\r
946 }\r
947\r
948 //\r
949 // Code should not come here\r
950 //\r
951 ASSERT (FALSE);\r
952 }\r
953}\r
954\r
9bedaec0
MK
955/**\r
956 Migrate a PEIM from temporary RAM to permanent memory.\r
957\r
958 @param PeimFileHandle Pointer to the FFS file header of the image.\r
959 @param MigratedFileHandle Pointer to the FFS file header of the migrated image.\r
960\r
961 @retval EFI_SUCCESS Sucessfully migrated the PEIM to permanent memory.\r
962\r
963**/\r
964EFI_STATUS\r
965EFIAPI\r
966MigratePeim (\r
967 IN EFI_PEI_FILE_HANDLE FileHandle,\r
968 IN EFI_PEI_FILE_HANDLE MigratedFileHandle\r
969 )\r
970{\r
971 EFI_STATUS Status;\r
972 EFI_FFS_FILE_HEADER *FileHeader;\r
973 VOID *Pe32Data;\r
974 VOID *ImageAddress;\r
975 CHAR8 *AsciiString;\r
976 UINTN Index;\r
977\r
978 Status = EFI_SUCCESS;\r
979\r
980 FileHeader = (EFI_FFS_FILE_HEADER *) FileHandle;\r
981 ASSERT (!IS_FFS_FILE2 (FileHeader));\r
982\r
983 ImageAddress = NULL;\r
984 PeiGetPe32Data (MigratedFileHandle, &ImageAddress);\r
985 if (ImageAddress != NULL) {\r
986 DEBUG_CODE_BEGIN ();\r
987 AsciiString = PeCoffLoaderGetPdbPointer (ImageAddress);\r
988 for (Index = 0; AsciiString[Index] != 0; Index++) {\r
989 if (AsciiString[Index] == '\\' || AsciiString[Index] == '/') {\r
990 AsciiString = AsciiString + Index + 1;\r
991 Index = 0;\r
992 } else if (AsciiString[Index] == '.') {\r
993 AsciiString[Index] = 0;\r
994 }\r
995 }\r
996 DEBUG ((DEBUG_INFO, "%a", AsciiString));\r
997 DEBUG_CODE_END ();\r
998\r
999 Pe32Data = (VOID *) ((UINTN) ImageAddress - (UINTN) MigratedFileHandle + (UINTN) FileHandle);\r
1000 Status = LoadAndRelocatePeCoffImageInPlace (Pe32Data, ImageAddress);\r
1001 ASSERT_EFI_ERROR (Status);\r
1002 }\r
1003\r
1004 return Status;\r
1005}\r
1006\r
1007/**\r
1008 Migrate Status Code Callback function pointers inside an FV from temporary memory to permanent memory.\r
1009\r
1010 @param OrgFvHandle Address of FV handle in temporary memory.\r
1011 @param FvHandle Address of FV handle in permanent memory.\r
1012 @param FvSize Size of the FV.\r
1013\r
1014**/\r
1015VOID\r
1016ConvertStatusCodeCallbacks (\r
1017 IN UINTN OrgFvHandle,\r
1018 IN UINTN FvHandle,\r
1019 IN UINTN FvSize\r
1020 )\r
1021{\r
1022 EFI_PEI_HOB_POINTERS Hob;\r
1023 UINTN *NumberOfEntries;\r
1024 UINTN *CallbackEntry;\r
1025 UINTN Index;\r
1026\r
1027 Hob.Raw = GetFirstGuidHob (&gStatusCodeCallbackGuid);\r
1028 while (Hob.Raw != NULL) {\r
1029 NumberOfEntries = GET_GUID_HOB_DATA (Hob);\r
1030 CallbackEntry = NumberOfEntries + 1;\r
1031 for (Index = 0; Index < *NumberOfEntries; Index++) {\r
1032 if (((VOID *) CallbackEntry[Index]) != NULL) {\r
1033 if ((CallbackEntry[Index] >= OrgFvHandle) && (CallbackEntry[Index] < (OrgFvHandle + FvSize))) {\r
1034 DEBUG ((\r
1035 DEBUG_INFO,\r
1036 "Migrating CallbackEntry[%Lu] from 0x%0*Lx to ",\r
1037 (UINT64)Index,\r
1038 (sizeof CallbackEntry[Index]) * 2,\r
1039 (UINT64)CallbackEntry[Index]\r
1040 ));\r
1041 if (OrgFvHandle > FvHandle) {\r
1042 CallbackEntry[Index] = CallbackEntry[Index] - (OrgFvHandle - FvHandle);\r
1043 } else {\r
1044 CallbackEntry[Index] = CallbackEntry[Index] + (FvHandle - OrgFvHandle);\r
1045 }\r
1046 DEBUG ((\r
1047 DEBUG_INFO,\r
1048 "0x%0*Lx\n",\r
1049 (sizeof CallbackEntry[Index]) * 2,\r
1050 (UINT64)CallbackEntry[Index]\r
1051 ));\r
1052 }\r
1053 }\r
1054 }\r
1055 Hob.Raw = GET_NEXT_HOB (Hob);\r
1056 Hob.Raw = GetNextGuidHob (&gStatusCodeCallbackGuid, Hob.Raw);\r
1057 }\r
1058}\r
1059\r
1060/**\r
1061 Migrates SEC modules in the given firmware volume.\r
1062\r
1063 Migrating SECURITY_CORE files requires special treatment since they are not tracked for PEI dispatch.\r
1064\r
1065 This functioun should be called after the FV has been copied to its post-memory location and the PEI Core FV list has\r
1066 been updated.\r
1067\r
1068 @param Private Pointer to the PeiCore's private data structure.\r
1069 @param FvIndex The firmware volume index to migrate.\r
1070 @param OrgFvHandle The handle to the firmware volume in temporary memory.\r
1071\r
1072 @retval EFI_SUCCESS SEC modules were migrated successfully\r
1073 @retval EFI_INVALID_PARAMETER The Private pointer is NULL or FvCount is invalid.\r
1074 @retval EFI_NOT_FOUND Can't find valid FFS header.\r
1075\r
1076**/\r
1077EFI_STATUS\r
1078EFIAPI\r
1079MigrateSecModulesInFv (\r
1080 IN PEI_CORE_INSTANCE *Private,\r
1081 IN UINTN FvIndex,\r
1082 IN UINTN OrgFvHandle\r
1083 )\r
1084{\r
1085 EFI_STATUS Status;\r
1086 EFI_STATUS FindFileStatus;\r
1087 EFI_PEI_FILE_HANDLE MigratedFileHandle;\r
1088 EFI_PEI_FILE_HANDLE FileHandle;\r
1089 UINT32 SectionAuthenticationStatus;\r
1090 UINT32 FileSize;\r
1091 VOID *OrgPe32SectionData;\r
1092 VOID *Pe32SectionData;\r
1093 EFI_FFS_FILE_HEADER *FfsFileHeader;\r
1094 EFI_COMMON_SECTION_HEADER *Section;\r
1095 BOOLEAN IsFfs3Fv;\r
1096 UINTN SectionInstance;\r
1097\r
1098 if (Private == NULL || FvIndex >= Private->FvCount) {\r
1099 return EFI_INVALID_PARAMETER;\r
1100 }\r
1101\r
1102 do {\r
1103 FindFileStatus = PeiFfsFindNextFile (\r
1104 GetPeiServicesTablePointer (),\r
1105 EFI_FV_FILETYPE_SECURITY_CORE,\r
1106 Private->Fv[FvIndex].FvHandle,\r
1107 &MigratedFileHandle\r
1108 );\r
1109 if (!EFI_ERROR (FindFileStatus ) && MigratedFileHandle != NULL) {\r
1110 FileHandle = (EFI_PEI_FILE_HANDLE) ((UINTN) MigratedFileHandle - (UINTN) Private->Fv[FvIndex].FvHandle + OrgFvHandle);\r
1111 FfsFileHeader = (EFI_FFS_FILE_HEADER *) MigratedFileHandle;\r
1112\r
1113 DEBUG ((DEBUG_VERBOSE, " Migrating SEC_CORE MigratedFileHandle at 0x%x.\n", (UINTN) MigratedFileHandle));\r
1114 DEBUG ((DEBUG_VERBOSE, " FileHandle at 0x%x.\n", (UINTN) FileHandle));\r
1115\r
1116 IsFfs3Fv = CompareGuid (&Private->Fv[FvIndex].FvHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid);\r
1117 if (IS_FFS_FILE2 (FfsFileHeader)) {\r
1118 ASSERT (FFS_FILE2_SIZE (FfsFileHeader) > 0x00FFFFFF);\r
1119 if (!IsFfs3Fv) {\r
1120 DEBUG ((DEBUG_ERROR, "It is a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader->Name));\r
1121 return EFI_NOT_FOUND;\r
1122 }\r
1123 Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER2));\r
1124 FileSize = FFS_FILE2_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER2);\r
1125 } else {\r
1126 Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER));\r
1127 FileSize = FFS_FILE_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER);\r
1128 }\r
1129\r
1130 SectionInstance = 1;\r
1131 SectionAuthenticationStatus = 0;\r
1132 Status = ProcessSection (\r
1133 GetPeiServicesTablePointer (),\r
1134 EFI_SECTION_PE32,\r
1135 &SectionInstance,\r
1136 Section,\r
1137 FileSize,\r
1138 &Pe32SectionData,\r
1139 &SectionAuthenticationStatus,\r
1140 IsFfs3Fv\r
1141 );\r
1142\r
1143 if (!EFI_ERROR (Status)) {\r
1144 OrgPe32SectionData = (VOID *) ((UINTN) Pe32SectionData - (UINTN) MigratedFileHandle + (UINTN) FileHandle);\r
1145 DEBUG ((DEBUG_VERBOSE, " PE32 section in migrated file at 0x%x.\n", (UINTN) Pe32SectionData));\r
1146 DEBUG ((DEBUG_VERBOSE, " PE32 section in original file at 0x%x.\n", (UINTN) OrgPe32SectionData));\r
1147 Status = LoadAndRelocatePeCoffImageInPlace (OrgPe32SectionData, Pe32SectionData);\r
1148 ASSERT_EFI_ERROR (Status);\r
1149 }\r
1150 }\r
1151 } while (!EFI_ERROR (FindFileStatus));\r
1152\r
1153 return EFI_SUCCESS;\r
1154}\r
1155\r
1156/**\r
1157 Migrates PEIMs in the given firmware volume.\r
1158\r
1159 @param Private Pointer to the PeiCore's private data structure.\r
1160 @param FvIndex The firmware volume index to migrate.\r
1161 @param OrgFvHandle The handle to the firmware volume in temporary memory.\r
1162 @param FvHandle The handle to the firmware volume in permanent memory.\r
1163\r
1164 @retval EFI_SUCCESS The PEIMs in the FV were migrated successfully\r
1165 @retval EFI_INVALID_PARAMETER The Private pointer is NULL or FvCount is invalid.\r
1166\r
1167**/\r
1168EFI_STATUS\r
1169EFIAPI\r
1170MigratePeimsInFv (\r
1171 IN PEI_CORE_INSTANCE *Private,\r
1172 IN UINTN FvIndex,\r
1173 IN UINTN OrgFvHandle,\r
1174 IN UINTN FvHandle\r
1175 )\r
1176{\r
1177 EFI_STATUS Status;\r
1178 volatile UINTN FileIndex;\r
1179 EFI_PEI_FILE_HANDLE MigratedFileHandle;\r
1180 EFI_PEI_FILE_HANDLE FileHandle;\r
1181\r
1182 if (Private == NULL || FvIndex >= Private->FvCount) {\r
1183 return EFI_INVALID_PARAMETER;\r
1184 }\r
1185\r
1186 if (Private->Fv[FvIndex].ScanFv) {\r
1187 for (FileIndex = 0; FileIndex < Private->Fv[FvIndex].PeimCount; FileIndex++) {\r
1188 if (Private->Fv[FvIndex].FvFileHandles[FileIndex] != NULL) {\r
1189 FileHandle = Private->Fv[FvIndex].FvFileHandles[FileIndex];\r
1190\r
1191 MigratedFileHandle = (EFI_PEI_FILE_HANDLE) ((UINTN) FileHandle - OrgFvHandle + FvHandle);\r
1192\r
1193 DEBUG ((DEBUG_VERBOSE, " Migrating FileHandle %2d ", FileIndex));\r
1194 Status = MigratePeim (FileHandle, MigratedFileHandle);\r
1195 DEBUG ((DEBUG_VERBOSE, "\n"));\r
1196 ASSERT_EFI_ERROR (Status);\r
1197\r
1198 if (!EFI_ERROR (Status)) {\r
1199 Private->Fv[FvIndex].FvFileHandles[FileIndex] = MigratedFileHandle;\r
1200 if (FvIndex == Private->CurrentPeimFvCount) {\r
1201 Private->CurrentFvFileHandles[FileIndex] = MigratedFileHandle;\r
1202 }\r
1203 }\r
1204 }\r
1205 }\r
1206 }\r
1207\r
1208 return EFI_SUCCESS;\r
1209}\r
1210\r
1211/**\r
1212 Migrate FVs out of temporary RAM before the cache is flushed.\r
1213\r
1214 @param Private PeiCore's private data structure\r
1215 @param SecCoreData Points to a data structure containing information about the PEI core's operating\r
1216 environment, such as the size and location of temporary RAM, the stack location and\r
1217 the BFV location.\r
1218\r
1219 @retval EFI_SUCCESS Succesfully migrated installed FVs from temporary RAM to permanent memory.\r
1220 @retval EFI_OUT_OF_RESOURCES Insufficient memory exists to allocate needed pages.\r
1221\r
1222**/\r
1223EFI_STATUS\r
1224EFIAPI\r
1225EvacuateTempRam (\r
1226 IN PEI_CORE_INSTANCE *Private,\r
1227 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData\r
1228 )\r
1229{\r
1230 EFI_STATUS Status;\r
1231 volatile UINTN FvIndex;\r
1232 volatile UINTN FvChildIndex;\r
1233 UINTN ChildFvOffset;\r
1234 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
1235 EFI_FIRMWARE_VOLUME_HEADER *ChildFvHeader;\r
1236 EFI_FIRMWARE_VOLUME_HEADER *MigratedFvHeader;\r
1237 EFI_FIRMWARE_VOLUME_HEADER *MigratedChildFvHeader;\r
1238\r
1239 PEI_CORE_FV_HANDLE PeiCoreFvHandle;\r
1240 EFI_PEI_CORE_FV_LOCATION_PPI *PeiCoreFvLocationPpi;\r
1241\r
1242 ASSERT (Private->PeiMemoryInstalled);\r
1243\r
1244 DEBUG ((DEBUG_VERBOSE, "Beginning evacuation of content in temporary RAM.\n"));\r
1245\r
1246 //\r
1247 // Migrate PPI Pointers of PEI_CORE from temporary memory to newly loaded PEI_CORE in permanent memory.\r
1248 //\r
1249 Status = PeiLocatePpi ((CONST EFI_PEI_SERVICES **) &Private->Ps, &gEfiPeiCoreFvLocationPpiGuid, 0, NULL, (VOID **) &PeiCoreFvLocationPpi);\r
1250 if (!EFI_ERROR (Status) && (PeiCoreFvLocationPpi->PeiCoreFvLocation != NULL)) {\r
1251 PeiCoreFvHandle.FvHandle = (EFI_PEI_FV_HANDLE) PeiCoreFvLocationPpi->PeiCoreFvLocation;\r
1252 } else {\r
1253 PeiCoreFvHandle.FvHandle = (EFI_PEI_FV_HANDLE) SecCoreData->BootFirmwareVolumeBase;\r
1254 }\r
1255 for (FvIndex = 0; FvIndex < Private->FvCount; FvIndex++) {\r
1256 if (Private->Fv[FvIndex].FvHandle == PeiCoreFvHandle.FvHandle) {\r
1257 PeiCoreFvHandle = Private->Fv[FvIndex];\r
1258 break;\r
1259 }\r
1260 }\r
1261 Status = EFI_SUCCESS;\r
1262\r
1263 ConvertPeiCorePpiPointers (Private, PeiCoreFvHandle);\r
1264\r
1265 for (FvIndex = 0; FvIndex < Private->FvCount; FvIndex++) {\r
1266 FvHeader = Private->Fv[FvIndex].FvHeader;\r
1267 ASSERT (FvHeader != NULL);\r
1268 ASSERT (FvIndex < Private->FvCount);\r
1269\r
1270 DEBUG ((DEBUG_VERBOSE, "FV[%02d] at 0x%x.\n", FvIndex, (UINTN) FvHeader));\r
1271 if (\r
1272 !(\r
1273 ((EFI_PHYSICAL_ADDRESS)(UINTN) FvHeader >= Private->PhysicalMemoryBegin) &&\r
1274 (((EFI_PHYSICAL_ADDRESS)(UINTN) FvHeader + (FvHeader->FvLength - 1)) < Private->FreePhysicalMemoryTop)\r
1275 )\r
1276 ) {\r
1277 Status = PeiServicesAllocatePages (\r
1278 EfiBootServicesCode,\r
1279 EFI_SIZE_TO_PAGES ((UINTN) FvHeader->FvLength),\r
1280 (EFI_PHYSICAL_ADDRESS *) &MigratedFvHeader\r
1281 );\r
1282 ASSERT_EFI_ERROR (Status);\r
1283\r
1284 DEBUG ((\r
1285 DEBUG_VERBOSE,\r
1286 " Migrating FV[%d] from 0x%08X to 0x%08X\n",\r
1287 FvIndex,\r
1288 (UINTN) FvHeader,\r
1289 (UINTN) MigratedFvHeader\r
1290 ));\r
1291\r
1292 CopyMem (MigratedFvHeader, FvHeader, (UINTN) FvHeader->FvLength);\r
1293\r
1294 //\r
1295 // Migrate any children for this FV now\r
1296 //\r
1297 for (FvChildIndex = FvIndex; FvChildIndex < Private->FvCount; FvChildIndex++) {\r
1298 ChildFvHeader = Private->Fv[FvChildIndex].FvHeader;\r
1299 if (\r
1300 ((UINTN) ChildFvHeader > (UINTN) FvHeader) &&\r
1301 (((UINTN) ChildFvHeader + ChildFvHeader->FvLength) < ((UINTN) FvHeader) + FvHeader->FvLength)\r
1302 ) {\r
1303 DEBUG ((DEBUG_VERBOSE, " Child FV[%02d] is being migrated.\n", FvChildIndex));\r
1304 ChildFvOffset = (UINTN) ChildFvHeader - (UINTN) FvHeader;\r
1305 DEBUG ((DEBUG_VERBOSE, " Child FV offset = 0x%x.\n", ChildFvOffset));\r
1306 MigratedChildFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) MigratedFvHeader + ChildFvOffset);\r
1307 Private->Fv[FvChildIndex].FvHeader = MigratedChildFvHeader;\r
1308 Private->Fv[FvChildIndex].FvHandle = (EFI_PEI_FV_HANDLE) MigratedChildFvHeader;\r
1309 DEBUG ((DEBUG_VERBOSE, " Child migrated FV header at 0x%x.\n", (UINTN) MigratedChildFvHeader));\r
1310\r
1311 Status = MigratePeimsInFv (Private, FvChildIndex, (UINTN) ChildFvHeader, (UINTN) MigratedChildFvHeader);\r
1312 ASSERT_EFI_ERROR (Status);\r
1313\r
1314 ConvertPpiPointersFv (\r
1315 Private,\r
1316 (UINTN) ChildFvHeader,\r
1317 (UINTN) MigratedChildFvHeader,\r
1318 (UINTN) ChildFvHeader->FvLength - 1\r
1319 );\r
1320\r
1321 ConvertStatusCodeCallbacks (\r
1322 (UINTN) ChildFvHeader,\r
1323 (UINTN) MigratedChildFvHeader,\r
1324 (UINTN) ChildFvHeader->FvLength - 1\r
1325 );\r
1326\r
1327 ConvertFvHob (Private, (UINTN) ChildFvHeader, (UINTN) MigratedChildFvHeader);\r
1328 }\r
1329 }\r
1330 Private->Fv[FvIndex].FvHeader = MigratedFvHeader;\r
1331 Private->Fv[FvIndex].FvHandle = (EFI_PEI_FV_HANDLE) MigratedFvHeader;\r
1332\r
1333 Status = MigratePeimsInFv (Private, FvIndex, (UINTN) FvHeader, (UINTN) MigratedFvHeader);\r
1334 ASSERT_EFI_ERROR (Status);\r
1335\r
1336 ConvertPpiPointersFv (\r
1337 Private,\r
1338 (UINTN) FvHeader,\r
1339 (UINTN) MigratedFvHeader,\r
1340 (UINTN) FvHeader->FvLength - 1\r
1341 );\r
1342\r
1343 ConvertStatusCodeCallbacks (\r
1344 (UINTN) FvHeader,\r
1345 (UINTN) MigratedFvHeader,\r
1346 (UINTN) FvHeader->FvLength - 1\r
1347 );\r
1348\r
1349 ConvertFvHob (Private, (UINTN) FvHeader, (UINTN) MigratedFvHeader);\r
1350 }\r
1351 }\r
1352\r
1353 RemoveFvHobsInTemporaryMemory (Private);\r
1354\r
1355 return Status;\r
1356}\r
1357\r
b1f6a7c6 1358/**\r
192f6d4c 1359 Conduct PEIM dispatch.\r
1360\r
b1f6a7c6 1361 @param SecCoreData Points to a data structure containing information about the PEI core's operating\r
5aae0aa7 1362 environment, such as the size and location of temporary RAM, the stack location and\r
1363 the BFV location.\r
b1f6a7c6 1364 @param Private Pointer to the private data passed in from caller\r
192f6d4c 1365\r
b1f6a7c6 1366**/\r
1367VOID\r
1368PeiDispatcher (\r
1369 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,\r
1370 IN PEI_CORE_INSTANCE *Private\r
1371 )\r
192f6d4c 1372{\r
b0d803fe 1373 EFI_STATUS Status;\r
1374 UINT32 Index1;\r
1375 UINT32 Index2;\r
6c7a807a 1376 CONST EFI_PEI_SERVICES **PeiServices;\r
b0d803fe 1377 EFI_PEI_FILE_HANDLE PeimFileHandle;\r
1378 UINTN FvCount;\r
1379 UINTN PeimCount;\r
1380 UINT32 AuthenticationState;\r
1381 EFI_PHYSICAL_ADDRESS EntryPoint;\r
797a9d67 1382 EFI_PEIM_ENTRY_POINT2 PeimEntryPoint;\r
b0d803fe 1383 UINTN SaveCurrentPeimCount;\r
1053e0c5 1384 UINTN SaveCurrentFvCount;\r
b0d803fe 1385 EFI_PEI_FILE_HANDLE SaveCurrentFileHandle;\r
288f9b38 1386 EFI_FV_FILE_INFO FvFileInfo;\r
3b428ade 1387 PEI_CORE_FV_HANDLE *CoreFvHandle;\r
d1102dba 1388\r
4140a663 1389 PeiServices = (CONST EFI_PEI_SERVICES **) &Private->Ps;\r
b0d803fe 1390 PeimEntryPoint = NULL;\r
1391 PeimFileHandle = NULL;\r
288f9b38 1392 EntryPoint = 0;\r
b0d803fe 1393\r
9bedaec0
MK
1394 if ((Private->PeiMemoryInstalled) &&\r
1395 (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||\r
1396 (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) ||\r
1397 PcdGetBool (PcdShadowPeimOnS3Boot))\r
1398 ) {\r
b0d803fe 1399 //\r
1400 // Once real memory is available, shadow the RegisterForShadow modules. And meanwhile\r
c2c4199b 1401 // update the modules' status from PEIM_STATE_REGISTER_FOR_SHADOW to PEIM_STATE_DONE.\r
b0d803fe 1402 //\r
1403 SaveCurrentPeimCount = Private->CurrentPeimCount;\r
1053e0c5 1404 SaveCurrentFvCount = Private->CurrentPeimFvCount;\r
b0d803fe 1405 SaveCurrentFileHandle = Private->CurrentFileHandle;\r
1406\r
b22d0931 1407 for (Index1 = 0; Index1 < Private->FvCount; Index1++) {\r
b62fe570 1408 for (Index2 = 0; Index2 < Private->Fv[Index1].PeimCount; Index2++) {\r
c2c4199b 1409 if (Private->Fv[Index1].PeimState[Index2] == PEIM_STATE_REGISTER_FOR_SHADOW) {\r
58dcdada 1410 PeimFileHandle = Private->Fv[Index1].FvFileHandles[Index2];\r
3d44658c
LG
1411 Private->CurrentFileHandle = PeimFileHandle;\r
1412 Private->CurrentPeimFvCount = Index1;\r
1413 Private->CurrentPeimCount = Index2;\r
b0d803fe 1414 Status = PeiLoadImage (\r
4140a663 1415 (CONST EFI_PEI_SERVICES **) &Private->Ps,\r
58dcdada 1416 PeimFileHandle,\r
c2c4199b 1417 PEIM_STATE_REGISTER_FOR_SHADOW,\r
58dcdada 1418 &EntryPoint,\r
b0d803fe 1419 &AuthenticationState\r
1420 );\r
1421 if (Status == EFI_SUCCESS) {\r
1422 //\r
c2c4199b 1423 // PEIM_STATE_REGISTER_FOR_SHADOW move to PEIM_STATE_DONE\r
b0d803fe 1424 //\r
1425 Private->Fv[Index1].PeimState[Index2]++;\r
b0d803fe 1426 //\r
1427 // Call the PEIM entry point\r
1428 //\r
797a9d67 1429 PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;\r
58dcdada 1430\r
67e9ab84 1431 PERF_START_IMAGE_BEGIN (PeimFileHandle);\r
4140a663 1432 PeimEntryPoint(PeimFileHandle, (const EFI_PEI_SERVICES **) &Private->Ps);\r
67e9ab84 1433 PERF_START_IMAGE_END (PeimFileHandle);\r
58dcdada 1434 }\r
1435\r
b0d803fe 1436 //\r
1437 // Process the Notify list and dispatch any notifies for\r
1438 // newly installed PPIs.\r
1439 //\r
f2bc359c 1440 ProcessDispatchNotifyList (Private);\r
b0d803fe 1441 }\r
1442 }\r
1443 }\r
58dcdada 1444 Private->CurrentFileHandle = SaveCurrentFileHandle;\r
1445 Private->CurrentPeimFvCount = SaveCurrentFvCount;\r
1446 Private->CurrentPeimCount = SaveCurrentPeimCount;\r
b0d803fe 1447 }\r
192f6d4c 1448\r
1449 //\r
1450 // This is the main dispatch loop. It will search known FVs for PEIMs and\r
1451 // attempt to dispatch them. If any PEIM gets dispatched through a single\r
d39d1260 1452 // pass of the dispatcher, it will start over from the BFV again to see\r
192f6d4c 1453 // if any new PEIMs dependencies got satisfied. With a well ordered\r
1454 // FV where PEIMs are found in the order their dependencies are also\r
d39d1260 1455 // satisfied, this dispatcher should run only once.\r
192f6d4c 1456 //\r
b0d803fe 1457 do {\r
82b8c8df 1458 //\r
d1102dba 1459 // In case that reenter PeiCore happens, the last pass record is still available.\r
82b8c8df 1460 //\r
1461 if (!Private->PeimDispatcherReenter) {\r
1462 Private->PeimNeedingDispatch = FALSE;\r
1463 Private->PeimDispatchOnThisPass = FALSE;\r
1464 } else {\r
1465 Private->PeimDispatcherReenter = FALSE;\r
1466 }\r
d1102dba 1467\r
b0d803fe 1468 for (FvCount = Private->CurrentPeimFvCount; FvCount < Private->FvCount; FvCount++) {\r
3b428ade 1469 CoreFvHandle = FindNextCoreFvHandle (Private, FvCount);\r
1470 ASSERT (CoreFvHandle != NULL);\r
d1102dba 1471\r
2a00326e 1472 //\r
3b428ade 1473 // If the FV has corresponding EFI_PEI_FIRMWARE_VOLUME_PPI instance, then dispatch it.\r
2a00326e 1474 //\r
3b428ade 1475 if (CoreFvHandle->FvPpi == NULL) {\r
1476 continue;\r
1477 }\r
d1102dba 1478\r
3b428ade 1479 Private->CurrentPeimFvCount = FvCount;\r
192f6d4c 1480\r
b0d803fe 1481 if (Private->CurrentPeimCount == 0) {\r
1482 //\r
1483 // When going through each FV, at first, search Apriori file to\r
58dcdada 1484 // reorder all PEIMs to ensure the PEIMs in Apriori file to get\r
b0d803fe 1485 // dispatch at first.\r
1486 //\r
3b428ade 1487 DiscoverPeimsAndOrderWithApriori (Private, CoreFvHandle);\r
b0d803fe 1488 }\r
192f6d4c 1489\r
1490 //\r
d39d1260 1491 // Start to dispatch all modules within the current FV.\r
192f6d4c 1492 //\r
58dcdada 1493 for (PeimCount = Private->CurrentPeimCount;\r
b62fe570 1494 PeimCount < Private->Fv[FvCount].PeimCount;\r
b0d803fe 1495 PeimCount++) {\r
1496 Private->CurrentPeimCount = PeimCount;\r
1497 PeimFileHandle = Private->CurrentFileHandle = Private->CurrentFvFileHandles[PeimCount];\r
1498\r
1499 if (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_NOT_DISPATCHED) {\r
1500 if (!DepexSatisfied (Private, PeimFileHandle, PeimCount)) {\r
82b8c8df 1501 Private->PeimNeedingDispatch = TRUE;\r
b0d803fe 1502 } else {\r
3b428ade 1503 Status = CoreFvHandle->FvPpi->GetFileInfo (CoreFvHandle->FvPpi, PeimFileHandle, &FvFileInfo);\r
288f9b38
LG
1504 ASSERT_EFI_ERROR (Status);\r
1505 if (FvFileInfo.FileType == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {\r
1506 //\r
d39d1260 1507 // For FV type file, Produce new FvInfo PPI and FV HOB\r
288f9b38 1508 //\r
c7935105
SZ
1509 Status = ProcessFvFile (Private, &Private->Fv[FvCount], PeimFileHandle);\r
1510 if (Status == EFI_SUCCESS) {\r
1511 //\r
1512 // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED\r
1513 //\r
1514 Private->Fv[FvCount].PeimState[PeimCount]++;\r
1515 Private->PeimDispatchOnThisPass = TRUE;\r
116cd856
SZ
1516 } else {\r
1517 //\r
1518 // The related GuidedSectionExtraction/Decompress PPI for the\r
1519 // encapsulated FV image section may be installed in the rest\r
1520 // of this do-while loop, so need to make another pass.\r
1521 //\r
1522 Private->PeimNeedingDispatch = TRUE;\r
c7935105 1523 }\r
288f9b38
LG
1524 } else {\r
1525 //\r
1526 // For PEIM driver, Load its entry point\r
1527 //\r
1528 Status = PeiLoadImage (\r
58dcdada 1529 PeiServices,\r
1530 PeimFileHandle,\r
341a658f 1531 PEIM_STATE_NOT_DISPATCHED,\r
58dcdada 1532 &EntryPoint,\r
288f9b38
LG
1533 &AuthenticationState\r
1534 );\r
c7935105 1535 if (Status == EFI_SUCCESS) {\r
b0d803fe 1536 //\r
c7935105
SZ
1537 // The PEIM has its dependencies satisfied, and its entry point\r
1538 // has been found, so invoke it.\r
b0d803fe 1539 //\r
67e9ab84 1540 PERF_START_IMAGE_BEGIN (PeimFileHandle);\r
58dcdada 1541\r
c7935105
SZ
1542 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
1543 EFI_PROGRESS_CODE,\r
1544 (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN),\r
fa3d30ea
LG
1545 (VOID *)(&PeimFileHandle),\r
1546 sizeof (PeimFileHandle)\r
c7935105
SZ
1547 );\r
1548\r
1549 Status = VerifyPeim (Private, CoreFvHandle->FvHandle, PeimFileHandle, AuthenticationState);\r
1550 if (Status != EFI_SECURITY_VIOLATION) {\r
1551 //\r
1552 // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED\r
1553 //\r
1554 Private->Fv[FvCount].PeimState[PeimCount]++;\r
288f9b38
LG
1555 //\r
1556 // Call the PEIM entry point for PEIM driver\r
1557 //\r
797a9d67 1558 PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;\r
1559 PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);\r
c7935105 1560 Private->PeimDispatchOnThisPass = TRUE;\r
9f671b47
LG
1561 } else {\r
1562 //\r
1563 // The related GuidedSectionExtraction PPI for the\r
1564 // signed PEIM image section may be installed in the rest\r
1565 // of this do-while loop, so need to make another pass.\r
1566 //\r
1567 Private->PeimNeedingDispatch = TRUE;\r
288f9b38 1568 }\r
797a9d67 1569\r
c7935105
SZ
1570 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
1571 EFI_PROGRESS_CODE,\r
1572 (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_END),\r
fa3d30ea
LG
1573 (VOID *)(&PeimFileHandle),\r
1574 sizeof (PeimFileHandle)\r
c7935105 1575 );\r
67e9ab84 1576 PERF_START_IMAGE_END (PeimFileHandle);\r
b0d803fe 1577\r
c7935105 1578 }\r
58dcdada 1579 }\r
1580\r
bfb685da 1581 PeiCheckAndSwitchStack (SecCoreData, Private);\r
192f6d4c 1582\r
58dcdada 1583 //\r
1584 // Process the Notify list and dispatch any notifies for\r
1585 // newly installed PPIs.\r
1586 //\r
f2bc359c 1587 ProcessDispatchNotifyList (Private);\r
58dcdada 1588\r
bfb685da 1589 //\r
f2bc359c 1590 // Recheck SwitchStackSignal after ProcessDispatchNotifyList()\r
bfb685da
SZ
1591 // in case PeiInstallPeiMemory() is done in a callback with\r
1592 // EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH.\r
1593 //\r
1594 PeiCheckAndSwitchStack (SecCoreData, Private);\r
1595\r
c2c4199b 1596 if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISTER_FOR_SHADOW) && \\r
9bedaec0
MK
1597 (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||\r
1598 (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) ||\r
1599 PcdGetBool (PcdShadowPeimOnS3Boot))\r
1600 ) {\r
b0d803fe 1601 //\r
6393d9c8 1602 // If memory is available we shadow images by default for performance reasons.\r
58dcdada 1603 // We call the entry point a 2nd time so the module knows it's shadowed.\r
b0d803fe 1604 //\r
1605 //PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0);\r
9bedaec0
MK
1606 if ((Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) && !PcdGetBool (PcdShadowPeimOnBoot) &&\r
1607 !PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) {\r
3d44658c
LG
1608 //\r
1609 // Load PEIM into Memory for Register for shadow PEIM.\r
1610 //\r
1611 Status = PeiLoadImage (\r
1612 PeiServices,\r
1613 PeimFileHandle,\r
c2c4199b 1614 PEIM_STATE_REGISTER_FOR_SHADOW,\r
3d44658c
LG
1615 &EntryPoint,\r
1616 &AuthenticationState\r
1617 );\r
1618 if (Status == EFI_SUCCESS) {\r
1619 PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;\r
1620 }\r
1621 }\r
e67ca95c 1622 ASSERT (PeimEntryPoint != NULL);\r
797a9d67 1623 PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);\r
b0d803fe 1624 //PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0);\r
58dcdada 1625\r
b0d803fe 1626 //\r
c2c4199b 1627 // PEIM_STATE_REGISTER_FOR_SHADOW move to PEIM_STATE_DONE\r
b0d803fe 1628 //\r
1629 Private->Fv[FvCount].PeimState[PeimCount]++;\r
192f6d4c 1630\r
192f6d4c 1631 //\r
b0d803fe 1632 // Process the Notify list and dispatch any notifies for\r
1633 // newly installed PPIs.\r
192f6d4c 1634 //\r
f2bc359c 1635 ProcessDispatchNotifyList (Private);\r
192f6d4c 1636 }\r
1637 }\r
1638 }\r
192f6d4c 1639 }\r
192f6d4c 1640\r
b0d803fe 1641 //\r
b62fe570 1642 // Before walking through the next FV, we should set them to NULL/0 to\r
93b8ed68 1643 // start at the beginning of the next FV.\r
b0d803fe 1644 //\r
1645 Private->CurrentFileHandle = NULL;\r
1646 Private->CurrentPeimCount = 0;\r
b62fe570 1647 Private->CurrentFvFileHandles = NULL;\r
192f6d4c 1648 }\r
1649\r
1650 //\r
b62fe570
SZ
1651 // Before making another pass, we should set it to 0 to\r
1652 // go through all the FVs.\r
192f6d4c 1653 //\r
b0d803fe 1654 Private->CurrentPeimFvCount = 0;\r
192f6d4c 1655\r
1656 //\r
116cd856 1657 // PeimNeedingDispatch being TRUE means we found a PEIM/FV that did not get\r
b0d803fe 1658 // dispatched. So we need to make another pass\r
192f6d4c 1659 //\r
116cd856
SZ
1660 // PeimDispatchOnThisPass being TRUE means we dispatched a PEIM/FV on this\r
1661 // pass. If we did not dispatch a PEIM/FV there is no point in trying again\r
b0d803fe 1662 // as it will fail the next time too (nothing has changed).\r
192f6d4c 1663 //\r
82b8c8df 1664 } while (Private->PeimNeedingDispatch && Private->PeimDispatchOnThisPass);\r
192f6d4c 1665\r
192f6d4c 1666}\r
1667\r
b1f6a7c6 1668/**\r
192f6d4c 1669 Initialize the Dispatcher's data members\r
1670\r
b1f6a7c6 1671 @param PrivateData PeiCore's private data structure\r
1672 @param OldCoreData Old data from SecCore\r
93b8ed68 1673 NULL if being run in non-permanent memory mode.\r
b1f6a7c6 1674 @param SecCoreData Points to a data structure containing information about the PEI core's operating\r
5aae0aa7 1675 environment, such as the size and location of temporary RAM, the stack location and\r
1676 the BFV location.\r
192f6d4c 1677\r
b1f6a7c6 1678 @return None.\r
192f6d4c 1679\r
b1f6a7c6 1680**/\r
1681VOID\r
1682InitializeDispatcherData (\r
1683 IN PEI_CORE_INSTANCE *PrivateData,\r
1684 IN PEI_CORE_INSTANCE *OldCoreData,\r
1685 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData\r
1686 )\r
192f6d4c 1687{\r
192f6d4c 1688 if (OldCoreData == NULL) {\r
82b8c8df 1689 PrivateData->PeimDispatcherReenter = FALSE;\r
b0d803fe 1690 PeiInitializeFv (PrivateData, SecCoreData);\r
8e0e40ed 1691 } else {\r
7ec93917 1692 PeiReinitializeFv (PrivateData);\r
192f6d4c 1693 }\r
1694\r
1695 return;\r
1696}\r
1697\r
b1f6a7c6 1698/**\r
1699 This routine parses the Dependency Expression, if available, and\r
1700 decides if the module can be executed.\r
1701\r
1702\r
1703 @param Private PeiCore's private data structure\r
1704 @param FileHandle PEIM's file handle\r
1705 @param PeimCount Peim count in all dispatched PEIMs.\r
192f6d4c 1706\r
b1f6a7c6 1707 @retval TRUE Can be dispatched\r
1708 @retval FALSE Cannot be dispatched\r
1709\r
1710**/\r
192f6d4c 1711BOOLEAN\r
1712DepexSatisfied (\r
b0d803fe 1713 IN PEI_CORE_INSTANCE *Private,\r
1714 IN EFI_PEI_FILE_HANDLE FileHandle,\r
1715 IN UINTN PeimCount\r
192f6d4c 1716 )\r
192f6d4c 1717{\r
288f9b38
LG
1718 EFI_STATUS Status;\r
1719 VOID *DepexData;\r
6a55eea3 1720 EFI_FV_FILE_INFO FileInfo;\r
b0d803fe 1721\r
6a55eea3 1722 Status = PeiServicesFfsGetFileInfo (FileHandle, &FileInfo);\r
1723 if (EFI_ERROR (Status)) {\r
1724 DEBUG ((DEBUG_DISPATCH, "Evaluate PEI DEPEX for FFS(Unknown)\n"));\r
1725 } else {\r
1726 DEBUG ((DEBUG_DISPATCH, "Evaluate PEI DEPEX for FFS(%g)\n", &FileInfo.FileName));\r
1727 }\r
d1102dba 1728\r
b0d803fe 1729 if (PeimCount < Private->AprioriCount) {\r
1730 //\r
d39d1260 1731 // If it's in the Apriori file then we set DEPEX to TRUE\r
b0d803fe 1732 //\r
6a55eea3 1733 DEBUG ((DEBUG_DISPATCH, " RESULT = TRUE (Apriori)\n"));\r
b0d803fe 1734 return TRUE;\r
1735 }\r
58dcdada 1736\r
288f9b38 1737 //\r
58dcdada 1738 // Depex section not in the encapsulated section.\r
288f9b38
LG
1739 //\r
1740 Status = PeiServicesFfsFindSectionData (\r
1741 EFI_SECTION_PEI_DEPEX,\r
58dcdada 1742 FileHandle,\r
288f9b38
LG
1743 (VOID **)&DepexData\r
1744 );\r
b0d803fe 1745\r
192f6d4c 1746 if (EFI_ERROR (Status)) {\r
b0d803fe 1747 //\r
1748 // If there is no DEPEX, assume the module can be executed\r
1749 //\r
6a55eea3 1750 DEBUG ((DEBUG_DISPATCH, " RESULT = TRUE (No DEPEX)\n"));\r
192f6d4c 1751 return TRUE;\r
1752 }\r
1753\r
1754 //\r
1755 // Evaluate a given DEPEX\r
1756 //\r
4140a663 1757 return PeimDispatchReadiness (&Private->Ps, DepexData);\r
192f6d4c 1758}\r
1759\r
14e8823a 1760/**\r
d3add11e
MK
1761 This routine enables a PEIM to register itself for shadow when the PEI Foundation\r
1762 discovers permanent memory.\r
14e8823a 1763\r
b1f6a7c6 1764 @param FileHandle File handle of a PEIM.\r
58dcdada 1765\r
b1f6a7c6 1766 @retval EFI_NOT_FOUND The file handle doesn't point to PEIM itself.\r
1767 @retval EFI_ALREADY_STARTED Indicate that the PEIM has been registered itself.\r
1768 @retval EFI_SUCCESS Successfully to register itself.\r
14e8823a 1769\r
58dcdada 1770**/\r
14e8823a 1771EFI_STATUS\r
1772EFIAPI\r
1773PeiRegisterForShadow (\r
1774 IN EFI_PEI_FILE_HANDLE FileHandle\r
1775 )\r
1776{\r
1777 PEI_CORE_INSTANCE *Private;\r
1778 Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());\r
1779\r
1780 if (Private->CurrentFileHandle != FileHandle) {\r
1781 //\r
1782 // The FileHandle must be for the current PEIM\r
1783 //\r
1784 return EFI_NOT_FOUND;\r
1785 }\r
1786\r
c2c4199b 1787 if (Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] >= PEIM_STATE_REGISTER_FOR_SHADOW) {\r
14e8823a 1788 //\r
1789 // If the PEIM has already entered the PEIM_STATE_REGISTER_FOR_SHADOW or PEIM_STATE_DONE then it's already been started\r
1790 //\r
1791 return EFI_ALREADY_STARTED;\r
1792 }\r
58dcdada 1793\r
c2c4199b 1794 Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] = PEIM_STATE_REGISTER_FOR_SHADOW;\r
14e8823a 1795\r
1796 return EFI_SUCCESS;\r
1797}\r
1798\r
3b428ade 1799\r
341a658f 1800\r