changeset 9:bfcc8180cf3c

bootmatch compiler written
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 10 Jun 2023 02:55:29 +0000
parents 304ac8119c8a
children 39b921d851fb
files .hgignore bootmatch/Makefile bootmatch/comp_defs.h bootmatch/comp_main.c bootmatch/comp_output.c bootmatch/comp_ranges.c bootmatch/comp_readbin.c
diffstat 7 files changed, 273 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore	Sat Jun 10 02:55:29 2023 +0000
@@ -0,0 +1,5 @@
+syntax: regexp
+
+\.[oa]$
+
+^bootmatch/bm-comp$
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bootmatch/Makefile	Sat Jun 10 02:55:29 2023 +0000
@@ -0,0 +1,12 @@
+CC=	gcc
+CFLAGS=	-O2
+BMC_PROG=bm-comp
+BMC_OBJS=comp_main.o comp_output.o comp_ranges.o comp_readbin.o
+
+all:	${BMC_PROG}
+
+${BMC_PROG}:	${BMC_OBJS}
+	${CC} ${CFLAGS} -o $@ ${BMC_OBJS}
+
+clean:
+	rm -f *.o ${BMC_PROG}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bootmatch/comp_defs.h	Sat Jun 10 02:55:29 2023 +0000
@@ -0,0 +1,11 @@
+/*
+ * This header file contains global definitions for our bootmatch compiler.
+ */
+
+#define	BOOT_BLOCK_SIZE	0x2000
+#define	MAX_RANGES	32
+
+struct range {
+	unsigned	offset;
+	unsigned	nbytes;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bootmatch/comp_main.c	Sat Jun 10 02:55:29 2023 +0000
@@ -0,0 +1,29 @@
+/*
+ * This C module is the main for our bootmatch compiler.
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "comp_defs.h"
+
+u_char boot_image[BOOT_BLOCK_SIZE];
+struct range range_list[MAX_RANGES];
+unsigned range_count;
+char *output_array_name;
+
+main(argc, argv)
+	char **argv;
+{
+	if (argc != 5) {
+		fprintf(stderr,
+		"usage: %s bin-file ranges-file array-name output-file\n",
+			argv[0]);
+		exit(1);
+	}
+	read_bin_file(argv[1]);
+	read_ranges_file(argv[2]);
+	output_array_name = argv[3];
+	emit_output_file(argv[4]);
+	exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bootmatch/comp_output.c	Sat Jun 10 02:55:29 2023 +0000
@@ -0,0 +1,86 @@
+/*
+ * This module is the output stage of our bootmatch compiler.
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "comp_defs.h"
+
+extern u_char boot_image[BOOT_BLOCK_SIZE];
+extern struct range range_list[MAX_RANGES];
+extern unsigned range_count;
+extern char *output_array_name;
+
+static FILE *outf;
+
+static void
+emit_header()
+{
+	fputs("#include <sys/types.h>\n", outf);
+	fputs("#include \"bootmatch.h\"\n", outf);
+	putc('\n', outf);
+}
+
+static void
+emit_refbytes_chunk(rp)
+	struct range *rp;
+{
+	u_char *dp, *endp;
+	unsigned linelen;
+
+	fprintf(outf, "static u_char refbytes_%04X[%u] = {\n", rp->offset,
+		rp->nbytes);
+	dp = boot_image + rp->offset;
+	endp = dp + rp->nbytes;
+	linelen = 0;
+	while (dp < endp) {
+		if (linelen >= 16) {
+			putc('\n', outf);
+			linelen = 0;
+		}
+		fprintf(outf, "0x%02X", *dp++);
+		if (dp < endp)
+			putc(',', outf);
+	}
+	fputs("\n};\n\n", outf);
+}
+
+static void
+emit_refbytes_all()
+{
+	unsigned n;
+
+	for (n = 0; n < range_count; n++)
+		emit_refbytes_chunk(range_list + n);
+}
+
+static void
+emit_bootmatch_array()
+{
+	unsigned n;
+	struct range *rp;
+
+	fprintf(outf, "struct bootmatch %s[] = {\n", output_array_name);
+	for (n = 0; n < range_count; n++) {
+		rp = range_list + n;
+		fprintf(outf, "\t{0x%04X, 0x%04X, refbytes_%04X},\n",
+			rp->offset, rp->nbytes, rp->offset);
+	}
+	fputs("\t{0,      0,      0}\n};\n", outf);
+}
+
+void
+emit_output_file(filename)
+	char *filename;
+{
+	outf = fopen(filename, "w");
+	if (!outf) {
+		perror(filename);
+		exit(1);
+	}
+	emit_header();
+	emit_refbytes_all();
+	emit_bootmatch_array();
+	fclose(outf);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bootmatch/comp_ranges.c	Sat Jun 10 02:55:29 2023 +0000
@@ -0,0 +1,92 @@
+/*
+ * Bootmatch compiler: here we read and parse the *.ranges file.
+ */
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "comp_defs.h"
+
+extern struct range range_list[MAX_RANGES];
+extern unsigned range_count;
+
+static void
+process_line(line, filename, lineno)
+	char *line, *filename;
+{
+	char *cp;
+	struct range *rp;
+	u_long hex_start, hex_end;
+
+	for (cp = line; isspace(*cp); cp++)
+		;
+	if (*cp == '\0' || *cp == '#')
+		return;
+	if (!isxdigit(*cp)) {
+inv_syntax:	fprintf(stderr, "%s line %d: invalid syntax\n",
+			filename, lineno);
+		exit(1);
+	}
+	hex_start = strtoul(cp, &cp, 16);
+	if (!isspace(*cp))
+		goto inv_syntax;
+	while (isspace(*cp))
+		cp++;
+	if (!isxdigit(*cp))
+		goto inv_syntax;
+	hex_end = strtoul(cp, &cp, 16);
+	if (*cp && !isspace(*cp))
+		goto inv_syntax;
+	while (isspace(*cp))
+		cp++;
+	if (*cp && *cp != '#')
+		goto inv_syntax;
+	if (hex_start >= BOOT_BLOCK_SIZE) {
+		fprintf(stderr, "%s line %d: start offset is out of range\n",
+			filename, lineno);
+		exit(1);
+	}
+	if (hex_end >= BOOT_BLOCK_SIZE) {
+		fprintf(stderr, "%s line %d: end offset is out of range\n",
+			filename, lineno);
+		exit(1);
+	}
+	if (hex_start >= hex_end) {
+		fprintf(stderr,
+		"%s line %d: end offset must be greater than start offset\n",
+			filename, lineno);
+		exit(1);
+	}
+	if (range_count >= MAX_RANGES) {
+		fprintf(stderr, "%s line %d: too many ranges defined\n",
+			filename, lineno);
+		exit(1);
+	}
+	rp = range_list + range_count;
+	rp->offset = hex_start;
+	rp->nbytes = hex_end - hex_start;
+	range_count++;
+}
+
+void
+read_ranges_file(filename)
+	char *filename;
+{
+	FILE *inf;
+	char linebuf[256];
+	int lineno;
+
+	inf = fopen(filename, "r");
+	if (!inf) {
+		perror(filename);
+		exit(1);
+	}
+	for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++)
+		process_line(linebuf, filename, lineno);
+	fclose(inf);
+	if (!range_count) {
+		fprintf(stderr, "error: no ranges defined in %s\n", filename);
+		exit(1);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bootmatch/comp_readbin.c	Sat Jun 10 02:55:29 2023 +0000
@@ -0,0 +1,38 @@
+/*
+ * Bootmatch compiler: here we read the binary file.
+ */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "comp_defs.h"
+
+extern u_char boot_image[BOOT_BLOCK_SIZE];
+
+void
+read_bin_file(filename)
+	char *filename;
+{
+	int fd;
+	struct stat st;
+
+	fd = open(filename, O_RDONLY);
+	if (fd < 0) {
+		perror(filename);
+		exit(1);
+	}
+	fstat(fd, &st);
+	if (!S_ISREG(st.st_mode)) {
+		fprintf(stderr, "error: %s is not a regular file\n", filename);
+		exit(1);
+	}
+	if (st.st_size != BOOT_BLOCK_SIZE) {
+		fprintf(stderr, "error: %s has wrong length\n", filename);
+		exit(1);
+	}
+	read(fd, boot_image, BOOT_BLOCK_SIZE);
+	close(fd);
+}