1 /* $OpenBSD: mksuncd.c,v 1.2 2010/02/25 17:15:42 deraadt 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 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 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 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 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 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 (get_label(bf, &sl)) 229 return (1); 230 231 if (adjust_base(bf, &sl)) 232 return (1); 233 234 cylstart = cylindersize(bf, &sl); 235 cylsize = cylindersize(of, &sl); 236 237 if (append_osfile(bf, of)) 238 return (1); 239 240 if (adjust_base(bf, &sl)) 241 return (1); 242 243 if (adjust_label(bf, &sl, part, cylstart, cylsize)) 244 return (1); 245 246 close(bf); 247 close(of); 248 249 return (0); 250 } 251 252 /* 253 * Put our entry into the disklabel, recompute label checksum, and 254 * write it back to the disk. 255 */ 256 int 257 adjust_label(int f, struct sun_disklabel *slp, int part, off_t start, off_t size) 258 { 259 u_short sum = 0, *sp; 260 int i; 261 262 if (start > 65535) 263 errx(1, "start too large! %lld", (long long)start); 264 if (part < 0 || part > 8) 265 errx(1, "invalid partition: %d", part); 266 slp->sl_part[part].sdkp_cyloffset = start; 267 slp->sl_part[part].sdkp_nsectors = 268 size * slp->sl_nsectors * slp->sl_ntracks; 269 270 slp->sl_cksum = 0; 271 sp = (u_short *)slp; 272 for (i = 0; i < sizeof(*slp)/sizeof(u_short); i++) { 273 sum ^= *sp; 274 sp++; 275 } 276 slp->sl_cksum = sum; 277 278 if (lseek(f, 0, SEEK_SET) == -1) 279 return (-1); 280 281 i = write(f, slp, sizeof(*slp)); 282 if (i < 0) 283 err(1, "write modified label"); 284 if (i != sizeof(*slp)) 285 errx(1, "short write modified label"); 286 return (0); 287 } 288 289 int 290 append_osfile(int outf, int inf) 291 { 292 char buf[512]; 293 int r, len; 294 295 while (1) { 296 len = read(inf, buf, sizeof(buf)); 297 if (len < 0) 298 err(1, "read osfile"); 299 if (len == 0) 300 return (0); 301 302 r = write(outf, buf, len); 303 if (r < 0) 304 err(1, "write basefile"); 305 if (r != len) 306 errx(1, "short write basefile"); 307 } 308 } 309 310 off_t 311 cylindersize(int f, struct sun_disklabel *slp) 312 { 313 struct stat st; 314 off_t sz, r; 315 316 if (fstat(f, &st) == -1) 317 err(1, "fstat"); 318 319 sz = ((off_t)slp->sl_nsectors) * 320 ((off_t)slp->sl_ntracks) * ((off_t)512); 321 322 r = st.st_size / sz; 323 324 if ((st.st_size % sz) == 0) 325 return (r); 326 return (r + 1); 327 } 328