xref: /netbsd-src/usr.sbin/sysinst/arch/ofppc/md.c (revision 03dcb730d46d34d85c9f496c1f5a3a6a43f2b7b3)
1 /*	$NetBSD: md.c,v 1.3 2015/05/10 10:14:03 martin Exp $	*/
2 
3 /*
4  * Copyright 1997 Piermont Information Systems Inc.
5  * All rights reserved.
6  *
7  * Based on code written by Philip A. Nelson for Piermont Information
8  * Systems Inc.
9  *
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. The name of Piermont Information Systems Inc. may not be used to endorse
19  *    or promote products derived from this software without specific prior
20  *    written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
26  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32  * THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 /* md.c -- ofppc machine specific routines */
36 
37 #include <sys/param.h>
38 #include <sys/sysctl.h>
39 #include <sys/disklabel_rdb.h>
40 #include <stdio.h>
41 #include <util.h>
42 #include <machine/cpu.h>
43 
44 #include "defs.h"
45 #include "md.h"
46 #include "msg_defs.h"
47 #include "menu_defs.h"
48 #include "endian.h"
49 
50 static int check_rdb(void);
51 static uint32_t rdbchksum(void *);
52 
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;
59 static int rdb_found = 0;
60 
61 /* bootstart/bootsize are for the fat */
62 int binfostart, binfosize, bprepstart, bprepsize;
63 
64 void
65 md_init(void)
66 {
67 }
68 
69 void
70 md_init_set_status(int flags)
71 {
72 
73 	(void)flags;
74 }
75 
76 int
77 md_get_info(void)
78 {
79 
80 	if (check_rdb())
81 		return 1;
82 
83 	return set_bios_geom_with_mbr_guess();
84 }
85 
86 /*
87  * md back-end code for menu-driven BSD disklabel editor.
88  */
89 int
90 md_make_bsd_partitions(void)
91 {
92 	int i;
93 	int part;
94 	int maxpart = getmaxpartitions();
95 	int partstart;
96 	int part_raw, part_bsd;
97 	int ptend;
98 	int no_swap = 0;
99 	partinfo *p;
100 
101 	if (rdb_found) {
102 		/*
103 		 * We found RDB partitions on the disk, which cannot be
104 		 * modified by rewriting the disklabel.
105 		 * So just use what we have got.
106 		 */
107 		for (part = 0; part < maxpart; part++) {
108 			if (PI_ISBSDFS(&pm->bsdlabel[part])) {
109 				pm->bsdlabel[part].pi_flags |=
110 				    PIF_NEWFS | PIF_MOUNT;
111 
112 				if (part == PART_A)
113 					strcpy(pm->bsdlabel[part].pi_mount, "/");
114 			}
115 		}
116 
117 		part_bsd = part_raw = getrawpartition();
118 		if (part_raw == -1)
119 			part_raw = PART_C;	/* for sanity... */
120 		pm->bsdlabel[part_raw].pi_offset = 0;
121 		pm->bsdlabel[part_raw].pi_size = pm->dlsize;
122 
123 		set_sizemultname_meg();
124 rdb_edit_check:
125 		if (edit_and_check_label(pm->bsdlabel, maxpart, part_raw,
126 		    part_bsd) == 0) {
127 			msg_display(MSG_abort);
128 			return 0;
129 		}
130 		if (md_check_partitions() == 0)
131 			goto rdb_edit_check;
132 
133 		return 1;
134 	}
135 
136 	/*
137 	 * Initialize global variables that track space used on this disk.
138 	 * Standard 4.4BSD 8-partition labels always cover whole disk.
139 	 */
140 	if (pm->ptsize == 0)
141 		pm->ptsize = pm->dlsize - pm->ptstart;
142 	if (pm->dlsize == 0)
143 		pm->dlsize = pm->ptstart + pm->ptsize;
144 
145 	partstart = pm->ptstart;
146 	ptend = pm->ptstart + pm->ptsize;
147 
148 	/* Ask for layout type -- standard or special */
149 	msg_display(MSG_layout,
150 		    pm->ptsize / (MEG / pm->sectorsize),
151 		    DEFROOTSIZE + DEFSWAPSIZE + DEFUSRSIZE,
152 		    DEFROOTSIZE + DEFSWAPSIZE + DEFUSRSIZE + XNEEDMB);
153 
154 	process_menu(MENU_layout, NULL);
155 
156 	/* Set so we use the 'real' geometry for rounding, input in MB */
157 	pm->current_cylsize = pm->dlcylsize;
158 	set_sizemultname_meg();
159 
160 	/* Build standard partitions */
161 	memset(&pm->bsdlabel, 0, sizeof pm->bsdlabel);
162 
163 	/* Set initial partition types to unused */
164 	for (part = 0 ; part < maxpart ; ++part)
165 		pm->bsdlabel[part].pi_fstype = FS_UNUSED;
166 
167 	/* Whole disk partition */
168 	part_raw = getrawpartition();
169 	if (part_raw == -1)
170 		part_raw = PART_C;	/* for sanity... */
171 	pm->bsdlabel[part_raw].pi_offset = 0;
172 	pm->bsdlabel[part_raw].pi_size = pm->dlsize;
173 
174 	if (part_raw == PART_D) {
175 		/* Probably a system that expects an i386 style mbr */
176 		part_bsd = PART_C;
177 		pm->bsdlabel[PART_C].pi_offset = pm->ptstart;
178 		pm->bsdlabel[PART_C].pi_size = pm->ptsize;
179 	} else {
180 		part_bsd = part_raw;
181 	}
182 
183 	if (pm->bootsize != 0) {
184 		pm->bsdlabel[PART_BOOT_FAT12].pi_fstype = FS_MSDOS;
185 		pm->bsdlabel[PART_BOOT_FAT12].pi_size = pm->bootsize;
186 		pm->bsdlabel[PART_BOOT_FAT12].pi_offset = pm->bootstart;
187 		pm->bsdlabel[PART_BOOT_FAT12].pi_flags |= PART_BOOT_FAT12_PI_FLAGS;
188 		strlcpy(pm->bsdlabel[PART_BOOT_FAT12].pi_mount,
189 		    PART_BOOT_FAT12_PI_MOUNT,
190 		    sizeof pm->bsdlabel[PART_BOOT_FAT12].pi_mount);
191 	}
192 	if (binfosize != 0) {
193 		pm->bsdlabel[PART_BOOT_BINFO].pi_fstype = FS_OTHER;
194 		pm->bsdlabel[PART_BOOT_BINFO].pi_size = binfosize;
195 		pm->bsdlabel[PART_BOOT_BINFO].pi_offset = binfostart;
196 	}
197 	if (bprepsize != 0) {
198 		pm->bsdlabel[PART_BOOT_PREP].pi_fstype = FS_BOOT;
199 		pm->bsdlabel[PART_BOOT_PREP].pi_size = bprepsize;
200 		pm->bsdlabel[PART_BOOT_PREP].pi_offset = bprepstart;
201 	}
202 
203 #ifdef PART_REST
204 	pm->bsdlabel[PART_REST].pi_offset = 0;
205 	pm->bsdlabel[PART_REST].pi_size = pm->ptstart;
206 #endif
207 
208 	/*
209 	 * Save any partitions that are outside the area we are
210 	 * going to use.
211 	 * In particular this saves details of the other MBR
212 	 * partitions on a multiboot i386 system.
213 	 */
214 	 for (i = maxpart; i--;) {
215 		if (pm->bsdlabel[i].pi_size != 0)
216 			/* Don't overwrite special partitions */
217 			continue;
218 		p = &pm->oldlabel[i];
219 		if (p->pi_fstype == FS_UNUSED || p->pi_size == 0)
220 			continue;
221 		if (layoutkind == LY_USEEXIST) {
222 			if (PI_ISBSDFS(p))
223 				p->pi_flags |= PIF_MOUNT;
224 		} else {
225 			if (p->pi_offset < pm->ptstart + pm->ptsize &&
226 			    p->pi_offset + p->pi_size > pm->ptstart)
227 				/* Not outside area we are allocating */
228 				continue;
229 			if (p->pi_fstype == FS_SWAP)
230 				no_swap = 1;
231 		}
232 		pm->bsdlabel[i] = pm->oldlabel[i];
233 	 }
234 
235 	if (layoutkind == LY_USEEXIST) {
236 		/* XXX Check we have a sensible layout */
237 		;
238 	} else
239 		get_ptn_sizes(partstart, ptend - partstart, no_swap);
240 
241 	/*
242 	 * OK, we have a partition table. Give the user the chance to
243 	 * edit it and verify it's OK, or abort altogether.
244 	 */
245  edit_check:
246 	if (edit_and_check_label(pm->bsdlabel, maxpart, part_raw, part_bsd) == 0) {
247 		msg_display(MSG_abort);
248 		return 0;
249 	}
250 	if (md_check_partitions() == 0)
251 		goto edit_check;
252 
253 	/* Disk name */
254 	msg_prompt(MSG_packname, pm->bsddiskname, pm->bsddiskname, sizeof pm->bsddiskname);
255 
256 	/* save label to disk for MI code to update. */
257 	(void) savenewlabel(pm->bsdlabel, maxpart);
258 
259 	/* Everything looks OK. */
260 	return 1;
261 }
262 
263 /*
264  * any additional partition validation
265  */
266 int
267 md_check_partitions(void)
268 {
269 	int part, fprep=0, ffat=0;
270 
271 	if (rdb_found)
272 		return 1;
273 
274 	/* we need to find a boot partition, otherwise we can't create
275 	 * our msdos fs boot partition.  We make the assumption that
276 	 * the user hasn't done something stupid, like move it away
277 	 * from the MBR partition.
278 	 */
279 	for (part = PART_A; part < MAXPARTITIONS; part++) {
280 		if (pm->bsdlabel[part].pi_fstype == FS_MSDOS) {
281 			bootpart_fat12 = part;
282 			ffat++;
283 		} else if (pm->bsdlabel[part].pi_fstype == FS_BOOT) {
284 			bootpart_prep = part;
285 			fprep++;
286 		} else if (pm->bsdlabel[part].pi_fstype == FS_OTHER) {
287 			bootpart_binfo = part;
288 			fprep++;
289 		}
290 	}
291 	/* oh, the confusion */
292 	if (ffat >= 1 && fprep < 2)
293 		return 1;
294 	if (ffat < 1 && fprep >= 2)
295 		return 2;
296 	if (ffat >=1 && fprep >= 2)
297 		return 3;
298 
299 	msg_display(MSG_nobootpartdisklabel);
300 	process_menu(MENU_ok, NULL);
301 	return 0;
302 }
303 
304 /*
305  * hook called before writing new disklabel.
306  */
307 int
308 md_pre_disklabel(void)
309 {
310 
311 	if (rdb_found)
312 		return 0;
313 
314 	msg_display(MSG_dofdisk);
315 
316 	/* write edited MBR onto disk. */
317 	if (write_mbr(pm->diskdev, &mbr, 1) != 0) {
318 		msg_display(MSG_wmbrfail);
319 		process_menu(MENU_ok, NULL);
320 		return 1;
321 	}
322 	return 0;
323 }
324 
325 /*
326  * hook called after writing disklabel to new target disk.
327  */
328 int
329 md_post_disklabel(void)
330 {
331 	char bootdev[100];
332 
333 	if (pm->bootstart == 0 || pm->bootsize == 0 || rdb_found)
334 		return 0;
335 
336 	snprintf(bootdev, sizeof bootdev, "/dev/r%s%c", pm->diskdev,
337 	    'a'+bootpart_fat12);
338 	run_program(RUN_DISPLAY, "/sbin/newfs_msdos %s", bootdev);
339 
340 	return 0;
341 }
342 
343 /*
344  * hook called after upgrade() or install() has finished setting
345  * up the target disk but immediately before the user is given the
346  * ``disks are now set up'' message.
347  */
348 int
349 md_post_newfs(void)
350 {
351 
352 	/* No bootblock. We use ofwboot from a partition visiable by OFW. */
353 	return 0;
354 }
355 
356 int
357 md_post_extract(void)
358 {
359 	char bootdev[100], bootbdev[100], version[64];
360 
361 	/* if we can't make it bootable, just punt */
362 	if ((nobootfix && noprepfix) || rdb_found)
363 		return 0;
364 
365 	snprintf(version, sizeof version, "NetBSD/%s %s", MACH, REL);
366 	run_program(RUN_DISPLAY, "/usr/mdec/mkbootinfo '%s' %d "
367 	    "/tmp/bootinfo.txt", version, bootinfo_mbr);
368 
369 	if (!nobootfix) {
370 		run_program(RUN_DISPLAY, "/bin/mkdir -p /%s/boot/ppc",
371 		    target_prefix());
372 		run_program(RUN_DISPLAY, "/bin/mkdir -p /%s/boot/netbsd",
373 		    target_prefix());
374 		run_program(RUN_DISPLAY, "/bin/cp /usr/mdec/ofwboot "
375 		    "/%s/boot/netbsd", target_prefix());
376 		run_program(RUN_DISPLAY, "/bin/cp /tmp/bootinfo.txt "
377 		    "/%s/boot/ppc", target_prefix());
378 		run_program(RUN_DISPLAY, "/bin/cp /usr/mdec/ofwboot "
379 		    "/%s/boot/ofwboot", target_prefix());
380 	}
381 
382 	if (!noprepfix) {
383 		snprintf(bootdev, sizeof bootdev, "/dev/r%s%c", pm->diskdev,
384 		    'a'+bootpart_prep);
385 		snprintf(bootbdev, sizeof bootbdev, "/dev/%s%c", pm->diskdev,
386 		    'a'+bootpart_prep);
387 		run_program(RUN_DISPLAY, "/bin/dd if=/dev/zero of=%s bs=512",
388 		    bootdev);
389 		run_program(RUN_DISPLAY, "/bin/dd if=/usr/mdec/ofwboot "
390 		    "of=%s bs=512", bootbdev);
391 
392 		snprintf(bootdev, sizeof bootdev, "/dev/r%s%c", pm->diskdev,
393 		    'a'+bootpart_binfo);
394 		snprintf(bootbdev, sizeof bootbdev, "/dev/%s%c", pm->diskdev,
395 		    'a'+bootpart_binfo);
396 		run_program(RUN_DISPLAY, "/bin/dd if=/dev/zero of=%s bs=512",
397 		    bootdev);
398 		run_program(RUN_DISPLAY, "/bin/dd if=/tmp/bootinfo.txt "
399 		    "of=%s bs=512", bootbdev);
400 	}
401 
402 	return 0;
403 }
404 
405 void
406 md_cleanup_install(void)
407 {
408 
409 #ifndef DEBUG
410 	enable_rc_conf();
411 #endif
412 }
413 
414 int
415 md_pre_update(void)
416 {
417 	struct mbr_partition *part;
418 	mbr_info_t *ext;
419 	int i;
420 
421 	if (check_rdb())
422 		return 1;
423 
424 	read_mbr(pm->diskdev, &mbr);
425 	/* do a sanity check of the partition table */
426 	for (ext = &mbr; ext; ext = ext->extended) {
427 		part = ext->mbr.mbr_parts;
428 		for (i = 0; i < MBR_PART_COUNT; part++, i++) {
429 			if (part->mbrp_type == MBR_PTYPE_PREP &&
430 			    part->mbrp_size > 50)
431 				bootinfo_mbr = i+1;
432 			if (part->mbrp_type == MBR_PTYPE_RESERVED_x21 &&
433 			    part->mbrp_size < (MIN_FAT12_BOOT/512)) {
434 				msg_display(MSG_boottoosmall);
435 				msg_display_add(MSG_nobootpartdisklabel, 0);
436 				if (!ask_yesno(NULL))
437 					return 0;
438 				nobootfix = 1;
439 			}
440 		}
441 	}
442 
443 	i = md_check_partitions();
444 	switch (i) {
445 	case 0: nobootfix=1; noprepfix=1; break;
446 	case 1: noprepfix=1; break;
447 	case 2: nobootfix=1; break;
448 	default: break;
449 	}
450 
451 	return 1;
452 }
453 
454 /* Upgrade support */
455 int
456 md_update(void)
457 {
458 
459 	nonewfsmsdos = 1;
460 	md_post_newfs();
461 	return 1;
462 }
463 
464 
465 int
466 md_check_mbr(mbr_info_t *mbri)
467 {
468 	mbr_info_t *ext;
469 	struct mbr_partition *part;
470 	int i;
471 
472 	for (ext = mbri; ext; ext = ext->extended) {
473 		part = ext->mbr.mbr_parts;
474 		for (i = 0; i < MBR_PART_COUNT; part++, i++) {
475 			if (part->mbrp_type == MBR_PTYPE_FAT12) {
476 				pm->bootstart = part->mbrp_start;
477 				pm->bootsize = part->mbrp_size;
478 			} else if (part->mbrp_type == MBR_PTYPE_PREP &&
479 			    part->mbrp_size < 50) {
480 				/* this is the bootinfo partition */
481 				binfostart = part->mbrp_start;
482 				binfosize = part->mbrp_size;
483 				bootinfo_mbr = i+1;
484 			} else if (part->mbrp_type == MBR_PTYPE_PREP &&
485 			    part->mbrp_size > 50) {
486 				bprepstart = part->mbrp_start;
487 				bprepsize = part->mbrp_size;
488 			}
489 			break;
490 		}
491 	}
492 
493 	/* we need to either have a pair of prep partitions, or a single
494 	 * fat.  if neither, things are broken. */
495 	if (!(pm->bootsize >= (MIN_FAT12_BOOT/512) ||
496 		(binfosize >= (MIN_BINFO_BOOT/512) &&
497 		    bprepsize >= (MIN_PREP_BOOT/512)))) {
498 		msg_display(MSG_bootnotright);
499 		msg_display_add(MSG_reeditpart, 0);
500 		if (!ask_yesno(NULL))
501 			return 0;
502 		return 1;
503 	}
504 
505 	/* check the prep partitions */
506 	if ((binfosize > 0 || bprepsize > 0) &&
507 	    (binfosize < (MIN_BINFO_BOOT/512) ||
508 		bprepsize < (MIN_PREP_BOOT/512))) {
509 		msg_display(MSG_preptoosmall);
510 		msg_display_add(MSG_reeditpart, 0);
511 		if (!ask_yesno(NULL))
512 			return 0;
513 		return 1;
514 	}
515 
516 	/* check the fat12 parititons */
517 	if (pm->bootsize > 0 && pm->bootsize < (MIN_FAT12_BOOT/512)) {
518 		msg_display(MSG_boottoosmall);
519 		msg_display_add(MSG_reeditpart, 0);
520 		if (!ask_yesno(NULL))
521 			return 0;
522 		return 1;
523 	}
524 
525 	/* if both sets contain zero, thats bad */
526 	if ((pm->bootstart == 0 || pm->bootsize == 0) &&
527 	    (binfosize == 0 || binfostart == 0 ||
528 		bprepsize == 0 || bprepstart == 0)) {
529 		msg_display(MSG_nobootpart);
530 		msg_display_add(MSG_reeditpart, 0);
531 		if (!ask_yesno(NULL))
532 			return 0;
533 		return 1;
534 	}
535 	return 2;
536 }
537 
538 /*
539  * NOTE, we use a reserved partition type, because some RS/6000 machines hang
540  * hard if they find a FAT12, and if we use type prep, that indicates that
541  * it should be read raw.
542  * One partition for FAT12 booting
543  * One partition for NetBSD
544  * One partition to hold the bootinfo.txt file
545  * One partition to hold ofwboot
546  */
547 
548 int
549 md_mbr_use_wholedisk(mbr_info_t *mbri)
550 {
551 	struct mbr_sector *mbrs = &mbri->mbr;
552 	mbr_info_t *ext;
553 	struct mbr_partition *part;
554 
555 	part = &mbrs->mbr_parts[0];
556 	/* Set the partition information for full disk usage. */
557 	while ((ext = mbri->extended)) {
558 		mbri->extended = ext->extended;
559 		free(ext);
560 	}
561 	memset(part, 0, MBR_PART_COUNT * sizeof *part);
562 
563 	part[0].mbrp_type = MBR_PTYPE_RESERVED_x21;
564 	part[0].mbrp_size = FAT12_BOOT_SIZE/512;
565 	part[0].mbrp_start = bsec;
566 	part[0].mbrp_flag = 0;
567 
568 	part[1].mbrp_type = MBR_PTYPE_NETBSD;
569 	part[1].mbrp_size = pm->dlsize - (bsec + FAT12_BOOT_SIZE/512 +
570 	    BINFO_BOOT_SIZE/512 + PREP_BOOT_SIZE/512);
571 	part[1].mbrp_start = bsec + FAT12_BOOT_SIZE/512 + BINFO_BOOT_SIZE/512 +
572 	    PREP_BOOT_SIZE/512;
573 	part[1].mbrp_flag = MBR_PFLAG_ACTIVE;
574 
575 	part[2].mbrp_type = MBR_PTYPE_PREP;
576 	part[2].mbrp_size = BINFO_BOOT_SIZE/512;
577 	part[2].mbrp_start = bsec + FAT12_BOOT_SIZE/512;
578 	part[2].mbrp_flag = 0;
579 
580 	part[3].mbrp_type = MBR_PTYPE_PREP;
581 	part[3].mbrp_size = PREP_BOOT_SIZE/512;
582 	part[3].mbrp_start = bsec + FAT12_BOOT_SIZE/512 + BINFO_BOOT_SIZE/512;
583 	part[3].mbrp_flag = 0;
584 
585 	pm->ptstart = part[1].mbrp_start;
586 	pm->ptsize = part[1].mbrp_size;
587 	pm->bootstart = part[0].mbrp_start;
588 	pm->bootsize = part[0].mbrp_size;
589 	binfostart = part[2].mbrp_start;
590 	binfosize= part[2].mbrp_size;
591 	bprepstart = part[3].mbrp_start;
592 	bprepsize = part[3].mbrp_size;
593 	bootinfo_mbr = 4;
594 
595 	return 1;
596 }
597 
598 const char *md_disklabel_cmd(void)
599 {
600 
601 	/* we cannot rewrite an RDB disklabel */
602 	if (rdb_found)
603 		return "sync No disklabel";
604 
605 	return "disklabel -w -r";
606 }
607 
608 static int
609 check_rdb(void)
610 {
611 	char buf[512], diskpath[MAXPATHLEN];
612 	struct rdblock *rdb;
613 	off_t blk;
614 	int fd;
615 
616 	/* Find out if this disk has a valid RDB, before continuing. */
617 	rdb = (struct rdblock *)buf;
618 	fd = opendisk(pm->diskdev, O_RDONLY, diskpath, sizeof(diskpath), 0);
619 	if (fd < 0)
620 		return 0;
621 	for (blk = 0; blk < RDB_MAXBLOCKS; blk++) {
622 		if (pread(fd, rdb, 512, blk * 512) != 512)
623 			return 0;
624 		if (rdb->id == RDBLOCK_ID && rdbchksum(rdb) == 0) {
625 			rdb_found = 1;	/* do not repartition! */
626 			return 1;
627 		}
628 	}
629 	return 0;
630 }
631 
632 static uint32_t
633 rdbchksum(void *bdata)
634 {
635 	uint32_t *blp, cnt, val;
636 
637 	blp = bdata;
638 	cnt = blp[1];
639 	val = 0;
640 	while (cnt--)
641 		val += *blp++;
642 	return val;
643 }
644 
645 int
646 md_pre_mount()
647 {
648 
649 	return 0;
650 }
651