diff loadtools/simatr.c @ 790:0bbe0213812d

fc-simint put together, compiles
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 19 Mar 2021 04:40:05 +0000
parents
children a31ae776de6e
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/loadtools/simatr.c	Fri Mar 19 04:40:05 2021 +0000
@@ -0,0 +1,92 @@
+/*
+ * This module implements the stage in fc-simint where ATR bytes
+ * received from simagent are validated.
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+extern int sim_allow_spenh;
+
+extern u_char sim_atr[];
+extern unsigned sim_atr_len;
+
+void
+sim_atr_validate()
+{
+	unsigned b, p, y, nhist, have_tck;
+
+	if (sim_atr_len < 2) {
+too_short:	fprintf(stderr, "error: ATR from simagent is too short\n");
+		exit(1);
+	}
+	b = sim_atr[1];
+	p = 2;
+	nhist = b & 0xF;
+	y = b & 0xF0;
+	have_tck = 0;
+	while (y) {
+		if (y & 0x10) {
+			if (p >= sim_atr_len)
+				goto too_short;
+			p++;
+		}
+		if (y & 0x20) {
+			if (p >= sim_atr_len)
+				goto too_short;
+			p++;
+		}
+		if (y & 0x40) {
+			if (p >= sim_atr_len)
+				goto too_short;
+			p++;
+		}
+		if (y & 0x80) {
+			if (p >= sim_atr_len)
+				goto too_short;
+			b = sim_atr[p++];
+			y = b & 0xF0;
+			if (b & 0x0F)
+				have_tck = 1;
+		} else
+			y = 0;
+	}
+	p += nhist + have_tck;
+	if (p > sim_atr_len)
+		goto too_short;
+	if (p < sim_atr_len) {
+		fprintf(stderr, "error: ATR from simagent is too long\n");
+		exit(1);
+	}
+	if (!have_tck)
+		return;
+	/* validate TCK */
+	b = 0;
+	for (p = 1; p < sim_atr_len; p++)
+		b ^= sim_atr[p];
+	if (b) {
+		fprintf(stderr, "error: ATR checksum is bad\n");
+		exit(1);
+	}
+}
+
+void
+sim_spenh_logic()
+{
+	static char *targv[2] = {"spenh", 0};
+
+	if (sim_atr_len < 3 || !(sim_atr[1] & 0x10) || (sim_atr[2] < 0x94)) {
+		printf("ATR indicates no support for speed enhancement\n");
+		return;
+	}
+	if (!sim_allow_spenh) {
+		printf("Speed enhancement disabled with -n option\n");
+		return;
+	}
+	tpinterf_make_cmd(targv);
+	if (tpinterf_send_cmd() < 0)
+		exit(1);
+	if (tpinterf_pass_output(10))
+		exit(1);
+}