xref: /netbsd-src/usr.sbin/sysinst/arch/ofppc/md.c (revision 8ecbf5f02b752fcb7debe1a8fab1dc82602bc760)
1 /*	$NetBSD: md.c,v 1.10 2020/01/27 21:21:23 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 part_id bootpart_fat12 = NO_PART, bootpart_binfo = NO_PART,
56     bootpart_prep = NO_PART;
57 static int bootinfo_mbr = 1;
58 static int rdb_found = 0;
59 
60 /* bootstart/bootsize are for the fat */
61 int binfostart, binfosize, bprepstart, bprepsize;
62 
63 void
64 md_init(void)
65 {
66 }
67 
68 void
69 md_init_set_status(int flags)
70 {
71 
72 	(void)flags;
73 }
74 
75 bool
76 md_get_info(struct install_partition_desc *install)
77 {
78 
79 	if (check_rdb())
80 		return true;
81 
82 
83 	if (pm->no_mbr || pm->no_part)
84 		return true;
85 
86 	if (pm->parts == NULL) {
87 
88 		const struct disk_partitioning_scheme *ps =
89 		    select_part_scheme(pm, NULL, true, NULL);
90 
91 		if (!ps)
92 			return false;
93 
94 		struct disk_partitions *parts =
95 		   (*ps->create_new_for_disk)(pm->diskdev,
96 		   0, pm->dlsize, true, NULL);
97 		if (!parts)
98 			return false;
99 
100 		pm->parts = parts;
101 		if (ps->size_limit > 0 && pm->dlsize > ps->size_limit)
102 			pm->dlsize = ps->size_limit;
103 	}
104 
105 	return set_bios_geom_with_mbr_guess(pm->parts);
106 }
107 
108 /*
109  * md back-end code for menu-driven BSD disklabel editor.
110  */
111 bool
112 md_make_bsd_partitions(struct install_partition_desc *install)
113 {
114 #if 0
115 	int i;
116 	int part;
117 	int maxpart = getmaxpartitions();
118 	int partstart;
119 	int part_raw, part_bsd;
120 	int ptend;
121 	int no_swap = 0;
122 #endif
123 
124 	if (rdb_found) {
125 #if 0
126 	/*
127 	 * XXX - need to test on real machine if the disklabel code
128 	 * deals with RDB partitions properly, otherwise write
129 	 * a read-only RDB backend
130 	 */
131 		/*
132 		 * We found RDB partitions on the disk, which cannot be
133 		 * modified by rewriting the disklabel.
134 		 * So just use what we have got.
135 		 */
136 		for (part = 0; part < maxpart; part++) {
137 			if (PI_ISBSDFS(&pm->bsdlabel[part])) {
138 				pm->bsdlabel[part].pi_flags |=
139 				    PIF_NEWFS | PIF_MOUNT;
140 
141 				if (part == PART_A)
142 					strcpy(pm->bsdlabel[part].pi_mount, "/");
143 			}
144 		}
145 
146 		part_bsd = part_raw = getrawpartition();
147 		if (part_raw == -1)
148 			part_raw = PART_C;	/* for sanity... */
149 		pm->bsdlabel[part_raw].pi_offset = 0;
150 		pm->bsdlabel[part_raw].pi_size = pm->dlsize;
151 
152 		set_sizemultname_meg();
153 rdb_edit_check:
154 		if (edit_and_check_label(pm->bsdlabel, maxpart, part_raw,
155 		    part_bsd) == 0) {
156 			msg_display(MSG_abort);
157 			return 0;
158 		}
159 		if (md_check_partitions() == 0)
160 			goto rdb_edit_check;
161 #endif
162 		return 1;
163 	}
164 
165 	/*
166 	 * Initialize global variables that track space used on this disk.
167 	 * Standard 4.4BSD 8-partition labels always cover whole disk.
168 	 */
169 	if (pm->ptsize == 0)
170 		pm->ptsize = pm->dlsize - pm->ptstart;
171 	if (pm->dlsize == 0)
172 		pm->dlsize = pm->ptstart + pm->ptsize;
173 
174 #if 0
175 	partstart = pm->ptstart;
176 	ptend = pm->ptstart + pm->ptsize;
177 
178 	/* Ask for layout type -- standard or special */
179 	msg_fmt_display(MSG_layout, "%d%d%d",
180 		    pm->ptsize / (MEG / pm->sectorsize),
181 		    DEFROOTSIZE + DEFSWAPSIZE + DEFUSRSIZE,
182 		    DEFROOTSIZE + DEFSWAPSIZE + DEFUSRSIZE + XNEEDMB);
183 
184 	process_menu(MENU_layout, NULL);
185 
186 	/* Set so we use the 'real' geometry for rounding, input in MB */
187 	pm->current_cylsize = pm->dlcylsize;
188 	set_sizemultname_meg();
189 
190 	/* Build standard partitions */
191 	memset(&pm->bsdlabel, 0, sizeof pm->bsdlabel);
192 
193 	/* Set initial partition types to unused */
194 	for (part = 0 ; part < maxpart ; ++part)
195 		pm->bsdlabel[part].pi_fstype = FS_UNUSED;
196 
197 	/* Whole disk partition */
198 	part_raw = getrawpartition();
199 	if (part_raw == -1)
200 		part_raw = PART_C;	/* for sanity... */
201 	pm->bsdlabel[part_raw].pi_offset = 0;
202 	pm->bsdlabel[part_raw].pi_size = pm->dlsize;
203 
204 	if (part_raw == PART_D) {
205 		/* Probably a system that expects an i386 style mbr */
206 		part_bsd = PART_C;
207 		pm->bsdlabel[PART_C].pi_offset = pm->ptstart;
208 		pm->bsdlabel[PART_C].pi_size = pm->ptsize;
209 	} else {
210 		part_bsd = part_raw;
211 	}
212 
213 	if (pm->bootsize != 0) {
214 		pm->bsdlabel[PART_BOOT_FAT12].pi_fstype = FS_MSDOS;
215 		pm->bsdlabel[PART_BOOT_FAT12].pi_size = pm->bootsize;
216 		pm->bsdlabel[PART_BOOT_FAT12].pi_offset = pm->bootstart;
217 		pm->bsdlabel[PART_BOOT_FAT12].pi_flags |= PART_BOOT_FAT12_PI_FLAGS;
218 		strlcpy(pm->bsdlabel[PART_BOOT_FAT12].pi_mount,
219 		    PART_BOOT_FAT12_PI_MOUNT,
220 		    sizeof pm->bsdlabel[PART_BOOT_FAT12].pi_mount);
221 	}
222 	if (binfosize != 0) {
223 		pm->bsdlabel[PART_BOOT_BINFO].pi_fstype = FS_OTHER;
224 		pm->bsdlabel[PART_BOOT_BINFO].pi_size = binfosize;
225 		pm->bsdlabel[PART_BOOT_BINFO].pi_offset = binfostart;
226 	}
227 	if (bprepsize != 0) {
228 		pm->bsdlabel[PART_BOOT_PREP].pi_fstype = FS_BOOT;
229 		pm->bsdlabel[PART_BOOT_PREP].pi_size = bprepsize;
230 		pm->bsdlabel[PART_BOOT_PREP].pi_offset = bprepstart;
231 	}
232 
233 #ifdef PART_REST
234 	pm->bsdlabel[PART_REST].pi_offset = 0;
235 	pm->bsdlabel[PART_REST].pi_size = pm->ptstart;
236 #endif
237 
238 	/*
239 	 * Save any partitions that are outside the area we are
240 	 * going to use.
241 	 * In particular this saves details of the other MBR
242 	 * partitions on a multiboot i386 system.
243 	 */
244 	 for (i = maxpart; i--;) {
245 		if (pm->bsdlabel[i].pi_size != 0)
246 			/* Don't overwrite special partitions */
247 			continue;
248 		p = &pm->oldlabel[i];
249 		if (p->pi_fstype == FS_UNUSED || p->pi_size == 0)
250 			continue;
251 		if (layoutkind == LY_USEEXIST) {
252 			if (PI_ISBSDFS(p))
253 				p->pi_flags |= PIF_MOUNT;
254 		} else {
255 			if (p->pi_offset < pm->ptstart + pm->ptsize &&
256 			    p->pi_offset + p->pi_size > pm->ptstart)
257 				/* Not outside area we are allocating */
258 				continue;
259 			if (p->pi_fstype == FS_SWAP)
260 				no_swap = 1;
261 		}
262 		pm->bsdlabel[i] = pm->oldlabel[i];
263 	 }
264 
265 	if (layoutkind == LY_USEEXIST) {
266 		/* XXX Check we have a sensible layout */
267 		;
268 	} else
269 		get_ptn_sizes(partstart, ptend - partstart, no_swap);
270 
271 	/*
272 	 * OK, we have a partition table. Give the user the chance to
273 	 * edit it and verify it's OK, or abort altogether.
274 	 */
275  edit_check:
276 	if (edit_and_check_label(pm->bsdlabel, maxpart, part_raw, part_bsd) == 0) {
277 		msg_display(MSG_abort);
278 		return 0;
279 	}
280 	if (md_check_partitions() == 0)
281 		goto edit_check;
282 
283 	/* Disk name */
284 	msg_prompt(MSG_packname, pm->bsddiskname, pm->bsddiskname, sizeof pm->bsddiskname);
285 
286 	/* save label to disk for MI code to update. */
287 	(void) savenewlabel(pm->bsdlabel, maxpart);
288 
289 	/* Everything looks OK. */
290 	return 1;
291 #endif
292 
293 	return make_bsd_partitions(install);
294 }
295 
296 /*
297  * any additional partition validation
298  */
299 bool
300 md_check_partitions(struct install_partition_desc *install)
301 {
302 	struct disk_partitions *parts;
303 	struct disk_part_info info;
304 	int fprep=0, ffat=0;
305 	part_id part;
306 
307 	if (rdb_found)
308 		return 1;
309 
310 	if (install->num < 1)
311 		return false;
312 	parts = install->infos[0].parts;	/* disklabel parts */
313 	if (parts->parent)
314 		parts = parts->parent;		/* MBR parts */
315 
316 	/* we need to find a boot partition, otherwise we can't create
317 	 * our msdos fs boot partition.  We make the assumption that
318 	 * the user hasn't done something stupid, like move it away
319 	 * from the MBR partition.
320 	 */
321 	for (part = 0; part < parts->num_part; part++) {
322 		if (!parts->pscheme->get_part_info(parts, part, &info))
323 			continue;
324 
325 		if (info.fs_type == FS_MSDOS) {
326 			bootpart_fat12 = part;
327 			ffat++;
328 		} else if (info.fs_type == FS_BOOT) {
329 			bootpart_prep = part;
330 			fprep++;
331 		} else if (info.fs_type == FS_OTHER) {
332 			bootpart_binfo = part;
333 			fprep++;
334 		}
335 	}
336 	/* oh, the confusion */
337 	if (ffat >= 1 && fprep < 2) {
338 		noprepfix = 1;
339 		return true;
340 	}
341 	if (ffat < 1 && fprep >= 2) {
342 		nobootfix = 1;
343 		return true;
344 	}
345 	if (ffat >=1 && fprep >= 2) {
346 		return true;
347 	}
348 
349 	msg_display(MSG_nobootpartdisklabel);
350 	process_menu(MENU_ok, NULL);
351 	nobootfix = 1;
352 	return false;
353 }
354 
355 /*
356  * hook called before writing new disklabel.
357  */
358 bool
359 md_pre_disklabel(struct install_partition_desc *install,
360     struct disk_partitions *parts)
361 {
362 
363 	if (rdb_found)
364 		return true;
365 
366 
367 	if (parts->parent == NULL)
368 		return true;	/* no outer partitions */
369 
370 	parts = parts->parent;
371 
372 	msg_display_subst(MSG_dofdisk, 3, parts->disk,
373 	    msg_string(parts->pscheme->name),
374 	    msg_string(parts->pscheme->short_name));
375 
376 	/* write edited "MBR" onto disk. */
377 	if (!parts->pscheme->write_to_disk(parts)) {
378 		msg_display(MSG_wmbrfail);
379 		process_menu(MENU_ok, NULL);
380 		return false;
381 	}
382 	return true;
383 }
384 
385 /*
386  * hook called after writing disklabel to new target disk.
387  */
388 bool
389 md_post_disklabel(struct install_partition_desc *install,
390     struct disk_partitions *parts)
391 {
392 	char bootdev[100];
393 
394 	if (pm->bootstart == 0 || pm->bootsize == 0 || rdb_found)
395 		return 0;
396 
397 	snprintf(bootdev, sizeof bootdev, "/dev/r%s%c", pm->diskdev,
398 	    (char)('a'+bootpart_fat12));
399 	run_program(RUN_DISPLAY, "/sbin/newfs_msdos %s", bootdev);
400 
401 	return 0;
402 }
403 
404 /*
405  * hook called after upgrade() or install() has finished setting
406  * up the target disk but immediately before the user is given the
407  * ``disks are now set up'' message.
408  */
409 int
410 md_post_newfs(struct install_partition_desc *install)
411 {
412 
413 	/* No bootblock. We use ofwboot from a partition visiable by OFW. */
414 	return 0;
415 }
416 
417 int
418 md_post_extract(struct install_partition_desc *install)
419 {
420 	char bootdev[100], bootbdev[100], version[64];
421 	struct disk_partitions *parts;
422 
423 	/* if we can't make it bootable, just punt */
424 	if ((nobootfix && noprepfix) || rdb_found)
425 		return 0;
426 
427 	snprintf(version, sizeof version, "NetBSD/%s %s", MACH, REL);
428 	run_program(RUN_DISPLAY, "/usr/mdec/mkbootinfo '%s' %d "
429 	    "/tmp/bootinfo.txt", version, bootinfo_mbr);
430 
431 	if (!nobootfix) {
432 		run_program(RUN_DISPLAY, "/bin/mkdir -p /%s/boot/ppc",
433 		    target_prefix());
434 		run_program(RUN_DISPLAY, "/bin/mkdir -p /%s/boot/netbsd",
435 		    target_prefix());
436 		run_program(RUN_DISPLAY, "/bin/cp /usr/mdec/ofwboot "
437 		    "/%s/boot/netbsd", target_prefix());
438 		run_program(RUN_DISPLAY, "/bin/cp /tmp/bootinfo.txt "
439 		    "/%s/boot/ppc", target_prefix());
440 		run_program(RUN_DISPLAY, "/bin/cp /usr/mdec/ofwboot "
441 		    "/%s/boot/ofwboot", target_prefix());
442 	}
443 
444 	if (!noprepfix && install != NULL && install->num > 0) {
445 		parts = install->infos[0].parts;	/* disklabel */
446 		if (parts->parent != NULL)
447 			parts = parts->parent;		/* MBR */
448 
449 		parts->pscheme->get_part_device(parts, bootpart_prep,
450 		    bootdev, sizeof bootdev, NULL, raw_dev_name, true, true);
451 		parts->pscheme->get_part_device(parts, bootpart_prep,
452 		    bootbdev, sizeof bootbdev, NULL, plain_name, true, true);
453 		run_program(RUN_DISPLAY, "/bin/dd if=/dev/zero of=%s bs=512",
454 		    bootdev);
455 		run_program(RUN_DISPLAY, "/bin/dd if=/usr/mdec/ofwboot "
456 		    "of=%s bs=512", bootbdev);
457 
458 		parts->pscheme->get_part_device(parts, bootpart_binfo,
459 		    bootdev, sizeof bootdev, NULL, raw_dev_name, true, true);
460 		parts->pscheme->get_part_device(parts, bootpart_binfo,
461 		    bootbdev, sizeof bootbdev, NULL, plain_name, true, true);
462 		run_program(RUN_DISPLAY, "/bin/dd if=/dev/zero of=%s bs=512",
463 		    bootdev);
464 		run_program(RUN_DISPLAY, "/bin/dd if=/tmp/bootinfo.txt "
465 		    "of=%s bs=512", bootbdev);
466 	}
467 
468 	return 0;
469 }
470 
471 void
472 md_cleanup_install(struct install_partition_desc *install)
473 {
474 
475 #ifndef DEBUG
476 	enable_rc_conf();
477 #endif
478 }
479 
480 int
481 md_pre_update(struct install_partition_desc *install)
482 {
483 #if 0
484 	struct mbr_partition *part;
485 	mbr_info_t *ext;
486 	int i;
487 #endif
488 
489 	if (check_rdb())
490 		return 1;
491 
492 #if 0
493 	read_mbr(pm->diskdev, &mbr);
494 	/* do a sanity check of the partition table */
495 	for (ext = &mbr; ext; ext = ext->extended) {
496 		part = ext->mbr.mbr_parts;
497 		for (i = 0; i < MBR_PART_COUNT; part++, i++) {
498 			if (part->mbrp_type == MBR_PTYPE_PREP &&
499 			    part->mbrp_size > 50)
500 				bootinfo_mbr = i+1;
501 			if (part->mbrp_type == MBR_PTYPE_RESERVED_x21 &&
502 			    part->mbrp_size < (MIN_FAT12_BOOT/512)) {
503 				msg_display(MSG_boottoosmall);
504 				msg_fmt_display_add(MSG_nobootpartdisklabel,
505 				    "%d", 0);
506 				if (!ask_yesno(NULL))
507 					return 0;
508 				nobootfix = 1;
509 			}
510 		}
511 	}
512 #endif
513 
514 	if (!md_check_partitions(install))
515 		return 0;
516 
517 	return 1;
518 }
519 
520 /* Upgrade support */
521 int
522 md_update(struct install_partition_desc *install)
523 {
524 
525 	nonewfsmsdos = 1;
526 	md_post_newfs(install);
527 	return 1;
528 }
529 
530 
531 int
532 md_check_mbr(struct disk_partitions *parts, mbr_info_t *mbri, bool quiet)
533 {
534 	mbr_info_t *ext;
535 	struct mbr_partition *part;
536 	int i;
537 
538 	for (ext = mbri; ext; ext = ext->extended) {
539 		part = ext->mbr.mbr_parts;
540 		for (i = 0; i < MBR_PART_COUNT; part++, i++) {
541 			if (part->mbrp_type == MBR_PTYPE_FAT12) {
542 				pm->bootstart = part->mbrp_start;
543 				pm->bootsize = part->mbrp_size;
544 			} else if (part->mbrp_type == MBR_PTYPE_PREP &&
545 			    part->mbrp_size < 50) {
546 				/* this is the bootinfo partition */
547 				binfostart = part->mbrp_start;
548 				binfosize = part->mbrp_size;
549 				bootinfo_mbr = i+1;
550 			} else if (part->mbrp_type == MBR_PTYPE_PREP &&
551 			    part->mbrp_size > 50) {
552 				bprepstart = part->mbrp_start;
553 				bprepsize = part->mbrp_size;
554 			}
555 			break;
556 		}
557 	}
558 
559 	/* we need to either have a pair of prep partitions, or a single
560 	 * fat.  if neither, things are broken. */
561 	if (!(pm->bootsize >= (MIN_FAT12_BOOT/512) ||
562 		(binfosize >= (MIN_BINFO_BOOT/512) &&
563 		    bprepsize >= (MIN_PREP_BOOT/512)))) {
564 		if (quiet)
565 			return 0;
566 		msg_display(MSG_bootnotright);
567 		return ask_reedit(parts);
568 	}
569 
570 	/* check the prep partitions */
571 	if ((binfosize > 0 || bprepsize > 0) &&
572 	    (binfosize < (MIN_BINFO_BOOT/512) ||
573 		bprepsize < (MIN_PREP_BOOT/512))) {
574 		if (quiet)
575 			return 0;
576 		msg_display(MSG_preptoosmall);
577 		return ask_reedit(parts);
578 	}
579 
580 	/* check the fat12 parititons */
581 	if (pm->bootsize > 0 && pm->bootsize < (MIN_FAT12_BOOT/512)) {
582 		if (quiet)
583 			return 0;
584 		msg_display(MSG_boottoosmall);
585 		return ask_reedit(parts);
586 	}
587 
588 	/* if both sets contain zero, thats bad */
589 	if ((pm->bootstart == 0 || pm->bootsize == 0) &&
590 	    (binfosize == 0 || binfostart == 0 ||
591 		bprepsize == 0 || bprepstart == 0)) {
592 		if (quiet)
593 			return 0;
594 		msg_display(MSG_nobootpart);
595 		return ask_reedit(parts);
596 	}
597 	return 2;
598 }
599 
600 /*
601  * NOTE, we use a reserved partition type, because some RS/6000 machines hang
602  * hard if they find a FAT12, and if we use type prep, that indicates that
603  * it should be read raw.
604  * One partition for FAT12 booting
605  * One partition for NetBSD
606  * One partition to hold the bootinfo.txt file
607  * One partition to hold ofwboot
608  */
609 
610 bool
611 md_parts_use_wholedisk(struct disk_partitions *parts)
612 {
613 	struct disk_part_info boot_parts[] =
614 	{
615 		{ .fs_type = FS_MSDOS, .size = FAT12_BOOT_SIZE/512 },
616 		{ .fs_type = FS_OTHER, .size = BINFO_BOOT_SIZE/512 },
617 		{ .fs_type = FS_BOOT, .size = PREP_BOOT_SIZE/512 }
618 	};
619 
620 	return parts_use_wholedisk(parts, __arraycount(boot_parts),
621 	     boot_parts);
622 }
623 
624 const char *md_disklabel_cmd(void)
625 {
626 
627 	/* we cannot rewrite an RDB disklabel */
628 	if (rdb_found)
629 		return "sync No disklabel";
630 
631 	return "disklabel -w -r";
632 }
633 
634 static int
635 check_rdb(void)
636 {
637 	char buf[512], diskpath[MAXPATHLEN];
638 	struct rdblock *rdb;
639 	off_t blk;
640 	int fd;
641 
642 	/* Find out if this disk has a valid RDB, before continuing. */
643 	rdb = (struct rdblock *)buf;
644 	fd = opendisk(pm->diskdev, O_RDONLY, diskpath, sizeof(diskpath), 0);
645 	if (fd < 0)
646 		return 0;
647 	for (blk = 0; blk < RDB_MAXBLOCKS; blk++) {
648 		if (pread(fd, rdb, 512, blk * 512) != 512)
649 			return 0;
650 		if (rdb->id == RDBLOCK_ID && rdbchksum(rdb) == 0) {
651 			rdb_found = 1;	/* do not repartition! */
652 			return 1;
653 		}
654 	}
655 	return 0;
656 }
657 
658 static uint32_t
659 rdbchksum(void *bdata)
660 {
661 	uint32_t *blp, cnt, val;
662 
663 	blp = bdata;
664 	cnt = blp[1];
665 	val = 0;
666 	while (cnt--)
667 		val += *blp++;
668 	return val;
669 }
670 
671 int
672 md_pre_mount(struct install_partition_desc *install, size_t ndx)
673 {
674 
675 	return 0;
676 }
677 
678 bool
679 md_mbr_update_check(struct disk_partitions *parts, mbr_info_t *mbri)
680 {
681 	return false;	/* no change, no need to write back */
682 }
683 
684 #ifdef HAVE_GPT
685 bool
686 md_gpt_post_write(struct disk_partitions *parts, part_id root_id,
687     bool root_is_new, part_id efi_id, bool efi_is_new)
688 {
689 	/* no GPT boot support, nothing needs to be done here */
690 	return true;
691 }
692 #endif
693 
694