Compare commits

...
Author SHA1 Message Date
t3hn3rd 1ae867d929 fix: adapt subsystems to new VFS volume API and fix desktop program registry
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
- ramdrive: rewrite from registerDrive callbacks to TFilesystem/TStorage_Volume
  hooks (rd_Read, rd_ReadDir, rd_ReadOffset, rd_Identify) and mount via
  vfs.mountVolume('/disk/ram', ...). Remove open-slot tracking; VFS now
  manages file handles through the FD table.

- vfs: fix PathValid for otDRIVE nodes — split relative path into parent
  directory + leaf name, list the parent via readDirCallback, and check
  each entry's type so individual files are correctly identified as pvFile
  instead of always returning pvDirectory or pvInvalid.

- desktop: replace static array[0..MAX_PROGRAMS-1] program registry with
  a dynamic PLinkedListBase. Lazy-init on first registerProgram call.
  Remove prog_count := 0 from init so programs registered before
  desktop.init (e.g. notepad, diskutil) are no longer wiped.

- filedispatch, wasmrunner: add storagetypes to uses, remove stale Lock
  parameter from vfs.OpenFile calls.

- progmanager: clean up duplicate uses clauses and remove invalid
  kernel.bsod registration.
2026-03-07 22:12:18 +00:00
t3hn3rd 40a1c05728 Fix: missing imports in wasmio.pas 2026-03-07 21:26:26 +00:00
t3hn3rd 2bfbb44cfb feature: WASM execution pipeline, file dispatch, RAM drive, and VFS handle table
- Add file-type dispatch registry (filedispatch.pas) matching files by
  magic header bytes and routing to registered handlers
- Add WASM integration layer: wasmshim, wasmio, wasmrunner, wasmcleanup
  providing full WASI Preview1 bridging (fd_write/read, proc_exit,
  clock, random, args passthrough, environ stubs)
- Add RAM drive (ramdrive.pas) providing in-memory VFS at /disk/ram
  with a built-in hello world WASM binary
- (Placeholder) Implement VFS handle table for proper
  open/read/write/close/filesize routing through registered drives
  and devices
- Integrate file dispatch into vterminal for unknown commands, supporting
  both foreground and background execution of dispatched files
- Expand progmanager init with PS, KILL, TERMINATE, DEV, DISK, MEMRAW,
  BSOD, IFCONFIG, ARP, and TCP commands; wire up ramdrive, filedispatch,
  and wasmrunner initialization
- Replace serial.sendString with syslog.logln in desktop launcher
2026-03-07 21:26:25 +00:00
t3hn3rd 8ab2d0d04f fix: drone pipeline not working
- compile_wasuro.sh was copying files to the /code directory which
  is not where drone builds from, fixed to use $(pwd) and relative
  directories based on the root.
2026-03-07 21:24:13 +00:00
t3hn3rd b51881ced7 feat: integrate Wasuro WASM runtime into Asuro build chain
- Add compile_wasuro.sh to sparse-clone Wasuro src/wasm from gitea
  (develop branch) with caching to skip redundant pulls
- Update compile.sh to include wasuro build step in pipeline
- Update compile_sources.sh to dynamically discover -Fu paths via
  find across src/ and wasuro/ directories
- Extend system.pas with FPC 3.2.2 compilerprocs required by Wasuro:
  - 64-bit signed/unsigned div and mod (fpc_div_int64, fpc_mod_int64,
    fpc_div_qword, fpc_mod_qword) with correct i386 parameter mapping
  - 64-bit multiply (fpc_mul_int64) via three 32-bit MUL instructions
  - Float-to-integer intrinsics (Trunc, Round) using x87 FPU
  - Memory allocation compilerprocs (fpc_getmem, fpc_freemem)
    delegating to kernel kalloc/kfree
  - Exception handling stubs (reraise, raiseexception, catches, doneexception)
  - setjmp/longjmp for exception address stack
  - Fix sInt64 type alias (was longint/32-bit, now int64/64-bit)
  - Add serial debug helpers (COM1 $3F8) for bare-metal tracing
- Wire up Wasuro in kernel.pas: init WASM VM, set I/O callback to
  syslog, and run all 1103 Wasuro tests (0 failures)
- Update .gitignore to exclude wasuro/ cache directory
2026-03-07 21:24:12 +00:00
t3hn3rd 0d6f1e006c feature: preemptive process management - implementation progress
Implement a preemptive multitasking system for the Asuro kernel.

