]>
Commit | Line | Data |
---|---|---|
c021880a WD |
1 | /* |
2 | * (C) Copyright 2003 | |
3 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | |
4 | * | |
5 | * See file CREDITS for list of people who contributed to this | |
6 | * project. | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License as published by | |
10 | * the Free Software Foundation; either version 2 of the License, or | |
11 | * (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 | * | |
22 | */ | |
23 | ||
24 | #include <common.h> | |
25 | #include <command.h> | |
c021880a | 26 | #include <image.h> |
a31e091a | 27 | #include <u-boot/zlib.h> |
c021880a WD |
28 | #include <asm/byteorder.h> |
29 | #include <asm/addrspace.h> | |
30 | ||
d87080b7 WD |
31 | DECLARE_GLOBAL_DATA_PTR; |
32 | ||
c021880a WD |
33 | #define LINUX_MAX_ENVS 256 |
34 | #define LINUX_MAX_ARGS 256 | |
35 | ||
c021880a WD |
36 | static int linux_argc; |
37 | static char ** linux_argv; | |
38 | ||
39 | static char ** linux_env; | |
40 | static char * linux_env_p; | |
41 | static int linux_env_idx; | |
42 | ||
43 | static void linux_params_init (ulong start, char * commandline); | |
44 | static void linux_env_set (char * env_name, char * env_val); | |
45 | ||
40d7e99d | 46 | int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) |
c021880a | 47 | { |
d5934ad7 MB |
48 | void (*theKernel) (int, char **, char **, int *); |
49 | char *commandline = getenv ("bootargs"); | |
50 | char env_buf[12]; | |
25dbe98a | 51 | char *cp; |
f13e7b2e | 52 | |
49c3a861 KG |
53 | if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) |
54 | return 1; | |
55 | ||
d5934ad7 | 56 | /* find kernel entry point */ |
c160a954 | 57 | theKernel = (void (*)(int, char **, char **, int *))images->ep; |
c021880a | 58 | |
fad63407 | 59 | show_boot_progress (15); |
c021880a WD |
60 | |
61 | #ifdef DEBUG | |
5da627a4 WD |
62 | printf ("## Transferring control to Linux (at address %08lx) ...\n", |
63 | (ulong) theKernel); | |
c021880a WD |
64 | #endif |
65 | ||
a2663ea4 | 66 | linux_params_init (UNCACHED_SDRAM (gd->bd->bi_boot_params), commandline); |
5da627a4 WD |
67 | |
68 | #ifdef CONFIG_MEMSIZE_IN_BYTES | |
25dbe98a WD |
69 | sprintf (env_buf, "%lu", (ulong)gd->ram_size); |
70 | debug ("## Giving linux memsize in bytes, %lu\n", (ulong)gd->ram_size); | |
5da627a4 | 71 | #else |
25dbe98a WD |
72 | sprintf (env_buf, "%lu", (ulong)(gd->ram_size >> 20)); |
73 | debug ("## Giving linux memsize in MB, %lu\n", (ulong)(gd->ram_size >> 20)); | |
5da627a4 | 74 | #endif /* CONFIG_MEMSIZE_IN_BYTES */ |
c021880a | 75 | |
5da627a4 | 76 | linux_env_set ("memsize", env_buf); |
c021880a | 77 | |
c4f9419c | 78 | sprintf (env_buf, "0x%08X", (uint) UNCACHED_SDRAM (images->rd_start)); |
72f1b65f | 79 | linux_env_set ("initrd_start", env_buf); |
c021880a | 80 | |
c4f9419c | 81 | sprintf (env_buf, "0x%X", (uint) (images->rd_end - images->rd_start)); |
5da627a4 | 82 | linux_env_set ("initrd_size", env_buf); |
c021880a | 83 | |
5da627a4 WD |
84 | sprintf (env_buf, "0x%08X", (uint) (gd->bd->bi_flashstart)); |
85 | linux_env_set ("flash_start", env_buf); | |
c021880a | 86 | |
5da627a4 WD |
87 | sprintf (env_buf, "0x%X", (uint) (gd->bd->bi_flashsize)); |
88 | linux_env_set ("flash_size", env_buf); | |
c021880a | 89 | |
e7c37452 JM |
90 | cp = getenv("ethaddr"); |
91 | if (cp != NULL) { | |
92 | linux_env_set("ethaddr", cp); | |
93 | } | |
94 | ||
95 | cp = getenv("eth1addr"); | |
96 | if (cp != NULL) { | |
97 | linux_env_set("eth1addr", cp); | |
98 | } | |
99 | ||
5da627a4 WD |
100 | /* we assume that the kernel is in place */ |
101 | printf ("\nStarting kernel ...\n\n"); | |
c021880a | 102 | |
5da627a4 | 103 | theKernel (linux_argc, linux_argv, linux_env, 0); |
cd7c596e | 104 | /* does not return */ |
40d7e99d | 105 | return 1; |
c021880a WD |
106 | } |
107 | ||
5da627a4 | 108 | static void linux_params_init (ulong start, char *line) |
c021880a | 109 | { |
5da627a4 | 110 | char *next, *quote, *argp; |
8bde7f77 | 111 | |
5da627a4 WD |
112 | linux_argc = 1; |
113 | linux_argv = (char **) start; | |
114 | linux_argv[0] = 0; | |
115 | argp = (char *) (linux_argv + LINUX_MAX_ARGS); | |
116 | ||
117 | next = line; | |
c021880a | 118 | |
5da627a4 WD |
119 | while (line && *line && linux_argc < LINUX_MAX_ARGS) { |
120 | quote = strchr (line, '"'); | |
121 | next = strchr (line, ' '); | |
c021880a | 122 | |
5da627a4 WD |
123 | while (next != NULL && quote != NULL && quote < next) { |
124 | /* we found a left quote before the next blank | |
125 | * now we have to find the matching right quote | |
126 | */ | |
127 | next = strchr (quote + 1, '"'); | |
128 | if (next != NULL) { | |
129 | quote = strchr (next + 1, '"'); | |
130 | next = strchr (next + 1, ' '); | |
131 | } | |
132 | } | |
8bde7f77 | 133 | |
5da627a4 WD |
134 | if (next == NULL) { |
135 | next = line + strlen (line); | |
136 | } | |
8bde7f77 | 137 | |
5da627a4 WD |
138 | linux_argv[linux_argc] = argp; |
139 | memcpy (argp, line, next - line); | |
140 | argp[next - line] = 0; | |
c021880a | 141 | |
5da627a4 WD |
142 | argp += next - line + 1; |
143 | linux_argc++; | |
144 | ||
145 | if (*next) | |
146 | next++; | |
147 | ||
148 | line = next; | |
149 | } | |
150 | ||
151 | linux_env = (char **) (((ulong) argp + 15) & ~15); | |
152 | linux_env[0] = 0; | |
153 | linux_env_p = (char *) (linux_env + LINUX_MAX_ENVS); | |
154 | linux_env_idx = 0; | |
c021880a WD |
155 | } |
156 | ||
5da627a4 | 157 | static void linux_env_set (char *env_name, char *env_val) |
c021880a | 158 | { |
5da627a4 WD |
159 | if (linux_env_idx < LINUX_MAX_ENVS - 1) { |
160 | linux_env[linux_env_idx] = linux_env_p; | |
c021880a | 161 | |
5da627a4 WD |
162 | strcpy (linux_env_p, env_name); |
163 | linux_env_p += strlen (env_name); | |
c021880a | 164 | |
5da627a4 WD |
165 | strcpy (linux_env_p, "="); |
166 | linux_env_p += 1; | |
c021880a | 167 | |
5da627a4 WD |
168 | strcpy (linux_env_p, env_val); |
169 | linux_env_p += strlen (env_val); | |
8bde7f77 | 170 | |
5da627a4 WD |
171 | linux_env_p++; |
172 | linux_env[++linux_env_idx] = 0; | |
173 | } | |
c021880a | 174 | } |