[T106][ZXW-22]7520V3SCV2.01.01.02P42U09_VEC_V0.8_AP_VEC origin source commit

Change-Id: Ic6e05d89ecd62fc34f82b23dcf306c93764aec4b
diff --git a/boot/common/src/uboot/downloader/Makefile b/boot/common/src/uboot/downloader/Makefile
new file mode 100644
index 0000000..77d377d
--- /dev/null
+++ b/boot/common/src/uboot/downloader/Makefile
@@ -0,0 +1,52 @@
+#

+# (C) Copyright 2000-2006

+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.

+#

+# See file CREDITS for list of people who contributed to this

+# project.

+#

+# This program is free software; you can redistribute it and/or

+# modify it under the terms of the GNU General Public License as

+# published by the Free Software Foundation; either version 2 of

+# the License, or (at your option) any later version.

+#

+# This program is distributed in the hope that it will be useful,

+# but WITHOUT ANY WARRANTY; without even the implied warranty of

+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

+# GNU General Public License for more details.

+#

+# You should have received a copy of the GNU General Public License

+# along with this program; if not, write to the Free Software

+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,

+# MA 02111-1307 USA

+#

+

+include $(TOPDIR)/config.mk

+

+#CFLAGS += -DET_DEBUG -DDEBUG

+

+LIB	= $(obj)libdownloader.o

+

+COBJS-y += cmd_downloader.o  cmd_getvar.o downloader_nand.o downloader_serial.o boot_usb.o 

+COBJS-y += cmd_erase.o  cmd_cp_reset.o cmd_ram_start.o cmd_testusb.o 

+COBJS-y += cmd_dl_nand.o cmd_dl_yaffs.o cmd_dl_ram.o cmd_set.o cmd_dl_raw.o 

+COBJS-y += cmd_compat_read.o cmd_compat_write.o 

+COBJS-y += cmd_bbt_count.o cmd_efuse_program.o

+

+COBJS	:= $(COBJS-y)

+SRCS	:= $(COBJS:.o=.c)

+OBJS	:= $(addprefix $(obj),$(COBJS))

+

+all:	$(LIB)

+

+$(LIB):	$(obj).depend $(OBJS)

+	$(call cmd_link_o_target, $(OBJS))

+

+#########################################################################

+

+# defines $(obj).depend target

+include $(SRCTREE)/rules.mk

+

+sinclude $(obj).depend

+

+#########################################################################

diff --git a/boot/common/src/uboot/downloader/boot_usb.c b/boot/common/src/uboot/downloader/boot_usb.c
new file mode 100644
index 0000000..a632802
--- /dev/null
+++ b/boot/common/src/uboot/downloader/boot_usb.c
@@ -0,0 +1,248 @@
+#include <usb/global.h>

+#include <usb/config.h>

+extern WORD32 USB_CDC_Enum(WORD32 USB_ADDR);

+//extern void USB_Pll_Clk_Rst_InitEnv(void);

+

+void USB_TstDev_InitEnv(void);

+

+#if 0

+void tsp_usb_init(WORD32 USB_ADDR)

+{

+    WORD32 dwConnect;

+

+    /*ÅäÖÃÍâΧ»·¾³*/

+

+    USB_Pll_Clk_Rst_InitEnv();

+  

+    dwConnect=USB_CDC_Enum(USB_ADDR);

+

+    if(0==dwConnect)

+    {

+        printk("NOLINK\n");

+        return ;

+    }

+

+    printk("FAILED\n");

+

+}

+#endif

+

+int tsp_usb_init(void)

+{

+	WORD32 retVal = 0;

+	WORD32 usb_addr = 0;

+//	BYTE boot_mode = get_boot_mode();

+	BYTE boot_mode = 1;

+	data_init();

+	/*add by sunyunchen*/

+	if(2 == boot_mode)

+	//if(0)

+	{ 

+	    printf("hsic\n");

+		global.g_USB_MODE = 1;

+	    usb_addr = SYS_USB_HSIC_BASE;

+	}

+	else 

+	{ 

+	    printf("usb\n");

+		global.g_USB_MODE = 0;

+        usb_addr = SYS_USB_BASE;

+	}

+	if((REG32(usb_addr+DWC_DEV_GLOBAL_REG_OFFSET)&0x7f0)!=0)//dcfg register

+	{

+	    //printf("usb_g_enum!\n");

+		global.g_enum =DONOT_NEED_ENUM; 

+

+

+		//global.g_enum =NEED_ENUM; 

+	}

+	if(NEED_ENUM == global.g_enum)

+	{

+	         //printf("need enum\n");

+	         USB_TstDev_InitEnv();

+	}

+	else

+	{

+	    //printf("global.g_dwc\n");

+		global.g_dwc_otg_pcd_tp.ep0state = EP0_IDLE;

+		global.dwRxQuit = 1;

+		global.dwTxQuit = 1;

+		global.g_dwc_otg_pcd_tp.request_config = 1;		

+	}

+

+	retVal = USB_CDC_Enum(usb_addr);

+	

+	return retVal;

+}

+

+void USB_TstDev_InitEnv(void)

+{

+#if USE_ASIC

+    WORD32 i;

+    if(0 == global.g_USB_MODE)

+    {

+

+    //ÊÍ·ÅUSB¸ôÀë8bit for usb ctrl

+    	REG32(POWER_DOMAIN_ISO) |= (1<<8);

+		usdelay(10);

+

+		REG32(POWER_DOMAIN_RST) |= (1<<8);

+		usdelay(10);

+

+		REG32(POWER_DOMAIN_POWERON) &= ~(1<<8);

+		usdelay(10);

+		

+		REG32(POWER_DOMAIN_POWERON) |= (1<<8);

+		usdelay(10);

+		

+		REG32(POWER_DOMAIN_RST) &= ~(1<<8);

+		usdelay(10);

+		

+		REG32(POWER_DOMAIN_ISO) &= ~(1<<8);

+		usdelay(10);

+

+          //usb  ahb clock enable

+        REG32(SOC_MOD_CLKEN0)&=~(1<<4);

+        usdelay(20);

+        REG32(SOC_MOD_CLKEN0)|=(1<<4);

+        //usb  phy clock enable

+        REG32(SOC_MOD_CLKEN1)&=~(1<<3);

+        usdelay(20);

+        REG32(SOC_MOD_CLKEN1)|=(1<<3);

+

+        // usb  ahb reset  ÏÈ×ÜÏߺó¹¤×÷

+        REG32(SOC_MOD_RSTEN)&=~(1<<5);

+        usdelay(100);

+        REG32(SOC_MOD_RSTEN)|=(1<<5);

+        usdelay(100);

+

+        // usb  work reset

+        REG32(SOC_MOD_RSTEN)&=~(1<<4);

+        usdelay(100);

+        REG32(SOC_MOD_RSTEN)|=(1<<4);

+		usdelay(100);

+

+        //release usb  phy reset 

+        REG32(SOC_MOD_RSTEN)&=~(1<<3);

+        usdelay(100);

+        REG32(SOC_MOD_RSTEN) |= 1<<3;

+        usdelay(100);

+		

+        i = 0;

+        while((REG32(SOC_MOD_USBSTATECTRL)&0x2) == 0)

+        {

+             i++;

+             usdelay(20);

+             if(i>50000) break;

+        }

+     }

+    else

+    {

+        //ÊÍ·ÅUSB_HSIC¸ôÀë9bit for hsic

+    	REG32(POWER_DOMAIN_ISO) |= (1<<9);

+		usdelay(10);

+

+		REG32(POWER_DOMAIN_RST) |= (1<<9);

+		usdelay(10);

+

+		REG32(POWER_DOMAIN_POWERON) &= ~(1<<9);

+		usdelay(10);

+		

+		REG32(POWER_DOMAIN_POWERON) |= (1<<9);

+		usdelay(10);

+		

+		REG32(POWER_DOMAIN_RST) &= ~(1<<9);

+		usdelay(10);

+		

+		REG32(POWER_DOMAIN_ISO) &= ~(1<<9);

+		usdelay(10);

+

+        //usb hsic ahb clock enable

+        REG32(SOC_MOD_CLKEN0)&=~(1<<2);

+        usdelay(20);

+        REG32(SOC_MOD_CLKEN0)|=(1<<2);

+        //usb hsic phy clock enable

+        REG32(SOC_MOD_CLKEN0)&=~(1<<1);

+        usdelay(20);

+        REG32(SOC_MOD_CLKEN0)|=(1<<1);

+

+        //usb hsic 480M clock enable

+        REG32(SOC_MOD_CLKEN0)&=~(1<<0);

+        usdelay(20);

+        REG32(SOC_MOD_CLKEN0)|=(1<<0);

+

+        // usb hsic ahb reset

+        REG32(SOC_MOD_RSTEN)&=~(1<<2);

+        usdelay(20);

+        REG32(SOC_MOD_RSTEN)|=(1<<2);

+        usdelay(10);

+

+        // usb hsic work reset

+        REG32(SOC_MOD_RSTEN)&=~(1<<1);

+        usdelay(20);

+        REG32(SOC_MOD_RSTEN)|=(1<<1);

+        //release usb hsic phy reset 

+        REG32(SOC_MOD_RSTEN)&=~(1<<0);

+        usdelay(20);

+        REG32(SOC_MOD_RSTEN)|=(1<<0);

+

+        usdelay(100);

+        i = 0;

+        while((REG32(SOC_MOD_USBSTATECTRL)&0x1) == 0)

+        {

+            i++;

+            usdelay(20);

+            if(i>50000) break;  

+        }

+

+#if SYNC_USB_HSIC

+        usdelay(20);

+		REG32(REG_GPIO_OUT)=1;

+        while(REG32(REG_GPIO_IN)!=0xFF);

+		usdelay(1);

+		REG32(REG_GPIO_OUT)=0;		

+#endif

+    }

+#endif  

+#if !USE_ASIC

+#if 1

+//usb power on

+    REG32(POWER_DOMAIN_POWERON) |= 0x300;

+    usdelay(10);

+//usb disable reset 

+    REG32(POWER_DOMAIN_RST) &= 0xfffffcff; //

+    usdelay(10);

+//usb disable iso 

+    REG32(POWER_DOMAIN_ISO) &= 0xfffffcff;

+    usdelay(10);

+

+//open usb0 and usb1

+    //usb ahb clock enable

+    REG32(SOC_MOD_CLKEN0)&=0xeffffffb;

+    usdelay(20);

+    REG32(SOC_MOD_CLKEN0)|=0x10000004;

+    //usb phy clock enable

+    REG32(SOC_MOD_CLKEN1)&=~(3<<16);

+    usdelay(20);

+    REG32(SOC_MOD_CLKEN1)|=(3<<16);

+

+

+    // usb ctr reset

+    REG32(SOC_MOD_RSTEN)&=0xeffffff7;

+    usdelay(20);

+    REG32(SOC_MOD_RSTEN)|=0x10000008;

+

+    // usb ahb reset

+    REG32(SOC_MOD_RSTEN)&=0xf7fffffb;

+    usdelay(20);

+    REG32(SOC_MOD_RSTEN)|=0x8000004;

+#endif

+/*    

+  usb ctr and ahb reset release ,delay 60us, check usb reset state,

+  if the reset state is 0, reset ,if 1,reset release.

+*/

+#endif

+}

+

+

+

