]> git.ipfire.org Git - thirdparty/util-linux.git/blame - fdisk/fdisksgilabel.c
Imported from util-linux-2.11b tarball.
[thirdparty/util-linux.git] / fdisk / fdisksgilabel.c
CommitLineData
5c36a0eb
KZ
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.
7eda085c
KZ
8 *
9 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
10 * Internationalization
5c36a0eb
KZ
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>
7eda085c 21#include "nls.h"
5c36a0eb
KZ
22#include <linux/major.h> /* FLOPPY_MAJOR */
23#include <linux/hdreg.h> /* HDIO_GETGEO */
24
7eda085c 25#include "common.h"
5c36a0eb
KZ
26#include "fdisk.h"
27#include "fdisksgilabel.h"
28
29static int other_endian = 0;
30static int debug = 0;
31static short volumes=1;
32
33/*
34 * only dealing with free blocks here
35 */
36
37typedef struct { int first; int last; } freeblocks;
38static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
22853e4a
KZ
39
40static void
41setfreelist( int i, int f, int l ) {
42 freelist[i].first = f;
43 freelist[i].last = l;
44}
45
46static void
47add2freelist( 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
55static void
56clearfreelist(void) {
57 int i = 0;
58 for( ; i<17 ; i++ ) {
59 setfreelist( i, 0, 0 );
60 }
61}
62
63static int
64isinfreelist( 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}
5c36a0eb
KZ
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 */
5c36a0eb 78struct systypes sgi_sys_types[] = {
c07ebfa1
KZ
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 }
5c36a0eb
KZ
98};
99
22853e4a
KZ
100static inline unsigned short
101__swap16(unsigned short x) {
5c36a0eb
KZ
102 return (((__u16)(x) & 0xFF) << 8) | (((__u16)(x) & 0xFF00) >> 8);
103}
22853e4a
KZ
104
105static inline __u32
106__swap32(__u32 x) {
5c36a0eb
KZ
107 return (((__u32)(x) & 0xFF) << 24) | (((__u32)(x) & 0xFF00) << 8) | (((__u32)(x) & 0xFF0000) >> 8) | (((__u32)(x) & 0xFF000000) >> 24);
108}
109
22853e4a
KZ
110static int
111sgi_get_nsect(void) {
5c36a0eb
KZ
112 return SSWAP16(sgilabel->devparam.nsect);
113}
114
22853e4a
KZ
115static int
116sgi_get_ntrks(void) {
5c36a0eb
KZ
117 return SSWAP16(sgilabel->devparam.ntrks);
118}
119
120#if 0
121static int
22853e4a 122sgi_get_head_vol0(void) {
5c36a0eb
KZ
123 return SSWAP16(sgilabel->devparam.head_vol0);
124}
125
126static int
22853e4a 127sgi_get_bytes(void) {
5c36a0eb
KZ
128 return SSWAP16(sgilabel->devparam.bytes);
129}
130#endif
131
22853e4a
KZ
132static int
133sgi_get_pcylcount(void) {
5c36a0eb
KZ
134 return SSWAP16(sgilabel->devparam.pcylcount);
135}
136
137void
138sgi_nolabel()
139{
140 sgilabel->magic = 0;
141 sgi_label = 0;
142 partitions = 4;
143}
144
22853e4a
KZ
145static unsigned int
146two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */ ) {
5c36a0eb
KZ
147 int i=0;
148 unsigned int sum=0;
22853e4a 149
5c36a0eb
KZ
150 size = size / sizeof( unsigned int );
151 for( i=0; i<size; i++ )
5c36a0eb 152 sum = sum - SSWAP32(base[i]);
5c36a0eb
KZ
153 return sum;
154}
155
22853e4a
KZ
156int
157check_sgi_label() {
5c36a0eb
KZ
158 if (sizeof(sgilabel) > 512) {
159 fprintf(stderr,
7eda085c
KZ
160 _("According to MIPS Computer Systems, Inc the "
161 "Label must not contain more than 512 bytes\n"));
5c36a0eb
KZ
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 {
7eda085c 179 fprintf( stderr, _("Detected sgi disklabel with wrong checksum.\n"));
5c36a0eb
KZ
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
193void
22853e4a 194sgi_list_table( int xtra ) {
5c36a0eb
KZ
195 int i, w;
196 char *type;
197
198 w = strlen( disk_device );
199
200 if( xtra )
201 {
7eda085c 202 printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
5c36a0eb
KZ
203 "%d cylinders, %d physical cylinders\n"
204 "%d extra sects/cyl, interleave %d:1\n"
205 "%s\n"
7eda085c 206 "Units = %s of %d * 512 bytes\n\n"),
5c36a0eb
KZ
207 disk_device, heads, sectors, cylinders,
208 SSWAP16(sgiparam.pcylcount),
209 SSWAP16(sgiparam.sparecyl),
210 SSWAP16(sgiparam.ilfact),
211 (char *)sgilabel,
7eda085c 212 str_units(PLURAL), units_per_sector);
5c36a0eb
KZ
213 } else
214 {
7eda085c
KZ
215 printf( _("\nDisk %s (SGI disk label): "
216 "%d heads, %d sectors, %d cylinders\n"
217 "Units = %s of %d * 512 bytes\n\n"),
5c36a0eb 218 disk_device, heads, sectors, cylinders,
7eda085c 219 str_units(PLURAL), units_per_sector );
5c36a0eb 220 }
7eda085c
KZ
221 printf(_("----- partitions -----\n"
222 "%*s Info Start End Sectors Id System\n"),
223 w + 1, _("Device"));
5c36a0eb
KZ
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)))
7eda085c 240 ? type : _("Unknown"));
5c36a0eb
KZ
241 }
242 }
7eda085c
KZ
243 printf(_("----- bootinfo -----\nBootfile: %s\n"
244 "----- directory entries -----\n"),
245 sgilabel->boot_file );
5c36a0eb
KZ
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;
7eda085c 253 printf(_("%2d: %-10s sector%5u size%8u\n"),
5c36a0eb
KZ
254 i, name, (unsigned int) start, (unsigned int) len);
255 }
256 }
257}
258
259int
22853e4a 260sgi_get_start_sector( int i ) {
5c36a0eb
KZ
261 return SSWAP32(sgilabel->partitions[i].start_sector);
262}
263
264int
22853e4a 265sgi_get_num_sectors( int i ) {
5c36a0eb
KZ
266 return SSWAP32(sgilabel->partitions[i].num_sectors);
267}
268
269int
270sgi_get_sysid( int i )
271{
272 return SSWAP32(sgilabel->partitions[i].id);
273}
274
275int
22853e4a 276sgi_get_bootpartition(void)
5c36a0eb
KZ
277{
278 return SSWAP16(sgilabel->boot_part);
279}
280
281int
22853e4a 282sgi_get_swappartition(void)
5c36a0eb
KZ
283{
284 return SSWAP16(sgilabel->swap_part);
285}
286
287void
288sgi_set_bootpartition( int i )
289{
290 sgilabel->boot_part = SSWAP16(((short)i));
5c36a0eb
KZ
291}
292
22853e4a
KZ
293static int
294sgi_get_lastblock(void) {
5c36a0eb
KZ
295 return heads * sectors * cylinders;
296}
297
298void
22853e4a 299sgi_set_swappartition( int i ) {
5c36a0eb 300 sgilabel->swap_part = SSWAP16(((short)i));
5c36a0eb
KZ
301}
302
303static int
22853e4a 304sgi_check_bootfile( const char* aFile ) {
5c36a0eb
KZ
305 if( strlen( aFile ) < 3 ) /* "/a\n" is minimum */
306 {
7eda085c 307 printf( _("\nInvalid Bootfile!\n"
5c36a0eb 308 "\tThe bootfile must be an absolute non-zero pathname,\n"
7eda085c 309 "\te.g. \"/unix\" or \"/unix.save\".\n") );
5c36a0eb
KZ
310 return 0;
311 } else
312 if( strlen( aFile ) > 16 )
313 {
7eda085c 314 printf( _("\n\tName of Bootfile too long: 16 bytes maximum.\n") );
5c36a0eb
KZ
315 return 0;
316 } else
317 if( aFile[0] != '/' )
318 {
7eda085c 319 printf( _("\n\tBootfile must have a fully qualified pathname.\n") );
5c36a0eb
KZ
320 return 0;
321 }
322 if( strncmp( aFile, sgilabel->boot_file, 16 ) )
323 {
7eda085c
KZ
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") );
5c36a0eb
KZ
326 /* filename is correct and did change */
327 return 1;
328 }
329 return 0; /* filename did not change */
330}
331
332const char *
333sgi_get_bootfile(void) {
334 return sgilabel->boot_file;
335}
336
337void
338sgi_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 }
7eda085c 352 printf( _("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file );
5c36a0eb 353 }
5c36a0eb
KZ
354}
355
356void
22853e4a 357create_sgiinfo(void)
5c36a0eb
KZ
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 ) );
c07ebfa1 362 strncpy( sgilabel->directory[0].vol_file_name, "sgilabel", 8 );
5c36a0eb
KZ
363}
364
22853e4a 365sgiinfo * fill_sgiinfo(void);
5c36a0eb
KZ
366
367void
22853e4a 368sgi_write_table(void)
5c36a0eb
KZ
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 }
5c36a0eb
KZ
395}
396
22853e4a
KZ
397static int
398compare_start( int *x, int *y ) {
5c36a0eb
KZ
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
22853e4a
KZ
417static int
418sgi_gaps(void) {
5c36a0eb
KZ
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
428int
429verify_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 */
5c36a0eb
KZ
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)
7eda085c 450 printf(_("More than one entire disk entry present.\n"));
5c36a0eb
KZ
451 }
452 }
453 }
454 }
455 if( sortcount == 0 )
456 {
457 if(verbose)
7eda085c 458 printf(_("No partitions defined\n"));
5c36a0eb
KZ
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 )
7eda085c 465 printf( _("IRIX likes when Partition 11 covers the entire disk.\n") );
5c36a0eb 466 if( ( sgi_get_start_sector( Index[0] ) != 0 ) && verbose )
7eda085c
KZ
467 printf( _("The entire disk partition should start at block 0,\nnot "
468 "at diskblock %d.\n"), sgi_get_start_sector(Index[0] ) );
5c36a0eb
KZ
469 if(debug) /* I do not understand how some disks fulfil it */
470 if( ( sgi_get_num_sectors( Index[0] ) != lastblock ) && verbose )
7eda085c
KZ
471 printf( _("The entire disk partition is only %d diskblock large,\n"
472 "but the disk is %d diskblocks long.\n"),
5c36a0eb
KZ
473 sgi_get_num_sectors( Index[0] ), lastblock );
474 lastblock = sgi_get_num_sectors( Index[0] );
475 } else
476 {
477 if( verbose )
7eda085c 478 printf( _("One Partition (#11) should cover the entire disk.\n") );
5c36a0eb
KZ
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 )
7eda085c 490 printf( _("Partition %d does not start on cylinder boundary.\n"),
5c36a0eb
KZ
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 )
7eda085c 497 printf( _("Partition %d does not end on cylinder boundary.\n"),
5c36a0eb
KZ
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 )
7eda085c 505 printf( _("The Partition %d and %d overlap by %d sectors.\n"),
5c36a0eb
KZ
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 )
7eda085c 514 printf( _("Unused gap of %8d sectors - sectors %8d-%d\n"),
5c36a0eb
KZ
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 )
7eda085c 534 printf( _("Unused gap of %8d sectors - sectors %8d-%d\n"),
5c36a0eb
KZ
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 {
7eda085c 547 printf( _("\nThe boot partition does not exist.\n") );
5c36a0eb
KZ
548 }
549 if( !sgi_get_num_sectors( sgi_get_swappartition() ) )
550 {
7eda085c 551 printf( _("\nThe swap partition does not exist.\n") );
5c36a0eb
KZ
552 } else
553 if( ( sgi_get_sysid( sgi_get_swappartition() ) != SGI_SWAP )
554 && ( sgi_get_sysid( sgi_get_swappartition() ) != LINUX_SWAP ) )
555 {
7eda085c 556 printf( _("\nThe swap partition has no swap type.\n") );
5c36a0eb
KZ
557 }
558 if( sgi_check_bootfile( "/unix" ) )
559 {
7eda085c 560 printf( _("\tYou have chosen an unusual boot file name.\n") );
5c36a0eb
KZ
561 }
562 }
563 return gap;
564}
565
566void
567sgi_change_sysid( int i, int sys )
568{
569 if( sgi_get_num_sectors(i) == 0 ) /* caught already before, ... */
570 {
7eda085c 571 printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
5c36a0eb
KZ
572 return;
573 }
574 if( ((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
575 && (sgi_get_start_sector(i)<1) )
576 {
577 read_chars(
7eda085c 578 _("It is highly recommended that the partition at offset 0\n"
5c36a0eb
KZ
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"
7eda085c 582 "Type YES if you are sure about tagging this partition differently.\n"));
5c36a0eb
KZ
583 if (strcmp (line_ptr, "YES\n"))
584 return;
585 }
586 sgilabel->partitions[i].id = SSWAP32(sys);
5c36a0eb
KZ
587}
588
22853e4a
KZ
589/* returns partition index of first entry marked as entire disk */
590static int
591sgi_entire(void) {
5c36a0eb
KZ
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
22853e4a
KZ
599static void
600sgi_set_partition( int i, uint start, uint length, int sys ) {
5c36a0eb
KZ
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 );
22853e4a
KZ
607 set_changed(i);
608 if( sgi_gaps() < 0 ) /* rebuild freelist */
7eda085c 609 printf(_("Do You know, You got a partition overlap on the disk?\n"));
5c36a0eb
KZ
610}
611
22853e4a
KZ
612static void
613sgi_set_entire(void) {
5c36a0eb 614 int n;
22853e4a
KZ
615 for( n=10; n<partitions; n++ ) {
616 if(!sgi_get_num_sectors( n ) ) {
5c36a0eb
KZ
617 sgi_set_partition( n, 0, sgi_get_lastblock(), SGI_VOLUME );
618 break;
619 }
620 }
5c36a0eb
KZ
621}
622
623static
624void
22853e4a 625sgi_set_volhdr(void)
5c36a0eb
KZ
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 }
5c36a0eb
KZ
643}
644
645void
646sgi_delete_partition( int i )
647{
648 sgi_set_partition( i, 0, 0, 0 );
5c36a0eb
KZ
649}
650
651void
652sgi_add_partition( int n, int sys )
653{
eb63b9b8 654 char mesg[256];
5c36a0eb
KZ
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 {
7eda085c
KZ
664 printf(_("Partition %d is already defined. Delete "
665 "it before re-adding it.\n"), n + 1);
5c36a0eb
KZ
666 return;
667 }
668 if( (sgi_entire() == -1)
669 && (sys != SGI_VOLUME) )
670 {
7eda085c 671 printf(_("Attempting to generate entire disk entry automatically.\n"));
5c36a0eb
KZ
672 sgi_set_entire();
673 sgi_set_volhdr();
674 }
675 if( (sgi_gaps() == 0)
676 && (sys != SGI_VOLUME) )
677 {
7eda085c 678 printf(_("The entire disk is already covered with partitions.\n"));
5c36a0eb
KZ
679 return;
680 }
681 if( sgi_gaps() < 0 )
682 {
7eda085c 683 printf(_("You got a partition overlap on the disk. Fix it first!\n"));
5c36a0eb
KZ
684 return;
685 }
c07ebfa1 686 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
7eda085c
KZ
687 for(;;) {
688 if(sys == SGI_VOLUME) {
5c36a0eb
KZ
689 last = sgi_get_lastblock();
690 first = read_int(0, 0, last-1, 0, mesg);
691 if( first != 0 ) {
7eda085c
KZ
692 printf(_("It is highly recommended that eleventh partition\n"
693 "covers the entire disk and is of type `SGI volume'\n"));
5c36a0eb
KZ
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 }
7eda085c
KZ
701 if (display_in_cyl_units)
702 first *= units_per_sector;
5c36a0eb
KZ
703 else
704 first = first; /* align to cylinder if you know how ... */
705 if( !last )
706 last = isinfreelist(first);
707 if( last == 0 ) {
7eda085c
KZ
708 printf(_("You will get a partition overlap on the disk. "
709 "Fix it first!\n"));
5c36a0eb
KZ
710 } else
711 break;
712 }
c07ebfa1 713 snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
5c36a0eb
KZ
714 last = read_int(scround(first), scround(last)-1, scround(last)-1,
715 scround(first), mesg)+1;
7eda085c
KZ
716 if (display_in_cyl_units)
717 last *= units_per_sector;
5c36a0eb
KZ
718 else
719 last = last; /* align to cylinder if You know how ... */
720 if( (sys == SGI_VOLUME) && ( first != 0 || last != sgi_get_lastblock() ) )
7eda085c
KZ
721 printf(_("It is highly recommended that eleventh partition\n"
722 "covers the entire disk and is of type `SGI volume'\n"));
5c36a0eb 723 sgi_set_partition( n, first, last-first, sys );
5c36a0eb
KZ
724}
725
726void
22853e4a 727create_sgilabel(void)
5c36a0eb
KZ
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,
7eda085c 735 _("Building a new SGI disklabel. Changes will remain in memory only,\n"
5c36a0eb 736 "until you decide to write them. After that, of course, the previous\n"
22853e4a 737 "content will be unrecoverably lost.\n\n"));
5c36a0eb
KZ
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;
22853e4a 756 if( valid_part_table_flag(MBRbuffer) )
5c36a0eb 757 {
22853e4a 758 if( get_part_table(i)->sys_ind )
5c36a0eb 759 {
22853e4a
KZ
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) );
7eda085c 763 printf( _("Trying to keep parameters of partition %d.\n"), i );
5c36a0eb 764 if( debug )
7eda085c 765 printf( _("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
5c36a0eb
KZ
766 old[i].sysid, old[i].start, old[i].nsect );
767 }
768 }
769 }
22853e4a 770 memset(MBRbuffer, 0, sizeof(MBRbuffer));
5c36a0eb
KZ
771 sgilabel->magic = SSWAP32(SGI_LABEL_MAGIC);
772 sgilabel->boot_part = SSWAP16(0);
c07ebfa1
KZ
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
5c36a0eb
KZ
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 }
5c36a0eb
KZ
819}
820
821void
22853e4a 822sgi_set_ilfact(void)
5c36a0eb
KZ
823{
824 /* do nothing in the beginning */
825}
826
827void
22853e4a 828sgi_set_rspeed(void)
5c36a0eb
KZ
829{
830 /* do nothing in the beginning */
831}
832
833void
22853e4a 834sgi_set_pcylcount(void)
5c36a0eb
KZ
835{
836 /* do nothing in the beginning */
837}
838
839void
22853e4a 840sgi_set_xcyl(void)
5c36a0eb
KZ
841{
842 /* do nothing in the beginning */
843}
844
845void
22853e4a 846sgi_set_ncyl(void)
5c36a0eb
KZ
847{
848 /* do nothing in the beginning */
849}
850
851/* _____________________________________________________________
852 */
853
854sgiinfo*
22853e4a 855fill_sgiinfo(void)
5c36a0eb
KZ
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}