1/* 2 * Copyright (c) 1987, 1988 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgment: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#if ENABLE_FEATURE_OSF_LABEL 35 36#ifndef BSD_DISKMAGIC 37#define BSD_DISKMAGIC ((uint32_t) 0x82564557) 38#endif 39 40#ifndef BSD_MAXPARTITIONS 41#define BSD_MAXPARTITIONS 16 42#endif 43 44#define BSD_LINUX_BOOTDIR "/usr/ucb/mdec" 45 46#if defined(i386) || defined(__sparc__) || defined(__arm__) \ 47 || defined(__m68k__) || defined(__mips__) || defined(__s390__) \ 48 || defined(__s390__) || defined(__s390x__) \ 49 || defined(__sh__) || defined(__x86_64__) || defined(__avr32__) 50# define BSD_LABELSECTOR 1 51# define BSD_LABELOFFSET 0 52#elif defined(__alpha__) || defined(__powerpc__) || defined(__ia64__) \ 53 || defined(__hppa__) 54# define BSD_LABELSECTOR 0 55# define BSD_LABELOFFSET 64 56#else 57# error unknown architecture 58#endif 59 60#define BSD_BBSIZE 8192 /* size of boot area, with label */ 61#define BSD_SBSIZE 8192 /* max size of fs superblock */ 62 63struct xbsd_disklabel { 64 uint32_t d_magic; /* the magic number */ 65 int16_t d_type; /* drive type */ 66 int16_t d_subtype; /* controller/d_type specific */ 67 char d_typename[16]; /* type name, e.g. "eagle" */ 68 char d_packname[16]; /* pack identifier */ 69 /* disk geometry: */ 70 uint32_t d_secsize; /* # of bytes per sector */ 71 uint32_t d_nsectors; /* # of data sectors per track */ 72 uint32_t d_ntracks; /* # of tracks per cylinder */ 73 uint32_t d_ncylinders; /* # of data cylinders per unit */ 74 uint32_t d_secpercyl; /* # of data sectors per cylinder */ 75 uint32_t d_secperunit; /* # of data sectors per unit */ 76 /* 77 * Spares (bad sector replacements) below 78 * are not counted in d_nsectors or d_secpercyl. 79 * Spare sectors are assumed to be physical sectors 80 * which occupy space at the end of each track and/or cylinder. 81 */ 82 uint16_t d_sparespertrack; /* # of spare sectors per track */ 83 uint16_t d_sparespercyl; /* # of spare sectors per cylinder */ 84 /* 85 * Alternate cylinders include maintenance, replacement, 86 * configuration description areas, etc. 87 */ 88 uint32_t d_acylinders; /* # of alt. cylinders per unit */ 89 90 /* hardware characteristics: */ 91 /* 92 * d_interleave, d_trackskew and d_cylskew describe perturbations 93 * in the media format used to compensate for a slow controller. 94 * Interleave is physical sector interleave, set up by the formatter 95 * or controller when formatting. When interleaving is in use, 96 * logically adjacent sectors are not physically contiguous, 97 * but instead are separated by some number of sectors. 98 * It is specified as the ratio of physical sectors traversed 99 * per logical sector. Thus an interleave of 1:1 implies contiguous 100 * layout, while 2:1 implies that logical sector 0 is separated 101 * by one sector from logical sector 1. 102 * d_trackskew is the offset of sector 0 on track N 103 * relative to sector 0 on track N-1 on the same cylinder. 104 * Finally, d_cylskew is the offset of sector 0 on cylinder N 105 * relative to sector 0 on cylinder N-1. 106 */ 107 uint16_t d_rpm; /* rotational speed */ 108 uint16_t d_interleave; /* hardware sector interleave */ 109 uint16_t d_trackskew; /* sector 0 skew, per track */ 110 uint16_t d_cylskew; /* sector 0 skew, per cylinder */ 111 uint32_t d_headswitch; /* head switch time, usec */ 112 uint32_t d_trkseek; /* track-to-track seek, usec */ 113 uint32_t d_flags; /* generic flags */ 114#define NDDATA 5 115 uint32_t d_drivedata[NDDATA]; /* drive-type specific information */ 116#define NSPARE 5 117 uint32_t d_spare[NSPARE]; /* reserved for future use */ 118 uint32_t d_magic2; /* the magic number (again) */ 119 uint16_t d_checksum; /* xor of data incl. partitions */ 120 /* filesystem and partition information: */ 121 uint16_t d_npartitions; /* number of partitions in following */ 122 uint32_t d_bbsize; /* size of boot area at sn0, bytes */ 123 uint32_t d_sbsize; /* max size of fs superblock, bytes */ 124 struct xbsd_partition { /* the partition table */ 125 uint32_t p_size; /* number of sectors in partition */ 126 uint32_t p_offset; /* starting sector */ 127 uint32_t p_fsize; /* filesystem basic fragment size */ 128 uint8_t p_fstype; /* filesystem type, see below */ 129 uint8_t p_frag; /* filesystem fragments per block */ 130 uint16_t p_cpg; /* filesystem cylinders per group */ 131 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */ 132}; 133 134/* d_type values: */ 135#define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */ 136#define BSD_DTYPE_MSCP 2 /* MSCP */ 137#define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */ 138#define BSD_DTYPE_SCSI 4 /* SCSI */ 139#define BSD_DTYPE_ESDI 5 /* ESDI interface */ 140#define BSD_DTYPE_ST506 6 /* ST506 etc. */ 141#define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */ 142#define BSD_DTYPE_HPFL 8 /* HP Fiber-link */ 143#define BSD_DTYPE_FLOPPY 10 /* floppy */ 144 145/* d_subtype values: */ 146#define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */ 147#define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */ 148#define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */ 149 150static const char *const xbsd_dktypenames[] = { 151 "unknown", 152 "SMD", 153 "MSCP", 154 "old DEC", 155 "SCSI", 156 "ESDI", 157 "ST506", 158 "HP-IB", 159 "HP-FL", 160 "type 9", 161 "floppy", 162 0 163}; 164 165 166/* 167 * Filesystem type and version. 168 * Used to interpret other filesystem-specific 169 * per-partition information. 170 */ 171#define BSD_FS_UNUSED 0 /* unused */ 172#define BSD_FS_SWAP 1 /* swap */ 173#define BSD_FS_V6 2 /* Sixth Edition */ 174#define BSD_FS_V7 3 /* Seventh Edition */ 175#define BSD_FS_SYSV 4 /* System V */ 176#define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */ 177#define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */ 178#define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */ 179#define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */ 180#define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */ 181#define BSD_FS_HPFS 11 /* OS/2 high-performance file system */ 182#define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */ 183#define BSD_FS_ISOFS BSD_FS_ISO9660 184#define BSD_FS_BOOT 13 /* partition contains bootstrap */ 185#define BSD_FS_ADOS 14 /* AmigaDOS fast file system */ 186#define BSD_FS_HFS 15 /* Macintosh HFS */ 187#define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */ 188 189/* this is annoying, but it's also the way it is :-( */ 190#ifdef __alpha__ 191#define BSD_FS_EXT2 8 /* ext2 file system */ 192#else 193#define BSD_FS_MSDOS 8 /* MS-DOS file system */ 194#endif 195 196static const char *const xbsd_fstypes[] = { 197 "\x00" "unused", /* BSD_FS_UNUSED */ 198 "\x01" "swap", /* BSD_FS_SWAP */ 199 "\x02" "Version 6", /* BSD_FS_V6 */ 200 "\x03" "Version 7", /* BSD_FS_V7 */ 201 "\x04" "System V", /* BSD_FS_SYSV */ 202 "\x05" "4.1BSD", /* BSD_FS_V71K */ 203 "\x06" "Eighth Edition", /* BSD_FS_V8 */ 204 "\x07" "4.2BSD", /* BSD_FS_BSDFFS */ 205#ifdef __alpha__ 206 "\x08" "ext2", /* BSD_FS_EXT2 */ 207#else 208 "\x08" "MS-DOS", /* BSD_FS_MSDOS */ 209#endif 210 "\x09" "4.4LFS", /* BSD_FS_BSDLFS */ 211 "\x0a" "unknown", /* BSD_FS_OTHER */ 212 "\x0b" "HPFS", /* BSD_FS_HPFS */ 213 "\x0c" "ISO-9660", /* BSD_FS_ISO9660 */ 214 "\x0d" "boot", /* BSD_FS_BOOT */ 215 "\x0e" "ADOS", /* BSD_FS_ADOS */ 216 "\x0f" "HFS", /* BSD_FS_HFS */ 217 "\x10" "AdvFS", /* BSD_FS_ADVFS */ 218 NULL 219}; 220 221 222/* 223 * flags shared by various drives: 224 */ 225#define BSD_D_REMOVABLE 0x01 /* removable media */ 226#define BSD_D_ECC 0x02 /* supports ECC */ 227#define BSD_D_BADSECT 0x04 /* supports bad sector forw. */ 228#define BSD_D_RAMDISK 0x08 /* disk emulator */ 229#define BSD_D_CHAIN 0x10 /* can do back-back transfers */ 230#define BSD_D_DOSPART 0x20 /* within MSDOS partition */ 231 232/* 233 Changes: 234 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls 235 236 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better 237 support for OSF/1 disklabels on Alpha. 238 Also fixed unaligned accesses in alpha_bootblock_checksum() 239*/ 240 241#define FREEBSD_PARTITION 0xa5 242#define NETBSD_PARTITION 0xa9 243 244static void xbsd_delete_part(void); 245static void xbsd_new_part(void); 246static void xbsd_write_disklabel(void); 247static int xbsd_create_disklabel(void); 248static void xbsd_edit_disklabel(void); 249static void xbsd_write_bootstrap(void); 250static void xbsd_change_fstype(void); 251static int xbsd_get_part_index(int max); 252static int xbsd_check_new_partition(int *i); 253static void xbsd_list_types(void); 254static uint16_t xbsd_dkcksum(struct xbsd_disklabel *lp); 255static int xbsd_initlabel(struct partition *p); 256static int xbsd_readlabel(struct partition *p); 257static int xbsd_writelabel(struct partition *p); 258 259#if defined(__alpha__) 260static void alpha_bootblock_checksum(char *boot); 261#endif 262 263#if !defined(__alpha__) 264static int xbsd_translate_fstype(int linux_type); 265static void xbsd_link_part(void); 266static struct partition *xbsd_part; 267static int xbsd_part_index; 268#endif 269 270 271/* Group big globals data and allocate it in one go */ 272struct bsd_globals { 273/* We access this through a uint64_t * when checksumming */ 274/* hopefully xmalloc gives us required alignment */ 275 char disklabelbuffer[BSD_BBSIZE]; 276 struct xbsd_disklabel xbsd_dlabel; 277}; 278 279static struct bsd_globals *bsd_globals_ptr; 280 281#define disklabelbuffer (bsd_globals_ptr->disklabelbuffer) 282#define xbsd_dlabel (bsd_globals_ptr->xbsd_dlabel) 283 284 285/* Code */ 286 287#define bsd_cround(n) \ 288 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n)) 289 290/* 291 * Test whether the whole disk has BSD disk label magic. 292 * 293 * Note: often reformatting with DOS-type label leaves the BSD magic, 294 * so this does not mean that there is a BSD disk label. 295 */ 296static int 297check_osf_label(void) 298{ 299 if (xbsd_readlabel(NULL) == 0) 300 return 0; 301 return 1; 302} 303 304static int 305bsd_trydev(const char * dev) 306{ 307 if (xbsd_readlabel(NULL) == 0) 308 return -1; 309 printf("\nBSD label for device: %s\n", dev); 310 xbsd_print_disklabel(0); 311 return 0; 312} 313 314static void 315bsd_menu(void) 316{ 317 puts("Command Action"); 318 puts("d\tdelete a BSD partition"); 319 puts("e\tedit drive data"); 320 puts("i\tinstall bootstrap"); 321 puts("l\tlist known filesystem types"); 322 puts("n\tadd a new BSD partition"); 323 puts("p\tprint BSD partition table"); 324 puts("q\tquit without saving changes"); 325 puts("r\treturn to main menu"); 326 puts("s\tshow complete disklabel"); 327 puts("t\tchange a partition's filesystem id"); 328 puts("u\tchange units (cylinders/sectors)"); 329 puts("w\twrite disklabel to disk"); 330#if !defined(__alpha__) 331 puts("x\tlink BSD partition to non-BSD partition"); 332#endif 333} 334 335#if !defined(__alpha__) 336static int 337hidden(int type) 338{ 339 return type ^ 0x10; 340} 341 342static int 343is_bsd_partition_type(int type) 344{ 345 return (type == FREEBSD_PARTITION || 346 type == hidden(FREEBSD_PARTITION) || 347 type == NETBSD_PARTITION || 348 type == hidden(NETBSD_PARTITION)); 349} 350#endif 351 352static void 353bsd_select(void) 354{ 355#if !defined(__alpha__) 356 int t, ss; 357 struct partition *p; 358 359 for (t = 0; t < 4; t++) { 360 p = get_part_table(t); 361 if (p && is_bsd_partition_type(p->sys_ind)) { 362 xbsd_part = p; 363 xbsd_part_index = t; 364 ss = get_start_sect(xbsd_part); 365 if (ss == 0) { 366 printf("Partition %s has invalid starting sector 0\n", 367 partname(disk_device, t+1, 0)); 368 return; 369 } 370 printf("Reading disklabel of %s at sector %u\n", 371 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR); 372 if (xbsd_readlabel(xbsd_part) == 0) 373 if (xbsd_create_disklabel() == 0) 374 return; 375 break; 376 } 377 } 378 379 if (t == 4) { 380 printf("There is no *BSD partition on %s\n", disk_device); 381 return; 382 } 383 384#elif defined(__alpha__) 385 386 if (xbsd_readlabel(NULL) == 0) 387 if (xbsd_create_disklabel() == 0) 388 exit(EXIT_SUCCESS); 389 390#endif 391 392 while (1) { 393 bb_putchar('\n'); 394 switch (tolower(read_nonempty("BSD disklabel command (m for help): "))) { 395 case 'd': 396 xbsd_delete_part(); 397 break; 398 case 'e': 399 xbsd_edit_disklabel(); 400 break; 401 case 'i': 402 xbsd_write_bootstrap(); 403 break; 404 case 'l': 405 xbsd_list_types(); 406 break; 407 case 'n': 408 xbsd_new_part(); 409 break; 410 case 'p': 411 xbsd_print_disklabel(0); 412 break; 413 case 'q': 414 if (ENABLE_FEATURE_CLEAN_UP) 415 close_dev_fd(); 416 exit(EXIT_SUCCESS); 417 case 'r': 418 return; 419 case 's': 420 xbsd_print_disklabel(1); 421 break; 422 case 't': 423 xbsd_change_fstype(); 424 break; 425 case 'u': 426 change_units(); 427 break; 428 case 'w': 429 xbsd_write_disklabel(); 430 break; 431#if !defined(__alpha__) 432 case 'x': 433 xbsd_link_part(); 434 break; 435#endif 436 default: 437 bsd_menu(); 438 break; 439 } 440 } 441} 442 443static void 444xbsd_delete_part(void) 445{ 446 int i; 447 448 i = xbsd_get_part_index(xbsd_dlabel.d_npartitions); 449 xbsd_dlabel.d_partitions[i].p_size = 0; 450 xbsd_dlabel.d_partitions[i].p_offset = 0; 451 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED; 452 if (xbsd_dlabel.d_npartitions == i + 1) 453 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0) 454 xbsd_dlabel.d_npartitions--; 455} 456 457static void 458xbsd_new_part(void) 459{ 460 off_t begin, end; 461 char mesg[256]; 462 int i; 463 464 if (!xbsd_check_new_partition(&i)) 465 return; 466 467#if !defined(__alpha__) && !defined(__powerpc__) && !defined(__hppa__) 468 begin = get_start_sect(xbsd_part); 469 end = begin + get_nr_sects(xbsd_part) - 1; 470#else 471 begin = 0; 472 end = xbsd_dlabel.d_secperunit - 1; 473#endif 474 475 snprintf(mesg, sizeof(mesg), "First %s", str_units(SINGULAR)); 476 begin = read_int(bsd_cround(begin), bsd_cround(begin), bsd_cround(end), 477 0, mesg); 478 479 if (display_in_cyl_units) 480 begin = (begin - 1) * xbsd_dlabel.d_secpercyl; 481 482 snprintf(mesg, sizeof(mesg), "Last %s or +size or +sizeM or +sizeK", 483 str_units(SINGULAR)); 484 end = read_int(bsd_cround(begin), bsd_cround(end), bsd_cround(end), 485 bsd_cround(begin), mesg); 486 487 if (display_in_cyl_units) 488 end = end * xbsd_dlabel.d_secpercyl - 1; 489 490 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1; 491 xbsd_dlabel.d_partitions[i].p_offset = begin; 492 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED; 493} 494 495static void 496xbsd_print_disklabel(int show_all) 497{ 498 struct xbsd_disklabel *lp = &xbsd_dlabel; 499 struct xbsd_partition *pp; 500 int i, j; 501 502 if (show_all) { 503 static const int d_masks[] = { BSD_D_REMOVABLE, BSD_D_ECC, BSD_D_BADSECT }; 504 505#if defined(__alpha__) 506 printf("# %s:\n", disk_device); 507#else 508 printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0)); 509#endif 510 if ((unsigned) lp->d_type < ARRAY_SIZE(xbsd_dktypenames)-1) 511 printf("type: %s\n", xbsd_dktypenames[lp->d_type]); 512 else 513 printf("type: %u\n", lp->d_type); 514 printf("disk: %.*s\n", (int) sizeof(lp->d_typename), lp->d_typename); 515 printf("label: %.*s\n", (int) sizeof(lp->d_packname), lp->d_packname); 516 printf("flags: "); 517 print_flags_separated(d_masks, "removable\0""ecc\0""badsect\0", lp->d_flags, " "); 518 bb_putchar('\n'); 519 /* On various machines the fields of *lp are short/int/long */ 520 /* In order to avoid problems, we cast them all to long. */ 521 printf("bytes/sector: %lu\n", (long) lp->d_secsize); 522 printf("sectors/track: %lu\n", (long) lp->d_nsectors); 523 printf("tracks/cylinder: %lu\n", (long) lp->d_ntracks); 524 printf("sectors/cylinder: %lu\n", (long) lp->d_secpercyl); 525 printf("cylinders: %lu\n", (long) lp->d_ncylinders); 526 printf("rpm: %u\n", lp->d_rpm); 527 printf("interleave: %u\n", lp->d_interleave); 528 printf("trackskew: %u\n", lp->d_trackskew); 529 printf("cylinderskew: %u\n", lp->d_cylskew); 530 printf("headswitch: %lu\t\t# milliseconds\n", 531 (long) lp->d_headswitch); 532 printf("track-to-track seek: %lu\t# milliseconds\n", 533 (long) lp->d_trkseek); 534 printf("drivedata: "); 535 for (i = NDDATA - 1; i >= 0; i--) 536 if (lp->d_drivedata[i]) 537 break; 538 if (i < 0) 539 i = 0; 540 for (j = 0; j <= i; j++) 541 printf("%lu ", (long) lp->d_drivedata[j]); 542 } 543 printf("\n%u partitions:\n", lp->d_npartitions); 544 printf("# start end size fstype [fsize bsize cpg]\n"); 545 pp = lp->d_partitions; 546 for (i = 0; i < lp->d_npartitions; i++, pp++) { 547 if (pp->p_size) { 548 if (display_in_cyl_units && lp->d_secpercyl) { 549 printf(" %c: %8lu%c %8lu%c %8lu%c ", 550 'a' + i, 551 (unsigned long) pp->p_offset / lp->d_secpercyl + 1, 552 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ', 553 (unsigned long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1) / lp->d_secpercyl, 554 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ', 555 (long) pp->p_size / lp->d_secpercyl, 556 (pp->p_size % lp->d_secpercyl) ? '*' : ' ' 557 ); 558 } else { 559 printf(" %c: %8lu %8lu %8lu ", 560 'a' + i, 561 (long) pp->p_offset, 562 (long) pp->p_offset + pp->p_size - 1, 563 (long) pp->p_size 564 ); 565 } 566 567 if ((unsigned) pp->p_fstype < ARRAY_SIZE(xbsd_fstypes)-1) 568 printf("%8.8s", xbsd_fstypes[pp->p_fstype]); 569 else 570 printf("%8x", pp->p_fstype); 571 572 switch (pp->p_fstype) { 573 case BSD_FS_UNUSED: 574 printf(" %5lu %5lu %5.5s ", 575 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, ""); 576 break; 577 case BSD_FS_BSDFFS: 578 printf(" %5lu %5lu %5u ", 579 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, pp->p_cpg); 580 break; 581 default: 582 printf("%22.22s", ""); 583 break; 584 } 585 bb_putchar('\n'); 586 } 587 } 588} 589 590static void 591xbsd_write_disklabel(void) 592{ 593#if defined(__alpha__) 594 printf("Writing disklabel to %s\n", disk_device); 595 xbsd_writelabel(NULL); 596#else 597 printf("Writing disklabel to %s\n", 598 partname(disk_device, xbsd_part_index + 1, 0)); 599 xbsd_writelabel(xbsd_part); 600#endif 601 reread_partition_table(0); /* no exit yet */ 602} 603 604static int 605xbsd_create_disklabel(void) 606{ 607 char c; 608 609#if defined(__alpha__) 610 printf("%s contains no disklabel\n", disk_device); 611#else 612 printf("%s contains no disklabel\n", 613 partname(disk_device, xbsd_part_index + 1, 0)); 614#endif 615 616 while (1) { 617 c = read_nonempty("Do you want to create a disklabel? (y/n) "); 618 if ((c|0x20) == 'y') { 619 if (xbsd_initlabel( 620#if defined(__alpha__) || defined(__powerpc__) || defined(__hppa__) || \ 621 defined(__s390__) || defined(__s390x__) 622 NULL 623#else 624 xbsd_part 625#endif 626 ) == 1) { 627 xbsd_print_disklabel(1); 628 return 1; 629 } 630 return 0; 631 } 632 if ((c|0x20) == 'n') 633 return 0; 634 } 635} 636 637static int 638edit_int(int def, const char *mesg) 639{ 640 mesg = xasprintf("%s (%u): ", mesg, def); 641 do { 642 if (!read_line(mesg)) 643 goto ret; 644 } while (!isdigit(*line_ptr)); 645 def = atoi(line_ptr); 646 ret: 647 free((char*)mesg); 648 return def; 649} 650 651static void 652xbsd_edit_disklabel(void) 653{ 654 struct xbsd_disklabel *d; 655 656 d = &xbsd_dlabel; 657 658#if defined(__alpha__) || defined(__ia64__) 659 d->d_secsize = edit_int(d->d_secsize , "bytes/sector"); 660 d->d_nsectors = edit_int(d->d_nsectors , "sectors/track"); 661 d->d_ntracks = edit_int(d->d_ntracks , "tracks/cylinder"); 662 d->d_ncylinders = edit_int(d->d_ncylinders , "cylinders"); 663#endif 664 665 /* d->d_secpercyl can be != d->d_nsectors * d->d_ntracks */ 666 while (1) { 667 d->d_secpercyl = edit_int(d->d_nsectors * d->d_ntracks, 668 "sectors/cylinder"); 669 if (d->d_secpercyl <= d->d_nsectors * d->d_ntracks) 670 break; 671 672 printf("Must be <= sectors/track * tracks/cylinder (default)\n"); 673 } 674 d->d_rpm = edit_int(d->d_rpm , "rpm"); 675 d->d_interleave = edit_int(d->d_interleave, "interleave"); 676 d->d_trackskew = edit_int(d->d_trackskew , "trackskew"); 677 d->d_cylskew = edit_int(d->d_cylskew , "cylinderskew"); 678 d->d_headswitch = edit_int(d->d_headswitch, "headswitch"); 679 d->d_trkseek = edit_int(d->d_trkseek , "track-to-track seek"); 680 681 d->d_secperunit = d->d_secpercyl * d->d_ncylinders; 682} 683 684static int 685xbsd_get_bootstrap(char *path, void *ptr, int size) 686{ 687 int fdb; 688 689 fdb = open_or_warn(path, O_RDONLY); 690 if (fdb < 0) { 691 return 0; 692 } 693 if (full_read(fdb, ptr, size) < 0) { 694 bb_simple_perror_msg(path); 695 close(fdb); 696 return 0; 697 } 698 printf(" ... %s\n", path); 699 close(fdb); 700 return 1; 701} 702 703static void 704sync_disks(void) 705{ 706 printf("Syncing disks\n"); 707 sync(); 708 /* sleep(4); What? */ 709} 710 711static void 712xbsd_write_bootstrap(void) 713{ 714 char path[MAXPATHLEN]; 715 const char *bootdir = BSD_LINUX_BOOTDIR; 716 const char *dkbasename; 717 struct xbsd_disklabel dl; 718 char *d, *p, *e; 719 int sector; 720 721 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI) 722 dkbasename = "sd"; 723 else 724 dkbasename = "wd"; 725 726 snprintf(path, sizeof(path), "Bootstrap: %sboot -> boot%s (%s): ", 727 dkbasename, dkbasename, dkbasename); 728 if (read_line(path)) { 729 dkbasename = line_ptr; 730 } 731 snprintf(path, sizeof(path), "%s/%sboot", bootdir, dkbasename); 732 if (!xbsd_get_bootstrap(path, disklabelbuffer, (int) xbsd_dlabel.d_secsize)) 733 return; 734 735/* We need a backup of the disklabel (xbsd_dlabel might have changed). */ 736 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE]; 737 memmove(&dl, d, sizeof(struct xbsd_disklabel)); 738 739/* The disklabel will be overwritten by 0's from bootxx anyway */ 740 memset(d, 0, sizeof(struct xbsd_disklabel)); 741 742 snprintf(path, sizeof(path), "%s/boot%s", bootdir, dkbasename); 743 if (!xbsd_get_bootstrap(path, &disklabelbuffer[xbsd_dlabel.d_secsize], 744 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize)) 745 return; 746 747 e = d + sizeof(struct xbsd_disklabel); 748 for (p = d; p < e; p++) 749 if (*p) { 750 printf("Bootstrap overlaps with disk label!\n"); 751 exit(EXIT_FAILURE); 752 } 753 754 memmove(d, &dl, sizeof(struct xbsd_disklabel)); 755 756#if defined(__powerpc__) || defined(__hppa__) 757 sector = 0; 758#elif defined(__alpha__) 759 sector = 0; 760 alpha_bootblock_checksum(disklabelbuffer); 761#else 762 sector = get_start_sect(xbsd_part); 763#endif 764 765 seek_sector(sector); 766 xwrite(dev_fd, disklabelbuffer, BSD_BBSIZE); 767 768#if defined(__alpha__) 769 printf("Bootstrap installed on %s\n", disk_device); 770#else 771 printf("Bootstrap installed on %s\n", 772 partname(disk_device, xbsd_part_index+1, 0)); 773#endif 774 775 sync_disks(); 776} 777 778static void 779xbsd_change_fstype(void) 780{ 781 int i; 782 783 i = xbsd_get_part_index(xbsd_dlabel.d_npartitions); 784 xbsd_dlabel.d_partitions[i].p_fstype = read_hex(xbsd_fstypes); 785} 786 787static int 788xbsd_get_part_index(int max) 789{ 790 char prompt[sizeof("Partition (a-%c): ") + 16]; 791 char l; 792 793 snprintf(prompt, sizeof(prompt), "Partition (a-%c): ", 'a' + max - 1); 794 do 795 l = tolower(read_nonempty(prompt)); 796 while (l < 'a' || l > 'a' + max - 1); 797 return l - 'a'; 798} 799 800static int 801xbsd_check_new_partition(int *i) 802{ 803 /* room for more? various BSD flavours have different maxima */ 804 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) { 805 int t; 806 807 for (t = 0; t < BSD_MAXPARTITIONS; t++) 808 if (xbsd_dlabel.d_partitions[t].p_size == 0) 809 break; 810 811 if (t == BSD_MAXPARTITIONS) { 812 printf("The maximum number of partitions has been created\n"); 813 return 0; 814 } 815 } 816 817 *i = xbsd_get_part_index(BSD_MAXPARTITIONS); 818 819 if (*i >= xbsd_dlabel.d_npartitions) 820 xbsd_dlabel.d_npartitions = (*i) + 1; 821 822 if (xbsd_dlabel.d_partitions[*i].p_size != 0) { 823 printf("This partition already exists\n"); 824 return 0; 825 } 826 827 return 1; 828} 829 830static void 831xbsd_list_types(void) 832{ 833 list_types(xbsd_fstypes); 834} 835 836static uint16_t 837xbsd_dkcksum(struct xbsd_disklabel *lp) 838{ 839 uint16_t *start, *end; 840 uint16_t sum = 0; 841 842 start = (uint16_t *) lp; 843 end = (uint16_t *) &lp->d_partitions[lp->d_npartitions]; 844 while (start < end) 845 sum ^= *start++; 846 return sum; 847} 848 849static int 850xbsd_initlabel(struct partition *p) 851{ 852 struct xbsd_disklabel *d = &xbsd_dlabel; 853 struct xbsd_partition *pp; 854 855 get_geometry(); 856 memset(d, 0, sizeof(struct xbsd_disklabel)); 857 858 d->d_magic = BSD_DISKMAGIC; 859 860 if (strncmp(disk_device, "/dev/sd", 7) == 0) 861 d->d_type = BSD_DTYPE_SCSI; 862 else 863 d->d_type = BSD_DTYPE_ST506; 864 865#if !defined(__alpha__) 866 d->d_flags = BSD_D_DOSPART; 867#else 868 d->d_flags = 0; 869#endif 870 d->d_secsize = SECTOR_SIZE; /* bytes/sector */ 871 d->d_nsectors = g_sectors; /* sectors/track */ 872 d->d_ntracks = g_heads; /* tracks/cylinder (heads) */ 873 d->d_ncylinders = g_cylinders; 874 d->d_secpercyl = g_sectors * g_heads;/* sectors/cylinder */ 875 if (d->d_secpercyl == 0) 876 d->d_secpercyl = 1; /* avoid segfaults */ 877 d->d_secperunit = d->d_secpercyl * d->d_ncylinders; 878 879 d->d_rpm = 3600; 880 d->d_interleave = 1; 881 d->d_trackskew = 0; 882 d->d_cylskew = 0; 883 d->d_headswitch = 0; 884 d->d_trkseek = 0; 885 886 d->d_magic2 = BSD_DISKMAGIC; 887 d->d_bbsize = BSD_BBSIZE; 888 d->d_sbsize = BSD_SBSIZE; 889 890#if !defined(__alpha__) 891 d->d_npartitions = 4; 892 pp = &d->d_partitions[2]; /* Partition C should be NetBSD partition */ 893 894 pp->p_offset = get_start_sect(p); 895 pp->p_size = get_nr_sects(p); 896 pp->p_fstype = BSD_FS_UNUSED; 897 pp = &d->d_partitions[3]; /* Partition D should be whole disk */ 898 899 pp->p_offset = 0; 900 pp->p_size = d->d_secperunit; 901 pp->p_fstype = BSD_FS_UNUSED; 902#else 903 d->d_npartitions = 3; 904 pp = &d->d_partitions[2]; /* Partition C should be 905 the whole disk */ 906 pp->p_offset = 0; 907 pp->p_size = d->d_secperunit; 908 pp->p_fstype = BSD_FS_UNUSED; 909#endif 910 911 return 1; 912} 913 914/* 915 * Read a xbsd_disklabel from sector 0 or from the starting sector of p. 916 * If it has the right magic, return 1. 917 */ 918static int 919xbsd_readlabel(struct partition *p) 920{ 921 struct xbsd_disklabel *d; 922 int t, sector; 923 924 if (!bsd_globals_ptr) 925 bsd_globals_ptr = xzalloc(sizeof(*bsd_globals_ptr)); 926 927 d = &xbsd_dlabel; 928 929 /* p is used only to get the starting sector */ 930#if !defined(__alpha__) 931 sector = (p ? get_start_sect(p) : 0); 932#else 933 sector = 0; 934#endif 935 936 seek_sector(sector); 937 if (BSD_BBSIZE != full_read(dev_fd, disklabelbuffer, BSD_BBSIZE)) 938 fdisk_fatal(unable_to_read); 939 940 memmove(d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET], 941 sizeof(struct xbsd_disklabel)); 942 943 if (d->d_magic != BSD_DISKMAGIC || d->d_magic2 != BSD_DISKMAGIC) 944 return 0; 945 946 for (t = d->d_npartitions; t < BSD_MAXPARTITIONS; t++) { 947 d->d_partitions[t].p_size = 0; 948 d->d_partitions[t].p_offset = 0; 949 d->d_partitions[t].p_fstype = BSD_FS_UNUSED; 950 } 951 952 if (d->d_npartitions > BSD_MAXPARTITIONS) 953 printf("Warning: too many partitions (%u, maximum is %u)\n", 954 d->d_npartitions, BSD_MAXPARTITIONS); 955 return 1; 956} 957 958static int 959xbsd_writelabel(struct partition *p) 960{ 961 struct xbsd_disklabel *d = &xbsd_dlabel; 962 unsigned int sector; 963 964#if !defined(__alpha__) && !defined(__powerpc__) && !defined(__hppa__) 965 sector = get_start_sect(p) + BSD_LABELSECTOR; 966#else 967 (void)p; /* silence warning */ 968 sector = BSD_LABELSECTOR; 969#endif 970 971 d->d_checksum = 0; 972 d->d_checksum = xbsd_dkcksum(d); 973 974 /* This is necessary if we want to write the bootstrap later, 975 otherwise we'd write the old disklabel with the bootstrap. 976 */ 977 memmove(&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET], 978 d, sizeof(struct xbsd_disklabel)); 979 980#if defined(__alpha__) && BSD_LABELSECTOR == 0 981 alpha_bootblock_checksum(disklabelbuffer); 982 seek_sector(0); 983 xwrite(dev_fd, disklabelbuffer, BSD_BBSIZE); 984#else 985 seek_sector(sector); 986 lseek(dev_fd, BSD_LABELOFFSET, SEEK_CUR); 987 xwrite(dev_fd, d, sizeof(*d)); 988#endif 989 sync_disks(); 990 return 1; 991} 992 993 994#if !defined(__alpha__) 995static int 996xbsd_translate_fstype(int linux_type) 997{ 998 switch (linux_type) { 999 case 0x01: /* DOS 12-bit FAT */ 1000 case 0x04: /* DOS 16-bit <32M */ 1001 case 0x06: /* DOS 16-bit >=32M */ 1002 case 0xe1: /* DOS access */ 1003 case 0xe3: /* DOS R/O */ 1004 case 0xf2: /* DOS secondary */ 1005 return BSD_FS_MSDOS; 1006 case 0x07: /* OS/2 HPFS */ 1007 return BSD_FS_HPFS; 1008 default: 1009 return BSD_FS_OTHER; 1010 } 1011} 1012 1013static void 1014xbsd_link_part(void) 1015{ 1016 int k, i; 1017 struct partition *p; 1018 1019 k = get_partition(1, g_partitions); 1020 1021 if (!xbsd_check_new_partition(&i)) 1022 return; 1023 1024 p = get_part_table(k); 1025 1026 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p); 1027 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p); 1028 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind); 1029} 1030#endif 1031 1032#if defined(__alpha__) 1033static void 1034alpha_bootblock_checksum(char *boot) 1035{ 1036 uint64_t *dp, sum; 1037 int i; 1038 1039 dp = (uint64_t *)boot; 1040 sum = 0; 1041 for (i = 0; i < 63; i++) 1042 sum += dp[i]; 1043 dp[63] = sum; 1044} 1045#endif /* __alpha__ */ 1046 1047/* Undefine 'global' tricks */ 1048#undef disklabelbuffer 1049#undef xbsd_dlabel 1050 1051#endif /* OSF_LABEL */ 1052