1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <boot/boot.h> 30 #include <boot/uart.h> 31 #include <boot/tags.h> 32 #include <boot/flash.h> 33 #include <boot/board.h> 34 35 #include <bootimg.h> 36 37 #define FLASH_PAGE_SIZE 2048 38 #define FLASH_PAGE_BITS 11 39 40 #define ADDR_TAGS 0x10000100 41 42 static void create_atags(unsigned taddr, const char *cmdline, 43 unsigned raddr, unsigned rsize) 44 { 45 unsigned n = 0; 46 unsigned pcount; 47 unsigned *tags = (unsigned *) taddr; 48 49 // ATAG_CORE 50 tags[n++] = 2; 51 tags[n++] = 0x54410001; 52 53 if(rsize) { 54 // ATAG_INITRD2 55 tags[n++] = 4; 56 tags[n++] = 0x54420005; 57 tags[n++] = raddr; 58 tags[n++] = rsize; 59 } 60 61 if((pcount = flash_get_ptn_count())){ 62 ptentry *ptn; 63 unsigned pn; 64 unsigned m = n + 2; 65 66 for(pn = 0; pn < pcount; pn++) { 67 ptn = flash_get_ptn(pn); 68 memcpy(tags + m, ptn, sizeof(ptentry)); 69 m += (sizeof(ptentry) / sizeof(unsigned)); 70 } 71 72 tags[n + 0] = m - n; 73 tags[n + 1] = 0x4d534d70; 74 n = m; 75 } 76 if(cmdline && cmdline[0]) { 77 const char *src; 78 char *dst; 79 unsigned len = 0; 80 81 dst = (char*) (tags + n + 2); 82 src = cmdline; 83 while((*dst++ = *src++)) len++; 84 85 len++; 86 len = (len + 3) & (~3); 87 88 // ATAG_CMDLINE 89 tags[n++] = 2 + (len / 4); 90 tags[n++] = 0x54410009; 91 92 n += (len / 4); 93 } 94 95 // ATAG_NONE 96 tags[n++] = 0; 97 tags[n++] = 0; 98 } 99 100 static void boot_linux(unsigned kaddr) 101 { 102 void (*entry)(unsigned,unsigned,unsigned) = (void*) kaddr; 103 104 entry(0, board_machtype(), ADDR_TAGS); 105 } 106 107 unsigned char raw_header[2048]; 108 109 int boot_linux_from_flash(void) 110 { 111 boot_img_hdr *hdr = (void*) raw_header; 112 unsigned n; 113 ptentry *p; 114 unsigned offset = 0; 115 const char *cmdline; 116 117 if((p = flash_find_ptn("boot")) == 0) { 118 cprintf("NO BOOT PARTITION\n"); 119 return -1; 120 } 121 122 if(flash_read(p, offset, raw_header, 2048)) { 123 cprintf("CANNOT READ BOOT IMAGE HEADER\n"); 124 return -1; 125 } 126 offset += 2048; 127 128 if(memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) { 129 cprintf("INVALID BOOT IMAGE HEADER\n"); 130 return -1; 131 } 132 133 n = (hdr->kernel_size + (FLASH_PAGE_SIZE - 1)) & (~(FLASH_PAGE_SIZE - 1)); 134 if(flash_read(p, offset, (void*) hdr->kernel_addr, n)) { 135 cprintf("CANNOT READ KERNEL IMAGE\n"); 136 return -1; 137 } 138 offset += n; 139 140 n = (hdr->ramdisk_size + (FLASH_PAGE_SIZE - 1)) & (~(FLASH_PAGE_SIZE - 1)); 141 if(flash_read(p, offset, (void*) hdr->ramdisk_addr, n)) { 142 cprintf("CANNOT READ RAMDISK IMAGE\n"); 143 return -1; 144 } 145 offset += n; 146 147 dprintf("\nkernel @ %x (%d bytes)\n", hdr->kernel_addr, hdr->kernel_size); 148 dprintf("ramdisk @ %x (%d bytes)\n\n\n", hdr->ramdisk_addr, hdr->ramdisk_size); 149 150 if(hdr->cmdline[0]) { 151 cmdline = (char*) hdr->cmdline; 152 } else { 153 cmdline = board_cmdline(); 154 if(cmdline == 0) { 155 cmdline = "mem=50M console=null"; 156 } 157 } 158 cprintf("cmdline = '%s'\n", cmdline); 159 160 cprintf("\nBooting Linux\n"); 161 162 create_atags(ADDR_TAGS, cmdline, 163 hdr->ramdisk_addr, hdr->ramdisk_size); 164 165 boot_linux(hdr->kernel_addr); 166 return 0; 167 } 168 169 void usbloader_init(void); 170 void uart_putc(unsigned); 171 const char *get_fastboot_version(void); 172 173 extern unsigned linux_type; 174 extern unsigned linux_tags; 175 176 static unsigned revision = 0; 177 178 char serialno[32]; 179 180 void dump_smem_info(void); 181 182 static void tag_dump(unsigned tag, void *data, unsigned sz, void *cookie) 183 { 184 dprintf("tag type=%x data=%x size=%x\n", tag, (unsigned) data, sz); 185 } 186 187 static struct tag_handler tag_dump_handler = { 188 .func = tag_dump, 189 .type = 0, 190 }; 191 192 void xdcc_putc(unsigned x) 193 { 194 while (dcc_putc(x) < 0) ; 195 } 196 197 #define SERIALNO_STR "androidboot.serialno=" 198 #define SERIALNO_LEN strlen(SERIALNO_STR) 199 200 static int boot_from_flash = 1; 201 202 void key_changed(unsigned int key, unsigned int down) 203 { 204 if(!down) return; 205 if(key == BOOT_KEY_STOP_BOOT) boot_from_flash = 0; 206 } 207 208 static int tags_okay(unsigned taddr) 209 { 210 unsigned *tags = (unsigned*) taddr; 211 212 if(taddr != ADDR_TAGS) return 0; 213 if(tags[0] != 2) return 0; 214 if(tags[1] != 0x54410001) return 0; 215 216 return 1; 217 } 218 219 int _main(unsigned zero, unsigned type, unsigned tags) 220 { 221 const char *cmdline = 0; 222 int n; 223 224 arm11_clock_init(); 225 226 /* must do this before board_init() so that we 227 ** use the partition table in the tags if it 228 ** already exists 229 */ 230 if((zero == 0) && (type != 0) && tags_okay(tags)) { 231 linux_type = type; 232 linux_tags = tags; 233 234 cmdline = tags_get_cmdline((void*) linux_tags); 235 236 tags_import_partitions((void*) linux_tags); 237 revision = tags_get_revision((void*) linux_tags); 238 if(revision == 1) { 239 console_set_colors(0x03E0, 0xFFFF); 240 } 241 if(revision == 2) { 242 console_set_colors(0x49B2, 0xFFFF); 243 } 244 245 /* we're running as a second-stage, so wait for interrupt */ 246 boot_from_flash = 0; 247 } else { 248 linux_type = board_machtype(); 249 linux_tags = 0; 250 } 251 252 board_init(); 253 keypad_init(); 254 255 console_init(); 256 dprintf_set_putc(uart_putc); 257 258 if(linux_tags == 0) { 259 /* generate atags containing partitions 260 * from the bootloader, etc 261 */ 262 linux_tags = ADDR_TAGS; 263 create_atags(linux_tags, 0, 0, 0); 264 } 265 266 if (cmdline) { 267 char *sn = strstr(cmdline, SERIALNO_STR); 268 if (sn) { 269 char *s = serialno; 270 sn += SERIALNO_LEN; 271 while (*sn && (*sn != ' ') && ((s - serialno) < 31)) { 272 *s++ = *sn++; 273 } 274 *s++ = 0; 275 } 276 } 277 278 cprintf("\n\nUSB FastBoot: V%s\n", get_fastboot_version()); 279 cprintf("Machine ID: %d v%d\n", linux_type, revision); 280 cprintf("Build Date: "__DATE__", "__TIME__"\n\n"); 281 282 cprintf("Serial Number: %s\n\n", serialno[0] ? serialno : "UNKNOWN"); 283 284 flash_dump_ptn(); 285 286 flash_init(); 287 288 /* scan the keyboard a bit */ 289 for(n = 0; n < 50; n++) { 290 boot_poll(); 291 } 292 293 if (boot_from_flash) { 294 cprintf("\n ** BOOTING LINUX FROM FLASH **\n"); 295 boot_linux_from_flash(); 296 } 297 298 usbloader_init(); 299 300 for(;;) { 301 usb_poll(); 302 } 303 return 0; 304 } 305