FATFS文件系统之f_mkfs()

关于FAT文件系统的基本理论,可以参考作者ZC·Shou的博客:
FatFs 之一 R0.13c版源码目录文件、函数、全配置项详解及移植说明

FatFs 之二 路径规则、字符编码、编码页、卷管理详解[添加链接描述]

FatFs 之三 FAT文件系统基础、FAT 数据格式、引导、编码

接下来对文件类型FAT12进行解析,其他相关配置默认不开启。

f_mkfs() FAT12格式化包含如下几个部分:

区域名称	                 作用	                                位置	        大小
MBR(主引导记录)	磁盘分区表,定义分区信息	                    磁盘的第一个扇区	    1 扇区
VRB    包含引导扇区、文件系统元数据	                分区的起始扇区	    由   BPB_ResvdSecCnt 定义
FAT 表	            记录簇的分配状态和簇链	                    保留区之后	        由 BPB_FATSz 定义(每个FAT表大小)
根目录	            存储根目录下的文件和子目录条目(仅 FAT12/16)	FAT 表之后	        固定大小(FAT32 无固定根目录)
数据区	            存储文件和目录的实际数据	根目录或 FAT 表之后	剩余所有扇区

f_mkfs()源码

FRESULT f_mkfs (
	const TCHAR* path,		/* Logical drive number */
	const MKFS_PARM* opt,	/* Format options */
	void* work,				/* Pointer to working buffer (null: use len bytes of heap memory) */
	UINT len				/* Size of working buffer [byte] */
)
{
	static const WORD cst[] = {1, 4, 16, 64, 256, 512, 0};	/* Cluster size boundary for FAT volume (4K sector unit)FAT卷的簇大小边界(4K扇区单位) */
	static const WORD cst32[] = {1, 2, 4, 8, 16, 32, 0};	/* Cluster size boundary for FAT32 volume (128K sector unit)FAT32 卷的簇大小边界(128K 扇区单位) */
	static const MKFS_PARM defopt = {FM_ANY, 0, 0, 0, 0};	/* Default parameter */
	BYTE fsopt, fsty, sys, pdrv, ipart;
	BYTE *buf;
	BYTE *pte;
	WORD ss;	/* Sector size */
	DWORD sz_buf, sz_blk, n_clst, pau, nsect, n, vsn;
	LBA_t sz_vol, b_vol, b_fat, b_data;		/* Volume size, base LBA of volume, base LBA of FAT and base LBA of data */
	LBA_t sect, lba[2];
	DWORD sz_rsv, sz_fat, sz_dir, sz_au;	/* Size of reserved area, FAT area, directry area, data area and cluster */
	UINT n_fat, n_root, i;					/* Number of FATs, number of roor directory entries and some index */
	int vol;
	DSTATUS ds;
	FRESULT res;


	/* Check mounted drive and clear work area */
	/*获取逻辑驱动卷ID,数字:0~9。并获取卷ID后面的段'\'*/
	vol = get_ldnumber(&path);					/* Get target logical drive 获取卷ID*/
	if (vol < 0) return FR_INVALID_DRIVE;
	
	if (FatFs[vol]) FatFs[vol]->fs_type = 0;	/* Clear the fs object if mounted  已挂载过,清除文件类型*/
	pdrv = LD2PD(vol);		/* Hosting physical drive   获取逻辑驱动号*/
	ipart = LD2PT(vol);		/* Hosting partition (0:create as new, 1..:existing partition)   默认0自动分区创建*/

	/* Initialize the hosting physical drive */
	ds = disk_initialize(pdrv);/*初始化物理磁盘*/
	if (ds & STA_NOINIT) return FR_NOT_READY;
	if (ds & STA_PROTECT) return FR_WRITE_PROTECTED;/*处于写保护时,不可操作*/

	/* Get physical drive parameters (sz_drv, sz_blk and ss) */
	/* 如配置:获取磁盘的一些参数设置:簇、目录数目、文件类型、fat表个数、块大小 */
	if (!opt) opt = &defopt;	/* 使用默认配置Use default parameter if it is not given */
	
	sz_blk = opt->align;
	if (sz_blk == 0) disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_blk);					/* Block size from the parameter or lower layer */
 	if (sz_blk == 0 || sz_blk > 0x8000 || (sz_blk & (sz_blk - 1))) sz_blk = 1;	/* Use default if the block size is invalid 参数检测包括:如果不是2的倍数(或者0),写入默认值  */
#if FF_MAX_SS != FF_MIN_SS
	if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &ss) != RES_OK) return FR_DISK_ERR;
	if (ss > FF_MAX_SS || ss < FF_MIN_SS || (ss & (ss - 1))) return FR_DISK_ERR;
#else
	ss = FF_MAX_SS;/*每个扇区大小 BYTE*/
#endif

	/* Options for FAT sub-type and FAT parameters FAT 子类型和 FAT 参数的选项*/
	fsopt = opt->fmt & (FM_ANY | FM_SFD);
	
	n_fat = (opt->n_fat >= 1 && opt->n_fat <= 2) ? opt->n_fat : 1;/*1~2  fat表个数最多为2(fat+fat备份)*/
	
	n_root = (opt->n_root >= 1 && opt->n_root <= 32768 && (opt->n_root % (ss / SZDIRE)) == 0) ? opt->n_root : 512;/*  根目录条目数,每个目录32字节*/
	
	sz_au = (opt->au_size <= 0x1000000 && (opt->au_size & (opt->au_size - 1)) == 0) ? opt->au_size : 0;/*簇大小 byte */
	sz_au /= ss;	/* Byte --> Sector   每簇包含多少扇区*/

	/* Get working buffer */
	sz_buf = len / ss;		/* Size of working buffer [sector]工作缓冲区 */
	if (sz_buf == 0) return FR_NOT_ENOUGH_CORE;
	
	buf = (BYTE*)work;		/* Working buffer   检测buff是否为空指针*/
#if FF_USE_LFN == 3
	if (!buf) buf = ff_memalloc(sz_buf * ss);	/* Use heap memory for working buffer */
#endif
	if (!buf) return FR_NOT_ENOUGH_CORE;

	/* Determine where the volume to be located (b_vol, sz_vol) 确定卷的位置(b_vol,sz_vol) */
	b_vol = sz_vol = 0;
	if (FF_MULTI_PARTITION && ipart != 0) {	/* Is the volume associated with any specific partition? 多分区*/
		/* Get partition location from the existing partition table */
		if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);	/* Load MBR */
		if (ld_word(buf + BS_55AA) != 0xAA55) LEAVE_MKFS(FR_MKFS_ABORTED);	/* Check if MBR is valid */
