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