]>
Commit | Line | Data |
---|---|---|
22723828 AB |
1 | /* |
2 | * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. | |
3 | * | |
4 | * SPDX-License-Identifier: GPL-2.0+ | |
5 | */ | |
6 | ||
7 | #include <common.h> | |
8 | #include <elf.h> | |
9 | #include <asm/sections.h> | |
10 | ||
11 | DECLARE_GLOBAL_DATA_PTR; | |
12 | ||
13 | /* | |
14 | * Base functionality is taken from x86 version with added ARC-specifics | |
15 | */ | |
16 | int do_elf_reloc_fixups(void) | |
17 | { | |
18 | Elf32_Rela *re_src = (Elf32_Rela *)(&__rel_dyn_start); | |
19 | Elf32_Rela *re_end = (Elf32_Rela *)(&__rel_dyn_end); | |
20 | ||
21 | Elf32_Addr *offset_ptr_rom, *last_offset = NULL; | |
22 | Elf32_Addr *offset_ptr_ram; | |
23 | ||
24 | do { | |
25 | /* Get the location from the relocation entry */ | |
26 | offset_ptr_rom = (Elf32_Addr *)re_src->r_offset; | |
27 | ||
28 | /* Check that the location of the relocation is in .text */ | |
29 | if (offset_ptr_rom >= (Elf32_Addr *)CONFIG_SYS_TEXT_BASE && | |
30 | offset_ptr_rom > last_offset) { | |
31 | unsigned int val; | |
32 | /* Switch to the in-RAM version */ | |
33 | offset_ptr_ram = (Elf32_Addr *)((ulong)offset_ptr_rom + | |
34 | gd->reloc_off); | |
35 | ||
36 | /* | |
37 | * Use "memcpy" because target location might be | |
38 | * 16-bit aligned on ARC so we may need to read | |
39 | * byte-by-byte. On attempt to read entire word by | |
40 | * CPU throws an exception | |
41 | */ | |
42 | memcpy(&val, offset_ptr_ram, sizeof(int)); | |
43 | ||
44 | /* If location in ".text" section swap value */ | |
45 | if ((unsigned int)offset_ptr_rom < | |
46 | (unsigned int)&__text_end) | |
47 | val = (val << 16) | (val >> 16); | |
48 | ||
49 | /* Check that the target points into .text */ | |
50 | if (val >= CONFIG_SYS_TEXT_BASE && val <= | |
51 | (unsigned int)&__bss_end) { | |
52 | val += gd->reloc_off; | |
53 | /* If location in ".text" section swap value */ | |
54 | if ((unsigned int)offset_ptr_rom < | |
55 | (unsigned int)&__text_end) | |
56 | val = (val << 16) | (val >> 16); | |
57 | memcpy(offset_ptr_ram, &val, sizeof(int)); | |
58 | } else { | |
59 | debug(" %p: rom reloc %x, ram %p, value %x, limit %x\n", | |
60 | re_src, re_src->r_offset, offset_ptr_ram, | |
61 | val, (unsigned int)&__bss_end); | |
62 | } | |
63 | } else { | |
64 | debug(" %p: rom reloc %x, last %p\n", re_src, | |
65 | re_src->r_offset, last_offset); | |
66 | } | |
67 | last_offset = offset_ptr_rom; | |
68 | ||
69 | } while (++re_src < re_end); | |
70 | ||
71 | return 0; | |
72 | } |