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