]>
Commit | Line | Data |
---|---|---|
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 | ||
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 */ | |
22853e4a KZ |
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 | } | |
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 | 78 | struct 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 |
100 | static inline unsigned short |
101 | __swap16(unsigned short x) { | |
5c36a0eb KZ |
102 | return (((__u16)(x) & 0xFF) << 8) | (((__u16)(x) & 0xFF00) >> 8); |
103 | } | |
22853e4a KZ |
104 | |
105 | static 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 |
110 | static int |
111 | sgi_get_nsect(void) { | |
5c36a0eb KZ |
112 | return SSWAP16(sgilabel->devparam.nsect); |
113 | } | |
114 | ||
22853e4a KZ |
115 | static int |
116 | sgi_get_ntrks(void) { | |
5c36a0eb KZ |
117 | return SSWAP16(sgilabel->devparam.ntrks); |
118 | } | |
119 | ||
120 | #if 0 | |
121 | static int | |
22853e4a | 122 | sgi_get_head_vol0(void) { |
5c36a0eb KZ |
123 | return SSWAP16(sgilabel->devparam.head_vol0); |
124 | } | |
125 | ||
126 | static int | |
22853e4a | 127 | sgi_get_bytes(void) { |
5c36a0eb KZ |
128 | return SSWAP16(sgilabel->devparam.bytes); |
129 | } | |
130 | #endif | |
131 | ||
22853e4a KZ |
132 | static int |
133 | sgi_get_pcylcount(void) { | |
5c36a0eb KZ |
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 | ||
22853e4a KZ |
145 | static unsigned int |
146 | two_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 |
156 | int |
157 | check_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 | ||
193 | void | |
22853e4a | 194 | sgi_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 | ||
259 | int | |
22853e4a | 260 | sgi_get_start_sector( int i ) { |
5c36a0eb KZ |
261 | return SSWAP32(sgilabel->partitions[i].start_sector); |
262 | } | |
263 | ||
264 | int | |
22853e4a | 265 | sgi_get_num_sectors( int i ) { |
5c36a0eb KZ |
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 | |
22853e4a | 276 | sgi_get_bootpartition(void) |
5c36a0eb KZ |
277 | { |
278 | return SSWAP16(sgilabel->boot_part); | |
279 | } | |
280 | ||
281 | int | |
22853e4a | 282 | sgi_get_swappartition(void) |
5c36a0eb KZ |
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)); | |
5c36a0eb KZ |
291 | } |
292 | ||
22853e4a KZ |
293 | static int |
294 | sgi_get_lastblock(void) { | |
5c36a0eb KZ |
295 | return heads * sectors * cylinders; |
296 | } | |
297 | ||
298 | void | |
22853e4a | 299 | sgi_set_swappartition( int i ) { |
5c36a0eb | 300 | sgilabel->swap_part = SSWAP16(((short)i)); |
5c36a0eb KZ |
301 | } |
302 | ||
303 | static int | |
22853e4a | 304 | sgi_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 | ||
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 | } | |
7eda085c | 352 | printf( _("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file ); |
5c36a0eb | 353 | } |
5c36a0eb KZ |
354 | } |
355 | ||
356 | void | |
22853e4a | 357 | create_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 | 365 | sgiinfo * fill_sgiinfo(void); |
5c36a0eb KZ |
366 | |
367 | void | |
22853e4a | 368 | sgi_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 |
397 | static int |
398 | compare_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 |
417 | static int |
418 | sgi_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 | ||
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 */ | |
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 | ||
566 | void | |
567 | sgi_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 */ |
590 | static int | |
591 | sgi_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 |
599 | static void |
600 | sgi_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 |
612 | static void |
613 | sgi_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 | ||
623 | static | |
624 | void | |
22853e4a | 625 | sgi_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 | ||
645 | void | |
646 | sgi_delete_partition( int i ) | |
647 | { | |
648 | sgi_set_partition( i, 0, 0, 0 ); | |
5c36a0eb KZ |
649 | } |
650 | ||
651 | void | |
652 | sgi_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 | ||
726 | void | |
22853e4a | 727 | create_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 | ||
821 | void | |
22853e4a | 822 | sgi_set_ilfact(void) |
5c36a0eb KZ |
823 | { |
824 | /* do nothing in the beginning */ | |
825 | } | |
826 | ||
827 | void | |
22853e4a | 828 | sgi_set_rspeed(void) |
5c36a0eb KZ |
829 | { |
830 | /* do nothing in the beginning */ | |
831 | } | |
832 | ||
833 | void | |
22853e4a | 834 | sgi_set_pcylcount(void) |
5c36a0eb KZ |
835 | { |
836 | /* do nothing in the beginning */ | |
837 | } | |
838 | ||
839 | void | |
22853e4a | 840 | sgi_set_xcyl(void) |
5c36a0eb KZ |
841 | { |
842 | /* do nothing in the beginning */ | |
843 | } | |
844 | ||
845 | void | |
22853e4a | 846 | sgi_set_ncyl(void) |
5c36a0eb KZ |
847 | { |
848 | /* do nothing in the beginning */ | |
849 | } | |
850 | ||
851 | /* _____________________________________________________________ | |
852 | */ | |
853 | ||
854 | sgiinfo* | |
22853e4a | 855 | fill_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 | } |