diff --git a/util/amisc/aslod.1 b/util/amisc/aslod.1 new file mode 100644 index 000000000..7e291838f --- /dev/null +++ b/util/amisc/aslod.1 @@ -0,0 +1,20 @@ +.TH ASLOD 1 "$Revision$" +.SH NAME +aslod \- ACK simple loader +.SH SYNOPSIS +aslod [-h] inputfile outputfile +.SH DESCRIPTION +.I aslod +converts an absolute ack.out file into a simple binary memory +dump. It is suitable for producing RAM images, executables for +simple operating systems such as CP/M, DOS, etc. + +The input file must contain exactly four segments: TEXT, ROM, +DATA and BSS, in that order, all occupying contiguous memory. +The file must have all references resolved and be linked to a +fixed address. aslod will dump the segments, in order, such +that the first byte of TEXT is at offset 0 in the file +(regardless of where it is in memory). + +.SH "SEE ALSO" +ack.out(5) diff --git a/util/amisc/aslod.c b/util/amisc/aslod.c new file mode 100644 index 000000000..9eb45033d --- /dev/null +++ b/util/amisc/aslod.c @@ -0,0 +1,325 @@ +/* + * Simple tool to produce a memory dump for an absolute + * ack.out file. Suitable for noddy operating systems + * like DOS, CP/M, Arthur, etc. Also useful for RAM + * images (but *not* ROM images, note) and, more + * importantly, general test purposes. + * + * Mostly pinched from the ARM cv (and then rewritten in + * ANSI C). Which, according to the comment, was pinched + * from m68k2; therefore I am merely continuing a time- + * honoured tradition. + * + * (I was 10 when the original for this was checked into + * CVS...) + * + * dtrg, 2006-10-17 + * + * $Source$ + * $State$ + */ + +#include +#include +#include +#include +#include "out.h" + +#define ASSERT(x) switch (2) { case 0: case (x): ; } + +/* + * Header and section table of ack object file. + */ + +struct outhead outhead; +struct outsect outsect[S_MAX]; +char* stringarea; + +char* outputfile = NULL; /* Name of output file, or NULL */ +char* program; /* Name of current program: argv[0] */ + +FILE* input; /* Input stream */ +FILE* output; /* Output stream */ + +#define readf(a, b, c) fread((a), (b), (int)(c), input) +#define writef(a, b, c) fwrite((a), (b), (int)(c), output) + +/* Output file definitions and such */ + +#define HDR_LENGTH 32 + +char hdr[HDR_LENGTH] ; + +/* Segment numbers understood by aslod. */ + +enum { + TEXT = 0, + ROM, + DATA, + BSS, + NUM_SEGMENTS +}; + +#define N_EXT 040 +#define N_UNDEF 00 +#define N_ABS 01 +#define N_TEXT 02 +#define N_DATA 03 +#define N_BSS 04 +#define N_FN 037 + +/* Produce an error message and exit. */ + +void fatal(const char* s, ...) +{ + va_list ap; + + fprintf(stderr, "%s: ",program) ; + + va_start(ap, s); + vfprintf(stderr, s, ap); + va_end(ap); + + fprintf(stderr, "\n"); + + if (outputfile) + unlink(outputfile); + exit(1); +} + +/* Calculate the result of a aligned to b (rounding up if necessary). */ + +long align(long a, long b) +{ + a += b - 1; + return a - a % b; +} + +int follows(struct outsect* pa, struct outsect* pb) +{ + /* return 1 if pa follows pb */ + + return (pa->os_base == align(pb->os_base+pb->os_size, pa->os_lign)); +} + +/* Copies the contents of a section from the input stream + * to the output stream, zero filling any uninitialised + * space. */ + +void emits(struct outsect* section) +{ + char buffer[BUFSIZ]; + + /* Copy the actual data. */ + + { + long n = section->os_flen; + while (n > 0) + { + int blocksize = (n > BUFSIZ) ? BUFSIZ : n; + readf(buffer, 1, blocksize); + writef(buffer, 1, blocksize); + n -= blocksize; + } + } + + /* Zero fill any remaining space. */ + + if (section->os_flen != section->os_size) + { + long n = section->os_size - section->os_flen; + memset(buffer, 0, BUFSIZ); + + while (n > 0) + { + int blocksize = (n > BUFSIZ) ? BUFSIZ : n; + writef(buffer, 1, blocksize); + n -= blocksize; + } + } +} + + +void iconvert(char* buf, char* str, char* fmt) +{ + register char *nf, *ni, *no ; + int last, i ; + long value ; + ni=buf ; no=str ; nf=fmt ; + while ( last = *nf++ ) { + last -= '0' ; + if ( last<1 || last >9 ) fatal("illegal out.h format string\n"); + value=0 ; + i=last ; + while ( i-- ) { + value = (value<<8) + (ni[i]&0xFF) ; + } + switch ( last ) { + case 0 : break ; + case 1 : *no= value ; break ; + case 2 : *(unsigned short *)no = value ; break ; + case 4 : *(long *)no = value ; break ; + default : + fatal("illegal out.h format string\n"); + } + ni += last ; no += last ; + } +} + +/* Read the ack.out file header. */ + +int rhead(FILE* f, struct outhead* head) +{ + char buf[sizeof(struct outhead)]; + + if (fread(buf, sizeof(buf), 1, f) != 1) + return 0; + + iconvert(buf, (char*) head, SF_HEAD); + return 1; +} + +/* Read an ack.out section header. */ + +int rsect(FILE* f, struct outsect* sect) +{ + char buf[sizeof(struct outsect)]; + + if (fread(buf, sizeof(buf), 1, f) != 1) + return 0; + + iconvert(buf, (char*) sect, SF_SECT); + return 1 ; +} + +int main(int argc, char* argv[]) +{ + /* General housecleaning and setup. */ + + input = stdin; + output = stdout; + program = argv[0]; + + /* Read in and process any flags. */ + + while ((argc > 1) && (argv[1][0] == '-')) + { + switch (argv[1][1]) + { + case 'h': + fprintf(stderr, "%s: Syntax: aslod [-h] \n", + program); + exit(0); + + default: + syntaxerror: + fatal("syntax error --- try -h for help)"); + } + + argv++; + argc--; + } + + /* Process the rest of the arguments. */ + + switch (argc) + { + case 1: /* No parameters --- read from stdin, write to stdout. */ + break; + + case 3: /* Both input and output files specified. */ + output = fopen(argv[2], "w"); + if (!output) + fatal("unable to open output file."); + outputfile = argv[2]; + /* fall through */ + + case 2: /* Input file specified. */ + input = fopen(argv[1], "r"); + if (!input) + fatal("unable to open input file."); + break; + + default: + goto syntaxerror; + } + + /* Read and check the ack.out file header. */ + + if (!rhead(input,&outhead)) + fatal("failed to read file header."); + if (BADMAGIC(outhead)) + fatal("this isn't an ack object file."); + if (outhead.oh_nrelo > 0) + fprintf(stderr, "Warning: relocation information present."); + if (!(outhead.oh_nsect == NUM_SEGMENTS) || + (outhead.oh_nsect == (NUM_SEGMENTS+1))) + fatal("the input file must have %d sections, not %ld.", + NUM_SEGMENTS, outhead.oh_nsect); + + /* Read in the section headers. */ + + { + int i; + for (i=0; i