4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
28 #include <sys/param.h>
29 #include <sys/bootvfs.h>
30 #include <sys/filep.h>
37 * This file is glue layer to pcfs module in usr/src/common/fs/pcfs.c.
38 * It's main functionality is to get the stage file blocklist. It's
39 * used for installing grub on a Solaris boot partition.
41 extern struct boot_fs_ops bpcfs_ops
;
42 struct boot_fs_ops
*bfs_ops
;
43 struct boot_fs_ops
*bfs_tab
[] = {&bpcfs_ops
, NULL
};
50 static unsigned int *blocklist
;
52 /* diskread_callback is set in filesytem module (pcfs.c) */
53 int (*diskread_callback
)(int, int);
54 int (*fileread_callback
)(int, int);
57 add_stage2_block(int blocknum
, int nblk
)
61 if (i
>= 0 && (blocklist
[i
] + blocklist
[i
+ 1] == blocknum
)) {
62 blocklist
[i
+ 1] += nblk
;
67 if (i
>= DEV_BSIZE
/ 8) {
68 fprintf(stderr
, PCFS_FRAGMENTED
);
71 blocklist
[i
] = blocknum
;
72 blocklist
[i
+ 1] = nblk
;
77 * This one reads the ramdisk. If fi_memp is set, we copy the
78 * ramdisk content to the designated buffer. Otherwise, we
79 * do a "cached" read (set fi_memp to the actual ramdisk buffer).
82 diskread(fileid_t
*filep
)
85 uint_t blocknum
, diskloc
;
87 blocknum
= filep
->fi_blocknum
;
89 if (diskread_callback
) {
90 diskread_callback(blocknum
, filep
->fi_count
/ DEV_BSIZE
);
94 diskloc
= blocknum
* DEV_BSIZE
;
95 if (filep
->fi_memp
== NULL
) {
96 filep
->fi_memp
= malloc(filep
->fi_count
);
98 if (filep
->fi_memp
== NULL
) {
99 fprintf(stderr
, OUT_OF_MEMORY
);
103 ret
= pread(dev_fd
, filep
->fi_memp
, filep
->fi_count
, diskloc
);
105 perror("diskread: pread");
106 return (ret
>= 0 ? 0 : -1);
110 bkmem_alloc(size_t s
)
117 bkmem_free(void *p
, size_t s
)
123 mountroot(char *name
)
127 /* try ops in bfs_tab and return the first successful one */
128 for (i
= 0; bfs_tab
[i
] != NULL
; i
++) {
129 bfs_ops
= bfs_tab
[i
];
130 if (BRD_MOUNTROOT(bfs_ops
, name
) == 0)
139 return (BRD_UNMOUNTROOT(bfs_ops
));
143 pcfs_glue_open(const char *filename
, int flags
)
145 return (BRD_OPEN(bfs_ops
, (char *)filename
, flags
));
149 pcfs_glue_close(int fd
)
151 return (BRD_CLOSE(bfs_ops
, fd
));
155 pcfs_glue_read(int fd
, void *buf
, size_t size
)
157 return (BRD_READ(bfs_ops
, fd
, buf
, size
));
161 * Get the blocklist for stage2
164 read_stage2_blocklist(int device_fd
, unsigned int *blkbuf
)
166 int i
, fd
, stage2_block
;
171 if (mountroot("dummy") != 0) {
172 fprintf(stderr
, MOUNT_FAIL_PCFS
);
176 if ((fd
= pcfs_glue_open("/boot/grub/stage2", 0)) == -1) {
177 fprintf(stderr
, OPEN_FAIL_PCFS
);
182 (void) printf("start reading stage2:\n");
185 fileread_callback
= add_stage2_block
;
187 size
= pcfs_glue_read(fd
, buf
, DEV_BSIZE
);
188 if (size
!= DEV_BSIZE
)
192 fileread_callback
= NULL
;
193 (void) pcfs_glue_close(fd
);
196 (void) printf("last block size = %d\n", size
);
197 for (i
= 0; blocklist
[i
] != 0; i
+= 2) {
198 (void) printf("sectors: %d-%d\n",
200 blocklist
[i
] + blocklist
[i
+ 1] - 1);
202 (void) printf("total blocks in stage 2: %d\n", stage2_block
);
205 (void) unmountroot();