From 21260c345cb5fe4c25837390772ac806364e9b87 Mon Sep 17 00:00:00 2001 From: Kevin Lange Date: Fri, 28 Jan 2011 23:09:09 -0600 Subject: [PATCH] [ext2] Read ext2 initial ramdisk image and print out a file's content --- Makefile | 2 +- core/Makefile | 7 +- core/fs/Makefile | 10 +++ core/fs/ext2_initrd.c | 4 ++ include/ext2.h | 152 ++++++++++++++++++++++++++++++++++++++++++ include/system.h | 2 + main.c | 78 +++++++++++++++++++--- 7 files changed, 243 insertions(+), 12 deletions(-) create mode 100644 core/fs/Makefile create mode 100644 core/fs/ext2_initrd.c create mode 100644 include/ext2.h diff --git a/Makefile b/Makefile index 92ae9c30..bf446589 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ run: bootdisk.img qemu -fda bootdisk.img kernel: start.o link.ld main.o core - ${LD} -T link.ld -o kernel *.o core/*.o + ${LD} -T link.ld -o kernel *.o core/*.o core/fs/*.o %.o: %.c ${CC} ${CFLAGS} -I./include -c -o $@ $< diff --git a/core/Makefile b/core/Makefile index 34b3c531..6bf95ff0 100644 --- a/core/Makefile +++ b/core/Makefile @@ -1,10 +1,13 @@ include ../Makefile.inc -.PHONY: all clean install core +.PHONY: all clean install fs -all: system.o multiboot.o gdt.o idt.o irq.o isrs.o kbd.o kprintf.o timer.o vga.o mem.o panic.o alloc.o vfs.o +all: system.o multiboot.o gdt.o idt.o irq.o isrs.o kbd.o kprintf.o timer.o vga.o mem.o panic.o alloc.o vfs.o fs %.o: %.c ${CC} ${CFLAGS} -I../include -c -o $@ $< +fs: + cd fs; ${MAKE} ${MFLAGS} + clean: -rm -f *.o diff --git a/core/fs/Makefile b/core/fs/Makefile new file mode 100644 index 00000000..740915cc --- /dev/null +++ b/core/fs/Makefile @@ -0,0 +1,10 @@ +include ../../Makefile.inc +.PHONY: all clean install + +all: ext2_initrd.o + +%.o: %.c + ${CC} ${CFLAGS} -I../../include -c -o $@ $< + +clean: + -rm -f *.o diff --git a/core/fs/ext2_initrd.c b/core/fs/ext2_initrd.c new file mode 100644 index 00000000..1d8849df --- /dev/null +++ b/core/fs/ext2_initrd.c @@ -0,0 +1,4 @@ +#include +#include + + diff --git a/include/ext2.h b/include/ext2.h new file mode 100644 index 00000000..06bd5857 --- /dev/null +++ b/include/ext2.h @@ -0,0 +1,152 @@ +#ifndef EXT2_H +#define EXT2_h + +#include +#include + +#define EXT2_SUPER_MAGIC 0xEF53 + +struct ext2_superblock { + 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[16]; + + 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)); + +typedef struct ext2_superblock ext2_superblock_t; + +struct ext2_bgdescriptor { + uint32_t block_bitmap; + uint32_t inode_bitmap; + uint32_t inode_table; + uint16_t free_blocks_count; + uint16_t free_inodes_count; + uint16_t used_dirs_count; + uint16_t pad; + uint8_t reserved[12]; +} __attribute__((packed)); + +typedef struct ext2_bgdescriptor ext2_bgdescriptor_t; + +/* File Types */ +#define EXT2_S_IFSOCK 0xC000 +#define EXT2_S_IFLNK 0xA000 +#define EXT2_S_IFREG 0x8000 +#define EXT2_S_IFBLK 0x6000 +#define EXT2_S_IFDIR 0x4000 +#define EXT2_S_IFCHR 0x2000 +#define EXT2_S_IFIFO 0x1000 + +/* setuid, etc. */ +#define EXT2_S_ISUID 0x0800 +#define EXT2_S_ISGID 0x0400 +#define EXT2_S_ISVTX 0x0200 + +/* rights */ +#define EXT2_S_IRUSR 0x0100 +#define EXT2_S_IWUSR 0x0080 +#define EXT2_S_IXUSR 0x0040 +#define EXT2_S_IRGRP 0x0020 +#define EXT2_S_IWGRP 0x0010 +#define EXT2_S_IXGRP 0x0008 +#define EXT2_S_IROTH 0x0004 +#define EXT2_S_IWOTH 0x0002 +#define EXT2_S_IXOTH 0x0001 + + +struct ext2_inodetable { + uint16_t mode; + uint16_t uid; + uint32_t size; + uint32_t atime; + uint32_t ctime; + uint32_t mtime; + uint32_t dtime; + uint16_t gid; + uint16_t links_count; + uint32_t blocks; + uint32_t flags; + uint32_t osd1; + uint32_t block[15]; + uint32_t generation; + uint32_t file_acl; + uint32_t dir_acl; + uint32_t faddr; + uint8_t osd2[12]; +} __attribute__((packed)); + +typedef struct ext2_inodetable ext2_inodetable_t; + +struct ext2_dir { + uint32_t inode; + uint16_t rec_len; + uint8_t name_len; + uint8_t file_type; + char name; /* Actually a set of characters, at most 255 bytes */ +} __attribute__((packed)); + +typedef struct ext2_dir ext2_dir_t; + +#endif diff --git a/include/system.h b/include/system.h index e1d46633..e17939e5 100644 --- a/include/system.h +++ b/include/system.h @@ -8,7 +8,9 @@ typedef unsigned long uintptr_t; typedef long size_t; typedef unsigned int uint32_t; +typedef unsigned short uint16_t; typedef unsigned char uint8_t; +typedef unsigned long long uint64_t; /* Unimportant Kernel Strings */ #define KERNEL_UNAME "ToAruOS" diff --git a/main.c b/main.c index 0ced0ebc..89a4b53c 100644 --- a/main.c +++ b/main.c @@ -31,6 +31,7 @@ #include #include +#include /* * kernel entry point @@ -88,18 +89,77 @@ main(struct multiboot *mboot_ptr) { /* Print multiboot information */ dump_multiboot(mboot_ptr); - kprintf("Will begin dumping from second kB of module 1 in a second.\n"); - timer_wait(100); - kprintf("Dumping.\n"); - uint32_t i; uint32_t module_start = *((uint32_t*)mboot_ptr->mods_addr); uint32_t module_end = *(uint32_t*)(mboot_ptr->mods_addr+4); - for (i = module_start + 1024; i < module_end; ++i) { - kprintf("%c ", *((char *)i)); - if (i % 35 == 0) { kprintf("\n"); } - timer_wait(1); - } + ext2_superblock_t * superblock = (ext2_superblock_t *)(module_start + 1024); + kprintf("Magic is 0x%x\n", (int)superblock->magic); + assert(superblock->magic == EXT2_SUPER_MAGIC); + + kprintf("Partition has %d inodes and %d blocks.\n", superblock->inodes_count, superblock->blocks_count); + kprintf("%d blocks reserved for root\n", superblock->r_blocks_count); + kprintf("%d blocks free\n", superblock->free_blocks_count); + kprintf("%d free inodes\n", superblock->free_inodes_count); + kprintf("Blocks contain %d bytes\n", 1024 << superblock->log_block_size); + kprintf("Fragments contain %d bytes\n", 1024 << superblock->log_frag_size); + kprintf("I am at block id: %d (should be 1 if this is a 1KB block)\n", superblock->first_data_block); + kprintf("There are %d blocks in a group\n", superblock->blocks_per_group); + kprintf("There are %d fragments in a group\n", superblock->frags_per_group); + kprintf("There are %d inodes in a group\n", superblock->inodes_per_group); + kprintf("Last mount: 0x%x\n", superblock->mtime); + kprintf("Last write: 0x%x\n", superblock->wtime); + kprintf("Mounts since verification: %d\n", superblock->mnt_count); + kprintf("Must be verified in %d mounts\n", superblock->max_mnt_count - superblock->mnt_count); + kprintf("Inodes are %d bytes\n", (int)superblock->inode_size); + + ext2_bgdescriptor_t * blockgroups = (ext2_bgdescriptor_t *)(module_start + 1024 + 1024); + kprintf("First block group has %d free blocks, %d free inodes, %d used dirs\n", + blockgroups->free_blocks_count, + blockgroups->free_inodes_count, + blockgroups->used_dirs_count); + + ext2_inodetable_t * inodetable = (ext2_inodetable_t *)(module_start + (1024 << superblock->log_block_size) * blockgroups->inode_table); + uint32_t i; + for (i = 0; i < superblock->inodes_per_group; ++i) { + ext2_inodetable_t * inode = (ext2_inodetable_t *)((int)inodetable + (int)superblock->inode_size * i); + if (inode->block[0] == 0) + continue; + kprintf("Inode %d starts at block %d,%d and is %d bytes (%d blocks). ", i, inode->block[0], inode->block[1], inode->size, inode->blocks); + if (inode->mode & EXT2_S_IFDIR) { + kprintf("is a directory\n"); + kprintf("File listing:\n"); + uint32_t dir_offset; + dir_offset = 0; + while (dir_offset < inode->size) { + ext2_dir_t * d_ent = (ext2_dir_t *)(module_start + (1024 << superblock->log_block_size) * inode->block[0] + dir_offset); + unsigned char * name = malloc(sizeof(unsigned char) * (d_ent->name_len + 1)); + memcpy(name, &d_ent->name, d_ent->name_len); + name[d_ent->name_len] = '\0'; + kprintf("[%d] %s [%d]\n", dir_offset, name, d_ent->inode); + if (name[0] == 'h' && + name[1] == 'e' && + name[2] == 'l' && + name[3] == 'l' && + name[4] == 'o') { + kprintf("Found a file to read.\n"); + ext2_inodetable_t * inode_f = (ext2_inodetable_t *)((int)inodetable + (int)superblock->inode_size * (d_ent->inode -1)); + kprintf("Going to print %d bytes from block %d\n", inode_f->size, inode_f->block[0]); + unsigned char * file_pointer = (unsigned char *)(module_start + (1024 << superblock->log_block_size) * inode_f->block[0]); + unsigned int file_offset; + for (file_offset = 0; file_offset < inode_f->size; ++file_offset) { + kprintf("%c", file_pointer[file_offset]); + } + } + + free(name); + dir_offset += d_ent->rec_len; + if (d_ent->inode == 0) + break; + } + break; + } + kprintf("\n"); + }; return 0; }