The kernel/snippet/nucleus/boot_tools/bconf_crt0.s file contains the bootconf startup routine, bconf_start().
.section .chr.my.rw.vaddr
rw_vaddr:
.section .chr.my.rw.kaddr
rw_kaddr:
.section .chr.my.rw.size
rw_size:
.section .chr.my.bss.vaddr
bss_vaddr:
.section .chr.my.bss.size
bss_size:
.section .text
GLOBAL(bconf_start)
bconf_start:
GLOBAL(__mkimage__label__start)
__mkimage__label__start:
LoadAddr(r5,bconf_main) /* bconf_main(r3) */
b .L1
GLOBAL(bconf_reboot_start)
bconf_reboot_start:
GLOBAL(__mkimage__label__reboot)
__mkimage__label__reboot:
LoadAddr(r5,bconf_reboot_main) /* bconf_reboot_main(r3, r4) */
b .L1
.L1:
/*
* Copy read/write segment if necessary
*
* (note that the segment can include the code that we are executing)
*/
LoadAddr(r8, rw_kaddr) /* r8 = src_addr */
LoadAddr(r9, rw_vaddr) /* r9 = dst_addr */
LoadAddr(r10, rw_size) /* r10 = size */
cmpwi r10,0 /* if (size) */
beq .L3 /* */
cmpw r8, r9 /* if (dst_addr != src_addr) */
beq .L3 /* */
.L2: /* do { */
lbz r0,0(r8) /* r0 = *src_addr */
stb r0,0(r9) /* *dst_addr = r0 */
addi r8,r8,1 /* ++src_addrq */
addi r9,r9,1 /* ++dst_addr */
subic. r10,r10,1 /* --size */
bne .L2 /* } while (size) */
.L3: /* */
/*
* Zero bss segment if necessary
*/
LoadAddr(r9, bss_vaddr) /* r9 = dst_addr */
LoadAddr(r10, bss_size) /* r10 = size */
cmpwi r10,0 /* if (size) */
beq .L5 /* */
li r0,0 /* r0 = 0 */
.L4: /* do { */
stb r0,0(r9) /* *dst_addr = 0 */
addi r9,r9,1 /* ++dst_addr */
subic. r10,r10,1 /* --size */
bne .L4 /* } while (size) */
.L5:
/*
* Setup the stack
*/
stack_setup:
LoadAddr(r1, heap) /* sp = heap[] */
LoadAddr(r9, heapSize) /* */
lwz r9, 0(r9) /* */
add r1, r1, r9 /* sp = sp + heapSize */
/*
* Jump to the main
*
* (note that if the code was also copied we must jump into the copy)
*/
jump_to_main:
mtlr r5
blr
The bootconf program defines two entry points bconf_start() and bconf_reboot_start(). The power-up initialization program enters using bconf_start() for a cold boot, whereas the reboot program enters using bconf_reboot_start() in the hot reboot path.
The install_me() routine tests whether the read-write segment and bss are link-edited in place (that is, at their places within the memory bank). To obtain the segment's layout within its memory bank and link-editing address, bconf_start() refers to predefined sections that mkimage relocated as follows:
The .chr.my.rw.vaddr section indicates the base link-editing address of the read-write segment.
The .chr.my.rw.kaddr section indicates the beginning of the read-write segment's image within the memory bank.
The .chr.my.rw.size section indicates the size of the read-write segment.
The .chr.my.bss.vaddr section indicates the base link-editing address of the bss.
The .chr.my.bss.size section indicates the size of the bss.
If necessary, install_me() copies the read-write segment and sets the bss to zero. Note that the bootconf code can be part of the read-write segment.
The stack_setup() routine initializes the stack pointer with the limit of the heap. The heap location and size are defined by heapStart and heapLimit (see "Heap and Stack").
The jump_to_main() routine jumps to the bconf_main() routine. If the bootconf code is part of the previously copied read-write segment, this jump transfers control from the original to the copy. The bconf_start program passes the content of register r3 as an opaque argument to bconf_main().
The __mkimage_label_start label enables the power-up program to transfer control to bootconf, as described in Example 3-1.
Note also that bconf_crt0.s preserves the value of r3 and r4 to allow callers to pass, at most, two arguments to the subsequent programs. For example, the initial loader can pass one board-dependent argument to the bootstrap program in r3, whereas the reboot program can pass two arguments (see "Hot Reboot").