// ext2.c // Author: Josh Holtrop // Date: 08/22/04 // Modified: 08/22/04 #include "hos_defines.h" #include "fs/devices.h" #include "kout.h" #include "ext2.h" #include "mm/vmm.h" #include "fs/vfs.h" #include "lang/asmfuncs.h" /* Turning an inode number into a (group, inode_index) pair: * group = (inode - 1) / s_inodes_per_group * index = (inode - 1) % s_inodes_per_group */ int ext2_init(int fsID) { vfs_fs_t *fs; if (( fs = New(vfs_fs_t) )) { fs->mount_super = ext2_mount_super; fs->umount_super = ext2_umount_super; fs->mkfs = ext2_mkfs; vfs_register_fs(fsID, fs); return 0; } return -1; } int ext2_mkfs(major_t major, minor_t minor) { return 0; } // read the superblock of the filesystem and return a pointer to it void *ext2_mount_super(major_t major, minor_t minor) { ext2_super_block_t *super = kmalloc(1024); block_read(major, minor, 2, 2, super); if (super->s_magic != EXT2_MAGIC) // not an ext2 filesystem { kfree(super); return NULL; } return super; } void ext2_dump_root(vfs_mount_t *mount) { ext2_inode_t inode_root = ext2_get_inode(mount, 2); kprintf("root dir i_mode: 0x%x, i_size: %d, i_links_count: %d, i_blocks: %d, i_uid: %d, i_gid: %d, i_flags: 0x%x\n", inode_root.i_mode, inode_root.i_size, inode_root.i_links_count, inode_root.i_blocks, inode_root.i_uid, inode_root.i_gid, inode_root.i_flags); ext2_super_block_t *super = mount->super; kprintf("s_def_resuid: %d, s_def_resgid: %d\n", super->s_def_resuid, super->s_def_resgid); } int ext2_stat(vfs_mount_t *mount, char *file, vfs_stat_t *stat) { if (file[0] != '/') return -1; char *fil = kmalloc(strlen(file) + 1); strcpy(fil, file); // TODO: stat the file :) kfree(fil); return 0; } ext2_open_inode_t *ext2_open_inode(vfs_mount_t *mount, u32_t inode_number) { ext2_inode_t inode = ext2_get_inode(mount, inode_number); ext2_open_inode_t *open_inode = New(ext2_open_inode_t); open_inode->inode = inode; open_inode->block = 0; open_inode->block_pointers = NULL; open_inode->block_pointers_start = 0; return open_inode; } int ext2_read_inode_block(vfs_mount_t *mount, ext2_open_inode_t *open_inode, void *block) { ext2_super_block_t *super = mount->super; // TODO: get the block number, read it to block } // block_index is a relative block number - the block number of the file // this needs to be transformed into an absolute block number for the entire disk u32_t ext2_block_number(vfs_mount_t *mount, ext2_open_inode_t *open_inode, u32_t block_index) { // TODO: convert block_index to block number using open_inode fields return 0; } int ext2_close_inode(vfs_mount_t *mount, ext2_open_inode_t *open_inode) { if (open_inode->block_pointers) kfree(open_inode->block_pointers); kfree(open_inode); return 0; } inline u32_t ext2_diskToFSBlock(u32_t block, ext2_super_block_t *super) { // convert # of disk blocks to # of filesystem blocks return block >> (super->s_log_block_size + 1); } inline u32_t ext2_FSToDiskBlock(u32_t block, ext2_super_block_t *super) { // convert # of filesystem blocks to # of disk blocks return block << (super->s_log_block_size + 1); } ext2_inode_t ext2_get_inode(vfs_mount_t *mount, u32_t inode) { ext2_super_block_t *super = mount->super; inode--; // turn inode into a 0-based index u32_t group = inode / super->s_inodes_per_group; u32_t index = inode % super->s_inodes_per_group; u32_t inodeAddr = (ext2_get_group_desc(mount, group).bg_inode_table << (10 + super->s_log_block_size)) + (index << 7); void *block = kmalloc(512); block_read(mount->major, mount->minor, inodeAddr >> 9, 1, block); ext2_inode_t in = *(ext2_inode_t *)(block + (inodeAddr & 0x1FF)); kfree(block); return in; } ext2_group_desc_t ext2_get_group_desc(vfs_mount_t *mount, u32_t group) { ext2_super_block_t *super = mount->super; u32_t groupDescAddr = ((1 + super->s_first_data_block) << (10 + super->s_log_block_size)) + (group << 5); void *block = kmalloc(512); block_read(mount->major, mount->minor, groupDescAddr >> 9, 1, block); ext2_group_desc_t gd = *(ext2_group_desc_t *)(block + (groupDescAddr & 0x1FF)); kfree(block); return gd; } int ext2_umount_super(vfs_mount_t *mount) { return kfree(mount->super); }