]> git.ipfire.org Git - people/ms/u-boot.git/blame - arch/mips/lib/bootm.c
mpc5200: Misc updates to a3m071 config header
[people/ms/u-boot.git] / arch / mips / lib / bootm.c
CommitLineData
c021880a
WD
1/*
2 * (C) Copyright 2003
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
1a459660 5 * SPDX-License-Identifier: GPL-2.0+
c021880a
WD
6 */
7
8#include <common.h>
9#include <command.h>
c021880a 10#include <image.h>
a31e091a 11#include <u-boot/zlib.h>
c021880a
WD
12#include <asm/byteorder.h>
13#include <asm/addrspace.h>
14
d87080b7
WD
15DECLARE_GLOBAL_DATA_PTR;
16
c021880a
WD
17#define LINUX_MAX_ENVS 256
18#define LINUX_MAX_ARGS 256
19
e51a6b7a
DS
20static int linux_argc;
21static char **linux_argv;
c021880a 22
e51a6b7a
DS
23static char **linux_env;
24static char *linux_env_p;
25static int linux_env_idx;
c021880a 26
e51a6b7a
DS
27static void linux_params_init(ulong start, char *commandline);
28static void linux_env_set(char *env_name, char *env_val);
c021880a 29
0ea7213f 30static void boot_prep_linux(bootm_headers_t *images)
c021880a 31{
e51a6b7a
DS
32 char *commandline = getenv("bootargs");
33 char env_buf[12];
34 char *cp;
f13e7b2e 35
e51a6b7a 36 linux_params_init(UNCACHED_SDRAM(gd->bd->bi_boot_params), commandline);
5da627a4
WD
37
38#ifdef CONFIG_MEMSIZE_IN_BYTES
e51a6b7a
DS
39 sprintf(env_buf, "%lu", (ulong)gd->ram_size);
40 debug("## Giving linux memsize in bytes, %lu\n", (ulong)gd->ram_size);
5da627a4 41#else
e51a6b7a
DS
42 sprintf(env_buf, "%lu", (ulong)(gd->ram_size >> 20));
43 debug("## Giving linux memsize in MB, %lu\n",
44 (ulong)(gd->ram_size >> 20));
5da627a4 45#endif /* CONFIG_MEMSIZE_IN_BYTES */
c021880a 46
e51a6b7a 47 linux_env_set("memsize", env_buf);
c021880a 48
e51a6b7a
DS
49 sprintf(env_buf, "0x%08X", (uint) UNCACHED_SDRAM(images->rd_start));
50 linux_env_set("initrd_start", env_buf);
c021880a 51
e51a6b7a
DS
52 sprintf(env_buf, "0x%X", (uint) (images->rd_end - images->rd_start));
53 linux_env_set("initrd_size", env_buf);
c021880a 54
e51a6b7a
DS
55 sprintf(env_buf, "0x%08X", (uint) (gd->bd->bi_flashstart));
56 linux_env_set("flash_start", env_buf);
c021880a 57
e51a6b7a
DS
58 sprintf(env_buf, "0x%X", (uint) (gd->bd->bi_flashsize));
59 linux_env_set("flash_size", env_buf);
c021880a 60
e7c37452 61 cp = getenv("ethaddr");
e51a6b7a 62 if (cp)
e7c37452 63 linux_env_set("ethaddr", cp);
e7c37452
JM
64
65 cp = getenv("eth1addr");
e51a6b7a 66 if (cp)
e7c37452 67 linux_env_set("eth1addr", cp);
0ea7213f
GJ
68}
69
70static void boot_jump_linux(bootm_headers_t *images)
71{
72 void (*theKernel) (int, char **, char **, int *);
73
74 /* find kernel entry point */
75 theKernel = (void (*)(int, char **, char **, int *))images->ep;
76
77 debug("## Transferring control to Linux (at address %08lx) ...\n",
78 (ulong) theKernel);
79
80 bootstage_mark(BOOTSTAGE_ID_RUN_OS);
81
82 /* we assume that the kernel is in place */
83 printf("\nStarting kernel ...\n\n");
84
85 theKernel(linux_argc, linux_argv, linux_env, 0);
86}
87
88int do_bootm_linux(int flag, int argc, char * const argv[],
89 bootm_headers_t *images)
90{
9c170e2e
GJ
91 /* No need for those on MIPS */
92 if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE)
93 return -1;
94
95 if (flag & BOOTM_STATE_OS_PREP) {
96 boot_prep_linux(images);
97 return 0;
98 }
99
100 if (flag & BOOTM_STATE_OS_GO) {
101 boot_jump_linux(images);
102 return 0;
103 }
e7c37452 104
0ea7213f 105 boot_prep_linux(images);
e08634c7 106 boot_jump_linux(images);
c021880a 107
cd7c596e 108 /* does not return */
40d7e99d 109 return 1;
c021880a
WD
110}
111
e51a6b7a 112static void linux_params_init(ulong start, char *line)
c021880a 113{
5da627a4 114 char *next, *quote, *argp;
8bde7f77 115
5da627a4
WD
116 linux_argc = 1;
117 linux_argv = (char **) start;
118 linux_argv[0] = 0;
119 argp = (char *) (linux_argv + LINUX_MAX_ARGS);
120
121 next = line;
c021880a 122
5da627a4 123 while (line && *line && linux_argc < LINUX_MAX_ARGS) {
e51a6b7a
DS
124 quote = strchr(line, '"');
125 next = strchr(line, ' ');
c021880a 126
e51a6b7a 127 while (next && quote && quote < next) {
5da627a4
WD
128 /* we found a left quote before the next blank
129 * now we have to find the matching right quote
130 */
e51a6b7a
DS
131 next = strchr(quote + 1, '"');
132 if (next) {
133 quote = strchr(next + 1, '"');
134 next = strchr(next + 1, ' ');
5da627a4
WD
135 }
136 }
8bde7f77 137
e51a6b7a
DS
138 if (!next)
139 next = line + strlen(line);
8bde7f77 140
5da627a4 141 linux_argv[linux_argc] = argp;
e51a6b7a 142 memcpy(argp, line, next - line);
5da627a4 143 argp[next - line] = 0;
c021880a 144
5da627a4
WD
145 argp += next - line + 1;
146 linux_argc++;
147
148 if (*next)
149 next++;
150
151 line = next;
152 }
153
154 linux_env = (char **) (((ulong) argp + 15) & ~15);
155 linux_env[0] = 0;
156 linux_env_p = (char *) (linux_env + LINUX_MAX_ENVS);
157 linux_env_idx = 0;
c021880a
WD
158}
159
e51a6b7a 160static void linux_env_set(char *env_name, char *env_val)
c021880a 161{
5da627a4
WD
162 if (linux_env_idx < LINUX_MAX_ENVS - 1) {
163 linux_env[linux_env_idx] = linux_env_p;
c021880a 164
e51a6b7a
DS
165 strcpy(linux_env_p, env_name);
166 linux_env_p += strlen(env_name);
c021880a 167
e51a6b7a 168 strcpy(linux_env_p, "=");
5da627a4 169 linux_env_p += 1;
c021880a 170
e51a6b7a
DS
171 strcpy(linux_env_p, env_val);
172 linux_env_p += strlen(env_val);
8bde7f77 173
5da627a4
WD
174 linux_env_p++;
175 linux_env[++linux_env_idx] = 0;
176 }
c021880a 177}