#if FF_LBA64
		if (buf[MBR_Table + PTE_System] == 0xEE) {	/* GPT protective MBR? */
			DWORD n_ent, ofs;
			QWORD pt_lba;

			/* Get the partition location from GPT */
			if (disk_read(pdrv, buf, 1, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);	/* Load GPT header sector (next to MBR) */
			if (!test_gpt_header(buf)) LEAVE_MKFS(FR_MKFS_ABORTED);	/* Check if GPT header is valid */
			n_ent = ld_dword(buf + GPTH_PtNum);		/* Number of entries */
			pt_lba = ld_qword(buf + GPTH_PtOfs);	/* Table start sector */
			ofs = i = 0;
			while (n_ent) {		/* Find MS Basic partition with order of ipart */
				if (ofs == 0 && disk_read(pdrv, buf, pt_lba++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);	/* Get PT sector */
				if (!memcmp(buf + ofs + GPTE_PtGuid, GUID_MS_Basic, 16) && ++i == ipart) {	/* MS basic data partition? */
					b_vol = ld_qword(buf + ofs + GPTE_FstLba);
					sz_vol = ld_qword(buf + ofs + GPTE_LstLba) - b_vol + 1;
					break;
				}
				n_ent--; ofs = (ofs + SZ_GPTE) % ss;	/* Next entry */
			}
			if (n_ent == 0) LEAVE_MKFS(FR_MKFS_ABORTED);	/* Partition not found */
			fsopt |= 0x80;	/* Partitioning is in GPT */
		} else
#endif
		{	/* Get the partition location from MBR partition table */
			pte = buf + (MBR_Table + (ipart - 1) * SZ_PTE);
			if (ipart > 4 || pte[PTE_System] == 0) LEAVE_MKFS(FR_MKFS_ABORTED);	/* No partition? */
			b_vol = ld_dword(pte + PTE_StLba);		/* Get volume start sector */
			sz_vol = ld_dword(pte + PTE_SizLba);	/* Get volume size */
		}
	} else {	/* The volume is associated with a physical drive 物理设备:扇区数目*/
		if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_vol) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
		if (!(fsopt & FM_SFD)) {	/* To be partitioned? 是否需要分区*/
			/* Create a single-partition on the drive in this function 在驱动器上创建一个单一分区*/
#if FF_LBA64
			if (sz_vol >= FF_MIN_GPT) {	/* Which partition type to create, MBR or GPT? */
				fsopt |= 0x80;		/* Partitioning is in GPT */
				b_vol = GPT_ALIGN / ss; sz_vol -= b_vol + GPT_ITEMS * SZ_GPTE / ss + 1;	/* Estimated partition offset and size */
			} else
#endif
			{	/* Partitioning is in MBR   MBR(主引导记录,存储分区表,定义分区信息)扇区0 */
				if (sz_vol > N_SEC_TRACK) {
					b_vol = N_SEC_TRACK; sz_vol -= b_vol;	/* Estimated partition offset and size 预计的分区偏移量和大小*/
				}
			}
		}
	}
	if (sz_vol < 128) LEAVE_MKFS(FR_MKFS_ABORTED);	/* Check if volume size is >=128 sectors */

	/* Now start to create an FAT volume at b_vol and sz_vol 开启创建FAT表 */

	do {	/* Pre-determine the FAT type 预先确定FAT类型*/
		if (FF_FS_EXFAT && (fsopt & FM_EXFAT)) {	/* exFAT possible? 是否是扩展FAT */
			if ((fsopt & FM_ANY) == FM_EXFAT || sz_vol >= 0x4000000 || sz_au > 128) {	/* exFAT only, vol >= 64M sectors or sz_au > 128 sectors ? */
				fsty = FS_EXFAT; break;
			}
		}
#if FF_LBA64
		if (sz_vol >= 0x100000000) LEAVE_MKFS(FR_MKFS_ABORTED);	/* Too large volume for FAT/FAT32 */
#endif
		if (sz_au > 128) sz_au = 128;	/* Invalid AU for FAT/FAT32? 簇数不能超过128 即簇数(n)*/
		if (fsopt & FM_FAT32) {	/* FAT32 possible? */
			if (!(fsopt & FM_FAT)) {	/* no-FAT? */
				fsty = FS_FAT32; break;
			}
		}
		if (!(fsopt & FM_FAT)) LEAVE_MKFS(FR_INVALID_PARAMETER);	/* no-FAT? */
		fsty = FS_FAT16;/*不是FAT32,默认FAT16,后面根据磁盘大小确定是FAT12 or FAT16*/
	} while (0);

	vsn = (DWORD)sz_vol + GET_FATTIME();	/* VSN(卷序列号) generated from current time and partition size */

