feature: boot.mgr replace hardcoded init sequence with dependency-driven boot manager

Introduce boot.mgr - a self-registering, dependency-ordered boot
initialization framework with barrier-based phasing and glob pattern
matching. Units now declare their own init procedures and dependencies
via registerBoot()/registerBarrier() in their initialization sections,
boot.mgr.run() topologically sorts and executes them.

- Add src/boot/boot.mgr.pas with topoSort, glob matching, barrier
  two-pass algorithm, and boot tree printer
- Gut src/asuro.pas (kmain): now just stores multiboot info, calls
  System.init(), boot.mgr.run, and yield()
- Add initialization sections with registerBoot() to 53 existing units
- Add new units: core.pas, test.pas, driver.storage.boot.pas,
  app.wasm.pas, app.bsod.pas (factored out of asuro.pas)
- Define 9 barrier phases: immediate -> early -> middle -> storage ->
  bus -> device -> bus.late -> late -> final
- Fix xHCI ISR: exclude PRC/WRC from PORTSC change bit clearing to
  prevent race with port reset busy-wait
- Fix driver.bus.usb.core fire_completion_hooks: guard against uint32
  underflow when CompletionHookCount = 0
- Move auto_mount_volumes from device barrier to late barrier so it
  runs after PCI scan discovers storage controllers
- Add toolchain/compile_initcalls.sh for boot entry extraction
- Add Boot Registration sections to all 51 doc files; create 4 new
  doc files; rewrite boot.mgr.md; update mkdocs.yml nav
This commit is contained in:
t3hn3rd committed 2026-03-13 15:37:43 +00:00
1 parent dd56ffbcb4
commit 2d190c221a
116 files changed
+1922 -465

No files matched your search

