blob: bb354d8d9c8c8d92a5200ea52547d4c4c36e8bdd [file] [log] [blame]
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00001#if ENABLE_FEATURE_SGI_LABEL
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002
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
Denis Vlasenko28703012006-12-19 20:32:02 +000087#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))
Denis Vlasenko98ae2162006-10-12 19:30:44 +000089
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
106static int sgi_other_endian;
107static int debug;
108static short sgi_volumes = 1;
109
110/*
111 * only dealing with free blocks here
112 */
113
114typedef struct {
115 unsigned int first;
116 unsigned int last;
117} freeblocks;
118static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
119
120static void
121setfreelist(int i, unsigned int f, unsigned int l)
122{
123 freelist[i].first = f;
124 freelist[i].last = l;
125}
126
127static void
128add2freelist(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
137static void
138clearfreelist(void)
139{
140 int i;
141
142 for (i = 0; i < 17 ; i++)
143 setfreelist(i, 0, 0);
144}
145
146static unsigned int
147isinfreelist(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
162static 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" },
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000181 { NULL }
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000182};
183
184
185static int
186sgi_get_nsect(void)
187{
188 return SGI_SSWAP16(sgilabel->devparam.nsect);
189}
190
191static int
192sgi_get_ntrks(void)
193{
194 return SGI_SSWAP16(sgilabel->devparam.ntrks);
195}
196
197static unsigned int
198two_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
209static int
210check_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
241static unsigned int
242sgi_get_start_sector(int i)
243{
244 return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
245}
246
247static unsigned int
248sgi_get_num_sectors(int i)
249{
250 return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
251}
252
253static int
254sgi_get_sysid(int i)
255{
256 return SGI_SSWAP32(sgilabel->partitions[i].id);
257}
258
259static int
260sgi_get_bootpartition(void)
261{
262 return SGI_SSWAP16(sgilabel->boot_part);
263}
264
265static int
266sgi_get_swappartition(void)
267{
268 return SGI_SSWAP16(sgilabel->swap_part);
269}
270
271static void
272sgi_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
338static void
339sgi_set_bootpartition(int i)
340{
341 sgilabel->boot_part = SGI_SSWAP16(((short)i));
342}
343
344static unsigned int
345sgi_get_lastblock(void)
346{
347 return heads * sectors * cylinders;
348}
349
350static void
351sgi_set_swappartition(int i)
352{
353 sgilabel->swap_part = SGI_SSWAP16(((short)i));
354}
355
356static int
357sgi_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
386static const char *
387sgi_get_bootfile(void)
388{
389 return (char*)sgilabel->boot_file;
390}
391
392static void
393sgi_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
410static void
411create_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
419static sgiinfo *fill_sgiinfo(void);
420
421static void
422sgi_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
449static int
450compare_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
470static int
471verify_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
590static int
591sgi_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
602static void
603sgi_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 */
624static int
625sgi_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
635static void
636sgi_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
646static void
647sgi_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
659static void
660sgi_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
679static void
680sgi_delete_partition(int i)
681{
682 sgi_set_partition(i, 0, 0, 0);
683}
684
685static void
686sgi_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"
Denis Vlasenko89f0b342006-11-18 22:04:09 +0000721 "covers the entire disk and is of type 'SGI volume'\n"));
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000722 }
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"
Denis Vlasenko89f0b342006-11-18 22:04:09 +0000750 "covers the entire disk and is of type 'SGI volume'\n"));
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000751 sgi_set_partition(n, first, last-first, sys);
752}
753
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000754#if ENABLE_FEATURE_FDISK_ADVANCED
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000755static void
756create_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));
Denis Vlasenkod5470832007-01-03 02:58:54 +0000811 /* fields with '//' are already zeroed out by memset above */
812
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000813 sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
Denis Vlasenkod5470832007-01-03 02:58:54 +0000814 //sgilabel->boot_part = SGI_SSWAP16(0);
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000815 sgilabel->swap_part = SGI_SSWAP16(1);
816
Denis Vlasenkod5470832007-01-03 02:58:54 +0000817 //memset(sgilabel->boot_file, 0, 16);
818 strcpy((char*)sgilabel->boot_file, "/unix"); /* sizeof(sgilabel->boot_file) == 16 > 6 */
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000819
Denis Vlasenkod5470832007-01-03 02:58:54 +0000820 //sgilabel->devparam.skew = (0);
821 //sgilabel->devparam.gap1 = (0);
822 //sgilabel->devparam.gap2 = (0);
823 //sgilabel->devparam.sparecyl = (0);
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000824 sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders);
Denis Vlasenkod5470832007-01-03 02:58:54 +0000825 //sgilabel->devparam.head_vol0 = SGI_SSWAP16(0);
826 /* tracks/cylinder (heads) */
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000827 sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads);
Denis Vlasenkod5470832007-01-03 02:58:54 +0000828 //sgilabel->devparam.cmd_tag_queue_depth = (0);
829 //sgilabel->devparam.unused0 = (0);
830 //sgilabel->devparam.unused1 = SGI_SSWAP16(0);
831 /* sectors/track */
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000832 sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000833 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);
Denis Vlasenkod5470832007-01-03 02:58:54 +0000837 //sgilabel->devparam.datarate = SGI_SSWAP32(0);
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000838 sgilabel->devparam.retries_on_error = SGI_SSWAP32(1);
Denis Vlasenkod5470832007-01-03 02:58:54 +0000839 //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 );
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000848 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
860static void
861sgi_set_xcyl(void)
862{
863 /* do nothing in the beginning */
864}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000865#endif /* FEATURE_FDISK_ADVANCED */
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000866
867/* _____________________________________________________________
868 */
869
870static sgiinfo *
871fill_sgiinfo(void)
872{
Denis Vlasenko9b1381f2007-01-03 02:56:00 +0000873 sgiinfo *info = xzalloc(sizeof(sgiinfo));
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000874
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 */