switch support
PATCH 1/2 switch support
Hello,
I have wanted a scheme to change switch settings at boot time so I change the behavior of the Linux kernel and here is one solution I put together.
This may be one way to simulate switch or jumper settings one may change on a board before booting. It uses a simple text file for input. The file name is pointed to by -config <path to file> on the command line.
example:
config file:
[switches]
7:on
[jumpers]
Note: both [switches] and [jumpers] are required at the moment
to use:
qemu-system-arm -M mainstone -kernel /tftpboot/mainstone -pflash ~/mst_flashl1 -config ~/config.txt
this will enable the processor flash bank on the Mainstone and if I change 7:on to 7:off , I get the main mother board flash.
feedback and comment are always welcome.
-Armin
vl.c +126 -0
@@ -232,6 +232,8 @@ const char *prom_envs[MAX_PROM_ENVS];#endif int nb_drives_opt;char drives_opt[MAX_DRIVES ][1024 ]; +int configed =0 ; +const char *qemu_config;static CPUState *cur_cpu;static CPUState *next_cpu;
@@ -1547,6 +1549,118 @@ static void quit_timers(void) alarm_timer->stop (alarm_timer); alarm_timer =NULL ; } +/**********************************************************/ +/* config file */ +#define CONFIG_MAXLEN 256 + +int switch_get_value (SwitchInterfaceType interface,int number) +{ +int index; + +struct spdt_switch *sw = config_table[interface].sw; + +for (index =0 ; index < config_table[interface].nb_switches; index++){ +if (sw[index].num == number) +return sw[index].value; + } +return -1 ; +} + +static ssize_t config_rdline (FILE *fd,char *buf,size_t bufsz) +{ +int i, ch; +for (i =0 ; i < bufsz && (ch=fgetc (fd)) !='\n' ; i++) { +if (ch ==EOF ) { + *buf ='\0' ; +return -1 ; + } +if (ch =='[' ) { +return -2 ; + } + *buf++ = ch; + } + *buf ='\0' ; +return i; +} + +static int config_read_switches (FILE *fd,int index) +{ +int cnt =0 ; +int size =0 ; +char *tmp; +int sw_size =sizeof (struct spdt_switch ); +struct spdt_switch *sw; + + sw = (struct spdt_switch *)malloc (sw_size); +if (!sw) { +printf ("config_read_switches - Malloc error!!" ); +return -ENOMEM ; + } + + config_table[index].sw = sw; +while (size !=-1 ) { +char buf[CONFIG_MAXLEN ]; + + size =config_rdline (fd, buf,CONFIG_MAXLEN ); +if (size <=0 ) { +break ; + } + + tmp =strchr (buf,':' ); + sw[cnt].value = (strcmp (++tmp,"off" )) ?1 :0 ; + sw[cnt].num =atoi (buf); + sw_size +=sizeof (struct spdt_switch ); + sw = (struct spdt_switch *)realloc (config_table[index].sw, sw_size ); +if (!sw) +return -1 ; + cnt++; + }; +return cnt; +} + +static int config_file_read (char const *file) +{ +FILE *fd; +int index; + +struct { +char *key; +SwitchInterfaceType interface; + } switch_keywords[]= { + {"switches" ,CFG_SPDT_SWITCH }, + {"jumpers" ,CFG_JUMPERS_SWITCH } + }; + + fd =fopen (file,"r" ); +if (fd <0 ) { +printf ("Open error\n" ); +return -1 ; + } + +for (index =0 ; index < (sizeof (switch_keywords)/sizeof (switch_keywords[0 ])); + index++){ + +int ret; +char buf[CONFIG_MAXLEN ]; + ret =config_rdline (fd, buf,CONFIG_MAXLEN ); +if (ret ==-1 ) { +return -1 ; + } +if (ret ==-2 ) { + ret =config_rdline (fd, buf,CONFIG_MAXLEN ); +if (ret ==-1 ) { +return -1 ; + } + } +if (strstr (buf, switch_keywords[index].key) !=NULL ) { +int cnt; + cnt =config_read_switches (fd,switch_keywords[index].interface); + config_table[index].nb_switches = cnt; + } + } +fclose (fd); +return 1 ; +}/***********************************************************/ /* character device */
@@ -7562,6 +7676,7 @@ static void help(int exitcode)#endif "-clock force the use of the given methods for timer alarm.\n" " To see what timers are available use -clock help\n" +"-config file config file for kernel startup like switches and jumpers\n" "\n" "During emulation, the following keys are useful:\n" "ctrl-alt-f toggle full screen\n"
@@ -7664,6 +7779,7 @@ enum { QEMU_OPTION_old_param, QEMU_OPTION_clock, QEMU_OPTION_startdate, + QEMU_OPTION_config, }; typedef struct QEMUOption {
@@ -7772,6 +7888,7 @@ const QEMUOption qemu_options[] = {#endif { "clock", HAS_ARG, QEMU_OPTION_clock }, { "startdate", HAS_ARG, QEMU_OPTION_startdate }, + { "config", HAS_ARG, QEMU_OPTION_config }, { NULL }, };
@@ -8603,6 +8720,15 @@ int main(int argc, char **argv) } }break ; + +case QEMU_OPTION_config: + qemu_config = optarg; + configed =config_file_read (qemu_config); +if ( configed ==-1 ){ +fprintf (stderr,"Invalid config file: %s\n" ,qemu_config); +exit (1 ); + } +break ; } } }
sysemu.h +4 -2
@@ -180,7 +180,8 @@ void usb_info(void);/* config */ typedef enum { -CFG_SPDT_SWITCH ,CFG_DIP_SWITCH +CFG_SPDT_SWITCH =0 , +CFG_JUMPERS_SWITCH }SwitchInterfaceType ;struct spdt_switch {
@@ -191,11 +192,12 @@ struct spdt_switch{typedef struct SwitchInfo {SwitchInterfaceType interface;struct spdt_switch *sw; +int nb_switches; }SwitchInfo ;#define MAX_SWITCH_TYPES 2SwitchInfo config_table[MAX_SWITCH_TYPES +1 ]; -extern int switch_get_index (SwitchInterfaceType interface,int number); +extern int switch_get_value (SwitchInterfaceType interface,int number);#endif