Handle improper file paths (#14)
* Sort memmap entries * fixed improper module path fault * Sort memmap entries * removed bin yet again * Sort memmap entries * build Co-authored-by: mintsuki <mintsuki@protonmail.com>
diff --git a/qloader2.bin b/qloader2.bin
index 01be75ed..78af2bf5 100644
Binary files a/qloader2.bin and b/qloader2.bin differ
diff --git a/src/fs/ext2.c b/src/fs/ext2.c
new file mode 100644
index 00000000..766322d1
--- /dev/null
+++ b/src/fs/ext2.c
@@ -0,0 +1,277 @@
+#include <stdint.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <fs/ext2.h>
+#include <drivers/disk.h>
+#include <lib/libc.h>
+#include <lib/blib.h>
+
+/* EXT2 Filesystem States */
+#define EXT2_FS_ERRORS 2
+
+#define EXT2_S_MAGIC 0xEF53
+
+/* Superblock Fields */
+struct ext2_superblock {
+ uint32_t s_inodes_count;
+ uint32_t s_blocks_count;
+ uint32_t s_r_blocks_count;
+ uint32_t s_free_blocks_count;
+ uint32_t s_free_inodes_count;
+ uint32_t s_first_data_block;
+ uint32_t s_log_block_size;
+ uint32_t s_log_frag_size;
+ uint32_t s_blocks_per_group;
+ uint32_t s_frags_per_group;
+ uint32_t s_inodes_per_group;
+ uint32_t s_mtime;
+ uint32_t s_wtime;
+
+ uint16_t s_mnt_count;
+ uint16_t s_max_mnt_count;
+ uint16_t s_magic;
+ uint16_t s_state;
+ uint16_t s_errors;
+ uint16_t s_minor_rev_level;
+
+ uint32_t s_lastcheck;
+ uint32_t s_checkinterval;
+ uint32_t s_creator_os;
+ uint32_t s_rev_level;
+ uint16_t s_def_resuid;
+ uint16_t s_def_gid;
+
+ // if version number >= 1, we have to use the ext2 extended superblock as well
+
+ /* Extended Superblock */
+ uint32_t s_first_ino;
+
+ uint16_t s_inode_size;
+ uint16_t s_block_group_nr;
+
+ uint32_t s_feature_compat;
+ uint32_t s_feature_incompat;
+ uint32_t s_feature_ro_compat;
+
+ uint64_t s_uuid[2];
+ uint64_t s_volume_name[2];
+
+ uint64_t s_last_mounted[8];
+} __attribute__((packed));
+
+/* EXT2 Block Group Descriptor */
+struct ext2_bgd {
+ uint32_t bg_block_bitmap;
+ uint32_t bg_inode_bitmap;
+ uint32_t bg_inode_table;
+
+ uint16_t bg_free_blocks_count;
+ uint16_t bg_free_inodes_count;
+ uint16_t bg_dirs_count;
+
+ uint16_t reserved[7];
+} __attribute__((packed));
+
+/* EXT2 Inode Types */
+#define EXT2_INO_DIRECTORY 0x4000
+#define EXT2_INO_FILE 0x8000
+
+/* EXT2 Directory Entry */
+struct ext2_dir_entry {
+ uint32_t inode;
+ uint16_t rec_len;
+ uint8_t name_len;
+ uint8_t type;
+} __attribute__((packed));
+
+static int inode_read(void *buf, uint64_t loc, uint64_t count,
+ uint64_t block_size, struct ext2_inode *inode,
+ uint64_t drive, struct part *part);
+
+// parse an inode given the partition base and inode number
+static int ext2_get_inode(struct ext2_inode *ret, uint64_t drive, struct part *part, uint64_t inode, struct ext2_superblock *sb) {
+ if (inode == 0)
+ return -1;
+
+ uint64_t ino_blk_grp = (inode - 1) / sb->s_inodes_per_group;
+ uint64_t ino_tbl_idx = (inode - 1) % sb->s_inodes_per_group;
+
+ uint64_t block_size = ((uint64_t)1024 << sb->s_log_block_size);
+
+ struct ext2_bgd target_descriptor;
+
+ uint64_t bgd_start_offset = block_size >= 2048 ? block_size : block_size * 2;
+
+ read_partition(drive, part, &target_descriptor, bgd_start_offset + (sizeof(struct ext2_bgd) * ino_blk_grp), sizeof(struct ext2_bgd));
+
+ read_partition(drive, part, ret, (target_descriptor.bg_inode_table * block_size) + (sb->s_inode_size * ino_tbl_idx), sizeof(struct ext2_inode));
+
+ return 0;
+}
+
+static int ext2_parse_dirent(struct ext2_dir_entry *dir, struct ext2_file_handle *fd, struct ext2_superblock *sb, const char *path) {
+ if (*path == '/')
+ path++;
+
+ struct ext2_inode *current_inode = balloc(sizeof(struct ext2_inode));
+ *current_inode = fd->root_inode;
+
+ bool escape = false;
+
+ char token[128] = {0};
+
+next:
+ for (size_t i = 0; *path != '/' && *path != '\0'; i++, path++)
+ token[i] = *path;
+
+ if (*path == '\0')
+ escape = true;
+ else
+ path++;
+
+ for (uint32_t i = 0; i < current_inode->i_size; ) {
+ // preliminary read
+ inode_read(dir, i, sizeof(struct ext2_dir_entry),
+ fd->block_size, current_inode,
+ fd->drive, &fd->part);
+
+ // name read
+ char *name = balloc(dir->name_len);
+ inode_read(name, i + sizeof(struct ext2_dir_entry), dir->name_len,
+ fd->block_size, current_inode,
+ fd->drive, &fd->part);
+
+ int r = strncmp(token, name, dir->name_len);
+
+ brewind(dir->name_len);
+
+ if (!r) {
+ if (escape) {
+ brewind(sizeof(struct ext2_inode));
+ return 0;
+ } else {
+ // update the current inode
+ ext2_get_inode(current_inode, fd->drive, &fd->part, dir->inode, sb);
+ goto next;
+ }
+ }
+
+ i += dir->rec_len;
+ }
+
+ brewind(sizeof(struct ext2_inode));
+ return -1;
+}
+
+int ext2_open(struct ext2_file_handle *ret, int drive, int partition, const char *path) {
+ if (get_part(&ret->part, drive, partition)) {
+ panic("Invalid partition");
+ }
+
+ ret->drive = drive;
+
+ struct ext2_superblock sb;
+ read_partition(drive, &ret->part, &sb, 1024, sizeof(struct ext2_superblock));
+
+ if (sb.s_state == EXT2_FS_ERRORS)
+ panic("ext2 fs has errors\n");
+
+ ret->block_size = ((uint64_t)1024 << sb.s_log_block_size);
+
+ ext2_get_inode(&ret->root_inode, drive, &ret->part, 2, &sb);
+
+ struct ext2_dir_entry entry;
+ int r = ext2_parse_dirent(&entry, ret, &sb, path);
+
+ if (r)
+ return r;
+
+ ext2_get_inode(&ret->inode, drive, &ret->part, entry.inode, &sb);
+ ret->size = ret->inode.i_size;
+
+ if (ret->inode.i_mode & EXT2_INO_DIRECTORY)
+ panic("Requested file \"%s\" is a directory!", path);
+
+ return 0;
+}
+
+int ext2_read(struct ext2_file_handle *file, void *buf, uint64_t loc, uint64_t count) {
+ return inode_read(buf, loc, count,
+ file->block_size, &file->inode,
+ file->drive, &file->part);
+}
+
+static int inode_read(void *buf, uint64_t loc, uint64_t count,
+ uint64_t block_size, struct ext2_inode *inode,
+ uint64_t drive, struct part *part) {
+ for (uint64_t progress = 0; progress < count;) {
+ uint64_t block = (loc + progress) / block_size;
+
+ uint64_t chunk = count - progress;
+ uint64_t offset = (loc + progress) % block_size;
+ if (chunk > block_size - offset)
+ chunk = block_size - offset;
+
+ uint32_t block_index;
+
+ if (block < 12) {
+ // Direct block
+ block_index = inode->i_blocks[block];
+ } else {
+ // Indirect block
+ block -= 12;
+ if (block * sizeof(uint32_t) >= block_size) {
+ // Double indirect block
+ block -= block_size / sizeof(uint32_t);
+ uint32_t index = block / (block_size / sizeof(uint32_t));
+ if (index * sizeof(uint32_t) >= block_size) {
+ // Triple indirect block
+ panic("ext2: triply indirect blocks unsupported");
+ }
+ uint32_t offset = block % (block_size / sizeof(uint32_t));
+ uint32_t indirect_block;
+ read_partition(
+ drive, part, &indirect_block,
+ inode->i_blocks[13] * block_size + index * sizeof(uint32_t),
+ sizeof(uint32_t)
+ );
+ read_partition(
+ drive, part, &block_index,
+ indirect_block * block_size + offset * sizeof(uint32_t),
+ sizeof(uint32_t)
+ );
+ } else {
+ read_partition(
+ drive, part, &block_index,
+ inode->i_blocks[12] * block_size + block * sizeof(uint32_t),
+ sizeof(uint32_t)
+ );
+ }
+ }
+
+ read_partition(drive, part, buf + progress, (block_index * block_size) + offset, chunk);
+
+ progress += chunk;
+ }
+
+ return 0;
+}
+
+// attempts to initialize the ext2 filesystem
+int ext2_check_signature(int drive, int partition) {
+ struct part part;
+ if (get_part(&part, drive, partition)) {
+ panic("Invalid partition");
+ }
+
+ uint16_t magic = 0;
+
+ // read only the checksum of the superblock
+ read_partition(drive, &part, &magic, 1024 + 56, 2);
+
+ if (magic == EXT2_S_MAGIC) {
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/src/fs/ext2.h b/src/fs/ext2.h
new file mode 100644
index 00000000..c0f082c6
--- /dev/null
+++ b/src/fs/ext2.h
@@ -0,0 +1,62 @@
+#ifndef __FS_EXT2_H__
+#define __FS_EXT2_H__
+
+#include <stdint.h>
+#include <stddef.h>
+#include <lib/part.h>
+
+struct ext2_linux {
+ uint8_t frag_num;
+ uint8_t frag_size;
+
+ uint16_t reserved_16;
+ uint16_t user_id_high;
+ uint16_t group_id_high;
+
+ uint32_t reserved_32;
+} __attribute__((packed));
+
+struct ext2_inode {
+ uint16_t i_mode;
+ uint16_t i_uid;
+
+ uint32_t i_size;
+ uint32_t i_atime;
+ uint32_t i_ctime;
+ uint32_t i_mtime;
+ uint32_t i_dtime;
+
+ uint16_t i_gid;
+ uint16_t i_links_count;
+
+ uint32_t i_blocks_count;
+ uint32_t i_flags;
+ uint32_t i_osd1;
+ uint32_t i_blocks[15];
+ uint32_t i_generation;
+
+ /* EXT2 v >= 1.0 */
+ uint32_t i_eab;
+ uint32_t i_maj;
+
+ /* EXT2 vAll */
+ uint32_t i_frag_block;
+
+ struct ext2_linux i_osd2;
+} __attribute__((packed));
+
+struct ext2_file_handle {
+ int drive;
+ struct part part;
+ int size;
+ struct ext2_inode root_inode;
+ struct ext2_inode inode;
+ uint64_t block_size;
+};
+
+int ext2_check_signature(int drive, int partition);
+
+int ext2_open(struct ext2_file_handle *ret, int drive, int partition, const char *path);
+int ext2_read(struct ext2_file_handle *file, void *buf, uint64_t loc, uint64_t count);
+
+#endif
diff --git a/src/fs/ext2fs.c b/src/fs/ext2fs.c
deleted file mode 100644
index c67e5898..00000000
--- a/src/fs/ext2fs.c
+++ /dev/null
@@ -1,372 +0,0 @@
-#include <stdint.h>
-#include <stddef.h>
-#include <stdbool.h>
-#include <fs/ext2fs.h>
-#include <drivers/disk.h>
-#include <lib/libc.h>
-#include <lib/blib.h>
-
-/* EXT2 Filesystem States */
-#define EXT2_FS_CLEAN 1
-#define EXT2_FS_ERRORS 2
-
-/* EXT2 Error Handling */
-#define EXT2_ERR_IGNORE 1
-#define EXT2_ERR_REMOUNT_AS_READ 2
-#define EXT2_ERR_PANIC 3
-
-/* EXT2 Creator OS IDs */
-#define EXT2_LINUX 0
-#define EXT2_GNU_HURD 1
-#define EXT2_MASIX 2
-#define EXT2_FREEBSD 3
-#define EXT2_BSD_DERIVATIVE 4
-
-/* EXT2 Optional Feature Flags */
-#define EXT2_OPT_PREALLOC 0x0001 // Prealloc x number of blocks (superblock byte 205)
-#define EXT2_OPT_AFS_INODES 0x0002 // AFS server inodes exist
-#define EXT2_OPT_JOURNAL 0x0004 // FS has a journal (ext3)
-#define EXT2_OPT_INODE_EXT_ATTR 0x0008 // Inodes have extended attributes
-#define EXT2_OPT_FS_RESIZE 0x0010 // FS can resize itself for larger partitions
-#define EXT2_OPT_DIR_HASH_IDX 0x0020 // Directories use a hash index
-
-/* EXT2 Required Feature Flags */
-#define EXT2_REQ_COMPRESSION 0x0001 // the FS uses compression
-#define EXT2_REQ_DIR_TYPE_FIELD 0x0002 // Dir entries contain a type field
-#define EXT2_REQ_JOURNAL_REPLAY 0x0004 // FS needs to replay its journal
-#define EXT2_REQ_USE_JOURNAL 0x0008 // FS uses a journal device
-
-/* EXT2 Read-Only Feature Flags */
-#define EXT2_SPARSE 0x0001 // Sparse superblocks and group descriptor tables
-#define EXT2_FS_LONG 0x0002 // FS uses 64 bit file sizes
-#define EXT2_BTREE 0x0004 // Directory contents are stored in a Binary Tree
-
-// https://wiki.osdev.org/Ext2#Superblock
-// the superblock starts at byte 1024 and occupies 1024 bytes
-// the size of each block is located at byte 24 of the superblock
-
-#define EXT2_S_MAGIC 0xEF53
-
-/* Superblock Fields */
-struct ext2fs_superblock {
- uint32_t s_inodes_count; // total number of inodes in the system
- uint32_t s_blocks_count; // total number of blocks in the system
- uint32_t s_r_blocks_count; // blocks that only the superuser can access
- uint32_t s_free_blocks_count; // number of free blocks
- uint32_t s_free_inodes_count; // number of free inodes
- uint32_t s_first_data_block; // block number of block that contains superblock
- uint32_t s_log_block_size; // [log2(blocksize) - 10] shift left 1024 to get block size
- uint32_t s_log_frag_size; // [log2(fragsize) - 10] sift left 1024 to get fragment size
- uint32_t s_blocks_per_group; // number of blocks per block group
- uint32_t s_frags_per_group; // number of fragments per block group
- uint32_t s_inodes_per_group; // number of inodes per block group
- uint32_t s_mtime; // Last mount time
- uint32_t s_wtime; // Last write time
-
- uint16_t s_mnt_count; // number of times the volume was mounted before last consistency check
- uint16_t s_max_mnt_count; // number of times the drive can be mounted before a check
- uint16_t s_magic; // 0xEF53 | used to confirm ext2 presence
- uint16_t s_state; // state of the filesystem
- uint16_t s_errors; // what to do incase of an error
- uint16_t s_minor_rev_level; // combine with major portion to get full version
-
- uint32_t s_lastcheck; // timestamp of last consistency check
- uint32_t s_checkinterval; // amount of time between required consistency checks
- uint32_t s_creator_os; // operating system ID
- uint32_t s_rev_level; // combine with minor portion to get full version
- uint16_t s_def_resuid; // User ID that can use reserved blocks
- uint16_t s_def_gid; // Group ID that can use reserved blocks
-
- // if version number >= 1, we have to use the ext2 extended superblock as well
-
- /* Extended Superblock */
- uint32_t s_first_ino; // first non reserved inode in the fs (fixed to 11 when version < 1)
-
- uint16_t s_inode_size; // size of each inode (in bytes) (fixed to 128 when version < 1)
- uint16_t s_block_group_nr; // block group this superblock is part of
-
- uint32_t s_feature_compat; // if optional features are present
- uint32_t s_feature_incompat; // if required features are present
- uint32_t s_feature_ro_compat; // features that are unsupported (make FS readonly)
-
- uint64_t s_uuid[2]; // FS ID
- uint64_t s_volume_name[2]; // Volume Name
-
- uint64_t s_last_mounted[8]; // last path the volume was mounted to (C-style string)
-
- uint32_t s_algo_bitmap; // Compression algorithm used
-
- uint8_t s_prealloc_blocks; // Number of blocks to preallocate for files
- uint8_t s_prealloc_dir_blocks; // Number of blocks to preallocate for directories
-
- uint16_t unused; // Unused
-
- uint64_t s_journal_uuid[2]; // Journal ID
-
- uint32_t s_journal_inum; // Journal Inode number
- uint32_t s_journal_dev; // Journal device
- uint32_t s_last_orphan; // Head of orphan inode list
- uint32_t s_hash_seed[4]; // Seeds used for hashing algo for dir indexing
-
- uint8_t s_def_hash_version; // Default hash versrion used for dir indexing
-
- uint8_t padding[3];
-
- uint32_t s_default_mnt_opts; // Default mount options
- uint32_t s_first_meta_bg; // Block group ID for first meta group
-
- /* UNUSED */
-} __attribute__((packed));
-
-/* EXT2 Block Group Descriptor */
-struct ext2fs_bgd {
- uint32_t bg_block_bitmap; // Block address of block usage bitmap
- uint32_t bg_inode_bitmap; // Block address of inode usage bitmap
- uint32_t bg_inode_table; // Starting block address of inode table
-
- uint16_t bg_free_blocks_count; // Number of unallocated blocks in group
- uint16_t bg_free_inodes_count; // Number of unallocated blocks in inode
- uint16_t bg_dirs_count; // Number of directories in group
-
- uint16_t reserved[7];
-} __attribute__((packed));
-
-/* EXT2 Inode Types */
-#define EXT2_INO_FIFO 0x1000
-#define EXT2_INO_CHR_DEV 0x2000 // Character device
-#define EXT2_INO_DIRECTORY 0x4000
-#define EXT2_INO_BLK_DEV 0x6000 // Block device
-#define EXT2_INO_FILE 0x8000
-#define EXT2_INO_SYMLINK 0xA000
-#define EXT2_INO_UNIX_SOCKET 0xC000
-
-/* EXT2 Inode Permissions */
-#define EXT2_INO_X_OTHER 0x001
-#define EXT2_INO_W_OTHER 0x002
-#define EXT2_INO_R_OTHER 0x004
-#define EXT2_INO_X_GROUP 0x008
-#define EXT2_INO_W_GROUP 0x010
-#define EXT2_INO_R_GROUP 0x020
-#define EXT2_INO_X_USER 0x040
-#define EXT2_INO_W_USER 0x080
-#define EXT2_INO_R_USER 0x100
-#define EXT2_INO_STICKY 0x200
-#define EXT2_INO_S_GRP_ID 0x400 // Set User ID
-#define EXT2_INO_S_USR_ID 0x800 // Set Group ID
-
-/* EXT2 Inode Flags */
-#define EXT2_INO_SECURE_DELETION 0x00000001 // Secure deletion (unused)
-#define EXT2_INO_KEEP_COPY 0x00000002 // Keep copy of data upon deleting (unused)
-#define EXT2_INO_FILE_COMPRESSION 0x00000004 // File compression (unused)
-#define EXT2_INO_SYNC_UPDATES 0x00000008 // Sync updates to disk
-#define EXT2_INO_FILE_IMMUTABLE 0x00000010 // File is readonly
-#define EXT2_INO_APPEND_ONLY 0x00000020 // Append only
-#define EXT2_INO_NO_INCLUDE_DUMP 0x00000040 // File not included in dump command
-#define EXT2_INO_NO_UDPATE_LAT 0x00000080 // Dont update the last access time
-#define EXT2_INO_HASH_IDX_DIR 0x00010000 // Directory is hash indexed
-#define EXT2_INO_AFS_DIR 0x00020000 // Is AFS directory
-#define EXT2_INO_JOURNAL_DATA 0x00040000 // Journal File Data
-
-/* EXT2 Directory File Types */
-#define EXT2_FT_UNKNOWN 0 // Unknown
-#define EXT2_FT_FILE 1 // Regular file
-#define EXT2_FT_DIR 2 // Directory
-#define EXT2_FT_CHRDEV 3 // Character Device
-#define EXT2_FT_BLKDEV 4 // Block Device
-#define EXT2_FT_FIFO 5 // FIFO
-#define EXT2_FT_SOCKET 6 // Unix Socket
-#define EXT2_FT_SYMLINK 7 // Symbolic Link
-
-/* EXT2 Directory Entry */
-struct ext2fs_dir_entry {
- uint32_t inode; // Inode number of file entry
- uint16_t rec_len; // Displacement to next directory entry from start of current one
- uint8_t name_len; // Length of the name
- uint8_t type; // File type
-} __attribute__((packed));
-
-static int inode_read(void *buf, uint64_t loc, uint64_t count,
- uint64_t block_size, struct ext2fs_inode *inode,
- uint64_t drive, struct part *part);
-
-// parse an inode given the partition base and inode number
-static int ext2fs_get_inode(struct ext2fs_inode *ret, uint64_t drive, struct part *part, uint64_t inode, struct ext2fs_superblock *sb) {
- if (inode == 0)
- return -1;
-
- uint64_t ino_blk_grp = (inode - 1) / sb->s_inodes_per_group;
- uint64_t ino_tbl_idx = (inode - 1) % sb->s_inodes_per_group;
-
- uint64_t block_size = ((uint64_t)1024 << sb->s_log_block_size);
-
- struct ext2fs_bgd target_descriptor;
-
- uint64_t bgd_start_offset = block_size >= 2048 ? block_size : block_size * 2;
-
- read_partition(drive, part, &target_descriptor, bgd_start_offset + (sizeof(struct ext2fs_bgd) * ino_blk_grp), sizeof(struct ext2fs_bgd));
-
- read_partition(drive, part, ret, (target_descriptor.bg_inode_table * block_size) + (sb->s_inode_size * ino_tbl_idx), sizeof(struct ext2fs_inode));
-
- return 0;
-}
-
-static int ext2fs_parse_dirent(struct ext2fs_dir_entry *dir, struct ext2fs_file_handle *fd, struct ext2fs_superblock *sb, const char *path) {
- if (*path == '/')
- path++;
-
- struct ext2fs_inode *current_inode = balloc(sizeof(struct ext2fs_inode));
- *current_inode = fd->root_inode;
-
- bool escape = false;
-
- char token[128] = {0};
-
-next:
- for (size_t i = 0; *path != '/' && *path != '\0'; i++, path++)
- token[i] = *path;
-
- if (*path == '\0')
- escape = true;
- else
- path++;
-
- for (uint32_t i = 0; i < current_inode->i_size; ) {
- // preliminary read
- inode_read(dir, i, sizeof(struct ext2fs_dir_entry),
- fd->block_size, current_inode,
- fd->drive, &fd->part);
-
- // name read
- char *name = balloc(dir->name_len);
- inode_read(name, i + sizeof(struct ext2fs_dir_entry), dir->name_len,
- fd->block_size, current_inode,
- fd->drive, &fd->part);
-
- int r = strncmp(token, name, dir->name_len);
-
- brewind(dir->name_len);
-
- if (!r) {
- if (escape) {
- brewind(sizeof(struct ext2fs_inode));
- return 0;
- } else {
- // update the current inode
- ext2fs_get_inode(current_inode, fd->drive, &fd->part, dir->inode, sb);
- goto next;
- }
- }
-
- i += dir->rec_len;
- }
-
- brewind(sizeof(struct ext2fs_inode));
- return -1;
-}
-
-int ext2fs_open(struct ext2fs_file_handle *ret, int drive, int partition, const char *path) {
- if (get_part(&ret->part, drive, partition)) {
- panic("Invalid partition");
- }
-
- ret->drive = drive;
-
- struct ext2fs_superblock sb;
- read_partition(drive, &ret->part, &sb, 1024, sizeof(struct ext2fs_superblock));
-
- ret->block_size = ((uint64_t)1024 << sb.s_log_block_size);
-
- ext2fs_get_inode(&ret->root_inode, drive, &ret->part, 2, &sb);
-
- struct ext2fs_dir_entry entry;
- int r = ext2fs_parse_dirent(&entry, ret, &sb, path);
-
- if (r)
- return r;
-
- ext2fs_get_inode(&ret->inode, drive, &ret->part, entry.inode, &sb);
- ret->size = ret->inode.i_size;
-
- return 0;
-}
-
-int ext2fs_read(struct ext2fs_file_handle *file, void *buf, uint64_t loc, uint64_t count) {
- return inode_read(buf, loc, count,
- file->block_size, &file->inode,
- file->drive, &file->part);
-}
-
-static int inode_read(void *buf, uint64_t loc, uint64_t count,
- uint64_t block_size, struct ext2fs_inode *inode,
- uint64_t drive, struct part *part) {
- for (uint64_t progress = 0; progress < count;) {
- uint64_t block = (loc + progress) / block_size;
-
- uint64_t chunk = count - progress;
- uint64_t offset = (loc + progress) % block_size;
- if (chunk > block_size - offset)
- chunk = block_size - offset;
-
- uint32_t block_index;
-
- if (block < 12) {
- // Direct block
- block_index = inode->i_blocks[block];
- } else {
- // Indirect block
- block -= 12;
- if (block * sizeof(uint32_t) >= block_size) {
- // Double indirect block
- block -= block_size / sizeof(uint32_t);
- uint32_t index = block / (block_size / sizeof(uint32_t));
- if (index * sizeof(uint32_t) >= block_size) {
- // Triple indirect block
- panic("ext2fs: triply indirect blocks unsupported");
- }
- uint32_t offset = block % (block_size / sizeof(uint32_t));
- uint32_t indirect_block;
- read_partition(
- drive, part, &indirect_block,
- inode->i_blocks[13] * block_size + index * sizeof(uint32_t),
- sizeof(uint32_t)
- );
- read_partition(
- drive, part, &block_index,
- indirect_block * block_size + offset * sizeof(uint32_t),
- sizeof(uint32_t)
- );
- } else {
- read_partition(
- drive, part, &block_index,
- inode->i_blocks[12] * block_size + block * sizeof(uint32_t),
- sizeof(uint32_t)
- );
- }
- }
-
- read_partition(drive, part, buf + progress, (block_index * block_size) + offset, chunk);
-
- progress += chunk;
- }
-
- return 0;
-}
-
-// attempts to initialize the ext2 filesystem
-int ext2fs_check_signature(int drive, int partition) {
- struct part part;
- if (get_part(&part, drive, partition)) {
- panic("Invalid partition");
- }
-
- uint16_t magic = 0;
-
- // read only the checksum of the superblock
- read_partition(drive, &part, &magic, 1024 + 56, 2);
-
- if (magic == EXT2_S_MAGIC) {
- return 1;
- }
-
- return 0;
-}
diff --git a/src/fs/ext2fs.h b/src/fs/ext2fs.h
deleted file mode 100644
index 77609397..00000000
--- a/src/fs/ext2fs.h
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef __FS_EXT2FS_H__
-#define __FS_EXT2FS_H__
-
-#include <stdint.h>
-#include <stddef.h>
-#include <lib/part.h>
-
-/* EXT2 OS Specific Value 2 (only Linux support) */
-struct ext2fs_linux {
- uint8_t frag_num; // Number of fragments
- uint8_t frag_size; // Fragment Size
-
- uint16_t reserved_16; // Reserved
- uint16_t user_id_high; // High 16 bits of 32 bit user_id
- uint16_t group_id_high; // High 16 bits of 32 bit group_id
-
- uint32_t reserved_32; // Reserved
-} __attribute__((packed));
-
-/* EXT2 Inode */
-struct ext2fs_inode {
- uint16_t i_mode; // Types and permissions
- uint16_t i_uid; // User ID
-
- uint32_t i_size; // Lower 32 bits of the size (in bytes)
- uint32_t i_atime; // Time of last access
- uint32_t i_ctime; // Time of creation
- uint32_t i_mtime; // Time of last modification
- uint32_t i_dtime; // Time of last deletion
-
- uint16_t i_gid; // Block group ID this inode belongs to
- uint16_t i_links_count; // Number of directory entries in this inode
-
- uint32_t i_blocks_count; // Number of blocks in use by this inode
- uint32_t i_flags; // Flags for this inode
- uint32_t i_osd1; // OS specific value #1 (linux support only) (unused)
- uint32_t i_blocks[15]; // Block Pointers
- uint32_t i_generation; // Generation number
-
- /* EXT2 v >= 1.0 */
- uint32_t i_eab; // Extended Attribute Block
- uint32_t i_maj; // If feature bit set, upper 32 bit of file size. Directory ACL if inode is directory
-
- /* EXT2 vAll */
- uint32_t i_frag_block; // Block address of fragment
-
- struct ext2fs_linux i_osd2; // OS specific value #2 (linux support only)
-} __attribute__((packed));
-
-struct ext2fs_file_handle {
- int drive;
- struct part part;
- int size;
- struct ext2fs_inode root_inode;
- struct ext2fs_inode inode;
- uint64_t block_size;
-};
-
-int ext2fs_check_signature(int drive, int partition);
-
-int ext2fs_open(struct ext2fs_file_handle *ret, int drive, int partition, const char *path);
-int ext2fs_read(struct ext2fs_file_handle *file, void *buf, uint64_t loc, uint64_t count);
-
-#endif
diff --git a/src/fs/file.c b/src/fs/file.c
index 038e61c1..f2b2d2c1 100644
--- a/src/fs/file.c
+++ b/src/fs/file.c
@@ -2,7 +2,7 @@
#include <stdint.h>
#include <fs/file.h>
#include <fs/echfs.h>
-#include <fs/ext2fs.h>
+#include <fs/ext2.h>
#include <fs/fat32.h>
#include <lib/blib.h>
@@ -23,15 +23,15 @@ int fopen(struct file_handle *ret, int disk, int partition, const char *filename
return 0;
}
- if (ext2fs_check_signature(disk, partition)) {
- struct ext2fs_file_handle *fd = balloc(sizeof(struct ext2fs_file_handle));
+ if (ext2_check_signature(disk, partition)) {
+ struct ext2_file_handle *fd = balloc(sizeof(struct ext2_file_handle));
- int r = ext2fs_open(fd, disk, partition, filename);
+ int r = ext2_open(fd, disk, partition, filename);
if (r)
return r;
ret->fd = (void *)fd;
- ret->read = (void *)ext2fs_read;
+ ret->read = (void *)ext2_read;
ret->disk = disk;
ret->partition = partition;
ret->size = fd->size;
diff --git a/src/lib/blib.c b/src/lib/blib.c
index 3d0c4af2..1bdf2999 100644
--- a/src/lib/blib.c
+++ b/src/lib/blib.c
@@ -36,7 +36,7 @@ __attribute__((noreturn)) void panic(const char *fmt, ...) {
va_start(args, fmt);
- print("PANIC: ");
+ print("\033[31mPANIC:\033[37;1m\033[40m ");
vprint(fmt, args);
va_end(args);
diff --git a/src/lib/memmap.c b/src/lib/memmap.c
index c77d39c6..594b394b 100644
--- a/src/lib/memmap.c
+++ b/src/lib/memmap.c
@@ -179,4 +179,4 @@ void memmap_alloc_range(uint64_t base, uint64_t length) {
}
panic("Out of memory");
-}
+}
\ No newline at end of file
diff --git a/src/protos/stivale.c b/src/protos/stivale.c
index 908bba0d..0f72574a 100644
--- a/src/protos/stivale.c
+++ b/src/protos/stivale.c
@@ -184,7 +184,9 @@ void stivale_load(char *cmdline, int boot_drive) {
}
struct file_handle f;
- fopen(&f, fd->disk, part, module_file);
+ if (fopen(&f, fd->disk, part, module_file)) {
+ panic("Requested module with path \"%s\" not found!\n", module_file);
+ }
void *module_addr = (void *)(((uint32_t)top_used_addr & 0xfff) ?
((uint32_t)top_used_addr & ~((uint32_t)0xfff)) + 0x1000 :
diff --git a/test/qloader2.cfg b/test/qloader2.cfg
index abfb8d8c..75cbf38d 100644
--- a/test/qloader2.cfg
+++ b/test/qloader2.cfg
@@ -5,7 +5,7 @@ TIMEOUT=3
PROTOCOL=stivale
KERNEL_PARTITION=1
-KERNEL_PATH=/boot/test.elf
+KERNEL_PATH=boot/test.elf
KERNEL_CMDLINE=something
MODULE_PARTITION=1