#if FF_FS_EXFAT
	if (fsty == FS_EXFAT) {	/* Create an exFAT volume */
		DWORD szb_bit, szb_case, sum, nbit, clu, clen[3];
		WCHAR ch, si;
		UINT j, st;

		if (sz_vol < 0x1000) LEAVE_MKFS(FR_MKFS_ABORTED);	/* Too small volume for exFAT? */
#if FF_USE_TRIM
		lba[0] = b_vol; lba[1] = b_vol + sz_vol - 1;	/* Inform storage device that the volume area may be erased */
		disk_ioctl(pdrv, CTRL_TRIM, lba);
#endif
		/* Determine FAT location, data location and number of clusters */
		if (sz_au == 0) {	/* AU auto-selection */
			sz_au = 8;
			if (sz_vol >= 0x80000) sz_au = 64;		/* >= 512Ks */
			if (sz_vol >= 0x4000000) sz_au = 256;	/* >= 64Ms */
		}
		b_fat = b_vol + 32;										/* FAT start at offset 32 */
		sz_fat = (DWORD)((sz_vol / sz_au + 2) * 4 + ss - 1) / ss;	/* Number of FAT sectors */
		b_data = (b_fat + sz_fat + sz_blk - 1) & ~((LBA_t)sz_blk - 1);	/* Align data area to the erase block boundary */
		if (b_data - b_vol >= sz_vol / 2) LEAVE_MKFS(FR_MKFS_ABORTED);	/* Too small volume? */
		n_clst = (DWORD)((sz_vol - (b_data - b_vol)) / sz_au);	/* Number of clusters */
		if (n_clst <16) LEAVE_MKFS(FR_MKFS_ABORTED);			/* Too few clusters? */
		if (n_clst > MAX_EXFAT) LEAVE_MKFS(FR_MKFS_ABORTED);	/* Too many clusters? */

		szb_bit = (n_clst + 7) / 8;								/* Size of allocation bitmap */
		clen[0] = (szb_bit + sz_au * ss - 1) / (sz_au * ss);	/* Number of allocation bitmap clusters */

		/* Create a compressed up-case table */
		sect = b_data + sz_au * clen[0];	/* Table start sector */
		sum = 0;							/* Table checksum to be stored in the 82 entry */
		st = 0; si = 0; i = 0; j = 0; szb_case = 0;
		do {
			switch (st) {
			case 0:
				ch = (WCHAR)ff_wtoupper(si);	/* Get an up-case char */
				if (ch != si) {
					si++; break;		/* Store the up-case char if exist */
				}
				for (j = 1; (WCHAR)(si + j) && (WCHAR)(si + j) == ff_wtoupper((WCHAR)(si + j)); j++) ;	/* Get run length of no-case block */
				if (j >= 128) {
					ch = 0xFFFF; st = 2; break;	/* Compress the no-case block if run is >= 128 chars */
				}
				st = 1;			/* Do not compress short run */
				/* FALLTHROUGH */
			case 1:
				ch = si++;		/* Fill the short run */
				if (--j == 0) st = 0;
				break;

			default:
				ch = (WCHAR)j; si += (WCHAR)j;	/* Number of chars to skip */
				st = 0;
			}
			sum = xsum32(buf[i + 0] = (BYTE)ch, sum);	/* Put it into the write buffer */
			sum = xsum32(buf[i + 1] = (BYTE)(ch >> 8), sum);
			i += 2; szb_case += 2;
			if (si == 0 || i == sz_buf * ss) {		/* Write buffered data when buffer full or end of process */
				n = (i + ss - 1) / ss;
				if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
				sect += n; i = 0;
			}
		} while (si);
		clen[1] = (szb_case + sz_au * ss - 1) / (sz_au * ss);	/* Number of up-case table clusters */
		clen[2] = 1;	/* Number of root directory clusters */

		/* Initialize the allocation bitmap */
		sect = b_data; nsect = (szb_bit + ss - 1) / ss;	/* Start of bitmap and number of bitmap sectors */
		nbit = clen[0] + clen[1] + clen[2];				/* Number of clusters in-use by system (bitmap, up-case and root-dir) */
		do {
			memset(buf, 0, sz_buf * ss);				/* Initialize bitmap buffer */
			for (i = 0; nbit != 0 && i / 8 < sz_buf * ss; buf[i / 8] |= 1 << (i % 8), i++, nbit--) ;	/* Mark used clusters */
			n = (nsect > sz_buf) ? sz_buf : nsect;		/* Write the buffered data */
			if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
			sect += n; nsect -= n;
		} while (nsect);

		/* Initialize the FAT */
		sect = b_fat; nsect = sz_fat;	/* Start of FAT and number of FAT sectors */
		j = nbit = clu = 0;
		do {
			memset(buf, 0, sz_buf * ss); i = 0;	/* Clear work area and reset write offset */
			if (clu == 0) {	/* Initialize FAT [0] and FAT[1] */
				st_dword(buf + i, 0xFFFFFFF8); i += 4; clu++;
				st_dword(buf + i, 0xFFFFFFFF); i += 4; clu++;
			}

			do {			/* Create chains of bitmap, up-case and root directory */
				while (nbit != 0 && i < sz_buf * ss) {	/* Create a chain */
					st_dword(buf + i, (nbit > 1) ? clu + 1 : 0xFFFFFFFF);
					i += 4; clu++; nbit--;
				}
				if (nbit == 0 && j < 3) nbit = clen[j++];	/* Get next chain length */
			} while (nbit != 0 && i < sz_buf * ss);
			n = (nsect > sz_buf) ? sz_buf : nsect;	/* Write the buffered data */
			if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
			sect += n; nsect -= n;
		} while (nsect);

		/* Initialize the root directory */
		memset(buf, 0, sz_buf * ss);
		buf[SZDIRE * 0 + 0] = ET_VLABEL;				/* Volume label entry (no label) */
		buf[SZDIRE * 1 + 0] = ET_BITMAP;				/* Bitmap entry */
		st_dword(buf + SZDIRE * 1 + 20, 2);				/*  cluster */
		st_dword(buf + SZDIRE * 1 + 24, szb_bit);		/*  size */
		buf[SZDIRE * 2 + 0] = ET_UPCASE;				/* Up-case table entry */
		st_dword(buf + SZDIRE * 2 + 4, sum);			/*  sum */
		st_dword(buf + SZDIRE * 2 + 20, 2 + clen[0]);	/*  cluster */
		st_dword(buf + SZDIRE * 2 + 24, szb_case);		/*  size */
		sect = b_data + sz_au * (clen[0] + clen[1]); nsect = sz_au;	/* Start of the root directory and number of sectors */
		do {	/* Fill root directory sectors */
			n = (nsect > sz_buf) ? sz_buf : nsect;
			if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
			memset(buf, 0, ss);	/* Rest of entries are filled with zero */
			sect += n; nsect -= n;
		} while (nsect);

		/* Create two set of the exFAT VBR blocks */
		sect = b_vol;
		for (n = 0; n < 2; n++) {
			/* Main record (+0) */
			memset(buf, 0, ss);
			memcpy(buf + BS_JmpBoot, "\xEB\x76\x90" "EXFAT   ", 11);	/* Boot jump code (x86), OEM name */
			st_qword(buf + BPB_VolOfsEx, b_vol);					/* Volume offset in the physical drive [sector] */
			st_qword(buf + BPB_TotSecEx, sz_vol);					/* Volume size [sector] */
			st_dword(buf + BPB_FatOfsEx, (DWORD)(b_fat - b_vol));	/* FAT offset [sector] */
			st_dword(buf + BPB_FatSzEx, sz_fat);					/* FAT size [sector] */
			st_dword(buf + BPB_DataOfsEx, (DWORD)(b_data - b_vol));	/* Data offset [sector] */
			st_dword(buf + BPB_NumClusEx, n_clst);					/* Number of clusters */
			st_dword(buf + BPB_RootClusEx, 2 + clen[0] + clen[1]);	/* Root directory cluster number */
			st_dword(buf + BPB_VolIDEx, vsn);						/* VSN */
			st_word(buf + BPB_FSVerEx, 0x100);						/* Filesystem version (1.00) */
			for (buf[BPB_BytsPerSecEx] = 0, i = ss; i >>= 1; buf[BPB_BytsPerSecEx]++) ;		/* Log2 of sector size [byte] */
			for (buf[BPB_SecPerClusEx] = 0, i = sz_au; i >>= 1; buf[BPB_SecPerClusEx]++) ;	/* Log2 of cluster size [sector] */
			buf[BPB_NumFATsEx] = 1;					/* Number of FATs */
			buf[BPB_DrvNumEx] = 0x80;				/* Drive number (for int13) */
			st_word(buf + BS_BootCodeEx, 0xFEEB);	/* Boot code (x86) */
			st_word(buf + BS_55AA, 0xAA55);			/* Signature (placed here regardless of sector size) */
			for (i = sum = 0; i < ss; i++) {		/* VBR checksum */
				if (i != BPB_VolFlagEx && i != BPB_VolFlagEx + 1 && i != BPB_PercInUseEx) sum = xsum32(buf[i], sum);
			}
			if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
			/* Extended bootstrap record (+1..+8) */
			memset(buf, 0, ss);
			st_word(buf + ss - 2, 0xAA55);	/* Signature (placed at end of sector) */
			for (j = 1; j < 9; j++) {
				for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ;	/* VBR checksum */
				if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
			}
			/* OEM/Reserved record (+9..+10) */
			memset(buf, 0, ss);
			for ( ; j < 11; j++) {
				for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ;	/* VBR checksum */
				if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
			}
			/* Sum record (+11) */
			for (i = 0; i < ss; i += 4) st_dword(buf + i, sum);		/* Fill with checksum value */
			if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
		}

	} else
