From 5de80e9c48dadbc669009d01b19f5ea86723db82 Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Tue, 2 Sep 2008 19:40:35 +0000 Subject: [PATCH] Add command line interface --- second/Makefile | 4 +- second/cli.c | 232 ++++++++++++++++++++++++++++++++++++++++++++++++ second/cli.h | 7 ++ second/config.c | 18 +++- 4 files changed, 257 insertions(+), 4 deletions(-) create mode 100644 second/cli.c create mode 100644 second/cli.h diff --git a/second/Makefile b/second/Makefile index 807a102..582ed1e 100644 --- a/second/Makefile +++ b/second/Makefile @@ -33,13 +33,13 @@ LIBS = $(OPT_LIBS) \ LS = ls AWK = awk -HEADERS = arch.h bank.h bootenv.h bootinfo.h bootx.h console.h driver.h enter_kernel030.h enter_kernel040.h enter_kernel.h enter_kernelnoMMU.h switch_to_PPC.h head.h keyboard.h load.h misc.h MMU030.h MMU040.h serial.h vga.h config.h copymem.i +HEADERS = arch.h bank.h bootenv.h bootinfo.h bootx.h console.h driver.h enter_kernel030.h enter_kernel040.h enter_kernel.h enter_kernelnoMMU.h switch_to_PPC.h head.h keyboard.h load.h misc.h MMU030.h MMU040.h serial.h vga.h config.h copymem.i cli.h SOURCES = head.S main.c console.c \ font_8x16.c \ misc.c bank.c arch.c \ load.c serial.c vga.c driver.c \ - enter_kernel.c config.c + enter_kernel.c config.c cli.c SOURCES_CLI = keyboard.c diff --git a/second/cli.c b/second/cli.c new file mode 100644 index 0000000..0d513d3 --- /dev/null +++ b/second/cli.c @@ -0,0 +1,232 @@ +/* + * + * (c) 2008 Laurent Vivier + * + */ + +#include +#include +#include + +#include + +#include "vga.h" +#include "console.h" +#include "arch.h" +#include "cli.h" + +#define COMMAND_LINE_LENGTH 256 + +typedef int (*command_handler)(int argc, char **argv); + +struct command_interface { + char *name; + command_handler handler; + char *help; +}; + +static struct command_interface command[]; +static int get_command(char *name); + +static int do_loop; + +static int exit_handler(int argc, char **argv) +{ + do_loop = 0; + return 0; +} + +static int help_handler(int argc, char **argv) +{ + int index; + + if (argc != 2) + { + printf("help needs one parameter\n"); + printf("Available commands are:\n"); + for (index = 0; command[index].name; index++) + { + printf("%s", command[index].name); + if (command[index].help) + printf(" %s", command[index].help); + printf("\n"); + } + return 1; + } + + index = get_command(argv[1]); + if (index == -1) + { + printf("Unknown command: %s\n", argv[1]); + return 1; + } + + if (command[index].help == NULL) + { + printf("No help available for %s\n", argv[1]); + return 2; + } + + printf("%s\n", command[index].help); + + return 0; +} + +static int vga_handler(int argc, char **argv) +{ + if (argc != 2) + { + printf("vga needs one parameter to set the display mode\n"); + return 1; + } + vga_init(argv[1]); + return 0; +} + +static int modem_handler(int argc, char **argv) +{ + return 0; +} + +static int printer_handler(int argc, char **argv) +{ + return 0; +} + +static int gestaltid_handler(int argc, char **argv) +{ + if (argc != 2) + { + printf("gestaltID needs a parameter\n"); + return 1; + } + machine_id = strtol(argv[1], NULL, 0); + + printf("New gestalt ID is %ld\n", machine_id); + + return 0; +} + +#define COMMAND_NB 7 +static struct command_interface command[COMMAND_NB]; +#define NEW_COMMAND(a,b,c) \ + do { \ + if (i < COMMAND_NB) { \ + command[i].name = a; \ + command[i].handler = b; \ + command[i].help = c; \ + i++; \ + } \ + } while(0) + + +static void cli_init(void) +{ + int i = 0; + + /* because of GOT */ + + NEW_COMMAND("exit", exit_handler, "exit from interpreter"); + NEW_COMMAND("help", help_handler, "give help of commands"); + NEW_COMMAND("vga", vga_handler, "set display mode"); + NEW_COMMAND("modem", modem_handler, + "set modem serial port configuation"); + NEW_COMMAND("printer", printer_handler, + "set printer serial port configuration"); + NEW_COMMAND("gestaltID", gestaltid_handler, "set machine gestalt ID"); + NEW_COMMAND(NULL, NULL, NULL); +} + +static int get_command(char *name) +{ + int i; + + for (i = 0; command[i].name; i++) + { + if (strcmp(name, command[i].name) == 0) + return i; + } + + return -1; +} + +static int skip_blank(char *line, int i) +{ + while (line[i] == ' ' || line[i] == '\t') + i++; + return i; +} + +static int skip_word(char *line, int i) +{ + while (line[i] != ' ' && line[i] != '\t' && line[i]) + i++; + return i; +} + +static int split_line(char *line, char ***argv) +{ + int i, j; + int argc; + char **words; + + /* how many words ? */ + + argc = 0; + for (i = skip_blank(line, 0); line[i]; i = skip_blank(line, i)) + { + i = skip_word(line, i); + argc++; + } + + words = (char**)malloc(argc * sizeof(char*)); + + /* where are the words ? */ + + i = skip_blank(line, 0); + j = 0; + while(1) + { + words[j++] = line + i; + i = skip_word(line, i); + if (line[i] == 0) + break; + line[i++] = 0; + i = skip_blank(line, i); + } + *argv = words; + return argc; +} + +void cli(void) +{ + char line[COMMAND_LINE_LENGTH]; + int argc; + char **argv; + int index; + + do_loop = 1; + + cli_init(); + console_clear(); + while(do_loop) + { + printf("emile> "); + memset(line, 0, COMMAND_LINE_LENGTH); + emile_edit(line, COMMAND_LINE_LENGTH); + printf("\n"); + argc = split_line(line, &argv); + if (argc > 0) + { + index = get_command(argv[0]); + if (index == -1) + printf("Unknown command: %s\n", argv[0]); + else + { + command[index].handler(argc, argv); + free(argv); + } + } + } + console_clear(); +} diff --git a/second/cli.h b/second/cli.h new file mode 100644 index 0000000..ab85ef5 --- /dev/null +++ b/second/cli.h @@ -0,0 +1,7 @@ +/* + * + * (c) 2008 Laurent Vivier + * + */ + +extern void cli(void); diff --git a/second/config.c b/second/config.c index 82d8ed8..7598741 100644 --- a/second/config.c +++ b/second/config.c @@ -16,6 +16,7 @@ #include "config.h" #if defined(USE_CLI) && defined(__LINUX__) #include "console.h" +#include "cli.h" #endif #include "arch.h" #include "misc.h" @@ -28,12 +29,13 @@ extern int boot_unit; #endif #define MSG_STATE_0 console_set_cursor_position(win.l + win.h + 1, 1); \ - printf(" Press 'b' or [RETURN] to boot or 'e' to edit\n"); + printf(" Press 'b' or [RETURN] to boot or 'e' to edit\n"); \ + printf(" Press 'c' to enter command line interpreter \n"); #define MSG_STATE_1 console_set_cursor_position(win.l + win.h + 1, 1); \ printf(" Press 'b' to boot, 'e' or [RETURN] to edit \n" \ " Press 'd' to delete, 'n' to create \n" \ - " Press [ESC] to go back \n"); + " Press 'c' to enter CLI or [ESC] to go back \n"); #define MSG_CLEAN console_set_cursor_position(win.l + win.h + 1, 1); \ printf(" \n" \ @@ -341,6 +343,12 @@ int read_config(emile_l2_header_t* info, emile_config_t *econfig) state = 1; MSG_STATE_1 break; + case 'c': + cli(); + console_set_cursor_position(1, len); + printf("%s\n", line); + MSG_STATE_0 + break; } break; case 1: /* select parameter */ @@ -383,6 +391,12 @@ int read_config(emile_l2_header_t* info, emile_config_t *econfig) MSG_CLEAN state = 2; break; + case 'c': + cli(); + console_set_cursor_position(1, len); + printf("%s\n", line); + MSG_STATE_1 + break; } break; case 2: /* edit parameter */