⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fsys_ufs.c

📁 open source bios with linux platform, very good and can be reused.
💻 C
字号:
/* *  GRUB  --  GRand Unified Bootloader *  Copyright (c) 2000, 2001  Free Software Foundation, Inc. *  Copyright (c) 2005  Rink Springer * *  This file is based on FreeBSD 5.4-RELEASE's /sys/boot/common/ufsread.c, *  and has some minor patches so it'll work with Cromwell/GRUB. * *//*- * Copyright (c) 2002 McAfee, Inc. * All rights reserved. * * This software was developed for the FreeBSD Project by Marshall * Kirk McKusick and McAfee Research,, the Security Research Division of * McAfee, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as * part of the DARPA CHATS research program * * 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 AUTHOR 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 AUTHOR 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. *//*- * Copyright (c) 1998 Robert Nordier * All rights reserved. * * Redistribution and use in source and binary forms are freely * permitted provided that the above copyright notice and this * paragraph and the following disclaimer are duplicated in all * such forms. * * This software is provided "AS IS" and without any express or * implied warranties, including, without limitation, the implied * warranties of merchantability and fitness for a particular * purpose. */#ifdef FSYS_UFS#include <stdint.h>#include "shared.h"#include "filesys.h"#include "ufs_dinode.h"#include "ufs_fs.h"#ifdef __i386__/* XXX: Revert to old (broken for over 1.5Tb filesystems) version of cgbase   (see sys/ufs/ffs/fs.h rev 1.39) so that i386 boot loader (boot2) can   support both UFS1 and UFS2 again. */#undef cgbase#define cgbase(fs, c)   ((ufs2_daddr_t)((fs)->fs_fpg * (c)))#endif/* * We use 4k `virtual' blocks for filesystem data, whatever the actual * filesystem block size. FFS blocks are always a multiple of 4k. */#define VBLKSHIFT	12#define VBLKSIZE	(1 << VBLKSHIFT)#define VBLKMASK	(VBLKSIZE - 1)#define DBPERVBLK	(VBLKSIZE / DEV_BSIZE)#define INDIRPERVBLK(fs) (NINDIR(fs) / ((fs)->fs_bsize >> VBLKSHIFT))#define IPERVBLK(fs)	(INOPB(fs) / ((fs)->fs_bsize >> VBLKSHIFT))#define INO_TO_VBA(fs, ipervblk, x) \    (fsbtodb(fs, cgimin(fs, ino_to_cg(fs, x))) + \    (((x) % (fs)->fs_ipg) / (ipervblk) * DBPERVBLK))#define INO_TO_VBO(ipervblk, x) ((x) % ipervblk)#define FS_TO_VBA(fs, fsb, off) (fsbtodb(fs, fsb) + \    ((off) / VBLKSIZE) * DBPERVBLK)#define FS_TO_VBO(fs, fsb, off) ((off) & VBLKMASK)/* Buffers that must not span a 64k boundary. */struct dmadat {	char blkbuf[VBLKSIZE];	/* filesystem blocks */	char indbuf[VBLKSIZE];	/* indir blocks */	char sbbuf[SBLOCKSIZE];	/* superblock */	char secbuf[DEV_BSIZE];	/* for MBR/disklabel */};struct dmadat *dmadat = (struct dmadat*)FSYS_BUF;#define SUPERBLOCK ((struct fs*)dmadat->sbbuf)ino_t lookup(const char *);ssize_t fsread(ino_t, void *, size_t);static int dsk_meta;static uint32_t fs_off;static ino_t cur_ino = 0;static inline intdskread (void* buf, unsigned lba, unsigned nblk){	return !devread (lba, 0, nblk * DEV_BSIZE, buf) ? -1 : 0;}#if defined(UFS2_ONLY)#define DIP(field) dp2.field#elif defined(UFS1_ONLY)#define DIP(field) dp1.field#else#define DIP(field) fs->fs_magic == FS_UFS1_MAGIC ? dp1.field : dp2.field#endifstatic __inline intfsfind(const char *name, ino_t * ino){	char buf[DEV_BSIZE];	struct ufs_dirent *d;	char *s;	ssize_t n;#ifndef UFS2_ONLY	static struct ufs1_dinode dp1;#endif#ifndef UFS1_ONLY	static struct ufs2_dinode dp2;#endif	char* blkbuf = dmadat->blkbuf;	struct fs* fs = (struct fs *)dmadat->sbbuf;	fs_off = 0;	while ((n = fsread(*ino, buf, DEV_BSIZE)) > 0)		for (s = buf; s < buf + DEV_BSIZE;) {			d = (void *)s;			if (!strcmp(name, d->d_name)) {				*ino = d->d_fileno;				/* below is for grub, which wants the file size				 */				n = IPERVBLK(fs);				if (dskread(blkbuf, INO_TO_VBA(fs, n, (*ino)), DBPERVBLK))					return -1;				n = INO_TO_VBO(n, (*ino));#if defined(UFS1_ONLY)				dp1 = ((struct ufs1_dinode *)blkbuf)[n];#elif defined(UFS2_ONLY)				dp2 = ((struct ufs2_dinode *)blkbuf)[n];#else				if (fs->fs_magic == FS_UFS1_MAGIC)					dp1 = ((struct ufs1_dinode *)blkbuf)[n];				else					dp2 = ((struct ufs2_dinode *)blkbuf)[n];#endif				filemax = DIP(di_size);				return d->d_type;			}			s += d->d_reclen;		}	return 0;}ino_tlookup(const char *path){	char name[MAXNAMLEN + 1];	const char *s;	ino_t ino;	ssize_t n;	int dt;	ino = ROOTINO;	dt = DT_DIR;	name[0] = '/';	name[1] = '\0';	for (;;) {		if (*path == '/')			path++;		if (!*path)			break;		for (s = path; *s && *s != '/'; s++);		if ((n = s - path) > MAXNAMLEN)			return 0;		memcpy(name, path, n);		name[n] = 0;		if (dt != DT_DIR) {			printk("%s: not a directory.\n", name);			return (0);		}		if ((dt = fsfind(name, &ino)) <= 0)			break;		path = s;	}	return dt == DT_REG ? ino : 0;}/* * Possible superblock locations ordered from most to least likely. */static const int sblock_try[] = SBLOCKSEARCH;ssize_tfsread(ino_t inode, void *buf, size_t nbyte){#ifndef UFS2_ONLY	static struct ufs1_dinode dp1;#endif#ifndef UFS1_ONLY	static struct ufs2_dinode dp2;#endif	static ino_t inomap;	char *blkbuf;	void *indbuf;	struct fs *fs;	char *s;	size_t n, nb, size, off, vboff;	ufs_lbn_t lbn;	ufs2_daddr_t addr, vbaddr;	static ufs2_daddr_t blkmap, indmap;	unsigned int u;	blkbuf = dmadat->blkbuf;	indbuf = dmadat->indbuf;	fs = (struct fs *)dmadat->sbbuf;	if (!dsk_meta) {		inomap = 0;		for (n = 0; sblock_try[n] != -1; n++) {			if (dskread(fs, sblock_try[n] / DEV_BSIZE,			    SBLOCKSIZE / DEV_BSIZE))				return -1;			if ((#if defined(UFS1_ONLY)			     fs->fs_magic == FS_UFS1_MAGIC#elif defined(UFS2_ONLY)			    (fs->fs_magic == FS_UFS2_MAGIC &&			    fs->fs_sblockloc == sblock_try[n])#else			     fs->fs_magic == FS_UFS1_MAGIC ||			    (fs->fs_magic == FS_UFS2_MAGIC &&			    fs->fs_sblockloc == sblock_try[n])#endif			    ) &&			    fs->fs_bsize <= MAXBSIZE &&			    fs->fs_bsize >= sizeof(struct fs))				break;		}		if (sblock_try[n] == -1) {			printk("Not ufs\n");			return -1;		}		dsk_meta++;	}	if (!inode)		return 0;	if (inomap != inode) {		n = IPERVBLK(fs);		if (dskread(blkbuf, INO_TO_VBA(fs, n, inode), DBPERVBLK))			return -1;		n = INO_TO_VBO(n, inode);#if defined(UFS1_ONLY)		dp1 = ((struct ufs1_dinode *)blkbuf)[n];#elif defined(UFS2_ONLY)		dp2 = ((struct ufs2_dinode *)blkbuf)[n];#else		if (fs->fs_magic == FS_UFS1_MAGIC)			dp1 = ((struct ufs1_dinode *)blkbuf)[n];		else			dp2 = ((struct ufs2_dinode *)blkbuf)[n];#endif		inomap = inode;		fs_off = 0;		blkmap = indmap = 0;	}	s = buf;	size = DIP(di_size);	n = size - fs_off;	if (nbyte > n)		nbyte = n;	nb = nbyte;	while (nb) {		lbn = lblkno(fs, fs_off);		off = blkoff(fs, fs_off);		if (lbn < NDADDR) {			addr = DIP(di_db[lbn]);		} else if (lbn < NDADDR + NINDIR(fs)) {			n = INDIRPERVBLK(fs);			addr = DIP(di_ib[0]);			u = (unsigned int)(lbn - NDADDR) / (n * DBPERVBLK);			vbaddr = fsbtodb(fs, addr) + u;			if (indmap != vbaddr) {				if (dskread(indbuf, vbaddr, DBPERVBLK))					return -1;				indmap = vbaddr;			}			n = (lbn - NDADDR) & (n - 1);#if defined(UFS1_ONLY)			addr = ((ufs1_daddr_t *)indbuf)[n];#elif defined(UFS2_ONLY)			addr = ((ufs2_daddr_t *)indbuf)[n];#else			if (fs->fs_magic == FS_UFS1_MAGIC)				addr = ((ufs1_daddr_t *)indbuf)[n];			else				addr = ((ufs2_daddr_t *)indbuf)[n];#endif		} else {			return -1;		}		vbaddr = fsbtodb(fs, addr) + (off >> VBLKSHIFT) * DBPERVBLK;		vboff = off & VBLKMASK;		n = sblksize(fs, size, lbn) - (off & ~VBLKMASK);		if (n > VBLKSIZE)			n = VBLKSIZE;		if (blkmap != vbaddr) {			if (dskread(blkbuf, vbaddr, n >> DEV_BSHIFT))				return -1;			blkmap = vbaddr;		}		n -= vboff;		if (n > nb)			n = nb;		memcpy(s, blkbuf + vboff, n);		s += n;		fs_off += n;		nb -= n;	}	return nbyte;}intufs_mount (void){  int i, retval = 0;  /*   * We don't care about stuff being in disklabels or not. If the magic   * matches, we're good to go.   */  for (i = 0; sblock_try[i] != -1; ++i)  {	if (! (part_length < (sblock_try[i] + (SBLOCKSIZE / DEV_BSIZE))		 || ! devread (0, sblock_try[i], SBLOCKSIZE, (char *) SUPERBLOCK)))	    {		if (#if defined(UFS1_ONLY)		     SUPERBLOCK->fs_magic == FS_UFS1_MAGIC#elif defined(UFS2_ONLY)		    (SUPERBLOCK->fs_magic == FS_UFS2_MAGIC &&		     SUPERBLOCK->fs_sblockloc == sblock_try[i])#else		     SUPERBLOCK->fs_magic == FS_UFS1_MAGIC ||		    (SUPERBLOCK->fs_magic == FS_UFS2_MAGIC &&		     SUPERBLOCK->fs_sblockloc == sblock_try[i])#endif		) {			retval = 1; break;		}	    }  }  return retval;}intufs_read (char *buf, int len){	return fsread(cur_ino, buf, len);}intufs_dir (char *dirname){	cur_ino = lookup(dirname);	return cur_ino & 0xffffffff;}intufs_embed (int* start_sector, int needed_sectors){	/* TODO; unused by Cromwell */	return 0;}#endif /* FSYS_UFS */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -