[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);
+}