From 758b39979d8a70b91f70d6684119156032841c4a Mon Sep 17 00:00:00 2001 From: John Rigby Date: Wed, 13 Oct 2010 13:57:31 -0600 Subject: common/image.c fix length calculation in boot_relocate_fdt boot_relocate_fdt is called on platforms with CONFIG_SYS_BOOTMAPSZ defined to relocate the device tree blob to be inside the boot map area between bootmap_base and bootmap_base+CONFIG_SYS_BOOTMAPSZ. For the case where the blob needs to be relocated, space is allocated inside the bootmap by calling lmb_alloc_base with size passed in plus some padding: of_len = *of_size + CONFIG_SYS_FDT_PAD; For the case where the blob is already inside the bounds of the boot map area, lmb_reserve is called to reserve the the space where the blob is already residing. The calculation for this case is currently: of_len = (CONFIG_SYS_BOOTMAPSZ + bootmap_base) - (ulong)fdt_blob; This is wrong because it reserves all the space in the boot map area from the blob to the end ignoring completely the actual size. The worst case is where the blob is at the beginning and the entire boot map area get reserved. Fix this by changing the length calculation to this: of_len = *of_size + CONFIG_SYS_FDT_PAD; This bug has likely never manifested itself because bootm has never been called with the fdt blob already in the bootmap area. In my testing on an OMAP3 beagle board I initially worked around the bug by simply moving the initial location of the fdt blob. I have tested with the new calculation with the fdt blob both inside and outside the boot map area. Signed-off-by: John Rigby --- common/image.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'common') diff --git a/common/image.c b/common/image.c index 3a2f25e..f59904d 100644 --- a/common/image.c +++ b/common/image.c @@ -1252,7 +1252,7 @@ int boot_relocate_fdt (struct lmb *lmb, ulong bootmap_base, *of_size = of_len; } else { *of_flat_tree = fdt_blob; - of_len = (CONFIG_SYS_BOOTMAPSZ + bootmap_base) - (ulong)fdt_blob; + of_len = *of_size + CONFIG_SYS_FDT_PAD; lmb_reserve(lmb, (ulong)fdt_blob, of_len); fdt_set_totalsize(*of_flat_tree, of_len); -- cgit v1.1 From d1263fced226c2fbe2554b260ea51a7b2ce58b33 Mon Sep 17 00:00:00 2001 From: John Rigby Date: Wed, 13 Oct 2010 13:57:32 -0600 Subject: common/image.c remove extra calls to be32_to_cpu in boot_get_fdt fdt_totalsize returns size in cpu endian so don't call be32_to_cpu on the result. This was harmless on big endian platforms but not on little endian ARMs. Signed-off-by: John Rigby --- common/image.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'common') diff --git a/common/image.c b/common/image.c index f59904d..dda3025 100644 --- a/common/image.c +++ b/common/image.c @@ -1561,7 +1561,7 @@ int boot_get_fdt (int flag, int argc, char * const argv[], bootm_headers_t *imag goto error; } - if (be32_to_cpu (fdt_totalsize (fdt_blob)) != fdt_len) { + if (fdt_totalsize(fdt_blob) != fdt_len) { fdt_error ("fdt size != image size"); goto error; } @@ -1575,7 +1575,7 @@ int boot_get_fdt (int flag, int argc, char * const argv[], bootm_headers_t *imag } *of_flat_tree = fdt_blob; - *of_size = be32_to_cpu (fdt_totalsize (fdt_blob)); + *of_size = fdt_totalsize(fdt_blob); debug (" of_flat_tree at 0x%08lx size 0x%08lx\n", (ulong)*of_flat_tree, *of_size); -- cgit v1.1 From a6bd9e83abc811d5cade88cb5e7caf93b4f7abe1 Mon Sep 17 00:00:00 2001 From: John Rigby Date: Wed, 13 Oct 2010 13:57:33 -0600 Subject: FDT: Add fixup support for multiple banks of memory Add fdt_fixup_memory_banks and reimplement fdt_fixup_memory using it. Tested on OMAP3 beagle board with two banks of memory. Signed-off-by: John Rigby CC: Jerry Van Baren Acked-by: Gerald Van Baren --- common/fdt_support.c | 86 ++++++++++++++++++++++++++++------------------------ 1 file changed, 46 insertions(+), 40 deletions(-) (limited to 'common') diff --git a/common/fdt_support.c b/common/fdt_support.c index b8a3dc9..90e9097 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -362,10 +362,40 @@ void do_fixup_by_compat_u32(void *fdt, const char *compat, do_fixup_by_compat(fdt, compat, prop, &val, 4, create); } -int fdt_fixup_memory(void *blob, u64 start, u64 size) +/* + * Get cells len in bytes + * if #NNNN-cells property is 2 then len is 8 + * otherwise len is 4 + */ +static int get_cells_len(void *blob, char *nr_cells_name) +{ + const u32 *cell; + + cell = fdt_getprop(blob, 0, nr_cells_name, NULL); + if (cell && *cell == 2) + return 8; + + return 4; +} + +/* + * Write a 4 or 8 byte big endian cell + */ +static void write_cell(u8 *addr, u64 val, int size) { - int err, nodeoffset, len = 0; - u8 tmp[16]; + int shift = (size - 1) * 8; + while (size-- > 0) { + *addr++ = (val >> shift) & 0xff; + shift -= 8; + } +} + +int fdt_fixup_memory_banks(void *blob, u64 start[], u64 size[], int banks) +{ + int err, nodeoffset; + int addr_cell_len, size_cell_len, len; + u8 tmp[banks * 8]; + int bank; const u32 *addrcell, *sizecell; err = fdt_check_header(blob); @@ -391,44 +421,15 @@ int fdt_fixup_memory(void *blob, u64 start, u64 size) return err; } - addrcell = fdt_getprop(blob, 0, "#address-cells", NULL); - /* use shifts and mask to ensure endianness */ - if ((addrcell) && (*addrcell == 2)) { - tmp[0] = (start >> 56) & 0xff; - tmp[1] = (start >> 48) & 0xff; - tmp[2] = (start >> 40) & 0xff; - tmp[3] = (start >> 32) & 0xff; - tmp[4] = (start >> 24) & 0xff; - tmp[5] = (start >> 16) & 0xff; - tmp[6] = (start >> 8) & 0xff; - tmp[7] = (start ) & 0xff; - len = 8; - } else { - tmp[0] = (start >> 24) & 0xff; - tmp[1] = (start >> 16) & 0xff; - tmp[2] = (start >> 8) & 0xff; - tmp[3] = (start ) & 0xff; - len = 4; - } + addr_cell_len = get_cells_len(blob, "#address-cells"); + size_cell_len = get_cells_len(blob, "#size-cells"); - sizecell = fdt_getprop(blob, 0, "#size-cells", NULL); - /* use shifts and mask to ensure endianness */ - if ((sizecell) && (*sizecell == 2)) { - tmp[0+len] = (size >> 56) & 0xff; - tmp[1+len] = (size >> 48) & 0xff; - tmp[2+len] = (size >> 40) & 0xff; - tmp[3+len] = (size >> 32) & 0xff; - tmp[4+len] = (size >> 24) & 0xff; - tmp[5+len] = (size >> 16) & 0xff; - tmp[6+len] = (size >> 8) & 0xff; - tmp[7+len] = (size ) & 0xff; - len += 8; - } else { - tmp[0+len] = (size >> 24) & 0xff; - tmp[1+len] = (size >> 16) & 0xff; - tmp[2+len] = (size >> 8) & 0xff; - tmp[3+len] = (size ) & 0xff; - len += 4; + for (bank = 0, len = 0; bank < banks; bank++) { + write_cell(tmp + len, start[bank], addr_cell_len); + len += addr_cell_len; + + write_cell(tmp + len, size[bank], size_cell_len); + len += size_cell_len; } err = fdt_setprop(blob, nodeoffset, "reg", tmp, len); @@ -440,6 +441,11 @@ int fdt_fixup_memory(void *blob, u64 start, u64 size) return 0; } +int fdt_fixup_memory(void *blob, u64 start, u64 size) +{ + return fdt_fixup_memory_banks(blob, &start, &size, 1); +} + void fdt_fixup_ethernet(void *fdt) { int node, i, j; -- cgit v1.1 From 5a75e121075a63f312ae07409477b6f686840a93 Mon Sep 17 00:00:00 2001 From: John Rigby Date: Wed, 13 Oct 2010 13:57:34 -0600 Subject: FDT: only call boot_get_fdt from generic code All arches except nios2 and microblaze call boot_get_fdt from bootm_start in common/cmd_bootm.c. Having nios2 and microblaze do so as well removes code from their respective do_bootm_linux routines and allows removal of a nasty ifdef from bootm_start. In the case where boot_get_fdt returns an error bootm_start returns and the platform specific do_bootm_linux routines will never get called. Also only check argv[3] for an fdt addr if argc > 3 first. This is already the case for nios2. Signed-off-by: John Rigby CC: Scott McNutt CC: Michal Simek CC: Thomas Chou Acked-by: Wolfgang Denk Acked-by: Michal Simek Tested-by: Thomas Chou --- common/cmd_bootm.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'common') diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index db59e6f..25bc39c 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -308,7 +308,6 @@ static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[] } #if defined(CONFIG_OF_LIBFDT) -#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_SPARC) /* find flattened device tree */ ret = boot_get_fdt (flag, argc, argv, &images, &images.ft_addr, &images.ft_len); @@ -319,7 +318,6 @@ static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[] set_working_fdt_addr(images.ft_addr); #endif -#endif } images.os.start = (ulong)os_hdr; -- cgit v1.1 From fca43cc8018327cbe13e943932fbf75772275192 Mon Sep 17 00:00:00 2001 From: John Rigby Date: Wed, 13 Oct 2010 13:57:35 -0600 Subject: boot: change some arch ifdefs to feature ifdefs The routines boot_ramdisk_high, boot_get_cmdline and boot_get_kbd are currently enabled by various combinations of CONFIG_M68K, CONFIG_POWERPC and CONFIG_SPARC. Use CONFIG_SYS_BOOT_ defines instead. CONFIG_SYS_BOOT_RAMDISK_HIGH CONFIG_SYS_BOOT_GET_CMDLINE CONFIG_SYS_BOOT_GET_KBD Define these as appropriate in arch/include/asm/config.h files. Signed-off-by: John Rigby Acked-by: Wolfgang Denk --- common/cmd_bootm.c | 4 ++-- common/image.c | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'common') diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 25bc39c..ce3c77c 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -472,7 +472,7 @@ static int bootm_start_standalone(ulong iflag, int argc, char * const argv[]) static cmd_tbl_t cmd_bootm_sub[] = { U_BOOT_CMD_MKENT(start, 0, 1, (void *)BOOTM_STATE_START, "", ""), U_BOOT_CMD_MKENT(loados, 0, 1, (void *)BOOTM_STATE_LOADOS, "", ""), -#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_SPARC) +#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH U_BOOT_CMD_MKENT(ramdisk, 0, 1, (void *)BOOTM_STATE_RAMDISK, "", ""), #endif #ifdef CONFIG_OF_LIBFDT @@ -528,7 +528,7 @@ int do_bootm_subcommand (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv lmb_reserve(&images.lmb, images.os.load, (load_end - images.os.load)); break; -#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_SPARC) +#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH case BOOTM_STATE_RAMDISK: { ulong rd_len = images.rd_end - images.rd_start; diff --git a/common/image.c b/common/image.c index dda3025..385464d 100644 --- a/common/image.c +++ b/common/image.c @@ -992,7 +992,7 @@ int boot_get_ramdisk (int argc, char * const argv[], bootm_headers_t *images, return 0; } -#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_SPARC) +#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH /** * boot_ramdisk_high - relocate init ramdisk * @lmb: pointer to lmb handle, will be used for memory mgmt @@ -1081,7 +1081,7 @@ int boot_ramdisk_high (struct lmb *lmb, ulong rd_data, ulong rd_len, error: return -1; } -#endif /* defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_SPARC) */ +#endif /* CONFIG_SYS_BOOT_RAMDISK_HIGH */ #ifdef CONFIG_OF_LIBFDT static void fdt_error (const char *msg) @@ -1588,7 +1588,7 @@ error: } #endif /* CONFIG_OF_LIBFDT */ -#if defined(CONFIG_PPC) || defined(CONFIG_M68K) +#ifdef CONFIG_SYS_BOOT_GET_CMDLINE /** * boot_get_cmdline - allocate and initialize kernel cmdline * @lmb: pointer to lmb handle, will be used for memory mgmt @@ -1630,7 +1630,9 @@ int boot_get_cmdline (struct lmb *lmb, ulong *cmd_start, ulong *cmd_end, return 0; } +#endif /* CONFIG_SYS_BOOT_GET_CMDLINE */ +#ifdef CONFIG_SYS_BOOT_GET_KBD /** * boot_get_kbd - allocate and initialize kernel copy of board info * @lmb: pointer to lmb handle, will be used for memory mgmt @@ -1663,7 +1665,7 @@ int boot_get_kbd (struct lmb *lmb, bd_t **kbd, ulong bootmap_base) return 0; } -#endif /* CONFIG_PPC || CONFIG_M68K */ +#endif /* CONFIG_SYS_BOOT_GET_KBD */ #endif /* !USE_HOSTCC */ #if defined(CONFIG_FIT) -- cgit v1.1 From dd88d79e317d4bd98be1410e526ea2ab486712ca Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 18 Jul 2010 04:49:18 +0200 Subject: common: Enable serial for PXA250 Signed-off-by: Marek Vasut --- common/serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'common') diff --git a/common/serial.c b/common/serial.c index 7bebc12..c3323ea 100644 --- a/common/serial.c +++ b/common/serial.c @@ -30,7 +30,7 @@ DECLARE_GLOBAL_DATA_PTR; static struct serial_device *serial_devices = NULL; static struct serial_device *serial_current = NULL; -#if !defined(CONFIG_LWMON) && !defined(CONFIG_PXA27X) +#if !defined(CONFIG_LWMON) && !defined(CONFIG_PXA250) && !defined(CONFIG_PXA27X) struct serial_device *__default_serial_console (void) { #if defined(CONFIG_8xx_CONS_SMC1) || defined(CONFIG_8xx_CONS_SMC2) -- cgit v1.1