ulong load_addr = CFG_LOAD_ADDR; /* Default Load Address */
static bootm_headers_t images; /* pointers to os/initrd/fdt images */
+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 */
lmb_add(&lmb, 0, gd->bd->bi_memsize);
#endif
+ board_lmb_reserve(&lmb);
+
/* get kernel image header, start address and length */
os_hdr = get_kernel (cmdtp, flag, argc, argv,
&images, &os_data, &os_len);
#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
* - 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,
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);
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;
}
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 = "";
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);
do_bdinfo(NULL, 0, 0, NULL);
#endif
- return (ulong)*kbd;
+ return 0;
}
#endif /* CONFIG_PPC || CONFIG_M68K */
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 */
/*******************************************************************/
int argc, char *argv[],
bootm_headers_t *images)
{
- 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 bootmap_base = 0;
bd_t *kbd;
ulong ep = 0;
void (*kernel) (bd_t *, ulong, ulong, ulong, ulong);
+ struct lmb *lmb = images->lmb;
/*
* Booting a (Linux) kernel image
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 entry point */
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);
static void fdt_error (const char *msg);
static int get_fdt (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
bootm_headers_t *images, char **of_flat_tree, ulong *of_size);
-static ulong fdt_relocate (ulong alloc_current,
+static int fdt_relocate (struct lmb *lmb, ulong bootmap_base,
cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
char **of_flat_tree, ulong *of_size);
#endif
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);
do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
bootm_headers_t *images)
{
- 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;
ulong ep = 0;
void (*kernel)(bd_t *, ulong, ulong, ulong, ulong);
int ret;
ulong of_size = 0;
+ struct lmb *lmb = images->lmb;
#if defined(CONFIG_OF_LIBFDT)
char *of_flat_tree = NULL;
#endif
+ bootmap_base = 0;
+
/*
* Booting a (Linux) kernel image
*
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 defined(CONFIG_OF_LIBFDT)
/* find flattened device tree */
if (!of_size) {
/* 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);
}
rd_len = rd_data_end - rd_data_start;
#if defined(CONFIG_OF_LIBFDT)
- alloc_current = fdt_relocate (alloc_current,
- cmdtp, flag, argc, argv, &of_flat_tree, &of_size);
+ ret = fdt_relocate (lmb, bootmap_base,
+ cmdtp, flag, argc, argv, &of_flat_tree, &of_size);
/*
* Add the chosen node if it doesn't exist, add the env and bd_t
}
#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 */
return 1;
}
-static ulong fdt_relocate (ulong alloc_current,
+static int fdt_relocate (struct lmb *lmb, ulong bootmap_base,
cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
char **of_flat_tree, ulong *of_size)
{
char *fdt_blob = *of_flat_tree;
ulong relocate = 0;
- ulong new_alloc_current;
+ ulong of_len = 0;
/* nothing to do */
if (*of_size == 0)
- return alloc_current;
+ return 0;
if (fdt_check_header (fdt_blob) != 0) {
fdt_error ("image is not a fdt");
relocate = 1;
#endif
-#ifdef CFG_BOOTMAPSZ
/*
* The blob must be within CFG_BOOTMAPSZ,
* so we flag it to be copied if it is not.
*/
if (fdt_blob >= (char *)CFG_BOOTMAPSZ)
relocate = 1;
-#endif
+
+ of_len = be32_to_cpu (fdt_totalsize (fdt));
/* move flattend device tree if needed */
if (relocate) {
int err;
- ulong of_start, of_len;
-
- of_len = *of_size;
+ 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_blob, (ulong)fdt_blob + of_len - 1,
puts ("OK\n");
*of_flat_tree = (char *)of_start;
- new_alloc_current = of_start;
} else {
*of_flat_tree = fdt_blob;
- 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