diff options
author | Freya Murphy <freya@freyacat.org> | 2025-03-27 14:41:28 -0400 |
---|---|---|
committer | Freya Murphy <freya@freyacat.org> | 2025-03-27 14:41:28 -0400 |
commit | e2ac88e1897395e4b480ad291405e6a8ddf5f149 (patch) | |
tree | 9d85d37cc9dbc53ed9370e0e94a6bfae6204cc24 /util | |
parent | remove trailing whitespace (diff) | |
download | comus-e2ac88e1897395e4b480ad291405e6a8ddf5f149.tar.gz comus-e2ac88e1897395e4b480ad291405e6a8ddf5f149.tar.bz2 comus-e2ac88e1897395e4b480ad291405e6a8ddf5f149.zip |
track util changes as well
Diffstat (limited to '')
-rw-r--r-- | util/BuildImage.c | 132 | ||||
-rw-r--r-- | util/listblob.c | 37 | ||||
-rw-r--r-- | util/mkblob.c | 32 |
3 files changed, 117 insertions, 84 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; } diff --git a/util/listblob.c b/util/listblob.c index ccae1d0..e6266a3 100644 --- a/util/listblob.c +++ b/util/listblob.c @@ -5,18 +5,17 @@ ** ** Examine a binary blob of ELF files. */ - #define _DEFAULT_SOURCE -#include <ctype.h> -#include <elf.h> -#include <fcntl.h> -#include <stdbool.h> -#include <stdint.h> #include <stdio.h> +#include <stdint.h> #include <stdlib.h> +#include <stdbool.h> #include <string.h> -#include <sys/stat.h> #include <unistd.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <elf.h> +#include <ctype.h> /* ** Blob file organization @@ -40,11 +39,11 @@ ** size Size of this ELF file, in bytes ** flags Flags related to this file */ + // blob header: 8 bytes typedef struct header_s { char magic[4]; uint32_t num; - } header_t; // The program table entry is 32 bytes long. To accomplish this, the @@ -73,8 +72,8 @@ typedef struct prog_s { typedef struct node_s { prog_t *data; struct node_s *next; - } node_t; + node_t *progs, *last_prog; // list pointers uint32_t n_progs; // number of files being copied uint32_t offset; // current file area offset @@ -129,11 +128,12 @@ void process(uint32_t num, prog_t *prog) char *slash = strrchr(prog->name, '/'); if (slash == NULL) { slash = prog->name; - } else { ++slash; } + slash[0] = toupper(slash[0]); + if (defs) { // just printing #define statements printf("#define %-15s %2d\n", prog->name, num); @@ -144,7 +144,6 @@ void process(uint32_t num, prog_t *prog) // first one, so print the file header puts(header); putchar('\t'); - } else { // second or later entry; limit to 8 per line fputs(((num & 0x7) == 0) ? ",\n\t" : ", ", stdout); @@ -160,56 +159,65 @@ void process(uint32_t num, prog_t *prog) prog->size, prog->flags); } } + void usage(char *name) { fprintf(stderr, "usage: %s [-d | -e] blob_name\n", name); } + int main(int argc, char *argv[]) { if (argc < 2 || argc > 3) { usage(argv[0]); exit(1); } + int nameix = 1; // could use getopt() for this, but this is easy enough if (argc == 3) { if (strcmp(argv[1], "-d") == 0) { defs = true; - } else if (strcmp(argv[1], "-e") == 0) { enums = true; - } else { usage(argv[0]); exit(1); } nameix = 2; } + char *name = argv[nameix]; + int fd = open(name, O_RDONLY); if (fd < 0) { perror(name); exit(1); } + header_t hdr; + int n = read(fd, &hdr, sizeof(header_t)); if (n != sizeof(header_t)) { fprintf(stderr, "%s: header read returned only %d bytes\n", name, n); close(fd); exit(1); } + if (strcmp(hdr.magic, "BLB") != 0) { fprintf(stderr, "%s: bad magic number\n", name); close(fd); exit(1); } + if (hdr.num < 1) { fprintf(stderr, "%s: no programs in blob?\n", name); close(fd); exit(1); } + prog_t progs[hdr.num]; + n = read(fd, progs, hdr.num * sizeof(prog_t)); if (n != (int)(hdr.num * sizeof(prog_t))) { fprintf(stderr, "%s: prog table only %d bytes, expected %lu\n", name, n, @@ -217,13 +225,16 @@ int main(int argc, char *argv[]) close(fd); exit(1); } + for (uint32_t i = 0; i < hdr.num; ++i) { process(i, &progs[i]); } + if (enums) { // print the file trailer puts(trailer); } + close(fd); return 0; } diff --git a/util/mkblob.c b/util/mkblob.c index fdf0680..ea6a946 100644 --- a/util/mkblob.c +++ b/util/mkblob.c @@ -5,17 +5,16 @@ ** ** Create a binary blob from a collection of ELF files. */ - #define _DEFAULT_SOURCE -#include <elf.h> -#include <fcntl.h> -#include <stdint.h> #include <stdio.h> +#include <stdint.h> #include <stdlib.h> #include <string.h> -#include <sys/stat.h> #include <unistd.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <elf.h> /* ** Blob file organization @@ -39,11 +38,11 @@ ** size Size of this ELF file, in bytes ** flags Flags related to this file */ + // blob header typedef struct header_s { char magic[4]; uint32_t num; - } header_t; // length of the file name field @@ -68,8 +67,8 @@ typedef struct node_s { prog_t *data; char *fullname; struct node_s *next; - } node_t; + node_t *progs, *last_prog; // list pointers uint32_t n_progs; // number of files being copied uint32_t offset; // current file area offset @@ -115,10 +114,12 @@ void process(const char *name) Elf32_Ehdr hdr; int n = read(fd, &hdr, sizeof(Elf32_Ehdr)); close(fd); + if (n != sizeof(Elf32_Ehdr)) { fprintf(stderr, "%s: header read was short - only %d\n", name, n); return; } + if (hdr.e_ident[EI_MAG0] != ELFMAG0 || hdr.e_ident[EI_MAG1] != ELFMAG1 || hdr.e_ident[EI_MAG2] != ELFMAG2 || hdr.e_ident[EI_MAG3] != ELFMAG3) { fprintf(stderr, "%s: bad ELF magic number\n", name); @@ -131,12 +132,14 @@ void process(const char *name) fprintf(stderr, "%s: calloc prog returned NULL\n", name); return; } + node_t *node = calloc(1, sizeof(node_t)); if (node == NULL) { free(new); fprintf(stderr, "%s: calloc node returned NULL\n", name); return; } + node->data = new; node->fullname = strdup(name); @@ -147,11 +150,11 @@ void process(const char *name) if (slash == NULL) { // only the file name slash = name; - } else { // skip the slash ++slash; } + strncpy(new->name, slash, sizeof(new->name) - 1); new->offset = offset; new->size = info.st_size; @@ -164,7 +167,6 @@ void process(const char *name) if ((info.st_size & FSIZE_MASK) != 0) { // nope, so we must round it up when we write it out new->flags |= FL_ROUNDUP; - // increases the offset to the next file offset += 8 - (info.st_size & FSIZE_MASK); } @@ -173,7 +175,6 @@ void process(const char *name) if (progs == NULL) { // first entry progs = node; - } else { // add to the end if (last_prog == NULL) { @@ -206,24 +207,23 @@ void copy(FILE *ofd, node_t *node) perror(node->fullname); return; } + uint8_t buf[512]; // copy it block-by-block do { int n = read(fd, buf, 512); - // no bytes --> we're done if (n < 1) { break; } - // copy it, and verify the copy count int k = fwrite(buf, 1, n, ofd); if (k != n) { fprintf(stderr, "%s: write of %d returned %d\n", prog->name, n, k); } - } while (1); + printf("%s: copied %d", prog->name, prog->size); // do we need to round up? @@ -249,12 +249,14 @@ void copy(FILE *ofd, node_t *node) // all done! close(fd); } + int main(int argc, char *argv[]) { // construct program list for (int i = 1; i < argc; ++i) { process(argv[i]); } + if (n_progs < 1) { fputs("Nothing to do... exiting.", stderr); exit(0); @@ -267,12 +269,14 @@ int main(int argc, char *argv[]) perror("user.img"); exit(1); } + printf("Processing %d ELF files\n", n_progs); // we need to adjust the offset values so they are relative to the // start of the blob, not relative to the start of the file area. // do this by adding the sum of the file header and program entries // to each offset field. + uint32_t hlen = sizeof(header_t) + n_progs * sizeof(prog_t); node_t *curr = progs; while (curr != NULL) { @@ -310,6 +314,8 @@ int main(int argc, char *argv[]) free(tmp->fullname); free(tmp); } + fclose(ofd); + return 0; } |