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").