summaryrefslogtreecommitdiff
path: root/doc/develop/overall.md
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/overall.md
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/overall.md')
-rw-r--r--doc/develop/overall.md123
1 files changed, 123 insertions, 0 deletions
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
+
+