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

📄 fatfs.c

📁 MIPS处理器的bootloader,龙芯就是用的修改过的PMON2
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: fatfs.c,v 1.1 2003/07/08 20:57:50 pefo Exp $ *//* * Copyright (c) 2003 Opsycon AB (www.opsycon.se) * Copyright (c) 2003 Patrik Lindergren (www.lindergren.com) *  * 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. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by Opsycon AB, Sweden. *	This product includes software developed by Patrik Lindergren. * 4. The name of the author may not be used to endorse or promote products *    derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. * */#include <stdio.h>#include <string.h>#include <termio.h>#include <fcntl.h>#include <file.h>#include <ctype.h>#include <ramfile.h>#include <sys/unistd.h>#include <stdlib.h>#include <unistd.h>#undef _KERNEL#include <errno.h>#include <pmon.h>#include <file.h>#include "fat.h"extern int errno;int   fat_open (int, const char *, int, int);int   fat_close (int);int   fat_read (int, void *, size_t);int   fat_write (int, const void *, size_t);off_t fat_lseek (int, off_t, int);/* * Internal */int fat_init(int , struct fat_sc *, int);int fat_dump_fatsc(struct fat_sc *);u_int32_t getFatEntry(struct fat_sc *, int );int readsector(struct fat_sc *, int , int , u_int8_t *);int parseShortFilename(struct direntry *, char *);int fat_getChain(struct fat_sc *, int , struct fatchain *);int getSectorIndex(struct fat_sc *, struct fatchain *, int );int fat_getPartition(struct fat_sc *, int );int fat_findfile(struct fat_sc *, char *);int fat_subdirscan(struct fat_sc *, char *, struct fatchain *);int fat_dump_fatsc(struct fat_sc *);int fat_dump_fileentry(struct fat_sc *);u_int8_t shortNameChkSum(u_int8_t *);int fat_parseDirEntries(int ,struct fat_fileentry *);/* * Supported paths: *	/dev/fat/disk@wd0/file *	/dev/fat/ram@address/file * */intfat_open(int fd, const char *path, int flags, int mode){	char dpath[64];	char dpath2[64];	const char *opath;	char *filename;	struct fat_sc *fsc;	int fd2;	int res;	/*  Try to get to the physical device */	opath = path;	if (strncmp(opath, "/dev/", 5) == 0)		opath += 5;	if (strncmp(opath, "fat/", 4) == 0)		opath += 4;	/* There has to be at least one more component after the devicename */	if (strchr(opath, '/') == NULL) {		errno = ENOENT;		return (-1);	}	/* Dig out the device name */	strncpy(dpath2, opath, sizeof(dpath2));	*(strchr(dpath2, '/')) = '\0';	sprintf(dpath, "/dev/%s", dpath2);	/* Set opath to point at the isolated filname path */	filename = strchr(opath, '/') + 1;	fsc = (struct fat_sc *)malloc(sizeof(struct fat_sc));	if (fsc == NULL) {		errno = ENOMEM;		return (-1);	}	/*	 * Need to mark existing fd to valid otherwise we can't	 * open the new device.	 */	_file[fd].valid = 1;	/* Try to open the physical device */	fd2 = open(dpath, flags, mode);	if (fd2 < 0) {		free(fsc);		errno = EINVAL;		_file[fd].valid = 0;		return (-1);	}	if (fat_init(fd2, fsc, 0) == 0) {		close(fd2);		free(fsc);		errno = EINVAL;		_file[fd].valid = 0;		return (-1);	}	res = fat_findfile(fsc, filename);	if (res <= 0) {		close(fd2);		free(fsc);		errno = EINVAL;		_file[fd].valid = 0;		return (-1);	}	fsc->LastSector = -1;	/* No valid sector in sector buffer */	_file[fd].posn = 0;	_file[fd].data = (void *)fsc;	return (fd);}intfat_close(int fd){	struct fat_sc *fsc;	fsc = (struct fat_sc *)_file[fd].data;	if (fsc->file.Chain.entries) {		free(fsc->file.Chain.entries);		fsc->file.Chain.entries = NULL;	}	fsc->file.Chain.count = 0;	close(fsc->fd);	free(fsc);	return (0);}intfat_read(int fd, void *buf, size_t len){	struct fat_sc *fsc;	int sectorIndex;	int totalcopy = 0;	int origpos;	int copylen;	int offset;	int sector;	int res = 0;	fsc = (struct fat_sc *)_file[fd].data;	origpos = _file[fd].posn;	/*	 * Check file size bounder	 */	if (_file[fd].posn >= fsc->file.FileSize) {	        return (-1);	}	if ((_file[fd].posn + len) > fsc->file.FileSize) {		len = fsc->file.FileSize - _file[fd].posn;	}	while (len) {		offset = _file[fd].posn % SECTORSIZE;		sectorIndex = _file[fd].posn / SECTORSIZE;				sector = getSectorIndex(fsc, &fsc->file.Chain, sectorIndex);		copylen = len;		if (copylen > (SECTORSIZE - offset)) {			copylen = (SECTORSIZE - offset);		}		if (sector != fsc->LastSector) {			res = readsector(fsc, sector, 1, fsc->LastSectorBuffer);			if (res < 0)				break;			fsc->LastSector = sector;		}				memcpy(buf, &fsc->LastSectorBuffer[offset], copylen);				buf += copylen;		_file[fd].posn += copylen;		len -= copylen;		totalcopy += copylen;	}		if (res < 0) {		_file[fd].posn = origpos;		return res;			}	return totalcopy;}intfat_write(int fd, const void *start, size_t size){	errno = EROFS;	return EROFS;}off_tfat_lseek(int fd, off_t offset, int whence){	struct fat_sc *fsc;	fsc = (struct fat_sc *)_file[fd].data;	switch (whence) {		case SEEK_SET:			_file[fd].posn = offset;			break;		case SEEK_CUR:			_file[fd].posn += offset;			break;		case SEEK_END:			_file[fd].posn = fsc->file.FileSize + offset;			break;		default:			errno = EINVAL;			return (-1);	}	return (_file[fd].posn);}/* *  File system registration info. */static FileSystem fatfs = {        "fat", FS_FILE,        fat_open,        fat_read,        fat_write,        fat_lseek,        fat_close,	NULL};static void init_fs(void) __attribute__ ((constructor));static voidinit_fs(){	filefs_init(&fatfs);}/*************************************************************************************************** * Internal function ***************************************************************************************************/int getSectorIndex(struct fat_sc *fsc, struct fatchain * chain, int index){	int clusterIndex;	int sectorIndex;	int sector;	int entry;	clusterIndex = index / fsc->SecPerClust;	sectorIndex = index % fsc->SecPerClust;	if (clusterIndex < chain->count)		entry = chain->entries[clusterIndex];	else		entry = -1;	sector = fsc->DataSectorBase + (entry - 2) * fsc->SecPerClust + sectorIndex;	return (sector);}int fat_getPartition(struct fat_sc *fsc, int partition){	u_int8_t buffer[SECTORSIZE];	struct mbr_t *mbr;	struct bpb_t *bpb;	int i;		fsc->PartitionStart = 0;	if (readsector(fsc, 0, 1, buffer) == 0)		return (0);	/*	 * Check if there exists a MBR	 */	bpb = (struct bpb_t *)buffer;	#if 0	if ((bpb->bpbBytesPerSec == 512) &&	    ((bpb->efat16.bsBootSig == BPB_SIG_VALUE1) ||	     (bpb->efat16.bsBootSig == BPB_SIG_VALUE2))) {		/*		 * No MBR where found		 */		return (1);	}#endif	if ((bpb->bpbBytesPerSec == 512) &&	    (bpb->bpbResSectors >= 1) &&	    ((bpb->bpbMedia & 0xf0) == 0xf0)) {		/*		 * No MBR where found		 */		return (1);	}	/*	 * Find the active partition	 */	mbr = (struct mbr_t *)buffer;	for (i = 0; i < PART_SIZE; i++) {		if ((mbr->partition[i].bootid == PART_BOOTID_ACTIVE) &&		    ((mbr->partition[i].systid == PART_TYPE_FAT12) ||		     (mbr->partition[i].systid == PART_TYPE_FAT16) ||		     (mbr->partition[i].systid == PART_TYPE_FAT16BIG))) {			break;		}	}	if (i == PART_SIZE) {		return (0);	}	fsc->PartitionStart = letoh32(mbr->partition[i].relsect);	return (1);}int fat_init(int fd, struct fat_sc *fsc, int partition){	unsigned char bootsector[SECTORSIZE];	struct bpb_t *bpb;	bzero(fsc, sizeof(struct fat_sc));	fsc->fd = fd;	/*	 * Check for partition	 */	fat_getPartition(fsc, partition);	/*	 * Init BPB	 */	if (readsector(fsc, 0, 1, bootsector) == 0) {		fprintf(stderr, "Can't read from %d bytes\n", SECTORSIZE);		return (-1);	}	bpb = (struct bpb_t *)bootsector;		/*	 * Init Fat Software structure	 */	fsc->RootDirEnts = letoh16(bpb->bpbRootDirEnts);	fsc->BytesPerSec = letoh16(bpb->bpbBytesPerSec);	fsc->ResSectors = letoh16(bpb->bpbResSectors);	fsc->SecPerClust = bpb->bpbSecPerClust;	fsc->NumFATs = bpb->bpbFATs;	fsc->FatCacheNum = -1;	if (bpb->bpbFATsecs != 0)		fsc->FATsecs = (u_int32_t)letoh16(bpb->bpbFATsecs);	else		fsc->FATsecs = letoh32(bpb->efat32.bpbFATSz32);	if (bpb->bpbSectors != 0)		fsc->TotalSectors = (u_int32_t)letoh16(bpb->bpbSectors);	else		fsc->TotalSectors = letoh32(bpb->bpbHugeSectors);	fsc->RootDirSectors = ((fsc->RootDirEnts * 32) + (fsc->BytesPerSec - 1)) / fsc->BytesPerSec;	fsc->DataSectors = fsc->TotalSectors - (fsc->ResSectors + (fsc->NumFATs * fsc->FATsecs) + fsc->RootDirSectors);	fsc->DataSectorBase = fsc->ResSectors + (fsc->NumFATs * fsc->FATsecs) + fsc->RootDirSectors;	fsc->CountOfClusters = fsc->DataSectors / fsc->SecPerClust;	fsc->ClusterSize = fsc->BytesPerSec * fsc->SecPerClust;	fsc->FirstRootDirSecNum = fsc->ResSectors + (fsc->NumFATs * fsc->FATsecs);	if (fsc->CountOfClusters < 4085) {		/* Volume is FAT12 */		fsc->FatType = TYPE_FAT12;	} else if (fsc->CountOfClusters < 65525) {		/* Volume is FAT16 */		fsc->FatType = TYPE_FAT16;	} else {

⌨️ 快捷键说明

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