From 3a5df7e5042b6b25939c270f628d04f9c7ed21b3 Mon Sep 17 00:00:00 2001 From: SangHee Kim Date: Mon, 19 Apr 2010 18:02:19 +0900 Subject: [PATCH] recovery: restructure the recovery source tree, modify OneNAND driver --- Makefile | 6 +- cpu/arm_cortexa8/start.S | 2 +- recovery/board/samsung/universal/Makefile | 84 ++---- recovery/board/samsung/universal/recovery.lds | 2 +- recovery/onenand.c | 377 +++++++++++++++++++------- recovery/onenand.h | 30 +- recovery/recovery.c | 42 ++- recovery/usbd.c | 31 ++- recovery/usbd.h | 1 + 9 files changed, 383 insertions(+), 192 deletions(-) diff --git a/Makefile b/Makefile index 5695fae..423ddd5 100644 --- a/Makefile +++ b/Makefile @@ -378,19 +378,19 @@ $(obj)u-boot.lds: $(LDSCRIPT) $(CPP) $(CPPFLAGS) $(LDPPFLAGS) -ansi -D__ASSEMBLY__ -P - <$^ >$@ $(NAND_SPL): $(TIMESTAMP_FILE) $(VERSION_FILE) $(obj)include/autoconf.mk - $(MAKE) -C nand_spl/board/$(BOARDDIR) all + $(MAKE) -C nand_spl/board/$(BOARDDIR) all || exit 1 $(U_BOOT_NAND): $(NAND_SPL) $(obj)u-boot.bin cat $(obj)nand_spl/u-boot-spl-16k.bin $(obj)u-boot.bin > $(obj)u-boot-nand.bin $(ONENAND_IPL): $(TIMESTAMP_FILE) $(VERSION_FILE) $(obj)include/autoconf.mk - $(MAKE) -C onenand_ipl/board/$(BOARDDIR) all + $(MAKE) -C onenand_ipl/board/$(BOARDDIR) all || exit 1 $(U_BOOT_ONENAND): $(ONENAND_IPL) $(obj)u-boot.bin cat $(ONENAND_BIN) $(obj)u-boot.bin > $(obj)u-boot-onenand.bin $(RECOVERY_BLOCK): $(TIMESTAMP_FILE) $(VERSION_FILE) $(obj)include/autoconf.mk $(ONENAND_IPL) - $(MAKE) -C recovery/board/$(BOARDDIR) all + $(MAKE) -C recovery/ all || exit 1 $(U_BOOT_RECOVERY): $(RECOVERY_BLOCK) $(obj)u-boot.bin cat $(RECOVERY_BIN) $(obj)u-boot.bin > $(obj)u-boot-recovery.bin diff --git a/cpu/arm_cortexa8/start.S b/cpu/arm_cortexa8/start.S index 3926bbd..e91c82e 100644 --- a/cpu/arm_cortexa8/start.S +++ b/cpu/arm_cortexa8/start.S @@ -166,7 +166,7 @@ copy_loop: @ copy 32 bytes at a time /* Set up the stack */ stack_setup: ldr r0, _TEXT_BASE @ upper 128 KiB: relocated uboot -#if defined(CONFIG_ONENAND_IPL) || defined(CONFIG_RECOVERY_BLOCK) +#if defined(CONFIG_ONENAND_IPL) sub sp, r0, #128 @ leave 32 words for abort-stack #else sub r0, r0, #CONFIG_SYS_MALLOC_LEN @ malloc area diff --git a/recovery/board/samsung/universal/Makefile b/recovery/board/samsung/universal/Makefile index 569c0ce..59b8f10 100644 --- a/recovery/board/samsung/universal/Makefile +++ b/recovery/board/samsung/universal/Makefile @@ -13,79 +13,50 @@ include $(TOPDIR)/config.mk -# Recovery block' size should be 1 block (256K) -# Recovery block includes the onenand_ipl(16K), so actual size is 240K -TEXT_BASE = 0x34000000 -# 256K - 16K(IPL Size) -TEXT_BASE_256K = 0x3403C000 +RECOVERYCFG = config.mk +include $(RECOVERYCFG) -LDSCRIPT= $(TOPDIR)/recovery/board/$(BOARDDIR)/recovery.lds -LDFLAGS = -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS) -AFLAGS += -DCONFIG_RECOVERY_BLOCK -g -UTEXT_BASE -DTEXT_BASE=$(TEXT_BASE) -CFLAGS += -DCONFIG_RECOVERY_BLOCK -g -D__HAVE_ARCH_MEMCPY32 -OBJCFLAGS += --gap-fill=0x00 +LIB := $(obj)lib$(BOARD).a -SOBJS += start.o _memcpy32.o -COBJS += recovery.o onenand.o -COBJS += usbd.o usb_downloader.o usb-hs-otg.o +SOBJS = start.o reset.o _memcpy32.o +COBJS = string.o dlmalloc.o +COBJS += usb_downloader.o usb-hs-otg.o +COBJS += gpio.o +COBJS += universal.o -SRCS := $(addprefix $(obj),$(SOBJS:.o=.S) $(COBJS:.o=.c)) -OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) -__OBJS := $(SOBJS) $(COBJS) -LNDIR := $(OBJTREE)/recovery/board/$(BOARDDIR) +SRCS := $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) -recoveryobj := $(OBJTREE)/recovery/ +all: $(LIB) -ALL = $(recoveryobj)recovery $(recoveryobj)recovery.bin $(recoveryobj)recovery-256k.bin - -all: $(obj).depend $(ALL) - -$(recoveryobj)recovery-256k.bin: $(recoveryobj)recovery - $(OBJCOPY) ${OBJCFLAGS} --pad-to=$(TEXT_BASE_256K) -O binary $< $@ - cat $(OBJTREE)/onenand_ipl/onenand-ipl-16k-evt0.bin $@ > $(recoveryobj)recovery-evt0.bin - cat $(OBJTREE)/onenand_ipl/onenand-ipl-16k-fused.bin $@ > $(recoveryobj)recovery-fused.bin - cat $(OBJTREE)/onenand_ipl/onenand-ipl-16k.bin $@ > $(recoveryobj)recovery.bin - -$(recoveryobj)recovery.bin: $(recoveryobj)recovery - $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@ - -$(recoveryobj)recovery: $(OBJS) - cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \ - -Map $@.map -o $@ +$(LIB): $(obj).depend $(SOBJS) $(OBJS) $(RECOVERYCFG) + $(AR) $(ARFLAGS) $@ $(SOBJS) $(OBJS) # create symbolic links from common files -# from cpu directory $(obj)start.S: @rm -f $@ - ln -s $(SRCTREE)/cpu/$(CPU)/start.S $@ + ln -s $(SRCTREE)/cpu/$(CPU)/$@ $@ -# from SoC directory +$(obj)reset.S: + @rm -f $@ + ln -s $(SRCTREE)/cpu/$(CPU)/s5pc1xx/$@ $@ -# from lib_arm $(obj)_memcpy32.S: - ln -sf $(SRCTREE)/lib_arm/_memcpy32.S $@ - -# from recovery directory -$(obj)recovery.c: - @rm -f $@ - ln -s $(SRCTREE)/recovery/recovery.c $@ + ln -sf $(SRCTREE)/lib_arm/$@ $@ -$(obj)onenand.h: +$(obj)string.c: @rm -f $@ - ln -s $(SRCTREE)/recovery/onenand.h $@ + ln -s $(SRCTREE)/lib_generic/$@ $@ -$(obj)onenand.c: $(obj)onenand.h +$(obj)dlmalloc.c: @rm -f $@ - ln -s $(SRCTREE)/recovery/onenand.c $@ + ln -s $(SRCTREE)/common/$@ $@ -$(obj)usbd.h: - @rm -f $@ - ln -s $(SRCTREE)/recovery/usbd.h $@ +clean: + @rm -rf ../../../$(BOARDHEADER) -$(obj)usbd.c: $(obj)usbd.h - @rm -f $@ - ln -s $(SRCTREE)/recovery/usbd.c $@ +######################################################################### $(obj)%.o: $(obj)%.S $(CC) $(AFLAGS) -c -o $@ $< @@ -93,11 +64,8 @@ $(obj)%.o: $(obj)%.S $(obj)%.o: $(obj)$.c $(CC) $(CFLAGS) -c -o $@ $< -# defines $(obj).depend target include $(SRCTREE)/rules.mk sinclude $(obj).depend -clean: - rm recovery.c onenand.c - +######################################################################### diff --git a/recovery/board/samsung/universal/recovery.lds b/recovery/board/samsung/universal/recovery.lds index 559f9f2..1c98cf3 100644 --- a/recovery/board/samsung/universal/recovery.lds +++ b/recovery/board/samsung/universal/recovery.lds @@ -33,7 +33,7 @@ SECTIONS . = ALIGN(4); .text : { - start.o (.text) + board/samsung/universal/start.o (.text) *(.text) } diff --git a/recovery/onenand.c b/recovery/onenand.c index 7409c68..55b31c5 100644 --- a/recovery/onenand.c +++ b/recovery/onenand.c @@ -22,141 +22,314 @@ */ #include +#include + +#include +#include +#include #include -#include #include "onenand.h" -#define onenand_block_address(block) (block) -#define onenand_sector_address(page) (page << 2) -#define onenand_buffer_address() ((1 << 3) << 8) -#define onenand_bufferram_address(block) (0) - -#ifdef __HAVE_ARCH_MEMCPY32 -extern void *memcpy32(void *dest, void *src, int size); +#ifdef printk +#undef printk +#endif +#define printk(...) do{} while(0) +#define puts(...) do{} while(0) +#ifdef printf +#undef printf #endif +#define printf(...) do{} while(0) + +struct mtd_info onenand_mtd; +struct onenand_chip onenand_chip; +struct onenand_op onenand_ops; + +static __attribute__((unused)) char dev_name[] = "onenand0"; +static struct mtd_info *mtd = &onenand_mtd; -int (*onenand_read_page)(ulong block, ulong page, u_char *buf, int pagesize); +static loff_t next_ofs; +static loff_t skip_ofs; -/* read a page with ECC */ -static int generic_onenand_read_page(ulong block, ulong page, - u_char * buf, int pagesize) +static inline int str2long(char *p, ulong *num) { - unsigned long *base; + char *endptr; -#ifndef __HAVE_ARCH_MEMCPY32 - unsigned int offset, value; - unsigned long *p; + *num = simple_strtoul(p, &endptr, 16); + return (*p != '\0' && *endptr == '\0') ? 1 : 0; +} +#if 0 +static int arg_off_size(int argc, char *argv[], ulong *off, ssize_t *size) +{ + if (argc >= 1) { + if (!(str2long(argv[0], off))) { + printf("'%s' is not a number\n", argv[0]); + return -1; + } + } else { + *off = 0; + } + + if (argc >= 2) { + if (!(str2long(argv[1], (ulong *)size))) { + printf("'%s' is not a number\n", argv[1]); + return -1; + } + } else { + *size = mtd->size - *off; + } + + if ((*off + *size) > mtd->size) { + printf("total chip size (0x%llx) exceeded!\n", mtd->size); + return -1; + } +#if 0 + if (*size == mtd->size) + puts("whole chip\n"); + else + printf("offset 0x%lx, size 0x%x\n", *off, *size); +#endif + return 0; +} #endif +static int onenand_block_read(loff_t from, ssize_t len, + ssize_t *retlen, u_char *buf, int oob) +{ + struct onenand_chip *this = mtd->priv; + int blocksize = (1 << this->erase_shift); + loff_t ofs = from; + struct mtd_oob_ops ops = { + .retlen = 0, + }; + ssize_t thislen; + int ret; - onenand_writew(onenand_block_address(block), - ONENAND_REG_START_ADDRESS1); + while (len > 0) { + thislen = min_t(ssize_t, len, blocksize); + thislen = ALIGN(thislen, mtd->writesize); - onenand_writew(onenand_bufferram_address(block), - ONENAND_REG_START_ADDRESS2); + ret = mtd->block_isbad(mtd, ofs); + if (ret) { + printk("Bad blocks %d at 0x%x\n", + (u32)(ofs >> this->erase_shift), (u32)ofs); + ofs += blocksize; + /* FIXME need to check how to handle the 'len' */ + len -= blocksize; + continue; + } - onenand_writew(onenand_sector_address(page), - ONENAND_REG_START_ADDRESS8); + if (oob) { + ops.oobbuf = buf; + ops.ooblen = thislen; + } else { + ops.datbuf = buf; + ops.len = thislen; + } - onenand_writew(onenand_buffer_address(), - ONENAND_REG_START_BUFFER); + ops.retlen = 0; + ret = mtd->read_oob(mtd, ofs, &ops); + if (ret) { + printk("Read failed 0x%x, %d\n", (u32)ofs, ret); + ofs += thislen; + continue; + } + ofs += thislen; + buf += thislen; + len -= thislen; + *retlen += ops.retlen; + } - onenand_writew(ONENAND_INT_CLEAR, ONENAND_REG_INTERRUPT); + return 0; +} - onenand_writew(ONENAND_CMD_READ, ONENAND_REG_COMMAND); +static int onenand_block_write(loff_t to, ssize_t len, + ssize_t *retlen, u_char * buf) +{ + struct onenand_chip *this = mtd->priv; + int blocksize = (1 << this->erase_shift); + struct mtd_oob_ops ops = { + .retlen = 0, + .oobbuf = NULL, + }; + loff_t ofs; + ssize_t thislen; + int ret; -#ifndef __HAVE_ARCH_MEMCPY32 - p = (unsigned long *) buf; -#endif - base = (unsigned long *) (CONFIG_SYS_ONENAND_BASE + ONENAND_DATARAM); + if (to == next_ofs) { + next_ofs = to + len; + to += skip_ofs; + } else { + next_ofs = to + len; + skip_ofs = 0; + } + ofs = to; - while (!(READ_INTERRUPT() & ONENAND_INT_READ)) - continue; + while (len > 0) { + thislen = min_t(ssize_t, len, blocksize); + thislen = ALIGN(thislen, mtd->writesize); - /* Check for invalid block mark */ - if (page < 2 && (onenand_readw(ONENAND_SPARERAM) != 0xffff)) - return 1; + ret = mtd->block_isbad(mtd, ofs); + if (ret) { + printk("Bad blocks %d at 0x%x\n", + (u32)(ofs >> this->erase_shift), (u32)ofs); + skip_ofs += blocksize; + goto next; + } -#ifdef __HAVE_ARCH_MEMCPY32 - /* 32 bytes boundary memory copy */ - memcpy32(buf, base, pagesize); -#else - for (offset = 0; offset < (pagesize >> 2); offset++) { - value = *(base + offset); - *p++ = value; + ops.datbuf = (u_char *) buf; + ops.len = thislen; + ops.retlen = 0; + ret = mtd->write_oob(mtd, ofs, &ops); + if (ret) { + printk("Write failed 0x%x, %d", (u32)ofs, ret); + skip_ofs += thislen; + goto next; + } + + buf += thislen; + len -= thislen; + if (retlen != NULL) + *retlen += ops.retlen; +next: + ofs += blocksize; } -#endif return 0; } -#ifndef CONFIG_ONENAND_START_PAGE -#define CONFIG_ONENAND_START_PAGE 1 -#endif -#define ONENAND_PAGES_PER_BLOCK 64 - -static int onenand_generic_init(int *page_is_4KiB, int *page) +static int onenand_block_erase(u32 start, u32 size, int force) { - int dev_id, density; - - if (onenand_readw(ONENAND_REG_TECHNOLOGY)) - *page_is_4KiB = 1; - dev_id = onenand_readw(ONENAND_REG_DEVICE_ID); - density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT; - density &= ONENAND_DEVICE_DENSITY_MASK; - if (density >= ONENAND_DEVICE_DENSITY_4Gb && - !(dev_id & ONENAND_DEVICE_IS_DDP)) - *page_is_4KiB = 1; - - return ONENAND_USE_DEFAULT; -} + struct onenand_chip *this = mtd->priv; + struct erase_info instr = { + .callback = NULL, + }; + loff_t ofs; + int ret; + int blocksize = 1 << this->erase_shift; -int onenand_board_init(int *page_is_4KiB, int *page) - __attribute__((weak, alias("onenand_generic_init"))); + for (ofs = start; ofs < (start + size); ofs += blocksize) { + ret = mtd->block_isbad(mtd, ofs); + if (ret && !force) { + printf("Skip erase bad block %d at 0x%x\n", + (u32)(ofs >> this->erase_shift), (u32)ofs); + continue; + } -/** - * onenand_read_block - Read CONFIG_RECOVERY_BOOT_BLOCKS from block #1 - * @return 0 on success - */ -int onenand_read_block(unsigned char *buf) + instr.addr = ofs; + instr.len = blocksize; + instr.priv = force; + instr.mtd = mtd; + ret = mtd->erase(mtd, &instr); + if (ret) { + printf("erase failed block %d at 0x%x\n", + (u32)(ofs >> this->erase_shift), (u32)ofs); + continue; + } + } + + return 0; +} +#if 0 +static int onenand_dump(struct mtd_info *mtd, ulong off, int only_oob) { - int block, nblocks; - int page = 0, offset = 0; - int pagesize, erase_shift; - int page_is_4KiB = 0, ret; - - pagesize = 2048; /* OneNAND has 2KiB pagesize */ - erase_shift = 17; - onenand_read_page = generic_onenand_read_page; - - ret = onenand_board_init(&page_is_4KiB, &page); - if (ret == ONENAND_USE_GENERIC) - onenand_generic_init(&page_is_4KiB, &page); - - if (page_is_4KiB) { - pagesize = 4096; /* OneNAND has 4KiB pagesize */ - erase_shift = 18; + int i; + u_char *datbuf, *oobbuf, *p; + struct mtd_oob_ops ops; + loff_t addr; + + datbuf = malloc(mtd->writesize + mtd->oobsize); + oobbuf = malloc(mtd->oobsize); + if (!datbuf || !oobbuf) { + puts("No memory for page buffer\n"); + return 1; + } + off &= ~(mtd->writesize - 1); + addr = (loff_t) off; + memset(&ops, 0, sizeof(ops)); + ops.datbuf = datbuf; + ops.oobbuf = oobbuf; /* must exist, but oob data will be appended to ops.datbuf */ + ops.len = mtd->writesize; + ops.ooblen = mtd->oobsize; + ops.retlen = 0; + i = mtd->read_oob(mtd, addr, &ops); + if (i < 0) { + printf("Error (%d) reading page %08lx\n", i, off); + free(datbuf); + free(oobbuf); + return 1; } + printf("Page %08lx dump:\n", off); + i = mtd->writesize >> 4; + p = datbuf; - nblocks = CONFIG_RECOVERY_BOOT_BLOCKS; - - /* NOTE: you must read page from page 1 of block 0 */ - /* read the block page by page */ - for (block = 1; block < nblocks; block++) { - for (; page < ONENAND_PAGES_PER_BLOCK; page++) { - if (onenand_read_page(block, page, buf + offset, - pagesize)) { - /* This block is bad. Skip it - * and read next block */ - offset -= page * pagesize; - nblocks++; - break; - } - offset += pagesize; - } - page = 0; + while (i--) { + if (!only_oob) + printf("\t%02x %02x %02x %02x %02x %02x %02x %02x" + " %02x %02x %02x %02x %02x %02x %02x %02x\n", + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], + p[8], p[9], p[10], p[11], p[12], p[13], p[14], + p[15]); + p += 16; + } + puts("OOB:\n"); + p = oobbuf; + i = mtd->oobsize >> 3; + while (i--) { + printf("\t%02x %02x %02x %02x %02x %02x %02x %02x\n", + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); + p += 8; } + free(datbuf); + free(oobbuf); return 0; } +#endif +void onenand_set_interface(struct onenand_op *onenand) +{ + onenand->read = onenand_block_read; + onenand->write = onenand_block_write; + onenand->erase = onenand_block_erase; + + onenand->mtd = &onenand_mtd; + onenand->this = &onenand_chip; +} + +struct onenand_op *onenand_get_interface(void) +{ + return &onenand_ops; +} + +void onenand_init(void) +{ + memset(&onenand_mtd, 0, sizeof(struct mtd_info)); + memset(&onenand_chip, 0, sizeof(struct onenand_chip)); + memset(&onenand_ops, 0, sizeof(struct onenand_op)); + + onenand_mtd.priv = &onenand_chip; + + onenand_chip.base = (void *) CONFIG_SYS_ONENAND_BASE; + /*onenand_chip.options |= ONENAND_RUNTIME_BADBLOCK_CHECK;*/ + + onenand_scan(&onenand_mtd, 1); + +#if 0 + if (onenand_chip.device_id & DEVICE_IS_FLEXONENAND) + puts("Flex-"); + puts("OneNAND: "); + print_size(onenand_chip.chipsize, "\n"); +#endif + +#if 0 + /* + * Add MTD device so that we can reference it later + * via the mtdcore infrastructure (e.g. ubi). + */ + onenand_mtd.name = dev_name; + add_mtd_device(&onenand_mtd); +#else + onenand_set_interface(&onenand_ops); +#endif +} + diff --git a/recovery/onenand.h b/recovery/onenand.h index 70dcb53..e629cce 100644 --- a/recovery/onenand.h +++ b/recovery/onenand.h @@ -17,26 +17,20 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ + +#ifndef _ONENAND_H +#define _ONENAND_H -#ifndef _ONENAND_IPL_H -#define _ONENAND_IPL_H +struct onenand_op { + int (*read)(loff_t, ssize_t, ssize_t *, u_char *, int); + int (*write)(loff_t, ssize_t, ssize_t *, u_char *); + int (*erase)(u32, u32, int); -#include - -#define onenand_readw(a) readw(THIS_ONENAND(a)) -#define onenand_writew(v, a) writew(v, THIS_ONENAND(a)) - -#define THIS_ONENAND(a) (CONFIG_SYS_ONENAND_BASE + (a)) - -#define READ_INTERRUPT() onenand_readw(ONENAND_REG_INTERRUPT) - -enum { - ONENAND_USE_DEFAULT, - ONENAND_USE_GENERIC, - ONENAND_USE_BOARD, + struct mtd_info *mtd; + struct onenand_chip *this; }; -extern int (*onenand_read_page)(ulong block, ulong page, - u_char *buf, int pagesize); -extern int onenand_read_block(unsigned char *buf); +struct onenand_op *onenand_get_interface(void); +void onenand_init(void); + #endif diff --git a/recovery/recovery.c b/recovery/recovery.c index b509805..7c56132 100644 --- a/recovery/recovery.c +++ b/recovery/recovery.c @@ -22,19 +22,55 @@ */ #include +#include +#include "common.h" +#include "usbd.h" #include "onenand.h" typedef int (init_fnc_t)(void); -void start_recovery_boot(void) +void normal_boot(void) { uchar *buf; buf = (uchar *)CONFIG_SYS_BOOT_ADDR; - onenand_read_block(buf); + board_load_uboot(buf); ((init_fnc_t *)CONFIG_SYS_BOOT_ADDR)(); +} + +void recovery_boot(void) +{ + /* usb download and write image */ + do_usbd_down(); + + /* reboot */ + reset_cpu(0); +} + +void start_recovery_boot(void) +{ + /* armboot_start is defined in the board-specific linker script */ + mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN, + CONFIG_SYS_MALLOC_LEN); + + onenand_init(); + + board_recovery_init(); + + if (board_check_condition()) { + recovery_boot(); + } else { + normal_boot(); + } + /* NOTREACHED - no way out of command loop except booting */ +} - /* should never come here */ +/* + * origin at lib_arm/eabi_compat.c to support EABI + */ +int raise (int signum) +{ + return 0; } diff --git a/recovery/usbd.c b/recovery/usbd.c index a850718..c26ffc2 100644 --- a/recovery/usbd.c +++ b/recovery/usbd.c @@ -7,7 +7,8 @@ */ #include -#include +#include "usbd.h" +#include "onenand.h" #define OPS_READ 0 #define OPS_WRITE 1 @@ -15,6 +16,28 @@ static struct usbd_ops usbd_ops; static unsigned long down_ram_addr; +int update_boot_image(void) +{ + struct onenand_op *onenand_ops = onenand_get_interface(); + ulong len, offset; + +#if 1 + /* case: IPL, Recovery, u-boot are one file */ + offset = 0; + len = CONFIG_RECOVERY_SIZE + CONFIG_RECOVERY_ADDR; +#else + /* case: IPL, Recover are one file and u-boot is another */ + offset = CONFIG_RECOVERY_ADDR; + len = CONFIG_RECOVERY_SIZE; +#endif + /* Erase */ + onenand_ops->erase(offset, len, 0); + /* Write */ + onenand_ops->write(offset, len, NULL, (u_char *)down_ram_addr); + + return 0; +} + /* Parsing received data packet and Process data */ static int process_data(struct usbd_ops *usbd) { @@ -83,11 +106,7 @@ static int process_data(struct usbd_ops *usbd) /* Erase and Write to NAND */ switch (img_type) { case IMG_BOOT: - /* TO DO */ - /* Erase */ - /* Write */ - /* offset: CONFIG_RECOVERY_ADDR */ - /* size: CONFIG_RECOVERY_SIZE */ + update_boot_image(); break; default: diff --git a/recovery/usbd.h b/recovery/usbd.h index 2728ee5..66bfdaf 100644 --- a/recovery/usbd.h +++ b/recovery/usbd.h @@ -119,6 +119,7 @@ struct usbd_ops { void (*cpu_reset)(void); }; +int do_usbd_down(void); /* This function is interfaced between USB Device Controller and USB Downloader * Must Implementation this function at USB Controller!! */ struct usbd_ops *usbd_set_interface(struct usbd_ops *); -- 2.7.4