Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 984 - (hide annotations) (download)
Sun May 30 11:32:42 2010 UTC (14 years ago) by niro
File MIME type: text/plain
File size: 25079 byte(s)
-updated to busybox-1.16.1 and enabled blkid/uuid support in default config
1 niro 984 /*
2     * Copyright (C) Andreas Neuper, Sep 1998.
3     *
4     * Licensed under GPLv2, see file LICENSE in this tarball for details.
5     */
6    
7 niro 532 #if ENABLE_FEATURE_SGI_LABEL
8    
9 niro 816 #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    
25 niro 532 struct 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 niro 984 unsigned int flags; /* controller flags */
40 niro 532 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    
62     typedef 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 niro 984 struct sgi_partinfo { /* 16 * 12 bytes */
74 niro 532 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    
82     typedef 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    
122 niro 816 static smallint sgi_other_endian; /* bool */
123     static smallint sgi_volumes = 1; /* max 15 */
124 niro 532
125     /*
126     * only dealing with free blocks here
127     */
128    
129     typedef struct {
130     unsigned int first;
131     unsigned int last;
132     } freeblocks;
133     static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
134    
135     static void
136     setfreelist(int i, unsigned int f, unsigned int l)
137     {
138     freelist[i].first = f;
139     freelist[i].last = l;
140     }
141    
142     static void
143     add2freelist(unsigned int f, unsigned int l)
144     {
145     int i;
146 niro 816 for (i = 0; i < 17; i++)
147 niro 532 if (freelist[i].last == 0)
148     break;
149     setfreelist(i, f, l);
150     }
151    
152     static void
153     clearfreelist(void)
154     {
155     int i;
156    
157 niro 816 for (i = 0; i < 17; i++)
158 niro 532 setfreelist(i, 0, 0);
159     }
160    
161     static unsigned int
162     isinfreelist(unsigned int b)
163     {
164     int i;
165    
166 niro 816 for (i = 0; i < 17; i++)
167 niro 532 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    
177 niro 816 static const char *const sgi_sys_types[] = {
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 niro 532 };
198    
199    
200     static int
201     sgi_get_nsect(void)
202     {
203     return SGI_SSWAP16(sgilabel->devparam.nsect);
204     }
205    
206     static int
207     sgi_get_ntrks(void)
208     {
209     return SGI_SSWAP16(sgilabel->devparam.ntrks);
210     }
211    
212     static unsigned int
213     two_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    
224 niro 816 void BUG_bad_sgi_partition_size(void);
225    
226 niro 532 static int
227     check_sgi_label(void)
228     {
229 niro 816 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 niro 532 }
234    
235     if (sgilabel->magic != SGI_LABEL_MAGIC
236 niro 816 && sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED
237     ) {
238     current_label_type = LABEL_DOS;
239 niro 532 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 niro 816 printf("Detected sgi disklabel with wrong checksum\n");
249 niro 532 }
250     update_units();
251 niro 816 current_label_type = LABEL_SGI;
252     g_partitions = 16;
253 niro 532 sgi_volumes = 15;
254     return 1;
255     }
256    
257     static unsigned int
258     sgi_get_start_sector(int i)
259     {
260     return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
261     }
262    
263     static unsigned int
264     sgi_get_num_sectors(int i)
265     {
266     return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
267     }
268    
269     static int
270     sgi_get_sysid(int i)
271     {
272     return SGI_SSWAP32(sgilabel->partitions[i].id);
273     }
274    
275     static int
276     sgi_get_bootpartition(void)
277     {
278     return SGI_SSWAP16(sgilabel->boot_part);
279     }
280    
281     static int
282     sgi_get_swappartition(void)
283     {
284     return SGI_SSWAP16(sgilabel->swap_part);
285     }
286    
287     static void
288     sgi_list_table(int xtra)
289     {
290     int i, w, wd;
291     int kpi = 0; /* kernel partition ID */
292    
293 niro 816 if (xtra) {
294 niro 984 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 niro 532 "%s\n"
298 niro 984 "Units = %s of %u * 512 bytes\n\n",
299 niro 816 disk_device, g_heads, g_sectors, g_cylinders,
300 niro 532 SGI_SSWAP16(sgiparam.pcylcount),
301     SGI_SSWAP16(sgiparam.sparecyl),
302     SGI_SSWAP16(sgiparam.ilfact),
303     (char *)sgilabel,
304     str_units(PLURAL), units_per_sector);
305     } else {
306 niro 816 printf("\nDisk %s (SGI disk label): "
307 niro 984 "%u heads, %u sectors, %u cylinders\n"
308     "Units = %s of %u * 512 bytes\n\n",
309 niro 816 disk_device, g_heads, g_sectors, g_cylinders,
310 niro 532 str_units(PLURAL), units_per_sector );
311     }
312    
313     w = strlen(disk_device);
314 niro 816 wd = sizeof("Device") - 1;
315 niro 532 if (w < wd)
316     w = wd;
317    
318 niro 816 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 niro 532 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 niro 984 "%2u: %s %4s %9lu %9lu %9lu %2x %s\n",
328 niro 532 /* 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 niro 816 printf("----- Bootinfo -----\nBootfile: %s\n"
340     "----- Directory Entries -----\n",
341 niro 532 sgilabel->boot_file);
342 niro 816 for (i = 0; i < sgi_volumes; i++) {
343 niro 532 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 niro 984 printf("%2u: %-10s sector%5u size%8u\n",
349 niro 532 i, (char*)name, (unsigned int) start, (unsigned int) len);
350     }
351     }
352     }
353    
354     static void
355     sgi_set_bootpartition(int i)
356     {
357     sgilabel->boot_part = SGI_SSWAP16(((short)i));
358     }
359    
360     static unsigned int
361     sgi_get_lastblock(void)
362     {
363 niro 816 return g_heads * g_sectors * g_cylinders;
364 niro 532 }
365    
366     static void
367     sgi_set_swappartition(int i)
368     {
369     sgilabel->swap_part = SGI_SSWAP16(((short)i));
370     }
371    
372     static int
373     sgi_check_bootfile(const char* aFile)
374     {
375 niro 816 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 niro 532 return 0;
380 niro 816 }
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 niro 532 if (strncmp(aFile, (char*)sgilabel->boot_file, 16)) {
390 niro 816 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 niro 532 /* filename is correct and did change */
393     return 1;
394     }
395     return 0; /* filename did not change */
396     }
397    
398     static const char *
399     sgi_get_bootfile(void)
400     {
401     return (char*)sgilabel->boot_file;
402     }
403    
404     static void
405     sgi_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 niro 816 printf("\n\tBootfile is changed to \"%s\"\n", sgilabel->boot_file);
419 niro 532 }
420     }
421    
422     static void
423     create_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     strncpy((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8);
429     }
430    
431     static sgiinfo *fill_sgiinfo(void);
432    
433     static void
434     sgi_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 niro 816 write_sector(0, sgilabel);
443 niro 532 if (!strncmp((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
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 niro 816 write_sector(infostartblock, info);
451 niro 532 free(info);
452     }
453     }
454    
455     static int
456     compare_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    
476     static int
477     verify_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 niro 816 printf("More than one entire disk entry present\n");
494 niro 532 }
495     }
496     }
497     }
498     if (sortcount == 0) {
499     if (verbose)
500 niro 816 printf("No partitions defined\n");
501 niro 532 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 niro 816 printf("IRIX likes when Partition 11 covers the entire disk\n");
507 niro 532 if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
508 niro 816 printf("The entire disk partition should start "
509 niro 532 "at block 0,\n"
510 niro 984 "not at diskblock %u\n",
511 niro 816 sgi_get_start_sector(Index[0]));
512     if (SGI_DEBUG) /* I do not understand how some disks fulfil it */
513 niro 532 if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
514 niro 984 printf("The entire disk partition is only %u diskblock large,\n"
515     "but the disk is %u diskblocks long\n",
516 niro 816 sgi_get_num_sectors(Index[0]), lastblock);
517     lastblock = sgi_get_num_sectors(Index[0]);
518 niro 532 } else {
519     if (verbose)
520 niro 816 printf("One Partition (#11) should cover the entire disk\n");
521     if (SGI_DEBUG > 2)
522 niro 984 printf("sysid=%u\tpartition=%u\n",
523 niro 532 sgi_get_sysid(Index[0]), Index[0]+1);
524     }
525     for (i = 1, start = 0; i < sortcount; i++) {
526     int cylsize = sgi_get_nsect() * sgi_get_ntrks();
527    
528     if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
529 niro 816 if (SGI_DEBUG) /* I do not understand how some disks fulfil it */
530 niro 532 if (verbose)
531 niro 984 printf("Partition %u does not start on cylinder boundary\n",
532 niro 532 Index[i]+1);
533     }
534     if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
535 niro 816 if (SGI_DEBUG) /* I do not understand how some disks fulfil it */
536 niro 532 if (verbose)
537 niro 984 printf("Partition %u does not end on cylinder boundary\n",
538 niro 532 Index[i]+1);
539     }
540     /* We cannot handle several "entire disk" entries. */
541     if (sgi_get_sysid(Index[i]) == SGI_ENTIRE_DISK) continue;
542     if (start > sgi_get_start_sector(Index[i])) {
543     if (verbose)
544 niro 984 printf("Partitions %u and %u overlap by %u sectors\n",
545 niro 532 Index[i-1]+1, Index[i]+1,
546     start - sgi_get_start_sector(Index[i]));
547 niro 816 if (gap > 0) gap = -gap;
548 niro 532 if (gap == 0) gap = -1;
549     }
550     if (start < sgi_get_start_sector(Index[i])) {
551     if (verbose)
552 niro 984 printf("Unused gap of %u sectors - sectors %u-%u\n",
553 niro 532 sgi_get_start_sector(Index[i]) - start,
554     start, sgi_get_start_sector(Index[i])-1);
555     gap += sgi_get_start_sector(Index[i]) - start;
556     add2freelist(start, sgi_get_start_sector(Index[i]));
557     }
558     start = sgi_get_start_sector(Index[i])
559     + sgi_get_num_sectors(Index[i]);
560 niro 816 if (SGI_DEBUG > 1) {
561 niro 532 if (verbose)
562 niro 984 printf("%2u:%12u\t%12u\t%12u\n", Index[i],
563 niro 532 sgi_get_start_sector(Index[i]),
564     sgi_get_num_sectors(Index[i]),
565     sgi_get_sysid(Index[i]));
566     }
567     }
568     if (start < lastblock) {
569     if (verbose)
570 niro 984 printf("Unused gap of %u sectors - sectors %u-%u\n",
571 niro 532 lastblock - start, start, lastblock-1);
572     gap += lastblock - start;
573     add2freelist(start, lastblock);
574     }
575     /*
576     * Done with arithmetics
577     * Go for details now
578     */
579     if (verbose) {
580     if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
581 niro 816 printf("\nThe boot partition does not exist\n");
582 niro 532 }
583     if (!sgi_get_num_sectors(sgi_get_swappartition())) {
584 niro 816 printf("\nThe swap partition does not exist\n");
585 niro 532 } else {
586     if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
587     && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
588 niro 816 printf("\nThe swap partition has no swap type\n");
589 niro 532 }
590     if (sgi_check_bootfile("/unix"))
591 niro 816 printf("\tYou have chosen an unusual boot file name\n");
592 niro 532 }
593     return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
594     }
595    
596     static int
597     sgi_gaps(void)
598     {
599     /*
600     * returned value is:
601     * = 0 : disk is properly filled to the rim
602     * < 0 : there is an overlap
603     * > 0 : there is still some vacant space
604     */
605     return verify_sgi(0);
606     }
607    
608     static void
609     sgi_change_sysid(int i, int sys)
610     {
611 niro 816 if (sgi_get_num_sectors(i) == 0) { /* caught already before, ... */
612     printf("Sorry you may change the Tag of non-empty partitions\n");
613 niro 532 return;
614     }
615 niro 816 if ((sys != SGI_ENTIRE_DISK) && (sys != SGI_VOLHDR)
616     && (sgi_get_start_sector(i) < 1)
617     ) {
618 niro 532 read_maybe_empty(
619 niro 816 "It is highly recommended that the partition at offset 0\n"
620 niro 532 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
621     "retrieve from its directory standalone tools like sash and fx.\n"
622     "Only the \"SGI volume\" entire disk section may violate this.\n"
623 niro 816 "Type YES if you are sure about tagging this partition differently.\n");
624     if (strcmp(line_ptr, "YES\n") != 0)
625 niro 532 return;
626     }
627     sgilabel->partitions[i].id = SGI_SSWAP32(sys);
628     }
629    
630     /* returns partition index of first entry marked as entire disk */
631     static int
632     sgi_entire(void)
633     {
634     int i;
635    
636     for (i = 0; i < 16; i++)
637     if (sgi_get_sysid(i) == SGI_VOLUME)
638     return i;
639     return -1;
640     }
641    
642     static void
643     sgi_set_partition(int i, unsigned int start, unsigned int length, int sys)
644     {
645     sgilabel->partitions[i].id = SGI_SSWAP32(sys);
646     sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
647     sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
648     set_changed(i);
649     if (sgi_gaps() < 0) /* rebuild freelist */
650 niro 816 printf("Partition overlap detected\n");
651 niro 532 }
652    
653     static void
654     sgi_set_entire(void)
655     {
656     int n;
657    
658 niro 816 for (n = 10; n < g_partitions; n++) {
659     if (!sgi_get_num_sectors(n) ) {
660 niro 532 sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
661     break;
662     }
663     }
664     }
665    
666     static void
667     sgi_set_volhdr(void)
668     {
669     int n;
670    
671 niro 816 for (n = 8; n < g_partitions; n++) {
672 niro 532 if (!sgi_get_num_sectors(n)) {
673     /*
674     * 5 cylinders is an arbitrary value I like
675     * IRIX 5.3 stored files in the volume header
676     * (like sash, symmon, fx, ide) with ca. 3200
677     * sectors.
678     */
679 niro 816 if (g_heads * g_sectors * 5 < sgi_get_lastblock())
680     sgi_set_partition(n, 0, g_heads * g_sectors * 5, SGI_VOLHDR);
681 niro 532 break;
682     }
683     }
684     }
685    
686     static void
687     sgi_delete_partition(int i)
688     {
689     sgi_set_partition(i, 0, 0, 0);
690     }
691    
692     static void
693     sgi_add_partition(int n, int sys)
694     {
695     char mesg[256];
696     unsigned int first = 0, last = 0;
697    
698     if (n == 10) {
699     sys = SGI_VOLUME;
700     } else if (n == 8) {
701     sys = 0;
702     }
703 niro 816 if (sgi_get_num_sectors(n)) {
704     printf(msg_part_already_defined, n + 1);
705 niro 532 return;
706     }
707     if ((sgi_entire() == -1) && (sys != SGI_VOLUME)) {
708 niro 816 printf("Attempting to generate entire disk entry automatically\n");
709 niro 532 sgi_set_entire();
710     sgi_set_volhdr();
711     }
712     if ((sgi_gaps() == 0) && (sys != SGI_VOLUME)) {
713 niro 816 printf("The entire disk is already covered with partitions\n");
714 niro 532 return;
715     }
716     if (sgi_gaps() < 0) {
717 niro 816 printf("You got a partition overlap on the disk. Fix it first!\n");
718 niro 532 return;
719     }
720 niro 816 snprintf(mesg, sizeof(mesg), "First %s", str_units(SINGULAR));
721 niro 532 while (1) {
722 niro 816 if (sys == SGI_VOLUME) {
723 niro 532 last = sgi_get_lastblock();
724     first = read_int(0, 0, last-1, 0, mesg);
725     if (first != 0) {
726 niro 816 printf("It is highly recommended that eleventh partition\n"
727     "covers the entire disk and is of type 'SGI volume'\n");
728 niro 532 }
729     } else {
730     first = freelist[0].first;
731     last = freelist[0].last;
732     first = read_int(scround(first), scround(first), scround(last)-1,
733     0, mesg);
734     }
735     if (display_in_cyl_units)
736     first *= units_per_sector;
737     else
738     first = first; /* align to cylinder if you know how ... */
739 niro 816 if (!last )
740 niro 532 last = isinfreelist(first);
741 niro 816 if (last != 0)
742 niro 532 break;
743 niro 816 printf("You will get a partition overlap on the disk. "
744     "Fix it first!\n");
745 niro 532 }
746 niro 816 snprintf(mesg, sizeof(mesg), " Last %s", str_units(SINGULAR));
747 niro 532 last = read_int(scround(first), scround(last)-1, scround(last)-1,
748     scround(first), mesg)+1;
749     if (display_in_cyl_units)
750     last *= units_per_sector;
751     else
752     last = last; /* align to cylinder if You know how ... */
753     if ( (sys == SGI_VOLUME) && (first != 0 || last != sgi_get_lastblock() ) )
754 niro 816 printf("It is highly recommended that eleventh partition\n"
755     "covers the entire disk and is of type 'SGI volume'\n");
756 niro 532 sgi_set_partition(n, first, last-first, sys);
757     }
758    
759     #if ENABLE_FEATURE_FDISK_ADVANCED
760     static void
761     create_sgilabel(void)
762     {
763     struct hd_geometry geometry;
764     struct {
765     unsigned int start;
766     unsigned int nsect;
767     int sysid;
768     } old[4];
769     int i = 0;
770     long longsectors; /* the number of sectors on the device */
771     int res; /* the result from the ioctl */
772     int sec_fac; /* the sector factor */
773    
774     sec_fac = sector_size / 512; /* determine the sector factor */
775    
776 niro 816 printf(msg_building_new_label, "SGI disklabel");
777 niro 532
778 niro 816 sgi_other_endian = BB_LITTLE_ENDIAN;
779     res = ioctl(dev_fd, BLKGETSIZE, &longsectors);
780     if (!ioctl(dev_fd, HDIO_GETGEO, &geometry)) {
781     g_heads = geometry.heads;
782     g_sectors = geometry.sectors;
783 niro 532 if (res == 0) {
784     /* the get device size ioctl was successful */
785 niro 816 g_cylinders = longsectors / (g_heads * g_sectors);
786     g_cylinders /= sec_fac;
787 niro 532 } else {
788     /* otherwise print error and use truncated version */
789 niro 816 g_cylinders = geometry.cylinders;
790     printf(
791 niro 984 "Warning: BLKGETSIZE ioctl failed on %s. Using geometry cylinder value of %u.\n"
792 niro 816 "This value may be truncated for devices > 33.8 GB.\n", disk_device, g_cylinders);
793 niro 532 }
794     }
795     for (i = 0; i < 4; i++) {
796     old[i].sysid = 0;
797     if (valid_part_table_flag(MBRbuffer)) {
798 niro 816 if (get_part_table(i)->sys_ind) {
799 niro 532 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 niro 984 printf("Trying to keep parameters of partition %u\n", i);
803 niro 816 if (SGI_DEBUG)
804 niro 984 printf("ID=%02x\tSTART=%u\tLENGTH=%u\n",
805 niro 532 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 niro 816 current_label_type = LABEL_SGI;
849     g_partitions = 16;
850 niro 532 sgi_volumes = 15;
851     sgi_set_entire();
852     sgi_set_volhdr();
853     for (i = 0; i < 4; i++) {
854 niro 816 if (old[i].sysid) {
855 niro 532 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 */