Kernel / memory:
- mm/kmalloc.c: fix "Heap: Out of memory" under the GUI. The desktop allocates
three full-screen 32-bit buffers (~11MB) which overflowed the fixed 16MB pool.
The heap now starts at 32MB and grows on demand from the PMM (16MB regions),
with region-safe coalescing (only merges physically adjacent blocks) so growth
never corrupts across separate PMM allocations. Adds heap_get_grow_count().
Build / run:
- Makefile: merge `run-gui` into `run` so `make run` boots into the graphical
desktop; add `run-headless` (serial-only via QEMU_CMD), bump guest RAM to
256M, update .PHONY and help.
Configure:
- scripts/kconfig/menuconfig.py: gate the curses UI behind isatty() on stdin and
stdout so non-interactive `make configure` stops emitting "nocbreak() returned
ERR" and falls cleanly through to the non-interactive writer.
GUI / userland:
- gui/gui_apps.c: rebuild the System Monitor from hardcoded values into live
telemetry -- real heap used/total/free with a colour-shifting bar, a scrolling
heap-utilisation graph, the grow counter, and real PMM RAM figures.
- lazybox `free`: report how many times the heap has grown.
Auth:
- Default login is now SUB / SUB (Kali-style username==password), seeded first
as the primary uid-0 account and set as the logged-in user; root kept for
compatibility. Hardcoded "root" defaults (whoami, su, passwd, ssh, sshd
session) updated to SUB.
Verified: clean build on x86_64/aarch64/armv8i; GUI boots with 0 OOM/0 panic;
auth engine initialises cleanly; `make configure` fallback is clean.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Fh5z6V7nGPbHvqVG5p4CXX
SUB-OS had a syscall table and user GDT descriptors but nothing that could
actually leave ring 0: lazybox and the shell run as kernel code, and
syscall_handler() was never reachable from a user program. This adds the
missing path end to end on x86_64.
Address spaces (arch/x86_64/mm/vmspace.c)
- The boot page tables identity-map the low 4 GB off PML4[0] and leave the
rest empty, so userland is given its own PML4 slot (512 GiB) rather than
holes punched in the kernel's 2 MB huge-page map. A process PML4 shares
entry 0 with the kernel and privately owns entry 1.
- Frames outside the identity map are refused rather than written through an
unmapped pointer; lifting that needs a recursive map or a higher-half
direct map, which is noted in the file.
ELF loader (kernel/elf.c)
- Validates ELF64/little-endian/ET_EXEC/machine, bounds-checks every program
header against both the image and the user address range, and lays PT_LOAD
segments into an address space. Frames arrive zeroed, so .bss is covered.
Ring transition (arch/x86_64/cpu/usermode.asm)
- user_enter() drops to ring 3 via iretq after scrubbing every GPR, and
user_return() unwinds back to it when the process exits, so exec looks like
a call that blocks until the program finishes.
Syscalls
- INT 0x80 installed at DPL 3 with the Linux x86_64 register convention.
The process gets its own kernel stack for the trap, because TSS.rsp0 must
not point at the stack user_enter() is standing on.
- Every user pointer is range-checked before use. The process page tables are
still live during a syscall, so without that check a program could pass a
kernel address and have write(2) dump kernel text to the console. The new
/sbin/init asserts both a wild pointer and a kernel pointer are rejected.
- write(2) to stdout/stderr routes through the new console_write(), which
reuses printk's routing so output reaches serial and the framebuffer
console rather than only the VGA text buffer.
Faults
- A ring 3 exception now kills that process and reports CR2 instead of
panicking the machine.
Userland (userland/init/)
- /sbin/init is a real freestanding static executable, linked at the user
base and embedded in the kernel image by scripts/mkblob.py. It reports its
pid, verifies .bss was zeroed and .data is writable, checks the two pointer
rejections, and exits.
aarch64 and armv8i keep building: the loader and exec path are portable, and
those ports get honest vmspace stubs that fail cleanly rather than pretending
to run a program with kernel privileges.
Verified under QEMU: init loads at 0x80004000a0, reports pid 1, .bss zeroed,
.data writable, both bad pointers rejected, and exits 0 back into the shell.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_0161Jh7uCEMLYEMNPsjC1LKf
The configurator had four defects that made buttons and selection behave
erratically in `make configure`.
lxdialog front-end:
- Pressing <Help> in a subsystem menu discarded every toggle made since the
menu was opened, because dialog reports only the focused tag and the result
was thrown away. Pass --help-status and fold the returned state back into
the config before showing help.
- <Help> always showed the generic subsystem blurb even though all 41 options
carry their own help text. Resolve the focused tag and show that item's help.
- The main menu prompt promised <Exit> but dialog rendered <Cancel>; label the
button to match.
curses fallback:
- The Help button raised AttributeError and killed the UI at top level: the
root node is the MENU_TREE list itself, and the fallback argument
`current_menu.get("help", ...)` is evaluated eagerly even when the item has
its own help.
- The '?' hotkey was nested inside the <Enter> branch where `key` can only be
a newline, so it was unreachable dead code.
- The button-bar spacing went negative on a narrow dialog and pushed the last
buttons through the right border; centre and clamp the row instead.
Front-end selection no longer swallows exceptions silently, so a crash reports
itself instead of looking like an unresponsive UI.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_0161Jh7uCEMLYEMNPsjC1LKf
Boot logo (init/bootlogo.c, init/logo_data.c, scripts/mklogo.py):
The logo appears in two forms because the framebuffer does not exist for the
first third of boot. An ASCII rendition goes to the text console and serial
line from the first moments; once the video driver is up at step [5/14] the
real bitmap takes over as a graphical splash with a progress bar tied to the
actual boot stages.
The asset is 4-bit palette indexed, so 160x160 pixels cost 12.5 KB instead of
100 KB, and carries a transparency mask so the mark composites onto the
gradient rather than stamping a flat rectangle over it. scripts/mklogo.py
regenerates init/logo_data.c from the source PNG.
Boot reaches the desktop in well under a second, so the splash is held for a
minimum duration and the bar sweeps to 100% during the hold; without that the
logo would flash past unseen. `splashtime=<ms>` tunes it and `nosplash`,
`nogui` or `text` skip it.
Bootloader (boot/stage2.asm):
stage2 staged the whole kernel in conventional RAM before copying it to 1 MB,
which capped the kernel at roughly 576 KB before the load ran into video
memory at 0xA0000. The logo pushed it over that line and the kernel stopped
booting. Each 32 KB chunk now goes into one fixed low buffer and is copied
straight to its final address, using unreal mode for the 32-bit reach. The
ceiling is now the image itself, 1.375 MB.
Console font (lib/font8x8.c):
fb_draw_char was a stub that ignored its character argument and drew a filled
rectangle, which is why the splash rendered its text as solid blocks. It now
renders real glyphs, and the table it uses is shared: the framebuffer console,
the canvas rasterizer and the desktop compositor had three divergent private
copies, two of which still carried the `// \` line-continuation defect.
printk console sink (kernel/printk.c):
printk output can be redirected to a callback, so a caller can run a subsystem
that reports via printk and capture what it printed. Serial and the dmesg ring
still see everything, which keeps a captured run debuggable.
Shell builtins (userland/lazybox/shell.c):
The builtin chain is extracted into shell_execute_builtin(), so the kernel TTY
and the desktop terminal accept the same vocabulary instead of the GUI seeing
only the applet table. Callers that cannot be suspended pass allow_blocking =
false to refuse the animating ones.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01L5yKJT4Wo2cV3rfPrwY5MP
- Support 'armv81' and 'armv81_defconfig' aliases in Makefile and Kconfig menuconfig.py
- Fix uint64_t to pointer cast on 32-bit ARM in LazyBox shell.c
- Add Linux kernel lxdialog GUI integration using dialog tool
- Support royal blue backdrop, floating gray dialog windows, 3D drop shadows
- Add bottom button bar: < Select >, < Exit >, < Help >, < Save >, < Defaults >
- Add full context-sensitive Help dialogs for every kernel subsystem and driver
- Provide pixel-perfect Python Curses GUI replica with Tab/Arrow/Hotkeys navigation
- Auto-generate .config and include/config/autoconf.h
- Guard curses curs_set(0) and use_default_colors() against terminal ERR
- Guard color pairs with curses.has_colors() checks
- Implement run_ansi_fallback() for non-curses/headless/dumb terminals
- Ensure 'make configure' runs seamlessly in all terminal environments