hdt: Rewrite DMI module using a new syntax for the CLI
authorPierre-Alexandre Meyer <pierre@mouraf.org>
Thu, 19 Mar 2009 03:22:58 +0000 (20:22 -0700)
committerPierre-Alexandre Meyer <pierre@mouraf.org>
Thu, 19 Mar 2009 03:27:11 +0000 (20:27 -0700)
Impact: Start refactoring the CLI.

In order to have an extensible CLI, the commands handling needs to be
refactored. This patch starts the migration by refactoring the DMI
module.

Note that the core of the new commands parser has been implemented.
Adapting other modules to use it simply requires to declare
new structures that maps the command string to the callback.

Signed-off-by: Pierre-Alexandre Meyer <pierre@mouraf.org>
com32/hdt/hdt-cli-dmi.c
com32/hdt/hdt-cli.c
com32/hdt/hdt-cli.h

index 0fe0845..4ec242d 100644 (file)
  * -----------------------------------------------------------------------
  */
 
-#include "hdt-cli.h"
-#include "hdt-common.h"
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <errno.h>
 
-static void show_dmi_modules(struct s_hardware *hardware)
+#include "hdt-cli.h"
+#include "hdt-common.h"
+
+static void show_dmi_modules(int argc, char** argv,
+                             struct s_hardware *hardware)
 {
   char available_dmi_commands[1024];
   memset(available_dmi_commands, 0, sizeof(available_dmi_commands));
@@ -80,16 +82,18 @@ static void show_dmi_modules(struct s_hardware *hardware)
   printf("Available DMI modules: %s\n", available_dmi_commands);
 }
 
-static void show_dmi_help(struct s_hardware *hardware)
+static void show_dmi_help(int argc, char** argv,
+                          struct s_hardware *hardware)
 {
   more_printf("Show supports the following commands : \n");
   more_printf(" %s\n", CLI_SHOW_LIST);
   more_printf(" <module_name>\n");
   more_printf(" -\n");
-  show_dmi_modules(hardware);
+  show_dmi_modules(0, NULL, hardware);
 }
 
-static void show_dmi_base_board(struct s_hardware *hardware)
+static void show_dmi_base_board(int argc, char** argv,
+                                struct s_hardware *hardware)
 {
   if (hardware->dmi.base_board.filled == false) {
     printf("Base_board module not available\n");
@@ -113,7 +117,8 @@ static void show_dmi_base_board(struct s_hardware *hardware)
   }
 }
 
