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