Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
soc:fredrikhultin [2006/06/12 14:52]
noname Initial post
soc:fredrikhultin [2006/07/12 00:24] (current)
noname
Line 2: Line 2:
 ===== The Project ===== ===== The Project =====
 I'm going to write a command line for gPXE which will let the user do some basic tasks interactively. Things like setting and getting an IP, pinging, specifying tftp-servers etc. I'm going to do this as a separate, custom made, but implementation independent command line library which will handle all the internals of the command line. For this lib a small driver in the underlying application (ie. gPXE) will send key pressings to the lib. Code in gPXE will be able to add any command in run time or link time to the lib using linker tables or doubly-linked lists. The command line lib will then call the registered service when a command successfully has been entered. I'm going to write a command line for gPXE which will let the user do some basic tasks interactively. Things like setting and getting an IP, pinging, specifying tftp-servers etc. I'm going to do this as a separate, custom made, but implementation independent command line library which will handle all the internals of the command line. For this lib a small driver in the underlying application (ie. gPXE) will send key pressings to the lib. Code in gPXE will be able to add any command in run time or link time to the lib using linker tables or doubly-linked lists. The command line lib will then call the registered service when a command successfully has been entered.
 +
 ===== Design goals ===== ===== Design goals =====
 Small, efficient and extensible code. It will be easy to add new commands and the command line will do as much data-processing and error checking it can before passing the presumably correct arguments to the underlying functions. Small, efficient and extensible code. It will be easy to add new commands and the command line will do as much data-processing and error checking it can before passing the presumably correct arguments to the underlying functions.
-===== Delay ===== 
-Sadly my project started with some heavy setbacks when a lot of different electronic gadgets in my apartment exploded(!). It seems someone or something felt like 230v wasn't enough for my machines, I apparently needed 460v in my wall sockets instead. Things in our apartment that didn't fully agree with that new and improved voltage includes, but is not limited to, our: 
  
