From a6a833a50b3287e6c719d9d5d54f909a894ebaa1 Mon Sep 17 00:00:00 2001 From: John-Mark Bell Date: Fri, 10 Mar 2023 22:21:21 +0000 Subject: Add support for relocateable AIFs Rework to use inttypes, improve support for squeezed images and handle relocateable images correctly. --- makerun.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 112 insertions(+), 23 deletions(-) (limited to 'makerun.c') diff --git a/makerun.c b/makerun.c index 8871b8f..5008b1b 100644 --- a/makerun.c +++ b/makerun.c @@ -1,3 +1,4 @@ +#include #include #include @@ -7,25 +8,40 @@ #endif struct header { - unsigned int decompress; - unsigned int selfreloc; - unsigned int zeroinit; - unsigned int entry; - unsigned int exit; - unsigned int rosize; - unsigned int rwsize; - unsigned int dbsize; - unsigned int zisize; - unsigned int dbtype; - unsigned int base; - unsigned int wkspace; + uint32_t decompress; + uint32_t selfreloc; + uint32_t zeroinit; + uint32_t entry; + uint32_t exit; + uint32_t rosize; + uint32_t rwsize; + uint32_t dbsize; + uint32_t zisize; + uint32_t dbtype; + uint32_t base; + uint32_t wkspace; + uint32_t flags; + uint32_t database; + uint32_t r1; + uint32_t r2; + uint32_t zicode[16]; +}; + +struct sqz_header { + uint32_t decsize; + uint32_t encsize; + uint32_t tabsize; + uint32_t nshorts; + uint32_t nlongs; + uint32_t bytestomove; }; int main(int argc, char **argv) { FILE *f, *g; struct header header; - unsigned int file_size; + long flen; + size_t file_size, reloc_size = 0; char buf[256]; if (argc != 4) { @@ -40,10 +56,64 @@ int main(int argc, char **argv) return 1; } - fread((void*)&header, sizeof(struct header), 1, f); + if (fseek(f, 0, SEEK_END) < 0 || (flen = ftell(f)) < 0 || + fseek(f, 0, SEEK_SET) < 0) { + fprintf(stderr, "Failed reading file size\n"); + fclose(f); + return 1; + } + file_size = (size_t) flen; + + if (file_size < sizeof(struct header) || + fread(&header, sizeof(struct header), 1, f) != 1) { + fprintf(stderr, "Failed reading image header"); + fclose(f); + return 1; + } + + if ((header.decompress >> 24) == 0xEB) { + /* Image is compressed */ + struct sqz_header sqzhdr; + uint8_t buf[1024], *lastb; + /* Compute offset of squeeze data (if any) */ + size_t off = ((header.decompress & 0xFFFFFF) << 2) + 8 - (6*4); + /* Read in at most 1024 trailing bytes */ + if (file_size - off > sizeof(buf)) { + fprintf(stderr, "Decompression buffer too small\n"); + fclose(f); + return 1; + } + if (fseek(f, (long) off, SEEK_SET) < 0 || + fread(buf, file_size - off, 1, f) != 1) { + fprintf(stderr, "Failed reading decompression code\n"); + fclose(f); + return 1; + } + /* Look for squeeze signature (file size must be a multiple + * of 15 and must end "rcc X.YZ\n" padded out with spaces */ + lastb = buf + (file_size - off); + while (lastb > buf && *(lastb-1) == ' ') + lastb--; + if ((file_size & 0xf) != 0xf || (lastb - 9 <= buf) || + *(lastb-9) != 'r' || *(lastb-8) != 'c' || + *(lastb-7) != 'c' || *(lastb-6) != ' ' || + *(lastb-4) != '.' || *(lastb-1) != '\n') { + fprintf(stderr, "Unknown compression scheme\n"); + fclose(f); + return 1; + } + + /* We have been squeezed: sanity check compressed size */ + memcpy(&sqzhdr, buf, sizeof(sqzhdr)); + if (sizeof(header) + 4 + sqzhdr.encsize + sqzhdr.tabsize != + off) { + fprintf(stderr, "Malformed squeeze data\n"); + fclose(f); + return 1; + } - fseek(f, 0, SEEK_END); - file_size = ftell(f); + file_size = sizeof(header) + (size_t) sqzhdr.decsize; + } fclose(f); @@ -56,19 +126,38 @@ int main(int argc, char **argv) return 1; } - if (header.rosize + header.rwsize + header.dbsize != - file_size) { - if ((header.decompress >> 24) != 0xEB) { - fprintf(stderr, "Mismatched field sizes\n"); + if ((header.selfreloc >> 24) == 0xEB) { + /* Image is relocateable */ + size_t off = 4 + + ((header.selfreloc & 0xFFFFFF) << 2) + 8; + + if (off >= file_size) { + fprintf(stderr, "Relocation code missing\n"); return 1; } + + /* Deduct relocation code and tables from file size */ + reloc_size = file_size - off; + file_size -= reloc_size; + /* Add relocation workspace on to reloc size */ + reloc_size += header.wkspace; } - file_size = header.rosize + header.rwsize + - header.dbsize + header.zisize + + if (header.rosize + header.rwsize + header.dbsize != + file_size) { + fprintf(stderr, "Mismatched field sizes\n"); + return 1; + } + +#define max(a, b) ((a) > (b) ? (a) : (b)) + file_size += max(header.zisize, reloc_size) + 0x8000 /* 32k of scratch space */; +#undef max } + /* Round slotsize up to the next 4k boundary */ + file_size = (file_size + 0xfff) & ~0xfff; + f = fopen(argv[2], "r"); if (f == NULL) { fprintf(stderr, "Failed opening %s\n", argv[2]); @@ -84,7 +173,7 @@ int main(int argc, char **argv) while (fgets(buf, sizeof(buf), f) != NULL) { if (strncmp(buf, "WIMPSLOT\n", 9) == 0) { - fprintf(g, "WimpSlot -min %dk -max %dk\n", + fprintf(g, "WimpSlot -min %zuk -max %zuk\n", (file_size / 1024), (file_size / 1024)); } else { fputs(buf, g); -- cgit v1.2.3