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

📄 fat.c

📁 基于s3c2440的U盘读写程序
💻 C
📖 第 1 页 / 共 3 页
字号:

#include "fat.h"
#include "part.h"
/*
 * Convert a string to lowercase.
 */
static void downcase(char *str)
{
    while (*str != '\0') 
    {
        TOLOWER(*str);
        str++;
    }
}


static  block_dev_desc_t *cur_dev = NULL;
static unsigned long part_offset = 0;
static int cur_part = 1;
#define DOS_PART_TBL_OFFSET	    0x1be
#define DOS_PART_MAGIC_OFFSET	    0x1fe
#define DOS_FS_TYPE_OFFSET	           0x36
int disk_read (__u32 startblock, __u32 getsize, __u8 * bufptr)
{
    startblock += part_offset;
    if (cur_dev == NULL)
    return -1;
    if (cur_dev->block_read) 
    {
        //return cur_dev->block_read (cur_dev->dev, startblock, getsize, (unsigned long *)bufptr);
        //add by wqh for debug
        int i,ret;
        ret=cur_dev->block_read (cur_dev->dev, startblock, getsize, (unsigned long *)bufptr);
        //s_UartPrint("block_read(%d+%d %d)\n",startblock,part_offset,getsize);
        //for(i=0;i<getsize*512;i++)
        //	s_UartPrint("[%05d] : %02x\n",i,bufptr[i]);
        return ret;
    }
    return -1;
}


int
fat_register_device(block_dev_desc_t *dev_desc, int part_no)
{
    unsigned char buffer[SECTOR_SIZE];
    int i,j;
    
    if (!dev_desc->block_read)
    return -1;
    cur_dev=dev_desc;
    /* check if we have a MBR (on floppies we have only a PBR) */
    if (dev_desc->block_read (dev_desc->dev, 0, 1, (ulong *) buffer) != 1) 
    {
        FAT_DPRINT("** Can't read from device %d **\n", dev_desc->dev);
        return -1;
    }
    //add by wqh for debug
    
    FAT_DPRINT("** 11111:block_read (0, 1) **\n");
	for(i=0;i<SECTOR_SIZE;i++)
	{ 
		if(i%0x10==0)
		{
			FAT_DPRINT("[%03x]: ",i);
			//FAT_DPRINT("[%03x]:%02x ", i,buffer[i]);
		}
		FAT_DPRINT("%02x ",buffer[i]);
		if((i+1)%0x10==0&&(i-0xf)>=0)
		{			
			FAT_DPRINT(": ");
			for(j=i-0xf;j<=i;j++)
			{
				if(buffer[j]=='\n')
					FAT_DPRINT(" ");
				else
					FAT_DPRINT("%c ",buffer[j]);
			}
			FAT_DPRINT("\n");
		}
	}

	/*
	MBR(Main Boot Record),按其字面上的理解即为主引导记录区,位于整个硬盘
	的0磁道0柱面1扇区。不过,在总共512字节的主引导扇区中,MBR只占用了其中的
	446个字节(偏移0--偏移1BDH),另外的64个字节(偏移1BEH--偏移1FDH)交给
	了DPT(Disk Partition Table硬盘分区表)(见下表),最后两个字节"55,AA"(
	偏移1FEH- 偏移1FFH)是分区的结束标志。这个整体构成了硬盘的主引导扇区。
    */
	if (buffer[DOS_PART_MAGIC_OFFSET] != 0x55 ||
    buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) 
    {
        /* no signature found */
        return -1;
    }
    
	//if(!strncmp((char *)&buffer[DOS_FS_TYPE_OFFSET],"FAT",3)) 
    //{
        /* ok, we assume we are on a PBR only */
    //    cur_part = 1;
    //    part_offset=0;
    //    FAT_DPRINT("**1-partoffset=%d cur_part=%d**\n",part_offset,cur_part);
    //}
    //else 
    //{
	//alter by simon 2009.10.21
	//这样改的原因是,我发现,行的U盘都可以运行到这里,不行的,就不能运行到这
    if(1)
    {
        disk_partition_t info;
        if(!get_partition_info(dev_desc, part_no, &info)) 
        {
            part_offset = info.start;
            cur_part = part_no;
            FAT_DPRINT("**2-partoffset=%d cur_part=%d**\n",part_offset,cur_part);
        }
        else 
        {
            FAT_DPRINT("** Partition %d not valid on device %d **\n",part_no,dev_desc->dev);
            return -1;
        }
    }
    return 0;
}


/*
 * Get the first occurence of a directory delimiter ('/' or '\') in a string.
 * Return index into string if found, -1 otherwise.
 */
