xref: /rk3399_rockchip-uboot/arch/mips/lib/bootm.c (revision c4b37847d3f8f98335253bd0e7aeee3ba141b237)
1ea0364f1SPeter Tyser /*
2ea0364f1SPeter Tyser  * (C) Copyright 2003
3ea0364f1SPeter Tyser  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4ea0364f1SPeter Tyser  *
51a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
6ea0364f1SPeter Tyser  */
7ea0364f1SPeter Tyser 
8ea0364f1SPeter Tyser #include <common.h>
9ea0364f1SPeter Tyser #include <command.h>
10ea0364f1SPeter Tyser #include <image.h>
11ea0364f1SPeter Tyser #include <u-boot/zlib.h>
12ea0364f1SPeter Tyser #include <asm/byteorder.h>
13ea0364f1SPeter Tyser #include <asm/addrspace.h>
14ea0364f1SPeter Tyser 
15ea0364f1SPeter Tyser DECLARE_GLOBAL_DATA_PTR;
16ea0364f1SPeter Tyser 
17ea0364f1SPeter Tyser #define	LINUX_MAX_ENVS		256
18ea0364f1SPeter Tyser #define	LINUX_MAX_ARGS		256
19ea0364f1SPeter Tyser 
20ea0364f1SPeter Tyser static int linux_argc;
21ea0364f1SPeter Tyser static char **linux_argv;
22ea0364f1SPeter Tyser 
23ea0364f1SPeter Tyser static char **linux_env;
24ea0364f1SPeter Tyser static char *linux_env_p;
25ea0364f1SPeter Tyser static int linux_env_idx;
26ea0364f1SPeter Tyser 
27ea0364f1SPeter Tyser static void linux_params_init(ulong start, char *commandline);
28ea0364f1SPeter Tyser static void linux_env_set(char *env_name, char *env_val);
29ea0364f1SPeter Tyser 
300ea7213fSGabor Juhos static void boot_prep_linux(bootm_headers_t *images)
31ea0364f1SPeter Tyser {
32ea0364f1SPeter Tyser 	char *commandline = getenv("bootargs");
33ea0364f1SPeter Tyser 	char env_buf[12];
34ea0364f1SPeter Tyser 	char *cp;
35ea0364f1SPeter Tyser 
36ea0364f1SPeter Tyser 	linux_params_init(UNCACHED_SDRAM(gd->bd->bi_boot_params), commandline);
37ea0364f1SPeter Tyser 
38ea0364f1SPeter Tyser #ifdef CONFIG_MEMSIZE_IN_BYTES
39ea0364f1SPeter Tyser 	sprintf(env_buf, "%lu", (ulong)gd->ram_size);
40ea0364f1SPeter Tyser 	debug("## Giving linux memsize in bytes, %lu\n", (ulong)gd->ram_size);
41ea0364f1SPeter Tyser #else
42ea0364f1SPeter Tyser 	sprintf(env_buf, "%lu", (ulong)(gd->ram_size >> 20));
43e51a6b7aSDaniel Schwierzeck 	debug("## Giving linux memsize in MB, %lu\n",
44e51a6b7aSDaniel Schwierzeck 	      (ulong)(gd->ram_size >> 20));
45ea0364f1SPeter Tyser #endif /* CONFIG_MEMSIZE_IN_BYTES */
46ea0364f1SPeter Tyser 
47ea0364f1SPeter Tyser 	linux_env_set("memsize", env_buf);
48ea0364f1SPeter Tyser 
49ea0364f1SPeter Tyser 	sprintf(env_buf, "0x%08X", (uint) UNCACHED_SDRAM(images->rd_start));
50ea0364f1SPeter Tyser 	linux_env_set("initrd_start", env_buf);
51ea0364f1SPeter Tyser 
52ea0364f1SPeter Tyser 	sprintf(env_buf, "0x%X", (uint) (images->rd_end - images->rd_start));
53ea0364f1SPeter Tyser 	linux_env_set("initrd_size", env_buf);
54ea0364f1SPeter Tyser 
55ea0364f1SPeter Tyser 	sprintf(env_buf, "0x%08X", (uint) (gd->bd->bi_flashstart));
56ea0364f1SPeter Tyser 	linux_env_set("flash_start", env_buf);
57ea0364f1SPeter Tyser 
58ea0364f1SPeter Tyser 	sprintf(env_buf, "0x%X", (uint) (gd->bd->bi_flashsize));
59ea0364f1SPeter Tyser 	linux_env_set("flash_size", env_buf);
60ea0364f1SPeter Tyser 
61ea0364f1SPeter Tyser 	cp = getenv("ethaddr");
62e51a6b7aSDaniel Schwierzeck 	if (cp)
63ea0364f1SPeter Tyser 		linux_env_set("ethaddr", cp);
64ea0364f1SPeter Tyser 
65ea0364f1SPeter Tyser 	cp = getenv("eth1addr");
66e51a6b7aSDaniel Schwierzeck 	if (cp)
67ea0364f1SPeter Tyser 		linux_env_set("eth1addr", cp);
680ea7213fSGabor Juhos }
69ea0364f1SPeter Tyser 
700ea7213fSGabor Juhos static void boot_jump_linux(bootm_headers_t *images)
710ea7213fSGabor Juhos {
72*c4b37847SDaniel Schwierzeck 	typedef void __noreturn (*kernel_entry_t)(int, ulong, ulong, ulong);
73*c4b37847SDaniel Schwierzeck 	kernel_entry_t kernel = (kernel_entry_t) images->ep;
740ea7213fSGabor Juhos 
75*c4b37847SDaniel Schwierzeck 	debug("## Transferring control to Linux (at address %p) ...\n", kernel);
760ea7213fSGabor Juhos 
770ea7213fSGabor Juhos 	bootstage_mark(BOOTSTAGE_ID_RUN_OS);
780ea7213fSGabor Juhos 
790ea7213fSGabor Juhos 	/* we assume that the kernel is in place */
800ea7213fSGabor Juhos 	printf("\nStarting kernel ...\n\n");
810ea7213fSGabor Juhos 
82*c4b37847SDaniel Schwierzeck 	kernel(linux_argc, (ulong)linux_argv, (ulong)linux_env, 0);
830ea7213fSGabor Juhos }
840ea7213fSGabor Juhos 
850ea7213fSGabor Juhos int do_bootm_linux(int flag, int argc, char * const argv[],
860ea7213fSGabor Juhos 			bootm_headers_t *images)
870ea7213fSGabor Juhos {
889c170e2eSGabor Juhos 	/* No need for those on MIPS */
899c170e2eSGabor Juhos 	if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE)
909c170e2eSGabor Juhos 		return -1;
919c170e2eSGabor Juhos 
929c170e2eSGabor Juhos 	if (flag & BOOTM_STATE_OS_PREP) {
939c170e2eSGabor Juhos 		boot_prep_linux(images);
949c170e2eSGabor Juhos 		return 0;
959c170e2eSGabor Juhos 	}
969c170e2eSGabor Juhos 
979c170e2eSGabor Juhos 	if (flag & BOOTM_STATE_OS_GO) {
989c170e2eSGabor Juhos 		boot_jump_linux(images);
999c170e2eSGabor Juhos 		return 0;
1009c170e2eSGabor Juhos 	}
1010ea7213fSGabor Juhos 
1020ea7213fSGabor Juhos 	boot_prep_linux(images);
103e08634c7SGabor Juhos 	boot_jump_linux(images);
104e51a6b7aSDaniel Schwierzeck 
105ea0364f1SPeter Tyser 	/* does not return */
106ea0364f1SPeter Tyser 	return 1;
107ea0364f1SPeter Tyser }
108ea0364f1SPeter Tyser 
109ea0364f1SPeter Tyser static void linux_params_init(ulong start, char *line)
110ea0364f1SPeter Tyser {
111ea0364f1SPeter Tyser 	char *next, *quote, *argp;
112ea0364f1SPeter Tyser 
113ea0364f1SPeter Tyser 	linux_argc = 1;
114ea0364f1SPeter Tyser 	linux_argv = (char **)start;
115ea0364f1SPeter Tyser 	linux_argv[0] = 0;
116ea0364f1SPeter Tyser 	argp = (char *)(linux_argv + LINUX_MAX_ARGS);
117ea0364f1SPeter Tyser 
118ea0364f1SPeter Tyser 	next = line;
119ea0364f1SPeter Tyser 
120ea0364f1SPeter Tyser 	while (line && *line && linux_argc < LINUX_MAX_ARGS) {
121ea0364f1SPeter Tyser 		quote = strchr(line, '"');
122ea0364f1SPeter Tyser 		next = strchr(line, ' ');
123ea0364f1SPeter Tyser 
124e51a6b7aSDaniel Schwierzeck 		while (next && quote && quote < next) {
12545bde489SDaniel Schwierzeck 			/*
12645bde489SDaniel Schwierzeck 			 * we found a left quote before the next blank
127ea0364f1SPeter Tyser 			 * now we have to find the matching right quote
128ea0364f1SPeter Tyser 			 */
129ea0364f1SPeter Tyser 			next = strchr(quote + 1, '"');
130e51a6b7aSDaniel Schwierzeck 			if (next) {
131ea0364f1SPeter Tyser 				quote = strchr(next + 1, '"');
132ea0364f1SPeter Tyser 				next = strchr(next + 1, ' ');
133ea0364f1SPeter Tyser 			}
134ea0364f1SPeter Tyser 		}
135ea0364f1SPeter Tyser 
136e51a6b7aSDaniel Schwierzeck 		if (!next)
137ea0364f1SPeter Tyser 			next = line + strlen(line);
138ea0364f1SPeter Tyser 
139ea0364f1SPeter Tyser 		linux_argv[linux_argc] = argp;
140ea0364f1SPeter Tyser 		memcpy(argp, line, next - line);
141ea0364f1SPeter Tyser 		argp[next - line] = 0;
142ea0364f1SPeter Tyser 
143ea0364f1SPeter Tyser 		argp += next - line + 1;
144ea0364f1SPeter Tyser 		linux_argc++;
145ea0364f1SPeter Tyser 
146ea0364f1SPeter Tyser 		if (*next)
147ea0364f1SPeter Tyser 			next++;
148ea0364f1SPeter Tyser 
149ea0364f1SPeter Tyser 		line = next;
150ea0364f1SPeter Tyser 	}
151ea0364f1SPeter Tyser 
152ea0364f1SPeter Tyser 	linux_env = (char **)(((ulong) argp + 15) & ~15);
153ea0364f1SPeter Tyser 	linux_env[0] = 0;
154ea0364f1SPeter Tyser 	linux_env_p = (char *)(linux_env + LINUX_MAX_ENVS);
155ea0364f1SPeter Tyser 	linux_env_idx = 0;
156ea0364f1SPeter Tyser }
157ea0364f1SPeter Tyser 
158ea0364f1SPeter Tyser static void linux_env_set(char *env_name, char *env_val)
159ea0364f1SPeter Tyser {
160ea0364f1SPeter Tyser 	if (linux_env_idx < LINUX_MAX_ENVS - 1) {
161ea0364f1SPeter Tyser 		linux_env[linux_env_idx] = linux_env_p;
162ea0364f1SPeter Tyser 
163ea0364f1SPeter Tyser 		strcpy(linux_env_p, env_name);
164ea0364f1SPeter Tyser 		linux_env_p += strlen(env_name);
165ea0364f1SPeter Tyser 
166ea0364f1SPeter Tyser 		strcpy(linux_env_p, "=");
167ea0364f1SPeter Tyser 		linux_env_p += 1;
168ea0364f1SPeter Tyser 
169ea0364f1SPeter Tyser 		strcpy(linux_env_p, env_val);
170ea0364f1SPeter Tyser 		linux_env_p += strlen(env_val);
171ea0364f1SPeter Tyser 
172ea0364f1SPeter Tyser 		linux_env_p++;
173ea0364f1SPeter Tyser 		linux_env[++linux_env_idx] = 0;
174ea0364f1SPeter Tyser 	}
175ea0364f1SPeter Tyser }
176