diff --git a/boot/common/src/uboot/downloader/cmd_bbt_count.c b/boot/common/src/uboot/downloader/cmd_bbt_count.c
new file mode 100644
index 0000000..0f1cf52
--- /dev/null
+++ b/boot/common/src/uboot/downloader/cmd_bbt_count.c
@@ -0,0 +1,398 @@
+/*******************************************************************************
+ * Copyright (C) 2016, ZIXC Corporation.
+ *
+ * File Name:cmd_bbt_count.c
+ * File Mark:
+ * Description:
+ * Others:
+ * Version:       1.0
+ * Author:        lankai
+ * Date:          2017-12-14
+ * History 1:
+ *     Date:
+ *     Version:
+ *     Author:
+ *     Modification:
+ * History 2:
+  ********************************************************************************/
+
+
+/****************************************************************************
+* 	                                     Include files
+****************************************************************************/
+#include <common.h>
+#include <command.h>
+#include <nand.h>
+
+#include "downloader_serial.h"
+#include "errno.h"
+#include <partition_table.h>
+#include <boot_mode.h>
+
+/****************************************************************************
+*							Global Function Prototypes
+****************************************************************************/
+int crc_switch_flag = 0;
+extern char *tsp_console_buffer;
+extern partition_table_t *g_partition_table_dl;
+extern partition_table_t *g_partition_table;
+
+
+/*******************************************************************************
+ * Function:do_bbt_count
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+ int do_bbt_count(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	struct mtd_info *mtd = get_mtd_info();
+	struct nand_chip *this = NULL;
+	int bad_block_num = 0;
+	int total_block_num = 0;
+	char ack[64] = {0};
+
+	if(argc != 1)
+    {
+        return cmd_usage(cmdtp);
+    }
+
+    if (NULL == mtd)
+    {
+    	printf("FAIL\n");
+    	return ENODEV;
+    }
+
+	this = mtd->priv;
+	bad_block_num = mtd->ecc_stats.badblocks;
+	total_block_num = this->chipsize >> this->bbt_erase_shift;
+
+	sprintf(ack, "bad_block_num:%04d total_block_num:%04d", bad_block_num, total_block_num);
+	downloader_serial_write(ack, strlen(ack) + 1);
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	bbt_count, CONFIG_SYS_MAXARGS, 0, do_bbt_count,	"bbt_count", ""
+);
+
+/*******************************************************************************
+ * Function:do_crc
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+ int do_crc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	u_char *crc_flag = NULL;
+	char *ack = tsp_console_buffer;
+	
+	if(argc<2)
+	{
+		return cmd_usage(cmdtp);
+	}
+	crc_flag = argv[1]; 
+
+	if (strcmp((const char *)crc_flag,"on") == 0)
+	{
+        crc_switch_flag = 1;
+		sprintf(ack,"OKAY");
+	}
+    else if (strcmp((const char *)crc_flag,"off") == 0)
+    {
+        crc_switch_flag = 0;
+		sprintf(ack,"OKAY");
+    }
+	else
+	{
+		sprintf(ack,"FAIL COMMAND ERROR");
+	}
+
+	downloader_serial_write(ack, strlen(ack)+1);
+	
+	return 0;
+}
+
+U_BOOT_CMD(
+	crc, CONFIG_SYS_MAXARGS, 0, do_crc,	"crc_check", ""
+);
+
+
+/*******************************************************************************
+ * Function:do_crc
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+ int do_partition_bbc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	int i, j, len, bad_nums, partition_nums;
+	char *ack = tsp_console_buffer;
+	nand_info_t *nand = &nand_info[nand_curr_device];
+	
+	if(argc != 1)
+	{
+		return cmd_usage(cmdtp);
+	}
+
+	partition_entry_t *entry = NULL;
+	uint32_t entry_nums = 0;
+	if(get_load_mode() == TLOAD_MODE)
+	{
+		entry_nums = g_partition_table_dl->entrys;
+		entry = &g_partition_table_dl->table[0];
+	}
+	else
+	{
+		entry_nums = g_partition_table->entrys;
+		entry = &g_partition_table->table[0];
+	}
+
+	sprintf(ack, "partition_nums:%04d", entry_nums - 2);
+
+	printf("entry_nums=%d\n", entry_nums - 2);
+
+	for(i = 0; i < entry_nums - 2; i++)
+	{ 
+		printf("entry->part_offset=0x%x, entry->part_size=0x%x\n", 
+				entry->part_offset, entry->part_size);
+		bad_nums = 0;
+		partition_nums = entry->part_size / nand->erasesize;
+		for(j = 0; j < partition_nums; j++)
+		{
+			if(nand_block_isbad (nand, entry->part_offset + (loff_t)j * nand->erasesize))
+			{
+				printf("bad block addr = 0x%x\n", (entry->part_offset + j * nand->erasesize));
+				bad_nums++;
+			}
+		}
+
+		len = strlen(ack);
+		sprintf(ack + len, " %s,%04d,%04d", entry->part_name, bad_nums, partition_nums);
+		entry++;
+	}
+
+	printf("partition_bbc:%s\n", ack);
+	
+	downloader_serial_write(ack, strlen(ack) + 1);
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	part_bbc, CONFIG_SYS_MAXARGS, 0, do_partition_bbc, "partition bad block count", ""
+);
+
+
+/*******************************************************************************
+ * Function:do_single_partition_bbc
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+ int do_single_partition_bbc(cmd_tbl_t *cmdtp, int flag, 
+ 							 int argc, char * const argv[])
+{
+	int j, bad_nums, part_block_nums;
+	u_char *partition_name = NULL;
+	char *ack = tsp_console_buffer;
+	nand_info_t *nand = &nand_info[nand_curr_device];
+	partition_entry_t *entry = NULL;
+	
+	if(argc < 2)
+	{
+		return cmd_usage(cmdtp);
+	}
+
+	partition_name = argv[1];
+
+	entry = find_partition_para(partition_name);
+	if(entry == NULL)
+	{
+		BOOT_PRINTF(UBOOT_ERR, "[%s]: can't find the partition...\n", partition_name);
+		return 1;
+	}
+	
+	printf("entry->part_offset=0x%x, entry->part_size=0x%x\n", 
+			entry->part_offset, entry->part_size);
+	bad_nums = 0;
+	part_block_nums = entry->part_size / nand->erasesize;
+	for(j = 0; j < part_block_nums; j++)
+	{
+		if(nand_block_isbad (nand, entry->part_offset + (loff_t)j * nand->erasesize))
+		{
+			printf("bad block addr = 0x%x\n", (entry->part_offset + j * nand->erasesize));
+			bad_nums++;
+		}
+	}
+
+	sprintf(ack, "%s,%04d,%04d", entry->part_name, bad_nums, part_block_nums);
+	printf("single_partition_bbc:%s\n", ack);	
+	downloader_serial_write(ack, strlen(ack) + 1);
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	single_part_bbc, CONFIG_SYS_MAXARGS, 0, do_single_partition_bbc, 
+	"single partition bad block count", ""
+);
+
+
+/*******************************************************************************
+ * Function:do_badblock_query
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+ int do_badblock_query(cmd_tbl_t *cmdtp, 
+ 					   int flag, 
+ 					   int argc, 
+ 					   char * const argv[])
+{
+	u_char *crc_flag = NULL;
+	int flash_type = 0;
+	char *ack = tsp_console_buffer;
+	
+	if(argc != 1)
+	{
+		return cmd_usage(cmdtp);
+	}
+
+	crc_flag = argv[0]; 	
+	if(strcmp((const char *)crc_flag,"badblock_query") != 0)
+	{
+		sprintf(ack,"COMMAND ERROR");	
+		downloader_serial_write(ack, strlen(ack) + 1);
+		return -1;
+	}
+
+	flash_type = read_boot_flashtype();
+	switch(flash_type)
+	{
+		case IF_TYPE_NAND:
+		case IF_TYPE_SPI_NAND:		
+			sprintf(ack,"SUPPORT");
+			break;
+		default:
+			sprintf(ack,"UNSUPPORT");
+			break;
+	}	
+	downloader_serial_write(ack, strlen(ack) + 1);
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	badblock_query, CONFIG_SYS_MAXARGS, 0, do_badblock_query, 
+	"is support bad block query", ""
+);
+
+/*
+ ******************************************************************************
+ * Function:do_part_valid_space_query
+ * Description:
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ *******************************************************************************
+ */
+ int do_part_valid_space_query(cmd_tbl_t *cmdtp, int flag, 
+ 							 int argc, char * const argv[])
+{
+	int j, bad_nums, part_block_nums;
+	u_char *partition_name = NULL;
+	char *ack = tsp_console_buffer;
+	nand_info_t *nand = &nand_info[nand_curr_device];
+	partition_entry_t *entry = NULL;
+	int flash_type = 0;
+	unsigned int valid_space_size = 0;
+	
+	if(argc < 2)
+	{
+		return cmd_usage(cmdtp);
+	}
+
+	partition_name = argv[1];
+
+	entry = find_partition_para(partition_name);
+	if(entry == NULL)
+	{
+		BOOT_PRINTF(UBOOT_ERR, "[%s]: can't find the partition...\n", partition_name);
+        sprintf(ack,"FAIL INVALID PARTITION");
+        downloader_serial_write(ack, strlen(ack)+1);
+		return -1;
+	}
+
+	flash_type = read_boot_flashtype();
+	if(flash_type == IF_TYPE_NOR)
+	{
+		valid_space_size = entry->part_size;
+	}
+	else
+	{
+		bad_nums = 0;
+		part_block_nums = entry->part_size / nand->erasesize;
+		for(j = 0; j < part_block_nums; j++)
+		{
+			if(nand_block_isbad (nand, entry->part_offset + (loff_t)j * nand->erasesize))
+			{
+				printf("bad block addr = 0x%x\n", (entry->part_offset + j * nand->erasesize));
+				bad_nums++;
+			}
+		}
+		valid_space_size = entry->part_size - bad_nums * nand->erasesize;
+	}
+
+	sprintf(ack, "%s,%08x", entry->part_name, valid_space_size);
+	printf("part_valid_space_query:%s\n", ack);	
+	downloader_serial_write(ack, strlen(ack) + 1);
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	part_valid_space_query, CONFIG_SYS_MAXARGS, 0, do_part_valid_space_query, 
+	"get partition valid physics space size", ""
+);
+
+
+
diff --git a/boot/common/src/uboot/downloader/cmd_compat_read.c b/boot/common/src/uboot/downloader/cmd_compat_read.c
new file mode 100644
index 0000000..04c59cc
--- /dev/null
+++ b/boot/common/src/uboot/downloader/cmd_compat_read.c
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * Copyright (C) 2016, ZIXC Corporation.
+ *
+ * File Name:cmd_compat_read.c
+ * File Mark:
+ * Description:
+ * Others:
+ * Version:       1.0
+ * Author:        zangxiaofeng
+ * Date:          2013-3-13
+ * History 1:
+ *     Date:
+ *     Version:
+ *     Author:
+ *     Modification:
+ * History 2:
+  ********************************************************************************/
+
+
+/****************************************************************************
+* 	                                     Include files
+****************************************************************************/
+#include <common.h>
+#include <command.h>
+#include <net.h>
+#include <jffs2/load_kernel.h>
+#include "downloader_config.h"
+#include "downloader_nand.h"
+#include "downloader_serial.h"
+#include <boot_mode.h>
+
+#include "errno.h"
+/****************************************************************************
+*							Global Function Prototypes
+****************************************************************************/
+
+
+/*******************************************************************************
+ * Function:do_compat_read
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+ int do_compat_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+    partition_entry_t *part = NULL;
+    char *par = NULL;
+    char ack[64]={0};
+	unsigned int offset = 0;
+	unsigned int size = 0;
+	unsigned int ret = 0;
+	
+	if(argc<4)
+    {
+        return cmd_usage(cmdtp);
+    }
+
+	
+	par = argv[1];
+    offset = (unsigned int)simple_strtoul (argv[2], NULL, 16);
+	size = (unsigned int)simple_strtoul (argv[3], NULL, 16);
+	part = downloader_get_part(par);
+	if(part == NULL)
+	{
+		sprintf(ack,"FAIL INVALID PARTITION TYPE");
+        downloader_serial_write(ack, strlen(ack)+1);
+	    return -1;
+	}
+
+	if((read_boot_flashtype() == IF_TYPE_NOR) 
+		&& (strcmp((const char *)part->part_type,"nand") == 0))
+
+	{
+        ret = do_nor_read(part, par, offset,size);
+		return ret;
+	}
+	
+
+	if(strcmp((const char *)part->part_type,"nand") == 0)
+	{
+	    ret = do_nand_read(part, par, offset, size);
+		return ret;
+	}
+	else if (strcmp((const char *)part->part_type,"fs") == 0)
+	{
+	    ret = do_yaffs_read(part, par, offset, size);
+		return ret;
+	}
+	else if (strcmp((const char *)part->part_type,"ddr") == 0)
+	{
+	    ret = do_ram_read(offset, size);
+		return ret;
+	}
+	else if (strcmp((const char *)part->part_type,"raw") == 0)
+	{
+	    ret = do_raw_read(offset, size);
+		return ret;
+	}
+	else
+	{
+	    sprintf(ack,"FAIL INVALID PARTITION TYPE");
+        downloader_serial_write(ack, strlen(ack)+1);
+	    return -1;
+	}
+}
+U_BOOT_CMD(
+	compat_read, CONFIG_SYS_MAXARGS, 0, do_compat_read,
+	"upload: compat_read [partition][offset][size]",
+	""
+);
+
+
+
+
+
+
diff --git a/boot/common/src/uboot/downloader/cmd_compat_write.c b/boot/common/src/uboot/downloader/cmd_compat_write.c
new file mode 100644
index 0000000..8ac27dd
--- /dev/null
+++ b/boot/common/src/uboot/downloader/cmd_compat_write.c
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * Copyright (C) 2016, ZIXC Corporation.
+ *
+ * File Name:cmd_compat_write.c
+ * File Mark:
+ * Description:
+ * Others:
+ * Version:       1.0
+ * Author:        zangxiaofeng
+ * Date:          2013-3-13
+ * History 1:
+ *     Date:
+ *     Version:
+ *     Author:
+ *     Modification:
+ * History 2:
+  ********************************************************************************/
+
+
+/****************************************************************************
+* 	                                     Include files
+****************************************************************************/
+#include <common.h>
+#include <command.h>
+#include <net.h>
+#include <jffs2/load_kernel.h>
+#include "downloader_config.h"
+#include "downloader_nand.h"
+#include "downloader_serial.h"
+#include "errno.h"
+#include <boot_mode.h>
+/****************************************************************************
+*							Global Function Prototypes
+****************************************************************************/
+
+/*******************************************************************************
+ * Function:do_compat_write
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+ int do_compat_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+    partition_entry_t *part = NULL;
+    char *par = NULL;
+    char ack[64]={0};
+	unsigned int offset = 0;
+	unsigned int size = 0;
+	unsigned int ret = 0;
+	
+	if(argc<4)
+    {
+        return cmd_usage(cmdtp);
+    }
+
+	par = argv[1];
+    offset = (unsigned int)simple_strtoul (argv[2], NULL, 16);
+	size = (unsigned int)simple_strtoul (argv[3], NULL, 16);
+	part = downloader_get_part_dl(par);
+	if(part == NULL)
+	{
+		sprintf(ack,"FAIL INVALID PARTITION TYPE");
+        downloader_serial_write(ack, strlen(ack)+1);
+	    return -1;
+	}
+
+	if((read_boot_flashtype() == IF_TYPE_NOR) 
+		&& (strcmp((const char *)part->part_type,"nand") == 0))
+	{
+        ret = do_nor_write(part, par, offset,size);
+		return ret;
+	}
+    
+	if(strcmp((const char *)part->part_type,"nand") == 0)
+	{
+	    ret = do_nand_write(part, par, offset, size);
+		return ret;
+	}
+	else if (strcmp((const char *)part->part_type,"fs") == 0)
+	{
+	    ret = do_yaffs_write(part, par, offset, size);
+		return ret;
+	}
+	else if (strcmp((const char *)part->part_type,"ddr") == 0)
+	{
+	    ret = do_ram_write(offset, size);
+		return ret;
+	}
+	else if (strcmp((const char *)part->part_type,"raw") == 0)
+	{
+	    ret = do_raw_write(offset, size);
+		return ret;
+	}
+	else
+	{
+	    sprintf(ack,"FAIL INVALID PARTITION TYPE");
+        downloader_serial_write(ack, strlen(ack)+1);
+	    return -1;
+	}
+}
+U_BOOT_CMD(
+	compat_write, CONFIG_SYS_MAXARGS, 0, do_compat_write,
+	"download: compat_write [partition][offset][size]",
+	""
+);
+
+
+
+
+
+
+
+
+
+
+
diff --git a/boot/common/src/uboot/downloader/cmd_cp_reset.c b/boot/common/src/uboot/downloader/cmd_cp_reset.c
new file mode 100644
index 0000000..fc75ad8
--- /dev/null
+++ b/boot/common/src/uboot/downloader/cmd_cp_reset.c
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (C) 2016, ZIXC Corporation.
+ *
+ * File Name:cmd_cp_reset.c
+ * File Mark:
+ * Description:
+ * Others:
+ * Version:       1.0
+ * Author:        zangxiaofeng
+ * Date:          2013-4-22
+ * History 1:
+ *     Date:
+ *     Version:
+ *     Author:
+ *     Modification:
+ * History 2:
+  ********************************************************************************/
+
+
+/****************************************************************************
+* 	                                     Include files
+****************************************************************************/
+#include <common.h>
+#include <command.h>
+#include <net.h>
+#include <jffs2/load_kernel.h>
+#include "downloader_nand.h"
+#include "downloader_config.h"
+#include "errno.h"
+#include <asm/io.h>
+
+/****************************************************************************
+*							Global Function Prototypes
+****************************************************************************/
+
+extern int downloader_serial_write(const char * buffer,unsigned int len);
+extern char *tsp_console_buffer;
+
+/*******************************************************************************
+ * Function:do_reboot
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int do_reboot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+    char *ack = tsp_console_buffer;
+    uint32_t reg_start = 0;
+		
+    if(argc < 1)
+    {
+        return cmd_usage(cmdtp);
+    }
+    
+    sprintf(ack,"OKAY REBOOT");
+    downloader_serial_write(ack, strlen(ack)+1);
+	
+    run_command("reset",0);
+    return 0;
+}
+
+U_BOOT_CMD(
+	reboot, CONFIG_SYS_MAXARGS, 0, do_reboot,
+	"reboot: reboot",
+	""
+);
+
+        
diff --git a/boot/common/src/uboot/downloader/cmd_dl_mmc.c b/boot/common/src/uboot/downloader/cmd_dl_mmc.c
new file mode 100644
index 0000000..1950ef2
--- /dev/null
+++ b/boot/common/src/uboot/downloader/cmd_dl_mmc.c
@@ -0,0 +1,369 @@
+/*******************************************************************************
+ * Copyright (C) 2016, ZIXC Corporation.
+ *
+ * File Name:cmd_dl_mmc.c
+ * File Mark:
+ * Description: download or upload bin from eMMC,compat with SD
+ * Others:
+ * Version:       1.0
+ * Author:        zangxiaofeng
+ * Date:          2014-1-13
+ * History 1:
+ *     Date:
+ *     Version:
+ *     Author:
+ *     Modification:
+ * History 2:
+  ********************************************************************************/
+
+
+
+/****************************************************************************
+* 	                                     Include files
+****************************************************************************/
+#include <common.h>
+#include <command.h>
+#include <net.h>
+#include <jffs2/load_kernel.h>
+#include "downloader_config.h"
+#include "downloader_nand.h"
+#include "downloader_serial.h"
+#include "errno.h"
+
+#include <mmc.h>
+
+extern partition_table_t * g_partition_table_dl;
+extern int downloader_readline (char * buffer);
+extern int downloader_mmc_erase(partition_entry_t * part, uint  partEraseSize);
+extern char *tsp_console_buffer;
+
+/*******************************************************************************
+ * Function:do_mmc_write
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int do_mmc_write(partition_entry_t *part, char *par , unsigned int offset,unsigned int size )
+{
+    char *ack = tsp_console_buffer;
+    unsigned int offset_par = offset;
+    unsigned int leftWriteLength = 0;
+    unsigned int curWriteLength = 0;
+#ifdef CONFIG_LOAD_CRC
+
+    unsigned long crc = 0;
+    unsigned long crc1 = 0;
+#endif
+    int ret = 0;
+    int zload_len = 8192;
+
+    nand_info_t *nand = NULL;
+
+    if(part==NULL)
+    {
+        sprintf(ack,"FAIL INVALID PARTITION");
+        downloader_serial_write(ack, strlen(ack)+1);
+        return EINVAL;	/* Invalid argument */
+    }
+    
+    if((size==0)||(size>part->part_size))
+    {
+        sprintf(ack,"FAIL INVALID LENGTH");
+        downloader_serial_write(ack, strlen(ack)+1);
+        return EINVAL;	/* Invalid argument */
+    }
+    leftWriteLength = size;
+	ret = downloader_mmc_erase( part, part->part_size);
+    while(leftWriteLength>0)
+    {
+        curWriteLength = MIN(leftWriteLength,DOWNLOADER_BUFFER_SIZE);
+#ifdef CONFIG_LOAD_CRC
+        sprintf(ack,"DATACRC %08x",curWriteLength);
+#else
+        sprintf(ack,"DATA %08x",curWriteLength);
+#endif
+        downloader_serial_write(ack, strlen(ack)+1); 
+#ifdef CONFIG_LOAD_CRC
+        downloader_serial_read_actuallen((char *)DOWNLOADER_BUFFER_BASE, curWriteLength+4);
+        crc = crc32(0,(unsigned char*)DOWNLOADER_BUFFER_BASE,curWriteLength);
+        memcpy((unsigned char *)(&crc1),(unsigned char*)(DOWNLOADER_BUFFER_BASE+curWriteLength),4);
+        //printf("CRC_calc= %x,CRC_rec=%x \n",crc,crc1);
+        if(crc != crc1)
+        {
+            sprintf(ack,"FAIL CRC ERROR");
+            downloader_serial_write(ack, strlen(ack)+1);
+            return ENOSYS;  /* Function not implemented */
+        }
+#else
+        downloader_serial_read_actuallen((char *)DOWNLOADER_BUFFER_BASE, curWriteLength);
+#endif
+        if(memcmp(par,"zloader",7) == 0)    /* ÏÂÔØzloader·ÖÇø£¬Í¬Ê±ÏÂÔØ·ÖÇø±í */
+        {
+            memcpy((char *)(DOWNLOADER_BUFFER_BASE+4096),g_partition_table_dl,4096);
+            ret = mmc_write( nand,(loff_t)(part->part_offset + offset_par) , &zload_len,  (unsigned char *)DOWNLOADER_BUFFER_BASE, 0);
+        }
+		else
+		{
+		    ret = mmc_write( nand,(loff_t)(part->part_offset + offset_par) , &curWriteLength,  (unsigned char *)DOWNLOADER_BUFFER_BASE, 0); 
+		}
+
+		if(ret)
+        {
+            sprintf(ack,"FAIL MMC WRITE %d,%d,ret = %d",offset_par,curWriteLength,ret);
+            downloader_serial_write(ack, strlen(ack)+1);
+            return ENOSYS;  /* Function not implemented */
+        }
+	    leftWriteLength -= curWriteLength;
+	    offset_par += curWriteLength;
+    }
+    sprintf(ack,"OKAY");
+    downloader_serial_write(ack, strlen(ack)+1);
+    return 0;
+}
+
+/*******************************************************************************
+ * Function:do_mmc_read
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int do_mmc_read(partition_entry_t *part, char *par , unsigned int offset,unsigned int size )
+{
+    char *rx_buffer = tsp_console_buffer;
+    char *ack = tsp_console_buffer;
+    unsigned int offset_par = offset;
+    unsigned int leftReadLength = 0;
+    unsigned int curReadLength = 0;
+#ifdef CONFIG_LOAD_CRC
+    unsigned long crc = 0;
+#endif
+    int ret = 0;
+	nand_info_t *nand = NULL;
+
+    if(part == NULL)
+    {
+        sprintf(ack,"FAIL INVALID PARTITION");
+        downloader_serial_write(ack, strlen(ack)+1);
+        return EINVAL;	/* Invalid argument */
+    }
+    if((size == 0)||(size>part->part_size))
+    {
+        sprintf(ack,"FAIL INVALID LENGTH");
+        downloader_serial_write(ack, strlen(ack)+1);
+        return EINVAL;	/* Invalid argument */
+    }
+    leftReadLength = size;
+#ifdef CONFIG_LOAD_CRC
+    sprintf(ack,"DATACRC %08x",MIN(size,DOWNLOADER_BUFFER_SIZE));
+#else
+    sprintf(ack,"DATA %08x",MIN(size,DOWNLOADER_BUFFER_SIZE));
+#endif
+    downloader_serial_write(ack, strlen(ack)+1); 
+    
+    while(leftReadLength>0)
+    {
+        curReadLength = MIN(leftReadLength,DOWNLOADER_BUFFER_SIZE);
+        downloader_readline(rx_buffer); 
+	    if(memcmp(rx_buffer,"OKAY",4)==0)
+	    {
+            ret = mmc_read( nand,(loff_t)(part->part_offset+offset_par), &curReadLength,  (unsigned char *)DOWNLOADER_BUFFER_BASE);
+            if(ret)
+            {
+                sprintf(ack,"FAIL MMC READ %d,%d, ret = %d",offset_par,curReadLength,ret);
+                downloader_serial_write(ack, strlen(ack)+1);
+                return ENOSYS;  /* Function not implemented */ 
+            }
+            //printf("start to upload LEN=%d \n",curReadLength);
+#ifdef CONFIG_LOAD_CRC
+            crc = crc32(0,(unsigned char*)DOWNLOADER_BUFFER_BASE,curReadLength);
+            memcpy((unsigned char*)(DOWNLOADER_BUFFER_BASE+curReadLength),(unsigned char *)(&crc),4);
+            downloader_serial_write_actuallen((const char *)DOWNLOADER_BUFFER_BASE, curReadLength+4);
+#else
+            downloader_serial_write_actuallen((const char *)DOWNLOADER_BUFFER_BASE, curReadLength); 
+#endif           
+            //downloader_serial_write_actuallen((const char *)DOWNLOADER_BUFFER_BASE, curReadLength); 
+       
+	    }
+	    else
+	    {
+            sprintf(ack,"FAIL COMMAND ERROR");
+            downloader_serial_write(ack, strlen(ack)+1);
+	        return EBADRQC;		/* Invalid request code */
+	    }
+	    leftReadLength -= curReadLength;
+	    offset_par += curReadLength;
+    }
+
+    downloader_readline(rx_buffer); 
+    if(memcmp(rx_buffer,"OKAY",4)==0)
+    {
+        return 0;
+    }
+    else
+    {
+       sprintf(ack,"FAIL COMMAND ERROR");
+       downloader_serial_write(ack, strlen(ack)+1);
+       return -1;
+    }
+}
+
+
+/*******************************************************************************
+ * Function:downloader_mmc_erase
+ * Description:erase mmc partition
+ * Parameters:
+ *	 Input:partEraseSize: must be multiple of 512KBytes
+ *               part:part information,offset and size must be multiple of 512KBytes
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+
+int downloader_mmc_erase(partition_entry_t * part, uint  partEraseSize)
+{
+	unsigned int blksize = 512;
+	int ret = 0;
+
+	if(part == NULL )
+	{
+		return -1;
+	}
+	ret = mmc_erase( (u64)part->part_offset, (lbaint_t)partEraseSize/blksize);
+
+	return ret;
+}
+/*******************************************************************************
+ * Function:do_mmc_eraseall
+ * Description:erase all mmc partitions
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+
+int downloader_mmc_eraseall(void)
+{
+
+	int  ret = 0;
+	partition_entry_t *entry = &g_partition_table->table[0];
+	uint32_t entry_nums = g_partition_table->entrys;
+		
+	while( entry_nums-- )
+	{
+	    if ( strcmp((const char *)entry->part_name, "ddr") == 0 \
+				||strcmp((const char *)entry->part_name, "raw") == 0)
+	    {
+	        entry++;
+	        continue;
+	    }
+		ret = downloader_mmc_erase(entry,entry->part_size);
+		entry++;
+	}
+	return ret;
+
+}
+/*******************************************************************************
+ * Function:do_mmc_eraseauto
+ * Description:erase mmc except nvr
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int downloader_mmc_eraseauto(void)
+{
+	int  ret = 0;
+	partition_entry_t *entry = &g_partition_table->table[0];
+	uint32_t entry_nums = g_partition_table->entrys;
+				
+	while( entry_nums-- )
+	{
+		if (strcmp((const char *)entry->part_name, "nvro") == 0||\
+			strcmp((const char *)entry->part_name, "ddr") == 0 \
+				||strcmp((const char *)entry->part_name, "raw") == 0)
+		{
+			entry++;
+			continue;
+		}
+		ret = downloader_mmc_erase(entry,entry->part_size);
+		entry++;
+	}
+	return ret;
+}
+
+
+/*
+ ******************************************************************************
+ * Function:set_mmc_dlflag 
+ * Description: open or close USB DL PORT, based on mmc
+ *                   dl on :open DL port ; dl off :close DL port
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ *******************************************************************************
+ */
+int set_mmc_dlflag( char * sign)
+{   
+	int ret = 0;
+	char value = 0;
+	int bootflag = 0;
+	int size = 8192;
+
+	u_char *buffer = kzalloc(0x3000,GFP_KERNEL);    
+	if( buffer == NULL )
+	    return -1;
+
+	if (strcmp((const char *)sign,"on") == 0)
+	{
+	    bootflag = 0x00;
+        memset(&value, bootflag, 1);
+	}
+	else if (strcmp((const char *)sign,"off") == 0)
+	{
+	    bootflag = 0x5a;
+        memset(&value, bootflag, 1);
+	}
+	memcpy(buffer+2, &value, 1);
+	ret = mmc_write( 0, 0, &size,buffer, 0);	
+		
+	sprintf(tsp_console_buffer,"DL OKAY");
+	downloader_serial_write(tsp_console_buffer, strlen(tsp_console_buffer)+1);
+			
+	kfree(buffer);
+	return 0;
+
+}
+
+
+
diff --git a/boot/common/src/uboot/downloader/cmd_dl_nand.c b/boot/common/src/uboot/downloader/cmd_dl_nand.c
new file mode 100644
index 0000000..d4b0e04
--- /dev/null
+++ b/boot/common/src/uboot/downloader/cmd_dl_nand.c
@@ -0,0 +1,431 @@
+/*******************************************************************************
+ * Copyright (C) 2016, ZIXC Corporation.
+ *
+ * File Name:cmd_load_nand.c
+ * File Mark:
+ * Description:
+ * Others:
+ * Version:       1.0
+ * Author:        zangxiaofeng
+ * Date:          2013-3-13
+ * History 1:
+ *     Date:
+ *     Version:
+ *     Author:
+ *     Modification:
+ * History 2:
+  ********************************************************************************/
+
+
+
+/****************************************************************************
+* 	                                     Include files
+****************************************************************************/
+#include <common.h>
+#include <command.h>
+#include <net.h>
+#include <jffs2/load_kernel.h>
+#include "downloader_config.h"
+#include "downloader_nand.h"
+#include "downloader_serial.h"
+#include "errno.h"
+
+extern partition_table_t * g_partition_table_dl;
+extern int downloader_readline (char * buffer);
+extern char *tsp_console_buffer;
+extern int crc_switch_flag;
+extern unsigned int null_slice_flag;
+
+
+/*******************************************************************************
+ * Function:do_nand_write
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int do_nand_write(partition_entry_t *part, char *par , 
+				  unsigned int offset, unsigned int size )
+{
+    char *ack = tsp_console_buffer;
+    unsigned int offset_par = offset;
+    unsigned int leftWriteLength = 0;
+    unsigned int curWriteLength = 0;
+	unsigned int read_buf_offset = 0;
+    unsigned long crc = 0;
+    int ret = 0;
+
+    //part = downloader_get_part(par);
+    if(part==NULL)
+    {
+        sprintf(ack,"FAIL INVALID PARTITION");
+        downloader_serial_write(ack, strlen(ack)+1);
+        return EINVAL;	/* Invalid argument */
+    }
+    
+    if((size==0)||(size>part->part_size))
+    {
+        sprintf(ack,"FAIL INVALID LENGTH");
+        downloader_serial_write(ack, strlen(ack)+1);
+        return EINVAL;	/* Invalid argument */
+    }
+	
+    leftWriteLength = size;
+    ret = downloader_nand_erase(part,part->part_size);
+    if(ret)
+    {
+        sprintf(ack,"FAIL ERASE ERROR");
+        downloader_serial_write(ack, strlen(ack)+1);
+        return ENOSYS;  /* Function not implemented */
+    }
+
+    while(leftWriteLength>0)
+    {
+        curWriteLength = MIN(leftWriteLength,DOWNLOADER_BUFFER_SIZE);
+
+        sprintf(ack,"DATA %08x",curWriteLength);
+        downloader_serial_write(ack, strlen(ack)+1); 
+
+        downloader_serial_read_actuallen((char *)DOWNLOADER_BUFFER_BASE, curWriteLength);
+
+        if(memcmp(par,"zloader",7) == 0)    /* ÏÂÔØzloader·ÖÇø£¬Í¬Ê±ÏÂÔØ·ÖÇø±í */
+        {
+            memcpy((char *)(DOWNLOADER_BUFFER_BASE+8192),g_partition_table_dl,4096);
+            ret = downloader_nand_write(part, offset_par, 0x3000,  
+										(unsigned char *)DOWNLOADER_BUFFER_BASE);
+        }
+		else
+		{
+		    ret = downloader_nand_write(part, offset_par, curWriteLength,  
+										(unsigned char *)DOWNLOADER_BUFFER_BASE); 
+		}
+
+		if(ret)
+        {
+            sprintf(ack,"FAIL NAND WRITE %d,%d,ret = %d",offset_par,curWriteLength,ret);
+            downloader_serial_write(ack, strlen(ack)+1);
+            return ENOSYS;  /* Function not implemented */
+        }
+	    leftWriteLength -= curWriteLength;
+	    offset_par += curWriteLength;
+    }
+	
+	if(crc_switch_flag == 0)
+	{
+		sprintf(ack,"OKAY");
+		downloader_serial_write(ack, strlen(ack)+1);
+	}
+	else 
+	{
+		leftWriteLength = size;
+		offset_par = offset;
+		
+		while(leftWriteLength>0)
+	    {
+	        curWriteLength = MIN(leftWriteLength,DOWNLOADER_BUFFER_SIZE);
+
+            ret = downloader_nand_read(part, offset_par, curWriteLength,  
+									   (unsigned char *)(DOWNLOADER_BUFFER_BASE + read_buf_offset));
+            if(ret)
+            {
+                sprintf(ack,"FAIL NAND READ %d,%d, ret = %d",offset_par,curWriteLength,ret);
+                downloader_serial_write(ack, strlen(ack)+1);
+                return ENOSYS;  /* Function not implemented */ 
+            }
+
+		    leftWriteLength -= curWriteLength;
+		    offset_par += curWriteLength;
+			read_buf_offset += curWriteLength; 
+	    }
+
+		crc = crc32(0,(unsigned char*)DOWNLOADER_BUFFER_BASE,size);
+		downloader_serial_write_actuallen((const char *)(&crc), 4); 
+	}
+
+    return 0;
+}
+
+/*******************************************************************************
+ * Function:do_nand_read
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int do_nand_read(partition_entry_t *part, char *par , 
+				 unsigned int offset, unsigned int size )
+{
+    char *rx_buffer = tsp_console_buffer;
+    char *ack = tsp_console_buffer;
+    unsigned int offset_par=offset;
+    unsigned int leftReadLength = 0;
+    unsigned int curReadLength = 0;
+    int ret = 0;
+
+	
+    //part = downloader_get_part(par);
+    if(part == NULL)
+    {
+        sprintf(ack,"FAIL INVALID PARTITION");
+        downloader_serial_write(ack, strlen(ack)+1);
+        return EINVAL;	/* Invalid argument */
+    }
+    if((size == 0)||(size>part->part_size))
+    {
+        sprintf(ack,"FAIL INVALID LENGTH");
+        downloader_serial_write(ack, strlen(ack)+1);
+        return EINVAL;	/* Invalid argument */
+    }
+    leftReadLength = size;
+
+    sprintf(ack,"DATA %08x",MIN(size,DOWNLOADER_BUFFER_SIZE));
+    downloader_serial_write(ack, strlen(ack)+1); 
+ 
+    while(leftReadLength>0)
+    {
+        curReadLength = MIN(leftReadLength,DOWNLOADER_BUFFER_SIZE);
+        downloader_readline(rx_buffer); 
+	    if(memcmp(rx_buffer,"OKAY",4)==0)
+	    {
+            ret = downloader_nand_read(part, offset_par, 
+									   curReadLength,  
+									   (unsigned char *)DOWNLOADER_BUFFER_BASE);
+            if(ret)
+            {
+                sprintf(ack,"FAIL NAND READ %d,%d, ret = %d",offset_par,curReadLength,ret);
+                downloader_serial_write(ack, strlen(ack)+1);
+                return ENOSYS;  /* Function not implemented */ 
+            }
+
+            downloader_serial_write_actuallen((const char *)DOWNLOADER_BUFFER_BASE, 
+											   curReadLength); 
+	    }
+	    else
+	    {
+            sprintf(ack,"FAIL COMMAND ERROR");
+            downloader_serial_write(ack, strlen(ack)+1);
+	        return EBADRQC;		/* Invalid request code */
+	    }
+	    leftReadLength -= curReadLength;
+	    offset_par += curReadLength;
+    }
+
+    downloader_readline(rx_buffer); 
+    if(memcmp(rx_buffer,"OKAY",4)==0)
+    {
+        return 0;
+    }
+    else
+    {
+       sprintf(ack,"FAIL COMMAND ERROR");
+       downloader_serial_write(ack, strlen(ack)+1);
+       return -1;
+    }
+}
+
+
+/*******************************************************************************
+ * Function:do_nor_write
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int do_nor_write(partition_entry_t *part, char *par , 
+				 unsigned int offset, unsigned int size )
+{
+    char *ack = tsp_console_buffer;
+    unsigned int offset_par = offset;
+    unsigned int leftWriteLength = 0;
+    unsigned int curWriteLength = 0;
+	unsigned int read_buf_offset = 0;
+    unsigned long crc = 0;
+    int ret = 0;
+
+    //part = downloader_get_part(par);
+    if(part==NULL)
+    {
+        sprintf(ack,"FAIL INVALID PARTITION");
+        downloader_serial_write(ack, strlen(ack)+1);
+        return EINVAL;	/* Invalid argument */
+    }
+    
+    if((size==0)||(size>part->part_size))
+    {
+        sprintf(ack,"FAIL INVALID LENGTH");
+        downloader_serial_write(ack, strlen(ack)+1);
+        return EINVAL;	/* Invalid argument */
+    }
+    leftWriteLength = size;
+
+	if(null_slice_flag == 1)
+	{
+		ret = downloader_nor_erase(part,part->part_size);
+		if(ret)
+		{
+			sprintf(ack,"FAIL ERASE ERROR");
+			downloader_serial_write(ack, strlen(ack)+1);
+			return ENOSYS;	/* Function not implemented */
+		}
+	}
+    
+    while(leftWriteLength>0)
+    {
+        curWriteLength = MIN(leftWriteLength,DOWNLOADER_BUFFER_SIZE);
+
+        sprintf(ack,"DATA %08x",curWriteLength);
+        downloader_serial_write(ack, strlen(ack)+1); 
+        downloader_serial_read_actuallen((char *)DOWNLOADER_BUFFER_BASE, curWriteLength);
+
+        if(memcmp(par,"zloader",7) == 0)    /* ÏÂÔØzloader·ÖÇø£¬Í¬Ê±ÏÂÔØ·ÖÇø±í */
+        {
+            memcpy((char *)(DOWNLOADER_BUFFER_BASE+8192),g_partition_table_dl,4096);
+            ret = downloader_nor_write( part, offset_par, 0x3000,  (unsigned char *)DOWNLOADER_BUFFER_BASE);
+        }
+		else
+		{
+		    ret = downloader_nor_write( part, offset_par, curWriteLength,  (unsigned char *)DOWNLOADER_BUFFER_BASE); 
+		}
+
+		if(ret)
+        {
+            sprintf(ack,"FAIL NAND WRITE %d,%d,ret = %d",offset_par,curWriteLength,ret);
+            downloader_serial_write(ack, strlen(ack)+1);
+            return ENOSYS;  /* Function not implemented */
+        }
+	    leftWriteLength -= curWriteLength;
+	    offset_par += curWriteLength;
+    }
+
+
+	if(crc_switch_flag == 0)	
+	{		
+		sprintf(ack,"OKAY");		
+		downloader_serial_write(ack, strlen(ack)+1);	
+	}	
+	else 	
+	{		
+		leftWriteLength = size;		
+		offset_par = offset;				
+		while(leftWriteLength>0)	    
+		{	        
+			curWriteLength = MIN(leftWriteLength,DOWNLOADER_BUFFER_SIZE);            
+			ret = downloader_nor_read(part, 
+									  offset_par,
+									  curWriteLength, 
+									  (unsigned char *)(DOWNLOADER_BUFFER_BASE + read_buf_offset));
+			if(ret)            
+			{                
+				sprintf(ack,"FAIL NAND READ %d,%d, ret = %d",offset_par,curWriteLength,ret);
+				downloader_serial_write(ack, strlen(ack)+1);                
+				return ENOSYS;  /* Function not implemented */             
+			}		    
+			leftWriteLength -= curWriteLength;		    
+			offset_par += curWriteLength;			
+			read_buf_offset += curWriteLength; 	    
+		}		
+		crc = crc32(0,(unsigned char*)DOWNLOADER_BUFFER_BASE,size);		
+		downloader_serial_write_actuallen((const char *)(&crc), 4); 	
+	}
+
+    return 0;
+}
+
+/*******************************************************************************
+ * Function:do_nor_read
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int do_nor_read(partition_entry_t *part, char *par , 
+				unsigned int offset, unsigned int size )
+{
+    char *rx_buffer = tsp_console_buffer;
+    char *ack = tsp_console_buffer;
+    unsigned int offset_par=offset;
+    unsigned int leftReadLength = 0;
+    unsigned int curReadLength = 0;
+    int ret = 0;
+
+	
+    //part = downloader_get_part(par);
+    if(part == NULL)
+    {
+        sprintf(ack,"FAIL INVALID PARTITION");
+        downloader_serial_write(ack, strlen(ack)+1);
+        return EINVAL;	/* Invalid argument */
+    }
+    if((size == 0)||(size>part->part_size))
+    {
+        sprintf(ack,"FAIL INVALID LENGTH");
+        downloader_serial_write(ack, strlen(ack)+1);
+        return EINVAL;	/* Invalid argument */
+    }
+    leftReadLength = size;
+    sprintf(ack,"DATA %08x",MIN(size,DOWNLOADER_BUFFER_SIZE));
+
+    downloader_serial_write(ack, strlen(ack)+1); 
+    while(leftReadLength>0)
+    {
+        curReadLength = MIN(leftReadLength,DOWNLOADER_BUFFER_SIZE);
+        downloader_readline(rx_buffer); 
+	    if(memcmp(rx_buffer,"OKAY",4)==0)
+	    {
+            ret = downloader_nor_read( part, offset_par, curReadLength,  (unsigned char *)DOWNLOADER_BUFFER_BASE);
+            if(ret)
+            {
+                sprintf(ack,"FAIL NAND READ %d,%d, ret = %d",offset_par,curReadLength,ret);
+                downloader_serial_write(ack, strlen(ack)+1);
+                return ENOSYS;  /* Function not implemented */ 
+            }
+            downloader_serial_write_actuallen((const char *)DOWNLOADER_BUFFER_BASE, curReadLength); 
+	    }
+	    else
+	    {
+            sprintf(ack,"FAIL COMMAND ERROR");
+            downloader_serial_write(ack, strlen(ack)+1);
+	        return EBADRQC;		/* Invalid request code */
+	    }
+	    leftReadLength -= curReadLength;
+	    offset_par += curReadLength;
+    }
+
+    downloader_readline(rx_buffer); 
+    if(memcmp(rx_buffer,"OKAY",4)==0)
+    {
+        return 0;
+    }
+    else
+    {
+       sprintf(ack,"FAIL COMMAND ERROR");
+       downloader_serial_write(ack, strlen(ack)+1);
+       return -1;
+    }
+}
+
+
diff --git a/boot/common/src/uboot/downloader/cmd_dl_ram.c b/boot/common/src/uboot/downloader/cmd_dl_ram.c
new file mode 100644
index 0000000..f1ac2c3
--- /dev/null
+++ b/boot/common/src/uboot/downloader/cmd_dl_ram.c
@@ -0,0 +1,174 @@
+

