ChorusOS 4.0 Porting Guide

Rebooting the Board

This section describes how the reboot program reboots the board.

Example 4-3 is the reboot service routine source code provided in src/nucleus/bsp/powerpc/sbc8260/src/reboot/reboot.c


Example 4-3 do_reboot() routine

    void
do_reboot(RebootDesc* rd, KnRebootReq* req)
{
    ASSERT(rd == &rebootDesc);

    if (req->mode == K_REBOOT_COLD) {
        rebootCold(req);
    }

    if (req->mode == K_REBOOT_HOT) {
        rebootHot(req);
    }

    if (req->mode == K_REBOOT_NEW) {
        rebootNew(req);
    }

    ASSERT(0);
}

This service routine dispatches execution to a particular reboot procedure.

Cold Reboot

Example 4-4 is the cold reboot service routine source code provided in src/nucleus/bsp/powerpc/sbc8260/src/reboot/reboot.c.


Example 4-4 coldReboot() routine

    void
rebootCold(KnRebootReq* req)
{
    printf ("Cold reboot ...\n");
    resetOp(0);
}

This cold reboot service calls the debug agent hardware reset service routine.

Hot Reboot

Example 4-5 is the hot reboot service routine source code provided in src/nucleus/bsp/powerpc/sbc8260/src/reboot/reboot.c.


Example 4-5 hotReboot() routine

#define STACK_SIZE 0x400
char stack[STACK_SIZE];

    void
rebootHot(KnRebootReq* req)
{
    printf ("Hot reboot ...\n");

    /*
     * Extend the persistemt memory w.r.t the rebbot request
     */
    prstExtend(&rebootDesc.hot.prstMem, &req->u.hot);

    /*
     * switch to a private stack
     */
    call_and_switch_stack(req, rebootHot_cont, stack + STACK_SIZE);
}


    void
rebootHot_cont(KnRebootReq* req)
{
    /*
     * Disable I/D-Caches.
     */
    cachesDisable();

    /*
     * Disable pagination.
     */
    setMSR(getMSR() & ~(MSR_IR | MSR_DR));

    /*
     * Reboot
     */
    rebootEntry(&rebootDesc, &bootParams);
}

This hot reboot service routine:

Note that the implementation switches from the original stack to a small stack area which is statically allocated in the reboot program data segment. This occurs prior to the MMU disabling to ensure that the current stack is safely accessible in the real mode. See "call_and_switch_stack() routine" for details.

Rebooting The New System Image

The ChorusOS boot monitor is implemented as an application on top of ChorusOS. The boot monitor reads the new system image from an external medium (for example, a network) and stores that image in a buffer. It then performs a sysReboot() request that eventually invokes the rebootNew() service routine. To simplify the reboot implementation, the ChorusOS boot monitor has to use a ChorusOS system, configured with flat memory management, model.s. Example 4-6 is the service routine source code provided in src/nucleus/bsp/powerpc/sbc8260/src/reboot/reboot.c.


Example 4-6 rebootNew() Routine

    void
rebootNew(KnRebootReq* req)
{
    KnNewRebootReq* nreq = >u.nw;
    BootParams* bootp;

    printf ("Boot new image ...\n");

    if (nreq->workSize < (launch_end - launch_start) + sizeof(BootParams)) {
        printf ("Not enough working memory to reboot\n");
        printf ("Try cold reboot\n");
        resetOp(0);
    }

    /*
     * Disable I/D-Caches.
     */
    cachesDisable();

    if (nreq->ipcSiteNb) {
        /*
         * Get Chours IPC site number from the loader
         */
        bootParams.ipcSiteNb = nreq->ipcSiteNb;
    }

    /*
     * Copy bootParams at the end of the working area
     */
    bootp = (BootParams*) (nreq->workAddr + nreq->workSize - 
                           sizeof(BootParams));
    bcopy(&bootParams, bootp, sizeof(BootParams));

    /*
     * Copy the launch routine to the working memory
     */
    bcopy(launch_start, (void*) nreq->workAddr, launch_end - launch_start);

    /*
     * Jump to the copied launch code
     */
    ((launch) nreq->workAddr)(nreq->dstAddr, nreq->srcAddr, 
                          nreq->size, nreq->entry, bootp);
}

The caller (that is, sysReboot()) provides a working area that is separate to that from the current system image, including the currently executing reboot program. The buffer, holding the new system image, and the system image destination area are also outside the working area. In the working area, the rebootNew() routine installs the bootParams structure and a small positional independent program, called launch(), and then runs launch(). The launch() program copies the new system image from the buffer to the destination address and jumps to its entry point, passing the address of the bootParams structure as the first argument. See "launch() Routine" for details.