ChorusOS 4.0 Porting Guide

bconf_crt0.s Source File

The kernel/snippet/nucleus/boot_tools/bconf_crt0.s file contains the bootconf startup routine, bconf_start().


Example 3-2 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:

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