Home | History | Annotate | Download | only in usbloader
      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