1 1.7 apb /* $NetBSD: svhlabel.c,v 1.7 2013/02/07 10:44:45 apb Exp $ */ 2 1.1 rumble 3 1.1 rumble /* 4 1.1 rumble * Copyright (C) 2007 Stephen M. Rumble. 5 1.1 rumble * Copyright (C) 1998 Wolfgang Solfrank. 6 1.1 rumble * Copyright (C) 1998 TooLs GmbH. 7 1.1 rumble * All rights reserved. 8 1.1 rumble * 9 1.1 rumble * Redistribution and use in source and binary forms, with or without 10 1.1 rumble * modification, are permitted provided that the following conditions 11 1.1 rumble * are met: 12 1.1 rumble * 1. Redistributions of source code must retain the above copyright 13 1.1 rumble * notice, this list of conditions and the following disclaimer. 14 1.1 rumble * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 rumble * notice, this list of conditions and the following disclaimer in the 16 1.1 rumble * documentation and/or other materials provided with the distribution. 17 1.1 rumble * 3. All advertising materials mentioning features or use of this software 18 1.1 rumble * must display the following acknowledgement: 19 1.1 rumble * This product includes software developed by TooLs GmbH. 20 1.1 rumble * 4. The name of TooLs GmbH may not be used to endorse or promote products 21 1.1 rumble * derived from this software without specific prior written permission. 22 1.1 rumble * 23 1.1 rumble * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 24 1.1 rumble * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 1.1 rumble * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 1.1 rumble * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 1.1 rumble * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 1.1 rumble * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 29 1.1 rumble * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 30 1.1 rumble * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 31 1.1 rumble * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 32 1.1 rumble * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 1.1 rumble */ 34 1.1 rumble 35 1.1 rumble #include <sys/cdefs.h> 36 1.1 rumble #ifndef lint 37 1.7 apb __RCSID("$NetBSD: svhlabel.c,v 1.7 2013/02/07 10:44:45 apb Exp $"); 38 1.1 rumble #endif /* not lint */ 39 1.1 rumble 40 1.1 rumble #include <stdio.h> 41 1.1 rumble #include <err.h> 42 1.1 rumble #include <errno.h> 43 1.1 rumble #include <fcntl.h> 44 1.1 rumble #include <limits.h> 45 1.1 rumble #include <stdlib.h> 46 1.1 rumble #include <string.h> 47 1.1 rumble #include <unistd.h> 48 1.1 rumble #include <util.h> 49 1.1 rumble 50 1.1 rumble #include <sys/param.h> 51 1.1 rumble #define FSTYPENAMES 52 1.1 rumble #include <sys/disklabel.h> 53 1.1 rumble #include <sys/bootblock.h> 54 1.1 rumble #include <sys/ioctl.h> 55 1.1 rumble 56 1.4 rumble #include <fs/efs/efs.h> 57 1.3 rumble #include <fs/efs/efs_sb.h> 58 1.3 rumble 59 1.1 rumble #include "dkcksum.h" 60 1.1 rumble #include "extern.h" 61 1.1 rumble 62 1.6 joerg __dead static void usage(void); 63 1.1 rumble static void getlabel(int); 64 1.1 rumble static void setlabel(int, int); 65 1.1 rumble static int getparts(int, int); 66 1.1 rumble static int is_efs(int, uint32_t); 67 1.1 rumble static struct sgi_boot_block *convert_sgi_boot_block(unsigned char *); 68 1.1 rumble 69 1.1 rumble struct disklabel label; 70 1.7 apb static int rawpart; 71 1.1 rumble 72 1.1 rumble static void 73 1.1 rumble getlabel(int sd) 74 1.1 rumble { 75 1.1 rumble 76 1.1 rumble if (ioctl(sd, DIOCGDINFO, &label) < 0) { 77 1.1 rumble perror("get label"); 78 1.1 rumble exit(1); 79 1.1 rumble } 80 1.1 rumble /* 81 1.1 rumble * Some ports seem to not set the number of partitions 82 1.1 rumble * correctly, albeit they seem to set the raw partition ok! 83 1.1 rumble */ 84 1.7 apb if (label.d_npartitions <= rawpart) 85 1.7 apb label.d_npartitions = rawpart + 1; 86 1.1 rumble } 87 1.1 rumble 88 1.1 rumble static void 89 1.1 rumble setlabel(int sd, int doraw) 90 1.1 rumble { 91 1.1 rumble int one = 1; 92 1.1 rumble 93 1.1 rumble label.d_checksum = 0; 94 1.1 rumble label.d_checksum = dkcksum(&label); 95 1.1 rumble if (ioctl(sd, doraw ? DIOCWDINFO : DIOCSDINFO, &label) < 0) { 96 1.1 rumble perror("set label"); 97 1.1 rumble exit(1); 98 1.1 rumble } 99 1.1 rumble if (!doraw) 100 1.1 rumble /* If we haven't written to the disk, don't discard on close */ 101 1.1 rumble ioctl(sd, DIOCKLABEL, &one); 102 1.1 rumble 103 1.1 rumble } 104 1.1 rumble 105 1.1 rumble static int 106 1.1 rumble getparts(int sd, int verbose) 107 1.1 rumble { 108 1.1 rumble unsigned char buf[DEV_BSIZE]; 109 1.1 rumble struct sgi_boot_block *vh; 110 1.1 rumble struct partition npe; 111 1.1 rumble int i, j, changed; 112 1.1 rumble 113 1.1 rumble changed = 0; 114 1.1 rumble 115 1.1 rumble if (lseek(sd, 0, SEEK_SET) == -1) { 116 1.1 rumble perror("seek vh"); 117 1.1 rumble exit(1); 118 1.1 rumble } 119 1.1 rumble if ((i = read(sd, buf, sizeof(buf))) != DEV_BSIZE) { 120 1.1 rumble perror("read vh"); 121 1.1 rumble exit(1); 122 1.1 rumble } 123 1.1 rumble vh = convert_sgi_boot_block(buf); 124 1.1 rumble 125 1.1 rumble if (vh->magic != SGI_BOOT_BLOCK_MAGIC) 126 1.1 rumble return (changed); 127 1.1 rumble 128 1.1 rumble if (label.d_secsize != SGI_BOOT_BLOCK_BLOCKSIZE) 129 1.1 rumble changed++; 130 1.1 rumble label.d_secsize = SGI_BOOT_BLOCK_BLOCKSIZE; 131 1.1 rumble 132 1.1 rumble for (i = j = 0; i < SGI_BOOT_BLOCK_MAXPARTITIONS; i++) { 133 1.1 rumble if (vh->partitions[i].blocks == 0) 134 1.1 rumble continue; 135 1.1 rumble 136 1.1 rumble if (j == MAXPARTITIONS) 137 1.1 rumble break; 138 1.1 rumble 139 1.1 rumble switch (vh->partitions[i].type) { 140 1.1 rumble case SGI_PTYPE_EFS: 141 1.1 rumble /* 142 1.1 rumble * For some reason, my IRIX CDs list EFS partitions as SYSV!? 143 1.1 rumble */ 144 1.1 rumble case SGI_PTYPE_SYSV: 145 1.1 rumble if (is_efs(sd, vh->partitions[i].first)) { 146 1.1 rumble npe.p_fstype = FS_EFS; 147 1.1 rumble npe.p_size = vh->partitions[i].blocks; 148 1.1 rumble npe.p_offset = vh->partitions[i].first; 149 1.1 rumble npe.p_fsize = 0; 150 1.1 rumble npe.p_frag = 0; 151 1.1 rumble npe.p_cpg = 0; 152 1.1 rumble } 153 1.1 rumble break; 154 1.1 rumble 155 1.1 rumble case SGI_PTYPE_VOLUME: 156 1.5 lukem if (label.d_secperunit != (uint32_t)vh->partitions[i].blocks) 157 1.1 rumble changed++; 158 1.1 rumble label.d_secperunit = vh->partitions[i].blocks; 159 1.1 rumble continue; 160 1.1 rumble 161 1.1 rumble default: 162 1.1 rumble continue; 163 1.1 rumble } 164 1.1 rumble 165 1.1 rumble if (j >= label.d_npartitions) 166 1.1 rumble break; 167 1.1 rumble 168 1.7 apb if (j == rawpart) { 169 1.1 rumble if (++j >= label.d_npartitions) 170 1.1 rumble break; 171 1.1 rumble } 172 1.1 rumble 173 1.1 rumble if (memcmp(&label.d_partitions[j], &npe, sizeof(npe)) != 0) { 174 1.1 rumble label.d_partitions[j] = npe; 175 1.1 rumble changed++; 176 1.1 rumble } 177 1.1 rumble 178 1.1 rumble j++; 179 1.1 rumble } 180 1.1 rumble 181 1.1 rumble /* XXX - fudge */ 182 1.1 rumble if (label.d_nsectors != 1 || label.d_ntracks != 1 || 183 1.1 rumble label.d_secpercyl != 1 || label.d_ncylinders != label.d_secperunit) 184 1.1 rumble changed++; 185 1.1 rumble label.d_nsectors = 1; 186 1.1 rumble label.d_ntracks = 1; 187 1.1 rumble label.d_secpercyl = 1; 188 1.1 rumble label.d_ncylinders = label.d_secperunit; 189 1.1 rumble 190 1.7 apb i = rawpart; 191 1.1 rumble if (label.d_partitions[i].p_fstype != FS_UNUSED || 192 1.1 rumble label.d_partitions[i].p_offset != 0 || 193 1.1 rumble label.d_partitions[i].p_size != label.d_secperunit) { 194 1.1 rumble label.d_partitions[i].p_fstype = FS_UNUSED; 195 1.1 rumble label.d_partitions[i].p_offset = 0; 196 1.1 rumble label.d_partitions[i].p_size = label.d_secperunit; 197 1.1 rumble changed++; 198 1.1 rumble } 199 1.1 rumble 200 1.1 rumble return (changed); 201 1.1 rumble } 202 1.1 rumble 203 1.1 rumble static int 204 1.1 rumble is_efs(int sd, uint32_t blkoff) 205 1.1 rumble { 206 1.4 rumble struct efs_sb sb; 207 1.1 rumble off_t oldoff; 208 1.1 rumble 209 1.1 rumble if ((oldoff = lseek(sd, 0, SEEK_CUR)) == -1) { 210 1.1 rumble perror("is_efs lseek 0"); 211 1.1 rumble exit(1); 212 1.1 rumble } 213 1.1 rumble 214 1.4 rumble blkoff *= SGI_BOOT_BLOCK_BLOCKSIZE; 215 1.4 rumble if (lseek(sd, blkoff + (EFS_BB_SB * EFS_BB_SIZE), SEEK_SET) == -1) { 216 1.1 rumble perror("is_efs lseek 1"); 217 1.1 rumble exit(1); 218 1.1 rumble } 219 1.1 rumble 220 1.4 rumble if (read(sd, &sb, sizeof(sb)) != sizeof(sb)) { 221 1.1 rumble perror("is_efs read"); 222 1.1 rumble exit(1); 223 1.1 rumble } 224 1.1 rumble 225 1.1 rumble if (lseek(sd, oldoff, SEEK_SET) == -1) { 226 1.1 rumble perror("is_efs lseek 2"); 227 1.1 rumble exit(1); 228 1.1 rumble } 229 1.1 rumble 230 1.4 rumble BE32TOH(sb.sb_magic); 231 1.1 rumble 232 1.4 rumble return (sb.sb_magic == EFS_SB_MAGIC || sb.sb_magic == EFS_SB_NEWMAGIC); 233 1.1 rumble } 234 1.1 rumble 235 1.1 rumble static struct sgi_boot_block * 236 1.1 rumble convert_sgi_boot_block(unsigned char *buf) 237 1.1 rumble { 238 1.1 rumble struct sgi_boot_block *vh; 239 1.1 rumble int i; 240 1.1 rumble 241 1.1 rumble vh = (struct sgi_boot_block *)buf; 242 1.1 rumble 243 1.1 rumble BE32TOH(vh->magic); 244 1.1 rumble BE16TOH(vh->root); 245 1.1 rumble BE16TOH(vh->swap); 246 1.1 rumble 247 1.1 rumble BE16TOH(vh->dp.dp_cyls); 248 1.1 rumble BE16TOH(vh->dp.dp_shd0); 249 1.1 rumble BE16TOH(vh->dp.dp_trks0); 250 1.1 rumble BE16TOH(vh->dp.dp_secs); 251 1.1 rumble BE16TOH(vh->dp.dp_secbytes); 252 1.1 rumble BE16TOH(vh->dp.dp_interleave); 253 1.1 rumble BE32TOH(vh->dp.dp_flags); 254 1.1 rumble BE32TOH(vh->dp.dp_datarate); 255 1.1 rumble BE32TOH(vh->dp.dp_nretries); 256 1.1 rumble BE32TOH(vh->dp.dp_mspw); 257 1.1 rumble BE16TOH(vh->dp.dp_xgap1); 258 1.1 rumble BE16TOH(vh->dp.dp_xsync); 259 1.1 rumble BE16TOH(vh->dp.dp_xrdly); 260 1.1 rumble BE16TOH(vh->dp.dp_xgap2); 261 1.1 rumble BE16TOH(vh->dp.dp_xrgate); 262 1.1 rumble BE16TOH(vh->dp.dp_xwcont); 263 1.1 rumble 264 1.1 rumble for (i = 0; i < SGI_BOOT_BLOCK_MAXVOLDIRS; i++) { 265 1.1 rumble BE32TOH(vh->voldir[i].block); 266 1.1 rumble BE32TOH(vh->voldir[i].bytes); 267 1.1 rumble } 268 1.1 rumble 269 1.1 rumble for (i = 0; i < SGI_BOOT_BLOCK_MAXPARTITIONS; i++) { 270 1.1 rumble BE32TOH(vh->partitions[i].blocks); 271 1.1 rumble BE32TOH(vh->partitions[i].first); 272 1.1 rumble BE32TOH(vh->partitions[i].type); 273 1.1 rumble } 274 1.1 rumble 275 1.1 rumble BE32TOH(vh->checksum); 276 1.1 rumble 277 1.1 rumble return (vh); 278 1.1 rumble } 279 1.1 rumble 280 1.1 rumble static void 281 1.1 rumble usage(void) 282 1.1 rumble { 283 1.1 rumble fprintf(stderr, "usage: %s [-fqrw] rawdisk\n", 284 1.1 rumble getprogname()); 285 1.1 rumble exit(1); 286 1.1 rumble } 287 1.1 rumble 288 1.1 rumble 289 1.1 rumble int 290 1.1 rumble main(int argc, char **argv) 291 1.1 rumble { 292 1.1 rumble int sd, ch, changed; 293 1.1 rumble char name[MAXPATHLEN]; 294 1.1 rumble int force; /* force label update */ 295 1.1 rumble int raw; /* update on-disk label as well */ 296 1.1 rumble int verbose; /* verbose output */ 297 1.1 rumble int write_it; /* update in-core label if changed */ 298 1.1 rumble 299 1.1 rumble force = 0; 300 1.1 rumble raw = 0; 301 1.1 rumble verbose = 1; 302 1.1 rumble write_it = 0; 303 1.1 rumble while ((ch = getopt(argc, argv, "fqrw")) != -1) { 304 1.1 rumble switch (ch) { 305 1.1 rumble case 'f': 306 1.1 rumble force = 1; 307 1.1 rumble break; 308 1.1 rumble case 'q': 309 1.1 rumble verbose = 0; 310 1.1 rumble break; 311 1.1 rumble case 'r': 312 1.1 rumble raw = 1; 313 1.1 rumble break; 314 1.1 rumble case 'w': 315 1.1 rumble write_it = 1; 316 1.1 rumble break; 317 1.1 rumble default: 318 1.1 rumble usage(); 319 1.1 rumble } 320 1.1 rumble } 321 1.1 rumble argc -= optind; 322 1.1 rumble argv += optind; 323 1.1 rumble if (argc != 1) 324 1.1 rumble usage(); 325 1.1 rumble 326 1.7 apb rawpart = getrawpartition(); 327 1.7 apb if (rawpart < 0) 328 1.7 apb err(EXIT_FAILURE, "getrawpartition"); 329 1.7 apb 330 1.1 rumble if ((sd = opendisk(argv[0], write_it ? O_RDWR : O_RDONLY, name, 331 1.1 rumble (size_t)MAXPATHLEN, 1)) < 0) { 332 1.1 rumble perror(argv[0]); 333 1.1 rumble exit(1); 334 1.1 rumble } 335 1.1 rumble getlabel(sd); 336 1.1 rumble changed = getparts(sd, verbose); 337 1.1 rumble 338 1.1 rumble if (verbose) { 339 1.1 rumble putchar('\n'); 340 1.1 rumble showpartitions(stdout, &label, 0); 341 1.1 rumble putchar('\n'); 342 1.1 rumble } 343 1.1 rumble if (write_it) { 344 1.1 rumble if (! changed && ! force) 345 1.1 rumble printf("No change; not updating disk label.\n"); 346 1.1 rumble else { 347 1.1 rumble if (verbose) 348 1.1 rumble printf("Updating in-core %sdisk label.\n", 349 1.1 rumble raw ? "and on-disk " : ""); 350 1.1 rumble raw = 0; /* XXX */ 351 1.1 rumble setlabel(sd, raw); 352 1.1 rumble } 353 1.1 rumble } else { 354 1.1 rumble printf("Not updating disk label.\n"); 355 1.1 rumble } 356 1.1 rumble close(sd); 357 1.1 rumble return (0); 358 1.1 rumble } 359