md.c revision 1.16
1/* $NetBSD: md.c,v 1.16 2019/06/17 14:18:32 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 62static struct biosdisk_info *biosdisk = NULL; 63 64/* prototypes */ 65 66static bool get_bios_info(const char*, struct disk_partitions*, int*, int*, int*); 67static int mbr_root_above_chs(void); 68static int md_read_bootcode(const char *, struct mbr_sector *); 69static unsigned int get_bootmodel(void); 70 71static int conmib[] = {CTL_MACHDEP, CPU_CONSDEV}; 72 73void 74md_init(void) 75{ 76} 77 78void 79md_init_set_status(int flags) 80{ 81 (void)flags; 82 83 /* Default to install same type of kernel as we are running */ 84 set_kernel_set(get_bootmodel()); 85} 86 87bool 88md_get_info(struct install_partition_desc *install) 89{ 90 int bcyl = 0, bhead = 0, bsec = 0; 91 92 if (pm->no_mbr || pm->no_part) 93 return true; 94 95 if (pm->parts == NULL) { 96 97 const struct disk_partitioning_scheme *ps = 98 select_part_scheme(pm, NULL, true, NULL); 99 100 if (!ps) 101 return true; 102 103 struct disk_partitions *parts = 104 (*ps->create_new_for_disk)(pm->diskdev, 105 0, pm->dlsize, pm->dlsize, true); 106 if (!parts) 107 return false; 108 109 pm->parts = parts; 110 if (ps->size_limit > 0 && pm->dlsize > ps->size_limit) 111 pm->dlsize = ps->size_limit; 112 } 113 114 if (get_bios_info(pm->diskdev, pm->parts, &bcyl, &bhead, &bsec) 115 && pm->parts->pscheme->change_disk_geom != NULL) 116 pm->parts->pscheme->change_disk_geom(pm->parts, 117 bcyl, bhead, bsec); 118 else 119 set_default_sizemult(MEG/512); 120 121 /* 122 * If the selected scheme does not need two-stage partitioning 123 * (like GPT), do not bother to edit the outer partitions. 124 */ 125 if (pm->parts->pscheme->secondary_partitions == NULL || 126 pm->parts->pscheme->secondary_scheme == NULL) 127 return true; 128 129 if (pm->no_mbr || pm->no_part) 130 return true; 131 132 return edit_outer_parts(pm->parts); 133} 134 135/* 136 * md back-end code for menu-driven BSD disklabel editor. 137 */ 138bool 139md_make_bsd_partitions(struct install_partition_desc *install) 140{ 141 return make_bsd_partitions(install); 142} 143 144/* 145 * any additional partition validation 146 */ 147bool 148md_check_partitions(struct install_partition_desc *install) 149{ 150 int rval; 151 char *bootxx; 152 153 /* check we have boot code for the root partition type */ 154 bootxx = bootxx_name(install); 155 rval = access(bootxx, R_OK); 156 free(bootxx); 157 if (rval == 0) 158 return true; 159 process_menu(MENU_ok, __UNCONST(MSG_No_Bootcode)); 160 return false; 161} 162 163/* 164 * hook called before writing new disklabel. 165 */ 166bool 167md_pre_disklabel(struct install_partition_desc *install, 168 struct disk_partitions *parts) 169{ 170 171 if (parts->parent == NULL) 172 return true; /* no outer partitions */ 173 174 parts = parts->parent; 175 176 msg_display_subst(MSG_dofdisk, 3, parts->disk, 177 msg_string(parts->pscheme->name), 178 msg_string(parts->pscheme->short_name)); 179 180 /* write edited "MBR" onto disk. */ 181 if (!parts->pscheme->write_to_disk(parts)) { 182 msg_display(MSG_wmbrfail); 183 process_menu(MENU_ok, NULL); 184 return false; 185 } 186 return true; 187} 188 189/* 190 * hook called after writing disklabel to new target disk. 191 */ 192bool 193md_post_disklabel(struct install_partition_desc *install, 194 struct disk_partitions *parts) 195{ 196 return true; 197} 198 199/* 200 * hook called after upgrade() or install() has finished setting 201 * up the target disk but immediately before the user is given the 202 * ``disks are now set up'' message. 203 */ 204int 205md_post_newfs(struct install_partition_desc *install) 206{ 207 int ret; 208 size_t len; 209 char boot_options[1024]; 210 char *bootxx_filename; 211 /* 212 * XXX - this code retains a lot of cruft from when we went 213 * to great pains to exclude installboot from the ramdisk 214 * for size reasons and should be rewritten. 215 */ 216 static const char *consoles[]={ 217 "pc", /* CONSDEV_PC */ 218 "com0", /* CONSDEV_COM0 */ 219 "com1", /* CONSDEV_COM1 */ 220 "com2", /* CONSDEV_COM2 */ 221 "com3", /* CONSDEV_COM3 */ 222 "com0kbd", /* CONSDEV_COM0KBD */ 223 "com1kbd", /* CONSDEV_COM1KBD */ 224 "com2kbd", /* CONSDEV_COM2KBD */ 225 "com3kbd" /* CONSDEV_COM3KBD */ }; 226 static struct x86_boot_params boottype = 227 {sizeof boottype, 0, 5, 0, 9600, { '\0' }, "", 0}; 228 struct termios t; 229 dev_t condev; 230 231 if (pm == NULL || !pm->no_part) { 232 /* 233 * Get console device, should either be ttyE0 or tty0n. 234 * Too hard to double check, so just 'know' the device numbers. 235 */ 236 len = sizeof condev; 237 if (sysctl(conmib, __arraycount(conmib), &condev, &len, NULL, 0) != -1 238 && (condev & ~3) == 0x800) { 239 /* Motherboard serial port */ 240 boottype.bp_consdev = (condev & 3) + 1; 241 /* Defaulting the baud rate to that of stdin should suffice */ 242 if (tcgetattr(0, &t) != -1) 243 boottype.bp_conspeed = t.c_ispeed; 244 } 245 246 process_menu(MENU_getboottype, &boottype); 247 msg_display(MSG_dobootblks, pm->diskdev); 248 if (boottype.bp_consdev == ~0u) 249 /* Use existing bootblocks */ 250 return 0; 251 } 252 253 ret = cp_to_target("/usr/mdec/boot", "/boot"); 254 if (ret) 255 return ret; 256 if (pm && pm->no_part) 257 return 0; 258 259 bootxx_filename = bootxx_name(install); 260 if (bootxx_filename != NULL) { 261 char rdev[PATH_MAX]; 262 263 install->infos[0].parts->pscheme->get_part_device( 264 install->infos[0].parts, install->infos[0].cur_part_id, 265 rdev, sizeof rdev, NULL, raw_dev_name, true); 266 267 snprintf(boot_options, sizeof boot_options, 268 "console=%s,speed=%u", consoles[boottype.bp_consdev], 269 boottype.bp_conspeed); 270 ret = run_program(RUN_DISPLAY, 271 "/usr/sbin/installboot -o %s %s %s", 272 boot_options, rdev, bootxx_filename); 273 free(bootxx_filename); 274 } else { 275 ret = -1; 276 } 277 278 if (ret != 0) 279 process_menu(MENU_ok, 280 __UNCONST("Warning: disk is probably not bootable")); 281 282 return ret; 283} 284 285int 286md_post_extract(struct install_partition_desc *install) 287{ 288 return 0; 289} 290 291void 292md_cleanup_install(struct install_partition_desc *install) 293{ 294 size_t len; 295 dev_t condev; 296 297#ifndef DEBUG 298 enable_rc_conf(); 299 add_rc_conf("wscons=YES\n"); 300 301# if defined(__i386__) && defined(SET_KERNEL_TINY) 302 /* 303 * For GENERIC_TINY, do not enable any extra screens or wsmux. 304 * Otherwise, run getty on 4 VTs. 305 */ 306 if (get_kernel_set() == SET_KERNEL_TINY) 307 run_program(RUN_CHROOT, 308 "sed -an -e '/^screen/s/^/#/;/^mux/s/^/#/;" 309 "H;$!d;g;w /etc/wscons.conf' /etc/wscons.conf"); 310 else 311# endif 312 run_program(RUN_CHROOT, 313 "sed -an -e '/^ttyE[1-9]/s/off/on/;" 314 "H;$!d;g;w /etc/ttys' /etc/ttys"); 315 316#endif 317 318 /* 319 * Get console device, should either be ttyE0 or tty0n. 320 * Too hard to double check, so just 'know' the device numbers. 321 */ 322 len = sizeof condev; 323 if (sysctl(conmib, __arraycount(conmib), &condev, &len, NULL, 0) != -1 324 && (condev & ~3) != 0x800) { 325 326 /* 327 * Current console is not com*, assume ttyE*. 328 * Modify /etc/ttys to use wsvt25 for all ports. 329 */ 330 331 run_program(RUN_CHROOT, 332 "sed -an -e 's/vt100/wsvt25/g;" 333 "H;$!d;g;w /etc/ttys' /etc/ttys"); 334 } 335} 336 337int 338md_pre_update(struct install_partition_desc *install) 339{ 340 return 1; 341} 342 343/* Upgrade support */ 344int 345md_update(struct install_partition_desc *install) 346{ 347 md_post_newfs(install); 348 return 1; 349} 350 351int 352md_check_mbr(struct disk_partitions *parts, mbr_info_t *mbri, bool quiet) 353{ 354 mbr_info_t *ext; 355 struct mbr_partition *p; 356 const char *bootcode; 357 int i, names, fl, ofl; 358#define ACTIVE_FOUND 0x0100 359#define NETBSD_ACTIVE 0x0200 360#define NETBSD_NAMED 0x0400 361#define ACTIVE_NAMED 0x0800 362 363 root_limit = 0; 364 if (biosdisk != NULL && (biosdisk->bi_flags & BIFLAG_EXTINT13) == 0) { 365 if (mbr_root_above_chs()) { 366 if (quiet) 367 return 0; 368 msg_display(MSG_partabovechs); 369 if (!ask_noyes(NULL)) 370 return 1; 371 /* The user is shooting themselves in the foot here...*/ 372 } else { 373 if (parts->pscheme->size_limit) 374 root_limit = min(parts->pscheme->size_limit, 375 parts->disk_size); 376 else 377 root_limit = parts->disk_size; 378 } 379 } 380 381 /* 382 * Ensure the install partition (at sector pm->ptstart) and the active 383 * partition are bootable. 384 * Determine whether the bootselect code is needed. 385 * Note that MBR_BS_NEWMBR is always set, so we ignore it! 386 */ 387 fl = 0; 388 names = 0; 389 for (ext = mbri; ext != NULL; ext = ext->extended) { 390 p = ext->mbr.mbr_parts; 391 for (i = 0; i < MBR_PART_COUNT; p++, i++) { 392 if (p->mbrp_flag == MBR_PFLAG_ACTIVE) { 393 fl |= ACTIVE_FOUND; 394 if (ext->sector + p->mbrp_start == pm->ptstart) 395 fl |= NETBSD_ACTIVE; 396 } 397 if (ext->mbrb.mbrbs_nametab[i][0] == 0) { 398 /* No bootmenu label... */ 399 if (ext->sector == 0) 400 continue; 401 if (ext->sector + p->mbrp_start == pm->ptstart) 402 /* 403 * Have installed into an extended ptn 404 * force name & bootsel... 405 */ 406 names++; 407 continue; 408 } 409 /* Partition has a bootmenu label... */ 410 if (ext->sector != 0) 411 fl |= MBR_BS_EXTLBA; 412 if (ext->sector + p->mbrp_start == pm->ptstart) 413 fl |= NETBSD_NAMED; 414 else if (p->mbrp_flag == MBR_PFLAG_ACTIVE) 415 fl |= ACTIVE_NAMED; 416 else 417 names++; 418 } 419 } 420 if (!(fl & ACTIVE_FOUND)) 421 fl |= NETBSD_ACTIVE; 422 if (fl & NETBSD_NAMED && fl & NETBSD_ACTIVE) 423 fl |= ACTIVE_NAMED; 424 425 if ((names > 0 || !(fl & NETBSD_ACTIVE)) && 426 (!(fl & NETBSD_NAMED) || !(fl & ACTIVE_NAMED))) { 427 /* 428 * There appear to be multiple bootable partitions, but they 429 * don't all have bootmenu texts. 430 */ 431 if (quiet) 432 return 0; 433 434 msg_display(MSG_missing_bootmenu_text); 435 if (ask_yesno(NULL)) 436 return 1; 437 } 438 439 if ((fl & MBR_BS_EXTLBA) && 440 (biosdisk == NULL || !(biosdisk->bi_flags & BIFLAG_EXTINT13))) { 441 /* Need unsupported LBA reads to read boot sectors */ 442 if (quiet) 443 return 0; 444 445 msg_display(MSG_no_extended_bootmenu); 446 if (!ask_noyes(NULL)) 447 return 1; 448 } 449 450 /* Sort out the name of the mbr code we need */ 451 if (names > 0 || fl & (NETBSD_NAMED | ACTIVE_NAMED)) { 452 /* Need bootselect code */ 453 fl |= MBR_BS_ACTIVE; 454 bootcode = fl & MBR_BS_EXTLBA ? _PATH_BOOTEXT : _PATH_BOOTSEL; 455 } else 456 bootcode = _PATH_MBR; 457 458 fl &= MBR_BS_ACTIVE | MBR_BS_EXTLBA; 459 460 /* Look at what is installed */ 461 ofl = mbri->mbrb.mbrbs_flags; 462 if (ofl == 0) { 463 /* Check there is some bootcode at all... */ 464 if (mbri->mbr.mbr_magic != htole16(MBR_MAGIC) || 465 mbri->mbr.mbr_jmpboot[0] == 0 || 466 mbr_root_above_chs()) 467 /* Existing won't do, force update */ 468 fl |= MBR_BS_NEWMBR; 469 } 470 ofl = mbri->oflags & (MBR_BS_ACTIVE | MBR_BS_EXTLBA); 471 472 if (!quiet) { 473 if (fl & ~ofl || (fl == 0 && ofl & MBR_BS_ACTIVE)) { 474 /* Existing boot code isn't the right one... */ 475 if (fl & MBR_BS_ACTIVE) 476 msg_display(MSG_installbootsel); 477 else 478 msg_display(MSG_installmbr); 479 } else 480 /* Existing code would (probably) be ok */ 481 msg_display(MSG_updatembr); 482 483 if (!ask_yesno(NULL)) 484 /* User doesn't want to update mbr code */ 485 return 2; 486 } 487 488 if (md_read_bootcode(bootcode, &mbri->mbr) == 0) 489 /* update suceeded - to memory copy */ 490 return 2; 491 492 /* This shouldn't happen since the files are in the floppy fs... */ 493 msg_display("Can't find %s", bootcode); 494 return ask_reedit(parts); 495} 496 497bool 498md_parts_use_wholedisk(struct disk_partitions *parts) 499{ 500 return parts_use_wholedisk(parts, 0, NULL); 501} 502 503static bool 504get_bios_info(const char *dev, struct disk_partitions *parts, int *bcyl, 505 int *bhead, int *bsec) 506{ 507 static struct disklist *disklist = NULL; 508 static int mib[2] = {CTL_MACHDEP, CPU_DISKINFO}; 509 int i; 510 size_t len; 511 struct biosdisk_info *bip; 512 struct nativedisk_info *nip = NULL, *nat; 513 int cyl, head, sec; 514 515 if (disklist == NULL) { 516 if (sysctl(mib, 2, NULL, &len, NULL, 0) < 0) 517 goto nogeom; 518 disklist = malloc(len); 519 if (disklist == NULL) { 520 fprintf(stderr, "Out of memory\n"); 521 return false; 522 } 523 sysctl(mib, 2, disklist, &len, NULL, 0); 524 } 525 526 for (i = 0; i < disklist->dl_nnativedisks; i++) { 527 nat = &disklist->dl_nativedisks[i]; 528 if (!strcmp(dev, nat->ni_devname)) { 529 nip = nat; 530 break; 531 } 532 } 533 if (nip == NULL || nip->ni_nmatches == 0) { 534nogeom: 535 if (nip != NULL) 536 msg_display(MSG_nobiosgeom, pm->dlcyl, pm->dlhead, pm->dlsec); 537 if (guess_biosgeom_from_parts(parts, &cyl, &head, &sec) >= 0 538 && nip != NULL) 539 msg_display_add(MSG_biosguess, cyl, head, sec); 540 biosdisk = NULL; 541 } else { 542 guess_biosgeom_from_parts(parts, &cyl, &head, &sec); 543 if (nip->ni_nmatches == 1) { 544 bip = &disklist->dl_biosdisks[nip->ni_biosmatches[0]]; 545 msg_display(MSG_onebiosmatch); 546 msg_table_add(MSG_onebiosmatch_header); 547 msg_table_add(MSG_onebiosmatch_row, bip->bi_dev, 548 bip->bi_cyl, bip->bi_head, bip->bi_sec, 549 (unsigned)bip->bi_lbasecs, 550 (unsigned)(bip->bi_lbasecs / (1000000000 / 512))); 551 msg_display_add(MSG_biosgeom_advise); 552 biosdisk = bip; 553 process_menu(MENU_biosonematch, &biosdisk); 554 } else { 555 msg_display(MSG_biosmultmatch); 556 msg_table_add(MSG_biosmultmatch_header); 557 for (i = 0; i < nip->ni_nmatches; i++) { 558 bip = &disklist->dl_biosdisks[ 559 nip->ni_biosmatches[i]]; 560 msg_table_add(MSG_biosmultmatch_row, i, 561 bip->bi_dev, bip->bi_cyl, bip->bi_head, 562 bip->bi_sec, (unsigned)bip->bi_lbasecs, 563 (unsigned)bip->bi_lbasecs/(1000000000/512)); 564 } 565 process_menu(MENU_biosmultmatch, &i); 566 if (i == -1) 567 biosdisk = NULL; 568 else 569 biosdisk = &disklist->dl_biosdisks[ 570 nip->ni_biosmatches[i]]; 571 } 572 } 573 if (biosdisk == NULL) { 574 if (nip != NULL) { 575 set_bios_geom(parts, cyl, head, sec); 576 } else { 577 *bcyl = cyl; 578 *bhead = head; 579 *bsec = sec; 580 } 581 } else { 582 *bcyl = biosdisk->bi_cyl; 583 *bhead = biosdisk->bi_head; 584 *bsec = biosdisk->bi_sec; 585 } 586 return true; 587} 588 589static int 590mbr_root_above_chs(void) 591{ 592 return pm->ptstart + (daddr_t)DEFROOTSIZE * (daddr_t)(MEG / 512) 593 >= pm->max_chs; 594} 595 596/* returns false if no write-back of parts is required */ 597bool 598md_mbr_update_check(struct disk_partitions *parts, mbr_info_t *mbri) 599{ 600 struct mbr_partition *mbrp; 601 int i, netbsdpart = -1, oldbsdpart = -1, oldbsdcount = 0; 602 603 if (pm->no_mbr || pm->no_part) 604 return false; 605 606 mbrp = &mbri->mbr.mbr_parts[0]; 607 608 for (i = 0; i < MBR_PART_COUNT; i++) { 609 if (mbrp[i].mbrp_type == MBR_PTYPE_386BSD) { 610 oldbsdpart = i; 611 oldbsdcount++; 612 } else if (mbrp[i].mbrp_type == MBR_PTYPE_NETBSD) 613 netbsdpart = i; 614 } 615 616 if (netbsdpart == -1 && oldbsdcount == 1) { 617 mbrp[oldbsdpart].mbrp_type = MBR_PTYPE_NETBSD; 618 return true; 619 } 620 621 return false; 622} 623 624/* 625 * Read MBR code from a file. 626 * The existing partition table and bootselect configuration is kept. 627 */ 628static int 629md_read_bootcode(const char *path, struct mbr_sector *mbrs) 630{ 631 int fd; 632 struct stat st; 633 size_t len; 634 struct mbr_sector new_mbr; 635 uint32_t dsn; 636 637 fd = open(path, O_RDONLY); 638 if (fd < 0) 639 return -1; 640 641 if (fstat(fd, &st) < 0 || st.st_size != sizeof *mbrs) { 642 close(fd); 643 return -1; 644 } 645 646 if (read(fd, &new_mbr, sizeof new_mbr) != sizeof new_mbr) { 647 close(fd); 648 return -1; 649 } 650 close(fd); 651 652 if (new_mbr.mbr_bootsel_magic != htole16(MBR_BS_MAGIC)) 653 return -1; 654 655 if (mbrs->mbr_bootsel_magic == htole16(MBR_BS_MAGIC)) { 656 len = offsetof(struct mbr_sector, mbr_bootsel); 657 } else 658 len = offsetof(struct mbr_sector, mbr_parts); 659 660 /* Preserve the 'drive serial number' - especially for Vista */ 661 dsn = mbrs->mbr_dsn; 662 memcpy(mbrs, &new_mbr, len); 663 mbrs->mbr_dsn = dsn; 664 665 /* Keep flags from object file - indicate the properties */ 666 mbrs->mbr_bootsel.mbrbs_flags = new_mbr.mbr_bootsel.mbrbs_flags; 667 mbrs->mbr_magic = htole16(MBR_MAGIC); 668 669 return 0; 670} 671 672static unsigned int 673get_bootmodel(void) 674{ 675#if defined(__i386__) 676 struct utsname ut; 677#ifdef DEBUG 678 char *envstr; 679 680 envstr = getenv("BOOTMODEL"); 681 if (envstr != NULL) 682 return atoi(envstr); 683#endif 684 685 if (uname(&ut) < 0) 686 ut.version[0] = 0; 687 688#if defined(SET_KERNEL_TINY) 689 if (strstr(ut.version, "TINY") != NULL) 690 return SET_KERNEL_TINY; 691#endif 692#if defined(SET_KERNEL_PS2) 693 if (strstr(ut.version, "PS2") != NULL) 694 return SET_KERNEL_PS2; 695#endif 696#endif 697 return SET_KERNEL_GENERIC; 698} 699 700 701int 702md_pre_mount(struct install_partition_desc *install) 703{ 704 return 0; 705} 706 707#ifdef HAVE_GPT 708/* 709 * New GPT partitions have been written, update bootloader or remember 710 * data untill needed in md_post_newfs 711 */ 712bool 713md_gpt_post_write(struct disk_partitions *parts, part_id root_id, 714 bool root_is_new, part_id efi_id, bool efi_is_new) 715{ 716 struct disk_part_info info; 717 718 assert(efi_id == NO_PART); /* XXX EFI support still missing */ 719 720 if (root_id != NO_PART) { 721 /* we always update the gpt boot record for now */ 722 if (!parts->pscheme->get_part_info(parts, root_id, &info)) 723 return false; 724 if (run_program(RUN_SILENT, "gpt biosboot -b %" PRIu64 " %s", 725 info.start, parts->disk) != 0) 726 return false; 727 } 728 729 return true; 730} 731#endif 732