feat: auto-mount boot drive to /boot; fix FAT32 deleted entry triple fault
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
- Decode multiboot boot_device byte in storagemanager to identify boot device - Add isBootDevice to TStorage_Device; propagate isBootDrive to volumes - Create /boot VFS directory at init; mount boot volume there in auto_mount_volumes - Fix getDirEntries skipping \-marked (deleted) FAT32 entries to prevent triple fault when navigating into a deleted directory via file picker
This commit is contained in:
1 parent
deb513c925
commit
3a733b1559
14 files changed
+1050
-297
No files matched your search
+10
-9
@@ -1,12 +1,13 @@
|
|||||||
*.o
|
/lib/*.ppu
|
||||||
*.ppu
|
/lib/*.a
|
||||||
*.s
|
/lib/*.o
|
||||||
*.iso
|
/release/*.svg
|
||||||
*.elf
|
/release/*.iso
|
||||||
lib/
|
/bin/*.bin
|
||||||
release/
|
/iso/boot/asuro.bin
|
||||||
doc/
|
/*.iso
|
||||||
bin/
|
/*.md5
|
||||||
|
/*.sh~
|
||||||
/*.img
|
/*.img
|
||||||
src/include/asuro.pas
|
src/include/asuro.pas
|
||||||
localenv.json
|
localenv.json
|
||||||
|
|||||||
+18
-18
@@ -7,12 +7,12 @@ eff5f36e129bc22770d643173c426cbd src//gdt.pas
|
|||||||
42d014445ddc0fd4d01c59e690795532 src//idt.pas
|
42d014445ddc0fd4d01c59e690795532 src//idt.pas
|
||||||
b40f0c2f3ec166a0bf2ebcf8f11f5614 src//irq.pas
|
b40f0c2f3ec166a0bf2ebcf8f11f5614 src//irq.pas
|
||||||
160ca7f01eb779595a5c90174f8d545e src//isr.pas
|
160ca7f01eb779595a5c90174f8d545e src//isr.pas
|
||||||
f0d6b256c4c136d1538259cf11358665 src//kernel.pas
|
40ca8769ba09f7e2696f38a3b48687aa src//kernel.pas
|
||||||
c413d77a3264adb2d5337712c50e1925 src//lmemorymanager.pas
|
c413d77a3264adb2d5337712c50e1925 src//lmemorymanager.pas
|
||||||
b290d919549d8b03a7568ff3323ccbca src//pmemorymanager.pas
|
b290d919549d8b03a7568ff3323ccbca src//pmemorymanager.pas
|
||||||
4a5f5bf0f2ca7fff89074ad02813091c src//processloader.pas
|
4a5f5bf0f2ca7fff89074ad02813091c src//processloader.pas
|
||||||
303a93d2dce68d91d454bcd7e883c5d5 src//processmanager.pas
|
ab28dadd75652c6f3c655c7941fdb823 src//processmanager.pas
|
||||||
99c3d17476d2fe34b04a848514a880f2 src//progmanager.pas
|
ba78e851b043241d0099c0a67d385362 src//progmanager.pas
|
||||||
81d4b5c4a25a1a855d75a88c725b77fe src//scheduler.pas
|
81d4b5c4a25a1a855d75a88c725b77fe src//scheduler.pas
|
||||||
1be263e53e4838f6a06d2ece86400ef2 src//stdio.pas
|
1be263e53e4838f6a06d2ece86400ef2 src//stdio.pas
|
||||||
940a7ed5808841c6ba344b67965ecba7 src//syslog.pas
|
940a7ed5808841c6ba344b67965ecba7 src//syslog.pas
|
||||||
@@ -26,7 +26,6 @@ fe1dba288d3a3ab427a9dea0a9f747ae src//tracer.pas
|
|||||||
1a107558af58e8d4d689ae67582913e8 src/driver/bus/usb/UHCI.pas
|
1a107558af58e8d4d689ae67582913e8 src/driver/bus/usb/UHCI.pas
|
||||||
6edd4a1e9c92e092aea1368d9aa2724f src/driver/bus/usb/USB.pas
|
6edd4a1e9c92e092aea1368d9aa2724f src/driver/bus/usb/USB.pas
|
||||||
33d50f2daa362859d80a1a684e69f75b src/driver/bus/usb/XHCI.pas
|
33d50f2daa362859d80a1a684e69f75b src/driver/bus/usb/XHCI.pas
|
||||||
442d27dfbf472cf94bb51ae08f203675 src/driver/bus/usb/usb_storage.pas
|
|
||||||
7694d4aeb0878b22792996a59efa7607 src/driver/bus/usb/usbcore.pas
|
7694d4aeb0878b22792996a59efa7607 src/driver/bus/usb/usbcore.pas
|
||||||
e8aabf9e1ba0c09ede43ed2844802aa0 src/driver/bus/usb/usbhub.pas
|
e8aabf9e1ba0c09ede43ed2844802aa0 src/driver/bus/usb/usbhub.pas
|
||||||
ea992f0cedb8a760d2b6d3f23ff88a86 src/driver/bus/usb/usbtypes.pas
|
ea992f0cedb8a760d2b6d3f23ff88a86 src/driver/bus/usb/usbtypes.pas
|
||||||
@@ -57,18 +56,19 @@ a2b9bf4fe7d878b73fe1af51e7d050b1 src/driver/storage/fdtable.pas
|
|||||||
c305190af3b74ae62992653d4c1a5cf8 src/driver/storage/iobuffer.pas
|
c305190af3b74ae62992653d4c1a5cf8 src/driver/storage/iobuffer.pas
|
||||||
82766a71b0f186f1be6832493fb84bdc src/driver/storage/iorequest.pas
|
82766a71b0f186f1be6832493fb84bdc src/driver/storage/iorequest.pas
|
||||||
08a8280503120f3a90a9a041bc8b67d3 src/driver/storage/partitiontable.pas
|
08a8280503120f3a90a9a041bc8b67d3 src/driver/storage/partitiontable.pas
|
||||||
7b2c0fddec72e7ed25f7aee080e24465 src/driver/storage/storagemanager.pas
|
d67ae26b98a12080f5ae3065b4352c9b src/driver/storage/storagemanager.pas
|
||||||
3285573a47389c43a7e47f872440964c src/driver/storage/storagetest.pas
|
260d1bc1716be4347d14f3cb2d92ccde src/driver/storage/storagetest.pas
|
||||||
91c530b1e023160a79cf942ba386805d src/driver/storage/storagetypes.pas
|
27ea69c2f0bdfb642a5beafdf71ec3d4 src/driver/storage/storagetypes.pas
|
||||||
b085ff2efcb7c812524ad840b7cdf315 src/driver/storage/vfs.pas
|
430a17272f1a2995ba6803d575ef9d3c src/driver/storage/usb_storage.pas
|
||||||
bac08992d201dc839edcc29818b55c75 src/driver/storage/volumemanager.pas
|
a03e87379ad290860ccbad1d822b37df src/driver/storage/vfs.pas
|
||||||
|
60fde551085ffa111ee913bea8791b44 src/driver/storage/volumemanager.pas
|
||||||
71ad146cd66801b5bc7992d57a7ecf31 src/driver/storage/AHCI/AHCI.pas
|
71ad146cd66801b5bc7992d57a7ecf31 src/driver/storage/AHCI/AHCI.pas
|
||||||
16304358a6278c23a751e31bb464eae5 src/driver/storage/AHCI/AHCITypes.pas
|
16304358a6278c23a751e31bb464eae5 src/driver/storage/AHCI/AHCITypes.pas
|
||||||
b5e3bcb914b585a95ac646cfea7d016e src/driver/storage/Filesystems/asfs.pas
|
b5e3bcb914b585a95ac646cfea7d016e src/driver/storage/Filesystems/asfs.pas
|
||||||
a4a0def26868069ed7b734fa78efef12 src/driver/storage/Filesystems/fat32.pas
|
df16abe38aafcb4bb02130baa6dc1607 src/driver/storage/Filesystems/fat32.pas
|
||||||
9bceba956d3eeffe97e07bdd45a9476f src/driver/storage/Filesystems/filesystemmanager.pas
|
9bceba956d3eeffe97e07bdd45a9476f src/driver/storage/Filesystems/filesystemmanager.pas
|
||||||
a0ea5cc8bdc152492312d444f249f3c1 src/driver/storage/Filesystems/flatfs.pas
|
a0ea5cc8bdc152492312d444f249f3c1 src/driver/storage/Filesystems/flatfs.pas
|
||||||
b16930bae1c7b49281582b0c6a601c4f src/driver/storage/Filesystems/iso9660.pas
|
9ef2de4df40c4b57af2deb297abfd664 src/driver/storage/Filesystems/iso9660.pas
|
||||||
ed26491124206842b40c219d2af4d70d src/driver/storage/IDE/IDE.pas
|
ed26491124206842b40c219d2af4d70d src/driver/storage/IDE/IDE.pas
|
||||||
0030f888faa8ef6c89963be0b6841289 src/driver/storage/IDE/ata.pas
|
0030f888faa8ef6c89963be0b6841289 src/driver/storage/IDE/ata.pas
|
||||||
68665eec07c019f5fdb874b52d3be03b src/driver/storage/IDE/atapi.pas
|
68665eec07c019f5fdb874b52d3be03b src/driver/storage/IDE/atapi.pas
|
||||||
@@ -78,9 +78,9 @@ c025ffabb5bba2272578d04903637d11 src/driver/timers/TMR_0_ISR.pas
|
|||||||
4a7434e5567f738b8545d56558902d9f src/driver/timers/TMR_1_ISR.pas
|
4a7434e5567f738b8545d56558902d9f src/driver/timers/TMR_1_ISR.pas
|
||||||
11aad5f2638a14546abe30ce19c0a807 src/driver/timers/graphicsrefresh.pas
|
11aad5f2638a14546abe30ce19c0a807 src/driver/timers/graphicsrefresh.pas
|
||||||
4503465b3f62464f25e17e1d1a67e54d src/driver/timers/usbhotplug.pas
|
4503465b3f62464f25e17e1d1a67e54d src/driver/timers/usbhotplug.pas
|
||||||
0434cc7b77429f971d372e89a8a6972d src/driver/video/desktop.pas
|
8d5f544ab27e5057d95f0f8069b8c2f6 src/driver/video/desktop.pas
|
||||||
fef57dc0269caad191652df07da04466 src/driver/video/doublebuffer.pas
|
fef57dc0269caad191652df07da04466 src/driver/video/doublebuffer.pas
|
||||||
f6038a53763be5d9c1f66fb8baacd83e src/driver/video/lvgl.pas
|
357cca32ea92028137551608dd5b0e82 src/driver/video/lvgl.pas
|
||||||
dce8755865885e41c08b062c162b06c9 src/driver/video/uidebug.pas
|
dce8755865885e41c08b062c162b06c9 src/driver/video/uidebug.pas
|
||||||
20dc95321989d632fa4c39a5faf74733 src/driver/video/vesa.pas
|
20dc95321989d632fa4c39a5faf74733 src/driver/video/vesa.pas
|
||||||
19c988cfcc36bcc78e73747662672d8f src/driver/video/vesa16.pas
|
19c988cfcc36bcc78e73747662672d8f src/driver/video/vesa16.pas
|
||||||
@@ -114,18 +114,18 @@ dee8388dac0ca79ee6aef73469d75f6b src/include/bios_data_area.pas
|
|||||||
717b8c0a42983f6b8864d5deda4dd532 src/include/color.pas
|
717b8c0a42983f6b8864d5deda4dd532 src/include/color.pas
|
||||||
1987f262a6053e02080023554d942ae1 src/include/crc.pas
|
1987f262a6053e02080023554d942ae1 src/include/crc.pas
|
||||||
7f6c812b5d7ae1a8af5ef00d42a4eb1d src/include/fonts.pas
|
7f6c812b5d7ae1a8af5ef00d42a4eb1d src/include/fonts.pas
|
||||||
bf9fe2883789147e08980ab4c43220f7 src/include/hashmap.pas
|
9cc7742497cf9a1940b9d400140348a6 src/include/hashmap.pas
|
||||||
513d59ae08ba6d753a871e1a82b46ed4 src/include/lists.pas
|
513d59ae08ba6d753a871e1a82b46ed4 src/include/lists.pas
|
||||||
c5ef14ac60dad5a32ebfa43da153d05c src/include/md5.pas
|
c5ef14ac60dad5a32ebfa43da153d05c src/include/md5.pas
|
||||||
124f12d75de7ade6993ccd2f02b53ad4 src/include/multiboot.pas
|
124f12d75de7ade6993ccd2f02b53ad4 src/include/multiboot.pas
|
||||||
1bb33ff2af8c360774d9c260f8036d2e src/include/proctypes.pas
|
c3cb83dddcf53d87c14f67f5ab4bbe5e src/include/proctypes.pas
|
||||||
d8beadde6ebb05c8a3e74aae57d61f34 src/include/rand.pas
|
d8beadde6ebb05c8a3e74aae57d61f34 src/include/rand.pas
|
||||||
cfa50e59e4bd9ea3a5b05c6b1275858d src/include/strings.pas
|
cfa50e59e4bd9ea3a5b05c6b1275858d src/include/strings.pas
|
||||||
cb254f95c5e09595c90db690bf98794f src/include/system.pas
|
cb254f95c5e09595c90db690bf98794f src/include/system.pas
|
||||||
5df11e0052010580d13f1a5ce3acd60f src/include/targa.pas
|
5df11e0052010580d13f1a5ce3acd60f src/include/targa.pas
|
||||||
833967cf14697db6da421a4be58e9044 src/include/texture.pas
|
833967cf14697db6da421a4be58e9044 src/include/texture.pas
|
||||||
635e5a8936a088a244ddfe48cd658a3f src/include/types.pas
|
635e5a8936a088a244ddfe48cd658a3f src/include/types.pas
|
||||||
cde48ecd2a80195da906f0d1e2658714 src/include/util.pas
|
ebf13bf342b063a79345613639c9b114 src/include/util.pas
|
||||||
d6a64b1434e1b528d1ba57171a9918ce src/include/data_structures/bheap.pas
|
d6a64b1434e1b528d1ba57171a9918ce src/include/data_structures/bheap.pas
|
||||||
54bc51933c982219ea4445e158a7c4ee src/include/data_structures/cfifo.pas
|
54bc51933c982219ea4445e158a7c4ee src/include/data_structures/cfifo.pas
|
||||||
51628ff135cf306cb9b0a0fac24f8c73 src/include/data_structures/cfifols.pas
|
51628ff135cf306cb9b0a0fac24f8c73 src/include/data_structures/cfifols.pas
|
||||||
@@ -144,11 +144,11 @@ e23b0bef333262860e1f68034331e529 src/isr/ioapic.pas
|
|||||||
f90540cb40f741dc70b1ae7435cf966b src/prog/diskcmd.pas
|
f90540cb40f741dc70b1ae7435cf966b src/prog/diskcmd.pas
|
||||||
cf729bd7af2f1bbb6319b3466ecb173a src/prog/diskutil.pas
|
cf729bd7af2f1bbb6319b3466ecb173a src/prog/diskutil.pas
|
||||||
93837d26fcacbcc6e5d339de51a666ff src/prog/edit.pas
|
93837d26fcacbcc6e5d339de51a666ff src/prog/edit.pas
|
||||||
99c3cf044d474264f7af27c1dcbeb1ca src/prog/filepicker.pas
|
b2dd736b9c8b93dfae3962422a597663 src/prog/filepicker.pas
|
||||||
190f559362d0ea3b0ebfdde710364fbb src/prog/inio.pas
|
190f559362d0ea3b0ebfdde710364fbb src/prog/inio.pas
|
||||||
1ff556cd50088e3ee3efa3103fdc6ba0 src/prog/md5sum.pas
|
1ff556cd50088e3ee3efa3103fdc6ba0 src/prog/md5sum.pas
|
||||||
1161e238b85f6b59debbc6a507dd9478 src/prog/meminfo.pas
|
1161e238b85f6b59debbc6a507dd9478 src/prog/meminfo.pas
|
||||||
3df29f500456aa285b10cc7fd7f05cda src/prog/notepad.pas
|
80c1abd52c36a13114cd952704b6f455 src/prog/notepad.pas
|
||||||
cd03ccb60a3a3f0708fad6e70e2559c2 src/prog/partcmd.pas
|
cd03ccb60a3a3f0708fad6e70e2559c2 src/prog/partcmd.pas
|
||||||
f47e06c6989dfb9a497b6efd024e5863 src/prog/ping.pas
|
f47e06c6989dfb9a497b6efd024e5863 src/prog/ping.pas
|
||||||
24289df8b6d60736a48633a927cfeb06 src/prog/testcmd.pas
|
24289df8b6d60736a48633a927cfeb06 src/prog/testcmd.pas
|
||||||
|
|||||||
Binary file not shown.
@@ -24,3 +24,17 @@ The correct way to block a process on an async I/O result is: (1) set up a compl
|
|||||||
## 9. VFS GetDirectoryListing Must Return a Snapshot, Not a Live Tree Reference
|
## 9. VFS GetDirectoryListing Must Return a Snapshot, Not a Live Tree Reference
|
||||||
`GetDirectoryListing` for `otVDIRECTORY` nodes previously returned `PHashMap(Obj^.Reference)` — a direct pointer into the live VFS tree. When callers called `FreeDirectoryListing` on the returned map, it freed the live VFSObjects and their name strings, destroying the VFS tree. Any subsequent `GetObjectFromPath` call would then dereference the trashed memory and page fault. **Fix**: always return a heap-allocated snapshot copy of the directory (new `PHashMap`, new `PVFSObject` entries with `stringCopy`'d keys). `FreeDirectoryListing` can then safely own and free the snapshot without touching the live tree. The rule: any function that returns a `PHashMap` to a caller who will call `FreeDirectoryListing` must allocate a fresh map — never return a raw interior pointer to a live data structure.
|
`GetDirectoryListing` for `otVDIRECTORY` nodes previously returned `PHashMap(Obj^.Reference)` — a direct pointer into the live VFS tree. When callers called `FreeDirectoryListing` on the returned map, it freed the live VFSObjects and their name strings, destroying the VFS tree. Any subsequent `GetObjectFromPath` call would then dereference the trashed memory and page fault. **Fix**: always return a heap-allocated snapshot copy of the directory (new `PHashMap`, new `PVFSObject` entries with `stringCopy`'d keys). `FreeDirectoryListing` can then safely own and free the snapshot without touching the live tree. The rule: any function that returns a `PHashMap` to a caller who will call `FreeDirectoryListing` must allocate a fresh map — never return a raw interior pointer to a live data structure.
|
||||||
|
|
||||||
|
## 10. Never Call Synchronous Disk I/O From an LVGL Timer or Event Callback
|
||||||
|
LVGL timer callbacks (`lv_timer_create`) and event callbacks run synchronously inside the LVGL render loop. Calling any function that parks the current process waiting for disk I/O (e.g. `vfs.FileSize`, `vfs.OpenFile`, `vfs.ReadFile`) from inside a timer or event callback will hang the entire UI — the process blocks mid-callback and the LVGL loop never resumes. All disk I/O that must occur in a UI context must either: (a) use the async VFS API (`OpenFileAsync`, `WriteFileAsync`) with a completion callback that triggers a deferred LVGL update, or (b) be deferred to a dedicated worker process that signals back via a flag the UI can poll. `GetDirectoryListingFrom` is the one bulk exception — it was already present in the original picker and works because it loads into a snapshot synchronously as a single operation; per-file calls like `FileSize` in a loop are the problem.
|
||||||
|
|
||||||
|
## 11. Never Allocate Large Arrays as Local Variables in Deep Kernel Call Chains
|
||||||
|
Local variables are stack-allocated in Pascal. Kernel processes have a fixed, limited stack (≈8 KB). In deep LVGL callback chains (kernel → LVGL render loop → timer callback → app code), there may only be a few KB of usable stack remaining by the time app code executes. Declaring local arrays larger than ~200–400 bytes (e.g. `array[0..255] of pchar` = 1024 bytes) inside any procedure that runs in this context will silently overflow the stack, corruptung adjacent memory and causing a page fault with a garbled call trace. **Rule**: any local variable array larger than ~128 bytes in a UI callback or procedure called from one must be moved to the heap with `kalloc`/`kfree`. The corruption pattern is a page fault with a call stack full of completely unrelated function names.
|
||||||
|
|
||||||
|
## 12. Pascal Silently Ignores Everything After `end.` — Dead Code Masquerades as Live Code
|
||||||
|
FPC compiles everything up to and including the first `end.` and silently discards the rest of the file. If a file is partially rewritten by prepending a new implementation but the old implementation is not deleted, the old code survives after `end.`. Forward declarations resolve to the **last** implementation before `end.` — so if the new code was added before the old `end.` but the old procedures were in the "dead" zone they have no effect. However the reverse is dangerous: if the old `end.` was replaced/removed and the new code placed before it, the old procedures in the dead zone still compile to nothing but pollute the source. **Rule**: after any large-scale replacement of a Pascal unit, explicitly check where `end.` falls with a text search and PowerShell-truncate the file at the first `end.`. Never assume a multi-step replacement tool correctly removed all old code — always verify with `Select-String -Pattern "^end\.$"`.
|
||||||
|
|
||||||
|
## 13. `for i := 0 to uint32_count - 1` Wraps to 4 Billion When Count is Zero
|
||||||
|
In Free Pascal, `uint32` arithmetic wraps: if `dir_count` is `uint32` and equals `0`, then `dir_count - 1 = 0xFFFFFFFF`. A `for i := 0 to dir_count - 1 do` loop with zero count does NOT skip — it runs 4 billion iterations, immediately accessing invalid memory and page faulting. FPC does not emit a warning for this. **Rule**: always guard `uint32`-bounded for loops: `if count > 0 then for i := 0 to count - 1 do`. Alternatively, use `sint32` for loop counters that might legitimately be zero.
|
||||||
|
|
||||||
|
## 14. FAT32 Deleted Entries ($E5) Must Be Filtered in getDirEntries
|
||||||
|
When a FAT32 directory entry is deleted, `fileName[0]` is overwritten with `$E5` but the rest of the entry (including the cluster pointer) remains intact on disk. `getDirEntries` must explicitly skip entries where `fileName[0] = char($E5)` — stopping only at `char(0)` (end-of-directory) is not enough. If `$E5` entries are returned to callers, they appear in directory listings with a garbage first character, and navigating into them follows a stale/freed cluster chain, which causes reads into arbitrary memory or FAT data, leading to a triple fault. Fix location: the `while i < maxEntries` loop in `fat32.getDirEntries`.
|
||||||
@@ -490,6 +490,12 @@ begin
|
|||||||
while i < maxEntries do begin
|
while i < maxEntries do begin
|
||||||
if PDirectory(buffer)[i].fileName[0] = char(0) then break;
|
if PDirectory(buffer)[i].fileName[0] = char(0) then break;
|
||||||
|
|
||||||
|
{ Skip deleted entries ($E5 = FAT32 deleted marker) }
|
||||||
|
if PDirectory(buffer)[i].fileName[0] = char($E5) then begin
|
||||||
|
i+=1;
|
||||||
|
continue;
|
||||||
|
end;
|
||||||
|
|
||||||
dirElm:= LL_Add(directories);
|
dirElm:= LL_Add(directories);
|
||||||
PDirectory(dirElm)^:= PDirectory(buffer)[i];
|
PDirectory(dirElm)^:= PDirectory(buffer)[i];
|
||||||
i+=1;
|
i+=1;
|
||||||
@@ -535,6 +541,9 @@ begin
|
|||||||
for i:= 0 to LL_Size(list) - 1 do begin
|
for i:= 0 to LL_Size(list) - 1 do begin
|
||||||
dir := PDirectory(LL_get(list, i));
|
dir := PDirectory(LL_get(list, i));
|
||||||
|
|
||||||
|
{ Skip deleted entries (should already be filtered by getDirEntries, but guard here too) }
|
||||||
|
if dir^.fileName[0] = char($E5) then continue;
|
||||||
|
|
||||||
{ Trim trailing spaces from fileName (8 bytes) }
|
{ Trim trailing spaces from fileName (8 bytes) }
|
||||||
nameLen := 8;
|
nameLen := 8;
|
||||||
while (nameLen > 0) and (dir^.fileName[nameLen - 1] = ' ') do
|
while (nameLen > 0) and (dir^.fileName[nameLen - 1] = ' ') do
|
||||||
|
|||||||
@@ -448,7 +448,7 @@ begin
|
|||||||
volume^.sectorCount := pvd^.volumeSpaceSizeLSB;
|
volume^.sectorCount := pvd^.volumeSpaceSizeLSB;
|
||||||
volume^.freeSectors := 0;
|
volume^.freeSectors := 0;
|
||||||
volume^.filesystem := @filesystem;
|
volume^.filesystem := @filesystem;
|
||||||
volume^.isBootDrive := false;
|
volume^.isBootDrive := disk^.isBootDevice;
|
||||||
|
|
||||||
volumemanager.register_volume(disk, volume);
|
volumemanager.register_volume(disk, volume);
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,15 @@ var
|
|||||||
storageDevices : PDList;
|
storageDevices : PDList;
|
||||||
nextDeviceId : uint32;
|
nextDeviceId : uint32;
|
||||||
|
|
||||||
|
{ BIOS drive byte from multiboot — set once during kernel init before any
|
||||||
|
device drivers run. $80=first HDD, $81=second HDD, $9F/other=CD-ROM. }
|
||||||
|
bootDriveByte : uint8;
|
||||||
|
hdCount : uint32; { non-ATAPI devices registered so far }
|
||||||
|
atapiCount : uint32; { ATAPI devices registered so far }
|
||||||
|
|
||||||
procedure init();
|
procedure init();
|
||||||
|
procedure set_boot_drive_byte(driveByte : uint8);
|
||||||
|
function get_boot_drive_byte() : uint8;
|
||||||
procedure register_device(device : PStorage_Device);
|
procedure register_device(device : PStorage_Device);
|
||||||
function get_device_list() : PDList;
|
function get_device_list() : PDList;
|
||||||
function get_device_count() : uint32;
|
function get_device_count() : uint32;
|
||||||
@@ -148,6 +156,21 @@ begin
|
|||||||
push_trace('StorageManager.init');
|
push_trace('StorageManager.init');
|
||||||
storageDevices := DL_New(sizeof(TStorage_Device));
|
storageDevices := DL_New(sizeof(TStorage_Device));
|
||||||
nextDeviceId := 0;
|
nextDeviceId := 0;
|
||||||
|
bootDriveByte := $FF; { $FF = unknown/uninitialised }
|
||||||
|
hdCount := 0;
|
||||||
|
atapiCount := 0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure set_boot_drive_byte(driveByte : uint8);
|
||||||
|
begin
|
||||||
|
bootDriveByte := driveByte;
|
||||||
|
syslog.log('STRMGR', 'Boot drive BIOS byte = 0x');
|
||||||
|
syslog.writehexln(driveByte);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function get_boot_drive_byte() : uint8;
|
||||||
|
begin
|
||||||
|
get_boot_drive_byte := bootDriveByte;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure register_device(device : PStorage_Device);
|
procedure register_device(device : PStorage_Device);
|
||||||
@@ -163,6 +186,7 @@ begin
|
|||||||
device^.requestQueue := CFIFO_New(SizeOf(TIORequest), 32);
|
device^.requestQueue := CFIFO_New(SizeOf(TIORequest), 32);
|
||||||
device^.activeRequest := nil;
|
device^.activeRequest := nil;
|
||||||
device^.cachedMBR := nil;
|
device^.cachedMBR := nil;
|
||||||
|
device^.isBootDevice := false;
|
||||||
{ dispatchRead/dispatchWrite: left as-is — driver sets them before
|
{ dispatchRead/dispatchWrite: left as-is — driver sets them before
|
||||||
calling register_device. memset(0) guarantees nil for unmigrated drivers. }
|
calling register_device. memset(0) guarantees nil for unmigrated drivers. }
|
||||||
|
|
||||||
@@ -172,6 +196,31 @@ begin
|
|||||||
{ Get pointer to the DList copy so volumes reference the canonical device }
|
{ Get pointer to the DList copy so volumes reference the canonical device }
|
||||||
storedDev := PStorage_Device(DL_Get(storageDevices, DL_Size(storageDevices) - 1));
|
storedDev := PStorage_Device(DL_Get(storageDevices, DL_Size(storageDevices) - 1));
|
||||||
|
|
||||||
|
{ Identify whether this is the boot device using the BIOS drive byte.
|
||||||
|
BIOS numbers HDDs from $80 upward; the nth HDD is $80 + (n-1).
|
||||||
|
ATAPI/CD-ROM devices are NOT in the $80-range HDD sequence, so if
|
||||||
|
bootDriveByte does not match any HDD we have seen, the first ATAPI
|
||||||
|
device is marked as the boot device (covers standard ISO boot). }
|
||||||
|
if (storedDev^.controller = ControllerATAPI) or
|
||||||
|
(storedDev^.controller = ControllerAHCI_ATAPI) then begin
|
||||||
|
{ ATAPI device: boot if the drive byte is outside the known HDD range }
|
||||||
|
if bootDriveByte < ($80 + hdCount) then begin
|
||||||
|
{ drive byte refers to an HDD — this ATAPI is not the boot device }
|
||||||
|
end else if atapiCount = 0 then begin
|
||||||
|
{ first ATAPI and boot byte is not a known HDD → this is the boot drive }
|
||||||
|
storedDev^.isBootDevice := true;
|
||||||
|
syslog.logln('STRMGR', 'Boot device identified (ATAPI/ISO).');
|
||||||
|
end;
|
||||||
|
atapiCount := atapiCount + 1;
|
||||||
|
end else begin
|
||||||
|
{ Non-ATAPI (HDD): boot if BIOS drive byte matches $80 + index }
|
||||||
|
if bootDriveByte = ($80 + hdCount) then begin
|
||||||
|
storedDev^.isBootDevice := true;
|
||||||
|
syslog.logln('STRMGR', 'Boot device identified (HDD).');
|
||||||
|
end;
|
||||||
|
hdCount := hdCount + 1;
|
||||||
|
end;
|
||||||
|
|
||||||
{ Discover partitions and register volumes automatically }
|
{ Discover partitions and register volumes automatically }
|
||||||
if storedDev^.maxSectorCount > 0 then
|
if storedDev^.maxSectorCount > 0 then
|
||||||
volumemanager.discover_volumes(storedDev);
|
volumemanager.discover_volumes(storedDev);
|
||||||
|
|||||||
@@ -209,6 +209,7 @@ type
|
|||||||
sectorSize : uint32; //in bytes
|
sectorSize : uint32; //in bytes
|
||||||
start : uint32; //start of device in sectors
|
start : uint32; //start of device in sectors
|
||||||
cachedMBR : pointer; { cached MBR data, nil if not yet read }
|
cachedMBR : pointer; { cached MBR data, nil if not yet read }
|
||||||
|
isBootDevice : boolean; { true if this is the device GRUB booted from }
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Filesystem driver descriptor }
|
{ Filesystem driver descriptor }
|
||||||
|
|||||||
@@ -430,6 +430,7 @@ begin
|
|||||||
if (dirList <> nil) and (status^ = 0) and (LL_Size(dirList) > 0) then begin
|
if (dirList <> nil) and (status^ = 0) and (LL_Size(dirList) > 0) then begin
|
||||||
for i := 0 to LL_Size(dirList) - 1 do begin
|
for i := 0 to LL_Size(dirList) - 1 do begin
|
||||||
entry := PDirectory_Entry(LL_Get(dirList, i));
|
entry := PDirectory_Entry(LL_Get(dirList, i));
|
||||||
|
if (entry = nil) or (entry^.fileName = nil) then continue;
|
||||||
newObj := PVFSObject(kalloc(sizeof(TVFSObject)));
|
newObj := PVFSObject(kalloc(sizeof(TVFSObject)));
|
||||||
newObj^.Parent := Parent;
|
newObj^.Parent := Parent;
|
||||||
newObj^.Reference := nil;
|
newObj^.Reference := nil;
|
||||||
@@ -2062,6 +2063,12 @@ begin
|
|||||||
syslog.writestring(' volume at ');
|
syslog.writestring(' volume at ');
|
||||||
syslog.writestringln(mountPath);
|
syslog.writestringln(mountPath);
|
||||||
|
|
||||||
|
{ If this is the boot volume, also mount it at /boot }
|
||||||
|
if vol^.isBootDrive then begin
|
||||||
|
mountVolume('/boot', vol);
|
||||||
|
syslog.writestringln('VFS: Boot volume mounted at /boot');
|
||||||
|
end;
|
||||||
|
|
||||||
kfree(void(volName));
|
kfree(void(volName));
|
||||||
kfree(void(prefix));
|
kfree(void(prefix));
|
||||||
kfree(void(mountPath));
|
kfree(void(mountPath));
|
||||||
@@ -2135,6 +2142,7 @@ begin
|
|||||||
newVirtualDirectory('/disk');
|
newVirtualDirectory('/disk');
|
||||||
newVirtualDirectory('/mnt');
|
newVirtualDirectory('/mnt');
|
||||||
newVirtualDirectory('/cfg');
|
newVirtualDirectory('/cfg');
|
||||||
|
newVirtualDirectory('/boot');
|
||||||
|
|
||||||
{ Register Terminal Commands }
|
{ Register Terminal Commands }
|
||||||
stdio.registerCommand('LS', @VFS_COMMAND_LS, 'List directory contents.');
|
stdio.registerCommand('LS', @VFS_COMMAND_LS, 'List directory contents.');
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ begin
|
|||||||
volume^.sectorSize := device^.sectorSize;
|
volume^.sectorSize := device^.sectorSize;
|
||||||
volume^.freeSectors := 0;
|
volume^.freeSectors := 0;
|
||||||
volume^.filesystem := nil;
|
volume^.filesystem := nil;
|
||||||
volume^.isBootDrive := false;
|
volume^.isBootDrive := device^.isBootDevice;
|
||||||
filesystemmanager.probe_volume(volume);
|
filesystemmanager.probe_volume(volume);
|
||||||
register_volume(device, volume);
|
register_volume(device, volume);
|
||||||
end;
|
end;
|
||||||
|
|||||||
+27
-1
@@ -22,7 +22,12 @@ unit hashmap;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
md5, util, strings, lmemorymanager, tracer, syslog;
|
lmemorymanager,
|
||||||
|
md5,
|
||||||
|
strings,
|
||||||
|
syslog,
|
||||||
|
tracer,
|
||||||
|
util;
|
||||||
|
|
||||||
type
|
type
|
||||||
DPHashItem = ^PHashItem;
|
DPHashItem = ^PHashItem;
|
||||||
@@ -45,12 +50,16 @@ const
|
|||||||
HASHMAP_DEFAULT_SIZE = 16;
|
HASHMAP_DEFAULT_SIZE = 16;
|
||||||
HASHMAP_DEFAULT_LOADFACTOR = 0.75;
|
HASHMAP_DEFAULT_LOADFACTOR = 0.75;
|
||||||
|
|
||||||
|
type
|
||||||
|
THashForEachCb = procedure(key: pchar; data: void; ud: void);
|
||||||
|
|
||||||
function new : PHashMap;
|
function new : PHashMap;
|
||||||
function newEx(size : uint32; loadFactor : Single) : PHashMap;
|
function newEx(size : uint32; loadFactor : Single) : PHashMap;
|
||||||
procedure add(map : PHashMap; key : pchar; value : void);
|
procedure add(map : PHashMap; key : pchar; value : void);
|
||||||
function get(map : PHashMap; key : pchar) : void;
|
function get(map : PHashMap; key : pchar) : void;
|
||||||
procedure delete(map : PHashMap; key : pchar; freeItem : boolean);
|
procedure delete(map : PHashMap; key : pchar; freeItem : boolean);
|
||||||
procedure printMap(map : PHashMap);
|
procedure printMap(map : PHashMap);
|
||||||
|
procedure forEach(map : PHashMap; cb : THashForEachCb; ud : void);
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
@@ -257,6 +266,23 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure forEach(map : PHashMap; cb : THashForEachCb; ud : void);
|
||||||
|
var
|
||||||
|
i : uint32;
|
||||||
|
item : PHashItem;
|
||||||
|
begin
|
||||||
|
if (map = nil) or (map^.Size = 0) or (map^.Table = nil) then exit;
|
||||||
|
if cb = nil then exit;
|
||||||
|
for i := 0 to map^.Size - 1 do begin
|
||||||
|
item := map^.Table[i];
|
||||||
|
while item <> nil do begin
|
||||||
|
if item^.Key <> nil then
|
||||||
|
cb(item^.Key, item^.Data, ud);
|
||||||
|
item := item^.Next;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure printMap(map : PHashMap);
|
procedure printMap(map : PHashMap);
|
||||||
var
|
var
|
||||||
i,c : uint32;
|
i,c : uint32;
|
||||||
|
|||||||
@@ -230,6 +230,7 @@ begin
|
|||||||
drivermanagement.init();
|
drivermanagement.init();
|
||||||
tracer.push_trace('kmain.STRMGMT');
|
tracer.push_trace('kmain.STRMGMT');
|
||||||
storagemanager.init();
|
storagemanager.init();
|
||||||
|
storagemanager.set_boot_drive_byte((multibootinfo^.boot_device shr 24) and $FF);
|
||||||
volumemanager.init();
|
volumemanager.init();
|
||||||
filesystemmanager.init();
|
filesystemmanager.init();
|
||||||
|
|
||||||
|
|||||||
+890
-201
File diff suppressed because it is too large.
Load diff
+21
-66
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user