1 /* $OpenBSD: mksuncd.c,v 1.5 2021/12/23 09:17:19 jsg Exp $ */
2
3 /*
4 * Copyright (c) 2001 Jason L. Wright (jason@thought.net)
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /*
30 * WARNING! WARNING!
31 * This program is not type safe (it assumes sparc type sizes) and not
32 * endian safe (assumes sparc endianness).
33 * WARNING! WARNING!
34 */
35
36 /*
37 * Copyright (c) 1992, 1993
38 * The Regents of the University of California. All rights reserved.
39 *
40 * This software was developed by the Computer Systems Engineering group
41 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
42 * contributed to Berkeley.
43 *
44 * All advertising materials mentioning features or use of this software
45 * must display the following acknowledgement:
46 * This product includes software developed by the University of
47 * California, Lawrence Berkeley Laboratory.
48 *
49 * Redistribution and use in source and binary forms, with or without
50 * modification, are permitted provided that the following conditions
51 * are met:
52 * 1. Redistributions of source code must retain the above copyright
53 * notice, this list of conditions and the following disclaimer.
54 * 2. Redistributions in binary form must reproduce the above copyright
55 * notice, this list of conditions and the following disclaimer in the
56 * documentation and/or other materials provided with the distribution.
57 * 3. Neither the name of the University nor the names of its contributors
58 * may be used to endorse or promote products derived from this software
59 * without specific prior written permission.
60 *
61 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
62 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
63 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
64 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
65 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
66 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
67 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
68 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
69 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
70 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
71 * SUCH DAMAGE.
72 *
73 * @(#)sun_disklabel.h 8.1 (Berkeley) 6/11/93
74 */
75
76 #include <stdio.h>
77 #include <sys/types.h>
78 #include <sys/stat.h>
79 #include <unistd.h>
80 #include <fcntl.h>
81 #include <err.h>
82 #include <string.h>
83
84 /*
85 * SunOS disk label layout (only relevant portions discovered here).
86 * JLW XXX should get these definitions from elsewhere, oh well.
87 */
88
89 #define SUN_DKMAGIC 55998
90
91 /* partition info */
92 struct sun_dkpart {
93 int sdkp_cyloffset; /* starting cylinder */
94 int sdkp_nsectors; /* number of sectors */
95 };
96
97 struct sun_disklabel { /* total size = 512 bytes */
98 char sl_text[128];
99 char sl_xxx1[292];
100 #define sl_bsdlabel sl_xxx1 /* Embedded OpenBSD label */
101 u_short sl_rpm; /* rotational speed */
102 u_short sl_pcylinders; /* number of physical cyls */
103 #define sl_pcyl sl_pcylinders /* XXX: old sun3 */
104 u_short sl_sparespercyl; /* spare sectors per cylinder */
105 char sl_xxx3[4];
106 u_short sl_interleave; /* interleave factor */
107 u_short sl_ncylinders; /* data cylinders */
108 u_short sl_acylinders; /* alternate cylinders */
109 u_short sl_ntracks; /* tracks per cylinder */
110 u_short sl_nsectors; /* sectors per track */
111 char sl_xxx4[4];
112 struct sun_dkpart sl_part[8]; /* partition layout */
113 u_short sl_magic; /* == SUN_DKMAGIC */
114 u_short sl_cksum; /* xor checksum of all shorts */
115 };
116
117 int expand_file(int, off_t);
118 void usage(void);
119 int adjust_base(int, struct sun_disklabel *);
120 int get_label(int, struct sun_disklabel *);
121 int append_osfile(int, int);
122 off_t cylindersize(int, struct sun_disklabel *);
123 int adjust_label(int, struct sun_disklabel *, int, off_t, off_t);
124
125 int
expand_file(int f,off_t len)126 expand_file(int f, off_t len)
127 {
128 char buf[1024];
129 off_t i;
130
131 if (lseek(f, 0, SEEK_END) == -1)
132 return (-1);
133 bzero(buf, sizeof(buf));
134 while (len) {
135 i = (sizeof(buf) < len) ? sizeof(buf) : len;
136 if (write(f, buf, i) != i)
137 return (-1);
138 len -= i;
139 }
140 return (0);
141 }
142
143 void
usage(void)144 usage(void)
145 {
146 fprintf(stderr, "usage: mksuncd partition isoimage bootimage\n");
147 }
148
149 /*
150 * Adjust size of base to meet a cylinder boundary.
151 */
152 int
adjust_base(int f,struct sun_disklabel * slp)153 adjust_base(int f, struct sun_disklabel *slp)
154 {
155 struct stat st;
156 off_t sz;
157
158 if (lseek(f, 0, SEEK_END) == -1)
159 err(1, "lseek");
160
161 if (fstat(f, &st) == -1)
162 err(1, "fstat");
163
164 sz = ((off_t)slp->sl_nsectors) *
165 ((off_t)slp->sl_ntracks) * ((off_t)512);
166
167 if ((st.st_size % sz) != 0) {
168 if (expand_file(f, sz - (st.st_size % sz)))
169 err(1, "expand_file");
170 }
171
172 return (0);
173 }
174
175 int
get_label(int f,struct sun_disklabel * slp)176 get_label(int f, struct sun_disklabel *slp)
177 {
178 int r;
179
180 if (lseek(f, 0, SEEK_SET) == -1)
181 err(1, "lseek");
182
183 r = read(f, slp, sizeof(*slp));
184 if (r == -1)
185 err(1, "read");
186 if (r != sizeof(*slp))
187 errx(1, "short read");
188
189 if (slp->sl_ntracks == 0 || slp->sl_ncylinders == 0 ||
190 slp->sl_nsectors == 0)
191 errx(1, "bogus disklabel");
192
193 return (0);
194 }
195
196 int
main(int argc,char ** argv)197 main(int argc, char **argv)
198 {
199 struct sun_disklabel sl;
200 int part, bf, of;
201 off_t cylstart, cylsize;
202
203 if (argc != 4) {
204 usage();
205 return (1);
206 }
207
208 if (argv[1] == NULL || strlen(argv[1]) != 1 ||
209 (argv[1][0] < 'a' || argv[1][0] > 'h')) {
210 usage();
211 return (1);
212 }
213 part = argv[1][0] - 'a';
214
215 if (argv[2] == NULL || argv[3] == NULL) {
216 usage();
217 return (1);
218 }
219
220 bf = open(argv[2], O_RDWR);
221 if (bf == -1)
222 err(1, "open");
223
224 of = open(argv[3], O_RDONLY);
225 if (of == -1)
226 err(1, "open");
227
228 if (pledge("stdio", NULL) == -1)
229 err(1, "pledge");
230
231 if (get_label(bf, &sl))
232 return (1);
233
234 if (adjust_base(bf, &sl))
235 return (1);
236
237 cylstart = cylindersize(bf, &sl);
238 cylsize = cylindersize(of, &sl);
239
240 if (append_osfile(bf, of))
241 return (1);
242
243 if (adjust_base(bf, &sl))
244 return (1);
245
246 if (adjust_label(bf, &sl, part, cylstart, cylsize))
247 return (1);
248
249 close(bf);
250 close(of);
251
252 return (0);
253 }
254
255 /*
256 * Put our entry into the disklabel, recompute label checksum, and
257 * write it back to the disk.
258 */
259 int
adjust_label(int f,struct sun_disklabel * slp,int part,off_t start,off_t size)260 adjust_label(int f, struct sun_disklabel *slp, int part, off_t start, off_t size)
261 {
262 u_short sum = 0, *sp;
263 int i;
264
265 if (start > 65535)
266 errx(1, "start too large! %lld", (long long)start);
267 if (part < 0 || part >= 8)
268 errx(1, "invalid partition: %d", part);
269 slp->sl_part[part].sdkp_cyloffset = start;
270 slp->sl_part[part].sdkp_nsectors =
271 size * slp->sl_nsectors * slp->sl_ntracks;
272
273 slp->sl_cksum = 0;
274 sp = (u_short *)slp;
275 for (i = 0; i < sizeof(*slp)/sizeof(u_short); i++) {
276 sum ^= *sp;
277 sp++;
278 }
279 slp->sl_cksum = sum;
280
281 if (lseek(f, 0, SEEK_SET) == -1)
282 return (-1);
283
284 i = write(f, slp, sizeof(*slp));
285 if (i == -1)
286 err(1, "write modified label");
287 if (i != sizeof(*slp))
288 errx(1, "short write modified label");
289 return (0);
290 }
291
292 int
append_osfile(int outf,int inf)293 append_osfile(int outf, int inf)
294 {
295 char buf[512];
296 int r, len;
297
298 while (1) {
299 len = read(inf, buf, sizeof(buf));
300 if (len == -1)
301 err(1, "read osfile");
302 if (len == 0)
303 return (0);
304
305 r = write(outf, buf, len);
306 if (r == -1)
307 err(1, "write basefile");
308 if (r != len)
309 errx(1, "short write basefile");
310 }
311 }
312
313 off_t
cylindersize(int f,struct sun_disklabel * slp)314 cylindersize(int f, struct sun_disklabel *slp)
315 {
316 struct stat st;
317 off_t sz, r;
318
319 if (fstat(f, &st) == -1)
320 err(1, "fstat");
321
322 sz = ((off_t)slp->sl_nsectors) *
323 ((off_t)slp->sl_ntracks) * ((off_t)512);
324
325 r = st.st_size / sz;
326
327 if ((st.st_size % sz) == 0)
328 return (r);
329 return (r + 1);
330 }
331