]> git.sur5r.net Git - u-boot/blob - arch/x86/lib/relocate.c
x86: use EFI calling convention for efi_main on x86_64
[u-boot] / arch / x86 / lib / relocate.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2008-2011
4  * Graeme Russ, <graeme.russ@gmail.com>
5  *
6  * (C) Copyright 2002
7  * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
8  *
9  * (C) Copyright 2002
10  * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
11  *
12  * (C) Copyright 2002
13  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
14  * Marius Groeger <mgroeger@sysgo.de>
15  */
16
17 #include <common.h>
18 #include <inttypes.h>
19 #include <relocate.h>
20 #include <asm/u-boot-x86.h>
21 #include <asm/sections.h>
22 #include <elf.h>
23
24 DECLARE_GLOBAL_DATA_PTR;
25
26 int copy_uboot_to_ram(void)
27 {
28         size_t len = (uintptr_t)&__data_end - (uintptr_t)&__text_start;
29
30         if (gd->flags & GD_FLG_SKIP_RELOC)
31                 return 0;
32         memcpy((void *)gd->relocaddr, (void *)&__text_start, len);
33
34         return 0;
35 }
36
37 int clear_bss(void)
38 {
39         ulong dst_addr = (ulong)&__bss_start + gd->reloc_off;
40         size_t len = (uintptr_t)&__bss_end - (uintptr_t)&__bss_start;
41
42         if (gd->flags & GD_FLG_SKIP_RELOC)
43                 return 0;
44         memset((void *)dst_addr, 0x00, len);
45
46         return 0;
47 }
48
49 #if CONFIG_IS_ENABLED(X86_64)
50 static void do_elf_reloc_fixups64(unsigned int text_base, uintptr_t size,
51                                   Elf64_Rela *re_src, Elf64_Rela *re_end)
52 {
53         Elf64_Addr *offset_ptr_rom, *last_offset = NULL;
54         Elf64_Addr *offset_ptr_ram;
55
56         do {
57                 /* Get the location from the relocation entry */
58                 offset_ptr_rom = (Elf64_Addr *)(uintptr_t)re_src->r_offset;
59
60                 /* Check that the location of the relocation is in .text */
61                 if (offset_ptr_rom >= (Elf64_Addr *)(uintptr_t)text_base &&
62                     offset_ptr_rom > last_offset) {
63                         /* Switch to the in-RAM version */
64                         offset_ptr_ram = (Elf64_Addr *)((ulong)offset_ptr_rom +
65                                                         gd->reloc_off);
66
67                         /* Check that the target points into .text */
68                         if (*offset_ptr_ram >= text_base &&
69                             *offset_ptr_ram <= text_base + size) {
70                                 *offset_ptr_ram = gd->reloc_off +
71                                                         re_src->r_addend;
72                         } else {
73                                 debug("   %p: %lx: rom reloc %lx, ram %p, value %lx, limit %"
74                                       PRIXPTR "\n",
75                                       re_src, (ulong)re_src->r_info,
76                                       (ulong)re_src->r_offset, offset_ptr_ram,
77                                       (ulong)*offset_ptr_ram, text_base + size);
78                         }
79                 } else {
80                         debug("   %p: %lx: rom reloc %lx, last %p\n", re_src,
81                               (ulong)re_src->r_info, (ulong)re_src->r_offset,
82                               last_offset);
83                 }
84                 last_offset = offset_ptr_rom;
85
86         } while (++re_src < re_end);
87 }
88 #else
89 static void do_elf_reloc_fixups32(unsigned int text_base, uintptr_t size,
90                                   Elf32_Rel *re_src, Elf32_Rel *re_end)
91 {
92         Elf32_Addr *offset_ptr_rom, *last_offset = NULL;
93         Elf32_Addr *offset_ptr_ram;
94
95         do {
96                 /* Get the location from the relocation entry */
97                 offset_ptr_rom = (Elf32_Addr *)(uintptr_t)re_src->r_offset;
98
99                 /* Check that the location of the relocation is in .text */
100                 if (offset_ptr_rom >= (Elf32_Addr *)(uintptr_t)text_base &&
101                     offset_ptr_rom > last_offset) {
102
103                         /* Switch to the in-RAM version */
104                         offset_ptr_ram = (Elf32_Addr *)((ulong)offset_ptr_rom +
105                                                         gd->reloc_off);
106
107                         /* Check that the target points into .text */
108                         if (*offset_ptr_ram >= text_base &&
109                             *offset_ptr_ram <= text_base + size) {
110                                 *offset_ptr_ram += gd->reloc_off;
111                         } else {
112                                 debug("   %p: rom reloc %x, ram %p, value %x,"
113                                         " limit %" PRIXPTR "\n", re_src,
114                                         re_src->r_offset, offset_ptr_ram,
115                                         *offset_ptr_ram,
116                                         text_base + size);
117                         }
118                 } else {
119                         debug("   %p: rom reloc %x, last %p\n", re_src,
120                                re_src->r_offset, last_offset);
121                 }
122                 last_offset = offset_ptr_rom;
123
124         } while (++re_src < re_end);
125 }
126 #endif
127
128 /*
129  * This function has more error checking than you might expect. Please see
130  * this commit message for more information:
131  *    62f7970a x86: Add error checking to x86 relocation code
132  */
133 int do_elf_reloc_fixups(void)
134 {
135         void *re_src = (void *)(&__rel_dyn_start);
136         void *re_end = (void *)(&__rel_dyn_end);
137         uint text_base;
138
139         /* The size of the region of u-boot that runs out of RAM. */
140         uintptr_t size = (uintptr_t)&__bss_end - (uintptr_t)&__text_start;
141
142         if (gd->flags & GD_FLG_SKIP_RELOC)
143                 return 0;
144         if (re_src == re_end)
145                 panic("No relocation data");
146
147 #ifdef CONFIG_SYS_TEXT_BASE
148         text_base = CONFIG_SYS_TEXT_BASE;
149 #else
150         panic("No CONFIG_SYS_TEXT_BASE");
151 #endif
152 #if CONFIG_IS_ENABLED(X86_64)
153         do_elf_reloc_fixups64(text_base, size, re_src, re_end);
154 #else
155         do_elf_reloc_fixups32(text_base, size, re_src, re_end);
156 #endif
157
158         return 0;
159 }