diff --git a/src/Compiler/Atomixilc/Lib/Memory.cs b/src/Compiler/Atomixilc/Lib/Memory.cs index 1ed082d..a1461df 100644 --- a/src/Compiler/Atomixilc/Lib/Memory.cs +++ b/src/Compiler/Atomixilc/Lib/Memory.cs @@ -129,7 +129,7 @@ public static void Write8(uint aAddress, byte Value) [NoException] [Assembly(false)] - public static void FastCopy(uint aDest, uint aSrc, uint aLen) + public static void FastCopy(uint aDest, uint aSrc, int aLen) { new Mov { DestinationReg = Register.EAX, SourceReg = Register.ESP, SourceDisplacement = 0x4, SourceIndirect = true }; new Mov { DestinationReg = Register.ESI, SourceReg = Register.ESP, SourceDisplacement = 0x8, SourceIndirect = true }; diff --git a/src/Compiler/Atomixilc/Lib/Plugs/String.cs b/src/Compiler/Atomixilc/Lib/Plugs/String.cs index ce9ed9a..9048315 100644 --- a/src/Compiler/Atomixilc/Lib/Plugs/String.cs +++ b/src/Compiler/Atomixilc/Lib/Plugs/String.cs @@ -132,7 +132,7 @@ internal static char[] ToCharArray(string aStr) { int len = aStr.Length; var aArray = new char[len]; - Memory.FastCopy(aArray.GetDataOffset(), aStr.GetDataOffset(), (uint)(len << 1)); + Memory.FastCopy(aArray.GetDataOffset(), aStr.GetDataOffset(), (len << 1)); return aArray; } diff --git a/src/Kernel/Atomix.Kernel_H/Arch/x86/Multiboot.cs b/src/Kernel/Atomix.Kernel_H/Arch/x86/Multiboot.cs index 3e2b7ab..09ecebf 100644 --- a/src/Kernel/Atomix.Kernel_H/Arch/x86/Multiboot.cs +++ b/src/Kernel/Atomix.Kernel_H/Arch/x86/Multiboot.cs @@ -109,7 +109,7 @@ internal static unsafe class Multiboot static Multiboot_Info* Mb_Info; static bool aIsValid; static uint Initrd; - static uint InitrdSize; + static int InitrdSize; internal static bool IsValid { get { return aIsValid; } } @@ -134,14 +134,14 @@ internal static uint RamDisk get { return Initrd; } } - internal static uint RamDiskSize + internal static int RamDiskSize { get { return InitrdSize; } } internal static uint RamDiskEnd { - get { return Initrd + InitrdSize; } + get { return Initrd + (uint)InitrdSize; } } internal static unsafe void Setup(uint xSig, uint Address) @@ -167,7 +167,7 @@ internal static unsafe void Setup(uint xSig, uint Address) if (Mb_Info->mods_count > 0) { Initrd = modules[0]; - InitrdSize = modules[1] - Initrd; + InitrdSize = (int)(modules[1] - Initrd); Initrd += 0xC0000000; Debug.Write(" RamDisk:%d\n", Initrd); Debug.Write(" RamDisk-Size:%d\n", InitrdSize); diff --git a/src/Kernel/Atomix.Kernel_H/Atomix.Kernel_H.csproj b/src/Kernel/Atomix.Kernel_H/Atomix.Kernel_H.csproj index 91c956a..c141db5 100644 --- a/src/Kernel/Atomix.Kernel_H/Atomix.Kernel_H.csproj +++ b/src/Kernel/Atomix.Kernel_H/Atomix.Kernel_H.csproj @@ -91,22 +91,30 @@ - + + + + + + + - - - - - - - - - + + + + + + - + + + + + + diff --git a/src/Kernel/Atomix.Kernel_H/Boot.cs b/src/Kernel/Atomix.Kernel_H/Boot.cs index 365634f..94a665c 100644 --- a/src/Kernel/Atomix.Kernel_H/Boot.cs +++ b/src/Kernel/Atomix.Kernel_H/Boot.cs @@ -8,12 +8,12 @@ using System; using Atomixilc.Lib; -using Atomix.Kernel_H.Lib.Cairo; using Atomix.Kernel_H.IO; using Atomix.Kernel_H.Gui; using Atomix.Kernel_H.Core; using Atomix.Kernel_H.Devices; using Atomix.Kernel_H.Arch.x86; +using Atomix.Kernel_H.Lib.Cairo; using Atomix.Kernel_H.Drivers.Video; using Atomix.Kernel_H.IO.FileSystem; @@ -35,9 +35,9 @@ internal unsafe static void Init() #region InitRamDisk if (Multiboot.RamDisk != 0) { - var xFileSystem = new RamFileSystem(Multiboot.RamDisk, Multiboot.RamDiskSize); - if (xFileSystem.IsValid) - VirtualFileSystem.MountDevice(null, xFileSystem); + var xFileSystem = new RamFileSystem("disk0", new MemoryStream(Multiboot.RamDisk, Multiboot.RamDiskSize)); + if (xFileSystem.Detect()) + VirtualFileSystem.Mount(xFileSystem, "/"); else throw new Exception("RamDisk Corrupted!"); } @@ -231,8 +231,6 @@ private static unsafe void DrawTaskbar(GuiRequest* request, byte[] xData) internal static void LoadIDE(bool IsPrimary, bool IsMaster) { var xIDE = new IDE(IsPrimary, IsMaster); - - bool Clean = true; if (xIDE.IsValid) { switch(xIDE.Device) @@ -252,12 +250,11 @@ internal static void LoadIDE(bool IsPrimary, bool IsMaster) /* * Iterate over all FileSystem Drivers and check which is valid */ - var xFileSystem = new FatFileSystem(xMBR.PartInfo[i]); + /*var xFileSystem = new FatFileSystem(xMBR.PartInfo[i]); if (xFileSystem.IsValid) { VirtualFileSystem.MountDevice(null, xFileSystem); - Clean = false; - } + }*/ } } } diff --git a/src/Kernel/Atomix.Kernel_H/Core/Syscall.cs b/src/Kernel/Atomix.Kernel_H/Core/Syscall.cs index ff7d14d..ab8fa28 100644 --- a/src/Kernel/Atomix.Kernel_H/Core/Syscall.cs +++ b/src/Kernel/Atomix.Kernel_H/Core/Syscall.cs @@ -7,9 +7,10 @@ using System; +using Atomixilc.Lib; + using Atomix.Kernel_H.IO; using Atomix.Kernel_H.Arch.x86; -using Atomix.Kernel_H.IO.FileSystem; namespace Atomix.Kernel_H.Core { @@ -99,7 +100,10 @@ private static unsafe int sys_read(int fd, byte* buffer, int count) if (fd >= files.Count) return -1; var stream = Process.Files[fd]; - return stream.Read(buffer, count); + var data = new byte[count]; + int status = stream.Read(data, count); + Memory.FastCopy((uint)buffer, data.GetDataOffset(), count); + return status; } private static int sys_seek(int fd, int offset, int origin) @@ -113,7 +117,7 @@ private static int sys_seek(int fd, int offset, int origin) if (origin > 2) return -1; var stream = Process.Files[fd]; - return stream.Seek(offset, (SEEK)origin); + return stream.Seek(offset, (FileSeek)origin); } private static int sys_close(int fd) @@ -134,15 +138,16 @@ private static int sys_close(int fd) return 0; } - private static unsafe int sys_open(sbyte* file, int flags, int mode) + private static unsafe int sys_open(sbyte* name, int flags, int mode) { - var filename = new string(file); - var stream = VirtualFileSystem.GetFile(filename); + var filename = new string(name); + var file = VirtualFileSystem.Open(filename); Debug.Write("fopen: %s\n", filename); - if (stream == null) + if (file == null || !(file is File)) return -1; + var stream = ((File)file).Open(FileMode.Read); var Process = Scheduler.RunningProcess; var files = Process.Files; int count = files.Count; diff --git a/src/Kernel/Atomix.Kernel_H/Exec/ELF.cs b/src/Kernel/Atomix.Kernel_H/Exec/ELF.cs index 250ed73..9a06974 100644 --- a/src/Kernel/Atomix.Kernel_H/Exec/ELF.cs +++ b/src/Kernel/Atomix.Kernel_H/Exec/ELF.cs @@ -18,381 +18,6 @@ namespace Atomix.Kernel_H.Exec { internal unsafe static class ELF { - [StructLayout(LayoutKind.Explicit, Size = 52)] - struct Elf_Header - { - [FieldOffset(0)] - public fixed byte e_ident[16]; - [FieldOffset(16)] - public ushort e_type; - [FieldOffset(18)] - public ushort e_machine; - [FieldOffset(20)] - public uint e_version; - [FieldOffset(24)] - public uint e_entry; - [FieldOffset(28)] - public uint e_phoff; - [FieldOffset(32)] - public uint e_shoff; - [FieldOffset(36)] - public uint e_flags; - [FieldOffset(40)] - public ushort e_ehsize; - [FieldOffset(42)] - public ushort e_phentsize; - [FieldOffset(44)] - public ushort e_phnum; - [FieldOffset(46)] - public ushort e_shentsize; - [FieldOffset(48)] - public ushort e_shnum; - [FieldOffset(50)] - public ushort e_shstrndx; - }; - [StructLayout(LayoutKind.Explicit, Size = 40)] - struct Elf_Shdr - { - [FieldOffset(0)] - public uint sh_name; - [FieldOffset(4)] - public uint sh_type; - [FieldOffset(8)] - public uint sh_flags; - [FieldOffset(12)] - public uint sh_addr; - [FieldOffset(16)] - public uint sh_offset; - [FieldOffset(20)] - public uint sh_size; - [FieldOffset(24)] - public int sh_link; - [FieldOffset(28)] - public int sh_info; - [FieldOffset(32)] - public uint sh_addralign; - [FieldOffset(36)] - public uint sh_entsize; - }; - - [StructLayout(LayoutKind.Explicit, Size = 8)] - struct Elf32_Rel - { - [FieldOffset(0)] - public uint r_offset; - [FieldOffset(4)] - public uint r_info; - }; - - [StructLayout(LayoutKind.Explicit, Size = 16)] - struct Elf32_Sym - { - [FieldOffset(0)] - public uint st_name; - [FieldOffset(4)] - public uint st_value; - [FieldOffset(8)] - public uint st_size; - [FieldOffset(12)] - public byte st_info; - [FieldOffset(13)] - public byte st_other; - [FieldOffset(14)] - public ushort st_shndx; - }; - - /* Identification indexes for e_ident field in ELF header */ - const int EI_MAG0 = 0; /* file ID byte 0 */ - const int EI_MAG1 = 1; /* file ID byte 1 */ - const int EI_MAG2 = 2; /* file ID byte 2 */ - const int EI_MAG3 = 3; /* file ID byte 3 */ - const int EI_CLASS = 4; /* file class (capacity) */ - const int EI_DATA = 5; /* data encoding */ - const int EI_VERSION = 6; /* file version */ - const int EI_PAD = 7; /* start of padding bytes */ - const int EI_NIDENT = 16; /* size of e_ident[] */ - - /* "Magic number" in e_ident field of ELF header */ - const byte ELFMAG0 = 0x7F; - const byte ELFMAG1 = (byte)'E'; - const byte ELFMAG2 = (byte)'L'; - const byte ELFMAG3 = (byte)'F'; - - /* Relocation Type for i386 machine */ - const byte R_386_NONE = 0; - const byte R_386_32 = 1; /* S + A */ - const byte R_386_PC32 = 2; /* S + A - P */ - const byte R_386_GOT32 = 3; /* G + A */ - const byte R_386_PLT32 = 4; /* L + A - P */ - const byte R_386_COPY = 5; - const byte R_386_GLOB_DAT = 6; /* S */ - const byte R_386_JMP_SLOT = 7; /* S */ - const byte R_386_RELATIVE = 8; /* B + A */ - const byte R_386_GOTOFF = 9; /* S + A - GOT */ - const byte R_386_GOTPC = 10; /* GOT + A - P */ - const byte R_386_32PLT = 11; /* L + A */ - - /* File class (or capacity) in e_ident[4] of ELF header */ - const byte ELFCLASSNONE = 0; /* invalid class */ - const byte ELFCLASS32 = 1; /* 32-bit processor */ - const byte ELFCLASS64 = 2; /* 64-bit processor */ - - /* Data encoding in e_ident[5] of ELF header */ - const byte ELFDATANONE = 0; /* invalid data encoding */ - const byte ELFDATA2LSB = 1; /* little-endian format */ - const byte ELFDATA2MSB = 2; /* big-endian format */ - - /* Object file type in e_type field of ELF header */ - const ushort ET_NONE = 0; /* no file type */ - const ushort ET_REL = 1; /* relocatble file */ - const ushort ET_EXEC = 2; /* executable file */ - const ushort ET_DYN = 3; /* shared object file */ - const ushort ET_CORE = 4; /* core file */ - const ushort ET_LOPROC = 0xff00; /* processor-specific */ - const ushort ET_HIPROC = 0xffff; /* processor-specific */ - - /* Required architecture in e_machine field of ELF header */ - const ushort EM_NONE = 0; /* no machine */ - const ushort EM_M32 = 1; /* AT&T WE 32100 */ - const ushort EM_SPARC = 2; /* SPARC */ - const ushort EM_386 = 3; /* Intel 80386 */ - const ushort EM_68K = 4; /* Motorola 68000 */ - const ushort EM_88K = 5; /* Motorola 88000 */ - const ushort EM_860 = 7; /* Intel 80860 */ - const ushort EM_MIPS = 8; /* MIPS RS3000 */ - const ushort EM_ARM = 40; /* Advanced RISC Machines ARM */ - - /* Object file version in e_version field of ELF header */ - const uint EV_NONE = 0; /* invalid version */ - const uint EV_CURRENT = 1; /* current version */ - - /* Section's semantics in sh_type field of ELF section header */ - const uint SHT_NULL = 0; /* no section associated with header */ - const uint SHT_PROGBITS = 1; /* program-defined data */ - const uint SHT_SYMTAB = 2; /* link editing & dynamic linking symbols */ - const uint SHT_STRTAB = 3; /* string table */ - const uint SHT_RELA = 4; /* minimal set of dynamic linking symbols */ - const uint SHT_HASH = 5; /* relocation entries with explicit addends */ - const uint SHT_DYNAMIC = 6; /* symbol hash table (dynamic linking) */ - const uint SHT_NOTE = 7; /* dynamic linking info */ - const uint SHT_NOBITS = 8; /* file-marking information */ - const uint SHT_REL = 9; /* relocation entries without explicit addends */ - const uint SHT_SHLIB = 10; /* reserved */ - const uint SHT_DYNSYM = 11; /* dynamic linking symbol table */ - const uint SHT_LOPROC = 0x70000000; /* LB for processor-specific dynamics */ - const uint SHT_HIPROC = 0x7fffffff; /* UB for processor-specific dynamics */ - const uint SHT_LOUSER = 0x80000000; /* LB for application-specific dynamics */ - const uint SHT_HIUSER = 0x8fffffff; /* UB for application-specific dynamics */ - - /* Section's attribute flags in sh_flags field of ELF section header */ - const uint SHF_WRITE = 0x1; /* data writable during execution */ - const uint SHF_ALLOC = 0x2; /* occupies memory during execution */ - const uint SHF_EXECINSTR = 0x4; /* executable machine instructions */ - const uint SHF_MASKPROC = 0xf0000000; /* mask for processor-specific semantics */ - - /* Special section indexes (reserved values) */ - const ushort SHN_UNDEF = 0; /* undefined section index */ - const ushort SHN_LORESERVE = 0xff00; /* LB (lower bound) of ELF reserved indexes */ - const ushort SHN_LOPROC = 0xff00; /* LB of processor-specific semantics */ - const ushort SHN_HIPROC = 0xff1f; /* UB of processor-specific semantics */ - const ushort SHN_ABS = 0xfff1; /* absolute (not relocatable) section */ - const ushort SHN_COMMON = 0xfff2; /* C external variables section */ - const ushort SHN_HIRESERVE = 0xffff; /* UB (upper bound) of ELF reserved indexes */ - - /* Symbol binding */ - const uint STB_LOCAL = 0; /* Local scope */ - const uint STB_GLOBAL = 1; /* Global scope */ - const uint STB_WEAK = 2; /* Weak, (ie. __attribute__((weak))) */ - - internal static uint Load(string aPath) - { - Stream xStream = VirtualFileSystem.GetFile(aPath); - - if (xStream == null) - throw new Exception("[ELF]: File not found!"); - - var xData = new byte[xStream.FileSize]; - xStream.Read(xData, xData.Length); - - uint BaseAddress = xData.GetDataOffset(); - Elf_Header* Header = (Elf_Header*)BaseAddress; - - /* verify ELF header and if this code support this type of elf */ - CheckHeader(Header); - - /* prepare sections and allocate memory (if required) */ - Elf_Shdr* Shdr = (Elf_Shdr*)(BaseAddress + Header->e_shoff); - for (int i = 0; i < Header->e_shnum; i++, Shdr++) - { - Shdr->sh_addr = BaseAddress + Shdr->sh_offset; - if ((Shdr->sh_flags & SHF_ALLOC) != 0) - { - LoadSection(BaseAddress, Shdr); - } - } - - /* Iterate over all sections and perform relocations */ - Shdr = (Elf_Shdr*)(BaseAddress + Header->e_shoff); - for (int i = 0; i < Header->e_shnum; i++, Shdr++) - { - switch (Shdr->sh_type) - { - case SHT_SYMTAB: - { - RegisterSymbol(Header, Shdr, aPath); - } - break; - case SHT_REL: - { - Shdr->sh_addr = BaseAddress + Shdr->sh_offset; - Relocate(Header, Shdr); - } - break; - } - } - - return Header->e_entry; - } - - private static void Relocate(Elf_Header* aHeader, Elf_Shdr* aShdr) - { - uint BaseAddress = (uint)aHeader; - Elf32_Rel* Reloc = (Elf32_Rel*)aShdr->sh_addr; - Elf_Shdr* TargetSection = (Elf_Shdr*)(BaseAddress + aHeader->e_shoff) + aShdr->sh_info; - - uint RelocCount = aShdr->sh_size / aShdr->sh_entsize; - - byte SymIdx; - uint SymVal, RelocType; - for (uint i = 0; i < RelocCount; i++, Reloc++) - { - SymVal = 0; - SymIdx = (byte)(Reloc->r_info >> 8); - RelocType = Reloc->r_info & 0xFF; - - if (SymIdx != SHN_UNDEF) - { - if (RelocType == R_386_PLT32) - SymVal = 0; - else - SymVal = GetSymValue(aHeader, TargetSection->sh_link, SymIdx); - } - - uint* add_ref = (uint*)(TargetSection->sh_addr + Reloc->r_offset); - switch (RelocType) - { - case R_386_32: - *add_ref = SymVal + *add_ref; // S + A - break; - case R_386_PLT32: // L + A - P - case R_386_PC32: // S + A - P - default: - throw new Exception("[ELF]: Unsupported Relocation type"); - } - } - } - - private static void RegisterSymbol(Elf_Header* aHeader, Elf_Shdr* aShdr, string aPath) - { - uint BaseAddress = (uint)aHeader; - Elf32_Sym* SymTab = (Elf32_Sym*)aShdr->sh_addr; - var StrTabAdd = ((Elf_Shdr*)(BaseAddress + aHeader->e_shoff) + aShdr->sh_link)->sh_addr; - - uint count = aShdr->sh_size / aShdr->sh_entsize; - - uint Address; - for (uint i = 0; i < count; i++, SymTab++) - { - uint flag = (uint)(SymTab->st_info >> 4); - if (flag == STB_GLOBAL) - { - switch (SymTab->st_shndx) - { - case SHN_UNDEF: - continue; // for now ignore UNDEF Symbols - case SHN_ABS: - Address = SymTab->st_value; - break; - default: - var TargetSection = (Elf_Shdr*)(BaseAddress + aHeader->e_shoff) + SymTab->st_shndx; - Address = TargetSection->sh_addr + SymTab->st_value; - break; - } - - string SymName = new string((sbyte*)(StrTabAdd + SymTab->st_name)); - Debug.Write("Symbol: %s\n", SymName); - } - } - } - - private static uint GetSymValue(Elf_Header* aHeader, int aTableIdx, int aSymIdx) - { - uint BaseAddress = (uint)aHeader; - Elf_Shdr* SymSection = (Elf_Shdr*)(BaseAddress + aHeader->e_shoff) + aTableIdx; - Elf32_Sym* SymTab = (Elf32_Sym*)(SymSection->sh_addr) + aSymIdx; - - switch (SymTab->st_shndx) - { - case SHN_UNDEF: - { - var StrTabAdd = ((Elf_Shdr*)(BaseAddress + aHeader->e_shoff) + SymSection->sh_link)->sh_addr; - string SymName = new string((sbyte*)(StrTabAdd + SymTab->st_name)); - - Debug.Write("Undefined Symbol: %s\n", SymName); - throw new Exception("[ELF]: Extern Symbol not supported"); - } - case SHN_ABS: - return SymTab->st_value; - default: - Elf_Shdr* TargetSection = (Elf_Shdr*)(BaseAddress + aHeader->e_shoff) + SymTab->st_shndx; - return TargetSection->sh_addr + SymTab->st_value; - } - } - - private static uint LoadSection(uint aBaseAddress, Elf_Shdr* aShdr) - { - // make sure address if aligned - uint align = aShdr->sh_addralign; - uint addr = Heap.kmalloc(aShdr->sh_size + align); - - if (align != 0) - { - uint offset = addr & (align - 1); - addr += align - offset; - } - - if (aShdr->sh_type != SHT_NOBITS) - Memory.FastCopy(addr, aBaseAddress + aShdr->sh_offset, aShdr->sh_size); - - aShdr->sh_addr = addr; - return addr; - } - - private static void CheckHeader(Elf_Header* aHeader) - { - /* Check if we are supporting this standard */ - var ident = aHeader->e_ident; - if ((ident[EI_MAG0] != ELFMAG0) || - (ident[EI_MAG1] != ELFMAG1) || - (ident[EI_MAG2] != ELFMAG2) || - (ident[EI_MAG3] != ELFMAG3)) - throw new Exception("[ELF]: Invalid File format"); - - if (ident[EI_CLASS] != ELFCLASS32) - throw new Exception("[ELF]: Unsupported EI_CLASS"); - - if (ident[EI_DATA] != ELFDATA2LSB) - throw new Exception("[ELF]: Unsupported EI_DATA"); - - if (aHeader->e_machine != EM_386) - throw new Exception("[ELF]: Unsupported Machine Type"); - - if (aHeader->e_type != ET_REL) - throw new Exception("[ELF]: Unsupported ELF Type"); - - if (aHeader->e_version != EV_CURRENT) - throw new Exception("[ELF]: Unsupported ELF Version"); - } } } diff --git a/src/Kernel/Atomix.Kernel_H/IO/Directory.cs b/src/Kernel/Atomix.Kernel_H/IO/Directory.cs new file mode 100644 index 0000000..4831bb5 --- /dev/null +++ b/src/Kernel/Atomix.Kernel_H/IO/Directory.cs @@ -0,0 +1,33 @@ +/* +* PROJECT: Atomix Development +* LICENSE: BSD 3-Clause (LICENSE.md) +* PURPOSE: VFS Directory +* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) +*/ + +namespace Atomix.Kernel_H.IO +{ + internal abstract class Directory : FSObject + { + internal Directory(string aName) + : base(aName) + { + + } + + internal virtual FSObject FindEntry(string aName) + { + return null; + } + + internal virtual File CreateFile(string aName) + { + return null; + } + + internal virtual Directory CreateDirectory(string aName) + { + return null; + } + } +} \ No newline at end of file diff --git a/src/Kernel/Atomix.Kernel_H/IO/FSObject.cs b/src/Kernel/Atomix.Kernel_H/IO/FSObject.cs new file mode 100644 index 0000000..ecc27b2 --- /dev/null +++ b/src/Kernel/Atomix.Kernel_H/IO/FSObject.cs @@ -0,0 +1,19 @@ +/* +* PROJECT: Atomix Development +* LICENSE: BSD 3-Clause (LICENSE.md) +* PURPOSE: VFS Object +* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) +*/ + +namespace Atomix.Kernel_H.IO +{ + internal abstract class FSObject + { + internal readonly string Name; + + internal FSObject(string aName) + { + Name = aName; + } + } +} \ No newline at end of file diff --git a/src/Kernel/Atomix.Kernel_H/IO/File.cs b/src/Kernel/Atomix.Kernel_H/IO/File.cs new file mode 100644 index 0000000..10d92d5 --- /dev/null +++ b/src/Kernel/Atomix.Kernel_H/IO/File.cs @@ -0,0 +1,22 @@ +/* +* PROJECT: Atomix Development +* LICENSE: BSD 3-Clause (LICENSE.md) +* PURPOSE: VFS File +* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) +*/ + +namespace Atomix.Kernel_H.IO +{ + internal abstract class File : FSObject + { + internal uint SizeInBytes; + + internal File(string aName) + : base(aName) + { + + } + + internal abstract Stream Open(FileMode aMode); + } +} \ No newline at end of file diff --git a/src/Kernel/Atomix.Kernel_H/IO/FileMode.cs b/src/Kernel/Atomix.Kernel_H/IO/FileMode.cs new file mode 100644 index 0000000..ac93543 --- /dev/null +++ b/src/Kernel/Atomix.Kernel_H/IO/FileMode.cs @@ -0,0 +1,16 @@ +/* +* PROJECT: Atomix Development +* LICENSE: BSD 3-Clause (LICENSE.md) +* PURPOSE: VFS File Mode +* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) +*/ + +namespace Atomix.Kernel_H.IO +{ + internal enum FileMode : int + { + Read = 1, + Write = 2, + Append = 4 + }; +} \ No newline at end of file diff --git a/src/Kernel/Atomix.Kernel_H/IO/FileSeek.cs b/src/Kernel/Atomix.Kernel_H/IO/FileSeek.cs new file mode 100644 index 0000000..a52bead --- /dev/null +++ b/src/Kernel/Atomix.Kernel_H/IO/FileSeek.cs @@ -0,0 +1,16 @@ +/* +* PROJECT: Atomix Development +* LICENSE: BSD 3-Clause (LICENSE.md) +* PURPOSE: VFS File Seek +* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) +*/ + +namespace Atomix.Kernel_H.IO +{ + public enum FileSeek : int + { + Origin = 0, + Current = 1, + End = 2, + } +} diff --git a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/Comparison.cs b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/Comparison.cs new file mode 100644 index 0000000..e983616 --- /dev/null +++ b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/Comparison.cs @@ -0,0 +1,14 @@ +/* +* PROJECT: Atomix Development +* LICENSE: BSD 3-Clause (LICENSE.md) +* PURPOSE: FAT Comparator +* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) +*/ + +namespace Atomix.Kernel_H.IO.FileSystem.FAT +{ + internal abstract class Comparison + { + internal abstract bool Compare(byte[] data, int offset, FatType type); + } +} diff --git a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/Entry.cs b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/Entry.cs new file mode 100644 index 0000000..e2e112f --- /dev/null +++ b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/Entry.cs @@ -0,0 +1,57 @@ +/* +* PROJECT: Atomix Development +* LICENSE: BSD 3-Clause (LICENSE.md) +* PURPOSE: FAT Entry Structure +* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) +*/ + +using System.Runtime.InteropServices; + +namespace Atomix.Kernel_H.IO.FileSystem.FAT +{ + [StructLayout(LayoutKind.Explicit, Size = 40)] + internal unsafe struct Entry + { + [FieldOffset(0)] + public fixed sbyte DOSName[8]; + + [FieldOffset(8)] + public fixed sbyte DOSExtension[3]; + + [FieldOffset(11)] + public FatFileAttributes FileAttributes; + + [FieldOffset(12)] + public byte Reserved; + + [FieldOffset(13)] + public byte CreationTimeFine; + + [FieldOffset(14)] + public short CreationTime; + + [FieldOffset(16)] + public short CreationDate; + + [FieldOffset(18)] + public short LastAccessDate; + + [FieldOffset(20)] + public short EAIndex; + + [FieldOffset(22)] + public short LastModifiedTime; + + [FieldOffset(24)] + public short LastModifiedDate; + + [FieldOffset(26)] + public short FirstCluster; + + [FieldOffset(28)] + public uint FileSize; + + [FieldOffset(32)] + public uint EntrySize; + }; +} diff --git a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/FatDirectory.cs b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/FatDirectory.cs new file mode 100644 index 0000000..d4fad29 --- /dev/null +++ b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/FatDirectory.cs @@ -0,0 +1,29 @@ +/* +* PROJECT: Atomix Development +* LICENSE: BSD 3-Clause (LICENSE.md) +* PURPOSE: FAT Directory +* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) +*/ + +namespace Atomix.Kernel_H.IO.FileSystem.FAT +{ + internal class FatDirectory : Directory + { + internal readonly FatFileSystem FS; + internal readonly int StartCluster; + internal readonly uint Size; + + internal FatDirectory(FatFileSystem aFS, string aName, int aStartCluster, uint aSize) + : base(aName) + { + FS = aFS; + StartCluster = aStartCluster; + Size = aSize; + } + + internal override FSObject FindEntry(string aName) + { + return FS.FindEntry(aName, StartCluster); + } + } +} diff --git a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/FatFile.cs b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/FatFile.cs new file mode 100644 index 0000000..2479b8c --- /dev/null +++ b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/FatFile.cs @@ -0,0 +1,31 @@ +/* +* PROJECT: Atomix Development +* LICENSE: BSD 3-Clause (LICENSE.md) +* PURPOSE: FAT Directory +* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) +*/ + +using System; + +namespace Atomix.Kernel_H.IO.FileSystem.FAT +{ + internal class FatFile : File + { + internal readonly FatFileSystem FS; + internal readonly int StartCluster; + internal readonly uint Size; + + internal FatFile(FatFileSystem aFS, string aName, int aStartCluster, uint aSize) + : base(aName) + { + FS = aFS; + StartCluster = aStartCluster;; + Size = aSize; + } + + internal override Stream Open(FileMode aMode) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/FatFileAttribute.cs b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/FatFileAttribute.cs new file mode 100644 index 0000000..6bfd654 --- /dev/null +++ b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/FatFileAttribute.cs @@ -0,0 +1,58 @@ +/* +* PROJECT: Atomix Development +* LICENSE: BSD 3-Clause (LICENSE.md) +* PURPOSE: FAT File Attribute Enum +* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) +*/ + + +namespace Atomix.Kernel_H.IO.FileSystem.FAT +{ + internal enum FatFileAttributes : byte + { + /// + /// Flag represents the file is read-only. + /// + ReadOnly = 0x01, + + /// + /// Flag represents the file is hidden. + /// + Hidden = 0x02, + + /// + /// Flag represents the file is a system file. + /// + System = 0x04, + + /// + /// Flag represents the file entry is a volume label. + /// + VolumeLabel = 0x08, + + /// + /// Flag represents the file entry is a subdirectory. + /// + SubDirectory = 0x10, + + /// + /// Flag represents the file has the archive bit set. + /// + Archive = 0x20, + + /// + /// Flag represents the file entry is for a device. + /// + Device = 0x40, + + /// + /// Flag is unused. + /// + Unused = 0x80, + + /// + /// Flag represents the file has a long file name. + /// + LongFileName = 0x0F + }; +} diff --git a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/FatFileSystem.cs b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/FatFileSystem.cs new file mode 100644 index 0000000..7206379 --- /dev/null +++ b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/FatFileSystem.cs @@ -0,0 +1,231 @@ +/* +* PROJECT: Atomix Development +* LICENSE: BSD 3-Clause (LICENSE.md) +* PURPOSE: Fat File System +* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) +*/ + +using System; + +using Atomixilc.Lib; + +using Atomix.Kernel_H.Core; +using Atomix.Kernel_H.IO.FileSystem.FAT; + +namespace Atomix.Kernel_H.IO.FileSystem +{ + internal unsafe class FatFileSystem : GenericFileSystem + { + int BytePerSector; + int SectorsPerCluster; + int ReservedSector; + int TotalFAT; + int DirectoryEntry; + int TotalSectors; + int SectorsPerFAT; + int DataSectorCount; + int ClusterCount; + int SerialNo; + int RootCluster; + int RootSector; + int RootSectorCount; + int DataSector; + int EntriesPerSector; + int fatEntries; + + FatType FatType; + + string VolumeLabel; + + public FatFileSystem(string aName, Stream aDevice) + :base(aName, aDevice) + { + BytePerSector = 512; + } + + internal override bool Detect() + { + var BootSector = new byte[512]; + + if (!ReadBlock(BootSector, 0, 1)) + return false; + + var xSig = BitConverter.ToUInt16(BootSector, 510); + if (xSig != 0xAA55) + return false; + + /* BPB (BIOS Parameter Block) */ + BytePerSector = BitConverter.ToUInt16(BootSector, 11); + SectorsPerCluster = BootSector[13]; + ReservedSector = BitConverter.ToUInt16(BootSector, 14); + TotalFAT = BootSector[16]; + DirectoryEntry = BitConverter.ToUInt16(BootSector, 17); + + if (BitConverter.ToUInt16(BootSector, 19) == 0) + { + /* Large amount of sector on media. This field is set if there are more than 65535 sectors in the volume. */ + TotalSectors = BitConverter.ToInt32(BootSector, 32); + } + else + { + TotalSectors = BitConverter.ToUInt16(BootSector, 19); + } + + /* FAT 12 and FAT 16 ONLY */ + SectorsPerFAT = BitConverter.ToUInt16(BootSector, 22); + if (SectorsPerFAT == 0) + { + /* FAT 32 ONLY */ + SectorsPerFAT = BitConverter.ToInt32(BootSector, 36); + } + + /* Not Necessary, To Avoid Crashes during corrupted BPB Info */ + // Just to prevent ourself from hacking + if (TotalFAT == 0 || TotalFAT > 2 || BytePerSector == 0 || TotalSectors == 0 || SectorsPerCluster == 0) + return false; + + /* Some basic calculations to check basic error :P */ + int RootDirSectors = 0; + DataSectorCount = TotalSectors - (ReservedSector + (TotalFAT * SectorsPerFAT) + RootDirSectors); + ClusterCount = DataSectorCount / SectorsPerCluster; + + /* Finally we got key xD */ + if (ClusterCount < 4085) + FatType = FatType.FAT12; + else if (ClusterCount < 65525) + FatType = FatType.FAT16; + else + FatType = FatType.FAT32; + + /* Now we open door of gold coins xDD */ + if (FatType == FatType.FAT32) + { + SerialNo = BitConverter.ToInt32(BootSector, 39); + VolumeLabel = new string((sbyte*)BootSector.GetDataOffset(), 71, 11); + RootCluster = BitConverter.ToInt32(BootSector, 44); + RootSector = 0; + RootSectorCount = 0; + } + /* The key is of another door */ + else + { + SerialNo = BitConverter.ToInt32(BootSector, 67); + VolumeLabel = new string((sbyte*)BootSector.GetDataOffset(), 43, 11); + RootSector = ReservedSector + (TotalFAT * SectorsPerFAT); + RootSectorCount = (DirectoryEntry * 32 + (BytePerSector - 1)) / BytePerSector; + fatEntries = SectorsPerFAT * 512 / 4; + } + + /* Now it shows our forward path ;) */ + EntriesPerSector = BytePerSector / 32; + DataSector = ReservedSector + (TotalFAT * SectorsPerFAT) + RootSectorCount; + return true; + } + + internal override FSObject FindEntry(string aName) + { + return FindEntry(aName, RootCluster); + } + + internal FSObject FindEntry(string name, int startCluster) + { + int len = name.Length; + if (len > 12) return null; + + int activeSector = ((startCluster - RootCluster) * SectorsPerCluster) + DataSector; + if (startCluster == 0) + { + activeSector = RootSector; + if (FatType == FatType.FAT32) + activeSector = GetSectorByCluster(RootCluster); + } + + var data = new byte[BytePerSector * SectorsPerCluster]; + ReadBlock(data, activeSector, SectorsPerCluster); + + var entry = (Entry*)data.GetDataOffset(); + for (int index = 0; index < EntriesPerSector * SectorsPerCluster; index++, entry++) + { + var filename = entry->DOSName; + var EntryAttribute = filename[0]; + switch((FileNameAttribute)EntryAttribute) + { + case FileNameAttribute.Escape: + case FileNameAttribute.Deleted: + case FileNameAttribute.LastEntry: + continue; + } + + // compare name + int i = 0; + for (; i < len; i++) + if (filename[i] != name[i]) + break; + + if ((i < len) && (name[i] != '.' || filename[i] != '\0')) + continue; + + i++; + for (; i < len; i++) + if (filename[i - 1] != name[i]) + break; + + if (i < len || filename[i - 1] != '\0') + continue; + + // calculate cluster number + int cluster = entry->FirstCluster; + if (FatType == FatType.FAT32) + cluster |= entry->EAIndex << 16; + + if (cluster == 0) + cluster = 2; + + if ((entry->FileAttributes & FatFileAttributes.SubDirectory) != 0) + return new FatDirectory(this, name, cluster, entry->FileSize); + return new FatFile(this, name, cluster, entry->FileSize); + } + + return null; + } + + internal int GetSectorByCluster(int cluster) + { + return DataSector + ((cluster - RootCluster) * SectorsPerCluster); + } + + internal bool ReadBlock(byte[] aBuffer, int aBlockIndex, int aBlockCount) + { + int count = BytePerSector * aBlockCount; + int offset = aBlockIndex * BytePerSector; + return Device.Read(aBuffer, offset, count) == count; + } + + internal bool WriteBlock(byte[] aBuffer, int aBlockIndex, int aBlockCount) + { + int count = BytePerSector * aBlockCount; + int offset = aBlockIndex * BytePerSector; + return Device.Write(aBuffer, offset, count) == count; + } + + internal void PrintDebugInfo() + { + Debug.Write("BytesPerSector\t\t:%d\n", BytePerSector); + Debug.Write("SectorsPerCluster\t\t:%d\n", SectorsPerCluster); + Debug.Write("ReservedSector\t\t:%d\n", ReservedSector); + Debug.Write("TotalFAT\t\t:%d\n", TotalFAT); + Debug.Write("TotalSectors\t\t:%d\n", TotalSectors); + Debug.Write("SectorsPerFAT\t\t:%d\n", SectorsPerFAT); + Debug.Write("DataSectorCount\t\t:%d\n", DataSectorCount); + Debug.Write("ClusterCount\t\t:%d\n", ClusterCount); + Debug.Write("SerialNo\t\t:%d\n", SerialNo); + Debug.Write("RootCluster\t\t:%d\n", RootCluster); + Debug.Write("RootSector\t\t:%d\n", RootSector); + Debug.Write("RootSectorCount\t\t:%d\n", RootSectorCount); + Debug.Write("DataSector\t\t:%d\n", DataSector); + Debug.Write("EntriesPerSector\t\t:%d\n", EntriesPerSector); + Debug.Write("fatEntries\t\t:%d\n", fatEntries); + Debug.Write("VolumeLabel\t\t:%s\n", VolumeLabel); + } + } +} diff --git a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/FatStream.cs b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/FatStream.cs index d5aa1ee..ed2492c 100644 --- a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/FatStream.cs +++ b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/FatStream.cs @@ -13,6 +13,7 @@ namespace Atomix.Kernel_H.IO.FileSystem.FAT { + /* internal unsafe class FatStream : Stream { private FatFileSystem mFS; @@ -134,5 +135,5 @@ internal override bool Close() Heap.Free((uint)mBufferCluster, (uint)mBufferLength); return true; } - } + }*/ } diff --git a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/FatType.cs b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/FatType.cs new file mode 100644 index 0000000..e69cd84 --- /dev/null +++ b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/FatType.cs @@ -0,0 +1,28 @@ +/* +* PROJECT: Atomix Development +* LICENSE: BSD 3-Clause (LICENSE.md) +* PURPOSE: FAT Type Enum +* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) +*/ + + +namespace Atomix.Kernel_H.IO.FileSystem.FAT +{ + public enum FatType : byte + { + /// + /// Represents a 12-bit FAT. + /// + FAT12 = 12, + + /// + /// Represents a 16-bit FAT. + /// + FAT16 = 16, + + /// + /// Represents a 32-bit FAT. + /// + FAT32 = 32 + } +} diff --git a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/FileLocation.cs b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/FileLocation.cs deleted file mode 100644 index 38d2216..0000000 --- a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/FileLocation.cs +++ /dev/null @@ -1,27 +0,0 @@ -/* -* PROJECT: Atomix Development -* LICENSE: BSD 3-Clause (LICENSE.md) -* PURPOSE: FAT Helper -* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) -*/ - -namespace Atomix.Kernel_H.IO.FileSystem.FAT -{ - internal class FatFileLocation - { - internal readonly uint FirstCluster; - internal readonly uint DirectorySector; - internal readonly uint DirectorySectorIndex; - internal readonly bool directory; - internal readonly int Size; - - internal FatFileLocation(uint aStartCluster, uint aDirectorySector, uint aDirectoryIndex, bool aDirectory, int aSize) - { - FirstCluster = aStartCluster; - DirectorySector = aDirectorySector; - DirectorySectorIndex = aDirectoryIndex; - directory = aDirectory; - Size = aSize; - } - } -} diff --git a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/FileNameAttribute.cs b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/FileNameAttribute.cs new file mode 100644 index 0000000..0be3520 --- /dev/null +++ b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/FileNameAttribute.cs @@ -0,0 +1,17 @@ +/* +* PROJECT: Atomix Development +* LICENSE: BSD 3-Clause (LICENSE.md) +* PURPOSE: FAT Name Attribute Enum +* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) +*/ + +namespace Atomix.Kernel_H.IO.FileSystem.FAT +{ + internal enum FileNameAttribute : uint + { + LastEntry = 0x00, + Escape = 0x05, + Dot = 0x2E, + Deleted = 0xE5, + }; +} diff --git a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/Find/Any.cs b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/Find/Any.cs deleted file mode 100644 index 3ef4541..0000000 --- a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/Find/Any.cs +++ /dev/null @@ -1,28 +0,0 @@ -/* -* PROJECT: Atomix Development -* LICENSE: BSD 3-Clause (LICENSE.md) -* PURPOSE: FAT Helper -* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) -*/ - -namespace Atomix.Kernel_H.IO.FileSystem.FAT.Find -{ - internal class Any : Comparison - { - internal Any() { } - - internal override bool Compare(byte[] data, int offset, FatType type) - { - switch ((FileNameAttribute)data[offset + (uint)Entry.DOSName]) - { - case FileNameAttribute.LastEntry: - case FileNameAttribute.Deleted: - case FileNameAttribute.Escape: - case FileNameAttribute.Dot: - return false; - default: - return true; - } - } - } -} diff --git a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/Find/ByCluster.cs b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/Find/ByCluster.cs deleted file mode 100644 index cf147b5..0000000 --- a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/Find/ByCluster.cs +++ /dev/null @@ -1,38 +0,0 @@ -/* -* PROJECT: Atomix Development -* LICENSE: BSD 3-Clause (LICENSE.md) -* PURPOSE: FAT Helper -* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) -*/ - -namespace Atomix.Kernel_H.IO.FileSystem.FAT.Find -{ - internal class ByCluster : Comparison - { - internal readonly uint Cluster; - internal ByCluster(uint aCluster) - { - Cluster = aCluster; - } - - internal override bool Compare(byte[] data, int offset, FatType type) - { - switch ((FileNameAttribute)data[offset + (uint)Entry.DOSName]) - { - case FileNameAttribute.LastEntry: - case FileNameAttribute.Deleted: - case FileNameAttribute.Escape: - case FileNameAttribute.Dot: - return false; - default: - break; - } - - uint startcluster = FatFileSystem.GetClusterEntry(data, (uint)offset, type); - if (startcluster == Cluster) - return true; - - return false; - } - } -} diff --git a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/Find/Empty.cs b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/Find/Empty.cs deleted file mode 100644 index 64028ed..0000000 --- a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/Find/Empty.cs +++ /dev/null @@ -1,22 +0,0 @@ -/* -* PROJECT: Atomix Development -* LICENSE: BSD 3-Clause (LICENSE.md) -* PURPOSE: FAT Helper -* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) -*/ - -namespace Atomix.Kernel_H.IO.FileSystem.FAT.Find -{ - internal class Empty : Comparison - { - internal Empty() { } - - internal override bool Compare(byte[] data, int offset, FatType type) - { - if ((FileNameAttribute)data[offset + (uint)Entry.DOSName] == FileNameAttribute.LastEntry) - return true; - - return false; - } - } -} diff --git a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/Find/WithName.cs b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/Find/WithName.cs deleted file mode 100644 index 4017926..0000000 --- a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/Find/WithName.cs +++ /dev/null @@ -1,67 +0,0 @@ -/* -* PROJECT: Atomix Development -* LICENSE: BSD 3-Clause (LICENSE.md) -* PURPOSE: FAT Helper -* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) -*/ - -namespace Atomix.Kernel_H.IO.FileSystem.FAT.Find -{ - internal class WithName : Comparison - { - internal string Name; - - internal WithName(string aName) - { - Name = aName; - } - - internal override bool Compare(byte[] data, int offset, FatType type) - { - switch ((FileNameAttribute)data[offset + (int)Entry.DOSName]) - { - case FileNameAttribute.LastEntry: - case FileNameAttribute.Deleted: - case FileNameAttribute.Escape: - return false; - default: - break; - } - - int index; - for (index = 7; index >= 0 && data[offset + index] == ' '; index--) ; - index++; - - int dot = Name.IndexOf('.'); - if (dot == -1) - dot = Name.Length; - - if (dot != index) - return false; - - for (index = 0; index < dot; index++) - { - if ((data[offset + index] & 0xDF) != (Name[index] & 0xDF)) - return false; - } - - for (index = 10; index >= 8 && data[offset + index] == ' '; index--) ; - index -= 7; - - int index2 = Name.Length - dot - 1; - if (index2 < 0) index2 = 0; - - if (index2 != index) - return false; - - dot++; - for (index = 0; index < index2; index++) - { - if ((data[offset + index + 8] & 0xDF) != (Name[dot + index] & 0xDF)) - return false; - } - - return true; - } - } -} diff --git a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/misc.cs b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/misc.cs deleted file mode 100644 index e50b4d5..0000000 --- a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FAT/misc.cs +++ /dev/null @@ -1,114 +0,0 @@ -/* -* PROJECT: Atomix Development -* LICENSE: BSD 3-Clause (LICENSE.md) -* PURPOSE: FAT Helper -* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) -*/ - -namespace Atomix.Kernel_H.IO.FileSystem.FAT -{ - public enum FatType : byte - { - /// - /// Represents a 12-bit FAT. - /// - FAT12 = 12, - - /// - /// Represents a 16-bit FAT. - /// - FAT16 = 16, - - /// - /// Represents a 32-bit FAT. - /// - FAT32 = 32 - } - - internal enum Entry : int - { - DOSName = 0x00, // 8 - DOSExtension = 0x08, // 3 - FileAttributes = 0x0B, // 1 - Reserved = 0x0C, // 1 - CreationTimeFine = 0x0D, // 1 - CreationTime = 0x0E, // 2 - CreationDate = 0x10, // 2 - LastAccessDate = 0x12, // 2 - EAIndex = 0x14, // 2 - LastModifiedTime = 0x16, // 2 - LastModifiedDate = 0x18, // 2 - FirstCluster = 0x1A, // 2 - FileSize = 0x1C, // 4 - EntrySize = 32, - } - - internal enum FindEntry - { - Any = 0x1, - ByCluster = 0x2, - Empty = 0x3, - WithName = 0x4, - } - - internal enum FileNameAttribute : uint - { - LastEntry = 0x00, - Escape = 0x05, // special msdos hack where 0x05 really means 0xE5 (since 0xE5 was already used for delete) - Dot = 0x2E, - Deleted = 0xE5, - } - - internal enum FatFileAttributes : byte - { - /// - /// Flag represents the file is read-only. - /// - ReadOnly = 0x01, - - /// - /// Flag represents the file is hidden. - /// - Hidden = 0x02, - - /// - /// Flag represents the file is a system file. - /// - System = 0x04, - - /// - /// Flag represents the file entry is a volume label. - /// - VolumeLabel = 0x08, - - /// - /// Flag represents the file entry is a subdirectory. - /// - SubDirectory = 0x10, - - /// - /// Flag represents the file has the archive bit set. - /// - Archive = 0x20, - - /// - /// Flag represents the file entry is for a device. - /// - Device = 0x40, - - /// - /// Flag is unused. - /// - Unused = 0x80, - - /// - /// Flag represents the file has a long file name. - /// - LongFileName = 0x0F - } - - internal abstract class Comparison - { - internal abstract bool Compare(byte[] data, int offset, FatType type); - } -} diff --git a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FatFileSystem.cs b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FatFileSystem.cs deleted file mode 100644 index 4ee7484..0000000 --- a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/FatFileSystem.cs +++ /dev/null @@ -1,275 +0,0 @@ -/* -* PROJECT: Atomix Development -* LICENSE: BSD 3-Clause (LICENSE.md) -* PURPOSE: Fat File System -* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) -*/ - -using System; - -using Atomixilc.Lib; - -using Atomix.Kernel_H.Core; -using Atomix.Kernel_H.Devices; -using Atomix.Kernel_H.IO.FileSystem.FAT; -using Atomix.Kernel_H.IO.FileSystem.FAT.Find; - -namespace Atomix.Kernel_H.IO.FileSystem -{ - internal class FatFileSystem : GenericFileSystem - { - // They should be private set only, so take care of this later - internal UInt32 BytePerSector; - internal UInt32 SectorsPerCluster; - internal UInt32 ReservedSector; - internal UInt32 TotalFAT; - internal UInt32 DirectoryEntry; - internal UInt32 TotalSectors; - internal UInt32 SectorsPerFAT; - internal UInt32 DataSectorCount; - internal UInt32 ClusterCount; - internal UInt32 SerialNo; - internal UInt32 RootCluster; - internal UInt32 RootSector; - internal UInt32 RootSectorCount; - internal UInt32 DataSector; - internal UInt32 EntriesPerSector; - internal UInt32 fatEntries; - - protected FatType FatType; - - protected string VolumeLabel; - - public FatFileSystem(Storage Device) - { - IDevice = Device; - mIsValid = IsFAT(); - } - - private unsafe bool IsFAT() - { - var BootSector = new byte[512]; - - if (!IDevice.Read(0U, 1U, BootSector)) - return false; - - var xSig = BitConverter.ToUInt16(BootSector, 510); - if (xSig != 0xAA55) - return false; - - /* BPB (BIOS Parameter Block) */ - BytePerSector = BitConverter.ToUInt16(BootSector, 11); - SectorsPerCluster = BootSector[13]; - ReservedSector = BitConverter.ToUInt16(BootSector, 14); - TotalFAT = BootSector[16]; - DirectoryEntry = BitConverter.ToUInt16(BootSector, 17); - - if (BitConverter.ToUInt16(BootSector, 19) == 0) - { - /* Large amount of sector on media. This field is set if there are more than 65535 sectors in the volume. */ - TotalSectors = BitConverter.ToUInt32(BootSector, 32); - } - else - { - TotalSectors = BitConverter.ToUInt16(BootSector, 19); - } - - /* FAT 12 and FAT 16 ONLY */ - SectorsPerFAT = BitConverter.ToUInt16(BootSector, 22); - - if (SectorsPerFAT == 0) - { - /* FAT 32 ONLY */ - SectorsPerFAT = BitConverter.ToUInt32(BootSector, 36); - } - - /* Not Necessary, To Avoid Crashes during corrupted BPB Info */ - // Just to prevent ourself from hacking - if (TotalFAT == 0 || TotalFAT > 2 || BytePerSector == 0 || TotalSectors == 0 || SectorsPerCluster == 0) - return false; - - /* Some basic calculations to check basic error :P */ - uint RootDirSectors = 0; - DataSectorCount = TotalSectors - (ReservedSector + (TotalFAT * SectorsPerFAT) + RootDirSectors); - ClusterCount = DataSectorCount / SectorsPerCluster; - - /* Finally we got key xD */ - if (ClusterCount < 4085) - FatType = FatType.FAT12; - else if (ClusterCount < 65525) - FatType = FatType.FAT16; - else - FatType = FatType.FAT32; - - /* Now we open door of gold coins xDD */ - if (FatType == FatType.FAT32) - { - SerialNo = BitConverter.ToUInt32(BootSector, 39); - VolumeLabel = new string((sbyte*)BootSector.GetDataOffset(), 71, 11); // for checking - RootCluster = BitConverter.ToUInt32(BootSector, 44); - RootSector = 0; - RootSectorCount = 0; - } - /* The key is of another door */ - else - { - SerialNo = BitConverter.ToUInt32(BootSector, 67); - VolumeLabel = new string((sbyte*)BootSector.GetDataOffset(), 43, 11); - RootSector = ReservedSector + (TotalFAT * SectorsPerFAT); - RootSectorCount = (UInt32)((DirectoryEntry * 32 + (BytePerSector - 1)) / BytePerSector); - fatEntries = SectorsPerFAT * 512 / 4; - } - /* Now it shows our forward path ;) */ - EntriesPerSector = (UInt32)(BytePerSector / 32); - DataSector = ReservedSector + (TotalFAT * SectorsPerFAT) + RootSectorCount; - - mFSType = FileSystemType.FAT; - return true; - } - - internal override bool CreateFile(string[] path, int pointer) - { - return false; - } - - internal override Stream GetFile(string[] path, int pointer) - { - if (!mIsValid) - return null; - - FatFileLocation FileLocation = ChangeDirectory(path, pointer); - if (FileLocation == null) - return null; - - var xStream = new FatStream(this, path[path.Length - 1], FileLocation.FirstCluster, FileLocation.Size); - return xStream; - } - - private FatFileLocation ChangeDirectory(string[] path, int pointer) - { - uint CurrentCluster = RootCluster; - var Compare = new WithName(null); - FatFileLocation location = null; - while (pointer < path.Length) - { - Compare.Name = path[pointer]; - location = FindEntry(Compare, CurrentCluster); - if (location == null) - return null; - CurrentCluster = location.FirstCluster; - pointer++; - } - - return location; - } - - private FatFileLocation FindEntry(Comparison compare, uint startCluster) - { - uint activeSector = ((startCluster - RootCluster) * SectorsPerCluster) + DataSector; - - if (startCluster == 0) - activeSector = (FatType == FatType.FAT32) ? GetSectorByCluster(RootCluster) : RootSector; - - byte[] aData = new byte[BytePerSector * SectorsPerCluster]; - this.IDevice.Read(activeSector, SectorsPerCluster, aData); - - for (uint index = 0; index < EntriesPerSector * SectorsPerCluster; index++) - { - int offset = (int)(index * (int)Entry.EntrySize); - if (compare.Compare(aData, offset, FatType)) - { - FatFileAttributes attribute = (FatFileAttributes)aData[offset + (int)Entry.FileAttributes]; - return new FatFileLocation( - GetClusterEntry(aData, index, FatType), - activeSector, - index, - (attribute & FatFileAttributes.SubDirectory) != 0, - BitConverter.ToInt32(aData, offset + (int)Entry.FileSize)); - } - - if (aData[(int)Entry.DOSName + offset] == (int)FileNameAttribute.LastEntry) - break; - } - - return null; - } - - internal uint GetClusterEntryValue(uint cluster) - { - uint fatoffset = cluster<<2; - uint sector = ReservedSector + (fatoffset / BytePerSector); - int sectorOffset = (int)(fatoffset % BytePerSector); - - var aData = new byte[512]; - IDevice.Read(sector, 1U, aData); - var xNextCluster = (BitConverter.ToUInt32(aData, sectorOffset) & 0x0FFFFFFF); - - return xNextCluster; - } - - private uint GetSectorByCluster(uint cluster) - { - return DataSector + ((cluster - RootCluster) * SectorsPerCluster); - } - - internal static uint GetClusterEntry(byte[] data, uint index, FatType type) - { - uint cluster = BitConverter.ToUInt16(data, (int)((uint)Entry.FirstCluster + (index * (uint)Entry.EntrySize))); - - if (type == FatType.FAT32) - cluster |= (uint)BitConverter.ToUInt16(data, (int)((uint)Entry.EAIndex + (index * (uint)Entry.EntrySize))) << 16; - - if (cluster == 0) - cluster = 2; - - return cluster; - } - - internal static bool IsClusterBad(uint Cluster) - { - // Values are depend only on FAT 32 FS - return (Cluster == 0x0FFFFFF7); - } - - internal static bool IsClusterFree(uint Cluster) - { - // Values are depend only on FAT 32 FS - return (Cluster == 0x0); - } - - internal static bool IsClusterReserved(uint Cluster) - { - // Values are depend only on FAT 32 FS - return ((Cluster == 0x0) || (Cluster >= 0xFFF0) && (Cluster < 0x0FFFFFF7)); - } - - internal static bool IsClusterLast(uint Cluster) - { - // Values are depend only on FAT 32 FS - return (Cluster == 0x0FFFFFF8); - } - - internal byte[] NewBlockArray - { get { return new byte[SectorsPerCluster * BytePerSector]; } } - - internal void PrintDebugInfo() - { - Debug.Write("BytesPerSector\t\t:%d\n", BytePerSector); - Debug.Write("SectorsPerCluster\t\t:%d\n", SectorsPerCluster); - Debug.Write("ReservedSector\t\t:%d\n", ReservedSector); - Debug.Write("TotalFAT\t\t:%d\n", TotalFAT); - Debug.Write("TotalSectors\t\t:%d\n", TotalSectors); - Debug.Write("SectorsPerFAT\t\t:%d\n", SectorsPerFAT); - Debug.Write("DataSectorCount\t\t:%d\n", DataSectorCount); - Debug.Write("ClusterCount\t\t:%d\n", ClusterCount); - Debug.Write("SerialNo\t\t:%d\n", SerialNo); - Debug.Write("RootCluster\t\t:%d\n", RootCluster); - Debug.Write("RootSector\t\t:%d\n", RootSector); - Debug.Write("RootSectorCount\t\t:%d\n", RootSectorCount); - Debug.Write("DataSector\t\t:%d\n", DataSector); - Debug.Write("EntriesPerSector\t\t:%d\n", EntriesPerSector); - Debug.Write("fatEntries\t\t:%d\n", fatEntries); - Debug.Write("VolumeLabel\t\t:%s\n", VolumeLabel); - } - } -} diff --git a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/GenericFileSystem.cs b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/GenericFileSystem.cs index f7a169e..2159c3d 100644 --- a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/GenericFileSystem.cs +++ b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/GenericFileSystem.cs @@ -1,34 +1,22 @@ /* * PROJECT: Atomix Development * LICENSE: BSD 3-Clause (LICENSE.md) -* PURPOSE: Generic File System class +* PURPOSE: Generic File System * PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) */ -using Atomix.Kernel_H.Devices; - namespace Atomix.Kernel_H.IO.FileSystem { - public abstract class GenericFileSystem + internal abstract class GenericFileSystem : Directory { - internal Storage IDevice; - protected bool mIsValid; - protected FileSystemType mFSType; - - internal bool IsValid - { get { return mIsValid; } } - - internal FileSystemType FileSystem - { get { return mFSType; } } + internal readonly Stream Device; - internal abstract Stream GetFile(string[] path, int pointer); + internal GenericFileSystem(string aName, Stream aDevice) + : base(aName) + { + Device = aDevice; + } - internal abstract bool CreateFile(string[] path, int pointer); - } - - public enum FileSystemType : byte - { - None = 0x0, - FAT = 0x1 + internal abstract bool Detect(); } -} +} \ No newline at end of file diff --git a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/RFS/FileEntry.cs b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/RFS/FileEntry.cs new file mode 100644 index 0000000..0a584ab --- /dev/null +++ b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/RFS/FileEntry.cs @@ -0,0 +1,24 @@ +/* +* PROJECT: Atomix Development +* LICENSE: BSD 3-Clause (LICENSE.md) +* PURPOSE: Ram File Entry +* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) +*/ + +using System.Runtime.InteropServices; + +namespace Atomix.Kernel_H.IO.FileSystem.RFS +{ + [StructLayout(LayoutKind.Explicit, Size = 40)] + internal unsafe struct FileEntry + { + [FieldOffset(0)] + public fixed sbyte Name[32]; + + [FieldOffset(32)] + public uint StartAddress; + + [FieldOffset(36)] + public int Length; + } +} diff --git a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/RFS/FileStream.cs b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/RFS/FileStream.cs deleted file mode 100644 index dfde690..0000000 --- a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/RFS/FileStream.cs +++ /dev/null @@ -1,93 +0,0 @@ -/* -* PROJECT: Atomix Development -* LICENSE: BSD 3-Clause (LICENSE.md) -* PURPOSE: RFS (Ram File System) File Stream class -* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) -*/ - -using System; - -using Atomixilc.Lib; - -using Atomix.Kernel_H.Core; - -namespace Atomix.Kernel_H.IO.FileSystem.RFS -{ - internal unsafe class FileStream : Stream - { - internal readonly RamFile RamFile; - int mPosition; - - internal FileStream(RamFile aRamFile) - :base(aRamFile.Name, aRamFile.Length) - { - RamFile = aRamFile; - mPosition = 0; - } - - internal override int Read(byte[] aBuffer, int aCount) - { - if (aBuffer.Length > aCount) - aCount = aBuffer.Length; - - return Read((byte*)aBuffer.GetDataOffset(), aCount); - } - - internal override unsafe int Read(byte* aBuffer, int aCount) - { - if (aCount + mPosition > RamFile.Length) - aCount = RamFile.Length - mPosition; - - Memory.FastCopy((uint)aBuffer, RamFile.StartAddress + (uint)mPosition, (uint)aCount); - - mPosition += aCount; - return aCount; - } - - internal override int Write(byte[] aBuffer, int aCount) - { - return 0; - } - - internal override unsafe int Write(byte* aBuffer, int aCount) - { - return 0; - } - - internal override bool CanRead() - { return true; } - - internal override bool CanSeek() - { return false; } - - internal override bool CanWrite() - { return false; } - - internal override int Position() - { return mPosition; } - - internal override int Seek(int val, SEEK pos) - { - switch(pos) - { - case SEEK.SEEK_FROM_CURRENT: - mPosition += val; - break; - case SEEK.SEEK_FROM_ORIGIN: - mPosition += val; - break; - case SEEK.SEEK_FROM_END: - mPosition = RamFile.Length + val; - break; - } - - mPosition %= RamFile.Length; - return mPosition; - } - - internal override bool Close() - { - return true; - } - } -} diff --git a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/RFS/RamFile.cs b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/RFS/RamFile.cs index 6e0d9a0..9817729 100644 --- a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/RFS/RamFile.cs +++ b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/RFS/RamFile.cs @@ -7,17 +7,23 @@ namespace Atomix.Kernel_H.IO.FileSystem.RFS { - internal class RamFile + internal class RamFile : File { - internal readonly string Name; - internal readonly uint StartAddress; - internal readonly int Length; + int mLength; + uint mStartAddress; internal RamFile(string aName, uint aStartAddress, int aLength) + :base(aName) { - Name = aName; - StartAddress = aStartAddress; - Length = aLength; + mLength = aLength; + mStartAddress = aStartAddress; + } + + internal override Stream Open(FileMode aMode) + { + if ((aMode & FileMode.Append) != 0 || (aMode & FileMode.Write) != 0) + return null; + return new MemoryStream(mStartAddress, mLength); } } } diff --git a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/RFS/RamFileSystem.cs b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/RFS/RamFileSystem.cs new file mode 100644 index 0000000..ffc13c3 --- /dev/null +++ b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/RFS/RamFileSystem.cs @@ -0,0 +1,49 @@ +/* +* PROJECT: Atomix Development +* LICENSE: BSD 3-Clause (LICENSE.md) +* PURPOSE: Ram File System +* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) +*/ + +using Atomixilc.Lib; + +using Atomix.Kernel_H.Lib; +using Atomix.Kernel_H.IO.FileSystem.RFS; + +namespace Atomix.Kernel_H.IO.FileSystem +{ + internal unsafe class RamFileSystem : GenericFileSystem + { + IDictionary mFiles; + + internal RamFileSystem(string aName, Stream aDevice) + :base(aName, aDevice) + { + mFiles = new IDictionary(Internals.GetHashCode, string.Equals); + } + + internal override bool Detect() + { + if (!(Device is MemoryStream)) + return false; + + var stream = (MemoryStream)Device; + var data = new byte[sizeof(FileEntry)]; + var entry = (FileEntry*)data.GetDataOffset(); + + stream.Read(data, sizeof(FileEntry)); + while (entry->StartAddress != 0) + { + var name = new string(entry->Name); + mFiles.Add(name, new RamFile(name, stream.Address + entry->StartAddress, entry->Length)); + Device.Read(data, sizeof(FileEntry)); + } + return true; + } + + internal override FSObject FindEntry(string aName) + { + return mFiles.GetValue(aName, null); + } + } +} diff --git a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/RamFileSystem.cs b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/RamFileSystem.cs deleted file mode 100644 index b1bbef0..0000000 --- a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/RamFileSystem.cs +++ /dev/null @@ -1,70 +0,0 @@ -/* -* PROJECT: Atomix Development -* LICENSE: BSD 3-Clause (LICENSE.md) -* PURPOSE: Ram File System -* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) -*/ - -using Atomixilc.Lib; - -using Atomix.Kernel_H.Lib; -using Atomix.Kernel_H.IO.FileSystem.RFS; - -using System.Runtime.InteropServices; - -namespace Atomix.Kernel_H.IO.FileSystem -{ - internal unsafe class RamFileSystem : GenericFileSystem - { - uint DataAddress; - uint DataLength; - IDictionary Files; - - internal RamFileSystem(uint aAddress, uint aLength) - { - DataAddress = aAddress; - DataLength = aLength; - Files = new IDictionary(Internals.GetHashCode, string.Equals); - mIsValid = LoadFileSystem(); - } - - private bool LoadFileSystem() - { - var Entries = (FileEntry*)DataAddress; - Entries++; - while(Entries->StartAddress != 0) - { - var FileName = new string(Entries->Name); - Files.Add(FileName, new RamFile(FileName, Entries->StartAddress + DataAddress, Entries->Length)); - Entries++; - } - return true; - } - - internal override Stream GetFile(string[] path, int pointer) - { - var FileName = path[pointer]; - if (Files.ContainsKey(FileName)) - return new FileStream(Files[FileName]); - return null; - } - - internal override bool CreateFile(string[] path, int pointer) - { - return false; - } - - [StructLayout(LayoutKind.Explicit, Size = 40)] - struct FileEntry - { - [FieldOffset(0)] - public fixed sbyte Name[32]; - - [FieldOffset(32)] - public uint StartAddress; - - [FieldOffset(36)] - public int Length; - } - } -} diff --git a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/VirtualFileSystem.cs b/src/Kernel/Atomix.Kernel_H/IO/FileSystem/VirtualFileSystem.cs deleted file mode 100644 index e38a338..0000000 --- a/src/Kernel/Atomix.Kernel_H/IO/FileSystem/VirtualFileSystem.cs +++ /dev/null @@ -1,77 +0,0 @@ -/* -* PROJECT: Atomix Development -* LICENSE: BSD 3-Clause (LICENSE.md) -* PURPOSE: Virtual File System -* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) -*/ - -using System; - -using Atomixilc.Lib; - -using Atomix.Kernel_H.Lib; -using Atomix.Kernel_H.Core; - -namespace Atomix.Kernel_H.IO.FileSystem -{ - internal static class VirtualFileSystem - { - static IDictionary MountedFS; - - internal static void Setup() - { - MountedFS = new IDictionary(Internals.GetHashCode, string.Equals); - } - - internal static GenericFileSystem GetFS(string aDevice) - { - if (!MountedFS.ContainsKey(aDevice)) - return null; - return MountedFS[aDevice]; - } - - internal static Stream GetFile(string aPath) - { - var paths = Marshal.Split(aPath, '/'); - var FileSystem = GetFS(paths[0]); - if (FileSystem == null) - return null; - var xStream = FileSystem.GetFile(paths, 1); - return xStream; - } - - internal static bool CreateFile(string aPath) - { - var paths = Marshal.Split(aPath, '/'); - var FileSystem = GetFS(paths[0]); - if (FileSystem == null) - return false; - var xValue = FileSystem.CreateFile(paths, 1); - return xValue; - } - - internal static bool MountDevice(string aDeviceName, GenericFileSystem aFS) - { - if (!aFS.IsValid) - return false; - - if (aDeviceName == null) - aDeviceName = GetDeviceLabel(); - - if (MountedFS.ContainsKey(aDeviceName)) - return false; - - MountedFS.Add(aDeviceName, aFS); - Debug.Write("Directory Mounted: %s\n", aDeviceName); - return true; - } - - static uint mDeviceLabelCounter = 0; - private static string GetDeviceLabel() - { - string suffix = Convert.ToString(mDeviceLabelCounter++); - string Label = ("disk") + suffix; - return Label; - } - } -} diff --git a/src/Kernel/Atomix.Kernel_H/IO/MemoryStream.cs b/src/Kernel/Atomix.Kernel_H/IO/MemoryStream.cs new file mode 100644 index 0000000..be0adb9 --- /dev/null +++ b/src/Kernel/Atomix.Kernel_H/IO/MemoryStream.cs @@ -0,0 +1,100 @@ +/* +* PROJECT: Atomix Development +* LICENSE: BSD 3-Clause (LICENSE.md) +* PURPOSE: Memory Stream Class +* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) +*/ + +using Atomixilc.Lib; + +namespace Atomix.Kernel_H.IO +{ + internal unsafe class MemoryStream : Stream + { + uint mAddress; + int mLength; + + int mPointer; + + internal uint Address + { get { return mAddress; } } + + internal int Length + { get { return mLength; } } + + internal MemoryStream(uint aAddress, int aLength) + { + mAddress = aAddress; + mLength = aLength; + mPointer = 0; + } + + internal override int Read(byte[] aBuffer, int aCount) + { + int aOffset = mPointer; + if (aOffset + aCount >= mLength) + aCount = mLength - aOffset; + Memory.FastCopy(aBuffer.GetDataOffset(), mAddress, aCount); + mPointer = aOffset + aCount; + return aCount; + } + + internal override int Read(byte[] aBuffer, int aOffset, int aCount) + { + if (aOffset + aCount >= mLength) + aCount = mLength - aOffset; + Memory.FastCopy(aBuffer.GetDataOffset(), mAddress, aCount); + return aCount; + } + + internal override int Write(byte[] aBuffer, int aCount) + { + int aOffset = mPointer; + if (aOffset + aCount >= mLength) + aCount = mLength - aOffset; + Memory.FastCopy(mAddress, aBuffer.GetDataOffset(), aCount); + mPointer = aOffset + aCount; + return aCount; + } + + internal override int Write(byte[] aBuffer, int aOffset, int aCount) + { + if (aOffset + aCount >= mLength) + aCount = mLength - aOffset; + Memory.FastCopy(mAddress, aBuffer.GetDataOffset(), aCount); + return aCount; + } + + internal override int Seek(int aValue, FileSeek aSeek) + { + switch (aSeek) + { + case FileSeek.Origin: + { + mPointer = 0; + } + break; + case FileSeek.Current: + { + if (mPointer + aValue > mLength) + break; + mPointer += aValue; + } + break; + case FileSeek.End: + { + if (aValue > mLength) + break; + mPointer = mLength - aValue; + } + break; + } + return mPointer; + } + + internal override bool Close() + { + return true; + } + } +} diff --git a/src/Kernel/Atomix.Kernel_H/IO/Pipe.cs b/src/Kernel/Atomix.Kernel_H/IO/Pipe.cs index a244ca2..3cd44f6 100644 --- a/src/Kernel/Atomix.Kernel_H/IO/Pipe.cs +++ b/src/Kernel/Atomix.Kernel_H/IO/Pipe.cs @@ -47,7 +47,7 @@ internal bool Write(byte* aData, bool Hangup = true) if (BufferStatus[WritingPointer]) return false; - Memory.FastCopy((uint)Buffer + (uint)(WritingPointer * PacketSize), (uint)aData, (uint)PacketSize); + Memory.FastCopy((uint)Buffer + (uint)(WritingPointer * PacketSize), (uint)aData, PacketSize); BufferStatus[WritingPointer] = true; WritingPointer = (WritingPointer + 1) % PacketsCount; @@ -59,7 +59,7 @@ internal bool Read(byte[] aData) while (!BufferStatus[ReadingPointer]) Task.Switch(); - Memory.FastCopy(aData.GetDataOffset(), (uint)Buffer + (uint)(ReadingPointer * PacketSize), (uint)PacketSize); + Memory.FastCopy(aData.GetDataOffset(), (uint)Buffer + (uint)(ReadingPointer * PacketSize), PacketSize); BufferStatus[ReadingPointer] = false; ReadingPointer = (ReadingPointer + 1) % PacketsCount; diff --git a/src/Kernel/Atomix.Kernel_H/IO/Stream.cs b/src/Kernel/Atomix.Kernel_H/IO/Stream.cs index 609b5ee..43add4c 100644 --- a/src/Kernel/Atomix.Kernel_H/IO/Stream.cs +++ b/src/Kernel/Atomix.Kernel_H/IO/Stream.cs @@ -5,40 +5,15 @@ * PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) */ -using Atomix.Kernel_H.Core; - namespace Atomix.Kernel_H.IO { - public abstract class Stream + internal abstract class Stream { - internal readonly string FileName; - internal readonly int FileSize; - - internal Stream(string aFileName, int aSize) - { - FileName = aFileName; - FileSize = aSize; - } - - internal abstract bool CanSeek(); - internal abstract int Position(); - internal abstract bool CanRead(); - internal abstract bool CanWrite(); - - internal abstract unsafe int Write(byte* aBuffer, int aCount); - internal abstract unsafe int Read(byte* aBuffer, int aCount); - + internal abstract int Seek(int aValue, FileSeek aSeek); internal abstract int Write(byte[] aBuffer, int aCount); + internal abstract int Write(byte[] aBuffer, int aOffset, int aCount); internal abstract int Read(byte[] aBuffer, int aCount); - internal abstract int Seek(int val, SEEK pos); - + internal abstract int Read(byte[] aBuffer, int aOffset, int aCount); internal abstract bool Close(); } - - public enum SEEK : int - { - SEEK_FROM_ORIGIN = 0, - SEEK_FROM_CURRENT = 1, - SEEK_FROM_END = 2, - } } diff --git a/src/Kernel/Atomix.Kernel_H/IO/VFN.cs b/src/Kernel/Atomix.Kernel_H/IO/VFN.cs new file mode 100644 index 0000000..746df54 --- /dev/null +++ b/src/Kernel/Atomix.Kernel_H/IO/VFN.cs @@ -0,0 +1,37 @@ +/* +* PROJECT: Atomix Development +* LICENSE: BSD 3-Clause (LICENSE.md) +* PURPOSE: Virtual File Node +* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) +*/ + +using Atomixilc.Lib; + +using Atomix.Kernel_H.Lib; + +namespace Atomix.Kernel_H.IO +{ + internal class VFN : Directory + { + IDictionary mEntries; + + internal VFN(string aName) + : base(aName) + { + mEntries = new IDictionary(Internals.GetHashCode, string.Equals); + } + + internal override FSObject FindEntry(string aName) + { + return mEntries.GetValue(aName, null); + } + + internal bool Mount(FSObject aObject) + { + if (mEntries.ContainsKey(aObject.Name)) + return false; + mEntries.Add(aObject.Name, aObject); + return true; + } + } +} \ No newline at end of file diff --git a/src/Kernel/Atomix.Kernel_H/IO/VirtualFileSystem.cs b/src/Kernel/Atomix.Kernel_H/IO/VirtualFileSystem.cs new file mode 100644 index 0000000..7a2a3f4 --- /dev/null +++ b/src/Kernel/Atomix.Kernel_H/IO/VirtualFileSystem.cs @@ -0,0 +1,56 @@ +/* +* PROJECT: Atomix Development +* LICENSE: BSD 3-Clause (LICENSE.md) +* PURPOSE: Virtual File System +* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com) +*/ + +using Atomix.Kernel_H.Lib; +using Atomix.Kernel_H.Core; + +namespace Atomix.Kernel_H.IO +{ + internal static class VirtualFileSystem + { + static VFN mRoot; + + internal static void Install() + { + mRoot = new VFN(string.Empty); + } + + internal static FSObject Open(string aPath) + { + var paths = Marshal.Split(aPath, '/'); + + int count = paths.Length; + if (paths[0] != string.Empty) + return null; + + FSObject node = mRoot; + for (int i = 1; i < count; i++) + { + if (node == null || !(node is Directory)) + return null; + node = ((Directory)node).FindEntry(paths[i]); + } + + return node; + } + + internal static bool Mount(FSObject aObject, string aPath) + { + var node = Open(aPath); + if (node == null || !(node is VFN)) + return false; + Debug.Write("VFS Mounted: %s\n", aPath); + ((VFN)node).Mount(aObject); + return true; + } + + internal static bool Map(string aPath, string aName) + { + return Mount(new VFN(aName), aPath); + } + } +} \ No newline at end of file diff --git a/src/Kernel/Atomix.Kernel_H/Lib/Marshal.cs b/src/Kernel/Atomix.Kernel_H/Lib/Marshal.cs index 4ac9997..7886e88 100644 --- a/src/Kernel/Atomix.Kernel_H/Lib/Marshal.cs +++ b/src/Kernel/Atomix.Kernel_H/Lib/Marshal.cs @@ -36,7 +36,7 @@ internal static void Copy(string aStr, sbyte* aCstr, int aLen) internal static void Copy(char* aDes, string aSrc, int aLen) { - Memory.FastCopy((uint)aDes, aSrc.GetDataOffset(), (uint)(aLen * sizeof(char))); + Memory.FastCopy((uint)aDes, aSrc.GetDataOffset(), aLen * sizeof(char)); aDes[aLen] = '\0'; } diff --git a/src/Kernel/Atomix.Kernel_H/Start-x86.cs b/src/Kernel/Atomix.Kernel_H/Start-x86.cs index c6db023..ee22316 100644 --- a/src/Kernel/Atomix.Kernel_H/Start-x86.cs +++ b/src/Kernel/Atomix.Kernel_H/Start-x86.cs @@ -13,11 +13,11 @@ using Atomixilc.Attributes; using Atomixilc.Machine.x86; +using Atomix.Kernel_H.IO; using Atomix.Kernel_H.Core; using Atomix.Kernel_H.Devices; using Atomix.Kernel_H.Arch.x86; using Atomix.Kernel_H.Drivers.Video; -using Atomix.Kernel_H.IO.FileSystem; namespace Atomix.Kernel_H { @@ -168,7 +168,7 @@ internal static void Start(uint magic, uint address, uint KernelDirectory, uint VBE.Init(); /* Initialise Virtual File system */ - VirtualFileSystem.Setup(); + VirtualFileSystem.Install(); /* Setup Syscall */ Syscall.Setup();