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:
1 parent
dd56ffbcb4
commit
2d190c221a
116 files changed
+1922
-465
No files matched your search
@@ -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
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -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
@@ -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
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -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
@@ -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
Reference in new issue
Block a user