]>
Commit | Line | Data |
---|---|---|
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 |
15 | DECLARE_GLOBAL_DATA_PTR; |
16 | ||
c021880a WD |
17 | #define LINUX_MAX_ENVS 256 |
18 | #define LINUX_MAX_ARGS 256 | |
19 | ||
e51a6b7a DS |
20 | static int linux_argc; |
21 | static char **linux_argv; | |
c021880a | 22 | |
e51a6b7a DS |
23 | static char **linux_env; |
24 | static char *linux_env_p; | |
25 | static int linux_env_idx; | |
c021880a | 26 | |
e51a6b7a DS |
27 | static void linux_params_init(ulong start, char *commandline); |
28 | static void linux_env_set(char *env_name, char *env_val); | |
c021880a | 29 | |
0ea7213f | 30 | static 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 | ||
70 | static 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 | ||
88 | int 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 | 112 | static 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 | 160 | static 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 | } |