Compare commits
17
Commits
720ba46630
...
64bit
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e69b134bff | ||
|
|
a6a55153af | ||
|
|
e462165049 | ||
|
|
b71e6d67b4 | ||
|
|
465cf1deca | ||
|
|
f8911ccdec | ||
|
|
a27d9cb39d | ||
|
|
7a6be7f66e | ||
|
|
6a1eb5e2ac | ||
|
|
e8e4061564 | ||
|
|
10691a9e03 | ||
|
|
cebad0b583 | ||
|
|
53cc758e60 | ||
|
|
6c7619bc2c | ||
|
|
d318eca262 | ||
|
|
c28b9dd77f | ||
|
|
c0c56a9c84 |
No files matched your search
+4
-1
@@ -1,6 +1,8 @@
|
||||
/lib/*.ppu
|
||||
/lib/*.a
|
||||
/lib/*.o
|
||||
/lib/x86_64/
|
||||
/bin/x86_64/
|
||||
/release/*.svg
|
||||
/release/*.iso
|
||||
/bin/*.bin
|
||||
@@ -15,8 +17,9 @@ localenv.json
|
||||
dockerout.txt
|
||||
AGENTS.md
|
||||
lessons_learnt.md
|
||||
/plan.md
|
||||
*.log
|
||||
wasuro
|
||||
src/core/core.version.pas
|
||||
site/*
|
||||
!site/.gitkeep
|
||||
!site/.gitkeep
|
||||
+3
-3
@@ -6,7 +6,7 @@ ENV DEBIAN_FRONTEND=noninteractive
|
||||
RUN dpkg --add-architecture i386
|
||||
RUN apt-get update && apt-get install -y \
|
||||
curl dos2unix wget git make nasm binutils xorriso grub-pc-bin gcc gcc-multilib \
|
||||
python3 python3-pip python3-pil && \
|
||||
python3 python3-pip python3-pil fp-compiler && \
|
||||
apt-get clean my room
|
||||
|
||||
RUN pip3 install --no-cache-dir --break-system-packages "mkdocs>=1.6,<2" mkdocs-material
|
||||
@@ -20,6 +20,6 @@ RUN curl -sL https://sourceforge.net/projects/freepascal/files/Linux/$FPC_VERSIO
|
||||
ADD https://raw.githubusercontent.com/fsaintjacques/semver-tool/master/src/semver /usr/bin/semver
|
||||
RUN chmod +x /usr/bin/semver
|
||||
WORKDIR /code
|
||||
RUN find . -type f -print0 | xargs -0 dos2unix
|
||||
# Sources are mounted at runtime; the CMD below normalizes build scripts.
|
||||
ENTRYPOINT ["/bin/bash", "-c"]
|
||||
CMD ["find toolchain -name '*.sh' -exec dos2unix {} + 2>/dev/null; find toolchain -name '*.sh' -exec chmod +x {} +; bash toolchain/compile.sh"]
|
||||
CMD ["find toolchain -name '*.sh' -exec dos2unix {} + 2>/dev/null; find toolchain -name '*.sh' -exec chmod +x {} +; bash toolchain/compile.sh"]
|
||||
+10
-10
@@ -22,12 +22,12 @@ type
|
||||
THeapPageHeader = memory.heap.THeapPageHeader;
|
||||
|
||||
procedure init;
|
||||
function kalloc(size : uint32) : void;
|
||||
function klalloc(size : uint32) : void;
|
||||
procedure klfree(address : uint32);
|
||||
function kpalloc(address : uint32) : void;
|
||||
function kalloc(size : SizeUInt) : void;
|
||||
function klalloc(size : SizeUInt) : void;
|
||||
procedure klfree(address : PtrUInt);
|
||||
function kpalloc(address : PtrUInt) : void;
|
||||
procedure kfree(area : void);
|
||||
function lmm_total_free : uint32;
|
||||
function lmm_total_free : SizeUInt;
|
||||
function lmm_page_count : uint32;
|
||||
|
||||
implementation
|
||||
@@ -37,22 +37,22 @@ begin
|
||||
memory.heap.init;
|
||||
end;
|
||||
|
||||
function kalloc(size : uint32) : void; inline;
|
||||
function kalloc(size : SizeUInt) : void; inline;
|
||||
begin
|
||||
kalloc := memory.heap.kalloc(size);
|
||||
end;
|
||||
|
||||
function klalloc(size : uint32) : void; inline;
|
||||
function klalloc(size : SizeUInt) : void; inline;
|
||||
begin
|
||||
klalloc := memory.heap.klalloc(size);
|
||||
end;
|
||||
|
||||
procedure klfree(address : uint32); inline;
|
||||
procedure klfree(address : PtrUInt); inline;
|
||||
begin
|
||||
memory.heap.klfree(address);
|
||||
end;
|
||||
|
||||
function kpalloc(address : uint32) : void; inline;
|
||||
function kpalloc(address : PtrUInt) : void; inline;
|
||||
begin
|
||||
kpalloc := memory.heap.kpalloc(address);
|
||||
end;
|
||||
@@ -62,7 +62,7 @@ begin
|
||||
memory.heap.kfree(area);
|
||||
end;
|
||||
|
||||
function lmm_total_free : uint32; inline;
|
||||
function lmm_total_free : SizeUInt; inline;
|
||||
begin
|
||||
lmm_total_free := memory.heap.lmm_total_free;
|
||||
end;
|
||||
|
||||
@@ -205,7 +205,7 @@ Key constants:
|
||||
- `DATA_OFFSET = $10000` — data area starts at 64 KB into each page
|
||||
- `LARGE_ALLOC_MAGIC = $FFFFFFFE` — sentinel for klalloc'd multi-page allocations
|
||||
|
||||
Interrupt safety: `pushfd; cli; pop saved_flags` (stack-balanced) + `restore_if(saved_flags)`
|
||||
Interrupt safety: `pushfd; cli; pop saved_flags` (stack-balanced) + `arch.platform.cpu.unlock(saved_flags)`
|
||||
inline procedure that only restores IF via `sti`, avoiding dangerous EFLAGS restoration
|
||||
(IOPL, NT, VM, AC bits that caused Bad-TSS on IRET).
|
||||
|
||||
@@ -256,7 +256,7 @@ list, fixes Search_Page, calls `free_page_at_address`). Skips Root_Page.
|
||||
|
||||
| Bug | Root Cause | Fix |
|
||||
|-----|-----------|-----|
|
||||
| Bad TSS exception during network processing | `pushfd`/`popfd` across separate asm blocks: FPC doesn't track ESP changes in asm, causing EFLAGS corruption (NT=1, IOPL wrong) → Bad TSS on IRET | Stack-balanced `pushfd; cli; pop local_var` + `restore_if()` that only does `sti` if IF was set |
|
||||
| Bad TSS exception during network processing | `pushfd`/`popfd` across separate asm blocks: FPC doesn't track ESP changes in asm, causing EFLAGS corruption (NT=1, IOPL wrong) → Bad TSS on IRET | Stack-balanced `pushfd; cli; pop local_var` + `arch.platform.cpu.unlock()` that only does `sti` if IF was set |
|
||||
| GPF from SSE MOVAPS in doublebuffer flush | `SIZE_PREFIX=4`→8 gave 8-byte alignment; `MOVAPS` needs 16-byte. `klalloc` returned `page+8` (not 16-aligned) | `SIZE_PREFIX=16` (4B size + 12B pad), klalloc header expanded to 16 bytes |
|
||||
| Pages never freed (historic) | `free_page` extracted wrong block index from PDE Address field | Fixed extraction to `Address SHR 10` — page freeing works for the first time |
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,49 +1,85 @@
|
||||
# driver.storage.ctl.usb
|
||||
<!--
|
||||
Copyright 2026 Aaron Hance
|
||||
Author: Aaron Hance <[email protected]>
|
||||
|
||||
USB Mass Storage Class driver stub.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
## Overview
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
This unit registers a USB class driver with the driver manager (`driver.mgr`) to claim USB Mass Storage Class interfaces (class `$08`, subclass `$06` SCSI, protocol `$50` Bulk-Only). When the USB stack enumerates a matching interface, the `load` callback is invoked. Currently the callback only logs a detection message; no I/O infrastructure is established.
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
Full Bulk-Only Transport (BOT) support — including Max LUN query, endpoint setup, CBW/CSW command exchange, and `driver.storage.mgr` device registration — is planned but not yet implemented.
|
||||
# USB mass storage
|
||||
|
||||
## Boot Registration
|
||||
`driver.storage.ctl.usb` implements SCSI transparent commands over USB Mass
|
||||
Storage Bulk-Only Transport (interface class/subclass/protocol `08/06/50`).
|
||||
|
||||
Registered with `boot.mgr` as `driver.storage.ctl.usb` at the `device` barrier. The barrier order places `device` after `bus`, ensuring `driver.bus.usb.core.init` has run before the storage class driver registers with the driver manager.
|
||||
It probes INQUIRY, TEST UNIT READY and READ CAPACITY(10), registers LUN 0 with
|
||||
the storage manager, and exposes READ(10), WRITE(10), REQUEST SENSE and
|
||||
SYNCHRONIZE CACHE(10). Existing partition discovery and filesystem mounting
|
||||
apply to the resulting USB disk. Writes complete only after cache synchronization.
|
||||
|
||||
## Dependencies
|
||||
## Execution and ownership
|
||||
|
||||
- `boot.mgr`
|
||||
An attachment task probes and registers each disk after scheduling starts; boot
|
||||
initialization never waits on a worker that cannot run yet.
|
||||
|
||||
- `driver.mgr`
|
||||
- `memory.heap`
|
||||
- `driver.storage.types`
|
||||
- `io.syslog`
|
||||
- `debug.tracer`
|
||||
- `driver.bus.usb.core`
|
||||
- `driver.bus.usb.types`
|
||||
- `core.util`, `arch.x86.util`
|
||||
Storage dispatch only publishes a request. One persistent `usb.storage` worker
|
||||
performs I/O in task context, with one command active per device and a reusable,
|
||||
page-aligned 4 KiB bounce buffer. Caller buffers are never submitted for DMA.
|
||||
Commands are split at the bounce-buffer boundary; all LBA/count and buffer-end
|
||||
arithmetic is checked before submission. CBW/CSW wire sizes, tags, status,
|
||||
residue, and actual transfer lengths are validated.
|
||||
|
||||
## Constants
|
||||
OHCI batches bulk data into spans of at most 4 KiB per transfer descriptor,
|
||||
using the endpoint's hardware toggle carry across packets. A 4 KiB full-speed
|
||||
read uses one data descriptor instead of 64. Short packets still halt the chain
|
||||
and report the actual byte count; interrupt endpoint packet sizing is unchanged.
|
||||
|
||||
| Constant | Value | Description |
|
||||
|---|---|---|
|
||||
| `USB_CLASS_MASS_STORAGE` | `$08` | USB interface class for mass storage |
|
||||
| `USB_SC_SCSI` | `$06` | SCSI transparent command set subclass |
|
||||
| `USB_PROTO_BBB` | `$50` | Bulk-Only (BOT) transport protocol |
|
||||
The worker performs reset recovery (class reset, clear bulk-IN halt, clear
|
||||
bulk-OUT halt) after malformed status or phase errors. Failed SCSI commands
|
||||
request sense and return storage errors, including write protection.
|
||||
|
||||
## Functions and Procedures
|
||||
On disconnect the disk is marked removed immediately. Accepted requests are
|
||||
completed with errors, and idle volumes are invalidated/unmounted by the worker;
|
||||
busy volumes are retried. Storage-manager records remain stable tombstones.
|
||||
Class-driver buffers and context are freed after pending hardware work drains.
|
||||
|
||||
### init
|
||||
Host controllers currently have no cancellation API. A timed-out transfer is
|
||||
therefore quarantined with its private device snapshot and DMA memory. No further
|
||||
commands are issued to that device. If hardware never completes, those allocations
|
||||
remain retained until reboot; freeing them would permit DMA into reused memory.
|
||||
The timeout uses the PIT's actual frequency and a bounded polling fallback.
|
||||
|
||||
```pascal
|
||||
procedure init;
|
||||
```
|
||||
## Supported scope
|
||||
|
||||
Constructs a `TDeviceIdentifier` matching any USB device with `bInterfaceClass = $08`, `bInterfaceSubClass = $06`, `bInterfaceProtocol = $50`, and registers the `load` callback with `driver.mgr`.
|
||||
- LUN 0 on a single-interface device with one bulk-IN and one bulk-OUT endpoint.
|
||||
- Direct-access disks with power-of-two sectors from 512 through 4096 bytes.
|
||||
- Capacity representable by the existing 32-bit storage-sector API; the
|
||||
READ CAPACITY(16) sentinel is rejected.
|
||||
- OHCI, EHCI and xHCI bulk transfers. OHCI/EHCI report actual data lengths and
|
||||
terminate bulk reads on short packets.
|
||||
|
||||
## Notes
|
||||
UAS, additional LUNs, composite/alternate-setting interfaces, UHCI storage,
|
||||
optical devices, and media replacement without USB reconnect are not supported.
|
||||
The current xHCI driver lacks endpoint-ring reset support: a halted bulk endpoint
|
||||
fails the device closed rather than attempting an unsafe ring reuse.
|
||||
|
||||
- The `load` callback currently returns true unconditionally after logging a detection message.
|
||||
- Once full BOT support is implemented, `load` should query the Max LUN, allocate endpoint structures, and call `driver.storage.mgr.register_device` for each logical unit.
|
||||
## Validation
|
||||
|
||||
`UnitTest` is called by the boot test suite and is available as `USBMSCTEST`.
|
||||
Tests use a memory-only mock host controller: wire layout, byte order, capacity
|
||||
limits, reads, writes, sense errors, short transfers, status stalls, reset ordering,
|
||||
and request bounds. They perform no disk I/O.
|
||||
|
||||
For hardware/VM checks, boot with a disposable USB disk, confirm `USBMSC` discovery
|
||||
and filesystem mounting, test file read/write/read-back, then unplug while idle
|
||||
and during I/O. Do not run destructive disk tests against a disk containing data.
|
||||
|
||||
Protocol: [USB-IF Bulk-Only Transport 1.0](https://www.usb.org/sites/default/files/usbmassbulk_10.pdf).
|
||||
@@ -1,3 +1,20 @@
|
||||
<!--
|
||||
Copyright 2026 Aaron Hance
|
||||
Author: Aaron Hance <[email protected]>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
# driver.storage.mgr
|
||||
|
||||
Physical storage device registry and I/O dispatch manager.
|
||||
@@ -14,7 +31,7 @@ The I/O model operates as follows:
|
||||
- `storage_read` / `storage_write` are convenience wrappers that build a stack-local `TIORequest` and call `submit_io_wait`.
|
||||
- `storage_read_async` / `storage_write_async` build and submit a request with a caller-supplied callback, returning immediately.
|
||||
|
||||
Legacy `storage_read_legacy` / `storage_write_legacy` procedure wrappers are retained for callers not yet migrated to the function-returning API.
|
||||
Blocking callers use `storage_read` / `storage_write` and check the returned `TError`.
|
||||
|
||||
## Dependencies
|
||||
|
||||
@@ -205,15 +222,6 @@ function storage_write_async(device : PStorage_Device; addr : uint32; sectors :
|
||||
|
||||
Non-blocking write. Analogous to `storage_read_async`.
|
||||
|
||||
### storage_read_legacy / storage_write_legacy
|
||||
|
||||
```pascal
|
||||
procedure storage_read_legacy(device : PStorage_Device; addr : uint32; sectors : uint32; buffer : puint32);
|
||||
procedure storage_write_legacy(device : PStorage_Device; addr : uint32; sectors : uint32; buffer : puint32);
|
||||
```
|
||||
|
||||
Drop-in procedure replacements for callers using the old void-returning API. Forward to `storage_read` / `storage_write` and discard the error code. Marked for removal once all callers are migrated.
|
||||
|
||||
## Notes
|
||||
|
||||
- `dispatch_next` is an internal procedure called with interrupts disabled. It dequeues the head of the CFIFO, allocates a heap copy via `ioreq_copy` (for ISR safety), and invokes the appropriate `dispatchRead` or `dispatchWrite` on the device. If neither dispatch pointer is set, the request is failed with `eDeviceNotFound`.
|
||||
|
||||
@@ -19,7 +19,7 @@ Every allocation is preceded by a 16-byte prefix: 4 bytes for the unit count, 12
|
||||
|
||||
Allocations larger than a single heap page's capacity are handled by `klalloc`, which maps contiguous virtual pages and stores a magic sentinel (`$FFFFFFFE`) in the header so `kfree` can identify them and call `klfree` instead of the normal bitmap path.
|
||||
|
||||
`kalloc` and `kfree` disable interrupts for the duration of their critical sections using a stack-balanced `pushfd`/`cli`/`pop` sequence and restore the interrupt flag via `restore_if` on all exit paths.
|
||||
`kalloc` and `kfree` disable interrupts for the duration of their critical sections using a stack-balanced `pushfd`/`cli`/`pop` sequence and restore the interrupt flag via `arch.platform.cpu.unlock` on all exit paths.
|
||||
|
||||
## Dependencies
|
||||
|
||||
@@ -132,7 +132,7 @@ Returns the number of heap pages currently in the linked list.
|
||||
|
||||
## Notes
|
||||
|
||||
The `restore_if` helper checks bit 9 (IF) of the saved EFLAGS word and issues `STI` only if interrupts were enabled on entry. It uses `STI` rather than `POPFD` to avoid restoring potentially dangerous EFLAGS bits (IOPL, NT, VM, AC) that could trigger a General Protection Fault or Bad-TSS on the next `IRET`.
|
||||
The `arch.platform.cpu.unlock` helper checks bit 9 (IF) of the saved EFLAGS word and issues `STI` only if interrupts were enabled on entry. It uses `STI` rather than `POPFD` to avoid restoring potentially dangerous EFLAGS bits (IOPL, NT, VM, AC) that could trigger a General Protection Fault or Bad-TSS on the next `IRET`.
|
||||
|
||||
When `DEBUG_LMM` is defined, `kalloc` allocates one additional unit and writes `GUARD_MAGIC` at the end of the allocation. `kfree` verifies this sentinel before freeing; a mismatch triggers a GPF with a syslog error, catching buffer overruns at free time.
|
||||
|
||||
|
||||
+4
-1
@@ -1,5 +1,8 @@
|
||||
services:
|
||||
builder:
|
||||
build: .
|
||||
environment:
|
||||
ASURO_ARCH: ${ASURO_ARCH:-x86}
|
||||
ASURO_BOOT_TEST: ${ASURO_BOOT_TEST:-none}
|
||||
volumes:
|
||||
- .:/code
|
||||
- .:/code
|
||||
@@ -295,6 +295,7 @@ nav:
|
||||
|
||||
- Planning:
|
||||
- Architecture: planning/architecture.md
|
||||
- x86-64 Migration: planning/x86_64.md
|
||||
- USB: planning/USB.md
|
||||
- XHCI: planning/XHCI.md
|
||||
- FlatFS: planning/flatfs.md
|
||||
|
||||
@@ -22,7 +22,7 @@ unit app.base64;
|
||||
interface
|
||||
|
||||
uses
|
||||
io.stdio, core.util, arch.x86.util, core.strings, debug.tracer, core.enc.base64, memory.heap;
|
||||
io.stdio, core.util, arch.platform.cpu, core.strings, debug.tracer, core.enc.base64, memory.heap;
|
||||
|
||||
procedure init();
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ unit app.dhclient;
|
||||
interface
|
||||
|
||||
uses
|
||||
io.stdio, core.util, arch.x86.util, core.strings, debug.tracer, driver.net.proto.dhcp;
|
||||
io.stdio, core.util, arch.platform.cpu, core.strings, debug.tracer, driver.net.proto.dhcp;
|
||||
|
||||
procedure init();
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ uses
|
||||
core.strings,
|
||||
io.stdio,
|
||||
debug.tracer,
|
||||
core.util, arch.x86.util,
|
||||
core.util, arch.platform.cpu,
|
||||
driver.storage.vol.mgr;
|
||||
|
||||
var
|
||||
@@ -254,7 +254,7 @@ begin
|
||||
{ Allocate a zero buffer - 64 sectors at a time }
|
||||
bufSects := 64;
|
||||
buf := puint32(kalloc(bufSects * device^.sectorSize));
|
||||
memset(uint32(buf), 0, bufSects * device^.sectorSize);
|
||||
memset(PtrUInt(buf), 0, bufSects * device^.sectorSize);
|
||||
|
||||
print('Wiping device ');
|
||||
printint(idx);
|
||||
|
||||
+25
-22
@@ -34,7 +34,7 @@ uses
|
||||
driver.video,
|
||||
driver.storage.vol.mgr,
|
||||
driver.video.windows,
|
||||
core.util, arch.x86.util;
|
||||
core.util, arch.platform.cpu;
|
||||
|
||||
const
|
||||
WIN_W = 740;
|
||||
@@ -129,9 +129,9 @@ begin
|
||||
item := PUIText(kalloc(sizeof(TUIText)+n+m+1));
|
||||
if item = nil then exit;
|
||||
item^.Next := TextTemps; TextTemps := item;
|
||||
dest := pchar(uint32(item)+sizeof(TUIText));
|
||||
if n > 0 then memcpy(uint32(a), uint32(dest), n);
|
||||
if m > 0 then memcpy(uint32(b), uint32(dest)+n, m);
|
||||
dest := pchar(PtrUInt(item)+sizeof(TUIText));
|
||||
if n > 0 then memcpy(PtrUInt(a), PtrUInt(dest), n);
|
||||
if m > 0 then memcpy(PtrUInt(b), PtrUInt(dest)+n, m);
|
||||
dest[n+m] := #0; uiConcat := dest;
|
||||
end;
|
||||
|
||||
@@ -606,7 +606,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
memset(uint32(@part), 0, sizeof(TPartition_table));
|
||||
memset(PtrUInt(@part), 0, sizeof(TPartition_table));
|
||||
driver.storage.vol.mbr.setup_partition(@part, lba, sectors);
|
||||
cbCtx := begin_partition_ui(1);
|
||||
if cbCtx = nil then exit;
|
||||
@@ -702,18 +702,19 @@ end;
|
||||
procedure operation_done(error : TError; userdata : pointer);
|
||||
var
|
||||
ctx : PFmtUICallbackCtx;
|
||||
flags : uint32;
|
||||
flags : PtrUInt;
|
||||
begin
|
||||
ctx := PFmtUICallbackCtx(userdata);
|
||||
if ctx <> nil then begin
|
||||
asm pushfd; cli; pop flags end;
|
||||
flags := arch.platform.cpu.lock;
|
||||
if ctx^.SessionID = ui_session_id then begin
|
||||
fmt_done_error := error;
|
||||
fmt_done_vol_idx := ctx^.VolumeIdx;
|
||||
done_kind := ctx^.Kind; done_device := ctx^.DeviceIdx;
|
||||
done_kind := ctx^.Kind;
|
||||
done_device := ctx^.DeviceIdx;
|
||||
puint32(@fmt_done_flag)^ := 1;
|
||||
end;
|
||||
if (flags and $200) <> 0 then asm sti end;
|
||||
arch.platform.cpu.unlock(flags);
|
||||
kfree(void(ctx));
|
||||
end;
|
||||
end;
|
||||
@@ -824,7 +825,7 @@ begin
|
||||
fs := driver.storage.fs.mgr.get_filesystem(selIdx);
|
||||
if fs = nil then begin closeMsgBox; exit; end;
|
||||
|
||||
memset(uint32(@params), 0, sizeof(TFSFormatParams));
|
||||
memset(PtrUInt(@params), 0, sizeof(TFSFormatParams));
|
||||
params.Version := FS_FORMAT_PARAMS_VERSION_1;
|
||||
paramPtr := nil;
|
||||
|
||||
@@ -874,7 +875,7 @@ begin
|
||||
if fs^.validateLabelCallback(text,normalized) <> eNone then begin
|
||||
set_fmt_param_error('Use up to 11 ASCII characters without punctuation such as / or :'); exit;
|
||||
end;
|
||||
memcpy(uint32(@normalized[0]),uint32(@params.LabelText[0]),12);
|
||||
memcpy(PtrUInt(@normalized[0]),PtrUInt(@params.LabelText[0]),12);
|
||||
params.Flags := params.Flags or FS_FORMAT_PARAM_LABEL; paramPtr := @params;
|
||||
end;
|
||||
|
||||
@@ -1200,7 +1201,8 @@ begin
|
||||
vol := findVolumeForPartition(device, part.LBA_start);
|
||||
if vol <> nil then begin
|
||||
freeB := uint64(vol^.freeSectors) * vol^.sectorSize;
|
||||
freeStr := uiConcat(formatSizeStr(freeB), ' free');
|
||||
if (vol^.lifecycleFlags and STORAGE_VOLUME_FLAG_FREE_UNKNOWN) <> 0 then freeStr := 'Free: unknown'
|
||||
else freeStr := uiConcat(formatSizeStr(freeB), ' free');
|
||||
lbl := lv_label_create(row);
|
||||
lv_label_set_text(lbl, freeStr);
|
||||
lv_obj_set_style_text_color(lbl, lv_color_make(100, 180, 130), 0);
|
||||
@@ -1240,7 +1242,6 @@ var
|
||||
dw : sint32;
|
||||
i : uint32;
|
||||
totalBytes : uint64;
|
||||
usedSectors : uint64;
|
||||
freeBytes : uint64;
|
||||
volCnt : uint32;
|
||||
devVolCnt : uint32;
|
||||
@@ -1274,22 +1275,18 @@ begin
|
||||
totalBytes := uint64(device^.maxSectorCount) * device^.sectorSize;
|
||||
addInfoRow(detail, dw, 'Total Size', formatSizePrecise(totalBytes));
|
||||
|
||||
{ Compute free space from in-memory volume data (no I/O) }
|
||||
usedSectors := 0;
|
||||
{ Use the same cached partition geometry as Add Partition. Volumes may
|
||||
still be undergoing filesystem probing after the device is published. }
|
||||
devVolCnt := 0;
|
||||
volCnt := driver.storage.vol.mgr.get_volume_count();
|
||||
if volCnt > 0 then for i := 0 to volCnt - 1 do begin
|
||||
vol := driver.storage.vol.mgr.get_volume(i);
|
||||
if (vol <> nil) and (vol^.device = device) then begin
|
||||
devVolCnt := devVolCnt + 1;
|
||||
usedSectors := usedSectors + vol^.sectorCount;
|
||||
end;
|
||||
end;
|
||||
if device^.maxSectorCount > usedSectors then
|
||||
freeBytes := uint64(device^.maxSectorCount - usedSectors) * device^.sectorSize
|
||||
else
|
||||
freeBytes := 0;
|
||||
addInfoRow(detail, dw, 'Free Space', formatSizePrecise(freeBytes));
|
||||
freeBytes := uint64(driver.storage.vol.mgr.get_free_sector_count(device)) * device^.sectorSize;
|
||||
addInfoRow(detail, dw, 'Unallocated Space', formatSizePrecise(freeBytes));
|
||||
addInfoRow(detail, dw, 'Volumes', uiInt(devVolCnt));
|
||||
|
||||
{ Usage bar }
|
||||
@@ -1352,7 +1349,8 @@ begin
|
||||
|
||||
{ Free space }
|
||||
freeB := uint64(vol^.freeSectors) * vol^.sectorSize;
|
||||
freeStr := uiConcat(formatSizeStr(freeB), ' free');
|
||||
if (vol^.lifecycleFlags and STORAGE_VOLUME_FLAG_FREE_UNKNOWN) <> 0 then freeStr := 'Free: unknown'
|
||||
else freeStr := uiConcat(formatSizeStr(freeB), ' free');
|
||||
lbl := lv_label_create(row);
|
||||
lv_label_set_text(lbl, freeStr);
|
||||
lv_obj_set_style_text_color(lbl, lv_color_make(100, 180, 130), 0);
|
||||
@@ -1494,6 +1492,10 @@ begin
|
||||
usedBytes := totalBytes - freeBytes;
|
||||
|
||||
addInfoRow(detail, dw, 'Total Size', formatSizePrecise(totalBytes));
|
||||
if (vol^.lifecycleFlags and STORAGE_VOLUME_FLAG_FREE_UNKNOWN) <> 0 then begin
|
||||
addInfoRow(detail, dw, 'Free Space', 'Unknown');
|
||||
addInfoRow(detail, dw, 'Used Space', 'Unknown');
|
||||
end else begin
|
||||
addInfoRow(detail, dw, 'Free Space', formatSizePrecise(freeBytes));
|
||||
addInfoRow(detail, dw, 'Used Space', formatSizePrecise(usedBytes));
|
||||
|
||||
@@ -1502,6 +1504,7 @@ begin
|
||||
addInfoRow(detail, dw, 'Usage', uiConcat(uiInt(pctUsed), '%'));
|
||||
addUsageBar(detail, dw, usedBytes, totalBytes);
|
||||
end;
|
||||
end;
|
||||
|
||||
addInfoRow(detail, dw, 'Boot Drive', boolStr(vol^.isBootDrive));
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ uses
|
||||
core.gfx.fileicons,
|
||||
debug.tracer,
|
||||
core.util,
|
||||
arch.x86.util;
|
||||
arch.platform.cpu;
|
||||
|
||||
const
|
||||
WIN_W = 800;
|
||||
@@ -785,9 +785,9 @@ begin
|
||||
dir_names := PNameBuf(kalloc(sizeof(TNameBuf)));
|
||||
file_names := PNameBuf(kalloc(sizeof(TNameBuf)));
|
||||
file_sizes := PSizeBuf(kalloc(sizeof(TSizeBuf)));
|
||||
memset(uint32(dir_names), 0, sizeof(TNameBuf));
|
||||
memset(uint32(file_names), 0, sizeof(TNameBuf));
|
||||
memset(uint32(file_sizes), 0, sizeof(TSizeBuf));
|
||||
memset(PtrUInt(dir_names), 0, sizeof(TNameBuf));
|
||||
memset(PtrUInt(file_names), 0, sizeof(TNameBuf));
|
||||
memset(PtrUInt(file_sizes), 0, sizeof(TSizeBuf));
|
||||
|
||||
{ Load directory from VFS — this may do disk I/O }
|
||||
Map := driver.storage.vfs.GetDirectoryListingFrom(state^.cur_path, '/');
|
||||
@@ -1330,7 +1330,7 @@ begin
|
||||
parent := stringCopy('/')
|
||||
else begin
|
||||
parent := pchar(kalloc(uint32(i) + 1));
|
||||
memcpy(uint32(cur), uint32(parent), uint32(i));
|
||||
memcpy(PtrUInt(cur), PtrUInt(parent), uint32(i));
|
||||
parent[i] := char(0);
|
||||
end;
|
||||
navigate_to(state, parent);
|
||||
@@ -1440,7 +1440,7 @@ begin
|
||||
|
||||
{ Segment name label }
|
||||
segBuf := pchar(kalloc(segEnd - segStart + 1));
|
||||
memcpy(uint32(@path[segStart]), uint32(segBuf), segEnd - segStart);
|
||||
memcpy(PtrUInt(@path[segStart]), uint32(segBuf), segEnd - segStart);
|
||||
segBuf[segEnd - segStart] := char(0);
|
||||
lbl := lv_label_create(btn);
|
||||
lv_label_set_text(lbl, segBuf);
|
||||
@@ -1979,7 +1979,7 @@ begin
|
||||
if state^.tabs[idx] <> nil then
|
||||
free_tab_snapshot(state^.tabs[idx]);
|
||||
snap := PTabSnapshot(kalloc(sizeof(TTabSnapshot)));
|
||||
memset(uint32(snap), 0, sizeof(TTabSnapshot));
|
||||
memset(PtrUInt(snap), 0, sizeof(TTabSnapshot));
|
||||
if state^.cur_path <> nil then
|
||||
snap^.cur_path := stringCopy(state^.cur_path)
|
||||
else
|
||||
@@ -2090,7 +2090,7 @@ begin
|
||||
save_tab(state, state^.active_tab);
|
||||
{ Create snapshot for new tab }
|
||||
snap := PTabSnapshot(kalloc(sizeof(TTabSnapshot)));
|
||||
memset(uint32(snap), 0, sizeof(TTabSnapshot));
|
||||
memset(PtrUInt(snap), 0, sizeof(TTabSnapshot));
|
||||
snap^.cur_path := stringCopy(path);
|
||||
snap^.hist_len := 0;
|
||||
snap^.hist_pos := 0;
|
||||
@@ -3053,7 +3053,7 @@ begin
|
||||
|
||||
{ Allocate and zero-initialise state }
|
||||
state := PFileBrowserState(kalloc(sizeof(TFileBrowserState)));
|
||||
memset(uint32(state), 0, sizeof(TFileBrowserState));
|
||||
memset(PtrUInt(state), 0, sizeof(TFileBrowserState));
|
||||
state^.win_id := g_win_id;
|
||||
state^.cur_path := stringCopy('/');
|
||||
state^.view_mode := vmDetail;
|
||||
|
||||
@@ -64,7 +64,7 @@ uses
|
||||
core.strings.helpers,
|
||||
io.syslog,
|
||||
debug.tracer,
|
||||
core.util, arch.x86.util,
|
||||
core.util, arch.platform.cpu,
|
||||
driver.storage.vfs;
|
||||
|
||||
const
|
||||
@@ -325,9 +325,9 @@ begin
|
||||
dir_names := PNameBuf(kalloc(sizeof(TNameBuf)));
|
||||
file_names := PNameBuf(kalloc(sizeof(TNameBuf)));
|
||||
file_sizes := PSizeBuf(kalloc(sizeof(TSizeBuf)));
|
||||
memset(uint32(dir_names), 0, sizeof(TNameBuf));
|
||||
memset(uint32(file_names), 0, sizeof(TNameBuf));
|
||||
memset(uint32(file_sizes), 0, sizeof(TSizeBuf));
|
||||
memset(PtrUInt(dir_names), 0, sizeof(TNameBuf));
|
||||
memset(PtrUInt(file_names), 0, sizeof(TNameBuf));
|
||||
memset(PtrUInt(file_sizes), 0, sizeof(TSizeBuf));
|
||||
|
||||
{ Sync path bar }
|
||||
if p^.path_bar <> nil then
|
||||
@@ -898,7 +898,7 @@ begin
|
||||
io.syslog.logln('FPCIK', 'make_picker: enter');
|
||||
|
||||
p := PPicker(kalloc(sizeof(TPicker)));
|
||||
memset(uint32(p), 0, sizeof(TPicker));
|
||||
memset(PtrUInt(p), 0, sizeof(TPicker));
|
||||
p^.cb := cb;
|
||||
p^.userdata := userdata;
|
||||
p^.is_save := is_save;
|
||||
|
||||
@@ -22,7 +22,7 @@ unit app.md5sum;
|
||||
interface
|
||||
|
||||
uses
|
||||
io.stdio, core.util, arch.x86.util, core.strings, debug.tracer, core.enc.md5;
|
||||
memory.heap, io.stdio, core.util, arch.platform.cpu, core.strings, debug.tracer, core.enc.md5;
|
||||
|
||||
procedure init();
|
||||
|
||||
@@ -36,6 +36,10 @@ var
|
||||
i : uint32;
|
||||
|
||||
begin
|
||||
if paramCount(Params) = 0 then begin
|
||||
io.stdio.bufWriteStrLn(stderr_buf, 'Usage: MD5SUM <word>');
|
||||
exit;
|
||||
end;
|
||||
md5word:= getParam(0, Params);
|
||||
wordlen:= stringSize(md5word);
|
||||
MD5_Hash := MD5Buffer(puint8(md5word), wordlen);
|
||||
@@ -43,6 +47,7 @@ begin
|
||||
io.stdio.bufWriteHexPair(stdout_buf, MD5_Hash^[i]);
|
||||
end;
|
||||
io.stdio.bufWriteStrLn(stdout_buf, ' ');
|
||||
memory.heap.kfree(void(MD5_Hash));
|
||||
end;
|
||||
|
||||
procedure init();
|
||||
@@ -51,4 +56,4 @@ begin
|
||||
io.stdio.registerCommand('MD5SUM', @Run, 'Perform MD5SUM on a word.');
|
||||
end;
|
||||
|
||||
end.
|
||||
end.
|
||||
+23
-43
@@ -22,7 +22,7 @@ unit app.meminfo;
|
||||
interface
|
||||
|
||||
uses
|
||||
io.stdio, arch.x86.multiboot, arch.x86.memory.physical, memory.heap, debug.tracer;
|
||||
io.stdio, arch.platform.memory, memory.heap, debug.tracer;
|
||||
|
||||
procedure init();
|
||||
|
||||
@@ -30,50 +30,30 @@ implementation
|
||||
|
||||
procedure run(Params : PParamList; stdin_buf, stdout_buf, stderr_buf : POutBuf);
|
||||
var
|
||||
pmm_total, pmm_free, pmm_used : uint32;
|
||||
lmm_pages, lmm_free : uint32;
|
||||
total, available: uint64;
|
||||
heapPages: uint32;
|
||||
begin
|
||||
{ Multiboot memory info }
|
||||
io.stdio.bufWriteStrLn(stdout_buf, '--- Multiboot ---');
|
||||
io.stdio.bufWriteStr(stdout_buf, 'Lower Memory : ');
|
||||
io.stdio.bufWriteInt(stdout_buf, multibootinfo^.mem_lower);
|
||||
io.stdio.bufWriteStrLn(stdout_buf, ' KB');
|
||||
io.stdio.bufWriteStr(stdout_buf, 'Upper Memory : ');
|
||||
io.stdio.bufWriteInt(stdout_buf, multibootinfo^.mem_upper);
|
||||
io.stdio.bufWriteStrLn(stdout_buf, ' KB');
|
||||
io.stdio.bufWriteStr(stdout_buf, 'Total Memory : ');
|
||||
io.stdio.bufWriteInt(stdout_buf, ((multibootinfo^.mem_upper + 1000) div 1024) + 1);
|
||||
io.stdio.bufWriteStrLn(stdout_buf, ' MB');
|
||||
|
||||
{ PMM stats }
|
||||
io.stdio.bufWriteStrLn(stdout_buf, '--- PMM (4 MB blocks) ---');
|
||||
pmm_total := arch.x86.memory.physical.pmm_total_blocks;
|
||||
pmm_free := arch.x86.memory.physical.pmm_free_blocks;
|
||||
pmm_used := pmm_total - pmm_free;
|
||||
io.stdio.bufWriteStr(stdout_buf, 'Total Blocks : ');
|
||||
io.stdio.bufWriteIntLn(stdout_buf, pmm_total);
|
||||
io.stdio.bufWriteStr(stdout_buf, 'Free Blocks : ');
|
||||
io.stdio.bufWriteIntLn(stdout_buf, pmm_free);
|
||||
io.stdio.bufWriteStr(stdout_buf, 'Used Blocks : ');
|
||||
io.stdio.bufWriteIntLn(stdout_buf, pmm_used);
|
||||
io.stdio.bufWriteStr(stdout_buf, 'Free Physical : ');
|
||||
io.stdio.bufWriteInt(stdout_buf, pmm_free * 4);
|
||||
io.stdio.bufWriteStrLn(stdout_buf, ' MB');
|
||||
|
||||
{ LMM heap stats }
|
||||
io.stdio.bufWriteStrLn(stdout_buf, '--- LMM (Heap) ---');
|
||||
lmm_pages := memory.heap.lmm_page_count;
|
||||
lmm_free := memory.heap.lmm_total_free;
|
||||
io.stdio.bufWriteStr(stdout_buf, 'Heap Pages : ');
|
||||
io.stdio.bufWriteIntLn(stdout_buf, lmm_pages);
|
||||
io.stdio.bufWriteStr(stdout_buf, 'Heap Size : ');
|
||||
io.stdio.bufWriteInt(stdout_buf, lmm_pages * 4);
|
||||
io.stdio.bufWriteStrLn(stdout_buf, ' MB');
|
||||
io.stdio.bufWriteStr(stdout_buf, 'Heap Free : ');
|
||||
io.stdio.bufWriteInt(stdout_buf, lmm_free div 1024);
|
||||
io.stdio.bufWriteStrLn(stdout_buf, ' KB');
|
||||
total := arch.platform.memory.totalPhysicalBytes;
|
||||
available := arch.platform.memory.freePhysicalBytes;
|
||||
io.stdio.bufWriteStr(stdout_buf, 'Usable Physical: ');
|
||||
io.stdio.bufWriteInt(stdout_buf, total div 1024);
|
||||
io.stdio.bufWriteStrLn(stdout_buf, ' KiB');
|
||||
io.stdio.bufWriteStr(stdout_buf, 'Free Physical : ');
|
||||
io.stdio.bufWriteInt(stdout_buf, available div 1024);
|
||||
io.stdio.bufWriteStrLn(stdout_buf, ' KiB');
|
||||
io.stdio.bufWriteStr(stdout_buf, 'Used Physical : ');
|
||||
io.stdio.bufWriteInt(stdout_buf, (total - available) div 1024);
|
||||
io.stdio.bufWriteStrLn(stdout_buf, ' KiB');
|
||||
heapPages := memory.heap.lmm_page_count;
|
||||
io.stdio.bufWriteStr(stdout_buf, 'Heap Regions : ');
|
||||
io.stdio.bufWriteIntLn(stdout_buf, heapPages);
|
||||
io.stdio.bufWriteStr(stdout_buf, 'Heap Size : ');
|
||||
io.stdio.bufWriteInt(stdout_buf, uint64(heapPages) * PAGE_SIZE_LMM div 1024);
|
||||
io.stdio.bufWriteStrLn(stdout_buf, ' KiB');
|
||||
io.stdio.bufWriteStr(stdout_buf, 'Heap Free : ');
|
||||
io.stdio.bufWriteInt(stdout_buf, memory.heap.lmm_total_free div 1024);
|
||||
io.stdio.bufWriteStrLn(stdout_buf, ' KiB');
|
||||
end;
|
||||
|
||||
procedure init();
|
||||
begin
|
||||
debug.tracer.push_trace('meminfo.init');
|
||||
|
||||
+1
-17
@@ -23,10 +23,9 @@ 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, app.iotest,
|
||||
app.base64, app.md5sum, app.dhclient, app.testcmd, app.ping, app.meminfo, app.setres,
|
||||
//drivers
|
||||
driver.storage.ctl.ram, driver.mgr,
|
||||
//network
|
||||
@@ -35,8 +34,6 @@ uses
|
||||
driver.storage.filedispatch,
|
||||
//wasm
|
||||
app.wasm.runner,
|
||||
app.divzero,
|
||||
app.bsod,
|
||||
app.vterminal;
|
||||
|
||||
{ Initialize all baked-in programs }
|
||||
@@ -47,7 +44,6 @@ implementation
|
||||
uses
|
||||
core.version,
|
||||
//command provider units
|
||||
arch.x86.cpu,
|
||||
app.diskcmd, driver.bus.usb.core, app.diskutil, app.notepad, app.partcmd, app.volcmd,
|
||||
app.filebrowser;
|
||||
|
||||
@@ -56,16 +52,10 @@ begin
|
||||
debug.tracer.push_trace('app.mgr.init');
|
||||
|
||||
{ Register commands from provider units }
|
||||
io.stdio.registerCommand('CPU', @arch.x86.cpu.Terminal_Command_CPU, 'CPU Info.');
|
||||
io.stdio.registerCommand('DEV', @driver.mgr.terminal_command_dev, 'Driver Management Interface.');
|
||||
io.stdio.registerCommand('PS', @proc.mgr.terminal_command_ps, 'List running processes.');
|
||||
io.stdio.registerCommand('KILL', @proc.mgr.terminal_command_kill, 'Force-kill a process by PID.');
|
||||
io.stdio.registerCommand('TERMINATE', @proc.mgr.terminal_command_terminate, 'Gracefully terminate a process by PID.');
|
||||
io.stdio.registerCommand('ARP', @driver.net.proto.arp.terminal_command_arp, 'Get ARP Table.');
|
||||
io.stdio.registerCommand('IFCONFIG', @driver.net.proto.ipv4.terminal_command_ifconfig, 'Configure Network Settings.');
|
||||
io.stdio.registerCommand('TCPCONNECT', @driver.net.proto.tcp.terminal_command_tcpconnect, 'Connect to a TCP host and send Hello World.');
|
||||
io.stdio.registerCommand('TCPLISTEN', @driver.net.proto.tcp.terminal_command_tcplisten, 'Listen on a TCP port and log received data.');
|
||||
io.stdio.registerCommand('TCPHTTP', @driver.net.proto.tcp.terminal_command_tcphttp, 'Send HTTP GET to a host IP (port 80 default).');
|
||||
io.stdio.registerCommand('USB', @driver.bus.usb.core.terminal_command_usb, 'driver.bus.usb subsystem information.');
|
||||
|
||||
{ File dispatch — must init before apps that register handlers }
|
||||
@@ -81,21 +71,15 @@ begin
|
||||
app.md5sum.init();
|
||||
app.base64.init();
|
||||
app.dhclient.init();
|
||||
app.vbeinfo.init();
|
||||
app.testcmd.init();
|
||||
app.ping.init();
|
||||
app.meminfo.init();
|
||||
{ WASM & remaining apps }
|
||||
app.wasm.runner.init();
|
||||
app.setres.init();
|
||||
app.divzero.init();
|
||||
app.bsod.init();
|
||||
app.vterminal.init;
|
||||
app.filebrowser.init();
|
||||
app.iotest.init();
|
||||
end;
|
||||
|
||||
Initialization
|
||||
boot.mgr.registerBoot('app.mgr', @init, 'Program Manager', BOOT_MGR_BARRIER_LATE);
|
||||
|
||||
end.
|
||||
Loaded 20 of 176 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user