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 <asm/byteorder.h> 29*ea0364f1SPeter Tyser #include <asm/addrspace.h> 30*ea0364f1SPeter Tyser 31*ea0364f1SPeter Tyser DECLARE_GLOBAL_DATA_PTR; 32*ea0364f1SPeter Tyser 33*ea0364f1SPeter Tyser #define LINUX_MAX_ENVS 256 34*ea0364f1SPeter Tyser #define LINUX_MAX_ARGS 256 35*ea0364f1SPeter Tyser 36*ea0364f1SPeter Tyser static int linux_argc; 37*ea0364f1SPeter Tyser static char ** linux_argv; 38*ea0364f1SPeter Tyser 39*ea0364f1SPeter Tyser static char ** linux_env; 40*ea0364f1SPeter Tyser static char * linux_env_p; 41*ea0364f1SPeter Tyser static int linux_env_idx; 42*ea0364f1SPeter Tyser 43*ea0364f1SPeter Tyser static void linux_params_init (ulong start, char * commandline); 44*ea0364f1SPeter Tyser static void linux_env_set (char * env_name, char * env_val); 45*ea0364f1SPeter Tyser 46*ea0364f1SPeter Tyser int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) 47*ea0364f1SPeter Tyser { 48*ea0364f1SPeter Tyser void (*theKernel) (int, char **, char **, int *); 49*ea0364f1SPeter Tyser char *commandline = getenv ("bootargs"); 50*ea0364f1SPeter Tyser char env_buf[12]; 51*ea0364f1SPeter Tyser char *cp; 52*ea0364f1SPeter Tyser 53*ea0364f1SPeter Tyser if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) 54*ea0364f1SPeter Tyser return 1; 55*ea0364f1SPeter Tyser 56*ea0364f1SPeter Tyser /* find kernel entry point */ 57*ea0364f1SPeter Tyser theKernel = (void (*)(int, char **, char **, int *))images->ep; 58*ea0364f1SPeter Tyser 59*ea0364f1SPeter Tyser show_boot_progress (15); 60*ea0364f1SPeter Tyser 61*ea0364f1SPeter Tyser #ifdef DEBUG 62*ea0364f1SPeter Tyser printf ("## Transferring control to Linux (at address %08lx) ...\n", 63*ea0364f1SPeter Tyser (ulong) theKernel); 64*ea0364f1SPeter Tyser #endif 65*ea0364f1SPeter Tyser 66*ea0364f1SPeter Tyser linux_params_init (UNCACHED_SDRAM (gd->bd->bi_boot_params), commandline); 67*ea0364f1SPeter Tyser 68*ea0364f1SPeter Tyser #ifdef CONFIG_MEMSIZE_IN_BYTES 69*ea0364f1SPeter Tyser sprintf (env_buf, "%lu", (ulong)gd->ram_size); 70*ea0364f1SPeter Tyser debug ("## Giving linux memsize in bytes, %lu\n", (ulong)gd->ram_size); 71*ea0364f1SPeter Tyser #else 72*ea0364f1SPeter Tyser sprintf (env_buf, "%lu", (ulong)(gd->ram_size >> 20)); 73*ea0364f1SPeter Tyser debug ("## Giving linux memsize in MB, %lu\n", (ulong)(gd->ram_size >> 20)); 74*ea0364f1SPeter Tyser #endif /* CONFIG_MEMSIZE_IN_BYTES */ 75*ea0364f1SPeter Tyser 76*ea0364f1SPeter Tyser linux_env_set ("memsize", env_buf); 77*ea0364f1SPeter Tyser 78*ea0364f1SPeter Tyser sprintf (env_buf, "0x%08X", (uint) UNCACHED_SDRAM (images->rd_start)); 79*ea0364f1SPeter Tyser linux_env_set ("initrd_start", env_buf); 80*ea0364f1SPeter Tyser 81*ea0364f1SPeter Tyser sprintf (env_buf, "0x%X", (uint) (images->rd_end - images->rd_start)); 82*ea0364f1SPeter Tyser linux_env_set ("initrd_size", env_buf); 83*ea0364f1SPeter Tyser 84*ea0364f1SPeter Tyser sprintf (env_buf, "0x%08X", (uint) (gd->bd->bi_flashstart)); 85*ea0364f1SPeter Tyser linux_env_set ("flash_start", env_buf); 86*ea0364f1SPeter Tyser 87*ea0364f1SPeter Tyser sprintf (env_buf, "0x%X", (uint) (gd->bd->bi_flashsize)); 88*ea0364f1SPeter Tyser linux_env_set ("flash_size", env_buf); 89*ea0364f1SPeter Tyser 90*ea0364f1SPeter Tyser cp = getenv("ethaddr"); 91*ea0364f1SPeter Tyser if (cp != NULL) { 92*ea0364f1SPeter Tyser linux_env_set("ethaddr", cp); 93*ea0364f1SPeter Tyser } 94*ea0364f1SPeter Tyser 95*ea0364f1SPeter Tyser cp = getenv("eth1addr"); 96*ea0364f1SPeter Tyser if (cp != NULL) { 97*ea0364f1SPeter Tyser linux_env_set("eth1addr", cp); 98*ea0364f1SPeter Tyser } 99*ea0364f1SPeter Tyser 100*ea0364f1SPeter Tyser /* we assume that the kernel is in place */ 101*ea0364f1SPeter Tyser printf ("\nStarting kernel ...\n\n"); 102*ea0364f1SPeter Tyser 103*ea0364f1SPeter Tyser theKernel (linux_argc, linux_argv, linux_env, 0); 104*ea0364f1SPeter Tyser /* does not return */ 105*ea0364f1SPeter Tyser return 1; 106*ea0364f1SPeter Tyser } 107*ea0364f1SPeter Tyser 108*ea0364f1SPeter Tyser static void linux_params_init (ulong start, char *line) 109*ea0364f1SPeter Tyser { 110*ea0364f1SPeter Tyser char *next, *quote, *argp; 111*ea0364f1SPeter Tyser 112*ea0364f1SPeter Tyser linux_argc = 1; 113*ea0364f1SPeter Tyser linux_argv = (char **) start; 114*ea0364f1SPeter Tyser linux_argv[0] = 0; 115*ea0364f1SPeter Tyser argp = (char *) (linux_argv + LINUX_MAX_ARGS); 116*ea0364f1SPeter Tyser 117*ea0364f1SPeter Tyser next = line; 118*ea0364f1SPeter Tyser 119*ea0364f1SPeter Tyser while (line && *line && linux_argc < LINUX_MAX_ARGS) { 120*ea0364f1SPeter Tyser quote = strchr (line, '"'); 121*ea0364f1SPeter Tyser next = strchr (line, ' '); 122*ea0364f1SPeter Tyser 123*ea0364f1SPeter Tyser while (next != NULL && quote != NULL && quote < next) { 124*ea0364f1SPeter Tyser /* we found a left quote before the next blank 125*ea0364f1SPeter Tyser * now we have to find the matching right quote 126*ea0364f1SPeter Tyser */ 127*ea0364f1SPeter Tyser next = strchr (quote + 1, '"'); 128*ea0364f1SPeter Tyser if (next != NULL) { 129*ea0364f1SPeter Tyser quote = strchr (next + 1, '"'); 130*ea0364f1SPeter Tyser next = strchr (next + 1, ' '); 131*ea0364f1SPeter Tyser } 132*ea0364f1SPeter Tyser } 133*ea0364f1SPeter Tyser 134*ea0364f1SPeter Tyser if (next == NULL) { 135*ea0364f1SPeter Tyser next = line + strlen (line); 136*ea0364f1SPeter Tyser } 137*ea0364f1SPeter Tyser 138*ea0364f1SPeter Tyser linux_argv[linux_argc] = argp; 139*ea0364f1SPeter Tyser memcpy (argp, line, next - line); 140*ea0364f1SPeter Tyser argp[next - line] = 0; 141*ea0364f1SPeter Tyser 142*ea0364f1SPeter Tyser argp += next - line + 1; 143*ea0364f1SPeter Tyser linux_argc++; 144*ea0364f1SPeter Tyser 145*ea0364f1SPeter Tyser if (*next) 146*ea0364f1SPeter Tyser next++; 147*ea0364f1SPeter Tyser 148*ea0364f1SPeter Tyser line = next; 149*ea0364f1SPeter Tyser } 150*ea0364f1SPeter Tyser 151*ea0364f1SPeter Tyser linux_env = (char **) (((ulong) argp + 15) & ~15); 152*ea0364f1SPeter Tyser linux_env[0] = 0; 153*ea0364f1SPeter Tyser linux_env_p = (char *) (linux_env + LINUX_MAX_ENVS); 154*ea0364f1SPeter Tyser linux_env_idx = 0; 155*ea0364f1SPeter Tyser } 156*ea0364f1SPeter Tyser 157*ea0364f1SPeter Tyser static void linux_env_set (char *env_name, char *env_val) 158*ea0364f1SPeter Tyser { 159*ea0364f1SPeter Tyser if (linux_env_idx < LINUX_MAX_ENVS - 1) { 160*ea0364f1SPeter Tyser linux_env[linux_env_idx] = linux_env_p; 161*ea0364f1SPeter Tyser 162*ea0364f1SPeter Tyser strcpy (linux_env_p, env_name); 163*ea0364f1SPeter Tyser linux_env_p += strlen (env_name); 164*ea0364f1SPeter Tyser 165*ea0364f1SPeter Tyser strcpy (linux_env_p, "="); 166*ea0364f1SPeter Tyser linux_env_p += 1; 167*ea0364f1SPeter Tyser 168*ea0364f1SPeter Tyser strcpy (linux_env_p, env_val); 169*ea0364f1SPeter Tyser linux_env_p += strlen (env_val); 170*ea0364f1SPeter Tyser 171*ea0364f1SPeter Tyser linux_env_p++; 172*ea0364f1SPeter Tyser linux_env[++linux_env_idx] = 0; 173*ea0364f1SPeter Tyser } 174*ea0364f1SPeter Tyser } 175