10 Commits

Author SHA1 Message Date
xamidev f7735eb3a4 Move headers to include/ 2026-03-18 11:48:33 +01:00
xamidev a1e8aacd01 improve README.md 2026-03-17 10:33:10 +01:00
xamidev ccc8985d4c Merge pull request 'Improve Makefile' (#15) from furtest/pepperOS:makefile into main
Reviewed-on: xamidev/pepperOS#15
2026-03-15 21:17:44 +01:00
xamidev 0482f594ef Flanterm back to bump alloc (allows earlier use for real hw debugging) 2026-03-15 21:11:47 +01:00
furtest b02a4b5284 Fix build-iso prerequisites 2026-03-15 18:05:24 +01:00
furtest 32f3889565 Move PHONY tags and fix clean
Move the PHONY tags to make them clearer to read.
Fix the clean rule so it deletes the build directory.
2026-03-15 18:01:35 +01:00
furtest 803ac0879b Auto find source files check for changes
Previously the build process removed everything and did all the build
again on each make invocation.
This fixes this behaviour with two changes.
First dynamically find the list of files to build using find instead of
a manually written list.
Then use implicit rules to only build files that need to be built again
instead of recompiling everything.
2026-03-15 17:56:26 +01:00
furtest 9fc55f98d8 Use variables for build and pepperk and rename build target.
Instead of hardcoding the names set them using a variable.
Also rename the target build to the name of the file it builds which is
in the ELFFILE variable.
2026-03-15 16:58:04 +01:00
furtest 11bd628821 Extract CC and LD to variables.
This allows to change the name of the compiler or linker when calling
make.
2026-03-15 16:57:29 +01:00
xamidev 80d8b49560 Merge pull request 'spinlock' (#14) from spinlock into main
Reviewed-on: xamidev/pepperOS#14
2026-03-15 09:55:45 +01:00
47 changed files with 175 additions and 120 deletions
+31 -17
View File
@@ -1,31 +1,41 @@
SOURCES = src/sched/spinlock.c src/debug/misc.c src/io/term/flanterm_backends/fb.c src/io/term/flanterm.c src/debug/panic.c src/debug/stacktrace.c src/boot/boot.c src/sched/scheduler.c src/sched/process.c src/mem/heap/kheap.c src/mem/paging/vmm.c src/mem/paging/paging.c src/mem/paging/pmm.c src/string/string.c src/io/kbd/ps2.c src/io/serial/serial.c src/io/term/term.c src/idt/idt.c src/mem/gdt/gdt.c src/mem/misc/utils.c src/time/timer.c src/kmain.c
BUILDDIR := build
ELFFILE := pepperk
SRC := src
SOURCES := $(shell find src -name '*.c')
OBJFILES := $(patsubst $(SRC)/%.c, $(BUILDDIR)/%.o, $(SOURCES))
CC := x86_64-elf-gcc
CC_FLAGS=-Wall -Wextra -std=gnu99 -nostdlib -ffreestanding -fno-stack-protector -fno-omit-frame-pointer -fno-stack-check -fno-PIC -ffunction-sections -fdata-sections -mcmodel=kernel
CC_PROBLEMATIC_FLAGS=-Wno-unused-parameter -Wno-unused-variable
.PHONY: build build-iso debug debug2 run clean
LD := x86_64-elf-ld
build:
mkdir -p build
rm -f *.o build/*.o
x86_64-elf-gcc -g -c -Isrc $(SOURCES) $(CC_PROBLEMATIC_FLAGS) $(CC_FLAGS)
mv *.o build/
nasm -f elf64 src/idt/idt.S -o build/idt_stub.o
x86_64-elf-ld -o pepperk -T linker.ld build/*.o
nm -n pepperk | awk '$$2 ~ /[TtDdBbRr]/ {print $$1, $$3}' > symbols.map
$(ELFFILE): $(BUILDDIR) $(OBJFILES)
nasm -f elf64 src/idt/idt.S -o $(BUILDDIR)/idt_stub.o
$(LD) -o $(ELFFILE) -T linker.ld $(OBJFILES) $(BUILDDIR)/idt_stub.o
# Get the symbols for debugging
nm -n $(ELFFILE) | awk '$$2 ~ /[TtDdBbRr]/ {print $$1, $$3}' > symbols.map
python3 symbols.py
nasm -f elf64 symbols.S -o build/symbols.o
x86_64-elf-ld -o pepperk -T linker.ld build/*.o
nasm -f elf64 symbols.S -o $(BUILDDIR)/symbols.o
$(LD) -o $(ELFFILE) -T linker.ld $(OBJFILES) $(BUILDDIR)/idt_stub.o
$(BUILDDIR):
@mkdir -p $(BUILDDIR)
$(BUILDDIR)/%.o: $(SRC)/%.c
mkdir -p $(dir $@)
$(CC) -g -c -Iinclude $< $(CC_PROBLEMATIC_FLAGS) $(CC_FLAGS) -o $@
limine/limine:
rm -rf limine
git clone https://github.com/limine-bootloader/limine.git --branch=v9.x-binary --depth=1
$(MAKE) -C limine
build-iso: limine/limine build
build-iso: limine/limine $(ELFFILE)
rm -rf iso_root
mkdir -p iso_root/boot
cp -v pepperk iso_root/boot
cp -v $(ELFFILE) iso_root/boot
mkdir -p iso_root/boot/limine
cp -v limine.conf iso_root/boot/limine
mkdir -p iso_root/EFI/BOOT
@@ -39,16 +49,20 @@ build-iso: limine/limine build
iso_root -o pepper.iso
./limine/limine bios-install pepper.iso
.PHONY: debug
debug:
/usr/bin/qemu-system-x86_64 -drive file=pepper.iso -s -S -d int -D qemu.log -no-reboot -no-shutdown &
gdb pepperk --command=debug.gdb
gdb $(ELFFILE) --command=debug.gdb
.PHONY: debug2
debug2:
/usr/bin/qemu-system-x86_64 -drive file=pepper.iso -s -S -d int -no-reboot -no-shutdown &
pwndbg pepperk --command=debug.gdb
pwndbg $(ELFFILE) --command=debug.gdb
.PHONY: run
run: build-iso
/usr/bin/qemu-system-x86_64 -cdrom pepper.iso -serial stdio
.PHONY: clean
clean:
rm -rf *.o symbols.map symbols.S pepperk iso_root pepper.iso limine build/*.o
rm -rf $(BUILDDIR) symbols.map symbols.S $(ELFFILE) iso_root pepper.iso limine
+28 -6
View File
@@ -1,17 +1,38 @@
# <img width="40" height="40" alt="red-pepper" src="https://i.ibb.co/mrHH6d1m/pixil-frame-0-4.png" /> pepperOS: "will never be done"
## Trying the kernel
## Description
First install the dependencies: `sudo apt install python3 xorriso make qemu-system`
PepperOS is a 64-bit freely-licensed monolithic kernel for x86 processors, with round-robin preemptive scheduling and 4-level paging. See the [manual](docs/MANUAL.md) for more.
Also, you have to get an x86_64 toolchain for compilation. The easiest way to do that on most systems is to install it from Homebrew:
## Trying the kernel in QEMU
### Debian-based distributions
First, install the dependencies: `sudo apt install nasm python3 xorriso make qemu-system`
Then, you can get an x86_64 toolchain for compilation. The easiest way to do that on most systems is to install it from Homebrew:
```
brew install x86_64-elf-gcc
```
Then, to compile the kernel and make an ISO image file: `make build-iso`
To run it with QEMU, `make run`
If you're already on a 64-bit machine (which you probably are), and don't want to install a cross-compiler, you can just override `CC` and `LD` variables in the Makefile, like so:
```
CC := gcc
LD := ld
```
Then, to compile the kernel and make an ISO image file, run: `make build-iso`
To run it with QEMU, do: `make run`
## Trying the kernel on real hardware
Compile the kernel and generate an ISO image like described above, then burn the image to a USB stick, `/dev/sdX` being the device name (you can get it using `lsblk`):
```
sudo dd if=pepper.iso of=/dev/sdX
```
## TODO
@@ -44,7 +65,7 @@ In the future, maybe?
PepperOS wouldn't be possible without the following freely-licensed software:
- the [Limine](https://codeberg.org/Limine/Limine) portable bootloader
- Marco Paland's freestanding [printf implementation](https://github.com/mpaland)
- Charles Nicholson's [nanoprintf](https://github.com/charlesnicholson/nanoprintf)
- Mintuski's [Flanterm](https://codeberg.org/Mintsuki/Flanterm) terminal emulator
...and without these amazing resources:
@@ -52,3 +73,4 @@ PepperOS wouldn't be possible without the following freely-licensed software:
- the [OSDev](https://osdev.org) wiki & forums
- Intel 64 and IA-32 Architectures Software Developer's Manual
- Documentation for the [GNU Compiler Collection](https://gcc.gnu.org/onlinedocs/gcc/)
- dreamos82's [OSDev Notes](https://github.com/dreamportdev/Osdev-Notes/tree/master)
+19
View File
@@ -0,0 +1,19 @@
# PepperOS Manual
# Table of Contents
- nothing (yet).
## I. Kernel architecture
### a. Boot process
### b. Memory management
### c. Scheduling
### d. Input/Output
## II. Syscall table
Not yet implemented.
+1 -1
View File
@@ -11,7 +11,7 @@
#define PEPPEROS_VERSION_MAJOR "0"
#define PEPPEROS_VERSION_MINOR "0"
#define PEPPEROS_VERSION_PATCH "58"
#define PEPPEROS_SPLASH "\x1b[38;5;196mPepperOS\x1b[0m version "PEPPEROS_VERSION_MAJOR"."PEPPEROS_VERSION_MINOR"."PEPPEROS_VERSION_PATCH"\n"
#define PEPPEROS_SPLASH "\x1b[38;5;196mPepperOS\x1b[0m version \x1b[38;5;220m"PEPPEROS_VERSION_MAJOR"."PEPPEROS_VERSION_MINOR"."PEPPEROS_VERSION_PATCH"\x1b[0m built on \x1b[38;5;40m"__DATE__" "__TIME__"\x1b[0m\n"
/* process */
#define PROCESS_NAME_MAX 64
View File
+3 -3
View File
@@ -15,9 +15,9 @@ enum ErrorCodes {
#define CLEAR_INTERRUPTS __asm__ volatile("cli")
#define SET_INTERRUPTS __asm__ volatile("sti")
#include "io/serial/serial.h"
#include "io/term/term.h"
#include "idt/idt.h"
#include <io/serial/serial.h>
#include <io/term/term.h>
#include <idt/idt.h>
#include <stdbool.h>
extern volatile uint64_t ticks;
View File
@@ -11,7 +11,7 @@
#include <stdint.h>
#include <limine.h>
#include "mem/heap/kheap.h"
#include <mem/kheap.h>
#include <kernel.h>
void paging_init(struct boot_context boot_ctx);
@@ -8,7 +8,7 @@
#define PROCESS_H
#include <stddef.h>
#include "config.h"
#include <config.h>
#include <stdint.h>
typedef enum {
+2
View File
@@ -1,6 +1,8 @@
timeout: 3
interface_branding: Welcome to the PepperOS disk!
/PepperOS
protocol: limine
comment: Default configuration (warning: spicy)
path: boot():/boot/pepperk
+2 -2
View File
@@ -5,8 +5,8 @@
*/
#include <kernel.h>
#include "limine.h"
#include "string/string.h"
#include <limine.h>
#include <string/string.h>
#include <stddef.h>
extern struct boot_context boot_ctx;
+3 -3
View File
@@ -5,9 +5,9 @@
*/
#include <stddef.h>
#include "idt/idt.h"
#include "io/serial/serial.h"
#include "kernel.h"
#include <idt/idt.h>
#include <io/serial/serial.h>
#include <kernel.h>
extern struct init_status init;
extern int panic_count;
+1 -1
View File
@@ -5,7 +5,7 @@
*/
#include <stdint.h>
#include "kernel.h"
#include <kernel.h>
#include <stddef.h>
extern struct init_status init;
+6 -6
View File
@@ -4,16 +4,16 @@
* @license GPL-3.0-only
*/
#include "idt.h"
#include <idt/idt.h>
#include <stdint.h>
#include <stddef.h>
#include "io/serial/serial.h"
#include "io/kbd/ps2.h"
#include <io/serial/serial.h>
#include <io/kbd/ps2.h>
#include <kernel.h>
#include <stdbool.h>
#include "sched/scheduler.h"
#include "config.h"
#include "sched/process.h"
#include <sched/scheduler.h>
#include <config.h>
#include <sched/process.h>
struct interrupt_descriptor idt[256];
struct idtr idt_reg;
+3 -3
View File
@@ -4,10 +4,10 @@
* @license GPL-3.0-only
*/
#include "io/serial/serial.h"
#include "ps2.h"
#include <io/serial/serial.h>
#include <io/kbd/ps2.h>
#include <stdint.h>
#include "io/term/term.h"
#include <io/term/term.h>
#include <kernel.h>
#include <stddef.h>
+2 -2
View File
@@ -5,7 +5,7 @@
*/
#include <kernel.h>
#include "serial.h"
#include <io/serial/serial.h>
extern struct init_status init;
@@ -61,8 +61,8 @@ int serial_init()
// Set normal operation mode
outb(PORT + 4, 0x0F);
DEBUG("*** Welcome to PepperOS! ***");
init.serial = true;
DEBUG("*** Welcome to PepperOS! (built @ %s %s) ***", __DATE__, __TIME__);
return 0;
}
+1 -1
View File
@@ -41,7 +41,7 @@
#define FLANTERM_IN_FLANTERM
#endif
#include "flanterm.h"
#include <io/term/flanterm.h>
// Tries to implement this standard for terminfo
// https://man7.org/linux/man-pages/man4/console_codes.4.html
+2 -2
View File
@@ -51,8 +51,8 @@
#define FLANTERM_IN_FLANTERM
#endif
#include "../flanterm.h"
#include "fb.h"
#include <io/term/flanterm.h>
#include <io/term/flanterm_backends/fb.h>
void *memset(void *, int, size_t);
void *memcpy(void *, const void *, size_t);
+11 -11
View File
@@ -13,18 +13,18 @@ because this shitty implementation will be replaced one day by Flanterm
#include <stddef.h>
#include <kernel.h>
#include "term.h"
#include "config.h"
#include "flanterm.h"
#include "flanterm_backends/fb.h"
#include "mem/heap/kheap.h"
#include "limine.h"
#include <io/term/term.h>
#include <config.h>
#include <io/term/flanterm.h>
#include <io/term/flanterm_backends/fb.h>
#include <mem/kheap.h>
#include <limine.h>
#include <stdarg.h>
#include "sched/spinlock.h"
#include "io/serial/serial.h"
#include <sched/spinlock.h>
#include <io/serial/serial.h>
#define NANOPRINTF_IMPLEMENTATION
#include "nanoprintf.h"
#include <io/term/nanoprintf.h>
extern struct flanterm_context* ft_ctx;
extern struct init_status init;
@@ -136,8 +136,8 @@ void term_init()
{
uint32_t bgColor = 0x252525;
ft_ctx = flanterm_fb_init(
kmalloc,
flanterm_free_wrapper,
NULL,
NULL,
boot_ctx.fb->address, boot_ctx.fb->width, boot_ctx.fb->height, boot_ctx.fb->pitch,
boot_ctx.fb->red_mask_size, boot_ctx.fb->red_mask_shift,
boot_ctx.fb->green_mask_size, boot_ctx.fb->green_mask_shift,
+21 -23
View File
@@ -7,24 +7,23 @@
#include <stdbool.h>
#include <stddef.h>
#include <limine.h>
#include "io/term/term.h"
#include "io/term/term.h"
#include "io/serial/serial.h"
#include "mem/gdt/gdt.h"
#include "mem/misc/utils.h"
#include "idt/idt.h"
#include "kernel.h"
#include "time/timer.h"
#include "io/kbd/ps2.h"
#include "mem/paging/pmm.h"
#include "mem/paging/paging.h"
#include "mem/paging/vmm.h"
#include "mem/heap/kheap.h"
#include "sched/process.h"
#include "sched/scheduler.h"
#include "config.h"
#include "io/term/flanterm.h"
#include "io/term/flanterm_backends/fb.h"
#include <io/term/term.h>
#include <io/serial/serial.h>
#include <mem/gdt.h>
#include <mem/utils.h>
#include <idt/idt.h>
#include <kernel.h>
#include <time/timer.h>
#include <io/kbd/ps2.h>
#include <mem/pmm.h>
#include <mem/paging.h>
#include <mem/vmm.h>
#include <mem/kheap.h>
#include <sched/process.h>
#include <sched/scheduler.h>
#include <config.h>
#include <io/term/flanterm.h>
#include <io/term/flanterm_backends/fb.h>
// Limine version used
__attribute__((used, section(".limine_requests")))
@@ -94,15 +93,16 @@ void kmain()
CLEAR_INTERRUPTS;
if (!LIMINE_BASE_REVISION_SUPPORTED) hcf();
serial_init();
timer_init();
// Populate boot context
boot_ctx.fb = framebuffer_request.response ? framebuffer_request.response->framebuffers[0] : NULL;
boot_ctx.mmap = memmap_request.response ? memmap_request.response : NULL;
boot_ctx.hhdm = hhdm_request.response ? hhdm_request.response : NULL;
boot_ctx.kaddr = kerneladdr_request.response ? kerneladdr_request.response : NULL;
term_init();
serial_init();
timer_init();
boot_mem_display();
pmm_init(boot_ctx);
@@ -112,8 +112,6 @@ void kmain()
keyboard_init(FR);
term_init();
gdt_init();
idt_init();
+2 -2
View File
@@ -4,9 +4,9 @@
* @license GPL-3.0-only
*/
#include "gdt.h"
#include <mem/gdt.h>
#include <stdint.h>
#include "io/serial/serial.h"
#include <io/serial/serial.h>
#include <kernel.h>
// Descriptors are 8-byte wide (64bits)
+5 -5
View File
@@ -4,13 +4,13 @@
* @license GPL-3.0-only
*/
#include "kheap.h"
#include "mem/paging/paging.h"
#include "mem/paging/pmm.h"
#include <mem/kheap.h>
#include <mem/paging.h>
#include <mem/pmm.h>
#include <stddef.h>
#include <kernel.h>
#include "sched/process.h"
#include "config.h"
#include <sched/process.h>
#include <config.h>
extern uint64_t kernel_phys_base;
extern uint64_t kernel_virt_base;
+3 -3
View File
@@ -4,12 +4,12 @@
* @license GPL-3.0-only
*/
#include "paging.h"
#include "pmm.h"
#include <mem/paging.h>
#include <mem/pmm.h>
#include <kernel.h>
#include <stddef.h>
#include <limine.h>
#include "config.h"
#include <config.h>
/*
Paging on x86 uses four different page table levels:
+3 -3
View File
@@ -11,13 +11,13 @@ it will probably need to get some info from Limine,
to see which pages are used by kernel/bootloader/mmio/fb etc.
*/
#include "paging.h"
#include <mem/paging.h>
#include <limine.h>
#include <stddef.h>
#include <stdint.h>
#include <kernel.h>
#include "mem/misc/utils.h"
#include "pmm.h"
#include <mem/utils.h>
#include <mem/pmm.h>
/*
First we'll have to discover the physical memory layout,
+2 -2
View File
@@ -7,8 +7,8 @@
#include <stddef.h>
#include <stdint.h>
#include <limine.h>
#include "kernel.h"
#include "string/string.h"
#include <kernel.h>
#include <string/string.h>
// We won't be linked to standard library, but still need the basic mem* functions
// so everything goes allright with the compiler
+3 -3
View File
@@ -13,10 +13,10 @@ in a specified virtual space
compared to the PMM which allocs/frees 4kb frames ("physical pages").
*/
#include "vmm.h"
#include "paging.h"
#include <mem/vmm.h>
#include <mem/paging.h>
#include <stddef.h>
#include "pmm.h"
#include <mem/pmm.h>
#include <kernel.h>
void* vmm_pt_root = 0;
+8 -8
View File
@@ -5,15 +5,15 @@
*/
#include <stddef.h>
#include "process.h"
#include "mem/heap/kheap.h"
#include "kernel.h"
#include "string/string.h"
#include "mem/gdt/gdt.h"
#include "config.h"
#include "io/serial/serial.h"
#include <sched/process.h>
#include <mem/kheap.h>
#include <kernel.h>
#include <string/string.h>
#include <mem/gdt.h>
#include <config.h>
#include <io/serial/serial.h>
#include "io/term/flanterm.h"
#include <io/term/flanterm.h>
extern struct flanterm_context* ft_ctx;
struct process_t* processes_list;
+4 -4
View File
@@ -4,11 +4,11 @@
* @license GPL-3.0-only
*/
#include "kernel.h"
#include "process.h"
#include "mem/paging/paging.h"
#include <kernel.h>
#include <sched/process.h>
#include <mem/paging.h>
#include <stdint.h>
#include "io/serial/serial.h"
#include <io/serial/serial.h>
extern struct process_t* processes_list;
extern struct process_t* current_process;
+2 -2
View File
@@ -6,8 +6,8 @@
#include <stdatomic.h>
#include <stdbool.h>
#include "kernel.h"
#include "spinlock.h"
#include <kernel.h>
#include <sched/spinlock.h>
/*
* spinlock_acquire - Lock a lock
+2 -2
View File
@@ -5,9 +5,9 @@
*/
#include <stdint.h>
#include "io/serial/serial.h"
#include <io/serial/serial.h>
#include <kernel.h>
#include "config.h"
#include <config.h>
/*
For now, the timer module will be using the PIC.