diff --git a/dev/eeprom.c b/dev/eeprom.c index 5e2ae3732607fe05f482438208526ebf03fe4f01..559b919ece873e76d296efabbb6b9d2b4dac5155 100644 --- a/dev/eeprom.c +++ b/dev/eeprom.c @@ -11,7 +11,7 @@ * is that it starts with 0xdeadbeef pattern. The structure of SFP section is: * * -------------- - * | count (4B) | + * | count (1B) | * -------------------------------------------------------------------------------------------- * | SFP(1) part number (16B) | alpha (4B) | deltaTx (4B) | deltaRx (4B) | chksum(1B) | * -------------------------------------------------------------------------------------------- @@ -30,6 +30,19 @@ * */ +/* + * The init script area consist of 2-byte size field and a set of shell commands + * separated with '\n' character. + * + * ------------------- + * | bytes used (2B) | + * ------------------------------------------------ + * | shell commands separated with '\n'..... | + * | | + * | | + * ------------------------------------------------ + */ + int eeprom_read(uint8_t i2cif, uint8_t i2c_addr, uint32_t offset, uint8_t *buf, size_t size) { @@ -127,7 +140,7 @@ int32_t eeprom_get_sfp(uint8_t i2cif, uint8_t i2c_addr, struct s_sfpinfo* sfp, u for(i=0; i<sizeof(struct s_sfpinfo)-1; ++i) //'-1' because we do not include chksum in computation chksum = (uint8_t) ((uint16_t)chksum + *(ptr++)) & 0xff; if(chksum != sfp->chksum) - EE_RET_CHKSUM; + EE_RET_CORRPT; } else { @@ -173,3 +186,117 @@ int8_t eeprom_match_sfp(uint8_t i2cif, uint8_t i2c_addr, struct s_sfpinfo* sfp) return 0; } + +int8_t eeprom_init_erase(uint8_t i2cif, uint8_t i2c_addr) +{ + uint16_t used = 0; + + if( eeprom_write(i2cif, i2c_addr, EE_BASE_INIT, &used, sizeof(used)) != sizeof(used)) + return EE_RET_I2CERR; + else + return used; +} + +int8_t eeprom_init_purge(uint8_t i2cif, uint8_t i2c_addr) +{ + uint16_t used = 0xffff, i; + uint16_t pattern = 0xff; + + eeprom_read(i2cif, i2c_addr, EE_BASE_INIT, &used, sizeof(used)); + if(used==0xffff) used=0; + for(i=0; i<used; ++i) + eeprom_write(i2cif, i2c_addr, EE_BASE_INIT+sizeof(used)+i, &pattern, 1); + used = 0xffff; + eeprom_write(i2cif, i2c_addr, EE_BASE_INIT, &used, 2); + + return used; +} + +/* + * Appends a new shell command at the end of boot script + */ +int8_t eeprom_init_add(uint8_t i2cif, uint8_t i2c_addr, const char *args[]) +{ + uint8_t i=1; + char separator = ' '; + uint16_t used, readback; + + if( eeprom_read(i2cif, i2c_addr, EE_BASE_INIT, &used, sizeof(used)) != sizeof(used) ) + return EE_RET_I2CERR; + + if( used==0xffff ) used=0; //this means the memory is blank + + while(args[i]!='\0') + { + if( eeprom_write(i2cif, i2c_addr, EE_BASE_INIT+sizeof(used)+used, args[i], strlen(args[i])) != strlen(args[i])) + return EE_RET_I2CERR; + used += strlen(args[i]); + if( eeprom_write(i2cif, i2c_addr, EE_BASE_INIT+sizeof(used)+used, &separator, sizeof(separator)) != sizeof(separator) ) + return EE_RET_I2CERR; + ++used; + ++i; + } + //the end of the command, replace last separator with '\n' + separator = '\n'; + if( eeprom_write(i2cif, i2c_addr, EE_BASE_INIT+sizeof(used)+used-1, &separator, sizeof(separator)) != sizeof(separator) ) + return EE_RET_I2CERR; + //and finally update the size of the script + if( eeprom_write(i2cif, i2c_addr, EE_BASE_INIT, &used, sizeof(used)) != sizeof(used) ) + return EE_RET_I2CERR; + + if( eeprom_read(i2cif, i2c_addr, EE_BASE_INIT, &readback, sizeof(readback)) != sizeof(readback) ) + return EE_RET_I2CERR; + + return 0; +} + +int32_t eeprom_init_show(uint8_t i2cif, uint8_t i2c_addr) +{ + uint16_t used, i; + char byte; + + if( eeprom_read(i2cif, i2c_addr, EE_BASE_INIT, &used, sizeof(used)) != sizeof(used) ) + return EE_RET_I2CERR; + + if(used==0 || used==0xffff) + { + used = 0; //this means the memory is blank + mprintf("Empty init script...\n"); + } + + //just read and print to the screen char after char + for(i=0; i<used; ++i) + { + if( eeprom_read(i2cif, i2c_addr, EE_BASE_INIT+sizeof(used)+i, &byte, sizeof(byte)) != sizeof(byte) ) + return EE_RET_I2CERR; + mprintf("%c", byte); + } + + return 0; +} + +int8_t eeprom_init_readcmd(uint8_t i2cif, uint8_t i2c_addr, char* buf, uint8_t bufsize, uint8_t next) +{ + static uint16_t ptr; + static uint16_t used = 0; + uint8_t i=0; + + if(next == 0) + { + if( eeprom_read(i2cif, i2c_addr, EE_BASE_INIT, &used, sizeof(used)) != sizeof(used) ) + return EE_RET_I2CERR; + ptr = sizeof(used); + } + + if(ptr-sizeof(used) >= used) + return 0; + + do + { + if(ptr-sizeof(used) > bufsize) return EE_RET_CORRPT; + if( eeprom_read(i2cif, i2c_addr, EE_BASE_INIT+(ptr++), &buf[i], sizeof(char)) != sizeof(char) ) + return EE_RET_I2CERR; + }while(buf[i++]!='\n'); + + return i; +} diff --git a/include/eeprom.h b/include/eeprom.h index ebe5593f8e53a95d7f7ac243607c16d3d2555f46..e1a2dd6363c2e1978ba39478b68072cb43fe3eda 100644 --- a/include/eeprom.h +++ b/include/eeprom.h @@ -9,7 +9,7 @@ #define EE_RET_I2CERR -1 #define EE_RET_DBFULL -2 -#define EE_RET_CHKSUM -3 +#define EE_RET_CORRPT -3 #define EE_RET_POSERR -4 extern int32_t sfp_alpha; @@ -28,9 +28,13 @@ struct s_sfpinfo int eeprom_read(uint8_t i2cif, uint8_t i2c_addr, uint32_t offset, uint8_t *buf, size_t size); int eeprom_write(uint8_t i2cif, uint8_t i2c_addr, uint32_t offset, uint8_t *buf, size_t size); - int32_t eeprom_sfpdb_erase(uint8_t i2cif, uint8_t i2c_addr); int32_t eeprom_sfp_section(uint8_t i2cif, uint8_t i2c_addr, size_t size, uint16_t *section_sz); int8_t eeprom_match_sfp(uint8_t i2cif, uint8_t i2c_addr, struct s_sfpinfo* sfp); +int8_t eeprom_init_erase(uint8_t i2cif, uint8_t i2c_addr); +int8_t eeprom_init_add(uint8_t i2cif, uint8_t i2c_addr, const char *args[]); +int32_t eeprom_init_show(uint8_t i2cif, uint8_t i2c_addr); +int8_t eeprom_init_readcmd(uint8_t i2cif, uint8_t i2c_addr, char* buf, uint8_t bufsize, uint8_t next); + #endif diff --git a/include/shell.h b/include/shell.h index 30c48636e33fdad9d377ab6b8b049aa8be3d4726..7f780eee9861022f50649f2878d83a37323af297 100644 --- a/include/shell.h +++ b/include/shell.h @@ -23,6 +23,8 @@ int cmd_time(const char *args[]); int cmd_ip(const char *args[]); int cmd_sdb(const char *args[]); int cmd_mac(const char *args[]); +int cmd_init(const char *args[]); + int cmd_env(const char *args[]); int cmd_saveenv(const char *args[]); @@ -35,5 +37,7 @@ void env_init(); int shell_exec(const char *buf); void shell_interactive(); +int shell_boot_script(void); + #endif diff --git a/shell/cmd_init.c b/shell/cmd_init.c new file mode 100644 index 0000000000000000000000000000000000000000..ee9d5cfea52891099414248bd8f655a8878e90ca --- /dev/null +++ b/shell/cmd_init.c @@ -0,0 +1,42 @@ + +#include "shell.h" +#include "eeprom.h" +#include "syscon.h" + + +int cmd_init(const char *args[]) +{ + if( !mi2c_devprobe(WRPC_FMC_I2C, FMC_EEPROM_ADR) ) + { + mprintf("EEPROM not found..\n"); + return -1; + } + + if(args[0] && !strcasecmp(args[0], "erase")) + { + if( eeprom_init_erase(WRPC_FMC_I2C, FMC_EEPROM_ADR) < 0 ) + mprintf("Could not erase init script\n"); + } + else if(args[0] && !strcasecmp(args[0], "purge")) + { + eeprom_init_purge(WRPC_FMC_I2C, FMC_EEPROM_ADR); + } + else if(args[1] && !strcasecmp(args[0], "add")) + { + if( eeprom_init_add(WRPC_FMC_I2C, FMC_EEPROM_ADR, args) < 0 ) + mprintf("Could not add the command\n"); + else + mprintf("OK.\n"); + } + else if(args[0] && !strcasecmp(args[0], "show")) + { + eeprom_init_show(WRPC_FMC_I2C, FMC_EEPROM_ADR); + } + else if(args[0] && !strcasecmp(args[0], "boot")) + { + shell_boot_script(); + } + + return 0; +} + diff --git a/shell/shell.c b/shell/shell.c index 57a300cfdcecba3af78cf5ce15e83c25e207fb96..3cd97492118c8874afe19f43d5ca6367dd93e08d 100644 --- a/shell/shell.c +++ b/shell/shell.c @@ -4,6 +4,7 @@ #include "util.h" #include "uart.h" +#include "syscon.h" #include "shell.h" #define SH_MAX_LINE_LEN 80 @@ -45,6 +46,7 @@ static const struct shell_cmd cmds_list[] = { { "saveenv", cmd_saveenv }, { "time", cmd_time }, { "sfp", cmd_sfp }, + { "init", cmd_init }, #if WITH_ETHERBONE { "ip", cmd_ip }, #endif @@ -266,3 +268,30 @@ const char* fromdec(const char* dec, int* v) { *v = o; return dec; } + +int shell_boot_script(void) +{ + uint8_t next=0; + + //first check if EEPROM is really there + if( !mi2c_devprobe(WRPC_FMC_I2C, FMC_EEPROM_ADR) ) + if( !mi2c_devprobe(WRPC_FMC_I2C, FMC_EEPROM_ADR) ) + return -1; + + while(1) + { + cmd_len = eeprom_init_readcmd(WRPC_FMC_I2C, FMC_EEPROM_ADR, cmd_buf, SH_MAX_LINE_LEN, next); + if(cmd_len <= 0) + { + if(next==0) mprintf("Empty init script...\n"); + break; + } + cmd_buf[cmd_len] = 0; + + mprintf("executing: %s", cmd_buf); + _shell_exec(); + next = 1; + } + + return 0; +} diff --git a/shell/shell.mk b/shell/shell.mk index cd67fb5051201696d5db3368c7f9e2981eaa7426..d1e89ca1b684e1b2dd6e37cbc585f9137aa808dc 100644 --- a/shell/shell.mk +++ b/shell/shell.mk @@ -10,7 +10,8 @@ OBJS_SHELL = shell/shell.o \ shell/cmd_time.o \ shell/cmd_gui.o \ shell/cmd_sdb.o \ - shell/cmd_mac.o + shell/cmd_mac.o \ + shell/cmd_init.o ifneq ($(WITH_ETHERBONE), 0) OBJS_SHELL += shell/cmd_ip.o diff --git a/wrc_main.c b/wrc_main.c index d7ea79ee63b6c7d9973e7395d35768f52af7b687..cef187656361591bd55d957b455f7769e18ccc78 100644 --- a/wrc_main.c +++ b/wrc_main.c @@ -71,6 +71,9 @@ void wrc_initialize() ipv4_init("wru1"); arp_init("wru1"); #endif + + //try to read and execute init script from EEPROM + shell_boot_script(); } #define LINK_WENT_UP 1