77
88#include " pe.h"
99
10- namespace {
11-
12- constexpr size_t BIT26 = 1 << 26 ;
13- constexpr size_t BIT11 = 1 << 11 ;
14- constexpr size_t BIT10 = 1 << 10 ;
15-
16- /* *
17- Pass in a pointer to an ARM MOVT or MOVW immediate instruciton and
18- return the immediate data encoded in the instruction.
19-
20- @param Instruction Pointer to ARM MOVT or MOVW immediate instruction
21-
22- @return Immediate address encoded in the instruction
23-
24- **/
25- uint16_t ThumbMovtImmediateAddress (const uint16_t *Instruction) {
26- uint32_t Movt{};
27- uint16_t Address{};
28-
29- // Thumb2 is two 16-bit instructions working together. Not a single 32-bit
30- // instruction Example MOVT R0, #0 is 0x0000f2c0 or 0xf2c0 0x0000
31- Movt = (*Instruction << 16 ) | (*(Instruction + 1 ));
32-
33- // imm16 = imm4:i:imm3:imm8
34- // imm4 -> Bit19:Bit16
35- // i -> Bit26
36- // imm3 -> Bit14:Bit12
37- // imm8 -> Bit7:Bit0
38- Address = static_cast <uint16_t >(Movt & 0x000000ff ); // imm8
39- Address |= static_cast <uint16_t >((Movt >> 4 ) & 0x0000f700 ); // imm4 imm3
40- Address |= (((Movt & BIT26) != 0 ) ? BIT11 : 0 ); // i
41- return Address;
42- }
43-
44- /* *
45- Pass in a pointer to an ARM MOVW/MOVT instruciton pair and
46- return the immediate data encoded in the two` instruction.
47-
48- @param Instructions Pointer to ARM MOVW/MOVT insturction pair
49-
50- @return Immediate address encoded in the instructions
51-
52- **/
53- uint32_t ThumbMovwMovtImmediateAddress (uint16_t *Instructions) {
54- uint16_t *Word{};
55- uint16_t *Top{};
56-
57- Word = Instructions; // MOVW
58- Top = Word + 2 ; // MOVT
59-
60- return (ThumbMovtImmediateAddress (Top) << 16 ) +
61- ThumbMovtImmediateAddress (Word);
62- }
63-
64- /* *
65- Update an ARM MOVT or MOVW immediate instruction immediate data.
66-
67- @param Instruction Pointer to ARM MOVT or MOVW immediate instruction
68- @param Address New addres to patch into the instruction
69- **/
70- void ThumbMovtImmediatePatch (uint16_t *Instruction, uint16_t Address) {
71- uint16_t Patch{};
72-
73- // First 16-bit chunk of instruciton
74- Patch = ((Address >> 12 ) & 0x000f ); // imm4
75- Patch |= (((Address & BIT11) != 0 ) ? BIT10 : 0 ); // i
76- // Mask out instruction bits and or in address
77- *(Instruction) = (*Instruction & ~0x040f ) | Patch;
78-
79- // Second 16-bit chunk of instruction
80- Patch = Address & 0x000000ff ; // imm8
81- Patch |= ((Address << 4 ) & 0x00007000 ); // imm3
82- // Mask out instruction bits and or in address
83- Instruction++;
84- *Instruction = (*Instruction & ~0x70ff ) | Patch;
85- }
86-
87- /* *
88- Update an ARM MOVW/MOVT immediate instruction instruction pair.
89-
90- @param Instructions Pointer to ARM MOVW/MOVT instruction pair
91- @param Address New addres to patch into the instructions
92- **/
93- void ThumbMovwMovtImmediatePatch (uint16_t *Instructions, uint32_t Address) {
94- uint16_t *Word{};
95- uint16_t *Top{};
96-
97- Word = Instructions; // MOVW
98- Top = Word + 2 ; // MOVT
99-
100- ThumbMovtImmediatePatch (Word, static_cast <uint16_t >(Address & 0xffff ));
101- ThumbMovtImmediatePatch (Top, static_cast <uint16_t >(Address >> 16 ));
102- }
103-
104- } // namespace
105-
10610int relocate_image (char *image) {
10711 const auto dos_header = reinterpret_cast <IMAGE_DOS_HEADER *>(image);
10812 const auto pe_header = dos_header->GetPEHeader ();
@@ -141,7 +45,6 @@ int relocate_image(char *image) {
14145 auto Fixup16 = reinterpret_cast <uint16_t *>(Fixup);
14246 auto Fixup32 = reinterpret_cast <uint32_t *>(Fixup);
14347 auto Fixup64 = reinterpret_cast <uint64_t *>(Fixup);
144- uint32_t FixupVal = 0 ;
14548 switch ((*Reloc) >> 12 ) {
14649 case EFI_IMAGE_REL_BASED_ABSOLUTE:
14750 break ;
@@ -167,18 +70,32 @@ int relocate_image(char *image) {
16770 *Fixup64 = *Fixup64 + static_cast <uint64_t >(Adjust);
16871 break ;
16972
170- case EFI_IMAGE_REL_BASED_ARM_MOV32T:
171- FixupVal = ThumbMovwMovtImmediateAddress (Fixup16) +
172- static_cast <uint32_t >(Adjust);
173- ThumbMovwMovtImmediatePatch (Fixup16, FixupVal);
174-
175- break ;
176-
17773 case EFI_IMAGE_REL_BASED_ARM_MOV32A:
17874 printf (" Unsupported relocation type: EFI_IMAGE_REL_BASED_ARM_MOV32A\n " );
17975 // break omitted - ARM instruction encoding not implemented
18076 break ;
181-
77+ case EFI_IMAGE_REL_BASED_LOONGARCH64_MARK_LA: {
78+ // The next four instructions are used to load a 64 bit address,
79+ // relocate all of them
80+ uint64_t Value =
81+ (*Fixup32 & 0x1ffffe0 ) << 7 | // lu12i.w 20bits from bit5
82+ (*(Fixup32 + 1 ) & 0x3ffc00 ) >> 10 ; // ori 12bits from bit10
83+ uint64_t Tmp1 = *(Fixup32 + 2 ) & 0x1ffffe0 ; // lu32i.d 20bits from bit5
84+ uint64_t Tmp2 = *(Fixup32 + 3 ) & 0x3ffc00 ; // lu52i.d 12bits from bit10
85+ Value = Value | (Tmp1 << 27 ) | (Tmp2 << 42 );
86+ Value += Adjust;
87+
88+ *Fixup32 = (*Fixup32 & ~0x1ffffe0 ) | (((Value >> 12 ) & 0xfffff ) << 5 );
89+
90+ Fixup += sizeof (uint32_t );
91+ *Fixup32 = (*Fixup32 & ~0x3ffc00 ) | ((Value & 0xfff ) << 10 );
92+
93+ Fixup += sizeof (uint32_t );
94+ *Fixup32 = (*Fixup32 & ~0x1ffffe0 ) | (((Value >> 32 ) & 0xfffff ) << 5 );
95+
96+ Fixup += sizeof (uint32_t );
97+ *Fixup32 = (*Fixup32 & ~0x3ffc00 ) | (((Value >> 52 ) & 0xfff ) << 10 );
98+ }
18299 default :
183100 printf (" Unsupported relocation type: %d\n " , (*Reloc) >> 12 );
184101 return -1 ;
0 commit comments