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