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