#endif	/* FF_FS_EXFAT */
	{	/* Create an FAT/FAT32 volume 此处开始创建一个FAT卷 */
		do {
			pau = sz_au;/* 簇大小:扇区数*/
			/* Pre-determine number of clusters and FAT sub-type 预先确定簇的数量和 FAT 子类型 前面默认定义fsty */
			if (fsty == FS_FAT32) {	/* FAT32 volume */
				if (pau == 0) {	/* AU auto-selection */
					n = (DWORD)sz_vol / 0x20000;	/* Volume size in unit of 128KS */
					for (i = 0, pau = 1; cst32[i] && cst32[i] <= n; i++, pau <<= 1) ;	/* Get from table */
				}
				n_clst = (DWORD)sz_vol / pau;	/* Number of clusters */
				sz_fat = (n_clst * 4 + 8 + ss - 1) / ss;	/* FAT size [sector] */
				sz_rsv = 32;	/* Number of reserved sectors */
				sz_dir = 0;		/* No static directory */
				if (n_clst <= MAX_FAT16 || n_clst > MAX_FAT32) LEAVE_MKFS(FR_MKFS_ABORTED);
			} else {				/* FAT volume */
				if (pau == 0) {	/* au auto-selection 如果未定义簇,则自动簇数*/
					n = (DWORD)sz_vol / 0x1000;	/* Volume size in unit of 4KS   sz_vol为去掉63扇区大小,卷尺寸以4k为单位*/
					for (i = 0, pau = 1; cst[i] && cst[i] <= n; i++, pau <<= 1) ;	/* Get from table */
				}
				n_clst = (DWORD)sz_vol / pau;/*计算出剩余扇区,也就是分区的总簇数 */
				if (n_clst > MAX_FAT12) {
					n = n_clst * 2 + 4;		/* FAT size [byte] */
				} else {
					fsty = FS_FAT12;
					n = (n_clst * 3 + 1) / 2 + 3;	/* FAT size [byte] 每簇1.5byte  总簇数在FAT表上总字节数=(n_clst +2)×1.5 向上取整*/
				}
				sz_fat = (n + ss - 1) / ss;		/* FAT size [sector] 根据簇数字节数,计算出FAT表大小(占用扇区数)*/
				sz_rsv = 1;						/* Number of reserved sectors  1个保留扇区*/
				sz_dir = (DWORD)n_root * SZDIRE / ss;	/* Root directory size [sector] 根目录大小(占用扇区数) 32字节一个目录 */
			}
			b_fat = b_vol + sz_rsv;						/* FAT base FAT表起始扇区*/
			b_data = b_fat + sz_fat * n_fat + sz_dir;	/* Data base 数据区起始扇区*/

			/* Align data area to erase block boundary (for flash memory media) 将数据区域对齐到擦除块边界(适用于闪存介质)*/
			n = (DWORD)(((b_data + sz_blk - 1) & ~(sz_blk - 1)) - b_data);	/* Sectors to next nearest from current data base 从当前数据块到下一个最近扇区的扇区数*/
			if (fsty == FS_FAT32) {		/* FAT32: Move FAT */
				sz_rsv += n; b_fat += n;
			} else {					/* FAT: Expand FAT */
				if (n % n_fat) {	/* Adjust fractional error if needed */
					n--; sz_rsv++; b_fat++;
				}
				sz_fat += n / n_fat;
			}

			/* Determine number of clusters and final check of validity of the FAT sub-type 确定簇的数量并最终检查 FAT 子类型的有效性*/
			if (sz_vol < b_data + pau * 16 - b_vol) LEAVE_MKFS(FR_MKFS_ABORTED);	/* Too small volume? */
			n_clst = ((DWORD)sz_vol - sz_rsv - sz_fat * n_fat - sz_dir) / pau;/*数据区占用的簇数*/
			if (fsty == FS_FAT32) {
				if (n_clst <= MAX_FAT16) {	/* Too few clusters for FAT32? */
					if (sz_au == 0 && (sz_au = pau / 2) != 0) continue;	/* Adjust cluster size and retry */
					LEAVE_MKFS(FR_MKFS_ABORTED);
				}
			}
			/*  根据数据区占用的簇数,计算出当前卷的文件类型*/
			if (fsty == FS_FAT16) {
				if (n_clst > MAX_FAT16) {	/* Too many clusters for FAT16 */
					if (sz_au == 0 && (pau * 2) <= 64) {
						sz_au = pau * 2; continue;	/* Adjust cluster size and retry */
					}
					if ((fsopt & FM_FAT32)) {
						fsty = FS_FAT32; continue;	/* Switch type to FAT32 and retry */
					}
					if (sz_au == 0 && (sz_au = pau * 2) <= 128) continue;	/* Adjust cluster size and retry */
					LEAVE_MKFS(FR_MKFS_ABORTED);
				}
				if  (n_clst <= MAX_FAT12) {	/* Too few clusters for FAT16 */
					if (sz_au == 0 && (sz_au = pau * 2) <= 128) continue;	/* Adjust cluster size and retry */
					LEAVE_MKFS(FR_MKFS_ABORTED);
				}
			}
			if (fsty == FS_FAT12 && n_clst > MAX_FAT12) LEAVE_MKFS(FR_MKFS_ABORTED);	/* Too many clusters for FAT12 */

			/* Ok, it is the valid cluster configuration */
			break;
		} while (1);

#if FF_USE_TRIM
		lba[0] = b_vol; lba[1] = b_vol + sz_vol - 1;	/* Inform storage device that the volume area may be erased */
		disk_ioctl(pdrv, CTRL_TRIM, lba);
#endif
		/* Create FAT VBR 分区起始的扇区VBR,记录分区信息 */
		memset(buf, 0, ss);
		memcpy(buf + BS_JmpBoot, "\xEB\xFE\x90" "MSDOS5.0", 11);	/* Boot jump code (x86), OEM name */
		st_word(buf + BPB_BytsPerSec, ss);				/* Sector size [byte] 扇区大小 */
		buf[BPB_SecPerClus] = (BYTE)pau;				/* Cluster size [sector] 每次操作的最小扇区数,簇*/
		st_word(buf + BPB_RsvdSecCnt, (WORD)sz_rsv);	/* Size of reserved area 保留扇区 */
		buf[BPB_NumFATs] = (BYTE)n_fat;					/* Number of FATs FAT表个数 */
		st_word(buf + BPB_RootEntCnt, (WORD)((fsty == FS_FAT32) ? 0 : n_root));	/* Number of root directory entries 根目录个数 */
		if (sz_vol < 0x10000) {
			st_word(buf + BPB_TotSec16, (WORD)sz_vol);	/* FAT卷有效扇区总数Volume size in 16-bit LBA */
		} else {
			st_dword(buf + BPB_TotSec32, (DWORD)sz_vol);	/* Volume size in 32-bit LBA */
		}
		buf[BPB_Media] = 0xF8;							/* 媒体类型Media descriptor byte */
		st_word(buf + BPB_SecPerTrk, 63);				/* 每个磁道的扇区数 Number of sectors per track (for int13) */
		st_word(buf + BPB_NumHeads, 255);				/* 头数量Number of heads (for int13) */
		st_dword(buf + BPB_HiddSec, (DWORD)b_vol);		/* 分区位置在卷上的偏移Volume offset in the physical drive [sector] */
		if (fsty == FS_FAT32) {
			st_dword(buf + BS_VolID32, vsn);			/* VSN */
			st_dword(buf + BPB_FATSz32, sz_fat);		/* FAT size [sector] */
			st_dword(buf + BPB_RootClus32, 2);			/* Root directory cluster # (2) */
			st_word(buf + BPB_FSInfo32, 1);				/* Offset of FSINFO sector (VBR + 1) */
			st_word(buf + BPB_BkBootSec32, 6);			/* Offset of backup VBR (VBR + 6) */
			buf[BS_DrvNum32] = 0x80;					/* Drive number (for int13) */
			buf[BS_BootSig32] = 0x29;					/* Extended boot signature */
			memcpy(buf + BS_VolLab32, "NO NAME    " "FAT32   ", 19);	/* Volume label, FAT signature */
		} else {
			st_dword(buf + BS_VolID, vsn);				/* VSN */
			st_word(buf + BPB_FATSz16, (WORD)sz_fat);	/* FAT size [sector] */
			buf[BS_DrvNum] = 0x80;						/* Drive number (for int13) */
			buf[BS_BootSig] = 0x29;						/* Extended boot signature */
			memcpy(buf + BS_VolLab, "NO NAME    " "FAT     ", 19);	/* Volume label, FAT signature */
		}
		st_word(buf + BS_55AA, 0xAA55);					/* 引导签名,指示这是一个有效的引导扇区Signature (offset is fixed here regardless of sector size) */
		if (disk_write(pdrv, buf, b_vol, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);	/* Write it to the VBR sector */

		/* Create FSINFO record if needed */
		if (fsty == FS_FAT32) {
			disk_write(pdrv, buf, b_vol + 6, 1);		/* Write backup VBR (VBR + 6) */
			memset(buf, 0, ss);
			st_dword(buf + FSI_LeadSig, 0x41615252);
			st_dword(buf + FSI_StrucSig, 0x61417272);
			st_dword(buf + FSI_Free_Count, n_clst - 1);	/* Number of free clusters */
			st_dword(buf + FSI_Nxt_Free, 2);			/* Last allocated cluster# */
			st_word(buf + BS_55AA, 0xAA55);
			disk_write(pdrv, buf, b_vol + 7, 1);		/* Write backup FSINFO (VBR + 7) */
			disk_write(pdrv, buf, b_vol + 1, 1);		/* Write original FSINFO (VBR + 1) */
		}

		/* Initialize FAT area  初始化FAT表 */
		memset(buf, 0, sz_buf * ss);
		sect = b_fat;		/* FAT start sector  FAT起始扇区位置*/
		for (i = 0; i < n_fat; i++) {			/* Initialize FATs each */
			if (fsty == FS_FAT32) {
				st_dword(buf + 0, 0xFFFFFFF8);	/* FAT[0] */
				st_dword(buf + 4, 0xFFFFFFFF);	/* FAT[1] */
				st_dword(buf + 8, 0x0FFFFFFF);	/* FAT[2] (root directory at cluster# 2) */
			} else {
				st_dword(buf + 0, (fsty == FS_FAT12) ? 0xFFFFF8 : 0xFFFFFFF8);	/* FAT[0] and FAT[1]  fat表的扇区头:2个簇号大小*/
			}
			nsect = sz_fat;		/* Number of FAT sectors */
			do {	/* Fill FAT sectors */
				n = (nsect > sz_buf) ? sz_buf : nsect;
				if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
				memset(buf, 0, ss);	/* Rest of FAT area is initially zero */
				sect += n; nsect -= n;
			} while (nsect);
		}

		/* Initialize root directory (fill with zero) 把根目录所在的扇区全部清0 */
		nsect = (fsty == FS_FAT32) ? pau : sz_dir;	/* Number of root directory sectors */
		do {
			n = (nsect > sz_buf) ? sz_buf : nsect;
			if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
			sect += n; nsect -= n;
		} while (nsect);
	}

	/* A FAT volume has been created here */

	/* Determine system ID in the MBR partition table   MBR:第0号扇区写入 */
	if (FF_FS_EXFAT && fsty == FS_EXFAT) {
		sys = 0x07;		/* exFAT */
	} else if (fsty == FS_FAT32) {
		sys = 0x0C;		/* FAT32X */
	} else if (sz_vol >= 0x10000) {
		sys = 0x06;		/* FAT12/16 (large) */
	} else if (fsty == FS_FAT16) {
		sys = 0x04;		/* FAT16 */
	} else {
		sys = 0x01;		/* FAT12 */
	}

	/* Update partition information */
	if (FF_MULTI_PARTITION && ipart != 0) {	/* Volume is in the existing partition */
		if (!FF_LBA64 || !(fsopt & 0x80)) {	/* Is the partition in MBR? */
			/* Update system ID in the partition table */
			if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);	/* Read the MBR */
			buf[MBR_Table + (ipart - 1) * SZ_PTE + PTE_System] = sys;			/* Set system ID */
			if (disk_write(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);	/* Write it back to the MBR */
		}
	} else {								/* Volume as a new single partition */
		if (!(fsopt & FM_SFD)) {			/* Create partition table if not in SFD format 如果不是SFD格式,则创建分区表。*/
			lba[0] = sz_vol; lba[1] = 0;
			res = create_partition(pdrv, lba, sys, buf);/*创建MBR*/
			if (res != FR_OK) LEAVE_MKFS(res);
		}
	}

	if (disk_ioctl(pdrv, CTRL_SYNC, 0) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);

	LEAVE_MKFS(FR_OK);
}

