[meta-xilinx] [PATCH] u-boot-xlnx_2016.07: Apply patch for Zynq to resolve obscure bug

Nathan Rossi nathan at nathanrossi.com
Sun Dec 4 01:58:51 PST 2016


This patch fixes a bug that was introduced in u-boot v2016.05 as well
as xilinx-v2016.2. The bug can appear in variety of ways, but was
observed as:

  Uncompressing Invalid Image ... Unimplemented compression type 23

See patch for specific details.

Signed-off-by: Nathan Rossi <nathan at nathanrossi.com>
---
 ...place-dram_init-functions-with-board_init.patch | 213 +++++++++++++++++++++
 recipes-bsp/u-boot/u-boot-xlnx_2016.07.bb          |   1 +
 2 files changed, 214 insertions(+)
 create mode 100644 recipes-bsp/u-boot/u-boot-xlnx/ARM-zynq-Replace-dram_init-functions-with-board_init.patch

diff --git a/recipes-bsp/u-boot/u-boot-xlnx/ARM-zynq-Replace-dram_init-functions-with-board_init.patch b/recipes-bsp/u-boot/u-boot-xlnx/ARM-zynq-Replace-dram_init-functions-with-board_init.patch
new file mode 100644
index 0000000000..b1885a9afc
--- /dev/null
+++ b/recipes-bsp/u-boot/u-boot-xlnx/ARM-zynq-Replace-dram_init-functions-with-board_init.patch
@@ -0,0 +1,213 @@
+From c5db12d072b43f1fc635edfdbece8256111faf42 Mon Sep 17 00:00:00 2001
+From: Nathan Rossi <nathan at nathanrossi.com>
+Date: Sun, 4 Dec 2016 19:33:22 +1000
+Subject: [PATCH] ARM: zynq: Replace dram_init* functions with board_init_f
+ safe ones
+
+The dram_init* functions for the zynq board are not safe for use from
+the board_init_f stage due to its use of the 'tmp' static variable.
+
+This incorrect use of a static variable was causing rare issues where
+the dram_init function would overwrite some parts the __rel_dyn section
+which caused obscure failures.
+
+This change removes the existing code and copies the implementation of
+the dram_init and dram_init_banksize from the
+arch/arm/mach-uniphier/dram_init.c source. This version of these
+functions does not use static variables and behaves the same (reading
+banks from fdt, and using the first bank as the ram_size).
+
+Signed-off-by: Nathan Rossi <nathan at nathanrossi.com>
+Fixes: 758f29d0f8 ("ARM: zynq: Support systems with more memory banks")
+Upstream-Status: Pending
+---
+This issue appears as the following error during image load for the Zybo
+board, however this is just one potential way this bug can surface.
+
+   Uncompressing Invalid Image ... Unimplemented compression type 23
+
+Changes in section sizes will vary the outcomes, and in some cases not
+present any issues during normal use.
+---
+ board/xilinx/zynq/board.c | 148 ++++++++++++++++------------------------------
+ 1 file changed, 50 insertions(+), 98 deletions(-)
+
+diff --git a/board/xilinx/zynq/board.c b/board/xilinx/zynq/board.c
+index 44ecb77b74..f6d4df6ad5 100644
+--- a/board/xilinx/zynq/board.c
++++ b/board/xilinx/zynq/board.c
+@@ -124,121 +124,73 @@ int zynq_board_read_rom_ethaddr(unsigned char *ethaddr)
+ }
+ 
+ #if !defined(CONFIG_SYS_SDRAM_BASE) && !defined(CONFIG_SYS_SDRAM_SIZE)
+-/*
+- * fdt_get_reg - Fill buffer by information from DT
+- */
+-static phys_size_t fdt_get_reg(const void *fdt, int nodeoffset, void *buf,
+-			       const u32 *cell, int n)
++static const void *get_memory_reg_prop(const void *fdt, int *lenp)
+ {
+-	int i = 0, b, banks;
+-	int parent_offset = fdt_parent_offset(fdt, nodeoffset);
+-	int address_cells = fdt_address_cells(fdt, parent_offset);
+-	int size_cells = fdt_size_cells(fdt, parent_offset);
+-	char *p = buf;
+-	u64 val;
+-	u64 vals;
+-
+-	debug("%s: addr_cells=%x, size_cell=%x, buf=%p, cell=%p\n",
+-	      __func__, address_cells, size_cells, buf, cell);
+-
+-	/* Check memory bank setup */
+-	banks = n % (address_cells + size_cells);
+-	if (banks)
+-		panic("Incorrect memory setup cells=%d, ac=%d, sc=%d\n",
+-		      n, address_cells, size_cells);
+-
+-	banks = n / (address_cells + size_cells);
+-
+-	for (b = 0; b < banks; b++) {
+-		debug("%s: Bank #%d:\n", __func__, b);
+-		if (address_cells == 2) {
+-			val = cell[i + 1];
+-			val <<= 32;
+-			val |= cell[i];
+-			val = fdt64_to_cpu(val);
+-			debug("%s: addr64=%llx, ptr=%p, cell=%p\n",
+-			      __func__, val, p, &cell[i]);
+-			*(phys_addr_t *)p = val;
+-		} else {
+-			debug("%s: addr32=%x, ptr=%p\n",
+-			      __func__, fdt32_to_cpu(cell[i]), p);
+-			*(phys_addr_t *)p = fdt32_to_cpu(cell[i]);
+-		}
+-		p += sizeof(phys_addr_t);
+-		i += address_cells;
+-
+-		debug("%s: pa=%p, i=%x, size=%zu\n", __func__, p, i,
+-		      sizeof(phys_addr_t));
+-
+-		if (size_cells == 2) {
+-			vals = cell[i + 1];
+-			vals <<= 32;
+-			vals |= cell[i];
+-			vals = fdt64_to_cpu(vals);
+-
+-			debug("%s: size64=%llx, ptr=%p, cell=%p\n",
+-			      __func__, vals, p, &cell[i]);
+-			*(phys_size_t *)p = vals;
+-		} else {
+-			debug("%s: size32=%x, ptr=%p\n",
+-			      __func__, fdt32_to_cpu(cell[i]), p);
+-			*(phys_size_t *)p = fdt32_to_cpu(cell[i]);
+-		}
+-		p += sizeof(phys_size_t);
+-		i += size_cells;
+-
+-		debug("%s: ps=%p, i=%x, size=%zu\n",
+-		      __func__, p, i, sizeof(phys_size_t));
+-	}
++	int offset;
+ 
+-	/* Return the first address size */
+-	return *(phys_size_t *)((char *)buf + sizeof(phys_addr_t));
+-}
++	offset = fdt_path_offset(fdt, "/memory");
++	if (offset < 0)
++		return NULL;
+ 
+-#define FDT_REG_SIZE  sizeof(u32)
+-/* Temp location for sharing data for storing */
+-/* Up to 64-bit address + 64-bit size */
+-static u8 tmp[CONFIG_NR_DRAM_BANKS * 16];
++	return fdt_getprop(fdt, offset, "reg", lenp);
++}
+ 
+ void dram_init_banksize(void)
+ {
+-	int bank;
++	const void *fdt = gd->fdt_blob;
++	const fdt32_t *val;
++	int ac, sc, cells, len, i;
++
++	val = get_memory_reg_prop(fdt, &len);
++	if (len < 0)
++		return;
++
++	ac = fdt_address_cells(fdt, 0);
++	sc = fdt_size_cells(fdt, 0);
++	if (ac < 1 || sc > 2 || sc < 1 || sc > 2) {
++		printf("invalid address/size cells\n");
++		return;
++	}
+ 
+-	memcpy(&gd->bd->bi_dram[0], &tmp, sizeof(tmp));
++	cells = ac + sc;
+ 
+-	for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
+-		debug("Bank #%d: start %llx\n", bank,
+-		      (unsigned long long)gd->bd->bi_dram[bank].start);
+-		debug("Bank #%d: size %llx\n", bank,
+-		      (unsigned long long)gd->bd->bi_dram[bank].size);
++	len /= sizeof(*val);
++
++	for (i = 0; i < CONFIG_NR_DRAM_BANKS && len >= cells;
++	     i++, len -= cells) {
++		gd->bd->bi_dram[i].start = fdtdec_get_number(val, ac);
++		val += ac;
++		gd->bd->bi_dram[i].size = fdtdec_get_number(val, sc);
++		val += sc;
++
++		debug("DRAM bank %d: start = %08lx, size = %08lx\n",
++		      i, (unsigned long)gd->bd->bi_dram[i].start,
++		      (unsigned long)gd->bd->bi_dram[i].size);
+ 	}
+ }
+ 
+ int dram_init(void)
+ {
+-	int node, len;
+-	const void *blob = gd->fdt_blob;
+-	const u32 *cell;
+-
+-	memset(&tmp, 0, sizeof(tmp));
+-
+-	/* find or create "/memory" node. */
+-	node = fdt_subnode_offset(blob, 0, "memory");
+-	if (node < 0) {
+-		printf("%s: Can't get memory node\n", __func__);
+-		return node;
++	const void *fdt = gd->fdt_blob;
++	const fdt32_t *val;
++	int ac, sc, len;
++
++	ac = fdt_address_cells(fdt, 0);
++	sc = fdt_size_cells(fdt, 0);
++	if (ac < 0 || sc < 1 || sc > 2) {
++		printf("invalid address/size cells\n");
++		return -EINVAL;
+ 	}
+ 
+-	/* Get pointer to cells and lenght of it */
+-	cell = fdt_getprop(blob, node, "reg", &len);
+-	if (!cell) {
+-		printf("%s: Can't get reg property\n", __func__);
+-		return -1;
+-	}
++	val = get_memory_reg_prop(fdt, &len);
++	if (len / sizeof(*val) < ac + sc)
++		return -EINVAL;
++
++	val += ac;
+ 
+-	gd->ram_size = fdt_get_reg(blob, node, &tmp, cell, len / FDT_REG_SIZE);
++	gd->ram_size = fdtdec_get_number(val, sc);
+ 
+-	debug("%s: Initial DRAM size %llx\n", __func__, (u64)gd->ram_size);
++	debug("DRAM size = %08lx\n", (unsigned long)gd->ram_size);
+ 
+ 	zynq_ddrc_init();
+ 
+-- 
+2.10.2
+
diff --git a/recipes-bsp/u-boot/u-boot-xlnx_2016.07.bb b/recipes-bsp/u-boot/u-boot-xlnx_2016.07.bb
index 61f1cb793b..6e393f1b81 100644
--- a/recipes-bsp/u-boot/u-boot-xlnx_2016.07.bb
+++ b/recipes-bsp/u-boot/u-boot-xlnx_2016.07.bb
@@ -8,6 +8,7 @@ PV = "v2016.07-xilinx-${XILINX_RELEASE_VERSION}+git${SRCPV}"
 
 FILESEXTRAPATHS_prepend := "${THISDIR}/u-boot-xlnx:"
 
+SRC_URI_append = " file://ARM-zynq-Replace-dram_init-functions-with-board_init.patch"
 SRC_URI_append_kc705-microblazeel = " file://microblaze-kc705-Convert-microblaze-generic-to-k.patch"
 
 LICENSE = "GPLv2+"
-- 
2.10.2




More information about the meta-xilinx mailing list