simple tar initfs

This commit is contained in:
Benji Dial 2025-07-05 15:23:49 -04:00
parent 9a4c59ecfd
commit 125707d5bc
5 changed files with 162 additions and 10 deletions

View file

@ -1,6 +1,7 @@
timeout: 0 timeout: 0
quiet: yes quiet: yes
/Calcite /Calcite
protocol: limine protocol: limine
path: boot():/calcite/kernel.elf path: boot():/calcite/kernel.elf
module_path: boot():/calcite/initfs.tar

26
kernel/include/initfs.h Normal file
View file

@ -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 <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <stdint.h>
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);

View file

@ -15,6 +15,7 @@
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include <initfs.h>
#include <limine.h> #include <limine.h>
#include <paging.h> #include <paging.h>
@ -44,6 +45,12 @@ static volatile struct limine_memmap_request memmap_request = {
.response = 0 .response = 0
}; };
static volatile struct limine_module_request module_request = {
.id = LIMINE_MODULE_REQUEST,
.revision = 0,
.response = 0
};
[[noreturn]] static void die() { [[noreturn]] static void die() {
while (1) while (1)
__asm__ ("hlt"); __asm__ ("hlt");
@ -70,6 +77,9 @@ static int fb_width;
static int fb_height; static int fb_height;
static int fb_pitch; static int fb_pitch;
static uint8_t *initfs_start;
static uint64_t initfs_length;
[[noreturn]] static void with_kernel_page_tables(); [[noreturn]] static void with_kernel_page_tables();
[[noreturn]] void kernel_entry() { [[noreturn]] void kernel_entry() {
@ -78,7 +88,9 @@ static int fb_pitch;
if (fb_request.response == 0 || hhdm_request.response == 0 || if (fb_request.response == 0 || hhdm_request.response == 0 ||
ka_request.response == 0 || memmap_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(); die();
struct limine_framebuffer *fb = fb_request.response->framebuffers[0]; 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) fb->blue_mask_shift != 0 || fb->blue_mask_size != 8)
die(); die();
struct limine_file *initfs = module_request.response->modules[0];
//set up page tables. we will mark the regions with bootloader structures as //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 //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 //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_height = fb->height;
fb_pitch = fb->pitch; 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!
switch_to_kernel_page_tables(&with_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() { [[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 y = 0; y < fb_height; ++y)
for (int x = 0; x < fb_width; ++x) { for (int x = 0; x < fb_width; ++x) {

74
kernel/src/initfs.c Normal file
View file

@ -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 <https://www.gnu.org/licenses/>.
*/
#include <initfs.h>
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;
}
}

View file

@ -1,5 +1,6 @@
CC_EXTRA_FLAGS = -O3 -Wall -Wextra COMMON_CC_EXTRA_FLAGS = -O3 -Wall -Wextra
CC_FLAGS = -std=c23 -mno-sse -ffreestanding ${CC_EXTRA_FLAGS} COMMON_CC_FLAGS = -std=c23 ${CC_EXTRA_FLAGS}
KERNEL_CC_FLAGS = -mno-sse -ffreestanding ${COMMON_CC_FLAGS}
.PHONY: default .PHONY: default
default: build/disk.iso default: build/disk.iso
@ -14,7 +15,7 @@ clean:
# kernel # 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 build/kernel/%.asm.o: kernel/src/%.asm
@mkdir -p ${@D} @mkdir -p ${@D}
@ -22,14 +23,22 @@ build/kernel/%.asm.o: kernel/src/%.asm
build/kernel/%.c.o: kernel/src/%.c build/kernel/%.c.o: kernel/src/%.c
@mkdir -p ${@D} @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} build/kernel/kernel.elf: ${KERNEL_SOURCES:%=build/kernel/%.o}
ld -T kernel/link.ld $^ -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 # disk
build/disk.iso: build/kernel/kernel.elf build/disk.iso: build/kernel/kernel.elf build/initfs.tar
rm -rf build/disk rm -rf build/disk
cp -r disk build/disk cp -r disk build/disk
cp dependencies/limine/limine-uefi-cd.bin build/disk/limine/ 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/ cp dependencies/limine/BOOTX64.EFI build/disk/EFI/BOOT/
mkdir build/disk/calcite mkdir build/disk/calcite
cp build/kernel/kernel.elf build/disk/calcite/ cp build/kernel/kernel.elf build/disk/calcite/
cp build/initfs.tar build/disk/calcite/
xorriso \ xorriso \
-as mkisofs -R -r -J -b limine/limine-bios-cd.bin -no-emul-boot \ -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 \ -boot-load-size 4 -boot-info-table -hfsplus -apm-block-size 2048 \