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