commit 0de2bf13007439a4a486fcc7280aad9724853964 Author: david-on-debian Date: Tue May 20 20:29:10 2025 -0500 Upload files to "/" diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..98662eb --- /dev/null +++ b/Makefile @@ -0,0 +1,71 @@ +# === Config === +TARGET := boot/espresso.bin +ISO := boot/espresso.iso +CC := i686-elf-gcc +AS := i686-elf-as +NASM := nasm +NASMFLAGS := -f elf32 +CFLAGS := -std=gnu99 -ffreestanding -O2 -Wall -Wextra -msse +LDFLAGS := -T linker.ld -ffreestanding -O2 -nostdlib +SRC_DIRS := kernel drivers src lib +INCLUDE_DIRS := include +INCLUDES := $(addprefix -I, $(INCLUDE_DIRS)) +ISO_DIR := isodir +BOOT_DIR := $(ISO_DIR)/boot +GRUB_DIR := $(BOOT_DIR)/grub +GRUB_CFG := grub.cfg + +# === File collection === +C_SRCS := $(foreach dir, $(SRC_DIRS), $(shell find $(dir) -name '*.c')) +S_SRCS := boot.s crti.s crtn.s misc_asm.s +NASM_SRCS := idt.asm isr128.asm gdt.asm isr_stub_table.asm +CRTI_OBJ := crti.o +CRTBEGIN_OBJ := $(shell $(CC) $(CFLAGS) -print-file-name=crtbegin.o) +CRTEND_OBJ := $(shell $(CC) $(CFLAGS) -print-file-name=crtend.o) +CRTN_OBJ := crtn.o +OBJS := $(C_SRCS:.c=.o) $(S_SRCS:.s=.o) $(NASM_SRCS:.asm=.o) + +OBJ_LINK_LIST := $(CRTI_OBJ) $(CRTBEGIN_OBJ) $(OBJS) $(CRTEND_OBJ) $(CRTN_OBJ) +INTERNAL_OBJS := $(CRTI_OBJ) $(OBJS) $(CRTN_OBJ) + +# === Build all targets === +build: all iso run clean + +# === Default target === +all: $(TARGET) + +# === Linking === +$(TARGET): boot.o $(filter-out boot.o, $(OBJ_LINK_LIST)) + @mkdir -p $(dir $@) + $(CC) $(LDFLAGS) -o $@ $^ -lgcc + +# === Compiling C files === +%.o: %.c + $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ + +# === Assembling S files === +%.o: %.s + $(AS) $< -o $@ + +%.o: %.asm + $(NASM) $(NASMFLAGS) $< -o $@ + +# === ISO generation === +iso: $(TARGET) + @grub-file --is-x86-multiboot $(TARGET) && echo "multiboot confirmed" || (echo "not multiboot" && exit 1) + mkdir -p $(GRUB_DIR) + cp $(TARGET) $(BOOT_DIR)/ + cp $(GRUB_CFG) $(GRUB_DIR)/ + grub-mkrescue -o $(ISO) $(ISO_DIR) + +# === Run in QEMU === +run: iso + qemu-system-i386 -kernel $(TARGET) -drive file=espresso.img,format=raw,if=ide,readonly=off,rerror=report,werror=report -cpu qemu32,sse2 #-singlestep + +# === Clean all build artifacts === +clean: + rm -f $(INTERNAL_OBJS) $(TARGET) $(ISO) + rm -rf $(ISO_DIR) + +.PHONY: all clean iso run + diff --git a/isr128.asm b/isr128.asm new file mode 100644 index 0000000..7c9a869 --- /dev/null +++ b/isr128.asm @@ -0,0 +1,10 @@ +[bits 32] +global isr128 +extern isr_handler +extern common_isr_stub + +isr128: + cli + push dword 0 ; No error code + push dword 128 ; Interrupt number + jmp common_isr_stub diff --git a/isr_stub_table.asm b/isr_stub_table.asm new file mode 100644 index 0000000..4040473 --- /dev/null +++ b/isr_stub_table.asm @@ -0,0 +1,85 @@ +[bits 32] +global isr_stub_table +global isr0, isr1, isr2, isr3, isr4, isr5, isr6, isr7 +global isr8, isr9, isr10, isr11, isr12, isr13, isr14, isr15 +global isr16, isr17, isr18, isr19, isr20, isr21, isr22, isr23 +global isr24, isr25, isr26, isr27, isr28, isr29, isr30, isr31 + +extern isr_handler +extern _push_regs +extern _pop_regs + +%macro ISR_NOERR 1 +isr%1: + cli + push dword 0 ; Fake error code + push dword %1 ; Interrupt number + jmp isr_common_stub +%endmacro + +%macro ISR_ERR 1 +isr%1: + cli + push dword %1 ; Interrupt number + jmp isr_common_stub +%endmacro + +; ISRs 0-31 (exceptions) +ISR_NOERR 0 +ISR_NOERR 1 +ISR_NOERR 2 +ISR_NOERR 3 +ISR_NOERR 4 +ISR_NOERR 5 +ISR_NOERR 6 +ISR_NOERR 7 +ISR_ERR 8 ; Double fault +ISR_NOERR 9 +ISR_ERR 10 ; Invalid TSS +ISR_ERR 11 ; Segment not present +ISR_ERR 12 ; Stack segment fault +ISR_ERR 13 ; General protection fault +ISR_ERR 14 ; Page fault +ISR_NOERR 15 +ISR_NOERR 16 +ISR_NOERR 17 +ISR_NOERR 18 +ISR_NOERR 19 +ISR_NOERR 20 +ISR_NOERR 21 +ISR_NOERR 22 +ISR_NOERR 23 +ISR_NOERR 24 +ISR_NOERR 25 +ISR_NOERR 26 +ISR_NOERR 27 +ISR_NOERR 28 +ISR_NOERR 29 +ISR_ERR 30 ; Security exception +ISR_NOERR 31 + +isr_common_stub: + call _push_regs + push ds + push es + push fs + push gs + + mov ax, 0x10 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + + push esp + call isr_handler + add esp, 4 + + pop gs + pop fs + pop es + pop ds + call _pop_regs + add esp, 8 + sti + iret diff --git a/linker.ld b/linker.ld new file mode 100644 index 0000000..b6f0aed --- /dev/null +++ b/linker.ld @@ -0,0 +1,71 @@ +/* The bootloader will look at this image and start execution at the symbol + designated as the entry point. */ +ENTRY(_start) + +/* Tell where the various sections of the object files will be put in the final + kernel image. */ +SECTIONS +{ + /* It used to be universally recommended to use 1M as a start offset, + as it was effectively guaranteed to be available under BIOS systems. + However, UEFI has made things more complicated, and experimental data + strongly suggests that 2M is a safer place to load. In 2016, a new + feature was introduced to the multiboot2 spec to inform bootloaders + that a kernel can be loaded anywhere within a range of addresses and + will be able to relocate itself to run from such a loader-selected + address, in order to give the loader freedom in selecting a span of + memory which is verified to be available by the firmware, in order to + work around this issue. This does not use that feature, so 2M was + chosen as a safer option than the traditional 1M. */ + . = 2M; + + /* First put the multiboot header, as it is required to be put very early + in the image or the bootloader won't recognize the file format. + Next we'll put the .text section. */ + .text BLOCK(4K) : ALIGN(4K) + { + KEEP(*(.multiboot)) + *(.text) + } + + /* Read-only data. */ + .rodata BLOCK(4K) : ALIGN(4K) + { + *(.rodata) + } + + /* Read-write data (initialized) */ + .data BLOCK(4K) : ALIGN(4K) + { + *(.data) + } + + /* Read-write data (uninitialized) and stack */ + .bss BLOCK(4K) : ALIGN(4K) + { + *(COMMON) + *(.bss) + } + + /* Include the list of initialization functions sorted. */ + .init_array : + { + crti.o(.init_array) + KEEP (*(SORT(EXCLUDE_FILE(crti.o crtn.o) .init_array.*))) + KEEP (*(EXCLUDE_FILE(crti.o crtn.o) .init_array)) + crtn.o(.init_array) + } + + /* Include the list of termination functions sorted. */ + .fini_array : + { + crti.o(.fini_array) + KEEP (*(SORT(EXCLUDE_FILE(crti.o crtn.o) .fini_array.*))) + KEEP (*(EXCLUDE_FILE(crti.o crtn.o) .fini_array)) + crtn.o(.fini_array) + } + + /* The compiler may produce other sections, by default it will put them in + a segment with the same name. Simply add stuff here as needed. */ +} + diff --git a/misc_asm.s b/misc_asm.s new file mode 100644 index 0000000..408b5b6 --- /dev/null +++ b/misc_asm.s @@ -0,0 +1,62 @@ +/* + A bunch of functions I could have written in C (or not), but decided not to, + Mostly so I could get more experience in assembler. +*/ + +/* + DO NOT USE "pusha" AND/OR "popa"!!! + THEY ARE DEPRECATED (or something like that) + AND SHOULD NOT BE USED!!! + INSTEAD PUSH/POP REGISTERS ON/OFF THE STACK INDIVIDUALLY!!! +*/ + + +.section .text + +.global _enable_paging_asm + +.global _push_regs +.global _pop_regs + +.global _hang_asm + +_enable_paging_asm: + push %eax + + mov %cr0, %eax + or $0x80000000, %eax + mov %eax, %cr0 + + pop %eax + + ret + +_push_regs: + push %eax + push %ebx + push %ecx + push %edx + push %esi + push %edi + push %esp + push %ebp + + ret + +_pop_regs: + pop %ebp + pop %esp + pop %edi + pop %esi + pop %edx + pop %ecx + pop %ebx + pop %eax + + ret + +_hang_asm: + hlt + jmp _hang_asm + +.section .data