]> git.ipfire.org Git - thirdparty/util-linux.git/blame - fdisk/fdiskbsdlabel.c
tests: fix compiler warnings [-Wunused-parameter]
[thirdparty/util-linux.git] / fdisk / fdiskbsdlabel.c
CommitLineData
726f69e2
KZ
1/*
2 NetBSD disklabel editor for Linux fdisk
3 Written by Bernhard Fastenrath (fasten@informatik.uni-bonn.de)
4 with code from the NetBSD disklabel command:
5
6 Copyright (c) 1987, 1988 Regents of the University of California.
7 All rights reserved.
8
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions
11 are met:
12 1. Redistributions of source code must retain the above copyright
13 notice, this list of conditions and the following disclaimer.
14 2. Redistributions in binary form must reproduce the above copyright
15 notice, this list of conditions and the following disclaimer in the
16 documentation and/or other materials provided with the distribution.
17 3. All advertising materials mentioning features or use of this software
18 must display the following acknowledgement:
19 This product includes software developed by the University of
20 California, Berkeley and its contributors.
21 4. Neither the name of the University nor the names of its contributors
22 may be used to endorse or promote products derived from this software
23 without specific prior written permission.
24
25 THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 SUCH DAMAGE.
7eda085c
KZ
36
37 Changes:
38 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
22853e4a
KZ
39
40 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
63cccae4
KZ
41 support for OSF/1 disklabels on Alpha.
42 Also fixed unaligned accesses in alpha_bootblock_checksum()
726f69e2
KZ
43*/
44
45#include <unistd.h>
46#include <stdio.h>
47#include <stdlib.h>
48#include <string.h>
49#include <fcntl.h>
50#include <ctype.h>
51#include <setjmp.h>
52#include <errno.h>
7eda085c 53#include "nls.h"
726f69e2 54
726f69e2
KZ
55#include <sys/param.h>
56
7eda085c 57#include "common.h"
726f69e2 58#include "fdisk.h"
e8f26419
KZ
59#define FREEBSD_PARTITION 0xa5
60#define NETBSD_PARTITION 0xa9
726f69e2 61#define DKTYPENAMES
5c36a0eb 62#include "fdiskbsdlabel.h"
726f69e2 63
fd6b7a7f
KZ
64static void xbsd_delete_part (void);
65static void xbsd_new_part (void);
fd6b7a7f
KZ
66static void xbsd_write_disklabel (void);
67static int xbsd_create_disklabel (void);
68static void xbsd_edit_disklabel (void);
69static void xbsd_write_bootstrap (void);
70static void xbsd_change_fstype (void);
71static int xbsd_get_part_index (int max);
72static int xbsd_check_new_partition (int *i);
73static void xbsd_list_types (void);
95961ee2 74static unsigned short xbsd_dkcksum (struct xbsd_disklabel *lp);
63cccae4
KZ
75static int xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d,
76 int pindex);
fd6b7a7f
KZ
77static int xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d);
78static int xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d);
726f69e2 79static void sync_disks (void);
22853e4a 80
726f69e2
KZ
81#if defined (__alpha__)
82void alpha_bootblock_checksum (char *boot);
83#endif
84
22853e4a
KZ
85#if !defined (__alpha__)
86static int xbsd_translate_fstype (int linux_type);
87static void xbsd_link_part (void);
fd6b7a7f
KZ
88static struct partition *xbsd_part;
89static int xbsd_part_index;
726f69e2
KZ
90#endif
91
22853e4a
KZ
92#if defined (__alpha__)
93/* We access this through a u_int64_t * when checksumming */
94static char disklabelbuffer[BSD_BBSIZE] __attribute__((aligned(8)));
95#else
96static char disklabelbuffer[BSD_BBSIZE];
97#endif
98
99static struct xbsd_disklabel xbsd_dlabel;
100
101#define bsd_cround(n) \
102 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
103
63cccae4
KZ
104/*
105 * Test whether the whole disk has BSD disk label magic.
106 *
107 * Note: often reformatting with DOS-type label leaves the BSD magic,
108 * so this does not mean that there is a BSD disk label.
109 */
22853e4a
KZ
110int
111check_osf_label(void) {
63cccae4
KZ
112 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
113 return 0;
114 return 1;
22853e4a
KZ
115}
116
2b6fc908 117int
fd6b7a7f 118btrydev (char * dev) {
63cccae4
KZ
119 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
120 return -1;
121 printf(_("\nBSD label for device: %s\n"), dev);
122 xbsd_print_disklabel (0);
123 return 0;
fd6b7a7f
KZ
124}
125
22853e4a
KZ
126static void
127bmenu (void) {
7eda085c
KZ
128 puts (_("Command action"));
129 puts (_(" d delete a BSD partition"));
130 puts (_(" e edit drive data"));
131 puts (_(" i install bootstrap"));
132 puts (_(" l list known filesystem types"));
133 puts (_(" m print this menu"));
134 puts (_(" n add a new BSD partition"));
135 puts (_(" p print BSD partition table"));
136 puts (_(" q quit without saving changes"));
7eda085c 137 puts (_(" r return to main menu"));
7eda085c
KZ
138 puts (_(" s show complete disklabel"));
139 puts (_(" t change a partition's filesystem id"));
22853e4a 140 puts (_(" u change units (cylinders/sectors)"));
7eda085c 141 puts (_(" w write disklabel to disk"));
22853e4a 142#if !defined (__alpha__)
7eda085c 143 puts (_(" x link BSD partition to non-BSD partition"));
726f69e2 144#endif
726f69e2
KZ
145}
146
22853e4a
KZ
147#if !defined (__alpha__)
148static int
5c36a0eb
KZ
149hidden(int type) {
150 return type ^ 0x10;
151}
152
22853e4a 153static int
e8f26419
KZ
154is_bsd_partition_type(int type) {
155 return (type == FREEBSD_PARTITION ||
156 type == hidden(FREEBSD_PARTITION) ||
157 type == NETBSD_PARTITION ||
158 type == hidden(NETBSD_PARTITION));
5c36a0eb 159}
22853e4a 160#endif
5c36a0eb 161
726f69e2 162void
5c36a0eb 163bselect (void) {
22853e4a 164#if !defined (__alpha__)
2b6fc908 165 int t, ss;
22853e4a 166 struct partition *p;
726f69e2 167
22853e4a
KZ
168 for (t=0; t<4; t++) {
169 p = get_part_table(t);
e8f26419 170 if (p && is_bsd_partition_type(p->sys_ind)) {
22853e4a 171 xbsd_part = p;
fd6b7a7f 172 xbsd_part_index = t;
2b6fc908 173 ss = get_start_sect(xbsd_part);
5c36a0eb 174 if (ss == 0) {
22853e4a
KZ
175 fprintf (stderr, _("Partition %s has invalid starting sector 0.\n"),
176 partname(disk_device, t+1, 0));
177 return;
726f69e2 178 }
22853e4a
KZ
179 printf (_("Reading disklabel of %s at sector %d.\n"),
180 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
fd6b7a7f 181 if (xbsd_readlabel (xbsd_part, &xbsd_dlabel) == 0)
22853e4a 182 if (xbsd_create_disklabel () == 0)
726f69e2
KZ
183 return;
184 break;
185 }
22853e4a 186 }
726f69e2 187
5c36a0eb 188 if (t == 4) {
7eda085c 189 printf (_("There is no *BSD partition on %s.\n"), disk_device);
726f69e2
KZ
190 return;
191 }
192
193#elif defined (__alpha__)
194
fd6b7a7f
KZ
195 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
196 if (xbsd_create_disklabel () == 0)
726f69e2
KZ
197 exit ( EXIT_SUCCESS );
198
199#endif
200
22853e4a 201 while (1) {
726f69e2 202 putchar ('\n');
22853e4a 203 switch (tolower (read_char (_("BSD disklabel command (m for help): ")))) {
726f69e2 204 case 'd':
22853e4a 205 xbsd_delete_part ();
726f69e2
KZ
206 break;
207 case 'e':
22853e4a 208 xbsd_edit_disklabel ();
726f69e2
KZ
209 break;
210 case 'i':
22853e4a 211 xbsd_write_bootstrap ();
726f69e2
KZ
212 break;
213 case 'l':
22853e4a 214 xbsd_list_types ();
726f69e2
KZ
215 break;
216 case 'n':
fd6b7a7f 217 xbsd_new_part ();
726f69e2
KZ
218 break;
219 case 'p':
fd6b7a7f 220 xbsd_print_disklabel (0);
726f69e2
KZ
221 break;
222 case 'q':
223 close (fd);
224 exit ( EXIT_SUCCESS );
22853e4a
KZ
225 case 'r':
226 return;
726f69e2 227 case 's':
fd6b7a7f 228 xbsd_print_disklabel (1);
726f69e2
KZ
229 break;
230 case 't':
22853e4a
KZ
231 xbsd_change_fstype ();
232 break;
233 case 'u':
234 change_units();
726f69e2
KZ
235 break;
236 case 'w':
fd6b7a7f 237 xbsd_write_disklabel ();
726f69e2 238 break;
22853e4a 239#if !defined (__alpha__)
726f69e2 240 case 'x':
fd6b7a7f 241 xbsd_link_part ();
726f69e2
KZ
242 break;
243#endif
244 default:
245 bmenu ();
246 break;
247 }
248 }
249}
250
251static void
fd6b7a7f 252xbsd_delete_part (void)
726f69e2
KZ
253{
254 int i;
255
fd6b7a7f
KZ
256 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
257 xbsd_dlabel.d_partitions[i].p_size = 0;
258 xbsd_dlabel.d_partitions[i].p_offset = 0;
22853e4a 259 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
fd6b7a7f
KZ
260 if (xbsd_dlabel.d_npartitions == i + 1)
261 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
262 xbsd_dlabel.d_npartitions--;
726f69e2
KZ
263}
264
265static void
fd6b7a7f 266xbsd_new_part (void)
726f69e2 267{
df1dddf9 268 unsigned int begin, end;
eb63b9b8 269 char mesg[256];
726f69e2
KZ
270 int i;
271
fd6b7a7f 272 if (!xbsd_check_new_partition (&i))
726f69e2
KZ
273 return;
274
364cda48 275#if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
2b6fc908
KZ
276 begin = get_start_sect(xbsd_part);
277 end = begin + get_nr_sects(xbsd_part) - 1;
364cda48 278#else
726f69e2 279 begin = 0;
eb63b9b8 280 end = xbsd_dlabel.d_secperunit - 1;
726f69e2
KZ
281#endif
282
c07ebfa1 283 snprintf (mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
22853e4a 284 begin = read_int (bsd_cround (begin), bsd_cround (begin), bsd_cround (end),
5c36a0eb 285 0, mesg);
726f69e2 286
eb63b9b8 287 if (display_in_cyl_units)
22853e4a 288 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
eb63b9b8 289
c07ebfa1 290 snprintf (mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
eb63b9b8 291 str_units(SINGULAR));
22853e4a
KZ
292 end = read_int (bsd_cround (begin), bsd_cround (end), bsd_cround (end),
293 bsd_cround (begin), mesg);
726f69e2 294
7eda085c 295 if (display_in_cyl_units)
22853e4a 296 end = end * xbsd_dlabel.d_secpercyl - 1;
eb63b9b8 297
fd6b7a7f
KZ
298 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
299 xbsd_dlabel.d_partitions[i].p_offset = begin;
22853e4a 300 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
726f69e2
KZ
301}
302
22853e4a
KZ
303void
304xbsd_print_disklabel (int show_all) {
fd6b7a7f
KZ
305 struct xbsd_disklabel *lp = &xbsd_dlabel;
306 struct xbsd_partition *pp;
726f69e2
KZ
307 FILE *f = stdout;
308 int i, j;
309
22853e4a
KZ
310 if (show_all) {
311#if defined (__alpha__)
726f69e2 312 fprintf(f, "# %s:\n", disk_device);
22853e4a
KZ
313#else
314 fprintf(f, "# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
726f69e2
KZ
315#endif
316 if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
7eda085c 317 fprintf(f, _("type: %s\n"), xbsd_dktypenames[lp->d_type]);
726f69e2 318 else
7eda085c
KZ
319 fprintf(f, _("type: %d\n"), lp->d_type);
320 fprintf(f, _("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
321 fprintf(f, _("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
322 fprintf(f, _("flags:"));
726f69e2 323 if (lp->d_flags & BSD_D_REMOVABLE)
7eda085c 324 fprintf(f, _(" removable"));
726f69e2 325 if (lp->d_flags & BSD_D_ECC)
7eda085c 326 fprintf(f, _(" ecc"));
726f69e2 327 if (lp->d_flags & BSD_D_BADSECT)
7eda085c 328 fprintf(f, _(" badsect"));
726f69e2 329 fprintf(f, "\n");
fd6b7a7f
KZ
330 /* On various machines the fields of *lp are short/int/long */
331 /* In order to avoid problems, we cast them all to long. */
7eda085c
KZ
332 fprintf(f, _("bytes/sector: %ld\n"), (long) lp->d_secsize);
333 fprintf(f, _("sectors/track: %ld\n"), (long) lp->d_nsectors);
334 fprintf(f, _("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
335 fprintf(f, _("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
336 fprintf(f, _("cylinders: %ld\n"), (long) lp->d_ncylinders);
337 fprintf(f, _("rpm: %d\n"), lp->d_rpm);
338 fprintf(f, _("interleave: %d\n"), lp->d_interleave);
339 fprintf(f, _("trackskew: %d\n"), lp->d_trackskew);
340 fprintf(f, _("cylinderskew: %d\n"), lp->d_cylskew);
22853e4a
KZ
341 fprintf(f, _("headswitch: %ld\t\t# milliseconds\n"),
342 (long) lp->d_headswitch);
343 fprintf(f, _("track-to-track seek: %ld\t# milliseconds\n"),
344 (long) lp->d_trkseek);
7eda085c 345 fprintf(f, _("drivedata: "));
726f69e2
KZ
346 for (i = NDDATA - 1; i >= 0; i--)
347 if (lp->d_drivedata[i])
348 break;
349 if (i < 0)
350 i = 0;
351 for (j = 0; j <= i; j++)
fd6b7a7f 352 fprintf(f, "%ld ", (long) lp->d_drivedata[j]);
726f69e2 353 }
7eda085c 354 fprintf (f, _("\n%d partitions:\n"), lp->d_npartitions);
22853e4a 355 fprintf (f, _("# start end size fstype [fsize bsize cpg]\n"));
726f69e2
KZ
356 pp = lp->d_partitions;
357 for (i = 0; i < lp->d_npartitions; i++, pp++) {
358 if (pp->p_size) {
22853e4a
KZ
359 if (display_in_cyl_units && lp->d_secpercyl) {
360 fprintf(f, " %c: %8ld%c %8ld%c %8ld%c ",
361 'a' + i,
362 (long) pp->p_offset / lp->d_secpercyl + 1,
363 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
364 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1)
365 / lp->d_secpercyl,
366 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
367 (long) pp->p_size / lp->d_secpercyl,
368 (pp->p_size % lp->d_secpercyl) ? '*' : ' ');
369 } else {
370 fprintf(f, " %c: %8ld %8ld %8ld ",
371 'a' + i,
372 (long) pp->p_offset,
373 (long) pp->p_offset + pp->p_size - 1,
374 (long) pp->p_size);
375 }
726f69e2 376 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
fd6b7a7f 377 fprintf(f, "%8.8s", xbsd_fstypes[pp->p_fstype].name);
726f69e2
KZ
378 else
379 fprintf(f, "%8x", pp->p_fstype);
22853e4a
KZ
380 switch (pp->p_fstype) {
381 case BSD_FS_UNUSED:
fd6b7a7f
KZ
382 fprintf(f, " %5ld %5ld %5.5s ",
383 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
726f69e2
KZ
384 break;
385
386 case BSD_FS_BSDFFS:
fd6b7a7f
KZ
387 fprintf(f, " %5ld %5ld %5d ",
388 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag,
726f69e2
KZ
389 pp->p_cpg);
390 break;
391
392 default:
22853e4a 393 fprintf(f, "%22.22s", "");
726f69e2
KZ
394 break;
395 }
22853e4a 396 fprintf(f, "\n");
726f69e2
KZ
397 }
398 }
399}
400
401static void
22853e4a
KZ
402xbsd_write_disklabel (void) {
403#if defined (__alpha__)
404 printf (_("Writing disklabel to %s.\n"), disk_device);
405 xbsd_writelabel (NULL, &xbsd_dlabel);
406#else
407 printf (_("Writing disklabel to %s.\n"),
408 partname(disk_device, xbsd_part_index+1, 0));
409 xbsd_writelabel (xbsd_part, &xbsd_dlabel);
726f69e2 410#endif
22853e4a 411 reread_partition_table(0); /* no exit yet */
726f69e2
KZ
412}
413
414static int
22853e4a
KZ
415xbsd_create_disklabel (void) {
416 char c;
726f69e2 417
22853e4a
KZ
418#if defined (__alpha__)
419 fprintf (stderr, _("%s contains no disklabel.\n"), disk_device);
420#else
421 fprintf (stderr, _("%s contains no disklabel.\n"),
422 partname(disk_device, xbsd_part_index+1, 0));
726f69e2
KZ
423#endif
424
22853e4a
KZ
425 while (1) {
426 c = read_char (_("Do you want to create a disklabel? (y/n) "));
427 if (tolower(c) == 'y') {
428 if (xbsd_initlabel (
95f1bdee
KZ
429#if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
430 defined (__s390__) || defined (__s390x__)
22853e4a
KZ
431 NULL, &xbsd_dlabel, 0
432#else
433 xbsd_part, &xbsd_dlabel, xbsd_part_index
726f69e2 434#endif
22853e4a
KZ
435 ) == 1) {
436 xbsd_print_disklabel (1);
437 return 1;
438 } else
439 return 0;
440 } else if (c == 'n')
441 return 0;
442 }
726f69e2
KZ
443}
444
445static int
446edit_int (int def, char *mesg)
447{
448 do {
449 fputs (mesg, stdout);
450 printf (" (%d): ", def);
8feb31e5 451 if (!read_line (NULL))
726f69e2
KZ
452 return def;
453 }
454 while (!isdigit (*line_ptr));
455 return atoi (line_ptr);
456}
457
458static void
fd6b7a7f 459xbsd_edit_disklabel (void)
726f69e2 460{
fd6b7a7f 461 struct xbsd_disklabel *d;
726f69e2 462
fd6b7a7f 463 d = &xbsd_dlabel;
726f69e2 464
22853e4a 465#if defined (__alpha__) || defined (__ia64__)
95961ee2
JW
466 d -> d_secsize = (unsigned long) edit_int ((unsigned long) d -> d_secsize ,_("bytes/sector"));
467 d -> d_nsectors = (unsigned long) edit_int ((unsigned long) d -> d_nsectors ,_("sectors/track"));
468 d -> d_ntracks = (unsigned long) edit_int ((unsigned long) d -> d_ntracks ,_("tracks/cylinder"));
469 d -> d_ncylinders = (unsigned long) edit_int ((unsigned long) d -> d_ncylinders ,_("cylinders"));
726f69e2
KZ
470#endif
471
472 /* d -> d_secpercyl can be != d -> d_nsectors * d -> d_ntracks */
473 while (1)
474 {
95961ee2 475 d -> d_secpercyl = (unsigned long) edit_int ((unsigned long) d -> d_nsectors * d -> d_ntracks,
7eda085c 476 _("sectors/cylinder"));
726f69e2
KZ
477 if (d -> d_secpercyl <= d -> d_nsectors * d -> d_ntracks)
478 break;
479
7eda085c 480 printf (_("Must be <= sectors/track * tracks/cylinder (default).\n"));
726f69e2 481 }
95961ee2
JW
482 d -> d_rpm = (unsigned short) edit_int ((unsigned short) d -> d_rpm ,_("rpm"));
483 d -> d_interleave = (unsigned short) edit_int ((unsigned short) d -> d_interleave,_("interleave"));
484 d -> d_trackskew = (unsigned short) edit_int ((unsigned short) d -> d_trackskew ,_("trackskew"));
485 d -> d_cylskew = (unsigned short) edit_int ((unsigned short) d -> d_cylskew ,_("cylinderskew"));
486 d -> d_headswitch = (unsigned long) edit_int ((unsigned long) d -> d_headswitch ,_("headswitch"));
487 d -> d_trkseek = (unsigned long) edit_int ((unsigned long) d -> d_trkseek ,_("track-to-track seek"));
726f69e2
KZ
488
489 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
490}
491
492static int
fd6b7a7f 493xbsd_get_bootstrap (char *path, void *ptr, int size)
726f69e2
KZ
494{
495 int fd;
496
497 if ((fd = open (path, O_RDONLY)) < 0)
498 {
499 perror (path);
500 return 0;
501 }
502 if (read (fd, ptr, size) < 0)
503 {
504 perror (path);
505 close (fd);
506 return 0;
507 }
508 printf (" ... %s\n", path);
509 close (fd);
510 return 1;
511}
512
513static void
fd6b7a7f 514xbsd_write_bootstrap (void)
726f69e2
KZ
515{
516 char *bootdir = BSD_LINUX_BOOTDIR;
7e5fad47 517 char path[sizeof(BSD_LINUX_BOOTDIR) + 1 + 2 + 4]; /* BSD_LINUX_BOOTDIR + / + {sd,wd} + boot */
726f69e2 518 char *dkbasename;
fd6b7a7f 519 struct xbsd_disklabel dl;
726f69e2
KZ
520 char *d, *p, *e;
521 int sector;
522
fd6b7a7f 523 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
726f69e2
KZ
524 dkbasename = "sd";
525 else
526 dkbasename = "wd";
527
c07ebfa1
KZ
528 printf (_("Bootstrap: %sboot -> boot%s (%s): "),
529 dkbasename, dkbasename, dkbasename);
8feb31e5 530 if (read_line (NULL)) {
726f69e2
KZ
531 line_ptr[strlen (line_ptr)-1] = '\0';
532 dkbasename = line_ptr;
533 }
c07ebfa1 534 snprintf (path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
22853e4a 535 if (!xbsd_get_bootstrap (path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
726f69e2
KZ
536 return;
537
fd6b7a7f 538 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
22853e4a 539 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
c0f19ccf 540 memmove (&dl, d, sizeof (struct xbsd_disklabel));
726f69e2
KZ
541
542 /* The disklabel will be overwritten by 0's from bootxx anyway */
56054a79 543 memset (d, 0, sizeof (struct xbsd_disklabel));
726f69e2 544
c07ebfa1 545 snprintf (path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
22853e4a 546 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
fd6b7a7f 547 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
726f69e2
KZ
548 return;
549
fd6b7a7f 550 e = d + sizeof (struct xbsd_disklabel);
726f69e2 551 for (p=d; p < e; p++)
c07ebfa1 552 if (*p) {
7eda085c 553 fprintf (stderr, _("Bootstrap overlaps with disk label!\n"));
726f69e2
KZ
554 exit ( EXIT_FAILURE );
555 }
556
c0f19ccf 557 memmove (d, &dl, sizeof (struct xbsd_disklabel));
726f69e2 558
364cda48 559#if defined (__powerpc__) || defined (__hppa__)
5c36a0eb 560 sector = 0;
726f69e2
KZ
561#elif defined (__alpha__)
562 sector = 0;
22853e4a
KZ
563 alpha_bootblock_checksum (disklabelbuffer);
564#else
565 sector = get_start_sect(xbsd_part);
726f69e2
KZ
566#endif
567
cf6d7fae 568 if (lseek (fd, (off_t) sector * SECTOR_SIZE, SEEK_SET) == -1)
726f69e2 569 fatal (unable_to_seek);
22853e4a 570 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
726f69e2
KZ
571 fatal (unable_to_write);
572
22853e4a 573#if defined (__alpha__)
7eda085c 574 printf (_("Bootstrap installed on %s.\n"), disk_device);
22853e4a
KZ
575#else
576 printf (_("Bootstrap installed on %s.\n"),
577 partname (disk_device, xbsd_part_index+1, 0));
726f69e2
KZ
578#endif
579
580 sync_disks ();
581}
582
583static void
fd6b7a7f 584xbsd_change_fstype (void)
726f69e2
KZ
585{
586 int i;
587
fd6b7a7f 588 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
2b6fc908 589 xbsd_dlabel.d_partitions[i].p_fstype = read_hex (xbsd_fstypes);
726f69e2
KZ
590}
591
592static int
fd6b7a7f 593xbsd_get_part_index (int max)
726f69e2 594{
eb63b9b8 595 char prompt[256];
726f69e2
KZ
596 char l;
597
c07ebfa1 598 snprintf (prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
726f69e2
KZ
599 do
600 l = tolower (read_char (prompt));
601 while (l < 'a' || l > 'a' + max - 1);
602 return l - 'a';
603}
604
605static int
63cccae4 606xbsd_check_new_partition (int *i) {
726f69e2 607
63cccae4
KZ
608 /* room for more? various BSD flavours have different maxima */
609 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
610 int t;
726f69e2 611
63cccae4
KZ
612 for (t = 0; t < BSD_MAXPARTITIONS; t++)
613 if (xbsd_dlabel.d_partitions[t].p_size == 0)
614 break;
726f69e2 615
63cccae4
KZ
616 if (t == BSD_MAXPARTITIONS) {
617 fprintf (stderr, _("The maximum number of partitions "
618 "has been created\n"));
619 return 0;
620 }
621 }
726f69e2 622
63cccae4
KZ
623 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
624
625 if (*i >= xbsd_dlabel.d_npartitions)
626 xbsd_dlabel.d_npartitions = (*i) + 1;
627
628 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
629 fprintf (stderr, _("This partition already exists.\n"));
630 return 0;
631 }
632
633 return 1;
726f69e2
KZ
634}
635
636static void
63cccae4
KZ
637xbsd_list_types (void) {
638 list_types (xbsd_fstypes);
726f69e2
KZ
639}
640
95961ee2 641static unsigned short
63cccae4 642xbsd_dkcksum (struct xbsd_disklabel *lp) {
95961ee2
JW
643 unsigned short *start, *end;
644 unsigned short sum = 0;
726f69e2 645
95961ee2
JW
646 start = (unsigned short *) lp;
647 end = (unsigned short *) &lp->d_partitions[lp->d_npartitions];
63cccae4
KZ
648 while (start < end)
649 sum ^= *start++;
650 return sum;
726f69e2
KZ
651}
652
653static int
63cccae4
KZ
654xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex) {
655 struct xbsd_partition *pp;
656 struct geom g;
726f69e2 657
63cccae4 658 get_geometry (fd, &g);
56054a79 659 memset (d, 0, sizeof (struct xbsd_disklabel));
726f69e2 660
63cccae4 661 d -> d_magic = BSD_DISKMAGIC;
726f69e2 662
63cccae4
KZ
663 if (strncmp (disk_device, "/dev/sd", 7) == 0)
664 d -> d_type = BSD_DTYPE_SCSI;
665 else
666 d -> d_type = BSD_DTYPE_ST506;
726f69e2
KZ
667
668#if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
63cccae4 669 d -> d_subtype = BSD_DSTYPE_INDOSPART & pindex;
726f69e2
KZ
670#endif
671
22853e4a 672#if !defined (__alpha__)
63cccae4 673 d -> d_flags = BSD_D_DOSPART;
726f69e2 674#else
63cccae4 675 d -> d_flags = 0;
726f69e2 676#endif
63cccae4
KZ
677 d -> d_secsize = SECTOR_SIZE; /* bytes/sector */
678 d -> d_nsectors = g.sectors; /* sectors/track */
679 d -> d_ntracks = g.heads; /* tracks/cylinder (heads) */
680 d -> d_ncylinders = g.cylinders;
681 d -> d_secpercyl = g.sectors * g.heads;/* sectors/cylinder */
682 if (d -> d_secpercyl == 0)
683 d -> d_secpercyl = 1; /* avoid segfaults */
684 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
685
686 d -> d_rpm = 3600;
687 d -> d_interleave = 1;
688 d -> d_trackskew = 0;
689 d -> d_cylskew = 0;
690 d -> d_headswitch = 0;
691 d -> d_trkseek = 0;
692
693 d -> d_magic2 = BSD_DISKMAGIC;
694 d -> d_bbsize = BSD_BBSIZE;
695 d -> d_sbsize = BSD_SBSIZE;
726f69e2 696
22853e4a 697#if !defined (__alpha__)
63cccae4
KZ
698 d -> d_npartitions = 4;
699 pp = &d -> d_partitions[2]; /* Partition C should be
700 the NetBSD partition */
701 pp -> p_offset = get_start_sect(p);
702 pp -> p_size = get_nr_sects(p);
703 pp -> p_fstype = BSD_FS_UNUSED;
704 pp = &d -> d_partitions[3]; /* Partition D should be
705 the whole disk */
706 pp -> p_offset = 0;
707 pp -> p_size = d -> d_secperunit;
708 pp -> p_fstype = BSD_FS_UNUSED;
726f69e2 709#elif defined (__alpha__)
63cccae4
KZ
710 d -> d_npartitions = 3;
711 pp = &d -> d_partitions[2]; /* Partition C should be
712 the whole disk */
713 pp -> p_offset = 0;
714 pp -> p_size = d -> d_secperunit;
715 pp -> p_fstype = BSD_FS_UNUSED;
726f69e2
KZ
716#endif
717
63cccae4 718 return 1;
726f69e2
KZ
719}
720
63cccae4
KZ
721/*
722 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
723 * If it has the right magic, return 1.
724 */
726f69e2 725static int
fd6b7a7f 726xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
726f69e2 727{
63cccae4 728 int t, sector;
726f69e2 729
63cccae4 730 /* p is used only to get the starting sector */
22853e4a 731#if !defined (__alpha__)
63cccae4 732 sector = (p ? get_start_sect(p) : 0);
726f69e2 733#elif defined (__alpha__)
63cccae4 734 sector = 0;
726f69e2
KZ
735#endif
736
cf6d7fae 737 if (lseek (fd, (off_t) sector * SECTOR_SIZE, SEEK_SET) == -1)
63cccae4
KZ
738 fatal (unable_to_seek);
739 if (BSD_BBSIZE != read (fd, disklabelbuffer, BSD_BBSIZE))
740 fatal (unable_to_read);
726f69e2 741
c0f19ccf
DM
742 memmove (d,
743 &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
744 sizeof (struct xbsd_disklabel));
726f69e2 745
63cccae4
KZ
746 if (d -> d_magic != BSD_DISKMAGIC || d -> d_magic2 != BSD_DISKMAGIC)
747 return 0;
726f69e2 748
63cccae4
KZ
749 for (t = d -> d_npartitions; t < BSD_MAXPARTITIONS; t++) {
750 d -> d_partitions[t].p_size = 0;
751 d -> d_partitions[t].p_offset = 0;
752 d -> d_partitions[t].p_fstype = BSD_FS_UNUSED;
753 }
754
755 if (d -> d_npartitions > BSD_MAXPARTITIONS)
756 fprintf (stderr, _("Warning: too many partitions "
757 "(%d, maximum is %d).\n"),
758 d -> d_npartitions, BSD_MAXPARTITIONS);
759 return 1;
726f69e2
KZ
760}
761
762static int
fd6b7a7f 763xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
726f69e2 764{
df1dddf9 765 unsigned int sector;
726f69e2 766
364cda48 767#if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
2b6fc908 768 sector = get_start_sect(p) + BSD_LABELSECTOR;
364cda48 769#else
726f69e2
KZ
770 sector = BSD_LABELSECTOR;
771#endif
772
773 d -> d_checksum = 0;
fd6b7a7f 774 d -> d_checksum = xbsd_dkcksum (d);
726f69e2
KZ
775
776 /* This is necessary if we want to write the bootstrap later,
777 otherwise we'd write the old disklabel with the bootstrap.
778 */
c0f19ccf
DM
779 memmove (&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET], d,
780 sizeof (struct xbsd_disklabel));
726f69e2
KZ
781
782#if defined (__alpha__) && BSD_LABELSECTOR == 0
22853e4a 783 alpha_bootblock_checksum (disklabelbuffer);
cf6d7fae 784 if (lseek (fd, (off_t) 0, SEEK_SET) == -1)
726f69e2 785 fatal (unable_to_seek);
22853e4a 786 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
726f69e2
KZ
787 fatal (unable_to_write);
788#else
cf6d7fae 789 if (lseek (fd, (off_t) sector * SECTOR_SIZE + BSD_LABELOFFSET,
22853e4a 790 SEEK_SET) == -1)
726f69e2 791 fatal (unable_to_seek);
fd6b7a7f 792 if (sizeof (struct xbsd_disklabel) != write (fd, d, sizeof (struct xbsd_disklabel)))
726f69e2
KZ
793 fatal (unable_to_write);
794#endif
795
796 sync_disks ();
797
798 return 1;
799}
800
801static void
802sync_disks (void)
803{
7eda085c 804 printf (_("\nSyncing disks.\n"));
726f69e2
KZ
805 sync ();
806 sleep (4);
807}
808
22853e4a 809#if !defined (__alpha__)
726f69e2 810static int
fd6b7a7f 811xbsd_translate_fstype (int linux_type)
726f69e2
KZ
812{
813 switch (linux_type)
814 {
815 case 0x01: /* DOS 12-bit FAT */
816 case 0x04: /* DOS 16-bit <32M */
817 case 0x06: /* DOS 16-bit >=32M */
818 case 0xe1: /* DOS access */
819 case 0xe3: /* DOS R/O */
820 case 0xf2: /* DOS secondary */
821 return BSD_FS_MSDOS;
822 case 0x07: /* OS/2 HPFS */
823 return BSD_FS_HPFS;
824 default:
825 return BSD_FS_OTHER;
826 }
827}
828
829static void
fd6b7a7f 830xbsd_link_part (void)
726f69e2
KZ
831{
832 int k, i;
22853e4a 833 struct partition *p;
726f69e2
KZ
834
835 k = get_partition (1, partitions);
836
fd6b7a7f 837 if (!xbsd_check_new_partition (&i))
726f69e2
KZ
838 return;
839
22853e4a
KZ
840 p = get_part_table(k);
841
842 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
843 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
844 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
726f69e2
KZ
845}
846#endif
847
848#if defined (__alpha__)
726f69e2 849
eb63b9b8 850#if !defined(__GLIBC__)
2b6fc908
KZ
851typedef unsigned long long u_int64_t;
852#endif
853
726f69e2
KZ
854void
855alpha_bootblock_checksum (char *boot)
856{
857 u_int64_t *dp, sum;
858 int i;
859
860 dp = (u_int64_t *)boot;
861 sum = 0;
862 for (i = 0; i < 63; i++)
863 sum += dp[i];
864 dp[63] = sum;
865}
866#endif /* __alpha__ */