diff options
Diffstat (limited to 'dev')
| -rw-r--r-- | dev/kernel/FSKit/Ext2.h | 218 | ||||
| -rw-r--r-- | dev/kernel/FSKit/Ext2IFS.h | 133 | ||||
| -rw-r--r-- | dev/kernel/HALKit/ARM64/HalHandoverStub.s | 8 |
3 files changed, 251 insertions, 108 deletions
diff --git a/dev/kernel/FSKit/Ext2.h b/dev/kernel/FSKit/Ext2.h index 35129dcd..42875c47 100644 --- a/dev/kernel/FSKit/Ext2.h +++ b/dev/kernel/FSKit/Ext2.h @@ -13,121 +13,131 @@ #include <hint/CompilerHint.h> /// @file Ext2.h -/// @brief EXT2 filesystem structures and constants. +/// @brief EXT2 filesystem structures, constants, and base wrappers. -#define kExt2FSMagic (0xEF53) -#define kExt2FSMaxFileNameLen (255U) -#define kExt2FSSuperblockOffset (1024) -#define kExt2FSRootInodeNumber (2) +namespace Ext2 { -#define kExt2FSInodeSize (128U) -#define kExt2FSBlockSizeBase (1024U) +/// EXT2 Constants +#define kExt2FSMagic (0xEF53) +#define kExt2FSMaxFileNameLen (255U) +#define kExt2FSSuperblockOffset (1024) +#define kExt2FSRootInodeNumber (2) +#define kExt2FSInodeSize (128U) +#define kExt2FSBlockSizeBase (1024U) -#define kExt2FSRev0 (0) -#define kExt2FSRev1 (1) +#define kExt2FSRev0 (0) +#define kExt2FSRev1 (1) -/// @brief EXT2's file types. +/// EXT2 file types enum { - kExt2FileTypeUnknown = 0, - kExt2FileTypeRegular = 1, - kExt2FileTypeDirectory = 2, - kExt2FileTypeCharDevice = 3, - kExt2FileTypeBlockDevice = 4, - kExt2FileTypeFIFO = 5, - kExt2FileTypeSocket = 6, - kExt2FileTypeSymbolicLink = 7 + kExt2FileTypeUnknown = 0, + kExt2FileTypeRegular = 1, + kExt2FileTypeDirectory = 2, + kExt2FileTypeCharDevice = 3, + kExt2FileTypeBlockDevice = 4, + kExt2FileTypeFIFO = 5, + kExt2FileTypeSocket = 6, + kExt2FileTypeSymbolicLink = 7 }; -/// @brief The super block structure, located at LBA 1024. struct PACKED EXT2_SUPER_BLOCK final { - Kernel::UInt32 fInodeCount; - Kernel::UInt32 fBlockCount; - Kernel::UInt32 fReservedBlockCount; - Kernel::UInt32 fFreeBlockCount; - Kernel::UInt32 fFreeInodeCount; - Kernel::UInt32 fFirstDataBlock; - Kernel::UInt32 fLogBlockSize; - Kernel::UInt32 fLogFragmentSize; - Kernel::UInt32 fBlocksPerGroup; - Kernel::UInt32 fFragmentsPerGroup; - Kernel::UInt32 fInodesPerGroup; - Kernel::UInt32 fMountTime; - Kernel::UInt32 fWriteTime; - Kernel::UInt16 fMountCount; - Kernel::UInt16 fMaxMountCount; - Kernel::UInt16 fMagic; // should be 0xEF53 - Kernel::UInt16 fState; - Kernel::UInt16 fErrors; - Kernel::UInt16 fMinorRevision; - Kernel::UInt32 fLastCheck; - Kernel::UInt32 fCheckInterval; - Kernel::UInt32 fCreatorOS; - Kernel::UInt32 fRevisionLevel; - Kernel::UInt16 fDefaultUID; - Kernel::UInt16 fDefaultGID; - - // EXT2_DYNAMIC_REV fields - Kernel::UInt32 fFirstInode; - Kernel::UInt16 fInodeSize; - Kernel::UInt16 fBlockGroupNumber; - Kernel::UInt32 fFeatureCompat; - Kernel::UInt32 fFeatureIncompat; - Kernel::UInt32 fFeatureROCompat; - Kernel::UInt8 fUUID[16]; - Kernel::Char fVolumeName[16]; - Kernel::Char fLastMounted[64]; - Kernel::UInt32 fAlgoBitmap; - - // Optional journal fields and padding - Kernel::UInt8 fPreallocBlocks; - Kernel::UInt8 fPreallocDirBlocks; - Kernel::UInt16 fReservedGDTBlocks; - - Kernel::UInt8 fJournalUUID[16]; - Kernel::UInt32 fJournalInode; - Kernel::UInt32 fJournalDevice; - Kernel::UInt32 fLastOrphan; - - Kernel::UInt32 fHashSeed[4]; - Kernel::UInt8 fDefHashVersion; - Kernel::UInt8 fReservedCharPad; - Kernel::UInt16 fReservedWordPad; - Kernel::UInt32 fDefaultMountOpts; - Kernel::UInt32 fFirstMetaBlockGroup; - - Kernel::UInt8 fReserved[760]; // Padding to make 1024 bytes + Kernel::UInt32 fInodeCount; + Kernel::UInt32 fBlockCount; + Kernel::UInt32 fReservedBlockCount; + Kernel::UInt32 fFreeBlockCount; + Kernel::UInt32 fFreeInodeCount; + Kernel::UInt32 fFirstDataBlock; + Kernel::UInt32 fLogBlockSize; + Kernel::UInt32 fLogFragmentSize; + Kernel::UInt32 fBlocksPerGroup; + Kernel::UInt32 fFragmentsPerGroup; + Kernel::UInt32 fInodesPerGroup; + Kernel::UInt32 fMountTime; + Kernel::UInt32 fWriteTime; + Kernel::UInt16 fMountCount; + Kernel::UInt16 fMaxMountCount; + Kernel::UInt16 fMagic; + Kernel::UInt16 fState; + Kernel::UInt16 fErrors; + Kernel::UInt16 fMinorRevision; + Kernel::UInt32 fLastCheck; + Kernel::UInt32 fCheckInterval; + Kernel::UInt32 fCreatorOS; + Kernel::UInt32 fRevisionLevel; + Kernel::UInt16 fDefaultUID; + Kernel::UInt16 fDefaultGID; + + // EXT2_DYNAMIC_REV fields + Kernel::UInt32 fFirstInode; + Kernel::UInt16 fInodeSize; + Kernel::UInt16 fBlockGroupNumber; + Kernel::UInt32 fFeatureCompat; + Kernel::UInt32 fFeatureIncompat; + Kernel::UInt32 fFeatureROCompat; + Kernel::UInt8 fUUID[16]; + Kernel::Char fVolumeName[16]; + Kernel::Char fLastMounted[64]; + Kernel::UInt32 fAlgoBitmap; + + Kernel::UInt8 fPreallocBlocks; + Kernel::UInt8 fPreallocDirBlocks; + Kernel::UInt16 fReservedGDTBlocks; + + Kernel::UInt8 fJournalUUID[16]; + Kernel::UInt32 fJournalInode; + Kernel::UInt32 fJournalDevice; + Kernel::UInt32 fLastOrphan; + + Kernel::UInt32 fHashSeed[4]; + Kernel::UInt8 fDefHashVersion; + Kernel::UInt8 fReservedCharPad; + Kernel::UInt16 fReservedWordPad; + Kernel::UInt32 fDefaultMountOpts; + Kernel::UInt32 fFirstMetaBlockGroup; + + Kernel::UInt8 fReserved[760]; // Padding to make 1024 bytes }; struct PACKED EXT2_INODE final { - Kernel::UInt16 fMode; - Kernel::UInt16 fUID; - Kernel::UInt32 fSize; - Kernel::UInt32 fAccessTime; - Kernel::UInt32 fCreateTime; - Kernel::UInt32 fModifyTime; - Kernel::UInt32 fDeleteTime; - Kernel::UInt16 fGID; - Kernel::UInt16 fLinksCount; - Kernel::UInt32 fBlocks; - Kernel::UInt32 fFlags; - Kernel::UInt32 fOSD1; - - Kernel::UInt32 - fBlock[15]; // 0-11: direct, 12: indirect, 13: double indirect, 14: triple indirect - - Kernel::UInt32 fGeneration; - Kernel::UInt32 fFileACL; - Kernel::UInt32 fDirACL; // Only for revision 1+ - Kernel::UInt32 fFragmentAddr; - - Kernel::UInt8 fOSD2[12]; + Kernel::UInt16 fMode; + Kernel::UInt16 fUID; + Kernel::UInt32 fSize; + Kernel::UInt32 fAccessTime; + Kernel::UInt32 fCreateTime; + Kernel::UInt32 fModifyTime; + Kernel::UInt32 fDeleteTime; + Kernel::UInt16 fGID; + Kernel::UInt16 fLinksCount; + Kernel::UInt32 fBlocks; + Kernel::UInt32 fFlags; + Kernel::UInt32 fOSD1; + + Kernel::UInt32 fBlock[15]; // direct 0-11, indirect 12, double 13, triple 14 + + Kernel::UInt32 fGeneration; + Kernel::UInt32 fFileACL; + Kernel::UInt32 fDirACL; + Kernel::UInt32 fFragmentAddr; + + Kernel::UInt8 fOSD2[12]; }; +/// Directory entry struct PACKED EXT2_DIR_ENTRY final { - Kernel::UInt32 fInode; - Kernel::UInt16 fRecordLength; - Kernel::UInt8 fNameLength; - Kernel::UInt8 fFileType; - Kernel::Char - fName[kExt2FSMaxFileNameLen]; // null-terminated, not fixed-length in actual on-disk layout -};
\ No newline at end of file + Kernel::UInt32 fInode; + Kernel::UInt16 fRecordLength; + Kernel::UInt8 fNameLength; + Kernel::UInt8 fFileType; + Kernel::Char fName[kExt2FSMaxFileNameLen]; +}; + +/// VFS usage +struct Ext2Node { + Kernel::UInt32 inodeNumber; + EXT2_INODE inode; + Kernel::UInt32 cursor{0}; +}; + +class Ext2FileSystemMgr; + +} // namespace Ext2 diff --git a/dev/kernel/FSKit/Ext2IFS.h b/dev/kernel/FSKit/Ext2IFS.h new file mode 100644 index 00000000..87095bc6 --- /dev/null +++ b/dev/kernel/FSKit/Ext2IFS.h @@ -0,0 +1,133 @@ +#pragma once + +#include <FSKit/Ext2.h> +#include <KernelKit/DriveMgr.h> +#include <KernelKit/HeapMgr.h> +#include <NeKit/Utils.h> +#include <NeKit/KernelPanic.h> +#include <NeKit/ErrorOr.h> +#include <KernelKit/KPC.h> + +namespace Ext2 { + +/// @brief Context for an EXT2 filesystem on a given drive +struct Context { + Kernel::DriveTrait* drive{nullptr}; + EXT2_SUPER_BLOCK* superblock{nullptr}; + + /// @brief context with a drive + explicit Context(Kernel::DriveTrait* drv) : drive(drv) {} + + /// @brief Clean up + ~Context() { + if (superblock) { + Kernel::mm_free_ptr(superblock); + superblock = nullptr; + } + } + + Context(const Context&) = delete; + Context& operator=(const Context&) = delete; + + Context(Context&& other) noexcept : drive(other.drive), superblock(other.superblock) { + other.drive = nullptr; + other.superblock = nullptr; + } + + Context& operator=(Context&& other) noexcept { + if (this != &other) { + if (superblock) { + Kernel::mm_free_ptr(superblock); + } + drive = other.drive; + superblock = other.superblock; + other.drive = nullptr; + other.superblock = nullptr; + } + return *this; + } + + inline Kernel::UInt32 BlockSize() const { + if (!superblock) return kExt2FSBlockSizeBase; + return kExt2FSBlockSizeBase << superblock->fLogBlockSize; + } +}; + +inline bool ext2_read_block(Kernel::DriveTrait* drv, Kernel::UInt32 lba, void* buffer, Kernel::UInt32 size) { + if (!drv || !buffer) return false; + + Kernel::DriveTrait::DrivePacket pkt{}; + pkt.fPacketContent = buffer; + pkt.fPacketSize = size; + pkt.fPacketLba = lba; + drv->fInput(pkt); + return pkt.fPacketGood; +} + +inline bool ext2_write_block(Kernel::DriveTrait* drv, Kernel::UInt32 lba, const void* buffer, Kernel::UInt32 size) { + if (!drv || !buffer) return false; + + Kernel::DriveTrait::DrivePacket pkt{}; + pkt.fPacketContent = const_cast<void*>(buffer); + pkt.fPacketSize = size; + pkt.fPacketLba = lba; + drv->fOutput(pkt); + return pkt.fPacketGood; +} + +// Load superblock +inline Kernel::ErrorOr<EXT2_SUPER_BLOCK*> ext2_load_superblock(Context* ctx) { + if (!ctx || !ctx->drive) return Kernel::ErrorOr<EXT2_SUPER_BLOCK*>(Kernel::kErrorInvalidData); + + auto buf = Kernel::mm_alloc_ptr(sizeof(EXT2_SUPER_BLOCK), true, false); + if (!buf) return Kernel::ErrorOr<EXT2_SUPER_BLOCK*>(Kernel::kErrorHeapOutOfMemory); + + Kernel::UInt32 blockLba = kExt2FSSuperblockOffset / ctx->drive->fSectorSz; + if (!ext2_read_block(ctx->drive, blockLba, buf, sizeof(EXT2_SUPER_BLOCK))) { + Kernel::mm_free_ptr(buf); + return Kernel::ErrorOr<EXT2_SUPER_BLOCK*>(Kernel::kErrorDisk); + } + + auto sb = reinterpret_cast<EXT2_SUPER_BLOCK*>(buf); + if (sb->fMagic != kExt2FSMagic) { + Kernel::mm_free_ptr(buf); + return Kernel::ErrorOr<EXT2_SUPER_BLOCK*>(Kernel::kErrorInvalidData); + } + + ctx->superblock = sb; + return Kernel::ErrorOr<EXT2_SUPER_BLOCK*>(sb); +} + +// Load inode +inline Kernel::ErrorOr<Ext2Node*> ext2_load_inode(Context* ctx, Kernel::UInt32 inodeNumber) { + if (!ctx || !ctx->superblock) return Kernel::ErrorOr<Ext2Node*>(Kernel::kErrorInvalidData); + + auto nodePtr = Kernel::mm_alloc_ptr(sizeof(Ext2Node), true, false); + if (!nodePtr) return Kernel::ErrorOr<Ext2Node*>(Kernel::kErrorHeapOutOfMemory); + + auto ext2Node = reinterpret_cast<Ext2Node*>(nodePtr); + ext2Node->inodeNumber = inodeNumber; + + // Compute block group and index within group + Kernel::UInt32 inodesPerGroup = ctx->superblock->fInodesPerGroup; + Kernel::UInt32 group = (inodeNumber - 1) / inodesPerGroup; + Kernel::UInt32 index = (inodeNumber - 1) % inodesPerGroup; + + // dummy: just offset first inode + Kernel::UInt32 inodeTableBlock = ctx->superblock->fFirstInode + group; + + if (!ext2_read_block(ctx->drive, inodeTableBlock, &ext2Node->inode, sizeof(EXT2_INODE))) { + Kernel::mm_free_ptr(nodePtr); + return Kernel::ErrorOr<Ext2Node*>(Kernel::kErrorDisk); + } + + ext2Node->cursor = 0; + return Kernel::ErrorOr<Ext2Node*>(ext2Node); +} + +inline Kernel::UInt32 inode_offset(const Context* ctx, Kernel::UInt32 inodeNumber) { + if (!ctx || !ctx->superblock) return 0; + return ((inodeNumber - 1) % ctx->superblock->fInodesPerGroup) * ctx->superblock->fInodeSize; +} + +} // namespace Ext2 diff --git a/dev/kernel/HALKit/ARM64/HalHandoverStub.s b/dev/kernel/HALKit/ARM64/HalHandoverStub.s index 7c70ebfd..c0e7cb2b 100644 --- a/dev/kernel/HALKit/ARM64/HalHandoverStub.s +++ b/dev/kernel/HALKit/ARM64/HalHandoverStub.s @@ -9,11 +9,11 @@ .section .ldr - ;; MAGIC + ;; // MAGIC .quad 0xDAB4 - ;; VERSION (1.0.0) + ;; // VERSION (1.0.0) .word 100 - ;; CPU (ARM64) + ;; // CPU (ARM64) .word 0 - ;; TYPE (KERNEL) + ;; // TYPE (KERNEL) .word 122 |
