X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=arch%2Fx86%2Flib%2Frelocate.c;h=0d683bfc12282ee5ca1243fde252da6771c0f165;hb=a5221b52064013137109e7aa659b661747f47e98;hp=badb5f84f1740d9ed63f6c500214f3d6ee7299a8;hpb=b156ff09aad5a54b5a47b940ebc26aeeae56ee07;p=u-boot diff --git a/arch/x86/lib/relocate.c b/arch/x86/lib/relocate.c index badb5f84f1..0d683bfc12 100644 --- a/arch/x86/lib/relocate.c +++ b/arch/x86/lib/relocate.c @@ -12,104 +12,97 @@ * Sysgo Real-Time Solutions, GmbH * Marius Groeger * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * SPDX-License-Identifier: GPL-2.0+ */ #include -#include +#include #include +#include +#include #include -static int copy_uboot_to_ram(void); -static int clear_bss(void); -static int do_elf_reloc_fixups(void); +DECLARE_GLOBAL_DATA_PTR; -static int copy_uboot_to_ram(void) +int copy_uboot_to_ram(void) { size_t len = (size_t)&__data_end - (size_t)&__text_start; + if (gd->flags & GD_FLG_SKIP_RELOC) + return 0; memcpy((void *)gd->relocaddr, (void *)&__text_start, len); return 0; } -static int clear_bss(void) +int clear_bss(void) { ulong dst_addr = (ulong)&__bss_start + gd->reloc_off; size_t len = (size_t)&__bss_end - (size_t)&__bss_start; + if (gd->flags & GD_FLG_SKIP_RELOC) + return 0; memset((void *)dst_addr, 0x00, len); return 0; } -static int do_elf_reloc_fixups(void) +/* + * This function has more error checking than you might expect. Please see + * the commit message for more informaiton. + */ +int do_elf_reloc_fixups(void) { Elf32_Rel *re_src = (Elf32_Rel *)(&__rel_dyn_start); Elf32_Rel *re_end = (Elf32_Rel *)(&__rel_dyn_end); - Elf32_Addr *offset_ptr_rom; + Elf32_Addr *offset_ptr_rom, *last_offset = NULL; Elf32_Addr *offset_ptr_ram; + unsigned int text_base = 0; /* The size of the region of u-boot that runs out of RAM. */ uintptr_t size = (uintptr_t)&__bss_end - (uintptr_t)&__text_start; + if (gd->flags & GD_FLG_SKIP_RELOC) + return 0; + if (re_src == re_end) + panic("No relocation data"); + +#ifdef CONFIG_SYS_TEXT_BASE + text_base = CONFIG_SYS_TEXT_BASE; +#else + panic("No CONFIG_SYS_TEXT_BASE"); +#endif do { /* Get the location from the relocation entry */ offset_ptr_rom = (Elf32_Addr *)re_src->r_offset; /* Check that the location of the relocation is in .text */ - if (offset_ptr_rom >= (Elf32_Addr *)CONFIG_SYS_TEXT_BASE) { + if (offset_ptr_rom >= (Elf32_Addr *)text_base && + offset_ptr_rom > last_offset) { /* Switch to the in-RAM version */ offset_ptr_ram = (Elf32_Addr *)((ulong)offset_ptr_rom + gd->reloc_off); /* Check that the target points into .text */ - if (*offset_ptr_ram >= CONFIG_SYS_TEXT_BASE && - *offset_ptr_ram < - (CONFIG_SYS_TEXT_BASE + size)) { + if (*offset_ptr_ram >= text_base && + *offset_ptr_ram <= text_base + size) { *offset_ptr_ram += gd->reloc_off; + } else { + debug(" %p: rom reloc %x, ram %p, value %x," + " limit %" PRIXPTR "\n", re_src, + re_src->r_offset, offset_ptr_ram, + *offset_ptr_ram, + text_base + size); } + } else { + debug(" %p: rom reloc %x, last %p\n", re_src, + re_src->r_offset, last_offset); } - } while (re_src++ < re_end); + last_offset = offset_ptr_rom; - return 0; -} + } while (++re_src < re_end); -void relocate_code(ulong dummy_1, gd_t *id, ulong dummy_2) -{ - /* - * Copy U-Boot into RAM, clear the BSS and perform relocation - * adjustments - */ - copy_uboot_to_ram(); - clear_bss(); - do_elf_reloc_fixups(); - - /* - * Transfer execution from Flash to RAM by calculating the address - * of the in-RAM copy of board_init_r() and calling it - */ - (board_init_r + gd->reloc_off)(gd, gd->relocaddr); - - /* NOTREACHED - board_init_r() does not return */ - while (1) - ; + return 0; }