/** ImageRead function that operates on a memory buffer whos base is passed into FileHandle. @param Reloc Ponter to baes of the input stream @param Fixup Offset to the start of the buffer @param FixupData Number of bytes to copy into the buffer @param Adjust Location to place results of read @retval RETURN_SUCCESS Data is read from FileOffset from the Handle into the buffer. **/ RETURN_STATUS GluePeHotRelocateImageEx ( IN UINT16 *Reloc, IN OUT CHAR8 *Fixup, IN OUT CHAR8 **FixupData, IN UINT64 Adjust ) { UINT64 *F64; UINT64 FixupVal; switch ((*Reloc) >> 12) { case EFI_IMAGE_REL_BASED_DIR64: F64 = (UINT64 *) Fixup; *FixupData = ALIGN_POINTER (*FixupData, sizeof (UINT64)); if (*(UINT64 *) (*FixupData) == *F64) { *F64 = *F64 + (UINT64) Adjust; } *FixupData = *FixupData + sizeof (UINT64); break; case EFI_IMAGE_REL_BASED_IA64_IMM64: F64 = (UINT64 *) Fixup; *FixupData = ALIGN_POINTER (*FixupData, sizeof (UINT64)); if (*(UINT64 *) (*FixupData) == *F64) { // // Align it to bundle address before fixing up the // 64-bit immediate value of the movl instruction. // // Fixup = (CHAR8 *) ((UINT64) Fixup & (UINT64)~(15)); FixupVal = (UINT64) 0; // // Extract the lower 32 bits of IMM64 from bundle // EXT_IMM64 ( FixupVal, (UINT32 *) Fixup + IMM64_IMM7B_INST_WORD_X, IMM64_IMM7B_SIZE_X, IMM64_IMM7B_INST_WORD_POS_X, IMM64_IMM7B_VAL_POS_X ); EXT_IMM64 ( FixupVal, (UINT32 *) Fixup + IMM64_IMM9D_INST_WORD_X, IMM64_IMM9D_SIZE_X, IMM64_IMM9D_INST_WORD_POS_X, IMM64_IMM9D_VAL_POS_X ); EXT_IMM64 ( FixupVal, (UINT32 *) Fixup + IMM64_IMM5C_INST_WORD_X, IMM64_IMM5C_SIZE_X, IMM64_IMM5C_INST_WORD_POS_X, IMM64_IMM5C_VAL_POS_X ); EXT_IMM64 ( FixupVal, (UINT32 *) Fixup + IMM64_IC_INST_WORD_X, IMM64_IC_SIZE_X, IMM64_IC_INST_WORD_POS_X, IMM64_IC_VAL_POS_X ); EXT_IMM64 ( FixupVal, (UINT32 *) Fixup + IMM64_IMM41a_INST_WORD_X, IMM64_IMM41a_SIZE_X, IMM64_IMM41a_INST_WORD_POS_X, IMM64_IMM41a_VAL_POS_X ); // // Update 64-bit address // FixupVal += Adjust; // // Insert IMM64 into bundle // INS_IMM64 ( FixupVal, ((UINT32 *) Fixup + IMM64_IMM7B_INST_WORD_X), IMM64_IMM7B_SIZE_X, IMM64_IMM7B_INST_WORD_POS_X, IMM64_IMM7B_VAL_POS_X ); INS_IMM64 ( FixupVal, ((UINT32 *) Fixup + IMM64_IMM9D_INST_WORD_X), IMM64_IMM9D_SIZE_X, IMM64_IMM9D_INST_WORD_POS_X, IMM64_IMM9D_VAL_POS_X ); INS_IMM64 ( FixupVal, ((UINT32 *) Fixup + IMM64_IMM5C_INST_WORD_X), IMM64_IMM5C_SIZE_X, IMM64_IMM5C_INST_WORD_POS_X, IMM64_IMM5C_VAL_POS_X ); INS_IMM64 ( FixupVal, ((UINT32 *) Fixup + IMM64_IC_INST_WORD_X), IMM64_IC_SIZE_X, IMM64_IC_INST_WORD_POS_X, IMM64_IC_VAL_POS_X ); INS_IMM64 ( FixupVal, ((UINT32 *) Fixup + IMM64_IMM41a_INST_WORD_X), IMM64_IMM41a_SIZE_X, IMM64_IMM41a_INST_WORD_POS_X, IMM64_IMM41a_VAL_POS_X ); INS_IMM64 ( FixupVal, ((UINT32 *) Fixup + IMM64_IMM41b_INST_WORD_X), IMM64_IMM41b_SIZE_X, IMM64_IMM41b_INST_WORD_POS_X, IMM64_IMM41b_VAL_POS_X ); INS_IMM64 ( FixupVal, ((UINT32 *) Fixup + IMM64_IMM41c_INST_WORD_X), IMM64_IMM41c_SIZE_X, IMM64_IMM41c_INST_WORD_POS_X, IMM64_IMM41c_VAL_POS_X ); INS_IMM64 ( FixupVal, ((UINT32 *) Fixup + IMM64_SIGN_INST_WORD_X), IMM64_SIGN_SIZE_X, IMM64_SIGN_INST_WORD_POS_X, IMM64_SIGN_VAL_POS_X ); *(UINT64 *) (*FixupData) = *F64; } *FixupData = *FixupData + sizeof (UINT64); break; default: DEBUG ((EFI_D_ERROR, "PeHotRelocateEx:unknown fixed type\n")); return RETURN_UNSUPPORTED; } return RETURN_SUCCESS; }
/** Performs an Itanium-based specific relocation fixup. @param Reloc The pointer to the relocation record. @param Fixup The pointer to the address to fix up. @param FixupData The pointer to a buffer to log the fixups. @param Adjust The offset to adjust the fixup. @retval RETURN_SUCCESS Succeed to fix the relocation entry. @retval RETURN_UNSUPPOTED Unrecoganized relocation entry. **/ RETURN_STATUS PeCoffLoaderRelocateImageEx ( IN UINT16 *Reloc, IN OUT CHAR8 *Fixup, IN OUT CHAR8 **FixupData, IN UINT64 Adjust ) { UINT64 *Fixup64; UINT64 FixupVal; switch ((*Reloc) >> 12) { case EFI_IMAGE_REL_BASED_IA64_IMM64: // // Align it to bundle address before fixing up the // 64-bit immediate value of the movl instruction. // Fixup = (CHAR8 *)((UINTN) Fixup & (UINTN) ~(15)); FixupVal = (UINT64)0; // // Extract the lower 32 bits of IMM64 from bundle // EXT_IMM64(FixupVal, (UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X, IMM64_IMM7B_SIZE_X, IMM64_IMM7B_INST_WORD_POS_X, IMM64_IMM7B_VAL_POS_X ); EXT_IMM64(FixupVal, (UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X, IMM64_IMM9D_SIZE_X, IMM64_IMM9D_INST_WORD_POS_X, IMM64_IMM9D_VAL_POS_X ); EXT_IMM64(FixupVal, (UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X, IMM64_IMM5C_SIZE_X, IMM64_IMM5C_INST_WORD_POS_X, IMM64_IMM5C_VAL_POS_X ); EXT_IMM64(FixupVal, (UINT32 *)Fixup + IMM64_IC_INST_WORD_X, IMM64_IC_SIZE_X, IMM64_IC_INST_WORD_POS_X, IMM64_IC_VAL_POS_X ); EXT_IMM64(FixupVal, (UINT32 *)Fixup + IMM64_IMM41A_INST_WORD_X, IMM64_IMM41A_SIZE_X, IMM64_IMM41A_INST_WORD_POS_X, IMM64_IMM41A_VAL_POS_X ); // // Update 64-bit address // FixupVal += Adjust; // // Insert IMM64 into bundle // INS_IMM64(FixupVal, ((UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X), IMM64_IMM7B_SIZE_X, IMM64_IMM7B_INST_WORD_POS_X, IMM64_IMM7B_VAL_POS_X ); INS_IMM64(FixupVal, ((UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X), IMM64_IMM9D_SIZE_X, IMM64_IMM9D_INST_WORD_POS_X, IMM64_IMM9D_VAL_POS_X ); INS_IMM64(FixupVal, ((UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X), IMM64_IMM5C_SIZE_X, IMM64_IMM5C_INST_WORD_POS_X, IMM64_IMM5C_VAL_POS_X ); INS_IMM64(FixupVal, ((UINT32 *)Fixup + IMM64_IC_INST_WORD_X), IMM64_IC_SIZE_X, IMM64_IC_INST_WORD_POS_X, IMM64_IC_VAL_POS_X ); INS_IMM64(FixupVal, ((UINT32 *)Fixup + IMM64_IMM41A_INST_WORD_X), IMM64_IMM41A_SIZE_X, IMM64_IMM41A_INST_WORD_POS_X, IMM64_IMM41A_VAL_POS_X ); INS_IMM64(FixupVal, ((UINT32 *)Fixup + IMM64_IMM41B_INST_WORD_X), IMM64_IMM41B_SIZE_X, IMM64_IMM41B_INST_WORD_POS_X, IMM64_IMM41B_VAL_POS_X ); INS_IMM64(FixupVal, ((UINT32 *)Fixup + IMM64_IMM41C_INST_WORD_X), IMM64_IMM41C_SIZE_X, IMM64_IMM41C_INST_WORD_POS_X, IMM64_IMM41C_VAL_POS_X ); INS_IMM64(FixupVal, ((UINT32 *)Fixup + IMM64_SIGN_INST_WORD_X), IMM64_SIGN_SIZE_X, IMM64_SIGN_INST_WORD_POS_X, IMM64_SIGN_VAL_POS_X ); Fixup64 = (UINT64 *) Fixup; if (*FixupData != NULL) { *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64)); *(UINT64 *)(*FixupData) = *Fixup64; *FixupData = *FixupData + sizeof(UINT64); } break; default: return RETURN_UNSUPPORTED; } return RETURN_SUCCESS; }
EFI_STATUS PeCoffLoaderRelocateImageEx ( IN UINT16 *Reloc, IN OUT CHAR8 *Fixup, IN OUT CHAR8 **FixupData, IN UINT64 Adjust ) /*++ Routine Description: Performs an Itanium-based specific relocation fixup Arguments: Reloc - Pointer to the relocation record Fixup - Pointer to the address to fix up FixupData - Pointer to a buffer to log the fixups Adjust - The offset to adjust the fixup Returns: Status code --*/ { UINT64 *F64; UINT64 FixupVal; switch ((*Reloc) >> 12) { case EFI_IMAGE_REL_BASED_IA64_IMM64: // // Align it to bundle address before fixing up the // 64-bit immediate value of the movl instruction. // Fixup = (CHAR8 *)((UINTN) Fixup & (UINTN) ~(15)); FixupVal = (UINT64)0; // // Extract the lower 32 bits of IMM64 from bundle // EXT_IMM64(FixupVal, (UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X, IMM64_IMM7B_SIZE_X, IMM64_IMM7B_INST_WORD_POS_X, IMM64_IMM7B_VAL_POS_X ); EXT_IMM64(FixupVal, (UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X, IMM64_IMM9D_SIZE_X, IMM64_IMM9D_INST_WORD_POS_X, IMM64_IMM9D_VAL_POS_X ); EXT_IMM64(FixupVal, (UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X, IMM64_IMM5C_SIZE_X, IMM64_IMM5C_INST_WORD_POS_X, IMM64_IMM5C_VAL_POS_X ); EXT_IMM64(FixupVal, (UINT32 *)Fixup + IMM64_IC_INST_WORD_X, IMM64_IC_SIZE_X, IMM64_IC_INST_WORD_POS_X, IMM64_IC_VAL_POS_X ); EXT_IMM64(FixupVal, (UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X, IMM64_IMM41a_SIZE_X, IMM64_IMM41a_INST_WORD_POS_X, IMM64_IMM41a_VAL_POS_X ); // // Update 64-bit address // FixupVal += Adjust; // // Insert IMM64 into bundle // INS_IMM64(FixupVal, ((UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X), IMM64_IMM7B_SIZE_X, IMM64_IMM7B_INST_WORD_POS_X, IMM64_IMM7B_VAL_POS_X ); INS_IMM64(FixupVal, ((UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X), IMM64_IMM9D_SIZE_X, IMM64_IMM9D_INST_WORD_POS_X, IMM64_IMM9D_VAL_POS_X ); INS_IMM64(FixupVal, ((UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X), IMM64_IMM5C_SIZE_X, IMM64_IMM5C_INST_WORD_POS_X, IMM64_IMM5C_VAL_POS_X ); INS_IMM64(FixupVal, ((UINT32 *)Fixup + IMM64_IC_INST_WORD_X), IMM64_IC_SIZE_X, IMM64_IC_INST_WORD_POS_X, IMM64_IC_VAL_POS_X ); INS_IMM64(FixupVal, ((UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X), IMM64_IMM41a_SIZE_X, IMM64_IMM41a_INST_WORD_POS_X, IMM64_IMM41a_VAL_POS_X ); INS_IMM64(FixupVal, ((UINT32 *)Fixup + IMM64_IMM41b_INST_WORD_X), IMM64_IMM41b_SIZE_X, IMM64_IMM41b_INST_WORD_POS_X, IMM64_IMM41b_VAL_POS_X ); INS_IMM64(FixupVal, ((UINT32 *)Fixup + IMM64_IMM41c_INST_WORD_X), IMM64_IMM41c_SIZE_X, IMM64_IMM41c_INST_WORD_POS_X, IMM64_IMM41c_VAL_POS_X ); INS_IMM64(FixupVal, ((UINT32 *)Fixup + IMM64_SIGN_INST_WORD_X), IMM64_SIGN_SIZE_X, IMM64_SIGN_INST_WORD_POS_X, IMM64_SIGN_VAL_POS_X ); F64 = (UINT64 *) Fixup; if (*FixupData != NULL) { *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64)); *(UINT64 *)(*FixupData) = *F64; *FixupData = *FixupData + sizeof(UINT64); } break; default: return EFI_UNSUPPORTED; } return EFI_SUCCESS; }