Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/util-linux/fdisk_sgi.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (hide annotations) (download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 9 months ago) by niro
File MIME type: text/plain
File size: 25349 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd

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