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/board.h> 31 #include <boot/flash.h> 32 33 #define FLASH_PAGE_SIZE 2048 34 #define FLASH_PAGE_BITS 11 35 36 int startswith(const char *str, const char *prefix) 37 { 38 while(*prefix){ 39 if(*prefix++ != *str++) return 0; 40 } 41 return 1; 42 } 43 44 void verify_flash(ptentry *p, void *addr, unsigned len, int extra) 45 { 46 int offset = 0; 47 void *buf = alloc(FLASH_PAGE_SIZE + extra); 48 int verify_extra = extra; 49 if(verify_extra > 4) 50 verify_extra = 16; 51 while(len > 0) { 52 flash_read_ext(p, extra, offset, buf, FLASH_PAGE_SIZE); 53 if(memcmp(addr, buf, FLASH_PAGE_SIZE + verify_extra)) { 54 dprintf("verify failed at %x\n", offset); 55 jtag_fail("verify failed"); 56 return; 57 } 58 offset += FLASH_PAGE_SIZE; 59 addr += FLASH_PAGE_SIZE; 60 len -= FLASH_PAGE_SIZE; 61 if(extra) { 62 addr += extra; 63 len -= extra; 64 } 65 } 66 dprintf("verify done %d extra bytes\n", verify_extra); 67 jtag_okay("verify done"); 68 } 69 70 void handle_flash(const char *name, unsigned addr, unsigned len) 71 { 72 int r; 73 ptentry *p; 74 75 dprintf("image @ %x (%d bytes)\n", addr, len); 76 dprintf("write to '%s' partition\n", name); 77 78 p = flash_find_ptn(name); 79 80 if(p == 0) { 81 jtag_fail("partition not found"); 82 return; 83 } else { 84 if(flash_init()) { 85 jtag_fail("flash_init() failed"); 86 return; 87 } 88 89 dprintf("erasing flash @ %d (len=%d)\n", p->start, p->length); 90 flash_erase(p); 91 92 if(len) { 93 dprintf("writing flash at @ %d\n", p->start); 94 95 if(!strcmp(name, "system") || !strcmp(name, "userdata")) { 96 r = flash_write(p, 64, (void*) addr, len); 97 } else { 98 len = (len + FLASH_PAGE_SIZE - 1) & (~(FLASH_PAGE_SIZE-1)); 99 r = flash_write(p, 0, (void*) addr, len); 100 } 101 //verify_flash(p, addr, len, (!strcmp(name, "system") || !strcmp(name, "userdata")) ? 64 : 0); 102 if(r) { 103 jtag_fail("partition write failed"); 104 } else { 105 jtag_okay("partition written"); 106 } 107 return; 108 } else { 109 jtag_okay("partition erased"); 110 return; 111 } 112 } 113 } 114 115 void hexdump(void *ptr, unsigned len) 116 { 117 unsigned char *b = ptr; 118 int count = 0; 119 120 dprintf("%x: ", (unsigned) b); 121 while(len-- > 0) { 122 dprintf("%b ", *b++); 123 if(++count == 16) { 124 dprintf("\n%x: ", (unsigned) b); 125 count = 0; 126 } 127 } 128 if(count != 0) dprintf("\n"); 129 } 130 131 static unsigned char *tmpbuf = 0; 132 133 void handle_dump(const char *name, unsigned offset) 134 { 135 ptentry *p; 136 137 if(tmpbuf == 0) { 138 tmpbuf = alloc(4096); 139 } 140 141 dprintf("dump '%s' partition\n", name); 142 p = flash_find_ptn(name); 143 144 if(p == 0) { 145 jtag_fail("partition not found"); 146 return; 147 } 148 149 if(flash_init()) { 150 jtag_fail("flash_init() failed"); 151 return; 152 } 153 154 #if 0 155 /* XXX reimpl */ 156 if(flash_read_page(p->start * 64, tmpbuf, tmpbuf + 2048)){ 157 jtag_fail("flash_read() failed"); 158 return; 159 } 160 #endif 161 162 dprintf("page %d data:\n", p->start * 64); 163 hexdump(tmpbuf, 256); 164 dprintf("page %d extra:\n", p->start * 64); 165 hexdump(tmpbuf, 16); 166 jtag_okay("done"); 167 } 168 169 void handle_command(const char *cmd, unsigned a0, unsigned a1, unsigned a2) 170 { 171 if(startswith(cmd,"flash:")){ 172 handle_flash(cmd + 6, a0, a1); 173 return; 174 } 175 176 if(startswith(cmd,"dump:")){ 177 handle_dump(cmd + 5, a0); 178 return; 179 } 180 181 jtag_fail("unknown command"); 182 } 183 184 int _main(void) 185 { 186 arm11_clock_init(); 187 188 dprintf_set_putc(jtag_dputc); 189 190 board_init(); 191 192 jtag_cmd_loop(handle_command); 193 194 return 0; 195 } 196