+33
View File
@@ -0,0 +1,33 @@
unit app.bsod;
interface
uses
io.stdio,
debug.tracer,
core.panic;
procedure init;
implementation
procedure terminal_command_bsod(params : PParamList; stdin_buf, stdout_buf, stderr_buf : POutBuf);
begin
push_trace('kernel.terminal_command_bsod');
if paramCount(params) > 1 then begin
core.panic.panic(getparam(0, params), getparam(1, params), nil);
end else begin
io.stdio.bufWriteStrLn(stderr_buf, 'Invalid number of params.');
io.stdio.bufWriteStrLn(stderr_buf, 'Usage: bsod <error> <info>');
end;
pop_trace;
end;
procedure init;
begin
io.stdio.registerCommand('BSOD', @terminal_command_bsod, 'Force a Panic Screen.');
end;
end.
+10 -1
View File
@@ -23,6 +23,7 @@ unit app.mgr;
interface
uses
boot.mgr,
debug.tracer, io.stdio, proc.mgr,
//progs
app.base64, app.md5sum, app.dhclient, app.vbeinfo, app.testcmd, app.ping, app.meminfo, app.setres,
@@ -34,7 +35,10 @@ uses
driver.storage.filedispatch,
//wasm
app.wasm.runner,
app.divzero;
app.divzero,
app.bsod,
app.vterminal,
app.filebrowser;
{ Initialize all baked-in programs }
procedure init();
@@ -86,7 +90,12 @@ begin
app.wasm.runner.init();
app.setres.init();
app.divzero.init();
app.bsod.init();
app.vterminal.init;
app.filebrowser.init();
end;
Initialization
boot.mgr.registerBoot('app.mgr', @init, 'Program Manager', BOOT_MGR_BARRIER_LATE);
end.
+25
View File
@@ -0,0 +1,25 @@
unit app.wasm;
interface
uses
boot.mgr;
implementation
uses
io.syslog,
wasm.vm.io,
wasm;
procedure init();
begin
{ Let's test Wasuro! }
wasm.vm.io.io_set_writechar(@io.syslog.logchar);
wasm.wasm_init;
end;
initialization
boot.mgr.registerBoot('app.wasm', @init, 'Initialize WASM VM Backend', BOOT_MGR_BARRIER_FINAL)
end.
+9
View File
@@ -22,6 +22,7 @@ unit arch.x86.cpu;
interface
uses
boot.mgr,
core.util, arch.x86.util, driver.timer.rtc, io.stdio;
type
@@ -117,6 +118,9 @@ procedure Terminal_Command_CPU(Params : PParamList; stdin_buf, stdout_buf, stder
implementation
uses
io.syslog;
procedure getCPUIdentifier;
var
id0, id1, id2 : uint32;
@@ -323,6 +327,7 @@ end;
procedure init();
begin
io.syslog.logln('CPU', 'Init begin');
CPUID.Capabilities0:= PCapabilities_Old(@CAP_OLD);
CPUID.Capabilities1:= PCapabilities_New(@CAP_NEW);
getCPUIdentifier;
@@ -330,6 +335,10 @@ begin
getCPUClockSpeed;
enableSSE;
enableAVX;
io.syslog.logln('CPU', 'Init end');
end;
initialization
boot.mgr.registerBoot('arch.x86.cpu', @init, 'x86 CPU Initialization', BOOT_MGR_BARRIER_EARLY);
end.
+26 -3
View File
@@ -22,7 +22,7 @@ unit arch.x86.gdt;
interface
uses
io.syslog;
io.syslog, core.panic;
type
TGDT_Entry = packed record
@@ -51,6 +51,9 @@ procedure reload;
implementation
uses
boot.mgr;
procedure flush_gdt(gdt_pointer : uint32); assembler; nostackframe;
asm
MOV EAX, gdt_pointer
@@ -105,9 +108,8 @@ begin
io.syslog.writestringln(' SET.');
end;
procedure init();
procedure initializeBaseGTD();
begin
io.syslog.logln('GDT','INIT START.');
gdt_pointer.limit:= 0;
gdt_pointer.base := uint32(@gdt_entries);
set_gate($00, $00, $00, $00, $00); //OFFSET: 0
@@ -116,7 +118,28 @@ begin
set_gate($03, $00, $FFFFFFFF, $FA, $CF); //OFFSET: 24
set_gate($04, $00, $FFFFFFFF, $F2, $CF); //OFFSET: 32
flush;
end;
procedure init();
var
dds : uint16;
begin
io.syslog.logln('GDT','INIT START.');
initializeBaseGTD();
asm
MOV dds, CS
end;
if dds = $08 then begin
io.syslog.logln('KERNEL', 'GDT: LOAD SUCCESS.');
end else begin
io.syslog.logln('KERNEL', 'GDT: LOAD FAIL.');
io.syslog.logln('KERNEL', 'HALTING.');
core.panic.panic('GDT', 'Failed to load the GDT correctly.', nil);
end;
io.syslog.logln('GDT','INIT END.');
end;
initialization
boot.mgr.registerBoot('arch.x86.gdt', @init, 'Global Descriptor Table', BOOT_MGR_BARRIER_EARLY);
end.
+4
View File
@@ -22,6 +22,7 @@ unit arch.x86.idt;
interface
uses
boot.mgr,
core.util, arch.x86.util, io.syslog;
const
@@ -86,4 +87,7 @@ begin
io.syslog.logln('IDT','INIT END.');
end;
initialization
boot.mgr.registerBoot('arch.x86.idt', @init, 'Interrupt Descriptor Table', 'arch.x86.gdt');
end.
+6 -1
View File
@@ -21,7 +21,9 @@ unit arch.x86.irq;
interface
uses core.util, arch.x86.util, io.syslog;
uses
boot.mgr,
core.util, arch.x86.util, io.syslog;
procedure init();
@@ -53,4 +55,7 @@ begin
io.syslog.logln('IRQ','INIT END.');
end;
initialization
boot.mgr.registerBoot('arch.x86.irq', @init, 'Interrupt Request Line', 'arch.x86.idt');
end.
+11 -1
View File
@@ -21,13 +21,23 @@ unit arch.x86.isr;
interface
uses
boot.mgr;
procedure init();
implementation
uses
arch.x86.util, arch.x86.isr.tmr0, arch.x86.bda;
procedure init();
begin
STI;
arch.x86.isr.tmr0.hook(uint32(@arch.x86.bda.tick_update));
end;
Initialization
boot.mgr.registerBoot('asuro.x86.isr', @init, 'Enable Interrupts and Timer', 'driver.storage.*.mgr');
end.
+9 -3
View File
@@ -12,7 +12,9 @@ unit arch.x86.panic;
interface
uses
core.panic;
boot.mgr,
core.panic,
io.syslog;
{ Register the x86 halt procedure with core.panic. Call after LVGL init. }
procedure init;
@@ -74,11 +76,15 @@ end;
procedure init;
begin
io.syslog.logln('PANIC', 'Initializing x86 Panic Handler.');
{ Register x86 halt as the panic halt procedure }
core.panic.registerHaltProc(@arch.x86.util.halt_and_catch_fire);
{ Initialize the BSOD LVGL screen }
core.panic.init;
io.syslog.logln('PANIC', 'Initialization complete.');
end;
initialization
boot.mgr.registerBoot('arch.x86.panic', @init, 'Panic Screen', 'driver.video*');
end.
+4
View File
@@ -20,6 +20,7 @@ unit arch.x86.v86;
interface
uses
boot.mgr,
core.util, arch.x86.util, core.panic, io.syslog, debug.tracer, arch.x86.memory.virtual, arch.x86.gdt, arch.x86.idt, arch.x86.isr.types;
const
@@ -771,4 +772,7 @@ begin
pop_trace;
end;
initialization
boot.mgr.registerBoot('arch.x86.v86', @init, 'V86 Mode Initialization', BOOT_MGR_BARRIER_EARLY);
end.
+1 -1
View File
@@ -49,7 +49,7 @@ MULTIBOOT_HEADER_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEA
;
; Kernel stack size
;
KERNEL_STACKSIZE equ 0x4000
KERNEL_STACKSIZE equ 0x4000
KERNEL_VIRTUAL_BASE equ 0xC0000000
KERNEL_PAGE_NUMBER equ (KERNEL_VIRTUAL_BASE >> 22)
+4
View File
@@ -22,6 +22,7 @@ unit arch.x86.fault;
interface
uses
boot.mgr,
arch.x86.fault.ace, arch.x86.fault.bpe, arch.x86.fault.btsse, arch.x86.fault.cfe, arch.x86.fault.csoe, arch.x86.fault.dbge, arch.x86.fault.dbz, arch.x86.fault.dfe, arch.x86.fault.gpf, arch.x86.fault.idoe, arch.x86.fault.iope, arch.x86.fault.mce,
arch.x86.fault.nce, arch.x86.fault.nmie, arch.x86.fault.oobe, arch.x86.fault.pf, arch.x86.fault.sfe, arch.x86.fault.snpe, arch.x86.fault.uie;
@@ -52,4 +53,7 @@ begin
arch.x86.fault.uie.register();
end;
initialization
boot.mgr.registerBoot('arch.x86.fault', @init, 'Faults', 'arch.x86.isr.mgr');
end.
+5
View File
@@ -22,6 +22,7 @@ unit arch.x86.isr.mgr;
interface
uses
boot.mgr,
arch.x86.isr, arch.x86.idt, arch.x86.isr.types, core.util, arch.x86.util;
type
@@ -2402,4 +2403,8 @@ begin
arch.x86.idt.set_gate(255, uint32(@ISR_255), $08, ISR_RING_0);
end;
initialization
boot.mgr.registerBoot('arch.x86.isr.mgr', @init, 'Interrupt Request Manager', 'arch.x86.irq');
end.
@@ -30,6 +30,7 @@ unit arch.x86.memory.physical;
interface
uses
boot.mgr,
arch.x86.multiboot,
io.syslog,
debug.tracer,
@@ -346,4 +347,7 @@ begin
pmm_total_blocks := nPresent;
end;
initialization
boot.mgr.registerBoot('arch.x86.memory.physical', @init, 'Physical Memory Manager', 'arch.x86.idt');
end.
@@ -23,6 +23,7 @@ unit arch.x86.memory.virtual;
interface
uses
boot.mgr,
core.util, arch.x86.util,
arch.x86.memory.physical,
io.syslog,
@@ -292,4 +293,7 @@ begin
pop_trace;
end;
initialization
boot.mgr.registerBoot('arch.x86.memory.virtual', @init, 'Virtual Memory Manager', 'arch.x86.memory.physical');
end.
+47 -1
View File
@@ -210,7 +210,27 @@ type
end;
PTextRec = ^TextRec;
{ FPC 3.2.2 INITFINAL table — compiler-generated unit init/finalize table.
Each unit with an initialization or finalization section gets an entry.
The table is emitted by the compiler under the symbol 'INITFINAL'. }
TInitFinalRec = packed record
InitProc : CodePointer;
FinalProc: CodePointer;
end;
TInitFinalTable = packed record
TableCount : longint;
Procs : array[1..1] of TInitFinalRec; { open array, actual size = TableCount }
end;
PInitFinalTable = ^TInitFinalTable;
{ Procedure type for calling initialization procs from the INITFINAL table }
TProcedure = procedure;
var
{ Compiler-generated INITFINAL table — contains init/finalize procs for
all units that have initialization or finalization sections }
InitFinalTable : TInitFinalTable; external name 'INITFINAL';
AK_START : uint32; external name 'kernel_start';
AK_END : uint32; external name 'kernel_end';
ASURO_KERNEL_START : uint32;
@@ -353,8 +373,19 @@ begin
end;
procedure fpc_initializeunits; [public, alias: 'FPC_INITIALIZEUNITS']; compilerproc;
var
i : longint;
proc : CodePointer;
begin
{ Unit initialization is handled by the core.version boot sequence }
{ Walk the compiler-generated INITFINAL table and call each unit's
initialization procedure (if non-nil). This runs before kmain, so
initialization sections must only do trivial work — write to static
globals, register boot entries, etc. No I/O or heap allocation. }
for i := 1 to InitFinalTable.TableCount do begin
proc := InitFinalTable.Procs[i].InitProc;
if proc <> nil then
TProcedure(proc)();
end;
end;
procedure fpc_do_exit; [public, alias: 'FPC_DO_EXIT']; compilerproc;
@@ -774,6 +805,9 @@ begin
end;
procedure init();
var
i : longint;
proc : CodePointer;
begin
ASURO_KERNEL_START := uint32(@AK_START);
ASURO_KERNEL_END := uint32(@AK_END);
@@ -783,6 +817,18 @@ begin
ErrorCode := 0;
ExitCode := 0;
ExitProc := nil;
{ Walk the INITFINAL table generated by compile_initcalls.sh and call
each unit's initialization section. FPC with -n does not insert this
call automatically, so we do it explicitly here — after basic system
globals are set up but before kmain proceeds.
Note: we inline the walk rather than calling fpc_initializeunits
because compilerproc procedures cannot be called from Pascal code. }
for i := 1 to InitFinalTable.TableCount do begin
proc := InitFinalTable.Procs[i].InitProc;
if proc <> nil then
TProcedure(proc)();
end;
end;
end.
+33 -328
View File
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+14 -1
View File
@@ -13,6 +13,7 @@ unit boot.splash;
interface
uses
boot.mgr,
driver.video.lvgl, driver.video, core.fmt.targa, core.gfx.texture, memory.heap;
{ Create the boot.splash screen and render the initial frame (0 %). }
@@ -82,6 +83,9 @@ var
logoTexture: PTexture;
logoDsc: PLVImageDsc;
var
Initialized : boolean = false;
{ ---- private helpers -------------------------------------------------- }
{ Build an lv_image_dsc_t that points to the decoded ARGB8888 pixel data. }
@@ -217,10 +221,13 @@ begin
{ Push the first frame to the display. }
redraw;
Initialized := true;
end;
procedure update(percent: uint32; status: pchar);
begin
if not Initialized then exit;
if splashScreen = nil then exit;
{ Clamp to 0..100 }
@@ -232,11 +239,12 @@ begin
redraw;
{ DEBUG: pause so each step is visible on screen }
busywait_500ms;
//busywait_500ms;
end;
procedure teardown;
begin
if not Initialized then exit;
if splashScreen = nil then exit;
{ Switch back to the screen that was active before the splash. }
@@ -260,6 +268,11 @@ begin
kfree(void(logoTexture));
logoTexture := nil;
end;
Initialized := false;
end;
Initialization
boot.mgr.registerBoot('boot.splash', @init, 'Boot Splash Screen', 'core.panic');
boot.mgr.registerBoot('boot.splash.teardown', @teardown, 'Stop Splash Screen', BOOT_MGR_BARRIER_FINAL);
end.
+9 -19
View File
@@ -76,6 +76,7 @@ procedure registerHaltProc(proc : THaltProc);
implementation
uses
boot.mgr,
io.syslog,
debug.tracer,
driver.video,
@@ -866,6 +867,8 @@ var
traceCard : Plv_obj;
traceHeader : Plv_obj;
begin
io.syslog.logln('PANIC', 'Initializing Core Panic Handler.');
{ Allocate text buffers — kernel-heap, persist for system lifetime }
faultTextBuf := pchar(kalloc(512));
regTextBuf := pchar(kalloc(PANIC_TEXT_BUF_SIZE));
@@ -1100,24 +1103,11 @@ begin
{ Mark BSOD screen as ready for panic rendering }
ScreenReady := true;
io.syslog.logln('PANIC', 'Core Panic Handler Initialized.');
end;
{ ====================================================================
Unit initialization — set safe defaults before init() is called.
==================================================================== }
begin
ScreenReady := false;
PanicInProgress := false;
HaltProc := @fallbackHalt;
faultTextBuf := nil;
regTextBuf := nil;
traceTextBuf := nil;
systemTextBuf := nil;
bsodScreen := nil;
faultLabel := nil;
regLabel := nil;
traceLabel := nil;
systemLabel := nil;
panicTexture := nil;
panicDsc := nil;
end.
initialization
boot.mgr.registerBoot('core.panic', @init, 'Core Panic Handler', 'arch.*.panic');
end.
Loaded 20 of 116 files, more files were not shown because too many files have changed in this diff. Show more