xref: /titanic_52/usr/src/cmd/boot/installgrub/installgrub.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <stdio.h>
30*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
31*7c478bd9Sstevel@tonic-gate #include <libgen.h>
32*7c478bd9Sstevel@tonic-gate #include <malloc.h>
33*7c478bd9Sstevel@tonic-gate #include <string.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
36*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
37*7c478bd9Sstevel@tonic-gate #include <unistd.h>
38*7c478bd9Sstevel@tonic-gate #include <strings.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/mount.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/mnttab.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/dktp/fdisk.h>
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate #include <libintl.h>
44*7c478bd9Sstevel@tonic-gate #include <locale.h>
45*7c478bd9Sstevel@tonic-gate #include "message.h"
46*7c478bd9Sstevel@tonic-gate 
47*7c478bd9Sstevel@tonic-gate #ifndef	TEXT_DOMAIN
48*7c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"SUNW_OST_OSCMD"
49*7c478bd9Sstevel@tonic-gate #endif
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate #define	SECTOR_SIZE	0x200
52*7c478bd9Sstevel@tonic-gate #define	STAGE2_MEMADDR	0x8000	/* loading addr of stage2 */
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate #define	STAGE1_BPB_OFFSET	0x3
55*7c478bd9Sstevel@tonic-gate #define	STAGE1_BPB_SIZE		0x3B
56*7c478bd9Sstevel@tonic-gate #define	STAGE1_BOOT_DRIVE	0x40
57*7c478bd9Sstevel@tonic-gate #define	STAGE1_FORCE_LBA	0x41
58*7c478bd9Sstevel@tonic-gate #define	STAGE1_STAGE2_ADDRESS	0x42
59*7c478bd9Sstevel@tonic-gate #define	STAGE1_STAGE2_SECTOR	0x44
60*7c478bd9Sstevel@tonic-gate #define	STAGE1_STAGE2_SEGMENT	0x48
61*7c478bd9Sstevel@tonic-gate 
62*7c478bd9Sstevel@tonic-gate #define	STAGE2_BLOCKLIST	(SECTOR_SIZE - 0x8)
63*7c478bd9Sstevel@tonic-gate #define	STAGE2_INSTALLPART	(SECTOR_SIZE + 0x8)
64*7c478bd9Sstevel@tonic-gate #define	STAGE2_FORCE_LBA	(SECTOR_SIZE + 0x11)
65*7c478bd9Sstevel@tonic-gate #define	STAGE2_VER_STRING	(SECTOR_SIZE + 0x12)
66*7c478bd9Sstevel@tonic-gate #define	STAGE2_BLKOFF		50	/* offset from start of fdisk part */
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate static int nowrite = 0;
69*7c478bd9Sstevel@tonic-gate static int write_mboot = 0;
70*7c478bd9Sstevel@tonic-gate static int force_mboot = 0;
71*7c478bd9Sstevel@tonic-gate static int is_floppy = 0;
72*7c478bd9Sstevel@tonic-gate static int is_bootpar = 0;
73*7c478bd9Sstevel@tonic-gate static int stage2_fd;
74*7c478bd9Sstevel@tonic-gate static int partition, slice = 0xff;
75*7c478bd9Sstevel@tonic-gate static int stage2_first_sector, stage2_second_sector;
76*7c478bd9Sstevel@tonic-gate 
77*7c478bd9Sstevel@tonic-gate 
78*7c478bd9Sstevel@tonic-gate static char bpb_sect[SECTOR_SIZE];
79*7c478bd9Sstevel@tonic-gate static char boot_sect[SECTOR_SIZE];
80*7c478bd9Sstevel@tonic-gate static char stage1_buffer[SECTOR_SIZE];
81*7c478bd9Sstevel@tonic-gate static char stage2_buffer[2 * SECTOR_SIZE];
82*7c478bd9Sstevel@tonic-gate static int blocklist[SECTOR_SIZE / sizeof (int)];
83*7c478bd9Sstevel@tonic-gate 
84*7c478bd9Sstevel@tonic-gate static int open_device(char *);
85*7c478bd9Sstevel@tonic-gate static void read_bpb_sect(int);
86*7c478bd9Sstevel@tonic-gate static void read_boot_sect(char *);
87*7c478bd9Sstevel@tonic-gate static void write_boot_sect(char *);
88*7c478bd9Sstevel@tonic-gate static void read_stage1_stage2(char *, char *);
89*7c478bd9Sstevel@tonic-gate static void modify_and_write_stage1(int);
90*7c478bd9Sstevel@tonic-gate static void modify_and_write_stage2(int);
91*7c478bd9Sstevel@tonic-gate static int get_start_sector();
92*7c478bd9Sstevel@tonic-gate static void copy_stage2(int, char *);
93*7c478bd9Sstevel@tonic-gate static char *get_raw_partition(char *);
94*7c478bd9Sstevel@tonic-gate static void usage(char *);
95*7c478bd9Sstevel@tonic-gate 
96*7c478bd9Sstevel@tonic-gate extern int read_stage2_blocklist(int, int *);
97*7c478bd9Sstevel@tonic-gate 
98*7c478bd9Sstevel@tonic-gate int
99*7c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
100*7c478bd9Sstevel@tonic-gate {
101*7c478bd9Sstevel@tonic-gate 	int dev_fd, opt;
102*7c478bd9Sstevel@tonic-gate 	char *stage1, *stage2, *device;
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
105*7c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate 	while ((opt = getopt(argc, argv, "fmn")) != EOF) {
108*7c478bd9Sstevel@tonic-gate 		switch (opt) {
109*7c478bd9Sstevel@tonic-gate 		case 'm':
110*7c478bd9Sstevel@tonic-gate 			write_mboot = 1;
111*7c478bd9Sstevel@tonic-gate 			break;
112*7c478bd9Sstevel@tonic-gate 		case 'n':
113*7c478bd9Sstevel@tonic-gate 			nowrite = 1;
114*7c478bd9Sstevel@tonic-gate 			break;
115*7c478bd9Sstevel@tonic-gate 		case 'f':
116*7c478bd9Sstevel@tonic-gate 			force_mboot = 1;
117*7c478bd9Sstevel@tonic-gate 			break;
118*7c478bd9Sstevel@tonic-gate 		default:
119*7c478bd9Sstevel@tonic-gate 			/* fall through to process non-optional args */
120*7c478bd9Sstevel@tonic-gate 			break;
121*7c478bd9Sstevel@tonic-gate 		}
122*7c478bd9Sstevel@tonic-gate 	}
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate 	/* check arguments */
125*7c478bd9Sstevel@tonic-gate 	if (argc != optind + 3) {
126*7c478bd9Sstevel@tonic-gate 		usage(argv[0]);
127*7c478bd9Sstevel@tonic-gate 	}
128*7c478bd9Sstevel@tonic-gate 
129*7c478bd9Sstevel@tonic-gate 	if (nowrite) {
130*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout, DRY_RUN);
131*7c478bd9Sstevel@tonic-gate 	}
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate 	stage1 = strdup(argv[optind]);
134*7c478bd9Sstevel@tonic-gate 	stage2 = strdup(argv[optind + 1]);
135*7c478bd9Sstevel@tonic-gate 	device = strdup(argv[optind + 2]);
136*7c478bd9Sstevel@tonic-gate 
137*7c478bd9Sstevel@tonic-gate 	if (!stage1 || !stage2 || !device) {
138*7c478bd9Sstevel@tonic-gate 		usage(argv[0]);
139*7c478bd9Sstevel@tonic-gate 	}
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate 	/* open and check device type */
142*7c478bd9Sstevel@tonic-gate 	dev_fd = open_device(device);
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate 	/* read in stage1 and stage2 into buffer */
145*7c478bd9Sstevel@tonic-gate 	read_stage1_stage2(stage1, stage2);
146*7c478bd9Sstevel@tonic-gate 
147*7c478bd9Sstevel@tonic-gate 	/* In the pcfs case, write a fresh stage2 */
148*7c478bd9Sstevel@tonic-gate 	if (is_floppy || is_bootpar) {
149*7c478bd9Sstevel@tonic-gate 		copy_stage2(dev_fd, device);
150*7c478bd9Sstevel@tonic-gate 		read_bpb_sect(dev_fd);
151*7c478bd9Sstevel@tonic-gate 	}
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 	/* read in boot sector */
154*7c478bd9Sstevel@tonic-gate 	if (!is_floppy)
155*7c478bd9Sstevel@tonic-gate 		read_boot_sect(device);
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate 	/* modify stage1 based on grub needs */
158*7c478bd9Sstevel@tonic-gate 	modify_and_write_stage1(dev_fd);
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate 	/* modify stage2 and write to media */
161*7c478bd9Sstevel@tonic-gate 	modify_and_write_stage2(dev_fd);
162*7c478bd9Sstevel@tonic-gate 
163*7c478bd9Sstevel@tonic-gate 	if (!is_floppy && write_mboot)
164*7c478bd9Sstevel@tonic-gate 		write_boot_sect(device);
165*7c478bd9Sstevel@tonic-gate 	(void) close(dev_fd);
166*7c478bd9Sstevel@tonic-gate 
167*7c478bd9Sstevel@tonic-gate 	return (0);
168*7c478bd9Sstevel@tonic-gate }
169*7c478bd9Sstevel@tonic-gate 
170*7c478bd9Sstevel@tonic-gate static int
171*7c478bd9Sstevel@tonic-gate get_start_sector()
172*7c478bd9Sstevel@tonic-gate {
173*7c478bd9Sstevel@tonic-gate 	static int start_sect = 0;
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate 	int i;
176*7c478bd9Sstevel@tonic-gate 	struct mboot *mboot;
177*7c478bd9Sstevel@tonic-gate 	struct ipart *part;
178*7c478bd9Sstevel@tonic-gate 
179*7c478bd9Sstevel@tonic-gate 	if (start_sect)
180*7c478bd9Sstevel@tonic-gate 		return (start_sect);
181*7c478bd9Sstevel@tonic-gate 
182*7c478bd9Sstevel@tonic-gate 	mboot = (struct mboot *)boot_sect;
183*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
184*7c478bd9Sstevel@tonic-gate 		part = (struct ipart *)mboot->parts + i;
185*7c478bd9Sstevel@tonic-gate 		if (is_bootpar) {
186*7c478bd9Sstevel@tonic-gate 			if (part->systid == 0xbe)
187*7c478bd9Sstevel@tonic-gate 				break;
188*7c478bd9Sstevel@tonic-gate 		} else {
189*7c478bd9Sstevel@tonic-gate 			if (part->systid == 0x82 || part->systid == 0xbf)
190*7c478bd9Sstevel@tonic-gate 				break;
191*7c478bd9Sstevel@tonic-gate 		}
192*7c478bd9Sstevel@tonic-gate 	}
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate 	if (i == FD_NUMPART) {
195*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, BOOTPAR);
196*7c478bd9Sstevel@tonic-gate 		exit(-1);
197*7c478bd9Sstevel@tonic-gate 	}
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate 	/* get confirmation for -m */
200*7c478bd9Sstevel@tonic-gate 	if (write_mboot && !force_mboot) {
201*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout, MBOOT_PROMPT);
202*7c478bd9Sstevel@tonic-gate 		if (getchar() != 'y') {
203*7c478bd9Sstevel@tonic-gate 			write_mboot = 0;
204*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stdout, MBOOT_NOT_UPDATED);
205*7c478bd9Sstevel@tonic-gate 		}
206*7c478bd9Sstevel@tonic-gate 	}
207*7c478bd9Sstevel@tonic-gate 
208*7c478bd9Sstevel@tonic-gate 	start_sect = part->relsect;
209*7c478bd9Sstevel@tonic-gate 	if (part->bootid != 128 && write_mboot == 0) {
210*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout, BOOTPAR_INACTIVE, i + 1);
211*7c478bd9Sstevel@tonic-gate 	}
212*7c478bd9Sstevel@tonic-gate 
213*7c478bd9Sstevel@tonic-gate 	partition = i;
214*7c478bd9Sstevel@tonic-gate 	return (start_sect);
215*7c478bd9Sstevel@tonic-gate }
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate static void
218*7c478bd9Sstevel@tonic-gate usage(char *progname)
219*7c478bd9Sstevel@tonic-gate {
220*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, USAGE, basename(progname));
221*7c478bd9Sstevel@tonic-gate 	exit(-1);
222*7c478bd9Sstevel@tonic-gate }
223*7c478bd9Sstevel@tonic-gate 
224*7c478bd9Sstevel@tonic-gate static int
225*7c478bd9Sstevel@tonic-gate open_device(char *device)
226*7c478bd9Sstevel@tonic-gate {
227*7c478bd9Sstevel@tonic-gate 	int dev_fd;
228*7c478bd9Sstevel@tonic-gate 	struct stat stat;
229*7c478bd9Sstevel@tonic-gate 	char *raw_part;
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate 	is_floppy = strncmp(device, "/dev/rdsk", strlen("/dev/rdsk")) &&
232*7c478bd9Sstevel@tonic-gate 	    strncmp(device, "/dev/dsk", strlen("/dev/dsk"));
233*7c478bd9Sstevel@tonic-gate 
234*7c478bd9Sstevel@tonic-gate 	/* handle boot partition specification */
235*7c478bd9Sstevel@tonic-gate 	if (!is_floppy && strstr(device, "p0:boot")) {
236*7c478bd9Sstevel@tonic-gate 		is_bootpar = 1;
237*7c478bd9Sstevel@tonic-gate 	}
238*7c478bd9Sstevel@tonic-gate 
239*7c478bd9Sstevel@tonic-gate 	raw_part = get_raw_partition(device);
240*7c478bd9Sstevel@tonic-gate 
241*7c478bd9Sstevel@tonic-gate 	if (nowrite)
242*7c478bd9Sstevel@tonic-gate 		dev_fd = open(raw_part, O_RDONLY);
243*7c478bd9Sstevel@tonic-gate 	else
244*7c478bd9Sstevel@tonic-gate 		dev_fd = open(raw_part, O_RDWR);
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate 	if (dev_fd == -1 || fstat(dev_fd, &stat) != 0) {
247*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, OPEN_FAIL, raw_part);
248*7c478bd9Sstevel@tonic-gate 		exit(-1);
249*7c478bd9Sstevel@tonic-gate 	}
250*7c478bd9Sstevel@tonic-gate 	if (S_ISCHR(stat.st_mode) == 0) {
251*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, NOT_RAW_DEVICE, raw_part);
252*7c478bd9Sstevel@tonic-gate 		exit(-1);
253*7c478bd9Sstevel@tonic-gate 	}
254*7c478bd9Sstevel@tonic-gate 
255*7c478bd9Sstevel@tonic-gate 	return (dev_fd);
256*7c478bd9Sstevel@tonic-gate }
257*7c478bd9Sstevel@tonic-gate 
258*7c478bd9Sstevel@tonic-gate static void
259*7c478bd9Sstevel@tonic-gate read_stage1_stage2(char *stage1, char *stage2)
260*7c478bd9Sstevel@tonic-gate {
261*7c478bd9Sstevel@tonic-gate 	int fd;
262*7c478bd9Sstevel@tonic-gate 
263*7c478bd9Sstevel@tonic-gate 	/* read the stage1 file from filesystem */
264*7c478bd9Sstevel@tonic-gate 	fd = open(stage1, O_RDONLY);
265*7c478bd9Sstevel@tonic-gate 	if (fd == -1 || read(fd, stage1_buffer, SECTOR_SIZE) != SECTOR_SIZE) {
266*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, READ_FAIL_STAGE1, stage1);
267*7c478bd9Sstevel@tonic-gate 		exit(-1);
268*7c478bd9Sstevel@tonic-gate 	}
269*7c478bd9Sstevel@tonic-gate 	(void) close(fd);
270*7c478bd9Sstevel@tonic-gate 
271*7c478bd9Sstevel@tonic-gate 	/* read first two blocks of stage 2 from filesystem */
272*7c478bd9Sstevel@tonic-gate 	stage2_fd = open(stage2, O_RDONLY);
273*7c478bd9Sstevel@tonic-gate 	if (stage2_fd == -1 ||
274*7c478bd9Sstevel@tonic-gate 	    read(stage2_fd, stage2_buffer, 2 * SECTOR_SIZE)
275*7c478bd9Sstevel@tonic-gate 	    != 2 * SECTOR_SIZE) {
276*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, READ_FAIL_STAGE2, stage2);
277*7c478bd9Sstevel@tonic-gate 		exit(-1);
278*7c478bd9Sstevel@tonic-gate 	}
279*7c478bd9Sstevel@tonic-gate 	/* leave the stage2 file open for later */
280*7c478bd9Sstevel@tonic-gate }
281*7c478bd9Sstevel@tonic-gate 
282*7c478bd9Sstevel@tonic-gate static void
283*7c478bd9Sstevel@tonic-gate read_bpb_sect(int dev_fd)
284*7c478bd9Sstevel@tonic-gate {
285*7c478bd9Sstevel@tonic-gate 	if (pread(dev_fd, bpb_sect, SECTOR_SIZE, 0) != SECTOR_SIZE) {
286*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, READ_FAIL_BPB);
287*7c478bd9Sstevel@tonic-gate 		exit(-1);
288*7c478bd9Sstevel@tonic-gate 	}
289*7c478bd9Sstevel@tonic-gate }
290*7c478bd9Sstevel@tonic-gate 
291*7c478bd9Sstevel@tonic-gate static void
292*7c478bd9Sstevel@tonic-gate read_boot_sect(char *device)
293*7c478bd9Sstevel@tonic-gate {
294*7c478bd9Sstevel@tonic-gate 	static int read_mbr = 0;
295*7c478bd9Sstevel@tonic-gate 	int i, fd;
296*7c478bd9Sstevel@tonic-gate 	char save[2];
297*7c478bd9Sstevel@tonic-gate 
298*7c478bd9Sstevel@tonic-gate 	if (read_mbr)
299*7c478bd9Sstevel@tonic-gate 		return;
300*7c478bd9Sstevel@tonic-gate 	read_mbr = 1;
301*7c478bd9Sstevel@tonic-gate 
302*7c478bd9Sstevel@tonic-gate 	/* get the whole disk (p0) */
303*7c478bd9Sstevel@tonic-gate 	i = strlen(device);
304*7c478bd9Sstevel@tonic-gate 	save[0] = device[i - 2];
305*7c478bd9Sstevel@tonic-gate 	save[1] = device[i - 1];
306*7c478bd9Sstevel@tonic-gate 	device[i - 2] = 'p';
307*7c478bd9Sstevel@tonic-gate 	device[i - 1] = '0';
308*7c478bd9Sstevel@tonic-gate 
309*7c478bd9Sstevel@tonic-gate 	fd = open(device, O_RDONLY);
310*7c478bd9Sstevel@tonic-gate 	if (fd == -1 || read(fd, boot_sect, SECTOR_SIZE) != SECTOR_SIZE) {
311*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, READ_FAIL_MBR, device);
312*7c478bd9Sstevel@tonic-gate 		if (fd == -1)
313*7c478bd9Sstevel@tonic-gate 			perror("open");
314*7c478bd9Sstevel@tonic-gate 		else
315*7c478bd9Sstevel@tonic-gate 			perror("read");
316*7c478bd9Sstevel@tonic-gate 		exit(-1);
317*7c478bd9Sstevel@tonic-gate 	}
318*7c478bd9Sstevel@tonic-gate 	(void) close(fd);
319*7c478bd9Sstevel@tonic-gate 	device[i - 2] = save[0];
320*7c478bd9Sstevel@tonic-gate 	device[i - 1] = save[1];
321*7c478bd9Sstevel@tonic-gate }
322*7c478bd9Sstevel@tonic-gate 
323*7c478bd9Sstevel@tonic-gate static void
324*7c478bd9Sstevel@tonic-gate write_boot_sect(char *device)
325*7c478bd9Sstevel@tonic-gate {
326*7c478bd9Sstevel@tonic-gate 	int fd, len;
327*7c478bd9Sstevel@tonic-gate 	char *raw, *end;
328*7c478bd9Sstevel@tonic-gate 	struct stat stat;
329*7c478bd9Sstevel@tonic-gate 
330*7c478bd9Sstevel@tonic-gate 	/* make a copy and chop off ":boot" */
331*7c478bd9Sstevel@tonic-gate 	raw = strdup(device);
332*7c478bd9Sstevel@tonic-gate 	end = strstr(raw, "p0:boot");
333*7c478bd9Sstevel@tonic-gate 	if (end)
334*7c478bd9Sstevel@tonic-gate 		end[2] = 0;
335*7c478bd9Sstevel@tonic-gate 
336*7c478bd9Sstevel@tonic-gate 	/* open p0 (whole disk) */
337*7c478bd9Sstevel@tonic-gate 	len = strlen(raw);
338*7c478bd9Sstevel@tonic-gate 	raw[len - 2] = 'p';
339*7c478bd9Sstevel@tonic-gate 	raw[len - 1] = '0';
340*7c478bd9Sstevel@tonic-gate 	fd = open(raw, O_WRONLY);
341*7c478bd9Sstevel@tonic-gate 	if (fd == -1 || fstat(fd, &stat) != 0) {
342*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, OPEN_FAIL, raw);
343*7c478bd9Sstevel@tonic-gate 		exit(-1);
344*7c478bd9Sstevel@tonic-gate 	}
345*7c478bd9Sstevel@tonic-gate 	if (!nowrite &&
346*7c478bd9Sstevel@tonic-gate 	    pwrite(fd, stage1_buffer, SECTOR_SIZE, 0) != SECTOR_SIZE) {
347*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, WRITE_FAIL_BOOTSEC);
348*7c478bd9Sstevel@tonic-gate 		exit(-1);
349*7c478bd9Sstevel@tonic-gate 	}
350*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, WRITE_MBOOT);
351*7c478bd9Sstevel@tonic-gate 	(void) close(fd);
352*7c478bd9Sstevel@tonic-gate }
353*7c478bd9Sstevel@tonic-gate 
354*7c478bd9Sstevel@tonic-gate static void
355*7c478bd9Sstevel@tonic-gate modify_and_write_stage1(int dev_fd)
356*7c478bd9Sstevel@tonic-gate {
357*7c478bd9Sstevel@tonic-gate 	if (is_floppy) {
358*7c478bd9Sstevel@tonic-gate 		stage2_first_sector = blocklist[0];
359*7c478bd9Sstevel@tonic-gate 		/* copy bios parameter block (for fat fs) */
360*7c478bd9Sstevel@tonic-gate 		bcopy(bpb_sect + STAGE1_BPB_OFFSET,
361*7c478bd9Sstevel@tonic-gate 		    stage1_buffer + STAGE1_BPB_OFFSET, STAGE1_BPB_SIZE);
362*7c478bd9Sstevel@tonic-gate 	} else if (is_bootpar) {
363*7c478bd9Sstevel@tonic-gate 		stage2_first_sector = get_start_sector() + blocklist[0];
364*7c478bd9Sstevel@tonic-gate 		/* copy bios parameter block (for fat fs) and MBR */
365*7c478bd9Sstevel@tonic-gate 		bcopy(bpb_sect + STAGE1_BPB_OFFSET,
366*7c478bd9Sstevel@tonic-gate 		    stage1_buffer + STAGE1_BPB_OFFSET, STAGE1_BPB_SIZE);
367*7c478bd9Sstevel@tonic-gate 		bcopy(boot_sect + BOOTSZ, stage1_buffer + BOOTSZ, 512 - BOOTSZ);
368*7c478bd9Sstevel@tonic-gate 		*((unsigned char *)(stage1_buffer + STAGE1_FORCE_LBA)) = 1;
369*7c478bd9Sstevel@tonic-gate 	} else {
370*7c478bd9Sstevel@tonic-gate 		stage2_first_sector = get_start_sector() + STAGE2_BLKOFF;
371*7c478bd9Sstevel@tonic-gate 		/* copy MBR to stage1 in case of overwriting MBR sector */
372*7c478bd9Sstevel@tonic-gate 		bcopy(boot_sect + BOOTSZ, stage1_buffer + BOOTSZ, 512 - BOOTSZ);
373*7c478bd9Sstevel@tonic-gate 		*((unsigned char *)(stage1_buffer + STAGE1_FORCE_LBA)) = 1;
374*7c478bd9Sstevel@tonic-gate 	}
375*7c478bd9Sstevel@tonic-gate 
376*7c478bd9Sstevel@tonic-gate 	/* modify default stage1 file generated by GRUB */
377*7c478bd9Sstevel@tonic-gate 	*((ulong_t *)(stage1_buffer + STAGE1_STAGE2_SECTOR))
378*7c478bd9Sstevel@tonic-gate 		= stage2_first_sector;
379*7c478bd9Sstevel@tonic-gate 	*((ushort_t *)(stage1_buffer + STAGE1_STAGE2_ADDRESS))
380*7c478bd9Sstevel@tonic-gate 		= STAGE2_MEMADDR;
381*7c478bd9Sstevel@tonic-gate 	*((ushort_t *)(stage1_buffer + STAGE1_STAGE2_SEGMENT))
382*7c478bd9Sstevel@tonic-gate 		= STAGE2_MEMADDR >> 4;
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate 	/*
385*7c478bd9Sstevel@tonic-gate 	 * XXX the default grub distribution also:
386*7c478bd9Sstevel@tonic-gate 	 * - Copy the possible MBR/extended part table
387*7c478bd9Sstevel@tonic-gate 	 * - Set the boot drive of stage1
388*7c478bd9Sstevel@tonic-gate 	 */
389*7c478bd9Sstevel@tonic-gate 
390*7c478bd9Sstevel@tonic-gate 	/* write stage1/pboot to 1st sector */
391*7c478bd9Sstevel@tonic-gate 	if (!nowrite &&
392*7c478bd9Sstevel@tonic-gate 	    pwrite(dev_fd, stage1_buffer, SECTOR_SIZE, 0) != SECTOR_SIZE) {
393*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, WRITE_FAIL_PBOOT);
394*7c478bd9Sstevel@tonic-gate 		exit(-1);
395*7c478bd9Sstevel@tonic-gate 	}
396*7c478bd9Sstevel@tonic-gate 
397*7c478bd9Sstevel@tonic-gate 	if (is_floppy) {
398*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout, WRITE_BOOTSEC_FLOPPY);
399*7c478bd9Sstevel@tonic-gate 	} else {
400*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout, WRITE_PBOOT,
401*7c478bd9Sstevel@tonic-gate 		    partition, get_start_sector());
402*7c478bd9Sstevel@tonic-gate 	}
403*7c478bd9Sstevel@tonic-gate }
404*7c478bd9Sstevel@tonic-gate 
405*7c478bd9Sstevel@tonic-gate #define	START_BLOCK(pos)	(*(ulong_t *)(pos))
406*7c478bd9Sstevel@tonic-gate #define	NUM_BLOCK(pos)		(*(ushort_t *)((pos) + 4))
407*7c478bd9Sstevel@tonic-gate #define	START_SEG(pos)		(*(ushort_t *)((pos) + 6))
408*7c478bd9Sstevel@tonic-gate 
409*7c478bd9Sstevel@tonic-gate static void
410*7c478bd9Sstevel@tonic-gate modify_and_write_stage2(int dev_fd)
411*7c478bd9Sstevel@tonic-gate {
412*7c478bd9Sstevel@tonic-gate 	int nrecord;
413*7c478bd9Sstevel@tonic-gate 	off_t offset;
414*7c478bd9Sstevel@tonic-gate 
415*7c478bd9Sstevel@tonic-gate 	if (is_floppy || is_bootpar) {
416*7c478bd9Sstevel@tonic-gate 		int i = 0;
417*7c478bd9Sstevel@tonic-gate 		uint_t partition_offset;
418*7c478bd9Sstevel@tonic-gate 		uint_t install_addr = 0x8200;
419*7c478bd9Sstevel@tonic-gate 		uchar_t *pos = (uchar_t *)stage2_buffer + STAGE2_BLOCKLIST;
420*7c478bd9Sstevel@tonic-gate 
421*7c478bd9Sstevel@tonic-gate 		stage2_first_sector = blocklist[0];
422*7c478bd9Sstevel@tonic-gate 
423*7c478bd9Sstevel@tonic-gate 		/* figure out the second sector */
424*7c478bd9Sstevel@tonic-gate 		if (blocklist[1] > 1) {
425*7c478bd9Sstevel@tonic-gate 			blocklist[0]++;
426*7c478bd9Sstevel@tonic-gate 			blocklist[1]--;
427*7c478bd9Sstevel@tonic-gate 		} else {
428*7c478bd9Sstevel@tonic-gate 			i += 2;
429*7c478bd9Sstevel@tonic-gate 		}
430*7c478bd9Sstevel@tonic-gate 		stage2_second_sector = blocklist[i];
431*7c478bd9Sstevel@tonic-gate 
432*7c478bd9Sstevel@tonic-gate 		if (is_floppy)
433*7c478bd9Sstevel@tonic-gate 			partition_offset = 0;
434*7c478bd9Sstevel@tonic-gate 		else	/* solaris boot partition */
435*7c478bd9Sstevel@tonic-gate 			partition_offset = get_start_sector();
436*7c478bd9Sstevel@tonic-gate 
437*7c478bd9Sstevel@tonic-gate 		/* install the blocklist at the end of stage2_buffer */
438*7c478bd9Sstevel@tonic-gate 		while (blocklist[i]) {
439*7c478bd9Sstevel@tonic-gate 			if (START_BLOCK(pos - 8) != 0 &&
440*7c478bd9Sstevel@tonic-gate 			    START_BLOCK(pos - 8) != blocklist[i + 2]) {
441*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, PCFS_FRAGMENTED);
442*7c478bd9Sstevel@tonic-gate 				exit(-1);
443*7c478bd9Sstevel@tonic-gate 			}
444*7c478bd9Sstevel@tonic-gate 			START_BLOCK(pos) = blocklist[i] + partition_offset;
445*7c478bd9Sstevel@tonic-gate 			START_SEG(pos) = (ushort_t)(install_addr >> 4);
446*7c478bd9Sstevel@tonic-gate 			NUM_BLOCK(pos) = blocklist[i + 1];
447*7c478bd9Sstevel@tonic-gate 			install_addr += blocklist[i + 1] * SECTOR_SIZE;
448*7c478bd9Sstevel@tonic-gate 			pos -= 8;
449*7c478bd9Sstevel@tonic-gate 			i += 2;
450*7c478bd9Sstevel@tonic-gate 		}
451*7c478bd9Sstevel@tonic-gate 
452*7c478bd9Sstevel@tonic-gate 	} else {
453*7c478bd9Sstevel@tonic-gate 		/*
454*7c478bd9Sstevel@tonic-gate 		 * In a solaris partition, stage2 is written to contiguous
455*7c478bd9Sstevel@tonic-gate 		 * blocks. So we update the starting block only.
456*7c478bd9Sstevel@tonic-gate 		 */
457*7c478bd9Sstevel@tonic-gate 		*((ulong_t *)(stage2_buffer + STAGE2_BLOCKLIST)) =
458*7c478bd9Sstevel@tonic-gate 		    stage2_first_sector + 1;
459*7c478bd9Sstevel@tonic-gate 	}
460*7c478bd9Sstevel@tonic-gate 
461*7c478bd9Sstevel@tonic-gate 	if (is_floppy) {
462*7c478bd9Sstevel@tonic-gate 		/* modify the config file to add (fd0) */
463*7c478bd9Sstevel@tonic-gate 		char *config_file = stage2_buffer + STAGE2_VER_STRING;
464*7c478bd9Sstevel@tonic-gate 		while (*config_file++)
465*7c478bd9Sstevel@tonic-gate 			;
466*7c478bd9Sstevel@tonic-gate 		strcpy(config_file, "(fd0)/boot/grub/menu.lst");
467*7c478bd9Sstevel@tonic-gate 	} else {
468*7c478bd9Sstevel@tonic-gate 		/* force lba and set disk partition */
469*7c478bd9Sstevel@tonic-gate 		*((unsigned char *) (stage2_buffer + STAGE2_FORCE_LBA)) = 1;
470*7c478bd9Sstevel@tonic-gate 		*((long *)(stage2_buffer + STAGE2_INSTALLPART))
471*7c478bd9Sstevel@tonic-gate 		    = (partition << 16) | (slice << 8) | 0xff;
472*7c478bd9Sstevel@tonic-gate 	}
473*7c478bd9Sstevel@tonic-gate 
474*7c478bd9Sstevel@tonic-gate 	/* modification done, now do the writing */
475*7c478bd9Sstevel@tonic-gate 	if (is_floppy || is_bootpar) {
476*7c478bd9Sstevel@tonic-gate 		/* we rewrite block 0 and 1 and that's it */
477*7c478bd9Sstevel@tonic-gate 		if (!nowrite &&
478*7c478bd9Sstevel@tonic-gate 		    (pwrite(dev_fd, stage2_buffer, SECTOR_SIZE,
479*7c478bd9Sstevel@tonic-gate 		    stage2_first_sector * SECTOR_SIZE) != SECTOR_SIZE ||
480*7c478bd9Sstevel@tonic-gate 		    pwrite(dev_fd, stage2_buffer + SECTOR_SIZE, SECTOR_SIZE,
481*7c478bd9Sstevel@tonic-gate 		    stage2_second_sector * SECTOR_SIZE) != SECTOR_SIZE)) {
482*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, WRITE_FAIL_STAGE2);
483*7c478bd9Sstevel@tonic-gate 			exit(-1);
484*7c478bd9Sstevel@tonic-gate 		}
485*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout, WRITE_STAGE2_PCFS);
486*7c478bd9Sstevel@tonic-gate 		return;
487*7c478bd9Sstevel@tonic-gate 	}
488*7c478bd9Sstevel@tonic-gate 
489*7c478bd9Sstevel@tonic-gate 	/* for disk, write stage2 starting at STAGE2_BLKOFF sector */
490*7c478bd9Sstevel@tonic-gate 	offset = STAGE2_BLKOFF;
491*7c478bd9Sstevel@tonic-gate 
492*7c478bd9Sstevel@tonic-gate 	/* write the modified first two sectors */
493*7c478bd9Sstevel@tonic-gate 	if (!nowrite && pwrite(dev_fd, stage2_buffer, 2 * SECTOR_SIZE,
494*7c478bd9Sstevel@tonic-gate 	    offset * SECTOR_SIZE) != 2 * SECTOR_SIZE) {
495*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, WRITE_FAIL_STAGE2);
496*7c478bd9Sstevel@tonic-gate 		exit(-1);
497*7c478bd9Sstevel@tonic-gate 	}
498*7c478bd9Sstevel@tonic-gate 
499*7c478bd9Sstevel@tonic-gate 	/* write the remaining sectors */
500*7c478bd9Sstevel@tonic-gate 	nrecord = 2;
501*7c478bd9Sstevel@tonic-gate 	offset += 2;
502*7c478bd9Sstevel@tonic-gate 	for (;;) {
503*7c478bd9Sstevel@tonic-gate 		int nread, nwrite;
504*7c478bd9Sstevel@tonic-gate 		nread = pread(stage2_fd, stage2_buffer, SECTOR_SIZE,
505*7c478bd9Sstevel@tonic-gate 		    nrecord * SECTOR_SIZE);
506*7c478bd9Sstevel@tonic-gate 		if (nread > 0 && !nowrite)
507*7c478bd9Sstevel@tonic-gate 			nwrite = pwrite(dev_fd, stage2_buffer, SECTOR_SIZE,
508*7c478bd9Sstevel@tonic-gate 			    offset * SECTOR_SIZE);
509*7c478bd9Sstevel@tonic-gate 		else
510*7c478bd9Sstevel@tonic-gate 			nwrite = SECTOR_SIZE;
511*7c478bd9Sstevel@tonic-gate 		if (nread < 0 || nwrite != SECTOR_SIZE) {
512*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, WRITE_FAIL_STAGE2_BLOCKS,
513*7c478bd9Sstevel@tonic-gate 			    nread, nwrite);
514*7c478bd9Sstevel@tonic-gate 			break;
515*7c478bd9Sstevel@tonic-gate 		}
516*7c478bd9Sstevel@tonic-gate 		nrecord ++;
517*7c478bd9Sstevel@tonic-gate 		offset ++;
518*7c478bd9Sstevel@tonic-gate 		if (nread < SECTOR_SIZE)
519*7c478bd9Sstevel@tonic-gate 			break;	/* end of file */
520*7c478bd9Sstevel@tonic-gate 	}
521*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, WRITE_STAGE2_DISK,
522*7c478bd9Sstevel@tonic-gate 	    partition, nrecord, STAGE2_BLKOFF, stage2_first_sector);
523*7c478bd9Sstevel@tonic-gate }
524*7c478bd9Sstevel@tonic-gate 
525*7c478bd9Sstevel@tonic-gate static char *
526*7c478bd9Sstevel@tonic-gate get_raw_partition(char *device)
527*7c478bd9Sstevel@tonic-gate {
528*7c478bd9Sstevel@tonic-gate 	int len;
529*7c478bd9Sstevel@tonic-gate 	struct mboot *mboot;
530*7c478bd9Sstevel@tonic-gate 	static char *raw = NULL;
531*7c478bd9Sstevel@tonic-gate 
532*7c478bd9Sstevel@tonic-gate 	if (raw)
533*7c478bd9Sstevel@tonic-gate 		return (raw);
534*7c478bd9Sstevel@tonic-gate 	raw = strdup(device);
535*7c478bd9Sstevel@tonic-gate 
536*7c478bd9Sstevel@tonic-gate 	if (is_floppy)
537*7c478bd9Sstevel@tonic-gate 		return (raw);
538*7c478bd9Sstevel@tonic-gate 
539*7c478bd9Sstevel@tonic-gate 	if (is_bootpar) {
540*7c478bd9Sstevel@tonic-gate 		int i;
541*7c478bd9Sstevel@tonic-gate 		char *end = strstr(raw, "p0:boot");
542*7c478bd9Sstevel@tonic-gate 
543*7c478bd9Sstevel@tonic-gate 		end[2] = 0;		/* chop off :boot */
544*7c478bd9Sstevel@tonic-gate 		read_boot_sect(raw);
545*7c478bd9Sstevel@tonic-gate 		mboot = (struct mboot *)boot_sect;
546*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < FD_NUMPART; i++) {
547*7c478bd9Sstevel@tonic-gate 			struct ipart *part = (struct ipart *)mboot->parts + i;
548*7c478bd9Sstevel@tonic-gate 			if (part->systid == 0xbe)	/* solaris boot part */
549*7c478bd9Sstevel@tonic-gate 				break;
550*7c478bd9Sstevel@tonic-gate 		}
551*7c478bd9Sstevel@tonic-gate 
552*7c478bd9Sstevel@tonic-gate 		if (i == FD_NUMPART) {
553*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, BOOTPAR_NOTFOUND, device);
554*7c478bd9Sstevel@tonic-gate 			exit(-1);
555*7c478bd9Sstevel@tonic-gate 		}
556*7c478bd9Sstevel@tonic-gate 		end[1] = '1' + i;	/* set partition name */
557*7c478bd9Sstevel@tonic-gate 		return (raw);
558*7c478bd9Sstevel@tonic-gate 	}
559*7c478bd9Sstevel@tonic-gate 
560*7c478bd9Sstevel@tonic-gate 	/* For disk, remember slice and return whole fdisk partition  */
561*7c478bd9Sstevel@tonic-gate 	len = strlen(raw);
562*7c478bd9Sstevel@tonic-gate 	if (raw[len - 2] != 's' || raw[len - 1] == '2') {
563*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, NOT_ROOT_SLICE);
564*7c478bd9Sstevel@tonic-gate 		exit(-1);
565*7c478bd9Sstevel@tonic-gate 	}
566*7c478bd9Sstevel@tonic-gate 	slice = atoi(&raw[len - 1]);
567*7c478bd9Sstevel@tonic-gate 
568*7c478bd9Sstevel@tonic-gate 	raw[len - 2] = 's';
569*7c478bd9Sstevel@tonic-gate 	raw[len - 1] = '2';
570*7c478bd9Sstevel@tonic-gate 	return (raw);
571*7c478bd9Sstevel@tonic-gate }
572*7c478bd9Sstevel@tonic-gate 
573*7c478bd9Sstevel@tonic-gate #define	TMP_MNTPT	"/tmp/installgrub_pcfs"
574*7c478bd9Sstevel@tonic-gate static void
575*7c478bd9Sstevel@tonic-gate copy_stage2(int dev_fd, char *device)
576*7c478bd9Sstevel@tonic-gate {
577*7c478bd9Sstevel@tonic-gate 	FILE *mntfp;
578*7c478bd9Sstevel@tonic-gate 	int i, pcfs_fp;
579*7c478bd9Sstevel@tonic-gate 	char buf[SECTOR_SIZE];
580*7c478bd9Sstevel@tonic-gate 	char *cp;
581*7c478bd9Sstevel@tonic-gate 	struct mnttab mp = {0}, mpref = {0};
582*7c478bd9Sstevel@tonic-gate 
583*7c478bd9Sstevel@tonic-gate 	/* convert raw to block device name by removing the first 'r' */
584*7c478bd9Sstevel@tonic-gate 	(void) strncpy(buf, device, sizeof (buf));
585*7c478bd9Sstevel@tonic-gate 	buf[sizeof (buf) - 1] = 0;
586*7c478bd9Sstevel@tonic-gate 	cp = strchr(buf, 'r');
587*7c478bd9Sstevel@tonic-gate 	if (cp == NULL) {
588*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, CONVERT_FAIL, device);
589*7c478bd9Sstevel@tonic-gate 		exit(-1);
590*7c478bd9Sstevel@tonic-gate 	}
591*7c478bd9Sstevel@tonic-gate 	do {
592*7c478bd9Sstevel@tonic-gate 		*cp = *(cp + 1);
593*7c478bd9Sstevel@tonic-gate 	} while (*(++cp));
594*7c478bd9Sstevel@tonic-gate 
595*7c478bd9Sstevel@tonic-gate 	/* get the mount point, if any */
596*7c478bd9Sstevel@tonic-gate 	mntfp = fopen("/etc/mnttab", "r");
597*7c478bd9Sstevel@tonic-gate 	if (mntfp == NULL) {
598*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, OPEN_FAIL_FILE, "/etc/mnttab");
599*7c478bd9Sstevel@tonic-gate 		exit(-1);
600*7c478bd9Sstevel@tonic-gate 	}
601*7c478bd9Sstevel@tonic-gate 
602*7c478bd9Sstevel@tonic-gate 	mpref.mnt_special = buf;
603*7c478bd9Sstevel@tonic-gate 	if (getmntany(mntfp, &mp, &mpref) != 0) {
604*7c478bd9Sstevel@tonic-gate 		char cmd[128];
605*7c478bd9Sstevel@tonic-gate 
606*7c478bd9Sstevel@tonic-gate 		/* not mounted, try remount */
607*7c478bd9Sstevel@tonic-gate 		(void) mkdir(TMP_MNTPT, S_IRWXU);
608*7c478bd9Sstevel@tonic-gate 		(void) snprintf(cmd, sizeof (cmd), "mount -F pcfs %s %s",
609*7c478bd9Sstevel@tonic-gate 		    buf, TMP_MNTPT);
610*7c478bd9Sstevel@tonic-gate 		(void) system(cmd);
611*7c478bd9Sstevel@tonic-gate 		rewind(mntfp);
612*7c478bd9Sstevel@tonic-gate 		bzero(&mp, sizeof (mp));
613*7c478bd9Sstevel@tonic-gate 		if (getmntany(mntfp, &mp, &mpref) != 0) {
614*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, MOUNT_FAIL, buf);
615*7c478bd9Sstevel@tonic-gate 			exit(-1);
616*7c478bd9Sstevel@tonic-gate 		}
617*7c478bd9Sstevel@tonic-gate 	}
618*7c478bd9Sstevel@tonic-gate 
619*7c478bd9Sstevel@tonic-gate 	(void) snprintf(buf, sizeof (buf),
620*7c478bd9Sstevel@tonic-gate 	    "%s/boot", mp.mnt_mountp);
621*7c478bd9Sstevel@tonic-gate 	(void) mkdir(buf, S_IRWXU);
622*7c478bd9Sstevel@tonic-gate 	(void) strcat(buf, "/grub");
623*7c478bd9Sstevel@tonic-gate 	(void) mkdir(buf, S_IRWXU);
624*7c478bd9Sstevel@tonic-gate 
625*7c478bd9Sstevel@tonic-gate 	(void) strcat(buf, "/stage2");
626*7c478bd9Sstevel@tonic-gate 	pcfs_fp = open(buf, O_WRONLY | O_CREAT, S_IRWXU);
627*7c478bd9Sstevel@tonic-gate 	if (pcfs_fp == -1) {
628*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, OPEN_FAIL_FILE, buf);
629*7c478bd9Sstevel@tonic-gate 		perror("open:");
630*7c478bd9Sstevel@tonic-gate 		(void) umount(TMP_MNTPT);
631*7c478bd9Sstevel@tonic-gate 		exit(-1);
632*7c478bd9Sstevel@tonic-gate 	}
633*7c478bd9Sstevel@tonic-gate 
634*7c478bd9Sstevel@tonic-gate 	/* write stage2 to pcfs */
635*7c478bd9Sstevel@tonic-gate 	for (i = 0; ; i++) {
636*7c478bd9Sstevel@tonic-gate 		int nread, nwrite;
637*7c478bd9Sstevel@tonic-gate 		nread = pread(stage2_fd, buf, SECTOR_SIZE, i * SECTOR_SIZE);
638*7c478bd9Sstevel@tonic-gate 		if (nowrite)
639*7c478bd9Sstevel@tonic-gate 			nwrite = nread;
640*7c478bd9Sstevel@tonic-gate 		else
641*7c478bd9Sstevel@tonic-gate 			nwrite = pwrite(pcfs_fp, buf, nread, i * SECTOR_SIZE);
642*7c478bd9Sstevel@tonic-gate 		if (nread < 0 || nwrite != nread) {
643*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, WRITE_FAIL_STAGE2_BLOCKS,
644*7c478bd9Sstevel@tonic-gate 			    nread, nwrite);
645*7c478bd9Sstevel@tonic-gate 			break;
646*7c478bd9Sstevel@tonic-gate 		}
647*7c478bd9Sstevel@tonic-gate 		if (nread < SECTOR_SIZE)
648*7c478bd9Sstevel@tonic-gate 			break;	/* end of file */
649*7c478bd9Sstevel@tonic-gate 	}
650*7c478bd9Sstevel@tonic-gate 	(void) close(pcfs_fp);
651*7c478bd9Sstevel@tonic-gate 	(void) umount(TMP_MNTPT);
652*7c478bd9Sstevel@tonic-gate 
653*7c478bd9Sstevel@tonic-gate 	/*
654*7c478bd9Sstevel@tonic-gate 	 * Now, get the blocklist from the device.
655*7c478bd9Sstevel@tonic-gate 	 */
656*7c478bd9Sstevel@tonic-gate 	bzero(blocklist, sizeof (blocklist));
657*7c478bd9Sstevel@tonic-gate 	if (read_stage2_blocklist(dev_fd, blocklist) != 0)
658*7c478bd9Sstevel@tonic-gate 		exit(-1);
659*7c478bd9Sstevel@tonic-gate }
660