+/*******************************************************************************
+ * Copyright (C) 2016, ZIXC Corporation.

+ *
+ * File Name:cmd_compat_write.c

+ * File Mark:
+ * Description:
+ * Others:
+ * Version:       1.0
+ * Author:        zangxiaofeng
+ * Date:          2013-3-13
+ * History 1:
+ *     Date:
+ *     Version:
+ *     Author:
+ *     Modification:
+ * History 2:
+  ********************************************************************************/
+
+
+/****************************************************************************
+* 	                                     Include files
+****************************************************************************/
+#include <common.h>
+#include <command.h>
+#include <net.h>
+#include <jffs2/load_kernel.h>
+#include "downloader_config.h"
+#include "downloader_nand.h"

+#include "downloader_serial.h"

+#include "errno.h"

+

+extern int downloader_readline (char * buffer);

+extern char *tsp_console_buffer;

+/*******************************************************************************
+ * Function:do_ram_write

+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int do_ram_write( unsigned int offset, unsigned int size)

+{
+    char *ack = tsp_console_buffer;

+    unsigned int addr = 0;
+    unsigned int leftWriteLength = 0;
+    unsigned int curWriteLength = 0;

+#ifdef CONFIG_LOAD_CRC

+    unsigned long crc = 0;
+    unsigned long crc1 = 0;

+#endif

+

+    addr = offset ;

+   
+    if(size == 0)

+    {
+        sprintf(ack,"FAIL INVALID LENGTH");
+        downloader_serial_write(ack, strlen(ack)+1);
+        return EINVAL;	

+    }

+    leftWriteLength = size;
+	
+    while(leftWriteLength>0)
+    {
+        curWriteLength = MIN(leftWriteLength,DOWNLOADER_BUFFER_SIZE);
+#ifdef CONFIG_LOAD_CRC
+        sprintf(ack,"DATACRC %08x",curWriteLength);

+#else
+        sprintf(ack,"DATA %08x",curWriteLength);

+#endif
+	    downloader_serial_write(ack, strlen(ack)+1); 
+#ifdef CONFIG_LOAD_CRC

+        

+		downloader_serial_read_actuallen((char *)DOWNLOADER_BUFFER_BASE, curWriteLength+4);

+		memcpy(( char *)addr,(char *)DOWNLOADER_BUFFER_BASE,  curWriteLength+4 );

+

+

+        crc = crc32(0,(unsigned char*)addr,curWriteLength);
+        memcpy((unsigned char *)(&crc1),(unsigned char*)(addr+curWriteLength),4);
+        if(crc != crc1)
+        {
+            sprintf(ack,"FAIL CRC ERROR");
+            downloader_serial_write(ack, strlen(ack)+1);
+            return ENOSYS;  /* Function not implemented */
+        }
+#else

+        

+

+	    downloader_serial_read_actuallen((char *)DOWNLOADER_BUFFER_BASE, curWriteLength);

+		memcpy(( char *)addr,(char *)DOWNLOADER_BUFFER_BASE,  curWriteLength );

+

+#endif
+	    leftWriteLength -= curWriteLength;
+	    addr += curWriteLength;

+    }	
+	
+    sprintf(ack,"OKAY");
+    downloader_serial_write(ack, strlen(ack)+1);
+    return 0;
+	
+}

+

+/*******************************************************************************
+ * Function:do_ram_read
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int do_ram_read(unsigned int offset, unsigned int size)

+{
+    char *rx_buffer = tsp_console_buffer;

+    char *ack = tsp_console_buffer;

+    unsigned int addr = 0;
+    unsigned int leftReadLength = 0;
+    unsigned int curReadLength = 0;

+	

+    addr = offset ;

+

+ 
+    if((size == 0)||(size > CONFIG_SYS_SDRAM_SIZE))
+    {
+        sprintf(ack,"FAIL INVALID LENGTH");
+        downloader_serial_write(ack, strlen(ack)+1);
+        return EINVAL;	/* Invalid argument */
+    }
+    leftReadLength = size;
+	
+    sprintf(ack,"DATA %08x",MIN(size,DOWNLOADER_BUFFER_SIZE));

