1/* 2 * fdisksunlabel.c 3 * 4 * I think this is mostly, or entirely, due to 5 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996 6 * 7 * Merged with fdisk for other architectures, aeb, June 1998. 8 * 9 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br> 10 * Internationalization 11 */ 12 13#include <stdio.h> /* stderr */ 14#include <stdlib.h> /* qsort */ 15#include <string.h> /* strstr */ 16#include <unistd.h> /* write */ 17#include <sys/ioctl.h> /* ioctl */ 18#include <sys/stat.h> /* stat */ 19#include <sys/sysmacros.h> /* major */ 20 21#include "nls.h" 22 23#include <endian.h> 24 25#ifdef HAVE_SCSI_SCSI_H 26#define u_char unsigned char 27#include <scsi/scsi.h> /* SCSI_IOCTL_GET_IDLUN */ 28#undef u_char 29#endif 30 31#include <linux/major.h> /* FLOPPY_MAJOR */ 32 33#include "common.h" 34#include "fdisk.h" 35#include "fdisksunlabel.h" 36 37static int other_endian = 0; 38static int scsi_disk = 0; 39static int floppy = 0; 40 41#define LINUX_SWAP 0x82 42#define LINUX_NATIVE 0x83 43 44struct systypes sun_sys_types[] = { 45 {0, N_("Empty")}, 46 {1, N_("Boot")}, 47 {2, N_("SunOS root")}, 48 {SUNOS_SWAP, N_("SunOS swap")}, 49 {4, N_("SunOS usr")}, 50 {WHOLE_DISK, N_("Whole disk")}, 51 {6, N_("SunOS stand")}, 52 {7, N_("SunOS var")}, 53 {8, N_("SunOS home")}, 54 {LINUX_SWAP, N_("Linux swap")}, 55 {LINUX_NATIVE, N_("Linux native")}, 56 {0x8e, N_("Linux LVM")}, 57 {0xfd, N_("Linux raid autodetect")},/* New (2.2.x) raid partition 58 with autodetect using 59 persistent superblock */ 60 { 0, NULL } 61}; 62 63static inline unsigned short __swap16(unsigned short x) { 64 return (((__u16)(x) & 0xFF) << 8) | (((__u16)(x) & 0xFF00) >> 8); 65} 66static inline __u32 __swap32(__u32 x) { 67 return (((__u32)(x) & 0xFF) << 24) | (((__u32)(x) & 0xFF00) << 8) | (((__u32)(x) & 0xFF0000) >> 8) | (((__u32)(x) & 0xFF000000) >> 24); 68} 69 70int 71get_num_sectors(struct sun_partition p) { 72 return SSWAP32(p.num_sectors); 73} 74 75#ifndef IDE0_MAJOR 76#define IDE0_MAJOR 3 77#endif 78#ifndef IDE1_MAJOR 79#define IDE1_MAJOR 22 80#endif 81void guess_device_type(int fd) { 82 struct stat bootstat; 83 84 if (fstat (fd, &bootstat) < 0) { 85 scsi_disk = 0; 86 floppy = 0; 87 } else if (S_ISBLK(bootstat.st_mode) 88 && (major(bootstat.st_rdev) == IDE0_MAJOR || 89 major(bootstat.st_rdev) == IDE1_MAJOR)) { 90 scsi_disk = 0; 91 floppy = 0; 92 } else if (S_ISBLK(bootstat.st_mode) 93 && major(bootstat.st_rdev) == FLOPPY_MAJOR) { 94 scsi_disk = 0; 95 floppy = 1; 96 } else { 97 scsi_disk = 1; 98 floppy = 0; 99 } 100} 101 102static void 103set_sun_partition(int i, unsigned int start, unsigned int stop, int sysid) { 104 sunlabel->infos[i].id = sysid; 105 sunlabel->partitions[i].start_cylinder = 106 SSWAP32(start / (heads * sectors)); 107 sunlabel->partitions[i].num_sectors = 108 SSWAP32(stop - start); 109 set_changed(i); 110} 111 112void 113sun_nolabel(void) { 114 sun_label = 0; 115 sunlabel->magic = 0; 116 partitions = 4; 117} 118 119int 120check_sun_label(void) { 121 unsigned short *ush; 122 int csum; 123 124 if (sunlabel->magic != SUN_LABEL_MAGIC && 125 sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) { 126 sun_label = 0; 127 other_endian = 0; 128 return 0; 129 } 130 other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED); 131 ush = ((unsigned short *) (sunlabel + 1)) - 1; 132 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--; 133 if (csum) { 134 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n" 135 "Probably you'll have to set all the values,\n" 136 "e.g. heads, sectors, cylinders and partitions\n" 137 "or force a fresh label (s command in main menu)\n")); 138 } else { 139 heads = SSWAP16(sunlabel->ntrks); 140 cylinders = SSWAP16(sunlabel->ncyl); 141 sectors = SSWAP16(sunlabel->nsect); 142 } 143 update_units(); 144 sun_label = 1; 145 partitions = 8; 146 return 1; 147} 148 149struct sun_predefined_drives { 150 char *vendor; 151 char *model; 152 unsigned short sparecyl; 153 unsigned short ncyl; 154 unsigned short nacyl; 155 unsigned short pcylcount; 156 unsigned short ntrks; 157 unsigned short nsect; 158 unsigned short rspeed; 159} sun_drives[] = { 160{"Quantum","ProDrive 80S",1,832,2,834,6,34,3662}, 161{"Quantum","ProDrive 105S",1,974,2,1019,6,35,3662}, 162{"CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600}, 163{"IBM","DPES-31080",0,4901,2,4903,4,108,5400}, 164{"IBM","DORS-32160",0,1015,2,1017,67,62,5400}, 165{"IBM","DNES-318350",0,11199,2,11474,10,320,7200}, 166{"SEAGATE","ST34371",0,3880,2,3882,16,135,7228}, 167{"","SUN0104",1,974,2,1019,6,35,3662}, 168{"","SUN0207",4,1254,2,1272,9,36,3600}, 169{"","SUN0327",3,1545,2,1549,9,46,3600}, 170{"","SUN0340",0,1538,2,1544,6,72,4200}, 171{"","SUN0424",2,1151,2,2500,9,80,4400}, 172{"","SUN0535",0,1866,2,2500,7,80,5400}, 173{"","SUN0669",5,1614,2,1632,15,54,3600}, 174{"","SUN1.0G",5,1703,2,1931,15,80,3597}, 175{"","SUN1.05",0,2036,2,2038,14,72,5400}, 176{"","SUN1.3G",6,1965,2,3500,17,80,5400}, 177{"","SUN2.1G",0,2733,2,3500,19,80,5400}, 178{"IOMEGA","Jaz",0,1019,2,1021,64,32,5394}, 179}; 180 181static struct sun_predefined_drives * 182sun_autoconfigure_scsi(void) { 183 struct sun_predefined_drives *p = NULL; 184 185#ifdef SCSI_IOCTL_GET_IDLUN 186 unsigned int id[2]; 187 char buffer[2048]; 188 char buffer2[2048]; 189 FILE *pfd; 190 char *vendor; 191 char *model; 192 char *q; 193 int i; 194 195 if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) { 196 sprintf(buffer, 197 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n", 198#if 0 199 ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33, 200#else 201 /* This is very wrong (works only if you have one HBA), 202 but I haven't found a way how to get hostno 203 from the current kernel */ 204 0, 205#endif 206 (id[0]>>16)&0xff, 207 id[0]&0xff, 208 (id[0]>>8)&0xff); 209 pfd = fopen("/proc/scsi/scsi","r"); 210 if (pfd) { 211 while (fgets(buffer2,2048,pfd)) { 212 if (!strcmp(buffer, buffer2)) { 213 if (fgets(buffer2,2048,pfd)) { 214 q = strstr(buffer2,"Vendor: "); 215 if (q) { 216 q += 8; 217 vendor = q; 218 q = strstr(q," "); 219 *q++ = 0; /* truncate vendor name */ 220 q = strstr(q,"Model: "); 221 if (q) { 222 *q = 0; 223 q += 7; 224 model = q; 225 q = strstr(q," Rev: "); 226 if (q) { 227 *q = 0; 228 for (i = 0; i < SIZE(sun_drives); i++) { 229 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor)) 230 continue; 231 if (!strstr(model, sun_drives[i].model)) 232 continue; 233 printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model); 234 p = sun_drives + i; 235 break; 236 } 237 } 238 } 239 } 240 } 241 break; 242 } 243 } 244 fclose(pfd); 245 } 246 } 247#endif 248 return p; 249} 250 251void create_sunlabel(void) 252{ 253 struct hd_geometry geometry; 254 unsigned int ndiv; 255 int i; 256 unsigned char c; 257 struct sun_predefined_drives *p = NULL; 258 259 fprintf(stderr, 260 _("Building a new sun disklabel. Changes will remain in memory only,\n" 261 "until you decide to write them. After that, of course, the previous\n" 262 "content won't be recoverable.\n\n")); 263#if BYTE_ORDER == LITTLE_ENDIAN 264 other_endian = 1; 265#else 266 other_endian = 0; 267#endif 268 memset(MBRbuffer, 0, sizeof(MBRbuffer)); 269 sunlabel->magic = SSWAP16(SUN_LABEL_MAGIC); 270 if (!floppy) { 271 puts(_("Drive type\n" 272 " ? auto configure\n" 273 " 0 custom (with hardware detected defaults)")); 274 for (i = 0; i < SIZE(sun_drives); i++) { 275 printf(" %c %s%s%s\n", 276 i + 'a', sun_drives[i].vendor, 277 (*sun_drives[i].vendor) ? " " : "", 278 sun_drives[i].model); 279 } 280 for (;;) { 281 c = read_char(_("Select type (? for auto, 0 for custom): ")); 282 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) { 283 p = sun_drives + c - 'a'; 284 break; 285 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) { 286 p = sun_drives + c - 'A'; 287 break; 288 } else if (c == '0') { 289 break; 290 } else if (c == '?' && scsi_disk) { 291 p = sun_autoconfigure_scsi(); 292 if (!p) 293 printf(_("Autoconfigure failed.\n")); 294 else 295 break; 296 } 297 } 298 } 299 if (!p || floppy) { 300 if (!ioctl(fd, HDIO_GETGEO, &geometry)) { 301 heads = geometry.heads; 302 sectors = geometry.sectors; 303 cylinders = geometry.cylinders; 304 } else { 305 heads = 0; 306 sectors = 0; 307 cylinders = 0; 308 } 309 if (floppy) { 310 sunlabel->nacyl = 0; 311 sunlabel->pcylcount = SSWAP16(cylinders); 312 sunlabel->rspeed = SSWAP16(300); 313 sunlabel->ilfact = SSWAP16(1); 314 sunlabel->sparecyl = 0; 315 } else { 316 heads = read_int(1,heads,1024,0,_("Heads")); 317 sectors = read_int(1,sectors,1024,0,_("Sectors/track")); 318 if (cylinders) 319 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders")); 320 else 321 cylinders = read_int(1,0,65535,0,_("Cylinders")); 322 sunlabel->nacyl = 323 SSWAP16(read_int(0,2,65535,0, 324 _("Alternate cylinders"))); 325 sunlabel->pcylcount = 326 SSWAP16(read_int(0,cylinders+SSWAP16(sunlabel->nacyl), 327 65535,0,_("Physical cylinders"))); 328 sunlabel->rspeed = 329 SSWAP16(read_int(1,5400,100000,0, 330 _("Rotation speed (rpm)"))); 331 sunlabel->ilfact = 332 SSWAP16(read_int(1,1,32,0,_("Interleave factor"))); 333 sunlabel->sparecyl = 334 SSWAP16(read_int(0,0,sectors,0, 335 _("Extra sectors per cylinder"))); 336 } 337 } else { 338 sunlabel->sparecyl = SSWAP16(p->sparecyl); 339 sunlabel->ncyl = SSWAP16(p->ncyl); 340 sunlabel->nacyl = SSWAP16(p->nacyl); 341 sunlabel->pcylcount = SSWAP16(p->pcylcount); 342 sunlabel->ntrks = SSWAP16(p->ntrks); 343 sunlabel->nsect = SSWAP16(p->nsect); 344 sunlabel->rspeed = SSWAP16(p->rspeed); 345 sunlabel->ilfact = SSWAP16(1); 346 cylinders = p->ncyl; 347 heads = p->ntrks; 348 sectors = p->nsect; 349 puts(_("You may change all the disk params from the x menu")); 350 } 351 352 snprintf(sunlabel->info, sizeof(sunlabel->info), 353 "%s%s%s cyl %d alt %d hd %d sec %d", 354 p ? p->vendor : "", (p && *p->vendor) ? " " : "", 355 p ? p->model 356 : (floppy ? _("3,5\" floppy") : _("Linux custom")), 357 cylinders, SSWAP16(sunlabel->nacyl), heads, sectors); 358 359 sunlabel->ntrks = SSWAP16(heads); 360 sunlabel->nsect = SSWAP16(sectors); 361 sunlabel->ncyl = SSWAP16(cylinders); 362 if (floppy) 363 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE); 364 else { 365 if (cylinders * heads * sectors >= 150 * 2048) { 366 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */ 367 } else 368 ndiv = cylinders * 2 / 3; 369 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE); 370 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP); 371 sunlabel->infos[1].flags |= 0x01; /* Not mountable */ 372 } 373 set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK); 374 { 375 unsigned short *ush = (unsigned short *)sunlabel; 376 unsigned short csum = 0; 377 while(ush < (unsigned short *)(&sunlabel->csum)) 378 csum ^= *ush++; 379 sunlabel->csum = csum; 380 } 381 382 set_all_unchanged(); 383 get_boot(create_empty_sun); 384 set_changed(0); 385} 386 387void 388toggle_sunflags(int i, unsigned char mask) { 389 if (sunlabel->infos[i].flags & mask) 390 sunlabel->infos[i].flags &= ~mask; 391 else sunlabel->infos[i].flags |= mask; 392 set_changed(i); 393} 394 395static void 396fetch_sun(unsigned int *starts, unsigned int *lens, unsigned int *start, unsigned int *stop) { 397 int i, continuous = 1; 398 *start = 0; *stop = cylinders * heads * sectors; 399 for (i = 0; i < partitions; i++) { 400 if (sunlabel->partitions[i].num_sectors 401 && sunlabel->infos[i].id 402 && sunlabel->infos[i].id != WHOLE_DISK) { 403 starts[i] = SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors; 404 lens[i] = SSWAP32(sunlabel->partitions[i].num_sectors); 405 if (continuous) { 406 if (starts[i] == *start) 407 *start += lens[i]; 408 else if (starts[i] + lens[i] >= *stop) 409 *stop = starts[i]; 410 else 411 continuous = 0; 412 /* There will be probably more gaps 413 than one, so lets check afterwards */ 414 } 415 } else { 416 starts[i] = 0; 417 lens[i] = 0; 418 } 419 } 420} 421 422static unsigned int *verify_sun_starts; 423 424static int 425verify_sun_cmp(int *a, int *b) { 426 if (*a == -1) return 1; 427 if (*b == -1) return -1; 428 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1; 429 return -1; 430} 431 432void 433verify_sun(void) { 434 unsigned int starts[8], lens[8], start, stop; 435 int i,j,k,starto,endo; 436 int array[8]; 437 438 verify_sun_starts = starts; 439 fetch_sun(starts,lens,&start,&stop); 440 for (k = 0; k < 7; k++) { 441 for (i = 0; i < 8; i++) { 442 if (k && (lens[i] % (heads * sectors))) { 443 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1); 444 } 445 if (lens[i]) { 446 for (j = 0; j < i; j++) 447 if (lens[j]) { 448 if (starts[j] == starts[i]+lens[i]) { 449 starts[j] = starts[i]; lens[j] += lens[i]; 450 lens[i] = 0; 451 } else if (starts[i] == starts[j]+lens[j]){ 452 lens[j] += lens[i]; 453 lens[i] = 0; 454 } else if (!k) { 455 if (starts[i] < starts[j]+lens[j] && 456 starts[j] < starts[i]+lens[i]) { 457 starto = starts[i]; 458 if (starts[j] > starto) 459 starto = starts[j]; 460 endo = starts[i]+lens[i]; 461 if (starts[j]+lens[j] < endo) 462 endo = starts[j]+lens[j]; 463 printf(_("Partition %d overlaps with others in " 464 "sectors %d-%d\n"), i+1, starto, endo); 465 } 466 } 467 } 468 } 469 } 470 } 471 for (i = 0; i < 8; i++) { 472 if (lens[i]) 473 array[i] = i; 474 else 475 array[i] = -1; 476 } 477 qsort(array,SIZE(array),sizeof(array[0]), 478 (int (*)(const void *,const void *)) verify_sun_cmp); 479 if (array[0] == -1) { 480 printf(_("No partitions defined\n")); 481 return; 482 } 483 stop = cylinders * heads * sectors; 484 if (starts[array[0]]) 485 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]); 486 for (i = 0; i < 7 && array[i+1] != -1; i++) { 487 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]); 488 } 489 start = starts[array[i]]+lens[array[i]]; 490 if (start < stop) 491 printf(_("Unused gap - sectors %d-%d\n"),start,stop); 492} 493 494void 495add_sun_partition(int n, int sys) { 496 unsigned int start, stop, stop2; 497 unsigned int starts[8], lens[8]; 498 int whole_disk = 0; 499 500 char mesg[256]; 501 int i, first, last; 502 503 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) { 504 printf(_("Partition %d is already defined. Delete " 505 "it before re-adding it.\n"), n + 1); 506 return; 507 } 508 509 fetch_sun(starts,lens,&start,&stop); 510 if (stop <= start) { 511 if (n == 2) 512 whole_disk = 1; 513 else { 514 printf(_("Other partitions already cover the whole disk.\nDelete " 515 "some/shrink them before retry.\n")); 516 return; 517 } 518 } 519 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR)); 520 for (;;) { 521 if (whole_disk) 522 first = read_int(0, 0, 0, 0, mesg); 523 else 524 first = read_int(scround(start), scround(stop)+1, 525 scround(stop), 0, mesg); 526 if (display_in_cyl_units) 527 first *= units_per_sector; 528 else { 529 /* Starting sector has to be properly aligned */ 530 int cs = heads * sectors; 531 int x = first % cs; 532 533 if (x) 534 first += cs - x; 535 } 536 if (n == 2 && first != 0) 537 printf ("\ 538It is highly recommended that the third partition covers the whole disk\n\ 539and is of type `Whole disk'\n"); 540 /* ewt asks to add: "don't start a partition at cyl 0" 541 However, edmundo@rano.demon.co.uk writes: 542 "In addition to having a Sun partition table, to be able to 543 boot from the disc, the first partition, /dev/sdX1, must 544 start at cylinder 0. This means that /dev/sdX1 contains 545 the partition table and the boot block, as these are the 546 first two sectors of the disc. Therefore you must be 547 careful what you use /dev/sdX1 for. In particular, you must 548 not use a partition starting at cylinder 0 for Linux swap, 549 as that would overwrite the partition table and the boot 550 block. You may, however, use such a partition for a UFS 551 or EXT2 file system, as these file systems leave the first 552 1024 bytes undisturbed. */ 553 /* On the other hand, one should not use partitions 554 starting at block 0 in an md, or the label will 555 be trashed. */ 556 for (i = 0; i < partitions; i++) 557 if (lens[i] && starts[i] <= first 558 && starts[i] + lens[i] > first) 559 break; 560 if (i < partitions && !whole_disk) { 561 if (n == 2 && !first) { 562 whole_disk = 1; 563 break; 564 } 565 printf(_("Sector %d is already allocated\n"), first); 566 } else 567 break; 568 } 569 stop = cylinders * heads * sectors; /* ancient */ 570 stop2 = stop; 571 for (i = 0; i < partitions; i++) { 572 if (starts[i] > first && starts[i] < stop) 573 stop = starts[i]; 574 } 575 snprintf(mesg, sizeof(mesg), 576 _("Last %s or +size or +sizeM or +sizeK"), 577 str_units(SINGULAR)); 578 if (whole_disk) 579 last = read_int(scround(stop2), scround(stop2), scround(stop2), 580 0, mesg); 581 else if (n == 2 && !first) 582 last = read_int(scround(first), scround(stop2), scround(stop2), 583 scround(first), mesg); 584 else 585 last = read_int(scround(first), scround(stop), scround(stop), 586 scround(first), mesg); 587 if (display_in_cyl_units) 588 last *= units_per_sector; 589 if (n == 2 && !first) { 590 if (last >= stop2) { 591 whole_disk = 1; 592 last = stop2; 593 } else if (last > stop) { 594 printf ( 595 _("You haven't covered the whole disk with the 3rd partition, but your value\n" 596 "%d %s covers some other partition. Your entry has been changed\n" 597 "to %d %s\n"), 598 scround(last), str_units(SINGULAR), 599 scround(stop), str_units(SINGULAR)); 600 last = stop; 601 } 602 } else if (!whole_disk && last > stop) 603 last = stop; 604 605 if (whole_disk) sys = WHOLE_DISK; 606 set_sun_partition(n, first, last, sys); 607} 608 609void 610sun_delete_partition(int i) { 611 unsigned int nsec; 612 613 if (i == 2 && sunlabel->infos[i].id == WHOLE_DISK && 614 !sunlabel->partitions[i].start_cylinder && 615 (nsec = SSWAP32(sunlabel->partitions[i].num_sectors)) 616 == heads * sectors * cylinders) 617 printf(_("If you want to maintain SunOS/Solaris compatibility, " 618 "consider leaving this\n" 619 "partition as Whole disk (5), starting at 0, with %u " 620 "sectors\n"), nsec); 621 sunlabel->infos[i].id = 0; 622 sunlabel->partitions[i].num_sectors = 0; 623} 624 625void 626sun_change_sysid(int i, int sys) { 627 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) { 628 read_chars( 629 _("It is highly recommended that the partition at offset 0\n" 630 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n" 631 "there may destroy your partition table and bootblock.\n" 632 "Type YES if you're very sure you would like that partition\n" 633 "tagged with 82 (Linux swap): ")); 634 if (strcmp (line_ptr, _("YES\n"))) 635 return; 636 } 637 switch (sys) { 638 case SUNOS_SWAP: 639 case LINUX_SWAP: 640 /* swaps are not mountable by default */ 641 sunlabel->infos[i].flags |= 0x01; 642 break; 643 default: 644 /* assume other types are mountable; 645 user can change it anyway */ 646 sunlabel->infos[i].flags &= ~0x01; 647 break; 648 } 649 sunlabel->infos[i].id = sys; 650} 651 652void 653sun_list_table(int xtra) { 654 int i, w; 655 char *type; 656 657 w = strlen(disk_device); 658 if (xtra) 659 printf( 660 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n" 661 "%d cylinders, %d alternate cylinders, %d physical cylinders\n" 662 "%d extra sects/cyl, interleave %d:1\n" 663 "%s\n" 664 "Units = %s of %d * 512 bytes\n\n"), 665 disk_device, heads, sectors, SSWAP16(sunlabel->rspeed), 666 cylinders, SSWAP16(sunlabel->nacyl), 667 SSWAP16(sunlabel->pcylcount), 668 SSWAP16(sunlabel->sparecyl), 669 SSWAP16(sunlabel->ilfact), 670 (char *)sunlabel, 671 str_units(PLURAL), units_per_sector); 672 else 673 printf( 674 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n" 675 "Units = %s of %d * 512 bytes\n\n"), 676 disk_device, heads, sectors, cylinders, 677 str_units(PLURAL), units_per_sector); 678 679 printf(_("%*s Flag Start End Blocks Id System\n"), 680 w + 1, _("Device")); 681 for (i = 0 ; i < partitions; i++) { 682 if (sunlabel->partitions[i].num_sectors) { 683 __u32 start = SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors; 684 __u32 len = SSWAP32(sunlabel->partitions[i].num_sectors); 685 printf( 686 "%s %c%c %9ld %9ld %9ld%c %2x %s\n", 687/* device */ partname(disk_device, i+1, w), 688/* flags */ (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ', 689 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ', 690/* start */ (long) scround(start), 691/* end */ (long) scround(start+len), 692/* odd flag on end */ (long) len / 2, len & 1 ? '+' : ' ', 693/* type id */ sunlabel->infos[i].id, 694/* type name */ (type = partition_type(sunlabel->infos[i].id)) 695 ? type : _("Unknown")); 696 } 697 } 698} 699 700void 701sun_set_alt_cyl(void) { 702 sunlabel->nacyl = 703 SSWAP16(read_int(0,SSWAP16(sunlabel->nacyl), 65535, 0, 704 _("Number of alternate cylinders"))); 705} 706 707void 708sun_set_ncyl(int cyl) { 709 sunlabel->ncyl = SSWAP16(cyl); 710} 711 712void 713sun_set_xcyl(void) { 714 sunlabel->sparecyl = 715 SSWAP16(read_int(0, SSWAP16(sunlabel->sparecyl), sectors, 0, 716 _("Extra sectors per cylinder"))); 717} 718 719void 720sun_set_ilfact(void) { 721 sunlabel->ilfact = 722 SSWAP16(read_int(1, SSWAP16(sunlabel->ilfact), 32, 0, 723 _("Interleave factor"))); 724} 725 726void 727sun_set_rspeed(void) { 728 sunlabel->rspeed = 729 SSWAP16(read_int(1, SSWAP16(sunlabel->rspeed), 100000, 0, 730 _("Rotation speed (rpm)"))); 731} 732 733void 734sun_set_pcylcount(void) { 735 sunlabel->pcylcount = 736 SSWAP16(read_int(0, SSWAP16(sunlabel->pcylcount), 65535, 0, 737 _("Number of physical cylinders"))); 738} 739 740void 741sun_write_table(void) { 742 unsigned short *ush = (unsigned short *)sunlabel; 743 unsigned short csum = 0; 744 745 while(ush < (unsigned short *)(&sunlabel->csum)) 746 csum ^= *ush++; 747 sunlabel->csum = csum; 748 if (lseek(fd, 0, SEEK_SET) < 0) 749 fatal(unable_to_seek); 750 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE) 751 fatal(unable_to_write); 752} 753