From 118898807865ba11f5d7754f6f0572a0403f8512 Mon Sep 17 00:00:00 2001 From: Marvin Borner Date: Wed, 30 Oct 2019 16:02:10 +0100 Subject: Started implementation of initrd based vfs --- src/kernel/acpi/acpi.c | 6 +-- src/kernel/boot.asm | 7 ++- src/kernel/commands/command.c | 2 +- src/kernel/fs/initrd.c | 104 ++++++++++++++++++++++++++++++++++++++++++ src/kernel/fs/initrd.h | 20 ++++++++ src/kernel/fs/vfs.c | 43 +++++++++++++++++ src/kernel/fs/vfs.h | 65 ++++++++++++++++++++++++++ src/kernel/graphics/vesa.c | 2 +- src/kernel/interrupts/idt.c | 2 +- src/kernel/kernel.c | 14 +++++- src/kernel/lib/lib.h | 6 +-- src/kernel/lib/memory.c | 6 +-- src/kernel/mutliboot.h | 47 +++++++++++++++++++ src/kernel/paging/paging.c | 2 - src/kernel/system.h | 5 ++ 15 files changed, 315 insertions(+), 16 deletions(-) create mode 100644 src/kernel/fs/initrd.c create mode 100644 src/kernel/fs/initrd.h create mode 100644 src/kernel/fs/vfs.c create mode 100644 src/kernel/fs/vfs.h create mode 100644 src/kernel/mutliboot.h (limited to 'src/kernel') diff --git a/src/kernel/acpi/acpi.c b/src/kernel/acpi/acpi.c index 24da496..e0d260b 100644 --- a/src/kernel/acpi/acpi.c +++ b/src/kernel/acpi/acpi.c @@ -24,7 +24,7 @@ unsigned int *acpi_check_rsd_ptr(unsigned int *ptr) { char check = 0; unsigned int i; - if (memory_compare(sig, rsdp, 8) == 0) { + if (memcmp(sig, rsdp, 8) == 0) { bptr = (char *) ptr; for (i = 0; i < sizeof(struct RSDPtr); i++) { check += *bptr; @@ -62,7 +62,7 @@ unsigned int *acpi_get_rsd_ptr() { } int acpi_check_header(unsigned int *ptr, char *sig) { - if (memory_compare(ptr, sig, 4) == 0) { + if (memcmp(ptr, sig, 4) == 0) { char *checkPtr = (char *) ptr; int len = *(ptr + 1); char check = 0; @@ -122,7 +122,7 @@ int acpi_install() { char *S5Addr = (char *) facp->DSDT + 36; int dsdt_length = *(facp->DSDT + 1) - 36; while (0 < dsdt_length--) { - if (memory_compare(S5Addr, "_S5_", 4) == 0) + if (memcmp(S5Addr, "_S5_", 4) == 0) break; S5Addr++; } diff --git a/src/kernel/boot.asm b/src/kernel/boot.asm index d533307..fad05ff 100644 --- a/src/kernel/boot.asm +++ b/src/kernel/boot.asm @@ -30,8 +30,13 @@ mboot: dd start ; Endless loop +extern kernel_main stublet: - extern kernel_main + ; Load multiboot information + push esp + push ebx + + cli call kernel_main jmp $ diff --git a/src/kernel/commands/command.c b/src/kernel/commands/command.c index 2334219..1118b29 100644 --- a/src/kernel/commands/command.c +++ b/src/kernel/commands/command.c @@ -8,7 +8,7 @@ int32_t starts_with(const char *a, const char *b) { size_t length_pre = strlen(b); size_t length_main = strlen(a); - return length_main < length_pre ? 0 : memory_compare(b, a, length_pre) == 0; + return length_main < length_pre ? 0 : memcmp(b, a, length_pre) == 0; } void exec_command(char *command) { diff --git a/src/kernel/fs/initrd.c b/src/kernel/fs/initrd.c new file mode 100644 index 0000000..b291801 --- /dev/null +++ b/src/kernel/fs/initrd.c @@ -0,0 +1,104 @@ +#include +#include +#include +#include +#include + +initrd_header_t *initrd_header; +initrd_file_header_t *file_headers; +fs_node_t *initrd_root; +fs_node_t *initrd_dev; +fs_node_t *root_nodes; +int nroot_nodes; + +struct dirent dirent; + +static uint32_t initrd_read(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) { + initrd_file_header_t header = file_headers[node->inode]; + if (offset > header.length) + return 0; + if (offset + size > header.length) + size = header.length - offset; + memcpy(buffer, (uint8_t *) (header.offset + offset), size); + return size; +} + +static struct dirent *initrd_readdir(fs_node_t *node, uint32_t index) { + if (node == initrd_root && index == 0) { + strcpy(dirent.name, "dev"); + dirent.name[3] = 0; + dirent.ino = 0; + return &dirent; + } + + if (index - 1 >= nroot_nodes) + return 0; + strcpy(dirent.name, root_nodes[index - 1].name); + dirent.name[strlen(root_nodes[index - 1].name)] = 0; + dirent.ino = root_nodes[index - 1].inode; + return &dirent; +} + +static fs_node_t *initrd_finddir(fs_node_t *node, char *name) { + if (node == initrd_root && + !strcmp(name, "dev")) + return initrd_dev; + + int i; + for (i = 0; i < nroot_nodes; i++) + if (!strcmp(name, root_nodes[i].name)) + return &root_nodes[i]; + return 0; +} + +fs_node_t *initialise_initrd(uint32_t location) { + initrd_header = (initrd_header_t *) location; + file_headers = (initrd_file_header_t *) (location + sizeof(initrd_header_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; + + initrd_dev = (fs_node_t *) kmalloc(sizeof(fs_node_t)); + strcpy(initrd_dev->name, "dev"); + initrd_dev->mask = initrd_dev->uid = initrd_dev->gid = initrd_dev->inode = initrd_dev->length = 0; + initrd_dev->flags = FS_DIRECTORY; + initrd_dev->read = 0; + initrd_dev->write = 0; + initrd_dev->open = 0; + initrd_dev->close = 0; + initrd_dev->readdir = &initrd_readdir; + initrd_dev->finddir = &initrd_finddir; + initrd_dev->ptr = 0; + initrd_dev->impl = 0; + + root_nodes = (fs_node_t *) kmalloc(sizeof(fs_node_t) * initrd_header->nfiles); + nroot_nodes = initrd_header->nfiles; + + for (int i = 0; i < initrd_header->nfiles; i++) { + file_headers[i].offset += location; + + 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; +} diff --git a/src/kernel/fs/initrd.h b/src/kernel/fs/initrd.h new file mode 100644 index 0000000..10dec22 --- /dev/null +++ b/src/kernel/fs/initrd.h @@ -0,0 +1,20 @@ +#ifndef MELVIX_INITRD_H +#define MELVIX_INITRD_H + +#include +#include + +typedef struct { + uint32_t nfiles; +} initrd_header_t; + +typedef struct { + uint8_t magic; + int8_t name[64]; + uint32_t offset; + uint32_t length; +} initrd_file_header_t; + +fs_node_t *initialise_initrd(uint32_t location); + +#endif diff --git a/src/kernel/fs/vfs.c b/src/kernel/fs/vfs.c new file mode 100644 index 0000000..5591a60 --- /dev/null +++ b/src/kernel/fs/vfs.c @@ -0,0 +1,43 @@ +#include + +fs_node_t *fs_root = 0; + +uint32_t read_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) { + if (node->read != 0) + return node->read(node, offset, size, buffer); + else + return 0; +} + +uint32_t write_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) { + if (node->write != 0) + return node->write(node, offset, size, buffer); + else + return 0; +} + +void open_fs(fs_node_t *node, uint8_t read, uint8_t write) { + if (node->open != 0) + return node->open(node); +} + +void close_fs(fs_node_t *node) { + if (node->close != 0) + return node->close(node); +} + +struct dirent *readdir_fs(fs_node_t *node, uint32_t index) { + if ((node->flags & 0x7) == FS_DIRECTORY && + node->readdir != 0) + return node->readdir(node, index); + else + return 0; +} + +fs_node_t *finddir_fs(fs_node_t *node, char *name) { + if ((node->flags & 0x7) == FS_DIRECTORY && + node->finddir != 0) + return node->finddir(node, name); + else + return 0; +} diff --git a/src/kernel/fs/vfs.h b/src/kernel/fs/vfs.h new file mode 100644 index 0000000..5a72861 --- /dev/null +++ b/src/kernel/fs/vfs.h @@ -0,0 +1,65 @@ +#ifndef MELVIX_VFS_H +#define MELVIX_VFS_H + +#include + +#define FS_FILE 0x01 +#define FS_DIRECTORY 0x02 +#define FS_CHARDEVICE 0x03 +#define FS_BLOCKDEVICE 0x04 +#define FS_PIPE 0x05 +#define FS_SYMLINK 0x06 +#define FS_MOUNTPOINT 0x08 + +struct fs_node; + +typedef uint32_t (*read_type_t)(struct fs_node *, uint32_t, uint32_t, uint8_t *); + +typedef uint32_t (*write_type_t)(struct fs_node *, uint32_t, uint32_t, uint8_t *); + +typedef void (*open_type_t)(struct fs_node *); + +typedef void (*close_type_t)(struct fs_node *); + +typedef struct dirent *(*readdir_type_t)(struct fs_node *, uint32_t); + +typedef struct fs_node *(*finddir_type_t)(struct fs_node *, char *name); + +typedef struct fs_node { + char name[128]; + uint32_t mask; + uint32_t uid; + uint32_t gid; + uint32_t flags; + uint32_t inode; + uint32_t length; + uint32_t impl; + read_type_t read; + write_type_t write; + open_type_t open; + close_type_t close; + readdir_type_t readdir; + finddir_type_t finddir; + struct fs_node *ptr; +} fs_node_t; + +struct dirent { + char name[128]; + uint32_t ino; +}; + +extern fs_node_t *fs_root; + +uint32_t read_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer); + +uint32_t write_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer); + +void open_fs(fs_node_t *node, uint8_t read, uint8_t write); + +void close_fs(fs_node_t *node); + +struct dirent *readdir_fs(fs_node_t *node, uint32_t index); + +fs_node_t *finddir_fs(fs_node_t *node, char *name); + +#endif diff --git a/src/kernel/graphics/vesa.c b/src/kernel/graphics/vesa.c index 8347c56..94f53c6 100644 --- a/src/kernel/graphics/vesa.c +++ b/src/kernel/graphics/vesa.c @@ -309,7 +309,7 @@ void vesa_keyboard_char(char ch) { } else if (ch == '\n') { vesa_draw_char(ch); exec_command(text); - memory_set(text, 0, sizeof(text)); + memset(text, 0, sizeof(text)); // terminal_scroll(); } else if (ch >= ' ') { vesa_draw_char(ch); diff --git a/src/kernel/interrupts/idt.c b/src/kernel/interrupts/idt.c index 26489c4..5f92294 100644 --- a/src/kernel/interrupts/idt.c +++ b/src/kernel/interrupts/idt.c @@ -39,7 +39,7 @@ void idt_install() { idtp.base = &idt; // Clear IDT by setting memory cells to 0 - memory_set(&idt, 0, sizeof(struct idt_entry) * 256); + memset(&idt, 0, sizeof(struct idt_entry) * 256); idt_load(); vga_log("Installed Interrupt Descriptor Table", 6); diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index 75867a8..cba4f6e 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -6,6 +6,8 @@ #include #include #include +#include +#include void init() { vga_log("Installing basic features of Melvix...", 0); @@ -25,9 +27,19 @@ void init() { asm volatile ("sti"); } -void kernel_main(void) { +void kernel_main(struct multiboot *mboot_ptr) { init(); + info("Kernel size in KiB: "); + vesa_draw_number((int) end >> 10); + + assert(mboot_ptr->mods_count > 0); + uint32_t initrd_location = *((uint32_t *) mboot_ptr->mods_addr); + uint32_t initrd_end = *(uint32_t *) (mboot_ptr->mods_addr + 4); + // Don't trample our module with placement accesses, please! + // placement_address = initrd_end; + fs_root = initialise_initrd(initrd_location); + // asm volatile ("div %0" :: "r"(0)); // Exception testing x/0 loop: asm volatile ("hlt"); diff --git a/src/kernel/lib/lib.h b/src/kernel/lib/lib.h index de09e0f..420dd5b 100644 --- a/src/kernel/lib/lib.h +++ b/src/kernel/lib/lib.h @@ -39,7 +39,7 @@ void strcpy(char *dest, const char *src); * @param count The number of bytes to be copied (src) * @return The modified dest pointer */ -void *memory_copy(void *dest, const void *src, size_t count); +void *memcpy(void *dest, const void *src, size_t count); /** * Replace n bytes of dest by val @@ -48,7 +48,7 @@ void *memory_copy(void *dest, const void *src, size_t count); * @param count The number of times val should replace dest entry * @return The modified dest pointer */ -void *memory_set(void *dest, char val, size_t count); +void *memset(void *dest, char val, size_t count); /** * Compare the first n bytes of a and b @@ -57,6 +57,6 @@ void *memory_set(void *dest, char val, size_t count); * @param size The number of bytes to be compared * @return -1 if a < b, 0 if a = b and 1 if a > b */ -int memory_compare(const void *a_ptr, const void *b_ptr, size_t size); +int memcmp(const void *a_ptr, const void *b_ptr, size_t size); #endif diff --git a/src/kernel/lib/memory.c b/src/kernel/lib/memory.c index 6ec4ed9..a030c9a 100644 --- a/src/kernel/lib/memory.c +++ b/src/kernel/lib/memory.c @@ -1,19 +1,19 @@ #include -void *memory_copy(void *dest, const void *src, size_t count) { +void *memcpy(void *dest, const void *src, size_t count) { const char *sp = (const char *) src; char *dp = (char *) dest; for (; count != 0; count--) *dp++ = *sp++; return dest; } -void *memory_set(void *dest, char val, size_t count) { +void *memset(void *dest, char val, size_t count) { char *temp = (char *) dest; for (; count != 0; count--) *temp++ = val; return dest; } -int memory_compare(const void *a_ptr, const void *b_ptr, size_t size) { +int memcmp(const void *a_ptr, const void *b_ptr, size_t size) { const unsigned char *a = (const unsigned char *) a_ptr; const unsigned char *b = (const unsigned char *) b_ptr; for (size_t i = 0; i < size; i++) { diff --git a/src/kernel/mutliboot.h b/src/kernel/mutliboot.h new file mode 100644 index 0000000..683f95f --- /dev/null +++ b/src/kernel/mutliboot.h @@ -0,0 +1,47 @@ +#ifndef MELVIX_MUTLIBOOT_H +#define MELVIX_MUTLIBOOT_H + +#include + +#define MULTIBOOT_FLAG_MEM 0x001 +#define MULTIBOOT_FLAG_DEVICE 0x002 +#define MULTIBOOT_FLAG_CMDLINE 0x004 +#define MULTIBOOT_FLAG_MODS 0x008 +#define MULTIBOOT_FLAG_AOUT 0x010 +#define MULTIBOOT_FLAG_ELF 0x020 +#define MULTIBOOT_FLAG_MMAP 0x040 +#define MULTIBOOT_FLAG_CONFIG 0x080 +#define MULTIBOOT_FLAG_LOADER 0x100 +#define MULTIBOOT_FLAG_APM 0x200 +#define MULTIBOOT_FLAG_VBE 0x400 + +struct multiboot { + uint32_t flags; + uint32_t mem_lower; + uint32_t mem_upper; + uint32_t boot_device; + uint32_t cmdline; + uint32_t mods_count; + uint32_t mods_addr; + uint32_t num; + uint32_t size; + uint32_t addr; + uint32_t shndx; + uint32_t mmap_length; + uint32_t mmap_addr; + uint32_t drives_length; + uint32_t drives_addr; + uint32_t config_table; + uint32_t boot_loader_name; + uint32_t apm_table; + uint32_t vbe_control_info; + uint32_t vbe_mode_info; + uint32_t vbe_mode; + uint32_t vbe_interface_seg; + uint32_t vbe_interface_off; + uint32_t vbe_interface_len; +} __attribute__((packed)); + +typedef struct multiboot_header multiboot_header_t; + +#endif diff --git a/src/kernel/paging/paging.c b/src/kernel/paging/paging.c index 02fc253..bb3b1df 100644 --- a/src/kernel/paging/paging.c +++ b/src/kernel/paging/paging.c @@ -2,8 +2,6 @@ #include #include -extern void *end; - uint32_t page_directory[1024] __attribute__((aligned(4096))); uint32_t page_tables[1024][1024] __attribute__((aligned(4096))); diff --git a/src/kernel/system.h b/src/kernel/system.h index e6888fc..d431a9e 100644 --- a/src/kernel/system.h +++ b/src/kernel/system.h @@ -1,6 +1,11 @@ #ifndef MELVIX_SYSTEM_H #define MELVIX_SYSTEM_H +/** + * The kernel end + */ +extern void *end; + /** * Initialize the basic features of the OS */ -- cgit v1.2.3 From 836e4eba09e73612b00f268e124750e78aeaa225 Mon Sep 17 00:00:00 2001 From: Marvin Borner Date: Wed, 30 Oct 2019 21:18:08 +0100 Subject: Added kind of working initrd support --- Makefile | 21 ++++-------------- src/bootloader/grub.cfg | 7 ++++++ src/bootloader/make_initrd.c | 53 ++++++++++++++++++++++++++++++++++++++++++++ src/bootloader/test.txt | 1 + src/kernel/graphics/vesa.c | 2 ++ src/kernel/graphics/vesa.h | 2 ++ src/kernel/grub.cfg | 7 ------ src/kernel/kernel.c | 30 ++++++++++++++++++++----- src/utils/make_initrd.c | 51 ------------------------------------------ src/utils/test.txt | 1 - 10 files changed, 94 insertions(+), 81 deletions(-) create mode 100644 src/bootloader/grub.cfg create mode 100644 src/bootloader/make_initrd.c create mode 100644 src/bootloader/test.txt delete mode 100644 src/kernel/grub.cfg delete mode 100644 src/utils/make_initrd.c delete mode 100644 src/utils/test.txt (limited to 'src/kernel') diff --git a/Makefile b/Makefile index 9f28fbb..cbb23b0 100644 --- a/Makefile +++ b/Makefile @@ -40,25 +40,12 @@ build: clean # Create ISO mkdir -p ./iso/boot/grub; \ cp ./build/melvix.bin ./iso/boot/; \ - cp ./src/kernel/grub.cfg ./iso/boot/grub/; \ + cp ./src/bootloader/grub.cfg ./iso/boot/grub/; \ + gcc -w ./src/bootloader/make_initrd.c -o ./build/make_initrd || exit; \ + ./build/make_initrd ./src/bootloader/test.txt test.txt || exit; \ + mv initrd.img ./iso/boot/melvix.initrd || exit; \ grub-mkrescue -o ./build/melvix.iso ./iso/; -image: build - @set -e; \ - gcc -w ./src/utils/make_initrd.c -o ./build/make_initrd || exit; \ - ./build/make_initrd ./src/utils/test.txt test.txt || exit; \ - mv initrd.img ./build/initrd.img || exit; \ - dd if=/dev/zero of=./build/image.img iflag=fullblock bs=1M count=10 && sync; \ - mkfs.ext2 ./build/image.img; \ - device=$$(sudo losetup -f); \ - sudo losetup $$device ./build/image.img || exit; \ - mkdir ./build/mnt/ || exit; \ - sudo mount $$device ./build/mnt/ || exit; \ - sudo cp ./build/melvix.iso ./build/mnt/kernel || exit; \ - sudo cp ./build/initrd.img ./build/mnt/initrd || exit; \ - sudo umount $$device || exit; \ - sudo losetup -d $$device; - cross: @set -e; \ [ -d "./cross/" ] && echo "Please remove ./cross/ and try again" && exit; \ diff --git a/src/bootloader/grub.cfg b/src/bootloader/grub.cfg new file mode 100644 index 0000000..cb265b1 --- /dev/null +++ b/src/bootloader/grub.cfg @@ -0,0 +1,7 @@ +set timeout=0 +set default=0 +menuentry "Melvix" { + multiboot /boot/melvix.bin + module /boot/melvix.initrd + boot +} \ No newline at end of file diff --git a/src/bootloader/make_initrd.c b/src/bootloader/make_initrd.c new file mode 100644 index 0000000..d7e0487 --- /dev/null +++ b/src/bootloader/make_initrd.c @@ -0,0 +1,53 @@ +#include + +struct initrd_header { + unsigned char magic; + char name[64]; + unsigned int offset; + unsigned int length; +}; + +int main(char argc, char **argv) { + int nheaders = (argc - 1) / 2; + struct initrd_header headers[64]; + printf("size of header: %d\n", sizeof(struct initrd_header)); + unsigned int off = sizeof(struct initrd_header) * 64 + sizeof(int); + + for (int i = 0; i < nheaders; i++) { + printf("writing file %s->%s at 0x%x\n", argv[i * 2 + 1], argv[i * 2 + 2], off); + strcpy(headers[i].name, argv[i * 2 + 2]); + headers[i].name[strlen(argv[i * 2 + 2])] = '\0'; + headers[i].offset = off; + FILE *stream = fopen(argv[i * 2 + 1], "r"); + if (stream == 0) { + printf("Error: file not found: %s\n", argv[i * 2 + 1]); + return 1; + } + fseek(stream, 0, SEEK_END); + headers[i].length = ftell(stream); + off += headers[i].length; + fclose(stream); + headers[i].magic = 0xBF; + } + + printf(headers[1].name); + + FILE *wstream = fopen("./initrd.img", "w"); + unsigned char *data = (unsigned char *) malloc(off); + fwrite(&nheaders, sizeof(int), 1, wstream); + fwrite(headers, sizeof(struct initrd_header), 64, wstream); + + for (int i = 0; i < nheaders; i++) { + FILE *stream = fopen(argv[i * 2 + 1], "r"); + unsigned char *buf = (unsigned char *) malloc(headers[i].length); + fread(buf, 1, headers[i].length, stream); + fwrite(buf, 1, headers[i].length, wstream); + fclose(stream); + free(buf); + } + + fclose(wstream); + free(data); + + return 0; +} diff --git a/src/bootloader/test.txt b/src/bootloader/test.txt new file mode 100644 index 0000000..9033296 --- /dev/null +++ b/src/bootloader/test.txt @@ -0,0 +1 @@ +hallo \ No newline at end of file diff --git a/src/kernel/graphics/vesa.c b/src/kernel/graphics/vesa.c index 94f53c6..3f8a9ba 100644 --- a/src/kernel/graphics/vesa.c +++ b/src/kernel/graphics/vesa.c @@ -287,6 +287,8 @@ void vesa_draw_char(char ch) { } else if (ch == '\n') { terminal_x = 0; terminal_y += font_height + 2; + } else if (ch == '\t') { + terminal_x += 4 * (font_width + 2); } if (terminal_x >= vbe_width) { diff --git a/src/kernel/graphics/vesa.h b/src/kernel/graphics/vesa.h index 649c6ee..748f8d0 100644 --- a/src/kernel/graphics/vesa.h +++ b/src/kernel/graphics/vesa.h @@ -128,6 +128,8 @@ void vesa_clear(); */ void vesa_set_font(int height); +void vesa_draw_char(char ch); + /** * Draw a char from keyboard * @param ch The character diff --git a/src/kernel/grub.cfg b/src/kernel/grub.cfg deleted file mode 100644 index 8a452ed..0000000 --- a/src/kernel/grub.cfg +++ /dev/null @@ -1,7 +0,0 @@ -set timeout=0 -set default=0 -menuentry "Melvix" { - multiboot /boot/melvix.bin - set gfxpayload=640x480x32 - boot -} \ No newline at end of file diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index cba4f6e..dd49949 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -30,16 +30,36 @@ void init() { void kernel_main(struct multiboot *mboot_ptr) { init(); - info("Kernel size in KiB: "); - vesa_draw_number((int) end >> 10); - assert(mboot_ptr->mods_count > 0); uint32_t initrd_location = *((uint32_t *) mboot_ptr->mods_addr); uint32_t initrd_end = *(uint32_t *) (mboot_ptr->mods_addr + 4); - // Don't trample our module with placement accesses, please! - // placement_address = initrd_end; + paging_set_used(0, (initrd_end >> 12) + 1); + fs_root = initialise_initrd(initrd_location); + int i = 0; + struct dirent *node = 0; + vesa_draw_string("\n"); + while ((node = readdir_fs(fs_root, i)) != 0) { + vesa_draw_string("Found file: "); + vesa_draw_string(node->name); + vesa_draw_string("\n"); + fs_node_t *fsnode = finddir_fs(fs_root, node->name); + + if ((fsnode->flags & 0x7) == FS_DIRECTORY) + vesa_draw_string("\t (directory)\n"); + else { + vesa_draw_string("\t contents: \""); + uint8_t buf[fsnode->length]; + uint32_t sz = read_fs(fsnode, 0, fsnode->length, buf); + for (uint32_t j = 0; j < sz; j++) + vesa_draw_char(buf[j]); + + vesa_draw_string("\"\n"); + } + i++; + } + // asm volatile ("div %0" :: "r"(0)); // Exception testing x/0 loop: asm volatile ("hlt"); diff --git a/src/utils/make_initrd.c b/src/utils/make_initrd.c deleted file mode 100644 index f6e504b..0000000 --- a/src/utils/make_initrd.c +++ /dev/null @@ -1,51 +0,0 @@ -#include - -struct initrd_header { - unsigned char magic; - char name[64]; - unsigned int offset; - unsigned int length; -}; - -int main(char argc, char **argv) { - int nheaders = (argc - 1) / 2; - struct initrd_header headers[64]; - printf("size of header: %d\n", sizeof(struct initrd_header)); - unsigned int off = sizeof(struct initrd_header) * 64 + sizeof(int); - - for (int i = 0; i < nheaders; i++) { - printf("writing file %s->%s at 0x%x\n", argv[i * 2 + 1], argv[i * 2 + 2], off); - strcpy(headers[i].name, argv[i * 2 + 2]); - headers[i].name[strlen(argv[i * 2 + 2])] = '\0'; - headers[i].offset = off; - FILE *stream = fopen(argv[i * 2 + 1], "r"); - if (stream == 0) { - printf("Error: file not found: %s\n", argv[i * 2 + 1]); - return 1; - } - fseek(stream, 0, SEEK_END); - headers[i].length = ftell(stream); - off += headers[i].length; - fclose(stream); - headers[i].magic = 0xBF; - } - - FILE *wstream = fopen("./initrd.img", "w"); - unsigned char *data = (unsigned char *) malloc(off); - fwrite(&nheaders, sizeof(int), 1, wstream); - fwrite(headers, sizeof(struct initrd_header), 64, wstream); - - for (int i = 0; i < nheaders; i++) { - FILE *stream = fopen(argv[i * 2 + 1], "r"); - unsigned char *buf = (unsigned char *) malloc(headers[i].length); - fread(buf, 1, headers[i].length, stream); - fwrite(buf, 1, headers[i].length, wstream); - fclose(stream); - free(buf); - } - - fclose(wstream); - free(data); - - return 0; -} diff --git a/src/utils/test.txt b/src/utils/test.txt deleted file mode 100644 index 9116450..0000000 --- a/src/utils/test.txt +++ /dev/null @@ -1 +0,0 @@ -heey -- cgit v1.2.3 From 91439462f5ad77eb128658229724c9a3660a2068 Mon Sep 17 00:00:00 2001 From: Marvin Borner Date: Wed, 30 Oct 2019 23:28:47 +0100 Subject: Fixed some warnings --- src/kernel/fs/initrd.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/kernel') diff --git a/src/kernel/fs/initrd.c b/src/kernel/fs/initrd.c index b291801..906498e 100644 --- a/src/kernel/fs/initrd.c +++ b/src/kernel/fs/initrd.c @@ -3,6 +3,7 @@ #include #include #include +#include initrd_header_t *initrd_header; initrd_file_header_t *file_headers; @@ -31,7 +32,7 @@ static struct dirent *initrd_readdir(fs_node_t *node, uint32_t index) { return &dirent; } - if (index - 1 >= nroot_nodes) + if (index - 1 >= (uint32_t) nroot_nodes) return 0; strcpy(dirent.name, root_nodes[index - 1].name); dirent.name[strlen(root_nodes[index - 1].name)] = 0; @@ -84,10 +85,10 @@ fs_node_t *initialise_initrd(uint32_t location) { root_nodes = (fs_node_t *) kmalloc(sizeof(fs_node_t) * initrd_header->nfiles); nroot_nodes = initrd_header->nfiles; - for (int i = 0; i < initrd_header->nfiles; i++) { + for (uint32_t i = 0; i < initrd_header->nfiles; i++) { file_headers[i].offset += location; - strcpy(root_nodes[i].name, &file_headers[i].name); + strcpy(root_nodes[i].name, (const char *) &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; -- cgit v1.2.3 From 7d5a9792e57b4088cce5cc97837eb04016b57a4d Mon Sep 17 00:00:00 2001 From: Marvin Borner Date: Thu, 31 Oct 2019 00:49:00 +0100 Subject: Implemented basic syscalls and user mode Doesn't completely work right now --- src/kernel/boot.asm | 19 +++++++++++ src/kernel/fs/initrd.c | 26 +++++++++++++++ src/kernel/fs/initrd.h | 2 ++ src/kernel/gdt/gdt.asm | 8 ++++- src/kernel/gdt/gdt.c | 75 +++++++++++++++++++++++++++++++++++++++++--- src/kernel/gdt/gdt.h | 2 ++ src/kernel/graphics/vesa.c | 2 +- src/kernel/graphics/vesa.h | 6 +++- src/kernel/kernel.c | 38 +++++++--------------- src/kernel/syscall/syscall.c | 45 ++++++++++++++++++++++++++ src/kernel/syscall/syscall.h | 44 ++++++++++++++++++++++++++ 11 files changed, 233 insertions(+), 34 deletions(-) create mode 100644 src/kernel/syscall/syscall.c create mode 100644 src/kernel/syscall/syscall.h (limited to 'src/kernel') diff --git a/src/kernel/boot.asm b/src/kernel/boot.asm index fad05ff..8f24066 100644 --- a/src/kernel/boot.asm +++ b/src/kernel/boot.asm @@ -50,6 +50,25 @@ stublet: %include "src/kernel/interact.asm" +global switch_to_user +switch_to_user: + cli + mov ax,0x23 + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + + mov eax,esp + push 0x23 + push eax + pushf + pop eax + or eax, 0x200 + push eax + push 0x1B + iret + ; Store the stack SECTION .bss resb 0x2000 ; Reserve 8KiB diff --git a/src/kernel/fs/initrd.c b/src/kernel/fs/initrd.c index 906498e..acaceb8 100644 --- a/src/kernel/fs/initrd.c +++ b/src/kernel/fs/initrd.c @@ -4,6 +4,7 @@ #include #include #include +#include initrd_header_t *initrd_header; initrd_file_header_t *file_headers; @@ -103,3 +104,28 @@ fs_node_t *initialise_initrd(uint32_t location) { } return initrd_root; } + +void initrd_test() { + int i = 0; + struct dirent *node = 0; + vesa_draw_string("\n"); + while ((node = readdir_fs(fs_root, i)) != 0) { + vesa_draw_string("Found file: "); + vesa_draw_string(node->name); + vesa_draw_string("\n"); + fs_node_t *fsnode = finddir_fs(fs_root, node->name); + + if ((fsnode->flags & 0x7) == FS_DIRECTORY) + vesa_draw_string("\t (directory)\n"); + else { + vesa_draw_string("\t contents: \""); + uint8_t buf[fsnode->length]; + uint32_t sz = read_fs(fsnode, 0, fsnode->length, buf); + for (uint32_t j = 0; j < sz; j++) + vesa_draw_char(buf[j]); + + vesa_draw_string("\"\n"); + } + i++; + } +} \ No newline at end of file diff --git a/src/kernel/fs/initrd.h b/src/kernel/fs/initrd.h index 10dec22..bb5c376 100644 --- a/src/kernel/fs/initrd.h +++ b/src/kernel/fs/initrd.h @@ -17,4 +17,6 @@ typedef struct { fs_node_t *initialise_initrd(uint32_t location); +void initrd_test(); + #endif diff --git a/src/kernel/gdt/gdt.asm b/src/kernel/gdt/gdt.asm index c2128e4..6cb2b7d 100644 --- a/src/kernel/gdt/gdt.asm +++ b/src/kernel/gdt/gdt.asm @@ -11,4 +11,10 @@ gdt_flush: mov ss, ax jmp 0x08:flush2 ; Code segment offset flush2: - ret ; Returns to C code \ No newline at end of file + ret ; Returns to C code + +global tss_flush +tss_flush: + mov ax, 0x2B + ltr ax + ret \ No newline at end of file diff --git a/src/kernel/gdt/gdt.c b/src/kernel/gdt/gdt.c index a4d6a57..b933950 100644 --- a/src/kernel/gdt/gdt.c +++ b/src/kernel/gdt/gdt.c @@ -1,4 +1,8 @@ +#include +#include #include +#include +#include struct gdt_entry { unsigned short limit_low; @@ -14,12 +18,46 @@ struct gdt_ptr { void *base; } __attribute__((packed)); -struct gdt_entry gdt[3]; +struct gdt_entry gdt[6]; struct gdt_ptr gp; +struct tss_entry_struct { + uint32_t prev_tss; + uint32_t esp0; + uint32_t ss0; + uint32_t esp1; + uint32_t ss1; + uint32_t esp2; + uint32_t ss2; + uint32_t cr3; + uint32_t eip; + uint32_t eflags; + uint32_t eax; + uint32_t ecx; + uint32_t edx; + uint32_t ebx; + uint32_t esp; + uint32_t ebp; + uint32_t esi; + uint32_t edi; + uint32_t es; + uint32_t cs; + uint32_t ss; + uint32_t ds; + uint32_t fs; + uint32_t gs; + uint32_t ldt; + uint16_t trap; + uint16_t iomap_base; +} __attribute__((packed)); + +struct tss_entry_struct tss_entry; + extern void gdt_flush(); -void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran) { +extern void tss_flush(); + +void gdt_set_gate(int32_t num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) { // Set descriptor base address gdt[num].base_low = (base & 0xFFFF); gdt[num].base_middle = (base >> 16) & 0xFF; @@ -36,7 +74,7 @@ void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned cha void gdt_install() { // Set GDT pointer and limit - gp.limit = (sizeof(struct gdt_entry) * 3) - 1; + gp.limit = (sizeof(struct gdt_entry) * 6) - 1; gp.base = &gdt; // NULL descriptor @@ -48,8 +86,37 @@ void gdt_install() { // Data segment gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); + // User mode code segment + gdt_set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); + + // User mode data segment + gdt_set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); + + // Write TSS + tss_write(5, 0x10, 0x0); + // Remove old GDT and install the new changes! gdt_flush(); + tss_flush(); // FAILS vga_log("Installed Global Descriptor Table", 2); -} \ No newline at end of file +} + +void tss_write(int32_t num, uint16_t ss0, uint32_t esp0) { + uint32_t base = (uint32_t) &tss_entry; + uint32_t limit = base + sizeof(tss_entry); + + gdt_set_gate(num, base, limit, 0xE9, 0x00); + + memset(&tss_entry, 0, sizeof(tss_entry)); + + tss_entry.ss0 = ss0; + tss_entry.esp0 = esp0; + + tss_entry.cs = 0x0b; + tss_entry.ss = tss_entry.ds = tss_entry.es = tss_entry.fs = tss_entry.gs = 0x13; +} + +void set_kernel_stack(uint32_t stack) { + tss_entry.esp0 = stack; +} diff --git a/src/kernel/gdt/gdt.h b/src/kernel/gdt/gdt.h index de8a6ff..0fffc20 100644 --- a/src/kernel/gdt/gdt.h +++ b/src/kernel/gdt/gdt.h @@ -6,4 +6,6 @@ */ void gdt_install(); +void tss_write(int32_t num, uint16_t ss0, uint32_t esp0); + #endif diff --git a/src/kernel/graphics/vesa.c b/src/kernel/graphics/vesa.c index 3f8a9ba..32ca717 100644 --- a/src/kernel/graphics/vesa.c +++ b/src/kernel/graphics/vesa.c @@ -324,7 +324,7 @@ void vesa_keyboard_char(char ch) { terminal_color); } -void vesa_draw_string(char *data) { +void vesa_draw_string(const char *data) { int i = 0; while (data[i] != '\0') { vesa_draw_char(data[i]); diff --git a/src/kernel/graphics/vesa.h b/src/kernel/graphics/vesa.h index 748f8d0..3fcef24 100644 --- a/src/kernel/graphics/vesa.h +++ b/src/kernel/graphics/vesa.h @@ -128,6 +128,10 @@ void vesa_clear(); */ void vesa_set_font(int height); +/** + * Draws a single char + * @param ch The char + */ void vesa_draw_char(char ch); /** @@ -140,7 +144,7 @@ void vesa_keyboard_char(char ch); * Draw a string in VESA mode * @param data The string */ -void vesa_draw_string(char *data); +void vesa_draw_string(const char *data); /** * Draw a number in VESA mode diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index dd49949..dd15409 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -8,8 +8,11 @@ #include #include #include +#include -void init() { +extern void switch_to_user(); + +void kernel_main(struct multiboot *mboot_ptr) { vga_log("Installing basic features of Melvix...", 0); // Install features timer_install(); @@ -21,44 +24,25 @@ void init() { isrs_install(); irq_install(); set_optimal_resolution(); + // Install drivers asm volatile ("cli"); keyboard_install(); asm volatile ("sti"); -} - -void kernel_main(struct multiboot *mboot_ptr) { - init(); + // Setup initial ramdisk assert(mboot_ptr->mods_count > 0); uint32_t initrd_location = *((uint32_t *) mboot_ptr->mods_addr); uint32_t initrd_end = *(uint32_t *) (mboot_ptr->mods_addr + 4); paging_set_used(0, (initrd_end >> 12) + 1); - fs_root = initialise_initrd(initrd_location); + initrd_test(); - int i = 0; - struct dirent *node = 0; - vesa_draw_string("\n"); - while ((node = readdir_fs(fs_root, i)) != 0) { - vesa_draw_string("Found file: "); - vesa_draw_string(node->name); - vesa_draw_string("\n"); - fs_node_t *fsnode = finddir_fs(fs_root, node->name); - - if ((fsnode->flags & 0x7) == FS_DIRECTORY) - vesa_draw_string("\t (directory)\n"); - else { - vesa_draw_string("\t contents: \""); - uint8_t buf[fsnode->length]; - uint32_t sz = read_fs(fsnode, 0, fsnode->length, buf); - for (uint32_t j = 0; j < sz; j++) - vesa_draw_char(buf[j]); + // User mode! + syscalls_install(); + switch_to_user(); - vesa_draw_string("\"\n"); - } - i++; - } + syscall_serial_write("Hello, user world!\n"); // asm volatile ("div %0" :: "r"(0)); // Exception testing x/0 loop: diff --git a/src/kernel/syscall/syscall.c b/src/kernel/syscall/syscall.c new file mode 100644 index 0000000..d1dbd6b --- /dev/null +++ b/src/kernel/syscall/syscall.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include + +DEFN_SYSCALL1(vesa_draw_string, 0, const char *); + +DEFN_SYSCALL1(vesa_draw_number, 1, int); + +DEFN_SYSCALL1(serial_write, 2, const char *); + +static void *syscalls[3] = { + &vesa_draw_string, + &vesa_draw_number, + &serial_write, +}; +uint32_t num_syscalls = 3; + +void syscall_handler(struct regs *r) { + if (r->eax >= num_syscalls) + return; + + void *location = syscalls[r->eax]; + + int ret; + asm volatile (" \ + push %1; \ + push %2; \ + push %3; \ + push %4; \ + push %5; \ + call *%6; \ + pop %%ebx; \ + pop %%ebx; \ + pop %%ebx; \ + pop %%ebx; \ + pop %%ebx; \ + " : "=a" (ret) : "r" (r->edi), "r" (r->esi), "r" (r->edx), "r" (r->ecx), "r" (r->ebx), "r" (location)); + r->eax = ret; +} + +void syscalls_install() { + irq_install_handler(0x80, &syscall_handler); +} diff --git a/src/kernel/syscall/syscall.h b/src/kernel/syscall/syscall.h new file mode 100644 index 0000000..d35c4e6 --- /dev/null +++ b/src/kernel/syscall/syscall.h @@ -0,0 +1,44 @@ +#ifndef MELVIX_SYSCALL_H +#define MELVIX_SYSCALL_H + +#include + +void syscalls_install(); + +void syscall_handler(struct regs *r); + +#define DECL_SYSCALL0(fn) int syscall_##fn(); +#define DECL_SYSCALL1(fn, p1) int syscall_##fn(p1); +#define DECL_SYSCALL2(fn, p1, p2) int syscall_##fn(p1,p2); +#define DECL_SYSCALL3(fn, p1, p2, p3) int syscall_##fn(p1,p2,p3); +#define DECL_SYSCALL4(fn, p1, p2, p3, p4) int syscall_##fn(p1,p2,p3,p4); +#define DECL_SYSCALL5(fn, p1, p2, p3, p4, p5) int syscall_##fn(p1,p2,p3,p4,p5); + +#define DEFN_SYSCALL0(fn, num) \ +int syscall_##fn() { \ + int a; \ + asm volatile("int $0x80" : "=a" (a) : "0" (num)); \ + return a; \ +} + +#define DEFN_SYSCALL1(fn, num, P1) \ +int syscall_##fn(P1 p1) { \ + int a; \ + asm volatile("int $0x80" : "=a" (a) : "0" (num), "b" ((int)p1)); \ + return a; \ +} + +#define DEFN_SYSCALL2(fn, num, P1, P2) \ +int syscall_##fn(P1 p1, P2 p2) { \ + int a; \ + asm volatile("int $0x80" : "=a" (a) : "0" (num), "b" ((int)p1), "c" ((int)p2)); \ + return a; \ +} + +DECL_SYSCALL1(vesa_draw_string, const char *) + +DECL_SYSCALL1(vesa_draw_number, int) + +DECL_SYSCALL1(serial_write, const char *) + +#endif -- cgit v1.2.3 From 2c7b6e0431d6dfbaf385d30e87e7eb9fd4a0e61d Mon Sep 17 00:00:00 2001 From: Marvin Borner Date: Thu, 31 Oct 2019 15:19:12 +0100 Subject: Some user mode improvements --- src/kernel/boot.asm | 29 ++++++++++++++--------------- src/kernel/gdt/gdt.c | 2 +- src/kernel/graphics/vesa.c | 2 +- src/kernel/kernel.c | 3 ++- src/kernel/syscall/syscall.c | 3 ++- src/userspace/main.c | 6 ++++++ 6 files changed, 26 insertions(+), 19 deletions(-) create mode 100644 src/userspace/main.c (limited to 'src/kernel') diff --git a/src/kernel/boot.asm b/src/kernel/boot.asm index 8f24066..2501ed9 100644 --- a/src/kernel/boot.asm +++ b/src/kernel/boot.asm @@ -51,23 +51,22 @@ stublet: %include "src/kernel/interact.asm" global switch_to_user +extern test_user switch_to_user: - cli - mov ax,0x23 - mov ds,ax - mov es,ax - mov fs,ax - mov gs,ax + sti + mov ax, 0x23 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax - mov eax,esp - push 0x23 - push eax - pushf - pop eax - or eax, 0x200 - push eax - push 0x1B - iret + mov eax, esp + push 0x23 + push eax + pushf + push 0x1B + push test_user + iret ; Store the stack SECTION .bss diff --git a/src/kernel/gdt/gdt.c b/src/kernel/gdt/gdt.c index b933950..1c69602 100644 --- a/src/kernel/gdt/gdt.c +++ b/src/kernel/gdt/gdt.c @@ -97,7 +97,7 @@ void gdt_install() { // Remove old GDT and install the new changes! gdt_flush(); - tss_flush(); // FAILS + tss_flush(); vga_log("Installed Global Descriptor Table", 2); } diff --git a/src/kernel/graphics/vesa.c b/src/kernel/graphics/vesa.c index 32ca717..858ed95 100644 --- a/src/kernel/graphics/vesa.c +++ b/src/kernel/graphics/vesa.c @@ -167,7 +167,7 @@ void set_optimal_resolution() { switch_to_vga(); } else vga_log("Mode detection succeeded", 11); - timer_wait(500); + // timer_wait(500); vbe_set_mode(highest); diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index dd15409..b133a0c 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -39,10 +39,11 @@ void kernel_main(struct multiboot *mboot_ptr) { initrd_test(); // User mode! + info("Switching to user mode..."); syscalls_install(); switch_to_user(); - syscall_serial_write("Hello, user world!\n"); + panic("This should NOT happen!"); // asm volatile ("div %0" :: "r"(0)); // Exception testing x/0 loop: diff --git a/src/kernel/syscall/syscall.c b/src/kernel/syscall/syscall.c index d1dbd6b..dec3e8e 100644 --- a/src/kernel/syscall/syscall.c +++ b/src/kernel/syscall/syscall.c @@ -18,6 +18,7 @@ static void *syscalls[3] = { uint32_t num_syscalls = 3; void syscall_handler(struct regs *r) { + serial_write("SYSCALL"); if (r->eax >= num_syscalls) return; @@ -41,5 +42,5 @@ void syscall_handler(struct regs *r) { } void syscalls_install() { - irq_install_handler(0x80, &syscall_handler); + irq_install_handler(0x80, syscall_handler); } diff --git a/src/userspace/main.c b/src/userspace/main.c new file mode 100644 index 0000000..d332d8e --- /dev/null +++ b/src/userspace/main.c @@ -0,0 +1,6 @@ +#include + +void test_user() { + asm volatile ("hlt"); + syscall_serial_write("Hello, user world!\n"); +} \ No newline at end of file -- cgit v1.2.3