From 9f21df049144d3f4244b24e789c9820ca631379e Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Fri, 1 Jul 2016 20:56:27 +0200 Subject: sysmobts: Store a simple network config in the EEPROM as well Make it possible to store: * Static vs. DHCP mode * IPv4 address * Netmask * GW IPv4 address * DNS IPv4 address Add a simple CRC8 and pick 0xFF as initial value so an all zero EEPROM will not generate a 0 CRC. The code tries to differentiate exit code between unreadable EEPROM and CRC error. This is a reference to see if we want to have store it in the EEPROM or not. Change-Id: Ia7c59506d9f6e4cb6acd4bb0e198abd28a90f50f --- src/osmo-bts-sysmo/misc/sysmobts_eeprom.h | 16 +++-- src/osmo-bts-sysmo/misc/sysmobts_par.c | 52 +++++++++++++++ src/osmo-bts-sysmo/misc/sysmobts_par.h | 4 ++ src/osmo-bts-sysmo/misc/sysmobts_util.c | 104 +++++++++++++++++++++++++++++- 4 files changed, 168 insertions(+), 8 deletions(-) diff --git a/src/osmo-bts-sysmo/misc/sysmobts_eeprom.h b/src/osmo-bts-sysmo/misc/sysmobts_eeprom.h index 782f7568..97344f37 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_eeprom.h +++ b/src/osmo-bts-sysmo/misc/sysmobts_eeprom.h @@ -3,6 +3,14 @@ #include +struct sysmobts_net_cfg { + uint8_t mode; /* 0 */ + uint32_t ip; /* 1 - 4 */ + uint32_t mask; /* 5 - 8 */ + uint32_t gw; /* 9 - 12 */ + uint32_t dns; /* 13 - 16 */ +} __attribute__((packed)); + struct sysmobts_eeprom { /* offset */ uint8_t eth_mac[6]; /* 0-5 */ uint8_t _pad0[10]; /* 6-15 */ @@ -17,13 +25,7 @@ struct sysmobts_eeprom { /* offset */ uint8_t trx_nr; /* 36 */ uint8_t boot_state[48]; /* 37-84 */ uint8_t _pad1[18]; /* 85-102 */ - struct { - uint8_t mode; /* 103 */ - uint32_t ip; /* 104 - 107 */ - uint32_t mask; /* 108 - 111 */ - uint32_t gw; /* 112 - 115 */ - uint32_t dns; /* 116 - 119 */ - } __attribute__((packed)) net_cfg; + struct sysmobts_net_cfg net_cfg;/* 103-119 */ uint8_t crc; /* 120 */ uint8_t gpg_key[128]; /* 121-249 */ } __attribute__((packed)); diff --git a/src/osmo-bts-sysmo/misc/sysmobts_par.c b/src/osmo-bts-sysmo/misc/sysmobts_par.c index e3a3c56b..98fe02b5 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_par.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_par.c @@ -30,6 +30,7 @@ #include #include +#include #include #include "sysmobts_eeprom.h" @@ -38,6 +39,13 @@ #define EEPROM_PATH "/sys/devices/platform/i2c_davinci.1/i2c-1/1-0050/eeprom" +static const struct osmo_crc8gen_code crc8_ccit = { + .bits = 8, + .poly = 0x83, + .init = 0xFF, + .remainder = 0x00, +}; + const struct value_string sysmobts_par_names[_NUM_SYSMOBTS_PAR+1] = { { SYSMOBTS_PAR_MAC, "ethaddr" }, { SYSMOBTS_PAR_CLK_FACTORY, "clk-factory" }, @@ -291,6 +299,50 @@ int sysmobts_par_set_buf(enum sysmobts_par par, const uint8_t *buf, return len; } +int sysmobts_par_get_net(struct sysmobts_net_cfg *cfg) +{ + struct sysmobts_eeprom *ee = get_eeprom(0); + ubit_t bits[sizeof(*cfg) * 8]; + uint8_t crc; + int rc; + + if (!ee) + return -EIO; + + /* convert the net_cfg to unpacked bits */ + rc = osmo_pbit2ubit(bits, (uint8_t *) &ee->net_cfg, sizeof(bits)); + if (rc != sizeof(bits)) + return -EFAULT; + /* compute the crc and compare */ + crc = osmo_crc8gen_compute_bits(&crc8_ccit, bits, sizeof(bits)); + if (crc != ee->crc) { + fprintf(stderr, "Computed CRC(%d) wanted CRC(%d)\n", crc, ee->crc); + return -EBADMSG; + } + /* return the actual data */ + *cfg = ee->net_cfg; + return 0; +} + +int sysmobts_par_set_net(struct sysmobts_net_cfg *cfg) +{ + struct sysmobts_eeprom *ee = get_eeprom(1); + ubit_t bits[sizeof(*cfg) * 8]; + int rc; + + if (!ee) + return -EIO; + + /* convert the net_cfg to unpacked bits */ + rc = osmo_pbit2ubit(bits, (uint8_t *) cfg, sizeof(bits)); + if (rc != sizeof(bits)) + return -EFAULT; + /* compute and store the result */ + ee->net_cfg = *cfg; + ee->crc = osmo_crc8gen_compute_bits(&crc8_ccit, bits, sizeof(bits)); + return set_eeprom(ee); +} + osmo_static_assert(offsetof(struct sysmobts_eeprom, trx_nr) == 36, offset_36); osmo_static_assert(offsetof(struct sysmobts_eeprom, boot_state) == 37, offset_37); osmo_static_assert(offsetof(struct sysmobts_eeprom, _pad1) == 85, offset_85); diff --git a/src/osmo-bts-sysmo/misc/sysmobts_par.h b/src/osmo-bts-sysmo/misc/sysmobts_par.h index 64803221..5a603cc0 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_par.h +++ b/src/osmo-bts-sysmo/misc/sysmobts_par.h @@ -3,6 +3,8 @@ #include +struct sysmobts_net_cfg; + enum sysmobts_par { SYSMOBTS_PAR_MAC, SYSMOBTS_PAR_CLK_FACTORY, @@ -26,6 +28,8 @@ int sysmobts_par_get_buf(enum sysmobts_par par, uint8_t *buf, unsigned int size); int sysmobts_par_set_buf(enum sysmobts_par par, const uint8_t *buf, unsigned int size); +int sysmobts_par_get_net(struct sysmobts_net_cfg *cfg); +int sysmobts_par_set_net(struct sysmobts_net_cfg *cfg); int sysmobts_par_is_int(enum sysmobts_par par); diff --git a/src/osmo-bts-sysmo/misc/sysmobts_util.c b/src/osmo-bts-sysmo/misc/sysmobts_util.c index d2b09a81..c9930d8f 100644 --- a/src/osmo-bts-sysmo/misc/sysmobts_util.c +++ b/src/osmo-bts-sysmo/misc/sysmobts_util.c @@ -25,23 +25,35 @@ #include #include +#include +#include +#include #include "sysmobts_par.h" +#include "sysmobts_eeprom.h" enum act { ACT_GET, ACT_SET, + ACT_NET_GET, + ACT_NET_SET, }; static enum act action; static char *write_arg; static int void_warranty; + +static struct in_addr net_ip = { 0, }, net_dns = { 0, }, net_gw = { 0, }, net_mask = { 0, }; +static uint8_t net_mode = 0; + static void print_help() { const struct value_string *par = sysmobts_par_names; printf("sysmobts-util [--void-warranty -r | -w value] param_name\n"); + printf("sysmobts-util --net-read\n"); + printf("sysmobts-util --net-write --mode INT --ip IP_STR --gw IP_STR --dns IP_STR --net-mask IP_STR\n"); printf("Possible param names:\n"); for (; par->str != NULL; par += 1) { @@ -60,6 +72,13 @@ static int parse_options(int argc, char **argv) { "read", 0, 0, 'r' }, { "void-warranty", 0, 0, 1000}, { "write", 1, 0, 'w' }, + { "ip", 1, 0, 241 }, + { "gw", 1, 0, 242 }, + { "dns", 1, 0, 243 }, + { "net-mask", 1, 0, 244 }, + { "mode", 1, 0, 245 }, + { "net-read", 0, 0, 246 }, + { "net-write", 0, 0, 247 }, { 0, 0, 0, 0 } }; @@ -83,7 +102,29 @@ static int parse_options(int argc, char **argv) printf("Will void warranty on write.\n"); void_warranty = 1; break; + case 246: + action = ACT_NET_GET; + break; + case 247: + action = ACT_NET_SET; + break; + case 245: + net_mode = atoi(optarg); + break; + case 244: + inet_aton(optarg, &net_mask); + break; + case 243: + inet_aton(optarg, &net_dns); + break; + case 242: + inet_aton(optarg, &net_gw); + break; + case 241: + inet_aton(optarg, &net_ip); + break; default: + printf("Unknown option %d/%c\n", c, c); return -1; } } @@ -91,6 +132,64 @@ static int parse_options(int argc, char **argv) return 0; } +static const char *make_addr(uint32_t saddr) +{ + struct in_addr addr; + addr.s_addr = ntohl(saddr); + return inet_ntoa(addr); +} + +static void dump_net_cfg(struct sysmobts_net_cfg *net_cfg) +{ + if (net_cfg->mode == NET_MODE_DHCP) { + printf("IP=dhcp\n"); + printf("DNS=\n"); + printf("GATEWAY=\n"); + printf("NETMASK=\n"); + } else { + printf("IP=%s\n", make_addr(net_cfg->ip)); + printf("GATEWAY=%s\n", make_addr(net_cfg->gw)); + printf("DNS=%s\n", make_addr(net_cfg->dns)); + printf("NETMASK=%s\n", make_addr(net_cfg->mask)); + } +} + +static int handle_net(void) +{ + struct sysmobts_net_cfg net_cfg; + int rc; + + switch (action) { + case ACT_NET_GET: + rc = sysmobts_par_get_net(&net_cfg); + if (rc != 0) { + fprintf(stderr, "Error %d\n", rc); + exit(rc); + } + dump_net_cfg(&net_cfg); + break; + case ACT_NET_SET: + memset(&net_cfg, 0, sizeof(net_cfg)); + net_cfg.mode = net_mode; + net_cfg.ip = htonl(net_ip.s_addr); + net_cfg.mask = htonl(net_mask.s_addr); + net_cfg.gw = htonl(net_gw.s_addr); + net_cfg.dns = htonl(net_dns.s_addr); + printf("Going to write\n"); + dump_net_cfg(&net_cfg); + + rc = sysmobts_par_set_net(&net_cfg); + if (rc != 0) { + fprintf(stderr, "Error %d\n", rc); + exit(rc); + } + break; + default: + printf("Unhandled action %d\n", action); + } + return 0; +} + int main(int argc, char **argv) { const char *parname; @@ -101,7 +200,10 @@ int main(int argc, char **argv) if (rc < 0) exit(2); - if (optind >= argc) { + if (action > ACT_SET) + return handle_net(); + + if (optind >= argc && action <+ ACT_NET_GET) { fprintf(stderr, "You must specify the parameter name\n"); exit(2); } -- cgit v1.2.3