]> git.kernelconcepts.de Git - karo-tx-redboot.git/blobdiff - packages/redboot/v2_0/src/parse.c
unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / redboot / v2_0 / src / parse.c
index bfae30726661cf3fc70c451b3f626786086e7a64..41c3e033a312d787adda85ca1fd16e71b4d0f2d0 100644 (file)
@@ -9,6 +9,7 @@
 // -------------------------------------------
 // This file is part of eCos, the Embedded Configurable Operating System.
 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2004, 2005, 2006 eCosCentric Limited
 //
 // eCos is free software; you can redistribute it and/or modify it under
 // the terms of the GNU General Public License as published by the Free
 //
 // This exception does not invalidate any other reasons why a work based on
 // this file might be covered by the GNU General Public License.
-//
-// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
-// at http://sources.redhat.com/ecos/ecos-license/
 // -------------------------------------------
 //####ECOSGPLCOPYRIGHTEND####
 //==========================================================================
 //#####DESCRIPTIONBEGIN####
 //
 // Author(s):    gthomas
-// Contributors: gthomas
+// Contributors: gthomas, eCosCentric
 // Date:         2000-07-14
 // Purpose:      
 // Description:  
@@ -193,6 +191,97 @@ cmd_usage(struct cmd *tab, struct cmd *tabend, char *prefix)
     }
 }
 
+//
+// Handle illegal memory accesses (and other abort conditions)
+//
+static hal_jmp_buf error_jmpbuf;
+static cyg_bool redboot_exec_call = false;
+#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
+__externC void* volatile __mem_fault_handler;
+
+static void error_handler(void)
+{
+    hal_longjmp(error_jmpbuf, 1);
+}
+#endif
+
+// Routine to allow code to invoke RedBoot commands. This is useful
+// during initialization and in platform specific code.
+//
+// Call it like this:
+//
+// result = redboot_exec( "load", "-m", "file", "foo", 0 );
+//
+// Note the terminating zero. The result will be zero if the command
+// succeeded, and <0 if something went wrong.
+
+#define ARGV_MAX        20
+int redboot_exec( char *command, ... )
+{
+    int argc;
+    char *argv[ARGV_MAX+1];
+    va_list ap;
+    struct cmd *cmd;
+    int result = 0;
+    
+    va_start(ap, command);
+
+    argv[0] = command;
+    for( argc = 1; argc < ARGV_MAX; argc++ )
+    {
+        char *arg = va_arg(ap, char *);
+        if( arg == 0 )
+            break;
+        argv[argc] = arg;
+    }
+    argv[argc] = NULL;
+
+    if(( cmd = cmd_search(__RedBoot_CMD_TAB__, &__RedBoot_CMD_TAB_END__, command) ))
+    {
+        // Try to handle aborts - messy because of the stack unwinding...
+#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
+        __mem_fault_handler = error_handler;
+#endif
+        redboot_exec_call = true;
+        if (hal_setjmp(error_jmpbuf))
+            result = -1;
+        else
+            (cmd->fun)(argc, argv);
+
+        redboot_exec_call = false;
+#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
+        __mem_fault_handler = 0;
+#endif
+    }
+    else
+        result = -1;
+    
+    va_end(ap);
+
+    return result;
+}
+
+externC void err_printf(const char *fmt, ... )
+{
+    va_list ap;
+    
+    va_start(ap, fmt);
+
+    diag_vprintf( fmt, ap );
+
+    va_end(ap);
+
+    // If we are not in redboot_exec() just return as usual. If we are
+    // inside a call to redboot_exec(), longjump out to terminate the command.
+    
+    if( redboot_exec_call )
+    {
+        diag_printf("err_printf: aborting command\n");
+        hal_longjmp(error_jmpbuf, 1);
+    }
+}
+
+
 // Option processing
 
 // Initialize option table entry (required because these entries
@@ -231,7 +320,7 @@ scan_opts(int argc, char *argv[], int first,
     struct option_info *opt;
 
     if (def_arg && (def_arg_type == OPTION_ARG_TYPE_STR)) {
-        *(char **)def_arg = (char *)0;
+        *(char **)def_arg = NULL;
     }
     opt = opts;
     for (j = 0;  j < num_opts;  j++, opt++) {
@@ -257,7 +346,7 @@ scan_opts(int argc, char *argv[], int first,
             for (j = 0;  j < num_opts;  j++, opt++) {
                 if (c == opt->flag) {
                     if (opt->arg_set && *opt->arg_set) {
-                        diag_printf("** Error: %s already specified\n", opt->name);
+                           diag_printf("** Error: option '-%c' already specified\n", opt->flag);
                         ok = false;
                     }
                     if (opt->takes_arg) {