comparison packages/redboot/current/src/main.c @ 130:eb9fd8c04db3 ecos-sw-2000-10-23

Merge from eCos master repository on 2000-10-23-17:01:37-BST
author jlarmour
date Mon, 23 Oct 2000 17:10:57 +0000
parents 0c2b7be0d798
children 0ae0bc38e387
comparison
equal deleted inserted replaced
129:605a0fc6f385 130:eb9fd8c04db3
53 #include <cyg/hal/hal_tables.h> 53 #include <cyg/hal/hal_tables.h>
54 54
55 // GDB interfaces 55 // GDB interfaces
56 extern void breakpoint(void); 56 extern void breakpoint(void);
57 57
58 // Internal functions
59 static struct cmd *parse(char *line, int *argc, char **argv);
60
61 // CLI command processing (defined in this file) 58 // CLI command processing (defined in this file)
62 RedBoot_cmd("help", 59 RedBoot_cmd("help",
63 "Help about help?", 60 "Help about help?",
64 "<topic>", 61 "<topic>",
65 do_help 62 do_help
69 "[-w <timeout>] [entry]", 66 "[-w <timeout>] [entry]",
70 do_go 67 do_go
71 ); 68 );
72 RedBoot_cmd("dump", 69 RedBoot_cmd("dump",
73 "Display (hex dump) a range of memory", 70 "Display (hex dump) a range of memory",
74 "<location> [<length>]", 71 "-b <location> [-l <length>]",
75 do_dump 72 do_dump
76 ); 73 );
77 RedBoot_cmd("cache", 74 RedBoot_cmd("cache",
78 "Manage machine caches", 75 "Manage machine caches",
79 "[ON | OFF]", 76 "[ON | OFF]",
80 do_caches 77 do_caches
81 ); 78 );
82 79
83 // Define table boundaries 80 // Define table boundaries
81 CYG_HAL_TABLE_BEGIN( __RedBoot_INIT_TAB__, RedBoot_inits );
82 CYG_HAL_TABLE_END( __RedBoot_INIT_TAB_END__, RedBoot_inits );
83 extern struct init_tab_entry __RedBoot_INIT_TAB__[], __RedBoot_INIT_TAB_END__;
84 CYG_HAL_TABLE_BEGIN( __RedBoot_CMD_TAB__, RedBoot_commands ); 84 CYG_HAL_TABLE_BEGIN( __RedBoot_CMD_TAB__, RedBoot_commands );
85 CYG_HAL_TABLE_END( __RedBoot_CMD_TAB_END__, RedBoot_commands ); 85 CYG_HAL_TABLE_END( __RedBoot_CMD_TAB_END__, RedBoot_commands );
86 extern struct cmd __RedBoot_CMD_TAB__[], __RedBoot_CMD_TAB_END__; 86 extern struct cmd __RedBoot_CMD_TAB__[], __RedBoot_CMD_TAB_END__;
87
88 CYG_HAL_TABLE_BEGIN( __RedBoot_INIT_TAB__, RedBoot_inits );
89 CYG_HAL_TABLE_END( __RedBoot_INIT_TAB_END__, RedBoot_inits );
90 extern struct init_tab_entry __RedBoot_INIT_TAB__[], __RedBoot_INIT_TAB_END__;
91 87
92 // 88 //
93 // This is the main entry point for RedBoot 89 // This is the main entry point for RedBoot
94 // 90 //
95 void 91 void
127 123
128 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG 124 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
129 // Give the guy a chance to abort any boot script 125 // Give the guy a chance to abort any boot script
130 if (script) { 126 if (script) {
131 unsigned char *hold_script = script; 127 unsigned char *hold_script = script;
132 printf("== Executing boot script in %d seconds - enter ^C to abort\n", script_timeout); 128 int script_timeout_ms = script_timeout * CYGNUM_REDBOOT_FLASH_SCRIPT_TIMEOUT_RESOLUTION;
129 printf("== Executing boot script in %d.%03d seconds - enter ^C to abort\n",
130 script_timeout_ms/1000, script_timeout_ms%1000);
133 script = (unsigned char *)0; 131 script = (unsigned char *)0;
134 res = gets(line, sizeof(line), script_timeout*1000); 132 res = gets(line, sizeof(line), script_timeout_ms);
135 if (res == -2) { 133 if (res == -2) {
136 script = (unsigned char *)0; // Disable script 134 script = (unsigned char *)0; // Disable script
137 } else { 135 } else {
138 script = hold_script; // Re-enable script 136 script = hold_script; // Re-enable script
139 } 137 }
162 } else { 160 } else {
163 if (strlen(line) > 0) { 161 if (strlen(line) > 0) {
164 if ((cmd = parse(line, &argc, &argv[0])) != (struct cmd *)0) { 162 if ((cmd = parse(line, &argc, &argv[0])) != (struct cmd *)0) {
165 (cmd->fun)(argc, argv); 163 (cmd->fun)(argc, argv);
166 } else { 164 } else {
167 printf("Illegal command: %s\n", line); 165 printf("** Error: Illegal command: %s\n", line);
168 } 166 }
169 } 167 }
170 prompt = true; 168 prompt = true;
171 } 169 }
172 } 170 }
173 } 171 }
174 } 172 }
175
176 //
177 // Scan through an input line and break it into "arguments". These
178 // are space delimited strings. Return a structure which points to
179 // the strings, similar to a Unix program.
180 // Note: original input is destroyed by replacing the delimiters with
181 // null ('\0') characters for ease of use.
182 //
183 struct cmd *
184 parse(char *line, int *argc, char **argv)
185 {
186 char *cp = line;
187 int indx = 0;
188
189 while (*cp) {
190 // Skip leading spaces
191 while (*cp && *cp == ' ') cp++;
192 if (!*cp) {
193 break; // Line ended with a string of spaces
194 }
195 argv[indx++] = cp;
196 while (*cp) {
197 if (*cp == ' ') {
198 *cp++ = '\0';
199 break;
200 } else if (*cp == '"') {
201 // Swallow quote, scan till following one
202 if (argv[indx-1] == cp) {
203 argv[indx-1] = ++cp;
204 }
205 while (*cp && *cp != '"') cp++;
206 if (!*cp) {
207 printf("Unbalanced string!\n");
208 } else {
209 *cp++ = '\0';
210 break;
211 }
212 } else {
213 cp++;
214 }
215 }
216 }
217 *argc = indx;
218 return cmd_search(__RedBoot_CMD_TAB__, &__RedBoot_CMD_TAB_END__, argv[0]);
219 }
220
221 //
222 // Search through a list of commands
223 //
224 struct cmd *
225 cmd_search(struct cmd *tab, struct cmd *tabend, char *arg)
226 {
227 int cmd_len;
228 struct cmd *cmd, *cmd2;
229 // Search command table
230 cmd_len = strlen(arg);
231 cmd = tab;
232 while (cmd != tabend) {
233 if (strncmpci(arg, cmd->str, cmd_len) == 0) {
234 if (strlen(cmd->str) > cmd_len) {
235 // Check for ambiguous commands here
236 // Note: If there are commands which are not length-unique
237 // then this check will be invalid. E.g. "du" and "dump"
238 bool first = true;
239 cmd2 = tab;
240 while (cmd2 != tabend) {
241 if ((cmd != cmd2) &&
242 (strncmpci(arg, cmd2->str, cmd_len) == 0)) {
243 if (first) {
244 printf("Ambiguous command '%s', choices are: %s", arg, cmd->str);
245 first = false;
246 }
247 printf(" %s", cmd2->str);
248 }
249 cmd2++;
250 }
251 if (!first) {
252 // At least one ambiguity found - fail the lookup
253 printf("\n");
254 return (struct cmd *)0;
255 }
256 }
257 return cmd;
258 }
259 cmd++;
260 }
261 return (struct cmd *)0;
262 }
263
264 void
265 cmd_usage(struct cmd *tab, struct cmd *tabend, char *prefix)
266 {
267 struct cmd *cmd;
268 printf("Usage:\n"); for (cmd = tab; cmd != tabend; cmd++) {
269 printf(" %s%s %s\n", prefix, cmd->str, cmd->usage);
270 }
271 }
272
273 // Option processing
274
275 // Initialize option table entry (required because these entries
276 // may have dynamic contents, thus cannot be statically initialized)
277 //
278 void
279 init_opts(struct option_info *opts, char flag, bool takes_arg,
280 int arg_type, void **arg, bool *arg_set, char *name)
281 {
282 opts->flag = flag;
283 opts->takes_arg = takes_arg;
284 opts->arg_type = arg_type,
285 opts->arg = arg;
286 opts->arg_set = arg_set;
287 opts->name = name;
288 }
289
290 //
291 // Scan command line arguments (argc/argv), processing options, etc.
292 //
293 bool
294 scan_opts(int argc, char *argv[], int first,
295 struct option_info *opts, int num_opts,
296 void **def_arg, int def_arg_type, char *def_descr)
297 {
298 bool ret = true;
299 bool flag_ok;
300 bool def_arg_set = false;
301 int i, j;
302 char c, *s;
303 struct option_info *opt;
304
305 if (def_arg && (def_arg_type == OPTION_ARG_TYPE_STR)) {
306 *def_arg = (char *)0;
307 }
308 opt = opts;
309 for (j = 0; j < num_opts; j++, opt++) {
310 if (opt->arg_set) {
311 *opt->arg_set = false;
312 }
313 if (!opt->takes_arg) {
314 switch (opt->arg_type) {
315 case OPTION_ARG_TYPE_NUM:
316 *(int *)opt->arg = 0;
317 break;
318 case OPTION_ARG_TYPE_FLG:
319 *(bool *)opt->arg = false;
320 break;
321 }
322 }
323 }
324 for (i = first; i < argc; i++) {
325 if (argv[i][0] == '-') {
326 c = argv[i][1];
327 flag_ok = false;
328 opt = opts;
329 for (j = 0; j < num_opts; j++, opt++) {
330 if (c == opt->flag) {
331 if (opt->arg_set && *opt->arg_set) {
332 printf("%s alread set\n", opt->name);
333 ret = false;
334 }
335 if (opt->takes_arg) {
336 if (argv[i][2] == '=') {
337 s = &argv[i][3];
338 } else {
339 s = argv[i+1];
340 i++;
341 }
342 switch (opt->arg_type) {
343 case OPTION_ARG_TYPE_NUM:
344 if (!parse_num(s, (unsigned long *)opt->arg, 0, 0)) {
345 printf("invalid number '%s' for %s\n", s, opt->name);
346 ret = false;
347 }
348 break;
349 case OPTION_ARG_TYPE_STR:
350 *opt->arg = s;
351 break;
352 }
353 *opt->arg_set = true;
354 } else {
355 switch (opt->arg_type) {
356 case OPTION_ARG_TYPE_NUM:
357 *(int *)opt->arg = *(int *)opt->arg + 1;
358 break;
359 case OPTION_ARG_TYPE_FLG:
360 *(bool *)opt->arg = true;
361 break;
362 }
363 }
364 flag_ok = true;
365 break;
366 }
367 }
368 if (!flag_ok) {
369 printf("invalid flag '%c'\n", c);
370 ret = false;
371 }
372 } else {
373 if (def_arg) {
374 if (def_arg_set) {
375 printf("%s already set\n", def_descr);
376 ret = false;
377 }
378 switch (def_arg_type) {
379 case OPTION_ARG_TYPE_NUM:
380 if (!parse_num(argv[i], (unsigned long *)def_arg, 0, 0)) {
381 printf("invalid number '%s' for %s\n", argv[i], def_descr);
382 ret = false;
383 }
384 break;
385 case OPTION_ARG_TYPE_STR:
386 *def_arg = argv[i];
387 break;
388 }
389 def_arg_set = true;
390 } else {
391 printf("no default/non-flag arguments supported\n");
392 ret = false;
393 }
394 }
395 }
396 return ret;
397 }
398
399 //
400 // Parse (scan) a number
401 //
402 bool
403 parse_num(char *s, unsigned long *val, char **es, char *delim)
404 {
405 bool first = true;
406 int radix = 10;
407 char c;
408 unsigned long result = 0;
409 int digit;
410
411 while (*s == ' ') s++;
412 while (*s) {
413 if (first && (s[0] == '0') && (tolower(s[1]) == 'x')) {
414 radix = 16;
415 s += 2;
416 }
417 first = false;
418 c = *s++;
419 if (_is_hex(c) && ((digit = _from_hex(c)) < radix)) {
420 // Valid digit
421 result = (result * radix) + digit;
422 } else {
423 if (delim != (char *)0) {
424 // See if this character is one of the delimiters
425 char *dp = delim;
426 while (*dp && (c != *dp)) dp++;
427 if (*dp) break; // Found a good delimiter
428 }
429 return false; // Malformatted number
430 }
431 }
432 *val = result;
433 if (es != (char **)0) {
434 *es = s;
435 }
436 return true;
437 }
438
439 bool
440 parse_bool(char *s, bool *val)
441 {
442 while (*s == ' ') s++;
443 if ((*s == 't') || (*s == 'T')) {
444 *val = true;
445 } else
446 if ((*s == 'f') || (*s == 'F')) {
447 *val = false;
448 } else {
449 return false;
450 }
451 return true;
452 }
453
454 173
455 void 174 void
456 do_caches(int argc, char *argv[]) 175 do_caches(int argc, char *argv[])
457 { 176 {
458 unsigned long oldints; 177 unsigned long oldints;
494 } 213 }
495 214
496 void 215 void
497 do_dump(int argc, char *argv[]) 216 do_dump(int argc, char *argv[])
498 { 217 {
218 struct option_info opts[2];
499 unsigned long base, len; 219 unsigned long base, len;
500 220 bool base_set, len_set;
501 if (argc < 2) { 221
222 init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,
223 (void **)&base, (bool *)&base_set, "base address");
224 init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM,
225 (void **)&len, (bool *)&len_set, "length");
226 if (!scan_opts(argc, argv, 1, opts, 2, 0, 0, ""))
227 {
228 return;
229 }
230 if (!base_set) {
502 printf("Dump what [location]?\n"); 231 printf("Dump what [location]?\n");
503 return; 232 return;
504 } 233 }
505 if (!parse_num(argv[1], &base, 0, 0)) { 234 if (!len_set) {
506 printf("Invalid start address: %s\n", argv[1]);
507 return;
508 }
509 if (argc > 2) {
510 if (!parse_num(argv[2], &len, 0, 0)) {
511 printf("Invalid length/end address: %s\n", argv[2]);
512 return;
513 }
514 } else {
515 len = 32; 235 len = 32;
516 } 236 }
517 dump_buf((void *)base, len); 237 dump_buf((void *)base, len);
518 } 238 }
519 239