source: MondoRescue/branches/3.3/mindi-busybox/util-linux/fdisk_osf.c@ 3625

Last change on this file since 3625 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

  • Property svn:eol-style set to native
File size: 29.2 KB
Line 
1/*
2 * Copyright (c) 1987, 1988 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgment:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if ENABLE_FEATURE_OSF_LABEL
35
36#ifndef BSD_DISKMAGIC
37#define BSD_DISKMAGIC ((uint32_t) 0x82564557)
38#endif
39
40#ifndef BSD_MAXPARTITIONS
41#define BSD_MAXPARTITIONS 16
42#endif
43
44#define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
45
46#if defined(__alpha__) \
47 || defined(__powerpc__) \
48 || defined(__ia64__) \
49 || defined(__hppa__)
50# define BSD_LABELSECTOR 0
51# define BSD_LABELOFFSET 64
52#else
53# define BSD_LABELSECTOR 1
54# define BSD_LABELOFFSET 0
55#endif
56
57#define BSD_BBSIZE 8192 /* size of boot area, with label */
58#define BSD_SBSIZE 8192 /* max size of fs superblock */
59
60struct xbsd_disklabel {
61 uint32_t d_magic; /* the magic number */
62 int16_t d_type; /* drive type */
63 int16_t d_subtype; /* controller/d_type specific */
64 char d_typename[16]; /* type name, e.g. "eagle" */
65 char d_packname[16]; /* pack identifier */
66 /* disk geometry: */
67 uint32_t d_secsize; /* # of bytes per sector */
68 uint32_t d_nsectors; /* # of data sectors per track */
69 uint32_t d_ntracks; /* # of tracks per cylinder */
70 uint32_t d_ncylinders; /* # of data cylinders per unit */
71 uint32_t d_secpercyl; /* # of data sectors per cylinder */
72 uint32_t d_secperunit; /* # of data sectors per unit */
73 /*
74 * Spares (bad sector replacements) below
75 * are not counted in d_nsectors or d_secpercyl.
76 * Spare sectors are assumed to be physical sectors
77 * which occupy space at the end of each track and/or cylinder.
78 */
79 uint16_t d_sparespertrack; /* # of spare sectors per track */
80 uint16_t d_sparespercyl; /* # of spare sectors per cylinder */
81 /*
82 * Alternate cylinders include maintenance, replacement,
83 * configuration description areas, etc.
84 */
85 uint32_t d_acylinders; /* # of alt. cylinders per unit */
86
87 /* hardware characteristics: */
88 /*
89 * d_interleave, d_trackskew and d_cylskew describe perturbations
90 * in the media format used to compensate for a slow controller.
91 * Interleave is physical sector interleave, set up by the formatter
92 * or controller when formatting. When interleaving is in use,
93 * logically adjacent sectors are not physically contiguous,
94 * but instead are separated by some number of sectors.
95 * It is specified as the ratio of physical sectors traversed
96 * per logical sector. Thus an interleave of 1:1 implies contiguous
97 * layout, while 2:1 implies that logical sector 0 is separated
98 * by one sector from logical sector 1.
99 * d_trackskew is the offset of sector 0 on track N
100 * relative to sector 0 on track N-1 on the same cylinder.
101 * Finally, d_cylskew is the offset of sector 0 on cylinder N
102 * relative to sector 0 on cylinder N-1.
103 */
104 uint16_t d_rpm; /* rotational speed */
105 uint16_t d_interleave; /* hardware sector interleave */
106 uint16_t d_trackskew; /* sector 0 skew, per track */
107 uint16_t d_cylskew; /* sector 0 skew, per cylinder */
108 uint32_t d_headswitch; /* head switch time, usec */
109 uint32_t d_trkseek; /* track-to-track seek, usec */
110 uint32_t d_flags; /* generic flags */
111#define NDDATA 5
112 uint32_t d_drivedata[NDDATA]; /* drive-type specific information */
113#define NSPARE 5
114 uint32_t d_spare[NSPARE]; /* reserved for future use */
115 uint32_t d_magic2; /* the magic number (again) */
116 uint16_t d_checksum; /* xor of data incl. partitions */
117 /* filesystem and partition information: */
118 uint16_t d_npartitions; /* number of partitions in following */
119 uint32_t d_bbsize; /* size of boot area at sn0, bytes */
120 uint32_t d_sbsize; /* max size of fs superblock, bytes */
121 struct xbsd_partition { /* the partition table */
122 uint32_t p_size; /* number of sectors in partition */
123 uint32_t p_offset; /* starting sector */
124 uint32_t p_fsize; /* filesystem basic fragment size */
125 uint8_t p_fstype; /* filesystem type, see below */
126 uint8_t p_frag; /* filesystem fragments per block */
127 uint16_t p_cpg; /* filesystem cylinders per group */
128 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
129};
130
131/* d_type values: */
132#define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
133#define BSD_DTYPE_MSCP 2 /* MSCP */
134#define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */
135#define BSD_DTYPE_SCSI 4 /* SCSI */
136#define BSD_DTYPE_ESDI 5 /* ESDI interface */
137#define BSD_DTYPE_ST506 6 /* ST506 etc. */
138#define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */
139#define BSD_DTYPE_HPFL 8 /* HP Fiber-link */
140#define BSD_DTYPE_FLOPPY 10 /* floppy */
141
142/* d_subtype values: */
143#define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */
144#define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */
145#define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */
146
147static const char *const xbsd_dktypenames[] = {
148 "unknown",
149 "SMD",
150 "MSCP",
151 "old DEC",
152 "SCSI",
153 "ESDI",
154 "ST506",
155 "HP-IB",
156 "HP-FL",
157 "type 9",
158 "floppy",
159 0
160};
161
162
163/*
164 * Filesystem type and version.
165 * Used to interpret other filesystem-specific
166 * per-partition information.
167 */
168#define BSD_FS_UNUSED 0 /* unused */
169#define BSD_FS_SWAP 1 /* swap */
170#define BSD_FS_V6 2 /* Sixth Edition */
171#define BSD_FS_V7 3 /* Seventh Edition */
172#define BSD_FS_SYSV 4 /* System V */
173#define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
174#define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */
175#define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */
176#define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */
177#define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */
178#define BSD_FS_HPFS 11 /* OS/2 high-performance file system */
179#define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */
180#define BSD_FS_ISOFS BSD_FS_ISO9660
181#define BSD_FS_BOOT 13 /* partition contains bootstrap */
182#define BSD_FS_ADOS 14 /* AmigaDOS fast file system */
183#define BSD_FS_HFS 15 /* Macintosh HFS */
184#define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */
185
186/* this is annoying, but it's also the way it is :-( */
187#ifdef __alpha__
188#define BSD_FS_EXT2 8 /* ext2 file system */
189#else
190#define BSD_FS_MSDOS 8 /* MS-DOS file system */
191#endif
192
193static const char *const xbsd_fstypes[] = {
194 "\x00" "unused", /* BSD_FS_UNUSED */
195 "\x01" "swap", /* BSD_FS_SWAP */
196 "\x02" "Version 6", /* BSD_FS_V6 */
197 "\x03" "Version 7", /* BSD_FS_V7 */
198 "\x04" "System V", /* BSD_FS_SYSV */
199 "\x05" "4.1BSD", /* BSD_FS_V71K */
200 "\x06" "Eighth Edition", /* BSD_FS_V8 */
201 "\x07" "4.2BSD", /* BSD_FS_BSDFFS */
202#ifdef __alpha__
203 "\x08" "ext2", /* BSD_FS_EXT2 */
204#else
205 "\x08" "MS-DOS", /* BSD_FS_MSDOS */
206#endif
207 "\x09" "4.4LFS", /* BSD_FS_BSDLFS */
208 "\x0a" "unknown", /* BSD_FS_OTHER */
209 "\x0b" "HPFS", /* BSD_FS_HPFS */
210 "\x0c" "ISO-9660", /* BSD_FS_ISO9660 */
211 "\x0d" "boot", /* BSD_FS_BOOT */
212 "\x0e" "ADOS", /* BSD_FS_ADOS */
213 "\x0f" "HFS", /* BSD_FS_HFS */
214 "\x10" "AdvFS", /* BSD_FS_ADVFS */
215 NULL
216};
217
218
219/*
220 * flags shared by various drives:
221 */
222#define BSD_D_REMOVABLE 0x01 /* removable media */
223#define BSD_D_ECC 0x02 /* supports ECC */
224#define BSD_D_BADSECT 0x04 /* supports bad sector forw. */
225#define BSD_D_RAMDISK 0x08 /* disk emulator */
226#define BSD_D_CHAIN 0x10 /* can do back-back transfers */
227#define BSD_D_DOSPART 0x20 /* within MSDOS partition */
228
229/*
230 Changes:
231 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
232
233 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
234 support for OSF/1 disklabels on Alpha.
235 Also fixed unaligned accesses in alpha_bootblock_checksum()
236*/
237
238#define FREEBSD_PARTITION 0xa5
239#define NETBSD_PARTITION 0xa9
240
241static void xbsd_delete_part(void);
242static void xbsd_new_part(void);
243static void xbsd_write_disklabel(void);
244static int xbsd_create_disklabel(void);
245static void xbsd_edit_disklabel(void);
246static void xbsd_write_bootstrap(void);
247static void xbsd_change_fstype(void);
248static int xbsd_get_part_index(int max);
249static int xbsd_check_new_partition(int *i);
250static void xbsd_list_types(void);
251static uint16_t xbsd_dkcksum(struct xbsd_disklabel *lp);
252static int xbsd_initlabel(struct partition *p);
253static int xbsd_readlabel(struct partition *p);
254static int xbsd_writelabel(struct partition *p);
255
256#if defined(__alpha__)
257static void alpha_bootblock_checksum(char *boot);
258#endif
259
260#if !defined(__alpha__)
261static int xbsd_translate_fstype(int linux_type);
262static void xbsd_link_part(void);
263static struct partition *xbsd_part;
264static int xbsd_part_index;
265#endif
266
267
268/* Group big globals data and allocate it in one go */
269struct bsd_globals {
270/* We access this through a uint64_t * when checksumming */
271/* hopefully xmalloc gives us required alignment */
272 char disklabelbuffer[BSD_BBSIZE];
273 struct xbsd_disklabel xbsd_dlabel;
274};
275
276static struct bsd_globals *bsd_globals_ptr;
277
278#define disklabelbuffer (bsd_globals_ptr->disklabelbuffer)
279#define xbsd_dlabel (bsd_globals_ptr->xbsd_dlabel)
280
281
282/* Code */
283
284#define bsd_cround(n) \
285 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
286
287/*
288 * Test whether the whole disk has BSD disk label magic.
289 *
290 * Note: often reformatting with DOS-type label leaves the BSD magic,
291 * so this does not mean that there is a BSD disk label.
292 */
293static int
294check_osf_label(void)
295{
296 if (xbsd_readlabel(NULL) == 0)
297 return 0;
298 return 1;
299}
300
301static int
302bsd_trydev(const char * dev)
303{
304 if (xbsd_readlabel(NULL) == 0)
305 return -1;
306 printf("\nBSD label for device: %s\n", dev);
307 xbsd_print_disklabel(0);
308 return 0;
309}
310
311static void
312bsd_menu(void)
313{
314 puts("Command Action");
315 puts("d\tdelete a BSD partition");
316 puts("e\tedit drive data");
317 puts("i\tinstall bootstrap");
318 puts("l\tlist known filesystem types");
319 puts("n\tadd a new BSD partition");
320 puts("p\tprint BSD partition table");
321 puts("q\tquit without saving changes");
322 puts("r\treturn to main menu");
323 puts("s\tshow complete disklabel");
324 puts("t\tchange a partition's filesystem id");
325 puts("u\tchange units (cylinders/sectors)");
326 puts("w\twrite disklabel to disk");
327#if !defined(__alpha__)
328 puts("x\tlink BSD partition to non-BSD partition");
329#endif
330}
331
332#if !defined(__alpha__)
333static int
334hidden(int type)
335{
336 return type ^ 0x10;
337}
338
339static int
340is_bsd_partition_type(int type)
341{
342 return (type == FREEBSD_PARTITION ||
343 type == hidden(FREEBSD_PARTITION) ||
344 type == NETBSD_PARTITION ||
345 type == hidden(NETBSD_PARTITION));
346}
347#endif
348
349static void
350bsd_select(void)
351{
352#if !defined(__alpha__)
353 int t, ss;
354 struct partition *p;
355
356 for (t = 0; t < 4; t++) {
357 p = get_part_table(t);
358 if (p && is_bsd_partition_type(p->sys_ind)) {
359 xbsd_part = p;
360 xbsd_part_index = t;
361 ss = get_start_sect(xbsd_part);
362 if (ss == 0) {
363 printf("Partition %s has invalid starting sector 0\n",
364 partname(disk_device, t+1, 0));
365 return;
366 }
367 printf("Reading disklabel of %s at sector %u\n",
368 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
369 if (xbsd_readlabel(xbsd_part) == 0) {
370 if (xbsd_create_disklabel() == 0)
371 return;
372 break;
373 }
374 }
375 }
376
377 if (t == 4) {
378 printf("There is no *BSD partition on %s\n", disk_device);
379 return;
380 }
381
382#elif defined(__alpha__)
383
384 if (xbsd_readlabel(NULL) == 0)
385 if (xbsd_create_disklabel() == 0)
386 exit(EXIT_SUCCESS);
387
388#endif
389
390 while (1) {
391 bb_putchar('\n');
392 switch (tolower(read_nonempty("BSD disklabel command (m for help): "))) {
393 case 'd':
394 xbsd_delete_part();
395 break;
396 case 'e':
397 xbsd_edit_disklabel();
398 break;
399 case 'i':
400 xbsd_write_bootstrap();
401 break;
402 case 'l':
403 xbsd_list_types();
404 break;
405 case 'n':
406 xbsd_new_part();
407 break;
408 case 'p':
409 xbsd_print_disklabel(0);
410 break;
411 case 'q':
412 if (ENABLE_FEATURE_CLEAN_UP)
413 close_dev_fd();
414 exit(EXIT_SUCCESS);
415 case 'r':
416 return;
417 case 's':
418 xbsd_print_disklabel(1);
419 break;
420 case 't':
421 xbsd_change_fstype();
422 break;
423 case 'u':
424 change_units();
425 break;
426 case 'w':
427 xbsd_write_disklabel();
428 break;
429#if !defined(__alpha__)
430 case 'x':
431 xbsd_link_part();
432 break;
433#endif
434 default:
435 bsd_menu();
436 break;
437 }
438 }
439}
440
441static void
442xbsd_delete_part(void)
443{
444 int i;
445
446 i = xbsd_get_part_index(xbsd_dlabel.d_npartitions);
447 xbsd_dlabel.d_partitions[i].p_size = 0;
448 xbsd_dlabel.d_partitions[i].p_offset = 0;
449 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
450 if (xbsd_dlabel.d_npartitions == i + 1)
451 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
452 xbsd_dlabel.d_npartitions--;
453}
454
455static void
456xbsd_new_part(void)
457{
458 off_t begin, end;
459 char mesg[256];
460 int i;
461
462 if (!xbsd_check_new_partition(&i))
463 return;
464
465#if !defined(__alpha__) && !defined(__powerpc__) && !defined(__hppa__)
466 begin = get_start_sect(xbsd_part);
467 end = begin + get_nr_sects(xbsd_part) - 1;
468#else
469 begin = 0;
470 end = xbsd_dlabel.d_secperunit - 1;
471#endif
472
473 snprintf(mesg, sizeof(mesg), "First %s", str_units(SINGULAR));
474 begin = read_int(bsd_cround(begin), bsd_cround(begin), bsd_cround(end),
475 0, mesg);
476
477 if (display_in_cyl_units)
478 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
479
480 snprintf(mesg, sizeof(mesg), "Last %s or +size or +sizeM or +sizeK",
481 str_units(SINGULAR));
482 end = read_int(bsd_cround(begin), bsd_cround(end), bsd_cround(end),
483 bsd_cround(begin), mesg);
484
485 if (display_in_cyl_units)
486 end = end * xbsd_dlabel.d_secpercyl - 1;
487
488 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
489 xbsd_dlabel.d_partitions[i].p_offset = begin;
490 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
491}
492
493static void
494xbsd_print_disklabel(int show_all)
495{
496 struct xbsd_disklabel *lp = &xbsd_dlabel;
497 struct xbsd_partition *pp;
498 int i, j;
499
500 if (show_all) {
501 static const int d_masks[] = { BSD_D_REMOVABLE, BSD_D_ECC, BSD_D_BADSECT };
502
503#if defined(__alpha__)
504 printf("# %s:\n", disk_device);
505#else
506 printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
507#endif
508 if ((unsigned) lp->d_type < ARRAY_SIZE(xbsd_dktypenames)-1)
509 printf("type: %s\n", xbsd_dktypenames[lp->d_type]);
510 else
511 printf("type: %u\n", lp->d_type);
512 printf("disk: %.*s\n", (int) sizeof(lp->d_typename), lp->d_typename);
513 printf("label: %.*s\n", (int) sizeof(lp->d_packname), lp->d_packname);
514 printf("flags: ");
515 print_flags_separated(d_masks, "removable\0""ecc\0""badsect\0", lp->d_flags, " ");
516 bb_putchar('\n');
517 /* On various machines the fields of *lp are short/int/long */
518 /* In order to avoid problems, we cast them all to long. */
519 printf("bytes/sector: %lu\n", (long) lp->d_secsize);
520 printf("sectors/track: %lu\n", (long) lp->d_nsectors);
521 printf("tracks/cylinder: %lu\n", (long) lp->d_ntracks);
522 printf("sectors/cylinder: %lu\n", (long) lp->d_secpercyl);
523 printf("cylinders: %lu\n", (long) lp->d_ncylinders);
524 printf("rpm: %u\n", lp->d_rpm);
525 printf("interleave: %u\n", lp->d_interleave);
526 printf("trackskew: %u\n", lp->d_trackskew);
527 printf("cylinderskew: %u\n", lp->d_cylskew);
528 printf("headswitch: %lu\t\t# milliseconds\n",
529 (long) lp->d_headswitch);
530 printf("track-to-track seek: %lu\t# milliseconds\n",
531 (long) lp->d_trkseek);
532 printf("drivedata: ");
533 for (i = NDDATA - 1; i >= 0; i--)
534 if (lp->d_drivedata[i])
535 break;
536 if (i < 0)
537 i = 0;
538 for (j = 0; j <= i; j++)
539 printf("%lu ", (long) lp->d_drivedata[j]);
540 }
541 printf("\n%u partitions:\n", lp->d_npartitions);
542 printf("# start end size fstype [fsize bsize cpg]\n");
543 pp = lp->d_partitions;
544 for (i = 0; i < lp->d_npartitions; i++, pp++) {
545 if (pp->p_size) {
546 if (display_in_cyl_units && lp->d_secpercyl) {
547 printf(" %c: %8lu%c %8lu%c %8lu%c ",
548 'a' + i,
549 (unsigned long) pp->p_offset / lp->d_secpercyl + 1,
550 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
551 (unsigned long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1) / lp->d_secpercyl,
552 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
553 (long) pp->p_size / lp->d_secpercyl,
554 (pp->p_size % lp->d_secpercyl) ? '*' : ' '
555 );
556 } else {
557 printf(" %c: %8lu %8lu %8lu ",
558 'a' + i,
559 (long) pp->p_offset,
560 (long) pp->p_offset + pp->p_size - 1,
561 (long) pp->p_size
562 );
563 }
564
565 if ((unsigned) pp->p_fstype < ARRAY_SIZE(xbsd_fstypes)-1)
566 printf("%8.8s", xbsd_fstypes[pp->p_fstype]);
567 else
568 printf("%8x", pp->p_fstype);
569
570 switch (pp->p_fstype) {
571 case BSD_FS_UNUSED:
572 printf(" %5lu %5lu %5.5s ",
573 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
574 break;
575 case BSD_FS_BSDFFS:
576 printf(" %5lu %5lu %5u ",
577 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, pp->p_cpg);
578 break;
579 default:
580 printf("%22.22s", "");
581 break;
582 }
583 bb_putchar('\n');
584 }
585 }
586}
587
588static void
589xbsd_write_disklabel(void)
590{
591#if defined(__alpha__)
592 printf("Writing disklabel to %s\n", disk_device);
593 xbsd_writelabel(NULL);
594#else
595 printf("Writing disklabel to %s\n",
596 partname(disk_device, xbsd_part_index + 1, 0));
597 xbsd_writelabel(xbsd_part);
598#endif
599 reread_partition_table(0); /* no exit yet */
600}
601
602static int
603xbsd_create_disklabel(void)
604{
605 char c;
606
607#if defined(__alpha__)
608 printf("%s contains no disklabel\n", disk_device);
609#else
610 printf("%s contains no disklabel\n",
611 partname(disk_device, xbsd_part_index + 1, 0));
612#endif
613
614 while (1) {
615 c = read_nonempty("Do you want to create a disklabel? (y/n) ");
616 if ((c|0x20) == 'y') {
617 if (xbsd_initlabel(
618#if defined(__alpha__) || defined(__powerpc__) || defined(__hppa__) || \
619 defined(__s390__) || defined(__s390x__)
620 NULL
621#else
622 xbsd_part
623#endif
624 ) == 1) {
625 xbsd_print_disklabel(1);
626 return 1;
627 }
628 return 0;
629 }
630 if ((c|0x20) == 'n')
631 return 0;
632 }
633}
634
635static int
636edit_int(int def, const char *mesg)
637{
638 mesg = xasprintf("%s (%u): ", mesg, def);
639 do {
640 if (!read_line(mesg))
641 goto ret;
642 } while (!isdigit(*line_ptr));
643 def = atoi(line_ptr);
644 ret:
645 free((char*)mesg);
646 return def;
647}
648
649static void
650xbsd_edit_disklabel(void)
651{
652 struct xbsd_disklabel *d;
653
654 d = &xbsd_dlabel;
655
656#if defined(__alpha__) || defined(__ia64__)
657 d->d_secsize = edit_int(d->d_secsize , "bytes/sector");
658 d->d_nsectors = edit_int(d->d_nsectors , "sectors/track");
659 d->d_ntracks = edit_int(d->d_ntracks , "tracks/cylinder");
660 d->d_ncylinders = edit_int(d->d_ncylinders , "cylinders");
661#endif
662
663 /* d->d_secpercyl can be != d->d_nsectors * d->d_ntracks */
664 while (1) {
665 d->d_secpercyl = edit_int(d->d_nsectors * d->d_ntracks,
666 "sectors/cylinder");
667 if (d->d_secpercyl <= d->d_nsectors * d->d_ntracks)
668 break;
669
670 printf("Must be <= sectors/track * tracks/cylinder (default)\n");
671 }
672 d->d_rpm = edit_int(d->d_rpm , "rpm");
673 d->d_interleave = edit_int(d->d_interleave, "interleave");
674 d->d_trackskew = edit_int(d->d_trackskew , "trackskew");
675 d->d_cylskew = edit_int(d->d_cylskew , "cylinderskew");
676 d->d_headswitch = edit_int(d->d_headswitch, "headswitch");
677 d->d_trkseek = edit_int(d->d_trkseek , "track-to-track seek");
678
679 d->d_secperunit = d->d_secpercyl * d->d_ncylinders;
680}
681
682static int
683xbsd_get_bootstrap(char *path, void *ptr, int size)
684{
685 int fdb;
686
687 fdb = open_or_warn(path, O_RDONLY);
688 if (fdb < 0) {
689 return 0;
690 }
691 if (full_read(fdb, ptr, size) < 0) {
692 bb_simple_perror_msg(path);
693 close(fdb);
694 return 0;
695 }
696 printf(" ... %s\n", path);
697 close(fdb);
698 return 1;
699}
700
701static void
702sync_disks(void)
703{
704 printf("Syncing disks\n");
705 sync();
706 /* sleep(4); What? */
707}
708
709static void
710xbsd_write_bootstrap(void)
711{
712 char path[MAXPATHLEN];
713 const char *bootdir = BSD_LINUX_BOOTDIR;
714 const char *dkbasename;
715 struct xbsd_disklabel dl;
716 char *d, *p, *e;
717 int sector;
718
719 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
720 dkbasename = "sd";
721 else
722 dkbasename = "wd";
723
724 snprintf(path, sizeof(path), "Bootstrap: %sboot -> boot%s (%s): ",
725 dkbasename, dkbasename, dkbasename);
726 if (read_line(path)) {
727 dkbasename = line_ptr;
728 }
729 snprintf(path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
730 if (!xbsd_get_bootstrap(path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
731 return;
732
733/* We need a backup of the disklabel (xbsd_dlabel might have changed). */
734 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
735 memmove(&dl, d, sizeof(struct xbsd_disklabel));
736
737/* The disklabel will be overwritten by 0's from bootxx anyway */
738 memset(d, 0, sizeof(struct xbsd_disklabel));
739
740 snprintf(path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
741 if (!xbsd_get_bootstrap(path, &disklabelbuffer[xbsd_dlabel.d_secsize],
742 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
743 return;
744
745 e = d + sizeof(struct xbsd_disklabel);
746 for (p = d; p < e; p++)
747 if (*p) {
748 printf("Bootstrap overlaps with disk label!\n");
749 exit(EXIT_FAILURE);
750 }
751
752 memmove(d, &dl, sizeof(struct xbsd_disklabel));
753
754#if defined(__powerpc__) || defined(__hppa__)
755 sector = 0;
756#elif defined(__alpha__)
757 sector = 0;
758 alpha_bootblock_checksum(disklabelbuffer);
759#else
760 sector = get_start_sect(xbsd_part);
761#endif
762
763 seek_sector(sector);
764 xwrite(dev_fd, disklabelbuffer, BSD_BBSIZE);
765
766#if defined(__alpha__)
767 printf("Bootstrap installed on %s\n", disk_device);
768#else
769 printf("Bootstrap installed on %s\n",
770 partname(disk_device, xbsd_part_index+1, 0));
771#endif
772
773 sync_disks();
774}
775
776static void
777xbsd_change_fstype(void)
778{
779 int i;
780
781 i = xbsd_get_part_index(xbsd_dlabel.d_npartitions);
782 xbsd_dlabel.d_partitions[i].p_fstype = read_hex(xbsd_fstypes);
783}
784
785static int
786xbsd_get_part_index(int max)
787{
788 char prompt[sizeof("Partition (a-%c): ") + 16];
789 char l;
790
791 snprintf(prompt, sizeof(prompt), "Partition (a-%c): ", 'a' + max - 1);
792 do
793 l = tolower(read_nonempty(prompt));
794 while (l < 'a' || l > 'a' + max - 1);
795 return l - 'a';
796}
797
798static int
799xbsd_check_new_partition(int *i)
800{
801 /* room for more? various BSD flavours have different maxima */
802 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
803 int t;
804
805 for (t = 0; t < BSD_MAXPARTITIONS; t++)
806 if (xbsd_dlabel.d_partitions[t].p_size == 0)
807 break;
808
809 if (t == BSD_MAXPARTITIONS) {
810 printf("The maximum number of partitions has been created\n");
811 return 0;
812 }
813 }
814
815 *i = xbsd_get_part_index(BSD_MAXPARTITIONS);
816
817 if (*i >= xbsd_dlabel.d_npartitions)
818 xbsd_dlabel.d_npartitions = (*i) + 1;
819
820 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
821 printf("This partition already exists\n");
822 return 0;
823 }
824
825 return 1;
826}
827
828static void
829xbsd_list_types(void)
830{
831 list_types(xbsd_fstypes);
832}
833
834static uint16_t
835xbsd_dkcksum(struct xbsd_disklabel *lp)
836{
837 uint16_t *start, *end;
838 uint16_t sum = 0;
839
840 start = (uint16_t *) lp;
841 end = (uint16_t *) &lp->d_partitions[lp->d_npartitions];
842 while (start < end)
843 sum ^= *start++;
844 return sum;
845}
846
847static int
848xbsd_initlabel(struct partition *p)
849{
850 struct xbsd_disklabel *d = &xbsd_dlabel;
851 struct xbsd_partition *pp;
852
853 get_geometry();
854 memset(d, 0, sizeof(struct xbsd_disklabel));
855
856 d->d_magic = BSD_DISKMAGIC;
857
858 if (is_prefixed_with(disk_device, "/dev/sd"))
859 d->d_type = BSD_DTYPE_SCSI;
860 else
861 d->d_type = BSD_DTYPE_ST506;
862
863#if !defined(__alpha__)
864 d->d_flags = BSD_D_DOSPART;
865#else
866 d->d_flags = 0;
867#endif
868 d->d_secsize = SECTOR_SIZE; /* bytes/sector */
869 d->d_nsectors = g_sectors; /* sectors/track */
870 d->d_ntracks = g_heads; /* tracks/cylinder (heads) */
871 d->d_ncylinders = g_cylinders;
872 d->d_secpercyl = g_sectors * g_heads;/* sectors/cylinder */
873 if (d->d_secpercyl == 0)
874 d->d_secpercyl = 1; /* avoid segfaults */
875 d->d_secperunit = d->d_secpercyl * d->d_ncylinders;
876
877 d->d_rpm = 3600;
878 d->d_interleave = 1;
879 d->d_trackskew = 0;
880 d->d_cylskew = 0;
881 d->d_headswitch = 0;
882 d->d_trkseek = 0;
883
884 d->d_magic2 = BSD_DISKMAGIC;
885 d->d_bbsize = BSD_BBSIZE;
886 d->d_sbsize = BSD_SBSIZE;
887
888#if !defined(__alpha__)
889 d->d_npartitions = 4;
890 pp = &d->d_partitions[2]; /* Partition C should be NetBSD partition */
891
892 pp->p_offset = get_start_sect(p);
893 pp->p_size = get_nr_sects(p);
894 pp->p_fstype = BSD_FS_UNUSED;
895 pp = &d->d_partitions[3]; /* Partition D should be whole disk */
896
897 pp->p_offset = 0;
898 pp->p_size = d->d_secperunit;
899 pp->p_fstype = BSD_FS_UNUSED;
900#else
901 d->d_npartitions = 3;
902 pp = &d->d_partitions[2]; /* Partition C should be the whole disk */
903 pp->p_offset = 0;
904 pp->p_size = d->d_secperunit;
905 pp->p_fstype = BSD_FS_UNUSED;
906#endif
907
908 return 1;
909}
910
911/*
912 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
913 * If it has the right magic, return 1.
914 */
915static int
916xbsd_readlabel(struct partition *p)
917{
918 struct xbsd_disklabel *d;
919 int t, sector;
920
921 if (!bsd_globals_ptr)
922 bsd_globals_ptr = xzalloc(sizeof(*bsd_globals_ptr));
923
924 d = &xbsd_dlabel;
925
926 /* p is used only to get the starting sector */
927#if !defined(__alpha__)
928 sector = (p ? get_start_sect(p) : 0);
929#else
930 sector = 0;
931#endif
932
933 seek_sector(sector);
934 if (BSD_BBSIZE != full_read(dev_fd, disklabelbuffer, BSD_BBSIZE))
935 fdisk_fatal(unable_to_read);
936
937 memmove(d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
938 sizeof(struct xbsd_disklabel));
939
940 if (d->d_magic != BSD_DISKMAGIC || d->d_magic2 != BSD_DISKMAGIC)
941 return 0;
942
943 for (t = d->d_npartitions; t < BSD_MAXPARTITIONS; t++) {
944 d->d_partitions[t].p_size = 0;
945 d->d_partitions[t].p_offset = 0;
946 d->d_partitions[t].p_fstype = BSD_FS_UNUSED;
947 }
948
949 if (d->d_npartitions > BSD_MAXPARTITIONS)
950 printf("Warning: too many partitions (%u, maximum is %u)\n",
951 d->d_npartitions, BSD_MAXPARTITIONS);
952 return 1;
953}
954
955static int
956xbsd_writelabel(struct partition *p)
957{
958 struct xbsd_disklabel *d = &xbsd_dlabel;
959 unsigned int sector;
960
961#if !defined(__alpha__) && !defined(__powerpc__) && !defined(__hppa__)
962 sector = get_start_sect(p) + BSD_LABELSECTOR;
963#else
964 (void)p; /* silence warning */
965 sector = BSD_LABELSECTOR;
966#endif
967
968 d->d_checksum = 0;
969 d->d_checksum = xbsd_dkcksum(d);
970
971 /* This is necessary if we want to write the bootstrap later,
972 otherwise we'd write the old disklabel with the bootstrap.
973 */
974 memmove(&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
975 d, sizeof(struct xbsd_disklabel));
976
977#if defined(__alpha__) && BSD_LABELSECTOR == 0
978 alpha_bootblock_checksum(disklabelbuffer);
979 seek_sector(0);
980 xwrite(dev_fd, disklabelbuffer, BSD_BBSIZE);
981#else
982 seek_sector(sector);
983 lseek(dev_fd, BSD_LABELOFFSET, SEEK_CUR);
984 xwrite(dev_fd, d, sizeof(*d));
985#endif
986 sync_disks();
987 return 1;
988}
989
990
991#if !defined(__alpha__)
992static int
993xbsd_translate_fstype(int linux_type)
994{
995 switch (linux_type) {
996 case 0x01: /* DOS 12-bit FAT */
997 case 0x04: /* DOS 16-bit <32M */
998 case 0x06: /* DOS 16-bit >=32M */
999 case 0xe1: /* DOS access */
1000 case 0xe3: /* DOS R/O */
1001 case 0xf2: /* DOS secondary */
1002 return BSD_FS_MSDOS;
1003 case 0x07: /* OS/2 HPFS */
1004 return BSD_FS_HPFS;
1005 default:
1006 return BSD_FS_OTHER;
1007 }
1008}
1009
1010static void
1011xbsd_link_part(void)
1012{
1013 int k, i;
1014 struct partition *p;
1015
1016 k = get_partition(1, g_partitions);
1017
1018 if (!xbsd_check_new_partition(&i))
1019 return;
1020
1021 p = get_part_table(k);
1022
1023 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
1024 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
1025 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
1026}
1027#endif
1028
1029#if defined(__alpha__)
1030static void
1031alpha_bootblock_checksum(char *boot)
1032{
1033 uint64_t *dp, sum;
1034 int i;
1035
1036 dp = (uint64_t *)boot;
1037 sum = 0;
1038 for (i = 0; i < 63; i++)
1039 sum += dp[i];
1040 dp[63] = sum;
1041}
1042#endif /* __alpha__ */
1043
1044/* Undefine 'global' tricks */
1045#undef disklabelbuffer
1046#undef xbsd_dlabel
1047
1048#endif /* OSF_LABEL */
Note: See TracBrowser for help on using the repository browser.