summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-01-02 00:47:16 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-01-02 00:58:45 +0800
commitd8eaa13f2efc1eeca4e5f230d5a2d535aaf27338 (patch)
tree6ca02e2a2d1b1121620431059e322724a3c94a33 /include
parent2dde56422dcfb94affee2baffc8d240ad16ad4b2 (diff)
downloadlume-d8eaa13f2efc1eeca4e5f230d5a2d535aaf27338.tar.gz
lume-d8eaa13f2efc1eeca4e5f230d5a2d535aaf27338.tar.xz
dev(file-system): establish VFS and Read-only FAT32 File System
Diffstat (limited to 'include')
-rw-r--r--include/common/fcntl.h9
-rw-r--r--include/drivers/virtio.h1
-rw-r--r--include/fs/fat32.h111
-rw-r--r--include/fs/file.h35
-rw-r--r--include/fs/fs.h92
-rw-r--r--include/fs/stat.h22
-rw-r--r--include/kernel/buf.h30
-rw-r--r--include/kernel/elf.h46
-rw-r--r--include/kernel/exec.h6
-rw-r--r--include/kernel/mm.h1
-rw-r--r--include/kernel/proc_def.h6
-rw-r--r--include/lib/string.h3
12 files changed, 361 insertions, 1 deletions
diff --git a/include/common/fcntl.h b/include/common/fcntl.h
new file mode 100644
index 0000000..24d40fa
--- /dev/null
+++ b/include/common/fcntl.h
@@ -0,0 +1,9 @@
+#pragma once
+
+#define O_RDONLY 0x000
+#define O_WRONLY 0x001
+#define O_RDWR 0x002
+#define O_CREATE 0x200
+#define O_TRUNC 0x400
+
+#define NOFILE 16 \ No newline at end of file
diff --git a/include/drivers/virtio.h b/include/drivers/virtio.h
index 308dae0..ea2c9a6 100644
--- a/include/drivers/virtio.h
+++ b/include/drivers/virtio.h
@@ -99,4 +99,5 @@ namespace VirtIO
void intr();
void rw(int write, uint64 blockno, char *buf);
void test_rw();
+ void test_bio();
} \ No newline at end of file
diff --git a/include/fs/fat32.h b/include/fs/fat32.h
new file mode 100644
index 0000000..c794bd7
--- /dev/null
+++ b/include/fs/fat32.h
@@ -0,0 +1,111 @@
+#pragma once
+#include "fs/fs.h"
+#include "kernel/buf.h"
+
+// Disk Layout Structures (On-Disk)
+
+// FAT32 Boot Sector (BPB)
+struct FAT32_BPB
+{
+ uint8 jmpBoot[3];
+ char oemName[8];
+ uint16 bytesPerSector;
+ uint8 secPerClus;
+ uint16 reservedSecCnt;
+ uint8 numFATs;
+ uint16 rootEntCnt;
+ uint16 totSec16;
+ uint8 media;
+ uint16 FATSz16;
+ uint16 secPerTrk;
+ uint16 numHeads;
+ uint32 hiddSec;
+ uint32 totSec32;
+ uint32 FATSz32;
+ uint16 extFlags;
+ uint16 FSVer;
+ uint32 rootClus;
+ uint16 FSInfo;
+ uint16 bkBootSec;
+ uint8 reserved[12];
+ uint8 drvNum;
+ uint8 reserved1;
+ uint8 bootSig;
+ uint32 volID;
+ char volLab[11];
+ char filSysType[8];
+} __attribute__((packed));
+
+// FAT32 Directory Entry (32 bytes)
+struct FAT32_DirEnt
+{
+ char name[11]; // 8.3 filename
+ uint8 attr; // File attributes
+ uint8 ntRes;
+ uint8 crtTimeTenth;
+ uint16 crtTime;
+ uint16 crtDate;
+ uint16 lstAccDate;
+ uint16 fstClusHI; // High 16 bits of first cluster
+ uint16 wrtTime;
+ uint16 wrtDate;
+ uint16 fstClusLO; // Low 16 bits of first cluster
+ uint32 fileSize;
+} __attribute__((packed));
+
+#define ATTR_READ_ONLY 0x01
+#define ATTR_HIDDEN 0x02
+#define ATTR_SYSTEM 0x04
+#define ATTR_VOLUME_ID 0x08
+#define ATTR_DIRECTORY 0x10
+#define ATTR_ARCHIVE 0x20
+#define ATTR_LONG_NAME 0x0F
+
+// In-Memory Classes
+
+class FAT32FileSystem;
+
+class FAT32Inode : public Inode
+{
+public:
+ FAT32FileSystem *fs;
+
+ // FAT32 Private Data
+ uint32 first_clus; // The starting cluster number of the file
+ uint32 parent_clus; // Starting cluster number of the parent directory
+ uint32 dir_offset; // The byte offset of this directory entry in the parent directory
+
+ FAT32Inode() : fs(nullptr), first_clus(0) {}
+ // Implement VFS Interface
+ void update() override;
+ int read(char *dst, uint32 off, uint32 n, int isUser) override;
+ int write(const char *src, uint32 off, uint32 n, int isUser) override;
+ Inode *lookup(const char *name) override;
+ Inode *create(const char *name, short type, short major, short minor) override;
+ void truncate() override;
+};
+
+class FAT32FileSystem : public FileSystem
+{
+public:
+ uint32 fat_start_sector;
+ uint32 data_start_sector;
+ uint32 root_cluster;
+ uint32 sectors_per_cluster;
+ uint32 bytes_per_cluster;
+
+ void init() override;
+ Inode* root() override;
+
+ // Helper functions
+ uint32 next_cluster(uint32 cluster); // Check the FAT table for the next cluster
+ uint32 alloc_cluster(); // Assign a new cluster
+ uint32 cluster_to_sector(uint32 cluster);
+
+ // directory entry parsing
+ void read_dir_ent(struct FAT32_DirEnt *de, char *filename);
+};
+
+extern FAT32FileSystem fat32_fs;
+
+void fat32_test(); \ No newline at end of file
diff --git a/include/fs/file.h b/include/fs/file.h
new file mode 100644
index 0000000..fc0c5d9
--- /dev/null
+++ b/include/fs/file.h
@@ -0,0 +1,35 @@
+#pragma once
+#include "common/types.h"
+#include "fs/fs.h"
+
+enum FileType
+{
+ FD_NONE,
+ FD_INODE,
+ FD_DEVICE,
+ FD_PIPE
+};
+
+struct file
+{
+ enum FileType type;
+ int ref;
+ char readable;
+ char writable;
+
+ struct pipe *pipe; // pipeline pointer
+ Inode *ip; // VFS Inode
+ uint32 off; // Current Offset
+};
+
+namespace FileTable
+{
+ void init();
+ struct file *alloc(); // Allocate a free file handle
+ struct file *dup(struct file *f); // Duplicate handle (sys_dup)
+ void close(struct file *f); // Close handle
+
+ int stat(struct file *f, uint64 addr);
+ int read(struct file *f, uint64 addr, int n);
+ int write(struct file *f, uint64 addr, int n);
+} // namespace FileTable
diff --git a/include/fs/fs.h b/include/fs/fs.h
new file mode 100644
index 0000000..6e4ec4b
--- /dev/null
+++ b/include/fs/fs.h
@@ -0,0 +1,92 @@
+#pragma once
+#include "common/types.h"
+#include "kernel/spinlock.h"
+#include "fs/stat.h"
+
+class FileSystem;
+
+// VFS Inode (Abstract Base Class)
+
+class Inode
+{
+private:
+ ;
+public:
+ // VFS Common Fields
+ uint32 dev; // Device number (VirtIO Block ID)
+ uint32 inum; // Inode number
+ int ref_cnt; // Memory reference count (number of struct file or processes referencing it)
+ int valid; // Whether the data is valid (whether metadata has been read from disk)
+
+ Mutex lock; // Sleep lock: protects internal Inode data and atomicity of read/write operations
+
+ // Metadata Cache (for speeding up getattr)
+ short type; // T_DIR, T_FILE, T_DEVICE
+ short major; // Major device number (only for T_DEVICE)
+ short minor; // Minor device number (only for T_DEVICE)
+ short nlink; // Number of hard links
+ uint32 size; // File size
+
+ Inode() : ref_cnt(0), valid(0)
+ {
+ lock.init("inode");
+ }
+ virtual ~Inode() {}
+
+ /* Core Operation Interface (Subclass Must Implement) */
+ // Update metadata
+ // Sync size, type, links, etc. from memory back to disk
+ virtual void update() = 0;
+ // Read content
+ // Read n bytes from the file at offset into dst
+ // Returns the actual number of bytes read, returns -1 on error
+ virtual int read(char *dst, uint32 off, uint32 n, int isUser) = 0;
+ // 3. Write content
+ // Write n bytes from src to the file at the given offset
+ // Need to handle file growth
+ virtual int write(const char *src, uint32 off, uint32 n, int isUser) = 0;
+ // Directory Lookup (only valid when type == T_DIR)
+ // Search for a file named 'name' in the current directory and return its Inode pointer (locked)
+ // Return nullptr if not found
+ virtual Inode *lookup(const char *name) = 0;
+ // Create file/directory (only effective when type == T_DIR)
+ // Create a new entry in the current directory
+ virtual Inode *create(const char *name, short type, short major, short minor) = 0;
+ // Get file status (populate the stat structure)
+ // Default implementation, subclasses can override to provide more detailed information
+ virtual void getattr(struct kstat *st);
+ // Truncate file (set size to 0, release all data blocks)
+ virtual void truncate() = 0;
+};
+
+// File System Abstraction (SuperBlock)
+class FileSystem
+{
+private:
+ ;
+public:
+ virtual void init() = 0;
+ virtual Inode* root() = 0;
+ virtual ~FileSystem() {};
+};
+
+// Inode Cache Interface (Global Function)
+namespace VFS
+{
+ void init();
+
+ // Decrease the reference count, and if it reaches 0, free the memory
+ void iput(Inode *ip);
+ // Increase reference count
+ Inode *idup(Inode *ip);
+ // lock and load data
+ void ilock(Inode *ip);
+ // unlock
+ void iunlock(Inode *ip);
+ // Mount the root filesystem
+ void mount_root(Inode *root);
+ // Get system root node
+ Inode *get_root();
+ // Path Analysis
+ Inode *namei(const char *path);
+} // namespace VFS
diff --git a/include/fs/stat.h b/include/fs/stat.h
new file mode 100644
index 0000000..cdce05a
--- /dev/null
+++ b/include/fs/stat.h
@@ -0,0 +1,22 @@
+#pragma once
+#include "common/types.h"
+
+#define T_DIR 1 // Directory
+#define T_FILE 2 // File
+#define T_DEVICE 3 // Device
+
+struct kstat
+{
+ int dev; // File System's disk device
+ uint32 ino; // Inode number
+ short type; //Type of file
+ short nlink; // Number of links to file
+ uint64 size; // Size of file in bytes
+
+ uint32 mode; // Protection: rwx
+ uint32 uid; // User ID
+ uint32 gid; // Group ID
+ uint32 atime; // Access time
+ uint32 mtime; // Modified time
+ uint32 ctime; // Change time
+};
diff --git a/include/kernel/buf.h b/include/kernel/buf.h
new file mode 100644
index 0000000..099523d
--- /dev/null
+++ b/include/kernel/buf.h
@@ -0,0 +1,30 @@
+#pragma once
+#include "common/types.h"
+#include "kernel/spinlock.h"
+
+#define BSIZE 1024
+#define NBUF 30
+
+struct Buf
+{
+ int valid; // Whether the data has been read from the disk (1=valid, 0=invalid)
+ int disk; // Whether it has been held by the driver (dirty bit/write-back flag is usually extended here)
+ uint32 dev; // Device Number
+ uint32 blockno; // Block number
+ uint32 refcnt; // Reference Counting
+ struct Buf *prev; // LRU linked list
+ struct Buf *next;
+ uchar data[BSIZE];
+
+ Mutex lock; // Sleep Lock
+};
+
+namespace BufferCache
+{
+ void init();
+ struct Buf *bread(uint32 dev, uint32 blockno);
+ void bwrite(struct Buf *b);
+ void brelse(struct Buf *b);
+ void bpin(struct Buf *b);
+ void bunpin(struct Buf *b);
+} // namespace BufferCache
diff --git a/include/kernel/elf.h b/include/kernel/elf.h
new file mode 100644
index 0000000..c216f1c
--- /dev/null
+++ b/include/kernel/elf.h
@@ -0,0 +1,46 @@
+#pragma once
+#include "common/types.h"
+
+#define ELF_MAGIC 0x464C457F // "\x7FELF" in little endian
+
+// ELF File Header
+struct elfhdr
+{
+ uint32 magic; // Must equal ELF_MAGIC
+ uint8 elf[12];
+ uint16 type;
+ uint16 machine;
+ uint32 version;
+ uint64 entry; // Program Entry Point (Virtual Address)
+ uint64 phoff; // File offset of the Program Header Table
+ uint64 shoff;
+ uint32 flags;
+ uint16 ehsize;
+ uint16 phentsize;
+ uint16 phnum; // Number of Program Headers
+ uint16 shentsize;
+ uint16 shnum;
+ uint16 shstrndx;
+};
+
+// Program Header
+// Describes how to load segments from a file into memory
+struct proghdr
+{
+ uint32 type;
+ uint32 flags;
+ uint64 off; // Offset of the section in the file
+ uint64 vaddr; // Virtual address of the segment in memory
+ uint64 paddr;
+ uint64 filesz; // Size of the section in the file
+ uint64 memsz; // The size of the segment in memory (memsz >= filesz)
+ uint64 align;
+};
+
+// Values for Proghdr type
+#define ELF_PROG_LOAD 1
+
+// Flag bits for Proghdr flags
+#define ELF_PROG_FLAG_EXEC 1
+#define ELF_PROG_FLAG_WRITE 2
+#define ELF_PROG_FLAG_READ 4 \ No newline at end of file
diff --git a/include/kernel/exec.h b/include/kernel/exec.h
new file mode 100644
index 0000000..964e3bb
--- /dev/null
+++ b/include/kernel/exec.h
@@ -0,0 +1,6 @@
+#pragma once
+
+namespace Exec
+{
+ int exec(char *path, char **argv);
+} \ No newline at end of file
diff --git a/include/kernel/mm.h b/include/kernel/mm.h
index 363ce74..1850574 100644
--- a/include/kernel/mm.h
+++ b/include/kernel/mm.h
@@ -18,6 +18,7 @@ namespace VM
int copyout(uint64 *pagetable, uint64 dstva, char *src, uint64 len);
int copyin(uint64 *pagetable, char *dst, uint64 srcva, uint64 len);
+ int copyinstr(uint64 *pagetable, char *dst, uint64 srcva, uint64 max);
int handle_cow_fault(uint64 *pagetable, uint64 va);
int mappages(uint64 *pagetable, uint64 va, uint64 size, uint64 pa, int perm);
diff --git a/include/kernel/proc_def.h b/include/kernel/proc_def.h
index e5a2cbc..06c80aa 100644
--- a/include/kernel/proc_def.h
+++ b/include/kernel/proc_def.h
@@ -1,8 +1,11 @@
#pragma once
#include "common/types.h"
+#include "common/fcntl.h"
struct cpu;
struct Trapframe;
+class Inode;
+struct file;
enum ProcState
{
@@ -51,6 +54,9 @@ struct Proc
void *chan;
int xstate;
+ Inode *cwd;
+ struct file *ofile[NOFILE];
+
struct Proc *next;
struct Proc *prev;
int priority;
diff --git a/include/lib/string.h b/include/lib/string.h
index aa87489..309bf02 100644
--- a/include/lib/string.h
+++ b/include/lib/string.h
@@ -10,4 +10,5 @@ void *memcpy(void *dst, const void *src, uint n);
void strcpy(char *dst, const char *src);
int strlen(const char *s);
-int strcmp(const char *s1, const char *s2); \ No newline at end of file
+int strcmp(const char *s1, const char *s2);
+int strcasecmp(const char *s1, const char *s2); \ No newline at end of file