Rename CONFIG_SYS_TEXT_BASE to CONFIG_TEXT_BASE
[pandora-u-boot.git] / arch / microblaze / cpu / relocate.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * (C) Copyright 2022 Advanced Micro Devices, Inc
4  * Michal Simek <michal.simek@amd.com>
5  */
6
7 #include <common.h>
8 #include <elf.h>
9
10 #define R_MICROBLAZE_NONE       0
11 #define R_MICROBLAZE_32         1
12 #define R_MICROBLAZE_REL        16
13 #define R_MICROBLAZE_GLOB_DAT   18
14
15 /**
16  * mb_fix_rela - update relocation to new address
17  * @reloc_addr: new relocation address
18  * @verbose: enable version messages
19  * @rela_start: rela section start
20  * @rela_end: rela section end
21  * @dyn_start: dynamic section start
22  * @origin_addr: address where u-boot starts(doesn't need to be CONFIG_TEXT_BASE)
23  */
24 void mb_fix_rela(u32 reloc_addr, u32 verbose, u32 rela_start,
25                  u32 rela_end, u32 dyn_start, u32 origin_addr)
26 {
27         u32 num, type, mask, i, reloc_off;
28
29         /*
30          * Return in case u-boot.elf is used directly.
31          * Skip it when u-boot.bin is loaded to different address than
32          * CONFIG_TEXT_BASE. In this case relocation is necessary to run.
33          */
34         if (reloc_addr == CONFIG_TEXT_BASE) {
35                 debug_cond(verbose,
36                            "Relocation address is the same - skip relocation\n");
37                 return;
38         }
39
40         reloc_off = reloc_addr - origin_addr;
41
42         debug_cond(verbose, "Relocation address:\t0x%08x\n", reloc_addr);
43         debug_cond(verbose, "Relocation offset:\t0x%08x\n", reloc_off);
44         debug_cond(verbose, "Origin address:\t0x%08x\n", origin_addr);
45         debug_cond(verbose, "Rela start:\t0x%08x\n", rela_start);
46         debug_cond(verbose, "Rela end:\t0x%08x\n", rela_end);
47         debug_cond(verbose, "Dynsym start:\t0x%08x\n", dyn_start);
48
49         num = (rela_end - rela_start) / sizeof(Elf32_Rela);
50
51         debug_cond(verbose, "Number of entries:\t%u\n", num);
52
53         for (i = 0; i < num; i++) {
54                 Elf32_Rela *rela;
55                 u32 temp;
56
57                 rela = (Elf32_Rela *)(rela_start + sizeof(Elf32_Rela) * i);
58
59                 mask = 0xffULL; /* would be different on 32-bit */
60                 type = rela->r_info & mask;
61
62                 debug_cond(verbose, "\nRela possition:\t%d/0x%x\n",
63                            i, (u32)rela);
64
65                 switch (type) {
66                 case R_MICROBLAZE_REL:
67                         temp = *(u32 *)rela->r_offset;
68
69                         debug_cond(verbose, "Type:\tREL\n");
70                         debug_cond(verbose, "Rela r_offset:\t\t0x%x\n", rela->r_offset);
71                         debug_cond(verbose, "Rela r_info:\t\t0x%x\n", rela->r_info);
72                         debug_cond(verbose, "Rela r_addend:\t\t0x%x\n", rela->r_addend);
73                         debug_cond(verbose, "Value at r_offset:\t0x%x\n", temp);
74
75                         rela->r_offset += reloc_off;
76                         rela->r_addend += reloc_off;
77
78                         temp = *(u32 *)rela->r_offset;
79                         temp += reloc_off;
80                         *(u32 *)rela->r_offset = temp;
81
82                         debug_cond(verbose, "New:Rela r_offset:\t0x%x\n", rela->r_offset);
83                         debug_cond(verbose, "New:Rela r_addend:\t0x%x\n", rela->r_addend);
84                         debug_cond(verbose, "New:Value at r_offset:\t0x%x\n", temp);
85                         break;
86                 case R_MICROBLAZE_32:
87                 case R_MICROBLAZE_GLOB_DAT:
88                         debug_cond(verbose, "Type:\t(32/GLOB) %u\n", type);
89                         debug_cond(verbose, "Rela r_offset:\t\t0x%x\n", rela->r_offset);
90                         debug_cond(verbose, "Rela r_info:\t\t0x%x\n", rela->r_info);
91                         debug_cond(verbose, "Rela r_addend:\t\t0x%x\n", rela->r_addend);
92                         debug_cond(verbose, "Value at r_offset:\t0x%x\n", temp);
93
94                         rela->r_offset += reloc_off;
95
96                         temp = *(u32 *)rela->r_offset;
97                         temp += reloc_off;
98                         *(u32 *)rela->r_offset = temp;
99
100                         debug_cond(verbose, "New:Rela r_offset:\t0x%x\n", rela->r_offset);
101                         debug_cond(verbose, "New:Value at r_offset:\t0x%x\n", temp);
102                         break;
103                 case R_MICROBLAZE_NONE:
104                         debug_cond(verbose, "R_MICROBLAZE_NONE - skip\n");
105                         break;
106                 default:
107                         debug_cond(verbose, "warning: unsupported relocation type %d at %x\n",
108                                    type, rela->r_offset);
109                 }
110         }
111 }