initial code about System Information decoding

the idea is to evolve this into something that can match on the GSMTAP
that's generated by OsmoBTS in order to validate the SI generation /
broadcasting of OsmoBTS+OsmoBSC
diff --git a/sysinfo/GSM_SystemInformation.ttcn b/sysinfo/GSM_SystemInformation.ttcn
new file mode 100644
index 0000000..01565c1
--- /dev/null
+++ b/sysinfo/GSM_SystemInformation.ttcn
@@ -0,0 +1,267 @@
+/* Encoding/Decoding routines for GSM System Information messages
+ * according to 3GPP TS 44.018 Version 12.3.0 Release 12 */
+
+/* (C) 2017 by Harald Welte <laforge@gnumonks.org> */
+
+module GSM_SystemInformation {
+
+	import from General_Types all;
+
+	type integer uint32_t (0..4294967295) with { variant "unsigned 32 bit" };
+	type integer uint16_t (0..65535) with { variant "unsigned 16 bit" };
+	type integer uint2_t (0..3) with { variant "unsigned 2 bit" };
+	type integer uint3_t (0..7) with { variant "unsigned 3 bit" };
+	type integer uint4_t (0..15) with { variant "unsigned 4 bit" };
+	type integer uint5_t (0..31) with { variant "unsigned 5 bit" };
+	type integer uint6_t (0..63) with { variant "unsigned 6 bit" };
+	type integer uint7_t (0..127) with { variant "unsigned 7 bit" };
+	type integer uint8_t (0..255) with { variant "unsigned 8 bit" };
+	type integer uint9_t (0..511) with { variant "unsigned 9 bit" };
+	type integer uint10_t (0..1023) with { variant "unsigned 10 bit" };
+	type integer uint11_t (0..2047) with { variant "unsigned 11 bit" };
+	type integer uint12_t (0..4095) with { variant "unsigned 12 bit" };
+
+	type record L2PseudoLength {
+		uint6_t		l2_plen,
+		BIT2		zero_one
+	} with { variant "" };
+
+	template L2PseudoLength t_L2Pseudolength(uint6_t len) := {
+		l2_plen := len,
+		zero_one := '01'B
+	};
+
+	type octetstring RestOctets  with { variant "PADDING(yes), PADDING_PATTERN('00101011'B)" };
+
+	type record MaioHsn {
+	} with { variant "" };
+
+	type union ArfcnOrMaio {
+		uint12_t	arfcn,
+		MaioHsn		maio_hsn
+	} with { variant "" };
+
+	type record SystemInformationHeader {
+		L2PseudoLength	l2_plen,
+		uint4_t		skip_indicator,
+		uint4_t		rr_protocol_discriminator,
+		OCT1		message_type
+	} with { variant "" };
+
+	template SystemInformationHeader t_SiHeader(OCT1 msg_type, uint6_t len) := {
+		l2_plen := t_L2Pseudolength(len),
+		rr_protocol_discriminator := 6,
+		message_type := msg_type
+	};
+
+	external function enc_SystemInformationHeader(in SystemInformationHeader si) return octetstring
+		with { extension "prototype(convert) encode(RAW)" };
+	external function dec_SystemInformationHeader(in octetstring stream) return SystemInformationHeader
+		with { extension "prototype(convert) decode(RAW)" };
+
+	type hexstring GsmBcdString with { variant "HEXORDER(low)" };
+	type GsmBcdString BcdMccMnc with { variant "FIELDLENGTH(6)" };
+
+	/* 24.008 10.5.1.1 */
+	type uint16_t CellIdentity;
+
+	/* 24.008 10.5.1.3 */
+	type record LocationAreaIdentification {
+		BcdMccMnc	mcc_mnc,
+		uint16_t	lac
+	} with { variant "" };
+
+	/* 44.018 10.5.2.1b */
+	type octetstring CellChannelDescription with { variant "FIELDLENGTH(16)" };
+
+	/* 44.018 10.5.2.3 */
+	type record CellOptions {
+		boolean		dn_ind,
+		boolean		pwrc,
+		BIT2		dtx,
+		BIT4		radio_link_timeout
+	} with { variant "" };
+
+	/* 44.018 10.5.2.3a */
+	type record CellOptionsSacch {
+		BIT1		dtx_ext,
+		boolean		pwrc,
+		BIT2		dtx,
+		BIT4		radio_link_timeout
+	} with { variant "" };
+
+	/* 44.018 10.5.2.4 */
+	type record CellSelectionParameters {
+		uint3_t		cell_resel_hyst,
+		uint5_t		ms_txpwr_max_cch,
+		boolean		acs,
+		boolean		neci,
+		uint6_t		rxlev_access_min
+	} with { variant "" };
+
+	/* 44.018 10.5.2.5 */
+	type record ChannelDescription {
+		OCT1		iei,
+		BIT5		chan_type_tdma_offset,
+		uint3_t		tn,
+		uint3_t		tsc,
+		boolean		h,
+		uint12_t	arfcn optional,
+		MaioHsn		maio_hsn optional
+	} with { variant (arfcn) "PRESENCE(h = true)"
+		 variant (maio_hsn) "PRESENCE(h = false)" };
+
+	/* 44.018 10.5.2.11 */
+	type record ControlChannelDescription {
+		boolean		mscrr,
+		boolean		att,
+		uint3_t		bs_ag_blks_res,
+		uint3_t		ccch_conf,
+		boolean		si22ind,
+		uint2_t		cbq3,
+		BIT2		spare,
+		uint3_t		bs_pa_mfrms,
+		uint8_t		t3212
+	} with { variant "" };
+
+	/* 44.018 10.5.2.21 */
+	type record MobileAllocation {
+		OCT1		iei,
+		uint8_t		len,
+		bitstring	ma
+	} with { variant "" };
+
+	/* 44.018 10.5.2.22 */
+	type octetstring NeighbourCellDescription with { variant "FIELDLENGTH(16)" };
+
+	/* 44.018 10.5.2.22a */
+	type octetstring NeighbourCellDescription2 with { variant "FIELDLENGTH(16)" };
+
+	type bitstring AccessControlClass with { variant "FIELDLENGTH(16), BYTEORDER(last)" };
+
+	/* 44.018 10.5.2.29 */
+	type record RachControlParameters {
+		BIT2		max_retrans,
+		BIT4		tx_integer,
+		boolean		cell_barr_access,
+		boolean		re,
+		AccessControlClass ac
+	} with { variant (ac) "FIELDLENGTH(16)" };
+
+	/* 44.018 10.5.2.32 */
+	type RestOctets Si1RestOctets with { variant "FIELDLENGTH(1)" };
+	type RestOctets Si3RestOctets with { variant "FIELDLENGTH(4)" };
+
+	/* 44.018 9.1.31 */
+	type record SystemInformationType1 {
+		SystemInformationHeader	header,
+		CellChannelDescription	cell_chan_desc,
+		RachControlParameters	rach_control,
+		Si1RestOctets		rest_octets
+	} with { variant "" };
+
+	/* 44.018 9.1.32 */
+	type record SystemInformationType2 {
+		SystemInformationHeader	header,
+		NeighbourCellDescription bcch_freq_list,
+		BIT8			ncc_permitted,
+		RachControlParameters	rach_control
+	} with { variant "" };
+
+	/* 44.018 9.1.33 */
+	type record SystemInformationType2bis {
+		SystemInformationHeader		header,
+		NeighbourCellDescription	extd_bcch_freq_list,
+		RachControlParameters		rach_control,
+		OCT1				rest_octets
+	} with { variant "" };
+
+	/* 44.018 9.1.34 */
+	type record SystemInformationType2ter {
+		SystemInformationHeader		header,
+		NeighbourCellDescription2	extd_bcch_freq_list,
+		RachControlParameters		rach_control,
+		OCT4				rest_octets
+	} with { variant "" };
+
+	/* 44.018 9.1.35 */
+	type record SystemInformationType3 {
+		SystemInformationHeader		header,
+		CellIdentity			cell_id,
+		LocationAreaIdentification	lai,
+		ControlChannelDescription	ctrl_chan_desc,
+		CellOptions			cell_options,
+		CellSelectionParameters		cell_sel_par,
+		RachControlParameters		rach_control,
+		Si3RestOctets			rest_octets
+	} with { variant "" };
+
+	/* 44.018 9.1.36 */
+	type record SystemInformationType4 {
+		SystemInformationHeader		header,
+		LocationAreaIdentification	lai,
+		CellSelectionParameters		cell_sel_par,
+		RachControlParameters		rach_control,
+		ChannelDescription		cbch_chan_desc optional,
+		MobileAllocation		cbch_mobile_alloc optional,
+		RestOctets			rest_octets
+	} with { variant "TAG(cbch_chan_desc, iei = '64'O; cbch_mobile_alloc, iei = '72'O)" };
+
+	/* 44.018 9.1.37 */
+	type record SystemInformationType5 {
+		SystemInformationHeader		header,
+		NeighbourCellDescription	bcch_freq_list
+	} with { variant "" };
+
+	/* 44.018 9.1.38 */
+	type record SystemInformationType5bis {
+		SystemInformationHeader		header,
+		NeighbourCellDescription	extd_bcch_freq_list
+	} with { variant "" };
+
+	/* 44.018 9.1.39 */
+	type record SystemInformationType5ter {
+		SystemInformationHeader		header,
+		NeighbourCellDescription2	extd_bcch_freq_list
+	} with { variant "" };
+
+	/* 44.018 9.1.40 */
+	type record SystemInformationType6 {
+		SystemInformationHeader		header,
+		CellIdentity			cell_id,
+		LocationAreaIdentification	lai,
+		CellOptionsSacch		cell_options,
+		BIT8				ncc_permitted,
+		OCT7				rest_octets
+	} with { variant "" };
+
+
+	type union SystemInformation {
+		SystemInformationType1		si1,
+		SystemInformationType2		si2,
+		SystemInformationType2bis	si2bis,
+		SystemInformationType2ter	si2ter,
+		SystemInformationType3		si3,
+		SystemInformationType4		si4,
+		SystemInformationType5		si5,
+		SystemInformationType5bis	si5bis,
+		SystemInformationType5ter	si5ter,
+		SystemInformationType6		si6
+	} with { variant "TAG(si1, header.message_type = '19'O;
+			      si2, header.message_type = '1A'O;
+			      si2bis, header.message_type = '02'O;
+			      si2ter, header.message_type = '03'O;
+			      si3, header.message_type = '1B'O;
+			      si4, header.message_type = '1C'O;
+			      si5, header.message_type = '1D'O;
+			      si5bis, header.message_type = '05'O;
+			      si5ter, header.message_type = '06'O;
+			      si6, header.message_type = '1E'O;
+			)" };
+
+	external function enc_SystemInformation(in SystemInformation si) return octetstring
+		with { extension "prototype(convert) encode(RAW)" };
+	external function dec_SystemInformation(in octetstring stream) return SystemInformation
+		with { extension "prototype(convert) decode(RAW)" };
+
+} with { encode "RAW"; variant "FIELDORDER(msb)" }
diff --git a/sysinfo/Test.ttcn b/sysinfo/Test.ttcn
new file mode 100644
index 0000000..b3506c0
--- /dev/null
+++ b/sysinfo/Test.ttcn
@@ -0,0 +1,28 @@
+module Test {
+	import from GSM_SystemInformation all;
+
+	const octetstring si1 := '5506198fb38000000000000000000000000000e504002b'O;
+	const octetstring si2 := '59061a00000000000000000000000000000000ffe50400'O;
+	const octetstring si3 := '49061b000062f22404d2490301275d40e50400392b2b2b'O;
+	const octetstring si4 := '31061c62f22404d25d40e504002b2b2b2b2b2b2b2b2b2b'O;
+
+	type component dummy_CT {
+	};
+
+	testcase TC_si1() runs on dummy_CT {
+		var SystemInformationHeader hdr := {
+			l2_plen := valueof(t_L2Pseudolength(21)),
+			skip_indicator := 0,
+			rr_protocol_discriminator := 6,
+			message_type := '19'O
+		};
+		log("SI: ", dec_SystemInformation(si1));
+		log("SI: ", dec_SystemInformation(si2));
+		log("SI: ", dec_SystemInformation(si3));
+		log("SI: ", dec_SystemInformation(si4));
+	}
+
+	control {
+		execute(TC_si1());
+	}
+}
diff --git a/sysinfo/regen_makefile.sh b/sysinfo/regen_makefile.sh
new file mode 100755
index 0000000..191da90
--- /dev/null
+++ b/sysinfo/regen_makefile.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+FILES="*.ttcn"
+
+ttcn3_makefilegen -f Test.ttcn $FILES
+sed -i -e 's/# TTCN3_DIR = /TTCN3_DIR = \/usr/' Makefile
+sed -i -e 's/LDFLAGS = /LDFLAGS = -L \/usr\/lib\/titan `pkg-config --libs libnetfilter_conntrack`/' Makefile
+sed -i -e 's/TTCN3_LIB = ttcn3-parallel/TTCN3_LIB = ttcn3/' Makefile
+sed -i -e 's/CPPFLAGS = -D$(PLATFORM) -I$(TTCN3_DIR)\/include/CPPFLAGS = -D$(PLATFORM) -I$(TTCN3_DIR)\/include -I\/usr\/include\/titan/' Makefile