Files
SUB-OS/kernel/main.c
T
subhobhai943andClaude Opus 5 2d01fd629e feat(video): Add a framebuffer console so the TTY and nano work after graphics mode
Pressing Esc left the desktop and started the shell, but nothing appeared in the
emulator window -- the session was only visible on the host terminal. Once the
VBE adapter is switched into graphics mode the VGA text buffer at 0xB8000 stops
being scanned out, so every printk after that point reached serial and the
dmesg ring but never the display.

Disabling the DISPI interface does not bring the text console back; QEMU keeps
presenting the last framebuffer surface. So rather than clawing the adapter back
to text mode, the console is now rendered into the framebuffer:

  drivers/video/fbcon.c draws the console with the shared 8x8 font and carries a
  VT100 subset -- SGR colours, cursor addressing, relative moves, erase-display,
  erase-line and save/restore. It presents a fixed 80x25 grid, because that is
  the geometry the userland assumes (nano pads its bars with %-80s, the shell
  wraps at TTY_WIDTH), with the glyph cell scaled to fill the active resolution.

The TTY driver became the console dispatcher: tty_write, tty_clear and
tty_set_cursor route to fbcon while it owns the display. That last one is what
makes nano work -- it positions with tty_set_cursor() rather than escapes, so
its full-screen repaint was landing as an append-only stream.

Also in this change:

  - `video=WIDTHxHEIGHT` on the kernel command line selects the display mode,
    defaulting to 1280x720 so a 16:9 host panel is filled rather than pillarboxed
    when QEMU goes fullscreen. Rejects modes the heap cannot back.
  - `make run-fullscreen`, plus zoom-to-fit on the windowed target, so scaling
    preserves the guest aspect ratio instead of stretching it.
  - QEMU targets raise vgamem_mb, since a 1280x720 32-bit surface exceeds the
    default VGA memory.
  - bochs_vbe_disable()/fb_set_active() let the framebuffer be marked dormant so
    drawing routines no-op after a mode teardown.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01L5yKJT4Wo2cV3rfPrwY5MP
2026-08-25 02:06:07 +05:30

360 lines
11 KiB
C

