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