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