1/* 2 NetBSD disklabel editor for Linux fdisk 3 Written by Bernhard Fastenrath (fasten@informatik.uni-bonn.de) 4 with code from the NetBSD disklabel command: 5 6 Copyright (c) 1987, 1988 Regents of the University of California. 7 All rights reserved. 8 9 Redistribution and use in source and binary forms, with or without 10 modification, are permitted provided that the following conditions 11 are met: 12 1. Redistributions of source code must retain the above copyright 13 notice, this list of conditions and the following disclaimer. 14 2. Redistributions in binary form must reproduce the above copyright 15 notice, this list of conditions and the following disclaimer in the 16 documentation and/or other materials provided with the distribution. 17 3. All advertising materials mentioning features or use of this software 18 must display the following acknowledgement: 19 This product includes software developed by the University of 20 California, Berkeley and its contributors. 21 4. Neither the name of the University nor the names of its contributors 22 may be used to endorse or promote products derived from this software 23 without specific prior written permission. 24 25 THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 SUCH DAMAGE. 36 37 Changes: 38 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls 39 40 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better 41 support for OSF/1 disklabels on Alpha. 42 Also fixed unaligned accesses in alpha_bootblock_checksum() 43*/ 44 45#include <unistd.h> 46#include <stdio.h> 47#include <stdlib.h> 48#include <string.h> 49#include <fcntl.h> 50#include <ctype.h> 51#include <setjmp.h> 52#include <errno.h> 53#include "nls.h" 54 55#include <sys/ioctl.h> 56#include <sys/param.h> 57 58#include "common.h" 59#include "fdisk.h" 60#define FREEBSD_PARTITION 0xa5 61#define NETBSD_PARTITION 0xa9 62#define DKTYPENAMES 63#include "fdiskbsdlabel.h" 64 65static void xbsd_delete_part (void); 66static void xbsd_new_part (void); 67static void xbsd_write_disklabel (void); 68static int xbsd_create_disklabel (void); 69static void xbsd_edit_disklabel (void); 70static void xbsd_write_bootstrap (void); 71static void xbsd_change_fstype (void); 72static int xbsd_get_part_index (int max); 73static int xbsd_check_new_partition (int *i); 74static void xbsd_list_types (void); 75static u_short xbsd_dkcksum (struct xbsd_disklabel *lp); 76static int xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, 77 int pindex); 78static int xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d); 79static int xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d); 80static void sync_disks (void); 81 82#if defined (__alpha__) 83void alpha_bootblock_checksum (char *boot); 84#endif 85 86#if !defined (__alpha__) 87static int xbsd_translate_fstype (int linux_type); 88static void xbsd_link_part (void); 89static struct partition *xbsd_part; 90static int xbsd_part_index; 91#endif 92 93#if defined (__alpha__) 94/* We access this through a u_int64_t * when checksumming */ 95static char disklabelbuffer[BSD_BBSIZE] __attribute__((aligned(8))); 96#else 97static char disklabelbuffer[BSD_BBSIZE]; 98#endif 99 100static struct xbsd_disklabel xbsd_dlabel; 101 102#define bsd_cround(n) \ 103 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n)) 104 105/* 106 * Test whether the whole disk has BSD disk label magic. 107 * 108 * Note: often reformatting with DOS-type label leaves the BSD magic, 109 * so this does not mean that there is a BSD disk label. 110 */ 111int 112check_osf_label(void) { 113 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0) 114 return 0; 115 return 1; 116} 117 118int 119btrydev (char * dev) { 120 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0) 121 return -1; 122 printf(_("\nBSD label for device: %s\n"), dev); 123 xbsd_print_disklabel (0); 124 return 0; 125} 126 127static void 128bmenu (void) { 129 puts (_("Command action")); 130 puts (_(" d delete a BSD partition")); 131 puts (_(" e edit drive data")); 132 puts (_(" i install bootstrap")); 133 puts (_(" l list known filesystem types")); 134 puts (_(" m print this menu")); 135 puts (_(" n add a new BSD partition")); 136 puts (_(" p print BSD partition table")); 137 puts (_(" q quit without saving changes")); 138 puts (_(" r return to main menu")); 139 puts (_(" s show complete disklabel")); 140 puts (_(" t change a partition's filesystem id")); 141 puts (_(" u change units (cylinders/sectors)")); 142 puts (_(" w write disklabel to disk")); 143#if !defined (__alpha__) 144 puts (_(" x link BSD partition to non-BSD partition")); 145#endif 146} 147 148#if !defined (__alpha__) 149static int 150hidden(int type) { 151 return type ^ 0x10; 152} 153 154static int 155is_bsd_partition_type(int type) { 156 return (type == FREEBSD_PARTITION || 157 type == hidden(FREEBSD_PARTITION) || 158 type == NETBSD_PARTITION || 159 type == hidden(NETBSD_PARTITION)); 160} 161#endif 162 163void 164bselect (void) { 165#if !defined (__alpha__) 166 int t, ss; 167 struct partition *p; 168 169 for (t=0; t<4; t++) { 170 p = get_part_table(t); 171 if (p && is_bsd_partition_type(p->sys_ind)) { 172 xbsd_part = p; 173 xbsd_part_index = t; 174 ss = get_start_sect(xbsd_part); 175 if (ss == 0) { 176 fprintf (stderr, _("Partition %s has invalid starting sector 0.\n"), 177 partname(disk_device, t+1, 0)); 178 return; 179 } 180 printf (_("Reading disklabel of %s at sector %d.\n"), 181 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR); 182 if (xbsd_readlabel (xbsd_part, &xbsd_dlabel) == 0) 183 if (xbsd_create_disklabel () == 0) 184 return; 185 break; 186 } 187 } 188 189 if (t == 4) { 190 printf (_("There is no *BSD partition on %s.\n"), disk_device); 191 return; 192 } 193 194#elif defined (__alpha__) 195 196 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0) 197 if (xbsd_create_disklabel () == 0) 198 exit ( EXIT_SUCCESS ); 199 200#endif 201 202 while (1) { 203 putchar ('\n'); 204 switch (tolower (read_char (_("BSD disklabel command (m for help): ")))) { 205 case 'd': 206 xbsd_delete_part (); 207 break; 208 case 'e': 209 xbsd_edit_disklabel (); 210 break; 211 case 'i': 212 xbsd_write_bootstrap (); 213 break; 214 case 'l': 215 xbsd_list_types (); 216 break; 217 case 'n': 218 xbsd_new_part (); 219 break; 220 case 'p': 221 xbsd_print_disklabel (0); 222 break; 223 case 'q': 224 close (fd); 225 exit ( EXIT_SUCCESS ); 226 case 'r': 227 return; 228 case 's': 229 xbsd_print_disklabel (1); 230 break; 231 case 't': 232 xbsd_change_fstype (); 233 break; 234 case 'u': 235 change_units(); 236 break; 237 case 'w': 238 xbsd_write_disklabel (); 239 break; 240#if !defined (__alpha__) 241 case 'x': 242 xbsd_link_part (); 243 break; 244#endif 245 default: 246 bmenu (); 247 break; 248 } 249 } 250} 251 252static void 253xbsd_delete_part (void) 254{ 255 int i; 256 257 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions); 258 xbsd_dlabel.d_partitions[i].p_size = 0; 259 xbsd_dlabel.d_partitions[i].p_offset = 0; 260 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED; 261 if (xbsd_dlabel.d_npartitions == i + 1) 262 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0) 263 xbsd_dlabel.d_npartitions--; 264} 265 266static void 267xbsd_new_part (void) 268{ 269 unsigned int begin, end; 270 char mesg[256]; 271 int i; 272 273 if (!xbsd_check_new_partition (&i)) 274 return; 275 276#if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__) 277 begin = get_start_sect(xbsd_part); 278 end = begin + get_nr_sects(xbsd_part) - 1; 279#else 280 begin = 0; 281 end = xbsd_dlabel.d_secperunit - 1; 282#endif 283 284 snprintf (mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR)); 285 begin = read_int (bsd_cround (begin), bsd_cround (begin), bsd_cround (end), 286 0, mesg); 287 288 if (display_in_cyl_units) 289 begin = (begin - 1) * xbsd_dlabel.d_secpercyl; 290 291 snprintf (mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"), 292 str_units(SINGULAR)); 293 end = read_int (bsd_cround (begin), bsd_cround (end), bsd_cround (end), 294 bsd_cround (begin), mesg); 295 296 if (display_in_cyl_units) 297 end = end * xbsd_dlabel.d_secpercyl - 1; 298 299 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1; 300 xbsd_dlabel.d_partitions[i].p_offset = begin; 301 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED; 302} 303 304void 305xbsd_print_disklabel (int show_all) { 306 struct xbsd_disklabel *lp = &xbsd_dlabel; 307 struct xbsd_partition *pp; 308 FILE *f = stdout; 309 int i, j; 310 311 if (show_all) { 312#if defined (__alpha__) 313 fprintf(f, "# %s:\n", disk_device); 314#else 315 fprintf(f, "# %s:\n", partname(disk_device, xbsd_part_index+1, 0)); 316#endif 317 if ((unsigned) lp->d_type < BSD_DKMAXTYPES) 318 fprintf(f, _("type: %s\n"), xbsd_dktypenames[lp->d_type]); 319 else 320 fprintf(f, _("type: %d\n"), lp->d_type); 321 fprintf(f, _("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename); 322 fprintf(f, _("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname); 323 fprintf(f, _("flags:")); 324 if (lp->d_flags & BSD_D_REMOVABLE) 325 fprintf(f, _(" removable")); 326 if (lp->d_flags & BSD_D_ECC) 327 fprintf(f, _(" ecc")); 328 if (lp->d_flags & BSD_D_BADSECT) 329 fprintf(f, _(" badsect")); 330 fprintf(f, "\n"); 331 /* On various machines the fields of *lp are short/int/long */ 332 /* In order to avoid problems, we cast them all to long. */ 333 fprintf(f, _("bytes/sector: %ld\n"), (long) lp->d_secsize); 334 fprintf(f, _("sectors/track: %ld\n"), (long) lp->d_nsectors); 335 fprintf(f, _("tracks/cylinder: %ld\n"), (long) lp->d_ntracks); 336 fprintf(f, _("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl); 337 fprintf(f, _("cylinders: %ld\n"), (long) lp->d_ncylinders); 338 fprintf(f, _("rpm: %d\n"), lp->d_rpm); 339 fprintf(f, _("interleave: %d\n"), lp->d_interleave); 340 fprintf(f, _("trackskew: %d\n"), lp->d_trackskew); 341 fprintf(f, _("cylinderskew: %d\n"), lp->d_cylskew); 342 fprintf(f, _("headswitch: %ld\t\t# milliseconds\n"), 343 (long) lp->d_headswitch); 344 fprintf(f, _("track-to-track seek: %ld\t# milliseconds\n"), 345 (long) lp->d_trkseek); 346 fprintf(f, _("drivedata: ")); 347 for (i = NDDATA - 1; i >= 0; i--) 348 if (lp->d_drivedata[i]) 349 break; 350 if (i < 0) 351 i = 0; 352 for (j = 0; j <= i; j++) 353 fprintf(f, "%ld ", (long) lp->d_drivedata[j]); 354 } 355 fprintf (f, _("\n%d partitions:\n"), lp->d_npartitions); 356 fprintf (f, _("# start end size fstype [fsize bsize cpg]\n")); 357 pp = lp->d_partitions; 358 for (i = 0; i < lp->d_npartitions; i++, pp++) { 359 if (pp->p_size) { 360 if (display_in_cyl_units && lp->d_secpercyl) { 361 fprintf(f, " %c: %8ld%c %8ld%c %8ld%c ", 362 'a' + i, 363 (long) pp->p_offset / lp->d_secpercyl + 1, 364 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ', 365 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1) 366 / lp->d_secpercyl, 367 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ', 368 (long) pp->p_size / lp->d_secpercyl, 369 (pp->p_size % lp->d_secpercyl) ? '*' : ' '); 370 } else { 371 fprintf(f, " %c: %8ld %8ld %8ld ", 372 'a' + i, 373 (long) pp->p_offset, 374 (long) pp->p_offset + pp->p_size - 1, 375 (long) pp->p_size); 376 } 377 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES) 378 fprintf(f, "%8.8s", xbsd_fstypes[pp->p_fstype].name); 379 else 380 fprintf(f, "%8x", pp->p_fstype); 381 switch (pp->p_fstype) { 382 case BSD_FS_UNUSED: 383 fprintf(f, " %5ld %5ld %5.5s ", 384 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, ""); 385 break; 386 387 case BSD_FS_BSDFFS: 388 fprintf(f, " %5ld %5ld %5d ", 389 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, 390 pp->p_cpg); 391 break; 392 393 default: 394 fprintf(f, "%22.22s", ""); 395 break; 396 } 397 fprintf(f, "\n"); 398 } 399 } 400} 401 402static void 403xbsd_write_disklabel (void) { 404#if defined (__alpha__) 405 printf (_("Writing disklabel to %s.\n"), disk_device); 406 xbsd_writelabel (NULL, &xbsd_dlabel); 407#else 408 printf (_("Writing disklabel to %s.\n"), 409 partname(disk_device, xbsd_part_index+1, 0)); 410 xbsd_writelabel (xbsd_part, &xbsd_dlabel); 411#endif 412 reread_partition_table(0); /* no exit yet */ 413} 414 415static int 416xbsd_create_disklabel (void) { 417 char c; 418 419#if defined (__alpha__) 420 fprintf (stderr, _("%s contains no disklabel.\n"), disk_device); 421#else 422 fprintf (stderr, _("%s contains no disklabel.\n"), 423 partname(disk_device, xbsd_part_index+1, 0)); 424#endif 425 426 while (1) { 427 c = read_char (_("Do you want to create a disklabel? (y/n) ")); 428 if (tolower(c) == 'y') { 429 if (xbsd_initlabel ( 430#if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \ 431 defined (__s390__) || defined (__s390x__) 432 NULL, &xbsd_dlabel, 0 433#else 434 xbsd_part, &xbsd_dlabel, xbsd_part_index 435#endif 436 ) == 1) { 437 xbsd_print_disklabel (1); 438 return 1; 439 } else 440 return 0; 441 } else if (c == 'n') 442 return 0; 443 } 444} 445 446static int 447edit_int (int def, char *mesg) 448{ 449 do { 450 fputs (mesg, stdout); 451 printf (" (%d): ", def); 452 if (!read_line ()) 453 return def; 454 } 455 while (!isdigit (*line_ptr)); 456 return atoi (line_ptr); 457} 458 459static void 460xbsd_edit_disklabel (void) 461{ 462 struct xbsd_disklabel *d; 463 464 d = &xbsd_dlabel; 465 466#if defined (__alpha__) || defined (__ia64__) 467 d -> d_secsize = (u_long) edit_int ((u_long) d -> d_secsize ,_("bytes/sector")); 468 d -> d_nsectors = (u_long) edit_int ((u_long) d -> d_nsectors ,_("sectors/track")); 469 d -> d_ntracks = (u_long) edit_int ((u_long) d -> d_ntracks ,_("tracks/cylinder")); 470 d -> d_ncylinders = (u_long) edit_int ((u_long) d -> d_ncylinders ,_("cylinders")); 471#endif 472 473 /* d -> d_secpercyl can be != d -> d_nsectors * d -> d_ntracks */ 474 while (1) 475 { 476 d -> d_secpercyl = (u_long) edit_int ((u_long) d -> d_nsectors * d -> d_ntracks, 477 _("sectors/cylinder")); 478 if (d -> d_secpercyl <= d -> d_nsectors * d -> d_ntracks) 479 break; 480 481 printf (_("Must be <= sectors/track * tracks/cylinder (default).\n")); 482 } 483 d -> d_rpm = (u_short) edit_int ((u_short) d -> d_rpm ,_("rpm")); 484 d -> d_interleave = (u_short) edit_int ((u_short) d -> d_interleave,_("interleave")); 485 d -> d_trackskew = (u_short) edit_int ((u_short) d -> d_trackskew ,_("trackskew")); 486 d -> d_cylskew = (u_short) edit_int ((u_short) d -> d_cylskew ,_("cylinderskew")); 487 d -> d_headswitch = (u_long) edit_int ((u_long) d -> d_headswitch ,_("headswitch")); 488 d -> d_trkseek = (u_long) edit_int ((u_long) d -> d_trkseek ,_("track-to-track seek")); 489 490 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders; 491} 492 493static int 494xbsd_get_bootstrap (char *path, void *ptr, int size) 495{ 496 int fd; 497 498 if ((fd = open (path, O_RDONLY)) < 0) 499 { 500 perror (path); 501 return 0; 502 } 503 if (read (fd, ptr, size) < 0) 504 { 505 perror (path); 506 close (fd); 507 return 0; 508 } 509 printf (" ... %s\n", path); 510 close (fd); 511 return 1; 512} 513 514static void 515xbsd_write_bootstrap (void) 516{ 517 char *bootdir = BSD_LINUX_BOOTDIR; 518 char path[MAXPATHLEN]; 519 char *dkbasename; 520 struct xbsd_disklabel dl; 521 char *d, *p, *e; 522 int sector; 523 524 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI) 525 dkbasename = "sd"; 526 else 527 dkbasename = "wd"; 528 529 printf (_("Bootstrap: %sboot -> boot%s (%s): "), 530 dkbasename, dkbasename, dkbasename); 531 if (read_line ()) { 532 line_ptr[strlen (line_ptr)-1] = '\0'; 533 dkbasename = line_ptr; 534 } 535 snprintf (path, sizeof(path), "%s/%sboot", bootdir, dkbasename); 536 if (!xbsd_get_bootstrap (path, disklabelbuffer, (int) xbsd_dlabel.d_secsize)) 537 return; 538 539 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */ 540 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE]; 541 bcopy (d, &dl, sizeof (struct xbsd_disklabel)); 542 543 /* The disklabel will be overwritten by 0's from bootxx anyway */ 544 bzero (d, sizeof (struct xbsd_disklabel)); 545 546 snprintf (path, sizeof(path), "%s/boot%s", bootdir, dkbasename); 547 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize], 548 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize)) 549 return; 550 551 e = d + sizeof (struct xbsd_disklabel); 552 for (p=d; p < e; p++) 553 if (*p) { 554 fprintf (stderr, _("Bootstrap overlaps with disk label!\n")); 555 exit ( EXIT_FAILURE ); 556 } 557 558 bcopy (&dl, d, sizeof (struct xbsd_disklabel)); 559 560#if defined (__powerpc__) || defined (__hppa__) 561 sector = 0; 562#elif defined (__alpha__) 563 sector = 0; 564 alpha_bootblock_checksum (disklabelbuffer); 565#else 566 sector = get_start_sect(xbsd_part); 567#endif 568 569 if (lseek (fd, (off_t) sector * SECTOR_SIZE, SEEK_SET) == -1) 570 fatal (unable_to_seek); 571 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE)) 572 fatal (unable_to_write); 573 574#if defined (__alpha__) 575 printf (_("Bootstrap installed on %s.\n"), disk_device); 576#else 577 printf (_("Bootstrap installed on %s.\n"), 578 partname (disk_device, xbsd_part_index+1, 0)); 579#endif 580 581 sync_disks (); 582} 583 584static void 585xbsd_change_fstype (void) 586{ 587 int i; 588 589 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions); 590 xbsd_dlabel.d_partitions[i].p_fstype = read_hex (xbsd_fstypes); 591} 592 593static int 594xbsd_get_part_index (int max) 595{ 596 char prompt[256]; 597 char l; 598 599 snprintf (prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1); 600 do 601 l = tolower (read_char (prompt)); 602 while (l < 'a' || l > 'a' + max - 1); 603 return l - 'a'; 604} 605 606static int 607xbsd_check_new_partition (int *i) { 608 609 /* room for more? various BSD flavours have different maxima */ 610 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) { 611 int t; 612 613 for (t = 0; t < BSD_MAXPARTITIONS; t++) 614 if (xbsd_dlabel.d_partitions[t].p_size == 0) 615 break; 616 617 if (t == BSD_MAXPARTITIONS) { 618 fprintf (stderr, _("The maximum number of partitions " 619 "has been created\n")); 620 return 0; 621 } 622 } 623 624 *i = xbsd_get_part_index (BSD_MAXPARTITIONS); 625 626 if (*i >= xbsd_dlabel.d_npartitions) 627 xbsd_dlabel.d_npartitions = (*i) + 1; 628 629 if (xbsd_dlabel.d_partitions[*i].p_size != 0) { 630 fprintf (stderr, _("This partition already exists.\n")); 631 return 0; 632 } 633 634 return 1; 635} 636 637static void 638xbsd_list_types (void) { 639 list_types (xbsd_fstypes); 640} 641 642static u_short 643xbsd_dkcksum (struct xbsd_disklabel *lp) { 644 u_short *start, *end; 645 u_short sum = 0; 646 647 start = (u_short *) lp; 648 end = (u_short *) &lp->d_partitions[lp->d_npartitions]; 649 while (start < end) 650 sum ^= *start++; 651 return sum; 652} 653 654static int 655xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex) { 656 struct xbsd_partition *pp; 657 struct geom g; 658 659 get_geometry (fd, &g); 660 bzero (d, sizeof (struct xbsd_disklabel)); 661 662 d -> d_magic = BSD_DISKMAGIC; 663 664 if (strncmp (disk_device, "/dev/sd", 7) == 0) 665 d -> d_type = BSD_DTYPE_SCSI; 666 else 667 d -> d_type = BSD_DTYPE_ST506; 668 669#if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */ 670 d -> d_subtype = BSD_DSTYPE_INDOSPART & pindex; 671#endif 672 673#if !defined (__alpha__) 674 d -> d_flags = BSD_D_DOSPART; 675#else 676 d -> d_flags = 0; 677#endif 678 d -> d_secsize = SECTOR_SIZE; /* bytes/sector */ 679 d -> d_nsectors = g.sectors; /* sectors/track */ 680 d -> d_ntracks = g.heads; /* tracks/cylinder (heads) */ 681 d -> d_ncylinders = g.cylinders; 682 d -> d_secpercyl = g.sectors * g.heads;/* sectors/cylinder */ 683 if (d -> d_secpercyl == 0) 684 d -> d_secpercyl = 1; /* avoid segfaults */ 685 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders; 686 687 d -> d_rpm = 3600; 688 d -> d_interleave = 1; 689 d -> d_trackskew = 0; 690 d -> d_cylskew = 0; 691 d -> d_headswitch = 0; 692 d -> d_trkseek = 0; 693 694 d -> d_magic2 = BSD_DISKMAGIC; 695 d -> d_bbsize = BSD_BBSIZE; 696 d -> d_sbsize = BSD_SBSIZE; 697 698#if !defined (__alpha__) 699 d -> d_npartitions = 4; 700 pp = &d -> d_partitions[2]; /* Partition C should be 701 the NetBSD partition */ 702 pp -> p_offset = get_start_sect(p); 703 pp -> p_size = get_nr_sects(p); 704 pp -> p_fstype = BSD_FS_UNUSED; 705 pp = &d -> d_partitions[3]; /* Partition D should be 706 the whole disk */ 707 pp -> p_offset = 0; 708 pp -> p_size = d -> d_secperunit; 709 pp -> p_fstype = BSD_FS_UNUSED; 710#elif defined (__alpha__) 711 d -> d_npartitions = 3; 712 pp = &d -> d_partitions[2]; /* Partition C should be 713 the whole disk */ 714 pp -> p_offset = 0; 715 pp -> p_size = d -> d_secperunit; 716 pp -> p_fstype = BSD_FS_UNUSED; 717#endif 718 719 return 1; 720} 721 722/* 723 * Read a xbsd_disklabel from sector 0 or from the starting sector of p. 724 * If it has the right magic, return 1. 725 */ 726static int 727xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d) 728{ 729 int t, sector; 730 731 /* p is used only to get the starting sector */ 732#if !defined (__alpha__) 733 sector = (p ? get_start_sect(p) : 0); 734#elif defined (__alpha__) 735 sector = 0; 736#endif 737 738 if (lseek (fd, (off_t) sector * SECTOR_SIZE, SEEK_SET) == -1) 739 fatal (unable_to_seek); 740 if (BSD_BBSIZE != read (fd, disklabelbuffer, BSD_BBSIZE)) 741 fatal (unable_to_read); 742 743 bcopy (&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET], 744 d, sizeof (struct xbsd_disklabel)); 745 746 if (d -> d_magic != BSD_DISKMAGIC || d -> d_magic2 != BSD_DISKMAGIC) 747 return 0; 748 749 for (t = d -> d_npartitions; t < BSD_MAXPARTITIONS; t++) { 750 d -> d_partitions[t].p_size = 0; 751 d -> d_partitions[t].p_offset = 0; 752 d -> d_partitions[t].p_fstype = BSD_FS_UNUSED; 753 } 754 755 if (d -> d_npartitions > BSD_MAXPARTITIONS) 756 fprintf (stderr, _("Warning: too many partitions " 757 "(%d, maximum is %d).\n"), 758 d -> d_npartitions, BSD_MAXPARTITIONS); 759 return 1; 760} 761 762static int 763xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d) 764{ 765 unsigned int sector; 766 767#if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__) 768 sector = get_start_sect(p) + BSD_LABELSECTOR; 769#else 770 sector = BSD_LABELSECTOR; 771#endif 772 773 d -> d_checksum = 0; 774 d -> d_checksum = xbsd_dkcksum (d); 775 776 /* This is necessary if we want to write the bootstrap later, 777 otherwise we'd write the old disklabel with the bootstrap. 778 */ 779 bcopy (d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET], 780 sizeof (struct xbsd_disklabel)); 781 782#if defined (__alpha__) && BSD_LABELSECTOR == 0 783 alpha_bootblock_checksum (disklabelbuffer); 784 if (lseek (fd, (off_t) 0, SEEK_SET) == -1) 785 fatal (unable_to_seek); 786 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE)) 787 fatal (unable_to_write); 788#else 789 if (lseek (fd, (off_t) sector * SECTOR_SIZE + BSD_LABELOFFSET, 790 SEEK_SET) == -1) 791 fatal (unable_to_seek); 792 if (sizeof (struct xbsd_disklabel) != write (fd, d, sizeof (struct xbsd_disklabel))) 793 fatal (unable_to_write); 794#endif 795 796 sync_disks (); 797 798 return 1; 799} 800 801static void 802sync_disks (void) 803{ 804 printf (_("\nSyncing disks.\n")); 805 sync (); 806 sleep (4); 807} 808 809#if !defined (__alpha__) 810static int 811xbsd_translate_fstype (int linux_type) 812{ 813 switch (linux_type) 814 { 815 case 0x01: /* DOS 12-bit FAT */ 816 case 0x04: /* DOS 16-bit <32M */ 817 case 0x06: /* DOS 16-bit >=32M */ 818 case 0xe1: /* DOS access */ 819 case 0xe3: /* DOS R/O */ 820 case 0xf2: /* DOS secondary */ 821 return BSD_FS_MSDOS; 822 case 0x07: /* OS/2 HPFS */ 823 return BSD_FS_HPFS; 824 default: 825 return BSD_FS_OTHER; 826 } 827} 828 829static void 830xbsd_link_part (void) 831{ 832 int k, i; 833 struct partition *p; 834 835 k = get_partition (1, partitions); 836 837 if (!xbsd_check_new_partition (&i)) 838 return; 839 840 p = get_part_table(k); 841 842 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p); 843 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p); 844 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind); 845} 846#endif 847 848#if defined (__alpha__) 849 850#if !defined(__GLIBC__) 851typedef unsigned long long u_int64_t; 852#endif 853 854void 855alpha_bootblock_checksum (char *boot) 856{ 857 u_int64_t *dp, sum; 858 int i; 859 860 dp = (u_int64_t *)boot; 861 sum = 0; 862 for (i = 0; i < 63; i++) 863 sum += dp[i]; 864 dp[63] = sum; 865} 866#endif /* __alpha__ */ 867