changeset 327:05874f1ddacb

rvinterf & rvtdump: new decoding of G23/GPF packets
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Sun, 20 Apr 2014 20:39:53 +0000
parents 7e878e6b9cf7
children 5d9001f0c3aa
files rvinterf/lowlevel/format.c rvinterf/lowlevel/format_g23.c
diffstat 2 files changed, 199 insertions(+), 71 deletions(-) [+]
line wrap: on
line diff
--- a/rvinterf/lowlevel/format.c	Sat Apr 19 05:23:11 2014 +0000
+++ b/rvinterf/lowlevel/format.c	Sun Apr 20 20:39:53 2014 +0000
@@ -13,14 +13,15 @@
 extern u_char rxpkt[];
 extern size_t rxpkt_len;
 
+char fmtbuf[MAX_PKT_FROM_TARGET*8];	/* size it generously */
+
 void
 print_rv_trace()
 {
-	char buf[MAX_PKT_FROM_TARGET*4];
 	int i, c;
 	char *dp;
 
-	dp = buf;
+	dp = fmtbuf;
 	strcpy(dp, "RV ");
 	dp += 3;
 	/* the SWE static ID is sent MSB first */
@@ -48,17 +49,16 @@
 			*dp++ = c;
 	}
 	*dp = '\0';
-	output_line(buf);
+	output_line(fmtbuf);
 }
 
 void
 print_l1_trace()
 {
-	char buf[MAX_PKT_FROM_TARGET*4+1];
 	int i, c;
 	char *dp;
 
-	dp = buf;
+	dp = fmtbuf;
 	strcpy(dp, "L1: ");
 	dp += 4;
 	for (i = 1; i < rxpkt_len; i++) {
@@ -66,10 +66,10 @@
 		    (rxpkt[i] == '\r' && rxpkt[i+1] == '\n' ||
 		     rxpkt[i] == '\n' && rxpkt[i+1] == '\r')) {
 			*dp = '\0';
-			output_line(buf);
+			output_line(fmtbuf);
 			if (i+2 == rxpkt_len)
 				return;
-			dp = buf;
+			dp = fmtbuf;
 			*dp++ = '+';
 			*dp++ = ' ';
 			i++;
@@ -92,17 +92,16 @@
 	}
 	/* will get here only if no newline sequence at the end */
 	*dp = '\0';
-	output_line(buf);
+	output_line(fmtbuf);
 }
 
 void
 print_etm_output_raw()
 {
-	char buf[MAX_PKT_FROM_TARGET*3+2];
 	int i;
 	char *dp;
 
-	dp = buf;
+	dp = fmtbuf;
 	strcpy(dp, "ETM:");
 	dp += 4;
 	for (i = 1; i < rxpkt_len; i++) {
@@ -110,17 +109,16 @@
 		dp += 3;
 	}
 	*dp = '\0';
-	output_line(buf);
+	output_line(fmtbuf);
 }
 
 void
 print_unknown_packet()
 {
-	char buf[MAX_PKT_FROM_TARGET*3+5];
 	int i;
 	char *dp;
 
-	dp = buf;
+	dp = fmtbuf;
 	strcpy(dp, "UNK:");
 	dp += 4;
 	for (i = 0; i < rxpkt_len; i++) {
@@ -128,5 +126,5 @@
 		dp += 3;
 	}
 	*dp = '\0';
-	output_line(buf);
+	output_line(fmtbuf);
 }
--- a/rvinterf/lowlevel/format_g23.c	Sat Apr 19 05:23:11 2014 +0000
+++ b/rvinterf/lowlevel/format_g23.c	Sun Apr 20 20:39:53 2014 +0000
@@ -1,14 +1,14 @@
 /*
  * This module implements the decoding of G23 trace packets into
- * human-readable form.  Because I have not yet reached the point
- * of integrating the target-side code that generates these packets,
- * I do not yet have the proper understanding of their format.
- * Therefore, the current decoding logic implemented here is based
- * on a heuristic examination of what the packets look like to an
- * uninitiated eye.
+ * human-readable form - or more precisely, traces, system primitives
+ * and other packets that can be emitted through GPF on targets.
+ * The decoding is based on my (Space Falcon's) understanding
+ * of the packet format, which is in turn based on the GPF sources
+ * available to us, now integrated under gsm-fw/gpf.
  */
 
 #include <sys/types.h>