接下来对源码执行步骤释义:

1.首先get_ldnumber(&path)获取当前逻辑驱动器的卷ID,可以是数字、字符或者字符和数字混合,例如:数字型:“0:/test.txt”,ID就是0。
/*-----------------------------------------------------------------------*/
/* Get logical drive number from path name                               */
/*-----------------------------------------------------------------------*/

static int get_ldnumber (	/* Returns logical drive number (-1:invalid drive number or null pointer) */
	const TCHAR** path		/* Pointer to pointer to the path name */
)
{
	const TCHAR *tp;
	const TCHAR *tt;
	TCHAR chr;
	int i;
#if FF_STR_VOLUME_ID		/* Find string volume ID */
	const char *vsp;
	char vchr;
#endif

	tt = tp = *path;
	if (!tp) return -1;		/* Invalid path name? */
	do {					/* Find a colon in the path */
		chr = *tt++;
	} while (!IsTerminator(chr) && chr != ':');

	if (chr == ':') {	/* Is there a DOS/Windows style volume ID? */
		i = FF_VOLUMES;
		if (IsDigit(*tp) && tp + 2 == tt) {	/* Is it a numeric volume ID + colon? */
			i = (int)*tp - '0';	/* Get the logical drive number */
		}
#if FF_STR_VOLUME_ID == 1	/* Arbitrary string volume ID is enabled   字符串卷ID*/
		else {
			i = 0;	/* Find volume ID string in the preconfigured table 在预配置表中查找卷 ID 字符串*/
			do {
				vsp = VolumeStr[i]; tp = *path;	/* Preconfigured string and path name to test */
				do {	/* Compare the volume ID with path name in case-insensitive */
					vchr = *vsp++; chr = *tp++;
					if (IsLower(vchr)) vchr -= 0x20;/*转换为大写 (小写-32)*/
					if (IsLower(chr)) chr -= 0x20;
				} while (vchr && (TCHAR)vchr == chr);
			} while ((vchr || tp != tt) && ++i < FF_VOLUMES);	/* Repeat for each id until pattern match 遍历卷ID*/
		}
#endif
		if (i >= FF_VOLUMES) return -1;	/* Not found or invalid volume ID */
		*path = tt;		/* Snip the drive prefix off  去掉驱动器前缀 :之前数据*/
		return i;		/* Return the found drive number */
	}
#if FF_STR_VOLUME_ID == 2		/* Unix style volume ID is enabled */
	if (*tp == '/') {			/* Is there a volume ID? */
		while (*(tp + 1) == '/') tp++;	/* Skip duplicated separator */
		i = 0;
		do {
			vsp = VolumeStr[i]; tt = tp; 	/* Preconfigured string and path name to test */
			do {	/* Compare the volume ID with path name in case-insensitive */
				vchr = *vsp++; chr = *(++tt);
				if (IsLower(vchr)) vchr -= 0x20;
				if (IsLower(chr)) chr -= 0x20;
			} while (vchr && (TCHAR)vchr == chr);
		} while ((vchr || (chr != '/' && !IsTerminator(chr))) && ++i < FF_VOLUMES);	/* Repeat for each ID until pattern match */
		if (i >= FF_VOLUMES) return -1;	/* Not found (invalid volume ID) */
		*path = tt;		/* Snip the node name off */
		return i;		/* Return the found drive number */
	}
#endif
	/* No drive prefix */
#if FF_FS_RPATH != 0
	return (int)CurrVol;	/* Default drive is current drive */
#else
	return 0;				/* Default drive is 0 */
#endif
}
2.物理设备初始化
 /* Initialize the hosting physical drive */
  ds = disk_initialize(pdrv);/*初始化物理磁盘*/
