diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:28:41 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:28:41 -0800 |
commit | 076ef94d61f349f7cf0fe776e60456d8f232cca5 (patch) | |
tree | 6a7dfaaef61ff7ee33bb2036cd14b08583e70223 /nandwrite | |
parent | 84fe89dad95fa18a8950d130a2537db834333bb7 (diff) | |
download | legacy-076ef94d61f349f7cf0fe776e60456d8f232cca5.tar.gz |
auto import from //depot/cupcake/@135843android-sdk-tools_r2android-sdk-1.6_r2android-sdk-1.6_r1android-sdk-1.6-docs_r1android-sdk-1.5_r3android-sdk-1.5_r1android-sdk-1.5-preandroid-1.6_r2android-1.6_r1.5android-1.6_r1.4android-1.6_r1.3android-1.6_r1.2android-1.6_r1.1android-1.6_r1android-1.5r4android-1.5r3android-1.5r2android-1.5donut-release2donut-releasedonutcupcake-releasecupcake
Diffstat (limited to 'nandwrite')
-rw-r--r-- | nandwrite/Android.mk | 20 | ||||
-rw-r--r-- | nandwrite/init.S | 78 | ||||
-rw-r--r-- | nandwrite/jtag.c | 114 | ||||
-rw-r--r-- | nandwrite/nandwrite.c | 195 |
4 files changed, 407 insertions, 0 deletions
diff --git a/nandwrite/Android.mk b/nandwrite/Android.mk new file mode 100644 index 0000000..be97da9 --- /dev/null +++ b/nandwrite/Android.mk @@ -0,0 +1,20 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm + +LOCAL_C_INCLUDES := $(call include-path-for, bootloader mkbootimg) + +LOCAL_SRC_FILES := init.S jtag.c nandwrite.c + +LOCAL_CFLAGS := -O2 -g -W -Wall +LOCAL_CFLAGS += -march=armv6 + +LOCAL_MODULE := nandwrite + +LOCAL_MODULE_PATH := $(PRODUCT_OUT) +LOCAL_STATIC_LIBRARIES := $(TARGET_BOOTLOADER_LIBS) libboot libboot_c + +include $(BUILD_RAW_EXECUTABLE) + +$(LOCAL_BUILT_MODULE) : PRIVATE_LINK_SCRIPT := $(TARGET_BOOTLOADER_LINK_SCRIPT) diff --git a/nandwrite/init.S b/nandwrite/init.S new file mode 100644 index 0000000..c542503 --- /dev/null +++ b/nandwrite/init.S @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <boot/arm.h> + +v_reset: + b start +v_undefined: + b . +v_swi: + b . +v_prefetch_abt: + b . +v_data_abt: + b . +v_reserved: + b . +v_irq: + b . +v_fiq: + b . + +start: + /* save registers for main() */ + mov r7, r0 + mov r8, r1 + mov r9, r2 + mov r10, r3 + + /* init stacks */ + ldr r0, =BOOTLOADER_STACK + msr cpsr_c, #(PSR_I | PSR_F | PSR_SVC) + mov sp, r0 + + /* zero the BSS */ + ldr r1, =BOOTLOADER_BSS + ldr r2, =BOOTLOADER_END + mov r0, #0 +1: str r0, [r1], #4 + cmp r1, r2 + ble 1b + + bl periph_2gb_open + + /* restore registers for main() */ + mov r0, r7 + mov r1, r8 + mov r2, r9 + mov r3, r10 + + ldr r4, =_main + blx r4 + b . diff --git a/nandwrite/jtag.c b/nandwrite/jtag.c new file mode 100644 index 0000000..e91d1e8 --- /dev/null +++ b/nandwrite/jtag.c @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <boot/boot.h> + +#define STATUS_NOMSG 0 +#define STATUS_OKAY 1 +#define STATUS_FAIL 2 +#define STATUS_PRINT 3 + +void jtag_hook(); + +volatile unsigned _jtag_cmd = 0; +volatile unsigned _jtag_msg = 0; +unsigned char _jtag_cmd_buffer[128]; +unsigned char _jtag_msg_buffer[128]; + +volatile unsigned _jtag_arg0 = 0; +volatile unsigned _jtag_arg1 = 0; +volatile unsigned _jtag_arg2 = 0; + +static void jtag_msg(unsigned status, const char *msg) +{ + unsigned char *out = _jtag_msg_buffer; + while((*out++ = *msg++) != 0) ; + _jtag_msg = status; + do { + jtag_hook(); + } while(_jtag_msg != 0); +} + +void jtag_okay(const char *msg) +{ + if(msg == 0) msg = "OKAY"; + jtag_msg(STATUS_OKAY, msg); +} + +void jtag_fail(const char *msg) +{ + if(msg == 0) msg = "FAIL"; + jtag_msg(STATUS_FAIL, msg); +} + +int jtag_cmd_pending() +{ + jtag_hook(); + return (int) _jtag_cmd; +} + +void jtag_cmd_loop(void (*do_cmd)(const char *, unsigned, unsigned, unsigned)) +{ + unsigned n; + for(;;) { + if(jtag_cmd_pending()){ + do_cmd((const char*) _jtag_cmd_buffer, _jtag_arg0, _jtag_arg1, _jtag_arg2); + for(n = 0; n < 256; n++) _jtag_cmd_buffer[n] = 0; + _jtag_arg0 = 0; + _jtag_arg1 = 0; + _jtag_arg2 = 0; + _jtag_cmd = 0; + } + } +} + +static char jtag_putc_buffer[128]; +static unsigned jtag_putc_count = 0; + +static void jtag_push_buffer(void) +{ + jtag_putc_buffer[jtag_putc_count] = 0; + jtag_putc_count = 0; + jtag_msg(STATUS_PRINT, jtag_putc_buffer); +} + +void jtag_dputc(unsigned c) +{ + if((c < 32) || (c > 127)) { + if(c == '\n') { + jtag_push_buffer(); + } + return; + } + + jtag_putc_buffer[jtag_putc_count++] = c; + if(jtag_putc_count == 127) { + jtag_push_buffer(); + } +} + diff --git a/nandwrite/nandwrite.c b/nandwrite/nandwrite.c new file mode 100644 index 0000000..c715095 --- /dev/null +++ b/nandwrite/nandwrite.c @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <boot/boot.h> +#include <boot/board.h> +#include <boot/flash.h> + +#define FLASH_PAGE_SIZE 2048 +#define FLASH_PAGE_BITS 11 + +int startswith(const char *str, const char *prefix) +{ + while(*prefix){ + if(*prefix++ != *str++) return 0; + } + return 1; +} + +void verify_flash(ptentry *p, void *addr, unsigned len, int extra) +{ + int offset = 0; + void *buf = alloc(FLASH_PAGE_SIZE + extra); + int verify_extra = extra; + if(verify_extra > 4) + verify_extra = 16; + while(len > 0) { + flash_read_ext(p, extra, offset, buf, FLASH_PAGE_SIZE); + if(memcmp(addr, buf, FLASH_PAGE_SIZE + verify_extra)) { + dprintf("verify failed at %x\n", offset); + jtag_fail("verify failed"); + return; + } + offset += FLASH_PAGE_SIZE; + addr += FLASH_PAGE_SIZE; + len -= FLASH_PAGE_SIZE; + if(extra) { + addr += extra; + len -= extra; + } + } + dprintf("verify done %d extra bytes\n", verify_extra); + jtag_okay("verify done"); +} + +void handle_flash(const char *name, unsigned addr, unsigned len) +{ + int r; + ptentry *p; + + dprintf("image @ %x (%d bytes)\n", addr, len); + dprintf("write to '%s' partition\n", name); + + p = flash_find_ptn(name); + + if(p == 0) { + jtag_fail("partition not found"); + return; + } else { + if(flash_init()) { + jtag_fail("flash_init() failed"); + return; + } + + dprintf("erasing flash @ %d (len=%d)\n", p->start, p->length); + flash_erase(p); + + if(len) { + dprintf("writing flash at @ %d\n", p->start); + + if(!strcmp(name, "system") || !strcmp(name, "userdata")) { + r = flash_write(p, 64, (void*) addr, len); + } else { + len = (len + FLASH_PAGE_SIZE - 1) & (~(FLASH_PAGE_SIZE-1)); + r = flash_write(p, 0, (void*) addr, len); + } + //verify_flash(p, addr, len, (!strcmp(name, "system") || !strcmp(name, "userdata")) ? 64 : 0); + if(r) { + jtag_fail("partition write failed"); + } else { + jtag_okay("partition written"); + } + return; + } else { + jtag_okay("partition erased"); + return; + } + } +} + +void hexdump(void *ptr, unsigned len) +{ + unsigned char *b = ptr; + int count = 0; + + dprintf("%x: ", (unsigned) b); + while(len-- > 0) { + dprintf("%b ", *b++); + if(++count == 16) { + dprintf("\n%x: ", (unsigned) b); + count = 0; + } + } + if(count != 0) dprintf("\n"); +} + +static unsigned char *tmpbuf = 0; + +void handle_dump(const char *name, unsigned offset) +{ + ptentry *p; + + if(tmpbuf == 0) { + tmpbuf = alloc(4096); + } + + dprintf("dump '%s' partition\n", name); + p = flash_find_ptn(name); + + if(p == 0) { + jtag_fail("partition not found"); + return; + } + + if(flash_init()) { + jtag_fail("flash_init() failed"); + return; + } + +#if 0 + /* XXX reimpl */ + if(flash_read_page(p->start * 64, tmpbuf, tmpbuf + 2048)){ + jtag_fail("flash_read() failed"); + return; + } +#endif + + dprintf("page %d data:\n", p->start * 64); + hexdump(tmpbuf, 256); + dprintf("page %d extra:\n", p->start * 64); + hexdump(tmpbuf, 16); + jtag_okay("done"); +} + +void handle_command(const char *cmd, unsigned a0, unsigned a1, unsigned a2) +{ + if(startswith(cmd,"flash:")){ + handle_flash(cmd + 6, a0, a1); + return; + } + + if(startswith(cmd,"dump:")){ + handle_dump(cmd + 5, a0); + return; + } + + jtag_fail("unknown command"); +} + +int _main(void) +{ + arm11_clock_init(); + + dprintf_set_putc(jtag_dputc); + + board_init(); + + jtag_cmd_loop(handle_command); + + return 0; +} |