blob: 9e748d254fab884098f3503be215f8d13b32a6d7 [file] [log] [blame]
Graeme Russb156ff02011-12-23 15:57:58 +11001/*
2 * (C) Copyright 2008-2011
3 * Graeme Russ, <graeme.russ@gmail.com>
4 *
5 * (C) Copyright 2002
6 * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
7 *
8 * (C) Copyright 2002
9 * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
10 *
11 * (C) Copyright 2002
12 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
13 * Marius Groeger <mgroeger@sysgo.de>
14 *
Wolfgang Denk1a459662013-07-08 09:37:19 +020015 * SPDX-License-Identifier: GPL-2.0+
Graeme Russb156ff02011-12-23 15:57:58 +110016 */
17
18#include <common.h>
Simon Glass6bcb8ad2014-10-15 04:38:36 -060019#include <inttypes.h>
Graeme Russb156ff02011-12-23 15:57:58 +110020#include <asm/u-boot-x86.h>
Graeme Russa1d57b72011-12-23 21:14:22 +110021#include <asm/relocate.h>
Simon Glass86cfb6b2013-03-05 14:39:54 +000022#include <asm/sections.h>
Graeme Russb156ff02011-12-23 15:57:58 +110023#include <elf.h>
24
Simon Glass7282d832013-04-17 16:13:33 +000025DECLARE_GLOBAL_DATA_PTR;
26
Graeme Russa1d57b72011-12-23 21:14:22 +110027int copy_uboot_to_ram(void)
Graeme Russb156ff02011-12-23 15:57:58 +110028{
29 size_t len = (size_t)&__data_end - (size_t)&__text_start;
30
Simon Glass981dca62015-08-04 12:33:44 -060031 if (gd->flags & GD_FLG_SKIP_RELOC)
32 return 0;
Graeme Russb156ff02011-12-23 15:57:58 +110033 memcpy((void *)gd->relocaddr, (void *)&__text_start, len);
34
35 return 0;
36}
37
Graeme Russa1d57b72011-12-23 21:14:22 +110038int clear_bss(void)
Graeme Russb156ff02011-12-23 15:57:58 +110039{
40 ulong dst_addr = (ulong)&__bss_start + gd->reloc_off;
41 size_t len = (size_t)&__bss_end - (size_t)&__bss_start;
42
Simon Glass981dca62015-08-04 12:33:44 -060043 if (gd->flags & GD_FLG_SKIP_RELOC)
44 return 0;
Graeme Russb156ff02011-12-23 15:57:58 +110045 memset((void *)dst_addr, 0x00, len);
46
47 return 0;
48}
49
Simon Glass62f79702013-02-28 19:26:16 +000050/*
51 * This function has more error checking than you might expect. Please see
52 * the commit message for more informaiton.
53 */
Graeme Russa1d57b72011-12-23 21:14:22 +110054int do_elf_reloc_fixups(void)
Graeme Russb156ff02011-12-23 15:57:58 +110055{
56 Elf32_Rel *re_src = (Elf32_Rel *)(&__rel_dyn_start);
57 Elf32_Rel *re_end = (Elf32_Rel *)(&__rel_dyn_end);
58
Simon Glass62f79702013-02-28 19:26:16 +000059 Elf32_Addr *offset_ptr_rom, *last_offset = NULL;
Graeme Russb156ff02011-12-23 15:57:58 +110060 Elf32_Addr *offset_ptr_ram;
61
62 /* The size of the region of u-boot that runs out of RAM. */
63 uintptr_t size = (uintptr_t)&__bss_end - (uintptr_t)&__text_start;
64
Simon Glass981dca62015-08-04 12:33:44 -060065 if (gd->flags & GD_FLG_SKIP_RELOC)
66 return 0;
Simon Glass512e5812014-11-14 18:18:23 -070067 if (re_src == re_end)
68 panic("No relocation data");
69
Graeme Russb156ff02011-12-23 15:57:58 +110070 do {
71 /* Get the location from the relocation entry */
72 offset_ptr_rom = (Elf32_Addr *)re_src->r_offset;
73
74 /* Check that the location of the relocation is in .text */
Simon Glass62f79702013-02-28 19:26:16 +000075 if (offset_ptr_rom >= (Elf32_Addr *)CONFIG_SYS_TEXT_BASE &&
76 offset_ptr_rom > last_offset) {
Graeme Russb156ff02011-12-23 15:57:58 +110077
78 /* Switch to the in-RAM version */
79 offset_ptr_ram = (Elf32_Addr *)((ulong)offset_ptr_rom +
80 gd->reloc_off);
81
82 /* Check that the target points into .text */
83 if (*offset_ptr_ram >= CONFIG_SYS_TEXT_BASE &&
Gabe Black842d3382012-11-03 11:41:25 +000084 *offset_ptr_ram <=
Graeme Russb156ff02011-12-23 15:57:58 +110085 (CONFIG_SYS_TEXT_BASE + size)) {
86 *offset_ptr_ram += gd->reloc_off;
Simon Glass62f79702013-02-28 19:26:16 +000087 } else {
88 debug(" %p: rom reloc %x, ram %p, value %x,"
Simon Glass6bcb8ad2014-10-15 04:38:36 -060089 " limit %" PRIXPTR "\n", re_src,
Simon Glass62f79702013-02-28 19:26:16 +000090 re_src->r_offset, offset_ptr_ram,
91 *offset_ptr_ram,
92 CONFIG_SYS_TEXT_BASE + size);
Graeme Russb156ff02011-12-23 15:57:58 +110093 }
Simon Glass62f79702013-02-28 19:26:16 +000094 } else {
95 debug(" %p: rom reloc %x, last %p\n", re_src,
96 re_src->r_offset, last_offset);
Graeme Russb156ff02011-12-23 15:57:58 +110097 }
Simon Glass62f79702013-02-28 19:26:16 +000098 last_offset = offset_ptr_rom;
99
Duncan Laurie0c392902012-10-23 18:04:43 +0000100 } while (++re_src < re_end);
Graeme Russb156ff02011-12-23 15:57:58 +1100101
102 return 0;
103}