diff --git a/Kconfig b/Kconfig index 1b9080a..a9331c4 100644 --- a/Kconfig +++ b/Kconfig @@ -4,6 +4,8 @@ # mainmenu "uniLoader Configuration" +source "arch/Kconfig" + menu "Building options" config CROSS_COMPILE string "Cross-compiler tool prefix" diff --git a/Makefile b/Makefile index 9c8b844..18f533c 100644 --- a/Makefile +++ b/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) \ diff --git a/arch/Kconfig b/arch/Kconfig new file mode 100644 index 0000000..dc21446 --- /dev/null +++ b/arch/Kconfig @@ -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 diff --git a/arch/aarch64/Makefile b/arch/aarch64/Makefile index de499da..6f1e0c9 100644 --- a/arch/aarch64/Makefile +++ b/arch/aarch64/Makefile @@ -2,4 +2,5 @@ # # Copyright (c) 2025 Ivaylo Ivanov +obj-$(CONFIG_POSITION_INDEPENDENT) += aarch64/reloc.o obj-y += aarch64/start.o aarch64/memcpy.o diff --git a/arch/aarch64/linker.lds.S b/arch/aarch64/linker.lds.S index daa98d8..666f204 100644 --- a/arch/aarch64/linker.lds.S +++ b/arch/aarch64/linker.lds.S @@ -2,8 +2,14 @@ /* * Copyright (c) 2022, Ivaylo Ivanov */ +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 } diff --git a/arch/aarch64/reloc.S b/arch/aarch64/reloc.S new file mode 100644 index 0000000..be745f1 --- /dev/null +++ b/arch/aarch64/reloc.S @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2025, Ivaylo Ivanov + */ +#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) diff --git a/arch/aarch64/start.S b/arch/aarch64/start.S index 16df791..5174008 100644 --- a/arch/aarch64/start.S +++ b/arch/aarch64/start.S @@ -27,3 +27,4 @@ END(_start) ENTRY(load_kernel_and_jump) br x4 END(load_kernel_and_jump) + diff --git a/configs/dreamlte_defconfig b/configs/dreamlte_defconfig index a5379a9..ca5510b 100644 --- a/configs/dreamlte_defconfig +++ b/configs/dreamlte_defconfig @@ -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 diff --git a/main/main.c b/main/main.c index b87bb3e..4b92e5e 100644 --- a/main/main.c +++ b/main/main.c @@ -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);