u-boot/arch/x86/lib/relocate.c
Tom Rini d678a59d2d Revert "Merge patch series "arm: dts: am62-beagleplay: Fix Beagleplay Ethernet""
When bringing in the series 'arm: dts: am62-beagleplay: Fix Beagleplay
Ethernet"' I failed to notice that b4 noticed it was based on next and
so took that as the base commit and merged that part of next to master.

This reverts commit c8ffd1356d, reversing
changes made to 2ee6f3a5f7.

Reported-by: Jonas Karlman <jonas@kwiboo.se>
Signed-off-by: Tom Rini <trini@konsulko.com>
2024-05-19 08:16:36 -06:00

177 lines
4.7 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2008-2011
* Graeme Russ, <graeme.russ@gmail.com>
*
* (C) Copyright 2002
* Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
*
* (C) Copyright 2002
* Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
*
* (C) Copyright 2002
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
* Marius Groeger <mgroeger@sysgo.de>
*/
#include <common.h>
#include <log.h>
#include <relocate.h>
#include <asm/global_data.h>
#include <asm/u-boot-x86.h>
#include <asm/sections.h>
#include <elf.h>
DECLARE_GLOBAL_DATA_PTR;
int copy_uboot_to_ram(void)
{
size_t len = (uintptr_t)__data_end - (uintptr_t)__text_start;
if (gd->flags & GD_FLG_SKIP_RELOC)
return 0;
memcpy((void *)gd->relocaddr, (void *)__text_start, len);
return 0;
}
#ifndef CONFIG_EFI_APP
int clear_bss(void)
{
ulong dst_addr = (ulong)__bss_start + gd->reloc_off;
size_t len = (uintptr_t)__bss_end - (uintptr_t)__bss_start;
if (gd->flags & GD_FLG_SKIP_RELOC)
return 0;
memset((void *)dst_addr, 0x00, len);
return 0;
}
#endif
#if CONFIG_IS_ENABLED(X86_64)
static void do_elf_reloc_fixups64(unsigned int text_base, uintptr_t size,
Elf64_Rela *re_src, Elf64_Rela *re_end)
{
Elf64_Addr *offset_ptr_rom, *last_offset = NULL;
Elf64_Addr *offset_ptr_ram;
do {
unsigned long long type = ELF64_R_TYPE(re_src->r_info);
if (type != R_X86_64_RELATIVE) {
printf("%s: unsupported relocation type 0x%llx "
"at %p, ", __func__, type, re_src);
printf("offset = 0x%llx\n", re_src->r_offset);
continue;
}
/* Get the location from the relocation entry */
offset_ptr_rom = (Elf64_Addr *)(uintptr_t)re_src->r_offset;
/* Check that the location of the relocation is in .text */
if (offset_ptr_rom >= (Elf64_Addr *)(uintptr_t)text_base &&
offset_ptr_rom > last_offset) {
/* Switch to the in-RAM version */
offset_ptr_ram = (Elf64_Addr *)((ulong)offset_ptr_rom +
gd->reloc_off);
/* Check that the target points into .text */
if (*offset_ptr_ram >= text_base &&
*offset_ptr_ram <= text_base + size) {
*offset_ptr_ram = gd->reloc_off +
re_src->r_addend;
} else {
debug(" %p: %lx: rom reloc %lx, ram %p, value %lx, limit %lX\n",
re_src, (ulong)re_src->r_info,
(ulong)re_src->r_offset, offset_ptr_ram,
(ulong)*offset_ptr_ram, text_base + size);
}
} else {
debug(" %p: %lx: rom reloc %lx, last %p\n", re_src,
(ulong)re_src->r_info, (ulong)re_src->r_offset,
last_offset);
}
last_offset = offset_ptr_rom;
} while (++re_src < re_end);
}
#else
static void do_elf_reloc_fixups32(unsigned int text_base, uintptr_t size,
Elf32_Rel *re_src, Elf32_Rel *re_end)
{
Elf32_Addr *offset_ptr_rom, *last_offset = NULL;
Elf32_Addr *offset_ptr_ram;
do {
unsigned int type = ELF32_R_TYPE(re_src->r_info);
if (type != R_386_RELATIVE) {
printf("%s: unsupported relocation type 0x%x "
"at %p, ", __func__, type, re_src);
printf("offset = 0x%x\n", re_src->r_offset);
continue;
}
/* Get the location from the relocation entry */
offset_ptr_rom = (Elf32_Addr *)(uintptr_t)re_src->r_offset;
/* Check that the location of the relocation is in .text */
if (offset_ptr_rom >= (Elf32_Addr *)(uintptr_t)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 >= 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 %lX\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);
}
last_offset = offset_ptr_rom;
} while (++re_src < re_end);
}
#endif
/*
* This function has more error checking than you might expect. Please see
* this commit message for more information:
* 62f7970a x86: Add error checking to x86 relocation code
*/
int do_elf_reloc_fixups(void)
{
void *re_src = (void *)__rel_dyn_start;
void *re_end = (void *)__rel_dyn_end;
uint text_base;
/* 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_TEXT_BASE
text_base = CONFIG_TEXT_BASE;
#else
panic("No CONFIG_TEXT_BASE");
#endif
#if CONFIG_IS_ENABLED(X86_64)
do_elf_reloc_fixups64(text_base, size, re_src, re_end);
#else
do_elf_reloc_fixups32(text_base, size, re_src, re_end);
#endif
return 0;
}