summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte (local) <laflocal@hanuman.gnumonks.org>2009-12-28 14:52:03 +0100
committerHarald Welte (local) <laflocal@hanuman.gnumonks.org>2009-12-28 14:52:03 +0100
commitc6e0e9a4e386a6333d282e77f56be2c9ff26d383 (patch)
treec22f6cbe9ce8e1c229ce492f5a8e2342420ba66d
parentd40594b364a580b958c3412a775eaaf92beaba4e (diff)
parent66169152f6c4458cf7380d6e447fa74e5ae66654 (diff)
Merge remote branch 'origin/master' into 26c3
-rw-r--r--openbsc/src/Makefile.am2
-rw-r--r--openbsc/src/abis_nm.c143
-rw-r--r--openbsc/src/gsm_04_11.c27
-rw-r--r--openbsc/src/ipaccess/ipaccess-config.c84
-rw-r--r--openbsc/src/ipaccess/ipaccess-firmware.c12
5 files changed, 239 insertions, 29 deletions
diff --git a/openbsc/src/Makefile.am b/openbsc/src/Makefile.am
index 080fed4d5..e665c99eb 100644
--- a/openbsc/src/Makefile.am
+++ b/openbsc/src/Makefile.am
@@ -2,7 +2,7 @@ INCLUDES = $(all_includes) -I$(top_srcdir)/include
AM_CFLAGS=-Wall
sbin_PROGRAMS = bsc_hack bs11_config ipaccess-find ipaccess-config \
- isdnsync bsc_mgcp ipaccess_firmware ipaccess-proxy
+ isdnsync bsc_mgcp ipaccess-firmware ipaccess-proxy
noinst_LIBRARIES = libbsc.a libmsc.a libvty.a libsccp.a
noinst_HEADERS = vty/cardshell.h
diff --git a/openbsc/src/abis_nm.c b/openbsc/src/abis_nm.c
index f62356dcc..8b3ac9c62 100644
--- a/openbsc/src/abis_nm.c
+++ b/openbsc/src/abis_nm.c
@@ -47,6 +47,7 @@
#define OM_ALLOC_SIZE 1024
#define OM_HEADROOM_SIZE 128
+#define IPACC_SEGMENT_SIZE 245
/* unidirectional messages from BTS to BSC */
static const enum abis_nm_msgtype reports[] = {
@@ -1225,11 +1226,19 @@ static int sw_load_init(struct abis_nm_sw *sw)
fill_om_fom_hdr(oh, len, NM_MT_LOAD_INIT, sw->obj_class,
sw->obj_instance[0], sw->obj_instance[1],
sw->obj_instance[2]);
-
- /* FIXME: this is BS11 specific format */
- msgb_tlv_put(msg, NM_ATT_FILE_ID, sw->file_id_len, sw->file_id);
- msgb_tlv_put(msg, NM_ATT_FILE_VERSION, sw->file_version_len,
- sw->file_version);
+
+ if (sw->bts->type == GSM_BTS_TYPE_NANOBTS) {
+ msgb_v_put(msg, NM_ATT_SW_DESCR);
+ msgb_tl16v_put(msg, NM_ATT_FILE_ID, sw->file_id_len, sw->file_id);
+ msgb_tl16v_put(msg, NM_ATT_FILE_VERSION, sw->file_version_len,
+ sw->file_version);
+ } else if (sw->bts->type == GSM_BTS_TYPE_BS11) {
+ msgb_tlv_put(msg, NM_ATT_FILE_ID, sw->file_id_len, sw->file_id);
+ msgb_tlv_put(msg, NM_ATT_FILE_VERSION, sw->file_version_len,
+ sw->file_version);
+ } else {
+ return -1;
+ }
msgb_tv_put(msg, NM_ATT_WINDOW_SIZE, sw->window_size);
return abis_nm_sendmsg(sw->bts, msg);
@@ -1287,7 +1296,24 @@ static int sw_load_segment(struct abis_nm_sw *sw)
/* we only now know the exact length for the OM hdr */
len = strlen(line_buf)+2;
break;
+ case GSM_BTS_TYPE_NANOBTS: {
+ static_assert(sizeof(seg_buf) >= IPACC_SEGMENT_SIZE, buffer_big_enough);
+ len = read(sw->fd, &seg_buf, IPACC_SEGMENT_SIZE);
+ if (len < 0) {
+ perror("read failed");
+ return -EINVAL;
+ }
+
+ if (len != IPACC_SEGMENT_SIZE)
+ sw->last_seg = 1;
+
+ ++sw->seg_in_window;
+ msgb_tl16v_put(msg, NM_ATT_IPACC_FILE_DATA, len, (const u_int8_t *) seg_buf);
+ len += 3;
+ break;
+ }
default:
+ LOGP(DNM, LOGL_ERROR, "sw_load_segment needs implementation for the BTS.\n");
/* FIXME: Other BTS types */
return -1;
}
@@ -1311,10 +1337,18 @@ static int sw_load_end(struct abis_nm_sw *sw)
sw->obj_instance[0], sw->obj_instance[1],
sw->obj_instance[2]);
- /* FIXME: this is BS11 specific format */
- msgb_tlv_put(msg, NM_ATT_FILE_ID, sw->file_id_len, sw->file_id);
- msgb_tlv_put(msg, NM_ATT_FILE_VERSION, sw->file_version_len,
- sw->file_version);
+ if (sw->bts->type == GSM_BTS_TYPE_NANOBTS) {
+ msgb_v_put(msg, NM_ATT_SW_DESCR);
+ msgb_tl16v_put(msg, NM_ATT_FILE_ID, sw->file_id_len, sw->file_id);
+ msgb_tl16v_put(msg, NM_ATT_FILE_VERSION, sw->file_version_len,
+ sw->file_version);
+ } else if (sw->bts->type == GSM_BTS_TYPE_BS11) {
+ msgb_tlv_put(msg, NM_ATT_FILE_ID, sw->file_id_len, sw->file_id);
+ msgb_tlv_put(msg, NM_ATT_FILE_VERSION, sw->file_version_len,
+ sw->file_version);
+ } else {
+ return -1;
+ }
return abis_nm_sendmsg(sw->bts, msg);
}
@@ -1339,9 +1373,57 @@ static int sw_activate(struct abis_nm_sw *sw)
return abis_nm_sendmsg(sw->bts, msg);
}
+struct sdp_firmware {
+ char magic[4];
+ char more_magic[4];
+ unsigned int header_length;
+ unsigned int file_length;
+} __attribute__ ((packed));
+
static int parse_sdp_header(struct abis_nm_sw *sw)
{
- return -1;
+ struct sdp_firmware firmware_header;
+ int rc;
+ struct stat stat;
+
+ rc = read(sw->fd, &firmware_header, sizeof(firmware_header));
+ if (rc != sizeof(firmware_header)) {
+ LOGP(DNM, LOGL_ERROR, "Could not read SDP file header.\n");
+ return -1;
+ }
+
+ if (strncmp(firmware_header.magic, " SDP", 4) != 0) {
+ LOGP(DNM, LOGL_ERROR, "The magic number1 is wrong.\n");
+ return -1;
+ }
+
+ if (firmware_header.more_magic[0] != 0x10 ||
+ firmware_header.more_magic[1] != 0x02 ||
+ firmware_header.more_magic[2] != 0x00 ||
+ firmware_header.more_magic[3] != 0x00) {
+ LOGP(DNM, LOGL_ERROR, "The more magic number is wrong.\n");
+ return -1;
+ }
+
+
+ if (fstat(sw->fd, &stat) == -1) {
+ LOGP(DNM, LOGL_ERROR, "Could not stat the file.\n");
+ return -1;
+ }
+
+ if (ntohl(firmware_header.file_length) != stat.st_size) {
+ LOGP(DNM, LOGL_ERROR, "The filesizes do not match.\n");
+ return -1;
+ }
+
+ /* go back to the start as we checked the whole filesize.. */
+ lseek(sw->fd, 0l, SEEK_SET);
+ LOGP(DNM, LOGL_NOTICE, "The ipaccess SDP header is not fully understood.\n"
+ "There might be checksums in the file that are not\n"
+ "verified and incomplete firmware might be flashed.\n"
+ "There is absolutely no WARRANTY that flashing will\n"
+ "work.\n");
+ return 0;
}
static int sw_open_file(struct abis_nm_sw *sw, const char *fname)
@@ -1376,18 +1458,17 @@ static int sw_open_file(struct abis_nm_sw *sw, const char *fname)
rewind(sw->stream);
break;
case GSM_BTS_TYPE_NANOBTS:
- sw->stream = fdopen(sw->fd, "r");
- if (!sw->stream) {
- perror("fdopen");
- return -1;
- }
-
/* TODO: extract that from the filename or content */
rc = parse_sdp_header(sw);
if (rc < 0) {
fprintf(stderr, "Could not parse the ipaccess SDP header\n");
return -1;
}
+
+ strcpy((char *)sw->file_id, "id");
+ sw->file_id_len = 3;
+ strcpy((char *)sw->file_version, "version");
+ sw->file_version_len = 8;
break;
default:
/* We don't know how to treat them yet */
@@ -1500,6 +1581,7 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb)
sw->cbfn(GSM_HOOK_NM_SWLOAD,
NM_MT_LOAD_END_ACK, mb,
sw->cb_data, NULL);
+ rc = 0;
break;
case NM_MT_LOAD_END_NACK:
if (sw->forced) {
@@ -1576,10 +1658,26 @@ int abis_nm_software_load(struct gsm_bts *bts, const char *fname,
return -EBUSY;
sw->bts = bts;
- sw->obj_class = NM_OC_SITE_MANAGER;
- sw->obj_instance[0] = 0xff;
- sw->obj_instance[1] = 0xff;
- sw->obj_instance[2] = 0xff;
+
+ switch (bts->type) {
+ case GSM_BTS_TYPE_BS11:
+ sw->obj_class = NM_OC_SITE_MANAGER;
+ sw->obj_instance[0] = 0xff;
+ sw->obj_instance[1] = 0xff;
+ sw->obj_instance[2] = 0xff;
+ break;
+ case GSM_BTS_TYPE_NANOBTS:
+ sw->obj_class = NM_OC_BASEB_TRANSC;
+ sw->obj_instance[0] = 0x00;
+ sw->obj_instance[1] = 0x00;
+ sw->obj_instance[2] = 0xff;
+ break;
+ case GSM_BTS_TYPE_UNKNOWN:
+ default:
+ LOGPC(DNM, LOGL_ERROR, "Software Load not properly implemented.\n");
+ return -1;
+ break;
+ }
sw->window_size = win_size;
sw->state = SW_STATE_WAIT_INITACK;
sw->cbfn = cbfn;
@@ -1607,7 +1705,10 @@ int abis_nm_software_load_status(struct gsm_bts *bts)
return rc;
}
- percent = (ftell(sw->stream) * 100) / st.st_size;
+ if (sw->stream)
+ percent = (ftell(sw->stream) * 100) / st.st_size;
+ else
+ percent = (lseek(sw->fd, 0, SEEK_CUR) * 100) / st.st_size;
return percent;
}
diff --git a/openbsc/src/gsm_04_11.c b/openbsc/src/gsm_04_11.c
index c3a49f399..7f570b8e5 100644
--- a/openbsc/src/gsm_04_11.c
+++ b/openbsc/src/gsm_04_11.c
@@ -948,6 +948,33 @@ int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id)
switch(msg_type) {
case GSM411_MT_CP_DATA:
DEBUGPC(DSMS, "RX SMS CP-DATA\n");
+
+ /* 5.4: For MO, if a CP-DATA is received for a new
+ * transaction, equals reception of an implicit
+ * last CP-ACK for previous transaction */
+ if (trans->sms.cp_state == GSM411_CPS_IDLE) {
+ int i;
+ struct gsm_trans *ptrans;
+
+ /* Scan through all remote initiated transactions */
+ for (i=8; i<15; i++) {
+ if (i == transaction_id)
+ continue;
+
+ ptrans = trans_find_by_id(lchan->subscr,
+ GSM48_PDISC_SMS, i);
+ if (!ptrans)
+ continue;
+
+ DEBUGP(DSMS, "Implicit CP-ACK for trans_id=%x\n", i);
+
+ /* Finish it for good */
+ bsc_del_timer(&ptrans->sms.cp_timer);
+ ptrans->sms.cp_state = GSM411_CPS_IDLE;
+ trans_free(ptrans);
+ }
+ }
+
/* 5.2.3.1.3: MO state exists when SMC has received
* CP-DATA, including sending of the assoc. CP-ACK */
/* 5.2.3.2.4: MT state exists when SMC has received
diff --git a/openbsc/src/ipaccess/ipaccess-config.c b/openbsc/src/ipaccess/ipaccess-config.c
index 7df4cefeb..c7d223438 100644
--- a/openbsc/src/ipaccess/ipaccess-config.c
+++ b/openbsc/src/ipaccess/ipaccess-config.c
@@ -1,6 +1,8 @@
/* ip.access nanoBTS configuration tool */
/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2009 by Holger Hans Peter Freyther
+ * (C) 2009 by On Waves
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
@@ -48,6 +50,7 @@ static char *prim_oml_ip;
static char *unit_id;
static u_int16_t nv_flags;
static u_int16_t nv_mask;
+static char *software = NULL;
/*
static u_int8_t prim_oml_attr[] = { 0x95, 0x00, 7, 0x88, 192, 168, 100, 11, 0x00, 0x00 };
@@ -164,6 +167,58 @@ static int nm_sig_cb(unsigned int subsys, unsigned int signal,
return 0;
}
+/* callback function passed to the ABIS OML code */
+static int percent;
+static int percent_old;
+static int swload_cbfn(unsigned int hook, unsigned int event, struct msgb *msg,
+ void *data, void *param)
+{
+ struct gsm_bts *bts;
+
+ if (hook != GSM_HOOK_NM_SWLOAD)
+ return 0;
+
+ bts = (struct gsm_bts *) data;
+
+ switch (event) {
+ case NM_MT_LOAD_INIT_ACK:
+ fprintf(stdout, "Software Load Initiate ACK\n");
+ break;
+ case NM_MT_LOAD_INIT_NACK:
+ fprintf(stderr, "ERROR: Software Load Initiate NACK\n");
+ exit(5);
+ break;
+ case NM_MT_LOAD_END_ACK:
+ fprintf(stderr, "LOAD END ACK...");
+#if 0
+ if (data) {
+ /* we did a safety load and must activate it */
+ abis_nm_software_activate(g_bts, fname_safety,
+ swload_cbfn, bts);
+ sleep(5);
+ }
+#endif
+ break;
+ case NM_MT_LOAD_END_NACK:
+ fprintf(stderr, "ERROR: Software Load End NACK\n");
+ exit(3);
+ break;
+ case NM_MT_ACTIVATE_SW_NACK:
+ fprintf(stderr, "ERROR: Activate Software NACK\n");
+ exit(4);
+ break;
+ case NM_MT_ACTIVATE_SW_ACK:
+ break;
+ case NM_MT_LOAD_SEG_ACK:
+ percent = abis_nm_software_load_status(bts);
+ if (percent > percent_old)
+ printf("Software Download Progress: %d%%\n", percent);
+ percent_old = percent;
+ break;
+ }
+ return 0;
+}
+
static void bootstrap_om(struct gsm_bts *bts)
{
int len;
@@ -226,6 +281,7 @@ static void bootstrap_om(struct gsm_bts *bts)
printf("restarting BTS\n");
abis_nm_ipaccess_restart(bts);
}
+
}
void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx)
@@ -257,13 +313,23 @@ int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
{
if (evt == EVT_STATECHG_OPER &&
obj_class == NM_OC_RADIO_CARRIER &&
- new_state->availability == 3 &&
- net_listen_testnr) {
+ new_state->availability == 3) {
struct gsm_bts_trx *trx = obj;
- u_int8_t phys_config[] = { 0x02, 0x0a, 0x00, 0x01, 0x02 };
- abis_nm_perform_test(trx->bts, 2, 0, 0, 0xff,
- net_listen_testnr, 1,
- phys_config, sizeof(phys_config));
+
+ if (net_listen_testnr) {
+ u_int8_t phys_config[] = { 0x02, 0x0a, 0x00, 0x01, 0x02 };
+ abis_nm_perform_test(trx->bts, 2, 0, 0, 0xff,
+ net_listen_testnr, 1,
+ phys_config, sizeof(phys_config));
+ } else if (software) {
+ int rc;
+ printf("Attempting software upload with '%s'\n", software);
+ rc = abis_nm_software_load(trx->bts, software, 19, 0, swload_cbfn, trx->bts);
+ if (rc < 0) {
+ fprintf(stderr, "Failed to start software load\n");
+ exit(-3);
+ }
+ }
}
return 0;
}
@@ -310,9 +376,10 @@ int main(int argc, char **argv)
{ "help", 0, 0, 'h' },
{ "listen", 1, 0, 'l' },
{ "stream-id", 1, 0, 's' },
+ { "software", 1, 0, 'd' },
};
- c = getopt_long(argc, argv, "u:o:rn:l:hs:", long_options,
+ c = getopt_long(argc, argv, "u:o:rn:l:hs:d:", long_options,
&option_index);
if (c == -1)
@@ -343,6 +410,9 @@ int main(int argc, char **argv)
case 's':
stream_id = atoi(optarg);
break;
+ case 'd':
+ software = strdup(optarg);
+ break;
case 'h':
print_usage();
print_help();
diff --git a/openbsc/src/ipaccess/ipaccess-firmware.c b/openbsc/src/ipaccess/ipaccess-firmware.c
index 4349f99da..8fdc2e9a4 100644
--- a/openbsc/src/ipaccess/ipaccess-firmware.c
+++ b/openbsc/src/ipaccess/ipaccess-firmware.c
@@ -52,6 +52,7 @@ static char more_magic[] = { 0x10, 0x02, 0x00, 0x0 };
static void analyze_file(int fd)
{
struct sdp_firmware *firmware_header;
+ struct stat stat;
char buf[4096];
int rc;
@@ -80,6 +81,17 @@ static void analyze_file(int fd)
printf("text2: %.64s\n", firmware_header->text2);
printf("time: %.8s\n", firmware_header->time);
printf("date: %.8s\n", firmware_header->date);
+
+ /* verify the file */
+ if (fstat(fd, &stat) == -1) {
+ perror("Can not stat the file");
+ return;
+ }
+
+ if (ntohl(firmware_header->file_length) != stat.st_size) {
+ fprintf(stderr, "The filesize and the header do not match.\n");
+ return;
+ }
}
int main(int argc, char** argv)