feat(boot): Add SUB-OS boot logo and splash, share the console font, and lift the kernel size ceiling

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
This commit is contained in:
subhobhai943andClaude Opus 5 committed 2026-08-25 01:37:20 +05:30
1 parent 280d7fa2bb
commit ba06264d12
15 files changed
+1711 -153

No files matched your search

+49
View File
@@ -0,0 +1,49 @@
#ifndef _INIT_BOOTLOGO_H
#define _INIT_BOOTLOGO_H
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
// SUB-OS boot logo.
//
// The logo appears in two forms because the framebuffer does not exist for the
// first third of boot. Until the video driver is up, an ASCII rendition goes to
// the text console and the serial line; once fb_init() and bochs_vbe_init()
// have run, the real bitmap takes over as a graphical splash with a progress
// bar, and the remaining boot log continues on serial only.
//
// Both forms are generated from the same artwork by scripts/mklogo.py.
// --- Generated asset (init/logo_data.c) ------------------------------------
extern const int boot_logo_width;
extern const int boot_logo_height;
extern const uint32_t boot_logo_palette[16];
// Bit N set means palette entry N is background and should not be drawn.
extern const uint16_t boot_logo_transparent_mask;
extern const uint8_t boot_logo_bitmap[];
extern const char* const boot_logo_ascii[];
// --- Text console ----------------------------------------------------------
// Draw the ASCII logo and version banner. Safe to call before any driver
// beyond printk is initialised.
void boot_logo_print_text(void);
// --- Graphical splash ------------------------------------------------------
// Take over the framebuffer. Returns false when no framebuffer is available,
// in which case the caller should keep logging to the text console.
bool boot_logo_splash_begin(void);
// Update the splash. `percent` is clamped to 0..100; `status` may be NULL.
void boot_logo_splash_progress(int percent, const char* status);
// Release the splash so the desktop (or the TTY) can own the screen again.
void boot_logo_splash_end(void);
bool boot_logo_splash_active(void);
// Draw the logo at an arbitrary position and integer scale, for callers that
// want the mark without the splash chrome (the desktop About box, say).
void boot_logo_draw(int x, int y, int scale);
#endif // _INIT_BOOTLOGO_H
+17
View File
@@ -4,6 +4,7 @@
#include <stddef.h>
#include <stdint.h>
#include <stdarg.h>
#include <stdbool.h>
#include <lib/printf.h>
// Linux-compatible log level prefixes
@@ -50,4 +51,20 @@ int kprintf(const char* fmt, ...); // Alias for compatibility
void dmesg_dump(void);
const char* dmesg_get_buffer(size_t* size_out);
// ---------------------------------------------------------------------------
// Console redirection
//
// While a sink is installed, printk output is handed to the callback instead
// of the text console, so a caller can run a subsystem that reports via printk
// and capture what it printed. The serial console and the dmesg ring still
// receive everything, which keeps a captured run debuggable.
//
// The sink must not itself call printk; re-entrant output is dropped.
// ---------------------------------------------------------------------------
typedef void (*printk_sink_fn_t)(const char* text, size_t len, void* ctx);
void printk_set_sink(printk_sink_fn_t fn, void* ctx);
void printk_clear_sink(void);
bool printk_has_sink(void);
#endif // _KERNEL_PRINTK_H
+23
View File
@@ -0,0 +1,23 @@
#ifndef _LIB_FONT8X8_H
#define _LIB_FONT8X8_H
#include <stdint.h>
// Shared 8x8 bitmap console font.
//
// The framebuffer console, the 2D canvas rasterizer and the desktop compositor
// all render text from this one table. Each glyph is 8 bytes, one per scanline,
// with the most significant bit at the left of the cell.
#define FONT8X8_WIDTH 8
#define FONT8X8_HEIGHT 8
#define FONT8X8_FIRST 32
#define FONT8X8_LAST 127
#define FONT8X8_GLYPHS (FONT8X8_LAST - FONT8X8_FIRST + 1)
extern const uint8_t font8x8_basic[FONT8X8_GLYPHS][FONT8X8_HEIGHT];
// Scanlines for `c`, substituting '?' for anything unprintable.
const uint8_t* font8x8_glyph(char c);
#endif // _LIB_FONT8X8_H
+20
View File
@@ -1,9 +1,29 @@
#ifndef _USERLAND_SHELL_H
#define _USERLAND_SHELL_H
#include <stdbool.h>
#define MAX_COMMAND_LENGTH 256
void shell_init(void);
void shell_run(void);
// Shared builtin dispatcher.
//
// Some commands (neofetch, calc, matrix, history, tty, ...) are shell builtins
// rather than LazyBox applets. Both the kernel TTY shell and the desktop
// terminal route through this so the two consoles accept the same vocabulary.
//
// `raw_cmd` is the untokenized line, which the argument-slurping builtins such
// as calc and hexdump need. Returns true if the command was recognised.
//
// `allow_blocking` is false for callers that must not be suspended -- the
// desktop compositor drives input from its own frame loop, so builtins that
// animate or wait for a key are refused there.
bool shell_execute_builtin(const char* raw_cmd, int argc, char** argv, bool allow_blocking);
// True when the name is a builtin, regardless of whether it can run here.
bool shell_is_builtin(const char* name);
bool shell_builtin_blocks(const char* name);
#endif // _USERLAND_SHELL_H