xref: /openbsd-src/usr.sbin/mksuncd/mksuncd.c (revision 3ec9f6c666125fcceba82f9441e651a7c9939b74)
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