source: MondoRescue/branches/stable/mindi-busybox/util-linux/fdisk_sgi.c @ 1770

Last change on this file since 1770 was 1770, checked in by Bruno Cornec, 12 years ago
  • Better output for mindi-busybox revision
  • Remove dummy file created on NFS - report from Arnaud Tiger <arnaud.tiger_at_hp.com>
  • strace useful for debug
  • fix new versions for pb (2.0.0 for mindi and 1.7.2 for mindi-busybox)
  • fix build process for mindi-busybox + options used in that version (dd for label-partitions-as-necessary)
  • fix typo in label-partitions-as-necessary which doesn't seem to work
  • Update to busybox 1.7.2
  • perl is now required at restore time to support uuid swap partitions (and will be used for many other thigs

in the future for sure)

  • next mindi version will be 2.0.0 due to all the changes made in it (udev may break working distros)
  • small optimization in mindi on keyboard handling (one single find instead of multiple)
  • better interaction for USB device when launching mindi manually
  • attempt to automatically guess block disk size for ramdisk
  • fix typos in bkphw
  • Fix the remaining problem with UUID support for swap partitions
  • Updates mondoarchive man page for USB support
  • Adds preliminary Hardware support to mindi (Proliant SSSTK)
  • Tries to add udev support also for rhel4
  • Fix UUID support which was still broken.
  • Be conservative in test for the start-nfs script
  • Update config file for mindi-busybox for 1.7.2 migration
  • Try to run around a busybox bug (1.2.2 pb on inexistant links)
  • Add build content for mindi-busybox in pb
  • Remove distributions content for mindi-busybox
  • Fix a warning on inexistant raidtab
  • Solve problem on tmpfs in restore init (Problem of inexistant symlink and busybox)
  • Create MONDO_CACHE and use it everywhere + creation at start
  • Really never try to eject a USB device
  • Fix a issue with &> usage (replaced with 1> and 2>)
  • Adds magic file to depllist in order to have file working + ldd which helps for debugging issues
  • tty modes correct to avoid sh error messages
  • Use ext3 normally and not ext2 instead
  • USB device should be corrected after reading (take 1st part)
  • Adds a mount_USB_here function derived from mount_CDROM_here
  • usb detection place before /dev detection in device name at restore time
  • Fix when restoring from USB: media is asked in interactive mode
  • Adds USB support for mondorestore
  • mount_cdrom => mount_media
  • elilo.efi is now searched throughout /boot/efi and not in a fixed place as there is no standard
  • untar-and-softlink => untar (+ interface change)
  • suppress useless softlinks creation/removal in boot process
  • avoids udevd messages on groups
  • Increase # of disks to 99 as in mindi at restore time (should be a conf file parameter)
  • skip existing big file creation
  • seems to work correctly for USB mindi boot
  • Adds group and tty link to udev conf
  • Always load usb-torage (even 2.6) to initiate USB bus discovery
  • Better printing of messages
  • Attempt to fix a bug in supporting OpenSusE 10.3 kernel for initramfs (mindi may now use multiple regex for kernel initrd detection)
  • Links were not correctly done as non relative for modules in mindi
  • exclusion of modules denied now works
  • Also create modules in their ordinary place, so that classical modprobe works + copy modules.dep
  • Fix bugs for DENY_MODS handling
  • Add device /dev/console for udev
  • ide-generic should now really be excluded
  • Fix a bug in major number for tty
  • If udev then adds modprobe/insmod to rootfs
  • tty0 is also cretaed with udev
  • ide-generic put rather in DENY_MODS
  • udevd remove from deplist s handled in mindi directly
  • better default for mindi when using --usb
  • Handles dynamically linked busybox (in case we want to use it soon ;-)
  • Adds fixed devices to create for udev
  • ide-generic should not be part of the initrd when using libata v2
  • support a dynamically linked udev (case on Ubuntu 7.10 and Mandriva 2008.0 so should be quite generic) This will give incitation to move to dyn. linked binaries in the initrd which will help for other tasks (ia6 4)
  • Improvement in udev support (do not use cl options not available in busybox)
  • Udev in mindi
    • auto creation of the right links at boot time with udev-links.conf(from Mandriva 2008.0)
    • rework startup of udev as current makes kernel crash (from Mandriva 2008.0)
    • add support for 64 bits udev
  • Try to render MyInsmod? silent at boot time
  • Adds udev support (mandatory for newest distributions to avoid remapping of devices in a different way as on the original system)
  • We also need vaft format support for USB boot
  • Adds libusual support (Ubuntu 7.10 needs it for USB)
  • Improve Ubuntu/Debian? keyboard detection and support
  • pbinit adapted to new pb (0.8.10). Filtering of docs done in it
  • Suppress some mondo warnings and errors on USB again
  • Tries to fix lack of files in deb mindi package
  • Verify should now work for USB devices
  • More log/mesages improvement for USB support
  • - Supress g_erase_tmpdir_and_scratchdir
  • Improve some log messages for USB support
  • Try to improve install in mindi to avoid issues with isolinux.cfg not installed vene if in the pkg :-(
  • Improve mindi-busybox build
  • In conformity with pb 0.8.9
  • Add support for Ubuntu 7.10 in build process
  • Add USB Key button to Menu UI (CD streamer removed)
  • Attempt to fix error messages on tmp/scratch files at the end by removing those dir at the latest possible.
  • Fix a bug linked to the size of the -E param which could be used (Arnaud Tiger/René? Ribaud).
  • Integrate ~/.pbrc content into mondorescue.pb (required project-builder >= 0.8.7)
  • Put mondorescue in conformity with new pb filtering rules
  • Add USB support at restore time (no test done yet). New start-usb script PB varibale added where useful
  • Unmounting USB device before removal of temporary scratchdir
  • Stil refining USB copy back to mondo (one command was not executed)
  • No need to have the image subdor in the csratchdir when USB.
  • umount the USB partition before attempting to use it
  • Remove useless copy from mindi to mondo at end of USB handling

(risky merge, we are raising the limits of 2 diverging branches. The status of stable is not completely sure as such. Will need lots of tests, but it's not yet done :-()
(merge -r1692:1769 $SVN_M/branches/2.2.5)

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