-   ​* ​DSL-Modem +===== Design ===== 
-   ​Router + 
-   ​Switch +==== User interface ==== 
-   ​Server + 
-   ​Studio Speakers +The plans for the user interface are so that it will look something like 
-   ​Audio mixer + 
-   ​* ​Projector+<​file>​ 
 +Welcome to Etherboot 
 + 
 +?>help 
 + 
 +Built in commands: 
 +  help               ​Command help, use "help help" for more info. 
 +  exit, quit, boot   Exits the command line and boots 
 + 
 +Compiled in commands: 
 +  ip                     Views or sets current IP adress and netmask 
 + 
 +?>help ip 
 +ip - Views or sets current IP adress and netmask 
 + 
 +Used for both IPv6 and IPv4. 
 + 
 +Set the IP adress and netmask (IPv4) 
 +  ip <ip> <​netmask>​ 
 + 
 +  Example: 
 +    ip 192.168.1.42 255.255.255.0 
 + 
 +Set the IP adress (IPv6) 
 +  ip <​ip>​ 
 + 
 +  Example: 
 +    ip 2001:​0db8::​1428:​57ab 
 + 
 +View the IP/​netmask 
 +  ip 
 + 
 +  Example: 
 +    ip 
 + 
 +?>ip 10.0.0.4 255.0.0.0 
 +?>ip 
 +Protocol version: 4 
 +Adress: 10.0.0.4 
 +Netmask: 255.0.0.0 
 +?>boot 
 +Booting... 
 +</​file>​ 
 + 
 +==== Command implementation ==== 
 + 
 +I've tried to minimize the code and work in/on the custom commands; the command line code will do most of the work. The ip command implementation could look something like this (without the parts actually doing anything) 
 + 
 +<code c> 
 +#include "​command.h"​ 
 + 
 +/Command description,​ table entry*/ 
 +struct command test_command __command = { 
 +        .name = "​ip",​ 
 +        .extra_help = "Used for both IPv6 and IPv4.",​ 
 +        .desc = "Views or sets current IP adress and netmask",​ 
 +        .exec = cmd_test_exec,​ 
 +        .get_param_list = cmd_ip_get_param_list;​ 
 +}; 
 + 
 +/* Get the parameter specifications */ 
 +static cmdl_param_list *cmd_ip_get_param_list (void) { 
 + 
 +  /* List set 1: set ipv4 adress and netmask */ 
 + 
 +  /* Create the list set */ 
 +  cmdl_param_list_set* ipv4; 
 +  ipv4 = cmdl_param_list_set_create();​ 
 + 
 +  /* Name and describe the list set */ 
 +  cmdl_param_list_set_name(ipv4,​ "​ipv4"​);​ 
 +  cmdl_param_list_set_desc(ipv4,​ "Set the IP adress and netmask (IPv4)"​);​ 
 + 
 +  /* Add the parameters with name, type and example value */ 
 +  cmdl_param_list_set_add(ipv4,​ "​ip",​ CMDL_IPV4, "​192.168.1.42"​);​ 
 +  cmdl_param_list_set_add(ipv4,​ "​netmask",​ CMDL_IPV4, "​255.255.255.0"​);​ 
 + 
 +  /* List set 2: set ipv6 adress */ 
 + 
 +  /* Create the list set */ 
 +  cmdl_param_list_set* ipv6; 
 +  ipv6 = cmdl_param_list_set_create();​ 
 + 
 +  /* Name and describe the list set */ 
 +  cmdl_param_list_set_name(ipv6,​ "​ipv6"​);​ 
 +  cmdl_param_list_set_desc(ipv6,​ "Set the IP adress (IPv6)"​);​ 
 + 
 +  cmdl_param_list_set_add(ipv6,​ "​ip",​ CMDL_IPV6, "​2001:​0db8::​1428:​57ab"​);​ 
 + 
 +  /* List set 3: view the IP adress and netmask */ 
 +  
 +  /* Create the list set */ 
 +  cmdl_param_list_set* view; 
 +  view = cmdl_param_list_set_create();​ 
 + 
 +  /* Name and describe the list set */ 
 +  cmdl_param_list_set_name(view,​ "​view"​);​ 
 +  cmdl_param_list_set_desc(view,​ "View the IP/​netmask"​);​ 
 + 
 +  /* (No parameters = view) */ 
 + 
 +  /* Create the parameter list */ 
 +  cmdl_param_list* param_list;​ 
 +  param_list = cmdl_param_list_create();​ 
 + 
 +  /* Add the three list sets to the parameter list */ 
 + 
 +  cmdl_param_list_add(param_list,​ ipv4); 
 +  cmdl_param_list_add(param_list,​ ipv6); 
 +  cmdl_param_list_add(param_list,​ view); 
 + 
 +  /* Return the parameter list to the command line */ 
 +  return param_list;​ 
 +
 + 
 +static int cmd_ip_exec ( cmd_line* cmd, cmdl_params* params ) { 
 + 
 +  /* View */ 
 +  if(strcmp("​view",​ params->​set_name) == 0){ 
 +    int protocolv;​ 
 +    cmdl_ipv4 ip4, netmask; 
 +    cmdl_ipv6 ip6; 
 + 
 +    protocolv = ...(); 
 +    cmdl_printf(cmd,​ "​Protocol version: %i\n"​);​ 
 + 
 +    if(protocol != 4){ 
 +    }else{ 
 +      ip4 = ...(); 
 +      netmask = ...(); 
 +      cmdl_printf(cmd,​ "​Adress:​ %i.%i.%i.%i\nNetmask:​ %i.%i.%i.%i\n",​  
 +                       ​ip4.octet[0], ​    ​ip4.octet[1], ​    ​ip4.octet[2], ​    ​ip4.octet[3],​  
 +                   ​netmask.octet[0],​ netmask.octet[1],​ netmask.octet[2],​ netmask.octet[3] ); 
 +    }else{ 
 +       ... 
 +    } 
 +  } 
 + 
 +  /ipv4 */ 
 +  ​if(strcmp("​ipv4",​ params->​set_name) == 0){ 
 +    if( !set_gpxe_ip_something( cmdl_param_get_ipv4(params->​param[0]) ){ 
 +      return -1; 
 +    } 
 +    if( !set_gpxe_netmask_something( cmdl_param_get_ipv4(params,​ 1) ){ 
 +      return -1; 
 +    } 
 +  } 
 + 
 +  /* ipv6 */ 
 +  ​if(strcmp("​ipv6",​ params->​set_name) == 0){ 
 +    if( !set_gpxe_ip6_something( cmdl_param_get_ipv6(params,​ 0) ){ 
 +      return -1; 
 +    } 
 +  } 
 + 
 +  return 0; 
 +
 +</​code>​ 
 + 
 +Observe that the output of "help ip" is generated from this implementation. 
 + 
 +==== Structures ==== 
 + 
 +=== The main command structure === 
 + 
 +<code c> 
 +struct command { 
 +  /* The name of the command ​*/ 
 +  const char *name; 
 + 
 +  /Additional help, or help that can't be automatically generated */ 
 +  const char *extra_help;​ 
 + 
 +  /* Short description of the command, what it does. */ 
 +  const char *desc; 
 + 
 +  /* The command function, returns an error code, takes command line pointer and params specified in param_list */ 
 +  int ( *exec ) ( cmd_line*, cmdl_params*) 
 + 
 +  /* Returns a list describing parameters the command accepts */ 
 +  cmdl_param_list *( *get_param_list )( void ); 
 + 
 +}; 
 +</​code>​ 
 + 
 +=== cmdl_param_list === 
 + 
 +cmdl_param_list will contain parameter list sets, since a command might accept many different sets of parameters. 
 + 
 +<code c> 
 +typedef struct { 
 +  int num_sets; // The number of sets in the list 
 +  cmdl_param_list_set** param_list_set;​ // An array of list set pointers 
 +} cmdl_param_list;​ 
 +</​code>​ 
 + 
 + 
 +=== cmdl_param_list_set === 
 + 
 +A parameter list set will contain parameter descriptions 
 + 
 +<code c> 
 +typedef struct { 
 +  char* name;  // Name of the list set (used for identification) 
 +  char* desc;  // Description of the list set (used for the automated help) 
 +  int num_params; ​  ​// The number of parameters 
 +  cmdl_param_desc** param; // An array of parameter description pointers 
 +} cmdl_param_list_set;​ 
 +</​code>​ 
 + 
 +=== cmdl_param_desc === 
 + 
 +A parameter description contains information about a single parameter 
 + 
 +<code c> 
 +typedef struct { 
 +  int type; // Parameter type 
 +  char* name; // Parameter name 
 +  char* example; // Example of possible value 
 +} cmdl_param_desc;​ 
 +</​code>​ 
 + 
 +  * name is the name of the input field, it will be used for the standardized automatic help function 
 +  * example is an example value for the field, also for the help 
 + 
 +type will be an enum with different types of inputs the command line will understand and parse, for example: 
 + 
 +<code c> 
 +enum{ 
 +  CMDL_INT=0,​ 
 +  CMDL_FP, 
 +  CMDL_STR, 
 +  CMDL_IPV4,​ 
 +  CMDL_IPV6 
 +}; 
 +</​code>​ 
 + 
 +=== cmdl_params === 
 +Contains one named parameter set 
 + 
 +<code c> 
 +typedef struct{ 
 +  char* set_name; // Name of the set 
 +  int num_params; // The number of parameters the set contains 
 +  cmdl_param** param; // An array of param pointers 
 +}cmdl_params;​ 
 +</​code>​ 
 + 
 +=== cmdl_param === 
 +Container class for parameter values. Only one parameter type is valid per parameter. 
 + 
 +<code c> 
 +typedef struct{ 
 +  int valid_type; // Defines the param type (which pointer is valid) 
 + 
 +  // Pointers to available types 
 + 
 +  int* integer; 
 +  double* fp; 
 +  char* str; 
 +  cmdl_ipv4* ipv4; 
 +  cmdl_ipv6* ipv6; 
 +  // ... 
 + 
 +}cmdl_param;​ 
 + 
 +// with supporting structures like 
 + 
 +typedef struct{ 
 +  unsigned char octet[4]; 
 +}cmdl_ipv4;​ 
 + 
 +typedef struct{ 
 +  unsigned short int part[ 
 + 
 +8]; 
 +}cmdl_ipv6;​ 
 + 
 +// ...etc 
 +</​code>​ 
 + 
 +==== Functions ==== 
 +Functions for the command implementation interface 
 + 
 +=== cmdl_param_list_set_create === 
 +Allocates a new list set and returns it. 
 + 
 +<​code>​ 
 +cmdl_param_list_set* cmdl_param_list_set_create();​ 
 +</​code>​ 
 + 
 +=== cmdl_param_list_set_name === 
 +Names a given list set with a given name. 
 + 
 +<​code>​ 
 +void cmdl_param_list_set_name(cmdl_param_list_set* list_set, char* name); 
 +</​code>​ 
 + 
 +=== cmdl_param_list_set_desc === 
 +Adds a description to a given list set. 
 + 
 +<​code>​ 
 +void cmdl_param_list_set_desc(cmdl_param_list_set* list_set, char* desc); 
 +</​code>​ 
 + 
 +=== cmdl_param_list_set_add === 
 +Adds a parameter description to a given list set. 
 + 
 +<​code>​ 
 +void cmdl_param_list_set_add(cmdl_param_list_set* list_set, char* name, int type, char* example); 
 +</​code>​ 
 + 
 + 
 +=== cmdl_param_list_create === 
 +Allocates and returns a parameter new parameter list. 
 + 
 +<​code>​ 
 +cmdl_param_list* cmdl_param_list_create();​ 
 +</​code>​ 
 + 
 +=== cmdl_param_list_add === 
 +Adds a parameter list set to a given parameter list. 
 + 
 +<​code>​ 
 +void cmdl_param_list_add(cmdl_param_list* param_list, cmdl_param 
 +</​code>​ 
 + 
 +=== cmdl_printf === 
 +Prints formated text to a given command line. 
 + 
 +<​code>​ 
 +int cmdl_printf(cmd_line* cmd, const char *format, ...); 
 +</​code>​ 
 + 
 +=== cmdl_param_get_TYPE === 
 +Returns the given parameter from a cmdl_params as TYPE. 
 +Rturns NULL if the parameter isn't a TYPE. 
 + 
 +<​code>​ 
 +int *cmdl_param_get_int(cmdl_params* params, int param_num);​ 
 +cmdl_ipv4 *cmdl_param_get_ipv4(cmdl_params* params, int param_num);​ 
 +... 
 +</​code>​ 
 + 
 +==== Concerns ==== 
 +Perhaps this implementation would be a bit over the top. I got an email from Michael last week and he suggested, without reading this, that I should use ordinary C-style command structures (int argc, char*argv). That might not be as grandiose, and it would be harder to generate standardized automated help output, but it'd be much easier to implement. With some nice parse helper functions available to the command implementations,​ then perhaps it wouldn'​t be so bad. Hmm...
  
-Luckily it was mostly the power adaptors/​PSUs that got toasted so I'm pretty much back on track again but I lost about a week. +===== Status ​=====
-===== Notes ===== +
-Google, where'​s my free gift!+
  
 +The command line is working and accepts input from the user, which it parses and then, at the moment, disregards.

Navigation

* [[:start|Home]] * [[:about|About our Project]] * [[:download|Download]] * [[:screenshots|Screenshots]] * Documentation * [[:howtos|HowTo Guides]] * [[:appnotes|Application Notes]] * [[:faq:|FAQs]] * [[:doc|General Doc]] * [[:talks|Videos, Talks, and Papers]] * [[:hardwareissues|Hardware Issues]] * [[:mailinglists|Mailing lists]] * [[http://support.etherboot.org/|Bugtracker]] * [[:contributing|Contributing]] * [[:editing_permission|Wiki Edit Permission]] * [[:wiki:syntax|Wiki Syntax]] * [[:contact|Contact]] * [[:relatedlinks|Related Links]] * [[:commerciallinks|Commercial Links]] * [[:acknowledgements|Acknowledgements]] * [[:logos|Logo Art]]

QR Code
QR Code soc:fredrikhultin (generated for current page)