-static void show_dmi_system(struct s_hardware *hardware)
+static void show_dmi_system(int argc, char** argv,
+                            struct s_hardware *hardware)
 {
   if (hardware->dmi.system.filled == false) {
     printf("System module not available\n");
@@ -131,7 +136,8 @@ static void show_dmi_system(struct s_hardware *hardware)
   more_printf(" Family       : %s\n", hardware->dmi.system.family);
 }
 
-static void show_dmi_bios(struct s_hardware *hardware)
+static void show_dmi_bios(int argc, char** argv,
+                          struct s_hardware *hardware)
 {
   if (hardware->dmi.bios.filled == false) {
     printf("Bios module not available\n");
@@ -176,7 +182,8 @@ static void show_dmi_bios(struct s_hardware *hardware)
 
 }
 
-static void show_dmi_chassis(struct s_hardware *hardware)
+static void show_dmi_chassis(int argc, char** argv,
+                             struct s_hardware *hardware)
 {
   if (hardware->dmi.chassis.filled == false) {
     printf("Chassis module not available\n");
@@ -208,7 +215,8 @@ static void show_dmi_chassis(struct s_hardware *hardware)
         hardware->dmi.chassis.nb_power_cords);
 }
 
-static void show_dmi_battery(struct s_hardware *hardware)
+static void show_dmi_battery(int argc, char** argv,
+                             struct s_hardware *hardware)
 {
   if (hardware->dmi.battery.filled == false) {
     printf("Battery module not available\n");
@@ -239,7 +247,8 @@ static void show_dmi_battery(struct s_hardware *hardware)
         hardware->dmi.battery.oem_info);
 }
 
-static void show_dmi_cpu(struct s_hardware *hardware)
+static void show_dmi_cpu(int argc, char** argv,
+                         struct s_hardware *hardware)
 {
   if (hardware->dmi.processor.filled == false) {
     printf("Processor module not available\n");
@@ -295,10 +304,16 @@ static void show_dmi_cpu(struct s_hardware *hardware)
   }
 }
 
-static void show_dmi_memory_bank(struct s_hardware *hardware, const char *item)
+static void show_dmi_memory_bank(int argc, char** argv,
+                                 struct s_hardware *hardware)
 {
-  long bank = strtol(item, (char **)NULL, 10);
-  if (errno == ERANGE) {
+  long bank = -1;
+
+  /* Sanitize arguments */
+  if (argc > 0)
+    bank = strtol(argv[0], (char **)NULL, 10);
+
+  if (errno == ERANGE || bank < 0) {
     printf("This bank number is incorrect\n");
     return;
   }
@@ -340,58 +355,6 @@ static void show_dmi_memory_bank(struct s_hardware *hardware, const char *item)
         hardware->dmi.memory[bank].part_number);
 }
 
-void dmi_show(char *item, struct s_hardware *hardware)
-{
-  if (!strncmp(item, CLI_DMI_BASE_BOARD, sizeof(CLI_DMI_BASE_BOARD) - 1)) {
-    show_dmi_base_board(hardware);
-    return;
-  }
-  if (!strncmp(item, CLI_DMI_SYSTEM, sizeof(CLI_DMI_SYSTEM) - 1)) {
-    show_dmi_system(hardware);
-    return;
-  }
-  if (!strncmp(item, CLI_DMI_BIOS, sizeof(CLI_DMI_BIOS) - 1)) {
-    show_dmi_bios(hardware);
-    return;
-  }
-  if (!strncmp(item, CLI_DMI_CHASSIS, sizeof(CLI_DMI_CHASSIS) - 1)) {
-    show_dmi_chassis(hardware);
-    return;
-  }
-  if (!strncmp(item, CLI_DMI_PROCESSOR, sizeof(CLI_DMI_PROCESSOR) - 1)) {
-    show_dmi_cpu(hardware);
-    return;
-  }
-  if (!strncmp(item, CLI_DMI_MEMORY, sizeof(CLI_DMI_MEMORY) - 1)) {
-    show_dmi_memory_modules(hardware, true, true);
-    return;
-  }
-  if (!strncmp
-      (item, CLI_DMI_MEMORY_BANK, sizeof(CLI_DMI_MEMORY_BANK) - 1)) {
-    show_dmi_memory_bank(hardware,
-             item + sizeof(CLI_DMI_MEMORY_BANK) - 1);
-    return;
-  }
-  if (!strncmp(item, CLI_SHOW_LIST, sizeof(CLI_SHOW_LIST) - 1)) {
-    show_dmi_modules(hardware);
-    return;
-  }
-  if (!strncmp(item, CLI_DMI_BATTERY, sizeof(CLI_DMI_BATTERY) - 1)) {
-    show_dmi_battery(hardware);
-    return;
-  }
-
-  show_dmi_help(hardware);
-}
-
-void handle_dmi_commands(char *cli_line, struct s_hardware *hardware)
-{
-  if (!strncmp(cli_line, CLI_SHOW, sizeof(CLI_SHOW) - 1)) {
-    dmi_show(strstr(cli_line, "show") + sizeof(CLI_SHOW), hardware);
-    return;
-  }
-}
-
 void main_show_dmi(struct s_hardware *hardware)
 {
 
@@ -405,12 +368,27 @@ void main_show_dmi(struct s_hardware *hardware)
          hardware->dmi.dmitable.major_version,
          hardware->dmi.dmitable.minor_version);
 
-  show_dmi_modules(hardware);
+  show_dmi_modules(0, NULL, hardware);
 }
 
-void show_dmi_memory_modules(struct s_hardware *hardware, bool clear,
-           bool show_free_banks)
+void show_dmi_memory_modules(int argc, char** argv,
+                             struct s_hardware *hardware)
 {
+  int clear = 1, show_free_banks = 1;
+
+  /* Sanitize arguments */
+  if (argc > 0) {
+    clear = strtol(argv[0], NULL, 10);
+    if (errno == ERANGE || clear < 0 || clear > 1)
+      goto usage;
+
+    if (argc > 1) {
+      show_free_banks = strtol(argv[1], NULL, 10);
+      if (errno == ERANGE || show_free_banks < 0 || show_free_banks > 1)
+        goto usage;
+    }
+  }
+
   char bank_number[10];
   char available_dmi_commands[1024];
   memset(available_dmi_commands, 0, sizeof(available_dmi_commands));
@@ -447,5 +425,60 @@ void show_dmi_memory_modules(struct s_hardware *hardware, bool clear,
       }
     }
   }
