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 /*
22af28f636SEnrico Perla - Sun Microsystems  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
2333f5ff17SMilan Jurik  * Copyright 2012 Milan Jurik. All rights reserved.
24*14d44f22SHans Rosenfeld  * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include <stdio.h>
287c478bd9Sstevel@tonic-gate #include <stdlib.h>
297c478bd9Sstevel@tonic-gate #include <libgen.h>
307c478bd9Sstevel@tonic-gate #include <malloc.h>
317c478bd9Sstevel@tonic-gate #include <string.h>
327c478bd9Sstevel@tonic-gate #include <fcntl.h>
337c478bd9Sstevel@tonic-gate #include <unistd.h>
347c478bd9Sstevel@tonic-gate #include <strings.h>
35af28f636SEnrico Perla - Sun Microsystems #include <libintl.h>
36af28f636SEnrico Perla - Sun Microsystems #include <locale.h>
37af28f636SEnrico Perla - Sun Microsystems #include <errno.h>
38af28f636SEnrico Perla - Sun Microsystems #include <libfdisk.h>
39af28f636SEnrico Perla - Sun Microsystems #include <stdarg.h>
40af28f636SEnrico Perla - Sun Microsystems #include <assert.h>
41af28f636SEnrico Perla - Sun Microsystems 
427c478bd9Sstevel@tonic-gate #include <sys/mount.h>
437c478bd9Sstevel@tonic-gate #include <sys/mnttab.h>
447c478bd9Sstevel@tonic-gate #include <sys/dktp/fdisk.h>
45d33344bbSsy #include <sys/dkio.h>
46d33344bbSsy #include <sys/vtoc.h>
47af28f636SEnrico Perla - Sun Microsystems #include <sys/types.h>
48af28f636SEnrico Perla - Sun Microsystems #include <sys/stat.h>
49af28f636SEnrico Perla - Sun Microsystems #include <sys/multiboot.h>
50af28f636SEnrico Perla - Sun Microsystems #include <sys/sysmacros.h>
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate #include "message.h"
53af28f636SEnrico Perla - Sun Microsystems #include "installgrub.h"
54af28f636SEnrico Perla - Sun Microsystems #include "./../common/bblk_einfo.h"
55af28f636SEnrico Perla - Sun Microsystems #include "./../common/boot_utils.h"
56af28f636SEnrico Perla - Sun Microsystems #include "./../common/mboot_extra.h"
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate #ifndef	TEXT_DOMAIN
597c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"SUNW_OST_OSCMD"
607c478bd9Sstevel@tonic-gate #endif
617c478bd9Sstevel@tonic-gate 
62af28f636SEnrico Perla - Sun Microsystems /*
63af28f636SEnrico Perla - Sun Microsystems  * Variables to track installgrub desired mode of operation.
64af28f636SEnrico Perla - Sun Microsystems  * 'nowrite' and 'boot_debug' come from boot_common.h.
65af28f636SEnrico Perla - Sun Microsystems  */
66af28f636SEnrico Perla - Sun Microsystems static boolean_t write_mbr = B_FALSE;
67af28f636SEnrico Perla - Sun Microsystems static boolean_t force_mbr = B_FALSE;
68af28f636SEnrico Perla - Sun Microsystems static boolean_t force_update = B_FALSE;
69af28f636SEnrico Perla - Sun Microsystems static boolean_t do_getinfo = B_FALSE;
70af28f636SEnrico Perla - Sun Microsystems static boolean_t do_version = B_FALSE;
71af28f636SEnrico Perla - Sun Microsystems static boolean_t do_mirror_bblk = B_FALSE;
72af28f636SEnrico Perla - Sun Microsystems static boolean_t strip = B_FALSE;
73af28f636SEnrico Perla - Sun Microsystems static boolean_t verbose_dump = B_FALSE;
74af28f636SEnrico Perla - Sun Microsystems 
75af28f636SEnrico Perla - Sun Microsystems /* Installing the bootblock is the default operation. */
76af28f636SEnrico Perla - Sun Microsystems static boolean_t do_install = B_TRUE;
77af28f636SEnrico Perla - Sun Microsystems 
78af28f636SEnrico Perla - Sun Microsystems /* Versioning string, if present. */
79af28f636SEnrico Perla - Sun Microsystems static char *update_str;
80af28f636SEnrico Perla - Sun Microsystems 
81af28f636SEnrico Perla - Sun Microsystems /*
82af28f636SEnrico Perla - Sun Microsystems  * Temporary buffer to store the first 32K of data looking for a multiboot
83af28f636SEnrico Perla - Sun Microsystems  * signature.
84af28f636SEnrico Perla - Sun Microsystems  */
85af28f636SEnrico Perla - Sun Microsystems char	mboot_scan[MBOOT_SCAN_SIZE];
86af28f636SEnrico Perla - Sun Microsystems 
87af28f636SEnrico Perla - Sun Microsystems /* Function prototypes. */
88af28f636SEnrico Perla - Sun Microsystems static void check_options(char *);
89af28f636SEnrico Perla - Sun Microsystems static int handle_install(char *, char **);
90af28f636SEnrico Perla - Sun Microsystems static int handle_mirror(char *, char **);
91af28f636SEnrico Perla - Sun Microsystems static int handle_getinfo(char *, char **);
92af28f636SEnrico Perla - Sun Microsystems static int commit_to_disk(ig_data_t *, char *);
93af28f636SEnrico Perla - Sun Microsystems static int init_device(ig_device_t *, char *path);
94af28f636SEnrico Perla - Sun Microsystems static void cleanup_device(ig_device_t *);
95af28f636SEnrico Perla - Sun Microsystems static void cleanup_stage2(ig_stage2_t *);
96af28f636SEnrico Perla - Sun Microsystems static int get_start_sector(ig_device_t *);
97af28f636SEnrico Perla - Sun Microsystems static int get_disk_fd(ig_device_t *device);
98af28f636SEnrico Perla - Sun Microsystems static int get_raw_partition_fd(ig_device_t *);
99af28f636SEnrico Perla - Sun Microsystems static char *get_raw_partition_path(ig_device_t *);
100af28f636SEnrico Perla - Sun Microsystems static boolean_t gather_stage2_from_dev(ig_data_t *);
101af28f636SEnrico Perla - Sun Microsystems static int propagate_bootblock(ig_data_t *, ig_data_t *, char *);
102af28f636SEnrico Perla - Sun Microsystems static int find_x86_bootpar(struct mboot *, int *, uint32_t *);
103af28f636SEnrico Perla - Sun Microsystems static int copy_stage2_to_pcfs(ig_data_t *);
104af28f636SEnrico Perla - Sun Microsystems static int write_stage2(ig_data_t *);
105af28f636SEnrico Perla - Sun Microsystems static int write_stage1(ig_data_t *);
1067c478bd9Sstevel@tonic-gate static void usage(char *);
107af28f636SEnrico Perla - Sun Microsystems static int read_stage1_from_file(char *, ig_data_t *);
108af28f636SEnrico Perla - Sun Microsystems static int read_stage2_from_file(char *, ig_data_t *);
109af28f636SEnrico Perla - Sun Microsystems static int read_stage1_from_disk(int, char *);
110af28f636SEnrico Perla - Sun Microsystems static int read_stage2_from_disk(int, ig_stage2_t *);
111af28f636SEnrico Perla - Sun Microsystems static int prepare_stage1(ig_data_t *);
112af28f636SEnrico Perla - Sun Microsystems static int prepare_stage2(ig_data_t *, char *);
113af28f636SEnrico Perla - Sun Microsystems static void prepare_fake_multiboot(ig_stage2_t *);
114af28f636SEnrico Perla - Sun Microsystems static void add_stage2_einfo(ig_stage2_t *, char *updt_str);
115af28f636SEnrico Perla - Sun Microsystems static boolean_t is_update_necessary(ig_data_t *, char *);
1167c478bd9Sstevel@tonic-gate 
117342440ecSPrasad Singamsetty extern int read_stage2_blocklist(int, unsigned int *);
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate int
1207c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
1217c478bd9Sstevel@tonic-gate {
122af28f636SEnrico Perla - Sun Microsystems 	int	opt;
123af28f636SEnrico Perla - Sun Microsystems 	int	params = 3;
124af28f636SEnrico Perla - Sun Microsystems 	int	ret;
125af28f636SEnrico Perla - Sun Microsystems 	char	**handle_args;
126af28f636SEnrico Perla - Sun Microsystems 	char	*progname;
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
1297c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
1307c478bd9Sstevel@tonic-gate 
131af28f636SEnrico Perla - Sun Microsystems 	/*
132af28f636SEnrico Perla - Sun Microsystems 	 * retro-compatibility: installing the bootblock is the default
133af28f636SEnrico Perla - Sun Microsystems 	 * and there is no switch for it.
134af28f636SEnrico Perla - Sun Microsystems 	 */
135af28f636SEnrico Perla - Sun Microsystems 	do_install = B_TRUE;
136af28f636SEnrico Perla - Sun Microsystems 
137af28f636SEnrico Perla - Sun Microsystems 	while ((opt = getopt(argc, argv, "dVMFfmneiu:")) != EOF) {
1387c478bd9Sstevel@tonic-gate 		switch (opt) {
1397c478bd9Sstevel@tonic-gate 		case 'm':
140af28f636SEnrico Perla - Sun Microsystems 			write_mbr = B_TRUE;
1417c478bd9Sstevel@tonic-gate 			break;
1427c478bd9Sstevel@tonic-gate 		case 'n':
143af28f636SEnrico Perla - Sun Microsystems 			nowrite = B_TRUE;
1447c478bd9Sstevel@tonic-gate 			break;
1457c478bd9Sstevel@tonic-gate 		case 'f':
146af28f636SEnrico Perla - Sun Microsystems 			force_mbr = B_TRUE;
1477c478bd9Sstevel@tonic-gate 			break;
1487ce76caaSEnrico Perla - Sun Microsystems 		case 'i':
149af28f636SEnrico Perla - Sun Microsystems 			do_getinfo = B_TRUE;
150af28f636SEnrico Perla - Sun Microsystems 			do_install = B_FALSE;
1517ce76caaSEnrico Perla - Sun Microsystems 			params = 1;
1527ce76caaSEnrico Perla - Sun Microsystems 			break;
153af28f636SEnrico Perla - Sun Microsystems 		case 'V':
154af28f636SEnrico Perla - Sun Microsystems 			verbose_dump = B_TRUE;
155af28f636SEnrico Perla - Sun Microsystems 			break;
156af28f636SEnrico Perla - Sun Microsystems 		case 'd':
157af28f636SEnrico Perla - Sun Microsystems 			boot_debug = B_TRUE;
158af28f636SEnrico Perla - Sun Microsystems 			break;
159af28f636SEnrico Perla - Sun Microsystems 		case 'F':
160af28f636SEnrico Perla - Sun Microsystems 			force_update = B_TRUE;
161af28f636SEnrico Perla - Sun Microsystems 			break;
1627ce76caaSEnrico Perla - Sun Microsystems 		case 'e':
163af28f636SEnrico Perla - Sun Microsystems 			strip = B_TRUE;
164af28f636SEnrico Perla - Sun Microsystems 			break;
165af28f636SEnrico Perla - Sun Microsystems 		case 'M':
166af28f636SEnrico Perla - Sun Microsystems 			do_mirror_bblk = B_TRUE;
167af28f636SEnrico Perla - Sun Microsystems 			do_install = B_FALSE;
168af28f636SEnrico Perla - Sun Microsystems 			params = 2;
1697ce76caaSEnrico Perla - Sun Microsystems 			break;
170af28f636SEnrico Perla - Sun Microsystems 		case 'u':
171af28f636SEnrico Perla - Sun Microsystems 			do_version = B_TRUE;
172af28f636SEnrico Perla - Sun Microsystems 
173af28f636SEnrico Perla - Sun Microsystems 			update_str = malloc(strlen(optarg) + 1);
174af28f636SEnrico Perla - Sun Microsystems 			if (update_str == NULL) {
175af28f636SEnrico Perla - Sun Microsystems 				(void) fprintf(stderr, gettext("Unable to "
176af28f636SEnrico Perla - Sun Microsystems 				    "allocate memory\n"));
177af28f636SEnrico Perla - Sun Microsystems 				exit(BC_ERROR);
178af28f636SEnrico Perla - Sun Microsystems 			}
179af28f636SEnrico Perla - Sun Microsystems 			(void) strlcpy(update_str, optarg, strlen(optarg) + 1);
1807ce76caaSEnrico Perla - Sun Microsystems 			break;
1817c478bd9Sstevel@tonic-gate 		default:
1827c478bd9Sstevel@tonic-gate 			/* fall through to process non-optional args */
1837c478bd9Sstevel@tonic-gate 			break;
1847c478bd9Sstevel@tonic-gate 		}
1857c478bd9Sstevel@tonic-gate 	}
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate 	/* check arguments */
1887ce76caaSEnrico Perla - Sun Microsystems 	if (argc != optind + params) {
1897c478bd9Sstevel@tonic-gate 		usage(argv[0]);
190af28f636SEnrico Perla - Sun Microsystems 		exit(BC_ERROR);
1917c478bd9Sstevel@tonic-gate 	}
1927c478bd9Sstevel@tonic-gate 
193af28f636SEnrico Perla - Sun Microsystems 	/*
194af28f636SEnrico Perla - Sun Microsystems 	 * clean up options (and bail out if an unrecoverable combination is
195af28f636SEnrico Perla - Sun Microsystems 	 * requested.
196af28f636SEnrico Perla - Sun Microsystems 	 */
197af28f636SEnrico Perla - Sun Microsystems 	progname = argv[0];
198af28f636SEnrico Perla - Sun Microsystems 	check_options(progname);
199af28f636SEnrico Perla - Sun Microsystems 	handle_args = argv + optind;
200af28f636SEnrico Perla - Sun Microsystems 
201af28f636SEnrico Perla - Sun Microsystems 	if (nowrite)
2027c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout, DRY_RUN);
203af28f636SEnrico Perla - Sun Microsystems 
204af28f636SEnrico Perla - Sun Microsystems 	if (do_getinfo) {
205af28f636SEnrico Perla - Sun Microsystems 		ret = handle_getinfo(progname, handle_args);
206af28f636SEnrico Perla - Sun Microsystems 	} else if (do_mirror_bblk) {
207af28f636SEnrico Perla - Sun Microsystems 		ret = handle_mirror(progname, handle_args);
208af28f636SEnrico Perla - Sun Microsystems 	} else {
209af28f636SEnrico Perla - Sun Microsystems 		ret = handle_install(progname, handle_args);
210af28f636SEnrico Perla - Sun Microsystems 	}
211af28f636SEnrico Perla - Sun Microsystems 	return (ret);
212af28f636SEnrico Perla - Sun Microsystems }
213af28f636SEnrico Perla - Sun Microsystems 
214af28f636SEnrico Perla - Sun Microsystems #define	MEANINGLESS_OPT	gettext("%s specified but meaningless, ignoring\n")
215af28f636SEnrico Perla - Sun Microsystems static void
216af28f636SEnrico Perla - Sun Microsystems check_options(char *progname)
217af28f636SEnrico Perla - Sun Microsystems {
218af28f636SEnrico Perla - Sun Microsystems 	if (do_getinfo && do_mirror_bblk) {
219af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Only one of -M and -i can be "
220af28f636SEnrico Perla - Sun Microsystems 		    "specified at the same time\n"));
221af28f636SEnrico Perla - Sun Microsystems 		usage(progname);
222af28f636SEnrico Perla - Sun Microsystems 		exit(BC_ERROR);
2237c478bd9Sstevel@tonic-gate 	}
2247c478bd9Sstevel@tonic-gate 
225af28f636SEnrico Perla - Sun Microsystems 	if (do_mirror_bblk) {
226af28f636SEnrico Perla - Sun Microsystems 		/*
227af28f636SEnrico Perla - Sun Microsystems 		 * -u and -F may actually reflect a user intent that is not
228af28f636SEnrico Perla - Sun Microsystems 		 * correct with this command (mirror can be interpreted
229af28f636SEnrico Perla - Sun Microsystems 		 * "similar" to install. Emit a message and continue.
230af28f636SEnrico Perla - Sun Microsystems 		 * -e and -V have no meaning, be quiet here and only report the
231af28f636SEnrico Perla - Sun Microsystems 		 * incongruence if a debug output is requested.
232af28f636SEnrico Perla - Sun Microsystems 		 */
233af28f636SEnrico Perla - Sun Microsystems 		if (do_version) {
234af28f636SEnrico Perla - Sun Microsystems 			(void) fprintf(stderr, MEANINGLESS_OPT, "-u");
235af28f636SEnrico Perla - Sun Microsystems 			do_version = B_FALSE;
236af28f636SEnrico Perla - Sun Microsystems 		}
237af28f636SEnrico Perla - Sun Microsystems 		if (force_update) {
238af28f636SEnrico Perla - Sun Microsystems 			(void) fprintf(stderr, MEANINGLESS_OPT, "-F");
239af28f636SEnrico Perla - Sun Microsystems 			force_update = B_FALSE;
2407ce76caaSEnrico Perla - Sun Microsystems 		}
241af28f636SEnrico Perla - Sun Microsystems 		if (strip || verbose_dump) {
242af28f636SEnrico Perla - Sun Microsystems 			BOOT_DEBUG(MEANINGLESS_OPT, "-e|-V");
243af28f636SEnrico Perla - Sun Microsystems 			strip = B_FALSE;
244af28f636SEnrico Perla - Sun Microsystems 			verbose_dump = B_FALSE;
245af28f636SEnrico Perla - Sun Microsystems 		}
246af28f636SEnrico Perla - Sun Microsystems 	}
2477c478bd9Sstevel@tonic-gate 
248af28f636SEnrico Perla - Sun Microsystems 	if (do_getinfo) {
249af28f636SEnrico Perla - Sun Microsystems 		if (write_mbr || force_mbr || do_version || force_update) {
250af28f636SEnrico Perla - Sun Microsystems 			BOOT_DEBUG(MEANINGLESS_OPT, "-m|-f|-u|-F");
251af28f636SEnrico Perla - Sun Microsystems 			write_mbr = force_mbr = do_version = B_FALSE;
252af28f636SEnrico Perla - Sun Microsystems 			force_update = B_FALSE;
2537ce76caaSEnrico Perla - Sun Microsystems 		}
2547c478bd9Sstevel@tonic-gate 	}
255af28f636SEnrico Perla - Sun Microsystems }
2567c478bd9Sstevel@tonic-gate 
257af28f636SEnrico Perla - Sun Microsystems /*
258af28f636SEnrico Perla - Sun Microsystems  * Install a new stage1/stage2 pair on the specified device. handle_install()
259af28f636SEnrico Perla - Sun Microsystems  * expects argv to contain 3 parameters (the path to stage1, the path to stage2,
260af28f636SEnrico Perla - Sun Microsystems  * the target device).
261af28f636SEnrico Perla - Sun Microsystems  *
262af28f636SEnrico Perla - Sun Microsystems  * Returns:	BC_SUCCESS - if the installation is successful
263af28f636SEnrico Perla - Sun Microsystems  *		BC_ERROR   - if the installation failed
264af28f636SEnrico Perla - Sun Microsystems  *		BC_NOUPDT  - if no installation was performed because the GRUB
265af28f636SEnrico Perla - Sun Microsystems  *		             version currently installed is more recent than the
266af28f636SEnrico Perla - Sun Microsystems  *			     supplied one.
267af28f636SEnrico Perla - Sun Microsystems  *
268af28f636SEnrico Perla - Sun Microsystems  */
269af28f636SEnrico Perla - Sun Microsystems static int
270af28f636SEnrico Perla - Sun Microsystems handle_install(char *progname, char **argv)
271af28f636SEnrico Perla - Sun Microsystems {
272af28f636SEnrico Perla - Sun Microsystems 	ig_data_t	install_data;
273af28f636SEnrico Perla - Sun Microsystems 	char		*stage1_path = NULL;
274af28f636SEnrico Perla - Sun Microsystems 	char		*stage2_path = NULL;
275af28f636SEnrico Perla - Sun Microsystems 	char		*device_path = NULL;
276af28f636SEnrico Perla - Sun Microsystems 	int		ret = BC_ERROR;
277af28f636SEnrico Perla - Sun Microsystems 
278af28f636SEnrico Perla - Sun Microsystems 	stage1_path = strdup(argv[0]);
279af28f636SEnrico Perla - Sun Microsystems 	stage2_path = strdup(argv[1]);
280af28f636SEnrico Perla - Sun Microsystems 	device_path = strdup(argv[2]);
281af28f636SEnrico Perla - Sun Microsystems 
282af28f636SEnrico Perla - Sun Microsystems 	bzero(&install_data, sizeof (ig_data_t));
283af28f636SEnrico Perla - Sun Microsystems 
284af28f636SEnrico Perla - Sun Microsystems 	if (!stage1_path || !stage2_path || !device_path) {
285af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Missing parameter"));
286af28f636SEnrico Perla - Sun Microsystems 		usage(progname);
287af28f636SEnrico Perla - Sun Microsystems 		goto out;
288af28f636SEnrico Perla - Sun Microsystems 	}
2897c478bd9Sstevel@tonic-gate 
290af28f636SEnrico Perla - Sun Microsystems 	BOOT_DEBUG("stage1 path: %s, stage2 path: %s, device: %s\n",
291af28f636SEnrico Perla - Sun Microsystems 	    stage1_path, stage2_path, device_path);
292af28f636SEnrico Perla - Sun Microsystems 
293af28f636SEnrico Perla - Sun Microsystems 	if (init_device(&install_data.device, device_path) != BC_SUCCESS) {
294af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Unable to gather device "
295af28f636SEnrico Perla - Sun Microsystems 		    "information for %s\n"), device_path);
296af28f636SEnrico Perla - Sun Microsystems 		goto out;
297af28f636SEnrico Perla - Sun Microsystems 	}
298af28f636SEnrico Perla - Sun Microsystems 
299af28f636SEnrico Perla - Sun Microsystems 	/* read in stage1 and stage2. */
300af28f636SEnrico Perla - Sun Microsystems 	if (read_stage1_from_file(stage1_path, &install_data) != BC_SUCCESS) {
301af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Error opening %s\n"),
302af28f636SEnrico Perla - Sun Microsystems 		    stage1_path);
303af28f636SEnrico Perla - Sun Microsystems 		goto out_dev;
3047ce76caaSEnrico Perla - Sun Microsystems 	}
3057ce76caaSEnrico Perla - Sun Microsystems 
306af28f636SEnrico Perla - Sun Microsystems 	if (read_stage2_from_file(stage2_path, &install_data) != BC_SUCCESS) {
307af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Error opening %s\n"),
308af28f636SEnrico Perla - Sun Microsystems 		    stage2_path);
309af28f636SEnrico Perla - Sun Microsystems 		goto out_dev;
310af28f636SEnrico Perla - Sun Microsystems 	}
3117c478bd9Sstevel@tonic-gate 
312af28f636SEnrico Perla - Sun Microsystems 	/* We do not support versioning on PCFS. */
313af28f636SEnrico Perla - Sun Microsystems 	if (is_bootpar(install_data.device.type) && do_version)
314af28f636SEnrico Perla - Sun Microsystems 		do_version = B_FALSE;
3157ce76caaSEnrico Perla - Sun Microsystems 
316af28f636SEnrico Perla - Sun Microsystems 	/*
317af28f636SEnrico Perla - Sun Microsystems 	 * is_update_necessary() will take care of checking if versioning and/or
318af28f636SEnrico Perla - Sun Microsystems 	 * forcing the update have been specified. It will also emit a warning
319af28f636SEnrico Perla - Sun Microsystems 	 * if a non-versioned update is attempted over a versioned bootblock.
320af28f636SEnrico Perla - Sun Microsystems 	 */
321af28f636SEnrico Perla - Sun Microsystems 	if (!is_update_necessary(&install_data, update_str)) {
322af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("GRUB version installed "
323af28f636SEnrico Perla - Sun Microsystems 		    "on %s is more recent or identical\n"
324af28f636SEnrico Perla - Sun Microsystems 		    "Use -F to override or install without the -u option\n"),
325af28f636SEnrico Perla - Sun Microsystems 		    device_path);
326af28f636SEnrico Perla - Sun Microsystems 		ret = BC_NOUPDT;
327af28f636SEnrico Perla - Sun Microsystems 		goto out_dev;
3287c478bd9Sstevel@tonic-gate 	}
329af28f636SEnrico Perla - Sun Microsystems 	/*
330af28f636SEnrico Perla - Sun Microsystems 	 * We get here if:
331af28f636SEnrico Perla - Sun Microsystems 	 * - the installed GRUB version is older than the one about to be
332af28f636SEnrico Perla - Sun Microsystems 	 *   installed.
333af28f636SEnrico Perla - Sun Microsystems 	 * - no versioning string has been passed through the command line.
334af28f636SEnrico Perla - Sun Microsystems 	 * - a forced update is requested (-F).
335af28f636SEnrico Perla - Sun Microsystems 	 */
336af28f636SEnrico Perla - Sun Microsystems 	BOOT_DEBUG("Ready to commit to disk\n");
337af28f636SEnrico Perla - Sun Microsystems 	ret = commit_to_disk(&install_data, update_str);
338af28f636SEnrico Perla - Sun Microsystems 
339af28f636SEnrico Perla - Sun Microsystems out_dev:
340af28f636SEnrico Perla - Sun Microsystems 	cleanup_device(&install_data.device);
341af28f636SEnrico Perla - Sun Microsystems out:
342af28f636SEnrico Perla - Sun Microsystems 	free(stage1_path);
343af28f636SEnrico Perla - Sun Microsystems 	free(stage2_path);
344af28f636SEnrico Perla - Sun Microsystems 	free(device_path);
345af28f636SEnrico Perla - Sun Microsystems 	return (ret);
346af28f636SEnrico Perla - Sun Microsystems }
3477c478bd9Sstevel@tonic-gate 
348af28f636SEnrico Perla - Sun Microsystems /*
349af28f636SEnrico Perla - Sun Microsystems  * Retrieves from a device the extended information (einfo) associated to the
350af28f636SEnrico Perla - Sun Microsystems  * installed stage2.
351af28f636SEnrico Perla - Sun Microsystems  * Expects one parameter, the device path, in the form: /dev/rdsk/c?[t?]d?s0.
352af28f636SEnrico Perla - Sun Microsystems  * Returns:
353af28f636SEnrico Perla - Sun Microsystems  *        - BC_SUCCESS (and prints out einfo contents depending on 'flags')
354af28f636SEnrico Perla - Sun Microsystems  *	  - BC_ERROR (on error)
355af28f636SEnrico Perla - Sun Microsystems  *        - BC_NOEINFO (no extended information available)
356af28f636SEnrico Perla - Sun Microsystems  */
357af28f636SEnrico Perla - Sun Microsystems static int
358af28f636SEnrico Perla - Sun Microsystems handle_getinfo(char *progname, char **argv)
359af28f636SEnrico Perla - Sun Microsystems {
360af28f636SEnrico Perla - Sun Microsystems 	ig_data_t	data;
361af28f636SEnrico Perla - Sun Microsystems 	ig_stage2_t	*stage2 = &data.stage2;
362af28f636SEnrico Perla - Sun Microsystems 	ig_device_t	*device = &data.device;
363af28f636SEnrico Perla - Sun Microsystems 	bblk_einfo_t	*einfo;
364af28f636SEnrico Perla - Sun Microsystems 	uint8_t		flags = 0;
365af28f636SEnrico Perla - Sun Microsystems 	uint32_t	size;
366af28f636SEnrico Perla - Sun Microsystems 	char		*device_path;
367af28f636SEnrico Perla - Sun Microsystems 	int		retval = BC_ERROR;
368af28f636SEnrico Perla - Sun Microsystems 	int		ret;
369af28f636SEnrico Perla - Sun Microsystems 
370af28f636SEnrico Perla - Sun Microsystems 	device_path = strdup(argv[0]);
371af28f636SEnrico Perla - Sun Microsystems 	if (!device_path) {
372af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Missing parameter"));
373af28f636SEnrico Perla - Sun Microsystems 		usage(progname);
374af28f636SEnrico Perla - Sun Microsystems 		goto out;
375af28f636SEnrico Perla - Sun Microsystems 	}
376af28f636SEnrico Perla - Sun Microsystems 
377af28f636SEnrico Perla - Sun Microsystems 	bzero(&data, sizeof (ig_data_t));
378af28f636SEnrico Perla - Sun Microsystems 	BOOT_DEBUG("device path: %s\n", device_path);
3797c478bd9Sstevel@tonic-gate 
380af28f636SEnrico Perla - Sun Microsystems 	if (init_device(device, device_path) != BC_SUCCESS) {
381af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Unable to gather device "
382af28f636SEnrico Perla - Sun Microsystems 		    "information for %s\n"), device_path);
383af28f636SEnrico Perla - Sun Microsystems 		goto out_dev;
384af28f636SEnrico Perla - Sun Microsystems 	}
3857c478bd9Sstevel@tonic-gate 
386af28f636SEnrico Perla - Sun Microsystems 	if (is_bootpar(device->type)) {
387af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Versioning not supported on "
388af28f636SEnrico Perla - Sun Microsystems 		    "PCFS\n"));
389af28f636SEnrico Perla - Sun Microsystems 		goto out_dev;
390af28f636SEnrico Perla - Sun Microsystems 	}
3917c478bd9Sstevel@tonic-gate 
392af28f636SEnrico Perla - Sun Microsystems 	ret = read_stage2_from_disk(device->part_fd, stage2);
393af28f636SEnrico Perla - Sun Microsystems 	if (ret == BC_ERROR) {
394af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Error reading stage2 from "
395af28f636SEnrico Perla - Sun Microsystems 		    "%s\n"), device_path);
396af28f636SEnrico Perla - Sun Microsystems 		goto out_dev;
397af28f636SEnrico Perla - Sun Microsystems 	}
3987ce76caaSEnrico Perla - Sun Microsystems 
399af28f636SEnrico Perla - Sun Microsystems 	if (ret == BC_NOEXTRA) {
400af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, gettext("No multiboot header found on "
401af28f636SEnrico Perla - Sun Microsystems 		    "%s, unable to locate extra information area\n"),
402af28f636SEnrico Perla - Sun Microsystems 		    device_path);
403af28f636SEnrico Perla - Sun Microsystems 		retval = BC_NOEINFO;
404af28f636SEnrico Perla - Sun Microsystems 		goto out_dev;
405af28f636SEnrico Perla - Sun Microsystems 	}
4067c478bd9Sstevel@tonic-gate 
407*14d44f22SHans Rosenfeld 	einfo = find_einfo(stage2->extra, stage2->extra_size);
408af28f636SEnrico Perla - Sun Microsystems 	if (einfo == NULL) {
409af28f636SEnrico Perla - Sun Microsystems 		retval = BC_NOEINFO;
410af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("No extended information "
411af28f636SEnrico Perla - Sun Microsystems 		    "found\n"));
412af28f636SEnrico Perla - Sun Microsystems 		goto out_dev;
413af28f636SEnrico Perla - Sun Microsystems 	}
414af28f636SEnrico Perla - Sun Microsystems 
415af28f636SEnrico Perla - Sun Microsystems 	/* Print the extended information. */
416af28f636SEnrico Perla - Sun Microsystems 	if (strip)
417af28f636SEnrico Perla - Sun Microsystems 		flags |= EINFO_EASY_PARSE;
418af28f636SEnrico Perla - Sun Microsystems 	if (verbose_dump)
419af28f636SEnrico Perla - Sun Microsystems 		flags |= EINFO_PRINT_HEADER;
420af28f636SEnrico Perla - Sun Microsystems 
421af28f636SEnrico Perla - Sun Microsystems 	size = stage2->buf_size - P2ROUNDUP(stage2->file_size, 8);
422af28f636SEnrico Perla - Sun Microsystems 	print_einfo(flags, einfo, size);
423af28f636SEnrico Perla - Sun Microsystems 	retval = BC_SUCCESS;
424af28f636SEnrico Perla - Sun Microsystems 
425af28f636SEnrico Perla - Sun Microsystems out_dev:
426af28f636SEnrico Perla - Sun Microsystems 	cleanup_device(&data.device);
427af28f636SEnrico Perla - Sun Microsystems out:
428af28f636SEnrico Perla - Sun Microsystems 	free(device_path);
429af28f636SEnrico Perla - Sun Microsystems 	return (retval);
4307c478bd9Sstevel@tonic-gate }
4317c478bd9Sstevel@tonic-gate 
432af28f636SEnrico Perla - Sun Microsystems /*
433af28f636SEnrico Perla - Sun Microsystems  * Attempt to mirror (propagate) the current stage2 over the attaching disk.
434af28f636SEnrico Perla - Sun Microsystems  *
435af28f636SEnrico Perla - Sun Microsystems  * Returns:
436af28f636SEnrico Perla - Sun Microsystems  *	- BC_SUCCESS (a successful propagation happened)
437af28f636SEnrico Perla - Sun Microsystems  *	- BC_ERROR (an error occurred)
438af28f636SEnrico Perla - Sun Microsystems  *	- BC_NOEXTRA (it is not possible to dump the current bootblock since
439af28f636SEnrico Perla - Sun Microsystems  *			there is no multiboot information)
440af28f636SEnrico Perla - Sun Microsystems  */
441af28f636SEnrico Perla - Sun Microsystems static int
442af28f636SEnrico Perla - Sun Microsystems handle_mirror(char *progname, char **argv)
4437c478bd9Sstevel@tonic-gate {
444af28f636SEnrico Perla - Sun Microsystems 	ig_data_t	curr_data;
445af28f636SEnrico Perla - Sun Microsystems 	ig_data_t	attach_data;
446af28f636SEnrico Perla - Sun Microsystems 	ig_device_t	*curr_device = &curr_data.device;
447af28f636SEnrico Perla - Sun Microsystems 	ig_device_t	*attach_device = &attach_data.device;
448af28f636SEnrico Perla - Sun Microsystems 	ig_stage2_t	*stage2_curr = &curr_data.stage2;
449af28f636SEnrico Perla - Sun Microsystems 	ig_stage2_t	*stage2_attach = &attach_data.stage2;
450af28f636SEnrico Perla - Sun Microsystems 	bblk_einfo_t	*einfo_curr = NULL;
451af28f636SEnrico Perla - Sun Microsystems 	char		*curr_device_path;
452af28f636SEnrico Perla - Sun Microsystems 	char		*attach_device_path;
453af28f636SEnrico Perla - Sun Microsystems 	char		*updt_str = NULL;
454af28f636SEnrico Perla - Sun Microsystems 	int		retval = BC_ERROR;
455af28f636SEnrico Perla - Sun Microsystems 	int		ret;
456af28f636SEnrico Perla - Sun Microsystems 
457af28f636SEnrico Perla - Sun Microsystems 	curr_device_path = strdup(argv[0]);
458af28f636SEnrico Perla - Sun Microsystems 	attach_device_path = strdup(argv[1]);
459af28f636SEnrico Perla - Sun Microsystems 
460af28f636SEnrico Perla - Sun Microsystems 	if (!curr_device_path || !attach_device_path) {
461af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Missing parameter"));
462af28f636SEnrico Perla - Sun Microsystems 		usage(progname);
463af28f636SEnrico Perla - Sun Microsystems 		goto out;
464af28f636SEnrico Perla - Sun Microsystems 	}
465af28f636SEnrico Perla - Sun Microsystems 	BOOT_DEBUG("Current device path is: %s, attaching device path is: "
466af28f636SEnrico Perla - Sun Microsystems 	    " %s\n", curr_device_path, attach_device_path);
467af28f636SEnrico Perla - Sun Microsystems 
468af28f636SEnrico Perla - Sun Microsystems 	bzero(&curr_data, sizeof (ig_data_t));
469af28f636SEnrico Perla - Sun Microsystems 	bzero(&attach_data, sizeof (ig_data_t));
470af28f636SEnrico Perla - Sun Microsystems 
471af28f636SEnrico Perla - Sun Microsystems 	if (init_device(curr_device, curr_device_path) != BC_SUCCESS) {
472af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Unable to gather device "
473af28f636SEnrico Perla - Sun Microsystems 		    "information for %s (current device)\n"), curr_device_path);
474af28f636SEnrico Perla - Sun Microsystems 		goto out_currdev;
475af28f636SEnrico Perla - Sun Microsystems 	}
476af28f636SEnrico Perla - Sun Microsystems 
477af28f636SEnrico Perla - Sun Microsystems 	if (init_device(attach_device, attach_device_path) != BC_SUCCESS) {
478af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Unable to gather device "
479af28f636SEnrico Perla - Sun Microsystems 		    "information for %s (attaching device)\n"),
480af28f636SEnrico Perla - Sun Microsystems 		    attach_device_path);
481af28f636SEnrico Perla - Sun Microsystems 		goto out_devs;
4827fc5d2a4SVikram Hegde 	}
4837fc5d2a4SVikram Hegde 
484af28f636SEnrico Perla - Sun Microsystems 	if (is_bootpar(curr_device->type) || is_bootpar(attach_device->type)) {
485af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("boot block mirroring is not "
486af28f636SEnrico Perla - Sun Microsystems 		    "supported on PCFS\n"));
487af28f636SEnrico Perla - Sun Microsystems 		goto out_devs;
488af28f636SEnrico Perla - Sun Microsystems 	}
489af28f636SEnrico Perla - Sun Microsystems 
490af28f636SEnrico Perla - Sun Microsystems 	ret = read_stage2_from_disk(curr_device->part_fd, stage2_curr);
491af28f636SEnrico Perla - Sun Microsystems 	if (ret == BC_ERROR) {
492af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("Error reading first stage2 blocks from %s\n",
493af28f636SEnrico Perla - Sun Microsystems 		    curr_device->path);
494af28f636SEnrico Perla - Sun Microsystems 		retval = BC_ERROR;
495af28f636SEnrico Perla - Sun Microsystems 		goto out_devs;
496af28f636SEnrico Perla - Sun Microsystems 	}
497af28f636SEnrico Perla - Sun Microsystems 
498af28f636SEnrico Perla - Sun Microsystems 	if (ret == BC_NOEXTRA) {
499af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("No multiboot header found on %s, unable to grab "
500af28f636SEnrico Perla - Sun Microsystems 		    "stage2\n", curr_device->path);
501af28f636SEnrico Perla - Sun Microsystems 		retval = BC_NOEXTRA;
502af28f636SEnrico Perla - Sun Microsystems 		goto out_devs;
503af28f636SEnrico Perla - Sun Microsystems 	}
504af28f636SEnrico Perla - Sun Microsystems 
505*14d44f22SHans Rosenfeld 	einfo_curr = find_einfo(stage2_curr->extra, stage2_curr->extra_size);
506af28f636SEnrico Perla - Sun Microsystems 	if (einfo_curr != NULL)
507af28f636SEnrico Perla - Sun Microsystems 		updt_str = einfo_get_string(einfo_curr);
508af28f636SEnrico Perla - Sun Microsystems 
509af28f636SEnrico Perla - Sun Microsystems 	write_mbr = B_TRUE;
510af28f636SEnrico Perla - Sun Microsystems 	force_mbr = B_TRUE;
511af28f636SEnrico Perla - Sun Microsystems 	retval = propagate_bootblock(&curr_data, &attach_data, updt_str);
512af28f636SEnrico Perla - Sun Microsystems 	cleanup_stage2(stage2_curr);
513af28f636SEnrico Perla - Sun Microsystems 	cleanup_stage2(stage2_attach);
514af28f636SEnrico Perla - Sun Microsystems 
515af28f636SEnrico Perla - Sun Microsystems out_devs:
516af28f636SEnrico Perla - Sun Microsystems 	cleanup_device(attach_device);
517af28f636SEnrico Perla - Sun Microsystems out_currdev:
518af28f636SEnrico Perla - Sun Microsystems 	cleanup_device(curr_device);
519af28f636SEnrico Perla - Sun Microsystems out:
520af28f636SEnrico Perla - Sun Microsystems 	free(curr_device_path);
521af28f636SEnrico Perla - Sun Microsystems 	free(attach_device_path);
522af28f636SEnrico Perla - Sun Microsystems 	return (retval);
523af28f636SEnrico Perla - Sun Microsystems }
524af28f636SEnrico Perla - Sun Microsystems 
525af28f636SEnrico Perla - Sun Microsystems static int
526af28f636SEnrico Perla - Sun Microsystems commit_to_disk(ig_data_t *install, char *updt_str)
527af28f636SEnrico Perla - Sun Microsystems {
528af28f636SEnrico Perla - Sun Microsystems 	assert(install != NULL);
5297fc5d2a4SVikram Hegde 	/*
530af28f636SEnrico Perla - Sun Microsystems 	 * vanilla stage1 and stage2 need to be updated at runtime.
531af28f636SEnrico Perla - Sun Microsystems 	 * Update stage2 before stage1 because stage1 needs to know the first
532af28f636SEnrico Perla - Sun Microsystems 	 * sector stage2 will be written to.
5337fc5d2a4SVikram Hegde 	 */
534af28f636SEnrico Perla - Sun Microsystems 	if (prepare_stage2(install, updt_str) != BC_SUCCESS) {
535af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Error building stage2\n"));
536af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
537af28f636SEnrico Perla - Sun Microsystems 	}
538af28f636SEnrico Perla - Sun Microsystems 	if (prepare_stage1(install) != BC_SUCCESS) {
539af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Error building stage1\n"));
540af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
541af28f636SEnrico Perla - Sun Microsystems 	}
542af28f636SEnrico Perla - Sun Microsystems 
543af28f636SEnrico Perla - Sun Microsystems 	/* Write stage2 out to disk. */
544af28f636SEnrico Perla - Sun Microsystems 	if (write_stage2(install) != BC_SUCCESS) {
545af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Error writing stage2 to "
546af28f636SEnrico Perla - Sun Microsystems 		    "disk\n"));
547af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
548af28f636SEnrico Perla - Sun Microsystems 	}
549af28f636SEnrico Perla - Sun Microsystems 
550af28f636SEnrico Perla - Sun Microsystems 	/* Write stage1 to disk and, if requested, to the MBR. */
551af28f636SEnrico Perla - Sun Microsystems 	if (write_stage1(install) != BC_SUCCESS) {
552af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Error writing stage1 to "
553af28f636SEnrico Perla - Sun Microsystems 		    "disk\n"));
554af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
555af28f636SEnrico Perla - Sun Microsystems 	}
556af28f636SEnrico Perla - Sun Microsystems 
557af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
558af28f636SEnrico Perla - Sun Microsystems }
559af28f636SEnrico Perla - Sun Microsystems 
560af28f636SEnrico Perla - Sun Microsystems /*
561af28f636SEnrico Perla - Sun Microsystems  * Propagate the bootblock on the source disk to the destination disk and
562af28f636SEnrico Perla - Sun Microsystems  * version it with 'updt_str' in the process. Since we cannot trust any data
563af28f636SEnrico Perla - Sun Microsystems  * on the attaching disk, we do not perform any specific check on a potential
564af28f636SEnrico Perla - Sun Microsystems  * target extended information structure and we just blindly update.
565af28f636SEnrico Perla - Sun Microsystems  */
566af28f636SEnrico Perla - Sun Microsystems static int
567af28f636SEnrico Perla - Sun Microsystems propagate_bootblock(ig_data_t *source, ig_data_t *target, char *updt_str)
568af28f636SEnrico Perla - Sun Microsystems {
569af28f636SEnrico Perla - Sun Microsystems 	ig_device_t	*src_device = &source->device;
570af28f636SEnrico Perla - Sun Microsystems 	ig_device_t	*dest_device = &target->device;
571af28f636SEnrico Perla - Sun Microsystems 	ig_stage2_t	*src_stage2 = &source->stage2;
572af28f636SEnrico Perla - Sun Microsystems 	ig_stage2_t	*dest_stage2 = &target->stage2;
573af28f636SEnrico Perla - Sun Microsystems 	uint32_t	buf_size;
574af28f636SEnrico Perla - Sun Microsystems 	int		retval;
575af28f636SEnrico Perla - Sun Microsystems 
576af28f636SEnrico Perla - Sun Microsystems 	assert(source != NULL);
577af28f636SEnrico Perla - Sun Microsystems 	assert(target != NULL);
578af28f636SEnrico Perla - Sun Microsystems 
579af28f636SEnrico Perla - Sun Microsystems 	/* read in stage1 from the source disk. */
580af28f636SEnrico Perla - Sun Microsystems 	if (read_stage1_from_disk(src_device->part_fd, target->stage1_buf)
581af28f636SEnrico Perla - Sun Microsystems 	    != BC_SUCCESS)
582af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
583af28f636SEnrico Perla - Sun Microsystems 
584af28f636SEnrico Perla - Sun Microsystems 	/* Prepare target stage2 for commit_to_disk. */
585af28f636SEnrico Perla - Sun Microsystems 	cleanup_stage2(dest_stage2);
586af28f636SEnrico Perla - Sun Microsystems 
587af28f636SEnrico Perla - Sun Microsystems 	if (updt_str != NULL)
588af28f636SEnrico Perla - Sun Microsystems 		do_version = B_TRUE;
589af28f636SEnrico Perla - Sun Microsystems 	else
590af28f636SEnrico Perla - Sun Microsystems 		do_version = B_FALSE;
591af28f636SEnrico Perla - Sun Microsystems 
592af28f636SEnrico Perla - Sun Microsystems 	buf_size = src_stage2->file_size + SECTOR_SIZE;
593af28f636SEnrico Perla - Sun Microsystems 
594af28f636SEnrico Perla - Sun Microsystems 	dest_stage2->buf_size = P2ROUNDUP(buf_size, SECTOR_SIZE);
595af28f636SEnrico Perla - Sun Microsystems 	dest_stage2->buf = malloc(dest_stage2->buf_size);
596af28f636SEnrico Perla - Sun Microsystems 	if (dest_stage2->buf == NULL) {
597af28f636SEnrico Perla - Sun Microsystems 		perror(gettext("Memory allocation failed"));
598af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
599af28f636SEnrico Perla - Sun Microsystems 	}
600af28f636SEnrico Perla - Sun Microsystems 	dest_stage2->file = dest_stage2->buf;
601af28f636SEnrico Perla - Sun Microsystems 	dest_stage2->file_size = src_stage2->file_size;
602af28f636SEnrico Perla - Sun Microsystems 	memcpy(dest_stage2->file, src_stage2->file, dest_stage2->file_size);
603af28f636SEnrico Perla - Sun Microsystems 	dest_stage2->extra = dest_stage2->buf +
604af28f636SEnrico Perla - Sun Microsystems 	    P2ROUNDUP(dest_stage2->file_size, 8);
605af28f636SEnrico Perla - Sun Microsystems 
606af28f636SEnrico Perla - Sun Microsystems 	/* If we get down here we do have a mboot structure. */
607af28f636SEnrico Perla - Sun Microsystems 	assert(src_stage2->mboot);
608af28f636SEnrico Perla - Sun Microsystems 
609af28f636SEnrico Perla - Sun Microsystems 	dest_stage2->mboot_off = src_stage2->mboot_off;
610af28f636SEnrico Perla - Sun Microsystems 	dest_stage2->mboot = (multiboot_header_t *)(dest_stage2->buf +
611af28f636SEnrico Perla - Sun Microsystems 	    dest_stage2->mboot_off);
612af28f636SEnrico Perla - Sun Microsystems 
613af28f636SEnrico Perla - Sun Microsystems 	(void) fprintf(stdout, gettext("Propagating %s stage1/stage2 to %s\n"),
614af28f636SEnrico Perla - Sun Microsystems 	    src_device->path, dest_device->path);
615af28f636SEnrico Perla - Sun Microsystems 	retval = commit_to_disk(target, updt_str);
616af28f636SEnrico Perla - Sun Microsystems 
617af28f636SEnrico Perla - Sun Microsystems 	return (retval);
618af28f636SEnrico Perla - Sun Microsystems }
619af28f636SEnrico Perla - Sun Microsystems 
620af28f636SEnrico Perla - Sun Microsystems /*
621af28f636SEnrico Perla - Sun Microsystems  * open the device and fill the various members of ig_device_t.
622af28f636SEnrico Perla - Sun Microsystems  */
623af28f636SEnrico Perla - Sun Microsystems static int
624af28f636SEnrico Perla - Sun Microsystems init_device(ig_device_t *device, char *path)
625af28f636SEnrico Perla - Sun Microsystems {
626af28f636SEnrico Perla - Sun Microsystems 	bzero(device, sizeof (*device));
627af28f636SEnrico Perla - Sun Microsystems 	device->part_fd = -1;
628af28f636SEnrico Perla - Sun Microsystems 	device->disk_fd = -1;
629af28f636SEnrico Perla - Sun Microsystems 	device->path_p0 = NULL;
630af28f636SEnrico Perla - Sun Microsystems 
631af28f636SEnrico Perla - Sun Microsystems 	device->path = strdup(path);
632af28f636SEnrico Perla - Sun Microsystems 	if (device->path == NULL) {
633af28f636SEnrico Perla - Sun Microsystems 		perror(gettext("Memory allocation failed"));
634af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
635af28f636SEnrico Perla - Sun Microsystems 	}
636af28f636SEnrico Perla - Sun Microsystems 
637af28f636SEnrico Perla - Sun Microsystems 	if (strstr(device->path, "diskette")) {
638af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("installing GRUB to a floppy "
639af28f636SEnrico Perla - Sun Microsystems 		    "disk is no longer supported\n"));
640af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
641af28f636SEnrico Perla - Sun Microsystems 	}
642af28f636SEnrico Perla - Sun Microsystems 
643af28f636SEnrico Perla - Sun Microsystems 	/* Detect if the target device is a pcfs partition. */
644af28f636SEnrico Perla - Sun Microsystems 	if (strstr(device->path, "p0:boot"))
645af28f636SEnrico Perla - Sun Microsystems 		device->type = IG_DEV_X86BOOTPAR;
646af28f636SEnrico Perla - Sun Microsystems 
647af28f636SEnrico Perla - Sun Microsystems 	if (get_disk_fd(device) != BC_SUCCESS)
648af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
649af28f636SEnrico Perla - Sun Microsystems 
650af28f636SEnrico Perla - Sun Microsystems 	/* read in the device boot sector. */
651af28f636SEnrico Perla - Sun Microsystems 	if (read(device->disk_fd, device->boot_sector, SECTOR_SIZE)
652af28f636SEnrico Perla - Sun Microsystems 	    != SECTOR_SIZE) {
653af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, gettext("Error reading boot sector\n"));
654af28f636SEnrico Perla - Sun Microsystems 		perror("read");
655af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
656af28f636SEnrico Perla - Sun Microsystems 	}
657af28f636SEnrico Perla - Sun Microsystems 
658af28f636SEnrico Perla - Sun Microsystems 	if (get_raw_partition_fd(device) != BC_SUCCESS)
659af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
660af28f636SEnrico Perla - Sun Microsystems 
661af28f636SEnrico Perla - Sun Microsystems 	if (get_start_sector(device) != BC_SUCCESS)
662af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
663af28f636SEnrico Perla - Sun Microsystems 
664af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
665af28f636SEnrico Perla - Sun Microsystems }
666af28f636SEnrico Perla - Sun Microsystems 
667af28f636SEnrico Perla - Sun Microsystems static void
668af28f636SEnrico Perla - Sun Microsystems cleanup_device(ig_device_t *device)
669af28f636SEnrico Perla - Sun Microsystems {
670af28f636SEnrico Perla - Sun Microsystems 	if (device->path)
671af28f636SEnrico Perla - Sun Microsystems 		free(device->path);
672af28f636SEnrico Perla - Sun Microsystems 	if (device->path_p0)
673af28f636SEnrico Perla - Sun Microsystems 		free(device->path_p0);
674af28f636SEnrico Perla - Sun Microsystems 
675af28f636SEnrico Perla - Sun Microsystems 	if (device->part_fd != -1)
676af28f636SEnrico Perla - Sun Microsystems 		(void) close(device->part_fd);
677af28f636SEnrico Perla - Sun Microsystems 	if (device->disk_fd != -1)
678af28f636SEnrico Perla - Sun Microsystems 		(void) close(device->disk_fd);
679af28f636SEnrico Perla - Sun Microsystems 
680af28f636SEnrico Perla - Sun Microsystems 	bzero(device, sizeof (ig_device_t));
681af28f636SEnrico Perla - Sun Microsystems 	device->part_fd = -1;
682af28f636SEnrico Perla - Sun Microsystems 	device->disk_fd = -1;
683af28f636SEnrico Perla - Sun Microsystems }
684af28f636SEnrico Perla - Sun Microsystems 
685af28f636SEnrico Perla - Sun Microsystems static void
686af28f636SEnrico Perla - Sun Microsystems cleanup_stage2(ig_stage2_t *stage2)
687af28f636SEnrico Perla - Sun Microsystems {
688af28f636SEnrico Perla - Sun Microsystems 	if (stage2->buf)
689af28f636SEnrico Perla - Sun Microsystems 		free(stage2->buf);
690af28f636SEnrico Perla - Sun Microsystems 	bzero(stage2, sizeof (ig_stage2_t));
691af28f636SEnrico Perla - Sun Microsystems }
692af28f636SEnrico Perla - Sun Microsystems 
693af28f636SEnrico Perla - Sun Microsystems static int
694af28f636SEnrico Perla - Sun Microsystems get_start_sector(ig_device_t *device)
695af28f636SEnrico Perla - Sun Microsystems {
696af28f636SEnrico Perla - Sun Microsystems 	uint32_t		secnum = 0, numsec = 0;
697af28f636SEnrico Perla - Sun Microsystems 	int			i, pno, rval, log_part = 0;
698af28f636SEnrico Perla - Sun Microsystems 	struct mboot		*mboot;
699af28f636SEnrico Perla - Sun Microsystems 	struct ipart		*part;
700af28f636SEnrico Perla - Sun Microsystems 	ext_part_t		*epp;
701af28f636SEnrico Perla - Sun Microsystems 	struct part_info	dkpi;
702af28f636SEnrico Perla - Sun Microsystems 	struct extpart_info	edkpi;
703af28f636SEnrico Perla - Sun Microsystems 
704af28f636SEnrico Perla - Sun Microsystems 	mboot = (struct mboot *)device->boot_sector;
705af28f636SEnrico Perla - Sun Microsystems 
706af28f636SEnrico Perla - Sun Microsystems 	if (is_bootpar(device->type)) {
707af28f636SEnrico Perla - Sun Microsystems 		if (find_x86_bootpar(mboot, &pno, &secnum) != BC_SUCCESS) {
708af28f636SEnrico Perla - Sun Microsystems 			(void) fprintf(stderr, NOBOOTPAR);
709af28f636SEnrico Perla - Sun Microsystems 			return (BC_ERROR);
710af28f636SEnrico Perla - Sun Microsystems 		} else {
711af28f636SEnrico Perla - Sun Microsystems 			device->start_sector = secnum;
712af28f636SEnrico Perla - Sun Microsystems 			device->partition = pno;
713af28f636SEnrico Perla - Sun Microsystems 			goto found_part;
714af28f636SEnrico Perla - Sun Microsystems 		}
7157fc5d2a4SVikram Hegde 	}
7167fc5d2a4SVikram Hegde 
7177fc5d2a4SVikram Hegde 	/*
718af28f636SEnrico Perla - Sun Microsystems 	 * Search for Solaris fdisk partition
7197fc5d2a4SVikram Hegde 	 * Get the solaris partition information from the device
7207fc5d2a4SVikram Hegde 	 * and compare the offset of S2 with offset of solaris partition
7217fc5d2a4SVikram Hegde 	 * from fdisk partition table.
7227fc5d2a4SVikram Hegde 	 */
723af28f636SEnrico Perla - Sun Microsystems 	if (ioctl(device->part_fd, DKIOCEXTPARTINFO, &edkpi) < 0) {
724af28f636SEnrico Perla - Sun Microsystems 		if (ioctl(device->part_fd, DKIOCPARTINFO, &dkpi) < 0) {
7257fc5d2a4SVikram Hegde 			(void) fprintf(stderr, PART_FAIL);
726af28f636SEnrico Perla - Sun Microsystems 			return (BC_ERROR);
7277fc5d2a4SVikram Hegde 		} else {
7287fc5d2a4SVikram Hegde 			edkpi.p_start = dkpi.p_start;
7297fc5d2a4SVikram Hegde 		}
7307fc5d2a4SVikram Hegde 	}
7317fc5d2a4SVikram Hegde 
7327fc5d2a4SVikram Hegde 	for (i = 0; i < FD_NUMPART; i++) {
7337fc5d2a4SVikram Hegde 		part = (struct ipart *)mboot->parts + i;
7347fc5d2a4SVikram Hegde 
7357fc5d2a4SVikram Hegde 		if (part->relsect == 0) {
7367fc5d2a4SVikram Hegde 			(void) fprintf(stderr, BAD_PART, i);
737af28f636SEnrico Perla - Sun Microsystems 			return (BC_ERROR);
7387fc5d2a4SVikram Hegde 		}
7397fc5d2a4SVikram Hegde 
7407fc5d2a4SVikram Hegde 		if (edkpi.p_start >= part->relsect &&
7417fc5d2a4SVikram Hegde 		    edkpi.p_start < (part->relsect + part->numsect)) {
7427fc5d2a4SVikram Hegde 			/* Found the partition */
7437fc5d2a4SVikram Hegde 			break;
744d33344bbSsy 		}
745d33344bbSsy 	}
746d33344bbSsy 
7477fc5d2a4SVikram Hegde 	if (i == FD_NUMPART) {
7487fc5d2a4SVikram Hegde 		/* No solaris fdisk partitions (primary or logical) */
7497fc5d2a4SVikram Hegde 		(void) fprintf(stderr, NOSOLPAR);
750af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
7517fc5d2a4SVikram Hegde 	}
7527fc5d2a4SVikram Hegde 
7537fc5d2a4SVikram Hegde 	/*
7547fc5d2a4SVikram Hegde 	 * We have found a Solaris fdisk partition (primary or extended)
7557fc5d2a4SVikram Hegde 	 * Handle the simple case first: Solaris in a primary partition
7567fc5d2a4SVikram Hegde 	 */
7577fc5d2a4SVikram Hegde 	if (!fdisk_is_dos_extended(part->systid)) {
758af28f636SEnrico Perla - Sun Microsystems 		device->start_sector = part->relsect;
759af28f636SEnrico Perla - Sun Microsystems 		device->partition = i;
7607fc5d2a4SVikram Hegde 		goto found_part;
7617fc5d2a4SVikram Hegde 	}
7627fc5d2a4SVikram Hegde 
7637fc5d2a4SVikram Hegde 	/*
7647fc5d2a4SVikram Hegde 	 * Solaris in a logical partition. Find that partition in the
7657fc5d2a4SVikram Hegde 	 * extended part.
7667fc5d2a4SVikram Hegde 	 */
767af28f636SEnrico Perla - Sun Microsystems 	if ((rval = libfdisk_init(&epp, device->path_p0, NULL, FDISK_READ_DISK))
768aa1b14e7SSheshadri Vasudevan 	    != FDISK_SUCCESS) {
769aa1b14e7SSheshadri Vasudevan 		switch (rval) {
770aa1b14e7SSheshadri Vasudevan 			/*
7716cb5747bSSharath M Srinivasan 			 * The first 3 cases are not an error per-se, just that
7727fc5d2a4SVikram Hegde 			 * there is no Solaris logical partition
773aa1b14e7SSheshadri Vasudevan 			 */
774aa1b14e7SSheshadri Vasudevan 			case FDISK_EBADLOGDRIVE:
775aa1b14e7SSheshadri Vasudevan 			case FDISK_ENOLOGDRIVE:
7766cb5747bSSharath M Srinivasan 			case FDISK_EBADMAGIC:
7777fc5d2a4SVikram Hegde 				(void) fprintf(stderr, NOSOLPAR);
778af28f636SEnrico Perla - Sun Microsystems 				return (BC_ERROR);
779aa1b14e7SSheshadri Vasudevan 			case FDISK_ENOVGEOM:
780aa1b14e7SSheshadri Vasudevan 				(void) fprintf(stderr, NO_VIRT_GEOM);
781af28f636SEnrico Perla - Sun Microsystems 				return (BC_ERROR);
782aa1b14e7SSheshadri Vasudevan 			case FDISK_ENOPGEOM:
783aa1b14e7SSheshadri Vasudevan 				(void) fprintf(stderr, NO_PHYS_GEOM);
784af28f636SEnrico Perla - Sun Microsystems 				return (BC_ERROR);
785aa1b14e7SSheshadri Vasudevan 			case FDISK_ENOLGEOM:
786aa1b14e7SSheshadri Vasudevan 				(void) fprintf(stderr, NO_LABEL_GEOM);
787af28f636SEnrico Perla - Sun Microsystems 				return (BC_ERROR);
788aa1b14e7SSheshadri Vasudevan 			default:
789aa1b14e7SSheshadri Vasudevan 				(void) fprintf(stderr, LIBFDISK_INIT_FAIL);
790af28f636SEnrico Perla - Sun Microsystems 				return (BC_ERROR);
791aa1b14e7SSheshadri Vasudevan 		}
792aa1b14e7SSheshadri Vasudevan 	}
793aa1b14e7SSheshadri Vasudevan 
794aa1b14e7SSheshadri Vasudevan 	rval = fdisk_get_solaris_part(epp, &pno, &secnum, &numsec);
7956cb5747bSSharath M Srinivasan 	libfdisk_fini(&epp);
7967fc5d2a4SVikram Hegde 	if (rval != FDISK_SUCCESS) {
7977fc5d2a4SVikram Hegde 		/* No solaris logical partition */
7987fc5d2a4SVikram Hegde 		(void) fprintf(stderr, NOSOLPAR);
799af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
800aa1b14e7SSheshadri Vasudevan 	}
801aa1b14e7SSheshadri Vasudevan 
802af28f636SEnrico Perla - Sun Microsystems 	device->start_sector = secnum;
803af28f636SEnrico Perla - Sun Microsystems 	device->partition = pno - 1;
8047fc5d2a4SVikram Hegde 	log_part = 1;
8057c478bd9Sstevel@tonic-gate 
8067fc5d2a4SVikram Hegde found_part:
8077c478bd9Sstevel@tonic-gate 	/* get confirmation for -m */
808af28f636SEnrico Perla - Sun Microsystems 	if (write_mbr && !force_mbr) {
8097c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout, MBOOT_PROMPT);
8107c478bd9Sstevel@tonic-gate 		if (getchar() != 'y') {
811af28f636SEnrico Perla - Sun Microsystems 			write_mbr = 0;
8127c478bd9Sstevel@tonic-gate 			(void) fprintf(stdout, MBOOT_NOT_UPDATED);
813af28f636SEnrico Perla - Sun Microsystems 			return (BC_ERROR);
8147c478bd9Sstevel@tonic-gate 		}
8157c478bd9Sstevel@tonic-gate 	}
8167c478bd9Sstevel@tonic-gate 
8177fc5d2a4SVikram Hegde 	/*
8187fc5d2a4SVikram Hegde 	 * Currently if Solaris is in an extended partition we need to
8197fc5d2a4SVikram Hegde 	 * write GRUB to the MBR. Check for this.
8207fc5d2a4SVikram Hegde 	 */
821af28f636SEnrico Perla - Sun Microsystems 	if (log_part && !write_mbr) {
822af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, gettext("Installing Solaris on an "
823af28f636SEnrico Perla - Sun Microsystems 		    "extended partition... forcing MBR update\n"));
824af28f636SEnrico Perla - Sun Microsystems 		write_mbr = 1;
825aa1b14e7SSheshadri Vasudevan 	}
826aa1b14e7SSheshadri Vasudevan 
8277fc5d2a4SVikram Hegde 	/*
8287fc5d2a4SVikram Hegde 	 * warn, if Solaris in primary partition and GRUB not in MBR and
8297fc5d2a4SVikram Hegde 	 * partition is not active
8307fc5d2a4SVikram Hegde 	 */
831af28f636SEnrico Perla - Sun Microsystems 	if (!log_part && part->bootid != 128 && !write_mbr) {
832af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, SOLPAR_INACTIVE, device->partition + 1);
8337c478bd9Sstevel@tonic-gate 	}
8347c478bd9Sstevel@tonic-gate 
835af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
8367c478bd9Sstevel@tonic-gate }
8377c478bd9Sstevel@tonic-gate 
8387c478bd9Sstevel@tonic-gate static int
839af28f636SEnrico Perla - Sun Microsystems get_disk_fd(ig_device_t *device)
8407c478bd9Sstevel@tonic-gate {
841af28f636SEnrico Perla - Sun Microsystems 	int	i;
842af28f636SEnrico Perla - Sun Microsystems 	char	save[2];
843af28f636SEnrico Perla - Sun Microsystems 	char	*end = NULL;
844af28f636SEnrico Perla - Sun Microsystems 
845af28f636SEnrico Perla - Sun Microsystems 	assert(device != NULL);
846af28f636SEnrico Perla - Sun Microsystems 	assert(device->path != NULL);
847af28f636SEnrico Perla - Sun Microsystems 
848af28f636SEnrico Perla - Sun Microsystems 	if (is_bootpar(device->type)) {
849af28f636SEnrico Perla - Sun Microsystems 		end = strstr(device->path, "p0:boot");
850af28f636SEnrico Perla - Sun Microsystems 		/* tested at the start of init_device() */
851af28f636SEnrico Perla - Sun Microsystems 		assert(end != NULL);
852af28f636SEnrico Perla - Sun Microsystems 		/* chop off :boot */
853af28f636SEnrico Perla - Sun Microsystems 		save[0] = end[2];
854af28f636SEnrico Perla - Sun Microsystems 		end[2] = '\0';
855af28f636SEnrico Perla - Sun Microsystems 	} else {
856af28f636SEnrico Perla - Sun Microsystems 		i = strlen(device->path);
857af28f636SEnrico Perla - Sun Microsystems 		save[0] = device->path[i - 2];
858af28f636SEnrico Perla - Sun Microsystems 		save[1] = device->path[i - 1];
859af28f636SEnrico Perla - Sun Microsystems 		device->path[i - 2] = 'p';
860af28f636SEnrico Perla - Sun Microsystems 		device->path[i - 1] = '0';
8617c478bd9Sstevel@tonic-gate 	}
8627c478bd9Sstevel@tonic-gate 
8637c478bd9Sstevel@tonic-gate 	if (nowrite)
864af28f636SEnrico Perla - Sun Microsystems 		device->disk_fd = open(device->path, O_RDONLY);
8657c478bd9Sstevel@tonic-gate 	else
866af28f636SEnrico Perla - Sun Microsystems 		device->disk_fd = open(device->path, O_RDWR);
8677c478bd9Sstevel@tonic-gate 
868af28f636SEnrico Perla - Sun Microsystems 	device->path_p0 = strdup(device->path);
869af28f636SEnrico Perla - Sun Microsystems 	if (device->path_p0 == NULL) {
870af28f636SEnrico Perla - Sun Microsystems 		perror("strdup");
871af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
8727c478bd9Sstevel@tonic-gate 	}
873af28f636SEnrico Perla - Sun Microsystems 
874af28f636SEnrico Perla - Sun Microsystems 	if (is_bootpar(device->type)) {
875af28f636SEnrico Perla - Sun Microsystems 		end[2] = save[0];
876af28f636SEnrico Perla - Sun Microsystems 	} else {
877af28f636SEnrico Perla - Sun Microsystems 		device->path[i - 2] = save[0];
878af28f636SEnrico Perla - Sun Microsystems 		device->path[i - 1] = save[1];
879af28f636SEnrico Perla - Sun Microsystems 	}
880af28f636SEnrico Perla - Sun Microsystems 
881af28f636SEnrico Perla - Sun Microsystems 	if (device->disk_fd == -1) {
882af28f636SEnrico Perla - Sun Microsystems 		perror("open");
883af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
8847c478bd9Sstevel@tonic-gate 	}
8857c478bd9Sstevel@tonic-gate 
886af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
8877c478bd9Sstevel@tonic-gate }
8887c478bd9Sstevel@tonic-gate 
8897c478bd9Sstevel@tonic-gate static void
890af28f636SEnrico Perla - Sun Microsystems prepare_fake_multiboot(ig_stage2_t *stage2)
8917c478bd9Sstevel@tonic-gate {
892af28f636SEnrico Perla - Sun Microsystems 	multiboot_header_t	*mboot;
8937c478bd9Sstevel@tonic-gate 
894af28f636SEnrico Perla - Sun Microsystems 	assert(stage2 != NULL);
895af28f636SEnrico Perla - Sun Microsystems 	assert(stage2->mboot != NULL);
896af28f636SEnrico Perla - Sun Microsystems 	assert(stage2->buf != NULL);
8977c478bd9Sstevel@tonic-gate 
898af28f636SEnrico Perla - Sun Microsystems 	mboot = stage2->mboot;
899af28f636SEnrico Perla - Sun Microsystems 
900af28f636SEnrico Perla - Sun Microsystems 	/*
901af28f636SEnrico Perla - Sun Microsystems 	 * Currently we expect find_multiboot() to have located a multiboot
902af28f636SEnrico Perla - Sun Microsystems 	 * header with the AOUT kludge flag set.
903af28f636SEnrico Perla - Sun Microsystems 	 */
904af28f636SEnrico Perla - Sun Microsystems 	assert(mboot->flags & BB_MBOOT_AOUT_FLAG);
905af28f636SEnrico Perla - Sun Microsystems 
906af28f636SEnrico Perla - Sun Microsystems 	/* Insert the information necessary to locate stage2. */
907af28f636SEnrico Perla - Sun Microsystems 	mboot->header_addr = stage2->mboot_off;
908af28f636SEnrico Perla - Sun Microsystems 	mboot->load_addr = 0;
909af28f636SEnrico Perla - Sun Microsystems 	mboot->load_end_addr = stage2->file_size;
9107c478bd9Sstevel@tonic-gate }
9117c478bd9Sstevel@tonic-gate 
9127c478bd9Sstevel@tonic-gate static void
913af28f636SEnrico Perla - Sun Microsystems add_stage2_einfo(ig_stage2_t *stage2, char *updt_str)
9147c478bd9Sstevel@tonic-gate {
915af28f636SEnrico Perla - Sun Microsystems 	bblk_hs_t	hs;
916af28f636SEnrico Perla - Sun Microsystems 	uint32_t	avail_space;
917af28f636SEnrico Perla - Sun Microsystems 
918af28f636SEnrico Perla - Sun Microsystems 	assert(stage2 != NULL);
919af28f636SEnrico Perla - Sun Microsystems 
920af28f636SEnrico Perla - Sun Microsystems 	/* Fill bootblock hashing source information. */
921af28f636SEnrico Perla - Sun Microsystems 	hs.src_buf = (unsigned char *)stage2->file;
922af28f636SEnrico Perla - Sun Microsystems 	hs.src_size = stage2->file_size;
923af28f636SEnrico Perla - Sun Microsystems 	/* How much space for the extended information structure? */
924af28f636SEnrico Perla - Sun Microsystems 	avail_space = stage2->buf_size - P2ROUNDUP(stage2->file_size, 8);
925af28f636SEnrico Perla - Sun Microsystems 	add_einfo(stage2->extra, updt_str, &hs, avail_space);
926af28f636SEnrico Perla - Sun Microsystems }
927af28f636SEnrico Perla - Sun Microsystems 
928af28f636SEnrico Perla - Sun Microsystems 
929af28f636SEnrico Perla - Sun Microsystems static int
930af28f636SEnrico Perla - Sun Microsystems write_stage2(ig_data_t *install)
931af28f636SEnrico Perla - Sun Microsystems {
932af28f636SEnrico Perla - Sun Microsystems 	ig_device_t		*device = &install->device;
933af28f636SEnrico Perla - Sun Microsystems 	ig_stage2_t		*stage2 = &install->stage2;
934af28f636SEnrico Perla - Sun Microsystems 	off_t			offset;
935af28f636SEnrico Perla - Sun Microsystems 
936af28f636SEnrico Perla - Sun Microsystems 	assert(install != NULL);
937af28f636SEnrico Perla - Sun Microsystems 
938af28f636SEnrico Perla - Sun Microsystems 	if (is_bootpar(device->type)) {
939af28f636SEnrico Perla - Sun Microsystems 		/*
940af28f636SEnrico Perla - Sun Microsystems 		 * stage2 is already on the filesystem, we only need to update
941af28f636SEnrico Perla - Sun Microsystems 		 * the first two blocks (that we have modified during
942af28f636SEnrico Perla - Sun Microsystems 		 * prepare_stage2())
943af28f636SEnrico Perla - Sun Microsystems 		 */
944af28f636SEnrico Perla - Sun Microsystems 		if (write_out(device->part_fd, stage2->file, SECTOR_SIZE,
945af28f636SEnrico Perla - Sun Microsystems 		    stage2->pcfs_first_sectors[0] * SECTOR_SIZE)
946af28f636SEnrico Perla - Sun Microsystems 		    != BC_SUCCESS ||
947af28f636SEnrico Perla - Sun Microsystems 		    write_out(device->part_fd, stage2->file + SECTOR_SIZE,
948af28f636SEnrico Perla - Sun Microsystems 		    SECTOR_SIZE, stage2->pcfs_first_sectors[1] * SECTOR_SIZE)
949af28f636SEnrico Perla - Sun Microsystems 		    != BC_SUCCESS) {
950af28f636SEnrico Perla - Sun Microsystems 			(void) fprintf(stderr, WRITE_FAIL_STAGE2);
951af28f636SEnrico Perla - Sun Microsystems 			return (BC_ERROR);
952af28f636SEnrico Perla - Sun Microsystems 		}
953af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, WRITE_STAGE2_PCFS);
954af28f636SEnrico Perla - Sun Microsystems 		return (BC_SUCCESS);
9557c478bd9Sstevel@tonic-gate 	}
956af28f636SEnrico Perla - Sun Microsystems 
957af28f636SEnrico Perla - Sun Microsystems 	/*
958af28f636SEnrico Perla - Sun Microsystems 	 * For disk, write stage2 starting at STAGE2_BLKOFF sector.
959af28f636SEnrico Perla - Sun Microsystems 	 * Note that we use stage2->buf rather than stage2->file, because we
960af28f636SEnrico Perla - Sun Microsystems 	 * may have extended information after the latter.
961af28f636SEnrico Perla - Sun Microsystems 	 */
962af28f636SEnrico Perla - Sun Microsystems 	offset = STAGE2_BLKOFF * SECTOR_SIZE;
963af28f636SEnrico Perla - Sun Microsystems 	if (write_out(device->part_fd, stage2->buf, stage2->buf_size,
964af28f636SEnrico Perla - Sun Microsystems 	    offset) != BC_SUCCESS) {
965af28f636SEnrico Perla - Sun Microsystems 		perror("write");
966af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
967af28f636SEnrico Perla - Sun Microsystems 	}
968af28f636SEnrico Perla - Sun Microsystems 
969af28f636SEnrico Perla - Sun Microsystems 	/* Simulate the "old" installgrub output. */
970af28f636SEnrico Perla - Sun Microsystems 	(void) fprintf(stdout, WRITE_STAGE2_DISK, device->partition,
971af28f636SEnrico Perla - Sun Microsystems 	    (stage2->buf_size / SECTOR_SIZE) + 1, STAGE2_BLKOFF,
972af28f636SEnrico Perla - Sun Microsystems 	    stage2->first_sector);
973af28f636SEnrico Perla - Sun Microsystems 
974af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
9757c478bd9Sstevel@tonic-gate }
9767c478bd9Sstevel@tonic-gate 
977af28f636SEnrico Perla - Sun Microsystems static int
978af28f636SEnrico Perla - Sun Microsystems write_stage1(ig_data_t *install)
9797c478bd9Sstevel@tonic-gate {
980af28f636SEnrico Perla - Sun Microsystems 	ig_device_t	*device = &install->device;
981af28f636SEnrico Perla - Sun Microsystems 
982af28f636SEnrico Perla - Sun Microsystems 	assert(install != NULL);
983af28f636SEnrico Perla - Sun Microsystems 
984af28f636SEnrico Perla - Sun Microsystems 	if (write_out(device->part_fd, install->stage1_buf,
985af28f636SEnrico Perla - Sun Microsystems 	    sizeof (install->stage1_buf), 0) != BC_SUCCESS) {
986af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, WRITE_FAIL_PBOOT);
987af28f636SEnrico Perla - Sun Microsystems 		perror("write");
988af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
9897c478bd9Sstevel@tonic-gate 	}
990af28f636SEnrico Perla - Sun Microsystems 
991af28f636SEnrico Perla - Sun Microsystems 	/* Simulate "old" installgrub output. */
992af28f636SEnrico Perla - Sun Microsystems 	(void) fprintf(stdout, WRITE_PBOOT, device->partition,
993af28f636SEnrico Perla - Sun Microsystems 	    device->start_sector);
994af28f636SEnrico Perla - Sun Microsystems 
995af28f636SEnrico Perla - Sun Microsystems 	if (write_mbr) {
996af28f636SEnrico Perla - Sun Microsystems 		if (write_out(device->disk_fd, install->stage1_buf,
997af28f636SEnrico Perla - Sun Microsystems 		    sizeof (install->stage1_buf), 0) != BC_SUCCESS) {
998af28f636SEnrico Perla - Sun Microsystems 			(void) fprintf(stdout, WRITE_FAIL_BOOTSEC);
999af28f636SEnrico Perla - Sun Microsystems 			perror("write");
1000af28f636SEnrico Perla - Sun Microsystems 			return (BC_ERROR);
1001af28f636SEnrico Perla - Sun Microsystems 		}
1002af28f636SEnrico Perla - Sun Microsystems 		/* Simulate "old" installgrub output. */
1003af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, WRITE_MBOOT);
1004af28f636SEnrico Perla - Sun Microsystems 	}
1005af28f636SEnrico Perla - Sun Microsystems 
1006af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
10077c478bd9Sstevel@tonic-gate }
10087c478bd9Sstevel@tonic-gate 
1009af28f636SEnrico Perla - Sun Microsystems #define	USAGE_STRING	"%s [-m|-f|-n|-F|-u verstr] stage1 stage2 device\n"    \
1010af28f636SEnrico Perla - Sun Microsystems 			"%s -M [-n] device1 device2\n"			       \
1011af28f636SEnrico Perla - Sun Microsystems 			"%s [-V|-e] -i device\n"			       \
1012af28f636SEnrico Perla - Sun Microsystems 
1013af28f636SEnrico Perla - Sun Microsystems #define	CANON_USAGE_STR	gettext(USAGE_STRING)
1014af28f636SEnrico Perla - Sun Microsystems 
10157c478bd9Sstevel@tonic-gate static void
1016af28f636SEnrico Perla - Sun Microsystems usage(char *progname)
10177c478bd9Sstevel@tonic-gate {
1018af28f636SEnrico Perla - Sun Microsystems 	(void) fprintf(stdout, CANON_USAGE_STR, progname, progname, progname);
1019af28f636SEnrico Perla - Sun Microsystems }
10207c478bd9Sstevel@tonic-gate 
10217c478bd9Sstevel@tonic-gate 
1022af28f636SEnrico Perla - Sun Microsystems static int
1023af28f636SEnrico Perla - Sun Microsystems read_stage1_from_file(char *path, ig_data_t *dest)
1024af28f636SEnrico Perla - Sun Microsystems {
1025af28f636SEnrico Perla - Sun Microsystems 	int	fd;
1026af28f636SEnrico Perla - Sun Microsystems 
1027af28f636SEnrico Perla - Sun Microsystems 	assert(dest);
1028af28f636SEnrico Perla - Sun Microsystems 
1029af28f636SEnrico Perla - Sun Microsystems 	/* read the stage1 file from filesystem */
1030af28f636SEnrico Perla - Sun Microsystems 	fd = open(path, O_RDONLY);
1031af28f636SEnrico Perla - Sun Microsystems 	if (fd == -1 ||
1032af28f636SEnrico Perla - Sun Microsystems 	    read(fd, dest->stage1_buf, SECTOR_SIZE) != SECTOR_SIZE) {
1033af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, READ_FAIL_STAGE1, path);
1034af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
10357c478bd9Sstevel@tonic-gate 	}
10367c478bd9Sstevel@tonic-gate 	(void) close(fd);
1037af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
10387c478bd9Sstevel@tonic-gate }
10397c478bd9Sstevel@tonic-gate 
1040af28f636SEnrico Perla - Sun Microsystems static int
1041af28f636SEnrico Perla - Sun Microsystems read_stage2_from_file(char *path, ig_data_t *dest)
10427c478bd9Sstevel@tonic-gate {
1043af28f636SEnrico Perla - Sun Microsystems 	int		fd;
1044af28f636SEnrico Perla - Sun Microsystems 	struct stat	sb;
1045af28f636SEnrico Perla - Sun Microsystems 	ig_stage2_t	*stage2 = &dest->stage2;
1046af28f636SEnrico Perla - Sun Microsystems 	ig_device_t	*device = &dest->device;
1047af28f636SEnrico Perla - Sun Microsystems 	uint32_t	buf_size;
1048af28f636SEnrico Perla - Sun Microsystems 
1049af28f636SEnrico Perla - Sun Microsystems 	assert(dest);
1050af28f636SEnrico Perla - Sun Microsystems 	assert(stage2->buf == NULL);
1051af28f636SEnrico Perla - Sun Microsystems 
1052af28f636SEnrico Perla - Sun Microsystems 	fd = open(path, O_RDONLY);
1053af28f636SEnrico Perla - Sun Microsystems 	if (fstat(fd, &sb) == -1) {
1054af28f636SEnrico Perla - Sun Microsystems 		perror("fstat");
1055af28f636SEnrico Perla - Sun Microsystems 		goto out;
1056af28f636SEnrico Perla - Sun Microsystems 	}
1057af28f636SEnrico Perla - Sun Microsystems 
1058af28f636SEnrico Perla - Sun Microsystems 	stage2->file_size = sb.st_size;
1059af28f636SEnrico Perla - Sun Microsystems 
1060af28f636SEnrico Perla - Sun Microsystems 	if (!is_bootpar(device->type)) {
1061af28f636SEnrico Perla - Sun Microsystems 		/*
1062af28f636SEnrico Perla - Sun Microsystems 		 * buffer size needs to account for stage2 plus the extra
1063af28f636SEnrico Perla - Sun Microsystems 		 * versioning information at the end of it. We reserve one
1064af28f636SEnrico Perla - Sun Microsystems 		 * extra sector (plus we round up to the next sector boundary).
1065af28f636SEnrico Perla - Sun Microsystems 		 */
1066af28f636SEnrico Perla - Sun Microsystems 		buf_size = stage2->file_size + SECTOR_SIZE;
10677c478bd9Sstevel@tonic-gate 	} else {
1068af28f636SEnrico Perla - Sun Microsystems 		/* In the PCFS case we only need to read in stage2. */
1069af28f636SEnrico Perla - Sun Microsystems 		buf_size = stage2->file_size;
10707c478bd9Sstevel@tonic-gate 	}
10717c478bd9Sstevel@tonic-gate 
1072af28f636SEnrico Perla - Sun Microsystems 	stage2->buf_size = P2ROUNDUP(buf_size, SECTOR_SIZE);
1073af28f636SEnrico Perla - Sun Microsystems 
1074af28f636SEnrico Perla - Sun Microsystems 	BOOT_DEBUG("stage2 buffer size = %d (%d sectors)\n", stage2->buf_size,
1075af28f636SEnrico Perla - Sun Microsystems 	    stage2->buf_size / SECTOR_SIZE);
1076af28f636SEnrico Perla - Sun Microsystems 
1077af28f636SEnrico Perla - Sun Microsystems 	stage2->buf = malloc(stage2->buf_size);
1078af28f636SEnrico Perla - Sun Microsystems 	if (stage2->buf == NULL) {
1079af28f636SEnrico Perla - Sun Microsystems 		perror(gettext("Memory allocation failed"));
1080af28f636SEnrico Perla - Sun Microsystems 		goto out_fd;
1081af28f636SEnrico Perla - Sun Microsystems 	}
1082af28f636SEnrico Perla - Sun Microsystems 
1083af28f636SEnrico Perla - Sun Microsystems 	stage2->file = stage2->buf;
10847c478bd9Sstevel@tonic-gate 
10857c478bd9Sstevel@tonic-gate 	/*
1086af28f636SEnrico Perla - Sun Microsystems 	 * Extra information (e.g. the versioning structure) is placed at the
1087af28f636SEnrico Perla - Sun Microsystems 	 * end of stage2, aligned on a 8-byte boundary.
10887c478bd9Sstevel@tonic-gate 	 */
1089af28f636SEnrico Perla - Sun Microsystems 	if (!(is_bootpar(device->type)))
1090af28f636SEnrico Perla - Sun Microsystems 		stage2->extra = stage2->file + P2ROUNDUP(stage2->file_size, 8);
10917c478bd9Sstevel@tonic-gate 
1092af28f636SEnrico Perla - Sun Microsystems 	if (lseek(fd, 0, SEEK_SET) == -1) {
1093af28f636SEnrico Perla - Sun Microsystems 		perror("lseek");
1094af28f636SEnrico Perla - Sun Microsystems 		goto out_alloc;
10957c478bd9Sstevel@tonic-gate 	}
10967c478bd9Sstevel@tonic-gate 
1097af28f636SEnrico Perla - Sun Microsystems 	if (read(fd, stage2->file, stage2->file_size) < 0) {
1098af28f636SEnrico Perla - Sun Microsystems 		perror(gettext("unable to read stage2"));
1099af28f636SEnrico Perla - Sun Microsystems 		goto out_alloc;
11007c478bd9Sstevel@tonic-gate 	}
11017c478bd9Sstevel@tonic-gate 
1102af28f636SEnrico Perla - Sun Microsystems 	(void) close(fd);
1103af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
11047ce76caaSEnrico Perla - Sun Microsystems 
1105af28f636SEnrico Perla - Sun Microsystems out_alloc:
1106af28f636SEnrico Perla - Sun Microsystems 	free(stage2->buf);
1107af28f636SEnrico Perla - Sun Microsystems 	stage2->buf = NULL;
1108af28f636SEnrico Perla - Sun Microsystems out_fd:
1109af28f636SEnrico Perla - Sun Microsystems 	(void) close(fd);
1110af28f636SEnrico Perla - Sun Microsystems out:
1111af28f636SEnrico Perla - Sun Microsystems 	return (BC_ERROR);
11127ce76caaSEnrico Perla - Sun Microsystems }
11137ce76caaSEnrico Perla - Sun Microsystems 
1114af28f636SEnrico Perla - Sun Microsystems static int
1115af28f636SEnrico Perla - Sun Microsystems prepare_stage1(ig_data_t *install)
11167ce76caaSEnrico Perla - Sun Microsystems {
1117af28f636SEnrico Perla - Sun Microsystems 	ig_device_t	*device = &install->device;
11187ce76caaSEnrico Perla - Sun Microsystems 
1119af28f636SEnrico Perla - Sun Microsystems 	assert(install != NULL);
1120af28f636SEnrico Perla - Sun Microsystems 
1121af28f636SEnrico Perla - Sun Microsystems 	/* If PCFS add the BIOS Parameter Block. */
1122af28f636SEnrico Perla - Sun Microsystems 	if (is_bootpar(device->type)) {
1123af28f636SEnrico Perla - Sun Microsystems 		char	bpb_sect[SECTOR_SIZE];
1124af28f636SEnrico Perla - Sun Microsystems 
1125af28f636SEnrico Perla - Sun Microsystems 		if (pread(device->part_fd, bpb_sect, SECTOR_SIZE, 0)
1126af28f636SEnrico Perla - Sun Microsystems 		    != SECTOR_SIZE) {
1127af28f636SEnrico Perla - Sun Microsystems 			(void) fprintf(stderr, READ_FAIL_BPB);
1128af28f636SEnrico Perla - Sun Microsystems 			return (BC_ERROR);
1129af28f636SEnrico Perla - Sun Microsystems 		}
1130af28f636SEnrico Perla - Sun Microsystems 		bcopy(bpb_sect + STAGE1_BPB_OFFSET,
1131af28f636SEnrico Perla - Sun Microsystems 		    install->stage1_buf + STAGE1_BPB_OFFSET, STAGE1_BPB_SIZE);
11327ce76caaSEnrico Perla - Sun Microsystems 	}
11337ce76caaSEnrico Perla - Sun Microsystems 
1134af28f636SEnrico Perla - Sun Microsystems 	/* copy MBR to stage1 in case of overwriting MBR sector. */
1135af28f636SEnrico Perla - Sun Microsystems 	bcopy(device->boot_sector + BOOTSZ, install->stage1_buf + BOOTSZ,
1136af28f636SEnrico Perla - Sun Microsystems 	    SECTOR_SIZE - BOOTSZ);
1137af28f636SEnrico Perla - Sun Microsystems 	/* modify default stage1 file generated by GRUB. */
1138af28f636SEnrico Perla - Sun Microsystems 	*((unsigned char *)(install->stage1_buf + STAGE1_FORCE_LBA)) = 1;
1139af28f636SEnrico Perla - Sun Microsystems 	*((ulong_t *)(install->stage1_buf + STAGE1_STAGE2_SECTOR))
1140af28f636SEnrico Perla - Sun Microsystems 	    = install->stage2.first_sector;
1141af28f636SEnrico Perla - Sun Microsystems 	*((ushort_t *)(install->stage1_buf + STAGE1_STAGE2_ADDRESS))
1142af28f636SEnrico Perla - Sun Microsystems 	    = STAGE2_MEMADDR;
1143af28f636SEnrico Perla - Sun Microsystems 	*((ushort_t *)(install->stage1_buf + STAGE1_STAGE2_SEGMENT))
1144af28f636SEnrico Perla - Sun Microsystems 	    = STAGE2_MEMADDR >> 4;
11457ce76caaSEnrico Perla - Sun Microsystems 
1146af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
11477ce76caaSEnrico Perla - Sun Microsystems }
11487ce76caaSEnrico Perla - Sun Microsystems 
1149af28f636SEnrico Perla - Sun Microsystems /*
1150af28f636SEnrico Perla - Sun Microsystems  * Grab stage1 from the specified device file descriptor.
1151af28f636SEnrico Perla - Sun Microsystems  */
11527ce76caaSEnrico Perla - Sun Microsystems static int
1153af28f636SEnrico Perla - Sun Microsystems read_stage1_from_disk(int dev_fd, char *stage1_buf)
11547ce76caaSEnrico Perla - Sun Microsystems {
1155af28f636SEnrico Perla - Sun Microsystems 	assert(stage1_buf != NULL);
11567ce76caaSEnrico Perla - Sun Microsystems 
1157af28f636SEnrico Perla - Sun Microsystems 	if (read_in(dev_fd, stage1_buf, SECTOR_SIZE, 0) != BC_SUCCESS) {
1158af28f636SEnrico Perla - Sun Microsystems 		perror(gettext("Unable to read stage1 from disk"));
1159af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
1160af28f636SEnrico Perla - Sun Microsystems 	}
1161af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
1162af28f636SEnrico Perla - Sun Microsystems }
11637ce76caaSEnrico Perla - Sun Microsystems 
1164af28f636SEnrico Perla - Sun Microsystems static int
1165af28f636SEnrico Perla - Sun Microsystems read_stage2_from_disk(int dev_fd, ig_stage2_t *stage2)
1166af28f636SEnrico Perla - Sun Microsystems {
1167af28f636SEnrico Perla - Sun Microsystems 	uint32_t		size;
1168af28f636SEnrico Perla - Sun Microsystems 	uint32_t		buf_size;
1169af28f636SEnrico Perla - Sun Microsystems 	uint32_t		mboot_off;
1170af28f636SEnrico Perla - Sun Microsystems 	multiboot_header_t	*mboot;
1171af28f636SEnrico Perla - Sun Microsystems 
1172af28f636SEnrico Perla - Sun Microsystems 	assert(stage2 != NULL);
1173af28f636SEnrico Perla - Sun Microsystems 	assert(dev_fd != -1);
1174af28f636SEnrico Perla - Sun Microsystems 
1175af28f636SEnrico Perla - Sun Microsystems 	if (read_in(dev_fd, mboot_scan, sizeof (mboot_scan),
1176af28f636SEnrico Perla - Sun Microsystems 	    STAGE2_BLKOFF * SECTOR_SIZE) != BC_SUCCESS) {
1177af28f636SEnrico Perla - Sun Microsystems 		perror(gettext("Error reading stage2 sectors"));
1178af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
1179af28f636SEnrico Perla - Sun Microsystems 	}
11807ce76caaSEnrico Perla - Sun Microsystems 
1181af28f636SEnrico Perla - Sun Microsystems 	/* No multiboot means no chance of knowing stage2 size */
1182af28f636SEnrico Perla - Sun Microsystems 	if (find_multiboot(mboot_scan, sizeof (mboot_scan), &mboot_off)
1183af28f636SEnrico Perla - Sun Microsystems 	    != BC_SUCCESS) {
1184af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("Unable to find multiboot header\n");
1185af28f636SEnrico Perla - Sun Microsystems 		return (BC_NOEXTRA);
1186af28f636SEnrico Perla - Sun Microsystems 	}
1187af28f636SEnrico Perla - Sun Microsystems 	mboot = (multiboot_header_t *)(mboot_scan + mboot_off);
11887ce76caaSEnrico Perla - Sun Microsystems 
1189af28f636SEnrico Perla - Sun Microsystems 	/*
1190af28f636SEnrico Perla - Sun Microsystems 	 * Unfilled mboot values mean an older version of installgrub installed
1191af28f636SEnrico Perla - Sun Microsystems 	 * the stage2. Again we have no chance of knowing stage2 size.
1192af28f636SEnrico Perla - Sun Microsystems 	 */
1193af28f636SEnrico Perla - Sun Microsystems 	if (mboot->load_end_addr == 0 ||
1194af28f636SEnrico Perla - Sun Microsystems 	    mboot->load_end_addr < mboot->load_addr)
1195af28f636SEnrico Perla - Sun Microsystems 		return (BC_NOEXTRA);
11967ce76caaSEnrico Perla - Sun Microsystems 
1197af28f636SEnrico Perla - Sun Microsystems 	/*
1198af28f636SEnrico Perla - Sun Microsystems 	 * Currently, the amount of space reserved for extra information
1199af28f636SEnrico Perla - Sun Microsystems 	 * is "fixed". We may have to scan for the terminating extra payload
1200af28f636SEnrico Perla - Sun Microsystems 	 * in the future.
1201af28f636SEnrico Perla - Sun Microsystems 	 */
1202af28f636SEnrico Perla - Sun Microsystems 	size = mboot->load_end_addr - mboot->load_addr;
1203af28f636SEnrico Perla - Sun Microsystems 	buf_size = P2ROUNDUP(size + SECTOR_SIZE, SECTOR_SIZE);
12047ce76caaSEnrico Perla - Sun Microsystems 
1205af28f636SEnrico Perla - Sun Microsystems 	stage2->buf = malloc(buf_size);
1206af28f636SEnrico Perla - Sun Microsystems 	if (stage2->buf == NULL) {
1207af28f636SEnrico Perla - Sun Microsystems 		perror(gettext("Memory allocation failed"));
1208af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
1209af28f636SEnrico Perla - Sun Microsystems 	}
1210af28f636SEnrico Perla - Sun Microsystems 	stage2->buf_size = buf_size;
12117ce76caaSEnrico Perla - Sun Microsystems 
1212af28f636SEnrico Perla - Sun Microsystems 	if (read_in(dev_fd, stage2->buf, buf_size, STAGE2_BLKOFF *
1213af28f636SEnrico Perla - Sun Microsystems 	    SECTOR_SIZE) != BC_SUCCESS) {
1214af28f636SEnrico Perla - Sun Microsystems 		perror("read");
1215af28f636SEnrico Perla - Sun Microsystems 		free(stage2->buf);
1216af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
12177ce76caaSEnrico Perla - Sun Microsystems 	}
12187ce76caaSEnrico Perla - Sun Microsystems 
1219af28f636SEnrico Perla - Sun Microsystems 	/* Update pointers. */
1220af28f636SEnrico Perla - Sun Microsystems 	stage2->file = stage2->buf;
1221af28f636SEnrico Perla - Sun Microsystems 	stage2->file_size = size;
1222af28f636SEnrico Perla - Sun Microsystems 	stage2->mboot_off = mboot_off;
1223af28f636SEnrico Perla - Sun Microsystems 	stage2->mboot = (multiboot_header_t *)(stage2->buf + stage2->mboot_off);
1224af28f636SEnrico Perla - Sun Microsystems 	stage2->extra = stage2->buf + P2ROUNDUP(stage2->file_size, 8);
1225*14d44f22SHans Rosenfeld 	stage2->extra_size = stage2->buf_size - P2ROUNDUP(stage2->file_size, 8);
12267ce76caaSEnrico Perla - Sun Microsystems 
1227af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
1228af28f636SEnrico Perla - Sun Microsystems }
12297ce76caaSEnrico Perla - Sun Microsystems 
1230af28f636SEnrico Perla - Sun Microsystems static boolean_t
1231af28f636SEnrico Perla - Sun Microsystems is_update_necessary(ig_data_t *data, char *updt_str)
12327ce76caaSEnrico Perla - Sun Microsystems {
1233af28f636SEnrico Perla - Sun Microsystems 	bblk_einfo_t	*einfo;
1234af28f636SEnrico Perla - Sun Microsystems 	bblk_hs_t	stage2_hs;
1235af28f636SEnrico Perla - Sun Microsystems 	ig_stage2_t	stage2_disk;
1236af28f636SEnrico Perla - Sun Microsystems 	ig_stage2_t	*stage2_file = &data->stage2;
1237af28f636SEnrico Perla - Sun Microsystems 	ig_device_t	*device = &data->device;
1238af28f636SEnrico Perla - Sun Microsystems 	int		dev_fd = device->part_fd;
1239af28f636SEnrico Perla - Sun Microsystems 
1240af28f636SEnrico Perla - Sun Microsystems 	assert(data != NULL);
1241af28f636SEnrico Perla - Sun Microsystems 	assert(device->part_fd != -1);
1242af28f636SEnrico Perla - Sun Microsystems 
1243af28f636SEnrico Perla - Sun Microsystems 	bzero(&stage2_disk, sizeof (ig_stage2_t));
1244af28f636SEnrico Perla - Sun Microsystems 
1245af28f636SEnrico Perla - Sun Microsystems 	/* Gather stage2 (if present) from the target device. */
1246af28f636SEnrico Perla - Sun Microsystems 	if (read_stage2_from_disk(dev_fd, &stage2_disk) != BC_SUCCESS) {
1247af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("Unable to read stage2 from %s\n", device->path);
1248af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("No multiboot wrapped stage2 on %s\n", device->path);
1249af28f636SEnrico Perla - Sun Microsystems 		return (B_TRUE);
1250af28f636SEnrico Perla - Sun Microsystems 	}
12517ce76caaSEnrico Perla - Sun Microsystems 
1252af28f636SEnrico Perla - Sun Microsystems 	/*
1253af28f636SEnrico Perla - Sun Microsystems 	 * Look for the extended information structure in the extra payload
1254af28f636SEnrico Perla - Sun Microsystems 	 * area.
1255af28f636SEnrico Perla - Sun Microsystems 	 */
1256*14d44f22SHans Rosenfeld 	einfo = find_einfo(stage2_disk.extra, stage2_disk.extra_size);
1257af28f636SEnrico Perla - Sun Microsystems 	if (einfo == NULL) {
1258af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("No extended information available\n");
1259af28f636SEnrico Perla - Sun Microsystems 		return (B_TRUE);
1260af28f636SEnrico Perla - Sun Microsystems 	}
12617ce76caaSEnrico Perla - Sun Microsystems 
1262af28f636SEnrico Perla - Sun Microsystems 	if (!do_version || updt_str == NULL) {
1263af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stdout, "WARNING: target device %s has a "
1264af28f636SEnrico Perla - Sun Microsystems 		    "versioned stage2 that is going to be overwritten by a non "
1265af28f636SEnrico Perla - Sun Microsystems 		    "versioned one\n", device->path);
1266af28f636SEnrico Perla - Sun Microsystems 		return (B_TRUE);
1267af28f636SEnrico Perla - Sun Microsystems 	}
12687ce76caaSEnrico Perla - Sun Microsystems 
1269af28f636SEnrico Perla - Sun Microsystems 	if (force_update) {
1270af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("Forcing update of %s bootblock\n", device->path);
1271af28f636SEnrico Perla - Sun Microsystems 		return (B_TRUE);
1272af28f636SEnrico Perla - Sun Microsystems 	}
12737ce76caaSEnrico Perla - Sun Microsystems 
1274af28f636SEnrico Perla - Sun Microsystems 	/* Compare the two extended information structures. */
1275af28f636SEnrico Perla - Sun Microsystems 	stage2_hs.src_buf = (unsigned char *)stage2_file->file;
1276af28f636SEnrico Perla - Sun Microsystems 	stage2_hs.src_size = stage2_file->file_size;
1277af28f636SEnrico Perla - Sun Microsystems 
1278af28f636SEnrico Perla - Sun Microsystems 	return (einfo_should_update(einfo, &stage2_hs, updt_str));
12797ce76caaSEnrico Perla - Sun Microsystems }
12807ce76caaSEnrico Perla - Sun Microsystems 
12817ce76caaSEnrico Perla - Sun Microsystems 
12827c478bd9Sstevel@tonic-gate #define	START_BLOCK(pos)	(*(ulong_t *)(pos))
12837c478bd9Sstevel@tonic-gate #define	NUM_BLOCK(pos)		(*(ushort_t *)((pos) + 4))
12847c478bd9Sstevel@tonic-gate #define	START_SEG(pos)		(*(ushort_t *)((pos) + 6))
12857c478bd9Sstevel@tonic-gate 
1286af28f636SEnrico Perla - Sun Microsystems static int
1287af28f636SEnrico Perla - Sun Microsystems prepare_stage2(ig_data_t *install, char *updt_str)
12887c478bd9Sstevel@tonic-gate {
1289af28f636SEnrico Perla - Sun Microsystems 	ig_device_t	*device = &install->device;
1290af28f636SEnrico Perla - Sun Microsystems 	ig_stage2_t	*stage2 = &install->stage2;
1291af28f636SEnrico Perla - Sun Microsystems 	uint32_t	mboot_off = 0;
1292af28f636SEnrico Perla - Sun Microsystems 
1293af28f636SEnrico Perla - Sun Microsystems 	assert(install != NULL);
1294af28f636SEnrico Perla - Sun Microsystems 	assert(stage2->file != NULL);
1295af28f636SEnrico Perla - Sun Microsystems 
1296af28f636SEnrico Perla - Sun Microsystems 	/* New stage2 files come with an embedded stage2. */
1297af28f636SEnrico Perla - Sun Microsystems 	if (find_multiboot(stage2->file, stage2->file_size, &mboot_off)
1298af28f636SEnrico Perla - Sun Microsystems 	    != BC_SUCCESS) {
1299af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("WARNING: no multiboot structure found in stage2, "
1300af28f636SEnrico Perla - Sun Microsystems 		    "are you using an old GRUB stage2?\n");
1301af28f636SEnrico Perla - Sun Microsystems 		if (do_version == B_TRUE) {
1302af28f636SEnrico Perla - Sun Microsystems 			(void) fprintf(stderr, gettext("Versioning requested "
1303af28f636SEnrico Perla - Sun Microsystems 			    "but stage2 does not support it.. skipping.\n"));
1304af28f636SEnrico Perla - Sun Microsystems 			do_version = B_FALSE;
1305af28f636SEnrico Perla - Sun Microsystems 		}
1306af28f636SEnrico Perla - Sun Microsystems 	} else {
1307af28f636SEnrico Perla - Sun Microsystems 		/* Keep track of where the multiboot header is. */
1308af28f636SEnrico Perla - Sun Microsystems 		stage2->mboot_off = mboot_off;
1309af28f636SEnrico Perla - Sun Microsystems 		stage2->mboot = (multiboot_header_t *)(stage2->file +
1310af28f636SEnrico Perla - Sun Microsystems 		    mboot_off);
1311af28f636SEnrico Perla - Sun Microsystems 		if (do_version) {
1312af28f636SEnrico Perla - Sun Microsystems 			/*
1313af28f636SEnrico Perla - Sun Microsystems 			 * Adding stage2 information needs to happen before
1314af28f636SEnrico Perla - Sun Microsystems 			 * we modify the copy of stage2 we have in memory, so
1315af28f636SEnrico Perla - Sun Microsystems 			 * that the hashing reflects the one of the file.
1316af28f636SEnrico Perla - Sun Microsystems 			 * An error here is not fatal.
1317af28f636SEnrico Perla - Sun Microsystems 			 */
1318af28f636SEnrico Perla - Sun Microsystems 			add_stage2_einfo(stage2, updt_str);
1319af28f636SEnrico Perla - Sun Microsystems 		}
1320af28f636SEnrico Perla - Sun Microsystems 		/*
1321af28f636SEnrico Perla - Sun Microsystems 		 * Fill multiboot information. We add them even without
1322af28f636SEnrico Perla - Sun Microsystems 		 * versioning to support as much as possible mirroring.
1323af28f636SEnrico Perla - Sun Microsystems 		 */
1324af28f636SEnrico Perla - Sun Microsystems 		prepare_fake_multiboot(stage2);
13257ce76caaSEnrico Perla - Sun Microsystems 	}
13267c478bd9Sstevel@tonic-gate 
1327af28f636SEnrico Perla - Sun Microsystems 	if (is_bootpar(device->type)) {
1328af28f636SEnrico Perla - Sun Microsystems 		uint32_t	blocklist[SECTOR_SIZE / sizeof (uint32_t)];
1329af28f636SEnrico Perla - Sun Microsystems 		uint32_t	install_addr = STAGE2_MEMADDR + SECTOR_SIZE;
1330af28f636SEnrico Perla - Sun Microsystems 		int		i = 0;
1331af28f636SEnrico Perla - Sun Microsystems 		uchar_t		*pos;
1332af28f636SEnrico Perla - Sun Microsystems 
1333af28f636SEnrico Perla - Sun Microsystems 		bzero(blocklist, sizeof (blocklist));
1334af28f636SEnrico Perla - Sun Microsystems 		if (read_stage2_blocklist(device->part_fd, blocklist) != 0) {
1335af28f636SEnrico Perla - Sun Microsystems 			(void) fprintf(stderr, gettext("Error reading pcfs "
1336af28f636SEnrico Perla - Sun Microsystems 			    "stage2 blocklist\n"));
1337af28f636SEnrico Perla - Sun Microsystems 			return (BC_ERROR);
1338af28f636SEnrico Perla - Sun Microsystems 		}
1339af28f636SEnrico Perla - Sun Microsystems 
1340af28f636SEnrico Perla - Sun Microsystems 		pos = (uchar_t *)stage2->file + STAGE2_BLOCKLIST;
1341af28f636SEnrico Perla - Sun Microsystems 		stage2->first_sector = device->start_sector + blocklist[0];
1342af28f636SEnrico Perla - Sun Microsystems 		stage2->pcfs_first_sectors[0] = blocklist[0];
1343af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("stage2 first sector: %d\n", stage2->first_sector);
13447c478bd9Sstevel@tonic-gate 
13457c478bd9Sstevel@tonic-gate 
13467c478bd9Sstevel@tonic-gate 		if (blocklist[1] > 1) {
13477c478bd9Sstevel@tonic-gate 			blocklist[0]++;
13487c478bd9Sstevel@tonic-gate 			blocklist[1]--;
13497c478bd9Sstevel@tonic-gate 		} else {
13507c478bd9Sstevel@tonic-gate 			i += 2;
13517c478bd9Sstevel@tonic-gate 		}
13527c478bd9Sstevel@tonic-gate 
1353af28f636SEnrico Perla - Sun Microsystems 		stage2->pcfs_first_sectors[1] = blocklist[i];
13547c478bd9Sstevel@tonic-gate 
13557c478bd9Sstevel@tonic-gate 		while (blocklist[i]) {
13567c478bd9Sstevel@tonic-gate 			if (START_BLOCK(pos - 8) != 0 &&
13577c478bd9Sstevel@tonic-gate 			    START_BLOCK(pos - 8) != blocklist[i + 2]) {
13587c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, PCFS_FRAGMENTED);
1359af28f636SEnrico Perla - Sun Microsystems 				return (BC_ERROR);
13607c478bd9Sstevel@tonic-gate 			}
1361af28f636SEnrico Perla - Sun Microsystems 			START_BLOCK(pos) = blocklist[i] + device->start_sector;
13627c478bd9Sstevel@tonic-gate 			START_SEG(pos) = (ushort_t)(install_addr >> 4);
13637c478bd9Sstevel@tonic-gate 			NUM_BLOCK(pos) = blocklist[i + 1];
13647c478bd9Sstevel@tonic-gate 			install_addr += blocklist[i + 1] * SECTOR_SIZE;
13657c478bd9Sstevel@tonic-gate 			pos -= 8;
13667c478bd9Sstevel@tonic-gate 			i += 2;
13677c478bd9Sstevel@tonic-gate 		}
13687c478bd9Sstevel@tonic-gate 	} else {
1369af28f636SEnrico Perla - Sun Microsystems 		/* Solaris VTOC */
1370af28f636SEnrico Perla - Sun Microsystems 		stage2->first_sector = device->start_sector + STAGE2_BLKOFF;
1371af28f636SEnrico Perla - Sun Microsystems 		BOOT_DEBUG("stage2 first sector: %d\n", stage2->first_sector);
13727c478bd9Sstevel@tonic-gate 		/*
13737c478bd9Sstevel@tonic-gate 		 * In a solaris partition, stage2 is written to contiguous
13747c478bd9Sstevel@tonic-gate 		 * blocks. So we update the starting block only.
13757c478bd9Sstevel@tonic-gate 		 */
1376af28f636SEnrico Perla - Sun Microsystems 		*((ulong_t *)(stage2->file + STAGE2_BLOCKLIST)) =
1377af28f636SEnrico Perla - Sun Microsystems 		    stage2->first_sector + 1;
13787c478bd9Sstevel@tonic-gate 	}
13797c478bd9Sstevel@tonic-gate 
1380af28f636SEnrico Perla - Sun Microsystems 	/* force lba and set disk partition */
1381af28f636SEnrico Perla - Sun Microsystems 	*((unsigned char *) (stage2->file + STAGE2_FORCE_LBA)) = 1;
1382af28f636SEnrico Perla - Sun Microsystems 	*((long *)(stage2->file + STAGE2_INSTALLPART))
1383af28f636SEnrico Perla - Sun Microsystems 	    = (device->partition << 16) | (device->slice << 8) | 0xff;
1384af28f636SEnrico Perla - Sun Microsystems 
1385af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
13867c478bd9Sstevel@tonic-gate }
13877c478bd9Sstevel@tonic-gate 
1388af28f636SEnrico Perla - Sun Microsystems static int
1389af28f636SEnrico Perla - Sun Microsystems find_x86_bootpar(struct mboot *mboot, int *part_num, uint32_t *start_sect)
13907c478bd9Sstevel@tonic-gate {
1391af28f636SEnrico Perla - Sun Microsystems 	int	i;
13927c478bd9Sstevel@tonic-gate 
1393af28f636SEnrico Perla - Sun Microsystems 	for (i = 0; i < FD_NUMPART; i++) {
1394af28f636SEnrico Perla - Sun Microsystems 		struct ipart	*part;
13957c478bd9Sstevel@tonic-gate 
1396af28f636SEnrico Perla - Sun Microsystems 		part = (struct ipart *)mboot->parts + i;
1397af28f636SEnrico Perla - Sun Microsystems 		if (part->systid == 0xbe) {
1398af28f636SEnrico Perla - Sun Microsystems 			if (start_sect)
1399af28f636SEnrico Perla - Sun Microsystems 				*start_sect = part->relsect;
1400af28f636SEnrico Perla - Sun Microsystems 			if (part_num)
1401af28f636SEnrico Perla - Sun Microsystems 				*part_num = i;
1402af28f636SEnrico Perla - Sun Microsystems 			/* solaris boot part */
1403af28f636SEnrico Perla - Sun Microsystems 			return (BC_SUCCESS);
1404af28f636SEnrico Perla - Sun Microsystems 		}
1405af28f636SEnrico Perla - Sun Microsystems 	}
1406af28f636SEnrico Perla - Sun Microsystems 	return (BC_ERROR);
1407af28f636SEnrico Perla - Sun Microsystems }
14087c478bd9Sstevel@tonic-gate 
1409af28f636SEnrico Perla - Sun Microsystems static char *
1410af28f636SEnrico Perla - Sun Microsystems get_raw_partition_path(ig_device_t *device)
1411af28f636SEnrico Perla - Sun Microsystems {
1412af28f636SEnrico Perla - Sun Microsystems 	char	*raw;
1413af28f636SEnrico Perla - Sun Microsystems 	int	len;
1414af28f636SEnrico Perla - Sun Microsystems 
1415af28f636SEnrico Perla - Sun Microsystems 	if (is_bootpar(device->type)) {
1416af28f636SEnrico Perla - Sun Microsystems 		int		part;
1417af28f636SEnrico Perla - Sun Microsystems 		struct mboot	*mboot;
1418af28f636SEnrico Perla - Sun Microsystems 
1419af28f636SEnrico Perla - Sun Microsystems 		mboot = (struct mboot *)device->boot_sector;
1420af28f636SEnrico Perla - Sun Microsystems 		if (find_x86_bootpar(mboot, &part, NULL) != BC_SUCCESS) {
1421af28f636SEnrico Perla - Sun Microsystems 			(void) fprintf(stderr, BOOTPAR_NOTFOUND,
1422af28f636SEnrico Perla - Sun Microsystems 			    device->path_p0);
1423af28f636SEnrico Perla - Sun Microsystems 			return (NULL);
14247c478bd9Sstevel@tonic-gate 		}
14257c478bd9Sstevel@tonic-gate 
1426af28f636SEnrico Perla - Sun Microsystems 		raw = strdup(device->path_p0);
1427af28f636SEnrico Perla - Sun Microsystems 		if (raw == NULL) {
1428af28f636SEnrico Perla - Sun Microsystems 			perror(gettext("Memory allocation failed"));
1429af28f636SEnrico Perla - Sun Microsystems 			return (NULL);
14307c478bd9Sstevel@tonic-gate 		}
1431af28f636SEnrico Perla - Sun Microsystems 
1432af28f636SEnrico Perla - Sun Microsystems 		raw[strlen(raw) - 2] = '1' + part;
14337c478bd9Sstevel@tonic-gate 		return (raw);
14347c478bd9Sstevel@tonic-gate 	}
14357c478bd9Sstevel@tonic-gate 
14367c478bd9Sstevel@tonic-gate 	/* For disk, remember slice and return whole fdisk partition  */
1437af28f636SEnrico Perla - Sun Microsystems 	raw = strdup(device->path);
1438af28f636SEnrico Perla - Sun Microsystems 	if (raw == NULL) {
1439af28f636SEnrico Perla - Sun Microsystems 		perror(gettext("Memory allocation failed"));
1440af28f636SEnrico Perla - Sun Microsystems 		return (NULL);
1441af28f636SEnrico Perla - Sun Microsystems 	}
1442af28f636SEnrico Perla - Sun Microsystems 
14437c478bd9Sstevel@tonic-gate 	len = strlen(raw);
14447c478bd9Sstevel@tonic-gate 	if (raw[len - 2] != 's' || raw[len - 1] == '2') {
14457c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, NOT_ROOT_SLICE);
1446af28f636SEnrico Perla - Sun Microsystems 		free(raw);
1447af28f636SEnrico Perla - Sun Microsystems 		return (NULL);
14487c478bd9Sstevel@tonic-gate 	}
1449af28f636SEnrico Perla - Sun Microsystems 	device->slice = atoi(&raw[len - 1]);
14507c478bd9Sstevel@tonic-gate 
14517c478bd9Sstevel@tonic-gate 	raw[len - 2] = 's';
14527c478bd9Sstevel@tonic-gate 	raw[len - 1] = '2';
1453af28f636SEnrico Perla - Sun Microsystems 
14547c478bd9Sstevel@tonic-gate 	return (raw);
14557c478bd9Sstevel@tonic-gate }
14567c478bd9Sstevel@tonic-gate 
1457af28f636SEnrico Perla - Sun Microsystems static int
1458af28f636SEnrico Perla - Sun Microsystems get_raw_partition_fd(ig_device_t *device)
1459af28f636SEnrico Perla - Sun Microsystems {
1460af28f636SEnrico Perla - Sun Microsystems 	struct stat	stat = {0};
1461af28f636SEnrico Perla - Sun Microsystems 	char		*raw;
1462af28f636SEnrico Perla - Sun Microsystems 
1463af28f636SEnrico Perla - Sun Microsystems 	raw = get_raw_partition_path(device);
1464af28f636SEnrico Perla - Sun Microsystems 	if (raw == NULL)
1465af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
1466af28f636SEnrico Perla - Sun Microsystems 
1467af28f636SEnrico Perla - Sun Microsystems 	if (nowrite)
1468af28f636SEnrico Perla - Sun Microsystems 		device->part_fd = open(raw, O_RDONLY);
1469af28f636SEnrico Perla - Sun Microsystems 	else
1470af28f636SEnrico Perla - Sun Microsystems 		device->part_fd = open(raw, O_RDWR);
1471af28f636SEnrico Perla - Sun Microsystems 
1472af28f636SEnrico Perla - Sun Microsystems 	if (device->part_fd < 0 || fstat(device->part_fd, &stat) != 0) {
1473af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, OPEN_FAIL, raw);
1474af28f636SEnrico Perla - Sun Microsystems 		free(raw);
1475af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
1476af28f636SEnrico Perla - Sun Microsystems 	}
1477af28f636SEnrico Perla - Sun Microsystems 
1478af28f636SEnrico Perla - Sun Microsystems 	if (S_ISCHR(stat.st_mode) == 0) {
1479af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, NOT_RAW_DEVICE, raw);
1480af28f636SEnrico Perla - Sun Microsystems 		(void) close(device->part_fd);
1481af28f636SEnrico Perla - Sun Microsystems 		device->part_fd = -1;
1482af28f636SEnrico Perla - Sun Microsystems 		free(raw);
1483af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
1484af28f636SEnrico Perla - Sun Microsystems 	}
1485af28f636SEnrico Perla - Sun Microsystems 
1486af28f636SEnrico Perla - Sun Microsystems 	free(raw);
1487af28f636SEnrico Perla - Sun Microsystems 	return (BC_SUCCESS);
1488af28f636SEnrico Perla - Sun Microsystems }
1489af28f636SEnrico Perla - Sun Microsystems 
14907c478bd9Sstevel@tonic-gate #define	TMP_MNTPT	"/tmp/installgrub_pcfs"
1491af28f636SEnrico Perla - Sun Microsystems static int
1492af28f636SEnrico Perla - Sun Microsystems copy_stage2_to_pcfs(ig_data_t *install)
14937c478bd9Sstevel@tonic-gate {
1494af28f636SEnrico Perla - Sun Microsystems 	FILE		*mntfp;
1495af28f636SEnrico Perla - Sun Microsystems 	int		pcfs_fp;
1496af28f636SEnrico Perla - Sun Microsystems 	int		status = BC_ERROR;
1497af28f636SEnrico Perla - Sun Microsystems 	char		buf[SECTOR_SIZE];
1498af28f636SEnrico Perla - Sun Microsystems 	char		*cp;
1499af28f636SEnrico Perla - Sun Microsystems 	struct mnttab	mp = {0}, mpref = {0};
1500af28f636SEnrico Perla - Sun Microsystems 	ig_device_t	*device = &install->device;
1501af28f636SEnrico Perla - Sun Microsystems 	ig_stage2_t	*stage2 = &install->stage2;
15027c478bd9Sstevel@tonic-gate 
15037c478bd9Sstevel@tonic-gate 	/* convert raw to block device name by removing the first 'r' */
1504af28f636SEnrico Perla - Sun Microsystems 	(void) strncpy(buf, device->path, sizeof (buf));
15057c478bd9Sstevel@tonic-gate 	buf[sizeof (buf) - 1] = 0;
15067c478bd9Sstevel@tonic-gate 	cp = strchr(buf, 'r');
15077c478bd9Sstevel@tonic-gate 	if (cp == NULL) {
1508af28f636SEnrico Perla - Sun Microsystems 		(void) fprintf(stderr, CONVERT_FAIL, device->path);
1509af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
15107c478bd9Sstevel@tonic-gate 	}
15117c478bd9Sstevel@tonic-gate 	do {
15127c478bd9Sstevel@tonic-gate 		*cp = *(cp + 1);
15137c478bd9Sstevel@tonic-gate 	} while (*(++cp));
15147c478bd9Sstevel@tonic-gate 
15157c478bd9Sstevel@tonic-gate 	/* get the mount point, if any */
15167c478bd9Sstevel@tonic-gate 	mntfp = fopen("/etc/mnttab", "r");
15177c478bd9Sstevel@tonic-gate 	if (mntfp == NULL) {
15187c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, OPEN_FAIL_FILE, "/etc/mnttab");
1519af28f636SEnrico Perla - Sun Microsystems 		return (BC_ERROR);
15207c478bd9Sstevel@tonic-gate 	}
15217c478bd9Sstevel@tonic-gate 
15227c478bd9Sstevel@tonic-gate 	mpref.mnt_special = buf;
15237c478bd9Sstevel@tonic-gate 	if (getmntany(mntfp, &mp, &mpref) != 0) {
15247c478bd9Sstevel@tonic-gate 		char cmd[128];
15257c478bd9Sstevel@tonic-gate 
15267c478bd9Sstevel@tonic-gate 		/* not mounted, try remount */
15277c478bd9Sstevel@tonic-gate 		(void) mkdir(TMP_MNTPT, S_IRWXU);
15287c478bd9Sstevel@tonic-gate 		(void) snprintf(cmd, sizeof (cmd), "mount -F pcfs %s %s",
15297c478bd9Sstevel@tonic-gate 		    buf, TMP_MNTPT);
15307c478bd9Sstevel@tonic-gate 		(void) system(cmd);
15317c478bd9Sstevel@tonic-gate 		rewind(mntfp);
15327c478bd9Sstevel@tonic-gate 		bzero(&mp, sizeof (mp));
15337c478bd9Sstevel@tonic-gate 		if (getmntany(mntfp, &mp, &mpref) != 0) {
15347c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, MOUNT_FAIL, buf);
1535af28f636SEnrico Perla - Sun Microsystems 			return (BC_ERROR);
15367c478bd9Sstevel@tonic-gate 		}
15377c478bd9Sstevel@tonic-gate 	}
15387c478bd9Sstevel@tonic-gate 
15397c478bd9Sstevel@tonic-gate 	(void) snprintf(buf, sizeof (buf),
15407c478bd9Sstevel@tonic-gate 	    "%s/boot", mp.mnt_mountp);
15417c478bd9Sstevel@tonic-gate 	(void) mkdir(buf, S_IRWXU);
15427c478bd9Sstevel@tonic-gate 	(void) strcat(buf, "/grub");
15437c478bd9Sstevel@tonic-gate 	(void) mkdir(buf, S_IRWXU);
15447c478bd9Sstevel@tonic-gate 
15457c478bd9Sstevel@tonic-gate 	(void) strcat(buf, "/stage2");
15467c478bd9Sstevel@tonic-gate 	pcfs_fp = open(buf, O_WRONLY | O_CREAT, S_IRWXU);
15477c478bd9Sstevel@tonic-gate 	if (pcfs_fp == -1) {
15487c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, OPEN_FAIL_FILE, buf);
15497c478bd9Sstevel@tonic-gate 		perror("open:");
1550af28f636SEnrico Perla - Sun Microsystems 		goto out;
1551af28f636SEnrico Perla - Sun Microsystems 	}
1552af28f636SEnrico Perla - Sun Microsystems 
1553af28f636SEnrico Perla - Sun Microsystems 	/* write stage2 to the pcfs mounted filesystem. */
1554af28f636SEnrico Perla - Sun Microsystems 	if (write(pcfs_fp, stage2->file, stage2->file_size)
1555af28f636SEnrico Perla - Sun Microsystems 	    != stage2->file_size) {
1556af28f636SEnrico Perla - Sun Microsystems 		perror(gettext("Error writing stage2"));
1557af28f636SEnrico Perla - Sun Microsystems 		goto out;
15587c478bd9Sstevel@tonic-gate 	}
1559af28f636SEnrico Perla - Sun Microsystems 
1560af28f636SEnrico Perla - Sun Microsystems 	status = BC_SUCCESS;
1561af28f636SEnrico Perla - Sun Microsystems out_fd:
15627c478bd9Sstevel@tonic-gate 	(void) close(pcfs_fp);
1563af28f636SEnrico Perla - Sun Microsystems out:
15647c478bd9Sstevel@tonic-gate 	(void) umount(TMP_MNTPT);
1565af28f636SEnrico Perla - Sun Microsystems 	(void) rmdir(TMP_MNTPT);
1566af28f636SEnrico Perla - Sun Microsystems 	return (status);
15677c478bd9Sstevel@tonic-gate }
1568