summaryrefslogtreecommitdiff
path: root/kernel/src
diff options
context:
space:
mode:
authorAleksa Vuckovic <aleksav013@gmail.com>2022-08-22 15:12:25 +0200
committerAleksa Vuckovic <aleksav013@gmail.com>2022-08-22 20:34:28 +0200
commit9a54c41ad07ec00316bb8fcdeba51c215446d454 (patch)
tree388f7704a61ff0e103875e3ccbc4435589f6a898 /kernel/src
parent501a706643a056863b6ea214882a2be270966f87 (diff)
ext2 as multiboot2 module
Diffstat (limited to 'kernel/src')
-rw-r--r--kernel/src/boot/multiboot2.c18
-rw-r--r--kernel/src/devices/disc.c32
-rw-r--r--kernel/src/fs/ext2.c237
-rw-r--r--kernel/src/grub.cfg2
-rw-r--r--kernel/src/libk/list.c1
-rw-r--r--kernel/src/main.c14
6 files changed, 302 insertions, 2 deletions
diff --git a/kernel/src/boot/multiboot2.c b/kernel/src/boot/multiboot2.c
index d0b0667..1bb9aac 100644
--- a/kernel/src/boot/multiboot2.c
+++ b/kernel/src/boot/multiboot2.c
@@ -13,6 +13,8 @@
/* https://www.gnu.org/software/grub/manual/multiboot2/html_node/Boot-information-format.html */
+mb2_tag_module* ext2_module;
+
void init_fb(mb2_tag_fb* tag_fb)
{
main_fb.addr = tag_fb->framebuffer_addr;
@@ -42,7 +44,8 @@ void init_mmap(mb2_tag_mmap* tag_mmap)
for (list_t* tmp = mmap; tmp != NULL; tmp = tmp->next) {
mb2_tag_mmap_entry* mmap_entry;
mmap_entry = tmp->data;
- printf("base_addr: 0x%x, length: 0x%x, type: %d\n", mmap_entry->base_addr, mmap_entry->length, mmap_entry->type);
+// printf("base_addr: 0x%x, length: 0x%x, type: %d\n", mmap_entry->base_addr, mmap_entry->length, mmap_entry->type);
+ mmap_entry = mmap_entry;
}
// free data
@@ -54,6 +57,15 @@ void init_mmap(mb2_tag_mmap* tag_mmap)
free_list(&mmap);
}
+void init_module(mb2_tag_module* tag_module)
+{
+ // name is utf-8 encoded string!
+ uint32_t name_size = tag_module->size - sizeof(tag_module) + sizeof(char*);
+ tag_module->name = (char*)kalloc(name_size);
+ memcpy(tag_module->name, tag_module + tag_module->size - name_size, name_size);
+ kfree(tag_module->name);
+}
+
void read_mb2(mb2_tag_header* multiboot_bootinfo, uint32_t multiboot_magic)
{
if (multiboot_magic != MB2_MAGIC) {
@@ -77,6 +89,9 @@ void read_mb2(mb2_tag_header* multiboot_bootinfo, uint32_t multiboot_magic)
case MB2_TAG_MMAP:
tag_mmap = (mb2_tag_mmap*)tag_header;
break;
+ case MB2_TAG_MODULE:
+ ext2_module = (mb2_tag_module*)tag_header;
+ break;
default:
break;
}
@@ -87,4 +102,5 @@ void read_mb2(mb2_tag_header* multiboot_bootinfo, uint32_t multiboot_magic)
init_fb(tag_fb);
init_mmap(tag_mmap);
+ init_module(ext2_module);
}
diff --git a/kernel/src/devices/disc.c b/kernel/src/devices/disc.c
new file mode 100644
index 0000000..8d34473
--- /dev/null
+++ b/kernel/src/devices/disc.c
@@ -0,0 +1,32 @@
+#include <disc.h>
+#include <multiboot2.h>
+#include <libk/string.h>
+#include <paging.h>
+#include <libk/math.h>
+
+#define KERNEL_VMA 0xc0000000
+
+disc_sector_t* disc;
+
+void disc_init()
+{
+ disc = (disc_sector_t*)(uint64_t)ext2_module->mod_start;
+ if (disc == NULL) {
+ printf("Error opening disc\n");
+ }
+
+ uint32_t disc_size = ext2_module->mod_end - ext2_module->mod_start;
+ for (size_t i = 0; i < upper_div(disc_size, PAGE_SIZE) + 1; i++) {
+ map_addr((uint64_t)((char*)disc + i * PAGE_SIZE), (uint64_t)((char*)disc + i * PAGE_SIZE), FLAG_PRESENT | FLAG_WRITABLE | FLAG_HUGE);
+ }
+}
+
+void read_sector(size_t sector_num, disc_sector_t* disc_sector)
+{
+ memcpy(disc_sector, disc + sector_num, SECTOR_SIZE);
+}
+
+void write_sector(size_t sector_num, disc_sector_t* disc_sector)
+{
+ memcpy(disc + sector_num, disc_sector, SECTOR_SIZE);
+}
diff --git a/kernel/src/fs/ext2.c b/kernel/src/fs/ext2.c
new file mode 100644
index 0000000..11f26fc
--- /dev/null
+++ b/kernel/src/fs/ext2.c
@@ -0,0 +1,237 @@
+#include <libk/string.h>
+#include <libk/stdio.h>
+#include <libk/math.h>
+#include <heap.h>
+#include <disc.h>
+#include <ext2.h>
+
+ext2_superblock_t* ext2_superblock;
+
+void read_block(uint32_t block_num, void* block_ptr)
+{
+ uint32_t sectors_per_block = BLOCK_SIZE / SECTOR_SIZE;
+
+ for (size_t i = 0; i < sectors_per_block; i++) {
+ read_sector(block_num * sectors_per_block + i, (disc_sector_t*)block_ptr + i);
+ }
+}
+
+void read_superblock(ext2_superblock_t* superblock)
+{
+ char block[1024];
+ read_sector(2, (disc_sector_t*)block);
+ read_sector(3, (disc_sector_t*)block + 1);
+ memcpy(superblock, block, sizeof(ext2_superblock_t));
+}
+
+void read_bg_desc(uint32_t bg_desc, ext2_bg_desc_t* ext2_bg_desc)
+{
+ uint32_t starting_block_num = BLOCK_SIZE == 1024 ? 2 : 1;
+ uint32_t bg_descs_per_block = BLOCK_SIZE / BG_DESC_SIZE;
+ uint32_t block_num = starting_block_num + bg_desc / bg_descs_per_block;
+ uint32_t block_index = bg_desc % bg_descs_per_block;
+
+ char block[BLOCK_SIZE];
+ read_block(block_num, block);
+ memcpy(ext2_bg_desc, (char*)block + BG_DESC_SIZE * block_index, sizeof(ext2_bg_desc_t));
+}
+
+void read_inode(uint32_t starting_block_num, uint32_t inode_index, ext2_inode_t* ext2_inode)
+{
+ uint32_t block_num = starting_block_num + inode_index / INODES_PER_BLOCK;
+ uint32_t block_index = inode_index % INODES_PER_BLOCK;
+
+ char block[BLOCK_SIZE];
+ read_block(block_num, block);
+ memcpy(ext2_inode, (char*)block + block_index * INODE_SIZE, sizeof(ext2_inode_t));
+}
+
+list_t* directory_to_entries(uint32_t inode)
+{
+ list_t* list = NULL;
+
+ uint32_t bg_desc = (inode - 1) / ext2_superblock->inodes_per_group;
+ uint32_t inode_index = (inode - 1) % ext2_superblock->inodes_per_group;
+
+ // block group descriptor
+ ext2_bg_desc_t* ext2_bg_desc;
+ ext2_bg_desc = (ext2_bg_desc_t*)kalloc(sizeof(ext2_bg_desc_t));
+ read_bg_desc(bg_desc, ext2_bg_desc);
+
+ // inode table
+ ext2_inode_t* ext2_inode;
+ ext2_inode = (ext2_inode_t*)kalloc(sizeof(ext2_inode_t));
+ read_inode(ext2_bg_desc->inode_block_address, inode_index, ext2_inode);
+
+ // if it is not directory
+ if (!(ext2_inode->type_perms & TYPE_DIR))
+ return list;
+
+ // read inode contents
+ for (size_t i = 0; i < 12; i++) {
+ if (ext2_inode->dbp[i] == 0)
+ break;
+
+ // get block
+ char block[BLOCK_SIZE];
+ read_block(ext2_inode->dbp[i], block);
+
+ // parse block
+ for (size_t block_offset = 0; block_offset < BLOCK_SIZE;) {
+ // get dentry header
+ ext2_dentry_t* ext2_dentry;
+ ext2_dentry = (ext2_dentry_t*)kalloc(sizeof(ext2_dentry_t));
+ memcpy(ext2_dentry, (char*)block + block_offset, sizeof(ext2_dentry_t) - sizeof(char*));
+
+ // get dentry name
+ ext2_dentry->name = (char*)kalloc(ext2_dentry->name_length_lower);
+ memcpy(ext2_dentry->name, (char*)block + block_offset + sizeof(ext2_dentry_t) - sizeof(char*), ext2_dentry->name_length_lower);
+
+ if (inode == 0) {
+ kfree(ext2_dentry->name);
+ kfree(ext2_dentry);
+ break;
+ }
+
+ // put dentry in list
+ add_to_list_head(&list, ext2_dentry);
+
+ // offset
+ block_offset += ext2_dentry->size;
+ }
+ }
+
+
+ kfree(ext2_bg_desc);
+ kfree(ext2_inode);
+
+ return list;
+}
+
+char* files_to_buffer(uint32_t inode)
+{
+ uint32_t bg_desc = (inode - 1) / ext2_superblock->inodes_per_group;
+ uint32_t inode_index = (inode - 1) % ext2_superblock->inodes_per_group;
+
+ // block group descriptor
+ ext2_bg_desc_t* ext2_bg_desc;
+ ext2_bg_desc = (ext2_bg_desc_t*)kalloc(sizeof(ext2_bg_desc_t));
+ read_bg_desc(bg_desc, ext2_bg_desc);
+
+ // inode table
+ ext2_inode_t* ext2_inode;
+ ext2_inode = (ext2_inode_t*)kalloc(sizeof(ext2_inode_t));
+ read_inode(ext2_bg_desc->inode_block_address, inode_index, ext2_inode);
+
+ char* data;
+
+ uint32_t size = ext2_inode->size_lower;
+ data = (char*)kalloc(size);
+
+ uint32_t block_num = upper_div(size, BLOCK_SIZE);
+ for (size_t i = 0; i < min(block_num, 12); i++) {
+ char block[BLOCK_SIZE];
+ read_block(ext2_inode->dbp[i], block);
+ memcpy(data + i * BLOCK_SIZE, block, size >= (i + 1) * BLOCK_SIZE ? BLOCK_SIZE : size % BLOCK_SIZE);
+ }
+
+ return data;
+}
+
+list_t* path_to_list(const char* path)
+{
+ size_t i, j;
+ list_t* divided_path = NULL;
+
+ size_t n = strlen(path);
+ for (i = 0, j = 0; i <= n; i++) {
+ if (i == n || path[i] == '/') {
+ // add data before slash
+ if (i != j) {
+ char* ptr = (char*)kalloc(sizeof(char) * (uint32_t)(i - j + 1));
+ memcpy(ptr, path + j, i - j);
+ ptr[i - j] = '\0';
+ add_to_list_tail(&divided_path, ptr);
+ }
+ // add slash
+ if (i != n) {
+ char* ptr = (char*)kalloc(sizeof(char) * 2);
+ ptr[0] = '/';
+ ptr[1] = '\0';
+ add_to_list_tail(&divided_path, ptr);
+ j = i + 1;
+ }
+ }
+ }
+
+ return divided_path;
+}
+
+// only supports absolute path for now
+uint32_t path_to_inode(const char* path)
+{
+ uint32_t inode = 0;
+ list_t* divided_path = path_to_list(path);
+
+ list_t* curr_dir = divided_path;
+
+ // first entry is /
+ curr_dir = curr_dir->next;
+ inode = 2;
+
+ while (curr_dir != NULL) {
+ // list of dentry
+ list_t* list = directory_to_entries(inode);
+
+ // check if inode is actually a dir
+ if (list == NULL) {
+ printf("not a directory\n");
+ return 0;
+ }
+
+ // iterate through all direntries
+ uint8_t ind = 1;
+ for (list_t* curr_list = list; curr_list != NULL; curr_list = curr_list->next) {
+ ext2_dentry_t* ext2_dentry;
+ ext2_dentry = curr_list->data;
+
+ if (!memcmp(curr_dir->data, ext2_dentry->name)) {
+ ind = 0;
+ inode = ext2_dentry->inode;
+ break;
+ }
+ }
+
+ // if dir not found error
+ if (ind) {
+ printf("file/dir not found\n");
+ return 0;
+ }
+
+ // next dir
+ curr_dir = curr_dir->next;
+ if (curr_dir != NULL)
+ curr_dir = curr_dir->next;
+ }
+
+ return inode;
+}
+
+void ls(uint32_t inode)
+{
+ list_t* dir = directory_to_entries(inode);
+
+ printf("ls dir with inode %d:\n", inode);
+ for (list_t* tmp = dir; tmp != NULL; tmp = tmp->next) {
+ ext2_dentry_t* ext2_dentry;
+ ext2_dentry = tmp->data;
+ printf("inode: %d, name: %s\n", ext2_dentry->inode, ext2_dentry->name);
+ }
+}
+
+void print(uint32_t inode)
+{
+ printf("contents of inode %d:\n", inode);
+ char *p = files_to_buffer(inode);
+ printf("%s", p);
+}
diff --git a/kernel/src/grub.cfg b/kernel/src/grub.cfg
index 05a13f7..89d3ddf 100644
--- a/kernel/src/grub.cfg
+++ b/kernel/src/grub.cfg
@@ -4,5 +4,5 @@ set default=0
insmod efi_gop
menuentry "mykernel64" {
multiboot2 /boot/kernel.bin
- boot
+ module2 /modules/ext2.img ext2
}
diff --git a/kernel/src/libk/list.c b/kernel/src/libk/list.c
index 5f75845..be2e4e5 100644
--- a/kernel/src/libk/list.c
+++ b/kernel/src/libk/list.c
@@ -14,6 +14,7 @@ void add_to_list_tail(list_t** ptr, void* data)
{
list_t* node = (list_t*)kalloc(sizeof(list_t));
node->data = data;
+ node->next = NULL;
if (*ptr == NULL) {
*ptr = node;
diff --git a/kernel/src/main.c b/kernel/src/main.c
index a3303e4..ce307e2 100644
--- a/kernel/src/main.c
+++ b/kernel/src/main.c
@@ -9,6 +9,8 @@
#include <libk/stdio.h>
#include <libk/string.h>
#include <libk/math.h>
+#include <disc.h>
+#include <ext2.h>
int kernel_main(mb2_tag_header* multiboot_bootinfo, uint32_t multiboot_magic);
int kernel_main(mb2_tag_header* multiboot_bootinfo, uint32_t multiboot_magic)
@@ -18,6 +20,18 @@ int kernel_main(mb2_tag_header* multiboot_bootinfo, uint32_t multiboot_magic)
init_heap();
read_mb2(multiboot_bootinfo, multiboot_magic);
+ // init disc
+ disc_init();
+
+ // read superblock
+ ext2_superblock = (ext2_superblock_t*)kalloc(sizeof(ext2_superblock_t));
+ read_superblock(ext2_superblock);
+
+ ls(path_to_inode("/"));
+
+ // free superblock
+ kfree(ext2_superblock);
+
for(;;) {
__asm__ volatile ("hlt;");
}