commit e40059e70d060276929fe9608e4cc89c1c8463ef Author: SpookyDervish Date: Mon Jul 13 13:07:29 2026 +1000 first boot diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5fa52b0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +CometOS.bin +CometOS.iso +build/ +iso/ \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c19ce09 --- /dev/null +++ b/Makefile @@ -0,0 +1,77 @@ +# ============================================================================== +# 1. PROJECT CONFIGURATION +# ============================================================================== +BIN_TARGET := CometOS.bin +TARGET := CometOS.iso +BUILD_DIR := build +LDSCRIPT := linker.ld + +# Toolchain definitions +CXX := g++ +ASM := as +LD := ld + +# Compiler and Linker Flags +ASMFLAGS := --32 +CXXFLAGS := -Wall -Wextra -O3 -m32 -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore +LDFLAGS := -T $(LDSCRIPT) -melf_i386 + +# ============================================================================== +# 2. FILE SEARCH AND COMPONENT SETUP +# ============================================================================== +# Find all source files recursively in the current folder and subfolders +SRCS := $(wildcard src/**/*.cpp src/**/*.S) + +# Strip paths and convert extensions to .o (e.g., "src/main.cpp" -> "main.o") +RAW_OBJS := $(patsubst %.cpp,%.o,$(patsubst %.S,%.o,$(notdir $(SRCS)))) + +# Place all object files into the build directory +OBJS := $(addprefix $(BUILD_DIR)/, $(RAW_OBJS)) + +# Automagically tell Make where to find the original source files +VPATH := $(sort $(dir $(SRCS))) + +# ============================================================================== +# 3. BUILD RULES +# ============================================================================== +.PHONY: all clean run + +# Default rule +all: $(TARGET) + +run: $(TARGET) + qemu-system-i386 -cdrom $(TARGET) -m 1024 + +# Link rule: Combines all objects using the linker script +$(BIN_TARGET): $(OBJS) $(LDSCRIPT) + $(LD) $(OBJS) $(LDFLAGS) -o $@ + @echo "Build successful: $(BIN_TARGET)" + +$(TARGET): $(BIN_TARGET) + @mkdir iso/boot/grub -p + @cp $< iso/boot/ + @echo 'set default=0' > iso/boot/grub/grub.cfg + @echo 'set timeout=0' >> iso/boot/grub/grub.cfg + @echo '' >> iso/boot/grub/grub.cfg + @echo 'menuentry "CometOS" {' >> iso/boot/grub/grub.cfg + @echo ' multiboot /boot/CometOS.bin' >> iso/boot/grub/grub.cfg + @echo ' boot' >> iso/boot/grub/grub.cfg + @echo '}' >> iso/boot/grub/grub.cfg + grub-mkrescue --output=$@ iso + +# Compilation rule for C++ files +$(BUILD_DIR)/%.o: %.cpp | $(BUILD_DIR) + $(CXX) $(CXXFLAGS) -c $< -o $@ + +# Compilation rule for Assembly files +$(BUILD_DIR)/%.o: %.S | $(BUILD_DIR) + $(ASM) $(ASMFLAGS) -c $< -o $@ + +# Safely create the build directory if it doesn't exist +$(BUILD_DIR): + mkdir -p $(BUILD_DIR) + +# Cleanup rule +clean: + rm -rf $(BUILD_DIR) $(BIN_TARGET) $(TARGET) + @echo "Cleaned up build files." diff --git a/linker.ld b/linker.ld new file mode 100644 index 0000000..a4a68d7 --- /dev/null +++ b/linker.ld @@ -0,0 +1,36 @@ +ENTRY(loader) +OUTPUT_FORMAT(elf32-i386) +OUTPUT_ARCH(i386:i386) + +SECTIONS +{ + . = 0x0100000; + + .text : + { + *(.multiboot) + *(.text*) + *(.rodata) + } + + .data : + { + start_ctors = .; + KEEP(*( .init_array )); + KEEP(*(SORT_BY_INIT_PRIORITY( .init_array.* ))) + end_ctors = .; + + *(.data) + } + + .bss : + { + *(.bss) + } + + /DISCARD/ : + { + *(.fini_array*) + *(.comment) + } +} \ No newline at end of file diff --git a/src/boot/loader.S b/src/boot/loader.S new file mode 100644 index 0000000..62abeab --- /dev/null +++ b/src/boot/loader.S @@ -0,0 +1,31 @@ +.set MAGIC, 0x1badb002 +.set FLAGS, (1<<0 | 1<<1) +.set CHECKSUM, -(MAGIC + FLAGS) + +.section .multiboot + .long MAGIC + .long FLAGS + .long CHECKSUM + +.section .text +.extern kernelMain +.extern callConstructors +.global loader + +loader: + mov $kernel_stack, %esp + + call callConstructors + + push %eax + push %ebx + call kernelMain + +_stop: # should never actually reach this but just in case... + cli + hlt + jmp _stop + +.section .bss +.space 2*1024*1024 # Give the kernel 2MB of stack space +kernel_stack: diff --git a/src/include/multiboot.h b/src/include/multiboot.h new file mode 100644 index 0000000..bf9fed9 --- /dev/null +++ b/src/include/multiboot.h @@ -0,0 +1,125 @@ +#ifndef MULTIBOOT_H +#define MULTIBOOT_H +// The following was copied from https://www.gnu.org/software/grub/manual/multiboot/html_node/multiboot.h.html + +/* multiboot.h - the header for Multiboot */ +/* Copyright (C) 1999, 2001 Free Software Foundation, Inc. + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* Macros. */ + +/* The magic number for the Multiboot header. */ +#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 + +/* The flags for the Multiboot header. */ +#ifdef __ELF__ +# define MULTIBOOT_HEADER_FLAGS 0x00000003 +#else +# define MULTIBOOT_HEADER_FLAGS 0x00010003 +#endif + +/* The magic number passed by a Multiboot-compliant boot loader. */ +#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 + +/* The size of our stack (16KB). */ +#define STACK_SIZE 0x4000 + +/* C symbol format. HAVE_ASM_USCORE is defined by configure. */ +#ifdef HAVE_ASM_USCORE +# define EXT_C(sym) _ ## sym +#else +# define EXT_C(sym) sym +#endif + +#ifndef ASM +/* Do not include here in boot.S. */ + +/* Types. */ + +/* The Multiboot header. */ +typedef struct multiboot_header +{ + unsigned long magic; + unsigned long flags; + unsigned long checksum; + unsigned long header_addr; + unsigned long load_addr; + unsigned long load_end_addr; + unsigned long bss_end_addr; + unsigned long entry_addr; +} multiboot_header_t; + +/* The symbol table for a.out. */ +typedef struct aout_symbol_table +{ + unsigned long tabsize; + unsigned long strsize; + unsigned long addr; + unsigned long reserved; +} aout_symbol_table_t; + +/* The section header table for ELF. */ +typedef struct elf_section_header_table +{ + unsigned long num; + unsigned long size; + unsigned long addr; + unsigned long shndx; +} elf_section_header_table_t; + +/* The Multiboot information. */ +typedef struct multiboot_info +{ + unsigned long flags; + unsigned long mem_lower; + unsigned long mem_upper; + unsigned long boot_device; + unsigned long cmdline; + unsigned long mods_count; + unsigned long mods_addr; + union + { + aout_symbol_table_t aout_sym; + elf_section_header_table_t elf_sec; + } u; + unsigned long mmap_length; + unsigned long mmap_addr; +} multiboot_info_t; + +/* The module structure. */ +typedef struct module +{ + unsigned long mod_start; + unsigned long mod_end; + unsigned long string; + unsigned long reserved; +} module_t; + +/* The memory map. Be careful that the offset 0 is base_addr_low + but no size. */ +typedef struct memory_map +{ + unsigned long size; + unsigned long base_addr_low; + unsigned long base_addr_high; + unsigned long length_low; + unsigned long length_high; + unsigned long type; +} memory_map_t; + +#endif /* ! ASM */ + +#endif /* MULTIBOOT_H */ \ No newline at end of file diff --git a/src/kernel/kernel.cpp b/src/kernel/kernel.cpp new file mode 100644 index 0000000..106c5d2 --- /dev/null +++ b/src/kernel/kernel.cpp @@ -0,0 +1,18 @@ +#include "../include/multiboot.h" +#include "vga_console.h" + +typedef void(*constructor)(); +extern "C" constructor start_ctors; +extern "C" constructor end_ctors; +extern "C" void callConstructors() +{ + for (constructor* i = &start_ctors; i != &end_ctors; i++) { + (*i)(); + } +} + +extern "C" void kernelMain(multiboot_info* multibootInfo, unsigned int magicNumber) { + vgaPrint("Hello, world!"); + + while (true); +} \ No newline at end of file diff --git a/src/kernel/vga_console.cpp b/src/kernel/vga_console.cpp new file mode 100644 index 0000000..51deabf --- /dev/null +++ b/src/kernel/vga_console.cpp @@ -0,0 +1,13 @@ +#include "vga_console.h" + +void vgaPrint(char* string) { + static unsigned short* vgaVideoMemory = (unsigned short*)0xb8000; + + for (unsigned int i = 0; string[i] != 0; i++) { + /* + The high byte in the VGA video memory contains colour info we don't want to overwrite. + So, we have to combine the high byte with the char we're writing. + */ + vgaVideoMemory[i] = (vgaVideoMemory[i] & 0xFF00) | string[i]; + } +} \ No newline at end of file diff --git a/src/kernel/vga_console.h b/src/kernel/vga_console.h new file mode 100644 index 0000000..f46b390 --- /dev/null +++ b/src/kernel/vga_console.h @@ -0,0 +1,3 @@ +#pragma once + +void vgaPrint(char* string); \ No newline at end of file