/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Paul Kranenburg.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
int *block_size_p; /* block size var. in prototype image */
int *block_count_p; /* block count var. in prototype image */
/* XXX ondisk32 */
int32_t *block_table; /* block number array in prototype image */
int maxblocknum; /* size of this array */
int
loadblocknums(char *boot, int devfd)
{
int i, fd;
struct stat statbuf;
struct statvfs statvfsbuf;
struct fs *fs;
char *buf;
daddr_t blk, *ap;
struct ufs1_dinode *ip;
int ndb;
/*
* Open 2nd-level boot program and record the block numbers
* it occupies on the filesystem represented by `devfd'.
*/
/* Make sure the (probably new) boot file is on disk. */
sync(); sleep(1);
if (fstatvfs(fd, &statvfsbuf) != 0)
err(1, "statfs: %s", boot);
if (strncmp(statvfsbuf.f_fstypename, "ffs",
sizeof(statvfsbuf.f_fstypename)) &&
strncmp(statvfsbuf.f_fstypename, "ufs",
sizeof(statvfsbuf.f_fstypename))) {
errx(1, "%s: must be on an FFS filesystem", boot);
}
if (fsync(fd) != 0)
err(1, "fsync: %s", boot);
if (fstat(fd, &statbuf) != 0)
err(1, "fstat: %s", boot);
/* Sanity-check super-block. */
if (fs->fs_magic != FS_UFS1_MAGIC)
errx(1, "Bad magic number in superblock, must be UFS1");
if (fs->fs_inopb <= 0)
err(1, "Bad inopb=%d in superblock", fs->fs_inopb);
/* Read inode */
if ((buf = malloc(fs->fs_bsize)) == NULL)
errx(1, "No memory for filesystem block");
/*
* Have the inode. Figure out how many blocks we need.
*/
ndb = howmany(ip->di_size, fs->fs_bsize);
if (ndb > maxblocknum)
errx(1, "Too many blocks");
*block_count_p = ndb;
*block_size_p = fs->fs_bsize;
if (verbose)
printf("Will load %d blocks of size %d each.\n",
ndb, fs->fs_bsize);
/*
* Get the block numbers; we don't handle fragments
*/
ap = ip->di_db;
for (i = 0; i < UFS_NDADDR && *ap && ndb; i++, ap++, ndb--) {
blk = FFS_FSBTODB(fs, *ap);
if (verbose)
printf("%d: %d\n", i, blk);
block_table[i] = blk;
}
if (ndb == 0)
return 0;
/*
* Just one level of indirections; there isn't much room
* for more in the 1st-level bootblocks anyway.
*/
blk = FFS_FSBTODB(fs, ip->di_ib[0]);
devread(devfd, buf, blk, fs->fs_bsize, "indirect block");
/* XXX ondisk32 */
ap = (int32_t *)buf;
for (; i < FFS_NINDIR(fs) && *ap && ndb; i++, ap++, ndb--) {
blk = FFS_FSBTODB(fs, *ap);
if (verbose)
printf("%d: %d\n", i, blk);
block_table[i] = blk;
}