+    downloader_serial_write(ack, strlen(ack)+1); 
+    while(leftReadLength>0)
+    {
+        curReadLength = MIN(leftReadLength,DOWNLOADER_BUFFER_SIZE);        
+        downloader_readline(rx_buffer); 
+	    if(memcmp(rx_buffer,"OKAY",4) == 0)
+	    {

+		   	memcpy((char *)DOWNLOADER_BUFFER_BASE, (const char *)addr, curReadLength );

+			downloader_serial_write_actuallen((const char *)DOWNLOADER_BUFFER_BASE, curReadLength);

+        }
+	    else
+	    {
+            sprintf(ack,"FAIL COMMAND ERROR");
+            downloader_serial_write(ack, strlen(ack)+1);
+	        return EBADRQC;		/* Invalid request code */
+	    }
+	    leftReadLength -= curReadLength;
+	    addr += curReadLength;
+    }
+
+    downloader_readline(rx_buffer); 
+    if(memcmp(rx_buffer,"OKAY",4) == 0)
+    {
+        return 0;
+    }
+    else
+    {
+        sprintf(ack,"FAIL COMMAND ERROR");
+        downloader_serial_write(ack, strlen(ack)+1);
+        return EBADRQC;		/* Invalid request code */
+    }
+	
+}
diff --git a/boot/common/src/uboot/downloader/cmd_dl_raw.c b/boot/common/src/uboot/downloader/cmd_dl_raw.c
new file mode 100644
index 0000000..eb42af5
--- /dev/null
+++ b/boot/common/src/uboot/downloader/cmd_dl_raw.c
@@ -0,0 +1,244 @@
+/*******************************************************************************
+ * Copyright (C) 2016, ZIXC Corporation.
+ *
+ * File Name:cmd_dl_raw.c
+ * File Mark:
+ * Description:
+ * Others:
+ * Version:       1.0
+ * Author:        zangxiaofeng
+ * Date:          2013-6-9
+ * History 1:
+ *     Date:
+ *     Version:
+ *     Author:
+ *     Modification:
+ * History 2:
+  ********************************************************************************/
+
+
+/****************************************************************************
+* 	                                     Include files
+****************************************************************************/
+#include <common.h>
+#include <command.h>
+#include <net.h>
+#include <jffs2/load_kernel.h>
+#include "downloader_config.h"
+#include "downloader_nand.h"
+#include "downloader_serial.h"
+
+#include "errno.h"
+
+extern int downloader_readline (char * buffer);
+extern char *tsp_console_buffer;
+
+/*******************************************************************************
+ * Function:do_raw_write
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int do_raw_write(unsigned int offset, unsigned int size)
+{
+    char *ack = tsp_console_buffer;
+	unsigned int leftWriteLength = 0;
+    unsigned int curWriteLength = 0;
+#ifdef CONFIG_LOAD_CRC
+    unsigned long crc = 0;
+    unsigned long crc1 = 0;
+#endif
+	int ret = 0;
+	nand_info_t *pNandInfo = NULL;
+	//struct erase_info instr;
+
+	pNandInfo = &nand_info[nand_curr_device];
+    assert(pNandInfo!=NULL); 
+	
+    leftWriteLength = size;
+	
+	if((size==0)||(offset+size > pNandInfo->size))
+    {
+        sprintf(ack,"FAIL INVALID LENGTH");
+        downloader_serial_write(ack, strlen(ack)+1);
+        return EINVAL;	/* Invalid argument */
+    }
+	ret = do_raw_erase(offset, size);
+	if(ret)
+    {
+        sprintf(ack,"FAIL ERASE ERROR");
+        downloader_serial_write(ack, strlen(ack)+1);
+        return ENOSYS;  /* Function not implemented */
+    }
+
+	while(leftWriteLength>0)
+    {
+        curWriteLength = MIN(leftWriteLength,DOWNLOADER_BUFFER_SIZE);
+#ifdef CONFIG_LOAD_CRC
+        sprintf(ack,"DATACRC %08x",curWriteLength);
+#else
+        sprintf(ack,"DATA %08x",curWriteLength);
+#endif
+        downloader_serial_write(ack, strlen(ack)+1); 
+#ifdef CONFIG_LOAD_CRC
+        downloader_serial_read_actuallen((char *)DOWNLOADER_BUFFER_BASE, curWriteLength+4);
+        crc = crc32(0,(unsigned char*)DOWNLOADER_BUFFER_BASE,curWriteLength);
+        memcpy((unsigned char *)(&crc1),(unsigned char*)(DOWNLOADER_BUFFER_BASE+curWriteLength),4);
+        //printf("CRC_calc= %x,CRC_rec=%x \n",crc,crc1);
+        if(crc != crc1)
+        {
+            sprintf(ack,"FAIL CRC ERROR");
+            downloader_serial_write(ack, strlen(ack)+1);
+            return ENOSYS;  /* Function not implemented */
+        }
+#else
+        downloader_serial_read_actuallen((char *)DOWNLOADER_BUFFER_BASE, curWriteLength);
+#endif
+        //printf("start to write\n");
+        ret = nand_write_skip_bad( pNandInfo, offset, &curWriteLength, (unsigned char *)DOWNLOADER_BUFFER_BASE,0); 
+        if(ret)
+        {
+            sprintf(ack,"FAIL NAND WRITE %d,%d,ret = %d",offset,curWriteLength,ret);
+            downloader_serial_write(ack, strlen(ack)+1);
+            return ENOSYS;  /* Function not implemented */
+        }
+        //printf("finish writing\n");
+	    leftWriteLength -= curWriteLength;
+	    offset += curWriteLength;
+    }
+	//printf("finish writing, leftlen = %d \n",leftWriteLength);
+    sprintf(ack,"OKAY");
+    downloader_serial_write(ack, strlen(ack)+1);
+    return 0;
+	
+
+	
+}
+
+/*******************************************************************************
+ * Function:do_raw_read
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int do_raw_read(unsigned int offset, unsigned int size)
+{
+    char *rx_buffer = tsp_console_buffer;
+	char *ack = tsp_console_buffer;
+	unsigned int leftReadLength = 0;
+    unsigned int curReadLength = 0;
+	int ret = 0;
+	nand_info_t *pNandInfo = NULL;
+	//struct erase_info instr;
+
+	pNandInfo = &nand_info[nand_curr_device];
+    assert(pNandInfo!=NULL); 
+	
+    leftReadLength = size;
+	if((size==0)||(offset+size > pNandInfo->size))
+    {
+        sprintf(ack,"FAIL INVALID LENGTH");
+        downloader_serial_write(ack, strlen(ack)+1);
+        return EINVAL;	/* Invalid argument */
+    }
+
+    sprintf(ack,"DATA %08x",MIN(size,DOWNLOADER_BUFFER_SIZE));
+    downloader_serial_write(ack, strlen(ack)+1); 
+	
+	while(leftReadLength>0)
+    {
+        curReadLength = MIN(leftReadLength,DOWNLOADER_BUFFER_SIZE);
+        downloader_readline(rx_buffer); 
+	    if(memcmp(rx_buffer,"OKAY",4)==0)
+	    {
+            ret = nand_read_skip_bad( pNandInfo, offset, &curReadLength,  (unsigned char *)DOWNLOADER_BUFFER_BASE);
+            if(ret)
+            {
+                sprintf(ack,"FAIL NAND READ %d,%d, ret = %d",offset,curReadLength,ret);
+                downloader_serial_write(ack, strlen(ack)+1);
+                return ENOSYS;  /* Function not implemented */ 
+            }
+            //printf("start to upload LEN=%d \n",curReadLength);
+
+            downloader_serial_write_actuallen((const char *)DOWNLOADER_BUFFER_BASE, curReadLength);                      
+	    }
+	    else
+	    {
+            sprintf(ack,"FAIL COMMAND ERROR");
+            downloader_serial_write(ack, strlen(ack)+1);
+	        return EBADRQC;		/* Invalid request code */
+	    }
+	    leftReadLength -= curReadLength;
+	    offset += curReadLength;
+    }
+	downloader_readline(rx_buffer); 
+    if(memcmp(rx_buffer,"OKAY",4)==0)
+    {
+        return 0;
+    }
+    else
+    {
+       sprintf(ack,"FAIL COMMAND ERROR");
+       downloader_serial_write(ack, strlen(ack)+1);
+       return -1;
+    }
+}
+
+int do_raw_erase(unsigned int offset, unsigned int partEraseSize)
+{
+    nand_info_t *pNandInfo = NULL;
+	struct erase_info instr;
+	unsigned int size = 0;
+	unsigned int ret = 0;
+    
+    pNandInfo = &nand_info[nand_curr_device];
+    assert(pNandInfo!=NULL);
+	instr.mtd = pNandInfo;
+	instr.addr = offset;
+	assert( (instr.addr & (pNandInfo->erasesize - 1)) == 0);
+	instr.callback = 0;
+
+	while((size < partEraseSize)  &&  (instr.addr < (offset+partEraseSize)))
+		{
+		if(nand_block_isbad (pNandInfo, instr.addr))
+			{
+				instr.addr += pNandInfo->erasesize;
+				continue ;
+			}
+		instr.len = pNandInfo->erasesize;
+		instr.state = 0;
+		ret = pNandInfo->erase(pNandInfo, &instr);
+		if(ret  && instr.state == MTD_ERASE_FAILED)
+			{
+				pNandInfo->block_markbad(pNandInfo,instr.addr);
+			}
+		else if (ret == 0)
+			{
+				size += pNandInfo->erasesize;
+			}
+		else
+			{
+				printf( "downloader nand: erase error\n");
+				return 1;
+			}
+		instr.addr += pNandInfo->erasesize;
+		}
+	return 0;
+	
+}
+
+
diff --git a/boot/common/src/uboot/downloader/cmd_dl_yaffs.c b/boot/common/src/uboot/downloader/cmd_dl_yaffs.c
new file mode 100644
index 0000000..c732457
--- /dev/null
+++ b/boot/common/src/uboot/downloader/cmd_dl_yaffs.c
@@ -0,0 +1,220 @@
+/*******************************************************************************
+ * Copyright (C) 2016, ZIXC Corporation.
+ *
+ * File Name:cmd_compat_read.c
+ * File Mark:
+ * Description:
+ * Others:
+ * Version:       1.0
+ * Author:        zangxiaofeng
+ * Date:          2013-3-13
+ * History 1:
+ *     Date:
+ *     Version:
+ *     Author:
+ *     Modification:
+ * History 2:
+  ********************************************************************************/
+
+
+/****************************************************************************
+* 	                                     Include files
+****************************************************************************/
+#include <common.h>
+#include <command.h>
+#include <net.h>
+#include <jffs2/load_kernel.h>
+#include "downloader_config.h"
+#include "downloader_nand.h"
+#include "downloader_serial.h"
+
+#include "errno.h"
+
+extern int downloader_readline (char * buffer);
+extern char *tsp_console_buffer;
+
+/*******************************************************************************
+ * Function:do_yaffs_write
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int do_yaffs_write(partition_entry_t *part, char *par , unsigned int offset, unsigned int size )
+{
+    char *ack = tsp_console_buffer;
+    unsigned int offset_par = offset;
+    unsigned int leftWriteLength = 0;
+    unsigned int curWriteLength = 0;
+    unsigned int size_fs = 0;
+    unsigned int pagefullsize = 0;
+#ifdef CONFIG_LOAD_CRC
+    unsigned long crc = 0;
+    unsigned long crc1 = 0;
+#endif
+    int ret = 0;
+    nand_info_t *pNandInfo = NULL;
+    
+    if(part == NULL)
+    {
+        sprintf(ack,"FAIL INVALID PARTITION");
+        downloader_serial_write(ack, strlen(ack)+1);
+        return EINVAL;	/* Invalid argument */
+    }
+    pNandInfo = &nand_info[nand_curr_device];
+    assert(pNandInfo!=NULL); 
+    pagefullsize=pNandInfo->writesize+pNandInfo->oobsize;
+    if((size==0)||(size>(part->part_size/pNandInfo->writesize)*pagefullsize))
+    {
+        sprintf(ack,"FAIL INVALID LENGTH");
+        downloader_serial_write(ack, strlen(ack)+1);
+        return EINVAL;	/* Invalid argument */
+    }
+    
+    leftWriteLength = size;
+    ret = downloader_nand_erase(part,part->part_size);
+    if(ret)
+    {
+        sprintf(ack,"FAIL ERASE ERROR");
+        downloader_serial_write(ack, strlen(ack)+1);
+        return ENOSYS;  /* Function not implemented */
+    }
+	
+    while(leftWriteLength>0)
+    {
+        curWriteLength = MIN(leftWriteLength,DOWNLOADER_BUFFER_SIZE);
+#ifdef CONFIG_LOAD_CRC
+        sprintf(ack,"DATACRC %08x",curWriteLength);
+#else
+        sprintf(ack,"DATA %08x",curWriteLength);
+#endif
+	    downloader_serial_write(ack, strlen(ack)+1); 
+#ifdef CONFIG_LOAD_CRC
+        downloader_serial_read_actuallen((char *)DOWNLOADER_BUFFER_BASE, curWriteLength+4);
+        crc = crc32(0,(unsigned char*)DOWNLOADER_BUFFER_BASE,curWriteLength);
+        memcpy((unsigned char *)(&crc1),(unsigned char*)(DOWNLOADER_BUFFER_BASE+curWriteLength),4);
+        if(crc != crc1)
+        {
+            sprintf(ack,"FAIL CRC ERROR");
+            downloader_serial_write(ack, strlen(ack)+1);
+            return ENOSYS;  /* Function not implemented */
+        }
+#else
+        downloader_serial_read_actuallen((char *)DOWNLOADER_BUFFER_BASE, curWriteLength);
+#endif
+        size_fs = (curWriteLength%pagefullsize)?(curWriteLength/pagefullsize+1)*(pagefullsize): curWriteLength;
+        if(curWriteLength<size_fs)
+        {
+            memset((char *)(DOWNLOADER_BUFFER_BASE+curWriteLength),0xff,size_fs-curWriteLength);
+        }
+        ret = downloader_nand_fs_write( part, offset_par, size_fs,  (unsigned char *)DOWNLOADER_BUFFER_BASE); 
+        if(ret)
+        {
+            sprintf(ack,"FAIL YAFFS WRITE %d,%d",offset_par,size_fs);
+            downloader_serial_write(ack, strlen(ack)+1);
+            return ENOSYS;  /* Function not implemented */
+        }
+	    leftWriteLength -= curWriteLength;
+	    offset_par += (curWriteLength/pagefullsize)*(pNandInfo->writesize);
+    }		
+
+    sprintf(ack,"OKAY");
+    downloader_serial_write(ack, strlen(ack)+1);
+    return 0;
+}
+
+
+
+/*******************************************************************************
+ * Function:do_yaffs_read
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int do_yaffs_read(partition_entry_t *part, char *par , unsigned int offset, unsigned int size)
+{
+    char *rx_buffer = tsp_console_buffer;
+    char *ack = tsp_console_buffer;
+    unsigned int offset_par = offset;
+    unsigned int size_fs = 0;
+    unsigned int pagefullsize = 0;
+    nand_info_t *pNandInfo = NULL;
+    unsigned int leftReadLength = 0;
+    unsigned int curReadLength = 0;
+    //unsigned long crc = 0;
+    int ret = 0;
+
+	if(part == NULL)
+    {
+        sprintf(ack,"FAIL INVALID PARTITION");
+        downloader_serial_write(ack, strlen(ack)+1);
+        return EINVAL;	/* Invalid argument */
+    }
+    if((size == 0)||(size > part->part_size))
+    {
+        sprintf(ack,"FAIL INVALID LENGTH");
+        downloader_serial_write(ack, strlen(ack)+1);
+        return EINVAL;	/* Invalid argument */
+    }
+    pNandInfo = &nand_info[nand_curr_device];
+    assert(pNandInfo!=NULL);
+    pagefullsize = pNandInfo->writesize+pNandInfo->oobsize;   
+    leftReadLength = size;
+
+    sprintf(ack,"DATA %08x",MIN(size,DOWNLOADER_BUFFER_SIZE));
+    downloader_serial_write(ack, strlen(ack)+1); 
+
+    while(leftReadLength>0)
+    {
+        curReadLength = MIN(leftReadLength,DOWNLOADER_BUFFER_SIZE);
+        size_fs = (curReadLength%pagefullsize)?(curReadLength/pagefullsize+1)*(pagefullsize): curReadLength;  
+        downloader_readline(rx_buffer); 
+	    if(memcmp(rx_buffer,"OKAY",4)==0)
+	    {
+            ret = downloader_nand_fs_read( part, offset_par, size_fs,  (unsigned char *)DOWNLOADER_BUFFER_BASE); 
+            if(ret)
+            {
+                sprintf(ack,"FAIL YAFFS READ %d,%d, ret = %d",offset_par,size_fs,ret);
+                downloader_serial_write(ack, strlen(ack)+1);
+                return ENOSYS;  /* Function not implemented */
+            }
+            downloader_serial_write_actuallen((const char *)DOWNLOADER_BUFFER_BASE, curReadLength);         
+       
+	    }
+	    else
+	    {
+            sprintf(ack,"FAIL COMMAND ERROR");
+            downloader_serial_write(ack, strlen(ack)+1);
+	        return EBADRQC;		/* Invalid request code */
+	    }
+	    leftReadLength -= curReadLength;
+	    offset_par += (curReadLength/pagefullsize)*(pNandInfo->writesize);
+    }
+	printf("prepare to receive OKAY");	
+    downloader_readline(rx_buffer);
+    if(memcmp(rx_buffer,"OKAY",4)==0)
+    {
+        return 0;
+    }
+    else
+    {
+       sprintf(ack,"FAIL COMMAND ERROR");
+       downloader_serial_write(ack, strlen(ack)+1);
+       return EBADRQC;		/* Invalid request code */
+    }
+	
+}
+
diff --git a/boot/common/src/uboot/downloader/cmd_downloader.c b/boot/common/src/uboot/downloader/cmd_downloader.c
new file mode 100644
index 0000000..9d0cbf4
--- /dev/null
+++ b/boot/common/src/uboot/downloader/cmd_downloader.c
@@ -0,0 +1,229 @@
+/*
+ ******************************************************************************
+ * Copyright (C) 2016, ZIXC Corporation.
+ *
+ * File Name:
+ * File Mark:
+ * Description:
+ * Others:
+ * Version:       1.0
+ * Author:        geanfeng
+ * Date:          2013-3-4
+ * History 1:
+ *     Date:
+ *     Version:
+ *     Author:
+ *     Modification:
+ * History 2:
+ *******************************************************************************
+ */
+
+/*
+ ***************************************************************************
+ * 	                                           Include files
+ ***************************************************************************
+ */
+#include <common.h>
+#include <command.h>
+#include <net.h>
+#include "downloader_serial.h"
+#include "partition_table.h"
+
+
+/****************************************************************************
+* 	                                           Local Macros
+****************************************************************************/
+#define TSP_DOWNLOADER_CBSIZE		256 
+ 
+/****************************************************************************
+*							Local Types
+****************************************************************************/
+
+/****************************************************************************
+*							Global Variables
+****************************************************************************/
+//char        tsp_console_buffer[TSP_DOWNLOADER_CBSIZE + 1];	/* downloader I/O buffer	*/
+ char *tsp_console_buffer = (char*)(CONFIG_NAND_DMA_BUF_ADDR+0x4000);
+
+unsigned int null_slice_flag = 0;
+
+
+/****************************************************************************
+*							Global Function Prototypes
+****************************************************************************/
+extern	void downloader_serial_init(void);
+extern int UART_CmdRead(char *pchBuf, int dwLen);
+
+/****************************************************************************
+*							Function Definitions
+****************************************************************************/
+/*******************************************************************************
+ * Function:downloader_readline_into_buffer
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int downloader_readline_into_buffer (char * buffer)
+{
+	char * p_buf = buffer;
+	unsigned int retSize = 0;
+	unsigned int recvSize = 0;
+	
+	while(1)
+		{
+#if CONFIG_USB_DL
+		retSize = downloader_serial_read(p_buf,512);
+#else
+		retSize = UART_CmdRead(p_buf,512);
+#endif
+		if(retSize<=0)
+			{
+				continue;
+			}
+		recvSize += retSize;
+		if(recvSize >= TSP_DOWNLOADER_CBSIZE)
+		{
+			recvSize = 0;
+			p_buf = buffer;
+		}
+		if(buffer[0] == 0x5a) /*filter syc 0x5a*/
+		{
+			printf("readline filter syc 0x5a\n");
+			recvSize = 0;
+			continue;
+		}
+
+		switch(p_buf[retSize-1])
+			{
+			case '\r':           /*Enter */
+			case '\n':
+			case '\0':
+				while(retSize>0)
+					{
+					if( (p_buf[retSize-1] >='a' && p_buf[retSize-1]<='z')  ||\
+						(p_buf[retSize-1] >='A' && p_buf[retSize-1]<='Z') || \
+						(p_buf[retSize-1] >='0' && p_buf[retSize-1]<='9') )   /*filter invalid character*/
+						{
+							break;
+						}
+					retSize--;
+					}
+				p_buf[retSize]='\0';
+				return 0;
+			default:
+				p_buf += retSize;
+				continue;
+			}
+
+		}
+
+	return 0;
+}
+/*******************************************************************************
+ * Function:downloader_readline
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int downloader_readline (char * buffer)
+{
+	/*
+	 * If console_buffer isn't 0-length the user will be prompted to modify
+	 * it instead of entering it from scratch as desired.
+	 */
+	buffer[0] = '\0';
+
+	return downloader_readline_into_buffer(buffer);
+}
+
+/*******************************************************************************
+ * Function:do_downloader
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int do_downloader(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	int ret = 0;
+	int type = 0;
+	char ack[20] = {0};
+    printf( "[sys_entry]: do downloader\n");
+	
+    ret = read_partition_and_check();
+    if( ret != 0 )
+    {
+        printf( "[sys_entry]: read_partition error...\n");
+    }
+
+	type = read_boot_flashtype();
+	if(type == IF_TYPE_NOR)
+	{
+		ret = get_nor_null_slice_flag(&null_slice_flag);
+	    if(ret)
+	    {
+			printf ("nor flash read null_slice_flag error.\n");
+			return 1; 
+	    }
+	}
+
+	downloader_serial_init();
+	printf ("### downloader : serial init success \n");
+
+	/*sync*/
+	while(1)
+		{
+#if CONFIG_USB_DL
+		downloader_serial_read(tsp_console_buffer,512);
+#else
+		downloader_serial_read(tsp_console_buffer,1);
+#endif
+		if(tsp_console_buffer[0]==0x5a)
+			{
+				tsp_console_buffer[0]=0xa7; /*ack*/
+				downloader_serial_write(tsp_console_buffer,1);
+				break;
+			}
+		}
+	
+	/*run commands*/
+	while(1)
+		{
+			downloader_readline(tsp_console_buffer);
+			ret = run_command (tsp_console_buffer, 0);
+			if(ret == -2)
+			{
+				sprintf(ack,"UNKNOWN COMMAND");
+        		downloader_serial_write(ack, strlen(ack)+1);
+			}
+		}
+	
+	return 0;
+}
+
+U_BOOT_CMD(
+	downloader, 1, 0,	do_downloader,
+	"Perform ZIXC TSP downloader",
+	""
+);
+
diff --git a/boot/common/src/uboot/downloader/cmd_efuse_program.c b/boot/common/src/uboot/downloader/cmd_efuse_program.c
new file mode 100644
index 0000000..abe9532
--- /dev/null
+++ b/boot/common/src/uboot/downloader/cmd_efuse_program.c
@@ -0,0 +1,276 @@
+/*******************************************************************************
+ * Copyright (C) 2016, ZIXC Corporation.
+ *
+ * File Name:cmd_efuse_program.c
+ * File Mark:
+ * Description:
+ * Others:
+ * Version:       1.0
+ * Author:        zhangdongdong
+ * Date:          2013-3-13
+ * History 1:
+ *     Date:
+ *     Version:
+ *     Author:
+ *     Modification:
+ * History 2:
+  ********************************************************************************/
+
+
+/****************************************************************************
+* 	                                     Include files
+****************************************************************************/
+#include <common.h>
+#include <command.h>
+#include "downloader_config.h"
+#include "downloader_nand.h"
+#include "downloader_serial.h"
+#include <secure_verify.h>
+#include <asm/arch/efuse.h>
+
+/*
+*******************************************************************
+* 	                                     Macro define
+*******************************************************************
+*/
+#define BOARD_TYPE_ZX297520V3		0x0
+#define BOARD_TYPE_ZX297520V3E32M	0x1
+#define BOARD_TYPE_ZX297520V3E64M	0x2
+#define BOARD_TYPE_ZX297520V3E256M	0x3
+
+#define BOARD_TYPE_UNKNOWN			0xFF
+
+
+/****************************************************************************
+*							Global Function Prototypes
+****************************************************************************/
+extern char *tsp_console_buffer;
+
+/*******************************************************************************
+ * Function:do_efuse_program
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+ int do_efuse_program(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+    char *cmd = NULL;
+	unsigned int secure_en = 0;
+	unsigned int chip_flag = 0;
+	unsigned int puk_hash[4] = {0};
+
+	if(argc<6)
+    {
+    	printf("invalid parameter\n");
+        return cmd_usage(cmdtp);
+    }
+
+	cmd = argv[1];
+
+	if (strcmp(cmd, "secure_en") == 0) 
+    {
+    	printf("argv2 = %4s\n",argv[2]);
+		if(strcmp(argv[2], "enable") == 0)
+			efuse_program_secure_en(1);
+		else if(strcmp(argv[2], "disable") == 0)
+			efuse_program_secure_en(0);
+		else
+			return -1;
+
+        return 0;
+	}
+
+	if (strcmp(cmd, "chip_flag") == 0) 
+    {
+		chip_flag = (unsigned int)simple_strtoul (argv[2], NULL, 16);
+		printf("efuse chip_flag=0x%x\n",chip_flag);
+		efuse_program_chip_flag(chip_flag);
+			
+        return 0;
+	}
+
+	if (strcmp(cmd, "puk_hash") == 0) 
+    {
+		puk_hash[0] = (unsigned int)simple_strtoul (argv[2], NULL, 16);
+		puk_hash[1] = (unsigned int)simple_strtoul (argv[3], NULL, 16);
+		puk_hash[2] = (unsigned int)simple_strtoul (argv[4], NULL, 16);
+		puk_hash[3] = (unsigned int)simple_strtoul (argv[5], NULL, 16);
+		printf("efuse puk hash0=0x%x, hash1=0x%x, hash2=0x%x, hash3=0x%x\n",puk_hash[0],puk_hash[1],puk_hash[2],puk_hash[3]);
+		efuse_program_puk_hash(puk_hash);
+        return 0;
+	}
+
+	return -1;	
+}
+
+
+/*******************************************************************************
+ * Function:do_efuse_read
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+ int do_efuse_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+    char *cmd = NULL;
+    char *rx_buffer = tsp_console_buffer;
+    char *ack = tsp_console_buffer;
+	efuse_struct efuse_info ={0};	
+	unsigned int dev_id[3] = {0};
+
+
+	if(argc < 2)
+    {
+    	printf("invalid read parameter\n");
+        return cmd_usage(cmdtp);
+    }
+
+	cmd = argv[1];
+
+	efuse_get_devinfo(&efuse_info);
+	
+	if (strcmp(cmd, "dev_id") == 0) 
+    {
+	
+		dev_id[0] = efuse_info.dev_id[0];
+		dev_id[1] = efuse_info.dev_id[1];
+		dev_id[2] = efuse_info.dev_id[2];
+		
+		sprintf(ack,"dev_id:");
+		downloader_serial_write(ack, strlen(ack)+1);
+
+		memcpy((unsigned char*)(DOWNLOADER_BUFFER_BASE),(unsigned char *)(dev_id),12);	
+		downloader_serial_write_actuallen((const char *)DOWNLOADER_BUFFER_BASE, 12); 
+		
+		printf("devid:[id0] =0x%x, [id1]=0x%x, [id2] =0x%x\n",dev_id[0],dev_id[1],dev_id[2]);
+
+		downloader_readline(rx_buffer);
+		if(memcmp(rx_buffer,"OKAY",4)==0)
+	    {
+	    	sprintf(ack,"DEVID SUCCESS");
+		    downloader_serial_write(ack, strlen(ack)+1);		
+	        return 0;
+	    }	
+	}
+	
+   sprintf(ack,"FAIL COMMAND ERROR");
+   downloader_serial_write(ack, strlen(ack)+1);
+   return -1;	
+}
+
+
+U_BOOT_CMD(
+	efuse_program, CONFIG_SYS_MAXARGS, 0, do_efuse_program,
+	"efuse_program: program [puk_hash/secure_en/chip_flag] [hash0/enable/SPE][hash1][hash2][hash3]",
+	""
+);
+
+U_BOOT_CMD(
+	efuse_read, CONFIG_SYS_MAXARGS, 0, do_efuse_read,
+	"efuse_read: read [devid]",
+	""
+);
+
+/*
+ ******************************************************************************
+ * Function:do_read_board_type
+ * Description:
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ *******************************************************************************
+ */
+ int do_read_board_type(cmd_tbl_t *cmdtp, int flag, 
+ 								int argc, char * const argv[])
+{
+    char *ack = tsp_console_buffer;
+	efuse_struct efuse_info ={0};
+	unsigned int secure_flag = 0;
+	unsigned int chip_flag = 0;
+	unsigned int board_type = 0;
+
+	if(argc != 1)
+    {
+        return cmd_usage(cmdtp);
+    }
+
+	efuse_get_devinfo(&efuse_info);
+
+	secure_flag = efuse_info.secure_flag;
+	chip_flag = secure_flag >> 8;
+	if((chip_flag == ZX297520V3_GW_NYB_1G_DDR)
+		||(chip_flag == ZX297520V3_GW_NYC_1G_DDR)
+		||(chip_flag == ZX297520V3ECO_GW_NYB_1G_DDR)
+		||(chip_flag == ZX297520V3ECO_GW_NYC_1G_DDR)
+		||(chip_flag == ZX297520V3SC_GW_NYC_1G_DDR)
+		||(chip_flag == ZX297520V3ECOSCC_GW_UNILC_1G_DDR)
+		||(chip_flag == ZX297520V3ECOSCC_GW_NYC_1G_DDR)
+		||(chip_flag == ZX297520V3ECOSC_GW_NYC_1G_DDR)
+		||(chip_flag == ZX297520V3ECOSC_GW_UNILC_1G_DDR)
+		||(chip_flag == ZX297520V3_ZW_NYB_1G_DDR)
+		||(chip_flag == ZX297520V3_ZW_NYC_1G_DDR)
+		||(chip_flag == ZX297520V3ECO_ZW_NYB_1G_DDR)
+		||(chip_flag == ZX297520V3ECO_ZW_NYC_1G_DDR))
+	{
+		printf("chip_flag=0x%x board_type is V3.\n", chip_flag);
+		board_type = BOARD_TYPE_ZX297520V3;
+	}
+	else if((chip_flag == ZX297520V3ECO_GW_UNILC_512M_DDR)
+			||(chip_flag == ZX297520V3ECO_GW_APM_512M_DDR)
+			||(chip_flag == ZX297520V3ECO_GW_ESMT_512M_DDR)
+			||(chip_flag == ZX297520V3ECO_ZW_UNILC_512M_DDR)
+			||(chip_flag == ZX297520V3ECO_AZW_UNILC_512M_DDR)
+			||(chip_flag == ZX297520V3ECO_ZW_APM_512M_DDR)
+			||(chip_flag == ZX297520V3ECO_ZW_ESMT_512M_DDR))
+	{
+		printf("chip_flag=0x%x board_type is V3E.\n", chip_flag);
+		board_type = BOARD_TYPE_ZX297520V3E64M;
+	}
+	else if(chip_flag == ZX297520V3ECOSC_GW_NYC_2G_DDR)
+	{
+		printf("chip_flag=0x%x board_type is V3E.\n", chip_flag);
+		board_type = BOARD_TYPE_ZX297520V3E256M;
+	}	
+	else if((chip_flag == ZX297520V3ECO_GW_WINBD_256M_DDR)
+			||(chip_flag == ZX297520V3ECO_GW_UNILC_256M_DDR)
+			||(chip_flag == ZX297520V3ECO_GW_APM_256M_DDR)
+			||(chip_flag == ZX297520V3ECO_ZW_WINBD_256M_DDR)
+			||(chip_flag == ZX297520V3ECO_ZW_UNILC_256M_DDR)
+			||(chip_flag == ZX297520V3ECO_ZW_APM_256M_DDR))
+	{
+		printf("chip_flag=0x%x board_type is V3T.\n", chip_flag);
+		board_type = BOARD_TYPE_ZX297520V3E32M;
+	}
+	else
+	{
+		printf("chip_flag=0x%x board_type is unknown.\n", chip_flag);
+		board_type = BOARD_TYPE_UNKNOWN;
+	}
+
+	sprintf(ack,"%04x", board_type);
+	downloader_serial_write(ack, strlen(ack)+1);
+   	return 0;	
+}
+
+U_BOOT_CMD(
+	read_board_type, CONFIG_SYS_MAXARGS, 0, do_read_board_type,
+	"read board type.",
+	""
+);
+
diff --git a/boot/common/src/uboot/downloader/cmd_erase.c b/boot/common/src/uboot/downloader/cmd_erase.c
new file mode 100644
index 0000000..7d68e95
--- /dev/null
+++ b/boot/common/src/uboot/downloader/cmd_erase.c
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * Copyright (C) 2016, ZIXC Corporation.
+ *
+ * File Name:cmd_erase.c
+ * File Mark:
+ * Description:
+ * Others:
+ * Version:       1.0
+ * Author:        zangxiaofeng
+ * Date:          2013-3-15
+ * History 1:
+ *     Date:
+ *     Version:
+ *     Author:
+ *     Modification:
+ * History 2:
+  ********************************************************************************/
+
+
+/****************************************************************************
+* 	                                     Include files
+****************************************************************************/
+#include <common.h>
+#include <command.h>
+#include <net.h>
+#include <jffs2/load_kernel.h>
+#include "downloader_config.h"
+#include "downloader_nand.h"
+#include "downloader_serial.h"
+#include "errno.h"
+#include "mmc.h"
+
+/****************************************************************************
+* 	                                     Function Definitions
+****************************************************************************/
+
+extern partition_table_t * g_partition_table;
+extern char *tsp_console_buffer;
+
+
+/*******************************************************************************
+ * Function:do_erase
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int do_erase(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+    partition_entry_t *part = NULL;
+    char *par=NULL;
+    char *ack=tsp_console_buffer;
+    int ret = 0;
+	int type = 0;
+
+    if(argc<2)
+    {
+        return cmd_usage(cmdtp);
+    }
+	type = read_boot_flashtype();
+    par = argv[1]; /*erase cmd*/
+    if((strcmp(par,"all") == 0) || (strcmp(par,"raw") == 0))
+    {
+		if((type == IF_TYPE_NAND)||(type == IF_TYPE_SPI_NAND))
+		{
+		    ret = downloader_nand_eraseall();
+		}
+		else if(type == IF_TYPE_NOR) 
+		{
+        	ret = downloader_nor_eraseall();
+		}
+		
+        if(ret == 0)
+        {
+            sprintf(ack,"OKAY");
+            downloader_serial_write(ack, strlen(ack)+1);
+            return 0;
+        }
+        else
+        {
+            sprintf(ack,"FAIL NAND ERASE");
+            downloader_serial_write(ack, strlen(ack)+1);
+            return ENOSYS;  /* Function not implemented */
+        }
+    }
+	
+    if(strcmp(par,"auto") == 0)
+    {
+	    if((type == IF_TYPE_NAND)||(type == IF_TYPE_SPI_NAND))
+		{
+		    ret = downloader_nand_erase_auto();
+		}
+		else if(type == IF_TYPE_NOR) 
+		{
+        	ret = downloader_nor_erase_auto();
+		}
+			
+        if(ret == 0)
+        {
+            sprintf(ack,"OKAY");
+            downloader_serial_write(ack, strlen(ack)+1);
+            return 0;
+        }
+        else
+        {
+            sprintf(ack,"FAIL NAND ERASE");
+            downloader_serial_write(ack, strlen(ack)+1);
+            return ENOSYS;  /* Function not implemented */
+        }
+    }
+	
+    part = downloader_get_part(par);
+    if(part == NULL)
+    {
+        sprintf(ack,"FAIL INVALID PARTITION");
+        downloader_serial_write(ack, strlen(ack)+1);
+        return EINVAL;	/* Invalid argument */
+    }
+
+	if((type == IF_TYPE_NAND)||(type == IF_TYPE_SPI_NAND))
+	{
+		ret = downloader_nand_erase(part,part->part_size);
+	}
+	else if(type == IF_TYPE_NOR) 
+	{
+        ret = downloader_nor_erase(part, part->part_size);
+	}
+
+	
+    if(ret == 0)
+    {
+        sprintf(ack,"OKAY");
+        downloader_serial_write(ack, strlen(ack)+1);
+        return 0;
+    }
+    else
+    {
+        sprintf(ack,"FAIL NAND ERASE");
+        downloader_serial_write(ack, strlen(ack)+1);
+        return ENOSYS;  /* Function not implemented */
+    }
+}
+
+U_BOOT_CMD(
+	erase, CONFIG_SYS_MAXARGS, 0, do_erase,
+	"Erase nand: erase [partition]",
+	""
+);
+
+    
diff --git a/boot/common/src/uboot/downloader/cmd_getvar.c b/boot/common/src/uboot/downloader/cmd_getvar.c
new file mode 100644
index 0000000..72622b6
--- /dev/null
+++ b/boot/common/src/uboot/downloader/cmd_getvar.c
@@ -0,0 +1,411 @@
+/*******************************************************************************
+ * Copyright (C) 2016, ZIXC Corporation.
+ *
+ * File Name:     cmd_getvar.c
+ * File Mark:
+ * Description:   get information such as IMEI,SN,NV CONFIG from UE.
+ * Others:
+ * Version:       1.0
+ * Author:        zangxiaofeng
+ * Date:          2013-3-6
+ * History 1:
+ *     Date:      2013-11-6
+ *     Version:
+ *     Author:
+ *     Modification: mod for after-sale tool
+ * History 2:
+  ********************************************************************************/
+/****************************************************************************
+* 	                                           Include files
+****************************************************************************/
+#include <common.h>
+#include <command.h>
+#include <net.h>
+#include "downloader_serial.h"
+#include <jffs2/load_kernel.h>
+#include "downloader_nand.h"
+#include "errno.h"
+
+extern char *tsp_console_buffer;
+
+/****************************************************************************
+* 	                                           Local Macros
+****************************************************************************/
+
+/*NVR AMT LENGTH*/
+#define ZPS_ImeiLen                                    20
+#define ZPS_ImeiSvLen                                  20
+#define ZPS_DEV_MSINFO_MAX_BORDNAME_LEN                20
+#define ZPS_DEV_MSINFO_MAX_MSerialNum_LEN              20
+#define ZPS_DEV_MSINFO_MAX_ValidFlag_LEN               4
+#define ZPS_DEV_MSINFO_MAX_InternalMAC_LEN             20
+#define ZPS_DEV_MSINFO_MAX_ExternalMAC_LEN             20
+#define ZPS_DEV_MSINFO_MAX_WIFIMAC_LEN                 20
+#define ZPS_DEV_MSINFO_MAX_NvVersion_LEN               40
+#define ZPS_DEV_MSINFO_MAX_TestInfo_LEN                200
+#define ZPS_DEV_MSINFO_MAX_SOFTVERSION_LEN             10 
+#define ZPS_NVR_LEN                                    394
+
+/*NVRW AMT LENGTH*/
+#define SoftVersion_LEN         10
+#define Register_LEN            77
+#define Bflag_LEN               1
+#define Reserve_LEN             40
+#define AfterSaleVersion_LEN    670
+#define InerVersion_LEN         100
+#define ExVersion_LEN           100
+#define HWVersion_LEN           100
+#define PCUIVersion_LEN         100
+#define InerMdelNum_LEN         32
+#define ExModelNum_LEN          32
+#define ModemVersion_LEN        100
+#define ZPS_NVRW_LEN            1362
+
+/****************************************************************************
+*							Local Types
+****************************************************************************/
+typedef struct
+{
+    unsigned int nvID;        /*NV file ID */
+    unsigned char nvPart[4];  /* NV partition name,nvr or nvrw */
+    unsigned int addr;        /*NV file address */
+    unsigned int size;        /*NV file size*/
+}Tsp_Nv_Config_Item;     /*NV CONFIG ITEM*/
+
+#define TSP_NV_COUNT 7
+Tsp_Nv_Config_Item tspNvConfig[TSP_NV_COUNT]=
+{
+{0,"nvro",0x0,16384},
+{1,"nvro",0x4000,98304},
+{2,"nvro",0x1c000,32768},
+{3,"nvro",0x24000,16384},
+{4,"nvro",0x28000,32768},
+{5,"nvro",0x30000,32768},
+{6,"nvro",0x38000,32768},
+};
+
+
+typedef struct getvar_info_nvr
+{
+     
+	/********************************************************************************
+        ¹¦ÄÜ£º   Ó²¼þÉ豸ºÅ
+        ȡֵ·¶Î§£ºIMEIÖÐÿһ¸öBCDÂ뷶ΧΪ0-9
+        ³ö³§Öµ£ºÓɳö²ú³§É̾ö¶¨
+         *********************************************************************************/
+    unsigned char    abImei[ZPS_ImeiLen]; 
+    
+	/********************************************************************************
+          ¹¦ÄÜ£º   Èí¼þ°æ±¾ºÅ
+          ȡֵ·¶Î§£ºIMEISVÖÐÿһ¸öBCDÂ뷶ΧΪ0-9
+          ³ö³§Öµ£ºÓɳö²ú³§É̾ö¶¨
+          *********************************************************************************/
+    unsigned char    abImeiSv[ZPS_ImeiSvLen];
+    
+    /********************************************************************************
+    ¹¦ÄÜ£º   Ö÷°åºÅ£¬ÓÉBCDÂë×é³É
+    ȡֵ·¶Î§£ºÖ÷°åºÅÖÐÿһ¸öBCDÂ뷶ΧΪ0-9
+    ³ö³§Öµ£ºÓɳö²ú³§É̾ö¶¨
+    *********************************************************************************/
+    unsigned char    abBordNum[ZPS_DEV_MSINFO_MAX_BORDNAME_LEN];
+    
+    /********************************************************************************
+    ¹¦ÄÜ£º   
+    ȡֵ·¶Î§£ºÈÎÒâ×Ö·û´®,ÒÔ'\0'±íʾ½áÊø
+    ³ö³§Öµ£ºÓɳö²ú³§É̾ö¶¨
+    *********************************************************************************/
+    unsigned char    abMSerialNum[ZPS_DEV_MSINFO_MAX_MSerialNum_LEN];
+    
+    /********************************************************************************
+    ¹¦ÄÜ£º  	MACµØÖ·Ñ¡Ôñ±ê־λ
+    ȡֵ·¶Î§£º0x30»òÕß0x31£¬Ä¬ÈÏΪ0x30
+    ³ö³§Öµ£º0x30
+    *********************************************************************************/
+    unsigned char	abValidFlag[ZPS_DEV_MSINFO_MAX_ValidFlag_LEN];
+    
+    /********************************************************************************
+    ¹¦ÄÜ£º   ÄÚ²¿MAC µØÖ·
+    ȡֵ·¶Î§£ºBCDÂë
+    ³ö³§Öµ£ºÓÉ´ó°æ±¾Ê×´ÎÆô¶¯Ê±Ð´Èë
+    *********************************************************************************/
+    unsigned char    abInternalMAC[ZPS_DEV_MSINFO_MAX_InternalMAC_LEN];
+    
+    /********************************************************************************
+    ¹¦ÄÜ£º   ÍⲿMAC µØÖ·
+    ȡֵ·¶Î§£ºBCDÂë
+    ³ö³§Öµ£ºÓÉ´ó°æ±¾Ê×´ÎÆô¶¯Ê±Ð´Èë
+    *********************************************************************************/
+    unsigned char    abExternalMAX[ZPS_DEV_MSINFO_MAX_ExternalMAC_LEN];
+	
+    /********************************************************************************
+    ¹¦ÄÜ£º   WIFI MACµØÖ·
+    ȡֵ·¶Î§£ºBCDÂë
+    ³ö³§Öµ£ºÓÉ´ó°æ±¾Ê×´ÎÆô¶¯Ê±Ð´Èë
+    *********************************************************************************/
+    unsigned char    abWiFiMAC[ZPS_DEV_MSINFO_MAX_WIFIMAC_LEN];
+   
+    /********************************************************************************
+    ¹¦ÄÜ£º   ָʾNV°æ±¾
+    ȡֵ·¶Î§£º¿É¼ûASCIIÂë×Ö·û£¬ÒÔ×Ö·û'\0'½áÊø£¬Ê£Óà×Ö½ÚÌî³ä0x00
+    ³ö³§Öµ£ºÓÉ´ó°æ±¾Ê×´ÎÆô¶¯Ê±Ð´Èë
+    *********************************************************************************/
+    unsigned char    abNVVersion[ZPS_DEV_MSINFO_MAX_NvVersion_LEN];
+    
+    /********************************************************************************
+    ¹¦ÄÜ£º  Éú²ú²âÊÔ±ê־λ
+    ȡֵ·¶Î§£º
+    ³ö³§Öµ£ºÓÉ´ó°æ±¾Ê×´ÎÆô¶¯Ê±Ð´Èë
+    *********************************************************************************/
+	unsigned char	 abTestInfo[ZPS_DEV_MSINFO_MAX_TestInfo_LEN];
+
+}getvar_info_nvr_t;
+
+typedef struct getvar_info_nvrw
+{
+     
+	/********************************************************************************
+        ¹¦ÄÜ£º   Èí¼þ°æ±¾ºÅ
+        ȡֵ·¶Î§£º
+        ³ö³§Öµ£ºÓɳö²ú³§É̾ö¶¨
+         *********************************************************************************/
+    unsigned char    SoftVersion[SoftVersion_LEN]; 
+	 
+	/********************************************************************************
+        ¹¦ÄÜ£º   ×Ô×¢²áÐÅÏ¢
+        ȡֵ·¶Î§£º
+        ³ö³§Öµ£ºÓɳö²ú³§É̾ö¶¨
+         *********************************************************************************/              
+    unsigned char    Register[Register_LEN];  
+   	
+	/********************************************************************************
+	  ¹¦ÄÜ£º	 BFLAGСϵͳÆô¶¯Ä£Ê½ÐÅÏ¢
+	  ȡֵ·¶Î§£º
+	  ³ö³§Öµ£ºÓɳö²ú³§É̾ö¶¨
+	********************************************************************************/ 
+	unsigned char	 Bflag[Bflag_LEN];
+      
+	/********************************************************************************
+	  ¹¦ÄÜ£º ±£Áô
+	  ȡֵ·¶Î§£º
+	  ³ö³§Öµ£ºÓɳö²ú³§É̾ö¶¨
+	********************************************************************************/ 
+    unsigned char   Reserve[Reserve_LEN];
+   
+	/********************************************************************************
+	  ¹¦ÄÜ£º ÊÛºó°æ±¾¿ØÖÆ
+	  ȡֵ·¶Î§£º
+	  ³ö³§Öµ£ºÓɳö²ú³§É̾ö¶¨
+	********************************************************************************/
+	unsigned char   AfterSaleVersion[AfterSaleVersion_LEN];   
+      
+	/********************************************************************************
+	  ¹¦ÄÜ£º ÄÚ²¿°æ±¾ºÅ
+	  ȡֵ·¶Î§£º
+	  ³ö³§Öµ£ºÓɳö²ú³§É̾ö¶¨
+	********************************************************************************/
+    unsigned char   InerVersion[InerVersion_LEN];
+	  
+	/********************************************************************************
+	  ¹¦ÄÜ£ºÍⲿ°æ±¾ºÅ
+	  ȡֵ·¶Î§£º
+	  ³ö³§Öµ£ºÓɳö²ú³§É̾ö¶¨
+	********************************************************************************/
+    unsigned char   ExVersion[ExVersion_LEN]; 
+	   
+	/********************************************************************************
+	  ¹¦ÄÜ£ºÓ²¼þ°æ±¾ºÅ
+	  ȡֵ·¶Î§£º
+	  ³ö³§Öµ£ºÓɳö²ú³§É̾ö¶¨
+	********************************************************************************/
+    unsigned char   HWVersion[HWVersion_LEN];
+      
+   /********************************************************************************
+		 ¹¦ÄÜ£ºPCUI °æ±¾ºÅ
+		 ȡֵ·¶Î§£º
+		 ³ö³§Öµ£ºÓɳö²ú³§É̾ö¶¨
+    ********************************************************************************/
+    unsigned char   PCUIVersion[PCUIVersion_LEN];
+     
+   /********************************************************************************
+	  ¹¦ÄÜ£ºÄÚ²¿ÐͺÅ
+	  ȡֵ·¶Î§£º
+	  ³ö³§Öµ£ºÓɳö²ú³§É̾ö¶¨
+	********************************************************************************/
+    unsigned char   InerMdelNum[InerMdelNum_LEN]; 
+     
+   /********************************************************************************
+	  ¹¦ÄÜ£ºÍⲿÐͺÅ
+	  ȡֵ·¶Î§£º
+	  ³ö³§Öµ£ºÓɳö²ú³§É̾ö¶¨
+	********************************************************************************/
+    unsigned char   ExModelNum[ExModelNum_LEN]; 
+     
+   /********************************************************************************
+	  ¹¦ÄÜ£ºMODEM°æ±¾ºÅ
+	  ȡֵ·¶Î§£º
+	  ³ö³§Öµ£ºÓɳö²ú³§É̾ö¶¨
+      ********************************************************************************/
+    unsigned char   ModemVersion[ModemVersion_LEN]; 
+}getvar_info_nvrw_t;
+
+typedef struct getvar_info_dl
+{
+    unsigned char    abImei[ZPS_ImeiLen];   
+	/********************************************************************************
+        ¹¦ÄÜ£º   Ó²¼þÉ豸ºÅ
+        ȡֵ·¶Î§£ºIMEIÖÐÿһ¸öBCDÂ뷶ΧΪ0-9
+        ³ö³§Öµ£ºÓɳö²ú³§É̾ö¶¨
+         *********************************************************************************/
+    unsigned char    abBordNum[ZPS_DEV_MSINFO_MAX_BORDNAME_LEN];
+    /********************************************************************************
+    ¹¦ÄÜ£º   Ö÷°åºÅ£¬ÓÉBCDÂë×é³É
+    ȡֵ·¶Î§£ºÖ÷°åºÅÖÐÿһ¸öBCDÂ뷶ΧΪ0-9
+    ³ö³§Öµ£ºÓɳö²ú³§É̾ö¶¨
+    *********************************************************************************/
+    unsigned char   InerVersion[InerVersion_LEN];   
+	/********************************************************************************
+	  ¹¦ÄÜ£º ÄÚ²¿°æ±¾ºÅ
+	  ȡֵ·¶Î§£º
+	  ³ö³§Öµ£ºÓɳö²ú³§É̾ö¶¨
+	********************************************************************************/
+	unsigned char   ExVersion[ExVersion_LEN];   
+	/********************************************************************************
+	  ¹¦ÄÜ£ºÍⲿ°æ±¾ºÅ
+	  ȡֵ·¶Î§£º
+	  ³ö³§Öµ£ºÓɳö²ú³§É̾ö¶¨
+	********************************************************************************/
+	unsigned char	InerMdelNum[InerMdelNum_LEN];	
+   /********************************************************************************
+	 ¹¦ÄÜ£ºÄÚ²¿ÐͺÅ
+	 ȡֵ·¶Î§£º
+	 ³ö³§Öµ£ºÓɳö²ú³§É̾ö¶¨
+	********************************************************************************/
+
+	unsigned char   ExModelNum[ExModelNum_LEN];   
+   /********************************************************************************
+	  ¹¦ÄÜ£ºÍⲿÐͺÅ
+	  ȡֵ·¶Î§£º
+	  ³ö³§Öµ£ºÓɳö²ú³§É̾ö¶¨
+	********************************************************************************/
+    
+}getvar_info_dl_t;
+
+/*******************************************************************************
+ * Function:do_getvar
+ * Description:Sending UE information to After_sale update toll. 
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:0 :success;
+ *            -1:fail;
+ *
+ * Others:
+ ********************************************************************************/ 
+int do_getvar(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+#if 0 //hsy
+    char *ack = NULL;
+    char *cmd = NULL;
+	int ret = 0;
+	partition_entry_t *part = NULL;
+	getvar_info_nvr_t *info_nvr = NULL;
+	getvar_info_nvrw_t *info_nvrw = NULL;
+	getvar_info_dl_t *info_dl = NULL;
+	
+	char *data_nvr = kzalloc(ZPS_NVR_LEN, GFP_KERNEL);
+	char *data_nvrw = kzalloc(ZPS_NVRW_LEN, GFP_KERNEL);
+	ack = tsp_console_buffer;
+	info_dl = kzalloc(4096, GFP_KERNEL);
+    cmd = argv[1];
+    if (argc < 2)
+    {
+        return cmd_usage(cmdtp);
+    }
+	part = downloader_get_part("nvro");   /*NVR READ*/
+	ret = downloader_zftl_read( part, 0, ZPS_NVR_LEN,  (unsigned char *)data_nvr);
+
+	part = downloader_get_part("nvrw");  /*NVRW READ*/
+	ret = downloader_zftl_read( part, 0, ZPS_NVRW_LEN,  (unsigned char *)data_nvrw);
+	if(ret)
+	{
+        sprintf(ack,"FAIL ZFTL READ ");
+        downloader_serial_write(ack, strlen(ack)+1);
+        kfree(data_nvr);
+        kfree(data_nvrw);
+		kfree(info_dl);
+        return ENOSYS;  /* Function not implemented */           
+	}
+	info_nvr = (getvar_info_nvr_t *)data_nvr;
+	info_nvrw = (getvar_info_nvrw_t *)data_nvrw;
+
+	memcpy(info_dl->abImei,info_nvr->abImei,ZPS_ImeiLen);     /*copy information from NV*/
+    memcpy(info_dl->abBordNum,info_nvr->abBordNum,ZPS_DEV_MSINFO_MAX_BORDNAME_LEN);
+	memcpy(info_dl->InerVersion,info_nvrw->InerVersion,InerVersion_LEN);
+	memcpy(info_dl->ExVersion,info_nvrw->ExVersion,ExVersion_LEN);
+	memcpy(info_dl->InerMdelNum,info_nvrw->InerMdelNum,InerMdelNum_LEN);
+	memcpy(info_dl->ExModelNum,info_nvrw->ExModelNum,ExModelNum_LEN);
+
+	if(strcmp(cmd,"version") == 0)
+    {
+		sprintf(ack,"DATA %08x",sizeof(getvar_info_dl_t));
+		downloader_serial_write(ack, strlen(ack)+1);    /* send length info*/
+		
+		downloader_readline(tsp_console_buffer); 
+	    if(memcmp(tsp_console_buffer,"OKAY",4)==0)               /* receive OKAY*/
+	    {
+            memcpy(ack,info_dl,sizeof(getvar_info_dl_t)); /* send information*/
+		    downloader_serial_write_actuallen(ack,sizeof(getvar_info_dl_t));
+	    }
+		else
+	    {
+            sprintf(ack,"FAIL COMMAND ERROR");
+            downloader_serial_write(ack, strlen(ack)+1);
+	        return EBADRQC;		/* Invalid request code */
+	    }
+    }
+	
+    else if(strcmp(cmd,"nv")== 0)
+    {
+        sprintf(ack,"DATA %08x",sizeof(tspNvConfig)+1);
+		downloader_serial_write(ack, strlen(ack)+1);    /* send length info*/
+
+		downloader_readline(tsp_console_buffer); 
+	    if(memcmp(tsp_console_buffer,"OKAY",4)==0)                /* receive OKAY*/
+	    {
+            ack[0] = TSP_NV_COUNT;
+            memcpy(&ack[1],&tspNvConfig,sizeof(tspNvConfig)); /* send nv config*/
+		    downloader_serial_write_actuallen(ack,sizeof(tspNvConfig)+1);
+	    }
+		else
+	    {
+            sprintf(ack,"FAIL COMMAND ERROR");
+            downloader_serial_write(ack, strlen(ack)+1);
+	        return EBADRQC;		/* Invalid request code */
+	    }
+    }
+    else
+    {
+	    sprintf(ack,"FAIL NOINFORMATION");
+        downloader_serial_write(ack,strlen(ack)+1);
+		kfree(data_nvr);
+        kfree(data_nvrw);
+		kfree(info_dl);
+        return -1;
+    }
+    kfree(data_nvr);
+    kfree(data_nvrw);
+	kfree(info_dl);
+#endif
+
+	return 0;
+}
+U_BOOT_CMD(
+	getvar, CONFIG_SYS_MAXARGS, 0, do_getvar,
+	"Downloader get information: getvar [info]",
+	""
+);
+
+
+
diff --git a/boot/common/src/uboot/downloader/cmd_ram_start.c b/boot/common/src/uboot/downloader/cmd_ram_start.c
new file mode 100644
index 0000000..598182b
--- /dev/null
+++ b/boot/common/src/uboot/downloader/cmd_ram_start.c
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (C) 2016, ZIXC Corporation.
+ *
+ * File Name:cmd_ram_start.c
+ * File Mark:
+ * Description:
+ * Others:
+ * Version:       1.0
+ * Author:        zangxiaofeng
+ * Date:          2013-4-22
+ * History 1:
+ *     Date:
+ *     Version:
+ *     Author:
+ *     Modification:
+ * History 2:
+  ********************************************************************************/
+
+
+/****************************************************************************
+* 	                                     Include files
+****************************************************************************/
+#include <common.h>
+#include <command.h>
+#include <net.h>
+#include <jffs2/load_kernel.h>
+#include "downloader_nand.h"
+#include "downloader_config.h"
+#include "downloader_serial.h"
+#include <asm/arch/cpu.h>
+#include <asm/io.h>
+
+
+static is_flush = 0;
+extern char *tsp_console_buffer;
+extern uint32_t arm_ps_ep;
+/****************************************************************************
+*							Global Function Prototypes
+****************************************************************************/
+int start_core(uchar *core_name, unsigned int addr);
+
+ 
+/*******************************************************************************
+ * Function:do_ram_start
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int do_ram_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	char *ack = tsp_console_buffer;
+	unsigned int i = 0;
+	unsigned int addr = 0;
+
+	if(argc < 1)
+	{
+		return cmd_usage(cmdtp);
+	}
+ 
+	sprintf(ack,"OKAY ram_start");
+	downloader_serial_write(ack, strlen(ack)+1); 
+	for(i=1; i<argc; i=i+2)
+	{
+		addr = (unsigned int)simple_strtoul (argv[i+1], NULL, 16);
+		printf("core is %s, addr is %x\n",(uchar *)argv[i],addr);
+		start_core((uchar *)argv[i], addr);
+	}
+	hang();
+	return 0;
+}
+
+U_BOOT_CMD(
+	ram_start, CONFIG_SYS_MAXARGS, 0, do_ram_start,
+	"ram_start: ram_start",
+	""
+);
+
+ int start_core(uchar *core_name, unsigned int addr)
+{
+	char *ack = tsp_console_buffer;
+
+	if(strcmp((const char *)core_name,"ps") == 0)
+	{
+		if(addr != 0xffffffff)
+		{
+			/* д PS Ìø×ªÆô¶¯´úÂë */ 
+
+			/* flush d-cache */
+			if( is_flush != 1 )
+			{
+				is_flush = 1;
+				cleanup_before_linux();
+			}
+			arm_ps_ep = addr;            
+			/* ÊÍ·ÅÆô¶¯ ARM_PS  */
+			printf("Starting the arm_ps ...\n");
+			start_arm_ps();
+		}
+		else
+		{
+			printf("No Starting the arm_ps ...\n");
+		}
+	}
+	else if (strcmp((const char *)core_name,"phy") == 0)
+	{
+		if(addr != 0xffffffff)
+		{
+			/* д PHY Ìø×ªÆô¶¯´úÂë */ 
+
+			/* flush d-cache */
+			/*if( is_flush != 1 )
+			{
+				is_flush = 1;
+				cleanup_before_linux();
+			}*/
+			//load_zsp_image(addr);
+			/* ÊÍ·ÅÆô¶¯ ARM_PHY  */
+
+			printf("Starting the arm_phy ...\n");
+		}
+		else
+		{
+			printf("No Starting the arm_phy ...\n");
+		}
+	}
+	else
+	{
+		sprintf(ack,"FAIL INVILID CORE NAME");
+		downloader_serial_write(ack, strlen(ack)+1);
+		return -1;
+	}
+	return 0;
+}
+        
diff --git a/boot/common/src/uboot/downloader/cmd_set.c b/boot/common/src/uboot/downloader/cmd_set.c
new file mode 100755
index 0000000..9e98959
--- /dev/null
+++ b/boot/common/src/uboot/downloader/cmd_set.c
@@ -0,0 +1,408 @@
+/*******************************************************************************

+ * Copyright (C) 2016, ZIXC Corporation.

+ *

+ * File Name:cmd_set.c

+ * File Mark:

+ * Description:

+ * Others:

+ * Version:       1.0

+ * Author:        zangxiaofeng

+ * Date:          2013-6-8

+ * History 1:

+ *     Date:

+ *     Version:

+ *     Author:

+ *     Modification:

+ * History 2:

+  ********************************************************************************/

