diff --git a/tools/ml.c b/tools/ml.c new file mode 100644 index 0000000..7ccace0 --- /dev/null +++ b/tools/ml.c @@ -0,0 +1,224 @@ +/* + * Quick hack to read old unix a.out files and make + * a simh "load file". + * + * Brad Parker 5/2008 + */ +#include +#include +#include + +/* Binary loader. + + Loader format consists of blocks, optionally preceded, separated, and + followed by zeroes. Each block consists of: + + 001 --- + xxx | + lo_count | + hi_count | + lo_origin > count bytes + hi_origin | + data byte | + : | + data byte --- + checksum + + If the byte count is exactly six, the block is the last on the tape, and + there is no checksum. If the origin is not 000001, then the origin is + the PC at which to start the program. +*/ + +typedef unsigned short u16; + +struct exec { + u16 a_magic; + u16 a_text; + u16 a_data; + u16 a_bss; + u16 a_syms; + u16 a_entry; + u16 a_unused; + u16 a_flag; +}; + +unsigned char buffer[1024]; +int checksum; + +int verbose; + +int +mk_hdr(int fd, int count, int origin) +{ + int i, ret, hc; + + checksum = 0; + hc = count + 6; + + buffer[0] = 0x01; + buffer[1] = 0x00; + buffer[2] = hc & 0xff; + buffer[3] = hc >> 8; + buffer[4] = origin & 0xff; + buffer[5] = origin >> 8; + + ret = write(fd, buffer, 6); + if (ret != 6) + return -1; + + for (i = 0; i < 6; i++) + checksum += buffer[i] & 0xff; + + return 0; +} + +int +mk_post_data(int fd) +{ + int ret, final_checksum; + + /* final checksum must be zero */ + final_checksum = 256 - (checksum & 0xff); + + buffer[0] = final_checksum; + if (verbose) + printf("checksum %08x, final %02x\n", checksum, final_checksum); + + ret = write(fd, buffer, 1); + if (ret != 1) + return -1; + + return 0; +} + +int +load(int fd, char *buf, int bufsize) +{ + int i, ret; + + printf("load: %d bytes\n", bufsize); + + if (bufsize < 65536) { + mk_hdr(fd, bufsize, 0); + + ret = write(fd, buf, bufsize); + if (ret != bufsize) + return -1; + + for (i = 0; i < bufsize; i++) + checksum += buf[i] & 0xff; + + mk_post_data(fd); + } + + return 0; +} + +int +finish(int fd, int origin) +{ + mk_hdr(fd, 0, origin); +} + +int +process_aout(int ifd, int ofd, int origin) +{ + int ret, hdr_size; + struct exec hdr; + char *textblob, *datablob; + + ret = read(ifd, (char *)&hdr, sizeof(hdr)); + if (ret != sizeof(hdr)) { + return -1; + } + + if (1) { + printf("magic 0%o\ntext %d, data %d, bss %d, syms %d\n", + hdr.a_magic & 0xffff, + hdr.a_text, hdr.a_data, hdr.a_bss, hdr.a_syms); + printf("entry %o, flag %o\n", + hdr.a_entry, + hdr.a_flag); + } + + textblob = malloc(hdr.a_text); + datablob = malloc(hdr.a_data); + + hdr_size = 0; + + /* v7 header? if so, 0 is after header */ + switch (hdr.a_magic) { + case 0407: hdr_size = 0; break; + case 0405: hdr_size = 12; break; + } + + if (hdr_size) { + /* back up */ + lseek(ifd, (off_t)-hdr_size, SEEK_CUR); + hdr.a_text += hdr_size; + } + + ret = read(ifd, textblob, hdr.a_text); + if (ret != hdr.a_text) + return -1; + + ret = read(ifd, datablob, hdr.a_data); + if (ret != hdr.a_data) + return -1; + + load(ofd, textblob, hdr.a_text); + load(ofd, datablob, hdr.a_data); + + finish(ofd, origin); + + return 0; + +} + +int +process(char *inf, char *outf) +{ + int ifd, ofd, ret; + int origin; + + ofd = open(outf, O_WRONLY | O_CREAT, 0666); + if (ofd < 0) { + perror(outf); + return -1; + } + + ifd = open(inf, O_RDONLY); + if (ifd < 0) { + perror(inf); + close(ofd); + return -1; + } + + ret = 0; + origin = 0; + + if (process_aout(ifd, ofd, origin)) { + ret = -1; + } + + close(ifd); + close(ofd); + + return ret; +} + + +main(int argc, char *argv[]) +{ + char *filename = "a.out"; + char *output_filename = "loadfile"; + int fd; + + verbose = 0; + + if (process(filename, output_filename)) { + fprintf(stderr, "%s: failed?\n", filename); + } + + exit(0); +}