From: Marian Balakowicz Date: Thu, 31 Jan 2008 12:57:17 +0000 (+0100) Subject: [new uImage] Move ramdisk loading to a common routine X-Git-Url: http://git.dujemihanovic.xyz/?a=commitdiff_plain;h=ceaed2b1e54ebf14d600e02fef016c8df5cc4d40;p=u-boot.git [new uImage] Move ramdisk loading to a common routine Ramdisk loading code, including initrd_high variable handling, was duplicated for PPC and M68K platforms. This patch creates common helper routine that is being called from both platform do_bootm_linux() routines. Signed-off-by: Marian Balakowicz --- diff --git a/common/image.c b/common/image.c index e4be4caf85..56d6b52a8d 100644 --- a/common/image.c +++ b/common/image.c @@ -22,6 +22,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ + +#define DEBUG + #ifndef USE_HOSTCC #include #include @@ -34,6 +37,10 @@ #include #endif +#ifdef CONFIG_LOGBUFFER +#include +#endif + extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); #else #include "mkimage.h" @@ -476,5 +483,111 @@ 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); } + +#if defined(CONFIG_PPC) || defined(CONFIG_M68K) +/** + * 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 + * start address (after possible relocation) + * @initrd_end: pointer to a ulong variable, will hold final init ramdisk + * end address (after possible relocation) + * + * ramdisk_high() takes a relocation hint from "initrd_high" environement + * variable and if requested ramdisk data is moved to a specified location. + * + * returns: + * 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 to zeros + * + */ +void ramdisk_high (ulong rd_data, ulong rd_len, bd_t *kbd, ulong sp_limit, + ulong sp, ulong *initrd_start, ulong *initrd_end) +{ + char *s; + ulong initrd_high; + int initrd_copy_to_ram = 1; + + if ((s = getenv ("initrd_high")) != NULL) { + /* a value of "no" or a similar string will act like 0, + * turning the "load high" feature off. This is intentional. + */ + initrd_high = simple_strtoul (s, NULL, 16); + if (initrd_high == ~0) + initrd_copy_to_ram = 0; + } else { + /* not set, no restrictions to load high */ + initrd_high = ~0; + } + +#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); +#endif + debug ("## initrd_high = 0x%08lx, copy_to_ram = %d\n", + initrd_high, initrd_copy_to_ram); + + if (rd_data) { + if (!initrd_copy_to_ram) { /* zero-copy ramdisk support */ + debug (" in-place initrd\n"); + *initrd_start = rd_data; + *initrd_end = rd_data + rd_len; + } else { + *initrd_start = (ulong)kbd - rd_len; + *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; + } + + show_boot_progress (12); + + *initrd_end = *initrd_start + rd_len; + printf (" Loading Ramdisk to %08lx, end %08lx ... ", + *initrd_start, *initrd_end); + + memmove_wd((void *)*initrd_start, + (void *)rd_data, rd_len, CHUNKSZ); + + puts ("OK\n"); + } + } else { + *initrd_start = 0; + *initrd_end = 0; + } + debug (" ramdisk load start = 0x%08lx, ramdisk load end = 0x%08lx\n", + *initrd_start, *initrd_end); +} +#endif /* CONFIG_PPC || CONFIG_M68K */ #endif /* USE_HOSTCC */ diff --git a/include/image.h b/include/image.h index b438564cfb..a8cb1dafe2 100644 --- a/include/image.h +++ b/include/image.h @@ -37,6 +37,7 @@ #include #ifndef USE_HOSTCC #include +#include #endif /* @@ -340,7 +341,11 @@ image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, void 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); -#endif /* USE_HOSTCCa */ +#if defined(CONFIG_PPC) || defined(CONFIG_M68K) +void ramdisk_high (ulong rd_data_start, ulong rd_len, bd_t *kbd, ulong sp_limit, + ulong sp, ulong *initrd_start, ulong *initrd_end); +#endif /* CONFIG_PPC || CONFIG_M68K */ +#endif /* USE_HOSTCC */ #endif /* __IMAGE_H__ */ diff --git a/lib_m68k/bootm.c b/lib_m68k/bootm.c index dac52763aa..3fd38e98d1 100644 --- a/lib_m68k/bootm.c +++ b/lib_m68k/bootm.c @@ -44,16 +44,16 @@ DECLARE_GLOBAL_DATA_PTR; # define SHOW_BOOT_PROGRESS(arg) #endif +static ulong get_sp (void); + void do_bootm_linux(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[], image_header_t *hdr, int verify) { - ulong sp; + ulong sp_limit; ulong rd_data_start, rd_data_end, rd_len; - ulong initrd_high; ulong initrd_start, initrd_end; - int initrd_copy_to_ram = 1; ulong cmd_start, cmd_end; char *cmdline; @@ -61,25 +61,6 @@ void do_bootm_linux(cmd_tbl_t * cmdtp, int flag, bd_t *kbd; void (*kernel) (bd_t *, ulong, ulong, ulong, ulong); - if ((s = getenv("initrd_high")) != NULL) { - /* a value of "no" or a similar string will act like 0, - * turning the "load high" feature off. This is intentional. - */ - initrd_high = simple_strtoul(s, NULL, 16); - if (initrd_high == ~0) - initrd_copy_to_ram = 0; - } else { /* not set, no restrictions to load high */ - initrd_high = ~0; - } - -#ifdef CONFIG_LOGBUFFER - kbd = gd->bd; - /* 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); -#endif - /* * Booting a (Linux) kernel image * @@ -89,19 +70,18 @@ void do_bootm_linux(cmd_tbl_t * cmdtp, int flag, * memory, which means far enough below the current stack * pointer. */ - asm("movel %%a7, %%d0\n" - "movel %%d0, %0\n": "=d"(sp): :"%d0"); + sp_limit = get_sp(); - debug("## Current stack ends at 0x%08lX ", sp); + debug("## Current stack ends at 0x%08lX ", sp_limit); - sp -= 2048; /* just to be sure */ - if (sp > CFG_BOOTMAPSZ) - sp = CFG_BOOTMAPSZ; - sp &= ~0xF; + sp_limit -= 2048; /* just to be sure */ + if (sp_limit > CFG_BOOTMAPSZ) + sp_limit = CFG_BOOTMAPSZ; + sp_limit &= ~0xF; - debug("=> set upper limit to 0x%08lX\n", sp); + debug("=> set upper limit to 0x%08lX\n", sp_limit); - cmdline = (char *)((sp - CFG_BARGSIZE) & ~0xF); + cmdline = (char *)((sp_limit - CFG_BARGSIZE) & ~0xF); kbd = (bd_t *) (((ulong) cmdline - sizeof(bd_t)) & ~0xF); if ((s = getenv("bootargs")) == NULL) @@ -126,69 +106,17 @@ void do_bootm_linux(cmd_tbl_t * cmdtp, int flag, kbd->bi_busfreq /= 1000000L; } + /* find kernel */ kernel = (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); - rd_len = rd_data_end - rd_data_start; - if (rd_data_start) { - if (!initrd_copy_to_ram) { /* zero-copy ramdisk support */ - initrd_start = rd_data_start; - initrd_end = rd_data_end; - } else { - initrd_start = (ulong) kbd - rd_len; - 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 - * above for command line args and board info. - */ - asm("movel %%a7, %%d0\n" - "movel %%d0, %0\n": "=d"(nsp): :"%d0"); - - 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) - initrd_start = nsp; - } - - SHOW_BOOT_PROGRESS(12); - - debug - ("## initrd at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n", - rd_data_start, rd_data_end - 1, rd_len, rd_len); - - initrd_end = initrd_start + rd_len; - printf(" Loading Ramdisk to %08lx, end %08lx ... ", - initrd_start, initrd_end); - - memmove_wd((void *)initrd_start, - (void *)rd_data_start, rd_len, CHUNKSZ); - - puts("OK\n"); - } - } else { - initrd_start = 0; - initrd_end = 0; - } + rd_len = rd_data_end - rd_data_start; + ramdisk_high (rd_data_start, rd_len, kdb, sp_limit, get_sp (), + &initrd_start, &initrd_end); debug("## Transferring control to Linux (at address %08lx) ...\n", (ulong) kernel); @@ -206,3 +134,13 @@ void do_bootm_linux(cmd_tbl_t * cmdtp, int flag, (*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end); /* does not return */ } + +static ulong get_sp (void) +{ + ulong sp; + + asm("movel %%a7, %%d0\n" + "movel %%d0, %0\n": "=d"(sp): :"%d0"); + + return sp; +} diff --git a/lib_ppc/bootm.c b/lib_ppc/bootm.c index 65edcdb588..d73d2fda79 100644 --- a/lib_ppc/bootm.c +++ b/lib_ppc/bootm.c @@ -43,10 +43,6 @@ static void fdt_error (const char *msg); #endif -#ifdef CONFIG_LOGBUFFER -#include -#endif - #ifdef CFG_INIT_RAM_LOCK #include #endif @@ -54,9 +50,10 @@ static void fdt_error (const char *msg); DECLARE_GLOBAL_DATA_PTR; extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +static ulong get_sp (void); #if defined(CONFIG_CMD_BDI) -extern int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +extern int do_bdinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); #endif void __attribute__((noinline)) @@ -65,15 +62,13 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, image_header_t *hdr, int verify) { - ulong initrd_high; - int initrd_copy_to_ram = 1; ulong initrd_start, initrd_end; ulong rd_data_start, rd_data_end, rd_len; ulong cmd_start, cmd_end; char *cmdline; - ulong sp; + ulong sp_limit; char *s; bd_t *kbd; void (*kernel)(bd_t *, ulong, ulong, ulong, ulong); @@ -84,25 +79,6 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, ulong of_data = 0; #endif - if ((s = getenv ("initrd_high")) != NULL) { - /* a value of "no" or a similar string will act like 0, - * turning the "load high" feature off. This is intentional. - */ - initrd_high = simple_strtoul(s, NULL, 16); - if (initrd_high == ~0) - initrd_copy_to_ram = 0; - } else { /* not set, no restrictions to load high */ - initrd_high = ~0; - } - -#ifdef CONFIG_LOGBUFFER - kbd=gd->bd; - /* 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); -#endif - /* * Booting a (Linux) kernel image * @@ -113,18 +89,17 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, * pointer. */ - asm( "mr %0,1": "=r"(sp) : ); - - debug ("## Current stack ends at 0x%08lX ", sp); + sp_limit = get_sp(); + debug ("## Current stack ends at 0x%08lX ", sp_limit); - sp -= 2048; /* just to be sure */ - if (sp > CFG_BOOTMAPSZ) - sp = CFG_BOOTMAPSZ; - sp &= ~0xF; + sp_limit -= 2048; /* just to be sure */ + if (sp_limit > CFG_BOOTMAPSZ) + sp_limit = CFG_BOOTMAPSZ; + sp_limit &= ~0xF; - debug ("=> set upper limit to 0x%08lX\n", sp); + debug ("=> set upper limit to 0x%08lX\n", sp_limit); - cmdline = (char *)((sp - CFG_BARGSIZE) & ~0xF); + cmdline = (char *)((sp_limit - CFG_BARGSIZE) & ~0xF); kbd = (bd_t *)(((ulong)cmdline - sizeof(bd_t)) & ~0xF); if ((s = getenv("bootargs")) == NULL) @@ -168,13 +143,20 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, #endif /* CONFIG_MPC5xxx */ } + /* find kernel */ 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); + rd_len = rd_data_end - rd_data_start; + ramdisk_high (rd_data_start, rd_len, kbd, sp_limit, get_sp (), + &initrd_start, &initrd_end); + #if defined(CONFIG_OF_LIBFDT) + /* find flattened device tree */ if(argc > 3) { of_flat_tree = (char *) simple_strtoul(argv[3], NULL, 16); fdt_hdr = (image_header_t *)of_flat_tree; @@ -265,56 +247,6 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, } #endif - if (rd_data_start) { - if (!initrd_copy_to_ram) { /* zero-copy ramdisk support */ - initrd_start = rd_data_start; - initrd_end = rd_data_end; - } else { - initrd_start = (ulong)kbd - rd_len; - 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 - * above for command line args and board info. - */ - asm( "mr %0,1": "=r"(nsp) : ); - 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) - initrd_start = nsp; - } - - show_boot_progress (12); - - debug ("## initrd at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n", - rd_data_start, rd_data_end - 1, rd_len, rd_len); - - initrd_end = initrd_start + rd_len; - printf (" Loading Ramdisk to %08lx, end %08lx ... ", - initrd_start, initrd_end); - - memmove_wd((void *)initrd_start, - (void *)rd_data_start, rd_len, CHUNKSZ); - - puts ("OK\n"); - } - } else { - initrd_start = 0; - initrd_end = 0; - } #if defined(CONFIG_OF_LIBFDT) @@ -413,6 +345,14 @@ do_bootm_linux(cmd_tbl_t *cmdtp, int flag, /* does not return */ } +static ulong get_sp (void) +{ + ulong sp; + + asm( "mr %0,1": "=r"(sp) : ); + return sp; +} + #if defined(CONFIG_OF_LIBFDT) static void fdt_error (const char *msg) {