root/ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/main.c

Revision 12429, 24.3 kB (checked in by BrainSlayer, 5 months ago)

compressed ELF support is required for ubnt images

Line 
1 //==========================================================================
2 //
3 //      main.c
4 //
5 //      RedBoot main routine
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
12 // Copyright (C) 2002, 2003, 2004 Gary Thomas
13 //
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version.
17 //
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
21 // for more details.
22 //
23 // You should have received a copy of the GNU General Public License along
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 //
27 // As a special exception, if other files instantiate templates or use macros
28 // or inline functions from this file, or you compile this file and link it
29 // with other works to produce a work based on this file, this file does not
30 // by itself cause the resulting work to be covered by the GNU General Public
31 // License. However the source code for this file must still be made available
32 // in accordance with section (3) of the GNU General Public License.
33 //
34 // This exception does not invalidate any other reasons why a work based on
35 // this file might be covered by the GNU General Public License.
36 //
37 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38 // at http://sources.redhat.com/ecos/ecos-license/
39 // -------------------------------------------
40 //####ECOSGPLCOPYRIGHTEND####
41 //==========================================================================
42 //#####DESCRIPTIONBEGIN####
43 //
44 // Author(s):    gthomas
45 // Contributors: gthomas, tkoeller
46 // Date:         2000-07-14
47 // Purpose:     
48 // Description: 
49 //             
50 // This code is part of RedBoot (tm).
51 //
52 //####DESCRIPTIONEND####
53 //
54 //==========================================================================
55
56 #define  DEFINE_VARS
57 #include <redboot.h>
58 #include <cyg/hal/hal_arch.h>
59 #include <cyg/hal/hal_intr.h>
60 #include <cyg/hal/hal_if.h>
61 #include <cyg/hal/hal_cache.h>
62 #include CYGHWR_MEMORY_LAYOUT_H
63
64 #ifdef CYGPKG_IO_ETH_DRIVERS
65 #include <cyg/io/eth/eth_drv.h>            // Logical driver interfaces
66 #endif
67
68 #include <cyg/hal/hal_tables.h>
69 #include <cyg/infra/cyg_ass.h>         // assertion macros
70
71 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
72 #ifdef CYGBLD_HAL_PLATFORM_STUB_H
73 #include CYGBLD_HAL_PLATFORM_STUB_H
74 #else
75 #include <cyg/hal/plf_stub.h>
76 #endif
77 // GDB interfaces
78 extern void breakpoint(void);
79 #endif
80
81 // Builtin Self Test (BIST)
82 externC void bist(void);
83
84 // Path to code run from a go command or to GDB stubs
85 static void trampoline(unsigned long entry);
86
87 // Return path for code run from a go command or for GDB stubs
88 static void return_to_redboot(int status);
89
90 // Address of area where current context is saved before executing
91 // trampoline procedure
92 static void * saved_context;
93
94 // Status returned after trampoline execution
95 static int return_status;
96  
97
98 // CLI command processing (defined in this file)
99 RedBoot_cmd("version",
100             "Display RedBoot version information",
101             "",
102             do_version
103     );
104 RedBoot_cmd("help",
105             "Help about help?",
106             "[<topic>]",
107             do_help
108     );
109
110 static char go_usage[] = "[-w <timeout>] [-c] "
111 #ifdef CYGPKG_IO_ETH_DRIVERS
112                       "[-n] "
113 #endif
114                       "[entry]";
115
116 RedBoot_cmd("go",
117             "Execute code at a location",
118             go_usage,
119             do_go
120     );
121 #ifdef HAL_PLATFORM_RESET
122 RedBoot_cmd("reset",
123             "Reset the system",
124             "",
125             do_reset
126     );
127 #endif
128 #ifdef CYGSEM_REDBOOT_VARIABLE_BAUD_RATE
129 RedBoot_cmd("baudrate",
130             "Set/Query the system console baud rate",
131             "[-b <rate>]",
132             do_baud_rate
133     );
134 #endif
135
136 // Define table boundaries
137 CYG_HAL_TABLE_BEGIN( __RedBoot_INIT_TAB__, RedBoot_inits );
138 CYG_HAL_TABLE_END( __RedBoot_INIT_TAB_END__, RedBoot_inits );
139 extern struct init_tab_entry __RedBoot_INIT_TAB__[], __RedBoot_INIT_TAB_END__;
140
141 CYG_HAL_TABLE_BEGIN( __RedBoot_CMD_TAB__, RedBoot_commands );
142 CYG_HAL_TABLE_END( __RedBoot_CMD_TAB_END__, RedBoot_commands );
143 extern struct cmd __RedBoot_CMD_TAB__[], __RedBoot_CMD_TAB_END__;
144
145 CYG_HAL_TABLE_BEGIN( __RedBoot_IDLE_TAB__, RedBoot_idle );
146 CYG_HAL_TABLE_END( __RedBoot_IDLE_TAB_END__, RedBoot_idle );
147 extern struct idle_tab_entry __RedBoot_IDLE_TAB__[], __RedBoot_IDLE_TAB_END__;
148
149 #ifdef HAL_ARCH_PROGRAM_NEW_STACK
150 extern void HAL_ARCH_PROGRAM_NEW_STACK(void *fun);
151 #endif
152
153 //
154 // [Null] Builtin [Power On] Self Test
155 //
156 void bist(void) CYGBLD_ATTRIB_WEAK;
157
158 #define RESCUE_SCRIPT "tftpd\n"
159
160 int in_rescue_mode = 0;
161
162 void set_gpio(int gpio,int state)
163 {
164 #if defined(CYGPKG_HAL_MIPS_AR2316)
165         *(volatile unsigned *)AR2316_GPIO_CR |= 1<<gpio;        /*set GPIO0 to be output */
166 if (state)
167         *(volatile unsigned *)AR2316_GPIO_DO |= 1<<gpio;        /*set GPIO0 to 1 to spi flash CS normal state */
168 else
169         *(volatile unsigned *)AR2316_GPIO_DO &= ~(1<<gpio);     /*set GPIO0 to 1 to spi flash CS normal state */
170 #else
171         *(volatile unsigned *)AR531X_GPIO_CR &= ~(1<<gpio);     /*set GPIO0 to be output */
172 if (state)
173         *(volatile unsigned *)AR531X_GPIO_DO |= 1<<gpio;        /*set GPIO0 to 1 to spi flash CS normal state */
174 else
175         *(volatile unsigned *)AR531X_GPIO_DO &= ~(1<<gpio);     /*set GPIO0 to 1 to spi flash CS normal state */
176 #endif
177
178 }
179
180
181 #include <ramconfig.h>
182 static int rescue_mode(void)
183 {
184         int b;
185         int inverse = (RESETBUTTON&0xf0);
186         int resetgpio = RESETBUTTON&0x0F;
187 #if defined(CYGPKG_HAL_MIPS_AR2316)
188         b = ((*(volatile unsigned int *)(AR2316_GPIO_DI)) >>
189                                         resetgpio) & 1;
190 #else
191         b = ((*(volatile unsigned int *)(AR531X_GPIO_DI)) >>
192                                         resetgpio) & 1;
193 #endif
194         if (inverse)
195             b=(1-b);
196         return b;
197 }
198
199 void
200 bist(void)
201 {
202         if (rescue_mode()) {
203                 diag_printf("Reset button pressed - switching to rescue mode.\n");
204                 in_rescue_mode = 1;
205         }
206
207 }
208
209 //
210 // 'version' command
211 //
212 void
213 do_version(int argc, char *argv[])
214 {
215 #if CYGBLD_REDBOOT_MAX_MEM_SEGMENTS > 1
216     int seg;
217 #endif
218 #ifdef CYGPKG_REDBOOT_FLASH
219     externC void _flash_info(void);
220 #endif
221     char *version = CYGACC_CALL_IF_MONITOR_VERSION();
222
223     diag_printf(version);
224 #ifdef HAL_PLATFORM_CPU
225     diag_printf("Platform: %s (%s) %s\n", HAL_PLATFORM_BOARD, HAL_PLATFORM_CPU, HAL_PLATFORM_EXTRA);
226 #endif
227     diag_printf("Copyright (C) 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.\n");
228     diag_printf("Copyright (C) 2009 NewMedia-NET GmbH\n\n");
229     diag_printf("Board: %s \n", CYGNUM_HAL_BOARD_TYPE);
230     diag_printf("RAM: %p-%p, ", (void*)ram_start, (void*)ram_end);
231     diag_printf("[%p-%p]", mem_segments[0].start, mem_segments[0].end);
232     diag_printf(" available\n");
233 #if CYGBLD_REDBOOT_MAX_MEM_SEGMENTS > 1
234     for (seg = 1;  seg < CYGBLD_REDBOOT_MAX_MEM_SEGMENTS;  seg++) {
235         if (mem_segments[seg].start != NO_MEMORY) {
236             diag_printf("     %p-%p, ", mem_segments[seg].start, mem_segments[seg].end);
237             diag_printf("[%p-%p]", mem_segments[seg].start, mem_segments[seg].end);
238             diag_printf(" available\n");
239         }
240     }
241 #endif
242 #ifdef CYGPKG_REDBOOT_FLASH
243     _flash_info();
244 #endif
245 }
246
247 //
248 // This function is called when RedBoot is idle (waiting for user
249 // input).  It will call any registered "idle" routines, e.g. scan
250 // for incoming network connections, blank an LCD screen, etc.
251 //
252 void
253 do_idle(bool is_idle)
254 {
255     struct idle_tab_entry *idle_entry;
256
257     for (idle_entry = __RedBoot_IDLE_TAB__;
258          idle_entry != &__RedBoot_IDLE_TAB_END__;  idle_entry++) {
259         (*idle_entry->fun)(is_idle);
260     }
261 }
262
263 // Wrapper used by diag_printf()
264 static void
265 _mon_write_char(char c, void **param)
266 {
267     if (c == '\n') {
268         mon_write_char('\r');
269     }
270     mon_write_char(c);
271 }
272
273 //
274 // Handle illegal memory accesses (and other abort conditions)
275 //
276 static hal_jmp_buf error_jmpbuf;
277 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
278 externC
279 #endif
280   void* volatile __mem_fault_handler;
281
282 static void error_handler(void)
283 {
284     hal_longjmp(error_jmpbuf, 1);
285 }
286
287
288 //
289 // This is the main entry point for RedBoot
290 //
291 void
292 cyg_start(void)
293 {
294     int res = 0;
295     bool prompt = true;
296     static char line[CYGPKG_REDBOOT_MAX_CMD_LINE];
297     char *command;
298     struct cmd *cmd;
299     int cur;
300     struct init_tab_entry *init_entry;
301     extern char RedBoot_version[];
302 #if CYGBLD_REDBOOT_MAX_MEM_SEGMENTS > 1
303     int seg;
304 #endif
305
306     // Export version information
307     CYGACC_CALL_IF_MONITOR_VERSION_SET(RedBoot_version);
308
309     CYGACC_CALL_IF_MONITOR_RETURN_SET(return_to_redboot);
310
311     // Make sure the channels are properly initialized.
312     diag_init_putc(_mon_write_char);
313     hal_if_diag_init();
314
315     // Force console to output raw text - but remember the old setting
316     // so it can be restored if interaction with a debugger is
317     // required.
318     cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
319     CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL);
320 #ifdef CYGPKG_REDBOOT_ANY_CONSOLE
321     console_selected = false;
322 #endif
323     console_echo = true;
324     CYGACC_CALL_IF_DELAY_US((cyg_int32)2*100000);
325
326     ram_start = (unsigned char *)CYGMEM_REGION_ram;
327     ram_end = (unsigned char *)(CYGMEM_REGION_ram+CYGMEM_REGION_ram_SIZE);
328 #ifdef HAL_MEM_REAL_REGION_TOP
329     {
330         unsigned char *ram_end_tmp = ram_end;
331         ram_end = HAL_MEM_REAL_REGION_TOP( ram_end_tmp );
332     }
333 #endif
334 #ifdef CYGMEM_SECTION_heap1
335     workspace_start = (unsigned char *)CYGMEM_SECTION_heap1;
336     workspace_end = (unsigned char *)(CYGMEM_SECTION_heap1+CYGMEM_SECTION_heap1_SIZE);
337 #else
338     workspace_start = (unsigned char *)CYGMEM_REGION_ram;
339     workspace_end = (unsigned char *)(CYGMEM_REGION_ram+CYGMEM_REGION_ram_SIZE);
340 #endif
341
342     if ( ram_end < workspace_end ) {
343         // when *less* SDRAM is installed than the possible maximum,
344         // but the heap1 region remains greater...
345         workspace_end = ram_end;
346     }
347
348     // Nothing has ever been loaded into memory
349     entry_address = (unsigned long)NO_MEMORY;
350
351     bist();
352
353 #if defined(CYGPRI_REDBOOT_ZLIB_FLASH) && defined(CYGOPT_REDBOOT_FIS_ZLIB_COMMON_BUFFER)
354     fis_zlib_common_buffer =
355     workspace_end -= CYGNUM_REDBOOT_FIS_ZLIB_COMMON_BUFFER_SIZE;
356 #endif
357
358 #ifdef CYGFUN_REDBOOT_BOOT_SCRIPT
359     script_timeout = CYGNUM_REDBOOT_BOOT_SCRIPT_DEFAULT_TIMEOUT;
360 #endif
361
362     for (init_entry = __RedBoot_INIT_TAB__; init_entry != &__RedBoot_INIT_TAB_END__;  init_entry++) {
363         (*init_entry->fun)();
364     }
365
366     mem_segments[0].start = workspace_start;
367     mem_segments[0].end = workspace_end;
368 #if CYGBLD_REDBOOT_MAX_MEM_SEGMENTS > 1
369     for (seg = 1;  seg < CYGBLD_REDBOOT_MAX_MEM_SEGMENTS;  seg++) {
370         cyg_plf_memory_segment(seg, &mem_segments[seg].start, &mem_segments[seg].end);
371     }
372 #endif
373
374 #ifdef CYGSEM_REDBOOT_PLF_STARTUP
375     cyg_plf_redboot_startup();
376 #endif
377     do_version(0,0);
378     if (in_rescue_mode) {
379             diag_printf("Starting RESCUE script...\n");
380             script = RESCUE_SCRIPT; 
381     }
382
383 #ifdef CYGFUN_REDBOOT_BOOT_SCRIPT
384 # ifdef CYGDAT_REDBOOT_DEFAULT_BOOT_SCRIPT
385     if (!script) {
386       script = CYGDAT_REDBOOT_DEFAULT_BOOT_SCRIPT;
387     }
388 # endif
389     if (script) {
390         // Give the guy a chance to abort any boot script
391         unsigned char *hold_script = script;
392         int script_timeout_ms = script_timeout * CYGNUM_REDBOOT_BOOT_SCRIPT_TIMEOUT_RESOLUTION;
393         diag_printf("== Executing boot script in %d.%03d seconds - enter ^C to abort\n",
394                     script_timeout_ms/1000, script_timeout_ms%1000);
395         script = (unsigned char *)0;
396         res = _GETS_CTRLC;  // Treat 0 timeout as ^C
397         while (script_timeout_ms >= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT) {
398             res = _rb_gets(line, sizeof(line), CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT);
399             if (res >= _GETS_OK) {
400                 diag_printf("== Executing boot script in %d.%03d seconds - enter ^C to abort\n",
401                             script_timeout_ms/1000, script_timeout_ms%1000);
402                 continue;  // Ignore anything but ^C
403             }
404             if (res != _GETS_TIMEOUT) break;
405             script_timeout_ms -= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT;
406         }
407         if (res == _GETS_CTRLC) {
408             script = (unsigned char *)0;  // Disable script
409         } else {
410             script = hold_script;  // Re-enable script
411         }
412     }
413 #endif
414
415     while (true) {
416         if (prompt) {
417             diag_printf("RedBoot> ");
418             prompt = false;
419         }
420 #if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0
421         cmd_history = true;  // Enable history collection
422 #endif
423         res = _rb_gets(line, sizeof(line), CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT);
424 #if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0
425         cmd_history = false;  // Enable history collection
426 #endif
427         if (res == _GETS_TIMEOUT) {
428             // No input arrived
429         } else {
430 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
431             if (res == _GETS_GDB) {
432                 int dbgchan;
433                 hal_virtual_comm_table_t *__chan;
434                 int i;
435                 // Special case of '$' - need to start GDB protocol
436                 gdb_active = true;
437                 // Mask interrupts on all channels
438                 for (i = 0;  i < CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS;  i++) {
439                     CYGACC_CALL_IF_SET_CONSOLE_COMM(i);
440                     __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
441                     CYGACC_COMM_IF_CONTROL( *__chan, __COMMCTL_IRQ_DISABLE );
442                 }
443    
444                 CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
445
446                 // set up a temporary context that will take us to the trampoline
447                 HAL_THREAD_INIT_CONTEXT(workspace_end,
448                                         breakpoint, trampoline, 0);
449
450                 // switch context to trampoline (get GDB stubs started)
451                 HAL_THREAD_SWITCH_CONTEXT(&saved_context, &workspace_end);
452
453                 gdb_active = false;
454
455                 dbgchan = CYGACC_CALL_IF_SET_DEBUG_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
456                 CYGACC_CALL_IF_SET_CONSOLE_COMM(dbgchan);
457             } else
458 #endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
459             {
460 #ifdef CYGSEM_REDBOOT_FLASH_ALIASES             
461                 expand_aliases(line, sizeof(line));
462 #endif
463                 command = (char *)&line;
464                 if ((*command == '#') || (*command == '=')) {
465                     // Special cases
466                     if (*command == '=') {
467                         // Print line on console
468                         diag_printf("%s\n", &line[2]);
469                     }
470                 } else {
471                     while (strlen(command) > 0) {                   
472                         if ((cmd = parse(&command, &argc, &argv[0])) != (struct cmd *)0) {
473                             // Try to handle aborts - messy because of the stack unwinding...
474                             __mem_fault_handler = error_handler;
475                             if (hal_setjmp(error_jmpbuf)) {
476                                 diag_printf("** command abort - illegal memory access?\n");
477                             } else {
478                                 (cmd->fun)(argc, argv);
479                             }
480                             __mem_fault_handler = 0;
481                         } else {
482                             diag_printf("** Error: Illegal command: \"%s\"\n", argv[0]);
483                         }
484                     }
485                 }
486                 prompt = true;
487             }
488         }
489     }
490 }
491
492 void
493 show_help(struct cmd *cmd, struct cmd *cmd_end, char *which, char *pre)
494 {
495     bool show;
496     int len = 0;
497
498     if (which) {
499         len = strlen(which);
500     }
501     while (cmd != cmd_end) {
502         show = true;
503         if (which && (strncasecmp(which, cmd->str, len) != 0)) {
504             show = false;
505         }
506         if (show) {
507             diag_printf("%s\n  %s %s %s\n", cmd->help, pre, cmd->str, cmd->usage);
508             if ((cmd->sub_cmds != (struct cmd *)0) && (which != (char *)0)) {
509                 show_help(cmd->sub_cmds, cmd->sub_cmds_end, 0, cmd->str);
510             }
511         }
512         cmd++;
513     }
514 }
515
516 void
517 do_help(int argc, char *argv[])
518 {
519     struct cmd *cmd;
520     char *which = (char *)0;
521
522     if (!scan_opts(argc, argv, 1, 0, 0, (void *)&which, OPTION_ARG_TYPE_STR, "<topic>")) {
523         diag_printf("Invalid argument\n");
524         return;
525     }
526     cmd = __RedBoot_CMD_TAB__;
527     show_help(cmd, &__RedBoot_CMD_TAB_END__, which, "");
528     return;
529 }
530
531 static void
532 trampoline(unsigned long entry)
533 {
534     typedef void code_fun(void);
535     code_fun *fun = (code_fun *)entry;
536     unsigned long oldints;
537
538     HAL_DISABLE_INTERRUPTS(oldints);
539
540 #ifdef HAL_ARCH_PROGRAM_NEW_STACK
541     HAL_ARCH_PROGRAM_NEW_STACK(fun);
542 #else
543     (*fun)();
544 #endif
545
546     HAL_THREAD_LOAD_CONTEXT(&saved_context);
547 }
548
549 static void
550 return_to_redboot(int status)
551 {
552     CYGARC_HAL_SAVE_GP();
553
554     return_status = status;
555     HAL_THREAD_LOAD_CONTEXT(&saved_context);
556     // never returns
557
558     // need this to balance above CYGARC_HAL_SAVE_GP on
559     // some platforms. It will never run, though.
560     CYGARC_HAL_RESTORE_GP();
561 }
562
563 void
564 do_go(int argc, char *argv[])
565 {
566     int i, cur, num_options;
567     unsigned long entry;
568     unsigned long oldints;
569     bool wait_time_set;
570     int  wait_time, res;
571     bool cache_enabled = false;
572 #ifdef CYGPKG_IO_ETH_DRIVERS
573     bool stop_net = false;
574 #endif
575     struct option_info opts[3];
576     char line[8];
577     hal_virtual_comm_table_t *__chan;
578
579     __mem_fault_handler = 0; // Let GDB handle any faults directly
580     entry = entry_address;  // Default from last 'load' operation
581     init_opts(&opts[0], 'w', true, OPTION_ARG_TYPE_NUM,
582               (void *)&wait_time, (bool *)&wait_time_set, "wait timeout");
583     init_opts(&opts[1], 'c', false, OPTION_ARG_TYPE_FLG,
584               (void *)&cache_enabled, (bool *)0, "go with caches enabled");
585     num_options = 2;
586 #ifdef CYGPKG_IO_ETH_DRIVERS
587     init_opts(&opts[2], 'n', false, OPTION_ARG_TYPE_FLG,
588               (void *)&stop_net, (bool *)0, "go with network driver stopped");
589     num_options++;
590 #endif
591
592     CYG_ASSERT(num_options <= NUM_ELEMS(opts), "Too many options");
593
594     if (!scan_opts(argc, argv, 1, opts, num_options, (void *)&entry, OPTION_ARG_TYPE_NUM, "starting address"))
595     {
596         return;
597     }
598     if (entry == (unsigned long)NO_MEMORY) {
599         diag_printf("No entry point known - aborted\n");
600         return;
601     }
602     if (wait_time_set) {
603         int script_timeout_ms = wait_time * 1000;
604 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
605         unsigned char *hold_script = script;
606         script = (unsigned char *)0;
607 #endif
608         diag_printf("About to start execution at %p - abort with ^C within %d seconds\n",
609                     (void *)entry, wait_time);
610         while (script_timeout_ms >= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT) {
611             res = _rb_gets(line, sizeof(line), CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT);
612             if (res == _GETS_CTRLC) {
613 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
614                 script = hold_script;  // Re-enable script
615 #endif
616                 return;
617             }
618             script_timeout_ms -= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT;
619         }
620     }
621
622     // Mask interrupts on all channels
623     cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
624     for (i = 0;  i < CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS;  i++) {
625         CYGACC_CALL_IF_SET_CONSOLE_COMM(i);
626         __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
627         CYGACC_COMM_IF_CONTROL( *__chan, __COMMCTL_IRQ_DISABLE );
628     }
629     CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
630
631     __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
632     CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_ENABLE_LINE_FLUSH);
633
634 #ifdef CYGPKG_IO_ETH_DRIVERS
635     if (stop_net)
636         eth_drv_stop();
637 #endif
638        
639     HAL_DISABLE_INTERRUPTS(oldints);
640     HAL_DCACHE_SYNC();
641     if (!cache_enabled) {
642         HAL_ICACHE_DISABLE();
643         HAL_DCACHE_DISABLE();
644         HAL_DCACHE_SYNC();
645     }
646     HAL_ICACHE_INVALIDATE_ALL();
647     HAL_DCACHE_INVALIDATE_ALL();
648     // set up a temporary context that will take us to the trampoline
649     HAL_THREAD_INIT_CONTEXT(workspace_end, entry, trampoline, 0);
650
651     // switch context to trampoline
652     HAL_THREAD_SWITCH_CONTEXT(&saved_context, &workspace_end);
653
654     // we get back here by way of return_to_redboot()
655
656     // undo the changes we made before switching context
657     if (!cache_enabled) {
658         HAL_ICACHE_ENABLE();
659         HAL_DCACHE_ENABLE();
660     }
661
662     CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_DISABLE_LINE_FLUSH);
663
664     HAL_RESTORE_INTERRUPTS(oldints);
665
666     diag_printf("\nProgram completed with status %d\n", return_status);
667 }
668
669 #ifdef HAL_PLATFORM_RESET
670 void
671 do_reset(int argc, char *argv[])
672 {
673     diag_printf("... Resetting.");
674     CYGACC_CALL_IF_DELAY_US(2*100000);
675     diag_printf("\n");
676     CYGACC_CALL_IF_RESET();
677     diag_printf("!! oops, RESET not working on this platform\n");
678 }
679 #endif
680
681 #ifdef CYGSEM_REDBOOT_VARIABLE_BAUD_RATE
682 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
683 #include <flash_config.h>
684 #endif
685
686 static int
687 set_comm_baud_rate(hal_virtual_comm_table_t *chan, int rate)
688 {
689     int current_rate;
690
691     current_rate = CYGACC_COMM_IF_CONTROL(*chan, __COMMCTL_GETBAUD);
692     if (rate != current_rate)
693         return CYGACC_COMM_IF_CONTROL(*chan, __COMMCTL_SETBAUD, rate);
694
695     return 0;
696 }
697
698 int
699 set_console_baud_rate(int rate)
700 {
701     int ret = -1;
702 #ifdef CYGPKG_REDBOOT_ANY_CONSOLE
703     if (!console_selected) {
704         int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
705         int i;
706         // Set baud for all channels
707         for (i = 0;  i < CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS;  i++) {
708             CYGACC_CALL_IF_SET_CONSOLE_COMM(i);
709             ret = set_comm_baud_rate(CYGACC_CALL_IF_CONSOLE_PROCS(), rate);
710             if (ret < 0)
711                 break;
712         }
713         CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
714     } else
715 #endif
716     ret = set_comm_baud_rate(CYGACC_CALL_IF_CONSOLE_PROCS(), rate);
717
718     if (ret < 0)
719         diag_printf("Setting console baud rate to %d failed\n", rate);
720
721     return ret;
722 }
723
724 static void
725 _sleep(int ms)
726 {
727     int i;
728     for (i = 0;  i < ms;  i++) {
729         CYGACC_CALL_IF_DELAY_US((cyg_int32)1000);
730     }
731 }
732
733 void
734 do_baud_rate(int argc, char *argv[])
735 {
736     int new_rate, ret, old_rate;
737     bool new_rate_set;
738     hal_virtual_comm_table_t *__chan;
739     struct option_info opts[1];
740 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
741     struct config_option opt;
742 #endif
743
744     init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,
745               (void *)&new_rate, (bool *)&new_rate_set, "new baud rate");
746     if (!scan_opts(argc, argv, 1, opts, 1, 0, 0, "")) {
747         return;
748     }
749     __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
750     if (new_rate_set) {
751         diag_printf("Baud rate will be changed to %d - update your settings\n", new_rate);
752         _sleep(500);  // Give serial time to flush
753         old_rate = CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_GETBAUD);
754         ret = set_console_baud_rate(new_rate);
755         if (ret < 0) {
756             if (old_rate > 0) {
757                 // Try to restore
758                 set_console_baud_rate(old_rate);
759                 _sleep(500);  // Give serial time to flush
760                 diag_printf("\nret = %d\n", ret);
761             }
762             return;  // Couldn't set the desired rate
763         }
764         // Make sure this new rate works or back off to previous value
765         // Sleep for a few seconds, then prompt to see if it works
766         _sleep(3000);  // Give serial time to flush
767         if (!verify_action_with_timeout(5000, "Baud rate changed to %d", new_rate)) {
768             _sleep(500);  // Give serial time to flush
769             set_console_baud_rate(old_rate);
770             _sleep(500);  // Give serial time to flush
771             return;
772         }
773 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
774         opt.type = CONFIG_INT;
775         opt.enable = (char *)0;
776         opt.enable_sense = 1;
777         opt.key = "console_baud_rate";
778         opt.dflt = new_rate;
779         flash_add_config(&opt, true);
780 #endif
781     } else {
782         ret = CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_GETBAUD);
783         diag_printf("Baud rate = ");
784         if (ret <= 0) {
785             diag_printf("unknown\n");
786         } else {
787             diag_printf("%d\n", ret);
788         }
789     }
790 }
791 #endif
792
793 //
794 // Validate an address to see if it is within any known RAM area
795 //
796 bool
797 valid_address(unsigned char *addr)
798 {
799     int seg;
800
801     for (seg = 0;  seg < CYGBLD_REDBOOT_MAX_MEM_SEGMENTS;  seg++) {
802         if (mem_segments[seg].start != NO_MEMORY) {
803             if ((addr >= mem_segments[seg].start) && (addr < mem_segments[seg].end)) {
804                 return true;
805             }
806         }
807     }
808     return false;
809 }
Note: See TracBrowser for help on using the browser.