ls102xa: pblimage: Add pblimage tool support for LS102xA

For LS102xA, the size of spl/u-boot-spl.bin is variable.
This patch adds the support to deal with the variable
u-boot size in pblimage tool. It will be padded to 64
byte boundary.

Use pblimage_check_params() to add the specific operations
for ARM, such as PBI CRC and END command and the calculation
of pbl_cmd_initaddr.

Signed-off-by: Alison Wang <alison.wang@freescale.com>
Reviewed-by: York Sun <yorksun@freescale.com>
diff --git a/Makefile b/Makefile
index 2308828..d3e99e5 100644
--- a/Makefile
+++ b/Makefile
@@ -999,7 +999,8 @@
 #concatenated with u-boot binary. It is need by PowerPC SoC having
 #internal SRAM <= 512KB.
 MKIMAGEFLAGS_u-boot-spl.pbl = -n $(srctree)/$(CONFIG_SYS_FSL_PBL_RCW:"%"=%) \
-		-R $(srctree)/$(CONFIG_SYS_FSL_PBL_PBI:"%"=%) -T pblimage
+		-R $(srctree)/$(CONFIG_SYS_FSL_PBL_PBI:"%"=%) -T pblimage \
+		-A $(ARCH) -a $(CONFIG_SPL_TEXT_BASE)
 
 spl/u-boot-spl.pbl: spl/u-boot-spl.bin FORCE
 	$(call if_changed,mkimage)
diff --git a/tools/pblimage.c b/tools/pblimage.c
index 6e6e801..2a799ab 100644
--- a/tools/pblimage.c
+++ b/tools/pblimage.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2012-2014 Freescale Semiconductor, Inc.
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -8,6 +8,10 @@
 #include "pblimage.h"
 #include "pbl_crc32.h"
 
+#define roundup(x, y)		((((x) + ((y) - 1)) / (y)) * (y))
+#define PBL_ACS_CONT_CMD	0x81000000
+#define PBL_ADDR_24BIT_MASK	0x00ffffff
+
 /*
  * Initialize to an invalid value.
  */
@@ -22,6 +26,13 @@
 static char *fname = "Unknown";
 static int lineno = -1;
 static struct pbl_header pblimage_header;
