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