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