3.structure (MKFS_PARM) 相关参数的检测。
typedef struct {
	BYTE fmt;			/* Format option (FM_FAT, FM_FAT32, FM_EXFAT and FM_SFD) */
	BYTE n_fat;			/* Number of FATs */
	UINT align;			/* Data area alignment (sector) */
	UINT n_root;		/* Number of root directory entries */
	DWORD au_size;		/* Cluster size (byte) */
} MKFS_PARM;

如未定义则使用默认值

static const MKFS_PARM defopt = {FM_ANY, 0, 0, 0, 0}; /* Default parameter */

其中簇是的单位是byte ,每簇包含的扇区数:除以FF_MAX_SS。

/* Options for FAT sub-type and FAT parameters 文件系统fat类型*/
	fsopt = opt->fmt & (FM_ANY | FM_SFD);
	
	n_fat = (opt->n_fat >= 1 && opt->n_fat <= 2) ? opt->n_fat : 1;/*1~2  fat表个数*/
	
	n_root = (opt->n_root >= 1 && opt->n_root <= 32768 && (opt->n_root % (ss / SZDIRE)) == 0) ? opt->n_root : 512;/*  根目录条目数*/
	
	sz_au = (opt->au_size <= 0x1000000 && (opt->au_size & (opt->au_size - 1)) == 0) ? opt->au_size : 0;/*簇大小  byte */
	sz_au /= ss;	/* Byte --> Sector   簇占用的扇区数*/

