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
@@ -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.
|
||||
Reference in new issue
Block a user