+
+  return;
   //printf("Type 'show bank<bank_number>' for more details.\n");
+
+usage:
+  printf("show memory <clear screen? <show free banks?>>\n");
+  return;
 }
+
+struct commands_module list_dmi_show_modules[] = {
+  {
+    .name = CLI_DMI_BASE_BOARD,
+    .exec = show_dmi_base_board,
+  },
+  {
+    .name = CLI_DMI_BIOS,
+    .exec = show_dmi_bios,
+  },
+  {
+    .name = CLI_DMI_BATTERY,
+    .exec = show_dmi_battery,
+  },
+  {
+    .name = CLI_DMI_CHASSIS,
+    .exec = show_dmi_chassis,
+  },
+  {
+    .name = CLI_DMI_MEMORY,
+    .exec = show_dmi_memory_modules,
+  },
+  {
+    .name = CLI_DMI_MEMORY_BANK,
+    .exec = show_dmi_memory_bank,
+  },
+  {
+    .name = CLI_DMI_PROCESSOR,
+    .exec = show_dmi_cpu,
+  },
+  {
+    .name = CLI_DMI_SYSTEM,
+    .exec = show_dmi_system,
+  },
+  {
+    .name = CLI_DMI_LIST,
+    .exec = show_dmi_modules,
+  },
+};
+
+struct commands_module_descr dmi_show_modules = {
+  .modules = list_dmi_show_modules,
+  .nb_modules = CLI_DMI_MAX_MODULES,
+};
+
+struct commands_mode dmi_mode = {
+  .mode = DMI_MODE,
+  .show_modules = &dmi_show_modules,
+};
index 73e3853..eadaf79 100644 (file)
 #include "hdt-cli.h"
 #include "hdt-common.h"
 
