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