diff --git a/sys/victoriafalls/CMakeLists.txt b/sys/victoriafalls/CMakeLists.txt index f62b8d4..47338ea 100644 --- a/sys/victoriafalls/CMakeLists.txt +++ b/sys/victoriafalls/CMakeLists.txt @@ -1,4 +1,5 @@ add_executable(victoriafalls + fs/ext2/ext2_driver.cpp victoriafalls.cpp) target_include_directories(victoriafalls diff --git a/sys/victoriafalls/fs/ext2/ext2.h b/sys/victoriafalls/fs/ext2/ext2.h new file mode 100644 index 0000000..3e6fac4 --- /dev/null +++ b/sys/victoriafalls/fs/ext2/ext2.h @@ -0,0 +1,62 @@ +#pragma once + +#include + +struct Superblock { + uint32_t inodes_count; + uint32_t blocks_count; + uint32_t reserved_blocks_count; + uint32_t free_blocks_count; + uint32_t free_inodes_count; + uint32_t first_data_blok; + uint32_t log_block_size; + uint32_t log_frag_size; + uint32_t blocks_per_group; + uint32_t frags_per_group; + uint32_t inodes_per_group; + uint32_t mtime; + uint32_t wtime; + uint16_t mnt_count; + uint16_t max_mnt_count; + uint16_t magic; + uint16_t state; + uint16_t errors; + uint16_t minor_rev_level; + uint32_t lastcheck; + uint32_t checkinterval; + uint32_t creator_os; + uint32_t rev_level; + uint16_t def_resuid; + uint16_t def_resgid; +} __attribute__((__packed__)); + +struct BlockGroupDescriptor { + uint32_t block_bitmap; + uint32_t inode_bitmap; + uint32_t inode_table; + uint16_t free_blocks_count; + uint16_t free_inodes_count; + uint16_t used_dirs_count; + uint8_t reserved[14]; +} __attribute__((__packed__)); + +struct Inode { + uint16_t mode; + uint16_t uid; + uint32_t size; + uint32_t atime; + uint32_t ctime; + uint32_t mtime; + uint32_t dtime; + uint16_t gid; + uint16_t links_count; + uint32_t blocks; + uint32_t flags; + uint32_t osd1; + uint32_t block[15]; + uint32_t generation; + uint32_t file_acl; + uint32_t dir_acl; + uint32_t faddr; + uint32_t osd2[3]; +} __attribute__((__packed__)); diff --git a/sys/victoriafalls/fs/ext2/ext2_driver.cpp b/sys/victoriafalls/fs/ext2/ext2_driver.cpp new file mode 100644 index 0000000..45500a5 --- /dev/null +++ b/sys/victoriafalls/fs/ext2/ext2_driver.cpp @@ -0,0 +1,50 @@ +#include "fs/ext2/ext2_driver.h" + +#include + +glcr::ErrorCode Ext2Driver::ProbePartition() { + // Read 1024 bytes from 1024 offset. + // FIXME: Don't assume 512 byte sectors somehow. + ASSIGN_OR_RETURN(MappedMemoryRegion superblock, denali_.ReadSectors(2, 2)); + superblock_ = reinterpret_cast(superblock.vaddr()); + + if (superblock_->magic != 0xEF53) { + dbgln("Invalid EXT2 magic code: %x"); + return glcr::INVALID_ARGUMENT; + } + dbgln("Block size: 0x%x", 1024 << superblock_->log_block_size); + + dbgln("Blocks: 0x%x (0x%x per group)", superblock_->blocks_count, + superblock_->blocks_per_group); + dbgln("Inodes: 0x%x (0x%x per group)", superblock_->inodes_count, + superblock_->inodes_per_group); + + dbgln("Mounts: 0x%x out of 0x%x", superblock_->mnt_count, + superblock_->max_mnt_count); + dbgln("State: %x", superblock_->state); + + dbgln("Created by: %x", superblock_->creator_os); + + uint64_t num_block_groups = + superblock_->blocks_count / superblock_->blocks_per_group; + dbgln("\nReading %u blocks groups", num_block_groups); + uint64_t bgdt_bytes = sizeof(BlockGroupDescriptor) * num_block_groups; + uint64_t bgdt_block = (superblock_->log_block_size == 0) ? 2 : 1; + ASSIGN_OR_RETURN(MappedMemoryRegion bgdt, + ReadBlocks(bgdt_block, BytesToBlockCount(bgdt_bytes))); + + BlockGroupDescriptor* bgds = + reinterpret_cast(bgdt.vaddr()); + + for (uint64_t i = 0; i < num_block_groups; i++) { + dbgln("BGD %x", i); + dbgln("Block Bitmap: %x", bgds[i].block_bitmap); + dbgln("Inode Bitmap: %x", bgds[i].inode_bitmap); + dbgln("Inode Table: %x", bgds[i].inode_table); + dbgln("Free blocks: %x", bgds[i].free_blocks_count); + dbgln("Free inodes: %x", bgds[i].free_inodes_count); + } + + uint64_t root_inode = 2; + return glcr::OK; +} diff --git a/sys/victoriafalls/fs/ext2/ext2_driver.h b/sys/victoriafalls/fs/ext2/ext2_driver.h new file mode 100644 index 0000000..8426638 --- /dev/null +++ b/sys/victoriafalls/fs/ext2/ext2_driver.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include + +#include "fs/ext2/ext2.h" + +class Ext2Driver { + public: + Ext2Driver(ScopedDenaliClient&& denali) : denali_(glcr::Move(denali)) {} + + glcr::ErrorCode ProbePartition(); + + glcr::ErrorOr ReadBlocks(uint64_t block_num, + uint64_t num_blocks) { + return denali_.ReadSectors(SectorsPerBlock() * block_num, + SectorsPerBlock() * num_blocks); + } + + uint64_t SectorsPerBlock() { return 1 << (superblock_->log_block_size + 1); } + uint64_t BlockToLba(uint64_t block) { return block * SectorsPerBlock(); } + uint64_t BytesToBlockCount(uint64_t bytes) { + return (bytes - 1) / (1024 << superblock_->log_block_size) + 1; + } + + private: + ScopedDenaliClient denali_; + Superblock* superblock_; +}; diff --git a/sys/victoriafalls/victoriafalls.cpp b/sys/victoriafalls/victoriafalls.cpp index 2e4b87d..b89d49b 100644 --- a/sys/victoriafalls/victoriafalls.cpp +++ b/sys/victoriafalls/victoriafalls.cpp @@ -2,13 +2,7 @@ #include #include -struct Superblock { - uint32_t inode_count; - uint32_t blocks_count; - uint32_t reserved_blocks_count; - uint32_t free_blocks_count; - uint32_t free_inodes_count; -}; +#include "fs/ext2/ext2_driver.h" uint64_t main(uint64_t init_cap) { ParseInitPort(init_cap); @@ -17,12 +11,9 @@ uint64_t main(uint64_t init_cap) { YellowstoneStub yellowstone(gInitEndpointCap); ASSIGN_OR_RETURN(ScopedDenaliClient denali, yellowstone.GetDenali()); + Ext2Driver ext2(glcr::Move(denali)); - ASSIGN_OR_RETURN(MappedMemoryRegion region, denali.ReadSectors(2, 2)); - Superblock* super = reinterpret_cast(region.vaddr()); - - dbgln("Inodes: %x / %x", super->free_inodes_count, super->inode_count); - dbgln("Blocks: %x / %x", super->free_blocks_count, super->blocks_count); + check(ext2.ProbePartition()); return 0; }