Compare commits

..
Author SHA1 Message Date
t3hn3rd d01b534a3d rebase fix: stdio.registerCommand('BSOS') removed from progmanager.pas
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
- This can sit in kernel for now, given that's where the handler is.
- TODO: Move everything to sit under prog/
2026-03-04 19:49:56 +00:00
t3hn3rd 491b0ea5c3 fix: Allocator Merge Conflicts Resolved 2026-03-04 19:43:43 +00:00
t3hn3rd de6fde05cc 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-04 19:42:33 +00:00
t3hn3rd fb675a2299 feature: implement TCP (RFC 793) protocol driver
Add full TCP/IP stack implementation at L4 alongside UDP and ICMP.

Core Protocol Engine:
- TCP types in nettypes.pas (header, TCB, state enum, error codes,
  callbacks, OOO entry, socket structures)
- 3-way handshake (active & passive OPEN)
- Reliable data transfer with ACK and sequence number tracking
- Graceful close (FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT)
- RST send/receive handling
- Retransmission with exponential backoff (max 5 attempts)
- Pseudo-header based checksum (RFC 793)

Server Support:
- LISTEN → SYN_RECEIVED → ESTABLISHED passive open path
- Listen backlog enforcement (configurable per-socket)
- accept() to retrieve established child connections

Robustness & Hardening:
- Delayed ACK timer (~200ms)
- Nagle's algorithm (buffer small sends while unACKed data pending)
- Jacobson/Karels RTT estimation with adaptive RTO
- Congestion control (slow start / congestion avoidance)
- Zero-window probing with exponential backoff
- MSS option negotiation in SYN/SYN-ACK (Kind=2, Len=4)
- Keep-alive (30s idle, 10s interval, 5 probes)
- Out-of-order segment reassembly (4-slot buffer)

Terminal & Testing:
- tcpconnect: active open + send "Hello, World!"
- tcplisten: passive open with syslog output
- tcphttp: HTTP/1.0 GET client

