/* * main.c -- startup code for colilo * * Based on NETtel code: (C) Copyright 1999, Moreton Bay Ventures Pty Ltd. * Modifications: (C) Copyright 1999, Rob Scott * * Cadre 3 additions: * (C) Copyright 1999, Roland Seuhs e9626680@student.tuwien.ac.at * * MCF5249C3 additions: * (C) Copyright 2003, Jeremy Andrus * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "prototypes.h" #include "arch.h" /* Board definitions: we need MCF_MEMBASE from this file */ #include "function.h" /* Include UI constants */ #include "ledstate.h" /* LED state definitions for setLED() */ unsigned int function; /*****************************************************************************/ unsigned int downloadPort; /* Sets which serial port to use for dl */ unsigned int image_size; /* Compressed image size */ unsigned char *xfer_addr; /* Transfer address to start execution at */ unsigned char *down_addr; /* Download image to this address */ unsigned char *dest_addr; /* Decompress image to this address */ unsigned char *source_addr; /* Compressed image at this address */ /*****************************************************************************/ /*** Local prototypes ***/ // void setupCRuntime() is in prototypes.h void runimage(unsigned char *src, unsigned int len, unsigned char *dest, unsigned char *xfer); int decompress(unsigned char *src, unsigned int len, unsigned char *dest); void recover(void); int run(unsigned char *dest); int loadimage(unsigned long *src, unsigned long *dst, unsigned int len); /*** These come from /vendor/$(VENDOR)/$(BOARD)/board.c ***/ extern void configureConsole(); extern void configureAuxSerial(); extern void setupBoard(); extern void setImageParams(); extern void setupDRAM(); extern char ident[]; extern void setLED(int status); void start_main() { // Chip selects, IO registers, and the like setupBoard(); // Setup the DRAM next. We cannot use RAM until this has been done. setLED(LED_STATUS_MEM); setupDRAM(); setLED(LED_STATUS_RUNTIME); setupCRuntime(); /* * Setup the UARTs */ setLED(LED_STATUS_UART); configureConsole(); configureAuxSerial(); #ifdef BOOTDEBUG dprintf("\n\r%s boot...\n\r", ident); #endif /* Set download image default parameters */ setImageParams(); /* * Do user interface stuff that isn't supported in ui.c */ #ifdef CONFIG_UI setLED(LED_STATUS_UI); while (function == DO_NOTHING) { ui(); switch (function) { case DO_NOTHING: break; case DO_LOAD: setLED(LED_STATUS_DLOAD); image_size = load(downloadPort, down_addr); function = DO_NOTHING; /* Stay in command loop */ break; case DO_DECOMPRESS: setLED(LED_STATUS_DDECOMPRESS); decompress(source_addr, image_size, dest_addr); function = DO_NOTHING; /* Stay in command loop */ break; case DO_GO: run(xfer_addr); break; case DO_DECOMP_GO: #ifdef BOOTDEBUG dprintf("Using image at %x\n", source_addr); #endif setLED(LED_STATUS_DDECOMPGO); runimage(source_addr, image_size, dest_addr, xfer_addr); function = DO_NOTHING; /* Stay in command loop */ break; default: case DO_ALL: /* Load and drop into runimage below */ load(downloadPort, down_addr); #ifdef BOOTDEBUG dprintf("Using image at %x\n", down_addr); #endif break; } } #endif /* * Load and run image. Need to deal with compressed images too. */ setLED(LED_STATUS_RUNIMAGE); runimage(source_addr, image_size, dest_addr, xfer_addr); /* Should never get here, but just in case */ setLED(LED_STATUS_ERROR); /* The LEDs indicate an error */ #ifdef BOOTDEBUG dprintf("unable to run image, trying to recover...\n"); #endif recover(); } /*****************************************************************************/ /* * Enable the Software/Bus Watchdog Timer. This will allows us to * trap out of any bad bus or software behavior. This is a fail safe * for the boot up process. If a bad image is loaded this should * get us into the recover routine. */ int enableswt(void) { #if 0 /* * SWT is broken on old mask of 5307 :-( */ volatile unsigned char *mbar; mbar = (volatile unsigned char *) MCF_MBAR; /* Setup vector info for software watchdog */ *((volatile unsigned char *) (mbar + MCFSIM_ICR0)) = 0x1f; *((volatile unsigned long *) (mbar + MCFSIM_IMR)) &= ~0x100; /* Setup watchdog registers */ *((volatile unsigned char *) (mbar + MCFSIM_SWIVR)) = 0x0f; *((volatile unsigned char *) (mbar + MCFSIM_SWSR)) = 0x55; *((volatile unsigned char *) (mbar + MCFSIM_SWSR)) = 0xaa; *((volatile unsigned char *) (mbar + MCFSIM_SYPCR)) = 0x84; *((volatile unsigned char *) (mbar + MCFSIM_SWSR)) = 0x55; *((volatile unsigned char *) (mbar + MCFSIM_SWSR)) = 0xaa; #endif return(0); } /*****************************************************************************/ /* * Disable Watchdog Timer. */ int disableswt(void) { #if 0 /* * SWT is broken on old mask of 5307 :-( */ volatile unsigned char *mbar; mbar = (volatile unsigned char *) MCF_MBAR; *((volatile unsigned char *) (mbar + MCFSIM_SYPCR)) = 0x00; *((volatile unsigned char *) (mbar + MCFSIM_SWSR)) = 0x55; *((volatile unsigned char *) (mbar + MCFSIM_SWSR)) = 0xaa; *((volatile unsigned long *) (mbar + MCFSIM_IMR)) = 0xffffffff; #endif return(0); } /*****************************************************************************/ /* * Set the the DATA and BSS segments for a proper execution * environment. Only required if the code is going to use any * static data. * * Note: We need to copy the Vector table * into RAM starting at 0x00000000 and ending at 0x000003ff * (uClinux likes a writeable vector table :-p) */ void setupCRuntime(void) { extern void _stext, _etext, _sdata, _edata, _sbss, _ebss; extern void _vectors, _version; /* Default to 0x00000000 as the base of RAM */ #ifndef MCF_MEMBASE #define MCF_MEMBASE 0x00000000 #endif // Copy initialized data from ROM to RAM setLED(LED_STATUS_COPYDATA); memcpy(&_sdata, &_etext, (&_edata - &_sdata)); // Zero out uninitialized data setLED(LED_STATUS_ZEROBSS); memset(&_sbss, 0, (&_ebss - &_sbss)); // Copy vector table into RAM setLED(LED_STATUS_INITVEC); memcpy(MCF_MEMBASE, &_vectors, (&_version - &_vectors) + 1); } /*****************************************************************************/ /* * Load the specific image src into [S]DRAM and start it up. * Source to load can be at any address, including FLASH or un-used DRAM. * Control is passed to the loaded image at dest. */ void runimage(unsigned char *src, unsigned int len, unsigned char *dest, unsigned char *xfer) { decompress(src, len, dest); run(xfer); } /* * Decompress or copy the specific image src into [S]DRAM. * Source to load can be at any address, including FLASH or un-used DRAM. */ int decompress(unsigned char *src, unsigned int len, unsigned char *dest) { /* * Figure out if this is a compressed image, or just a strait * up binary. Either way get it loaded into RAM for execution. */ setLED(LED_STATUS_DECOMP1); if ((src[0] == 037) && ((src[1] == 0213) || (src[1] == 0236))) { setLED(LED_STATUS_ENCACHE); enableCache(); setLED(LED_STATUS_DECOMP2); decompress_image(src, dest, len); } else { setLED(LED_STATUS_LOADIMG); loadimage((unsigned long *) src, (unsigned long *) dest, len); } return(0); } /*****************************************************************************/ int run(unsigned char *dest) { setLED(LED_STATUS_ENSWT); enableswt(); setLED(LED_STATUS_STARTIMG); xfer_addr = dest; startimage(); return(0); } /* * Image is a normal binary, so just copy it to the start address. */ int loadimage(unsigned long *src, unsigned long *dst, unsigned int len) { unsigned long *end; // unsigned int cksum; len = len >> 2; end = src + len; // cksum = 0; while (src < end) { // cksum += *src; *dst++ = *src++; } #if 0 if (cksum) recover(); #endif return(0); } /* * For some reason the boot loader has decided that it has to enter * a safe recovery state. Could be bad FLASH image, maybe some broken * hardware. Whatever it is, FLASH the LEDs and try to do a serial * load into RAM. * * The serial data loader will timeout after 5 seconds, or so, of * no data and the attempt to run what it has loaded. It can be a * compressed image, or a normal binary. */ void recover() { /* Probably got here due to the watchdog, so disable now. */ disableswt(); disableCache(); configureConsole(); configureAuxSerial(); load(downloadPort, (unsigned char *)xfer_addr); run((unsigned char *)xfer_addr); } /* * Download image from serial port */ int load(int port, unsigned char *download_addr) { unsigned char *src, *sp; unsigned char led; int tick, chrtimeout; int char_count; #ifdef BOOTDEBUG dprintf("load: %s download to %x\n", ident, download_addr); #endif setLED(LED_STATUS_LOAD1); tick = 0; chrtimeout = 0; led = 0xff; char_count = 0; src = sp = download_addr; for (;;) { if (rs_is_char_port(port)) { *src++ = rs_get_char_port(port); char_count++; chrtimeout = 0; tick += 0x25; } if (tick++ > 0x8000) { tick = 0; led ^= 0xff; if (char_count != 0) { if (chrtimeout++ > 4) break; led |= 0xc3; } setLED(led); } } setLED(LED_STATUS_LOAD2); #ifdef BOOTDEBUG dprintf("Downloaded %d bytes\n", char_count); #endif return(char_count); } int atexit (void *foo) { return 0; }