It fixes the warning for loop has empty body [-Werror,-Wempty-body]. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Liang Vincent <vincent.liang@intel.com> Reviewed-by: Star Zeng <star.zeng@intel.com>
		
			
				
	
	
		
			1373 lines
		
	
	
		
			57 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1373 lines
		
	
	
		
			57 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   EFI PEI Core dispatch services
 | |
|   
 | |
| Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
 | |
| (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
 | |
| This program and the accompanying materials
 | |
| are licensed and made available under the terms and conditions of the BSD License
 | |
| which accompanies this distribution.  The full text of the license may be found at
 | |
| http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "PeiMain.h"
 | |
| 
 | |
| /**
 | |
| 
 | |
|   Discover all Peims and optional Apriori file in one FV. There is at most one
 | |
|   Apriori file in one FV.
 | |
| 
 | |
| 
 | |
|   @param Private          Pointer to the private data passed in from caller
 | |
|   @param CoreFileHandle   The instance of PEI_CORE_FV_HANDLE.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| DiscoverPeimsAndOrderWithApriori (
 | |
|   IN  PEI_CORE_INSTANCE    *Private,
 | |
|   IN  PEI_CORE_FV_HANDLE   *CoreFileHandle
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                          Status;
 | |
|   EFI_PEI_FILE_HANDLE                 FileHandle;
 | |
|   EFI_PEI_FILE_HANDLE                 AprioriFileHandle;
 | |
|   EFI_GUID                            *Apriori;
 | |
|   UINTN                               Index;
 | |
|   UINTN                               Index2;
 | |
|   UINTN                               PeimIndex;
 | |
|   UINTN                               PeimCount;
 | |
|   EFI_GUID                            *Guid;
 | |
|   EFI_PEI_FILE_HANDLE                 *TempFileHandles;
 | |
|   EFI_GUID                            *FileGuid;
 | |
|   EFI_PEI_FIRMWARE_VOLUME_PPI         *FvPpi;
 | |
|   EFI_FV_FILE_INFO                    FileInfo;
 | |
|   
 | |
|   FvPpi = CoreFileHandle->FvPpi;
 | |
|   
 | |
|   //
 | |
|   // Walk the FV and find all the PEIMs and the Apriori file.
 | |
|   //
 | |
|   AprioriFileHandle = NULL;
 | |
|   Private->CurrentFvFileHandles[0] = NULL;
 | |
|   Guid = NULL;
 | |
|   FileHandle = NULL;
 | |
|   TempFileHandles = Private->FileHandles;
 | |
|   FileGuid        = Private->FileGuid;
 | |
| 
 | |
|   //
 | |
|   // If the current Fv has been scanned, directly get its cachable record.
 | |
|   //
 | |
|   if (Private->Fv[Private->CurrentPeimFvCount].ScanFv) {
 | |
|     CopyMem (Private->CurrentFvFileHandles, Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, sizeof (EFI_PEI_FILE_HANDLE) * PcdGet32 (PcdPeiCoreMaxPeimPerFv));
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Go ahead to scan this Fv, and cache FileHandles within it.
 | |
|   //
 | |
|   Status = EFI_NOT_FOUND;
 | |
|   for (PeimCount = 0; PeimCount <= PcdGet32 (PcdPeiCoreMaxPeimPerFv); PeimCount++) {
 | |
|     Status = FvPpi->FindFileByType (FvPpi, PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE, CoreFileHandle->FvHandle, &FileHandle);
 | |
|     if (Status != EFI_SUCCESS || PeimCount == PcdGet32 (PcdPeiCoreMaxPeimPerFv)) {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     Private->CurrentFvFileHandles[PeimCount] = FileHandle;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Check whether the count of files exceeds the max support files in a FV image
 | |
|   // If more files are required in a FV image, PcdPeiCoreMaxPeimPerFv can be set to a larger value in DSC file.
 | |
|   //
 | |
|   ASSERT ((Status != EFI_SUCCESS) || (PeimCount < PcdGet32 (PcdPeiCoreMaxPeimPerFv)));
 | |
| 
 | |
|   //
 | |
|   // Get Apriori File handle
 | |
|   //
 | |
|   Private->AprioriCount = 0;
 | |
|   Status = FvPpi->FindFileByName (FvPpi, &gPeiAprioriFileNameGuid, &CoreFileHandle->FvHandle, &AprioriFileHandle);
 | |
|   if (!EFI_ERROR(Status) && AprioriFileHandle != NULL) {
 | |
|     //
 | |
|     // Read the Apriori file
 | |
|     //
 | |
|     Status = FvPpi->FindSectionByType (FvPpi, EFI_SECTION_RAW, AprioriFileHandle, (VOID **) &Apriori);
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       //
 | |
|       // Calculate the number of PEIMs in the A Priori list
 | |
|       //
 | |
|       Status = FvPpi->GetFileInfo (FvPpi, AprioriFileHandle, &FileInfo);
 | |
|       ASSERT_EFI_ERROR (Status);
 | |
|       Private->AprioriCount = FileInfo.BufferSize;
 | |
|       if (IS_SECTION2 (FileInfo.Buffer)) {
 | |
|         Private->AprioriCount -= sizeof (EFI_COMMON_SECTION_HEADER2);
 | |
|       } else {
 | |
|         Private->AprioriCount -= sizeof (EFI_COMMON_SECTION_HEADER);
 | |
|       }
 | |
|       Private->AprioriCount /= sizeof (EFI_GUID);
 | |
| 
 | |
|       for (Index = 0; Index < PeimCount; Index++) {
 | |
|         //
 | |
|         // Make an array of file name guids that matches the FileHandle array so we can convert
 | |
|         // quickly from file name to file handle
 | |
|         //
 | |
|         Status = FvPpi->GetFileInfo (FvPpi, Private->CurrentFvFileHandles[Index], &FileInfo);
 | |
|         CopyMem (&FileGuid[Index], &FileInfo.FileName, sizeof(EFI_GUID));
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // Walk through FileGuid array to find out who is invalid PEIM guid in Apriori file.
 | |
|       // Add available PEIMs in Apriori file into TempFileHandles array at first.
 | |
|       //
 | |
|       Index2 = 0;
 | |
|       for (Index = 0; Index2 < Private->AprioriCount; Index++) {
 | |
|         while (Index2 < Private->AprioriCount) {
 | |
|           Guid = ScanGuid (FileGuid, PeimCount * sizeof (EFI_GUID), &Apriori[Index2++]);
 | |
|           if (Guid != NULL) {
 | |
|             break;
 | |
|           }
 | |
|         }
 | |
|         if (Guid == NULL) {
 | |
|           break;
 | |
|         }
 | |
|         PeimIndex = ((UINTN)Guid - (UINTN)&FileGuid[0])/sizeof (EFI_GUID);
 | |
|         TempFileHandles[Index] = Private->CurrentFvFileHandles[PeimIndex];
 | |
| 
 | |
|         //
 | |
|         // Since we have copied the file handle we can remove it from this list.
 | |
|         //
 | |
|         Private->CurrentFvFileHandles[PeimIndex] = NULL;
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // Update valid Aprioricount
 | |
|       //
 | |
|       Private->AprioriCount = Index;
 | |
| 
 | |
|       //
 | |
|       // Add in any PEIMs not in the Apriori file
 | |
|       //
 | |
|       for (;Index < PeimCount; Index++) {
 | |
|         for (Index2 = 0; Index2 < PeimCount; Index2++) {
 | |
|           if (Private->CurrentFvFileHandles[Index2] != NULL) {
 | |
|             TempFileHandles[Index] = Private->CurrentFvFileHandles[Index2];
 | |
|             Private->CurrentFvFileHandles[Index2] = NULL;
 | |
|             break;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       //
 | |
|       //Index the end of array contains re-range Pei moudle.
 | |
|       //
 | |
|       TempFileHandles[Index] = NULL;
 | |
| 
 | |
|       //
 | |
|       // Private->CurrentFvFileHandles is currently in PEIM in the FV order.
 | |
|       // We need to update it to start with files in the A Priori list and
 | |
|       // then the remaining files in PEIM order.
 | |
|       //
 | |
|       CopyMem (Private->CurrentFvFileHandles, TempFileHandles, sizeof (EFI_PEI_FILE_HANDLE) * PcdGet32 (PcdPeiCoreMaxPeimPerFv));
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // Cache the current Fv File Handle. So that we don't have to scan the Fv again.
 | |
|   // Instead, we can retrieve the file handles within this Fv from cachable data.
 | |
|   //
 | |
|   Private->Fv[Private->CurrentPeimFvCount].ScanFv = TRUE;
 | |
|   CopyMem (Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, Private->CurrentFvFileHandles, sizeof (EFI_PEI_FILE_HANDLE) * PcdGet32 (PcdPeiCoreMaxPeimPerFv));
 | |
| 
 | |
| }
 | |
| 
 | |
| //
 | |
| // This is the minimum memory required by DxeCore initialization. When LMFA feature enabled,
 | |
| // This part of memory still need reserved on the very top of memory so that the DXE Core could  
 | |
| // use these memory for data initialization. This macro should be sync with the same marco
 | |
| // defined in DXE Core.
 | |
| //
 | |
| #define MINIMUM_INITIAL_MEMORY_SIZE 0x10000
 | |
| /**
 | |
|   This function is to test if the memory range described in resource HOB is available or not. 
 | |
|   
 | |
|   This function should only be invoked when Loading Module at Fixed Address(LMFA) feature is enabled. Some platform may allocate the 
 | |
|   memory before PeiLoadFixAddressHook in invoked. so this function is to test if the memory range described by the input resource HOB is
 | |
|   available or not.
 | |
| 
 | |
|   @param PrivateData         Pointer to the private data passed in from caller
 | |
|   @param ResourceHob         Pointer to a resource HOB which described the memory range described by the input resource HOB
 | |
| **/
 | |
| BOOLEAN
 | |
| PeiLoadFixAddressIsMemoryRangeAvailable (
 | |
|   IN PEI_CORE_INSTANCE                  *PrivateData,
 | |
|   IN EFI_HOB_RESOURCE_DESCRIPTOR        *ResourceHob
 | |
|   )
 | |
| {
 | |
| 	EFI_HOB_MEMORY_ALLOCATION          *MemoryHob;
 | |
| 	BOOLEAN                             IsAvailable;
 | |
| 	EFI_PEI_HOB_POINTERS                Hob;
 | |
| 	
 | |
|   IsAvailable = TRUE;
 | |
| 	if (PrivateData == NULL || ResourceHob == NULL) {
 | |
| 	  return FALSE;
 | |
| 	}
 | |
| 	//
 | |
|   // test if the memory range describe in the HOB is already allocated.
 | |
|   //
 | |
|   for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
 | |
|     //                                                              
 | |
|     // See if this is a memory allocation HOB                     
 | |
|     //
 | |
|     if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) { 
 | |
|       MemoryHob = Hob.MemoryAllocation;
 | |
|       if(MemoryHob->AllocDescriptor.MemoryBaseAddress == ResourceHob->PhysicalStart && 
 | |
|          MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength == ResourceHob->PhysicalStart + ResourceHob->ResourceLength) {
 | |
|          IsAvailable = FALSE;
 | |
|          break;  
 | |
|        }
 | |
|      }
 | |
|   }
 | |