4. FAT表、目录、数据区扇区偏移。
				if (pau == 0) {	/* au auto-selection 自动簇数*/
					n = (DWORD)sz_vol / 0x1000;	/* Volume size in unit of 4KS   默认扇区4k为一簇*/
					for (i = 0, pau = 1; cst[i] && cst[i] <= n; i++, pau <<= 1) ;	/* Get from table */
				}
				n_clst = (DWORD)sz_vol / pau;/*总簇数 */
				if (n_clst > MAX_FAT12) {
					n = n_clst * 2 + 4;		
				} else {
					fsty = FS_FAT12;
					n = (n_clst * 3 + 1) / 2 + 3;	/* FAT size [byte] 每簇1.5byte   总字节数=(n_clst +2)×1.5 向上取整*/
				}
				sz_fat = (n + ss - 1) / ss;		/* FAT size [sector] fat扇区数*/
				sz_rsv = 1;						/* Number of reserved sectors  保留扇区*/
				sz_dir = (DWORD)n_root * SZDIRE / ss;	/* Root directory size [sector] 根目录大小 扇区数 */
			}
			b_fat = b_vol + sz_rsv;						/* FAT base FAT表 扇区偏移数 63+sz_rsv*/
			b_data = b_fat + sz_fat * n_fat + sz_dir;	/* Data base 数据区位置 偏移扇区数   */

			/* Align data area to erase block boundary (for flash memory media) 将数据区域对齐到擦除块边界(适用于闪存介质)*/
			n = (DWORD)(((b_data + sz_blk - 1) & ~(sz_blk - 1)) - b_data);	/* Sectors to next nearest from current data base 从当前数据块到下一个最近扇区的扇区数*/
			if (fsty == FS_FAT32) {		/* FAT32: Move FAT */
				sz_rsv += n; b_fat += n;
			} else {					/* FAT: Expand FAT */
				if (n % n_fat) {	/* Adjust fractional error if needed */
					n--; sz_rsv++; b_fat++;
				}
				sz_fat += n / n_fat;
			}
