1 1.9 dholland /* $NetBSD: ext2fs.c,v 1.9 2013/06/23 02:06:06 dholland Exp $ */ 2 1.1 tsutsui 3 1.1 tsutsui /* 4 1.1 tsutsui * Copyright (c) 1997 Manuel Bouyer. 5 1.1 tsutsui * 6 1.1 tsutsui * Redistribution and use in source and binary forms, with or without 7 1.1 tsutsui * modification, are permitted provided that the following conditions 8 1.1 tsutsui * are met: 9 1.1 tsutsui * 1. Redistributions of source code must retain the above copyright 10 1.1 tsutsui * notice, this list of conditions and the following disclaimer. 11 1.1 tsutsui * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 tsutsui * notice, this list of conditions and the following disclaimer in the 13 1.1 tsutsui * documentation and/or other materials provided with the distribution. 14 1.1 tsutsui * 15 1.1 tsutsui * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 1.1 tsutsui * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 1.1 tsutsui * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 1.1 tsutsui * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 1.1 tsutsui * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 1.1 tsutsui * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 1.1 tsutsui * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 1.1 tsutsui * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 1.1 tsutsui * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 1.1 tsutsui * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 1.1 tsutsui */ 26 1.1 tsutsui 27 1.1 tsutsui /*- 28 1.1 tsutsui * Copyright (c) 2002 The NetBSD Foundation, Inc. 29 1.1 tsutsui * All rights reserved. 30 1.1 tsutsui * 31 1.1 tsutsui * This code is derived from software contributed to The NetBSD Foundation 32 1.1 tsutsui * by Matt Fredette. 33 1.1 tsutsui * 34 1.1 tsutsui * Redistribution and use in source and binary forms, with or without 35 1.1 tsutsui * modification, are permitted provided that the following conditions 36 1.1 tsutsui * are met: 37 1.1 tsutsui * 1. Redistributions of source code must retain the above copyright 38 1.1 tsutsui * notice, this list of conditions and the following disclaimer. 39 1.1 tsutsui * 2. Redistributions in binary form must reproduce the above copyright 40 1.1 tsutsui * notice, this list of conditions and the following disclaimer in the 41 1.1 tsutsui * documentation and/or other materials provided with the distribution. 42 1.1 tsutsui * 43 1.1 tsutsui * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 44 1.1 tsutsui * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 45 1.1 tsutsui * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 46 1.1 tsutsui * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 47 1.1 tsutsui * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 48 1.1 tsutsui * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 49 1.1 tsutsui * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 50 1.1 tsutsui * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 51 1.1 tsutsui * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 52 1.1 tsutsui * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 53 1.1 tsutsui * POSSIBILITY OF SUCH DAMAGE. 54 1.1 tsutsui */ 55 1.1 tsutsui 56 1.1 tsutsui #if HAVE_NBTOOL_CONFIG_H 57 1.1 tsutsui #include "nbtool_config.h" 58 1.1 tsutsui #endif 59 1.1 tsutsui 60 1.1 tsutsui #include <sys/cdefs.h> 61 1.6 tsutsui #if !defined(__lint) 62 1.9 dholland __RCSID("$NetBSD: ext2fs.c,v 1.9 2013/06/23 02:06:06 dholland Exp $"); 63 1.1 tsutsui #endif /* !__lint */ 64 1.1 tsutsui 65 1.1 tsutsui #include <sys/param.h> 66 1.1 tsutsui 67 1.1 tsutsui #if !HAVE_NBTOOL_CONFIG_H 68 1.1 tsutsui #include <sys/mount.h> 69 1.1 tsutsui #endif 70 1.1 tsutsui 71 1.1 tsutsui #include <assert.h> 72 1.1 tsutsui #include <err.h> 73 1.1 tsutsui #include <errno.h> 74 1.1 tsutsui #include <fcntl.h> 75 1.1 tsutsui #include <stdarg.h> 76 1.1 tsutsui #include <stdio.h> 77 1.1 tsutsui #include <stdlib.h> 78 1.1 tsutsui #include <string.h> 79 1.1 tsutsui #include <unistd.h> 80 1.1 tsutsui 81 1.1 tsutsui #include "installboot.h" 82 1.1 tsutsui 83 1.1 tsutsui #include <ufs/ext2fs/ext2fs_dinode.h> 84 1.1 tsutsui #include <ufs/ext2fs/ext2fs_dir.h> 85 1.1 tsutsui #include <ufs/ext2fs/ext2fs.h> 86 1.1 tsutsui 87 1.1 tsutsui static int ext2fs_read_disk_block(ib_params *, uint64_t, int, uint8_t []); 88 1.1 tsutsui static int ext2fs_read_sblock(ib_params *, struct m_ext2fs *fs); 89 1.1 tsutsui static int ext2fs_read_gdblock(ib_params *, struct m_ext2fs *fs); 90 1.1 tsutsui static int ext2fs_find_disk_blocks(ib_params *, ino_t, 91 1.1 tsutsui int (*)(ib_params *, void *, uint64_t, uint32_t), void *); 92 1.1 tsutsui static int ext2fs_findstage2_ino(ib_params *, void *, uint64_t, uint32_t); 93 1.1 tsutsui static int ext2fs_findstage2_blocks(ib_params *, void *, uint64_t, 94 1.1 tsutsui uint32_t); 95 1.1 tsutsui 96 1.1 tsutsui 97 1.1 tsutsui /* This reads a disk block from the file system. */ 98 1.1 tsutsui /* XXX: should be shared with ffs.c? */ 99 1.1 tsutsui static int 100 1.1 tsutsui ext2fs_read_disk_block(ib_params *params, uint64_t blkno, int size, 101 1.1 tsutsui uint8_t blk[]) 102 1.1 tsutsui { 103 1.1 tsutsui int rv; 104 1.1 tsutsui 105 1.1 tsutsui assert(params != NULL); 106 1.1 tsutsui assert(params->filesystem != NULL); 107 1.1 tsutsui assert(params->fsfd != -1); 108 1.1 tsutsui assert(size > 0); 109 1.1 tsutsui assert(blk != NULL); 110 1.1 tsutsui 111 1.5 tsutsui rv = pread(params->fsfd, blk, size, blkno * params->sectorsize); 112 1.1 tsutsui if (rv == -1) { 113 1.1 tsutsui warn("Reading block %llu in `%s'", 114 1.1 tsutsui (unsigned long long)blkno, params->filesystem); 115 1.1 tsutsui return 0; 116 1.1 tsutsui } else if (rv != size) { 117 1.1 tsutsui warnx("Reading block %llu in `%s': short read", 118 1.1 tsutsui (unsigned long long)blkno, params->filesystem); 119 1.1 tsutsui return 0; 120 1.1 tsutsui } 121 1.1 tsutsui 122 1.1 tsutsui return 1; 123 1.1 tsutsui } 124 1.1 tsutsui 125 1.1 tsutsui static int 126 1.1 tsutsui ext2fs_read_sblock(ib_params *params, struct m_ext2fs *fs) 127 1.1 tsutsui { 128 1.1 tsutsui uint8_t sbbuf[SBSIZE]; 129 1.1 tsutsui 130 1.5 tsutsui if (ext2fs_read_disk_block(params, SBOFF / params->sectorsize, SBSIZE, 131 1.1 tsutsui sbbuf) == 0) 132 1.1 tsutsui 133 1.1 tsutsui e2fs_sbload((void *)sbbuf, &fs->e2fs); 134 1.1 tsutsui 135 1.1 tsutsui if (fs->e2fs.e2fs_magic != E2FS_MAGIC) 136 1.1 tsutsui return 0; 137 1.1 tsutsui 138 1.1 tsutsui if (fs->e2fs.e2fs_rev > E2FS_REV1 || 139 1.1 tsutsui (fs->e2fs.e2fs_rev == E2FS_REV1 && 140 1.1 tsutsui (fs->e2fs.e2fs_first_ino != EXT2_FIRSTINO || 141 1.1 tsutsui fs->e2fs.e2fs_inode_size != EXT2_DINODE_SIZE || 142 1.1 tsutsui (fs->e2fs.e2fs_features_incompat & ~EXT2F_INCOMPAT_SUPP) != 0))) 143 1.1 tsutsui return 0; 144 1.1 tsutsui 145 1.1 tsutsui fs->e2fs_ncg = 146 1.1 tsutsui howmany(fs->e2fs.e2fs_bcount - fs->e2fs.e2fs_first_dblock, 147 1.1 tsutsui fs->e2fs.e2fs_bpg); 148 1.1 tsutsui /* XXX assume hw bsize = 512 */ 149 1.1 tsutsui fs->e2fs_fsbtodb = fs->e2fs.e2fs_log_bsize + 1; 150 1.1 tsutsui fs->e2fs_bsize = MINBSIZE << fs->e2fs.e2fs_log_bsize; 151 1.1 tsutsui fs->e2fs_bshift = LOG_MINBSIZE + fs->e2fs.e2fs_log_bsize; 152 1.1 tsutsui fs->e2fs_qbmask = fs->e2fs_bsize - 1; 153 1.1 tsutsui fs->e2fs_bmask = ~fs->e2fs_qbmask; 154 1.1 tsutsui fs->e2fs_ngdb = 155 1.1 tsutsui howmany(fs->e2fs_ncg, fs->e2fs_bsize / sizeof(struct ext2_gd)); 156 1.1 tsutsui fs->e2fs_ipb = fs->e2fs_bsize / EXT2_DINODE_SIZE; 157 1.1 tsutsui fs->e2fs_itpg = fs->e2fs.e2fs_ipg / fs->e2fs_ipb; 158 1.1 tsutsui 159 1.1 tsutsui return 1; 160 1.1 tsutsui } 161 1.1 tsutsui 162 1.1 tsutsui static int 163 1.1 tsutsui ext2fs_read_gdblock(ib_params *params, struct m_ext2fs *fs) 164 1.1 tsutsui { 165 1.1 tsutsui uint8_t gdbuf[MAXBSIZE]; 166 1.1 tsutsui uint32_t gdpb; 167 1.1 tsutsui int i; 168 1.1 tsutsui 169 1.1 tsutsui gdpb = fs->e2fs_bsize / sizeof(struct ext2_gd); 170 1.1 tsutsui 171 1.1 tsutsui for (i = 0; i < fs->e2fs_ngdb; i++) { 172 1.9 dholland if (ext2fs_read_disk_block(params, EXT2_FSBTODB(fs, 173 1.1 tsutsui fs->e2fs.e2fs_first_dblock + 1 /* superblock */ + i), 174 1.1 tsutsui SBSIZE, gdbuf) == 0) 175 1.1 tsutsui return 0; 176 1.1 tsutsui 177 1.1 tsutsui e2fs_cgload((struct ext2_gd *)gdbuf, &fs->e2fs_gd[gdpb * i], 178 1.1 tsutsui (i == (fs->e2fs_ngdb - 1)) ? 179 1.1 tsutsui (fs->e2fs_ncg - gdpb * i) * sizeof(struct ext2_gd): 180 1.1 tsutsui fs->e2fs_bsize); 181 1.1 tsutsui } 182 1.1 tsutsui 183 1.1 tsutsui return 1; 184 1.1 tsutsui } 185 1.1 tsutsui 186 1.1 tsutsui /* 187 1.1 tsutsui * This iterates over the data blocks belonging to an inode, 188 1.1 tsutsui * making a callback each iteration with the disk block number 189 1.1 tsutsui * and the size. 190 1.1 tsutsui */ 191 1.1 tsutsui static int 192 1.1 tsutsui ext2fs_find_disk_blocks(ib_params *params, ino_t ino, 193 1.1 tsutsui int (*callback)(ib_params *, void *, uint64_t, uint32_t), 194 1.1 tsutsui void *state) 195 1.1 tsutsui { 196 1.1 tsutsui uint8_t sbbuf[sizeof(struct m_ext2fs)]; 197 1.1 tsutsui struct m_ext2fs *fs; 198 1.1 tsutsui uint8_t inodebuf[MAXBSIZE]; 199 1.1 tsutsui struct ext2fs_dinode inode_store, *inode; 200 1.1 tsutsui int level_i; 201 1.1 tsutsui int32_t blk, lblk, nblk; 202 1.1 tsutsui int rv; 203 1.1 tsutsui #define LEVELS 4 204 1.1 tsutsui struct { 205 1.1 tsutsui uint32_t *blknums; 206 1.1 tsutsui unsigned long blkcount; 207 1.1 tsutsui uint8_t diskbuf[MAXBSIZE]; 208 1.1 tsutsui } level[LEVELS]; 209 1.1 tsutsui 210 1.1 tsutsui assert(params != NULL); 211 1.1 tsutsui assert(params->fstype != NULL); 212 1.1 tsutsui assert(callback != NULL); 213 1.1 tsutsui assert(state != NULL); 214 1.1 tsutsui 215 1.1 tsutsui /* Read the superblock. */ 216 1.1 tsutsui fs = (void *)sbbuf; 217 1.1 tsutsui if (ext2fs_read_sblock(params, fs) == 0) 218 1.1 tsutsui return 0; 219 1.1 tsutsui 220 1.1 tsutsui fs->e2fs_gd = malloc(sizeof(struct ext2_gd) * fs->e2fs_ncg); 221 1.1 tsutsui if (fs->e2fs_gd == NULL) { 222 1.1 tsutsui warnx("Can't allocate memofy for group descriptors"); 223 1.1 tsutsui return 0; 224 1.1 tsutsui } 225 1.1 tsutsui 226 1.1 tsutsui if (ext2fs_read_gdblock(params, fs) == 0) { 227 1.1 tsutsui warnx("Can't read group descriptors"); 228 1.1 tsutsui return 0; 229 1.1 tsutsui } 230 1.1 tsutsui 231 1.1 tsutsui if (fs->e2fs_ipb <= 0) { 232 1.1 tsutsui warnx("Bad ipb %d in superblock in `%s'", 233 1.1 tsutsui fs->e2fs_ipb, params->filesystem); 234 1.1 tsutsui return 0; 235 1.1 tsutsui } 236 1.1 tsutsui 237 1.1 tsutsui /* Read the inode. */ 238 1.1 tsutsui if (ext2fs_read_disk_block(params, 239 1.9 dholland EXT2_FSBTODB(fs, ino_to_fsba(fs, ino)) + params->fstype->offset, 240 1.1 tsutsui fs->e2fs_bsize, inodebuf)) 241 1.1 tsutsui return 0; 242 1.1 tsutsui inode = (void *)inodebuf; 243 1.1 tsutsui e2fs_iload(&inode[ino_to_fsbo(fs, ino)], &inode_store); 244 1.1 tsutsui inode = &inode_store; 245 1.1 tsutsui 246 1.1 tsutsui /* Get the block count and initialize for our block walk. */ 247 1.1 tsutsui nblk = howmany(inode->e2di_size, fs->e2fs_bsize); 248 1.1 tsutsui lblk = 0; 249 1.1 tsutsui level_i = 0; 250 1.1 tsutsui level[0].blknums = &inode->e2di_blocks[0]; 251 1.7 dholland level[0].blkcount = UFS_NDADDR; 252 1.7 dholland level[1].blknums = &inode->e2di_blocks[UFS_NDADDR + 0]; 253 1.1 tsutsui level[1].blkcount = 1; 254 1.7 dholland level[2].blknums = &inode->e2di_blocks[UFS_NDADDR + 1]; 255 1.1 tsutsui level[2].blkcount = 1; 256 1.7 dholland level[3].blknums = &inode->e2di_blocks[UFS_NDADDR + 2]; 257 1.1 tsutsui level[3].blkcount = 1; 258 1.1 tsutsui 259 1.1 tsutsui /* Walk the data blocks. */ 260 1.1 tsutsui while (nblk > 0) { 261 1.1 tsutsui 262 1.1 tsutsui /* 263 1.1 tsutsui * If there are no more blocks at this indirection 264 1.1 tsutsui * level, move up one indirection level and loop. 265 1.1 tsutsui */ 266 1.1 tsutsui if (level[level_i].blkcount == 0) { 267 1.1 tsutsui if (++level_i == LEVELS) 268 1.1 tsutsui break; 269 1.1 tsutsui continue; 270 1.1 tsutsui } 271 1.1 tsutsui 272 1.1 tsutsui /* Get the next block at this level. */ 273 1.1 tsutsui blk = fs2h32(*(level[level_i].blknums++)); 274 1.1 tsutsui level[level_i].blkcount--; 275 1.1 tsutsui 276 1.1 tsutsui #if 0 277 1.1 tsutsui fprintf(stderr, "ino %lu blk %lu level %d\n", ino, blk, 278 1.1 tsutsui level_i); 279 1.1 tsutsui #endif 280 1.1 tsutsui 281 1.1 tsutsui /* 282 1.1 tsutsui * If we're not at the direct level, descend one 283 1.1 tsutsui * level, read in that level's new block list, 284 1.1 tsutsui * and loop. 285 1.1 tsutsui */ 286 1.1 tsutsui if (level_i > 0) { 287 1.1 tsutsui level_i--; 288 1.1 tsutsui if (blk == 0) 289 1.1 tsutsui memset(level[level_i].diskbuf, 0, MAXBSIZE); 290 1.1 tsutsui else if (ext2fs_read_disk_block(params, 291 1.9 dholland EXT2_FSBTODB(fs, blk) + params->fstype->offset, 292 1.1 tsutsui fs->e2fs_bsize, level[level_i].diskbuf) == 0) 293 1.1 tsutsui return 0; 294 1.1 tsutsui /* XXX ondisk32 */ 295 1.1 tsutsui level[level_i].blknums = 296 1.1 tsutsui (uint32_t *)level[level_i].diskbuf; 297 1.8 dholland level[level_i].blkcount = EXT2_NINDIR(fs); 298 1.1 tsutsui continue; 299 1.1 tsutsui } 300 1.1 tsutsui 301 1.1 tsutsui /* blk is the next direct level block. */ 302 1.1 tsutsui #if 0 303 1.1 tsutsui fprintf(stderr, "ino %lu db %lu blksize %lu\n", ino, 304 1.9 dholland EXT2_FSBTODB(fs, blk), ext2_sblksize(fs, inode->di_size, lblk)); 305 1.1 tsutsui #endif 306 1.1 tsutsui rv = (*callback)(params, state, 307 1.9 dholland EXT2_FSBTODB(fs, blk) + params->fstype->offset, fs->e2fs_bsize); 308 1.1 tsutsui lblk++; 309 1.1 tsutsui nblk--; 310 1.1 tsutsui if (rv != 1) 311 1.1 tsutsui return rv; 312 1.1 tsutsui } 313 1.1 tsutsui 314 1.1 tsutsui if (nblk != 0) { 315 1.1 tsutsui warnx("Inode %llu in `%s' ran out of blocks?", 316 1.1 tsutsui (unsigned long long)ino, params->filesystem); 317 1.1 tsutsui return 0; 318 1.1 tsutsui } 319 1.1 tsutsui 320 1.1 tsutsui return 1; 321 1.1 tsutsui } 322 1.1 tsutsui 323 1.1 tsutsui /* 324 1.1 tsutsui * This callback reads a block of the root directory, 325 1.1 tsutsui * searches for an entry for the secondary bootstrap, 326 1.1 tsutsui * and saves the inode number if one is found. 327 1.1 tsutsui */ 328 1.1 tsutsui static int 329 1.1 tsutsui ext2fs_findstage2_ino(ib_params *params, void *_ino, 330 1.1 tsutsui uint64_t blk, uint32_t blksize) 331 1.1 tsutsui { 332 1.1 tsutsui uint8_t dirbuf[MAXBSIZE]; 333 1.1 tsutsui struct ext2fs_direct *de, *ede; 334 1.1 tsutsui uint32_t ino; 335 1.1 tsutsui 336 1.1 tsutsui assert(params != NULL); 337 1.1 tsutsui assert(params->fstype != NULL); 338 1.1 tsutsui assert(params->stage2 != NULL); 339 1.1 tsutsui assert(_ino != NULL); 340 1.1 tsutsui 341 1.1 tsutsui /* Skip directory holes. */ 342 1.1 tsutsui if (blk == 0) 343 1.1 tsutsui return 1; 344 1.1 tsutsui 345 1.1 tsutsui /* Read the directory block. */ 346 1.1 tsutsui if (ext2fs_read_disk_block(params, blk, blksize, dirbuf) == 0) 347 1.1 tsutsui return 0; 348 1.1 tsutsui 349 1.1 tsutsui /* Loop over the directory entries. */ 350 1.1 tsutsui de = (struct ext2fs_direct *)&dirbuf[0]; 351 1.1 tsutsui ede = (struct ext2fs_direct *)&dirbuf[blksize]; 352 1.1 tsutsui while (de < ede) { 353 1.1 tsutsui ino = fs2h32(de->e2d_ino); 354 1.1 tsutsui if (ino != 0 && strcmp(de->e2d_name, params->stage2) == 0) { 355 1.1 tsutsui *((uint32_t *)_ino) = ino; 356 1.1 tsutsui return (2); 357 1.1 tsutsui } 358 1.1 tsutsui if (fs2h16(de->e2d_reclen) == 0) 359 1.1 tsutsui break; 360 1.1 tsutsui de = (struct ext2fs_direct *)((char *)de + 361 1.1 tsutsui fs2h16(de->e2d_reclen)); 362 1.1 tsutsui } 363 1.1 tsutsui 364 1.1 tsutsui return 1; 365 1.1 tsutsui } 366 1.1 tsutsui 367 1.1 tsutsui struct findblks_state { 368 1.1 tsutsui uint32_t maxblk; 369 1.1 tsutsui uint32_t nblk; 370 1.1 tsutsui ib_block *blocks; 371 1.1 tsutsui }; 372 1.1 tsutsui 373 1.1 tsutsui /* This callback records the blocks of the secondary bootstrap. */ 374 1.1 tsutsui static int 375 1.1 tsutsui ext2fs_findstage2_blocks(ib_params *params, void *_state, 376 1.1 tsutsui uint64_t blk, uint32_t blksize) 377 1.1 tsutsui { 378 1.1 tsutsui struct findblks_state *state = _state; 379 1.1 tsutsui 380 1.1 tsutsui assert(params != NULL); 381 1.1 tsutsui assert(params->stage2 != NULL); 382 1.1 tsutsui assert(_state != NULL); 383 1.1 tsutsui 384 1.1 tsutsui if (state->nblk == state->maxblk) { 385 1.1 tsutsui warnx("Secondary bootstrap `%s' has too many blocks (max %d)", 386 1.1 tsutsui params->stage2, state->maxblk); 387 1.1 tsutsui return (0); 388 1.1 tsutsui } 389 1.1 tsutsui state->blocks[state->nblk].block = blk; 390 1.1 tsutsui state->blocks[state->nblk].blocksize = blksize; 391 1.1 tsutsui state->nblk++; 392 1.1 tsutsui return 1; 393 1.1 tsutsui } 394 1.1 tsutsui 395 1.1 tsutsui /* 396 1.1 tsutsui * publicly visible functions 397 1.1 tsutsui */ 398 1.1 tsutsui 399 1.1 tsutsui int 400 1.1 tsutsui ext2fs_match(ib_params *params) 401 1.1 tsutsui { 402 1.1 tsutsui uint8_t sbbuf[sizeof(struct m_ext2fs)]; 403 1.1 tsutsui struct m_ext2fs *fs; 404 1.1 tsutsui 405 1.1 tsutsui assert(params != NULL); 406 1.1 tsutsui assert(params->fstype != NULL); 407 1.1 tsutsui 408 1.1 tsutsui /* Read the superblock. */ 409 1.1 tsutsui fs = (void *)sbbuf; 410 1.1 tsutsui if (ext2fs_read_sblock(params, fs) == 0) 411 1.1 tsutsui return 0; 412 1.1 tsutsui 413 1.1 tsutsui params->fstype->needswap = 0; 414 1.1 tsutsui params->fstype->blocksize = fs->e2fs_bsize; 415 1.1 tsutsui params->fstype->offset = 0; 416 1.1 tsutsui 417 1.1 tsutsui return 1; 418 1.1 tsutsui } 419 1.1 tsutsui 420 1.1 tsutsui int 421 1.1 tsutsui ext2fs_findstage2(ib_params *params, uint32_t *maxblk, ib_block *blocks) 422 1.1 tsutsui { 423 1.1 tsutsui int rv; 424 1.1 tsutsui uint32_t ino; 425 1.1 tsutsui struct findblks_state state; 426 1.1 tsutsui 427 1.1 tsutsui assert(params != NULL); 428 1.1 tsutsui assert(params->stage2 != NULL); 429 1.1 tsutsui assert(maxblk != NULL); 430 1.1 tsutsui assert(blocks != NULL); 431 1.1 tsutsui 432 1.1 tsutsui if (params->flags & IB_STAGE2START) 433 1.1 tsutsui return hardcode_stage2(params, maxblk, blocks); 434 1.1 tsutsui 435 1.1 tsutsui /* The secondary bootstrap must be clearly in /. */ 436 1.1 tsutsui if (params->stage2[0] == '/') 437 1.1 tsutsui params->stage2++; 438 1.1 tsutsui if (strchr(params->stage2, '/') != NULL) { 439 1.1 tsutsui warnx("The secondary bootstrap `%s' must be in /", 440 1.1 tsutsui params->stage2); 441 1.3 apb warnx("(Path must be relative to the file system in `%s')", 442 1.3 apb params->filesystem); 443 1.1 tsutsui return 0; 444 1.1 tsutsui } 445 1.1 tsutsui 446 1.1 tsutsui /* Get the inode number of the secondary bootstrap. */ 447 1.1 tsutsui rv = ext2fs_find_disk_blocks(params, EXT2_ROOTINO, 448 1.1 tsutsui ext2fs_findstage2_ino, &ino); 449 1.1 tsutsui if (rv != 2) { 450 1.1 tsutsui warnx("Could not find secondary bootstrap `%s' in `%s'", 451 1.1 tsutsui params->stage2, params->filesystem); 452 1.3 apb warnx("(Path must be relative to the file system in `%s')", 453 1.3 apb params->filesystem); 454 1.1 tsutsui return 0; 455 1.1 tsutsui } 456 1.1 tsutsui 457 1.1 tsutsui /* Record the disk blocks of the secondary bootstrap. */ 458 1.1 tsutsui state.maxblk = *maxblk; 459 1.1 tsutsui state.nblk = 0; 460 1.1 tsutsui state.blocks = blocks; 461 1.1 tsutsui rv = ext2fs_find_disk_blocks(params, ino, 462 1.1 tsutsui ext2fs_findstage2_blocks, &state); 463 1.1 tsutsui if (rv == 0) 464 1.1 tsutsui return 0; 465 1.1 tsutsui 466 1.1 tsutsui *maxblk = state.nblk; 467 1.1 tsutsui return 1; 468 1.1 tsutsui } 469