|   
 | |
|   return IsAvailable;
 | |
|        
 | |
| }
 | |
| /**
 | |
|   Hook function for Loading Module at Fixed Address feature
 | |
|   
 | |
|   This function should only be invoked when Loading Module at Fixed Address(LMFA) feature is enabled. When feature is
 | |
|   configured as Load Modules at Fix Absolute Address, this function is to validate the top address assigned by user. When 
 | |
|   feature is configured as Load Modules at Fixed Offset, the functino is to find the top address which is TOLM-TSEG in general.  
 | |
|   And also the function will re-install PEI memory. 
 | |
| 
 | |
|   @param PrivateData         Pointer to the private data passed in from caller
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| PeiLoadFixAddressHook(
 | |
|   IN PEI_CORE_INSTANCE           *PrivateData
 | |
|   )
 | |
| {
 | |
|   EFI_PHYSICAL_ADDRESS               TopLoadingAddress;
 | |
|   UINT64                             PeiMemorySize;
 | |
|   UINT64                             TotalReservedMemorySize;
 | |
|   UINT64                             MemoryRangeEnd;
 | |
|   EFI_PHYSICAL_ADDRESS               HighAddress; 
 | |
|   EFI_HOB_RESOURCE_DESCRIPTOR        *ResourceHob;
 | |
|   EFI_HOB_RESOURCE_DESCRIPTOR        *NextResourceHob;
 | |
|   EFI_HOB_RESOURCE_DESCRIPTOR        *CurrentResourceHob;
 | |
|   EFI_PEI_HOB_POINTERS               CurrentHob;
 | |
|   EFI_PEI_HOB_POINTERS               Hob;
 | |
|   EFI_PEI_HOB_POINTERS               NextHob;
 | |
|   EFI_HOB_MEMORY_ALLOCATION          *MemoryHob;
 | |
|   //
 | |
|   // Initialize Local Variables
 | |
|   //
 | |
|   CurrentResourceHob    = NULL;
 | |
|   ResourceHob           = NULL;
 | |
|   NextResourceHob       = NULL;
 | |
|   HighAddress           = 0;
 | |
|   TopLoadingAddress     = 0;
 | |
|   MemoryRangeEnd      = 0;
 | |
|   CurrentHob.Raw      = PrivateData->HobList.Raw;
 | |
|   PeiMemorySize = PrivateData->PhysicalMemoryLength;
 | |
|   //
 | |
|   // The top reserved memory include 3 parts: the topest range is for DXE core initialization with the size  MINIMUM_INITIAL_MEMORY_SIZE
 | |
|   // then RuntimeCodePage range and Boot time code range.
 | |
|   //  
 | |
|   TotalReservedMemorySize = MINIMUM_INITIAL_MEMORY_SIZE + EFI_PAGES_TO_SIZE(PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber));
 | |
|   TotalReservedMemorySize+= EFI_PAGES_TO_SIZE(PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber)) ;  
 | |
|   //
 | |
|   // PEI memory range lies below the top reserved memory
 | |
|   // 
 | |
|   TotalReservedMemorySize += PeiMemorySize;
 | |
|   
 | |
|   DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressRuntimeCodePageNumber= 0x%x.\n", PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber)));
 | |
|   DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressBootTimeCodePageNumber= 0x%x.\n", PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber)));
 | |
|   DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressPeiCodePageNumber= 0x%x.\n", PcdGet32(PcdLoadFixAddressPeiCodePageNumber)));   
 | |
|   DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: Total Reserved Memory Size = 0x%lx.\n", TotalReservedMemorySize));
 | |
|   //
 | |
|   // Loop through the system memory typed hob to merge the adjacent memory range 
 | |
|   //
 | |
|   for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
 | |
|     //                                                              
 | |
|     // See if this is a resource descriptor HOB                     
 | |
|     //
 | |
|     if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
 | |
|       
 | |
|       ResourceHob = Hob.ResourceDescriptor;  
 | |
|       //
 | |
|       // If range described in this hob is not system memory or heigher than MAX_ADDRESS, ignored.
 | |
|       //
 | |
|       if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY ||
 | |
|           ResourceHob->PhysicalStart + ResourceHob->ResourceLength > MAX_ADDRESS)   {
 | |
|         continue;
 | |
|       }   
 | |
|       
 | |
|       for (NextHob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(NextHob); NextHob.Raw = GET_NEXT_HOB(NextHob)) {       
 | |
|         if (NextHob.Raw == Hob.Raw){
 | |
|           continue;
 | |
|         }  
 | |
|         //
 | |
|         // See if this is a resource descriptor HOB
 | |
|         //
 | |
|         if (GET_HOB_TYPE (NextHob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
 | |
|       
 | |
|           NextResourceHob = NextHob.ResourceDescriptor;
 | |
|           //
 | |
|           // test if range described in this NextResourceHob is system memory and have the same attribute.
 | |
|           // Note: Here is a assumption that system memory should always be healthy even without test.
 | |
|           //    
 | |
|           if (NextResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&
 | |
|              (((NextResourceHob->ResourceAttribute^ResourceHob->ResourceAttribute)&(~EFI_RESOURCE_ATTRIBUTE_TESTED)) == 0)){
 | |
|               
 | |
|               //
 | |
|               // See if the memory range described in ResourceHob and NextResourceHob is adjacent
 | |
|               //
 | |
|               if ((ResourceHob->PhysicalStart <= NextResourceHob->PhysicalStart && 
 | |
|                     ResourceHob->PhysicalStart + ResourceHob->ResourceLength >= NextResourceHob->PhysicalStart)|| 
 | |
|                   (ResourceHob->PhysicalStart >= NextResourceHob->PhysicalStart&&
 | |
|                      ResourceHob->PhysicalStart <= NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength)) {
 | |
|              
 | |
|                 MemoryRangeEnd = ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength)>(NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength)) ?
 | |
|                                      (ResourceHob->PhysicalStart + ResourceHob->ResourceLength):(NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength);
 | |
|           
 | |
|                 ResourceHob->PhysicalStart = (ResourceHob->PhysicalStart < NextResourceHob->PhysicalStart) ? 
 | |
|                                                     ResourceHob->PhysicalStart : NextResourceHob->PhysicalStart;
 | |
|                 
 | |
|                
 | |
|                 ResourceHob->ResourceLength = (MemoryRangeEnd - ResourceHob->PhysicalStart);
 | |
|                 
 | |
|                 ResourceHob->ResourceAttribute = ResourceHob->ResourceAttribute & (~EFI_RESOURCE_ATTRIBUTE_TESTED);
 | |
|                 //
 | |
|                 // Delete the NextResourceHob by marking it as unused.
 | |
|                 //
 | |
|                 GET_HOB_TYPE (NextHob) = EFI_HOB_TYPE_UNUSED;
 | |
|                 
 | |
|               }
 | |
|            }
 | |
|         } 
 | |
|       }
 | |
|     } 
 | |
|   }
 | |
|   //
 | |
|   // Some platform is already allocated pages before the HOB re-org. Here to build dedicated resource HOB to describe
 | |
|   //  the allocated memory range
 | |
|   //
 | |
|   for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
 | |
|     //                                                              
 | |
|     // See if this is a memory allocation HOB                     
 | |
|     //
 | |
|     if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
 | |
|       MemoryHob = Hob.MemoryAllocation;
 | |
|       for (NextHob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(NextHob); NextHob.Raw = GET_NEXT_HOB(NextHob)) {
 | |
|         //
 | |
|         // See if this is a resource descriptor HOB
 | |
|         //
 | |
|         if (GET_HOB_TYPE (NextHob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
 | |
|         	NextResourceHob = NextHob.ResourceDescriptor;
 | |
|           //
 | |
|           // If range described in this hob is not system memory or heigher than MAX_ADDRESS, ignored.
 | |
|           //
 | |
|           if (NextResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY || NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength > MAX_ADDRESS) {
 | |
|             continue;
 | |
|           }
 | |
|           //
 | |
|           // If the range describe in memory allocation HOB  belongs to the memroy range described by the resource hob
 | |
|           //          
 | |
|           if (MemoryHob->AllocDescriptor.MemoryBaseAddress >= NextResourceHob->PhysicalStart && 
 | |
|               MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength <= NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength) {
 | |
|              //
 | |
|              // Build seperate resource hob for this allocated range
 | |
|              //                     
 | |
|              if (MemoryHob->AllocDescriptor.MemoryBaseAddress > NextResourceHob->PhysicalStart) {
 | |
|                BuildResourceDescriptorHob (
 | |
|                  EFI_RESOURCE_SYSTEM_MEMORY,                       
 | |
|                  NextResourceHob->ResourceAttribute,
 | |
|                  NextResourceHob->PhysicalStart,                             
 | |
|                  (MemoryHob->AllocDescriptor.MemoryBaseAddress - NextResourceHob->PhysicalStart)      
 | |
|                );
 | |
|              }
 | |
|              if (MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength < NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength) {
 | |
|                BuildResourceDescriptorHob (
 | |
|                  EFI_RESOURCE_SYSTEM_MEMORY,                       
 | |
|                  NextResourceHob->ResourceAttribute,
 | |
|                  MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength,                            
 | |
|                  (NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength -(MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength))    
 | |
|                );
 | |
|              }
 | |
|              NextResourceHob->PhysicalStart = MemoryHob->AllocDescriptor.MemoryBaseAddress;
 | |
|              NextResourceHob->ResourceLength = MemoryHob->AllocDescriptor.MemoryLength;
 | |
|              break;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Try to find and validate the TOP address.
 | |
|   //  
 | |
|   if ((INT64)PcdGet64(PcdLoadModuleAtFixAddressEnable) > 0 ) {
 | |
|     //
 | |
|     // The LMFA feature is enabled as load module at fixed absolute address.
 | |
|     //
 | |
|     TopLoadingAddress = (EFI_PHYSICAL_ADDRESS)PcdGet64(PcdLoadModuleAtFixAddressEnable);
 | |
|     DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: Loading module at fixed absolute address.\n"));
 | |
|     //
 | |
|     // validate the Address. Loop the resource descriptor HOB to make sure the address is in valid memory range
 | |
|     //
 | |
|     if ((TopLoadingAddress & EFI_PAGE_MASK) != 0) {
 | |
|       DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:Top Address 0x%lx is invalid since top address should be page align. \n", TopLoadingAddress)); 
 | |
|       ASSERT (FALSE);    
 | |
|     }
 | |
|     //
 | |
|     // Search for a memory region that is below MAX_ADDRESS and in which TopLoadingAddress lies 
 | |
|     //
 | |
|     for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
 | |
|       //
 | |
|       // See if this is a resource descriptor HOB
 | |
|       //
 | |
|       if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
 | |
| 
 | |
|         ResourceHob = Hob.ResourceDescriptor;
 | |
|         //
 | |
|         // See if this resource descrior HOB describes tested system memory below MAX_ADDRESS
 | |
|         //    
 | |
|         if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&
 | |
|             ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS) {
 | |
|             //
 | |
|             // See if Top address specified by user is valid.
 | |
|             //
 | |
|             if (ResourceHob->PhysicalStart + TotalReservedMemorySize < TopLoadingAddress && 
 | |
|                 (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MINIMUM_INITIAL_MEMORY_SIZE) >= TopLoadingAddress && 
 | |
|                 PeiLoadFixAddressIsMemoryRangeAvailable(PrivateData, ResourceHob)) {
 | |
|               CurrentResourceHob = ResourceHob; 
 | |
|               CurrentHob = Hob;
 | |
|               break;
 | |
|            }
 | |
|         }
 | |
|       }  
 | |
|     }  
 | |
|     if (CurrentResourceHob != NULL) {
 | |
|       DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO:Top Address 0x%lx is valid \n",  TopLoadingAddress));
 | |
|       TopLoadingAddress += MINIMUM_INITIAL_MEMORY_SIZE; 
 | |
|     } else {
 | |
|       DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:Top Address 0x%lx is invalid \n",  TopLoadingAddress)); 
 | |
|       DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:The recommended Top Address for the platform is: \n")); 
 | |
|       //
 | |
|       // Print the recomended Top address range.
 | |
|       // 
 | |
|       for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
 | |
|         //
 | |
|         // See if this is a resource descriptor HOB
 | |
|         //
 | |
|         if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
 | |
|         
 | |
|           ResourceHob = Hob.ResourceDescriptor;
 | |
|           //
 | |
|           // See if this resource descrior HOB describes tested system memory below MAX_ADDRESS
 | |
|           //    
 | |
|           if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&
 | |
|               ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS) {
 | |
|               //
 | |
|               // See if Top address specified by user is valid.
 | |
|               //
 | |
|               if (ResourceHob->ResourceLength > TotalReservedMemorySize && PeiLoadFixAddressIsMemoryRangeAvailable(PrivateData, ResourceHob)) {
 | |
|                  DEBUG ((EFI_D_INFO, "(0x%lx, 0x%lx)\n",  
 | |
|                           (ResourceHob->PhysicalStart + TotalReservedMemorySize -MINIMUM_INITIAL_MEMORY_SIZE), 
 | |
|                           (ResourceHob->PhysicalStart + ResourceHob->ResourceLength -MINIMUM_INITIAL_MEMORY_SIZE) 
 | |
|                         )); 
 | |
|               }
 | |
|           }
 | |
|         }
 | |
|       }  
 | |
|       //
 | |
|       // Assert here 
 | |
|       //
 | |
|       ASSERT (FALSE);   
 | |
|       return;   
 | |
|     }     
 | |
|   } else {
 | |
|     //
 | |
|     // The LMFA feature is enabled as load module at fixed offset relative to TOLM
 | |
|     // Parse the Hob list to find the topest available memory. Generally it is (TOLM - TSEG)
 | |
|     //
 | |
|     //
 | |
|     // Search for a tested memory region that is below MAX_ADDRESS
 | |
|     //
 | |
|     for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
 | |
|       //
 | |
|       // See if this is a resource descriptor HOB 
 | |
|       //
 | |
|       if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
 | |
|         
 | |
|         ResourceHob = Hob.ResourceDescriptor;                                                                                                                                                                                                                               
 | |
|         //
 | |
|         // See if this resource descrior HOB describes tested system memory below MAX_ADDRESS
 | |
|         //
 | |
|         if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY && 
 | |
|             ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS &&
 | |
|             ResourceHob->ResourceLength > TotalReservedMemorySize && PeiLoadFixAddressIsMemoryRangeAvailable(PrivateData, ResourceHob)) {
 | |
|           //
 | |
|           // See if this is the highest largest system memory region below MaxAddress
 | |
|           //
 | |
|           if (ResourceHob->PhysicalStart > HighAddress) {
 | |
|              CurrentResourceHob = ResourceHob;
 | |
|              CurrentHob = Hob;
 | |
|              HighAddress = CurrentResourceHob->PhysicalStart;
 | |
|           }
 | |
|         }
 | |
|       }  
 | |
|     }
 | |
|     if (CurrentResourceHob == NULL) {
 | |
|       DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:The System Memory is too small\n")); 
 | |
|       //
 | |
|       // Assert here 
 | |
|       //
 | |
|       ASSERT (FALSE);
 | |
|       return;  
 | |
|     } else {
 | |
|       TopLoadingAddress = CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength ; 
 | |
|     }         
 | |
|   }
 | |
|   
 | |
|   if (CurrentResourceHob != NULL) {
 | |
|     //
 | |
|     // rebuild resource HOB for PEI memmory and reserved memory
 | |
|     //
 | |
|     BuildResourceDescriptorHob (
 | |
|       EFI_RESOURCE_SYSTEM_MEMORY,                       
 | |
|       (
 | |
|       EFI_RESOURCE_ATTRIBUTE_PRESENT |
 | |
|       EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
 | |
|       EFI_RESOURCE_ATTRIBUTE_TESTED |
 | |
|       EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
 | |
|       EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
 | |
|       EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
 | |
|       EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
 | |
|       ),
 | |
|       (TopLoadingAddress - TotalReservedMemorySize),                             
 | |
|       TotalReservedMemorySize     
 | |
|     );
 | |
|     //
 | |
|     // rebuild resource for the remain memory if necessary
 | |
|     //
 | |
|     if (CurrentResourceHob->PhysicalStart < TopLoadingAddress - TotalReservedMemorySize) {
 | |
|       BuildResourceDescriptorHob (
 | |
|         EFI_RESOURCE_SYSTEM_MEMORY,                       
 | |
|         (
 | |
|          EFI_RESOURCE_ATTRIBUTE_PRESENT |
 | |
|          EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
 | |
|          EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
 | |
|          EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
 | |
|          EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
 | |
|          EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
 | |
|          ),
 | |
|          CurrentResourceHob->PhysicalStart,                             
 | |
|          (TopLoadingAddress - TotalReservedMemorySize - CurrentResourceHob->PhysicalStart)      
 | |
|        );
 | |
|     }
 | |
|     if (CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength  > TopLoadingAddress ) {
 | |
|       BuildResourceDescriptorHob (
 | |
|         EFI_RESOURCE_SYSTEM_MEMORY,                     
 | |
|         (
 | |
|          EFI_RESOURCE_ATTRIBUTE_PRESENT |
 | |
|          EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
 | |
|          EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
 | |
|          EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
 | |
|          EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
 | |
|          EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
 | |
|          ),
 | |
|          TopLoadingAddress,                            
 | |
|          (CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength  - TopLoadingAddress)     
 | |
|        );
 | |
|     }
 | |
|     //
 | |
|     // Delete CurrentHob by marking it as unused since the the memory range described by is rebuilt.
 | |
|     //
 | |
|     GET_HOB_TYPE (CurrentHob) = EFI_HOB_TYPE_UNUSED;         
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Cache the top address for Loading Module at Fixed Address feature
 | |
|   //
 | |
|   PrivateData->LoadModuleAtFixAddressTopAddress = TopLoadingAddress - MINIMUM_INITIAL_MEMORY_SIZE;
 | |
|   DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: Top address = 0x%lx\n",  PrivateData->LoadModuleAtFixAddressTopAddress)); 
 | |
|   //
 | |
|   // reinstall the PEI memory relative to TopLoadingAddress
 | |
|   //
 | |
|   PrivateData->PhysicalMemoryBegin   = TopLoadingAddress - TotalReservedMemorySize;
 | |
|   PrivateData->FreePhysicalMemoryTop = PrivateData->PhysicalMemoryBegin + PeiMemorySize;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This routine is invoked in switch stack as PeiCore Entry.
 | |
| 
 | |
|   @param SecCoreData     Points to a data structure containing information about the PEI core's operating
 | |
|                          environment, such as the size and location of temporary RAM, the stack location and
 | |
|                          the BFV location.
 | |
|   @param Private         Pointer to old core data that is used to initialize the
 | |
|                          core's data areas.
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| PeiCoreEntry (
 | |
|   IN CONST EFI_SEC_PEI_HAND_OFF    *SecCoreData,
 | |
|   IN PEI_CORE_INSTANCE             *Private
 | |
|   )
 | |
| {
 | |
|   //
 | |
|   // Entry PEI Phase 2
 | |
|   //
 | |
|   PeiCore (SecCoreData, NULL, Private);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Check SwitchStackSignal and switch stack if SwitchStackSignal is TRUE.
 | |
| 
 | |
|   @param[in] SecCoreData    Points to a data structure containing information about the PEI core's operating
 | |
|                             environment, such as the size and location of temporary RAM, the stack location and
 | |
|                             the BFV location.
 | |
|   @param[in] Private        Pointer to the private data passed in from caller.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| PeiCheckAndSwitchStack (
 | |
|   IN CONST EFI_SEC_PEI_HAND_OFF         *SecCoreData,
 | |
|   IN PEI_CORE_INSTANCE                  *Private
 | |
|   )
 | |
| {
 | |
|   VOID                                  *LoadFixPeiCodeBegin;
 | |
|   EFI_STATUS                            Status;
 | |
|   CONST EFI_PEI_SERVICES                **PeiServices;
 | |
|   UINT64                                NewStackSize;
 | |
|   EFI_PHYSICAL_ADDRESS                  TopOfOldStack;
 | |
|   EFI_PHYSICAL_ADDRESS                  TopOfNewStack;
 | |
|   UINTN                                 StackOffset;
 | |
|   BOOLEAN                               StackOffsetPositive;
 | |
|   EFI_PHYSICAL_ADDRESS                  TemporaryRamBase;
 | |
|   UINTN                                 TemporaryRamSize;
 | |
|   UINTN                                 TemporaryStackSize;
 | |
|   VOID                                  *TemporaryStackBase;
 | |
|   UINTN                                 PeiTemporaryRamSize;
 | |
|   VOID                                  *PeiTemporaryRamBase;
 | |
|   EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI     *TemporaryRamSupportPpi;
 | |
|   EFI_PHYSICAL_ADDRESS                  BaseOfNewHeap;
 | |
|   EFI_PHYSICAL_ADDRESS                  HoleMemBase;
 | |
|   UINTN                                 HoleMemSize;
 | |
|   UINTN                                 HeapTemporaryRamSize;
 | |
|   EFI_PHYSICAL_ADDRESS                  TempBase1;
 | |
|   UINTN                                 TempSize1;
 | |
|   EFI_PHYSICAL_ADDRESS                  TempBase2;
 | |
|   UINTN                                 TempSize2;
 | |
|   UINTN                                 Index;
 | |
| 
 | |
|   PeiServices = (CONST EFI_PEI_SERVICES **) &Private->Ps;
 | |
| 
 | |
|   if (Private->SwitchStackSignal) {
 | |
|     //
 | |
|     // Before switch stack from temporary memory to permanent memory, calculate the heap and stack
 | |
|     // usage in temporary memory for debugging.
 | |
|     //
 | |
|     DEBUG_CODE_BEGIN ();
 | |
|       UINT32                *StackPointer;
 | |
|       EFI_PEI_HOB_POINTERS  Hob;
 | |
| 
 | |
|       for (StackPointer = (UINT32*)SecCoreData->StackBase;
 | |
|            (StackPointer < (UINT32*)((UINTN)SecCoreData->StackBase + SecCoreData->StackSize)) \
 | |
|            && (*StackPointer == PcdGet32 (PcdInitValueInTempStack));
 | |
|            StackPointer ++) {
 | |
|       }
 | |
| 
 | |
|       DEBUG ((DEBUG_INFO, "Temp Stack : BaseAddress=0x%p Length=0x%X\n", SecCoreData->StackBase, (UINT32)SecCoreData->StackSize));
 | |
|       DEBUG ((DEBUG_INFO, "Temp Heap  : BaseAddress=0x%p Length=0x%X\n", SecCoreData->PeiTemporaryRamBase, (UINT32)SecCoreData->PeiTemporaryRamSize));
 | |
|       DEBUG ((DEBUG_INFO, "Total temporary memory:    %d bytes.\n", (UINT32)SecCoreData->TemporaryRamSize));
 | |
|       DEBUG ((DEBUG_INFO, "  temporary memory stack ever used:       %d bytes.\n",
 | |
|              (UINT32)(SecCoreData->StackSize - ((UINTN) StackPointer - (UINTN)SecCoreData->StackBase))
 | |
|             ));
 | |
|       DEBUG ((DEBUG_INFO, "  temporary memory heap used for HobList: %d bytes.\n",
 | |
|              (UINT32)((UINTN)Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - (UINTN)Private->HobList.Raw)
 | |
|             ));
 | |
|       DEBUG ((DEBUG_INFO, "  temporary memory heap occupied by memory pages: %d bytes.\n",
 | |
|              (UINT32)(UINTN)(Private->HobList.HandoffInformationTable->EfiMemoryTop - Private->HobList.HandoffInformationTable->EfiFreeMemoryTop)
 | |
|             ));
 | |
|       for (Hob.Raw = Private->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
 | |
|         if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
 | |
|           DEBUG ((DEBUG_INFO, "Memory Allocation 0x%08x 0x%0lx - 0x%0lx\n", \
 | |
|             Hob.MemoryAllocation->AllocDescriptor.MemoryType,               \
 | |
|             Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress,        \
 | |
|             Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress + Hob.MemoryAllocation->AllocDescriptor.MemoryLength - 1));
 | |
|         }
 | |
|       }
 | |
|     DEBUG_CODE_END ();
 | |
| 
 | |
|     if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0 && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
 | |
|       //
 | |
|       // Loading Module at Fixed Address is enabled
 | |
|       //
 | |
|       PeiLoadFixAddressHook (Private);
 | |
| 
 | |
|       //
 | |
|       // If Loading Module at Fixed Address is enabled, Allocating memory range for Pei code range.
 | |
|       //
 | |
|       LoadFixPeiCodeBegin = AllocatePages((UINTN)PcdGet32(PcdLoadFixAddressPeiCodePageNumber));
 | |
|       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)));
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Reserve the size of new stack at bottom of physical memory
 | |
|     //
 | |
|     // The size of new stack in permanent memory must be the same size
 | |
|     // or larger than the size of old stack in temporary memory.
 | |
|     // But if new stack is smaller than the size of old stack, we also reserve
 | |
|     // the size of old stack at bottom of permanent memory.
 | |
|     //
 | |
|     NewStackSize = RShiftU64 (Private->PhysicalMemoryLength, 1);
 | |
|     NewStackSize = ALIGN_VALUE (NewStackSize, EFI_PAGE_SIZE);
 | |
|     NewStackSize = MIN (PcdGet32(PcdPeiCoreMaxPeiStackSize), NewStackSize);
 | |
|     DEBUG ((EFI_D_INFO, "Old Stack size %d, New stack size %d\n", (UINT32)SecCoreData->StackSize, (UINT32)NewStackSize));
 | |
|     ASSERT (NewStackSize >= SecCoreData->StackSize);
 | |
| 
 | |
|     //
 | |
|     // Calculate stack offset and heap offset between temporary memory and new permement 
 | |
|     // memory seperately.
 | |
|     //
 | |
|     TopOfOldStack = (UINTN)SecCoreData->StackBase + SecCoreData->StackSize;
 | |
|     TopOfNewStack = Private->PhysicalMemoryBegin + NewStackSize;
 | |
|     if (TopOfNewStack >= TopOfOldStack) {
 | |
|       StackOffsetPositive = TRUE;
 | |
|       StackOffset = (UINTN)(TopOfNewStack - TopOfOldStack);
 | |
|     } else {
 | |
|       StackOffsetPositive = FALSE;
 | |
|       StackOffset = (UINTN)(TopOfOldStack - TopOfNewStack);
 | |
|     }
 | |
|     Private->StackOffsetPositive = StackOffsetPositive;
 | |
|     Private->StackOffset = StackOffset;
 | |
| 
 | |
|     //
 | |
|     // Build Stack HOB that describes the permanent memory stack
 | |
|     //
 | |
|     DEBUG ((EFI_D_INFO, "Stack Hob: BaseAddress=0x%lX Length=0x%lX\n", TopOfNewStack - NewStackSize, NewStackSize));
 | |
|     BuildStackHob (TopOfNewStack - NewStackSize, NewStackSize);
 | |
| 
 | |
|     //
 | |
|     // Cache information from SecCoreData into locals before SecCoreData is converted to a permanent memory address
 | |
|     //
 | |
|     TemporaryRamBase    = (EFI_PHYSICAL_ADDRESS)(UINTN)SecCoreData->TemporaryRamBase;
 | |
|     TemporaryRamSize    = SecCoreData->TemporaryRamSize;
 | |
|     TemporaryStackSize  = SecCoreData->StackSize;
 | |
|     TemporaryStackBase  = SecCoreData->StackBase;
 | |
|     PeiTemporaryRamSize = SecCoreData->PeiTemporaryRamSize;
 | |
|     PeiTemporaryRamBase = SecCoreData->PeiTemporaryRamBase;
 | |
| 
 | |
|     //
 | |
|     // TemporaryRamSupportPpi is produced by platform's SEC
 | |
|     //
 | |
|     Status = PeiServicesLocatePpi (
 | |
|                &gEfiTemporaryRamSupportPpiGuid,
 | |
|                0,
 | |
|                NULL,
 | |
|                (VOID**)&TemporaryRamSupportPpi
 | |
|                );
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       //
 | |
|       // Heap Offset
 | |
|       //
 | |
|       BaseOfNewHeap = TopOfNewStack;
 | |
|       if (BaseOfNewHeap >= (UINTN)SecCoreData->PeiTemporaryRamBase) {
 | |
|         Private->HeapOffsetPositive = TRUE;
 | |
|         Private->HeapOffset = (UINTN)(BaseOfNewHeap - (UINTN)SecCoreData->PeiTemporaryRamBase);
 | |
|       } else {
 | |
|         Private->HeapOffsetPositive = FALSE;
 | |
|         Private->HeapOffset = (UINTN)((UINTN)SecCoreData->PeiTemporaryRamBase - BaseOfNewHeap);
 | |
|       }
 | |
| 
 | |
|       DEBUG ((EFI_D_INFO, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (UINT64) Private->HeapOffset, (UINT64) Private->StackOffset));
 | |
| 
 | |
|       //
 | |
|       // Calculate new HandOffTable and PrivateData address in permanent memory's stack
 | |
|       //
 | |
|       if (StackOffsetPositive) {
 | |
|         SecCoreData = (CONST EFI_SEC_PEI_HAND_OFF *)((UINTN)(VOID *)SecCoreData + StackOffset);
 | |
|         Private = (PEI_CORE_INSTANCE *)((UINTN)(VOID *)Private + StackOffset);
 | |
|       } else {
 | |
|         SecCoreData = (CONST EFI_SEC_PEI_HAND_OFF *)((UINTN)(VOID *)SecCoreData - StackOffset);
 | |
|         Private = (PEI_CORE_INSTANCE *)((UINTN)(VOID *)Private - StackOffset);
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // Temporary Ram Support PPI is provided by platform, it will copy 
 | |
|       // temporary memory to permanent memory and do stack switching.
 | |
|       // After invoking Temporary Ram Support PPI, the following code's 
 | |
|       // stack is in permanent memory.
 | |
|       //
 | |
|       TemporaryRamSupportPpi->TemporaryRamMigration (
 | |
|                                 PeiServices,
 | |
|                                 TemporaryRamBase,
 | |
|                                 (EFI_PHYSICAL_ADDRESS)(UINTN)(TopOfNewStack - TemporaryStackSize),
 | |
|                                 TemporaryRamSize
 | |
|                                 );
 | |
| 
 | |
|       //
 | |
|       // Migrate memory pages allocated in pre-memory phase.
 | |
|       // It could not be called before calling TemporaryRamSupportPpi->TemporaryRamMigration()
 | |
|       // as the migrated memory pages may be overridden by TemporaryRamSupportPpi->TemporaryRamMigration().
 | |
|       //
 | |
|       MigrateMemoryPages (Private, TRUE);
 | |
| 
 | |
|       //
 | |
|       // Entry PEI Phase 2
 | |
|       //
 | |
|       PeiCore (SecCoreData, NULL, Private);
 | |
|     } else {
 | |
|       //
 | |
|       // Migrate memory pages allocated in pre-memory phase.
 | |
|       //
 | |
|       MigrateMemoryPages (Private, FALSE);
 | |
| 
 | |
|       //
 | |
|       // Migrate the PEI Services Table pointer from temporary RAM to permanent RAM.
 | |
|       //
 | |
|       MigratePeiServicesTablePointer ();
 | |
| 
 | |
|       //
 | |
|       // Heap Offset
 | |
|       //
 | |
|       BaseOfNewHeap = TopOfNewStack;
 | |
|       HoleMemBase   = TopOfNewStack;
 | |
|       HoleMemSize   = TemporaryRamSize - PeiTemporaryRamSize - TemporaryStackSize;
 | |
|       if (HoleMemSize != 0) {
 | |
|         //
 | |
|         // Make sure HOB List start address is 8 byte alignment.
 | |
|         //
 | |
|         BaseOfNewHeap = ALIGN_VALUE (BaseOfNewHeap + HoleMemSize, 8);
 | |
|       }
 | |
|       if (BaseOfNewHeap >= (UINTN)SecCoreData->PeiTemporaryRamBase) {
 | |
|         Private->HeapOffsetPositive = TRUE;
 | |
|         Private->HeapOffset = (UINTN)(BaseOfNewHeap - (UINTN)SecCoreData->PeiTemporaryRamBase);
 | |
|       } else {
 | |
|         Private->HeapOffsetPositive = FALSE;
 | |
|         Private->HeapOffset = (UINTN)((UINTN)SecCoreData->PeiTemporaryRamBase - BaseOfNewHeap);
 | |
|       }
 | |
| 
 | |
|       DEBUG ((EFI_D_INFO, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (UINT64) Private->HeapOffset, (UINT64) Private->StackOffset));
 | |
| 
 | |
|       //
 | |
|       // Migrate Heap
 | |
|       //
 | |
|       HeapTemporaryRamSize = (UINTN) (Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - Private->HobList.HandoffInformationTable->EfiMemoryBottom);
 | |
|       ASSERT (BaseOfNewHeap + HeapTemporaryRamSize <= Private->FreePhysicalMemoryTop);
 | |
|       CopyMem ((UINT8 *) (UINTN) BaseOfNewHeap, PeiTemporaryRamBase, HeapTemporaryRamSize);
 | |
| 
 | |
|       //
 | |
|       // Migrate Stack
 | |
|       //
 | |
|       CopyMem ((UINT8 *) (UINTN) (TopOfNewStack - TemporaryStackSize), TemporaryStackBase, TemporaryStackSize);
 | |
| 
 | |
|       //
 | |
|       // Copy Hole Range Data
 | |
|       //
 | |
|       if (HoleMemSize != 0) {
 | |
|         //
 | |
|         // Prepare Hole
 | |
|         //
 | |
|         if (PeiTemporaryRamBase < TemporaryStackBase) {
 | |
|           TempBase1 = (EFI_PHYSICAL_ADDRESS) (UINTN) PeiTemporaryRamBase;
 | |
|           TempSize1 = PeiTemporaryRamSize;
 | |
|           TempBase2 = (EFI_PHYSICAL_ADDRESS) (UINTN) TemporaryStackBase;
 | |
|           TempSize2 = TemporaryStackSize;
 | |
|         } else {
 | |
|           TempBase1 = (EFI_PHYSICAL_ADDRESS) (UINTN) TemporaryStackBase;
 | |
|           TempSize1 = TemporaryStackSize;
 | |
|           TempBase2 =(EFI_PHYSICAL_ADDRESS) (UINTN) PeiTemporaryRamBase;
 | |
|           TempSize2 = PeiTemporaryRamSize;
 | |
|         }
 | |
|         if (TemporaryRamBase < TempBase1) {
 | |
|           Private->HoleData[0].Base = TemporaryRamBase;
 | |
|           Private->HoleData[0].Size = (UINTN) (TempBase1 - TemporaryRamBase);
 | |
|         }
 | |
|         if (TempBase1 + TempSize1 < TempBase2) {
 | |
|           Private->HoleData[1].Base = TempBase1 + TempSize1;
 | |
|           Private->HoleData[1].Size = (UINTN) (TempBase2 - TempBase1 - TempSize1);
 | |
|         }
 | |
|         if (TempBase2 + TempSize2 < TemporaryRamBase + TemporaryRamSize) {
 | |
|           Private->HoleData[2].Base = TempBase2 + TempSize2;
 | |
|           Private->HoleData[2].Size = (UINTN) (TemporaryRamBase + TemporaryRamSize - TempBase2 - TempSize2);
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // Copy Hole Range data.
 | |
|         //
 | |
|         for (Index = 0; Index < HOLE_MAX_NUMBER; Index ++) {
 | |
|           if (Private->HoleData[Index].Size > 0) {
 | |
|             if (HoleMemBase > Private->HoleData[Index].Base) {
 | |
|               Private->HoleData[Index].OffsetPositive = TRUE;
 | |
|               Private->HoleData[Index].Offset = (UINTN) (HoleMemBase - Private->HoleData[Index].Base);
 | |
|             } else {
 | |
|               Private->HoleData[Index].OffsetPositive = FALSE;
 | |
|               Private->HoleData[Index].Offset = (UINTN) (Private->HoleData[Index].Base - HoleMemBase);
 | |
|             }
 | |
|             CopyMem ((VOID *) (UINTN) HoleMemBase, (VOID *) (UINTN) Private->HoleData[Index].Base, Private->HoleData[Index].Size);
 | |
|             HoleMemBase = HoleMemBase + Private->HoleData[Index].Size;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // Switch new stack
 | |
|       //
 | |
|       SwitchStack (
 | |
|         (SWITCH_STACK_ENTRY_POINT)(UINTN)PeiCoreEntry,
 | |
|         (VOID *) SecCoreData,
 | |
|         (VOID *) Private,
 | |
|         (VOID *) (UINTN) TopOfNewStack
 | |
|         );
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Code should not come here
 | |
|     //
 | |
|     ASSERT (FALSE);
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Conduct PEIM dispatch.
 | |
| 
 | |
|   @param SecCoreData     Points to a data structure containing information about the PEI core's operating
 | |
|                          environment, such as the size and location of temporary RAM, the stack location and
 | |
|                          the BFV location.
 | |
|   @param Private         Pointer to the private data passed in from caller
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| PeiDispatcher (
 | |
|   IN CONST EFI_SEC_PEI_HAND_OFF  *SecCoreData,
 | |
|   IN PEI_CORE_INSTANCE           *Private
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                          Status;
 | |
|   UINT32                              Index1;
 | |
|   UINT32                              Index2;
 | |
|   CONST EFI_PEI_SERVICES              **PeiServices;
 | |
|   EFI_PEI_FILE_HANDLE                 PeimFileHandle;
 | |
|   UINTN                               FvCount;
 | |
|   UINTN                               PeimCount;
 | |
|   UINT32                              AuthenticationState;
 | |
|   EFI_PHYSICAL_ADDRESS                EntryPoint;
 | |
|   EFI_PEIM_ENTRY_POINT2               PeimEntryPoint;
 | |
|   UINTN                               SaveCurrentPeimCount;
 | |
|   UINTN                               SaveCurrentFvCount;
 | |
|   EFI_PEI_FILE_HANDLE                 SaveCurrentFileHandle;
 | |
|   EFI_FV_FILE_INFO                    FvFileInfo;
 | |
|   PEI_CORE_FV_HANDLE                  *CoreFvHandle;
 | |
|   
 | |
|   PeiServices = (CONST EFI_PEI_SERVICES **) &Private->Ps;
 | |
|   PeimEntryPoint = NULL;
 | |
|   PeimFileHandle = NULL;
 | |
|   EntryPoint     = 0;
 | |
| 
 | |
|   if ((Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME || PcdGetBool (PcdShadowPeimOnS3Boot))) {
 | |
|     //
 | |
|     // Once real memory is available, shadow the RegisterForShadow modules. And meanwhile
 | |
|     // update the modules' status from PEIM_STATE_REGISITER_FOR_SHADOW to PEIM_STATE_DONE.
 | |
|     //
 | |
|     SaveCurrentPeimCount  = Private->CurrentPeimCount;
 | |
|     SaveCurrentFvCount    = Private->CurrentPeimFvCount;
 | |
|     SaveCurrentFileHandle =  Private->CurrentFileHandle;
 | |
| 
 | |
|     for (Index1 = 0; Index1 <= SaveCurrentFvCount; Index1++) {
 | |
|       for (Index2 = 0; (Index2 < PcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->Fv[Index1].FvFileHandles[Index2] != NULL); Index2++) {
 | |
|         if (Private->Fv[Index1].PeimState[Index2] == PEIM_STATE_REGISITER_FOR_SHADOW) {
 | |
|           PeimFileHandle = Private->Fv[Index1].FvFileHandles[Index2];
 | |
|           Private->CurrentFileHandle   = PeimFileHandle;
 | |
|           Private->CurrentPeimFvCount  = Index1;
 | |
|           Private->CurrentPeimCount    = Index2;
 | |
|           Status = PeiLoadImage (
 | |
|                     (CONST EFI_PEI_SERVICES **) &Private->Ps,
 | |
|                     PeimFileHandle,
 | |
|                     PEIM_STATE_REGISITER_FOR_SHADOW,
 | |
|                     &EntryPoint,
 | |
|                     &AuthenticationState
 | |
|                     );
 | |
|           if (Status == EFI_SUCCESS) {
 | |
|             //
 | |
|             // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE
 | |
|             //
 | |
|             Private->Fv[Index1].PeimState[Index2]++;
 | |
|             //
 | |
|             // Call the PEIM entry point
 | |
|             //
 | |
|             PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;
 | |
| 
 | |
|             PERF_START (PeimFileHandle, "PEIM", NULL, 0);
 | |
|             PeimEntryPoint(PeimFileHandle, (const EFI_PEI_SERVICES **) &Private->Ps);
 | |
|             PERF_END (PeimFileHandle, "PEIM", NULL, 0);
 | |
|           }
 | |
| 
 | |
|           //
 | |
|           // Process the Notify list and dispatch any notifies for
 | |
|           // newly installed PPIs.
 | |
|           //
 | |
|           ProcessNotifyList (Private);
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     Private->CurrentFileHandle  = SaveCurrentFileHandle;
 | |
|     Private->CurrentPeimFvCount = SaveCurrentFvCount;
 | |
|     Private->CurrentPeimCount   = SaveCurrentPeimCount;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // This is the main dispatch loop.  It will search known FVs for PEIMs and
 | |
|   // attempt to dispatch them.  If any PEIM gets dispatched through a single
 | |
|   // pass of the dispatcher, it will start over from the Bfv again to see
 | |
|   // if any new PEIMs dependencies got satisfied.  With a well ordered
 | |
|   // FV where PEIMs are found in the order their dependencies are also
 | |
|   // satisfied, this dipatcher should run only once.
 | |
|   //
 | |
|   do {
 | |
|     //
 | |
|     // In case that reenter PeiCore happens, the last pass record is still available.   
 | |
|     //
 | |
|     if (!Private->PeimDispatcherReenter) {
 | |
|       Private->PeimNeedingDispatch      = FALSE;
 | |
|       Private->PeimDispatchOnThisPass   = FALSE;
 | |
|     } else {
 | |
|       Private->PeimDispatcherReenter    = FALSE;
 | |
|     }
 | |
|     
 | |
|     for (FvCount = Private->CurrentPeimFvCount; FvCount < Private->FvCount; FvCount++) {
 | |
|       CoreFvHandle = FindNextCoreFvHandle (Private, FvCount);
 | |
|       ASSERT (CoreFvHandle != NULL);
 | |
|       
 | |
|       //
 | |
|       // If the FV has corresponding EFI_PEI_FIRMWARE_VOLUME_PPI instance, then dispatch it.
 | |
|       //
 | |
|       if (CoreFvHandle->FvPpi == NULL) {
 | |
|         continue;
 | |
|       }
 | |
|       
 | |
|       Private->CurrentPeimFvCount = FvCount;
 | |
| 
 | |
|       if (Private->CurrentPeimCount == 0) {
 | |
|         //
 | |
|         // When going through each FV, at first, search Apriori file to
 | |
|         // reorder all PEIMs to ensure the PEIMs in Apriori file to get
 | |
|         // dispatch at first.
 | |
|         //
 | |
|         DiscoverPeimsAndOrderWithApriori (Private, CoreFvHandle);
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // Start to dispatch all modules within the current Fv.
 | |
|       //
 | |
|       for (PeimCount = Private->CurrentPeimCount;
 | |
|            (PeimCount < PcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->CurrentFvFileHandles[PeimCount] != NULL);
 | |
|            PeimCount++) {
 | |
|         Private->CurrentPeimCount  = PeimCount;
 | |
|         PeimFileHandle = Private->CurrentFileHandle = Private->CurrentFvFileHandles[PeimCount];
 | |
| 
 | |
|         if (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_NOT_DISPATCHED) {
 | |
|           if (!DepexSatisfied (Private, PeimFileHandle, PeimCount)) {
 | |
|             Private->PeimNeedingDispatch = TRUE;
 | |
|           } else {
 | |
|             Status = CoreFvHandle->FvPpi->GetFileInfo (CoreFvHandle->FvPpi, PeimFileHandle, &FvFileInfo);
 | |
|             ASSERT_EFI_ERROR (Status);
 | |
|             if (FvFileInfo.FileType == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
 | |
|               //
 | |
|               // For Fv type file, Produce new FvInfo PPI and FV hob
 | |
|               //
 | |
|               Status = ProcessFvFile (Private, &Private->Fv[FvCount], PeimFileHandle);
 | |
|               if (Status == EFI_SUCCESS) {
 | |
|                 //
 | |
|                 // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED
 | |
|                 //
 | |
|                 Private->Fv[FvCount].PeimState[PeimCount]++;
 | |
|                 Private->PeimDispatchOnThisPass = TRUE;
 | |
|               } else {
 | |
|                 //
 | |
|                 // The related GuidedSectionExtraction/Decompress PPI for the
 | |
|                 // encapsulated FV image section may be installed in the rest
 | |
|                 // of this do-while loop, so need to make another pass.
 | |
|                 //
 | |
|                 Private->PeimNeedingDispatch = TRUE;
 | |
|               }
 | |
|             } else {
 | |
|               //
 | |
|               // For PEIM driver, Load its entry point
 | |
|               //
 | |
|               Status = PeiLoadImage (
 | |
|                          PeiServices,
 | |
|                          PeimFileHandle,
 | |
|                          PEIM_STATE_NOT_DISPATCHED,
 | |
|                          &EntryPoint,
 | |
|                          &AuthenticationState
 | |
|                          );
 | |
|               if (Status == EFI_SUCCESS) {
 | |
|                 //
 | |
|                 // The PEIM has its dependencies satisfied, and its entry point
 | |
|                 // has been found, so invoke it.
 | |
|                 //
 | |
|                 PERF_START (PeimFileHandle, "PEIM", NULL, 0);
 | |
| 
 | |
|                 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
 | |
|                   EFI_PROGRESS_CODE,
 | |
|                   (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN),
 | |
|                   (VOID *)(&PeimFileHandle),
 | |
|                   sizeof (PeimFileHandle)
 | |
|                   );
 | |
| 
 | |
|                 Status = VerifyPeim (Private, CoreFvHandle->FvHandle, PeimFileHandle, AuthenticationState);
 | |
|                 if (Status != EFI_SECURITY_VIOLATION) {
 | |
|                   //
 | |
|                   // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED
 | |
|                   //
 | |
|                   Private->Fv[FvCount].PeimState[PeimCount]++;
 | |
|                   //
 | |
|                   // Call the PEIM entry point for PEIM driver
 | |
|                   //
 | |
|                   PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;
 | |
|                   PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);
 | |
|                   Private->PeimDispatchOnThisPass = TRUE;
 | |
|                 } else {
 | |
|                   //
 | |
|                   // The related GuidedSectionExtraction PPI for the
 | |
|                   // signed PEIM image section may be installed in the rest
 | |
|                   // of this do-while loop, so need to make another pass.
 | |
|                   //
 | |
|                   Private->PeimNeedingDispatch = TRUE;
 | |
|                 }
 | |
| 
 | |
|                 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
 | |
|                   EFI_PROGRESS_CODE,
 | |
|                   (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_END),
 | |
|                   (VOID *)(&PeimFileHandle),
 | |
|                   sizeof (PeimFileHandle)
 | |
|                   );
 | |
|                 PERF_END (PeimFileHandle, "PEIM", NULL, 0);
 | |
| 
 | |
|               }
 | |
|             }
 | |
| 
 | |
|             PeiCheckAndSwitchStack (SecCoreData, Private);
 | |
| 
 | |
|             //
 | |
|             // Process the Notify list and dispatch any notifies for
 | |
|             // newly installed PPIs.
 | |
|             //
 | |
|             ProcessNotifyList (Private);
 | |
| 
 | |
|             //
 | |
|             // Recheck SwitchStackSignal after ProcessNotifyList()
 | |
|             // in case PeiInstallPeiMemory() is done in a callback with
 | |
|             // EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH.
 | |
|             //
 | |
|             PeiCheckAndSwitchStack (SecCoreData, Private);
 | |
| 
 | |
|             if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISITER_FOR_SHADOW) &&   \
 | |
|                 (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME || PcdGetBool (PcdShadowPeimOnS3Boot))) {
 | |
|               //
 | |
|               // If memory is available we shadow images by default for performance reasons.
 | |
|               // We call the entry point a 2nd time so the module knows it's shadowed.
 | |
|               //
 | |
|               //PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0);
 | |
|               if ((Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) && !PcdGetBool (PcdShadowPeimOnBoot)) {
 | |
|                 //
 | |
|                 // Load PEIM into Memory for Register for shadow PEIM.
 | |
|                 //
 | |
|                 Status = PeiLoadImage (
 | |
|                            PeiServices,
 | |
|                            PeimFileHandle,
 | |
|                            PEIM_STATE_REGISITER_FOR_SHADOW,
 | |
|                            &EntryPoint,
 | |
|                            &AuthenticationState
 | |
|                            );
 | |
|                 if (Status == EFI_SUCCESS) {
 | |
|                   PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;
 | |
|                 }
 | |
|               }
 | |
|               ASSERT (PeimEntryPoint != NULL);
 | |
|               PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);
 | |
|               //PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0);
 | |
| 
 | |
|               //
 | |
|               // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE
 | |
|               //
 | |
|               Private->Fv[FvCount].PeimState[PeimCount]++;
 | |
| 
 | |
|               //
 | |
|               // Process the Notify list and dispatch any notifies for
 | |
|               // newly installed PPIs.
 | |
|               //
 | |
|               ProcessNotifyList (Private);
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // We set to NULL here to optimize the 2nd entry to this routine after
 | |
|       //  memory is found. This reprevents rescanning of the FV. We set to
 | |
|       //  NULL here so we start at the begining of the next FV
 | |
|       //
 | |
|       Private->CurrentFileHandle = NULL;
 | |
|       Private->CurrentPeimCount = 0;
 | |
|       //
 | |
|       // Before walking through the next FV,Private->CurrentFvFileHandles[]should set to NULL
 | |
|       //
 | |
|       SetMem (Private->CurrentFvFileHandles, sizeof (EFI_PEI_FILE_HANDLE) * PcdGet32 (PcdPeiCoreMaxPeimPerFv), 0);
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Before making another pass, we should set Private->CurrentPeimFvCount =0 to go
 | |
|     // through all the FV.
 | |
|     //
 | |
|     Private->CurrentPeimFvCount = 0;
 | |
| 
 | |
|     //
 | |
|     // PeimNeedingDispatch being TRUE means we found a PEIM/FV that did not get
 | |
|     //  dispatched. So we need to make another pass
 | |
|     //
 | |
|     // PeimDispatchOnThisPass being TRUE means we dispatched a PEIM/FV on this
 | |
|     //  pass. If we did not dispatch a PEIM/FV there is no point in trying again
 | |
|     //  as it will fail the next time too (nothing has changed).
 | |
|     //
 | |
|   } while (Private->PeimNeedingDispatch && Private->PeimDispatchOnThisPass);
 | |
| 
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Initialize the Dispatcher's data members
 | |
| 
 | |
|   @param PrivateData     PeiCore's private data structure
 | |
|   @param OldCoreData     Old data from SecCore
 | |
|                          NULL if being run in non-permament memory mode.
 | |
|   @param SecCoreData     Points to a data structure containing information about the PEI core's operating
 | |
|                          environment, such as the size and location of temporary RAM, the stack location and
 | |
|                          the BFV location.
 | |
| 
 | |
|   @return None.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| InitializeDispatcherData (
 | |
|   IN PEI_CORE_INSTANCE            *PrivateData,
 | |
|   IN PEI_CORE_INSTANCE            *OldCoreData,
 | |
|   IN CONST EFI_SEC_PEI_HAND_OFF   *SecCoreData
 | |
|   )
 | |
| {
 | |
|   if (OldCoreData == NULL) {
 | |
|     PrivateData->PeimDispatcherReenter = FALSE;
 | |
|     PeiInitializeFv (PrivateData, SecCoreData);
 | |
|   } else {
 | |
|     PeiReinitializeFv (PrivateData);
 | |
|   }
 | |
| 
 | |
|   return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This routine parses the Dependency Expression, if available, and
 | |
|   decides if the module can be executed.
 | |
| 
 | |
| 
 | |
|   @param Private         PeiCore's private data structure
 | |
|   @param FileHandle      PEIM's file handle
 | |
|   @param PeimCount       Peim count in all dispatched PEIMs.
 | |
| 
 | |
|   @retval TRUE   Can be dispatched
 | |
|   @retval FALSE  Cannot be dispatched
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| DepexSatisfied (
 | |
|   IN PEI_CORE_INSTANCE          *Private,
 | |
|   IN EFI_PEI_FILE_HANDLE        FileHandle,
 | |
|   IN UINTN                      PeimCount
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS           Status;
 | |
|   VOID                 *DepexData;
 | |
|   EFI_FV_FILE_INFO     FileInfo;
 | |
| 
 | |
|   Status = PeiServicesFfsGetFileInfo (FileHandle, &FileInfo);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_DISPATCH, "Evaluate PEI DEPEX for FFS(Unknown)\n"));
 | |
|   } else {
 | |
|     DEBUG ((DEBUG_DISPATCH, "Evaluate PEI DEPEX for FFS(%g)\n", &FileInfo.FileName));
 | |
|   }
 | |
|   
 | |
|   if (PeimCount < Private->AprioriCount) {
 | |
|     //
 | |
|     // If its in the A priori file then we set Depex to TRUE
 | |
|     //
 | |
|     DEBUG ((DEBUG_DISPATCH, "  RESULT = TRUE (Apriori)\n"));
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Depex section not in the encapsulated section.
 | |
|   //
 | |
|   Status = PeiServicesFfsFindSectionData (
 | |
|               EFI_SECTION_PEI_DEPEX,
 | |
|               FileHandle,
 | |
|               (VOID **)&DepexData
 | |
|               );
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     //
 | |
|     // If there is no DEPEX, assume the module can be executed
 | |
|     //
 | |
|     DEBUG ((DEBUG_DISPATCH, "  RESULT = TRUE (No DEPEX)\n"));
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Evaluate a given DEPEX
 | |
|   //
 | |
|   return PeimDispatchReadiness (&Private->Ps, DepexData);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This routine enable a PEIM to register itself to shadow when PEI Foundation
 | |
|   discovery permanent memory.
 | |
| 
 | |
|   @param FileHandle             File handle of a PEIM.
 | |
| 
 | |
|   @retval EFI_NOT_FOUND         The file handle doesn't point to PEIM itself.
 | |
|   @retval EFI_ALREADY_STARTED   Indicate that the PEIM has been registered itself.
 | |
|   @retval EFI_SUCCESS           Successfully to register itself.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| PeiRegisterForShadow (
 | |
|   IN EFI_PEI_FILE_HANDLE       FileHandle
 | |
|   )
 | |
| {
 | |
|   PEI_CORE_INSTANCE            *Private;
 | |
|   Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());
 | |
| 
 | |
|   if (Private->CurrentFileHandle != FileHandle) {
 | |
|     //
 | |
|     // The FileHandle must be for the current PEIM
 | |
|     //
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   if (Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] >= PEIM_STATE_REGISITER_FOR_SHADOW) {
 | |
|     //
 | |
|     // If the PEIM has already entered the PEIM_STATE_REGISTER_FOR_SHADOW or PEIM_STATE_DONE then it's already been started
 | |
|     //
 | |
|     return EFI_ALREADY_STARTED;
 | |
|   }
 | |
| 
 | |
|   Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] = PEIM_STATE_REGISITER_FOR_SHADOW;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 |