[U-Boot-Users] [PATCH 0/9] [new uImage] Add support for booting images at non-zero addresses

This is an updated set of patches that clean up some of the code in the new uImage branch of u-boot-testing and add the ability to boot images at non-zero addresses and constrain the locations the boot images use on PPC hosts.
This work is also availabie in the new-image branch of: git://git.kernel.org/pub/scm/boot/u-boot/galak/u-boot.git new-image
- k

We don't actually need the kdb param as we are just using it to get bd->bi_memsize which we can get from gd->bd->bi_memsize. Also, if we boot via OF we might not actually fill out a kdb.
Signed-off-by: Kumar Gala galak@kernel.crashing.org --- common/image.c | 9 ++++----- include/image.h | 2 +- lib_m68k/bootm.c | 3 +-- lib_ppc/bootm.c | 3 +-- 4 files changed, 7 insertions(+), 10 deletions(-)
diff --git a/common/image.c b/common/image.c index 39e5f23..46cecef 100644 --- a/common/image.c +++ b/common/image.c @@ -495,7 +495,6 @@ void get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], * ramdisk_high - relocate init ramdisk * @rd_data: ramdisk data start address * @rd_len: ramdisk data length - * @kbd: kernel board info copy (within BOOTMAPSZ boundary) * @sp_limit: stack pointer limit (including BOOTMAPSZ) * @sp: current stack pointer * @initrd_start: pointer to a ulong variable, will hold final init ramdisk @@ -513,7 +512,7 @@ void get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], * - returns new allc_current, next free address below BOOTMAPSZ */ ulong ramdisk_high (ulong alloc_current, ulong rd_data, ulong rd_len, - bd_t *kbd, ulong sp_limit, ulong sp, + ulong sp_limit, ulong sp, ulong *initrd_start, ulong *initrd_end) { char *s; @@ -535,9 +534,9 @@ ulong ramdisk_high (ulong alloc_current, ulong rd_data, ulong rd_len,
#ifdef CONFIG_LOGBUFFER /* Prevent initrd from overwriting logbuffer */ - if (initrd_high < (kbd->bi_memsize - LOGBUFF_LEN - LOGBUFF_OVERHEAD)) - initrd_high = kbd->bi_memsize - LOGBUFF_LEN - LOGBUFF_OVERHEAD; - debug ("## Logbuffer at 0x%08lx ", kbd->bi_memsize - LOGBUFF_LEN); + if (initrd_high < (gd->bd->bi_memsize - LOGBUFF_LEN - LOGBUFF_OVERHEAD)) + initrd_high = gd->bd->bi_memsize - LOGBUFF_LEN - LOGBUFF_OVERHEAD; + debug ("## Logbuffer at 0x%08lx ", gd->bd->bi_memsize - LOGBUFF_LEN); #endif debug ("## initrd_high = 0x%08lx, copy_to_ram = %d\n", initrd_high, initrd_copy_to_ram); diff --git a/include/image.h b/include/image.h index dbbbee9..a67489e 100644 --- a/include/image.h +++ b/include/image.h @@ -344,7 +344,7 @@ void get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
#if defined(CONFIG_PPC) || defined(CONFIG_M68K) ulong ramdisk_high (ulong alloc_current, ulong rd_data, ulong rd_len, - bd_t *kbd, ulong sp_limit, ulong sp, + ulong sp_limit, ulong sp, ulong *initrd_start, ulong *initrd_end);
ulong get_boot_sp_limit (ulong sp); diff --git a/lib_m68k/bootm.c b/lib_m68k/bootm.c index ac04da0..da76844 100644 --- a/lib_m68k/bootm.c +++ b/lib_m68k/bootm.c @@ -88,8 +88,7 @@ void do_bootm_linux(cmd_tbl_t * cmdtp, int flag,
rd_len = rd_data_end - rd_data_start; alloc_current = ramdisk_high (alloc_current, rd_data_start, rd_len, - kbd, sp_limit, get_sp (), - &initrd_start, &initrd_end); + sp_limit, get_sp (), &initrd_start, &initrd_end);
debug("## Transferring control to Linux (at address %08lx) ...\n", (ulong) kernel); diff --git a/lib_ppc/bootm.c b/lib_ppc/bootm.c index 69ec459..1f1be69 100644 --- a/lib_ppc/bootm.c +++ b/lib_ppc/bootm.c @@ -107,8 +107,7 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, rd_len = rd_data_end - rd_data_start;
alloc_current = ramdisk_high (alloc_current, rd_data_start, rd_len, - kbd, sp_limit, get_sp (), - &initrd_start, &initrd_end); + sp_limit, get_sp (), &initrd_start, &initrd_end);
#if defined(CONFIG_OF_LIBFDT) /* find flattened device tree */

If we are bootin OF style than we can skip setting up some things that are used for the old boot method.
Signed-off-by: Kumar Gala galak@kernel.crashing.org --- lib_ppc/bootm.c | 25 ++++++++++++++++++++----- 1 files changed, 20 insertions(+), 5 deletions(-)
diff --git a/lib_ppc/bootm.c b/lib_ppc/bootm.c index 1f1be69..5158ccc 100644 --- a/lib_ppc/bootm.c +++ b/lib_ppc/bootm.c @@ -71,8 +71,21 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, bd_t *kbd; void (*kernel)(bd_t *, ulong, ulong, ulong, ulong);
+ int has_of = 0; + #if defined(CONFIG_OF_LIBFDT) char *of_flat_tree; + + /* determine if we are booting w/of */ + if (argc > 3) + has_of = 1; + if (image_check_type (hdr, IH_TYPE_MULTI)) { + ulong fdt_data, fdt_len; + image_multi_getimg (hdr, 2, &fdt_data, &fdt_len); + + if (fdt_len) + has_of = 1; + } #endif
/* @@ -90,12 +103,14 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, alloc_current = sp_limit = get_boot_sp_limit(sp); debug ("=> set upper limit to 0x%08lx\n", sp_limit);
- /* allocate space and init command line */ - alloc_current = get_boot_cmdline (alloc_current, &cmd_start, &cmd_end); + if (!has_of) { + /* allocate space and init command line */ + alloc_current = get_boot_cmdline (alloc_current, &cmd_start, &cmd_end);
- /* allocate space for kernel copy of board info */ - alloc_current = get_boot_kbd (alloc_current, &kbd); - set_clocks_in_mhz(kbd); + /* allocate space for kernel copy of board info */ + alloc_current = get_boot_kbd (alloc_current, &kbd); + set_clocks_in_mhz(kbd); + }
/* find kernel */ kernel = (void (*)(bd_t *, ulong, ulong, ulong, ulong))image_get_ep (hdr);

Doing the fdt before the ramdisk allows us to grow the fdt w/o concern however it does mean we have to go in and fixup the initrd info since we don't know where it will be.
Signed-off-by: Kumar Gala galak@kernel.crashing.org --- lib_ppc/bootm.c | 39 +++++++++++++++++++++++++++++++++++---- 1 files changed, 35 insertions(+), 4 deletions(-)
diff --git a/lib_ppc/bootm.c b/lib_ppc/bootm.c index 5158ccc..99d32eb 100644 --- a/lib_ppc/bootm.c +++ b/lib_ppc/bootm.c @@ -71,6 +71,7 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, bd_t *kbd; void (*kernel)(bd_t *, ulong, ulong, ulong, ulong);
+ int ret; int has_of = 0;
#if defined(CONFIG_OF_LIBFDT) @@ -121,9 +122,6 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag,
rd_len = rd_data_end - rd_data_start;
- alloc_current = ramdisk_high (alloc_current, rd_data_start, rd_len, - sp_limit, get_sp (), &initrd_start, &initrd_end); - #if defined(CONFIG_OF_LIBFDT) /* find flattened device tree */ alloc_current = get_fdt (alloc_current, @@ -134,7 +132,8 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, * if the user wants it (the logic is in the subroutines). */ if (of_flat_tree) { - if (fdt_chosen(of_flat_tree, initrd_start, initrd_end, 0) < 0) { + /* pass in dummy initrd info, we'll fix up later */ + if (fdt_chosen(of_flat_tree, rd_data_start, rd_data_end, 0) < 0) { fdt_error ("/chosen node create failed"); do_reset (cmdtp, flag, argc, argv); } @@ -157,6 +156,38 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, } #endif /* CONFIG_OF_LIBFDT */
+ alloc_current = ramdisk_high (alloc_current, rd_data_start, rd_len, + sp_limit, get_sp (), &initrd_start, &initrd_end); + +#if defined(CONFIG_OF_LIBFDT) + /* fixup the initrd now that we know where it should be */ + if ((of_flat_tree) && (initrd_start && initrd_end)) { + uint64_t addr, size; + int total = fdt_num_mem_rsv(of_flat_tree); + int j; + + /* Look for the dummy entry and delete it */ + for (j = 0; j < total; j++) { + fdt_get_mem_rsv(of_flat_tree, j, &addr, &size); + if (addr == rd_data_start) { + fdt_del_mem_rsv(of_flat_tree, j); + break; + } + } + + ret = fdt_add_mem_rsv(of_flat_tree, initrd_start, + initrd_end - initrd_start + 1); + if (ret < 0) { + printf("fdt_chosen: %s\n", fdt_strerror(ret)); + do_reset (cmdtp, flag, argc, argv); + } + + do_fixup_by_path_u32(of_flat_tree, "/chosen", + "linux,initrd-start", initrd_start, 0); + do_fixup_by_path_u32(of_flat_tree, "/chosen", + "linux,initrd-end", initrd_end, 0); + } +#endif debug ("## Transferring control to Linux (at address %08lx) ...\n", (ulong)kernel);

Changed image_get_ramdisk() to just return NULL on error and have get_ramdisk() propogate that error to the caller. It's left to the caller to call do_reset() if it wants to.
Also moved calling do_reset() in get_fdt() on ppc to a common location. In the future we will change get_fdt() to return success/failure and not call do_reset() at all.
Signed-off-by: Kumar Gala galak@kernel.crashing.org --- common/image.c | 25 ++++++++++++++++--------- include/image.h | 2 +- lib_m68k/bootm.c | 15 +++++++++++++-- lib_ppc/bootm.c | 46 +++++++++++++++++++++++++++++----------------- 4 files changed, 59 insertions(+), 29 deletions(-)
diff --git a/common/image.c b/common/image.c index 46cecef..0a74083 100644 --- a/common/image.c +++ b/common/image.c @@ -41,8 +41,6 @@ #include <logbuff.h> #endif
-extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); - #ifdef CONFIG_CMD_BDI extern int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); #endif @@ -324,7 +322,7 @@ const char* image_get_comp_name (uint8_t comp) * * returns: * pointer to a ramdisk image header, if image was found and valid - * otherwise, board is reset + * otherwise, return NULL */ image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], @@ -348,13 +346,13 @@ image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, if (!image_check_magic (rd_hdr)) { puts ("Bad Magic Number\n"); show_boot_progress (-10); - do_reset (cmdtp, flag, argc, argv); + return NULL; }
if (!image_check_hcrc (rd_hdr)) { puts ("Bad Header Checksum\n"); show_boot_progress (-11); - do_reset (cmdtp, flag, argc, argv); + return NULL; }
show_boot_progress (10); @@ -377,7 +375,7 @@ image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, if (!image_check_dcrc_wd (rd_hdr, CHUNKSZ)) { puts ("Bad Data CRC\n"); show_boot_progress (-12); - do_reset (cmdtp, flag, argc, argv); + return NULL; } puts("OK\n"); } @@ -390,7 +388,7 @@ image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, printf ("No Linux %s Ramdisk Image\n", image_get_arch_name(arch)); show_boot_progress (-13); - do_reset (cmdtp, flag, argc, argv); + return NULL; }
return rd_hdr; @@ -417,9 +415,10 @@ image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, * rd_start and rd_end are set to ramdisk start/end addresses if * ramdisk image is found and valid * rd_start and rd_end are set to 0 if no ramdisk exists - * board is reset if ramdisk image is found but corrupted + * return 1 if ramdisk image is found but corrupted + * */ -void get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], +int get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], image_header_t *hdr, int verify, uint8_t arch, ulong *rd_start, ulong *rd_end) { @@ -447,6 +446,12 @@ void get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], rd_hdr = image_get_ramdisk (cmdtp, flag, argc, argv, rd_addr, arch, verify);
+ if (rd_hdr == NULL) { + *rd_start = 0; + *rd_end = 0; + return 1; + } + rd_data = image_get_data (rd_hdr); rd_len = image_get_data_size (rd_hdr);
@@ -488,6 +493,8 @@ void get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], } debug (" ramdisk start = 0x%08lx, ramdisk end = 0x%08lx\n", *rd_start, *rd_end); + + return 0; }
#if defined(CONFIG_PPC) || defined(CONFIG_M68K) diff --git a/include/image.h b/include/image.h index a67489e..d35b476 100644 --- a/include/image.h +++ b/include/image.h @@ -338,7 +338,7 @@ image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], ulong rd_addr, uint8_t arch, int verify);
-void get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], +int get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], image_header_t *hdr, int verify, uint8_t arch, ulong *rd_start, ulong *rd_end);
diff --git a/lib_m68k/bootm.c b/lib_m68k/bootm.c index da76844..9a98b83 100644 --- a/lib_m68k/bootm.c +++ b/lib_m68k/bootm.c @@ -35,6 +35,8 @@
DECLARE_GLOBAL_DATA_PTR;
+extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); + #define PHYSADDR(x) x
#define LINUX_MAX_ENVS 256 @@ -51,6 +53,7 @@ void do_bootm_linux(cmd_tbl_t * cmdtp, int flag,
ulong rd_data_start, rd_data_end, rd_len; ulong initrd_start, initrd_end; + int ret;
ulong cmd_start, cmd_end; bd_t *kbd; @@ -83,8 +86,11 @@ void do_bootm_linux(cmd_tbl_t * cmdtp, int flag, (void (*)(bd_t *, ulong, ulong, ulong, ulong))image_get_ep (hdr);
/* find ramdisk */ - get_ramdisk (cmdtp, flag, argc, argv, hdr, verify, - IH_ARCH_M68K, &rd_data_start, &rd_data_end); + ret = get_ramdisk (cmdtp, flag, argc, argv, hdr, verify, + IH_ARCH_M68K, &rd_data_start, &rd_data_end); + + if (ret) + goto error;
rd_len = rd_data_end - rd_data_start; alloc_current = ramdisk_high (alloc_current, rd_data_start, rd_len, @@ -105,6 +111,11 @@ void do_bootm_linux(cmd_tbl_t * cmdtp, int flag, */ (*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end); /* does not return */ + return ; + +error: + do_reset (cmdtp, flag, argc, argv); + return ; }
static ulong get_sp (void) diff --git a/lib_ppc/bootm.c b/lib_ppc/bootm.c index 99d32eb..ec98e1b 100644 --- a/lib_ppc/bootm.c +++ b/lib_ppc/bootm.c @@ -75,7 +75,7 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int has_of = 0;
#if defined(CONFIG_OF_LIBFDT) - char *of_flat_tree; + char *of_flat_tree = NULL;
/* determine if we are booting w/of */ if (argc > 3) @@ -117,8 +117,11 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, kernel = (void (*)(bd_t *, ulong, ulong, ulong, ulong))image_get_ep (hdr);
/* find ramdisk */ - get_ramdisk (cmdtp, flag, argc, argv, hdr, verify, - IH_ARCH_PPC, &rd_data_start, &rd_data_end); + ret = get_ramdisk (cmdtp, flag, argc, argv, hdr, verify, + IH_ARCH_PPC, &rd_data_start, &rd_data_end); + + if (ret) + goto error;
rd_len = rd_data_end - rd_data_start;
@@ -135,18 +138,18 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, /* pass in dummy initrd info, we'll fix up later */ if (fdt_chosen(of_flat_tree, rd_data_start, rd_data_end, 0) < 0) { fdt_error ("/chosen node create failed"); - do_reset (cmdtp, flag, argc, argv); + goto error; } #ifdef CONFIG_OF_HAS_UBOOT_ENV if (fdt_env(of_flat_tree) < 0) { fdt_error ("/u-boot-env node create failed"); - do_reset (cmdtp, flag, argc, argv); + goto error; } #endif #ifdef CONFIG_OF_HAS_BD_T if (fdt_bd_t(of_flat_tree) < 0) { fdt_error ("/bd_t node create failed"); - do_reset (cmdtp, flag, argc, argv); + goto error; } #endif #ifdef CONFIG_OF_BOARD_SETUP @@ -179,7 +182,7 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, initrd_end - initrd_start + 1); if (ret < 0) { printf("fdt_chosen: %s\n", fdt_strerror(ret)); - do_reset (cmdtp, flag, argc, argv); + goto error; }
do_fixup_by_path_u32(of_flat_tree, "/chosen", @@ -221,6 +224,11 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, */ (*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end); /* does not return */ + return ; + +error: + do_reset (cmdtp, flag, argc, argv); + return ; }
static ulong get_sp (void) @@ -304,32 +312,32 @@ static ulong get_fdt (ulong alloc_current,
if ((load_start < image_end) && (load_end > image_start)) { fdt_error ("fdt overwritten"); - do_reset (cmdtp, flag, argc, argv); + goto error; }
puts (" Verifying Checksum ... "); if (!image_check_hcrc (fdt_hdr)) { fdt_error ("fdt header checksum invalid"); - do_reset (cmdtp, flag, argc, argv); + goto error; }
if (!image_check_dcrc (fdt_hdr)) { fdt_error ("fdt checksum invalid"); - do_reset (cmdtp, flag, argc, argv); + goto error; } puts ("OK\n");
if (!image_check_type (fdt_hdr, IH_TYPE_FLATDT)) { fdt_error ("uImage is not a fdt"); - do_reset (cmdtp, flag, argc, argv); + goto error; } if (image_get_comp (fdt_hdr) != IH_COMP_NONE) { fdt_error ("uImage is compressed"); - do_reset (cmdtp, flag, argc, argv); + goto error; } if (fdt_check_header ((char *)image_get_data (fdt_hdr)) != 0) { fdt_error ("uImage data is not a fdt"); - do_reset (cmdtp, flag, argc, argv); + goto error; }
memmove ((void *)image_get_load (fdt_hdr), @@ -339,7 +347,7 @@ static ulong get_fdt (ulong alloc_current, fdt = (char *)image_get_load (fdt_hdr); } else { fdt_error ("Did not find a Flattened Device Tree"); - do_reset (cmdtp, flag, argc, argv); + goto error; } printf (" Booting using the fdt at 0x%x\n", fdt); @@ -363,12 +371,12 @@ static ulong get_fdt (ulong alloc_current,
if (fdt_check_header (fdt) != 0) { fdt_error ("image is not a fdt"); - do_reset (cmdtp, flag, argc, argv); + goto error; }
if (be32_to_cpu (fdt_totalsize (fdt)) != fdt_len) { fdt_error ("fdt size != image size"); - do_reset (cmdtp, flag, argc, argv); + goto error; } } else { debug (" Did not find a Flattened Device Tree"); @@ -405,7 +413,7 @@ static ulong get_fdt (ulong alloc_current, err = fdt_open_into (fdt, (void *)of_start, of_len); if (err != 0) { fdt_error ("fdt move failed"); - do_reset (cmdtp, flag, argc, argv); + goto error; } puts ("OK\n");
@@ -417,5 +425,9 @@ static ulong get_fdt (ulong alloc_current, }
return new_alloc_current; + +error: + do_reset (cmdtp, flag, argc, argv); + return 1; } #endif

For historical reasons we limited the stack to 256M because some boards could only map that much via BATS. However newer boards are capable of mapping more memory (for example 85xx is capable of doing up to 2G).
Signed-off-by: Kumar Gala galak@kernel.crashing.org --- lib_ppc/board.c | 22 +++++++++++++++------- 1 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/lib_ppc/board.c b/lib_ppc/board.c index 45d1328..fbf1c5d 100644 --- a/lib_ppc/board.c +++ b/lib_ppc/board.c @@ -361,6 +361,20 @@ init_fnc_t *init_sequence[] = { NULL, /* Terminate this list */ };
+#ifndef CONFIG_MAX_MEM_MAPPED +#define CONFIG_MAX_MEM_MAPPED (256 << 20) +#endif +ulong get_effective_memsize(void) +{ +#ifndef CONFIG_VERY_BIG_RAM + return gd->ram_size; +#else + /* limit stack to what we can reasonable map */ + return ((gd->ram_size > CONFIG_MAX_MEM_MAPPED) ? + CONFIG_MAX_MEM_MAPPED : gd->ram_size); +#endif +} + /************************************************************************ * * This is the first part of the initialization sequence that is @@ -419,13 +433,7 @@ void board_init_f (ulong bootflag) */ len = (ulong)&_end - CFG_MONITOR_BASE;
-#ifndef CONFIG_VERY_BIG_RAM - addr = CFG_SDRAM_BASE + gd->ram_size; -#else - /* only allow stack below 256M */ - addr = CFG_SDRAM_BASE + - (gd->ram_size > 256 << 20) ? 256 << 20 : gd->ram_size; -#endif + addr = CFG_SDRAM_BASE + get_effective_memsize();
#ifdef CONFIG_LOGBUFFER /* reserve kernel log buffer */

Introduce the LMB lib used on PPC in the kernel as a clean way to manage the memory spaces used by various boot images and structures. This code will allow us to simplify the code in bootm and its support functions.
Also, added passing autostart flag to bootm functions. This was done since the feature was removed as part of the new uImage cleanup and rather than touching the bootm prototype twice (once for lmb and once for autostart) we just do it once.
We don't actually use either the lmb or autostart flag with this patch.
Signed-off-by: Kumar Gala galak@kernel.crashing.org --- common/cmd_bootm.c | 50 ++++++--- common/image.c | 6 + include/image.h | 1 + include/lmb.h | 54 +++++++++ lib_arm/bootm.c | 6 +- lib_avr32/bootm.c | 4 +- lib_blackfin/bootm.c | 6 +- lib_generic/Makefile | 1 + lib_generic/lmb.c | 280 ++++++++++++++++++++++++++++++++++++++++++++++++ lib_i386/bootm.c | 4 +- lib_m68k/bootm.c | 7 +- lib_microblaze/bootm.c | 6 +- lib_mips/bootm.c | 6 +- lib_nios/bootm.c | 4 +- lib_nios2/bootm.c | 4 +- lib_ppc/bootm.c | 8 +- lib_sh/bootm.c | 6 +- 17 files changed, 418 insertions(+), 35 deletions(-) create mode 100644 include/lmb.h create mode 100644 lib_generic/lmb.c
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 2ddb191..dac1dd9 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -34,6 +34,7 @@ #include <zlib.h> #include <bzlib.h> #include <environment.h> +#include <lmb.h> #include <asm/byteorder.h>
#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) @@ -90,7 +91,9 @@ extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); typedef void boot_os_fn (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], image_header_t *hdr, /* of image to boot */ - int verify); /* getenv("verify")[0] != 'n' */ + int verify, /* getenv("verify")[0] != 'n' */ + int autostart, /* getenv("autostart")[0] != 'n' */ + struct lmb *lmb);
extern boot_os_fn do_bootm_linux; static boot_os_fn do_bootm_netbsd; @@ -122,6 +125,7 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) const char *type_name; uint unc_len = CFG_BOOTM_LEN; int verify = getenv_verify(); + int autostart = getenv_autostart();
image_header_t *hdr; ulong os_data, os_len; @@ -129,6 +133,16 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) ulong image_start, image_end; ulong load_start, load_end;
+ struct lmb lmb; + + lmb_init(&lmb); + +#ifdef CFG_SDRAM_BASE + lmb_add(&lmb, CFG_SDRAM_BASE, gd->bd->bi_memsize); +#else + lmb_add(&lmb, 0, gd->bd->bi_memsize); +#endif + /* get kernel image header, start address and length */ hdr = get_kernel (cmdtp, flag, argc, argv, verify, &os_data, &os_len); @@ -228,42 +242,44 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
show_boot_progress (8);
+ lmb_reserve(&lmb, load_start, (load_end - load_start)); + switch (image_get_os (hdr)) { default: /* handled by (original) Linux case */ case IH_OS_LINUX: #ifdef CONFIG_SILENT_CONSOLE fixup_silent_linux(); #endif - do_bootm_linux (cmdtp, flag, argc, argv, hdr, verify); + do_bootm_linux (cmdtp, flag, argc, argv, hdr, verify, autostart, &lmb); break;
case IH_OS_NETBSD: - do_bootm_netbsd (cmdtp, flag, argc, argv, hdr, verify); + do_bootm_netbsd (cmdtp, flag, argc, argv, hdr, verify, autostart, &lmb); break;
#ifdef CONFIG_LYNXKDI case IH_OS_LYNXOS: - do_bootm_lynxkdi (cmdtp, flag, argc, argv, hdr, verify); + do_bootm_lynxkdi (cmdtp, flag, argc, argv, hdr, verify, autostart, &lmb); break; #endif
case IH_OS_RTEMS: - do_bootm_rtems (cmdtp, flag, argc, argv, hdr, verify); + do_bootm_rtems (cmdtp, flag, argc, argv, hdr, verify, autostart, &lmb); break;
#if defined(CONFIG_CMD_ELF) case IH_OS_VXWORKS: - do_bootm_vxworks (cmdtp, flag, argc, argv, hdr, verify); + do_bootm_vxworks (cmdtp, flag, argc, argv, hdr, verify, autostart, &lmb); break;
case IH_OS_QNX: - do_bootm_qnxelf (cmdtp, flag, argc, argv, hdr, verify); + do_bootm_qnxelf (cmdtp, flag, argc, argv, hdr, verify, autostart, &lmb); break; #endif
#ifdef CONFIG_ARTOS case IH_OS_ARTOS: - do_bootm_artos (cmdtp, flag, argc, argv, hdr, verify); + do_bootm_artos (cmdtp, flag, argc, argv, hdr, verify, autostart, &lmb); break; #endif } @@ -626,7 +642,8 @@ static void fixup_silent_linux ()
static void do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - image_header_t *hdr, int verify) + image_header_t *hdr, int verify, + int autostart, struct lmb *lmb) { void (*loader)(bd_t *, image_header_t *, char *, char *); image_header_t *img_addr; @@ -702,7 +719,8 @@ static void do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag, #ifdef CONFIG_LYNXKDI static void do_bootm_lynxkdi (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - image_header_t *hdr, int verify) + image_header_t *hdr, int verify + struct lmb *lmb) { lynxkdi_boot (hdr); } @@ -710,7 +728,8 @@ static void do_bootm_lynxkdi (cmd_tbl_t *cmdtp, int flag,
static void do_bootm_rtems (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - image_header_t *hdr, int verify) + image_header_t *hdr, int verify, + int autostart, struct lmb *lmb) { void (*entry_point)(bd_t *);
@@ -731,7 +750,8 @@ static void do_bootm_rtems (cmd_tbl_t *cmdtp, int flag, #if defined(CONFIG_CMD_ELF) static void do_bootm_vxworks (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - image_header_t *hdr, int verify) + image_header_t *hdr, int verify, + int autostart, struct lmb *lmb) { char str[80];
@@ -742,7 +762,8 @@ static void do_bootm_vxworks (cmd_tbl_t *cmdtp, int flag,
static void do_bootm_qnxelf(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - image_header_t *hdr, int verify) + image_header_t *hdr, int verify, + int autostart, struct lmb *lmb) { char *local_args[2]; char str[16]; @@ -757,7 +778,8 @@ static void do_bootm_qnxelf(cmd_tbl_t *cmdtp, int flag, #if defined(CONFIG_ARTOS) && defined(CONFIG_PPC) static void do_bootm_artos (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - image_header_t *hdr, int verify) + image_header_t *hdr, int verify + struct lmb *lmb) { ulong top; char *s, *cmdline; diff --git a/common/image.c b/common/image.c index 0a74083..dfe2004 100644 --- a/common/image.c +++ b/common/image.c @@ -112,6 +112,12 @@ int getenv_verify (void) return (s && (*s == 'n')) ? 0 : 1; }
+int getenv_autostart (void) +{ + char *s = getenv ("autostart"); + return (s && (*s == 'n')) ? 0 : 1; +} + void memmove_wd (void *to, void *from, size_t len, ulong chunksz) { #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) diff --git a/include/image.h b/include/image.h index d35b476..4cf9567 100644 --- a/include/image.h +++ b/include/image.h @@ -272,6 +272,7 @@ int image_check_dcrc (image_header_t *hdr); #ifndef USE_HOSTCC int image_check_dcrc_wd (image_header_t *hdr, ulong chunksize); int getenv_verify (void); +int getenv_autostart (void); void memmove_wd (void *to, void *from, size_t len, ulong chunksz); #endif
diff --git a/include/lmb.h b/include/lmb.h new file mode 100644 index 0000000..cc64cbb --- /dev/null +++ b/include/lmb.h @@ -0,0 +1,54 @@ +#ifndef _LINUX_LMB_H +#define _LINUX_LMB_H +#ifdef __KERNEL__ + +#include <asm/types.h> +/* + * Logical memory blocks. + * + * Copyright (C) 2001 Peter Bergner, IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#define MAX_LMB_REGIONS 8 + +struct lmb_property { + ulong base; + ulong size; +}; + +struct lmb_region { + unsigned long cnt; + ulong size; + struct lmb_property region[MAX_LMB_REGIONS+1]; +}; + +struct lmb { + struct lmb_region memory; + struct lmb_region reserved; +}; + +extern struct lmb lmb; + +extern void lmb_init(struct lmb *lmb); +extern long lmb_add(struct lmb *lmb, ulong base, ulong size); +extern long lmb_reserve(struct lmb *lmb, ulong base, ulong size); +extern ulong lmb_alloc(struct lmb *lmb, ulong size, ulong align); +extern ulong lmb_alloc_base(struct lmb *lmb, ulong size, ulong align, ulong max_addr); +extern ulong __lmb_alloc_base(struct lmb *lmb, ulong size, ulong align, ulong max_addr); +extern int lmb_is_reserved(struct lmb *lmb, ulong addr); + +extern void lmb_dump_all(struct lmb *lmb); + +static inline ulong +lmb_size_bytes(struct lmb_region *type, unsigned long region_nr) +{ + return type->region[region_nr].size; +} +#endif /* __KERNEL__ */ + +#endif /* _LINUX_LMB_H */ diff --git a/lib_arm/bootm.c b/lib_arm/bootm.c index 529b097..c850ae3 100644 --- a/lib_arm/bootm.c +++ b/lib_arm/bootm.c @@ -25,6 +25,7 @@ #include <command.h> #include <image.h> #include <zlib.h> +#include <lmb.h> #include <asm/byteorder.h>
DECLARE_GLOBAL_DATA_PTR; @@ -60,8 +61,9 @@ static void setup_videolfb_tag (gd_t *gd); static struct tag *params; #endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */
-void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - image_header_t *hdr, int verify) +void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], + image_header_t *hdr, int verify, int autostart, + struct lmb *lmb) { ulong initrd_start, initrd_end; void (*theKernel)(int zero, int arch, uint params); diff --git a/lib_avr32/bootm.c b/lib_avr32/bootm.c index a934cae..8bfd2b5 100644 --- a/lib_avr32/bootm.c +++ b/lib_avr32/bootm.c @@ -23,6 +23,7 @@ #include <command.h> #include <image.h> #include <zlib.h> +#include <lmb.h> #include <asm/byteorder.h> #include <asm/addrspace.h> #include <asm/io.h> @@ -172,7 +173,8 @@ static void setup_end_tag(struct tag *params) }
void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - image_header_t *hdr, int verify) + image_header_t *hdr, int verify, int autostart, + struct lmb *lmb) { ulong initrd_start, initrd_end;
diff --git a/lib_blackfin/bootm.c b/lib_blackfin/bootm.c index 6299415..edb54e4 100644 --- a/lib_blackfin/bootm.c +++ b/lib_blackfin/bootm.c @@ -31,6 +31,7 @@ #include <command.h> #include <image.h> #include <zlib.h> +#include <lmb.h> #include <asm/byteorder.h>
#define LINUX_MAX_ENVS 256 @@ -46,8 +47,9 @@ extern void flush_instruction_cache(void); extern void flush_data_cache(void); static char *make_command_line(void);
-void do_bootm_linux(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[], - image_header_t *hdr, int verify) +void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], + image_header_t *hdr, int verify, int autostart, + struct lmb *lmb) { int (*appl) (char *cmdline); char *cmdline; diff --git a/lib_generic/Makefile b/lib_generic/Makefile index 9713353..b10793b 100644 --- a/lib_generic/Makefile +++ b/lib_generic/Makefile @@ -34,6 +34,7 @@ COBJS-y += crc32.o COBJS-y += ctype.o COBJS-y += display_options.o COBJS-y += div64.o +COBJS-y += lmb.o COBJS-y += ldiv.o COBJS-y += sha1.o COBJS-y += string.o diff --git a/lib_generic/lmb.c b/lib_generic/lmb.c new file mode 100644 index 0000000..3b8c805 --- /dev/null +++ b/lib_generic/lmb.c @@ -0,0 +1,280 @@ +/* + * Procedures for maintaining information about logical memory blocks. + * + * Peter Bergner, IBM Corp. June 2001. + * Copyright (C) 2001 Peter Bergner. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <common.h> +#include <lmb.h> + +#define LMB_ALLOC_ANYWHERE 0 + +void lmb_dump_all(struct lmb *lmb) +{ +#ifdef DEBUG + unsigned long i; + + debug("lmb_dump_all:\n"); + debug(" memory.cnt = 0x%lx\n", lmb->memory.cnt); + debug(" memory.size = 0x%08x\n", lmb->memory.size); + for (i=0; i < lmb->memory.cnt ;i++) { + debug(" memory.reg[0x%x].base = 0x%08x\n", i, + lmb->memory.region[i].base); + debug(" .size = 0x%08x\n", + lmb->memory.region[i].size); + } + + debug("\n reserved.cnt = 0x%lx\n", lmb->reserved.cnt); + debug(" reserved.size = 0x%08x\n", lmb->reserved.size); + for (i=0; i < lmb->reserved.cnt ;i++) { + debug(" reserved.reg[0x%x].base = 0x%08x\n", i, + lmb->reserved.region[i].base); + debug(" .size = 0x%08x\n", + lmb->reserved.region[i].size); + } +#endif /* DEBUG */ +} + +static unsigned long lmb_addrs_overlap(ulong base1, + ulong size1, ulong base2, ulong size2) +{ + return ((base1 < (base2+size2)) && (base2 < (base1+size1))); +} + +static long lmb_addrs_adjacent(ulong base1, ulong size1, + ulong base2, ulong size2) +{ + if (base2 == base1 + size1) + return 1; + else if (base1 == base2 + size2) + return -1; + + return 0; +} + +static long lmb_regions_adjacent(struct lmb_region *rgn, + unsigned long r1, unsigned long r2) +{ + ulong base1 = rgn->region[r1].base; + ulong size1 = rgn->region[r1].size; + ulong base2 = rgn->region[r2].base; + ulong size2 = rgn->region[r2].size; + + return lmb_addrs_adjacent(base1, size1, base2, size2); +} + +static void lmb_remove_region(struct lmb_region *rgn, unsigned long r) +{ + unsigned long i; + + for (i = r; i < rgn->cnt - 1; i++) { + rgn->region[i].base = rgn->region[i + 1].base; + rgn->region[i].size = rgn->region[i + 1].size; + } + rgn->cnt--; +} + +/* Assumption: base addr of region 1 < base addr of region 2 */ +static void lmb_coalesce_regions(struct lmb_region *rgn, + unsigned long r1, unsigned long r2) +{ + rgn->region[r1].size += rgn->region[r2].size; + lmb_remove_region(rgn, r2); +} + +void lmb_init(struct lmb *lmb) +{ + /* Create a dummy zero size LMB which will get coalesced away later. + * This simplifies the lmb_add() code below... + */ + lmb->memory.region[0].base = 0; + lmb->memory.region[0].size = 0; + lmb->memory.cnt = 1; + lmb->memory.size = 0; + + /* Ditto. */ + lmb->reserved.region[0].base = 0; + lmb->reserved.region[0].size = 0; + lmb->reserved.cnt = 1; + lmb->reserved.size = 0; +} + +/* This routine called with relocation disabled. */ +static long lmb_add_region(struct lmb_region *rgn, ulong base, ulong size) +{ + unsigned long coalesced = 0; + long adjacent, i; + + if ((rgn->cnt == 1) && (rgn->region[0].size == 0)) { + rgn->region[0].base = base; + rgn->region[0].size = size; + return 0; + } + + /* First try and coalesce this LMB with another. */ + for (i=0; i < rgn->cnt; i++) { + ulong rgnbase = rgn->region[i].base; + ulong rgnsize = rgn->region[i].size; + + if ((rgnbase == base) && (rgnsize == size)) + /* Already have this region, so we're done */ + return 0; + + adjacent = lmb_addrs_adjacent(base,size,rgnbase,rgnsize); + if ( adjacent > 0 ) { + rgn->region[i].base -= size; + rgn->region[i].size += size; + coalesced++; + break; + } + else if ( adjacent < 0 ) { + rgn->region[i].size += size; + coalesced++; + break; + } + } + + if ((i < rgn->cnt-1) && lmb_regions_adjacent(rgn, i, i+1) ) { + lmb_coalesce_regions(rgn, i, i+1); + coalesced++; + } + + if (coalesced) + return coalesced; + if (rgn->cnt >= MAX_LMB_REGIONS) + return -1; + + /* Couldn't coalesce the LMB, so add it to the sorted table. */ + for (i = rgn->cnt-1; i >= 0; i--) { + if (base < rgn->region[i].base) { + rgn->region[i+1].base = rgn->region[i].base; + rgn->region[i+1].size = rgn->region[i].size; + } else { + rgn->region[i+1].base = base; + rgn->region[i+1].size = size; + break; + } + } + + if (base < rgn->region[0].base) { + rgn->region[0].base = base; + rgn->region[0].size = size; + } + + rgn->cnt++; + + return 0; +} + +/* This routine may be called with relocation disabled. */ +long lmb_add(struct lmb *lmb, ulong base, ulong size) +{ + struct lmb_region *_rgn = &(lmb->memory); + + return lmb_add_region(_rgn, base, size); +} + +long lmb_reserve(struct lmb *lmb, ulong base, ulong size) +{ + struct lmb_region *_rgn = &(lmb->reserved); + + return lmb_add_region(_rgn, base, size); +} + +long lmb_overlaps_region(struct lmb_region *rgn, ulong base, + ulong size) +{ + unsigned long i; + + for (i=0; i < rgn->cnt; i++) { + ulong rgnbase = rgn->region[i].base; + ulong rgnsize = rgn->region[i].size; + if ( lmb_addrs_overlap(base,size,rgnbase,rgnsize) ) { + break; + } + } + + return (i < rgn->cnt) ? i : -1; +} + +ulong lmb_alloc(struct lmb *lmb, ulong size, ulong align) +{ + return lmb_alloc_base(lmb, size, align, LMB_ALLOC_ANYWHERE); +} + +ulong lmb_alloc_base(struct lmb *lmb, ulong size, ulong align, ulong max_addr) +{ + ulong alloc; + + alloc = __lmb_alloc_base(lmb, size, align, max_addr); + + if (alloc == 0) + printf("ERROR: Failed to allocate 0x%lx bytes below 0x%lx.\n", + size, max_addr); + + return alloc; +} + +static ulong lmb_align_down(ulong addr, ulong size) +{ + return addr & ~(size - 1); +} + +static ulong lmb_align_up(ulong addr, ulong size) +{ + return (addr + (size - 1)) & ~(size - 1); +} + +ulong __lmb_alloc_base(struct lmb *lmb, ulong size, ulong align, ulong max_addr) +{ + long i, j; + ulong base = 0; + + for (i = lmb->memory.cnt-1; i >= 0; i--) { + ulong lmbbase = lmb->memory.region[i].base; + ulong lmbsize = lmb->memory.region[i].size; + + if (max_addr == LMB_ALLOC_ANYWHERE) + base = lmb_align_down(lmbbase + lmbsize - size, align); + else if (lmbbase < max_addr) { + base = min(lmbbase + lmbsize, max_addr); + base = lmb_align_down(base - size, align); + } else + continue; + + while ((lmbbase <= base) && + ((j = lmb_overlaps_region(&(lmb->reserved), base, size)) >= 0) ) + base = lmb_align_down(lmb->reserved.region[j].base - size, + align); + + if ((base != 0) && (lmbbase <= base)) + break; + } + + if (i < 0) + return 0; + + if (lmb_add_region(&(lmb->reserved), base, lmb_align_up(size, align)) < 0) + return 0; + + return base; +} + +int lmb_is_reserved(struct lmb *lmb, ulong addr) +{ + int i; + + for (i = 0; i < lmb->reserved.cnt; i++) { + ulong upper = lmb->reserved.region[i].base + + lmb->reserved.region[i].size - 1; + if ((addr >= lmb->reserved.region[i].base) && (addr <= upper)) + return 1; + } + return 0; +} diff --git a/lib_i386/bootm.c b/lib_i386/bootm.c index ab6c2a9..60d2658 100644 --- a/lib_i386/bootm.c +++ b/lib_i386/bootm.c @@ -25,6 +25,7 @@ #include <command.h> #include <image.h> #include <zlib.h> +#include <lmb.h> #include <asm/byteorder.h> #include <asm/zimage.h>
@@ -32,7 +33,8 @@ extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - image_header_t *hdr, int verify) + image_header_t *hdr, int verify, int autostart, + struct lmb *lmb) { void *base_ptr;
diff --git a/lib_m68k/bootm.c b/lib_m68k/bootm.c index 9a98b83..c614e74 100644 --- a/lib_m68k/bootm.c +++ b/lib_m68k/bootm.c @@ -28,6 +28,7 @@ #include <bzlib.h> #include <watchdog.h> #include <environment.h> +#include <lmb.h> #include <asm/byteorder.h> #ifdef CONFIG_SHOW_BOOT_PROGRESS # include <status_led.h> @@ -45,9 +46,9 @@ extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); static ulong get_sp (void); static void set_clocks_in_mhz (bd_t *kbd);
-void do_bootm_linux(cmd_tbl_t * cmdtp, int flag, - int argc, char *argv[], - image_header_t *hdr, int verify) +void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], + image_header_t *hdr, int verify, int autostart, + struct lmb *lmb) { ulong sp, sp_limit, alloc_current;
diff --git a/lib_microblaze/bootm.c b/lib_microblaze/bootm.c index bccfbe1..957c7c1 100644 --- a/lib_microblaze/bootm.c +++ b/lib_microblaze/bootm.c @@ -28,12 +28,14 @@ #include <command.h> #include <image.h> #include <zlib.h> +#include <lmb.h> #include <asm/byteorder.h>
DECLARE_GLOBAL_DATA_PTR;
-void do_bootm_linux (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[], - image_header_t *hdr, int verify) +void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], + image_header_t *hdr, int verify, int autostart, + struct lmb *lmb) { /* First parameter is mapped to $r5 for kernel boot args */ void (*theKernel) (char *); diff --git a/lib_mips/bootm.c b/lib_mips/bootm.c index fb91c76..c3583f0 100644 --- a/lib_mips/bootm.c +++ b/lib_mips/bootm.c @@ -25,6 +25,7 @@ #include <command.h> #include <image.h> #include <zlib.h> +#include <lmb.h> #include <asm/byteorder.h> #include <asm/addrspace.h>
@@ -44,8 +45,9 @@ static void linux_params_init (ulong start, char * commandline); static void linux_env_set (char * env_name, char * env_val);
-void do_bootm_linux (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[], - image_header_t *hdr, int verify) +void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], + image_header_t *hdr, int verify, int autostart, + struct lmb *lmb) { ulong initrd_start, initrd_end;
diff --git a/lib_nios/bootm.c b/lib_nios/bootm.c index 55f7e3a..376a3b8 100644 --- a/lib_nios/bootm.c +++ b/lib_nios/bootm.c @@ -23,12 +23,14 @@
#include <common.h> #include <command.h> +#include <lmb.h>
/* FIXME: Once we find a stable version of uC-linux for nios * we can get this working. ;-) * */ void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - image__header_t *hdr, int verify) + image_header_t *hdr, int verify, int autostart, + struct lmb *lmb) { } diff --git a/lib_nios2/bootm.c b/lib_nios2/bootm.c index cb84324..9efbd47 100644 --- a/lib_nios2/bootm.c +++ b/lib_nios2/bootm.c @@ -23,10 +23,12 @@
#include <common.h> #include <command.h> +#include <lmb.h> #include <asm/byteorder.h>
void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - image_header_t *hdr, int verify) + image_header_t *hdr, int verify, int autostart, + struct lmb *lmb) { void (*kernel)(void) = (void (*)(void))image_get_ep (hdr);
diff --git a/lib_ppc/bootm.c b/lib_ppc/bootm.c index ec98e1b..666f909 100644 --- a/lib_ppc/bootm.c +++ b/lib_ppc/bootm.c @@ -33,6 +33,7 @@ #include <zlib.h> #include <bzlib.h> #include <environment.h> +#include <lmb.h> #include <asm/byteorder.h>
#if defined(CONFIG_OF_LIBFDT) @@ -57,10 +58,9 @@ static ulong get_sp (void); static void set_clocks_in_mhz (bd_t *kbd);
void __attribute__((noinline)) -do_bootm_linux(cmd_tbl_t *cmdtp, int flag, - int argc, char *argv[], - image_header_t *hdr, - int verify) +do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], + image_header_t *hdr, int verify, int autostart, + struct lmb *lmb) { ulong sp, sp_limit, alloc_current;
diff --git a/lib_sh/bootm.c b/lib_sh/bootm.c index 4e5fe77..742ebe2 100644 --- a/lib_sh/bootm.c +++ b/lib_sh/bootm.c @@ -23,6 +23,7 @@
#include <common.h> #include <command.h> +#include <lmb.h> #include <asm/byteorder.h>
/* The SH kernel reads arguments from the empty zero page at location @@ -57,8 +58,9 @@ static void hexdump (unsigned char *buf, int len) } #endif
-void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - image_header_t *hdr, int verify) +void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], + image_header_t *hdr, int verify, int autostart, + struct lmb *lmb) { char *bootargs = getenv("bootargs"); void (*kernel) (void) = (void (*)(void))image_get_ep (hdr);

Convert generic ramdisk_high(), get_boot_cmdline(), get_boot_kbd() functions over to using lmb for allocation of the ramdisk, command line and kernel bd info.
Convert PPC specific get_fdt() to use lmb for allocation of the device tree.
Provided a weak function that board code can call to do additional lmb reserves if needed.
Also introduce the concept of bootmap_base to specify the offset in physical memory that the bootmap is located at. This is used for allocations of the cmdline, kernel bd, and device tree as they should be contained within bootmap_base and bootmap_base + CFG_BOOTMAPSZ.
Signed-off-by: Kumar Gala galak@kernel.crashing.org --- common/cmd_bootm.c | 8 +++ common/image.c | 134 ++++++++++++++++++--------------------------------- include/image.h | 13 ++--- lib_m68k/bootm.c | 29 ++++++++---- lib_ppc/bootm.c | 78 ++++++++++++++++++------------ 5 files changed, 127 insertions(+), 135 deletions(-)
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index dac1dd9..9b77518 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -115,6 +115,12 @@ static boot_os_fn do_bootm_artos;
ulong load_addr = CFG_LOAD_ADDR; /* Default Load Address */
+void __board_lmb_reserve(struct lmb *lmb) +{ + /* please define platform specific board_lmb_reserve() */ +} +void board_lmb_reserve(struct lmb *lmb) __attribute__((weak, alias("__board_lmb_reserve"))); +
/*******************************************************************/ /* bootm - boot application image from image in memory */ @@ -143,6 +149,8 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) lmb_add(&lmb, 0, gd->bd->bi_memsize); #endif
+ board_lmb_reserve(&lmb); + /* get kernel image header, start address and length */ hdr = get_kernel (cmdtp, flag, argc, argv, verify, &os_data, &os_len); diff --git a/common/image.c b/common/image.c index dfe2004..b5f7a7a 100644 --- a/common/image.c +++ b/common/image.c @@ -506,10 +506,9 @@ int get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], #if defined(CONFIG_PPC) || defined(CONFIG_M68K) /** * ramdisk_high - relocate init ramdisk + * @lmb: pointer to lmb handle, will be used for memory mgmt * @rd_data: ramdisk data start address * @rd_len: ramdisk data length - * @sp_limit: stack pointer limit (including BOOTMAPSZ) - * @sp: current stack pointer * @initrd_start: pointer to a ulong variable, will hold final init ramdisk * start address (after possible relocation) * @initrd_end: pointer to a ulong variable, will hold final init ramdisk @@ -522,16 +521,16 @@ int get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], * - initrd_start and initrd_end are set to final (after relocation) ramdisk * start/end addresses if ramdisk image start and len were provided * otherwise set initrd_start and initrd_end set to zeros - * - returns new allc_current, next free address below BOOTMAPSZ + * - returns: + * 0 - success + * -1 - failure */ -ulong ramdisk_high (ulong alloc_current, ulong rd_data, ulong rd_len, - ulong sp_limit, ulong sp, - ulong *initrd_start, ulong *initrd_end) +int ramdisk_high (struct lmb *lmb, ulong rd_data, ulong rd_len, + ulong *initrd_start, ulong *initrd_end) { char *s; ulong initrd_high; int initrd_copy_to_ram = 1; - ulong new_alloc_current = alloc_current;
if ((s = getenv ("initrd_high")) != NULL) { /* a value of "no" or a similar string will act like 0, @@ -545,12 +544,6 @@ ulong ramdisk_high (ulong alloc_current, ulong rd_data, ulong rd_len, initrd_high = ~0; }
-#ifdef CONFIG_LOGBUFFER - /* Prevent initrd from overwriting logbuffer */ - if (initrd_high < (gd->bd->bi_memsize - LOGBUFF_LEN - LOGBUFF_OVERHEAD)) - initrd_high = gd->bd->bi_memsize - LOGBUFF_LEN - LOGBUFF_OVERHEAD; - debug ("## Logbuffer at 0x%08lx ", gd->bd->bi_memsize - LOGBUFF_LEN); -#endif debug ("## initrd_high = 0x%08lx, copy_to_ram = %d\n", initrd_high, initrd_copy_to_ram);
@@ -559,40 +552,17 @@ ulong ramdisk_high (ulong alloc_current, ulong rd_data, ulong rd_len, debug (" in-place initrd\n"); *initrd_start = rd_data; *initrd_end = rd_data + rd_len; + lmb_reserve(lmb, rd_data, rd_len); } else { - new_alloc_current = alloc_current - rd_len; - *initrd_start = new_alloc_current; - *initrd_start &= ~(4096 - 1); /* align on page */ - - if (initrd_high) { - ulong nsp; - - /* - * the inital ramdisk does not need to be within - * CFG_BOOTMAPSZ as it is not accessed until after - * the mm system is initialised. - * - * do the stack bottom calculation again and see if - * the initrd will fit just below the monitor stack - * bottom without overwriting the area allocated - * for command line args and board info. - */ - nsp = sp; - nsp -= 2048; /* just to be sure */ - nsp &= ~0xF; - - if (nsp > initrd_high) /* limit as specified */ - nsp = initrd_high; - - nsp -= rd_len; - nsp &= ~(4096 - 1); /* align on page */ - - if (nsp >= sp_limit) { - *initrd_start = nsp; - new_alloc_current = alloc_current; - } + if (initrd_high) + *initrd_start = lmb_alloc_base(lmb, rd_len, 0x1000, initrd_high); + else + *initrd_start = lmb_alloc(lmb, rd_len, 0x1000); + + if (*initrd_start == 0) { + puts("ramdisk - allocation error\n"); + goto error; } - show_boot_progress (12);
*initrd_end = *initrd_start + rd_len; @@ -610,56 +580,40 @@ ulong ramdisk_high (ulong alloc_current, ulong rd_data, ulong rd_len, } debug (" ramdisk load start = 0x%08lx, ramdisk load end = 0x%08lx\n", *initrd_start, *initrd_end); + return 0;
- return new_alloc_current; -} - -/** - * get_boot_sp_limit - calculate stack pointer limit - * @sp: current stack pointer - * - * get_boot_sp_limit() takes current stack pointer adrress and calculates - * stack pointer limit, below which kernel boot data (cmdline, board info, - * etc.) will be allocated. - * - * returns: - * stack pointer limit - */ -ulong get_boot_sp_limit(ulong sp) -{ - ulong sp_limit = sp; - - sp_limit -= 2048; /* just to be sure */ - - /* make sure sp_limit is within kernel mapped space */ - if (sp_limit > CFG_BOOTMAPSZ) - sp_limit = CFG_BOOTMAPSZ; - sp_limit &= ~0xF; - - return sp_limit; +error: + return -1; }
/** * get_boot_cmdline - allocate and initialize kernel cmdline - * @alloc_current: current boot allocation address (counting down - * from sp_limit) + * @lmb: pointer to lmb handle, will be used for memory mgmt * @cmd_start: pointer to a ulong variable, will hold cmdline start * @cmd_end: pointer to a ulong variable, will hold cmdline end + * @bootmap_base: ulong variable, holds offset in physical memory to + * base of bootmap * * get_boot_cmdline() allocates space for kernel command line below - * provided alloc_current address. If "bootargs" U-boot environemnt + * BOOTMAPSZ + bootmap_base address. If "bootargs" U-boot environemnt * variable is present its contents is copied to allocated kernel * command line. * * returns: - * alloc_current after cmdline allocation + * 0 - success + * -1 - failure */ -ulong get_boot_cmdline (ulong alloc_current, ulong *cmd_start, ulong *cmd_end) +int get_boot_cmdline (struct lmb *lmb, ulong *cmd_start, ulong *cmd_end, + ulong bootmap_base) { char *cmdline; char *s;
- cmdline = (char *)((alloc_current - CFG_BARGSIZE) & ~0xF); + cmdline = (char *)lmb_alloc_base(lmb, CFG_BARGSIZE, 0xf, + CFG_BOOTMAPSZ + bootmap_base); + + if (cmdline == NULL) + return -1;
if ((s = getenv("bootargs")) == NULL) s = ""; @@ -671,25 +625,31 @@ ulong get_boot_cmdline (ulong alloc_current, ulong *cmd_start, ulong *cmd_end)
debug ("## cmdline at 0x%08lx ... 0x%08lx\n", *cmd_start, *cmd_end);
- return (ulong)cmdline; + return 0; }
/** * get_boot_kbd - allocate and initialize kernel copy of board info - * @alloc_current: current boot allocation address (counting down - * from sp_limit) + * @lmb: pointer to lmb handle, will be used for memory mgmt * @kbd: double pointer to board info data + * @bootmap_base: ulong variable, holds offset in physical memory to + * base of bootmap * - * get_boot_kbd() - allocates space for kernel copy of board info data. - * Space is allocated below provided alloc_current address and kernel - * board info is initialized with the current u-boot board info data. + * get_boot_kbd() allocates space for kernel copy of board info data below + * BOOTMAPSZ + bootmap_base address and kernel board info is initialized with + * the current u-boot board info data. * * returns: - * alloc_current after kbd allocation + * 0 - success + * -1 - failure */ -ulong get_boot_kbd (ulong alloc_current, bd_t **kbd) +int get_boot_kbd (struct lmb *lmb, bd_t **kbd, ulong bootmap_base) { - *kbd = (bd_t *) (((ulong)alloc_current - sizeof(bd_t)) & ~0xF); + *kbd = (bd_t *)lmb_alloc_base(lmb, sizeof(bd_t), 0xf, + CFG_BOOTMAPSZ + bootmap_base); + if (*kbd == NULL) + return -1; + **kbd = *(gd->bd);
debug ("## kernel board info at 0x%08lx\n", (ulong)*kbd); @@ -698,7 +658,7 @@ ulong get_boot_kbd (ulong alloc_current, bd_t **kbd) do_bdinfo(NULL, 0, 0, NULL); #endif
- return (ulong)*kbd; + return 0; } #endif /* CONFIG_PPC || CONFIG_M68K */
diff --git a/include/image.h b/include/image.h index 4cf9567..f26b7e6 100644 --- a/include/image.h +++ b/include/image.h @@ -36,6 +36,7 @@ #include <asm/byteorder.h> #include <command.h> #ifndef USE_HOSTCC +#include <lmb.h> #include <linux/string.h> #include <asm/u-boot.h> #endif @@ -344,13 +345,11 @@ int get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], ulong *rd_start, ulong *rd_end);
#if defined(CONFIG_PPC) || defined(CONFIG_M68K) -ulong ramdisk_high (ulong alloc_current, ulong rd_data, ulong rd_len, - ulong sp_limit, ulong sp, - ulong *initrd_start, ulong *initrd_end); - -ulong get_boot_sp_limit (ulong sp); -ulong get_boot_cmdline (ulong alloc_current, ulong *cmd_start, ulong *cmd_end); -ulong get_boot_kbd (ulong alloc_current, bd_t **kbd); +int ramdisk_high (struct lmb *lmb, ulong rd_data, ulong rd_len, + ulong *initrd_start, ulong *initrd_end); +int get_boot_cmdline (struct lmb *lmb, ulong *cmd_start, ulong *cmd_end, + ulong bootmap_base); +int get_boot_kbd (struct lmb *lmb, bd_t **kbd, ulong bootmap_base); #endif /* CONFIG_PPC || CONFIG_M68K */
#endif /* USE_HOSTCC */ diff --git a/lib_m68k/bootm.c b/lib_m68k/bootm.c index c614e74..5aedb99 100644 --- a/lib_m68k/bootm.c +++ b/lib_m68k/bootm.c @@ -50,16 +50,18 @@ void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], image_header_t *hdr, int verify, int autostart, struct lmb *lmb) { - ulong sp, sp_limit, alloc_current; + ulong sp;
ulong rd_data_start, rd_data_end, rd_len; ulong initrd_start, initrd_end; int ret;
- ulong cmd_start, cmd_end; + ulong cmd_start, cmd_end, bootmap_base; bd_t *kbd; void (*kernel) (bd_t *, ulong, ulong, ulong, ulong);
+ bootmap_base = 0; + /* * Booting a (Linux) kernel image * @@ -72,14 +74,23 @@ void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], sp = get_sp(); debug ("## Current stack ends at 0x%08lx ", sp);
- alloc_current = sp_limit = get_boot_sp_limit(sp); - debug ("=> set upper limit to 0x%08lx\n", sp_limit); + /* adjust sp by 1K to be safe */ + sp -= 1024; + lmb_reserve(lmb, sp, (CFG_SDRAM_BASE + gd->ram_size - sp));
/* allocate space and init command line */ - alloc_current = get_boot_cmdline (alloc_current, &cmd_start, &cmd_end); + ret = get_boot_cmdline (lmb, &cmd_start, &cmd_end, bootmap_base); + if (ret) { + puts("ERROR with allocation of cmdline\n"); + goto error; + }
/* allocate space for kernel copy of board info */ - alloc_current = get_boot_kbd (alloc_current, &kbd); + ret = get_boot_kbd (lmb, &kbd, bootmap_base); + if (ret) { + puts("ERROR with allocation of kernel bd\n"); + goto error; + } set_clocks_in_mhz(kbd);
/* find kernel */ @@ -89,13 +100,13 @@ void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], /* find ramdisk */ ret = get_ramdisk (cmdtp, flag, argc, argv, hdr, verify, IH_ARCH_M68K, &rd_data_start, &rd_data_end); - if (ret) goto error;
rd_len = rd_data_end - rd_data_start; - alloc_current = ramdisk_high (alloc_current, rd_data_start, rd_len, - sp_limit, get_sp (), &initrd_start, &initrd_end); + ret = ramdisk_high (lmb, rd_data_start, rd_len, &initrd_start, &initrd_end); + if (ret) + goto error;
debug("## Transferring control to Linux (at address %08lx) ...\n", (ulong) kernel); diff --git a/lib_ppc/bootm.c b/lib_ppc/bootm.c index 666f909..c8d6935 100644 --- a/lib_ppc/bootm.c +++ b/lib_ppc/bootm.c @@ -42,9 +42,9 @@ #include <fdt_support.h>
static void fdt_error (const char *msg); -static ulong get_fdt (ulong alloc_current, cmd_tbl_t *cmdtp, int flag, - int argc, char *argv[], - image_header_t *hdr, char **of_flat_tree); +static int get_fdt (struct lmb *lmb, cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], ulong bootmap_base, + image_header_t *hdr, char **of_flat_tree); #endif
#ifdef CFG_INIT_RAM_LOCK @@ -54,6 +54,7 @@ static ulong get_fdt (ulong alloc_current, cmd_tbl_t *cmdtp, int flag, DECLARE_GLOBAL_DATA_PTR;
extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +extern ulong get_effective_memsize(void); static ulong get_sp (void); static void set_clocks_in_mhz (bd_t *kbd);
@@ -62,12 +63,12 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], image_header_t *hdr, int verify, int autostart, struct lmb *lmb) { - ulong sp, sp_limit, alloc_current; + ulong sp;
ulong initrd_start, initrd_end; ulong rd_data_start, rd_data_end, rd_len;
- ulong cmd_start, cmd_end; + ulong cmd_start, cmd_end, bootmap_base; bd_t *kbd; void (*kernel)(bd_t *, ulong, ulong, ulong, ulong);
@@ -89,6 +90,8 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], } #endif
+ bootmap_base = 0; + /* * Booting a (Linux) kernel image * @@ -101,15 +104,24 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], sp = get_sp(); debug ("## Current stack ends at 0x%08lx ", sp);
- alloc_current = sp_limit = get_boot_sp_limit(sp); - debug ("=> set upper limit to 0x%08lx\n", sp_limit); + /* adjust sp by 1K to be safe */ + sp -= 1024; + lmb_reserve(lmb, sp, (CFG_SDRAM_BASE + get_effective_memsize() - sp));
if (!has_of) { /* allocate space and init command line */ - alloc_current = get_boot_cmdline (alloc_current, &cmd_start, &cmd_end); + ret = get_boot_cmdline (lmb, &cmd_start, &cmd_end, bootmap_base); + if (ret) { + puts("ERROR with allocation of cmdline\n"); + goto error; + }
/* allocate space for kernel copy of board info */ - alloc_current = get_boot_kbd (alloc_current, &kbd); + ret = get_boot_kbd (lmb, &kbd, bootmap_base); + if (ret) { + puts("ERROR with allocation of kernel bd\n"); + goto error; + } set_clocks_in_mhz(kbd); }
@@ -119,7 +131,6 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], /* find ramdisk */ ret = get_ramdisk (cmdtp, flag, argc, argv, hdr, verify, IH_ARCH_PPC, &rd_data_start, &rd_data_end); - if (ret) goto error;
@@ -127,8 +138,11 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
#if defined(CONFIG_OF_LIBFDT) /* find flattened device tree */ - alloc_current = get_fdt (alloc_current, - cmdtp, flag, argc, argv, hdr, &of_flat_tree); + ret = get_fdt (lmb, cmdtp, flag, argc, argv, bootmap_base, hdr, + &of_flat_tree); + + if (ret) + goto error;
/* * Add the chosen node if it doesn't exist, add the env and bd_t @@ -159,8 +173,9 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], } #endif /* CONFIG_OF_LIBFDT */
- alloc_current = ramdisk_high (alloc_current, rd_data_start, rd_len, - sp_limit, get_sp (), &initrd_start, &initrd_end); + ret = ramdisk_high (lmb, rd_data_start, rd_len, &initrd_start, &initrd_end); + if (ret) + goto error;
#if defined(CONFIG_OF_LIBFDT) /* fixup the initrd now that we know where it should be */ @@ -275,15 +290,14 @@ static void fdt_error (const char *msg) puts (" - must RESET the board to recover.\n"); }
-static ulong get_fdt (ulong alloc_current, - cmd_tbl_t *cmdtp, int flag, - int argc, char *argv[], - image_header_t *hdr, char **of_flat_tree) +static int get_fdt (struct lmb *lmb, cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], ulong bootmap_base, + image_header_t *hdr, char **of_flat_tree) { image_header_t *fdt_hdr; ulong fdt_relocate = 0; char *fdt = NULL; - ulong new_alloc_current; + ulong of_len;
if(argc > 3) { fdt = (char *)simple_strtoul (argv[3], NULL, 16); @@ -349,8 +363,7 @@ static ulong get_fdt (ulong alloc_current, fdt_error ("Did not find a Flattened Device Tree"); goto error; } - printf (" Booting using the fdt at 0x%x\n", - fdt); + printf (" Booting using the fdt at 0x%x\n", fdt); } else if (image_check_type (hdr, IH_TYPE_MULTI)) { ulong fdt_data, fdt_len;
@@ -383,25 +396,28 @@ static ulong get_fdt (ulong alloc_current, } }
-#ifdef CFG_BOOTMAPSZ /* * The blob must be within CFG_BOOTMAPSZ, * so we flag it to be copied if it is not. */ if (fdt >= (char *)CFG_BOOTMAPSZ) fdt_relocate = 1; -#endif + + of_len = be32_to_cpu (fdt_totalsize (fdt));
/* move flattend device tree if needed */ if (fdt_relocate) { int err; - ulong of_start, of_len; - - of_len = be32_to_cpu (fdt_totalsize (fdt)); + ulong of_start;
/* position on a 4K boundary before the alloc_current */ - of_start = alloc_current - of_len; - of_start &= ~(4096 - 1); /* align on page */ + of_start = lmb_alloc_base(lmb, of_len, 0x1000, + (CFG_BOOTMAPSZ + bootmap_base)); + + if (of_start == 0) { + puts("device tree - allocation error\n"); + goto error; + }
debug ("## device tree at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n", (ulong)fdt, (ulong)fdt + of_len - 1, @@ -418,16 +434,14 @@ static ulong get_fdt (ulong alloc_current, puts ("OK\n");
*of_flat_tree = (char *)of_start; - new_alloc_current = of_start; } else { *of_flat_tree = fdt; - new_alloc_current = alloc_current; + lmb_reserve(lmb, (ulong)fdt, of_len); }
- return new_alloc_current; + return 0;
error: - do_reset (cmdtp, flag, argc, argv); return 1; } #endif

Allow the user to set 'bootm_low' and 'bootm_size' env vars as a way to restrict what memory range is used for bootm.
Signed-off-by: Kumar Gala galak@kernel.crashing.org --- common/cmd_bootm.c | 10 +++++----- common/image.c | 26 ++++++++++++++++++++++++++ include/image.h | 2 ++ lib_m68k/bootm.c | 2 +- lib_ppc/bootm.c | 26 ++++++++++++++++++++++++-- 5 files changed, 58 insertions(+), 8 deletions(-)
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 9b77518..520ac2f 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -138,16 +138,16 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
ulong image_start, image_end; ulong load_start, load_end; + ulong mem_start, mem_size;
struct lmb lmb;
lmb_init(&lmb);
-#ifdef CFG_SDRAM_BASE - lmb_add(&lmb, CFG_SDRAM_BASE, gd->bd->bi_memsize); -#else - lmb_add(&lmb, 0, gd->bd->bi_memsize); -#endif + mem_start = getenv_bootm_low(); + mem_size = getenv_bootm_size(); + + lmb_add(&lmb, mem_start, mem_size);
board_lmb_reserve(&lmb);
diff --git a/common/image.c b/common/image.c index b5f7a7a..7ad1140 100644 --- a/common/image.c +++ b/common/image.c @@ -118,6 +118,32 @@ int getenv_autostart (void) return (s && (*s == 'n')) ? 0 : 1; }
+ulong getenv_bootm_low(void) +{ + char *s = getenv ("bootm_low"); + if (s) { + ulong tmp = simple_strtoul (s, NULL, 16); + return tmp; + } + +#ifdef CFG_SDRAM_BASE + return CFG_SDRAM_BASE; +#else + return 0; +#endif +} + +ulong getenv_bootm_size(void) +{ + char *s = getenv ("bootm_size"); + if (s) { + ulong tmp = simple_strtoul (s, NULL, 16); + return tmp; + } + + return gd->bd->bi_memsize; +} + void memmove_wd (void *to, void *from, size_t len, ulong chunksz) { #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) diff --git a/include/image.h b/include/image.h index f26b7e6..6f7df4f 100644 --- a/include/image.h +++ b/include/image.h @@ -274,6 +274,8 @@ int image_check_dcrc (image_header_t *hdr); int image_check_dcrc_wd (image_header_t *hdr, ulong chunksize); int getenv_verify (void); int getenv_autostart (void); +ulong getenv_bootm_low(void); +ulong getenv_bootm_size(void); void memmove_wd (void *to, void *from, size_t len, ulong chunksz); #endif
diff --git a/lib_m68k/bootm.c b/lib_m68k/bootm.c index 5aedb99..91cf5b1 100644 --- a/lib_m68k/bootm.c +++ b/lib_m68k/bootm.c @@ -60,7 +60,7 @@ void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], bd_t *kbd; void (*kernel) (bd_t *, ulong, ulong, ulong, ulong);
- bootmap_base = 0; + bootmap_base = getenv_bootm_low();
/* * Booting a (Linux) kernel image diff --git a/lib_ppc/bootm.c b/lib_ppc/bootm.c index c8d6935..b0a30a0 100644 --- a/lib_ppc/bootm.c +++ b/lib_ppc/bootm.c @@ -58,6 +58,10 @@ extern ulong get_effective_memsize(void); static ulong get_sp (void); static void set_clocks_in_mhz (bd_t *kbd);
+#ifndef CFG_LINUX_LOWMEM_MAX_SIZE +#define CFG_LINUX_LOWMEM_MAX_SIZE (768*1024*1024) +#endif + void __attribute__((noinline)) do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], image_header_t *hdr, int verify, int autostart, @@ -67,6 +71,7 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
ulong initrd_start, initrd_end; ulong rd_data_start, rd_data_end, rd_len; + ulong size;
ulong cmd_start, cmd_end, bootmap_base; bd_t *kbd; @@ -90,7 +95,24 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], } #endif
- bootmap_base = 0; + bootmap_base = getenv_bootm_low(); + size = getenv_bootm_size(); + +#ifdef DEBUG + if (((u64)bootmap_base + size) > (CFG_SDRAM_BASE + (u64)gd->ram_size)) + puts("WARNING: bootm_low + bootm_size exceed total memory\n"); + if ((bootmap_base + size) > get_effective_memsize()) + puts("WARNING: bootm_low + bootm_size exceed eff. memory\n"); +#endif + + size = min(size, get_effective_memsize()); + size = min(size, CFG_LINUX_LOWMEM_MAX_SIZE); + + if (size < getenv_bootm_size()) { + ulong base = bootmap_base + size; + printf("WARNING: adjusting available memory to %x\n", size); + lmb_reserve(lmb, base, getenv_bootm_size() - size); + }
/* * Booting a (Linux) kernel image @@ -102,7 +124,7 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], * pointer. */ sp = get_sp(); - debug ("## Current stack ends at 0x%08lx ", sp); + debug ("## Current stack ends at 0x%08lx\n", sp);
/* adjust sp by 1K to be safe */ sp -= 1024;

Signed-off-by: Kumar Gala galak@kernel.crashing.org --- lib_arm/bootm.c | 3 +++ lib_avr32/bootm.c | 3 +++ lib_blackfin/bootm.c | 3 +++ lib_i386/bootm.c | 3 +++ lib_m68k/bootm.c | 5 ++++- lib_microblaze/bootm.c | 3 +++ lib_mips/bootm.c | 3 +++ lib_nios2/bootm.c | 3 +++ lib_ppc/bootm.c | 5 ++++- lib_sh/bootm.c | 3 +++ 10 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/lib_arm/bootm.c b/lib_arm/bootm.c index c850ae3..cc05416 100644 --- a/lib_arm/bootm.c +++ b/lib_arm/bootm.c @@ -113,6 +113,9 @@ void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], setup_end_tag (bd); #endif
+ if (!autostart) + return ; + /* we assume that the kernel is in place */ printf ("\nStarting kernel ...\n\n");
diff --git a/lib_avr32/bootm.c b/lib_avr32/bootm.c index 8bfd2b5..e64daa3 100644 --- a/lib_avr32/bootm.c +++ b/lib_avr32/bootm.c @@ -202,6 +202,9 @@ void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], params = setup_ethernet_tags(params); setup_end_tag(params);
+ if (!autostart) + return ; + printf("\nStarting kernel at %p (params at %p)...\n\n", theKernel, params_start);
diff --git a/lib_blackfin/bootm.c b/lib_blackfin/bootm.c index edb54e4..cc89085 100644 --- a/lib_blackfin/bootm.c +++ b/lib_blackfin/bootm.c @@ -54,6 +54,9 @@ void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], int (*appl) (char *cmdline); char *cmdline;
+ if (!autostart) + return ; + #ifdef SHARED_RESOURCES swap_to(FLASH); #endif diff --git a/lib_i386/bootm.c b/lib_i386/bootm.c index 60d2658..8d200fb 100644 --- a/lib_i386/bootm.c +++ b/lib_i386/bootm.c @@ -61,6 +61,9 @@ void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
}
+ if (!autostart) + return ; + #ifdef DEBUG printf ("## Transferring control to Linux (at address %08x) ...\n", (u32)base_ptr); diff --git a/lib_m68k/bootm.c b/lib_m68k/bootm.c index 91cf5b1..38a8880 100644 --- a/lib_m68k/bootm.c +++ b/lib_m68k/bootm.c @@ -113,6 +113,8 @@ void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
show_boot_progress (15);
+ if (!autostart) + return; /* * Linux Kernel Parameters (passing board info data): * r3: ptr to board info data @@ -126,7 +128,8 @@ void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], return ;
error: - do_reset (cmdtp, flag, argc, argv); + if (autostart) + do_reset (cmdtp, flag, argc, argv); return ; }
diff --git a/lib_microblaze/bootm.c b/lib_microblaze/bootm.c index 957c7c1..cf09636 100644 --- a/lib_microblaze/bootm.c +++ b/lib_microblaze/bootm.c @@ -41,6 +41,9 @@ void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], void (*theKernel) (char *); char *commandline = getenv ("bootargs");
+ if (!autostart) + return ; + theKernel = (void (*)(char *))image_get_ep (hdr);
show_boot_progress (15); diff --git a/lib_mips/bootm.c b/lib_mips/bootm.c index c3583f0..d334edf 100644 --- a/lib_mips/bootm.c +++ b/lib_mips/bootm.c @@ -96,6 +96,9 @@ void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], sprintf (env_buf, "0x%X", (uint) (gd->bd->bi_flashsize)); linux_env_set ("flash_size", env_buf);
+ if (!autostart) + return ; + /* we assume that the kernel is in place */ printf ("\nStarting kernel ...\n\n");
diff --git a/lib_nios2/bootm.c b/lib_nios2/bootm.c index 9efbd47..03f9551 100644 --- a/lib_nios2/bootm.c +++ b/lib_nios2/bootm.c @@ -32,6 +32,9 @@ void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], { void (*kernel)(void) = (void (*)(void))image_get_ep (hdr);
+ if (!autostart) + return ; + /* For now we assume the Microtronix linux ... which only * needs to be called ;-) */ diff --git a/lib_ppc/bootm.c b/lib_ppc/bootm.c index b0a30a0..7133f20 100644 --- a/lib_ppc/bootm.c +++ b/lib_ppc/bootm.c @@ -236,6 +236,8 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], #if defined(CFG_INIT_RAM_LOCK) && !defined(CONFIG_E500) unlock_ram_in_cache(); #endif + if (!autostart) + return ;
#if defined(CONFIG_OF_LIBFDT) if (of_flat_tree) { /* device tree; boot new style */ @@ -264,7 +266,8 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], return ;
error: - do_reset (cmdtp, flag, argc, argv); + if (autostart) + do_reset (cmdtp, flag, argc, argv); return ; }
diff --git a/lib_sh/bootm.c b/lib_sh/bootm.c index 742ebe2..5a57253 100644 --- a/lib_sh/bootm.c +++ b/lib_sh/bootm.c @@ -65,6 +65,9 @@ void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], char *bootargs = getenv("bootargs"); void (*kernel) (void) = (void (*)(void))image_get_ep (hdr);
+ if (!autostart) + return ; + /* Setup parameters */ memset(PARAM, 0, 0x1000); /* Clear zero page */ strcpy(COMMAND_LINE, bootargs);

Kumar Gala wrote:
For historical reasons we limited the stack to 256M because some boards could only map that much via BATS. However newer boards are capable of mapping more memory (for example 85xx is capable of doing up to 2G).
Signed-off-by: Kumar Gala galak@kernel.crashing.org
Acked-by: Marian Balakowicz m8@semihalf.com
m.
participants (2)
-
Kumar Gala
-
Marian Balakowicz