1 1.12 msaitoh /* $NetBSD: ahdilabel.c,v 1.12 2021/12/05 07:06:17 msaitoh Exp $ */ 2 1.1 leo 3 1.1 leo /* 4 1.1 leo * Copyright (c) 1999 The NetBSD Foundation, Inc. 5 1.1 leo * All rights reserved. 6 1.1 leo * 7 1.1 leo * This code is derived from software contributed to The NetBSD Foundation 8 1.1 leo * by Julian Coleman. 9 1.1 leo * 10 1.1 leo * Redistribution and use in source and binary forms, with or without 11 1.1 leo * modification, are permitted provided that the following conditions 12 1.1 leo * are met: 13 1.1 leo * 1. Redistributions of source code must retain the above copyright 14 1.1 leo * notice, this list of conditions and the following disclaimer. 15 1.1 leo * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 leo * notice, this list of conditions and the following disclaimer in the 17 1.1 leo * documentation and/or other materials provided with the distribution. 18 1.1 leo * 19 1.1 leo * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 leo * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 leo * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 leo * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 leo * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 leo * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 leo * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 leo * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 leo * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 leo * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 leo * POSSIBILITY OF SUCH DAMAGE. 30 1.1 leo */ 31 1.1 leo 32 1.1 leo #include "privahdi.h" 33 1.1 leo #include <ctype.h> 34 1.1 leo #include <errno.h> 35 1.1 leo #include <stdio.h> 36 1.1 leo #include <stdlib.h> 37 1.1 leo #include <strings.h> 38 1.1 leo 39 1.1 leo /* 40 1.1 leo * I think we can safely assume a fixed blocksize - AHDI won't support 41 1.1 leo * something different... 42 1.1 leo */ 43 1.1 leo #define BLPM ((1024 * 1024) / DEV_BSIZE) 44 1.1 leo #define UNITS_SECTORS 0 45 1.1 leo #define UNITS_CTS 1 46 1.3 jdc #define PART_ROOT 0 47 1.3 jdc #define PART_START 1 48 1.3 jdc #define PART_END 2 49 1.1 leo 50 1.1 leo int main (int, char*[]); 51 1.1 leo void show_parts (struct ahdi_ptable*, int, int, int); 52 1.3 jdc int get_input (char *, int); 53 1.9 christos char *sec_to_cts (struct ahdi_ptable*, u_int32_t, char *, size_t); 54 1.3 jdc u_int32_t read_sector (struct ahdi_ptable*, char *, int, int); 55 1.1 leo void change_part (struct ahdi_ptable*, int, int); 56 1.1 leo 57 1.1 leo int 58 1.8 dsl main (int argc, char *argv[]) 59 1.1 leo { 60 1.1 leo struct ahdi_ptable ptable; 61 1.1 leo int flags, rv, key, units; 62 1.1 leo 63 1.1 leo if (argc < 2) { 64 1.1 leo fprintf (stderr, "usage: %s raw_disk\n", argv[0]); 65 1.1 leo exit (EXIT_FAILURE); 66 1.1 leo } 67 1.1 leo 68 1.2 jdc flags = AHDI_IGN_CKSUM; 69 1.1 leo while ((rv = ahdi_readlabel(&ptable, argv[1], flags)) != 1) { 70 1.1 leo switch (rv) { 71 1.1 leo case -1: 72 1.1 leo fprintf (stderr, 73 1.1 leo "%s: %s: %s\n", argv[0], argv[1], 74 1.1 leo strerror (errno)); 75 1.1 leo exit (EXIT_FAILURE); 76 1.1 leo break; 77 1.1 leo case -2: 78 1.1 leo fprintf (stderr, 79 1.1 leo "%s: disk not 512 bytes/sector\n", argv[0]); 80 1.1 leo exit (EXIT_FAILURE); 81 1.1 leo break; 82 1.1 leo case -3: 83 1.3 jdc (void) fpurge(stdin); 84 1.1 leo printf ("No AHDI partitions found. Continue (y/N)?"); 85 1.1 leo if (toupper(getchar()) == 'Y') { 86 1.1 leo flags |= FORCE_AHDI; 87 1.1 leo } else 88 1.1 leo exit (EXIT_FAILURE); 89 1.1 leo break; 90 1.1 leo case -4: 91 1.1 leo case -5: 92 1.1 leo case -6: 93 1.3 jdc (void) fpurge(stdin); 94 1.1 leo printf ("Errors reading AHDI partition table. Override (y/N)? "); 95 1.1 leo if (toupper(getchar()) == 'Y') { 96 1.1 leo flags |= AHDI_IGN_EXISTS | AHDI_IGN_EXT | 97 1.2 jdc AHDI_IGN_SPU; 98 1.1 leo } else 99 1.1 leo exit (EXIT_FAILURE); 100 1.1 leo break; 101 1.1 leo case 1: 102 1.1 leo /* Everything is OK */ 103 1.1 leo break; 104 1.1 leo default: 105 1.1 leo exit (EXIT_FAILURE); 106 1.1 leo break; 107 1.1 leo } 108 1.1 leo } 109 1.1 leo 110 1.1 leo units = UNITS_SECTORS; 111 1.3 jdc flags = AHDI_KEEP_BOOT | AHDI_KEEP_BSL; 112 1.1 leo show_parts (&ptable, 0, ptable.nparts, units); 113 1.3 jdc printf ("Preserve boot sector - "); 114 1.3 jdc flags & AHDI_KEEP_BOOT ? printf ("yes\n") : 115 1.3 jdc printf ("no\n"); 116 1.3 jdc printf ("Preserve bad sector list - "); 117 1.3 jdc flags & AHDI_KEEP_BSL ? printf ("yes\n") : 118 1.3 jdc printf ("no\n"); 119 1.1 leo key = 0; 120 1.1 leo while (key != 'Q') { 121 1.1 leo (void) fpurge(stdin); 122 1.3 jdc printf ("Change [a-p], r)ecalculate, s)how, u)nits, w)rite, z)ero or q)uit "); 123 1.1 leo key = toupper(getchar()); 124 1.1 leo if (key == EOF) 125 1.1 leo key = 'Q'; 126 1.3 jdc if (key >= 'A' && key <= 'P') 127 1.1 leo change_part (&ptable, key - 'A', units); 128 1.1 leo if (key == 'R') { 129 1.3 jdc if (ahdi_buildlabel (&ptable)) { 130 1.12 msaitoh printf ("Partition table adjusted\n"); 131 1.3 jdc } else { 132 1.3 jdc printf ("No changes necessary\n"); 133 1.3 jdc } 134 1.1 leo } 135 1.1 leo if (key == 'S') { 136 1.1 leo show_parts (&ptable, 0, ptable.nparts, units); 137 1.3 jdc printf ("Preserve boot sector - "); 138 1.3 jdc flags & AHDI_KEEP_BOOT ? printf ("yes\n") : 139 1.3 jdc printf ("no\n"); 140 1.3 jdc printf ("Preserve bad sector list - "); 141 1.3 jdc flags & AHDI_KEEP_BSL ? printf ("yes\n") : 142 1.3 jdc printf ("no\n"); 143 1.1 leo } 144 1.1 leo if (key == 'U') { 145 1.3 jdc if (units == UNITS_SECTORS) { 146 1.3 jdc printf ("Units now cylinder/track/sector\n"); 147 1.1 leo units = UNITS_CTS; 148 1.3 jdc } else { 149 1.3 jdc printf ("Units now sector\n"); 150 1.1 leo units = UNITS_SECTORS; 151 1.3 jdc } 152 1.1 leo } 153 1.1 leo if (key == 'W') { 154 1.3 jdc if ((rv = ahdi_writelabel (&ptable, argv[1], flags)) < 0) { 155 1.1 leo if (rv == -1) 156 1.1 leo perror ("\0"); 157 1.1 leo if (rv == -2) 158 1.1 leo printf ("Invalid number of partitions!\n"); 159 1.1 leo if (rv == -3) 160 1.1 leo printf ("GEM partition should be BGM or BGM partition should be GEM!\n"); 161 1.1 leo if (rv == -4) 162 1.1 leo printf ("Partition overlaps root sector or bad sector list (starts before sector 2)!\n"); 163 1.1 leo if (rv == -5) 164 1.1 leo printf ("Partition extends past end of disk!\n"); 165 1.1 leo if (rv == -6) 166 1.1 leo printf ("Partitions overlap!\n"); 167 1.1 leo if (rv == -7) 168 1.4 wiz printf ("Partition overlaps auxiliary root!\n"); 169 1.1 leo if (rv == -8) 170 1.1 leo printf ("More than 4 partitions in root sector!\n"); 171 1.1 leo if (rv == -9) 172 1.1 leo printf ("More than 1 partition in an auxiliary root!\n"); 173 1.1 leo if (rv < -1 && ahdi_errp1 != -1) 174 1.1 leo printf ("\tpartition %c has errors.\n", 175 1.1 leo ahdi_errp1 + 'a'); 176 1.1 leo if (rv < -1 && ahdi_errp2 != -1) 177 1.1 leo printf ("\tpartition %c has errors.\n", 178 1.1 leo ahdi_errp2 + 'a'); 179 1.1 leo } 180 1.1 leo } 181 1.3 jdc if (key == 'Z') { 182 1.3 jdc (void) fpurge(stdin); 183 1.3 jdc printf ("Preserve boot sector? "); 184 1.3 jdc if (flags & AHDI_KEEP_BOOT) { 185 1.3 jdc printf ("[y] "); 186 1.3 jdc if (toupper (getchar ()) == 'N') 187 1.3 jdc flags &= ~AHDI_KEEP_BOOT; 188 1.3 jdc } else { 189 1.3 jdc printf ("[n] "); 190 1.3 jdc if (toupper (getchar ()) == 'Y') 191 1.3 jdc flags |= AHDI_KEEP_BOOT; 192 1.3 jdc } 193 1.3 jdc (void) fpurge(stdin); 194 1.3 jdc printf ("Preserve bad sector list? "); 195 1.3 jdc if (flags & AHDI_KEEP_BSL) { 196 1.3 jdc printf ("[y] "); 197 1.3 jdc if (toupper (getchar ()) == 'N') 198 1.3 jdc flags &= ~AHDI_KEEP_BSL; 199 1.3 jdc } else { 200 1.3 jdc printf ("[n] "); 201 1.3 jdc if (toupper (getchar ()) == 'Y') 202 1.3 jdc flags |= AHDI_KEEP_BSL; 203 1.3 jdc } 204 1.3 jdc } 205 1.1 leo } 206 1.1 leo return (0); 207 1.1 leo } 208 1.1 leo 209 1.1 leo void 210 1.8 dsl show_parts (struct ahdi_ptable *ptable, int start, int finish, int units) 211 1.1 leo { 212 1.1 leo int i; 213 1.1 leo 214 1.1 leo printf ("Disk information :\n"); 215 1.1 leo printf (" sectors/track: %d\n", ptable->nsectors); 216 1.1 leo printf (" tracks/cylinder: %d\n", ptable->ntracks); 217 1.1 leo printf (" sectors/cylinder: %d\n", ptable->secpercyl); 218 1.1 leo printf (" cylinders: %d\n", ptable->ncylinders); 219 1.1 leo printf (" total sectors: %d\n", ptable->secperunit); 220 1.1 leo 221 1.1 leo if (units == UNITS_SECTORS) { 222 1.1 leo printf (" # id root start end size MBs\n"); 223 1.1 leo for (i = start; i < finish; i++) { 224 1.3 jdc if (finish - start > 10 && i - start == 8) { 225 1.3 jdc (void) fpurge(stdin); 226 1.3 jdc printf ("-- Press return for more -- "); 227 1.3 jdc (void) getchar(); 228 1.3 jdc } 229 1.1 leo printf (" %c %c%c%c %8u %8u %8u %8u (%4u)\n", 230 1.1 leo i + 'a', ptable->parts[i].id[0], 231 1.1 leo ptable->parts[i].id[1], ptable->parts[i].id[2], 232 1.1 leo ptable->parts[i].root, ptable->parts[i].start, 233 1.1 leo ptable->parts[i].start + 234 1.1 leo (ptable->parts[i].size ? 235 1.1 leo ptable->parts[i].size - 1 : 0), 236 1.1 leo ptable->parts[i].size, 237 1.1 leo (ptable->parts[i].size + (BLPM >> 1)) / BLPM); 238 1.1 leo } 239 1.1 leo } else { 240 1.1 leo u_int32_t cylinder, track, sector; 241 1.1 leo printf (" # id root start end size MBs\n"); 242 1.1 leo for (i = start; i < finish; i++) { 243 1.3 jdc if (finish - start > 10 && i - start == 8) { 244 1.3 jdc (void) fpurge(stdin); 245 1.3 jdc printf ("-- Press return for more -- "); 246 1.3 jdc (void) getchar(); 247 1.3 jdc } 248 1.1 leo printf (" %c %c%c%c ", i + 'a', 249 1.1 leo ptable->parts[i].id[0], ptable->parts[i].id[1], 250 1.1 leo ptable->parts[i].id[2]); 251 1.1 leo sector = ptable->parts[i].root; 252 1.1 leo cylinder = sector / ptable->secpercyl; 253 1.1 leo sector -= cylinder * ptable->secpercyl; 254 1.1 leo track = sector / ptable->nsectors; 255 1.1 leo sector -= track * ptable->nsectors; 256 1.1 leo printf ("%5u/%2u/%3u ", cylinder, track, sector); 257 1.1 leo sector = ptable->parts[i].start; 258 1.1 leo cylinder = sector / ptable->secpercyl; 259 1.1 leo sector -= cylinder * ptable->secpercyl; 260 1.1 leo track = sector / ptable->nsectors; 261 1.1 leo sector -= track * ptable->nsectors; 262 1.1 leo printf ("%5u/%2u/%3u ", cylinder, track, sector); 263 1.1 leo sector = ptable->parts[i].start + 264 1.1 leo (ptable->parts[i].size ? 265 1.11 christos ptable->parts[i].size - 1 : 0); 266 1.1 leo cylinder = sector / ptable->secpercyl; 267 1.1 leo sector -= cylinder * ptable->secpercyl; 268 1.1 leo track = sector / ptable->nsectors; 269 1.1 leo sector -= track * ptable->nsectors; 270 1.1 leo printf ("%5u/%2u/%3u ", cylinder, track, sector); 271 1.1 leo sector = ptable->parts[i].size; 272 1.1 leo cylinder = sector / ptable->secpercyl; 273 1.1 leo sector -= cylinder * ptable->secpercyl; 274 1.1 leo track = sector / ptable->nsectors; 275 1.1 leo sector -= track * ptable->nsectors; 276 1.1 leo printf ("%5u/%2u/%3u ", cylinder, track, sector); 277 1.1 leo printf ("(%4u)\n", 278 1.1 leo (ptable->parts[i].size + (BLPM >> 1)) / BLPM); 279 1.1 leo } 280 1.1 leo } 281 1.1 leo } 282 1.1 leo 283 1.3 jdc int 284 1.8 dsl get_input (char *buf, int len) 285 1.1 leo { 286 1.1 leo int count, key; 287 1.1 leo 288 1.1 leo count = 0; 289 1.1 leo (void) fpurge(stdin); 290 1.3 jdc while (count < (len - 1) && (key = getchar()) != '\n' && key != '\r') { 291 1.1 leo buf[count] = key; 292 1.1 leo count++; 293 1.1 leo } 294 1.1 leo buf[count] = '\0'; 295 1.3 jdc return(count); 296 1.1 leo } 297 1.1 leo 298 1.1 leo char * 299 1.9 christos sec_to_cts (struct ahdi_ptable *ptable, u_int32_t sector, char *cts, size_t len) 300 1.1 leo { 301 1.1 leo u_int32_t cylinder, track; 302 1.1 leo 303 1.1 leo cylinder = sector / ptable->secpercyl; 304 1.1 leo sector -= cylinder * ptable->secpercyl; 305 1.1 leo track = sector / ptable->nsectors; 306 1.1 leo sector -= track * ptable->nsectors; 307 1.9 christos snprintf (cts, len, "%u/%u/%u", cylinder, track, sector); 308 1.1 leo return (cts); 309 1.1 leo } 310 1.1 leo 311 1.1 leo u_int32_t 312 1.8 dsl read_sector (struct ahdi_ptable *ptable, char *buf, int part, int se) 313 1.1 leo { 314 1.1 leo u_int32_t sector, track, cylinder; 315 1.3 jdc int i; 316 1.1 leo 317 1.1 leo sector = track = cylinder = 0; 318 1.1 leo if ((strchr (buf, '/') != NULL) && 319 1.1 leo ((sscanf (buf, "%u/%u/%u", &cylinder, &track, §or) == 3) || 320 1.1 leo (sscanf (buf, "%u/%u/", &cylinder, &track) == 2) || 321 1.1 leo (sscanf (buf, "%u/", &cylinder) == 1))) { 322 1.1 leo if (sector > ptable->nsectors || track > ptable->ntracks || 323 1.1 leo cylinder > ptable->ncylinders) 324 1.1 leo return (0); 325 1.1 leo sector += ptable->nsectors * track; 326 1.1 leo sector += ptable->secpercyl * cylinder; 327 1.1 leo return (sector); 328 1.1 leo } 329 1.3 jdc if (buf[0] == '-' && buf[1]) { 330 1.3 jdc if (buf[1] == '1' && se == PART_END) 331 1.3 jdc /* Extend to end of disk */ 332 1.3 jdc return (ptable->secperunit - 333 1.3 jdc ptable->parts[part].start); 334 1.5 he i = (int) (toupper ((unsigned char)(buf[1]) - 'A')); 335 1.3 jdc if (i >= 0 && i <= ptable->nparts ) { 336 1.3 jdc if (se == PART_ROOT && part > i) 337 1.3 jdc /* Root after partition ... */ 338 1.3 jdc return (ptable->parts[i].start + 339 1.3 jdc ptable->parts[i].size); 340 1.3 jdc if (se == PART_START && part > i) { 341 1.3 jdc /* Start after partition ... */ 342 1.3 jdc if (ptable->parts[part].root) 343 1.3 jdc return (ptable->parts[i].start + 344 1.3 jdc ptable->parts[i].size + 1); 345 1.3 jdc else 346 1.3 jdc return (ptable->parts[i].start + 347 1.3 jdc ptable->parts[i].size); 348 1.3 jdc } 349 1.3 jdc if (se == PART_END && part < i) 350 1.3 jdc /* End before partition ... */ 351 1.3 jdc return (ptable->parts[i].root - 352 1.3 jdc ptable->parts[part].start); 353 1.3 jdc } 354 1.3 jdc return (0); 355 1.3 jdc } 356 1.3 jdc if (sscanf (buf, "%u", §or) == 1) { 357 1.3 jdc if (buf[strlen (buf) - 1] == 'm' || 358 1.3 jdc buf[strlen (buf) - 1] == 'M') 359 1.3 jdc sector *= BLPM; 360 1.1 leo return (sector); 361 1.3 jdc } 362 1.1 leo return (0); 363 1.1 leo } 364 1.1 leo 365 1.1 leo void 366 1.8 dsl change_part (struct ahdi_ptable *ptable, int part, int units) 367 1.1 leo { 368 1.1 leo #define BUFLEN 20 369 1.1 leo #define CTSLEN 64 370 1.1 leo char buf[BUFLEN], cts[CTSLEN]; 371 1.1 leo u_int32_t sector; 372 1.1 leo 373 1.1 leo if (part > ptable->nparts) { 374 1.1 leo part = ptable->nparts; 375 1.1 leo printf ("Changing partition %c!\n", part + 'a'); 376 1.1 leo ptable->nparts++; 377 1.1 leo } 378 1.1 leo if (part == ptable->nparts) 379 1.1 leo ptable->nparts++; 380 1.1 leo show_parts (ptable, part, part + 1, units); 381 1.1 leo 382 1.1 leo printf ("id [%c%c%c] ", ptable->parts[part].id[0], 383 1.1 leo ptable->parts[part].id[1], ptable->parts[part].id[2]); 384 1.3 jdc if (get_input (&buf[0], BUFLEN) > 2) { 385 1.1 leo ptable->parts[part].id[0] = buf[0]; 386 1.1 leo ptable->parts[part].id[1] = buf[1]; 387 1.1 leo ptable->parts[part].id[2] = buf[2]; 388 1.1 leo } 389 1.1 leo 390 1.1 leo printf ("root [%8u (%s)] ", ptable->parts[part].root, 391 1.9 christos sec_to_cts (ptable, ptable->parts[part].root, cts, sizeof(cts))); 392 1.3 jdc if (get_input (&buf[0], BUFLEN)) { 393 1.3 jdc sector = read_sector (ptable, buf, part, PART_ROOT); 394 1.3 jdc ptable->parts[part].root = sector; 395 1.1 leo } 396 1.1 leo 397 1.1 leo printf ("start [%8u (%s)] ", ptable->parts[part].start, 398 1.9 christos sec_to_cts (ptable, ptable->parts[part].start, cts, sizeof(cts))); 399 1.3 jdc if (get_input (&buf[0], BUFLEN)) { 400 1.3 jdc sector = read_sector (ptable, buf, part, PART_START); 401 1.3 jdc ptable->parts[part].start = sector; 402 1.1 leo } 403 1.1 leo 404 1.3 jdc printf ("size [%8u (%s) (%4uM)] ", ptable->parts[part].size, 405 1.10 ozaki sec_to_cts (ptable, ptable->parts[part].size, cts, sizeof(cts)), 406 1.3 jdc (ptable->parts[part].size + (BLPM >> 1)) / BLPM); 407 1.3 jdc if (get_input (&buf[0], BUFLEN)) { 408 1.3 jdc sector = read_sector (ptable, buf, part, PART_END); 409 1.3 jdc ptable->parts[part].size = sector; 410 1.1 leo } 411 1.1 leo 412 1.1 leo /* 413 1.1 leo printf ("NetBSD disk letter [%c] ", ptable->parts[part].letter + 'a'); 414 1.3 jdc if (get_input (&buf[0], BUFLEN)) { 415 1.3 jdc buf[0] = tolower(buf[0]); 416 1.1 leo if (buf[0] == 'a' || (buf[0] >= 'd' && buf[0] <= 'p')) 417 1.1 leo ptable->parts[part].letter = buf[0] - 'a'; 418 1.1 leo */ 419 1.1 leo 420 1.1 leo if (!ptable->parts[part].start && !ptable->parts[part].size) { 421 1.1 leo if (part == ptable->nparts - 1) 422 1.1 leo ptable->nparts--; 423 1.1 leo } 424 1.1 leo } 425