diff options
Diffstat (limited to 'kernel/src')
| -rw-r--r-- | kernel/src/boot/multiboot2.c | 18 | ||||
| -rw-r--r-- | kernel/src/devices/disc.c | 32 | ||||
| -rw-r--r-- | kernel/src/fs/ext2.c | 237 | ||||
| -rw-r--r-- | kernel/src/grub.cfg | 2 | ||||
| -rw-r--r-- | kernel/src/libk/list.c | 1 | ||||
| -rw-r--r-- | kernel/src/main.c | 14 |
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(÷d_path, ptr); + } + // add slash + if (i != n) { + char* ptr = (char*)kalloc(sizeof(char) * 2); + ptr[0] = '/'; + ptr[1] = '\0'; + add_to_list_tail(÷d_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;"); } |
