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