summaryrefslogtreecommitdiff
path: root/util/BuildImage.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--util/BuildImage.c132
1 files changed, 74 insertions, 58 deletions
diff --git a/util/BuildImage.c b/util/BuildImage.c
index f8e35f0..f43f0b0 100644
--- a/util/BuildImage.c
+++ b/util/BuildImage.c
@@ -16,11 +16,11 @@
#define _POSIX_C_SOURCE 200809L
-#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <unistd.h>
+#include <string.h>
+#include <errno.h>
#define TRUE 1
#define FALSE 0
@@ -29,6 +29,7 @@
#define DRIVE_USB 0x80
#define SECT_SIZE 512
+
char *progname; /* invocation name of this program */
char *bootstrap_filename; /* path of file holding bootstrap program */
char *output_filename; /* path of disk image file */
@@ -44,7 +45,9 @@ short drive = DRIVE_USB; /* boot drive */
** device) are the only limiting factors on how many program sections
** can be loaded.
*/
+
#define N_INFO (SECT_SIZE / sizeof(short))
+
short info[N_INFO];
int n_info = N_INFO;
@@ -66,7 +69,6 @@ void quit(char *msg, int call_perror)
errno = err_num;
if (call_perror) {
perror(msg);
-
} else {
fprintf(stderr, "%s\n", msg);
}
@@ -75,12 +77,11 @@ void quit(char *msg, int call_perror)
unlink(output_filename);
}
exit(EXIT_FAILURE);
-
// NOTREACHED
}
+
const char usage_error_msg[] =
- "\nUsage: %s [ -d drive ] -b bootfile -o outfile { progfile loadpt } "
- "...\n\n"
+ "\nUsage: %s [ -d drive ] -b bootfile -o outfile { progfile loadpt } ...\n\n"
"\t'drive' is either 'floppy' or 'usb' (default 'usb')\n\n"
"\tThere must be at least one program file and load point.\n\n"
"\tLoad points may be specified either as 32-bit quantities in hex,\n"
@@ -98,7 +99,6 @@ void usage_error(void)
{
fprintf(stderr, usage_error_msg, progname);
quit(NULL, FALSE);
-
// NOTREACHED
}
@@ -117,15 +117,16 @@ int copy_file(FILE *in)
int i;
/*
- ** Copy the file to the output, being careful that the
- ** last sector is padded with null bytes out to the
- ** sector size.
- */
+ ** Copy the file to the output, being careful that the
+ ** last sector is padded with null bytes out to the
+ ** sector size.
+ */
n_sectors = 0;
while ((n_bytes = fread(buf, 1, sizeof(buf), in)) > 0) {
// pad this sector out to block size
if (n_bytes < sizeof(buf)) {
int i;
+
for (i = n_bytes; i < sizeof(buf); i += 1) {
buf[i] = '\0';
}
@@ -152,25 +153,25 @@ void process_file(char *name, char *addr)
int n_bytes;
/*
- ** Open the input file.
- */
+ ** Open the input file.
+ */
FILE *in = fopen(name, "rb");
if (in == NULL) {
quit(name, TRUE);
}
/*
- ** Copy the file to the output, being careful that the
- ** last block is padded with null bytes.
- */
+ ** Copy the file to the output, being careful that the
+ ** last block is padded with null bytes.
+ */
int n_sectors = copy_file(in);
fclose(in);
/*
- ** Decode the address they gave us. We'll accept two forms:
- ** "nnnn:nnnn" for a segment:offset value (assumed to be hex),
- ** "nnnnnnn" for a decimal, hex, or octal value
- */
+ ** Decode the address they gave us. We'll accept two forms:
+ ** "nnnn:nnnn" for a segment:offset value (assumed to be hex),
+ ** "nnnnnnn" for a decimal, hex, or octal value
+ */
int valid_address = FALSE;
char *cp = strchr(addr, ':');
if (cp != NULL) {
@@ -178,46 +179,49 @@ void process_file(char *name, char *addr)
if (strlen(addr) == 9 && cp == addr + 4) {
char *ep1, *ep2;
int a1, a2;
+
segment = strtol(addr, &ep1, 16);
offset = strtol(addr + 5, &ep2, 16);
address = (segment << 4) + offset;
valid_address = *ep1 == '\0' && *ep2 == '\0';
-
} else {
fprintf(stderr, "Bad address format - '%s'\n", addr);
quit(NULL, FALSE);
}
-
} else {
// just a number, possibly hex or octal
char *ep;
+
address = strtol(addr, &ep, 0);
segment = (short)(address >> 4);
offset = (short)(address & 0xf);
valid_address = *ep == '\0' && address <= 0x0009ffff;
}
+
if (!valid_address) {
fprintf(stderr, "%s: Invalid address: %s\n", progname, addr);
quit(NULL, FALSE);
}
/*
- ** Make sure the program will fit!
- */
+ ** Make sure the program will fit!
+ */
if (address + n_sectors * SECT_SIZE > 0x0009ffff) {
fprintf(stderr, "Program %s too large to start at 0x%08x\n", name,
(unsigned int)address);
quit(NULL, FALSE);
}
+
if (n_info < 3) {
quit("Too many programs!", FALSE);
}
/*
- ** Looks good: report and store the information.
- */
+ ** Looks good: report and store the information.
+ */
fprintf(stderr, " %s: %d sectors, loaded at 0x%x\n", name, n_sectors,
(unsigned int)address);
+
info[--n_info] = n_sectors;
info[--n_info] = segment;
info[--n_info] = offset;
@@ -226,6 +230,7 @@ void process_file(char *name, char *addr)
/*
** Global variables set by getopt()
*/
+
extern int optind, optopt;
extern char *optarg;
@@ -238,17 +243,21 @@ extern char *optarg;
void process_args(int ac, char **av)
{
int c;
+
while ((c = getopt(ac, av, ":d:o:b:")) != EOF) {
switch (c) {
case ':': /* missing arg value */
fprintf(stderr, "missing operand after -%c\n", optopt);
+ /* FALL THROUGH */
- /* FALL THROUGH */ case '?': /* error */
+ case '?': /* error */
usage_error();
+ /* NOTREACHED */
- /* NOTREACHED */ case 'b': /* -b bootstrap_file */
+ case 'b': /* -b bootstrap_file */
bootstrap_filename = optarg;
break;
+
case 'd': /* -d drive */
switch (*optarg) {
case 'f':
@@ -261,27 +270,31 @@ void process_args(int ac, char **av)
usage_error();
}
break;
+
case 'o': /* -o output_file */
output_filename = optarg;
break;
+
default:
usage_error();
}
}
+
if (!bootstrap_filename) {
fprintf(stderr, "%s: no bootstrap file specified\n", progname);
exit(2);
}
+
if (!output_filename) {
fprintf(stderr, "%s: no disk image file specified\n", progname);
exit(2);
}
/*
- ** Must have at least two remaining arguments (file to load,
- ** address at which it should be loaded), and must have an
- ** even number of remaining arguments.
- */
+ ** Must have at least two remaining arguments (file to load,
+ ** address at which it should be loaded), and must have an
+ ** even number of remaining arguments.
+ */
int remain = ac - optind;
if (remain < 2 || (remain & 1) != 0) {
usage_error();
@@ -307,49 +320,50 @@ int main(int ac, char **av)
int i;
/*
- ** Save the program name for error messages
- */
+ ** Save the program name for error messages
+ */
progname = strrchr(av[0], '/');
if (progname != NULL) {
progname++;
-
} else {
progname = av[0];
}
/*
- ** Process arguments
- */
+ ** Process arguments
+ */
process_args(ac, av);
/*
- ** Open the output file
- */
+ ** Open the output file
+ */
+
out = fopen(output_filename, "wb+");
if (out == NULL) {
quit(output_filename, TRUE);
}
/*
- ** Open the bootstrap file and copy it to the output image.
- */
+ ** Open the bootstrap file and copy it to the output image.
+ */
bootimage = fopen(bootstrap_filename, "rb");
if (bootimage == NULL) {
quit(bootstrap_filename, TRUE);
}
/*
- ** Remember the size of the bootstrap for later, as we
- ** need to patch some things into it
- */
+ ** Remember the size of the bootstrap for later, as we
+ ** need to patch some things into it
+ */
int n_sectors = copy_file(bootimage);
fclose(bootimage);
+
bootimage_size = n_sectors * SECT_SIZE;
fprintf(stderr, " %s: %d sectors\n", bootstrap_filename, n_sectors);
/*
- ** Process the programs one by one
- */
+ ** Process the programs one by one
+ */
ac -= optind;
av += optind;
while (ac >= 2) {
@@ -359,16 +373,16 @@ int main(int ac, char **av)
}
/*
- ** Check for oddball leftover argument
- */
+ ** Check for oddball leftover argument
+ */
if (ac > 0) {
usage_error();
}
/*
- ** Seek to where the array of module data must begin and read
- ** what's already there.
- */
+ ** Seek to where the array of module data must begin and read
+ ** what's already there.
+ */
n_words = (N_INFO - n_info);
n_bytes = n_words * sizeof(info[0]);
fseek(out, bootimage_size - n_bytes, SEEK_SET);
@@ -377,8 +391,8 @@ int main(int ac, char **av)
}
/*
- ** If that space is non-zero, we have a problem
- */
+ ** If that space is non-zero, we have a problem
+ */
for (i = 0; i < n_words; i += 1) {
if (existing_data[i] != 0) {
quit("Too many programs to load!", FALSE);
@@ -386,19 +400,21 @@ int main(int ac, char **av)
}
/*
- ** We know that we're only overwriting zeros at the end of
- ** the bootstrap image, so it is ok to go ahead and do it.
- */
+ ** We know that we're only overwriting zeros at the end of
+ ** the bootstrap image, so it is ok to go ahead and do it.
+ */
fseek(out, bootimage_size - n_bytes, SEEK_SET);
if (fwrite(info + n_info, sizeof(info[0]), n_words, out) != n_words) {
quit("Write to boot image failed or was too short", FALSE);
}
/*
- ** Write the drive index to the image.
- */
+ ** Write the drive index to the image.
+ */
fseek(out, 508, SEEK_SET);
fwrite((void *)&drive, sizeof(drive), 1, out);
+
fclose(out);
+
return EXIT_SUCCESS;
}