+/****************************************************************************

+* 	                                     Include files

+****************************************************************************/

+#include <common.h>

+#include <command.h>

+#include <net.h>

+#include <jffs2/load_kernel.h>

+#include <nand.h>

+#include <linux/mtd/spi-nor.h>

+#include <linux/mtd/nor_spifc.h>

+

+#include "downloader_config.h"

+#include "downloader_nand.h"

+#include "downloader_serial.h"

+#include "errno.h"

+#include "boot_mode.h"

+

+

+#define ZLOAD_PARTITION_SIZE	0x3000

+

+

+/****************************************************************************

+*							Global Function Prototypes

+****************************************************************************/

+extern partition_table_t * g_partition_table;

+int set_partitions(unsigned int size);

+partition_entry_t * get_partitions(const char *partname, partition_table_t *table);

+

+partition_table_t * g_partition_table_dl = NULL;

+

+extern char *tsp_console_buffer;

+extern struct fsl_qspi spi_nor_flash;

+

+

+/*******************************************************************************

+ * Function:do_set

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *

+ *

+ * Others:

+ ********************************************************************************/

+int do_set(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])

+{

+    

+    char *par = NULL;

+	unsigned int size = 0;

+	unsigned int ret = 0;

+	

+	if(argc<3)

+    {

+        return cmd_usage(cmdtp);

+    }

+	par = argv[1];

+	size = (unsigned int)simple_strtoul (argv[2], NULL, 16);

+

+	if(strcmp(par,"partitions") == 0)

+	{

+	    sprintf(tsp_console_buffer,"OKAY RECV_TABLES");

+        downloader_serial_write(tsp_console_buffer, strlen(tsp_console_buffer)+1);

+	    ret = set_partitions(size);

+		return ret;

+	}

+	else

+	{

+	    sprintf(tsp_console_buffer,"FAIL COMMAND ERROR");

+        downloader_serial_write(tsp_console_buffer, strlen(tsp_console_buffer)+1);

+		return -1;

+	}

+	

+

+}

