/* * vivi/lib/command.c: * - to support user commands on the boot loader * * Copyright (C) 2001 MIZI Research, Inc. * * This program 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 Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * Author: Janghoon Lyu * Date : $Date: 2004/02/04 06:22:25 $ * * $Revision: 1.1.1.1 $ * * * History * * 2001-12-23: Janghoon Lyu * - Initial code * - Base on bootldr/bootldr.c * * 2002-02-23: Janghoon Lyu * - Add flash commands * * 2002-07-13: Janghoon Lyu * */ #include #include "serial.h" #include "UART_printf.h" #include "load_file.h" #include "boot_interface.h" enum ParseState { PS_WHITESPACE, PS_TOKEN, PS_STRING, PS_ESCAPE }; #define MAX_CMDBUF_SIZE 80 #define CTL_CH(c) ((c) - 'a' + 1) void getcmd(char *cmd_buf, unsigned int len); void exec_string(char *buf); void execcmd(int argc, char **argv); void jump(int argc, char **argv) { unsigned int jump_addr; int ret; switch( argc ) { case 0: jump_addr = RAM_BASE; break; case 1: jump_addr = strtoul(argv[0], NULL, 0, &ret); if (ret) { UART_printf("Can't parsing argumets.\n"); return ; } if( (jump_addr & 0x11) != 0 ) { UART_printf("Address must be aligned 4.\n"); return ; } break; default:UART_printf("invalid 'jump' command: too many arguments\n"); return ; } jump_to( jump_addr ); } void serial_term(void) { char cmd_buf[MAX_CMDBUF_SIZE]; UART_printf("Now command shell is starting.\n"); for (;;) { UART_printf("Input command >>"); getcmd(cmd_buf, MAX_CMDBUF_SIZE); /* execute a user command */ if( strcmp( cmd_buf, "quit" ) == 0 ) { UART_printf("Now quit command shell.\n"); break; } if (cmd_buf[0]) exec_string(cmd_buf); } } void getcmd(char *cmd_buf, unsigned int len) { char curpos = 0; /* current position - index into cmd_buf */ char c; int cmd_echo = 1; /* Clear out the buffer */ memset(cmd_buf, 0, MAX_CMDBUF_SIZE); for (;;) { c = UART_getchar(); switch (c) { case 0x08: case 0x06: case 0x07: case 0x7E: case 0x7F: /* backspace or delete */ /* we're not at the beginning of the line */ if (curpos) { curpos--; UART_putchar(0x08); /* go backwards */ UART_putchar(' '); /* overwrite the char */ UART_putchar(0x08); /* go back again */ } cmd_buf[curpos] = '\0'; break; case '\r': case '\n': case '\0': UART_putchar('\r'); UART_putchar('\n'); goto end_cmd; case CTL_CH('x'): curpos = 0; break; default: if (curpos < MAX_CMDBUF_SIZE) { cmd_buf[curpos] = c; /* echo it back out to the screen */ if (cmd_echo) UART_putchar(c); curpos++; } break; } } end_cmd: UART_printf("COMMAND: %s\n\r", cmd_buf); } /* * Parse user command line */ void parseargs(char *argstr, int *argc_p, char **argv, char** resid) { int argc = 0; char c; enum ParseState stackedState; enum ParseState lastState = PS_WHITESPACE; /* tokenize the argstr */ while ((c = *argstr) != 0) { enum ParseState newState; if (c == ';' && lastState != PS_STRING && lastState != PS_ESCAPE) break; if (lastState == PS_ESCAPE) { newState = stackedState; } else if (lastState == PS_STRING) { if (c == '"') { newState = PS_WHITESPACE; *argstr = 0; } else { newState = PS_STRING; } } else if ((c == ' ') || (c == '\t')) { /* whitespace character */ *argstr = 0; newState = PS_WHITESPACE; } else if (c == '"') { newState = PS_STRING; *argstr++ = 0; argv[argc++] = argstr; } else if (c == '\\') { stackedState = lastState; newState = PS_ESCAPE; } else { /* token */ if (lastState == PS_WHITESPACE) { argv[argc++] = argstr; } newState = PS_TOKEN; } lastState = newState; argstr++; } argv[argc] = NULL; if (argc_p != NULL) *argc_p = argc; if (*argstr == ';') { *argstr++ = '\0'; } *resid = argstr; } void execcmd(int argc, char **argv) { if( strcmp( argv[0], "load" ) == 0 ) { if( strcmp( argv[1], "ram" ) == 0) load_ram( argc-1, argv+1 ); else if( strcmp( argv[1], "flash" ) == 0 ) load_flash( argc-1, argv+1 ); else { UART_printf("Could not found '%s' sub-command\n", argv[0]); UART_printf("If you want to konw available commands, type 'help'\n"); } } else if( strcmp( argv[0], "jump" ) == 0 ) jump( argc-1, argv+1 ); else if( strcmp( argv[0], "help" ) == 0 ) { UART_printf( "\nload |- flash \t--Load a file to Flash\n" " |- ram [addr [length]] \t-- Load a file to RAM \n" "\njump [addr] \t-- jump to addr(default value:RAM_BASE) and execute .\n" "\nquit \t--quit command shell .\n" "\nhelp \t--about help .\n" ); } else { UART_printf("The '%s' command is an invilid command.\n" "If you want to konw available commands, type 'help'\n"); } } /* parse and execute a string */ void exec_string(char *buf) { int argc; char *argv[10]; char *resid; while (*buf) { memset(argv, 0, sizeof(argv)); parseargs(buf, &argc, argv, &resid); if (argc > 0) execcmd(argc, (char **)argv); buf = resid; } }