DF-3212 / craft_img.c
/* * craft_img.c - DF-3212 superblock fs_qbmask patcher (read-side OOB harness). * * Same mechanic as the DF-0903 pack: binary-patch fs_qbmask (int64 LE, * file offset SBOFF(8192) + 1336 = 9528) in a cleanly-unmounted UFS1 image * produced by `newfs -b 8192 -f 1024`. Normal qbmask for bsize 8192 is * 0x1FFF; we patch 0x7FFFF so blkoff(fs, off) = off & 0x7FFFF can reach * 0x7FFFE, i.e. up to 7 MAXBSIZE (64KB) buffer-cache KVA slots past the * 8192-byte buffer that ffs_blkatoff_ra() returns. * * Field offsets verified via offsets.c on this guest (struct fs, sizeof=1384): * fs_bsize=48 fs_bmask=72 fs_bshift=80 fs_inodefmt=1324 * fs_qbmask=1336 fs_qfmask=1344 fs_postblformat=1356 fs_magic=1372 * * Build: cc -O -o craft_img craft_img.c * Usage: craft_img <base.img> <out.img> <qbmask_hex> */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <unistd.h> #include <fcntl.h> #define SBOFF 8192 #define OFF_FS_BSIZE 48 #define OFF_FS_BMASK 72 #define OFF_FS_INODEFMT 1324 #define OFF_FS_QBMASK 1336 /* int64, 8 bytes */ #define OFF_FS_MAGIC 1372 static int32_t rd_i32(const unsigned char *p){ return (int32_t)(p[0] | (p[1]<<8) | (p[2]<<16) | ((uint32_t)p[3]<<24)); } static int64_t rd_i64(const unsigned char *p){ uint64_t v = 0; for (int i = 0; i < 8; i++) v |= (uint64_t)p[i] << (8*i); return (int64_t)v; } static void wr_i64(unsigned char *p, int64_t v){ uint64_t u = (uint64_t)v; for (int i = 0; i < 8; i++) p[i] = (unsigned char)((u >> (8*i)) & 0xff); } int main(int argc, char **argv){ if (argc < 4) { fprintf(stderr, "usage: %s base.img out.img qbmask_hex\n", argv[0]); return 2; } const char *base = argv[1]; const char *out = argv[2]; int64_t qbmask = (int64_t)strtoll(argv[3], NULL, 0); FILE *f = fopen(base, "rb"); if (!f) { perror("open base"); return 2; } fseek(f, 0, SEEK_END); long sz = ftell(f); fseek(f, 0, SEEK_SET); unsigned char *buf = malloc(sz); if (!buf) { perror("malloc"); return 2; } if ((long)fread(buf, 1, sz, f) != sz) { perror("read"); return 2; } fclose(f); unsigned char *sb = buf + SBOFF; if (rd_i32(sb + OFF_FS_MAGIC) != 0x011954) { fprintf(stderr, "bad magic at SBOFF\n"); return 2; } printf("base: fs_bsize=%d fs_bmask=0x%x fs_inodefmt=%d fs_qbmask=0x%llx\n", rd_i32(sb + OFF_FS_BSIZE), rd_i32(sb + OFF_FS_BMASK), rd_i32(sb + OFF_FS_INODEFMT), (unsigned long long)rd_i64(sb + OFF_FS_QBMASK)); wr_i64(sb + OFF_FS_QBMASK, qbmask); printf("patched: fs_qbmask=0x%llx\n", (unsigned long long)qbmask); FILE *g = fopen(out, "wb"); if (!g) { perror("open out"); return 2; } if ((long)fwrite(buf, 1, sz, g) != sz) { perror("write"); return 2; } fclose(g); free(buf); return 0; } |