+static int uboot_size;
+static int arch_flag;
+
+static uint32_t pbl_cmd_initaddr;
+static uint32_t pbi_crc_cmd1;
+static uint32_t pbi_crc_cmd2;
+static uint32_t pbl_end_cmd[4];
 
 static union
 {
@@ -38,20 +49,6 @@
  * start offset by subtracting the size of the u-boot image from the
  * top of the allowable 24-bit range.
  */
-static void init_next_pbl_cmd(FILE *fp_uboot)
-{
-	struct stat st;
-	int fd = fileno(fp_uboot);
-
-	if (fstat(fd, &st) == -1) {
-		printf("Error: Could not determine u-boot image size. %s\n",
-			strerror(errno));
-		exit(EXIT_FAILURE);
-	}
-
-	next_pbl_cmd = 0x82000000 - st.st_size;
-}
-
 static void generate_pbl_cmd(void)
 {
 	uint32_t val = next_pbl_cmd;
@@ -66,11 +63,15 @@
 
 static void pbl_fget(size_t size, FILE *stream)
 {
-	unsigned char c;
+	unsigned char c = 0xff;
 	int c_temp;
 
-	while (size && (c_temp = fgetc(stream)) != EOF) {
-		c = (unsigned char)c_temp;
+	while (size) {
+		c_temp = fgetc(stream);
+		if (c_temp != EOF)
+			c = (unsigned char)c_temp;
+		else if ((c_temp == EOF) && (arch_flag == IH_ARCH_ARM))
+			c = 0xff;
 		*pmem_buf++ = c;
 		pbl_size++;
 		size--;
@@ -80,8 +81,8 @@
 /* load split u-boot with PBI command 81xxxxxx. */
 static void load_uboot(FILE *fp_uboot)
 {
-	init_next_pbl_cmd(fp_uboot);
-	while (next_pbl_cmd < 0x82000000) {
+	next_pbl_cmd = pbl_cmd_initaddr - uboot_size;
+	while (next_pbl_cmd < pbl_cmd_initaddr) {
 		generate_pbl_cmd();
 		pbl_fget(64, fp_uboot);
 	}
@@ -154,8 +155,6 @@
 /* write end command and crc command to memory. */
 static void add_end_cmd(void)
 {
-	uint32_t pbl_end_cmd[4] = {0x09138000, 0x00000000,
-		0x091380c0, 0x00000000};
 	uint32_t crc32_pbl;
 	int i;
 	unsigned char *p = (unsigned char *)&pbl_end_cmd;
@@ -172,8 +171,8 @@
 
 	/* Add PBI CRC command. */
 	*pmem_buf++ = 0x08;
-	*pmem_buf++ = 0x13;
-	*pmem_buf++ = 0x80;
+	*pmem_buf++ = pbi_crc_cmd1;
+	*pmem_buf++ = pbi_crc_cmd2;
 	*pmem_buf++ = 0x40;
 	pbl_size += 4;
 
@@ -184,17 +183,6 @@
 	*pmem_buf++ = (crc32_pbl >> 8) & 0xff;
 	*pmem_buf++ = (crc32_pbl) & 0xff;
 	pbl_size += 4;
-
-	if ((pbl_size % 16) != 0) {
-		for (i = 0; i < 8; i++) {
-			*pmem_buf++ = 0x0;
-			pbl_size++;
-		}
-	}
-	if ((pbl_size % 16 != 0)) {
-		printf("Error: Bad size of image file\n");
-		exit(EXIT_FAILURE);
-	}
 }
 
 void pbl_load_uboot(int ifd, struct image_tool_params *params)
@@ -268,12 +256,64 @@
 	/*nothing need to do, pbl_load_uboot takes care of whole file. */
 }
 
+int pblimage_check_params(struct image_tool_params *params)
+{
+	FILE *fp_uboot;
+	int fd;
+	struct stat st;
+
+	if (!params)
+		return EXIT_FAILURE;
+
+	fp_uboot = fopen(params->datafile, "r");
+	if (fp_uboot == NULL) {
+		printf("Error: %s open failed\n", params->datafile);
+		exit(EXIT_FAILURE);
+	}
+	fd = fileno(fp_uboot);
+
+	if (fstat(fd, &st) == -1) {
+		printf("Error: Could not determine u-boot image size. %s\n",
+		       strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+
+	/* For the variable size, we need to pad it to 64 byte boundary */
+	uboot_size = roundup(st.st_size, 64);
+
+	if (params->arch == IH_ARCH_ARM) {
+		arch_flag = IH_ARCH_ARM;
+		pbi_crc_cmd1 = 0x61;
+		pbi_crc_cmd2 = 0;
+		pbl_cmd_initaddr = params->addr & PBL_ADDR_24BIT_MASK;
+		pbl_cmd_initaddr |= PBL_ACS_CONT_CMD;
+		pbl_cmd_initaddr |= uboot_size;
+		pbl_end_cmd[0] = 0x09610000;
+		pbl_end_cmd[1] = 0x00000000;
+		pbl_end_cmd[2] = 0x096100c0;
+		pbl_end_cmd[3] = 0x00000000;
+	} else if (params->arch == IH_ARCH_PPC) {
+		arch_flag = IH_ARCH_PPC;
+		pbi_crc_cmd1 = 0x13;
+		pbi_crc_cmd2 = 0x80;
+		pbl_cmd_initaddr = 0x82000000;
+		pbl_end_cmd[0] = 0x09138000;
+		pbl_end_cmd[1] = 0x00000000;
+		pbl_end_cmd[2] = 0x091380c0;
+		pbl_end_cmd[3] = 0x00000000;
+	}
+
+	next_pbl_cmd = pbl_cmd_initaddr;
+	return 0;
+};
+
 /* pblimage parameters */
 static struct image_type_params pblimage_params = {
 	.name		= "Freescale PBL Boot Image support",
 	.header_size	= sizeof(struct pbl_header),
 	.hdr		= (void *)&pblimage_header,
 	.check_image_type = pblimage_check_image_types,
+	.check_params	= pblimage_check_params,
 	.verify_header	= pblimage_verify_header,
 	.print_header	= pblimage_print_header,
 	.set_header	= pblimage_set_header,