📄 fs_fat32util.c
字号:
void fat_putuint16(ubyte *ptr, uint16 value16){ ubyte *val = (ubyte*)&value16;#ifdef CONFIG_ENDIAN_BIG /* The bytes always have to be swapped if the target is big-endian */ ptr[0] = val[1]; ptr[1] = val[0];#else /* Byte-by-byte transfer is still necessary if the address is un-aligned */ ptr[0] = val[0]; ptr[1] = val[1];#endif}/**************************************************************************** * Name: fat_putuint32 ****************************************************************************/void fat_putuint32(ubyte *ptr, uint32 value32){ uint16 *val = (uint16*)&value32;#ifdef CONFIG_ENDIAN_BIG /* The bytes always have to be swapped if the target is big-endian */ fat_putuint16(&ptr[0], val[2]); fat_putuint16(&ptr[2], val[0]);#else /* Byte-by-byte transfer is still necessary if the address is un-aligned */ fat_putuint16(&ptr[0], val[0]); fat_putuint16(&ptr[2], val[2]);#endif}/**************************************************************************** * Name: fat_semtake ****************************************************************************/void fat_semtake(struct fat_mountpt_s *fs){ /* Take the semaphore (perhaps waiting) */ while (sem_wait(&fs->fs_sem) != 0) { /* The only case that an error should occur here is if * the wait was awakened by a signal. */ ASSERT(*get_errno_ptr() == EINTR); }}/**************************************************************************** * Name: fat_semgive ****************************************************************************/void fat_semgive(struct fat_mountpt_s *fs){ sem_post(&fs->fs_sem);}/**************************************************************************** * Name: fat_systime2fattime * * Desciption: Get the system time convertto a time and and date suitble * for writing into the FAT FS. * * TIME in LS 16-bits: * Bits 0:4 = 2 second count (0-29 representing 0-58 seconds) * Bits 5-10 = minutes (0-59) * Bits 11-15 = hours (0-23) * DATE in MS 16-bits * Bits 0:4 = Day of month (0-31) * Bits 5:8 = Month of year (1-12) * Bits 9:15 = Year from 1980 (0-127 representing 1980-2107) * ****************************************************************************/uint32 fat_systime2fattime(void){#warning "Time not implemented" return 0;}/**************************************************************************** * Name: fat_fattime2systime * * Desciption: Convert FAT data and time to a system time_t * * 16-bit FAT time: * Bits 0:4 = 2 second count (0-29 representing 0-58 seconds) * Bits 5-10 = minutes (0-59) * Bits 11-15 = hours (0-23) * 16-bit FAT date: * Bits 0:4 = Day of month (0-31) * Bits 5:8 = Month of year (1-12) * Bits 9:15 = Year from 1980 (0-127 representing 1980-2107) * ****************************************************************************/time_t fat_fattime2systime(uint16 fattime, uint16 fatdate){#warning "Time not implemented" return 0;}/**************************************************************************** * Name: fat_mount * * Desciption: This function is called only when the mountpoint is first * established. It initializes the mountpoint structure and verifies * that a valid FAT32 filesystem is provided by the block driver. * * The caller should hold the mountpoint semaphore * ****************************************************************************/int fat_mount(struct fat_mountpt_s *fs, boolean writeable){ FAR struct inode *inode; struct geometry geo; int ret; /* Assume that the mount is successful */ fs->fs_mounted = TRUE; /* Check if there is media available */ inode = fs->fs_blkdriver; if (!inode || !inode->u.i_bops || !inode->u.i_bops->geometry || inode->u.i_bops->geometry(inode, &geo) != OK || !geo.geo_available) { ret = -ENODEV; goto errout; } /* Make sure that that the media is write-able (if write access is needed) */ if (writeable && !geo.geo_writeenabled) { ret = -EACCES; goto errout; } /* Save the hardware geometry */ fs->fs_hwsectorsize = geo.geo_sectorsize; fs->fs_hwnsectors = geo.geo_nsectors; /* Allocate a buffer to hold one hardware sector */ fs->fs_buffer = (ubyte*)malloc(fs->fs_hwsectorsize); if (!fs->fs_buffer) { ret = -ENOMEM; goto errout; } /* Search FAT boot record on the drive. First check at sector zero. This * could be either the boot record or a partition that refers to the boot * record. * * First read sector zero. This will be the first access to the drive and a * likely failure point. */ fs->fs_fatbase = 0; ret = fat_hwread(fs, fs->fs_buffer, 0, 1); if (ret < 0) { goto errout_with_buffer; } if (fat_checkbootrecord(fs) != OK) { /* The contents of sector 0 is not a boot record. It could be a * partition, however. Assume it is a partition and get the offset * into the partition table. This table is at offset MBR_TABLE and is * indexed by 16x the partition number. Here we support only * parition 0. */ ubyte *partition = &fs->fs_buffer[MBR_TABLE + 0]; /* Check if the partition exists and, if so, get the bootsector for that * partition and see if we can find the boot record there. */ if (partition[4]) { /* There appears to be a partition, get the sector number of the * partition (LBA) */ fs->fs_fatbase = MBR_GETPARTSECTOR(&partition[8]); /* Read the new candidate boot sector */ ret = fat_hwread(fs, fs->fs_buffer, fs->fs_fatbase, 1); if (ret < 0) { goto errout_with_buffer; } /* Check if this is a boot record */ if (fat_checkbootrecord(fs) != OK) { goto errout_with_buffer; } } } /* We have what appears to be a valid FAT filesystem! Now read the * FSINFO sector (FAT32 only) */ if (fs->fs_type == FSTYPE_FAT32) { ret = fat_checkfsinfo(fs); if (ret != OK) { goto errout_with_buffer; } } /* We did it! */ fdbg("FAT%d:\n", fs->fs_type == 0 ? 12 : fs->fs_type == 1 ? 16 : 32); fdbg("\tHW sector size: %d\n", fs->fs_hwsectorsize); fdbg("\t sectors: %d\n", fs->fs_hwnsectors); fdbg("\tFAT reserved: %d\n", fs->fs_fatresvdseccount); fdbg("\t sectors: %d\n", fs->fs_fattotsec); fdbg("\t start sector: %d\n", fs->fs_fatbase); fdbg("\t root sector: %d\n", fs->fs_rootbase); fdbg("\t root entries: %d\n", fs->fs_rootentcnt); fdbg("\t data sector: %d\n", fs->fs_database); fdbg("\t FSINFO sector: %d\n", fs->fs_fsinfo); fdbg("\t Num FATs: %d\n", fs->fs_fatnumfats); fdbg("\t FAT sectors: %d\n", fs->fs_nfatsects); fdbg("\t sectors/cluster: %d\n", fs->fs_fatsecperclus); fdbg("\t max clusters: %d\n", fs->fs_nclusters); fdbg("\tFSI free count %d\n", fs->fs_fsifreecount); fdbg("\t next free %d\n", fs->fs_fsinextfree); return OK; errout_with_buffer: free(fs->fs_buffer); fs->fs_buffer = 0; errout: fs->fs_mounted = FALSE; return ret;}/**************************************************************************** * Name: fat_checkmount * * Desciption: Check if the mountpoint is still valid. * * The caller should hold the mountpoint semaphore * ****************************************************************************/int fat_checkmount(struct fat_mountpt_s *fs){ /* If the fs_mounted flag is FALSE, then we have already handled the loss * of the mount. */ if (fs && fs->fs_mounted) { struct fat_file_s *file; /* We still think the mount is healthy. Check an see if this is * still the case */ if (fs->fs_blkdriver) { struct inode *inode = fs->fs_blkdriver; if (inode && inode->u.i_bops && inode->u.i_bops->geometry) { struct geometry geo; int errcode = inode->u.i_bops->geometry(inode, &geo); if (errcode == OK && geo.geo_available && !geo.geo_mediachanged) { return OK; } } } /* If we get here, the mount is NOT healthy */ fs->fs_mounted = FALSE; /* Make sure that this is flagged in every opened file */ for (file = fs->fs_head; file; file = file->ff_next) { file->ff_open = FALSE; } } return -ENODEV;}/**************************************************************************** * Name: fat_hwread * * Desciption: Read the specified sector into the sector buffer * ****************************************************************************/int fat_hwread(struct fat_mountpt_s *fs, ubyte *buffer, size_t sector, unsigned int nsectors){ int ret = -ENODEV; if (fs && fs->fs_blkdriver ) { struct inode *inode = fs->fs_blkdriver; if (inode && inode->u.i_bops && inode->u.i_bops->read) { ssize_t nSectorsRead = inode->u.i_bops->read(inode, buffer, sector, nsectors); if (nSectorsRead == nsectors) { ret = OK; } else if (nSectorsRead < 0) { ret = nSectorsRead; } } } return ret;}/**************************************************************************** * Name: fat_hwwrite * * Desciption: Write the sector buffer to the specified sector * ****************************************************************************/int fat_hwwrite(struct fat_mountpt_s *fs, ubyte *buffer, size_t sector, unsigned int nsectors){ int ret = -ENODEV; if (fs && fs->fs_blkdriver ) { struct inode *inode = fs->fs_blkdriver; if (inode && inode->u.i_bops && inode->u.i_bops->write) { ssize_t nSectorsWritten = inode->u.i_bops->write(inode, buffer, sector, nsectors); if (nSectorsWritten == nsectors) { ret = OK; } else if (nSectorsWritten < 0) { ret = nSectorsWritten; } } } return ret;}/**************************************************************************** * Name: fat_cluster2sector * * Desciption: Convert a cluster number to a start sector number * ****************************************************************************/ssize_t fat_cluster2sector(struct fat_mountpt_s *fs, uint32 cluster ){ cluster -= 2; if (cluster >= fs->fs_nclusters - 2) { return -EINVAL; } return cluster * fs->fs_fatsecperclus + fs->fs_database;}/**************************************************************************** * Name: fat_getcluster * * Desciption: Get the cluster start sector into the FAT. * * Return: <0: error, 0:cluster unassigned, >=0: start sector of cluster * ****************************************************************************/ssize_t fat_getcluster(struct fat_mountpt_s *fs, uint32 clusterno){ /* Verify that the cluster number is within range */ if (clusterno >= 2 && clusterno < fs->fs_nclusters) { /* Okay.. Read the next cluster from the FAT. The way we will do * this depends on the type of FAT filesystm we are dealing with. */ switch (fs->fs_type) { case FSTYPE_FAT12 : { size_t fatsector; unsigned int fatoffset; unsigned int startsector; unsigned int fatindex; /* FAT12 is more complex because it has 12-bits (1.5 bytes) * per FAT entry. Get the offset to the first byte: */ fatoffset = (clusterno * 3) / 2; fatsector = fs->fs_fatbase + SEC_NSECTORS(fs, fatoffset); /* Read the sector at this offset */ if (fat_fscacheread(fs, fatsector) < 0) { /* Read error */ break; } /* Get the first, LS byte of the cluster from the FAT */ fatindex = fatoffset & SEC_NDXMASK(fs); startsector = fs->fs_buffer[fatindex]; /* With FAT12, the second byte of the cluster number may lie in * a different sector than the first byte. */ fatindex++; if (fatindex >= fs->fs_hwsectorsize) { fatsector++; fatindex = 0; if (fat_fscacheread(fs, fatsector) < 0) { /* Read error */ break; } } /* Get the second, MS byte of the cluster for 16-bits. The * does not depend on the endian-ness of the target, but only * on the fact that the byte stream is little-endian. */ startsector |= (unsigned int)fs->fs_buffer[fatindex] << 8; /* Now, pick out the correct 12 bit cluster start sector value */ if ((clusterno & 1) != 0) { /* Odd.. take the MS 12-bits */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -