From 125707d5bc4772bdce7868d2998ce4c41be3c280 Mon Sep 17 00:00:00 2001 From: Benji Dial Date: Sat, 5 Jul 2025 15:23:49 -0400 Subject: [PATCH] simple tar initfs --- disk/limine/limine.conf | 7 ++-- kernel/include/initfs.h | 26 +++++++++++++++ kernel/src/entry.c | 45 +++++++++++++++++++++++-- kernel/src/initfs.c | 74 +++++++++++++++++++++++++++++++++++++++++ makefile | 20 ++++++++--- 5 files changed, 162 insertions(+), 10 deletions(-) create mode 100644 kernel/include/initfs.h create mode 100644 kernel/src/initfs.c diff --git a/disk/limine/limine.conf b/disk/limine/limine.conf index c4cb186..2f7adf6 100644 --- a/disk/limine/limine.conf +++ b/disk/limine/limine.conf @@ -1,6 +1,7 @@ timeout: 0 -quiet: yes +quiet: yes /Calcite -protocol: limine -path: boot():/calcite/kernel.elf +protocol: limine +path: boot():/calcite/kernel.elf +module_path: boot():/calcite/initfs.tar diff --git a/kernel/include/initfs.h b/kernel/include/initfs.h new file mode 100644 index 0000000..3a1a4d3 --- /dev/null +++ b/kernel/include/initfs.h @@ -0,0 +1,26 @@ +/* Calcite, kernel/include/initfs.h + * Copyright 2025 Benji Dial + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#pragma once + +#include + +void set_initfs(const uint8_t *start, uint64_t length); + +//if the file does not exist, *start_out is set to a null pointer. +void look_up_initfs_file( + const char *path, const uint8_t **start_out, uint64_t *length_out); diff --git a/kernel/src/entry.c b/kernel/src/entry.c index 14a1af8..1e9a46c 100644 --- a/kernel/src/entry.c +++ b/kernel/src/entry.c @@ -15,6 +15,7 @@ * this program. If not, see . */ +#include #include #include @@ -44,6 +45,12 @@ static volatile struct limine_memmap_request memmap_request = { .response = 0 }; +static volatile struct limine_module_request module_request = { + .id = LIMINE_MODULE_REQUEST, + .revision = 0, + .response = 0 +}; + [[noreturn]] static void die() { while (1) __asm__ ("hlt"); @@ -70,6 +77,9 @@ static int fb_width; static int fb_height; static int fb_pitch; +static uint8_t *initfs_start; +static uint64_t initfs_length; + [[noreturn]] static void with_kernel_page_tables(); [[noreturn]] void kernel_entry() { @@ -78,7 +88,9 @@ static int fb_pitch; if (fb_request.response == 0 || hhdm_request.response == 0 || ka_request.response == 0 || memmap_request.response == 0 || - fb_request.response->framebuffer_count == 0) + module_request.response == 0 || + fb_request.response->framebuffer_count == 0 || + module_request.response->module_count == 0) die(); struct limine_framebuffer *fb = fb_request.response->framebuffers[0]; @@ -88,6 +100,8 @@ static int fb_pitch; fb->blue_mask_shift != 0 || fb->blue_mask_size != 8) die(); + struct limine_file *initfs = module_request.response->modules[0]; + //set up page tables. we will mark the regions with bootloader structures as //usable, so we need to be careful not to allocate any physical pages until //after we are done using bootloader structures. we map the kernel into our @@ -131,6 +145,18 @@ static int fb_pitch; fb_height = fb->height; fb_pitch = fb->pitch; + //remap initfs module and store information. + + uint64_t initfs_physical_start = + (uint64_t)initfs->address - hhdm_request.response->offset; + + initfs_length = initfs->size; + uint64_t initfs_length_rounded = ((initfs_length - 1) / 4096 + 1) * 4096; + + initfs_start = find_free_kernel_region(initfs_length_rounded); + map_kernel_region( + initfs_physical_start, initfs_start, initfs_length_rounded, 0, 0); + //switch to kernel page tables! switch_to_kernel_page_tables(&with_kernel_page_tables); @@ -139,7 +165,22 @@ static int fb_pitch; [[noreturn]] static void with_kernel_page_tables() { - //display our test pattern + //test initfs + + set_initfs(initfs_start, initfs_length); + + const uint8_t *hello_start; + uint64_t hello_length; + look_up_initfs_file("resx/hello.txt", &hello_start, &hello_length); + + if (hello_length != 7) + die(); + + for (int i = 0; i < 7; ++i) + if (hello_start[i] != "Hello!\n"[i]) + die(); + + //test framebuffer for (int y = 0; y < fb_height; ++y) for (int x = 0; x < fb_width; ++x) { diff --git a/kernel/src/initfs.c b/kernel/src/initfs.c new file mode 100644 index 0000000..a176b3e --- /dev/null +++ b/kernel/src/initfs.c @@ -0,0 +1,74 @@ +/* Calcite, kernel/src/initfs.c + * Copyright 2025 Benji Dial + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include + +static const uint8_t *initfs_start; +static uint64_t initfs_length; + +void set_initfs(const uint8_t *start, uint64_t length) { + initfs_start = start; + initfs_length = length; +} + +static uint64_t decode_octal(const char *from) { + uint64_t value = 0; + while (*from != '\0') { + value = value * 8 + *from - '0'; + ++from; + } + return value; +} + +void look_up_initfs_file( + const char *path, const uint8_t **start_out, uint64_t *length_out) { + + int path_len = 0; + while (path[path_len] != '\0') + ++path_len; + + uint64_t offset = 0; + + while (1) { + + if (offset + 512 > initfs_length) { + *start_out = 0; + return; + } + + uint64_t length = + decode_octal((const char *)(initfs_start + offset + 0x7c)); + + int found_it = 1; + + for (int i = 0; i < path_len; ++i) + if (initfs_start[offset + i] != path[i]) { + found_it = 0; + break; + } + + if (found_it) { + *start_out = initfs_start + offset + 512; + *length_out = length; + return; + } + + offset += 512 + ((length - 1) / 512 + 1) * 512; + + } + +} diff --git a/makefile b/makefile index cedcfe3..2f154f8 100644 --- a/makefile +++ b/makefile @@ -1,5 +1,6 @@ -CC_EXTRA_FLAGS = -O3 -Wall -Wextra -CC_FLAGS = -std=c23 -mno-sse -ffreestanding ${CC_EXTRA_FLAGS} +COMMON_CC_EXTRA_FLAGS = -O3 -Wall -Wextra +COMMON_CC_FLAGS = -std=c23 ${CC_EXTRA_FLAGS} +KERNEL_CC_FLAGS = -mno-sse -ffreestanding ${COMMON_CC_FLAGS} .PHONY: default default: build/disk.iso @@ -14,7 +15,7 @@ clean: # kernel -KERNEL_SOURCES = entry.c paging.asm paging.c +KERNEL_SOURCES = entry.c initfs.c paging.asm paging.c build/kernel/%.asm.o: kernel/src/%.asm @mkdir -p ${@D} @@ -22,14 +23,22 @@ build/kernel/%.asm.o: kernel/src/%.asm build/kernel/%.c.o: kernel/src/%.c @mkdir -p ${@D} - cc -c ${CC_FLAGS} -I dependencies/limine -I kernel/include $^ -o $@ + cc -c ${KERNEL_CC_FLAGS} -I dependencies/limine -I kernel/include $^ -o $@ build/kernel/kernel.elf: ${KERNEL_SOURCES:%=build/kernel/%.o} ld -T kernel/link.ld $^ -o $@ +# initfs + +build/initfs.tar: + rm -rf build/initfs + mkdir -p build/initfs/resx + echo Hello! > build/initfs/resx/hello.txt + cd build/initfs; tar cf ../initfs.tar * + # disk -build/disk.iso: build/kernel/kernel.elf +build/disk.iso: build/kernel/kernel.elf build/initfs.tar rm -rf build/disk cp -r disk build/disk cp dependencies/limine/limine-uefi-cd.bin build/disk/limine/ @@ -39,6 +48,7 @@ build/disk.iso: build/kernel/kernel.elf cp dependencies/limine/BOOTX64.EFI build/disk/EFI/BOOT/ mkdir build/disk/calcite cp build/kernel/kernel.elf build/disk/calcite/ + cp build/initfs.tar build/disk/calcite/ xorriso \ -as mkisofs -R -r -J -b limine/limine-bios-cd.bin -no-emul-boot \ -boot-load-size 4 -boot-info-table -hfsplus -apm-block-size 2048 \