diff --git a/arch/arm/config.mk b/arch/arm/config.mk index 6923f6d..0be47d3 100644 --- a/arch/arm/config.mk +++ b/arch/arm/config.mk @@ -33,11 +33,6 @@ STANDALONE_LOAD_ADDR = 0xc100000 endif endif -ifndef CONFIG_SYS_ARM_WITHOUT_RELOC -# needed for relocation -PLATFORM_RELFLAGS += -fPIC -endif - ifdef CONFIG_SYS_ARM_WITHOUT_RELOC PLATFORM_CPPFLAGS += -DCONFIG_SYS_ARM_WITHOUT_RELOC endif @@ -72,3 +67,8 @@ PLATFORM_LIBS += $(OBJTREE)/arch/arm/lib/eabi_compat.o endif endif LDSCRIPT := $(SRCTREE)/$(CPUDIR)/u-boot.lds + +ifndef CONFIG_SYS_ARM_WITHOUT_RELOC +# needed for relocation +PLATFORM_LDFLAGS += -pie +endif diff --git a/arch/arm/cpu/arm926ejs/start.S b/arch/arm/cpu/arm926ejs/start.S index a960689..49ca839 100644 --- a/arch/arm/cpu/arm926ejs/start.S +++ b/arch/arm/cpu/arm926ejs/start.S @@ -10,6 +10,7 @@ * Copyright (c) 2002 Gary Jennejohn * Copyright (c) 2003 Richard Woodruff * Copyright (c) 2003 Kshitij + * Copyright (c) 2010 Albert Aribaud * * See file CREDITS for list of people who contributed to this * project. @@ -118,22 +119,19 @@ _fiq: _TEXT_BASE: .word TEXT_BASE -#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC) -.globl _armboot_start -_armboot_start: - .word _start -#endif - /* * These are defined in the board-specific linker script. + * Subtracting _start from them lets the linker put their + * relative position in the executable instead of leaving + * them null. */ -.globl _bss_start -_bss_start: - .word __bss_start +.globl _bss_start_ofs +_bss_start_ofs: + .word __bss_start - _start -.globl _bss_end -_bss_end: - .word _end +.globl _bss_end_ofs +_bss_end_ofs: + .word _end - _start #ifdef CONFIG_USE_IRQ /* IRQ stack memory (calculated at run-time) */ @@ -153,30 +151,6 @@ FIQ_STACK_START: IRQ_STACK_START_IN: .word 0x0badc0de -.globl _datarel_start -_datarel_start: - .word __datarel_start - -.globl _datarelrolocal_start -_datarelrolocal_start: - .word __datarelrolocal_start - -.globl _datarellocal_start -_datarellocal_start: - .word __datarellocal_start - -.globl _datarelro_start -_datarelro_start: - .word __datarelro_start - -.globl _got_start -_got_start: - .word __got_start - -.globl _got_end -_got_end: - .word __got_end - /* * the actual reset code */ @@ -226,9 +200,8 @@ stack_setup: adr r0, _start ldr r2, _TEXT_BASE - ldr r3, _bss_start - sub r2, r3, r2 /* r2 <- size of armboot */ - add r2, r0, r2 /* r2 <- source end address */ + ldr r3, _bss_start_ofs + add r2, r0, r3 /* r2 <- source end address */ cmp r0, r6 beq clear_bss @@ -240,36 +213,54 @@ copy_loop: blo copy_loop #ifndef CONFIG_PRELOADER - /* fix got entries */ - ldr r1, _TEXT_BASE /* Text base */ - mov r0, r7 /* reloc addr */ - ldr r2, _got_start /* addr in Flash */ - ldr r3, _got_end /* addr in Flash */ - sub r3, r3, r1 - add r3, r3, r0 - sub r2, r2, r1 - add r2, r2, r0 - + /* + * fix .rel.dyn relocations + */ + ldr r0, _TEXT_BASE /* r0 <- Text base */ + sub r9, r7, r0 /* r9 <- relocation offset */ + ldr r10, _dynsym_start_ofs /* r10 <- sym table ofs */ + add r10, r10, r0 /* r10 <- sym table in FLASH */ + ldr r2, _rel_dyn_start_ofs /* r2 <- rel dyn start ofs */ + add r2, r2, r0 /* r2 <- rel dyn start in FLASH */ + ldr r3, _rel_dyn_end_ofs /* r3 <- rel dyn end ofs */ + add r3, r3, r0 /* r3 <- rel dyn end in FLASH */ fixloop: - ldr r4, [r2] - sub r4, r4, r1 - add r4, r4, r0 - str r4, [r2] - add r2, r2, #4 + ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */ + add r0, r9 /* r0 <- location to fix up in RAM */ + ldr r1, [r2, #4] + and r8, r1, #0xff + cmp r8, #23 /* relative fixup? */ + beq fixrel + cmp r8, #2 /* absolute fixup? */ + beq fixabs + /* ignore unknown type of fixup */ + b fixnext +fixabs: + /* absolute fix: set location to (offset) symbol value */ + mov r1, r1, LSR #4 /* r1 <- symbol index in .dynsym */ + add r1, r10, r1 /* r1 <- address of symbol in table */ + ldr r1, [r1, #4] /* r1 <- symbol value */ + add r1, r9 /* r1 <- relocated sym addr */ + b fixnext +fixrel: + /* relative fix: increase location by offset */ + ldr r1, [r0] + add r1, r1, r9 +fixnext: + str r1, [r0] + add r2, r2, #8 /* each rel.dyn entry is 8 bytes */ cmp r2, r3 - bne fixloop + blo fixloop #endif #endif /* #ifndef CONFIG_SKIP_RELOCATE_UBOOT */ clear_bss: #ifndef CONFIG_PRELOADER - ldr r0, _bss_start - ldr r1, _bss_end + ldr r0, _bss_start_ofs + ldr r1, _bss_end_ofs ldr r3, _TEXT_BASE /* Text base */ mov r4, r7 /* reloc addr */ - sub r0, r0, r3 add r0, r0, r4 - sub r1, r1, r3 add r1, r1, r4 mov r2, #0x00000000 /* clear */ @@ -287,24 +278,33 @@ clbss_l:str r2, [r0] /* clear loop... */ * initialization, now running from RAM. */ #ifdef CONFIG_NAND_SPL - ldr pc, _nand_boot - -_nand_boot: .word nand_boot + ldr r0, _nand_boot_ofs + adr r1, _start + add pc, r0, r1 +_nand_boot_ofs + : .word nand_boot - _start #else - ldr r0, _TEXT_BASE - ldr r2, _board_init_r - sub r2, r2, r0 - add r2, r2, r7 /* position from board_init_r in RAM */ + ldr r0, _board_init_r_ofs + adr r1, _start + add r0, r0, r1 + add lr, r0, r9 /* setup parameters for board_init_r */ mov r0, r5 /* gd_t */ mov r1, r7 /* dest_addr */ /* jump to it ... */ - mov lr, r2 mov pc, lr -_board_init_r: .word board_init_r +_board_init_r_ofs: + .word board_init_r - _start #endif +_rel_dyn_start_ofs: + .word __rel_dyn_start - _start +_rel_dyn_end_ofs: + .word __rel_dyn_end - _start +_dynsym_start_ofs: + .word __dynsym_start - _start + #else /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */ /* * the actual reset code @@ -333,10 +333,8 @@ relocate: /* relocate U-Boot to RAM */ ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ cmp r0, r1 /* don't reloc during debug */ beq stack_setup - ldr r2, _armboot_start - ldr r3, _bss_start - sub r2, r3, r2 /* r2 <- size of armboot */ - add r2, r0, r2 /* r2 <- source end address */ + ldr r3, _bss_start_ofs /* r3 <- _bss_start - _start */ + add r2, r0, r3 /* r2 <- source end address */ copy_loop: ldmia r0!, {r3-r10} /* copy from source address [r0] */ @@ -360,8 +358,11 @@ stack_setup: bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ clear_bss: - ldr r0, _bss_start /* find start of bss segment */ - ldr r1, _bss_end /* stop here */ + adr r2, _start + ldr r0, _bss_start_ofs /* find start of bss segment */ + add r0, r0, r2 + ldr r1, _bss_end_ofs /* stop here */ + add r1, r1, r2 mov r2, #0x00000000 /* clear */ #ifndef CONFIG_PRELOADER @@ -374,13 +375,16 @@ clbss_l:str r2, [r0] /* clear loop... */ bl red_LED_on #endif /* CONFIG_PRELOADER */ - ldr pc, _start_armboot + ldr r0, _start_armboot_ofs + adr r1, _start + add r0, r0, r1 + ldr pc, r0 -_start_armboot: +_start_armboot_ofs: #ifdef CONFIG_NAND_SPL - .word nand_boot + .word nand_boot - _start #else - .word start_armboot + .word start_armboot - _start #endif /* CONFIG_NAND_SPL */ #endif /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */ @@ -469,7 +473,7 @@ cpu_init_crit: sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12 #if defined(CONFIG_SYS_ARM_WITHOUT_RELOC) - ldr r2, _armboot_start + adr r2, _start sub r2, r2, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN) sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ set base 2 words into abort stack #else @@ -507,7 +511,7 @@ cpu_init_crit: .macro get_bad_stack #if defined(CONFIG_SYS_ARM_WITHOUT_RELOC) - ldr r13, _armboot_start @ setup our mode stack + adr r13, _start @ setup our mode stack sub r13, r13, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN) sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack #else diff --git a/arch/arm/cpu/arm926ejs/u-boot.lds b/arch/arm/cpu/arm926ejs/u-boot.lds index 02eb8ca..72f45f8 100644 --- a/arch/arm/cpu/arm926ejs/u-boot.lds +++ b/arch/arm/cpu/arm926ejs/u-boot.lds @@ -41,21 +41,19 @@ SECTIONS . = ALIGN(4); .data : { *(.data) - __datarel_start = .; - *(.data.rel) - __datarelrolocal_start = .; - *(.data.rel.ro.local) - __datarellocal_start = .; - *(.data.rel.local) - __datarelro_start = .; - *(.data.rel.ro) } - __got_start = .; . = ALIGN(4); - .got : { *(.got) } - __got_end = .; + __rel_dyn_start = .; + .rel.dyn : { *(.rel.dyn) } + __rel_dyn_end = .; + + __dynsym_start = .; + .dynsym : { *(.dynsym) } + + . = ALIGN(4); + . = .; __u_boot_cmd_start = .; .u_boot_cmd : { *(.u_boot_cmd) } @@ -65,4 +63,10 @@ SECTIONS __bss_start = .; .bss (NOLOAD) : { *(.bss) . = ALIGN(4); } _end = .; + + /DISCARD/ : { *(.dynstr*) } + /DISCARD/ : { *(.dynamic*) } + /DISCARD/ : { *(.plt*) } + /DISCARD/ : { *(.interp*) } + /DISCARD/ : { *(.gnu*) } } diff --git a/arch/arm/include/asm/config.h b/arch/arm/include/asm/config.h index 4e8dfd7..8d3eb10 100644 --- a/arch/arm/include/asm/config.h +++ b/arch/arm/include/asm/config.h @@ -21,8 +21,6 @@ #ifndef _ASM_CONFIG_H_ #define _ASM_CONFIG_H_ -#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC) /* Relocation to SDRAM works on all ARM boards */ #define CONFIG_RELOC_FIXUP_WORKS #endif -#endif diff --git a/arch/arm/include/asm/u-boot-arm.h b/arch/arm/include/asm/u-boot-arm.h index faf800a..4ac4f61 100644 --- a/arch/arm/include/asm/u-boot-arm.h +++ b/arch/arm/include/asm/u-boot-arm.h @@ -30,18 +30,18 @@ #define _U_BOOT_ARM_H_ 1 /* for the following variables, see start.S */ -extern ulong _bss_start; /* code + data end == BSS start */ -extern ulong _bss_end; /* BSS end */ +extern ulong _bss_start_ofs; /* BSS start relative to _start */ +extern ulong _bss_end_ofs; /* BSS end relative to _start */ extern ulong IRQ_STACK_START; /* top of IRQ stack */ extern ulong FIQ_STACK_START; /* top of FIQ stack */ #if defined(CONFIG_SYS_ARM_WITHOUT_RELOC) -extern ulong _armboot_start; /* code start */ +extern ulong _armboot_start_ofs; /* code start */ #else extern ulong _TEXT_BASE; /* code start */ -extern ulong _datarel_start; -extern ulong _datarelrolocal_start; -extern ulong _datarellocal_start; -extern ulong _datarelro_start; +extern ulong _datarel_start_ofs; +extern ulong _datarelrolocal_start_ofs; +extern ulong _datarellocal_start_ofs; +extern ulong _datarelro_start_ofs; extern ulong IRQ_STACK_START_IN; /* 8 bytes in IRQ stack */ #endif diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c index 5f2dfd0..e411d93 100644 --- a/arch/arm/lib/board.c +++ b/arch/arm/lib/board.c @@ -147,7 +147,7 @@ static int display_banner (void) #else _armboot_start, #endif - _bss_start, _bss_end); + _bss_start_ofs+_TEXT_BASE, _bss_end_ofs+_TEXT_BASE); #ifdef CONFIG_MODEM_SUPPORT debug ("Modem Support enabled\n"); #endif @@ -517,7 +517,7 @@ void board_init_f (ulong bootflag) memset ((void*)gd, 0, sizeof (gd_t)); - gd->mon_len = _bss_end - _TEXT_BASE; + gd->mon_len = _bss_end_ofs; for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { if ((*init_fnc_ptr)() != 0) { @@ -679,6 +679,7 @@ static char *failed = "*** failed ***\n"; * ************************************************************************ */ + void board_init_r (gd_t *id, ulong dest_addr) { char *s; @@ -702,7 +703,7 @@ void board_init_r (gd_t *id, ulong dest_addr) gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */ - monitor_flash_len = _bss_start - _TEXT_BASE; + monitor_flash_len = _bss_start_ofs; debug ("monitor flash len: %08lX\n", monitor_flash_len); board_init(); /* Setup chipselects */ @@ -914,6 +915,7 @@ extern void davinci_eth_set_mac_addr (const u_int8_t *addr); /* NOTREACHED - no way out of command loop except booting */ } + #endif /* defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */ void hang (void) diff --git a/doc/README.arm-relocation b/doc/README.arm-relocation index e3ed60e..b46347b 100644 --- a/doc/README.arm-relocation +++ b/doc/README.arm-relocation @@ -1,49 +1,54 @@ To make relocation on arm working, the following changes are done: -Add new compilerflag: +At arch level: add linker flag -pie --fPIC + This causes the linker to generate fixup tables .rel.dyn and .dynsym, + which must be applied to the relocated image before transferring + control to it. - -> compiler generates position independent code + These fixups are described in the ARM ELF documentation as type 23 + (program-base-relative) and 2 (symbol-relative) -changes in board code: +At cpu level: modify linker file and add a relocation and fixup loop -- dram_init: - - bd pointer is now at this point not accessible, so only - detect the real dramsize, and store it in gd->ram_size. - best detected with get_ram_size(); - ToDo: move there also the dram initialization on boards where - it is possible. - - setup the bd_t dram bank info in the new function - dram_init_banksize(). + the linker file must be modified to include the .rel.dyn and .dynsym + tables in the binary image, and to provide symbols for the relocation + code to access these tables -- board.c code is adapted from ppc code + The relocation and fixup loop must be executed after executing + board_init_f at initial location and before executing board_init_r + at final location. -- undef CONFIG_RELOC_FIXUP_WORKS +At board level: - -> cmdtabl, and subcommand table must be handled from "hand" - collected in section "__datarellocal_start". + dram_init(): bd pointer is now at this point not accessible, so only + detect the real dramsize, and store it in gd->ram_size. Bst detected + with get_ram_size(). - - How To fixup the sections: +TODO: move also dram initialization there on boards where it is possible. - __datarel_start, __datarelrolocal_start, __datarellocal_start and - __datarelro_start + Setup of the the bd_t dram bank info is done in the new function + dram_init_banksize() called after bd is accessible. - automatically? Then it should be possible to define again - CONFIG_RELOC_FIXUP_WORKS +At lib level: -- irq stack setup is now not longer on a fix position, instead it is - calculated in board_init_f, and stored in gd->irq_sp + Board.c code is adapted from ppc code -------------------------------------------------------------------------------------- +At config level: -To compile a board without relocation, define CONFIG_SYS_ARM_WITHOUT_RELOC -This possibility will removed!! So please fix your board to compile without -CONFIG_SYS_ARM_WITHOUT_RELOC defined!!! + Define CONFIG_RELOC_FIXUP_WORKS. + Undefine CONFIG_SYS_ARM_WITHOUT_RELOC -------------------------------------------------------------------------------------- +* WARNING ** WARNING ** WARNING ** WARNING ** WARNING ** WARNING ** WARNING * + +Boards which are not fixed to support relocation will be REMOVED! + +Eventually, CONFIG_SYS_ARM_WITHOUT_RELOC and CONFIG_RELOC_FIXUP_WORKS will +disappear and boards which have to migrated to relocation will disappear too. + +----------------------------------------------------------------------------- -For boards which boot from nand_spl, it is possible to save a copy +For boards which boot from nand_spl, it is possible to save one copy if TEXT_BASE == relocation address! This prevents that uboot code is copied again in relocate_code(). @@ -64,9 +69,9 @@ f) u-boot code steps through board_init_f() and calculates If TEXT_BASE == relocation address, the copying of u-boot in f) could be saved. -------------------------------------------------------------------------------------- +----------------------------------------------------------------------------- -ToDo: +TODO - fill in bd_t infos (check) - adapt all boards @@ -80,7 +85,7 @@ ToDo: - new function dram_init_banksize() is actual board specific. Maybe we make a weak default function in arch/arm/lib/board.c ? -------------------------------------------------------------------------------------- +----------------------------------------------------------------------------- Relocation with NAND_SPL (example for the tx25): @@ -98,158 +103,11 @@ Relocation with NAND_SPL (example for the tx25): from the nand_spl code), no need to copy, just go on with bss clear and jump to board_init_r. -------------------------------------------------------------------------------------- - -Relocation: -How to translate flash addresses in GOT to ram addresses. -This is automagically done from code, but this example -shows, how this magic code works ;-) -(example on the qong board) - -Find a variable: - -a) search it in System.map -(for example flash_info) - -a005b4c0 B BootpID -a005b4c4 B BootpTry -a005b4c8 b slave -a005b4cc B flash_info -^^^^^^^^ -a005c908 b saved_sector.4002 -a005c910 b cfi_mtd_info -a005c9c0 b cfi_mtd_names -a005c9d0 B mtd_table - ---------------------------------------- - -b) create hexdump from u-boot code: - -hexdump -C u-boot > gnlmpfhex - ---------------------------------------- - -c) search the variables address in the hexdump - - -* -0005fc80 00 00 00 00 00 00 00 00 2c 06 01 a0 18 cd 05 a0 |........,.......| -0005fc90 9c d4 05 a0 bc b4 05 a0 1c 7f 05 a0 f0 05 01 a0 |................| -0005fca0 08 5a 04 a0 1c ab 05 a0 ec a4 05 a0 98 c3 01 a0 |.Z..............| -0005fcb0 a0 d6 05 a0 04 71 05 a0 c0 f9 00 a0 3c cd 05 a0 |.....q......<...| -0005fcc0 cc b4 05 a0 f0 fa 00 a0 f0 d6 05 a0 10 86 05 a0 |................| - ^^^^^^^^^^^ -0005fcd0 a4 16 06 a0 dc 64 05 a0 18 86 05 a0 52 48 05 a0 |.....d......RH..| -0005fce0 c0 86 05 a0 24 6e 02 a0 b4 6c 05 a0 b0 94 01 a0 |....$n...l......| -0005fcf0 1c 86 05 a0 50 85 05 a0 d4 0c 06 a0 bc 0b 06 a0 |....P...........| - - --> 0005fcc0 - ----------------------------------------- - -d) know we calculate this address in RAM - - - 8ff08000 (new address of code in RAM *1) - -+ 0005fcc0 - -- 00008000 (offset of text *2) - ----------- - - 8ff5fcc0 -> Addr GOT in RAM - -*1: -activate debug and look for the line: -Now running in RAM - U-Boot at: 8ff08000 - ^^^^^^^^ - new address of u-boot code in RAM - -*2: -Section Headers: - [Nr] Name Type Addr Off Size ES Flg Lk Inf Al - [ 0] NULL 00000000 000000 000000 00 0 0 0 - [ 1] .text PROGBITS a0000000 008000 04599c 00 AX 0 0 32 - ^^^^^^ - Offset of text +----------------------------------------------------------------------------- ----------------------------------------- +How ELF relocations 23 and 2 work. -e) now we look in 8ff5fcc0 (RAM) - - -QongEVB>md 0x8ff5fcc0 -8ff5fcc0 : a005b4cc a000faf0 a005d6f0 a0058610 ................ - ^^^^^^^^ - Bingo, here we have the old flash address (when relocation - is working, here is the fixed ram address. see @ f, how - it gets calculated) - - ----------------------------------------- - -f) now translate it in the new RAM address - - a005b4cc - -- a0000000 TextBase - -+ 8ff08000 new address of u-boot in ram ----------- - 8ff634cc - -QongEVB>mm 0x8ff5fcc0 0x8ff634cc 1 -QongEVB>md 0x8ff5fcc0 -8ff5fcc0 : 8ff634cc a000faf0 a005d6f0 a0058610 .4.............. -8ff5fcd0 : a00616a4 a00564dc a0058618 a0054852 .....d......RH.. - -As this must be done for all address in the GOT, the u-boot -code did this automagically ... :-) - ----------------------------------------------- - -g) check if the new address is really in the bss section: - -bss start: -8ff6054c (8ff08000 + 0005854C monitorlen) - -bss end: -8ff698ac (8ff08000 + 618AC) - -8ff634cc is in bss :-) - ----------------------------------------------- - -h) u-boot prints: - -important addresses: - -U-Boot code: A0000000 -> A005854C BSS: -> A00618AC TextBase 0xa0000000 -Now running in RAM - U-Boot at: 8ff08000 relocBase 0x8ff08000 - - ---------- - -U-Boot 2010.06-rc2-00002-gf8fbb25-dirty (Jun 18 2010 - 17:07:19) - -U-Boot code: A0000000 -> A005854C BSS: -> A00618AC -CPU: Freescale i.MX31 at 398 MHz -Board: DAVE/DENX Qong -mon: FFFFFFFF gd->monLen: 000618AC -Top of RAM usable for U-Boot at: 90000000 -LCD panel info: 640 x 480, 16 bit/pix -Reserving 600k for LCD Framebuffer at: 8ff6a000 -Reserving 390k for U-Boot at: 8ff08000 -Reserving 1280k for malloc() at: 8fdc8000 -Reserving 28 Bytes for Board Info at: 8fdc7fe4 -Reserving 48 Bytes for Global Data at: 8fdc7fb4 -New Stack Pointer is: 8fdc7fb0 -RAM Configuration: -Bank #0: 80000000 256 MiB -mon: 0005854C gd->monLen: 000618AC -Now running in RAM - U-Boot at: 8ff08000 +TBC -------------------------------------------------------------------------------------