aboutsummaryrefslogtreecommitdiffstats
path: root/recipes-bsp/u-boot/u-boot/0002-ARM-zynq-Replace-board-specific-with-generic-memory-.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes-bsp/u-boot/u-boot/0002-ARM-zynq-Replace-board-specific-with-generic-memory-.patch')
-rw-r--r--recipes-bsp/u-boot/u-boot/0002-ARM-zynq-Replace-board-specific-with-generic-memory-.patch170
1 files changed, 170 insertions, 0 deletions
diff --git a/recipes-bsp/u-boot/u-boot/0002-ARM-zynq-Replace-board-specific-with-generic-memory-.patch b/recipes-bsp/u-boot/u-boot/0002-ARM-zynq-Replace-board-specific-with-generic-memory-.patch
new file mode 100644
index 00000000..41806966
--- /dev/null
+++ b/recipes-bsp/u-boot/u-boot/0002-ARM-zynq-Replace-board-specific-with-generic-memory-.patch
@@ -0,0 +1,170 @@
+From de9bf1b591a80ef8fce8cad5c3d5a1139d136a77 Mon Sep 17 00:00:00 2001
+From: Nathan Rossi <nathan@nathanrossi.com>
+Date: Mon, 19 Dec 2016 00:03:34 +1000
+Subject: [PATCH 2/3] ARM: zynq: Replace board specific with generic memory
+ bank decoding
+
+The dram_init and dram_init_banksize functions were using a board
+specific implementation for decoding the memory banks from the fdt. This
+board specific implementation uses a static variable 'tmp' which makes
+these functions unsafe for execution from within the board_init_f
+context.
+
+This unsafe use of a static variable was causing a specific bug when
+using the zynq_zybo configuration, U-Boot would generate the following
+error during image load. This was caused due to dram_init overwriting
+the relocations for the 'image' variable within the do_bootm function.
+Out of coincidence the un-initialized memory has a compression type
+which is the same as the value for the relocation type R_ARM_RELATIVE.
+
+ Uncompressing Invalid Image ... Unimplemented compression type 23
+
+It should be noted that this is just one way the issue could surface,
+other cases my not be observed in normal boot flow. Depending on the
+size of various sections, and location of relocations within __rel_dyn
+and the compiler/linker the outcome of this bug can differ greatly.
+
+This change makes the dram_init* functions use a generic implementation
+of decoding and populating memory bank and size data.
+
+Signed-off-by: Nathan Rossi <nathan@nathanrossi.com>
+Fixes: 758f29d0f8 ("ARM: zynq: Support systems with more memory banks")
+Cc: Michal Simek <monstr@monstr.eu>
+Signed-off-by: Michal Simek <michal.simek@xilinx.com>
+Upstream-Status: Backport
+---
+ board/xilinx/zynq/board.c | 112 ++--------------------------------------------
+ 1 file changed, 3 insertions(+), 109 deletions(-)
+
+diff --git a/board/xilinx/zynq/board.c b/board/xilinx/zynq/board.c
+index 2c86940957..5cd9bbf711 100644
+--- a/board/xilinx/zynq/board.c
++++ b/board/xilinx/zynq/board.c
+@@ -124,121 +124,15 @@ 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)
+-{
+- 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));
+- }
+-
+- /* Return the first address size */
+- return *(phys_size_t *)((char *)buf + sizeof(phys_addr_t));
+-}
+-
+-#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];
+-
+ void dram_init_banksize(void)
+ {
+- int bank;
+-
+- memcpy(&gd->bd->bi_dram[0], &tmp, sizeof(tmp));
+-
+- 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);
+- }
++ fdtdec_setup_memory_banksize();
+ }
+
+ 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;
+- }
+-
+- /* 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;
+- }
+-
+- gd->ram_size = fdt_get_reg(blob, node, &tmp, cell, len / FDT_REG_SIZE);
+-
+- debug("%s: Initial DRAM size %llx\n", __func__, (u64)gd->ram_size);
++ if (fdtdec_setup_memory_size() != 0)
++ return -EINVAL;
+
+ zynq_ddrc_init();
+
+--
+2.11.0
+