diff --git a/Makefile b/Makefile index ad5dcea..1d1d493 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,7 @@ required : make -C lib make -C drivers make -C memory + make -C filesystem $(ISO) : $(BINARY) grub-mkrescue -o $@ isoroot @@ -50,6 +51,7 @@ fclean : clean make -C lib fclean make -C drivers fclean make -C memory fclean + make -C filesystem fclean rm -rf obj rm -rf $(ISO) rm -rf $(BINARY) diff --git a/filesystem/Makefile b/filesystem/Makefile index 344a2c9..68e494a 100644 --- a/filesystem/Makefile +++ b/filesystem/Makefile @@ -3,6 +3,9 @@ MEM = filesystem.a VFS_SRC = vfs/vfs.c VFS_OBJ = vfs/vfs.o +IRD_SRC = initrd/initrd.c +IRD_OBJ = initrd/initrd.o + AR = ../gcc_kfs/bin/i386-elf-ar rcs CC = ../gcc_kfs/bin/i386-elf-gcc FLAGS = -ffreestanding \ @@ -13,17 +16,23 @@ FLAGS = -ffreestanding \ all: $(MEM) -$(MEM): $(VFS_OBJ) +$(MEM): $(VFS_OBJ) $(IRD_OBJ) $(AR) $@ $^ vfs/%.o: vfs/%.c $(CC) $(FLAGS) -c $^ -o $@ -vfs/%.o: vfs/%.s +initrd/%.o: initrd/%.c $(CC) $(FLAGS) -c $^ -o $@ +generator: filesystem_generator.c + gcc filesystem_generator.c -o filesystem_generator + ./filesystem_generator + rm -rf filesystem_generator + clean: rm -rf $(VFS_OBJ) + rm -rf $(IRD_OBJ) fclean: clean rm -rf $(MEM) diff --git a/filesystem/filesystem_generator.c b/filesystem/filesystem_generator.c new file mode 100644 index 0000000..85cebb5 --- /dev/null +++ b/filesystem/filesystem_generator.c @@ -0,0 +1,52 @@ +#include +#include +#include +#include + +struct initrd_header { + uint8_t magic; + char name[64]; + uint32_t offset; + uint32_t len; +}; + +int main(int argc, char **argv) { + int nheaders = (argc - 1) / 2; + struct initrd_header headers[64]; + printf("size of headers: %ld\n", sizeof(struct initrd_header)); + uint32_t off = sizeof(struct initrd_header) * 64 + sizeof(int); + size_t i; + for (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].offset = off; + FILE* stream =fopen(argv[i * 2 + 1], "r"); + if (!stream) { + printf("Error: file not found: %s\n", argv[i * 2 + 1]); + return 1; + } + fseek(stream, 0, SEEK_END); + headers[i].len = ftell(stream); + off += headers[i].len; + fclose(stream); + headers[i].magic = 0xBF; + } + + FILE* wstream = fopen("./initrd.img", "w"); + uint8_t* data = (uint8_t*)malloc(off); + fwrite(&nheaders, sizeof(uint32_t), 1, wstream); + fwrite(headers, sizeof(struct initrd_header), 64, wstream); + + for (i = 0; i < nheaders; i++) { + FILE* stream = fopen(argv[i * 2 + 1], "r"); + uint8_t* buf = (uint8_t*)malloc(headers[i].len); + fread(buf, 1, headers[i].len, stream); + fwrite(buf, 1, headers[i].len, wstream); + fclose(stream); + free(buf); + } + + fclose(wstream); + free(data); + return 0; +} diff --git a/filesystem/initrd/initrd.c b/filesystem/initrd/initrd.c new file mode 100644 index 0000000..7b39cb4 --- /dev/null +++ b/filesystem/initrd/initrd.c @@ -0,0 +1,102 @@ +#include "initrd.h" + +initrd_header_t *initrd_header; // The header. +initrd_file_header_t *file_headers; // The list of file headers. +fs_node_t *initrd_root; // Our root directory node. +fs_node_t *initrd_dev; // We also add a directory node for /dev, so we can mount devfs later on. +fs_node_t *root_nodes; // List of file nodes. +int nroot_nodes; // Number of file nodes. + +dir_entry_t 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.len) return 0; + if (offset+size > header.len) size = header.len - offset; + memcpy(buffer, (uint8_t*) (header.offset + offset), size); + return size; +} + +static dir_entry_t *initrd_readdir(fs_node_t *node, uint32_t index) { + if (node == initrd_root && index == 0) + { + strcpy(dirent.name, "dev"); + dirent.name[3] = 0; // Make sure the string is NULL-terminated. + dirent.inode = 0; + return &dirent; + } + + if (index - 1 >= nroot_nodes) return NULL; + strcpy(dirent.name, root_nodes[index-1].name); + dirent.name[strlen(root_nodes[index-1].name)] = 0; // Make sure the string is NULL-terminated. + dirent.inode = 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; + for (size_t i = 0; i < nroot_nodes; i++) { + if (!strcmp(name, root_nodes[i].name)) return &root_nodes[i]; + } + return NULL; +} + +fs_node_t *initialise_initrd( uint32_t location) +{ + // Initialise the main and file header pointers and populate the root directory. + initrd_header = (initrd_header_t *)location; + file_headers = (initrd_file_header_t *) (location+sizeof(initrd_header_t)); + // Initialise the root directory. + initrd_root = (fs_node_t*)kmalloc(sizeof(fs_node_t)); + strcpy(initrd_root->name, "initrd"); + initrd_root->permissions = initrd_root->uid = initrd_root->gid = initrd_root->inode = initrd_root->len = 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; + // Initialise the /dev directory (required!) + initrd_dev = (fs_node_t*)kmalloc(sizeof(fs_node_t)); + strcpy(initrd_dev->name, "dev"); + initrd_dev->permissions = initrd_dev->uid = initrd_dev->gid = initrd_dev->inode = initrd_dev->len = 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; +// Allocate space for the files in the ramdisk + root_nodes = (fs_node_t*)kmalloc(sizeof(fs_node_t) * initrd_header->nfiles); + nroot_nodes = initrd_header->nfiles; + // For every file... + int i; + for (i = 0; i < initrd_header->nfiles; i++) + { + // Edit the file's header - currently it holds the file offset + // relative to the start of the ramdisk. We want it relative to the start + // of memory. + file_headers[i].offset += location; + // Create a new file node. + strcpy(root_nodes[i].name, &file_headers[i].name); + root_nodes[i].permissions = root_nodes[i].uid = root_nodes[i].gid = 0; + root_nodes[i].len = file_headers[i].len; + 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/filesystem/initrd/initrd.h b/filesystem/initrd/initrd.h new file mode 100644 index 0000000..3050bbc --- /dev/null +++ b/filesystem/initrd/initrd.h @@ -0,0 +1,19 @@ +#ifndef INITRD_H +#define INITRD_H + +#include "../vfs/vfs.h" + +typedef struct { + uint32_t nfiles; +} initrd_header_t; + +typedef struct { + uint8_t magic; + char name[64]; + uint32_t offset; + uint32_t len; +} initrd_file_header_t; + +fs_node_t *initialise_initrd(uint32_t location); + +#endif diff --git a/filesystem/vfs/vfs.c b/filesystem/vfs/vfs.c index 00f1e99..2641ad1 100644 --- a/filesystem/vfs/vfs.c +++ b/filesystem/vfs/vfs.c @@ -1,27 +1,31 @@ #include "vfs.h" -fs_node_t *fs_root = NULL; - -uint32_t fs_write(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer) { +struct fs_node_s *fs_root = NULL; +uint32_t fs_write(struct fs_node_s* node, uint32_t offset, uint32_t size, uint8_t* buffer) { + if (!node->write) return node->write(node, offset, size, buffer); + return 0; } -uint32_t fs_read(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer) { - +uint32_t fs_read(struct fs_node_s* node, uint32_t offset, uint32_t size, uint8_t* buffer) { + if (!node->read) return node->read(node, offset, size, buffer); + return 0; } -void fs_open(fs_node_t* node, uint8_t read, uint8_t write) { - +void fs_open(struct fs_node_s* node, uint8_t read, uint8_t write) { + if (!node->open) (node->open(node)); } -void fs_close(fs_node_t* node) { - +void fs_close(struct fs_node_s* node) { + if (!node->close) (node->close(node)); } -dir_entry_t* readdir_fs(fs_node_t* node, uint32_t index) { - +dir_entry_t* readdir_fs(struct fs_node_s* node, uint32_t index) { + if (!node->readdir && (node->flags & 7 == FS_DIRECTORY)) return node->readdir(node, index); + return NULL; } -fs_node_t* finddir_fs(fs_node_t*, char* name) { - +struct fs_node_s* finddir_fs(struct fs_node_s* node, char* name) { + if (!node->finddir && (node->flags & 7 == FS_DIRECTORY)) return node->finddir(node, name); + return NULL; } diff --git a/filesystem/vfs/vfs.h b/filesystem/vfs/vfs.h index fd2a367..0d72abb 100644 --- a/filesystem/vfs/vfs.h +++ b/filesystem/vfs/vfs.h @@ -3,6 +3,8 @@ #include #include +#include "../../lib/string/string.h" +#include "../../memory/vmm/vmm.h" enum fs_flags { FS_FILE = 1, @@ -14,6 +16,11 @@ enum fs_flags { FS_MOUNTPOINT = 8 }; +typedef uint32_t (*rw_t)(struct fs_node_s*, uint32_t, uint32_t, uint8_t*); +typedef void (*oc_t)(struct fs_node_s*); +typedef struct dir_entry_s * (*readdir_t)(struct fs_node_s*, uint32_t); +typedef struct fs_node_s * (*finddir_t)(struct fs_node_s*, char* name); + typedef struct fs_node_s { char name[128]; // Should move it to directory node uint32_t permissions; @@ -33,21 +40,19 @@ typedef struct fs_node_s { struct fs_node_s *ptr; // For symlink and mountpoint } fs_node_t; -typedef struct { +typedef struct dir_entry_s { char name[128]; uint32_t inode; } dir_entry_t; -typedef uint32_t (*rw_t)(fs_node_t*, uint32_t, uint32_t, uint8_t*); -typedef void (*oc_t)(fs_node_t*); -typedef dir_entry_t * (*readdir_t)(fs_node_t*, uint32_t); -typedef fs_node_t * (*finddir_t)(fs_node_t*, char* name); - -uint32_t fs_write(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer); -uint32_t fs_read(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer); -void fs_open(fs_node_t* node, uint8_t read, uint8_t write); -void fs_close(fs_node_t* node); -dir_entry_t* readdir_fs(fs_node_t* node, uint32_t index); -fs_node_t* finddir_fs(fs_node_t*, char* name); + +uint32_t fs_write(struct fs_node_s* node, uint32_t offset, uint32_t size, uint8_t* buffer); +uint32_t fs_read(struct fs_node_s* node, uint32_t offset, uint32_t size, uint8_t* buffer); +void fs_open(struct fs_node_s* node, uint8_t read, uint8_t write); +void fs_close(struct fs_node_s* node); +dir_entry_t* readdir_fs(struct fs_node_s* node, uint32_t index); +struct fs_node_s* finddir_fs(struct fs_node_s*, char* name); + +extern fs_node_t* fs_root; #endif diff --git a/kernel/kernel.c b/kernel/kernel.c index a0e5d72..70ad409 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -31,6 +31,8 @@ void kernel_main(uint32_t magic, uint32_t addr) { multiboot_info_t* mbi = (multiboot_info_t*)addr; struct multiboot_mmap_entry* region = (struct multiboot_mmap_entry*) mbi->mmap_addr; uint32_t mem_size = MAX_MEMORY_SIZE; + uint32_t initrd_location = *(uint32_t*)(mbi->mods_addr); + uint32_t initrd_end = *(uint32_t*)(mbi->mods_addr + 4); init_current_screen(BLUE, WHITE); term_clear(); @@ -38,18 +40,10 @@ void kernel_main(uint32_t magic, uint32_t addr) { init_keyboard(); init_timer(50); init_syscall(); - asm volatile( - "mov $1, %eax\n" - "int $0x80" - ); pmm_init(mem_size, &bitmap); for (size_t i = 0; i < 15; i++) { if (region[i].type > 5) region[i].type = MULTIBOOT_MEMORY_AVAILABLE; if (i > 0 && region[i].addr_low == 0) break; - printf ("region %d: start: %p length (bytes): %p type: %d (%s)\n", i, - region[i].addr_low, - region[i].len_low, - region[i].type, strMemoryTypes[region[i].type-1]); if (region[i].type == MULTIBOOT_MEMORY_AVAILABLE) pmm_init_region(region[i].addr_low, region[i].len_low); } pmm_deinit_region(0x100000, 0); @@ -60,12 +54,6 @@ void kernel_main(uint32_t magic, uint32_t addr) { asm volatile("mov %%cr0, %0" : "=r" (cr0)); if (cr0 & 0x80000000) printf("Paging enabled: cr0 == %p\n", cr0); else printf("Paging disabled: cr0 == %p\n", cr0); - uint8_t* test = kmalloc(1); - void* test2 = kmalloc(1); - *test = 5; - uint16_t* test3 = kmalloc(16); - *test3 = 6; - printf("test: %p sizeof(test) == %d bytes and value %d\n", test, kget_size(test), *test); - kfree(test); - printf("test %p | test2 %p | test3 %p\n", test, test2, test3); + if (!mbi->mods_count) printf("no mods added\n"); + fs_root = initialise_initrd(initrd_location); } diff --git a/kernel/kernel.h b/kernel/kernel.h index 3dd41d0..59b4aac 100644 --- a/kernel/kernel.h +++ b/kernel/kernel.h @@ -11,4 +11,5 @@ #include "../multiboot/multiboot.h" #include "../memory/pmm/pmm.h" #include "../memory/vmm/vmm.h" +#include "../filesystem/initrd/initrd.h" #endif