/** Main entry point to last PEIM. This function finds DXE Core in the firmware volume and transfer the control to DXE core. @param This Entry point for DXE IPL PPI. @param PeiServices General purpose services available to every PEIM. @param HobList Address to the Pei HOB list. @return EFI_SUCCESS DXE core was successfully loaded. @return EFI_OUT_OF_RESOURCES There are not enough resources to load DXE core. **/ EFI_STATUS EFIAPI DxeLoadCore ( IN CONST EFI_DXE_IPL_PPI *This, IN EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_HOB_POINTERS HobList ) { EFI_STATUS Status; EFI_FV_FILE_INFO DxeCoreFileInfo; EFI_PHYSICAL_ADDRESS DxeCoreAddress; UINT64 DxeCoreSize; EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint; EFI_BOOT_MODE BootMode; EFI_PEI_FILE_HANDLE FileHandle; EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable; EFI_PEI_LOAD_FILE_PPI *LoadFile; UINTN Instance; UINT32 AuthenticationState; UINTN DataSize; EFI_PEI_S3_RESUME2_PPI *S3Resume; EFI_PEI_RECOVERY_MODULE_PPI *PeiRecovery; EFI_MEMORY_TYPE_INFORMATION MemoryData[EfiMaxMemoryType + 1]; // // if in S3 Resume, restore configure // BootMode = GetBootModeHob (); if (BootMode == BOOT_ON_S3_RESUME) { Status = PeiServicesLocatePpi ( &gEfiPeiS3Resume2PpiGuid, 0, NULL, (VOID **) &S3Resume ); if (EFI_ERROR (Status)) { // // Report Status code that S3Resume PPI can not be found // REPORT_STATUS_CODE ( EFI_ERROR_CODE | EFI_ERROR_MAJOR, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_S3_RESUME_PPI_NOT_FOUND) ); } ASSERT_EFI_ERROR (Status); Status = S3Resume->S3RestoreConfig2 (S3Resume); ASSERT_EFI_ERROR (Status); } else if (BootMode == BOOT_IN_RECOVERY_MODE) { REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_RECOVERY_BEGIN)); Status = PeiServicesLocatePpi ( &gEfiPeiRecoveryModulePpiGuid, 0, NULL, (VOID **) &PeiRecovery ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Locate Recovery PPI Failed.(Status = %r)\n", Status)); // // Report Status code the failure of locating Recovery PPI // REPORT_STATUS_CODE ( EFI_ERROR_CODE | EFI_ERROR_MAJOR, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_RECOVERY_PPI_NOT_FOUND) ); CpuDeadLoop (); } REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_CAPSULE_LOAD)); Status = PeiRecovery->LoadRecoveryCapsule (PeiServices, PeiRecovery); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Load Recovery Capsule Failed.(Status = %r)\n", Status)); // // Report Status code that recovery image can not be found // REPORT_STATUS_CODE ( EFI_ERROR_CODE | EFI_ERROR_MAJOR, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_NO_RECOVERY_CAPSULE) ); CpuDeadLoop (); } REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_CAPSULE_START)); // // Now should have a HOB with the DXE core // } if (GetFirstGuidHob ((CONST EFI_GUID *)&gEfiMemoryTypeInformationGuid) == NULL) { // // Don't build GuidHob if GuidHob has been installed. // Status = PeiServicesLocatePpi ( &gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (VOID **)&Variable ); if (!EFI_ERROR (Status)) { DataSize = sizeof (MemoryData); Status = Variable->GetVariable ( Variable, EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME, &gEfiMemoryTypeInformationGuid, NULL, &DataSize, &MemoryData ); if (!EFI_ERROR (Status) && ValidateMemoryTypeInfoVariable(MemoryData, DataSize)) { // // Build the GUID'd HOB for DXE // BuildGuidDataHob ( &gEfiMemoryTypeInformationGuid, MemoryData, DataSize ); } } } // // Look in all the FVs present in PEI and find the DXE Core FileHandle // FileHandle = DxeIplFindDxeCore (); // // Load the DXE Core from a Firmware Volume. // Instance = 0; do { Status = PeiServicesLocatePpi (&gEfiPeiLoadFilePpiGuid, Instance++, NULL, (VOID **) &LoadFile); // // These must exist an instance of EFI_PEI_LOAD_FILE_PPI to support to load DxeCore file handle successfully. // ASSERT_EFI_ERROR (Status); Status = LoadFile->LoadFile ( LoadFile, FileHandle, &DxeCoreAddress, &DxeCoreSize, &DxeCoreEntryPoint, &AuthenticationState ); } while (EFI_ERROR (Status)); // // Get the DxeCore File Info from the FileHandle for the DxeCore GUID file name. // Status = PeiServicesFfsGetFileInfo (FileHandle, &DxeCoreFileInfo); ASSERT_EFI_ERROR (Status); // // Add HOB for the DXE Core // BuildModuleHob ( &DxeCoreFileInfo.FileName, DxeCoreAddress, ALIGN_VALUE (DxeCoreSize, EFI_PAGE_SIZE), DxeCoreEntryPoint ); // // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT // REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_CORE | EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT)); DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading DXE CORE at 0x%11p EntryPoint=0x%11p\n", (VOID *)(UINTN)DxeCoreAddress, FUNCTION_ENTRY_POINT (DxeCoreEntryPoint))); // // Transfer control to the DXE Core // The hand off state is simply a pointer to the HOB list // HandOffToDxeCore (DxeCoreEntryPoint, HobList); // // If we get here, then the DXE Core returned. This is an error // DxeCore should not return. // ASSERT (FALSE); CpuDeadLoop (); return EFI_OUT_OF_RESOURCES; }
EFI_STATUS EFIAPI LoadDxeCoreFromFfsFile ( IN EFI_PEI_FILE_HANDLE FileHandle, IN UINTN StackSize ) { EFI_STATUS Status; VOID *PeCoffImage; EFI_PHYSICAL_ADDRESS ImageAddress; UINT64 ImageSize; EFI_PHYSICAL_ADDRESS EntryPoint; VOID *BaseOfStack; VOID *TopOfStack; VOID *Hob; EFI_FV_FILE_INFO FvFileInfo; Status = FfsFindSectionData (EFI_SECTION_PE32, FileHandle, &PeCoffImage); if (EFI_ERROR (Status)) { return Status; } Status = LoadPeCoffImage (PeCoffImage, &ImageAddress, &ImageSize, &EntryPoint); // For NT32 Debug Status = SecWinNtPeiLoadFile (PeCoffImage, &ImageAddress, &ImageSize, &EntryPoint); ASSERT_EFI_ERROR (Status); // // Extract the DxeCore GUID file name. // Status = FfsGetFileInfo (FileHandle, &FvFileInfo); ASSERT_EFI_ERROR (Status); BuildModuleHob (&FvFileInfo.FileName, (EFI_PHYSICAL_ADDRESS)(UINTN)ImageAddress, EFI_SIZE_TO_PAGES ((UINT32) ImageSize) * EFI_PAGE_SIZE, EntryPoint); DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading DxeCore at 0x%10p EntryPoint=0x%10p\n", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)EntryPoint)); Hob = GetHobList (); if (StackSize == 0) { // User the current stack ((DXE_CORE_ENTRY_POINT)(UINTN)EntryPoint) (Hob); } else { // // Allocate 128KB for the Stack // BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (StackSize)); ASSERT (BaseOfStack != NULL); // // Compute the top of the stack we were allocated. Pre-allocate a UINTN // for safety. // TopOfStack = (VOID *) ((UINTN) BaseOfStack + EFI_SIZE_TO_PAGES (StackSize) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT); TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT); // // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore. // UpdateStackHob ((EFI_PHYSICAL_ADDRESS)(UINTN) BaseOfStack, StackSize); SwitchStack ( (SWITCH_STACK_ENTRY_POINT)(UINTN)EntryPoint, Hob, NULL, TopOfStack ); } // Should never get here as DXE Core does not return DEBUG ((EFI_D_ERROR, "DxeCore returned\n")); ASSERT (FALSE); return EFI_DEVICE_ERROR; }