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