1*ea0364f1SPeter Tyser /* 2*ea0364f1SPeter Tyser * (C) Copyright 2003 3*ea0364f1SPeter Tyser * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4*ea0364f1SPeter Tyser * 5*ea0364f1SPeter Tyser * See file CREDITS for list of people who contributed to this 6*ea0364f1SPeter Tyser * project. 7*ea0364f1SPeter Tyser * 8*ea0364f1SPeter Tyser * This program is free software; you can redistribute it and/or modify 9*ea0364f1SPeter Tyser * it under the terms of the GNU General Public License as published by 10*ea0364f1SPeter Tyser * the Free Software Foundation; either version 2 of the License, or 11*ea0364f1SPeter Tyser * (at your option) any later version. 12*ea0364f1SPeter Tyser * 13*ea0364f1SPeter Tyser * This program is distributed in the hope that it will be useful, 14*ea0364f1SPeter Tyser * but WITHOUT ANY WARRANTY; without even the implied warranty of 15*ea0364f1SPeter Tyser * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16*ea0364f1SPeter Tyser * GNU General Public License for more details. 17*ea0364f1SPeter Tyser * 18*ea0364f1SPeter Tyser * You should have received a copy of the GNU General Public License 19*ea0364f1SPeter Tyser * along with this program; if not, write to the Free Software 20*ea0364f1SPeter Tyser * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21*ea0364f1SPeter Tyser * 22*ea0364f1SPeter Tyser */ 23*ea0364f1SPeter Tyser 24*ea0364f1SPeter Tyser #include <common.h> 25*ea0364f1SPeter Tyser #include <command.h> 26*ea0364f1SPeter Tyser #include <image.h> 27*ea0364f1SPeter Tyser #include <u-boot/zlib.h> 28*ea0364f1SPeter Tyser #include <bzlib.h> 29*ea0364f1SPeter Tyser #include <watchdog.h> 30*ea0364f1SPeter Tyser #include <environment.h> 31*ea0364f1SPeter Tyser #include <asm/byteorder.h> 32*ea0364f1SPeter Tyser #ifdef CONFIG_SHOW_BOOT_PROGRESS 33*ea0364f1SPeter Tyser # include <status_led.h> 34*ea0364f1SPeter Tyser #endif 35*ea0364f1SPeter Tyser 36*ea0364f1SPeter Tyser DECLARE_GLOBAL_DATA_PTR; 37*ea0364f1SPeter Tyser 38*ea0364f1SPeter Tyser #define PHYSADDR(x) x 39*ea0364f1SPeter Tyser 40*ea0364f1SPeter Tyser #define LINUX_MAX_ENVS 256 41*ea0364f1SPeter Tyser #define LINUX_MAX_ARGS 256 42*ea0364f1SPeter Tyser 43*ea0364f1SPeter Tyser static ulong get_sp (void); 44*ea0364f1SPeter Tyser static void set_clocks_in_mhz (bd_t *kbd); 45*ea0364f1SPeter Tyser 46*ea0364f1SPeter Tyser void arch_lmb_reserve(struct lmb *lmb) 47*ea0364f1SPeter Tyser { 48*ea0364f1SPeter Tyser ulong sp; 49*ea0364f1SPeter Tyser 50*ea0364f1SPeter Tyser /* 51*ea0364f1SPeter Tyser * Booting a (Linux) kernel image 52*ea0364f1SPeter Tyser * 53*ea0364f1SPeter Tyser * Allocate space for command line and board info - the 54*ea0364f1SPeter Tyser * address should be as high as possible within the reach of 55*ea0364f1SPeter Tyser * the kernel (see CONFIG_SYS_BOOTMAPSZ settings), but in unused 56*ea0364f1SPeter Tyser * memory, which means far enough below the current stack 57*ea0364f1SPeter Tyser * pointer. 58*ea0364f1SPeter Tyser */ 59*ea0364f1SPeter Tyser sp = get_sp(); 60*ea0364f1SPeter Tyser debug ("## Current stack ends at 0x%08lx ", sp); 61*ea0364f1SPeter Tyser 62*ea0364f1SPeter Tyser /* adjust sp by 1K to be safe */ 63*ea0364f1SPeter Tyser sp -= 1024; 64*ea0364f1SPeter Tyser lmb_reserve(lmb, sp, (CONFIG_SYS_SDRAM_BASE + gd->ram_size - sp)); 65*ea0364f1SPeter Tyser } 66*ea0364f1SPeter Tyser 67*ea0364f1SPeter Tyser int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) 68*ea0364f1SPeter Tyser { 69*ea0364f1SPeter Tyser ulong rd_len; 70*ea0364f1SPeter Tyser ulong initrd_start, initrd_end; 71*ea0364f1SPeter Tyser int ret; 72*ea0364f1SPeter Tyser 73*ea0364f1SPeter Tyser ulong cmd_start, cmd_end; 74*ea0364f1SPeter Tyser ulong bootmap_base; 75*ea0364f1SPeter Tyser bd_t *kbd; 76*ea0364f1SPeter Tyser void (*kernel) (bd_t *, ulong, ulong, ulong, ulong); 77*ea0364f1SPeter Tyser struct lmb *lmb = &images->lmb; 78*ea0364f1SPeter Tyser 79*ea0364f1SPeter Tyser if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) 80*ea0364f1SPeter Tyser return 1; 81*ea0364f1SPeter Tyser 82*ea0364f1SPeter Tyser bootmap_base = getenv_bootm_low(); 83*ea0364f1SPeter Tyser 84*ea0364f1SPeter Tyser /* allocate space and init command line */ 85*ea0364f1SPeter Tyser ret = boot_get_cmdline (lmb, &cmd_start, &cmd_end, bootmap_base); 86*ea0364f1SPeter Tyser if (ret) { 87*ea0364f1SPeter Tyser puts("ERROR with allocation of cmdline\n"); 88*ea0364f1SPeter Tyser goto error; 89*ea0364f1SPeter Tyser } 90*ea0364f1SPeter Tyser 91*ea0364f1SPeter Tyser /* allocate space for kernel copy of board info */ 92*ea0364f1SPeter Tyser ret = boot_get_kbd (lmb, &kbd, bootmap_base); 93*ea0364f1SPeter Tyser if (ret) { 94*ea0364f1SPeter Tyser puts("ERROR with allocation of kernel bd\n"); 95*ea0364f1SPeter Tyser goto error; 96*ea0364f1SPeter Tyser } 97*ea0364f1SPeter Tyser set_clocks_in_mhz(kbd); 98*ea0364f1SPeter Tyser 99*ea0364f1SPeter Tyser kernel = (void (*)(bd_t *, ulong, ulong, ulong, ulong))images->ep; 100*ea0364f1SPeter Tyser 101*ea0364f1SPeter Tyser rd_len = images->rd_end - images->rd_start; 102*ea0364f1SPeter Tyser ret = boot_ramdisk_high (lmb, images->rd_start, rd_len, 103*ea0364f1SPeter Tyser &initrd_start, &initrd_end); 104*ea0364f1SPeter Tyser if (ret) 105*ea0364f1SPeter Tyser goto error; 106*ea0364f1SPeter Tyser 107*ea0364f1SPeter Tyser debug("## Transferring control to Linux (at address %08lx) ...\n", 108*ea0364f1SPeter Tyser (ulong) kernel); 109*ea0364f1SPeter Tyser 110*ea0364f1SPeter Tyser show_boot_progress (15); 111*ea0364f1SPeter Tyser 112*ea0364f1SPeter Tyser /* 113*ea0364f1SPeter Tyser * Linux Kernel Parameters (passing board info data): 114*ea0364f1SPeter Tyser * sp+00: Ignore, side effect of using jsr to jump to kernel 115*ea0364f1SPeter Tyser * sp+04: ptr to board info data 116*ea0364f1SPeter Tyser * sp+08: initrd_start or 0 if no initrd 117*ea0364f1SPeter Tyser * sp+12: initrd_end - unused if initrd_start is 0 118*ea0364f1SPeter Tyser * sp+16: Start of command line string 119*ea0364f1SPeter Tyser * sp+20: End of command line string 120*ea0364f1SPeter Tyser */ 121*ea0364f1SPeter Tyser (*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end); 122*ea0364f1SPeter Tyser /* does not return */ 123*ea0364f1SPeter Tyser error: 124*ea0364f1SPeter Tyser return 1; 125*ea0364f1SPeter Tyser } 126*ea0364f1SPeter Tyser 127*ea0364f1SPeter Tyser static ulong get_sp (void) 128*ea0364f1SPeter Tyser { 129*ea0364f1SPeter Tyser ulong sp; 130*ea0364f1SPeter Tyser 131*ea0364f1SPeter Tyser asm("movel %%a7, %%d0\n" 132*ea0364f1SPeter Tyser "movel %%d0, %0\n": "=d"(sp): :"%d0"); 133*ea0364f1SPeter Tyser 134*ea0364f1SPeter Tyser return sp; 135*ea0364f1SPeter Tyser } 136*ea0364f1SPeter Tyser 137*ea0364f1SPeter Tyser static void set_clocks_in_mhz (bd_t *kbd) 138*ea0364f1SPeter Tyser { 139*ea0364f1SPeter Tyser char *s; 140*ea0364f1SPeter Tyser 141*ea0364f1SPeter Tyser if ((s = getenv("clocks_in_mhz")) != NULL) { 142*ea0364f1SPeter Tyser /* convert all clock information to MHz */ 143*ea0364f1SPeter Tyser kbd->bi_intfreq /= 1000000L; 144*ea0364f1SPeter Tyser kbd->bi_busfreq /= 1000000L; 145*ea0364f1SPeter Tyser } 146*ea0364f1SPeter Tyser } 147