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