]>
Commit | Line | Data |
---|---|---|
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 |
64 | static void xbsd_delete_part (void); |
65 | static void xbsd_new_part (void); | |
7737f698 DB |
66 | static void xbsd_write_disklabel (struct fdisk_context *cxt); |
67 | static int xbsd_create_disklabel (struct fdisk_context *cxt); | |
fd6b7a7f | 68 | static void xbsd_edit_disklabel (void); |
7737f698 | 69 | static void xbsd_write_bootstrap (struct fdisk_context *cxt); |
fd6b7a7f KZ |
70 | static void xbsd_change_fstype (void); |
71 | static int xbsd_get_part_index (int max); | |
72 | static int xbsd_check_new_partition (int *i); | |
73 | static void xbsd_list_types (void); | |
95961ee2 | 74 | static unsigned short xbsd_dkcksum (struct xbsd_disklabel *lp); |
7737f698 DB |
75 | static int xbsd_initlabel (struct fdisk_context *cxt, |
76 | struct partition *p, struct xbsd_disklabel *d, | |
63cccae4 | 77 | int pindex); |
7737f698 DB |
78 | static int xbsd_readlabel (struct fdisk_context *cxt, |
79 | struct partition *p, struct xbsd_disklabel *d); | |
80 | static int xbsd_writelabel (struct fdisk_context *cxt, struct partition *p, struct xbsd_disklabel *d); | |
726f69e2 | 81 | static void sync_disks (void); |
22853e4a | 82 | |
726f69e2 KZ |
83 | #if defined (__alpha__) |
84 | void alpha_bootblock_checksum (char *boot); | |
85 | #endif | |
86 | ||
22853e4a KZ |
87 | #if !defined (__alpha__) |
88 | static int xbsd_translate_fstype (int linux_type); | |
89 | static void xbsd_link_part (void); | |
fd6b7a7f KZ |
90 | static struct partition *xbsd_part; |
91 | static 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 */ | |
96 | static char disklabelbuffer[BSD_BBSIZE] __attribute__((aligned(8))); | |
97 | #else | |
98 | static char disklabelbuffer[BSD_BBSIZE]; | |
99 | #endif | |
100 | ||
101 | static 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 | 112 | int |
7737f698 DB |
113 | check_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 | 119 | int |
7737f698 DB |
120 | btrydev (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__) |
129 | static int | |
5c36a0eb KZ |
130 | hidden(int type) { |
131 | return type ^ 0x10; | |
132 | } | |
133 | ||
22853e4a | 134 | static int |
e8f26419 KZ |
135 | is_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 | 143 | void |
7737f698 | 144 | bsd_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 | ||
233 | static void | |
fd6b7a7f | 234 | xbsd_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 | ||
247 | static void | |
fd6b7a7f | 248 | xbsd_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 | 285 | void |
7737f698 | 286 | xbsd_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 | ||
383 | static void | |
7737f698 | 384 | xbsd_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 | ||
396 | static int | |
7737f698 | 397 | xbsd_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 | ||
427 | static int | |
428 | edit_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 | ||
440 | static void | |
fd6b7a7f | 441 | xbsd_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 | ||
474 | static int | |
fd6b7a7f | 475 | xbsd_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 | ||
495 | static void | |
7737f698 | 496 | xbsd_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 | ||
565 | static void | |
fd6b7a7f | 566 | xbsd_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 | ||
574 | static int | |
fd6b7a7f | 575 | xbsd_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 | ||
587 | static int | |
63cccae4 | 588 | xbsd_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 | ||
618 | static void | |
63cccae4 KZ |
619 | xbsd_list_types (void) { |
620 | list_types (xbsd_fstypes); | |
726f69e2 KZ |
621 | } |
622 | ||
95961ee2 | 623 | static unsigned short |
63cccae4 | 624 | xbsd_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 | ||
635 | static int | |
7737f698 | 636 | xbsd_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 | 708 | static int |
7737f698 | 709 | xbsd_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 | ||
745 | static int | |
7737f698 | 746 | xbsd_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 | ||
784 | static void | |
785 | sync_disks (void) | |
786 | { | |
7eda085c | 787 | printf (_("\nSyncing disks.\n")); |
726f69e2 KZ |
788 | sync (); |
789 | sleep (4); | |
790 | } | |
791 | ||
22853e4a | 792 | #if !defined (__alpha__) |
726f69e2 | 793 | static int |
fd6b7a7f | 794 | xbsd_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 | ||
812 | static void | |
fd6b7a7f | 813 | xbsd_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 |
834 | typedef unsigned long long u_int64_t; |
835 | #endif | |
836 | ||
726f69e2 KZ |
837 | void |
838 | alpha_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__ */ |