]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
MdeModulePkg PeiCore: Recheck SwitchStackSignal after ProcessNotifyList()
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Dispatcher / Dispatcher.c
CommitLineData
615c6dd0 1/** @file\r
b1f6a7c6 2 EFI PEI Core dispatch services\r
3 \r
e50a226b 4Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
cd5ebaa0 5This program and the accompanying materials\r
192f6d4c 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
615c6dd0 13**/\r
192f6d4c 14\r
0d516397 15#include "PeiMain.h"\r
192f6d4c 16\r
b1f6a7c6 17///\r
3d4d0c34 18/// temporary memory is filled with this initial value during SEC phase\r
b1f6a7c6 19///\r
a7715e73 20#define INIT_CAR_VALUE 0x5AA55AA5\r
21\r
b1f6a7c6 22/**\r
b0d803fe 23\r
24 Discover all Peims and optional Apriori file in one FV. There is at most one\r
25 Apriori file in one FV.\r
26\r
b0d803fe 27\r
3b428ade 28 @param Private Pointer to the private data passed in from caller\r
29 @param CoreFileHandle The instance of PEI_CORE_FV_HANDLE.\r
b0d803fe 30\r
b1f6a7c6 31**/\r
32VOID\r
33DiscoverPeimsAndOrderWithApriori (\r
34 IN PEI_CORE_INSTANCE *Private,\r
3b428ade 35 IN PEI_CORE_FV_HANDLE *CoreFileHandle\r
b1f6a7c6 36 )\r
b0d803fe 37{\r
38 EFI_STATUS Status;\r
890e5417 39 EFI_PEI_FILE_HANDLE FileHandle;\r
177aabe6 40 EFI_PEI_FILE_HANDLE AprioriFileHandle;\r
b0d803fe 41 EFI_GUID *Apriori;\r
42 UINTN Index;\r
43 UINTN Index2;\r
44 UINTN PeimIndex;\r
45 UINTN PeimCount;\r
46 EFI_GUID *Guid;\r
fe781940
SZ
47 EFI_PEI_FILE_HANDLE *TempFileHandles;\r
48 EFI_GUID *FileGuid;\r
3b428ade 49 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;\r
50 EFI_FV_FILE_INFO FileInfo;\r
51 \r
52 FvPpi = CoreFileHandle->FvPpi;\r
53 \r
b0d803fe 54 //\r
55 // Walk the FV and find all the PEIMs and the Apriori file.\r
56 //\r
57 AprioriFileHandle = NULL;\r
58 Private->CurrentFvFileHandles[0] = NULL;\r
59 Guid = NULL;\r
60 FileHandle = NULL;\r
fe781940
SZ
61 TempFileHandles = Private->FileHandles;\r
62 FileGuid = Private->FileGuid;\r
b0d803fe 63\r
64 //\r
65 // If the current Fv has been scanned, directly get its cachable record.\r
66 //\r
67 if (Private->Fv[Private->CurrentPeimFvCount].ScanFv) {\r
fe781940 68 CopyMem (Private->CurrentFvFileHandles, Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, sizeof (EFI_PEI_FILE_HANDLE) * PcdGet32 (PcdPeiCoreMaxPeimPerFv));\r
b0d803fe 69 return;\r
70 }\r
71\r
72 //\r
73 // Go ahead to scan this Fv, and cache FileHandles within it.\r
74 //\r
9b8e61be 75 Status = EFI_NOT_FOUND;\r
fe781940 76 for (PeimCount = 0; PeimCount <= PcdGet32 (PcdPeiCoreMaxPeimPerFv); PeimCount++) {\r
3b428ade 77 Status = FvPpi->FindFileByType (FvPpi, PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE, CoreFileHandle->FvHandle, &FileHandle);\r
fe781940 78 if (Status != EFI_SUCCESS || PeimCount == PcdGet32 (PcdPeiCoreMaxPeimPerFv)) {\r
b0d803fe 79 break;\r
80 }\r
58dcdada 81\r
b0d803fe 82 Private->CurrentFvFileHandles[PeimCount] = FileHandle;\r
83 }\r
9b8e61be 84\r
97b2c9b5 85 //\r
21d9882c
LG
86 // Check whether the count of files exceeds the max support files in a FV image\r
87 // If more files are required in a FV image, PcdPeiCoreMaxPeimPerFv can be set to a larger value in DSC file.\r
97b2c9b5 88 //\r
fe781940 89 ASSERT ((Status != EFI_SUCCESS) || (PeimCount < PcdGet32 (PcdPeiCoreMaxPeimPerFv)));\r
b0d803fe 90\r
3b428ade 91 //\r
92 // Get Apriori File handle\r
93 //\r
58dcdada 94 Private->AprioriCount = 0;\r
3b428ade 95 Status = FvPpi->FindFileByName (FvPpi, &gPeiAprioriFileNameGuid, &CoreFileHandle->FvHandle, &AprioriFileHandle);\r
96 if (!EFI_ERROR(Status) && AprioriFileHandle != NULL) {\r
b0d803fe 97 //\r
98 // Read the Apriori file\r
99 //\r
3b428ade 100 Status = FvPpi->FindSectionByType (FvPpi, EFI_SECTION_RAW, AprioriFileHandle, (VOID **) &Apriori);\r
b0d803fe 101 if (!EFI_ERROR (Status)) {\r
102 //\r
103 // Calculate the number of PEIMs in the A Priori list\r
104 //\r
3b428ade 105 Status = FvPpi->GetFileInfo (FvPpi, AprioriFileHandle, &FileInfo);\r
106 ASSERT_EFI_ERROR (Status);\r
890e5417
SZ
107 Private->AprioriCount = FileInfo.BufferSize;\r
108 if (IS_SECTION2 (FileInfo.Buffer)) {\r
109 Private->AprioriCount -= sizeof (EFI_COMMON_SECTION_HEADER2);\r
110 } else {\r
111 Private->AprioriCount -= sizeof (EFI_COMMON_SECTION_HEADER);\r
112 }\r
b0d803fe 113 Private->AprioriCount /= sizeof (EFI_GUID);\r
58dcdada 114\r
b0d803fe 115 for (Index = 0; Index < PeimCount; Index++) {\r
116 //\r
117 // Make an array of file name guids that matches the FileHandle array so we can convert\r
118 // quickly from file name to file handle\r
119 //\r
3b428ade 120 Status = FvPpi->GetFileInfo (FvPpi, Private->CurrentFvFileHandles[Index], &FileInfo);\r
121 CopyMem (&FileGuid[Index], &FileInfo.FileName, sizeof(EFI_GUID));\r
b0d803fe 122 }\r
123\r
124 //\r
125 // Walk through FileGuid array to find out who is invalid PEIM guid in Apriori file.\r
890e5417 126 // Add available PEIMs in Apriori file into TempFileHandles array at first.\r
b0d803fe 127 //\r
128 Index2 = 0;\r
129 for (Index = 0; Index2 < Private->AprioriCount; Index++) {\r
130 while (Index2 < Private->AprioriCount) {\r
131 Guid = ScanGuid (FileGuid, PeimCount * sizeof (EFI_GUID), &Apriori[Index2++]);\r
132 if (Guid != NULL) {\r
133 break;\r
134 }\r
135 }\r
136 if (Guid == NULL) {\r
58dcdada 137 break;\r
b0d803fe 138 }\r
139 PeimIndex = ((UINTN)Guid - (UINTN)&FileGuid[0])/sizeof (EFI_GUID);\r
140 TempFileHandles[Index] = Private->CurrentFvFileHandles[PeimIndex];\r
141\r
142 //\r
143 // Since we have copied the file handle we can remove it from this list.\r
144 //\r
145 Private->CurrentFvFileHandles[PeimIndex] = NULL;\r
146 }\r
147\r
148 //\r
149 // Update valid Aprioricount\r
150 //\r
151 Private->AprioriCount = Index;\r
58dcdada 152\r
b0d803fe 153 //\r
154 // Add in any PEIMs not in the Apriori file\r
155 //\r
156 for (;Index < PeimCount; Index++) {\r
157 for (Index2 = 0; Index2 < PeimCount; Index2++) {\r
158 if (Private->CurrentFvFileHandles[Index2] != NULL) {\r
159 TempFileHandles[Index] = Private->CurrentFvFileHandles[Index2];\r
160 Private->CurrentFvFileHandles[Index2] = NULL;\r
161 break;\r
162 }\r
163 }\r
164 }\r
165 //\r
166 //Index the end of array contains re-range Pei moudle.\r
167 //\r
168 TempFileHandles[Index] = NULL;\r
58dcdada 169\r
b0d803fe 170 //\r
171 // Private->CurrentFvFileHandles is currently in PEIM in the FV order.\r
58dcdada 172 // We need to update it to start with files in the A Priori list and\r
173 // then the remaining files in PEIM order.\r
b0d803fe 174 //\r
fe781940 175 CopyMem (Private->CurrentFvFileHandles, TempFileHandles, sizeof (EFI_PEI_FILE_HANDLE) * PcdGet32 (PcdPeiCoreMaxPeimPerFv));\r
b0d803fe 176 }\r
177 }\r
178 //\r
179 // Cache the current Fv File Handle. So that we don't have to scan the Fv again.\r
180 // Instead, we can retrieve the file handles within this Fv from cachable data.\r
181 //\r
182 Private->Fv[Private->CurrentPeimFvCount].ScanFv = TRUE;\r
fe781940 183 CopyMem (Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, Private->CurrentFvFileHandles, sizeof (EFI_PEI_FILE_HANDLE) * PcdGet32 (PcdPeiCoreMaxPeimPerFv));\r
58dcdada 184\r
185}\r
186\r
54ea99a7 187//\r
188// This is the minimum memory required by DxeCore initialization. When LMFA feature enabled,\r
189// This part of memory still need reserved on the very top of memory so that the DXE Core could \r
190// use these memory for data initialization. This macro should be sync with the same marco\r
191// defined in DXE Core.\r
192//\r
193#define MINIMUM_INITIAL_MEMORY_SIZE 0x10000\r
9bfb4940 194/**\r
195 This function is to test if the memory range described in resource HOB is available or not. \r
196 \r
197 This function should only be invoked when Loading Module at Fixed Address(LMFA) feature is enabled. Some platform may allocate the \r
198 memory before PeiLoadFixAddressHook in invoked. so this function is to test if the memory range described by the input resource HOB is\r
199 available or not.\r
200\r
201 @param PrivateData Pointer to the private data passed in from caller\r
202 @param ResourceHob Pointer to a resource HOB which described the memory range described by the input resource HOB\r
203**/\r
204BOOLEAN\r
205PeiLoadFixAddressIsMemoryRangeAvailable (\r
206 IN PEI_CORE_INSTANCE *PrivateData,\r
207 IN EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob\r
208 )\r
209{\r
210 EFI_HOB_MEMORY_ALLOCATION *MemoryHob;\r
211 BOOLEAN IsAvailable;\r
212 EFI_PEI_HOB_POINTERS Hob;\r
213 \r
214 IsAvailable = TRUE;\r
215 if (PrivateData == NULL || ResourceHob == NULL) {\r
216 return FALSE;\r
217 }\r
218 //\r
219 // test if the memory range describe in the HOB is already allocated.\r
220 //\r
221 for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
222 // \r
223 // See if this is a memory allocation HOB \r
224 //\r
225 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) { \r
226 MemoryHob = Hob.MemoryAllocation;\r
227 if(MemoryHob->AllocDescriptor.MemoryBaseAddress == ResourceHob->PhysicalStart && \r
228 MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength == ResourceHob->PhysicalStart + ResourceHob->ResourceLength) {\r
229 IsAvailable = FALSE;\r
230 break; \r
231 }\r
232 }\r
233 }\r
234 \r
235 return IsAvailable;\r
236 \r
237}\r
54ea99a7 238/**\r
239 Hook function for Loading Module at Fixed Address feature\r
240 \r
241 This function should only be invoked when Loading Module at Fixed Address(LMFA) feature is enabled. When feature is\r
242 configured as Load Modules at Fix Absolute Address, this function is to validate the top address assigned by user. When \r
243 feature is configured as Load Modules at Fixed Offset, the functino is to find the top address which is TOLM-TSEG in general. \r
244 And also the function will re-install PEI memory. \r
b0d803fe 245\r
54ea99a7 246 @param PrivateData Pointer to the private data passed in from caller\r
247\r
248**/\r
249VOID\r
250PeiLoadFixAddressHook(\r
251 IN PEI_CORE_INSTANCE *PrivateData\r
252 )\r
253{\r
254 EFI_PHYSICAL_ADDRESS TopLoadingAddress;\r
255 UINT64 PeiMemorySize;\r
256 UINT64 TotalReservedMemorySize;\r
257 UINT64 MemoryRangeEnd;\r
258 EFI_PHYSICAL_ADDRESS HighAddress; \r
259 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;\r
260 EFI_HOB_RESOURCE_DESCRIPTOR *NextResourceHob;\r
261 EFI_HOB_RESOURCE_DESCRIPTOR *CurrentResourceHob;\r
262 EFI_PEI_HOB_POINTERS CurrentHob;\r
263 EFI_PEI_HOB_POINTERS Hob;\r
264 EFI_PEI_HOB_POINTERS NextHob;\r
9bfb4940 265 EFI_HOB_MEMORY_ALLOCATION *MemoryHob;\r
54ea99a7 266 //\r
267 // Initialize Local Variables\r
268 //\r
269 CurrentResourceHob = NULL;\r
270 ResourceHob = NULL;\r
271 NextResourceHob = NULL;\r
54ea99a7 272 HighAddress = 0;\r
273 TopLoadingAddress = 0;\r
274 MemoryRangeEnd = 0;\r
275 CurrentHob.Raw = PrivateData->HobList.Raw;\r
276 PeiMemorySize = PrivateData->PhysicalMemoryLength;\r
277 //\r
278 // The top reserved memory include 3 parts: the topest range is for DXE core initialization with the size MINIMUM_INITIAL_MEMORY_SIZE\r
279 // then RuntimeCodePage range and Boot time code range.\r
280 // \r
e18fa167 281 TotalReservedMemorySize = MINIMUM_INITIAL_MEMORY_SIZE + EFI_PAGES_TO_SIZE(PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber));\r
282 TotalReservedMemorySize+= EFI_PAGES_TO_SIZE(PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber)) ; \r
54ea99a7 283 //\r
284 // PEI memory range lies below the top reserved memory\r
285 // \r
286 TotalReservedMemorySize += PeiMemorySize;\r
e18fa167 287 \r
852081fc 288 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressRuntimeCodePageNumber= 0x%x.\n", PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber)));\r
289 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressBootTimeCodePageNumber= 0x%x.\n", PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber)));\r
290 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressPeiCodePageNumber= 0x%x.\n", PcdGet32(PcdLoadFixAddressPeiCodePageNumber))); \r
291 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: Total Reserved Memory Size = 0x%lx.\n", TotalReservedMemorySize));\r
54ea99a7 292 //\r
293 // Loop through the system memory typed hob to merge the adjacent memory range \r
294 //\r
295 for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
296 // \r
297 // See if this is a resource descriptor HOB \r
298 //\r
299 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
300 \r
301 ResourceHob = Hob.ResourceDescriptor; \r
302 //\r
303 // If range described in this hob is not system memory or heigher than MAX_ADDRESS, ignored.\r
304 //\r
63e70348 305 if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY ||\r
54ea99a7 306 ResourceHob->PhysicalStart + ResourceHob->ResourceLength > MAX_ADDRESS) {\r
307 continue;\r
308 } \r
309 \r
310 for (NextHob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(NextHob); NextHob.Raw = GET_NEXT_HOB(NextHob)) { \r
311 if (NextHob.Raw == Hob.Raw){\r
312 continue;\r
313 } \r
314 //\r
315 // See if this is a resource descriptor HOB\r
316 //\r
317 if (GET_HOB_TYPE (NextHob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
318 \r
319 NextResourceHob = NextHob.ResourceDescriptor;\r
320 //\r
321 // test if range described in this NextResourceHob is system memory and have the same attribute.\r
322 // Note: Here is a assumption that system memory should always be healthy even without test.\r
323 // \r
324 if (NextResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&\r
325 (((NextResourceHob->ResourceAttribute^ResourceHob->ResourceAttribute)&(~EFI_RESOURCE_ATTRIBUTE_TESTED)) == 0)){\r
326 \r
327 //\r
328 // See if the memory range described in ResourceHob and NextResourceHob is adjacent\r
329 //\r
330 if ((ResourceHob->PhysicalStart <= NextResourceHob->PhysicalStart && \r
331 ResourceHob->PhysicalStart + ResourceHob->ResourceLength >= NextResourceHob->PhysicalStart)|| \r
332 (ResourceHob->PhysicalStart >= NextResourceHob->PhysicalStart&&\r
333 ResourceHob->PhysicalStart <= NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength)) {\r
334 \r
335 MemoryRangeEnd = ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength)>(NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength)) ?\r
336 (ResourceHob->PhysicalStart + ResourceHob->ResourceLength):(NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength);\r
337 \r
338 ResourceHob->PhysicalStart = (ResourceHob->PhysicalStart < NextResourceHob->PhysicalStart) ? \r
339 ResourceHob->PhysicalStart : NextResourceHob->PhysicalStart;\r
340 \r
341 \r
342 ResourceHob->ResourceLength = (MemoryRangeEnd - ResourceHob->PhysicalStart);\r
343 \r
344 ResourceHob->ResourceAttribute = ResourceHob->ResourceAttribute & (~EFI_RESOURCE_ATTRIBUTE_TESTED);\r
345 //\r
346 // Delete the NextResourceHob by marking it as unused.\r
347 //\r
348 GET_HOB_TYPE (NextHob) = EFI_HOB_TYPE_UNUSED;\r
349 \r
350 }\r
351 }\r
352 } \r
353 }\r
354 } \r
355 }\r
9bfb4940 356 //\r
357 // Some platform is already allocated pages before the HOB re-org. Here to build dedicated resource HOB to describe\r
358 // the allocated memory range\r
359 //\r
360 for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
361 // \r
362 // See if this is a memory allocation HOB \r
363 //\r
364 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {\r
365 MemoryHob = Hob.MemoryAllocation;\r
366 for (NextHob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(NextHob); NextHob.Raw = GET_NEXT_HOB(NextHob)) {\r
367 //\r
368 // See if this is a resource descriptor HOB\r
369 //\r
370 if (GET_HOB_TYPE (NextHob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
371 NextResourceHob = NextHob.ResourceDescriptor;\r
372 //\r
373 // If range described in this hob is not system memory or heigher than MAX_ADDRESS, ignored.\r
374 //\r
63e70348 375 if (NextResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY || NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength > MAX_ADDRESS) {\r
9bfb4940 376 continue;\r
377 }\r
378 //\r
379 // If the range describe in memory allocation HOB belongs to the memroy range described by the resource hob\r
380 // \r
381 if (MemoryHob->AllocDescriptor.MemoryBaseAddress >= NextResourceHob->PhysicalStart && \r
382 MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength <= NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength) {\r
383 //\r
384 // Build seperate resource hob for this allocated range\r
385 // \r
386 if (MemoryHob->AllocDescriptor.MemoryBaseAddress > NextResourceHob->PhysicalStart) {\r
387 BuildResourceDescriptorHob (\r
388 EFI_RESOURCE_SYSTEM_MEMORY, \r
389 NextResourceHob->ResourceAttribute,\r
390 NextResourceHob->PhysicalStart, \r
391 (MemoryHob->AllocDescriptor.MemoryBaseAddress - NextResourceHob->PhysicalStart) \r
392 );\r
393 }\r
394 if (MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength < NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength) {\r
395 BuildResourceDescriptorHob (\r
396 EFI_RESOURCE_SYSTEM_MEMORY, \r
397 NextResourceHob->ResourceAttribute,\r
398 MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength, \r
399 (NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength -(MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength)) \r
400 );\r
401 }\r
402 NextResourceHob->PhysicalStart = MemoryHob->AllocDescriptor.MemoryBaseAddress;\r
403 NextResourceHob->ResourceLength = MemoryHob->AllocDescriptor.MemoryLength;\r
404 break;\r
405 }\r
406 }\r
407 }\r
408 }\r
409 }\r
410\r
54ea99a7 411 //\r
412 // Try to find and validate the TOP address.\r
413 // \r
852081fc 414 if ((INT64)PcdGet64(PcdLoadModuleAtFixAddressEnable) > 0 ) {\r
54ea99a7 415 //\r
416 // The LMFA feature is enabled as load module at fixed absolute address.\r
417 //\r
852081fc 418 TopLoadingAddress = (EFI_PHYSICAL_ADDRESS)PcdGet64(PcdLoadModuleAtFixAddressEnable);\r
54ea99a7 419 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: Loading module at fixed absolute address.\n"));\r
420 //\r
421 // validate the Address. Loop the resource descriptor HOB to make sure the address is in valid memory range\r
422 //\r
423 if ((TopLoadingAddress & EFI_PAGE_MASK) != 0) {\r
852081fc 424 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:Top Address 0x%lx is invalid since top address should be page align. \n", TopLoadingAddress)); \r
54ea99a7 425 ASSERT (FALSE); \r
426 }\r
427 //\r
428 // Search for a memory region that is below MAX_ADDRESS and in which TopLoadingAddress lies \r
429 //\r
430 for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
431 //\r
432 // See if this is a resource descriptor HOB\r
433 //\r
434 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
435\r
436 ResourceHob = Hob.ResourceDescriptor;\r
437 //\r
438 // See if this resource descrior HOB describes tested system memory below MAX_ADDRESS\r
439 // \r
440 if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&\r
441 ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS) {\r
442 //\r
443 // See if Top address specified by user is valid.\r
444 //\r
445 if (ResourceHob->PhysicalStart + TotalReservedMemorySize < TopLoadingAddress && \r
9bfb4940 446 (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MINIMUM_INITIAL_MEMORY_SIZE) >= TopLoadingAddress && \r
447 PeiLoadFixAddressIsMemoryRangeAvailable(PrivateData, ResourceHob)) {\r
54ea99a7 448 CurrentResourceHob = ResourceHob; \r
449 CurrentHob = Hob;\r
450 break;\r
9bfb4940 451 }\r
54ea99a7 452 }\r
453 } \r
454 } \r
455 if (CurrentResourceHob != NULL) {\r
852081fc 456 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO:Top Address 0x%lx is valid \n", TopLoadingAddress));\r
54ea99a7 457 TopLoadingAddress += MINIMUM_INITIAL_MEMORY_SIZE; \r
458 } else {\r
852081fc 459 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:Top Address 0x%lx is invalid \n", TopLoadingAddress)); \r
54ea99a7 460 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:The recommended Top Address for the platform is: \n")); \r
461 //\r
462 // Print the recomended Top address range.\r
463 // \r
464 for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
465 //\r
466 // See if this is a resource descriptor HOB\r
467 //\r
468 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
469 \r
470 ResourceHob = Hob.ResourceDescriptor;\r
471 //\r
472 // See if this resource descrior HOB describes tested system memory below MAX_ADDRESS\r
473 // \r
474 if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&\r
475 ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS) {\r
476 //\r
477 // See if Top address specified by user is valid.\r
478 //\r
9bfb4940 479 if (ResourceHob->ResourceLength > TotalReservedMemorySize && PeiLoadFixAddressIsMemoryRangeAvailable(PrivateData, ResourceHob)) {\r
852081fc 480 DEBUG ((EFI_D_INFO, "(0x%lx, 0x%lx)\n", \r
54ea99a7 481 (ResourceHob->PhysicalStart + TotalReservedMemorySize -MINIMUM_INITIAL_MEMORY_SIZE), \r
482 (ResourceHob->PhysicalStart + ResourceHob->ResourceLength -MINIMUM_INITIAL_MEMORY_SIZE) \r
483 )); \r
484 }\r
485 }\r
486 }\r
487 } \r
488 //\r
489 // Assert here \r
490 //\r
9bfb4940 491 ASSERT (FALSE); \r
492 return; \r
54ea99a7 493 } \r
494 } else {\r
495 //\r
496 // The LMFA feature is enabled as load module at fixed offset relative to TOLM\r
497 // Parse the Hob list to find the topest available memory. Generally it is (TOLM - TSEG)\r
498 //\r
499 //\r
500 // Search for a tested memory region that is below MAX_ADDRESS\r
501 //\r
502 for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
503 //\r
504 // See if this is a resource descriptor HOB \r
505 //\r
506 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
507 \r
508 ResourceHob = Hob.ResourceDescriptor; \r
509 //\r
510 // See if this resource descrior HOB describes tested system memory below MAX_ADDRESS\r
511 //\r
512 if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY && \r
513 ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS &&\r
9bfb4940 514 ResourceHob->ResourceLength > TotalReservedMemorySize && PeiLoadFixAddressIsMemoryRangeAvailable(PrivateData, ResourceHob)) {\r
54ea99a7 515 //\r
516 // See if this is the highest largest system memory region below MaxAddress\r
517 //\r
518 if (ResourceHob->PhysicalStart > HighAddress) {\r
519 CurrentResourceHob = ResourceHob;\r
520 CurrentHob = Hob;\r
521 HighAddress = CurrentResourceHob->PhysicalStart;\r
522 }\r
523 }\r
524 } \r
525 }\r
526 if (CurrentResourceHob == NULL) {\r
527 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:The System Memory is too small\n")); \r
528 //\r
529 // Assert here \r
530 //\r
9bfb4940 531 ASSERT (FALSE);\r
532 return; \r
54ea99a7 533 } else {\r
534 TopLoadingAddress = CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength ; \r
535 } \r
536 }\r
537 \r
538 if (CurrentResourceHob != NULL) {\r
539 //\r
9bfb4940 540 // rebuild resource HOB for PEI memmory and reserved memory\r
54ea99a7 541 //\r
542 BuildResourceDescriptorHob (\r
9bfb4940 543 EFI_RESOURCE_SYSTEM_MEMORY, \r
54ea99a7 544 (\r
545 EFI_RESOURCE_ATTRIBUTE_PRESENT |\r
546 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |\r
547 EFI_RESOURCE_ATTRIBUTE_TESTED |\r
548 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |\r
549 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |\r
550 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |\r
551 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE\r
552 ),\r
9bfb4940 553 (TopLoadingAddress - TotalReservedMemorySize), \r
554 TotalReservedMemorySize \r
54ea99a7 555 );\r
556 //\r
9bfb4940 557 // rebuild resource for the remain memory if necessary\r
54ea99a7 558 //\r
559 if (CurrentResourceHob->PhysicalStart < TopLoadingAddress - TotalReservedMemorySize) {\r
560 BuildResourceDescriptorHob (\r
9bfb4940 561 EFI_RESOURCE_SYSTEM_MEMORY, \r
54ea99a7 562 (\r
563 EFI_RESOURCE_ATTRIBUTE_PRESENT |\r
564 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |\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
9bfb4940 570 CurrentResourceHob->PhysicalStart, \r
571 (TopLoadingAddress - TotalReservedMemorySize - CurrentResourceHob->PhysicalStart) \r
54ea99a7 572 );\r
573 }\r
574 if (CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength > TopLoadingAddress ) {\r
575 BuildResourceDescriptorHob (\r
576 EFI_RESOURCE_SYSTEM_MEMORY, \r
577 (\r
578 EFI_RESOURCE_ATTRIBUTE_PRESENT |\r
579 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |\r
580 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |\r
581 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |\r
582 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |\r
583 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE\r
584 ),\r
585 TopLoadingAddress, \r
586 (CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength - TopLoadingAddress) \r
587 );\r
588 }\r
589 //\r
590 // Delete CurrentHob by marking it as unused since the the memory range described by is rebuilt.\r
591 //\r
592 GET_HOB_TYPE (CurrentHob) = EFI_HOB_TYPE_UNUSED; \r
593 }\r
594\r
595 //\r
596 // Cache the top address for Loading Module at Fixed Address feature\r
597 //\r
598 PrivateData->LoadModuleAtFixAddressTopAddress = TopLoadingAddress - MINIMUM_INITIAL_MEMORY_SIZE;\r
852081fc 599 DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: Top address = 0x%lx\n", PrivateData->LoadModuleAtFixAddressTopAddress)); \r
54ea99a7 600 //\r
601 // reinstall the PEI memory relative to TopLoadingAddress\r
602 //\r
603 PrivateData->PhysicalMemoryBegin = TopLoadingAddress - TotalReservedMemorySize;\r
604 PrivateData->FreePhysicalMemoryTop = PrivateData->PhysicalMemoryBegin + PeiMemorySize;\r
605}\r
0f9ebb32
LG
606\r
607/**\r
608 This routine is invoked in switch stack as PeiCore Entry.\r
609\r
610 @param SecCoreData Points to a data structure containing information about the PEI core's operating\r
611 environment, such as the size and location of temporary RAM, the stack location and\r
612 the BFV location.\r
613 @param Private Pointer to old core data that is used to initialize the\r
614 core's data areas.\r
615**/\r
616VOID\r
617EFIAPI\r
618PeiCoreEntry (\r
619 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,\r
620 IN PEI_CORE_INSTANCE *Private\r
621 )\r
622{\r
623 //\r
624 // Entry PEI Phase 2\r
625 //\r
626 PeiCore (SecCoreData, NULL, Private);\r
627}\r
628\r
bfb685da
SZ
629/**\r
630 Check SwitchStackSignal and switch stack if SwitchStackSignal is TRUE.\r
631\r
632 @param[in] SecCoreData Points to a data structure containing information about the PEI core's operating\r
633 environment, such as the size and location of temporary RAM, the stack location and\r
634 the BFV location.\r
635 @param[in] Private Pointer to the private data passed in from caller.\r
636\r
637**/\r
638VOID\r
639PeiCheckAndSwitchStack (\r
640 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,\r
641 IN PEI_CORE_INSTANCE *Private\r
642 )\r
643{\r
644 VOID *LoadFixPeiCodeBegin;\r
645 EFI_STATUS Status;\r
646 CONST EFI_PEI_SERVICES **PeiServices;\r
647 UINT64 NewStackSize;\r
648 EFI_PHYSICAL_ADDRESS TopOfOldStack;\r
649 EFI_PHYSICAL_ADDRESS TopOfNewStack;\r
650 UINTN StackOffset;\r
651 BOOLEAN StackOffsetPositive;\r
652 EFI_PHYSICAL_ADDRESS TemporaryRamBase;\r
653 UINTN TemporaryRamSize;\r
654 UINTN TemporaryStackSize;\r
655 VOID *TemporaryStackBase;\r
656 UINTN PeiTemporaryRamSize;\r
657 VOID *PeiTemporaryRamBase;\r
658 EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI *TemporaryRamSupportPpi;\r
659 EFI_PHYSICAL_ADDRESS BaseOfNewHeap;\r
660 EFI_PHYSICAL_ADDRESS HoleMemBase;\r
661 UINTN HoleMemSize;\r
662 UINTN HeapTemporaryRamSize;\r
663 EFI_PHYSICAL_ADDRESS TempBase1;\r
664 UINTN TempSize1;\r
665 EFI_PHYSICAL_ADDRESS TempBase2;\r
666 UINTN TempSize2;\r
667 UINTN Index;\r
668\r
669 PeiServices = (CONST EFI_PEI_SERVICES **) &Private->Ps;\r
670\r
671 if (Private->SwitchStackSignal) {\r
672 //\r
673 // Before switch stack from temporary memory to permenent memory, calculate the heap and stack\r
674 // usage in temporary memory for debuging.\r
675 //\r
676 DEBUG_CODE_BEGIN ();\r
677 UINT32 *StackPointer;\r
678\r
679 for (StackPointer = (UINT32*)SecCoreData->StackBase;\r
680 (StackPointer < (UINT32*)((UINTN)SecCoreData->StackBase + SecCoreData->StackSize)) \\r
681 && (*StackPointer == INIT_CAR_VALUE);\r
682 StackPointer ++);\r
683\r
684 DEBUG ((EFI_D_INFO, "Temp Stack : BaseAddress=0x%p Length=0x%X\n", SecCoreData->StackBase, (UINT32)SecCoreData->StackSize));\r
685 DEBUG ((EFI_D_INFO, "Temp Heap : BaseAddress=0x%p Length=0x%X\n", Private->HobList.Raw, (UINT32)((UINTN) Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - (UINTN) Private->HobList.Raw)));\r
686 DEBUG ((EFI_D_INFO, "Total temporary memory: %d bytes.\n", (UINT32)SecCoreData->TemporaryRamSize));\r
687 DEBUG ((EFI_D_INFO, " temporary memory stack ever used: %d bytes.\n",\r
688 (UINT32)(SecCoreData->StackSize - ((UINTN) StackPointer - (UINTN)SecCoreData->StackBase))\r
689 ));\r
690 DEBUG ((EFI_D_INFO, " temporary memory heap used: %d bytes.\n",\r
691 (UINT32)((UINTN)Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - (UINTN)Private->HobList.Raw)\r
692 ));\r
693 DEBUG_CODE_END ();\r
694\r
695 if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0 && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
696 //\r
697 // Loading Module at Fixed Address is enabled\r
698 //\r
699 PeiLoadFixAddressHook (Private);\r
700\r
701 //\r
702 // If Loading Module at Fixed Address is enabled, Allocating memory range for Pei code range.\r
703 //\r
704 LoadFixPeiCodeBegin = AllocatePages((UINTN)PcdGet32(PcdLoadFixAddressPeiCodePageNumber));\r
705 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
706 }\r
707\r
708 //\r
709 // Reserve the size of new stack at bottom of physical memory\r
710 //\r
711 // The size of new stack in permenent memory must be the same size \r
712 // or larger than the size of old stack in temporary memory.\r
713 // But if new stack is smaller than the size of old stack, we also reserve\r
714 // the size of old stack at bottom of permenent memory.\r
715 //\r
716 NewStackSize = RShiftU64 (Private->PhysicalMemoryLength, 1);\r
717 NewStackSize = ALIGN_VALUE (NewStackSize, EFI_PAGE_SIZE);\r
718 NewStackSize = MIN (PcdGet32(PcdPeiCoreMaxPeiStackSize), NewStackSize);\r
719 DEBUG ((EFI_D_INFO, "Old Stack size %d, New stack size %d\n", (UINT32)SecCoreData->StackSize, (UINT32)NewStackSize));\r
720 ASSERT (NewStackSize >= SecCoreData->StackSize);\r
721\r
722 //\r
723 // Calculate stack offset and heap offset between temporary memory and new permement \r
724 // memory seperately.\r
725 //\r
726 TopOfOldStack = (UINTN)SecCoreData->StackBase + SecCoreData->StackSize;\r
727 TopOfNewStack = Private->PhysicalMemoryBegin + NewStackSize;\r
728 if (TopOfNewStack >= TopOfOldStack) {\r
729 StackOffsetPositive = TRUE;\r
730 StackOffset = (UINTN)(TopOfNewStack - TopOfOldStack);\r
731 } else {\r
732 StackOffsetPositive = FALSE;\r
733 StackOffset = (UINTN)(TopOfOldStack - TopOfNewStack);\r
734 }\r
735 Private->StackOffsetPositive = StackOffsetPositive;\r
736 Private->StackOffset = StackOffset;\r
737\r
738 //\r
739 // Build Stack HOB that describes the permanent memory stack\r
740 //\r
741 DEBUG ((EFI_D_INFO, "Stack Hob: BaseAddress=0x%lX Length=0x%lX\n", TopOfNewStack - NewStackSize, NewStackSize));\r
742 BuildStackHob (TopOfNewStack - NewStackSize, NewStackSize);\r
743\r
744 //\r
745 // Cache information from SecCoreData into locals before SecCoreData is converted to a permanent memory address\r
746 //\r
747 TemporaryRamBase = (EFI_PHYSICAL_ADDRESS)(UINTN)SecCoreData->TemporaryRamBase;\r
748 TemporaryRamSize = SecCoreData->TemporaryRamSize;\r
749 TemporaryStackSize = SecCoreData->StackSize;\r
750 TemporaryStackBase = SecCoreData->StackBase;\r
751 PeiTemporaryRamSize = SecCoreData->PeiTemporaryRamSize;\r
752 PeiTemporaryRamBase = SecCoreData->PeiTemporaryRamBase;\r
753\r
754 //\r
755 // TemporaryRamSupportPpi is produced by platform's SEC\r
756 //\r
757 Status = PeiServicesLocatePpi (\r
758 &gEfiTemporaryRamSupportPpiGuid,\r
759 0,\r
760 NULL,\r
761 (VOID**)&TemporaryRamSupportPpi\r
762 );\r
763 if (!EFI_ERROR (Status)) {\r
764 //\r
765 // Heap Offset\r
766 //\r
767 BaseOfNewHeap = TopOfNewStack;\r
768 if (BaseOfNewHeap >= (UINTN)SecCoreData->PeiTemporaryRamBase) {\r
769 Private->HeapOffsetPositive = TRUE;\r
770 Private->HeapOffset = (UINTN)(BaseOfNewHeap - (UINTN)SecCoreData->PeiTemporaryRamBase);\r
771 } else {\r
772 Private->HeapOffsetPositive = FALSE;\r
773 Private->HeapOffset = (UINTN)((UINTN)SecCoreData->PeiTemporaryRamBase - BaseOfNewHeap);\r
774 }\r
775\r
776 DEBUG ((EFI_D_INFO, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (UINT64) Private->HeapOffset, (UINT64) Private->StackOffset));\r
777\r
778 //\r
779 // Calculate new HandOffTable and PrivateData address in permanent memory's stack\r
780 //\r
781 if (StackOffsetPositive) {\r
782 SecCoreData = (CONST EFI_SEC_PEI_HAND_OFF *)((UINTN)(VOID *)SecCoreData + StackOffset);\r
783 Private = (PEI_CORE_INSTANCE *)((UINTN)(VOID *)Private + StackOffset);\r
784 } else {\r
785 SecCoreData = (CONST EFI_SEC_PEI_HAND_OFF *)((UINTN)(VOID *)SecCoreData - StackOffset);\r
786 Private = (PEI_CORE_INSTANCE *)((UINTN)(VOID *)Private - StackOffset);\r
787 }\r
788\r
789 //\r
790 // Temporary Ram Support PPI is provided by platform, it will copy \r
791 // temporary memory to permenent memory and do stack switching.\r
792 // After invoking Temporary Ram Support PPI, the following code's \r
793 // stack is in permanent memory.\r
794 //\r
795 TemporaryRamSupportPpi->TemporaryRamMigration (\r
796 PeiServices,\r
797 TemporaryRamBase,\r
798 (EFI_PHYSICAL_ADDRESS)(UINTN)(TopOfNewStack - TemporaryStackSize),\r
799 TemporaryRamSize\r
800 );\r
801\r
802 //\r
803 // Entry PEI Phase 2\r
804 //\r
805 PeiCore (SecCoreData, NULL, Private);\r
806 } else {\r
807 //\r
808 // Migrate the PEI Services Table pointer from temporary RAM to permanent RAM.\r
809 //\r
810 MigratePeiServicesTablePointer ();\r
811 \r
812 //\r
813 // Heap Offset\r
814 //\r
815 BaseOfNewHeap = TopOfNewStack;\r
816 HoleMemBase = TopOfNewStack;\r
817 HoleMemSize = TemporaryRamSize - PeiTemporaryRamSize - TemporaryStackSize;\r
818 if (HoleMemSize != 0) {\r
819 //\r
820 // Make sure HOB List start address is 8 byte alignment.\r
821 //\r
822 BaseOfNewHeap = ALIGN_VALUE (BaseOfNewHeap + HoleMemSize, 8);\r
823 }\r
824 if (BaseOfNewHeap >= (UINTN)SecCoreData->PeiTemporaryRamBase) {\r
825 Private->HeapOffsetPositive = TRUE;\r
826 Private->HeapOffset = (UINTN)(BaseOfNewHeap - (UINTN)SecCoreData->PeiTemporaryRamBase);\r
827 } else {\r
828 Private->HeapOffsetPositive = FALSE;\r
829 Private->HeapOffset = (UINTN)((UINTN)SecCoreData->PeiTemporaryRamBase - BaseOfNewHeap);\r
830 }\r
831\r
832 DEBUG ((EFI_D_INFO, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (UINT64) Private->HeapOffset, (UINT64) Private->StackOffset));\r
833\r
834 //\r
835 // Migrate Heap\r
836 //\r
837 HeapTemporaryRamSize = (UINTN) (Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - Private->HobList.HandoffInformationTable->EfiMemoryBottom);\r
838 ASSERT (BaseOfNewHeap + HeapTemporaryRamSize <= Private->FreePhysicalMemoryTop);\r
839 CopyMem ((UINT8 *) (UINTN) BaseOfNewHeap, (UINT8 *) PeiTemporaryRamBase, HeapTemporaryRamSize);\r
840\r
841 //\r
842 // Migrate Stack\r
843 //\r
844 CopyMem ((UINT8 *) (UINTN) (TopOfNewStack - TemporaryStackSize), TemporaryStackBase, TemporaryStackSize);\r
845\r
846 //\r
847 // Copy Hole Range Data\r
848 // Convert PPI from Hole. \r
849 //\r
850 if (HoleMemSize != 0) {\r
851 //\r
852 // Prepare Hole\r
853 //\r
854 if (PeiTemporaryRamBase < TemporaryStackBase) {\r
855 TempBase1 = (EFI_PHYSICAL_ADDRESS) (UINTN) PeiTemporaryRamBase;\r
856 TempSize1 = PeiTemporaryRamSize;\r
857 TempBase2 = (EFI_PHYSICAL_ADDRESS) (UINTN) TemporaryStackBase;\r
858 TempSize2 = TemporaryStackSize;\r
859 } else {\r
860 TempBase1 = (EFI_PHYSICAL_ADDRESS) (UINTN) TemporaryStackBase;\r
861 TempSize1 = TemporaryStackSize;\r
862 TempBase2 =(EFI_PHYSICAL_ADDRESS) (UINTN) PeiTemporaryRamBase;\r
863 TempSize2 = PeiTemporaryRamSize;\r
864 }\r
865 if (TemporaryRamBase < TempBase1) {\r
866 Private->HoleData[0].Base = TemporaryRamBase;\r
867 Private->HoleData[0].Size = (UINTN) (TempBase1 - TemporaryRamBase);\r
868 }\r
869 if (TempBase1 + TempSize1 < TempBase2) {\r
870 Private->HoleData[1].Base = TempBase1 + TempSize1;\r
871 Private->HoleData[1].Size = (UINTN) (TempBase2 - TempBase1 - TempSize1);\r
872 }\r
873 if (TempBase2 + TempSize2 < TemporaryRamBase + TemporaryRamSize) {\r
874 Private->HoleData[2].Base = TempBase2 + TempSize2;\r
875 Private->HoleData[2].Size = (UINTN) (TemporaryRamBase + TemporaryRamSize - TempBase2 - TempSize2);\r
876 }\r
877\r
878 //\r
879 // Copy Hole Range data.\r
880 //\r
881 for (Index = 0; Index < HOLE_MAX_NUMBER; Index ++) {\r
882 if (Private->HoleData[Index].Size > 0) {\r
883 if (HoleMemBase > Private->HoleData[Index].Base) {\r
884 Private->HoleData[Index].OffsetPositive = TRUE;\r
885 Private->HoleData[Index].Offset = (UINTN) (HoleMemBase - Private->HoleData[Index].Base);\r
886 } else {\r
887 Private->HoleData[Index].OffsetPositive = FALSE;\r
888 Private->HoleData[Index].Offset = (UINTN) (Private->HoleData[Index].Base - HoleMemBase);\r
889 }\r
890 CopyMem ((VOID *) (UINTN) HoleMemBase, (VOID *) (UINTN) Private->HoleData[Index].Base, Private->HoleData[Index].Size);\r
891 HoleMemBase = HoleMemBase + Private->HoleData[Index].Size;\r
892 }\r
893 }\r
894 }\r
895\r
896 //\r
897 // Switch new stack\r
898 //\r
899 SwitchStack (\r
900 (SWITCH_STACK_ENTRY_POINT)(UINTN)PeiCoreEntry,\r
901 (VOID *) SecCoreData,\r
902 (VOID *) Private,\r
903 (VOID *) (UINTN) TopOfNewStack\r
904 );\r
905 }\r
906\r
907 //\r
908 // Code should not come here\r
909 //\r
910 ASSERT (FALSE);\r
911 }\r
912}\r
913\r
b1f6a7c6 914/**\r
192f6d4c 915 Conduct PEIM dispatch.\r
916\r
b1f6a7c6 917 @param SecCoreData Points to a data structure containing information about the PEI core's operating\r
5aae0aa7 918 environment, such as the size and location of temporary RAM, the stack location and\r
919 the BFV location.\r
b1f6a7c6 920 @param Private Pointer to the private data passed in from caller\r
192f6d4c 921\r
b1f6a7c6 922**/\r
923VOID\r
924PeiDispatcher (\r
925 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,\r
926 IN PEI_CORE_INSTANCE *Private\r
927 )\r
192f6d4c 928{\r
b0d803fe 929 EFI_STATUS Status;\r
930 UINT32 Index1;\r
931 UINT32 Index2;\r
6c7a807a 932 CONST EFI_PEI_SERVICES **PeiServices;\r
b0d803fe 933 EFI_PEI_FILE_HANDLE PeimFileHandle;\r
934 UINTN FvCount;\r
935 UINTN PeimCount;\r
936 UINT32 AuthenticationState;\r
937 EFI_PHYSICAL_ADDRESS EntryPoint;\r
797a9d67 938 EFI_PEIM_ENTRY_POINT2 PeimEntryPoint;\r
b0d803fe 939 UINTN SaveCurrentPeimCount;\r
1053e0c5 940 UINTN SaveCurrentFvCount;\r
b0d803fe 941 EFI_PEI_FILE_HANDLE SaveCurrentFileHandle;\r
288f9b38 942 EFI_FV_FILE_INFO FvFileInfo;\r
3b428ade 943 PEI_CORE_FV_HANDLE *CoreFvHandle;\r
0f9ebb32 944 \r
4140a663 945 PeiServices = (CONST EFI_PEI_SERVICES **) &Private->Ps;\r
b0d803fe 946 PeimEntryPoint = NULL;\r
947 PeimFileHandle = NULL;\r
288f9b38 948 EntryPoint = 0;\r
b0d803fe 949\r
5d7f3126 950 if ((Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME || PcdGetBool (PcdShadowPeimOnS3Boot))) {\r
b0d803fe 951 //\r
952 // Once real memory is available, shadow the RegisterForShadow modules. And meanwhile\r
953 // update the modules' status from PEIM_STATE_REGISITER_FOR_SHADOW to PEIM_STATE_DONE.\r
954 //\r
955 SaveCurrentPeimCount = Private->CurrentPeimCount;\r
1053e0c5 956 SaveCurrentFvCount = Private->CurrentPeimFvCount;\r
b0d803fe 957 SaveCurrentFileHandle = Private->CurrentFileHandle;\r
958\r
1053e0c5 959 for (Index1 = 0; Index1 <= SaveCurrentFvCount; Index1++) {\r
fe781940 960 for (Index2 = 0; (Index2 < PcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->Fv[Index1].FvFileHandles[Index2] != NULL); Index2++) {\r
b0d803fe 961 if (Private->Fv[Index1].PeimState[Index2] == PEIM_STATE_REGISITER_FOR_SHADOW) {\r
58dcdada 962 PeimFileHandle = Private->Fv[Index1].FvFileHandles[Index2];\r
3d44658c
LG
963 Private->CurrentFileHandle = PeimFileHandle;\r
964 Private->CurrentPeimFvCount = Index1;\r
965 Private->CurrentPeimCount = Index2;\r
b0d803fe 966 Status = PeiLoadImage (\r
4140a663 967 (CONST EFI_PEI_SERVICES **) &Private->Ps,\r
58dcdada 968 PeimFileHandle,\r
341a658f 969 PEIM_STATE_REGISITER_FOR_SHADOW,\r
58dcdada 970 &EntryPoint,\r
b0d803fe 971 &AuthenticationState\r
972 );\r
973 if (Status == EFI_SUCCESS) {\r
974 //\r
975 // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE\r
976 //\r
977 Private->Fv[Index1].PeimState[Index2]++;\r
b0d803fe 978 //\r
979 // Call the PEIM entry point\r
980 //\r
797a9d67 981 PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;\r
58dcdada 982\r
087e13cb 983 PERF_START (PeimFileHandle, "PEIM", NULL, 0);\r
4140a663 984 PeimEntryPoint(PeimFileHandle, (const EFI_PEI_SERVICES **) &Private->Ps);\r
087e13cb 985 PERF_END (PeimFileHandle, "PEIM", NULL, 0);\r
58dcdada 986 }\r
987\r
b0d803fe 988 //\r
989 // Process the Notify list and dispatch any notifies for\r
990 // newly installed PPIs.\r
991 //\r
992 ProcessNotifyList (Private);\r
993 }\r
994 }\r
995 }\r
58dcdada 996 Private->CurrentFileHandle = SaveCurrentFileHandle;\r
997 Private->CurrentPeimFvCount = SaveCurrentFvCount;\r
998 Private->CurrentPeimCount = SaveCurrentPeimCount;\r
b0d803fe 999 }\r
192f6d4c 1000\r
1001 //\r
1002 // This is the main dispatch loop. It will search known FVs for PEIMs and\r
1003 // attempt to dispatch them. If any PEIM gets dispatched through a single\r
1004 // pass of the dispatcher, it will start over from the Bfv again to see\r
1005 // if any new PEIMs dependencies got satisfied. With a well ordered\r
1006 // FV where PEIMs are found in the order their dependencies are also\r
1007 // satisfied, this dipatcher should run only once.\r
1008 //\r
b0d803fe 1009 do {\r
82b8c8df 1010 //\r
1011 // In case that reenter PeiCore happens, the last pass record is still available. \r
1012 //\r
1013 if (!Private->PeimDispatcherReenter) {\r
1014 Private->PeimNeedingDispatch = FALSE;\r
1015 Private->PeimDispatchOnThisPass = FALSE;\r
1016 } else {\r
1017 Private->PeimDispatcherReenter = FALSE;\r
1018 }\r
1019 \r
b0d803fe 1020 for (FvCount = Private->CurrentPeimFvCount; FvCount < Private->FvCount; FvCount++) {\r
3b428ade 1021 CoreFvHandle = FindNextCoreFvHandle (Private, FvCount);\r
1022 ASSERT (CoreFvHandle != NULL);\r
1023 \r
2a00326e 1024 //\r
3b428ade 1025 // If the FV has corresponding EFI_PEI_FIRMWARE_VOLUME_PPI instance, then dispatch it.\r
2a00326e 1026 //\r
3b428ade 1027 if (CoreFvHandle->FvPpi == NULL) {\r
1028 continue;\r
1029 }\r
1030 \r
1031 Private->CurrentPeimFvCount = FvCount;\r
192f6d4c 1032\r
b0d803fe 1033 if (Private->CurrentPeimCount == 0) {\r
1034 //\r
1035 // When going through each FV, at first, search Apriori file to\r
58dcdada 1036 // reorder all PEIMs to ensure the PEIMs in Apriori file to get\r
b0d803fe 1037 // dispatch at first.\r
1038 //\r
3b428ade 1039 DiscoverPeimsAndOrderWithApriori (Private, CoreFvHandle);\r
b0d803fe 1040 }\r
192f6d4c 1041\r
1042 //\r
b0d803fe 1043 // Start to dispatch all modules within the current Fv.\r
192f6d4c 1044 //\r
58dcdada 1045 for (PeimCount = Private->CurrentPeimCount;\r
fe781940 1046 (PeimCount < PcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->CurrentFvFileHandles[PeimCount] != NULL);\r
b0d803fe 1047 PeimCount++) {\r
1048 Private->CurrentPeimCount = PeimCount;\r
1049 PeimFileHandle = Private->CurrentFileHandle = Private->CurrentFvFileHandles[PeimCount];\r
1050\r
1051 if (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_NOT_DISPATCHED) {\r
1052 if (!DepexSatisfied (Private, PeimFileHandle, PeimCount)) {\r
82b8c8df 1053 Private->PeimNeedingDispatch = TRUE;\r
b0d803fe 1054 } else {\r
3b428ade 1055 Status = CoreFvHandle->FvPpi->GetFileInfo (CoreFvHandle->FvPpi, PeimFileHandle, &FvFileInfo);\r
288f9b38
LG
1056 ASSERT_EFI_ERROR (Status);\r
1057 if (FvFileInfo.FileType == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {\r
1058 //\r
1059 // For Fv type file, Produce new FV PPI and FV hob\r
1060 //\r
c7935105
SZ
1061 Status = ProcessFvFile (Private, &Private->Fv[FvCount], PeimFileHandle);\r
1062 if (Status == EFI_SUCCESS) {\r
1063 //\r
1064 // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED\r
1065 //\r
1066 Private->Fv[FvCount].PeimState[PeimCount]++;\r
1067 Private->PeimDispatchOnThisPass = TRUE;\r
1068 }\r
288f9b38
LG
1069 } else {\r
1070 //\r
1071 // For PEIM driver, Load its entry point\r
1072 //\r
1073 Status = PeiLoadImage (\r
58dcdada 1074 PeiServices,\r
1075 PeimFileHandle,\r
341a658f 1076 PEIM_STATE_NOT_DISPATCHED,\r
58dcdada 1077 &EntryPoint,\r
288f9b38
LG
1078 &AuthenticationState\r
1079 );\r
c7935105 1080 if (Status == EFI_SUCCESS) {\r
b0d803fe 1081 //\r
c7935105
SZ
1082 // The PEIM has its dependencies satisfied, and its entry point\r
1083 // has been found, so invoke it.\r
b0d803fe 1084 //\r
c7935105 1085 PERF_START (PeimFileHandle, "PEIM", NULL, 0);\r
58dcdada 1086\r
c7935105
SZ
1087 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
1088 EFI_PROGRESS_CODE,\r
1089 (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN),\r
fa3d30ea
LG
1090 (VOID *)(&PeimFileHandle),\r
1091 sizeof (PeimFileHandle)\r
c7935105
SZ
1092 );\r
1093\r
1094 Status = VerifyPeim (Private, CoreFvHandle->FvHandle, PeimFileHandle, AuthenticationState);\r
1095 if (Status != EFI_SECURITY_VIOLATION) {\r
1096 //\r
1097 // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED\r
1098 //\r
1099 Private->Fv[FvCount].PeimState[PeimCount]++;\r
288f9b38
LG
1100 //\r
1101 // Call the PEIM entry point for PEIM driver\r
1102 //\r
797a9d67 1103 PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;\r
1104 PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);\r
c7935105 1105 Private->PeimDispatchOnThisPass = TRUE;\r
288f9b38 1106 }\r
797a9d67 1107\r
c7935105
SZ
1108 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
1109 EFI_PROGRESS_CODE,\r
1110 (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_END),\r
fa3d30ea
LG
1111 (VOID *)(&PeimFileHandle),\r
1112 sizeof (PeimFileHandle)\r
c7935105
SZ
1113 );\r
1114 PERF_END (PeimFileHandle, "PEIM", NULL, 0);\r
b0d803fe 1115\r
c7935105 1116 }\r
58dcdada 1117 }\r
1118\r
bfb685da 1119 PeiCheckAndSwitchStack (SecCoreData, Private);\r
192f6d4c 1120\r
58dcdada 1121 //\r
1122 // Process the Notify list and dispatch any notifies for\r
1123 // newly installed PPIs.\r
1124 //\r
1125 ProcessNotifyList (Private);\r
1126\r
bfb685da
SZ
1127 //\r
1128 // Recheck SwitchStackSignal after ProcessNotifyList()\r
1129 // in case PeiInstallPeiMemory() is done in a callback with\r
1130 // EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH.\r
1131 //\r
1132 PeiCheckAndSwitchStack (SecCoreData, Private);\r
1133\r
b0d803fe 1134 if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISITER_FOR_SHADOW) && \\r
5d7f3126 1135 (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME || PcdGetBool (PcdShadowPeimOnS3Boot))) {\r
b0d803fe 1136 //\r
58dcdada 1137 // If memory is availble we shadow images by default for performance reasons.\r
1138 // We call the entry point a 2nd time so the module knows it's shadowed.\r
b0d803fe 1139 //\r
1140 //PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0);\r
3d44658c
LG
1141 if ((Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) && !PcdGetBool (PcdShadowPeimOnBoot)) {\r
1142 //\r
1143 // Load PEIM into Memory for Register for shadow PEIM.\r
1144 //\r
1145 Status = PeiLoadImage (\r
1146 PeiServices,\r
1147 PeimFileHandle,\r
1148 PEIM_STATE_REGISITER_FOR_SHADOW,\r
1149 &EntryPoint,\r
1150 &AuthenticationState\r
1151 );\r
1152 if (Status == EFI_SUCCESS) {\r
1153 PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;\r
1154 }\r
1155 }\r
e67ca95c 1156 ASSERT (PeimEntryPoint != NULL);\r
797a9d67 1157 PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);\r
b0d803fe 1158 //PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0);\r
58dcdada 1159\r
b0d803fe 1160 //\r
1161 // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE\r
1162 //\r
1163 Private->Fv[FvCount].PeimState[PeimCount]++;\r
192f6d4c 1164\r
192f6d4c 1165 //\r
b0d803fe 1166 // Process the Notify list and dispatch any notifies for\r
1167 // newly installed PPIs.\r
192f6d4c 1168 //\r
b0d803fe 1169 ProcessNotifyList (Private);\r
192f6d4c 1170 }\r
1171 }\r
1172 }\r
192f6d4c 1173 }\r
192f6d4c 1174\r
b0d803fe 1175 //\r
1176 // We set to NULL here to optimize the 2nd entry to this routine after\r
1177 // memory is found. This reprevents rescanning of the FV. We set to\r
1178 // NULL here so we start at the begining of the next FV\r
1179 //\r
1180 Private->CurrentFileHandle = NULL;\r
1181 Private->CurrentPeimCount = 0;\r
1182 //\r
1183 // Before walking through the next FV,Private->CurrentFvFileHandles[]should set to NULL\r
1184 //\r
fe781940 1185 SetMem (Private->CurrentFvFileHandles, sizeof (EFI_PEI_FILE_HANDLE) * PcdGet32 (PcdPeiCoreMaxPeimPerFv), 0);\r
192f6d4c 1186 }\r
1187\r
1188 //\r
58dcdada 1189 // Before making another pass, we should set Private->CurrentPeimFvCount =0 to go\r
b0d803fe 1190 // through all the FV.\r
192f6d4c 1191 //\r
b0d803fe 1192 Private->CurrentPeimFvCount = 0;\r
192f6d4c 1193\r
1194 //\r
58dcdada 1195 // PeimNeedingDispatch being TRUE means we found a PEIM that did not get\r
b0d803fe 1196 // dispatched. So we need to make another pass\r
192f6d4c 1197 //\r
58dcdada 1198 // PeimDispatchOnThisPass being TRUE means we dispatched a PEIM on this\r
b0d803fe 1199 // pass. If we did not dispatch a PEIM there is no point in trying again\r
1200 // as it will fail the next time too (nothing has changed).\r
192f6d4c 1201 //\r
82b8c8df 1202 } while (Private->PeimNeedingDispatch && Private->PeimDispatchOnThisPass);\r
192f6d4c 1203\r
192f6d4c 1204}\r
1205\r
b1f6a7c6 1206/**\r
192f6d4c 1207 Initialize the Dispatcher's data members\r
1208\r
b1f6a7c6 1209 @param PrivateData PeiCore's private data structure\r
1210 @param OldCoreData Old data from SecCore\r
192f6d4c 1211 NULL if being run in non-permament memory mode.\r
b1f6a7c6 1212 @param SecCoreData Points to a data structure containing information about the PEI core's operating\r
5aae0aa7 1213 environment, such as the size and location of temporary RAM, the stack location and\r
1214 the BFV location.\r
192f6d4c 1215\r
b1f6a7c6 1216 @return None.\r
192f6d4c 1217\r
b1f6a7c6 1218**/\r
1219VOID\r
1220InitializeDispatcherData (\r
1221 IN PEI_CORE_INSTANCE *PrivateData,\r
1222 IN PEI_CORE_INSTANCE *OldCoreData,\r
1223 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData\r
1224 )\r
192f6d4c 1225{\r
192f6d4c 1226 if (OldCoreData == NULL) {\r
82b8c8df 1227 PrivateData->PeimDispatcherReenter = FALSE;\r
b0d803fe 1228 PeiInitializeFv (PrivateData, SecCoreData);\r
8e0e40ed 1229 } else {\r
7ec93917 1230 PeiReinitializeFv (PrivateData);\r
192f6d4c 1231 }\r
1232\r
1233 return;\r
1234}\r
1235\r
b1f6a7c6 1236/**\r
1237 This routine parses the Dependency Expression, if available, and\r
1238 decides if the module can be executed.\r
1239\r
1240\r
1241 @param Private PeiCore's private data structure\r
1242 @param FileHandle PEIM's file handle\r
1243 @param PeimCount Peim count in all dispatched PEIMs.\r
192f6d4c 1244\r
b1f6a7c6 1245 @retval TRUE Can be dispatched\r
1246 @retval FALSE Cannot be dispatched\r
1247\r
1248**/\r
192f6d4c 1249BOOLEAN\r
1250DepexSatisfied (\r
b0d803fe 1251 IN PEI_CORE_INSTANCE *Private,\r
1252 IN EFI_PEI_FILE_HANDLE FileHandle,\r
1253 IN UINTN PeimCount\r
192f6d4c 1254 )\r
192f6d4c 1255{\r
288f9b38
LG
1256 EFI_STATUS Status;\r
1257 VOID *DepexData;\r
6a55eea3 1258 EFI_FV_FILE_INFO FileInfo;\r
b0d803fe 1259\r
6a55eea3 1260 Status = PeiServicesFfsGetFileInfo (FileHandle, &FileInfo);\r
1261 if (EFI_ERROR (Status)) {\r
1262 DEBUG ((DEBUG_DISPATCH, "Evaluate PEI DEPEX for FFS(Unknown)\n"));\r
1263 } else {\r
1264 DEBUG ((DEBUG_DISPATCH, "Evaluate PEI DEPEX for FFS(%g)\n", &FileInfo.FileName));\r
1265 }\r
1266 \r
b0d803fe 1267 if (PeimCount < Private->AprioriCount) {\r
1268 //\r
1269 // If its in the A priori file then we set Depex to TRUE\r
1270 //\r
6a55eea3 1271 DEBUG ((DEBUG_DISPATCH, " RESULT = TRUE (Apriori)\n"));\r
b0d803fe 1272 return TRUE;\r
1273 }\r
58dcdada 1274\r
288f9b38 1275 //\r
58dcdada 1276 // Depex section not in the encapsulated section.\r
288f9b38
LG
1277 //\r
1278 Status = PeiServicesFfsFindSectionData (\r
1279 EFI_SECTION_PEI_DEPEX,\r
58dcdada 1280 FileHandle,\r
288f9b38
LG
1281 (VOID **)&DepexData\r
1282 );\r
b0d803fe 1283\r
192f6d4c 1284 if (EFI_ERROR (Status)) {\r
b0d803fe 1285 //\r
1286 // If there is no DEPEX, assume the module can be executed\r
1287 //\r
6a55eea3 1288 DEBUG ((DEBUG_DISPATCH, " RESULT = TRUE (No DEPEX)\n"));\r
192f6d4c 1289 return TRUE;\r
1290 }\r
1291\r
1292 //\r
1293 // Evaluate a given DEPEX\r
1294 //\r
4140a663 1295 return PeimDispatchReadiness (&Private->Ps, DepexData);\r
192f6d4c 1296}\r
1297\r
14e8823a 1298/**\r
1299 This routine enable a PEIM to register itself to shadow when PEI Foundation\r
1300 discovery permanent memory.\r
1301\r
b1f6a7c6 1302 @param FileHandle File handle of a PEIM.\r
58dcdada 1303\r
b1f6a7c6 1304 @retval EFI_NOT_FOUND The file handle doesn't point to PEIM itself.\r
1305 @retval EFI_ALREADY_STARTED Indicate that the PEIM has been registered itself.\r
1306 @retval EFI_SUCCESS Successfully to register itself.\r
14e8823a 1307\r
58dcdada 1308**/\r
14e8823a 1309EFI_STATUS\r
1310EFIAPI\r
1311PeiRegisterForShadow (\r
1312 IN EFI_PEI_FILE_HANDLE FileHandle\r
1313 )\r
1314{\r
1315 PEI_CORE_INSTANCE *Private;\r
1316 Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());\r
1317\r
1318 if (Private->CurrentFileHandle != FileHandle) {\r
1319 //\r
1320 // The FileHandle must be for the current PEIM\r
1321 //\r
1322 return EFI_NOT_FOUND;\r
1323 }\r
1324\r
1325 if (Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] >= PEIM_STATE_REGISITER_FOR_SHADOW) {\r
1326 //\r
1327 // If the PEIM has already entered the PEIM_STATE_REGISTER_FOR_SHADOW or PEIM_STATE_DONE then it's already been started\r
1328 //\r
1329 return EFI_ALREADY_STARTED;\r
1330 }\r
58dcdada 1331\r
14e8823a 1332 Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] = PEIM_STATE_REGISITER_FOR_SHADOW;\r
1333\r
1334 return EFI_SUCCESS;\r
1335}\r
1336\r
3b428ade 1337\r
341a658f 1338\r