+U_BOOT_CMD(

+	set, CONFIG_SYS_MAXARGS, 0, do_set,

+	"set : set [module] [size]",

+	""

+);

+

+/*******************************************************************************

+ * Function:set_partitions

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *

+ *

+ * Others:

+ ********************************************************************************/

+ int set_partitions(unsigned int size)

+{

+	partition_entry_t *part_nvr = NULL;

+	partition_entry_t *part_nvr_dl = NULL;

+	partition_table_t *table_dl = NULL;

+	char *table_new = (char*)(CONFIG_USB_DMA_BUF_ADDR); /*USB DMA BUFFER*/

+

+	/* UE´ÓPC»ñÈ¡·ÖÇø±í */

+	downloader_serial_read_actuallen((char *)table_new, size); 

+	table_dl = (partition_table_t *)table_new;

+	

+	g_partition_table_dl = kzalloc(4096, GFP_KERNEL);

+	if(g_partition_table_dl == NULL)

+	{

+		printf("set_partitions kzalloc failed.\n");

+		return -1;

+	}

+	

+	memcpy(g_partition_table_dl,table_dl,size);

+	if(table_dl->magic != PARTITION_MAGIC)

+	{

+	    sprintf(tsp_console_buffer,"FAIL INVALID_PARTITION_TABLE");

+        downloader_serial_write(tsp_console_buffer, strlen(tsp_console_buffer)+1);

+		return -1;

+	}

+

+	/* ·ÖÇø±íÆ¥Åä»òûÓзÖÇø±í */

+	if(memcmp( g_partition_table, table_dl, sizeof(partition_table_t))==0

+		|| g_partition_table->magic != PARTITION_MAGIC)   

+	{

+	    g_partition_table = g_partition_table_dl;

+		sprintf(tsp_console_buffer,"OKAY");

+        downloader_serial_write(tsp_console_buffer, strlen(tsp_console_buffer)+1);

+		return 0;

+	}

+	else

+	{

+		/* UE´ÓPC»ñÈ¡NV·ÖÇøÐÅÏ¢ */

+	    part_nvr_dl = get_partitions("nvrofs", table_dl);    

+		if(part_nvr_dl == NULL)

+		{

+			printf("pc part nvrofs get failed.\n");

+			return -1;

+		}

+

+		/* ´ÓUEµÄNAND¶ÁÈ¡NV·ÖÇøÐÅÏ¢ */		

+	    part_nvr = get_partitions("nvrofs", g_partition_table);

+		if(part_nvr == NULL)

+		{

+			printf("part_nvrofs get failed.\n");

+		    sprintf(tsp_console_buffer,"FAIL UNACCEPTABLE_PARTITION_CHANGE");

+            downloader_serial_write(tsp_console_buffer, strlen(tsp_console_buffer)+1);

+			return -1;	

+		}

+		

+		if((part_nvr->part_offset == part_nvr_dl->part_offset)

+			&&(part_nvr->part_size == part_nvr_dl->part_size))

+		{

+            sprintf(tsp_console_buffer,"FAIL ACCEPTABLE_PARTITION_CHANGE");

+            downloader_serial_write(tsp_console_buffer, strlen(tsp_console_buffer)+1);

+		    return 0;

+		}

+		else

+		{

+		    sprintf(tsp_console_buffer,"FAIL UNACCEPTABLE_PARTITION_CHANGE");

+            downloader_serial_write(tsp_console_buffer, strlen(tsp_console_buffer)+1);

+		    return -1;

+		}

+	}

+}

+

+/*******************************************************************************

+ * Function:get_partitions

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *

+ *

+ * Others:

+ ********************************************************************************/

+ partition_entry_t * get_partitions(const char *partname, partition_table_t *table)

+{

+    

+    partition_entry_t *entry = &table->table[0];

+    uint32_t entry_nums = table->entrys;

+    while( entry_nums-- )
+    {
+        if ( strcmp((const char *)entry->part_name,partname) == 0 )

+            return entry;
+        entry++;
+    }
+    return NULL;

+}

+

+/*******************************************************************************

+ * Function:set_nand_dlflag 

+ * Description: open or close USB DL PORT, based on nand

+ *                   dl on :open DL port ; dl off :close DL port

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *

+ *

+ * Others:

+ ********************************************************************************/

+ int set_nand_dlflag( char * sign)

+{   

+	char value = 0;

+	int bootflag = 0;

+	int times = 0;

+	int i =0;

+	int ret = 0;

+	struct erase_info ei;

+ 	nand_info_t *nand = &nand_info[nand_curr_device];

+	

+	u_char *buffer = kzalloc(6*(nand->writesize + nand->oobsize),GFP_KERNEL);

+	u_char *p_buffer = buffer;

+    

+	if( buffer == NULL )

+        return 1;

+	

+	times = 12*1024/nand->writesize;

+	for(i=0;i<times;i++)

+	{

+        nand_read_page_with_ecc(nand, 

+								((loff_t)i*nand->writesize), 

+								0,

+								p_buffer);

+		p_buffer += nand->writesize;

+	}

+

+    if (strcmp((const char *)sign,"on") == 0)

+	{

+        bootflag = 0x00;

+        memset(&value, bootflag, 1);

+	}

+    else if (strcmp((const char *)sign,"off") == 0)

+    {

+        bootflag = 0x5a;

+        memset(&value, bootflag, 1);

+    }

+	memcpy(buffer+2, &value, 1);

+	

+	memset(&ei, 0, sizeof(struct erase_info));

+	ei.mtd	= nand;

+	ei.addr = (uint64_t)(0);

+	ei.len	= (uint64_t)nand->erasesize;	

+	ret = nand->erase(nand, &ei);  /*²Á³ýµÚÒ»¿é*/

+

+	p_buffer = buffer;

+

+	for(i=0;i<times;i++)

+	{

+        nand_write_page_with_ecc(nand, ((loff_t)i*nand->writesize), p_buffer);

+		p_buffer += nand->writesize;

+	}

+

+    sprintf(tsp_console_buffer,"DL OKAY");

+    downloader_serial_write(tsp_console_buffer, strlen(tsp_console_buffer)+1);

+		

+	kfree(buffer);

+

+	return 0;

+

+}

+

+

+/*******************************************************************************

+ * Function:set_nor_dlflag 

+ * Description: open or close USB DL PORT, based on nand

+ *                   dl on :open DL port ; dl off :close DL port

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *

+ *

+ * Others:

+ ********************************************************************************/

+ int set_nor_dlflag(char *sign)

+{   

+	int ret = 0;

+	char value = 0;

+	int bootflag = 0;

+	uint32_t load_addr = 0x0;

+	uint32_t size_read = ZLOAD_PARTITION_SIZE;

+	uint32_t size_write = ZLOAD_PARTITION_SIZE;

+	struct fsl_qspi *nor = &spi_nor_flash;	

+	u_char *buffer = kzalloc(ZLOAD_PARTITION_SIZE,GFP_KERNEL);

+	

+	if(buffer == NULL)

+	{

+		return -1;

+	}

+        

+	ret = nand_read(&(nor->nor[0].mtd), load_addr, &size_read, buffer);

+	if(ret != 0)

+	{

+		printf("nand_read error.\n");

+		return -1;

+	}

+

+    if (strcmp((const char *)sign,"on") == 0)

+	{

+        bootflag = 0x00;

+        memset(&value, bootflag, 1);

+	}

+    else if (strcmp((const char *)sign,"off") == 0)

+    {

+        bootflag = 0x5a;

+        memset(&value, bootflag, 1);

+    }

+	memcpy(buffer+2, &value, 1);

+

+    ret = nand_erase(&(nor->nor[0].mtd), load_addr, nor->nor[0].mtd.erasesize);

+	if(ret != 0)

+	{

+		printf("nand_erase error.\n");

+		return -1;

+	}

+

+    ret = nand_write(&(nor->nor[0].mtd), load_addr, &size_write, buffer);

+	if(ret != 0)

+	{

+		printf("nand_write error.\n");

+		return -1;

+	}

+

+    sprintf(tsp_console_buffer,"DL OKAY");

+    downloader_serial_write(tsp_console_buffer, strlen(tsp_console_buffer)+1);

+		

+	kfree(buffer);

+

+	return 0;

+}

