Magellan Linux

Contents of /trunk/mkinitrd-magellan/busybox/util-linux/fdisk_sun.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (show annotations) (download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 9 months ago) by niro
File MIME type: text/plain
File size: 20684 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd

1 #if ENABLE_FEATURE_SUN_LABEL
2
3 #define SUN_LABEL_MAGIC 0xDABE
4 #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
5 #define SUN_SSWAP16(x) (sun_other_endian ? fdisk_swap16(x) : (uint16_t)(x))
6 #define SUN_SSWAP32(x) (sun_other_endian ? fdisk_swap32(x) : (uint32_t)(x))
7
8 /* Copied from linux/major.h */
9 #define FLOPPY_MAJOR 2
10
11 #define SCSI_IOCTL_GET_IDLUN 0x5382
12
13 /*
14 * fdisksunlabel.c
15 *
16 * I think this is mostly, or entirely, due to
17 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
18 *
19 * Merged with fdisk for other architectures, aeb, June 1998.
20 *
21 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
22 * Internationalization
23 */
24
25
26 static int sun_other_endian;
27 static int scsi_disk;
28 static int floppy;
29
30 #ifndef IDE0_MAJOR
31 #define IDE0_MAJOR 3
32 #endif
33 #ifndef IDE1_MAJOR
34 #define IDE1_MAJOR 22
35 #endif
36
37 static void
38 guess_device_type(void)
39 {
40 struct stat bootstat;
41
42 if (fstat(fd, &bootstat) < 0) {
43 scsi_disk = 0;
44 floppy = 0;
45 } else if (S_ISBLK(bootstat.st_mode)
46 && (major(bootstat.st_rdev) == IDE0_MAJOR ||
47 major(bootstat.st_rdev) == IDE1_MAJOR)) {
48 scsi_disk = 0;
49 floppy = 0;
50 } else if (S_ISBLK(bootstat.st_mode)
51 && major(bootstat.st_rdev) == FLOPPY_MAJOR) {
52 scsi_disk = 0;
53 floppy = 1;
54 } else {
55 scsi_disk = 1;
56 floppy = 0;
57 }
58 }
59
60 static const struct systypes sun_sys_types[] = {
61 { "\x00" "Empty" }, /* 0 */
62 { "\x01" "Boot" }, /* 1 */
63 { "\x02" "SunOS root" }, /* 2 */
64 { "\x03" "SunOS swap" }, /* SUNOS_SWAP */
65 { "\x04" "SunOS usr" }, /* 4 */
66 { "\x05" "Whole disk" }, /* SUN_WHOLE_DISK */
67 { "\x06" "SunOS stand" }, /* 6 */
68 { "\x07" "SunOS var" }, /* 7 */
69 { "\x08" "SunOS home" }, /* 8 */
70 { "\x82" "Linux swap" }, /* LINUX_SWAP */
71 { "\x83" "Linux native" }, /* LINUX_NATIVE */
72 { "\x8e" "Linux LVM" }, /* 0x8e */
73 /* New (2.2.x) raid partition with autodetect using persistent superblock */
74 { "\xfd" "Linux raid autodetect" }, /* 0xfd */
75 { NULL }
76 };
77
78
79 static void
80 set_sun_partition(int i, uint start, uint stop, int sysid)
81 {
82 sunlabel->infos[i].id = sysid;
83 sunlabel->partitions[i].start_cylinder =
84 SUN_SSWAP32(start / (heads * sectors));
85 sunlabel->partitions[i].num_sectors =
86 SUN_SSWAP32(stop - start);
87 set_changed(i);
88 }
89
90 static int
91 check_sun_label(void)
92 {
93 unsigned short *ush;
94 int csum;
95
96 if (sunlabel->magic != SUN_LABEL_MAGIC
97 && sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
98 current_label_type = label_dos;
99 sun_other_endian = 0;
100 return 0;
101 }
102 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
103 ush = ((unsigned short *) (sunlabel + 1)) - 1;
104 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
105 if (csum) {
106 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
107 "Probably you'll have to set all the values,\n"
108 "e.g. heads, sectors, cylinders and partitions\n"
109 "or force a fresh label (s command in main menu)\n"));
110 } else {
111 heads = SUN_SSWAP16(sunlabel->ntrks);
112 cylinders = SUN_SSWAP16(sunlabel->ncyl);
113 sectors = SUN_SSWAP16(sunlabel->nsect);
114 }
115 update_units();
116 current_label_type = label_sun;
117 partitions = 8;
118 return 1;
119 }
120
121 static const struct sun_predefined_drives {
122 const char *vendor;
123 const char *model;
124 unsigned short sparecyl;
125 unsigned short ncyl;
126 unsigned short nacyl;
127 unsigned short pcylcount;
128 unsigned short ntrks;
129 unsigned short nsect;
130 unsigned short rspeed;
131 } sun_drives[] = {
132 { "Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
133 { "Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
134 { "CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
135 { "IBM","DPES-31080",0,4901,2,4903,4,108,5400},
136 { "IBM","DORS-32160",0,1015,2,1017,67,62,5400},
137 { "IBM","DNES-318350",0,11199,2,11474,10,320,7200},
138 { "SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
139 { "","SUN0104",1,974,2,1019,6,35,3662},
140 { "","SUN0207",4,1254,2,1272,9,36,3600},
141 { "","SUN0327",3,1545,2,1549,9,46,3600},
142 { "","SUN0340",0,1538,2,1544,6,72,4200},
143 { "","SUN0424",2,1151,2,2500,9,80,4400},
144 { "","SUN0535",0,1866,2,2500,7,80,5400},
145 { "","SUN0669",5,1614,2,1632,15,54,3600},
146 { "","SUN1.0G",5,1703,2,1931,15,80,3597},
147 { "","SUN1.05",0,2036,2,2038,14,72,5400},
148 { "","SUN1.3G",6,1965,2,3500,17,80,5400},
149 { "","SUN2.1G",0,2733,2,3500,19,80,5400},
150 { "IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
151 };
152
153 static const struct sun_predefined_drives *
154 sun_autoconfigure_scsi(void)
155 {
156 const struct sun_predefined_drives *p = NULL;
157
158 #ifdef SCSI_IOCTL_GET_IDLUN
159 unsigned int id[2];
160 char buffer[2048];
161 char buffer2[2048];
162 FILE *pfd;
163 char *vendor;
164 char *model;
165 char *q;
166 int i;
167
168 if (ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id))
169 return NULL;
170
171 sprintf(buffer,
172 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
173 /* This is very wrong (works only if you have one HBA),
174 but I haven't found a way how to get hostno
175 from the current kernel */
176 0,
177 (id[0]>>16) & 0xff,
178 id[0] & 0xff,
179 (id[0]>>8) & 0xff
180 );
181 pfd = fopen("/proc/scsi/scsi", "r");
182 if (!pfd) {
183 return NULL;
184 }
185 while (fgets(buffer2, 2048, pfd)) {
186 if (strcmp(buffer, buffer2))
187 continue;
188 if (!fgets(buffer2, 2048, pfd))
189 break;
190 q = strstr(buffer2, "Vendor: ");
191 if (!q)
192 break;
193 q += 8;
194 vendor = q;
195 q = strstr(q, " ");
196 *q++ = '\0'; /* truncate vendor name */
197 q = strstr(q, "Model: ");
198 if (!q)
199 break;
200 *q = '\0';
201 q += 7;
202 model = q;
203 q = strstr(q, " Rev: ");
204 if (!q)
205 break;
206 *q = '\0';
207 for (i = 0; i < SIZE(sun_drives); i++) {
208 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
209 continue;
210 if (!strstr(model, sun_drives[i].model))
211 continue;
212 printf(_("Autoconfigure found a %s%s%s\n"),
213 sun_drives[i].vendor,
214 (*sun_drives[i].vendor) ? " " : "",
215 sun_drives[i].model);
216 p = sun_drives + i;
217 break;
218 }
219 break;
220 }
221 fclose(pfd);
222 #endif
223 return p;
224 }
225
226 static void
227 create_sunlabel(void)
228 {
229 struct hd_geometry geometry;
230 unsigned int ndiv;
231 int i;
232 unsigned char c;
233 const struct sun_predefined_drives *p = NULL;
234
235 fprintf(stderr,
236 _("Building a new sun disklabel. Changes will remain in memory only,\n"
237 "until you decide to write them. After that, of course, the previous\n"
238 "content won't be recoverable.\n\n"));
239 sun_other_endian = BB_LITTLE_ENDIAN;
240 memset(MBRbuffer, 0, sizeof(MBRbuffer));
241 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
242 if (!floppy) {
243 puts(_("Drive type\n"
244 " ? auto configure\n"
245 " 0 custom (with hardware detected defaults)"));
246 for (i = 0; i < SIZE(sun_drives); i++) {
247 printf(" %c %s%s%s\n",
248 i + 'a', sun_drives[i].vendor,
249 (*sun_drives[i].vendor) ? " " : "",
250 sun_drives[i].model);
251 }
252 while (1) {
253 c = read_nonempty(_("Select type (? for auto, 0 for custom): "));
254 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
255 p = sun_drives + c - 'a';
256 break;
257 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
258 p = sun_drives + c - 'A';
259 break;
260 } else if (c == '0') {
261 break;
262 } else if (c == '?' && scsi_disk) {
263 p = sun_autoconfigure_scsi();
264 if (!p)
265 printf(_("Autoconfigure failed.\n"));
266 else
267 break;
268 }
269 }
270 }
271 if (!p || floppy) {
272 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
273 heads = geometry.heads;
274 sectors = geometry.sectors;
275 cylinders = geometry.cylinders;
276 } else {
277 heads = 0;
278 sectors = 0;
279 cylinders = 0;
280 }
281 if (floppy) {
282 sunlabel->nacyl = 0;
283 sunlabel->pcylcount = SUN_SSWAP16(cylinders);
284 sunlabel->rspeed = SUN_SSWAP16(300);
285 sunlabel->ilfact = SUN_SSWAP16(1);
286 sunlabel->sparecyl = 0;
287 } else {
288 heads = read_int(1,heads,1024,0,_("Heads"));
289 sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
290 if (cylinders)
291 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
292 else
293 cylinders = read_int(1,0,65535,0,_("Cylinders"));
294 sunlabel->nacyl = SUN_SSWAP16(read_int(0,2,65535,0, _("Alternate cylinders")));
295 sunlabel->pcylcount = SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl), 65535,0, _("Physical cylinders")));
296 sunlabel->rspeed = SUN_SSWAP16(read_int(1,5400,100000,0, _("Rotation speed (rpm)")));
297 sunlabel->ilfact = SUN_SSWAP16(read_int(1,1,32,0, _("Interleave factor")));
298 sunlabel->sparecyl = SUN_SSWAP16(read_int(0,0,sectors,0, _("Extra sectors per cylinder")));
299 }
300 } else {
301 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
302 sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
303 sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
304 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
305 sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
306 sunlabel->nsect = SUN_SSWAP16(p->nsect);
307 sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
308 sunlabel->ilfact = SUN_SSWAP16(1);
309 cylinders = p->ncyl;
310 heads = p->ntrks;
311 sectors = p->nsect;
312 puts(_("You may change all the disk params from the x menu"));
313 }
314
315 snprintf((char *)(sunlabel->info), sizeof(sunlabel->info),
316 "%s%s%s cyl %d alt %d hd %d sec %d",
317 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
318 p ? p->model : (floppy ? _("3,5\" floppy") : _("Linux custom")),
319 cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
320
321 sunlabel->ntrks = SUN_SSWAP16(heads);
322 sunlabel->nsect = SUN_SSWAP16(sectors);
323 sunlabel->ncyl = SUN_SSWAP16(cylinders);
324 if (floppy)
325 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
326 else {
327 if (cylinders * heads * sectors >= 150 * 2048) {
328 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
329 } else
330 ndiv = cylinders * 2 / 3;
331 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
332 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
333 sunlabel->infos[1].flags |= 0x01; /* Not mountable */
334 }
335 set_sun_partition(2, 0, cylinders * heads * sectors, SUN_WHOLE_DISK);
336 {
337 unsigned short *ush = (unsigned short *)sunlabel;
338 unsigned short csum = 0;
339 while (ush < (unsigned short *)(&sunlabel->csum))
340 csum ^= *ush++;
341 sunlabel->csum = csum;
342 }
343
344 set_all_unchanged();
345 set_changed(0);
346 get_boot(create_empty_sun);
347 }
348
349 static void
350 toggle_sunflags(int i, unsigned char mask)
351 {
352 if (sunlabel->infos[i].flags & mask)
353 sunlabel->infos[i].flags &= ~mask;
354 else
355 sunlabel->infos[i].flags |= mask;
356 set_changed(i);
357 }
358
359 static void
360 fetch_sun(uint *starts, uint *lens, uint *start, uint *stop)
361 {
362 int i, continuous = 1;
363
364 *start = 0;
365 *stop = cylinders * heads * sectors;
366 for (i = 0; i < partitions; i++) {
367 if (sunlabel->partitions[i].num_sectors
368 && sunlabel->infos[i].id
369 && sunlabel->infos[i].id != SUN_WHOLE_DISK) {
370 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
371 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
372 if (continuous) {
373 if (starts[i] == *start)
374 *start += lens[i];
375 else if (starts[i] + lens[i] >= *stop)
376 *stop = starts[i];
377 else
378 continuous = 0;
379 /* There will be probably more gaps
380 than one, so lets check afterwards */
381 }
382 } else {
383 starts[i] = 0;
384 lens[i] = 0;
385 }
386 }
387 }
388
389 static uint *verify_sun_starts;
390
391 static int
392 verify_sun_cmp(int *a, int *b)
393 {
394 if (*a == -1) return 1;
395 if (*b == -1) return -1;
396 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
397 return -1;
398 }
399
400 static void
401 verify_sun(void)
402 {
403 uint starts[8], lens[8], start, stop;
404 int i,j,k,starto,endo;
405 int array[8];
406
407 verify_sun_starts = starts;
408 fetch_sun(starts,lens,&start,&stop);
409 for (k = 0; k < 7; k++) {
410 for (i = 0; i < 8; i++) {
411 if (k && (lens[i] % (heads * sectors))) {
412 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
413 }
414 if (lens[i]) {
415 for (j = 0; j < i; j++)
416 if (lens[j]) {
417 if (starts[j] == starts[i]+lens[i]) {
418 starts[j] = starts[i]; lens[j] += lens[i];
419 lens[i] = 0;
420 } else if (starts[i] == starts[j]+lens[j]){
421 lens[j] += lens[i];
422 lens[i] = 0;
423 } else if (!k) {
424 if (starts[i] < starts[j]+lens[j]
425 && starts[j] < starts[i]+lens[i]) {
426 starto = starts[i];
427 if (starts[j] > starto)
428 starto = starts[j];
429 endo = starts[i]+lens[i];
430 if (starts[j]+lens[j] < endo)
431 endo = starts[j]+lens[j];
432 printf(_("Partition %d overlaps with others in "
433 "sectors %d-%d\n"), i+1, starto, endo);
434 }
435 }
436 }
437 }
438 }
439 }
440 for (i = 0; i < 8; i++) {
441 if (lens[i])
442 array[i] = i;
443 else
444 array[i] = -1;
445 }
446 qsort(array,SIZE(array),sizeof(array[0]),
447 (int (*)(const void *,const void *)) verify_sun_cmp);
448 if (array[0] == -1) {
449 printf(_("No partitions defined\n"));
450 return;
451 }
452 stop = cylinders * heads * sectors;
453 if (starts[array[0]])
454 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
455 for (i = 0; i < 7 && array[i+1] != -1; i++) {
456 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
457 }
458 start = starts[array[i]] + lens[array[i]];
459 if (start < stop)
460 printf(_("Unused gap - sectors %d-%d\n"),start,stop);
461 }
462
463 static void
464 add_sun_partition(int n, int sys)
465 {
466 uint start, stop, stop2;
467 uint starts[8], lens[8];
468 int whole_disk = 0;
469
470 char mesg[256];
471 int i, first, last;
472
473 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
474 printf(_("Partition %d is already defined. Delete "
475 "it before re-adding it.\n"), n + 1);
476 return;
477 }
478
479 fetch_sun(starts,lens,&start,&stop);
480 if (stop <= start) {
481 if (n == 2)
482 whole_disk = 1;
483 else {
484 printf(_("Other partitions already cover the whole disk.\nDelete "
485 "some/shrink them before retry.\n"));
486 return;
487 }
488 }
489 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
490 while (1) {
491 if (whole_disk)
492 first = read_int(0, 0, 0, 0, mesg);
493 else
494 first = read_int(scround(start), scround(stop)+1,
495 scround(stop), 0, mesg);
496 if (display_in_cyl_units)
497 first *= units_per_sector;
498 else
499 /* Starting sector has to be properly aligned */
500 first = (first + heads * sectors - 1) / (heads * sectors);
501 if (n == 2 && first != 0)
502 printf("\
503 It is highly recommended that the third partition covers the whole disk\n\
504 and is of type `Whole disk'\n");
505 /* ewt asks to add: "don't start a partition at cyl 0"
506 However, edmundo@rano.demon.co.uk writes:
507 "In addition to having a Sun partition table, to be able to
508 boot from the disc, the first partition, /dev/sdX1, must
509 start at cylinder 0. This means that /dev/sdX1 contains
510 the partition table and the boot block, as these are the
511 first two sectors of the disc. Therefore you must be
512 careful what you use /dev/sdX1 for. In particular, you must
513 not use a partition starting at cylinder 0 for Linux swap,
514 as that would overwrite the partition table and the boot
515 block. You may, however, use such a partition for a UFS
516 or EXT2 file system, as these file systems leave the first
517 1024 bytes undisturbed. */
518 /* On the other hand, one should not use partitions
519 starting at block 0 in an md, or the label will
520 be trashed. */
521 for (i = 0; i < partitions; i++)
522 if (lens[i] && starts[i] <= first && starts[i] + lens[i] > first)
523 break;
524 if (i < partitions && !whole_disk) {
525 if (n == 2 && !first) {
526 whole_disk = 1;
527 break;
528 }
529 printf(_("Sector %d is already allocated\n"), first);
530 } else
531 break;
532 }
533 stop = cylinders * heads * sectors;
534 stop2 = stop;
535 for (i = 0; i < partitions; i++) {
536 if (starts[i] > first && starts[i] < stop)
537 stop = starts[i];
538 }
539 snprintf(mesg, sizeof(mesg),
540 _("Last %s or +size or +sizeM or +sizeK"),
541 str_units(SINGULAR));
542 if (whole_disk)
543 last = read_int(scround(stop2), scround(stop2), scround(stop2),
544 0, mesg);
545 else if (n == 2 && !first)
546 last = read_int(scround(first), scround(stop2), scround(stop2),
547 scround(first), mesg);
548 else
549 last = read_int(scround(first), scround(stop), scround(stop),
550 scround(first), mesg);
551 if (display_in_cyl_units)
552 last *= units_per_sector;
553 if (n == 2 && !first) {
554 if (last >= stop2) {
555 whole_disk = 1;
556 last = stop2;
557 } else if (last > stop) {
558 printf(_("You haven't covered the whole disk with "
559 "the 3rd partition, but your value\n"
560 "%d %s covers some other partition. "
561 "Your entry has been changed\n"
562 "to %d %s\n"),
563 scround(last), str_units(SINGULAR),
564 scround(stop), str_units(SINGULAR));
565 last = stop;
566 }
567 } else if (!whole_disk && last > stop)
568 last = stop;
569
570 if (whole_disk)
571 sys = SUN_WHOLE_DISK;
572 set_sun_partition(n, first, last, sys);
573 }
574
575 static void
576 sun_delete_partition(int i)
577 {
578 unsigned int nsec;
579
580 if (i == 2
581 && sunlabel->infos[i].id == SUN_WHOLE_DISK
582 && !sunlabel->partitions[i].start_cylinder
583 && (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors)) == heads * sectors * cylinders)
584 printf(_("If you want to maintain SunOS/Solaris compatibility, "
585 "consider leaving this\n"
586 "partition as Whole disk (5), starting at 0, with %u "
587 "sectors\n"), nsec);
588 sunlabel->infos[i].id = 0;
589 sunlabel->partitions[i].num_sectors = 0;
590 }
591
592 static void
593 sun_change_sysid(int i, int sys)
594 {
595 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
596 read_maybe_empty(
597 _("It is highly recommended that the partition at offset 0\n"
598 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
599 "there may destroy your partition table and bootblock.\n"
600 "Type YES if you're very sure you would like that partition\n"
601 "tagged with 82 (Linux swap): "));
602 if (strcmp (line_ptr, _("YES\n")))
603 return;
604 }
605 switch (sys) {
606 case SUNOS_SWAP:
607 case LINUX_SWAP:
608 /* swaps are not mountable by default */
609 sunlabel->infos[i].flags |= 0x01;
610 break;
611 default:
612 /* assume other types are mountable;
613 user can change it anyway */
614 sunlabel->infos[i].flags &= ~0x01;
615 break;
616 }
617 sunlabel->infos[i].id = sys;
618 }
619
620 static void
621 sun_list_table(int xtra)
622 {
623 int i, w;
624
625 w = strlen(disk_device);
626 if (xtra)
627 printf(
628 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
629 "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
630 "%d extra sects/cyl, interleave %d:1\n"
631 "%s\n"
632 "Units = %s of %d * 512 bytes\n\n"),
633 disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
634 cylinders, SUN_SSWAP16(sunlabel->nacyl),
635 SUN_SSWAP16(sunlabel->pcylcount),
636 SUN_SSWAP16(sunlabel->sparecyl),
637 SUN_SSWAP16(sunlabel->ilfact),
638 (char *)sunlabel,
639 str_units(PLURAL), units_per_sector);
640 else
641 printf(
642 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
643 "Units = %s of %d * 512 bytes\n\n"),
644 disk_device, heads, sectors, cylinders,
645 str_units(PLURAL), units_per_sector);
646
647 printf(_("%*s Flag Start End Blocks Id System\n"),
648 w + 1, _("Device"));
649 for (i = 0 ; i < partitions; i++) {
650 if (sunlabel->partitions[i].num_sectors) {
651 uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
652 uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
653 printf("%s %c%c %9ld %9ld %9ld%c %2x %s\n",
654 partname(disk_device, i+1, w), /* device */
655 (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ', /* flags */
656 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
657 (long) scround(start), /* start */
658 (long) scround(start+len), /* end */
659 (long) len / 2, len & 1 ? '+' : ' ', /* odd flag on end */
660 sunlabel->infos[i].id, /* type id */
661 partition_type(sunlabel->infos[i].id)); /* type name */
662 }
663 }
664 }
665
666 #if ENABLE_FEATURE_FDISK_ADVANCED
667
668 static void
669 sun_set_alt_cyl(void)
670 {
671 sunlabel->nacyl =
672 SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
673 _("Number of alternate cylinders")));
674 }
675
676 static void
677 sun_set_ncyl(int cyl)
678 {
679 sunlabel->ncyl = SUN_SSWAP16(cyl);
680 }
681
682 static void
683 sun_set_xcyl(void)
684 {
685 sunlabel->sparecyl =
686 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
687 _("Extra sectors per cylinder")));
688 }
689
690 static void
691 sun_set_ilfact(void)
692 {
693 sunlabel->ilfact =
694 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
695 _("Interleave factor")));
696 }
697
698 static void
699 sun_set_rspeed(void)
700 {
701 sunlabel->rspeed =
702 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
703 _("Rotation speed (rpm)")));
704 }
705
706 static void
707 sun_set_pcylcount(void)
708 {
709 sunlabel->pcylcount =
710 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
711 _("Number of physical cylinders")));
712 }
713 #endif /* FEATURE_FDISK_ADVANCED */
714
715 static void
716 sun_write_table(void)
717 {
718 unsigned short *ush = (unsigned short *)sunlabel;
719 unsigned short csum = 0;
720
721 while (ush < (unsigned short *)(&sunlabel->csum))
722 csum ^= *ush++;
723 sunlabel->csum = csum;
724 if (lseek(fd, 0, SEEK_SET) < 0)
725 fdisk_fatal(unable_to_seek);
726 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
727 fdisk_fatal(unable_to_write);
728 }
729 #endif /* SUN_LABEL */