#include <kernel/kernel.h>
#include <kernel/printk.h>
#include <kernel/sched.h>
#include <kernel/task.h>
#include <kernel/signal.h>
#include <kernel/syscall.h>
#include <kernel/timer.h>
#include <kernel/workqueue.h>
#include <kernel/module.h>
#include <kernel/trace.h>
#include <kernel/namespace.h>
#include <kernel/syslog.h>
#include <kernel/cron.h>
#include <kernel/metrics.h>
#include <kernel/bpf.h>
#include <kernel/kobject.h>
#include <kernel/wait.h>
#include <kernel/futex.h>
#include <kernel/rcu.h>
#include <kernel/ktest.h>
#include <mm/page_cache.h>
#include <mm/vma.h>
#include <drivers/canvas.h>
#include <drivers/pty.h>
#include <arch/arch.h>
#include <mm/pmm.h>
#include <mm/kmalloc.h>
#include <mm/slab.h>
#include <drivers/tty.h>
#include <drivers/serial.h>
#include <drivers/keyboard.h>
#include <drivers/mouse.h>
#include <drivers/ata.h>
#include <drivers/ahci.h>
#include <drivers/nvme.h>
#include <drivers/bochs.h>
#include <drivers/virtio_blk.h>
#include <drivers/virtio_net.h>
#include <drivers/virtio_rng.h>
#include <drivers/hwmon.h>
#include <drivers/pci.h>
#include <drivers/e1000.h>
#include <drivers/rtl8139.h>
#include <drivers/speaker.h>
#include <drivers/fb.h>
#include <drivers/rtc.h>
#include <drivers/acpi.h>
#include <drivers/usb.h>
#include <drivers/xhci.h>
#include <drivers/ramdisk.h>
#include <block/block.h>
#include <ipc/ipc.h>
#include <sound/sound.h>
#include <sound/hda.h>
#include <sound/melody.h>
#include <fs/vfs.h>
#include <fs/fat32.h>
#include <fs/ext2.h>
#include <fs/sysfs.h>
#include <net/net.h>
#include <net/socket.h>
#include <net/udp.h>
#include <net/tcp.h>
#include <net/dhcp.h>
#include <net/dns.h>
#include <net/dns_cache.h>
#include <ipc/shm_posix.h>
#include <sound/beep.h>
#include <kernel/tsc.h>
#include <drivers/e1000e.h>
#include <drivers/virtio_gpu.h>
#include <drivers/cpufreq.h>
#include <drivers/virtio_input.h>
#include <gui/gui.h>
#include <init/init.h>
#include <kernel/rust.h>
#include <kernel/sub_lang.h>
#include <kernel/cpp_kernel.h>
#include <net/filter.h>
#include <net/http.h>
#include <net/ssh.h>
#include <crypto/crypto.h>
#include <certs/certs.h>
#include <security/security.h>
#include <security/auth.h>
#include <io_uring/io_uring.h>
#include <usr/initramfs.h>
#include <virt/virt.h>
#include <init/init.h>
#include <init/service.h>
#include <init/version.h>
#include <init/bootlogo.h>
#include <userland/lazybox.h>
#include <userland/sh.h>
#include <userland/shell.h>
static void subos_modular_core_boot(void) {
#if defined(__x86_64__)
pci_init();
#endif
// Storage & Block Layer
printk(KERN_INFO "[4/14] Initializing Block Layer & Storage Controllers... ");
block_init();
page_cache_init();
ramdisk_init();
#if defined(__x86_64__)
ata_init();
ahci_init();
nvme_init();
#endif
virtio_blk_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// Bus & Devices
printk(KERN_INFO "[5/14] Enumerating System Devices, Canvas & PTY... ");
#if defined(__x86_64__)
virt_init();
fb_init();
bochs_vbe_init();
virtio_gpu_init();
usb_init();
xhci_init();
hwmon_init();
cpufreq_init();
#endif
canvas_init();
pty_init();
virtio_rng_init();
virtio_input_init();
tsc_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// The framebuffer exists from here on, so raise the graphical splash
// unless the boot was asked for a text console. Remaining boot messages
// keep flowing to the serial line and the dmesg ring.
bool want_splash = !(init_has_param("nogui") || init_has_param("text") ||
init_has_param("emergency") || init_has_param("single") ||
init_has_param("nosplash"));
if (want_splash) {
boot_logo_splash_begin();
}
// Network Subsystem, NetFilter, HTTPD & SSH Server
printk(KERN_INFO "[6/14] Initializing Network Stack, NetFilter, HTTPD & SSHD... ");
boot_logo_splash_progress(40, "Bringing up the network stack");
filter_init();
httpd_init();
sshd_init();
#if defined(__x86_64__)
rtl8139_init();
virtio_net_init();
e1000e_init();
if (e1000_init() || e1000e_is_online()) {
net_init();
socket_subsystem_init();
udp_init();
tcp_init();
dhcp_init();
dns_init();
dns_cache_init();
printk(ANSI_BRIGHT_GREEN "Online\n" ANSI_RESET);
} else {
printk(ANSI_YELLOW "No NIC detected\n" ANSI_RESET);
}
#else
virtio_net_init();
dns_cache_init();
printk(ANSI_BRIGHT_GREEN "Online\n" ANSI_RESET);
#endif
// Sound & Voice Synthesizer
#if defined(__x86_64__)
printk(KERN_INFO "[7/14] Initializing Sound Architecture, Melody Player & Formant TTS... ");
sound_init();
hda_init();
melody_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
#endif
// Crypto, Certificates, LSM Security, Authentication, Namespaces, Rust, SUB-Lang & C++ Subsystems
printk(KERN_INFO "[8/14] Initializing Rust, C++ Core, SUB-Lang Engine, Keyring & Auth... ");
boot_logo_splash_progress(55, "Starting Rust, C++ and SUB-Lang engines");
rust_kernel_init();
cpp_kernel_init();
sub_kernel_init();
prng_seed(0, 0);
certs_init();
security_init();
auth_init();
namespace_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// Concurrency Primitives: Wait Queues, Futexes & Tiny RCU
printk(KERN_INFO "[9/14] Initializing Wait Queues, Futex Hash & Tiny RCU... ");
boot_logo_splash_progress(65, "Initializing concurrency primitives");
wait_subsystem_init();
futex_init();
rcu_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// Inter-Process Communication
printk(KERN_INFO "[9/14] Initializing IPC Engine (Pipes, MsgQueues, POSIX SHM, Semaphores)... ");
ipc_init();
posix_shm_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// Asynchronous I/O Engine
printk(KERN_INFO "[10/14] Initializing io_uring Async Ring Engine... ");
io_uring_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// Virtual File System & Multi-Filesystem Support
printk(KERN_INFO "[11/14] Mounting Virtual File System (VFS, devfs, procfs, sysfs)... ");
boot_logo_splash_progress(78, "Mounting the virtual file system");
vfs_init();
sysfs_init();
kobject_subsystem_init();
fat32_init();
ext2_init();
initramfs_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// Kernel Core: Signals, Modules, Syscalls, Tracing, Syslog, Metrics, Crond & Systemd
printk(KERN_INFO "[12/14] Initializing Syslog, Metrics, Cron, Tracing, BPF & Services... ");
boot_logo_splash_progress(88, "Starting kernel services");
signal_init();
workqueue_init();
syscall_init();
module_init_subsystem();
trace_init();
bpf_init();
syslog_init();
metrics_init();
cron_init();
service_manager_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// Preemptive Multi-Tasking & Userland
printk(KERN_INFO "[13/14] Initializing Preemptive Task Scheduler & LazyBox... ");
boot_logo_splash_progress(95, "Starting the scheduler and userland");
sched_init();
lazybox_init();
ktest_init();
ktest_register_builtin_suites();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
// Hardware Interrupts
printk(KERN_INFO "[14/14] Enabling Hardware Interrupts... ");
arch_enable_interrupts();
printk(ANSI_BRIGHT_GREEN "ACTIVE\n" ANSI_RESET);
// Boot directly into GUI Desktop unless emergency text mode is requested
bool emergency_text = init_has_param("nogui") || init_has_param("text") ||
init_has_param("emergency") || init_has_param("single");
if (!emergency_text) {
printk(KERN_INFO "INIT: Booting directly into SUB-OS Graphical Desktop Environment...\n");
boot_logo_splash_end();
gui_start_desktop();
printk(KERN_INFO "INIT: GUI session closed. Entering Emergency Kernel TTY Mode.\n");
} else {
boot_logo_splash_end();
printk(KERN_INFO "INIT: Emergency text/kernel TTY mode requested via boot parameters.\n");
}
// Launch Shell (Emergency TTY Mode)
shell_run();
while (1) {
arch_halt();
}
}
#if defined(__x86_64__)
void kernel_main(void* memory_map, uint64_t memory_map_count) {
tty_init();
serial_init();
printk_init();
boot_logo_print_text();
printk(ANSI_BRIGHT_CYAN "=================================================================\n" ANSI_RESET);
printk(ANSI_BRIGHT_CYAN " SUB-OS 64-Bit [%s] Modular Monolithic Kernel %s\n" ANSI_RESET, arch_get_name(), kernel_get_version());
printk(ANSI_BRIGHT_CYAN "=================================================================\n\n" ANSI_RESET);
init_early("root=/dev/sda console=tty1 init=/bin/lazybox video=1280x720 quiet");
rtc_init();
printk(KERN_INFO "[1/14] Initializing 64-Bit GDT, IDT, PIC & PIT Timer... ");
arch_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
printk(KERN_INFO "[2/14] Initializing PS/2 Keyboard, Mouse & ACPI... ");
keyboard_init();
mouse_init();
acpi_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
printk(KERN_INFO "[3/14] Initializing Physical PMM, Dynamic Heap & SLAB Cache... ");
pmm_init(memory_map, memory_map_count);
heap_init();
slab_init();
vma_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
subos_modular_core_boot();
}
#elif defined(__aarch64__)
void kernel_main_aarch64(void) {
arch_early_init();
printk_init();
boot_logo_print_text();
printk(ANSI_BRIGHT_CYAN "=================================================================\n" ANSI_RESET);
printk(ANSI_BRIGHT_CYAN " SUB-OS 64-Bit [%s] Modular Monolithic Kernel %s\n" ANSI_RESET, arch_get_name(), kernel_get_version());
printk(ANSI_BRIGHT_CYAN "=================================================================\n\n" ANSI_RESET);
init_early("root=/dev/vda console=ttyAMA0 init=/bin/lazybox quiet");
printk(KERN_INFO "[1/14] Initializing AArch64 CPU, GICv2, Generic Timer & MMU... ");
arch_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
printk(KERN_INFO "[2/14] Initializing Physical PMM, Dynamic Heap & SLAB Cache... ");
pmm_init(NULL, 0);
heap_init();
slab_init();
vma_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
subos_modular_core_boot();
}
#elif defined(__arm__) || defined(__armv8i__)
void kernel_main_armv8i(void) {
arch_early_init();
printk_init();
printk(ANSI_BRIGHT_CYAN "=================================================================\n" ANSI_RESET);
printk(ANSI_BRIGHT_CYAN " SUB-OS 32-Bit [%s] Modular Monolithic Kernel %s\n" ANSI_RESET, arch_get_name(), kernel_get_version());
printk(ANSI_BRIGHT_CYAN "=================================================================\n\n" ANSI_RESET);
init_early("root=/dev/vda console=ttyAMA0 init=/bin/lazybox quiet");
printk(KERN_INFO "[1/14] Initializing ARMv8i CPU, GICv2, Generic Timer & MMU... ");
arch_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
printk(KERN_INFO "[2/14] Initializing Physical PMM, Dynamic Heap & SLAB Cache... ");
pmm_init(NULL, 0);
heap_init();
slab_init();
vma_init();
printk(ANSI_BRIGHT_GREEN "OK\n" ANSI_RESET);
subos_modular_core_boot();
}
#endif