189 lines
5.8 KiB
Nim
189 lines
5.8 KiB
Nim
# Markus Maiwald (Architect) | Voxis Forge (AI)
|
|
# Rumpk Phase 11: The Sovereign Filesystem (SFS)
|
|
# Simple Flat System (Contiguous, Directory-based, No Inodes)
|
|
|
|
# import ../ion # Removing to avoid cycle and ambiguity
|
|
# import ../kernel # Removing to avoid cycle
|
|
|
|
proc kprintln(s: cstring) {.importc, cdecl.}
|
|
proc kprint(s: cstring) {.importc, cdecl.}
|
|
proc kprint_hex(n: uint64) {.importc, cdecl.}
|
|
|
|
# =========================================================
|
|
# SFS Definitions
|
|
# =========================================================
|
|
|
|
const SFS_MAGIC = 0x31534653'u32 # "SFS1" in Little Endian (S=53, F=46, S=53, 1=31 -> 31 53 46 53? No, S is lowest addr)
|
|
# "SFS1" as string: bufs[0]=S, buf[1]=F...
|
|
# u32 representation depends on Endianness.
|
|
# On Little Endian (RISC-V):
|
|
# 0x31534653 -> LSB is 0x53 (S). MSB is 0x31 (1).
|
|
# So "SFS1" in memory.
|
|
|
|
type
|
|
Superblock* = object
|
|
magic*: uint32
|
|
disk_size*: uint32 # in sectors? or bytes? Nipbox wrote u64 bytes. Let's use sectors for kernel simplicity?
|
|
# Stack layout alignment might be issue. Let's read raw bytes.
|
|
|
|
DirEntry* = object
|
|
filename*: array[32, char]
|
|
start_sector*: uint32
|
|
size_bytes*: uint32
|
|
reserved*: array[24, byte] # Pad to 64 bytes? 32+4+4 = 40. 64-40=24.
|
|
# 512 / 64 = 8 entries per sector.
|
|
|
|
# =========================================================
|
|
# SFS State
|
|
# =========================================================
|
|
|
|
var sfs_mounted: bool = false
|
|
var io_buffer: array[512, byte] # Kernel IO Buffer for FS ops
|
|
|
|
# =========================================================
|
|
# SFS Driver
|
|
# =========================================================
|
|
|
|
# Import HAL block ops
|
|
proc virtio_blk_read(sector: uint64, buf: pointer) {.importc, cdecl.}
|
|
proc virtio_blk_write(sector: uint64, buf: pointer) {.importc, cdecl.}
|
|
|
|
proc sfs_mount*() =
|
|
kprintln("[SFS] Mounting System...")
|
|
|
|
# 1. Read Sector 0 (Superblock)
|
|
virtio_blk_read(0, addr io_buffer[0])
|
|
|
|
# 2. Check Magic
|
|
# "SFS1" -> 0x53, 0x46, 0x53, 0x31
|
|
if io_buffer[0] == 0x53 and io_buffer[1] == 0x46 and
|
|
io_buffer[2] == 0x53 and io_buffer[3] == 0x31:
|
|
kprintln("[SFS] Mount SUCCESS. Magic: SFS1")
|
|
sfs_mounted = true
|
|
else:
|
|
kprint("[SFS] Mount FAILED. Invalid Magic. Found: ")
|
|
kprint_hex(cast[uint64](io_buffer[0]))
|
|
kprint(" ")
|
|
kprint_hex(cast[uint64](io_buffer[1]))
|
|
kprint(" ")
|
|
kprint_hex(cast[uint64](io_buffer[2]))
|
|
kprintln("")
|
|
|
|
proc sfs_list*() =
|
|
if not sfs_mounted:
|
|
kprintln("[SFS] Error: Not mounted.")
|
|
return
|
|
|
|
# Read Sector 1 (Directory Table)
|
|
virtio_blk_read(1, addr io_buffer[0])
|
|
|
|
kprintln("[SFS] Files:")
|
|
# Parse Entries (assuming 64 bytes stride for now if nipbox holds it)
|
|
# Actually nipbox `mkfs` just zeroed it.
|
|
|
|
var found = false
|
|
var offset = 0
|
|
while offset < 512:
|
|
if io_buffer[offset] != 0:
|
|
# Found entry
|
|
var name: string = ""
|
|
for i in 0..31:
|
|
let c = char(io_buffer[offset+i])
|
|
if c == '\0': break
|
|
name.add(c)
|
|
|
|
kprint(" - ")
|
|
kprintln(cstring(name))
|
|
found = true
|
|
|
|
offset += 64
|
|
|
|
if not found:
|
|
kprintln(" (Empty)")
|
|
|
|
proc sfs_write_file*(name: cstring, data: cstring, data_len: int) =
|
|
if not sfs_mounted:
|
|
kprintln("[SFS] Write Error: Not mounted.")
|
|
return
|
|
|
|
# 1. Read Directory Table (Sector 1)
|
|
virtio_blk_read(1, addr io_buffer[0])
|
|
|
|
var free_slot_offset = -1
|
|
var found_file_offset = -1
|
|
var max_sector: uint32 = 1
|
|
|
|
var offset = 0
|
|
while offset < 512:
|
|
if io_buffer[offset] != 0:
|
|
var entry_name: string = ""
|
|
for i in 0..31:
|
|
if io_buffer[offset+i] == 0: break
|
|
entry_name.add(char(io_buffer[offset+i]))
|
|
|
|
if entry_name == $name:
|
|
found_file_offset = offset
|
|
|
|
var s_sect: uint32 = uint32(io_buffer[offset+32]) or
|
|
(uint32(io_buffer[offset+33]) shl 8) or
|
|
(uint32(io_buffer[offset+34]) shl 16) or
|
|
(uint32(io_buffer[offset+35]) shl 24)
|
|
if s_sect > max_sector: max_sector = s_sect
|
|
elif free_slot_offset == -1:
|
|
free_slot_offset = offset
|
|
|
|
offset += 64
|
|
|
|
# 2. Determine Target Sector
|
|
var target_sector: uint32 = 0
|
|
var target_offset = 0
|
|
|
|
if found_file_offset != -1:
|
|
kprintln("[SFS] Overwriting existing file...")
|
|
target_offset = found_file_offset
|
|
target_sector = uint32(io_buffer[target_offset+32]) or
|
|
(uint32(io_buffer[target_offset+33]) shl 8) or
|
|
(uint32(io_buffer[target_offset+34]) shl 16) or
|
|
(uint32(io_buffer[target_offset+35]) shl 24)
|
|
elif free_slot_offset != -1:
|
|
kprintln("[SFS] Creating new file...")
|
|
target_offset = free_slot_offset
|
|
target_sector = max_sector + 1
|
|
else:
|
|
kprintln("[SFS] Error: Directory Full.")
|
|
return
|
|
|
|
# 3. Write Data
|
|
kprint("[SFS] Writing to Sector: ")
|
|
kprint_hex(uint64(target_sector))
|
|
kprintln("")
|
|
|
|
var data_buf: array[512, byte]
|
|
for i in 0..511: data_buf[i] = 0
|
|
for i in 0 ..< data_len:
|
|
if i < 512: data_buf[i] = byte(data[i])
|
|
|
|
virtio_blk_write(uint64(target_sector), addr data_buf[0])
|
|
|
|
# 4. Update Directory Entry
|
|
var n_str = $name
|
|
for i in 0..31:
|
|
if i < n_str.len: io_buffer[target_offset+i] = byte(n_str[i])
|
|
else: io_buffer[target_offset+i] = 0
|
|
|
|
io_buffer[target_offset+32] = byte(target_sector and 0xFF)
|
|
io_buffer[target_offset+33] = byte((target_sector shr 8) and 0xFF)
|
|
io_buffer[target_offset+34] = byte((target_sector shr 16) and 0xFF)
|
|
io_buffer[target_offset+35] = byte((target_sector shr 24) and 0xFF)
|
|
|
|
var sz = uint32(data_len)
|
|
io_buffer[target_offset+36] = byte(sz and 0xFF)
|
|
io_buffer[target_offset+37] = byte((sz shr 8) and 0xFF)
|
|
io_buffer[target_offset+38] = byte((sz shr 16) and 0xFF)
|
|
io_buffer[target_offset+39] = byte((sz shr 24) and 0xFF)
|
|
|
|
# 5. Write Directory Table Back
|
|
virtio_blk_write(1, addr io_buffer[0])
|
|
kprintln("[SFS] Write Complete.")
|
|
|