]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
IntelFspPkg: Remove the const condition if statement to refine the code.
[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
b1f6a7c6 629/**\r
192f6d4c 630 Conduct PEIM dispatch.\r
631\r
b1f6a7c6 632 @param SecCoreData Points to a data structure containing information about the PEI core's operating\r
5aae0aa7 633 environment, such as the size and location of temporary RAM, the stack location and\r
634 the BFV location.\r
b1f6a7c6 635 @param Private Pointer to the private data passed in from caller\r
192f6d4c 636\r
b1f6a7c6 637**/\r
638VOID\r
639PeiDispatcher (\r
640 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,\r
641 IN PEI_CORE_INSTANCE *Private\r
642 )\r
192f6d4c 643{\r
b0d803fe 644 EFI_STATUS Status;\r
645 UINT32 Index1;\r
646 UINT32 Index2;\r
6c7a807a 647 CONST EFI_PEI_SERVICES **PeiServices;\r
b0d803fe 648 EFI_PEI_FILE_HANDLE PeimFileHandle;\r
649 UINTN FvCount;\r
650 UINTN PeimCount;\r
651 UINT32 AuthenticationState;\r
652 EFI_PHYSICAL_ADDRESS EntryPoint;\r
797a9d67 653 EFI_PEIM_ENTRY_POINT2 PeimEntryPoint;\r
b0d803fe 654 UINTN SaveCurrentPeimCount;\r
1053e0c5 655 UINTN SaveCurrentFvCount;\r
b0d803fe 656 EFI_PEI_FILE_HANDLE SaveCurrentFileHandle;\r
d0a3ead2 657 EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI *TemporaryRamSupportPpi;\r
ef05e063 658 UINT64 NewStackSize;\r
18d3e280 659 UINTN HeapTemporaryRamSize;\r
0f9ebb32 660 EFI_PHYSICAL_ADDRESS BaseOfNewHeap;\r
ef05e063 661 EFI_PHYSICAL_ADDRESS TopOfNewStack;\r
662 EFI_PHYSICAL_ADDRESS TopOfOldStack;\r
663 EFI_PHYSICAL_ADDRESS TemporaryRamBase;\r
664 UINTN TemporaryRamSize;\r
0f9ebb32
LG
665 UINTN TemporaryStackSize;\r
666 VOID *TemporaryStackBase;\r
667 UINTN PeiTemporaryRamSize;\r
668 VOID *PeiTemporaryRamBase;\r
ef05e063 669 UINTN StackOffset;\r
670 BOOLEAN StackOffsetPositive;\r
0f9ebb32
LG
671 EFI_PHYSICAL_ADDRESS HoleMemBase;\r
672 UINTN HoleMemSize;\r
288f9b38 673 EFI_FV_FILE_INFO FvFileInfo;\r
3b428ade 674 PEI_CORE_FV_HANDLE *CoreFvHandle;\r
54ea99a7 675 VOID *LoadFixPeiCodeBegin;\r
0f9ebb32
LG
676 EFI_PHYSICAL_ADDRESS TempBase1;\r
677 UINTN TempSize1;\r
678 EFI_PHYSICAL_ADDRESS TempBase2;\r
679 UINTN TempSize2;\r
680 UINTN Index;\r
681 \r
4140a663 682 PeiServices = (CONST EFI_PEI_SERVICES **) &Private->Ps;\r
b0d803fe 683 PeimEntryPoint = NULL;\r
684 PeimFileHandle = NULL;\r
288f9b38 685 EntryPoint = 0;\r
b0d803fe 686\r
5d7f3126 687 if ((Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME || PcdGetBool (PcdShadowPeimOnS3Boot))) {\r
b0d803fe 688 //\r
689 // Once real memory is available, shadow the RegisterForShadow modules. And meanwhile\r
690 // update the modules' status from PEIM_STATE_REGISITER_FOR_SHADOW to PEIM_STATE_DONE.\r
691 //\r
692 SaveCurrentPeimCount = Private->CurrentPeimCount;\r
1053e0c5 693 SaveCurrentFvCount = Private->CurrentPeimFvCount;\r
b0d803fe 694 SaveCurrentFileHandle = Private->CurrentFileHandle;\r
695\r
1053e0c5 696 for (Index1 = 0; Index1 <= SaveCurrentFvCount; Index1++) {\r
fe781940 697 for (Index2 = 0; (Index2 < PcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->Fv[Index1].FvFileHandles[Index2] != NULL); Index2++) {\r
b0d803fe 698 if (Private->Fv[Index1].PeimState[Index2] == PEIM_STATE_REGISITER_FOR_SHADOW) {\r
58dcdada 699 PeimFileHandle = Private->Fv[Index1].FvFileHandles[Index2];\r
b0d803fe 700 Status = PeiLoadImage (\r
4140a663 701 (CONST EFI_PEI_SERVICES **) &Private->Ps,\r
58dcdada 702 PeimFileHandle,\r
341a658f 703 PEIM_STATE_REGISITER_FOR_SHADOW,\r
58dcdada 704 &EntryPoint,\r
b0d803fe 705 &AuthenticationState\r
706 );\r
707 if (Status == EFI_SUCCESS) {\r
708 //\r
709 // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE\r
710 //\r
711 Private->Fv[Index1].PeimState[Index2]++;\r
1053e0c5 712 Private->CurrentFileHandle = PeimFileHandle;\r
58dcdada 713 Private->CurrentPeimFvCount = Index1;\r
714 Private->CurrentPeimCount = Index2;\r
b0d803fe 715 //\r
716 // Call the PEIM entry point\r
717 //\r
797a9d67 718 PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;\r
58dcdada 719\r
087e13cb 720 PERF_START (PeimFileHandle, "PEIM", NULL, 0);\r
4140a663 721 PeimEntryPoint(PeimFileHandle, (const EFI_PEI_SERVICES **) &Private->Ps);\r
087e13cb 722 PERF_END (PeimFileHandle, "PEIM", NULL, 0);\r
58dcdada 723 }\r
724\r
b0d803fe 725 //\r
726 // Process the Notify list and dispatch any notifies for\r
727 // newly installed PPIs.\r
728 //\r
729 ProcessNotifyList (Private);\r
730 }\r
731 }\r
732 }\r
58dcdada 733 Private->CurrentFileHandle = SaveCurrentFileHandle;\r
734 Private->CurrentPeimFvCount = SaveCurrentFvCount;\r
735 Private->CurrentPeimCount = SaveCurrentPeimCount;\r
b0d803fe 736 }\r
192f6d4c 737\r
738 //\r
739 // This is the main dispatch loop. It will search known FVs for PEIMs and\r
740 // attempt to dispatch them. If any PEIM gets dispatched through a single\r
741 // pass of the dispatcher, it will start over from the Bfv again to see\r
742 // if any new PEIMs dependencies got satisfied. With a well ordered\r
743 // FV where PEIMs are found in the order their dependencies are also\r
744 // satisfied, this dipatcher should run only once.\r
745 //\r
b0d803fe 746 do {\r
82b8c8df 747 //\r
748 // In case that reenter PeiCore happens, the last pass record is still available. \r
749 //\r
750 if (!Private->PeimDispatcherReenter) {\r
751 Private->PeimNeedingDispatch = FALSE;\r
752 Private->PeimDispatchOnThisPass = FALSE;\r
753 } else {\r
754 Private->PeimDispatcherReenter = FALSE;\r
755 }\r
756 \r
b0d803fe 757 for (FvCount = Private->CurrentPeimFvCount; FvCount < Private->FvCount; FvCount++) {\r
3b428ade 758 CoreFvHandle = FindNextCoreFvHandle (Private, FvCount);\r
759 ASSERT (CoreFvHandle != NULL);\r
760 \r
2a00326e 761 //\r
3b428ade 762 // If the FV has corresponding EFI_PEI_FIRMWARE_VOLUME_PPI instance, then dispatch it.\r
2a00326e 763 //\r
3b428ade 764 if (CoreFvHandle->FvPpi == NULL) {\r
765 continue;\r
766 }\r
767 \r
768 Private->CurrentPeimFvCount = FvCount;\r
192f6d4c 769\r
b0d803fe 770 if (Private->CurrentPeimCount == 0) {\r
771 //\r
772 // When going through each FV, at first, search Apriori file to\r
58dcdada 773 // reorder all PEIMs to ensure the PEIMs in Apriori file to get\r
b0d803fe 774 // dispatch at first.\r
775 //\r
3b428ade 776 DiscoverPeimsAndOrderWithApriori (Private, CoreFvHandle);\r
b0d803fe 777 }\r
192f6d4c 778\r
779 //\r
b0d803fe 780 // Start to dispatch all modules within the current Fv.\r
192f6d4c 781 //\r
58dcdada 782 for (PeimCount = Private->CurrentPeimCount;\r
fe781940 783 (PeimCount < PcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->CurrentFvFileHandles[PeimCount] != NULL);\r
b0d803fe 784 PeimCount++) {\r
785 Private->CurrentPeimCount = PeimCount;\r
786 PeimFileHandle = Private->CurrentFileHandle = Private->CurrentFvFileHandles[PeimCount];\r
787\r
788 if (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_NOT_DISPATCHED) {\r
789 if (!DepexSatisfied (Private, PeimFileHandle, PeimCount)) {\r
82b8c8df 790 Private->PeimNeedingDispatch = TRUE;\r
b0d803fe 791 } else {\r
3b428ade 792 Status = CoreFvHandle->FvPpi->GetFileInfo (CoreFvHandle->FvPpi, PeimFileHandle, &FvFileInfo);\r
288f9b38
LG
793 ASSERT_EFI_ERROR (Status);\r
794 if (FvFileInfo.FileType == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {\r
795 //\r
796 // For Fv type file, Produce new FV PPI and FV hob\r
797 //\r
c7935105
SZ
798 Status = ProcessFvFile (Private, &Private->Fv[FvCount], PeimFileHandle);\r
799 if (Status == EFI_SUCCESS) {\r
800 //\r
801 // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED\r
802 //\r
803 Private->Fv[FvCount].PeimState[PeimCount]++;\r
804 Private->PeimDispatchOnThisPass = TRUE;\r
805 }\r
288f9b38
LG
806 } else {\r
807 //\r
808 // For PEIM driver, Load its entry point\r
809 //\r
810 Status = PeiLoadImage (\r
58dcdada 811 PeiServices,\r
812 PeimFileHandle,\r
341a658f 813 PEIM_STATE_NOT_DISPATCHED,\r
58dcdada 814 &EntryPoint,\r
288f9b38
LG
815 &AuthenticationState\r
816 );\r
c7935105 817 if (Status == EFI_SUCCESS) {\r
b0d803fe 818 //\r
c7935105
SZ
819 // The PEIM has its dependencies satisfied, and its entry point\r
820 // has been found, so invoke it.\r
b0d803fe 821 //\r
c7935105 822 PERF_START (PeimFileHandle, "PEIM", NULL, 0);\r
58dcdada 823\r
c7935105
SZ
824 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
825 EFI_PROGRESS_CODE,\r
826 (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN),\r
fa3d30ea
LG
827 (VOID *)(&PeimFileHandle),\r
828 sizeof (PeimFileHandle)\r
c7935105
SZ
829 );\r
830\r
831 Status = VerifyPeim (Private, CoreFvHandle->FvHandle, PeimFileHandle, AuthenticationState);\r
832 if (Status != EFI_SECURITY_VIOLATION) {\r
833 //\r
834 // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED\r
835 //\r
836 Private->Fv[FvCount].PeimState[PeimCount]++;\r
288f9b38
LG
837 //\r
838 // Call the PEIM entry point for PEIM driver\r
839 //\r
797a9d67 840 PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;\r
841 PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);\r
c7935105 842 Private->PeimDispatchOnThisPass = TRUE;\r
288f9b38 843 }\r
797a9d67 844\r
c7935105
SZ
845 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
846 EFI_PROGRESS_CODE,\r
847 (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_END),\r
fa3d30ea
LG
848 (VOID *)(&PeimFileHandle),\r
849 sizeof (PeimFileHandle)\r
c7935105
SZ
850 );\r
851 PERF_END (PeimFileHandle, "PEIM", NULL, 0);\r
b0d803fe 852\r
c7935105 853 }\r
58dcdada 854 }\r
855\r
856 if (Private->SwitchStackSignal) {\r
a7715e73 857 //\r
e50a226b 858 // Before switch stack from temporary memory to permenent memory, calculate the heap and stack\r
a7715e73 859 // usage in temporary memory for debuging.\r
860 //\r
861 DEBUG_CODE_BEGIN ();\r
96317468 862 UINT32 *StackPointer;\r
a7715e73 863 \r
96317468 864 for (StackPointer = (UINT32*)SecCoreData->StackBase;\r
865 (StackPointer < (UINT32*)((UINTN)SecCoreData->StackBase + SecCoreData->StackSize)) \\r
a7715e73 866 && (*StackPointer == INIT_CAR_VALUE);\r
867 StackPointer ++);\r
868 \r
ef05e063 869 DEBUG ((EFI_D_INFO, "Temp Stack : BaseAddress=0x%p Length=0x%X\n", SecCoreData->StackBase, (UINT32)SecCoreData->StackSize));\r
870 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
3d4d0c34 871 DEBUG ((EFI_D_INFO, "Total temporary memory: %d bytes.\n", (UINT32)SecCoreData->TemporaryRamSize));\r
872 DEBUG ((EFI_D_INFO, " temporary memory stack ever used: %d bytes.\n",\r
ef05e063 873 (UINT32)(SecCoreData->StackSize - ((UINTN) StackPointer - (UINTN)SecCoreData->StackBase))\r
a7715e73 874 ));\r
3d4d0c34 875 DEBUG ((EFI_D_INFO, " temporary memory heap used: %d bytes.\n",\r
ef05e063 876 (UINT32)((UINTN)Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - (UINTN)Private->HobList.Raw)\r
a7715e73 877 ));\r
878 DEBUG_CODE_END ();\r
879 \r
f73b3df8 880 if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0 && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
54ea99a7 881 //\r
882 // Loading Module at Fixed Address is enabled\r
883 //\r
ef05e063 884 PeiLoadFixAddressHook (Private);\r
885\r
4fb72076 886 //\r
ef05e063 887 // If Loading Module at Fixed Address is enabled, Allocating memory range for Pei code range.\r
4fb72076 888 //\r
889 LoadFixPeiCodeBegin = AllocatePages((UINTN)PcdGet32(PcdLoadFixAddressPeiCodePageNumber));\r
3978f5d9 890 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
54ea99a7 891 }\r
892 \r
a3a15d21 893 //\r
58dcdada 894 // Reserve the size of new stack at bottom of physical memory\r
a3a15d21 895 //\r
ef05e063 896 // The size of new stack in permenent memory must be the same size \r
897 // or larger than the size of old stack in temporary memory.\r
58dcdada 898 // But if new stack is smaller than the size of old stack, we also reserve\r
899 // the size of old stack at bottom of permenent memory.\r
900 //\r
ef05e063 901 NewStackSize = RShiftU64 (Private->PhysicalMemoryLength, 1);\r
902 NewStackSize = ALIGN_VALUE (NewStackSize, EFI_PAGE_SIZE);\r
903 NewStackSize = MIN (PcdGet32(PcdPeiCoreMaxPeiStackSize), NewStackSize);\r
904 DEBUG ((EFI_D_INFO, "Old Stack size %d, New stack size %d\n", (UINT32)SecCoreData->StackSize, (UINT32)NewStackSize));\r
905 ASSERT (NewStackSize >= SecCoreData->StackSize);\r
d74eeda8 906\r
58dcdada 907 //\r
e50a226b 908 // Calculate stack offset and heap offset between temporary memory and new permement \r
ef05e063 909 // memory seperately.\r
58dcdada 910 //\r
ef05e063 911 TopOfOldStack = (UINTN)SecCoreData->StackBase + SecCoreData->StackSize;\r
912 TopOfNewStack = Private->PhysicalMemoryBegin + NewStackSize;\r
ef05e063 913 if (TopOfNewStack >= TopOfOldStack) {\r
914 StackOffsetPositive = TRUE;\r
915 StackOffset = (UINTN)(TopOfNewStack - TopOfOldStack);\r
916 } else {\r
917 StackOffsetPositive = FALSE;\r
918 StackOffset = (UINTN)(TopOfOldStack - TopOfNewStack);\r
919 }\r
424b7c9f 920 Private->StackOffsetPositive = StackOffsetPositive;\r
921 Private->StackOffset = StackOffset;\r
ef05e063 922\r
192f6d4c 923 //\r
ef05e063 924 // Build Stack HOB that describes the permanent memory stack\r
192f6d4c 925 //\r
ef05e063 926 DEBUG ((EFI_D_INFO, "Stack Hob: BaseAddress=0x%lX Length=0x%lX\n", TopOfNewStack - NewStackSize, NewStackSize));\r
927 BuildStackHob (TopOfNewStack - NewStackSize, NewStackSize);\r
928\r
40f26b8f 929 //\r
ef05e063 930 // Cache information from SecCoreData into locals before SecCoreData is converted to a permanent memory address\r
40f26b8f 931 //\r
0f9ebb32
LG
932 TemporaryRamBase = (EFI_PHYSICAL_ADDRESS)(UINTN)SecCoreData->TemporaryRamBase;\r
933 TemporaryRamSize = SecCoreData->TemporaryRamSize;\r
934 TemporaryStackSize = SecCoreData->StackSize;\r
935 TemporaryStackBase = SecCoreData->StackBase;\r
936 PeiTemporaryRamSize = SecCoreData->PeiTemporaryRamSize;\r
937 PeiTemporaryRamBase = SecCoreData->PeiTemporaryRamBase;\r
938 \r
192f6d4c 939 //\r
58dcdada 940 // TemporaryRamSupportPpi is produced by platform's SEC\r
192f6d4c 941 //\r
ef05e063 942 Status = PeiServicesLocatePpi (\r
58dcdada 943 &gEfiTemporaryRamSupportPpiGuid,\r
944 0,\r
945 NULL,\r
946 (VOID**)&TemporaryRamSupportPpi\r
947 );\r
58dcdada 948 if (!EFI_ERROR (Status)) {\r
0f9ebb32
LG
949 //\r
950 // Heap Offset\r
951 //\r
952 BaseOfNewHeap = TopOfNewStack;\r
953 if (BaseOfNewHeap >= (UINTN)SecCoreData->PeiTemporaryRamBase) {\r
954 Private->HeapOffsetPositive = TRUE;\r
955 Private->HeapOffset = (UINTN)(BaseOfNewHeap - (UINTN)SecCoreData->PeiTemporaryRamBase);\r
956 } else {\r
957 Private->HeapOffsetPositive = FALSE;\r
958 Private->HeapOffset = (UINTN)((UINTN)SecCoreData->PeiTemporaryRamBase - BaseOfNewHeap);\r
959 }\r
6c8cfb07
SZ
960\r
961 DEBUG ((EFI_D_INFO, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (UINT64) Private->HeapOffset, (UINT64) Private->StackOffset));\r
962\r
0f9ebb32 963 //\r
e50a226b 964 // Calculate new HandOffTable and PrivateData address in permanent memory's stack\r
0f9ebb32
LG
965 //\r
966 if (StackOffsetPositive) {\r
967 SecCoreData = (CONST EFI_SEC_PEI_HAND_OFF *)((UINTN)(VOID *)SecCoreData + StackOffset);\r
968 Private = (PEI_CORE_INSTANCE *)((UINTN)(VOID *)Private + StackOffset);\r
969 } else {\r
970 SecCoreData = (CONST EFI_SEC_PEI_HAND_OFF *)((UINTN)(VOID *)SecCoreData - StackOffset);\r
971 Private = (PEI_CORE_INSTANCE *)((UINTN)(VOID *)Private - StackOffset);\r
972 }\r
973\r
40f26b8f 974 //\r
ef05e063 975 // Temporary Ram Support PPI is provided by platform, it will copy \r
40f26b8f 976 // temporary memory to permenent memory and do stack switching.\r
ef05e063 977 // After invoking Temporary Ram Support PPI, the following code's \r
978 // stack is in permanent memory.\r
40f26b8f 979 //\r
58dcdada 980 TemporaryRamSupportPpi->TemporaryRamMigration (\r
ef05e063 981 PeiServices,\r
982 TemporaryRamBase,\r
983 (EFI_PHYSICAL_ADDRESS)(UINTN)(TopOfNewStack - TemporaryStackSize),\r
984 TemporaryRamSize\r
58dcdada 985 );\r
986\r
0f9ebb32
LG
987 //\r
988 // Entry PEI Phase 2\r
989 //\r
990 PeiCore (SecCoreData, NULL, Private);\r
58dcdada 991 } else {\r
ffd332ca
LG
992 //\r
993 // Migrate the PEI Services Table pointer from temporary RAM to permanent RAM.\r
994 //\r
995 MigratePeiServicesTablePointer ();\r
996 \r
b414ea4b 997 //\r
0f9ebb32 998 // Heap Offset\r
b414ea4b 999 //\r
0f9ebb32
LG
1000 BaseOfNewHeap = TopOfNewStack;\r
1001 HoleMemBase = TopOfNewStack;\r
1002 HoleMemSize = TemporaryRamSize - PeiTemporaryRamSize - TemporaryStackSize;\r
1003 if (HoleMemSize != 0) {\r
9b8e61be
LG
1004 //\r
1005 // Make sure HOB List start address is 8 byte alignment.\r
1006 //\r
1007 BaseOfNewHeap = ALIGN_VALUE (BaseOfNewHeap + HoleMemSize, 8);\r
0f9ebb32
LG
1008 }\r
1009 if (BaseOfNewHeap >= (UINTN)SecCoreData->PeiTemporaryRamBase) {\r
1010 Private->HeapOffsetPositive = TRUE;\r
1011 Private->HeapOffset = (UINTN)(BaseOfNewHeap - (UINTN)SecCoreData->PeiTemporaryRamBase);\r
1012 } else {\r
1013 Private->HeapOffsetPositive = FALSE;\r
1014 Private->HeapOffset = (UINTN)((UINTN)SecCoreData->PeiTemporaryRamBase - BaseOfNewHeap);\r
1015 }\r
58dcdada 1016\r
6c8cfb07
SZ
1017 DEBUG ((EFI_D_INFO, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (UINT64) Private->HeapOffset, (UINT64) Private->StackOffset));\r
1018\r
0f9ebb32
LG
1019 //\r
1020 // Migrate Heap\r
1021 //\r
18d3e280
LG
1022 HeapTemporaryRamSize = (UINTN) (Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - Private->HobList.HandoffInformationTable->EfiMemoryBottom);\r
1023 ASSERT (BaseOfNewHeap + HeapTemporaryRamSize <= Private->FreePhysicalMemoryTop);\r
1024 CopyMem ((UINT8 *) (UINTN) BaseOfNewHeap, (UINT8 *) PeiTemporaryRamBase, HeapTemporaryRamSize);\r
0f9ebb32
LG
1025 \r
1026 //\r
1027 // Migrate Stack\r
1028 //\r
1029 CopyMem ((UINT8 *) (UINTN) (TopOfNewStack - TemporaryStackSize), TemporaryStackBase, TemporaryStackSize);\r
1030 \r
1031 //\r
1032 // Copy Hole Range Data\r
1033 // Convert PPI from Hole. \r
1034 //\r
1035 if (HoleMemSize != 0) {\r
1036 //\r
1037 // Prepare Hole\r
1038 //\r
1039 if (PeiTemporaryRamBase < TemporaryStackBase) {\r
1040 TempBase1 = (EFI_PHYSICAL_ADDRESS) (UINTN) PeiTemporaryRamBase;\r
1041 TempSize1 = PeiTemporaryRamSize;\r
1042 TempBase2 = (EFI_PHYSICAL_ADDRESS) (UINTN) TemporaryStackBase;\r
1043 TempSize2 = TemporaryStackSize;\r
1044 } else {\r
1045 TempBase1 = (EFI_PHYSICAL_ADDRESS) (UINTN) TemporaryStackBase;\r
1046 TempSize1 = TemporaryStackSize;\r
1047 TempBase2 =(EFI_PHYSICAL_ADDRESS) (UINTN) PeiTemporaryRamBase;\r
1048 TempSize2 = PeiTemporaryRamSize;\r
1049 }\r
1050 if (TemporaryRamBase < TempBase1) {\r
1051 Private->HoleData[0].Base = TemporaryRamBase;\r
1052 Private->HoleData[0].Size = (UINTN) (TempBase1 - TemporaryRamBase);\r
1053 }\r
1054 if (TempBase1 + TempSize1 < TempBase2) {\r
1055 Private->HoleData[1].Base = TempBase1 + TempSize1;\r
1056 Private->HoleData[1].Size = (UINTN) (TempBase2 - TempBase1 - TempSize1);\r
1057 }\r
1058 if (TempBase2 + TempSize2 < TemporaryRamBase + TemporaryRamSize) {\r
1059 Private->HoleData[2].Base = TempBase2 + TempSize2;\r
1060 Private->HoleData[2].Size = (UINTN) (TemporaryRamBase + TemporaryRamSize - TempBase2 - TempSize2);\r
1061 }\r
1062 \r
1063 //\r
1064 // Copy Hole Range data.\r
1065 //\r
1066 for (Index = 0; Index < HOLE_MAX_NUMBER; Index ++) {\r
1067 if (Private->HoleData[Index].Size > 0) {\r
1068 if (HoleMemBase > Private->HoleData[Index].Base) {\r
1069 Private->HoleData[Index].OffsetPositive = TRUE;\r
1070 Private->HoleData[Index].Offset = (UINTN) (HoleMemBase - Private->HoleData[Index].Base);\r
1071 } else {\r
1072 Private->HoleData[Index].OffsetPositive = FALSE;\r
1073 Private->HoleData[Index].Offset = (UINTN) (Private->HoleData[Index].Base - HoleMemBase);\r
1074 }\r
1075 CopyMem ((VOID *) (UINTN) HoleMemBase, (VOID *) (UINTN) Private->HoleData[Index].Base, Private->HoleData[Index].Size);\r
1076 HoleMemBase = HoleMemBase + Private->HoleData[Index].Size;\r
1077 }\r
1078 }\r
1079 }\r
1080\r
1081 //\r
1082 // Switch new stack\r
1083 //\r
1084 SwitchStack (\r
1085 (SWITCH_STACK_ENTRY_POINT)(UINTN)PeiCoreEntry,\r
1086 (VOID *) SecCoreData,\r
1087 (VOID *) Private,\r
1088 (VOID *) (UINTN) TopOfNewStack\r
1089 );\r
1090 }\r
b0d803fe 1091\r
58dcdada 1092 //\r
1093 // Code should not come here\r
1094 //\r
ef05e063 1095 ASSERT (FALSE);\r
192f6d4c 1096 }\r
192f6d4c 1097\r
58dcdada 1098 //\r
1099 // Process the Notify list and dispatch any notifies for\r
1100 // newly installed PPIs.\r
1101 //\r
1102 ProcessNotifyList (Private);\r
1103\r
b0d803fe 1104 if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISITER_FOR_SHADOW) && \\r
5d7f3126 1105 (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME || PcdGetBool (PcdShadowPeimOnS3Boot))) {\r
b0d803fe 1106 //\r
58dcdada 1107 // If memory is availble we shadow images by default for performance reasons.\r
1108 // We call the entry point a 2nd time so the module knows it's shadowed.\r
b0d803fe 1109 //\r
1110 //PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0);\r
e67ca95c 1111 ASSERT (PeimEntryPoint != NULL);\r
797a9d67 1112 PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);\r
b0d803fe 1113 //PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0);\r
58dcdada 1114\r
b0d803fe 1115 //\r
1116 // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE\r
1117 //\r
1118 Private->Fv[FvCount].PeimState[PeimCount]++;\r
192f6d4c 1119\r
192f6d4c 1120 //\r
b0d803fe 1121 // Process the Notify list and dispatch any notifies for\r
1122 // newly installed PPIs.\r
192f6d4c 1123 //\r
b0d803fe 1124 ProcessNotifyList (Private);\r
192f6d4c 1125 }\r
1126 }\r
1127 }\r
192f6d4c 1128 }\r
192f6d4c 1129\r
b0d803fe 1130 //\r
1131 // We set to NULL here to optimize the 2nd entry to this routine after\r
1132 // memory is found. This reprevents rescanning of the FV. We set to\r
1133 // NULL here so we start at the begining of the next FV\r
1134 //\r
1135 Private->CurrentFileHandle = NULL;\r
1136 Private->CurrentPeimCount = 0;\r
1137 //\r
1138 // Before walking through the next FV,Private->CurrentFvFileHandles[]should set to NULL\r
1139 //\r
fe781940 1140 SetMem (Private->CurrentFvFileHandles, sizeof (EFI_PEI_FILE_HANDLE) * PcdGet32 (PcdPeiCoreMaxPeimPerFv), 0);\r
192f6d4c 1141 }\r
1142\r
1143 //\r
58dcdada 1144 // Before making another pass, we should set Private->CurrentPeimFvCount =0 to go\r
b0d803fe 1145 // through all the FV.\r
192f6d4c 1146 //\r
b0d803fe 1147 Private->CurrentPeimFvCount = 0;\r
192f6d4c 1148\r
1149 //\r
58dcdada 1150 // PeimNeedingDispatch being TRUE means we found a PEIM that did not get\r
b0d803fe 1151 // dispatched. So we need to make another pass\r
192f6d4c 1152 //\r
58dcdada 1153 // PeimDispatchOnThisPass being TRUE means we dispatched a PEIM on this\r
b0d803fe 1154 // pass. If we did not dispatch a PEIM there is no point in trying again\r
1155 // as it will fail the next time too (nothing has changed).\r
192f6d4c 1156 //\r
82b8c8df 1157 } while (Private->PeimNeedingDispatch && Private->PeimDispatchOnThisPass);\r
192f6d4c 1158\r
192f6d4c 1159}\r
1160\r
b1f6a7c6 1161/**\r
192f6d4c 1162 Initialize the Dispatcher's data members\r
1163\r
b1f6a7c6 1164 @param PrivateData PeiCore's private data structure\r
1165 @param OldCoreData Old data from SecCore\r
192f6d4c 1166 NULL if being run in non-permament memory mode.\r
b1f6a7c6 1167 @param SecCoreData Points to a data structure containing information about the PEI core's operating\r
5aae0aa7 1168 environment, such as the size and location of temporary RAM, the stack location and\r
1169 the BFV location.\r
192f6d4c 1170\r
b1f6a7c6 1171 @return None.\r
192f6d4c 1172\r
b1f6a7c6 1173**/\r
1174VOID\r
1175InitializeDispatcherData (\r
1176 IN PEI_CORE_INSTANCE *PrivateData,\r
1177 IN PEI_CORE_INSTANCE *OldCoreData,\r
1178 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData\r
1179 )\r
192f6d4c 1180{\r
192f6d4c 1181 if (OldCoreData == NULL) {\r
82b8c8df 1182 PrivateData->PeimDispatcherReenter = FALSE;\r
b0d803fe 1183 PeiInitializeFv (PrivateData, SecCoreData);\r
8e0e40ed 1184 } else {\r
7ec93917 1185 PeiReinitializeFv (PrivateData);\r
192f6d4c 1186 }\r
1187\r
1188 return;\r
1189}\r
1190\r
b1f6a7c6 1191/**\r
1192 This routine parses the Dependency Expression, if available, and\r
1193 decides if the module can be executed.\r
1194\r
1195\r
1196 @param Private PeiCore's private data structure\r
1197 @param FileHandle PEIM's file handle\r
1198 @param PeimCount Peim count in all dispatched PEIMs.\r
192f6d4c 1199\r
b1f6a7c6 1200 @retval TRUE Can be dispatched\r
1201 @retval FALSE Cannot be dispatched\r
1202\r
1203**/\r
192f6d4c 1204BOOLEAN\r
1205DepexSatisfied (\r
b0d803fe 1206 IN PEI_CORE_INSTANCE *Private,\r
1207 IN EFI_PEI_FILE_HANDLE FileHandle,\r
1208 IN UINTN PeimCount\r
192f6d4c 1209 )\r
192f6d4c 1210{\r
288f9b38
LG
1211 EFI_STATUS Status;\r
1212 VOID *DepexData;\r
6a55eea3 1213 EFI_FV_FILE_INFO FileInfo;\r
b0d803fe 1214\r
6a55eea3 1215 Status = PeiServicesFfsGetFileInfo (FileHandle, &FileInfo);\r
1216 if (EFI_ERROR (Status)) {\r
1217 DEBUG ((DEBUG_DISPATCH, "Evaluate PEI DEPEX for FFS(Unknown)\n"));\r
1218 } else {\r
1219 DEBUG ((DEBUG_DISPATCH, "Evaluate PEI DEPEX for FFS(%g)\n", &FileInfo.FileName));\r
1220 }\r
1221 \r
b0d803fe 1222 if (PeimCount < Private->AprioriCount) {\r
1223 //\r
1224 // If its in the A priori file then we set Depex to TRUE\r
1225 //\r
6a55eea3 1226 DEBUG ((DEBUG_DISPATCH, " RESULT = TRUE (Apriori)\n"));\r
b0d803fe 1227 return TRUE;\r
1228 }\r
58dcdada 1229\r
288f9b38 1230 //\r
58dcdada 1231 // Depex section not in the encapsulated section.\r
288f9b38
LG
1232 //\r
1233 Status = PeiServicesFfsFindSectionData (\r
1234 EFI_SECTION_PEI_DEPEX,\r
58dcdada 1235 FileHandle,\r
288f9b38
LG
1236 (VOID **)&DepexData\r
1237 );\r
b0d803fe 1238\r
192f6d4c 1239 if (EFI_ERROR (Status)) {\r
b0d803fe 1240 //\r
1241 // If there is no DEPEX, assume the module can be executed\r
1242 //\r
6a55eea3 1243 DEBUG ((DEBUG_DISPATCH, " RESULT = TRUE (No DEPEX)\n"));\r
192f6d4c 1244 return TRUE;\r
1245 }\r
1246\r
1247 //\r
1248 // Evaluate a given DEPEX\r
1249 //\r
4140a663 1250 return PeimDispatchReadiness (&Private->Ps, DepexData);\r
192f6d4c 1251}\r
1252\r
14e8823a 1253/**\r
1254 This routine enable a PEIM to register itself to shadow when PEI Foundation\r
1255 discovery permanent memory.\r
1256\r
b1f6a7c6 1257 @param FileHandle File handle of a PEIM.\r
58dcdada 1258\r
b1f6a7c6 1259 @retval EFI_NOT_FOUND The file handle doesn't point to PEIM itself.\r
1260 @retval EFI_ALREADY_STARTED Indicate that the PEIM has been registered itself.\r
1261 @retval EFI_SUCCESS Successfully to register itself.\r
14e8823a 1262\r
58dcdada 1263**/\r
14e8823a 1264EFI_STATUS\r
1265EFIAPI\r
1266PeiRegisterForShadow (\r
1267 IN EFI_PEI_FILE_HANDLE FileHandle\r
1268 )\r
1269{\r
1270 PEI_CORE_INSTANCE *Private;\r
1271 Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());\r
1272\r
1273 if (Private->CurrentFileHandle != FileHandle) {\r
1274 //\r
1275 // The FileHandle must be for the current PEIM\r
1276 //\r
1277 return EFI_NOT_FOUND;\r
1278 }\r
1279\r
1280 if (Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] >= PEIM_STATE_REGISITER_FOR_SHADOW) {\r
1281 //\r
1282 // If the PEIM has already entered the PEIM_STATE_REGISTER_FOR_SHADOW or PEIM_STATE_DONE then it's already been started\r
1283 //\r
1284 return EFI_ALREADY_STARTED;\r
1285 }\r
58dcdada 1286\r
14e8823a 1287 Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] = PEIM_STATE_REGISITER_FOR_SHADOW;\r
1288\r
1289 return EFI_SUCCESS;\r
1290}\r
1291\r
3b428ade 1292\r
341a658f 1293\r