changeset 39:2467b7acad1f

fc-simtool smsp-restore implemented
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 12 Feb 2021 21:54:01 +0000
parents f5a26c1d0b93
children 4c240a37e7c4
files simtool/Makefile simtool/dispatch.c simtool/smsp_restore.c
diffstat 3 files changed, 247 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/simtool/Makefile	Fri Feb 12 20:39:15 2021 +0000
+++ b/simtool/Makefile	Fri Feb 12 21:54:01 2021 +0000
@@ -4,8 +4,8 @@
 OBJS=	a38.o chv.o curfile.o dispatch.o dumpdir.o grcard1.o grcard2.o hlread.o\
 	main.o pbcommon.o pbdump.o pberase.o pbupd_file.o pbupd_imm.o \
 	pbupd_immhex.o readcmd.o readops.o restorebin.o savebin.o script.o \
-	select.o smsp_common.o smsp_dump.o sysmo.o telsum.o writecmd.o \
-	writeops.o
+	select.o smsp_common.o smsp_dump.o smsp_restore.o sysmo.o telsum.o \
+	writecmd.o writeops.o
 LIBS=	../libcommon/libcommon.a
 INSTBIN=/opt/freecalypso/bin
 
--- a/simtool/dispatch.c	Fri Feb 12 20:39:15 2021 +0000
+++ b/simtool/dispatch.c	Fri Feb 12 21:54:01 2021 +0000
@@ -39,6 +39,7 @@
 extern int cmd_save_sms_bin();
 extern int cmd_select();
 extern int cmd_smsp_dump();
+extern int cmd_smsp_restore();
 extern int cmd_spn();
 extern int cmd_telecom_sum();
 extern int cmd_uicc_dir();
@@ -103,6 +104,7 @@
 	{"select", 1, 1, cmd_select},
 	{"sim-resp", 0, 0, display_sim_resp_in_hex},
 	{"smsp-dump", 0, 1, cmd_smsp_dump},
