/* * ui.c - User Interface for Coldfire Boot * * Copyright (C) 1999 Rob Scott (rscott@mtrob.fdns.net) * All rights reserved. * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #include "function.h" #include "prototypes.h" extern unsigned int downloadPort; extern unsigned int image_size; extern unsigned char *xfer_addr; extern unsigned char *down_addr; extern unsigned char *dest_addr; extern unsigned char *source_addr; extern unsigned int function; /* For the usage() function */ extern char ident[]; extern char copyright[]; unsigned char *dump_addr; /* Internal defines */ int valid; /* Valid command found */ int eol; /* End of text line */ unsigned char *mem_dump(); void mem_copy(); void boot_image(); void print_hex(unsigned int value); void usage() { dprintf("Coldfire Linux Loader\n"); dprintf(" Platform: %s\n", ident); dprintf(" %s\n", copyright); dprintf("Commands available:\n"); dprintf(" b - boot default image\n"); dprintf(" m [addr] - memory dump at addr\n"); dprintf(" g [xfer_addr] - go to xfer_addr\n"); dprintf(" l [down_addr] [port] - load image from port\n"); dprintf(" c [source_addr] [dest_addr] [size] - copy memory\n"); dprintf(" d [source_addr] [dest_addr] [size] - decompress image\n"); dprintf(" x [down_addr] [dest_addr] [xfer_addr] [port] - cmds l, d, g\n"); dprintf(" z [source_addr] [dest_addr] [xfer_addr] - cmds d, g\n"); dprintf(" Where:\n"); dprintf(" xfer_addr: hex address to start running at\n"); dprintf(" down_addr: hex address of downloaded image\n"); dprintf(" dest_addr: hex address of image destination\n"); dprintf(" source_addr: hex address of compressed image\n"); dprintf(" size: size of compressed image\n"); dprintf(" port: 0 = /dev/ttyS0, 1 = /dev/ttyS1\n"); dprintf(" Default values for paramaters:\n"); dprintf(" down_addr: %x\n", down_addr); dprintf(" source_addr: %x\n", source_addr); dprintf(" dest_addr: %x\n", dest_addr); dprintf(" xfer_addr: %x\n", xfer_addr); dprintf(" size: %d\n", image_size); dprintf(" downloadPort: %d\n", downloadPort); } char get_char() { while (!rs_is_char()); return((char)rs_get_char()); } /* * gets - get a character stream from the console, with editing */ char *gets(char *string) { char rec_char; /* Place for incoming chars */ int index = 0; /* String index */ int done = 0; /* Set when CR rec'd */ while (!done) { rec_char = get_char(); switch(rec_char) { case '\b': /* handle deletes, either BS or DEL key */ case 0x7f: if(index > 0) { /* Don't delete beyond buffer! */ index--; dprintf("\b \b"); } break; case '\r': /* Handle CR or LF */ case '\n': dprintf("\n"); done = 1; break; default: if (rec_char >= ' ') { string[index++] = rec_char; console_nextPut(rec_char); /* Echo data */ } break; } } string[index] = 0; /* Terminate string */ return(string); } /* * translate from ascii to hex * */ unsigned int a2h(char input) { if (input >= '0' && input <= '9') return (input & 0x0f); if (input >= 'a' && input <= 'f') return ((input - 'a') + 10); if (input >= 'A' && input <= 'F') return ((input - 'A') + 10); dprintf("Invalid character in numeric value: %c\n", (int)input); valid = 0; function = DO_NOTHING; return 0; } unsigned int get_num(char **stringP, unsigned int default_value) { int count; unsigned int value; char *string; char input; count = 0; value = 0; string = *stringP; while(valid && count < 8 && !eol) { input = *string++; switch ((int)input) { case 0: /* End of string */ eol = 1; break; case 'x' : if (count > 1) { dprintf("Invalid character in numeric value: %c\n", (int)input); valid = 0; function = DO_NOTHING; } break; case ' ' : /* delimit numeric string */ if (count > 0) count = 8; /* done with number */ break; default: value = (value << 4) | a2h(input); count++; break; } } if (count == 0 || valid == 0) value = default_value; *stringP = string; return(value); } int parse (char *string) { int index; char parse_char; unsigned int value; eol = 0; index = 0; value = downloadPort; /* Note function is set to DO_NOTHING if invalid chars found in numbers */ while (!eol) { parse_char = *string++; switch((int)parse_char) { case '?' : usage(); function = DO_NOTHING; eol = 1; break; case 'l' : /* load */ function = DO_LOAD; valid = 1; /* will be set to zero, if number not ok */ down_addr = (unsigned char *)get_num(&string, (unsigned int)down_addr); if (eol == 0) value = get_num(&string, downloadPort); if (value > 1) { dprintf("Invalid port: %d\n", value); valid = 0; } else { downloadPort = value; } eol = 1; break; case 'd' : /* Decompress */ function = DO_DECOMPRESS; valid = 1; /* will be set to zero, if number not ok */ source_addr = (unsigned char *)get_num(&string, (unsigned int)source_addr); if (eol == 0) dest_addr = (unsigned char *)get_num(&string, (unsigned int)dest_addr); if (eol == 0) image_size = get_num(&string, image_size); eol = 1; break; case 'g' : /* Go */ function = DO_GO; valid = 1; xfer_addr = (unsigned char *)get_num(&string, (unsigned int)xfer_addr); eol = 1; break; case 'x' : /* load, decompress and go */ function = DO_ALL; valid = 1; down_addr = (unsigned char *)get_num(&string, (unsigned int)down_addr); if (eol == 0) dest_addr = (unsigned char *)get_num(&string, (unsigned int)dest_addr); if (eol == 0) xfer_addr = (unsigned char *)get_num(&string, (unsigned int)xfer_addr); if (eol == 0) value = get_num(&string, downloadPort); if (value > 1) { dprintf("Invalid port: %d\n", downloadPort); valid = 0; } else { downloadPort = value; } eol = 1; break; case 'z' : /* decompress and go */ function = DO_DECOMP_GO; valid = 1; source_addr = (unsigned char *)get_num(&string, (unsigned int)source_addr); if (eol == 0) dest_addr = (unsigned char *)get_num(&string, (unsigned int)dest_addr); if (eol == 0) xfer_addr = (unsigned char *)get_num(&string, (unsigned int)xfer_addr); eol = 1; break; case 'm' : /* Memory dump */ function = DO_MEM_DUMP; valid = 1; dump_addr = (unsigned char *)get_num(&string, (unsigned int)dump_addr); eol = 1; break; case 'c' : /* copy memory */ function = DO_COPY_MEM; valid = 1; source_addr = (unsigned char *)get_num(&string, (unsigned int)source_addr); if (eol == 0) dest_addr = (unsigned char *)get_num(&string, (unsigned int)dest_addr); if (eol == 0) image_size = get_num(&string, image_size); eol = 1; break; case 'b' : /* boot an image */ valid = 1; function = DO_BOOT_IMAGE; eol = 1; break; case ' ' : /* ignore leading spaces */ eol = 0; break; case 0 : /* ignore zero length lines */ eol = 1; function = DO_NOTHING; break; default: dprintf("Unknown command - try ?\n"); eol = 1; function = DO_NOTHING; break; } } return(valid); } void ui() { char string[80]; int valid; valid = 0; while (!valid) { dprintf("colilo>"); gets(string); valid = parse(string); /* perform locally supported functions */ switch (function) { case '?' : function = DO_NOTHING; break; case DO_MEM_DUMP: dump_addr = mem_dump(dump_addr); /* Cause main.c to not perform any functions */ function = DO_NOTHING; break; case DO_COPY_MEM: mem_copy(source_addr, dest_addr, image_size); /* Cause main.c to not perform any functions */ function = DO_NOTHING; break; /* These should be defined in the arch. specific 'board.c' file #define BOOT_SRC 0xffe40000 #define BOOT_DEST 0x00000000 #define BOOT_XFER 0x00000000 #define BOOT_SIZE 475740 */ case DO_BOOT_IMAGE: /* Do a decompress and go command */ /* Use boot image parameters */ // image_size = (unsigned int)BOOT_SIZE; // xfer_addr = (unsigned char *)BOOT_XFER; // dest_addr = (unsigned char *)BOOT_DEST; // source_addr = (unsigned char *)BOOT_SRC; function = DO_DECOMP_GO; break; default: break; } } } /*****************************************************************************/ /* Local functions, not found in main.c */ void mem_copy(unsigned char *src, unsigned char *dest, int size ) { int i; for (i = 0; i < size; i++) { *dest++ = *src++; } } unsigned char *mem_dump(unsigned char *dump) { int i, j; unsigned int addr, value; for (j = 0; j < 16; j++) { addr = (unsigned int) dump; print_hex(addr); dprintf(": "); for (i = 0; i < 4; i++) { value = *((unsigned int *) dump); print_hex(value); dprintf(" "); dump += 4; } dprintf("\n"); } return(dump); } /* print zero padded hex integers */ void print_hex(unsigned int value) { int i; unsigned char nibble, byte, out; for (i = 24; i >= 0; i = i - 8) { byte = (value >> i) & 0xff; nibble = (byte >> 4) & 0x0f; out = nibble > 9 ? nibble - 10 + 'a' : nibble + '0'; dprintf("%c", out); nibble = byte & 0x0f; out = nibble > 9 ? nibble - 10 + 'a' : nibble + '0'; dprintf("%c", out); } } /*****************************************************************************/