1 /* $NetBSD: md.c,v 1.5 2009/05/16 10:40:17 nonaka Exp $ */
4 * Copyright 1997 Piermont Information Systems Inc.
7 * Based on code written by Philip A. Nelson for Piermont Information
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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
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>
45 #include <machine/cpu.h>
50 #include "menu_defs.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
;
69 md_init_set_status(int minimal
)
77 return set_bios_geom_with_mbr_guess();
81 * md back-end code for menu-driven BSD disklabel editor.
84 md_make_bsd_partitions(void)
88 int maxpart
= getmaxpartitions();
90 int part_raw
, part_bsd
;
96 * Initialize global variables that track space used on this disk.
97 * Standard 4.4BSD 8-partition labels always cover whole disk.
100 ptsize
= dlsize
- ptstart
;
102 dlsize
= ptstart
+ ptsize
;
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();
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 */
136 bsdlabel
[PART_C
].pi_offset
= ptstart
;
137 bsdlabel
[PART_C
].pi_size
= ptsize
;
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
;
163 bsdlabel
[PART_REST
].pi_offset
= 0;
164 bsdlabel
[PART_REST
].pi_size
= ptstart
;
168 * Save any partitions that are outside the area we are
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 */
178 if (p
->pi_fstype
== FS_UNUSED
|| p
->pi_size
== 0)
180 if (layoutkind
== 4) {
182 p
->pi_flags
|= PIF_MOUNT
;
184 if (p
->pi_offset
< ptstart
+ ptsize
&&
185 p
->pi_offset
+ p
->pi_size
> ptstart
)
186 /* Not outside area we are allocating */
188 if (p
->pi_fstype
== FS_SWAP
)
191 bsdlabel
[i
] = oldlabel
[i
];
194 if (layoutkind
== 4) {
195 /* XXX Check we have a sensible layout */
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.
205 if (edit_and_check_label(bsdlabel
, maxpart
, part_raw
, part_bsd
) == 0) {
206 msg_display(MSG_abort
);
209 if (md_check_partitions() == 0)
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. */
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
;
239 } else if (bsdlabel
[part
].pi_fstype
== FS_BOOT
) {
240 bootpart_prep
= part
;
242 } else if (bsdlabel
[part
].pi_fstype
== FS_OTHER
) {
243 bootpart_binfo
= part
;
247 /* oh, the confusion */
248 if (ffat
>= 1 && fprep
< 2)
250 if (ffat
< 1 && fprep
>= 2)
252 if (ffat
>=1 && fprep
>= 2)
255 msg_display(MSG_nobootpartdisklabel
);
256 process_menu(MENU_ok
, NULL
);
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
);
278 * hook called after writing disklabel to new target disk.
281 md_post_disklabel(void)
285 if (bootstart
== 0 || bootsize
== 0)
288 snprintf(bootdev
, sizeof bootdev
, "/dev/r%s%c", diskdev
,
290 run_program(RUN_DISPLAY
, "/sbin/newfs_msdos %s", bootdev
);
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.
305 run_program(RUN_DISPLAY
, "/sbin/umount /targetroot/boot");
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
)
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
);
323 snprintf(bootdev
, sizeof bootdev
, "/dev/r%s%c", diskdev
,
325 snprintf(bootbdev
, sizeof bootbdev
, "/dev/%s%c", diskdev
,
328 if (nonewfsmsdos
== 0)
329 run_program(RUN_DISPLAY
, "/sbin/newfs_msdos %s",
331 run_program(RUN_DISPLAY
, "/sbin/mount_msdos %s /mnt2",
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 "
337 run_program(RUN_DISPLAY
, "/bin/cp /tmp/bootinfo.txt "
339 run_program(RUN_DISPLAY
,
340 "/bin/cp /usr/mdec/ofwboot /mnt2/ofwboot");
341 run_program(RUN_DISPLAY
, "/sbin/umount /mnt2");
345 snprintf(bootdev
, sizeof bootdev
, "/dev/r%s%c", diskdev
,
347 snprintf(bootbdev
, sizeof bootbdev
, "/dev/%s%c", diskdev
,
349 run_program(RUN_DISPLAY
, "/bin/dd if=/dev/zero of=%s bs=512",
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
,
356 snprintf(bootbdev
, sizeof bootbdev
, "/dev/%s%c", diskdev
,
358 run_program(RUN_DISPLAY
, "/bin/dd if=/dev/zero of=%s bs=512",
360 run_program(RUN_DISPLAY
, "/bin/dd if=/tmp/bootinfo.txt "
361 "of=%s bs=512", bootbdev
);
368 md_cleanup_install(void)
378 struct mbr_partition
*part
;
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)
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
);
402 i
= md_check_partitions();
404 case 0: nobootfix
=1; noprepfix
=1; break;
405 case 1: noprepfix
=1; break;
406 case 2: nobootfix
=1; break;
413 /* Upgrade support */
424 md_check_mbr(mbr_info_t
*mbri
)
427 struct mbr_partition
*part
;
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
;
442 } else if (part
->mbrp_type
== MBR_PTYPE_PREP
&&
443 part
->mbrp_size
> 50) {
444 bprepstart
= part
->mbrp_start
;
445 bprepsize
= part
->mbrp_size
;
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
);
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
);
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
);
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
);
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
;
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
;
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 +
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
;