[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