5.创建VBR :分区起始的扇区位置,包含当前分区的信息。
	/* Create FAT VBR 分区起始的扇区VBR,记录分区信息 */
		memset(buf, 0, ss);
		memcpy(buf + BS_JmpBoot, "\xEB\xFE\x90" "MSDOS5.0", 11);	/* Boot jump code (x86), OEM name */
		st_word(buf + BPB_BytsPerSec, ss);				/* Sector size [byte] 扇区大小 */
		buf[BPB_SecPerClus] = (BYTE)pau;				/* Cluster size [sector] 每次操作的最小扇区数,簇*/
		st_word(buf + BPB_RsvdSecCnt, (WORD)sz_rsv);	/* Size of reserved area 保留扇区 */
		buf[BPB_NumFATs] = (BYTE)n_fat;					/* Number of FATs FAT表个数 */
		st_word(buf + BPB_RootEntCnt, (WORD)((fsty == FS_FAT32) ? 0 : n_root));	/* Number of root directory entries 根目录个数 */
		if (sz_vol < 0x10000) {
			st_word(buf + BPB_TotSec16, (WORD)sz_vol);	/* FAT卷有效扇区总数Volume size in 16-bit LBA */
		} else {
			st_dword(buf + BPB_TotSec32, (DWORD)sz_vol);	/* Volume size in 32-bit LBA */
		}
		buf[BPB_Media] = 0xF8;							/* 媒体类型Media descriptor byte */
		st_word(buf + BPB_SecPerTrk, 63);				/* 每个磁道的扇区数 Number of sectors per track (for int13) */
		st_word(buf + BPB_NumHeads, 255);				/* 头数量Number of heads (for int13) */
		st_dword(buf + BPB_HiddSec, (DWORD)b_vol);		/* 分区位置在卷上的偏移Volume offset in the physical drive [sector] */
		if (fsty == FS_FAT32) {
			st_dword(buf + BS_VolID32, vsn);			/* VSN */
			st_dword(buf + BPB_FATSz32, sz_fat);		/* FAT size [sector] */
			st_dword(buf + BPB_RootClus32, 2);			/* Root directory cluster # (2) */
			st_word(buf + BPB_FSInfo32, 1);				/* Offset of FSINFO sector (VBR + 1) */
			st_word(buf + BPB_BkBootSec32, 6);			/* Offset of backup VBR (VBR + 6) */
			buf[BS_DrvNum32] = 0x80;					/* Drive number (for int13) */
			buf[BS_BootSig32] = 0x29;					/* Extended boot signature */
			memcpy(buf + BS_VolLab32, "NO NAME    " "FAT32   ", 19);	/* Volume label, FAT signature */
		} else {
			st_dword(buf + BS_VolID, vsn);				/* VSN */
			st_word(buf + BPB_FATSz16, (WORD)sz_fat);	/* FAT size [sector] */
			buf[BS_DrvNum] = 0x80;						/* Drive number (for int13) */
			buf[BS_BootSig] = 0x29;						/* Extended boot signature */
			memcpy(buf + BS_VolLab, "NO NAME    " "FAT     ", 19);	/* Volume label, FAT signature */
		}
		st_word(buf + BS_55AA, 0xAA55);					/* 引导签名,指示这是一个有效的引导扇区Signature (offset is fixed here regardless of sector size) */
		if (disk_write(pdrv, buf, b_vol, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);	/* Write it to the VBR sector */

		/* Create FSINFO record if needed */
		if (fsty == FS_FAT32) {
			disk_write(pdrv, buf, b_vol + 6, 1);		/* Write backup VBR (VBR + 6) */
			memset(buf, 0, ss);
			st_dword(buf + FSI_LeadSig, 0x41615252);
			st_dword(buf + FSI_StrucSig, 0x61417272);
			st_dword(buf + FSI_Free_Count, n_clst - 1);	/* Number of free clusters */
			st_dword(buf + FSI_Nxt_Free, 2);			/* Last allocated cluster# */
			st_word(buf + BS_55AA, 0xAA55);
			disk_write(pdrv, buf, b_vol + 7, 1);		/* Write backup FSINFO (VBR + 7) */
			disk_write(pdrv, buf, b_vol + 1, 1);		/* Write original FSINFO (VBR + 1) */
		}
6. 初始化FAT表:每个fat表扇区头写入2个簇号大小的默认值,如FAT12,每个簇号1.5字节,所以写入3个字节0xFFFFF8。
		/* Initialize FAT area  初始化FAT表 */
		memset(buf, 0, sz_buf * ss);
		sect = b_fat;		/* FAT start sector */
		for (i = 0; i < n_fat; i++) {			/* Initialize FATs each */
			if (fsty == FS_FAT32) {
				st_dword(buf + 0, 0xFFFFFFF8);	/* FAT[0] */
				st_dword(buf + 4, 0xFFFFFFFF);	/* FAT[1] */
				st_dword(buf + 8, 0x0FFFFFFF);	/* FAT[2] (root directory at cluster# 2) */
			} else {
				st_dword(buf + 0, (fsty == FS_FAT12) ? 0xFFFFF8 : 0xFFFFFFF8);	/* FAT[0] and FAT[1] */
			}
			nsect = sz_fat;		/* Number of FAT sectors */
			do {	/* Fill FAT sectors */
				n = (nsect > sz_buf) ? sz_buf : nsect;
				if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
				memset(buf, 0, ss);	/* Rest of FAT area is initially zero */
				sect += n; nsect -= n;
			} while (nsect);
		
7.初始化目录表:根目录所在的扇区全部清0
	/* Initialize root directory (fill with zero)  */
		nsect = (fsty == FS_FAT32) ? pau : sz_dir;	/* Number of root directory sectors */
		do {
			n = (nsect > sz_buf) ? sz_buf : nsect;
			if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
			sect += n; nsect -= n;
		} while (nsect);
8.创建MBR:主引导记录。最多4个分区。

主要关注这两个信息:分区起始扇区和分区大小。
st_dword(pte + PTE_StLba, nxt_alloc32); /* Partition start LBA sector /
st_dword(pte + PTE_SizLba, sz_part32); /
Size of partition [sector]

static FRESULT create_partition (
	BYTE drv,			/* Physical drive number */
	const LBA_t plst[],	/* Partition list */
	BYTE sys,			/* System ID for each partition (for only MBR) */
	BYTE *buf			/* Working buffer for a sector */
)
{
	UINT i, cy;
	LBA_t sz_drv;
	DWORD sz_drv32, nxt_alloc32, sz_part32;
	BYTE *pte;
	BYTE hd, n_hd, sc, n_sc;

	/* Get physical drive size */
	if (disk_ioctl(drv, GET_SECTOR_COUNT, &sz_drv) != RES_OK) return FR_DISK_ERR;
	{	/* Create partitions in MBR format */
		sz_drv32 = (DWORD)sz_drv;
		n_sc = N_SEC_TRACK;				/* Determine drive CHS without any consideration of the drive geometry 在不考虑驱动器几何结构的情况下确定驱动器的CHS*/
		for (n_hd = 8; n_hd != 0 && sz_drv32 / n_hd / n_sc > 1024; n_hd *= 2) ;
		if (n_hd == 0) n_hd = 255;		/* Number of heads needs to be <256 */

		memset(buf, 0, FF_MAX_SS);		/* Clear MBR */
		pte = buf + MBR_Table;	/* Partition table in the MBR */
		for (i = 0, nxt_alloc32 = n_sc; i < 4 && nxt_alloc32 != 0 && nxt_alloc32 < sz_drv32; i++, nxt_alloc32 += sz_part32) {
			sz_part32 = (DWORD)plst[i];	/* Get partition size */
			if (sz_part32 <= 100) sz_part32 = (sz_part32 == 100) ? sz_drv32 : sz_drv32 / 100 * sz_part32;	/* Size in percentage? */
			if (nxt_alloc32 + sz_part32 > sz_drv32 || nxt_alloc32 + sz_part32 < nxt_alloc32) sz_part32 = sz_drv32 - nxt_alloc32;	/* Clip at drive size */
			if (sz_part32 == 0) break;	/* End of table or no sector to allocate? */

			st_dword(pte + PTE_StLba, nxt_alloc32);	/* Partition start LBA sector */
			st_dword(pte + PTE_SizLba, sz_part32);	/* Size of partition [sector] */
			pte[PTE_System] = sys;					/* System type */

			cy = (UINT)(nxt_alloc32 / n_sc / n_hd);	/* Partitio start CHS cylinder */
			hd = (BYTE)(nxt_alloc32 / n_sc % n_hd);	/* Partition start CHS head */
			sc = (BYTE)(nxt_alloc32 % n_sc + 1);	/* Partition start CHS sector */
			pte[PTE_StHead] = hd;
			pte[PTE_StSec] = (BYTE)((cy >> 2 & 0xC0) | sc);
			pte[PTE_StCyl] = (BYTE)cy;

			cy = (UINT)((nxt_alloc32 + sz_part32 - 1) / n_sc / n_hd);	/* Partition end CHS cylinder */
			hd = (BYTE)((nxt_alloc32 + sz_part32 - 1) / n_sc % n_hd);	/* Partition end CHS head */
			sc = (BYTE)((nxt_alloc32 + sz_part32 - 1) % n_sc + 1);		/* Partition end CHS sector */
			pte[PTE_EdHead] = hd;
			pte[PTE_EdSec] = (BYTE)((cy >> 2 & 0xC0) | sc);
			pte[PTE_EdCyl] = (BYTE)cy;

			pte += SZ_PTE;		/* Next entry */
		}
		st_word(buf + BS_55AA, 0xAA55);		/* MBR signature */
		if (disk_write(drv, buf, 0, 1) != RES_OK) return FR_DISK_ERR;	/* Write it to the MBR */
	}
	return FR_OK;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值