Annotation of src/usr.sbin/sysinst/arch/i386/md.c, Revision 1.20.2.9
1.20.2.9! msaitoh 1: /* $NetBSD: md.c,v 1.20.2.8 2020/11/04 13:31:23 sborrill Exp $ */
1.1 dholland 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 -- i386 machine specific routines - also used by amd64 */
36:
37: #include <sys/param.h>
38: #include <sys/sysctl.h>
39: #include <sys/exec.h>
40: #include <sys/utsname.h>
41: #include <sys/types.h>
42: #include <sys/stat.h>
43: #include <machine/cpu.h>
1.15 martin 44: #include <assert.h>
1.1 dholland 45: #include <stdio.h>
46: #include <stddef.h>
47: #include <util.h>
48: #include <dirent.h>
49: #include <termios.h>
50:
51: #include "defs.h"
52: #include "md.h"
53: #include "endian.h"
54: #include "msg_defs.h"
55: #include "menu_defs.h"
56:
57: #ifdef NO_LBA_READS /* for testing */
58: #undef BIFLAG_EXTINT13
59: #define BIFLAG_EXTINT13 0
60: #endif
61:
62: static struct biosdisk_info *biosdisk = NULL;
1.20 martin 63: static bool uefi_boot;
1.1 dholland 64:
65: /* prototypes */
66:
1.15 martin 67: static bool get_bios_info(const char*, struct disk_partitions*, int*, int*, int*);
1.20.2.7 bouyer 68: static int mbr_root_above_chs(daddr_t);
1.1 dholland 69: static int md_read_bootcode(const char *, struct mbr_sector *);
70: static unsigned int get_bootmodel(void);
71:
1.20 martin 72: static int conmib[] = { CTL_MACHDEP, CPU_CONSDEV };
73:
74: #define BOOT_PART (128*(MEG/512))
75: #define BOOT_PART_TYPE PT_EFI_SYSTEM
76:
77: static const char * uefi_bootloaders[] = {
78: "/usr/mdec/bootia32.efi",
79: "/usr/mdec/bootx64.efi",
80: };
1.13 martin 81:
1.1 dholland 82: void
83: md_init(void)
84: {
1.20 martin 85: char boot_method[100];
86: size_t len;
87:
88: len = sizeof(boot_method);
89: if (sysctlbyname("machdep.bootmethod", boot_method, &len, NULL, 0)
90: != -1) {
91: if (strcmp(boot_method, "BIOS") == 0)
92: uefi_boot = false;
93: else if (strcmp(boot_method, "UEFI") == 0)
94: uefi_boot = true;
95: }
1.1 dholland 96: }
97:
98: void
99: md_init_set_status(int flags)
100: {
101: (void)flags;
102:
103: /* Default to install same type of kernel as we are running */
104: set_kernel_set(get_bootmodel());
105: }
106:
1.15 martin 107: bool
108: md_get_info(struct install_partition_desc *install)
1.1 dholland 109: {
1.20.2.7 bouyer 110: int bcyl = 0, bhead = 0, bsec = 0, res;
1.1 dholland 111:
1.15 martin 112: if (pm->no_mbr || pm->no_part)
113: return true;
1.1 dholland 114:
1.20.2.7 bouyer 115: again:
1.15 martin 116: if (pm->parts == NULL) {
1.1 dholland 117:
1.15 martin 118: const struct disk_partitioning_scheme *ps =
119: select_part_scheme(pm, NULL, true, NULL);
1.1 dholland 120:
1.15 martin 121: if (!ps)
1.20.2.1 msaitoh 122: return false;
1.1 dholland 123:
1.15 martin 124: struct disk_partitions *parts =
125: (*ps->create_new_for_disk)(pm->diskdev,
1.20.2.5 msaitoh 126: 0, pm->dlsize, true, NULL);
1.15 martin 127: if (!parts)
128: return false;
1.1 dholland 129:
1.15 martin 130: pm->parts = parts;
131: if (ps->size_limit > 0 && pm->dlsize > ps->size_limit)
132: pm->dlsize = ps->size_limit;
1.1 dholland 133: }
134:
1.15 martin 135: if (get_bios_info(pm->diskdev, pm->parts, &bcyl, &bhead, &bsec)
136: && pm->parts->pscheme->change_disk_geom != NULL)
137: pm->parts->pscheme->change_disk_geom(pm->parts,
138: bcyl, bhead, bsec);
139: else
1.20.2.5 msaitoh 140: set_default_sizemult(pm->diskdev, MEG, pm->sectorsize);
1.1 dholland 141:
1.15 martin 142: /*
143: * If the selected scheme does not need two-stage partitioning
144: * (like GPT), do not bother to edit the outer partitions.
145: */
146: if (pm->parts->pscheme->secondary_partitions == NULL ||
147: pm->parts->pscheme->secondary_scheme == NULL)
148: return true;
1.1 dholland 149:
1.15 martin 150: if (pm->no_mbr || pm->no_part)
151: return true;
1.1 dholland 152:
1.20.2.7 bouyer 153: res = edit_outer_parts(pm->parts);
154: if (res == 0)
155: return false;
156: else if (res == 1)
157: return true;
158:
159: pm->parts->pscheme->destroy_part_scheme(pm->parts);
160: pm->parts = NULL;
161: goto again;
1.1 dholland 162: }
163:
164: /*
165: * md back-end code for menu-driven BSD disklabel editor.
166: */
1.20.2.7 bouyer 167: int
1.15 martin 168: md_make_bsd_partitions(struct install_partition_desc *install)
1.1 dholland 169: {
1.15 martin 170: return make_bsd_partitions(install);
1.1 dholland 171: }
172:
173: /*
174: * any additional partition validation
175: */
1.15 martin 176: bool
177: md_check_partitions(struct install_partition_desc *install)
1.1 dholland 178: {
179: int rval;
180: char *bootxx;
181:
1.20 martin 182: /* if booting via UEFI no boot blocks are needed */
183: if (uefi_boot)
184: return true;
185:
1.1 dholland 186: /* check we have boot code for the root partition type */
1.15 martin 187: bootxx = bootxx_name(install);
1.1 dholland 188: rval = access(bootxx, R_OK);
189: free(bootxx);
190: if (rval == 0)
1.15 martin 191: return true;
1.8 joerg 192: process_menu(MENU_ok, __UNCONST(MSG_No_Bootcode));
1.15 martin 193: return false;
1.1 dholland 194: }
195:
196: /*
197: * hook called before writing new disklabel.
198: */
1.15 martin 199: bool
200: md_pre_disklabel(struct install_partition_desc *install,
201: struct disk_partitions *parts)
1.1 dholland 202: {
203:
1.15 martin 204: if (parts->parent == NULL)
205: return true; /* no outer partitions */
206:
207: parts = parts->parent;
208:
209: msg_display_subst(MSG_dofdisk, 3, parts->disk,
210: msg_string(parts->pscheme->name),
211: msg_string(parts->pscheme->short_name));
1.1 dholland 212:
1.15 martin 213: /* write edited "MBR" onto disk. */
214: if (!parts->pscheme->write_to_disk(parts)) {
1.1 dholland 215: msg_display(MSG_wmbrfail);
216: process_menu(MENU_ok, NULL);
1.15 martin 217: return false;
1.1 dholland 218: }
1.15 martin 219: return true;
1.1 dholland 220: }
221:
222: /*
223: * hook called after writing disklabel to new target disk.
224: */
1.15 martin 225: bool
226: md_post_disklabel(struct install_partition_desc *install,
227: struct disk_partitions *parts)
1.1 dholland 228: {
1.15 martin 229: return true;
1.1 dholland 230: }
231:
232: /*
1.20 martin 233: * Do all legacy bootblock update/setup here
1.1 dholland 234: */
1.20 martin 235: static int
1.20.2.9! msaitoh 236: update_bios_boot(struct install_partition_desc *install, bool use_target_files)
1.1 dholland 237: {
238: int ret;
239: size_t len;
1.3 riz 240: char boot_options[1024];
1.20.2.9! msaitoh 241: char *bootxx_filename, *p;
1.1 dholland 242: /*
1.3 riz 243: * XXX - this code retains a lot of cruft from when we went
244: * to great pains to exclude installboot from the ramdisk
245: * for size reasons and should be rewritten.
1.1 dholland 246: */
1.3 riz 247: static const char *consoles[]={
248: "pc", /* CONSDEV_PC */
249: "com0", /* CONSDEV_COM0 */
250: "com1", /* CONSDEV_COM1 */
251: "com2", /* CONSDEV_COM2 */
252: "com3", /* CONSDEV_COM3 */
253: "com0kbd", /* CONSDEV_COM0KBD */
254: "com1kbd", /* CONSDEV_COM1KBD */
255: "com2kbd", /* CONSDEV_COM2KBD */
256: "com3kbd" /* CONSDEV_COM3KBD */ };
1.1 dholland 257: static struct x86_boot_params boottype =
258: {sizeof boottype, 0, 5, 0, 9600, { '\0' }, "", 0};
259: struct termios t;
260: dev_t condev;
261:
1.9 martin 262: if (pm == NULL || !pm->no_part) {
263: /*
264: * Get console device, should either be ttyE0 or tty0n.
265: * Too hard to double check, so just 'know' the device numbers.
266: */
267: len = sizeof condev;
1.20.2.2 msaitoh 268: if (sysctl(conmib, __arraycount(conmib), &condev, &len, NULL,
269: 0) != -1 && (condev & ~3) == 0x800) {
1.9 martin 270: /* Motherboard serial port */
271: boottype.bp_consdev = (condev & 3) + 1;
1.20.2.2 msaitoh 272: /* Defaulting the baud rate to that of stdin should
273: suffice */
1.9 martin 274: if (tcgetattr(0, &t) != -1)
275: boottype.bp_conspeed = t.c_ispeed;
276: }
277:
278: process_menu(MENU_getboottype, &boottype);
1.18 christos 279: msg_fmt_display(MSG_dobootblks, "%s", pm->diskdev);
1.9 martin 280: if (boottype.bp_consdev == ~0u)
281: /* Use existing bootblocks */
282: return 0;
1.1 dholland 283: }
284:
1.20.2.9! msaitoh 285: if (use_target_files)
! 286: ret = cp_within_target("/usr/mdec/boot", "/", 0);
! 287: else
! 288: ret = cp_to_target("/usr/mdec/boot", "/");
1.1 dholland 289: if (ret)
290: return ret;
1.9 martin 291: if (pm && pm->no_part)
292: return 0;
1.1 dholland 293:
1.20.2.9! msaitoh 294: p = bootxx_name(install);
! 295: if (p && use_target_files) {
! 296: bootxx_filename = strdup(target_expand(p));
! 297: free(p);
! 298: } else {
! 299: bootxx_filename = p;
! 300: }
1.9 martin 301: if (bootxx_filename != NULL) {
1.15 martin 302: char rdev[PATH_MAX];
303:
304: install->infos[0].parts->pscheme->get_part_device(
305: install->infos[0].parts, install->infos[0].cur_part_id,
1.20.2.5 msaitoh 306: rdev, sizeof rdev, NULL, raw_dev_name, true, true);
1.15 martin 307:
1.3 riz 308: snprintf(boot_options, sizeof boot_options,
309: "console=%s,speed=%u", consoles[boottype.bp_consdev],
310: boottype.bp_conspeed);
1.15 martin 311: ret = run_program(RUN_DISPLAY,
1.20.2.6 bouyer 312: "/usr/sbin/installboot -f -o %s %s %s",
1.16 martin 313: boot_options, rdev, bootxx_filename);
1.15 martin 314: free(bootxx_filename);
1.16 martin 315: } else {
316: ret = -1;
317: }
318:
319: if (ret != 0)
320: process_menu(MENU_ok,
321: __UNCONST("Warning: disk is probably not bootable"));
1.1 dholland 322:
323: return ret;
324: }
325:
1.20.2.9! msaitoh 326: static int
! 327: md_post_newfs_bios(struct install_partition_desc *install)
! 328: {
! 329: return update_bios_boot(install, false);
! 330: }
! 331:
1.20 martin 332: /*
333: * Make sure our bootloader(s) are in the proper directory in the boot
334: * boot partition (or update them).
335: */
336: static int
337: copy_uefi_boot(const struct part_usage_info *boot)
338: {
1.20.2.9! msaitoh 339: char dev[MAXPATHLEN], path[MAXPATHLEN], src[MAXPATHLEN];
1.20 martin 340: size_t i;
341: int err;
342:
343: if (!boot->parts->pscheme->get_part_device(boot->parts,
1.20.2.5 msaitoh 344: boot->cur_part_id, dev, sizeof(dev), NULL, plain_name, true, true))
1.20 martin 345: return -1;
346:
347: /*
348: * We should have a valid file system on that partition.
349: * Try to mount it and check if there is a /EFI in there.
350: */
351: if (boot->mount[0])
352: strlcpy(path, boot->mount, sizeof(path));
353: else
354: strcpy(path, "/mnt");
355:
356: if (!(boot->instflags & PUIINST_MOUNT)) {
357: make_target_dir(path);
358: err = target_mount("", dev, path);
359: if (err != 0)
360: return err;
361: }
362:
363: strlcat(path, "/EFI/boot", sizeof(path));
364: make_target_dir(path);
365:
366: for (i = 0; i < __arraycount(uefi_bootloaders); i++) {
1.20.2.9! msaitoh 367: strcpy(src, target_expand(uefi_bootloaders[i]));
! 368: if (access(src, R_OK) != 0)
1.20 martin 369: continue;
1.20.2.9! msaitoh 370: err = cp_within_target(uefi_bootloaders[i], path, 0);
1.20 martin 371: if (err)
372: return err;
373: }
374:
375: return 0;
376: }
377:
378: /*
379: * Find (U)EFI boot partition and install/update bootloaders
380: */
381: static int
1.20.2.9! msaitoh 382: update_uefi_boot_code(struct install_partition_desc *install)
1.20 martin 383: {
1.20.2.9! msaitoh 384: size_t i, boot_part;
1.20 martin 385:
1.20.2.9! msaitoh 386: boot_part = ~0U;
1.20 martin 387: for (i = 0; i < install->num; i++) {
388: if (!(install->infos[i].instflags & PUIINST_BOOT))
389: continue;
1.20.2.9! msaitoh 390: boot_part = i;
! 391: break;
! 392: }
! 393: if (boot_part == ~0U) {
! 394: /*
! 395: * Didn't find an explicitly marked boot partition,
! 396: * check if we have any EFI System Partitions and
! 397: * use the first.
! 398: */
! 399: for (i = 0; i < install->num; i++) {
! 400: if (install->infos[i].type != PT_EFI_SYSTEM)
! 401: continue;
! 402: boot_part = i;
! 403: break;
! 404: }
1.20 martin 405: }
406:
1.20.2.9! msaitoh 407: if (boot_part < install->num)
! 408: return copy_uefi_boot(&install->infos[boot_part]);
! 409:
1.20 martin 410: return -1; /* no EFI boot partition found */
411: }
1.20.2.9! msaitoh 412:
! 413: /*
! 414: * Find bootloader options and update bootloader
! 415: */
! 416: static int
! 417: update_bios_boot_code(struct install_partition_desc *install)
! 418: {
! 419: return update_bios_boot(install, true);
! 420: }
! 421:
! 422: static int
! 423: update_boot_code(struct install_partition_desc *install)
! 424: {
! 425: return uefi_boot ?
! 426: update_uefi_boot_code(install)
! 427: : update_bios_boot_code(install);
! 428: }
! 429:
! 430: static int
! 431: md_post_newfs_uefi(struct install_partition_desc *install)
! 432: {
! 433: return update_uefi_boot_code(install);
! 434: }
1.20 martin 435:
436: /*
437: * hook called after upgrade() or install() has finished setting
438: * up the target disk but immediately before the user is given the
439: * ``disks are now set up'' message.
440: */
441: int
442: md_post_newfs(struct install_partition_desc *install)
443: {
444:
445: return uefi_boot ? md_post_newfs_uefi(install)
446: : md_post_newfs_bios(install);
447: }
448:
1.1 dholland 449: int
1.20.2.9! msaitoh 450: md_post_extract(struct install_partition_desc *install, bool upgrade)
1.1 dholland 451: {
1.20.2.9! msaitoh 452: if (upgrade)
! 453: update_boot_code(install);
! 454:
1.20.2.3 msaitoh 455: #if defined(__amd64__)
456: if (get_kernel_set() == SET_KERNEL_2) {
457: int ret;
458:
459: ret = cp_within_target("/usr/mdec/prekern", "/prekern", 0);
460: if (ret)
461: return ret;
462: }
463: #endif
1.20.2.9! msaitoh 464:
1.1 dholland 465: return 0;
466: }
467:
468: void
1.15 martin 469: md_cleanup_install(struct install_partition_desc *install)
1.1 dholland 470: {
1.13 martin 471: size_t len;
472: dev_t condev;
473:
1.1 dholland 474: #ifndef DEBUG
475: enable_rc_conf();
476: add_rc_conf("wscons=YES\n");
477:
478: # if defined(__i386__) && defined(SET_KERNEL_TINY)
479: /*
480: * For GENERIC_TINY, do not enable any extra screens or wsmux.
481: * Otherwise, run getty on 4 VTs.
482: */
483: if (get_kernel_set() == SET_KERNEL_TINY)
484: run_program(RUN_CHROOT,
485: "sed -an -e '/^screen/s/^/#/;/^mux/s/^/#/;"
486: "H;$!d;g;w /etc/wscons.conf' /etc/wscons.conf");
487: else
488: # endif
489: run_program(RUN_CHROOT,
490: "sed -an -e '/^ttyE[1-9]/s/off/on/;"
491: "H;$!d;g;w /etc/ttys' /etc/ttys");
492:
493: #endif
1.13 martin 494:
495: /*
496: * Get console device, should either be ttyE0 or tty0n.
497: * Too hard to double check, so just 'know' the device numbers.
498: */
499: len = sizeof condev;
1.15 martin 500: if (sysctl(conmib, __arraycount(conmib), &condev, &len, NULL, 0) != -1
1.13 martin 501: && (condev & ~3) != 0x800) {
502:
503: /*
504: * Current console is not com*, assume ttyE*.
505: * Modify /etc/ttys to use wsvt25 for all ports.
506: */
507:
508: run_program(RUN_CHROOT,
509: "sed -an -e 's/vt100/wsvt25/g;"
510: "H;$!d;g;w /etc/ttys' /etc/ttys");
511: }
1.1 dholland 512: }
513:
514: int
1.15 martin 515: md_pre_update(struct install_partition_desc *install)
1.1 dholland 516: {
517: return 1;
518: }
519:
520: /* Upgrade support */
521: int
1.15 martin 522: md_update(struct install_partition_desc *install)
1.1 dholland 523: {
524: return 1;
525: }
526:
527: int
1.15 martin 528: md_check_mbr(struct disk_partitions *parts, mbr_info_t *mbri, bool quiet)
1.1 dholland 529: {
1.15 martin 530: mbr_info_t *ext;
531: struct mbr_partition *p;
532: const char *bootcode;
1.20.2.7 bouyer 533: daddr_t inst_start, inst_size;
1.15 martin 534: int i, names, fl, ofl;
535: #define ACTIVE_FOUND 0x0100
536: #define NETBSD_ACTIVE 0x0200
537: #define NETBSD_NAMED 0x0400
538: #define ACTIVE_NAMED 0x0800
539:
540: root_limit = 0;
1.20.2.7 bouyer 541: if (parts->pscheme->guess_install_target == NULL ||
542: !parts->pscheme->guess_install_target(parts, &inst_start,
543: &inst_size)) {
544: inst_start = parts->disk_start;
545: inst_size = parts->disk_size;
546: }
547:
1.15 martin 548: if (biosdisk != NULL && (biosdisk->bi_flags & BIFLAG_EXTINT13) == 0) {
1.20.2.7 bouyer 549: if (mbr_root_above_chs(inst_start)) {
1.15 martin 550: if (quiet)
551: return 0;
552: msg_display(MSG_partabovechs);
553: if (!ask_noyes(NULL))
554: return 1;
555: /* The user is shooting themselves in the foot here...*/
556: } else {
557: if (parts->pscheme->size_limit)
558: root_limit = min(parts->pscheme->size_limit,
559: parts->disk_size);
560: else
561: root_limit = parts->disk_size;
562: }
563: }
564:
565: /*
1.20.2.7 bouyer 566: * Ensure the install partition (at sector inst_start) and the active
1.15 martin 567: * partition are bootable.
568: * Determine whether the bootselect code is needed.
569: * Note that MBR_BS_NEWMBR is always set, so we ignore it!
570: */
571: fl = 0;
572: names = 0;
573: for (ext = mbri; ext != NULL; ext = ext->extended) {
574: p = ext->mbr.mbr_parts;
575: for (i = 0; i < MBR_PART_COUNT; p++, i++) {
576: if (p->mbrp_flag == MBR_PFLAG_ACTIVE) {
577: fl |= ACTIVE_FOUND;
1.20.2.7 bouyer 578: if (ext->sector + p->mbrp_start == inst_start)
1.15 martin 579: fl |= NETBSD_ACTIVE;
580: }
581: if (ext->mbrb.mbrbs_nametab[i][0] == 0) {
582: /* No bootmenu label... */
583: if (ext->sector == 0)
584: continue;
1.20.2.7 bouyer 585: if (ext->sector + p->mbrp_start == inst_start)
1.15 martin 586: /*
587: * Have installed into an extended ptn
588: * force name & bootsel...
589: */
590: names++;
591: continue;
592: }
593: /* Partition has a bootmenu label... */
594: if (ext->sector != 0)
595: fl |= MBR_BS_EXTLBA;
1.20.2.7 bouyer 596: if (ext->sector + p->mbrp_start == inst_start)
1.15 martin 597: fl |= NETBSD_NAMED;
598: else if (p->mbrp_flag == MBR_PFLAG_ACTIVE)
599: fl |= ACTIVE_NAMED;
600: else
601: names++;
602: }
603: }
604: if (!(fl & ACTIVE_FOUND))
605: fl |= NETBSD_ACTIVE;
606: if (fl & NETBSD_NAMED && fl & NETBSD_ACTIVE)
607: fl |= ACTIVE_NAMED;
608:
609: if ((names > 0 || !(fl & NETBSD_ACTIVE)) &&
610: (!(fl & NETBSD_NAMED) || !(fl & ACTIVE_NAMED))) {
611: /*
612: * There appear to be multiple bootable partitions, but they
613: * don't all have bootmenu texts.
614: */
615: if (quiet)
616: return 0;
617:
618: msg_display(MSG_missing_bootmenu_text);
619: if (ask_yesno(NULL))
620: return 1;
621: }
622:
623: if ((fl & MBR_BS_EXTLBA) &&
624: (biosdisk == NULL || !(biosdisk->bi_flags & BIFLAG_EXTINT13))) {
625: /* Need unsupported LBA reads to read boot sectors */
626: if (quiet)
627: return 0;
628:
629: msg_display(MSG_no_extended_bootmenu);
630: if (!ask_noyes(NULL))
631: return 1;
632: }
633:
634: /* Sort out the name of the mbr code we need */
1.20.2.8 sborrill 635: if (names > 1 ||
636: (parts->num_part > 1 && (fl & (NETBSD_NAMED | ACTIVE_NAMED)))) {
1.15 martin 637: /* Need bootselect code */
638: fl |= MBR_BS_ACTIVE;
639: bootcode = fl & MBR_BS_EXTLBA ? _PATH_BOOTEXT : _PATH_BOOTSEL;
1.20.2.8 sborrill 640: } else {
1.15 martin 641: bootcode = _PATH_MBR;
1.20.2.8 sborrill 642: }
1.15 martin 643:
644: fl &= MBR_BS_ACTIVE | MBR_BS_EXTLBA;
645:
646: /* Look at what is installed */
647: ofl = mbri->mbrb.mbrbs_flags;
648: if (ofl == 0) {
649: /* Check there is some bootcode at all... */
650: if (mbri->mbr.mbr_magic != htole16(MBR_MAGIC) ||
651: mbri->mbr.mbr_jmpboot[0] == 0 ||
1.20.2.7 bouyer 652: mbr_root_above_chs(inst_start))
1.15 martin 653: /* Existing won't do, force update */
654: fl |= MBR_BS_NEWMBR;
655: }
656: ofl = mbri->oflags & (MBR_BS_ACTIVE | MBR_BS_EXTLBA);
657:
658: if (!quiet) {
659: if (fl & ~ofl || (fl == 0 && ofl & MBR_BS_ACTIVE)) {
660: /* Existing boot code isn't the right one... */
661: if (fl & MBR_BS_ACTIVE)
662: msg_display(MSG_installbootsel);
663: else
664: msg_display(MSG_installmbr);
665: } else
666: /* Existing code would (probably) be ok */
667: msg_display(MSG_updatembr);
668:
669: if (!ask_yesno(NULL))
670: /* User doesn't want to update mbr code */
671: return 2;
672: }
673:
674: if (md_read_bootcode(bootcode, &mbri->mbr) == 0)
675: /* update suceeded - to memory copy */
676: return 2;
677:
678: /* This shouldn't happen since the files are in the floppy fs... */
1.18 christos 679: msg_fmt_display("Can't find %s", "%s", bootcode);
1.15 martin 680: return ask_reedit(parts);
1.1 dholland 681: }
682:
1.15 martin 683: bool
684: md_parts_use_wholedisk(struct disk_partitions *parts)
1.1 dholland 685: {
1.20 martin 686: struct disk_part_info boot_part = {
687: .size = BOOT_PART,
688: .fs_type = FS_MSDOS, .fs_sub_type = MBR_PTYPE_FAT32L,
689: };
690:
691: if (!uefi_boot)
692: return parts_use_wholedisk(parts, 0, NULL);
693:
694: boot_part.nat_type = parts->pscheme->get_generic_part_type(
695: PT_EFI_SYSTEM);
696:
697: return parts_use_wholedisk(parts, 1, &boot_part);
1.1 dholland 698: }
699:
1.15 martin 700: static bool
701: get_bios_info(const char *dev, struct disk_partitions *parts, int *bcyl,
702: int *bhead, int *bsec)
1.1 dholland 703: {
704: static struct disklist *disklist = NULL;
705: static int mib[2] = {CTL_MACHDEP, CPU_DISKINFO};
706: int i;
707: size_t len;
708: struct biosdisk_info *bip;
709: struct nativedisk_info *nip = NULL, *nat;
1.15 martin 710: int cyl, head, sec;
1.1 dholland 711:
712: if (disklist == NULL) {
713: if (sysctl(mib, 2, NULL, &len, NULL, 0) < 0)
714: goto nogeom;
715: disklist = malloc(len);
716: if (disklist == NULL) {
717: fprintf(stderr, "Out of memory\n");
1.15 martin 718: return false;
1.1 dholland 719: }
720: sysctl(mib, 2, disklist, &len, NULL, 0);
721: }
722:
723: for (i = 0; i < disklist->dl_nnativedisks; i++) {
724: nat = &disklist->dl_nativedisks[i];
725: if (!strcmp(dev, nat->ni_devname)) {
726: nip = nat;
727: break;
728: }
729: }
730: if (nip == NULL || nip->ni_nmatches == 0) {
731: nogeom:
732: if (nip != NULL)
1.18 christos 733: msg_fmt_display(MSG_nobiosgeom, "%d%d%d",
734: pm->dlcyl, pm->dlhead, pm->dlsec);
1.15 martin 735: if (guess_biosgeom_from_parts(parts, &cyl, &head, &sec) >= 0
1.1 dholland 736: && nip != NULL)
1.18 christos 737: {
738: msg_fmt_display_add(MSG_biosguess, "%d%d%d",
739: cyl, head, sec);
740: }
1.1 dholland 741: biosdisk = NULL;
742: } else {
1.15 martin 743: guess_biosgeom_from_parts(parts, &cyl, &head, &sec);
1.1 dholland 744: if (nip->ni_nmatches == 1) {
745: bip = &disklist->dl_biosdisks[nip->ni_biosmatches[0]];
746: msg_display(MSG_onebiosmatch);
747: msg_table_add(MSG_onebiosmatch_header);
1.18 christos 748: msg_fmt_table_add(MSG_onebiosmatch_row, "%d%d%d%d%u%u",
749: bip->bi_dev, bip->bi_cyl, bip->bi_head, bip->bi_sec,
1.1 dholland 750: (unsigned)bip->bi_lbasecs,
751: (unsigned)(bip->bi_lbasecs / (1000000000 / 512)));
752: msg_display_add(MSG_biosgeom_advise);
753: biosdisk = bip;
754: process_menu(MENU_biosonematch, &biosdisk);
755: } else {
756: msg_display(MSG_biosmultmatch);
757: msg_table_add(MSG_biosmultmatch_header);
758: for (i = 0; i < nip->ni_nmatches; i++) {
759: bip = &disklist->dl_biosdisks[
760: nip->ni_biosmatches[i]];
1.18 christos 761: msg_fmt_table_add(MSG_biosmultmatch_row,
762: "%d%d%d%d%d%u%u", i,
1.1 dholland 763: bip->bi_dev, bip->bi_cyl, bip->bi_head,
764: bip->bi_sec, (unsigned)bip->bi_lbasecs,
765: (unsigned)bip->bi_lbasecs/(1000000000/512));
766: }
767: process_menu(MENU_biosmultmatch, &i);
768: if (i == -1)
769: biosdisk = NULL;
770: else
771: biosdisk = &disklist->dl_biosdisks[
772: nip->ni_biosmatches[i]];
773: }
774: }
775: if (biosdisk == NULL) {
1.17 martin 776: *bcyl = cyl;
777: *bhead = head;
778: *bsec = sec;
779: if (nip != NULL)
780: set_bios_geom(parts, bcyl, bhead, bsec);
1.1 dholland 781: } else {
1.15 martin 782: *bcyl = biosdisk->bi_cyl;
783: *bhead = biosdisk->bi_head;
784: *bsec = biosdisk->bi_sec;
1.1 dholland 785: }
1.15 martin 786: return true;
1.1 dholland 787: }
788:
789: static int
1.20.2.7 bouyer 790: mbr_root_above_chs(daddr_t ptstart)
1.1 dholland 791: {
1.20.2.7 bouyer 792: return ptstart + (daddr_t)DEFROOTSIZE * (daddr_t)(MEG / 512)
1.15 martin 793: >= pm->max_chs;
1.1 dholland 794: }
795:
1.15 martin 796: /* returns false if no write-back of parts is required */
797: bool
798: md_mbr_update_check(struct disk_partitions *parts, mbr_info_t *mbri)
1.1 dholland 799: {
800: struct mbr_partition *mbrp;
801: int i, netbsdpart = -1, oldbsdpart = -1, oldbsdcount = 0;
802:
1.15 martin 803: if (pm->no_mbr || pm->no_part)
804: return false;
1.1 dholland 805:
1.15 martin 806: mbrp = &mbri->mbr.mbr_parts[0];
1.1 dholland 807:
808: for (i = 0; i < MBR_PART_COUNT; i++) {
809: if (mbrp[i].mbrp_type == MBR_PTYPE_386BSD) {
810: oldbsdpart = i;
811: oldbsdcount++;
812: } else if (mbrp[i].mbrp_type == MBR_PTYPE_NETBSD)
813: netbsdpart = i;
814: }
815:
816: if (netbsdpart == -1 && oldbsdcount == 1) {
817: mbrp[oldbsdpart].mbrp_type = MBR_PTYPE_NETBSD;
1.15 martin 818: return true;
1.1 dholland 819: }
1.15 martin 820:
821: return false;
1.1 dholland 822: }
823:
824: /*
825: * Read MBR code from a file.
826: * The existing partition table and bootselect configuration is kept.
827: */
828: static int
829: md_read_bootcode(const char *path, struct mbr_sector *mbrs)
830: {
831: int fd;
832: struct stat st;
833: size_t len;
834: struct mbr_sector new_mbr;
835: uint32_t dsn;
836:
837: fd = open(path, O_RDONLY);
838: if (fd < 0)
839: return -1;
840:
841: if (fstat(fd, &st) < 0 || st.st_size != sizeof *mbrs) {
842: close(fd);
843: return -1;
844: }
845:
846: if (read(fd, &new_mbr, sizeof new_mbr) != sizeof new_mbr) {
847: close(fd);
848: return -1;
849: }
850: close(fd);
851:
852: if (new_mbr.mbr_bootsel_magic != htole16(MBR_BS_MAGIC))
853: return -1;
854:
855: if (mbrs->mbr_bootsel_magic == htole16(MBR_BS_MAGIC)) {
856: len = offsetof(struct mbr_sector, mbr_bootsel);
857: } else
858: len = offsetof(struct mbr_sector, mbr_parts);
859:
860: /* Preserve the 'drive serial number' - especially for Vista */
861: dsn = mbrs->mbr_dsn;
862: memcpy(mbrs, &new_mbr, len);
863: mbrs->mbr_dsn = dsn;
864:
865: /* Keep flags from object file - indicate the properties */
866: mbrs->mbr_bootsel.mbrbs_flags = new_mbr.mbr_bootsel.mbrbs_flags;
867: mbrs->mbr_magic = htole16(MBR_MAGIC);
868:
869: return 0;
870: }
871:
872: static unsigned int
873: get_bootmodel(void)
874: {
875: #if defined(__i386__)
876: struct utsname ut;
877: #ifdef DEBUG
878: char *envstr;
879:
880: envstr = getenv("BOOTMODEL");
881: if (envstr != NULL)
882: return atoi(envstr);
883: #endif
884:
885: if (uname(&ut) < 0)
886: ut.version[0] = 0;
887:
888: #if defined(SET_KERNEL_TINY)
889: if (strstr(ut.version, "TINY") != NULL)
890: return SET_KERNEL_TINY;
891: #endif
892: #if defined(SET_KERNEL_PS2)
893: if (strstr(ut.version, "PS2") != NULL)
894: return SET_KERNEL_PS2;
895: #endif
896: #endif
897: return SET_KERNEL_GENERIC;
898: }
899:
900:
901: int
1.19 martin 902: md_pre_mount(struct install_partition_desc *install, size_t ndx)
1.1 dholland 903: {
904: return 0;
905: }
1.15 martin 906:
907: #ifdef HAVE_GPT
908: /*
909: * New GPT partitions have been written, update bootloader or remember
910: * data untill needed in md_post_newfs
911: */
912: bool
913: md_gpt_post_write(struct disk_partitions *parts, part_id root_id,
914: bool root_is_new, part_id efi_id, bool efi_is_new)
915: {
916: struct disk_part_info info;
917:
918: if (root_id != NO_PART) {
919: /* we always update the gpt boot record for now */
920: if (!parts->pscheme->get_part_info(parts, root_id, &info))
921: return false;
922: if (run_program(RUN_SILENT, "gpt biosboot -b %" PRIu64 " %s",
923: info.start, parts->disk) != 0)
924: return false;
925: }
926:
927: return true;
928: }
929: #endif
1.20 martin 930:
931: /*
932: * When we do an UEFI install, we have completely different default
933: * partitions and need to adjust the description at runtime.
934: */
935: void
936: x86_md_part_defaults(struct pm_devs *cur_pm, struct part_usage_info **partsp,
937: size_t *num_usage_infos)
938: {
939: static const struct part_usage_info uefi_boot_part =
940: {
941: .size = BOOT_PART,
942: .type = BOOT_PART_TYPE,
943: .instflags = PUIINST_NEWFS|PUIINST_BOOT,
944: .fs_type = FS_MSDOS, .fs_version = MBR_PTYPE_FAT32L,
945: .flags = PUIFLAG_ADD_OUTER,
946: };
947:
948: struct disk_partitions *parts;
949: struct part_usage_info *new_usage, *boot;
950: struct disk_part_info info;
951: size_t num;
952: part_id pno;
953:
954: if (!uefi_boot)
955: return; /* legacy defaults apply */
956:
957: /*
958: * Insert a UEFI boot partition at the beginning of the array
959: */
960:
961: /* create space for new description */
962: num = *num_usage_infos + 1;
963: new_usage = realloc(*partsp, sizeof(*new_usage)*num);
964: if (new_usage == NULL)
965: return;
966: *partsp = new_usage;
967: *num_usage_infos = num;
968: boot = new_usage;
969: memmove(boot+1, boot, sizeof(*boot)*(num-1));
970: *boot = uefi_boot_part;
971:
972: /*
973: * Check if the UEFI partition already exists
974: */
975: parts = pm->parts;
976: if (parts->parent != NULL)
977: parts = parts->parent;
978: for (pno = 0; pno < parts->num_part; pno++) {
979: if (!parts->pscheme->get_part_info(parts, pno, &info))
980: continue;
981: if (info.nat_type->generic_ptype != boot->type)
982: continue;
983: boot->flags &= ~PUIFLAG_ADD_OUTER;
1.20.2.2 msaitoh 984: boot->flags |= PUIFLG_IS_OUTER|PUIFLG_ADD_INNER;
1.20 martin 985: boot->size = info.size;
986: boot->cur_start = info.start;
987: boot->cur_flags = info.flags;
988: break;
989: }
990: }
991:
992: /* no need to install bootblock if installing for UEFI */
993: bool
994: x86_md_need_bootblock(struct install_partition_desc *install)
995: {
996:
997: return !uefi_boot;
998: }
CVSweb <webmaster@jp.NetBSD.org>