xref: /titanic_53/usr/src/cmd/boot/installgrub/installgrub.c (revision 7fc5d2a453d54fb46bb4a17b2bd1b59b0a711575)
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
5d33344bbSsy25831  * Common Development and Distribution License (the "License").
6d33344bbSsy25831  * 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 /*
22aa1b14e7SSheshadri Vasudevan  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <stdio.h>
277c478bd9Sstevel@tonic-gate #include <stdlib.h>
287c478bd9Sstevel@tonic-gate #include <libgen.h>
297c478bd9Sstevel@tonic-gate #include <malloc.h>
307c478bd9Sstevel@tonic-gate #include <string.h>
317c478bd9Sstevel@tonic-gate #include <sys/types.h>
327c478bd9Sstevel@tonic-gate #include <sys/stat.h>
337c478bd9Sstevel@tonic-gate #include <fcntl.h>
347c478bd9Sstevel@tonic-gate #include <unistd.h>
357c478bd9Sstevel@tonic-gate #include <strings.h>
367c478bd9Sstevel@tonic-gate #include <sys/mount.h>
377c478bd9Sstevel@tonic-gate #include <sys/mnttab.h>
387c478bd9Sstevel@tonic-gate #include <sys/dktp/fdisk.h>
39d33344bbSsy25831 #include <sys/dkio.h>
40d33344bbSsy25831 #include <sys/vtoc.h>
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate #include <libintl.h>
437c478bd9Sstevel@tonic-gate #include <locale.h>
447c478bd9Sstevel@tonic-gate #include "message.h"
45c6fe1048Sjongkis #include <errno.h>
46aa1b14e7SSheshadri Vasudevan #include <libfdisk.h>
477ce76caaSEnrico Perla - Sun Microsystems #include <md5.h>
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate #ifndef	TEXT_DOMAIN
507c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"SUNW_OST_OSCMD"
517c478bd9Sstevel@tonic-gate #endif
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate #define	SECTOR_SIZE	0x200
547ce76caaSEnrico Perla - Sun Microsystems #define	HASH_SIZE	0x10
557ce76caaSEnrico Perla - Sun Microsystems #define	VERSION_SIZE	0x50
567c478bd9Sstevel@tonic-gate #define	STAGE2_MEMADDR	0x8000	/* loading addr of stage2 */
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate #define	STAGE1_BPB_OFFSET	0x3
597c478bd9Sstevel@tonic-gate #define	STAGE1_BPB_SIZE		0x3B
607c478bd9Sstevel@tonic-gate #define	STAGE1_BOOT_DRIVE	0x40
617c478bd9Sstevel@tonic-gate #define	STAGE1_FORCE_LBA	0x41
627c478bd9Sstevel@tonic-gate #define	STAGE1_STAGE2_ADDRESS	0x42
637c478bd9Sstevel@tonic-gate #define	STAGE1_STAGE2_SECTOR	0x44
647c478bd9Sstevel@tonic-gate #define	STAGE1_STAGE2_SEGMENT	0x48
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate #define	STAGE2_BLOCKLIST	(SECTOR_SIZE - 0x8)
677c478bd9Sstevel@tonic-gate #define	STAGE2_INSTALLPART	(SECTOR_SIZE + 0x8)
687c478bd9Sstevel@tonic-gate #define	STAGE2_FORCE_LBA	(SECTOR_SIZE + 0x11)
697c478bd9Sstevel@tonic-gate #define	STAGE2_VER_STRING	(SECTOR_SIZE + 0x12)
707ce76caaSEnrico Perla - Sun Microsystems #define	STAGE2_SIGN_OFFSET	(SECTOR_SIZE + 0x60)
717ce76caaSEnrico Perla - Sun Microsystems #define	STAGE2_PKG_VERSION	(SECTOR_SIZE + 0x70)
727c478bd9Sstevel@tonic-gate #define	STAGE2_BLKOFF		50	/* offset from start of fdisk part */
737c478bd9Sstevel@tonic-gate 
747ce76caaSEnrico Perla - Sun Microsystems static char extended_sig[] = "\xCC\xCC\xCC\xCC\xAA\xAA\xAA\xAA\xBB\xBB\xBB\xBB"
757ce76caaSEnrico Perla - Sun Microsystems "\xBB\xBB\xBB\xBB";
767ce76caaSEnrico Perla - Sun Microsystems 
777c478bd9Sstevel@tonic-gate static int nowrite = 0;
787c478bd9Sstevel@tonic-gate static int write_mboot = 0;
797c478bd9Sstevel@tonic-gate static int force_mboot = 0;
807ce76caaSEnrico Perla - Sun Microsystems static int getinfo = 0;
817ce76caaSEnrico Perla - Sun Microsystems static int do_version = 0;
827c478bd9Sstevel@tonic-gate static int is_floppy = 0;
837c478bd9Sstevel@tonic-gate static int is_bootpar = 0;
847ce76caaSEnrico Perla - Sun Microsystems static int strip = 0;
857c478bd9Sstevel@tonic-gate static int stage2_fd;
867c478bd9Sstevel@tonic-gate static int partition, slice = 0xff;
87aa1b14e7SSheshadri Vasudevan static char *device_p0;
88aa1b14e7SSheshadri Vasudevan static uint32_t stage2_first_sector, stage2_second_sector;
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate static char bpb_sect[SECTOR_SIZE];
927c478bd9Sstevel@tonic-gate static char boot_sect[SECTOR_SIZE];
937c478bd9Sstevel@tonic-gate static char stage1_buffer[SECTOR_SIZE];
947c478bd9Sstevel@tonic-gate static char stage2_buffer[2 * SECTOR_SIZE];
957ce76caaSEnrico Perla - Sun Microsystems static char signature[HASH_SIZE];
967ce76caaSEnrico Perla - Sun Microsystems static char verstring[VERSION_SIZE];
97342440ecSPrasad Singamsetty static unsigned int blocklist[SECTOR_SIZE / sizeof (unsigned int)];
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate static int open_device(char *);
1007c478bd9Sstevel@tonic-gate static void read_bpb_sect(int);
1017c478bd9Sstevel@tonic-gate static void read_boot_sect(char *);
1027c478bd9Sstevel@tonic-gate static void write_boot_sect(char *);
1037c478bd9Sstevel@tonic-gate static void read_stage1_stage2(char *, char *);
1047c478bd9Sstevel@tonic-gate static void modify_and_write_stage1(int);
1057c478bd9Sstevel@tonic-gate static void modify_and_write_stage2(int);
106342440ecSPrasad Singamsetty static unsigned int get_start_sector(int);
1077c478bd9Sstevel@tonic-gate static void copy_stage2(int, char *);
1087c478bd9Sstevel@tonic-gate static char *get_raw_partition(char *);
1097c478bd9Sstevel@tonic-gate static void usage(char *);
1107ce76caaSEnrico Perla - Sun Microsystems static void print_info();
1117ce76caaSEnrico Perla - Sun Microsystems static int read_stage2_info(int);
1127ce76caaSEnrico Perla - Sun Microsystems static void check_extended_support();
1137c478bd9Sstevel@tonic-gate 
114342440ecSPrasad Singamsetty extern int read_stage2_blocklist(int, unsigned int *);
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate int
1177c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
1187c478bd9Sstevel@tonic-gate {
1197ce76caaSEnrico Perla - Sun Microsystems 	int dev_fd, opt, params = 3;
1207c478bd9Sstevel@tonic-gate 	char *stage1, *stage2, *device;
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
1237c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
1247c478bd9Sstevel@tonic-gate 
1257ce76caaSEnrico Perla - Sun Microsystems 	while ((opt = getopt(argc, argv, "fmneis:")) != EOF) {
1267c478bd9Sstevel@tonic-gate 		switch (opt) {
1277c478bd9Sstevel@tonic-gate 		case 'm':
1287c478bd9Sstevel@tonic-gate 			write_mboot = 1;
1297c478bd9Sstevel@tonic-gate 			break;
1307c478bd9Sstevel@tonic-gate 		case 'n':
1317c478bd9Sstevel@tonic-gate 			nowrite = 1;
1327c478bd9Sstevel@tonic-gate 			break;
1337c478bd9Sstevel@tonic-gate 		case 'f':
1347c478bd9Sstevel@tonic-gate 			force_mboot = 1;
1357c478bd9Sstevel@tonic-gate 			break;
1367ce76caaSEnrico Perla - Sun Microsystems 		case 'i':
1377ce76caaSEnrico Perla - Sun Microsystems 			getinfo = 1;
1387ce76caaSEnrico Perla - Sun Microsystems 			params = 1;
1397ce76caaSEnrico Perla - Sun Microsystems 			break;
1407ce76caaSEnrico Perla - Sun Microsystems 		case 'e':
1417ce76caaSEnrico Perla - Sun Microsystems 			strip = 1;
1427ce76caaSEnrico Perla - Sun Microsystems 			break;
1437ce76caaSEnrico Perla - Sun Microsystems 		case 's':
1447ce76caaSEnrico Perla - Sun Microsystems 			do_version = 1;
1457ce76caaSEnrico Perla - Sun Microsystems 			(void) snprintf(verstring, sizeof (verstring), "%s",
1467ce76caaSEnrico Perla - Sun Microsystems 			    optarg);
1477ce76caaSEnrico Perla - Sun Microsystems 			break;
1487c478bd9Sstevel@tonic-gate 		default:
1497c478bd9Sstevel@tonic-gate 			/* fall through to process non-optional args */
1507c478bd9Sstevel@tonic-gate 			break;
1517c478bd9Sstevel@tonic-gate 		}
1527c478bd9Sstevel@tonic-gate 	}
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 	/* check arguments */
1557ce76caaSEnrico Perla - Sun Microsystems 	if (argc != optind + params) {
1567c478bd9Sstevel@tonic-gate 		usage(argv[0]);
1577c478bd9Sstevel@tonic-gate 	}
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	if (nowrite) {
1607c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout, DRY_RUN);
1617c478bd9Sstevel@tonic-gate 	}
1627c478bd9Sstevel@tonic-gate 
1637ce76caaSEnrico Perla - Sun Microsystems 	if (params == 1) {
1647ce76caaSEnrico Perla - Sun Microsystems 		device = strdup(argv[optind]);
1657ce76caaSEnrico Perla - Sun Microsystems 		if (!device) {
1667ce76caaSEnrico Perla - Sun Microsystems 			usage(argv[0]);
1677ce76caaSEnrico Perla - Sun Microsystems 		}
1687ce76caaSEnrico Perla - Sun Microsystems 	} else if (params == 3) {
1697c478bd9Sstevel@tonic-gate 		stage1 = strdup(argv[optind]);
1707c478bd9Sstevel@tonic-gate 		stage2 = strdup(argv[optind + 1]);
1717c478bd9Sstevel@tonic-gate 		device = strdup(argv[optind + 2]);
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate 		if (!stage1 || !stage2 || !device) {
1747c478bd9Sstevel@tonic-gate 			usage(argv[0]);
1757c478bd9Sstevel@tonic-gate 		}
1767ce76caaSEnrico Perla - Sun Microsystems 	}
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate 	/* open and check device type */
1797c478bd9Sstevel@tonic-gate 	dev_fd = open_device(device);
1807c478bd9Sstevel@tonic-gate 
1817ce76caaSEnrico Perla - Sun Microsystems 	if (getinfo) {
1827ce76caaSEnrico Perla - Sun Microsystems 		if (read_stage2_info(dev_fd) != 0) {
1837ce76caaSEnrico Perla - Sun Microsystems 			fprintf(stderr, "Unable to read extended information"
1847ce76caaSEnrico Perla - Sun Microsystems 			    " from %s\n", device);
1857ce76caaSEnrico Perla - Sun Microsystems 			exit(1);
1867ce76caaSEnrico Perla - Sun Microsystems 		}
1877ce76caaSEnrico Perla - Sun Microsystems 		print_info();
1887ce76caaSEnrico Perla - Sun Microsystems 		(void) free(device);
1897ce76caaSEnrico Perla - Sun Microsystems 		(void) close(dev_fd);
1907ce76caaSEnrico Perla - Sun Microsystems 		return (0);
1917ce76caaSEnrico Perla - Sun Microsystems 	}
1927ce76caaSEnrico Perla - Sun Microsystems 
1937c478bd9Sstevel@tonic-gate 	/* read in stage1 and stage2 into buffer */
1947c478bd9Sstevel@tonic-gate 	read_stage1_stage2(stage1, stage2);
1957c478bd9Sstevel@tonic-gate 
1967ce76caaSEnrico Perla - Sun Microsystems 	/* check if stage2 supports extended versioning */
1977ce76caaSEnrico Perla - Sun Microsystems 	if (do_version)
1987ce76caaSEnrico Perla - Sun Microsystems 		check_extended_support(stage2);
1997ce76caaSEnrico Perla - Sun Microsystems 
2007c478bd9Sstevel@tonic-gate 	/* In the pcfs case, write a fresh stage2 */
2017c478bd9Sstevel@tonic-gate 	if (is_floppy || is_bootpar) {
2027c478bd9Sstevel@tonic-gate 		copy_stage2(dev_fd, device);
2037c478bd9Sstevel@tonic-gate 		read_bpb_sect(dev_fd);
2047c478bd9Sstevel@tonic-gate 	}
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 	/* read in boot sector */
2077c478bd9Sstevel@tonic-gate 	if (!is_floppy)
2087c478bd9Sstevel@tonic-gate 		read_boot_sect(device);
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 	/* modify stage1 based on grub needs */
2117c478bd9Sstevel@tonic-gate 	modify_and_write_stage1(dev_fd);
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate 	/* modify stage2 and write to media */
2147c478bd9Sstevel@tonic-gate 	modify_and_write_stage2(dev_fd);
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate 	if (!is_floppy && write_mboot)
2177c478bd9Sstevel@tonic-gate 		write_boot_sect(device);
2187ce76caaSEnrico Perla - Sun Microsystems 
2197c478bd9Sstevel@tonic-gate 	(void) close(dev_fd);
2207ce76caaSEnrico Perla - Sun Microsystems 	free(device);
2217ce76caaSEnrico Perla - Sun Microsystems 	free(stage1);
2227ce76caaSEnrico Perla - Sun Microsystems 	free(stage2);
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 	return (0);
2257c478bd9Sstevel@tonic-gate }
2267c478bd9Sstevel@tonic-gate 
227342440ecSPrasad Singamsetty static unsigned int
228d33344bbSsy25831 get_start_sector(int fd)
2297c478bd9Sstevel@tonic-gate {
230342440ecSPrasad Singamsetty 	static unsigned int start_sect = 0;
231*7fc5d2a4SVikram Hegde 	uint32_t secnum = 0, numsec = 0;
232*7fc5d2a4SVikram Hegde 	int i, pno, rval, log_part = 0;
2337c478bd9Sstevel@tonic-gate 	struct mboot *mboot;
2347c478bd9Sstevel@tonic-gate 	struct ipart *part;
235aa1b14e7SSheshadri Vasudevan 	ext_part_t *epp;
236*7fc5d2a4SVikram Hegde 	struct part_info dkpi;
237*7fc5d2a4SVikram Hegde 	struct extpart_info edkpi;
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate 	if (start_sect)
2407c478bd9Sstevel@tonic-gate 		return (start_sect);
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 	mboot = (struct mboot *)boot_sect;
2437c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
2447c478bd9Sstevel@tonic-gate 		part = (struct ipart *)mboot->parts + i;
2457c478bd9Sstevel@tonic-gate 		if (is_bootpar) {
246*7fc5d2a4SVikram Hegde 			if (part->systid == 0xbe) {
247*7fc5d2a4SVikram Hegde 				start_sect = part->relsect;
248*7fc5d2a4SVikram Hegde 				partition = i;
249*7fc5d2a4SVikram Hegde 				goto found_part;
250*7fc5d2a4SVikram Hegde 			}
251d33344bbSsy25831 		}
252d33344bbSsy25831 	}
253d33344bbSsy25831 
254aa1b14e7SSheshadri Vasudevan 	/*
255*7fc5d2a4SVikram Hegde 	 * We will not support x86 boot partition on extended partitions
256aa1b14e7SSheshadri Vasudevan 	 */
257*7fc5d2a4SVikram Hegde 	if (is_bootpar) {
258*7fc5d2a4SVikram Hegde 		(void) fprintf(stderr, NOBOOTPAR);
259*7fc5d2a4SVikram Hegde 		exit(-1);
2607d87efa8Sjmcp 	}
2617d87efa8Sjmcp 
262d33344bbSsy25831 	/*
263*7fc5d2a4SVikram Hegde 	 * Not an x86 boot partition. Search for Solaris fdisk partition
264d33344bbSsy25831 	 * Get the solaris partition information from the device
265d33344bbSsy25831 	 * and compare the offset of S2 with offset of solaris partition
266d33344bbSsy25831 	 * from fdisk partition table.
267d33344bbSsy25831 	 */
268342440ecSPrasad Singamsetty 	if (ioctl(fd, DKIOCEXTPARTINFO, &edkpi) < 0) {
269d33344bbSsy25831 		if (ioctl(fd, DKIOCPARTINFO, &dkpi) < 0) {
270d33344bbSsy25831 			(void) fprintf(stderr, PART_FAIL);
271d33344bbSsy25831 			exit(-1);
272342440ecSPrasad Singamsetty 		} else {
273342440ecSPrasad Singamsetty 			edkpi.p_start = dkpi.p_start;
274342440ecSPrasad Singamsetty 		}
275d33344bbSsy25831 	}
276d33344bbSsy25831 
277d33344bbSsy25831 	for (i = 0; i < FD_NUMPART; i++) {
278d33344bbSsy25831 		part = (struct ipart *)mboot->parts + i;
279d33344bbSsy25831 
280d33344bbSsy25831 		if (part->relsect == 0) {
281d33344bbSsy25831 			(void) fprintf(stderr, BAD_PART, i);
282d33344bbSsy25831 			exit(-1);
283d33344bbSsy25831 		}
284aa1b14e7SSheshadri Vasudevan 
285342440ecSPrasad Singamsetty 		if (edkpi.p_start >= part->relsect &&
286342440ecSPrasad Singamsetty 		    edkpi.p_start < (part->relsect + part->numsect)) {
287d33344bbSsy25831 			/* Found the partition */
2887c478bd9Sstevel@tonic-gate 			break;
289d33344bbSsy25831 		}
2907c478bd9Sstevel@tonic-gate 	}
2917c478bd9Sstevel@tonic-gate 
292*7fc5d2a4SVikram Hegde 	if (i == FD_NUMPART) {
293*7fc5d2a4SVikram Hegde 		/* No solaris fdisk partitions (primary or logical) */
294*7fc5d2a4SVikram Hegde 		(void) fprintf(stderr, NOSOLPAR);
2957c478bd9Sstevel@tonic-gate 		exit(-1);
2967c478bd9Sstevel@tonic-gate 	}
2977c478bd9Sstevel@tonic-gate 
298*7fc5d2a4SVikram Hegde 	/*
299*7fc5d2a4SVikram Hegde 	 * We have found a Solaris fdisk partition (primary or extended)
300*7fc5d2a4SVikram Hegde 	 * Handle the simple case first: Solaris in a primary partition
301*7fc5d2a4SVikram Hegde 	 */
302*7fc5d2a4SVikram Hegde 	if (!fdisk_is_dos_extended(part->systid)) {
303*7fc5d2a4SVikram Hegde 		start_sect = part->relsect;
304*7fc5d2a4SVikram Hegde 		partition = i;
305*7fc5d2a4SVikram Hegde 		goto found_part;
306*7fc5d2a4SVikram Hegde 	}
307*7fc5d2a4SVikram Hegde 
308*7fc5d2a4SVikram Hegde 	/*
309*7fc5d2a4SVikram Hegde 	 * Solaris in a logical partition. Find that partition in the
310*7fc5d2a4SVikram Hegde 	 * extended part.
311*7fc5d2a4SVikram Hegde 	 */
312*7fc5d2a4SVikram Hegde 	if ((rval = libfdisk_init(&epp, device_p0, NULL, FDISK_READ_DISK))
313*7fc5d2a4SVikram Hegde 	    != FDISK_SUCCESS) {
314*7fc5d2a4SVikram Hegde 		switch (rval) {
315*7fc5d2a4SVikram Hegde 			/*
316*7fc5d2a4SVikram Hegde 			 * The first 2 cases are not an error per-se, just that
317*7fc5d2a4SVikram Hegde 			 * there is no Solaris logical partition
318*7fc5d2a4SVikram Hegde 			 */
319*7fc5d2a4SVikram Hegde 			case FDISK_EBADLOGDRIVE:
320*7fc5d2a4SVikram Hegde 			case FDISK_ENOLOGDRIVE:
321*7fc5d2a4SVikram Hegde 				(void) fprintf(stderr, NOSOLPAR);
322*7fc5d2a4SVikram Hegde 				exit(-1);
323*7fc5d2a4SVikram Hegde 				/*NOTREACHED*/
324*7fc5d2a4SVikram Hegde 			case FDISK_ENOVGEOM:
325*7fc5d2a4SVikram Hegde 				(void) fprintf(stderr, NO_VIRT_GEOM);
326*7fc5d2a4SVikram Hegde 				exit(1);
327*7fc5d2a4SVikram Hegde 				break;
328*7fc5d2a4SVikram Hegde 			case FDISK_ENOPGEOM:
329*7fc5d2a4SVikram Hegde 				(void) fprintf(stderr, NO_PHYS_GEOM);
330*7fc5d2a4SVikram Hegde 				exit(1);
331*7fc5d2a4SVikram Hegde 				break;
332*7fc5d2a4SVikram Hegde 			case FDISK_ENOLGEOM:
333*7fc5d2a4SVikram Hegde 				(void) fprintf(stderr, NO_LABEL_GEOM);
334*7fc5d2a4SVikram Hegde 				exit(1);
335*7fc5d2a4SVikram Hegde 				break;
336*7fc5d2a4SVikram Hegde 			default:
337*7fc5d2a4SVikram Hegde 				(void) fprintf(stderr, LIBFDISK_INIT_FAIL);
338*7fc5d2a4SVikram Hegde 				exit(1);
339*7fc5d2a4SVikram Hegde 				break;
340*7fc5d2a4SVikram Hegde 		}
341*7fc5d2a4SVikram Hegde 	}
342*7fc5d2a4SVikram Hegde 
343*7fc5d2a4SVikram Hegde 	rval = fdisk_get_solaris_part(epp, &pno, &secnum, &numsec);
344*7fc5d2a4SVikram Hegde 	if (rval != FDISK_SUCCESS) {
345*7fc5d2a4SVikram Hegde 		/* No solaris logical partition */
346*7fc5d2a4SVikram Hegde 		(void) fprintf(stderr, NOSOLPAR);
347*7fc5d2a4SVikram Hegde 		exit(-1);
348*7fc5d2a4SVikram Hegde 	}
349*7fc5d2a4SVikram Hegde 	libfdisk_fini(&epp);
350*7fc5d2a4SVikram Hegde 
351*7fc5d2a4SVikram Hegde 	start_sect = secnum;
352*7fc5d2a4SVikram Hegde 	partition = pno - 1;
353*7fc5d2a4SVikram Hegde 	log_part = 1;
354*7fc5d2a4SVikram Hegde 
355*7fc5d2a4SVikram Hegde found_part:
3567c478bd9Sstevel@tonic-gate 	/* get confirmation for -m */
3577c478bd9Sstevel@tonic-gate 	if (write_mboot && !force_mboot) {
3587c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout, MBOOT_PROMPT);
3597c478bd9Sstevel@tonic-gate 		if (getchar() != 'y') {
3607c478bd9Sstevel@tonic-gate 			write_mboot = 0;
3617c478bd9Sstevel@tonic-gate 			(void) fprintf(stdout, MBOOT_NOT_UPDATED);
3627c478bd9Sstevel@tonic-gate 		}
3637c478bd9Sstevel@tonic-gate 	}
3647c478bd9Sstevel@tonic-gate 
365*7fc5d2a4SVikram Hegde 	/*
366*7fc5d2a4SVikram Hegde 	 * Currently if Solaris is in an extended partition we need to
367*7fc5d2a4SVikram Hegde 	 * write GRUB to the MBR. Check for this.
368*7fc5d2a4SVikram Hegde 	 */
369*7fc5d2a4SVikram Hegde 	if (log_part && !write_mboot) {
370*7fc5d2a4SVikram Hegde 		(void) fprintf(stderr, EXTSOLPAR);
371*7fc5d2a4SVikram Hegde 		exit(-1);
372aa1b14e7SSheshadri Vasudevan 	}
373aa1b14e7SSheshadri Vasudevan 
374*7fc5d2a4SVikram Hegde 	/*
375*7fc5d2a4SVikram Hegde 	 * warn, if Solaris in primary partition and GRUB not in MBR and
376*7fc5d2a4SVikram Hegde 	 * partition is not active
377*7fc5d2a4SVikram Hegde 	 */
378*7fc5d2a4SVikram Hegde 	if (!log_part && part->bootid != 128 && !write_mboot) {
379*7fc5d2a4SVikram Hegde 		(void) fprintf(stdout, SOLPAR_INACTIVE, partition + 1);
3807c478bd9Sstevel@tonic-gate 	}
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 	return (start_sect);
3837c478bd9Sstevel@tonic-gate }
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate static void
3867c478bd9Sstevel@tonic-gate usage(char *progname)
3877c478bd9Sstevel@tonic-gate {
3887c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, USAGE, basename(progname));
3897c478bd9Sstevel@tonic-gate 	exit(-1);
3907c478bd9Sstevel@tonic-gate }
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate static int
3937c478bd9Sstevel@tonic-gate open_device(char *device)
3947c478bd9Sstevel@tonic-gate {
3957c478bd9Sstevel@tonic-gate 	int dev_fd;
3967c478bd9Sstevel@tonic-gate 	struct stat stat;
3977c478bd9Sstevel@tonic-gate 	char *raw_part;
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 	is_floppy = strncmp(device, "/dev/rdsk", strlen("/dev/rdsk")) &&
4007c478bd9Sstevel@tonic-gate 	    strncmp(device, "/dev/dsk", strlen("/dev/dsk"));
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate 	/* handle boot partition specification */
4037c478bd9Sstevel@tonic-gate 	if (!is_floppy && strstr(device, "p0:boot")) {
4047c478bd9Sstevel@tonic-gate 		is_bootpar = 1;
4057c478bd9Sstevel@tonic-gate 	}
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate 	raw_part = get_raw_partition(device);
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 	if (nowrite)
4107c478bd9Sstevel@tonic-gate 		dev_fd = open(raw_part, O_RDONLY);
4117c478bd9Sstevel@tonic-gate 	else
4127c478bd9Sstevel@tonic-gate 		dev_fd = open(raw_part, O_RDWR);
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 	if (dev_fd == -1 || fstat(dev_fd, &stat) != 0) {
4157c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, OPEN_FAIL, raw_part);
4167c478bd9Sstevel@tonic-gate 		exit(-1);
4177c478bd9Sstevel@tonic-gate 	}
4187c478bd9Sstevel@tonic-gate 	if (S_ISCHR(stat.st_mode) == 0) {
4197c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, NOT_RAW_DEVICE, raw_part);
4207c478bd9Sstevel@tonic-gate 		exit(-1);
4217c478bd9Sstevel@tonic-gate 	}
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate 	return (dev_fd);
4247c478bd9Sstevel@tonic-gate }
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate static void
4277c478bd9Sstevel@tonic-gate read_stage1_stage2(char *stage1, char *stage2)
4287c478bd9Sstevel@tonic-gate {
4297c478bd9Sstevel@tonic-gate 	int fd;
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 	/* read the stage1 file from filesystem */
4327c478bd9Sstevel@tonic-gate 	fd = open(stage1, O_RDONLY);
4337c478bd9Sstevel@tonic-gate 	if (fd == -1 || read(fd, stage1_buffer, SECTOR_SIZE) != SECTOR_SIZE) {
4347c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, READ_FAIL_STAGE1, stage1);
4357c478bd9Sstevel@tonic-gate 		exit(-1);
4367c478bd9Sstevel@tonic-gate 	}
4377c478bd9Sstevel@tonic-gate 	(void) close(fd);
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate 	/* read first two blocks of stage 2 from filesystem */
4407c478bd9Sstevel@tonic-gate 	stage2_fd = open(stage2, O_RDONLY);
4417c478bd9Sstevel@tonic-gate 	if (stage2_fd == -1 ||
4427c478bd9Sstevel@tonic-gate 	    read(stage2_fd, stage2_buffer, 2 * SECTOR_SIZE)
4437c478bd9Sstevel@tonic-gate 	    != 2 * SECTOR_SIZE) {
4447c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, READ_FAIL_STAGE2, stage2);
4457c478bd9Sstevel@tonic-gate 		exit(-1);
4467c478bd9Sstevel@tonic-gate 	}
4477c478bd9Sstevel@tonic-gate 	/* leave the stage2 file open for later */
4487c478bd9Sstevel@tonic-gate }
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate static void
4517c478bd9Sstevel@tonic-gate read_bpb_sect(int dev_fd)
4527c478bd9Sstevel@tonic-gate {
4537c478bd9Sstevel@tonic-gate 	if (pread(dev_fd, bpb_sect, SECTOR_SIZE, 0) != SECTOR_SIZE) {
4547c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, READ_FAIL_BPB);
4557c478bd9Sstevel@tonic-gate 		exit(-1);
4567c478bd9Sstevel@tonic-gate 	}
4577c478bd9Sstevel@tonic-gate }
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate static void
4607c478bd9Sstevel@tonic-gate read_boot_sect(char *device)
4617c478bd9Sstevel@tonic-gate {
4627c478bd9Sstevel@tonic-gate 	static int read_mbr = 0;
4637c478bd9Sstevel@tonic-gate 	int i, fd;
4647c478bd9Sstevel@tonic-gate 	char save[2];
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate 	if (read_mbr)
4677c478bd9Sstevel@tonic-gate 		return;
4687c478bd9Sstevel@tonic-gate 	read_mbr = 1;
4697c478bd9Sstevel@tonic-gate 
4707c478bd9Sstevel@tonic-gate 	/* get the whole disk (p0) */
4717c478bd9Sstevel@tonic-gate 	i = strlen(device);
4727c478bd9Sstevel@tonic-gate 	save[0] = device[i - 2];
4737c478bd9Sstevel@tonic-gate 	save[1] = device[i - 1];
4747c478bd9Sstevel@tonic-gate 	device[i - 2] = 'p';
4757c478bd9Sstevel@tonic-gate 	device[i - 1] = '0';
4767c478bd9Sstevel@tonic-gate 
477aa1b14e7SSheshadri Vasudevan 	device_p0 = strdup(device);
4787c478bd9Sstevel@tonic-gate 	fd = open(device, O_RDONLY);
4797c478bd9Sstevel@tonic-gate 	if (fd == -1 || read(fd, boot_sect, SECTOR_SIZE) != SECTOR_SIZE) {
4807c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, READ_FAIL_MBR, device);
4817c478bd9Sstevel@tonic-gate 		if (fd == -1)
4827c478bd9Sstevel@tonic-gate 			perror("open");
4837c478bd9Sstevel@tonic-gate 		else
4847c478bd9Sstevel@tonic-gate 			perror("read");
4857c478bd9Sstevel@tonic-gate 		exit(-1);
4867c478bd9Sstevel@tonic-gate 	}
4877c478bd9Sstevel@tonic-gate 	(void) close(fd);
4887c478bd9Sstevel@tonic-gate 	device[i - 2] = save[0];
4897c478bd9Sstevel@tonic-gate 	device[i - 1] = save[1];
4907c478bd9Sstevel@tonic-gate }
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate static void
4937c478bd9Sstevel@tonic-gate write_boot_sect(char *device)
4947c478bd9Sstevel@tonic-gate {
4957c478bd9Sstevel@tonic-gate 	int fd, len;
4967c478bd9Sstevel@tonic-gate 	char *raw, *end;
4977c478bd9Sstevel@tonic-gate 	struct stat stat;
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate 	/* make a copy and chop off ":boot" */
5007c478bd9Sstevel@tonic-gate 	raw = strdup(device);
5017c478bd9Sstevel@tonic-gate 	end = strstr(raw, "p0:boot");
5027c478bd9Sstevel@tonic-gate 	if (end)
5037c478bd9Sstevel@tonic-gate 		end[2] = 0;
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate 	/* open p0 (whole disk) */
5067c478bd9Sstevel@tonic-gate 	len = strlen(raw);
5077c478bd9Sstevel@tonic-gate 	raw[len - 2] = 'p';
5087c478bd9Sstevel@tonic-gate 	raw[len - 1] = '0';
5097c478bd9Sstevel@tonic-gate 	fd = open(raw, O_WRONLY);
5107c478bd9Sstevel@tonic-gate 	if (fd == -1 || fstat(fd, &stat) != 0) {
5117c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, OPEN_FAIL, raw);
5127c478bd9Sstevel@tonic-gate 		exit(-1);
5137c478bd9Sstevel@tonic-gate 	}
5147c478bd9Sstevel@tonic-gate 	if (!nowrite &&
5157c478bd9Sstevel@tonic-gate 	    pwrite(fd, stage1_buffer, SECTOR_SIZE, 0) != SECTOR_SIZE) {
5167c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, WRITE_FAIL_BOOTSEC);
5177c478bd9Sstevel@tonic-gate 		exit(-1);
5187c478bd9Sstevel@tonic-gate 	}
5197c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, WRITE_MBOOT);
5207c478bd9Sstevel@tonic-gate 	(void) close(fd);
5217c478bd9Sstevel@tonic-gate }
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate static void
5247c478bd9Sstevel@tonic-gate modify_and_write_stage1(int dev_fd)
5257c478bd9Sstevel@tonic-gate {
5267c478bd9Sstevel@tonic-gate 	if (is_floppy) {
5277c478bd9Sstevel@tonic-gate 		stage2_first_sector = blocklist[0];
5287c478bd9Sstevel@tonic-gate 		/* copy bios parameter block (for fat fs) */
5297c478bd9Sstevel@tonic-gate 		bcopy(bpb_sect + STAGE1_BPB_OFFSET,
5307c478bd9Sstevel@tonic-gate 		    stage1_buffer + STAGE1_BPB_OFFSET, STAGE1_BPB_SIZE);
5317c478bd9Sstevel@tonic-gate 	} else if (is_bootpar) {
532d33344bbSsy25831 		stage2_first_sector = get_start_sector(dev_fd) + blocklist[0];
5337c478bd9Sstevel@tonic-gate 		/* copy bios parameter block (for fat fs) and MBR */
5347c478bd9Sstevel@tonic-gate 		bcopy(bpb_sect + STAGE1_BPB_OFFSET,
5357c478bd9Sstevel@tonic-gate 		    stage1_buffer + STAGE1_BPB_OFFSET, STAGE1_BPB_SIZE);
5367c478bd9Sstevel@tonic-gate 		bcopy(boot_sect + BOOTSZ, stage1_buffer + BOOTSZ, 512 - BOOTSZ);
5377c478bd9Sstevel@tonic-gate 		*((unsigned char *)(stage1_buffer + STAGE1_FORCE_LBA)) = 1;
5387c478bd9Sstevel@tonic-gate 	} else {
539d33344bbSsy25831 		stage2_first_sector = get_start_sector(dev_fd) + STAGE2_BLKOFF;
5407c478bd9Sstevel@tonic-gate 		/* copy MBR to stage1 in case of overwriting MBR sector */
5417c478bd9Sstevel@tonic-gate 		bcopy(boot_sect + BOOTSZ, stage1_buffer + BOOTSZ, 512 - BOOTSZ);
5427c478bd9Sstevel@tonic-gate 		*((unsigned char *)(stage1_buffer + STAGE1_FORCE_LBA)) = 1;
5437c478bd9Sstevel@tonic-gate 	}
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate 	/* modify default stage1 file generated by GRUB */
5467c478bd9Sstevel@tonic-gate 	*((ulong_t *)(stage1_buffer + STAGE1_STAGE2_SECTOR))
5477c478bd9Sstevel@tonic-gate 	    = stage2_first_sector;
5487c478bd9Sstevel@tonic-gate 	*((ushort_t *)(stage1_buffer + STAGE1_STAGE2_ADDRESS))
5497c478bd9Sstevel@tonic-gate 	    = STAGE2_MEMADDR;
5507c478bd9Sstevel@tonic-gate 	*((ushort_t *)(stage1_buffer + STAGE1_STAGE2_SEGMENT))
5517c478bd9Sstevel@tonic-gate 	    = STAGE2_MEMADDR >> 4;
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 	/*
5547c478bd9Sstevel@tonic-gate 	 * XXX the default grub distribution also:
5557c478bd9Sstevel@tonic-gate 	 * - Copy the possible MBR/extended part table
5567c478bd9Sstevel@tonic-gate 	 * - Set the boot drive of stage1
5577c478bd9Sstevel@tonic-gate 	 */
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate 	/* write stage1/pboot to 1st sector */
5607c478bd9Sstevel@tonic-gate 	if (!nowrite &&
5617c478bd9Sstevel@tonic-gate 	    pwrite(dev_fd, stage1_buffer, SECTOR_SIZE, 0) != SECTOR_SIZE) {
5627c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, WRITE_FAIL_PBOOT);
5637c478bd9Sstevel@tonic-gate 		exit(-1);
5647c478bd9Sstevel@tonic-gate 	}
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate 	if (is_floppy) {
5677c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout, WRITE_BOOTSEC_FLOPPY);
5687c478bd9Sstevel@tonic-gate 	} else {
5697c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout, WRITE_PBOOT,
570d33344bbSsy25831 		    partition, get_start_sector(dev_fd));
5717c478bd9Sstevel@tonic-gate 	}
5727c478bd9Sstevel@tonic-gate }
5737c478bd9Sstevel@tonic-gate 
5747ce76caaSEnrico Perla - Sun Microsystems static void check_extended_support(char *stage2)
5757ce76caaSEnrico Perla - Sun Microsystems {
5767ce76caaSEnrico Perla - Sun Microsystems 	char	*cmp = stage2_buffer + STAGE2_SIGN_OFFSET - 1;
5777ce76caaSEnrico Perla - Sun Microsystems 
5787ce76caaSEnrico Perla - Sun Microsystems 	if ((*cmp++ != '\xEE') && memcmp(cmp, extended_sig, HASH_SIZE) != 0) {
5797ce76caaSEnrico Perla - Sun Microsystems 		fprintf(stderr, "%s does not support extended versioning\n",
5807ce76caaSEnrico Perla - Sun Microsystems 		    stage2);
5817ce76caaSEnrico Perla - Sun Microsystems 		do_version = 0;
5827ce76caaSEnrico Perla - Sun Microsystems 	}
5837ce76caaSEnrico Perla - Sun Microsystems }
5847ce76caaSEnrico Perla - Sun Microsystems 
5857ce76caaSEnrico Perla - Sun Microsystems 
5867ce76caaSEnrico Perla - Sun Microsystems static void print_info()
5877ce76caaSEnrico Perla - Sun Microsystems {
5887ce76caaSEnrico Perla - Sun Microsystems 	int	i;
5897ce76caaSEnrico Perla - Sun Microsystems 
5907ce76caaSEnrico Perla - Sun Microsystems 	if (strip) {
5917ce76caaSEnrico Perla - Sun Microsystems 		fprintf(stdout, "%s\n", verstring);
5927ce76caaSEnrico Perla - Sun Microsystems 	} else {
5937ce76caaSEnrico Perla - Sun Microsystems 		fprintf(stdout, "Grub extended version information : %s\n",
5947ce76caaSEnrico Perla - Sun Microsystems 		    verstring);
5957ce76caaSEnrico Perla - Sun Microsystems 		fprintf(stdout, "Grub stage2 (MD5) signature : ");
5967ce76caaSEnrico Perla - Sun Microsystems 	}
5977ce76caaSEnrico Perla - Sun Microsystems 
5987ce76caaSEnrico Perla - Sun Microsystems 	for (i = 0; i < HASH_SIZE; i++)
5997ce76caaSEnrico Perla - Sun Microsystems 		fprintf(stdout, "%02x", (unsigned char)signature[i]);
6007ce76caaSEnrico Perla - Sun Microsystems 
6017ce76caaSEnrico Perla - Sun Microsystems 	fprintf(stdout, "\n");
6027ce76caaSEnrico Perla - Sun Microsystems }
6037ce76caaSEnrico Perla - Sun Microsystems 
6047ce76caaSEnrico Perla - Sun Microsystems static int
6057ce76caaSEnrico Perla - Sun Microsystems read_stage2_info(int dev_fd)
6067ce76caaSEnrico Perla - Sun Microsystems {
6077ce76caaSEnrico Perla - Sun Microsystems 	int 	ret;
6087ce76caaSEnrico Perla - Sun Microsystems 	int	first_offset, second_offset;
6097ce76caaSEnrico Perla - Sun Microsystems 	char	*sign;
6107ce76caaSEnrico Perla - Sun Microsystems 
6117ce76caaSEnrico Perla - Sun Microsystems 	if (is_floppy || is_bootpar) {
6127ce76caaSEnrico Perla - Sun Microsystems 
6137ce76caaSEnrico Perla - Sun Microsystems 		ret = pread(dev_fd, stage1_buffer, SECTOR_SIZE, 0);
6147ce76caaSEnrico Perla - Sun Microsystems 		if (ret != SECTOR_SIZE) {
6157ce76caaSEnrico Perla - Sun Microsystems 			perror("Error reading stage1 sector");
6167ce76caaSEnrico Perla - Sun Microsystems 			return (1);
6177ce76caaSEnrico Perla - Sun Microsystems 		}
6187ce76caaSEnrico Perla - Sun Microsystems 
6197ce76caaSEnrico Perla - Sun Microsystems 		first_offset = *((ulong_t *)(stage1_buffer +
6207ce76caaSEnrico Perla - Sun Microsystems 		    STAGE1_STAGE2_SECTOR));
6217ce76caaSEnrico Perla - Sun Microsystems 
6227ce76caaSEnrico Perla - Sun Microsystems 		/* Start reading in the first sector of stage 2 */
6237ce76caaSEnrico Perla - Sun Microsystems 
6247ce76caaSEnrico Perla - Sun Microsystems 		ret = pread(dev_fd, stage2_buffer, SECTOR_SIZE, first_offset *
6257ce76caaSEnrico Perla - Sun Microsystems 		    SECTOR_SIZE);
6267ce76caaSEnrico Perla - Sun Microsystems 		if (ret != SECTOR_SIZE) {
6277ce76caaSEnrico Perla - Sun Microsystems 			perror("Error reading stage2 first sector");
6287ce76caaSEnrico Perla - Sun Microsystems 			return (1);
6297ce76caaSEnrico Perla - Sun Microsystems 		}
6307ce76caaSEnrico Perla - Sun Microsystems 
6317ce76caaSEnrico Perla - Sun Microsystems 		/* From the block list section grab stage2 second sector */
6327ce76caaSEnrico Perla - Sun Microsystems 
6337ce76caaSEnrico Perla - Sun Microsystems 		second_offset = *((ulong_t *)(stage2_buffer +
6347ce76caaSEnrico Perla - Sun Microsystems 		    STAGE2_BLOCKLIST));
6357ce76caaSEnrico Perla - Sun Microsystems 
6367ce76caaSEnrico Perla - Sun Microsystems 		ret = pread(dev_fd, stage2_buffer + SECTOR_SIZE, SECTOR_SIZE,
6377ce76caaSEnrico Perla - Sun Microsystems 		    second_offset * SECTOR_SIZE);
6387ce76caaSEnrico Perla - Sun Microsystems 		if (ret != SECTOR_SIZE) {
6397ce76caaSEnrico Perla - Sun Microsystems 			perror("Error reading stage2 second sector");
6407ce76caaSEnrico Perla - Sun Microsystems 			return (1);
6417ce76caaSEnrico Perla - Sun Microsystems 		}
6427ce76caaSEnrico Perla - Sun Microsystems 	} else {
6437ce76caaSEnrico Perla - Sun Microsystems 		ret = pread(dev_fd, stage2_buffer, 2 * SECTOR_SIZE,
6447ce76caaSEnrico Perla - Sun Microsystems 		    STAGE2_BLKOFF * SECTOR_SIZE);
6457ce76caaSEnrico Perla - Sun Microsystems 		if (ret != 2 * SECTOR_SIZE) {
6467ce76caaSEnrico Perla - Sun Microsystems 			perror("Error reading stage2 sectors");
6477ce76caaSEnrico Perla - Sun Microsystems 			return (1);
6487ce76caaSEnrico Perla - Sun Microsystems 		}
6497ce76caaSEnrico Perla - Sun Microsystems 	}
6507ce76caaSEnrico Perla - Sun Microsystems 
6517ce76caaSEnrico Perla - Sun Microsystems 	sign = stage2_buffer + STAGE2_SIGN_OFFSET - 1;
6527ce76caaSEnrico Perla - Sun Microsystems 	if (*sign++ != '\xEE')
6537ce76caaSEnrico Perla - Sun Microsystems 		return (1);
6547ce76caaSEnrico Perla - Sun Microsystems 	(void) memcpy(signature, sign, HASH_SIZE);
6557ce76caaSEnrico Perla - Sun Microsystems 	sign = stage2_buffer + STAGE2_PKG_VERSION;
6567ce76caaSEnrico Perla - Sun Microsystems 	(void) strncpy(verstring, sign, VERSION_SIZE);
6577ce76caaSEnrico Perla - Sun Microsystems 	return (0);
6587ce76caaSEnrico Perla - Sun Microsystems }
6597ce76caaSEnrico Perla - Sun Microsystems 
6607ce76caaSEnrico Perla - Sun Microsystems 
6617ce76caaSEnrico Perla - Sun Microsystems static int
6627ce76caaSEnrico Perla - Sun Microsystems compute_and_write_md5hash(char *dest)
6637ce76caaSEnrico Perla - Sun Microsystems {
6647ce76caaSEnrico Perla - Sun Microsystems 	struct stat	sb;
6657ce76caaSEnrico Perla - Sun Microsystems 	char		*buffer;
6667ce76caaSEnrico Perla - Sun Microsystems 
6677ce76caaSEnrico Perla - Sun Microsystems 	if (fstat(stage2_fd, &sb) == -1)
6687ce76caaSEnrico Perla - Sun Microsystems 		return (-1);
6697ce76caaSEnrico Perla - Sun Microsystems 
6707ce76caaSEnrico Perla - Sun Microsystems 	buffer = malloc(sb.st_size);
6717ce76caaSEnrico Perla - Sun Microsystems 	if (buffer == NULL)
6727ce76caaSEnrico Perla - Sun Microsystems 		return (-1);
6737ce76caaSEnrico Perla - Sun Microsystems 
6747ce76caaSEnrico Perla - Sun Microsystems 	if (lseek(stage2_fd, 0, SEEK_SET) == -1)
6757ce76caaSEnrico Perla - Sun Microsystems 		return (-1);
6767ce76caaSEnrico Perla - Sun Microsystems 	if (read(stage2_fd, buffer, sb.st_size) < 0)
6777ce76caaSEnrico Perla - Sun Microsystems 		return (-1);
6787ce76caaSEnrico Perla - Sun Microsystems 
6797ce76caaSEnrico Perla - Sun Microsystems 	md5_calc(dest, buffer, sb.st_size);
6807ce76caaSEnrico Perla - Sun Microsystems 	free(buffer);
6817ce76caaSEnrico Perla - Sun Microsystems 	return (0);
6827ce76caaSEnrico Perla - Sun Microsystems }
6837ce76caaSEnrico Perla - Sun Microsystems 
6847ce76caaSEnrico Perla - Sun Microsystems 
6857c478bd9Sstevel@tonic-gate #define	START_BLOCK(pos)	(*(ulong_t *)(pos))
6867c478bd9Sstevel@tonic-gate #define	NUM_BLOCK(pos)		(*(ushort_t *)((pos) + 4))
6877c478bd9Sstevel@tonic-gate #define	START_SEG(pos)		(*(ushort_t *)((pos) + 6))
6887c478bd9Sstevel@tonic-gate 
6897c478bd9Sstevel@tonic-gate static void
6907c478bd9Sstevel@tonic-gate modify_and_write_stage2(int dev_fd)
6917c478bd9Sstevel@tonic-gate {
6927c478bd9Sstevel@tonic-gate 	int 	nrecord;
6937c478bd9Sstevel@tonic-gate 	off_t 	offset;
6947ce76caaSEnrico Perla - Sun Microsystems 	char	*dest;
6957ce76caaSEnrico Perla - Sun Microsystems 
6967ce76caaSEnrico Perla - Sun Microsystems 	if (do_version) {
6977ce76caaSEnrico Perla - Sun Microsystems 		dest = stage2_buffer + STAGE2_SIGN_OFFSET;
6987ce76caaSEnrico Perla - Sun Microsystems 		if (compute_and_write_md5hash(dest) < 0)
6997ce76caaSEnrico Perla - Sun Microsystems 			perror("MD5 operation");
7007ce76caaSEnrico Perla - Sun Microsystems 		dest = stage2_buffer + STAGE2_PKG_VERSION;
7017ce76caaSEnrico Perla - Sun Microsystems 		(void) strncpy(dest, verstring, VERSION_SIZE);
7027ce76caaSEnrico Perla - Sun Microsystems 	}
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 	if (is_floppy || is_bootpar) {
7057c478bd9Sstevel@tonic-gate 		int i = 0;
706aa1b14e7SSheshadri Vasudevan 		uint32_t partition_offset;
707aa1b14e7SSheshadri Vasudevan 		uint32_t install_addr = 0x8200;
7087c478bd9Sstevel@tonic-gate 		uchar_t *pos = (uchar_t *)stage2_buffer + STAGE2_BLOCKLIST;
7097c478bd9Sstevel@tonic-gate 
7107c478bd9Sstevel@tonic-gate 		stage2_first_sector = blocklist[0];
7117c478bd9Sstevel@tonic-gate 
7127c478bd9Sstevel@tonic-gate 		/* figure out the second sector */
7137c478bd9Sstevel@tonic-gate 		if (blocklist[1] > 1) {
7147c478bd9Sstevel@tonic-gate 			blocklist[0]++;
7157c478bd9Sstevel@tonic-gate 			blocklist[1]--;
7167c478bd9Sstevel@tonic-gate 		} else {
7177c478bd9Sstevel@tonic-gate 			i += 2;
7187c478bd9Sstevel@tonic-gate 		}
7197c478bd9Sstevel@tonic-gate 		stage2_second_sector = blocklist[i];
7207c478bd9Sstevel@tonic-gate 
7217c478bd9Sstevel@tonic-gate 		if (is_floppy)
7227c478bd9Sstevel@tonic-gate 			partition_offset = 0;
7237c478bd9Sstevel@tonic-gate 		else	/* solaris boot partition */
724d33344bbSsy25831 			partition_offset = get_start_sector(dev_fd);
7257c478bd9Sstevel@tonic-gate 
7267c478bd9Sstevel@tonic-gate 		/* install the blocklist at the end of stage2_buffer */
7277c478bd9Sstevel@tonic-gate 		while (blocklist[i]) {
7287c478bd9Sstevel@tonic-gate 			if (START_BLOCK(pos - 8) != 0 &&
7297c478bd9Sstevel@tonic-gate 			    START_BLOCK(pos - 8) != blocklist[i + 2]) {
7307c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, PCFS_FRAGMENTED);
7317c478bd9Sstevel@tonic-gate 				exit(-1);
7327c478bd9Sstevel@tonic-gate 			}
7337c478bd9Sstevel@tonic-gate 			START_BLOCK(pos) = blocklist[i] + partition_offset;
7347c478bd9Sstevel@tonic-gate 			START_SEG(pos) = (ushort_t)(install_addr >> 4);
7357c478bd9Sstevel@tonic-gate 			NUM_BLOCK(pos) = blocklist[i + 1];
7367c478bd9Sstevel@tonic-gate 			install_addr += blocklist[i + 1] * SECTOR_SIZE;
7377c478bd9Sstevel@tonic-gate 			pos -= 8;
7387c478bd9Sstevel@tonic-gate 			i += 2;
7397c478bd9Sstevel@tonic-gate 		}
7407c478bd9Sstevel@tonic-gate 
7417c478bd9Sstevel@tonic-gate 	} else {
7427c478bd9Sstevel@tonic-gate 		/*
7437c478bd9Sstevel@tonic-gate 		 * In a solaris partition, stage2 is written to contiguous
7447c478bd9Sstevel@tonic-gate 		 * blocks. So we update the starting block only.
7457c478bd9Sstevel@tonic-gate 		 */
7467c478bd9Sstevel@tonic-gate 		*((ulong_t *)(stage2_buffer + STAGE2_BLOCKLIST)) =
7477c478bd9Sstevel@tonic-gate 		    stage2_first_sector + 1;
7487c478bd9Sstevel@tonic-gate 	}
7497c478bd9Sstevel@tonic-gate 
7507c478bd9Sstevel@tonic-gate 	if (is_floppy) {
7517c478bd9Sstevel@tonic-gate 		/* modify the config file to add (fd0) */
7527c478bd9Sstevel@tonic-gate 		char *config_file = stage2_buffer + STAGE2_VER_STRING;
7537c478bd9Sstevel@tonic-gate 		while (*config_file++)
7547c478bd9Sstevel@tonic-gate 			;
7557c478bd9Sstevel@tonic-gate 		strcpy(config_file, "(fd0)/boot/grub/menu.lst");
7567c478bd9Sstevel@tonic-gate 	} else {
7577c478bd9Sstevel@tonic-gate 		/* force lba and set disk partition */
7587c478bd9Sstevel@tonic-gate 		*((unsigned char *) (stage2_buffer + STAGE2_FORCE_LBA)) = 1;
7597c478bd9Sstevel@tonic-gate 		*((long *)(stage2_buffer + STAGE2_INSTALLPART))
7607c478bd9Sstevel@tonic-gate 		    = (partition << 16) | (slice << 8) | 0xff;
7617c478bd9Sstevel@tonic-gate 	}
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate 	/* modification done, now do the writing */
7647c478bd9Sstevel@tonic-gate 	if (is_floppy || is_bootpar) {
7657c478bd9Sstevel@tonic-gate 		/* we rewrite block 0 and 1 and that's it */
7667c478bd9Sstevel@tonic-gate 		if (!nowrite &&
7677c478bd9Sstevel@tonic-gate 		    (pwrite(dev_fd, stage2_buffer, SECTOR_SIZE,
7687c478bd9Sstevel@tonic-gate 		    stage2_first_sector * SECTOR_SIZE) != SECTOR_SIZE ||
7697c478bd9Sstevel@tonic-gate 		    pwrite(dev_fd, stage2_buffer + SECTOR_SIZE, SECTOR_SIZE,
7707c478bd9Sstevel@tonic-gate 		    stage2_second_sector * SECTOR_SIZE) != SECTOR_SIZE)) {
7717c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, WRITE_FAIL_STAGE2);
7727c478bd9Sstevel@tonic-gate 			exit(-1);
7737c478bd9Sstevel@tonic-gate 		}
7747c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout, WRITE_STAGE2_PCFS);
7757c478bd9Sstevel@tonic-gate 		return;
7767c478bd9Sstevel@tonic-gate 	}
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate 	/* for disk, write stage2 starting at STAGE2_BLKOFF sector */
7797c478bd9Sstevel@tonic-gate 	offset = STAGE2_BLKOFF;
7807c478bd9Sstevel@tonic-gate 
7817c478bd9Sstevel@tonic-gate 	/* write the modified first two sectors */
7827c478bd9Sstevel@tonic-gate 	if (!nowrite && pwrite(dev_fd, stage2_buffer, 2 * SECTOR_SIZE,
7837c478bd9Sstevel@tonic-gate 	    offset * SECTOR_SIZE) != 2 * SECTOR_SIZE) {
7847c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, WRITE_FAIL_STAGE2);
7857c478bd9Sstevel@tonic-gate 		exit(-1);
7867c478bd9Sstevel@tonic-gate 	}
7877c478bd9Sstevel@tonic-gate 
7887c478bd9Sstevel@tonic-gate 	/* write the remaining sectors */
7897c478bd9Sstevel@tonic-gate 	nrecord = 2;
7907c478bd9Sstevel@tonic-gate 	offset += 2;
7917c478bd9Sstevel@tonic-gate 	for (;;) {
7927c478bd9Sstevel@tonic-gate 		int nread, nwrite;
7937c478bd9Sstevel@tonic-gate 		nread = pread(stage2_fd, stage2_buffer, SECTOR_SIZE,
7947c478bd9Sstevel@tonic-gate 		    nrecord * SECTOR_SIZE);
7957c478bd9Sstevel@tonic-gate 		if (nread > 0 && !nowrite)
7967c478bd9Sstevel@tonic-gate 			nwrite = pwrite(dev_fd, stage2_buffer, SECTOR_SIZE,
7977c478bd9Sstevel@tonic-gate 			    offset * SECTOR_SIZE);
7987c478bd9Sstevel@tonic-gate 		else
7997c478bd9Sstevel@tonic-gate 			nwrite = SECTOR_SIZE;
8007c478bd9Sstevel@tonic-gate 		if (nread < 0 || nwrite != SECTOR_SIZE) {
8017c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, WRITE_FAIL_STAGE2_BLOCKS,
8027c478bd9Sstevel@tonic-gate 			    nread, nwrite);
8037c478bd9Sstevel@tonic-gate 			break;
8047c478bd9Sstevel@tonic-gate 		}
805c6fe1048Sjongkis 		if (nread > 0) {
8067c478bd9Sstevel@tonic-gate 			nrecord ++;
8077c478bd9Sstevel@tonic-gate 			offset ++;
808c6fe1048Sjongkis 		}
8097c478bd9Sstevel@tonic-gate 		if (nread < SECTOR_SIZE)
8107c478bd9Sstevel@tonic-gate 			break;	/* end of file */
8117c478bd9Sstevel@tonic-gate 	}
8127c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, WRITE_STAGE2_DISK,
8137c478bd9Sstevel@tonic-gate 	    partition, nrecord, STAGE2_BLKOFF, stage2_first_sector);
8147c478bd9Sstevel@tonic-gate }
8157c478bd9Sstevel@tonic-gate 
8167c478bd9Sstevel@tonic-gate static char *
8177c478bd9Sstevel@tonic-gate get_raw_partition(char *device)
8187c478bd9Sstevel@tonic-gate {
8197c478bd9Sstevel@tonic-gate 	int len;
8207c478bd9Sstevel@tonic-gate 	struct mboot *mboot;
8217c478bd9Sstevel@tonic-gate 	static char *raw = NULL;
8227c478bd9Sstevel@tonic-gate 
8237c478bd9Sstevel@tonic-gate 	if (raw)
8247c478bd9Sstevel@tonic-gate 		return (raw);
8257c478bd9Sstevel@tonic-gate 	raw = strdup(device);
8267c478bd9Sstevel@tonic-gate 
8277c478bd9Sstevel@tonic-gate 	if (is_floppy)
8287c478bd9Sstevel@tonic-gate 		return (raw);
8297c478bd9Sstevel@tonic-gate 
8307c478bd9Sstevel@tonic-gate 	if (is_bootpar) {
8317c478bd9Sstevel@tonic-gate 		int i;
8327c478bd9Sstevel@tonic-gate 		char *end = strstr(raw, "p0:boot");
8337c478bd9Sstevel@tonic-gate 
8347c478bd9Sstevel@tonic-gate 		end[2] = 0;		/* chop off :boot */
8357c478bd9Sstevel@tonic-gate 		read_boot_sect(raw);
8367c478bd9Sstevel@tonic-gate 		mboot = (struct mboot *)boot_sect;
8377c478bd9Sstevel@tonic-gate 		for (i = 0; i < FD_NUMPART; i++) {
8387c478bd9Sstevel@tonic-gate 			struct ipart *part = (struct ipart *)mboot->parts + i;
8397c478bd9Sstevel@tonic-gate 			if (part->systid == 0xbe)	/* solaris boot part */
8407c478bd9Sstevel@tonic-gate 				break;
8417c478bd9Sstevel@tonic-gate 		}
8427c478bd9Sstevel@tonic-gate 
8437c478bd9Sstevel@tonic-gate 		if (i == FD_NUMPART) {
8447c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, BOOTPAR_NOTFOUND, device);
8457c478bd9Sstevel@tonic-gate 			exit(-1);
8467c478bd9Sstevel@tonic-gate 		}
8477c478bd9Sstevel@tonic-gate 		end[1] = '1' + i;	/* set partition name */
8487c478bd9Sstevel@tonic-gate 		return (raw);
8497c478bd9Sstevel@tonic-gate 	}
8507c478bd9Sstevel@tonic-gate 
8517c478bd9Sstevel@tonic-gate 	/* For disk, remember slice and return whole fdisk partition  */
8527c478bd9Sstevel@tonic-gate 	len = strlen(raw);
8537c478bd9Sstevel@tonic-gate 	if (raw[len - 2] != 's' || raw[len - 1] == '2') {
8547c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, NOT_ROOT_SLICE);
8557c478bd9Sstevel@tonic-gate 		exit(-1);
8567c478bd9Sstevel@tonic-gate 	}
8577c478bd9Sstevel@tonic-gate 	slice = atoi(&raw[len - 1]);
8587c478bd9Sstevel@tonic-gate 
8597c478bd9Sstevel@tonic-gate 	raw[len - 2] = 's';
8607c478bd9Sstevel@tonic-gate 	raw[len - 1] = '2';
8617c478bd9Sstevel@tonic-gate 	return (raw);
8627c478bd9Sstevel@tonic-gate }
8637c478bd9Sstevel@tonic-gate 
8647c478bd9Sstevel@tonic-gate #define	TMP_MNTPT	"/tmp/installgrub_pcfs"
8657c478bd9Sstevel@tonic-gate static void
8667c478bd9Sstevel@tonic-gate copy_stage2(int dev_fd, char *device)
8677c478bd9Sstevel@tonic-gate {
8687c478bd9Sstevel@tonic-gate 	FILE *mntfp;
8697c478bd9Sstevel@tonic-gate 	int i, pcfs_fp;
8707c478bd9Sstevel@tonic-gate 	char buf[SECTOR_SIZE];
8717c478bd9Sstevel@tonic-gate 	char *cp;
8727c478bd9Sstevel@tonic-gate 	struct mnttab mp = {0}, mpref = {0};
8737c478bd9Sstevel@tonic-gate 
8747c478bd9Sstevel@tonic-gate 	/* convert raw to block device name by removing the first 'r' */
8757c478bd9Sstevel@tonic-gate 	(void) strncpy(buf, device, sizeof (buf));
8767c478bd9Sstevel@tonic-gate 	buf[sizeof (buf) - 1] = 0;
8777c478bd9Sstevel@tonic-gate 	cp = strchr(buf, 'r');
8787c478bd9Sstevel@tonic-gate 	if (cp == NULL) {
8797c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, CONVERT_FAIL, device);
8807c478bd9Sstevel@tonic-gate 		exit(-1);
8817c478bd9Sstevel@tonic-gate 	}
8827c478bd9Sstevel@tonic-gate 	do {
8837c478bd9Sstevel@tonic-gate 		*cp = *(cp + 1);
8847c478bd9Sstevel@tonic-gate 	} while (*(++cp));
8857c478bd9Sstevel@tonic-gate 
8867c478bd9Sstevel@tonic-gate 	/* get the mount point, if any */
8877c478bd9Sstevel@tonic-gate 	mntfp = fopen("/etc/mnttab", "r");
8887c478bd9Sstevel@tonic-gate 	if (mntfp == NULL) {
8897c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, OPEN_FAIL_FILE, "/etc/mnttab");
8907c478bd9Sstevel@tonic-gate 		exit(-1);
8917c478bd9Sstevel@tonic-gate 	}
8927c478bd9Sstevel@tonic-gate 
8937c478bd9Sstevel@tonic-gate 	mpref.mnt_special = buf;
8947c478bd9Sstevel@tonic-gate 	if (getmntany(mntfp, &mp, &mpref) != 0) {
8957c478bd9Sstevel@tonic-gate 		char cmd[128];
8967c478bd9Sstevel@tonic-gate 
8977c478bd9Sstevel@tonic-gate 		/* not mounted, try remount */
8987c478bd9Sstevel@tonic-gate 		(void) mkdir(TMP_MNTPT, S_IRWXU);
8997c478bd9Sstevel@tonic-gate 		(void) snprintf(cmd, sizeof (cmd), "mount -F pcfs %s %s",
9007c478bd9Sstevel@tonic-gate 		    buf, TMP_MNTPT);
9017c478bd9Sstevel@tonic-gate 		(void) system(cmd);
9027c478bd9Sstevel@tonic-gate 		rewind(mntfp);
9037c478bd9Sstevel@tonic-gate 		bzero(&mp, sizeof (mp));
9047c478bd9Sstevel@tonic-gate 		if (getmntany(mntfp, &mp, &mpref) != 0) {
9057c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, MOUNT_FAIL, buf);
9067c478bd9Sstevel@tonic-gate 			exit(-1);
9077c478bd9Sstevel@tonic-gate 		}
9087c478bd9Sstevel@tonic-gate 	}
9097c478bd9Sstevel@tonic-gate 
9107c478bd9Sstevel@tonic-gate 	(void) snprintf(buf, sizeof (buf),
9117c478bd9Sstevel@tonic-gate 	    "%s/boot", mp.mnt_mountp);
9127c478bd9Sstevel@tonic-gate 	(void) mkdir(buf, S_IRWXU);
9137c478bd9Sstevel@tonic-gate 	(void) strcat(buf, "/grub");
9147c478bd9Sstevel@tonic-gate 	(void) mkdir(buf, S_IRWXU);
9157c478bd9Sstevel@tonic-gate 
9167c478bd9Sstevel@tonic-gate 	(void) strcat(buf, "/stage2");
9177c478bd9Sstevel@tonic-gate 	pcfs_fp = open(buf, O_WRONLY | O_CREAT, S_IRWXU);
9187c478bd9Sstevel@tonic-gate 	if (pcfs_fp == -1) {
9197c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, OPEN_FAIL_FILE, buf);
9207c478bd9Sstevel@tonic-gate 		perror("open:");
9217c478bd9Sstevel@tonic-gate 		(void) umount(TMP_MNTPT);
9227c478bd9Sstevel@tonic-gate 		exit(-1);
9237c478bd9Sstevel@tonic-gate 	}
9247c478bd9Sstevel@tonic-gate 
9257c478bd9Sstevel@tonic-gate 	/* write stage2 to pcfs */
9267c478bd9Sstevel@tonic-gate 	for (i = 0; ; i++) {
9277c478bd9Sstevel@tonic-gate 		int nread, nwrite;
9287c478bd9Sstevel@tonic-gate 		nread = pread(stage2_fd, buf, SECTOR_SIZE, i * SECTOR_SIZE);
9297c478bd9Sstevel@tonic-gate 		if (nowrite)
9307c478bd9Sstevel@tonic-gate 			nwrite = nread;
9317c478bd9Sstevel@tonic-gate 		else
9327c478bd9Sstevel@tonic-gate 			nwrite = pwrite(pcfs_fp, buf, nread, i * SECTOR_SIZE);
9337c478bd9Sstevel@tonic-gate 		if (nread < 0 || nwrite != nread) {
9347c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, WRITE_FAIL_STAGE2_BLOCKS,
9357c478bd9Sstevel@tonic-gate 			    nread, nwrite);
9367c478bd9Sstevel@tonic-gate 			break;
9377c478bd9Sstevel@tonic-gate 		}
9387c478bd9Sstevel@tonic-gate 		if (nread < SECTOR_SIZE)
9397c478bd9Sstevel@tonic-gate 			break;	/* end of file */
9407c478bd9Sstevel@tonic-gate 	}
9417c478bd9Sstevel@tonic-gate 	(void) close(pcfs_fp);
9427c478bd9Sstevel@tonic-gate 	(void) umount(TMP_MNTPT);
9437c478bd9Sstevel@tonic-gate 
9447c478bd9Sstevel@tonic-gate 	/*
9457c478bd9Sstevel@tonic-gate 	 * Now, get the blocklist from the device.
9467c478bd9Sstevel@tonic-gate 	 */
9477c478bd9Sstevel@tonic-gate 	bzero(blocklist, sizeof (blocklist));
9487c478bd9Sstevel@tonic-gate 	if (read_stage2_blocklist(dev_fd, blocklist) != 0)
9497c478bd9Sstevel@tonic-gate 		exit(-1);
9507c478bd9Sstevel@tonic-gate }
951