diff --git a/kernel/block/ramdisk.c b/kernel/block/ramdisk.c index 0ead280..73b2da3 100644 --- a/kernel/block/ramdisk.c +++ b/kernel/block/ramdisk.c @@ -80,7 +80,7 @@ int ramdisk_block_read(minor_t minor, u32_t blockNum, u32_t count, void *buffer) if ((blockNum << BLOCK_SIZE_LOG) >= ramdisks[minor]->size) return -2; void *rdAddr = ramdisks[minor]->start + (blockNum << BLOCK_SIZE_LOG); - u32_t copyLen = min(count << BLOCK_SIZE_LOG, ramdisks[minor]->size - (u32_t)rdAddr); + u32_t copyLen = min(count << BLOCK_SIZE_LOG, ramdisks[minor]->size + (u32_t)ramdisks[minor]->start - (u32_t)rdAddr); memcpyd(buffer, rdAddr, copyLen >> 2); return copyLen; } @@ -92,7 +92,7 @@ int ramdisk_block_write(minor_t minor, u32_t blockNum, u32_t count, void *buffer if ((blockNum << BLOCK_SIZE_LOG) >= ramdisks[minor]->size) return -2; void *rdAddr = ramdisks[minor]->start + (blockNum << BLOCK_SIZE_LOG); - u32_t copyLen = min(count << BLOCK_SIZE_LOG, ramdisks[minor]->size - (u32_t)rdAddr); + u32_t copyLen = min(count << BLOCK_SIZE_LOG, ramdisks[minor]->size + (u32_t)ramdisks[minor]->start - (u32_t)rdAddr); memcpyd(rdAddr, buffer, copyLen >> 2); return copyLen; } diff --git a/kernel/fs/devfs.c b/kernel/fs/devfs.c index 07b4922..56aa6ac 100644 --- a/kernel/fs/devfs.c +++ b/kernel/fs/devfs.c @@ -11,12 +11,7 @@ int devfs_init() { - minor_t devfs_minor = ramdisk_new(DEVFS_SIZE); - if (devfs_minor < 0) - return -1; -// ext2_mkfs(MAJORB_RAMDISK, devfs_minor); -// vfs_mount(MAJORB_RAMDISK, rd_minor, FS_EXT2, "/dev"); -// mknod(MAJORB_RAMDISK, initrd_minor, 0600, "/dev/rd0"); + return 0; } diff --git a/kernel/fs/devfs.h b/kernel/fs/devfs.h index b1f4b33..8ed721e 100644 --- a/kernel/fs/devfs.h +++ b/kernel/fs/devfs.h @@ -9,8 +9,6 @@ #include "hos_defines.h" #include "fs/devices.h" -#define DEVFS_SIZE 102400 - int devfs_init(); #endif diff --git a/kernel/fs/ext2.c b/kernel/fs/ext2.c index b0c8754..3dbf358 100644 --- a/kernel/fs/ext2.c +++ b/kernel/fs/ext2.c @@ -1,7 +1,7 @@ // ext2.c // Author: Josh Holtrop // Date: 08/22/04 -// Modified: 08/22/04 +// Modified: 12/24/04 #include "hos_defines.h" #include "fs/devices.h" @@ -10,6 +10,7 @@ #include "mm/vmm.h" #include "fs/vfs.h" #include "lang/asmfuncs.h" +#include "functions.h" /* Turning an inode number into a (group, inode_index) pair: * group = (inode - 1) / s_inodes_per_group @@ -17,14 +18,16 @@ */ +// initialize the filesystem driver int ext2_init(int fsID) { vfs_fs_t *fs; - if (( fs = New(vfs_fs_t) )) + if (( fs = New(vfs_fs_t) )) // give the VFS system our FS structure { fs->mount_super = ext2_mount_super; fs->umount_super = ext2_umount_super; fs->mkfs = ext2_mkfs; + fs->stat = ext2_stat; vfs_register_fs(fsID, fs); return 0; } @@ -32,13 +35,14 @@ int ext2_init(int fsID) } +// create an ext2 filesystem on the given device int ext2_mkfs(major_t major, minor_t minor) { return 0; } -// read the superblock of the filesystem and return a pointer to it +// mount the superblock of the filesystem and return a pointer to it, if valid void *ext2_mount_super(major_t major, minor_t minor) { ext2_super_block_t *super = kmalloc(1024); @@ -51,25 +55,61 @@ void *ext2_mount_super(major_t major, minor_t minor) 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); -} - +// stat a file, return a structure of info about it int ext2_stat(vfs_mount_t *mount, char *file, vfs_stat_t *stat) { - if (file[0] != '/') + u32_t inode_number = ext2_get_inode_number(mount, file); + if (!inode_number) return -1; - char *fil = kmalloc(strlen(file) + 1); - strcpy(fil, file); - // TODO: stat the file :) - kfree(fil); + ext2_inode_t inode = ext2_get_inode(mount, inode_number); + + switch(inode.i_mode & EXT2_I_MODE_TYPE_MASK) + { + case EXT2_I_MODE_FIFO: stat->type = VFS_FT_FIFO; + case EXT2_I_MODE_CHAR: stat->type = VFS_FT_CHAR; + case EXT2_I_MODE_DIR: stat->type = VFS_FT_DIR; + case EXT2_I_MODE_BLOCK: stat->type = VFS_FT_BLOCK; + case EXT2_I_MODE_FILE: stat->type = VFS_FT_FILE; + case EXT2_I_MODE_SYM: stat->type = VFS_FT_SYMLINK; + case EXT2_I_MODE_SOCK: stat->type = VFS_FT_SOCK; + default: stat->type = VFS_FT_UNKNOWN; + } + stat->size = inode.i_size; + stat->inode = inode_number; + stat->permissions = inode.i_mode & EXT2_I_MODE_ATTR_MASK; + stat->uid = inode.i_uid; + stat->gid = inode.i_gid; + stat->atime = inode.i_atime; + stat->mtime = inode.i_mtime; + stat->ctime = inode.i_ctime; + stat->links = inode.i_links_count; + return 0; } +// returns the inode number that the given file name points to +u32_t ext2_get_inode_number(vfs_mount_t *mount, char *file) +{ + if (file[0] != '/') + return 0; + int length = strlen(file); + if (length == 1) + return 2; + char *fil = kmalloc(length + 1); + strcpy(fil, file); + if (fil[length-1] == '/') + { + length--; + fil[length] = 0; + } + u32_t inode_number = 0; + // TODO: get inode number + + kfree(fil); + return inode_number; +} + +// open an inode for reading 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); @@ -78,19 +118,36 @@ ext2_open_inode_t *ext2_open_inode(vfs_mount_t *mount, u32_t inode_number) open_inode->block = 0; open_inode->block_pointers = NULL; open_inode->block_pointers_start = 0; + mount->refs++; return open_inode; } +// seek to a certain block of an open inode +int ext2_inode_seek(ext2_open_inode_t *open_inode, u32_t block_number) +{ + if (open_inode->inode.i_size <= (block_number << (10 + super->s_log_block_size))) + return -1; // at or past EOF + open_inode->block = block_number; + return 0; +} + +// returns number of bytes read 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 + if (open_inode->inode.i_size <= (open_inode->block << (10 + super->s_log_block_size))) + return 0; // at or past EOF + u32_t leftover_bytes = open_inode->inode.i_size - (open_inode->block << (10 + super->s_log_block_size)); + u32_t block_number = ext2_block_number(mount, open_inode); + block_read(mount->major, mount->minor, ext2_FSToDiskBlock(block_number, super), + 2 << super->s_log_block_size, block); + open_inode->block++; + return min(leftover_bytes, 1024 << super->s_log_block_size); } // transform open_inode->block (a relative block number) to an absolute block number for the filesystem u32_t ext2_block_number(vfs_mount_t *mount, ext2_open_inode_t *open_inode) { - // TODO: convert block_index to block number using open_inode fields if (open_inode->block < 12) return open_inode->inode.i_block[open_inode->block]; ext2_super_block_t *super = mount->super; @@ -105,7 +162,7 @@ u32_t ext2_block_number(vfs_mount_t *mount, ext2_open_inode_t *open_inode) if (rel_block < pointersPerBlock) // indirect block in i_block[12] { block_read(mount->major, mount->minor, ext2_FSToDiskBlock(open_inode->inode.i_block[12], super), - 1 << super->s_log_block_size, open_inode->block_pointers); + 2 << super->s_log_block_size, open_inode->block_pointers); open_inode->block_pointers_start = 12; return open_inode->block_pointers[rel_block]; } @@ -113,47 +170,42 @@ u32_t ext2_block_number(vfs_mount_t *mount, ext2_open_inode_t *open_inode) if (rel_block < (pointersPerBlock * pointersPerBlock)) // double-indirect block in i_block[13] { block_read(mount->major, mount->minor, ext2_FSToDiskBlock(open_inode->inode.i_block[13], super), - 1 << super->s_log_block_size, open_inode->block_pointers); + 2 << super->s_log_block_size, open_inode->block_pointers); u32_t real_block = open_inode->block_pointers[rel_block / pointersPerBlock]; block_read(mount->major, mount->minor, ext2_FSToDiskBlock(real_block, super), - 1 << super->s_log_block_size, open_inode->block_pointers); + 2 << super->s_log_block_size, open_inode->block_pointers); open_inode->block_pointers_start = 12 + pointersPerBlock + rel_block - (rel_block % pointersPerBlock); return open_inode->block_pointers[rel_block % pointersPerBlock]; } + // this code shouldn't run unless we are dealing with a 65+mb file ... rel_block -= pointersPerBlock * pointersPerBlock; - // TODO: triple-indirect block in i_block[14] block_read(mount->major, mount->minor, ext2_FSToDiskBlock(open_inode->inode.i_block[14], super), - 1 << super->s_log_block_size, open_inode->block_pointers); - u32_t block_1 = open_inode->block_pointers[rel_block / (pointersPerBlock * pointersPerBlock)]; + 2 << super->s_log_block_size, open_inode->block_pointers); + u32_t index_1 = rel_block / (pointersPerBlock * pointersPerBlock); + u32_t leftover_1 = rel_block % (pointersPerBlock * pointersPerBlock); + u32_t block_1 = open_inode->block_pointers[index_1]; block_read(mount->major, mount->minor, ext2_FSToDiskBlock(block_1, super), - 1 << super->s_log_block_size, open_inode->block_pointers); - u32_t block_2 = open_inode->block_pointers[rel_block / (pointersPerBlock * pointersPerBlock)]; - block_read(mount->major, mount->minor, ext2_FSToDiskBlock(block_1, super), - 1 << super->s_log_block_size, open_inode->block_pointers); - open_inode->block_pointers_start = 12 + pointersPerBlock + rel_block - (rel_block % pointersPerBlock); - return open_inode->block_pointers[rel_block % pointersPerBlock]; + 2 << super->s_log_block_size, open_inode->block_pointers); + u32_t index_2 = leftover_1 / pointersPerBlock; + u32_t leftover_2 = leftover_1 % pointersPerBlock; + u32_t block_2 = open_inode->block_pointers[index_2]; + block_read(mount->major, mount->minor, ext2_FSToDiskBlock(block_2, super), + 2 << super->s_log_block_size, open_inode->block_pointers); + open_inode->block_pointers_start = 12 + (pointersPerBlock + 1) * pointersPerBlock + rel_block - (rel_block % pointersPerBlock); + return open_inode->block_pointers[leftover_2]; } +// close an open inode int ext2_close_inode(vfs_mount_t *mount, ext2_open_inode_t *open_inode) { + mount->refs--; if (open_inode->block_pointers) - kfree(open_inode->block_pointers); + kfree(open_inode->block_pointers); // free the block pointers cache 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); -} - +// read the inode structure from the device and return it ext2_inode_t ext2_get_inode(vfs_mount_t *mount, u32_t inode) { ext2_super_block_t *super = mount->super; @@ -169,6 +221,7 @@ ext2_inode_t ext2_get_inode(vfs_mount_t *mount, u32_t inode) return in; } +// read the group descriptor structure from the device and return it ext2_group_desc_t ext2_get_group_desc(vfs_mount_t *mount, u32_t group) { ext2_super_block_t *super = mount->super; @@ -180,8 +233,9 @@ ext2_group_desc_t ext2_get_group_desc(vfs_mount_t *mount, u32_t group) return gd; } +// called when we are unmounting this filesystem mount int ext2_umount_super(vfs_mount_t *mount) { - return kfree(mount->super); + return kfree(mount->super); // free memory that the superblock was taking } diff --git a/kernel/fs/ext2.h b/kernel/fs/ext2.h index e98d267..ccbcf64 100644 --- a/kernel/fs/ext2.h +++ b/kernel/fs/ext2.h @@ -1,7 +1,7 @@ // ext2.h // Author: Josh Holtrop // Date: 08/22/04 -// Modified: 08/22/04 +// Modified: 12/24/04 #ifndef __HOS_EXT2_H__ #define __HOS_EXT2_H__ __HOS_EXT2_H__ @@ -13,6 +13,7 @@ #define EXT2_MAGIC 0xEF53 #define EXT2_NAME_LEN 255 +#define EXT2_I_MODE_ATTR_MASK 0x0FFF #define EXT2_I_MODE_OX 0x0001 #define EXT2_I_MODE_OW 0x0002 #define EXT2_I_MODE_OR 0x0004 @@ -118,7 +119,7 @@ typedef struct u32_t i_flags; // File flags u32_t i_reserved1; u32_t i_block[15]; // Pointers to file blocks - u32_t i_version; // File version (NFS?) + u32_t i_version; // File version (for NFS) u32_t i_file_acl; // File ACL u32_t i_dir_acl; // Directory ACL u32_t i_faddr; // Fragment address @@ -145,22 +146,33 @@ typedef struct u32_t block_pointers_start; } ext2_open_inode_t; + +static 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); +} + +static 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); +} + + int ext2_init(int fsID); void *ext2_mount_super(major_t major, minor_t minor); int ext2_umount_super(vfs_mount_t *mount); int ext2_mkfs(major_t major, minor_t minor); ext2_inode_t ext2_get_inode(vfs_mount_t *mount, u32_t inode); ext2_group_desc_t ext2_get_group_desc(vfs_mount_t *mount, u32_t group); -inline u32_t ext2_diskToFSBlock(u32_t block, ext2_super_block_t *super); -inline u32_t ext2_FSToDiskBlock(u32_t block, ext2_super_block_t *super); int ext2_stat(vfs_mount_t *mount, char *file, vfs_stat_t *stat); ext2_open_inode_t *ext2_open_inode(vfs_mount_t *mount, u32_t inode_number); int ext2_close_inode(vfs_mount_t *mount, ext2_open_inode_t *open_inode); int ext2_read_inode_block(vfs_mount_t *mount, ext2_open_inode_t *open_inode, void *block); u32_t ext2_block_number(vfs_mount_t *mount, ext2_open_inode_t *open_inode); - - -void ext2_dump_root(vfs_mount_t *mount); +u32_t ext2_get_inode_number(vfs_mount_t *mount, char *file); +int ext2_inode_seek(ext2_open_inode_t *open_inode, u32_t block_number); #endif diff --git a/kernel/fs/vfs.h b/kernel/fs/vfs.h index 620efa4..4289e24 100644 --- a/kernel/fs/vfs.h +++ b/kernel/fs/vfs.h @@ -32,14 +32,6 @@ typedef struct minor_t minor; } vfs_mount_t; -/* Every filesystem must provide pointers to its respective functions in a structure like this */ -typedef struct -{ - void *(*mount_super)(major_t major, minor_t minor); - int (*umount_super)(vfs_mount_t *mount); - int (*mkfs)(major_t major, minor_t minor); -} vfs_fs_t; - /* This structure represents a node of the "VFS Mount Tree" */ struct vfs_node_s { @@ -76,6 +68,15 @@ typedef struct u16_t links; } vfs_stat_t; +/* Every filesystem must provide pointers to its respective functions in a structure like this */ +typedef struct +{ + void *(*mount_super)(major_t major, minor_t minor); + int (*umount_super)(vfs_mount_t *mount); + int (*mkfs)(major_t major, minor_t minor); + int (*stat)(vfs_mount_t *mount, char *file, vfs_stat_t *stat); +} vfs_fs_t; + int vfs_init(); int vfs_mount(major_t maj, minor_t min, int fsType, char *mountPoint); diff --git a/kernel/functions.h b/kernel/functions.h index 4166039..0f94a4c 100644 --- a/kernel/functions.h +++ b/kernel/functions.h @@ -91,13 +91,13 @@ static inline byte byte2bcd(byte bite) // get the maximum of two values static inline u32_t max(u32_t v1, u32_t v2) { - return ( (v2 > v1) ? v2 : v1 ); + return ( (v2 > v1) ? v2 : v1 ); } // get the minimum of two values static inline u32_t min(u32_t v1, u32_t v2) { - return ( (v2 > v1) ? v1 : v2 ); + return ( (v2 > v1) ? v1 : v2 ); } #endif diff --git a/kernel/kernel.c b/kernel/kernel.c index 44447ea..adc3f14 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -97,7 +97,6 @@ mb_module_t *k_mbsave(mb_info_t *mbinfo, unsigned int mb_magic) return real_mode_module; } - /* Main kernel initialization routine */ void k_init() { @@ -127,8 +126,8 @@ void k_init() for (i = 0; i < mb_info_block.mods_count; i++) { kprintf("Loaded kernel module %d: 0x%x - 0x%x (%d bytes)\n", i, mb_modules[i].mod_start, mb_modules[i].mod_end, mb_modules[i].mod_end - mb_modules[i].mod_start); - if (((mb_modules[i].mod_end - mb_modules[i].mod_start) > 0x43A) && - (*(u16_t *)(mb_modules[i].mod_start + 0x438) == EXT2_MAGIC)) + if (((mb_modules[i].mod_end - mb_modules[i].mod_start) > 1024) && + ((ext2_super_block_t *)(mb_modules[i].mod_start + 1024))->s_magic == EXT2_MAGIC) { // we found an initrd minor_t initrd_minor = ramdisk_register((void *)mb_modules[i].mod_start, mb_modules[i].mod_end - mb_modules[i].mod_start);