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

Revision 12368, 23.6 kB (checked in by BrainSlayer, 5 months ago)

tftp server added, supports wiligear, ubiquiti and dd-wrt webflash format

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
163 #include <ramconfig.h>
164 static int rescue_mode(void)
165 {
166         int b;
167         int inverse = (RESETBUTTON&0xf0);
168         int resetgpio = RESETBUTTON&0x0F;
169 #if defined(CYGPKG_HAL_MIPS_AR2316)
170         b = ((*(volatile unsigned int *)(AR2316_GPIO_DI)) >>
171                                         resetgpio) & 1;
172 #else
173         b = ((*(volatile unsigned int *)(AR531X_GPIO_DI)) >>
174                                         resetgpio) & 1;
175 #endif
176         if (inverse)
177             b=(1-b);
178         return b;
179 }
180
181 void
182 bist(void)
183 {
184         if (rescue_mode()) {
185                 diag_printf("Reset button pressed - switching to rescue mode.\n");
186                 in_rescue_mode = 1;
187         }
188
189 }
190
191 //
192 // 'version' command
193 //
194 void
195 do_version(int argc, char *argv[])
196 {
197 #if CYGBLD_REDBOOT_MAX_MEM_SEGMENTS > 1
198     int seg;
199 #endif
200 #ifdef CYGPKG_REDBOOT_FLASH
201     externC void _flash_info(void);
202 #endif
203     char *version = CYGACC_CALL_IF_MONITOR_VERSION();
204
205     diag_printf(version);
206 #ifdef HAL_PLATFORM_CPU
207     diag_printf("Platform: %s (%s) %s\n", HAL_PLATFORM_BOARD, HAL_PLATFORM_CPU, HAL_PLATFORM_EXTRA);
208 #endif
209     diag_printf("Copyright (C) 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.\n");
210     diag_printf("Copyright (C) 2009 NewMedia-NET GmbH\n\n");
211     diag_printf("Board: %s \n", CYGNUM_HAL_BOARD_TYPE);
212     diag_printf("RAM: %p-%p, ", (void*)ram_start, (void*)ram_end);
213     diag_printf("[%p-%p]", mem_segments[0].start, mem_segments[0].end);
214     diag_printf(" available\n");
215 #if CYGBLD_REDBOOT_MAX_MEM_SEGMENTS > 1
216     for (seg = 1;  seg < CYGBLD_REDBOOT_MAX_MEM_SEGMENTS;  seg++) {
217         if (mem_segments[seg].start != NO_MEMORY) {
218             diag_printf("     %p-%p, ", mem_segments[seg].start, mem_segments[seg].end);
219             diag_printf("[%p-%p]", mem_segments[seg].start, mem_segments[seg].end);
220             diag_printf(" available\n");
221         }
222     }
223 #endif
224 #ifdef CYGPKG_REDBOOT_FLASH
225     _flash_info();
226 #endif
227 }
228
229 //
230 // This function is called when RedBoot is idle (waiting for user
231 // input).  It will call any registered "idle" routines, e.g. scan
232 // for incoming network connections, blank an LCD screen, etc.
233 //
234 void
235 do_idle(bool is_idle)
236 {
237     struct idle_tab_entry *idle_entry;
238
239     for (idle_entry = __RedBoot_IDLE_TAB__;
240          idle_entry != &__RedBoot_IDLE_TAB_END__;  idle_entry++) {
241         (*idle_entry->fun)(is_idle);
242     }
243 }
244
245 // Wrapper used by diag_printf()
246 static void
247 _mon_write_char(char c, void **param)
248 {
249     if (c == '\n') {
250         mon_write_char('\r');
251     }
252     mon_write_char(c);
253 }
254
255 //
256 // Handle illegal memory accesses (and other abort conditions)
257 //
258 static hal_jmp_buf error_jmpbuf;
259 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
260 externC
261 #endif
262   void* volatile __mem_fault_handler;
263
264 static void error_handler(void)
265 {
266     hal_longjmp(error_jmpbuf, 1);
267 }
268
269
270 //
271 // This is the main entry point for RedBoot
272 //
273 void
274 cyg_start(void)
275 {
276     int res = 0;
277     bool prompt = true;
278     static char line[CYGPKG_REDBOOT_MAX_CMD_LINE];
279     char *command;
280     struct cmd *cmd;
281     int cur;
282     struct init_tab_entry *init_entry;
283     extern char RedBoot_version[];
284 #if CYGBLD_REDBOOT_MAX_MEM_SEGMENTS > 1
285     int seg;
286 #endif
287
288     // Export version information
289     CYGACC_CALL_IF_MONITOR_VERSION_SET(RedBoot_version);
290
291     CYGACC_CALL_IF_MONITOR_RETURN_SET(return_to_redboot);
292
293     // Make sure the channels are properly initialized.
294     diag_init_putc(_mon_write_char);
295     hal_if_diag_init();
296
297     // Force console to output raw text - but remember the old setting
298     // so it can be restored if interaction with a debugger is
299     // required.
300     cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
301     CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL);
302 #ifdef CYGPKG_REDBOOT_ANY_CONSOLE
303     console_selected = false;
304 #endif
305     console_echo = true;
306     CYGACC_CALL_IF_DELAY_US((cyg_int32)2*100000);
307
308     ram_start = (unsigned char *)CYGMEM_REGION_ram;
309     ram_end = (unsigned char *)(CYGMEM_REGION_ram+CYGMEM_REGION_ram_SIZE);
310 #ifdef HAL_MEM_REAL_REGION_TOP
311     {
312         unsigned char *ram_end_tmp = ram_end;
313         ram_end = HAL_MEM_REAL_REGION_TOP( ram_end_tmp );
314     }
315 #endif
316 #ifdef CYGMEM_SECTION_heap1
317     workspace_start = (unsigned char *)CYGMEM_SECTION_heap1;
318     workspace_end = (unsigned char *)(CYGMEM_SECTION_heap1+CYGMEM_SECTION_heap1_SIZE);
319 #else
320     workspace_start = (unsigned char *)CYGMEM_REGION_ram;
321     workspace_end = (unsigned char *)(CYGMEM_REGION_ram+CYGMEM_REGION_ram_SIZE);
322 #endif
323
324     if ( ram_end < workspace_end ) {
325         // when *less* SDRAM is installed than the possible maximum,
326         // but the heap1 region remains greater...
327         workspace_end = ram_end;
328     }
329
330     // Nothing has ever been loaded into memory
331     entry_address = (unsigned long)NO_MEMORY;
332
333     bist();
334
335 #if defined(CYGPRI_REDBOOT_ZLIB_FLASH) && defined(CYGOPT_REDBOOT_FIS_ZLIB_COMMON_BUFFER)
336     fis_zlib_common_buffer =
337     workspace_end -= CYGNUM_REDBOOT_FIS_ZLIB_COMMON_BUFFER_SIZE;
338 #endif
339
340 #ifdef CYGFUN_REDBOOT_BOOT_SCRIPT
341     script_timeout = CYGNUM_REDBOOT_BOOT_SCRIPT_DEFAULT_TIMEOUT;
342 #endif
343
344     for (init_entry = __RedBoot_INIT_TAB__; init_entry != &__RedBoot_INIT_TAB_END__;  init_entry++) {
345         (*init_entry->fun)();
346     }
347
348     mem_segments[0].start = workspace_start;
349     mem_segments[0].end = workspace_end;
350 #if CYGBLD_REDBOOT_MAX_MEM_SEGMENTS > 1
351     for (seg = 1;  seg < CYGBLD_REDBOOT_MAX_MEM_SEGMENTS;  seg++) {
352         cyg_plf_memory_segment(seg, &mem_segments[seg].start, &mem_segments[seg].end);
353     }
354 #endif
355
356 #ifdef CYGSEM_REDBOOT_PLF_STARTUP
357     cyg_plf_redboot_startup();
358 #endif
359     do_version(0,0);
360
361     if (in_rescue_mode) {
362             diag_printf("Starting RESCUE script...\n");
363             script = RESCUE_SCRIPT; 
364     }
365
366 #ifdef CYGFUN_REDBOOT_BOOT_SCRIPT
367 # ifdef CYGDAT_REDBOOT_DEFAULT_BOOT_SCRIPT
368     if (!script) {
369       script = CYGDAT_REDBOOT_DEFAULT_BOOT_SCRIPT;
370     }
371 # endif
372     if (script) {
373         // Give the guy a chance to abort any boot script
374         unsigned char *hold_script = script;
375         int script_timeout_ms = script_timeout * CYGNUM_REDBOOT_BOOT_SCRIPT_TIMEOUT_RESOLUTION;
376         diag_printf("== Executing boot script in %d.%03d seconds - enter ^C to abort\n",
377                     script_timeout_ms/1000, script_timeout_ms%1000);
378         script = (unsigned char *)0;
379         res = _GETS_CTRLC;  // Treat 0 timeout as ^C
380         while (script_timeout_ms >= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT) {
381             res = _rb_gets(line, sizeof(line), CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT);
382             if (res >= _GETS_OK) {
383                 diag_printf("== Executing boot script in %d.%03d seconds - enter ^C to abort\n",
384                             script_timeout_ms/1000, script_timeout_ms%1000);
385                 continue;  // Ignore anything but ^C
386             }
387             if (res != _GETS_TIMEOUT) break;
388             script_timeout_ms -= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT;
389         }
390         if (res == _GETS_CTRLC) {
391             script = (unsigned char *)0;  // Disable script
392         } else {
393             script = hold_script;  // Re-enable script
394         }
395     }
396 #endif
397
398     while (true) {
399         if (prompt) {
400             diag_printf("RedBoot> ");
401             prompt = false;
402         }
403 #if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0
404         cmd_history = true;  // Enable history collection
405 #endif
406         res = _rb_gets(line, sizeof(line), CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT);
407 #if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0
408         cmd_history = false;  // Enable history collection
409 #endif
410         if (res == _GETS_TIMEOUT) {
411             // No input arrived
412         } else {
413 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
414             if (res == _GETS_GDB) {
415                 int dbgchan;
416                 hal_virtual_comm_table_t *__chan;
417                 int i;
418                 // Special case of '$' - need to start GDB protocol
419                 gdb_active = true;
420                 // Mask interrupts on all channels
421                 for (i = 0;  i < CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS;  i++) {
422                     CYGACC_CALL_IF_SET_CONSOLE_COMM(i);
423                     __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
424                     CYGACC_COMM_IF_CONTROL( *__chan, __COMMCTL_IRQ_DISABLE );
425                 }
426    
427                 CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
428
429                 // set up a temporary context that will take us to the trampoline
430                 HAL_THREAD_INIT_CONTEXT(workspace_end,
431                                         breakpoint, trampoline, 0);
432
433                 // switch context to trampoline (get GDB stubs started)
434                 HAL_THREAD_SWITCH_CONTEXT(&saved_context, &workspace_end);
435
436                 gdb_active = false;
437
438                 dbgchan = CYGACC_CALL_IF_SET_DEBUG_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
439                 CYGACC_CALL_IF_SET_CONSOLE_COMM(dbgchan);
440             } else
441 #endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
442             {
443 #ifdef CYGSEM_REDBOOT_FLASH_ALIASES             
444                 expand_aliases(line, sizeof(line));
445 #endif
446                 command = (char *)&line;
447                 if ((*command == '#') || (*command == '=')) {
448                     // Special cases
449                     if (*command == '=') {
450                         // Print line on console
451                         diag_printf("%s\n", &line[2]);
452                     }
453                 } else {
454                     while (strlen(command) > 0) {                   
455                         if ((cmd = parse(&command, &argc, &argv[0])) != (struct cmd *)0) {
456                             // Try to handle aborts - messy because of the stack unwinding...
457                             __mem_fault_handler = error_handler;
458                             if (hal_setjmp(error_jmpbuf)) {
459                                 diag_printf("** command abort - illegal memory access?\n");
460                             } else {
461                                 (cmd->fun)(argc, argv);
462                             }
463                             __mem_fault_handler = 0;
464                         } else {
465                             diag_printf("** Error: Illegal command: \"%s\"\n", argv[0]);
466                         }
467                     }
468                 }
469                 prompt = true;
470             }
471         }
472     }
473 }
474
475 void
476 show_help(struct cmd *cmd, struct cmd *cmd_end, char *which, char *pre)
477 {
478     bool show;
479     int len = 0;
480
481     if (which) {
482         len = strlen(which);
483     }
484     while (cmd != cmd_end) {
485         show = true;
486         if (which && (strncasecmp(which, cmd->str, len) != 0)) {
487             show = false;
488         }
489         if (show) {
490             diag_printf("%s\n  %s %s %s\n", cmd->help, pre, cmd->str, cmd->usage);
491             if ((cmd->sub_cmds != (struct cmd *)0) && (which != (char *)0)) {
492                 show_help(cmd->sub_cmds, cmd->sub_cmds_end, 0, cmd->str);
493             }
494         }
495         cmd++;
496     }
497 }
498
499 void
500 do_help(int argc, char *argv[])
501 {
502     struct cmd *cmd;
503     char *which = (char *)0;
504
505     if (!scan_opts(argc, argv, 1, 0, 0, (void *)&which, OPTION_ARG_TYPE_STR, "<topic>")) {
506         diag_printf("Invalid argument\n");
507         return;
508     }
509     cmd = __RedBoot_CMD_TAB__;
510     show_help(cmd, &__RedBoot_CMD_TAB_END__, which, "");
511     return;
512 }
513
514 static void
515 trampoline(unsigned long entry)
516 {
517     typedef void code_fun(void);
518     code_fun *fun = (code_fun *)entry;
519     unsigned long oldints;
520
521     HAL_DISABLE_INTERRUPTS(oldints);
522
523 #ifdef HAL_ARCH_PROGRAM_NEW_STACK
524     HAL_ARCH_PROGRAM_NEW_STACK(fun);
525 #else
526     (*fun)();
527 #endif
528
529     HAL_THREAD_LOAD_CONTEXT(&saved_context);
530 }
531
532 static void
533 return_to_redboot(int status)
534 {
535     CYGARC_HAL_SAVE_GP();
536
537     return_status = status;
538     HAL_THREAD_LOAD_CONTEXT(&saved_context);
539     // never returns
540
541     // need this to balance above CYGARC_HAL_SAVE_GP on
542     // some platforms. It will never run, though.
543     CYGARC_HAL_RESTORE_GP();
544 }
545
546 void
547 do_go(int argc, char *argv[])
548 {
549     int i, cur, num_options;
550     unsigned long entry;
551     unsigned long oldints;
552     bool wait_time_set;
553     int  wait_time, res;
554     bool cache_enabled = false;
555 #ifdef CYGPKG_IO_ETH_DRIVERS
556     bool stop_net = false;
557 #endif
558     struct option_info opts[3];
559     char line[8];
560     hal_virtual_comm_table_t *__chan;
561
562     __mem_fault_handler = 0; // Let GDB handle any faults directly
563     entry = entry_address;  // Default from last 'load' operation
564     init_opts(&opts[0], 'w', true, OPTION_ARG_TYPE_NUM,
565               (void *)&wait_time, (bool *)&wait_time_set, "wait timeout");
566     init_opts(&opts[1], 'c', false, OPTION_ARG_TYPE_FLG,
567               (void *)&cache_enabled, (bool *)0, "go with caches enabled");
568     num_options = 2;
569 #ifdef CYGPKG_IO_ETH_DRIVERS
570     init_opts(&opts[2], 'n', false, OPTION_ARG_TYPE_FLG,
571               (void *)&stop_net, (bool *)0, "go with network driver stopped");
572     num_options++;
573 #endif
574
575     CYG_ASSERT(num_options <= NUM_ELEMS(opts), "Too many options");
576
577     if (!scan_opts(argc, argv, 1, opts, num_options, (void *)&entry, OPTION_ARG_TYPE_NUM, "starting address"))
578     {
579         return;
580     }
581     if (entry == (unsigned long)NO_MEMORY) {
582         diag_printf("No entry point known - aborted\n");
583         return;
584     }
585     if (wait_time_set) {
586         int script_timeout_ms = wait_time * 1000;
587 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
588         unsigned char *hold_script = script;
589         script = (unsigned char *)0;
590 #endif
591         diag_printf("About to start execution at %p - abort with ^C within %d seconds\n",
592                     (void *)entry, wait_time);
593         while (script_timeout_ms >= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT) {
594             res = _rb_gets(line, sizeof(line), CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT);
595             if (res == _GETS_CTRLC) {
596 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
597                 script = hold_script;  // Re-enable script
598 #endif
599                 return;
600             }
601             script_timeout_ms -= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT;
602         }
603     }
604
605     // Mask interrupts on all channels
606     cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
607     for (i = 0;  i < CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS;  i++) {
608         CYGACC_CALL_IF_SET_CONSOLE_COMM(i);
609         __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
610         CYGACC_COMM_IF_CONTROL( *__chan, __COMMCTL_IRQ_DISABLE );
611     }
612     CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
613
614     __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
615     CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_ENABLE_LINE_FLUSH);
616
617 #ifdef CYGPKG_IO_ETH_DRIVERS
618     if (stop_net)
619         eth_drv_stop();
620 #endif
621        
622     HAL_DISABLE_INTERRUPTS(oldints);
623     HAL_DCACHE_SYNC();
624     if (!cache_enabled) {
625         HAL_ICACHE_DISABLE();
626         HAL_DCACHE_DISABLE();
627         HAL_DCACHE_SYNC();
628     }
629     HAL_ICACHE_INVALIDATE_ALL();
630     HAL_DCACHE_INVALIDATE_ALL();
631     // set up a temporary context that will take us to the trampoline
632     HAL_THREAD_INIT_CONTEXT(workspace_end, entry, trampoline, 0);
633
634     // switch context to trampoline
635     HAL_THREAD_SWITCH_CONTEXT(&saved_context, &workspace_end);
636
637     // we get back here by way of return_to_redboot()
638
639     // undo the changes we made before switching context
640     if (!cache_enabled) {
641         HAL_ICACHE_ENABLE();
642         HAL_DCACHE_ENABLE();
643     }
644
645     CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_DISABLE_LINE_FLUSH);
646
647     HAL_RESTORE_INTERRUPTS(oldints);
648
649     diag_printf("\nProgram completed with status %d\n", return_status);
650 }
651
652 #ifdef HAL_PLATFORM_RESET
653 void
654 do_reset(int argc, char *argv[])
655 {
656     diag_printf("... Resetting.");
657     CYGACC_CALL_IF_DELAY_US(2*100000);
658     diag_printf("\n");
659     CYGACC_CALL_IF_RESET();
660     diag_printf("!! oops, RESET not working on this platform\n");
661 }
662 #endif
663
664 #ifdef CYGSEM_REDBOOT_VARIABLE_BAUD_RATE
665 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
666 #include <flash_config.h>
667 #endif
668
669 static int
670 set_comm_baud_rate(hal_virtual_comm_table_t *chan, int rate)
671 {
672     int current_rate;
673
674     current_rate = CYGACC_COMM_IF_CONTROL(*chan, __COMMCTL_GETBAUD);
675     if (rate != current_rate)
676         return CYGACC_COMM_IF_CONTROL(*chan, __COMMCTL_SETBAUD, rate);
677
678     return 0;
679 }
680
681 int
682 set_console_baud_rate(int rate)
683 {
684     int ret = -1;
685 #ifdef CYGPKG_REDBOOT_ANY_CONSOLE
686     if (!console_selected) {
687         int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
688         int i;
689         // Set baud for all channels
690         for (i = 0;  i < CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS;  i++) {
691             CYGACC_CALL_IF_SET_CONSOLE_COMM(i);
692             ret = set_comm_baud_rate(CYGACC_CALL_IF_CONSOLE_PROCS(), rate);
693             if (ret < 0)
694                 break;
695         }
696         CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
697     } else
698 #endif
699     ret = set_comm_baud_rate(CYGACC_CALL_IF_CONSOLE_PROCS(), rate);
700
701     if (ret < 0)
702         diag_printf("Setting console baud rate to %d failed\n", rate);
703
704     return ret;
705 }
706
707 static void
708 _sleep(int ms)
709 {
710     int i;
711     for (i = 0;  i < ms;  i++) {
712         CYGACC_CALL_IF_DELAY_US((cyg_int32)1000);
713     }
714 }
715
716 void
717 do_baud_rate(int argc, char *argv[])
718 {
719     int new_rate, ret, old_rate;
720     bool new_rate_set;
721     hal_virtual_comm_table_t *__chan;
722     struct option_info opts[1];
723 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
724     struct config_option opt;
725 #endif
726
727     init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,
728               (void *)&new_rate, (bool *)&new_rate_set, "new baud rate");
729     if (!scan_opts(argc, argv, 1, opts, 1, 0, 0, "")) {
730         return;
731     }
732     __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
733     if (new_rate_set) {
734         diag_printf("Baud rate will be changed to %d - update your settings\n", new_rate);
735         _sleep(500);  // Give serial time to flush
736         old_rate = CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_GETBAUD);
737         ret = set_console_baud_rate(new_rate);
738         if (ret < 0) {
739             if (old_rate > 0) {
740                 // Try to restore
741                 set_console_baud_rate(old_rate);
742                 _sleep(500);  // Give serial time to flush
743                 diag_printf("\nret = %d\n", ret);
744             }
745             return;  // Couldn't set the desired rate
746         }
747         // Make sure this new rate works or back off to previous value
748         // Sleep for a few seconds, then prompt to see if it works
749         _sleep(3000);  // Give serial time to flush
750         if (!verify_action_with_timeout(5000, "Baud rate changed to %d", new_rate)) {
751             _sleep(500);  // Give serial time to flush
752             set_console_baud_rate(old_rate);
753             _sleep(500);  // Give serial time to flush
754             return;
755         }
756 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
757         opt.type = CONFIG_INT;
758         opt.enable = (char *)0;
759         opt.enable_sense = 1;
760         opt.key = "console_baud_rate";
761         opt.dflt = new_rate;
762         flash_add_config(&opt, true);
763 #endif
764     } else {
765         ret = CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_GETBAUD);
766         diag_printf("Baud rate = ");
767         if (ret <= 0) {
768             diag_printf("unknown\n");
769         } else {
770             diag_printf("%d\n", ret);
771         }
772     }
773 }
774 #endif
775
776 //
777 // Validate an address to see if it is within any known RAM area
778 //
779 bool
780 valid_address(unsigned char *addr)
781 {
782     int seg;
783
784     for (seg = 0;  seg < CYGBLD_REDBOOT_MAX_MEM_SEGMENTS;  seg++) {
785         if (mem_segments[seg].start != NO_MEMORY) {
786             if ((addr >= mem_segments[seg].start) && (addr < mem_segments[seg].end)) {
787                 return true;
788             }
789         }
790     }
791     return false;
792 }
Note: See TracBrowser for help on using the browser.