Commit 9c3483113de1204118a1b252bf4c81b899dd12b4
Committed by
Albert ARIBAUD
1 parent
2627c8c0a1
Exists in
master
and in
54 other branches
common: add possibility for readline_into_buffer timeout
add possibility to add a timeout when reading a line into a buffer. Signed-off-by: Heiko Schocher <hs@denx.de> Cc: Mike Frysinger <vapier@gentoo.org> Acked-by: Mike Frysinger <vapier@gentoo.org>
Showing 4 changed files with 21 additions and 7 deletions Inline Diff
common/cmd_nvedit.c
1 | /* | 1 | /* |
2 | * (C) Copyright 2000-2010 | 2 | * (C) Copyright 2000-2010 |
3 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | 3 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. |
4 | * | 4 | * |
5 | * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com> | 5 | * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com> |
6 | * Andreas Heppel <aheppel@sysgo.de> | 6 | * Andreas Heppel <aheppel@sysgo.de> |
7 | * | 7 | * |
8 | * Copyright 2011 Freescale Semiconductor, Inc. | 8 | * Copyright 2011 Freescale Semiconductor, Inc. |
9 | * | 9 | * |
10 | * See file CREDITS for list of people who contributed to this | 10 | * See file CREDITS for list of people who contributed to this |
11 | * project. | 11 | * project. |
12 | * | 12 | * |
13 | * This program is free software; you can redistribute it and/or | 13 | * This program is free software; you can redistribute it and/or |
14 | * modify it under the terms of the GNU General Public License as | 14 | * modify it under the terms of the GNU General Public License as |
15 | * published by the Free Software Foundation; either version 2 of | 15 | * published by the Free Software Foundation; either version 2 of |
16 | * the License, or (at your option) any later version. | 16 | * the License, or (at your option) any later version. |
17 | * | 17 | * |
18 | * This program is distributed in the hope that it will be useful, | 18 | * This program is distributed in the hope that it will be useful, |
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
21 | * GNU General Public License for more details. | 21 | * GNU General Public License for more details. |
22 | * | 22 | * |
23 | * You should have received a copy of the GNU General Public License | 23 | * You should have received a copy of the GNU General Public License |
24 | * along with this program; if not, write to the Free Software | 24 | * along with this program; if not, write to the Free Software |
25 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | 25 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
26 | * MA 02111-1307 USA | 26 | * MA 02111-1307 USA |
27 | */ | 27 | */ |
28 | 28 | ||
29 | /* | 29 | /* |
30 | * Support for persistent environment data | 30 | * Support for persistent environment data |
31 | * | 31 | * |
32 | * The "environment" is stored on external storage as a list of '\0' | 32 | * The "environment" is stored on external storage as a list of '\0' |
33 | * terminated "name=value" strings. The end of the list is marked by | 33 | * terminated "name=value" strings. The end of the list is marked by |
34 | * a double '\0'. The environment is preceeded by a 32 bit CRC over | 34 | * a double '\0'. The environment is preceeded by a 32 bit CRC over |
35 | * the data part and, in case of redundant environment, a byte of | 35 | * the data part and, in case of redundant environment, a byte of |
36 | * flags. | 36 | * flags. |
37 | * | 37 | * |
38 | * This linearized representation will also be used before | 38 | * This linearized representation will also be used before |
39 | * relocation, i. e. as long as we don't have a full C runtime | 39 | * relocation, i. e. as long as we don't have a full C runtime |
40 | * environment. After that, we use a hash table. | 40 | * environment. After that, we use a hash table. |
41 | */ | 41 | */ |
42 | 42 | ||
43 | #include <common.h> | 43 | #include <common.h> |
44 | #include <command.h> | 44 | #include <command.h> |
45 | #include <environment.h> | 45 | #include <environment.h> |
46 | #include <search.h> | 46 | #include <search.h> |
47 | #include <errno.h> | 47 | #include <errno.h> |
48 | #include <malloc.h> | 48 | #include <malloc.h> |
49 | #include <watchdog.h> | 49 | #include <watchdog.h> |
50 | #include <serial.h> | 50 | #include <serial.h> |
51 | #include <linux/stddef.h> | 51 | #include <linux/stddef.h> |
52 | #include <asm/byteorder.h> | 52 | #include <asm/byteorder.h> |
53 | #if defined(CONFIG_CMD_NET) | 53 | #if defined(CONFIG_CMD_NET) |
54 | #include <net.h> | 54 | #include <net.h> |
55 | #endif | 55 | #endif |
56 | 56 | ||
57 | DECLARE_GLOBAL_DATA_PTR; | 57 | DECLARE_GLOBAL_DATA_PTR; |
58 | 58 | ||
59 | #if !defined(CONFIG_ENV_IS_IN_EEPROM) && \ | 59 | #if !defined(CONFIG_ENV_IS_IN_EEPROM) && \ |
60 | !defined(CONFIG_ENV_IS_IN_FLASH) && \ | 60 | !defined(CONFIG_ENV_IS_IN_FLASH) && \ |
61 | !defined(CONFIG_ENV_IS_IN_DATAFLASH) && \ | 61 | !defined(CONFIG_ENV_IS_IN_DATAFLASH) && \ |
62 | !defined(CONFIG_ENV_IS_IN_MG_DISK) && \ | 62 | !defined(CONFIG_ENV_IS_IN_MG_DISK) && \ |
63 | !defined(CONFIG_ENV_IS_IN_MMC) && \ | 63 | !defined(CONFIG_ENV_IS_IN_MMC) && \ |
64 | !defined(CONFIG_ENV_IS_IN_NAND) && \ | 64 | !defined(CONFIG_ENV_IS_IN_NAND) && \ |
65 | !defined(CONFIG_ENV_IS_IN_NVRAM) && \ | 65 | !defined(CONFIG_ENV_IS_IN_NVRAM) && \ |
66 | !defined(CONFIG_ENV_IS_IN_ONENAND) && \ | 66 | !defined(CONFIG_ENV_IS_IN_ONENAND) && \ |
67 | !defined(CONFIG_ENV_IS_IN_SPI_FLASH) && \ | 67 | !defined(CONFIG_ENV_IS_IN_SPI_FLASH) && \ |
68 | !defined(CONFIG_ENV_IS_NOWHERE) | 68 | !defined(CONFIG_ENV_IS_NOWHERE) |
69 | # error Define one of CONFIG_ENV_IS_IN_{EEPROM|FLASH|DATAFLASH|ONENAND|\ | 69 | # error Define one of CONFIG_ENV_IS_IN_{EEPROM|FLASH|DATAFLASH|ONENAND|\ |
70 | SPI_FLASH|MG_DISK|NVRAM|MMC} or CONFIG_ENV_IS_NOWHERE | 70 | SPI_FLASH|MG_DISK|NVRAM|MMC} or CONFIG_ENV_IS_NOWHERE |
71 | #endif | 71 | #endif |
72 | 72 | ||
73 | #define XMK_STR(x) #x | 73 | #define XMK_STR(x) #x |
74 | #define MK_STR(x) XMK_STR(x) | 74 | #define MK_STR(x) XMK_STR(x) |
75 | 75 | ||
76 | /* | 76 | /* |
77 | * Maximum expected input data size for import command | 77 | * Maximum expected input data size for import command |
78 | */ | 78 | */ |
79 | #define MAX_ENV_SIZE (1 << 20) /* 1 MiB */ | 79 | #define MAX_ENV_SIZE (1 << 20) /* 1 MiB */ |
80 | 80 | ||
81 | ulong load_addr = CONFIG_SYS_LOAD_ADDR; /* Default Load Address */ | 81 | ulong load_addr = CONFIG_SYS_LOAD_ADDR; /* Default Load Address */ |
82 | ulong save_addr; /* Default Save Address */ | 82 | ulong save_addr; /* Default Save Address */ |
83 | ulong save_size; /* Default Save Size (in bytes) */ | 83 | ulong save_size; /* Default Save Size (in bytes) */ |
84 | 84 | ||
85 | /* | 85 | /* |
86 | * Table with supported baudrates (defined in config_xyz.h) | 86 | * Table with supported baudrates (defined in config_xyz.h) |
87 | */ | 87 | */ |
88 | static const unsigned long baudrate_table[] = CONFIG_SYS_BAUDRATE_TABLE; | 88 | static const unsigned long baudrate_table[] = CONFIG_SYS_BAUDRATE_TABLE; |
89 | #define N_BAUDRATES (sizeof(baudrate_table) / sizeof(baudrate_table[0])) | 89 | #define N_BAUDRATES (sizeof(baudrate_table) / sizeof(baudrate_table[0])) |
90 | 90 | ||
91 | /* | 91 | /* |
92 | * This variable is incremented on each do_env_set(), so it can | 92 | * This variable is incremented on each do_env_set(), so it can |
93 | * be used via get_env_id() as an indication, if the environment | 93 | * be used via get_env_id() as an indication, if the environment |
94 | * has changed or not. So it is possible to reread an environment | 94 | * has changed or not. So it is possible to reread an environment |
95 | * variable only if the environment was changed ... done so for | 95 | * variable only if the environment was changed ... done so for |
96 | * example in NetInitLoop() | 96 | * example in NetInitLoop() |
97 | */ | 97 | */ |
98 | static int env_id = 1; | 98 | static int env_id = 1; |
99 | 99 | ||
100 | int get_env_id(void) | 100 | int get_env_id(void) |
101 | { | 101 | { |
102 | return env_id; | 102 | return env_id; |
103 | } | 103 | } |
104 | 104 | ||
105 | /* | 105 | /* |
106 | * Command interface: print one or all environment variables | 106 | * Command interface: print one or all environment variables |
107 | * | 107 | * |
108 | * Returns 0 in case of error, or length of printed string | 108 | * Returns 0 in case of error, or length of printed string |
109 | */ | 109 | */ |
110 | static int env_print(char *name) | 110 | static int env_print(char *name) |
111 | { | 111 | { |
112 | char *res = NULL; | 112 | char *res = NULL; |
113 | size_t len; | 113 | size_t len; |
114 | 114 | ||
115 | if (name) { /* print a single name */ | 115 | if (name) { /* print a single name */ |
116 | ENTRY e, *ep; | 116 | ENTRY e, *ep; |
117 | 117 | ||
118 | e.key = name; | 118 | e.key = name; |
119 | e.data = NULL; | 119 | e.data = NULL; |
120 | hsearch_r(e, FIND, &ep, &env_htab); | 120 | hsearch_r(e, FIND, &ep, &env_htab); |
121 | if (ep == NULL) | 121 | if (ep == NULL) |
122 | return 0; | 122 | return 0; |
123 | len = printf("%s=%s\n", ep->key, ep->data); | 123 | len = printf("%s=%s\n", ep->key, ep->data); |
124 | return len; | 124 | return len; |
125 | } | 125 | } |
126 | 126 | ||
127 | /* print whole list */ | 127 | /* print whole list */ |
128 | len = hexport_r(&env_htab, '\n', &res, 0, 0, NULL); | 128 | len = hexport_r(&env_htab, '\n', &res, 0, 0, NULL); |
129 | 129 | ||
130 | if (len > 0) { | 130 | if (len > 0) { |
131 | puts(res); | 131 | puts(res); |
132 | free(res); | 132 | free(res); |
133 | return len; | 133 | return len; |
134 | } | 134 | } |
135 | 135 | ||
136 | /* should never happen */ | 136 | /* should never happen */ |
137 | return 0; | 137 | return 0; |
138 | } | 138 | } |
139 | 139 | ||
140 | int do_env_print (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | 140 | int do_env_print (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
141 | { | 141 | { |
142 | int i; | 142 | int i; |
143 | int rcode = 0; | 143 | int rcode = 0; |
144 | 144 | ||
145 | if (argc == 1) { | 145 | if (argc == 1) { |
146 | /* print all env vars */ | 146 | /* print all env vars */ |
147 | rcode = env_print(NULL); | 147 | rcode = env_print(NULL); |
148 | if (!rcode) | 148 | if (!rcode) |
149 | return 1; | 149 | return 1; |
150 | printf("\nEnvironment size: %d/%ld bytes\n", | 150 | printf("\nEnvironment size: %d/%ld bytes\n", |
151 | rcode, (ulong)ENV_SIZE); | 151 | rcode, (ulong)ENV_SIZE); |
152 | return 0; | 152 | return 0; |
153 | } | 153 | } |
154 | 154 | ||
155 | /* print selected env vars */ | 155 | /* print selected env vars */ |
156 | for (i = 1; i < argc; ++i) { | 156 | for (i = 1; i < argc; ++i) { |
157 | int rc = env_print(argv[i]); | 157 | int rc = env_print(argv[i]); |
158 | if (!rc) { | 158 | if (!rc) { |
159 | printf("## Error: \"%s\" not defined\n", argv[i]); | 159 | printf("## Error: \"%s\" not defined\n", argv[i]); |
160 | ++rcode; | 160 | ++rcode; |
161 | } | 161 | } |
162 | } | 162 | } |
163 | 163 | ||
164 | return rcode; | 164 | return rcode; |
165 | } | 165 | } |
166 | 166 | ||
167 | #ifdef CONFIG_CMD_GREPENV | 167 | #ifdef CONFIG_CMD_GREPENV |
168 | static int do_env_grep(cmd_tbl_t *cmdtp, int flag, | 168 | static int do_env_grep(cmd_tbl_t *cmdtp, int flag, |
169 | int argc, char * const argv[]) | 169 | int argc, char * const argv[]) |
170 | { | 170 | { |
171 | ENTRY *match; | 171 | ENTRY *match; |
172 | unsigned char matched[env_htab.size / 8]; | 172 | unsigned char matched[env_htab.size / 8]; |
173 | int rcode = 1, arg = 1, idx; | 173 | int rcode = 1, arg = 1, idx; |
174 | 174 | ||
175 | if (argc < 2) | 175 | if (argc < 2) |
176 | return cmd_usage(cmdtp); | 176 | return cmd_usage(cmdtp); |
177 | 177 | ||
178 | memset(matched, 0, env_htab.size / 8); | 178 | memset(matched, 0, env_htab.size / 8); |
179 | 179 | ||
180 | while (arg <= argc) { | 180 | while (arg <= argc) { |
181 | idx = 0; | 181 | idx = 0; |
182 | while ((idx = hstrstr_r(argv[arg], idx, &match, &env_htab))) { | 182 | while ((idx = hstrstr_r(argv[arg], idx, &match, &env_htab))) { |
183 | if (!(matched[idx / 8] & (1 << (idx & 7)))) { | 183 | if (!(matched[idx / 8] & (1 << (idx & 7)))) { |
184 | puts(match->key); | 184 | puts(match->key); |
185 | puts("="); | 185 | puts("="); |
186 | puts(match->data); | 186 | puts(match->data); |
187 | puts("\n"); | 187 | puts("\n"); |
188 | } | 188 | } |
189 | matched[idx / 8] |= 1 << (idx & 7); | 189 | matched[idx / 8] |= 1 << (idx & 7); |
190 | rcode = 0; | 190 | rcode = 0; |
191 | } | 191 | } |
192 | arg++; | 192 | arg++; |
193 | } | 193 | } |
194 | 194 | ||
195 | return rcode; | 195 | return rcode; |
196 | } | 196 | } |
197 | #endif | 197 | #endif |
198 | 198 | ||
199 | /* | 199 | /* |
200 | * Set a new environment variable, | 200 | * Set a new environment variable, |
201 | * or replace or delete an existing one. | 201 | * or replace or delete an existing one. |
202 | */ | 202 | */ |
203 | int _do_env_set(int flag, int argc, char * const argv[]) | 203 | int _do_env_set(int flag, int argc, char * const argv[]) |
204 | { | 204 | { |
205 | bd_t *bd = gd->bd; | 205 | bd_t *bd = gd->bd; |
206 | int i, len; | 206 | int i, len; |
207 | int console = -1; | 207 | int console = -1; |
208 | char *name, *value, *s; | 208 | char *name, *value, *s; |
209 | ENTRY e, *ep; | 209 | ENTRY e, *ep; |
210 | 210 | ||
211 | name = argv[1]; | 211 | name = argv[1]; |
212 | 212 | ||
213 | if (strchr(name, '=')) { | 213 | if (strchr(name, '=')) { |
214 | printf("## Error: illegal character '=' in variable name" | 214 | printf("## Error: illegal character '=' in variable name" |
215 | "\"%s\"\n", name); | 215 | "\"%s\"\n", name); |
216 | return 1; | 216 | return 1; |
217 | } | 217 | } |
218 | 218 | ||
219 | env_id++; | 219 | env_id++; |
220 | /* | 220 | /* |
221 | * search if variable with this name already exists | 221 | * search if variable with this name already exists |
222 | */ | 222 | */ |
223 | e.key = name; | 223 | e.key = name; |
224 | e.data = NULL; | 224 | e.data = NULL; |
225 | hsearch_r(e, FIND, &ep, &env_htab); | 225 | hsearch_r(e, FIND, &ep, &env_htab); |
226 | 226 | ||
227 | /* Check for console redirection */ | 227 | /* Check for console redirection */ |
228 | if (strcmp(name, "stdin") == 0) | 228 | if (strcmp(name, "stdin") == 0) |
229 | console = stdin; | 229 | console = stdin; |
230 | else if (strcmp(name, "stdout") == 0) | 230 | else if (strcmp(name, "stdout") == 0) |
231 | console = stdout; | 231 | console = stdout; |
232 | else if (strcmp(name, "stderr") == 0) | 232 | else if (strcmp(name, "stderr") == 0) |
233 | console = stderr; | 233 | console = stderr; |
234 | 234 | ||
235 | if (console != -1) { | 235 | if (console != -1) { |
236 | if (argc < 3) { /* Cannot delete it! */ | 236 | if (argc < 3) { /* Cannot delete it! */ |
237 | printf("Can't delete \"%s\"\n", name); | 237 | printf("Can't delete \"%s\"\n", name); |
238 | return 1; | 238 | return 1; |
239 | } | 239 | } |
240 | 240 | ||
241 | #ifdef CONFIG_CONSOLE_MUX | 241 | #ifdef CONFIG_CONSOLE_MUX |
242 | i = iomux_doenv(console, argv[2]); | 242 | i = iomux_doenv(console, argv[2]); |
243 | if (i) | 243 | if (i) |
244 | return i; | 244 | return i; |
245 | #else | 245 | #else |
246 | /* Try assigning specified device */ | 246 | /* Try assigning specified device */ |
247 | if (console_assign(console, argv[2]) < 0) | 247 | if (console_assign(console, argv[2]) < 0) |
248 | return 1; | 248 | return 1; |
249 | 249 | ||
250 | #ifdef CONFIG_SERIAL_MULTI | 250 | #ifdef CONFIG_SERIAL_MULTI |
251 | if (serial_assign(argv[2]) < 0) | 251 | if (serial_assign(argv[2]) < 0) |
252 | return 1; | 252 | return 1; |
253 | #endif | 253 | #endif |
254 | #endif /* CONFIG_CONSOLE_MUX */ | 254 | #endif /* CONFIG_CONSOLE_MUX */ |
255 | } | 255 | } |
256 | 256 | ||
257 | /* | 257 | /* |
258 | * Some variables like "ethaddr" and "serial#" can be set only | 258 | * Some variables like "ethaddr" and "serial#" can be set only |
259 | * once and cannot be deleted; also, "ver" is readonly. | 259 | * once and cannot be deleted; also, "ver" is readonly. |
260 | */ | 260 | */ |
261 | if (ep) { /* variable exists */ | 261 | if (ep) { /* variable exists */ |
262 | #ifndef CONFIG_ENV_OVERWRITE | 262 | #ifndef CONFIG_ENV_OVERWRITE |
263 | if (strcmp(name, "serial#") == 0 || | 263 | if (strcmp(name, "serial#") == 0 || |
264 | (strcmp(name, "ethaddr") == 0 | 264 | (strcmp(name, "ethaddr") == 0 |
265 | #if defined(CONFIG_OVERWRITE_ETHADDR_ONCE) && defined(CONFIG_ETHADDR) | 265 | #if defined(CONFIG_OVERWRITE_ETHADDR_ONCE) && defined(CONFIG_ETHADDR) |
266 | && strcmp(ep->data, MK_STR(CONFIG_ETHADDR)) != 0 | 266 | && strcmp(ep->data, MK_STR(CONFIG_ETHADDR)) != 0 |
267 | #endif /* CONFIG_OVERWRITE_ETHADDR_ONCE && CONFIG_ETHADDR */ | 267 | #endif /* CONFIG_OVERWRITE_ETHADDR_ONCE && CONFIG_ETHADDR */ |
268 | )) { | 268 | )) { |
269 | printf("Can't overwrite \"%s\"\n", name); | 269 | printf("Can't overwrite \"%s\"\n", name); |
270 | return 1; | 270 | return 1; |
271 | } | 271 | } |
272 | #endif | 272 | #endif |
273 | /* | 273 | /* |
274 | * Switch to new baudrate if new baudrate is supported | 274 | * Switch to new baudrate if new baudrate is supported |
275 | */ | 275 | */ |
276 | if (strcmp(name, "baudrate") == 0) { | 276 | if (strcmp(name, "baudrate") == 0) { |
277 | int baudrate = simple_strtoul(argv[2], NULL, 10); | 277 | int baudrate = simple_strtoul(argv[2], NULL, 10); |
278 | int i; | 278 | int i; |
279 | for (i = 0; i < N_BAUDRATES; ++i) { | 279 | for (i = 0; i < N_BAUDRATES; ++i) { |
280 | if (baudrate == baudrate_table[i]) | 280 | if (baudrate == baudrate_table[i]) |
281 | break; | 281 | break; |
282 | } | 282 | } |
283 | if (i == N_BAUDRATES) { | 283 | if (i == N_BAUDRATES) { |
284 | printf("## Baudrate %d bps not supported\n", | 284 | printf("## Baudrate %d bps not supported\n", |
285 | baudrate); | 285 | baudrate); |
286 | return 1; | 286 | return 1; |
287 | } | 287 | } |
288 | printf("## Switch baudrate to %d bps and" | 288 | printf("## Switch baudrate to %d bps and" |
289 | "press ENTER ...\n", baudrate); | 289 | "press ENTER ...\n", baudrate); |
290 | udelay(50000); | 290 | udelay(50000); |
291 | gd->baudrate = baudrate; | 291 | gd->baudrate = baudrate; |
292 | #if defined(CONFIG_PPC) || defined(CONFIG_MCF52x2) | 292 | #if defined(CONFIG_PPC) || defined(CONFIG_MCF52x2) |
293 | gd->bd->bi_baudrate = baudrate; | 293 | gd->bd->bi_baudrate = baudrate; |
294 | #endif | 294 | #endif |
295 | 295 | ||
296 | serial_setbrg(); | 296 | serial_setbrg(); |
297 | udelay(50000); | 297 | udelay(50000); |
298 | while (getc() != '\r') | 298 | while (getc() != '\r') |
299 | ; | 299 | ; |
300 | } | 300 | } |
301 | } | 301 | } |
302 | 302 | ||
303 | /* Delete only ? */ | 303 | /* Delete only ? */ |
304 | if (argc < 3 || argv[2] == NULL) { | 304 | if (argc < 3 || argv[2] == NULL) { |
305 | int rc = hdelete_r(name, &env_htab); | 305 | int rc = hdelete_r(name, &env_htab); |
306 | return !rc; | 306 | return !rc; |
307 | } | 307 | } |
308 | 308 | ||
309 | /* | 309 | /* |
310 | * Insert / replace new value | 310 | * Insert / replace new value |
311 | */ | 311 | */ |
312 | for (i = 2, len = 0; i < argc; ++i) | 312 | for (i = 2, len = 0; i < argc; ++i) |
313 | len += strlen(argv[i]) + 1; | 313 | len += strlen(argv[i]) + 1; |
314 | 314 | ||
315 | value = malloc(len); | 315 | value = malloc(len); |
316 | if (value == NULL) { | 316 | if (value == NULL) { |
317 | printf("## Can't malloc %d bytes\n", len); | 317 | printf("## Can't malloc %d bytes\n", len); |
318 | return 1; | 318 | return 1; |
319 | } | 319 | } |
320 | for (i = 2, s = value; i < argc; ++i) { | 320 | for (i = 2, s = value; i < argc; ++i) { |
321 | char *v = argv[i]; | 321 | char *v = argv[i]; |
322 | 322 | ||
323 | while ((*s++ = *v++) != '\0') | 323 | while ((*s++ = *v++) != '\0') |
324 | ; | 324 | ; |
325 | *(s - 1) = ' '; | 325 | *(s - 1) = ' '; |
326 | } | 326 | } |
327 | if (s != value) | 327 | if (s != value) |
328 | *--s = '\0'; | 328 | *--s = '\0'; |
329 | 329 | ||
330 | e.key = name; | 330 | e.key = name; |
331 | e.data = value; | 331 | e.data = value; |
332 | hsearch_r(e, ENTER, &ep, &env_htab); | 332 | hsearch_r(e, ENTER, &ep, &env_htab); |
333 | free(value); | 333 | free(value); |
334 | if (!ep) { | 334 | if (!ep) { |
335 | printf("## Error inserting \"%s\" variable, errno=%d\n", | 335 | printf("## Error inserting \"%s\" variable, errno=%d\n", |
336 | name, errno); | 336 | name, errno); |
337 | return 1; | 337 | return 1; |
338 | } | 338 | } |
339 | 339 | ||
340 | /* | 340 | /* |
341 | * Some variables should be updated when the corresponding | 341 | * Some variables should be updated when the corresponding |
342 | * entry in the environment is changed | 342 | * entry in the environment is changed |
343 | */ | 343 | */ |
344 | if (strcmp(name, "ipaddr") == 0) { | 344 | if (strcmp(name, "ipaddr") == 0) { |
345 | char *s = argv[2]; /* always use only one arg */ | 345 | char *s = argv[2]; /* always use only one arg */ |
346 | char *e; | 346 | char *e; |
347 | unsigned long addr; | 347 | unsigned long addr; |
348 | bd->bi_ip_addr = 0; | 348 | bd->bi_ip_addr = 0; |
349 | for (addr = 0, i = 0; i < 4; ++i) { | 349 | for (addr = 0, i = 0; i < 4; ++i) { |
350 | ulong val = s ? simple_strtoul(s, &e, 10) : 0; | 350 | ulong val = s ? simple_strtoul(s, &e, 10) : 0; |
351 | addr <<= 8; | 351 | addr <<= 8; |
352 | addr |= val & 0xFF; | 352 | addr |= val & 0xFF; |
353 | if (s) | 353 | if (s) |
354 | s = *e ? e + 1 : e; | 354 | s = *e ? e + 1 : e; |
355 | } | 355 | } |
356 | bd->bi_ip_addr = htonl(addr); | 356 | bd->bi_ip_addr = htonl(addr); |
357 | return 0; | 357 | return 0; |
358 | } else if (strcmp(argv[1], "loadaddr") == 0) { | 358 | } else if (strcmp(argv[1], "loadaddr") == 0) { |
359 | load_addr = simple_strtoul(argv[2], NULL, 16); | 359 | load_addr = simple_strtoul(argv[2], NULL, 16); |
360 | return 0; | 360 | return 0; |
361 | } | 361 | } |
362 | #if defined(CONFIG_CMD_NET) | 362 | #if defined(CONFIG_CMD_NET) |
363 | else if (strcmp(argv[1], "bootfile") == 0) { | 363 | else if (strcmp(argv[1], "bootfile") == 0) { |
364 | copy_filename(BootFile, argv[2], sizeof(BootFile)); | 364 | copy_filename(BootFile, argv[2], sizeof(BootFile)); |
365 | return 0; | 365 | return 0; |
366 | } | 366 | } |
367 | #endif | 367 | #endif |
368 | return 0; | 368 | return 0; |
369 | } | 369 | } |
370 | 370 | ||
371 | int setenv(const char *varname, const char *varvalue) | 371 | int setenv(const char *varname, const char *varvalue) |
372 | { | 372 | { |
373 | const char * const argv[4] = { "setenv", varname, varvalue, NULL }; | 373 | const char * const argv[4] = { "setenv", varname, varvalue, NULL }; |
374 | 374 | ||
375 | if (varvalue == NULL || varvalue[0] == '\0') | 375 | if (varvalue == NULL || varvalue[0] == '\0') |
376 | return _do_env_set(0, 2, (char * const *)argv); | 376 | return _do_env_set(0, 2, (char * const *)argv); |
377 | else | 377 | else |
378 | return _do_env_set(0, 3, (char * const *)argv); | 378 | return _do_env_set(0, 3, (char * const *)argv); |
379 | } | 379 | } |
380 | 380 | ||
381 | /** | 381 | /** |
382 | * Set an environment variable to an integer value | 382 | * Set an environment variable to an integer value |
383 | * | 383 | * |
384 | * @param varname Environmet variable to set | 384 | * @param varname Environmet variable to set |
385 | * @param value Value to set it to | 385 | * @param value Value to set it to |
386 | * @return 0 if ok, 1 on error | 386 | * @return 0 if ok, 1 on error |
387 | */ | 387 | */ |
388 | int setenv_ulong(const char *varname, ulong value) | 388 | int setenv_ulong(const char *varname, ulong value) |
389 | { | 389 | { |
390 | /* TODO: this should be unsigned */ | 390 | /* TODO: this should be unsigned */ |
391 | char *str = simple_itoa(value); | 391 | char *str = simple_itoa(value); |
392 | 392 | ||
393 | return setenv(varname, str); | 393 | return setenv(varname, str); |
394 | } | 394 | } |
395 | 395 | ||
396 | /** | 396 | /** |
397 | * Set an environment variable to an address in hex | 397 | * Set an environment variable to an address in hex |
398 | * | 398 | * |
399 | * @param varname Environmet variable to set | 399 | * @param varname Environmet variable to set |
400 | * @param addr Value to set it to | 400 | * @param addr Value to set it to |
401 | * @return 0 if ok, 1 on error | 401 | * @return 0 if ok, 1 on error |
402 | */ | 402 | */ |
403 | int setenv_addr(const char *varname, const void *addr) | 403 | int setenv_addr(const char *varname, const void *addr) |
404 | { | 404 | { |
405 | char str[17]; | 405 | char str[17]; |
406 | 406 | ||
407 | sprintf(str, "%lx", (uintptr_t)addr); | 407 | sprintf(str, "%lx", (uintptr_t)addr); |
408 | return setenv(varname, str); | 408 | return setenv(varname, str); |
409 | } | 409 | } |
410 | 410 | ||
411 | int do_env_set(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | 411 | int do_env_set(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
412 | { | 412 | { |
413 | if (argc < 2) | 413 | if (argc < 2) |
414 | return cmd_usage(cmdtp); | 414 | return cmd_usage(cmdtp); |
415 | 415 | ||
416 | return _do_env_set(flag, argc, argv); | 416 | return _do_env_set(flag, argc, argv); |
417 | } | 417 | } |
418 | 418 | ||
419 | /* | 419 | /* |
420 | * Prompt for environment variable | 420 | * Prompt for environment variable |
421 | */ | 421 | */ |
422 | #if defined(CONFIG_CMD_ASKENV) | 422 | #if defined(CONFIG_CMD_ASKENV) |
423 | int do_env_ask(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | 423 | int do_env_ask(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
424 | { | 424 | { |
425 | char message[CONFIG_SYS_CBSIZE]; | 425 | char message[CONFIG_SYS_CBSIZE]; |
426 | int size = CONFIG_SYS_CBSIZE - 1; | 426 | int size = CONFIG_SYS_CBSIZE - 1; |
427 | int i, len, pos; | 427 | int i, len, pos; |
428 | char *local_args[4]; | 428 | char *local_args[4]; |
429 | 429 | ||
430 | local_args[0] = argv[0]; | 430 | local_args[0] = argv[0]; |
431 | local_args[1] = argv[1]; | 431 | local_args[1] = argv[1]; |
432 | local_args[2] = NULL; | 432 | local_args[2] = NULL; |
433 | local_args[3] = NULL; | 433 | local_args[3] = NULL; |
434 | 434 | ||
435 | /* Check the syntax */ | 435 | /* Check the syntax */ |
436 | switch (argc) { | 436 | switch (argc) { |
437 | case 1: | 437 | case 1: |
438 | return cmd_usage(cmdtp); | 438 | return cmd_usage(cmdtp); |
439 | 439 | ||
440 | case 2: /* env_ask envname */ | 440 | case 2: /* env_ask envname */ |
441 | sprintf(message, "Please enter '%s':", argv[1]); | 441 | sprintf(message, "Please enter '%s':", argv[1]); |
442 | break; | 442 | break; |
443 | 443 | ||
444 | case 3: /* env_ask envname size */ | 444 | case 3: /* env_ask envname size */ |
445 | sprintf(message, "Please enter '%s':", argv[1]); | 445 | sprintf(message, "Please enter '%s':", argv[1]); |
446 | size = simple_strtoul(argv[2], NULL, 10); | 446 | size = simple_strtoul(argv[2], NULL, 10); |
447 | break; | 447 | break; |
448 | 448 | ||
449 | default: /* env_ask envname message1 ... messagen size */ | 449 | default: /* env_ask envname message1 ... messagen size */ |
450 | for (i = 2, pos = 0; i < argc - 1; i++) { | 450 | for (i = 2, pos = 0; i < argc - 1; i++) { |
451 | if (pos) | 451 | if (pos) |
452 | message[pos++] = ' '; | 452 | message[pos++] = ' '; |
453 | 453 | ||
454 | strcpy(message + pos, argv[i]); | 454 | strcpy(message + pos, argv[i]); |
455 | pos += strlen(argv[i]); | 455 | pos += strlen(argv[i]); |
456 | } | 456 | } |
457 | 457 | ||
458 | message[pos] = '\0'; | 458 | message[pos] = '\0'; |
459 | size = simple_strtoul(argv[argc - 1], NULL, 10); | 459 | size = simple_strtoul(argv[argc - 1], NULL, 10); |
460 | break; | 460 | break; |
461 | } | 461 | } |
462 | 462 | ||
463 | if (size >= CONFIG_SYS_CBSIZE) | 463 | if (size >= CONFIG_SYS_CBSIZE) |
464 | size = CONFIG_SYS_CBSIZE - 1; | 464 | size = CONFIG_SYS_CBSIZE - 1; |
465 | 465 | ||
466 | if (size <= 0) | 466 | if (size <= 0) |
467 | return 1; | 467 | return 1; |
468 | 468 | ||
469 | /* prompt for input */ | 469 | /* prompt for input */ |
470 | len = readline(message); | 470 | len = readline(message); |
471 | 471 | ||
472 | if (size < len) | 472 | if (size < len) |
473 | console_buffer[size] = '\0'; | 473 | console_buffer[size] = '\0'; |
474 | 474 | ||
475 | len = 2; | 475 | len = 2; |
476 | if (console_buffer[0] != '\0') { | 476 | if (console_buffer[0] != '\0') { |
477 | local_args[2] = console_buffer; | 477 | local_args[2] = console_buffer; |
478 | len = 3; | 478 | len = 3; |
479 | } | 479 | } |
480 | 480 | ||
481 | /* Continue calling setenv code */ | 481 | /* Continue calling setenv code */ |
482 | return _do_env_set(flag, len, local_args); | 482 | return _do_env_set(flag, len, local_args); |
483 | } | 483 | } |
484 | #endif | 484 | #endif |
485 | 485 | ||
486 | /* | 486 | /* |
487 | * Interactively edit an environment variable | 487 | * Interactively edit an environment variable |
488 | */ | 488 | */ |
489 | #if defined(CONFIG_CMD_EDITENV) | 489 | #if defined(CONFIG_CMD_EDITENV) |
490 | int do_env_edit(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | 490 | int do_env_edit(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
491 | { | 491 | { |
492 | char buffer[CONFIG_SYS_CBSIZE]; | 492 | char buffer[CONFIG_SYS_CBSIZE]; |
493 | char *init_val; | 493 | char *init_val; |
494 | 494 | ||
495 | if (argc < 2) | 495 | if (argc < 2) |
496 | return cmd_usage(cmdtp); | 496 | return cmd_usage(cmdtp); |
497 | 497 | ||
498 | /* Set read buffer to initial value or empty sting */ | 498 | /* Set read buffer to initial value or empty sting */ |
499 | init_val = getenv(argv[1]); | 499 | init_val = getenv(argv[1]); |
500 | if (init_val) | 500 | if (init_val) |
501 | sprintf(buffer, "%s", init_val); | 501 | sprintf(buffer, "%s", init_val); |
502 | else | 502 | else |
503 | buffer[0] = '\0'; | 503 | buffer[0] = '\0'; |
504 | 504 | ||
505 | readline_into_buffer("edit: ", buffer); | 505 | readline_into_buffer("edit: ", buffer, 0); |
506 | 506 | ||
507 | return setenv(argv[1], buffer); | 507 | return setenv(argv[1], buffer); |
508 | } | 508 | } |
509 | #endif /* CONFIG_CMD_EDITENV */ | 509 | #endif /* CONFIG_CMD_EDITENV */ |
510 | 510 | ||
511 | /* | 511 | /* |
512 | * Look up variable from environment, | 512 | * Look up variable from environment, |
513 | * return address of storage for that variable, | 513 | * return address of storage for that variable, |
514 | * or NULL if not found | 514 | * or NULL if not found |
515 | */ | 515 | */ |
516 | char *getenv(const char *name) | 516 | char *getenv(const char *name) |
517 | { | 517 | { |
518 | if (gd->flags & GD_FLG_ENV_READY) { /* after import into hashtable */ | 518 | if (gd->flags & GD_FLG_ENV_READY) { /* after import into hashtable */ |
519 | ENTRY e, *ep; | 519 | ENTRY e, *ep; |
520 | 520 | ||
521 | WATCHDOG_RESET(); | 521 | WATCHDOG_RESET(); |
522 | 522 | ||
523 | e.key = name; | 523 | e.key = name; |
524 | e.data = NULL; | 524 | e.data = NULL; |
525 | hsearch_r(e, FIND, &ep, &env_htab); | 525 | hsearch_r(e, FIND, &ep, &env_htab); |
526 | 526 | ||
527 | return ep ? ep->data : NULL; | 527 | return ep ? ep->data : NULL; |
528 | } | 528 | } |
529 | 529 | ||
530 | /* restricted capabilities before import */ | 530 | /* restricted capabilities before import */ |
531 | if (getenv_f(name, (char *)(gd->env_buf), sizeof(gd->env_buf)) > 0) | 531 | if (getenv_f(name, (char *)(gd->env_buf), sizeof(gd->env_buf)) > 0) |
532 | return (char *)(gd->env_buf); | 532 | return (char *)(gd->env_buf); |
533 | 533 | ||
534 | return NULL; | 534 | return NULL; |
535 | } | 535 | } |
536 | 536 | ||
537 | /* | 537 | /* |
538 | * Look up variable from environment for restricted C runtime env. | 538 | * Look up variable from environment for restricted C runtime env. |
539 | */ | 539 | */ |
540 | int getenv_f(const char *name, char *buf, unsigned len) | 540 | int getenv_f(const char *name, char *buf, unsigned len) |
541 | { | 541 | { |
542 | int i, nxt; | 542 | int i, nxt; |
543 | 543 | ||
544 | for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) { | 544 | for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) { |
545 | int val, n; | 545 | int val, n; |
546 | 546 | ||
547 | for (nxt = i; env_get_char(nxt) != '\0'; ++nxt) { | 547 | for (nxt = i; env_get_char(nxt) != '\0'; ++nxt) { |
548 | if (nxt >= CONFIG_ENV_SIZE) | 548 | if (nxt >= CONFIG_ENV_SIZE) |
549 | return -1; | 549 | return -1; |
550 | } | 550 | } |
551 | 551 | ||
552 | val = envmatch((uchar *)name, i); | 552 | val = envmatch((uchar *)name, i); |
553 | if (val < 0) | 553 | if (val < 0) |
554 | continue; | 554 | continue; |
555 | 555 | ||
556 | /* found; copy out */ | 556 | /* found; copy out */ |
557 | for (n = 0; n < len; ++n, ++buf) { | 557 | for (n = 0; n < len; ++n, ++buf) { |
558 | *buf = env_get_char(val++); | 558 | *buf = env_get_char(val++); |
559 | if (*buf == '\0') | 559 | if (*buf == '\0') |
560 | return n; | 560 | return n; |
561 | } | 561 | } |
562 | 562 | ||
563 | if (n) | 563 | if (n) |
564 | *--buf = '\0'; | 564 | *--buf = '\0'; |
565 | 565 | ||
566 | printf("env_buf [%d bytes] too small for value of \"%s\"\n", | 566 | printf("env_buf [%d bytes] too small for value of \"%s\"\n", |
567 | len, name); | 567 | len, name); |
568 | 568 | ||
569 | return n; | 569 | return n; |
570 | } | 570 | } |
571 | 571 | ||
572 | return -1; | 572 | return -1; |
573 | } | 573 | } |
574 | 574 | ||
575 | /** | 575 | /** |
576 | * Decode the integer value of an environment variable and return it. | 576 | * Decode the integer value of an environment variable and return it. |
577 | * | 577 | * |
578 | * @param name Name of environemnt variable | 578 | * @param name Name of environemnt variable |
579 | * @param base Number base to use (normally 10, or 16 for hex) | 579 | * @param base Number base to use (normally 10, or 16 for hex) |
580 | * @param default_val Default value to return if the variable is not | 580 | * @param default_val Default value to return if the variable is not |
581 | * found | 581 | * found |
582 | * @return the decoded value, or default_val if not found | 582 | * @return the decoded value, or default_val if not found |
583 | */ | 583 | */ |
584 | ulong getenv_ulong(const char *name, int base, ulong default_val) | 584 | ulong getenv_ulong(const char *name, int base, ulong default_val) |
585 | { | 585 | { |
586 | /* | 586 | /* |
587 | * We can use getenv() here, even before relocation, since the | 587 | * We can use getenv() here, even before relocation, since the |
588 | * environment variable value is an integer and thus short. | 588 | * environment variable value is an integer and thus short. |
589 | */ | 589 | */ |
590 | const char *str = getenv(name); | 590 | const char *str = getenv(name); |
591 | 591 | ||
592 | return str ? simple_strtoul(str, NULL, base) : default_val; | 592 | return str ? simple_strtoul(str, NULL, base) : default_val; |
593 | } | 593 | } |
594 | 594 | ||
595 | #if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE) | 595 | #if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE) |
596 | int do_env_save(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | 596 | int do_env_save(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
597 | { | 597 | { |
598 | printf("Saving Environment to %s...\n", env_name_spec); | 598 | printf("Saving Environment to %s...\n", env_name_spec); |
599 | 599 | ||
600 | return saveenv() ? 1 : 0; | 600 | return saveenv() ? 1 : 0; |
601 | } | 601 | } |
602 | 602 | ||
603 | U_BOOT_CMD( | 603 | U_BOOT_CMD( |
604 | saveenv, 1, 0, do_env_save, | 604 | saveenv, 1, 0, do_env_save, |
605 | "save environment variables to persistent storage", | 605 | "save environment variables to persistent storage", |
606 | "" | 606 | "" |
607 | ); | 607 | ); |
608 | #endif | 608 | #endif |
609 | 609 | ||
610 | 610 | ||
611 | /* | 611 | /* |
612 | * Match a name / name=value pair | 612 | * Match a name / name=value pair |
613 | * | 613 | * |
614 | * s1 is either a simple 'name', or a 'name=value' pair. | 614 | * s1 is either a simple 'name', or a 'name=value' pair. |
615 | * i2 is the environment index for a 'name2=value2' pair. | 615 | * i2 is the environment index for a 'name2=value2' pair. |
616 | * If the names match, return the index for the value2, else -1. | 616 | * If the names match, return the index for the value2, else -1. |
617 | */ | 617 | */ |
618 | int envmatch(uchar *s1, int i2) | 618 | int envmatch(uchar *s1, int i2) |
619 | { | 619 | { |
620 | while (*s1 == env_get_char(i2++)) | 620 | while (*s1 == env_get_char(i2++)) |
621 | if (*s1++ == '=') | 621 | if (*s1++ == '=') |
622 | return i2; | 622 | return i2; |
623 | 623 | ||
624 | if (*s1 == '\0' && env_get_char(i2-1) == '=') | 624 | if (*s1 == '\0' && env_get_char(i2-1) == '=') |
625 | return i2; | 625 | return i2; |
626 | 626 | ||
627 | return -1; | 627 | return -1; |
628 | } | 628 | } |
629 | 629 | ||
630 | static int do_env_default(cmd_tbl_t *cmdtp, int flag, | 630 | static int do_env_default(cmd_tbl_t *cmdtp, int flag, |
631 | int argc, char * const argv[]) | 631 | int argc, char * const argv[]) |
632 | { | 632 | { |
633 | if (argc != 2 || strcmp(argv[1], "-f") != 0) | 633 | if (argc != 2 || strcmp(argv[1], "-f") != 0) |
634 | return cmd_usage(cmdtp); | 634 | return cmd_usage(cmdtp); |
635 | 635 | ||
636 | set_default_env("## Resetting to default environment\n"); | 636 | set_default_env("## Resetting to default environment\n"); |
637 | return 0; | 637 | return 0; |
638 | } | 638 | } |
639 | 639 | ||
640 | static int do_env_delete(cmd_tbl_t *cmdtp, int flag, | 640 | static int do_env_delete(cmd_tbl_t *cmdtp, int flag, |
641 | int argc, char * const argv[]) | 641 | int argc, char * const argv[]) |
642 | { | 642 | { |
643 | printf("Not implemented yet\n"); | 643 | printf("Not implemented yet\n"); |
644 | return 0; | 644 | return 0; |
645 | } | 645 | } |
646 | 646 | ||
647 | #ifdef CONFIG_CMD_EXPORTENV | 647 | #ifdef CONFIG_CMD_EXPORTENV |
648 | /* | 648 | /* |
649 | * env export [-t | -b | -c] [-s size] addr [var ...] | 649 | * env export [-t | -b | -c] [-s size] addr [var ...] |
650 | * -t: export as text format; if size is given, data will be | 650 | * -t: export as text format; if size is given, data will be |
651 | * padded with '\0' bytes; if not, one terminating '\0' | 651 | * padded with '\0' bytes; if not, one terminating '\0' |
652 | * will be added (which is included in the "filesize" | 652 | * will be added (which is included in the "filesize" |
653 | * setting so you can for exmple copy this to flash and | 653 | * setting so you can for exmple copy this to flash and |
654 | * keep the termination). | 654 | * keep the termination). |
655 | * -b: export as binary format (name=value pairs separated by | 655 | * -b: export as binary format (name=value pairs separated by |
656 | * '\0', list end marked by double "\0\0") | 656 | * '\0', list end marked by double "\0\0") |
657 | * -c: export as checksum protected environment format as | 657 | * -c: export as checksum protected environment format as |
658 | * used for example by "saveenv" command | 658 | * used for example by "saveenv" command |
659 | * -s size: | 659 | * -s size: |
660 | * size of output buffer | 660 | * size of output buffer |
661 | * addr: memory address where environment gets stored | 661 | * addr: memory address where environment gets stored |
662 | * var... List of variable names that get included into the | 662 | * var... List of variable names that get included into the |
663 | * export. Without arguments, the whole environment gets | 663 | * export. Without arguments, the whole environment gets |
664 | * exported. | 664 | * exported. |
665 | * | 665 | * |
666 | * With "-c" and size is NOT given, then the export command will | 666 | * With "-c" and size is NOT given, then the export command will |
667 | * format the data as currently used for the persistent storage, | 667 | * format the data as currently used for the persistent storage, |
668 | * i. e. it will use CONFIG_ENV_SECT_SIZE as output block size and | 668 | * i. e. it will use CONFIG_ENV_SECT_SIZE as output block size and |
669 | * prepend a valid CRC32 checksum and, in case of resundant | 669 | * prepend a valid CRC32 checksum and, in case of resundant |
670 | * environment, a "current" redundancy flag. If size is given, this | 670 | * environment, a "current" redundancy flag. If size is given, this |
671 | * value will be used instead of CONFIG_ENV_SECT_SIZE; again, CRC32 | 671 | * value will be used instead of CONFIG_ENV_SECT_SIZE; again, CRC32 |
672 | * checksum and redundancy flag will be inserted. | 672 | * checksum and redundancy flag will be inserted. |
673 | * | 673 | * |
674 | * With "-b" and "-t", always only the real data (including a | 674 | * With "-b" and "-t", always only the real data (including a |
675 | * terminating '\0' byte) will be written; here the optional size | 675 | * terminating '\0' byte) will be written; here the optional size |
676 | * argument will be used to make sure not to overflow the user | 676 | * argument will be used to make sure not to overflow the user |
677 | * provided buffer; the command will abort if the size is not | 677 | * provided buffer; the command will abort if the size is not |
678 | * sufficient. Any remainign space will be '\0' padded. | 678 | * sufficient. Any remainign space will be '\0' padded. |
679 | * | 679 | * |
680 | * On successful return, the variable "filesize" will be set. | 680 | * On successful return, the variable "filesize" will be set. |
681 | * Note that filesize includes the trailing/terminating '\0' byte(s). | 681 | * Note that filesize includes the trailing/terminating '\0' byte(s). |
682 | * | 682 | * |
683 | * Usage szenario: create a text snapshot/backup of the current settings: | 683 | * Usage szenario: create a text snapshot/backup of the current settings: |
684 | * | 684 | * |
685 | * => env export -t 100000 | 685 | * => env export -t 100000 |
686 | * => era ${backup_addr} +${filesize} | 686 | * => era ${backup_addr} +${filesize} |
687 | * => cp.b 100000 ${backup_addr} ${filesize} | 687 | * => cp.b 100000 ${backup_addr} ${filesize} |
688 | * | 688 | * |
689 | * Re-import this snapshot, deleting all other settings: | 689 | * Re-import this snapshot, deleting all other settings: |
690 | * | 690 | * |
691 | * => env import -d -t ${backup_addr} | 691 | * => env import -d -t ${backup_addr} |
692 | */ | 692 | */ |
693 | static int do_env_export(cmd_tbl_t *cmdtp, int flag, | 693 | static int do_env_export(cmd_tbl_t *cmdtp, int flag, |
694 | int argc, char * const argv[]) | 694 | int argc, char * const argv[]) |
695 | { | 695 | { |
696 | char buf[32]; | 696 | char buf[32]; |
697 | char *addr, *cmd, *res; | 697 | char *addr, *cmd, *res; |
698 | size_t size = 0; | 698 | size_t size = 0; |
699 | ssize_t len; | 699 | ssize_t len; |
700 | env_t *envp; | 700 | env_t *envp; |
701 | char sep = '\n'; | 701 | char sep = '\n'; |
702 | int chk = 0; | 702 | int chk = 0; |
703 | int fmt = 0; | 703 | int fmt = 0; |
704 | 704 | ||
705 | cmd = *argv; | 705 | cmd = *argv; |
706 | 706 | ||
707 | while (--argc > 0 && **++argv == '-') { | 707 | while (--argc > 0 && **++argv == '-') { |
708 | char *arg = *argv; | 708 | char *arg = *argv; |
709 | while (*++arg) { | 709 | while (*++arg) { |
710 | switch (*arg) { | 710 | switch (*arg) { |
711 | case 'b': /* raw binary format */ | 711 | case 'b': /* raw binary format */ |
712 | if (fmt++) | 712 | if (fmt++) |
713 | goto sep_err; | 713 | goto sep_err; |
714 | sep = '\0'; | 714 | sep = '\0'; |
715 | break; | 715 | break; |
716 | case 'c': /* external checksum format */ | 716 | case 'c': /* external checksum format */ |
717 | if (fmt++) | 717 | if (fmt++) |
718 | goto sep_err; | 718 | goto sep_err; |
719 | sep = '\0'; | 719 | sep = '\0'; |
720 | chk = 1; | 720 | chk = 1; |
721 | break; | 721 | break; |
722 | case 's': /* size given */ | 722 | case 's': /* size given */ |
723 | if (--argc <= 0) | 723 | if (--argc <= 0) |
724 | return cmd_usage(cmdtp); | 724 | return cmd_usage(cmdtp); |
725 | size = simple_strtoul(*++argv, NULL, 16); | 725 | size = simple_strtoul(*++argv, NULL, 16); |
726 | goto NXTARG; | 726 | goto NXTARG; |
727 | case 't': /* text format */ | 727 | case 't': /* text format */ |
728 | if (fmt++) | 728 | if (fmt++) |
729 | goto sep_err; | 729 | goto sep_err; |
730 | sep = '\n'; | 730 | sep = '\n'; |
731 | break; | 731 | break; |
732 | default: | 732 | default: |
733 | return cmd_usage(cmdtp); | 733 | return cmd_usage(cmdtp); |
734 | } | 734 | } |
735 | } | 735 | } |
736 | NXTARG: ; | 736 | NXTARG: ; |
737 | } | 737 | } |
738 | 738 | ||
739 | if (argc < 1) | 739 | if (argc < 1) |
740 | return cmd_usage(cmdtp); | 740 | return cmd_usage(cmdtp); |
741 | 741 | ||
742 | addr = (char *)simple_strtoul(argv[0], NULL, 16); | 742 | addr = (char *)simple_strtoul(argv[0], NULL, 16); |
743 | 743 | ||
744 | if (size) | 744 | if (size) |
745 | memset(addr, '\0', size); | 745 | memset(addr, '\0', size); |
746 | 746 | ||
747 | argc--; | 747 | argc--; |
748 | argv++; | 748 | argv++; |
749 | 749 | ||
750 | if (sep) { /* export as text file */ | 750 | if (sep) { /* export as text file */ |
751 | len = hexport_r(&env_htab, sep, &addr, size, argc, argv); | 751 | len = hexport_r(&env_htab, sep, &addr, size, argc, argv); |
752 | if (len < 0) { | 752 | if (len < 0) { |
753 | error("Cannot export environment: errno = %d\n", errno); | 753 | error("Cannot export environment: errno = %d\n", errno); |
754 | return 1; | 754 | return 1; |
755 | } | 755 | } |
756 | sprintf(buf, "%zX", (size_t)len); | 756 | sprintf(buf, "%zX", (size_t)len); |
757 | setenv("filesize", buf); | 757 | setenv("filesize", buf); |
758 | 758 | ||
759 | return 0; | 759 | return 0; |
760 | } | 760 | } |
761 | 761 | ||
762 | envp = (env_t *)addr; | 762 | envp = (env_t *)addr; |
763 | 763 | ||
764 | if (chk) /* export as checksum protected block */ | 764 | if (chk) /* export as checksum protected block */ |
765 | res = (char *)envp->data; | 765 | res = (char *)envp->data; |
766 | else /* export as raw binary data */ | 766 | else /* export as raw binary data */ |
767 | res = addr; | 767 | res = addr; |
768 | 768 | ||
769 | len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, argc, argv); | 769 | len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, argc, argv); |
770 | if (len < 0) { | 770 | if (len < 0) { |
771 | error("Cannot export environment: errno = %d\n", errno); | 771 | error("Cannot export environment: errno = %d\n", errno); |
772 | return 1; | 772 | return 1; |
773 | } | 773 | } |
774 | 774 | ||
775 | if (chk) { | 775 | if (chk) { |
776 | envp->crc = crc32(0, envp->data, ENV_SIZE); | 776 | envp->crc = crc32(0, envp->data, ENV_SIZE); |
777 | #ifdef CONFIG_ENV_ADDR_REDUND | 777 | #ifdef CONFIG_ENV_ADDR_REDUND |
778 | envp->flags = ACTIVE_FLAG; | 778 | envp->flags = ACTIVE_FLAG; |
779 | #endif | 779 | #endif |
780 | } | 780 | } |
781 | sprintf(buf, "%zX", (size_t)(len + offsetof(env_t, data))); | 781 | sprintf(buf, "%zX", (size_t)(len + offsetof(env_t, data))); |
782 | setenv("filesize", buf); | 782 | setenv("filesize", buf); |
783 | 783 | ||
784 | return 0; | 784 | return 0; |
785 | 785 | ||
786 | sep_err: | 786 | sep_err: |
787 | printf("## %s: only one of \"-b\", \"-c\" or \"-t\" allowed\n", cmd); | 787 | printf("## %s: only one of \"-b\", \"-c\" or \"-t\" allowed\n", cmd); |
788 | return 1; | 788 | return 1; |
789 | } | 789 | } |
790 | #endif | 790 | #endif |
791 | 791 | ||
792 | #ifdef CONFIG_CMD_IMPORTENV | 792 | #ifdef CONFIG_CMD_IMPORTENV |
793 | /* | 793 | /* |
794 | * env import [-d] [-t | -b | -c] addr [size] | 794 | * env import [-d] [-t | -b | -c] addr [size] |
795 | * -d: delete existing environment before importing; | 795 | * -d: delete existing environment before importing; |
796 | * otherwise overwrite / append to existion definitions | 796 | * otherwise overwrite / append to existion definitions |
797 | * -t: assume text format; either "size" must be given or the | 797 | * -t: assume text format; either "size" must be given or the |
798 | * text data must be '\0' terminated | 798 | * text data must be '\0' terminated |
799 | * -b: assume binary format ('\0' separated, "\0\0" terminated) | 799 | * -b: assume binary format ('\0' separated, "\0\0" terminated) |
800 | * -c: assume checksum protected environment format | 800 | * -c: assume checksum protected environment format |
801 | * addr: memory address to read from | 801 | * addr: memory address to read from |
802 | * size: length of input data; if missing, proper '\0' | 802 | * size: length of input data; if missing, proper '\0' |
803 | * termination is mandatory | 803 | * termination is mandatory |
804 | */ | 804 | */ |
805 | static int do_env_import(cmd_tbl_t *cmdtp, int flag, | 805 | static int do_env_import(cmd_tbl_t *cmdtp, int flag, |
806 | int argc, char * const argv[]) | 806 | int argc, char * const argv[]) |
807 | { | 807 | { |
808 | char *cmd, *addr; | 808 | char *cmd, *addr; |
809 | char sep = '\n'; | 809 | char sep = '\n'; |
810 | int chk = 0; | 810 | int chk = 0; |
811 | int fmt = 0; | 811 | int fmt = 0; |
812 | int del = 0; | 812 | int del = 0; |
813 | size_t size; | 813 | size_t size; |
814 | 814 | ||
815 | cmd = *argv; | 815 | cmd = *argv; |
816 | 816 | ||
817 | while (--argc > 0 && **++argv == '-') { | 817 | while (--argc > 0 && **++argv == '-') { |
818 | char *arg = *argv; | 818 | char *arg = *argv; |
819 | while (*++arg) { | 819 | while (*++arg) { |
820 | switch (*arg) { | 820 | switch (*arg) { |
821 | case 'b': /* raw binary format */ | 821 | case 'b': /* raw binary format */ |
822 | if (fmt++) | 822 | if (fmt++) |
823 | goto sep_err; | 823 | goto sep_err; |
824 | sep = '\0'; | 824 | sep = '\0'; |
825 | break; | 825 | break; |
826 | case 'c': /* external checksum format */ | 826 | case 'c': /* external checksum format */ |
827 | if (fmt++) | 827 | if (fmt++) |
828 | goto sep_err; | 828 | goto sep_err; |
829 | sep = '\0'; | 829 | sep = '\0'; |
830 | chk = 1; | 830 | chk = 1; |
831 | break; | 831 | break; |
832 | case 't': /* text format */ | 832 | case 't': /* text format */ |
833 | if (fmt++) | 833 | if (fmt++) |
834 | goto sep_err; | 834 | goto sep_err; |
835 | sep = '\n'; | 835 | sep = '\n'; |
836 | break; | 836 | break; |
837 | case 'd': | 837 | case 'd': |
838 | del = 1; | 838 | del = 1; |
839 | break; | 839 | break; |
840 | default: | 840 | default: |
841 | return cmd_usage(cmdtp); | 841 | return cmd_usage(cmdtp); |
842 | } | 842 | } |
843 | } | 843 | } |
844 | } | 844 | } |
845 | 845 | ||
846 | if (argc < 1) | 846 | if (argc < 1) |
847 | return cmd_usage(cmdtp); | 847 | return cmd_usage(cmdtp); |
848 | 848 | ||
849 | if (!fmt) | 849 | if (!fmt) |
850 | printf("## Warning: defaulting to text format\n"); | 850 | printf("## Warning: defaulting to text format\n"); |
851 | 851 | ||
852 | addr = (char *)simple_strtoul(argv[0], NULL, 16); | 852 | addr = (char *)simple_strtoul(argv[0], NULL, 16); |
853 | 853 | ||
854 | if (argc == 2) { | 854 | if (argc == 2) { |
855 | size = simple_strtoul(argv[1], NULL, 16); | 855 | size = simple_strtoul(argv[1], NULL, 16); |
856 | } else { | 856 | } else { |
857 | char *s = addr; | 857 | char *s = addr; |
858 | 858 | ||
859 | size = 0; | 859 | size = 0; |
860 | 860 | ||
861 | while (size < MAX_ENV_SIZE) { | 861 | while (size < MAX_ENV_SIZE) { |
862 | if ((*s == sep) && (*(s+1) == '\0')) | 862 | if ((*s == sep) && (*(s+1) == '\0')) |
863 | break; | 863 | break; |
864 | ++s; | 864 | ++s; |
865 | ++size; | 865 | ++size; |
866 | } | 866 | } |
867 | if (size == MAX_ENV_SIZE) { | 867 | if (size == MAX_ENV_SIZE) { |
868 | printf("## Warning: Input data exceeds %d bytes" | 868 | printf("## Warning: Input data exceeds %d bytes" |
869 | " - truncated\n", MAX_ENV_SIZE); | 869 | " - truncated\n", MAX_ENV_SIZE); |
870 | } | 870 | } |
871 | size += 2; | 871 | size += 2; |
872 | printf("## Info: input data size = %zu = 0x%zX\n", size, size); | 872 | printf("## Info: input data size = %zu = 0x%zX\n", size, size); |
873 | } | 873 | } |
874 | 874 | ||
875 | if (chk) { | 875 | if (chk) { |
876 | uint32_t crc; | 876 | uint32_t crc; |
877 | env_t *ep = (env_t *)addr; | 877 | env_t *ep = (env_t *)addr; |
878 | 878 | ||
879 | size -= offsetof(env_t, data); | 879 | size -= offsetof(env_t, data); |
880 | memcpy(&crc, &ep->crc, sizeof(crc)); | 880 | memcpy(&crc, &ep->crc, sizeof(crc)); |
881 | 881 | ||
882 | if (crc32(0, ep->data, size) != crc) { | 882 | if (crc32(0, ep->data, size) != crc) { |
883 | puts("## Error: bad CRC, import failed\n"); | 883 | puts("## Error: bad CRC, import failed\n"); |
884 | return 1; | 884 | return 1; |
885 | } | 885 | } |
886 | addr = (char *)ep->data; | 886 | addr = (char *)ep->data; |
887 | } | 887 | } |
888 | 888 | ||
889 | if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR) == 0) { | 889 | if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR) == 0) { |
890 | error("Environment import failed: errno = %d\n", errno); | 890 | error("Environment import failed: errno = %d\n", errno); |
891 | return 1; | 891 | return 1; |
892 | } | 892 | } |
893 | gd->flags |= GD_FLG_ENV_READY; | 893 | gd->flags |= GD_FLG_ENV_READY; |
894 | 894 | ||
895 | return 0; | 895 | return 0; |
896 | 896 | ||
897 | sep_err: | 897 | sep_err: |
898 | printf("## %s: only one of \"-b\", \"-c\" or \"-t\" allowed\n", | 898 | printf("## %s: only one of \"-b\", \"-c\" or \"-t\" allowed\n", |
899 | cmd); | 899 | cmd); |
900 | return 1; | 900 | return 1; |
901 | } | 901 | } |
902 | #endif | 902 | #endif |
903 | 903 | ||
904 | /* | 904 | /* |
905 | * New command line interface: "env" command with subcommands | 905 | * New command line interface: "env" command with subcommands |
906 | */ | 906 | */ |
907 | static cmd_tbl_t cmd_env_sub[] = { | 907 | static cmd_tbl_t cmd_env_sub[] = { |
908 | #if defined(CONFIG_CMD_ASKENV) | 908 | #if defined(CONFIG_CMD_ASKENV) |
909 | U_BOOT_CMD_MKENT(ask, CONFIG_SYS_MAXARGS, 1, do_env_ask, "", ""), | 909 | U_BOOT_CMD_MKENT(ask, CONFIG_SYS_MAXARGS, 1, do_env_ask, "", ""), |
910 | #endif | 910 | #endif |
911 | U_BOOT_CMD_MKENT(default, 1, 0, do_env_default, "", ""), | 911 | U_BOOT_CMD_MKENT(default, 1, 0, do_env_default, "", ""), |
912 | U_BOOT_CMD_MKENT(delete, 2, 0, do_env_delete, "", ""), | 912 | U_BOOT_CMD_MKENT(delete, 2, 0, do_env_delete, "", ""), |
913 | #if defined(CONFIG_CMD_EDITENV) | 913 | #if defined(CONFIG_CMD_EDITENV) |
914 | U_BOOT_CMD_MKENT(edit, 2, 0, do_env_edit, "", ""), | 914 | U_BOOT_CMD_MKENT(edit, 2, 0, do_env_edit, "", ""), |
915 | #endif | 915 | #endif |
916 | #if defined(CONFIG_CMD_EXPORTENV) | 916 | #if defined(CONFIG_CMD_EXPORTENV) |
917 | U_BOOT_CMD_MKENT(export, 4, 0, do_env_export, "", ""), | 917 | U_BOOT_CMD_MKENT(export, 4, 0, do_env_export, "", ""), |
918 | #endif | 918 | #endif |
919 | #if defined(CONFIG_CMD_GREPENV) | 919 | #if defined(CONFIG_CMD_GREPENV) |
920 | U_BOOT_CMD_MKENT(grep, CONFIG_SYS_MAXARGS, 1, do_env_grep, "", ""), | 920 | U_BOOT_CMD_MKENT(grep, CONFIG_SYS_MAXARGS, 1, do_env_grep, "", ""), |
921 | #endif | 921 | #endif |
922 | #if defined(CONFIG_CMD_IMPORTENV) | 922 | #if defined(CONFIG_CMD_IMPORTENV) |
923 | U_BOOT_CMD_MKENT(import, 5, 0, do_env_import, "", ""), | 923 | U_BOOT_CMD_MKENT(import, 5, 0, do_env_import, "", ""), |
924 | #endif | 924 | #endif |
925 | U_BOOT_CMD_MKENT(print, CONFIG_SYS_MAXARGS, 1, do_env_print, "", ""), | 925 | U_BOOT_CMD_MKENT(print, CONFIG_SYS_MAXARGS, 1, do_env_print, "", ""), |
926 | #if defined(CONFIG_CMD_RUN) | 926 | #if defined(CONFIG_CMD_RUN) |
927 | U_BOOT_CMD_MKENT(run, CONFIG_SYS_MAXARGS, 1, do_run, "", ""), | 927 | U_BOOT_CMD_MKENT(run, CONFIG_SYS_MAXARGS, 1, do_run, "", ""), |
928 | #endif | 928 | #endif |
929 | #if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE) | 929 | #if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE) |
930 | U_BOOT_CMD_MKENT(save, 1, 0, do_env_save, "", ""), | 930 | U_BOOT_CMD_MKENT(save, 1, 0, do_env_save, "", ""), |
931 | #endif | 931 | #endif |
932 | U_BOOT_CMD_MKENT(set, CONFIG_SYS_MAXARGS, 0, do_env_set, "", ""), | 932 | U_BOOT_CMD_MKENT(set, CONFIG_SYS_MAXARGS, 0, do_env_set, "", ""), |
933 | }; | 933 | }; |
934 | 934 | ||
935 | #if defined(CONFIG_NEEDS_MANUAL_RELOC) | 935 | #if defined(CONFIG_NEEDS_MANUAL_RELOC) |
936 | void env_reloc(void) | 936 | void env_reloc(void) |
937 | { | 937 | { |
938 | fixup_cmdtable(cmd_env_sub, ARRAY_SIZE(cmd_env_sub)); | 938 | fixup_cmdtable(cmd_env_sub, ARRAY_SIZE(cmd_env_sub)); |
939 | } | 939 | } |
940 | #endif | 940 | #endif |
941 | 941 | ||
942 | static int do_env(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | 942 | static int do_env(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
943 | { | 943 | { |
944 | cmd_tbl_t *cp; | 944 | cmd_tbl_t *cp; |
945 | 945 | ||
946 | if (argc < 2) | 946 | if (argc < 2) |
947 | return cmd_usage(cmdtp); | 947 | return cmd_usage(cmdtp); |
948 | 948 | ||
949 | /* drop initial "env" arg */ | 949 | /* drop initial "env" arg */ |
950 | argc--; | 950 | argc--; |
951 | argv++; | 951 | argv++; |
952 | 952 | ||
953 | cp = find_cmd_tbl(argv[0], cmd_env_sub, ARRAY_SIZE(cmd_env_sub)); | 953 | cp = find_cmd_tbl(argv[0], cmd_env_sub, ARRAY_SIZE(cmd_env_sub)); |
954 | 954 | ||
955 | if (cp) | 955 | if (cp) |
956 | return cp->cmd(cmdtp, flag, argc, argv); | 956 | return cp->cmd(cmdtp, flag, argc, argv); |
957 | 957 | ||
958 | return cmd_usage(cmdtp); | 958 | return cmd_usage(cmdtp); |
959 | } | 959 | } |
960 | 960 | ||
961 | U_BOOT_CMD( | 961 | U_BOOT_CMD( |
962 | env, CONFIG_SYS_MAXARGS, 1, do_env, | 962 | env, CONFIG_SYS_MAXARGS, 1, do_env, |
963 | "environment handling commands", | 963 | "environment handling commands", |
964 | #if defined(CONFIG_CMD_ASKENV) | 964 | #if defined(CONFIG_CMD_ASKENV) |
965 | "ask name [message] [size] - ask for environment variable\nenv " | 965 | "ask name [message] [size] - ask for environment variable\nenv " |
966 | #endif | 966 | #endif |
967 | "default -f - reset default environment\n" | 967 | "default -f - reset default environment\n" |
968 | #if defined(CONFIG_CMD_EDITENV) | 968 | #if defined(CONFIG_CMD_EDITENV) |
969 | "env edit name - edit environment variable\n" | 969 | "env edit name - edit environment variable\n" |
970 | #endif | 970 | #endif |
971 | "env export [-t | -b | -c] [-s size] addr [var ...] - export environment\n" | 971 | "env export [-t | -b | -c] [-s size] addr [var ...] - export environment\n" |
972 | #if defined(CONFIG_CMD_GREPENV) | 972 | #if defined(CONFIG_CMD_GREPENV) |
973 | "env grep string [...] - search environment\n" | 973 | "env grep string [...] - search environment\n" |
974 | #endif | 974 | #endif |
975 | "env import [-d] [-t | -b | -c] addr [size] - import environment\n" | 975 | "env import [-d] [-t | -b | -c] addr [size] - import environment\n" |
976 | "env print [name ...] - print environment\n" | 976 | "env print [name ...] - print environment\n" |
977 | #if defined(CONFIG_CMD_RUN) | 977 | #if defined(CONFIG_CMD_RUN) |
978 | "env run var [...] - run commands in an environment variable\n" | 978 | "env run var [...] - run commands in an environment variable\n" |
979 | #endif | 979 | #endif |
980 | #if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE) | 980 | #if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE) |
981 | "env save - save environment\n" | 981 | "env save - save environment\n" |
982 | #endif | 982 | #endif |
983 | "env set [-f] name [arg ...]\n" | 983 | "env set [-f] name [arg ...]\n" |
984 | ); | 984 | ); |
985 | 985 | ||
986 | /* | 986 | /* |
987 | * Old command line interface, kept for compatibility | 987 | * Old command line interface, kept for compatibility |
988 | */ | 988 | */ |
989 | 989 | ||
990 | #if defined(CONFIG_CMD_EDITENV) | 990 | #if defined(CONFIG_CMD_EDITENV) |
991 | U_BOOT_CMD_COMPLETE( | 991 | U_BOOT_CMD_COMPLETE( |
992 | editenv, 2, 0, do_env_edit, | 992 | editenv, 2, 0, do_env_edit, |
993 | "edit environment variable", | 993 | "edit environment variable", |
994 | "name\n" | 994 | "name\n" |
995 | " - edit environment variable 'name'", | 995 | " - edit environment variable 'name'", |
996 | var_complete | 996 | var_complete |
997 | ); | 997 | ); |
998 | #endif | 998 | #endif |
999 | 999 | ||
1000 | U_BOOT_CMD_COMPLETE( | 1000 | U_BOOT_CMD_COMPLETE( |
1001 | printenv, CONFIG_SYS_MAXARGS, 1, do_env_print, | 1001 | printenv, CONFIG_SYS_MAXARGS, 1, do_env_print, |
1002 | "print environment variables", | 1002 | "print environment variables", |
1003 | "\n - print values of all environment variables\n" | 1003 | "\n - print values of all environment variables\n" |
1004 | "printenv name ...\n" | 1004 | "printenv name ...\n" |
1005 | " - print value of environment variable 'name'", | 1005 | " - print value of environment variable 'name'", |
1006 | var_complete | 1006 | var_complete |
1007 | ); | 1007 | ); |
1008 | 1008 | ||
1009 | #ifdef CONFIG_CMD_GREPENV | 1009 | #ifdef CONFIG_CMD_GREPENV |
1010 | U_BOOT_CMD_COMPLETE( | 1010 | U_BOOT_CMD_COMPLETE( |
1011 | grepenv, CONFIG_SYS_MAXARGS, 0, do_env_grep, | 1011 | grepenv, CONFIG_SYS_MAXARGS, 0, do_env_grep, |
1012 | "search environment variables", | 1012 | "search environment variables", |
1013 | "string ...\n" | 1013 | "string ...\n" |
1014 | " - list environment name=value pairs matching 'string'", | 1014 | " - list environment name=value pairs matching 'string'", |
1015 | var_complete | 1015 | var_complete |
1016 | ); | 1016 | ); |
1017 | #endif | 1017 | #endif |
1018 | 1018 | ||
1019 | U_BOOT_CMD_COMPLETE( | 1019 | U_BOOT_CMD_COMPLETE( |
1020 | setenv, CONFIG_SYS_MAXARGS, 0, do_env_set, | 1020 | setenv, CONFIG_SYS_MAXARGS, 0, do_env_set, |
1021 | "set environment variables", | 1021 | "set environment variables", |
1022 | "name value ...\n" | 1022 | "name value ...\n" |
1023 | " - set environment variable 'name' to 'value ...'\n" | 1023 | " - set environment variable 'name' to 'value ...'\n" |
1024 | "setenv name\n" | 1024 | "setenv name\n" |
1025 | " - delete environment variable 'name'", | 1025 | " - delete environment variable 'name'", |
1026 | var_complete | 1026 | var_complete |
1027 | ); | 1027 | ); |
1028 | 1028 | ||
1029 | #if defined(CONFIG_CMD_ASKENV) | 1029 | #if defined(CONFIG_CMD_ASKENV) |
1030 | 1030 | ||
1031 | U_BOOT_CMD( | 1031 | U_BOOT_CMD( |
1032 | askenv, CONFIG_SYS_MAXARGS, 1, do_env_ask, | 1032 | askenv, CONFIG_SYS_MAXARGS, 1, do_env_ask, |
1033 | "get environment variables from stdin", | 1033 | "get environment variables from stdin", |
1034 | "name [message] [size]\n" | 1034 | "name [message] [size]\n" |
1035 | " - get environment variable 'name' from stdin (max 'size' chars)\n" | 1035 | " - get environment variable 'name' from stdin (max 'size' chars)\n" |
1036 | "askenv name\n" | 1036 | "askenv name\n" |
1037 | " - get environment variable 'name' from stdin\n" | 1037 | " - get environment variable 'name' from stdin\n" |
1038 | "askenv name size\n" | 1038 | "askenv name size\n" |
1039 | " - get environment variable 'name' from stdin (max 'size' chars)\n" | 1039 | " - get environment variable 'name' from stdin (max 'size' chars)\n" |
1040 | "askenv name [message] size\n" | 1040 | "askenv name [message] size\n" |
1041 | " - display 'message' string and get environment variable 'name'" | 1041 | " - display 'message' string and get environment variable 'name'" |
1042 | "from stdin (max 'size' chars)" | 1042 | "from stdin (max 'size' chars)" |
1043 | ); | 1043 | ); |
1044 | #endif | 1044 | #endif |
1045 | 1045 | ||
1046 | #if defined(CONFIG_CMD_RUN) | 1046 | #if defined(CONFIG_CMD_RUN) |
1047 | U_BOOT_CMD_COMPLETE( | 1047 | U_BOOT_CMD_COMPLETE( |
1048 | run, CONFIG_SYS_MAXARGS, 1, do_run, | 1048 | run, CONFIG_SYS_MAXARGS, 1, do_run, |
1049 | "run commands in an environment variable", | 1049 | "run commands in an environment variable", |
1050 | "var [...]\n" | 1050 | "var [...]\n" |
1051 | " - run the commands in the environment variable(s) 'var'", | 1051 | " - run the commands in the environment variable(s) 'var'", |
1052 | var_complete | 1052 | var_complete |
1053 | ); | 1053 | ); |
1054 | #endif | 1054 | #endif |
1055 | 1055 |
common/main.c
1 | /* | 1 | /* |
2 | * (C) Copyright 2000 | 2 | * (C) Copyright 2000 |
3 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | 3 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. |
4 | * | 4 | * |
5 | * Add to readline cmdline-editing by | 5 | * Add to readline cmdline-editing by |
6 | * (C) Copyright 2005 | 6 | * (C) Copyright 2005 |
7 | * JinHua Luo, GuangDong Linux Center, <luo.jinhua@gd-linux.com> | 7 | * JinHua Luo, GuangDong Linux Center, <luo.jinhua@gd-linux.com> |
8 | * | 8 | * |
9 | * See file CREDITS for list of people who contributed to this | 9 | * See file CREDITS for list of people who contributed to this |
10 | * project. | 10 | * project. |
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or | 12 | * This program is free software; you can redistribute it and/or |
13 | * modify it under the terms of the GNU General Public License as | 13 | * modify it under the terms of the GNU General Public License as |
14 | * published by the Free Software Foundation; either version 2 of | 14 | * published by the Free Software Foundation; either version 2 of |
15 | * the License, or (at your option) any later version. | 15 | * the License, or (at your option) any later version. |
16 | * | 16 | * |
17 | * This program is distributed in the hope that it will be useful, | 17 | * This program is distributed in the hope that it will be useful, |
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
20 | * GNU General Public License for more details. | 20 | * GNU General Public License for more details. |
21 | * | 21 | * |
22 | * You should have received a copy of the GNU General Public License | 22 | * You should have received a copy of the GNU General Public License |
23 | * along with this program; if not, write to the Free Software | 23 | * along with this program; if not, write to the Free Software |
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | 24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
25 | * MA 02111-1307 USA | 25 | * MA 02111-1307 USA |
26 | */ | 26 | */ |
27 | 27 | ||
28 | /* #define DEBUG */ | 28 | /* #define DEBUG */ |
29 | 29 | ||
30 | #include <common.h> | 30 | #include <common.h> |
31 | #include <watchdog.h> | 31 | #include <watchdog.h> |
32 | #include <command.h> | 32 | #include <command.h> |
33 | #include <version.h> | 33 | #include <version.h> |
34 | #ifdef CONFIG_MODEM_SUPPORT | 34 | #ifdef CONFIG_MODEM_SUPPORT |
35 | #include <malloc.h> /* for free() prototype */ | 35 | #include <malloc.h> /* for free() prototype */ |
36 | #endif | 36 | #endif |
37 | 37 | ||
38 | #ifdef CONFIG_SYS_HUSH_PARSER | 38 | #ifdef CONFIG_SYS_HUSH_PARSER |
39 | #include <hush.h> | 39 | #include <hush.h> |
40 | #endif | 40 | #endif |
41 | 41 | ||
42 | #include <post.h> | 42 | #include <post.h> |
43 | #include <linux/ctype.h> | 43 | #include <linux/ctype.h> |
44 | 44 | ||
45 | #if defined(CONFIG_SILENT_CONSOLE) || defined(CONFIG_POST) || defined(CONFIG_CMDLINE_EDITING) | 45 | #if defined(CONFIG_SILENT_CONSOLE) || defined(CONFIG_POST) || defined(CONFIG_CMDLINE_EDITING) |
46 | DECLARE_GLOBAL_DATA_PTR; | 46 | DECLARE_GLOBAL_DATA_PTR; |
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | /* | 49 | /* |
50 | * Board-specific Platform code can reimplement show_boot_progress () if needed | 50 | * Board-specific Platform code can reimplement show_boot_progress () if needed |
51 | */ | 51 | */ |
52 | void inline __show_boot_progress (int val) {} | 52 | void inline __show_boot_progress (int val) {} |
53 | void show_boot_progress (int val) __attribute__((weak, alias("__show_boot_progress"))); | 53 | void show_boot_progress (int val) __attribute__((weak, alias("__show_boot_progress"))); |
54 | 54 | ||
55 | #if defined(CONFIG_UPDATE_TFTP) | 55 | #if defined(CONFIG_UPDATE_TFTP) |
56 | int update_tftp (ulong addr); | 56 | int update_tftp (ulong addr); |
57 | #endif /* CONFIG_UPDATE_TFTP */ | 57 | #endif /* CONFIG_UPDATE_TFTP */ |
58 | 58 | ||
59 | #define MAX_DELAY_STOP_STR 32 | 59 | #define MAX_DELAY_STOP_STR 32 |
60 | 60 | ||
61 | #undef DEBUG_PARSER | 61 | #undef DEBUG_PARSER |
62 | 62 | ||
63 | char console_buffer[CONFIG_SYS_CBSIZE + 1]; /* console I/O buffer */ | 63 | char console_buffer[CONFIG_SYS_CBSIZE + 1]; /* console I/O buffer */ |
64 | 64 | ||
65 | static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen); | 65 | static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen); |
66 | static const char erase_seq[] = "\b \b"; /* erase sequence */ | 66 | static const char erase_seq[] = "\b \b"; /* erase sequence */ |
67 | static const char tab_seq[] = " "; /* used to expand TABs */ | 67 | static const char tab_seq[] = " "; /* used to expand TABs */ |
68 | 68 | ||
69 | #ifdef CONFIG_BOOT_RETRY_TIME | 69 | #ifdef CONFIG_BOOT_RETRY_TIME |
70 | static uint64_t endtime = 0; /* must be set, default is instant timeout */ | 70 | static uint64_t endtime = 0; /* must be set, default is instant timeout */ |
71 | static int retry_time = -1; /* -1 so can call readline before main_loop */ | 71 | static int retry_time = -1; /* -1 so can call readline before main_loop */ |
72 | #endif | 72 | #endif |
73 | 73 | ||
74 | #define endtick(seconds) (get_ticks() + (uint64_t)(seconds) * get_tbclk()) | 74 | #define endtick(seconds) (get_ticks() + (uint64_t)(seconds) * get_tbclk()) |
75 | 75 | ||
76 | #ifndef CONFIG_BOOT_RETRY_MIN | 76 | #ifndef CONFIG_BOOT_RETRY_MIN |
77 | #define CONFIG_BOOT_RETRY_MIN CONFIG_BOOT_RETRY_TIME | 77 | #define CONFIG_BOOT_RETRY_MIN CONFIG_BOOT_RETRY_TIME |
78 | #endif | 78 | #endif |
79 | 79 | ||
80 | #ifdef CONFIG_MODEM_SUPPORT | 80 | #ifdef CONFIG_MODEM_SUPPORT |
81 | int do_mdm_init = 0; | 81 | int do_mdm_init = 0; |
82 | extern void mdm_init(void); /* defined in board.c */ | 82 | extern void mdm_init(void); /* defined in board.c */ |
83 | #endif | 83 | #endif |
84 | 84 | ||
85 | /*************************************************************************** | 85 | /*************************************************************************** |
86 | * Watch for 'delay' seconds for autoboot stop or autoboot delay string. | 86 | * Watch for 'delay' seconds for autoboot stop or autoboot delay string. |
87 | * returns: 0 - no key string, allow autoboot 1 - got key string, abort | 87 | * returns: 0 - no key string, allow autoboot 1 - got key string, abort |
88 | */ | 88 | */ |
89 | #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) | 89 | #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) |
90 | # if defined(CONFIG_AUTOBOOT_KEYED) | 90 | # if defined(CONFIG_AUTOBOOT_KEYED) |
91 | #ifndef CONFIG_MENU | 91 | #ifndef CONFIG_MENU |
92 | static inline | 92 | static inline |
93 | #endif | 93 | #endif |
94 | int abortboot(int bootdelay) | 94 | int abortboot(int bootdelay) |
95 | { | 95 | { |
96 | int abort = 0; | 96 | int abort = 0; |
97 | uint64_t etime = endtick(bootdelay); | 97 | uint64_t etime = endtick(bootdelay); |
98 | struct { | 98 | struct { |
99 | char* str; | 99 | char* str; |
100 | u_int len; | 100 | u_int len; |
101 | int retry; | 101 | int retry; |
102 | } | 102 | } |
103 | delaykey [] = { | 103 | delaykey [] = { |
104 | { str: getenv ("bootdelaykey"), retry: 1 }, | 104 | { str: getenv ("bootdelaykey"), retry: 1 }, |
105 | { str: getenv ("bootdelaykey2"), retry: 1 }, | 105 | { str: getenv ("bootdelaykey2"), retry: 1 }, |
106 | { str: getenv ("bootstopkey"), retry: 0 }, | 106 | { str: getenv ("bootstopkey"), retry: 0 }, |
107 | { str: getenv ("bootstopkey2"), retry: 0 }, | 107 | { str: getenv ("bootstopkey2"), retry: 0 }, |
108 | }; | 108 | }; |
109 | 109 | ||
110 | char presskey [MAX_DELAY_STOP_STR]; | 110 | char presskey [MAX_DELAY_STOP_STR]; |
111 | u_int presskey_len = 0; | 111 | u_int presskey_len = 0; |
112 | u_int presskey_max = 0; | 112 | u_int presskey_max = 0; |
113 | u_int i; | 113 | u_int i; |
114 | 114 | ||
115 | # ifdef CONFIG_AUTOBOOT_PROMPT | 115 | # ifdef CONFIG_AUTOBOOT_PROMPT |
116 | printf(CONFIG_AUTOBOOT_PROMPT); | 116 | printf(CONFIG_AUTOBOOT_PROMPT); |
117 | # endif | 117 | # endif |
118 | 118 | ||
119 | # ifdef CONFIG_AUTOBOOT_DELAY_STR | 119 | # ifdef CONFIG_AUTOBOOT_DELAY_STR |
120 | if (delaykey[0].str == NULL) | 120 | if (delaykey[0].str == NULL) |
121 | delaykey[0].str = CONFIG_AUTOBOOT_DELAY_STR; | 121 | delaykey[0].str = CONFIG_AUTOBOOT_DELAY_STR; |
122 | # endif | 122 | # endif |
123 | # ifdef CONFIG_AUTOBOOT_DELAY_STR2 | 123 | # ifdef CONFIG_AUTOBOOT_DELAY_STR2 |
124 | if (delaykey[1].str == NULL) | 124 | if (delaykey[1].str == NULL) |
125 | delaykey[1].str = CONFIG_AUTOBOOT_DELAY_STR2; | 125 | delaykey[1].str = CONFIG_AUTOBOOT_DELAY_STR2; |
126 | # endif | 126 | # endif |
127 | # ifdef CONFIG_AUTOBOOT_STOP_STR | 127 | # ifdef CONFIG_AUTOBOOT_STOP_STR |
128 | if (delaykey[2].str == NULL) | 128 | if (delaykey[2].str == NULL) |
129 | delaykey[2].str = CONFIG_AUTOBOOT_STOP_STR; | 129 | delaykey[2].str = CONFIG_AUTOBOOT_STOP_STR; |
130 | # endif | 130 | # endif |
131 | # ifdef CONFIG_AUTOBOOT_STOP_STR2 | 131 | # ifdef CONFIG_AUTOBOOT_STOP_STR2 |
132 | if (delaykey[3].str == NULL) | 132 | if (delaykey[3].str == NULL) |
133 | delaykey[3].str = CONFIG_AUTOBOOT_STOP_STR2; | 133 | delaykey[3].str = CONFIG_AUTOBOOT_STOP_STR2; |
134 | # endif | 134 | # endif |
135 | 135 | ||
136 | for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i ++) { | 136 | for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i ++) { |
137 | delaykey[i].len = delaykey[i].str == NULL ? | 137 | delaykey[i].len = delaykey[i].str == NULL ? |
138 | 0 : strlen (delaykey[i].str); | 138 | 0 : strlen (delaykey[i].str); |
139 | delaykey[i].len = delaykey[i].len > MAX_DELAY_STOP_STR ? | 139 | delaykey[i].len = delaykey[i].len > MAX_DELAY_STOP_STR ? |
140 | MAX_DELAY_STOP_STR : delaykey[i].len; | 140 | MAX_DELAY_STOP_STR : delaykey[i].len; |
141 | 141 | ||
142 | presskey_max = presskey_max > delaykey[i].len ? | 142 | presskey_max = presskey_max > delaykey[i].len ? |
143 | presskey_max : delaykey[i].len; | 143 | presskey_max : delaykey[i].len; |
144 | 144 | ||
145 | # if DEBUG_BOOTKEYS | 145 | # if DEBUG_BOOTKEYS |
146 | printf("%s key:<%s>\n", | 146 | printf("%s key:<%s>\n", |
147 | delaykey[i].retry ? "delay" : "stop", | 147 | delaykey[i].retry ? "delay" : "stop", |
148 | delaykey[i].str ? delaykey[i].str : "NULL"); | 148 | delaykey[i].str ? delaykey[i].str : "NULL"); |
149 | # endif | 149 | # endif |
150 | } | 150 | } |
151 | 151 | ||
152 | /* In order to keep up with incoming data, check timeout only | 152 | /* In order to keep up with incoming data, check timeout only |
153 | * when catch up. | 153 | * when catch up. |
154 | */ | 154 | */ |
155 | do { | 155 | do { |
156 | if (tstc()) { | 156 | if (tstc()) { |
157 | if (presskey_len < presskey_max) { | 157 | if (presskey_len < presskey_max) { |
158 | presskey [presskey_len ++] = getc(); | 158 | presskey [presskey_len ++] = getc(); |
159 | } | 159 | } |
160 | else { | 160 | else { |
161 | for (i = 0; i < presskey_max - 1; i ++) | 161 | for (i = 0; i < presskey_max - 1; i ++) |
162 | presskey [i] = presskey [i + 1]; | 162 | presskey [i] = presskey [i + 1]; |
163 | 163 | ||
164 | presskey [i] = getc(); | 164 | presskey [i] = getc(); |
165 | } | 165 | } |
166 | } | 166 | } |
167 | 167 | ||
168 | for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i ++) { | 168 | for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i ++) { |
169 | if (delaykey[i].len > 0 && | 169 | if (delaykey[i].len > 0 && |
170 | presskey_len >= delaykey[i].len && | 170 | presskey_len >= delaykey[i].len && |
171 | memcmp (presskey + presskey_len - delaykey[i].len, | 171 | memcmp (presskey + presskey_len - delaykey[i].len, |
172 | delaykey[i].str, | 172 | delaykey[i].str, |
173 | delaykey[i].len) == 0) { | 173 | delaykey[i].len) == 0) { |
174 | # if DEBUG_BOOTKEYS | 174 | # if DEBUG_BOOTKEYS |
175 | printf("got %skey\n", | 175 | printf("got %skey\n", |
176 | delaykey[i].retry ? "delay" : "stop"); | 176 | delaykey[i].retry ? "delay" : "stop"); |
177 | # endif | 177 | # endif |
178 | 178 | ||
179 | # ifdef CONFIG_BOOT_RETRY_TIME | 179 | # ifdef CONFIG_BOOT_RETRY_TIME |
180 | /* don't retry auto boot */ | 180 | /* don't retry auto boot */ |
181 | if (! delaykey[i].retry) | 181 | if (! delaykey[i].retry) |
182 | retry_time = -1; | 182 | retry_time = -1; |
183 | # endif | 183 | # endif |
184 | abort = 1; | 184 | abort = 1; |
185 | } | 185 | } |
186 | } | 186 | } |
187 | } while (!abort && get_ticks() <= etime); | 187 | } while (!abort && get_ticks() <= etime); |
188 | 188 | ||
189 | # if DEBUG_BOOTKEYS | 189 | # if DEBUG_BOOTKEYS |
190 | if (!abort) | 190 | if (!abort) |
191 | puts("key timeout\n"); | 191 | puts("key timeout\n"); |
192 | # endif | 192 | # endif |
193 | 193 | ||
194 | #ifdef CONFIG_SILENT_CONSOLE | 194 | #ifdef CONFIG_SILENT_CONSOLE |
195 | if (abort) | 195 | if (abort) |
196 | gd->flags &= ~GD_FLG_SILENT; | 196 | gd->flags &= ~GD_FLG_SILENT; |
197 | #endif | 197 | #endif |
198 | 198 | ||
199 | return abort; | 199 | return abort; |
200 | } | 200 | } |
201 | 201 | ||
202 | # else /* !defined(CONFIG_AUTOBOOT_KEYED) */ | 202 | # else /* !defined(CONFIG_AUTOBOOT_KEYED) */ |
203 | 203 | ||
204 | #ifdef CONFIG_MENUKEY | 204 | #ifdef CONFIG_MENUKEY |
205 | static int menukey = 0; | 205 | static int menukey = 0; |
206 | #endif | 206 | #endif |
207 | 207 | ||
208 | #ifndef CONFIG_MENU | 208 | #ifndef CONFIG_MENU |
209 | static inline | 209 | static inline |
210 | #endif | 210 | #endif |
211 | int abortboot(int bootdelay) | 211 | int abortboot(int bootdelay) |
212 | { | 212 | { |
213 | int abort = 0; | 213 | int abort = 0; |
214 | 214 | ||
215 | #ifdef CONFIG_MENUPROMPT | 215 | #ifdef CONFIG_MENUPROMPT |
216 | printf(CONFIG_MENUPROMPT); | 216 | printf(CONFIG_MENUPROMPT); |
217 | #else | 217 | #else |
218 | printf("Hit any key to stop autoboot: %2d ", bootdelay); | 218 | printf("Hit any key to stop autoboot: %2d ", bootdelay); |
219 | #endif | 219 | #endif |
220 | 220 | ||
221 | #if defined CONFIG_ZERO_BOOTDELAY_CHECK | 221 | #if defined CONFIG_ZERO_BOOTDELAY_CHECK |
222 | /* | 222 | /* |
223 | * Check if key already pressed | 223 | * Check if key already pressed |
224 | * Don't check if bootdelay < 0 | 224 | * Don't check if bootdelay < 0 |
225 | */ | 225 | */ |
226 | if (bootdelay >= 0) { | 226 | if (bootdelay >= 0) { |
227 | if (tstc()) { /* we got a key press */ | 227 | if (tstc()) { /* we got a key press */ |
228 | (void) getc(); /* consume input */ | 228 | (void) getc(); /* consume input */ |
229 | puts ("\b\b\b 0"); | 229 | puts ("\b\b\b 0"); |
230 | abort = 1; /* don't auto boot */ | 230 | abort = 1; /* don't auto boot */ |
231 | } | 231 | } |
232 | } | 232 | } |
233 | #endif | 233 | #endif |
234 | 234 | ||
235 | while ((bootdelay > 0) && (!abort)) { | 235 | while ((bootdelay > 0) && (!abort)) { |
236 | int i; | 236 | int i; |
237 | 237 | ||
238 | --bootdelay; | 238 | --bootdelay; |
239 | /* delay 100 * 10ms */ | 239 | /* delay 100 * 10ms */ |
240 | for (i=0; !abort && i<100; ++i) { | 240 | for (i=0; !abort && i<100; ++i) { |
241 | if (tstc()) { /* we got a key press */ | 241 | if (tstc()) { /* we got a key press */ |
242 | abort = 1; /* don't auto boot */ | 242 | abort = 1; /* don't auto boot */ |
243 | bootdelay = 0; /* no more delay */ | 243 | bootdelay = 0; /* no more delay */ |
244 | # ifdef CONFIG_MENUKEY | 244 | # ifdef CONFIG_MENUKEY |
245 | menukey = getc(); | 245 | menukey = getc(); |
246 | # else | 246 | # else |
247 | (void) getc(); /* consume input */ | 247 | (void) getc(); /* consume input */ |
248 | # endif | 248 | # endif |
249 | break; | 249 | break; |
250 | } | 250 | } |
251 | udelay(10000); | 251 | udelay(10000); |
252 | } | 252 | } |
253 | 253 | ||
254 | printf("\b\b\b%2d ", bootdelay); | 254 | printf("\b\b\b%2d ", bootdelay); |
255 | } | 255 | } |
256 | 256 | ||
257 | putc('\n'); | 257 | putc('\n'); |
258 | 258 | ||
259 | #ifdef CONFIG_SILENT_CONSOLE | 259 | #ifdef CONFIG_SILENT_CONSOLE |
260 | if (abort) | 260 | if (abort) |
261 | gd->flags &= ~GD_FLG_SILENT; | 261 | gd->flags &= ~GD_FLG_SILENT; |
262 | #endif | 262 | #endif |
263 | 263 | ||
264 | return abort; | 264 | return abort; |
265 | } | 265 | } |
266 | # endif /* CONFIG_AUTOBOOT_KEYED */ | 266 | # endif /* CONFIG_AUTOBOOT_KEYED */ |
267 | #endif /* CONFIG_BOOTDELAY >= 0 */ | 267 | #endif /* CONFIG_BOOTDELAY >= 0 */ |
268 | 268 | ||
269 | /* | 269 | /* |
270 | * Return 0 on success, or != 0 on error. | 270 | * Return 0 on success, or != 0 on error. |
271 | */ | 271 | */ |
272 | #ifndef CONFIG_CMD_PXE | 272 | #ifndef CONFIG_CMD_PXE |
273 | static inline | 273 | static inline |
274 | #endif | 274 | #endif |
275 | int run_command2(const char *cmd, int flag) | 275 | int run_command2(const char *cmd, int flag) |
276 | { | 276 | { |
277 | #ifndef CONFIG_SYS_HUSH_PARSER | 277 | #ifndef CONFIG_SYS_HUSH_PARSER |
278 | /* | 278 | /* |
279 | * run_command can return 0 or 1 for success, so clean up its result. | 279 | * run_command can return 0 or 1 for success, so clean up its result. |
280 | */ | 280 | */ |
281 | if (run_command(cmd, flag) == -1) | 281 | if (run_command(cmd, flag) == -1) |
282 | return 1; | 282 | return 1; |
283 | 283 | ||
284 | return 0; | 284 | return 0; |
285 | #else | 285 | #else |
286 | return parse_string_outer(cmd, | 286 | return parse_string_outer(cmd, |
287 | FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP); | 287 | FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP); |
288 | #endif | 288 | #endif |
289 | } | 289 | } |
290 | 290 | ||
291 | /****************************************************************************/ | 291 | /****************************************************************************/ |
292 | 292 | ||
293 | void main_loop (void) | 293 | void main_loop (void) |
294 | { | 294 | { |
295 | #ifndef CONFIG_SYS_HUSH_PARSER | 295 | #ifndef CONFIG_SYS_HUSH_PARSER |
296 | static char lastcommand[CONFIG_SYS_CBSIZE] = { 0, }; | 296 | static char lastcommand[CONFIG_SYS_CBSIZE] = { 0, }; |
297 | int len; | 297 | int len; |
298 | int rc = 1; | 298 | int rc = 1; |
299 | int flag; | 299 | int flag; |
300 | #endif | 300 | #endif |
301 | 301 | ||
302 | #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) | 302 | #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) |
303 | char *s; | 303 | char *s; |
304 | int bootdelay; | 304 | int bootdelay; |
305 | #endif | 305 | #endif |
306 | #ifdef CONFIG_PREBOOT | 306 | #ifdef CONFIG_PREBOOT |
307 | char *p; | 307 | char *p; |
308 | #endif | 308 | #endif |
309 | #ifdef CONFIG_BOOTCOUNT_LIMIT | 309 | #ifdef CONFIG_BOOTCOUNT_LIMIT |
310 | unsigned long bootcount = 0; | 310 | unsigned long bootcount = 0; |
311 | unsigned long bootlimit = 0; | 311 | unsigned long bootlimit = 0; |
312 | char *bcs; | 312 | char *bcs; |
313 | char bcs_set[16]; | 313 | char bcs_set[16]; |
314 | #endif /* CONFIG_BOOTCOUNT_LIMIT */ | 314 | #endif /* CONFIG_BOOTCOUNT_LIMIT */ |
315 | 315 | ||
316 | #ifdef CONFIG_BOOTCOUNT_LIMIT | 316 | #ifdef CONFIG_BOOTCOUNT_LIMIT |
317 | bootcount = bootcount_load(); | 317 | bootcount = bootcount_load(); |
318 | bootcount++; | 318 | bootcount++; |
319 | bootcount_store (bootcount); | 319 | bootcount_store (bootcount); |
320 | sprintf (bcs_set, "%lu", bootcount); | 320 | sprintf (bcs_set, "%lu", bootcount); |
321 | setenv ("bootcount", bcs_set); | 321 | setenv ("bootcount", bcs_set); |
322 | bcs = getenv ("bootlimit"); | 322 | bcs = getenv ("bootlimit"); |
323 | bootlimit = bcs ? simple_strtoul (bcs, NULL, 10) : 0; | 323 | bootlimit = bcs ? simple_strtoul (bcs, NULL, 10) : 0; |
324 | #endif /* CONFIG_BOOTCOUNT_LIMIT */ | 324 | #endif /* CONFIG_BOOTCOUNT_LIMIT */ |
325 | 325 | ||
326 | #ifdef CONFIG_MODEM_SUPPORT | 326 | #ifdef CONFIG_MODEM_SUPPORT |
327 | debug ("DEBUG: main_loop: do_mdm_init=%d\n", do_mdm_init); | 327 | debug ("DEBUG: main_loop: do_mdm_init=%d\n", do_mdm_init); |
328 | if (do_mdm_init) { | 328 | if (do_mdm_init) { |
329 | char *str = strdup(getenv("mdm_cmd")); | 329 | char *str = strdup(getenv("mdm_cmd")); |
330 | setenv ("preboot", str); /* set or delete definition */ | 330 | setenv ("preboot", str); /* set or delete definition */ |
331 | if (str != NULL) | 331 | if (str != NULL) |
332 | free (str); | 332 | free (str); |
333 | mdm_init(); /* wait for modem connection */ | 333 | mdm_init(); /* wait for modem connection */ |
334 | } | 334 | } |
335 | #endif /* CONFIG_MODEM_SUPPORT */ | 335 | #endif /* CONFIG_MODEM_SUPPORT */ |
336 | 336 | ||
337 | #ifdef CONFIG_VERSION_VARIABLE | 337 | #ifdef CONFIG_VERSION_VARIABLE |
338 | { | 338 | { |
339 | setenv ("ver", version_string); /* set version variable */ | 339 | setenv ("ver", version_string); /* set version variable */ |
340 | } | 340 | } |
341 | #endif /* CONFIG_VERSION_VARIABLE */ | 341 | #endif /* CONFIG_VERSION_VARIABLE */ |
342 | 342 | ||
343 | #ifdef CONFIG_SYS_HUSH_PARSER | 343 | #ifdef CONFIG_SYS_HUSH_PARSER |
344 | u_boot_hush_start (); | 344 | u_boot_hush_start (); |
345 | #endif | 345 | #endif |
346 | 346 | ||
347 | #if defined(CONFIG_HUSH_INIT_VAR) | 347 | #if defined(CONFIG_HUSH_INIT_VAR) |
348 | hush_init_var (); | 348 | hush_init_var (); |
349 | #endif | 349 | #endif |
350 | 350 | ||
351 | #ifdef CONFIG_PREBOOT | 351 | #ifdef CONFIG_PREBOOT |
352 | if ((p = getenv ("preboot")) != NULL) { | 352 | if ((p = getenv ("preboot")) != NULL) { |
353 | # ifdef CONFIG_AUTOBOOT_KEYED | 353 | # ifdef CONFIG_AUTOBOOT_KEYED |
354 | int prev = disable_ctrlc(1); /* disable Control C checking */ | 354 | int prev = disable_ctrlc(1); /* disable Control C checking */ |
355 | # endif | 355 | # endif |
356 | 356 | ||
357 | run_command2(p, 0); | 357 | run_command2(p, 0); |
358 | 358 | ||
359 | # ifdef CONFIG_AUTOBOOT_KEYED | 359 | # ifdef CONFIG_AUTOBOOT_KEYED |
360 | disable_ctrlc(prev); /* restore Control C checking */ | 360 | disable_ctrlc(prev); /* restore Control C checking */ |
361 | # endif | 361 | # endif |
362 | } | 362 | } |
363 | #endif /* CONFIG_PREBOOT */ | 363 | #endif /* CONFIG_PREBOOT */ |
364 | 364 | ||
365 | #if defined(CONFIG_UPDATE_TFTP) | 365 | #if defined(CONFIG_UPDATE_TFTP) |
366 | update_tftp (0UL); | 366 | update_tftp (0UL); |
367 | #endif /* CONFIG_UPDATE_TFTP */ | 367 | #endif /* CONFIG_UPDATE_TFTP */ |
368 | 368 | ||
369 | #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) | 369 | #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) |
370 | s = getenv ("bootdelay"); | 370 | s = getenv ("bootdelay"); |
371 | bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY; | 371 | bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY; |
372 | 372 | ||
373 | debug ("### main_loop entered: bootdelay=%d\n\n", bootdelay); | 373 | debug ("### main_loop entered: bootdelay=%d\n\n", bootdelay); |
374 | 374 | ||
375 | # ifdef CONFIG_BOOT_RETRY_TIME | 375 | # ifdef CONFIG_BOOT_RETRY_TIME |
376 | init_cmd_timeout (); | 376 | init_cmd_timeout (); |
377 | # endif /* CONFIG_BOOT_RETRY_TIME */ | 377 | # endif /* CONFIG_BOOT_RETRY_TIME */ |
378 | 378 | ||
379 | #ifdef CONFIG_POST | 379 | #ifdef CONFIG_POST |
380 | if (gd->flags & GD_FLG_POSTFAIL) { | 380 | if (gd->flags & GD_FLG_POSTFAIL) { |
381 | s = getenv("failbootcmd"); | 381 | s = getenv("failbootcmd"); |
382 | } | 382 | } |
383 | else | 383 | else |
384 | #endif /* CONFIG_POST */ | 384 | #endif /* CONFIG_POST */ |
385 | #ifdef CONFIG_BOOTCOUNT_LIMIT | 385 | #ifdef CONFIG_BOOTCOUNT_LIMIT |
386 | if (bootlimit && (bootcount > bootlimit)) { | 386 | if (bootlimit && (bootcount > bootlimit)) { |
387 | printf ("Warning: Bootlimit (%u) exceeded. Using altbootcmd.\n", | 387 | printf ("Warning: Bootlimit (%u) exceeded. Using altbootcmd.\n", |
388 | (unsigned)bootlimit); | 388 | (unsigned)bootlimit); |
389 | s = getenv ("altbootcmd"); | 389 | s = getenv ("altbootcmd"); |
390 | } | 390 | } |
391 | else | 391 | else |
392 | #endif /* CONFIG_BOOTCOUNT_LIMIT */ | 392 | #endif /* CONFIG_BOOTCOUNT_LIMIT */ |
393 | s = getenv ("bootcmd"); | 393 | s = getenv ("bootcmd"); |
394 | 394 | ||
395 | debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>"); | 395 | debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>"); |
396 | 396 | ||
397 | if (bootdelay >= 0 && s && !abortboot (bootdelay)) { | 397 | if (bootdelay >= 0 && s && !abortboot (bootdelay)) { |
398 | # ifdef CONFIG_AUTOBOOT_KEYED | 398 | # ifdef CONFIG_AUTOBOOT_KEYED |
399 | int prev = disable_ctrlc(1); /* disable Control C checking */ | 399 | int prev = disable_ctrlc(1); /* disable Control C checking */ |
400 | # endif | 400 | # endif |
401 | 401 | ||
402 | run_command2(s, 0); | 402 | run_command2(s, 0); |
403 | 403 | ||
404 | # ifdef CONFIG_AUTOBOOT_KEYED | 404 | # ifdef CONFIG_AUTOBOOT_KEYED |
405 | disable_ctrlc(prev); /* restore Control C checking */ | 405 | disable_ctrlc(prev); /* restore Control C checking */ |
406 | # endif | 406 | # endif |
407 | } | 407 | } |
408 | 408 | ||
409 | # ifdef CONFIG_MENUKEY | 409 | # ifdef CONFIG_MENUKEY |
410 | if (menukey == CONFIG_MENUKEY) { | 410 | if (menukey == CONFIG_MENUKEY) { |
411 | s = getenv("menucmd"); | 411 | s = getenv("menucmd"); |
412 | if (s) | 412 | if (s) |
413 | run_command2(s, 0); | 413 | run_command2(s, 0); |
414 | } | 414 | } |
415 | #endif /* CONFIG_MENUKEY */ | 415 | #endif /* CONFIG_MENUKEY */ |
416 | #endif /* CONFIG_BOOTDELAY */ | 416 | #endif /* CONFIG_BOOTDELAY */ |
417 | 417 | ||
418 | /* | 418 | /* |
419 | * Main Loop for Monitor Command Processing | 419 | * Main Loop for Monitor Command Processing |
420 | */ | 420 | */ |
421 | #ifdef CONFIG_SYS_HUSH_PARSER | 421 | #ifdef CONFIG_SYS_HUSH_PARSER |
422 | parse_file_outer(); | 422 | parse_file_outer(); |
423 | /* This point is never reached */ | 423 | /* This point is never reached */ |
424 | for (;;); | 424 | for (;;); |
425 | #else | 425 | #else |
426 | for (;;) { | 426 | for (;;) { |
427 | #ifdef CONFIG_BOOT_RETRY_TIME | 427 | #ifdef CONFIG_BOOT_RETRY_TIME |
428 | if (rc >= 0) { | 428 | if (rc >= 0) { |
429 | /* Saw enough of a valid command to | 429 | /* Saw enough of a valid command to |
430 | * restart the timeout. | 430 | * restart the timeout. |
431 | */ | 431 | */ |
432 | reset_cmd_timeout(); | 432 | reset_cmd_timeout(); |
433 | } | 433 | } |
434 | #endif | 434 | #endif |
435 | len = readline (CONFIG_SYS_PROMPT); | 435 | len = readline (CONFIG_SYS_PROMPT); |
436 | 436 | ||
437 | flag = 0; /* assume no special flags for now */ | 437 | flag = 0; /* assume no special flags for now */ |
438 | if (len > 0) | 438 | if (len > 0) |
439 | strcpy (lastcommand, console_buffer); | 439 | strcpy (lastcommand, console_buffer); |
440 | else if (len == 0) | 440 | else if (len == 0) |
441 | flag |= CMD_FLAG_REPEAT; | 441 | flag |= CMD_FLAG_REPEAT; |
442 | #ifdef CONFIG_BOOT_RETRY_TIME | 442 | #ifdef CONFIG_BOOT_RETRY_TIME |
443 | else if (len == -2) { | 443 | else if (len == -2) { |
444 | /* -2 means timed out, retry autoboot | 444 | /* -2 means timed out, retry autoboot |
445 | */ | 445 | */ |
446 | puts ("\nTimed out waiting for command\n"); | 446 | puts ("\nTimed out waiting for command\n"); |
447 | # ifdef CONFIG_RESET_TO_RETRY | 447 | # ifdef CONFIG_RESET_TO_RETRY |
448 | /* Reinit board to run initialization code again */ | 448 | /* Reinit board to run initialization code again */ |
449 | do_reset (NULL, 0, 0, NULL); | 449 | do_reset (NULL, 0, 0, NULL); |
450 | # else | 450 | # else |
451 | return; /* retry autoboot */ | 451 | return; /* retry autoboot */ |
452 | # endif | 452 | # endif |
453 | } | 453 | } |
454 | #endif | 454 | #endif |
455 | 455 | ||
456 | if (len == -1) | 456 | if (len == -1) |
457 | puts ("<INTERRUPT>\n"); | 457 | puts ("<INTERRUPT>\n"); |
458 | else | 458 | else |
459 | rc = run_command (lastcommand, flag); | 459 | rc = run_command (lastcommand, flag); |
460 | 460 | ||
461 | if (rc <= 0) { | 461 | if (rc <= 0) { |
462 | /* invalid command or not repeatable, forget it */ | 462 | /* invalid command or not repeatable, forget it */ |
463 | lastcommand[0] = 0; | 463 | lastcommand[0] = 0; |
464 | } | 464 | } |
465 | } | 465 | } |
466 | #endif /*CONFIG_SYS_HUSH_PARSER*/ | 466 | #endif /*CONFIG_SYS_HUSH_PARSER*/ |
467 | } | 467 | } |
468 | 468 | ||
469 | #ifdef CONFIG_BOOT_RETRY_TIME | 469 | #ifdef CONFIG_BOOT_RETRY_TIME |
470 | /*************************************************************************** | 470 | /*************************************************************************** |
471 | * initialize command line timeout | 471 | * initialize command line timeout |
472 | */ | 472 | */ |
473 | void init_cmd_timeout(void) | 473 | void init_cmd_timeout(void) |
474 | { | 474 | { |
475 | char *s = getenv ("bootretry"); | 475 | char *s = getenv ("bootretry"); |
476 | 476 | ||
477 | if (s != NULL) | 477 | if (s != NULL) |
478 | retry_time = (int)simple_strtol(s, NULL, 10); | 478 | retry_time = (int)simple_strtol(s, NULL, 10); |
479 | else | 479 | else |
480 | retry_time = CONFIG_BOOT_RETRY_TIME; | 480 | retry_time = CONFIG_BOOT_RETRY_TIME; |
481 | 481 | ||
482 | if (retry_time >= 0 && retry_time < CONFIG_BOOT_RETRY_MIN) | 482 | if (retry_time >= 0 && retry_time < CONFIG_BOOT_RETRY_MIN) |
483 | retry_time = CONFIG_BOOT_RETRY_MIN; | 483 | retry_time = CONFIG_BOOT_RETRY_MIN; |
484 | } | 484 | } |
485 | 485 | ||
486 | /*************************************************************************** | 486 | /*************************************************************************** |
487 | * reset command line timeout to retry_time seconds | 487 | * reset command line timeout to retry_time seconds |
488 | */ | 488 | */ |
489 | void reset_cmd_timeout(void) | 489 | void reset_cmd_timeout(void) |
490 | { | 490 | { |
491 | endtime = endtick(retry_time); | 491 | endtime = endtick(retry_time); |
492 | } | 492 | } |
493 | #endif | 493 | #endif |
494 | 494 | ||
495 | #ifdef CONFIG_CMDLINE_EDITING | 495 | #ifdef CONFIG_CMDLINE_EDITING |
496 | 496 | ||
497 | /* | 497 | /* |
498 | * cmdline-editing related codes from vivi. | 498 | * cmdline-editing related codes from vivi. |
499 | * Author: Janghoon Lyu <nandy@mizi.com> | 499 | * Author: Janghoon Lyu <nandy@mizi.com> |
500 | */ | 500 | */ |
501 | 501 | ||
502 | #define putnstr(str,n) do { \ | 502 | #define putnstr(str,n) do { \ |
503 | printf ("%.*s", (int)n, str); \ | 503 | printf ("%.*s", (int)n, str); \ |
504 | } while (0) | 504 | } while (0) |
505 | 505 | ||
506 | #define CTL_CH(c) ((c) - 'a' + 1) | 506 | #define CTL_CH(c) ((c) - 'a' + 1) |
507 | #define CTL_BACKSPACE ('\b') | 507 | #define CTL_BACKSPACE ('\b') |
508 | #define DEL ((char)255) | 508 | #define DEL ((char)255) |
509 | #define DEL7 ((char)127) | 509 | #define DEL7 ((char)127) |
510 | #define CREAD_HIST_CHAR ('!') | 510 | #define CREAD_HIST_CHAR ('!') |
511 | 511 | ||
512 | #define getcmd_putch(ch) putc(ch) | 512 | #define getcmd_putch(ch) putc(ch) |
513 | #define getcmd_getch() getc() | 513 | #define getcmd_getch() getc() |
514 | #define getcmd_cbeep() getcmd_putch('\a') | 514 | #define getcmd_cbeep() getcmd_putch('\a') |
515 | 515 | ||
516 | #define HIST_MAX 20 | 516 | #define HIST_MAX 20 |
517 | #define HIST_SIZE CONFIG_SYS_CBSIZE | 517 | #define HIST_SIZE CONFIG_SYS_CBSIZE |
518 | 518 | ||
519 | static int hist_max = 0; | 519 | static int hist_max = 0; |
520 | static int hist_add_idx = 0; | 520 | static int hist_add_idx = 0; |
521 | static int hist_cur = -1; | 521 | static int hist_cur = -1; |
522 | unsigned hist_num = 0; | 522 | unsigned hist_num = 0; |
523 | 523 | ||
524 | char* hist_list[HIST_MAX]; | 524 | char* hist_list[HIST_MAX]; |
525 | char hist_lines[HIST_MAX][HIST_SIZE + 1]; /* Save room for NULL */ | 525 | char hist_lines[HIST_MAX][HIST_SIZE + 1]; /* Save room for NULL */ |
526 | 526 | ||
527 | #define add_idx_minus_one() ((hist_add_idx == 0) ? hist_max : hist_add_idx-1) | 527 | #define add_idx_minus_one() ((hist_add_idx == 0) ? hist_max : hist_add_idx-1) |
528 | 528 | ||
529 | static void hist_init(void) | 529 | static void hist_init(void) |
530 | { | 530 | { |
531 | int i; | 531 | int i; |
532 | 532 | ||
533 | hist_max = 0; | 533 | hist_max = 0; |
534 | hist_add_idx = 0; | 534 | hist_add_idx = 0; |
535 | hist_cur = -1; | 535 | hist_cur = -1; |
536 | hist_num = 0; | 536 | hist_num = 0; |
537 | 537 | ||
538 | for (i = 0; i < HIST_MAX; i++) { | 538 | for (i = 0; i < HIST_MAX; i++) { |
539 | hist_list[i] = hist_lines[i]; | 539 | hist_list[i] = hist_lines[i]; |
540 | hist_list[i][0] = '\0'; | 540 | hist_list[i][0] = '\0'; |
541 | } | 541 | } |
542 | } | 542 | } |
543 | 543 | ||
544 | static void cread_add_to_hist(char *line) | 544 | static void cread_add_to_hist(char *line) |
545 | { | 545 | { |
546 | strcpy(hist_list[hist_add_idx], line); | 546 | strcpy(hist_list[hist_add_idx], line); |
547 | 547 | ||
548 | if (++hist_add_idx >= HIST_MAX) | 548 | if (++hist_add_idx >= HIST_MAX) |
549 | hist_add_idx = 0; | 549 | hist_add_idx = 0; |
550 | 550 | ||
551 | if (hist_add_idx > hist_max) | 551 | if (hist_add_idx > hist_max) |
552 | hist_max = hist_add_idx; | 552 | hist_max = hist_add_idx; |
553 | 553 | ||
554 | hist_num++; | 554 | hist_num++; |
555 | } | 555 | } |
556 | 556 | ||
557 | static char* hist_prev(void) | 557 | static char* hist_prev(void) |
558 | { | 558 | { |
559 | char *ret; | 559 | char *ret; |
560 | int old_cur; | 560 | int old_cur; |
561 | 561 | ||
562 | if (hist_cur < 0) | 562 | if (hist_cur < 0) |
563 | return NULL; | 563 | return NULL; |
564 | 564 | ||
565 | old_cur = hist_cur; | 565 | old_cur = hist_cur; |
566 | if (--hist_cur < 0) | 566 | if (--hist_cur < 0) |
567 | hist_cur = hist_max; | 567 | hist_cur = hist_max; |
568 | 568 | ||
569 | if (hist_cur == hist_add_idx) { | 569 | if (hist_cur == hist_add_idx) { |
570 | hist_cur = old_cur; | 570 | hist_cur = old_cur; |
571 | ret = NULL; | 571 | ret = NULL; |
572 | } else | 572 | } else |
573 | ret = hist_list[hist_cur]; | 573 | ret = hist_list[hist_cur]; |
574 | 574 | ||
575 | return (ret); | 575 | return (ret); |
576 | } | 576 | } |
577 | 577 | ||
578 | static char* hist_next(void) | 578 | static char* hist_next(void) |
579 | { | 579 | { |
580 | char *ret; | 580 | char *ret; |
581 | 581 | ||
582 | if (hist_cur < 0) | 582 | if (hist_cur < 0) |
583 | return NULL; | 583 | return NULL; |
584 | 584 | ||
585 | if (hist_cur == hist_add_idx) | 585 | if (hist_cur == hist_add_idx) |
586 | return NULL; | 586 | return NULL; |
587 | 587 | ||
588 | if (++hist_cur > hist_max) | 588 | if (++hist_cur > hist_max) |
589 | hist_cur = 0; | 589 | hist_cur = 0; |
590 | 590 | ||
591 | if (hist_cur == hist_add_idx) { | 591 | if (hist_cur == hist_add_idx) { |
592 | ret = ""; | 592 | ret = ""; |
593 | } else | 593 | } else |
594 | ret = hist_list[hist_cur]; | 594 | ret = hist_list[hist_cur]; |
595 | 595 | ||
596 | return (ret); | 596 | return (ret); |
597 | } | 597 | } |
598 | 598 | ||
599 | #ifndef CONFIG_CMDLINE_EDITING | 599 | #ifndef CONFIG_CMDLINE_EDITING |
600 | static void cread_print_hist_list(void) | 600 | static void cread_print_hist_list(void) |
601 | { | 601 | { |
602 | int i; | 602 | int i; |
603 | unsigned long n; | 603 | unsigned long n; |
604 | 604 | ||
605 | n = hist_num - hist_max; | 605 | n = hist_num - hist_max; |
606 | 606 | ||
607 | i = hist_add_idx + 1; | 607 | i = hist_add_idx + 1; |
608 | while (1) { | 608 | while (1) { |
609 | if (i > hist_max) | 609 | if (i > hist_max) |
610 | i = 0; | 610 | i = 0; |
611 | if (i == hist_add_idx) | 611 | if (i == hist_add_idx) |
612 | break; | 612 | break; |
613 | printf("%s\n", hist_list[i]); | 613 | printf("%s\n", hist_list[i]); |
614 | n++; | 614 | n++; |
615 | i++; | 615 | i++; |
616 | } | 616 | } |
617 | } | 617 | } |
618 | #endif /* CONFIG_CMDLINE_EDITING */ | 618 | #endif /* CONFIG_CMDLINE_EDITING */ |
619 | 619 | ||
620 | #define BEGINNING_OF_LINE() { \ | 620 | #define BEGINNING_OF_LINE() { \ |
621 | while (num) { \ | 621 | while (num) { \ |
622 | getcmd_putch(CTL_BACKSPACE); \ | 622 | getcmd_putch(CTL_BACKSPACE); \ |
623 | num--; \ | 623 | num--; \ |
624 | } \ | 624 | } \ |
625 | } | 625 | } |
626 | 626 | ||
627 | #define ERASE_TO_EOL() { \ | 627 | #define ERASE_TO_EOL() { \ |
628 | if (num < eol_num) { \ | 628 | if (num < eol_num) { \ |
629 | printf("%*s", (int)(eol_num - num), ""); \ | 629 | printf("%*s", (int)(eol_num - num), ""); \ |
630 | do { \ | 630 | do { \ |
631 | getcmd_putch(CTL_BACKSPACE); \ | 631 | getcmd_putch(CTL_BACKSPACE); \ |
632 | } while (--eol_num > num); \ | 632 | } while (--eol_num > num); \ |
633 | } \ | 633 | } \ |
634 | } | 634 | } |
635 | 635 | ||
636 | #define REFRESH_TO_EOL() { \ | 636 | #define REFRESH_TO_EOL() { \ |
637 | if (num < eol_num) { \ | 637 | if (num < eol_num) { \ |
638 | wlen = eol_num - num; \ | 638 | wlen = eol_num - num; \ |
639 | putnstr(buf + num, wlen); \ | 639 | putnstr(buf + num, wlen); \ |
640 | num = eol_num; \ | 640 | num = eol_num; \ |
641 | } \ | 641 | } \ |
642 | } | 642 | } |
643 | 643 | ||
644 | static void cread_add_char(char ichar, int insert, unsigned long *num, | 644 | static void cread_add_char(char ichar, int insert, unsigned long *num, |
645 | unsigned long *eol_num, char *buf, unsigned long len) | 645 | unsigned long *eol_num, char *buf, unsigned long len) |
646 | { | 646 | { |
647 | unsigned long wlen; | 647 | unsigned long wlen; |
648 | 648 | ||
649 | /* room ??? */ | 649 | /* room ??? */ |
650 | if (insert || *num == *eol_num) { | 650 | if (insert || *num == *eol_num) { |
651 | if (*eol_num > len - 1) { | 651 | if (*eol_num > len - 1) { |
652 | getcmd_cbeep(); | 652 | getcmd_cbeep(); |
653 | return; | 653 | return; |
654 | } | 654 | } |
655 | (*eol_num)++; | 655 | (*eol_num)++; |
656 | } | 656 | } |
657 | 657 | ||
658 | if (insert) { | 658 | if (insert) { |
659 | wlen = *eol_num - *num; | 659 | wlen = *eol_num - *num; |
660 | if (wlen > 1) { | 660 | if (wlen > 1) { |
661 | memmove(&buf[*num+1], &buf[*num], wlen-1); | 661 | memmove(&buf[*num+1], &buf[*num], wlen-1); |
662 | } | 662 | } |
663 | 663 | ||
664 | buf[*num] = ichar; | 664 | buf[*num] = ichar; |
665 | putnstr(buf + *num, wlen); | 665 | putnstr(buf + *num, wlen); |
666 | (*num)++; | 666 | (*num)++; |
667 | while (--wlen) { | 667 | while (--wlen) { |
668 | getcmd_putch(CTL_BACKSPACE); | 668 | getcmd_putch(CTL_BACKSPACE); |
669 | } | 669 | } |
670 | } else { | 670 | } else { |
671 | /* echo the character */ | 671 | /* echo the character */ |
672 | wlen = 1; | 672 | wlen = 1; |
673 | buf[*num] = ichar; | 673 | buf[*num] = ichar; |
674 | putnstr(buf + *num, wlen); | 674 | putnstr(buf + *num, wlen); |
675 | (*num)++; | 675 | (*num)++; |
676 | } | 676 | } |
677 | } | 677 | } |
678 | 678 | ||
679 | static void cread_add_str(char *str, int strsize, int insert, unsigned long *num, | 679 | static void cread_add_str(char *str, int strsize, int insert, unsigned long *num, |
680 | unsigned long *eol_num, char *buf, unsigned long len) | 680 | unsigned long *eol_num, char *buf, unsigned long len) |
681 | { | 681 | { |
682 | while (strsize--) { | 682 | while (strsize--) { |
683 | cread_add_char(*str, insert, num, eol_num, buf, len); | 683 | cread_add_char(*str, insert, num, eol_num, buf, len); |
684 | str++; | 684 | str++; |
685 | } | 685 | } |
686 | } | 686 | } |
687 | 687 | ||
688 | static int cread_line(const char *const prompt, char *buf, unsigned int *len) | 688 | static int cread_line(const char *const prompt, char *buf, unsigned int *len, |
689 | int timeout) | ||
689 | { | 690 | { |
690 | unsigned long num = 0; | 691 | unsigned long num = 0; |
691 | unsigned long eol_num = 0; | 692 | unsigned long eol_num = 0; |
692 | unsigned long wlen; | 693 | unsigned long wlen; |
693 | char ichar; | 694 | char ichar; |
694 | int insert = 1; | 695 | int insert = 1; |
695 | int esc_len = 0; | 696 | int esc_len = 0; |
696 | char esc_save[8]; | 697 | char esc_save[8]; |
697 | int init_len = strlen(buf); | 698 | int init_len = strlen(buf); |
699 | int first = 1; | ||
698 | 700 | ||
699 | if (init_len) | 701 | if (init_len) |
700 | cread_add_str(buf, init_len, 1, &num, &eol_num, buf, *len); | 702 | cread_add_str(buf, init_len, 1, &num, &eol_num, buf, *len); |
701 | 703 | ||
702 | while (1) { | 704 | while (1) { |
703 | #ifdef CONFIG_BOOT_RETRY_TIME | 705 | #ifdef CONFIG_BOOT_RETRY_TIME |
704 | while (!tstc()) { /* while no incoming data */ | 706 | while (!tstc()) { /* while no incoming data */ |
705 | if (retry_time >= 0 && get_ticks() > endtime) | 707 | if (retry_time >= 0 && get_ticks() > endtime) |
706 | return (-2); /* timed out */ | 708 | return (-2); /* timed out */ |
707 | WATCHDOG_RESET(); | 709 | WATCHDOG_RESET(); |
708 | } | 710 | } |
709 | #endif | 711 | #endif |
712 | if (first && timeout) { | ||
713 | uint64_t etime = endtick(timeout); | ||
710 | 714 | ||
715 | while (!tstc()) { /* while no incoming data */ | ||
716 | if (get_ticks() >= etime) | ||
717 | return -2; /* timed out */ | ||
718 | WATCHDOG_RESET(); | ||
719 | } | ||
720 | first = 0; | ||
721 | } | ||
722 | |||
711 | ichar = getcmd_getch(); | 723 | ichar = getcmd_getch(); |
712 | 724 | ||
713 | if ((ichar == '\n') || (ichar == '\r')) { | 725 | if ((ichar == '\n') || (ichar == '\r')) { |
714 | putc('\n'); | 726 | putc('\n'); |
715 | break; | 727 | break; |
716 | } | 728 | } |
717 | 729 | ||
718 | /* | 730 | /* |
719 | * handle standard linux xterm esc sequences for arrow key, etc. | 731 | * handle standard linux xterm esc sequences for arrow key, etc. |
720 | */ | 732 | */ |
721 | if (esc_len != 0) { | 733 | if (esc_len != 0) { |
722 | if (esc_len == 1) { | 734 | if (esc_len == 1) { |
723 | if (ichar == '[') { | 735 | if (ichar == '[') { |
724 | esc_save[esc_len] = ichar; | 736 | esc_save[esc_len] = ichar; |
725 | esc_len = 2; | 737 | esc_len = 2; |
726 | } else { | 738 | } else { |
727 | cread_add_str(esc_save, esc_len, insert, | 739 | cread_add_str(esc_save, esc_len, insert, |
728 | &num, &eol_num, buf, *len); | 740 | &num, &eol_num, buf, *len); |
729 | esc_len = 0; | 741 | esc_len = 0; |
730 | } | 742 | } |
731 | continue; | 743 | continue; |
732 | } | 744 | } |
733 | 745 | ||
734 | switch (ichar) { | 746 | switch (ichar) { |
735 | 747 | ||
736 | case 'D': /* <- key */ | 748 | case 'D': /* <- key */ |
737 | ichar = CTL_CH('b'); | 749 | ichar = CTL_CH('b'); |
738 | esc_len = 0; | 750 | esc_len = 0; |
739 | break; | 751 | break; |
740 | case 'C': /* -> key */ | 752 | case 'C': /* -> key */ |
741 | ichar = CTL_CH('f'); | 753 | ichar = CTL_CH('f'); |
742 | esc_len = 0; | 754 | esc_len = 0; |
743 | break; /* pass off to ^F handler */ | 755 | break; /* pass off to ^F handler */ |
744 | case 'H': /* Home key */ | 756 | case 'H': /* Home key */ |
745 | ichar = CTL_CH('a'); | 757 | ichar = CTL_CH('a'); |
746 | esc_len = 0; | 758 | esc_len = 0; |
747 | break; /* pass off to ^A handler */ | 759 | break; /* pass off to ^A handler */ |
748 | case 'A': /* up arrow */ | 760 | case 'A': /* up arrow */ |
749 | ichar = CTL_CH('p'); | 761 | ichar = CTL_CH('p'); |
750 | esc_len = 0; | 762 | esc_len = 0; |
751 | break; /* pass off to ^P handler */ | 763 | break; /* pass off to ^P handler */ |
752 | case 'B': /* down arrow */ | 764 | case 'B': /* down arrow */ |
753 | ichar = CTL_CH('n'); | 765 | ichar = CTL_CH('n'); |
754 | esc_len = 0; | 766 | esc_len = 0; |
755 | break; /* pass off to ^N handler */ | 767 | break; /* pass off to ^N handler */ |
756 | default: | 768 | default: |
757 | esc_save[esc_len++] = ichar; | 769 | esc_save[esc_len++] = ichar; |
758 | cread_add_str(esc_save, esc_len, insert, | 770 | cread_add_str(esc_save, esc_len, insert, |
759 | &num, &eol_num, buf, *len); | 771 | &num, &eol_num, buf, *len); |
760 | esc_len = 0; | 772 | esc_len = 0; |
761 | continue; | 773 | continue; |
762 | } | 774 | } |
763 | } | 775 | } |
764 | 776 | ||
765 | switch (ichar) { | 777 | switch (ichar) { |
766 | case 0x1b: | 778 | case 0x1b: |
767 | if (esc_len == 0) { | 779 | if (esc_len == 0) { |
768 | esc_save[esc_len] = ichar; | 780 | esc_save[esc_len] = ichar; |
769 | esc_len = 1; | 781 | esc_len = 1; |
770 | } else { | 782 | } else { |
771 | puts("impossible condition #876\n"); | 783 | puts("impossible condition #876\n"); |
772 | esc_len = 0; | 784 | esc_len = 0; |
773 | } | 785 | } |
774 | break; | 786 | break; |
775 | 787 | ||
776 | case CTL_CH('a'): | 788 | case CTL_CH('a'): |
777 | BEGINNING_OF_LINE(); | 789 | BEGINNING_OF_LINE(); |
778 | break; | 790 | break; |
779 | case CTL_CH('c'): /* ^C - break */ | 791 | case CTL_CH('c'): /* ^C - break */ |
780 | *buf = '\0'; /* discard input */ | 792 | *buf = '\0'; /* discard input */ |
781 | return (-1); | 793 | return (-1); |
782 | case CTL_CH('f'): | 794 | case CTL_CH('f'): |
783 | if (num < eol_num) { | 795 | if (num < eol_num) { |
784 | getcmd_putch(buf[num]); | 796 | getcmd_putch(buf[num]); |
785 | num++; | 797 | num++; |
786 | } | 798 | } |
787 | break; | 799 | break; |
788 | case CTL_CH('b'): | 800 | case CTL_CH('b'): |
789 | if (num) { | 801 | if (num) { |
790 | getcmd_putch(CTL_BACKSPACE); | 802 | getcmd_putch(CTL_BACKSPACE); |
791 | num--; | 803 | num--; |
792 | } | 804 | } |
793 | break; | 805 | break; |
794 | case CTL_CH('d'): | 806 | case CTL_CH('d'): |
795 | if (num < eol_num) { | 807 | if (num < eol_num) { |
796 | wlen = eol_num - num - 1; | 808 | wlen = eol_num - num - 1; |
797 | if (wlen) { | 809 | if (wlen) { |
798 | memmove(&buf[num], &buf[num+1], wlen); | 810 | memmove(&buf[num], &buf[num+1], wlen); |
799 | putnstr(buf + num, wlen); | 811 | putnstr(buf + num, wlen); |
800 | } | 812 | } |
801 | 813 | ||
802 | getcmd_putch(' '); | 814 | getcmd_putch(' '); |
803 | do { | 815 | do { |
804 | getcmd_putch(CTL_BACKSPACE); | 816 | getcmd_putch(CTL_BACKSPACE); |
805 | } while (wlen--); | 817 | } while (wlen--); |
806 | eol_num--; | 818 | eol_num--; |
807 | } | 819 | } |
808 | break; | 820 | break; |
809 | case CTL_CH('k'): | 821 | case CTL_CH('k'): |
810 | ERASE_TO_EOL(); | 822 | ERASE_TO_EOL(); |
811 | break; | 823 | break; |
812 | case CTL_CH('e'): | 824 | case CTL_CH('e'): |
813 | REFRESH_TO_EOL(); | 825 | REFRESH_TO_EOL(); |
814 | break; | 826 | break; |
815 | case CTL_CH('o'): | 827 | case CTL_CH('o'): |
816 | insert = !insert; | 828 | insert = !insert; |
817 | break; | 829 | break; |
818 | case CTL_CH('x'): | 830 | case CTL_CH('x'): |
819 | case CTL_CH('u'): | 831 | case CTL_CH('u'): |
820 | BEGINNING_OF_LINE(); | 832 | BEGINNING_OF_LINE(); |
821 | ERASE_TO_EOL(); | 833 | ERASE_TO_EOL(); |
822 | break; | 834 | break; |
823 | case DEL: | 835 | case DEL: |
824 | case DEL7: | 836 | case DEL7: |
825 | case 8: | 837 | case 8: |
826 | if (num) { | 838 | if (num) { |
827 | wlen = eol_num - num; | 839 | wlen = eol_num - num; |
828 | num--; | 840 | num--; |
829 | memmove(&buf[num], &buf[num+1], wlen); | 841 | memmove(&buf[num], &buf[num+1], wlen); |
830 | getcmd_putch(CTL_BACKSPACE); | 842 | getcmd_putch(CTL_BACKSPACE); |
831 | putnstr(buf + num, wlen); | 843 | putnstr(buf + num, wlen); |
832 | getcmd_putch(' '); | 844 | getcmd_putch(' '); |
833 | do { | 845 | do { |
834 | getcmd_putch(CTL_BACKSPACE); | 846 | getcmd_putch(CTL_BACKSPACE); |
835 | } while (wlen--); | 847 | } while (wlen--); |
836 | eol_num--; | 848 | eol_num--; |
837 | } | 849 | } |
838 | break; | 850 | break; |
839 | case CTL_CH('p'): | 851 | case CTL_CH('p'): |
840 | case CTL_CH('n'): | 852 | case CTL_CH('n'): |
841 | { | 853 | { |
842 | char * hline; | 854 | char * hline; |
843 | 855 | ||
844 | esc_len = 0; | 856 | esc_len = 0; |
845 | 857 | ||
846 | if (ichar == CTL_CH('p')) | 858 | if (ichar == CTL_CH('p')) |
847 | hline = hist_prev(); | 859 | hline = hist_prev(); |
848 | else | 860 | else |
849 | hline = hist_next(); | 861 | hline = hist_next(); |
850 | 862 | ||
851 | if (!hline) { | 863 | if (!hline) { |
852 | getcmd_cbeep(); | 864 | getcmd_cbeep(); |
853 | continue; | 865 | continue; |
854 | } | 866 | } |
855 | 867 | ||
856 | /* nuke the current line */ | 868 | /* nuke the current line */ |
857 | /* first, go home */ | 869 | /* first, go home */ |
858 | BEGINNING_OF_LINE(); | 870 | BEGINNING_OF_LINE(); |
859 | 871 | ||
860 | /* erase to end of line */ | 872 | /* erase to end of line */ |
861 | ERASE_TO_EOL(); | 873 | ERASE_TO_EOL(); |
862 | 874 | ||
863 | /* copy new line into place and display */ | 875 | /* copy new line into place and display */ |
864 | strcpy(buf, hline); | 876 | strcpy(buf, hline); |
865 | eol_num = strlen(buf); | 877 | eol_num = strlen(buf); |
866 | REFRESH_TO_EOL(); | 878 | REFRESH_TO_EOL(); |
867 | continue; | 879 | continue; |
868 | } | 880 | } |
869 | #ifdef CONFIG_AUTO_COMPLETE | 881 | #ifdef CONFIG_AUTO_COMPLETE |
870 | case '\t': { | 882 | case '\t': { |
871 | int num2, col; | 883 | int num2, col; |
872 | 884 | ||
873 | /* do not autocomplete when in the middle */ | 885 | /* do not autocomplete when in the middle */ |
874 | if (num < eol_num) { | 886 | if (num < eol_num) { |
875 | getcmd_cbeep(); | 887 | getcmd_cbeep(); |
876 | break; | 888 | break; |
877 | } | 889 | } |
878 | 890 | ||
879 | buf[num] = '\0'; | 891 | buf[num] = '\0'; |
880 | col = strlen(prompt) + eol_num; | 892 | col = strlen(prompt) + eol_num; |
881 | num2 = num; | 893 | num2 = num; |
882 | if (cmd_auto_complete(prompt, buf, &num2, &col)) { | 894 | if (cmd_auto_complete(prompt, buf, &num2, &col)) { |
883 | col = num2 - num; | 895 | col = num2 - num; |
884 | num += col; | 896 | num += col; |
885 | eol_num += col; | 897 | eol_num += col; |
886 | } | 898 | } |
887 | break; | 899 | break; |
888 | } | 900 | } |
889 | #endif | 901 | #endif |
890 | default: | 902 | default: |
891 | cread_add_char(ichar, insert, &num, &eol_num, buf, *len); | 903 | cread_add_char(ichar, insert, &num, &eol_num, buf, *len); |
892 | break; | 904 | break; |
893 | } | 905 | } |
894 | } | 906 | } |
895 | *len = eol_num; | 907 | *len = eol_num; |
896 | buf[eol_num] = '\0'; /* lose the newline */ | 908 | buf[eol_num] = '\0'; /* lose the newline */ |
897 | 909 | ||
898 | if (buf[0] && buf[0] != CREAD_HIST_CHAR) | 910 | if (buf[0] && buf[0] != CREAD_HIST_CHAR) |
899 | cread_add_to_hist(buf); | 911 | cread_add_to_hist(buf); |
900 | hist_cur = hist_add_idx; | 912 | hist_cur = hist_add_idx; |
901 | 913 | ||
902 | return 0; | 914 | return 0; |
903 | } | 915 | } |
904 | 916 | ||
905 | #endif /* CONFIG_CMDLINE_EDITING */ | 917 | #endif /* CONFIG_CMDLINE_EDITING */ |
906 | 918 | ||
907 | /****************************************************************************/ | 919 | /****************************************************************************/ |
908 | 920 | ||
909 | /* | 921 | /* |
910 | * Prompt for input and read a line. | 922 | * Prompt for input and read a line. |
911 | * If CONFIG_BOOT_RETRY_TIME is defined and retry_time >= 0, | 923 | * If CONFIG_BOOT_RETRY_TIME is defined and retry_time >= 0, |
912 | * time out when time goes past endtime (timebase time in ticks). | 924 | * time out when time goes past endtime (timebase time in ticks). |
913 | * Return: number of read characters | 925 | * Return: number of read characters |
914 | * -1 if break | 926 | * -1 if break |
915 | * -2 if timed out | 927 | * -2 if timed out |
916 | */ | 928 | */ |
917 | int readline (const char *const prompt) | 929 | int readline (const char *const prompt) |
918 | { | 930 | { |
919 | /* | 931 | /* |
920 | * If console_buffer isn't 0-length the user will be prompted to modify | 932 | * If console_buffer isn't 0-length the user will be prompted to modify |
921 | * it instead of entering it from scratch as desired. | 933 | * it instead of entering it from scratch as desired. |
922 | */ | 934 | */ |
923 | console_buffer[0] = '\0'; | 935 | console_buffer[0] = '\0'; |
924 | 936 | ||
925 | return readline_into_buffer(prompt, console_buffer); | 937 | return readline_into_buffer(prompt, console_buffer, 0); |
926 | } | 938 | } |
927 | 939 | ||
928 | 940 | ||
929 | int readline_into_buffer (const char *const prompt, char * buffer) | 941 | int readline_into_buffer(const char *const prompt, char *buffer, int timeout) |
930 | { | 942 | { |
931 | char *p = buffer; | 943 | char *p = buffer; |
932 | #ifdef CONFIG_CMDLINE_EDITING | 944 | #ifdef CONFIG_CMDLINE_EDITING |
933 | unsigned int len = CONFIG_SYS_CBSIZE; | 945 | unsigned int len = CONFIG_SYS_CBSIZE; |
934 | int rc; | 946 | int rc; |
935 | static int initted = 0; | 947 | static int initted = 0; |
936 | 948 | ||
937 | /* | 949 | /* |
938 | * History uses a global array which is not | 950 | * History uses a global array which is not |
939 | * writable until after relocation to RAM. | 951 | * writable until after relocation to RAM. |
940 | * Revert to non-history version if still | 952 | * Revert to non-history version if still |
941 | * running from flash. | 953 | * running from flash. |
942 | */ | 954 | */ |
943 | if (gd->flags & GD_FLG_RELOC) { | 955 | if (gd->flags & GD_FLG_RELOC) { |
944 | if (!initted) { | 956 | if (!initted) { |
945 | hist_init(); | 957 | hist_init(); |
946 | initted = 1; | 958 | initted = 1; |
947 | } | 959 | } |
948 | 960 | ||
949 | if (prompt) | 961 | if (prompt) |
950 | puts (prompt); | 962 | puts (prompt); |
951 | 963 | ||
952 | rc = cread_line(prompt, p, &len); | 964 | rc = cread_line(prompt, p, &len, timeout); |
953 | return rc < 0 ? rc : len; | 965 | return rc < 0 ? rc : len; |
954 | 966 | ||
955 | } else { | 967 | } else { |
956 | #endif /* CONFIG_CMDLINE_EDITING */ | 968 | #endif /* CONFIG_CMDLINE_EDITING */ |
957 | char * p_buf = p; | 969 | char * p_buf = p; |
958 | int n = 0; /* buffer index */ | 970 | int n = 0; /* buffer index */ |
959 | int plen = 0; /* prompt length */ | 971 | int plen = 0; /* prompt length */ |
960 | int col; /* output column cnt */ | 972 | int col; /* output column cnt */ |
961 | char c; | 973 | char c; |
962 | 974 | ||
963 | /* print prompt */ | 975 | /* print prompt */ |
964 | if (prompt) { | 976 | if (prompt) { |
965 | plen = strlen (prompt); | 977 | plen = strlen (prompt); |
966 | puts (prompt); | 978 | puts (prompt); |
967 | } | 979 | } |
968 | col = plen; | 980 | col = plen; |
969 | 981 | ||
970 | for (;;) { | 982 | for (;;) { |
971 | #ifdef CONFIG_BOOT_RETRY_TIME | 983 | #ifdef CONFIG_BOOT_RETRY_TIME |
972 | while (!tstc()) { /* while no incoming data */ | 984 | while (!tstc()) { /* while no incoming data */ |
973 | if (retry_time >= 0 && get_ticks() > endtime) | 985 | if (retry_time >= 0 && get_ticks() > endtime) |
974 | return (-2); /* timed out */ | 986 | return (-2); /* timed out */ |
975 | WATCHDOG_RESET(); | 987 | WATCHDOG_RESET(); |
976 | } | 988 | } |
977 | #endif | 989 | #endif |
978 | WATCHDOG_RESET(); /* Trigger watchdog, if needed */ | 990 | WATCHDOG_RESET(); /* Trigger watchdog, if needed */ |
979 | 991 | ||
980 | #ifdef CONFIG_SHOW_ACTIVITY | 992 | #ifdef CONFIG_SHOW_ACTIVITY |
981 | while (!tstc()) { | 993 | while (!tstc()) { |
982 | extern void show_activity(int arg); | 994 | extern void show_activity(int arg); |
983 | show_activity(0); | 995 | show_activity(0); |
984 | WATCHDOG_RESET(); | 996 | WATCHDOG_RESET(); |
985 | } | 997 | } |
986 | #endif | 998 | #endif |
987 | c = getc(); | 999 | c = getc(); |
988 | 1000 | ||
989 | /* | 1001 | /* |
990 | * Special character handling | 1002 | * Special character handling |
991 | */ | 1003 | */ |
992 | switch (c) { | 1004 | switch (c) { |
993 | case '\r': /* Enter */ | 1005 | case '\r': /* Enter */ |
994 | case '\n': | 1006 | case '\n': |
995 | *p = '\0'; | 1007 | *p = '\0'; |
996 | puts ("\r\n"); | 1008 | puts ("\r\n"); |
997 | return (p - p_buf); | 1009 | return (p - p_buf); |
998 | 1010 | ||
999 | case '\0': /* nul */ | 1011 | case '\0': /* nul */ |
1000 | continue; | 1012 | continue; |
1001 | 1013 | ||
1002 | case 0x03: /* ^C - break */ | 1014 | case 0x03: /* ^C - break */ |
1003 | p_buf[0] = '\0'; /* discard input */ | 1015 | p_buf[0] = '\0'; /* discard input */ |
1004 | return (-1); | 1016 | return (-1); |
1005 | 1017 | ||
1006 | case 0x15: /* ^U - erase line */ | 1018 | case 0x15: /* ^U - erase line */ |
1007 | while (col > plen) { | 1019 | while (col > plen) { |
1008 | puts (erase_seq); | 1020 | puts (erase_seq); |
1009 | --col; | 1021 | --col; |
1010 | } | 1022 | } |
1011 | p = p_buf; | 1023 | p = p_buf; |
1012 | n = 0; | 1024 | n = 0; |
1013 | continue; | 1025 | continue; |
1014 | 1026 | ||
1015 | case 0x17: /* ^W - erase word */ | 1027 | case 0x17: /* ^W - erase word */ |
1016 | p=delete_char(p_buf, p, &col, &n, plen); | 1028 | p=delete_char(p_buf, p, &col, &n, plen); |
1017 | while ((n > 0) && (*p != ' ')) { | 1029 | while ((n > 0) && (*p != ' ')) { |
1018 | p=delete_char(p_buf, p, &col, &n, plen); | 1030 | p=delete_char(p_buf, p, &col, &n, plen); |
1019 | } | 1031 | } |
1020 | continue; | 1032 | continue; |
1021 | 1033 | ||
1022 | case 0x08: /* ^H - backspace */ | 1034 | case 0x08: /* ^H - backspace */ |
1023 | case 0x7F: /* DEL - backspace */ | 1035 | case 0x7F: /* DEL - backspace */ |
1024 | p=delete_char(p_buf, p, &col, &n, plen); | 1036 | p=delete_char(p_buf, p, &col, &n, plen); |
1025 | continue; | 1037 | continue; |
1026 | 1038 | ||
1027 | default: | 1039 | default: |
1028 | /* | 1040 | /* |
1029 | * Must be a normal character then | 1041 | * Must be a normal character then |
1030 | */ | 1042 | */ |
1031 | if (n < CONFIG_SYS_CBSIZE-2) { | 1043 | if (n < CONFIG_SYS_CBSIZE-2) { |
1032 | if (c == '\t') { /* expand TABs */ | 1044 | if (c == '\t') { /* expand TABs */ |
1033 | #ifdef CONFIG_AUTO_COMPLETE | 1045 | #ifdef CONFIG_AUTO_COMPLETE |
1034 | /* if auto completion triggered just continue */ | 1046 | /* if auto completion triggered just continue */ |
1035 | *p = '\0'; | 1047 | *p = '\0'; |
1036 | if (cmd_auto_complete(prompt, console_buffer, &n, &col)) { | 1048 | if (cmd_auto_complete(prompt, console_buffer, &n, &col)) { |
1037 | p = p_buf + n; /* reset */ | 1049 | p = p_buf + n; /* reset */ |
1038 | continue; | 1050 | continue; |
1039 | } | 1051 | } |
1040 | #endif | 1052 | #endif |
1041 | puts (tab_seq+(col&07)); | 1053 | puts (tab_seq+(col&07)); |
1042 | col += 8 - (col&07); | 1054 | col += 8 - (col&07); |
1043 | } else { | 1055 | } else { |
1044 | ++col; /* echo input */ | 1056 | ++col; /* echo input */ |
1045 | putc (c); | 1057 | putc (c); |
1046 | } | 1058 | } |
1047 | *p++ = c; | 1059 | *p++ = c; |
1048 | ++n; | 1060 | ++n; |
1049 | } else { /* Buffer full */ | 1061 | } else { /* Buffer full */ |
1050 | putc ('\a'); | 1062 | putc ('\a'); |
1051 | } | 1063 | } |
1052 | } | 1064 | } |
1053 | } | 1065 | } |
1054 | #ifdef CONFIG_CMDLINE_EDITING | 1066 | #ifdef CONFIG_CMDLINE_EDITING |
1055 | } | 1067 | } |
1056 | #endif | 1068 | #endif |
1057 | } | 1069 | } |
1058 | 1070 | ||
1059 | /****************************************************************************/ | 1071 | /****************************************************************************/ |
1060 | 1072 | ||
1061 | static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen) | 1073 | static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen) |
1062 | { | 1074 | { |
1063 | char *s; | 1075 | char *s; |
1064 | 1076 | ||
1065 | if (*np == 0) { | 1077 | if (*np == 0) { |
1066 | return (p); | 1078 | return (p); |
1067 | } | 1079 | } |
1068 | 1080 | ||
1069 | if (*(--p) == '\t') { /* will retype the whole line */ | 1081 | if (*(--p) == '\t') { /* will retype the whole line */ |
1070 | while (*colp > plen) { | 1082 | while (*colp > plen) { |
1071 | puts (erase_seq); | 1083 | puts (erase_seq); |
1072 | (*colp)--; | 1084 | (*colp)--; |
1073 | } | 1085 | } |
1074 | for (s=buffer; s<p; ++s) { | 1086 | for (s=buffer; s<p; ++s) { |
1075 | if (*s == '\t') { | 1087 | if (*s == '\t') { |
1076 | puts (tab_seq+((*colp) & 07)); | 1088 | puts (tab_seq+((*colp) & 07)); |
1077 | *colp += 8 - ((*colp) & 07); | 1089 | *colp += 8 - ((*colp) & 07); |
1078 | } else { | 1090 | } else { |
1079 | ++(*colp); | 1091 | ++(*colp); |
1080 | putc (*s); | 1092 | putc (*s); |
1081 | } | 1093 | } |
1082 | } | 1094 | } |
1083 | } else { | 1095 | } else { |
1084 | puts (erase_seq); | 1096 | puts (erase_seq); |
1085 | (*colp)--; | 1097 | (*colp)--; |
1086 | } | 1098 | } |
1087 | (*np)--; | 1099 | (*np)--; |
1088 | return (p); | 1100 | return (p); |
1089 | } | 1101 | } |
1090 | 1102 | ||
1091 | /****************************************************************************/ | 1103 | /****************************************************************************/ |
1092 | 1104 | ||
1093 | int parse_line (char *line, char *argv[]) | 1105 | int parse_line (char *line, char *argv[]) |
1094 | { | 1106 | { |
1095 | int nargs = 0; | 1107 | int nargs = 0; |
1096 | 1108 | ||
1097 | #ifdef DEBUG_PARSER | 1109 | #ifdef DEBUG_PARSER |
1098 | printf ("parse_line: \"%s\"\n", line); | 1110 | printf ("parse_line: \"%s\"\n", line); |
1099 | #endif | 1111 | #endif |
1100 | while (nargs < CONFIG_SYS_MAXARGS) { | 1112 | while (nargs < CONFIG_SYS_MAXARGS) { |
1101 | 1113 | ||
1102 | /* skip any white space */ | 1114 | /* skip any white space */ |
1103 | while (isblank(*line)) | 1115 | while (isblank(*line)) |
1104 | ++line; | 1116 | ++line; |
1105 | 1117 | ||
1106 | if (*line == '\0') { /* end of line, no more args */ | 1118 | if (*line == '\0') { /* end of line, no more args */ |
1107 | argv[nargs] = NULL; | 1119 | argv[nargs] = NULL; |
1108 | #ifdef DEBUG_PARSER | 1120 | #ifdef DEBUG_PARSER |
1109 | printf ("parse_line: nargs=%d\n", nargs); | 1121 | printf ("parse_line: nargs=%d\n", nargs); |
1110 | #endif | 1122 | #endif |
1111 | return (nargs); | 1123 | return (nargs); |
1112 | } | 1124 | } |
1113 | 1125 | ||
1114 | argv[nargs++] = line; /* begin of argument string */ | 1126 | argv[nargs++] = line; /* begin of argument string */ |
1115 | 1127 | ||
1116 | /* find end of string */ | 1128 | /* find end of string */ |
1117 | while (*line && !isblank(*line)) | 1129 | while (*line && !isblank(*line)) |
1118 | ++line; | 1130 | ++line; |
1119 | 1131 | ||
1120 | if (*line == '\0') { /* end of line, no more args */ | 1132 | if (*line == '\0') { /* end of line, no more args */ |
1121 | argv[nargs] = NULL; | 1133 | argv[nargs] = NULL; |
1122 | #ifdef DEBUG_PARSER | 1134 | #ifdef DEBUG_PARSER |
1123 | printf ("parse_line: nargs=%d\n", nargs); | 1135 | printf ("parse_line: nargs=%d\n", nargs); |
1124 | #endif | 1136 | #endif |
1125 | return (nargs); | 1137 | return (nargs); |
1126 | } | 1138 | } |
1127 | 1139 | ||
1128 | *line++ = '\0'; /* terminate current arg */ | 1140 | *line++ = '\0'; /* terminate current arg */ |
1129 | } | 1141 | } |
1130 | 1142 | ||
1131 | printf ("** Too many args (max. %d) **\n", CONFIG_SYS_MAXARGS); | 1143 | printf ("** Too many args (max. %d) **\n", CONFIG_SYS_MAXARGS); |
1132 | 1144 | ||
1133 | #ifdef DEBUG_PARSER | 1145 | #ifdef DEBUG_PARSER |
1134 | printf ("parse_line: nargs=%d\n", nargs); | 1146 | printf ("parse_line: nargs=%d\n", nargs); |
1135 | #endif | 1147 | #endif |
1136 | return (nargs); | 1148 | return (nargs); |
1137 | } | 1149 | } |
1138 | 1150 | ||
1139 | /****************************************************************************/ | 1151 | /****************************************************************************/ |
1140 | 1152 | ||
1141 | static void process_macros (const char *input, char *output) | 1153 | static void process_macros (const char *input, char *output) |
1142 | { | 1154 | { |
1143 | char c, prev; | 1155 | char c, prev; |
1144 | const char *varname_start = NULL; | 1156 | const char *varname_start = NULL; |
1145 | int inputcnt = strlen (input); | 1157 | int inputcnt = strlen (input); |
1146 | int outputcnt = CONFIG_SYS_CBSIZE; | 1158 | int outputcnt = CONFIG_SYS_CBSIZE; |
1147 | int state = 0; /* 0 = waiting for '$' */ | 1159 | int state = 0; /* 0 = waiting for '$' */ |
1148 | 1160 | ||
1149 | /* 1 = waiting for '(' or '{' */ | 1161 | /* 1 = waiting for '(' or '{' */ |
1150 | /* 2 = waiting for ')' or '}' */ | 1162 | /* 2 = waiting for ')' or '}' */ |
1151 | /* 3 = waiting for ''' */ | 1163 | /* 3 = waiting for ''' */ |
1152 | #ifdef DEBUG_PARSER | 1164 | #ifdef DEBUG_PARSER |
1153 | char *output_start = output; | 1165 | char *output_start = output; |
1154 | 1166 | ||
1155 | printf ("[PROCESS_MACROS] INPUT len %d: \"%s\"\n", strlen (input), | 1167 | printf ("[PROCESS_MACROS] INPUT len %d: \"%s\"\n", strlen (input), |
1156 | input); | 1168 | input); |
1157 | #endif | 1169 | #endif |
1158 | 1170 | ||
1159 | prev = '\0'; /* previous character */ | 1171 | prev = '\0'; /* previous character */ |
1160 | 1172 | ||
1161 | while (inputcnt && outputcnt) { | 1173 | while (inputcnt && outputcnt) { |
1162 | c = *input++; | 1174 | c = *input++; |
1163 | inputcnt--; | 1175 | inputcnt--; |
1164 | 1176 | ||
1165 | if (state != 3) { | 1177 | if (state != 3) { |
1166 | /* remove one level of escape characters */ | 1178 | /* remove one level of escape characters */ |
1167 | if ((c == '\\') && (prev != '\\')) { | 1179 | if ((c == '\\') && (prev != '\\')) { |
1168 | if (inputcnt-- == 0) | 1180 | if (inputcnt-- == 0) |
1169 | break; | 1181 | break; |
1170 | prev = c; | 1182 | prev = c; |
1171 | c = *input++; | 1183 | c = *input++; |
1172 | } | 1184 | } |
1173 | } | 1185 | } |
1174 | 1186 | ||
1175 | switch (state) { | 1187 | switch (state) { |
1176 | case 0: /* Waiting for (unescaped) $ */ | 1188 | case 0: /* Waiting for (unescaped) $ */ |
1177 | if ((c == '\'') && (prev != '\\')) { | 1189 | if ((c == '\'') && (prev != '\\')) { |
1178 | state = 3; | 1190 | state = 3; |
1179 | break; | 1191 | break; |
1180 | } | 1192 | } |
1181 | if ((c == '$') && (prev != '\\')) { | 1193 | if ((c == '$') && (prev != '\\')) { |
1182 | state++; | 1194 | state++; |
1183 | } else { | 1195 | } else { |
1184 | *(output++) = c; | 1196 | *(output++) = c; |
1185 | outputcnt--; | 1197 | outputcnt--; |
1186 | } | 1198 | } |
1187 | break; | 1199 | break; |
1188 | case 1: /* Waiting for ( */ | 1200 | case 1: /* Waiting for ( */ |
1189 | if (c == '(' || c == '{') { | 1201 | if (c == '(' || c == '{') { |
1190 | state++; | 1202 | state++; |
1191 | varname_start = input; | 1203 | varname_start = input; |
1192 | } else { | 1204 | } else { |
1193 | state = 0; | 1205 | state = 0; |
1194 | *(output++) = '$'; | 1206 | *(output++) = '$'; |
1195 | outputcnt--; | 1207 | outputcnt--; |
1196 | 1208 | ||
1197 | if (outputcnt) { | 1209 | if (outputcnt) { |
1198 | *(output++) = c; | 1210 | *(output++) = c; |
1199 | outputcnt--; | 1211 | outputcnt--; |
1200 | } | 1212 | } |
1201 | } | 1213 | } |
1202 | break; | 1214 | break; |
1203 | case 2: /* Waiting for ) */ | 1215 | case 2: /* Waiting for ) */ |
1204 | if (c == ')' || c == '}') { | 1216 | if (c == ')' || c == '}') { |
1205 | int i; | 1217 | int i; |
1206 | char envname[CONFIG_SYS_CBSIZE], *envval; | 1218 | char envname[CONFIG_SYS_CBSIZE], *envval; |
1207 | int envcnt = input - varname_start - 1; /* Varname # of chars */ | 1219 | int envcnt = input - varname_start - 1; /* Varname # of chars */ |
1208 | 1220 | ||
1209 | /* Get the varname */ | 1221 | /* Get the varname */ |
1210 | for (i = 0; i < envcnt; i++) { | 1222 | for (i = 0; i < envcnt; i++) { |
1211 | envname[i] = varname_start[i]; | 1223 | envname[i] = varname_start[i]; |
1212 | } | 1224 | } |
1213 | envname[i] = 0; | 1225 | envname[i] = 0; |
1214 | 1226 | ||
1215 | /* Get its value */ | 1227 | /* Get its value */ |
1216 | envval = getenv (envname); | 1228 | envval = getenv (envname); |
1217 | 1229 | ||
1218 | /* Copy into the line if it exists */ | 1230 | /* Copy into the line if it exists */ |
1219 | if (envval != NULL) | 1231 | if (envval != NULL) |
1220 | while ((*envval) && outputcnt) { | 1232 | while ((*envval) && outputcnt) { |
1221 | *(output++) = *(envval++); | 1233 | *(output++) = *(envval++); |
1222 | outputcnt--; | 1234 | outputcnt--; |
1223 | } | 1235 | } |
1224 | /* Look for another '$' */ | 1236 | /* Look for another '$' */ |
1225 | state = 0; | 1237 | state = 0; |
1226 | } | 1238 | } |
1227 | break; | 1239 | break; |
1228 | case 3: /* Waiting for ' */ | 1240 | case 3: /* Waiting for ' */ |
1229 | if ((c == '\'') && (prev != '\\')) { | 1241 | if ((c == '\'') && (prev != '\\')) { |
1230 | state = 0; | 1242 | state = 0; |
1231 | } else { | 1243 | } else { |
1232 | *(output++) = c; | 1244 | *(output++) = c; |
1233 | outputcnt--; | 1245 | outputcnt--; |
1234 | } | 1246 | } |
1235 | break; | 1247 | break; |
1236 | } | 1248 | } |
1237 | prev = c; | 1249 | prev = c; |
1238 | } | 1250 | } |
1239 | 1251 | ||
1240 | if (outputcnt) | 1252 | if (outputcnt) |
1241 | *output = 0; | 1253 | *output = 0; |
1242 | else | 1254 | else |
1243 | *(output - 1) = 0; | 1255 | *(output - 1) = 0; |
1244 | 1256 | ||
1245 | #ifdef DEBUG_PARSER | 1257 | #ifdef DEBUG_PARSER |
1246 | printf ("[PROCESS_MACROS] OUTPUT len %d: \"%s\"\n", | 1258 | printf ("[PROCESS_MACROS] OUTPUT len %d: \"%s\"\n", |
1247 | strlen (output_start), output_start); | 1259 | strlen (output_start), output_start); |
1248 | #endif | 1260 | #endif |
1249 | } | 1261 | } |
1250 | 1262 | ||
1251 | /**************************************************************************** | 1263 | /**************************************************************************** |
1252 | * returns: | 1264 | * returns: |
1253 | * 1 - command executed, repeatable | 1265 | * 1 - command executed, repeatable |
1254 | * 0 - command executed but not repeatable, interrupted commands are | 1266 | * 0 - command executed but not repeatable, interrupted commands are |
1255 | * always considered not repeatable | 1267 | * always considered not repeatable |
1256 | * -1 - not executed (unrecognized, bootd recursion or too many args) | 1268 | * -1 - not executed (unrecognized, bootd recursion or too many args) |
1257 | * (If cmd is NULL or "" or longer than CONFIG_SYS_CBSIZE-1 it is | 1269 | * (If cmd is NULL or "" or longer than CONFIG_SYS_CBSIZE-1 it is |
1258 | * considered unrecognized) | 1270 | * considered unrecognized) |
1259 | * | 1271 | * |
1260 | * WARNING: | 1272 | * WARNING: |
1261 | * | 1273 | * |
1262 | * We must create a temporary copy of the command since the command we get | 1274 | * We must create a temporary copy of the command since the command we get |
1263 | * may be the result from getenv(), which returns a pointer directly to | 1275 | * may be the result from getenv(), which returns a pointer directly to |
1264 | * the environment data, which may change magicly when the command we run | 1276 | * the environment data, which may change magicly when the command we run |
1265 | * creates or modifies environment variables (like "bootp" does). | 1277 | * creates or modifies environment variables (like "bootp" does). |
1266 | */ | 1278 | */ |
1267 | 1279 | ||
1268 | int run_command (const char *cmd, int flag) | 1280 | int run_command (const char *cmd, int flag) |
1269 | { | 1281 | { |
1270 | cmd_tbl_t *cmdtp; | 1282 | cmd_tbl_t *cmdtp; |
1271 | char cmdbuf[CONFIG_SYS_CBSIZE]; /* working copy of cmd */ | 1283 | char cmdbuf[CONFIG_SYS_CBSIZE]; /* working copy of cmd */ |
1272 | char *token; /* start of token in cmdbuf */ | 1284 | char *token; /* start of token in cmdbuf */ |
1273 | char *sep; /* end of token (separator) in cmdbuf */ | 1285 | char *sep; /* end of token (separator) in cmdbuf */ |
1274 | char finaltoken[CONFIG_SYS_CBSIZE]; | 1286 | char finaltoken[CONFIG_SYS_CBSIZE]; |
1275 | char *str = cmdbuf; | 1287 | char *str = cmdbuf; |
1276 | char *argv[CONFIG_SYS_MAXARGS + 1]; /* NULL terminated */ | 1288 | char *argv[CONFIG_SYS_MAXARGS + 1]; /* NULL terminated */ |
1277 | int argc, inquotes; | 1289 | int argc, inquotes; |
1278 | int repeatable = 1; | 1290 | int repeatable = 1; |
1279 | int rc = 0; | 1291 | int rc = 0; |
1280 | 1292 | ||
1281 | #ifdef DEBUG_PARSER | 1293 | #ifdef DEBUG_PARSER |
1282 | printf ("[RUN_COMMAND] cmd[%p]=\"", cmd); | 1294 | printf ("[RUN_COMMAND] cmd[%p]=\"", cmd); |
1283 | puts (cmd ? cmd : "NULL"); /* use puts - string may be loooong */ | 1295 | puts (cmd ? cmd : "NULL"); /* use puts - string may be loooong */ |
1284 | puts ("\"\n"); | 1296 | puts ("\"\n"); |
1285 | #endif | 1297 | #endif |
1286 | 1298 | ||
1287 | clear_ctrlc(); /* forget any previous Control C */ | 1299 | clear_ctrlc(); /* forget any previous Control C */ |
1288 | 1300 | ||
1289 | if (!cmd || !*cmd) { | 1301 | if (!cmd || !*cmd) { |
1290 | return -1; /* empty command */ | 1302 | return -1; /* empty command */ |
1291 | } | 1303 | } |
1292 | 1304 | ||
1293 | if (strlen(cmd) >= CONFIG_SYS_CBSIZE) { | 1305 | if (strlen(cmd) >= CONFIG_SYS_CBSIZE) { |
1294 | puts ("## Command too long!\n"); | 1306 | puts ("## Command too long!\n"); |
1295 | return -1; | 1307 | return -1; |
1296 | } | 1308 | } |
1297 | 1309 | ||
1298 | strcpy (cmdbuf, cmd); | 1310 | strcpy (cmdbuf, cmd); |
1299 | 1311 | ||
1300 | /* Process separators and check for invalid | 1312 | /* Process separators and check for invalid |
1301 | * repeatable commands | 1313 | * repeatable commands |
1302 | */ | 1314 | */ |
1303 | 1315 | ||
1304 | #ifdef DEBUG_PARSER | 1316 | #ifdef DEBUG_PARSER |
1305 | printf ("[PROCESS_SEPARATORS] %s\n", cmd); | 1317 | printf ("[PROCESS_SEPARATORS] %s\n", cmd); |
1306 | #endif | 1318 | #endif |
1307 | while (*str) { | 1319 | while (*str) { |
1308 | 1320 | ||
1309 | /* | 1321 | /* |
1310 | * Find separator, or string end | 1322 | * Find separator, or string end |
1311 | * Allow simple escape of ';' by writing "\;" | 1323 | * Allow simple escape of ';' by writing "\;" |
1312 | */ | 1324 | */ |
1313 | for (inquotes = 0, sep = str; *sep; sep++) { | 1325 | for (inquotes = 0, sep = str; *sep; sep++) { |
1314 | if ((*sep=='\'') && | 1326 | if ((*sep=='\'') && |
1315 | (*(sep-1) != '\\')) | 1327 | (*(sep-1) != '\\')) |
1316 | inquotes=!inquotes; | 1328 | inquotes=!inquotes; |
1317 | 1329 | ||
1318 | if (!inquotes && | 1330 | if (!inquotes && |
1319 | (*sep == ';') && /* separator */ | 1331 | (*sep == ';') && /* separator */ |
1320 | ( sep != str) && /* past string start */ | 1332 | ( sep != str) && /* past string start */ |
1321 | (*(sep-1) != '\\')) /* and NOT escaped */ | 1333 | (*(sep-1) != '\\')) /* and NOT escaped */ |
1322 | break; | 1334 | break; |
1323 | } | 1335 | } |
1324 | 1336 | ||
1325 | /* | 1337 | /* |
1326 | * Limit the token to data between separators | 1338 | * Limit the token to data between separators |
1327 | */ | 1339 | */ |
1328 | token = str; | 1340 | token = str; |
1329 | if (*sep) { | 1341 | if (*sep) { |
1330 | str = sep + 1; /* start of command for next pass */ | 1342 | str = sep + 1; /* start of command for next pass */ |
1331 | *sep = '\0'; | 1343 | *sep = '\0'; |
1332 | } | 1344 | } |
1333 | else | 1345 | else |
1334 | str = sep; /* no more commands for next pass */ | 1346 | str = sep; /* no more commands for next pass */ |
1335 | #ifdef DEBUG_PARSER | 1347 | #ifdef DEBUG_PARSER |
1336 | printf ("token: \"%s\"\n", token); | 1348 | printf ("token: \"%s\"\n", token); |
1337 | #endif | 1349 | #endif |
1338 | 1350 | ||
1339 | /* find macros in this token and replace them */ | 1351 | /* find macros in this token and replace them */ |
1340 | process_macros (token, finaltoken); | 1352 | process_macros (token, finaltoken); |
1341 | 1353 | ||
1342 | /* Extract arguments */ | 1354 | /* Extract arguments */ |
1343 | if ((argc = parse_line (finaltoken, argv)) == 0) { | 1355 | if ((argc = parse_line (finaltoken, argv)) == 0) { |
1344 | rc = -1; /* no command at all */ | 1356 | rc = -1; /* no command at all */ |
1345 | continue; | 1357 | continue; |
1346 | } | 1358 | } |
1347 | 1359 | ||
1348 | /* Look up command in command table */ | 1360 | /* Look up command in command table */ |
1349 | if ((cmdtp = find_cmd(argv[0])) == NULL) { | 1361 | if ((cmdtp = find_cmd(argv[0])) == NULL) { |
1350 | printf ("Unknown command '%s' - try 'help'\n", argv[0]); | 1362 | printf ("Unknown command '%s' - try 'help'\n", argv[0]); |
1351 | rc = -1; /* give up after bad command */ | 1363 | rc = -1; /* give up after bad command */ |
1352 | continue; | 1364 | continue; |
1353 | } | 1365 | } |
1354 | 1366 | ||
1355 | /* found - check max args */ | 1367 | /* found - check max args */ |
1356 | if (argc > cmdtp->maxargs) { | 1368 | if (argc > cmdtp->maxargs) { |
1357 | cmd_usage(cmdtp); | 1369 | cmd_usage(cmdtp); |
1358 | rc = -1; | 1370 | rc = -1; |
1359 | continue; | 1371 | continue; |
1360 | } | 1372 | } |
1361 | 1373 | ||
1362 | #if defined(CONFIG_CMD_BOOTD) | 1374 | #if defined(CONFIG_CMD_BOOTD) |
1363 | /* avoid "bootd" recursion */ | 1375 | /* avoid "bootd" recursion */ |
1364 | if (cmdtp->cmd == do_bootd) { | 1376 | if (cmdtp->cmd == do_bootd) { |
1365 | #ifdef DEBUG_PARSER | 1377 | #ifdef DEBUG_PARSER |
1366 | printf ("[%s]\n", finaltoken); | 1378 | printf ("[%s]\n", finaltoken); |
1367 | #endif | 1379 | #endif |
1368 | if (flag & CMD_FLAG_BOOTD) { | 1380 | if (flag & CMD_FLAG_BOOTD) { |
1369 | puts ("'bootd' recursion detected\n"); | 1381 | puts ("'bootd' recursion detected\n"); |
1370 | rc = -1; | 1382 | rc = -1; |
1371 | continue; | 1383 | continue; |
1372 | } else { | 1384 | } else { |
1373 | flag |= CMD_FLAG_BOOTD; | 1385 | flag |= CMD_FLAG_BOOTD; |
1374 | } | 1386 | } |
1375 | } | 1387 | } |
1376 | #endif | 1388 | #endif |
1377 | 1389 | ||
1378 | /* OK - call function to do the command */ | 1390 | /* OK - call function to do the command */ |
1379 | if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) { | 1391 | if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) { |
1380 | rc = -1; | 1392 | rc = -1; |
1381 | } | 1393 | } |
1382 | 1394 | ||
1383 | repeatable &= cmdtp->repeatable; | 1395 | repeatable &= cmdtp->repeatable; |
1384 | 1396 | ||
1385 | /* Did the user stop this? */ | 1397 | /* Did the user stop this? */ |
1386 | if (had_ctrlc ()) | 1398 | if (had_ctrlc ()) |
1387 | return -1; /* if stopped then not repeatable */ | 1399 | return -1; /* if stopped then not repeatable */ |
1388 | } | 1400 | } |
1389 | 1401 | ||
1390 | return rc ? rc : repeatable; | 1402 | return rc ? rc : repeatable; |
1391 | } | 1403 | } |
1392 | 1404 | ||
1393 | /****************************************************************************/ | 1405 | /****************************************************************************/ |
1394 | 1406 | ||
1395 | #if defined(CONFIG_CMD_RUN) | 1407 | #if defined(CONFIG_CMD_RUN) |
1396 | int do_run (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) | 1408 | int do_run (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) |
1397 | { | 1409 | { |
1398 | int i; | 1410 | int i; |
1399 | 1411 | ||
1400 | if (argc < 2) | 1412 | if (argc < 2) |
1401 | return cmd_usage(cmdtp); | 1413 | return cmd_usage(cmdtp); |
1402 | 1414 | ||
1403 | for (i=1; i<argc; ++i) { | 1415 | for (i=1; i<argc; ++i) { |
1404 | char *arg; | 1416 | char *arg; |
1405 | 1417 | ||
1406 | if ((arg = getenv (argv[i])) == NULL) { | 1418 | if ((arg = getenv (argv[i])) == NULL) { |
1407 | printf ("## Error: \"%s\" not defined\n", argv[i]); | 1419 | printf ("## Error: \"%s\" not defined\n", argv[i]); |
1408 | return 1; | 1420 | return 1; |
1409 | } | 1421 | } |
1410 | 1422 | ||
1411 | if (run_command2(arg, flag) != 0) | 1423 | if (run_command2(arg, flag) != 0) |
1412 | return 1; | 1424 | return 1; |
1413 | } | 1425 | } |
1414 | return 0; | 1426 | return 0; |
1415 | } | 1427 | } |
1416 | #endif | 1428 | #endif |
1417 | 1429 |
common/menu.c
1 | /* | 1 | /* |
2 | * Copyright 2010-2011 Calxeda, Inc. | 2 | * Copyright 2010-2011 Calxeda, Inc. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms of the GNU General Public License as published by the Free | 5 | * under the terms of the GNU General Public License as published by the Free |
6 | * Software Foundation; either version 2 of the License, or (at your option) | 6 | * Software Foundation; either version 2 of the License, or (at your option) |
7 | * any later version. | 7 | * any later version. |
8 | * | 8 | * |
9 | * This program is distributed in the hope it will be useful, but WITHOUT | 9 | * This program is distributed in the hope it will be useful, but WITHOUT |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
12 | * more details. | 12 | * more details. |
13 | * | 13 | * |
14 | * You should have received a copy of the GNU General Public License along with | 14 | * You should have received a copy of the GNU General Public License along with |
15 | * this program. If not, see <http://www.gnu.org/licenses/>. | 15 | * this program. If not, see <http://www.gnu.org/licenses/>. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <common.h> | 18 | #include <common.h> |
19 | #include <malloc.h> | 19 | #include <malloc.h> |
20 | #include <errno.h> | 20 | #include <errno.h> |
21 | #include <linux/list.h> | 21 | #include <linux/list.h> |
22 | 22 | ||
23 | #include "menu.h" | 23 | #include "menu.h" |
24 | 24 | ||
25 | /* | 25 | /* |
26 | * Internally, each item in a menu is represented by a struct menu_item. | 26 | * Internally, each item in a menu is represented by a struct menu_item. |
27 | * | 27 | * |
28 | * These items will be alloc'd and initialized by menu_item_add and destroyed | 28 | * These items will be alloc'd and initialized by menu_item_add and destroyed |
29 | * by menu_item_destroy, and the consumer of the interface never sees that | 29 | * by menu_item_destroy, and the consumer of the interface never sees that |
30 | * this struct is used at all. | 30 | * this struct is used at all. |
31 | */ | 31 | */ |
32 | struct menu_item { | 32 | struct menu_item { |
33 | char *key; | 33 | char *key; |
34 | void *data; | 34 | void *data; |
35 | struct list_head list; | 35 | struct list_head list; |
36 | }; | 36 | }; |
37 | 37 | ||
38 | /* | 38 | /* |
39 | * The menu is composed of a list of items along with settings and callbacks | 39 | * The menu is composed of a list of items along with settings and callbacks |
40 | * provided by the user. An incomplete definition of this struct is available | 40 | * provided by the user. An incomplete definition of this struct is available |
41 | * in menu.h, but the full definition is here to prevent consumers from | 41 | * in menu.h, but the full definition is here to prevent consumers from |
42 | * relying on its contents. | 42 | * relying on its contents. |
43 | */ | 43 | */ |
44 | struct menu { | 44 | struct menu { |
45 | struct menu_item *default_item; | 45 | struct menu_item *default_item; |
46 | int timeout; | 46 | int timeout; |
47 | char *title; | 47 | char *title; |
48 | int prompt; | 48 | int prompt; |
49 | void (*item_data_print)(void *); | 49 | void (*item_data_print)(void *); |
50 | struct list_head items; | 50 | struct list_head items; |
51 | }; | 51 | }; |
52 | 52 | ||
53 | /* | 53 | /* |
54 | * An iterator function for menu items. callback will be called for each item | 54 | * An iterator function for menu items. callback will be called for each item |
55 | * in m, with m, a pointer to the item, and extra being passed to callback. If | 55 | * in m, with m, a pointer to the item, and extra being passed to callback. If |
56 | * callback returns a value other than NULL, iteration stops and the value | 56 | * callback returns a value other than NULL, iteration stops and the value |
57 | * return by callback is returned from menu_items_iter. This allows it to be | 57 | * return by callback is returned from menu_items_iter. This allows it to be |
58 | * used for search type operations. It is also safe for callback to remove the | 58 | * used for search type operations. It is also safe for callback to remove the |
59 | * item from the list of items. | 59 | * item from the list of items. |
60 | */ | 60 | */ |
61 | static inline void *menu_items_iter(struct menu *m, | 61 | static inline void *menu_items_iter(struct menu *m, |
62 | void *(*callback)(struct menu *, struct menu_item *, void *), | 62 | void *(*callback)(struct menu *, struct menu_item *, void *), |
63 | void *extra) | 63 | void *extra) |
64 | { | 64 | { |
65 | struct list_head *pos, *n; | 65 | struct list_head *pos, *n; |
66 | struct menu_item *item; | 66 | struct menu_item *item; |
67 | void *ret; | 67 | void *ret; |
68 | 68 | ||
69 | list_for_each_safe(pos, n, &m->items) { | 69 | list_for_each_safe(pos, n, &m->items) { |
70 | item = list_entry(pos, struct menu_item, list); | 70 | item = list_entry(pos, struct menu_item, list); |
71 | 71 | ||
72 | ret = callback(m, item, extra); | 72 | ret = callback(m, item, extra); |
73 | 73 | ||
74 | if (ret) | 74 | if (ret) |
75 | return ret; | 75 | return ret; |
76 | } | 76 | } |
77 | 77 | ||
78 | return NULL; | 78 | return NULL; |
79 | } | 79 | } |
80 | 80 | ||
81 | /* | 81 | /* |
82 | * Print a menu_item. If the consumer provided an item_data_print function | 82 | * Print a menu_item. If the consumer provided an item_data_print function |
83 | * when creating the menu, call it with a pointer to the item's private data. | 83 | * when creating the menu, call it with a pointer to the item's private data. |
84 | * Otherwise, print the key of the item. | 84 | * Otherwise, print the key of the item. |
85 | */ | 85 | */ |
86 | static inline void *menu_item_print(struct menu *m, | 86 | static inline void *menu_item_print(struct menu *m, |
87 | struct menu_item *item, | 87 | struct menu_item *item, |
88 | void *extra) | 88 | void *extra) |
89 | { | 89 | { |
90 | if (!m->item_data_print) { | 90 | if (!m->item_data_print) { |
91 | puts(item->key); | 91 | puts(item->key); |
92 | putc('\n'); | 92 | putc('\n'); |
93 | } else { | 93 | } else { |
94 | m->item_data_print(item->data); | 94 | m->item_data_print(item->data); |
95 | } | 95 | } |
96 | 96 | ||
97 | return NULL; | 97 | return NULL; |
98 | } | 98 | } |
99 | 99 | ||
100 | /* | 100 | /* |
101 | * Free the memory used by a menu item. This includes the memory used by its | 101 | * Free the memory used by a menu item. This includes the memory used by its |
102 | * key. | 102 | * key. |
103 | */ | 103 | */ |
104 | static inline void *menu_item_destroy(struct menu *m, | 104 | static inline void *menu_item_destroy(struct menu *m, |
105 | struct menu_item *item, | 105 | struct menu_item *item, |
106 | void *extra) | 106 | void *extra) |
107 | { | 107 | { |
108 | if (item->key) | 108 | if (item->key) |
109 | free(item->key); | 109 | free(item->key); |
110 | 110 | ||
111 | free(item); | 111 | free(item); |
112 | 112 | ||
113 | return NULL; | 113 | return NULL; |
114 | } | 114 | } |
115 | 115 | ||
116 | /* | 116 | /* |
117 | * Display a menu so the user can make a choice of an item. First display its | 117 | * Display a menu so the user can make a choice of an item. First display its |
118 | * title, if any, and then each item in the menu. | 118 | * title, if any, and then each item in the menu. |
119 | */ | 119 | */ |
120 | static inline void menu_display(struct menu *m) | 120 | static inline void menu_display(struct menu *m) |
121 | { | 121 | { |
122 | if (m->title) { | 122 | if (m->title) { |
123 | puts(m->title); | 123 | puts(m->title); |
124 | putc('\n'); | 124 | putc('\n'); |
125 | } | 125 | } |
126 | 126 | ||
127 | menu_items_iter(m, menu_item_print, NULL); | 127 | menu_items_iter(m, menu_item_print, NULL); |
128 | } | 128 | } |
129 | 129 | ||
130 | /* | 130 | /* |
131 | * Check if an item's key matches a provided string, pointed to by extra. If | 131 | * Check if an item's key matches a provided string, pointed to by extra. If |
132 | * extra is NULL, an item with a NULL key will match. Otherwise, the item's | 132 | * extra is NULL, an item with a NULL key will match. Otherwise, the item's |
133 | * key has to match according to strcmp. | 133 | * key has to match according to strcmp. |
134 | * | 134 | * |
135 | * This is called via menu_items_iter, so it returns a pointer to the item if | 135 | * This is called via menu_items_iter, so it returns a pointer to the item if |
136 | * the key matches, and returns NULL otherwise. | 136 | * the key matches, and returns NULL otherwise. |
137 | */ | 137 | */ |
138 | static inline void *menu_item_key_match(struct menu *m, | 138 | static inline void *menu_item_key_match(struct menu *m, |
139 | struct menu_item *item, void *extra) | 139 | struct menu_item *item, void *extra) |
140 | { | 140 | { |
141 | char *item_key = extra; | 141 | char *item_key = extra; |
142 | 142 | ||
143 | if (!item_key || !item->key) { | 143 | if (!item_key || !item->key) { |
144 | if (item_key == item->key) | 144 | if (item_key == item->key) |
145 | return item; | 145 | return item; |
146 | 146 | ||
147 | return NULL; | 147 | return NULL; |
148 | } | 148 | } |
149 | 149 | ||
150 | if (strcmp(item->key, item_key) == 0) | 150 | if (strcmp(item->key, item_key) == 0) |
151 | return item; | 151 | return item; |
152 | 152 | ||
153 | return NULL; | 153 | return NULL; |
154 | } | 154 | } |
155 | 155 | ||
156 | /* | 156 | /* |
157 | * Find the first item with a key matching item_key, if any exists. | 157 | * Find the first item with a key matching item_key, if any exists. |
158 | */ | 158 | */ |
159 | static inline struct menu_item *menu_item_by_key(struct menu *m, | 159 | static inline struct menu_item *menu_item_by_key(struct menu *m, |
160 | char *item_key) | 160 | char *item_key) |
161 | { | 161 | { |
162 | return menu_items_iter(m, menu_item_key_match, item_key); | 162 | return menu_items_iter(m, menu_item_key_match, item_key); |
163 | } | 163 | } |
164 | 164 | ||
165 | /* | 165 | /* |
166 | * Wait for the user to hit a key according to the timeout set for the menu. | 166 | * Wait for the user to hit a key according to the timeout set for the menu. |
167 | * Returns 1 if the user hit a key, or 0 if the timeout expired. | 167 | * Returns 1 if the user hit a key, or 0 if the timeout expired. |
168 | */ | 168 | */ |
169 | static inline int menu_interrupted(struct menu *m) | 169 | static inline int menu_interrupted(struct menu *m) |
170 | { | 170 | { |
171 | if (!m->timeout) | 171 | if (!m->timeout) |
172 | return 0; | 172 | return 0; |
173 | 173 | ||
174 | if (abortboot(m->timeout/10)) | 174 | if (abortboot(m->timeout/10)) |
175 | return 1; | 175 | return 1; |
176 | 176 | ||
177 | return 0; | 177 | return 0; |
178 | } | 178 | } |
179 | 179 | ||
180 | /* | 180 | /* |
181 | * Checks whether or not the default menu item should be used without | 181 | * Checks whether or not the default menu item should be used without |
182 | * prompting for a user choice. If the menu is set to always prompt, or the | 182 | * prompting for a user choice. If the menu is set to always prompt, or the |
183 | * user hits a key during the timeout period, return 0. Otherwise, return 1 to | 183 | * user hits a key during the timeout period, return 0. Otherwise, return 1 to |
184 | * indicate we should use the default menu item. | 184 | * indicate we should use the default menu item. |
185 | */ | 185 | */ |
186 | static inline int menu_use_default(struct menu *m) | 186 | static inline int menu_use_default(struct menu *m) |
187 | { | 187 | { |
188 | return !m->prompt && !menu_interrupted(m); | 188 | return !m->prompt && !menu_interrupted(m); |
189 | } | 189 | } |
190 | 190 | ||
191 | /* | 191 | /* |
192 | * Set *choice to point to the default item's data, if any default item was | 192 | * Set *choice to point to the default item's data, if any default item was |
193 | * set, and returns 1. If no default item was set, returns -ENOENT. | 193 | * set, and returns 1. If no default item was set, returns -ENOENT. |
194 | */ | 194 | */ |
195 | static inline int menu_default_choice(struct menu *m, void **choice) | 195 | static inline int menu_default_choice(struct menu *m, void **choice) |
196 | { | 196 | { |
197 | if (m->default_item) { | 197 | if (m->default_item) { |
198 | *choice = m->default_item->data; | 198 | *choice = m->default_item->data; |
199 | return 1; | 199 | return 1; |
200 | } | 200 | } |
201 | 201 | ||
202 | return -ENOENT; | 202 | return -ENOENT; |
203 | } | 203 | } |
204 | 204 | ||
205 | /* | 205 | /* |
206 | * Displays the menu and asks the user to choose an item. *choice will point | 206 | * Displays the menu and asks the user to choose an item. *choice will point |
207 | * to the private data of the item the user chooses. The user makes a choice | 207 | * to the private data of the item the user chooses. The user makes a choice |
208 | * by inputting a string matching the key of an item. Invalid choices will | 208 | * by inputting a string matching the key of an item. Invalid choices will |
209 | * cause the user to be prompted again, repeatedly, until the user makes a | 209 | * cause the user to be prompted again, repeatedly, until the user makes a |
210 | * valid choice. The user can exit the menu without making a choice via ^c. | 210 | * valid choice. The user can exit the menu without making a choice via ^c. |
211 | * | 211 | * |
212 | * Returns 1 if the user made a choice, or -EINTR if they bail via ^c. | 212 | * Returns 1 if the user made a choice, or -EINTR if they bail via ^c. |
213 | */ | 213 | */ |
214 | static inline int menu_interactive_choice(struct menu *m, void **choice) | 214 | static inline int menu_interactive_choice(struct menu *m, void **choice) |
215 | { | 215 | { |
216 | char cbuf[CONFIG_SYS_CBSIZE]; | 216 | char cbuf[CONFIG_SYS_CBSIZE]; |
217 | struct menu_item *choice_item = NULL; | 217 | struct menu_item *choice_item = NULL; |
218 | int readret; | 218 | int readret; |
219 | 219 | ||
220 | while (!choice_item) { | 220 | while (!choice_item) { |
221 | cbuf[0] = '\0'; | 221 | cbuf[0] = '\0'; |
222 | 222 | ||
223 | menu_display(m); | 223 | menu_display(m); |
224 | 224 | ||
225 | readret = readline_into_buffer("Enter choice: ", cbuf); | 225 | readret = readline_into_buffer("Enter choice: ", cbuf, |
226 | m->timeout); | ||
226 | 227 | ||
227 | if (readret >= 0) { | 228 | if (readret >= 0) { |
228 | choice_item = menu_item_by_key(m, cbuf); | 229 | choice_item = menu_item_by_key(m, cbuf); |
229 | 230 | ||
230 | if (!choice_item) | 231 | if (!choice_item) |
231 | printf("%s not found\n", cbuf); | 232 | printf("%s not found\n", cbuf); |
232 | } else { | 233 | } else { |
233 | puts("^C\n"); | 234 | puts("^C\n"); |
234 | return -EINTR; | 235 | return -EINTR; |
235 | } | 236 | } |
236 | } | 237 | } |
237 | 238 | ||
238 | *choice = choice_item->data; | 239 | *choice = choice_item->data; |
239 | 240 | ||
240 | return 1; | 241 | return 1; |
241 | } | 242 | } |
242 | 243 | ||
243 | /* | 244 | /* |
244 | * menu_default_set() - Sets the default choice for the menu. This is safe to | 245 | * menu_default_set() - Sets the default choice for the menu. This is safe to |
245 | * call more than once on a menu. | 246 | * call more than once on a menu. |
246 | * | 247 | * |
247 | * m - Points to a menu created by menu_create(). | 248 | * m - Points to a menu created by menu_create(). |
248 | * | 249 | * |
249 | * item_key - Points to a string that, when compared using strcmp, matches the | 250 | * item_key - Points to a string that, when compared using strcmp, matches the |
250 | * key for an existing item in the menu. | 251 | * key for an existing item in the menu. |
251 | * | 252 | * |
252 | * Returns 1 if successful, -EINVAL if m is NULL, or -ENOENT if no item with a | 253 | * Returns 1 if successful, -EINVAL if m is NULL, or -ENOENT if no item with a |
253 | * key matching item_key is found. | 254 | * key matching item_key is found. |
254 | */ | 255 | */ |
255 | int menu_default_set(struct menu *m, char *item_key) | 256 | int menu_default_set(struct menu *m, char *item_key) |
256 | { | 257 | { |
257 | struct menu_item *item; | 258 | struct menu_item *item; |
258 | 259 | ||
259 | if (!m) | 260 | if (!m) |
260 | return -EINVAL; | 261 | return -EINVAL; |
261 | 262 | ||
262 | item = menu_item_by_key(m, item_key); | 263 | item = menu_item_by_key(m, item_key); |
263 | 264 | ||
264 | if (!item) | 265 | if (!item) |
265 | return -ENOENT; | 266 | return -ENOENT; |
266 | 267 | ||
267 | m->default_item = item; | 268 | m->default_item = item; |
268 | 269 | ||
269 | return 1; | 270 | return 1; |
270 | } | 271 | } |
271 | 272 | ||
272 | /* | 273 | /* |
273 | * menu_get_choice() - Returns the user's selected menu entry, or the default | 274 | * menu_get_choice() - Returns the user's selected menu entry, or the default |
274 | * if the menu is set to not prompt or the timeout expires. This is safe to | 275 | * if the menu is set to not prompt or the timeout expires. This is safe to |
275 | * call more than once. | 276 | * call more than once. |
276 | * | 277 | * |
277 | * m - Points to a menu created by menu_create(). | 278 | * m - Points to a menu created by menu_create(). |
278 | * | 279 | * |
279 | * choice - Points to a location that will store a pointer to the selected | 280 | * choice - Points to a location that will store a pointer to the selected |
280 | * menu item. If no item is selected or there is an error, no value will be | 281 | * menu item. If no item is selected or there is an error, no value will be |
281 | * written at the location it points to. | 282 | * written at the location it points to. |
282 | * | 283 | * |
283 | * Returns 1 if successful, -EINVAL if m or choice is NULL, -ENOENT if no | 284 | * Returns 1 if successful, -EINVAL if m or choice is NULL, -ENOENT if no |
284 | * default has been set and the menu is set to not prompt or the timeout | 285 | * default has been set and the menu is set to not prompt or the timeout |
285 | * expires, or -EINTR if the user exits the menu via ^c. | 286 | * expires, or -EINTR if the user exits the menu via ^c. |
286 | */ | 287 | */ |
287 | int menu_get_choice(struct menu *m, void **choice) | 288 | int menu_get_choice(struct menu *m, void **choice) |
288 | { | 289 | { |
289 | if (!m || !choice) | 290 | if (!m || !choice) |
290 | return -EINVAL; | 291 | return -EINVAL; |
291 | 292 | ||
292 | if (menu_use_default(m)) | 293 | if (menu_use_default(m)) |
293 | return menu_default_choice(m, choice); | 294 | return menu_default_choice(m, choice); |
294 | 295 | ||
295 | return menu_interactive_choice(m, choice); | 296 | return menu_interactive_choice(m, choice); |
296 | } | 297 | } |
297 | 298 | ||
298 | /* | 299 | /* |
299 | * menu_item_add() - Adds or replaces a menu item. Note that this replaces the | 300 | * menu_item_add() - Adds or replaces a menu item. Note that this replaces the |
300 | * data of an item if it already exists, but doesn't change the order of the | 301 | * data of an item if it already exists, but doesn't change the order of the |
301 | * item. | 302 | * item. |
302 | * | 303 | * |
303 | * m - Points to a menu created by menu_create(). | 304 | * m - Points to a menu created by menu_create(). |
304 | * | 305 | * |
305 | * item_key - Points to a string that will uniquely identify the item. The | 306 | * item_key - Points to a string that will uniquely identify the item. The |
306 | * string will be copied to internal storage, and is safe to discard after | 307 | * string will be copied to internal storage, and is safe to discard after |
307 | * passing to menu_item_add. | 308 | * passing to menu_item_add. |
308 | * | 309 | * |
309 | * item_data - An opaque pointer associated with an item. It is never | 310 | * item_data - An opaque pointer associated with an item. It is never |
310 | * dereferenced internally, but will be passed to the item_data_print, and | 311 | * dereferenced internally, but will be passed to the item_data_print, and |
311 | * will be returned from menu_get_choice if the menu item is selected. | 312 | * will be returned from menu_get_choice if the menu item is selected. |
312 | * | 313 | * |
313 | * Returns 1 if successful, -EINVAL if m is NULL, or -ENOMEM if there is | 314 | * Returns 1 if successful, -EINVAL if m is NULL, or -ENOMEM if there is |
314 | * insufficient memory to add the menu item. | 315 | * insufficient memory to add the menu item. |
315 | */ | 316 | */ |
316 | int menu_item_add(struct menu *m, char *item_key, void *item_data) | 317 | int menu_item_add(struct menu *m, char *item_key, void *item_data) |
317 | { | 318 | { |
318 | struct menu_item *item; | 319 | struct menu_item *item; |
319 | 320 | ||
320 | if (!m) | 321 | if (!m) |
321 | return -EINVAL; | 322 | return -EINVAL; |
322 | 323 | ||
323 | item = menu_item_by_key(m, item_key); | 324 | item = menu_item_by_key(m, item_key); |
324 | 325 | ||
325 | if (item) { | 326 | if (item) { |
326 | item->data = item_data; | 327 | item->data = item_data; |
327 | return 1; | 328 | return 1; |
328 | } | 329 | } |
329 | 330 | ||
330 | item = malloc(sizeof *item); | 331 | item = malloc(sizeof *item); |
331 | if (!item) | 332 | if (!item) |
332 | return -ENOMEM; | 333 | return -ENOMEM; |
333 | 334 | ||
334 | item->key = strdup(item_key); | 335 | item->key = strdup(item_key); |
335 | 336 | ||
336 | if (!item->key) { | 337 | if (!item->key) { |
337 | free(item); | 338 | free(item); |
338 | return -ENOMEM; | 339 | return -ENOMEM; |
339 | } | 340 | } |
340 | 341 | ||
341 | item->data = item_data; | 342 | item->data = item_data; |
342 | 343 | ||
343 | list_add_tail(&item->list, &m->items); | 344 | list_add_tail(&item->list, &m->items); |
344 | 345 | ||
345 | return 1; | 346 | return 1; |
346 | } | 347 | } |
347 | 348 | ||
348 | /* | 349 | /* |
349 | * menu_create() - Creates a menu handle with default settings | 350 | * menu_create() - Creates a menu handle with default settings |
350 | * | 351 | * |
351 | * title - If not NULL, points to a string that will be displayed before the | 352 | * title - If not NULL, points to a string that will be displayed before the |
352 | * list of menu items. It will be copied to internal storage, and is safe to | 353 | * list of menu items. It will be copied to internal storage, and is safe to |
353 | * discard after passing to menu_create(). | 354 | * discard after passing to menu_create(). |
354 | * | 355 | * |
355 | * timeout - A delay in seconds to wait for user input. If 0, timeout is | 356 | * timeout - A delay in seconds to wait for user input. If 0, timeout is |
356 | * disabled, and the default choice will be returned unless prompt is 1. | 357 | * disabled, and the default choice will be returned unless prompt is 1. |
357 | * | 358 | * |
358 | * prompt - If 0, don't ask for user input unless there is an interrupted | 359 | * prompt - If 0, don't ask for user input unless there is an interrupted |
359 | * timeout. If 1, the user will be prompted for input regardless of the value | 360 | * timeout. If 1, the user will be prompted for input regardless of the value |
360 | * of timeout. | 361 | * of timeout. |
361 | * | 362 | * |
362 | * item_data_print - If not NULL, will be called for each item when the menu | 363 | * item_data_print - If not NULL, will be called for each item when the menu |
363 | * is displayed, with the pointer to the item's data passed as the argument. | 364 | * is displayed, with the pointer to the item's data passed as the argument. |
364 | * If NULL, each item's key will be printed instead. Since an item's key is | 365 | * If NULL, each item's key will be printed instead. Since an item's key is |
365 | * what must be entered to select an item, the item_data_print function should | 366 | * what must be entered to select an item, the item_data_print function should |
366 | * make it obvious what the key for each entry is. | 367 | * make it obvious what the key for each entry is. |
367 | * | 368 | * |
368 | * Returns a pointer to the menu if successful, or NULL if there is | 369 | * Returns a pointer to the menu if successful, or NULL if there is |
369 | * insufficient memory available to create the menu. | 370 | * insufficient memory available to create the menu. |
370 | */ | 371 | */ |
371 | struct menu *menu_create(char *title, int timeout, int prompt, | 372 | struct menu *menu_create(char *title, int timeout, int prompt, |
372 | void (*item_data_print)(void *)) | 373 | void (*item_data_print)(void *)) |
373 | { | 374 | { |
374 | struct menu *m; | 375 | struct menu *m; |
375 | 376 | ||
376 | m = malloc(sizeof *m); | 377 | m = malloc(sizeof *m); |
377 | 378 | ||
378 | if (!m) | 379 | if (!m) |
379 | return NULL; | 380 | return NULL; |
380 | 381 | ||
381 | m->default_item = NULL; | 382 | m->default_item = NULL; |
382 | m->prompt = prompt; | 383 | m->prompt = prompt; |
383 | m->timeout = timeout; | 384 | m->timeout = timeout; |
384 | m->item_data_print = item_data_print; | 385 | m->item_data_print = item_data_print; |
385 | 386 | ||
386 | if (title) { | 387 | if (title) { |
387 | m->title = strdup(title); | 388 | m->title = strdup(title); |
388 | if (!m->title) { | 389 | if (!m->title) { |
389 | free(m); | 390 | free(m); |
390 | return NULL; | 391 | return NULL; |
391 | } | 392 | } |
392 | } else | 393 | } else |
393 | m->title = NULL; | 394 | m->title = NULL; |
394 | 395 | ||
395 | 396 | ||
396 | INIT_LIST_HEAD(&m->items); | 397 | INIT_LIST_HEAD(&m->items); |
397 | 398 | ||
398 | return m; | 399 | return m; |
399 | } | 400 | } |
400 | 401 | ||
401 | /* | 402 | /* |
402 | * menu_destroy() - frees the memory used by a menu and its items. | 403 | * menu_destroy() - frees the memory used by a menu and its items. |
403 | * | 404 | * |
404 | * m - Points to a menu created by menu_create(). | 405 | * m - Points to a menu created by menu_create(). |
405 | * | 406 | * |
406 | * Returns 1 if successful, or -EINVAL if m is NULL. | 407 | * Returns 1 if successful, or -EINVAL if m is NULL. |
407 | */ | 408 | */ |
408 | int menu_destroy(struct menu *m) | 409 | int menu_destroy(struct menu *m) |
409 | { | 410 | { |
410 | if (!m) | 411 | if (!m) |
411 | return -EINVAL; | 412 | return -EINVAL; |
412 | 413 | ||
413 | menu_items_iter(m, menu_item_destroy, NULL); | 414 | menu_items_iter(m, menu_item_destroy, NULL); |
414 | 415 | ||
415 | if (m->title) | 416 | if (m->title) |
416 | free(m->title); | 417 | free(m->title); |
417 | 418 | ||
418 | free(m); | 419 | free(m); |
419 | 420 | ||
420 | return 1; | 421 | return 1; |
421 | } | 422 | } |
422 | 423 |
include/common.h
1 | /* | 1 | /* |
2 | * (C) Copyright 2000-2009 | 2 | * (C) Copyright 2000-2009 |
3 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | 3 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. |
4 | * | 4 | * |
5 | * See file CREDITS for list of people who contributed to this | 5 | * See file CREDITS for list of people who contributed to this |
6 | * project. | 6 | * project. |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU General Public License as | 9 | * modify it under the terms of the GNU General Public License as |
10 | * published by the Free Software Foundation; either version 2 of | 10 | * published by the Free Software Foundation; either version 2 of |
11 | * the License, or (at your option) any later version. | 11 | * the License, or (at your option) any later version. |
12 | * | 12 | * |
13 | * This program is distributed in the hope that it will be useful, | 13 | * This program is distributed in the hope that it will be useful, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | * GNU General Public License for more details. | 16 | * GNU General Public License for more details. |
17 | * | 17 | * |
18 | * You should have received a copy of the GNU General Public License | 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 | 19 | * along with this program; if not, write to the Free Software |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
21 | * MA 02111-1307 USA | 21 | * MA 02111-1307 USA |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #ifndef __COMMON_H_ | 24 | #ifndef __COMMON_H_ |
25 | #define __COMMON_H_ 1 | 25 | #define __COMMON_H_ 1 |
26 | 26 | ||
27 | #undef _LINUX_CONFIG_H | 27 | #undef _LINUX_CONFIG_H |
28 | #define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */ | 28 | #define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */ |
29 | 29 | ||
30 | #ifndef __ASSEMBLY__ /* put C only stuff in this section */ | 30 | #ifndef __ASSEMBLY__ /* put C only stuff in this section */ |
31 | 31 | ||
32 | typedef unsigned char uchar; | 32 | typedef unsigned char uchar; |
33 | typedef volatile unsigned long vu_long; | 33 | typedef volatile unsigned long vu_long; |
34 | typedef volatile unsigned short vu_short; | 34 | typedef volatile unsigned short vu_short; |
35 | typedef volatile unsigned char vu_char; | 35 | typedef volatile unsigned char vu_char; |
36 | 36 | ||
37 | #include <config.h> | 37 | #include <config.h> |
38 | #include <asm-offsets.h> | 38 | #include <asm-offsets.h> |
39 | #include <linux/bitops.h> | 39 | #include <linux/bitops.h> |
40 | #include <linux/types.h> | 40 | #include <linux/types.h> |
41 | #include <linux/string.h> | 41 | #include <linux/string.h> |
42 | #include <asm/ptrace.h> | 42 | #include <asm/ptrace.h> |
43 | #include <stdarg.h> | 43 | #include <stdarg.h> |
44 | #if defined(CONFIG_PCI) && (defined(CONFIG_4xx) && !defined(CONFIG_AP1000)) | 44 | #if defined(CONFIG_PCI) && (defined(CONFIG_4xx) && !defined(CONFIG_AP1000)) |
45 | #include <pci.h> | 45 | #include <pci.h> |
46 | #endif | 46 | #endif |
47 | #if defined(CONFIG_8xx) | 47 | #if defined(CONFIG_8xx) |
48 | #include <asm/8xx_immap.h> | 48 | #include <asm/8xx_immap.h> |
49 | #if defined(CONFIG_MPC852) || defined(CONFIG_MPC852T) || \ | 49 | #if defined(CONFIG_MPC852) || defined(CONFIG_MPC852T) || \ |
50 | defined(CONFIG_MPC859) || defined(CONFIG_MPC859T) || \ | 50 | defined(CONFIG_MPC859) || defined(CONFIG_MPC859T) || \ |
51 | defined(CONFIG_MPC859DSL) || \ | 51 | defined(CONFIG_MPC859DSL) || \ |
52 | defined(CONFIG_MPC866) || defined(CONFIG_MPC866T) || \ | 52 | defined(CONFIG_MPC866) || defined(CONFIG_MPC866T) || \ |
53 | defined(CONFIG_MPC866P) | 53 | defined(CONFIG_MPC866P) |
54 | # define CONFIG_MPC866_FAMILY 1 | 54 | # define CONFIG_MPC866_FAMILY 1 |
55 | #elif defined(CONFIG_MPC870) \ | 55 | #elif defined(CONFIG_MPC870) \ |
56 | || defined(CONFIG_MPC875) \ | 56 | || defined(CONFIG_MPC875) \ |
57 | || defined(CONFIG_MPC880) \ | 57 | || defined(CONFIG_MPC880) \ |
58 | || defined(CONFIG_MPC885) | 58 | || defined(CONFIG_MPC885) |
59 | # define CONFIG_MPC885_FAMILY 1 | 59 | # define CONFIG_MPC885_FAMILY 1 |
60 | #endif | 60 | #endif |
61 | #if defined(CONFIG_MPC860) \ | 61 | #if defined(CONFIG_MPC860) \ |
62 | || defined(CONFIG_MPC860T) \ | 62 | || defined(CONFIG_MPC860T) \ |
63 | || defined(CONFIG_MPC866_FAMILY) \ | 63 | || defined(CONFIG_MPC866_FAMILY) \ |
64 | || defined(CONFIG_MPC885_FAMILY) | 64 | || defined(CONFIG_MPC885_FAMILY) |
65 | # define CONFIG_MPC86x 1 | 65 | # define CONFIG_MPC86x 1 |
66 | #endif | 66 | #endif |
67 | #elif defined(CONFIG_5xx) | 67 | #elif defined(CONFIG_5xx) |
68 | #include <asm/5xx_immap.h> | 68 | #include <asm/5xx_immap.h> |
69 | #elif defined(CONFIG_MPC5xxx) | 69 | #elif defined(CONFIG_MPC5xxx) |
70 | #include <mpc5xxx.h> | 70 | #include <mpc5xxx.h> |
71 | #elif defined(CONFIG_MPC512X) | 71 | #elif defined(CONFIG_MPC512X) |
72 | #include <asm/immap_512x.h> | 72 | #include <asm/immap_512x.h> |
73 | #elif defined(CONFIG_MPC8220) | 73 | #elif defined(CONFIG_MPC8220) |
74 | #include <asm/immap_8220.h> | 74 | #include <asm/immap_8220.h> |
75 | #elif defined(CONFIG_8260) | 75 | #elif defined(CONFIG_8260) |
76 | #if defined(CONFIG_MPC8247) \ | 76 | #if defined(CONFIG_MPC8247) \ |
77 | || defined(CONFIG_MPC8248) \ | 77 | || defined(CONFIG_MPC8248) \ |
78 | || defined(CONFIG_MPC8271) \ | 78 | || defined(CONFIG_MPC8271) \ |
79 | || defined(CONFIG_MPC8272) | 79 | || defined(CONFIG_MPC8272) |
80 | #define CONFIG_MPC8272_FAMILY 1 | 80 | #define CONFIG_MPC8272_FAMILY 1 |
81 | #endif | 81 | #endif |
82 | #if defined(CONFIG_MPC8272_FAMILY) | 82 | #if defined(CONFIG_MPC8272_FAMILY) |
83 | #define CONFIG_MPC8260 1 | 83 | #define CONFIG_MPC8260 1 |
84 | #endif | 84 | #endif |
85 | #include <asm/immap_8260.h> | 85 | #include <asm/immap_8260.h> |
86 | #endif | 86 | #endif |
87 | #ifdef CONFIG_MPC86xx | 87 | #ifdef CONFIG_MPC86xx |
88 | #include <mpc86xx.h> | 88 | #include <mpc86xx.h> |
89 | #include <asm/immap_86xx.h> | 89 | #include <asm/immap_86xx.h> |
90 | #endif | 90 | #endif |
91 | #ifdef CONFIG_MPC85xx | 91 | #ifdef CONFIG_MPC85xx |
92 | #include <mpc85xx.h> | 92 | #include <mpc85xx.h> |
93 | #include <asm/immap_85xx.h> | 93 | #include <asm/immap_85xx.h> |
94 | #endif | 94 | #endif |
95 | #ifdef CONFIG_MPC83xx | 95 | #ifdef CONFIG_MPC83xx |
96 | #include <mpc83xx.h> | 96 | #include <mpc83xx.h> |
97 | #include <asm/immap_83xx.h> | 97 | #include <asm/immap_83xx.h> |
98 | #endif | 98 | #endif |
99 | #ifdef CONFIG_4xx | 99 | #ifdef CONFIG_4xx |
100 | #include <asm/ppc4xx.h> | 100 | #include <asm/ppc4xx.h> |
101 | #endif | 101 | #endif |
102 | #ifdef CONFIG_HYMOD | 102 | #ifdef CONFIG_HYMOD |
103 | #include <board/hymod/hymod.h> | 103 | #include <board/hymod/hymod.h> |
104 | #endif | 104 | #endif |
105 | #ifdef CONFIG_ARM | 105 | #ifdef CONFIG_ARM |
106 | #define asmlinkage /* nothing */ | 106 | #define asmlinkage /* nothing */ |
107 | #endif | 107 | #endif |
108 | #ifdef CONFIG_BLACKFIN | 108 | #ifdef CONFIG_BLACKFIN |
109 | #include <asm/blackfin.h> | 109 | #include <asm/blackfin.h> |
110 | #endif | 110 | #endif |
111 | #ifdef CONFIG_SOC_DA8XX | 111 | #ifdef CONFIG_SOC_DA8XX |
112 | #include <asm/arch/hardware.h> | 112 | #include <asm/arch/hardware.h> |
113 | #endif | 113 | #endif |
114 | 114 | ||
115 | #include <part.h> | 115 | #include <part.h> |
116 | #include <flash.h> | 116 | #include <flash.h> |
117 | #include <image.h> | 117 | #include <image.h> |
118 | 118 | ||
119 | #ifdef DEBUG | 119 | #ifdef DEBUG |
120 | #define _DEBUG 1 | 120 | #define _DEBUG 1 |
121 | #else | 121 | #else |
122 | #define _DEBUG 0 | 122 | #define _DEBUG 0 |
123 | #endif | 123 | #endif |
124 | 124 | ||
125 | /* | 125 | /* |
126 | * Output a debug text when condition "cond" is met. The "cond" should be | 126 | * Output a debug text when condition "cond" is met. The "cond" should be |
127 | * computed by a preprocessor in the best case, allowing for the best | 127 | * computed by a preprocessor in the best case, allowing for the best |
128 | * optimization. | 128 | * optimization. |
129 | */ | 129 | */ |
130 | #define debug_cond(cond, fmt, args...) \ | 130 | #define debug_cond(cond, fmt, args...) \ |
131 | do { \ | 131 | do { \ |
132 | if (cond) \ | 132 | if (cond) \ |
133 | printf(fmt, ##args); \ | 133 | printf(fmt, ##args); \ |
134 | } while (0) | 134 | } while (0) |
135 | 135 | ||
136 | #define debug(fmt, args...) \ | 136 | #define debug(fmt, args...) \ |
137 | debug_cond(_DEBUG, fmt, ##args) | 137 | debug_cond(_DEBUG, fmt, ##args) |
138 | 138 | ||
139 | /* | 139 | /* |
140 | * An assertion is run-time check done in debug mode only. If DEBUG is not | 140 | * An assertion is run-time check done in debug mode only. If DEBUG is not |
141 | * defined then it is skipped. If DEBUG is defined and the assertion fails, | 141 | * defined then it is skipped. If DEBUG is defined and the assertion fails, |
142 | * then it calls panic*( which may or may not reset/halt U-Boot (see | 142 | * then it calls panic*( which may or may not reset/halt U-Boot (see |
143 | * CONFIG_PANIC_HANG), It is hoped that all failing assertions are found | 143 | * CONFIG_PANIC_HANG), It is hoped that all failing assertions are found |
144 | * before release, and after release it is hoped that they don't matter. But | 144 | * before release, and after release it is hoped that they don't matter. But |
145 | * in any case these failing assertions cannot be fixed with a reset (which | 145 | * in any case these failing assertions cannot be fixed with a reset (which |
146 | * may just do the same assertion again). | 146 | * may just do the same assertion again). |
147 | */ | 147 | */ |
148 | void __assert_fail(const char *assertion, const char *file, unsigned line, | 148 | void __assert_fail(const char *assertion, const char *file, unsigned line, |
149 | const char *function); | 149 | const char *function); |
150 | #define assert(x) \ | 150 | #define assert(x) \ |
151 | ({ if (!(x) && _DEBUG) \ | 151 | ({ if (!(x) && _DEBUG) \ |
152 | __assert_fail(#x, __FILE__, __LINE__, __func__); }) | 152 | __assert_fail(#x, __FILE__, __LINE__, __func__); }) |
153 | 153 | ||
154 | #define error(fmt, args...) do { \ | 154 | #define error(fmt, args...) do { \ |
155 | printf("ERROR: " fmt "\nat %s:%d/%s()\n", \ | 155 | printf("ERROR: " fmt "\nat %s:%d/%s()\n", \ |
156 | ##args, __FILE__, __LINE__, __func__); \ | 156 | ##args, __FILE__, __LINE__, __func__); \ |
157 | } while (0) | 157 | } while (0) |
158 | 158 | ||
159 | #ifndef BUG | 159 | #ifndef BUG |
160 | #define BUG() do { \ | 160 | #define BUG() do { \ |
161 | printf("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __FUNCTION__); \ | 161 | printf("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __FUNCTION__); \ |
162 | panic("BUG!"); \ | 162 | panic("BUG!"); \ |
163 | } while (0) | 163 | } while (0) |
164 | #define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0) | 164 | #define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0) |
165 | #endif /* BUG */ | 165 | #endif /* BUG */ |
166 | 166 | ||
167 | /* Force a compilation error if condition is true */ | 167 | /* Force a compilation error if condition is true */ |
168 | #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) | 168 | #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) |
169 | 169 | ||
170 | typedef void (interrupt_handler_t)(void *); | 170 | typedef void (interrupt_handler_t)(void *); |
171 | 171 | ||
172 | #include <asm/u-boot.h> /* boot information for Linux kernel */ | 172 | #include <asm/u-boot.h> /* boot information for Linux kernel */ |
173 | #include <asm/global_data.h> /* global data used for startup functions */ | 173 | #include <asm/global_data.h> /* global data used for startup functions */ |
174 | 174 | ||
175 | /* | 175 | /* |
176 | * enable common handling for all TQM8xxL/M boards: | 176 | * enable common handling for all TQM8xxL/M boards: |
177 | * - CONFIG_TQM8xxM will be defined for all TQM8xxM boards | 177 | * - CONFIG_TQM8xxM will be defined for all TQM8xxM boards |
178 | * - CONFIG_TQM8xxL will be defined for all TQM8xxL _and_ TQM8xxM boards | 178 | * - CONFIG_TQM8xxL will be defined for all TQM8xxL _and_ TQM8xxM boards |
179 | * and for the TQM885D board | 179 | * and for the TQM885D board |
180 | */ | 180 | */ |
181 | #if defined(CONFIG_TQM823M) || defined(CONFIG_TQM850M) || \ | 181 | #if defined(CONFIG_TQM823M) || defined(CONFIG_TQM850M) || \ |
182 | defined(CONFIG_TQM855M) || defined(CONFIG_TQM860M) || \ | 182 | defined(CONFIG_TQM855M) || defined(CONFIG_TQM860M) || \ |
183 | defined(CONFIG_TQM862M) || defined(CONFIG_TQM866M) | 183 | defined(CONFIG_TQM862M) || defined(CONFIG_TQM866M) |
184 | # ifndef CONFIG_TQM8xxM | 184 | # ifndef CONFIG_TQM8xxM |
185 | # define CONFIG_TQM8xxM | 185 | # define CONFIG_TQM8xxM |
186 | # endif | 186 | # endif |
187 | #endif | 187 | #endif |
188 | #if defined(CONFIG_TQM823L) || defined(CONFIG_TQM850L) || \ | 188 | #if defined(CONFIG_TQM823L) || defined(CONFIG_TQM850L) || \ |
189 | defined(CONFIG_TQM855L) || defined(CONFIG_TQM860L) || \ | 189 | defined(CONFIG_TQM855L) || defined(CONFIG_TQM860L) || \ |
190 | defined(CONFIG_TQM862L) || defined(CONFIG_TQM8xxM) || \ | 190 | defined(CONFIG_TQM862L) || defined(CONFIG_TQM8xxM) || \ |
191 | defined(CONFIG_TQM885D) | 191 | defined(CONFIG_TQM885D) |
192 | # ifndef CONFIG_TQM8xxL | 192 | # ifndef CONFIG_TQM8xxL |
193 | # define CONFIG_TQM8xxL | 193 | # define CONFIG_TQM8xxL |
194 | # endif | 194 | # endif |
195 | #endif | 195 | #endif |
196 | 196 | ||
197 | #ifndef CONFIG_SERIAL_MULTI | 197 | #ifndef CONFIG_SERIAL_MULTI |
198 | 198 | ||
199 | #if defined(CONFIG_8xx_CONS_SMC1) || defined(CONFIG_8xx_CONS_SMC2) \ | 199 | #if defined(CONFIG_8xx_CONS_SMC1) || defined(CONFIG_8xx_CONS_SMC2) \ |
200 | || defined(CONFIG_8xx_CONS_SCC1) || defined(CONFIG_8xx_CONS_SCC2) \ | 200 | || defined(CONFIG_8xx_CONS_SCC1) || defined(CONFIG_8xx_CONS_SCC2) \ |
201 | || defined(CONFIG_8xx_CONS_SCC3) || defined(CONFIG_8xx_CONS_SCC4) | 201 | || defined(CONFIG_8xx_CONS_SCC3) || defined(CONFIG_8xx_CONS_SCC4) |
202 | 202 | ||
203 | #define CONFIG_SERIAL_MULTI 1 | 203 | #define CONFIG_SERIAL_MULTI 1 |
204 | 204 | ||
205 | #endif | 205 | #endif |
206 | 206 | ||
207 | #endif /* CONFIG_SERIAL_MULTI */ | 207 | #endif /* CONFIG_SERIAL_MULTI */ |
208 | 208 | ||
209 | /* | 209 | /* |
210 | * General Purpose Utilities | 210 | * General Purpose Utilities |
211 | */ | 211 | */ |
212 | #define min(X, Y) \ | 212 | #define min(X, Y) \ |
213 | ({ typeof (X) __x = (X); \ | 213 | ({ typeof (X) __x = (X); \ |
214 | typeof (Y) __y = (Y); \ | 214 | typeof (Y) __y = (Y); \ |
215 | (__x < __y) ? __x : __y; }) | 215 | (__x < __y) ? __x : __y; }) |
216 | 216 | ||
217 | #define max(X, Y) \ | 217 | #define max(X, Y) \ |
218 | ({ typeof (X) __x = (X); \ | 218 | ({ typeof (X) __x = (X); \ |
219 | typeof (Y) __y = (Y); \ | 219 | typeof (Y) __y = (Y); \ |
220 | (__x > __y) ? __x : __y; }) | 220 | (__x > __y) ? __x : __y; }) |
221 | 221 | ||
222 | #define MIN(x, y) min(x, y) | 222 | #define MIN(x, y) min(x, y) |
223 | #define MAX(x, y) max(x, y) | 223 | #define MAX(x, y) max(x, y) |
224 | 224 | ||
225 | #if defined(CONFIG_ENV_IS_EMBEDDED) | 225 | #if defined(CONFIG_ENV_IS_EMBEDDED) |
226 | #define TOTAL_MALLOC_LEN CONFIG_SYS_MALLOC_LEN | 226 | #define TOTAL_MALLOC_LEN CONFIG_SYS_MALLOC_LEN |
227 | #elif ( ((CONFIG_ENV_ADDR+CONFIG_ENV_SIZE) < CONFIG_SYS_MONITOR_BASE) || \ | 227 | #elif ( ((CONFIG_ENV_ADDR+CONFIG_ENV_SIZE) < CONFIG_SYS_MONITOR_BASE) || \ |
228 | (CONFIG_ENV_ADDR >= (CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN)) ) || \ | 228 | (CONFIG_ENV_ADDR >= (CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN)) ) || \ |
229 | defined(CONFIG_ENV_IS_IN_NVRAM) | 229 | defined(CONFIG_ENV_IS_IN_NVRAM) |
230 | #define TOTAL_MALLOC_LEN (CONFIG_SYS_MALLOC_LEN + CONFIG_ENV_SIZE) | 230 | #define TOTAL_MALLOC_LEN (CONFIG_SYS_MALLOC_LEN + CONFIG_ENV_SIZE) |
231 | #else | 231 | #else |
232 | #define TOTAL_MALLOC_LEN CONFIG_SYS_MALLOC_LEN | 232 | #define TOTAL_MALLOC_LEN CONFIG_SYS_MALLOC_LEN |
233 | #endif | 233 | #endif |
234 | 234 | ||
235 | /** | 235 | /** |
236 | * container_of - cast a member of a structure out to the containing structure | 236 | * container_of - cast a member of a structure out to the containing structure |
237 | * @ptr: the pointer to the member. | 237 | * @ptr: the pointer to the member. |
238 | * @type: the type of the container struct this is embedded in. | 238 | * @type: the type of the container struct this is embedded in. |
239 | * @member: the name of the member within the struct. | 239 | * @member: the name of the member within the struct. |
240 | * | 240 | * |
241 | */ | 241 | */ |
242 | #define container_of(ptr, type, member) ({ \ | 242 | #define container_of(ptr, type, member) ({ \ |
243 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ | 243 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ |
244 | (type *)( (char *)__mptr - offsetof(type,member) );}) | 244 | (type *)( (char *)__mptr - offsetof(type,member) );}) |
245 | 245 | ||
246 | /* | 246 | /* |
247 | * Function Prototypes | 247 | * Function Prototypes |
248 | */ | 248 | */ |
249 | 249 | ||
250 | void hang (void) __attribute__ ((noreturn)); | 250 | void hang (void) __attribute__ ((noreturn)); |
251 | 251 | ||
252 | int timer_init(void); | 252 | int timer_init(void); |
253 | int cpu_init(void); | 253 | int cpu_init(void); |
254 | 254 | ||
255 | /* */ | 255 | /* */ |
256 | phys_size_t initdram (int); | 256 | phys_size_t initdram (int); |
257 | int display_options (void); | 257 | int display_options (void); |
258 | void print_size(unsigned long long, const char *); | 258 | void print_size(unsigned long long, const char *); |
259 | int print_buffer (ulong addr, void* data, uint width, uint count, uint linelen); | 259 | int print_buffer (ulong addr, void* data, uint width, uint count, uint linelen); |
260 | 260 | ||
261 | /* common/main.c */ | 261 | /* common/main.c */ |
262 | void main_loop (void); | 262 | void main_loop (void); |
263 | int run_command (const char *cmd, int flag); | 263 | int run_command (const char *cmd, int flag); |
264 | #ifdef CONFIG_CMD_PXE | 264 | #ifdef CONFIG_CMD_PXE |
265 | int run_command2(const char *cmd, int flag); | 265 | int run_command2(const char *cmd, int flag); |
266 | #endif | 266 | #endif |
267 | int readline (const char *const prompt); | 267 | int readline (const char *const prompt); |
268 | int readline_into_buffer (const char *const prompt, char * buffer); | 268 | int readline_into_buffer(const char *const prompt, char *buffer, |
269 | int timeout); | ||
269 | int parse_line (char *, char *[]); | 270 | int parse_line (char *, char *[]); |
270 | void init_cmd_timeout(void); | 271 | void init_cmd_timeout(void); |
271 | void reset_cmd_timeout(void); | 272 | void reset_cmd_timeout(void); |
272 | #ifdef CONFIG_MENU | 273 | #ifdef CONFIG_MENU |
273 | int abortboot(int bootdelay); | 274 | int abortboot(int bootdelay); |
274 | #endif | 275 | #endif |
275 | extern char console_buffer[]; | 276 | extern char console_buffer[]; |
276 | 277 | ||
277 | /* arch/$(ARCH)/lib/board.c */ | 278 | /* arch/$(ARCH)/lib/board.c */ |
278 | void board_init_f (ulong) __attribute__ ((noreturn)); | 279 | void board_init_f (ulong) __attribute__ ((noreturn)); |
279 | void board_init_r (gd_t *, ulong) __attribute__ ((noreturn)); | 280 | void board_init_r (gd_t *, ulong) __attribute__ ((noreturn)); |
280 | int checkboard (void); | 281 | int checkboard (void); |
281 | int checkflash (void); | 282 | int checkflash (void); |
282 | int checkdram (void); | 283 | int checkdram (void); |
283 | int last_stage_init(void); | 284 | int last_stage_init(void); |
284 | extern ulong monitor_flash_len; | 285 | extern ulong monitor_flash_len; |
285 | int mac_read_from_eeprom(void); | 286 | int mac_read_from_eeprom(void); |
286 | extern u8 _binary_dt_dtb_start[]; /* embedded device tree blob */ | 287 | extern u8 _binary_dt_dtb_start[]; /* embedded device tree blob */ |
287 | 288 | ||
288 | /* | 289 | /* |
289 | * Called when console output is requested before the console is available. | 290 | * Called when console output is requested before the console is available. |
290 | * The board should do its best to get the character out to the user any way | 291 | * The board should do its best to get the character out to the user any way |
291 | * it can. | 292 | * it can. |
292 | */ | 293 | */ |
293 | void board_pre_console_putc(int ch); | 294 | void board_pre_console_putc(int ch); |
294 | 295 | ||
295 | /* common/flash.c */ | 296 | /* common/flash.c */ |
296 | void flash_perror (int); | 297 | void flash_perror (int); |
297 | 298 | ||
298 | /* common/cmd_source.c */ | 299 | /* common/cmd_source.c */ |
299 | int source (ulong addr, const char *fit_uname); | 300 | int source (ulong addr, const char *fit_uname); |
300 | 301 | ||
301 | extern ulong load_addr; /* Default Load Address */ | 302 | extern ulong load_addr; /* Default Load Address */ |
302 | extern ulong save_addr; /* Default Save Address */ | 303 | extern ulong save_addr; /* Default Save Address */ |
303 | extern ulong save_size; /* Default Save Size */ | 304 | extern ulong save_size; /* Default Save Size */ |
304 | 305 | ||
305 | /* common/cmd_doc.c */ | 306 | /* common/cmd_doc.c */ |
306 | void doc_probe(unsigned long physadr); | 307 | void doc_probe(unsigned long physadr); |
307 | 308 | ||
308 | /* common/cmd_net.c */ | 309 | /* common/cmd_net.c */ |
309 | int do_tftpb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); | 310 | int do_tftpb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); |
310 | 311 | ||
311 | /* common/cmd_nvedit.c */ | 312 | /* common/cmd_nvedit.c */ |
312 | int env_init (void); | 313 | int env_init (void); |
313 | void env_relocate (void); | 314 | void env_relocate (void); |
314 | int envmatch (uchar *, int); | 315 | int envmatch (uchar *, int); |
315 | char *getenv (const char *); | 316 | char *getenv (const char *); |
316 | int getenv_f (const char *name, char *buf, unsigned len); | 317 | int getenv_f (const char *name, char *buf, unsigned len); |
317 | ulong getenv_ulong(const char *name, int base, ulong default_val); | 318 | ulong getenv_ulong(const char *name, int base, ulong default_val); |
318 | int saveenv (void); | 319 | int saveenv (void); |
319 | #ifdef CONFIG_PPC /* ARM version to be fixed! */ | 320 | #ifdef CONFIG_PPC /* ARM version to be fixed! */ |
320 | int inline setenv (const char *, const char *); | 321 | int inline setenv (const char *, const char *); |
321 | #else | 322 | #else |
322 | int setenv (const char *, const char *); | 323 | int setenv (const char *, const char *); |
323 | int setenv_ulong(const char *varname, ulong value); | 324 | int setenv_ulong(const char *varname, ulong value); |
324 | int setenv_addr(const char *varname, const void *addr); | 325 | int setenv_addr(const char *varname, const void *addr); |
325 | #endif /* CONFIG_PPC */ | 326 | #endif /* CONFIG_PPC */ |
326 | #ifdef CONFIG_ARM | 327 | #ifdef CONFIG_ARM |
327 | # include <asm/mach-types.h> | 328 | # include <asm/mach-types.h> |
328 | # include <asm/setup.h> | 329 | # include <asm/setup.h> |
329 | # include <asm/u-boot-arm.h> /* ARM version to be fixed! */ | 330 | # include <asm/u-boot-arm.h> /* ARM version to be fixed! */ |
330 | #endif /* CONFIG_ARM */ | 331 | #endif /* CONFIG_ARM */ |
331 | #ifdef CONFIG_X86 /* x86 version to be fixed! */ | 332 | #ifdef CONFIG_X86 /* x86 version to be fixed! */ |
332 | # include <asm/u-boot-x86.h> | 333 | # include <asm/u-boot-x86.h> |
333 | #endif /* CONFIG_X86 */ | 334 | #endif /* CONFIG_X86 */ |
334 | #ifdef CONFIG_SANDBOX | 335 | #ifdef CONFIG_SANDBOX |
335 | # include <asm/u-boot-sandbox.h> /* TODO(sjg) what needs to be fixed? */ | 336 | # include <asm/u-boot-sandbox.h> /* TODO(sjg) what needs to be fixed? */ |
336 | #endif | 337 | #endif |
337 | #ifdef CONFIG_NDS32 | 338 | #ifdef CONFIG_NDS32 |
338 | # include <asm/mach-types.h> | 339 | # include <asm/mach-types.h> |
339 | # include <asm/u-boot-nds32.h> | 340 | # include <asm/u-boot-nds32.h> |
340 | #endif /* CONFIG_NDS32 */ | 341 | #endif /* CONFIG_NDS32 */ |
341 | 342 | ||
342 | #ifdef CONFIG_AUTO_COMPLETE | 343 | #ifdef CONFIG_AUTO_COMPLETE |
343 | int env_complete(char *var, int maxv, char *cmdv[], int maxsz, char *buf); | 344 | int env_complete(char *var, int maxv, char *cmdv[], int maxsz, char *buf); |
344 | #endif | 345 | #endif |
345 | int get_env_id (void); | 346 | int get_env_id (void); |
346 | 347 | ||
347 | void pci_init (void); | 348 | void pci_init (void); |
348 | void pci_init_board(void); | 349 | void pci_init_board(void); |
349 | void pciinfo (int, int); | 350 | void pciinfo (int, int); |
350 | 351 | ||
351 | #if defined(CONFIG_PCI) && (defined(CONFIG_4xx) && !defined(CONFIG_AP1000)) | 352 | #if defined(CONFIG_PCI) && (defined(CONFIG_4xx) && !defined(CONFIG_AP1000)) |
352 | int pci_pre_init (struct pci_controller *); | 353 | int pci_pre_init (struct pci_controller *); |
353 | int is_pci_host (struct pci_controller *); | 354 | int is_pci_host (struct pci_controller *); |
354 | #endif | 355 | #endif |
355 | 356 | ||
356 | #if defined(CONFIG_PCI) && (defined(CONFIG_440) || defined(CONFIG_405EX)) | 357 | #if defined(CONFIG_PCI) && (defined(CONFIG_440) || defined(CONFIG_405EX)) |
357 | # if defined(CONFIG_SYS_PCI_TARGET_INIT) | 358 | # if defined(CONFIG_SYS_PCI_TARGET_INIT) |
358 | void pci_target_init (struct pci_controller *); | 359 | void pci_target_init (struct pci_controller *); |
359 | # endif | 360 | # endif |
360 | # if defined(CONFIG_SYS_PCI_MASTER_INIT) | 361 | # if defined(CONFIG_SYS_PCI_MASTER_INIT) |
361 | void pci_master_init (struct pci_controller *); | 362 | void pci_master_init (struct pci_controller *); |
362 | # endif | 363 | # endif |
363 | #if defined(CONFIG_440SPE) || \ | 364 | #if defined(CONFIG_440SPE) || \ |
364 | defined(CONFIG_460EX) || defined(CONFIG_460GT) || \ | 365 | defined(CONFIG_460EX) || defined(CONFIG_460GT) || \ |
365 | defined(CONFIG_405EX) | 366 | defined(CONFIG_405EX) |
366 | void pcie_setup_hoses(int busno); | 367 | void pcie_setup_hoses(int busno); |
367 | #endif | 368 | #endif |
368 | #endif | 369 | #endif |
369 | 370 | ||
370 | int misc_init_f (void); | 371 | int misc_init_f (void); |
371 | int misc_init_r (void); | 372 | int misc_init_r (void); |
372 | 373 | ||
373 | /* common/exports.c */ | 374 | /* common/exports.c */ |
374 | void jumptable_init(void); | 375 | void jumptable_init(void); |
375 | 376 | ||
376 | /* common/kallsysm.c */ | 377 | /* common/kallsysm.c */ |
377 | const char *symbol_lookup(unsigned long addr, unsigned long *caddr); | 378 | const char *symbol_lookup(unsigned long addr, unsigned long *caddr); |
378 | 379 | ||
379 | /* api/api.c */ | 380 | /* api/api.c */ |
380 | void api_init (void); | 381 | void api_init (void); |
381 | 382 | ||
382 | /* common/memsize.c */ | 383 | /* common/memsize.c */ |
383 | long get_ram_size (long *, long); | 384 | long get_ram_size (long *, long); |
384 | 385 | ||
385 | /* $(BOARD)/$(BOARD).c */ | 386 | /* $(BOARD)/$(BOARD).c */ |
386 | void reset_phy (void); | 387 | void reset_phy (void); |
387 | void fdc_hw_init (void); | 388 | void fdc_hw_init (void); |
388 | 389 | ||
389 | /* $(BOARD)/eeprom.c */ | 390 | /* $(BOARD)/eeprom.c */ |
390 | void eeprom_init (void); | 391 | void eeprom_init (void); |
391 | #ifndef CONFIG_SPI | 392 | #ifndef CONFIG_SPI |
392 | int eeprom_probe (unsigned dev_addr, unsigned offset); | 393 | int eeprom_probe (unsigned dev_addr, unsigned offset); |
393 | #endif | 394 | #endif |
394 | int eeprom_read (unsigned dev_addr, unsigned offset, uchar *buffer, unsigned cnt); | 395 | int eeprom_read (unsigned dev_addr, unsigned offset, uchar *buffer, unsigned cnt); |
395 | int eeprom_write (unsigned dev_addr, unsigned offset, uchar *buffer, unsigned cnt); | 396 | int eeprom_write (unsigned dev_addr, unsigned offset, uchar *buffer, unsigned cnt); |
396 | #ifdef CONFIG_LWMON | 397 | #ifdef CONFIG_LWMON |
397 | extern uchar pic_read (uchar reg); | 398 | extern uchar pic_read (uchar reg); |
398 | extern void pic_write (uchar reg, uchar val); | 399 | extern void pic_write (uchar reg, uchar val); |
399 | #endif | 400 | #endif |
400 | 401 | ||
401 | /* | 402 | /* |
402 | * Set this up regardless of board | 403 | * Set this up regardless of board |
403 | * type, to prevent errors. | 404 | * type, to prevent errors. |
404 | */ | 405 | */ |
405 | #if defined(CONFIG_SPI) || !defined(CONFIG_SYS_I2C_EEPROM_ADDR) | 406 | #if defined(CONFIG_SPI) || !defined(CONFIG_SYS_I2C_EEPROM_ADDR) |
406 | # define CONFIG_SYS_DEF_EEPROM_ADDR 0 | 407 | # define CONFIG_SYS_DEF_EEPROM_ADDR 0 |
407 | #else | 408 | #else |
408 | #if !defined(CONFIG_ENV_EEPROM_IS_ON_I2C) | 409 | #if !defined(CONFIG_ENV_EEPROM_IS_ON_I2C) |
409 | # define CONFIG_SYS_DEF_EEPROM_ADDR CONFIG_SYS_I2C_EEPROM_ADDR | 410 | # define CONFIG_SYS_DEF_EEPROM_ADDR CONFIG_SYS_I2C_EEPROM_ADDR |
410 | #endif | 411 | #endif |
411 | #endif /* CONFIG_SPI || !defined(CONFIG_SYS_I2C_EEPROM_ADDR) */ | 412 | #endif /* CONFIG_SPI || !defined(CONFIG_SYS_I2C_EEPROM_ADDR) */ |
412 | 413 | ||
413 | #if defined(CONFIG_SPI) | 414 | #if defined(CONFIG_SPI) |
414 | extern void spi_init_f (void); | 415 | extern void spi_init_f (void); |
415 | extern void spi_init_r (void); | 416 | extern void spi_init_r (void); |
416 | extern ssize_t spi_read (uchar *, int, uchar *, int); | 417 | extern ssize_t spi_read (uchar *, int, uchar *, int); |
417 | extern ssize_t spi_write (uchar *, int, uchar *, int); | 418 | extern ssize_t spi_write (uchar *, int, uchar *, int); |
418 | #endif | 419 | #endif |
419 | 420 | ||
420 | #ifdef CONFIG_RPXCLASSIC | 421 | #ifdef CONFIG_RPXCLASSIC |
421 | void rpxclassic_init (void); | 422 | void rpxclassic_init (void); |
422 | #endif | 423 | #endif |
423 | 424 | ||
424 | void rpxlite_init (void); | 425 | void rpxlite_init (void); |
425 | 426 | ||
426 | #ifdef CONFIG_MBX | 427 | #ifdef CONFIG_MBX |
427 | /* $(BOARD)/mbx8xx.c */ | 428 | /* $(BOARD)/mbx8xx.c */ |
428 | void mbx_init (void); | 429 | void mbx_init (void); |
429 | void board_serial_init (void); | 430 | void board_serial_init (void); |
430 | void board_ether_init (void); | 431 | void board_ether_init (void); |
431 | #endif | 432 | #endif |
432 | 433 | ||
433 | #ifdef CONFIG_HERMES | 434 | #ifdef CONFIG_HERMES |
434 | /* $(BOARD)/hermes.c */ | 435 | /* $(BOARD)/hermes.c */ |
435 | void hermes_start_lxt980 (int speed); | 436 | void hermes_start_lxt980 (int speed); |
436 | #endif | 437 | #endif |
437 | 438 | ||
438 | #ifdef CONFIG_EVB64260 | 439 | #ifdef CONFIG_EVB64260 |
439 | void evb64260_init(void); | 440 | void evb64260_init(void); |
440 | void debug_led(int, int); | 441 | void debug_led(int, int); |
441 | void display_mem_map(void); | 442 | void display_mem_map(void); |
442 | void perform_soft_reset(void); | 443 | void perform_soft_reset(void); |
443 | #endif | 444 | #endif |
444 | 445 | ||
445 | /* $(BOARD)/$(BOARD).c */ | 446 | /* $(BOARD)/$(BOARD).c */ |
446 | int board_early_init_f (void); | 447 | int board_early_init_f (void); |
447 | int board_late_init (void); | 448 | int board_late_init (void); |
448 | int board_postclk_init (void); /* after clocks/timebase, before env/serial */ | 449 | int board_postclk_init (void); /* after clocks/timebase, before env/serial */ |
449 | int board_early_init_r (void); | 450 | int board_early_init_r (void); |
450 | void board_poweroff (void); | 451 | void board_poweroff (void); |
451 | 452 | ||
452 | #if defined(CONFIG_SYS_DRAM_TEST) | 453 | #if defined(CONFIG_SYS_DRAM_TEST) |
453 | int testdram(void); | 454 | int testdram(void); |
454 | #endif /* CONFIG_SYS_DRAM_TEST */ | 455 | #endif /* CONFIG_SYS_DRAM_TEST */ |
455 | 456 | ||
456 | /* $(CPU)/start.S */ | 457 | /* $(CPU)/start.S */ |
457 | #if defined(CONFIG_5xx) || \ | 458 | #if defined(CONFIG_5xx) || \ |
458 | defined(CONFIG_8xx) | 459 | defined(CONFIG_8xx) |
459 | uint get_immr (uint); | 460 | uint get_immr (uint); |
460 | #endif | 461 | #endif |
461 | uint get_pir (void); | 462 | uint get_pir (void); |
462 | #if defined(CONFIG_MPC5xxx) | 463 | #if defined(CONFIG_MPC5xxx) |
463 | uint get_svr (void); | 464 | uint get_svr (void); |
464 | #endif | 465 | #endif |
465 | uint get_pvr (void); | 466 | uint get_pvr (void); |
466 | uint get_svr (void); | 467 | uint get_svr (void); |
467 | uint rd_ic_cst (void); | 468 | uint rd_ic_cst (void); |
468 | void wr_ic_cst (uint); | 469 | void wr_ic_cst (uint); |
469 | void wr_ic_adr (uint); | 470 | void wr_ic_adr (uint); |
470 | uint rd_dc_cst (void); | 471 | uint rd_dc_cst (void); |
471 | void wr_dc_cst (uint); | 472 | void wr_dc_cst (uint); |
472 | void wr_dc_adr (uint); | 473 | void wr_dc_adr (uint); |
473 | int icache_status (void); | 474 | int icache_status (void); |
474 | void icache_enable (void); | 475 | void icache_enable (void); |
475 | void icache_disable(void); | 476 | void icache_disable(void); |
476 | int dcache_status (void); | 477 | int dcache_status (void); |
477 | void dcache_enable (void); | 478 | void dcache_enable (void); |
478 | void dcache_disable(void); | 479 | void dcache_disable(void); |
479 | void mmu_disable(void); | 480 | void mmu_disable(void); |
480 | void relocate_code (ulong, gd_t *, ulong) __attribute__ ((noreturn)); | 481 | void relocate_code (ulong, gd_t *, ulong) __attribute__ ((noreturn)); |
481 | ulong get_endaddr (void); | 482 | ulong get_endaddr (void); |
482 | void trap_init (ulong); | 483 | void trap_init (ulong); |
483 | #if defined (CONFIG_4xx) || \ | 484 | #if defined (CONFIG_4xx) || \ |
484 | defined (CONFIG_MPC5xxx) || \ | 485 | defined (CONFIG_MPC5xxx) || \ |
485 | defined (CONFIG_74xx_7xx) || \ | 486 | defined (CONFIG_74xx_7xx) || \ |
486 | defined (CONFIG_74x) || \ | 487 | defined (CONFIG_74x) || \ |
487 | defined (CONFIG_75x) || \ | 488 | defined (CONFIG_75x) || \ |
488 | defined (CONFIG_74xx) || \ | 489 | defined (CONFIG_74xx) || \ |
489 | defined (CONFIG_MPC8220) || \ | 490 | defined (CONFIG_MPC8220) || \ |
490 | defined (CONFIG_MPC85xx) || \ | 491 | defined (CONFIG_MPC85xx) || \ |
491 | defined (CONFIG_MPC86xx) || \ | 492 | defined (CONFIG_MPC86xx) || \ |
492 | defined (CONFIG_MPC83xx) | 493 | defined (CONFIG_MPC83xx) |
493 | unsigned char in8(unsigned int); | 494 | unsigned char in8(unsigned int); |
494 | void out8(unsigned int, unsigned char); | 495 | void out8(unsigned int, unsigned char); |
495 | unsigned short in16(unsigned int); | 496 | unsigned short in16(unsigned int); |
496 | unsigned short in16r(unsigned int); | 497 | unsigned short in16r(unsigned int); |
497 | void out16(unsigned int, unsigned short value); | 498 | void out16(unsigned int, unsigned short value); |
498 | void out16r(unsigned int, unsigned short value); | 499 | void out16r(unsigned int, unsigned short value); |
499 | unsigned long in32(unsigned int); | 500 | unsigned long in32(unsigned int); |
500 | unsigned long in32r(unsigned int); | 501 | unsigned long in32r(unsigned int); |
501 | void out32(unsigned int, unsigned long value); | 502 | void out32(unsigned int, unsigned long value); |
502 | void out32r(unsigned int, unsigned long value); | 503 | void out32r(unsigned int, unsigned long value); |
503 | void ppcDcbf(unsigned long value); | 504 | void ppcDcbf(unsigned long value); |
504 | void ppcDcbi(unsigned long value); | 505 | void ppcDcbi(unsigned long value); |
505 | void ppcSync(void); | 506 | void ppcSync(void); |
506 | void ppcDcbz(unsigned long value); | 507 | void ppcDcbz(unsigned long value); |
507 | #endif | 508 | #endif |
508 | #if defined (CONFIG_MICROBLAZE) | 509 | #if defined (CONFIG_MICROBLAZE) |
509 | unsigned short in16(unsigned int); | 510 | unsigned short in16(unsigned int); |
510 | void out16(unsigned int, unsigned short value); | 511 | void out16(unsigned int, unsigned short value); |
511 | #endif | 512 | #endif |
512 | 513 | ||
513 | #if defined (CONFIG_MPC83xx) | 514 | #if defined (CONFIG_MPC83xx) |
514 | void ppcDWload(unsigned int *addr, unsigned int *ret); | 515 | void ppcDWload(unsigned int *addr, unsigned int *ret); |
515 | void ppcDWstore(unsigned int *addr, unsigned int *value); | 516 | void ppcDWstore(unsigned int *addr, unsigned int *value); |
516 | void disable_addr_trans(void); | 517 | void disable_addr_trans(void); |
517 | void enable_addr_trans(void); | 518 | void enable_addr_trans(void); |
518 | #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER) | 519 | #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER) |
519 | void ddr_enable_ecc(unsigned int dram_size); | 520 | void ddr_enable_ecc(unsigned int dram_size); |
520 | #endif | 521 | #endif |
521 | #endif | 522 | #endif |
522 | 523 | ||
523 | /* $(CPU)/cpu.c */ | 524 | /* $(CPU)/cpu.c */ |
524 | static inline int cpumask_next(int cpu, unsigned int mask) | 525 | static inline int cpumask_next(int cpu, unsigned int mask) |
525 | { | 526 | { |
526 | for (cpu++; !((1 << cpu) & mask); cpu++) | 527 | for (cpu++; !((1 << cpu) & mask); cpu++) |
527 | ; | 528 | ; |
528 | 529 | ||
529 | return cpu; | 530 | return cpu; |
530 | } | 531 | } |
531 | 532 | ||
532 | #define for_each_cpu(iter, cpu, num_cpus, mask) \ | 533 | #define for_each_cpu(iter, cpu, num_cpus, mask) \ |
533 | for (iter = 0, cpu = cpumask_next(-1, mask); \ | 534 | for (iter = 0, cpu = cpumask_next(-1, mask); \ |
534 | iter < num_cpus; \ | 535 | iter < num_cpus; \ |
535 | iter++, cpu = cpumask_next(cpu, mask)) \ | 536 | iter++, cpu = cpumask_next(cpu, mask)) \ |
536 | 537 | ||
537 | int cpu_numcores (void); | 538 | int cpu_numcores (void); |
538 | u32 cpu_mask (void); | 539 | u32 cpu_mask (void); |
539 | int is_core_valid (unsigned int); | 540 | int is_core_valid (unsigned int); |
540 | int probecpu (void); | 541 | int probecpu (void); |
541 | int checkcpu (void); | 542 | int checkcpu (void); |
542 | int checkicache (void); | 543 | int checkicache (void); |
543 | int checkdcache (void); | 544 | int checkdcache (void); |
544 | void upmconfig (unsigned int, unsigned int *, unsigned int); | 545 | void upmconfig (unsigned int, unsigned int *, unsigned int); |
545 | ulong get_tbclk (void); | 546 | ulong get_tbclk (void); |
546 | void reset_cpu (ulong addr); | 547 | void reset_cpu (ulong addr); |
547 | #if defined (CONFIG_OF_LIBFDT) && defined (CONFIG_OF_BOARD_SETUP) | 548 | #if defined (CONFIG_OF_LIBFDT) && defined (CONFIG_OF_BOARD_SETUP) |
548 | void ft_cpu_setup(void *blob, bd_t *bd); | 549 | void ft_cpu_setup(void *blob, bd_t *bd); |
549 | #ifdef CONFIG_PCI | 550 | #ifdef CONFIG_PCI |
550 | void ft_pci_setup(void *blob, bd_t *bd); | 551 | void ft_pci_setup(void *blob, bd_t *bd); |
551 | #endif | 552 | #endif |
552 | #endif | 553 | #endif |
553 | 554 | ||
554 | 555 | ||
555 | /* $(CPU)/serial.c */ | 556 | /* $(CPU)/serial.c */ |
556 | int serial_init (void); | 557 | int serial_init (void); |
557 | void serial_setbrg (void); | 558 | void serial_setbrg (void); |
558 | void serial_putc (const char); | 559 | void serial_putc (const char); |
559 | void serial_putc_raw(const char); | 560 | void serial_putc_raw(const char); |
560 | void serial_puts (const char *); | 561 | void serial_puts (const char *); |
561 | int serial_getc (void); | 562 | int serial_getc (void); |
562 | int serial_tstc (void); | 563 | int serial_tstc (void); |
563 | 564 | ||
564 | void _serial_setbrg (const int); | 565 | void _serial_setbrg (const int); |
565 | void _serial_putc (const char, const int); | 566 | void _serial_putc (const char, const int); |
566 | void _serial_putc_raw(const char, const int); | 567 | void _serial_putc_raw(const char, const int); |
567 | void _serial_puts (const char *, const int); | 568 | void _serial_puts (const char *, const int); |
568 | int _serial_getc (const int); | 569 | int _serial_getc (const int); |
569 | int _serial_tstc (const int); | 570 | int _serial_tstc (const int); |
570 | 571 | ||
571 | /* $(CPU)/speed.c */ | 572 | /* $(CPU)/speed.c */ |
572 | int get_clocks (void); | 573 | int get_clocks (void); |
573 | int get_clocks_866 (void); | 574 | int get_clocks_866 (void); |
574 | int sdram_adjust_866 (void); | 575 | int sdram_adjust_866 (void); |
575 | int adjust_sdram_tbs_8xx (void); | 576 | int adjust_sdram_tbs_8xx (void); |
576 | #if defined(CONFIG_8260) | 577 | #if defined(CONFIG_8260) |
577 | int prt_8260_clks (void); | 578 | int prt_8260_clks (void); |
578 | #elif defined(CONFIG_MPC5xxx) | 579 | #elif defined(CONFIG_MPC5xxx) |
579 | int prt_mpc5xxx_clks (void); | 580 | int prt_mpc5xxx_clks (void); |
580 | #endif | 581 | #endif |
581 | #if defined(CONFIG_MPC512X) | 582 | #if defined(CONFIG_MPC512X) |
582 | int prt_mpc512xxx_clks (void); | 583 | int prt_mpc512xxx_clks (void); |
583 | #endif | 584 | #endif |
584 | #if defined(CONFIG_MPC8220) | 585 | #if defined(CONFIG_MPC8220) |
585 | int prt_mpc8220_clks (void); | 586 | int prt_mpc8220_clks (void); |
586 | #endif | 587 | #endif |
587 | #ifdef CONFIG_4xx | 588 | #ifdef CONFIG_4xx |
588 | ulong get_OPB_freq (void); | 589 | ulong get_OPB_freq (void); |
589 | ulong get_PCI_freq (void); | 590 | ulong get_PCI_freq (void); |
590 | #endif | 591 | #endif |
591 | #if defined(CONFIG_S3C24X0) || \ | 592 | #if defined(CONFIG_S3C24X0) || \ |
592 | defined(CONFIG_LH7A40X) || \ | 593 | defined(CONFIG_LH7A40X) || \ |
593 | defined(CONFIG_S3C6400) || \ | 594 | defined(CONFIG_S3C6400) || \ |
594 | defined(CONFIG_EP93XX) | 595 | defined(CONFIG_EP93XX) |
595 | ulong get_FCLK (void); | 596 | ulong get_FCLK (void); |
596 | ulong get_HCLK (void); | 597 | ulong get_HCLK (void); |
597 | ulong get_PCLK (void); | 598 | ulong get_PCLK (void); |
598 | ulong get_UCLK (void); | 599 | ulong get_UCLK (void); |
599 | #endif | 600 | #endif |
600 | #if defined(CONFIG_LH7A40X) | 601 | #if defined(CONFIG_LH7A40X) |
601 | ulong get_PLLCLK (void); | 602 | ulong get_PLLCLK (void); |
602 | #endif | 603 | #endif |
603 | #if defined CONFIG_INCA_IP | 604 | #if defined CONFIG_INCA_IP |
604 | uint incaip_get_cpuclk (void); | 605 | uint incaip_get_cpuclk (void); |
605 | #endif | 606 | #endif |
606 | #if defined(CONFIG_IMX) | 607 | #if defined(CONFIG_IMX) |
607 | ulong get_systemPLLCLK(void); | 608 | ulong get_systemPLLCLK(void); |
608 | ulong get_FCLK(void); | 609 | ulong get_FCLK(void); |
609 | ulong get_HCLK(void); | 610 | ulong get_HCLK(void); |
610 | ulong get_BCLK(void); | 611 | ulong get_BCLK(void); |
611 | ulong get_PERCLK1(void); | 612 | ulong get_PERCLK1(void); |
612 | ulong get_PERCLK2(void); | 613 | ulong get_PERCLK2(void); |
613 | ulong get_PERCLK3(void); | 614 | ulong get_PERCLK3(void); |
614 | #endif | 615 | #endif |
615 | ulong get_bus_freq (ulong); | 616 | ulong get_bus_freq (ulong); |
616 | int get_serial_clock(void); | 617 | int get_serial_clock(void); |
617 | 618 | ||
618 | #if defined(CONFIG_MPC83xx) || defined(CONFIG_MPC85xx) | 619 | #if defined(CONFIG_MPC83xx) || defined(CONFIG_MPC85xx) |
619 | ulong get_ddr_freq(ulong); | 620 | ulong get_ddr_freq(ulong); |
620 | #endif | 621 | #endif |
621 | #if defined(CONFIG_MPC85xx) | 622 | #if defined(CONFIG_MPC85xx) |
622 | typedef MPC85xx_SYS_INFO sys_info_t; | 623 | typedef MPC85xx_SYS_INFO sys_info_t; |
623 | void get_sys_info ( sys_info_t * ); | 624 | void get_sys_info ( sys_info_t * ); |
624 | #endif | 625 | #endif |
625 | #if defined(CONFIG_MPC86xx) | 626 | #if defined(CONFIG_MPC86xx) |
626 | typedef MPC86xx_SYS_INFO sys_info_t; | 627 | typedef MPC86xx_SYS_INFO sys_info_t; |
627 | void get_sys_info ( sys_info_t * ); | 628 | void get_sys_info ( sys_info_t * ); |
628 | static inline ulong get_ddr_freq(ulong dummy) | 629 | static inline ulong get_ddr_freq(ulong dummy) |
629 | { | 630 | { |
630 | return get_bus_freq(dummy); | 631 | return get_bus_freq(dummy); |
631 | } | 632 | } |
632 | #endif | 633 | #endif |
633 | 634 | ||
634 | #if defined(CONFIG_4xx) || defined(CONFIG_IOP480) | 635 | #if defined(CONFIG_4xx) || defined(CONFIG_IOP480) |
635 | # if defined(CONFIG_440) | 636 | # if defined(CONFIG_440) |
636 | # if defined(CONFIG_440SPE) | 637 | # if defined(CONFIG_440SPE) |
637 | unsigned long determine_sysper(void); | 638 | unsigned long determine_sysper(void); |
638 | unsigned long determine_pci_clock_per(void); | 639 | unsigned long determine_pci_clock_per(void); |
639 | # endif | 640 | # endif |
640 | # endif | 641 | # endif |
641 | typedef PPC4xx_SYS_INFO sys_info_t; | 642 | typedef PPC4xx_SYS_INFO sys_info_t; |
642 | int ppc440spe_revB(void); | 643 | int ppc440spe_revB(void); |
643 | void get_sys_info ( sys_info_t * ); | 644 | void get_sys_info ( sys_info_t * ); |
644 | #endif | 645 | #endif |
645 | 646 | ||
646 | /* $(CPU)/cpu_init.c */ | 647 | /* $(CPU)/cpu_init.c */ |
647 | #if defined(CONFIG_8xx) || defined(CONFIG_8260) | 648 | #if defined(CONFIG_8xx) || defined(CONFIG_8260) |
648 | void cpu_init_f (volatile immap_t *immr); | 649 | void cpu_init_f (volatile immap_t *immr); |
649 | #endif | 650 | #endif |
650 | #if defined(CONFIG_4xx) || defined(CONFIG_MPC85xx) || defined(CONFIG_MCF52x2) ||defined(CONFIG_MPC86xx) | 651 | #if defined(CONFIG_4xx) || defined(CONFIG_MPC85xx) || defined(CONFIG_MCF52x2) ||defined(CONFIG_MPC86xx) |
651 | void cpu_init_f (void); | 652 | void cpu_init_f (void); |
652 | #endif | 653 | #endif |
653 | 654 | ||
654 | int cpu_init_r (void); | 655 | int cpu_init_r (void); |
655 | #if defined(CONFIG_8260) | 656 | #if defined(CONFIG_8260) |
656 | int prt_8260_rsr (void); | 657 | int prt_8260_rsr (void); |
657 | #elif defined(CONFIG_MPC83xx) | 658 | #elif defined(CONFIG_MPC83xx) |
658 | int prt_83xx_rsr (void); | 659 | int prt_83xx_rsr (void); |
659 | #endif | 660 | #endif |
660 | 661 | ||
661 | /* $(CPU)/interrupts.c */ | 662 | /* $(CPU)/interrupts.c */ |
662 | int interrupt_init (void); | 663 | int interrupt_init (void); |
663 | void timer_interrupt (struct pt_regs *); | 664 | void timer_interrupt (struct pt_regs *); |
664 | void external_interrupt (struct pt_regs *); | 665 | void external_interrupt (struct pt_regs *); |
665 | void irq_install_handler(int, interrupt_handler_t *, void *); | 666 | void irq_install_handler(int, interrupt_handler_t *, void *); |
666 | void irq_free_handler (int); | 667 | void irq_free_handler (int); |
667 | void reset_timer (void); | 668 | void reset_timer (void); |
668 | ulong get_timer (ulong base); | 669 | ulong get_timer (ulong base); |
669 | void enable_interrupts (void); | 670 | void enable_interrupts (void); |
670 | int disable_interrupts (void); | 671 | int disable_interrupts (void); |
671 | 672 | ||
672 | /* $(CPU)/.../commproc.c */ | 673 | /* $(CPU)/.../commproc.c */ |
673 | int dpram_init (void); | 674 | int dpram_init (void); |
674 | uint dpram_base(void); | 675 | uint dpram_base(void); |
675 | uint dpram_base_align(uint align); | 676 | uint dpram_base_align(uint align); |
676 | uint dpram_alloc(uint size); | 677 | uint dpram_alloc(uint size); |
677 | uint dpram_alloc_align(uint size,uint align); | 678 | uint dpram_alloc_align(uint size,uint align); |
678 | void bootcount_store (ulong); | 679 | void bootcount_store (ulong); |
679 | ulong bootcount_load (void); | 680 | ulong bootcount_load (void); |
680 | #define BOOTCOUNT_MAGIC 0xB001C041 | 681 | #define BOOTCOUNT_MAGIC 0xB001C041 |
681 | 682 | ||
682 | /* $(CPU)/.../<eth> */ | 683 | /* $(CPU)/.../<eth> */ |
683 | void mii_init (void); | 684 | void mii_init (void); |
684 | 685 | ||
685 | /* $(CPU)/.../lcd.c */ | 686 | /* $(CPU)/.../lcd.c */ |
686 | ulong lcd_setmem (ulong); | 687 | ulong lcd_setmem (ulong); |
687 | 688 | ||
688 | /* $(CPU)/.../video.c */ | 689 | /* $(CPU)/.../video.c */ |
689 | ulong video_setmem (ulong); | 690 | ulong video_setmem (ulong); |
690 | 691 | ||
691 | /* arch/$(ARCH)/lib/cache.c */ | 692 | /* arch/$(ARCH)/lib/cache.c */ |
692 | void enable_caches(void); | 693 | void enable_caches(void); |
693 | void flush_cache (unsigned long, unsigned long); | 694 | void flush_cache (unsigned long, unsigned long); |
694 | void flush_dcache_all(void); | 695 | void flush_dcache_all(void); |
695 | void flush_dcache_range(unsigned long start, unsigned long stop); | 696 | void flush_dcache_range(unsigned long start, unsigned long stop); |
696 | void invalidate_dcache_range(unsigned long start, unsigned long stop); | 697 | void invalidate_dcache_range(unsigned long start, unsigned long stop); |
697 | void invalidate_dcache_all(void); | 698 | void invalidate_dcache_all(void); |
698 | void invalidate_icache_all(void); | 699 | void invalidate_icache_all(void); |
699 | 700 | ||
700 | /* arch/$(ARCH)/lib/ticks.S */ | 701 | /* arch/$(ARCH)/lib/ticks.S */ |
701 | unsigned long long get_ticks(void); | 702 | unsigned long long get_ticks(void); |
702 | void wait_ticks (unsigned long); | 703 | void wait_ticks (unsigned long); |
703 | 704 | ||
704 | /* arch/$(ARCH)/lib/time.c */ | 705 | /* arch/$(ARCH)/lib/time.c */ |
705 | void __udelay (unsigned long); | 706 | void __udelay (unsigned long); |
706 | ulong usec2ticks (unsigned long usec); | 707 | ulong usec2ticks (unsigned long usec); |
707 | ulong ticks2usec (unsigned long ticks); | 708 | ulong ticks2usec (unsigned long ticks); |
708 | int init_timebase (void); | 709 | int init_timebase (void); |
709 | 710 | ||
710 | /* lib/gunzip.c */ | 711 | /* lib/gunzip.c */ |
711 | int gunzip(void *, int, unsigned char *, unsigned long *); | 712 | int gunzip(void *, int, unsigned char *, unsigned long *); |
712 | int zunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp, | 713 | int zunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp, |
713 | int stoponerr, int offset); | 714 | int stoponerr, int offset); |
714 | 715 | ||
715 | /* lib/net_utils.c */ | 716 | /* lib/net_utils.c */ |
716 | #include <net.h> | 717 | #include <net.h> |
717 | static inline IPaddr_t getenv_IPaddr (char *var) | 718 | static inline IPaddr_t getenv_IPaddr (char *var) |
718 | { | 719 | { |
719 | return (string_to_ip(getenv(var))); | 720 | return (string_to_ip(getenv(var))); |
720 | } | 721 | } |
721 | 722 | ||
722 | /* lib/qsort.c */ | 723 | /* lib/qsort.c */ |
723 | void qsort(void *base, size_t nmemb, size_t size, | 724 | void qsort(void *base, size_t nmemb, size_t size, |
724 | int(*compar)(const void *, const void *)); | 725 | int(*compar)(const void *, const void *)); |
725 | int strcmp_compar(const void *, const void *); | 726 | int strcmp_compar(const void *, const void *); |
726 | 727 | ||
727 | /* lib/time.c */ | 728 | /* lib/time.c */ |
728 | void udelay (unsigned long); | 729 | void udelay (unsigned long); |
729 | void mdelay(unsigned long); | 730 | void mdelay(unsigned long); |
730 | 731 | ||
731 | /* lib/uuid.c */ | 732 | /* lib/uuid.c */ |
732 | void uuid_str_to_bin(const char *uuid, unsigned char *out); | 733 | void uuid_str_to_bin(const char *uuid, unsigned char *out); |
733 | int uuid_str_valid(const char *uuid); | 734 | int uuid_str_valid(const char *uuid); |
734 | 735 | ||
735 | /* lib/vsprintf.c */ | 736 | /* lib/vsprintf.c */ |
736 | #include <vsprintf.h> | 737 | #include <vsprintf.h> |
737 | 738 | ||
738 | /* lib/strmhz.c */ | 739 | /* lib/strmhz.c */ |
739 | char * strmhz(char *buf, unsigned long hz); | 740 | char * strmhz(char *buf, unsigned long hz); |
740 | 741 | ||
741 | /* lib/crc32.c */ | 742 | /* lib/crc32.c */ |
742 | #include <u-boot/crc.h> | 743 | #include <u-boot/crc.h> |
743 | 744 | ||
744 | /* common/console.c */ | 745 | /* common/console.c */ |
745 | int console_init_f(void); /* Before relocation; uses the serial stuff */ | 746 | int console_init_f(void); /* Before relocation; uses the serial stuff */ |
746 | int console_init_r(void); /* After relocation; uses the console stuff */ | 747 | int console_init_r(void); /* After relocation; uses the console stuff */ |
747 | int console_assign(int file, const char *devname); /* Assign the console */ | 748 | int console_assign(int file, const char *devname); /* Assign the console */ |
748 | int ctrlc (void); | 749 | int ctrlc (void); |
749 | int had_ctrlc (void); /* have we had a Control-C since last clear? */ | 750 | int had_ctrlc (void); /* have we had a Control-C since last clear? */ |
750 | void clear_ctrlc (void); /* clear the Control-C condition */ | 751 | void clear_ctrlc (void); /* clear the Control-C condition */ |
751 | int disable_ctrlc (int); /* 1 to disable, 0 to enable Control-C detect */ | 752 | int disable_ctrlc (int); /* 1 to disable, 0 to enable Control-C detect */ |
752 | 753 | ||
753 | /* | 754 | /* |
754 | * STDIO based functions (can always be used) | 755 | * STDIO based functions (can always be used) |
755 | */ | 756 | */ |
756 | /* serial stuff */ | 757 | /* serial stuff */ |
757 | int serial_printf (const char *fmt, ...) | 758 | int serial_printf (const char *fmt, ...) |
758 | __attribute__ ((format (__printf__, 1, 2))); | 759 | __attribute__ ((format (__printf__, 1, 2))); |
759 | /* stdin */ | 760 | /* stdin */ |
760 | int getc(void); | 761 | int getc(void); |
761 | int tstc(void); | 762 | int tstc(void); |
762 | 763 | ||
763 | /* stdout */ | 764 | /* stdout */ |
764 | void putc(const char c); | 765 | void putc(const char c); |
765 | void puts(const char *s); | 766 | void puts(const char *s); |
766 | int printf(const char *fmt, ...) | 767 | int printf(const char *fmt, ...) |
767 | __attribute__ ((format (__printf__, 1, 2))); | 768 | __attribute__ ((format (__printf__, 1, 2))); |
768 | int vprintf(const char *fmt, va_list args); | 769 | int vprintf(const char *fmt, va_list args); |
769 | 770 | ||
770 | /* stderr */ | 771 | /* stderr */ |
771 | #define eputc(c) fputc(stderr, c) | 772 | #define eputc(c) fputc(stderr, c) |
772 | #define eputs(s) fputs(stderr, s) | 773 | #define eputs(s) fputs(stderr, s) |
773 | #define eprintf(fmt,args...) fprintf(stderr,fmt ,##args) | 774 | #define eprintf(fmt,args...) fprintf(stderr,fmt ,##args) |
774 | 775 | ||
775 | /* | 776 | /* |
776 | * FILE based functions (can only be used AFTER relocation!) | 777 | * FILE based functions (can only be used AFTER relocation!) |
777 | */ | 778 | */ |
778 | #define stdin 0 | 779 | #define stdin 0 |
779 | #define stdout 1 | 780 | #define stdout 1 |
780 | #define stderr 2 | 781 | #define stderr 2 |
781 | #define MAX_FILES 3 | 782 | #define MAX_FILES 3 |
782 | 783 | ||
783 | int fprintf(int file, const char *fmt, ...) | 784 | int fprintf(int file, const char *fmt, ...) |
784 | __attribute__ ((format (__printf__, 2, 3))); | 785 | __attribute__ ((format (__printf__, 2, 3))); |
785 | void fputs(int file, const char *s); | 786 | void fputs(int file, const char *s); |
786 | void fputc(int file, const char c); | 787 | void fputc(int file, const char c); |
787 | int ftstc(int file); | 788 | int ftstc(int file); |
788 | int fgetc(int file); | 789 | int fgetc(int file); |
789 | 790 | ||
790 | /* | 791 | /* |
791 | * CONSOLE multiplexing. | 792 | * CONSOLE multiplexing. |
792 | */ | 793 | */ |
793 | #ifdef CONFIG_CONSOLE_MUX | 794 | #ifdef CONFIG_CONSOLE_MUX |
794 | #include <iomux.h> | 795 | #include <iomux.h> |
795 | #endif | 796 | #endif |
796 | 797 | ||
797 | int pcmcia_init (void); | 798 | int pcmcia_init (void); |
798 | 799 | ||
799 | #ifdef CONFIG_STATUS_LED | 800 | #ifdef CONFIG_STATUS_LED |
800 | # include <status_led.h> | 801 | # include <status_led.h> |
801 | #endif | 802 | #endif |
802 | /* | 803 | /* |
803 | * Board-specific Platform code can reimplement show_boot_progress () if needed | 804 | * Board-specific Platform code can reimplement show_boot_progress () if needed |
804 | */ | 805 | */ |
805 | void show_boot_progress(int val); | 806 | void show_boot_progress(int val); |
806 | 807 | ||
807 | /* Multicore arch functions */ | 808 | /* Multicore arch functions */ |
808 | #ifdef CONFIG_MP | 809 | #ifdef CONFIG_MP |
809 | int cpu_status(int nr); | 810 | int cpu_status(int nr); |
810 | int cpu_reset(int nr); | 811 | int cpu_reset(int nr); |
811 | int cpu_disable(int nr); | 812 | int cpu_disable(int nr); |
812 | int cpu_release(int nr, int argc, char * const argv[]); | 813 | int cpu_release(int nr, int argc, char * const argv[]); |
813 | #endif | 814 | #endif |
814 | 815 | ||
815 | #endif /* __ASSEMBLY__ */ | 816 | #endif /* __ASSEMBLY__ */ |
816 | 817 | ||
817 | #ifdef CONFIG_PPC | 818 | #ifdef CONFIG_PPC |
818 | /* | 819 | /* |
819 | * Has to be included outside of the #ifndef __ASSEMBLY__ section. | 820 | * Has to be included outside of the #ifndef __ASSEMBLY__ section. |
820 | * Otherwise might lead to compilation errors in assembler files. | 821 | * Otherwise might lead to compilation errors in assembler files. |
821 | */ | 822 | */ |
822 | #include <asm/cache.h> | 823 | #include <asm/cache.h> |
823 | #endif | 824 | #endif |
824 | 825 | ||
825 | /* Put only stuff here that the assembler can digest */ | 826 | /* Put only stuff here that the assembler can digest */ |
826 | 827 | ||
827 | #ifdef CONFIG_POST | 828 | #ifdef CONFIG_POST |
828 | #define CONFIG_HAS_POST | 829 | #define CONFIG_HAS_POST |
829 | #ifndef CONFIG_POST_ALT_LIST | 830 | #ifndef CONFIG_POST_ALT_LIST |
830 | #define CONFIG_POST_STD_LIST | 831 | #define CONFIG_POST_STD_LIST |
831 | #endif | 832 | #endif |
832 | #endif | 833 | #endif |
833 | 834 | ||
834 | #ifdef CONFIG_INIT_CRITICAL | 835 | #ifdef CONFIG_INIT_CRITICAL |
835 | #error CONFIG_INIT_CRITICAL is deprecated! | 836 | #error CONFIG_INIT_CRITICAL is deprecated! |
836 | #error Read section CONFIG_SKIP_LOWLEVEL_INIT in README. | 837 | #error Read section CONFIG_SKIP_LOWLEVEL_INIT in README. |
837 | #endif | 838 | #endif |
838 | 839 | ||
839 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) | 840 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) |
840 | 841 | ||
841 | #define ROUND(a,b) (((a) + (b) - 1) & ~((b) - 1)) | 842 | #define ROUND(a,b) (((a) + (b) - 1) & ~((b) - 1)) |
842 | #define DIV_ROUND(n,d) (((n) + ((d)/2)) / (d)) | 843 | #define DIV_ROUND(n,d) (((n) + ((d)/2)) / (d)) |
843 | #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) | 844 | #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) |
844 | #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) | 845 | #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) |
845 | 846 | ||
846 | #define ALIGN(x,a) __ALIGN_MASK((x),(typeof(x))(a)-1) | 847 | #define ALIGN(x,a) __ALIGN_MASK((x),(typeof(x))(a)-1) |
847 | #define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) | 848 | #define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) |
848 | 849 | ||
849 | /* | 850 | /* |
850 | * ARCH_DMA_MINALIGN is defined in asm/cache.h for each architecture. It | 851 | * ARCH_DMA_MINALIGN is defined in asm/cache.h for each architecture. It |
851 | * is used to align DMA buffers. | 852 | * is used to align DMA buffers. |
852 | */ | 853 | */ |
853 | #ifndef __ASSEMBLY__ | 854 | #ifndef __ASSEMBLY__ |
854 | #include <asm/cache.h> | 855 | #include <asm/cache.h> |
855 | #endif | 856 | #endif |
856 | 857 | ||
857 | /* | 858 | /* |
858 | * The ALLOC_CACHE_ALIGN_BUFFER macro is used to allocate a buffer on the | 859 | * The ALLOC_CACHE_ALIGN_BUFFER macro is used to allocate a buffer on the |
859 | * stack that meets the minimum architecture alignment requirements for DMA. | 860 | * stack that meets the minimum architecture alignment requirements for DMA. |
860 | * Such a buffer is useful for DMA operations where flushing and invalidating | 861 | * Such a buffer is useful for DMA operations where flushing and invalidating |
861 | * the cache before and after a read and/or write operation is required for | 862 | * the cache before and after a read and/or write operation is required for |
862 | * correct operations. | 863 | * correct operations. |
863 | * | 864 | * |
864 | * When called the macro creates an array on the stack that is sized such | 865 | * When called the macro creates an array on the stack that is sized such |
865 | * that: | 866 | * that: |
866 | * | 867 | * |
867 | * 1) The beginning of the array can be advanced enough to be aligned. | 868 | * 1) The beginning of the array can be advanced enough to be aligned. |
868 | * | 869 | * |
869 | * 2) The size of the aligned portion of the array is a multiple of the minimum | 870 | * 2) The size of the aligned portion of the array is a multiple of the minimum |
870 | * architecture alignment required for DMA. | 871 | * architecture alignment required for DMA. |
871 | * | 872 | * |
872 | * 3) The aligned portion contains enough space for the original number of | 873 | * 3) The aligned portion contains enough space for the original number of |
873 | * elements requested. | 874 | * elements requested. |
874 | * | 875 | * |
875 | * The macro then creates a pointer to the aligned portion of this array and | 876 | * The macro then creates a pointer to the aligned portion of this array and |
876 | * assigns to the pointer the address of the first element in the aligned | 877 | * assigns to the pointer the address of the first element in the aligned |
877 | * portion of the array. | 878 | * portion of the array. |
878 | * | 879 | * |
879 | * Calling the macro as: | 880 | * Calling the macro as: |
880 | * | 881 | * |
881 | * ALLOC_CACHE_ALIGN_BUFFER(uint32_t, buffer, 1024); | 882 | * ALLOC_CACHE_ALIGN_BUFFER(uint32_t, buffer, 1024); |
882 | * | 883 | * |
883 | * Will result in something similar to saying: | 884 | * Will result in something similar to saying: |
884 | * | 885 | * |
885 | * uint32_t buffer[1024]; | 886 | * uint32_t buffer[1024]; |
886 | * | 887 | * |
887 | * The following differences exist: | 888 | * The following differences exist: |
888 | * | 889 | * |
889 | * 1) The resulting buffer is guaranteed to be aligned to the value of | 890 | * 1) The resulting buffer is guaranteed to be aligned to the value of |
890 | * ARCH_DMA_MINALIGN. | 891 | * ARCH_DMA_MINALIGN. |
891 | * | 892 | * |
892 | * 2) The buffer variable created by the macro is a pointer to the specified | 893 | * 2) The buffer variable created by the macro is a pointer to the specified |
893 | * type, and NOT an array of the specified type. This can be very important | 894 | * type, and NOT an array of the specified type. This can be very important |
894 | * if you want the address of the buffer, which you probably do, to pass it | 895 | * if you want the address of the buffer, which you probably do, to pass it |
895 | * to the DMA hardware. The value of &buffer is different in the two cases. | 896 | * to the DMA hardware. The value of &buffer is different in the two cases. |
896 | * In the macro case it will be the address of the pointer, not the address | 897 | * In the macro case it will be the address of the pointer, not the address |
897 | * of the space reserved for the buffer. However, in the second case it | 898 | * of the space reserved for the buffer. However, in the second case it |
898 | * would be the address of the buffer. So if you are replacing hard coded | 899 | * would be the address of the buffer. So if you are replacing hard coded |
899 | * stack buffers with this macro you need to make sure you remove the & from | 900 | * stack buffers with this macro you need to make sure you remove the & from |
900 | * the locations where you are taking the address of the buffer. | 901 | * the locations where you are taking the address of the buffer. |
901 | * | 902 | * |
902 | * Note that the size parameter is the number of array elements to allocate, | 903 | * Note that the size parameter is the number of array elements to allocate, |
903 | * not the number of bytes. | 904 | * not the number of bytes. |
904 | * | 905 | * |
905 | * This macro can not be used outside of function scope, or for the creation | 906 | * This macro can not be used outside of function scope, or for the creation |
906 | * of a function scoped static buffer. It can not be used to create a cache | 907 | * of a function scoped static buffer. It can not be used to create a cache |
907 | * line aligned global buffer. | 908 | * line aligned global buffer. |
908 | */ | 909 | */ |
909 | #define ALLOC_CACHE_ALIGN_BUFFER(type, name, size) \ | 910 | #define ALLOC_CACHE_ALIGN_BUFFER(type, name, size) \ |
910 | char __##name[ROUND(size * sizeof(type), ARCH_DMA_MINALIGN) + \ | 911 | char __##name[ROUND(size * sizeof(type), ARCH_DMA_MINALIGN) + \ |
911 | ARCH_DMA_MINALIGN - 1]; \ | 912 | ARCH_DMA_MINALIGN - 1]; \ |
912 | \ | 913 | \ |
913 | type *name = (type *) ALIGN((uintptr_t)__##name, ARCH_DMA_MINALIGN) | 914 | type *name = (type *) ALIGN((uintptr_t)__##name, ARCH_DMA_MINALIGN) |
914 | 915 | ||
915 | /* Pull in stuff for the build system */ | 916 | /* Pull in stuff for the build system */ |
916 | #ifdef DO_DEPS_ONLY | 917 | #ifdef DO_DEPS_ONLY |
917 | # include <environment.h> | 918 | # include <environment.h> |
918 | #endif | 919 | #endif |
919 | 920 | ||
920 | #endif /* __COMMON_H_ */ | 921 | #endif /* __COMMON_H_ */ |
921 | 922 |