mirror of
https://github.com/ivoszbg/uniLoader.git
synced 2026-08-15 05:18:32 +00:00
aarch64: introduce early relocation of the bootloader
All newer exynos devices with s-boot have the "feature" of placing the android kernel at a random location in dram, specifically around 0x80000000 and 0x83000000. This made it hard to assume where we are at, hence why we made everything as PiE (position-independent) as possible. This, however, resulted in a lot of issues. I usually managed to get around them with ugly hacks, but in the last 5-6 commits, with the fixed support for armv7, everything fell apart for arm64. So, the solution for this is to implement code at the beginning of the bootloader that relocates it to a safe place in memory. This is currently enabled for dreamlte, and it must be enabled and configured for all other boards with that issue. Otherwise they will NOT boot anymore. Boards that don't need this can keep CONFIG_POSITION_INDEPENDENT disabled.
This commit is contained in:
2
Kconfig
2
Kconfig
@@ -4,6 +4,8 @@
|
||||
#
|
||||
mainmenu "uniLoader Configuration"
|
||||
|
||||
source "arch/Kconfig"
|
||||
|
||||
menu "Building options"
|
||||
config CROSS_COMPILE
|
||||
string "Cross-compiler tool prefix"
|
||||
|
||||
3
Makefile
3
Makefile
@@ -373,7 +373,8 @@ all: arch/$(ARCH)/linker.lds uniLoader
|
||||
|
||||
# Generate linker script from template
|
||||
quiet_cmd_cpp_lds = LDS $@
|
||||
cmd_cpp_lds = $(CPP) $< -DTEXT_BASE=$(TEXT_BASE) \
|
||||
cmd_cpp_lds = $(CPP) -include include/generated/autoconf.h $< \
|
||||
-DTEXT_BASE=$(TEXT_BASE) \
|
||||
-DKERNEL_PATH=$(KERNEL_PATH) \
|
||||
-DDTB_PATH=$(DT_PATH) \
|
||||
-DRAMDISK_PATH=$(RAMDISK_PATH) \
|
||||
|
||||
7
arch/Kconfig
Normal file
7
arch/Kconfig
Normal file
@@ -0,0 +1,7 @@
|
||||
menu "Architecture"
|
||||
config POSITION_INDEPENDENT
|
||||
bool "Code relocation during early boot"
|
||||
help
|
||||
Say Y if your previous bootloader loads uniLoader at an unknown
|
||||
or different address every time.
|
||||
endmenu
|
||||
@@ -2,4 +2,5 @@
|
||||
#
|
||||
# Copyright (c) 2025 Ivaylo Ivanov <ivo.ivanov.ivanov1@gmail.com>
|
||||
|
||||
obj-$(CONFIG_POSITION_INDEPENDENT) += aarch64/reloc.o
|
||||
obj-y += aarch64/start.o aarch64/memcpy.o
|
||||
|
||||
@@ -2,8 +2,14 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Ivaylo Ivanov <ivo.ivanov.ivanov1@gmail.com>
|
||||
*/
|
||||
ENTRY(
|
||||
#ifdef CONFIG_POSITION_INDEPENDENT
|
||||
_head
|
||||
#else
|
||||
_start
|
||||
#endif
|
||||
);
|
||||
|
||||
ENTRY(_start);
|
||||
|
||||
OUTPUT_FORMAT("elf64-littleaarch64")
|
||||
OUTPUT_ARCH(aarch64)
|
||||
@@ -15,12 +21,31 @@ INPUT(RAMDISK_PATH)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = TEXT_BASE;
|
||||
|
||||
.text : {
|
||||
KEEP(*(.text.start))
|
||||
#ifdef CONFIG_POSITION_INDEPENDENT
|
||||
_reloc_start = .;
|
||||
#endif
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
}
|
||||
|
||||
.kernel ALIGN(4096) : {
|
||||
kernel = .;
|
||||
KERNEL_PATH
|
||||
}
|
||||
|
||||
.dtb ALIGN(4096) : {
|
||||
dtb = .;
|
||||
DTB_PATH
|
||||
}
|
||||
|
||||
.ramdisk ALIGN(4096) : {
|
||||
ramdisk = .;
|
||||
RAMDISK_PATH
|
||||
}
|
||||
|
||||
.rodata ALIGN(4) : {
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
@@ -42,23 +67,14 @@ SECTIONS
|
||||
.stack ALIGN(4096) : {
|
||||
. = . + 4096;
|
||||
_stack_end = .;
|
||||
}
|
||||
|
||||
.dtb ALIGN(4096) : {
|
||||
dtb = .;
|
||||
DTB_PATH
|
||||
}
|
||||
|
||||
.kernel ALIGN(4096) : {
|
||||
kernel = .;
|
||||
KERNEL_PATH
|
||||
}
|
||||
|
||||
.ramdisk ALIGN(4096) : {
|
||||
ramdisk = .;
|
||||
RAMDISK_PATH
|
||||
#ifdef CONFIG_POSITION_INDEPENDENT
|
||||
_reloc_end = .;
|
||||
#endif
|
||||
}
|
||||
|
||||
kernel_size = SIZEOF(.kernel);
|
||||
ramdisk_size = SIZEOF(.ramdisk);
|
||||
#ifdef CONFIG_POSITION_INDEPENDENT
|
||||
_reloc_size = _reloc_end - _reloc_start;
|
||||
#endif
|
||||
}
|
||||
|
||||
46
arch/aarch64/reloc.S
Normal file
46
arch/aarch64/reloc.S
Normal file
@@ -0,0 +1,46 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2025, Ivaylo Ivanov <ivo.ivanov.ivanov1@gmail.com>
|
||||
*/
|
||||
#include "asmdefs.h"
|
||||
|
||||
.extern _reloc_size
|
||||
.extern _start
|
||||
|
||||
ENTRY_ALIAS(_head)
|
||||
adr x1, _relocated_uni
|
||||
b _reloc_entry
|
||||
|
||||
ENTRY_ALIAS(_rel_stack_base)
|
||||
.quad _start
|
||||
|
||||
ENTRY_ALIAS(_rel_stack_size)
|
||||
.quad _reloc_size
|
||||
.quad 0
|
||||
.quad 0
|
||||
.quad 0
|
||||
.quad 0
|
||||
.ascii "ARM\x64"
|
||||
.long 0
|
||||
|
||||
ENTRY_ALIAS( _reloc_entry)
|
||||
adr x4, _start
|
||||
ldr x5, _rel_stack_base
|
||||
cmp x4, x5
|
||||
beq _entry
|
||||
ldr x6, _rel_stack_size
|
||||
|
||||
_copy:
|
||||
ldp x2, x3, [x4], #16
|
||||
stp x2, x3, [x5], #16
|
||||
subs x6, x6, #16
|
||||
b.ne _copy
|
||||
ldr x5, _rel_stack_base
|
||||
|
||||
_entry:
|
||||
br x5
|
||||
|
||||
_dead: /* we should never get here */
|
||||
b _dead
|
||||
|
||||
ENTRY_ALIAS(_relocated_uni)
|
||||
@@ -27,3 +27,4 @@ END(_start)
|
||||
ENTRY(load_kernel_and_jump)
|
||||
br x4
|
||||
END(load_kernel_and_jump)
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
CONFIG_POSITION_INDEPENDENT=y
|
||||
CONFIG_EXYNOS_8895=y
|
||||
CONFIG_SAMSUNG_DREAMLTE=y
|
||||
CONFIG_TEXT_BASE=0x87000000
|
||||
CONFIG_PAYLOAD_ENTRY=0x90000000
|
||||
CONFIG_RAMDISK_ENTRY=0x82000000
|
||||
CONFIG_RAMDISK_ENTRY=0x84000000
|
||||
CONFIG_FRAMEBUFFER_BASE=0xcc000000
|
||||
CONFIG_FRAMEBUFFER_WIDTH=1440
|
||||
CONFIG_FRAMEBUFFER_HEIGHT=2960
|
||||
|
||||
@@ -44,7 +44,6 @@ void main(void* dt, void* kernel, void* ramdisk)
|
||||
|
||||
/* Copy kernel to memory and boot */
|
||||
printk(-1, "booting linux...\n");
|
||||
|
||||
#ifdef __aarch64__
|
||||
memcpy((void*)CONFIG_PAYLOAD_ENTRY, kernel, (unsigned long) &kernel_size);
|
||||
__optimized_memcpy((void*)CONFIG_RAMDISK_ENTRY, ramdisk, (unsigned long) &ramdisk_size);
|
||||
|
||||
Reference in New Issue
Block a user