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