xref: /rk3399_rockchip-uboot/arch/mips/lib/bootm.c (revision ea0364f1bbfed1e3ea711147420875cf338fe77a)
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