diff options
| author | Arseney300 <Arseney300@gmail.com> | 2026-03-29 02:07:17 +0700 |
|---|---|---|
| committer | Arseney300 <Arseney300@gmail.com> | 2026-04-08 01:19:07 +0700 |
| commit | 4912796d2e88c6eb5d02fbf0fb9c39f8c9f7cd4c (patch) | |
| tree | 9ee8110e2c090c888f23797cda56c7e2df531695 /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.md | 28 | ||||
| -rw-r--r-- | doc/develop/overall.md | 123 | ||||
| -rw-r--r-- | doc/develop/study_resources.md | 15 |
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 |
