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.
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.
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]
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.
42 #include <sys/mount.h>
43 #include <sys/mnttab.h>
44 #include <sys/dktp/fdisk.h>
47 #include <sys/types.h>
49 #include <sys/multiboot.h>
50 #include <sys/sysmacros.h>
51 #include <sys/efi_partition.h>
53 #include <libnvpair.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"
64 #define TEXT_DOMAIN "SUNW_OST_OSCMD"
68 * Variables to track installgrub desired mode of operation.
69 * 'nowrite' and 'boot_debug' come from boot_common.h.
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
;
80 /* Installing the bootblock is the default operation. */
81 static boolean_t do_install
= B_TRUE
;
83 /* Versioning string, if present. */
84 static char *update_str
;
87 * Temporary buffer to store the first 32K of data looking for a multiboot
90 char mboot_scan
[MBOOT_SCAN_SIZE
];
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 *);
122 extern int read_stage2_blocklist(int, unsigned int *);
125 main(int argc
, char *argv
[])
133 (void) setlocale(LC_ALL
, "");
134 (void) textdomain(TEXT_DOMAIN
);
135 if (init_yes() < 0) {
136 (void) fprintf(stderr
, gettext(ERR_MSG_INIT_YES
),
142 * retro-compatibility: installing the bootblock is the default
143 * and there is no switch for it.
147 while ((opt
= getopt(argc
, argv
, "dVMFfmneiu:")) != EOF
) {
160 do_install
= B_FALSE
;
164 verbose_dump
= B_TRUE
;
170 force_update
= B_TRUE
;
176 do_mirror_bblk
= B_TRUE
;
177 do_install
= B_FALSE
;
183 update_str
= malloc(strlen(optarg
) + 1);
184 if (update_str
== NULL
) {
185 (void) fprintf(stderr
, gettext("Unable to "
186 "allocate memory\n"));
189 (void) strlcpy(update_str
, optarg
, strlen(optarg
) + 1);
192 /* fall through to process non-optional args */
197 /* check arguments */
198 if (argc
!= optind
+ params
) {
204 * clean up options (and bail out if an unrecoverable combination is
208 check_options(progname
);
209 handle_args
= argv
+ optind
;
212 (void) fprintf(stdout
, DRY_RUN
);
215 ret
= handle_getinfo(progname
, handle_args
);
216 } else if (do_mirror_bblk
) {
217 ret
= handle_mirror(progname
, handle_args
);
219 ret
= handle_install(progname
, handle_args
);
224 #define MEANINGLESS_OPT gettext("%s specified but meaningless, ignoring\n")
226 check_options(char *progname
)
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"));
235 if (do_mirror_bblk
) {
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.
244 (void) fprintf(stderr
, MEANINGLESS_OPT
, "-u");
245 do_version
= B_FALSE
;
248 (void) fprintf(stderr
, MEANINGLESS_OPT
, "-F");
249 force_update
= B_FALSE
;
251 if (strip
|| verbose_dump
) {
252 BOOT_DEBUG(MEANINGLESS_OPT
, "-e|-V");
254 verbose_dump
= B_FALSE
;
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
;
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).
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
280 handle_install(char *progname
, char **argv
)
282 ig_data_t install_data
;
283 char *stage1_path
= NULL
;
284 char *stage2_path
= NULL
;
285 char *device_path
= NULL
;
288 stage1_path
= strdup(argv
[0]);
289 stage2_path
= strdup(argv
[1]);
290 device_path
= strdup(argv
[2]);
292 bzero(&install_data
, sizeof (ig_data_t
));
294 if (!stage1_path
|| !stage2_path
|| !device_path
) {
295 (void) fprintf(stderr
, gettext("Missing parameter"));
300 BOOT_DEBUG("stage1 path: %s, stage2 path: %s, device: %s\n",
301 stage1_path
, stage2_path
, device_path
);
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
);
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"),
316 if (read_stage2_from_file(stage2_path
, &install_data
) != BC_SUCCESS
) {
317 (void) fprintf(stderr
, gettext("Error opening %s\n"),
322 /* We do not support versioning on PCFS. */
323 if (is_bootpar(install_data
.device
.type
) && do_version
)
324 do_version
= B_FALSE
;
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.
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"),
341 * - the installed GRUB version is older than the one about to be
343 * - no versioning string has been passed through the command line.
344 * - a forced update is requested (-F).
346 BOOT_DEBUG("Ready to commit to disk\n");
347 ret
= commit_to_disk(&install_data
, update_str
);
350 cleanup_device(&install_data
.device
);
359 * Retrieves from a device the extended information (einfo) associated to the
361 * Expects one parameter, the device path, in the form: /dev/rdsk/c?[t?]d?s0.
363 * - BC_SUCCESS (and prints out einfo contents depending on 'flags')
364 * - BC_ERROR (on error)
365 * - BC_NOEINFO (no extended information available)
368 handle_getinfo(char *progname
, char **argv
)
371 ig_stage2_t
*stage2
= &data
.stage2
;
372 ig_device_t
*device
= &data
.device
;
377 int retval
= BC_ERROR
;
380 device_path
= strdup(argv
[0]);
382 (void) fprintf(stderr
, gettext("Missing parameter"));
387 bzero(&data
, sizeof (ig_data_t
));
388 BOOT_DEBUG("device path: %s\n", device_path
);
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
);
396 if (is_bootpar(device
->type
)) {
397 (void) fprintf(stderr
, gettext("Versioning not supported on "
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
);
409 if (ret
== BC_NOEXTRA
) {
410 (void) fprintf(stdout
, gettext("No multiboot header found on "
411 "%s, unable to locate extra information area\n"),
417 einfo
= find_einfo(stage2
->extra
, stage2
->extra_size
);
420 (void) fprintf(stderr
, gettext("No extended information "
425 /* Print the extended information. */
427 flags
|= EINFO_EASY_PARSE
;
429 flags
|= EINFO_PRINT_HEADER
;
431 size
= stage2
->buf_size
- P2ROUNDUP(stage2
->file_size
, 8);
432 print_einfo(flags
, einfo
, size
);
436 cleanup_device(&data
.device
);
443 * Attempt to mirror (propagate) the current stage2 over the attaching disk.
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)
452 handle_mirror(char *progname
, char **argv
)
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
;
467 curr_device_path
= strdup(argv
[0]);
468 attach_device_path
= strdup(argv
[1]);
470 if (!curr_device_path
|| !attach_device_path
) {
471 (void) fprintf(stderr
, gettext("Missing parameter"));
475 BOOT_DEBUG("Current device path is: %s, attaching device path is: "
476 " %s\n", curr_device_path
, attach_device_path
);
478 bzero(&curr_data
, sizeof (ig_data_t
));
479 bzero(&attach_data
, sizeof (ig_data_t
));
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
);
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"),
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"));
500 ret
= read_stage2_from_disk(curr_device
->part_fd
, stage2_curr
,
502 if (ret
== BC_ERROR
) {
503 BOOT_DEBUG("Error reading first stage2 blocks from %s\n",
509 if (ret
== BC_NOEXTRA
) {
510 BOOT_DEBUG("No multiboot header found on %s, unable to grab "
511 "stage2\n", curr_device
->path
);
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
);
522 retval
= propagate_bootblock(&curr_data
, &attach_data
, updt_str
);
523 cleanup_stage2(stage2_curr
);
524 cleanup_stage2(stage2_attach
);
527 cleanup_device(attach_device
);
529 cleanup_device(curr_device
);
531 free(curr_device_path
);
532 free(attach_device_path
);
537 commit_to_disk(ig_data_t
*install
, char *updt_str
)
539 assert(install
!= NULL
);
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.
545 if (prepare_stage2(install
, updt_str
) != BC_SUCCESS
) {
546 (void) fprintf(stderr
, gettext("Error building stage2\n"));
549 if (prepare_stage1(install
) != BC_SUCCESS
) {
550 (void) fprintf(stderr
, gettext("Error building stage1\n"));
554 /* Write stage2 out to disk. */
555 if (write_stage2(install
) != BC_SUCCESS
) {
556 (void) fprintf(stderr
, gettext("Error writing stage2 to "
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 "
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.
578 propagate_bootblock(ig_data_t
*source
, ig_data_t
*target
, char *updt_str
)
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
;
587 assert(source
!= NULL
);
588 assert(target
!= NULL
);
590 /* read in stage1 from the source disk. */
591 if (read_stage1_from_disk(src_device
->part_fd
, target
->stage1_buf
)
595 /* Prepare target stage2 for commit_to_disk. */
596 cleanup_stage2(dest_stage2
);
598 if (updt_str
!= NULL
)
601 do_version
= B_FALSE
;
603 buf_size
= src_stage2
->file_size
+ SECTOR_SIZE
;
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"));
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);
617 /* If we get down here we do have a mboot structure. */
618 assert(src_stage2
->mboot
);
620 dest_stage2
->mboot_off
= src_stage2
->mboot_off
;
621 dest_stage2
->mboot
= (multiboot_header_t
*)(dest_stage2
->buf
+
622 dest_stage2
->mboot_off
);
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
);
632 * open the device and fill the various members of ig_device_t.
635 init_device(ig_device_t
*device
, char *path
)
641 bzero(device
, sizeof (*device
));
642 device
->part_fd
= -1;
643 device
->disk_fd
= -1;
644 device
->path_p0
= NULL
;
646 device
->path
= strdup(path
);
647 if (device
->path
== NULL
) {
648 perror(gettext("Memory allocation failed"));
652 if (strstr(device
->path
, "diskette")) {
653 (void) fprintf(stderr
, gettext("installing GRUB to a floppy "
654 "disk is no longer supported\n"));
658 /* Detect if the target device is a pcfs partition. */
659 if (strstr(device
->path
, "p0:boot"))
660 device
->type
= IG_DEV_X86BOOTPAR
;
662 if (get_disk_fd(device
) != BC_SUCCESS
)
665 /* read in the device boot sector. */
666 if (read(device
->disk_fd
, device
->boot_sector
, SECTOR_SIZE
)
668 (void) fprintf(stderr
, gettext("Error reading boot sector\n"));
673 if (efi_alloc_and_read(device
->disk_fd
, &vtoc
) > 0) {
674 device
->type
= IG_DEV_EFI
;
678 if (get_raw_partition_fd(device
) != BC_SUCCESS
)
681 if (is_efi(device
->type
)) {
682 if (fstyp_init(device
->part_fd
, 0, NULL
, &fhdl
) != 0)
685 if (fstyp_ident(fhdl
, "zfs", &fident
) != 0) {
687 (void) fprintf(stderr
, gettext("Booting of EFI labeled "
688 "disks is only supported with ZFS\n"));
694 if (get_start_sector(device
) != BC_SUCCESS
)
701 cleanup_device(ig_device_t
*device
)
706 free(device
->path_p0
);
708 if (device
->part_fd
!= -1)
709 (void) close(device
->part_fd
);
710 if (device
->disk_fd
!= -1)
711 (void) close(device
->disk_fd
);
713 bzero(device
, sizeof (ig_device_t
));
714 device
->part_fd
= -1;
715 device
->disk_fd
= -1;
719 cleanup_stage2(ig_stage2_t
*stage2
)
723 bzero(stage2
, sizeof (ig_stage2_t
));
727 get_start_sector(ig_device_t
*device
)
729 uint32_t secnum
= 0, numsec
= 0;
730 int i
, pno
, rval
, log_part
= 0;
734 struct part_info dkpi
;
735 struct extpart_info edkpi
;
737 if (is_efi(device
->type
)) {
740 if (efi_alloc_and_read(device
->disk_fd
, &vtoc
) <= 0)
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;
752 mboot
= (struct mboot
*)device
->boot_sector
;
754 if (is_bootpar(device
->type
)) {
755 if (find_x86_bootpar(mboot
, &pno
, &secnum
) != BC_SUCCESS
) {
756 (void) fprintf(stderr
, NOBOOTPAR
);
759 device
->start_sector
= secnum
;
760 device
->partition
= pno
;
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.
771 if (ioctl(device
->part_fd
, DKIOCEXTPARTINFO
, &edkpi
) < 0) {
772 if (ioctl(device
->part_fd
, DKIOCPARTINFO
, &dkpi
) < 0) {
773 (void) fprintf(stderr
, PART_FAIL
);
776 edkpi
.p_start
= dkpi
.p_start
;
780 for (i
= 0; i
< FD_NUMPART
; i
++) {
781 part
= (struct ipart
*)mboot
->parts
+ i
;
783 if (part
->relsect
== 0) {
784 (void) fprintf(stderr
, BAD_PART
, i
);
788 if (edkpi
.p_start
>= part
->relsect
&&
789 edkpi
.p_start
< (part
->relsect
+ part
->numsect
)) {
790 /* Found the partition */
795 if (i
== FD_NUMPART
) {
796 /* No solaris fdisk partitions (primary or logical) */
797 (void) fprintf(stderr
, NOSOLPAR
);
802 * We have found a Solaris fdisk partition (primary or extended)
803 * Handle the simple case first: Solaris in a primary partition
805 if (!fdisk_is_dos_extended(part
->systid
)) {
806 device
->start_sector
= part
->relsect
;
807 device
->partition
= i
;
812 * Solaris in a logical partition. Find that partition in the
815 if ((rval
= libfdisk_init(&epp
, device
->path_p0
, NULL
, FDISK_READ_DISK
))
819 * The first 3 cases are not an error per-se, just that
820 * there is no Solaris logical partition
822 case FDISK_EBADLOGDRIVE
:
823 case FDISK_ENOLOGDRIVE
:
824 case FDISK_EBADMAGIC
:
825 (void) fprintf(stderr
, NOSOLPAR
);
828 (void) fprintf(stderr
, NO_VIRT_GEOM
);
831 (void) fprintf(stderr
, NO_PHYS_GEOM
);
834 (void) fprintf(stderr
, NO_LABEL_GEOM
);
837 (void) fprintf(stderr
, LIBFDISK_INIT_FAIL
);
842 rval
= fdisk_get_solaris_part(epp
, &pno
, &secnum
, &numsec
);
844 if (rval
!= FDISK_SUCCESS
) {
845 /* No solaris logical partition */
846 (void) fprintf(stderr
, NOSOLPAR
);
850 device
->start_sector
= secnum
;
851 device
->partition
= pno
- 1;
855 /* get confirmation for -m */
856 if (write_mbr
&& !force_mbr
) {
857 (void) fprintf(stdout
, MBOOT_PROMPT
);
860 (void) fprintf(stdout
, MBOOT_NOT_UPDATED
);
866 * Currently if Solaris is in an extended partition we need to
867 * write GRUB to the MBR. Check for this.
869 if (log_part
&& !write_mbr
) {
870 (void) fprintf(stdout
, gettext("Installing Solaris on an "
871 "extended partition... forcing MBR update\n"));
876 * warn, if Solaris in primary partition and GRUB not in MBR and
877 * partition is not active
879 if (!log_part
&& part
->bootid
!= 128 && !write_mbr
) {
880 (void) fprintf(stdout
, SOLPAR_INACTIVE
, device
->partition
+ 1);
887 get_disk_fd(ig_device_t
*device
)
893 assert(device
!= NULL
);
894 assert(device
->path
!= NULL
);
896 if (is_bootpar(device
->type
)) {
897 end
= strstr(device
->path
, "p0:boot");
898 /* tested at the start of init_device() */
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';
912 device
->disk_fd
= open(device
->path
, O_RDONLY
);
914 device
->disk_fd
= open(device
->path
, O_RDWR
);
916 device
->path_p0
= strdup(device
->path
);
917 if (device
->path_p0
== NULL
) {
922 if (is_bootpar(device
->type
)) {
925 device
->path
[i
- 2] = save
[0];
926 device
->path
[i
- 1] = save
[1];
929 if (device
->disk_fd
== -1) {
938 prepare_fake_multiboot(ig_stage2_t
*stage2
)
940 multiboot_header_t
*mboot
;
942 assert(stage2
!= NULL
);
943 assert(stage2
->mboot
!= NULL
);
944 assert(stage2
->buf
!= NULL
);
946 mboot
= stage2
->mboot
;
949 * Currently we expect find_multiboot() to have located a multiboot
950 * header with the AOUT kludge flag set.
952 assert(mboot
->flags
& BB_MBOOT_AOUT_FLAG
);
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
;
961 add_stage2_einfo(ig_stage2_t
*stage2
, char *updt_str
)
964 uint32_t avail_space
;
966 assert(stage2
!= NULL
);
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
);
978 write_stage2(ig_data_t
*install
)
980 ig_device_t
*device
= &install
->device
;
981 ig_stage2_t
*stage2
= &install
->stage2
;
984 assert(install
!= NULL
);
986 if (is_bootpar(device
->type
)) {
988 * stage2 is already on the filesystem, we only need to update
989 * the first two blocks (that we have modified during
992 if (write_out(device
->part_fd
, stage2
->file
, SECTOR_SIZE
,
993 stage2
->pcfs_first_sectors
[0] * SECTOR_SIZE
)
995 write_out(device
->part_fd
, stage2
->file
+ SECTOR_SIZE
,
996 SECTOR_SIZE
, stage2
->pcfs_first_sectors
[1] * SECTOR_SIZE
)
998 (void) fprintf(stderr
, WRITE_FAIL_STAGE2
);
1001 (void) fprintf(stdout
, WRITE_STAGE2_PCFS
);
1002 return (BC_SUCCESS
);
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.
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.
1014 if (is_efi(device
->type
) && stage2
->buf_size
> STAGE2_MAXSIZE
) {
1015 (void) fprintf(stderr
, WRITE_FAIL_STAGE2
);
1019 offset
= STAGE2_BLKOFF(device
->type
) * SECTOR_SIZE
;
1021 if (write_out(device
->part_fd
, stage2
->buf
, stage2
->buf_size
,
1022 offset
) != BC_SUCCESS
) {
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
);
1032 return (BC_SUCCESS
);
1036 write_stage1(ig_data_t
*install
)
1038 ig_device_t
*device
= &install
->device
;
1040 assert(install
!= NULL
);
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
);
1049 /* Simulate "old" installgrub output. */
1050 (void) fprintf(stdout
, WRITE_PBOOT
, device
->partition
,
1051 device
->start_sector
);
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
);
1060 /* Simulate "old" installgrub output. */
1061 (void) fprintf(stdout
, WRITE_MBOOT
);
1064 return (BC_SUCCESS
);
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" \
1071 #define CANON_USAGE_STR gettext(USAGE_STRING)
1074 usage(char *progname
)
1076 (void) fprintf(stdout
, CANON_USAGE_STR
, progname
, progname
, progname
);
1081 read_stage1_from_file(char *path
, ig_data_t
*dest
)
1087 /* read the stage1 file from filesystem */
1088 fd
= open(path
, O_RDONLY
);
1090 read(fd
, dest
->stage1_buf
, SECTOR_SIZE
) != SECTOR_SIZE
) {
1091 (void) fprintf(stderr
, READ_FAIL_STAGE1
, path
);
1095 return (BC_SUCCESS
);
1099 read_stage2_from_file(char *path
, ig_data_t
*dest
)
1103 ig_stage2_t
*stage2
= &dest
->stage2
;
1104 ig_device_t
*device
= &dest
->device
;
1108 assert(stage2
->buf
== NULL
);
1110 fd
= open(path
, O_RDONLY
);
1111 if (fstat(fd
, &sb
) == -1) {
1116 stage2
->file_size
= sb
.st_size
;
1118 if (!is_bootpar(device
->type
)) {
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).
1124 buf_size
= stage2
->file_size
+ SECTOR_SIZE
;
1126 /* In the PCFS case we only need to read in stage2. */
1127 buf_size
= stage2
->file_size
;
1130 stage2
->buf_size
= P2ROUNDUP(buf_size
, SECTOR_SIZE
);
1132 BOOT_DEBUG("stage2 buffer size = %d (%d sectors)\n", stage2
->buf_size
,
1133 stage2
->buf_size
/ SECTOR_SIZE
);
1135 stage2
->buf
= malloc(stage2
->buf_size
);
1136 if (stage2
->buf
== NULL
) {
1137 perror(gettext("Memory allocation failed"));
1141 stage2
->file
= stage2
->buf
;
1144 * Extra information (e.g. the versioning structure) is placed at the
1145 * end of stage2, aligned on a 8-byte boundary.
1147 if (!(is_bootpar(device
->type
)))
1148 stage2
->extra
= stage2
->file
+ P2ROUNDUP(stage2
->file_size
, 8);
1150 if (lseek(fd
, 0, SEEK_SET
) == -1) {
1155 if (read(fd
, stage2
->file
, stage2
->file_size
) < 0) {
1156 perror(gettext("unable to read stage2"));
1161 return (BC_SUCCESS
);
1173 prepare_stage1(ig_data_t
*install
)
1175 ig_device_t
*device
= &install
->device
;
1177 assert(install
!= NULL
);
1179 /* If PCFS add the BIOS Parameter Block. */
1180 if (is_bootpar(device
->type
)) {
1181 char bpb_sect
[SECTOR_SIZE
];
1183 if (pread(device
->part_fd
, bpb_sect
, SECTOR_SIZE
, 0)
1185 (void) fprintf(stderr
, READ_FAIL_BPB
);
1188 bcopy(bpb_sect
+ STAGE1_BPB_OFFSET
,
1189 install
->stage1_buf
+ STAGE1_BPB_OFFSET
, STAGE1_BPB_SIZE
);
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
))
1201 *((ushort_t
*)(install
->stage1_buf
+ STAGE1_STAGE2_SEGMENT
))
1202 = STAGE2_MEMADDR
>> 4;
1204 return (BC_SUCCESS
);
1208 * Grab stage1 from the specified device file descriptor.
1211 read_stage1_from_disk(int dev_fd
, char *stage1_buf
)
1213 assert(stage1_buf
!= NULL
);
1215 if (read_in(dev_fd
, stage1_buf
, SECTOR_SIZE
, 0) != BC_SUCCESS
) {
1216 perror(gettext("Unable to read stage1 from disk"));
1219 return (BC_SUCCESS
);
1223 read_stage2_from_disk(int dev_fd
, ig_stage2_t
*stage2
, int type
)
1228 multiboot_header_t
*mboot
;
1230 assert(stage2
!= NULL
);
1231 assert(dev_fd
!= -1);
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"));
1239 /* No multiboot means no chance of knowing stage2 size */
1240 if (find_multiboot(mboot_scan
, sizeof (mboot_scan
), &mboot_off
)
1242 BOOT_DEBUG("Unable to find multiboot header\n");
1243 return (BC_NOEXTRA
);
1245 mboot
= (multiboot_header_t
*)(mboot_scan
+ mboot_off
);
1248 * Unfilled mboot values mean an older version of installgrub installed
1249 * the stage2. Again we have no chance of knowing stage2 size.
1251 if (mboot
->load_end_addr
== 0 ||
1252 mboot
->load_end_addr
< mboot
->load_addr
)
1253 return (BC_NOEXTRA
);
1256 * Currently, the amount of space reserved for extra information
1257 * is "fixed". We may have to scan for the terminating extra payload
1260 size
= mboot
->load_end_addr
- mboot
->load_addr
;
1261 buf_size
= P2ROUNDUP(size
+ SECTOR_SIZE
, SECTOR_SIZE
);
1263 stage2
->buf
= malloc(buf_size
);
1264 if (stage2
->buf
== NULL
) {
1265 perror(gettext("Memory allocation failed"));
1268 stage2
->buf_size
= buf_size
;
1270 if (read_in(dev_fd
, stage2
->buf
, buf_size
, STAGE2_BLKOFF(type
) *
1271 SECTOR_SIZE
) != BC_SUCCESS
) {
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);
1285 return (BC_SUCCESS
);
1289 is_update_necessary(ig_data_t
*data
, char *updt_str
)
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
;
1298 assert(data
!= NULL
);
1299 assert(device
->part_fd
!= -1);
1301 bzero(&stage2_disk
, sizeof (ig_stage2_t
));
1303 /* Gather stage2 (if present) from the target device. */
1304 if (read_stage2_from_disk(dev_fd
, &stage2_disk
, device
->type
)
1306 BOOT_DEBUG("Unable to read stage2 from %s\n", device
->path
);
1307 BOOT_DEBUG("No multiboot wrapped stage2 on %s\n", device
->path
);
1312 * Look for the extended information structure in the extra payload
1315 einfo
= find_einfo(stage2_disk
.extra
, stage2_disk
.extra_size
);
1316 if (einfo
== NULL
) {
1317 BOOT_DEBUG("No extended information available\n");
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
);
1329 BOOT_DEBUG("Forcing update of %s bootblock\n", device
->path
);
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
;
1337 return (einfo_should_update(einfo
, &stage2_hs
, updt_str
));
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))
1346 prepare_stage2(ig_data_t
*install
, char *updt_str
)
1348 ig_device_t
*device
= &install
->device
;
1349 ig_stage2_t
*stage2
= &install
->stage2
;
1350 uint32_t mboot_off
= 0;
1352 assert(install
!= NULL
);
1353 assert(stage2
->file
!= NULL
);
1355 /* New stage2 files come with an embedded stage2. */
1356 if (find_multiboot(stage2
->file
, stage2
->file_size
, &mboot_off
)
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
;
1366 /* Keep track of where the multiboot header is. */
1367 stage2
->mboot_off
= mboot_off
;
1368 stage2
->mboot
= (multiboot_header_t
*)(stage2
->file
+
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.
1377 add_stage2_einfo(stage2
, updt_str
);
1380 * Fill multiboot information. We add them even without
1381 * versioning to support as much as possible mirroring.
1383 prepare_fake_multiboot(stage2
);
1386 if (is_bootpar(device
->type
)) {
1387 uint32_t blocklist
[SECTOR_SIZE
/ sizeof (uint32_t)];
1388 uint32_t install_addr
= STAGE2_MEMADDR
+ SECTOR_SIZE
;
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"));
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
);
1405 if (blocklist
[1] > 1) {
1412 stage2
->pcfs_first_sectors
[1] = blocklist
[i
];
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
);
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
;
1429 stage2
->first_sector
= device
->start_sector
+
1430 STAGE2_BLKOFF(device
->type
);
1431 BOOT_DEBUG("stage2 first sector: %d\n", stage2
->first_sector
);
1433 * In a solaris partition, stage2 is written to contiguous
1434 * blocks. So we update the starting block only.
1436 *((ulong_t
*)(stage2
->file
+ STAGE2_BLOCKLIST
)) =
1437 stage2
->first_sector
+ 1;
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;
1445 return (BC_SUCCESS
);
1449 find_x86_bootpar(struct mboot
*mboot
, int *part_num
, uint32_t *start_sect
)
1453 for (i
= 0; i
< FD_NUMPART
; i
++) {
1456 part
= (struct ipart
*)mboot
->parts
+ i
;
1457 if (part
->systid
== 0xbe) {
1459 *start_sect
= part
->relsect
;
1462 /* solaris boot part */
1463 return (BC_SUCCESS
);
1470 get_raw_partition_path(ig_device_t
*device
)
1475 if (is_bootpar(device
->type
)) {
1477 struct mboot
*mboot
;
1479 mboot
= (struct mboot
*)device
->boot_sector
;
1480 if (find_x86_bootpar(mboot
, &part
, NULL
) != BC_SUCCESS
) {
1481 (void) fprintf(stderr
, BOOTPAR_NOTFOUND
,
1486 raw
= strdup(device
->path_p0
);
1488 perror(gettext("Memory allocation failed"));
1492 raw
[strlen(raw
) - 2] = '1' + part
;
1496 /* For disk, remember slice and return whole fdisk partition */
1497 raw
= strdup(device
->path
);
1499 perror(gettext("Memory allocation failed"));
1504 if (!is_efi(device
->type
) &&
1505 (raw
[len
- 2] != 's' || raw
[len
- 1] == '2')) {
1506 (void) fprintf(stderr
, NOT_ROOT_SLICE
);
1510 device
->slice
= atoi(&raw
[len
- 1]);
1512 if (!is_efi(device
->type
)) {
1521 get_raw_partition_fd(ig_device_t
*device
)
1523 struct stat stat
= {0};
1526 raw
= get_raw_partition_path(device
);
1531 device
->part_fd
= open(raw
, O_RDONLY
);
1533 device
->part_fd
= open(raw
, O_RDWR
);
1535 if (device
->part_fd
< 0 || fstat(device
->part_fd
, &stat
) != 0) {
1536 (void) fprintf(stderr
, OPEN_FAIL
, raw
);
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;
1550 return (BC_SUCCESS
);
1553 #define TMP_MNTPT "/tmp/installgrub_pcfs"
1555 copy_stage2_to_pcfs(ig_data_t
*install
)
1559 int status
= BC_ERROR
;
1560 char buf
[SECTOR_SIZE
];
1562 struct mnttab mp
= {0}, mpref
= {0};
1563 ig_device_t
*device
= &install
->device
;
1564 ig_stage2_t
*stage2
= &install
->stage2
;
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');
1571 (void) fprintf(stderr
, CONVERT_FAIL
, device
->path
);
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");
1585 mpref
.mnt_special
= buf
;
1586 if (getmntany(mntfp
, &mp
, &mpref
) != 0) {
1589 /* not mounted, try remount */
1590 (void) mkdir(TMP_MNTPT
, S_IRWXU
);
1591 (void) snprintf(cmd
, sizeof (cmd
), "mount -F pcfs %s %s",
1595 bzero(&mp
, sizeof (mp
));
1596 if (getmntany(mntfp
, &mp
, &mpref
) != 0) {
1597 (void) fprintf(stderr
, MOUNT_FAIL
, buf
);
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
);
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
);
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"));
1623 status
= BC_SUCCESS
;
1625 (void) close(pcfs_fp
);
1627 (void) umount(TMP_MNTPT
);
1628 (void) rmdir(TMP_MNTPT
);