Also add push_trace() instrumentation to net, eth2, arp, ipv4,
icmp, udp, and dhcp entry points for call tracing, and register
tcp in net.init.
2026-03-04 19:39:32 +00:00
t3hn3rd aa374b6816 Merge pull request 'refactor(memory): complete PMM/VMM/LMM rewrite - bitmap allocators, bug fixes, hardening' (#40) from feature/memory-allocation-optimization into develop
continuous-integration/drone/push Build is passing
Reviewed-on: #40
Reviewed-by: Aaron Hance <[email protected]>
2026-03-04 19:34:44 +00:00
t3hn3rd f427b7bcc7 refactor(memory): complete PMM/VMM/LMM rewrite - bitmap allocators, bug fixes, hardening
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
PMM Rewrite:
- Replace ~8KB record array with compact bitmaps
  (PhysPresent/PhysAlloc/PhysScanned, 128B each)
- Add PhysOwner[0..1023] for per-block ownership tracking
- new_block: O(1) amortised via NextFreeHint + dword-level BSF scan,
  returns 0 as OOM sentinel
- free_block: O(1) direct bit clear with double-free detection
- alloc_block: validates PhysPresent and PhysAlloc bits before allocation
- Add pmm_free_blocks/pmm_total_blocks stats functions

VMM Correctness Fixes:
- Fix free_page block extraction (Address SHR 10, was using
  raw Address field)
- Fix invlpg operand (use virtual address, was passing PDE index)
- Clear PDE entry on free_page before returning block to PMM
- Remove map_page double-write (delegate to map_page_ex only)
- Add OOM propagation (new_page returns false if PMM returns 0)
- Fix missing pop_trace in new_page error path

LMM Rewrite:
- Replace per-entry record array with bitmap allocator
  (93% vs 43% page efficiency)
- Layout: Header(24B) + Bitmap(64512B) + Padding + Data at 0x10000
- SIZE_PREFIX=16 for 16-byte aligned returns (SSE MOVAPS requirement)
- Next-fit bitmap scan with roving hint (NextFree) and dword-level
  fast skip
- Large alloc sentinel (LARGE_ALLOC_MAGIC=$FFFFFFFE) so kfree detects
  klalloc'd memory
- Implement klfree (was previously a no-op - pages could never
  be returned)
- Implement try_release_page (return fully-free heap pages to VMM/PMM)
- Fix interrupt safety: stack-balanced pushfd/cli/pop +
  restore_if (sti only)
  Fixes Bad TSS caused by popfd restoring dangerous EFLAGS bits (NT, IOPL)
- Zero memory via rep stosd instead of byte-by-byte loop

Hardening:
- kalloc OOM now triggers BSOD instead of returning nil
  (90% of callers don't check)
- Double-free detection in kfree (verify bitmap bits set before clearing)
- Guard bytes ({$IFDEF DEBUG_LMM}): $DEADBEEF sentinel for buffer overrun detection
- kpalloc: bounds check (block >= 1024 -> GPF) + syslog MMIO mapping audit log

Observability:
- Add MEMINFO command as src/prog/meminfo.pas (moved from inline kernel.pas)
- Displays multiboot memory, PMM block stats, LMM heap stats
- Register via progmanager.pas following standard prog pattern

Files changed:
- src/pmemorymanager.pas
- src/vmemorymanager.pas
- src/lmemorymanager.pas
- src/kernel.pas
- src/progmanager.pas
- src/prog/meminfo.pas
2026-03-04 19:23:46 +00:00
Aaron 4ba3c5b524 Merge pull request 'feature/Queues' (#37) from feature/Queues into develop
continuous-integration/drone/push Build is passing
Reviewed-on: #37
2026-03-04 00:06:10 +00:00
t3hn3rd 7180ad39d8 Merge pull request 'feature: Pipeline - LVGL Build Caching' (#38) from feature/lvgl-build-caching into develop
continuous-integration/drone/push Build is passing
Reviewed-on: #38
Reviewed-by: Aaron Hance <[email protected]>
2026-03-04 00:05:01 +00:00
Aaron 6c7bcc1911 better testing
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2026-03-04 00:00:56 +00:00
Aaron e09c9b5595 refactor 2026-03-04 00:00:56 +00:00
Aaron 9476bb0c8a compile 2026-03-04 00:00:56 +00:00
Aaron 8f7db8507b Queues 2026-03-04 00:00:56 +00:00
t3hn3rd 188b1aebb0 feature: Pipeline - LVGL Build Caching
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
- Add LVGL build caching: store liblvgl.a on host mount to skip
  full recompilation on subsequent builds
2026-03-03 23:22:09 +00:00
t3hn3rd 452203b7b4 Merge pull request 'bug: vtop incorrect bitmask' (#36) from feature/vtop-fix into develop
continuous-integration/drone/push Build is passing
Reviewed-on: #36
Reviewed-by: Aaron Hance <[email protected]>
2026-03-03 20:03:47 +00:00
t3hn3rd 76c419336e bug: vtop incorrect bitmask
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
- Fix for issue #32 in which the incorrect bitmask ($FFFFFF) is used where
  $3FFFFF should be used instead. (24 vs 22 bits).
2026-03-03 19:10:08 +00:00
admin 2ad0ae8420 Merge pull request 'feature/gitattributes' (#30) from feature/gitattributes into develop
continuous-integration/drone/push Build is passing
Reviewed-on: #30
2026-03-02 21:56:56 +00:00
43 changed files with 7876 additions and 708 deletions
+22 -8
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
# compile_lvgl.sh — Download LVGL v9.2 source and compile into lib/liblvgl.a
# Clone & compile in /tmp (fast container-local fs).
# Copy source + objects to /lvgl (host mount) for debugging.
# Cache liblvgl.a on host mount (/code/lvgl/) to skip rebuild.
set -e
LVGL_VERSION="v9.2.2"
@@ -10,6 +10,7 @@ LVGL_DIR="/tmp/lvgl"
OBJ_DIR="/tmp/lvgl_obj"
CONF_DIR="$(pwd)/lvglh"
OUT_DIR="$(pwd)/lib"
CACHE_DIR="/code/lvgl"
CC="gcc"
CFLAGS="-m32 -march=i686 -ffreestanding \
@@ -26,6 +27,17 @@ echo " "
echo "Compiling LVGL..."
echo " "
# If cached liblvgl.a exists on host mount, just copy it and skip everything
if [ -f "${CACHE_DIR}/liblvgl.a" ]; then
echo "Found cached liblvgl.a in ${CACHE_DIR}, copying to ${OUT_DIR}..."
cp "${CACHE_DIR}/liblvgl.a" "${OUT_DIR}/liblvgl.a"
echo "(Delete lvgl/liblvgl.a to force a full rebuild.)"
echo " "
echo "LVGL compilation complete (cached)."
echo " "
exit 0
fi
# Clone LVGL into /tmp (container-local)
rm -rf "$LVGL_DIR"
echo "Downloading LVGL ${LVGL_VERSION}..."
@@ -105,14 +117,16 @@ else
echo "No custom LVGL files in lvglh/."
fi
# Copy source + objects to /lvgl host mount for debugging
echo "Copying LVGL source and objects to host mount..."
mkdir /code/lvgl 2>/dev/null || true
rm -rf /code/lvgl/* /code/lvgl/.[!.]* /code/lvgl/..?* 2>/dev/null || true
cp -a "$LVGL_DIR/src" /code/lvgl/src
cp -a "$OBJ_DIR" /code/lvgl/obj
# Cache liblvgl.a and source to host mount for next build
echo "Caching LVGL to host mount..."
mkdir -p "$CACHE_DIR"
rm -rf ${CACHE_DIR}/* ${CACHE_DIR}/.[!.]* ${CACHE_DIR}/..?* 2>/dev/null || true
cp "${OUT_DIR}/liblvgl.a" "${CACHE_DIR}/liblvgl.a"
cp -a "$LVGL_DIR/src" "${CACHE_DIR}/src"
cp -a "$LVGL_DIR"/*.h "${CACHE_DIR}/" 2>/dev/null || true
cp -a "$OBJ_DIR" "${CACHE_DIR}/obj"
echo "Done."
echo " "
echo "LVGL compilation complete."
echo " "
echo " "
+1 -1
View File
@@ -4,4 +4,4 @@ echo "======================="
echo " "
echo "Compiling FPC Sources..."
echo " "
fpc -Aelf -gw -g -gl -n -v0ew -O3 -OpPENTIUM3 -Si -Sc -Sg -Xd -CX -XXs -CfSSE -CfSSE2 -Rintel -Pi386 -Tlinux -FElib/ -Fusrc/* -Fusrc/driver/* -Fusrc/driver/net/* -Fusrc/driver/bus/* -Fusrc/driver/bus/usb/* -Fusrc/driver/hid/* src/kernel.pas
fpc -Aelf -gw -g -gl -n -v0ew -O3 -OpPENTIUM3 -Si -Sc -Sg -Xd -CX -XXs -CfSSE -CfSSE2 -Rintel -Pi386 -Tlinux -FElib/ -Fusrc/* -Fusrc/include/* -Fusrc/driver/* -Fusrc/driver/net/* -Fusrc/driver/bus/* -Fusrc/driver/bus/usb/* -Fusrc/driver/hid/* src/kernel.pas
+111 -5
View File
@@ -12,15 +12,121 @@
// See the License for the specific language governing permissions and
// limitations under the License.
{
ContextSwitcher - Switch Process Contexts when preempted.
@author(Kieron Morris <[email protected]>)
{
ContextSwitcher - Custom IRQ0 handler for preemptive context switching.
Replaces the default ISR_32 with a naked assembly stub that saves the
interrupted context (PUSHAD + segment regs), calls a Pascal helper to
dispatch timer hooks, send EOI, and run the scheduler, then restores
the next process context (or idles) via the returned ESP.
@author(Kieron Morris <[email protected]>)
}
unit contextswitcher;
{$ASMMODE intel}
interface
implementation;
uses
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
{ -----------------------------------------------------------------------
do_context_switch_work
Pascal helper called from the assembly ISR. Receives the current ESP
(pointing to the GS..EFLAGS save area), dispatches timer hooks, sends
EOI, runs the scheduler and returns the ESP for the next context.
Uses register calling convention: saved_esp in EAX, result in EAX.
----------------------------------------------------------------------- }
function do_context_switch_work(saved_esp : uint32) : uint32;
var
next : PProcessContext;
begin
{ 1. Save ESP into the current process }
processmanager.CurrentProcess^.SavedESP := saved_esp;
{ 2. Dispatch all hooks registered on interrupt 32 (timer hooks).
This fires TMR_0_ISR.Main which in turn fires BDA tick,
graphics refresh, USB hotplug, etc. }
isrmanager.dispatchHooks(32);
{ 3. Send End-Of-Interrupt to the master PIC }
outb($20, $20);
{ 4. Pick the next process to run (always returns non-nil; idle as fallback) }
next := processmanager.scheduler_pick_next;
processmanager.CurrentProcess := next;
{ 5. Return the selected process ESP }
do_context_switch_work := next^.SavedESP;
end;
{ -----------------------------------------------------------------------
context_switch_isr
Naked assembly ISR that replaces ISR_32 (IRQ0 / PIT timer).
Stack on entry (pushed by CPU):
[ESP+8] EFLAGS
[ESP+4] CS
[ESP+0] EIP
We push general-purpose and segment registers, call the Pascal helper,
switch ESP to the returned value, pop registers and IRETD.
----------------------------------------------------------------------- }
procedure context_switch_isr; assembler; nostackframe;
asm
{ Save all general-purpose registers (EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI) }
pushad
{ Save segment registers }
push ds
push es
push fs
push gs
{ Load kernel data segments }
mov ax, $10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
{ Call Pascal helper: EAX = current ESP (register calling convention).
Returns new ESP in EAX. }
mov eax, esp
call do_context_switch_work
mov esp, eax
{ Restore segment registers }
pop gs
pop fs
pop es
pop ds
{ Restore general-purpose registers }
popad
{ Return from interrupt }
iretd
end;
{ -----------------------------------------------------------------------
init
Override IDT gate 32 with our custom ISR. Must be called AFTER
isrmanager.init so that the default gate has been set up first.
----------------------------------------------------------------------- }
procedure init;
begin
idt.set_gate(32, uint32(@context_switch_isr), $08, ISR_RING_0);
tracer.push_trace('contextswitcher.init');
end;
end.
+2 -5
View File
@@ -22,7 +22,7 @@ unit cpu;
interface
uses
util, RTC;
util, RTC, stdio;
type
PCapabilities_Old = ^TCapabilities_Old;
@@ -113,12 +113,10 @@ var
CAP_OLD, CAP_NEW : uint32;
procedure init();
procedure Terminal_Command_CPU(Params : PParamList; stdin_buf, stdout_buf, stderr_buf : POutBuf);
implementation
uses
stdio;
procedure getCPUIdentifier;
var
id0, id1, id2 : uint32;
@@ -325,7 +323,6 @@ end;
procedure init();
begin
stdio.registerCommand('CPU', @Terminal_Command_CPU, 'CPU Info.');
CPUID.Capabilities0:= PCapabilities_Old(@CAP_OLD);
CPUID.Capabilities1:= PCapabilities_New(@CAP_NEW);
getCPUIdentifier;
+3 -1
View File
@@ -158,6 +158,9 @@ procedure init;
{ Unit Tests }
procedure UnitTest;
{ Terminal command }
procedure terminal_command_usb(params : PParamList; stdin_buf, stdout_buf, stderr_buf : POutBuf);
implementation
{ ========================= Globals ========================= }
@@ -1100,7 +1103,6 @@ begin
CompletionHookCount := 0;
for i := 0 to MAX_COMPLETION_HOOKS - 1 do
CompletionHooks[i] := nil;
stdio.registerCommand('USB', @terminal_command_usb, 'USB subsystem information.');
syslog.logln('USB Core', 'INIT END.');
pop_trace;
end;
File diff suppressed because it is too large Load Diff
+5 -4
View File
@@ -100,8 +100,8 @@ end;
procedure send(p_data : void; p_len : uint16);
begin
//push_trace('net.send');
//writeToLogLn('L1: net.send');
push_trace('net.send');
writeToLogLn('L1/NET: send');
if CBSend <> nil then CBSend(p_data, p_len);
pop_trace;
end;
@@ -111,8 +111,7 @@ var
context : PPacketContext;
begin
//push_trace('net.recv');
//writeToLogLn('L1: net.recv');
push_trace('net.recv');
context:= newPacketContext;
if CBNext <> nil then CBNext(p_data, p_len, context);
freePacketContext(context);
@@ -129,6 +128,7 @@ end;
procedure init;
begin
push_trace('net.init');
writeToLogLn('L1/NET: init');
//l2
eth2.register;
//l3
@@ -136,6 +136,7 @@ begin
ipv4.register;
//l4
icmp.register;
tcp.register;
udp.register;
//l5
dhcp.register;
+4 -1
View File
@@ -46,6 +46,7 @@ var
procedure registerTypePromisc(eType : uint16; RecvCB : TRecvCallback);
begin
push_trace('eth2.registerTypePromisc');
register;
if EthTypes[eType] = nil then EthTypes[eType]:= RecvCB;
Promisc[eType]:= true;
@@ -53,6 +54,7 @@ end;
procedure registerType(eType : uint16; RecvCB : TRecvCallback);
begin
push_trace('eth2.registerType');
register;
if EthTypes[eType] = nil then EthTypes[eType]:= RecvCB;
end;
@@ -93,7 +95,7 @@ var
buf : puint8;
begin
//writeToLogLn(' L2: eth2.recv');
push_trace('eth2.recv');
buf:= puint8(p_data);
Header:= PEthernetHeader(buf);
@@ -120,6 +122,7 @@ var
begin
push_trace('eth2.register');
if not Registered then begin
writeToLogLn(' L2/ETH: register');
for i:=0 to 65535 do begin
EthTypes[i]:= nil;
Promisc[i]:= false;
+12 -3
View File
@@ -25,7 +25,7 @@ uses
tracer, lmemorymanager,
util, lists,
net, nettypes, netutils,
eth2, ipv4;
eth2, ipv4, stdio;
type
PARPCacheRecord = ^TARPCacheRecord;
@@ -41,11 +41,12 @@ procedure sendGratuitous;
procedure sendRequest(ip : puint8);
procedure send(hType : uint16; pType : uint16; op : uint16; p_context : PPacketContext);
function resolveIP(ip : puint8) : puint8;
procedure terminal_command_arp(Params : PParamList; stdin_buf, stdout_buf, stderr_buf : POutBuf);
implementation
uses
stdio, strings;
strings;
var
Registered : Boolean = false;
@@ -96,6 +97,7 @@ var
hSize, pSize : uint8;
begin
push_trace('arp.send');
if p_context <> nil then begin
buf:= kalloc(sizeof(TARPHeader));
hdr:= PARPHeader(buf);
@@ -135,6 +137,8 @@ var
context : PPacketContext;
begin
push_trace('arp.sendGratuitous');
writeToLogLn(' L3/ARP: sendGratuitous');
context:= newPacketContext;
CopyIPv4(@getIPv4Config^.Address[0], @context^.IP.Destination[0]);
CopyIPv4(@getIPv4Config^.Address[0], @context^.IP.Source[0]);
@@ -150,6 +154,7 @@ var
CacheRecord : PARPCacheRecord;
begin
push_trace('arp.sendRequestGateway');
context:= newPacketContext;
CacheRecord:= findCacheRecordByIP(@getIPv4Config^.Gateway[0]);
if CacheRecord <> nil then begin
@@ -168,6 +173,8 @@ var
CacheRecord : PARPCacheRecord;
begin
push_trace('arp.sendRequest');
writeToLogLn(' L3/ARP: sendRequest');
context:= newPacketContext;
CopyIPv4(ip, @context^.IP.Destination[0]);
CopyIPv4(@getIPv4Config^.Address[0], @context^.IP.Source[0]);
@@ -184,6 +191,7 @@ var
CacheRecord : PARPCacheRecord;
begin
push_trace('arp.resolveIP');
CacheRecord:= findCacheRecordByIP(ip);
resolveIP:= nil;
if CacheRecord = nil then begin
@@ -203,6 +211,7 @@ var
context : PPacketContext;
begin
push_trace('arp.recv');
{ Get our converted Header }
Header:= PARPHeader(p_data);
AHeader.Hardware_Type:= (Header^.Hardware_Type_Hi SHL 8) + Header^.Hardware_Type_Lo;
@@ -298,9 +307,9 @@ procedure register;
begin
push_trace('arp.register');
if not Registered then begin
writeToLogLn(' L3/ARP: register');
Cache:= LL_New(sizeof(TARPCacheRecord));
eth2.registerTypePromisc($0806, @recv);
stdio.registerCommand('ARP', @terminal_command_arp, 'Get ARP Table.');
Registered:= true;
end;
pop_trace;
+10 -3
View File
@@ -26,17 +26,18 @@ uses
util, strings,
net, nettypes, netutils,
lists,
eth2;
eth2, stdio;
procedure send(p_data : void; p_len : uint16; p_context : PPacketContext);
procedure registerProtocol(Protocol_ID : uint8; recv_callback : TRecvCallback);
function getIPv4Config : PIPv4Configuration;
procedure register;
procedure terminal_command_ifconfig(params : PParamList; stdin_buf, stdout_buf, stderr_buf : POutBuf);
implementation
uses
arp, stdio;
arp;
var
Registered : Boolean = false;
@@ -46,7 +47,9 @@ var
function getIPv4Config : PIPv4Configuration;
begin
push_trace('ipv4.getIPv4Config');
getIPv4Config:= @Config;
pop_trace;
end;
procedure send(p_data : void; p_len : uint16; p_context : PPacketContext);
@@ -57,6 +60,7 @@ var
buffer : void;
begin
push_trace('ipv4.send');
inc(CurrentID);
Header.version:= 4;
Header.header_len:= 5;
@@ -84,6 +88,7 @@ begin
memcpy(uint32(p_data), uint32(Buffer) + (Header.header_len * 4), p_len);
eth2.send(Buffer, (Header.header_len * 4) + p_len, $0800, p_context);
kfree(Buffer);
pop_trace;
end;
procedure recv(p_data : void; p_len : uint16; p_context : PPacketContext);
@@ -95,6 +100,7 @@ var
len : uint16;
begin
push_trace('ipv4.recv');
Header:= PIPV4Header(p_data);
AHeader.version:= Header^.version;
AHeader.header_len:= Header^.header_len;
@@ -195,6 +201,7 @@ var
begin
push_trace('ipv4.register');
if not Registered then begin
writeToLogLn(' L3/IPv4: register');
for i:=0 to 255 do begin
Protocols[i]:= nil;
end;
@@ -205,7 +212,6 @@ begin
end;
Config.UP:= false;
eth2.registerType($0800, @recv);
stdio.registerCommand('IFCONFIG', @terminal_command_ifconfig, 'Configure Network Settings.');
Registered:= true;
end;
pop_trace;
@@ -213,6 +219,7 @@ end;
procedure registerProtocol(Protocol_ID : uint8; recv_callback : TRecvCallback);
begin
push_trace('ipv4.registerProtocol');
register;
if Protocols[Protocol_ID] = nil then Protocols[Protocol_ID]:= recv_callback;
pop_trace;
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+8 -1
View File
@@ -25,7 +25,7 @@ uses
lmemorymanager,
nettypes, netutils,
ipv4, net,
util;
tracer, util;
procedure register();
function bind(bindContext : PUDPBindContext) : TUDPError;
@@ -71,6 +71,7 @@ begin
nullend:= true;
end;
pseudoBuffer:= kalloc(sizeof(TUDPPseudoHeader) + pseudoSize);
push_trace('udp.CalculateChecksum');
pseudoBuffer8:= puint8(pseudoBuffer);
pseudoBuffer16:= puint16(pseudoBuffer);
pseudoBuffer32:= puint32(pseudoBuffer);
@@ -118,6 +119,7 @@ var
begin
push_trace('udp.send');
if udpContext <> nil then begin
size:= p_len + sizeof(TUDPHeader);
buffer:= kalloc(size);
@@ -152,6 +154,7 @@ var
context : PUDPBindContext;
begin
push_trace('udp.bind');
result:= tueGenericError;
if bindContext <> nil then begin
if Ports[bindContext^.port] = nil then begin
@@ -174,6 +177,7 @@ var
context : PUDPBindContext;
begin
push_trace('udp.unbind');
result:= tueGenericError;
if bindContext <> nil then begin
context:= Ports[bindContext^.port];
@@ -203,6 +207,7 @@ var
size : uint16;
begin
push_trace('udp.ProcessPacket');
header:= PUDPHeader(p_data);
if Ports[switchendian16(header^.DstPort)] <> nil then begin
context:= PUDPPacketContext(kalloc(sizeof(TUDPPacketContext)));
@@ -245,6 +250,8 @@ var
Checksum : uint32;
begin
push_trace('udp.register');
writeToLogLn(' L4/UDP: register');
for i:=0 to 65535 do begin
Ports[i]:= nil;
end;
+6 -3
View File
@@ -415,7 +415,7 @@ end;
procedure processPacket_NAK(Header : PDHCPHeader; Options : PDHCPOptions);
begin
syslog.logln('DHCP', 'Process NAK.');
writeToLogLn(' L5/DHCP: Process NAK.');
{ Server provided a NAK, NULL configuration ready for next DISCOVER/Request }
nullConfiguration();
end;
@@ -429,7 +429,7 @@ var
cfgopt : void;
begin
syslog.logln('DHCP', 'Process ACK.');
writeToLogLn(' L5/DHCP: Process ACK.');
getIPv4Config^.UP:= false;
//Copy new address
@@ -484,7 +484,7 @@ Var
begin
syslog.logln('DHCP', 'Process OFFER.');
writeToLogLn(' L5/DHCP: Process OFFER.');
{ Check the Transaction ID matches our stored ID, discard if not. }
if Header^.Transaction_ID = Configuration^.Transaction then begin
syslog.logln('DHCP', 'XID Match');
@@ -566,6 +566,7 @@ var
begin
tracer.push_trace('dhcp.processPacket.enter');
writeToLogLn(' L5/DHCP: processPacket');
syslog.logln('DHCP','processPacket');
{ Give access to header values & process to correct endianness. }
@@ -636,6 +637,7 @@ var
begin
tracer.push_trace('dhcp.DHCPDiscover.begin');
writeToLogLn(' L5/DHCP: DHCPDiscover');
{ Ensure we have a socket bound. }
if Socket <> nil then begin
{ Clear any current configuration }
@@ -711,6 +713,7 @@ var
begin
tracer.push_trace('dhcp.register');
writeToLogLn(' L5/DHCP: register');
syslog.logln('DHCP', 'Register begin.');
{ Kalloc our Configuration Data }
+1 -1
View File
@@ -112,6 +112,7 @@ function get_device_list() : PLinkedListBase;
procedure register_filesystem(filesystem : PFilesystem);
procedure register_volume(device : PStorage_Device; volume : PStorage_Volume);
procedure disk_command(params : PParamList; stdin_buf, stdout_buf, stderr_buf : POutBuf);
//function writeNewFile(fileName : pchar; extension : pchar; buffer : puint32; size : uint32) : uint32;
//function readFile(fileName : pchar; extension : pchar; buffer : puint32; byteCount : puint32) : puint32;
@@ -231,7 +232,6 @@ begin
setworkingdirectory('.');
storageDevices:= ll_new(sizeof(TStorage_Device));
fileSystems:= ll_New(sizeof(TFilesystem));
stdio.registerCommand('DISK', @disk_command, 'Disk utility');
pop_trace();
end;
+67 -5
View File
@@ -104,6 +104,10 @@ function GetDirectories(Handle : uint32; Path : pchar) : PHashMap;
function PathValid(Path : pchar) : TIsPathValid;
function changeDirectory(Path : pchar) : TIsPathValid;
function getWorkingDirectory : pchar;
function makeAbsolutePathFrom(Path : pchar; BaseDir : pchar) : pchar;
function resolvePathFrom(Path : pchar; BaseDir : pchar) : TIsPathValid;
function GetDirectoryListingFrom(Path : pchar; BaseDir : pchar) : PHashMap;
function changeDirectoryFrom(Path : pchar; BaseDir : pchar; var NewDir : pchar) : TIsPathValid;
//VFS Functions
function newVirtualDirectory(Path : pchar) : TError;
@@ -608,6 +612,67 @@ begin
tracer.push_trace('vfs.getWorkingDirectory.exit');
end;
function makeAbsolutePathFrom(Path : pchar; BaseDir : pchar) : pchar;
var
AbsPath : pchar;
TempPath : pchar;
begin
if Path[0] = '/' then
AbsPath := stringCopy(Path)
else begin
if BaseDir[StringSize(BaseDir)-1] <> '/' then
TempPath := StringConcat(BaseDir, '/')
else
TempPath := stringCopy(BaseDir);
AbsPath := StringConcat(TempPath, Path);
kfree(void(TempPath));
end;
makeAbsolutePathFrom := AbsPath;
end;
function resolvePathFrom(Path : pchar; BaseDir : pchar) : TIsPathValid;
var
TempPath : pchar;
AbsPath : pchar;
begin
TempPath := makeAbsolutePathFrom(Path, BaseDir);
AbsPath := evaluatePath(TempPath);
kfree(void(TempPath));
resolvePathFrom := PathValid(AbsPath);
kfree(void(AbsPath));
end;
function GetDirectoryListingFrom(Path : pchar; BaseDir : pchar) : PHashMap;
var
TempPath : pchar;
AbsPath : pchar;
begin
TempPath := makeAbsolutePathFrom(Path, BaseDir);
AbsPath := evaluatePath(TempPath);
kfree(void(TempPath));
GetDirectoryListingFrom := GetDirectoryListing(AbsPath);
kfree(void(AbsPath));
end;
function changeDirectoryFrom(Path : pchar; BaseDir : pchar; var NewDir : pchar) : TIsPathValid;
var
TempPath : pchar;
AbsPath : pchar;
Validity : TIsPathValid;
begin
TempPath := makeAbsolutePathFrom(Path, BaseDir);
AbsPath := evaluatePath(TempPath);
kfree(void(TempPath));
Validity := PathValid(AbsPath);
if Validity = pvDirectory then
NewDir := AbsPath
else begin
NewDir := nil;
kfree(void(AbsPath));
end;
changeDirectoryFrom := Validity;
end;
{ Terminal Commands }
procedure VFS_COMMAND_PUSHD(params : PParamList; stdin_buf, stdout_buf, stderr_buf : POutBuf);
@@ -746,11 +811,8 @@ begin
//outputln('VFS', makeRelative('/test/mydisk/mything', '/test/mydisk'));
//while true do begin end;
{ Register Terminal Commands }
stdio.registerCommand('LS', @VFS_COMMAND_LS, 'List directory contents.');
stdio.registerCommand('CD', @VFS_COMMAND_CD, 'Set working directory.');
stdio.registerCommand('PUSHD', @VFS_COMMAND_PUSHD, 'Push the working directory.');
stdio.registerCommand('POPD', @VFS_COMMAND_POPD, 'Pop the working directory.');
{ LS, CD, PUSHD, POPD are now handled as per-terminal builtins
in vterminal.pas so each terminal has its own working directory. }
//ht:= PHashMap(Root^.Reference);
//hashmap.add(ht, 'VDirectory', void(newDummyObject(otVDIRECTORY)));
+2
View File
@@ -21,6 +21,7 @@ uses
uidebug,
lvgl,
video,
windows,
syslog;
const
@@ -35,6 +36,7 @@ begin
TickCounter := TickCounter + 1;
if TickCounter >= TICKS_PER_FRAME then begin
TickCounter := 0;
windows.reapOrphanedWindows;
desktop.update;
uidebug.update;
lvgl_handler;
+11
View File
@@ -467,6 +467,7 @@ const
LV_KEY_PREV = 11;
LV_KEY_HOME = 2;
LV_KEY_END = 3;
LV_KEY_CTRLC = 128; { Ctrl+C — terminal interrupt }
{ Arc mode }
LV_ARC_MODE_NORMAL = 0;
@@ -1861,6 +1862,16 @@ begin
exit;
end;
{ Ctrl+C — inject custom key code so focused terminal can handle it }
if key_info.is_down_code and key_info.CTRL_DOWN and (key_info.key_code = ord('c')) then begin
next_head := (kb_head + 1) mod KB_BUF_SIZE;
if next_head <> kb_tail then begin
kb_buf[kb_head] := LV_KEY_CTRLC;
kb_head := next_head;
end;
exit;
end;
{ Map Asuro key codes to LVGL key codes }
case key_info.key_code of
$1B: k := LV_KEY_ESC;
+45 -1
View File
@@ -11,7 +11,7 @@ unit windows;
interface
uses
lvgl, mouse, serial, tracer;
lvgl, mouse, serial, tracer, processmanager, proctypes;
const
MAX_WINDOWS = 16;
@@ -55,6 +55,7 @@ type
on_close : TWinCloseCallback;
on_resize : TWinResizeCallback;
cursor_obj : Plv_obj; { cursor to keep on top }
owner_pid : uint32; { owning process PID; 0 = unowned }
end;
{ Create a new window. Returns window ID (0 = failure). }
@@ -81,6 +82,15 @@ function getWindowCount: uint32;
{ Set a callback to be notified when a window is resized. }
procedure setWindowResizeCallback(win_id: uint32; cb: TWinResizeCallback);
{ Assign an owning process to a window.
When reapOrphanedWindows detects the process has died, the window
is automatically closed via its on_close callback. }
procedure setWindowOwner(win_id: uint32; pid: uint32);
{ Check all windows for dead owner processes and close them.
Called once per frame from graphicsrefresh. }
procedure reapOrphanedWindows;
implementation
var
@@ -641,6 +651,7 @@ begin
wins[id].on_close := closeCB;
wins[id].on_resize := nil;
wins[id].cursor_obj := cursor;
wins[id].owner_pid := 0;
{ Bring to front }
bringToFront(id);
@@ -698,6 +709,7 @@ begin
wins[win_id].on_close := nil;
wins[win_id].on_resize := nil;
wins[win_id].cursor_obj := nil;
wins[win_id].owner_pid := 0;
tracer.pop_trace;
end;
@@ -746,4 +758,36 @@ begin
wins[win_id].on_resize := cb;
end;
{ ============================================================
Public: set window owner PID
============================================================ }
procedure setWindowOwner(win_id: uint32; pid: uint32);
begin
if (win_id < 1) or (win_id > MAX_WINDOWS) then exit;
if wins[win_id].state = wsNone then exit;
wins[win_id].owner_pid := pid;
end;
{ ============================================================
Public: reap windows whose owning process has died
============================================================ }
procedure reapOrphanedWindows;
var
i : uint32;
ctx : PProcessContext;
begin
for i := 1 to MAX_WINDOWS do begin
if wins[i].state = wsNone then continue;
if wins[i].owner_pid = 0 then continue;
ctx := processmanager.findByID(wins[i].owner_pid);
if (ctx = nil) or (ctx^.State = psFinished) or (ctx^.State = psError) then begin
{ Owner is dead — trigger close callback or destroy directly }
if wins[i].on_close <> nil then
wins[i].on_close(i)
else
destroyWindow(i);
end;
end;
end;
end.
+2 -4
View File
@@ -72,6 +72,8 @@ procedure register_driver(Driver_Name : PChar; DeviceID : PDeviceIdentifier; Loa
procedure register_driver_ex(Driver_Name : PChar; DeviceID : PDeviceIdentifier; Load_Callback : TDriverLoadCallback; force_load : boolean);
procedure register_device(Device_Name : PChar; DeviceID : PDeviceIdentifier; ptr : void);
procedure terminal_command_dev(Params : PParamList; stdin_buf, stdout_buf, stderr_buf : POutBuf);
var
Root : PDriverRegistration = nil;
Dev : PDeviceRegistration = nil;
@@ -328,10 +330,6 @@ end;
procedure init;
begin
push_trace('driver_management.init');
stdio.registerCommand('DEV', @terminal_command_dev, 'Driver Management Interface.');
//stdio.registerCommand('DRIVERSEX', @terminal_command_driversex, 'List all available drivers.');
//stdio.registerCommand('DRIVERS', @terminal_command_drivers, 'List loaded drivers.');
//stdio.registerCommand('DEVICES', @terminal_command_devices, 'List devices.');
pop_trace;
end;

Some files were not shown because too many files have changed in this diff Show More