/* * Milkymist SoC (Software) * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 Sebastien Bourdeauducq * * 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, version 3 of the License. * * 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 . */ #include #include #include #include #include #include #include #include #include #include #include #include #include "microudp.h" #include "tftp.h" #include "boot.h" extern int rescue; extern void boot_helper(unsigned int r1, unsigned int r2, unsigned int r3, unsigned int r4, unsigned int addr); static void __attribute__((noreturn)) boot(unsigned int r1, unsigned int r2, unsigned int r3, unsigned int r4, unsigned int addr) { printf("Executing booted program.\n"); uart_sync(); irq_setmask(0); irq_setie(0); boot_helper(r1, r2, r3, r4, addr); while(1); } static int check_ack(void) { int recognized; static const char str[SFL_MAGIC_LEN] = SFL_MAGIC_ACK; timer_enable(0); timer_set_reload(0); timer_set_counter(get_system_frequency()/4); timer_enable(1); recognized = 0; while(timer_get()) { if(uart_read_nonblock()) { char c; c = uart_read(); if(c == str[recognized]) { recognized++; if(recognized == SFL_MAGIC_LEN) return 1; } else { if(c == str[0]) recognized = 1; else recognized = 0; } } } return 0; } #define MAX_FAILED 5 void serialboot(void) { struct sfl_frame frame; int failed; unsigned int cmdline_adr, initrdstart_adr, initrdend_adr; static const char str[SFL_MAGIC_LEN+1] = SFL_MAGIC_REQ; const char *c; printf("Booting from serial...\n"); c = str; while(*c) { uart_write(*c); c++; } if(!check_ack()) { printf("Timeout\n"); return; } failed = 0; cmdline_adr = initrdstart_adr = initrdend_adr = 0; while(1) { int i; int actualcrc; int goodcrc; /* Grab one frame */ frame.length = uart_read(); frame.crc[0] = uart_read(); frame.crc[1] = uart_read(); frame.cmd = uart_read(); for(i=0;i 0) printf("Successfully downloaded %d bytes from %s over TFTP\n", r, filename); else printf("Unable to download %s over TFTP\n", filename); return r; } void netboot(void) { int size; unsigned int cmdline_adr, initrdstart_adr, initrdend_adr; unsigned int ip; unsigned char *macadr = (unsigned char *)FLASH_OFFSET_MAC_ADDRESS; printf("Booting from network...\n"); printf("Local IP : %d.%d.%d.%d\n", LOCALIP1, LOCALIP2, LOCALIP3, LOCALIP4); printf("Remote IP: %d.%d.%d.%d\n", REMOTEIP1, REMOTEIP2, REMOTEIP3, REMOTEIP4); ip = IPTOINT(REMOTEIP1, REMOTEIP2, REMOTEIP3, REMOTEIP4); microudp_start(macadr, IPTOINT(LOCALIP1, LOCALIP2, LOCALIP3, LOCALIP4)); if(tftp_get_v(ip, "boot.bin", (void *)SDRAM_BASE) <= 0) { printf("Network boot failed\n"); return; } cmdline_adr = SDRAM_BASE+0x1000000; size = tftp_get_v(ip, "cmdline.txt", (void *)cmdline_adr); if(size <= 0) { printf("No command line parameters found\n"); cmdline_adr = 0; } else *((char *)(cmdline_adr+size)) = 0x00; initrdstart_adr = SDRAM_BASE+0x1002000; size = tftp_get_v(ip, "initrd.bin", (void *)initrdstart_adr); if(size <= 0) { printf("No initial ramdisk found\n"); initrdstart_adr = 0; initrdend_adr = 0; } else initrdend_adr = initrdstart_adr + size; boot(cmdline_adr, initrdstart_adr, initrdend_adr, rescue, SDRAM_BASE); } void flashboot(void) { unsigned int *flashbase; unsigned int length; unsigned int crc; unsigned int got_crc; printf("Booting from flash...\n"); if(rescue) flashbase = (unsigned int *)FLASH_OFFSET_RESCUE_APP; else flashbase = (unsigned int *)FLASH_OFFSET_REGULAR_APP; length = *flashbase++; crc = *flashbase++; if((length < 32) || (length > 4*1024*1024)) { printf("Error: Invalid flash boot image length\n"); return; } printf("Loading %d bytes from flash...\n", length); memcpy((void *)SDRAM_BASE, flashbase, length); got_crc = crc32((unsigned char *)SDRAM_BASE, length); if(crc != got_crc) { printf("CRC failed (expected %08x, got %08x)\n", crc, got_crc); return; } boot(0, 0, 0, rescue, SDRAM_BASE); }