1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright 2012 Milan Jurik. All rights reserved. 24 * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 25 */ 26 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <libgen.h> 30 #include <malloc.h> 31 #include <string.h> 32 #include <fcntl.h> 33 #include <unistd.h> 34 #include <strings.h> 35 #include <libintl.h> 36 #include <locale.h> 37 #include <errno.h> 38 #include <libfdisk.h> 39 #include <stdarg.h> 40 #include <assert.h> 41 42 #include <sys/mount.h> 43 #include <sys/mnttab.h> 44 #include <sys/dktp/fdisk.h> 45 #include <sys/dkio.h> 46 #include <sys/vtoc.h> 47 #include <sys/types.h> 48 #include <sys/stat.h> 49 #include <sys/multiboot.h> 50 #include <sys/sysmacros.h> 51 #include <sys/efi_partition.h> 52 53 #include <libnvpair.h> 54 #include <libfstyp.h> 55 56 #include "message.h" 57 #include "installgrub.h" 58 #include "./../common/bblk_einfo.h" 59 #include "./../common/boot_utils.h" 60 #include "./../common/mboot_extra.h" 61 62 #ifndef TEXT_DOMAIN 63 #define TEXT_DOMAIN "SUNW_OST_OSCMD" 64 #endif 65 66 /* 67 * Variables to track installgrub desired mode of operation. 68 * 'nowrite' and 'boot_debug' come from boot_common.h. 69 */ 70 static boolean_t write_mbr = B_FALSE; 71 static boolean_t force_mbr = B_FALSE; 72 static boolean_t force_update = B_FALSE; 73 static boolean_t do_getinfo = B_FALSE; 74 static boolean_t do_version = B_FALSE; 75 static boolean_t do_mirror_bblk = B_FALSE; 76 static boolean_t strip = B_FALSE; 77 static boolean_t verbose_dump = B_FALSE; 78 79 /* Installing the bootblock is the default operation. */ 80 static boolean_t do_install = B_TRUE; 81 82 /* Versioning string, if present. */ 83 static char *update_str; 84 85 /* 86 * Temporary buffer to store the first 32K of data looking for a multiboot 87 * signature. 88 */ 89 char mboot_scan[MBOOT_SCAN_SIZE]; 90 91 /* Function prototypes. */ 92 static void check_options(char *); 93 static int handle_install(char *, char **); 94 static int handle_mirror(char *, char **); 95 static int handle_getinfo(char *, char **); 96 static int commit_to_disk(ig_data_t *, char *); 97 static int init_device(ig_device_t *, char *path); 98 static void cleanup_device(ig_device_t *); 99 static void cleanup_stage2(ig_stage2_t *); 100 static int get_start_sector(ig_device_t *); 101 static int get_disk_fd(ig_device_t *device); 102 static int get_raw_partition_fd(ig_device_t *); 103 static char *get_raw_partition_path(ig_device_t *); 104 static boolean_t gather_stage2_from_dev(ig_data_t *); 105 static int propagate_bootblock(ig_data_t *, ig_data_t *, char *); 106 static int find_x86_bootpar(struct mboot *, int *, uint32_t *); 107 static int copy_stage2_to_pcfs(ig_data_t *); 108 static int write_stage2(ig_data_t *); 109 static int write_stage1(ig_data_t *); 110 static void usage(char *); 111 static int read_stage1_from_file(char *, ig_data_t *); 112 static int read_stage2_from_file(char *, ig_data_t *); 113 static int read_stage1_from_disk(int, char *); 114 static int read_stage2_from_disk(int, ig_stage2_t *, int); 115 static int prepare_stage1(ig_data_t *); 116 static int prepare_stage2(ig_data_t *, char *); 117 static void prepare_fake_multiboot(ig_stage2_t *); 118 static void add_stage2_einfo(ig_stage2_t *, char *updt_str); 119 static boolean_t is_update_necessary(ig_data_t *, char *); 120 121 extern int read_stage2_blocklist(int, unsigned int *); 122 123 int 124 main(int argc, char *argv[]) 125 { 126 int opt; 127 int params = 3; 128 int ret; 129 char **handle_args; 130 char *progname; 131 132 (void) setlocale(LC_ALL, ""); 133 (void) textdomain(TEXT_DOMAIN); 134 135 /* 136 * retro-compatibility: installing the bootblock is the default 137 * and there is no switch for it. 138 */ 139 do_install = B_TRUE; 140 141 while ((opt = getopt(argc, argv, "dVMFfmneiu:")) != EOF) { 142 switch (opt) { 143 case 'm': 144 write_mbr = B_TRUE; 145 break; 146 case 'n': 147 nowrite = B_TRUE; 148 break; 149 case 'f': 150 force_mbr = B_TRUE; 151 break; 152 case 'i': 153 do_getinfo = B_TRUE; 154 do_install = B_FALSE; 155 params = 1; 156 break; 157 case 'V': 158 verbose_dump = B_TRUE; 159 break; 160 case 'd': 161 boot_debug = B_TRUE; 162 break; 163 case 'F': 164 force_update = B_TRUE; 165 break; 166 case 'e': 167 strip = B_TRUE; 168 break; 169 case 'M': 170 do_mirror_bblk = B_TRUE; 171 do_install = B_FALSE; 172 params = 2; 173 break; 174 case 'u': 175 do_version = B_TRUE; 176 177 update_str = malloc(strlen(optarg) + 1); 178 if (update_str == NULL) { 179 (void) fprintf(stderr, gettext("Unable to " 180 "allocate memory\n")); 181 exit(BC_ERROR); 182 } 183 (void) strlcpy(update_str, optarg, strlen(optarg) + 1); 184 break; 185 default: 186 /* fall through to process non-optional args */ 187 break; 188 } 189 } 190 191 /* check arguments */ 192 if (argc != optind + params) { 193 usage(argv[0]); 194 exit(BC_ERROR); 195 } 196 197 /* 198 * clean up options (and bail out if an unrecoverable combination is 199 * requested. 200 */ 201 progname = argv[0]; 202 check_options(progname); 203 handle_args = argv + optind; 204 205 if (nowrite) 206 (void) fprintf(stdout, DRY_RUN); 207 208 if (do_getinfo) { 209 ret = handle_getinfo(progname, handle_args); 210 } else if (do_mirror_bblk) { 211 ret = handle_mirror(progname, handle_args); 212 } else { 213 ret = handle_install(progname, handle_args); 214 } 215 return (ret); 216 } 217 218 #define MEANINGLESS_OPT gettext("%s specified but meaningless, ignoring\n") 219 static void 220 check_options(char *progname) 221 { 222 if (do_getinfo && do_mirror_bblk) { 223 (void) fprintf(stderr, gettext("Only one of -M and -i can be " 224 "specified at the same time\n")); 225 usage(progname); 226 exit(BC_ERROR); 227 } 228 229 if (do_mirror_bblk) { 230 /* 231 * -u and -F may actually reflect a user intent that is not 232 * correct with this command (mirror can be interpreted 233 * "similar" to install. Emit a message and continue. 234 * -e and -V have no meaning, be quiet here and only report the 235 * incongruence if a debug output is requested. 236 */ 237 if (do_version) { 238 (void) fprintf(stderr, MEANINGLESS_OPT, "-u"); 239 do_version = B_FALSE; 240 } 241 if (force_update) { 242 (void) fprintf(stderr, MEANINGLESS_OPT, "-F"); 243 force_update = B_FALSE; 244 } 245 if (strip || verbose_dump) { 246 BOOT_DEBUG(MEANINGLESS_OPT, "-e|-V"); 247 strip = B_FALSE; 248 verbose_dump = B_FALSE; 249 } 250 } 251 252 if (do_getinfo) { 253 if (write_mbr || force_mbr || do_version || force_update) { 254 BOOT_DEBUG(MEANINGLESS_OPT, "-m|-f|-u|-F"); 255 write_mbr = force_mbr = do_version = B_FALSE; 256 force_update = B_FALSE; 257 } 258 } 259 } 260 261 /* 262 * Install a new stage1/stage2 pair on the specified device. handle_install() 263 * expects argv to contain 3 parameters (the path to stage1, the path to stage2, 264 * the target device). 265 * 266 * Returns: BC_SUCCESS - if the installation is successful 267 * BC_ERROR - if the installation failed 268 * BC_NOUPDT - if no installation was performed because the GRUB 269 * version currently installed is more recent than the 270 * supplied one. 271 * 272 */ 273 static int 274 handle_install(char *progname, char **argv) 275 { 276 ig_data_t install_data; 277 char *stage1_path = NULL; 278 char *stage2_path = NULL; 279 char *device_path = NULL; 280 int ret = BC_ERROR; 281 282 stage1_path = strdup(argv[0]); 283 stage2_path = strdup(argv[1]); 284 device_path = strdup(argv[2]); 285 286 bzero(&install_data, sizeof (ig_data_t)); 287 288 if (!stage1_path || !stage2_path || !device_path) { 289 (void) fprintf(stderr, gettext("Missing parameter")); 290 usage(progname); 291 goto out; 292 } 293 294 BOOT_DEBUG("stage1 path: %s, stage2 path: %s, device: %s\n", 295 stage1_path, stage2_path, device_path); 296 297 if (init_device(&install_data.device, device_path) != BC_SUCCESS) { 298 (void) fprintf(stderr, gettext("Unable to gather device " 299 "information for %s\n"), device_path); 300 goto out; 301 } 302 303 /* read in stage1 and stage2. */ 304 if (read_stage1_from_file(stage1_path, &install_data) != BC_SUCCESS) { 305 (void) fprintf(stderr, gettext("Error opening %s\n"), 306 stage1_path); 307 goto out_dev; 308 } 309 310 if (read_stage2_from_file(stage2_path, &install_data) != BC_SUCCESS) { 311 (void) fprintf(stderr, gettext("Error opening %s\n"), 312 stage2_path); 313 goto out_dev; 314 } 315 316 /* We do not support versioning on PCFS. */ 317 if (is_bootpar(install_data.device.type) && do_version) 318 do_version = B_FALSE; 319 320 /* 321 * is_update_necessary() will take care of checking if versioning and/or 322 * forcing the update have been specified. It will also emit a warning 323 * if a non-versioned update is attempted over a versioned bootblock. 324 */ 325 if (!is_update_necessary(&install_data, update_str)) { 326 (void) fprintf(stderr, gettext("GRUB version installed " 327 "on %s is more recent or identical\n" 328 "Use -F to override or install without the -u option\n"), 329 device_path); 330 ret = BC_NOUPDT; 331 goto out_dev; 332 } 333 /* 334 * We get here if: 335 * - the installed GRUB version is older than the one about to be 336 * installed. 337 * - no versioning string has been passed through the command line. 338 * - a forced update is requested (-F). 339 */ 340 BOOT_DEBUG("Ready to commit to disk\n"); 341 ret = commit_to_disk(&install_data, update_str); 342 343 out_dev: 344 cleanup_device(&install_data.device); 345 out: 346 free(stage1_path); 347 free(stage2_path); 348 free(device_path); 349 return (ret); 350 } 351 352 /* 353 * Retrieves from a device the extended information (einfo) associated to the 354 * installed stage2. 355 * Expects one parameter, the device path, in the form: /dev/rdsk/c?[t?]d?s0. 356 * Returns: 357 * - BC_SUCCESS (and prints out einfo contents depending on 'flags') 358 * - BC_ERROR (on error) 359 * - BC_NOEINFO (no extended information available) 360 */ 361 static int 362 handle_getinfo(char *progname, char **argv) 363 { 364 ig_data_t data; 365 ig_stage2_t *stage2 = &data.stage2; 366 ig_device_t *device = &data.device; 367 bblk_einfo_t *einfo; 368 uint8_t flags = 0; 369 uint32_t size; 370 char *device_path; 371 int retval = BC_ERROR; 372 int ret; 373 374 device_path = strdup(argv[0]); 375 if (!device_path) { 376 (void) fprintf(stderr, gettext("Missing parameter")); 377 usage(progname); 378 goto out; 379 } 380 381 bzero(&data, sizeof (ig_data_t)); 382 BOOT_DEBUG("device path: %s\n", device_path); 383 384 if (init_device(device, device_path) != BC_SUCCESS) { 385 (void) fprintf(stderr, gettext("Unable to gather device " 386 "information for %s\n"), device_path); 387 goto out_dev; 388 } 389 390 if (is_bootpar(device->type)) { 391 (void) fprintf(stderr, gettext("Versioning not supported on " 392 "PCFS\n")); 393 goto out_dev; 394 } 395 396 ret = read_stage2_from_disk(device->part_fd, stage2, device->type); 397 if (ret == BC_ERROR) { 398 (void) fprintf(stderr, gettext("Error reading stage2 from " 399 "%s\n"), device_path); 400 goto out_dev; 401 } 402 403 if (ret == BC_NOEXTRA) { 404 (void) fprintf(stdout, gettext("No multiboot header found on " 405 "%s, unable to locate extra information area\n"), 406 device_path); 407 retval = BC_NOEINFO; 408 goto out_dev; 409 } 410 411 einfo = find_einfo(stage2->extra, stage2->extra_size); 412 if (einfo == NULL) { 413 retval = BC_NOEINFO; 414 (void) fprintf(stderr, gettext("No extended information " 415 "found\n")); 416 goto out_dev; 417 } 418 419 /* Print the extended information. */ 420 if (strip) 421 flags |= EINFO_EASY_PARSE; 422 if (verbose_dump) 423 flags |= EINFO_PRINT_HEADER; 424 425 size = stage2->buf_size - P2ROUNDUP(stage2->file_size, 8); 426 print_einfo(flags, einfo, size); 427 retval = BC_SUCCESS; 428 429 out_dev: 430 cleanup_device(&data.device); 431 out: 432 free(device_path); 433 return (retval); 434 } 435 436 /* 437 * Attempt to mirror (propagate) the current stage2 over the attaching disk. 438 * 439 * Returns: 440 * - BC_SUCCESS (a successful propagation happened) 441 * - BC_ERROR (an error occurred) 442 * - BC_NOEXTRA (it is not possible to dump the current bootblock since 443 * there is no multiboot information) 444 */ 445 static int 446 handle_mirror(char *progname, char **argv) 447 { 448 ig_data_t curr_data; 449 ig_data_t attach_data; 450 ig_device_t *curr_device = &curr_data.device; 451 ig_device_t *attach_device = &attach_data.device; 452 ig_stage2_t *stage2_curr = &curr_data.stage2; 453 ig_stage2_t *stage2_attach = &attach_data.stage2; 454 bblk_einfo_t *einfo_curr = NULL; 455 char *curr_device_path; 456 char *attach_device_path; 457 char *updt_str = NULL; 458 int retval = BC_ERROR; 459 int ret; 460 461 curr_device_path = strdup(argv[0]); 462 attach_device_path = strdup(argv[1]); 463 464 if (!curr_device_path || !attach_device_path) { 465 (void) fprintf(stderr, gettext("Missing parameter")); 466 usage(progname); 467 goto out; 468 } 469 BOOT_DEBUG("Current device path is: %s, attaching device path is: " 470 " %s\n", curr_device_path, attach_device_path); 471 472 bzero(&curr_data, sizeof (ig_data_t)); 473 bzero(&attach_data, sizeof (ig_data_t)); 474 475 if (init_device(curr_device, curr_device_path) != BC_SUCCESS) { 476 (void) fprintf(stderr, gettext("Unable to gather device " 477 "information for %s (current device)\n"), curr_device_path); 478 goto out_currdev; 479 } 480 481 if (init_device(attach_device, attach_device_path) != BC_SUCCESS) { 482 (void) fprintf(stderr, gettext("Unable to gather device " 483 "information for %s (attaching device)\n"), 484 attach_device_path); 485 goto out_devs; 486 } 487 488 if (is_bootpar(curr_device->type) || is_bootpar(attach_device->type)) { 489 (void) fprintf(stderr, gettext("boot block mirroring is not " 490 "supported on PCFS\n")); 491 goto out_devs; 492 } 493 494 ret = read_stage2_from_disk(curr_device->part_fd, stage2_curr, 495 curr_device->type); 496 if (ret == BC_ERROR) { 497 BOOT_DEBUG("Error reading first stage2 blocks from %s\n", 498 curr_device->path); 499 retval = BC_ERROR; 500 goto out_devs; 501 } 502 503 if (ret == BC_NOEXTRA) { 504 BOOT_DEBUG("No multiboot header found on %s, unable to grab " 505 "stage2\n", curr_device->path); 506 retval = BC_NOEXTRA; 507 goto out_devs; 508 } 509 510 einfo_curr = find_einfo(stage2_curr->extra, stage2_curr->extra_size); 511 if (einfo_curr != NULL) 512 updt_str = einfo_get_string(einfo_curr); 513 514 write_mbr = B_TRUE; 515 force_mbr = B_TRUE; 516 retval = propagate_bootblock(&curr_data, &attach_data, updt_str); 517 cleanup_stage2(stage2_curr); 518 cleanup_stage2(stage2_attach); 519 520 out_devs: 521 cleanup_device(attach_device); 522 out_currdev: 523 cleanup_device(curr_device); 524 out: 525 free(curr_device_path); 526 free(attach_device_path); 527 return (retval); 528 } 529 530 static int 531 commit_to_disk(ig_data_t *install, char *updt_str) 532 { 533 assert(install != NULL); 534 /* 535 * vanilla stage1 and stage2 need to be updated at runtime. 536 * Update stage2 before stage1 because stage1 needs to know the first 537 * sector stage2 will be written to. 538 */ 539 if (prepare_stage2(install, updt_str) != BC_SUCCESS) { 540 (void) fprintf(stderr, gettext("Error building stage2\n")); 541 return (BC_ERROR); 542 } 543 if (prepare_stage1(install) != BC_SUCCESS) { 544 (void) fprintf(stderr, gettext("Error building stage1\n")); 545 return (BC_ERROR); 546 } 547 548 /* Write stage2 out to disk. */ 549 if (write_stage2(install) != BC_SUCCESS) { 550 (void) fprintf(stderr, gettext("Error writing stage2 to " 551 "disk\n")); 552 return (BC_ERROR); 553 } 554 555 /* Write stage1 to disk and, if requested, to the MBR. */ 556 if (write_stage1(install) != BC_SUCCESS) { 557 (void) fprintf(stderr, gettext("Error writing stage1 to " 558 "disk\n")); 559 return (BC_ERROR); 560 } 561 562 return (BC_SUCCESS); 563 } 564 565 /* 566 * Propagate the bootblock on the source disk to the destination disk and 567 * version it with 'updt_str' in the process. Since we cannot trust any data 568 * on the attaching disk, we do not perform any specific check on a potential 569 * target extended information structure and we just blindly update. 570 */ 571 static int 572 propagate_bootblock(ig_data_t *source, ig_data_t *target, char *updt_str) 573 { 574 ig_device_t *src_device = &source->device; 575 ig_device_t *dest_device = &target->device; 576 ig_stage2_t *src_stage2 = &source->stage2; 577 ig_stage2_t *dest_stage2 = &target->stage2; 578 uint32_t buf_size; 579 int retval; 580 581 assert(source != NULL); 582 assert(target != NULL); 583 584 /* read in stage1 from the source disk. */ 585 if (read_stage1_from_disk(src_device->part_fd, target->stage1_buf) 586 != BC_SUCCESS) 587 return (BC_ERROR); 588 589 /* Prepare target stage2 for commit_to_disk. */ 590 cleanup_stage2(dest_stage2); 591 592 if (updt_str != NULL) 593 do_version = B_TRUE; 594 else 595 do_version = B_FALSE; 596 597 buf_size = src_stage2->file_size + SECTOR_SIZE; 598 599 dest_stage2->buf_size = P2ROUNDUP(buf_size, SECTOR_SIZE); 600 dest_stage2->buf = malloc(dest_stage2->buf_size); 601 if (dest_stage2->buf == NULL) { 602 perror(gettext("Memory allocation failed")); 603 return (BC_ERROR); 604 } 605 dest_stage2->file = dest_stage2->buf; 606 dest_stage2->file_size = src_stage2->file_size; 607 memcpy(dest_stage2->file, src_stage2->file, dest_stage2->file_size); 608 dest_stage2->extra = dest_stage2->buf + 609 P2ROUNDUP(dest_stage2->file_size, 8); 610 611 /* If we get down here we do have a mboot structure. */ 612 assert(src_stage2->mboot); 613 614 dest_stage2->mboot_off = src_stage2->mboot_off; 615 dest_stage2->mboot = (multiboot_header_t *)(dest_stage2->buf + 616 dest_stage2->mboot_off); 617 618 (void) fprintf(stdout, gettext("Propagating %s stage1/stage2 to %s\n"), 619 src_device->path, dest_device->path); 620 retval = commit_to_disk(target, updt_str); 621 622 return (retval); 623 } 624 625 /* 626 * open the device and fill the various members of ig_device_t. 627 */ 628 static int 629 init_device(ig_device_t *device, char *path) 630 { 631 struct dk_gpt *vtoc; 632 fstyp_handle_t fhdl; 633 const char *fident; 634 635 bzero(device, sizeof (*device)); 636 device->part_fd = -1; 637 device->disk_fd = -1; 638 device->path_p0 = NULL; 639 640 device->path = strdup(path); 641 if (device->path == NULL) { 642 perror(gettext("Memory allocation failed")); 643 return (BC_ERROR); 644 } 645 646 if (strstr(device->path, "diskette")) { 647 (void) fprintf(stderr, gettext("installing GRUB to a floppy " 648 "disk is no longer supported\n")); 649 return (BC_ERROR); 650 } 651 652 /* Detect if the target device is a pcfs partition. */ 653 if (strstr(device->path, "p0:boot")) 654 device->type = IG_DEV_X86BOOTPAR; 655 656 if (get_disk_fd(device) != BC_SUCCESS) 657 return (BC_ERROR); 658 659 /* read in the device boot sector. */ 660 if (read(device->disk_fd, device->boot_sector, SECTOR_SIZE) 661 != SECTOR_SIZE) { 662 (void) fprintf(stderr, gettext("Error reading boot sector\n")); 663 perror("read"); 664 return (BC_ERROR); 665 } 666 667 if (efi_alloc_and_read(device->disk_fd, &vtoc) > 0) { 668 device->type = IG_DEV_EFI; 669 efi_free(vtoc); 670 } 671 672 if (get_raw_partition_fd(device) != BC_SUCCESS) 673 return (BC_ERROR); 674 675 if (is_efi(device->type)) { 676 if (fstyp_init(device->part_fd, 0, NULL, &fhdl) != 0) 677 return (BC_ERROR); 678 679 if (fstyp_ident(fhdl, "zfs", &fident) != 0) { 680 fstyp_fini(fhdl); 681 (void) fprintf(stderr, gettext("Booting of EFI labeled " 682 "disks is only supported with ZFS\n")); 683 return (BC_ERROR); 684 } 685 fstyp_fini(fhdl); 686 } 687 688 if (get_start_sector(device) != BC_SUCCESS) 689 return (BC_ERROR); 690 691 return (BC_SUCCESS); 692 } 693 694 static void 695 cleanup_device(ig_device_t *device) 696 { 697 if (device->path) 698 free(device->path); 699 if (device->path_p0) 700 free(device->path_p0); 701 702 if (device->part_fd != -1) 703 (void) close(device->part_fd); 704 if (device->disk_fd != -1) 705 (void) close(device->disk_fd); 706 707 bzero(device, sizeof (ig_device_t)); 708 device->part_fd = -1; 709 device->disk_fd = -1; 710 } 711 712 static void 713 cleanup_stage2(ig_stage2_t *stage2) 714 { 715 if (stage2->buf) 716 free(stage2->buf); 717 bzero(stage2, sizeof (ig_stage2_t)); 718 } 719 720 static int 721 get_start_sector(ig_device_t *device) 722 { 723 uint32_t secnum = 0, numsec = 0; 724 int i, pno, rval, log_part = 0; 725 struct mboot *mboot; 726 struct ipart *part; 727 ext_part_t *epp; 728 struct part_info dkpi; 729 struct extpart_info edkpi; 730 731 if (is_efi(device->type)) { 732 struct dk_gpt *vtoc; 733 734 if (efi_alloc_and_read(device->disk_fd, &vtoc) <= 0) 735 return (BC_ERROR); 736 737 device->start_sector = vtoc->efi_parts[device->slice].p_start; 738 /* GPT doesn't use traditional slice letters */ 739 device->slice = 0xff; 740 device->partition = 0; 741 742 efi_free(vtoc); 743 goto found_part; 744 } 745 746 mboot = (struct mboot *)device->boot_sector; 747 748 if (is_bootpar(device->type)) { 749 if (find_x86_bootpar(mboot, &pno, &secnum) != BC_SUCCESS) { 750 (void) fprintf(stderr, NOBOOTPAR); 751 return (BC_ERROR); 752 } else { 753 device->start_sector = secnum; 754 device->partition = pno; 755 goto found_part; 756 } 757 } 758 759 /* 760 * Search for Solaris fdisk partition 761 * Get the solaris partition information from the device 762 * and compare the offset of S2 with offset of solaris partition 763 * from fdisk partition table. 764 */ 765 if (ioctl(device->part_fd, DKIOCEXTPARTINFO, &edkpi) < 0) { 766 if (ioctl(device->part_fd, DKIOCPARTINFO, &dkpi) < 0) { 767 (void) fprintf(stderr, PART_FAIL); 768 return (BC_ERROR); 769 } else { 770 edkpi.p_start = dkpi.p_start; 771 } 772 } 773 774 for (i = 0; i < FD_NUMPART; i++) { 775 part = (struct ipart *)mboot->parts + i; 776 777 if (part->relsect == 0) { 778 (void) fprintf(stderr, BAD_PART, i); 779 return (BC_ERROR); 780 } 781 782 if (edkpi.p_start >= part->relsect && 783 edkpi.p_start < (part->relsect + part->numsect)) { 784 /* Found the partition */ 785 break; 786 } 787 } 788 789 if (i == FD_NUMPART) { 790 /* No solaris fdisk partitions (primary or logical) */ 791 (void) fprintf(stderr, NOSOLPAR); 792 return (BC_ERROR); 793 } 794 795 /* 796 * We have found a Solaris fdisk partition (primary or extended) 797 * Handle the simple case first: Solaris in a primary partition 798 */ 799 if (!fdisk_is_dos_extended(part->systid)) { 800 device->start_sector = part->relsect; 801 device->partition = i; 802 goto found_part; 803 } 804 805 /* 806 * Solaris in a logical partition. Find that partition in the 807 * extended part. 808 */ 809 if ((rval = libfdisk_init(&epp, device->path_p0, NULL, FDISK_READ_DISK)) 810 != FDISK_SUCCESS) { 811 switch (rval) { 812 /* 813 * The first 3 cases are not an error per-se, just that 814 * there is no Solaris logical partition 815 */ 816 case FDISK_EBADLOGDRIVE: 817 case FDISK_ENOLOGDRIVE: 818 case FDISK_EBADMAGIC: 819 (void) fprintf(stderr, NOSOLPAR); 820 return (BC_ERROR); 821 case FDISK_ENOVGEOM: 822 (void) fprintf(stderr, NO_VIRT_GEOM); 823 return (BC_ERROR); 824 case FDISK_ENOPGEOM: 825 (void) fprintf(stderr, NO_PHYS_GEOM); 826 return (BC_ERROR); 827 case FDISK_ENOLGEOM: 828 (void) fprintf(stderr, NO_LABEL_GEOM); 829 return (BC_ERROR); 830 default: 831 (void) fprintf(stderr, LIBFDISK_INIT_FAIL); 832 return (BC_ERROR); 833 } 834 } 835 836 rval = fdisk_get_solaris_part(epp, &pno, &secnum, &numsec); 837 libfdisk_fini(&epp); 838 if (rval != FDISK_SUCCESS) { 839 /* No solaris logical partition */ 840 (void) fprintf(stderr, NOSOLPAR); 841 return (BC_ERROR); 842 } 843 844 device->start_sector = secnum; 845 device->partition = pno - 1; 846 log_part = 1; 847 848 found_part: 849 /* get confirmation for -m */ 850 if (write_mbr && !force_mbr) { 851 (void) fprintf(stdout, MBOOT_PROMPT); 852 if (getchar() != 'y') { 853 write_mbr = 0; 854 (void) fprintf(stdout, MBOOT_NOT_UPDATED); 855 return (BC_ERROR); 856 } 857 } 858 859 /* 860 * Currently if Solaris is in an extended partition we need to 861 * write GRUB to the MBR. Check for this. 862 */ 863 if (log_part && !write_mbr) { 864 (void) fprintf(stdout, gettext("Installing Solaris on an " 865 "extended partition... forcing MBR update\n")); 866 write_mbr = 1; 867 } 868 869 /* 870 * warn, if Solaris in primary partition and GRUB not in MBR and 871 * partition is not active 872 */ 873 if (!log_part && part->bootid != 128 && !write_mbr) { 874 (void) fprintf(stdout, SOLPAR_INACTIVE, device->partition + 1); 875 } 876 877 return (BC_SUCCESS); 878 } 879 880 static int 881 get_disk_fd(ig_device_t *device) 882 { 883 int i; 884 char save[2]; 885 char *end = NULL; 886 887 assert(device != NULL); 888 assert(device->path != NULL); 889 890 if (is_bootpar(device->type)) { 891 end = strstr(device->path, "p0:boot"); 892 /* tested at the start of init_device() */ 893 assert(end != NULL); 894 /* chop off :boot */ 895 save[0] = end[2]; 896 end[2] = '\0'; 897 } else { 898 i = strlen(device->path); 899 save[0] = device->path[i - 2]; 900 save[1] = device->path[i - 1]; 901 device->path[i - 2] = 'p'; 902 device->path[i - 1] = '0'; 903 } 904 905 if (nowrite) 906 device->disk_fd = open(device->path, O_RDONLY); 907 else 908 device->disk_fd = open(device->path, O_RDWR); 909 910 device->path_p0 = strdup(device->path); 911 if (device->path_p0 == NULL) { 912 perror("strdup"); 913 return (BC_ERROR); 914 } 915 916 if (is_bootpar(device->type)) { 917 end[2] = save[0]; 918 } else { 919 device->path[i - 2] = save[0]; 920 device->path[i - 1] = save[1]; 921 } 922 923 if (device->disk_fd == -1) { 924 perror("open"); 925 return (BC_ERROR); 926 } 927 928 return (BC_SUCCESS); 929 } 930 931 static void 932 prepare_fake_multiboot(ig_stage2_t *stage2) 933 { 934 multiboot_header_t *mboot; 935 936 assert(stage2 != NULL); 937 assert(stage2->mboot != NULL); 938 assert(stage2->buf != NULL); 939 940 mboot = stage2->mboot; 941 942 /* 943 * Currently we expect find_multiboot() to have located a multiboot 944 * header with the AOUT kludge flag set. 945 */ 946 assert(mboot->flags & BB_MBOOT_AOUT_FLAG); 947 948 /* Insert the information necessary to locate stage2. */ 949 mboot->header_addr = stage2->mboot_off; 950 mboot->load_addr = 0; 951 mboot->load_end_addr = stage2->file_size; 952 } 953 954 static void 955 add_stage2_einfo(ig_stage2_t *stage2, char *updt_str) 956 { 957 bblk_hs_t hs; 958 uint32_t avail_space; 959 960 assert(stage2 != NULL); 961 962 /* Fill bootblock hashing source information. */ 963 hs.src_buf = (unsigned char *)stage2->file; 964 hs.src_size = stage2->file_size; 965 /* How much space for the extended information structure? */ 966 avail_space = stage2->buf_size - P2ROUNDUP(stage2->file_size, 8); 967 add_einfo(stage2->extra, updt_str, &hs, avail_space); 968 } 969 970 971 static int 972 write_stage2(ig_data_t *install) 973 { 974 ig_device_t *device = &install->device; 975 ig_stage2_t *stage2 = &install->stage2; 976 off_t offset; 977 978 assert(install != NULL); 979 980 if (is_bootpar(device->type)) { 981 /* 982 * stage2 is already on the filesystem, we only need to update 983 * the first two blocks (that we have modified during 984 * prepare_stage2()) 985 */ 986 if (write_out(device->part_fd, stage2->file, SECTOR_SIZE, 987 stage2->pcfs_first_sectors[0] * SECTOR_SIZE) 988 != BC_SUCCESS || 989 write_out(device->part_fd, stage2->file + SECTOR_SIZE, 990 SECTOR_SIZE, stage2->pcfs_first_sectors[1] * SECTOR_SIZE) 991 != BC_SUCCESS) { 992 (void) fprintf(stderr, WRITE_FAIL_STAGE2); 993 return (BC_ERROR); 994 } 995 (void) fprintf(stdout, WRITE_STAGE2_PCFS); 996 return (BC_SUCCESS); 997 } 998 999 /* 1000 * For disk, write stage2 starting at STAGE2_BLKOFF sector. 1001 * Note that we use stage2->buf rather than stage2->file, because we 1002 * may have extended information after the latter. 1003 * 1004 * If we're writing to an EFI-labeled disk where stage2 lives in the 1005 * 3.5MB boot loader gap following the ZFS vdev labels, make sure the 1006 * size of the buffer doesn't exceed the size of the gap. 1007 */ 1008 if (is_efi(device->type) && stage2->buf_size > STAGE2_MAXSIZE) { 1009 (void) fprintf(stderr, WRITE_FAIL_STAGE2); 1010 return (BC_ERROR); 1011 } 1012 1013 offset = STAGE2_BLKOFF(device->type) * SECTOR_SIZE; 1014 1015 if (write_out(device->part_fd, stage2->buf, stage2->buf_size, 1016 offset) != BC_SUCCESS) { 1017 perror("write"); 1018 return (BC_ERROR); 1019 } 1020 1021 /* Simulate the "old" installgrub output. */ 1022 (void) fprintf(stdout, WRITE_STAGE2_DISK, device->partition, 1023 (stage2->buf_size / SECTOR_SIZE) + 1, STAGE2_BLKOFF(device->type), 1024 stage2->first_sector); 1025 1026 return (BC_SUCCESS); 1027 } 1028 1029 static int 1030 write_stage1(ig_data_t *install) 1031 { 1032 ig_device_t *device = &install->device; 1033 1034 assert(install != NULL); 1035 1036 if (write_out(device->part_fd, install->stage1_buf, 1037 sizeof (install->stage1_buf), 0) != BC_SUCCESS) { 1038 (void) fprintf(stdout, WRITE_FAIL_PBOOT); 1039 perror("write"); 1040 return (BC_ERROR); 1041 } 1042 1043 /* Simulate "old" installgrub output. */ 1044 (void) fprintf(stdout, WRITE_PBOOT, device->partition, 1045 device->start_sector); 1046 1047 if (write_mbr) { 1048 if (write_out(device->disk_fd, install->stage1_buf, 1049 sizeof (install->stage1_buf), 0) != BC_SUCCESS) { 1050 (void) fprintf(stdout, WRITE_FAIL_BOOTSEC); 1051 perror("write"); 1052 return (BC_ERROR); 1053 } 1054 /* Simulate "old" installgrub output. */ 1055 (void) fprintf(stdout, WRITE_MBOOT); 1056 } 1057 1058 return (BC_SUCCESS); 1059 } 1060 1061 #define USAGE_STRING "%s [-m|-f|-n|-F|-u verstr] stage1 stage2 device\n" \ 1062 "%s -M [-n] device1 device2\n" \ 1063 "%s [-V|-e] -i device\n" \ 1064 1065 #define CANON_USAGE_STR gettext(USAGE_STRING) 1066 1067 static void 1068 usage(char *progname) 1069 { 1070 (void) fprintf(stdout, CANON_USAGE_STR, progname, progname, progname); 1071 } 1072 1073 1074 static int 1075 read_stage1_from_file(char *path, ig_data_t *dest) 1076 { 1077 int fd; 1078 1079 assert(dest); 1080 1081 /* read the stage1 file from filesystem */ 1082 fd = open(path, O_RDONLY); 1083 if (fd == -1 || 1084 read(fd, dest->stage1_buf, SECTOR_SIZE) != SECTOR_SIZE) { 1085 (void) fprintf(stderr, READ_FAIL_STAGE1, path); 1086 return (BC_ERROR); 1087 } 1088 (void) close(fd); 1089 return (BC_SUCCESS); 1090 } 1091 1092 static int 1093 read_stage2_from_file(char *path, ig_data_t *dest) 1094 { 1095 int fd; 1096 struct stat sb; 1097 ig_stage2_t *stage2 = &dest->stage2; 1098 ig_device_t *device = &dest->device; 1099 uint32_t buf_size; 1100 1101 assert(dest); 1102 assert(stage2->buf == NULL); 1103 1104 fd = open(path, O_RDONLY); 1105 if (fstat(fd, &sb) == -1) { 1106 perror("fstat"); 1107 goto out; 1108 } 1109 1110 stage2->file_size = sb.st_size; 1111 1112 if (!is_bootpar(device->type)) { 1113 /* 1114 * buffer size needs to account for stage2 plus the extra 1115 * versioning information at the end of it. We reserve one 1116 * extra sector (plus we round up to the next sector boundary). 1117 */ 1118 buf_size = stage2->file_size + SECTOR_SIZE; 1119 } else { 1120 /* In the PCFS case we only need to read in stage2. */ 1121 buf_size = stage2->file_size; 1122 } 1123 1124 stage2->buf_size = P2ROUNDUP(buf_size, SECTOR_SIZE); 1125 1126 BOOT_DEBUG("stage2 buffer size = %d (%d sectors)\n", stage2->buf_size, 1127 stage2->buf_size / SECTOR_SIZE); 1128 1129 stage2->buf = malloc(stage2->buf_size); 1130 if (stage2->buf == NULL) { 1131 perror(gettext("Memory allocation failed")); 1132 goto out_fd; 1133 } 1134 1135 stage2->file = stage2->buf; 1136 1137 /* 1138 * Extra information (e.g. the versioning structure) is placed at the 1139 * end of stage2, aligned on a 8-byte boundary. 1140 */ 1141 if (!(is_bootpar(device->type))) 1142 stage2->extra = stage2->file + P2ROUNDUP(stage2->file_size, 8); 1143 1144 if (lseek(fd, 0, SEEK_SET) == -1) { 1145 perror("lseek"); 1146 goto out_alloc; 1147 } 1148 1149 if (read(fd, stage2->file, stage2->file_size) < 0) { 1150 perror(gettext("unable to read stage2")); 1151 goto out_alloc; 1152 } 1153 1154 (void) close(fd); 1155 return (BC_SUCCESS); 1156 1157 out_alloc: 1158 free(stage2->buf); 1159 stage2->buf = NULL; 1160 out_fd: 1161 (void) close(fd); 1162 out: 1163 return (BC_ERROR); 1164 } 1165 1166 static int 1167 prepare_stage1(ig_data_t *install) 1168 { 1169 ig_device_t *device = &install->device; 1170 1171 assert(install != NULL); 1172 1173 /* If PCFS add the BIOS Parameter Block. */ 1174 if (is_bootpar(device->type)) { 1175 char bpb_sect[SECTOR_SIZE]; 1176 1177 if (pread(device->part_fd, bpb_sect, SECTOR_SIZE, 0) 1178 != SECTOR_SIZE) { 1179 (void) fprintf(stderr, READ_FAIL_BPB); 1180 return (BC_ERROR); 1181 } 1182 bcopy(bpb_sect + STAGE1_BPB_OFFSET, 1183 install->stage1_buf + STAGE1_BPB_OFFSET, STAGE1_BPB_SIZE); 1184 } 1185 1186 /* copy MBR to stage1 in case of overwriting MBR sector. */ 1187 bcopy(device->boot_sector + BOOTSZ, install->stage1_buf + BOOTSZ, 1188 SECTOR_SIZE - BOOTSZ); 1189 /* modify default stage1 file generated by GRUB. */ 1190 *((unsigned char *)(install->stage1_buf + STAGE1_FORCE_LBA)) = 1; 1191 *((ulong_t *)(install->stage1_buf + STAGE1_STAGE2_SECTOR)) 1192 = install->stage2.first_sector; 1193 *((ushort_t *)(install->stage1_buf + STAGE1_STAGE2_ADDRESS)) 1194 = STAGE2_MEMADDR; 1195 *((ushort_t *)(install->stage1_buf + STAGE1_STAGE2_SEGMENT)) 1196 = STAGE2_MEMADDR >> 4; 1197 1198 return (BC_SUCCESS); 1199 } 1200 1201 /* 1202 * Grab stage1 from the specified device file descriptor. 1203 */ 1204 static int 1205 read_stage1_from_disk(int dev_fd, char *stage1_buf) 1206 { 1207 assert(stage1_buf != NULL); 1208 1209 if (read_in(dev_fd, stage1_buf, SECTOR_SIZE, 0) != BC_SUCCESS) { 1210 perror(gettext("Unable to read stage1 from disk")); 1211 return (BC_ERROR); 1212 } 1213 return (BC_SUCCESS); 1214 } 1215 1216 static int 1217 read_stage2_from_disk(int dev_fd, ig_stage2_t *stage2, int type) 1218 { 1219 uint32_t size; 1220 uint32_t buf_size; 1221 uint32_t mboot_off; 1222 multiboot_header_t *mboot; 1223 1224 assert(stage2 != NULL); 1225 assert(dev_fd != -1); 1226 1227 if (read_in(dev_fd, mboot_scan, sizeof (mboot_scan), 1228 STAGE2_BLKOFF(type) * SECTOR_SIZE) != BC_SUCCESS) { 1229 perror(gettext("Error reading stage2 sectors")); 1230 return (BC_ERROR); 1231 } 1232 1233 /* No multiboot means no chance of knowing stage2 size */ 1234 if (find_multiboot(mboot_scan, sizeof (mboot_scan), &mboot_off) 1235 != BC_SUCCESS) { 1236 BOOT_DEBUG("Unable to find multiboot header\n"); 1237 return (BC_NOEXTRA); 1238 } 1239 mboot = (multiboot_header_t *)(mboot_scan + mboot_off); 1240 1241 /* 1242 * Unfilled mboot values mean an older version of installgrub installed 1243 * the stage2. Again we have no chance of knowing stage2 size. 1244 */ 1245 if (mboot->load_end_addr == 0 || 1246 mboot->load_end_addr < mboot->load_addr) 1247 return (BC_NOEXTRA); 1248 1249 /* 1250 * Currently, the amount of space reserved for extra information 1251 * is "fixed". We may have to scan for the terminating extra payload 1252 * in the future. 1253 */ 1254 size = mboot->load_end_addr - mboot->load_addr; 1255 buf_size = P2ROUNDUP(size + SECTOR_SIZE, SECTOR_SIZE); 1256 1257 stage2->buf = malloc(buf_size); 1258 if (stage2->buf == NULL) { 1259 perror(gettext("Memory allocation failed")); 1260 return (BC_ERROR); 1261 } 1262 stage2->buf_size = buf_size; 1263 1264 if (read_in(dev_fd, stage2->buf, buf_size, STAGE2_BLKOFF(type) * 1265 SECTOR_SIZE) != BC_SUCCESS) { 1266 perror("read"); 1267 free(stage2->buf); 1268 return (BC_ERROR); 1269 } 1270 1271 /* Update pointers. */ 1272 stage2->file = stage2->buf; 1273 stage2->file_size = size; 1274 stage2->mboot_off = mboot_off; 1275 stage2->mboot = (multiboot_header_t *)(stage2->buf + stage2->mboot_off); 1276 stage2->extra = stage2->buf + P2ROUNDUP(stage2->file_size, 8); 1277 stage2->extra_size = stage2->buf_size - P2ROUNDUP(stage2->file_size, 8); 1278 1279 return (BC_SUCCESS); 1280 } 1281 1282 static boolean_t 1283 is_update_necessary(ig_data_t *data, char *updt_str) 1284 { 1285 bblk_einfo_t *einfo; 1286 bblk_hs_t stage2_hs; 1287 ig_stage2_t stage2_disk; 1288 ig_stage2_t *stage2_file = &data->stage2; 1289 ig_device_t *device = &data->device; 1290 int dev_fd = device->part_fd; 1291 1292 assert(data != NULL); 1293 assert(device->part_fd != -1); 1294 1295 bzero(&stage2_disk, sizeof (ig_stage2_t)); 1296 1297 /* Gather stage2 (if present) from the target device. */ 1298 if (read_stage2_from_disk(dev_fd, &stage2_disk, device->type) 1299 != BC_SUCCESS) { 1300 BOOT_DEBUG("Unable to read stage2 from %s\n", device->path); 1301 BOOT_DEBUG("No multiboot wrapped stage2 on %s\n", device->path); 1302 return (B_TRUE); 1303 } 1304 1305 /* 1306 * Look for the extended information structure in the extra payload 1307 * area. 1308 */ 1309 einfo = find_einfo(stage2_disk.extra, stage2_disk.extra_size); 1310 if (einfo == NULL) { 1311 BOOT_DEBUG("No extended information available\n"); 1312 return (B_TRUE); 1313 } 1314 1315 if (!do_version || updt_str == NULL) { 1316 (void) fprintf(stdout, "WARNING: target device %s has a " 1317 "versioned stage2 that is going to be overwritten by a non " 1318 "versioned one\n", device->path); 1319 return (B_TRUE); 1320 } 1321 1322 if (force_update) { 1323 BOOT_DEBUG("Forcing update of %s bootblock\n", device->path); 1324 return (B_TRUE); 1325 } 1326 1327 /* Compare the two extended information structures. */ 1328 stage2_hs.src_buf = (unsigned char *)stage2_file->file; 1329 stage2_hs.src_size = stage2_file->file_size; 1330 1331 return (einfo_should_update(einfo, &stage2_hs, updt_str)); 1332 } 1333 1334 1335 #define START_BLOCK(pos) (*(ulong_t *)(pos)) 1336 #define NUM_BLOCK(pos) (*(ushort_t *)((pos) + 4)) 1337 #define START_SEG(pos) (*(ushort_t *)((pos) + 6)) 1338 1339 static int 1340 prepare_stage2(ig_data_t *install, char *updt_str) 1341 { 1342 ig_device_t *device = &install->device; 1343 ig_stage2_t *stage2 = &install->stage2; 1344 uint32_t mboot_off = 0; 1345 1346 assert(install != NULL); 1347 assert(stage2->file != NULL); 1348 1349 /* New stage2 files come with an embedded stage2. */ 1350 if (find_multiboot(stage2->file, stage2->file_size, &mboot_off) 1351 != BC_SUCCESS) { 1352 BOOT_DEBUG("WARNING: no multiboot structure found in stage2, " 1353 "are you using an old GRUB stage2?\n"); 1354 if (do_version == B_TRUE) { 1355 (void) fprintf(stderr, gettext("Versioning requested " 1356 "but stage2 does not support it.. skipping.\n")); 1357 do_version = B_FALSE; 1358 } 1359 } else { 1360 /* Keep track of where the multiboot header is. */ 1361 stage2->mboot_off = mboot_off; 1362 stage2->mboot = (multiboot_header_t *)(stage2->file + 1363 mboot_off); 1364 if (do_version) { 1365 /* 1366 * Adding stage2 information needs to happen before 1367 * we modify the copy of stage2 we have in memory, so 1368 * that the hashing reflects the one of the file. 1369 * An error here is not fatal. 1370 */ 1371 add_stage2_einfo(stage2, updt_str); 1372 } 1373 /* 1374 * Fill multiboot information. We add them even without 1375 * versioning to support as much as possible mirroring. 1376 */ 1377 prepare_fake_multiboot(stage2); 1378 } 1379 1380 if (is_bootpar(device->type)) { 1381 uint32_t blocklist[SECTOR_SIZE / sizeof (uint32_t)]; 1382 uint32_t install_addr = STAGE2_MEMADDR + SECTOR_SIZE; 1383 int i = 0; 1384 uchar_t *pos; 1385 1386 bzero(blocklist, sizeof (blocklist)); 1387 if (read_stage2_blocklist(device->part_fd, blocklist) != 0) { 1388 (void) fprintf(stderr, gettext("Error reading pcfs " 1389 "stage2 blocklist\n")); 1390 return (BC_ERROR); 1391 } 1392 1393 pos = (uchar_t *)stage2->file + STAGE2_BLOCKLIST; 1394 stage2->first_sector = device->start_sector + blocklist[0]; 1395 stage2->pcfs_first_sectors[0] = blocklist[0]; 1396 BOOT_DEBUG("stage2 first sector: %d\n", stage2->first_sector); 1397 1398 1399 if (blocklist[1] > 1) { 1400 blocklist[0]++; 1401 blocklist[1]--; 1402 } else { 1403 i += 2; 1404 } 1405 1406 stage2->pcfs_first_sectors[1] = blocklist[i]; 1407 1408 while (blocklist[i]) { 1409 if (START_BLOCK(pos - 8) != 0 && 1410 START_BLOCK(pos - 8) != blocklist[i + 2]) { 1411 (void) fprintf(stderr, PCFS_FRAGMENTED); 1412 return (BC_ERROR); 1413 } 1414 START_BLOCK(pos) = blocklist[i] + device->start_sector; 1415 START_SEG(pos) = (ushort_t)(install_addr >> 4); 1416 NUM_BLOCK(pos) = blocklist[i + 1]; 1417 install_addr += blocklist[i + 1] * SECTOR_SIZE; 1418 pos -= 8; 1419 i += 2; 1420 } 1421 } else { 1422 /* Solaris VTOC */ 1423 stage2->first_sector = device->start_sector + 1424 STAGE2_BLKOFF(device->type); 1425 BOOT_DEBUG("stage2 first sector: %d\n", stage2->first_sector); 1426 /* 1427 * In a solaris partition, stage2 is written to contiguous 1428 * blocks. So we update the starting block only. 1429 */ 1430 *((ulong_t *)(stage2->file + STAGE2_BLOCKLIST)) = 1431 stage2->first_sector + 1; 1432 } 1433 1434 /* force lba and set disk partition */ 1435 *((unsigned char *) (stage2->file + STAGE2_FORCE_LBA)) = 1; 1436 *((long *)(stage2->file + STAGE2_INSTALLPART)) 1437 = (device->partition << 16) | (device->slice << 8) | 0xff; 1438 1439 return (BC_SUCCESS); 1440 } 1441 1442 static int 1443 find_x86_bootpar(struct mboot *mboot, int *part_num, uint32_t *start_sect) 1444 { 1445 int i; 1446 1447 for (i = 0; i < FD_NUMPART; i++) { 1448 struct ipart *part; 1449 1450 part = (struct ipart *)mboot->parts + i; 1451 if (part->systid == 0xbe) { 1452 if (start_sect) 1453 *start_sect = part->relsect; 1454 if (part_num) 1455 *part_num = i; 1456 /* solaris boot part */ 1457 return (BC_SUCCESS); 1458 } 1459 } 1460 return (BC_ERROR); 1461 } 1462 1463 static char * 1464 get_raw_partition_path(ig_device_t *device) 1465 { 1466 char *raw; 1467 int len; 1468 1469 if (is_bootpar(device->type)) { 1470 int part; 1471 struct mboot *mboot; 1472 1473 mboot = (struct mboot *)device->boot_sector; 1474 if (find_x86_bootpar(mboot, &part, NULL) != BC_SUCCESS) { 1475 (void) fprintf(stderr, BOOTPAR_NOTFOUND, 1476 device->path_p0); 1477 return (NULL); 1478 } 1479 1480 raw = strdup(device->path_p0); 1481 if (raw == NULL) { 1482 perror(gettext("Memory allocation failed")); 1483 return (NULL); 1484 } 1485 1486 raw[strlen(raw) - 2] = '1' + part; 1487 return (raw); 1488 } 1489 1490 /* For disk, remember slice and return whole fdisk partition */ 1491 raw = strdup(device->path); 1492 if (raw == NULL) { 1493 perror(gettext("Memory allocation failed")); 1494 return (NULL); 1495 } 1496 1497 len = strlen(raw); 1498 if (!is_efi(device->type) && 1499 (raw[len - 2] != 's' || raw[len - 1] == '2')) { 1500 (void) fprintf(stderr, NOT_ROOT_SLICE); 1501 free(raw); 1502 return (NULL); 1503 } 1504 device->slice = atoi(&raw[len - 1]); 1505 1506 if (!is_efi(device->type)) { 1507 raw[len - 2] = 's'; 1508 raw[len - 1] = '2'; 1509 } 1510 1511 return (raw); 1512 } 1513 1514 static int 1515 get_raw_partition_fd(ig_device_t *device) 1516 { 1517 struct stat stat = {0}; 1518 char *raw; 1519 1520 raw = get_raw_partition_path(device); 1521 if (raw == NULL) 1522 return (BC_ERROR); 1523 1524 if (nowrite) 1525 device->part_fd = open(raw, O_RDONLY); 1526 else 1527 device->part_fd = open(raw, O_RDWR); 1528 1529 if (device->part_fd < 0 || fstat(device->part_fd, &stat) != 0) { 1530 (void) fprintf(stderr, OPEN_FAIL, raw); 1531 free(raw); 1532 return (BC_ERROR); 1533 } 1534 1535 if (S_ISCHR(stat.st_mode) == 0) { 1536 (void) fprintf(stderr, NOT_RAW_DEVICE, raw); 1537 (void) close(device->part_fd); 1538 device->part_fd = -1; 1539 free(raw); 1540 return (BC_ERROR); 1541 } 1542 1543 free(raw); 1544 return (BC_SUCCESS); 1545 } 1546 1547 #define TMP_MNTPT "/tmp/installgrub_pcfs" 1548 static int 1549 copy_stage2_to_pcfs(ig_data_t *install) 1550 { 1551 FILE *mntfp; 1552 int pcfs_fp; 1553 int status = BC_ERROR; 1554 char buf[SECTOR_SIZE]; 1555 char *cp; 1556 struct mnttab mp = {0}, mpref = {0}; 1557 ig_device_t *device = &install->device; 1558 ig_stage2_t *stage2 = &install->stage2; 1559 1560 /* convert raw to block device name by removing the first 'r' */ 1561 (void) strncpy(buf, device->path, sizeof (buf)); 1562 buf[sizeof (buf) - 1] = 0; 1563 cp = strchr(buf, 'r'); 1564 if (cp == NULL) { 1565 (void) fprintf(stderr, CONVERT_FAIL, device->path); 1566 return (BC_ERROR); 1567 } 1568 do { 1569 *cp = *(cp + 1); 1570 } while (*(++cp)); 1571 1572 /* get the mount point, if any */ 1573 mntfp = fopen("/etc/mnttab", "r"); 1574 if (mntfp == NULL) { 1575 (void) fprintf(stderr, OPEN_FAIL_FILE, "/etc/mnttab"); 1576 return (BC_ERROR); 1577 } 1578 1579 mpref.mnt_special = buf; 1580 if (getmntany(mntfp, &mp, &mpref) != 0) { 1581 char cmd[128]; 1582 1583 /* not mounted, try remount */ 1584 (void) mkdir(TMP_MNTPT, S_IRWXU); 1585 (void) snprintf(cmd, sizeof (cmd), "mount -F pcfs %s %s", 1586 buf, TMP_MNTPT); 1587 (void) system(cmd); 1588 rewind(mntfp); 1589 bzero(&mp, sizeof (mp)); 1590 if (getmntany(mntfp, &mp, &mpref) != 0) { 1591 (void) fprintf(stderr, MOUNT_FAIL, buf); 1592 return (BC_ERROR); 1593 } 1594 } 1595 1596 (void) snprintf(buf, sizeof (buf), 1597 "%s/boot", mp.mnt_mountp); 1598 (void) mkdir(buf, S_IRWXU); 1599 (void) strcat(buf, "/grub"); 1600 (void) mkdir(buf, S_IRWXU); 1601 1602 (void) strcat(buf, "/stage2"); 1603 pcfs_fp = open(buf, O_WRONLY | O_CREAT, S_IRWXU); 1604 if (pcfs_fp == -1) { 1605 (void) fprintf(stderr, OPEN_FAIL_FILE, buf); 1606 perror("open:"); 1607 goto out; 1608 } 1609 1610 /* write stage2 to the pcfs mounted filesystem. */ 1611 if (write(pcfs_fp, stage2->file, stage2->file_size) 1612 != stage2->file_size) { 1613 perror(gettext("Error writing stage2")); 1614 goto out; 1615 } 1616 1617 status = BC_SUCCESS; 1618 out_fd: 1619 (void) close(pcfs_fp); 1620 out: 1621 (void) umount(TMP_MNTPT); 1622 (void) rmdir(TMP_MNTPT); 1623 return (status); 1624 } 1625