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