+

+

+/*******************************************************************************

+ * Function:do_dlflag

+ * Description: open or close USB DL PORT, 

+ *                   dl on :open DL port ; dl off :close DL port

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *

+ *

+ * Others:

+ ********************************************************************************/

+int do_dlflag(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])

+{   

+    int ret = 0;

+	u_char *sign = NULL;

+	int type = 0;

+ 	

+	if(argc<2)

+    {

+        return cmd_usage(cmdtp);

+    }

+	sign = argv[1];	

+	type = read_boot_flashtype();

+

+	if(type == IF_TYPE_NAND || type == IF_TYPE_SPI_NAND)

+	{

+        ret = set_nand_dlflag(sign);

+	}

+	else if(type == IF_TYPE_NOR)

+	{

+		ret = set_nor_dlflag(sign);

+	}

+

+	if(ret != 0)

+	{

+		return -1;

+	}

+		

+	return 0;

+

+}

+U_BOOT_CMD(

+	dl, CONFIG_SYS_MAXARGS, 0, do_dlflag,

+	"dl : dl [sign]",

+	""

+);

diff --git a/boot/common/src/uboot/downloader/cmd_testusb.c b/boot/common/src/uboot/downloader/cmd_testusb.c
new file mode 100644
index 0000000..921a66d5f1
--- /dev/null
+++ b/boot/common/src/uboot/downloader/cmd_testusb.c
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (C) 2016, ZIXC Corporation.
+ *
+ * File Name:cmd_testusb.c
+ * File Mark:
+ * Description:
+ * Others:
+ * Version:       1.0
+ * Author:        zangxiaofeng
+ * Date:          2013-4-22
+ * History 1:
+ *     Date:
+ *     Version:
+ *     Author:
+ *     Modification:
+ * History 2:
+  ********************************************************************************/
+
+
+/****************************************************************************
+* 	                                     Include files
+****************************************************************************/
+#include <common.h>
+#include <command.h>
+#include <net.h>
+#include <jffs2/load_kernel.h>
+#include "downloader_nand.h"
+#include "downloader_config.h"
+#include "errno.h"
+/****************************************************************************
+*							Global Function Prototypes
+****************************************************************************/
+extern int downloader_serial_write(const char * buffer,unsigned int len);
+extern int downloader_serial_read_actuallen(char * buffer,unsigned int len);
+
+/*******************************************************************************
+ * Function:do_reboot
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int do_testusb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+    unsigned int size = 0;
+    char ack[64] = {0};
+    
+    if(argc < 2)
+    {
+        return cmd_usage(cmdtp);
+    }
+    size = (unsigned int)simple_strtoul (argv[1], NULL, 16);
+
+    sprintf(ack,"DATA %x",size);
+    downloader_serial_write(ack, strlen(ack)+1);
+    downloader_serial_read_actuallen((char *)DOWNLOADER_BUFFER_BASE, size); 
+    sprintf(ack,"OKAY");
+    downloader_serial_write(ack, strlen(ack)+1);
+    return 0;
+}
+
+U_BOOT_CMD(
+	testusb, CONFIG_SYS_MAXARGS, 0, do_testusb,
+	"testusb: testusb [size]",
+	""
+);
+
diff --git a/boot/common/src/uboot/downloader/downloader_config.h b/boot/common/src/uboot/downloader/downloader_config.h
new file mode 100755
index 0000000..d9efe61
--- /dev/null
+++ b/boot/common/src/uboot/downloader/downloader_config.h
@@ -0,0 +1,14 @@
+#include "config.h"

+

+#define DOWNLOADER_BUFFER_BASE CONFIG_USB_DMA_BUF_ADDR

+

+#ifdef CONFIG_ZX297520V3T_64M_UBOOT

+#define DOWNLOADER_BUFFER_SIZE 0x3000000 /* 48M */

+#else

+#define DOWNLOADER_BUFFER_SIZE 0x1A00000 /*26M*/

+#endif

+

+//#define DOWNLOADER_BUFFER_SIZE (CONFIG_SYS_SDRAM_SIZE-0xA00000)

+//#define DOWNLOADER_BUFFER_SIZE 0x80000

+//#define CONFIG_LOAD_CRC

+

diff --git a/boot/common/src/uboot/downloader/downloader_nand.c b/boot/common/src/uboot/downloader/downloader_nand.c
new file mode 100644
index 0000000..d28cfbc
--- /dev/null
+++ b/boot/common/src/uboot/downloader/downloader_nand.c
@@ -0,0 +1,974 @@
+/*******************************************************************************

+ * Copyright (C) 2016, ZIXC Corporation.

+ *

+ * File Name:

+ * File Mark:

+ * Description:

+ * Others:

+ * Version:       1.0

+ * Author:        geanfeng

+ * Date:          2013-3-4

+ * History 1:

+ *     Date:

+ *     Version:

+ *     Author:

+ *     Modification:

+ * History 2:

+  ********************************************************************************/

+

+/****************************************************************************

+* 	                                     Include files

+****************************************************************************/

+#include "downloader_nand.h"

+#include <asm/errno.h>

+#include "partition_table.h"

+#include <linux/mtd/nor_spifc.h>

+

+

+/****************************************************************************

+* 	                                    Local Macros

+****************************************************************************/

+#define DATA_WITH_OOB	(1 << 0) /* whether write with oob data*/

+/****************************************************************************

+*							Local Types

+****************************************************************************/

+/****************************************************************************

+*							Global Variables

+****************************************************************************/

+extern partition_table_t * g_partition_table;

+extern partition_table_t * g_partition_table_dl;

+extern partition_entry_t * get_partitions(const char *partname, partition_table_t *table);

+

+/****************************************************************************

+*							Global Function Prototypes

+****************************************************************************/

+/****************************************************************************

+*							Function Definitions

+****************************************************************************/

+/*******************************************************************************

+ * Function:get_part_offset_skipbase

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *phyBase

+ *

+ * Others:

+ ********************************************************************************/

+static int  get_part_offset_skipbase(partition_entry_t * part, uint offset, uint * skipBase)

+{

+	nand_info_t * pNandInfo = NULL;

+	uint  offsetSkipBase = 0;

+	uint blockNum = 0;

+	int ret = 0;

+	

+	pNandInfo = &nand_info[nand_curr_device];

+	offsetSkipBase = part->part_offset;

+	assert((offset & (pNandInfo->erasesize - 1)) == 0);

+	assert((offsetSkipBase & (pNandInfo->erasesize - 1)) == 0);

+	if(offset != 0)

+		{

+			blockNum = offset /pNandInfo->erasesize;

+			while(blockNum > 0)

+				{

+					ret = nand_block_isbad (pNandInfo, offsetSkipBase);

+					offsetSkipBase += pNandInfo->erasesize;

+					if (ret)

+						{

+							continue;

+						}

+					else

+						{

+							blockNum--;

+						}					

+				}

+		}

+	*skipBase = offsetSkipBase;

+

+	return 0;

+}

+

+

+/*******************************************************************************

+ * Function:nand_read_skip_bad_compt

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *	NULL:error    else: success

+ *

+ * Others:

+ ********************************************************************************/

+int nand_read_skip_bad_compat(nand_info_t *nand, loff_t offset, size_t *length,

+			u_char *buffer, int flags)

+{

+	int rval = 0, blocksize;

+	size_t left_to_read = *length;

+	u_char *p_buffer = buffer;

+

+	if (flags & DATA_WITH_OOB) {

+		int pages;

+		pages = nand->erasesize / nand->writesize;

+		blocksize = (pages * nand->oobsize) + nand->erasesize;

+		if (*length % (nand->writesize + nand->oobsize)) {

+			printf ("Attempt to write incomplete page"

+				" in yaffs mode\n");

+			return -EINVAL;

+		}

+	} else

+	{

+		blocksize = nand->erasesize;

+	}

+

+	if ((offset & (nand->writesize - 1)) != 0) {

+		printf ("Attempt to write non page aligned data\n");

+		*length = 0;

+		return -EINVAL;

+	}	

+

+	while (left_to_read > 0) {

+		size_t block_offset = offset & (nand->erasesize - 1);

+		size_t read_size, truncated_read_size;

+

+		if (nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) {

+			printf ("Skip bad block 0x%08llx\n",

+				(u64)(offset & ~(nand->erasesize - 1)));

+			offset += nand->erasesize - block_offset;

+			continue;

+		}

+

+		if (left_to_read < (blocksize - block_offset))

+			read_size = left_to_read;

+		else

+			read_size = blocksize - block_offset;

+

+		if (flags & DATA_WITH_OOB) {

+			int page, pages;

+			size_t pagesize = nand->writesize;

+			size_t pagesize_oob = pagesize + nand->oobsize;

+			struct mtd_oob_ops ops;

+			memset(&ops, 0x0, sizeof(ops));

+

+			ops.len = pagesize;

+			ops.ooblen = nand->oobsize;

+			ops.mode = MTD_OOB_RAW;

+			ops.ooboffs = 0;

+

+			pages = read_size / pagesize_oob;

+			for (page = 0; page < pages; page++) {

+				ops.datbuf = p_buffer;

+				ops.oobbuf = ops.datbuf + pagesize;

+				rval = nand->read_oob(nand, offset, &ops);

+				if (rval)

+					break;

+

+				offset += pagesize;

+				p_buffer += pagesize_oob;

+			}

+		}

+		else

+		{

+			truncated_read_size = read_size;	

+			rval = nand_read(nand, offset, &truncated_read_size,

+					p_buffer);

+			offset += read_size;

+			p_buffer += read_size;

+		}

+

+		if (rval != 0) {

+			printf ("NAND read from offset %llx failed %d\n",

+				(u64)offset, rval);

+			*length -= left_to_read;

+			return rval;

+		}

+

+		left_to_read -= read_size;

+	}

+

+	return 0;

+}

+/*******************************************************************************

+ * Function:nand_read_skip_bad_compt

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *	NULL:error    else: success

+ *

+ * Others:

+ ********************************************************************************/

+int nand_write_skip_bad_compat(nand_info_t *nand, loff_t offset, size_t *length,

+			u_char *buffer, int flags)

+{

+	int rval = 0, blocksize;

+	size_t left_to_write = *length;

+	u_char *p_buffer = buffer;

+

+	if (flags & DATA_WITH_OOB) {

+		int pages;

+		pages = nand->erasesize / nand->writesize;

+		blocksize = (pages * nand->oobsize) + nand->erasesize;

+		if (*length % (nand->writesize + nand->oobsize)) {

+			printf ("Attempt to write incomplete page"

+				" in yaffs mode\n");

+			return -EINVAL;

+		}

+	} else

+	{

+		blocksize = nand->erasesize;

+	}

+

+	/*

+	 * nand_write() handles unaligned, partial page writes.

+	 *

+	 * We allow length to be unaligned, for convenience in

+	 * using the $filesize variable.

+	 *

+	 * However, starting at an unaligned offset makes the

+	 * semantics of bad block skipping ambiguous (really,

+	 * you should only start a block skipping access at a

+	 * partition boundary).  So don't try to handle that.

+	 */

+	if ((offset & (nand->writesize - 1)) != 0) {

+		printf ("Attempt to write non page aligned data\n");

+		*length = 0;

+		return -EINVAL;

+	}	

+

+	while (left_to_write > 0) {

+		size_t block_offset = offset & (nand->erasesize - 1);

+		size_t write_size, truncated_write_size;

+

+		if (nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) {

+			printf ("Skip bad block 0x%08llx\n",

+				(u64)(offset & ~(nand->erasesize - 1)));

+			offset += nand->erasesize - block_offset;

+			continue;

+		}

+

+		if (left_to_write < (blocksize - block_offset))

+			write_size = left_to_write;

+		else

+			write_size = blocksize - block_offset;

+

+		if (flags & DATA_WITH_OOB) {

+			int page, pages;

+			size_t pagesize = nand->writesize;

+			size_t pagesize_oob = pagesize + nand->oobsize;

+			struct mtd_oob_ops ops;

+

+			ops.len = pagesize;

+			ops.ooblen = nand->oobsize;

+			ops.mode = MTD_OOB_RAW;

+			ops.ooboffs = 0;

+

+			pages = write_size / pagesize_oob;

+			for (page = 0; page < pages; page++) {

+				ops.datbuf = p_buffer;

+				ops.oobbuf = ops.datbuf + pagesize;

+				//ops.oobbuf = NULL;

+				if(*(ops.datbuf + pagesize) != 0xFF || *(ops.datbuf + pagesize+1) != 0xFF) {

+					printf ("Fs image format error\n");

+					return  -EINVAL;

+					}

+				rval = nand->write_oob(nand, offset, &ops);

+

+

+				if (rval)

+					break;

+

+				offset += pagesize;

+				p_buffer += pagesize_oob;

+			}

+		}

+		else

+		{

+			truncated_write_size = write_size;	

+			rval = nand_write(nand, offset, &truncated_write_size,

+					p_buffer);

+			offset += write_size;

+			p_buffer += write_size;

+		}

+

+		if (rval != 0) {

+			printf ("NAND write to offset %llx failed %d\n",

+				(u64)offset, rval);

+			*length -= left_to_write;

+			return rval;

+		}

+

+		left_to_write -= write_size;

+	}

+

+	return 0;	

+}

+/*******************************************************************************

+ * Function:downloader_get_part

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *	NULL:error    else: success

+ *

+ * Others:

+ ********************************************************************************/

+partition_entry_t *  downloader_get_part(const char *partname)

+{

+	partition_entry_t *part;

+

+	part = find_partition_para((uchar *)partname);

+	if(part == NULL)

+		return NULL;

+

+	return part;	

+}

+/*******************************************************************************

+ * Function:downloader_get_part_dl

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *	NULL:error    else: success

+ *

+ * Others:

+ ********************************************************************************/

+partition_entry_t *  downloader_get_part_dl(const char *partname)

+{

+	partition_entry_t *part;

+

+	part = get_partitions((const char *)partname,g_partition_table_dl);

+	if(part == NULL)

+	{

+		return NULL;

+	}

+	printf("name=%s,part-name=%s,typt=%s\n",partname,part->part_name,part->part_type);

+

+	return part;	

+}

+/*******************************************************************************

+ * Function:downloader_get_part_actual_size

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *	NULL:error    else: success

+ *

+ * Others:

+ ********************************************************************************/

+u32 downloader_get_part_actual_size(partition_entry_t *part)

+{

+    nand_info_t * pNandInfo = NULL;

+	pNandInfo = &nand_info[nand_curr_device];

+	u32 bad_blk_cnt = 0;

+	u32 offset = part->part_offset;

+	while(offset < part->part_offset + part->part_size )

+	{

+		if (nand_block_isbad (pNandInfo, offset) ){

+			bad_blk_cnt  = bad_blk_cnt +1 ;

+			offset += pNandInfo->erasesize;

+				continue;

+			}

+		offset += pNandInfo->erasesize;

+	}

+	printf("downloader_get_part_actual_size:[%s] bad_blk_cnt = %d\n",part->part_name, bad_blk_cnt);

+	u32 part_actual_size = part->part_size -(bad_blk_cnt * pNandInfo->erasesize);

+	return part_actual_size;

+}

+

+/*******************************************************************************

+ * Function:downloader_nand_read

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *  0: success else:error

+ *

+ * Others:

+ ********************************************************************************/

+int 	downloader_nand_read(partition_entry_t * part, uint offset,  uint size,  unchar * buffer)

+{

+	nand_info_t * pNandInfo = NULL;

+	uint  nandPhyBase = 0;

+	int ret = 0;

+	

+	char ack[64] = {0};

+	if(part == NULL  || \

+		offset>part->part_size  || (size>downloader_get_part_actual_size(part)) || (offset+size) > part->part_size)

+		{

+		    printf(" [downloader_nand_read:][%s]bin_size > actual part_size \n", part->part_name);

+			sprintf(ack, " READ FAIL UNLEGAL SIZE ");

+			downloader_serial_write(ack, strlen(ack)+1);	

+			return -1;

+		}

+	pNandInfo = &nand_info[nand_curr_device];

+	get_part_offset_skipbase(part,offset,&nandPhyBase);

+

+    if( strcmp((const char *)part->part_name , "zloader") == 0 )

+    {   

+        /* ÕâÀﲻʹÓÃECC¶Áȡʱ£¬Òª¶ÁÈ¡OOB£¬¶øOOBµÃÊý¾Ý»á·ÅÈëdata->buf; 

+           ËùÒÔ´æ·ÅÊý¾ÝµÄbuf±ØÐëΪ (1 page + oob),²»ÄÜʹÓÃÉÏÃæ´«ÏÂÀ´µÄ

+           buffer,ÒòΪbufferµÄ´óСΪ²»°üº¬ oob µÄ´óС

+        */

+        u_char *buf = kzalloc(pNandInfo->writesize + pNandInfo->oobsize, GFP_KERNEL);

+        if( buf == NULL )

+        {

+			printf("downloader_nand_read kzalloc error\n");

+			return -1;

+		}

+                 

+        int times = size/pNandInfo->writesize;

+        int i = 0;

+        for(; i<times; i++)

+        {

+	        ret += nand_read_page_with_ecc(pNandInfo, 

+										   ((loff_t)i*pNandInfo->writesize),

+										   &size,

+										   (u_char*)buf );

+            memcpy((u_char*)buffer, buf ,pNandInfo->writesize);

+            buffer += pNandInfo->writesize;

+        }

+        kfree(buf);

+        

+    }

+        

+    else

+	    ret = nand_read_skip_bad(pNandInfo,\

+		        nandPhyBase+offset%(pNandInfo->erasesize),&size,(u_char*)buffer);

+	if(ret)

+		{

+			printf("downloader_nand_read error\n");

+			return -1;

+		}

+	return 0;

+}

+

+/*******************************************************************************

+ * Function:downloader_nand_write

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *  0: success else:error

+ *

+ * Others:

+ ********************************************************************************/

+int 	downloader_nand_write(partition_entry_t * part, uint offset,  uint size,  unchar * buffer)

+{

+	nand_info_t * pNandInfo = NULL;

+	uint  nandPhyBase = 0;

+	int ret = 0;

+    uchar * buf = buffer;

+	char ack[64] = {0};

+	if(part == NULL  || \

+		offset>part->part_size  || (size > downloader_get_part_actual_size(part)) || (offset+size) > part->part_size)

+		{

+		    printf("[downloader_nand_write:][%s] bin_size > actual part_size \n", part->part_name);

+			sprintf(ack, "WRITE FAIL UNLEGAL SIZE ");

+			downloader_serial_write(ack, strlen(ack)+1);	

+			return -1;

+		}

+	/*if(zftl_get_ZFTLrecord(part->part_offset))

+		{

+			printf("Function not allowed write zftl\n");

+			return -1;

+		}*/

+	pNandInfo = &nand_info[nand_curr_device];

+	get_part_offset_skipbase(part,offset,&nandPhyBase);

+	printf("entry nand_write\n");

+	

+    /* רÃÅдZ-LOADʱʹÓ㬲»Ê¹ÓÃECC*/

+    if( strcmp((const char *)part->part_name , "zloader") == 0 )

+    {   

+        if( size != 12*1024 )

+        {

+            printf("downloader_nand_write z-load size != 12k...\n");

+			return -1;

+        } 

+        int times = 12*1024/pNandInfo->writesize;

+        int i = 0;

+

+        for(; i<times; i++)

+        {

+            

+            ret += nand_write_page_with_ecc(pNandInfo, 

+											((loff_t)i*(pNandInfo->writesize)),

+											buf );

+            buf += pNandInfo->writesize;

+        }

+        

+    }

+        

+    else

+	    ret = nand_write_skip_bad(pNandInfo,\

+		        nandPhyBase+offset%(pNandInfo->erasesize),&size,(u_char*)buffer, 0);

+    printf("write skipbad finish, addr = %d,size = %d\n",nandPhyBase+offset%(pNandInfo->erasesize),size);

+	if(ret)

+		{

+			printf("downloader_nand_write error\n");

+			return -1;

+		}

+	return 0;

+}

+

+/*******************************************************************************

+ * Function:downloader_nand_fs_read

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *  0: success else:error

+ *

+ * Others:

+ ********************************************************************************/

+int 	downloader_nand_fs_read(partition_entry_t * part, uint offset,  uint size,  unchar * buffer)

+{

+	nand_info_t * pNandInfo = NULL;

+	uint  nandPhyBase = 0;

+	int ret = 0;

+	

+	char ack[64] = {0};

+	if(part == NULL || \

+		offset>part->part_size  || (size>downloader_get_part_actual_size(part)) || (offset+size) > part->part_size)

+		{

+		    printf("[downloader_nand_fs_read:][%s] bin_size > actual part_size \n", part->part_name);

+			sprintf(ack, " FS_READ FAIL UNLEGAL SIZE ");

+			downloader_serial_write(ack, strlen(ack)+1);	

+			return -1;

+		}

+	pNandInfo = &nand_info[nand_curr_device];

+	assert(pNandInfo!=NULL);

+	get_part_offset_skipbase(part,offset,&nandPhyBase);

+	ret = nand_read_skip_bad_compat(pNandInfo,nandPhyBase+offset%(pNandInfo->erasesize),&size,(u_char*)buffer,DATA_WITH_OOB);

+	if(ret)

+		{

+			printf("downloader_nand_fs_read error\n");

+			return -1;

+		}

+	return 0;

+}

+

+/*******************************************************************************

+ * Function:downloader_nand_fs_write

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *  0: success else:error

+ *

+ * Others:

+ ********************************************************************************/

