17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5d33344bbSsy  * Common Development and Distribution License (the "License").
6d33344bbSsy  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*af28f636SEnrico Perla - Sun Microsystems  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate #include <stdio.h>
267c478bd9Sstevel@tonic-gate #include <stdlib.h>
277c478bd9Sstevel@tonic-gate #include <libgen.h>
287c478bd9Sstevel@tonic-gate #include <malloc.h>
297c478bd9Sstevel@tonic-gate #include <string.h>
307c478bd9Sstevel@tonic-gate #include <fcntl.h>
317c478bd9Sstevel@tonic-gate #include <unistd.h>
327c478bd9Sstevel@tonic-gate #include <strings.h>
33*af28f636SEnrico Perla - Sun Microsystems #include <libintl.h>
34*af28f636SEnrico Perla - Sun Microsystems #include <locale.h>
35*af28f636SEnrico Perla - Sun Microsystems #include <errno.h>
36*af28f636SEnrico Perla - Sun Microsystems #include <libfdisk.h>
37*af28f636SEnrico Perla - Sun Microsystems #include <stdarg.h>
38*af28f636SEnrico Perla - Sun Microsystems #include <assert.h>
39*af28f636SEnrico Perla - Sun Microsystems 
407c478bd9Sstevel@tonic-gate #include <sys/mount.h>
417c478bd9Sstevel@tonic-gate #include <sys/mnttab.h>
427c478bd9Sstevel@tonic-gate #include <sys/dktp/fdisk.h>
43d33344bbSsy #include <sys/dkio.h>
44d33344bbSsy #include <sys/vtoc.h>
45*af28f636SEnrico Perla - Sun Microsystems #include <sys/types.h>
46*af28f636SEnrico Perla - Sun Microsystems #include <sys/stat.h>
47*af28f636SEnrico Perla - Sun Microsystems #include <sys/multiboot.h>
48*af28f636SEnrico Perla - Sun Microsystems #include <sys/sysmacros.h>
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate #include "message.h"
51*af28f636SEnrico Perla - Sun Microsystems #include "installgrub.h"
52*af28f636SEnrico Perla - Sun Microsystems #include "./../common/bblk_einfo.h"
53*af28f636SEnrico Perla - Sun Microsystems #include "./../common/boot_utils.h"
54*af28f636SEnrico Perla - Sun Microsystems #include "./../common/mboot_extra.h"
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate #ifndef	TEXT_DOMAIN
577c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"SUNW_OST_OSCMD"
587c478bd9Sstevel@tonic-gate #endif
597c478bd9Sstevel@tonic-gate 
60*af28f636SEnrico Perla - Sun Microsystems /*
61*af28f636SEnrico Perla - Sun Microsystems  * Variables to track installgrub desired mode of operation.
62*af28f636SEnrico Perla - Sun Microsystems  * 'nowrite' and 'boot_debug' come from boot_common.h.
63*af28f636SEnrico Perla - Sun Microsystems  */
64*af28f636SEnrico Perla - Sun Microsystems static boolean_t write_mbr = B_FALSE;
65*af28f636SEnrico Perla - Sun Microsystems static boolean_t force_mbr = B_FALSE;
66*af28f636SEnrico Perla - Sun Microsystems static boolean_t force_update = B_FALSE;
67*af28f636SEnrico Perla - Sun Microsystems static boolean_t do_getinfo = B_FALSE;
68*af28f636SEnrico Perla - Sun Microsystems static boolean_t do_version = B_FALSE;
69*af28f636SEnrico Perla - Sun Microsystems static boolean_t do_mirror_bblk = B_FALSE;
70*af28f636SEnrico Perla - Sun Microsystems static boolean_t strip = B_FALSE;
71*af28f636SEnrico Perla - Sun Microsystems static boolean_t verbose_dump = B_FALSE;
72*af28f636SEnrico Perla - Sun Microsystems 
73*af28f636SEnrico Perla - Sun Microsystems /* Installing the bootblock is the default operation. */
74*af28f636SEnrico Perla - Sun Microsystems static boolean_t do_install = B_TRUE;
75*af28f636SEnrico Perla - Sun Microsystems 
76*af28f636SEnrico Perla - Sun Microsystems /* Versioning string, if present. */
77*af28f636SEnrico Perla - Sun Microsystems static char *update_str;
78*af28f636SEnrico Perla - Sun Microsystems 
79*af28f636SEnrico Perla - Sun Microsystems /*
80*af28f636SEnrico Perla - Sun Microsystems  * Temporary buffer to store the first 32K of data looking for a multiboot
81*af28f636SEnrico Perla - Sun Microsystems  * signature.
82*af28f636SEnrico Perla - Sun Microsystems  */
83*af28f636SEnrico Perla - Sun Microsystems char	mboot_scan[MBOOT_SCAN_SIZE];
84*af28f636SEnrico Perla - Sun Microsystems 
85*af28f636SEnrico Perla - Sun Microsystems /* Function prototypes. */
86*af28f636SEnrico Perla - Sun Microsystems static void check_options(char *);
87*af28f636SEnrico Perla - Sun Microsystems static int handle_install(char *, char **);
88*af28f636SEnrico Perla - Sun Microsystems static int handle_mirror(char *, char **);
89*af28f636SEnrico Perla - Sun Microsystems static int handle_getinfo(char *, char **);
90*af28f636SEnrico Perla - Sun Microsystems static int commit_to_disk(ig_data_t *, char *);
91*af28f636SEnrico Perla - Sun Microsystems static int init_device(ig_device_t *, char *path);
92*af28f636SEnrico Perla - Sun Microsystems static void cleanup_device(ig_device_t *);
93*af28f636SEnrico Perla - Sun Microsystems static void cleanup_stage2(ig_stage2_t *);
94*af28f636SEnrico Perla - Sun Microsystems static int get_start_sector(ig_device_t *);
95*af28f636SEnrico Perla - Sun Microsystems static int get_disk_fd(ig_device_t *device);
96*af28f636SEnrico Perla - Sun Microsystems static int get_raw_partition_fd(ig_device_t *);
97*af28f636SEnrico Perla - Sun Microsystems static char *get_raw_partition_path(ig_device_t *);
98*af28f636SEnrico Perla - Sun Microsystems static boolean_t gather_stage2_from_dev(ig_data_t *);
99*af28f636SEnrico Perla - Sun Microsystems static int propagate_bootblock(ig_data_t *, ig_data_t *, char *);
100*af28f636SEnrico Perla - Sun Microsystems static int find_x86_bootpar(struct mboot *, int *, uint32_t *);
101*af28f636SEnrico Perla - Sun Microsystems static int copy_stage2_to_pcfs(ig_data_t *);
102*af28f636SEnrico Perla - Sun Microsystems static int write_stage2(ig_data_t *);
103*af28f636SEnrico Perla - Sun Microsystems static int write_stage1(ig_data_t *);
1047c478bd9Sstevel@tonic-gate static void usage(char *);
105*af28f636SEnrico Perla - Sun Microsystems static int read_stage1_from_file(char *, ig_data_t *);
106*af28f636SEnrico Perla - Sun Microsystems static int read_stage2_from_file(char *, ig_data_t *);
107*af28f636SEnrico Perla - Sun Microsystems static int read_stage1_from_disk(int, char *);
108*af28f636SEnrico Perla - Sun Microsystems static int read_stage2_from_disk(int, ig_stage2_t *);
109*af28f636SEnrico Perla - Sun Microsystems static int prepare_stage1(ig_data_t *);
110*af28f636SEnrico Perla - Sun Microsystems static int prepare_stage2(ig_data_t *, char *);
111*af28f636SEnrico Perla - Sun Microsystems static void prepare_fake_multiboot(ig_stage2_t *);
112*af28f636SEnrico Perla - Sun Microsystems static void add_stage2_einfo(ig_stage2_t *, char *updt_str);
113*af28f636SEnrico Perla - Sun Microsystems static boolean_t is_update_necessary(ig_data_t *, char *);
1147c478bd9Sstevel@tonic-gate 
115342440ecSPrasad Singamsetty extern int read_stage2_blocklist(int, unsigned int *);
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate int
1187c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
1197c478bd9Sstevel@tonic-gate {
120*af28f636SEnrico Perla - Sun Microsystems 	int	opt;
121*af28f636SEnrico Perla - Sun Microsystems 	int	params = 3;
122*af28f636SEnrico Perla - Sun Microsystems 	int	ret;
123*af28f636SEnrico Perla - Sun Microsystems 	char	**handle_args;
124*af28f636SEnrico Perla - Sun Microsystems 	char	*progname;
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
1277c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
1287c478bd9Sstevel@tonic-gate 
129*af28f636SEnrico Perla - Sun Microsystems 	/*
130*af28f636SEnrico Perla - Sun Microsystems 	 * retro-compatibility: installing the bootblock is the default
131*af28f636SEnrico Perla - Sun Microsystems 	 * and there is no switch for it.
132*af28f636SEnrico Perla - Sun Microsystems 	 */
133*af28f636SEnrico Perla - Sun Microsystems 	do_install = B_TRUE;
134*af28f636SEnrico Perla - Sun Microsystems 
135*af28f636SEnrico Perla - Sun Microsystems 	while ((opt = getopt(argc, argv, "dVMFfmneiu:")) != EOF) {
1367c478bd9Sstevel@tonic-gate 		switch (opt) {
1377c478bd9Sstevel@tonic-gate 		case 'm':
138*af28f636SEnrico Perla - Sun Microsystems 			write_mbr = B_TRUE;
1397c478bd9Sstevel@tonic-gate 			break;
1407c478bd9Sstevel@tonic-gate 		case 'n':
141*af28f636SEnrico Perla - Sun Microsystems 			nowrite = B_TRUE;
1427c478bd9Sstevel@tonic-gate 			break;
1437c478bd9Sstevel@tonic-gate 		case 'f':
144*af28f636SEnrico Perla - Sun Microsystems 			force_mbr = B_TRUE;
1457c478bd9Sstevel@tonic-gate 			break;
1467ce76caaSEnrico Perla - Sun Microsystems 		case 'i':
147*af28f636SEnrico Perla - Sun Microsystems 			do_getinfo = B_TRUE;
148*af28f636SEnrico Perla - Sun Microsystems 			do_install = B_FALSE;
1497ce76caaSEnrico Perla - Sun Microsystems 			params = 1;
1507ce76caaSEnrico Perla - Sun Microsystems 			break;
151*af28f636SEnrico Perla - Sun Microsystems 		case 'V':
152*af28f636SEnrico Perla - Sun Microsystems 			verbose_dump = B_TRUE;
153*af28f636SEnrico Perla - Sun Microsystems 			break;
154*af28f636SEnrico Perla - Sun Microsystems 		case 'd':
155*af28f636SEnrico Perla - Sun Microsystems 			boot_debug = B_TRUE;
156*af28f636SEnrico Perla - Sun Microsystems 			break;
157*af28f636SEnrico Perla - Sun Microsystems 		case 'F':
158*af28f636SEnrico Perla - Sun Microsystems 			force_update = B_TRUE;
159*af28f636SEnrico Perla - Sun Microsystems 			break;
1607ce76caaSEnrico Perla - Sun Microsystems 		case 'e':
161*af28f636SEnrico Perla - Sun Microsystems 			strip = B_TRUE;
162*af28f636SEnrico Perla - Sun Microsystems 			break;
163*af28f636SEnrico Perla - Sun Microsystems 		case 'M':
164*af28f636SEnrico Perla - Sun Microsystems 			do_mirror_bblk = B_TRUE;
165*af28f636SEnrico Perla - Sun Microsystems 			do_install = B_FALSE;
166*af28f636SEnrico Perla - Sun Microsystems 			params = 2;
1677ce76caaSEnrico Perla - Sun Microsystems 			break;
168*af28f636SEnrico Perla - Sun Microsystems 		case 'u':
169*af28f636SEnrico Perla - Sun Microsystems 			do_version = B_TRUE;
170*af28f636SEnrico Perla - Sun Microsystems 
171*af28f636SEnrico Perla - Sun Microsystems 			update_str = malloc(strlen(optarg) + 1);
172*af28f636SEnrico Perla - Sun Microsystems 			if (update_str == NULL) {
173*af28f636SEnrico Perla - Sun Microsystems 				(void) fprintf(stderr, gettext("Unable to "
174*af28f636SEnrico Perla - Sun Microsystems 				    "allocate memory\n"));
175*af28f636SEnrico Perla - Sun Microsystems 				exit(BC_ERROR);
176*af28f636SEnrico Perla - Sun Microsystems 			}
177*af28f636SEnrico Perla - Sun Microsystems 			(void) strlcpy(update_str, optarg, strlen(optarg) + 1);
1787ce76caaSEnrico Perla - Sun Microsystems 			break;
1797c478bd9Sstevel@tonic-gate 		default:
1807c478bd9Sstevel@tonic-gate 			/* fall through to process non-optional args */
1817c478bd9Sstevel@tonic-gate 			break;
1827c478bd9Sstevel@tonic-gate 		}
1837c478bd9Sstevel@tonic-gate 	}
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 	/* check arguments */
1867ce76caaSEnrico Perla - Sun Microsystems 	if (argc != optind + params) {
1877c478bd9Sstevel@tonic-gate 		usage(argv[0]);
188*af28f636SEnrico Perla - Sun Microsystems 		exit(BC_ERROR);
1897c478bd9Sstevel@tonic-gate 	}
1907c478bd9Sstevel@tonic-gate 
191*af28f636SEnrico Perla - Sun Microsystems 	/*
192*af28f636SEnrico Perla - Sun Microsystems 	 * clean up options (and bail out if an unrecoverable combination is
193*af28f636SEnrico Perla - Sun Microsystems 	 * requested.
194*af28f636SEnrico Perla - Sun Microsystems 	 */
195*af28f636SEnrico Perla - Sun Microsystems 	progname = argv[0];
196*af28f636SEnrico Perla - Sun Microsystems 	check_options(progname);
197*af28f636SEnrico Perla - Sun Microsystems 	handle_args = argv + optind;
198*af28f636SEnrico Perla - Sun Microsystems 
199*af28f636SEnrico Perla - Sun Microsystems 	if (nowrite)
2007c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout, DRY_RUN);
201*af28f636SEnrico Perla - Sun Microsystems 
202*af28f636SEnrico Perla - Sun Microsystems 	if (do_getinfo) {
203*af28f636SEnrico Perla - Sun Microsystems 		ret = handle_getinfo(progname, handle_args);
204*af28f636SEnrico Perla - Sun Microsystems 	} else if (do_mirror_bblk) {
205*af28f636SEnrico Perla - Sun Microsystems 		ret = handle_mirror(progname, handle_args);
206*af28f636SEnrico Perla - Sun Microsystems 	} else {
207*af28f636SEnrico Perla - Sun Microsystems 		ret = handle_install(progname, handle_args);
208*af28f636SEnrico Perla - Sun Microsystems 	}
209*af28f636SEnrico Perla - Sun Microsystems 	return (ret);
210*af28f636SEnrico Perla - Sun Microsystems }
211*af28f636SEnrico Perla - Sun Microsystems 
212*af28f636SEnrico Perla - Sun Microsystems #define	MEANINGLESS_OPT	gettext("%s specified but meaningless, ignoring\n")
213*af28f636SEnrico Perla - Sun Microsystems static void
214*af28f636SEnrico Perla - Sun Microsystems check_options(char *progname)
215*af28f636SEnrico Perla - Sun Microsystems {
216*af28f636SEnrico Perla - Sun Microsystems 	if (do_getinfo && do_mirror_bblk) {
217*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Only one of -M and -i can be "
218*af28f636SEnrico Perla - Sun Microsystems 		    "specified at the same time\n"));
219*af28f636SEnrico Perla - Sun Microsystems 		usage(progname);
220*af28f636SEnrico Perla - Sun Microsystems 		exit(BC_ERROR);
2217c478bd9Sstevel@tonic-gate 	}
2227c478bd9Sstevel@tonic-gate 
223*af28f636SEnrico Perla - Sun Microsystems 	if (do_mirror_bblk) {
224*af28f636SEnrico Perla - Sun Microsystems 		/*
225*af28f636SEnrico Perla - Sun Microsystems 		 * -u and -F may actually reflect a user intent that is not
226*af28f636SEnrico Perla - Sun Microsystems 		 * correct with this command (mirror can be interpreted
227*af28f636SEnrico Perla - Sun Microsystems 		 * "similar" to install. Emit a message and continue.
228*af28f636SEnrico Perla - Sun Microsystems 		 * -e and -V have no meaning, be quiet here and only report the
229*af28f636SEnrico Perla - Sun Microsystems 		 * incongruence if a debug output is requested.
230*af28f636SEnrico Perla - Sun Microsystems 		 */
231*af28f636SEnrico Perla - Sun Microsystems 		if (do_version) {
232*af28f636SEnrico Perla - Sun Microsystems 			(void) fprintf(stderr, MEANINGLESS_OPT, "-u");
233*af28f636SEnrico Perla - Sun Microsystems 			do_version = B_FALSE;
234*af28f636SEnrico Perla - Sun Microsystems 		}
235*af28f636SEnrico Perla - Sun Microsystems 		if (force_update) {
236*af28f636SEnrico Perla - Sun Microsystems 			(void) fprintf(stderr, MEANINGLESS_OPT, "-F");
237*af28f636SEnrico Perla - Sun Microsystems 			force_update = B_FALSE;
2387ce76caaSEnrico Perla - Sun Microsystems 		}
239*af28f636SEnrico Perla - Sun Microsystems 		if (strip || verbose_dump) {
240*af28f636SEnrico Perla - Sun Microsystems 			BOOT_DEBUG(MEANINGLESS_OPT, "-e|-V");
241*af28f636SEnrico Perla - Sun Microsystems 			strip = B_FALSE;
242*af28f636SEnrico Perla - Sun Microsystems 			verbose_dump = B_FALSE;
243*af28f636SEnrico Perla - Sun Microsystems 		}
244*af28f636SEnrico Perla - Sun Microsystems 	}
2457c478bd9Sstevel@tonic-gate 
246*af28f636SEnrico Perla - Sun Microsystems 	if (do_getinfo) {
247*af28f636SEnrico Perla - Sun Microsystems 		if (write_mbr || force_mbr || do_version || force_update) {
248*af28f636SEnrico Perla - Sun Microsystems 			BOOT_DEBUG(MEANINGLESS_OPT, "-m|-f|-u|-F");
249*af28f636SEnrico Perla - Sun Microsystems 			write_mbr = force_mbr = do_version = B_FALSE;
250*af28f636SEnrico Perla - Sun Microsystems 			force_update = B_FALSE;
2517ce76caaSEnrico Perla - Sun Microsystems 		}
2527c478bd9Sstevel@tonic-gate 	}
253*af28f636SEnrico Perla - Sun Microsystems }
2547c478bd9Sstevel@tonic-gate 
255*af28f636SEnrico Perla - Sun Microsystems /*
256*af28f636SEnrico Perla - Sun Microsystems  * Install a new stage1/stage2 pair on the specified device. handle_install()
257*af28f636SEnrico Perla - Sun Microsystems  * expects argv to contain 3 parameters (the path to stage1, the path to stage2,
258*af28f636SEnrico Perla - Sun Microsystems  * the target device).
259*af28f636SEnrico Perla - Sun Microsystems  *
260*af28f636SEnrico Perla - Sun Microsystems  * Returns:	BC_SUCCESS - if the installation is successful
261*af28f636SEnrico Perla - Sun Microsystems  *		BC_ERROR   - if the installation failed
262*af28f636SEnrico Perla - Sun Microsystems  *		BC_NOUPDT  - if no installation was performed because the GRUB
263*af28f636SEnrico Perla - Sun Microsystems  *		             version currently installed is more recent than the
264*af28f636SEnrico Perla - Sun Microsystems  *			     supplied one.
265*af28f636SEnrico Perla - Sun Microsystems  *
266*af28f636SEnrico Perla - Sun Microsystems  */
267*af28f636SEnrico Perla - Sun Microsystems static int
268*af28f636SEnrico Perla - Sun Microsystems handle_install(char *progname, char **argv)
269*af28f636SEnrico Perla - Sun Microsystems {
270*af28f636SEnrico Perla - Sun Microsystems 	ig_data_t	install_data;
271*af28f636SEnrico Perla - Sun Microsystems 	char		*stage1_path = NULL;
272*af28f636SEnrico Perla - Sun Microsystems 	char		*stage2_path = NULL;
273*af28f636SEnrico Perla - Sun Microsystems 	char		*device_path = NULL;
274*af28f636SEnrico Perla - Sun Microsystems 	int		ret = BC_ERROR;
275*af28f636SEnrico Perla - Sun Microsystems 
276*af28f636SEnrico Perla - Sun Microsystems 	stage1_path = strdup(argv[0]);
277*af28f636SEnrico Perla - Sun Microsystems 	stage2_path = strdup(argv[1]);
278*af28f636SEnrico Perla - Sun Microsystems 	device_path = strdup(argv[2]);
279*af28f636SEnrico Perla - Sun Microsystems 
280*af28f636SEnrico Perla - Sun Microsystems 	bzero(&install_data, sizeof (ig_data_t));
281*af28f636SEnrico Perla - Sun Microsystems 
282*af28f636SEnrico Perla - Sun Microsystems 	if (!stage1_path || !stage2_path || !device_path) {
283*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Missing parameter"));
284*af28f636SEnrico Perla - Sun Microsystems 		usage(progname);
285*af28f636SEnrico Perla - Sun Microsystems 		goto out;
286*af28f636SEnrico Perla - Sun Microsystems 	}
2877c478bd9Sstevel@tonic-gate 
288*af28f636SEnrico Perla - Sun Microsystems 	BOOT_DEBUG("stage1 path: %s, stage2 path: %s, device: %s\n",
289*af28f636SEnrico Perla - Sun Microsystems 	    stage1_path, stage2_path, device_path);
290*af28f636SEnrico Perla - Sun Microsystems 
291*af28f636SEnrico Perla - Sun Microsystems 	if (init_device(&install_data.device, device_path) != BC_SUCCESS) {
292*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Unable to gather device "
293*af28f636SEnrico Perla - Sun Microsystems 		    "information for %s\n"), device_path);
294*af28f636SEnrico Perla - Sun Microsystems 		goto out;
295*af28f636SEnrico Perla - Sun Microsystems 	}
296*af28f636SEnrico Perla - Sun Microsystems 
297*af28f636SEnrico Perla - Sun Microsystems 	/* read in stage1 and stage2. */
298*af28f636SEnrico Perla - Sun Microsystems 	if (read_stage1_from_file(stage1_path, &install_data) != BC_SUCCESS) {
299*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Error opening %s\n"),
300*af28f636SEnrico Perla - Sun Microsystems 		    stage1_path);
301*af28f636SEnrico Perla - Sun Microsystems 		goto out_dev;
3027ce76caaSEnrico Perla - Sun Microsystems 	}
3037ce76caaSEnrico Perla - Sun Microsystems 
304*af28f636SEnrico Perla - Sun Microsystems 	if (read_stage2_from_file(stage2_path, &install_data) != BC_SUCCESS) {
305*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Error opening %s\n"),
306*af28f636SEnrico Perla - Sun Microsystems 		    stage2_path);
307*af28f636SEnrico Perla - Sun Microsystems 		goto out_dev;
308*af28f636SEnrico Perla - Sun Microsystems 	}
3097c478bd9Sstevel@tonic-gate 
310*af28f636SEnrico Perla - Sun Microsystems 	/* We do not support versioning on PCFS. */
311*af28f636SEnrico Perla - Sun Microsystems 	if (is_bootpar(install_data.device.type) && do_version)
312*af28f636SEnrico Perla - Sun Microsystems 		do_version = B_FALSE;
3137ce76caaSEnrico Perla - Sun Microsystems 
314*af28f636SEnrico Perla - Sun Microsystems 	/*
315*af28f636SEnrico Perla - Sun Microsystems 	 * is_update_necessary() will take care of checking if versioning and/or
316*af28f636SEnrico Perla - Sun Microsystems 	 * forcing the update have been specified. It will also emit a warning
317*af28f636SEnrico Perla - Sun Microsystems 	 * if a non-versioned update is attempted over a versioned bootblock.
318*af28f636SEnrico Perla - Sun Microsystems 	 */
319*af28f636SEnrico Perla - Sun Microsystems 	if (!is_update_necessary(&install_data, update_str)) {
320*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("GRUB version installed "
321*af28f636SEnrico Perla - Sun Microsystems 		    "on %s is more recent or identical\n"
322*af28f636SEnrico Perla - Sun Microsystems 		    "Use -F to override or install without the -u option\n"),
323*af28f636SEnrico Perla - Sun Microsystems 		    device_path);
324*af28f636SEnrico Perla - Sun Microsystems 		ret = BC_NOUPDT;
325*af28f636SEnrico Perla - Sun Microsystems 		goto out_dev;
3267c478bd9Sstevel@tonic-gate 	}
327*af28f636SEnrico Perla - Sun Microsystems 	/*
328*af28f636SEnrico Perla - Sun Microsystems 	 * We get here if:
329*af28f636SEnrico Perla - Sun Microsystems 	 * - the installed GRUB version is older than the one about to be
330*af28f636SEnrico Perla - Sun Microsystems 	 *   installed.
331*af28f636SEnrico Perla - Sun Microsystems 	 * - no versioning string has been passed through the command line.
332*af28f636SEnrico Perla - Sun Microsystems 	 * - a forced update is requested (-F).
333*af28f636SEnrico Perla - Sun Microsystems 	 */
334*af28f636SEnrico Perla - Sun Microsystems 	BOOT_DEBUG("Ready to commit to disk\n");
335*af28f636SEnrico Perla - Sun Microsystems 	ret = commit_to_disk(&install_data, update_str);
336*af28f636SEnrico Perla - Sun Microsystems 
337*af28f636SEnrico Perla - Sun Microsystems out_dev:
338*af28f636SEnrico Perla - Sun Microsystems 	cleanup_device(&install_data.device);
339*af28f636SEnrico Perla - Sun Microsystems out:
340*af28f636SEnrico Perla - Sun Microsystems 	free(stage1_path);
341*af28f636SEnrico Perla - Sun Microsystems 	free(stage2_path);
342*af28f636SEnrico Perla - Sun Microsystems 	free(device_path);
343*af28f636SEnrico Perla - Sun Microsystems 	return (ret);
344*af28f636SEnrico Perla - Sun Microsystems }
3457c478bd9Sstevel@tonic-gate 
346*af28f636SEnrico Perla - Sun Microsystems /*
347*af28f636SEnrico Perla - Sun Microsystems  * Retrieves from a device the extended information (einfo) associated to the
348*af28f636SEnrico Perla - Sun Microsystems  * installed stage2.
349*af28f636SEnrico Perla - Sun Microsystems  * Expects one parameter, the device path, in the form: /dev/rdsk/c?[t?]d?s0.
350*af28f636SEnrico Perla - Sun Microsystems  * Returns:
351*af28f636SEnrico Perla - Sun Microsystems  *        - BC_SUCCESS (and prints out einfo contents depending on 'flags')
352*af28f636SEnrico Perla - Sun Microsystems  *	  - BC_ERROR (on error)
353*af28f636SEnrico Perla - Sun Microsystems  *        - BC_NOEINFO (no extended information available)
354*af28f636SEnrico Perla - Sun Microsystems  */
355*af28f636SEnrico Perla - Sun Microsystems static int
356*af28f636SEnrico Perla - Sun Microsystems handle_getinfo(char *progname, char **argv)
357*af28f636SEnrico Perla - Sun Microsystems {
358*af28f636SEnrico Perla - Sun Microsystems 	ig_data_t	data;
359*af28f636SEnrico Perla - Sun Microsystems 	ig_stage2_t	*stage2 = &data.stage2;
360*af28f636SEnrico Perla - Sun Microsystems 	ig_device_t	*device = &data.device;
361*af28f636SEnrico Perla - Sun Microsystems 	bblk_einfo_t	*einfo;
362*af28f636SEnrico Perla - Sun Microsystems 	uint8_t		flags = 0;
363*af28f636SEnrico Perla - Sun Microsystems 	uint32_t	size;
364*af28f636SEnrico Perla - Sun Microsystems 	char		*device_path;
365*af28f636SEnrico Perla - Sun Microsystems 	int		retval = BC_ERROR;
366*af28f636SEnrico Perla - Sun Microsystems 	int		ret;
367*af28f636SEnrico Perla - Sun Microsystems 
368*af28f636SEnrico Perla - Sun Microsystems 	device_path = strdup(argv[0]);
369*af28f636SEnrico Perla - Sun Microsystems 	if (!device_path) {
370*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Missing parameter"));
371*af28f636SEnrico Perla - Sun Microsystems 		usage(progname);
372*af28f636SEnrico Perla - Sun Microsystems 		goto out;
373*af28f636SEnrico Perla - Sun Microsystems 	}
374*af28f636SEnrico Perla - Sun Microsystems 
375*af28f636SEnrico Perla - Sun Microsystems 	bzero(&data, sizeof (ig_data_t));
376*af28f636SEnrico Perla - Sun Microsystems 	BOOT_DEBUG("device path: %s\n", device_path);
3777c478bd9Sstevel@tonic-gate 
378*af28f636SEnrico Perla - Sun Microsystems 	if (init_device(device, device_path) != BC_SUCCESS) {
379*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Unable to gather device "
380*af28f636SEnrico Perla - Sun Microsystems 		    "information for %s\n"), device_path);
381*af28f636SEnrico Perla - Sun Microsystems 		goto out_dev;
382*af28f636SEnrico Perla - Sun Microsystems 	}
3837c478bd9Sstevel@tonic-gate 
384*af28f636SEnrico Perla - Sun Microsystems 	if (is_bootpar(device->type)) {
385*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Versioning not supported on "
386*af28f636SEnrico Perla - Sun Microsystems 		    "PCFS\n"));
387*af28f636SEnrico Perla - Sun Microsystems 		goto out_dev;
388*af28f636SEnrico Perla - Sun Microsystems 	}
3897c478bd9Sstevel@tonic-gate 
390*af28f636SEnrico Perla - Sun Microsystems 	ret = read_stage2_from_disk(device->part_fd, stage2);
391*af28f636SEnrico Perla - Sun Microsystems 	if (ret == BC_ERROR) {
392*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Error reading stage2 from "
393*af28f636SEnrico Perla - Sun Microsystems 		    "%s\n"), device_path);
394*af28f636SEnrico Perla - Sun Microsystems 		goto out_dev;
395*af28f636SEnrico Perla - Sun Microsystems 	}
3967ce76caaSEnrico Perla - Sun Microsystems 
397*af28f636SEnrico Perla - Sun Microsystems 	if (ret == BC_NOEXTRA) {
398*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, gettext("No multiboot header found on "
399*af28f636SEnrico Perla - Sun Microsystems 		    "%s, unable to locate extra information area\n"),
400*af28f636SEnrico Perla - Sun Microsystems 		    device_path);
401*af28f636SEnrico Perla - Sun Microsystems 		retval = BC_NOEINFO;
402*af28f636SEnrico Perla - Sun Microsystems 		goto out_dev;
403*af28f636SEnrico Perla - Sun Microsystems 	}
4047c478bd9Sstevel@tonic-gate 
405*af28f636SEnrico Perla - Sun Microsystems 	einfo = find_einfo(stage2->extra);
406*af28f636SEnrico Perla - Sun Microsystems 	if (einfo == NULL) {
407*af28f636SEnrico Perla - Sun Microsystems 		retval = BC_NOEINFO;
408*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("No extended information "
409*af28f636SEnrico Perla - Sun Microsystems 		    "found\n"));
410*af28f636SEnrico Perla - Sun Microsystems 		goto out_dev;
411*af28f636SEnrico Perla - Sun Microsystems 	}
412*af28f636SEnrico Perla - Sun Microsystems 
413*af28f636SEnrico Perla - Sun Microsystems 	/* Print the extended information. */
414*af28f636SEnrico Perla - Sun Microsystems 	if (strip)
415*af28f636SEnrico Perla - Sun Microsystems 		flags |= EINFO_EASY_PARSE;
416*af28f636SEnrico Perla - Sun Microsystems 	if (verbose_dump)
417*af28f636SEnrico Perla - Sun Microsystems 		flags |= EINFO_PRINT_HEADER;
418*af28f636SEnrico Perla - Sun Microsystems 
419*af28f636SEnrico Perla - Sun Microsystems 	size = stage2->buf_size - P2ROUNDUP(stage2->file_size, 8);
420*af28f636SEnrico Perla - Sun Microsystems 	print_einfo(flags, einfo, size);
421*af28f636SEnrico Perla - Sun Microsystems 	retval = BC_SUCCESS;
422*af28f636SEnrico Perla - Sun Microsystems 
423*af28f636SEnrico Perla - Sun Microsystems out_dev:
424*af28f636SEnrico Perla - Sun Microsystems 	cleanup_device(&data.device);
425*af28f636SEnrico Perla - Sun Microsystems out:
426*af28f636SEnrico Perla - Sun Microsystems 	free(device_path);
427*af28f636SEnrico Perla - Sun Microsystems 	return (retval);
4287c478bd9Sstevel@tonic-gate }
4297c478bd9Sstevel@tonic-gate 
430*af28f636SEnrico Perla - Sun Microsystems /*
431*af28f636SEnrico Perla - Sun Microsystems  * Attempt to mirror (propagate) the current stage2 over the attaching disk.
432*af28f636SEnrico Perla - Sun Microsystems  *
433*af28f636SEnrico Perla - Sun Microsystems  * Returns:
434*af28f636SEnrico Perla - Sun Microsystems  *	- BC_SUCCESS (a successful propagation happened)
435*af28f636SEnrico Perla - Sun Microsystems  *	- BC_ERROR (an error occurred)
436*af28f636SEnrico Perla - Sun Microsystems  *	- BC_NOEXTRA (it is not possible to dump the current bootblock since
437*af28f636SEnrico Perla - Sun Microsystems  *			there is no multiboot information)
438*af28f636SEnrico Perla - Sun Microsystems  */
439*af28f636SEnrico Perla - Sun Microsystems static int
440*af28f636SEnrico Perla - Sun Microsystems handle_mirror(char *progname, char **argv)
4417c478bd9Sstevel@tonic-gate {
442*af28f636SEnrico Perla - Sun Microsystems 	ig_data_t	curr_data;
443*af28f636SEnrico Perla - Sun Microsystems 	ig_data_t	attach_data;
444*af28f636SEnrico Perla - Sun Microsystems 	ig_device_t	*curr_device = &curr_data.device;
445*af28f636SEnrico Perla - Sun Microsystems 	ig_device_t	*attach_device = &attach_data.device;
446*af28f636SEnrico Perla - Sun Microsystems 	ig_stage2_t	*stage2_curr = &curr_data.stage2;
447*af28f636SEnrico Perla - Sun Microsystems 	ig_stage2_t	*stage2_attach = &attach_data.stage2;
448*af28f636SEnrico Perla - Sun Microsystems 	bblk_einfo_t	*einfo_curr = NULL;
449*af28f636SEnrico Perla - Sun Microsystems 	char		*curr_device_path;
450*af28f636SEnrico Perla - Sun Microsystems 	char		*attach_device_path;
451*af28f636SEnrico Perla - Sun Microsystems 	char		*updt_str = NULL;
452*af28f636SEnrico Perla - Sun Microsystems 	int		retval = BC_ERROR;
453*af28f636SEnrico Perla - Sun Microsystems 	int		ret;
454*af28f636SEnrico Perla - Sun Microsystems 
455*af28f636SEnrico Perla - Sun Microsystems 	curr_device_path = strdup(argv[0]);
456*af28f636SEnrico Perla - Sun Microsystems 	attach_device_path = strdup(argv[1]);
457*af28f636SEnrico Perla - Sun Microsystems 
458*af28f636SEnrico Perla - Sun Microsystems 	if (!curr_device_path || !attach_device_path) {
459*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Missing parameter"));
460*af28f636SEnrico Perla - Sun Microsystems 		usage(progname);
461*af28f636SEnrico Perla - Sun Microsystems 		goto out;
462*af28f636SEnrico Perla - Sun Microsystems 	}
463*af28f636SEnrico Perla - Sun Microsystems 	BOOT_DEBUG("Current device path is: %s, attaching device path is: "
464*af28f636SEnrico Perla - Sun Microsystems 	    " %s\n", curr_device_path, attach_device_path);
465*af28f636SEnrico Perla - Sun Microsystems 
466*af28f636SEnrico Perla - Sun Microsystems 	bzero(&curr_data, sizeof (ig_data_t));
467*af28f636SEnrico Perla - Sun Microsystems 	bzero(&attach_data, sizeof (ig_data_t));
468*af28f636SEnrico Perla - Sun Microsystems 
469*af28f636SEnrico Perla - Sun Microsystems 	if (init_device(curr_device, curr_device_path) != BC_SUCCESS) {
470*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Unable to gather device "
471*af28f636SEnrico Perla - Sun Microsystems 		    "information for %s (current device)\n"), curr_device_path);
472*af28f636SEnrico Perla - Sun Microsystems 		goto out_currdev;
473*af28f636SEnrico Perla - Sun Microsystems 	}
474*af28f636SEnrico Perla - Sun Microsystems 
475*af28f636SEnrico Perla - Sun Microsystems 	if (init_device(attach_device, attach_device_path) != BC_SUCCESS) {
476*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Unable to gather device "
477*af28f636SEnrico Perla - Sun Microsystems 		    "information for %s (attaching device)\n"),
478*af28f636SEnrico Perla - Sun Microsystems 		    attach_device_path);
479*af28f636SEnrico Perla - Sun Microsystems 		goto out_devs;
4807fc5d2a4SVikram Hegde 	}
4817fc5d2a4SVikram Hegde 
482*af28f636SEnrico Perla - Sun Microsystems 	if (is_bootpar(curr_device->type) || is_bootpar(attach_device->type)) {
483*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("boot block mirroring is not "
484*af28f636SEnrico Perla - Sun Microsystems 		    "supported on PCFS\n"));
485*af28f636SEnrico Perla - Sun Microsystems 		goto out_devs;
486*af28f636SEnrico Perla - Sun Microsystems 	}
487*af28f636SEnrico Perla - Sun Microsystems 
488*af28f636SEnrico Perla - Sun Microsystems 	ret = read_stage2_from_disk(curr_device->part_fd, stage2_curr);
489*af28f636SEnrico Perla - Sun Microsystems 	if (ret == BC_ERROR) {
490*af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("Error reading first stage2 blocks from %s\n",
491*af28f636SEnrico Perla - Sun Microsystems 		    curr_device->path);
492*af28f636SEnrico Perla - Sun Microsystems 		retval = BC_ERROR;
493*af28f636SEnrico Perla - Sun Microsystems 		goto out_devs;
494*af28f636SEnrico Perla - Sun Microsystems 	}
495*af28f636SEnrico Perla - Sun Microsystems 
496*af28f636SEnrico Perla - Sun Microsystems 	if (ret == BC_NOEXTRA) {
497*af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("No multiboot header found on %s, unable to grab "
498*af28f636SEnrico Perla - Sun Microsystems 		    "stage2\n", curr_device->path);
499*af28f636SEnrico Perla - Sun Microsystems 		retval = BC_NOEXTRA;
500*af28f636SEnrico Perla - Sun Microsystems 		goto out_devs;
501*af28f636SEnrico Perla - Sun Microsystems 	}
502*af28f636SEnrico Perla - Sun Microsystems 
503*af28f636SEnrico Perla - Sun Microsystems 	einfo_curr = find_einfo(stage2_curr->extra);
504*af28f636SEnrico Perla - Sun Microsystems 	if (einfo_curr != NULL)
505*af28f636SEnrico Perla - Sun Microsystems 		updt_str = einfo_get_string(einfo_curr);
506*af28f636SEnrico Perla - Sun Microsystems 
507*af28f636SEnrico Perla - Sun Microsystems 	write_mbr = B_TRUE;
508*af28f636SEnrico Perla - Sun Microsystems 	force_mbr = B_TRUE;
509*af28f636SEnrico Perla - Sun Microsystems 	retval = propagate_bootblock(&curr_data, &attach_data, updt_str);
510*af28f636SEnrico Perla - Sun Microsystems 	cleanup_stage2(stage2_curr);
511*af28f636SEnrico Perla - Sun Microsystems 	cleanup_stage2(stage2_attach);
512*af28f636SEnrico Perla - Sun Microsystems 
513*af28f636SEnrico Perla - Sun Microsystems out_devs:
514*af28f636SEnrico Perla - Sun Microsystems 	cleanup_device(attach_device);
515*af28f636SEnrico Perla - Sun Microsystems out_currdev:
516*af28f636SEnrico Perla - Sun Microsystems 	cleanup_device(curr_device);
517*af28f636SEnrico Perla - Sun Microsystems out:
518*af28f636SEnrico Perla - Sun Microsystems 	free(curr_device_path);
519*af28f636SEnrico Perla - Sun Microsystems 	free(attach_device_path);
520*af28f636SEnrico Perla - Sun Microsystems 	return (retval);
521*af28f636SEnrico Perla - Sun Microsystems }
522*af28f636SEnrico Perla - Sun Microsystems 
523*af28f636SEnrico Perla - Sun Microsystems static int
524*af28f636SEnrico Perla - Sun Microsystems commit_to_disk(ig_data_t *install, char *updt_str)
525*af28f636SEnrico Perla - Sun Microsystems {
526*af28f636SEnrico Perla - Sun Microsystems 	assert(install != NULL);
5277fc5d2a4SVikram Hegde 	/*
528*af28f636SEnrico Perla - Sun Microsystems 	 * vanilla stage1 and stage2 need to be updated at runtime.
529*af28f636SEnrico Perla - Sun Microsystems 	 * Update stage2 before stage1 because stage1 needs to know the first
530*af28f636SEnrico Perla - Sun Microsystems 	 * sector stage2 will be written to.
5317fc5d2a4SVikram Hegde 	 */
532*af28f636SEnrico Perla - Sun Microsystems 	if (prepare_stage2(install, updt_str) != BC_SUCCESS) {
533*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Error building stage2\n"));
534*af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
535*af28f636SEnrico Perla - Sun Microsystems 	}
536*af28f636SEnrico Perla - Sun Microsystems 	if (prepare_stage1(install) != BC_SUCCESS) {
537*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Error building stage1\n"));
538*af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
539*af28f636SEnrico Perla - Sun Microsystems 	}
540*af28f636SEnrico Perla - Sun Microsystems 
541*af28f636SEnrico Perla - Sun Microsystems 	/* Write stage2 out to disk. */
542*af28f636SEnrico Perla - Sun Microsystems 	if (write_stage2(install) != BC_SUCCESS) {
543*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Error writing stage2 to "
544*af28f636SEnrico Perla - Sun Microsystems 		    "disk\n"));
545*af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
546*af28f636SEnrico Perla - Sun Microsystems 	}
547*af28f636SEnrico Perla - Sun Microsystems 
548*af28f636SEnrico Perla - Sun Microsystems 	/* Write stage1 to disk and, if requested, to the MBR. */
549*af28f636SEnrico Perla - Sun Microsystems 	if (write_stage1(install) != BC_SUCCESS) {
550*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Error writing stage1 to "
551*af28f636SEnrico Perla - Sun Microsystems 		    "disk\n"));
552*af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
553*af28f636SEnrico Perla - Sun Microsystems 	}
554*af28f636SEnrico Perla - Sun Microsystems 
555*af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
556*af28f636SEnrico Perla - Sun Microsystems }
557*af28f636SEnrico Perla - Sun Microsystems 
558*af28f636SEnrico Perla - Sun Microsystems /*
559*af28f636SEnrico Perla - Sun Microsystems  * Propagate the bootblock on the source disk to the destination disk and
560*af28f636SEnrico Perla - Sun Microsystems  * version it with 'updt_str' in the process. Since we cannot trust any data
561*af28f636SEnrico Perla - Sun Microsystems  * on the attaching disk, we do not perform any specific check on a potential
562*af28f636SEnrico Perla - Sun Microsystems  * target extended information structure and we just blindly update.
563*af28f636SEnrico Perla - Sun Microsystems  */
564*af28f636SEnrico Perla - Sun Microsystems static int
565*af28f636SEnrico Perla - Sun Microsystems propagate_bootblock(ig_data_t *source, ig_data_t *target, char *updt_str)
566*af28f636SEnrico Perla - Sun Microsystems {
567*af28f636SEnrico Perla - Sun Microsystems 	ig_device_t	*src_device = &source->device;
568*af28f636SEnrico Perla - Sun Microsystems 	ig_device_t	*dest_device = &target->device;
569*af28f636SEnrico Perla - Sun Microsystems 	ig_stage2_t	*src_stage2 = &source->stage2;
570*af28f636SEnrico Perla - Sun Microsystems 	ig_stage2_t	*dest_stage2 = &target->stage2;
571*af28f636SEnrico Perla - Sun Microsystems 	uint32_t	buf_size;
572*af28f636SEnrico Perla - Sun Microsystems 	int		retval;
573*af28f636SEnrico Perla - Sun Microsystems 
574*af28f636SEnrico Perla - Sun Microsystems 	assert(source != NULL);
575*af28f636SEnrico Perla - Sun Microsystems 	assert(target != NULL);
576*af28f636SEnrico Perla - Sun Microsystems 
577*af28f636SEnrico Perla - Sun Microsystems 	/* read in stage1 from the source disk. */
578*af28f636SEnrico Perla - Sun Microsystems 	if (read_stage1_from_disk(src_device->part_fd, target->stage1_buf)
579*af28f636SEnrico Perla - Sun Microsystems 	    != BC_SUCCESS)
580*af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
581*af28f636SEnrico Perla - Sun Microsystems 
582*af28f636SEnrico Perla - Sun Microsystems 	/* Prepare target stage2 for commit_to_disk. */
583*af28f636SEnrico Perla - Sun Microsystems 	cleanup_stage2(dest_stage2);
584*af28f636SEnrico Perla - Sun Microsystems 
585*af28f636SEnrico Perla - Sun Microsystems 	if (updt_str != NULL)
586*af28f636SEnrico Perla - Sun Microsystems 		do_version = B_TRUE;
587*af28f636SEnrico Perla - Sun Microsystems 	else
588*af28f636SEnrico Perla - Sun Microsystems 		do_version = B_FALSE;
589*af28f636SEnrico Perla - Sun Microsystems 
590*af28f636SEnrico Perla - Sun Microsystems 	buf_size = src_stage2->file_size + SECTOR_SIZE;
591*af28f636SEnrico Perla - Sun Microsystems 
592*af28f636SEnrico Perla - Sun Microsystems 	dest_stage2->buf_size = P2ROUNDUP(buf_size, SECTOR_SIZE);
593*af28f636SEnrico Perla - Sun Microsystems 	dest_stage2->buf = malloc(dest_stage2->buf_size);
594*af28f636SEnrico Perla - Sun Microsystems 	if (dest_stage2->buf == NULL) {
595*af28f636SEnrico Perla - Sun Microsystems 		perror(gettext("Memory allocation failed"));
596*af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
597*af28f636SEnrico Perla - Sun Microsystems 	}
598*af28f636SEnrico Perla - Sun Microsystems 	dest_stage2->file = dest_stage2->buf;
599*af28f636SEnrico Perla - Sun Microsystems 	dest_stage2->file_size = src_stage2->file_size;
600*af28f636SEnrico Perla - Sun Microsystems 	memcpy(dest_stage2->file, src_stage2->file, dest_stage2->file_size);
601*af28f636SEnrico Perla - Sun Microsystems 	dest_stage2->extra = dest_stage2->buf +
602*af28f636SEnrico Perla - Sun Microsystems 	    P2ROUNDUP(dest_stage2->file_size, 8);
603*af28f636SEnrico Perla - Sun Microsystems 
604*af28f636SEnrico Perla - Sun Microsystems 	/* If we get down here we do have a mboot structure. */
605*af28f636SEnrico Perla - Sun Microsystems 	assert(src_stage2->mboot);
606*af28f636SEnrico Perla - Sun Microsystems 
607*af28f636SEnrico Perla - Sun Microsystems 	dest_stage2->mboot_off = src_stage2->mboot_off;
608*af28f636SEnrico Perla - Sun Microsystems 	dest_stage2->mboot = (multiboot_header_t *)(dest_stage2->buf +
609*af28f636SEnrico Perla - Sun Microsystems 	    dest_stage2->mboot_off);
610*af28f636SEnrico Perla - Sun Microsystems 
611*af28f636SEnrico Perla - Sun Microsystems 	(void) fprintf(stdout, gettext("Propagating %s stage1/stage2 to %s\n"),
612*af28f636SEnrico Perla - Sun Microsystems 	    src_device->path, dest_device->path);
613*af28f636SEnrico Perla - Sun Microsystems 	retval = commit_to_disk(target, updt_str);
614*af28f636SEnrico Perla - Sun Microsystems 
615*af28f636SEnrico Perla - Sun Microsystems 	return (retval);
616*af28f636SEnrico Perla - Sun Microsystems }
617*af28f636SEnrico Perla - Sun Microsystems 
618*af28f636SEnrico Perla - Sun Microsystems /*
619*af28f636SEnrico Perla - Sun Microsystems  * open the device and fill the various members of ig_device_t.
620*af28f636SEnrico Perla - Sun Microsystems  */
621*af28f636SEnrico Perla - Sun Microsystems static int
622*af28f636SEnrico Perla - Sun Microsystems init_device(ig_device_t *device, char *path)
623*af28f636SEnrico Perla - Sun Microsystems {
624*af28f636SEnrico Perla - Sun Microsystems 	bzero(device, sizeof (*device));
625*af28f636SEnrico Perla - Sun Microsystems 	device->part_fd = -1;
626*af28f636SEnrico Perla - Sun Microsystems 	device->disk_fd = -1;
627*af28f636SEnrico Perla - Sun Microsystems 	device->path_p0 = NULL;
628*af28f636SEnrico Perla - Sun Microsystems 
629*af28f636SEnrico Perla - Sun Microsystems 	device->path = strdup(path);
630*af28f636SEnrico Perla - Sun Microsystems 	if (device->path == NULL) {
631*af28f636SEnrico Perla - Sun Microsystems 		perror(gettext("Memory allocation failed"));
632*af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
633*af28f636SEnrico Perla - Sun Microsystems 	}
634*af28f636SEnrico Perla - Sun Microsystems 
635*af28f636SEnrico Perla - Sun Microsystems 	if (strstr(device->path, "diskette")) {
636*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("installing GRUB to a floppy "
637*af28f636SEnrico Perla - Sun Microsystems 		    "disk is no longer supported\n"));
638*af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
639*af28f636SEnrico Perla - Sun Microsystems 	}
640*af28f636SEnrico Perla - Sun Microsystems 
641*af28f636SEnrico Perla - Sun Microsystems 	/* Detect if the target device is a pcfs partition. */
642*af28f636SEnrico Perla - Sun Microsystems 	if (strstr(device->path, "p0:boot"))
643*af28f636SEnrico Perla - Sun Microsystems 		device->type = IG_DEV_X86BOOTPAR;
644*af28f636SEnrico Perla - Sun Microsystems 
645*af28f636SEnrico Perla - Sun Microsystems 	if (get_disk_fd(device) != BC_SUCCESS)
646*af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
647*af28f636SEnrico Perla - Sun Microsystems 
648*af28f636SEnrico Perla - Sun Microsystems 	/* read in the device boot sector. */
649*af28f636SEnrico Perla - Sun Microsystems 	if (read(device->disk_fd, device->boot_sector, SECTOR_SIZE)
650*af28f636SEnrico Perla - Sun Microsystems 	    != SECTOR_SIZE) {
651*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Error reading boot sector\n"));
652*af28f636SEnrico Perla - Sun Microsystems 		perror("read");
653*af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
654*af28f636SEnrico Perla - Sun Microsystems 	}
655*af28f636SEnrico Perla - Sun Microsystems 
656*af28f636SEnrico Perla - Sun Microsystems 	if (get_raw_partition_fd(device) != BC_SUCCESS)
657*af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
658*af28f636SEnrico Perla - Sun Microsystems 
659*af28f636SEnrico Perla - Sun Microsystems 	if (get_start_sector(device) != BC_SUCCESS)
660*af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
661*af28f636SEnrico Perla - Sun Microsystems 
662*af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
663*af28f636SEnrico Perla - Sun Microsystems }
664*af28f636SEnrico Perla - Sun Microsystems 
665*af28f636SEnrico Perla - Sun Microsystems static void
666*af28f636SEnrico Perla - Sun Microsystems cleanup_device(ig_device_t *device)
667*af28f636SEnrico Perla - Sun Microsystems {
668*af28f636SEnrico Perla - Sun Microsystems 	if (device->path)
669*af28f636SEnrico Perla - Sun Microsystems 		free(device->path);
670*af28f636SEnrico Perla - Sun Microsystems 	if (device->path_p0)
671*af28f636SEnrico Perla - Sun Microsystems 		free(device->path_p0);
672*af28f636SEnrico Perla - Sun Microsystems 
673*af28f636SEnrico Perla - Sun Microsystems 	if (device->part_fd != -1)
674*af28f636SEnrico Perla - Sun Microsystems 		(void) close(device->part_fd);
675*af28f636SEnrico Perla - Sun Microsystems 	if (device->disk_fd != -1)
676*af28f636SEnrico Perla - Sun Microsystems 		(void) close(device->disk_fd);
677*af28f636SEnrico Perla - Sun Microsystems 
678*af28f636SEnrico Perla - Sun Microsystems 	bzero(device, sizeof (ig_device_t));
679*af28f636SEnrico Perla - Sun Microsystems 	device->part_fd = -1;
680*af28f636SEnrico Perla - Sun Microsystems 	device->disk_fd = -1;
681*af28f636SEnrico Perla - Sun Microsystems }
682*af28f636SEnrico Perla - Sun Microsystems 
683*af28f636SEnrico Perla - Sun Microsystems static void
684*af28f636SEnrico Perla - Sun Microsystems cleanup_stage2(ig_stage2_t *stage2)
685*af28f636SEnrico Perla - Sun Microsystems {
686*af28f636SEnrico Perla - Sun Microsystems 	if (stage2->buf)
687*af28f636SEnrico Perla - Sun Microsystems 		free(stage2->buf);
688*af28f636SEnrico Perla - Sun Microsystems 	bzero(stage2, sizeof (ig_stage2_t));
689*af28f636SEnrico Perla - Sun Microsystems }
690*af28f636SEnrico Perla - Sun Microsystems 
691*af28f636SEnrico Perla - Sun Microsystems static int
692*af28f636SEnrico Perla - Sun Microsystems get_start_sector(ig_device_t *device)
693*af28f636SEnrico Perla - Sun Microsystems {
694*af28f636SEnrico Perla - Sun Microsystems 	uint32_t		secnum = 0, numsec = 0;
695*af28f636SEnrico Perla - Sun Microsystems 	int			i, pno, rval, log_part = 0;
696*af28f636SEnrico Perla - Sun Microsystems 	struct mboot		*mboot;
697*af28f636SEnrico Perla - Sun Microsystems 	struct ipart		*part;
698*af28f636SEnrico Perla - Sun Microsystems 	ext_part_t		*epp;
699*af28f636SEnrico Perla - Sun Microsystems 	struct part_info	dkpi;
700*af28f636SEnrico Perla - Sun Microsystems 	struct extpart_info	edkpi;
701*af28f636SEnrico Perla - Sun Microsystems 
702*af28f636SEnrico Perla - Sun Microsystems 	mboot = (struct mboot *)device->boot_sector;
703*af28f636SEnrico Perla - Sun Microsystems 
704*af28f636SEnrico Perla - Sun Microsystems 	if (is_bootpar(device->type)) {
705*af28f636SEnrico Perla - Sun Microsystems 		if (find_x86_bootpar(mboot, &pno, &secnum) != BC_SUCCESS) {
706*af28f636SEnrico Perla - Sun Microsystems 			(void) fprintf(stderr, NOBOOTPAR);
707*af28f636SEnrico Perla - Sun Microsystems 			return (BC_ERROR);
708*af28f636SEnrico Perla - Sun Microsystems 		} else {
709*af28f636SEnrico Perla - Sun Microsystems 			device->start_sector = secnum;
710*af28f636SEnrico Perla - Sun Microsystems 			device->partition = pno;
711*af28f636SEnrico Perla - Sun Microsystems 			goto found_part;
712*af28f636SEnrico Perla - Sun Microsystems 		}
7137fc5d2a4SVikram Hegde 	}
7147fc5d2a4SVikram Hegde 
7157fc5d2a4SVikram Hegde 	/*
716*af28f636SEnrico Perla - Sun Microsystems 	 * Search for Solaris fdisk partition
7177fc5d2a4SVikram Hegde 	 * Get the solaris partition information from the device
7187fc5d2a4SVikram Hegde 	 * and compare the offset of S2 with offset of solaris partition
7197fc5d2a4SVikram Hegde 	 * from fdisk partition table.
7207fc5d2a4SVikram Hegde 	 */
721*af28f636SEnrico Perla - Sun Microsystems 	if (ioctl(device->part_fd, DKIOCEXTPARTINFO, &edkpi) < 0) {
722*af28f636SEnrico Perla - Sun Microsystems 		if (ioctl(device->part_fd, DKIOCPARTINFO, &dkpi) < 0) {
7237fc5d2a4SVikram Hegde 			(void) fprintf(stderr, PART_FAIL);
724*af28f636SEnrico Perla - Sun Microsystems 			return (BC_ERROR);
7257fc5d2a4SVikram Hegde 		} else {
7267fc5d2a4SVikram Hegde 			edkpi.p_start = dkpi.p_start;
7277fc5d2a4SVikram Hegde 		}
7287fc5d2a4SVikram Hegde 	}
7297fc5d2a4SVikram Hegde 
7307fc5d2a4SVikram Hegde 	for (i = 0; i < FD_NUMPART; i++) {
7317fc5d2a4SVikram Hegde 		part = (struct ipart *)mboot->parts + i;
7327fc5d2a4SVikram Hegde 
7337fc5d2a4SVikram Hegde 		if (part->relsect == 0) {
7347fc5d2a4SVikram Hegde 			(void) fprintf(stderr, BAD_PART, i);
735*af28f636SEnrico Perla - Sun Microsystems 			return (BC_ERROR);
7367fc5d2a4SVikram Hegde 		}
7377fc5d2a4SVikram Hegde 
7387fc5d2a4SVikram Hegde 		if (edkpi.p_start >= part->relsect &&
7397fc5d2a4SVikram Hegde 		    edkpi.p_start < (part->relsect + part->numsect)) {
7407fc5d2a4SVikram Hegde 			/* Found the partition */
7417fc5d2a4SVikram Hegde 			break;
742d33344bbSsy 		}
743d33344bbSsy 	}
744d33344bbSsy 
7457fc5d2a4SVikram Hegde 	if (i == FD_NUMPART) {
7467fc5d2a4SVikram Hegde 		/* No solaris fdisk partitions (primary or logical) */
7477fc5d2a4SVikram Hegde 		(void) fprintf(stderr, NOSOLPAR);
748*af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
7497fc5d2a4SVikram Hegde 	}
7507fc5d2a4SVikram Hegde 
7517fc5d2a4SVikram Hegde 	/*
7527fc5d2a4SVikram Hegde 	 * We have found a Solaris fdisk partition (primary or extended)
7537fc5d2a4SVikram Hegde 	 * Handle the simple case first: Solaris in a primary partition
7547fc5d2a4SVikram Hegde 	 */
7557fc5d2a4SVikram Hegde 	if (!fdisk_is_dos_extended(part->systid)) {
756*af28f636SEnrico Perla - Sun Microsystems 		device->start_sector = part->relsect;
757*af28f636SEnrico Perla - Sun Microsystems 		device->partition = i;
7587fc5d2a4SVikram Hegde 		goto found_part;
7597fc5d2a4SVikram Hegde 	}
7607fc5d2a4SVikram Hegde 
7617fc5d2a4SVikram Hegde 	/*
7627fc5d2a4SVikram Hegde 	 * Solaris in a logical partition. Find that partition in the
7637fc5d2a4SVikram Hegde 	 * extended part.
7647fc5d2a4SVikram Hegde 	 */
765*af28f636SEnrico Perla - Sun Microsystems 	if ((rval = libfdisk_init(&epp, device->path_p0, NULL, FDISK_READ_DISK))
766aa1b14e7SSheshadri Vasudevan 	    != FDISK_SUCCESS) {
767aa1b14e7SSheshadri Vasudevan 		switch (rval) {
768aa1b14e7SSheshadri Vasudevan 			/*
7696cb5747bSSharath M Srinivasan 			 * The first 3 cases are not an error per-se, just that
7707fc5d2a4SVikram Hegde 			 * there is no Solaris logical partition
771aa1b14e7SSheshadri Vasudevan 			 */
772aa1b14e7SSheshadri Vasudevan 			case FDISK_EBADLOGDRIVE:
773aa1b14e7SSheshadri Vasudevan 			case FDISK_ENOLOGDRIVE:
7746cb5747bSSharath M Srinivasan 			case FDISK_EBADMAGIC:
7757fc5d2a4SVikram Hegde 				(void) fprintf(stderr, NOSOLPAR);
776*af28f636SEnrico Perla - Sun Microsystems 				return (BC_ERROR);
777aa1b14e7SSheshadri Vasudevan 			case FDISK_ENOVGEOM:
778aa1b14e7SSheshadri Vasudevan 				(void) fprintf(stderr, NO_VIRT_GEOM);
779*af28f636SEnrico Perla - Sun Microsystems 				return (BC_ERROR);
780aa1b14e7SSheshadri Vasudevan 			case FDISK_ENOPGEOM:
781aa1b14e7SSheshadri Vasudevan 				(void) fprintf(stderr, NO_PHYS_GEOM);
782*af28f636SEnrico Perla - Sun Microsystems 				return (BC_ERROR);
783aa1b14e7SSheshadri Vasudevan 			case FDISK_ENOLGEOM:
784aa1b14e7SSheshadri Vasudevan 				(void) fprintf(stderr, NO_LABEL_GEOM);
785*af28f636SEnrico Perla - Sun Microsystems 				return (BC_ERROR);
786aa1b14e7SSheshadri Vasudevan 			default:
787aa1b14e7SSheshadri Vasudevan 				(void) fprintf(stderr, LIBFDISK_INIT_FAIL);
788*af28f636SEnrico Perla - Sun Microsystems 				return (BC_ERROR);
789aa1b14e7SSheshadri Vasudevan 				break;
790aa1b14e7SSheshadri Vasudevan 		}
791aa1b14e7SSheshadri Vasudevan 	}
792aa1b14e7SSheshadri Vasudevan 
793aa1b14e7SSheshadri Vasudevan 	rval = fdisk_get_solaris_part(epp, &pno, &secnum, &numsec);
7946cb5747bSSharath M Srinivasan 	libfdisk_fini(&epp);
7957fc5d2a4SVikram Hegde 	if (rval != FDISK_SUCCESS) {
7967fc5d2a4SVikram Hegde 		/* No solaris logical partition */
7977fc5d2a4SVikram Hegde 		(void) fprintf(stderr, NOSOLPAR);
798*af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
799aa1b14e7SSheshadri Vasudevan 	}
800aa1b14e7SSheshadri Vasudevan 
801*af28f636SEnrico Perla - Sun Microsystems 	device->start_sector = secnum;
802*af28f636SEnrico Perla - Sun Microsystems 	device->partition = pno - 1;
8037fc5d2a4SVikram Hegde 	log_part = 1;
8047c478bd9Sstevel@tonic-gate 
8057fc5d2a4SVikram Hegde found_part:
8067c478bd9Sstevel@tonic-gate 	/* get confirmation for -m */
807*af28f636SEnrico Perla - Sun Microsystems 	if (write_mbr && !force_mbr) {
8087c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout, MBOOT_PROMPT);
8097c478bd9Sstevel@tonic-gate 		if (getchar() != 'y') {
810*af28f636SEnrico Perla - Sun Microsystems 			write_mbr = 0;
8117c478bd9Sstevel@tonic-gate 			(void) fprintf(stdout, MBOOT_NOT_UPDATED);
812*af28f636SEnrico Perla - Sun Microsystems 			return (BC_ERROR);
8137c478bd9Sstevel@tonic-gate 		}
8147c478bd9Sstevel@tonic-gate 	}
8157c478bd9Sstevel@tonic-gate 
8167fc5d2a4SVikram Hegde 	/*
8177fc5d2a4SVikram Hegde 	 * Currently if Solaris is in an extended partition we need to
8187fc5d2a4SVikram Hegde 	 * write GRUB to the MBR. Check for this.
8197fc5d2a4SVikram Hegde 	 */
820*af28f636SEnrico Perla - Sun Microsystems 	if (log_part && !write_mbr) {
821*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, gettext("Installing Solaris on an "
822*af28f636SEnrico Perla - Sun Microsystems 		    "extended partition... forcing MBR update\n"));
823*af28f636SEnrico Perla - Sun Microsystems 		write_mbr = 1;
824aa1b14e7SSheshadri Vasudevan 	}
825aa1b14e7SSheshadri Vasudevan 
8267fc5d2a4SVikram Hegde 	/*
8277fc5d2a4SVikram Hegde 	 * warn, if Solaris in primary partition and GRUB not in MBR and
8287fc5d2a4SVikram Hegde 	 * partition is not active
8297fc5d2a4SVikram Hegde 	 */
830*af28f636SEnrico Perla - Sun Microsystems 	if (!log_part && part->bootid != 128 && !write_mbr) {
831*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, SOLPAR_INACTIVE, device->partition + 1);
8327c478bd9Sstevel@tonic-gate 	}
8337c478bd9Sstevel@tonic-gate 
834*af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
8357c478bd9Sstevel@tonic-gate }
8367c478bd9Sstevel@tonic-gate 
8377c478bd9Sstevel@tonic-gate static int
838*af28f636SEnrico Perla - Sun Microsystems get_disk_fd(ig_device_t *device)
8397c478bd9Sstevel@tonic-gate {
840*af28f636SEnrico Perla - Sun Microsystems 	int	i;
841*af28f636SEnrico Perla - Sun Microsystems 	char	save[2];
842*af28f636SEnrico Perla - Sun Microsystems 	char	*end = NULL;
843*af28f636SEnrico Perla - Sun Microsystems 
844*af28f636SEnrico Perla - Sun Microsystems 	assert(device != NULL);
845*af28f636SEnrico Perla - Sun Microsystems 	assert(device->path != NULL);
846*af28f636SEnrico Perla - Sun Microsystems 
847*af28f636SEnrico Perla - Sun Microsystems 	if (is_bootpar(device->type)) {
848*af28f636SEnrico Perla - Sun Microsystems 		end = strstr(device->path, "p0:boot");
849*af28f636SEnrico Perla - Sun Microsystems 		/* tested at the start of init_device() */
850*af28f636SEnrico Perla - Sun Microsystems 		assert(end != NULL);
851*af28f636SEnrico Perla - Sun Microsystems 		/* chop off :boot */
852*af28f636SEnrico Perla - Sun Microsystems 		save[0] = end[2];
853*af28f636SEnrico Perla - Sun Microsystems 		end[2] = '\0';
854*af28f636SEnrico Perla - Sun Microsystems 	} else {
855*af28f636SEnrico Perla - Sun Microsystems 		i = strlen(device->path);
856*af28f636SEnrico Perla - Sun Microsystems 		save[0] = device->path[i - 2];
857*af28f636SEnrico Perla - Sun Microsystems 		save[1] = device->path[i - 1];
858*af28f636SEnrico Perla - Sun Microsystems 		device->path[i - 2] = 'p';
859*af28f636SEnrico Perla - Sun Microsystems 		device->path[i - 1] = '0';
8607c478bd9Sstevel@tonic-gate 	}
8617c478bd9Sstevel@tonic-gate 
8627c478bd9Sstevel@tonic-gate 	if (nowrite)
863*af28f636SEnrico Perla - Sun Microsystems 		device->disk_fd = open(device->path, O_RDONLY);
8647c478bd9Sstevel@tonic-gate 	else
865*af28f636SEnrico Perla - Sun Microsystems 		device->disk_fd = open(device->path, O_RDWR);
8667c478bd9Sstevel@tonic-gate 
867*af28f636SEnrico Perla - Sun Microsystems 	device->path_p0 = strdup(device->path);
868*af28f636SEnrico Perla - Sun Microsystems 	if (device->path_p0 == NULL) {
869*af28f636SEnrico Perla - Sun Microsystems 		perror("strdup");
870*af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
8717c478bd9Sstevel@tonic-gate 	}
872*af28f636SEnrico Perla - Sun Microsystems 
873*af28f636SEnrico Perla - Sun Microsystems 	if (is_bootpar(device->type)) {
874*af28f636SEnrico Perla - Sun Microsystems 		end[2] = save[0];
875*af28f636SEnrico Perla - Sun Microsystems 	} else {
876*af28f636SEnrico Perla - Sun Microsystems 		device->path[i - 2] = save[0];
877*af28f636SEnrico Perla - Sun Microsystems 		device->path[i - 1] = save[1];
878*af28f636SEnrico Perla - Sun Microsystems 	}
879*af28f636SEnrico Perla - Sun Microsystems 
880*af28f636SEnrico Perla - Sun Microsystems 	if (device->disk_fd == -1) {
881*af28f636SEnrico Perla - Sun Microsystems 		perror("open");
882*af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
8837c478bd9Sstevel@tonic-gate 	}
8847c478bd9Sstevel@tonic-gate 
885*af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
8867c478bd9Sstevel@tonic-gate }
8877c478bd9Sstevel@tonic-gate 
8887c478bd9Sstevel@tonic-gate static void
889*af28f636SEnrico Perla - Sun Microsystems prepare_fake_multiboot(ig_stage2_t *stage2)
8907c478bd9Sstevel@tonic-gate {
891*af28f636SEnrico Perla - Sun Microsystems 	multiboot_header_t	*mboot;
8927c478bd9Sstevel@tonic-gate 
893*af28f636SEnrico Perla - Sun Microsystems 	assert(stage2 != NULL);
894*af28f636SEnrico Perla - Sun Microsystems 	assert(stage2->mboot != NULL);
895*af28f636SEnrico Perla - Sun Microsystems 	assert(stage2->buf != NULL);
8967c478bd9Sstevel@tonic-gate 
897*af28f636SEnrico Perla - Sun Microsystems 	mboot = stage2->mboot;
898*af28f636SEnrico Perla - Sun Microsystems 
899*af28f636SEnrico Perla - Sun Microsystems 	/*
900*af28f636SEnrico Perla - Sun Microsystems 	 * Currently we expect find_multiboot() to have located a multiboot
901*af28f636SEnrico Perla - Sun Microsystems 	 * header with the AOUT kludge flag set.
902*af28f636SEnrico Perla - Sun Microsystems 	 */
903*af28f636SEnrico Perla - Sun Microsystems 	assert(mboot->flags & BB_MBOOT_AOUT_FLAG);
904*af28f636SEnrico Perla - Sun Microsystems 
905*af28f636SEnrico Perla - Sun Microsystems 	/* Insert the information necessary to locate stage2. */
906*af28f636SEnrico Perla - Sun Microsystems 	mboot->header_addr = stage2->mboot_off;
907*af28f636SEnrico Perla - Sun Microsystems 	mboot->load_addr = 0;
908*af28f636SEnrico Perla - Sun Microsystems 	mboot->load_end_addr = stage2->file_size;
9097c478bd9Sstevel@tonic-gate }
9107c478bd9Sstevel@tonic-gate 
9117c478bd9Sstevel@tonic-gate static void
912*af28f636SEnrico Perla - Sun Microsystems add_stage2_einfo(ig_stage2_t *stage2, char *updt_str)
9137c478bd9Sstevel@tonic-gate {
914*af28f636SEnrico Perla - Sun Microsystems 	bblk_hs_t	hs;
915*af28f636SEnrico Perla - Sun Microsystems 	uint32_t	avail_space;
916*af28f636SEnrico Perla - Sun Microsystems 
917*af28f636SEnrico Perla - Sun Microsystems 	assert(stage2 != NULL);
918*af28f636SEnrico Perla - Sun Microsystems 
919*af28f636SEnrico Perla - Sun Microsystems 	/* Fill bootblock hashing source information. */
920*af28f636SEnrico Perla - Sun Microsystems 	hs.src_buf = (unsigned char *)stage2->file;
921*af28f636SEnrico Perla - Sun Microsystems 	hs.src_size = stage2->file_size;
922*af28f636SEnrico Perla - Sun Microsystems 	/* How much space for the extended information structure? */
923*af28f636SEnrico Perla - Sun Microsystems 	avail_space = stage2->buf_size - P2ROUNDUP(stage2->file_size, 8);
924*af28f636SEnrico Perla - Sun Microsystems 	add_einfo(stage2->extra, updt_str, &hs, avail_space);
925*af28f636SEnrico Perla - Sun Microsystems }
926*af28f636SEnrico Perla - Sun Microsystems 
927*af28f636SEnrico Perla - Sun Microsystems 
928*af28f636SEnrico Perla - Sun Microsystems static int
929*af28f636SEnrico Perla - Sun Microsystems write_stage2(ig_data_t *install)
930*af28f636SEnrico Perla - Sun Microsystems {
931*af28f636SEnrico Perla - Sun Microsystems 	ig_device_t		*device = &install->device;
932*af28f636SEnrico Perla - Sun Microsystems 	ig_stage2_t		*stage2 = &install->stage2;
933*af28f636SEnrico Perla - Sun Microsystems 	off_t			offset;
934*af28f636SEnrico Perla - Sun Microsystems 
935*af28f636SEnrico Perla - Sun Microsystems 	assert(install != NULL);
936*af28f636SEnrico Perla - Sun Microsystems 
937*af28f636SEnrico Perla - Sun Microsystems 	if (is_bootpar(device->type)) {
938*af28f636SEnrico Perla - Sun Microsystems 		/*
939*af28f636SEnrico Perla - Sun Microsystems 		 * stage2 is already on the filesystem, we only need to update
940*af28f636SEnrico Perla - Sun Microsystems 		 * the first two blocks (that we have modified during
941*af28f636SEnrico Perla - Sun Microsystems 		 * prepare_stage2())
942*af28f636SEnrico Perla - Sun Microsystems 		 */
943*af28f636SEnrico Perla - Sun Microsystems 		if (write_out(device->part_fd, stage2->file, SECTOR_SIZE,
944*af28f636SEnrico Perla - Sun Microsystems 		    stage2->pcfs_first_sectors[0] * SECTOR_SIZE)
945*af28f636SEnrico Perla - Sun Microsystems 		    != BC_SUCCESS ||
946*af28f636SEnrico Perla - Sun Microsystems 		    write_out(device->part_fd, stage2->file + SECTOR_SIZE,
947*af28f636SEnrico Perla - Sun Microsystems 		    SECTOR_SIZE, stage2->pcfs_first_sectors[1] * SECTOR_SIZE)
948*af28f636SEnrico Perla - Sun Microsystems 		    != BC_SUCCESS) {
949*af28f636SEnrico Perla - Sun Microsystems 			(void) fprintf(stderr, WRITE_FAIL_STAGE2);
950*af28f636SEnrico Perla - Sun Microsystems 			return (BC_ERROR);
951*af28f636SEnrico Perla - Sun Microsystems 		}
952*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, WRITE_STAGE2_PCFS);
953*af28f636SEnrico Perla - Sun Microsystems 		return (BC_SUCCESS);
9547c478bd9Sstevel@tonic-gate 	}
955*af28f636SEnrico Perla - Sun Microsystems 
956*af28f636SEnrico Perla - Sun Microsystems 	/*
957*af28f636SEnrico Perla - Sun Microsystems 	 * For disk, write stage2 starting at STAGE2_BLKOFF sector.
958*af28f636SEnrico Perla - Sun Microsystems 	 * Note that we use stage2->buf rather than stage2->file, because we
959*af28f636SEnrico Perla - Sun Microsystems 	 * may have extended information after the latter.
960*af28f636SEnrico Perla - Sun Microsystems 	 */
961*af28f636SEnrico Perla - Sun Microsystems 	offset = STAGE2_BLKOFF * SECTOR_SIZE;
962*af28f636SEnrico Perla - Sun Microsystems 	if (write_out(device->part_fd, stage2->buf, stage2->buf_size,
963*af28f636SEnrico Perla - Sun Microsystems 	    offset) != BC_SUCCESS) {
964*af28f636SEnrico Perla - Sun Microsystems 		perror("write");
965*af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
966*af28f636SEnrico Perla - Sun Microsystems 	}
967*af28f636SEnrico Perla - Sun Microsystems 
968*af28f636SEnrico Perla - Sun Microsystems 	/* Simulate the "old" installgrub output. */
969*af28f636SEnrico Perla - Sun Microsystems 	(void) fprintf(stdout, WRITE_STAGE2_DISK, device->partition,
970*af28f636SEnrico Perla - Sun Microsystems 	    (stage2->buf_size / SECTOR_SIZE) + 1, STAGE2_BLKOFF,
971*af28f636SEnrico Perla - Sun Microsystems 	    stage2->first_sector);
972*af28f636SEnrico Perla - Sun Microsystems 
973*af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
9747c478bd9Sstevel@tonic-gate }
9757c478bd9Sstevel@tonic-gate 
976*af28f636SEnrico Perla - Sun Microsystems static int
977*af28f636SEnrico Perla - Sun Microsystems write_stage1(ig_data_t *install)
9787c478bd9Sstevel@tonic-gate {
979*af28f636SEnrico Perla - Sun Microsystems 	ig_device_t	*device = &install->device;
980*af28f636SEnrico Perla - Sun Microsystems 
981*af28f636SEnrico Perla - Sun Microsystems 	assert(install != NULL);
982*af28f636SEnrico Perla - Sun Microsystems 
983*af28f636SEnrico Perla - Sun Microsystems 	if (write_out(device->part_fd, install->stage1_buf,
984*af28f636SEnrico Perla - Sun Microsystems 	    sizeof (install->stage1_buf), 0) != BC_SUCCESS) {
985*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, WRITE_FAIL_PBOOT);
986*af28f636SEnrico Perla - Sun Microsystems 		perror("write");
987*af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
9887c478bd9Sstevel@tonic-gate 	}
989*af28f636SEnrico Perla - Sun Microsystems 
990*af28f636SEnrico Perla - Sun Microsystems 	/* Simulate "old" installgrub output. */
991*af28f636SEnrico Perla - Sun Microsystems 	(void) fprintf(stdout, WRITE_PBOOT, device->partition,
992*af28f636SEnrico Perla - Sun Microsystems 	    device->start_sector);
993*af28f636SEnrico Perla - Sun Microsystems 
994*af28f636SEnrico Perla - Sun Microsystems 	if (write_mbr) {
995*af28f636SEnrico Perla - Sun Microsystems 		if (write_out(device->disk_fd, install->stage1_buf,
996*af28f636SEnrico Perla - Sun Microsystems 		    sizeof (install->stage1_buf), 0) != BC_SUCCESS) {
997*af28f636SEnrico Perla - Sun Microsystems 			(void) fprintf(stdout, WRITE_FAIL_BOOTSEC);
998*af28f636SEnrico Perla - Sun Microsystems 			perror("write");
999*af28f636SEnrico Perla - Sun Microsystems 			return (BC_ERROR);
1000*af28f636SEnrico Perla - Sun Microsystems 		}
1001*af28f636SEnrico Perla - Sun Microsystems 		/* Simulate "old" installgrub output. */
1002*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, WRITE_MBOOT);
1003*af28f636SEnrico Perla - Sun Microsystems 	}
1004*af28f636SEnrico Perla - Sun Microsystems 
1005*af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
10067c478bd9Sstevel@tonic-gate }
10077c478bd9Sstevel@tonic-gate 
1008*af28f636SEnrico Perla - Sun Microsystems #define	USAGE_STRING	"%s [-m|-f|-n|-F|-u verstr] stage1 stage2 device\n"    \
1009*af28f636SEnrico Perla - Sun Microsystems 			"%s -M [-n] device1 device2\n"			       \
1010*af28f636SEnrico Perla - Sun Microsystems 			"%s [-V|-e] -i device\n"			       \
1011*af28f636SEnrico Perla - Sun Microsystems 
1012*af28f636SEnrico Perla - Sun Microsystems #define	CANON_USAGE_STR	gettext(USAGE_STRING)
1013*af28f636SEnrico Perla - Sun Microsystems 
10147c478bd9Sstevel@tonic-gate static void
1015*af28f636SEnrico Perla - Sun Microsystems usage(char *progname)
10167c478bd9Sstevel@tonic-gate {
1017*af28f636SEnrico Perla - Sun Microsystems 	(void) fprintf(stdout, CANON_USAGE_STR, progname, progname, progname);
1018*af28f636SEnrico Perla - Sun Microsystems }
10197c478bd9Sstevel@tonic-gate 
10207c478bd9Sstevel@tonic-gate 
1021*af28f636SEnrico Perla - Sun Microsystems static int
1022*af28f636SEnrico Perla - Sun Microsystems read_stage1_from_file(char *path, ig_data_t *dest)
1023*af28f636SEnrico Perla - Sun Microsystems {
1024*af28f636SEnrico Perla - Sun Microsystems 	int	fd;
1025*af28f636SEnrico Perla - Sun Microsystems 
1026*af28f636SEnrico Perla - Sun Microsystems 	assert(dest);
1027*af28f636SEnrico Perla - Sun Microsystems 
1028*af28f636SEnrico Perla - Sun Microsystems 	/* read the stage1 file from filesystem */
1029*af28f636SEnrico Perla - Sun Microsystems 	fd = open(path, O_RDONLY);
1030*af28f636SEnrico Perla - Sun Microsystems 	if (fd == -1 ||
1031*af28f636SEnrico Perla - Sun Microsystems 	    read(fd, dest->stage1_buf, SECTOR_SIZE) != SECTOR_SIZE) {
1032*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, READ_FAIL_STAGE1, path);
1033*af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
10347c478bd9Sstevel@tonic-gate 	}
10357c478bd9Sstevel@tonic-gate 	(void) close(fd);
1036*af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
10377c478bd9Sstevel@tonic-gate }
10387c478bd9Sstevel@tonic-gate 
1039*af28f636SEnrico Perla - Sun Microsystems static int
1040*af28f636SEnrico Perla - Sun Microsystems read_stage2_from_file(char *path, ig_data_t *dest)
10417c478bd9Sstevel@tonic-gate {
1042*af28f636SEnrico Perla - Sun Microsystems 	int		fd;
1043*af28f636SEnrico Perla - Sun Microsystems 	struct stat	sb;
1044*af28f636SEnrico Perla - Sun Microsystems 	ig_stage2_t	*stage2 = &dest->stage2;
1045*af28f636SEnrico Perla - Sun Microsystems 	ig_device_t	*device = &dest->device;
1046*af28f636SEnrico Perla - Sun Microsystems 	uint32_t	buf_size;
1047*af28f636SEnrico Perla - Sun Microsystems 
1048*af28f636SEnrico Perla - Sun Microsystems 	assert(dest);
1049*af28f636SEnrico Perla - Sun Microsystems 	assert(stage2->buf == NULL);
1050*af28f636SEnrico Perla - Sun Microsystems 
1051*af28f636SEnrico Perla - Sun Microsystems 	fd = open(path, O_RDONLY);
1052*af28f636SEnrico Perla - Sun Microsystems 	if (fstat(fd, &sb) == -1) {
1053*af28f636SEnrico Perla - Sun Microsystems 		perror("fstat");
1054*af28f636SEnrico Perla - Sun Microsystems 		goto out;
1055*af28f636SEnrico Perla - Sun Microsystems 	}
1056*af28f636SEnrico Perla - Sun Microsystems 
1057*af28f636SEnrico Perla - Sun Microsystems 	stage2->file_size = sb.st_size;
1058*af28f636SEnrico Perla - Sun Microsystems 
1059*af28f636SEnrico Perla - Sun Microsystems 	if (!is_bootpar(device->type)) {
1060*af28f636SEnrico Perla - Sun Microsystems 		/*
1061*af28f636SEnrico Perla - Sun Microsystems 		 * buffer size needs to account for stage2 plus the extra
1062*af28f636SEnrico Perla - Sun Microsystems 		 * versioning information at the end of it. We reserve one
1063*af28f636SEnrico Perla - Sun Microsystems 		 * extra sector (plus we round up to the next sector boundary).
1064*af28f636SEnrico Perla - Sun Microsystems 		 */
1065*af28f636SEnrico Perla - Sun Microsystems 		buf_size = stage2->file_size + SECTOR_SIZE;
10667c478bd9Sstevel@tonic-gate 	} else {
1067*af28f636SEnrico Perla - Sun Microsystems 		/* In the PCFS case we only need to read in stage2. */
1068*af28f636SEnrico Perla - Sun Microsystems 		buf_size = stage2->file_size;
10697c478bd9Sstevel@tonic-gate 	}
10707c478bd9Sstevel@tonic-gate 
1071*af28f636SEnrico Perla - Sun Microsystems 	stage2->buf_size = P2ROUNDUP(buf_size, SECTOR_SIZE);
1072*af28f636SEnrico Perla - Sun Microsystems 
1073*af28f636SEnrico Perla - Sun Microsystems 	BOOT_DEBUG("stage2 buffer size = %d (%d sectors)\n", stage2->buf_size,
1074*af28f636SEnrico Perla - Sun Microsystems 	    stage2->buf_size / SECTOR_SIZE);
1075*af28f636SEnrico Perla - Sun Microsystems 
1076*af28f636SEnrico Perla - Sun Microsystems 	stage2->buf = malloc(stage2->buf_size);
1077*af28f636SEnrico Perla - Sun Microsystems 	if (stage2->buf == NULL) {
1078*af28f636SEnrico Perla - Sun Microsystems 		perror(gettext("Memory allocation failed"));
1079*af28f636SEnrico Perla - Sun Microsystems 		goto out_fd;
1080*af28f636SEnrico Perla - Sun Microsystems 	}
1081*af28f636SEnrico Perla - Sun Microsystems 
1082*af28f636SEnrico Perla - Sun Microsystems 	stage2->file = stage2->buf;
10837c478bd9Sstevel@tonic-gate 
10847c478bd9Sstevel@tonic-gate 	/*
1085*af28f636SEnrico Perla - Sun Microsystems 	 * Extra information (e.g. the versioning structure) is placed at the
1086*af28f636SEnrico Perla - Sun Microsystems 	 * end of stage2, aligned on a 8-byte boundary.
10877c478bd9Sstevel@tonic-gate 	 */
1088*af28f636SEnrico Perla - Sun Microsystems 	if (!(is_bootpar(device->type)))
1089*af28f636SEnrico Perla - Sun Microsystems 		stage2->extra = stage2->file + P2ROUNDUP(stage2->file_size, 8);
10907c478bd9Sstevel@tonic-gate 
1091*af28f636SEnrico Perla - Sun Microsystems 	if (lseek(fd, 0, SEEK_SET) == -1) {
1092*af28f636SEnrico Perla - Sun Microsystems 		perror("lseek");
1093*af28f636SEnrico Perla - Sun Microsystems 		goto out_alloc;
10947c478bd9Sstevel@tonic-gate 	}
10957c478bd9Sstevel@tonic-gate 
1096*af28f636SEnrico Perla - Sun Microsystems 	if (read(fd, stage2->file, stage2->file_size) < 0) {
1097*af28f636SEnrico Perla - Sun Microsystems 		perror(gettext("unable to read stage2"));
1098*af28f636SEnrico Perla - Sun Microsystems 		goto out_alloc;
10997c478bd9Sstevel@tonic-gate 	}
11007c478bd9Sstevel@tonic-gate 
1101*af28f636SEnrico Perla - Sun Microsystems 	(void) close(fd);
1102*af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
11037ce76caaSEnrico Perla - Sun Microsystems 
1104*af28f636SEnrico Perla - Sun Microsystems out_alloc:
1105*af28f636SEnrico Perla - Sun Microsystems 	free(stage2->buf);
1106*af28f636SEnrico Perla - Sun Microsystems 	stage2->buf = NULL;
1107*af28f636SEnrico Perla - Sun Microsystems out_fd:
1108*af28f636SEnrico Perla - Sun Microsystems 	(void) close(fd);
1109*af28f636SEnrico Perla - Sun Microsystems out:
1110*af28f636SEnrico Perla - Sun Microsystems 	return (BC_ERROR);
11117ce76caaSEnrico Perla - Sun Microsystems }
11127ce76caaSEnrico Perla - Sun Microsystems 
1113*af28f636SEnrico Perla - Sun Microsystems static int
1114*af28f636SEnrico Perla - Sun Microsystems prepare_stage1(ig_data_t *install)
11157ce76caaSEnrico Perla - Sun Microsystems {
1116*af28f636SEnrico Perla - Sun Microsystems 	ig_device_t	*device = &install->device;
11177ce76caaSEnrico Perla - Sun Microsystems 
1118*af28f636SEnrico Perla - Sun Microsystems 	assert(install != NULL);
1119*af28f636SEnrico Perla - Sun Microsystems 
1120*af28f636SEnrico Perla - Sun Microsystems 	/* If PCFS add the BIOS Parameter Block. */
1121*af28f636SEnrico Perla - Sun Microsystems 	if (is_bootpar(device->type)) {
1122*af28f636SEnrico Perla - Sun Microsystems 		char	bpb_sect[SECTOR_SIZE];
1123*af28f636SEnrico Perla - Sun Microsystems 
1124*af28f636SEnrico Perla - Sun Microsystems 		if (pread(device->part_fd, bpb_sect, SECTOR_SIZE, 0)
1125*af28f636SEnrico Perla - Sun Microsystems 		    != SECTOR_SIZE) {
1126*af28f636SEnrico Perla - Sun Microsystems 			(void) fprintf(stderr, READ_FAIL_BPB);
1127*af28f636SEnrico Perla - Sun Microsystems 			return (BC_ERROR);
1128*af28f636SEnrico Perla - Sun Microsystems 		}
1129*af28f636SEnrico Perla - Sun Microsystems 		bcopy(bpb_sect + STAGE1_BPB_OFFSET,
1130*af28f636SEnrico Perla - Sun Microsystems 		    install->stage1_buf + STAGE1_BPB_OFFSET, STAGE1_BPB_SIZE);
11317ce76caaSEnrico Perla - Sun Microsystems 	}
11327ce76caaSEnrico Perla - Sun Microsystems 
1133*af28f636SEnrico Perla - Sun Microsystems 	/* copy MBR to stage1 in case of overwriting MBR sector. */
1134*af28f636SEnrico Perla - Sun Microsystems 	bcopy(device->boot_sector + BOOTSZ, install->stage1_buf + BOOTSZ,
1135*af28f636SEnrico Perla - Sun Microsystems 	    SECTOR_SIZE - BOOTSZ);
1136*af28f636SEnrico Perla - Sun Microsystems 	/* modify default stage1 file generated by GRUB. */
1137*af28f636SEnrico Perla - Sun Microsystems 	*((unsigned char *)(install->stage1_buf + STAGE1_FORCE_LBA)) = 1;
1138*af28f636SEnrico Perla - Sun Microsystems 	*((ulong_t *)(install->stage1_buf + STAGE1_STAGE2_SECTOR))
1139*af28f636SEnrico Perla - Sun Microsystems 	    = install->stage2.first_sector;
1140*af28f636SEnrico Perla - Sun Microsystems 	*((ushort_t *)(install->stage1_buf + STAGE1_STAGE2_ADDRESS))
1141*af28f636SEnrico Perla - Sun Microsystems 	    = STAGE2_MEMADDR;
1142*af28f636SEnrico Perla - Sun Microsystems 	*((ushort_t *)(install->stage1_buf + STAGE1_STAGE2_SEGMENT))
1143*af28f636SEnrico Perla - Sun Microsystems 	    = STAGE2_MEMADDR >> 4;
11447ce76caaSEnrico Perla - Sun Microsystems 
1145*af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
11467ce76caaSEnrico Perla - Sun Microsystems }
11477ce76caaSEnrico Perla - Sun Microsystems 
1148*af28f636SEnrico Perla - Sun Microsystems /*
1149*af28f636SEnrico Perla - Sun Microsystems  * Grab stage1 from the specified device file descriptor.
1150*af28f636SEnrico Perla - Sun Microsystems  */
11517ce76caaSEnrico Perla - Sun Microsystems static int
1152*af28f636SEnrico Perla - Sun Microsystems read_stage1_from_disk(int dev_fd, char *stage1_buf)
11537ce76caaSEnrico Perla - Sun Microsystems {
1154*af28f636SEnrico Perla - Sun Microsystems 	assert(stage1_buf != NULL);
11557ce76caaSEnrico Perla - Sun Microsystems 
1156*af28f636SEnrico Perla - Sun Microsystems 	if (read_in(dev_fd, stage1_buf, SECTOR_SIZE, 0) != BC_SUCCESS) {
1157*af28f636SEnrico Perla - Sun Microsystems 		perror(gettext("Unable to read stage1 from disk"));
1158*af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
1159*af28f636SEnrico Perla - Sun Microsystems 	}
1160*af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
1161*af28f636SEnrico Perla - Sun Microsystems }
11627ce76caaSEnrico Perla - Sun Microsystems 
1163*af28f636SEnrico Perla - Sun Microsystems static int
1164*af28f636SEnrico Perla - Sun Microsystems read_stage2_from_disk(int dev_fd, ig_stage2_t *stage2)
1165*af28f636SEnrico Perla - Sun Microsystems {
1166*af28f636SEnrico Perla - Sun Microsystems 	uint32_t		size;
1167*af28f636SEnrico Perla - Sun Microsystems 	uint32_t		buf_size;
1168*af28f636SEnrico Perla - Sun Microsystems 	uint32_t		mboot_off;
1169*af28f636SEnrico Perla - Sun Microsystems 	multiboot_header_t	*mboot;
1170*af28f636SEnrico Perla - Sun Microsystems 
1171*af28f636SEnrico Perla - Sun Microsystems 	assert(stage2 != NULL);
1172*af28f636SEnrico Perla - Sun Microsystems 	assert(dev_fd != -1);
1173*af28f636SEnrico Perla - Sun Microsystems 
1174*af28f636SEnrico Perla - Sun Microsystems 	if (read_in(dev_fd, mboot_scan, sizeof (mboot_scan),
1175*af28f636SEnrico Perla - Sun Microsystems 	    STAGE2_BLKOFF * SECTOR_SIZE) != BC_SUCCESS) {
1176*af28f636SEnrico Perla - Sun Microsystems 		perror(gettext("Error reading stage2 sectors"));
1177*af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
1178*af28f636SEnrico Perla - Sun Microsystems 	}
11797ce76caaSEnrico Perla - Sun Microsystems 
1180*af28f636SEnrico Perla - Sun Microsystems 	/* No multiboot means no chance of knowing stage2 size */
1181*af28f636SEnrico Perla - Sun Microsystems 	if (find_multiboot(mboot_scan, sizeof (mboot_scan), &mboot_off)
1182*af28f636SEnrico Perla - Sun Microsystems 	    != BC_SUCCESS) {
1183*af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("Unable to find multiboot header\n");
1184*af28f636SEnrico Perla - Sun Microsystems 		return (BC_NOEXTRA);
1185*af28f636SEnrico Perla - Sun Microsystems 	}
1186*af28f636SEnrico Perla - Sun Microsystems 	mboot = (multiboot_header_t *)(mboot_scan + mboot_off);
11877ce76caaSEnrico Perla - Sun Microsystems 
1188*af28f636SEnrico Perla - Sun Microsystems 	/*
1189*af28f636SEnrico Perla - Sun Microsystems 	 * Unfilled mboot values mean an older version of installgrub installed
1190*af28f636SEnrico Perla - Sun Microsystems 	 * the stage2. Again we have no chance of knowing stage2 size.
1191*af28f636SEnrico Perla - Sun Microsystems 	 */
1192*af28f636SEnrico Perla - Sun Microsystems 	if (mboot->load_end_addr == 0 ||
1193*af28f636SEnrico Perla - Sun Microsystems 	    mboot->load_end_addr < mboot->load_addr)
1194*af28f636SEnrico Perla - Sun Microsystems 		return (BC_NOEXTRA);
11957ce76caaSEnrico Perla - Sun Microsystems 
1196*af28f636SEnrico Perla - Sun Microsystems 	/*
1197*af28f636SEnrico Perla - Sun Microsystems 	 * Currently, the amount of space reserved for extra information
1198*af28f636SEnrico Perla - Sun Microsystems 	 * is "fixed". We may have to scan for the terminating extra payload
1199*af28f636SEnrico Perla - Sun Microsystems 	 * in the future.
1200*af28f636SEnrico Perla - Sun Microsystems 	 */
1201*af28f636SEnrico Perla - Sun Microsystems 	size = mboot->load_end_addr - mboot->load_addr;
1202*af28f636SEnrico Perla - Sun Microsystems 	buf_size = P2ROUNDUP(size + SECTOR_SIZE, SECTOR_SIZE);
12037ce76caaSEnrico Perla - Sun Microsystems 
1204*af28f636SEnrico Perla - Sun Microsystems 	stage2->buf = malloc(buf_size);
1205*af28f636SEnrico Perla - Sun Microsystems 	if (stage2->buf == NULL) {
1206*af28f636SEnrico Perla - Sun Microsystems 		perror(gettext("Memory allocation failed"));
1207*af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
1208*af28f636SEnrico Perla - Sun Microsystems 	}
1209*af28f636SEnrico Perla - Sun Microsystems 	stage2->buf_size = buf_size;
12107ce76caaSEnrico Perla - Sun Microsystems 
1211*af28f636SEnrico Perla - Sun Microsystems 	if (read_in(dev_fd, stage2->buf, buf_size, STAGE2_BLKOFF *
1212*af28f636SEnrico Perla - Sun Microsystems 	    SECTOR_SIZE) != BC_SUCCESS) {
1213*af28f636SEnrico Perla - Sun Microsystems 		perror("read");
1214*af28f636SEnrico Perla - Sun Microsystems 		free(stage2->buf);
1215*af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
12167ce76caaSEnrico Perla - Sun Microsystems 	}
12177ce76caaSEnrico Perla - Sun Microsystems 
1218*af28f636SEnrico Perla - Sun Microsystems 	/* Update pointers. */
1219*af28f636SEnrico Perla - Sun Microsystems 	stage2->file = stage2->buf;
1220*af28f636SEnrico Perla - Sun Microsystems 	stage2->file_size = size;
1221*af28f636SEnrico Perla - Sun Microsystems 	stage2->mboot_off = mboot_off;
1222*af28f636SEnrico Perla - Sun Microsystems 	stage2->mboot = (multiboot_header_t *)(stage2->buf + stage2->mboot_off);
1223*af28f636SEnrico Perla - Sun Microsystems 	stage2->extra = stage2->buf + P2ROUNDUP(stage2->file_size, 8);
12247ce76caaSEnrico Perla - Sun Microsystems 
1225*af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
1226*af28f636SEnrico Perla - Sun Microsystems }
12277ce76caaSEnrico Perla - Sun Microsystems 
1228*af28f636SEnrico Perla - Sun Microsystems static boolean_t
1229*af28f636SEnrico Perla - Sun Microsystems is_update_necessary(ig_data_t *data, char *updt_str)
12307ce76caaSEnrico Perla - Sun Microsystems {
1231*af28f636SEnrico Perla - Sun Microsystems 	bblk_einfo_t	*einfo;
1232*af28f636SEnrico Perla - Sun Microsystems 	bblk_hs_t	stage2_hs;
1233*af28f636SEnrico Perla - Sun Microsystems 	ig_stage2_t	stage2_disk;
1234*af28f636SEnrico Perla - Sun Microsystems 	ig_stage2_t	*stage2_file = &data->stage2;
1235*af28f636SEnrico Perla - Sun Microsystems 	ig_device_t	*device = &data->device;
1236*af28f636SEnrico Perla - Sun Microsystems 	int		dev_fd = device->part_fd;
1237*af28f636SEnrico Perla - Sun Microsystems 
1238*af28f636SEnrico Perla - Sun Microsystems 	assert(data != NULL);
1239*af28f636SEnrico Perla - Sun Microsystems 	assert(device->part_fd != -1);
1240*af28f636SEnrico Perla - Sun Microsystems 
1241*af28f636SEnrico Perla - Sun Microsystems 	bzero(&stage2_disk, sizeof (ig_stage2_t));
1242*af28f636SEnrico Perla - Sun Microsystems 
1243*af28f636SEnrico Perla - Sun Microsystems 	/* Gather stage2 (if present) from the target device. */
1244*af28f636SEnrico Perla - Sun Microsystems 	if (read_stage2_from_disk(dev_fd, &stage2_disk) != BC_SUCCESS) {
1245*af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("Unable to read stage2 from %s\n", device->path);
1246*af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("No multiboot wrapped stage2 on %s\n", device->path);
1247*af28f636SEnrico Perla - Sun Microsystems 		return (B_TRUE);
1248*af28f636SEnrico Perla - Sun Microsystems 	}
12497ce76caaSEnrico Perla - Sun Microsystems 
1250*af28f636SEnrico Perla - Sun Microsystems 	/*
1251*af28f636SEnrico Perla - Sun Microsystems 	 * Look for the extended information structure in the extra payload
1252*af28f636SEnrico Perla - Sun Microsystems 	 * area.
1253*af28f636SEnrico Perla - Sun Microsystems 	 */
1254*af28f636SEnrico Perla - Sun Microsystems 	einfo = find_einfo(stage2_disk.extra);
1255*af28f636SEnrico Perla - Sun Microsystems 	if (einfo == NULL) {
1256*af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("No extended information available\n");
1257*af28f636SEnrico Perla - Sun Microsystems 		return (B_TRUE);
1258*af28f636SEnrico Perla - Sun Microsystems 	}
12597ce76caaSEnrico Perla - Sun Microsystems 
1260*af28f636SEnrico Perla - Sun Microsystems 	if (!do_version || updt_str == NULL) {
1261*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, "WARNING: target device %s has a "
1262*af28f636SEnrico Perla - Sun Microsystems 		    "versioned stage2 that is going to be overwritten by a non "
1263*af28f636SEnrico Perla - Sun Microsystems 		    "versioned one\n", device->path);
1264*af28f636SEnrico Perla - Sun Microsystems 		return (B_TRUE);
1265*af28f636SEnrico Perla - Sun Microsystems 	}
12667ce76caaSEnrico Perla - Sun Microsystems 
1267*af28f636SEnrico Perla - Sun Microsystems 	if (force_update) {
1268*af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("Forcing update of %s bootblock\n", device->path);
1269*af28f636SEnrico Perla - Sun Microsystems 		return (B_TRUE);
1270*af28f636SEnrico Perla - Sun Microsystems 	}
12717ce76caaSEnrico Perla - Sun Microsystems 
1272*af28f636SEnrico Perla - Sun Microsystems 	/* Compare the two extended information structures. */
1273*af28f636SEnrico Perla - Sun Microsystems 	stage2_hs.src_buf = (unsigned char *)stage2_file->file;
1274*af28f636SEnrico Perla - Sun Microsystems 	stage2_hs.src_size = stage2_file->file_size;
1275*af28f636SEnrico Perla - Sun Microsystems 
1276*af28f636SEnrico Perla - Sun Microsystems 	return (einfo_should_update(einfo, &stage2_hs, updt_str));
12777ce76caaSEnrico Perla - Sun Microsystems }
12787ce76caaSEnrico Perla - Sun Microsystems 
12797ce76caaSEnrico Perla - Sun Microsystems 
12807c478bd9Sstevel@tonic-gate #define	START_BLOCK(pos)	(*(ulong_t *)(pos))
12817c478bd9Sstevel@tonic-gate #define	NUM_BLOCK(pos)		(*(ushort_t *)((pos) + 4))
12827c478bd9Sstevel@tonic-gate #define	START_SEG(pos)		(*(ushort_t *)((pos) + 6))
12837c478bd9Sstevel@tonic-gate 
1284*af28f636SEnrico Perla - Sun Microsystems static int
1285*af28f636SEnrico Perla - Sun Microsystems prepare_stage2(ig_data_t *install, char *updt_str)
12867c478bd9Sstevel@tonic-gate {
1287*af28f636SEnrico Perla - Sun Microsystems 	ig_device_t	*device = &install->device;
1288*af28f636SEnrico Perla - Sun Microsystems 	ig_stage2_t	*stage2 = &install->stage2;
1289*af28f636SEnrico Perla - Sun Microsystems 	uint32_t	mboot_off = 0;
1290*af28f636SEnrico Perla - Sun Microsystems 
1291*af28f636SEnrico Perla - Sun Microsystems 	assert(install != NULL);
1292*af28f636SEnrico Perla - Sun Microsystems 	assert(stage2->file != NULL);
1293*af28f636SEnrico Perla - Sun Microsystems 
1294*af28f636SEnrico Perla - Sun Microsystems 	/* New stage2 files come with an embedded stage2. */
1295*af28f636SEnrico Perla - Sun Microsystems 	if (find_multiboot(stage2->file, stage2->file_size, &mboot_off)
1296*af28f636SEnrico Perla - Sun Microsystems 	    != BC_SUCCESS) {
1297*af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("WARNING: no multiboot structure found in stage2, "
1298*af28f636SEnrico Perla - Sun Microsystems 		    "are you using an old GRUB stage2?\n");
1299*af28f636SEnrico Perla - Sun Microsystems 		if (do_version == B_TRUE) {
1300*af28f636SEnrico Perla - Sun Microsystems 			(void) fprintf(stderr, gettext("Versioning requested "
1301*af28f636SEnrico Perla - Sun Microsystems 			    "but stage2 does not support it.. skipping.\n"));
1302*af28f636SEnrico Perla - Sun Microsystems 			do_version = B_FALSE;
1303*af28f636SEnrico Perla - Sun Microsystems 		}
1304*af28f636SEnrico Perla - Sun Microsystems 	} else {
1305*af28f636SEnrico Perla - Sun Microsystems 		/* Keep track of where the multiboot header is. */
1306*af28f636SEnrico Perla - Sun Microsystems 		stage2->mboot_off = mboot_off;
1307*af28f636SEnrico Perla - Sun Microsystems 		stage2->mboot = (multiboot_header_t *)(stage2->file +
1308*af28f636SEnrico Perla - Sun Microsystems 		    mboot_off);
1309*af28f636SEnrico Perla - Sun Microsystems 		if (do_version) {
1310*af28f636SEnrico Perla - Sun Microsystems 			/*
1311*af28f636SEnrico Perla - Sun Microsystems 			 * Adding stage2 information needs to happen before
1312*af28f636SEnrico Perla - Sun Microsystems 			 * we modify the copy of stage2 we have in memory, so
1313*af28f636SEnrico Perla - Sun Microsystems 			 * that the hashing reflects the one of the file.
1314*af28f636SEnrico Perla - Sun Microsystems 			 * An error here is not fatal.
1315*af28f636SEnrico Perla - Sun Microsystems 			 */
1316*af28f636SEnrico Perla - Sun Microsystems 			add_stage2_einfo(stage2, updt_str);
1317*af28f636SEnrico Perla - Sun Microsystems 		}
1318*af28f636SEnrico Perla - Sun Microsystems 		/*
1319*af28f636SEnrico Perla - Sun Microsystems 		 * Fill multiboot information. We add them even without
1320*af28f636SEnrico Perla - Sun Microsystems 		 * versioning to support as much as possible mirroring.
1321*af28f636SEnrico Perla - Sun Microsystems 		 */
1322*af28f636SEnrico Perla - Sun Microsystems 		prepare_fake_multiboot(stage2);
13237ce76caaSEnrico Perla - Sun Microsystems 	}
13247c478bd9Sstevel@tonic-gate 
1325*af28f636SEnrico Perla - Sun Microsystems 	if (is_bootpar(device->type)) {
1326*af28f636SEnrico Perla - Sun Microsystems 		uint32_t	blocklist[SECTOR_SIZE / sizeof (uint32_t)];
1327*af28f636SEnrico Perla - Sun Microsystems 		uint32_t	install_addr = STAGE2_MEMADDR + SECTOR_SIZE;
1328*af28f636SEnrico Perla - Sun Microsystems 		int		i = 0;
1329*af28f636SEnrico Perla - Sun Microsystems 		uchar_t		*pos;
1330*af28f636SEnrico Perla - Sun Microsystems 
1331*af28f636SEnrico Perla - Sun Microsystems 		bzero(blocklist, sizeof (blocklist));
1332*af28f636SEnrico Perla - Sun Microsystems 		if (read_stage2_blocklist(device->part_fd, blocklist) != 0) {
1333*af28f636SEnrico Perla - Sun Microsystems 			(void) fprintf(stderr, gettext("Error reading pcfs "
1334*af28f636SEnrico Perla - Sun Microsystems 			    "stage2 blocklist\n"));
1335*af28f636SEnrico Perla - Sun Microsystems 			return (BC_ERROR);
1336*af28f636SEnrico Perla - Sun Microsystems 		}
1337*af28f636SEnrico Perla - Sun Microsystems 
1338*af28f636SEnrico Perla - Sun Microsystems 		pos = (uchar_t *)stage2->file + STAGE2_BLOCKLIST;
1339*af28f636SEnrico Perla - Sun Microsystems 		stage2->first_sector = device->start_sector + blocklist[0];
1340*af28f636SEnrico Perla - Sun Microsystems 		stage2->pcfs_first_sectors[0] = blocklist[0];
1341*af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("stage2 first sector: %d\n", stage2->first_sector);
13427c478bd9Sstevel@tonic-gate 
13437c478bd9Sstevel@tonic-gate 
13447c478bd9Sstevel@tonic-gate 		if (blocklist[1] > 1) {
13457c478bd9Sstevel@tonic-gate 			blocklist[0]++;
13467c478bd9Sstevel@tonic-gate 			blocklist[1]--;
13477c478bd9Sstevel@tonic-gate 		} else {
13487c478bd9Sstevel@tonic-gate 			i += 2;
13497c478bd9Sstevel@tonic-gate 		}
13507c478bd9Sstevel@tonic-gate 
1351*af28f636SEnrico Perla - Sun Microsystems 		stage2->pcfs_first_sectors[1] = blocklist[i];
13527c478bd9Sstevel@tonic-gate 
13537c478bd9Sstevel@tonic-gate 		while (blocklist[i]) {
13547c478bd9Sstevel@tonic-gate 			if (START_BLOCK(pos - 8) != 0 &&
13557c478bd9Sstevel@tonic-gate 			    START_BLOCK(pos - 8) != blocklist[i + 2]) {
13567c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, PCFS_FRAGMENTED);
1357*af28f636SEnrico Perla - Sun Microsystems 				return (BC_ERROR);
13587c478bd9Sstevel@tonic-gate 			}
1359*af28f636SEnrico Perla - Sun Microsystems 			START_BLOCK(pos) = blocklist[i] + device->start_sector;
13607c478bd9Sstevel@tonic-gate 			START_SEG(pos) = (ushort_t)(install_addr >> 4);
13617c478bd9Sstevel@tonic-gate 			NUM_BLOCK(pos) = blocklist[i + 1];
13627c478bd9Sstevel@tonic-gate 			install_addr += blocklist[i + 1] * SECTOR_SIZE;
13637c478bd9Sstevel@tonic-gate 			pos -= 8;
13647c478bd9Sstevel@tonic-gate 			i += 2;
13657c478bd9Sstevel@tonic-gate 		}
13667c478bd9Sstevel@tonic-gate 	} else {
1367*af28f636SEnrico Perla - Sun Microsystems 		/* Solaris VTOC */
1368*af28f636SEnrico Perla - Sun Microsystems 		stage2->first_sector = device->start_sector + STAGE2_BLKOFF;
1369*af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("stage2 first sector: %d\n", stage2->first_sector);
13707c478bd9Sstevel@tonic-gate 		/*
13717c478bd9Sstevel@tonic-gate 		 * In a solaris partition, stage2 is written to contiguous
13727c478bd9Sstevel@tonic-gate 		 * blocks. So we update the starting block only.
13737c478bd9Sstevel@tonic-gate 		 */
1374*af28f636SEnrico Perla - Sun Microsystems 		*((ulong_t *)(stage2->file + STAGE2_BLOCKLIST)) =
1375*af28f636SEnrico Perla - Sun Microsystems 		    stage2->first_sector + 1;
13767c478bd9Sstevel@tonic-gate 	}
13777c478bd9Sstevel@tonic-gate 
1378*af28f636SEnrico Perla - Sun Microsystems 	/* force lba and set disk partition */
1379*af28f636SEnrico Perla - Sun Microsystems 	*((unsigned char *) (stage2->file + STAGE2_FORCE_LBA)) = 1;
1380*af28f636SEnrico Perla - Sun Microsystems 	*((long *)(stage2->file + STAGE2_INSTALLPART))
1381*af28f636SEnrico Perla - Sun Microsystems 	    = (device->partition << 16) | (device->slice << 8) | 0xff;
1382*af28f636SEnrico Perla - Sun Microsystems 
1383*af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
13847c478bd9Sstevel@tonic-gate }
13857c478bd9Sstevel@tonic-gate 
1386*af28f636SEnrico Perla - Sun Microsystems static int
1387*af28f636SEnrico Perla - Sun Microsystems find_x86_bootpar(struct mboot *mboot, int *part_num, uint32_t *start_sect)
13887c478bd9Sstevel@tonic-gate {
1389*af28f636SEnrico Perla - Sun Microsystems 	int	i;
13907c478bd9Sstevel@tonic-gate 
1391*af28f636SEnrico Perla - Sun Microsystems 	for (i = 0; i < FD_NUMPART; i++) {
1392*af28f636SEnrico Perla - Sun Microsystems 		struct ipart	*part;
13937c478bd9Sstevel@tonic-gate 
1394*af28f636SEnrico Perla - Sun Microsystems 		part = (struct ipart *)mboot->parts + i;
1395*af28f636SEnrico Perla - Sun Microsystems 		if (part->systid == 0xbe) {
1396*af28f636SEnrico Perla - Sun Microsystems 			if (start_sect)
1397*af28f636SEnrico Perla - Sun Microsystems 				*start_sect = part->relsect;
1398*af28f636SEnrico Perla - Sun Microsystems 			if (part_num)
1399*af28f636SEnrico Perla - Sun Microsystems 				*part_num = i;
1400*af28f636SEnrico Perla - Sun Microsystems 			/* solaris boot part */
1401*af28f636SEnrico Perla - Sun Microsystems 			return (BC_SUCCESS);
1402*af28f636SEnrico Perla - Sun Microsystems 		}
1403*af28f636SEnrico Perla - Sun Microsystems 	}
1404*af28f636SEnrico Perla - Sun Microsystems 	return (BC_ERROR);
1405*af28f636SEnrico Perla - Sun Microsystems }
14067c478bd9Sstevel@tonic-gate 
1407*af28f636SEnrico Perla - Sun Microsystems static char *
1408*af28f636SEnrico Perla - Sun Microsystems get_raw_partition_path(ig_device_t *device)
1409*af28f636SEnrico Perla - Sun Microsystems {
1410*af28f636SEnrico Perla - Sun Microsystems 	char	*raw;
1411*af28f636SEnrico Perla - Sun Microsystems 	int	len;
1412*af28f636SEnrico Perla - Sun Microsystems 
1413*af28f636SEnrico Perla - Sun Microsystems 	if (is_bootpar(device->type)) {
1414*af28f636SEnrico Perla - Sun Microsystems 		int		part;
1415*af28f636SEnrico Perla - Sun Microsystems 		struct mboot	*mboot;
1416*af28f636SEnrico Perla - Sun Microsystems 
1417*af28f636SEnrico Perla - Sun Microsystems 		mboot = (struct mboot *)device->boot_sector;
1418*af28f636SEnrico Perla - Sun Microsystems 		if (find_x86_bootpar(mboot, &part, NULL) != BC_SUCCESS) {
1419*af28f636SEnrico Perla - Sun Microsystems 			(void) fprintf(stderr, BOOTPAR_NOTFOUND,
1420*af28f636SEnrico Perla - Sun Microsystems 			    device->path_p0);
1421*af28f636SEnrico Perla - Sun Microsystems 			return (NULL);
14227c478bd9Sstevel@tonic-gate 		}
14237c478bd9Sstevel@tonic-gate 
1424*af28f636SEnrico Perla - Sun Microsystems 		raw = strdup(device->path_p0);
1425*af28f636SEnrico Perla - Sun Microsystems 		if (raw == NULL) {
1426*af28f636SEnrico Perla - Sun Microsystems 			perror(gettext("Memory allocation failed"));
1427*af28f636SEnrico Perla - Sun Microsystems 			return (NULL);
14287c478bd9Sstevel@tonic-gate 		}
1429*af28f636SEnrico Perla - Sun Microsystems 
1430*af28f636SEnrico Perla - Sun Microsystems 		raw[strlen(raw) - 2] = '1' + part;
14317c478bd9Sstevel@tonic-gate 		return (raw);
14327c478bd9Sstevel@tonic-gate 	}
14337c478bd9Sstevel@tonic-gate 
14347c478bd9Sstevel@tonic-gate 	/* For disk, remember slice and return whole fdisk partition  */
1435*af28f636SEnrico Perla - Sun Microsystems 	raw = strdup(device->path);
1436*af28f636SEnrico Perla - Sun Microsystems 	if (raw == NULL) {
1437*af28f636SEnrico Perla - Sun Microsystems 		perror(gettext("Memory allocation failed"));
1438*af28f636SEnrico Perla - Sun Microsystems 		return (NULL);
1439*af28f636SEnrico Perla - Sun Microsystems 	}
1440*af28f636SEnrico Perla - Sun Microsystems 
14417c478bd9Sstevel@tonic-gate 	len = strlen(raw);
14427c478bd9Sstevel@tonic-gate 	if (raw[len - 2] != 's' || raw[len - 1] == '2') {
14437c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, NOT_ROOT_SLICE);
1444*af28f636SEnrico Perla - Sun Microsystems 		free(raw);
1445*af28f636SEnrico Perla - Sun Microsystems 		return (NULL);
14467c478bd9Sstevel@tonic-gate 	}
1447*af28f636SEnrico Perla - Sun Microsystems 	device->slice = atoi(&raw[len - 1]);
14487c478bd9Sstevel@tonic-gate 
14497c478bd9Sstevel@tonic-gate 	raw[len - 2] = 's';
14507c478bd9Sstevel@tonic-gate 	raw[len - 1] = '2';
1451*af28f636SEnrico Perla - Sun Microsystems 
14527c478bd9Sstevel@tonic-gate 	return (raw);
14537c478bd9Sstevel@tonic-gate }
14547c478bd9Sstevel@tonic-gate 
1455*af28f636SEnrico Perla - Sun Microsystems static int
1456*af28f636SEnrico Perla - Sun Microsystems get_raw_partition_fd(ig_device_t *device)
1457*af28f636SEnrico Perla - Sun Microsystems {
1458*af28f636SEnrico Perla - Sun Microsystems 	struct stat	stat = {0};
1459*af28f636SEnrico Perla - Sun Microsystems 	char		*raw;
1460*af28f636SEnrico Perla - Sun Microsystems 
1461*af28f636SEnrico Perla - Sun Microsystems 	raw = get_raw_partition_path(device);
1462*af28f636SEnrico Perla - Sun Microsystems 	if (raw == NULL)
1463*af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
1464*af28f636SEnrico Perla - Sun Microsystems 
1465*af28f636SEnrico Perla - Sun Microsystems 	if (nowrite)
1466*af28f636SEnrico Perla - Sun Microsystems 		device->part_fd = open(raw, O_RDONLY);
1467*af28f636SEnrico Perla - Sun Microsystems 	else
1468*af28f636SEnrico Perla - Sun Microsystems 		device->part_fd = open(raw, O_RDWR);
1469*af28f636SEnrico Perla - Sun Microsystems 
1470*af28f636SEnrico Perla - Sun Microsystems 	if (device->part_fd < 0 || fstat(device->part_fd, &stat) != 0) {
1471*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, OPEN_FAIL, raw);
1472*af28f636SEnrico Perla - Sun Microsystems 		free(raw);
1473*af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
1474*af28f636SEnrico Perla - Sun Microsystems 	}
1475*af28f636SEnrico Perla - Sun Microsystems 
1476*af28f636SEnrico Perla - Sun Microsystems 	if (S_ISCHR(stat.st_mode) == 0) {
1477*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, NOT_RAW_DEVICE, raw);
1478*af28f636SEnrico Perla - Sun Microsystems 		(void) close(device->part_fd);
1479*af28f636SEnrico Perla - Sun Microsystems 		device->part_fd = -1;
1480*af28f636SEnrico Perla - Sun Microsystems 		free(raw);
1481*af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
1482*af28f636SEnrico Perla - Sun Microsystems 	}
1483*af28f636SEnrico Perla - Sun Microsystems 
1484*af28f636SEnrico Perla - Sun Microsystems 	free(raw);
1485*af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
1486*af28f636SEnrico Perla - Sun Microsystems }
1487*af28f636SEnrico Perla - Sun Microsystems 
14887c478bd9Sstevel@tonic-gate #define	TMP_MNTPT	"/tmp/installgrub_pcfs"
1489*af28f636SEnrico Perla - Sun Microsystems static int
1490*af28f636SEnrico Perla - Sun Microsystems copy_stage2_to_pcfs(ig_data_t *install)
14917c478bd9Sstevel@tonic-gate {
1492*af28f636SEnrico Perla - Sun Microsystems 	FILE		*mntfp;
1493*af28f636SEnrico Perla - Sun Microsystems 	int		pcfs_fp;
1494*af28f636SEnrico Perla - Sun Microsystems 	int		status = BC_ERROR;
1495*af28f636SEnrico Perla - Sun Microsystems 	char		buf[SECTOR_SIZE];
1496*af28f636SEnrico Perla - Sun Microsystems 	char		*cp;
1497*af28f636SEnrico Perla - Sun Microsystems 	struct mnttab	mp = {0}, mpref = {0};
1498*af28f636SEnrico Perla - Sun Microsystems 	ig_device_t	*device = &install->device;
1499*af28f636SEnrico Perla - Sun Microsystems 	ig_stage2_t	*stage2 = &install->stage2;
15007c478bd9Sstevel@tonic-gate 
15017c478bd9Sstevel@tonic-gate 	/* convert raw to block device name by removing the first 'r' */
1502*af28f636SEnrico Perla - Sun Microsystems 	(void) strncpy(buf, device->path, sizeof (buf));
15037c478bd9Sstevel@tonic-gate 	buf[sizeof (buf) - 1] = 0;
15047c478bd9Sstevel@tonic-gate 	cp = strchr(buf, 'r');
15057c478bd9Sstevel@tonic-gate 	if (cp == NULL) {
1506*af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, CONVERT_FAIL, device->path);
1507*af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
15087c478bd9Sstevel@tonic-gate 	}
15097c478bd9Sstevel@tonic-gate 	do {
15107c478bd9Sstevel@tonic-gate 		*cp = *(cp + 1);
15117c478bd9Sstevel@tonic-gate 	} while (*(++cp));
15127c478bd9Sstevel@tonic-gate 
15137c478bd9Sstevel@tonic-gate 	/* get the mount point, if any */
15147c478bd9Sstevel@tonic-gate 	mntfp = fopen("/etc/mnttab", "r");
15157c478bd9Sstevel@tonic-gate 	if (mntfp == NULL) {
15167c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, OPEN_FAIL_FILE, "/etc/mnttab");
1517*af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
15187c478bd9Sstevel@tonic-gate 	}
15197c478bd9Sstevel@tonic-gate 
15207c478bd9Sstevel@tonic-gate 	mpref.mnt_special = buf;
15217c478bd9Sstevel@tonic-gate 	if (getmntany(mntfp, &mp, &mpref) != 0) {
15227c478bd9Sstevel@tonic-gate 		char cmd[128];
15237c478bd9Sstevel@tonic-gate 
15247c478bd9Sstevel@tonic-gate 		/* not mounted, try remount */
15257c478bd9Sstevel@tonic-gate 		(void) mkdir(TMP_MNTPT, S_IRWXU);
15267c478bd9Sstevel@tonic-gate 		(void) snprintf(cmd, sizeof (cmd), "mount -F pcfs %s %s",
15277c478bd9Sstevel@tonic-gate 		    buf, TMP_MNTPT);
15287c478bd9Sstevel@tonic-gate 		(void) system(cmd);
15297c478bd9Sstevel@tonic-gate 		rewind(mntfp);
15307c478bd9Sstevel@tonic-gate 		bzero(&mp, sizeof (mp));
15317c478bd9Sstevel@tonic-gate 		if (getmntany(mntfp, &mp, &mpref) != 0) {
15327c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, MOUNT_FAIL, buf);
1533*af28f636SEnrico Perla - Sun Microsystems 			return (BC_ERROR);
15347c478bd9Sstevel@tonic-gate 		}
15357c478bd9Sstevel@tonic-gate 	}
15367c478bd9Sstevel@tonic-gate 
15377c478bd9Sstevel@tonic-gate 	(void) snprintf(buf, sizeof (buf),
15387c478bd9Sstevel@tonic-gate 	    "%s/boot", mp.mnt_mountp);
15397c478bd9Sstevel@tonic-gate 	(void) mkdir(buf, S_IRWXU);
15407c478bd9Sstevel@tonic-gate 	(void) strcat(buf, "/grub");
15417c478bd9Sstevel@tonic-gate 	(void) mkdir(buf, S_IRWXU);
15427c478bd9Sstevel@tonic-gate 
15437c478bd9Sstevel@tonic-gate 	(void) strcat(buf, "/stage2");
15447c478bd9Sstevel@tonic-gate 	pcfs_fp = open(buf, O_WRONLY | O_CREAT, S_IRWXU);
15457c478bd9Sstevel@tonic-gate 	if (pcfs_fp == -1) {
15467c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, OPEN_FAIL_FILE, buf);
15477c478bd9Sstevel@tonic-gate 		perror("open:");
1548*af28f636SEnrico Perla - Sun Microsystems 		goto out;
1549*af28f636SEnrico Perla - Sun Microsystems 	}
1550*af28f636SEnrico Perla - Sun Microsystems 
1551*af28f636SEnrico Perla - Sun Microsystems 	/* write stage2 to the pcfs mounted filesystem. */
1552*af28f636SEnrico Perla - Sun Microsystems 	if (write(pcfs_fp, stage2->file, stage2->file_size)
1553*af28f636SEnrico Perla - Sun Microsystems 	    != stage2->file_size) {
1554*af28f636SEnrico Perla - Sun Microsystems 		perror(gettext("Error writing stage2"));
1555*af28f636SEnrico Perla - Sun Microsystems 		goto out;
15567c478bd9Sstevel@tonic-gate 	}
1557*af28f636SEnrico Perla - Sun Microsystems 
1558*af28f636SEnrico Perla - Sun Microsystems 	status = BC_SUCCESS;
1559*af28f636SEnrico Perla - Sun Microsystems out_fd:
15607c478bd9Sstevel@tonic-gate 	(void) close(pcfs_fp);
1561*af28f636SEnrico Perla - Sun Microsystems out:
15627c478bd9Sstevel@tonic-gate 	(void) umount(TMP_MNTPT);
1563*af28f636SEnrico Perla - Sun Microsystems 	(void) rmdir(TMP_MNTPT);
1564*af28f636SEnrico Perla - Sun Microsystems 	return (status);
15657c478bd9Sstevel@tonic-gate }
1566