xref: /titanic_44/usr/src/cmd/boot/installgrub/pcfs_glue.c (revision 6a634c9dca3093f3922e4b7ab826d7bdf17bf78e)
1*af28f636SEnrico Perla - Sun Microsystems /*
2*af28f636SEnrico Perla - Sun Microsystems  * CDDL HEADER START
3*af28f636SEnrico Perla - Sun Microsystems  *
4*af28f636SEnrico Perla - Sun Microsystems  * The contents of this file are subject to the terms of the
5*af28f636SEnrico Perla - Sun Microsystems  * Common Development and Distribution License (the "License").
6*af28f636SEnrico Perla - Sun Microsystems  * You may not use this file except in compliance with the License.
7*af28f636SEnrico Perla - Sun Microsystems  *
8*af28f636SEnrico Perla - Sun Microsystems  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*af28f636SEnrico Perla - Sun Microsystems  * or http://www.opensolaris.org/os/licensing.
10*af28f636SEnrico Perla - Sun Microsystems  * See the License for the specific language governing permissions
11*af28f636SEnrico Perla - Sun Microsystems  * and limitations under the License.
12*af28f636SEnrico Perla - Sun Microsystems  *
13*af28f636SEnrico Perla - Sun Microsystems  * When distributing Covered Code, include this CDDL HEADER in each
14*af28f636SEnrico Perla - Sun Microsystems  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*af28f636SEnrico Perla - Sun Microsystems  * If applicable, add the following below this CDDL HEADER, with the
16*af28f636SEnrico Perla - Sun Microsystems  * fields enclosed by brackets "[]" replaced with your own identifying
17*af28f636SEnrico Perla - Sun Microsystems  * information: Portions Copyright [yyyy] [name of copyright owner]
18*af28f636SEnrico Perla - Sun Microsystems  *
19*af28f636SEnrico Perla - Sun Microsystems  * CDDL HEADER END
20*af28f636SEnrico Perla - Sun Microsystems  */
21*af28f636SEnrico Perla - Sun Microsystems /*
22*af28f636SEnrico Perla - Sun Microsystems  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23*af28f636SEnrico Perla - Sun Microsystems  */
24*af28f636SEnrico Perla - Sun Microsystems 
25*af28f636SEnrico Perla - Sun Microsystems #include <stdio.h>
26*af28f636SEnrico Perla - Sun Microsystems #include <stdlib.h>
27*af28f636SEnrico Perla - Sun Microsystems #include <unistd.h>
28*af28f636SEnrico Perla - Sun Microsystems #include <sys/param.h>
29*af28f636SEnrico Perla - Sun Microsystems #include <sys/bootvfs.h>
30*af28f636SEnrico Perla - Sun Microsystems #include <sys/filep.h>
31*af28f636SEnrico Perla - Sun Microsystems 
32*af28f636SEnrico Perla - Sun Microsystems #include <libintl.h>
33*af28f636SEnrico Perla - Sun Microsystems #include <locale.h>
34*af28f636SEnrico Perla - Sun Microsystems #include "message.h"
35*af28f636SEnrico Perla - Sun Microsystems 
36*af28f636SEnrico Perla - Sun Microsystems /*
37*af28f636SEnrico Perla - Sun Microsystems  * This file is glue layer to pcfs module in usr/src/common/fs/pcfs.c.
38*af28f636SEnrico Perla - Sun Microsystems  * It's main functionality is to get the stage file blocklist. It's
39*af28f636SEnrico Perla - Sun Microsystems  * used for installing grub on a Solaris boot partition.
40*af28f636SEnrico Perla - Sun Microsystems  */
41*af28f636SEnrico Perla - Sun Microsystems extern struct boot_fs_ops bpcfs_ops;
42*af28f636SEnrico Perla - Sun Microsystems struct boot_fs_ops *bfs_ops;
43*af28f636SEnrico Perla - Sun Microsystems struct boot_fs_ops *bfs_tab[] = {&bpcfs_ops, NULL};
44*af28f636SEnrico Perla - Sun Microsystems static int dev_fd;
45*af28f636SEnrico Perla - Sun Microsystems int bootrd_debug = 0;
46*af28f636SEnrico Perla - Sun Microsystems 
47*af28f636SEnrico Perla - Sun Microsystems #define	DEV_BSIZE	512
48*af28f636SEnrico Perla - Sun Microsystems #define	MAX_CHUNK	64
49*af28f636SEnrico Perla - Sun Microsystems 
50*af28f636SEnrico Perla - Sun Microsystems static unsigned int *blocklist;
51*af28f636SEnrico Perla - Sun Microsystems 
52*af28f636SEnrico Perla - Sun Microsystems /* diskread_callback is set in filesytem module (pcfs.c) */
53*af28f636SEnrico Perla - Sun Microsystems int (*diskread_callback)(int, int);
54*af28f636SEnrico Perla - Sun Microsystems int (*fileread_callback)(int, int);
55*af28f636SEnrico Perla - Sun Microsystems 
56*af28f636SEnrico Perla - Sun Microsystems static int
add_stage2_block(int blocknum,int nblk)57*af28f636SEnrico Perla - Sun Microsystems add_stage2_block(int blocknum, int nblk)
58*af28f636SEnrico Perla - Sun Microsystems {
59*af28f636SEnrico Perla - Sun Microsystems 	static int i = -2;
60*af28f636SEnrico Perla - Sun Microsystems 
61*af28f636SEnrico Perla - Sun Microsystems 	if (i >= 0 && (blocklist[i] + blocklist[i + 1] == blocknum)) {
62*af28f636SEnrico Perla - Sun Microsystems 		blocklist[i + 1] += nblk;
63*af28f636SEnrico Perla - Sun Microsystems 		return (0);
64*af28f636SEnrico Perla - Sun Microsystems 	}
65*af28f636SEnrico Perla - Sun Microsystems 
66*af28f636SEnrico Perla - Sun Microsystems 	i += 2;
67*af28f636SEnrico Perla - Sun Microsystems 	if (i >= DEV_BSIZE / 8) {
68*af28f636SEnrico Perla - Sun Microsystems 		fprintf(stderr, PCFS_FRAGMENTED);
69*af28f636SEnrico Perla - Sun Microsystems 		exit(-1);
70*af28f636SEnrico Perla - Sun Microsystems 	}
71*af28f636SEnrico Perla - Sun Microsystems 	blocklist[i] = blocknum;
72*af28f636SEnrico Perla - Sun Microsystems 	blocklist[i + 1] = nblk;
73*af28f636SEnrico Perla - Sun Microsystems 	return (0);
74*af28f636SEnrico Perla - Sun Microsystems }
75*af28f636SEnrico Perla - Sun Microsystems 
76*af28f636SEnrico Perla - Sun Microsystems /*
77*af28f636SEnrico Perla - Sun Microsystems  * This one reads the ramdisk. If fi_memp is set, we copy the
78*af28f636SEnrico Perla - Sun Microsystems  * ramdisk content to the designated buffer. Otherwise, we
79*af28f636SEnrico Perla - Sun Microsystems  * do a "cached" read (set fi_memp to the actual ramdisk buffer).
80*af28f636SEnrico Perla - Sun Microsystems  */
81*af28f636SEnrico Perla - Sun Microsystems int
diskread(fileid_t * filep)82*af28f636SEnrico Perla - Sun Microsystems diskread(fileid_t *filep)
83*af28f636SEnrico Perla - Sun Microsystems {
84*af28f636SEnrico Perla - Sun Microsystems 	int ret;
85*af28f636SEnrico Perla - Sun Microsystems 	uint_t blocknum, diskloc;
86*af28f636SEnrico Perla - Sun Microsystems 
87*af28f636SEnrico Perla - Sun Microsystems 	blocknum = filep->fi_blocknum;
88*af28f636SEnrico Perla - Sun Microsystems 
89*af28f636SEnrico Perla - Sun Microsystems 	if (diskread_callback) {
90*af28f636SEnrico Perla - Sun Microsystems 		diskread_callback(blocknum, filep->fi_count / DEV_BSIZE);
91*af28f636SEnrico Perla - Sun Microsystems 		return (0);
92*af28f636SEnrico Perla - Sun Microsystems 	}
93*af28f636SEnrico Perla - Sun Microsystems 
94*af28f636SEnrico Perla - Sun Microsystems 	diskloc = blocknum * DEV_BSIZE;
95*af28f636SEnrico Perla - Sun Microsystems 	if (filep->fi_memp == NULL) {
96*af28f636SEnrico Perla - Sun Microsystems 		filep->fi_memp = malloc(filep->fi_count);
97*af28f636SEnrico Perla - Sun Microsystems 	}
98*af28f636SEnrico Perla - Sun Microsystems 	if (filep->fi_memp == NULL) {
99*af28f636SEnrico Perla - Sun Microsystems 		fprintf(stderr, OUT_OF_MEMORY);
100*af28f636SEnrico Perla - Sun Microsystems 		return (-1);
101*af28f636SEnrico Perla - Sun Microsystems 	}
102*af28f636SEnrico Perla - Sun Microsystems 
103*af28f636SEnrico Perla - Sun Microsystems 	ret = pread(dev_fd, filep->fi_memp, filep->fi_count, diskloc);
104*af28f636SEnrico Perla - Sun Microsystems 	if (ret < 0)
105*af28f636SEnrico Perla - Sun Microsystems 		perror("diskread: pread");
106*af28f636SEnrico Perla - Sun Microsystems 	return (ret >= 0 ? 0 : -1);
107*af28f636SEnrico Perla - Sun Microsystems }
108*af28f636SEnrico Perla - Sun Microsystems 
109*af28f636SEnrico Perla - Sun Microsystems void *
bkmem_alloc(size_t s)110*af28f636SEnrico Perla - Sun Microsystems bkmem_alloc(size_t s)
111*af28f636SEnrico Perla - Sun Microsystems {
112*af28f636SEnrico Perla - Sun Microsystems 	return (malloc(s));
113*af28f636SEnrico Perla - Sun Microsystems }
114*af28f636SEnrico Perla - Sun Microsystems 
115*af28f636SEnrico Perla - Sun Microsystems /*ARGSUSED*/
116*af28f636SEnrico Perla - Sun Microsystems void
bkmem_free(void * p,size_t s)117*af28f636SEnrico Perla - Sun Microsystems bkmem_free(void *p, size_t s)
118*af28f636SEnrico Perla - Sun Microsystems {
119*af28f636SEnrico Perla - Sun Microsystems 	free(p);
120*af28f636SEnrico Perla - Sun Microsystems }
121*af28f636SEnrico Perla - Sun Microsystems 
122*af28f636SEnrico Perla - Sun Microsystems static int
mountroot(char * name)123*af28f636SEnrico Perla - Sun Microsystems mountroot(char *name)
124*af28f636SEnrico Perla - Sun Microsystems {
125*af28f636SEnrico Perla - Sun Microsystems 	int i;
126*af28f636SEnrico Perla - Sun Microsystems 
127*af28f636SEnrico Perla - Sun Microsystems 	/* try ops in bfs_tab and return the first successful one */
128*af28f636SEnrico Perla - Sun Microsystems 	for (i = 0; bfs_tab[i] != NULL; i++) {
129*af28f636SEnrico Perla - Sun Microsystems 		bfs_ops = bfs_tab[i];
130*af28f636SEnrico Perla - Sun Microsystems 		if (BRD_MOUNTROOT(bfs_ops, name) == 0)
131*af28f636SEnrico Perla - Sun Microsystems 			return (0);
132*af28f636SEnrico Perla - Sun Microsystems 	}
133*af28f636SEnrico Perla - Sun Microsystems 	return (-1);
134*af28f636SEnrico Perla - Sun Microsystems }
135*af28f636SEnrico Perla - Sun Microsystems 
136*af28f636SEnrico Perla - Sun Microsystems static int
unmountroot()137*af28f636SEnrico Perla - Sun Microsystems unmountroot()
138*af28f636SEnrico Perla - Sun Microsystems {
139*af28f636SEnrico Perla - Sun Microsystems 	return (BRD_UNMOUNTROOT(bfs_ops));
140*af28f636SEnrico Perla - Sun Microsystems }
141*af28f636SEnrico Perla - Sun Microsystems 
142*af28f636SEnrico Perla - Sun Microsystems static int
pcfs_glue_open(const char * filename,int flags)143*af28f636SEnrico Perla - Sun Microsystems pcfs_glue_open(const char *filename, int flags)
144*af28f636SEnrico Perla - Sun Microsystems {
145*af28f636SEnrico Perla - Sun Microsystems 	return (BRD_OPEN(bfs_ops, (char *)filename, flags));
146*af28f636SEnrico Perla - Sun Microsystems }
147*af28f636SEnrico Perla - Sun Microsystems 
148*af28f636SEnrico Perla - Sun Microsystems static int
pcfs_glue_close(int fd)149*af28f636SEnrico Perla - Sun Microsystems pcfs_glue_close(int fd)
150*af28f636SEnrico Perla - Sun Microsystems {
151*af28f636SEnrico Perla - Sun Microsystems 	return (BRD_CLOSE(bfs_ops, fd));
152*af28f636SEnrico Perla - Sun Microsystems }
153*af28f636SEnrico Perla - Sun Microsystems 
154*af28f636SEnrico Perla - Sun Microsystems static ssize_t
pcfs_glue_read(int fd,void * buf,size_t size)155*af28f636SEnrico Perla - Sun Microsystems pcfs_glue_read(int fd, void *buf, size_t size)
156*af28f636SEnrico Perla - Sun Microsystems {
157*af28f636SEnrico Perla - Sun Microsystems 	return (BRD_READ(bfs_ops, fd, buf, size));
158*af28f636SEnrico Perla - Sun Microsystems }
159*af28f636SEnrico Perla - Sun Microsystems 
160*af28f636SEnrico Perla - Sun Microsystems static off_t
pcfs_glue_lseek(int fd,off_t addr,int whence)161*af28f636SEnrico Perla - Sun Microsystems pcfs_glue_lseek(int fd, off_t addr, int whence)
162*af28f636SEnrico Perla - Sun Microsystems {
163*af28f636SEnrico Perla - Sun Microsystems 	return (BRD_SEEK(bfs_ops, fd, addr, whence));
164*af28f636SEnrico Perla - Sun Microsystems }
165*af28f636SEnrico Perla - Sun Microsystems 
166*af28f636SEnrico Perla - Sun Microsystems /*
167*af28f636SEnrico Perla - Sun Microsystems  * Get the blocklist for stage2
168*af28f636SEnrico Perla - Sun Microsystems  */
169*af28f636SEnrico Perla - Sun Microsystems int
read_stage2_blocklist(int device_fd,unsigned int * blkbuf)170*af28f636SEnrico Perla - Sun Microsystems read_stage2_blocklist(int device_fd, unsigned int *blkbuf)
171*af28f636SEnrico Perla - Sun Microsystems {
172*af28f636SEnrico Perla - Sun Microsystems 	int i, fd, stage2_block;
173*af28f636SEnrico Perla - Sun Microsystems 	char buf[DEV_BSIZE];
174*af28f636SEnrico Perla - Sun Microsystems 	ssize_t size;
175*af28f636SEnrico Perla - Sun Microsystems 
176*af28f636SEnrico Perla - Sun Microsystems 	dev_fd = device_fd;
177*af28f636SEnrico Perla - Sun Microsystems 	if (mountroot("dummy") != 0) {
178*af28f636SEnrico Perla - Sun Microsystems 		fprintf(stderr, MOUNT_FAIL_PCFS);
179*af28f636SEnrico Perla - Sun Microsystems 		return (-1);
180*af28f636SEnrico Perla - Sun Microsystems 	}
181*af28f636SEnrico Perla - Sun Microsystems 
182*af28f636SEnrico Perla - Sun Microsystems 	if ((fd = pcfs_glue_open("/boot/grub/stage2", 0)) == -1) {
183*af28f636SEnrico Perla - Sun Microsystems 		fprintf(stderr, OPEN_FAIL_PCFS);
184*af28f636SEnrico Perla - Sun Microsystems 		return (-1);
185*af28f636SEnrico Perla - Sun Microsystems 	}
186*af28f636SEnrico Perla - Sun Microsystems 
187*af28f636SEnrico Perla - Sun Microsystems 	if (bootrd_debug)
188*af28f636SEnrico Perla - Sun Microsystems 		(void) printf("start reading stage2:\n");
189*af28f636SEnrico Perla - Sun Microsystems 	stage2_block = 0;
190*af28f636SEnrico Perla - Sun Microsystems 	blocklist = blkbuf;
191*af28f636SEnrico Perla - Sun Microsystems 	fileread_callback = add_stage2_block;
192*af28f636SEnrico Perla - Sun Microsystems 	for (;;) {
193*af28f636SEnrico Perla - Sun Microsystems 		size = pcfs_glue_read(fd, buf, DEV_BSIZE);
194*af28f636SEnrico Perla - Sun Microsystems 		if (size != DEV_BSIZE)
195*af28f636SEnrico Perla - Sun Microsystems 			break;
196*af28f636SEnrico Perla - Sun Microsystems 		stage2_block++;
197*af28f636SEnrico Perla - Sun Microsystems 	}
198*af28f636SEnrico Perla - Sun Microsystems 	fileread_callback = NULL;
199*af28f636SEnrico Perla - Sun Microsystems 	(void) pcfs_glue_close(fd);
200*af28f636SEnrico Perla - Sun Microsystems 
201*af28f636SEnrico Perla - Sun Microsystems 	if (bootrd_debug) {
202*af28f636SEnrico Perla - Sun Microsystems 		(void) printf("last block size = %d\n", size);
203*af28f636SEnrico Perla - Sun Microsystems 		for (i = 0; blocklist[i] != 0; i += 2) {
204*af28f636SEnrico Perla - Sun Microsystems 			(void) printf("sectors: %d-%d\n",
205*af28f636SEnrico Perla - Sun Microsystems 			    blocklist[i],
206*af28f636SEnrico Perla - Sun Microsystems 			    blocklist[i] + blocklist[i + 1] - 1);
207*af28f636SEnrico Perla - Sun Microsystems 		}
208*af28f636SEnrico Perla - Sun Microsystems 		(void) printf("total blocks in stage 2: %d\n", stage2_block);
209*af28f636SEnrico Perla - Sun Microsystems 	}
210*af28f636SEnrico Perla - Sun Microsystems 
211*af28f636SEnrico Perla - Sun Microsystems 	(void) unmountroot();
212*af28f636SEnrico Perla - Sun Microsystems 	return (0);
213*af28f636SEnrico Perla - Sun Microsystems }
214