f_mount()源码:
/*-----------------------------------------------------------------------*/
/* Mount/Unmount a Logical Drive */
/*-----------------------------------------------------------------------*/
FRESULT f_mount (
FATFS* fs, /* Pointer to the filesystem object to be registered (NULL:unmount)*/
const TCHAR* path, /* Logical drive number to be mounted/unmounted */
BYTE opt /* Mount option: 0=Do not mount (delayed mount), 1=Mount immediately */
)
{
FATFS *cfs;
int vol;
FRESULT res;
const TCHAR *rp = path;
/* Get volume ID (logical drive number) */
vol = get_ldnumber(&rp);//获取卷ID:逻辑驱动号
if (vol < 0) return FR_INVALID_DRIVE;
cfs = FatFs[vol]; /* Pointer to the filesystem object of the volume 检测文件系统是否存在*/
if (cfs) { /* Unregister current filesystem object if registered 已挂载过,取消注册 */
FatFs[vol] = 0; /*文件对象指向空指针*/
#if FF_FS_LOCK
clear_share(cfs);/*取消对应卷ID的文件锁*/
#endif
#if FF_FS_REENTRANT /* Discard mutex of the current volume */
ff_mutex_delete(vol);
#endif
cfs->fs_type = 0; /*清除文件类型 Invalidate the filesystem object to be unregistered */
}
if (fs) { /* Register new filesystem object 注册新的文件对象*/
fs->pdrv = LD2PD(vol); /* Volume hosting physical drive 承载物理驱动器的卷号 */
#if FF_FS_REENTRANT /* Create a volume mutex */
fs->ldrv = (BYTE)vol; /* Owner volume ID */
if (!ff_mutex_create(vol)) return FR_INT_ERR;
#if FF_FS_LOCK
if (SysLock == 0) { /* Create a system mutex if needed 线程互斥量*/
if (!ff_mutex_create(FF_VOLUMES)) {
ff_mutex_delete(vol);
return FR_INT_ERR;
}
SysLock = 1; /* System mutex is ready */
}
#endif
#endif
fs->fs_type = 0; /* Invalidate the new filesystem object 新的文件对象 */
FatFs[vol] = fs; /* Register new fs object */
}
if (opt == 0) return FR_OK; /* Do not mount now, it will be mounted in subsequent file functions 后续的文件操作中挂载。*/
res = mount_volume(&path, &fs, 0); /* Force mounted the volume 立即挂载*/
LEAVE_FF(fs, res);
}
mount_volume() 真正开始挂载。
mount_volume()
/*-----------------------------------------------------------------------*/
/* Determine logical drive number and mount the volume if needed */
/*-----------------------------------------------------------------------*/
static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */
const TCHAR** path, /* Pointer to pointer to the path name (drive number) */
FATFS** rfs, /* Pointer to pointer to the found filesystem object */
BYTE mode /* Desiered access mode to check write protection */
)
{
int vol;
FATFS *fs;
DSTATUS stat;
LBA_t bsect;
DWORD tsect, sysect, fasize, nclst, szbfat;
WORD nrsv;
UINT fmt;
/* Get logical drive number */
/*1.解析路径获取逻辑驱动号*/
*rfs = 0;
vol = get_ldnumber(path);
if (vol < 0) return FR_INVALID_DRIVE;/*驱动号从0开始*/
/* Check if the filesystem object is valid or not */
/* 检测文件对象是否存在*/
fs = FatFs[vol]; /* Get pointer to the filesystem object f_mount时创建新的FatFs[voal]指针*/
if (!fs) return FR_NOT_ENABLED; /* Is the filesystem object available? 文件系统是否初始化*/
#if FF_FS_REENTRANT
if (!lock_volume(fs, 1)) return FR_TIMEOUT; /* Lock the volume, and system if needed */
#endif
*rfs = fs; /* Return pointer to the filesystem object */
mode &= (BYTE)~FA_READ; /* Desired access mode, write access or not 是否具有其他权限 */
if (fs->fs_type != 0) { /* If the volume has been mounted 是否已经挂载过 */
stat = disk_status(fs->pdrv);
if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized 物理设备保持已被初始化过*/
if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check write protection if needed 处于保护状态不操作*/
return FR_WRITE_PROTECTED;
}
return FR_OK; /* The filesystem object is already valid 文件对象已挂载,直接返回ok*/
}
}
/* The filesystem object is not valid. */
/* Following code attempts to mount the volume. (find an FAT volume, analyze the BPB and initialize the filesystem object) */
/* 文件系统对象无效。 */
/* 以下代码尝试挂载卷。(查找 FAT 卷,分析 BPB 并初始化文件系统对象) */
/*2.初始化物理设备*/
fs->fs_type = 0; /* Invalidate the filesystem object */
stat = disk_initialize(fs->pdrv); /* Initialize the volume hosting physical drive */
if (stat & STA_NOINIT) { /* Check if the initialization succeeded */
return FR_NOT_READY; /* Failed to initialize due to no medium or hard error 初始化驱动器失败*/
}
if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check disk write protection if needed */
return FR_WRITE_PROTECTED;/*处于保护状态 退出*/
}
#if FF_MAX_SS != FF_MIN_SS /* Get sector size (multiple sector size cfg only) 扇区大小不同 ,更新当前卷id(fs->pdrv)的扇区大小到SS(fs)*/
if (disk_ioctl(fs->pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK) return FR_DISK_ERR;
if (SS(fs) > FF_MAX_SS || SS(fs) < FF_MIN_SS || (SS(fs) & (SS(fs) - 1))) return FR_DISK_ERR;
#endif
/* Find an FAT volume on the hosting drive */
/*3.在承载驱动器上查找 FAT 卷:根据f_mkfs()创建的MBR分区信息,找到VBR区 ,进行检测*/
fmt = find_volume(fs, LD2PT(vol));
if (fmt == 4) return FR_DISK_ERR; /* An error occurred in the disk I/O layer */
if (fmt >= 2) return FR_NO_FILESYSTEM; /* No FAT volume is found 引导分区 无FAT表,表明需要重新格式化*/
bsect = fs->winsect; /* Volume offset in the hosting physical drive */
/* An FAT volume is found (bsect). Following code initializes the filesystem object */
#if FF_FS_EXFAT
if (fmt == 1) {
QWORD maxlba;
DWORD so, cv, bcl, i;
for (i = BPB_ZeroedEx; i < BPB_ZeroedEx + 53 && fs->win[i] == 0; i++) ; /* Check zero filler */
if (i < BPB_ZeroedEx + 53) return FR_NO_FILESYSTEM;
if (ld_word(fs->win + BPB_FSVerEx) != 0x100) return FR_NO_FILESYSTEM; /* Check exFAT version (must be version 1.0) */
if (1 << fs->win[BPB_BytsPerSecEx] != SS(fs)) { /* (BPB_BytsPerSecEx must be equal to the physical sector size) */
return FR_NO_FILESYSTEM;
}
maxlba = ld_qword(fs->win + BPB_TotSecEx) + bsect; /* Last LBA of the volume + 1 */
if (!FF_LBA64 && maxlba >= 0x100000000) return FR_NO_FILESYSTEM; /* (It cannot be accessed in 32-bit LBA) */
fs->fsize = ld_dword(fs->win + BPB_FatSzEx); /* Number of sectors per FAT */
fs->n_fats = fs->win[BPB_NumFATsEx]; /* Number of FATs */
if (fs->n_fats != 1) return FR_NO_FILESYSTEM; /* (Supports only 1 FAT) */
fs->csize = 1 << fs->win[BPB_SecPerClusEx]; /* Cluster size */
if (fs->csize == 0) return FR_NO_FILESYSTEM; /* (Must be 1..32768 sectors) */
nclst = ld_dword(fs->win + BPB_NumClusEx); /* Number of clusters */
if (nclst > MAX_EXFAT) return FR_NO_FILESYSTEM; /* (Too many clusters) */
fs->n_fatent = nclst + 2;
/* Boundaries and Limits */
fs->volbase = bsect;
fs->database = bsect + ld_dword(fs->win + BPB_DataOfsEx);
fs->fatbase = bsect + ld_dword(fs->win + BPB_FatOfsEx);
if (maxlba < (QWORD)fs->database + nclst * fs->csize) return FR_NO_FILESYSTEM; /* (Volume size must not be smaller than the size required) */
fs->dirbase = ld_dword(fs->win + BPB_RootClusEx);
/* Get bitmap location and check if it is contiguous (implementation assumption) */
so = i = 0;
for (;;) { /* Find the bitmap entry in the root directory (in only first cluster) */
if (i == 0) {
if (so >= fs->csize) return FR_NO_FILESYSTEM; /* Not found? */
if (move_window(fs, clst2sect(fs, (DWORD)fs->dirbase) + so) != FR_OK) return FR_DISK_ERR;
so++;
}
if (fs->win[i] == ET_BITMAP) break; /* Is it a bitmap entry? */
i = (i + SZDIRE) % SS(fs); /* Next entry */
}
bcl = ld_dword(fs->win + i + 20); /* Bitmap cluster */
if (bcl < 2 || bcl >= fs->n_fatent) return FR_NO_FILESYSTEM; /* (Wrong cluster#) */
fs->bitbase = fs->database + fs->csize * (bcl - 2); /* Bitmap sector */
for (;;) { /* Check if bitmap is contiguous */
if (move_window(fs, fs->fatbase + bcl / (SS(fs) / 4)) != FR_OK) return FR_DISK_ERR;
cv = ld_dword(fs->win + bcl % (SS(fs) / 4) * 4);
if (cv == 0xFFFFFFFF) break; /* Last link? */
if (cv != ++bcl) return FR_NO_FILESYSTEM; /* Fragmented bitmap? */
}
#if !FF_FS_READONLY
fs->last_clst = fs->free_clst = 0xFFFFFFFF; /* Invalidate cluster allocation information */
fs->fsi_flag = 0; /* Enable to sync PercInUse value in VBR */
#endif
fmt = FS_EXFAT; /* FAT sub-type */
} else
#endif /* FF_FS_EXFAT */
{/* 4. 读取当前卷VBR 分区信息,更新到fs对象*/
/*读取VRB扇区大小,检测与当前卷的扇区大小是否匹配 */
if (ld_word(fs->win + BPB_BytsPerSec) != SS(fs)) return FR_NO_FILESYSTEM; /* (BPB_BytsPerSec must be equal to the physical sector size) */
/*当前卷一个FAT表扇区数*/
fasize = ld_word(fs->win + BPB_FATSz16); /* Number of sectors per FAT */
if (fasize == 0) fasize = ld_dword(fs->win + BPB_FATSz32);/*fasize 无效,读取FAT32*/
fs->fsize = fasize;
fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FATs FAT表数*/
if (fs->n_fats != 1 && fs->n_fats != 2) return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */
fasize *= fs->n_fats; /* Number of sectors for FAT area fat表总扇区数 */
fs->csize = fs->win[BPB_SecPerClus]; /* Cluster size 每簇扇区数*/
if (fs->csize == 0 || (fs->csize & (fs->csize - 1))) return FR_NO_FILESYSTEM; /* (Must be power of 2) */
fs->n_rootdir = ld_word(fs->win + BPB_RootEntCnt); /* Number of root directory entries根目录条目数 */
if (fs->n_rootdir % (SS(fs) / SZDIRE)) return FR_NO_FILESYSTEM; /* (Must be sector aligned) 根目录范围必须是扇区的整数倍*/
tsect = ld_word(fs->win + BPB_TotSec16); /* Number of sectors on the volume 当前卷大小*/
if (tsect == 0) tsect = ld_dword(fs->win + BPB_TotSec32);
nrsv = ld_word(fs->win + BPB_RsvdSecCnt); /* Number of reserved sectors 保留扇区*/
if (nrsv == 0) return FR_NO_FILESYSTEM; /* (Must not be 0) */
/* Determine the FAT sub type 数据区起始偏移扇区 */
sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZDIRE); /* RSV + FAT + DIR */
if (tsect < sysect) return FR_NO_FILESYSTEM; /* (Invalid volume size) */
nclst = (tsect - sysect) / fs->csize; /* 数据区对应的簇数 Number of clusters */
if (nclst == 0) return FR_NO_FILESYSTEM; /* (Invalid volume size) */
fmt = 0;
/*计算出文件类型*/
if (nclst <= MAX_FAT32) fmt = FS_FAT32;
if (nclst <= MAX_FAT16) fmt = FS_FAT16;
if (nclst <= MAX_FAT12) fmt = FS_FAT12;
if (fmt == 0) return FR_NO_FILESYSTEM;
/* Boundaries and Limits */
fs->n_fatent = nclst + 2; /* Number of FAT entries fat包含多少簇号,从2开始。0~1簇为FAT表起始扇区头*/
fs->volbase = bsect; /* 分区起始偏移扇区Volume start sector */
fs->fatbase = bsect + nrsv; /* FAT表起始扇区FAT start sector */
fs->database = bsect + sysect; /* 数据区起始扇区 Data start sector */
if (fmt == FS_FAT32) {
if (ld_word(fs->win + BPB_FSVer32) != 0) return FR_NO_FILESYSTEM; /* (Must be FAT32 revision 0.0) */
if (fs->n_rootdir != 0) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */
fs->dirbase = ld_dword(fs->win + BPB_RootClus32); /* Root directory start cluster */
szbfat = fs->n_fatent * 4; /* (Needed FAT size) */
} else {
if (fs->n_rootdir == 0) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */
fs->dirbase = fs->fatbase + fasize; /* 目录区起始扇区Root directory start sector */
szbfat = (fmt == FS_FAT16) ? /* fat表簇号占用的字节(Needed FAT size) */
fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1);
}
/*校验格式化时的FAT表扇区是否够用*/
if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) return FR_NO_FILESYSTEM; /* (BPB_FATSz must not be less than the size needed) */
#if !FF_FS_READONLY
/* Get FSInfo if available */
fs->last_clst = fs->free_clst = 0xFFFFFFFF; /* Invalidate cluster allocation information */
fs->fsi_flag = 0x80; /* Disable FSInfo by default */
if (fmt == FS_FAT32
&& ld_word(fs->win + BPB_FSInfo32) == 1 /* FAT32: Enable FSInfo feature only if FSInfo sector is next to VBR */
&& move_window(fs, bsect + 1) == FR_OK)
{
fs->fsi_flag = 0;
if ( ld_dword(fs->win + FSI_LeadSig) == 0x41615252 /* Load FSInfo data if available */
&& ld_dword(fs->win + FSI_StrucSig) == 0x61417272
&& ld_dword(fs->win + FSI_TrailSig) == 0xAA550000)
{
#if (FF_FS_NOFSINFO & 1) == 0 /* Get free cluster count if trust it */
fs->free_clst = ld_dword(fs->win + FSI_Free_Count);
#endif
#if (FF_FS_NOFSINFO & 2) == 0 /* Get next free cluster if rtust it */
fs->last_clst = ld_dword(fs->win + FSI_Nxt_Free);
#endif
}
}
#endif /* !FF_FS_READONLY */
}
/*更新文件类型到fs文件对象*/
fs->fs_type = (BYTE)fmt;/* FAT sub-type (the filesystem object gets valid) */
fs->id = ++Fsid; /* Volume mount ID 记录当前卷的挂载ID*/
#if FF_USE_LFN == 1
fs->lfnbuf = LfnBuf; /* Static LFN working buffer */
#if FF_FS_EXFAT
fs->dirbuf = DirBuf; /* Static directory block scratchpad buuffer */
#endif
#endif
#if FF_FS_RPATH != 0
fs->cdir = 0; /* Initialize current directory */
#endif
#if FF_FS_LOCK /* Clear file lock semaphores */
clear_share(fs);
#endif
return FR_OK;
}
调用的其他函数
find_volume()
/* Find an FAT volume */
/* (It supports only generic partitioning rules, MBR, GPT and SFD) */
static UINT find_volume ( /* Returns BS status found in the hosting drive */
FATFS* fs, /* Filesystem object */
UINT part /* Partition to fined = 0:find as SFD and partitions, >0:forced partition number */
)
{
UINT fmt, i;
DWORD mbr_pt[4];
/*参数:0 。检测MBR 引导扇区区是否有效*/
fmt = check_fs(fs, 0); /* Load sector 0 and check if it is an FAT VBR as SFD format 加载扇区0 并检查它是否为 FAT VBR 格式,作为 SFD 格式。”*/
if (fmt != 2 && (fmt >= 3 || part == 0)) return fmt; /* Returns if it is an FAT VBR as auto scan, not a BS or disk error */
/* Sector 0 is not an FAT VBR or forced partition number wants a partition */
#if FF_LBA64
if (fs->win[MBR_Table + PTE_System] == 0xEE) { /* GPT protective MBR? */
DWORD n_ent, v_ent, ofs;
QWORD pt_lba;
if (move_window(fs, 1) != FR_OK) return 4; /* Load GPT header sector (next to MBR) */
if (!test_gpt_header(fs->win)) return 3; /* Check if GPT header is valid */
n_ent = ld_dword(fs->win + GPTH_PtNum); /* Number of entries */
pt_lba = ld_qword(fs->win + GPTH_PtOfs); /* Table location */
for (v_ent = i = 0; i < n_ent; i++) { /* Find FAT partition */
if (move_window(fs, pt_lba + i * SZ_GPTE / SS(fs)) != FR_OK) return 4; /* PT sector */
ofs = i * SZ_GPTE % SS(fs); /* Offset in the sector */
if (!memcmp(fs->win + ofs + GPTE_PtGuid, GUID_MS_Basic, 16)) { /* MS basic data partition? */
v_ent++;
fmt = check_fs(fs, ld_qword(fs->win + ofs + GPTE_FstLba)); /* Load VBR and check status */
if (part == 0 && fmt <= 1) return fmt; /* Auto search (valid FAT volume found first) */
if (part != 0 && v_ent == part) return fmt; /* Forced partition order (regardless of it is valid or not) */
}
}
return 3; /* Not found */
}
#endif
if (FF_MULTI_PARTITION && part > 4) return 3; /* MBR 最多支持4个分区 */
for (i = 0; i < 4; i++) { /* 读取每个分区偏移扇区
*/
mbr_pt[i] = ld_dword(fs->win + MBR_Table + i * SZ_PTE + PTE_StLba);
}
i = part ? part - 1 : 0; /* Table index to find first */
do { /* Find an FAT volume */
/*检测分区VRB 分区信息是否有效*/
fmt = mbr_pt[i] ? check_fs(fs, mbr_pt[i]) : 3; /* Check if the partition is FAT */
} while (part == 0 && fmt >= 2 && ++i < 4);
return fmt;
}
check_fs ()
/*-----------------------------------------------------------------------*/
/* Load a sector and check if it is an FAT VBR */
/*-----------------------------------------------------------------------*/
/* Check what the sector is */
static UINT check_fs ( /* 0:FAT/FAT32 VBR, 1:exFAT VBR, 2:Not FAT and valid BS, 3:Not FAT and invalid BS, 4:Disk error */
FATFS* fs, /* Filesystem object */
LBA_t sect /* Sector to load and check if it is an FAT-VBR or not */
)
{
WORD w, sign;
BYTE b;
fs->wflag = 0; fs->winsect = (LBA_t)0 - 1; /* Invaidate window */
if (move_window(fs, sect) != FR_OK) return 4; /* Load the boot sector 加载引导扇区*/
sign = ld_word(fs->win + BS_55AA);/*引导签名地址:偏移510 data:0xAA55*/
#if FF_FS_EXFAT
if (sign == 0xAA55 && !memcmp(fs->win + BS_JmpBoot, "\xEB\x76\x90" "EXFAT ", 11)) return 1; /* It is an exFAT VBR */
#endif
b = fs->win[BS_JmpBoot];
if (b == 0xEB || b == 0xE9 || b == 0xE8) { /* Valid JumpBoot code? (short jump, near jump or near call) */
if (sign == 0xAA55 && !memcmp(fs->win + BS_FilSysType32, "FAT32 ", 8)) {
return 0; /* It is an FAT32 VBR */
}
/* 早期 MS-DOS 时代创建的 AT 卷缺少 BS_55AA 和 BS_FilSysType,因此 FAT VBR 需要在没有它们的情况下进行识别。 */
w = ld_word(fs->win + BPB_BytsPerSec);
b = fs->win[BPB_SecPerClus];
if ((w & (w - 1)) == 0 && w >= FF_MIN_SS && w <= FF_MAX_SS /* Properness of sector size (512-4096 and 2^n) */
&& b != 0 && (b & (b - 1)) == 0 /* Properness of cluster size (2^n) */
&& ld_word(fs->win + BPB_RsvdSecCnt) != 0 /* Properness of number of reserved sectors (MNBZ) */
&& (UINT)fs->win[BPB_NumFATs] - 1 <= 1 /* Properness of number of FATs (1 or 2) */
&& ld_word(fs->win + BPB_RootEntCnt) != 0 /* Properness of root dir size (MNBZ) */
&& (ld_word(fs->win + BPB_TotSec16) >= 128 || ld_dword(fs->win + BPB_TotSec32) >= 0x10000) /* Properness of volume size (>=128) */
&& ld_word(fs->win + BPB_FATSz16) != 0) { /* Properness of FAT size (MNBZ) */
return 0; /* It can be presumed an FAT VBR */
}
}
return sign == 0xAA55 ? 2 : 3; /* Not an FAT VBR (with valid or invalid BS) */
}