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

Change-Id: Ic6e05d89ecd62fc34f82b23dcf306c93764aec4b
diff --git a/boot/common/src/loader/lib/Makefile b/boot/common/src/loader/lib/Makefile
new file mode 100644
index 0000000..81e5713
--- /dev/null
+++ b/boot/common/src/loader/lib/Makefile
@@ -0,0 +1,45 @@
+#
+# (C) Copyright 2004 Texas Instruments
+#
+# (C) Copyright 2002
+# 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
+
+LIB	= lib$(ARCH).a
+
+AOBJS	=
+
+#ifeq ($(strip $(board)),$(filter $(board),evb mdl cpe fwp mifi phone watch))
+COBJS	= board.o string.o
+#endif	
+
+OBJS	= $(AOBJS) $(COBJS)
+
+$(LIB):	.depend $(OBJS)
+	$(AR) crv $@ $(OBJS)
+
+#########################################################################
+
+sinclude .depend
+
+#########################################################################
diff --git a/boot/common/src/loader/lib/board.c b/boot/common/src/loader/lib/board.c
new file mode 100755
index 0000000..3d138a9
--- /dev/null
+++ b/boot/common/src/loader/lib/board.c
@@ -0,0 +1,435 @@
+/*
+ * Copyright (C) 2016 ZXIC Inc.
+ *
+ */
+#include <common.h>
+#include <version.h>
+#include <asm/io.h>
+#include <asm/string.h>
+#include <asm/arch/cpu.h>
+#include <image.h>
+#include <linux/byteorder/generic.h>
+#include <load_mode.h>
+#include <asm/arch/top_clock.h>
+#include <asm/arch/uart.h>
+
+#include "config.h"
+#include "ddr.h"
+#include "../drivers/efuse.h"
+#include "../drivers/flash.h"
+
+#define FLAGS_PARTITION_ERROR (0x1111) /*·ÖÇøÒì³£*/
+
+typedef short (init_fnc_t) (void);
+
+int print_info(void)
+{
+#if defined(CFG_ZLOAD)
+	printf ("\nInc zloader 1.3.4\n");
+#else
+	printf ("\nInc tLoader 1.3.4\n");
+#endif
+	return 0;
+}
+
+void copy_to_iram1(void) 
+{
+	memcpy(0x100000, 0x8a000, 0x2000);	/* TEXT_BASE=0x100000 */
+	writel(CFG_START_STAGE1_STATE, CFG_START_STAGE1_ADDR);
+}
+
+/*
+ ******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others: IRAM addr is provided from ap
+ *******************************************************************************
+ */
+void clear_iram( void )
+{
+	uint32_t i = 0;
+
+	for( i=0x82000400; i<=0x82003400; i+=4 )    
+	{
+		writel(0x0, i);
+	}
+}
+
+/*
+ ******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ *******************************************************************************
+ */
+ void write_loader_mode(uint32_t mode)
+{
+	writel(mode, CFG_BOOT_MODE_SAVE_ADDR_FOR_UBOOT);  
+}
+
+void hang (void)
+{
+	/* call board specific hang function */
+	for (;;);
+}
+
+/*******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+void usb_apcore_poweroff(void)
+{
+	u32 tmp;
+
+	tmp =readl(USB_RESET); /*usb hsic reset*/
+	tmp	&= ~0x7;
+	writel(tmp, USB_RESET);
+	
+	tmp =readl(CORE_OUTPUT_SWITCH_CONFIG_REG);/*ap clk&mg control by sw*/
+	tmp &= ~((0x1<<2)|(0x1<<5));
+	writel(tmp, CORE_OUTPUT_SWITCH_CONFIG_REG);
+	
+	tmp =readl(CORE_OUTPUT_SW_CONFIG_REG1);/*ap clk off*/
+	tmp &= ~(0x1<<2);
+	writel(tmp, CORE_OUTPUT_SW_CONFIG_REG1);	
+	
+	tmp =readl(CORE_OUTPUT_SW_CONFIG_REG2);/*ap mg iso*/
+	tmp |= (0x1<<5);
+	writel(tmp, CORE_OUTPUT_SW_CONFIG_REG2);
+	
+	usdelay(1);
+
+	tmp =readl(CORE_OUTPUT_SW_CONFIG_REG2);/*ap mg rst*/
+	tmp |= (0x1<<4);
+	writel(tmp, CORE_OUTPUT_SW_CONFIG_REG2);
+	
+	usdelay(1);
+
+	tmp =readl(CORE_OUTPUT_SW_CONFIG_REG2);/*ap mg off*/
+	tmp &= ~(0x1<<3);
+	writel(tmp, CORE_OUTPUT_SW_CONFIG_REG2);	
+	
+	//__REG(0x0013a0ac) &= ~((0x1<<2)|(0x1<<5));    /*ap clk&mg control by sw*/
+	//__REG(0x0013a0b8)       &= ~(0x1<<2);               /*ap clk off*/
+	//__REG(0x0013a0bc)       |= (0x1<<5);               /*ap mg iso*/
+	//__REG(0x0013a0bc)       |= (0x1<<4);               /*ap mg rst*/
+	//__REG(0x0013a0bc)       &= ~(0x1<<3);              /*ap mg off*/	
+}
+
+//#ifdef CONFIG_ZX297520V3E_MDL_AB
+#if defined(CONFIG_ZX297520V3E_MDL_AB) || defined(CONFIG_ZX297520V3E_VEHICLE_DC)
+void start_armboot (void)
+{
+	int32_t ret = 0;
+	int32_t add;
+	uint32_t amt_value = 0;
+	int32_t err_flag = 0;
+    T_BOOT_TARGET bootTarget;
+	T_BOOT_FOTA_FLAG flagsData;
+	T_BOOT_FOTA_FLAG *fotaFlag;
+	T_FOTA_FLAG_INFO *fotaFlagInfo;
+	T_BOOT_DUALSYSTEM_TYPE dualSystemType;
+
+	clk_init();
+	timer_init();
+#if CFG_PRINTF
+	uart_init();
+#endif
+	print_info();
+
+	/* After reset, Copy zloader forcely. */
+	/* Now IRAM1 maybe occupied by dirty data. */
+	writel(0, CFG_START_STAGE1_ADDR);
+	amt_value = readl(CFG_AMT_MODE_SWITCH_ADDR);
+	clear_iram();
+	writel(amt_value, CFG_AMT_MODE_SWITCH_ADDR);
+
+	ret = board_flash_init();
+	if(ret != 0)
+	{
+		goto error;
+	}	
+		
+	efuse_init();
+
+	if(get_ddr_flag() == CHIP_DDR_IS_32M)
+	{
+		ddr_init(CHIP_DDR_IS_32M);
+	}
+	else if(get_ddr_flag() == CHIP_DDR_IS_64M)
+	{
+		ddr_init(CHIP_DDR_IS_64M);
+	}
+	else if(get_ddr_flag() == CHIP_DDR_IS_128M)
+	{
+		ddr_init(CHIP_DDR_IS_128M);		
+	}	
+	else
+	{
+		ddr_init(CHIP_DDR_IS_256M);
+	}
+	
+	usb_apcore_poweroff();
+/********************* ÔËÐÐT-LOAD,½øÈëÏÂÔØÄ£Ê½ ******************/
+#if defined(CFG_TLOAD)
+	write_loader_mode(CFG_TLOAD_MODE);
+
+#if CFG_USB
+	usb_boot(SYS_USB_BASE);
+#endif
+
+#if CFG_UART
+	uart_boot();
+#endif
+    
+#endif	/* CFG_TLOAD */
+
+/********************* ÔËÐÐZ-LOAD,½øÈëÕý³£Æô¶¯Ä£Ê½ **********/
+#if defined(CFG_ZLOAD)
+	uint32_t uboot_entry_point = 0;
+	char boot_mode = 0;
+
+	write_loader_mode(CFG_ZLOAD_MODE);
+
+	/*read flags·ÖÇø*/
+	ret = read_flags_image((uint8_t *)FLAGS_IMAGE);
+
+	if( ret != 0 )
+	{
+		printf("read flags partition error! Use default parameters\n");
+		//goto error;
+		err_flag = 1;
+		
+		/*ĬÈÏflags·ÖÇøÊý¾Ý*/
+		flagsData.magic = FLAGS_MAGIC;
+		flagsData.boot_to = DUAL_SYSTEM;
+		flagsData.fota_status = 1;
+		flagsData.system.status = DUALSYSTEM_STATUS_BOOTABLE;
+		flagsData.system2.status = DUALSYSTEM_STATUS_BOOTABLE;
+		fotaFlag = &flagsData;
+	}
+	else
+	{
+        fotaFlag = (T_BOOT_FOTA_FLAG *)(CFG_TEMP_ADDR);
+	}
+
+	bootTarget = fotaFlag->boot_to;
+
+	writel(DUALSYSTEM_STATUS_BOOTABLE, BOOT_FLAG_ADDR);/*ĬÈÏ¿ÉÆô¶¯*/
+	
+    if(bootTarget == DUAL_SYSTEM)
+    {
+        if (fotaFlag->system.status == DUALSYSTEM_STATUS_UNBOOTABLE)
+        {
+            printf("dual_system status is unbootable!");
+		    goto error;
+		}
+		ret = read_uboot_image((uint8_t *)UBOOT_IMAGE, &uboot_entry_point);    
+		if( ret != 0)
+        {
+            printf("read uboot1 image error, goto uboot2!");
+			writel(DUALSYSTEM_STATUS_UNBOOTABLE, BOOT_FLAG_ADDR);		
+			ret = read_uboot_image((uint8_t *)UBOOT2_IMAGE, &uboot_entry_point);		
+			if( ret != 0)
+	        {
+	            printf("read uboot2 iamge error!");
+				goto error;	
+			}
+		}
+		else	
+		    printf("goto uboot!");
+	}
+    else if(bootTarget == DUAL_SYSTEM2)
+    {
+        if (fotaFlag->system2.status == DUALSYSTEM_STATUS_UNBOOTABLE)
+        {
+            printf("dual_system2 status is unbootable!");
+		    goto error;
+		}
+		ret = read_uboot_image((uint8_t *)UBOOT2_IMAGE, &uboot_entry_point);		
+		if( ret != 0)
+        {
+            printf("read uboot2 iamge error, goto uboot!");
+			writel(DUALSYSTEM_STATUS_UNBOOTABLE, BOOT_FLAG_ADDR);	
+			ret = read_uboot_image((uint8_t *)UBOOT_IMAGE, &uboot_entry_point);		
+			if( ret != 0)
+	        {
+	            printf("read uboot iamge error!");
+				goto error;	
+			}
+		}
+		else
+		    printf("goto uboot2!");
+	}
+	else
+	{
+		printf("boot target get error!");
+		goto error;
+	}
+
+	if(err_flag == 1)
+	{
+        writel(FLAGS_PARTITION_ERROR, BOOT_FLAG_ADDR);
+	}
+	
+	printf("read uboot ok.\n");
+	
+	/* set arm jump PC start code  */
+	writel(0xE59ff000, SYS_IRAM1_BASE);			
+	writel(uboot_entry_point, SYS_IRAM1_BASE + 8);
+
+	printf("start uboot...\n");
+	/* Relese A9 Core, A9 start to run uboot right now. */
+	writel(CPU_UFI_SW_RSTEN, CPU_A9_SUBSYS_CFG);	
+
+
+	/* waiting for uboot read m0 image. */
+	uint32_t m0_entry_point = 0;
+	ret = nand_read_m0(&m0_entry_point);
+	if(ret != 0)
+	{
+		goto error;
+	}
+
+	/* M0 Core start to run cpurpm right now. */
+	((init_fnc_t *)m0_entry_point)();
+	
+#endif
+
+error:
+	printf("ERR\n");
+	hang();
+}
+#else
+void start_armboot (void)
+{
+	int32_t ret = 0;
+	uint32_t amt_value = 0;
+
+
+	clk_init();
+	timer_init();
+#if CFG_PRINTF
+	uart_init();
+#endif
+	print_info();
+
+	/* After reset, Copy zloader forcely. */
+	/* Now IRAM1 maybe occupied by dirty data. */
+	writel(0, CFG_START_STAGE1_ADDR);
+	amt_value = readl(CFG_AMT_MODE_SWITCH_ADDR);
+	clear_iram();
+	writel(amt_value, CFG_AMT_MODE_SWITCH_ADDR);
+
+	ret = board_flash_init();
+	if(ret != 0)
+	{
+		goto error;
+	}	
+		
+	efuse_init();
+
+	if(get_ddr_flag() == CHIP_DDR_IS_32M)
+	{
+		ddr_init(CHIP_DDR_IS_32M);
+	}
+	else if(get_ddr_flag() == CHIP_DDR_IS_64M)
+	{
+		ddr_init(CHIP_DDR_IS_64M);
+	}
+	else if(get_ddr_flag() == CHIP_DDR_IS_128M)
+	{
+		ddr_init(CHIP_DDR_IS_128M);		
+	}	
+	else
+	{
+		ddr_init(CHIP_DDR_IS_256M);
+	}
+	
+	
+	usb_apcore_poweroff();
+/********************* ÔËÐÐT-LOAD,½øÈëÏÂÔØÄ£Ê½ ******************/
+#if defined(CFG_TLOAD)
+	write_loader_mode(CFG_TLOAD_MODE);
+
+#if CFG_USB
+	usb_boot(SYS_USB_BASE);
+#endif
+
+#if CFG_UART
+	uart_boot();
+#endif
+    
+#endif	/* CFG_TLOAD */
+
+/********************* ÔËÐÐZ-LOAD,½øÈëÕý³£Æô¶¯Ä£Ê½ **********/
+#if defined(CFG_ZLOAD)
+	uint32_t uboot_entry_point = 0;
+	char boot_mode = 0;
+
+	write_loader_mode(CFG_ZLOAD_MODE);
+
+	ret = read_uboot_image((uint8_t *)UBOOT_IMAGE, &uboot_entry_point);
+	if( ret != 0 )
+	{
+		boot_mode = get_boot_mode();
+		if((boot_mode == SPI_NAND_BOOT) || (boot_mode == NAND_BOOT))
+		{
+			ret = read_uboot_image((uint8_t *)UBOOT_MIRROR_IMAGE, 
+									&uboot_entry_point);
+			if(ret != 0)
+			{
+				goto error;
+			}
+		}
+		else
+		{
+			goto error;
+		}
+	}
+	printf("read uboot ok.\n");
+	
+	/* set arm jump PC start code  */
+	writel(0xE59ff000, SYS_IRAM1_BASE);			
+	writel(uboot_entry_point, SYS_IRAM1_BASE + 8);
+
+	printf("start uboot...\n");
+	/* Relese A9 Core, A9 start to run uboot right now. */
+	writel(CPU_UFI_SW_RSTEN, CPU_A9_SUBSYS_CFG);	
+
+
+	/* waiting for uboot read m0 image. */
+	uint32_t m0_entry_point = 0;
+	ret = nand_read_m0(&m0_entry_point);
+	if(ret != 0)
+	{
+		goto error;
+	}
+
+	/* M0 Core start to run cpurpm right now. */
+	((init_fnc_t *)m0_entry_point)();
+	
+#endif
+
+error:
+	printf("ERR\n");
+	hang();
+}
+#endif
diff --git a/boot/common/src/loader/lib/config.h b/boot/common/src/loader/lib/config.h
new file mode 100644
index 0000000..4f14b4b
--- /dev/null
+++ b/boot/common/src/loader/lib/config.h
@@ -0,0 +1,93 @@
+/*******************************************************************************

+* °æÈ¨ËùÓÐ (C)2010, ÉîÛÚÊÐÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£

+*

+* ÎļþÃû³Æ£º config.h

+* Îļþ±êʶ£º /include/config.h

+* ÄÚÈÝÕªÒª£º ÒýÈ뿪·¢°åµÄÅäÖÃÎļþ

+* ÆäËü˵Ã÷£º

+* µ±Ç°°æ±¾£º 1.0

+* ×÷¡¡¡¡Õߣº ÎÌÔÆ·å

+* Íê³ÉÈÕÆÚ£º 2010-9-30

+*

+*

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

+#ifndef __INCLUDE_CONFIG_H_

+#define __INCLUDE_CONFIG_H_

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

+1:open 0:close

+* ¹¦ÄÜ             SIM_EN     USE_ASIC    SYNC_USB_CTRL    SYNC_USB_HSIC   SYNC_SETADDRESS

+*  FPGA                   1               0                    0                          0                              0                  

+*  usb_ctrlÑéÖ¤    0               1                    1                          1                              1

+*  usb_hsicÑéÖ¤   0               1                    1                          1                              1

+*  usbtimeoutÑéÖ¤0               1                    1                          1                              1

+*  asic                     1               1                    0                          0                              0

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

+#define SIM_EN 1

+#define USE_ASIC 1

+#define SYNC_USB_CTRL 0

+#define SYNC_USB_HSIC 0

+#define SYNC_SETADDRESS 0

+

+#if  !USE_ASIC   ///0:fpga   1:asic

+// CPUʱÖÓÆµÂÊ

+#define SYS_CPU_FREQ							50000000		// ¶¨ÒåCPUʱÖÓ,ÓÃÓÚ¼ÆÊ±

+#define SYS_UART_CLK							25000000		// ʱÖÓÆµÂÊ

+#define SYS_UART_CLK_CONFIG_PLL				25000000		// ʱÖÓÆµÂÊ

+#else

+// CPUʱÖÓÆµÂÊ

+#define SYS_CPU_FREQ							208000000		// ¶¨ÒåCPUʱÖÓ,ÓÃÓÚ¼ÆÊ±

+#define SYS_UART_CLK							(26000000/6)		// ʱÖÓÆµÂÊ

+#define SYS_UART_CLK_CONFIG_PLL				104000000		// ʱÖÓÆµÂÊ

+#endif

+// Æô¶¯Ä£Ê½Ñ¡Ôñ¼Ä´æÆ÷

+#define SYS_BOOTSEL_BASE						0x0013b004		// ¶¨ÒåBOOTSEL¼Ä´æÆ÷µØÖ·

+

+#define SOC_CRM_BASE            (0x0010c000)

+#define BOOT_SEL                (0x3c)

+#define NAND_CFG                (0x34)

+//#define SOC_MOD_CLKEN0         (0x0010c00c)

+//#define SOC_MOD_CLKEN1         (0x0010c010)

+//#define SOC_MOD_RSTEN          (0x0010c018)

+#define SOC_MOD_USBSTATECTRL  (0x0013B084)

+#define SOC_MOD_RSTEN1          (0x0010c064)

+

+#define CFG_STACK_TOP							0x0008AFE0		// ¶¨ÒåÁËÕ»¶¥

+

+// UART ²ÎÊý

+#define SYS_UART_BASE							0x00102000		// »ùµØÖ·

+//#define SYS_UART_CLK							25000000		// ʱÖÓÆµÂÊ

+#define CFG_UART_BAUDRATE						115200			// ²¨ÌØÂÊ

+#define CFG_BUF_SIZE							64				// Êý¾Ý»º³åÇø´óС

+#if !USE_ASIC

+// USB ²ÎÊý

+#define SYS_USB_BASE							0x01500000		// »ùµØÖ·

+#define SYS_USB_HSIC_BASE						0x01500000		// »ùµØÖ·

+#else

+#define SYS_USB_BASE							0x01500000		// »ùµØÖ·

+#define SYS_USB_HSIC_BASE						0x01500000		// »ùµØÖ·

+#endif

+

+

+// NAND FLASH ²ÎÊý

+#define SYS_NAND_BASE                   	 	0x01207000		// ¼Ä´æÆ÷»ùµØÖ·

+#define SYS_NAND_DATA                    		0x01208000		// Êý¾Ý»ùµØÖ·

+

+// ͨÓòÎÊý

+#define CFG_LOAD_BASE                    		0x0008B000      // ¼ÓÔØ´úÂëµ½¸ÃµØÖ·,±ØÐë4K¶ÔÆë

+#define SYS_LOAD_LEN                     		0x1000          // ¼ÓÔØ³¤¶È

+#define CFG_PRINT_BUF_SIZE						256

+

+//#define POWER_DOMAIN_ISO                      (0x0010d200+0x41*4)

+//#define POWER_DOMAIN_POWERON                  (0x0010d200+0x42*4)

+//#define POWER_DOMAIN_RST                      (0x0010d200+0x40*4)

+

+//ÑéÖ¤ÐèÒª

+#if SYNC_USB_CTRL

+#define ARM_PORTA				(0x102040)

+#endif

+

+#if SYNC_USB_HSIC

+#define REG_GPIO_OUT  0x01400014     

+#define REG_GPIO_IN   0x01409020  

+#endif

+#endif

diff --git a/boot/common/src/loader/lib/string.c b/boot/common/src/loader/lib/string.c
new file mode 100644
index 0000000..aed8b92
--- /dev/null
+++ b/boot/common/src/loader/lib/string.c
@@ -0,0 +1,120 @@
+/*
+ *  linux/lib/string.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+/*
+ * stupid library routines.. The optimized versions should generally be found
+ * as inline code in <asm-xx/string.h>
+ *
+ * These are buggy as well..
+ *
+ * * Fri Jun 25 1999, Ingo Oeser <ioe@informatik.tu-chemnitz.de>
+ * -  Added strsep() which will replace strtok() soon (because strsep() is
+ *    reentrant and should be faster). Use only strsep() in new code, please.
+ */
+
+#include <linux/types.h>
+#include <asm/string.h>
+//#include <malloc.h>
+
+
+/*
+ ******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ *******************************************************************************
+ */
+uint32_t strlen( uint8_t* s )
+{
+	uint8_t *sc;
+
+	for (sc = s; *sc != '\0'; ++sc)
+		/* nothing */;
+	return sc - s;
+}
+
+/*
+ ******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ *******************************************************************************
+ */
+void * memset(void * s,int c,size_t count)
+{
+	unsigned long *sl = (unsigned long *) s;
+	unsigned long cl = 0;
+	char *s8;
+	int i;
+
+	/* do it one word at a time (32 bits or 64 bits) while possible */
+	if ( ((ulong)s & (sizeof(*sl) - 1)) == 0) {
+		for (i = 0; i < sizeof(*sl); i++) {
+			cl <<= 8;
+			cl |= c & 0xff;
+		}
+		while (count >= sizeof(*sl)) {
+			*sl++ = cl;
+			count -= sizeof(*sl);
+		}
+	}
+	/* fill 8 bits at a time */
+	s8 = (char *)sl;
+	while (count--)
+		*s8++ = c;
+
+	return s;
+}
+
+/*
+ ******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ *******************************************************************************
+ */
+int memcmp(void *a, void *c, int n)
+{
+	int i;
+	for (i = 0; i < n; i++) {
+		if (((unsigned char *)c)[i] != ((unsigned char *)a)[i])
+			return 1;
+	}
+	return 0;
+}
+
+/*
+ ******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ *******************************************************************************
+ */
+void memcpy( uint32_t dest, uint32_t src, uint32_t count )
+{
+	char *tmp = (char *) dest, *s = (char *) src;
+
+	while (count--)
+		*tmp++ = *s++;
+}
+
+
diff --git a/boot/common/src/loader/lib/vsprintf.c b/boot/common/src/loader/lib/vsprintf.c
new file mode 100644
index 0000000..5751e29
--- /dev/null
+++ b/boot/common/src/loader/lib/vsprintf.c
@@ -0,0 +1,740 @@
+/*
+ *  linux/lib/vsprintf.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
+/*
+ * Wirzenius wrote this portably, Torvalds fucked it up :-)
+ */
+
+#include <stdarg.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <errno.h>
+
+#include <common.h>
+#if !defined (CONFIG_PANIC_HANG)
+#include <command.h>
+#endif
+
+#include <div64.h>
+# define NUM_TYPE long long
+#define noinline __attribute__((noinline))
+
+const char hex_asc[] = "0123456789abcdef";
+#define hex_asc_lo(x)   hex_asc[((x) & 0x0f)]
+#define hex_asc_hi(x)   hex_asc[((x) & 0xf0) >> 4]
+
+static inline char *pack_hex_byte(char *buf, u8 byte)
+{
+	*buf++ = hex_asc_hi(byte);
+	*buf++ = hex_asc_lo(byte);
+	return buf;
+}
+
+unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
+{
+	unsigned long result = 0,value;
+
+	if (*cp == '0') {
+		cp++;
+		if ((*cp == 'x') && isxdigit(cp[1])) {
+			base = 16;
+			cp++;
+		}
+		if (!base) {
+			base = 8;
+		}
+	}
+	if (!base) {
+		base = 10;
+	}
+	while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
+	    ? toupper(*cp) : *cp)-'A'+10) < base) {
+		result = result*base + value;
+		cp++;
+	}
+	if (endp)
+		*endp = (char *)cp;
+	return result;
+}
+
+/**
+ * strict_strtoul - convert a string to an unsigned long strictly
+ * @cp: The string to be converted
+ * @base: The number base to use
+ * @res: The converted result value
+ *
+ * strict_strtoul converts a string to an unsigned long only if the
+ * string is really an unsigned long string, any string containing
+ * any invalid char at the tail will be rejected and -EINVAL is returned,
+ * only a newline char at the tail is acceptible because people generally
+ * change a module parameter in the following way:
+ *
+ *      echo 1024 > /sys/module/e1000/parameters/copybreak
+ *
+ * echo will append a newline to the tail.
+ *
+ * It returns 0 if conversion is successful and *res is set to the converted
+ * value, otherwise it returns -EINVAL and *res is set to 0.
+ *
+ * simple_strtoul just ignores the successive invalid characters and
+ * return the converted value of prefix part of the string.
+ *
+ * Copied this function from Linux 2.6.38 commit ID:
+ * 521cb40b0c44418a4fd36dc633f575813d59a43d
+ *
+ */
+int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
+{
+	char *tail;
+	unsigned long val;
+	size_t len;
+
+	*res = 0;
+	len = strlen(cp);
+	if (len == 0)
+		return -EINVAL;
+
+	val = simple_strtoul(cp, &tail, base);
+	if (tail == cp)
+		return -EINVAL;
+
+	if ((*tail == '\0') ||
+		((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
+		*res = val;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+long simple_strtol(const char *cp,char **endp,unsigned int base)
+{
+	if(*cp=='-')
+		return -simple_strtoul(cp+1,endp,base);
+	return simple_strtoul(cp,endp,base);
+}
+
+int ustrtoul(const char *cp, char **endp, unsigned int base)
+{
+	unsigned long result = simple_strtoul(cp, endp, base);
+	switch (**endp) {
+	case 'G' :
+		result *= 1024;
+		/* fall through */
+	case 'M':
+		result *= 1024;
+		/* fall through */
+	case 'K':
+	case 'k':
+		result *= 1024;
+		if ((*endp)[1] == 'i') {
+			if ((*endp)[2] == 'B')
+				(*endp) += 3;
+			else
+				(*endp) += 2;
+		}
+	}
+	return result;
+}
+
+unsigned long long simple_strtoull (const char *cp, char **endp, unsigned int base)
+{
+	unsigned long long result = 0, value;
+
+	if (*cp == '0') {
+		cp++;
+		if ((*cp == 'x') && isxdigit (cp[1])) {
+			base = 16;
+			cp++;
+		}
+		if (!base) {
+			base = 8;
+		}
+	}
+	if (!base) {
+		base = 10;
+	}
+	while (isxdigit (*cp) && (value = isdigit (*cp)
+				? *cp - '0'
+				: (islower (*cp) ? toupper (*cp) : *cp) - 'A' + 10) < base) {
+		result = result * base + value;
+		cp++;
+	}
+	if (endp)
+		*endp = (char *) cp;
+	return result;
+}
+
+/* we use this so that we can do without the ctype library */
+#define is_digit(c)	((c) >= '0' && (c) <= '9')
+
+static int skip_atoi(const char **s)
+{
+	int i=0;
+
+	while (is_digit(**s))
+		i = i*10 + *((*s)++) - '0';
+	return i;
+}
+
+/* Decimal conversion is by far the most typical, and is used
+ * for /proc and /sys data. This directly impacts e.g. top performance
+ * with many processes running. We optimize it for speed
+ * using code from
+ * http://www.cs.uiowa.edu/~jones/bcd/decimal.html
+ * (with permission from the author, Douglas W. Jones). */
+
+/* Formats correctly any integer in [0,99999].
+ * Outputs from one to five digits depending on input.
+ * On i386 gcc 4.1.2 -O2: ~250 bytes of code. */
+static char* put_dec_trunc(char *buf, unsigned q)
+{
+	unsigned d3, d2, d1, d0;
+	d1 = (q>>4) & 0xf;
+	d2 = (q>>8) & 0xf;
+	d3 = (q>>12);
+
+	d0 = 6*(d3 + d2 + d1) + (q & 0xf);
+	q = (d0 * 0xcd) >> 11;
+	d0 = d0 - 10*q;
+	*buf++ = d0 + '0'; /* least significant digit */
+	d1 = q + 9*d3 + 5*d2 + d1;
+	if (d1 != 0) {
+		q = (d1 * 0xcd) >> 11;
+		d1 = d1 - 10*q;
+		*buf++ = d1 + '0'; /* next digit */
+
+		d2 = q + 2*d2;
+		if ((d2 != 0) || (d3 != 0)) {
+			q = (d2 * 0xd) >> 7;
+			d2 = d2 - 10*q;
+			*buf++ = d2 + '0'; /* next digit */
+
+			d3 = q + 4*d3;
+			if (d3 != 0) {
+				q = (d3 * 0xcd) >> 11;
+				d3 = d3 - 10*q;
+				*buf++ = d3 + '0';  /* next digit */
+				if (q != 0)
+					*buf++ = q + '0';  /* most sign. digit */
+			}
+		}
+	}
+	return buf;
+}
+/* Same with if's removed. Always emits five digits */
+static char* put_dec_full(char *buf, unsigned q)
+{
+	/* BTW, if q is in [0,9999], 8-bit ints will be enough, */
+	/* but anyway, gcc produces better code with full-sized ints */
+	unsigned d3, d2, d1, d0;
+	d1 = (q>>4) & 0xf;
+	d2 = (q>>8) & 0xf;
+	d3 = (q>>12);
+
+	/*
+	 * Possible ways to approx. divide by 10
+	 * gcc -O2 replaces multiply with shifts and adds
+	 * (x * 0xcd) >> 11: 11001101 - shorter code than * 0x67 (on i386)
+	 * (x * 0x67) >> 10:  1100111
+	 * (x * 0x34) >> 9:    110100 - same
+	 * (x * 0x1a) >> 8:     11010 - same
+	 * (x * 0x0d) >> 7:      1101 - same, shortest code (on i386)
+	 */
+
+	d0 = 6*(d3 + d2 + d1) + (q & 0xf);
+	q = (d0 * 0xcd) >> 11;
+	d0 = d0 - 10*q;
+	*buf++ = d0 + '0';
+	d1 = q + 9*d3 + 5*d2 + d1;
+		q = (d1 * 0xcd) >> 11;
+		d1 = d1 - 10*q;
+		*buf++ = d1 + '0';
+
+		d2 = q + 2*d2;
+			q = (d2 * 0xd) >> 7;
+			d2 = d2 - 10*q;
+			*buf++ = d2 + '0';
+
+			d3 = q + 4*d3;
+				q = (d3 * 0xcd) >> 11; /* - shorter code */
+				/* q = (d3 * 0x67) >> 10; - would also work */
+				d3 = d3 - 10*q;
+				*buf++ = d3 + '0';
+					*buf++ = q + '0';
+	return buf;
+}
+/* No inlining helps gcc to use registers better */
+static noinline char* put_dec(char *buf, unsigned NUM_TYPE num)
+{
+	while (1) {
+		unsigned rem;
+		if (num < 100000)
+			return put_dec_trunc(buf, num);
+		rem = do_div(num, 100000);
+		buf = put_dec_full(buf, rem);
+	}
+}
+
+#define ZEROPAD	1		/* pad with zero */
+#define SIGN	2		/* unsigned/signed long */
+#define PLUS	4		/* show plus */
+#define SPACE	8		/* space if plus */
+#define LEFT	16		/* left justified */
+#define SMALL	32		/* Must be 32 == 0x20 */
+#define SPECIAL	64		/* 0x */
+
+static char *number(char *buf, unsigned NUM_TYPE num, int base, int size, int precision, int type)
+{
+	/* we are called with base 8, 10 or 16, only, thus don't need "G..."  */
+	static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
+
+	char tmp[66];
+	char sign;
+	char locase;
+	int need_pfx = ((type & SPECIAL) && base != 10);
+	int i;
+
+	/* locase = 0 or 0x20. ORing digits or letters with 'locase'
+	 * produces same digits or (maybe lowercased) letters */
+	locase = (type & SMALL);
+	if (type & LEFT)
+		type &= ~ZEROPAD;
+	sign = 0;
+	if (type & SIGN) {
+		if ((signed NUM_TYPE) num < 0) {
+			sign = '-';
+			num = - (signed NUM_TYPE) num;
+			size--;
+		} else if (type & PLUS) {
+			sign = '+';
+			size--;
+		} else if (type & SPACE) {
+			sign = ' ';
+			size--;
+		}
+	}
+	if (need_pfx) {
+		size--;
+		if (base == 16)
+			size--;
+	}
+
+	/* generate full string in tmp[], in reverse order */
+	i = 0;
+	if (num == 0)
+		tmp[i++] = '0';
+	/* Generic code, for any base:
+	else do {
+		tmp[i++] = (digits[do_div(num,base)] | locase);
+	} while (num != 0);
+	*/
+	else if (base != 10) { /* 8 or 16 */
+		int mask = base - 1;
+		int shift = 3;
+		if (base == 16) shift = 4;
+		do {
+			tmp[i++] = (digits[((unsigned char)num) & mask] | locase);
+			num >>= shift;
+		} while (num);
+	} else { /* base 10 */
+		i = put_dec(tmp, num) - tmp;
+	}
+
+	/* printing 100 using %2d gives "100", not "00" */
+	if (i > precision)
+		precision = i;
+	/* leading space padding */
+	size -= precision;
+	if (!(type & (ZEROPAD+LEFT)))
+		while(--size >= 0)
+			*buf++ = ' ';
+	/* sign */
+	if (sign)
+		*buf++ = sign;
+	/* "0x" / "0" prefix */
+	if (need_pfx) {
+		*buf++ = '0';
+		if (base == 16)
+			*buf++ = ('X' | locase);
+	}
+	/* zero or space padding */
+	if (!(type & LEFT)) {
+		char c = (type & ZEROPAD) ? '0' : ' ';
+		while (--size >= 0)
+			*buf++ = c;
+	}
+	/* hmm even more zero padding? */
+	while (i <= --precision)
+		*buf++ = '0';
+	/* actual digits of result */
+	while (--i >= 0)
+		*buf++ = tmp[i];
+	/* trailing space padding */
+	while (--size >= 0)
+		*buf++ = ' ';
+	return buf;
+}
+
+static char *string(char *buf, char *s, int field_width, int precision, int flags)
+{
+	int len, i;
+
+	if (s == 0)
+		s = "<NULL>";
+
+	len = strnlen(s, precision);
+
+	if (!(flags & LEFT))
+		while (len < field_width--)
+			*buf++ = ' ';
+	for (i = 0; i < len; ++i)
+		*buf++ = *s++;
+	while (len < field_width--)
+		*buf++ = ' ';
+	return buf;
+}
+
+#ifdef CONFIG_CMD_NET
+static char *mac_address_string(char *buf, u8 *addr, int field_width,
+				int precision, int flags)
+{
+	char mac_addr[6 * 3]; /* (6 * 2 hex digits), 5 colons and trailing zero */
+	char *p = mac_addr;
+	int i;
+
+	for (i = 0; i < 6; i++) {
+		p = pack_hex_byte(p, addr[i]);
+		if (!(flags & SPECIAL) && i != 5)
+			*p++ = ':';
+	}
+	*p = '\0';
+
+	return string(buf, mac_addr, field_width, precision, flags & ~SPECIAL);
+}
+
+static char *ip6_addr_string(char *buf, u8 *addr, int field_width,
+			 int precision, int flags)
+{
+	char ip6_addr[8 * 5]; /* (8 * 4 hex digits), 7 colons and trailing zero */
+	char *p = ip6_addr;
+	int i;
+
+	for (i = 0; i < 8; i++) {
+		p = pack_hex_byte(p, addr[2 * i]);
+		p = pack_hex_byte(p, addr[2 * i + 1]);
+		if (!(flags & SPECIAL) && i != 7)
+			*p++ = ':';
+	}
+	*p = '\0';
+
+	return string(buf, ip6_addr, field_width, precision, flags & ~SPECIAL);
+}
+
+static char *ip4_addr_string(char *buf, u8 *addr, int field_width,
+			 int precision, int flags)
+{
+	char ip4_addr[4 * 4]; /* (4 * 3 decimal digits), 3 dots and trailing zero */
+	char temp[3];	/* hold each IP quad in reverse order */
+	char *p = ip4_addr;
+	int i, digits;
+
+	for (i = 0; i < 4; i++) {
+		digits = put_dec_trunc(temp, addr[i]) - temp;
+		/* reverse the digits in the quad */
+		while (digits--)
+			*p++ = temp[digits];
+		if (i != 3)
+			*p++ = '.';
+	}
+	*p = '\0';
+
+	return string(buf, ip4_addr, field_width, precision, flags & ~SPECIAL);
+}
+#endif
+
+/*
+ * Show a '%p' thing.  A kernel extension is that the '%p' is followed
+ * by an extra set of alphanumeric characters that are extended format
+ * specifiers.
+ *
+ * Right now we handle:
+ *
+ * - 'M' For a 6-byte MAC address, it prints the address in the
+ *       usual colon-separated hex notation
+ * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way (dot-separated
+ *       decimal for v4 and colon separated network-order 16 bit hex for v6)
+ * - 'i' [46] for 'raw' IPv4/IPv6 addresses, IPv6 omits the colons, IPv4 is
+ *       currently the same
+ *
+ * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
+ * function pointers are really function descriptors, which contain a
+ * pointer to the real address.
+ */
+static char *pointer(const char *fmt, char *buf, void *ptr, int field_width, int precision, int flags)
+{
+	if (!ptr)
+		return string(buf, "(null)", field_width, precision, flags);
+
+#ifdef CONFIG_CMD_NET
+	switch (*fmt) {
+	case 'm':
+		flags |= SPECIAL;
+		/* Fallthrough */
+	case 'M':
+		return mac_address_string(buf, ptr, field_width, precision, flags);
+	case 'i':
+		flags |= SPECIAL;
+		/* Fallthrough */
+	case 'I':
+		if (fmt[1] == '6')
+			return ip6_addr_string(buf, ptr, field_width, precision, flags);
+		if (fmt[1] == '4')
+			return ip4_addr_string(buf, ptr, field_width, precision, flags);
+		flags &= ~SPECIAL;
+		break;
+	}
+#endif
+	flags |= SMALL;
+	if (field_width == -1) {
+		field_width = 2*sizeof(void *);
+		flags |= ZEROPAD;
+	}
+	return number(buf, (unsigned long) ptr, 16, field_width, precision, flags);
+}
+
+/**
+ * vsprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @fmt: The format string to use
+ * @args: Arguments for the format string
+ *
+ * This function follows C99 vsprintf, but has some extensions:
+ * %pS output the name of a text symbol
+ * %pF output the name of a function pointer
+ * %pR output the address range in a struct resource
+ *
+ * The function returns the number of characters written
+ * into @buf.
+ *
+ * Call this function if you are already dealing with a va_list.
+ * You probably want sprintf() instead.
+ */
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+	unsigned NUM_TYPE num;
+	int base;
+	char *str;
+
+	int flags;		/* flags to number() */
+
+	int field_width;	/* width of output field */
+	int precision;		/* min. # of digits for integers; max
+				   number of chars for from string */
+	int qualifier;		/* 'h', 'l', or 'L' for integer fields */
+				/* 'z' support added 23/7/1999 S.H.    */
+				/* 'z' changed to 'Z' --davidm 1/25/99 */
+				/* 't' added for ptrdiff_t */
+
+	str = buf;
+
+	for (; *fmt ; ++fmt) {
+		if (*fmt != '%') {
+			*str++ = *fmt;
+			continue;
+		}
+
+		/* process flags */
+		flags = 0;
+		repeat:
+			++fmt;		/* this also skips first '%' */
+			switch (*fmt) {
+				case '-': flags |= LEFT; goto repeat;
+				case '+': flags |= PLUS; goto repeat;
+				case ' ': flags |= SPACE; goto repeat;
+				case '#': flags |= SPECIAL; goto repeat;
+				case '0': flags |= ZEROPAD; goto repeat;
+			}
+
+		/* get field width */
+		field_width = -1;
+		if (is_digit(*fmt))
+			field_width = skip_atoi(&fmt);
+		else if (*fmt == '*') {
+			++fmt;
+			/* it's the next argument */
+			field_width = va_arg(args, int);
+			if (field_width < 0) {
+				field_width = -field_width;
+				flags |= LEFT;
+			}
+		}
+
+		/* get the precision */
+		precision = -1;
+		if (*fmt == '.') {
+			++fmt;
+			if (is_digit(*fmt))
+				precision = skip_atoi(&fmt);
+			else if (*fmt == '*') {
+				++fmt;
+				/* it's the next argument */
+				precision = va_arg(args, int);
+			}
+			if (precision < 0)
+				precision = 0;
+		}
+
+		/* get the conversion qualifier */
+		qualifier = -1;
+		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
+		    *fmt == 'Z' || *fmt == 'z' || *fmt == 't') {
+			qualifier = *fmt;
+			++fmt;
+			if (qualifier == 'l' && *fmt == 'l') {
+				qualifier = 'L';
+				++fmt;
+			}
+		}
+
+		/* default base */
+		base = 10;
+
+		switch (*fmt) {
+		case 'c':
+			if (!(flags & LEFT))
+				while (--field_width > 0)
+					*str++ = ' ';
+			*str++ = (unsigned char) va_arg(args, int);
+			while (--field_width > 0)
+				*str++ = ' ';
+			continue;
+
+		case 's':
+			str = string(str, va_arg(args, char *), field_width, precision, flags);
+			continue;
+
+		case 'p':
+			str = pointer(fmt+1, str,
+					va_arg(args, void *),
+					field_width, precision, flags);
+			/* Skip all alphanumeric pointer suffixes */
+			while (isalnum(fmt[1]))
+				fmt++;
+			continue;
+
+		case 'n':
+			if (qualifier == 'l') {
+				long * ip = va_arg(args, long *);
+				*ip = (str - buf);
+			} else {
+				int * ip = va_arg(args, int *);
+				*ip = (str - buf);
+			}
+			continue;
+
+		case '%':
+			*str++ = '%';
+			continue;
+
+		/* integer number formats - set up the flags and "break" */
+		case 'o':
+			base = 8;
+			break;
+
+		case 'x':
+			flags |= SMALL;
+		case 'X':
+			base = 16;
+			break;
+
+		case 'd':
+		case 'i':
+			flags |= SIGN;
+		case 'u':
+			break;
+
+		default:
+			*str++ = '%';
+			if (*fmt)
+				*str++ = *fmt;
+			else
+				--fmt;
+			continue;
+		}
+		if (qualifier == 'L')  /* "quad" for 64 bit variables */
+			num = va_arg(args, unsigned long long);
+		else if (qualifier == 'l') {
+			num = va_arg(args, unsigned long);
+			if (flags & SIGN)
+				num = (signed long) num;
+		} else if (qualifier == 'Z' || qualifier == 'z') {
+			num = va_arg(args, size_t);
+		} else if (qualifier == 't') {
+			num = va_arg(args, ptrdiff_t);
+		} else if (qualifier == 'h') {
+			num = (unsigned short) va_arg(args, int);
+			if (flags & SIGN)
+				num = (signed short) num;
+		} else {
+			num = va_arg(args, unsigned int);
+			if (flags & SIGN)
+				num = (signed int) num;
+		}
+		str = number(str, num, base, field_width, precision, flags);
+	}
+	*str = '\0';
+	return str-buf;
+}
+
+/**
+ * sprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @fmt: The format string to use
+ * @...: Arguments for the format string
+ *
+ * The function returns the number of characters written
+ * into @buf.
+ *
+ * See the vsprintf() documentation for format string extensions over C99.
+ */
+int sprintf(char * buf, const char *fmt, ...)
+{
+	va_list args;
+	int i;
+
+	va_start(args, fmt);
+	i=vsprintf(buf,fmt,args);
+	va_end(args);
+	return i;
+}
+
+void panic(const char *fmt, ...)
+{
+	va_list	args;
+	va_start(args, fmt);
+	vprintf(fmt, args);
+	putc('\n');
+	va_end(args);
+#if defined (CONFIG_PANIC_HANG)
+	hang();
+#else
+	usdelay (100000);	/* allow messages to go out */
+	do_reset (NULL, 0, 0, NULL);
+#endif
+	while (1)
+		;
+}
+
+void __assert_fail(const char *assertion, const char *file, unsigned line,
+		   const char *function)
+{
+	/* This will not return */
+	panic("%s:%u: %s: Assertion `%s' failed.", file, line, function,
+	      assertion);
+}