Initial import of ViperOS
This commit is contained in:
237
VKernel/Kernel/drivers/fs/fat32/example_fs.py
Normal file
237
VKernel/Kernel/drivers/fs/fat32/example_fs.py
Normal file
@@ -0,0 +1,237 @@
|
||||
from stdint import *
|
||||
import fat32 as fs
|
||||
import fat32_types as types
|
||||
import fat32_part as part
|
||||
import fat32_mkfs as mkfs_mod
|
||||
import t, c
|
||||
|
||||
|
||||
def print_fresult(res: types.FRESULT, msg: t.CConst) -> t.CInt:
|
||||
if res == types.FRESULT.FR_OK:
|
||||
print(f"[成功] {msg}")
|
||||
return 0
|
||||
else:
|
||||
print(f"[失败] {msg}: {res}")
|
||||
return -1
|
||||
|
||||
|
||||
def print_fresult_void(res: types.FRESULT, msg: t.CConst):
|
||||
print_fresult(res, msg)
|
||||
|
||||
|
||||
def example_main() -> t.CInt:
|
||||
print("=== FAT32 文件系统完整示例 ===")
|
||||
print()
|
||||
|
||||
# 1. 扫描可用驱动器
|
||||
print("--- 1. 扫描可用驱动器 ---")
|
||||
res: types.FRESULT = fs.scan_drives()
|
||||
print_fresult_void(res, "扫描驱动器")
|
||||
|
||||
drive_count: t.CInt = fs.get_drive_count()
|
||||
print(f"找到 {drive_count} 个驱动器")
|
||||
i: t.CInt
|
||||
for i in range(drive_count):
|
||||
letter: t.CChar = fs.get_drive_letter(i)
|
||||
part_count: t.CInt = fs.get_partition_count(letter)
|
||||
print(f" 驱动器 {i}: {letter}")
|
||||
for j in range(part_count):
|
||||
is_fat32: t.CInt = fs.is_partition_fat32(letter, j)
|
||||
print(f" 分区 {j}: FAT32={is_fat32}")
|
||||
print()
|
||||
|
||||
# 2. 挂载文件系统
|
||||
print("--- 2. 挂载文件系统 ---")
|
||||
res = fs.mount()
|
||||
if print_fresult(res, "挂载文件系统") != 0:
|
||||
print("提示: 可能需要先格式化磁盘")
|
||||
print()
|
||||
|
||||
# 3. 文件系统信息
|
||||
print("--- 3. 文件系统信息 ---")
|
||||
mounted: t.CInt = fs.is_mounted()
|
||||
print(f"已挂载: {mounted}")
|
||||
if mounted:
|
||||
total_clusters: t.CUInt32T = fs.get_total()
|
||||
free_clusters: t.CUInt32T = fs.get_free()
|
||||
cluster_size: t.CUInt32T = fs.get_cluster_size()
|
||||
total_bytes: t.CUInt64T = t.CUInt64T(total_clusters) * t.CUInt64T(cluster_size)
|
||||
free_bytes: t.CUInt64T = t.CUInt64T(free_clusters) * t.CUInt64T(cluster_size)
|
||||
print(f"总簇数: {total_clusters}")
|
||||
print(f"空闲簇数: {free_clusters}")
|
||||
print(f"簇大小: {cluster_size} 字节")
|
||||
print(f"总大小: {total_bytes} 字节")
|
||||
print(f"空闲大小: {free_bytes} 字节")
|
||||
print()
|
||||
|
||||
# 4. 元数据操作
|
||||
print("--- 4. 元数据操作 ---")
|
||||
fs.set_metadata(0x12345678)
|
||||
metadata: t.CUInt32T = fs.get_metadata()
|
||||
print(f"设置的元数据: 0x{metadata:08X}")
|
||||
print()
|
||||
|
||||
# 5. 获取 FAT 时间
|
||||
print("--- 5. 获取 FAT 时间 ---")
|
||||
fattime: t.CUInt32T = fs.get_fattime()
|
||||
print(f"当前 FAT 时间: 0x{fattime:08X}")
|
||||
print()
|
||||
|
||||
# 6. 目录操作
|
||||
if fs.is_mounted():
|
||||
print("--- 6. 目录操作 ---")
|
||||
|
||||
# 创建目录
|
||||
res = fs.mkdir("/test_dir_1")
|
||||
print_fresult_void(res, "创建目录 /test_dir_1")
|
||||
|
||||
res = fs.mkdir("/test_dir_1/subdir")
|
||||
print_fresult_void(res, "创建子目录 /test_dir_1/subdir")
|
||||
|
||||
res = fs.mkdir("/test_dir_2")
|
||||
print_fresult_void(res, "创建目录 /test_dir_2")
|
||||
print()
|
||||
|
||||
# 7. 文件操作
|
||||
print("--- 7. 文件操作 ---")
|
||||
|
||||
# 创建并写入文件
|
||||
fp1: types.fileobj | t.CPtr = fs.open("/test_dir_1/file1.txt", types.FA_CREATE_ALWAYS | types.FA_WRITE)
|
||||
if fp1 is not None:
|
||||
test_data1: t.CConst = "Hello, World!"
|
||||
written: t.CUInt32T = fs.write(fp1, test_data1, 13)
|
||||
print(f"写入文件 /test_dir_1/file1.txt: {written} 字节")
|
||||
fs.close(fp1)
|
||||
|
||||
# 打开追加
|
||||
fp2: types.fileobj | t.CPtr = fs.open("/test_dir_1/file1.txt", types.FA_OPEN_ALWAYS | types.FA_WRITE | types.FA_OPEN_APPEND)
|
||||
if fp2 is not None:
|
||||
test_data2: t.CConst = " Append data!"
|
||||
written2: t.CUInt32T = fs.write(fp2, test_data2, 13)
|
||||
print(f"追加写入: {written2} 字节")
|
||||
fs.close(fp2)
|
||||
|
||||
# 读取文件
|
||||
fp3: types.fileobj | t.CPtr = fs.open("/test_dir_1/file1.txt", types.FA_OPEN_EXISTING | types.FA_READ)
|
||||
if fp3 is not None:
|
||||
buf: t.CArray[t.CUInt8T, 256]
|
||||
read_bytes: t.CUInt32T = fs.read(fp3, t.CVoid(c.Addr(buf[0]), t.CPtr), 256)
|
||||
print(f"读取字节数: {read_bytes}")
|
||||
print(f"文件内容: {t.CChar(c.Addr(buf[0]), t.CPtr)}")
|
||||
|
||||
# seek 和 tell
|
||||
fs.seek(fp3, 5)
|
||||
pos: t.CUInt32T = fs.tell(fp3)
|
||||
print(f"seek 到位置 5, 当前位置: {pos}")
|
||||
|
||||
read_bytes2: t.CUInt32T = fs.read(fp3, t.CVoid(c.Addr(buf[0]), t.CPtr), 256)
|
||||
print(f"从位置 5 读取: {t.CChar(c.Addr(buf[0]), t.CPtr)}")
|
||||
|
||||
# 获取文件大小
|
||||
fsize: t.CUInt32T = fs.size(fp3)
|
||||
print(f"文件大小: {fsize} 字节")
|
||||
|
||||
fs.close(fp3)
|
||||
|
||||
# 创建另一个文件
|
||||
fp4: types.fileobj | t.CPtr = fs.open("/test_dir_1/large_file.txt", types.FA_CREATE_ALWAYS | types.FA_WRITE)
|
||||
if fp4 is not None:
|
||||
large_data: t.CArray[t.CUInt8T, 1024]
|
||||
k: t.CInt
|
||||
for k in range(1024):
|
||||
large_data[k] = t.CUInt8T(ord('A') + (k % 26))
|
||||
written3: t.CUInt32T = fs.write(fp4, t.CVoid(c.Addr(large_data[0]), t.CPtr), 1024)
|
||||
print(f"创建大文件, 写入: {written3} 字节")
|
||||
fs.close(fp4)
|
||||
print()
|
||||
|
||||
# 8. 文件状态和属性
|
||||
print("--- 8. 文件状态和属性 ---")
|
||||
|
||||
info: types.fileinfo
|
||||
res = fs.stat("/test_dir_1/file1.txt", info)
|
||||
print_fresult_void(res, "获取文件信息")
|
||||
if res == types.FRESULT.FR_OK:
|
||||
print(f" 文件名: {info.fname}")
|
||||
print(f" 大小: {info.file_size} 字节")
|
||||
print(f" 属性: 0x{info.attr:02X}")
|
||||
print(f" 创建时间: 0x{info.ctime:04X}")
|
||||
print(f" 创建日期: 0x{info.cdate:04X}")
|
||||
print(f" 修改时间: 0x{info.mtime:04X}")
|
||||
print(f" 修改日期: 0x{info.mdate:04X}")
|
||||
print(f" 访问日期: 0x{info.adate:04X}")
|
||||
|
||||
# 修改属性
|
||||
res = fs.chmod("/test_dir_1/file1.txt", types.AM_RDO, types.AM_RDO)
|
||||
print_fresult_void(res, "设置文件为只读")
|
||||
print()
|
||||
|
||||
# 9. 重命名和移动
|
||||
print("--- 9. 重命名和移动 ---")
|
||||
|
||||
res = fs.rename("/test_dir_1/file1.txt", "/test_dir_1/renamed.txt")
|
||||
print_fresult_void(res, "重命名文件")
|
||||
|
||||
res = fs.move("/test_dir_1/renamed.txt", "/test_dir_2/moved.txt")
|
||||
print_fresult_void(res, "移动文件")
|
||||
|
||||
res = fs.rename("/test_dir_2", "/test_dir_renamed")
|
||||
print_fresult_void(res, "重命名目录")
|
||||
print()
|
||||
|
||||
# 10. 列出目录
|
||||
print("--- 10. 列出目录 ---")
|
||||
|
||||
dp: types.dirobj
|
||||
res = fs.opendir("/", dp)
|
||||
if res == types.FRESULT.FR_OK:
|
||||
print("根目录内容:")
|
||||
dir_info: types.fileinfo
|
||||
while True:
|
||||
res = fs.readdir(dp, dir_info)
|
||||
if res != types.FRESULT.FR_OK:
|
||||
break
|
||||
attr_str: t.CConst = ""
|
||||
if dir_info.attr & types.AM_DIR:
|
||||
attr_str = attr_str + "D"
|
||||
else:
|
||||
attr_str = attr_str + "F"
|
||||
if dir_info.attr & types.AM_RDO:
|
||||
attr_str = attr_str + "R"
|
||||
if dir_info.attr & types.AM_HID:
|
||||
attr_str = attr_str + "H"
|
||||
if dir_info.attr & types.AM_SYS:
|
||||
attr_str = attr_str + "S"
|
||||
if dir_info.attr & types.AM_ARC:
|
||||
attr_str = attr_str + "A"
|
||||
print(f" [{attr_str}] {dir_info.fname} ({dir_info.file_size} 字节)")
|
||||
fs.closedir(dp)
|
||||
print()
|
||||
|
||||
# 11. 删除文件和目录
|
||||
print("--- 11. 删除文件和目录 ---")
|
||||
|
||||
res = fs.remove("/test_dir_renamed/moved.txt")
|
||||
print_fresult_void(res, "删除文件")
|
||||
|
||||
res = fs.remove("/test_dir_1/large_file.txt")
|
||||
print_fresult_void(res, "删除大文件")
|
||||
|
||||
res = fs.rmdir("/test_dir_1/subdir")
|
||||
print_fresult_void(res, "删除子目录")
|
||||
|
||||
res = fs.rmdir("/test_dir_1")
|
||||
print_fresult_void(res, "删除目录 /test_dir_1")
|
||||
|
||||
res = fs.rmdir("/test_dir_renamed")
|
||||
print_fresult_void(res, "删除目录 /test_dir_renamed")
|
||||
print()
|
||||
|
||||
# 12. 卸载文件系统
|
||||
print("--- 12. 卸载文件系统 ---")
|
||||
res = fs.unmount()
|
||||
print_fresult_void(res, "卸载文件系统")
|
||||
print()
|
||||
|
||||
print("=== 示例完成 ===")
|
||||
return 0
|
||||
208
VKernel/Kernel/drivers/fs/fat32/fat32.py
Normal file
208
VKernel/Kernel/drivers/fs/fat32/fat32.py
Normal file
@@ -0,0 +1,208 @@
|
||||
from stdint import *
|
||||
import string
|
||||
import fat32_types as types
|
||||
import fat32_time as ftime
|
||||
import fat32_mkfs as mkfs_mod
|
||||
import fat32_part as part
|
||||
import fat32_diskio as diskio
|
||||
import sched.sched as sched
|
||||
import t, c
|
||||
|
||||
|
||||
default_fs: types.volinfo = types.volinfo()
|
||||
_fs_lock: t.CInt = 0
|
||||
|
||||
def lock():
|
||||
global _fs_lock
|
||||
while True:
|
||||
c.Asm("cli")
|
||||
if _fs_lock == 0:
|
||||
_fs_lock = 1
|
||||
c.Asm("sti")
|
||||
return
|
||||
c.Asm("sti")
|
||||
sched.Scheduler._yield()
|
||||
|
||||
def unlock():
|
||||
global _fs_lock
|
||||
_fs_lock = 0
|
||||
|
||||
def mount() -> types.FRESULT:
|
||||
default_fs.pdrv = 0
|
||||
default_fs.hidden_sectors = 0
|
||||
buf: t.CArray[t.CUInt8T, 512]
|
||||
dres: types.DRESULT = diskio.read(0, c.Addr(buf[0]), 0, 1)
|
||||
if dres == types.DRESULT.RES_OK:
|
||||
if buf[0] == 0xEB or buf[0] == 0xE9:
|
||||
default_fs.hidden_sectors = 0
|
||||
else:
|
||||
sig: t.CUInt16T = t.CUInt16T(buf[510]) | (t.CUInt16T(buf[511]) << 8)
|
||||
if sig == 0xAA55:
|
||||
ptype: t.CUInt8T = buf[450]
|
||||
if ptype != 0:
|
||||
slba: t.CUInt32T = t.CUInt32T(buf[454]) | (t.CUInt32T(buf[455]) << 8) | (t.CUInt32T(buf[456]) << 16) | (t.CUInt32T(buf[457]) << 24)
|
||||
default_fs.hidden_sectors = slba
|
||||
if default_fs.mounted: return types.FRESULT.FR_OK
|
||||
dsk_res: types.DRESULT = diskio.status(default_fs.pdrv)
|
||||
if dsk_res != types.DRESULT.RES_OK:
|
||||
dsk_res = diskio.init(default_fs.pdrv)
|
||||
if dsk_res != types.DRESULT.RES_OK: return types.FRESULT.FR_NOT_READY
|
||||
default_fs.winsect = 0xFFFFFFFFFFFFFFFF
|
||||
default_fs.fat_winsect = 0xFFFFFFFFFFFFFFFF
|
||||
wres: types.FRESULT = default_fs.win_read(0)
|
||||
if wres != types.FRESULT.FR_OK: return types.FRESULT.FR_DISK_ERR
|
||||
bps: t.CUInt16T = default_fs.win[11] | (t.CUInt16T(default_fs.win[12]) << 8)
|
||||
spc: t.CUInt8T = default_fs.win[13]
|
||||
rsc: t.CUInt16T = default_fs.win[14] | (t.CUInt16T(default_fs.win[15]) << 8)
|
||||
nf: t.CUInt8T = default_fs.win[16]
|
||||
if bps != 512: return types.FRESULT.FR_NO_FILESYSTEM
|
||||
if spc == 0 or (spc & (spc - 1)) != 0: return types.FRESULT.FR_NO_FILESYSTEM
|
||||
if rsc == 0: return types.FRESULT.FR_NO_FILESYSTEM
|
||||
if nf == 0: return types.FRESULT.FR_NO_FILESYSTEM
|
||||
root_ent: t.CUInt16T = default_fs.win[17] | (t.CUInt16T(default_fs.win[18]) << 8)
|
||||
fat16sz: t.CUInt16T = default_fs.win[22] | (t.CUInt16T(default_fs.win[23]) << 8)
|
||||
tot32: t.CUInt32T = t.CUInt32T(default_fs.win[32]) | (t.CUInt32T(default_fs.win[33]) << 8) | (t.CUInt32T(default_fs.win[34]) << 16) | (t.CUInt32T(default_fs.win[35]) << 24)
|
||||
fat32sz: t.CUInt32T = t.CUInt32T(default_fs.win[36]) | (t.CUInt32T(default_fs.win[37]) << 8) | (t.CUInt32T(default_fs.win[38]) << 16) | (t.CUInt32T(default_fs.win[39]) << 24)
|
||||
root_clus: t.CUInt32T = t.CUInt32T(default_fs.win[44]) | (t.CUInt32T(default_fs.win[45]) << 8) | (t.CUInt32T(default_fs.win[46]) << 16) | (t.CUInt32T(default_fs.win[47]) << 24)
|
||||
if root_ent != 0 or fat16sz != 0: return types.FRESULT.FR_NO_FILESYSTEM
|
||||
if fat32sz == 0: return types.FRESULT.FR_NO_FILESYSTEM
|
||||
if tot32 == 0: return types.FRESULT.FR_NO_FILESYSTEM
|
||||
if default_fs.win[510] != 0x55 or default_fs.win[511] != 0xAA: return types.FRESULT.FR_NO_FILESYSTEM
|
||||
fsinfo_sec: t.CUInt16T = default_fs.win[48] | (t.CUInt16T(default_fs.win[49]) << 8)
|
||||
bkboot_sec: t.CUInt16T = default_fs.win[50] | (t.CUInt16T(default_fs.win[51]) << 8)
|
||||
default_fs.sector_size = 512
|
||||
default_fs.cluster_sectors = spc
|
||||
default_fs.cluster_size = t.CUInt32T(spc) * 512
|
||||
default_fs.num_fats = nf
|
||||
default_fs.reserved_sectors = rsc
|
||||
default_fs.fat_size = fat32sz
|
||||
default_fs.fat_start = t.CUInt64T(rsc)
|
||||
default_fs.total_sectors = t.CUInt64T(tot32)
|
||||
default_fs.root_cluster = root_clus
|
||||
default_fs.fsinfo_sector = fsinfo_sec
|
||||
default_fs.backup_sector = bkboot_sec
|
||||
default_fs.vol_id = t.CUInt32T(default_fs.win[67]) | (t.CUInt32T(default_fs.win[68]) << 8) | (t.CUInt32T(default_fs.win[69]) << 16) | (t.CUInt32T(default_fs.win[70]) << 24)
|
||||
data_sectors: t.CUInt64T = default_fs.total_sectors - t.CUInt64T(rsc) - t.CUInt64T(t.CUInt64T(nf) * t.CUInt64T(fat32sz))
|
||||
default_fs.total_clusters = t.CUInt32T(data_sectors / t.CUInt64T(spc))
|
||||
default_fs.data_start = default_fs.fat_start + t.CUInt64T(t.CUInt64T(nf) * t.CUInt64T(fat32sz))
|
||||
default_fs.last_alloc = 2
|
||||
default_fs.free_clusters = 0xFFFFFFFF
|
||||
if fsinfo_sec != 0:
|
||||
default_fs.fsinfo_read()
|
||||
default_fs.mounted = 1
|
||||
return types.FRESULT.FR_OK
|
||||
|
||||
def unmount() -> types.FRESULT:
|
||||
return default_fs.unmount()
|
||||
|
||||
def format(sec_per_clus: t.CUInt8T = 0, vol_id: t.CUInt32T = 0) -> types.FRESULT:
|
||||
return mkfs_mod.mkfs(default_fs.pdrv, sec_per_clus, vol_id)
|
||||
|
||||
def open(path: t.CConst | str, mode: t.CUInt8T) -> types.fileobj | t.CPtr:
|
||||
return default_fs.file_open(path, mode)
|
||||
|
||||
def close(fp: types.fileobj | t.CPtr) -> types.FRESULT:
|
||||
return fp.close()
|
||||
|
||||
def read(fp: types.fileobj | t.CPtr, buff: t.CVoid | t.CPtr, btr: t.CUInt32T) -> t.CUInt32T:
|
||||
br: t.CUInt32T = 0
|
||||
fp.read(buff, btr, c.Addr(br))
|
||||
return br
|
||||
|
||||
def write(fp: types.fileobj | t.CPtr, buff: t.CConst | t.CVoid | t.CPtr, btw: t.CUInt32T) -> t.CUInt32T:
|
||||
bw: t.CUInt32T = 0
|
||||
fp.write(buff, btw, c.Addr(bw))
|
||||
return bw
|
||||
|
||||
def seek(fp: types.fileobj | t.CPtr, offset: t.CUInt32T) -> types.FRESULT:
|
||||
return fp.seek(offset)
|
||||
|
||||
def tell(fp: types.fileobj | t.CPtr) -> t.CUInt32T:
|
||||
return fp.tell()
|
||||
|
||||
def size(fp: types.fileobj | t.CPtr) -> t.CUInt32T:
|
||||
return fp.size()
|
||||
|
||||
def truncate(fp: types.fileobj | t.CPtr) -> types.FRESULT:
|
||||
return fp.truncate()
|
||||
|
||||
def remove(path: t.CConst | str) -> types.FRESULT:
|
||||
return default_fs.file_delete(path)
|
||||
|
||||
def rename(old_path: t.CConst | str, new_path: t.CConst | str) -> types.FRESULT:
|
||||
return default_fs.file_rename(old_path, new_path)
|
||||
|
||||
def move(old_path: t.CConst | str, new_path: t.CConst | str) -> types.FRESULT:
|
||||
return default_fs.file_rename(old_path, new_path)
|
||||
|
||||
def stat(path: t.CConst | str, info: types.fileinfo | t.CPtr) -> types.FRESULT:
|
||||
return default_fs.file_stat(path, info)
|
||||
|
||||
def mkdir(path: t.CConst | str) -> types.FRESULT:
|
||||
return default_fs.dir_make(path)
|
||||
|
||||
def rmdir(path: t.CConst | str) -> types.FRESULT:
|
||||
return default_fs.dir_remove(path)
|
||||
|
||||
def opendir(path: t.CConst | str, dp: types.dirobj | t.CPtr) -> types.FRESULT:
|
||||
return default_fs.dir_open_path(path, dp)
|
||||
|
||||
def readdir(dp: types.dirobj | t.CPtr, info: types.fileinfo | t.CPtr) -> types.FRESULT:
|
||||
return default_fs.dir_read(dp, info)
|
||||
|
||||
def closedir(dp: types.dirobj | t.CPtr):
|
||||
dp.is_open = 0
|
||||
|
||||
def chmod(path: t.CConst | str, attr: t.CUInt8T, mask: t.CUInt8T) -> types.FRESULT:
|
||||
return default_fs.chmod(path, attr, mask)
|
||||
|
||||
def utime(path: t.CConst | str, mtime: t.CUInt16T, mdate: t.CUInt16T) -> types.FRESULT:
|
||||
return default_fs.utime(path, mtime, mdate)
|
||||
|
||||
def get_free() -> t.CUInt32T:
|
||||
if not default_fs.mounted: return 0
|
||||
if default_fs.free_clusters == 0xFFFFFFFF:
|
||||
return default_fs.count_free_clusters()
|
||||
return default_fs.free_clusters
|
||||
|
||||
def get_total() -> t.CUInt32T:
|
||||
if not default_fs.mounted: return 0
|
||||
return default_fs.total_clusters
|
||||
|
||||
def get_cluster_size() -> t.CUInt32T:
|
||||
if not default_fs.mounted: return 0
|
||||
return default_fs.cluster_size
|
||||
|
||||
def is_mounted() -> t.CInt:
|
||||
return default_fs.mounted
|
||||
|
||||
def last_error() -> t.CUInt32T:
|
||||
return default_fs.last_error
|
||||
|
||||
def get_fattime() -> t.CUInt32T:
|
||||
return ftime.get_fattime()
|
||||
|
||||
def get_metadata() -> t.CUInt32T:
|
||||
return default_fs.metadata
|
||||
|
||||
def set_metadata(val: t.CUInt32T):
|
||||
default_fs.metadata = val
|
||||
|
||||
def scan_drives() -> types.FRESULT:
|
||||
return part.scan_drives()
|
||||
|
||||
def get_drive_count() -> t.CInt:
|
||||
return part.get_drive_count()
|
||||
|
||||
def get_drive_letter(idx: t.CInt) -> t.CChar:
|
||||
return part.get_drive_letter(idx)
|
||||
|
||||
def set_drive_letter(idx: t.CInt, letter: t.CChar) -> types.FRESULT:
|
||||
return part.set_drive_letter(idx, letter)
|
||||
|
||||
def get_partition_count(letter: t.CChar) -> t.CInt:
|
||||
return part.get_partition_count(letter)
|
||||
|
||||
def is_partition_fat32(letter: t.CChar, part_idx: t.CInt) -> t.CInt:
|
||||
return part.is_partition_fat32(letter, part_idx)
|
||||
|
||||
16
VKernel/Kernel/drivers/fs/fat32/fat32_core.py
Normal file
16
VKernel/Kernel/drivers/fs/fat32/fat32_core.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from stdint import *
|
||||
import fat32_types as types
|
||||
import t, c
|
||||
|
||||
|
||||
_read32 = types._read32
|
||||
_read16 = types._read16
|
||||
_write32 = types._write32
|
||||
_write16 = types._write16
|
||||
|
||||
|
||||
def is_eoc(cluster: t.CUInt32T) -> t.CInt:
|
||||
return 1 if (cluster >= types.CLUSTER_EOC_MIN and cluster <= types.CLUSTER_EOC_MAX) else 0
|
||||
|
||||
def is_free(cluster: t.CUInt32T) -> t.CInt:
|
||||
return 1 if cluster == types.CLUSTER_FREE else 0
|
||||
13
VKernel/Kernel/drivers/fs/fat32/fat32_dir.py
Normal file
13
VKernel/Kernel/drivers/fs/fat32/fat32_dir.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from stdint import *
|
||||
import fat32_types as types
|
||||
import t, c
|
||||
|
||||
|
||||
sfn_checksum = types.sfn_checksum
|
||||
uni2oem_placeholder = types.uni2oem_placeholder
|
||||
lfn_get_char = types.lfn_get_char
|
||||
lfn_set_char = types.lfn_set_char
|
||||
lfn_extract = types.lfn_extract
|
||||
sfn_from_lfn = types.sfn_from_lfn
|
||||
sfn_to_str = types.sfn_to_str
|
||||
_split_path = types._split_path
|
||||
76
VKernel/Kernel/drivers/fs/fat32/fat32_diskio.py
Normal file
76
VKernel/Kernel/drivers/fs/fat32/fat32_diskio.py
Normal file
@@ -0,0 +1,76 @@
|
||||
import drivers.storage.ide.ide as ide
|
||||
import fat32_types as types
|
||||
import spinlock
|
||||
import string
|
||||
import t, c
|
||||
|
||||
|
||||
MAX_DRIVES: t.CDefine = 4
|
||||
|
||||
drive_initialized: t.CArray[t.CInt, MAX_DRIVES]
|
||||
drive_lock: spinlock._spinlock = spinlock._spinlock()
|
||||
|
||||
def status(pdrv: t.CUInt8T) -> types.DRESULT:
|
||||
if pdrv >= MAX_DRIVES: return types.DRESULT.RES_PARERR
|
||||
if not drive_initialized[pdrv]: return types.DRESULT.RES_NOTRDY
|
||||
return types.DRESULT.RES_OK
|
||||
|
||||
def init(pdrv: t.CUInt8T) -> types.DRESULT:
|
||||
if pdrv >= MAX_DRIVES: return types.DRESULT.RES_PARERR
|
||||
drive_lock.lock()
|
||||
err: t.CInt = ide.init()
|
||||
if err != 0:
|
||||
drive_lock.unlock()
|
||||
return types.DRESULT.RES_NOTRDY
|
||||
drive_initialized[pdrv] = 1
|
||||
drive_lock.unlock()
|
||||
return types.DRESULT.RES_OK
|
||||
|
||||
def read(pdrv: t.CUInt8T, buff: t.CUInt8T | t.CPtr, sector: t.CUInt32T, count: t.CUInt32T) -> types.DRESULT:
|
||||
if pdrv >= MAX_DRIVES: return types.DRESULT.RES_PARERR
|
||||
if not drive_initialized[pdrv]: return types.DRESULT.RES_NOTRDY
|
||||
drive_lock.lock()
|
||||
i: t.CUInt32T
|
||||
for i in range(count):
|
||||
rd_res: t.CInt = ide.readSector(sector + i, buff + (i * 512))
|
||||
if rd_res != 0:
|
||||
drive_lock.unlock()
|
||||
return types.DRESULT.RES_ERROR
|
||||
drive_lock.unlock()
|
||||
return types.DRESULT.RES_OK
|
||||
|
||||
def write(pdrv: t.CUInt8T, buff: t.CConst | t.CUInt8T | t.CPtr, sector: t.CUInt32T, count: t.CUInt32T) -> types.DRESULT:
|
||||
if pdrv >= MAX_DRIVES: return types.DRESULT.RES_PARERR
|
||||
if not drive_initialized[pdrv]: return types.DRESULT.RES_NOTRDY
|
||||
drive_lock.lock()
|
||||
i: t.CUInt32T
|
||||
for i in range(count):
|
||||
if ide.writeSector(sector + i, buff + (i * 512)) != 0:
|
||||
drive_lock.unlock()
|
||||
return types.DRESULT.RES_ERROR
|
||||
drive_lock.unlock()
|
||||
return types.DRESULT.RES_OK
|
||||
|
||||
def ioctl(pdrv: t.CUInt8T, cmd: t.CUInt8T, buff: t.CVoid | t.CPtr) -> types.DRESULT:
|
||||
if pdrv >= MAX_DRIVES: return types.DRESULT.RES_PARERR
|
||||
if not drive_initialized[pdrv]: return types.DRESULT.RES_NOTRDY
|
||||
match cmd:
|
||||
case types.GET_SECTOR_COUNT:
|
||||
disk_size: t.CUInt64T = ide.getDiskSize()
|
||||
if disk_size == 0:
|
||||
c.Set(t.CUInt32T(buff, t.CPtr), 131072)
|
||||
elif disk_size > 0xFFFFFFFF:
|
||||
c.Set(t.CUInt32T(buff, t.CPtr), 0xFFFFFFFF)
|
||||
else:
|
||||
c.Set(t.CUInt32T(buff, t.CPtr), t.CUInt32T(disk_size))
|
||||
return types.DRESULT.RES_OK
|
||||
case types.GET_SECTOR_SIZE:
|
||||
c.Set(t.CUInt16T(buff, t.CPtr), 512)
|
||||
return types.DRESULT.RES_OK
|
||||
case types.GET_BLOCK_SIZE:
|
||||
c.Set(t.CUInt32T(buff, t.CPtr), 1)
|
||||
return types.DRESULT.RES_OK
|
||||
case types.CTRL_SYNC:
|
||||
return types.DRESULT.RES_OK
|
||||
case _:
|
||||
return types.DRESULT.RES_PARERR
|
||||
17
VKernel/Kernel/drivers/fs/fat32/fat32_file.py
Normal file
17
VKernel/Kernel/drivers/fs/fat32/fat32_file.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from stdint import *
|
||||
import fat32_types as types
|
||||
import t, c
|
||||
|
||||
|
||||
handle_table = types.handle_table
|
||||
lock_table = types.lock_table
|
||||
handles_initialized = types.handles_initialized
|
||||
handles_init = types.handles_init
|
||||
handle_alloc = types.handle_alloc
|
||||
lock_check = types.lock_check
|
||||
lock_acquire = types.lock_acquire
|
||||
lock_release = types.lock_release
|
||||
|
||||
def handle_free(fp):
|
||||
fp.is_open = 0
|
||||
fp.lock_count = 0
|
||||
143
VKernel/Kernel/drivers/fs/fat32/fat32_mkfs.py
Normal file
143
VKernel/Kernel/drivers/fs/fat32/fat32_mkfs.py
Normal file
@@ -0,0 +1,143 @@
|
||||
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
|
||||
147
VKernel/Kernel/drivers/fs/fat32/fat32_part.py
Normal file
147
VKernel/Kernel/drivers/fs/fat32/fat32_part.py
Normal file
@@ -0,0 +1,147 @@
|
||||
from stdint import *
|
||||
import fat32_types as types
|
||||
import fat32_diskio as diskio
|
||||
import string
|
||||
import t, c
|
||||
|
||||
|
||||
MAX_VOLUMES: t.CDefine = 4
|
||||
MAX_PARTITIONS: t.CDefine = 4
|
||||
|
||||
MBR_SIGNATURE: t.CDefine = 0xAA55
|
||||
PART_TYPE_FAT32: t.CDefine = 0x0C
|
||||
PART_TYPE_FAT32_LBA: t.CDefine = 0x0B
|
||||
PART_TYPE_FAT16: t.CDefine = 0x06
|
||||
PART_TYPE_FAT16_LBA: t.CDefine = 0x0E
|
||||
|
||||
class partition_entry:
|
||||
boot_flag: t.CUInt8T
|
||||
start_chs: t.CArray[t.CUInt8T, 3]
|
||||
part_type: t.CUInt8T
|
||||
end_chs: t.CArray[t.CUInt8T, 3]
|
||||
start_lba: t.CUInt32T
|
||||
total_sectors: t.CUInt32T
|
||||
|
||||
drive_pdrv: t.CArray[t.CUInt8T, MAX_VOLUMES]
|
||||
drive_num_parts: t.CArray[t.CInt, MAX_VOLUMES]
|
||||
drive_letter_map: t.CArray[t.CChar, MAX_VOLUMES]
|
||||
volume_mounted: t.CArray[t.CInt, MAX_VOLUMES]
|
||||
part_types: t.CArray[t.CUInt8T, MAX_VOLUMES * MAX_PARTITIONS]
|
||||
part_start_lbas: t.CArray[t.CUInt64T, MAX_VOLUMES * MAX_PARTITIONS]
|
||||
part_totals: t.CArray[t.CUInt64T, MAX_VOLUMES * MAX_PARTITIONS]
|
||||
part_is_fat32: t.CArray[t.CInt, MAX_VOLUMES * MAX_PARTITIONS]
|
||||
|
||||
num_drives: t.CInt = 0
|
||||
|
||||
def _init():
|
||||
if num_drives > 0: return
|
||||
i: t.CInt
|
||||
for i in range(MAX_VOLUMES):
|
||||
drive_letter_map[i] = 0
|
||||
volume_mounted[i] = 0
|
||||
drive_pdrv[i] = 0
|
||||
drive_num_parts[i] = 0
|
||||
j: t.CInt
|
||||
for j in range(MAX_VOLUMES * MAX_PARTITIONS):
|
||||
part_types[j] = 0
|
||||
part_start_lbas[j] = 0
|
||||
part_totals[j] = 0
|
||||
part_is_fat32[j] = 0
|
||||
|
||||
def _part_idx(drive: t.CInt, part: t.CInt) -> t.CInt:
|
||||
return drive * MAX_PARTITIONS + part
|
||||
|
||||
def parse_mbr(pdrv: t.CUInt8T, drive_idx: t.CInt) -> types.FRESULT:
|
||||
buf: t.CArray[t.CUInt8T, 512]
|
||||
res: types.DRESULT = diskio.read(pdrv, c.Addr(buf[0]), 0, 1)
|
||||
if res != types.DRESULT.RES_OK: return types.FRESULT.FR_DISK_ERR
|
||||
if buf[0] == 0xEB or buf[0] == 0xE9:
|
||||
return types.FRESULT.FR_NO_FILESYSTEM
|
||||
sig: t.CUInt16T = t.CUInt16T(buf[510]) | (t.CUInt16T(buf[511]) << 8)
|
||||
if sig != MBR_SIGNATURE: return types.FRESULT.FR_NO_FILESYSTEM
|
||||
drive_pdrv[drive_idx] = pdrv
|
||||
drive_num_parts[drive_idx] = 0
|
||||
i: t.CInt
|
||||
for i in range(4):
|
||||
base: t.CUInt32T = 446 + t.CUInt32T(i * 16)
|
||||
ptype: t.CUInt8T = buf[base + 4]
|
||||
slba: t.CUInt32T = t.CUInt32T(buf[base + 8]) | (t.CUInt32T(buf[base + 9]) << 8) | (t.CUInt32T(buf[base + 10]) << 16) | (t.CUInt32T(buf[base + 11]) << 24)
|
||||
tsec: t.CUInt32T = t.CUInt32T(buf[base + 12]) | (t.CUInt32T(buf[base + 13]) << 8) | (t.CUInt32T(buf[base + 14]) << 16) | (t.CUInt32T(buf[base + 15]) << 24)
|
||||
if ptype != 0 and tsec > 0:
|
||||
pi: t.CInt = drive_num_parts[drive_idx]
|
||||
if pi < MAX_PARTITIONS:
|
||||
pidx: t.CInt = _part_idx(drive_idx, pi)
|
||||
part_types[pidx] = ptype
|
||||
part_start_lbas[pidx] = t.CUInt64T(slba)
|
||||
part_totals[pidx] = t.CUInt64T(tsec)
|
||||
part_is_fat32[pidx] = 1 if (ptype == PART_TYPE_FAT32 or ptype == PART_TYPE_FAT32_LBA) else 0
|
||||
drive_num_parts[drive_idx] = pi + 1
|
||||
return types.FRESULT.FR_OK
|
||||
|
||||
def scan_drives() -> types.FRESULT:
|
||||
_init()
|
||||
global num_drives
|
||||
num_drives = 0
|
||||
pdrv: t.CUInt8T
|
||||
for pdrv in range(MAX_VOLUMES):
|
||||
res: types.DRESULT = diskio.init(pdrv)
|
||||
if res != types.DRESULT.RES_OK: continue
|
||||
res2: types.FRESULT = parse_mbr(pdrv, num_drives)
|
||||
if res2 == types.FRESULT.FR_OK and drive_num_parts[num_drives] > 0:
|
||||
drive_letter_map[num_drives] = t.CChar(ord('C') + num_drives)
|
||||
else:
|
||||
drive_pdrv[num_drives] = pdrv
|
||||
drive_num_parts[num_drives] = 1
|
||||
pidx: t.CInt = _part_idx(num_drives, 0)
|
||||
part_types[pidx] = PART_TYPE_FAT32_LBA
|
||||
part_start_lbas[pidx] = 0
|
||||
part_totals[pidx] = 0
|
||||
part_is_fat32[pidx] = 1
|
||||
drive_letter_map[num_drives] = t.CChar(ord('C') + num_drives)
|
||||
num_drives = num_drives + 1
|
||||
if num_drives >= MAX_VOLUMES: break
|
||||
return types.FRESULT.FR_OK
|
||||
|
||||
def get_drive(letter: t.CChar) -> t.CInt:
|
||||
_init()
|
||||
i: t.CInt
|
||||
for i in range(num_drives):
|
||||
if drive_letter_map[i] == letter or drive_letter_map[i] == (letter - 32) or drive_letter_map[i] == (letter + 32):
|
||||
return i
|
||||
return -1
|
||||
|
||||
def get_pdrv(letter: t.CChar) -> t.CUInt8T:
|
||||
idx: t.CInt = get_drive(letter)
|
||||
if idx < 0: return 0
|
||||
return drive_pdrv[idx]
|
||||
|
||||
def get_partition_start(letter: t.CChar, part_idx: t.CInt) -> t.CUInt64T:
|
||||
idx: t.CInt = get_drive(letter)
|
||||
if idx < 0: return 0
|
||||
if part_idx >= drive_num_parts[idx]: return 0
|
||||
pidx: t.CInt = _part_idx(idx, part_idx)
|
||||
return part_start_lbas[pidx]
|
||||
|
||||
def get_partition_count(letter: t.CChar) -> t.CInt:
|
||||
idx: t.CInt = get_drive(letter)
|
||||
if idx < 0: return 0
|
||||
return drive_num_parts[idx]
|
||||
|
||||
def is_partition_fat32(letter: t.CChar, part_idx: t.CInt) -> t.CInt:
|
||||
idx: t.CInt = get_drive(letter)
|
||||
if idx < 0: return 0
|
||||
if part_idx >= drive_num_parts[idx]: return 0
|
||||
pidx: t.CInt = _part_idx(idx, part_idx)
|
||||
return part_is_fat32[pidx]
|
||||
|
||||
def get_drive_count() -> t.CInt:
|
||||
return num_drives
|
||||
|
||||
def get_drive_letter(idx: t.CInt) -> t.CChar:
|
||||
if idx < 0 or idx >= num_drives: return 0
|
||||
return drive_letter_map[idx]
|
||||
|
||||
def set_drive_letter(idx: t.CInt, letter: t.CChar) -> types.FRESULT:
|
||||
if idx < 0 or idx >= num_drives: return types.FRESULT.FR_INVALID_PARAMETER
|
||||
drive_letter_map[idx] = letter
|
||||
return types.FRESULT.FR_OK
|
||||
64
VKernel/Kernel/drivers/fs/fat32/fat32_time.py
Normal file
64
VKernel/Kernel/drivers/fs/fat32/fat32_time.py
Normal file
@@ -0,0 +1,64 @@
|
||||
from stdint import *
|
||||
import t, c
|
||||
import asm
|
||||
|
||||
|
||||
rtc_cmos_addr: t.CUInt16T = 0x70
|
||||
rtc_cmos_data: t.CUInt16T = 0x71
|
||||
|
||||
def cmos_read(reg: t.CUInt8T) -> t.CUInt8T:
|
||||
asm.outb(rtc_cmos_addr, reg)
|
||||
return asm.inb(rtc_cmos_data)
|
||||
|
||||
def bcd_to_bin(bcd: t.CUInt8T) -> t.CUInt8T:
|
||||
return (bcd >> 4) * 10 + (bcd & 0x0F)
|
||||
|
||||
def get_rtc_time() -> t.CUInt32T:
|
||||
while cmos_read(0x0A) & 0x80: pass
|
||||
sec: t.CUInt8T = cmos_read(0x00)
|
||||
min_: t.CUInt8T = cmos_read(0x02)
|
||||
hour: t.CUInt8T = cmos_read(0x04)
|
||||
day: t.CUInt8T = cmos_read(0x07)
|
||||
mon: t.CUInt8T = cmos_read(0x08)
|
||||
year: t.CUInt8T = cmos_read(0x09)
|
||||
reg_b: t.CUInt8T = cmos_read(0x0B)
|
||||
if not (reg_b & 0x04):
|
||||
sec = bcd_to_bin(sec)
|
||||
min_ = bcd_to_bin(min_)
|
||||
hour = bcd_to_bin(hour)
|
||||
day = bcd_to_bin(day)
|
||||
mon = bcd_to_bin(mon)
|
||||
year = bcd_to_bin(year)
|
||||
fat_year: t.CUInt16T = t.CUInt16T(year) + 2000 - 1980
|
||||
if fat_year > 127: fat_year = 127
|
||||
fat_date: t.CUInt16T = (fat_year << 9) | (t.CUInt16T(mon) << 5) | t.CUInt16T(day)
|
||||
fat_time: t.CUInt16T = (t.CUInt16T(hour) << 11) | (t.CUInt16T(min_) << 5) | (t.CUInt16T(sec) / 2)
|
||||
return (t.CUInt32T(fat_date) << 16) | t.CUInt32T(fat_time)
|
||||
|
||||
def get_fattime() -> t.CUInt32T:
|
||||
return get_rtc_time()
|
||||
|
||||
def to_year(ft: t.CUInt32T) -> t.CUInt16T:
|
||||
return t.CUInt16T((ft >> 25) & 0x7F) + 1980
|
||||
|
||||
def to_month(ft: t.CUInt32T) -> t.CUInt8T:
|
||||
return t.CUInt8T((ft >> 21) & 0x0F)
|
||||
|
||||
def to_day(ft: t.CUInt32T) -> t.CUInt8T:
|
||||
return t.CUInt8T((ft >> 16) & 0x1F)
|
||||
|
||||
def to_hour(ft: t.CUInt32T) -> t.CUInt8T:
|
||||
return t.CUInt8T((ft >> 11) & 0x1F)
|
||||
|
||||
def to_minute(ft: t.CUInt32T) -> t.CUInt8T:
|
||||
return t.CUInt8T((ft >> 5) & 0x3F)
|
||||
|
||||
def to_second(ft: t.CUInt32T) -> t.CUInt8T:
|
||||
return t.CUInt8T((ft & 0x1F) * 2)
|
||||
|
||||
def make(year: t.CUInt16T, month: t.CUInt8T, day: t.CUInt8T, hour: t.CUInt8T, minute: t.CUInt8T, second: t.CUInt8T) -> t.CUInt32T:
|
||||
fat_year: t.CUInt16T = year - 1980
|
||||
if fat_year > 127: fat_year = 127
|
||||
fat_date: t.CUInt16T = (fat_year << 9) | (t.CUInt16T(month) << 5) | t.CUInt16T(day)
|
||||
fat_time: t.CUInt16T = (t.CUInt16T(hour) << 11) | (t.CUInt16T(minute) << 5) | (t.CUInt16T(second) / 2)
|
||||
return (t.CUInt32T(fat_date) << 16) | t.CUInt32T(fat_time)
|
||||
1698
VKernel/Kernel/drivers/fs/fat32/fat32_types.py
Normal file
1698
VKernel/Kernel/drivers/fs/fat32/fat32_types.py
Normal file
File diff suppressed because it is too large
Load Diff
3
VKernel/Kernel/drivers/fs/fat32/fileio.py
Normal file
3
VKernel/Kernel/drivers/fs/fat32/fileio.py
Normal file
@@ -0,0 +1,3 @@
|
||||
import fat32
|
||||
|
||||
|
||||
Reference in New Issue
Block a user