static int
dirdelim(char *str)
{
    char *start = str;
    while (*str != '\0') 
    {
        if (ISDIRDELIM(*str)) return str - start;
        str++;
    }
    return -1;
}


/*
 * Match volume_info fs_type strings.
 * Return 0 on match, -1 otherwise.
 */
static int
compare_sign(char *str1, char *str2)
{
    char *end = str1+SIGNLEN;
    while (str1 != end) 
    {
        if (*str1 != *str2) 
        {
            return -1;
        }
        str1++;
        str2++;
    }
    return 0;
}


/*
 * Extract zero terminated short name from a directory entry.
 */
static void get_name (dir_entry *dirent, char *s_name)
{
    char *ptr;
    memcpy (s_name, dirent->name, 8);
    s_name[8] = '\0';
    ptr = s_name;
    while (*ptr && *ptr != ' ')
    ptr++;
    if (dirent->ext[0] && dirent->ext[0] != ' ') 
    {
        *ptr = '.';
        ptr++;
        memcpy (ptr, dirent->ext, 3);
        ptr[3] = '\0';
        while (*ptr && *ptr != ' ')
        ptr++;
    }
    *ptr = '\0';
    if (*s_name == DELETED_FLAG)
    *s_name = '\0';
    else if (*s_name == aRING)
    *s_name = '?';
    downcase (s_name);
}


/*
 * Get the entry at index 'entry' in a FAT (12/16/32) table.
 * On failure 0x00 is returned.
 */
static __u32
get_fatent(fsdata *mydata, __u32 entry)
{
    __u32 bufnum;
    __u32 offset;
    __u32 ret = 0x00;
    switch (mydata->fatsize) 
    {
    case 32:
        bufnum = entry / FAT32BUFSIZE;
        offset = entry - bufnum * FAT32BUFSIZE;
        break;
    case 16:
        bufnum = entry / FAT16BUFSIZE;
        offset = entry - bufnum * FAT16BUFSIZE;
        break;
    case 12:
        bufnum = entry / FAT12BUFSIZE;
        offset = entry - bufnum * FAT12BUFSIZE;
        break;
    default:
        /* Unsupported FAT size */
        return ret;
    }
    /* Read a new block of FAT entries into the cache. */
    if (bufnum != mydata->fatbufnum) 
    {
        int getsize = FATBUFSIZE/FS_BLOCK_SIZE;
        __u8 *bufptr = mydata->fatbuf;
        __u32 fatlength = mydata->fatlength;
        __u32 startblock = bufnum * FATBUFBLOCKS;
        fatlength *= SECTOR_SIZE;	/* We want it in bytes now */
        startblock += mydata->fat_sect;	/* Offset from start of disk */
        if (getsize > fatlength) getsize = fatlength;
        if (disk_read(startblock, getsize, bufptr) < 0) 
        {
            FAT_DPRINT("Error reading FAT blocks\n");
            return ret;
        }
        mydata->fatbufnum = bufnum;
    }
    /* Get the actual entry from the table */
    switch (mydata->fatsize) 
    {
    case 32:
        ret = FAT2CPU32(((__u32*)mydata->fatbuf)[offset]);
        break;
    case 16:
        ret = FAT2CPU16(((__u16*)mydata->fatbuf)[offset]);
        break;
        case 12: 
        {
            __u32 off16 = (offset*3)/4;
            __u16 val1, val2;
            switch (offset & 0x3) 
            {
            case 0:
                ret = FAT2CPU16(((__u16*)mydata->fatbuf)[off16]);
                ret &= 0xfff;
                break;
            case 1:
                val1 = FAT2CPU16(((__u16*)mydata->fatbuf)[off16]);
                val1 &= 0xf000;
                val2 = FAT2CPU16(((__u16*)mydata->fatbuf)[off16+1]);
                val2 &= 0x00ff;
                ret = (val2 << 4) | (val1 >> 12);
                break;
            case 2:
                val1 = FAT2CPU16(((__u16*)mydata->fatbuf)[off16]);
                val1 &= 0xff00;
                val2 = FAT2CPU16(((__u16*)mydata->fatbuf)[off16+1]);
                val2 &= 0x000f;
                ret = (val2 << 8) | (val1 >> 8);
                break;
            case 3:
                ret = FAT2CPU16(((__u16*)mydata->fatbuf)[off16]);;
                ret = (ret & 0xfff0) >> 4;
                break;
            default:
                break;
            }
        }
        break;
    }
    FAT_DPRINT("ret: %d, offset: %d\n", ret, offset);
    return ret;
}


/*
 * Read at most 'size' bytes from the specified cluster into 'buffer'.
 * Return 0 on success, -1 otherwise.
 */
