ChorusOS 4.0 Porting Guide

Reboot Program Implementation Framework

This section discribes the library routines that can be used by reboot programs.

prstExtend() Routine

The prstExtend() routine can be used to allocate a new persistent memory device descriptor. Example 4-7 is the prstExtend() routine source code provided in kernel/snippet/nucleus/boot_tools/prstExtend.c.


Example 4-7 prstExtend() Routine

    void
prstExtend(PrstMem* pm, KnHotRebootReq* hreq)
{
    if (hreq->prstMemExtension) {
        if (pm->numChunks == pm->maxChunks) {
            printf ("Hot reboot can't allocate more than %d presistent "
                    "memory devices\n", pm->maxChunks);
        } else {
            int id_len = strlen(hreq->prstMemId) + 1;
            if (pm->curStrLen + id_len > pm->maxStrLen) {
                printf ("Hot reboot can't allocate more than %d bytes "
                        "for persistent memory device ids\n", 
                        pm->maxStrLen);
            } else {
                PrstChunk* ch_cur = pm->chunks+ pm->numChunks;
                ch_cur->status = 0;
                ch_cur->size = (PhSize) hreq->prstMemExtension;
                ch_cur->id = pm->str + pm->curStrLen;
                strcpy(ch_cur->id, hreq->prstMemId);
                pm->curStrLen += id_len;
                pm->numChunks += 1;
            }
        }
    }
}

The prstExtend() routine allocates the next available entry in the chunk array (the array is held within the persistent memory descriptor and is pointed to by the pm argument). The routine also copies the symbolic name of the new memory device from the caller address space into the str buffer (also held within the persistent memory descriptor). Note that the persistent memory descriptor is typically allocated within the reboot program data segment.

call_and_switch_stack() routine

Example 4-6 is the call_and_switch_stack() routine source code provided in kernel/snippet/nucleus/boot_tools/call_and_switch_stack.s.


Example 4-8 call_and_switch_stack() Routine

			/*
			 *     void
			 * call_and_swithc_stack(void* cookie, void* new_pc, void* new_sp)
			 */

			GLOBAL(call_and_switch_stack)
call_and_switch_stack:
    mr    r5, r1    /* sp = new_sp */
    mtlr  r4, lr    /* (*new_pc) (cookie) */
    blr

The call_and_switch_stack() routine switches to the stack provided as argument three, new_pc, jumps to the function specified by the second argument, new_pc, passing to that function the first argument, cookie.

launch() Routine

Example 4-6 is the launch() routine source code provided in kernel/snippet/nucleus/boot_tools/launch.s.


Example 4-9 launch() Routine

        /*
         *     void
         * launch (VmAddr dst, VmAddr src, VmSize size , KnPc entry, void* cookie);
         */

        .global launch_start
        .global launch_end

launch_start:   

launch_end:     


The launch() function copies size bytes from the source address, src, to the destination address, dst, and then jumps to the location entry, passing cookie as the argument.

The launch() routine is positional independent. The caller can copy the instructions, starting from the address launch_start() up to the address launch_end(), to any destination location and execute them there.

The launch() routine does not require a stack and is not required to preserve any general register state.