summaryrefslogtreecommitdiff
path: root/doc/develop
diff options
context:
space:
mode:
authorArseney300 <Arseney300@gmail.com>2026-03-29 02:07:17 +0700
committerArseney300 <Arseney300@gmail.com>2026-04-08 01:19:07 +0700
commit4912796d2e88c6eb5d02fbf0fb9c39f8c9f7cd4c (patch)
tree9ee8110e2c090c888f23797cda56c7e2df531695 /doc/develop
bastion: initial implementation
ready project skeleton dual-arch build system with Linux-config style configuration UEFI EFI stub loader (PE32+) for x86_64 and AArch64 ELF64 kernel parser Temporary framebuffer console freestanding string and c++ abi stubs For now, kernel boots, prints banner, memory map and go halt
Diffstat (limited to 'doc/develop')
-rw-r--r--doc/develop/file_summary.md28
-rw-r--r--doc/develop/overall.md123
-rw-r--r--doc/develop/study_resources.md15
3 files changed, 166 insertions, 0 deletions
diff --git a/doc/develop/file_summary.md b/doc/develop/file_summary.md
new file mode 100644
index 0000000..de7df15
--- /dev/null
+++ b/doc/develop/file_summary.md
@@ -0,0 +1,28 @@
+Makefile - Top-level Makefile, deligates to boot/ and kernel/ Makefiles with ARCH=x86_64 or ARCH=aarch64. Provides make all, make disk-aarch64, make run-x86_64 and other
+config.mk - Shared toolchain config - defines Clang/LLD paths, per-arch target triples and flags, common c++20 freestanding flags (-fno-exception, -fno-rtti, -nostlib and other)
+
+include/boot_info.h - The loader <-> kernel boot_info struct.
+
+boot/Makefile - Builds .efi binary via ELF->PE32+ objcopy. Compiles c++ with --target=x86_64-unknown-windows (or aarch64), links with lld-link to produce a PE32+ .efi binary directly
+boot/common/efi.h - Standalone UEFI types (without gnu-efi or EDK2 dependency). It defines EFI_SYSTEM_TABLE, EFI_BOOT_SERVICE, GOP, FIle Protocol, Loaded Image Protocol, GUIDs, status codes.
+boot/common/elf.h - ELF64 format definitions. It defines Elf64_Ehdr, Elf64_Phdr, segment types(PT_LOAD), machine types(EM_X86_64, EM_AARCH64), and the ElfLoadResult struct.
+boot/common/elf_parser.cpp - Reads ELF64 bin from memory, validates headers, calculates virtual address span, allocates phisycal pages via UEFI AllocatePages, copies PT_LOAD segments, zeroes BSS. Returns entry point and load addresses.
+boot/common/efi_loader.cpp - Main boot logic: load ELF, GOP, memory map, ExitBootService. Opens the ESP filesystem, reads bastion.elf, calls the ELF parser, locates GOF framebuffer, finds ACPI/FDT config tables, does GetMemoryMap -> ExitBootServices, converts UEFI memory map to our format, populates BootInfo.
+boot/x86_64/entry.cpp - efi_main() -> common loader -> jump to kernel. Calls efi_loader_main(), then computes the physical entry address from the ELF virtual entry and jumps to the kernel with BootInfo* in RDI register.
+boot/x86_64/linker.ld - PE32+ layout for x86_64 loader. Linker script for this loader - section layout for text/rodata/data/bss.
+boot/aarch64/entry.cpp - efi_main() -> common loader -> jump to kernel but for aarch64. Instead of RDI uses X0(AAPCS64)
+boot/aarch64/linkel.ld - PE32+ layout for aarch64 loader
+
+kernel/Makefile - Builds kernel.elf - auto-discovers .cpp asd .S sources via wildcard, compiles as freestanding ELF, links with the arch-specifc linker script
+kernel/arch/x86_64/entry.S - Assembly entry: set stack, call kernel_main. Sets up a 16KiB stack, calls ```kernel_main(BootInfo*)``` . Written in AT&T syntax for Clang's integrated assembler.
+kernel/arch/x86_64/linker.ld - Places kernel at phiscal 0x100000 (1MiB). Defines .text, .rodata .data .bss sections with section boundary symbols (__bss_start, __kernel_end)
+kernel/arch/aarch64/entry.S - Same for AArch64. Masks interrupts, sets stack from _stack_top, calls kernel_main.
+kernel/arch/aarch64/linkel.ld - Same, but at 0x40100000 (QEMU virt machine convention)
+kernel/core/kernel_main.cpp - First c++ code: init console, dump memory map, halt. Validate BootInfo magic, init the framebuffer console, prints a banner with arch name, dumps framebuffer info, firmware table addresses, memory map with region types and total usable RAM, then halts.
+kernel/lib/kprint.cpp - Framebuffer console with 8x16 VGA bitmap font (ASCII 32-126).
+kernel/lib/string.cpp - Freestanding memcpy/memset/strlet and other
+kernel/lib/cxxabi.cpp - C++ ABI stubs(```__ctx_atexit``` and other). Has placeholder for new/delete operators. Needed because the compiler emits references to these symbols even in freestanding mode.
+kernel/include/kernel/kprint.h - Console API header
+kernel/include/kernel/types.h - PhysAddr, VirtAddr, aligment helpers
+scripts/create_disk.sh - Creates 64 MiB GPT + FAT32 ESP disp image. Copies BOOTX64.efi to EFI/BOOT/ and bastion.elf to the root. Uses sgdisk + mkfs.vfat + mtools
+scripts/run_qemu.sh - Finds OVMF/AAVMF firmware on the system and launches QEMU with the disk image, serial on stdio, interrupt logging enabled.
diff --git a/doc/develop/overall.md b/doc/develop/overall.md
new file mode 100644
index 0000000..0ea2508
--- /dev/null
+++ b/doc/develop/overall.md
@@ -0,0 +1,123 @@
+# Overall stages of developen BastionOS kernel
+
+## I Phase
+UEFI boot
+
+My main task here is create bootable efi application.
+
+
+First kernel booting stage is running PE32+ efi binary. It calls UEFI Boot Services to get the memory map, framebuffer(GOP) and ACPI/device_tree_pointer (for arm64 if it will supports dts). Then it loads my ELF kernel into memory and jumps to it after calling ExitBootServices().
+GNU-EFI (https://github.com/ncroxon/gnu-efi.git) should help me somehow to do it.
+
+
+So, what we need to have after uefi:
+1) Physical memory map (which regions are usable)
+2) Framebuffer address and pitch (for console)
+3) RSDP pointer (for ACPI table parsing)
+4) Device Tree pointer (for arm)
+5) Kernel's own physical/virtual address
+
+## II Phase
+Arch-Specific CPU setup
+
+# For x86_64
+- Load a GDT (minimal: null, kernel code64, kernel data, user code64, user data, TSS)
+- Set up IDT - 256 entries, wire ISR stubs in assembly, that push error codes uniformly, then call dispatch_interrupt(InterruptFrame&) handler
+- Configure paging: PML4 page table hierarchy, higher-half kernel mapping(canonical address like 0xFFFF800000000000+), recursive or direct-map strategy for page table self-reference
+- Enable and configure the local APIC + I/O APIC (from MADT ACPI table), replace the legacy PIC
+
+# For AArch64:
+- Set up exception vectors(VBAR_EL1) - 4 exception types x 4 source levels = 16 vectors
+- Configure the MMU: TCR_EL1, MAIR_EL1, TTBR0_EL1/ TTBR1_EL1 (user/kernel split), 4-level page tables (4KB granule, 48-bit VA)
+- Set up the GIC(Generic Interrupt Controller) v2 or v3 from device tree info
+
+
+Because of using c++ as main language i can create abstraction for it:
+```
+namespace arch {
+ void init_interrupts();
+ void enable_interrupts();
+ void disable_interrupts();
+ void set_page_table(PhysAddr root);
+ void invalidate_page(VirtAddr addr);
+ [[noreturn]] void halt();
+}
+```
+
+
+## III Phase
+
+### PMM - Physical Memory Manager
+- Parse the boot memory map (that we did in I phase), build a buddy allocator or bitmap allocator over free regions
+- Track allocation in page-sized (4KiB) granules
+- Provide alloc_page() / free_page functions
+
+### VMM - Virtual Memory Manager
+- Implement VirtualAddressSpace object, that wraps a page table root
+- Operations map(VirtAddr, PhysAddr, flags), unmap(VirtAddr), translate(VirtAddr) -> PhysAddr
+- Kernel its own address space; each process will get one later
+- Both archs use 4-level tables with similar structure - abstract the entry format
+
+### Kernel Heap
+- Implement a slab allocator or a simple kmalloc/kfree on tho of the VMM
+- Overload global operator new/delete to use it - this unlocks C++ STL
+
+
+## IV Phase
+### Timer
+- x86_64: APIC Timer (calibrated against HPET or PIT) or TSC deadline mode
+- AArch64: Generic Timer (CNTPCT_EL0, CNTP_TVAL_EL0)
+
+### Scheduler
+- At begining, i want to use simple round-robit with a reade one queue
+- Each task has: a kernel stack, saved register context, an address space
+- Context switch is arch-specific assembly: save/restore registers + swap stack pointer + swap page table root (the best arch for context switching is still riscV with only one simple command, x86 will be very hard(considering Linux code), but if i will not use hash it can be easy and understandable)
+- Preemption via timer interrupt
+
+## V Phase
+### ELF Parser
+- Parse ELF64 header, validate e_ident magic, check EM_X86_64 or EM_AARCH64
+- Iterate program headers(PT_LOAD segments), map them into the process address space at their p_vaddr with correct permissions (rwx from p_flags)
+- Set entry point from e_entry
+
+### Userspace transition
+- Allocate a user stack, set up the initial stack frame (argc, argv, envp, auxv)
+- x86_64: sysretq or iretq to ring3
+- aarch64: eret to EL0
+
+### SysCall
+- x86_64: syscall/sysret via MSRr(LSTAR, STAR, SFMASK)
+- aarch64: svc instruction, handled in the EL1 syncronous exception vector
+- Define a syscall table - start with basic write(), read(), exit(), mmap(), fork()/spawn()/clone()
+
+
+## VI Phase
+### Essential drivers
+- UART/Serial
+- Framebuffer console
+- USB keyboard (or PS/2 for qemu testing)
+- Virtio-blk (block device in QEMU - much simpler than AHCI/NVMe)
+
+### Filesystem
+- Implement a VFS layer (struct Inode, struct File, open()/read()/write()/close())
+- Start with in-memory initramfs (USTAR or CPIO) baked into the boot image
+- Later: ext2 read support (very simple)
+- Later: normal ext4
+- Sometime: fat
+- Never: ntfs
+
+## VII Phase
+## dynamic linking and shared libs
+## porting full libc (or mlibc, that designed for hobby kernels)
+## do full POSIX support
+
+## VIII Phase
+### Network (virtio-net + tcp/ip stack)
+
+## IX Phase
+### multicore/SMP
+
+## X Phase
+## Window drawing
+
+
diff --git a/doc/develop/study_resources.md b/doc/develop/study_resources.md
new file mode 100644
index 0000000..251f06a
--- /dev/null
+++ b/doc/develop/study_resources.md
@@ -0,0 +1,15 @@
+# Sites
+- OSDev Wiki (wiki.osdev.org)
+- uefi.org
+
+# Books
+- Tannebaum
+- Operating Systems: Three Easy Pieces
+
+# Repos
+- managarm
+- LemonOS
+- Limine Boot Loader
+
+# Specifications
+- ARM Architecture Reference Manual