from stdint import * import fat32_types as types import fat32_diskio as diskio import fat32_time as ftime import string import t, c def _div_round_up(a: t.CUInt64T, b: t.CUInt64T) -> t.CUInt64T: return (a + b - 1) / b def _calc_fat_size(total_sectors: t.CUInt64T, reserved: t.CUInt32T, sec_per_clus: t.CUInt8T, num_fats: t.CUInt8T) -> t.CUInt32T: tmp: t.CUInt64T = total_sectors - t.CUInt64T(reserved) fat_sz: t.CUInt32T = 1 while True: data_sectors: t.CUInt64T = tmp - t.CUInt64T(fat_sz) * t.CUInt64T(num_fats) total_clusters: t.CUInt32T = t.CUInt32T(data_sectors / t.CUInt64T(sec_per_clus)) needed: t.CUInt64T = _div_round_up(t.CUInt64T(total_clusters) * 4, 512) if needed <= t.CUInt64T(fat_sz): break fat_sz = t.CUInt32T(needed) return fat_sz def _write_boot_sector(pdrv: t.CUInt8T, total_sectors: t.CUInt64T, sec_per_clus: t.CUInt8T, vol_id: t.CUInt32T, fat_sz: t.CUInt32T) -> types.DRESULT: buf: t.CArray[t.CUInt8T, 512] string.memset(c.Addr(buf[0]), 0, 512) buf[0] = 0xEB; buf[1] = 0x58; buf[2] = 0x90 buf[3] = 'M'; buf[4] = 'S'; buf[5] = 'W'; buf[6] = 'I'; buf[7] = 'N' buf[8] = '4'; buf[9] = '.'; buf[10] = '1' types._write16(c.Addr(buf[0]), 11, 512) buf[13] = sec_per_clus types._write16(c.Addr(buf[0]), 14, 32) buf[16] = 2 types._write16(c.Addr(buf[0]), 17, 0) buf[21] = 0xF8 types._write16(c.Addr(buf[0]), 22, 0) types._write16(c.Addr(buf[0]), 24, 63) types._write16(c.Addr(buf[0]), 26, 255) types._write32(c.Addr(buf[0]), 28, 0) types._write32(c.Addr(buf[0]), 32, t.CUInt32T(total_sectors)) types._write32(c.Addr(buf[0]), 36, fat_sz) types._write16(c.Addr(buf[0]), 40, 0) types._write16(c.Addr(buf[0]), 42, 0) types._write32(c.Addr(buf[0]), 44, 2) types._write16(c.Addr(buf[0]), 48, 1) types._write16(c.Addr(buf[0]), 50, 6) buf[64] = 0x80 buf[66] = 0x29 types._write32(c.Addr(buf[0]), 67, vol_id) vol_label: t.CArray[t.CChar, 11] vol_label[0] = 'N'; vol_label[1] = 'O'; vol_label[2] = ' '; vol_label[3] = ' ' vol_label[4] = ' '; vol_label[5] = ' '; vol_label[6] = ' '; vol_label[7] = ' ' vol_label[8] = ' '; vol_label[9] = ' '; vol_label[10] = ' ' i: t.CInt for i in range(11): buf[71 + i] = t.CUInt8T(vol_label[i]) buf[82] = 'F'; buf[83] = 'A'; buf[84] = 'T'; buf[85] = '3' buf[86] = '2'; buf[87] = ' '; buf[88] = ' '; buf[89] = ' ' buf[510] = 0x55; buf[511] = 0xAA return diskio.write(pdrv, c.Addr(buf[0]), 0, 1) def _write_fsinfo(pdrv: t.CUInt8T, free_count: t.CUInt32T, next_free: t.CUInt32T) -> types.DRESULT: buf: t.CArray[t.CUInt8T, 512] string.memset(c.Addr(buf[0]), 0, 512) types._write32(c.Addr(buf[0]), 0, 0x41615252) types._write32(c.Addr(buf[0]), 484, 0x61417272) types._write32(c.Addr(buf[0]), 488, free_count) types._write32(c.Addr(buf[0]), 492, next_free) types._write32(c.Addr(buf[0]), 508, 0xAA550000) return diskio.write(pdrv, c.Addr(buf[0]), 1, 1) def _init_fat(pdrv: t.CUInt8T, fat_start: t.CUInt64T, fat_sz: t.CUInt32T, root_cluster: t.CUInt32T) -> types.DRESULT: buf: t.CArray[t.CUInt8T, 512] string.memset(c.Addr(buf[0]), 0, 512) types._write32(c.Addr(buf[0]), 0, 0x0FFFFFF8) types._write32(c.Addr(buf[0]), 4, 0x0FFFFFFF) types._write32(c.Addr(buf[0]), 8, 0x0FFFFFFF) if root_cluster >= 2: cluster_off: t.CUInt32T = root_cluster * 4 sector_off: t.CUInt32T = cluster_off / 512 byte_off: t.CUInt32T = cluster_off % 512 if sector_off == 0: types._write32(c.Addr(buf[0]), byte_off, 0x0FFFFFFF) res: types.DRESULT = diskio.write(pdrv, c.Addr(buf[0]), t.CUInt32T(fat_start), 1) if res != types.DRESULT.RES_OK: return res string.memset(c.Addr(buf[0]), 0, 512) s: t.CUInt32T for s in range(1, fat_sz): res2: types.DRESULT = diskio.write(pdrv, c.Addr(buf[0]), t.CUInt32T(fat_start) + s, 1) if res2 != types.DRESULT.RES_OK: return res2 return types.DRESULT.RES_OK def _init_root_dir(pdrv: t.CUInt8T, root_sector: t.CUInt64T, sec_per_clus: t.CUInt8T) -> types.DRESULT: buf: t.CArray[t.CUInt8T, 512] string.memset(c.Addr(buf[0]), 0, 512) s: t.CUInt8T for s in range(sec_per_clus): res: types.DRESULT = diskio.write(pdrv, c.Addr(buf[0]), t.CUInt32T(root_sector + t.CUInt64T(s)), 1) if res != types.DRESULT.RES_OK: return res return types.DRESULT.RES_OK def _calc_sec_per_clus(total_sectors: t.CUInt64T) -> t.CUInt8T: ts: t.CUInt64T = total_sectors if ts < 532480: return 1 elif ts < 16777216: return 8 elif ts < 33554432: return 16 elif ts < 67108864: return 32 else: return 64 def mkfs(pdrv: t.CUInt8T, sec_per_clus: t.CUInt8T, vol_id: t.CUInt32T) -> types.FRESULT: if pdrv != types.DEV_DISK: return types.FRESULT.FR_INVALID_DRIVE total_sectors_buf: t.CUInt32T = 0 diskio.ioctl(pdrv, types.GET_SECTOR_COUNT, c.Addr(total_sectors_buf)) total_sectors: t.CUInt64T = t.CUInt64T(total_sectors_buf) if total_sectors < 65536: return types.FRESULT.FR_MKFS_ABORTED if sec_per_clus == 0: sec_per_clus = _calc_sec_per_clus(total_sectors) if sec_per_clus != 1 and sec_per_clus != 2 and sec_per_clus != 4 and sec_per_clus != 8 and sec_per_clus != 16 and sec_per_clus != 32 and sec_per_clus != 64 and sec_per_clus != 128: return types.FRESULT.FR_INVALID_PARAMETER if vol_id == 0: vol_id = ftime.get_fattime() reserved: t.CUInt32T = 32 num_fats: t.CUInt8T = 2 fat_sz: t.CUInt32T = _calc_fat_size(total_sectors, reserved, sec_per_clus, num_fats) data_sectors: t.CUInt64T = total_sectors - t.CUInt64T(reserved) - t.CUInt64T(fat_sz) * t.CUInt64T(num_fats) total_clusters: t.CUInt32T = t.CUInt32T(data_sectors / t.CUInt64T(sec_per_clus)) free_count: t.CUInt32T = total_clusters - 1 res: types.DRESULT = _write_boot_sector(pdrv, total_sectors, sec_per_clus, vol_id, fat_sz) if res != types.DRESULT.RES_OK: return types.FRESULT.FR_DISK_ERR res2: types.DRESULT = _write_fsinfo(pdrv, free_count, 3) if res2 != types.DRESULT.RES_OK: return types.FRESULT.FR_DISK_ERR boot_backup: t.CArray[t.CUInt8T, 512] diskio.read(pdrv, c.Addr(boot_backup[0]), 0, 1) diskio.write(pdrv, c.Addr(boot_backup[0]), 6, 1) fsinfo_backup: t.CArray[t.CUInt8T, 512] diskio.read(pdrv, c.Addr(fsinfo_backup[0]), 1, 1) diskio.write(pdrv, c.Addr(fsinfo_backup[0]), 7, 1) fat_start: t.CUInt64T = t.CUInt64T(reserved) res3: types.DRESULT = _init_fat(pdrv, fat_start, fat_sz, 2) if res3 != types.DRESULT.RES_OK: return types.FRESULT.FR_DISK_ERR fat2_start: t.CUInt64T = fat_start + t.CUInt64T(fat_sz) res4: types.DRESULT = _init_fat(pdrv, fat2_start, fat_sz, 2) if res4 != types.DRESULT.RES_OK: return types.FRESULT.FR_DISK_ERR root_sector: t.CUInt64T = fat2_start + t.CUInt64T(fat_sz) res5: types.DRESULT = _init_root_dir(pdrv, root_sector, sec_per_clus) if res5 != types.DRESULT.RES_OK: return types.FRESULT.FR_DISK_ERR return types.FRESULT.FR_OK