summaryrefslogtreecommitdiff
path: root/nandwrite
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:28:41 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:28:41 -0800
commit076ef94d61f349f7cf0fe776e60456d8f232cca5 (patch)
tree6a7dfaaef61ff7ee33bb2036cd14b08583e70223 /nandwrite
parent84fe89dad95fa18a8950d130a2537db834333bb7 (diff)
downloadlegacy-076ef94d61f349f7cf0fe776e60456d8f232cca5.tar.gz
Diffstat (limited to 'nandwrite')
-rw-r--r--nandwrite/Android.mk20
-rw-r--r--nandwrite/init.S78
-rw-r--r--nandwrite/jtag.c114
-rw-r--r--nandwrite/nandwrite.c195
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;
+}