xref: /netbsd-src/usr.sbin/sysinst/arch/i386/md.c (revision d24f36fab5977a1f962347d6cf381acc85840434)
1*d24f36faSmartin /*	$NetBSD: md.c,v 1.35 2022/02/10 16:11:42 martin Exp $ */
250dbef1aSdholland 
350dbef1aSdholland /*
450dbef1aSdholland  * Copyright 1997 Piermont Information Systems Inc.
550dbef1aSdholland  * All rights reserved.
650dbef1aSdholland  *
750dbef1aSdholland  * Based on code written by Philip A. Nelson for Piermont Information
850dbef1aSdholland  * Systems Inc.
950dbef1aSdholland  *
1050dbef1aSdholland  * Redistribution and use in source and binary forms, with or without
1150dbef1aSdholland  * modification, are permitted provided that the following conditions
1250dbef1aSdholland  * are met:
1350dbef1aSdholland  * 1. Redistributions of source code must retain the above copyright
1450dbef1aSdholland  *    notice, this list of conditions and the following disclaimer.
1550dbef1aSdholland  * 2. Redistributions in binary form must reproduce the above copyright
1650dbef1aSdholland  *    notice, this list of conditions and the following disclaimer in the
1750dbef1aSdholland  *    documentation and/or other materials provided with the distribution.
1850dbef1aSdholland  * 3. The name of Piermont Information Systems Inc. may not be used to endorse
1950dbef1aSdholland  *    or promote products derived from this software without specific prior
2050dbef1aSdholland  *    written permission.
2150dbef1aSdholland  *
2250dbef1aSdholland  * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
2350dbef1aSdholland  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2450dbef1aSdholland  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2550dbef1aSdholland  * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
2650dbef1aSdholland  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2750dbef1aSdholland  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2850dbef1aSdholland  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2950dbef1aSdholland  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3050dbef1aSdholland  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3150dbef1aSdholland  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
3250dbef1aSdholland  * THE POSSIBILITY OF SUCH DAMAGE.
3350dbef1aSdholland  */
3450dbef1aSdholland 
3550dbef1aSdholland /* md.c -- i386 machine specific routines - also used by amd64 */
3650dbef1aSdholland 
3750dbef1aSdholland #include <sys/param.h>
3850dbef1aSdholland #include <sys/sysctl.h>
3950dbef1aSdholland #include <sys/exec.h>
4050dbef1aSdholland #include <sys/utsname.h>
4150dbef1aSdholland #include <sys/types.h>
4250dbef1aSdholland #include <sys/stat.h>
4350dbef1aSdholland #include <machine/cpu.h>
444103857bSmartin #include <assert.h>
4550dbef1aSdholland #include <stdio.h>
4650dbef1aSdholland #include <stddef.h>
4750dbef1aSdholland #include <util.h>
4850dbef1aSdholland #include <dirent.h>
4950dbef1aSdholland #include <termios.h>
5050dbef1aSdholland 
5150dbef1aSdholland #include "defs.h"
5250dbef1aSdholland #include "md.h"
5350dbef1aSdholland #include "endian.h"
5450dbef1aSdholland #include "msg_defs.h"
5550dbef1aSdholland #include "menu_defs.h"
5650dbef1aSdholland 
5750dbef1aSdholland #ifdef NO_LBA_READS		/* for testing */
5850dbef1aSdholland #undef BIFLAG_EXTINT13
5950dbef1aSdholland #define BIFLAG_EXTINT13	0
6050dbef1aSdholland #endif
6150dbef1aSdholland 
6250dbef1aSdholland static struct biosdisk_info *biosdisk = NULL;
6332ea71a6Smartin static bool uefi_boot;
6450dbef1aSdholland 
6550dbef1aSdholland /* prototypes */
6650dbef1aSdholland 
674103857bSmartin static bool get_bios_info(const char*, struct disk_partitions*, int*, int*, int*);
686ddad149Smartin static int mbr_root_above_chs(daddr_t);
6950dbef1aSdholland static int md_read_bootcode(const char *, struct mbr_sector *);
7050dbef1aSdholland static unsigned int get_bootmodel(void);
7150dbef1aSdholland 
72c42e76ebSmartin static int conmib[] = { CTL_MACHDEP, CPU_CONSDEV };
73c42e76ebSmartin 
7432ea71a6Smartin #define	BOOT_PART	(128*(MEG/512))
7532ea71a6Smartin #define	BOOT_PART_TYPE	PT_EFI_SYSTEM
7632ea71a6Smartin 
7732ea71a6Smartin static const char * uefi_bootloaders[] = {
7832ea71a6Smartin 	"/usr/mdec/bootia32.efi",
7932ea71a6Smartin 	"/usr/mdec/bootx64.efi",
8032ea71a6Smartin };
8132ea71a6Smartin 
8250dbef1aSdholland void
md_init(void)8350dbef1aSdholland md_init(void)
8450dbef1aSdholland {
8532ea71a6Smartin 	char boot_method[100];
8632ea71a6Smartin 	size_t len;
8732ea71a6Smartin 
8832ea71a6Smartin 	len = sizeof(boot_method);
8932ea71a6Smartin 	if (sysctlbyname("machdep.bootmethod", boot_method, &len, NULL, 0)
9032ea71a6Smartin 	    != -1) {
9132ea71a6Smartin 		if (strcmp(boot_method, "BIOS") == 0)
9232ea71a6Smartin 			uefi_boot = false;
9332ea71a6Smartin 		else if (strcmp(boot_method, "UEFI") == 0)
9432ea71a6Smartin 			uefi_boot = true;
9532ea71a6Smartin 	}
9650dbef1aSdholland }
9750dbef1aSdholland 
9850dbef1aSdholland void
md_init_set_status(int flags)9950dbef1aSdholland md_init_set_status(int flags)
10050dbef1aSdholland {
10150dbef1aSdholland 	(void)flags;
10250dbef1aSdholland 
10350dbef1aSdholland 	/* Default to install same type of kernel as we are running */
10450dbef1aSdholland 	set_kernel_set(get_bootmodel());
10550dbef1aSdholland }
10650dbef1aSdholland 
1074103857bSmartin bool
md_get_info(struct install_partition_desc * install)1084103857bSmartin md_get_info(struct install_partition_desc *install)
1094103857bSmartin {
110957b5cd6Smartin 	int bcyl = 0, bhead = 0, bsec = 0, res;
1114103857bSmartin 
1124103857bSmartin 	if (pm->no_mbr || pm->no_part)
1134103857bSmartin 		return true;
1144103857bSmartin 
115957b5cd6Smartin again:
1164103857bSmartin 	if (pm->parts == NULL) {
1174103857bSmartin 
1184103857bSmartin 		const struct disk_partitioning_scheme *ps =
1194103857bSmartin 		    select_part_scheme(pm, NULL, true, NULL);
1204103857bSmartin 
1214103857bSmartin 		if (!ps)
1226fec6798Smartin 			return false;
1234103857bSmartin 
1244103857bSmartin 		struct disk_partitions *parts =
1254103857bSmartin 		   (*ps->create_new_for_disk)(pm->diskdev,
12686906049Smartin 		   0, pm->dlsize, true, NULL);
1274103857bSmartin 		if (!parts)
1284103857bSmartin 			return false;
1294103857bSmartin 
1304103857bSmartin 		pm->parts = parts;
1314103857bSmartin 		if (ps->size_limit > 0 && pm->dlsize > ps->size_limit)
1324103857bSmartin 			pm->dlsize = ps->size_limit;
1334103857bSmartin 	}
1344103857bSmartin 
1354103857bSmartin 	if (get_bios_info(pm->diskdev, pm->parts, &bcyl, &bhead, &bsec)
1364103857bSmartin 	    && pm->parts->pscheme->change_disk_geom != NULL)
1374103857bSmartin 		pm->parts->pscheme->change_disk_geom(pm->parts,
1384103857bSmartin 		    bcyl, bhead, bsec);
1394103857bSmartin 	else
14086906049Smartin 		set_default_sizemult(pm->diskdev, MEG, pm->sectorsize);
1414103857bSmartin 
1424103857bSmartin 	/*
1434103857bSmartin 	 * If the selected scheme does not need two-stage partitioning
1444103857bSmartin 	 * (like GPT), do not bother to edit the outer partitions.
1454103857bSmartin 	 */
1464103857bSmartin 	if (pm->parts->pscheme->secondary_partitions == NULL ||
1474103857bSmartin 	    pm->parts->pscheme->secondary_scheme == NULL)
1484103857bSmartin 		return true;
1494103857bSmartin 
1504103857bSmartin 	if (pm->no_mbr || pm->no_part)
1514103857bSmartin 		return true;
1524103857bSmartin 
153957b5cd6Smartin 	res = edit_outer_parts(pm->parts);
154957b5cd6Smartin 	if (res == 0)
155957b5cd6Smartin 		return false;
156957b5cd6Smartin 	else if (res == 1)
157957b5cd6Smartin 		return true;
158957b5cd6Smartin 
159957b5cd6Smartin 	pm->parts->pscheme->destroy_part_scheme(pm->parts);
160957b5cd6Smartin 	pm->parts = NULL;
161957b5cd6Smartin 	goto again;
1624103857bSmartin }
1634103857bSmartin 
1644103857bSmartin /*
1654103857bSmartin  * md back-end code for menu-driven BSD disklabel editor.
1664103857bSmartin  */
167957b5cd6Smartin int
md_make_bsd_partitions(struct install_partition_desc * install)1684103857bSmartin md_make_bsd_partitions(struct install_partition_desc *install)
1694103857bSmartin {
1704103857bSmartin 	return make_bsd_partitions(install);
1714103857bSmartin }
1724103857bSmartin 
1734103857bSmartin /*
1744103857bSmartin  * any additional partition validation
1754103857bSmartin  */
1764103857bSmartin bool
md_check_partitions(struct install_partition_desc * install)1774103857bSmartin md_check_partitions(struct install_partition_desc *install)
1784103857bSmartin {
1794103857bSmartin 	int rval;
1804103857bSmartin 	char *bootxx;
1814103857bSmartin 
18232ea71a6Smartin 	/* if booting via UEFI no boot blocks are needed */
18332ea71a6Smartin 	if (uefi_boot)
18432ea71a6Smartin 		return true;
18532ea71a6Smartin 
1864103857bSmartin 	/* check we have boot code for the root partition type */
1874103857bSmartin 	bootxx = bootxx_name(install);
1884103857bSmartin 	rval = access(bootxx, R_OK);
1894103857bSmartin 	free(bootxx);
1904103857bSmartin 	if (rval == 0)
1914103857bSmartin 		return true;
1924103857bSmartin 	process_menu(MENU_ok, __UNCONST(MSG_No_Bootcode));
1934103857bSmartin 	return false;
1944103857bSmartin }
1954103857bSmartin 
1964103857bSmartin /*
1974103857bSmartin  * hook called before writing new disklabel.
1984103857bSmartin  */
1994103857bSmartin bool
md_pre_disklabel(struct install_partition_desc * install,struct disk_partitions * parts)2004103857bSmartin md_pre_disklabel(struct install_partition_desc *install,
2014103857bSmartin     struct disk_partitions *parts)
2024103857bSmartin {
2034103857bSmartin 
2044103857bSmartin 	if (parts->parent == NULL)
2054103857bSmartin 		return true;	/* no outer partitions */
2064103857bSmartin 
2074103857bSmartin 	parts = parts->parent;
2084103857bSmartin 
2094103857bSmartin 	msg_display_subst(MSG_dofdisk, 3, parts->disk,
2104103857bSmartin 	    msg_string(parts->pscheme->name),
2114103857bSmartin 	    msg_string(parts->pscheme->short_name));
2124103857bSmartin 
2134103857bSmartin 	/* write edited "MBR" onto disk. */
2144103857bSmartin 	if (!parts->pscheme->write_to_disk(parts)) {
2154103857bSmartin 		msg_display(MSG_wmbrfail);
2164103857bSmartin 		process_menu(MENU_ok, NULL);
2174103857bSmartin 		return false;
2184103857bSmartin 	}
2194103857bSmartin 	return true;
2204103857bSmartin }
2214103857bSmartin 
2224103857bSmartin /*
2234103857bSmartin  * hook called after writing disklabel to new target disk.
2244103857bSmartin  */
2254103857bSmartin bool
md_post_disklabel(struct install_partition_desc * install,struct disk_partitions * parts)2264103857bSmartin md_post_disklabel(struct install_partition_desc *install,
2274103857bSmartin     struct disk_partitions *parts)
2284103857bSmartin {
2294103857bSmartin 	return true;
2304103857bSmartin }
2314103857bSmartin 
2324103857bSmartin /*
23332ea71a6Smartin  * Do all legacy bootblock update/setup here
2344103857bSmartin  */
23532ea71a6Smartin static int
update_bios_boot(struct install_partition_desc * install,bool use_target_files)2364204f810Smartin update_bios_boot(struct install_partition_desc *install, bool use_target_files)
2374103857bSmartin {
2384103857bSmartin 	int ret;
2394103857bSmartin 	size_t len;
2404103857bSmartin 	char boot_options[1024];
2414204f810Smartin 	char *bootxx_filename, *p;
2424103857bSmartin 	/*
2434103857bSmartin 	 * XXX - this code retains a lot of cruft from when we went
2444103857bSmartin 	 * to great pains to exclude installboot from the ramdisk
2454103857bSmartin 	 * for size reasons and should be rewritten.
2464103857bSmartin 	 */
2474103857bSmartin 	static const char *consoles[]={
2484103857bSmartin         	"pc", /* CONSDEV_PC */
2494103857bSmartin 		"com0", /* CONSDEV_COM0 */
2504103857bSmartin 		"com1", /* CONSDEV_COM1 */
2514103857bSmartin 		"com2", /* CONSDEV_COM2 */
2524103857bSmartin 		"com3", /* CONSDEV_COM3 */
2534103857bSmartin 		"com0kbd", /* CONSDEV_COM0KBD */
2544103857bSmartin 		"com1kbd", /* CONSDEV_COM1KBD */
2554103857bSmartin 		"com2kbd", /* CONSDEV_COM2KBD */
2564103857bSmartin 		"com3kbd" /* CONSDEV_COM3KBD */ };
2574103857bSmartin 	static struct x86_boot_params boottype =
2584103857bSmartin 		{sizeof boottype, 0, 5, 0, 9600, { '\0' }, "", 0};
2594103857bSmartin 	struct termios t;
2604103857bSmartin 	dev_t condev;
2614103857bSmartin 
2624103857bSmartin 	if (pm == NULL || !pm->no_part) {
2634103857bSmartin 		/*
2644103857bSmartin 		 * Get console device, should either be ttyE0 or tty0n.
2654103857bSmartin 		 * Too hard to double check, so just 'know' the device numbers.
2664103857bSmartin 		 */
2674103857bSmartin 		len = sizeof condev;
26805e0fd74Smartin 		if (sysctl(conmib, __arraycount(conmib), &condev, &len, NULL,
26905e0fd74Smartin 		    0) != -1 && (condev & ~3) == 0x800) {
2704103857bSmartin 			/* Motherboard serial port */
2714103857bSmartin 			boottype.bp_consdev = (condev & 3) + 1;
27205e0fd74Smartin 			/* Defaulting the baud rate to that of stdin should
27305e0fd74Smartin 			   suffice */
2744103857bSmartin 			if (tcgetattr(0, &t) != -1)
2754103857bSmartin 				boottype.bp_conspeed = t.c_ispeed;
2764103857bSmartin 		}
2774103857bSmartin 
2784103857bSmartin 		process_menu(MENU_getboottype, &boottype);
27924ecf24eSchristos 		msg_fmt_display(MSG_dobootblks, "%s", pm->diskdev);
2804103857bSmartin 		if (boottype.bp_consdev == ~0u)
2814103857bSmartin 			/* Use existing bootblocks */
2824103857bSmartin 			return 0;
2834103857bSmartin 	}
2844103857bSmartin 
2854204f810Smartin 	if (use_target_files)
2864204f810Smartin 		ret = cp_within_target("/usr/mdec/boot", "/", 0);
2874204f810Smartin 	else
2884204f810Smartin 		ret = cp_to_target("/usr/mdec/boot", "/");
2894103857bSmartin 	if (ret)
2904103857bSmartin 		return ret;
2914103857bSmartin 	if (pm && pm->no_part)
2924103857bSmartin 		return 0;
2934103857bSmartin 
2944204f810Smartin 	p = bootxx_name(install);
2954204f810Smartin 	if (p && use_target_files) {
2964204f810Smartin 		bootxx_filename = strdup(target_expand(p));
2974204f810Smartin 		free(p);
2984204f810Smartin 	} else {
2994204f810Smartin 	        bootxx_filename = p;
3004204f810Smartin 	}
3014103857bSmartin         if (bootxx_filename != NULL) {
3024103857bSmartin 		char rdev[PATH_MAX];
3034103857bSmartin 
3044103857bSmartin 		install->infos[0].parts->pscheme->get_part_device(
3054103857bSmartin 		    install->infos[0].parts, install->infos[0].cur_part_id,
306abce8cb3Smartin 		    rdev, sizeof rdev, NULL, raw_dev_name, true, true);
3074103857bSmartin 
3084103857bSmartin 		snprintf(boot_options, sizeof boot_options,
3094103857bSmartin 		    "console=%s,speed=%u", consoles[boottype.bp_consdev],
3104103857bSmartin 		    boottype.bp_conspeed);
3114103857bSmartin                	ret = run_program(RUN_DISPLAY,
3128ef7426aSmartin                 	    "/usr/sbin/installboot -f -o %s %s %s",
3134103857bSmartin 			    boot_options, rdev, bootxx_filename);
3144103857bSmartin                 free(bootxx_filename);
31508fc9285Smartin         } else {
3164103857bSmartin                 ret = -1;
31708fc9285Smartin 	}
3184103857bSmartin 
3194103857bSmartin         if (ret != 0)
3204103857bSmartin                 process_menu(MENU_ok,
3214103857bSmartin                     __UNCONST("Warning: disk is probably not bootable"));
3224103857bSmartin 
3234103857bSmartin 	return ret;
3244103857bSmartin }
3254103857bSmartin 
3264204f810Smartin static int
md_post_newfs_bios(struct install_partition_desc * install)3274204f810Smartin md_post_newfs_bios(struct install_partition_desc *install)
3284204f810Smartin {
3294204f810Smartin 	return update_bios_boot(install, false);
3304204f810Smartin }
3314204f810Smartin 
33232ea71a6Smartin /*
33332ea71a6Smartin  * Make sure our bootloader(s) are in the proper directory in the boot
33432ea71a6Smartin  * boot partition (or update them).
33532ea71a6Smartin  */
33632ea71a6Smartin static int
copy_uefi_boot(const struct part_usage_info * boot,bool target_is_populated)337*d24f36faSmartin copy_uefi_boot(const struct part_usage_info *boot, bool target_is_populated)
33832ea71a6Smartin {
3394204f810Smartin 	char dev[MAXPATHLEN], path[MAXPATHLEN], src[MAXPATHLEN];
340*d24f36faSmartin 	const char *s;
34132ea71a6Smartin 	size_t i;
34232ea71a6Smartin 	int err;
34332ea71a6Smartin 
34432ea71a6Smartin 	if (!boot->parts->pscheme->get_part_device(boot->parts,
345abce8cb3Smartin 	    boot->cur_part_id, dev, sizeof(dev), NULL, plain_name, true, true))
34632ea71a6Smartin 		return -1;
34732ea71a6Smartin 
34832ea71a6Smartin 	/*
34932ea71a6Smartin 	 * We should have a valid file system on that partition.
35032ea71a6Smartin 	 * Try to mount it and check if there is a /EFI in there.
35132ea71a6Smartin 	 */
35232ea71a6Smartin 	if (boot->mount[0])
35332ea71a6Smartin 		strlcpy(path, boot->mount, sizeof(path));
35432ea71a6Smartin 	else
35532ea71a6Smartin 		strcpy(path, "/mnt");
35632ea71a6Smartin 
35732ea71a6Smartin 	if (!(boot->instflags & PUIINST_MOUNT)) {
35832ea71a6Smartin 		make_target_dir(path);
35932ea71a6Smartin 		err = target_mount("", dev, path);
36032ea71a6Smartin 		if (err != 0)
36132ea71a6Smartin 			return err;
36232ea71a6Smartin 	}
36332ea71a6Smartin 
36432ea71a6Smartin 	strlcat(path, "/EFI/boot", sizeof(path));
36532ea71a6Smartin 	make_target_dir(path);
36632ea71a6Smartin 
36732ea71a6Smartin 	for (i = 0; i < __arraycount(uefi_bootloaders); i++) {
368*d24f36faSmartin 		s = uefi_bootloaders[i];
369*d24f36faSmartin 		strcpy(src, target_is_populated ? target_expand(s) : s);
3704204f810Smartin 		if (access(src, R_OK) != 0)
37132ea71a6Smartin 			continue;
372*d24f36faSmartin 		err = target_is_populated ?
373*d24f36faSmartin 		    cp_within_target(s, path, 0) :
374*d24f36faSmartin 		    cp_to_target(s, path);
37532ea71a6Smartin 		if (err)
37632ea71a6Smartin 			return err;
37732ea71a6Smartin 	}
378*d24f36faSmartin 	if (boot->mount[0] == 0)
379*d24f36faSmartin 		target_unmount("/mnt");
38032ea71a6Smartin 
38132ea71a6Smartin 	return 0;
38232ea71a6Smartin }
38332ea71a6Smartin 
38432ea71a6Smartin /*
38532ea71a6Smartin  * Find (U)EFI boot partition and install/update bootloaders
38632ea71a6Smartin  */
38732ea71a6Smartin static int
update_uefi_boot_code(struct install_partition_desc * install,bool target_is_populated)388*d24f36faSmartin update_uefi_boot_code(struct install_partition_desc *install,
389*d24f36faSmartin     bool target_is_populated)
39032ea71a6Smartin {
3914204f810Smartin 	size_t i, boot_part;
39232ea71a6Smartin 
3934204f810Smartin 	boot_part = ~0U;
39432ea71a6Smartin 	for (i = 0; i < install->num; i++) {
39532ea71a6Smartin 		if (!(install->infos[i].instflags & PUIINST_BOOT))
39632ea71a6Smartin 			continue;
3974204f810Smartin 		boot_part = i;
3984204f810Smartin 		break;
3994204f810Smartin 	}
4004204f810Smartin 	if (boot_part == ~0U) {
4014204f810Smartin 		/*
4024204f810Smartin 		 * Didn't find an explicitly marked boot partition,
4034204f810Smartin 		 * check if we have any EFI System Partitions and
4044204f810Smartin 		 * use the first.
4054204f810Smartin 		 */
4064204f810Smartin 		for (i = 0; i < install->num; i++) {
4074204f810Smartin 			if (install->infos[i].type != PT_EFI_SYSTEM)
4084204f810Smartin 				continue;
4094204f810Smartin 			boot_part = i;
4104204f810Smartin 			break;
4114204f810Smartin 		}
41232ea71a6Smartin 	}
41332ea71a6Smartin 
4144204f810Smartin 	if (boot_part < install->num)
415*d24f36faSmartin 		return copy_uefi_boot(&install->infos[boot_part],
416*d24f36faSmartin 		    target_is_populated);
4174204f810Smartin 
41832ea71a6Smartin 	return -1;	/* no EFI boot partition found */
41932ea71a6Smartin }
42032ea71a6Smartin 
42132ea71a6Smartin /*
4224204f810Smartin  * Find bootloader options and update bootloader
4234204f810Smartin  */
4244204f810Smartin static int
update_bios_boot_code(struct install_partition_desc * install)4254204f810Smartin update_bios_boot_code(struct install_partition_desc *install)
4264204f810Smartin {
4274204f810Smartin 	return update_bios_boot(install, true);
4284204f810Smartin }
4294204f810Smartin 
4304204f810Smartin static int
update_boot_code(struct install_partition_desc * install,bool target_is_populated)431*d24f36faSmartin update_boot_code(struct install_partition_desc *install,
432*d24f36faSmartin     bool target_is_populated)
4334204f810Smartin {
4344204f810Smartin 	return uefi_boot ?
435*d24f36faSmartin 	    update_uefi_boot_code(install, target_is_populated)
4364204f810Smartin 	    : update_bios_boot_code(install);
4374204f810Smartin }
4384204f810Smartin 
4394204f810Smartin static int
md_post_newfs_uefi(struct install_partition_desc * install)4404204f810Smartin md_post_newfs_uefi(struct install_partition_desc *install)
4414204f810Smartin {
442*d24f36faSmartin 	return update_uefi_boot_code(install, false);
4434204f810Smartin }
4444204f810Smartin 
4454204f810Smartin /*
44632ea71a6Smartin  * hook called after upgrade() or install() has finished setting
44732ea71a6Smartin  * up the target disk but immediately before the user is given the
44832ea71a6Smartin  * ``disks are now set up'' message.
44932ea71a6Smartin  */
45032ea71a6Smartin int
md_post_newfs(struct install_partition_desc * install)45132ea71a6Smartin md_post_newfs(struct install_partition_desc *install)
45232ea71a6Smartin {
45332ea71a6Smartin 
45432ea71a6Smartin 	return uefi_boot ? md_post_newfs_uefi(install)
45532ea71a6Smartin 	    : md_post_newfs_bios(install);
45632ea71a6Smartin }
45732ea71a6Smartin 
4584103857bSmartin int
md_post_extract(struct install_partition_desc * install,bool upgrade)4594204f810Smartin md_post_extract(struct install_partition_desc *install, bool upgrade)
4604103857bSmartin {
4614204f810Smartin 	if (upgrade)
462*d24f36faSmartin 		update_boot_code(install, true);
4634204f810Smartin 
464db4a9cc4Smartin #if defined(__amd64__)
465db4a9cc4Smartin 	if (get_kernel_set() == SET_KERNEL_2) {
466db4a9cc4Smartin 		int ret;
467db4a9cc4Smartin 
468db4a9cc4Smartin 		ret = cp_within_target("/usr/mdec/prekern", "/prekern", 0);
469db4a9cc4Smartin 		if (ret)
470db4a9cc4Smartin 			return ret;
471db4a9cc4Smartin 	}
472db4a9cc4Smartin #endif
4734204f810Smartin 
4744103857bSmartin 	return 0;
4754103857bSmartin }
4764103857bSmartin 
4774103857bSmartin void
md_cleanup_install(struct install_partition_desc * install)4784103857bSmartin md_cleanup_install(struct install_partition_desc *install)
4794103857bSmartin {
4804103857bSmartin 	size_t len;
4814103857bSmartin 	dev_t condev;
4824103857bSmartin 
4834103857bSmartin #ifndef DEBUG
4844103857bSmartin 	enable_rc_conf();
4854103857bSmartin 	add_rc_conf("wscons=YES\n");
4864103857bSmartin 
4874103857bSmartin # if defined(__i386__) && defined(SET_KERNEL_TINY)
4884103857bSmartin 	/*
4894103857bSmartin 	 * For GENERIC_TINY, do not enable any extra screens or wsmux.
4904103857bSmartin 	 * Otherwise, run getty on 4 VTs.
4914103857bSmartin 	 */
4924103857bSmartin 	if (get_kernel_set() == SET_KERNEL_TINY)
4934103857bSmartin 		run_program(RUN_CHROOT,
4944103857bSmartin                             "sed -an -e '/^screen/s/^/#/;/^mux/s/^/#/;"
4954103857bSmartin 			    "H;$!d;g;w /etc/wscons.conf' /etc/wscons.conf");
4964103857bSmartin 	else
4974103857bSmartin # endif
4984103857bSmartin 		run_program(RUN_CHROOT,
4994103857bSmartin 			    "sed -an -e '/^ttyE[1-9]/s/off/on/;"
5004103857bSmartin 			    "H;$!d;g;w /etc/ttys' /etc/ttys");
5014103857bSmartin 
5024103857bSmartin #endif
5034103857bSmartin 
5044103857bSmartin 	/*
5054103857bSmartin 	 * Get console device, should either be ttyE0 or tty0n.
5064103857bSmartin 	 * Too hard to double check, so just 'know' the device numbers.
5074103857bSmartin 	 */
5084103857bSmartin 	len = sizeof condev;
5094103857bSmartin 	if (sysctl(conmib, __arraycount(conmib), &condev, &len, NULL, 0) != -1
5104103857bSmartin 	    && (condev & ~3) != 0x800) {
5114103857bSmartin 
5124103857bSmartin 		/*
5134103857bSmartin 		 * Current console is not com*, assume ttyE*.
5144103857bSmartin 		 * Modify /etc/ttys to use wsvt25 for all ports.
5154103857bSmartin 		 */
5164103857bSmartin 
5174103857bSmartin 		run_program(RUN_CHROOT,
5184103857bSmartin 			    "sed -an -e 's/vt100/wsvt25/g;"
5194103857bSmartin 			    "H;$!d;g;w  /etc/ttys' /etc/ttys");
5204103857bSmartin 	}
5214103857bSmartin }
5224103857bSmartin 
5234103857bSmartin int
md_pre_update(struct install_partition_desc * install)5244103857bSmartin md_pre_update(struct install_partition_desc *install)
5254103857bSmartin {
5264103857bSmartin 	return 1;
5274103857bSmartin }
5284103857bSmartin 
5294103857bSmartin /* Upgrade support */
5304103857bSmartin int
md_update(struct install_partition_desc * install)5314103857bSmartin md_update(struct install_partition_desc *install)
5324103857bSmartin {
5334103857bSmartin 	return 1;
5344103857bSmartin }
5354103857bSmartin 
5364103857bSmartin int
md_check_mbr(struct disk_partitions * parts,mbr_info_t * mbri,bool quiet)5374103857bSmartin md_check_mbr(struct disk_partitions *parts, mbr_info_t *mbri, bool quiet)
53850dbef1aSdholland {
53950dbef1aSdholland 	mbr_info_t *ext;
54050dbef1aSdholland 	struct mbr_partition *p;
54150dbef1aSdholland 	const char *bootcode;
5426ddad149Smartin 	daddr_t inst_start, inst_size;
5434103857bSmartin 	int i, names, fl, ofl;
54450dbef1aSdholland #define	ACTIVE_FOUND	0x0100
54550dbef1aSdholland #define	NETBSD_ACTIVE	0x0200
54650dbef1aSdholland #define	NETBSD_NAMED	0x0400
54750dbef1aSdholland #define	ACTIVE_NAMED	0x0800
54850dbef1aSdholland 
54950dbef1aSdholland 	root_limit = 0;
5506ddad149Smartin 	if (parts->pscheme->guess_install_target == NULL ||
5516ddad149Smartin 	    !parts->pscheme->guess_install_target(parts, &inst_start,
5526ddad149Smartin 	    &inst_size)) {
5536ddad149Smartin 		inst_start = parts->disk_start;
5546ddad149Smartin 		inst_size = parts->disk_size;
5556ddad149Smartin 	}
5566ddad149Smartin 
55750dbef1aSdholland 	if (biosdisk != NULL && (biosdisk->bi_flags & BIFLAG_EXTINT13) == 0) {
5586ddad149Smartin 		if (mbr_root_above_chs(inst_start)) {
5594103857bSmartin 			if (quiet)
5604103857bSmartin 				return 0;
56150dbef1aSdholland 			msg_display(MSG_partabovechs);
562e21052b4Smartin 			if (!ask_noyes(NULL))
5634103857bSmartin 				return 1;
56450dbef1aSdholland 			/* The user is shooting themselves in the foot here...*/
5654103857bSmartin 		} else {
5664103857bSmartin 			if (parts->pscheme->size_limit)
5674103857bSmartin 				root_limit = min(parts->pscheme->size_limit,
5684103857bSmartin 				    parts->disk_size);
5694103857bSmartin 			else
5704103857bSmartin 				root_limit = parts->disk_size;
5714103857bSmartin 		}
57250dbef1aSdholland 	}
57350dbef1aSdholland 
57450dbef1aSdholland 	/*
5756ddad149Smartin 	 * Ensure the install partition (at sector inst_start) and the active
57650dbef1aSdholland 	 * partition are bootable.
57750dbef1aSdholland 	 * Determine whether the bootselect code is needed.
57850dbef1aSdholland 	 * Note that MBR_BS_NEWMBR is always set, so we ignore it!
57950dbef1aSdholland 	 */
58050dbef1aSdholland 	fl = 0;
58150dbef1aSdholland 	names = 0;
5824103857bSmartin 	for (ext = mbri; ext != NULL; ext = ext->extended) {
58350dbef1aSdholland 		p = ext->mbr.mbr_parts;
58450dbef1aSdholland 		for (i = 0; i < MBR_PART_COUNT; p++, i++) {
58550dbef1aSdholland 			if (p->mbrp_flag == MBR_PFLAG_ACTIVE) {
58650dbef1aSdholland 				fl |= ACTIVE_FOUND;
5876ddad149Smartin 			    if (ext->sector + p->mbrp_start == inst_start)
58850dbef1aSdholland 				fl |= NETBSD_ACTIVE;
58950dbef1aSdholland 			}
59050dbef1aSdholland 			if (ext->mbrb.mbrbs_nametab[i][0] == 0) {
59150dbef1aSdholland 				/* No bootmenu label... */
59250dbef1aSdholland 				if (ext->sector == 0)
59350dbef1aSdholland 					continue;
5946ddad149Smartin 				if (ext->sector + p->mbrp_start == inst_start)
59550dbef1aSdholland 					/*
59650dbef1aSdholland 					 * Have installed into an extended ptn
59750dbef1aSdholland 					 * force name & bootsel...
59850dbef1aSdholland 					 */
59950dbef1aSdholland 					names++;
60050dbef1aSdholland 				continue;
60150dbef1aSdholland 			}
60250dbef1aSdholland 			/* Partition has a bootmenu label... */
60350dbef1aSdholland 			if (ext->sector != 0)
60450dbef1aSdholland 				fl |= MBR_BS_EXTLBA;
6056ddad149Smartin 			if (ext->sector + p->mbrp_start == inst_start)
60650dbef1aSdholland 				fl |= NETBSD_NAMED;
60750dbef1aSdholland 			else if (p->mbrp_flag == MBR_PFLAG_ACTIVE)
60850dbef1aSdholland 				fl |= ACTIVE_NAMED;
60950dbef1aSdholland 			else
61050dbef1aSdholland 				names++;
61150dbef1aSdholland 		}
61250dbef1aSdholland 	}
61350dbef1aSdholland 	if (!(fl & ACTIVE_FOUND))
61450dbef1aSdholland 		fl |= NETBSD_ACTIVE;
61550dbef1aSdholland 	if (fl & NETBSD_NAMED && fl & NETBSD_ACTIVE)
61650dbef1aSdholland 		fl |= ACTIVE_NAMED;
61750dbef1aSdholland 
61850dbef1aSdholland 	if ((names > 0 || !(fl & NETBSD_ACTIVE)) &&
61950dbef1aSdholland 	    (!(fl & NETBSD_NAMED) || !(fl & ACTIVE_NAMED))) {
62050dbef1aSdholland 		/*
62150dbef1aSdholland 		 * There appear to be multiple bootable partitions, but they
62250dbef1aSdholland 		 * don't all have bootmenu texts.
62350dbef1aSdholland 		 */
6244103857bSmartin 		if (quiet)
6254103857bSmartin 			return 0;
6264103857bSmartin 
62750dbef1aSdholland 		msg_display(MSG_missing_bootmenu_text);
628e21052b4Smartin 		if (ask_yesno(NULL))
6294103857bSmartin 			return 1;
63050dbef1aSdholland 	}
63150dbef1aSdholland 
63250dbef1aSdholland 	if ((fl & MBR_BS_EXTLBA) &&
63350dbef1aSdholland 	    (biosdisk == NULL || !(biosdisk->bi_flags & BIFLAG_EXTINT13))) {
63450dbef1aSdholland 		/* Need unsupported LBA reads to read boot sectors */
6354103857bSmartin 		if (quiet)
6364103857bSmartin 			return 0;
6374103857bSmartin 
63850dbef1aSdholland 		msg_display(MSG_no_extended_bootmenu);
639e21052b4Smartin 		if (!ask_noyes(NULL))
6404103857bSmartin 			return 1;
64150dbef1aSdholland 	}
64250dbef1aSdholland 
64350dbef1aSdholland 	/* Sort out the name of the mbr code we need */
64457bc5d61Smartin 	if (names > 1 ||
64557bc5d61Smartin 	    (parts->num_part > 1 && (fl & (NETBSD_NAMED | ACTIVE_NAMED)))) {
64650dbef1aSdholland 		/* Need bootselect code */
64750dbef1aSdholland 		fl |= MBR_BS_ACTIVE;
64850dbef1aSdholland 		bootcode = fl & MBR_BS_EXTLBA ? _PATH_BOOTEXT : _PATH_BOOTSEL;
64957bc5d61Smartin 	} else {
65050dbef1aSdholland 		bootcode = _PATH_MBR;
65157bc5d61Smartin 	}
65250dbef1aSdholland 
65350dbef1aSdholland 	fl &=  MBR_BS_ACTIVE | MBR_BS_EXTLBA;
65450dbef1aSdholland 
65550dbef1aSdholland 	/* Look at what is installed */
6564103857bSmartin 	ofl = mbri->mbrb.mbrbs_flags;
65750dbef1aSdholland 	if (ofl == 0) {
65850dbef1aSdholland 		/* Check there is some bootcode at all... */
6594103857bSmartin 		if (mbri->mbr.mbr_magic != htole16(MBR_MAGIC) ||
6604103857bSmartin 		    mbri->mbr.mbr_jmpboot[0] == 0 ||
6616ddad149Smartin 		    mbr_root_above_chs(inst_start))
66250dbef1aSdholland 			/* Existing won't do, force update */
66350dbef1aSdholland 			fl |= MBR_BS_NEWMBR;
66450dbef1aSdholland 	}
6654103857bSmartin 	ofl = mbri->oflags & (MBR_BS_ACTIVE | MBR_BS_EXTLBA);
66650dbef1aSdholland 
6674103857bSmartin 	if (!quiet) {
66850dbef1aSdholland 		if (fl & ~ofl || (fl == 0 && ofl & MBR_BS_ACTIVE)) {
66950dbef1aSdholland 			/* Existing boot code isn't the right one... */
67050dbef1aSdholland 			if (fl & MBR_BS_ACTIVE)
67150dbef1aSdholland 				msg_display(MSG_installbootsel);
67250dbef1aSdholland 			else
67350dbef1aSdholland 				msg_display(MSG_installmbr);
67450dbef1aSdholland 		} else
67550dbef1aSdholland 			/* Existing code would (probably) be ok */
67650dbef1aSdholland 			msg_display(MSG_updatembr);
67750dbef1aSdholland 
678e21052b4Smartin 		if (!ask_yesno(NULL))
67950dbef1aSdholland 			/* User doesn't want to update mbr code */
68050dbef1aSdholland 			return 2;
68150dbef1aSdholland 	}
68250dbef1aSdholland 
6834103857bSmartin 	if (md_read_bootcode(bootcode, &mbri->mbr) == 0)
6844103857bSmartin 		/* update suceeded - to memory copy */
6854103857bSmartin 		return 2;
6864103857bSmartin 
6874103857bSmartin 	/* This shouldn't happen since the files are in the floppy fs... */
68824ecf24eSchristos 	msg_fmt_display("Can't find %s", "%s", bootcode);
6894103857bSmartin 	return ask_reedit(parts);
69050dbef1aSdholland }
69150dbef1aSdholland 
6924103857bSmartin bool
md_parts_use_wholedisk(struct disk_partitions * parts)6934103857bSmartin md_parts_use_wholedisk(struct disk_partitions *parts)
6944103857bSmartin {
69532ea71a6Smartin 	struct disk_part_info boot_part = {
69632ea71a6Smartin 		.size = BOOT_PART,
69732ea71a6Smartin 		.fs_type = FS_MSDOS, .fs_sub_type = MBR_PTYPE_FAT32L,
69832ea71a6Smartin 	};
69932ea71a6Smartin 
70032ea71a6Smartin 	if (!uefi_boot)
7014103857bSmartin 		return parts_use_wholedisk(parts, 0, NULL);
70232ea71a6Smartin 
70332ea71a6Smartin 	boot_part.nat_type = parts->pscheme->get_generic_part_type(
70432ea71a6Smartin 	    PT_EFI_SYSTEM);
70532ea71a6Smartin 
70632ea71a6Smartin 	return parts_use_wholedisk(parts, 1, &boot_part);
7074103857bSmartin }
7084103857bSmartin 
7094103857bSmartin static bool
get_bios_info(const char * dev,struct disk_partitions * parts,int * bcyl,int * bhead,int * bsec)7104103857bSmartin get_bios_info(const char *dev, struct disk_partitions *parts, int *bcyl,
7114103857bSmartin     int *bhead, int *bsec)
71250dbef1aSdholland {
71350dbef1aSdholland 	static struct disklist *disklist = NULL;
71450dbef1aSdholland 	static int mib[2] = {CTL_MACHDEP, CPU_DISKINFO};
71550dbef1aSdholland 	int i;
71650dbef1aSdholland 	size_t len;
71750dbef1aSdholland 	struct biosdisk_info *bip;
71850dbef1aSdholland 	struct nativedisk_info *nip = NULL, *nat;
7194103857bSmartin 	int cyl, head, sec;
72050dbef1aSdholland 
72150dbef1aSdholland 	if (disklist == NULL) {
72250dbef1aSdholland 		if (sysctl(mib, 2, NULL, &len, NULL, 0) < 0)
72350dbef1aSdholland 			goto nogeom;
72450dbef1aSdholland 		disklist = malloc(len);
72550dbef1aSdholland 		if (disklist == NULL) {
72650dbef1aSdholland 			fprintf(stderr, "Out of memory\n");
7274103857bSmartin 			return false;
72850dbef1aSdholland 		}
72950dbef1aSdholland 		sysctl(mib, 2, disklist, &len, NULL, 0);
73050dbef1aSdholland 	}
73150dbef1aSdholland 
73250dbef1aSdholland 	for (i = 0; i < disklist->dl_nnativedisks; i++) {
73350dbef1aSdholland 		nat = &disklist->dl_nativedisks[i];
73450dbef1aSdholland 		if (!strcmp(dev, nat->ni_devname)) {
73550dbef1aSdholland 			nip = nat;
73650dbef1aSdholland 			break;
73750dbef1aSdholland 		}
73850dbef1aSdholland 	}
73950dbef1aSdholland 	if (nip == NULL || nip->ni_nmatches == 0) {
74050dbef1aSdholland nogeom:
74150dbef1aSdholland 		if (nip != NULL)
74224ecf24eSchristos 			msg_fmt_display(MSG_nobiosgeom, "%d%d%d",
74324ecf24eSchristos 			    pm->dlcyl, pm->dlhead, pm->dlsec);
7444103857bSmartin 		if (guess_biosgeom_from_parts(parts, &cyl, &head, &sec) >= 0
74550dbef1aSdholland 		    && nip != NULL)
74624ecf24eSchristos 		{
74724ecf24eSchristos 			msg_fmt_display_add(MSG_biosguess, "%d%d%d",
74824ecf24eSchristos 			    cyl, head, sec);
74924ecf24eSchristos 		}
75050dbef1aSdholland 		biosdisk = NULL;
75150dbef1aSdholland 	} else {
7524103857bSmartin 		guess_biosgeom_from_parts(parts, &cyl, &head, &sec);
75350dbef1aSdholland 		if (nip->ni_nmatches == 1) {
75450dbef1aSdholland 			bip = &disklist->dl_biosdisks[nip->ni_biosmatches[0]];
75550dbef1aSdholland 			msg_display(MSG_onebiosmatch);
75650dbef1aSdholland 			msg_table_add(MSG_onebiosmatch_header);
75724ecf24eSchristos 			msg_fmt_table_add(MSG_onebiosmatch_row, "%d%d%d%d%u%u",
75824ecf24eSchristos 			    bip->bi_dev, bip->bi_cyl, bip->bi_head, bip->bi_sec,
75950dbef1aSdholland 			    (unsigned)bip->bi_lbasecs,
76050dbef1aSdholland 			    (unsigned)(bip->bi_lbasecs / (1000000000 / 512)));
76150dbef1aSdholland 			msg_display_add(MSG_biosgeom_advise);
76250dbef1aSdholland 			biosdisk = bip;
76350dbef1aSdholland 			process_menu(MENU_biosonematch, &biosdisk);
76450dbef1aSdholland 		} else {
76550dbef1aSdholland 			msg_display(MSG_biosmultmatch);
76650dbef1aSdholland 			msg_table_add(MSG_biosmultmatch_header);
76750dbef1aSdholland 			for (i = 0; i < nip->ni_nmatches; i++) {
76850dbef1aSdholland 				bip = &disklist->dl_biosdisks[
76950dbef1aSdholland 							nip->ni_biosmatches[i]];
77024ecf24eSchristos 				msg_fmt_table_add(MSG_biosmultmatch_row,
77124ecf24eSchristos 				    "%d%d%d%d%d%u%u", i,
77250dbef1aSdholland 				    bip->bi_dev, bip->bi_cyl, bip->bi_head,
77350dbef1aSdholland 				    bip->bi_sec, (unsigned)bip->bi_lbasecs,
77450dbef1aSdholland 				    (unsigned)bip->bi_lbasecs/(1000000000/512));
77550dbef1aSdholland 			}
77650dbef1aSdholland 			process_menu(MENU_biosmultmatch, &i);
77750dbef1aSdholland 			if (i == -1)
77850dbef1aSdholland 				biosdisk = NULL;
77950dbef1aSdholland 			else
78050dbef1aSdholland 				biosdisk = &disklist->dl_biosdisks[
78150dbef1aSdholland 							nip->ni_biosmatches[i]];
78250dbef1aSdholland 		}
78350dbef1aSdholland 	}
78450dbef1aSdholland 	if (biosdisk == NULL) {
7854103857bSmartin 		*bcyl = cyl;
7864103857bSmartin 		*bhead = head;
7874103857bSmartin 		*bsec = sec;
788d2aaad12Smartin 		if (nip != NULL)
789d2aaad12Smartin 			set_bios_geom(parts, bcyl, bhead, bsec);
79050dbef1aSdholland 	} else {
7914103857bSmartin 		*bcyl = biosdisk->bi_cyl;
7924103857bSmartin 		*bhead = biosdisk->bi_head;
7934103857bSmartin 		*bsec = biosdisk->bi_sec;
79450dbef1aSdholland 	}
7954103857bSmartin 	return true;
79650dbef1aSdholland }
79750dbef1aSdholland 
79850dbef1aSdholland static int
mbr_root_above_chs(daddr_t ptstart)7996ddad149Smartin mbr_root_above_chs(daddr_t ptstart)
80050dbef1aSdholland {
8016ddad149Smartin 	return ptstart + (daddr_t)DEFROOTSIZE * (daddr_t)(MEG / 512)
8024103857bSmartin 	    >= pm->max_chs;
80350dbef1aSdholland }
80450dbef1aSdholland 
8054103857bSmartin /* returns false if no write-back of parts is required */
8064103857bSmartin bool
md_mbr_update_check(struct disk_partitions * parts,mbr_info_t * mbri)8074103857bSmartin md_mbr_update_check(struct disk_partitions *parts, mbr_info_t *mbri)
80850dbef1aSdholland {
80950dbef1aSdholland 	struct mbr_partition *mbrp;
81050dbef1aSdholland 	int i, netbsdpart = -1, oldbsdpart = -1, oldbsdcount = 0;
81150dbef1aSdholland 
8124103857bSmartin 	if (pm->no_mbr || pm->no_part)
8134103857bSmartin 		return false;
81450dbef1aSdholland 
8154103857bSmartin 	mbrp = &mbri->mbr.mbr_parts[0];
81650dbef1aSdholland 
81750dbef1aSdholland 	for (i = 0; i < MBR_PART_COUNT; i++) {
81850dbef1aSdholland 		if (mbrp[i].mbrp_type == MBR_PTYPE_386BSD) {
81950dbef1aSdholland 			oldbsdpart = i;
82050dbef1aSdholland 			oldbsdcount++;
82150dbef1aSdholland 		} else if (mbrp[i].mbrp_type == MBR_PTYPE_NETBSD)
82250dbef1aSdholland 			netbsdpart = i;
82350dbef1aSdholland 	}
82450dbef1aSdholland 
82550dbef1aSdholland 	if (netbsdpart == -1 && oldbsdcount == 1) {
82650dbef1aSdholland 		mbrp[oldbsdpart].mbrp_type = MBR_PTYPE_NETBSD;
8274103857bSmartin 		return true;
82850dbef1aSdholland 	}
8294103857bSmartin 
8304103857bSmartin 	return false;
83150dbef1aSdholland }
83250dbef1aSdholland 
83350dbef1aSdholland /*
83450dbef1aSdholland  * Read MBR code from a file.
83550dbef1aSdholland  * The existing partition table and bootselect configuration is kept.
83650dbef1aSdholland  */
83750dbef1aSdholland static int
md_read_bootcode(const char * path,struct mbr_sector * mbrs)83850dbef1aSdholland md_read_bootcode(const char *path, struct mbr_sector *mbrs)
83950dbef1aSdholland {
84050dbef1aSdholland 	int fd;
84150dbef1aSdholland 	struct stat st;
84250dbef1aSdholland 	size_t len;
84350dbef1aSdholland 	struct mbr_sector new_mbr;
84450dbef1aSdholland 	uint32_t dsn;
84550dbef1aSdholland 
84650dbef1aSdholland 	fd = open(path, O_RDONLY);
84750dbef1aSdholland 	if (fd < 0)
84850dbef1aSdholland 		return -1;
84950dbef1aSdholland 
85050dbef1aSdholland 	if (fstat(fd, &st) < 0 || st.st_size != sizeof *mbrs) {
85150dbef1aSdholland 		close(fd);
85250dbef1aSdholland 		return -1;
85350dbef1aSdholland 	}
85450dbef1aSdholland 
85550dbef1aSdholland 	if (read(fd, &new_mbr, sizeof new_mbr) != sizeof new_mbr) {
85650dbef1aSdholland 		close(fd);
85750dbef1aSdholland 		return -1;
85850dbef1aSdholland 	}
85950dbef1aSdholland 	close(fd);
86050dbef1aSdholland 
86150dbef1aSdholland 	if (new_mbr.mbr_bootsel_magic != htole16(MBR_BS_MAGIC))
86250dbef1aSdholland 		return -1;
86350dbef1aSdholland 
86450dbef1aSdholland 	if (mbrs->mbr_bootsel_magic == htole16(MBR_BS_MAGIC)) {
86550dbef1aSdholland 		len = offsetof(struct mbr_sector, mbr_bootsel);
86650dbef1aSdholland 	} else
86750dbef1aSdholland 		len = offsetof(struct mbr_sector, mbr_parts);
86850dbef1aSdholland 
86950dbef1aSdholland 	/* Preserve the 'drive serial number' - especially for Vista */
87050dbef1aSdholland 	dsn = mbrs->mbr_dsn;
87150dbef1aSdholland 	memcpy(mbrs, &new_mbr, len);
87250dbef1aSdholland 	mbrs->mbr_dsn = dsn;
87350dbef1aSdholland 
87450dbef1aSdholland 	/* Keep flags from object file - indicate the properties */
87550dbef1aSdholland 	mbrs->mbr_bootsel.mbrbs_flags = new_mbr.mbr_bootsel.mbrbs_flags;
87650dbef1aSdholland 	mbrs->mbr_magic = htole16(MBR_MAGIC);
87750dbef1aSdholland 
87850dbef1aSdholland 	return 0;
87950dbef1aSdholland }
88050dbef1aSdholland 
88150dbef1aSdholland static unsigned int
get_bootmodel(void)88250dbef1aSdholland get_bootmodel(void)
88350dbef1aSdholland {
88450dbef1aSdholland #if defined(__i386__)
88550dbef1aSdholland 	struct utsname ut;
88650dbef1aSdholland #ifdef DEBUG
88750dbef1aSdholland 	char *envstr;
88850dbef1aSdholland 
88950dbef1aSdholland 	envstr = getenv("BOOTMODEL");
89050dbef1aSdholland 	if (envstr != NULL)
89150dbef1aSdholland 		return atoi(envstr);
89250dbef1aSdholland #endif
89350dbef1aSdholland 
89450dbef1aSdholland 	if (uname(&ut) < 0)
89550dbef1aSdholland 		ut.version[0] = 0;
89650dbef1aSdholland 
89750dbef1aSdholland #if defined(SET_KERNEL_TINY)
89850dbef1aSdholland 	if (strstr(ut.version, "TINY") != NULL)
89950dbef1aSdholland 		return SET_KERNEL_TINY;
90050dbef1aSdholland #endif
90150dbef1aSdholland #if defined(SET_KERNEL_PS2)
90250dbef1aSdholland 	if (strstr(ut.version, "PS2") != NULL)
90350dbef1aSdholland 		return SET_KERNEL_PS2;
90450dbef1aSdholland #endif
90550dbef1aSdholland #endif
90650dbef1aSdholland 	return SET_KERNEL_GENERIC;
90750dbef1aSdholland }
90850dbef1aSdholland 
90950dbef1aSdholland 
91050dbef1aSdholland int
md_pre_mount(struct install_partition_desc * install,size_t ndx)9114f30cbf3Smartin md_pre_mount(struct install_partition_desc *install, size_t ndx)
91250dbef1aSdholland {
91350dbef1aSdholland 	return 0;
91450dbef1aSdholland }
9154103857bSmartin 
9164103857bSmartin #ifdef HAVE_GPT
9174103857bSmartin /*
9184103857bSmartin  * New GPT partitions have been written, update bootloader or remember
9194103857bSmartin  * data untill needed in md_post_newfs
9204103857bSmartin  */
9214103857bSmartin bool
md_gpt_post_write(struct disk_partitions * parts,part_id root_id,bool root_is_new,part_id efi_id,bool efi_is_new)9224103857bSmartin md_gpt_post_write(struct disk_partitions *parts, part_id root_id,
9234103857bSmartin     bool root_is_new, part_id efi_id, bool efi_is_new)
9244103857bSmartin {
9254103857bSmartin 	struct disk_part_info info;
9264103857bSmartin 
9274103857bSmartin 	if (root_id != NO_PART) {
9284103857bSmartin 		/* we always update the gpt boot record for now */
9294103857bSmartin 		if (!parts->pscheme->get_part_info(parts, root_id, &info))
9304103857bSmartin 			return false;
9314103857bSmartin 		if (run_program(RUN_SILENT, "gpt biosboot -b %" PRIu64 " %s",
9324103857bSmartin 		    info.start, parts->disk) != 0)
9334103857bSmartin 			return false;
9344103857bSmartin 	}
9354103857bSmartin 
9364103857bSmartin 	return true;
9374103857bSmartin }
9384103857bSmartin #endif
93932ea71a6Smartin 
94032ea71a6Smartin /*
94132ea71a6Smartin  * When we do an UEFI install, we have completely different default
94232ea71a6Smartin  * partitions and need to adjust the description at runtime.
94332ea71a6Smartin  */
94432ea71a6Smartin void
x86_md_part_defaults(struct pm_devs * cur_pm,struct part_usage_info ** partsp,size_t * num_usage_infos)94532ea71a6Smartin x86_md_part_defaults(struct pm_devs *cur_pm, struct part_usage_info **partsp,
94632ea71a6Smartin     size_t *num_usage_infos)
94732ea71a6Smartin {
94832ea71a6Smartin 	static const struct part_usage_info uefi_boot_part =
94932ea71a6Smartin 	{
95032ea71a6Smartin 		.size = BOOT_PART,
95132ea71a6Smartin 		.type = BOOT_PART_TYPE,
95232ea71a6Smartin 		.instflags = PUIINST_NEWFS|PUIINST_BOOT,
95332ea71a6Smartin 		.fs_type = FS_MSDOS, .fs_version = MBR_PTYPE_FAT32L,
95432ea71a6Smartin 		.flags = PUIFLAG_ADD_OUTER,
95532ea71a6Smartin 	};
95632ea71a6Smartin 
95732ea71a6Smartin 	struct disk_partitions *parts;
95832ea71a6Smartin 	struct part_usage_info *new_usage, *boot;
95932ea71a6Smartin 	struct disk_part_info info;
96032ea71a6Smartin 	size_t num;
96132ea71a6Smartin 	part_id pno;
96232ea71a6Smartin 
96332ea71a6Smartin 	if (!uefi_boot)
96432ea71a6Smartin 		return;		/* legacy defaults apply */
96532ea71a6Smartin 
96632ea71a6Smartin 	/*
96732ea71a6Smartin 	 * Insert a UEFI boot partition at the beginning of the array
96832ea71a6Smartin 	 */
96932ea71a6Smartin 
97032ea71a6Smartin 	/* create space for new description */
97132ea71a6Smartin 	num = *num_usage_infos + 1;
97232ea71a6Smartin 	new_usage = realloc(*partsp, sizeof(*new_usage)*num);
97332ea71a6Smartin 	if (new_usage == NULL)
97432ea71a6Smartin 		return;
97532ea71a6Smartin 	*partsp = new_usage;
97632ea71a6Smartin 	*num_usage_infos = num;
97732ea71a6Smartin 	boot = new_usage;
97832ea71a6Smartin 	memmove(boot+1, boot, sizeof(*boot)*(num-1));
97932ea71a6Smartin 	*boot = uefi_boot_part;
98032ea71a6Smartin 
98132ea71a6Smartin 	/*
98232ea71a6Smartin 	 * Check if the UEFI partition already exists
98332ea71a6Smartin 	 */
98432ea71a6Smartin 	parts = pm->parts;
98532ea71a6Smartin 	if (parts->parent != NULL)
98632ea71a6Smartin 		parts = parts->parent;
98732ea71a6Smartin 	for (pno = 0; pno < parts->num_part; pno++) {
98832ea71a6Smartin 		if (!parts->pscheme->get_part_info(parts, pno, &info))
98932ea71a6Smartin 			continue;
99032ea71a6Smartin 		if (info.nat_type->generic_ptype != boot->type)
99132ea71a6Smartin 			continue;
99232ea71a6Smartin 		boot->flags &= ~PUIFLAG_ADD_OUTER;
993f77b58b1Smartin 		boot->flags |= PUIFLG_IS_OUTER|PUIFLG_ADD_INNER;
99432ea71a6Smartin 		boot->size = info.size;
99532ea71a6Smartin 		boot->cur_start = info.start;
99632ea71a6Smartin 		boot->cur_flags = info.flags;
99732ea71a6Smartin 		break;
99832ea71a6Smartin 	}
99932ea71a6Smartin }
100032ea71a6Smartin 
100132ea71a6Smartin /* no need to install bootblock if installing for UEFI */
100232ea71a6Smartin bool
x86_md_need_bootblock(struct install_partition_desc * install)100332ea71a6Smartin x86_md_need_bootblock(struct install_partition_desc *install)
100432ea71a6Smartin {
100532ea71a6Smartin 
100632ea71a6Smartin 	return !uefi_boot;
100732ea71a6Smartin }
1008