]> git.ipfire.org Git - thirdparty/util-linux.git/blame - fdisk/fdiskbsdlabel.c
fdisk: sun: use sector_t
[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);
7737f698
DB
66static void xbsd_write_disklabel (struct fdisk_context *cxt);
67static int xbsd_create_disklabel (struct fdisk_context *cxt);
fd6b7a7f 68static void xbsd_edit_disklabel (void);
7737f698 69static void xbsd_write_bootstrap (struct fdisk_context *cxt);
fd6b7a7f
KZ
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);
7737f698
DB
75static int xbsd_initlabel (struct fdisk_context *cxt,
76 struct partition *p, struct xbsd_disklabel *d,
63cccae4 77 int pindex);
7737f698
DB
78static int xbsd_readlabel (struct fdisk_context *cxt,
79 struct partition *p, struct xbsd_disklabel *d);
80static int xbsd_writelabel (struct fdisk_context *cxt, struct partition *p, struct xbsd_disklabel *d);
726f69e2 81static void sync_disks (void);
22853e4a 82
726f69e2
KZ
83#if defined (__alpha__)
84void alpha_bootblock_checksum (char *boot);
85#endif
86
22853e4a
KZ
87#if !defined (__alpha__)
88static int xbsd_translate_fstype (int linux_type);
89static void xbsd_link_part (void);
fd6b7a7f
KZ
90static struct partition *xbsd_part;
91static int xbsd_part_index;
726f69e2
KZ
92#endif
93
22853e4a
KZ
94#if defined (__alpha__)
95/* We access this through a u_int64_t * when checksumming */
96static char disklabelbuffer[BSD_BBSIZE] __attribute__((aligned(8)));
97#else
98static char disklabelbuffer[BSD_BBSIZE];
99#endif
100
101static struct xbsd_disklabel xbsd_dlabel;
102
103#define bsd_cround(n) \
104 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
105
63cccae4
KZ
106/*
107 * Test whether the whole disk has BSD disk label magic.
108 *
109 * Note: often reformatting with DOS-type label leaves the BSD magic,
110 * so this does not mean that there is a BSD disk label.
111 */
22853e4a 112int
7737f698
DB
113check_osf_label(struct fdisk_context *cxt) {
114 if (xbsd_readlabel (cxt, NULL, &xbsd_dlabel) == 0)
63cccae4
KZ
115 return 0;
116 return 1;
22853e4a
KZ
117}
118
2b6fc908 119int
7737f698
DB
120btrydev (struct fdisk_context *cxt) {
121 if (xbsd_readlabel (cxt, NULL, &xbsd_dlabel) == 0)
63cccae4 122 return -1;
7737f698
DB
123 printf(_("\nBSD label for device: %s\n"), cxt->dev_path);
124 xbsd_print_disklabel (cxt, 0);
63cccae4 125 return 0;
fd6b7a7f
KZ
126}
127
22853e4a
KZ
128#if !defined (__alpha__)
129static int
5c36a0eb
KZ
130hidden(int type) {
131 return type ^ 0x10;
132}
133
22853e4a 134static int
e8f26419
KZ
135is_bsd_partition_type(int type) {
136 return (type == FREEBSD_PARTITION ||
137 type == hidden(FREEBSD_PARTITION) ||
138 type == NETBSD_PARTITION ||
139 type == hidden(NETBSD_PARTITION));
5c36a0eb 140}
22853e4a 141#endif
5c36a0eb 142
726f69e2 143void
7737f698 144bsd_command_prompt (struct fdisk_context *cxt)
e97a991a 145{
22853e4a 146#if !defined (__alpha__)
2b6fc908 147 int t, ss;
22853e4a 148 struct partition *p;
726f69e2 149
22853e4a
KZ
150 for (t=0; t<4; t++) {
151 p = get_part_table(t);
e8f26419 152 if (p && is_bsd_partition_type(p->sys_ind)) {
22853e4a 153 xbsd_part = p;
fd6b7a7f 154 xbsd_part_index = t;
2b6fc908 155 ss = get_start_sect(xbsd_part);
5c36a0eb 156 if (ss == 0) {
22853e4a 157 fprintf (stderr, _("Partition %s has invalid starting sector 0.\n"),
823f0fd1 158 partname(cxt->dev_path, t+1, 0));
22853e4a 159 return;
726f69e2 160 }
22853e4a 161 printf (_("Reading disklabel of %s at sector %d.\n"),
823f0fd1 162 partname(cxt->dev_path, t+1, 0), ss + BSD_LABELSECTOR);
7737f698
DB
163 if (xbsd_readlabel (cxt, xbsd_part, &xbsd_dlabel) == 0)
164 if (xbsd_create_disklabel (cxt) == 0)
726f69e2
KZ
165 return;
166 break;
167 }
22853e4a 168 }
726f69e2 169
5c36a0eb 170 if (t == 4) {
823f0fd1 171 printf (_("There is no *BSD partition on %s.\n"), cxt->dev_path);
726f69e2
KZ
172 return;
173 }
174
175#elif defined (__alpha__)
176
7737f698
DB
177 if (xbsd_readlabel (cxt, NULL, &xbsd_dlabel) == 0)
178 if (xbsd_create_disklabel (cxt) == 0)
726f69e2
KZ
179 exit ( EXIT_SUCCESS );
180
181#endif
182
22853e4a 183 while (1) {
726f69e2 184 putchar ('\n');
22853e4a 185 switch (tolower (read_char (_("BSD disklabel command (m for help): ")))) {
726f69e2 186 case 'd':
22853e4a 187 xbsd_delete_part ();
726f69e2
KZ
188 break;
189 case 'e':
22853e4a 190 xbsd_edit_disklabel ();
726f69e2
KZ
191 break;
192 case 'i':
7737f698 193 xbsd_write_bootstrap (cxt);
726f69e2
KZ
194 break;
195 case 'l':
22853e4a 196 xbsd_list_types ();
726f69e2
KZ
197 break;
198 case 'n':
fd6b7a7f 199 xbsd_new_part ();
726f69e2
KZ
200 break;
201 case 'p':
7737f698 202 xbsd_print_disklabel (cxt, 0);
726f69e2
KZ
203 break;
204 case 'q':
823f0fd1 205 close (cxt->dev_fd);
726f69e2 206 exit ( EXIT_SUCCESS );
22853e4a
KZ
207 case 'r':
208 return;
726f69e2 209 case 's':
7737f698 210 xbsd_print_disklabel (cxt, 1);
726f69e2
KZ
211 break;
212 case 't':
22853e4a
KZ
213 xbsd_change_fstype ();
214 break;
215 case 'u':
216 change_units();
726f69e2
KZ
217 break;
218 case 'w':
7737f698 219 xbsd_write_disklabel (cxt);
726f69e2 220 break;
22853e4a 221#if !defined (__alpha__)
726f69e2 222 case 'x':
fd6b7a7f 223 xbsd_link_part ();
726f69e2
KZ
224 break;
225#endif
226 default:
c482303e 227 print_menu(MAIN_MENU);
726f69e2
KZ
228 break;
229 }
230 }
231}
232
233static void
fd6b7a7f 234xbsd_delete_part (void)
726f69e2
KZ
235{
236 int i;
237
fd6b7a7f
KZ
238 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
239 xbsd_dlabel.d_partitions[i].p_size = 0;
240 xbsd_dlabel.d_partitions[i].p_offset = 0;
22853e4a 241 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
fd6b7a7f
KZ
242 if (xbsd_dlabel.d_npartitions == i + 1)
243 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
244 xbsd_dlabel.d_npartitions--;
726f69e2
KZ
245}
246
247static void
fd6b7a7f 248xbsd_new_part (void)
726f69e2 249{
df1dddf9 250 unsigned int begin, end;
eb63b9b8 251 char mesg[256];
726f69e2
KZ
252 int i;
253
fd6b7a7f 254 if (!xbsd_check_new_partition (&i))
726f69e2
KZ
255 return;
256
364cda48 257#if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
2b6fc908
KZ
258 begin = get_start_sect(xbsd_part);
259 end = begin + get_nr_sects(xbsd_part) - 1;
364cda48 260#else
726f69e2 261 begin = 0;
eb63b9b8 262 end = xbsd_dlabel.d_secperunit - 1;
726f69e2
KZ
263#endif
264
c07ebfa1 265 snprintf (mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
22853e4a 266 begin = read_int (bsd_cround (begin), bsd_cround (begin), bsd_cround (end),
5c36a0eb 267 0, mesg);
726f69e2 268
eb63b9b8 269 if (display_in_cyl_units)
22853e4a 270 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
eb63b9b8 271
c07ebfa1 272 snprintf (mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
eb63b9b8 273 str_units(SINGULAR));
22853e4a
KZ
274 end = read_int (bsd_cround (begin), bsd_cround (end), bsd_cround (end),
275 bsd_cround (begin), mesg);
726f69e2 276
7eda085c 277 if (display_in_cyl_units)
22853e4a 278 end = end * xbsd_dlabel.d_secpercyl - 1;
eb63b9b8 279
fd6b7a7f
KZ
280 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
281 xbsd_dlabel.d_partitions[i].p_offset = begin;
22853e4a 282 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
726f69e2
KZ
283}
284
22853e4a 285void
7737f698 286xbsd_print_disklabel (struct fdisk_context *cxt, int show_all) {
fd6b7a7f
KZ
287 struct xbsd_disklabel *lp = &xbsd_dlabel;
288 struct xbsd_partition *pp;
726f69e2
KZ
289 FILE *f = stdout;
290 int i, j;
291
22853e4a
KZ
292 if (show_all) {
293#if defined (__alpha__)
823f0fd1 294 fprintf(f, "# %s:\n", cxt->dev_path);
22853e4a 295#else
823f0fd1 296 fprintf(f, "# %s:\n", partname(cxt->dev_path, xbsd_part_index+1, 0));
726f69e2
KZ
297#endif
298 if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
7eda085c 299 fprintf(f, _("type: %s\n"), xbsd_dktypenames[lp->d_type]);
726f69e2 300 else
7eda085c
KZ
301 fprintf(f, _("type: %d\n"), lp->d_type);
302 fprintf(f, _("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
303 fprintf(f, _("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
304 fprintf(f, _("flags:"));
726f69e2 305 if (lp->d_flags & BSD_D_REMOVABLE)
7eda085c 306 fprintf(f, _(" removable"));
726f69e2 307 if (lp->d_flags & BSD_D_ECC)
7eda085c 308 fprintf(f, _(" ecc"));
726f69e2 309 if (lp->d_flags & BSD_D_BADSECT)
7eda085c 310 fprintf(f, _(" badsect"));
726f69e2 311 fprintf(f, "\n");
fd6b7a7f
KZ
312 /* On various machines the fields of *lp are short/int/long */
313 /* In order to avoid problems, we cast them all to long. */
7eda085c
KZ
314 fprintf(f, _("bytes/sector: %ld\n"), (long) lp->d_secsize);
315 fprintf(f, _("sectors/track: %ld\n"), (long) lp->d_nsectors);
316 fprintf(f, _("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
317 fprintf(f, _("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
318 fprintf(f, _("cylinders: %ld\n"), (long) lp->d_ncylinders);
319 fprintf(f, _("rpm: %d\n"), lp->d_rpm);
320 fprintf(f, _("interleave: %d\n"), lp->d_interleave);
321 fprintf(f, _("trackskew: %d\n"), lp->d_trackskew);
322 fprintf(f, _("cylinderskew: %d\n"), lp->d_cylskew);
22853e4a
KZ
323 fprintf(f, _("headswitch: %ld\t\t# milliseconds\n"),
324 (long) lp->d_headswitch);
325 fprintf(f, _("track-to-track seek: %ld\t# milliseconds\n"),
326 (long) lp->d_trkseek);
7eda085c 327 fprintf(f, _("drivedata: "));
726f69e2
KZ
328 for (i = NDDATA - 1; i >= 0; i--)
329 if (lp->d_drivedata[i])
330 break;
331 if (i < 0)
332 i = 0;
333 for (j = 0; j <= i; j++)
fd6b7a7f 334 fprintf(f, "%ld ", (long) lp->d_drivedata[j]);
726f69e2 335 }
7eda085c 336 fprintf (f, _("\n%d partitions:\n"), lp->d_npartitions);
22853e4a 337 fprintf (f, _("# start end size fstype [fsize bsize cpg]\n"));
726f69e2
KZ
338 pp = lp->d_partitions;
339 for (i = 0; i < lp->d_npartitions; i++, pp++) {
340 if (pp->p_size) {
22853e4a
KZ
341 if (display_in_cyl_units && lp->d_secpercyl) {
342 fprintf(f, " %c: %8ld%c %8ld%c %8ld%c ",
343 'a' + i,
344 (long) pp->p_offset / lp->d_secpercyl + 1,
345 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
346 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1)
347 / lp->d_secpercyl,
348 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
349 (long) pp->p_size / lp->d_secpercyl,
350 (pp->p_size % lp->d_secpercyl) ? '*' : ' ');
351 } else {
352 fprintf(f, " %c: %8ld %8ld %8ld ",
353 'a' + i,
354 (long) pp->p_offset,
355 (long) pp->p_offset + pp->p_size - 1,
356 (long) pp->p_size);
357 }
726f69e2 358 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
fd6b7a7f 359 fprintf(f, "%8.8s", xbsd_fstypes[pp->p_fstype].name);
726f69e2
KZ
360 else
361 fprintf(f, "%8x", pp->p_fstype);
22853e4a
KZ
362 switch (pp->p_fstype) {
363 case BSD_FS_UNUSED:
fd6b7a7f
KZ
364 fprintf(f, " %5ld %5ld %5.5s ",
365 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
726f69e2
KZ
366 break;
367
368 case BSD_FS_BSDFFS:
fd6b7a7f
KZ
369 fprintf(f, " %5ld %5ld %5d ",
370 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag,
726f69e2
KZ
371 pp->p_cpg);
372 break;
373
374 default:
22853e4a 375 fprintf(f, "%22.22s", "");
726f69e2
KZ
376 break;
377 }
22853e4a 378 fprintf(f, "\n");
726f69e2
KZ
379 }
380 }
381}
382
383static void
7737f698 384xbsd_write_disklabel (struct fdisk_context *cxt) {
22853e4a 385#if defined (__alpha__)
823f0fd1 386 printf (_("Writing disklabel to %s.\n"), cxt->dev_path);
7737f698 387 xbsd_writelabel (cxt, NULL, &xbsd_dlabel);
22853e4a
KZ
388#else
389 printf (_("Writing disklabel to %s.\n"),
823f0fd1 390 partname(cxt->dev_path, xbsd_part_index+1, 0));
7737f698 391 xbsd_writelabel (cxt, xbsd_part, &xbsd_dlabel);
726f69e2 392#endif
7737f698 393 reread_partition_table(cxt, 0); /* no exit yet */
726f69e2
KZ
394}
395
396static int
7737f698 397xbsd_create_disklabel (struct fdisk_context *cxt) {
22853e4a 398 char c;
726f69e2 399
22853e4a 400#if defined (__alpha__)
823f0fd1 401 fprintf (stderr, _("%s contains no disklabel.\n"), cxt->dev_path);
22853e4a
KZ
402#else
403 fprintf (stderr, _("%s contains no disklabel.\n"),
823f0fd1 404 partname(cxt->dev_path, xbsd_part_index+1, 0));
726f69e2
KZ
405#endif
406
22853e4a
KZ
407 while (1) {
408 c = read_char (_("Do you want to create a disklabel? (y/n) "));
409 if (tolower(c) == 'y') {
7737f698 410 if (xbsd_initlabel (cxt,
95f1bdee
KZ
411#if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
412 defined (__s390__) || defined (__s390x__)
22853e4a
KZ
413 NULL, &xbsd_dlabel, 0
414#else
415 xbsd_part, &xbsd_dlabel, xbsd_part_index
726f69e2 416#endif
22853e4a 417 ) == 1) {
7737f698 418 xbsd_print_disklabel (cxt, 1);
22853e4a
KZ
419 return 1;
420 } else
421 return 0;
422 } else if (c == 'n')
423 return 0;
424 }
726f69e2
KZ
425}
426
427static int
428edit_int (int def, char *mesg)
429{
430 do {
431 fputs (mesg, stdout);
432 printf (" (%d): ", def);
8feb31e5 433 if (!read_line (NULL))
726f69e2
KZ
434 return def;
435 }
436 while (!isdigit (*line_ptr));
437 return atoi (line_ptr);
438}
439
440static void
fd6b7a7f 441xbsd_edit_disklabel (void)
726f69e2 442{
fd6b7a7f 443 struct xbsd_disklabel *d;
726f69e2 444
fd6b7a7f 445 d = &xbsd_dlabel;
726f69e2 446
22853e4a 447#if defined (__alpha__) || defined (__ia64__)
95961ee2
JW
448 d -> d_secsize = (unsigned long) edit_int ((unsigned long) d -> d_secsize ,_("bytes/sector"));
449 d -> d_nsectors = (unsigned long) edit_int ((unsigned long) d -> d_nsectors ,_("sectors/track"));
450 d -> d_ntracks = (unsigned long) edit_int ((unsigned long) d -> d_ntracks ,_("tracks/cylinder"));
451 d -> d_ncylinders = (unsigned long) edit_int ((unsigned long) d -> d_ncylinders ,_("cylinders"));
726f69e2
KZ
452#endif
453
454 /* d -> d_secpercyl can be != d -> d_nsectors * d -> d_ntracks */
455 while (1)
456 {
95961ee2 457 d -> d_secpercyl = (unsigned long) edit_int ((unsigned long) d -> d_nsectors * d -> d_ntracks,
7eda085c 458 _("sectors/cylinder"));
726f69e2
KZ
459 if (d -> d_secpercyl <= d -> d_nsectors * d -> d_ntracks)
460 break;
461
7eda085c 462 printf (_("Must be <= sectors/track * tracks/cylinder (default).\n"));
726f69e2 463 }
95961ee2
JW
464 d -> d_rpm = (unsigned short) edit_int ((unsigned short) d -> d_rpm ,_("rpm"));
465 d -> d_interleave = (unsigned short) edit_int ((unsigned short) d -> d_interleave,_("interleave"));
466 d -> d_trackskew = (unsigned short) edit_int ((unsigned short) d -> d_trackskew ,_("trackskew"));
467 d -> d_cylskew = (unsigned short) edit_int ((unsigned short) d -> d_cylskew ,_("cylinderskew"));
468 d -> d_headswitch = (unsigned long) edit_int ((unsigned long) d -> d_headswitch ,_("headswitch"));
469 d -> d_trkseek = (unsigned long) edit_int ((unsigned long) d -> d_trkseek ,_("track-to-track seek"));
726f69e2
KZ
470
471 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
472}
473
474static int
fd6b7a7f 475xbsd_get_bootstrap (char *path, void *ptr, int size)
726f69e2
KZ
476{
477 int fd;
478
479 if ((fd = open (path, O_RDONLY)) < 0)
480 {
481 perror (path);
482 return 0;
483 }
484 if (read (fd, ptr, size) < 0)
485 {
486 perror (path);
487 close (fd);
488 return 0;
489 }
490 printf (" ... %s\n", path);
491 close (fd);
492 return 1;
493}
494
495static void
7737f698 496xbsd_write_bootstrap (struct fdisk_context *cxt)
726f69e2
KZ
497{
498 char *bootdir = BSD_LINUX_BOOTDIR;
7e5fad47 499 char path[sizeof(BSD_LINUX_BOOTDIR) + 1 + 2 + 4]; /* BSD_LINUX_BOOTDIR + / + {sd,wd} + boot */
726f69e2 500 char *dkbasename;
fd6b7a7f 501 struct xbsd_disklabel dl;
726f69e2
KZ
502 char *d, *p, *e;
503 int sector;
504
fd6b7a7f 505 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
726f69e2
KZ
506 dkbasename = "sd";
507 else
508 dkbasename = "wd";
509
c07ebfa1
KZ
510 printf (_("Bootstrap: %sboot -> boot%s (%s): "),
511 dkbasename, dkbasename, dkbasename);
8feb31e5 512 if (read_line (NULL)) {
726f69e2
KZ
513 line_ptr[strlen (line_ptr)-1] = '\0';
514 dkbasename = line_ptr;
515 }
c07ebfa1 516 snprintf (path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
22853e4a 517 if (!xbsd_get_bootstrap (path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
726f69e2
KZ
518 return;
519
fd6b7a7f 520 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
22853e4a 521 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
c0f19ccf 522 memmove (&dl, d, sizeof (struct xbsd_disklabel));
726f69e2
KZ
523
524 /* The disklabel will be overwritten by 0's from bootxx anyway */
56054a79 525 memset (d, 0, sizeof (struct xbsd_disklabel));
726f69e2 526
c07ebfa1 527 snprintf (path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
22853e4a 528 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
fd6b7a7f 529 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
726f69e2
KZ
530 return;
531
fd6b7a7f 532 e = d + sizeof (struct xbsd_disklabel);
726f69e2 533 for (p=d; p < e; p++)
c07ebfa1 534 if (*p) {
7eda085c 535 fprintf (stderr, _("Bootstrap overlaps with disk label!\n"));
726f69e2
KZ
536 exit ( EXIT_FAILURE );
537 }
538
c0f19ccf 539 memmove (d, &dl, sizeof (struct xbsd_disklabel));
726f69e2 540
364cda48 541#if defined (__powerpc__) || defined (__hppa__)
5c36a0eb 542 sector = 0;
726f69e2
KZ
543#elif defined (__alpha__)
544 sector = 0;
22853e4a
KZ
545 alpha_bootblock_checksum (disklabelbuffer);
546#else
547 sector = get_start_sect(xbsd_part);
726f69e2
KZ
548#endif
549
823f0fd1 550 if (lseek (cxt->dev_fd, (off_t) sector * SECTOR_SIZE, SEEK_SET) == -1)
7737f698 551 fatal (cxt, unable_to_seek);
823f0fd1 552 if (BSD_BBSIZE != write (cxt->dev_fd, disklabelbuffer, BSD_BBSIZE))
7737f698 553 fatal (cxt, unable_to_write);
726f69e2 554
22853e4a 555#if defined (__alpha__)
823f0fd1 556 printf (_("Bootstrap installed on %s.\n"), cxt->dev_path);
22853e4a
KZ
557#else
558 printf (_("Bootstrap installed on %s.\n"),
823f0fd1 559 partname (cxt->dev_path, xbsd_part_index+1, 0));
726f69e2
KZ
560#endif
561
562 sync_disks ();
563}
564
565static void
fd6b7a7f 566xbsd_change_fstype (void)
726f69e2
KZ
567{
568 int i;
569
fd6b7a7f 570 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
2b6fc908 571 xbsd_dlabel.d_partitions[i].p_fstype = read_hex (xbsd_fstypes);
726f69e2
KZ
572}
573
574static int
fd6b7a7f 575xbsd_get_part_index (int max)
726f69e2 576{
eb63b9b8 577 char prompt[256];
726f69e2
KZ
578 char l;
579
c07ebfa1 580 snprintf (prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
726f69e2
KZ
581 do
582 l = tolower (read_char (prompt));
583 while (l < 'a' || l > 'a' + max - 1);
584 return l - 'a';
585}
586
587static int
63cccae4 588xbsd_check_new_partition (int *i) {
726f69e2 589
63cccae4
KZ
590 /* room for more? various BSD flavours have different maxima */
591 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
592 int t;
726f69e2 593
63cccae4
KZ
594 for (t = 0; t < BSD_MAXPARTITIONS; t++)
595 if (xbsd_dlabel.d_partitions[t].p_size == 0)
596 break;
726f69e2 597
63cccae4
KZ
598 if (t == BSD_MAXPARTITIONS) {
599 fprintf (stderr, _("The maximum number of partitions "
600 "has been created\n"));
601 return 0;
602 }
603 }
726f69e2 604
63cccae4
KZ
605 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
606
607 if (*i >= xbsd_dlabel.d_npartitions)
608 xbsd_dlabel.d_npartitions = (*i) + 1;
609
610 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
611 fprintf (stderr, _("This partition already exists.\n"));
612 return 0;
613 }
614
615 return 1;
726f69e2
KZ
616}
617
618static void
63cccae4
KZ
619xbsd_list_types (void) {
620 list_types (xbsd_fstypes);
726f69e2
KZ
621}
622
95961ee2 623static unsigned short
63cccae4 624xbsd_dkcksum (struct xbsd_disklabel *lp) {
95961ee2
JW
625 unsigned short *start, *end;
626 unsigned short sum = 0;
726f69e2 627
95961ee2
JW
628 start = (unsigned short *) lp;
629 end = (unsigned short *) &lp->d_partitions[lp->d_npartitions];
63cccae4
KZ
630 while (start < end)
631 sum ^= *start++;
632 return sum;
726f69e2
KZ
633}
634
635static int
7737f698 636xbsd_initlabel (struct fdisk_context *cxt, struct partition *p, struct xbsd_disklabel *d,
e99da659 637 int pindex __attribute__((__unused__))) {
63cccae4
KZ
638 struct xbsd_partition *pp;
639 struct geom g;
726f69e2 640
7737f698 641 get_geometry (cxt, &g);
56054a79 642 memset (d, 0, sizeof (struct xbsd_disklabel));
726f69e2 643
63cccae4 644 d -> d_magic = BSD_DISKMAGIC;
726f69e2 645
823f0fd1 646 if (strncmp (cxt->dev_path, "/dev/sd", 7) == 0)
63cccae4
KZ
647 d -> d_type = BSD_DTYPE_SCSI;
648 else
649 d -> d_type = BSD_DTYPE_ST506;
726f69e2
KZ
650
651#if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
63cccae4 652 d -> d_subtype = BSD_DSTYPE_INDOSPART & pindex;
726f69e2
KZ
653#endif
654
22853e4a 655#if !defined (__alpha__)
63cccae4 656 d -> d_flags = BSD_D_DOSPART;
726f69e2 657#else
63cccae4 658 d -> d_flags = 0;
726f69e2 659#endif
63cccae4
KZ
660 d -> d_secsize = SECTOR_SIZE; /* bytes/sector */
661 d -> d_nsectors = g.sectors; /* sectors/track */
662 d -> d_ntracks = g.heads; /* tracks/cylinder (heads) */
663 d -> d_ncylinders = g.cylinders;
664 d -> d_secpercyl = g.sectors * g.heads;/* sectors/cylinder */
665 if (d -> d_secpercyl == 0)
666 d -> d_secpercyl = 1; /* avoid segfaults */
667 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
668
669 d -> d_rpm = 3600;
670 d -> d_interleave = 1;
671 d -> d_trackskew = 0;
672 d -> d_cylskew = 0;
673 d -> d_headswitch = 0;
674 d -> d_trkseek = 0;
675
676 d -> d_magic2 = BSD_DISKMAGIC;
677 d -> d_bbsize = BSD_BBSIZE;
678 d -> d_sbsize = BSD_SBSIZE;
726f69e2 679
22853e4a 680#if !defined (__alpha__)
63cccae4
KZ
681 d -> d_npartitions = 4;
682 pp = &d -> d_partitions[2]; /* Partition C should be
683 the NetBSD partition */
684 pp -> p_offset = get_start_sect(p);
685 pp -> p_size = get_nr_sects(p);
686 pp -> p_fstype = BSD_FS_UNUSED;
687 pp = &d -> d_partitions[3]; /* Partition D should be
688 the whole disk */
689 pp -> p_offset = 0;
690 pp -> p_size = d -> d_secperunit;
691 pp -> p_fstype = BSD_FS_UNUSED;
726f69e2 692#elif defined (__alpha__)
63cccae4
KZ
693 d -> d_npartitions = 3;
694 pp = &d -> d_partitions[2]; /* Partition C should be
695 the whole disk */
696 pp -> p_offset = 0;
697 pp -> p_size = d -> d_secperunit;
698 pp -> p_fstype = BSD_FS_UNUSED;
726f69e2
KZ
699#endif
700
63cccae4 701 return 1;
726f69e2
KZ
702}
703
63cccae4
KZ
704/*
705 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
706 * If it has the right magic, return 1.
707 */
726f69e2 708static int
7737f698 709xbsd_readlabel (struct fdisk_context *cxt, struct partition *p, struct xbsd_disklabel *d)
726f69e2 710{
63cccae4 711 int t, sector;
726f69e2 712
63cccae4 713 /* p is used only to get the starting sector */
22853e4a 714#if !defined (__alpha__)
63cccae4 715 sector = (p ? get_start_sect(p) : 0);
726f69e2 716#elif defined (__alpha__)
63cccae4 717 sector = 0;
726f69e2
KZ
718#endif
719
823f0fd1 720 if (lseek (cxt->dev_fd, (off_t) sector * SECTOR_SIZE, SEEK_SET) == -1)
7737f698 721 fatal (cxt, unable_to_seek);
823f0fd1 722 if (BSD_BBSIZE != read (cxt->dev_fd, disklabelbuffer, BSD_BBSIZE))
7737f698 723 fatal (cxt, unable_to_read);
726f69e2 724
c0f19ccf
DM
725 memmove (d,
726 &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
727 sizeof (struct xbsd_disklabel));
726f69e2 728
63cccae4
KZ
729 if (d -> d_magic != BSD_DISKMAGIC || d -> d_magic2 != BSD_DISKMAGIC)
730 return 0;
726f69e2 731
63cccae4
KZ
732 for (t = d -> d_npartitions; t < BSD_MAXPARTITIONS; t++) {
733 d -> d_partitions[t].p_size = 0;
734 d -> d_partitions[t].p_offset = 0;
735 d -> d_partitions[t].p_fstype = BSD_FS_UNUSED;
736 }
737
738 if (d -> d_npartitions > BSD_MAXPARTITIONS)
739 fprintf (stderr, _("Warning: too many partitions "
740 "(%d, maximum is %d).\n"),
741 d -> d_npartitions, BSD_MAXPARTITIONS);
742 return 1;
726f69e2
KZ
743}
744
745static int
7737f698 746xbsd_writelabel (struct fdisk_context *cxt, struct partition *p, struct xbsd_disklabel *d)
726f69e2 747{
df1dddf9 748 unsigned int sector;
726f69e2 749
364cda48 750#if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
2b6fc908 751 sector = get_start_sect(p) + BSD_LABELSECTOR;
364cda48 752#else
726f69e2
KZ
753 sector = BSD_LABELSECTOR;
754#endif
755
756 d -> d_checksum = 0;
fd6b7a7f 757 d -> d_checksum = xbsd_dkcksum (d);
726f69e2
KZ
758
759 /* This is necessary if we want to write the bootstrap later,
760 otherwise we'd write the old disklabel with the bootstrap.
761 */
c0f19ccf
DM
762 memmove (&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET], d,
763 sizeof (struct xbsd_disklabel));
726f69e2
KZ
764
765#if defined (__alpha__) && BSD_LABELSECTOR == 0
22853e4a 766 alpha_bootblock_checksum (disklabelbuffer);
823f0fd1 767 if (lseek (cxt->dev_fd, (off_t) 0, SEEK_SET) == -1)
7737f698 768 fatal (cxt, unable_to_seek);
823f0fd1 769 if (BSD_BBSIZE != write (cxt->dev_fd, disklabelbuffer, BSD_BBSIZE))
7737f698 770 fatal (cxt, unable_to_write);
726f69e2 771#else
823f0fd1 772 if (lseek (cxt->dev_fd, (off_t) sector * SECTOR_SIZE + BSD_LABELOFFSET,
22853e4a 773 SEEK_SET) == -1)
7737f698 774 fatal (cxt, unable_to_seek);
823f0fd1 775 if (sizeof (struct xbsd_disklabel) != write (cxt->dev_fd, d, sizeof (struct xbsd_disklabel)))
7737f698 776 fatal (cxt, unable_to_write);
726f69e2
KZ
777#endif
778
779 sync_disks ();
780
781 return 1;
782}
783
784static void
785sync_disks (void)
786{
7eda085c 787 printf (_("\nSyncing disks.\n"));
726f69e2
KZ
788 sync ();
789 sleep (4);
790}
791
22853e4a 792#if !defined (__alpha__)
726f69e2 793static int
fd6b7a7f 794xbsd_translate_fstype (int linux_type)
726f69e2
KZ
795{
796 switch (linux_type)
797 {
798 case 0x01: /* DOS 12-bit FAT */
799 case 0x04: /* DOS 16-bit <32M */
800 case 0x06: /* DOS 16-bit >=32M */
801 case 0xe1: /* DOS access */
802 case 0xe3: /* DOS R/O */
803 case 0xf2: /* DOS secondary */
804 return BSD_FS_MSDOS;
805 case 0x07: /* OS/2 HPFS */
806 return BSD_FS_HPFS;
807 default:
808 return BSD_FS_OTHER;
809 }
810}
811
812static void
fd6b7a7f 813xbsd_link_part (void)
726f69e2
KZ
814{
815 int k, i;
22853e4a 816 struct partition *p;
726f69e2
KZ
817
818 k = get_partition (1, partitions);
819
fd6b7a7f 820 if (!xbsd_check_new_partition (&i))
726f69e2
KZ
821 return;
822
22853e4a
KZ
823 p = get_part_table(k);
824
825 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
826 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
827 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
726f69e2
KZ
828}
829#endif
830
831#if defined (__alpha__)
726f69e2 832
eb63b9b8 833#if !defined(__GLIBC__)
2b6fc908
KZ
834typedef unsigned long long u_int64_t;
835#endif
836
726f69e2
KZ
837void
838alpha_bootblock_checksum (char *boot)
839{
840 u_int64_t *dp, sum;
841 int i;
842
843 dp = (u_int64_t *)boot;
844 sum = 0;
845 for (i = 0; i < 63; i++)
846 sum += dp[i];
847 dp[63] = sum;
848}
849#endif /* __alpha__ */