X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FCore%2FPei%2FDispatcher%2FDispatcher.c;h=f5ce4dee613a3a883f7719459a51a287c659792b;hp=164c2c874623e38db06fe367dbe6aed80031ddd4;hb=e94358a3fe824986cfaa777690170f26aa5a8200;hpb=a3a15d2108bb276f8a668a059c86ccfc101e5986 diff --git a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c index 164c2c8746..f5ce4dee61 100644 --- a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c +++ b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c @@ -1,4 +1,4 @@ -/*++ +/** @file Copyright (c) 2006, Intel Corporation All rights reserved. This program and the accompanying materials @@ -19,17 +19,19 @@ Abstract: Revision History ---*/ +**/ #include -STATIC -VOID -InvokePeiCore ( - VOID *Context1, - VOID *Context2 - ); +// +//CAR is filled with this initial value during SEC phase +// +#define INIT_CAR_VALUE 0x5AA55AA5 +typedef struct { + EFI_STATUS_CODE_DATA DataHeader; + EFI_HANDLE Handle; +} PEIM_FILE_HANDLE_EXTENDED_DATA; VOID DiscoverPeimsAndOrderWithApriori ( @@ -51,7 +53,7 @@ Returns: NONE ---*/ +--*/ { EFI_STATUS Status; EFI_PEI_FV_HANDLE FileHandle; @@ -86,20 +88,20 @@ Returns: // for (PeimCount = 0; PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv); PeimCount++) { Status = PeiFindFileEx ( - VolumeHandle, - NULL, - PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE, + VolumeHandle, + NULL, + PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE, &FileHandle, &AprioriFileHandle ); if (Status != EFI_SUCCESS) { break; } - + Private->CurrentFvFileHandles[PeimCount] = FileHandle; } - Private->AprioriCount = 0; + Private->AprioriCount = 0; if (AprioriFileHandle != NULL) { // // Read the Apriori file @@ -110,21 +112,21 @@ Returns: // Calculate the number of PEIMs in the A Priori list // Private->AprioriCount = *(UINT32 *)(((EFI_FFS_FILE_HEADER *)AprioriFileHandle)->Size) & 0x00FFFFFF; - Private->AprioriCount -= sizeof (EFI_FFS_FILE_HEADER) - sizeof (EFI_COMMON_SECTION_HEADER); + Private->AprioriCount -= sizeof (EFI_FFS_FILE_HEADER) - sizeof (EFI_COMMON_SECTION_HEADER); Private->AprioriCount /= sizeof (EFI_GUID); - + SetMem (FileGuid, sizeof (FileGuid), 0); 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 // - CopyMem (&FileGuid[Index], &((EFI_FFS_FILE_HEADER *)Private->CurrentFvFileHandles[Index])->Name,sizeof(EFI_GUID)); + CopyMem (&FileGuid[Index], &((EFI_FFS_FILE_HEADER *)Private->CurrentFvFileHandles[Index])->Name,sizeof(EFI_GUID)); } // // Walk through FileGuid array to find out who is invalid PEIM guid in Apriori file. - // Add avalible PEIMs in Apriori file into TempFileHandles array at first. + // Add avalible PEIMs in Apriori file into TempFileHandles array at first. // Index2 = 0; for (Index = 0; Index2 < Private->AprioriCount; Index++) { @@ -135,7 +137,7 @@ Returns: } } if (Guid == NULL) { - break; + break; } PeimIndex = ((UINTN)Guid - (UINTN)&FileGuid[0])/sizeof (EFI_GUID); TempFileHandles[Index] = Private->CurrentFvFileHandles[PeimIndex]; @@ -150,7 +152,7 @@ Returns: // Update valid Aprioricount // Private->AprioriCount = Index; - + // // Add in any PEIMs not in the Apriori file // @@ -167,11 +169,11 @@ Returns: //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. + // 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 (Private->CurrentFvFileHandles)); } @@ -182,7 +184,46 @@ Returns: // Private->Fv[Private->CurrentPeimFvCount].ScanFv = TRUE; CopyMem (Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, Private->CurrentFvFileHandles, sizeof (Private->CurrentFvFileHandles)); - + +} + +VOID* +ShadowPeiCore( + EFI_PEI_SERVICES **PeiServices, + PEI_CORE_INSTANCE *PrivateInMem + ) +{ + EFI_PEI_FILE_HANDLE PeiCoreFileHandle; + EFI_PHYSICAL_ADDRESS EntryPoint; + EFI_STATUS Status; + UINT32 AuthenticationState; + + PeiCoreFileHandle = NULL; + + // + // Find the PEI Core in the BFV + // + Status = PeiFindFileEx ( + (EFI_PEI_FV_HANDLE)PrivateInMem->Fv[0].FvHeader, + NULL, + EFI_FV_FILETYPE_PEI_CORE, + &PeiCoreFileHandle, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Shadow PEI Core into memory so it will run faster + // + Status = PeiLoadImage ( + PeiServices, + *((EFI_PEI_FILE_HANDLE*)&PeiCoreFileHandle), + &EntryPoint, + &AuthenticationState + ); + ASSERT_EFI_ERROR (Status); + + return (VOID*) ((UINTN) EntryPoint + (UINTN) PeiCore - (UINTN) _ModuleEntryPoint); } VOID @@ -216,28 +257,38 @@ Returns: UINT32 Index1; UINT32 Index2; EFI_PEI_SERVICES **PeiServices; - VOID *PrivateInMem; - EFI_PEI_FV_HANDLE VolumeHandle; - EFI_PEI_FILE_HANDLE PeiCoreFileHandle; + EFI_PEI_FV_HANDLE VolumeHandle; EFI_PEI_FILE_HANDLE PeimFileHandle; UINTN FvCount; UINTN PeimCount; UINT32 AuthenticationState; EFI_PHYSICAL_ADDRESS EntryPoint; - EFI_PEIM_ENTRY_POINT PeimEntryPoint; + EFI_PEIM_ENTRY_POINT2 PeimEntryPoint; BOOLEAN PeimNeedingDispatch; BOOLEAN PeimDispatchOnThisPass; UINTN SaveCurrentPeimCount; UINTN SaveCurrentFvCount; EFI_PEI_FILE_HANDLE SaveCurrentFileHandle; - VOID *TopOfStack; - PEI_CORE_PARAMETERS PeiCoreParameters; - EFI_DEVICE_HANDLE_EXTENDED_DATA ExtendedData; + PEIM_FILE_HANDLE_EXTENDED_DATA ExtendedData; + EFI_PHYSICAL_ADDRESS NewPermenentMemoryBase; + TEMPORARY_RAM_SUPPORT_PPI *TemporaryRamSupportPpi; + EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffTable; + EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffTable; + INTN StackOffset; + INTN HeapOffset; + PEI_CORE_INSTANCE *PrivateInMem; + UINT64 NewPeiStackSize; + UINT64 OldPeiStackSize; + UINT64 StackGap; + EFI_FV_FILE_INFO FvFileInfo; + UINTN OldCheckingTop; + UINTN OldCheckingBottom; PeiServices = &Private->PS; PeimEntryPoint = NULL; PeimFileHandle = NULL; + EntryPoint = 0; if ((Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) { // @@ -251,11 +302,11 @@ Returns: for (Index1 = 0; Index1 <= SaveCurrentFvCount; Index1++) { for (Index2 = 0; (Index2 < FixedPcdGet32 (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]; + PeimFileHandle = Private->Fv[Index1].FvFileHandles[Index2]; Status = PeiLoadImage ( - &Private->PS, - PeimFileHandle, - &EntryPoint, + &Private->PS, + PeimFileHandle, + &EntryPoint, &AuthenticationState ); if (Status == EFI_SUCCESS) { @@ -264,18 +315,18 @@ Returns: // Private->Fv[Index1].PeimState[Index2]++; Private->CurrentFileHandle = PeimFileHandle; - Private->CurrentPeimFvCount = Index1; - Private->CurrentPeimCount = Index2; + Private->CurrentPeimFvCount = Index1; + Private->CurrentPeimCount = Index2; // // Call the PEIM entry point // - PeimEntryPoint = (EFI_PEIM_ENTRY_POINT)(UINTN)EntryPoint; - + PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint; + PERF_START (0, "PEIM", NULL, 0); - PeimEntryPoint(PeimFileHandle, &Private->PS); + PeimEntryPoint(PeimFileHandle, (const EFI_PEI_SERVICES **) &Private->PS); PERF_END (0, "PEIM", NULL, 0); - } - + } + // // Process the Notify list and dispatch any notifies for // newly installed PPIs. @@ -284,9 +335,9 @@ Returns: } } } - Private->CurrentFileHandle = SaveCurrentFileHandle; - Private->CurrentPeimFvCount = SaveCurrentFvCount; - Private->CurrentPeimCount = SaveCurrentPeimCount; + Private->CurrentFileHandle = SaveCurrentFileHandle; + Private->CurrentPeimFvCount = SaveCurrentFvCount; + Private->CurrentPeimCount = SaveCurrentPeimCount; } // @@ -308,7 +359,7 @@ Returns: 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 + // reorder all PEIMs to ensure the PEIMs in Apriori file to get // dispatch at first. // DiscoverPeimsAndOrderWithApriori (Private, VolumeHandle); @@ -317,8 +368,8 @@ Returns: // // Start to dispatch all modules within the current Fv. // - for (PeimCount = Private->CurrentPeimCount; - (PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->CurrentFvFileHandles[PeimCount] != NULL); + for (PeimCount = Private->CurrentPeimCount; + (PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->CurrentFvFileHandles[PeimCount] != NULL); PeimCount++) { Private->CurrentPeimCount = PeimCount; PeimFileHandle = Private->CurrentFileHandle = Private->CurrentFvFileHandles[PeimCount]; @@ -327,12 +378,25 @@ Returns: if (!DepexSatisfied (Private, PeimFileHandle, PeimCount)) { PeimNeedingDispatch = TRUE; } else { - Status = PeiLoadImage ( - PeiServices, - PeimFileHandle, - &EntryPoint, - &AuthenticationState - ); + Status = PeiFfsGetFileInfo (PeimFileHandle, &FvFileInfo); + ASSERT_EFI_ERROR (Status); + if (FvFileInfo.FileType == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) { + // + // For Fv type file, Produce new FV PPI and FV hob + // + Status = ProcessFvFile (PeiServices, PeimFileHandle, &AuthenticationState); + } else { + // + // For PEIM driver, Load its entry point + // + Status = PeiLoadImage ( + PeiServices, + PeimFileHandle, + &EntryPoint, + &AuthenticationState + ); + } + if ((Status == EFI_SUCCESS)) { // // The PEIM has its dependencies satisfied, and its entry point @@ -344,7 +408,7 @@ Returns: REPORT_STATUS_CODE_WITH_EXTENDED_DATA ( EFI_PROGRESS_CODE, - EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN, + FixedPcdGet32(PcdStatusCodeValuePeimDispatch), (VOID *)(&ExtendedData), sizeof (ExtendedData) ); @@ -356,118 +420,214 @@ Returns: // Private->Fv[FvCount].PeimState[PeimCount]++; - // - // Call the PEIM entry point - // - PeimEntryPoint = (EFI_PEIM_ENTRY_POINT)(UINTN)EntryPoint; - PeimEntryPoint (PeimFileHandle, PeiServices); + if (FvFileInfo.FileType != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) { + // + // Call the PEIM entry point for PEIM driver + // + PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint; + PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices); + } + PeimDispatchOnThisPass = TRUE; } REPORT_STATUS_CODE_WITH_EXTENDED_DATA ( EFI_PROGRESS_CODE, - EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_END, + FixedPcdGet32(PcdStatusCodeValuePeimDispatch), (VOID *)(&ExtendedData), sizeof (ExtendedData) ); PERF_END (0, "PEIM", NULL, 0); - } else { + } + + if (Private->SwitchStackSignal) { // - // If PeiLoadImage fails, the section extraction PPI or Decompress PPI may not be ready, - // we flag that more Peims need to be dispatched. + // Before switch stack from CAR to permenent memory, caculate the heap and stack + // usage in temporary memory for debuging. // - PeimNeedingDispatch = TRUE; - } + DEBUG_CODE_BEGIN (); + UINT32 *StackPointer; + + for (StackPointer = (UINT32*)SecCoreData->StackBase; + (StackPointer < (UINT32*)((UINTN)SecCoreData->StackBase + SecCoreData->StackSize)) \ + && (*StackPointer == INIT_CAR_VALUE); + StackPointer ++); + + DEBUG ((EFI_D_INFO, "Total Cache as RAM: %d bytes.\n", SecCoreData->TemporaryRamSize)); + DEBUG ((EFI_D_INFO, " CAR stack ever used: %d bytes.\n", + (SecCoreData->StackSize - ((UINTN) StackPointer - (UINTN)SecCoreData->StackBase)) + )); + DEBUG ((EFI_D_INFO, " CAR heap used: %d bytes.\n", + ((UINTN) Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - + (UINTN) Private->HobList.Raw) + )); + DEBUG_CODE_END (); + + // + // Reserve the size of new stack at bottom of physical memory + // + OldPeiStackSize = Private->StackSize; + NewPeiStackSize = (RShiftU64 (Private->PhysicalMemoryLength, 1) + EFI_PAGE_MASK) & ~EFI_PAGE_MASK; + if (FixedPcdGet32(PcdPeiCoreMaxPeiStackSize) > (UINT32) NewPeiStackSize) { + Private->StackSize = NewPeiStackSize; + } else { + Private->StackSize = FixedPcdGet32(PcdPeiCoreMaxPeiStackSize); + } - // - // Process the Notify list and dispatch any notifies for - // newly installed PPIs. - // - ProcessNotifyList (Private); + // + // In theory, the size of new stack in permenent memory should large than + // 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 permenent memory. + // + StackGap = 0; + if (Private->StackSize > OldPeiStackSize) { + StackGap = Private->StackSize - OldPeiStackSize; + } - // - // If permanent memory was discovered and installed by this - // PEIM, shadow PEI Core and switch the stacks to the new memory. - // - if (Private->SwitchStackSignal) { + // + // Update HandOffHob for new installed permenent memory + // + OldHandOffTable = Private->HobList.HandoffInformationTable; + OldCheckingBottom = (UINTN)OldHandOffTable; + OldCheckingTop = (UINTN)(OldCheckingBottom + SecCoreData->TemporaryRamSize); // - // Make sure we don't retry the same PEIM that added memory + // The whole temporary memory will be migrated to physical memory. + // CAUTION: The new base is computed accounding to gap of new stack. // - Private->CurrentPeimCount++; + NewPermenentMemoryBase = Private->PhysicalMemoryBegin + StackGap; + StackOffset = (UINTN) NewPermenentMemoryBase - (UINTN) SecCoreData->StackBase; + HeapOffset = (INTN) ((UINTN) Private->PhysicalMemoryBegin + Private->StackSize - \ + (UINTN) SecCoreData->PeiTemporaryRamBase); + DEBUG ((EFI_D_INFO, "Heap Offset = 0x%X Stack Offset = 0x%X\n", HeapOffset, StackOffset)); + + NewHandOffTable = (EFI_HOB_HANDOFF_INFO_TABLE *)((UINTN)OldHandOffTable + HeapOffset); + PrivateInMem = (PEI_CORE_INSTANCE *)((UINTN) (VOID*) Private + StackOffset); // - // Migrate IDT from CAR into real memory, so after stack switches to - // the new memory, the caller can get memory version PeiServiceTable. + // TemporaryRamSupportPpi is produced by platform's SEC // - MigrateIdtTable (PeiServices); + Status = PeiLocatePpi ( + (CONST EFI_PEI_SERVICES **) PeiServices, + &gEfiTemporaryRamSupportPpiGuid, + 0, + NULL, + (VOID**)&TemporaryRamSupportPpi + ); + + + if (!EFI_ERROR (Status)) { + TemporaryRamSupportPpi->TemporaryRamMigration ( + (CONST EFI_PEI_SERVICES **) PeiServices, + (EFI_PHYSICAL_ADDRESS)(UINTN) SecCoreData->TemporaryRamBase, + (EFI_PHYSICAL_ADDRESS)(UINTN) NewPermenentMemoryBase, + SecCoreData->TemporaryRamSize + ); + + } else { + // + // In IA32/x64/Itanium architecture, we need platform provide + // TEMPORAY_RAM_MIGRATION_PPI. + // + ASSERT (FALSE); + } + + // // - // Since we are at dispatch level, only the Core's private data - // is preserved, nobody else should have any data on the stack. - // So we need to copy PEI core instance data to memory. + // Fixup the PeiCore's private data // - PrivateInMem = AllocateCopyPool (sizeof (PEI_CORE_INSTANCE), Private); - ASSERT (PrivateInMem != NULL); + PrivateInMem->PS = &PrivateInMem->ServiceTableShadow; + PrivateInMem->CpuIo = &PrivateInMem->ServiceTableShadow.CpuIo; + PrivateInMem->HobList.Raw = (VOID*) ((UINTN) PrivateInMem->HobList.Raw + HeapOffset); + PrivateInMem->StackBase = (EFI_PHYSICAL_ADDRESS)(((UINTN)PrivateInMem->PhysicalMemoryBegin + EFI_PAGE_MASK) & ~EFI_PAGE_MASK); + + PeiServices = &PrivateInMem->PS; // - // Shadow PEI Core. When permanent memory is avaiable, shadow - // PEI Core and PEIMs to get high performance. + // Fixup for PeiService's address + // + SetPeiServicesTablePointer(PeiServices); + // - PeiCoreFileHandle = NULL; + // Update HandOffHob for new installed permenent memory // - // Find the PEI Core in the BFV + NewHandOffTable->EfiEndOfHobList = + (EFI_PHYSICAL_ADDRESS)((UINTN) NewHandOffTable->EfiEndOfHobList + HeapOffset); + NewHandOffTable->EfiMemoryTop = PrivateInMem->PhysicalMemoryBegin + + PrivateInMem->PhysicalMemoryLength; + NewHandOffTable->EfiMemoryBottom = PrivateInMem->PhysicalMemoryBegin; + NewHandOffTable->EfiFreeMemoryTop = PrivateInMem->FreePhysicalMemoryTop; + NewHandOffTable->EfiFreeMemoryBottom = NewHandOffTable->EfiEndOfHobList + + sizeof (EFI_HOB_GENERIC_HEADER); + // - Status = PeiFindFileEx ( - (EFI_PEI_FV_HANDLE)Private->Fv[0].FvHeader, - NULL, - EFI_FV_FILETYPE_PEI_CORE, - &PeiCoreFileHandle, - NULL - ); - ASSERT_EFI_ERROR (Status); - + // We need convert the PPI desciptor's pointer // - // Shadow PEI Core into memory so it will run faster + ConvertPpiPointers ((CONST EFI_PEI_SERVICES **)PeiServices, + OldCheckingBottom, + OldCheckingTop, + NewHandOffTable); + + DEBUG ((EFI_D_INFO, "Stack Hob: BaseAddress=0x%X Length=0x%X\n", + (UINTN)PrivateInMem->StackBase, + PrivateInMem->StackSize)); + BuildStackHob (PrivateInMem->StackBase, PrivateInMem->StackSize); + // - Status = PeiLoadImage (PeiServices, PeiCoreFileHandle, &EntryPoint, &AuthenticationState); - ASSERT_EFI_ERROR (Status); - + // After the whole temporary memory is migrated, then we can allocate page in + // permenent memory. // - // Switch to memory based stack and reenter PEI Core that has been - // shadowed to memory. + PrivateInMem->PeiMemoryInstalled = TRUE; + // + // Restart scan of all PEIMs on next pass // - // Adjust the top of stack to be aligned at CPU_STACK_ALIGNMENT + PrivateInMem->CurrentPeimCount = 0; + // - TopOfStack = (VOID *)((UINTN)Private->StackBase + (UINTN)Private->StackSize - CPU_STACK_ALIGNMENT); - TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT); - - PeiCoreParameters.SecCoreData = SecCoreData; - PeiCoreParameters.PpiList = NULL; - PeiCoreParameters.Data = PrivateInMem; - ASSERT (PeiCoreParameters.Data != 0); - - PeiSwitchStacks ( - InvokePeiCore, - (VOID*) ((UINTN) EntryPoint + ((UINTN) PeiCore - (UINTN) _ModuleEntryPoint)), - (VOID*) &PeiCoreParameters, - TopOfStack, - (VOID*)(UINTN)Private->StackBase - ); + // Shadow PEI Core. When permanent memory is avaiable, shadow + // PEI Core and PEIMs to get high performance. + // + PrivateInMem->ShadowedPeiCore = ShadowPeiCore ( + PeiServices, + PrivateInMem + ); + // + // Process the Notify list and dispatch any notifies for + // newly installed PPIs. + // + ProcessNotifyList (PrivateInMem); + + // + // Entry PEI Phase 2 + // + PeiCore (SecCoreData, NULL, PrivateInMem); + + // + // Code should not come here + // + ASSERT_EFI_ERROR(FALSE); } + // + // Process the Notify list and dispatch any notifies for + // newly installed PPIs. + // + ProcessNotifyList (Private); + if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISITER_FOR_SHADOW) && \ (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) { // - // If memory is availble we shadow images by default for performance reasons. - // We call the entry point a 2nd time so the module knows it's shadowed. + // If memory is availble 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); - PeimEntryPoint (PeimFileHandle, PeiServices); + PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices); //PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0); - + // // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE // @@ -497,16 +657,16 @@ Returns: } // - // Before making another pass, we should set Private->CurrentPeimFvCount =0 to go + // 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 that did not get + // PeimNeedingDispatch being TRUE means we found a PEIM that did not get // dispatched. So we need to make another pass // - // PeimDispatchOnThisPass being TRUE means we dispatched a PEIM on this + // PeimDispatchOnThisPass being TRUE means we dispatched a PEIM on this // pass. If we did not dispatch a PEIM there is no point in trying again // as it will fail the next time too (nothing has changed). // @@ -572,8 +732,8 @@ Returns: --*/ { - EFI_STATUS Status; - VOID *DepexData; + EFI_STATUS Status; + VOID *DepexData; if (PeimCount < Private->AprioriCount) { // @@ -582,7 +742,15 @@ Returns: return TRUE; } - Status = PeiServicesFfsFindSectionData (EFI_SECTION_PEI_DEPEX, FileHandle, (VOID **) &DepexData); + // + // 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 @@ -601,12 +769,12 @@ Returns: 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 ( @@ -629,49 +797,126 @@ PeiRegisterForShadow ( // return EFI_ALREADY_STARTED; } - + Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] = PEIM_STATE_REGISITER_FOR_SHADOW; return EFI_SUCCESS; } + /** - This routine invoke the PeiCore's entry in new stack environment. + Get Fv image from the FV type file, then install FV INFO ppi, Build FV hob. - @param Context1 The first context parameter is entry of PeiCore - @param Context2 The second context parameter is parameter structure point for PeiCore + @param PeiServices Pointer to the PEI Core Services Table. + @param FileHandle File handle of a Fv type file. + @param AuthenticationState Pointer to attestation authentication state of image. -**/ -STATIC -VOID -InvokePeiCore ( - VOID *Context1, - VOID *Context2 + + @retval EFI_NOT_FOUND FV image can't be found. + @retval EFI_SUCCESS Successfully to process it. + +**/ +EFI_STATUS +ProcessFvFile ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_FILE_HANDLE FvFileHandle, + OUT UINT32 *AuthenticationState ) { - PEI_CORE_ENTRY_POINT PeiCoreEntryPoint; - PEI_CORE_PARAMETERS *PeiCoreParameters; + EFI_STATUS Status; + EFI_PEI_FV_HANDLE FvImageHandle; + EFI_FV_INFO FvImageInfo; + UINT32 FvAlignment; + VOID *FvBuffer; + EFI_PEI_HOB_POINTERS HobFv2; + + FvBuffer = NULL; + *AuthenticationState = 0; // - // Running on new stack in SEC Core + // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already + // been extracted. // + HobFv2.Raw = GetHobList (); + while ((HobFv2.Raw = GetNextHob (EFI_HOB_TYPE_FV2, HobFv2.Raw)) != NULL) { + if (CompareGuid (&(((EFI_FFS_FILE_HEADER *)FvFileHandle)->Name), &HobFv2.FirmwareVolume2->FileName)) { + // + // this FILE has been dispatched, it will not be dispatched again. + // + return EFI_SUCCESS; + } + HobFv2.Raw = GET_NEXT_HOB (HobFv2); + } - PeiCoreEntryPoint = (PEI_CORE_ENTRY_POINT) (UINTN) Context1; - PeiCoreParameters = (PEI_CORE_PARAMETERS *)Context2; + // + // Find FvImage in FvFile + // + Status = PeiFfsFindSectionData ( + (CONST EFI_PEI_SERVICES **) PeiServices, + EFI_SECTION_FIRMWARE_VOLUME_IMAGE, + FvFileHandle, + (VOID **)&FvImageHandle + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Collect FvImage Info. + // + Status = PeiFfsGetVolumeInfo (FvImageHandle, &FvImageInfo); + ASSERT_EFI_ERROR (Status); // - // Call PEI Core using new stack + // FvAlignment must be more than 8 bytes required by FvHeader structure. // - PeiCoreEntryPoint ( - PeiCoreParameters->SecCoreData, - PeiCoreParameters->PpiList, - PeiCoreParameters->Data + FvAlignment = 1 << ((FvImageInfo.FvAttributes & EFI_FVB2_ALIGNMENT) >> 16); + if (FvAlignment < 8) { + FvAlignment = 8; + } + // + // Check FvImage + // + if ((UINTN) FvImageInfo.FvStart % FvAlignment != 0) { + FvBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINT32) FvImageInfo.FvSize), FvAlignment); + if (FvBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + CopyMem (FvBuffer, FvImageInfo.FvStart, (UINTN) FvImageInfo.FvSize); + // + // Update FvImageInfo after reload FvImage to new aligned memory + // + PeiFfsGetVolumeInfo ((EFI_PEI_FV_HANDLE) FvBuffer, &FvImageInfo); + } + + // + // Install FvPpi and Build FvHob + // + PiLibInstallFvInfoPpi ( + NULL, + FvImageInfo.FvStart, + (UINT32) FvImageInfo.FvSize, + &(FvImageInfo.FvName), + &(((EFI_FFS_FILE_HEADER*)FvFileHandle)->Name) ); // - // Never returns + // Inform HOB consumer phase, i.e. DXE core, the existance of this FV + // + BuildFvHob ( + (EFI_PHYSICAL_ADDRESS) (UINTN) FvImageInfo.FvStart, + FvImageInfo.FvSize + ); + // + // Makes the encapsulated volume show up in DXE phase to skip processing of + // encapsulated file again. // - ASSERT (FALSE); - CpuDeadLoop (); + BuildFv2Hob ( + (EFI_PHYSICAL_ADDRESS) (UINTN) FvImageInfo.FvStart, + FvImageInfo.FvSize, + &FvImageInfo.FvName, + &(((EFI_FFS_FILE_HEADER *)FvFileHandle)->Name) + ); + + return EFI_SUCCESS; }