Context Switching & Scheduling:
- Custom IRQ0 ISR (contextswitcher.pas) with PUSHAD/POPAD ESP-swap
- Round-robin scheduler with priority-based quantum
- Process table using DList of PProcessContext pointers
- Idle process (PID 0) replaces kernel HLT loop

Process Lifecycle:
- create/kill/terminate/sendMessage API (processmanager.pas)
- Process states: Created, Running, Ready, Suspended, Awaiting,
  Finished, Error
- Parent-child tracking (ParentID, smChildExited notification on reap)
- proc_yield, proc_sleep_ms, proc_await, proc_suspend, proc_exit

Resource Binding & Cleanup:
- Per-process resource list
  (bindResource/unbindResource/unbindAllResources)
- TCP sockets auto-bound to owning process (OwnerPID on TTCPSocket)
- socket_cleanup + auto-unbind in DestroySocket

VTerminal Refactor:
- Multi-instance design (heap-allocated TVTermState per terminal)
- Foreground process with incremental stdout/stderr drain via LVGL timer
- Ctrl+C kills foreground process (killForeground)
- Per-terminal CWD, dir stack, FS builtins (CD/LS/PUSHD/POPD)
- Background job support (& suffix, JOBS/FG commands)
- Command history (Up/Down arrow)

Command Consolidation:
- 14 commands extracted from 9 units into centralized progmanager.pas
- Command procedures exported in host unit interfaces
- E1000/TRACER/stdio builtins kept in-place (conditional/circular)

New Units:
- src/include/proctypes.pas — process type definitions
- src/processmanager.pas — core process manager
- src/prog/ping.pas — standalone ICMP ping process
- src/prog/testcmd.pas — test command (proc_sleep_ms demo)
- src/testprocs.pas — process subsystem smoke tests