+	{"smsp-restore", 1, 1, cmd_smsp_restore},
 	{"spn", 0, 0, cmd_spn},
 	{"telecom-sum", 0, 0, cmd_telecom_sum},
 	{"uicc-dir", 0, 0, cmd_uicc_dir},
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simtool/smsp_restore.c	Fri Feb 12 21:54:01 2021 +0000
@@ -0,0 +1,243 @@
+/*
+ * This module implements the smsp-restore command.
+ */
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <string.h>
+#include <strings.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "curfile.h"
+
+extern char *alpha_from_file_qstring();
+extern char *alpha_from_file_hex();
+
+static char *
+parse_da(cp, bina, filename_for_errs, lineno_for_errs)
+	char *cp, *filename_for_errs;
+	u_char *bina;
+{
+	u_char digits[20];
+	unsigned ndigits, num_digit_bytes;
+	int c;
+
+	if (digit_char_to_gsm(*cp) < 0) {
+inv_syntax:	fprintf(stderr, "%s line %d: DA= parameter invalid syntax\n",
+			filename_for_errs, lineno_for_errs);
+		return(0);
+	}
+	for (ndigits = 0; ; ndigits++) {
+		c = digit_char_to_gsm(*cp);
+		if (c < 0)
+			break;
+		cp++;
+		if (ndigits >= 20) {
+			fprintf(stderr, "%s line %d: too many number digits\n",
+				filename_for_errs, lineno_for_errs);
+			return(0);
+		}
+		digits[ndigits] = c;
+	}
+	bina[0] = ndigits;
+	if (ndigits & 1)
+		digits[ndigits++] = 0xF;
+	num_digit_bytes = ndigits >> 1;
+	pack_digit_bytes(digits, bina + 2, num_digit_bytes);
+	if (*cp++ != ',')
+		goto inv_syntax;
+	if (cp[0] != '0' || cp[1] != 'x' && cp[1] != 'X' || !isxdigit(cp[2]) ||
+	    !isxdigit(cp[3]) || !isspace(cp[4]))
+		goto inv_syntax;
+	bina[1] = strtoul(cp, 0, 16);
+	cp += 5;
+	while (isspace(*cp))
+		cp++;
+	return(cp);
+}
+
+static char *
+parse_sc(cp, bina, filename_for_errs, lineno_for_errs)
+	char *cp, *filename_for_errs;
+	u_char *bina;
+{
+	u_char digits[20];
+	unsigned ndigits, num_digit_bytes;
+	int c;
+
+	if (digit_char_to_gsm(*cp) < 0) {
+inv_syntax:	fprintf(stderr, "%s line %d: SC= parameter invalid syntax\n",
+			filename_for_errs, lineno_for_errs);
+		return(0);
+	}
+	for (ndigits = 0; ; ndigits++) {
+		c = digit_char_to_gsm(*cp);
+		if (c < 0)
+			break;
+		cp++;
+		if (ndigits >= 20) {
+			fprintf(stderr, "%s line %d: too many number digits\n",
+				filename_for_errs, lineno_for_errs);
+			return(0);
+		}
+		digits[ndigits] = c;
+	}
+	if (ndigits & 1)
+		digits[ndigits++] = 0xF;
+	num_digit_bytes = ndigits >> 1;
+	bina[0] = num_digit_bytes + 1;
+	pack_digit_bytes(digits, bina + 2, num_digit_bytes);
+	if (*cp++ != ',')
+		goto inv_syntax;
+	if (cp[0] != '0' || cp[1] != 'x' && cp[1] != 'X' || !isxdigit(cp[2]) ||
+	    !isxdigit(cp[3]) || !isspace(cp[4]))
+		goto inv_syntax;
+	bina[1] = strtoul(cp, 0, 16);
+	cp += 5;
+	while (isspace(*cp))
+		cp++;
+	return(cp);
+}
+
+static
+process_record(line, filename_for_errs, lineno_for_errs)
+	char *line, *filename_for_errs;
+{
+	unsigned recno;
+	u_char record[255], *fixp;
+	char *cp;
+
+	recno = strtoul(line+1, 0, 10);
+	if (recno < 1 || recno > curfile_record_count) {
+		fprintf(stderr, "%s line %d: record number is out of range\n",
+			filename_for_errs, lineno_for_errs);
+		return(-1);
+	}
+	cp = line + 1;
+	while (isdigit(*cp))
+		cp++;
+	if (*cp++ != ':') {
+inv_syntax:	fprintf(stderr, "%s line %d: invalid syntax\n",
+			filename_for_errs, lineno_for_errs);
+		return(-1);
+	}
+	while (isspace(*cp))
+		cp++;
+	memset(record, 0xFF, curfile_record_len);
+	fixp = record + curfile_record_len - 28;
+	if (!strncasecmp(cp, "DA=", 3)) {
+		cp += 3;
+		cp = parse_da(cp, fixp + 1, filename_for_errs, lineno_for_errs);
+		if (!cp)
+			return(-1);
+		fixp[0] &= 0xFE;
+	}
+	if (!strncasecmp(cp, "SC=", 3)) {
+		cp += 3;
+		cp = parse_sc(cp, fixp+13, filename_for_errs, lineno_for_errs);
+		if (!cp)
+			return(-1);
+		fixp[0] &= 0xFD;
+	}
+	if (!strncasecmp(cp, "PID=", 4)) {
+		cp += 4;
+		if (!isdigit(*cp)) {
+			fprintf(stderr,
+				"%s line %d: PID= parameter invalid syntax\n",
+				filename_for_errs, lineno_for_errs);
+			return(-1);
+		}
+		fixp[25] = strtoul(cp, 0, 0);
+		while (*cp && !isspace(*cp))
+			cp++;
+		while (isspace(*cp))
+			cp++;
+	}
+	if (!strncasecmp(cp, "DCS=", 4)) {
+		cp += 4;
+		if (!isdigit(*cp)) {
+			fprintf(stderr,
+				"%s line %d: DCS= parameter invalid syntax\n",
+				filename_for_errs, lineno_for_errs);
+			return(-1);
+		}
+		fixp[26] = strtoul(cp, 0, 0);
+		while (*cp && !isspace(*cp))
+			cp++;
+		while (isspace(*cp))
+			cp++;
+	}
+	if (!strncasecmp(cp, "VP=", 3)) {
+		cp += 3;
+		if (!isdigit(*cp)) {
+			fprintf(stderr,
+				"%s line %d: VP= parameter invalid syntax\n",
+				filename_for_errs, lineno_for_errs);
+			return(-1);
+		}
+		fixp[27] = strtoul(cp, 0, 0);
+		while (*cp && !isspace(*cp))
+			cp++;
+		while (isspace(*cp))
+			cp++;
+	}
+	if (*cp == '"') {
+		cp++;
+		cp = alpha_from_file_qstring(cp, record,
+					     curfile_record_len - 28,
+					     filename_for_errs,
+					     lineno_for_errs);
+		if (!cp)
+			return(-1);
+	} else if (!strncasecmp(cp, "HEX", 3)) {
+		cp += 3;
+		while (isspace(*cp))
+			cp++;
+		cp = alpha_from_file_hex(cp, record, curfile_record_len - 28,
+					 filename_for_errs, lineno_for_errs);
+		if (!cp)
+			return(-1);
+	} else
+		goto inv_syntax;
+	while (isspace(*cp))
+		cp++;
+	if (*cp)
+		goto inv_syntax;
+	return update_rec_op(recno, 0x04, record, curfile_record_len);
+}
+
+cmd_smsp_restore(argc, argv)
+	char **argv;
+{
+	int rc;
+	FILE *inf;
+	int lineno;
+	char linebuf[1024];
+
+	rc = select_ef_smsp();
+	if (rc < 0)
+		return(rc);
+	inf = fopen(argv[1], "r");
+	if (!inf) {
+		perror(argv[1]);
+		return(-1);
+	}
+	for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++) {
+		if (!index(linebuf, '\n')) {
+			fprintf(stderr,
+				"%s line %d: too long or missing newline\n",
+				argv[1], lineno);
+			fclose(inf);
+			return(-1);
+		}
+		if (linebuf[0] != '#' || !isdigit(linebuf[1]))
+			continue;
+		rc = process_record(linebuf, argv[1], lineno);
+		if (rc < 0) {
+			fclose(inf);
+			return(rc);
+		}
+	}
+	fclose(inf);
+	return(0);
+}