diff --git a/build.txt b/build.txt index dc1841a..ab28aad 100644 --- a/build.txt +++ b/build.txt @@ -1,2 +1,2 @@ To build the HOS kernel, just run 'make' -To build a HOS floppy image for bochs, run 'make initrd' and 'make install_img' as root (root permissions needed to mount floppy image) +To build a HOS floppy image for bochs, run 'make initrd' and 'make install_img'. You will need root permissions to mount the ext2 image. This can be accomplished my setting the MOUNT variable to "sudo mount" in the Makefile or by running the last two mount commands as root. diff --git a/kernel/fs/FileSystem.cpp b/kernel/fs/FileSystem.cpp index 67e961c..3ee0170 100644 --- a/kernel/fs/FileSystem.cpp +++ b/kernel/fs/FileSystem.cpp @@ -7,7 +7,7 @@ #include "FileSystem.h" #include "hos_defines.h" -FileSystem::FileSystem() {myError = -10278;} +FileSystem::FileSystem() {} FileSystem::~FileSystem() {} u32_t FileSystem::totalBlocks(){return 0;} u32_t FileSystem::usedBlocks(){return 0;}; @@ -16,4 +16,3 @@ u32_t FileSystem::totalInodes(){return 0;}; u32_t FileSystem::usedInodes(){return 0;}; u32_t FileSystem::freeInodes(){return 0;}; u32_t FileSystem::getRootInodeNumber(){return 0;}; -int FileSystem::check(){return myError;}; diff --git a/kernel/fs/FileSystem.h b/kernel/fs/FileSystem.h index 0b1fdf9..e5de9f3 100644 --- a/kernel/fs/FileSystem.h +++ b/kernel/fs/FileSystem.h @@ -12,12 +12,8 @@ class FileSystem { -protected: - int myError; - device_t myDevice; public: FileSystem(); - FileSystem(device_t dev); virtual ~FileSystem(); virtual u32_t totalBlocks(); /* 512 byte blocks */ @@ -29,8 +25,6 @@ public: virtual u32_t freeInodes(); virtual u32_t getRootInodeNumber(); - - virtual int check(); }; #endif diff --git a/kernel/fs/ext2/ext2.cpp b/kernel/fs/ext2/ext2.cpp index 35d8260..78d791d 100644 --- a/kernel/fs/ext2/ext2.cpp +++ b/kernel/fs/ext2/ext2.cpp @@ -8,26 +8,45 @@ extern "C" { #include "display/kout.h" +#include "mm/vmm.h" +#include "lang/lang.h" } #include "ext2.h" -Ext2fs::Ext2fs(device_t dev) +int ext2_init() +{ + vfs_register("ext2", ext2__mount_func); + return 0; +} + +FileSystem *ext2__mount_func(device_t dev) +{ + ext2_super_block_t *super = + (ext2_super_block_t *) New(ext2_super_block_t); + if ( (block_read(DEV_MAJOR(dev), DEV_MINOR(dev), 2, 2, super) < 1024) + || (super->s_magic != EXT2_MAGIC) ) + { + kfree(super); + return NULL; + } + Ext2fs *fs = new Ext2fs(super, dev); + kfree(super); + return fs; +} + +Ext2fs::Ext2fs(ext2_super_block_t *super, device_t dev) { myDevice = dev; - if (block_read(DEV_MAJOR(dev), DEV_MINOR(dev), 2, 2, &mySuper) < 1024) - { - myError = -1; - return; - } - if (mySuper.s_magic != EXT2_MAGIC) - { - myError = -2; - return; - } - myError = 0; + memcpy(&mySuper, super, sizeof(ext2_super_block_t)); mySuperDirty = 0; - kprintf("Device: %d\n", myDevice); + kprintf("Blocks: %d (%d free), Inodes: %d (%d free) Creator OS:\n", + mySuper.s_blocks_count, + mySuper.s_free_blocks_count, + mySuper.s_inodes_count, + mySuper.s_free_inodes_count, + mySuper.s_creator_os); + } Ext2fs::~Ext2fs() diff --git a/kernel/fs/ext2/ext2.h b/kernel/fs/ext2/ext2.h index 184a4e5..bc36640 100644 --- a/kernel/fs/ext2/ext2.h +++ b/kernel/fs/ext2/ext2.h @@ -41,6 +41,7 @@ #define EXT2_I_FLAGS_APPEND 0x20 #define EXT2_I_FLAGS_NODUMP 0x40 +/* ext2 standard inode numbers */ #define EXT2_INODE_BAD_BLOCKS 1 #define EXT2_INODE_ROOT 2 #define EXT2_INODE_ACL_INDEX 3 @@ -49,15 +50,16 @@ #define EXT2_INODE_UNDELETE_DIR 6 #define EXT2_INODE_AVAIL 11 -#define EXT2_FT_UNKNOWN 0 -#define EXT2_FT_FILE 1 -#define EXT2_FT_DIR 2 -#define EXT2_FT_CHAR 3 -#define EXT2_FT_BLOCK 4 -#define EXT2_FT_FIFO 5 -#define EXT2_FT_SOCK 6 -#define EXT2_FT_SYMLINK 7 -#define EXT2_FT_MAX 8 +/* The directory entry file type field values */ +#define EXT2_FT_UNKNOWN 0 +#define EXT2_FT_FILE 1 +#define EXT2_FT_DIR 2 +#define EXT2_FT_CHAR 3 +#define EXT2_FT_BLOCK 4 +#define EXT2_FT_FIFO 5 +#define EXT2_FT_SOCK 6 +#define EXT2_FT_SYMLINK 7 +#define EXT2_FT_MAX 8 #include "fs/vfs.h" @@ -140,13 +142,17 @@ typedef struct #ifdef _HOS_CPP_ +int ext2_init(); +FileSystem *ext2__mount_func(device_t dev); + class Ext2fs : public FileSystem { protected: + device_t myDevice; + int mySuperDirty; ext2_super_block_t mySuper; - int mySuperDirty; public: - Ext2fs(device_t dev); + Ext2fs(ext2_super_block_t *super, device_t dev); ~Ext2fs(); }; diff --git a/kernel/fs/vfs.cpp b/kernel/fs/vfs.cpp index 8407827..1611894 100644 --- a/kernel/fs/vfs.cpp +++ b/kernel/fs/vfs.cpp @@ -21,16 +21,32 @@ extern "C" { inode_num_t rootInode; vector *mountPoints; +vector *fses; int vfs_init() { mountPoints = new vector; + fses = new vector; + ext2_init(); return 0; } -int vfs_mount(device_t device, int fsType, char *mountPoint) +int vfs_register(char *fs, FileSystem *(*mount_func)(device_t)) +{ + string fsName(fs); + if (vfs_get_mount_func(fsName)) + return -1; + FSHandle fsh = {fsName, mount_func}; + fses->add(fsh); + return 0; +} + +int vfs_mount(device_t device, char *fsType, char *mountPoint) { string mountPt(mountPoint); + string fsName(fsType); + if (!vfs_get_mount_func(fsName)) + return -501; if (mountPt == "/") { if (mountPoints->size()) @@ -47,27 +63,26 @@ int vfs_mount(device_t device, int fsType, char *mountPoint) } else { - + // TODO: mount a second filesystem } return 500; } -FileSystem *vfs_attempt_mount(device_t device, int fsType) +FileSystem *vfs_attempt_mount(device_t device, char *fsType) { - FileSystem *fs; - switch (fsType) - { - case FS_EXT2: - fs = new Ext2fs(device); - break; - default: + mount_func_t mount_func; + if (( mount_func = vfs_get_mount_func(string(fsType)) )) + return mount_func(device); + else return NULL; - } - if (fs->check()) - { - delete fs; - return NULL; - } - return fs; } +mount_func_t vfs_get_mount_func(const string & fsName) +{ + for (unsigned int i = 0; i < fses->size(); i++) + { + if (fsName == (*fses)[i].name) + return (*fses)[i].mount_func; + } + return NULL; +} diff --git a/kernel/fs/vfs.h b/kernel/fs/vfs.h index 1b52c37..65c567c 100644 --- a/kernel/fs/vfs.h +++ b/kernel/fs/vfs.h @@ -7,9 +7,6 @@ #ifndef __HOS_VFS_H__ #define __HOS_VFS_H__ __HOS_VFS_H__ -#define FS_EXT2 1 -#define FS_MAX 5 - #define VFS_FT_UNKNOWN 0 #define VFS_FT_FILE 1 #define VFS_FT_DIR 2 @@ -37,14 +34,14 @@ #include "hos_defines.h" #include "devices.h" +typedef u64_t inode_num_t; + #ifdef _HOS_CPP_ extern "C" { #endif -typedef u64_t inode_num_t; - int vfs_init(); -int vfs_mount(device_t device, int fsType, char *mountPoint); +int vfs_mount(device_t device, char *fsType, char *mountPoint); #ifdef _HOS_CPP_ } @@ -53,7 +50,17 @@ int vfs_mount(device_t device, int fsType, char *mountPoint); #include "fs/FileSystem.h" #include "fs/VFSMount.h" -FileSystem *vfs_attempt_mount(device_t device, int fsType); +typedef FileSystem *(*mount_func_t)(device_t); + +typedef struct +{ + string name; + mount_func_t mount_func; +} FSHandle; + +FileSystem *vfs_attempt_mount(device_t device, char *fsType); +int vfs_register(char *fs, FileSystem *(*mount_func)(device_t)); +mount_func_t vfs_get_mount_func(const string & fsName); #endif diff --git a/kernel/fs/vfs_old.h b/kernel/fs/vfs_old.h index 3985d0e..c410aec 100644 --- a/kernel/fs/vfs_old.h +++ b/kernel/fs/vfs_old.h @@ -39,21 +39,20 @@ typedef u64_t vfs_inode_t; /* Structure to hold information about a mount point */ -struct vfs_mount_s +typedef struct vfs_mount_s { - int refs; - void *super; - int fs; - major_t major; - minor_t minor; - char *mountPoint; - vfs_inode_t vfs_mount_inode; - vfs_inode_t vfs_up_inode; - vfs_inode_t vfs_root_inode; + int refs; + void *super; + int fs; + major_t major; + minor_t minor; + char *mountPoint; + vfs_inode_t vfs_mount_inode; + vfs_inode_t vfs_up_inode; + vfs_inode_t vfs_root_inode; struct vfs_mount_s *next; struct vfs_mount_s *prev; -}; -typedef struct vfs_mount_s vfs_mount_t; +} vfs_mount_t; typedef struct { diff --git a/kernel/kernel.c b/kernel/kernel.c index ef7cdcb..96d2b71 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -141,7 +141,7 @@ void k_init() // 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); kprintf("initrd (%dkb) loaded\n", (mb_modules[i].mod_end - mb_modules[i].mod_start) >> 10); - k_check(vfs_mount(DEV(MAJOR_RAMDISK, initrd_minor), FS_EXT2, "/"), "Could not mount initrd to /!"); + k_check(vfs_mount(DEV(MAJOR_RAMDISK, initrd_minor), "ext2", "/"), "Kernel panic: Could not mount initrd to /!"); } } @@ -184,7 +184,6 @@ void k_init() else kprintf("Error: Could not open directory\n"); */ - criticalCounter--; } diff --git a/kernel/mm/vmm.c b/kernel/mm/vmm.c index b030815..0995bdc 100644 --- a/kernel/mm/vmm.c +++ b/kernel/mm/vmm.c @@ -2,7 +2,7 @@ // Author: Josh Holtrop // Date: 09/30/03 // Rewritten from scratch: 12/23/03 -// Modified: 07/30/04 +// Modified: 08/17/05 #include "hos_defines.h" #include "kernel.h" @@ -18,6 +18,7 @@ int vmm_coalesceEntry(u32_t queue, HeapEntry_t *newHE); void vmm_heb_init(HeapEntryBlock_t *heb); void vmm_addToQueue(u32_t queue, HeapEntry_t *preceeding, HeapEntry_t *he); int vmm_countHeapEntries(HeapEntry_t *he); +int vmm_unmapp(void *addr); HeapEntry_t *vmm_followChain(HeapEntry_t *he); HeapEntry_t *vmm_getUnusedEntry(); HeapEntry_t *vmm_stripUnusedEntry(); @@ -101,10 +102,13 @@ int vmm_mapn(u32_t virt, u32_t physical, u32_t n) } -// This function removes the virtual address's entry in the page directory / page table +// This function removes the virtual address's entry in the +// page directory / page table void vmm_unmap1(u32_t virt) { - *(u32_t *)(0xFFC00000 | ((virt & 0xFFC00000) >> 10) | ((virt & 0x003FF000) >> 10)) = 0; + *(u32_t *)(0xFFC00000 | + ((virt & 0xFFC00000) >> 10) | + ((virt & 0x003FF000) >> 10)) = 0; invlpg_(virt); } @@ -125,7 +129,7 @@ void vmm_unmapn(u32_t virt, u32_t n) int vmm_map_range(void *virt_start, void *virt_end, u32_t phys_start) { if (virt_end < virt_start) - return -1; // invalid region + return -1; // invalid region while (virt_start < virt_end) { if (vmm_map1((u32_t)virt_start, phys_start)) @@ -139,11 +143,12 @@ int vmm_map_range(void *virt_start, void *virt_end, u32_t phys_start) // kernel virtual memory allocator -void *kmalloc(u32_t size) +void *kmalloc(u32_t size) { k_enter_critical(); if (size % VMM_MALLOC_GRANULARITY) - size = size + VMM_MALLOC_GRANULARITY - (size % VMM_MALLOC_GRANULARITY); + size = size + VMM_MALLOC_GRANULARITY - + (size % VMM_MALLOC_GRANULARITY); void *attempt = vmm_getFreeChunk(size); if (attempt) { @@ -153,7 +158,7 @@ void *kmalloc(u32_t size) if (vmm_moreCore(size)) { k_leave_critical(); - return NULL; //we could not get any more heap memory + return NULL; //we could not get any more heap memory } attempt = vmm_getFreeChunk(size); k_leave_critical(); @@ -162,7 +167,7 @@ void *kmalloc(u32_t size) // kernel virtual memory de-allocator -int kfree(void *addr) +int kfree(void *addr) { k_enter_critical(); HeapEntry_t *he = heapEntryQueues[VMM_HE_USED].head->next; @@ -185,7 +190,7 @@ int kfree(void *addr) // This function allocates a virtual page and maps it to a physical page -void *vmm_palloc() +void *vmm_palloc() { k_enter_critical(); HeapEntry_t *he = heapEntryQueues[VMM_HE_HOLE].head->next; @@ -196,7 +201,8 @@ void *vmm_palloc() { vmm_removeHeapEntry(VMM_HE_HOLE, he); vmm_addToQueue(VMM_HE_USED, &heapEntryHeadNodes[VMM_HE_USED], he); - vmm_map(he->base); + if (vmm_map(he->base)) + he->base = NULL; k_leave_critical(); return he->base; } @@ -214,22 +220,35 @@ void *vmm_palloc() he->base = wilderness->base + wilderness->length; he->length = 4096; vmm_addToQueue(VMM_HE_USED, &heapEntryHeadNodes[VMM_HE_USED], he); - vmm_map(he->base); + if (vmm_map(he->base)) + he->base = NULL; k_leave_critical(); return he->base; } // This function frees a previously-allocated virtual page -int vmm_pfree(void *addr) +int vmm_pfree(void *addr) { + u32_t pbase = *(u32_t *)(0xFFC00000 | + (((u32_t)addr & 0xFFC00000) >> 10) | + (((u32_t)addr & 0x003FF000) >> 10)); + if (vmm_unmapp(addr)) + return -1; + mm_pfree(pbase); +} + +int vmm_unmapp(void *addr) +{ + if (!addr) + return -2; k_enter_critical(); HeapEntry_t *he = heapEntryQueues[VMM_HE_USED].head->next; while (he->next) { if (he->base == addr) //found the page to free { - vmm_removeHeapEntry(VMM_HE_USED, he); + vmm_removeHeapEntry(VMM_HE_USED, he); vmm_unmap1((u32_t)he->base); vmm_addToQueue(VMM_HE_HOLE, &heapEntryHeadNodes[VMM_HE_HOLE], he); k_leave_critical();