+#define MAX_MODES 1
+struct commands_mode *list_modes[] = {
+  &dmi_mode,
+};
+
 static void set_mode(struct s_cli_mode *cli_mode, cli_mode_t mode,
                     struct s_hardware *hardware)
 {
@@ -203,10 +208,108 @@ static void exec_command(char *command, struct s_cli_mode *cli_mode,
         * All commands before that line are common for all cli modes.
         * The following will be specific for every mode.
         */
+
+  int modes_iter = 0, modules_iter = 0;
+
+  /* Find the mode selected */
+  while (modes_iter < MAX_MODES &&
+         list_modes[modes_iter]->mode != cli_mode->mode)
+    modes_iter++;
+
+  if (modes_iter != MAX_MODES) {
+    struct commands_mode *current_mode = list_modes[modes_iter];
+
+    /*
+     * Find the type of command.
+     *
+     * The syntax of the cli is the following:
+     *    <type of command> <module on which to operate> <args>
+     * e.g.
+     *    dmi> show system
+     *    dmi> show bank 1
+     *    dmi> show memory 0 1
+     *    pci> show device 12
+     */
+    if (!strncmp(command, CLI_SHOW, sizeof(CLI_SHOW) - 1)) {
+      int module_len = 0, args_len = 0;
+      int argc = 0, args_iter = 0, argc_iter = 0;
+      char* module = NULL, * args = NULL, * args_cpy = NULL;
+      char** argv = NULL;
+
+      /* Get the module name and args */
+      while (strncmp(command + sizeof(CLI_SHOW) + module_len, CLI_SPACE, 1))
+        module_len++;
+
+      /* cli_line is filled with \0 when initialized */
+      while (strncmp(command + sizeof(CLI_SHOW) + module_len + 1 + args_len,
+             "\0", 1))
+        args_len++;
+
+      module = malloc(module_len + 1);
+      strncpy(module, command + sizeof(CLI_SHOW), module_len);
+      module[module_len] = '\0';
+
+      /* Skip arguments handling if none is supplied */
+      if (!args_len)
+        goto find_callback;
+
+      args = malloc(args_len + 1);
+      strncpy(args, command + sizeof(CLI_SHOW) + module_len + 1,
+              args_len);
+      args[args_len] = '\0';
+
+      /* Compute the number of arguments */
+      args_cpy = args;
+read_argument:
+      args_iter = 0;
+      while (args_iter < args_len && strncmp(args_cpy + args_iter, CLI_SPACE, 1))
+        args_iter++;
+      argc++;
+      args_iter++;
+      args_cpy += args_iter;
+      args_len -= args_iter;
+      if (args_len > 0)
+        goto read_argument;
+
+      /* Transform the arguments string into an array */
+      char* result = NULL;
+      argv = malloc(argc * sizeof(char *));
+      result = strtok(args, CLI_SPACE);
+      while (result != NULL) {
+        argv[argc_iter] = result;
+        argc_iter++;
+        result = strtok(NULL, CLI_SPACE);
+      }
+
+find_callback:
+      /* Find the callback to execute */
+      while (modules_iter < current_mode->show_modules->nb_modules &&
+             strncmp(module,
+                     current_mode->show_modules->modules[modules_iter].name,
+                     module_len + 1) != 0)
+        modules_iter++;
+
+      if (modules_iter != current_mode->show_modules->nb_modules) {
+        struct commands_module current_module =
+                          current_mode->show_modules->modules[modules_iter];
+        /* Execute the callback */
+        current_module.exec(argc, argv, hardware);
+      } else
+        printf("Module %s unknown.\n", module);
+        /* XXX Add a default help option for empty commands */
+
+      free(module);
+      if (args_len) {
+        free(args);
+        free(argv);
+      }
+    }
+    /* Handle here other keywords such as 'set', ... */
+  } else
+    printf("Mode unknown.\n");
+
+       /* Legacy cli */
        switch (cli_mode->mode) {
-       case DMI_MODE:
-               handle_dmi_commands(command, hardware);
-               break;
        case PCI_MODE:
                handle_pci_commands(command, hardware);
                break;
@@ -340,7 +443,10 @@ static void main_show_summary(struct s_hardware *hardware)
                more_printf(" Version      : %s\n", hardware->dmi.bios.version);
                more_printf(" Release      : %s\n",
                            hardware->dmi.bios.release_date);
-               show_dmi_memory_modules(hardware, false, false);
+
+               int argc = 2;
+               char* argv[2] = {"0", "0"};
+               show_dmi_memory_modules(argc, argv, hardware);
        }
        main_show_pci(hardware);
 
index 8951bfe..20f2c84 100644 (file)
@@ -71,6 +71,26 @@ struct s_cli_mode {
   char prompt[32];
 };
 
+/* A command-line command */
+struct commands_mode {
+  const unsigned int mode;
+  struct commands_module_descr* show_modules;
+  /* Future: set? */
+};
+
+struct commands_module {
+  const char *name;
+  void ( * exec ) ( int argc, char** argv, struct s_hardware *hardware );
+};
+
+/* Describe 'show', 'set', ... commands in a module */
+struct commands_module_descr {
+  struct commands_module* modules;
+  const int nb_modules;
+};
+
+struct commands_mode dmi_mode;
+
 void start_cli_mode(struct s_hardware *hardware);
 void main_show(char *item, struct s_hardware *hardware);
 int do_exit(struct s_cli_mode *cli_mode);
@@ -84,10 +104,11 @@ int do_exit(struct s_cli_mode *cli_mode);
 #define CLI_DMI_MEMORY_BANK "bank"
 #define CLI_DMI_PROCESSOR "cpu"
 #define CLI_DMI_SYSTEM "system"
+#define CLI_DMI_LIST CLI_SHOW_LIST
+#define CLI_DMI_MAX_MODULES 9
 void main_show_dmi(struct s_hardware *hardware);
 void handle_dmi_commands(char *cli_line, struct s_hardware *hardware);
-void show_dmi_memory_modules(struct s_hardware *hardware, bool clearscreen,
-                             bool show_free_banks);
+void show_dmi_memory_modules(int argc, char** argv, struct s_hardware *hardware);
 
 // PCI STUFF
 #define CLI_PCI_DEVICE "device"