static int
get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size)
{
    int idx = 0;
    __u32 startsect;
    if (clustnum > 0) 
    {
        startsect = mydata->data_begin + clustnum*mydata->clust_size;
    } 
    else 
    {
        startsect = mydata->rootdir_sect;
    }
    FAT_DPRINT("gc - clustnum: %d, startsect: %d\n", clustnum, startsect);
    if (disk_read(startsect, size/FS_BLOCK_SIZE , buffer) < 0) 
    {
        FAT_DPRINT("Error reading data\n");
        return -1;
    }
    if(size % FS_BLOCK_SIZE) 
    {
        __u8 tmpbuf[FS_BLOCK_SIZE];
        idx= size/FS_BLOCK_SIZE;
        if (disk_read(startsect + idx, 1, tmpbuf) < 0) 
        {
            FAT_DPRINT("Error reading data\n");
            return -1;
        }
        buffer += idx*FS_BLOCK_SIZE;
        memcpy(buffer, tmpbuf, size % FS_BLOCK_SIZE);
        return 0;
    }
    return 0;
}


/*
 * Read at most 'maxsize' bytes from the file associated with 'dentptr'
 * into 'buffer'.
 * Return the number of bytes read or -1 on fatal errors.
 */
static long
get_contents(fsdata *mydata, dir_entry *dentptr, __u8 *buffer,
unsigned long maxsize,unsigned long addr)
{
    unsigned long filesize = FAT2CPU32(dentptr->size), gotsize = 0;
    unsigned int bytesperclust = mydata->clust_size * SECTOR_SIZE;
    __u32 curclust = START(dentptr);
    __u32 endclust, newclust;
    unsigned long actsize;
    unsigned long addroffset=0;
    __u8 tempbuffer[8*1024];
    unsigned long newmaxsize,offset;
    if(addr>=filesize) return 0;
    if(!maxsize)        return 0;
    newmaxsize=addr+maxsize;
    FAT_DPRINT("Filesize: %ld bytes\n", filesize);
    if (newmaxsize > 0 && filesize > newmaxsize) filesize = newmaxsize;
    FAT_DPRINT("Reading: %ld bytes\n", filesize);
    actsize=bytesperclust;
    endclust=curclust;
    FAT_DPRINT("step1: actsize=%d endclust=%d \n",actsize,endclust);
    do 
    {
        /* search for consecutive clusters */
        while(actsize < filesize) 
        {
            FAT_DPRINT("step2: actsize=%d endclust=%d \n",actsize,endclust);
            newclust = get_fatent(mydata, endclust);
            if((newclust -1)!=endclust)
            goto getit;
            if (newclust <= 0x0001 || newclust >= 0xfff0) 
            {
                FAT_DPRINT("curclust: 0x%x\n", newclust);
                FAT_DPRINT("Invalid FAT entry\n");
                return gotsize;
            }
            endclust=newclust;
            actsize+= bytesperclust;
        }
        /* actsize >= file size */
        actsize -= bytesperclust;
        /* get remaining clusters */
        if (get_cluster(mydata, curclust, tempbuffer, (int)actsize) != 0) 
        {
            FAT_ERROR("Error reading cluster\n");
            return -1;
        }
        FAT_DPRINT("step3: actsize=%d endclust=%d \n",actsize,endclust);
        if((addroffset+actsize)>addr)
        {
            offset=0;
            if(addr>addroffset) offset=addr-addroffset;
            memcpy(buffer,tempbuffer+offset,actsize-offset);
            gotsize += (int)(actsize-offset);
            buffer+=actsize-offset;			 
        }
        addroffset+=actsize;
        filesize -= actsize;                      
        actsize= filesize;
        /* get remaining bytes */
        //gotsize += (int)actsize;
        //filesize -= actsize;               		
        //buffer += actsize;
        //actsize= filesize;
        if (get_cluster(mydata, endclust, tempbuffer, (int)actsize) != 0) 
        {
            FAT_ERROR("Error reading cluster\n");
            return -1;
        }
        FAT_DPRINT("step4: actsize=%d endclust=%d \n",actsize,endclust);
        if((addroffset+actsize)>addr)
        {
            offset=0;
            if(addr>addroffset) offset=addr-addroffset;
            memcpy(buffer,tempbuffer+offset,actsize-offset);
            gotsize += (int)(actsize-offset);
            //buffer+=actsize-offset;			 
        }
        //addroffset+=actsize;
        //filesize -= actsize;                      
        //actsize= filesize;
        //gotsize+=actsize;
        return gotsize;
    getit:
        if (get_cluster(mydata, curclust, tempbuffer, (int)actsize) != 0) 
        {
            FAT_ERROR("Error reading cluster\n");

⌨️ 快捷键说明

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