37
36
static int scsi_disk = 0;
38
37
static int floppy = 0;
40
#define LINUX_SWAP 0x82
41
#define LINUX_NATIVE 0x83
43
39
struct systypes sun_sys_types[] = {
46
{2, N_("SunOS root")},
47
{SUNOS_SWAP, N_("SunOS swap")},
49
{WHOLE_DISK, N_("Whole disk")},
50
{6, N_("SunOS stand")},
52
{8, N_("SunOS home")},
53
{LINUX_SWAP, N_("Linux swap")},
54
{LINUX_NATIVE, N_("Linux native")},
55
{0x8e, N_("Linux LVM")},
56
{0xfd, N_("Linux raid autodetect")},/* New (2.2.x) raid partition
58
persistent superblock */
40
{SUN_TAG_UNASSIGNED, N_("Unassigned")},
41
{SUN_TAG_BOOT, N_("Boot")},
42
{SUN_TAG_ROOT, N_("SunOS root")},
43
{SUN_TAG_SWAP, N_("SunOS swap")},
44
{SUN_TAG_USR, N_("SunOS usr")},
45
{SUN_TAG_BACKUP, N_("Whole disk")},
46
{SUN_TAG_STAND, N_("SunOS stand")},
47
{SUN_TAG_VAR, N_("SunOS var")},
48
{SUN_TAG_HOME, N_("SunOS home")},
49
{SUN_TAG_ALTSCTR, N_("SunOS alt sectors")},
50
{SUN_TAG_CACHE, N_("SunOS cachefs")},
51
{SUN_TAG_RESERVED, N_("SunOS reserved")},
52
{SUN_TAG_LINUX_SWAP, N_("Linux swap")},
53
{SUN_TAG_LINUX_NATIVE, N_("Linux native")},
54
{SUN_TAG_LINUX_LVM, N_("Linux LVM")},
55
{SUN_TAG_LINUX_RAID, N_("Linux raid autodetect")},
129
128
other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
130
130
ush = ((unsigned short *) (sunlabel + 1)) - 1;
131
for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
131
for (csum = 0; ush >= (unsigned short *)sunlabel;)
133
135
fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
134
136
"Probably you'll have to set all the values,\n"
135
137
"e.g. heads, sectors, cylinders and partitions\n"
136
138
"or force a fresh label (s command in main menu)\n"));
138
heads = SSWAP16(sunlabel->ntrks);
142
heads = SSWAP16(sunlabel->nhead);
139
143
cylinders = SSWAP16(sunlabel->ncyl);
140
144
sectors = SSWAP16(sunlabel->nsect);
146
if (sunlabel->version != SSWAP32(SUN_LABEL_VERSION)) {
147
fprintf(stderr,_("Detected sun disklabel with wrong version [0x%08x].\n"),
151
if (sunlabel->sanity != SSWAP32(SUN_LABEL_SANE)) {
152
fprintf(stderr,_("Detected sun disklabel with wrong sanity [0x%08x].\n"),
156
if (sunlabel->num_partitions != SSWAP16(SUN_NUM_PARTITIONS)) {
157
fprintf(stderr,_("Detected sun disklabel with wrong num_partitions [%u].\n"),
158
sunlabel->num_partitions);
162
fprintf(stderr, _("Warning: Wrong values need to be "
163
"fixed up and will be corrected "
165
sunlabel->version = SSWAP32(SUN_LABEL_VERSION);
166
sunlabel->sanity = SSWAP32(SUN_LABEL_SANE);
167
sunlabel->num_partitions = SSWAP16(SUN_NUM_PARTITIONS);
169
ush = (unsigned short *)sunlabel;
171
while(ush < (unsigned short *)(&sunlabel->cksum))
173
sunlabel->cksum = csum;
180
partitions = SUN_NUM_PARTITIONS;
148
struct sun_predefined_drives {
151
unsigned short sparecyl;
153
unsigned short nacyl;
154
unsigned short pcylcount;
155
unsigned short ntrks;
156
unsigned short nsect;
157
unsigned short rspeed;
159
{"Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
160
{"Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
161
{"CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
162
{"IBM","DPES-31080",0,4901,2,4903,4,108,5400},
163
{"IBM","DORS-32160",0,1015,2,1017,67,62,5400},
164
{"IBM","DNES-318350",0,11199,2,11474,10,320,7200},
165
{"SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
166
{"","SUN0104",1,974,2,1019,6,35,3662},
167
{"","SUN0207",4,1254,2,1272,9,36,3600},
168
{"","SUN0327",3,1545,2,1549,9,46,3600},
169
{"","SUN0340",0,1538,2,1544,6,72,4200},
170
{"","SUN0424",2,1151,2,2500,9,80,4400},
171
{"","SUN0535",0,1866,2,2500,7,80,5400},
172
{"","SUN0669",5,1614,2,1632,15,54,3600},
173
{"","SUN1.0G",5,1703,2,1931,15,80,3597},
174
{"","SUN1.05",0,2036,2,2038,14,72,5400},
175
{"","SUN1.3G",6,1965,2,3500,17,80,5400},
176
{"","SUN2.1G",0,2733,2,3500,19,80,5400},
177
{"IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
180
static struct sun_predefined_drives *
181
sun_autoconfigure_scsi(void) {
182
struct sun_predefined_drives *p = NULL;
184
#ifdef SCSI_IOCTL_GET_IDLUN
194
if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
196
"Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
198
((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
200
/* This is very wrong (works only if you have one HBA),
201
but I haven't found a way how to get hostno
202
from the current kernel */
208
pfd = fopen("/proc/scsi/scsi","r");
210
while (fgets(buffer2,2048,pfd)) {
211
if (!strcmp(buffer, buffer2)) {
212
if (fgets(buffer2,2048,pfd)) {
213
q = strstr(buffer2,"Vendor: ");
218
*q++ = 0; /* truncate vendor name */
219
q = strstr(q,"Model: ");
224
q = strstr(q," Rev: ");
227
for (i = 0; i < SIZE(sun_drives); i++) {
228
if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
230
if (!strstr(model, sun_drives[i].model))
232
printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
250
184
void create_sunlabel(void)
252
186
struct hd_geometry geometry;
187
unsigned long long llsectors, llcyls;
253
188
unsigned int ndiv;
256
struct sun_predefined_drives *p = NULL;
259
192
_("Building a new sun disklabel. Changes will remain in memory only,\n"
267
200
memset(MBRbuffer, 0, sizeof(MBRbuffer));
268
201
sunlabel->magic = SSWAP16(SUN_LABEL_MAGIC);
270
puts(_("Drive type\n"
271
" ? auto configure\n"
272
" 0 custom (with hardware detected defaults)"));
273
for (i = 0; i < SIZE(sun_drives); i++) {
274
printf(" %c %s%s%s\n",
275
i + 'a', sun_drives[i].vendor,
276
(*sun_drives[i].vendor) ? " " : "",
277
sun_drives[i].model);
280
c = read_char(_("Select type (? for auto, 0 for custom): "));
281
if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
282
p = sun_drives + c - 'a';
284
} else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
285
p = sun_drives + c - 'A';
287
} else if (c == '0') {
289
} else if (c == '?' && scsi_disk) {
290
p = sun_autoconfigure_scsi();
292
printf(_("Autoconfigure failed.\n"));
299
if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
202
sunlabel->sanity = SSWAP32(SUN_LABEL_SANE);
203
sunlabel->version = SSWAP32(SUN_LABEL_VERSION);
204
sunlabel->num_partitions = SSWAP16(SUN_NUM_PARTITIONS);
206
res = disksize(fd, &llsectors);
207
sec_fac = sector_size / 512;
209
if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
300
210
heads = geometry.heads;
301
211
sectors = geometry.sectors;
302
cylinders = geometry.cylinders;
310
sunlabel->pcylcount = SSWAP16(cylinders);
311
sunlabel->rspeed = SSWAP16(300);
312
sunlabel->ilfact = SSWAP16(1);
313
sunlabel->sparecyl = 0;
315
heads = read_int(1,heads,1024,0,_("Heads"));
316
sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
318
cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
320
cylinders = read_int(1,0,65535,0,_("Cylinders"));
322
SSWAP16(read_int(0,2,65535,0,
323
_("Alternate cylinders")));
324
sunlabel->pcylcount =
325
SSWAP16(read_int(0,cylinders+SSWAP16(sunlabel->nacyl),
326
65535,0,_("Physical cylinders")));
328
SSWAP16(read_int(1,5400,100000,0,
329
_("Rotation speed (rpm)")));
331
SSWAP16(read_int(1,1,32,0,_("Interleave factor")));
333
SSWAP16(read_int(0,0,sectors,0,
334
_("Extra sectors per cylinder")));
213
llcyls = llsectors / (heads * sectors * sec_fac);
215
if (cylinders != llcyls)
218
cylinders = geometry.cylinders;
220
_("Warning: BLKGETSIZE ioctl failed on %s. "
221
"Using geometry cylinder value of %d.\n"
222
"This value may be truncated for devices"
223
" > 33.8 GB.\n"), disk_device, cylinders);
337
sunlabel->sparecyl = SSWAP16(p->sparecyl);
338
sunlabel->ncyl = SSWAP16(p->ncyl);
339
sunlabel->nacyl = SSWAP16(p->nacyl);
340
sunlabel->pcylcount = SSWAP16(p->pcylcount);
341
sunlabel->ntrks = SSWAP16(p->ntrks);
342
sunlabel->nsect = SSWAP16(p->nsect);
343
sunlabel->rspeed = SSWAP16(p->rspeed);
344
sunlabel->ilfact = SSWAP16(1);
348
puts(_("You may change all the disk params from the x menu"));
226
heads = read_int(1,1,1024,0,_("Heads"));
227
sectors = read_int(1,1,1024,0,_("Sectors/track"));
228
cylinders = read_int(1,1,65535,0,_("Cylinders"));
351
snprintf(sunlabel->info, sizeof(sunlabel->info),
352
"%s%s%s cyl %d alt %d hd %d sec %d",
353
p ? p->vendor : "", (p && *p->vendor) ? " " : "",
355
: (floppy ? _("3,5\" floppy") : _("Linux custom")),
356
cylinders, SSWAP16(sunlabel->nacyl), heads, sectors);
231
sunlabel->acyl = SSWAP16(2);
232
sunlabel->pcyl = SSWAP16(cylinders);
233
sunlabel->ncyl = SSWAP16(cylinders - 2);
234
sunlabel->rpm = SSWAP16(5400);
235
sunlabel->intrlv = SSWAP16(1);
236
sunlabel->apc = SSWAP16(0);
358
sunlabel->ntrks = SSWAP16(heads);
238
sunlabel->nhead = SSWAP16(heads);
359
239
sunlabel->nsect = SSWAP16(sectors);
360
240
sunlabel->ncyl = SSWAP16(cylinders);
362
set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
364
if (cylinders * heads * sectors >= 150 * 2048) {
242
snprintf(sunlabel->label_id, sizeof(sunlabel->label_id),
243
"Linux cyl %d alt %d hd %d sec %llu",
244
cylinders, SSWAP16(sunlabel->acyl), heads, sectors);
246
if (cylinders * heads * sectors >= 150 * 2048) {
365
247
ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
367
249
ndiv = cylinders * 2 / 3;
368
set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
369
set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
370
sunlabel->infos[1].flags |= 0x01; /* Not mountable */
372
set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
251
set_sun_partition(0, 0, ndiv * heads * sectors,
252
SUN_TAG_LINUX_NATIVE);
253
set_sun_partition(1, ndiv * heads * sectors,
254
cylinders * heads * sectors,
256
sunlabel->part_tags[1].flag |= SSWAP16(SUN_FLAG_UNMNT);
258
set_sun_partition(2, 0, cylinders * heads * sectors, SUN_TAG_BACKUP);
374
261
unsigned short *ush = (unsigned short *)sunlabel;
375
262
unsigned short csum = 0;
376
while(ush < (unsigned short *)(&sunlabel->csum))
263
while(ush < (unsigned short *)(&sunlabel->cksum))
378
sunlabel->csum = csum;
265
sunlabel->cksum = csum;
381
268
set_all_unchanged();
482
382
stop = cylinders * heads * sectors;
483
383
if (starts[array[0]])
484
printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
384
printf(_("Unused gap - sectors 0-%d\n"), starts[array[0]]);
485
385
for (i = 0; i < 7 && array[i+1] != -1; i++) {
486
printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
386
printf(_("Unused gap - sectors %d-%d\n"),
387
(starts[array[i]] + lens[array[i]]),
488
start = starts[array[i]]+lens[array[i]];
390
start = (starts[array[i]] + lens[array[i]]);
489
391
if (start < stop)
490
printf(_("Unused gap - sectors %d-%d\n"),start,stop);
392
printf(_("Unused gap - sectors %d-%d\n"), start, stop);
494
add_sun_partition(int n, int sys) {
495
unsigned int start, stop, stop2;
496
unsigned int starts[8], lens[8];
395
void add_sun_partition(int n, int sys)
397
__u32 starts[SUN_NUM_PARTITIONS], lens[SUN_NUM_PARTITIONS];
398
struct sun_partition *part = &sunlabel->partitions[n];
399
struct sun_tag_flag *tag = &sunlabel->part_tags[n];
400
__u32 start, stop, stop2;
497
401
int whole_disk = 0;
500
404
int i, first, last;
502
if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
406
if (part->num_sectors && tag->tag != SSWAP16(SUN_TAG_UNASSIGNED)) {
503
407
printf(_("Partition %d is already defined. Delete "
504
408
"it before re-adding it.\n"), n + 1);
508
fetch_sun(starts,lens,&start,&stop);
412
fetch_sun(starts, lens, &start, &stop);
509
413
if (stop <= start) {
601
505
} else if (!whole_disk && last > stop)
604
if (whole_disk) sys = WHOLE_DISK;
509
sys = SUN_TAG_BACKUP;
605
511
set_sun_partition(n, first, last, sys);
609
sun_delete_partition(int i) {
514
void sun_delete_partition(int i)
516
struct sun_partition *part = &sunlabel->partitions[i];
517
struct sun_tag_flag *tag = &sunlabel->part_tags[i];
610
518
unsigned int nsec;
612
if (i == 2 && sunlabel->infos[i].id == WHOLE_DISK &&
613
!sunlabel->partitions[i].start_cylinder &&
614
(nsec = SSWAP32(sunlabel->partitions[i].num_sectors))
521
tag->tag == SSWAP16(SUN_TAG_BACKUP) &&
522
!part->start_cylinder &&
523
(nsec = SSWAP32(part->num_sectors))
615
524
== heads * sectors * cylinders)
616
525
printf(_("If you want to maintain SunOS/Solaris compatibility, "
617
526
"consider leaving this\n"
618
527
"partition as Whole disk (5), starting at 0, with %u "
619
528
"sectors\n"), nsec);
620
sunlabel->infos[i].id = 0;
621
sunlabel->partitions[i].num_sectors = 0;
529
tag->tag = SSWAP16(SUN_TAG_UNASSIGNED);
530
part->num_sectors = 0;
625
sun_change_sysid(int i, int sys) {
626
if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
533
int sun_change_sysid(int i, __u16 sys)
535
struct sun_partition *part = &sunlabel->partitions[i];
536
struct sun_tag_flag *tag = &sunlabel->part_tags[i];
538
if (sys == SUN_TAG_LINUX_SWAP && !part->start_cylinder) {
628
540
_("It is highly recommended that the partition at offset 0\n"
629
541
"is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
631
543
"Type YES if you're very sure you would like that partition\n"
632
544
"tagged with 82 (Linux swap): "));
633
545
if (strcmp (line_ptr, _("YES\n")))
550
case SUN_TAG_LINUX_SWAP:
639
551
/* swaps are not mountable by default */
640
sunlabel->infos[i].flags |= 0x01;
552
tag->flag |= SSWAP16(SUN_FLAG_UNMNT);
643
555
/* assume other types are mountable;
644
556
user can change it anyway */
645
sunlabel->infos[i].flags &= ~0x01;
557
tag->flag &= ~SSWAP16(SUN_FLAG_UNMNT);
648
sunlabel->infos[i].id = sys;
560
tag->tag = SSWAP16(sys);
652
sun_list_table(int xtra) {
564
void sun_list_table(int xtra)
656
569
w = strlen(disk_device);
659
_("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
572
_("\nDisk %s (Sun disk label): %d heads, %llu sectors, %d rpm\n"
660
573
"%d cylinders, %d alternate cylinders, %d physical cylinders\n"
661
574
"%d extra sects/cyl, interleave %d:1\n"
663
577
"Units = %s of %d * 512 bytes\n\n"),
664
disk_device, heads, sectors, SSWAP16(sunlabel->rspeed),
665
cylinders, SSWAP16(sunlabel->nacyl),
666
SSWAP16(sunlabel->pcylcount),
667
SSWAP16(sunlabel->sparecyl),
668
SSWAP16(sunlabel->ilfact),
578
disk_device, heads, sectors, SSWAP16(sunlabel->rpm),
579
cylinders, SSWAP16(sunlabel->acyl),
580
SSWAP16(sunlabel->pcyl),
581
SSWAP16(sunlabel->apc),
582
SSWAP16(sunlabel->intrlv),
670
585
str_units(PLURAL), units_per_sector);
673
_("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
588
_("\nDisk %s (Sun disk label): %d heads, %llu sectors, %d cylinders\n"
674
589
"Units = %s of %d * 512 bytes\n\n"),
675
590
disk_device, heads, sectors, cylinders,
676
591
str_units(PLURAL), units_per_sector);
678
593
printf(_("%*s Flag Start End Blocks Id System\n"),
679
594
w + 1, _("Device"));
680
595
for (i = 0 ; i < partitions; i++) {
681
if (sunlabel->partitions[i].num_sectors) {
682
__u32 start = SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
683
__u32 len = SSWAP32(sunlabel->partitions[i].num_sectors);
596
struct sun_partition *part = &sunlabel->partitions[i];
597
struct sun_tag_flag *tag = &sunlabel->part_tags[i];
599
if (part->num_sectors) {
600
__u32 start = SSWAP32(part->start_cylinder) * heads * sectors;
601
__u32 len = SSWAP32(part->num_sectors);
685
603
"%s %c%c %9ld %9ld %9ld%c %2x %s\n",
686
604
/* device */ partname(disk_device, i+1, w),
687
/* flags */ (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ',
688
(sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
605
/* flags */ (tag->flag & SSWAP16(SUN_FLAG_UNMNT)) ? 'u' : ' ',
606
(tag->flag & SSWAP16(SUN_FLAG_RONLY)) ? 'r' : ' ',
689
607
/* start */ (long) scround(start),
690
608
/* end */ (long) scround(start+len),
691
609
/* odd flag on end */ (long) len / 2, len & 1 ? '+' : ' ',
692
/* type id */ sunlabel->infos[i].id,
693
/* type name */ (type = partition_type(sunlabel->infos[i].id))
610
/* type id */ SSWAP16(tag->tag),
611
/* type name */ (type = partition_type(SSWAP16(tag->tag)))
694
612
? type : _("Unknown"));
700
sun_set_alt_cyl(void) {
702
SSWAP16(read_int(0,SSWAP16(sunlabel->nacyl), 65535, 0,
617
void sun_set_alt_cyl(void)
620
SSWAP16(read_int(0,SSWAP16(sunlabel->acyl), 65535, 0,
703
621
_("Number of alternate cylinders")));
707
sun_set_ncyl(int cyl) {
624
void sun_set_ncyl(int cyl)
708
626
sunlabel->ncyl = SSWAP16(cyl);
714
SSWAP16(read_int(0, SSWAP16(sunlabel->sparecyl), sectors, 0,
629
void sun_set_xcyl(void)
632
SSWAP16(read_int(0, SSWAP16(sunlabel->apc), sectors, 0,
715
633
_("Extra sectors per cylinder")));
719
sun_set_ilfact(void) {
721
SSWAP16(read_int(1, SSWAP16(sunlabel->ilfact), 32, 0,
636
void sun_set_ilfact(void)
639
SSWAP16(read_int(1, SSWAP16(sunlabel->intrlv), 32, 0,
722
640
_("Interleave factor")));
726
sun_set_rspeed(void) {
728
SSWAP16(read_int(1, SSWAP16(sunlabel->rspeed), 100000, 0,
643
void sun_set_rspeed(void)
646
SSWAP16(read_int(1, SSWAP16(sunlabel->rpm), 100000, 0,
729
647
_("Rotation speed (rpm)")));
733
sun_set_pcylcount(void) {
734
sunlabel->pcylcount =
735
SSWAP16(read_int(0, SSWAP16(sunlabel->pcylcount), 65535, 0,
650
void sun_set_pcylcount(void)
653
SSWAP16(read_int(0, SSWAP16(sunlabel->pcyl), 65535, 0,
736
654
_("Number of physical cylinders")));
740
sun_write_table(void) {
657
void sun_write_table(void)
741
659
unsigned short *ush = (unsigned short *)sunlabel;
742
660
unsigned short csum = 0;
744
while(ush < (unsigned short *)(&sunlabel->csum))
662
while(ush < (unsigned short *)(&sunlabel->cksum))
746
sunlabel->csum = csum;
664
sunlabel->cksum = csum;
747
665
if (lseek(fd, 0, SEEK_SET) < 0)
748
666
fatal(unable_to_seek);
749
667
if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
750
668
fatal(unable_to_write);
671
int sun_get_sysid(int i)
673
return SSWAP16(sunlabel->part_tags[i].tag);