Misc:
- ICMP callbacks gain userData parameter for concurrency-safe ping
- CLI/STI guards on kalloc/kfree (lmemorymanager.pas)
- LV_KEY_CTRLC constant + Ctrl+C interception in LVGL keyboard hook
- Window owner PID tracking (windows.pas)
- ISR_32 gate override support (isrmanager.pas)
2026-03-07 21:21:45 +00:00
16 changed files with 1795 additions and 68 deletions
+2 -1
View File
@@ -16,4 +16,5 @@ dockerout.txt
AGENTS.md
lessons_learnt.md
*.log
/doc/*.md
/doc/*.md
wasuro
+1
View File
@@ -24,6 +24,7 @@ declare -a run_steps=(
"compile_stub.sh" "Failed to compile stub!"
"compile_vergen.sh" "Versions failed to compile"
"compile_lvgl.sh" "Failed to compile LVGL!"
"compile_wasuro.sh" "Failed to pull Wasuro!"
"compile_sources.sh" "Failed to compile FPC Sources!"
"compile_link.sh" "Failed linking!"
"compile_isogen.sh" "Failed to create ISO!"
+43
View File
@@ -0,0 +1,43 @@
#!/usr/bin/env bash
# compile_wasuro.sh — Pull Wasuro WASM runtime source into wasuro/
# Clones the repo (sparse, src/wasm only) and copies the Pascal sources
# into $PWD/wasuro so the FPC build can reference them via -Fu.
set -e
WASURO_REPO="https://gitea.spexeah.com/Spexeah/Wasuro.git"
WASURO_BRANCH="develop"
WASURO_TMP="/tmp/wasuro"
WASURO_OUT="$(pwd)/wasuro"
echo " "
echo "======================="
echo " "
echo "Pulling Wasuro WASM runtime..."
echo " "
# Skip if wasuro/ already has .pas files (cached from previous build)
if [ -n "$(find "${WASURO_OUT}" -name '*.pas' 2>/dev/null | head -1)" ]; then
echo "Wasuro sources already present in ${WASURO_OUT}, skipping pull."
echo " "
exit 0
fi
# Clone sparse checkout (only src/wasm)
rm -rf "$WASURO_TMP"
git clone --depth 1 --branch "${WASURO_BRANCH}" --filter=blob:none --sparse \
"${WASURO_REPO}" "${WASURO_TMP}" 2>&1
cd "$WASURO_TMP"
git sparse-checkout set src/wasm 2>&1
cd -
echo "Copying src/wasm to ${WASURO_OUT}..."
rm -rf "$WASURO_OUT"
mkdir -p "$WASURO_OUT"
cp -a "${WASURO_TMP}/src/wasm/"* "$WASURO_OUT"/
rm -rf "$WASURO_TMP"
TOTAL=$(find "$WASURO_OUT" -name '*.pas' | wc -l)
echo "Copied ${TOTAL} Pascal source files."
echo " "
echo "Wasuro pull complete."
echo " "
+4 -1
View File
@@ -29,11 +29,14 @@ unit contextswitcher;
interface
uses
idt, isrmanager, processmanager, proctypes, util, tracer;
idt, isrmanager, processmanager, proctypes, util, syslog, tracer;
{ Initialise: overwrite IDT gate 32 with our custom ISR. }
procedure init;
{ No idle ESP variable needed — idle is now a formal process (PID 0)
with its SavedESP managed like any other process. }
implementation
{ -----------------------------------------------------------------------
File diff suppressed because it is too large Load Diff
+64 -10
View File
@@ -1157,6 +1157,13 @@ var
pvVol : PStorage_Volume;
pvStatus : puint32;
pvDirList: PLinkedListBase;
pvSplitRel : PLinkedListBase;
pvSegCount : uint32;
pvIdx : uint32;
pvLeafName : pchar;
pvParentDir : pchar;
pvTmpConcat : pchar;
pvEntry : PDirectory_Entry;
begin
tracer.push_trace('vfs.PathValid.enter');
@@ -1175,22 +1182,69 @@ begin
RelPath[0] := '/';
end;
pvVol := PStorage_Volume(Obj^.Reference);
{ Actually verify the path exists on the volume }
{ Verify the path exists on the volume }
if (pvVol^.filesystem <> nil) and (pvVol^.filesystem^.readDirCallback <> nil) then begin
{ If RelPath is just '/' we're at volume root — always valid }
if StringEquals(RelPath, '/') then begin
PathValid := pvDirectory;
end else begin
{ Ask the filesystem if this directory actually exists }
pvStatus := puint32(kalloc(4));
pvStatus^ := 0;
pvDirList := pvVol^.filesystem^.readDirCallback(pvVol, RelPath, pvStatus);
if pvStatus^ = 0 then
PathValid := pvDirectory
else
{ Split RelPath into parent directory and leaf name,
then list the parent and look for the leaf entry. }
pvSplitRel := STRLL_FromString(RelPath, '/');
pvSegCount := STRLL_Size(pvSplitRel);
if pvSegCount = 0 then begin
PathValid := pvInvalid;
if pvDirList <> nil then LL_Free(pvDirList);
kfree(puint32(pvStatus));
end else begin
pvLeafName := STRLL_Get(pvSplitRel, pvSegCount - 1);
{ Build parent directory path from all segments except the last }
if pvSegCount <= 1 then begin
pvParentDir := stringNew(1);
pvParentDir[0] := '/';
end else begin
pvParentDir := stringNew(0);
for pvIdx := 0 to pvSegCount - 2 do begin
if stringSize(pvParentDir) > 0 then begin
pvTmpConcat := stringConcat(pvParentDir, '/');
kfree(void(pvParentDir));
pvParentDir := pvTmpConcat;
end;
pvTmpConcat := stringConcat(pvParentDir, STRLL_Get(pvSplitRel, pvIdx));
kfree(void(pvParentDir));
pvParentDir := pvTmpConcat;
end;
end;
{ List parent directory }
pvStatus := puint32(kalloc(4));
pvStatus^ := 0;
pvDirList := pvVol^.filesystem^.readDirCallback(pvVol, pvParentDir, pvStatus);
PathValid := pvInvalid;
if (pvDirList <> nil) and (pvStatus^ = 0) and (LL_Size(pvDirList) > 0) then begin
for pvIdx := 0 to LL_Size(pvDirList) - 1 do begin
pvEntry := PDirectory_Entry(LL_Get(pvDirList, pvIdx));
if (pvEntry <> nil) and (pvEntry^.fileName <> nil) then begin
if stringEquals(pvEntry^.fileName, pvLeafName) then begin
case pvEntry^.entryType of
fileEntry: PathValid := pvFile;
directoryEntry: PathValid := pvDirectory;
mountEntry: PathValid := pvDirectory;
end;
break;
end;
end;
end;
{ Free entry file names and list }
for pvIdx := 0 to LL_Size(pvDirList) - 1 do begin
pvEntry := PDirectory_Entry(LL_Get(pvDirList, pvIdx));
if (pvEntry <> nil) and (pvEntry^.fileName <> nil) then
kfree(void(pvEntry^.fileName));
end;
LL_Free(pvDirList);
end else if pvDirList <> nil then
LL_Free(pvDirList);
kfree(puint32(pvStatus));
kfree(void(pvParentDir));
end;
STRLL_Free(pvSplitRel);
end;
end else
PathValid := pvInvalid;
+41 -26
View File
@@ -29,6 +29,9 @@ procedure relayout;
implementation
uses
syslog, lists, lmemorymanager;
const
DOCK_HEIGHT = 48;
DOCK_MARGIN = 8;
@@ -47,8 +50,6 @@ const
SYSINFO_W = 480;
SYSINFO_H = 560;
MAX_PROGRAMS = 16;
{ Animation }
ANIM_SPEED = 12; { pixels per frame to slide }
@@ -59,10 +60,10 @@ type
launch : TProgLaunchProc;
active : boolean;
end;
PProgEntry = ^TProgEntry;
var
programs : array[0..MAX_PROGRAMS-1] of TProgEntry;
prog_count : uint32;
programs : PLinkedListBase;
{ ---- Desktop UI elements ---- }
var
@@ -99,12 +100,15 @@ var
Program Registry
============================================================ }
procedure registerProgram(name: pchar; launcher: TProgLaunchProc);
var
entry : PProgEntry;
begin
if prog_count >= MAX_PROGRAMS then exit;
programs[prog_count].name := name;
programs[prog_count].launch := launcher;
programs[prog_count].active := true;
inc(prog_count);
if programs = nil then
programs := LL_New(sizeof(TProgEntry));
entry := PProgEntry(LL_Add(programs));
entry^.name := name;
entry^.launch := launcher;
entry^.active := true;
end;
{ ============================================================
@@ -435,6 +439,7 @@ var
code : uint32;
target : Plv_obj;
i, pi : uint32;
entry : PProgEntry;
begin
code := lv_event_get_code(e);
if code <> LV_EVENT_CLICKED then exit;
@@ -443,10 +448,13 @@ begin
for i := 0 to RESULTS_MAX_VISIBLE - 1 do begin
if result_btns[i] = target then begin
pi := result_prog[i];
if (pi < prog_count) and programs[pi].active then begin
serial.sendString('[Desktop] Launching program' + #10);
clearAndClose;
programs[pi].launch;
if (programs <> nil) and (pi < LL_Size(programs)) then begin
entry := PProgEntry(LL_Get(programs, pi));
if (entry <> nil) and entry^.active then begin
syslog.logln('Desktop', 'Launching program');
clearAndClose;
entry^.launch;
end;
end;
exit;
end;
@@ -547,6 +555,7 @@ var
query : pchar;
i, vis : uint32;
panel_h : sint32;
fentry : PProgEntry;
begin
if not results_open then exit;
if results_panel = nil then exit;
@@ -554,15 +563,18 @@ begin
query := lv_textarea_get_text(search_ta);
vis := 0;
for i := 0 to prog_count - 1 do begin
if vis >= RESULTS_MAX_VISIBLE then break;
if not programs[i].active then continue;
if programs <> nil then begin
for i := 0 to LL_Size(programs) - 1 do begin
if vis >= RESULTS_MAX_VISIBLE then break;
fentry := PProgEntry(LL_Get(programs, i));
if (fentry = nil) or (not fentry^.active) then continue;
if (query = nil) or (query^ = #0) or ciContains(programs[i].name, query) then begin
lv_label_set_text(result_lbls[vis], programs[i].name);
result_prog[vis] := i;
lv_obj_remove_flag(result_btns[vis], LV_OBJ_FLAG_HIDDEN);
inc(vis);
if (query = nil) or (query^ = #0) or ciContains(fentry^.name, query) then begin
lv_label_set_text(result_lbls[vis], fentry^.name);
result_prog[vis] := i;
lv_obj_remove_flag(result_btns[vis], LV_OBJ_FLAG_HIDDEN);
inc(vis);
end;
end;
end;
@@ -588,7 +600,8 @@ end;
============================================================ }
procedure search_event_cb(e: Plv_event); cdecl;
var
code : uint32;
code : uint32;
rentry : PProgEntry;
begin
code := lv_event_get_code(e);
@@ -618,9 +631,12 @@ begin
else if code = LV_EVENT_READY then begin
{ Enter pressed (one-line textarea) — launch first result }
if results_visible > 0 then begin
if result_prog[0] < prog_count then begin
clearAndClose;
programs[result_prog[0]].launch;
if (programs <> nil) and (result_prog[0] < LL_Size(programs)) then begin
rentry := PProgEntry(LL_Get(programs, result_prog[0]));
if rentry <> nil then begin
clearAndClose;
rentry^.launch;
end;
end;
end;
end;
@@ -701,7 +717,6 @@ begin
tracer.push_trace('desktop.init.enter');
sysinfo_win_id := 0;
prog_count := 0;
results_open := false;
results_panel := nil;
anim_closing := false;
File diff suppressed because it is too large Load Diff
+203 -18
View File
File diff suppressed because it is too large Load Diff
+9
View File
@@ -106,6 +106,10 @@ uses
volcmd,
volumemanager,
vterminal,
wasm,
wasm.vm.io,
wasm.test,
wasm.test.framework,
Windows,
XHCI;
@@ -243,6 +247,10 @@ begin
vfs.init();
storagetest.init;
{ Let's test Wasuro! }
wasm.vm.io.io_set_writechar(@syslog.logchar);
wasm.wasm_init;
{ Management Interfaces }
tracer.push_trace('kmain.STRMGMT');
splash.update(10, 'Initializing storage management...');
@@ -328,6 +336,7 @@ begin
cfifols.UnitTest;
lifo.UnitTest;
circ.UnitTest;
wasm.test.run_all_tests;
splash.update(90, 'Running test suite...');
minh.UnitTest;
maxh.UnitTest;
+83 -5
View File
@@ -18,7 +18,7 @@ interface
uses
lvgl, video, windows, desktop, keyboard, tracer,
strings, util, lmemorymanager, asuro, stdio, vfs,
processmanager, proctypes, lists, hashmap;
processmanager, proctypes, lists, hashmap, filedispatch;
procedure init;
@@ -445,6 +445,8 @@ var
lastParam : pchar;
job : PBackgroundJob;
slotPtr : ^uint32;
absPath : pchar;
dispatchPID : uint32;
begin
{ Null-terminate input }
state^.line_buf[state^.line_len] := 0;
@@ -693,10 +695,86 @@ begin
end;
end;
end else begin
appendText(state, 'Unknown command. Type HELP for a list.');
appendChar(state, #10);
stdio.freeParams(params);
showPrompt(state);
{ No built-in command found — try file dispatch }
absPath := vfs.makeAbsolutePathFrom(params^.Param, state^.cwd);
if absPath <> nil then begin
if is_bg then begin
{ Background file dispatch }
job := PBackgroundJob(kalloc(SizeOf(TBackgroundJob)));
if job <> nil then begin
memset(uint32(job), 0, SizeOf(TBackgroundJob));
job^.StdOut := stdio.createOutBuf(1024);
job^.StdErr := stdio.createOutBuf(1024);
job^.LastDrain := 0;
job^.LastDrainE := 0;
inc(state^.bg_next_job);
job^.JobNum := state^.bg_next_job;
pcount := stringSize(params^.Param);
if pcount > 31 then pcount := 31;
memcpy(uint32(params^.Param), uint32(@job^.CmdName[0]), pcount);
job^.CmdName[pcount] := #0;
dispatchPID := filedispatch.dispatch(absPath, params,
nil, job^.StdOut, job^.StdErr);
if dispatchPID > 0 then begin
job^.PID := dispatchPID;
if state^.bg_jobs = nil then
state^.bg_jobs := DL_New(SizeOf(uint32));
slotPtr := DL_Add(state^.bg_jobs);
slotPtr^ := uint32(job);
appendText(state, '[');
lastParam := intToString(job^.JobNum);
appendText(state, lastParam);
kfree(void(lastParam));
appendText(state, '] ');
lastParam := intToString(job^.PID);
appendText(state, lastParam);
kfree(void(lastParam));
appendChar(state, #10);
end else begin
appendText(state, 'Unknown command. Type HELP for a list.');
appendChar(state, #10);
stdio.freeOutBuf(job^.StdOut);
stdio.freeOutBuf(job^.StdErr);
kfree(void(job));
end;
end;
kfree(void(absPath));
stdio.freeParams(params);
showPrompt(state);
end else begin
{ Foreground file dispatch }
state^.fg_stdout := stdio.createOutBuf(1024);
state^.fg_stderr := stdio.createOutBuf(1024);
state^.fg_stdin := stdio.createOutBuf(0);
state^.last_drain := 0;
state^.last_drain_err := 0;
state^.fg_params := params;
dispatchPID := filedispatch.dispatch(absPath, params,
state^.fg_stdin, state^.fg_stdout, state^.fg_stderr);
kfree(void(absPath));
if dispatchPID > 0 then begin
state^.ForegroundPID := dispatchPID;
end else begin
appendText(state, 'Unknown command. Type HELP for a list.');
appendChar(state, #10);
stdio.freeOutBuf(state^.fg_stdout); state^.fg_stdout := nil;
stdio.freeOutBuf(state^.fg_stderr); state^.fg_stderr := nil;
stdio.freeOutBuf(state^.fg_stdin); state^.fg_stdin := nil;
stdio.freeParams(params);
state^.fg_params := nil;
state^.ForegroundPID := 0;
showPrompt(state);
end;
end;
end else begin
appendText(state, 'Unknown command. Type HELP for a list.');
appendChar(state, #10);
stdio.freeParams(params);
showPrompt(state);
end;
end;
end else begin
if params <> nil then stdio.freeParams(params);
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+44
View File
@@ -0,0 +1,44 @@
{
Prog->WASM->WASMShim - Bridges the Asuro process model to WASURO VM.
Defines the shim record that ties a PProcessContext to a
PWASMProcessContext, plus fault classification types.
@author(Kieron Morris <[email protected]>)
}
unit wasmshim;
interface
uses
proctypes,
wasm.types.context;
type
{ Fault classification — detected Asuro-side after wasm_tick returns false }
TWASMFaultKind = (
wfNone, { No fault — normal completion }
wfInvalidBinary, { Parse or validation failure }
wfNoStartExport, { _start not found in exports }
wfUnexpectedHalt, { Running=false with no ExitCode, IP < Limit }
wfCodeOverrun, { IP ran past code limit }
wfUnknown { Catch-all }
);
{ The shim bridges Asuro process context to the WASURO VM context }
PProcessWASMShim = ^TProcessWASMShim;
TProcessWASMShim = record
ProcessCtx : PProcessContext; { The owning Asuro process }
WASMCtx : PWASMProcessContext; { The WASURO VM context }
FileBuffer : puint8; { kalloc'd buffer holding the .wasm file }
FileSize : uint32; { Size of the loaded file }
FaultKind : TWASMFaultKind; { Fault classification after execution }
FaultIP : uint32; { IP at which fault occurred }
ArgCount : uint32; { Number of command-line arguments }
ArgBuf : pchar; { Flat buffer of null-terminated arg strings }
ArgBufSize : uint32; { Total byte size of ArgBuf }
end;
implementation
end.
+18 -7
View File
@@ -23,9 +23,17 @@ unit progmanager;
interface
uses
tracer,
tracer, stdio, processmanager,
//progs
base64_prog, md5sum, dhclient, vbeinfo, testcmd, ping, meminfo, setres;
base64_prog, md5sum, dhclient, vbeinfo, testcmd, ping, meminfo, setres,
//drivers
ramdrive, drivermanagement,
//network
ipv4, arp, tcp,
//dispatch
filedispatch,
//wasm
wasmrunner;
{ Initialize all baked-in programs }
procedure init();
@@ -33,10 +41,9 @@ procedure init();
implementation
uses
stdio,
kernel,
//command provider units
kernel, cpu, drivermanagement, processmanager,
arp, ipv4, tcp,
cpu,
diskcmd, usbcore, diskutil, notepad, partcmd, volcmd;
procedure init();
@@ -60,8 +67,8 @@ begin
diskcmd.init();
partcmd.init();
volcmd.init();
diskutil.init;
notepad.init;
diskutil.init();
notepad.init();
md5sum.init();
base64_prog.init();
dhclient.init();
@@ -69,6 +76,10 @@ begin
testcmd.init();
ping.init();
meminfo.init();
{ File dispatch & WASM integration }
ramdrive.init();
filedispatch.init();
wasmrunner.init();
setres.init();
end;