Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/util-linux/fdisk_osf.c

Parent Directory Parent Directory | Revision Log Revision Log


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