[U-Boot] Trying to understand ARM926EJS/start.S

Reinhard Meyer
2010-10-30T18:09:17Z

Hello,

I am not (yet) good at ARM assembler syntax and instructions, so trying
to understand the start.S code is not very easy for me. However I think
I saw some places there that need clarification. All what I see as
suspiscious I have marked with $$$ and just comments with %%% in the
next line.

...
.globl _bss_start_ofs
_bss_start_ofs:
.word __bss_start - _start

.globl _bss_end_ofs
_bss_end_ofs:
.word _end - _start
%%% both yield constants that are in TEXT and can be accessed
%%% PC relative, right?
...
reset:
/*
* set the cpu to SVC32 mode
*/
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0xd3
msr cpsr,r0
%%% just style: the rest uses spaces after the comma.
/*
* we do sys-critical inits only at reboot,
* not when booting from ram!
*/
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif

/* Set stackpointer in internal RAM to call board_init_f */
call_board_init_f:
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
ldr r0,=0x00000000
%%% style
bl board_init_f

/*------------------------------------------------------------------------------*/

/*
* void relocate_code (addr_sp, gd, addr_moni)
*
* This "function" does not return, instead it continues in RAM
* after relocating the monitor code.
*
*/
.globl relocate_code
relocate_code:
mov r4, r0 /* save addr_sp */
mov r5, r1 /* save addr of gd */
mov r6, r2 /* save addr of destination */
mov r7, r2 /* save addr of destination */

/* Set up the stack */
stack_setup:
mov sp, r4

adr r0, _start
%%% adr reg, label sets reg to the address of label?
%%% ldr reg, label sets reg to the content of mem at label?
ldr r2, _TEXT_BASE
$$$ r2 is overwritten two lines below, right?
ldr r3, _bss_start_ofs
add r2, r0, r3 /* r2 <- source end address */
cmp r0, r6
beq clear_bss

copy_loop:
ldmia r0!, {r9-r10} /* copy from source address [r0] */
stmia r6!, {r9-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end address [r2] */
blo copy_loop

#ifndef CONFIG_PRELOADER
/*
* fix .rel.dyn relocations
*/
ldr r0, _TEXT_BASE /* r0 <- Text base */
%%% why are we using _TEXT_BASE here and not _start?
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 r0, [r2] /* r0 <- location to fix up, IN FLASH! */
add r0, 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
blo fixloop
#endif

clear_bss:
#ifndef CONFIG_PRELOADER
ldr r0, _bss_start_ofs
%%% r0 = __bss_start - _start
ldr r1, _bss_end_ofs
%%% r1 = _end - _start
ldr r3, _TEXT_BASE /* Text base */
$$$ r3 is not used below this
mov r4, r7 /* reloc addr */
%%% why move it to r4? could we not add r7 in the next 2 lines?
add r0, r0, r4
%%% ok, this yields r0 = __bss_start - _start + "relocated address"
add r1, r1, r4
%%% ok, this yields r1 = _end - _start + "relocated address"
mov r2, #0x00000000 /* clear */

clbss_l:str r2, [r0] /* clear loop... */
add r0, r0, #4
cmp r0, r1
bne clbss_l
%%% this should better be blo, just in case _end is not aligned?

%%% I cannot see anything here that would prevent BSS being cleared.
bl coloured_LED_init
bl red_LED_on
#endif

/*
* We are done. Do not return, instead branch to second part of board
* initialization, now running from RAM.
*/
#ifdef CONFIG_NAND_SPL
ldr r0, _nand_boot_ofs
mov pc, r0

_nand_boot_ofs:
.word nand_boot
#else
ldr r0, _board_init_r_ofs
adr r1, _start
add lr, r0, r1
add lr, lr, r9
/* setup parameters for board_init_r */
mov r0, r5 /* gd_t */
mov r1, r7 /* dest_addr */
/* jump to it ... */
mov pc, lr
...

Best Regards,
Reinhard