busybox/util-linux/fdisk_sgi.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) Andreas Neuper, Sep 1998.
   3 *
   4 * Licensed under GPLv2, see file LICENSE in this source tree.
   5 */
   6
   7#if ENABLE_FEATURE_SGI_LABEL
   8
   9#define SGI_DEBUG 0
  10
  11#define SGI_VOLHDR      0x00
  12/* 1 and 2 were used for drive types no longer supported by SGI */
  13#define SGI_SWAP        0x03
  14/* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
  15#define SGI_VOLUME      0x06
  16#define SGI_EFS         0x07
  17#define SGI_LVOL        0x08
  18#define SGI_RLVOL       0x09
  19#define SGI_XFS         0x0a
  20#define SGI_XFSLOG      0x0b
  21#define SGI_XLV         0x0c
  22#define SGI_XVM         0x0d
  23#define SGI_ENTIRE_DISK SGI_VOLUME
  24
  25struct device_parameter { /* 48 bytes */
  26        unsigned char  skew;
  27        unsigned char  gap1;
  28        unsigned char  gap2;
  29        unsigned char  sparecyl;
  30        unsigned short pcylcount;
  31        unsigned short head_vol0;
  32        unsigned short ntrks;   /* tracks in cyl 0 or vol 0 */
  33        unsigned char  cmd_tag_queue_depth;
  34        unsigned char  unused0;
  35        unsigned short unused1;
  36        unsigned short nsect;   /* sectors/tracks in cyl 0 or vol 0 */
  37        unsigned short bytes;
  38        unsigned short ilfact;
  39        unsigned int   flags;   /* controller flags */
  40        unsigned int   datarate;
  41        unsigned int   retries_on_error;
  42        unsigned int   ms_per_word;
  43        unsigned short xylogics_gap1;
  44        unsigned short xylogics_syncdelay;
  45        unsigned short xylogics_readdelay;
  46        unsigned short xylogics_gap2;
  47        unsigned short xylogics_readgate;
  48        unsigned short xylogics_writecont;
  49};
  50
  51/*
  52 * controller flags
  53 */
  54#define SECTOR_SLIP     0x01
  55#define SECTOR_FWD      0x02
  56#define TRACK_FWD       0x04
  57#define TRACK_MULTIVOL  0x08
  58#define IGNORE_ERRORS   0x10
  59#define RESEEK          0x20
  60#define ENABLE_CMDTAGQ  0x40
  61
  62typedef struct {
  63        unsigned int   magic;            /* expect SGI_LABEL_MAGIC */
  64        unsigned short boot_part;        /* active boot partition */
  65        unsigned short swap_part;        /* active swap partition */
  66        unsigned char  boot_file[16];    /* name of the bootfile */
  67        struct device_parameter devparam;       /*  1 * 48 bytes */
  68        struct volume_directory {               /* 15 * 16 bytes */
  69                unsigned char vol_file_name[8]; /* a character array */
  70                unsigned int  vol_file_start;   /* number of logical block */
  71                unsigned int  vol_file_size;    /* number of bytes */
  72        } directory[15];
  73        struct sgi_partinfo {                   /* 16 * 12 bytes */
  74                unsigned int num_sectors;       /* number of blocks */
  75                unsigned int start_sector;      /* must be cylinder aligned */
  76                unsigned int id;
  77        } partitions[16];
  78        unsigned int   csum;
  79        unsigned int   fillbytes;
  80} sgi_partition;
  81
  82typedef struct {
  83        unsigned int   magic;           /* looks like a magic number */
  84        unsigned int   a2;
  85        unsigned int   a3;
  86        unsigned int   a4;
  87        unsigned int   b1;
  88        unsigned short b2;
  89        unsigned short b3;
  90        unsigned int   c[16];
  91        unsigned short d[3];
  92        unsigned char  scsi_string[50];
  93        unsigned char  serial[137];
  94        unsigned short check1816;
  95        unsigned char  installer[225];
  96} sgiinfo;
  97
  98#define SGI_LABEL_MAGIC         0x0be5a941
  99#define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b
 100#define SGI_INFO_MAGIC          0x00072959
 101#define SGI_INFO_MAGIC_SWAPPED  0x59290700
 102
 103#define SGI_SSWAP16(x) (sgi_other_endian ? fdisk_swap16(x) : (uint16_t)(x))
 104#define SGI_SSWAP32(x) (sgi_other_endian ? fdisk_swap32(x) : (uint32_t)(x))
 105
 106#define sgilabel ((sgi_partition *)MBRbuffer)
 107#define sgiparam (sgilabel->devparam)
 108
 109/*
 110 *
 111 * fdisksgilabel.c
 112 *
 113 * Copyright (C) Andreas Neuper, Sep 1998.
 114 *      This file may be modified and redistributed under
 115 *      the terms of the GNU Public License.
 116 *
 117 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
 118 *      Internationalization
 119 */
 120
 121
 122static smallint sgi_other_endian; /* bool */
 123static smallint sgi_volumes = 1; /* max 15 */
 124
 125/*
 126 * only dealing with free blocks here
 127 */
 128
 129typedef struct {
 130        unsigned int first;
 131        unsigned int last;
 132} freeblocks;
 133static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
 134
 135static void
 136setfreelist(int i, unsigned int f, unsigned int l)
 137{
 138        freelist[i].first = f;
 139        freelist[i].last = l;
 140}
 141
 142static void
 143add2freelist(unsigned int f, unsigned int l)
 144{
 145        int i;
 146        for (i = 0; i < 17; i++)
 147                if (freelist[i].last == 0)
 148                        break;
 149        setfreelist(i, f, l);
 150}
 151
 152static void
 153clearfreelist(void)
 154{
 155        int i;
 156
 157        for (i = 0; i < 17; i++)
 158                setfreelist(i, 0, 0);
 159}
 160
 161static unsigned int
 162isinfreelist(unsigned int b)
 163{
 164        int i;
 165
 166        for (i = 0; i < 17; i++)
 167                if (freelist[i].first <= b && freelist[i].last >= b)
 168                        return freelist[i].last;
 169        return 0;
 170}
 171        /* return last vacant block of this stride (never 0). */
 172        /* the '>=' is not quite correct, but simplifies the code */
 173/*
 174 * end of free blocks section
 175 */
 176
 177static const char *const sgi_sys_types[] ALIGN_PTR = {
 178/* SGI_VOLHDR   */      "\x00" "SGI volhdr"  ,
 179/* 0x01         */      "\x01" "SGI trkrepl" ,
 180/* 0x02         */      "\x02" "SGI secrepl" ,
 181/* SGI_SWAP     */      "\x03" "SGI raw"     ,
 182/* 0x04         */      "\x04" "SGI bsd"     ,
 183/* 0x05         */      "\x05" "SGI sysv"    ,
 184/* SGI_ENTIRE_DISK  */  "\x06" "SGI volume"  ,
 185/* SGI_EFS      */      "\x07" "SGI efs"     ,
 186/* 0x08         */      "\x08" "SGI lvol"    ,
 187/* 0x09         */      "\x09" "SGI rlvol"   ,
 188/* SGI_XFS      */      "\x0a" "SGI xfs"     ,
 189/* SGI_XFSLOG   */      "\x0b" "SGI xfslog"  ,
 190/* SGI_XLV      */      "\x0c" "SGI xlv"     ,
 191/* SGI_XVM      */      "\x0d" "SGI xvm"     ,
 192/* LINUX_SWAP   */      "\x82" "Linux swap"  ,
 193/* LINUX_NATIVE */      "\x83" "Linux native",
 194/* LINUX_LVM    */      "\x8d" "Linux LVM"   ,
 195/* LINUX_RAID   */      "\xfd" "Linux RAID"  ,
 196                        NULL
 197};
 198
 199
 200static int
 201sgi_get_nsect(void)
 202{
 203        return SGI_SSWAP16(sgilabel->devparam.nsect);
 204}
 205
 206static int
 207sgi_get_ntrks(void)
 208{
 209        return SGI_SSWAP16(sgilabel->devparam.ntrks);
 210}
 211
 212static unsigned int
 213two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */)
 214{
 215        int i = 0;
 216        unsigned int sum = 0;
 217
 218        size /= sizeof(unsigned int);
 219        for (i = 0; i < size; i++)
 220                sum -= SGI_SSWAP32(base[i]);
 221        return sum;
 222}
 223
 224void BUG_bad_sgi_partition_size(void);
 225
 226static int
 227check_sgi_label(void)
 228{
 229        if (sizeof(sgi_partition) > 512) {
 230                /* According to MIPS Computer Systems, Inc the label
 231                 * must not contain more than 512 bytes */
 232                BUG_bad_sgi_partition_size();
 233        }
 234
 235        if (sgilabel->magic != SGI_LABEL_MAGIC
 236         && sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED
 237        ) {
 238                current_label_type = LABEL_DOS;
 239                return 0;
 240        }
 241
 242        sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
 243        /*
 244         * test for correct checksum
 245         */
 246        if (two_s_complement_32bit_sum((unsigned int*)sgilabel,
 247                                sizeof(*sgilabel))) {
 248                printf("Detected sgi disklabel with wrong checksum\n");
 249        }
 250        update_units();
 251        current_label_type = LABEL_SGI;
 252        g_partitions = 16;
 253        sgi_volumes = 15;
 254        return 1;
 255}
 256
 257static unsigned int
 258sgi_get_start_sector(int i)
 259{
 260        return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
 261}
 262
 263static unsigned int
 264sgi_get_num_sectors(int i)
 265{
 266        return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
 267}
 268
 269static int
 270sgi_get_sysid(int i)
 271{
 272        return SGI_SSWAP32(sgilabel->partitions[i].id);
 273}
 274
 275static int
 276sgi_get_bootpartition(void)
 277{
 278        return SGI_SSWAP16(sgilabel->boot_part);
 279}
 280
 281static int
 282sgi_get_swappartition(void)
 283{
 284        return SGI_SSWAP16(sgilabel->swap_part);
 285}
 286
 287static void
 288sgi_list_table(int xtra)
 289{
 290        int i, w, wd;
 291        int kpi = 0;                /* kernel partition ID */
 292
 293        if (xtra) {
 294                printf("\nDisk %s (SGI disk label): %u heads, %u sectors\n"
 295                        "%u cylinders, %u physical cylinders\n"
 296                        "%u extra sects/cyl, interleave %u:1\n"
 297                        "%s\n"
 298                        "Units = %ss of %u * 512 bytes\n\n",
 299                        disk_device, g_heads, g_sectors, g_cylinders,
 300                        SGI_SSWAP16(sgiparam.pcylcount),
 301                        SGI_SSWAP16(sgiparam.sparecyl),
 302                        SGI_SSWAP16(sgiparam.ilfact),
 303                        (char *)sgilabel,
 304                        str_units(), units_per_sector);
 305        } else {
 306                printf("\nDisk %s (SGI disk label): "
 307                        "%u heads, %u sectors, %u cylinders\n"
 308                        "Units = %ss of %u * 512 bytes\n\n",
 309                        disk_device, g_heads, g_sectors, g_cylinders,
 310                        str_units(), units_per_sector );
 311        }
 312
 313        w = strlen(disk_device);
 314        wd = sizeof("Device") - 1;
 315        if (w < wd)
 316        w = wd;
 317
 318        printf("----- partitions -----\n"
 319                "Pt# %*s  Info     Start       End   Sectors  Id  System\n",
 320                w + 2, "Device");
 321        for (i = 0; i < g_partitions; i++) {
 322                if (sgi_get_num_sectors(i) || SGI_DEBUG) {
 323                        uint32_t start = sgi_get_start_sector(i);
 324                        uint32_t len = sgi_get_num_sectors(i);
 325                        kpi++;              /* only count nonempty partitions */
 326                        printf(
 327                        "%2u: %s %4s %9lu %9lu %9lu  %2x  %s\n",
 328/* fdisk part number */ i+1,
 329/* device */            partname(disk_device, kpi, w+3),
 330/* flags */             (sgi_get_swappartition() == i) ? "swap" :
 331/* flags */             (sgi_get_bootpartition() == i) ? "boot" : "    ",
 332/* start */             (long) scround(start),
 333/* end */               (long) scround(start+len)-1,
 334/* no odd flag on end */(long) len,
 335/* type id */           sgi_get_sysid(i),
 336/* type name */         partition_type(sgi_get_sysid(i)));
 337                }
 338        }
 339        printf("----- Bootinfo -----\nBootfile: %s\n"
 340                "----- Directory Entries -----\n",
 341                sgilabel->boot_file);
 342        for (i = 0; i < sgi_volumes; i++) {
 343                if (sgilabel->directory[i].vol_file_size) {
 344                        uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
 345                        uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
 346                        unsigned char *name = sgilabel->directory[i].vol_file_name;
 347
 348                        printf("%2u: %-10s sector%5u size%8u\n",
 349                                i, (char*)name, (unsigned int) start, (unsigned int) len);
 350                }
 351        }
 352}
 353
 354static void
 355sgi_set_bootpartition(int i)
 356{
 357        sgilabel->boot_part = SGI_SSWAP16(((short)i));
 358}
 359
 360static unsigned int
 361sgi_get_lastblock(void)
 362{
 363        return g_heads * g_sectors * g_cylinders;
 364}
 365
 366static void
 367sgi_set_swappartition(int i)
 368{
 369        sgilabel->swap_part = SGI_SSWAP16(((short)i));
 370}
 371
 372static int
 373sgi_check_bootfile(const char* aFile)
 374{
 375        if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
 376                printf("\nInvalid Bootfile!\n"
 377                        "\tThe bootfile must be an absolute non-zero pathname,\n"
 378                        "\te.g. \"/unix\" or \"/unix.save\".\n");
 379                return 0;
 380        }
 381        if (strlen(aFile) > 16) {
 382                printf("\nName of Bootfile too long (>16 bytes)\n");
 383                return 0;
 384        }
 385        if (aFile[0] != '/') {
 386                printf("\nBootfile must have a fully qualified pathname\n");
 387                return 0;
 388        }
 389        if (strncmp(aFile, (char*)sgilabel->boot_file, 16)) {
 390                printf("\nBe aware, that the bootfile is not checked for existence.\n"
 391                         "\tSGI's default is \"/unix\" and for backup \"/unix.save\".\n");
 392                /* filename is correct and did change */
 393                return 1;
 394        }
 395        return 0;   /* filename did not change */
 396}
 397
 398static const char *
 399sgi_get_bootfile(void)
 400{
 401        return (char*)sgilabel->boot_file;
 402}
 403
 404static void
 405sgi_set_bootfile(const char* aFile)
 406{
 407        int i = 0;
 408
 409        if (sgi_check_bootfile(aFile)) {
 410                while (i < 16) {
 411                        if ((aFile[i] != '\n')  /* in principle caught again by next line */
 412                         && (strlen(aFile) > i))
 413                                sgilabel->boot_file[i] = aFile[i];
 414                        else
 415                                sgilabel->boot_file[i] = 0;
 416                        i++;
 417                }
 418                printf("\n\tBootfile is changed to \"%s\"\n", sgilabel->boot_file);
 419        }
 420}
 421
 422static void
 423create_sgiinfo(void)
 424{
 425        /* I keep SGI's habit to write the sgilabel to the second block */
 426        sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2);
 427        sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo));
 428        memcpy((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8);
 429}
 430
 431static sgiinfo *fill_sgiinfo(void);
 432
 433static void
 434sgi_write_table(void)
 435{
 436        sgilabel->csum = 0;
 437        sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum(
 438                        (unsigned int*)sgilabel, sizeof(*sgilabel)));
 439        assert(two_s_complement_32bit_sum(
 440                (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
 441
 442        write_sector(0, sgilabel);
 443        if (is_prefixed_with((char*)sgilabel->directory[0].vol_file_name, "sgilabel")) {
 444                /*
 445                 * keep this habit of first writing the "sgilabel".
 446                 * I never tested whether it works without (AN 981002).
 447                 */
 448                sgiinfo *info = fill_sgiinfo();
 449                int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
 450                write_sector(infostartblock, info);
 451                free(info);
 452        }
 453}
 454
 455static int
 456compare_start(int *x, int *y)
 457{
 458        /*
 459         * sort according to start sectors
 460         * and prefers largest partition:
 461         * entry zero is entire disk entry
 462         */
 463        unsigned int i = *x;
 464        unsigned int j = *y;
 465        unsigned int a = sgi_get_start_sector(i);
 466        unsigned int b = sgi_get_start_sector(j);
 467        unsigned int c = sgi_get_num_sectors(i);
 468        unsigned int d = sgi_get_num_sectors(j);
 469
 470        if (a == b)
 471                return (d > c) ? 1 : (d == c) ? 0 : -1;
 472        return (a > b) ? 1 : -1;
 473}
 474
 475
 476static int
 477verify_sgi(int verbose)
 478{
 479        int Index[16];      /* list of valid partitions */
 480        int sortcount = 0;  /* number of used partitions, i.e. non-zero lengths */
 481        int entire = 0, i = 0;
 482        unsigned int start = 0;
 483        long long gap = 0;      /* count unused blocks */
 484        unsigned int lastblock = sgi_get_lastblock();
 485
 486        clearfreelist();
 487        for (i = 0; i < 16; i++) {
 488                if (sgi_get_num_sectors(i) != 0) {
 489                        Index[sortcount++] = i;
 490                        if (sgi_get_sysid(i) == SGI_ENTIRE_DISK) {
 491                                if (entire++ == 1) {
 492                                        if (verbose)
 493                                                printf("More than one entire disk entry present\n");
 494                                }
 495                        }
 496                }
 497        }
 498        if (sortcount == 0) {
 499                if (verbose)
 500                        printf("No partitions defined\n");
 501                return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
 502        }
 503        qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
 504        if (sgi_get_sysid(Index[0]) == SGI_ENTIRE_DISK) {
 505                if ((Index[0] != 10) && verbose)
 506                        printf("IRIX likes when Partition 11 covers the entire disk\n");
 507                if ((sgi_get_start_sector(Index[0]) != 0) && verbose) {
 508                        printf("The entire disk partition should start "
 509                                "at block 0,\n"
 510                                "not at diskblock %u\n",
 511                                sgi_get_start_sector(Index[0]));
 512                }
 513                if (SGI_DEBUG) {     /* I do not understand how some disks fulfil it */
 514                        if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
 515                                printf("The entire disk partition is only %u diskblock large,\n"
 516                                        "but the disk is %u diskblocks long\n",
 517                                        sgi_get_num_sectors(Index[0]), lastblock);
 518                        lastblock = sgi_get_num_sectors(Index[0]);
 519                }
 520        } else {
 521                if (verbose)
 522                        printf("One Partition (#11) should cover the entire disk\n");
 523                if (SGI_DEBUG > 2)
 524                        printf("sysid=%u\tpartition=%u\n",
 525                                sgi_get_sysid(Index[0]), Index[0]+1);
 526        }
 527        for (i = 1, start = 0; i < sortcount; i++) {
 528                int cylsize = sgi_get_nsect() * sgi_get_ntrks();
 529
 530                if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
 531                        if (SGI_DEBUG)      /* I do not understand how some disks fulfil it */
 532                                if (verbose)
 533                                        printf("Partition %u does not start on cylinder boundary\n",
 534                                                Index[i]+1);
 535                }
 536                if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
 537                        if (SGI_DEBUG)      /* I do not understand how some disks fulfil it */
 538                                if (verbose)
 539                                        printf("Partition %u does not end on cylinder boundary\n",
 540                                                Index[i]+1);
 541                }
 542                /* We cannot handle several "entire disk" entries. */
 543                if (sgi_get_sysid(Index[i]) == SGI_ENTIRE_DISK) continue;
 544                if (start > sgi_get_start_sector(Index[i])) {
 545                        if (verbose)
 546                                printf("Partitions %u and %u overlap by %u sectors\n",
 547                                        Index[i-1]+1, Index[i]+1,
 548                                        start - sgi_get_start_sector(Index[i]));
 549                        if (gap > 0) gap = -gap;
 550                        if (gap == 0) gap = -1;
 551                }
 552                if (start < sgi_get_start_sector(Index[i])) {
 553                        if (verbose)
 554                                printf("Unused gap of %u sectors - sectors %u-%u\n",
 555                                        sgi_get_start_sector(Index[i]) - start,
 556                                        start, sgi_get_start_sector(Index[i])-1);
 557                        gap += sgi_get_start_sector(Index[i]) - start;
 558                        add2freelist(start, sgi_get_start_sector(Index[i]));
 559                }
 560                start = sgi_get_start_sector(Index[i])
 561                           + sgi_get_num_sectors(Index[i]);
 562                if (SGI_DEBUG > 1) {
 563                        if (verbose)
 564                                printf("%2u:%12u\t%12u\t%12u\n", Index[i],
 565                                        sgi_get_start_sector(Index[i]),
 566                                        sgi_get_num_sectors(Index[i]),
 567                                        sgi_get_sysid(Index[i]));
 568                }
 569        }
 570        if (start < lastblock) {
 571                if (verbose)
 572                        printf("Unused gap of %u sectors - sectors %u-%u\n",
 573                                lastblock - start, start, lastblock-1);
 574                gap += lastblock - start;
 575                add2freelist(start, lastblock);
 576        }
 577        /*
 578         * Done with arithmetics
 579         * Go for details now
 580         */
 581        if (verbose) {
 582                if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
 583                        printf("\nThe boot partition does not exist\n");
 584                }
 585                if (!sgi_get_num_sectors(sgi_get_swappartition())) {
 586                        printf("\nThe swap partition does not exist\n");
 587                } else {
 588                        if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
 589                         && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
 590                                printf("\nThe swap partition has no swap type\n");
 591                }
 592                if (sgi_check_bootfile("/unix"))
 593                        printf("\tYou have chosen an unusual boot file name\n");
 594        }
 595        return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
 596}
 597
 598static int
 599sgi_gaps(void)
 600{
 601        /*
 602         * returned value is:
 603         *  = 0 : disk is properly filled to the rim
 604         *  < 0 : there is an overlap
 605         *  > 0 : there is still some vacant space
 606         */
 607        return verify_sgi(0);
 608}
 609
 610static void
 611sgi_change_sysid(int i, int sys)
 612{
 613        if (sgi_get_num_sectors(i) == 0) { /* caught already before, ... */
 614                printf("Sorry you may change the Tag of non-empty partitions\n");
 615                return;
 616        }
 617        if ((sys != SGI_ENTIRE_DISK) && (sys != SGI_VOLHDR)
 618         && (sgi_get_start_sector(i) < 1)
 619        ) {
 620                read_maybe_empty(
 621                        "It is highly recommended that the partition at offset 0\n"
 622                        "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
 623                        "retrieve from its directory standalone tools like sash and fx.\n"
 624                        "Only the \"SGI volume\" entire disk section may violate this.\n"
 625                        "Type YES if you are sure about tagging this partition differently.\n");
 626                if (strcmp(line_ptr, "YES") != 0)
 627                        return;
 628        }
 629        sgilabel->partitions[i].id = SGI_SSWAP32(sys);
 630}
 631
 632/* returns partition index of first entry marked as entire disk */
 633static int
 634sgi_entire(void)
 635{
 636        int i;
 637
 638        for (i = 0; i < 16; i++)
 639                if (sgi_get_sysid(i) == SGI_VOLUME)
 640                        return i;
 641        return -1;
 642}
 643
 644static void
 645sgi_set_partition(int i, unsigned int start, unsigned int length, int sys)
 646{
 647        sgilabel->partitions[i].id = SGI_SSWAP32(sys);
 648        sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
 649        sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
 650        set_changed(i);
 651        if (sgi_gaps() < 0)     /* rebuild freelist */
 652                printf("Partition overlap detected\n");
 653}
 654
 655static void
 656sgi_set_entire(void)
 657{
 658        int n;
 659
 660        for (n = 10; n < g_partitions; n++) {
 661                if (!sgi_get_num_sectors(n) ) {
 662                        sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
 663                        break;
 664                }
 665        }
 666}
 667
 668static void
 669sgi_set_volhdr(void)
 670{
 671        int n;
 672
 673        for (n = 8; n < g_partitions; n++) {
 674                if (!sgi_get_num_sectors(n)) {
 675                        /*
 676                         * 5 cylinders is an arbitrary value I like
 677                         * IRIX 5.3 stored files in the volume header
 678                         * (like sash, symmon, fx, ide) with ca. 3200
 679                         * sectors.
 680                         */
 681                        if (g_heads * g_sectors * 5 < sgi_get_lastblock()) {
 682                                sgi_set_partition(n, 0, g_heads * g_sectors * 5, SGI_VOLHDR);
 683                                break;
 684                        }
 685                }
 686        }
 687}
 688
 689static void
 690sgi_delete_partition(int i)
 691{
 692        sgi_set_partition(i, 0, 0, 0);
 693}
 694
 695static void
 696sgi_add_partition(int n, int sys)
 697{
 698        char mesg[256];
 699        unsigned int first = 0, last = 0;
 700
 701        if (n == 10) {
 702                sys = SGI_VOLUME;
 703        } else if (n == 8) {
 704                sys = 0;
 705        }
 706        if (sgi_get_num_sectors(n)) {
 707                printf(msg_part_already_defined, n + 1);
 708                return;
 709        }
 710        if ((sgi_entire() == -1) && (sys != SGI_VOLUME)) {
 711                printf("Attempting to generate entire disk entry automatically\n");
 712                sgi_set_entire();
 713                sgi_set_volhdr();
 714        }
 715        if ((sgi_gaps() == 0) && (sys != SGI_VOLUME)) {
 716                printf("The entire disk is already covered with partitions\n");
 717                return;
 718        }
 719        if (sgi_gaps() < 0) {
 720                printf("You got a partition overlap on the disk. Fix it first!\n");
 721                return;
 722        }
 723        snprintf(mesg, sizeof(mesg), "First %s", str_units());
 724        while (1) {
 725                if (sys == SGI_VOLUME) {
 726                        last = sgi_get_lastblock();
 727                        first = read_int(0, 0, last-1, 0, mesg);
 728                        if (first != 0) {
 729                                printf("It is highly recommended that eleventh partition\n"
 730                                                "covers the entire disk and is of type 'SGI volume'\n");
 731                        }
 732                } else {
 733                        first = freelist[0].first;
 734                        last  = freelist[0].last;
 735                        first = read_int(scround(first), scround(first), scround(last)-1,
 736                                0, mesg);
 737                }
 738                if (display_in_cyl_units)
 739                        first *= units_per_sector;
 740                else
 741                        first = first; /* align to cylinder if you know how ... */
 742                if (!last )
 743                        last = isinfreelist(first);
 744                if (last != 0)
 745                        break;
 746                printf("You will get a partition overlap on the disk. "
 747                                "Fix it first!\n");
 748        }
 749        snprintf(mesg, sizeof(mesg), " Last %s", str_units());
 750        last = read_int(scround(first), scround(last)-1, scround(last)-1,
 751                        scround(first), mesg)+1;
 752        if (display_in_cyl_units)
 753                last *= units_per_sector;
 754        else
 755                last = last; /* align to cylinder if You know how ... */
 756        if ( (sys == SGI_VOLUME) && (first != 0 || last != sgi_get_lastblock() ) )
 757                printf("It is highly recommended that eleventh partition\n"
 758                        "covers the entire disk and is of type 'SGI volume'\n");
 759        sgi_set_partition(n, first, last-first, sys);
 760}
 761
 762#if ENABLE_FEATURE_FDISK_ADVANCED
 763static void
 764create_sgilabel(void)
 765{
 766        struct hd_geometry geometry;
 767        struct {
 768                unsigned int start;
 769                unsigned int nsect;
 770                int sysid;
 771        } old[4];
 772        int i = 0;
 773        long longsectors;               /* the number of sectors on the device */
 774        int res;                        /* the result from the ioctl */
 775        int sec_fac;                    /* the sector factor */
 776
 777        sec_fac = sector_size / 512;    /* determine the sector factor */
 778
 779        printf(msg_building_new_label, "SGI disklabel");
 780
 781        sgi_other_endian = BB_LITTLE_ENDIAN;
 782        res = ioctl(dev_fd, BLKGETSIZE, &longsectors);
 783        if (!ioctl(dev_fd, HDIO_GETGEO, &geometry)) {
 784                g_heads = geometry.heads;
 785                g_sectors = geometry.sectors;
 786                if (res == 0) {
 787                        /* the get device size ioctl was successful */
 788                        g_cylinders = longsectors / (g_heads * g_sectors);
 789                        g_cylinders /= sec_fac;
 790                } else {
 791                        /* otherwise print error and use truncated version */
 792                        g_cylinders = geometry.cylinders;
 793                        printf(
 794"Warning: BLKGETSIZE ioctl failed on %s.  Using geometry cylinder value of %u.\n"
 795"This value may be truncated for devices > 33.8 GB.\n", disk_device, g_cylinders);
 796                }
 797        }
 798        for (i = 0; i < 4; i++) {
 799                old[i].sysid = 0;
 800                if (valid_part_table_flag(MBRbuffer)) {
 801                        if (get_part_table(i)->sys_ind) {
 802                                old[i].sysid = get_part_table(i)->sys_ind;
 803                                old[i].start = get_start_sect(get_part_table(i));
 804                                old[i].nsect = get_nr_sects(get_part_table(i));
 805                                printf("Trying to keep parameters of partition %u\n", i);
 806                                if (SGI_DEBUG)
 807                                        printf("ID=%02x\tSTART=%u\tLENGTH=%u\n",
 808                                old[i].sysid, old[i].start, old[i].nsect);
 809                        }
 810                }
 811        }
 812
 813        memset(MBRbuffer, 0, sizeof(MBRbuffer));
 814        /* fields with '//' are already zeroed out by memset above */
 815
 816        sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
 817        //sgilabel->boot_part = SGI_SSWAP16(0);
 818        sgilabel->swap_part = SGI_SSWAP16(1);
 819
 820        //memset(sgilabel->boot_file, 0, 16);
 821        strcpy((char*)sgilabel->boot_file, "/unix"); /* sizeof(sgilabel->boot_file) == 16 > 6 */
 822
 823        //sgilabel->devparam.skew                     = (0);
 824        //sgilabel->devparam.gap1                     = (0);
 825        //sgilabel->devparam.gap2                     = (0);
 826        //sgilabel->devparam.sparecyl                 = (0);
 827        sgilabel->devparam.pcylcount                = SGI_SSWAP16(geometry.cylinders);
 828        //sgilabel->devparam.head_vol0                = SGI_SSWAP16(0);
 829        /* tracks/cylinder (heads) */
 830        sgilabel->devparam.ntrks                    = SGI_SSWAP16(geometry.heads);
 831        //sgilabel->devparam.cmd_tag_queue_depth      = (0);
 832        //sgilabel->devparam.unused0                  = (0);
 833        //sgilabel->devparam.unused1                  = SGI_SSWAP16(0);
 834        /* sectors/track */
 835        sgilabel->devparam.nsect                    = SGI_SSWAP16(geometry.sectors);
 836        sgilabel->devparam.bytes                    = SGI_SSWAP16(512);
 837        sgilabel->devparam.ilfact                   = SGI_SSWAP16(1);
 838        sgilabel->devparam.flags                    = SGI_SSWAP32(TRACK_FWD|
 839                                                        IGNORE_ERRORS|RESEEK);
 840        //sgilabel->devparam.datarate                 = SGI_SSWAP32(0);
 841        sgilabel->devparam.retries_on_error         = SGI_SSWAP32(1);
 842        //sgilabel->devparam.ms_per_word              = SGI_SSWAP32(0);
 843        //sgilabel->devparam.xylogics_gap1            = SGI_SSWAP16(0);
 844        //sgilabel->devparam.xylogics_syncdelay       = SGI_SSWAP16(0);
 845        //sgilabel->devparam.xylogics_readdelay       = SGI_SSWAP16(0);
 846        //sgilabel->devparam.xylogics_gap2            = SGI_SSWAP16(0);
 847        //sgilabel->devparam.xylogics_readgate        = SGI_SSWAP16(0);
 848        //sgilabel->devparam.xylogics_writecont       = SGI_SSWAP16(0);
 849        //memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
 850        //memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partinfo)*16 );
 851        current_label_type = LABEL_SGI;
 852        g_partitions = 16;
 853        sgi_volumes = 15;
 854        sgi_set_entire();
 855        sgi_set_volhdr();
 856        for (i = 0; i < 4; i++) {
 857                if (old[i].sysid) {
 858                        sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
 859                }
 860        }
 861}
 862
 863static void
 864sgi_set_xcyl(void)
 865{
 866        /* do nothing in the beginning */
 867}
 868#endif /* FEATURE_FDISK_ADVANCED */
 869
 870/* _____________________________________________________________
 871 */
 872
 873static sgiinfo *
 874fill_sgiinfo(void)
 875{
 876        sgiinfo *info = xzalloc(sizeof(sgiinfo));
 877
 878        info->magic = SGI_SSWAP32(SGI_INFO_MAGIC);
 879        info->b1 = SGI_SSWAP32(-1);
 880        info->b2 = SGI_SSWAP16(-1);
 881        info->b3 = SGI_SSWAP16(1);
 882        /* You may want to replace this string !!!!!!! */
 883        strcpy( (char*)info->scsi_string, "IBM OEM 0662S12         3 30" );
 884        strcpy( (char*)info->serial, "0000" );
 885        info->check1816 = SGI_SSWAP16(18*256 +16 );
 886        strcpy( (char*)info->installer, "Sfx version 5.3, Oct 18, 1994" );
 887        return info;
 888}
 889#endif /* SGI_LABEL */
 890