]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
b156ff09 GR |
2 | /* |
3 | * (C) Copyright 2008-2011 | |
4 | * Graeme Russ, <[email protected]> | |
5 | * | |
6 | * (C) Copyright 2002 | |
7 | * Daniel Engström, Omicron Ceti AB, <[email protected]> | |
8 | * | |
9 | * (C) Copyright 2002 | |
10 | * Wolfgang Denk, DENX Software Engineering, <[email protected]> | |
11 | * | |
12 | * (C) Copyright 2002 | |
13 | * Sysgo Real-Time Solutions, GmbH <www.elinos.com> | |
14 | * Marius Groeger <[email protected]> | |
b156ff09 GR |
15 | */ |
16 | ||
17 | #include <common.h> | |
e47b2d67 | 18 | #include <relocate.h> |
b156ff09 | 19 | #include <asm/u-boot-x86.h> |
86cfb6bd | 20 | #include <asm/sections.h> |
b156ff09 GR |
21 | #include <elf.h> |
22 | ||
7282d834 SG |
23 | DECLARE_GLOBAL_DATA_PTR; |
24 | ||
a1d57b7a | 25 | int copy_uboot_to_ram(void) |
b156ff09 | 26 | { |
f196bd21 | 27 | size_t len = (uintptr_t)&__data_end - (uintptr_t)&__text_start; |
b156ff09 | 28 | |
981dca69 SG |
29 | if (gd->flags & GD_FLG_SKIP_RELOC) |
30 | return 0; | |
b156ff09 GR |
31 | memcpy((void *)gd->relocaddr, (void *)&__text_start, len); |
32 | ||
33 | return 0; | |
34 | } | |
35 | ||
a1d57b7a | 36 | int clear_bss(void) |
b156ff09 GR |
37 | { |
38 | ulong dst_addr = (ulong)&__bss_start + gd->reloc_off; | |
f196bd21 | 39 | size_t len = (uintptr_t)&__bss_end - (uintptr_t)&__bss_start; |
b156ff09 | 40 | |
981dca69 SG |
41 | if (gd->flags & GD_FLG_SKIP_RELOC) |
42 | return 0; | |
b156ff09 GR |
43 | memset((void *)dst_addr, 0x00, len); |
44 | ||
45 | return 0; | |
46 | } | |
47 | ||
b50b1633 SG |
48 | #if CONFIG_IS_ENABLED(X86_64) |
49 | static void do_elf_reloc_fixups64(unsigned int text_base, uintptr_t size, | |
50 | Elf64_Rela *re_src, Elf64_Rela *re_end) | |
51 | { | |
52 | Elf64_Addr *offset_ptr_rom, *last_offset = NULL; | |
53 | Elf64_Addr *offset_ptr_ram; | |
54 | ||
55 | do { | |
80df194f HS |
56 | unsigned long long type = ELF64_R_TYPE(re_src->r_info); |
57 | ||
58 | if (type != R_X86_64_RELATIVE) { | |
59 | printf("%s: unsupported relocation type 0x%llx " | |
60 | "at %p, ", __func__, type, re_src); | |
61 | printf("offset = 0x%llx\n", re_src->r_offset); | |
62 | continue; | |
63 | } | |
64 | ||
b50b1633 SG |
65 | /* Get the location from the relocation entry */ |
66 | offset_ptr_rom = (Elf64_Addr *)(uintptr_t)re_src->r_offset; | |
67 | ||
68 | /* Check that the location of the relocation is in .text */ | |
69 | if (offset_ptr_rom >= (Elf64_Addr *)(uintptr_t)text_base && | |
70 | offset_ptr_rom > last_offset) { | |
71 | /* Switch to the in-RAM version */ | |
72 | offset_ptr_ram = (Elf64_Addr *)((ulong)offset_ptr_rom + | |
73 | gd->reloc_off); | |
74 | ||
75 | /* Check that the target points into .text */ | |
76 | if (*offset_ptr_ram >= text_base && | |
77 | *offset_ptr_ram <= text_base + size) { | |
78 | *offset_ptr_ram = gd->reloc_off + | |
79 | re_src->r_addend; | |
80 | } else { | |
dee37fc9 | 81 | debug(" %p: %lx: rom reloc %lx, ram %p, value %lx, limit %lX\n", |
b50b1633 SG |
82 | re_src, (ulong)re_src->r_info, |
83 | (ulong)re_src->r_offset, offset_ptr_ram, | |
84 | (ulong)*offset_ptr_ram, text_base + size); | |
85 | } | |
86 | } else { | |
87 | debug(" %p: %lx: rom reloc %lx, last %p\n", re_src, | |
88 | (ulong)re_src->r_info, (ulong)re_src->r_offset, | |
89 | last_offset); | |
90 | } | |
91 | last_offset = offset_ptr_rom; | |
92 | ||
93 | } while (++re_src < re_end); | |
94 | } | |
95 | #else | |
dc7e2133 SG |
96 | static void do_elf_reloc_fixups32(unsigned int text_base, uintptr_t size, |
97 | Elf32_Rel *re_src, Elf32_Rel *re_end) | |
b156ff09 | 98 | { |
62f7970a | 99 | Elf32_Addr *offset_ptr_rom, *last_offset = NULL; |
b156ff09 | 100 | Elf32_Addr *offset_ptr_ram; |
512e581c | 101 | |
b156ff09 | 102 | do { |
80df194f HS |
103 | unsigned int type = ELF32_R_TYPE(re_src->r_info); |
104 | ||
105 | if (type != R_386_RELATIVE) { | |
106 | printf("%s: unsupported relocation type 0x%x " | |
107 | "at %p, ", __func__, type, re_src); | |
108 | printf("offset = 0x%x\n", re_src->r_offset); | |
109 | continue; | |
110 | } | |
111 | ||
b156ff09 | 112 | /* Get the location from the relocation entry */ |
dc7e2133 | 113 | offset_ptr_rom = (Elf32_Addr *)(uintptr_t)re_src->r_offset; |
b156ff09 GR |
114 | |
115 | /* Check that the location of the relocation is in .text */ | |
dc7e2133 | 116 | if (offset_ptr_rom >= (Elf32_Addr *)(uintptr_t)text_base && |
a42bfe02 | 117 | offset_ptr_rom > last_offset) { |
b156ff09 GR |
118 | |
119 | /* Switch to the in-RAM version */ | |
120 | offset_ptr_ram = (Elf32_Addr *)((ulong)offset_ptr_rom + | |
121 | gd->reloc_off); | |
122 | ||
123 | /* Check that the target points into .text */ | |
a42bfe02 SG |
124 | if (*offset_ptr_ram >= text_base && |
125 | *offset_ptr_ram <= text_base + size) { | |
b156ff09 | 126 | *offset_ptr_ram += gd->reloc_off; |
62f7970a | 127 | } else { |
dee37fc9 MY |
128 | debug(" %p: rom reloc %x, ram %p, value %x, limit %lX\n", |
129 | re_src, re_src->r_offset, offset_ptr_ram, | |
130 | *offset_ptr_ram, text_base + size); | |
b156ff09 | 131 | } |
62f7970a SG |
132 | } else { |
133 | debug(" %p: rom reloc %x, last %p\n", re_src, | |
134 | re_src->r_offset, last_offset); | |
b156ff09 | 135 | } |
62f7970a SG |
136 | last_offset = offset_ptr_rom; |
137 | ||
0c392909 | 138 | } while (++re_src < re_end); |
dc7e2133 | 139 | } |
b50b1633 | 140 | #endif |
dc7e2133 SG |
141 | |
142 | /* | |
143 | * This function has more error checking than you might expect. Please see | |
144 | * this commit message for more information: | |
145 | * 62f7970a x86: Add error checking to x86 relocation code | |
146 | */ | |
147 | int do_elf_reloc_fixups(void) | |
148 | { | |
149 | void *re_src = (void *)(&__rel_dyn_start); | |
150 | void *re_end = (void *)(&__rel_dyn_end); | |
151 | uint text_base; | |
152 | ||
153 | /* The size of the region of u-boot that runs out of RAM. */ | |
154 | uintptr_t size = (uintptr_t)&__bss_end - (uintptr_t)&__text_start; | |
155 | ||
156 | if (gd->flags & GD_FLG_SKIP_RELOC) | |
157 | return 0; | |
158 | if (re_src == re_end) | |
159 | panic("No relocation data"); | |
160 | ||
161 | #ifdef CONFIG_SYS_TEXT_BASE | |
162 | text_base = CONFIG_SYS_TEXT_BASE; | |
163 | #else | |
164 | panic("No CONFIG_SYS_TEXT_BASE"); | |
165 | #endif | |
b50b1633 SG |
166 | #if CONFIG_IS_ENABLED(X86_64) |
167 | do_elf_reloc_fixups64(text_base, size, re_src, re_end); | |
168 | #else | |
dc7e2133 | 169 | do_elf_reloc_fixups32(text_base, size, re_src, re_end); |
b50b1633 | 170 | #endif |
b156ff09 GR |
171 | |
172 | return 0; | |
173 | } |