NKLegacy is organised as a single repository whose two top-level concerns — the NKBootman bootloader and the ntoskrnl kernel — live in cleanly separated directories. A singleDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/pastaboy12345/NKLegacy/llms.txt
Use this file to discover all available pages before exploring further.
Makefile at the root ties everything together, driving the NASM assembler, the GCC C compiler in freestanding mode, and the GNU linker to produce either a GRUB-bootable ELF image or a raw floppy disk image. All build output lands under build/ and is never committed to the repository.
Annotated directory tree
Module-by-module walkthrough
boot/ — NKBootman two-stage bootloader
boot/stage1/mbr.asm — Stage 1 MBR
boot/stage1/mbr.asm — Stage 1 MBR
0x55AA boot signature at bytes 510–511). Its sole job is to be loaded by the BIOS at physical address 0x7C00, locate Stage 2 on the floppy, and transfer control to it. The NASM source is assembled with -f bin to produce a flat binary (build/boot/mbr.bin) that is written directly to sector 0 of the disk image by the Makefile.boot/stage2/stage2.asm — Stage 2 protected-mode setup
boot/stage2/stage2.asm — Stage 2 protected-mode setup
0x100000 and jumps to it. Like Stage 1, it is assembled as a flat binary (build/boot/stage2.bin).include/nk/ — Shared kernel headers
These headers are included by both the bootloader and the kernel via -I$(ROOT)/include in CFLAGS.
include/nk/types.h — Fundamental type definitions
include/nk/types.h — Fundamental type definitions
<stdint.h>, <stddef.h>, and <stdbool.h> from GCC’s own freestanding include directory (located at build time via gcc -m32 -print-file-name=include). Defines two architecture-specific address types and overrides NULL:include/nk/string.h — Freestanding string function declarations
include/nk/string.h — Freestanding string function declarations
ntoskrnl/lib/string.c. Because the kernel is compiled with -nostdinc, the standard <string.h> is not available; this header provides equivalent declarations:ntoskrnl/arch/i386/ — Architecture layer
This directory contains everything that is specific to the x86 (i386) CPU and must be written in assembly or be tightly coupled to hardware registers.
boot.asm — Multiboot entry point
boot.asm — Multiboot entry point
_start symbol (referenced in linker.ld) which sets up an initial stack and calls kmain(magic, mboot_info). Assembled by NASM with -f elf32.gdt.c / gdt.h — Global Descriptor Table
gdt.c / gdt.h — Global Descriptor Table
gdt_init() populates a static array of segment descriptors (null, kernel code, kernel data) and calls the inline lgdt wrapper to load the GDTR. After gdt_init() returns, all subsequent memory accesses use the flat 32-bit segments established here.idt.c / idt.h — Interrupt Descriptor Table
idt.c / idt.h — Interrupt Descriptor Table
idt_init() fills all 256 IDT entries with interrupt gate descriptors pointing at the ISR stubs defined in isr.asm, then calls lidt to load the IDTR. Entries 0–31 cover CPU exceptions; entries 32–47 are remapped hardware IRQs.isr.asm — ISR/IRQ assembly stubs
isr.asm — ISR/IRQ assembly stubs
-f elf32 and linked into the kernel ELF.io.h — Port I/O inline helpers
io.h — Port I/O inline helpers
static inline wrappers around x86 port I/O instructions:ntoskrnl/driver/ — Hardware drivers
Each driver lives in its own subdirectory and exposes a minimal public API.
| Directory | Hardware | Key details |
|---|---|---|
driver/vga/ | VGA text mode | 80×25 framebuffer at 0xB8000, 16-colour attributes, hardware cursor via CRT index registers |
driver/serial/ | COM1 UART | Initialised to 115200 baud; serial_init(COM1) is called first in kmain to capture all early debug output |
driver/pic/ | 8259A PIC | Remaps master PIC to IRQ vectors 32–39 and slave to 40–47, clearing the default BIOS mapping that conflicts with CPU exceptions |
driver/pit/ | 8253/8254 PIT | Configured in mode 3 (square wave) to produce 1000 Hz interrupts; pit_get_ticks() returns a running tick counter |
driver/keyboard/ | PS/2 keyboard | Reads scancode set 1 from port 0x60 on IRQ 1; decodes scancodes to ASCII with Shift modifier support |
ntoskrnl/kernel/ — Kernel core
kmain.c — Boot sequence and entry point
kmain.c — Boot sequence and entry point
kmain(uint32_t magic, void *mboot_info) is the C entry point called from boot.asm. It runs the kernel through five distinct phases:- Phase 1 — Early hardware init:
serial_init(COM1)thenvga_clear(). - Phase 2 — CPU tables:
gdt_init()thenidt_init(). - Phase 3 — Interrupt hardware:
pic_init(),pit_init(),keyboard_init(), thensti. - Phase 4 — Boot banner: Prints the NT-style
[OK]status lines to the VGA console using colour attributes (light cyan for the banner, light green for[OK], white for descriptions). - Phase 5 — Shell loop:
nkfs_init()followed bycmd_run(), which does not return.
kprintf.c / kprintf.h — Formatted kernel output
kprintf.c / kprintf.h — Formatted kernel output
kprintf(const char *fmt, ...) is a printf-style formatter that writes simultaneously to the VGA framebuffer and COM1. It is the primary output primitive used throughout the kernel and drivers.bsod.c / bsod.h — Blue Screen of Death
bsod.c / bsod.h — Blue Screen of Death
panic.c / panic.h — Kernel panic handler
panic.c / panic.h — Kernel panic handler
panic() is called from exception handlers and assertion failures. It prints the panic message via kprintf, optionally invokes the BSOD display, disables interrupts, and halts.ntoskrnl/lib/ — Freestanding runtime library
lib/string.c provides all ten functions declared in include/nk/string.h. The implementations are straightforward byte-by-byte loops — intentionally simple so the code is easy to audit:
ntoskrnl/exe/ — Executable support and shell
pe.c / pe.h — PE parser and loader
pe.c / pe.h — PE parser and loader
run shell command to execute a PE binary built by NKBuild.nkbuild.c / nkbuild.h — PE builder
nkbuild.c / nkbuild.h — PE builder
build shell command. Takes source input from the user and produces a valid PE binary stored in the NKFS filesystem, which can then be loaded and executed with run.cmd.c / cmd.h — NT-style interactive shell
cmd.c / cmd.h — NT-style interactive shell
cmd_run() implements the main shell loop. It reads characters from the PS/2 keyboard driver, echoes them to the VGA console, and dispatches completed lines to cmd_execute(). The shell maintains a current working directory pointer into the NKFS tree and a cwd_path string (e.g. C:\docs) to display in the prompt.Supported commands: help, cls, ver, dir, cd, mkdir (md), type, echo, build, run.ntoskrnl/fs/nkfs/ — NKFS RAM filesystem
NKFS is a purely in-memory hierarchical filesystem. Each node is a nkfs_node_t struct:
nkfs.h:
nkfs_init() is called from kmain just before cmd_run() and sets up the root node of the filesystem tree.
ntoskrnl/linker.ld — Kernel linker script
The linker script places the kernel at physical address 0x100000 (1 MB), where both the NKBootman Stage 2 and the Multiboot protocol expect to find it. It defines _kernel_start, aligns the .multiboot section to a 4-byte boundary (within the first 8 KB so GRUB can find the magic), and aligns .text to a 4 KB page boundary.
Makefile — Master build system
The Makefile defines four phony top-level targets and handles all dependency tracking:
| Target | Description |
|---|---|
make all | Builds kernel ELF + NKBootman binaries + floppy image (runs kernel, bootloader, image) |
make kernel | Compiles all C and ASM sources and links build/nklegacy.elf |
make bootloader | Assembles build/boot/mbr.bin (Stage 1) and build/boot/stage2.bin (Stage 2) |
make image | Creates the 1.44 MB floppy image build/nklegacy.img |
make iso | Builds the GRUB rescue ISO (build/nklegacy.iso) |
make run | Builds ISO then launches qemu-system-i386 with -serial stdio |
make run-bootman | Builds floppy image then boots it in QEMU via -fda |
make run-serial | Builds ISO then launches QEMU headless (-display none -no-reboot) |
make clean | Removes the entire build/ directory |
CFLAGS includes -ffreestanding -fno-builtin -fno-stack-protector -nostdlib -nostdinc along with strict warning flags -Wall -Wextra -Werror. GCC’s own built-in headers (stdint.h, stdarg.h, stddef.h, stdbool.h) are still available via -isystem $(GCC_INCDIR) where GCC_INCDIR is resolved at build time with gcc -m32 -print-file-name=include. No host libc is linked.