From f263f3f4810ae0e6395d1b17ed9d2826475e2e12 Mon Sep 17 00:00:00 2001 From: Marco Cetica Date: Fri, 5 Feb 2021 13:05:05 +0100 Subject: [PATCH] Added initrd driver --- kernel/drivers/Makefile | 2 +- kernel/drivers/initrd.c | 63 +++++++++++++++++++++++++++++++++++++---- kernel/drivers/initrd.h | 4 +-- kernel/kernel_main.c | 24 +++++++++++++++- kernel/mem/multiboot.h | 30 ++++++++++++++++++++ 5 files changed, 113 insertions(+), 10 deletions(-) diff --git a/kernel/drivers/Makefile b/kernel/drivers/Makefile index e731821..de9981f 100644 --- a/kernel/drivers/Makefile +++ b/kernel/drivers/Makefile @@ -1,5 +1,5 @@ OBJS = tty.o gdt.o idt.o isr.o timer.o keyboard.o \ - fs.o cpuid.o + fs.o cpuid.o initrd.o CC = i686-elf-gcc # cross-compiler CFLAGS = -m32 -fno-stack-protector -DDEFAULT_USER=root -DDEFAULT_HOSTNAME=vulcan -ffreestanding -Wall -Wextra -Werror -g -c diff --git a/kernel/drivers/initrd.c b/kernel/drivers/initrd.c index 488856c..84b1ef1 100644 --- a/kernel/drivers/initrd.c +++ b/kernel/drivers/initrd.c @@ -1,26 +1,79 @@ #include "initrd.h" +// Private API to IO operations on dir and files +static uint32_t initrd_read(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer); +static struct dirent *initrd_readdir(fs_node_t *node, uint32_t index); +static fs_node_t *initrd_finddir(fs_node_t *node, uint8_t *name); + // Declare various things initrd_header_t *initrd_header; // Header -initrd_file_header_t *file_header; // List of headers +initrd_file_header_t *file_headers; // List of headers fs_node_t *initrd_root; // Directory root node fs_node_t *initrd_dev; // Directory dev node(/dev) fs_node_t *root_nodes; // List of file nodes -uint32_t nroot_nodes; +uint32_t nroot_nodes; // Number of file nodes struct dirent dirent; fs_node_t *init_ramdisk(uint32_t multiboot_location) { // Initialize main and file headers initrd_header = (initrd_header_t*)multiboot_location; - file_header = (initrd_file_header_t*)(multiboot_location+sizeof(initrd_header_t)); + file_headers = (initrd_file_header_t*)(multiboot_location+sizeof(initrd_header_t)); // Initialize root directory - initrd_root = (fs_node_t*) + initrd_root = (fs_node_t*)kmalloc(sizeof(fs_node_t)); + strcpy(initrd_root->name, "initrd"); + initrd_root->mask = initrd_root->uid = initrd_root->gid = initrd_root->inode = initrd_root->length = 0; + initrd_root->flags = FS_DIRECTORY; + initrd_root->read = 0; + initrd_root->write = 0; + initrd_root->open = 0; + initrd_root->close = 0; + initrd_root->readdir = &initrd_readdir; + initrd_root->finddir = &initrd_finddir; + initrd_root->ptr = 0; + initrd_root->impl = 0; + // Initialize the /dev/ directory + initrd_dev = (fs_node_t*)kmalloc(sizeof(fs_node_t)); + strcpy(initrd_root->name, "dev"); + initrd_root->mask = initrd_root->uid = initrd_root->gid = initrd_root->inode = initrd_root->length = 0; + initrd_root->flags = FS_DIRECTORY; + initrd_root->read = 0; + initrd_root->write = 0; + initrd_root->open = 0; + initrd_root->close = 0; + initrd_root->readdir = &initrd_readdir; + initrd_root->finddir = &initrd_finddir; + initrd_root->ptr = 0; + initrd_root->impl = 0; + + // Add dev and root directories to the ramdisk + // Let us first allocate space for them + root_nodes = (fs_node_t*)kmalloc(sizeof(fs_node_t) *initrd_header->nfiles); + nroot_nodes = initrd_header->nfiles; + // and then, add each file to an inode + for(uint32_t i = 0; i < initrd_header->nfiles; i++) { + file_headers[i].offset += multiboot_location; + // Create an inode for the file + strcpy(root_nodes[i].name, &file_headers[i].name); + root_nodes[i].mask = root_nodes[i].uid = root_nodes[i].gid = 0; + root_nodes[i].length = file_headers[i].length; + root_nodes[i].inode = i; + root_nodes[i].flags = FS_FILE; + root_nodes[i].read = &initrd_read; + root_nodes[i].write = 0; + root_nodes[i].readdir = 0; + root_nodes[i].finddir = 0; + root_nodes[i].open = 0; + root_nodes[i].close = 0; + root_nodes[i].impl = 0; + } + + return initrd_root; } static uint32_t initrd_read(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) { - initrd_file_header_t header = file_header[node->inode]; + initrd_file_header_t header = file_headers[node->inode]; if(offset > header.length) return 0; if(offset+size > header.length) diff --git a/kernel/drivers/initrd.h b/kernel/drivers/initrd.h index 80fd6c1..5a5695e 100644 --- a/kernel/drivers/initrd.h +++ b/kernel/drivers/initrd.h @@ -13,6 +13,7 @@ #include #include "../libc/string.h" +#include "../mem/kheap.h" #include "fs.h" typedef struct { @@ -29,8 +30,5 @@ typedef struct { // Function to initialize initrd, we'll pass the multiboot // module as parameter fs_node_t *init_ramdisk(uint32_t multiboot_location); -static uint32_t initrd_read(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer); -static struct dirent *initrd_readdir(fs_node_t *node, uint32_t index); -static fs_node_t *initrd_finddir(fs_node_t *node, uint8_t *name); #endif diff --git a/kernel/kernel_main.c b/kernel/kernel_main.c index 30f80f6..9f15868 100644 --- a/kernel/kernel_main.c +++ b/kernel/kernel_main.c @@ -10,6 +10,7 @@ #include "drivers/idt.h" #include "drivers/timer.h" #include "drivers/keyboard.h" +#include "drivers/initrd.h" #include "mem/paging.h" #include "mem/kheap.h" #include "mem/multiboot.h" @@ -23,8 +24,22 @@ #define PRTAT printf("\n["); printf_color(" ** ", LIGHT_BROWN, BLACK); printf("]"); // Ugly hack to print "[ * ]" #define PRTER printf("\n["); printf_color(" ERR ", LIGHT_RED, BLACK); printf("]"); // Ugly hack to print "[ ER ]" +uint32_t initrd_setup( struct multiboot *mboot_ptr) { + if(mboot_ptr->mods_count < 0) { // Assert that initrd image is available + PRTER + puts(" - initrd not found!"); + PANIC("Cannot find initrd"); + } -void kernel_main(unsigned long magic, uint32_t addr) { + extern uint32_t placement_addr; + uint32_t initrd_location = *((uint32_t*)mboot_ptr->mods_addr); + uint32_t initrd_end = *(uint32_t*)(mboot_ptr->mods_addr+4); + placement_addr = initrd_end; + + return initrd_location; +} + +void kernel_main(unsigned long magic, uint32_t addr, struct multiboot *mboot_ptr) { // First of all, check if we're booted by a Multiboot-compliant boot loader if(magic != MULTIBOOT2_BOOTLOADER_MAGIC) { PRTER @@ -57,9 +72,16 @@ void kernel_main(unsigned long magic, uint32_t addr) { PRTOK printf(" - Loaded PS/2 driver"); + uint32_t loc = initrd_setup(mboot_ptr); // Setup initial ramdisk + init_paging(); // Initialize paging PRTOK printf(" - Loaded Paging"); + + // Now we can start initrd + fs_root = init_ramdisk(loc); + PRTOK + printf(" - Loaded Initrd"); PRTAT printf(" - Testing heap...\t"); diff --git a/kernel/mem/multiboot.h b/kernel/mem/multiboot.h index 5c31e0a..ece69e3 100644 --- a/kernel/mem/multiboot.h +++ b/kernel/mem/multiboot.h @@ -94,6 +94,36 @@ typedef unsigned short multiboot_uint16_t; typedef unsigned int multiboot_uint32_t; typedef unsigned long long multiboot_uint64_t; +struct multiboot +{ + multiboot_uint32_t flags; + multiboot_uint32_t mem_lower; + multiboot_uint32_t mem_upper; + multiboot_uint32_t boot_device; + multiboot_uint32_t cmdline; + int32_t mods_count; + multiboot_uint32_t mods_addr; + multiboot_uint32_t num; + multiboot_uint32_t size; + multiboot_uint32_t addr; + multiboot_uint32_t shndx; + multiboot_uint32_t mmap_length; + multiboot_uint32_t mmap_addr; + multiboot_uint32_t drives_length; + multiboot_uint32_t drives_addr; + multiboot_uint32_t config_table; + multiboot_uint32_t boot_loader_name; + multiboot_uint32_t apm_table; + multiboot_uint32_t vbe_control_info; + multiboot_uint32_t vbe_mode_info; + multiboot_uint32_t vbe_mode; + multiboot_uint32_t vbe_interface_seg; + multiboot_uint32_t vbe_interface_off; + multiboot_uint32_t vbe_interface_len; +} __attribute__((packed)); + +typedef struct multiboot_header multiboot_header_t; + struct multiboot_header { /* Must be MULTIBOOT_MAGIC - see above. */