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