diff --git a/mentos/CMakeLists.txt b/mentos/CMakeLists.txt index f43a68e..cb08bd0 100644 --- a/mentos/CMakeLists.txt +++ b/mentos/CMakeLists.txt @@ -160,6 +160,7 @@ if(USE_BUDDY_SYSTEM) src/fs/procfs.c src/fs/ioctl.c src/fs/namei.c + src/fs/ext2.c src/hardware/timer.c src/hardware/cpuid.c src/hardware/pic8259.c @@ -243,6 +244,7 @@ else(USE_BUDDY_SYSTEM) src/fs/procfs.c src/fs/ioctl.c src/fs/namei.c + src/fs/ext2.c src/hardware/timer.c src/hardware/cpuid.c src/hardware/pic8259.c diff --git a/mentos/inc/fs/ext2.h b/mentos/inc/fs/ext2.h new file mode 100644 index 0000000..0968c85 --- /dev/null +++ b/mentos/inc/fs/ext2.h @@ -0,0 +1,17 @@ +/// @file ext2.h +/// @author Enrico Fraccaroli (enry.frak@gmail.com) +/// @brief EXT2 driver. +/// @version 0.1 +/// @date 2021-12-13 +/// @copyright (c) 2014-2021 This file is distributed under the MIT License. +/// See LICENSE.md for details. + +#pragma once + +/// @brief Initializes the EXT2 drivers. +/// @return 0 on success, 1 on error. +int ext2_initialize(); + +/// @brief De-initializes the EXT2 drivers. +/// @return 0 on success, 1 on error. +int ext2_finalize(); diff --git a/mentos/src/fs/ext2.c b/mentos/src/fs/ext2.c new file mode 100644 index 0000000..b30c479 --- /dev/null +++ b/mentos/src/fs/ext2.c @@ -0,0 +1,211 @@ +/// @file ext2.c +/// @author Enrico Fraccaroli (enry.frak@gmail.com) +/// @brief EXT2 driver. +/// @version 0.1 +/// @date 2021-12-13 +/// @copyright (c) 2014-2021 This file is distributed under the MIT License. +/// See LICENSE.md for details. + +#include "fs/ext2.h" + +#define __DEBUG_HEADER__ "[EXT2 ]" +#define __DEBUG_LEVEL__ 100 + +#include "process/scheduler.h" +#include "process/process.h" +#include "klib/spinlock.h" +#include "fs/vfs_types.h" +#include "sys/errno.h" +#include "io/debug.h" +#include "fs/vfs.h" +#include "string.h" +#include "stdio.h" +#include "fcntl.h" + +/// @brief The superblock contains all the information about the configuration +/// of the filesystem. +/// @details The primary copy of the superblock is stored at an offset of 1024 +/// bytes from the start of the device, and it is essential to mounting the +/// filesystem. Since it is so important, backup copies of the superblock are +/// stored in block groups throughout the filesystem. +typedef struct ext2_superblock_t { + uint32_t inodes_count; + uint32_t blocks_count; + uint32_t r_blocks_count; + uint32_t free_blocks_count; + uint32_t free_inodes_count; + uint32_t first_data_block; + 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; + // EXT2_DYNAMIC_REV + uint32_t first_ino; + uint16_t inode_size; + uint16_t block_group_nr; + uint32_t feature_compat; + uint32_t feature_incompat; + uint32_t feature_ro_compat; + uint8_t uuid[16]; + uint8_t volume_name[16]; + uint8_t last_mounted[64]; + uint32_t algo_bitmap; + // Performance Hints + uint8_t prealloc_blocks; + uint8_t prealloc_dir_blocks; + uint16_t _padding; + // Journaling Support + uint8_t journal_uuid[16]; + uint32_t journal_inum; + uint32_t jounral_dev; + uint32_t last_orphan; + // Directory Indexing Support + uint32_t hash_seed[4]; + uint8_t def_hash_version; + uint16_t _padding_a; + uint8_t _padding_b; + // Other Options + uint32_t default_mount_options; + uint32_t first_meta_bg; + uint8_t _unused[760]; +} __attribute__((packed)) ext2_superblock_t; + +static const char *uuid_to_string(uint8_t uuid[16]) +{ + static char s[33] = { 0 }; + sprintf(s, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", + uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7], + uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]); + return s; +} + +static const char *time_to_string(uint32_t time) +{ + static char s[250] = { 0 }; + tm_t *tm = localtime(&time); + sprintf(s, "%2d/%2d %2d:%2d", tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min); + return s; +} + +static void ext2_dump_superblock(ext2_superblock_t *sb) +{ + pr_debug("inodes_count : %d\n", sb->inodes_count); + pr_debug("blocks_count : %d\n", sb->blocks_count); + pr_debug("r_blocks_count : %d\n", sb->r_blocks_count); + pr_debug("free_blocks_count : %d\n", sb->free_blocks_count); + pr_debug("free_inodes_count : %d\n", sb->free_inodes_count); + pr_debug("first_data_block : %d\n", sb->first_data_block); + pr_debug("log_block_size : %d\n", sb->log_block_size); + pr_debug("log_frag_size : %d\n", sb->log_frag_size); + pr_debug("blocks_per_group : %d\n", sb->blocks_per_group); + pr_debug("frags_per_group : %d\n", sb->frags_per_group); + pr_debug("inodes_per_group : %d\n", sb->inodes_per_group); + pr_debug("mtime : %s\n", time_to_string(sb->mtime)); + pr_debug("wtime : %s\n", time_to_string(sb->wtime)); + pr_debug("mnt_count : %d\n", sb->mnt_count); + pr_debug("max_mnt_count : %d\n", sb->max_mnt_count); + pr_debug("magic : %d\n", sb->magic); + pr_debug("state : %d\n", sb->state); + pr_debug("errors : %d\n", sb->errors); + pr_debug("minor_rev_level : %d\n", sb->minor_rev_level); + pr_debug("lastcheck : %s\n", time_to_string(sb->lastcheck)); + pr_debug("checkinterval : %d\n", sb->checkinterval); + pr_debug("creator_os : %d\n", sb->creator_os); + pr_debug("rev_level : %d\n", sb->rev_level); + pr_debug("def_resuid : %d\n", sb->def_resuid); + pr_debug("def_resgid : %d\n", sb->def_resgid); + pr_debug("first_ino : %d\n", sb->first_ino); + pr_debug("inode_size : %d\n", sb->inode_size); + pr_debug("block_group_nr : %d\n", sb->block_group_nr); + pr_debug("feature_compat : %d\n", sb->feature_compat); + pr_debug("feature_incompat : %d\n", sb->feature_incompat); + pr_debug("feature_ro_compat : %d\n", sb->feature_ro_compat); + pr_debug("uuid : %s\n", uuid_to_string(sb->uuid)); + pr_debug("volume_name : %s\n", (char *)sb->volume_name); + pr_debug("last_mounted : %s\n", (char *)sb->last_mounted); + pr_debug("algo_bitmap : %d\n", sb->algo_bitmap); + pr_debug("prealloc_blocks : %d\n", sb->prealloc_blocks); + pr_debug("prealloc_dir_blocks : %d\n", sb->prealloc_dir_blocks); + pr_debug("_padding : %d\n", sb->_padding); + pr_debug("journal_uuid : %s\n", uuid_to_string(sb->journal_uuid)); + pr_debug("journal_inum : %d\n", sb->journal_inum); + pr_debug("jounral_dev : %d\n", sb->jounral_dev); + pr_debug("last_orphan : %d\n", sb->last_orphan); + pr_debug("hash_seed : %u %u %u %u\n", sb->hash_seed[0], sb->hash_seed[1], sb->hash_seed[2], sb->hash_seed[3]); + pr_debug("def_hash_version : %d\n", sb->def_hash_version); + pr_debug("_padding_a : %d\n", sb->_padding_a); + pr_debug("_padding_b : %d\n", sb->_padding_b); + pr_debug("default_mount_options : %d\n", sb->default_mount_options); + pr_debug("first_meta_bg : %d\n", sb->first_meta_bg); +} + +static vfs_file_t *ext2_mount_callback(const char *path, const char *device) +{ + vfs_file_t *dev = vfs_open(device, 0, 0); + if (dev && (dev->flags == DT_BLK)) { + pr_debug("Correctly found block device.\n"); + ext2_superblock_t sb; + memset(&sb, 0, sizeof(ext2_superblock_t)); + if (vfs_read(dev, &sb, 1024, sizeof(ext2_superblock_t)) == -1) { + pr_err("Failed to read the superblock table at 1024.\n"); + return NULL; + } + ext2_dump_superblock(&sb); + } + return NULL; +} + +/// Filesystem general operations. +static vfs_sys_operations_t ext2_sys_operations = { + .mkdir_f = NULL, + .rmdir_f = NULL, + .stat_f = NULL +}; + +/// Filesystem file operations. +static vfs_file_operations_t ext2_fs_operations = { + .open_f = NULL, + .unlink_f = NULL, + .close_f = NULL, + .read_f = NULL, + .write_f = NULL, + .lseek_f = NULL, + .stat_f = NULL, + .ioctl_f = NULL, + .getdents_f = NULL +}; + +/// Filesystem information. +static file_system_type ext2_file_system_type = { + .name = "ext2", + .fs_flags = 0, + .mount = ext2_mount_callback +}; + +int ext2_initialize(void) +{ + // Register the filesystem. + vfs_register_filesystem(&ext2_file_system_type); + return 0; +} + +int ext2_finalize(void) +{ + vfs_unregister_filesystem(&ext2_file_system_type); + return 0; +} \ No newline at end of file diff --git a/mentos/src/kernel.c b/mentos/src/kernel.c index 361658c..c579d9b 100644 --- a/mentos/src/kernel.c +++ b/mentos/src/kernel.c @@ -20,6 +20,7 @@ #include "io/debug.h" #include "drivers/fdc.h" #include "fs/initrd.h" +#include "fs/ext2.h" #include "klib/irqflags.h" #include "drivers/keyboard/keyboard.h" #include "process/scheduler.h" @@ -268,6 +269,11 @@ int kmain(boot_info_t *boot_informations) return 1; } + ext2_initialize(); + if (do_mount("ext2", "/mnt", "/dev/hda")) { + pr_warning("Failed to mount ext at `/dev/hda`!\n"); + } + //========================================================================== pr_notice("Setting up keyboard driver...\n"); printf("Setting up keyboard driver...");