From: Erik M. <er...@us...> - 2001-08-06 22:44:55
|
Update of /cvsroot/blob/blob/src In directory usw-pr-cvs1:/tmp/cvs-serv26030/src Modified Files: Makefile.am clock.c command.c flash.c led.c main.c serial.c start.S time.c util.c uucodec.c Added Files: flashasm.S ledasm.S linux.c memory.c memsetup.S rest-ld-script start-ld-script testmem.S testmem2.S trampoline.S Removed Files: ld-script Log Message: Here we go: merge the blob_1_0_9_hack branch back into the HEAD branch Index: flashasm.S =================================================================== RCS file: flashasm.S diff -N flashasm.S --- /dev/null Thu May 24 22:33:05 2001 +++ /tmp/cvsgmVRnq Mon Aug 6 15:44:54 2001 @@ -0,0 +1,190 @@ +/* + * flashasm.S: flash magic for LART + * + * Copyright (C) 1999 2000 2001 Jan-Derk bakker (J.D...@it...) + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +.ident "$Id$" + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +.text + + +.globl data_to_flash +.globl data_from_flash + /* Subroutine that takes data in r0 and formats it so it will be in */ + /* the correct order for the internal flash */ + /* used for LART only */ +data_to_flash: +#if defined LART + mov r1, #0x0 + + tst r0, #0x00000001 + orrne r1, r1, #0x00001000 + tst r0, #0x00000002 + orrne r1, r1, #0x00004000 + tst r0, #0x00000004 + orrne r1, r1, #0x00000800 + tst r0, #0x00000008 + orrne r1, r1, #0x00000200 + tst r0, #0x00000010 + orrne r1, r1, #0x00000001 + tst r0, #0x00000020 + orrne r1, r1, #0x00000004 + tst r0, #0x00000040 + orrne r1, r1, #0x00000080 + tst r0, #0x00000080 + orrne r1, r1, #0x00000020 + + tst r0, #0x00000100 + orrne r1, r1, #0x00002000 + tst r0, #0x00000200 + orrne r1, r1, #0x00008000 + tst r0, #0x00000400 + orrne r1, r1, #0x00000400 + tst r0, #0x00000800 + orrne r1, r1, #0x00000100 + tst r0, #0x00001000 + orrne r1, r1, #0x00000002 + tst r0, #0x00002000 + orrne r1, r1, #0x00000008 + tst r0, #0x00004000 + orrne r1, r1, #0x00000040 + tst r0, #0x00008000 + orrne r1, r1, #0x00000010 + + tst r0, #0x00010000 + orrne r1, r1, #0x00100000 + tst r0, #0x00020000 + orrne r1, r1, #0x00400000 + tst r0, #0x00040000 + orrne r1, r1, #0x00080000 + tst r0, #0x00080000 + orrne r1, r1, #0x00020000 + tst r0, #0x00100000 + orrne r1, r1, #0x01000000 + tst r0, #0x00200000 + orrne r1, r1, #0x04000000 + tst r0, #0x00400000 + orrne r1, r1, #0x80000000 + tst r0, #0x00800000 + orrne r1, r1, #0x20000000 + + tst r0, #0x01000000 + orrne r1, r1, #0x00200000 + tst r0, #0x02000000 + orrne r1, r1, #0x00800000 + tst r0, #0x04000000 + orrne r1, r1, #0x00040000 + tst r0, #0x08000000 + orrne r1, r1, #0x00010000 + tst r0, #0x10000000 + orrne r1, r1, #0x02000000 + tst r0, #0x20000000 + orrne r1, r1, #0x08000000 + tst r0, #0x40000000 + orrne r1, r1, #0x40000000 + tst r0, #0x80000000 + orrne r1, r1, #0x10000000 + + mov r0, r1 +#endif + mov pc, r14 + + /* Takes data received from the flash, and unshuffles it. */ +data_from_flash: +#if defined LART + mov r1, #0x00 + + tst r0, #0x00000001 + orrne r1, r1, #0x00000010 + tst r0, #0x00000002 + orrne r1, r1, #0x00001000 + tst r0, #0x00000004 + orrne r1, r1, #0x00000020 + tst r0, #0x00000008 + orrne r1, r1, #0x00002000 + tst r0, #0x00000010 + orrne r1, r1, #0x00008000 + tst r0, #0x00000020 + orrne r1, r1, #0x00000080 + tst r0, #0x00000040 + orrne r1, r1, #0x00004000 + tst r0, #0x00000080 + orrne r1, r1, #0x00000040 + + tst r0, #0x00000100 + orrne r1, r1, #0x00000800 + tst r0, #0x00000200 + orrne r1, r1, #0x00000008 + tst r0, #0x00000400 + orrne r1, r1, #0x00000400 + tst r0, #0x00000800 + orrne r1, r1, #0x00000004 + tst r0, #0x00001000 + orrne r1, r1, #0x00000001 + tst r0, #0x00002000 + orrne r1, r1, #0x00000100 + tst r0, #0x00004000 + orrne r1, r1, #0x00000002 + tst r0, #0x00008000 + orrne r1, r1, #0x00000200 + + tst r0, #0x00010000 + orrne r1, r1, #0x08000000 + tst r0, #0x00020000 + orrne r1, r1, #0x00080000 + tst r0, #0x00040000 + orrne r1, r1, #0x04000000 + tst r0, #0x00080000 + orrne r1, r1, #0x00040000 + tst r0, #0x00100000 + orrne r1, r1, #0x00010000 + tst r0, #0x00200000 + orrne r1, r1, #0x01000000 + tst r0, #0x00400000 + orrne r1, r1, #0x00020000 + tst r0, #0x00800000 + orrne r1, r1, #0x02000000 + + tst r0, #0x01000000 + orrne r1, r1, #0x00100000 + tst r0, #0x02000000 + orrne r1, r1, #0x10000000 + tst r0, #0x04000000 + orrne r1, r1, #0x00200000 + tst r0, #0x08000000 + orrne r1, r1, #0x20000000 + tst r0, #0x10000000 + orrne r1, r1, #0x80000000 + tst r0, #0x20000000 + orrne r1, r1, #0x00800000 + tst r0, #0x40000000 + orrne r1, r1, #0x40000000 + tst r0, #0x80000000 + orrne r1, r1, #0x00400000 + + mov r0, r1 +#endif + mov pc, r14 + + + Index: ledasm.S =================================================================== RCS file: ledasm.S diff -N ledasm.S --- /dev/null Thu May 24 22:33:05 2001 +++ /tmp/cvsVaCKDr Mon Aug 6 15:44:54 2001 @@ -0,0 +1,82 @@ +/* + * ledasm.S: simple LED control code + * + * Copyright (C) 2001 Erik Mouw (J.A...@it...) + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +/* + * Documentation: + * [1] Intel Corporation, "Intel StrongARM SA-1100 Microprocessor + * Developer's Manual", April 1999 + * [2] Intel Corporation, "Intel StrongARM SA-1110 Microprocessor + * Advanced Developer's manual, December 1999 + */ + +.ident "$Id$" + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#define ASSEMBLY +#include "led.h" + + + +.text + +LED: .long LED_GPIO +GPIO_BASE: .long 0x90040000 +#define GPDR 0x00000004 +#define GPSR 0x00000008 +#define GPCR 0x0000000c + + + + +.globl ledinit + /* initialise LED GPIO and turn LED on. + * clobbers r0 and r1 + */ +ledinit: + ldr r0, GPIO_BASE + ldr r1, LED + str r1, [r0, #GPDR] /* LED GPIO is output */ + str r1, [r0, #GPSR] /* turn LED on */ + mov pc, lr + + + + +.globl led_on + /* turn LED on. clobbers r0 and r1 */ +led_on: + ldr r0, GPIO_BASE + ldr r1, LED + str r1, [r0, #GPSR] + mov pc, lr + + + + +.globl led_off + /* turn LED off. clobbers r0 and r1 */ +led_off: + ldr r0, GPIO_BASE + ldr r1, LED + str r1, [r0, #GPCR] + mov pc, lr Index: linux.c =================================================================== RCS file: linux.c diff -N linux.c --- /dev/null Thu May 24 22:33:05 2001 +++ /tmp/cvsmK81Iq Mon Aug 6 15:44:54 2001 @@ -0,0 +1,169 @@ +/* + * linux.c: support functions for booting a kernel + * + * Copyright (C) 2001 Erik Mouw (J.A...@it...) + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ident "$Id$" + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "linux.h" +#include "main.h" +#include "flash.h" +#include "memory.h" +#include "serial.h" +#include "util.h" + +#include <asm/setup.h> + + +static void setup_start_tag(void); +static void setup_memory_tags(void); +static void setup_commandline_tag(char *commandline); +static void setup_ramdisk_tag(void); +static void setup_initrd_tag(void); +static void setup_end_tag(void); + + +static struct tag *params; + + +void boot_linux(char *commandline) +{ + register u32 i; + void (*theKernel)(int zero, int arch) = (void (*)(int, int))KERNEL_RAM_BASE; + + setup_start_tag(); + setup_memory_tags(); + setup_commandline_tag(commandline); + setup_initrd_tag(); + setup_ramdisk_tag(); + setup_end_tag(); + + /* we assume that the kernel is in place */ + SerialOutputString("\nStarting kernel ...\n\n"); + + /* turn off I-cache */ + asm ("mrc p15, 0, %0, c1, c0, 0": "=r" (i)); + i &= ~0x1000; + asm ("mcr p15, 0, %0, c1, c0, 0": : "r" (i)); + + /* flush I-cache */ + asm ("mcr p15, 0, %0, c7, c5, 0": : "r" (i)); + + theKernel(0, ARCH_NUMBER); + + SerialOutputString("Hey, the kernel returned! This should not happen.\n"); +} + + +static void setup_start_tag(void) +{ + params = (struct tag *)BOOT_PARAMS; + + params->hdr.tag = ATAG_CORE; + params->hdr.size = tag_size(tag_core); + + params->u.core.flags = 0; + params->u.core.pagesize = 0; + params->u.core.rootdev = 0; + + params = tag_next(params); +} + + +static void setup_memory_tags(void) +{ + int i; + + for(i = 0; i < NUM_MEM_AREAS; i++) { + if(memory_map[i].used) { + params->hdr.tag = ATAG_MEM; + params->hdr.size = tag_size(tag_mem32); + + params->u.mem.start = memory_map[i].start; + params->u.mem.size = memory_map[i].len; + + params = tag_next(params); + } + } +} + + +static void setup_commandline_tag(char *commandline) +{ + char *p; + + /* eat leading white space */ + for(p = commandline; *p == ' '; p++) + ; + + /* skip non-existent command lines so the kernel will still + * use its default command line. + */ + if(*p == '\0') + return; + + params->hdr.tag = ATAG_CMDLINE; + params->hdr.size = (sizeof(struct tag_header) + strlen(p) + 1 + 4) >> 2; + + strcpy(params->u.cmdline.cmdline, p); + + params = tag_next(params); +} + + +static void setup_initrd_tag(void) +{ + /* an ATAG_INITRD node tells the kernel where the compressed + * ramdisk can be found. ATAG_RDIMG is a better name, actually. + */ + params->hdr.tag = ATAG_INITRD; + params->hdr.size = tag_size(tag_initrd); + + params->u.initrd.start = RAMDISK_RAM_BASE; + params->u.initrd.size = INITRD_LEN; + + params = tag_next(params); +} + + +static void setup_ramdisk_tag(void) +{ + /* an ATAG_RAMDISK node tells the kernel how large the + * decompressed ramdisk will become. + */ + params->hdr.tag = ATAG_RAMDISK; + params->hdr.size = tag_size(tag_ramdisk); + + params->u.ramdisk.start = 0; + params->u.ramdisk.size = RAMDISK_SIZE; + params->u.ramdisk.flags = 1; /* automatically load ramdisk */ + + params = tag_next(params); +} + + +static void setup_end_tag(void) +{ + params->hdr.tag = ATAG_NONE; + params->hdr.size = 0; +} Index: memory.c =================================================================== RCS file: memory.c diff -N memory.c --- /dev/null Thu May 24 22:33:05 2001 +++ /tmp/cvswY83qs Mon Aug 6 15:44:54 2001 @@ -0,0 +1,115 @@ +/* + * memory.c: memory test routines for the blob bootloader + * + * Copyright (C) 2001 Erik Mouw (J.A...@it...) + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ident "$Id$" + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "main.h" +#include "memory.h" +#include "serial.h" + +/* test in 1MB chunks */ +#define TEST_BLOCK_SIZE (1024 * 1024) + + + + +/* from testmem2.S */ +extern int testram(u32 addr); + + + + +memory_area_t memory_map[NUM_MEM_AREAS]; + + + + +void get_memory_map(void) +{ + u32 addr; + int i; + + /* init */ + for(i = 0; i < NUM_MEM_AREAS; i++) + memory_map[i].used = 0; + + /* first write a 0 to all memory locations */ + for(addr = MEMORY_START; addr < MEMORY_END; addr += TEST_BLOCK_SIZE) + * (u32 *)addr = 0; + + /* scan memory in blocks */ + i = 0; + for(addr = MEMORY_START; addr < MEMORY_END; addr += TEST_BLOCK_SIZE) { + if(testram(addr) == 0) { + /* yes, memory */ + if(* (u32 *)addr != 0) { /* alias? */ +#ifdef BLOB_DEBUG + SerialOutputString("Detected alias at 0x"); + SerialOutputHex(addr); + SerialOutputString(", aliased from 0x"); + SerialOutputHex(* (u32 *)addr); + SerialOutputByte('\n'); +#endif + if(memory_map[i].used) + i++; + + continue; + } + + /* not an alias, write the current address */ + * (u32 *)addr = addr; +#ifdef BLOB_DEBUG + SerialOutputString("Detected memory at 0x"); + SerialOutputHex(addr); + SerialOutputByte('\n'); +#endif + /* does this start a new block? */ + if(memory_map[i].used == 0) { + memory_map[i].start = addr; + memory_map[i].len = TEST_BLOCK_SIZE; + memory_map[i].used = 1; + } else { + memory_map[i].len += TEST_BLOCK_SIZE; + } + } else { + /* no memory here */ + if(memory_map[i].used == 1) + i++; + } + } + + SerialOutputString("Memory map:\n"); + for(i = 0; i < NUM_MEM_AREAS; i++) { + if(memory_map[i].used) { + SerialOutputString(" 0x"); + SerialOutputHex(memory_map[i].len); + SerialOutputString(" @ 0x"); + SerialOutputHex(memory_map[i].start); + SerialOutputString(" ("); + SerialOutputDec(memory_map[i].len / (1024 * 1024)); + SerialOutputString(" MB)\n"); + } + } +} Index: memsetup.S =================================================================== RCS file: memsetup.S diff -N memsetup.S --- /dev/null Thu May 24 22:33:05 2001 +++ /tmp/cvsjPbkQr Mon Aug 6 15:44:54 2001 @@ -0,0 +1,219 @@ +/* + * memsetup.S: memory setup for various architectures + * + * Copyright (C) 1999 2000 2001 Erik Mouw (J.A...@it...) and + * Jan-Derk Bakker (J.D...@it...) + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +/* + * Documentation: + * [1] Intel Corporation, "Intel StrongARM SA-1100 Microprocessor + * Developer's Manual", April 1999 + * [2] Intel Corporation, "Intel StrongARM SA-1110 Microprocessor + * Advanced Developer's manual, December 1999 + */ + +.ident "$Id$" + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + + + + +.text + + + + +MEM_BASE: .long 0xa0000000 +MEM_START: .long 0xc0000000 +#define MDCNFG 0x0 +#define MDCAS0 0x04 +#define MDCAS1 0x08 +#define MDCAS2 0x0c +#define MCS0 0x10 + + + + +#if (defined BRUTUS) +mdcas0: .long 0xc71c703f +mdcas1: .long 0xffc71c71 +mdcas2: .long 0xffffffff +mdcnfg: .long 0x0334b22f +mcs0: .long 0xfff8fff8 +#endif + +#if (defined NESA) +mdcas0: .long 0xc71c703f +mdcas1: .long 0xffc71c71 +mdcas2: .long 0xffffffff +mdcnfg: .long 0x0334b22f +mcs0: .long 0xfff84458 +#endif + +#if defined LART +mdcas0: .long 0xc71c703f +mdcas1: .long 0xffc71c71 +mdcas2: .long 0xffffffff +mdcnfg: .long 0x0334b22f +mcs0: .long 0xad8c4888 +#endif + +#if defined PLEB +mdcas0: .long 0x1c71c01f +mdcas1: .long 0xff1c71c7 +mdcas2: .long 0xffffffff +mdcnfg: .long 0x0c7f3ca3 +mcs0: .long 0xfff8fff8 +#endif + +#if defined SHANNON +mdcas0: .long 0xc71c703f +mdcas1: .long 0xffc71c71 +mdcas2: .long 0xffffffff +mdcnfg: .long 0x0334b21f +mcs0: .long 0xfff84458 +#endif + + +.globl memsetup +memsetup: +#if defined USE_SA1100 + /* Setup the flash memory */ + ldr r0, MEM_BASE + + ldr r1, mcs0 + str r1, [r0, #MCS0] + + /* Set up the DRAM */ + + /* MDCAS0 */ + ldr r1, mdcas0 + str r1, [r0, #MDCAS0] + + /* MDCAS1 */ + ldr r1, mdcas1 + str r1, [r0, #MDCAS1] + + /* MDCAS2 */ + ldr r1, mdcas2 + str r1, [r0, #MDCAS2] + + /* MDCNFG */ + ldr r1, mdcnfg + str r1, [r0, #MDCNFG] + + /* Issue read requests to disabled bank to start refresh */ + /* this is required by the Micron memory on a TuxScreen */ + + /* Comment from JDB: + * This is not strictly necessary. As long as blob writes something to + * the serial port between enabling and accessing DRAM (as I think it + * does even on Shannon), you can pretty much guarantee that the + * required eight refreshes have occurred (as 1 refresh is ~16 + * microseconds, so even writing two characters at 115k2 covers the + * refreshes). + * + * Comment (on comment) from Erik: + * We don't print anymore in the low level loader, so we need this + * on all architectures. + */ + ldr r1, MEM_START + +.rept 8 + ldr r0, [r1] +.endr + + +#elif defined USE_SA1110 + /* This part is actually for the Assabet only. If your board + * uses other settings, you'll have to ifdef them here. + */ + /* Set up the SDRAM */ + mov r1, #0xA0000000 /* MDCNFG base address */ + + ldr r2, =0xAAAAAA7F + str r2, [r1, #0x04] /* MDCAS00 */ + str r2, [r1, #0x20] /* MDCAS20 */ + + ldr r2, =0xAAAAAAAA + str r2, [r1, #0x08] /* MDCAS01 */ + str r2, [r1, #0x24] /* MDCAS21 */ + + ldr r2, =0xAAAAAAAA + str r2, [r1, #0x0C] /* MDCAS02 */ + str r2, [r1, #0x28] /* MDCAS22 */ + + ldr r2, =0x4dbc0327 /* MDREFR */ + str r2, [r1, #0x1C] + + ldr r2, =0x72547254 /* MDCNFG */ + str r2, [r1, #0x00] + + /* Issue read requests to disabled bank to start refresh */ + + ldr r1, =0xC0000000 + +.rept 8 + ldr r0, [r1] +.endr + + mov r1, #0xA0000000 /* MDCNFG base address */ + + ldr r2, =0x72547255 /* Enable the banks */ + str r2, [r1, #0x00] /* MDCNFG */ + +/* Static memory chip selects on Assabet: */ + + ldr r2, =0x4b90 /* MCS0 */ + orr r2,r2,r2,lsl #16 + str r2, [r1, #0x10] + + ldr r2, =0x22212419 /* MCS1 */ + str r2, [r1, #0x14] + + ldr r2, =0x42196669 /* MCS2 */ + str r2, [r1, #0x2C] + + ldr r2, =0xafccafcc /* SMCNFG */ + str r2, [r1, #0x30] + +/* Set up PCMCIA space */ + + ldr r2, =0x994a994a + str r2, [r1, #0x18] + +/* All SDRAM memory settings should be ready to go... */ +/* For best performance, should fill out remaining memory config regs: */ + + + /* Testing ,Chester */ + mov r3,#0x12000000 + mov r2,#0x5000 /* D9_LED on and D8_LED off */ + str r2,[r3] + mov r4, #0x20000 +gogogo2: + subs r4, r4, #1 + bne gogogo2 +#else +#error "Configuration error: CPU not defined!" +#endif + + mov pc, lr Index: rest-ld-script =================================================================== RCS file: rest-ld-script diff -N rest-ld-script --- /dev/null Thu May 24 22:33:05 2001 +++ /tmp/cvs0UaYCt Mon Aug 6 15:44:54 2001 @@ -0,0 +1,35 @@ +/*------------------------------------------------------------------------- + * Filename: rest-ld-script + * Version: $Id$ + * Copyright: Copyright (C) 1999, Erik Mouw + * Author: Erik Mouw <J.A...@it...> + * Description: ld (linker) script to make the blob bootlader. + * Heavily inspired by the Linux kernel linker scripts. + * Created at: Tue Aug 24 17:24:06 1999 + * Modified by: Erik Mouw <J.A...@it...> + * Modified at: Sun Aug 29 14:45:54 1999 + *-----------------------------------------------------------------------*/ +/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/ +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_trampoline) +SECTIONS +{ + . = 0xc0000400; + + . = ALIGN(4); + .text : { *(.text) } + + . = ALIGN(4); + .rodata : { *(.rodata) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + .got : { *(.got) } + + . = ALIGN(4); + .bss : { *(.bss) } +} + Index: start-ld-script =================================================================== RCS file: start-ld-script diff -N start-ld-script --- /dev/null Thu May 24 22:33:05 2001 +++ /tmp/cvs3NCYUs Mon Aug 6 15:44:54 2001 @@ -0,0 +1,35 @@ +/*------------------------------------------------------------------------- + * Filename: ld-script + * Version: $Id$ + * Copyright: Copyright (C) 1999, Erik Mouw + * Author: Erik Mouw <J.A...@it...> + * Description: ld (linker) script to make the blob bootlader. + * Heavily inspired by the Linux kernel linker scripts. + * Created at: Tue Aug 24 17:24:06 1999 + * Modified by: Erik Mouw <J.A...@it...> + * Modified at: Sun Aug 29 14:45:54 1999 + *-----------------------------------------------------------------------*/ +/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/ +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : { *(.text) } + + . = ALIGN(4); + .rodata : { *(.rodata) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + .got : { *(.got) } + + . = ALIGN(4); + .bss : { *(.bss) } +} + Index: testmem.S =================================================================== RCS file: testmem.S diff -N testmem.S --- /dev/null Thu May 24 22:33:05 2001 +++ /tmp/cvsgiOEHu Mon Aug 6 15:44:54 2001 @@ -0,0 +1,56 @@ +/* + * testmem.S: memory tester, test if there is RAM available at given location + * + * Copyright (C) 2001 Russell King (rm...@ar...) + * + * This version clobbers registers r1-r4, so be sure to store their contents + * in a safe position. This function is not APCS compliant, so only use it + * from assembly code. + * + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +.ident "$Id$" + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +.text +.globl testram + @ r0 = address to test + @ returns r0 = 0 - ram present, r0 = 1 - no ram + @ clobbers r1 - r4 +testram: + ldmia r0, {r1, r2} @ store current value in r1 and r2 + mov r3, #0x55 @ write 0x55 to first word + mov r4, #0xaa @ 0xaa to second + stmia r0, {r3, r4} + ldmia r0, {r3, r4} @ read it back + teq r3, #0x55 @ do the values match + teqeq r4, #0xaa + bne bad @ oops, no + mov r3, #0xaa @ write 0xaa to first word + mov r4, #0x55 @ 0x55 to second + stmia r0, {r3, r4} + ldmia r0, {r3, r4} @ read it back + teq r3, #0xaa @ do the values match + teqeq r4, #0x55 +bad: stmia r0, {r1, r2} @ in any case, restore old data + moveq r0, #0 @ ok - all values matched + movne r0, #1 @ no ram at this location + mov pc, lr Index: testmem2.S =================================================================== RCS file: testmem2.S diff -N testmem2.S --- /dev/null Thu May 24 22:33:05 2001 +++ /tmp/cvsXfq68t Mon Aug 6 15:44:54 2001 @@ -0,0 +1,56 @@ +/* + * testmem2.S: memory tester, test if there is RAM available at given location + * + * Copyright (C) 2001 Russell King (rm...@ar...) + * + * This version doesn't clobber registers r1-r4, so it's safe to call it from + * C code (fits nicely into the APCS specs). + * + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +.ident "$Id$" + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +.text +.globl testram + @ r0 = address to test + @ returns r0 = 0 - ram present, r0 = 1 - no ram + @ doesnt clobber r1 - r4 +testram: + stmdb sp!, {r1-r4, lr} + ldmia r0, {r1, r2} + mov r3, #0x55 @ write 0x55 to first word + mov r4, #0xaa @ 0xaa to second + stmia r0, {r3, r4} + ldmia r0, {r3, r4} @ read it back + teq r3, #0x55 @ do the values match + teqeq r4, #0xaa + bne bad @ oops, no + mov r3, #0xaa @ write 0xaa to first word + mov r4, #0x55 @ 0x55 to second + stmia r0, {r3, r4} + ldmia r0, {r3, r4} @ read it back + teq r3, #0xaa @ do the values match + teqeq r4, #0x55 +bad: stmia r0, {r1, r2} @ in any case, restore old data + moveq r0, #0 @ ok - all values matched + movne r0, #1 @ no ram at this location + ldmia sp!, {r1-r4, pc} Index: trampoline.S =================================================================== RCS file: trampoline.S diff -N trampoline.S --- /dev/null Thu May 24 22:33:05 2001 +++ /tmp/cvsOKfmKv Mon Aug 6 15:44:54 2001 @@ -0,0 +1,34 @@ +/* + * trampoline.S: start of second stage boot loader, jump from assembly to C + * + * Copyright (C) 2001 Erik Mouw (J.A...@it...) + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +.ident "$Id$" + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +.text + +.globl _trampoline +_trampoline: + bl main + /* if main ever returns we just call it again */ + b _trampoline Index: Makefile.am =================================================================== RCS file: /cvsroot/blob/blob/src/Makefile.am,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- Makefile.am 2001/06/27 19:47:42 1.1.1.1 +++ Makefile.am 2001/08/06 22:44:52 1.2 @@ -12,46 +12,94 @@ bin_PROGRAMS = \ - blob-elf32 \ + blob-start-elf32 \ + blob-start \ + blob-rest-elf32 \ + blob-rest \ blob +# First specify how to build the first stage loader + # WARNING: start.S *must* be the first file, otherwise the target will # be linked in the wrong order! -blob_elf32_SOURCES = \ +blob_start_elf32_SOURCES = \ start.S \ + memsetup.S \ + ledasm.S \ + testmem.S + + +blob_start_elf32_LDFLAGS += \ + -Wl,-T,${top_srcdir}/src/start-ld-script + +blob_start_elf32_LDADD += \ + -lgcc + + +blob_start_SOURCES = + + +blob-start: blob-start-elf32 + $(OBJCOPY) $(OCFLAGS) $< $@ + + +# Now specify how to build the second stage loader + +blob_rest_elf32_SOURCES = \ + trampoline.S \ + flashasm.S \ + testmem2.S \ clock.c \ command.c \ - main.c \ flash.c \ + led.c \ + linux.c \ + main.c \ + memory.c \ serial.c \ time.c \ util.c \ uucodec.c -blob_SOURCES = +blob_rest_elf32_LDFLAGS += \ + -Wl,-T,${top_srcdir}/src/rest-ld-script -EXTRA_DIST = \ - ld-script +blob_rest_elf32_LDADD += \ + -lgcc -blob_elf32_LDFLAGS += \ - -Wl,-T,${top_srcdir}/src/ld-script +blob_rest_SOURCES = -blob_elf32_LDADD += \ - -lgcc +blob-rest: blob-rest-elf32 + $(OBJCOPY) $(OCFLAGS) $< $@ + + +# Finally specify how to build the full binary + +blob_SOURCES = + +blob: blob-start blob-rest + rm -f $@ + dd if=blob-start of=$@ bs=1k conv=sync + dd if=blob-rest of=$@ bs=1k seek=1 + chmod +x blob + +# automake administrativia + +EXTRA_DIST = \ + start-ld-script \ + rest-ld-script + + INCLUDES += \ -I${top_builddir}/include \ -I${top_srcdir}/include - - -blob: blob-elf32 - $(OBJCOPY) $(OCFLAGS) $< $@ CLEANFILES = *~ Index: clock.c =================================================================== RCS file: /cvsroot/blob/blob/src/clock.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- clock.c 2001/06/27 19:47:42 1.1.1.1 +++ clock.c 2001/08/06 22:44:52 1.2 @@ -36,12 +36,11 @@ #endif #include "types.h" -#include "util.h" +#include "sa1100.h" #include "serial.h" #include "time.h" +#include "util.h" -#define __ASM_ARCH_HARDWARE_H -#include <asm/arch-sa1100/SA-1100.h> /* It should be possible to improve this function */ /* Determine if the given character is a 0 to 9 or a to z, Index: command.c =================================================================== RCS file: /cvsroot/blob/blob/src/command.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- command.c 2001/06/27 19:47:42 1.1.1.1 +++ command.c 2001/08/06 22:44:52 1.2 @@ -65,6 +65,8 @@ int numRead; int maxRead = len - 1; + TimerClearOverflow(); + startTime = TimerGetTime(); for(numRead = 0, i = 0; numRead < maxRead;) { @@ -85,7 +87,7 @@ command[i++] = '\0'; /* print newline */ - SerialOutputByte('\r'); + SerialOutputByte('\n'); return(numRead); } else if(c == '\b') { /* FIXME: is this backspace? */ if(i > 0) { Index: flash.c =================================================================== RCS file: /cvsroot/blob/blob/src/flash.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- flash.c 2001/06/27 19:47:42 1.1.1.1 +++ flash.c 2001/08/06 22:44:52 1.2 @@ -35,6 +35,7 @@ # include "config.h" #endif +#include "led.h" #include "main.h" #include "util.h" #include "serial.h" @@ -114,6 +115,22 @@ u32 data_from_flash(u32 what); u32 data_to_flash(u32 what); +#if defined SHANNON || defined NESA +#define READ_ARRAY 0x00F000F0 +#define UNLOCK1 0x00AA00AA +#define UNLOCK2 0x00550055 +#define ERASE_SETUP 0x00800080 +#define ERASE_CONFIRM 0x00300030 +#define PGM_SETUP 0x00A000A0 +#define UNLOCK_BYPASS 0x00200020 +#define FLASH_ADDR1 (0x00000555 << 2) +#define FLASH_ADDR2 (0x000002AA << 2) +#define ERASE_DONE 0x00800080 +#define RDY_MASK 0x00800080 +#define STATUS_PGM_ERR 0x00200020 +#define STATUS_ERASE_ERR 0x00000001 + +#else #define READ_ARRAY 0x00FF00FF #define ERASE_SETUP 0x00200020 #define ERASE_CONFIRM 0x00D000D0 @@ -123,34 +140,42 @@ #define STATUS_BUSY 0x00800080 #define STATUS_ERASE_ERR 0x00200020 #define STATUS_PGM_ERR 0x00100010 - - +#endif void EraseBlocks(tBlockType which) { char *thisBlock; int numBlocks, i; - if(RunningFromInternal()) { - SerialOutputString("*** Can't erase -- running from internal flash.\r"); - return; - } - - if(which == blKernel) { + switch(which) { + case blBlob: + thisBlock = (char *)BLOB_START; + numBlocks = NUM_BLOB_BLOCKS; + break; + + case blKernel: thisBlock = (char *)KERNEL_START; numBlocks = NUM_KERNEL_BLOCKS; - } else { + break; + + case blRamdisk: thisBlock = (char *)INITRD_START; numBlocks = NUM_INITRD_BLOCKS; + break; + + default: + /* this should not happen */ + return; } for(i = 0; i < numBlocks; i++, thisBlock += MAIN_BLOCK_SIZE) { SerialOutputByte('.'); + led_toggle(); if((EraseOne(thisBlock) & STATUS_ERASE_ERR) != 0) { - SerialOutputString("\r*** Erase error at address 0x"); + SerialOutputString("\n*** Erase error at address 0x"); SerialOutputHex((u32)thisBlock); - SerialOutputByte('\r'); + SerialOutputByte('\n'); return; } } @@ -164,25 +189,42 @@ volatile u32 *flashBase; u32 result; int maxLength, i; +#if defined SHANNON || defined NESA +#define READY 1 +#define ERR 2 + int chip1, chip2; +#endif if((u32)source & 0x03) { SerialOutputString("*** Source is not on a word boundary: 0x"); SerialOutputHex((u32)source); - SerialOutputByte('\r'); + SerialOutputByte('\n'); return; } if(length & 0x03) length += 0x04; length &= ~((u32) 0x03); - - if(type == blKernel) { + + switch(type) { + case blBlob: + flashBase = (u32 *)BLOB_START; + maxLength = BLOB_LEN; + break; + + case blKernel: flashBase = (u32 *)KERNEL_START; maxLength = KERNEL_LEN; - } - else { + break; + + case blRamdisk: flashBase = (u32 *)INITRD_START; maxLength = INITRD_LEN; + break; + + default: + /* this should not happen */ + return; } if(length > maxLength) @@ -195,16 +237,53 @@ SerialOutputHex((u32)source); SerialOutputString(" to 0x"); SerialOutputHex((u32)flashBase); - SerialOutputByte('\r'); + SerialOutputByte('\n'); #endif + +#if defined SHANNON || defined NESA + *(u32 *)FLASH_ADDR1 = data_to_flash(UNLOCK1); + *(u32 *)FLASH_ADDR2 = data_to_flash(UNLOCK2); + *(u32 *)FLASH_ADDR1 = data_to_flash(UNLOCK_BYPASS); +#endif for(i = 0; i < length; i+= 4, flashBase++, source++) { - if((i % MAIN_BLOCK_SIZE) == 0) + if((i % MAIN_BLOCK_SIZE) == 0) { SerialOutputByte('.'); + led_toggle(); + } *flashBase = data_to_flash(PGM_SETUP); *flashBase = *source; +#if defined SHANNON || defined NESA + + /* This is a pretty similar situation to the erasing status below + * Bit 7 is ~(data bit 7) until the flash is complete. If bit 5 + * gets set before this happens, there is an error, but this could + * happen near the clock edge, and bit 5 could be the actual data + * before bit 7 changes, so we have to read again. + */ + chip1 = chip2 = 0; + do { + result = data_from_flash(*flashBase); + + if (!chip1 && ((result & 0x80) == (*source & 0x80))) chip1 = READY; + if (!chip1 && ((result & 0xFFFF) & STATUS_PGM_ERR)) { + result = data_from_flash(*flashBase); + if ((result & 0x80) == (*source & 0x80)) chip1 = READY; + else chip1 = ERR; + } + if (!chip2 && ((result & (0x80 << 16)) == (*source & (0x80 << 16)))) chip2 = READY; + if (!chip2 && ((result >> 16) & STATUS_PGM_ERR)) { + result = data_from_flash(*flashBase); + if ((result & (0x80 << 16)) == (*source & (0x80 << 16))) chip2 = READY; + else chip2 = ERR; + } + + } while (!chip1 || !chip2); + + if (chip1 == ERR || chip2 == ERR || *flashBase != *source) { +#else do { *flashBase = data_to_flash(STATUS_READ); result = data_from_flash(*flashBase); @@ -213,17 +292,21 @@ *flashBase = data_to_flash(READ_ARRAY); if((result & STATUS_PGM_ERR) != 0 || *flashBase != *source) { - SerialOutputString("\r*** Write error at address 0x"); +#endif + SerialOutputString("\n*** Write error at address 0x"); SerialOutputHex((u32)flashBase); - SerialOutputByte('\r'); + SerialOutputByte('\n'); return; } } + +#if defined SHANNON || defined NESA + *(u32 *)FLASH_ADDR1 = data_to_flash(READ_ARRAY); +#endif } /* WriteBlocksFromMem */ - static u32 EraseOne(const char *whichOne) { /* Routine to erase one block of flash */ @@ -231,12 +314,45 @@ volatile u32 *writeMe = (u32 *)whichOne; u32 result; +#if defined SHANNON || defined NESA + int chip1, chip2; +#endif + #ifdef BLOB_DEBUG SerialOutputString(__FUNCTION__ "(): erasing block at address 0x"); SerialOutputHex((u32)whichOne); - SerialOutputByte('\r'); + SerialOutputByte('\n'); #endif +#if defined SHANNON || defined NESA + *(u32 *)FLASH_ADDR1 = data_to_flash(UNLOCK1); + *(u32 *)FLASH_ADDR2 = data_to_flash(UNLOCK2); + *(u32 *)FLASH_ADDR1 = data_to_flash(ERASE_SETUP); + *(u32 *)FLASH_ADDR1 = data_to_flash(UNLOCK1); + *(u32 *)FLASH_ADDR2 = data_to_flash(UNLOCK2); + *writeMe = data_to_flash(ERASE_CONFIRM); + + /* I just can't find clean ways of dealing with this flash... + * The error bit is a *set* bit, so if its read, and bit 7 is 0, + * but bit 5 is 1, its an error, however, after these status reads + * are done, erased flash goes to 0xff...sooo...each chip has to + * be caught where the bits are the status bits */ + chip1 = chip2 = 0; + do { + result = data_from_flash(*writeMe); + if (!chip1 && (result & 0xFFFF) & ERASE_DONE) chip1 = READY; + if (!chip1 && (result & 0xFFFF) & STATUS_PGM_ERR) chip1 = ERR; + if (!chip2 && (result >> 16) & ERASE_DONE) chip2 = READY; + if (!chip2 && (result >> 16) & STATUS_PGM_ERR) chip2 = ERR; + + } while(!chip1 || !chip2); + + *(u32 *)FLASH_ADDR1 = data_to_flash(READ_ARRAY); + + if (chip1 == ERR || chip2 == ERR) return 1; + return 0; +#else + *writeMe = data_to_flash(ERASE_SETUP); *writeMe = data_to_flash(ERASE_CONFIRM); @@ -247,8 +363,8 @@ *writeMe = data_to_flash(READ_ARRAY); return result; +#endif } /* EraseOne */ - Index: led.c =================================================================== RCS file: /cvsroot/blob/blob/src/led.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- led.c 2001/06/27 19:47:42 1.1.1.1 +++ led.c 2001/08/06 22:44:52 1.2 @@ -8,72 +8,71 @@ * Modified by: Erik Mouw <J.A...@it...> * Modified at: Mon Aug 16 16:55:21 1999 *-----------------------------------------------------------------------*/ +/* + * led.c: simple LED control functions + * + * Copyright (C) 1999 2001 Erik Mouw (J.A...@it...) + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +/* + * All functions assume that the LED is properly initialised by the code + * in ledasm.S. + * + */ #ident "$Id$" -/* function prototypes */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif -void blink_led(void); +#include "led.h" +#include "sa1100.h" -static inline void init_gpio(void); -static inline void led_on(void); -static inline void led_off(void); -static inline void waitloop(void); -static inline void init_gpio(void) -{ - /* GPIO Pin Direction Register */ - register unsigned int *gpdr = (unsigned int *)0x90040004; - - /* bit 23 is the LED */ - *gpdr = 0x00800000; -} - - - +static int led_state; -static inline void led_on(void) -{ - register unsigned int *gpsr = (unsigned int *)0x90040008; - - *gpsr = 0x00800000; -} - -static inline void led_off(void) +void led_on(void) { - register unsigned int *gpcr = (unsigned int *)0x9004000c; - - *gpcr = 0x00800000; + GPSR = LED_GPIO; + led_state = 1; } -static inline void waitloop(void) +void led_off(void) { - __asm__ __volatile__ ( - " mov r4, #0x8000\n" - "0: subs r4, r4, #1\n" - " bne 0b\n"); + GPCR = LED_GPIO; + led_state = 0; } -void blink_led(void) +void led_toggle(void) { - init_gpio(); - - for(;;) - { - led_on(); - waitloop(); - led_off(); - waitloop(); - } + if(led_state) + led_off(); + else + led_on(); } Index: main.c =================================================================== RCS file: /cvsroot/blob/blob/src/main.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- main.c 2001/06/27 19:47:42 1.1.1.1 +++ main.c 2001/08/06 22:44:52 1.2 @@ -12,8 +12,9 @@ /* * main.c: main file for the blob bootloader * - * Copyright (C) 1999 Jan-Derk Bakker (J.D...@it...) and - * Erik Mouw (J.A...@it...) + * Copyright (C) 1999 2000 2001 + * Jan-Derk Bakker (J.D...@it...) and + * Erik Mouw (J.A...@it...) * * 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 @@ -40,103 +41,100 @@ #include "clock.h" #include "command.h" #include "flash.h" +#include "led.h" +#include "linux.h" +#include "main.h" +#include "memory.h" +#include "sa1100.h" #include "serial.h" #include "time.h" -#include "main.h" #include "util.h" #include "uucodec.h" - -typedef enum { - fromFlash = 0, - fromDownload = 1 -} blockSource; - - - - -typedef struct { - int kernelSize; - blockSource kernelType; - - int ramdiskSize; - blockSource ramdiskType; - - u32 blockSize; - eBauds downloadSpeed; -} blobStatus; +void Download(char *commandline); +void Flash(char *commandline); +void PrintHelp(void); +void SetDownloadSpeed(char *commandline); +void PrintStatus(void); +void ResetTerminal(void); +void Reload(char *commandline); +void PrintSerialSpeed(eBauds speed); +void Reboot(void); +void Reblob(void); -void BootKernel(char *commandline); -void Download(char *commandline, blobStatus *status); -void Flash(char *commandline, blobStatus *status); -void PrintHelp(void); -void SetDownloadSpeed(char *commandline, blobStatus *status); -void PrintStatus(blobStatus *status); -void ResetTerminal(void); -void Reload(char *commandline, blobStatus *status); -void PrintSerialSpeed(eBauds speed); +blob_status_t blob_status; -void c_main(char *blockBase, u32 blockSize) +int main(void) { + u32 blockSize = 0x00800000; int numRead = 0; char commandline[128]; - blobStatus status; int i; int retval = 0; + + /* Turn the LED on again, so we can see that we safely made it + * into C code. + */ + led_on(); /* We really want to be able to communicate, so initialise the * serial port at 9k6 (which works good for terminals) */ SerialInit(baud9k6); TimerInit(); - - /* initialise status */ - status.kernelSize = 0; - status.kernelType = fromFlash; - status.ramdiskSize = 0; - status.ramdiskType = fromFlash; - status.blockSize = blockSize; - status.downloadSpeed = baud115k2; - - /* Load kernel and ramdisk from flash to RAM */ - Reload("kernel", &status); - Reload("ramdisk", &status); /* Print the required GPL string */ - SerialOutputString("\r" PACKAGE " version " VERSION "\r" - "Copyright (C) 1999 2000 " - "Jan-Derk Bakker and Erik Mouw\r" + SerialOutputString("\nConsider yourself LARTed!\n\n"); + SerialOutputString(PACKAGE " version " VERSION "\n" + "Copyright (C) 1999 2000 2001 " + "Jan-Derk Bakker and Erik Mouw\n" "Copyright (C) 2000 " - "Johan Pouwelse.\r"); + "Johan Pouwelse\n"); SerialOutputString(PACKAGE " comes with ABSOLUTELY NO WARRANTY; " - "read the GNU GPL for details.\r"); + "read the GNU GPL for details.\n"); SerialOutputString("This is free software, and you are welcome " - "to redistribute it\r"); + "to redistribute it\n"); SerialOutputString("under certain conditions; " - "read the GNU GPL for details.\r\r"); + "read the GNU GPL for details.\n"); + + + /* get the amount of memory */ + get_memory_map(); + + /* initialise status */ + blob_status.kernelSize = 0; + blob_status.kernelType = fromFlash; + blob_status.ramdiskSize = 0; + blob_status.ramdiskType = fromFlash; + blob_status.blockSize = blockSize; + blob_status.downloadSpeed = baud115k2; + - /* and some information */ + /* Load kernel and ramdisk from flash to RAM */ + Reload("blob"); + Reload("kernel"); + Reload("ramdisk"); + #ifdef BLOB_DEBUG + /* print some information */ SerialOutputString("Running from "); if(RunningFromInternal()) - SerialOutputString("internal flash\r"); + SerialOutputString("internal flash\n"); else - SerialOutputString("external flash\r"); + SerialOutputString("external flash\n"); - SerialOutputString("blockBase = 0x"); - SerialOutputHex((int) blockBase); SerialOutputString(", blockSize = 0x"); SerialOutputHex(blockSize); - SerialOutputByte('\r'); + SerialOutputByte('\n'); #endif /* wait 10 seconds before starting autoboot */ SerialOutputString("Autoboot in progress, press any key to stop "); @@ -152,132 +150,108 @@ /* no key was pressed, so proceed booting the kernel */ if(retval == 0) { commandline[0] = '\0'; - BootKernel(commandline); + boot_linux(commandline); } - SerialOutputString("\rAutoboot aborted\r"); - SerialOutputString("Type \"help\" to get a list of commands\r"); + SerialOutputString("\nAutoboot aborted\n"); + SerialOutputString("Type \"help\" to get a list of commands\n"); /* the command loop. endless, of course */ for(;;) { DisplayPrompt(NULL); - /* wait an hour to get a command */ - numRead = GetCommand(commandline, 128, 3600); + /* wait 10 minutes for a command */ + numRead = GetCommand(commandline, 128, 600); if(numRead > 0) { if(MyStrNCmp(commandline, "boot", 4) == 0) { - BootKernel(commandline + 4); + boot_linux(commandline + 4); } else if(MyStrNCmp(commandline, "clock", 5) == 0) { SetClock(commandline + 5); } else if(MyStrNCmp(commandline, "download ", 9) == 0) { - Download(commandline + 9, &status); + Download(commandline + 9); } else if(MyStrNCmp(commandline, "flash ", 6) == 0) { - Flash(commandline + 6, &status); + Flash(commandline + 6); } else if(MyStrNCmp(commandline, "help", 4) == 0) { PrintHelp(); + } else if(MyStrNCmp(commandline, "reblob", 6) == 0) { + Reblob(); + } else if(MyStrNCmp(commandline, "reboot", 6) == 0) { + Reboot(); } else if(MyStrNCmp(commandline, "reload ", 7) == 0) { - Reload(commandline + 7, &status); + Reload(commandline + 7); } else if(MyStrNCmp(commandline, "reset", 5) == 0) { ResetTerminal(); } else if(MyStrNCmp(commandline, "speed ", 6) == 0) { - SetDownloadSpeed(commandline + 6, &status); + SetDownloadSpeed(commandline + 6); } else if(MyStrNCmp(commandline, "status", 6) == 0) { - PrintStatus(&status); + PrintStatus(); } else { SerialOutputString("*** Unknown command: "); SerialOutputString(commandline); - SerialOutputByte('\r'); + SerialOutputByte('\n'); } } } -} /* c_main */ - - - - -void BootKernel(char *commandline) -{ - void (*theKernel)(int zero, int arch) = (void (*)(int, int))KERNEL_RAM_BASE; - -#warning "FIXME: should set kernel commandline parameters -- Erik" -#ifdef BLOB_DEBUG - SerialOutputString("\r*** Ignoring kernel parameters\r"); -#endif + return 0; +} /* main */ - /* we assume that the kernel is in place */ - /* See linux/include/asm-arm/system.h for architecture numbers */ - SerialOutputString("\rStarting kernel ...\r\r"); - -#if defined ASSABET - theKernel(0, 25); -#elif defined BRUTUS - theKernel(0, 16); -#elif defined LART - theKernel(0, 27); -#elif defined PLEB -#warning "This is NOT the correct PLEB architecture number!" - theKernel(0, 18); -#else - /* Be generic and just tell the kernel that we are an SA1100 - architecture */ -#warning "Calling the kernel with a generic SA1100 architecture code. YMMV!" - theKernel(0,18); -#endif - - SerialOutputString("Hey, the kernel returned! This should not happen.\r"); -} - -void Download(char *commandline, blobStatus *status) +void Download(char *commandline) { u32 startAddress = 0; int bufLen; int *numRead = 0; - if(MyStrNCmp(commandline, "kernel", 6) == 0) { + if(MyStrNCmp(commandline, "blob", 4) == 0) { + /* download blob */ + startAddress = BLOB_RAM_BASE; + bufLen = blob_status.blockSize - BLOB_BLOCK_OFFSET; + numRead = &blob_status.blobSize; + blob_status.blobType = fromDownload; + } else if(MyStrNCmp(commandline, "kernel", 6) == 0) { /* download kernel */ startAddress = KERNEL_RAM_BASE; - bufLen = status->blockSize - KERNEL_BLOCK_OFFSET; - numRead = &status->kernelSize; - status->kernelType = fromDownload; + bufLen = blob_status.blockSize - KERNEL_BLOCK_OFFSET; + numRead = &blob_status.kernelSize; + blob_status.kernelType = fromDownload; } else if(MyStrNCmp(commandline, "ramdisk", 7) == 0) { /* download ramdisk */ startAddress = RAMDISK_RAM_BASE; - bufLen = status->blockSize - RAMDISK_BLOCK_OFFSET; - numRead = &status->ramdiskSize; - status->ramdiskType = fromDownload; + bufLen = blob_status.blockSize - RAMDISK_BLOCK_OFFSET; + numRead = &blob_status.ramdiskSize; + blob_status.ramdiskType = fromDownload; } else { SerialOutputString("*** Don't know how to download \""); SerialOutputString(commandline); - SerialOutputString("\"\r"); + SerialOutputString("\"\n"); return; } SerialOutputString("Switching to "); - PrintSerialSpeed(status->downloadSpeed); - SerialOutputString(" baud\r"); + PrintSerialSpeed(blob_status.downloadSpeed); + SerialOutputString(" baud\n"); - SerialOutputString("You have 60 seconds to switch your terminal emulator to the same speed and\r"); - SerialOutputString("start downloading. After that " PACKAGE " will switch back to 9600 baud.\r"); + SerialOutputString("You have 60 seconds to switch your terminal emulator to the same speed and\n"); + SerialOutputString("start downloading. After that " PACKAGE " will switch back to 9600 baud.\n"); - SerialInit(status->downloadSpeed); + SerialInit(blob_status.downloadSpeed); *numRead = UUDecode((char *)startAddress, bufLen); - SerialOutputString("\r(Please switch your terminal emulator back to 9600 baud)\r"); + SerialOutputString("\n(Please switch your terminal emulator back to 9600 baud)\n"); if(*numRead < 0) { /* something went wrong */ - SerialOutputString("*** Uudecode receive failed\r"); + SerialOutputString("*** Uudecode receive failed\n"); /* reload the correct memory */ - Reload(commandline, status); + Reload(commandline); SerialInit(baud9k6); return; @@ -286,7 +260,7 @@ SerialOutputDec(*numRead); SerialOutputString(" (0x"); SerialOutputHex(*numRead); - SerialOutputString(") bytes.\r"); + SerialOutputString(") bytes.\n"); SerialInit(baud9k6); @@ -295,24 +269,33 @@ -void Flash(char *commandline, blobStatus *status) +void Flash(char *commandline) { u32 startAddress = 0; tBlockType block; - int numBytes = 0;; + int numBytes = 0; + int maxSize = 0; - if(RunningFromInternal()) { - SerialOutputString("*** Flash not possible when using internal flash\r"); - return; - } + if(MyStrNCmp(commandline, "blob", 4) == 0) { + startAddress = BLOB_RAM_BASE; + block = blBlob; + numBytes = blob_status.blobSize; + maxSize = BLOB_LEN; - if(MyStrNCmp(commandline, "kernel", 6) == 0) { + if(blob_status.blobType == fromFlash) { + SerialOutputString("*** No blob downloaded\n"); + return; + } + + SerialOutputString("Saving blob to flash "); + } else if(MyStrNCmp(commandline, "kernel", 6) == 0) { startAddress = KERNEL_RAM_BASE; block = blKernel; - numBytes = status->kernelSize; + numBytes = blob_status.kernelSize; + maxSize = KERNEL_LEN; - if(status->kernelType == fromFlash) { - SerialOutputString("*** No kernel downloaded\r"); + if(blob_status.kernelType == fromFlash) { + SerialOutputString("*** No kernel downloaded\n"); return; } @@ -320,10 +303,11 @@ } else if(MyStrNCmp(commandline, "ramdisk", 7) == 0) { startAddress = RAMDISK_RAM_BASE; block = blRamdisk; - numBytes = status->ramdiskSize; + numBytes = blob_status.ramdiskSize; + maxSize = INITRD_LEN; - if(status->ramdiskType == fromFlash) { - SerialOutputString("*** No ramdisk downloaded\r"); + if(blob_status.ramdiskType == fromFlash) { + SerialOutputString("*** No ramdisk downloaded\n"); return; } @@ -331,14 +315,25 @@ } else { SerialOutputString("*** Don't know how to flash \""); SerialOutputString(commandline); - SerialOutputString("\"\r"); + SerialOutputString("\"\n"); + return; + } + + if(numBytes > maxSize) { + SerialOutputString("*** Downloaded image too large for flash area\n"); + SerialOutputString("*** (0x"); + SerialOutputHex(numBytes); + SerialOutputString(" downloaded, maximum size is 0x"); + SerialOutputHex(maxSize); + SerialOutputString(" bytes)\n"); + return; } EraseBlocks(block); SerialOutputByte(' '); WriteBlocksFromMem(block, (u32 *)startAddress, numBytes); - SerialOutputString(" done\r"); + SerialOutputString(" done\n"); } @@ -346,70 +341,72 @@ void PrintHelp(void) { - SerialOutputString("Help for " PACKAGE " " VERSION ", the LART bootloader\r"); - SerialOutputString("The following commands are supported:\r"); - SerialOutputString("* boot [kernel options] Boot Linux with optional kernel options\r"); - SerialOutputString("* clock PPCR MDCNFG MDCAS0 MDCAS1 MDCAS2\r"); - SerialOutputString(" Set the SA1100 core clock and DRAM timings\r"); - SerialOutputString(" (WARNING: dangerous command!)\r"); - SerialOutputString("* download {kernel|ramdisk} Download kernel or ramdisk image to RAM\r"); - SerialOutputString("* flash {kernel|ramdisk} Copy kernel or ramdisk from RAM to flash\r"); - SerialOutputString("* help Get this help\r"); - SerialOutputString("* reload {kernel|ramdisk} Reload kernel or ramdisk from flash to RAM\r"); - SerialOutputString("* reset Reset terminal\r"); - SerialOutputString("* speed Set download speed\r"); - SerialOutputString("* status Display current status\r"); + SerialOutputString("Help for " PACKAGE " " VERSION ", the LART bootloader\n"); + SerialOutputString("The following commands are supported:\n"); + SerialOutputString("* boot [kernel options] Boot Linux with optional kernel options\n"); + SerialOutputString("* clock PPCR MDCNFG MDCAS0 MDCAS1 MDCAS2\n"); + SerialOutputString(" Set the SA1100 core clock and DRAM timings\n"); + SerialOutputString(" (WARNING: dangerous command!)\n"); + SerialOutputString("* download {blob|kernel|ramdisk} Download kernel or ramdisk image to RAM\n"); + SerialOutputString("* flash {blob|kernel|ramdisk} Copy kernel or ramdisk from RAM to flash\n"); + SerialOutputString("* help Get this help\n"); + SerialOutputString("* reblob Restart blob from RAM\n"); + SerialOutputString("* reboot Reboot system\n"); + SerialOutputString("* reload {blob|kernel|ramdisk} Reload kernel or ramdisk from flash to RAM\n"); + SerialOutputString("* reset Reset terminal\n"); + SerialOutputString("* speed Set download speed\n"); + SerialOutputString("* status Display current status\n"); } -void SetDownloadSpeed(char *commandline, blobStatus *status) +void SetDownloadSpeed(char *commandline) { if(MyStrNCmp(commandline, "1200", 4) == 0) { - status->downloadSpeed = baud1k2; + blob_status.downloadSpeed = baud1k2; } else if(MyStrNCmp(commandline, "1k2", 3) == 0) { - status->downloadSpeed = baud1k2; + blob_status.downloadSpeed = baud1k2; } else if(MyStrNCmp(commandline, "9600", 4) == 0) { - status->downloadSpeed = baud9k6; + blob_status.downloadSpeed = baud9k6; } else if(MyStrNCmp(commandline, "9k6", 3) == 0) { - status->downloadSpeed = baud9k6; + blob_status.downloadSpeed = baud9k6; } else if(MyStrNCmp(commandline, "19200", 5) == 0) { - status->downloadSpeed = baud19k2; + blob_status.downloadSpeed = baud19k2; } else if(MyStrNCmp(commandline, "19k2", 4) == 0) { - status->downloadSpeed = baud19k2; + blob_status.downloadSpeed = baud19k2; } else if(MyStrNCmp(commandline, "38400", 5) == 0) { - status->downloadSpeed = baud38k4; + blob_status.downloadSpeed = baud38k4; } else if(MyStrNCmp(commandline, "38k4", 4) == 0) { - status->downloadSpeed = baud38k4; + blob_status.downloadSpeed = baud38k4; } else if(MyStrNCmp(commandline, "57600", 5) == 0) { - status->downloadSpeed = baud57k6; + blob_status.downloadSpeed = baud57k6; } else if(MyStrNCmp(commandline, "57k6", 4) == 0) { - status->downloadSpeed = baud57k6; + blob_status.downloadSpeed = baud57k6; } else if(MyStrNCmp(commandline, "115200", 6) == 0) { - status->downloadSpeed = baud115k2; + blob_status.downloadSpeed = baud115k2; } else if(MyStrNCmp(commandline, "115k2", 5) == 0) { - status->downloadSpeed = baud115k2; + blob_status.downloadSpeed = baud115k2; } else { SerialOutputString("*** Invalid download speed value \""); SerialOutputString(commandline); - SerialOutputString("\"\r*** Valid values are:\r"); - SerialOutputString("*** 1200, 9600, 19200, 38400, 57600, 115200,\r"); - SerialOutputString("*** 1k2, 9k6, 19k2, 38k4, 57k6, and 115k2\r"); + SerialOutputString("\"\n*** Valid values are:\n"); + SerialOutputString("*** 1200, 9600, 19200, 38400, 57600, 115200,\n"); + SerialOutputString("*** 1k2, 9k6, 19k2, 38k4, 57k6, and 115k2\n"); } SerialOutputString("Download speed set to "); - PrintSerialSpeed(status->downloadSpeed); - SerialOutputString(" baud\r"); + PrintSerialSpeed(blob_status.downloadSpeed); + SerialOutputString(" baud\n"); } -void PrintStatus(blobStatus *status) +void PrintStatus(void) { - SerialOutputString("Bootloader : " PACKAGE "\r"); - SerialOutputString("Version : " VERSION "\r"); + SerialOutputString("Bootloader : " PACKAGE "\n"); + SerialOutputString("Version : " VERSION "\n"); SerialOutputString("Running from : "); if(RunningFromInternal()) @@ -417,29 +414,38 @@ else SerialOutputString("external"); - SerialOutputString(" flash\rBlocksize : 0x"); - SerialOutputHex(status->blockSize); + SerialOutputString(" flash\nBlocksize : 0x"); + SerialOutputHex(blob_status.blockSize); - SerialOutputString("\rDownload speed: "); - PrintSerialSpeed(status->downloadSpeed); - SerialOutputString(" baud\r"); + SerialOutputString("\nDownload speed: "); + PrintSerialSpeed(blob_status.downloadSpeed); + SerialOutputString(" baud\n"); + + SerialOutputString("Blob : "); + if(blob_status.blobType == fromFlash) { + SerialOutputString("from flash\n"); + } else { + SerialOutputString("downloaded, "); + SerialOutputDec(blob_status.blobSize); + SerialOutputString(" bytes\n"); + } SerialOutputString("Kernel : "); - if(status->kernelType == fromFlash) { - SerialOutputString("from flash\r"); + if(blob_status.kernelType == fromFlash) { + SerialOutputString("from flash\n"); } else { SerialOutputString("downloaded, "); - SerialOutputDec(status->kernelSize); - SerialOutputString(" bytes\r"); + SerialOutputDec(blob_status.kernelSize); + SerialOutputString(" by... [truncated message content] |