1 /* 2 * Copyright 2020, François Revol, revol@free.fr. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #include <fcntl.h> 7 #include <stddef.h> 8 #include <stdio.h> 9 #include <stdint.h> 10 #include <unistd.h> 11 #include <arpa/inet.h> 12 13 #include <disklabel.h> 14 15 /* for now we actually write all of the disk label here. */ 16 17 #define DL_SIZE (offsetof(struct disk_label, dl_un.DL_v3_checksum) \ 18 + sizeof(uint16_t)) 19 #define SUM_CNT (offsetof(struct disk_label, dl_un.DL_v3_checksum) \ 20 / sizeof(uint16_t)) 21 22 #define H2B32 htonl 23 #define H2B16 htons 24 #define B2H16 ntohs 25 26 27 // see https://unix.superglobalmegacorp.com/darwin01/newsrc/machdep/i386/checksum_16.c.html 28 static uint16_t checksum_16(uint16_t *p, int count) 29 { 30 uint32_t sum = 0; 31 for (;count--;) 32 sum += B2H16(*p++); 33 // sum both shorts 34 sum = (sum & 0x0ffff) + (sum >> 16); 35 if (sum > 65535) 36 sum -= 65535; 37 return sum; 38 } 39 40 41 int main(int argc, char **argv) 42 { 43 int fd; 44 uint16_t sum; 45 int labelOffsets[] = { 0, 15, 30, 45 }; 46 // HACK: for now we force a single label plus the bootlock at 8kb 47 // (min offset the ROM allows) to fit before the tgz 48 int numLabels = 1; // sizeof(labelOffsets) / sizeof(int); 49 uint32_t bootBlockStart = 0x8; // usually 0x20 50 51 struct disk_label disklabel = { 52 H2B32(DL_V3), 53 H2B32(0), 54 H2B32(0), 55 "HaikuBoot",//"NextBoot", 56 H2B32(0), 57 // dl_tag, we use 'HAIK' 58 H2B32(0x4841494b), // H2B32(0xa991637a), 59 "Sony MPX-111N 2880-512", // same as NS image, not sure it matters 60 "removable_rw_floppy", 61 H2B32(1024), // !! 1024 bytes / sector !! 62 H2B32(2), 63 H2B32(9), 64 H2B32(80), 65 H2B32(300), 66 H2B16(96), 67 H2B16(0), 68 H2B16(0), 69 H2B16(0), 70 H2B16(0), 71 H2B16(0), 72 // boot blocks in 1024 bytes sectors 73 H2B32(bootBlockStart),H2B32(0xffffffff), 74 "haiku_loader", // "fdmach" 75 "schredder", // "silly" 76 'a', 'b', 77 // partitions 78 { 79 // Nextstep uses this: 80 //{ H2B32(0), H2B32(0x540), H2B16(0x2000), H2B16(0x400), 't', 81 // H2B16(0x20), H2B16(0x800), 0, 1, "", 1, "4.3BSD"}, 82 // XXX: should we fake an fs anyway? 83 { H2B32(-1), H2B32(-1), H2B16(-1), H2B16(-1), 0, 84 H2B16(-1), H2B16(-1), -1, 0, "", 0, ""}, 85 { H2B32(-1), H2B32(-1), H2B16(-1), H2B16(-1), 0, 86 H2B16(-1), H2B16(-1), -1, 0, "", 0, ""}, 87 { H2B32(-1), H2B32(-1), H2B16(-1), H2B16(-1), 0, 88 H2B16(-1), H2B16(-1), -1, 0, "", 0, ""}, 89 { H2B32(-1), H2B32(-1), H2B16(-1), H2B16(-1), 0, 90 H2B16(-1), H2B16(-1), -1, 0, "", 0, ""}, 91 { H2B32(-1), H2B32(-1), H2B16(-1), H2B16(-1), 0, 92 H2B16(-1), H2B16(-1), -1, 0, "", 0, ""}, 93 { H2B32(-1), H2B32(-1), H2B16(-1), H2B16(-1), 0, 94 H2B16(-1), H2B16(-1), -1, 0, "", 0, ""}, 95 { H2B32(-1), H2B32(-1), H2B16(-1), H2B16(-1), 0, 96 H2B16(-1), H2B16(-1), -1, 0, "", 0, ""}, 97 { H2B32(-1), H2B32(-1), H2B16(-1), H2B16(-1), 0, 98 H2B16(-1), H2B16(-1), -1, 0, "", 0, ""} 99 }, 100 { 0 }, 101 0 102 }; 103 fd = open(argv[1], O_RDWR); 104 if (fd < 0) { 105 perror("open"); 106 return 1; 107 } 108 //XXX: support simple checksum of existing label? 109 #if 0 110 if (read(fd, bootblock, DL_SIZE) < DL_SIZE) { 111 perror("read"); 112 return 1; 113 } 114 #endif 115 116 // TODO: take boot block offsets as arg? 117 118 sum = checksum_16((uint16_t *)&disklabel, SUM_CNT); 119 fprintf(stderr, "checksum: 0x%04x\n", sum); 120 disklabel.dl_un.DL_v3_checksum = H2B16(sum); 121 122 for (unsigned int i = 0; i < numLabels; i++) { 123 /* also write copies elsewhere, note we don't update the checksum */ 124 disklabel.dl_label_blkno = H2B32(labelOffsets[i]); 125 /* oddly this field seems to use 512 bytes sectors */ 126 lseek(fd, labelOffsets[i] * 0x200LL, SEEK_SET); 127 write(fd, &disklabel, DL_SIZE); 128 } 129 130 // TODO: patch the bootblock text segment to include the tgz 131 132 return 0; 133 } 134