DF-3039 / mkfat3039.c
/* DF-3039 image crafter (guest-side): sparse FAT32 with data area start * (firstcluster = 32 + 2*0x40000000 = 0x80000020) beyond the 2^31 block * boundary, so cntobn(pmp, newcluster) >= 2^31 truncates in 'int bn'. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <unistd.h> #include <fcntl.h> static unsigned char bs[512], fsi[512], fat0[24]; static void p16(unsigned char *p, int off, unsigned v) { p[off] = v & 0xff; p[off+1] = (v >> 8) & 0xff; } static void p32(unsigned char *p, int off, uint32_t v) { p[off] = v & 0xff; p[off+1] = (v >> 8) & 0xff; p[off+2] = (v >> 16) & 0xff; p[off+3] = (v >> 24) & 0xff; } int main(int argc, char **argv) { const char *img = argv[1]; uint32_t resv = 32, nfats = 2; uint32_t fatsecs = 0x40000000u; /* 2^30 sectors/FAT */ uint32_t hugesec = 0x80012020u; /* firstcluster + 0x12000 */ int fd; memset(bs, 0, sizeof(bs)); memset(fsi, 0, sizeof(fsi)); memset(fat0, 0, sizeof(fat0)); memcpy(bs, "\xeb\x58\x90" "DF3039 ", 11); p16(bs, 11, 512); /* bytes/sec */ bs[13] = 1; /* sec/cluster */ p16(bs, 14, resv); bs[16] = (unsigned char)nfats; bs[21] = 0xF8; p16(bs, 24, 63); p16(bs, 26, 255); p32(bs, 32, hugesec); /* totsec32 */ p32(bs, 36, fatsecs); /* fatsz32 */ p16(bs, 40, 0); /* extflags */ p16(bs, 42, 0); /* fsver */ p32(bs, 44, 2); /* root cluster */ p16(bs, 48, 1); /* fsinfo sector */ p16(bs, 50, 6); /* bkboot sector */ bs[510] = 0x55; bs[511] = 0xAA; memcpy(fsi, "RRaA", 4); p32(fsi, 484, 0xFFFFFFFFu); p32(fsi, 488, 0xFFFFFFFFu); memcpy(fsi + 508, "rrAa", 4); p32(fat0, 0, 0xFFFFFFF8u); /* FAT[0] */ p32(fat0, 4, 0xFFFFFFFFu); /* FAT[1] */ p32(fat0, 8, 0xFFFFFFFFu); /* FAT[2] root EOC */ fd = open(img, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (fd < 0) { perror("open"); exit(1); } if (write(fd, bs, 512) != 512) { perror("write"); exit(1); } if (lseek(fd, 512, SEEK_SET) < 0 || write(fd, fsi, 512) != 512) { perror("fsinfo"); exit(1); } if (lseek(fd, 6 * 512, SEEK_SET) < 0 || write(fd, bs, 512) != 512) { perror("bkboot"); exit(1); } if (lseek(fd, (off_t)resv * 512, SEEK_SET) < 0 || write(fd, fat0, 24) != 24) { perror("fat"); exit(1); } if (ftruncate(fd, (off_t)hugesec * 512) < 0) { perror("ftruncate"); exit(1); } close(fd); printf("firstcluster=0x%x hugesec=0x%x (~%u clusters) size=%.2f TiB sparse\n", 32 + (uint32_t)(nfats * fatsecs), hugesec, hugesec - 32 - nfats * fatsecs, (double)((off_t)hugesec * 512) / 1099511627776.0); return 0; } |