/** Loads a PEIM into memory for subsequent execution. If there are compressed images or images that need to be relocated into memory for performance reasons, this service performs that transformation. @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation @param FileHandle Pointer to the FFS file header of the image. @param ImageAddressArg Pointer to PE/TE image. @param ImageSizeArg Size of PE/TE image. @param EntryPoint Pointer to entry point of specified image file for output. @param AuthenticationState - Pointer to attestation authentication state of image. @retval EFI_SUCCESS Image is successfully loaded. @retval EFI_NOT_FOUND Fail to locate necessary PPI. @retval EFI_UNSUPPORTED Image Machine Type is not supported. @retval EFI_WARN_BUFFER_TOO_SMALL There is not enough heap to allocate the requested size. This will not prevent the XIP image from being invoked. **/ EFI_STATUS PeiLoadImageLoadImage ( IN CONST EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_FILE_HANDLE FileHandle, OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL OUT UINT64 *ImageSizeArg, OPTIONAL OUT EFI_PHYSICAL_ADDRESS *EntryPoint, OUT UINT32 *AuthenticationState ) { EFI_STATUS Status; VOID *Pe32Data; EFI_PHYSICAL_ADDRESS ImageAddress; UINT64 ImageSize; EFI_PHYSICAL_ADDRESS ImageEntryPoint; UINT16 Machine; EFI_SECTION_TYPE SearchType1; EFI_SECTION_TYPE SearchType2; *EntryPoint = 0; ImageSize = 0; *AuthenticationState = 0; if (FeaturePcdGet (PcdPeiCoreImageLoaderSearchTeSectionFirst)) { SearchType1 = EFI_SECTION_TE; SearchType2 = EFI_SECTION_PE32; } else { SearchType1 = EFI_SECTION_PE32; SearchType2 = EFI_SECTION_TE; } // // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst // is true, TE will be searched first). // Status = PeiServicesFfsFindSectionData3 ( SearchType1, 0, FileHandle, &Pe32Data, AuthenticationState ); // // If we didn't find a first exe section, try to find the second exe section. // if (EFI_ERROR (Status)) { Status = PeiServicesFfsFindSectionData3 ( SearchType2, 0, FileHandle, &Pe32Data, AuthenticationState ); if (EFI_ERROR (Status)) { // // PEI core only carry the loader function for TE and PE32 executables // If this two section does not exist, just return. // return Status; } } // // If memory is installed, perform the shadow operations // Status = LoadAndRelocatePeCoffImage ( Pe32Data, &ImageAddress, &ImageSize, &ImageEntryPoint ); ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) { return Status; } // // Got the entry point from the loaded Pe32Data // Pe32Data = (VOID *) ((UINTN) ImageAddress); *EntryPoint = ImageEntryPoint; Machine = PeCoffLoaderGetMachineType (Pe32Data); if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Machine)) { if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Machine)) { return EFI_UNSUPPORTED; } } if (ImageAddressArg != NULL) { *ImageAddressArg = ImageAddress; } if (ImageSizeArg != NULL) { *ImageSizeArg = ImageSize; } DEBUG_CODE_BEGIN (); CHAR8 *AsciiString; CHAR8 EfiFileName[512]; INT32 Index; INT32 StartIndex; // // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi // if (Machine != EFI_IMAGE_MACHINE_IA64) { DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)*EntryPoint)); } else { // // For IPF Image, the real entry point should be print. // DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)(*(UINT64 *)(UINTN)*EntryPoint))); } // // Print Module Name by PeImage PDB file name. // AsciiString = PeCoffLoaderGetPdbPointer (Pe32Data); if (AsciiString != NULL) { StartIndex = 0; for (Index = 0; AsciiString[Index] != 0; Index++) { if (AsciiString[Index] == '\\' || AsciiString[Index] == '/') { StartIndex = Index + 1; } } // // Copy the PDB file name to our temporary string, and replace .pdb with .efi // The PDB file name is limited in the range of 0~511. // If the length is bigger than 511, trim the redudant characters to avoid overflow in array boundary. // for (Index = 0; Index < sizeof (EfiFileName) - 4; Index++) { EfiFileName[Index] = AsciiString[Index + StartIndex]; if (EfiFileName[Index] == 0) { EfiFileName[Index] = '.'; } if (EfiFileName[Index] == '.') { EfiFileName[Index + 1] = 'e'; EfiFileName[Index + 2] = 'f'; EfiFileName[Index + 3] = 'i'; EfiFileName[Index + 4] = 0; break; } } if (Index == sizeof (EfiFileName) - 4) { EfiFileName[Index] = 0; } DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a", EfiFileName)); } DEBUG_CODE_END (); DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n")); return EFI_SUCCESS; }
/** Loads a PEIM into memory for subsequent execution. If there are compressed images or images that need to be relocated into memory for performance reasons, this service performs that transformation. @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation @param FileHandle Pointer to the FFS file header of the image. @param ImageAddressArg Pointer to PE/TE image. @param ImageSizeArg Size of PE/TE image. @param EntryPoint Pointer to entry point of specified image file for output. @param AuthenticationState - Pointer to attestation authentication state of image. @retval EFI_SUCCESS Image is successfully loaded. @retval EFI_NOT_FOUND Fail to locate necessary PPI. @retval EFI_UNSUPPORTED Image Machine Type is not supported. **/ EFI_STATUS PeiLoadImageLoadImage ( IN CONST EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_FILE_HANDLE FileHandle, OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg, OPTIONAL OUT UINT64 *ImageSizeArg, OPTIONAL OUT EFI_PHYSICAL_ADDRESS *EntryPoint, OUT UINT32 *AuthenticationState ) { EFI_STATUS Status; VOID *Pe32Data; EFI_PHYSICAL_ADDRESS ImageAddress; UINT64 ImageSize; EFI_PHYSICAL_ADDRESS ImageEntryPoint; UINT16 Machine; EFI_SECTION_TYPE SearchType1; EFI_SECTION_TYPE SearchType2; *EntryPoint = 0; ImageSize = 0; *AuthenticationState = 0; if (FeaturePcdGet (PcdPeiCoreImageLoaderSearchTeSectionFirst)) { SearchType1 = EFI_SECTION_TE; SearchType2 = EFI_SECTION_PE32; } else { SearchType1 = EFI_SECTION_PE32; SearchType2 = EFI_SECTION_TE; } // // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst // is true, TE will be searched first). // Status = PeiServicesFfsFindSectionData ( SearchType1, FileHandle, &Pe32Data ); // // If we didn't find a first exe section, try to find the second exe section. // if (EFI_ERROR (Status)) { Status = PeiServicesFfsFindSectionData ( SearchType2, FileHandle, &Pe32Data ); if (EFI_ERROR (Status)) { // // PEI core only carry the loader function fro TE and PE32 executables // If this two section does not exist, just return. // return Status; } } // // If memory is installed, perform the shadow operations // Status = LoadAndRelocatePeCoffImage ( Pe32Data, &ImageAddress, &ImageSize, &ImageEntryPoint ); ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) { return Status; } // // Got the entry point from the loaded Pe32Data // Pe32Data = (VOID *) ((UINTN) ImageAddress); *EntryPoint = ImageEntryPoint; Machine = PeCoffLoaderGetMachineType (Pe32Data); if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Machine)) { if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Machine)) { return EFI_UNSUPPORTED; } } if (ImageAddressArg != NULL) { *ImageAddressArg = ImageAddress; } if (ImageSizeArg != NULL) { *ImageSizeArg = ImageSize; } DEBUG_CODE_BEGIN (); CHAR8 *AsciiString; CHAR8 AsciiBuffer[512]; INT32 Index; INT32 Index1; // // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi // if (Machine != EFI_IMAGE_MACHINE_IA64) { DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)*EntryPoint)); } else { // // For IPF Image, the real entry point should be print. // DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)(*(UINT64 *)(UINTN)*EntryPoint))); } // // Print Module Name by PeImage PDB file name. // AsciiString = PeCoffLoaderGetPdbPointer (Pe32Data); if (AsciiString != NULL) { for (Index = (INT32) AsciiStrLen (AsciiString) - 1; Index >= 0; Index --) { if (AsciiString[Index] == '\\') { break; } } if (Index != 0) { for (Index1 = 0; AsciiString[Index + 1 + Index1] != '.'; Index1 ++) { AsciiBuffer [Index1] = AsciiString[Index + 1 + Index1]; } AsciiBuffer [Index1] = '\0'; DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a.efi", AsciiBuffer)); } } DEBUG_CODE_END (); DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n")); return EFI_SUCCESS; }