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