+#include <ctype.h>
 #include <stdio.h>
 #include <string.h>
 #include <strings.h>
@@ -17,80 +17,58 @@
 
 extern u_char rxpkt[];
 extern size_t rxpkt_len;
+extern char fmtbuf[];
+
+static char *fmtbuf_ptr;
 
 static int
-is_well_formed()
+basic_checks()
 {
 	int i, c;
 
 	if (rxpkt_len < 17)
 		return(0);
+	/* check version bits in the header byte */
+	if ((rxpkt[1] & 0xC0) != 0x80)
+		return(0);
+	/* check the length */
+	c = rxpkt[2] | rxpkt[3] << 8;
+	if (c + 4 != rxpkt_len)
+		return(0);
+	/* ensure that the "from" and "to" are printable ASCII */
 	for (i = 8; i < 16; i++) {
 		c = rxpkt[i];
 		if (c < ' ' || c > '~')
 			return(0);
 	}
+	/* basic checks pass */
 	return(1);
 }
 
-static void
-print_well_formed()
+static int
+psprim_extra_checks()
 {
-	char buf[MAX_PKT_FROM_TARGET*4];
 	int i, c;
-	char *dp;
 
-	dp = buf;
-	strcpy(dp, "G23:");
-	dp += 4;
-	for (i = 1; i <= 7; i++) {
-		sprintf(dp, " %02X", rxpkt[i]);
-		dp += 3;
-	}
-	sprintf(dp, " \"%.4s\" \"%.4s\" ", rxpkt+8, rxpkt+12);
-	dp += 15;
-	i = 16;
-	if (rxpkt[i] < 0x20) {
-		sprintf(dp, "%02X ", rxpkt[i]);
-		dp += 3;
-		i++;
+	if (rxpkt_len < 24)
+		return(0);
+	/* "original rcvr" field needs to be printable ASCII */
+	for (i = 16; i < 20; i++) {
+		c = rxpkt[i];
+		if (c < ' ' || c > '~')
+			return(0);
 	}
-	if (rxpkt_len - i == 5 && rxpkt[i] == '%' &&
-	    !rxpkt[i+3] && !rxpkt[i+4]) {
-		sprintf(dp, "%d", rxpkt[i+2] << 8 | rxpkt[i+1]);
-		output_line(buf);
-		return;
-	}
-	*dp++ = '\"';
-	for (; i < rxpkt_len; i++) {
-		c = rxpkt[i];
-		if (c & 0x80) {
-			*dp++ = 'M';
-			*dp++ = '-';
-			c &= 0x7F;
-		}
-		if (c < 0x20) {
-			*dp++ = '^';
-			*dp++ = c + '@';
-		} else if (c == 0x7F) {
-			*dp++ = '^';
-			*dp++ = '?';
-		} else
-			*dp++ = c;
-	}
-	*dp++ = '\"';
-	*dp = '\0';
-	output_line(buf);
+	/* checks pass */
+	return(1);
 }
 
 static void
 print_malformed()
 {
-	char buf[MAX_PKT_FROM_TARGET*3+6];
 	int i;
 	char *dp;
 
-	dp = buf;
+	dp = fmtbuf;
 	strcpy(dp, "G23 UNK:");
 	dp += 8;
 	for (i = 1; i < rxpkt_len; i++) {
@@ -98,14 +76,166 @@
 		dp += 3;
 	}
 	*dp = '\0';
-	output_line(buf);
+	output_line(fmtbuf);
+}
+
+static int
+entity_name_well_formed(p)
+	char *p;
+{
+	int i, len;
+
+	if (!isupper(p[0]))
+		return(0);
+	for (i = 0; i < 4; i++)
+		if (!isalnum(p[i]))
+			break;
+	len = i;
+	for (; i < 4; i++)
+		if (p[i] != ' ')
+			return(0);
+	return(len);
+}
+
+static void
+print_entity_name(raw)
+	char *raw;
+{
+	int len;
+
+	len = entity_name_well_formed(raw);
+	if (len)
+		sprintf(fmtbuf_ptr, "%.*s", len, raw);
+	else
+		sprintf(fmtbuf_ptr, "\"%.4s\"", raw);
+	fmtbuf_ptr = index(fmtbuf_ptr, '\0');
+}
+
+static void
+print_common_hdr(typestr)
+	char *typestr;
+{
+	sprintf(fmtbuf, "G23 %s id=%02X ts=%02X%02X%02X%02X ", typestr,
+		rxpkt[1], rxpkt[7], rxpkt[6], rxpkt[5], rxpkt[4]);
+	fmtbuf_ptr = index(fmtbuf, '\0');
+	print_entity_name(rxpkt + 8);
+	*fmtbuf_ptr++ = '-';
+	*fmtbuf_ptr++ = '>';
+	print_entity_name(rxpkt + 12);
+	*fmtbuf_ptr++ = ' ';
+}
+
+static void
+format_text(start_off)
+{
+	int i, c;
+
+	*fmtbuf_ptr++ = '\"';
+	for (i = start_off; i < rxpkt_len; i++) {
+		c = rxpkt[i];
+		if (c & 0x80) {
+			*fmtbuf_ptr++ = 'M';
+			*fmtbuf_ptr++ = '-';
+			c &= 0x7F;
+		}
+		if (c < 0x20) {
+			*fmtbuf_ptr++ = '^';
+			*fmtbuf_ptr++ = c + '@';
+		} else if (c == 0x7F) {
+			*fmtbuf_ptr++ = '^';
+			*fmtbuf_ptr++ = '?';
+		} else
+			*fmtbuf_ptr++ = c;
+	}
+	*fmtbuf_ptr++ = '\"';
+	*fmtbuf_ptr = '\0';
+	output_line(fmtbuf);
+}
+
+static void
+format_compressed_trace(start_off)
+{
+	int i;
+
+	i = start_off + 1;
+	sprintf(fmtbuf_ptr, "%d", rxpkt[i+1] << 8 | rxpkt[i]);
+	fmtbuf_ptr = index(fmtbuf_ptr, '\0');
+	i += 4;
+	for (; i < rxpkt_len; i++) {
+		sprintf(fmtbuf_ptr, " %02X", rxpkt[i]);
+		fmtbuf_ptr += 3;
+	}
+	*fmtbuf_ptr = '\0';
+	output_line(fmtbuf);
+}
+
+static void
+format_trace()
+{
+	int i;
+
+	i = 16;
+	if (rxpkt[i] < 0x20) {
+		sprintf(fmtbuf_ptr, "tc=%02X ", rxpkt[i]);
+		fmtbuf_ptr += 6;
+		i++;
+	}
+	if (rxpkt_len - i >= 5 && rxpkt[i] == '%' &&
+	    !rxpkt[i+3] && !rxpkt[i+4])
+		format_compressed_trace(i);
+	else
+		format_text(i);
+}
+
+static void
+format_psprim()
+{
+	int i;
+
+	/* original destination */
+	*fmtbuf_ptr++ = '(';
+	print_entity_name(rxpkt + 16);
+	*fmtbuf_ptr++ = ')';
+	/* opcode */
+	sprintf(fmtbuf_ptr, " %02X%02X%02X%02X",
+		rxpkt[23], rxpkt[22], rxpkt[21], rxpkt[20]);
+	fmtbuf_ptr += 9;
+	for (i = 24; i < rxpkt_len; i++) {
+		sprintf(fmtbuf_ptr, " %02X", rxpkt[i]);
+		fmtbuf_ptr += 3;
+	}
+	*fmtbuf_ptr = '\0';
+	output_line(fmtbuf);
 }
 
 void
 print_g23_trace()
 {
-	if (is_well_formed())
-		print_well_formed();
-	else
+	if (!basic_checks()) {
 		print_malformed();
+		return;
+	}
+	/* dispatch by type */
+	switch (rxpkt[1] & 0x30) {
+	case 0x10:
+		/* PS primitive */
+		if (psprim_extra_checks()) {
+			print_common_hdr("PSprim");
+			format_psprim();
+		} else
+			print_malformed();
+		return;
+	case 0x20:
+		/* trace */
+		print_common_hdr("trace");
+		format_trace();
+		return;
+	case 0x30:
+		/* system primitive */
+		print_common_hdr("sysprim");
+		format_text(16);
+		return;
+	default:
+		print_malformed();
+	}
 }