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
checksum_16(uint16_t * p,int count)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
main(int argc,char ** argv)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