Fix up mix of man(7)/mdoc(7).
[netbsd-mini2440.git] / distrib / utils / sysinst / arch / ofppc / md.c
bloba46ad61d3467a91d5c705c3c4871cca531c4f6ff
1 /* $NetBSD: md.c,v 1.5 2009/05/16 10:40:17 nonaka Exp $ */
3 /*
4 * Copyright 1997 Piermont Information Systems Inc.
5 * All rights reserved.
7 * Based on code written by Philip A. Nelson for Piermont Information
8 * Systems Inc.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed for the NetBSD Project by
21 * Piermont Information Systems Inc.
22 * 4. The name of Piermont Information Systems Inc. may not be used to endorse
23 * or promote products derived from this software without specific prior
24 * written permission.
26 * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
27 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
30 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
36 * THE POSSIBILITY OF SUCH DAMAGE.
39 /* md.c -- ofppc machine specific routines */
41 #include <sys/param.h>
42 #include <sys/sysctl.h>
43 #include <stdio.h>
44 #include <util.h>
45 #include <machine/cpu.h>
47 #include "defs.h"
48 #include "md.h"
49 #include "msg_defs.h"
50 #include "menu_defs.h"
51 #include "endian.h"
53 /* We use MBR_PTYPE_PREP like port-prep does. */
54 static int nonewfsmsdos = 0, nobootfix = 0, noprepfix=0;
55 static int bootpart_fat12 = PART_BOOT_FAT12;
56 static int bootpart_binfo = PART_BOOT_BINFO;
57 static int bootpart_prep = PART_BOOT_PREP;
58 static int bootinfo_mbr = 1;
60 /* bootstart/bootsize are for the fat */
61 int binfostart, binfosize, bprepstart, bprepsize;
63 void
64 md_init(void)
68 void
69 md_init_set_status(int minimal)
71 (void)minimal;
74 int
75 md_get_info(void)
77 return set_bios_geom_with_mbr_guess();
81 * md back-end code for menu-driven BSD disklabel editor.
83 int
84 md_make_bsd_partitions(void)
86 int i;
87 int part;
88 int maxpart = getmaxpartitions();
89 int partstart;
90 int part_raw, part_bsd;
91 int ptend;
92 int no_swap = 0;
93 partinfo *p;
96 * Initialize global variables that track space used on this disk.
97 * Standard 4.4BSD 8-partition labels always cover whole disk.
99 if (ptsize == 0)
100 ptsize = dlsize - ptstart;
101 if (dlsize == 0)
102 dlsize = ptstart + ptsize;
104 partstart = ptstart;
105 ptend = ptstart + ptsize;
107 /* Ask for layout type -- standard or special */
108 msg_display(MSG_layout,
109 ptsize / (MEG / sectorsize),
110 DEFROOTSIZE + DEFSWAPSIZE + DEFUSRSIZE,
111 DEFROOTSIZE + DEFSWAPSIZE + DEFUSRSIZE + XNEEDMB);
113 process_menu(MENU_layout, NULL);
115 /* Set so we use the 'real' geometry for rounding, input in MB */
116 current_cylsize = dlcylsize;
117 set_sizemultname_meg();
119 /* Build standard partitions */
120 memset(&bsdlabel, 0, sizeof bsdlabel);
122 /* Set initial partition types to unused */
123 for (part = 0 ; part < maxpart ; ++part)
124 bsdlabel[part].pi_fstype = FS_UNUSED;
126 /* Whole disk partition */
127 part_raw = getrawpartition();
128 if (part_raw == -1)
129 part_raw = PART_C; /* for sanity... */
130 bsdlabel[part_raw].pi_offset = 0;
131 bsdlabel[part_raw].pi_size = dlsize;
133 if (part_raw == PART_D) {
134 /* Probably a system that expects an i386 style mbr */
135 part_bsd = PART_C;
136 bsdlabel[PART_C].pi_offset = ptstart;
137 bsdlabel[PART_C].pi_size = ptsize;
138 } else {
139 part_bsd = part_raw;
142 if (bootsize != 0) {
143 bsdlabel[PART_BOOT_FAT12].pi_fstype = FS_MSDOS;
144 bsdlabel[PART_BOOT_FAT12].pi_size = bootsize;
145 bsdlabel[PART_BOOT_FAT12].pi_offset = bootstart;
146 bsdlabel[PART_BOOT_FAT12].pi_flags |= PART_BOOT_FAT12_PI_FLAGS;
147 strlcpy(bsdlabel[PART_BOOT_FAT12].pi_mount,
148 PART_BOOT_FAT12_PI_MOUNT,
149 sizeof bsdlabel[PART_BOOT_FAT12].pi_mount);
151 if (binfosize != 0) {
152 bsdlabel[PART_BOOT_BINFO].pi_fstype = FS_OTHER;
153 bsdlabel[PART_BOOT_BINFO].pi_size = binfosize;
154 bsdlabel[PART_BOOT_BINFO].pi_offset = binfostart;
156 if (bprepsize != 0) {
157 bsdlabel[PART_BOOT_PREP].pi_fstype = FS_BOOT;
158 bsdlabel[PART_BOOT_PREP].pi_size = bprepsize;
159 bsdlabel[PART_BOOT_PREP].pi_offset = bprepstart;
162 #ifdef PART_REST
163 bsdlabel[PART_REST].pi_offset = 0;
164 bsdlabel[PART_REST].pi_size = ptstart;
165 #endif
168 * Save any partitions that are outside the area we are
169 * going to use.
170 * In particular this saves details of the other MBR
171 * partitions on a multiboot i386 system.
173 for (i = maxpart; i--;) {
174 if (bsdlabel[i].pi_size != 0)
175 /* Don't overwrite special partitions */
176 continue;
177 p = &oldlabel[i];
178 if (p->pi_fstype == FS_UNUSED || p->pi_size == 0)
179 continue;
180 if (layoutkind == 4) {
181 if (PI_ISBSDFS(p))
182 p->pi_flags |= PIF_MOUNT;
183 } else {
184 if (p->pi_offset < ptstart + ptsize &&
185 p->pi_offset + p->pi_size > ptstart)
186 /* Not outside area we are allocating */
187 continue;
188 if (p->pi_fstype == FS_SWAP)
189 no_swap = 1;
191 bsdlabel[i] = oldlabel[i];
194 if (layoutkind == 4) {
195 /* XXX Check we have a sensible layout */
197 } else
198 get_ptn_sizes(partstart, ptend - partstart, no_swap);
201 * OK, we have a partition table. Give the user the chance to
202 * edit it and verify it's OK, or abort altogether.
204 edit_check:
205 if (edit_and_check_label(bsdlabel, maxpart, part_raw, part_bsd) == 0) {
206 msg_display(MSG_abort);
207 return 0;
209 if (md_check_partitions() == 0)
210 goto edit_check;
212 /* Disk name */
213 msg_prompt(MSG_packname, bsddiskname, bsddiskname, sizeof bsddiskname);
215 /* save label to disk for MI code to update. */
216 (void) savenewlabel(bsdlabel, maxpart);
218 /* Everything looks OK. */
219 return 1;
223 * any additional partition validation
226 md_check_partitions(void)
228 int part, fprep=0, ffat=0;
230 /* we need to find a boot partition, otherwise we can't create
231 * our msdos fs boot partition. We make the assumption that
232 * the user hasn't done something stupid, like move it away
233 * from the MBR partition.
235 for (part = PART_A; part < MAXPARTITIONS; part++) {
236 if (bsdlabel[part].pi_fstype == FS_MSDOS) {
237 bootpart_fat12 = part;
238 ffat++;
239 } else if (bsdlabel[part].pi_fstype == FS_BOOT) {
240 bootpart_prep = part;
241 fprep++;
242 } else if (bsdlabel[part].pi_fstype == FS_OTHER) {
243 bootpart_binfo = part;
244 fprep++;
247 /* oh, the confusion */
248 if (ffat >= 1 && fprep < 2)
249 return 1;
250 if (ffat < 1 && fprep >= 2)
251 return 2;
252 if (ffat >=1 && fprep >= 2)
253 return 3;
255 msg_display(MSG_nobootpartdisklabel);
256 process_menu(MENU_ok, NULL);
257 return 0;
261 * hook called before writing new disklabel.
264 md_pre_disklabel(void)
266 msg_display(MSG_dofdisk);
268 /* write edited MBR onto disk. */
269 if (write_mbr(diskdev, &mbr, 1) != 0) {
270 msg_display(MSG_wmbrfail);
271 process_menu(MENU_ok, NULL);
272 return 1;
274 return 0;
278 * hook called after writing disklabel to new target disk.
281 md_post_disklabel(void)
283 char bootdev[100];
285 if (bootstart == 0 || bootsize == 0)
286 return 0;
288 snprintf(bootdev, sizeof bootdev, "/dev/r%s%c", diskdev,
289 'a'+bootpart_fat12);
290 run_program(RUN_DISPLAY, "/sbin/newfs_msdos %s", bootdev);
292 return 0;
296 * hook called after upgrade() or install() has finished setting
297 * up the target disk but immediately before the user is given the
298 * ``disks are now set up'' message.
301 md_post_newfs(void)
304 /* just in case */
305 run_program(RUN_DISPLAY, "/sbin/umount /targetroot/boot");
306 return 0;
310 md_post_extract(void)
312 char bootdev[100], bootbdev[100], version[64];
314 /* if we can't make it bootable, just punt */
315 if (nobootfix && noprepfix)
316 return 0;
318 snprintf(version, sizeof version, "NetBSD/%s %s", MACH, REL);
319 run_program(RUN_DISPLAY, "/usr/mdec/mkbootinfo '%s' %d "
320 "/tmp/bootinfo.txt", version, bootinfo_mbr);
322 if (!nobootfix) {
323 snprintf(bootdev, sizeof bootdev, "/dev/r%s%c", diskdev,
324 'a'+bootpart_fat12);
325 snprintf(bootbdev, sizeof bootbdev, "/dev/%s%c", diskdev,
326 'a'+bootpart_fat12);
328 if (nonewfsmsdos == 0)
329 run_program(RUN_DISPLAY, "/sbin/newfs_msdos %s",
330 bootdev);
331 run_program(RUN_DISPLAY, "/sbin/mount_msdos %s /mnt2",
332 bootbdev);
333 run_program(RUN_DISPLAY, "/bin/mkdir -p /mnt2/ppc");
334 run_program(RUN_DISPLAY, "/bin/mkdir -p /mnt2/netbsd");
335 run_program(RUN_DISPLAY, "/bin/cp /usr/mdec/ofwboot "
336 "/mnt2/netbsd");
337 run_program(RUN_DISPLAY, "/bin/cp /tmp/bootinfo.txt "
338 "/mnt2/ppc");
339 run_program(RUN_DISPLAY,
340 "/bin/cp /usr/mdec/ofwboot /mnt2/ofwboot");
341 run_program(RUN_DISPLAY, "/sbin/umount /mnt2");
344 if (!noprepfix) {
345 snprintf(bootdev, sizeof bootdev, "/dev/r%s%c", diskdev,
346 'a'+bootpart_prep);
347 snprintf(bootbdev, sizeof bootbdev, "/dev/%s%c", diskdev,
348 'a'+bootpart_prep);
349 run_program(RUN_DISPLAY, "/bin/dd if=/dev/zero of=%s bs=512",
350 bootdev);
351 run_program(RUN_DISPLAY, "/bin/dd if=/usr/mdec/ofwboot "
352 "of=%s bs=512", bootbdev);
354 snprintf(bootdev, sizeof bootdev, "/dev/r%s%c", diskdev,
355 'a'+bootpart_binfo);
356 snprintf(bootbdev, sizeof bootbdev, "/dev/%s%c", diskdev,
357 'a'+bootpart_binfo);
358 run_program(RUN_DISPLAY, "/bin/dd if=/dev/zero of=%s bs=512",
359 bootdev);
360 run_program(RUN_DISPLAY, "/bin/dd if=/tmp/bootinfo.txt "
361 "of=%s bs=512", bootbdev);
364 return 0;
367 void
368 md_cleanup_install(void)
370 #ifndef DEBUG
371 enable_rc_conf();
372 #endif
376 md_pre_update(void)
378 struct mbr_partition *part;
379 mbr_info_t *ext;
380 int i;
382 read_mbr(diskdev, &mbr);
383 /* do a sanity check of the partition table */
384 for (ext = &mbr; ext; ext = ext->extended) {
385 part = ext->mbr.mbr_parts;
386 for (i = 0; i < MBR_PART_COUNT; part++, i++) {
387 if (part->mbrp_type == MBR_PTYPE_PREP &&
388 part->mbrp_size > 50)
389 bootinfo_mbr = i+1;
390 if (part->mbrp_type == MBR_PTYPE_RESERVED_x21 &&
391 part->mbrp_size < (MIN_FAT12_BOOT/512)) {
392 msg_display(MSG_boottoosmall);
393 msg_display_add(MSG_nobootpartdisklabel, 0);
394 process_menu(MENU_yesno, NULL);
395 if (!yesno)
396 return 0;
397 nobootfix = 1;
402 i = md_check_partitions();
403 switch (i) {
404 case 0: nobootfix=1; noprepfix=1; break;
405 case 1: noprepfix=1; break;
406 case 2: nobootfix=1; break;
407 default: break;
410 return 1;
413 /* Upgrade support */
415 md_update(void)
417 nonewfsmsdos = 1;
418 md_post_newfs();
419 return 1;
424 md_check_mbr(mbr_info_t *mbri)
426 mbr_info_t *ext;
427 struct mbr_partition *part;
428 int i;
430 for (ext = mbri; ext; ext = ext->extended) {
431 part = ext->mbr.mbr_parts;
432 for (i = 0; i < MBR_PART_COUNT; part++, i++) {
433 if (part->mbrp_type == MBR_PTYPE_FAT12) {
434 bootstart = part->mbrp_start;
435 bootsize = part->mbrp_size;
436 } else if (part->mbrp_type == MBR_PTYPE_PREP &&
437 part->mbrp_size < 50) {
438 /* this is the bootinfo partition */
439 binfostart = part->mbrp_start;
440 binfosize = part->mbrp_size;
441 bootinfo_mbr = i+1;
442 } else if (part->mbrp_type == MBR_PTYPE_PREP &&
443 part->mbrp_size > 50) {
444 bprepstart = part->mbrp_start;
445 bprepsize = part->mbrp_size;
447 break;
451 /* we need to either have a pair of prep partitions, or a single
452 * fat. if neither, things are broken. */
453 if (!(bootsize >= (MIN_FAT12_BOOT/512) ||
454 (binfosize >= (MIN_BINFO_BOOT/512) &&
455 bprepsize >= (MIN_PREP_BOOT/512)))) {
456 msg_display(MSG_bootnotright);
457 msg_display_add(MSG_reeditpart, 0);
458 process_menu(MENU_yesno, NULL);
459 if (!yesno)
460 return 0;
461 return 1;
464 /* check the prep partitions */
465 if ((binfosize > 0 || bprepsize > 0) &&
466 (binfosize < (MIN_BINFO_BOOT/512) ||
467 bprepsize < (MIN_PREP_BOOT/512))) {
468 msg_display(MSG_preptoosmall);
469 msg_display_add(MSG_reeditpart, 0);
470 process_menu(MENU_yesno, NULL);
471 if (!yesno)
472 return 0;
473 return 1;
476 /* check the fat12 parititons */
477 if (bootsize > 0 && bootsize < (MIN_FAT12_BOOT/512)) {
478 msg_display(MSG_boottoosmall);
479 msg_display_add(MSG_reeditpart, 0);
480 process_menu(MENU_yesno, NULL);
481 if (!yesno)
482 return 0;
483 return 1;
486 /* if both sets contain zero, thats bad */
487 if ((bootstart == 0 || bootsize == 0) &&
488 (binfosize == 0 || binfostart == 0 ||
489 bprepsize == 0 || bprepstart == 0)) {
490 msg_display(MSG_nobootpart);
491 msg_display_add(MSG_reeditpart, 0);
492 process_menu(MENU_yesno, NULL);
493 if (!yesno)
494 return 0;
495 return 1;
497 return 2;
501 * NOTE, we use a reserved partition type, because some RS/6000 machines hang
502 * hard if they find a FAT12, and if we use type prep, that indicates that
503 * it should be read raw.
504 * One partition for FAT12 booting
505 * One partition for NetBSD
506 * One partition to hold the bootinfo.txt file
507 * One partition to hold ofwboot
511 md_mbr_use_wholedisk(mbr_info_t *mbri)
513 struct mbr_sector *mbrs = &mbri->mbr;
514 mbr_info_t *ext;
515 struct mbr_partition *part;
517 part = &mbrs->mbr_parts[0];
518 /* Set the partition information for full disk usage. */
519 while ((ext = mbri->extended)) {
520 mbri->extended = ext->extended;
521 free(ext);
523 memset(part, 0, MBR_PART_COUNT * sizeof *part);
525 part[0].mbrp_type = MBR_PTYPE_RESERVED_x21;
526 part[0].mbrp_size = FAT12_BOOT_SIZE/512;
527 part[0].mbrp_start = bsec;
528 part[0].mbrp_flag = 0;
530 part[1].mbrp_type = MBR_PTYPE_NETBSD;
531 part[1].mbrp_size = dlsize - (bsec + FAT12_BOOT_SIZE/512 +
532 BINFO_BOOT_SIZE/512 + PREP_BOOT_SIZE/512);
533 part[1].mbrp_start = bsec + FAT12_BOOT_SIZE/512 + BINFO_BOOT_SIZE/512 +
534 PREP_BOOT_SIZE/512;
535 part[1].mbrp_flag = MBR_PFLAG_ACTIVE;
537 part[2].mbrp_type = MBR_PTYPE_PREP;
538 part[2].mbrp_size = BINFO_BOOT_SIZE/512;
539 part[2].mbrp_start = bsec + FAT12_BOOT_SIZE/512;
540 part[2].mbrp_flag = 0;
542 part[3].mbrp_type = MBR_PTYPE_PREP;
543 part[3].mbrp_size = PREP_BOOT_SIZE/512;
544 part[3].mbrp_start = bsec + FAT12_BOOT_SIZE/512 + BINFO_BOOT_SIZE/512;
545 part[3].mbrp_flag = 0;
547 ptstart = part[1].mbrp_start;
548 ptsize = part[1].mbrp_size;
549 bootstart = part[0].mbrp_start;
550 bootsize = part[0].mbrp_size;
551 binfostart = part[2].mbrp_start;
552 binfosize= part[2].mbrp_size;
553 bprepstart = part[3].mbrp_start;
554 bprepsize = part[3].mbrp_size;
555 bootinfo_mbr = 4;
557 return 1;