mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
As recommended in http://www.gnu.org/licenses/gpl-howto.en.html. This is the result of: $ git grep -El Mass\|Temple\|Franklin | xargs ./fsf.pl Where fsf.pl is: #!/usr/bin/perl -w -pi.bak -0777 my $repl = 'If not, see <http://www.gnu.org/licenses/>.'; my $br = qr/(?:\s*\n\s*(?:[\*\#]|\/\/|\.\\" )?\s*|\s+)/; my $inwt = qr/[Ii]f${br}not,${br}write${br}(?:to${br})?the${br}Free${br}Software${br}Foundation,(?:${br}Inc\.,)?/; my $mass = qr/675${br}Mass${br}Ave,?${br}Cambridge,?${br}MA${br}02139,?${br}USA,?\.?/; my $franklin = qr/51${br}Franklin${br}St(?:reet)?(?:,${br}| - )Fifth${br}Floor,?${br}Boston,?${br}MA,?${br}02110-1301,?${br}USA,?\.?/; my $temple = qr/59${br}Temple${br}Place(?:,${br}| - )Suite${br}330,?${br}Boston,?${br}MA,?${br}021110?-1307,?${br}USA,?\.?/; s|$inwt$br$mass|$repl|m; s|$inwt$br$franklin|$repl|m; s|$inwt$br$temple|$repl|m; The only remaining mentions of these addresses are in COPYING files which I haven't touched. Some of the changed files are imports from elsewhere, however filtering them out is tricky, I think it is tolerable to have these files be modified here and then perhaps reverted on the next sync, since it's only 1-2 lines and obvious what is going on. Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
278 lines
6.7 KiB
C
278 lines
6.7 KiB
C
/*
|
|
* GRUB -- GRand Unified Bootloader
|
|
* Copyright (C) 2006 Free Software Foundation, Inc.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
/*
|
|
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
|
* Use is subject to license terms.
|
|
*/
|
|
|
|
/* From Solaris usr/src/stand/lib/fs/ufs/ufsops.c */
|
|
|
|
#include <fsimage_grub.h>
|
|
|
|
#include "ufs.h"
|
|
|
|
/* These are the pools of buffers, etc. */
|
|
|
|
#define SUPERBLOCK ((struct fs *)(FSYS_BUF + 0x2000))
|
|
#define INODE ((struct icommon *)(FSYS_BUF + 0x1000))
|
|
#define DIRENT (FSYS_BUF + 0x4000)
|
|
#define MAXBSIZE ((FSYS_BUFLEN - 0x4000) / 2)
|
|
#define INDIRBLK1 ((grub_daddr32_t *)(FSYS_BUF + 0x4000)) /* 2+ indir blk */
|
|
#define INDIRBLK0 ((grub_daddr32_t *)(FSYS_BUF+ 0x4000 + MAXBSIZE)) /* 1st indirect blk */
|
|
|
|
#define indirblk0 (*fsig_int1(ffi))
|
|
#define indirblk1 (*fsig_int2(ffi))
|
|
|
|
static int openi(fsi_file_t *, grub_ino_t);
|
|
static grub_ino_t dlook(fsi_file_t *, grub_ino_t, char *);
|
|
static grub_daddr32_t sbmap(fsi_file_t *, grub_daddr32_t);
|
|
|
|
/* read superblock and check fs magic */
|
|
static int
|
|
ufs_mount(fsi_file_t *ffi, const char *options)
|
|
{
|
|
if (/*! IS_PC_SLICE_TYPE_SOLARIS(current_slice) || */
|
|
!devread(ffi, UFS_SBLOCK, 0, UFS_SBSIZE, (char *)SUPERBLOCK) ||
|
|
SUPERBLOCK->fs_magic != UFS_MAGIC ||
|
|
MAXBSIZE < SUPERBLOCK->fs_bsize)
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
/*
|
|
* searching for a file, if successful, inode will be loaded in INODE
|
|
* The entry point should really be named ufs_open(char *pathname).
|
|
* For now, keep it consistent with the rest of fsys modules.
|
|
*/
|
|
static int
|
|
ufs_dir(fsi_file_t *ffi, char *dirname)
|
|
{
|
|
grub_ino_t inode = ROOTINO; /* start from root */
|
|
char *fname, ch;
|
|
|
|
indirblk0 = indirblk1 = 0;
|
|
|
|
/* skip leading slashes */
|
|
while (*dirname == '/')
|
|
dirname++;
|
|
|
|
while (inode && *dirname && !isspace((uint8_t)*dirname)) {
|
|
if (!openi(ffi, inode))
|
|
return 0;
|
|
|
|
/* parse for next path component */
|
|
fname = dirname;
|
|
while (*dirname && !isspace((uint8_t)*dirname) && *dirname != '/')
|
|
dirname++;
|
|
ch = *dirname;
|
|
*dirname = 0; /* ensure null termination */
|
|
|
|
inode = dlook(ffi, inode, fname);
|
|
*dirname = ch;
|
|
while (*dirname == '/')
|
|
dirname++;
|
|
}
|
|
|
|
/* return 1 only if inode exists and is a regular file */
|
|
if (! openi(ffi, inode))
|
|
return (0);
|
|
filepos = 0;
|
|
filemax = INODE->ic_sizelo;
|
|
return (inode && ((INODE->ic_smode & IFMT) == IFREG));
|
|
}
|
|
|
|
/*
|
|
* This is the high-level read function.
|
|
*/
|
|
static int
|
|
ufs_read(fsi_file_t *ffi, char *buf, int len)
|
|
{
|
|
int off, size, ret = 0, ok;
|
|
grub_daddr32_t lblk, dblk;
|
|
|
|
while (len) {
|
|
off = blkoff(SUPERBLOCK, filepos);
|
|
lblk = lblkno(SUPERBLOCK, filepos);
|
|
size = SUPERBLOCK->fs_bsize;
|
|
size -= off;
|
|
if (size > len)
|
|
size = len;
|
|
|
|
if ((dblk = sbmap(ffi, lblk)) <= 0) {
|
|
/* we are in a file hole, just zero the buf */
|
|
grub_memset(buf, 0, size);
|
|
} else {
|
|
disk_read_func = disk_read_hook;
|
|
ok = devread(ffi, fsbtodb(SUPERBLOCK, dblk),
|
|
off, size, buf);
|
|
disk_read_func = 0;
|
|
if (!ok)
|
|
return 0;
|
|
}
|
|
buf += size;
|
|
len -= size;
|
|
filepos += size;
|
|
ret += size;
|
|
}
|
|
|
|
return (ret);
|
|
}
|
|
|
|
int
|
|
ufs_embed (int *start_sector, int needed_sectors)
|
|
{
|
|
if (needed_sectors > 14)
|
|
return 0;
|
|
|
|
*start_sector = 2;
|
|
return 1;
|
|
}
|
|
|
|
/* read inode and place content in INODE */
|
|
static int
|
|
openi(fsi_file_t *ffi, grub_ino_t inode)
|
|
{
|
|
grub_daddr32_t dblk;
|
|
int off;
|
|
|
|
/* get block and byte offset into the block */
|
|
dblk = fsbtodb(SUPERBLOCK, itod(SUPERBLOCK, inode));
|
|
off = itoo(SUPERBLOCK, inode) * sizeof (struct icommon);
|
|
|
|
return (devread(ffi, dblk, off, sizeof (struct icommon), (char *)INODE));
|
|
}
|
|
|
|
/*
|
|
* Performs fileblock mapping. Convert file block no. to disk block no.
|
|
* Returns 0 when block doesn't exist and <0 when block isn't initialized
|
|
* (i.e belongs to a hole in the file).
|
|
*/
|
|
grub_daddr32_t
|
|
sbmap(fsi_file_t *ffi, grub_daddr32_t bn)
|
|
{
|
|
int level, bound, i, index;
|
|
grub_daddr32_t nb, blkno;
|
|
grub_daddr32_t *db = INODE->ic_db;
|
|
|
|
/* blocks 0..UFS_NDADDR are direct blocks */
|
|
if (bn < UFS_NDADDR) {
|
|
return db[bn];
|
|
}
|
|
|
|
/* determine how many levels of indirection. */
|
|
level = 0;
|
|
bn -= UFS_NDADDR;
|
|
bound = UFS_NINDIR(SUPERBLOCK);
|
|
while (bn >= bound) {
|
|
level++;
|
|
bn -= bound;
|
|
bound *= UFS_NINDIR(SUPERBLOCK);
|
|
}
|
|
if (level >= UFS_NIADDR) /* bn too big */
|
|
return ((grub_daddr32_t)0);
|
|
|
|
/* fetch the first indirect block */
|
|
nb = INODE->ic_ib[level];
|
|
if (nb == 0) {
|
|
return ((grub_daddr32_t)0);
|
|
}
|
|
if (indirblk0 != nb) {
|
|
indirblk0 = 0;
|
|
blkno = fsbtodb(SUPERBLOCK, nb);
|
|
if (!devread(ffi, blkno, 0, SUPERBLOCK->fs_bsize,
|
|
(char *)INDIRBLK0))
|
|
return (0);
|
|
indirblk0 = nb;
|
|
}
|
|
bound /= UFS_NINDIR(SUPERBLOCK);
|
|
index = (bn / bound) % UFS_NINDIR(SUPERBLOCK);
|
|
nb = INDIRBLK0[index];
|
|
|
|
/* fetch through the indirect blocks */
|
|
for (i = 1; i <= level; i++) {
|
|
if (indirblk1 != nb) {
|
|
blkno = fsbtodb(SUPERBLOCK, nb);
|
|
if (!devread(ffi, blkno, 0, SUPERBLOCK->fs_bsize,
|
|
(char *)INDIRBLK1))
|
|
return (0);
|
|
indirblk1 = nb;
|
|
}
|
|
bound /= UFS_NINDIR(SUPERBLOCK);
|
|
index = (bn / bound) % UFS_NINDIR(SUPERBLOCK);
|
|
nb = INDIRBLK1[index];
|
|
if (nb == 0)
|
|
return ((grub_daddr32_t)0);
|
|
}
|
|
|
|
return (nb);
|
|
}
|
|
|
|
/* search directory content for name, return inode number */
|
|
static grub_ino_t
|
|
dlook(fsi_file_t *ffi, grub_ino_t dir_ino, char *name)
|
|
{
|
|
int loc, off;
|
|
grub_daddr32_t lbn, dbn, dblk;
|
|
struct direct *dp;
|
|
|
|
if ((INODE->ic_smode & IFMT) != IFDIR)
|
|
return 0;
|
|
|
|
loc = 0;
|
|
while (loc < INODE->ic_sizelo) {
|
|
/* offset into block */
|
|
off = blkoff(SUPERBLOCK, loc);
|
|
if (off == 0) { /* need to read in a new block */
|
|
/* get logical block number */
|
|
lbn = lblkno(SUPERBLOCK, loc);
|
|
/* resolve indrect blocks */
|
|
dbn = sbmap(ffi, lbn);
|
|
if (dbn == 0)
|
|
return (0);
|
|
|
|
dblk = fsbtodb(SUPERBLOCK, dbn);
|
|
if (!devread(ffi, dblk, 0, SUPERBLOCK->fs_bsize,
|
|
(char *)DIRENT)) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
dp = (struct direct *)(DIRENT + off);
|
|
if (dp->d_ino && substring(name, dp->d_name) == 0)
|
|
return (dp->d_ino);
|
|
loc += dp->d_reclen;
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
fsi_plugin_ops_t *
|
|
fsi_init_plugin(int version, fsi_plugin_t *fp, const char **name)
|
|
{
|
|
static fsig_plugin_ops_t ops = {
|
|
FSIMAGE_PLUGIN_VERSION,
|
|
.fpo_mount = ufs_mount,
|
|
.fpo_dir = ufs_dir,
|
|
.fpo_read = ufs_read
|
|
};
|
|
|
|
*name = "ufs";
|
|
return (fsig_init(fp, &ops));
|
|
}
|