#pypp 0 // Iris: micro-kernel for a capability-based operating system. // mips/nanonote/nand-boot.ccp: standalone program for booting from nand. // Copyright 2010 Bas Wijnen // // 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 3 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, see . asm volatile ("\t.set noreorder\n" "\t.text\n" "\t.globl __start\n" "\t.globl addr_0\n" "addr_0:\n" "\t.word ~0\n" "__start:\n" "\tbal 1f\n" "__hack_label:\n" "\tnop\n" "\t.word _gp\n" "1:\n" "\tori $t0, $zero, 0x0006\n" "\tmtc0 $t0, $12\n" "\tlw $gp, 0($ra)\n" "\tla $sp, stack + 0x1000\n" "\tla $t9, nandboot_start\n" "\tjr $t9\n" "\tnop\n" "\t.fill 0x1b8 - (. - addr_0)\n" "\t.word 0xd2b9e1a8\n" // Disk signature. "\t.short 0x0000\n" "\t.byte 0x00\n" // bootable: no. "\t.byte 0x00, 0x02, 0x00\n" // first sector chs. "\t.byte 0x83\n" // type. "\t.byte 0x08, 0x18, 0x00\n" // last sector chs. "\t.byte 0x01, 0x00, 0x00, 0x00\n" // first sector, lba. "\t.byte 0xff, 0x01, 0x00, 0x00\n" // size, lba. "\t.byte 0x00\n" // bootable: no. "\t.byte 0x08, 0x19, 0x00\n" // first sector chs. "\t.byte 0x83\n" // type. "\t.byte 0x05, 0xe1, 0xf3\n" // last sector chs. "\t.byte 0x00, 0x02, 0x00, 0x00\n" // first sector, lba: 256 kB. "\t.byte 0x00, 0xfe, 0x1f, 0x00\n" // size, lba: 1 GB - first. "\t.byte 0\n" // bootable: no. "\t.byte 0, 0, 0\n" // first sector chs. "\t.byte 0\n" // type. "\t.byte 0, 0, 0\n" // last sector chs. "\t.byte 0, 0, 0, 0\n" // first sector, lba. "\t.byte 0, 0, 0, 0\n" // size, lba. "\t.byte 0\n" // bootable: no. "\t.byte 0, 0, 0\n" // first sector chs. "\t.byte 0\n" // type. "\t.byte 0, 0, 0\n" // last sector chs. "\t.byte 0, 0, 0, 0\n" // first sector, lba. "\t.byte 0, 0, 0, 0\n" // size, lba. "\t.byte 0x55, 0xaa\n" // mbr signature. "\t.set reorder") #define __KERNEL__ #include #define DELAY() static void debug (unsigned ch): while !(UART0_LSR & UARTLSR_TDRQ): UART0_TDR = ch static void debug_num (unsigned num, unsigned base, unsigned min_digits = 1): char const *encode = "0123456789abcdef" unsigned digits = 1 unsigned power = 1 while power <= num / base || min_digits > digits: power *= base ++digits for unsigned i = 0; i < digits; ++i: unsigned d = num / power debug (encode[d]) num -= d * power power /= base static void debug (char const *f, ...): unsigned *last = (unsigned *)&f while *f: if *f == '%': ++f switch *f: case '%': debug ('%') break case 'd': ++last debug_num (*last, 10) break case 'x': ++last debug_num (*last, 0x10) break case 's': ++last char *str = (char*)*last while *str: debug (*str++) break default: debug ("warning: invalid character in dbg format string\n") break else: debug (*f) ++f #define debug_line() debug ("nand-boot line %d\n", __LINE__) #include "nand.hh" static void setup_uart (): cpm_start_uart0 () gpio_as_uart0 () UART0_IER = 0 UART0_FCR = 0 UART0_MCR = 0 UART0_SIRCR = 0 UART0_UACR = 0 UART0_UMR = 16 UART0_LCR = UARTLCR_WLEN_8 | UARTLCR_STOP1 | UARTLCR_DLAB unsigned const baud = 57600 unsigned uart_div = 12000000 / 16 / baud UART0_DLHR = (uart_div >> 8) & 0xff UART0_DLLR = uart_div & 0xff UART0_LCR = UARTLCR_WLEN_8 | UARTLCR_STOP1 UART0_FCR = UARTFCR_UUE | UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS debug ("\n\nNand-boot: serial port initialized\n") extern "C": void nandboot_start (): unsigned base = 0x18000000 + 0xa0000000 data = (volatile char *)base command = (volatile char *)(base + 0x8000) address = (volatile char *)(base + 0x10000) pll_init () cpm_start_all () gpio_as_sdram_16bit () gpio_as_nand () setup_sdram () setup_uart () reset () // Load contents of nand flash (from 0x4000) into 0xa0600000; unsigned a = 0x4000 unsigned target = 0xa0600000 while read (a, (char *)target): a += 0x200 target += 0x200 // Tell about what'll happen. debug ("Jumping to a0600000:\n") for unsigned d = 0; d < 0x40; ++d: debug (" ") debug_num (((char *)0xa0600000)[d] & 0xff, 16, 2) debug ('\n') // Wait for the serial port to finish. while !(UART0_LSR & UARTLSR_TEMT): // Then jump to 0xa0600000. ((void (*)())0xa0600000) () unsigned char stack[0x1000] unsigned __gxx_personality_v0