+int 	downloader_nand_fs_write(partition_entry_t * part, uint offset,  uint size,  unchar * buffer)

+{

+	nand_info_t * pNandInfo = NULL;

+	uint  nandPhyBase = 0;

+	int ret = 0;

+	char ack[64] = {0};

+	if(part == NULL || \

+		offset>part->part_size  || (size>downloader_get_part_actual_size(part)) || (offset+size) > part->part_size)

+		{

+		    printf("[downloader_nand_fs_write:][%s] bin_size > actual part_size \n", part->part_name);

+			sprintf(ack, " FS_WRITE FAIL UNLEGAL SIZE ");

+			downloader_serial_write(ack, strlen(ack)+1);	

+			return -1;

+		}

+

+	pNandInfo = &nand_info[nand_curr_device];

+	assert(pNandInfo!=NULL);

+	get_part_offset_skipbase(part,offset,&nandPhyBase);

+	ret = nand_write_skip_bad_compat(pNandInfo,nandPhyBase+offset%(pNandInfo->erasesize),&size,(u_char*)buffer, DATA_WITH_OOB);

+	if(ret)

+		{

+			printf("downloader_nand_fs_write error\n");

+			return -1;

+		}

+	return 0;

+}

+/*******************************************************************************

+ * Function:downloader_nand_erase

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *  0: success else:error

+ *

+ * Others:

+ ********************************************************************************/

+int 	downloader_nand_erase(partition_entry_t * part, uint  partEraseSize)

+{

+	nand_info_t * pNandInfo = NULL;

+	int  ret = 0;

+	struct erase_info instr;

+	uint  size = 0;

+	

+	if(part == NULL )

+	{

+		return -1;

+	}

+

+	pNandInfo = &nand_info[nand_curr_device];

+	instr.mtd = pNandInfo;

+	instr.addr = part->part_offset;

+	assert( (instr.addr & (pNandInfo->erasesize - 1)) == 0);

+	instr.callback = 0;

+	//ret=nand_erase(pNandInfo, part->part_offset, part->part_size);

+	while(size < partEraseSize  &&  (instr.addr < (part->part_offset+part->part_size)))

+		{

+		if(nand_block_isbad (pNandInfo, instr.addr))

+			{

+				instr.addr += pNandInfo->erasesize;

+				continue ;

+			}

+		instr.len = pNandInfo->erasesize;

+		instr.state = 0;

+		ret = pNandInfo->erase(pNandInfo, &instr);

+		if(ret  && instr.state == MTD_ERASE_FAILED)

+			{

+				pNandInfo->block_markbad(pNandInfo,instr.addr);

+			}

+		else if (ret == 0)

+			{

+				size += pNandInfo->erasesize;

+			}

+		else

+			{

+				printf( "downloader nand: erase error\n");

+				return 1;

+			}

+		instr.addr += pNandInfo->erasesize;

+		}

+	

+	return ret;

+}

+/*******************************************************************************

+ * Function:downloader_nand_eraseall

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *  0: success else:error

+ *

+ * Others:

+ ********************************************************************************/

+int 	downloader_nand_eraseall(void)

+{

+	nand_info_t * pNandInfo = NULL;

+	struct erase_info instr;

+	int i = 0;

+	int  ret = 0;

+

+	for(i=0; i<CONFIG_SYS_MAX_NAND_DEVICE; i++)

+		{

+			pNandInfo = &nand_info[i];

+

+			instr.mtd = pNandInfo;

+			instr.addr = 0x00;

+			assert( (instr.addr & (pNandInfo->erasesize - 1)) == 0);

+			instr.callback = 0;

+			while(instr.addr < pNandInfo->size)

+				{

+				if(nand_block_isbad (pNandInfo, instr.addr))

+					{

+						instr.addr += pNandInfo->erasesize;

+						continue ;

+					}

+				instr.len = pNandInfo->erasesize;

+				instr.state = 0;

+				ret = pNandInfo->erase(pNandInfo, &instr);

+				if(ret && instr.state == MTD_ERASE_FAILED)

+					{

+						pNandInfo->block_markbad(pNandInfo,instr.addr);

+					}

+				instr.addr += pNandInfo->erasesize;

+				}

+		}

+	return ret;

+}

+/*******************************************************************************

+ * Function:downloader_nand_erase_auto

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *  0: success else:error

+ *

+ * Others:

+ ********************************************************************************/

+int 	downloader_nand_erase_auto(void)

+{

+	int  ret = 0;

+	partition_entry_t *entry = &g_partition_table->table[0];

+    uint32_t entry_nums = g_partition_table->entrys;

+	

+	while( entry_nums-- )

+    {

+        if ( strcmp((const char *)entry->part_name, "nvrofs") == 0 \

+			||strcmp((const char *)entry->part_name, "ddr") == 0 \

+			||strcmp((const char *)entry->part_name, "raw") == 0)

+        {

+            entry++;

+            continue;

+        }

+		ret = downloader_nand_erase(entry,entry->part_size);

+        entry++;

+    }

+	return ret;

+}

+

+extern struct fsl_qspi spi_nor_flash;

+

+

+/*******************************************************************************

+ * Function:downloader_nor_read

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *  0: success else:error

+ *

+ * Others:

+ ********************************************************************************/

+int downloader_nor_read(partition_entry_t * part, uint offset,  uint size,  unchar * buffer)

+{

+	int ret = 0;

+	char ack[64] = {0};

+	size_t read_size = size;

+	struct fsl_qspi *nor = NULL;

+	

+	if(part == NULL  

+	   ||offset>part->part_size  

+	   || (offset+size) > part->part_size)

+	{

+		    printf(" [downloader_nor_read:][%s]bin_size > actual part_size \n", part->part_name);

+			sprintf(ack, " READ FAIL UNLEGAL SIZE ");

+			downloader_serial_write(ack, strlen(ack)+1);	

+			return -1;

+	}

+	

+	nor = &spi_nor_flash;

+    ret = nand_read(&(nor->nor[0].mtd), part->part_offset + offset, &read_size, buffer);

+	if(ret)

+	{

+		printf("downloader_nor_read error\n");

+		return -1;

+	}

+	

+	return 0;

+}

+

+

+/*******************************************************************************

+ * Function:downloader_nor_write

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *  0: success else:error

+ *

+ * Others:

+ ********************************************************************************/

+

+int downloader_nor_write(partition_entry_t * part, uint offset,  uint size,  unchar * buffer)

+{

+	int ret = 0;

+     size_t write_size=0;

+	char ack[64] = {0};

+	struct fsl_qspi *nor = NULL;

+

+	write_size = size;

+	

+	if(part == NULL  

+	   || offset>part->part_size   

+	   || (offset+size) > part->part_size)

+	{

+		printf("[downloader_nor_write:][%s] bin_size > actual part_size \n", part->part_name);

+		sprintf(ack, "WRITE FAIL UNLEGAL SIZE ");

+		downloader_serial_write(ack, strlen(ack)+1);	

+		return -1;

+	}

+	

+	nor = &spi_nor_flash;

+	ret = nand_write(&(nor->nor[0].mtd), part->part_offset + offset, &write_size, buffer);

+	if(ret)

+	{

+		printf("downloader_nor_write error\n");

+		return ret;

+	}

+	

+	return 0;

+}

+

+/*******************************************************************************

+ * Function:downloader_nand_erase

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *  0: success else:error

+ *

+ * Others:

+ ********************************************************************************/

+int downloader_nor_erase(partition_entry_t * part, uint  partEraseSize)

+{

+	int  ret = 0;

+	struct fsl_qspi *nor = NULL;

+	

+	if(part == NULL)

+	{

+		return -1;

+	}

+

+	nor = &spi_nor_flash;

+	ret = nand_erase(&(nor->nor[0].mtd), part->part_offset, partEraseSize);

+	if(ret)

+	{

+		printf("downloader_nor_erase error\n");

+		return ret;

+	}

+	printf("downloader_nor_erase ok\n");

+	return 0;

+}

+/*******************************************************************************

+ * Function:downloader_nor_eraseall

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *  0: success else:error

+ *

+ * Others:

+ ********************************************************************************/

+int downloader_nor_eraseall(void)

+{

+	int  ret = 0;

+	struct fsl_qspi *nor = NULL;

+	

+	nor = &spi_nor_flash;

+	ret = nand_erase(&(nor->nor[0].mtd), 0x0, nor->nor[0].mtd.size);

+	if(ret)

+	{

+		printf("downloader_nor_eraseall error\n");

+		return ret;

+	}

+	printf("downloader_nor_eraseall ok\n");

+	return 0;

+

+}

+/*******************************************************************************

+ * Function:downloader_nor_erase_auto

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *  0: success else:error

+ *

+ * Others:

+ ********************************************************************************/

+int downloader_nor_erase_auto(void)

+{

+	int  ret = 0;

+	partition_entry_t *entry = &g_partition_table->table[0];

+    uint32_t entry_nums = g_partition_table->entrys;

+	

+	while(entry_nums--)

+    {

+        if ( strcmp((const char *)entry->part_name, "nvrofs") == 0 \

+			||strcmp((const char *)entry->part_name, "ddr") == 0 \

+			||strcmp((const char *)entry->part_name, "raw") == 0)

+        {

+            entry++;

+            continue;

+        }

+		ret = downloader_nor_erase(entry,entry->part_size);

+		if(ret)

+		{

+			printf("downloader_nor_erase_auto error\n");

+			return ret;

+		}

+        entry++;

+    }

+	printf("downloader_nor_erase_auto ok\n");

+	return 0;

+}

+

+int get_nor_null_slice_flag(unsigned int *flag)

+{

+	int ret = 0;

+	size_t read_size = 0x100;

+	unchar buffer[256];

+	struct fsl_qspi *nor = NULL;

+		

+	memset(buffer, 0xFF, 0x100);

+	

+	nor = &spi_nor_flash;

+    ret = nand_read(&(nor->nor[0].mtd), 0x0, &read_size, buffer);

+	if(ret)

+	{

+		printf("downloader_nor_read error\n");

+		return -1;

+	}

+

+	if(strncmp((const char *)(buffer+4), "ZX7521V1", 8) == 0)

+	{

+		*flag = 1;

+		printf("nor flash not null\n");

+	}

+	

+	return 0;

+}

+	

+

+

diff --git a/boot/common/src/uboot/downloader/downloader_nand.h b/boot/common/src/uboot/downloader/downloader_nand.h
new file mode 100644
index 0000000..ec638d4
--- /dev/null
+++ b/boot/common/src/uboot/downloader/downloader_nand.h
@@ -0,0 +1,231 @@
+/*******************************************************************************

+ * Copyright (C) 2016, ZIXC Corporation.

+ *

+ * File Name:    downloader_nand.h

+ * File Mark:    

+ * Description:  

+ * Others:        

+ * Version:       1.0

+ * Author:        geanfeng

+ * Date:          2013-03-04

+ * History 1:      

+ *     Date: 

+ *     Version:

+ *     Author: 

+ *     Modification:  

+ * History 2: 

+  ********************************************************************************/

+#ifndef _DOWNLOADER_NAND_H

+#define _DOWNLOADER_NAND_H

+/****************************************************************************

+* 	                        Include files

+****************************************************************************/

+#include <common.h>

+#include <linux/mtd/mtd.h>

+#include <command.h>

+#include <malloc.h>

+#include <nand.h>

+#include <jffs2/jffs2.h>

+#include <partition_table.h>

+/****************************************************************************

+* 	                         Macros

+****************************************************************************/

+

+/****************************************************************************

+* 	                         Types

+****************************************************************************/

+/****************************************************************************

+* 	                         Constants

+****************************************************************************/

+

+/****************************************************************************

+* 	                         Global  Variables

+****************************************************************************/

+

+/****************************************************************************

+* 	                         Function Prototypes

+****************************************************************************/

+

+/*******************************************************************************

+ * Function:downloader_get_part

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *

+ *

+ * Others:

+ ********************************************************************************/

+partition_entry_t *  downloader_get_part(const char *partname);

+/*******************************************************************************

+ * Function:downloader_get_part_dl

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *

+ *

+ * Others:

+ ********************************************************************************/

+

+partition_entry_t *  downloader_get_part_dl(const char *partname);

+/*******************************************************************************

+ * Function:downloader_nand_read

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *

+ *

+ * Others:

+ ********************************************************************************/

+int 	downloader_nand_read(partition_entry_t * part, uint offset,  uint size,  unchar * buffer);

+/*******************************************************************************

+ * Function:downloader_nand_write

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *

+ *

+ * Others:

+ ********************************************************************************/

+int 	downloader_nand_write(partition_entry_t * part, uint offset,  uint size,  unchar * buffer);

+/*******************************************************************************

+ * Function:downloader_zftl_read

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *

+ *

+ * Others:

+ ********************************************************************************/

+int 	downloader_zftl_read(partition_entry_t * part, uint offset,  uint size,  unchar * buffer);

+/*******************************************************************************

+ * Function:downloader_zftl_write

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *

+ *

+ * Others:

+ ********************************************************************************/

+int 	downloader_zftl_write(partition_entry_t * part, uint offset,  uint size,  unchar * buffer);

+/*******************************************************************************

+ * Function:downloader_nand_fs_read

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *

+ *

+ * Others:

+ ********************************************************************************/

+int 	downloader_nand_fs_read(partition_entry_t * part, uint offset,  uint size,  unchar * buffer);

+/*******************************************************************************

+ * Function:downloader_nand_fs_write

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *

+ *

+ * Others:

+ ********************************************************************************/

+int 	downloader_nand_fs_write(partition_entry_t * part, uint offset,  uint size,  unchar * buffer);

+/*******************************************************************************

+ * Function:downloader_nand_erase

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *

+ *

+ * Others:

+ ********************************************************************************/

+int 	downloader_nand_erase(partition_entry_t * part, uint  partEraseSize);

+/*******************************************************************************

+ * Function:downloader_nand_eraseall

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *

+ *

+ * Others:

+ ********************************************************************************/

+int 	downloader_nand_eraseall(void);

+

+/*******************************************************************************

+ * Function:downloader_nand_auto

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *

+ *

+ * Others:

+ ********************************************************************************/

+int 	downloader_nand_erase_auto(void);

+

+int do_nand_read(partition_entry_t *part, char *par , unsigned int offset, unsigned int size );

+

+int do_raw_read(unsigned int offset, unsigned int size);

+

+int  do_ram_read(unsigned int offset, unsigned int size);

+

+int do_zftl_read(partition_entry_t *part, char *par , unsigned int offset, unsigned int size);

+

+int do_yaffs_read(partition_entry_t *part, char *par , unsigned int offset, unsigned int size);

+

+int do_mmc_read(partition_entry_t *part, char *par , unsigned int offset,unsigned int size );

+

+int do_nand_write(partition_entry_t *part, char *par , unsigned int offset, unsigned int size );

+

+int do_raw_write(unsigned int offset, unsigned int size);

+

+int do_yaffs_write(partition_entry_t *part, char *par , unsigned int offset, unsigned int size );

+

+int do_zftl_write(partition_entry_t *part, char *par , unsigned int offset, unsigned int size);

+

+int do_ram_write( unsigned int offset, unsigned int size);

+

+int do_mmc_write(partition_entry_t *part, char *par , unsigned int offset,unsigned int size );

+

+#endif

+

diff --git a/boot/common/src/uboot/downloader/downloader_serial.c b/boot/common/src/uboot/downloader/downloader_serial.c
new file mode 100755
index 0000000..2d05568
--- /dev/null
+++ b/boot/common/src/uboot/downloader/downloader_serial.c
@@ -0,0 +1,215 @@
+/*******************************************************************************
+ * Copyright (C) 2016, ZIXC Corporation.
+ *
+ * File Name:
+ * File Mark:
+ * Description:
+ * Others:
+ * Version:       1.0
+ * Author:        geanfeng
+ * Date:          2013-3-4
+ * History 1:
+ *     Date:
+ *     Version:
+ *     Author:
+ *     Modification:
+ * History 2:
+  ********************************************************************************/
+
+/****************************************************************************
+* 	                                           Include files
+****************************************************************************/
+#include <linux/types.h>
+#include <usb/common.h>
+#include <command.h>
+#include <common.h>
+#include <net.h>
+#include <usb/usb_config.h>
+/****************************************************************************
+* 	                                           Local Macros
+****************************************************************************/
+/****************************************************************************
+*							Local Types
+****************************************************************************/
+
+/****************************************************************************
+*							Global Variables
+****************************************************************************/
+int  dl_serial_initial = 0;
+/****************************************************************************
+*							Global Function Prototypes
+****************************************************************************/
+extern int tsp_usb_init(void);
+extern WORD32 usb_read(WORD32 dwLen, BYTE *pchBuf);
+
+
+extern WORD32 usb_write(WORD32 dwLen, BYTE *pchBuf);
+
+extern int UART_Read(char *pchBuf, int dwLen);
+extern int UART_Write(char *pchBuf, int dwLen);
+/****************************************************************************
+*							Function Definitions
+****************************************************************************/
+
+/*******************************************************************************
+ * Function:downloader_serial_init
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+void downloader_serial_init(void)
+{
+#if CONFIG_USB_DL
+     usb_boot(SYS_USB_BASE); 	/*usb*/
+#endif
+	 dl_serial_initial =1;	
+}
+/*******************************************************************************
+ * Function:downloader_serial_read
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+ unsigned int g_testLen = 0;
+unsigned int g_testAddr = 0;
+unsigned int g_testFlag1 = 0;
+int downloader_serial_read(char * buffer,unsigned int len)
+{
+	int ret = 0;
+
+	if(!dl_serial_initial)
+		return 0;
+ 	g_testAddr = (unsigned int)&len;
+#if CONFIG_USB_DL
+	ret = usb_read(len,buffer);
+#else
+	ret = UART_Read(buffer,len);
+#endif
+    g_testLen = len;
+    g_testFlag1 = 1;
+ 	if(!ret)
+		{
+			return 0; /*error return 0*/
+		}
+	else
+		{
+            
+			return ret;/*actual length*/
+		}
+}
+/*******************************************************************************
+ * Function:downloader_serial_read_actuallen
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int downloader_serial_read_actuallen(char * buffer,unsigned int len)
+{
+	char* pBuffer = buffer;
+	uint  readLength = 0;
+	uint  length = 0;
+	//printf("start to rececive len = %d \n",len);
+#if CONFIG_USB_DL
+	while(readLength < len)
+		{
+			length = downloader_serial_read(pBuffer,512);
+            //printf(" receiving len = %d \n",length);
+			if(length)
+				{
+					readLength += length;
+                    //printf(" readLength = %d \n",readLength);
+					pBuffer += length;
+				}
+			else
+				{
+					continue;
+				}
+		}
+    //printf("finish receiving len = %d \n",len);
+#else
+
+    length = downloader_serial_read(pBuffer,len);
+#endif
+	return 0;
+}
+
+/*******************************************************************************
+ * Function:downloader_serial_write
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int downloader_serial_write(const char * buffer,unsigned int len)
+{
+	if(!dl_serial_initial)
+		return 0;
+	
+#if CONFIG_USB_DL
+	return usb_write(len,(char *)buffer);
+#else
+	return UART_Write((char *)buffer,len);
+#endif
+}
+/*******************************************************************************
+ * Function:downloader_serial_write_actuallen
+ * Description:
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int downloader_serial_write_actuallen(const char * buffer,unsigned int len)
+{
+	const char* pBuffer = buffer;
+	uint  writeLength = 0;
+	uint  length = 0;
+    
+	/*need modify*/
+	while(writeLength < len)
+		{
+            
+            length = MIN(len-writeLength,136192);
+            //printf("prepare to write len=%d\n",length);
+			downloader_serial_write(pBuffer,length);
+            //printf("this time usb write len=%d\n",length);
+			writeLength += length;
+			//printf("usb have writen len=%d\n",writeLength);
+			
+			pBuffer += length;
+		}
+	return 0;
+}
+
diff --git a/boot/common/src/uboot/downloader/downloader_serial.h b/boot/common/src/uboot/downloader/downloader_serial.h
new file mode 100644
index 0000000..2360101
--- /dev/null
+++ b/boot/common/src/uboot/downloader/downloader_serial.h
@@ -0,0 +1,99 @@
+/*******************************************************************************

+ * Copyright (C) 2016, ZIXC Corporation.

+ *

+ * File Name:    downloader_serial.h

+ * File Mark:    

+ * Description:  

+ * Others:        

+ * Version:       1.0

+ * Author:        geanfeng

+ * Date:          2013-03-04

+ * History 1:      

+ *     Date: 

+ *     Version:

+ *     Author: 

+ *     Modification:  

+ * History 2: 

+  ********************************************************************************/

+#ifndef _DOWNLOADER_SERIAL_H

+#define _DOWNLOADER_SERIAL_H

+/****************************************************************************

+* 	                        Include files

+****************************************************************************/

+

+/****************************************************************************

+* 	                         Macros

+****************************************************************************/

+

+/****************************************************************************

+* 	                         Types

+****************************************************************************/

+/****************************************************************************

+* 	                         Constants

+****************************************************************************/

+

+/****************************************************************************

+* 	                         Global  Variables

+****************************************************************************/

+

+/****************************************************************************

+* 	                         Function Prototypes

+****************************************************************************/

+

+/*******************************************************************************

+ * Function:downloader_serial_read

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *

+ *

+ * Others:

+ ********************************************************************************/

+int downloader_serial_read(char * buffer,unsigned int len);

+/*******************************************************************************

+ * Function:downloader_serial_read_actuallen

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *

+ *

+ * Others:

+ ********************************************************************************/

+int downloader_serial_read_actuallen(char * buffer,unsigned int len);

+/*******************************************************************************

+ * Function:downloader_serial_write

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *

+ *

+ * Others:

+ ********************************************************************************/

+int downloader_serial_write(const char * buffer,unsigned int len);

+/*******************************************************************************

+ * Function:downloader_serial_write_actuallen

+ * Description:

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *

+ *

+ * Others:

+ ********************************************************************************/

+int downloader_serial_write_actuallen(const char * buffer,unsigned int len);

+#endif