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:
+10
-9
@@ -1,12 +1,13 @@
|
||||
*.o
|
||||
*.ppu
|
||||
*.s
|
||||
*.iso
|
||||
*.elf
|
||||
lib/
|
||||
release/
|
||||
doc/
|
||||
bin/
|
||||
/lib/*.ppu
|
||||
/lib/*.a
|
||||
/lib/*.o
|
||||
/release/*.svg
|
||||
/release/*.iso
|
||||
/bin/*.bin
|
||||
/iso/boot/asuro.bin
|
||||
/*.iso
|
||||
/*.md5
|
||||
/*.sh~
|
||||
/*.img
|
||||
src/include/asuro.pas
|
||||
localenv.json
|
||||
|
||||
+18
-18
@@ -7,12 +7,12 @@ eff5f36e129bc22770d643173c426cbd src//gdt.pas
|
||||
42d014445ddc0fd4d01c59e690795532 src//idt.pas
|
||||
b40f0c2f3ec166a0bf2ebcf8f11f5614 src//irq.pas
|
||||
160ca7f01eb779595a5c90174f8d545e src//isr.pas
|
||||
f0d6b256c4c136d1538259cf11358665 src//kernel.pas
|
||||
40ca8769ba09f7e2696f38a3b48687aa src//kernel.pas
|
||||
c413d77a3264adb2d5337712c50e1925 src//lmemorymanager.pas
|
||||
b290d919549d8b03a7568ff3323ccbca src//pmemorymanager.pas
|
||||
4a5f5bf0f2ca7fff89074ad02813091c src//processloader.pas
|
||||
303a93d2dce68d91d454bcd7e883c5d5 src//processmanager.pas
|
||||
99c3d17476d2fe34b04a848514a880f2 src//progmanager.pas
|
||||
ab28dadd75652c6f3c655c7941fdb823 src//processmanager.pas
|
||||
ba78e851b043241d0099c0a67d385362 src//progmanager.pas
|
||||
81d4b5c4a25a1a855d75a88c725b77fe src//scheduler.pas
|
||||
1be263e53e4838f6a06d2ece86400ef2 src//stdio.pas
|
||||
940a7ed5808841c6ba344b67965ecba7 src//syslog.pas
|
||||
@@ -26,7 +26,6 @@ fe1dba288d3a3ab427a9dea0a9f747ae src//tracer.pas
|
||||
1a107558af58e8d4d689ae67582913e8 src/driver/bus/usb/UHCI.pas
|
||||
6edd4a1e9c92e092aea1368d9aa2724f src/driver/bus/usb/USB.pas
|
||||
33d50f2daa362859d80a1a684e69f75b src/driver/bus/usb/XHCI.pas
|
||||
442d27dfbf472cf94bb51ae08f203675 src/driver/bus/usb/usb_storage.pas
|
||||
7694d4aeb0878b22792996a59efa7607 src/driver/bus/usb/usbcore.pas
|
||||
e8aabf9e1ba0c09ede43ed2844802aa0 src/driver/bus/usb/usbhub.pas
|
||||
ea992f0cedb8a760d2b6d3f23ff88a86 src/driver/bus/usb/usbtypes.pas
|
||||
@@ -57,18 +56,19 @@ a2b9bf4fe7d878b73fe1af51e7d050b1 src/driver/storage/fdtable.pas
|
||||
c305190af3b74ae62992653d4c1a5cf8 src/driver/storage/iobuffer.pas
|
||||
82766a71b0f186f1be6832493fb84bdc src/driver/storage/iorequest.pas
|
||||
08a8280503120f3a90a9a041bc8b67d3 src/driver/storage/partitiontable.pas
|
||||
7b2c0fddec72e7ed25f7aee080e24465 src/driver/storage/storagemanager.pas
|
||||
3285573a47389c43a7e47f872440964c src/driver/storage/storagetest.pas
|
||||
91c530b1e023160a79cf942ba386805d src/driver/storage/storagetypes.pas
|
||||
b085ff2efcb7c812524ad840b7cdf315 src/driver/storage/vfs.pas
|
||||
bac08992d201dc839edcc29818b55c75 src/driver/storage/volumemanager.pas
|
||||
d67ae26b98a12080f5ae3065b4352c9b src/driver/storage/storagemanager.pas
|
||||
260d1bc1716be4347d14f3cb2d92ccde src/driver/storage/storagetest.pas
|
||||
27ea69c2f0bdfb642a5beafdf71ec3d4 src/driver/storage/storagetypes.pas
|
||||
430a17272f1a2995ba6803d575ef9d3c src/driver/storage/usb_storage.pas
|
||||
a03e87379ad290860ccbad1d822b37df src/driver/storage/vfs.pas
|
||||
60fde551085ffa111ee913bea8791b44 src/driver/storage/volumemanager.pas
|
||||
71ad146cd66801b5bc7992d57a7ecf31 src/driver/storage/AHCI/AHCI.pas
|
||||
16304358a6278c23a751e31bb464eae5 src/driver/storage/AHCI/AHCITypes.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
|
||||
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
|
||||
0030f888faa8ef6c89963be0b6841289 src/driver/storage/IDE/ata.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
|
||||
11aad5f2638a14546abe30ce19c0a807 src/driver/timers/graphicsrefresh.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
|
||||
f6038a53763be5d9c1f66fb8baacd83e src/driver/video/lvgl.pas
|
||||
357cca32ea92028137551608dd5b0e82 src/driver/video/lvgl.pas
|
||||
dce8755865885e41c08b062c162b06c9 src/driver/video/uidebug.pas
|
||||
20dc95321989d632fa4c39a5faf74733 src/driver/video/vesa.pas
|
||||
19c988cfcc36bcc78e73747662672d8f src/driver/video/vesa16.pas
|
||||
@@ -114,18 +114,18 @@ dee8388dac0ca79ee6aef73469d75f6b src/include/bios_data_area.pas
|
||||
717b8c0a42983f6b8864d5deda4dd532 src/include/color.pas
|
||||
1987f262a6053e02080023554d942ae1 src/include/crc.pas
|
||||
7f6c812b5d7ae1a8af5ef00d42a4eb1d src/include/fonts.pas
|
||||
bf9fe2883789147e08980ab4c43220f7 src/include/hashmap.pas
|
||||
9cc7742497cf9a1940b9d400140348a6 src/include/hashmap.pas
|
||||
513d59ae08ba6d753a871e1a82b46ed4 src/include/lists.pas
|
||||
c5ef14ac60dad5a32ebfa43da153d05c src/include/md5.pas
|
||||
124f12d75de7ade6993ccd2f02b53ad4 src/include/multiboot.pas
|
||||
1bb33ff2af8c360774d9c260f8036d2e src/include/proctypes.pas
|
||||
c3cb83dddcf53d87c14f67f5ab4bbe5e src/include/proctypes.pas
|
||||
d8beadde6ebb05c8a3e74aae57d61f34 src/include/rand.pas
|
||||
cfa50e59e4bd9ea3a5b05c6b1275858d src/include/strings.pas
|
||||
cb254f95c5e09595c90db690bf98794f src/include/system.pas
|
||||
5df11e0052010580d13f1a5ce3acd60f src/include/targa.pas
|
||||
833967cf14697db6da421a4be58e9044 src/include/texture.pas
|
||||
635e5a8936a088a244ddfe48cd658a3f src/include/types.pas
|
||||
cde48ecd2a80195da906f0d1e2658714 src/include/util.pas
|
||||
ebf13bf342b063a79345613639c9b114 src/include/util.pas
|
||||
d6a64b1434e1b528d1ba57171a9918ce src/include/data_structures/bheap.pas
|
||||
54bc51933c982219ea4445e158a7c4ee src/include/data_structures/cfifo.pas
|
||||
51628ff135cf306cb9b0a0fac24f8c73 src/include/data_structures/cfifols.pas
|
||||
@@ -144,11 +144,11 @@ e23b0bef333262860e1f68034331e529 src/isr/ioapic.pas
|
||||
f90540cb40f741dc70b1ae7435cf966b src/prog/diskcmd.pas
|
||||
cf729bd7af2f1bbb6319b3466ecb173a src/prog/diskutil.pas
|
||||
93837d26fcacbcc6e5d339de51a666ff src/prog/edit.pas
|
||||
99c3cf044d474264f7af27c1dcbeb1ca src/prog/filepicker.pas
|
||||
b2dd736b9c8b93dfae3962422a597663 src/prog/filepicker.pas
|
||||
190f559362d0ea3b0ebfdde710364fbb src/prog/inio.pas
|
||||
1ff556cd50088e3ee3efa3103fdc6ba0 src/prog/md5sum.pas
|
||||
1161e238b85f6b59debbc6a507dd9478 src/prog/meminfo.pas
|
||||
3df29f500456aa285b10cc7fd7f05cda src/prog/notepad.pas
|
||||
80c1abd52c36a13114cd952704b6f455 src/prog/notepad.pas
|
||||
cd03ccb60a3a3f0708fad6e70e2559c2 src/prog/partcmd.pas
|
||||
f47e06c6989dfb9a497b6efd024e5863 src/prog/ping.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
|
||||
`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
|
||||
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);
|
||||
PDirectory(dirElm)^:= PDirectory(buffer)[i];
|
||||
i+=1;
|
||||
@@ -535,6 +541,9 @@ begin
|
||||
for i:= 0 to LL_Size(list) - 1 do begin
|
||||
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) }
|
||||
nameLen := 8;
|
||||
while (nameLen > 0) and (dir^.fileName[nameLen - 1] = ' ') do
|
||||
|
||||
@@ -448,7 +448,7 @@ begin
|
||||
volume^.sectorCount := pvd^.volumeSpaceSizeLSB;
|
||||
volume^.freeSectors := 0;
|
||||
volume^.filesystem := @filesystem;
|
||||
volume^.isBootDrive := false;
|
||||
volume^.isBootDrive := disk^.isBootDevice;
|
||||
|
||||
volumemanager.register_volume(disk, volume);
|
||||
|
||||
|
||||
@@ -52,7 +52,15 @@ var
|
||||
storageDevices : PDList;
|
||||
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 set_boot_drive_byte(driveByte : uint8);
|
||||
function get_boot_drive_byte() : uint8;
|
||||
procedure register_device(device : PStorage_Device);
|
||||
function get_device_list() : PDList;
|
||||
function get_device_count() : uint32;
|
||||
@@ -147,7 +155,22 @@ procedure init();
|
||||
begin
|
||||
push_trace('StorageManager.init');
|
||||
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;
|
||||
|
||||
procedure register_device(device : PStorage_Device);
|
||||
@@ -163,6 +186,7 @@ begin
|
||||
device^.requestQueue := CFIFO_New(SizeOf(TIORequest), 32);
|
||||
device^.activeRequest := nil;
|
||||
device^.cachedMBR := nil;
|
||||
device^.isBootDevice := false;
|
||||
{ dispatchRead/dispatchWrite: left as-is — driver sets them before
|
||||
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 }
|
||||
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 }
|
||||
if storedDev^.maxSectorCount > 0 then
|
||||
volumemanager.discover_volumes(storedDev);
|
||||
|
||||
@@ -209,6 +209,7 @@ type
|
||||
sectorSize : uint32; //in bytes
|
||||
start : uint32; //start of device in sectors
|
||||
cachedMBR : pointer; { cached MBR data, nil if not yet read }
|
||||
isBootDevice : boolean; { true if this is the device GRUB booted from }
|
||||
end;
|
||||
|
||||
{ Filesystem driver descriptor }
|
||||
|
||||
@@ -430,6 +430,7 @@ begin
|
||||
if (dirList <> nil) and (status^ = 0) and (LL_Size(dirList) > 0) then begin
|
||||
for i := 0 to LL_Size(dirList) - 1 do begin
|
||||
entry := PDirectory_Entry(LL_Get(dirList, i));
|
||||
if (entry = nil) or (entry^.fileName = nil) then continue;
|
||||
newObj := PVFSObject(kalloc(sizeof(TVFSObject)));
|
||||
newObj^.Parent := Parent;
|
||||
newObj^.Reference := nil;
|
||||
@@ -2062,6 +2063,12 @@ begin
|
||||
syslog.writestring(' volume at ');
|
||||
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(prefix));
|
||||
kfree(void(mountPath));
|
||||
@@ -2135,6 +2142,7 @@ begin
|
||||
newVirtualDirectory('/disk');
|
||||
newVirtualDirectory('/mnt');
|
||||
newVirtualDirectory('/cfg');
|
||||
newVirtualDirectory('/boot');
|
||||
|
||||
{ Register Terminal Commands }
|
||||
stdio.registerCommand('LS', @VFS_COMMAND_LS, 'List directory contents.');
|
||||
|
||||
@@ -81,7 +81,7 @@ begin
|
||||
volume^.sectorSize := device^.sectorSize;
|
||||
volume^.freeSectors := 0;
|
||||
volume^.filesystem := nil;
|
||||
volume^.isBootDrive := false;
|
||||
volume^.isBootDrive := device^.isBootDevice;
|
||||
filesystemmanager.probe_volume(volume);
|
||||
register_volume(device, volume);
|
||||
end;
|
||||
|
||||
+27
-1
@@ -22,7 +22,12 @@ unit hashmap;
|
||||
interface
|
||||
|
||||
uses
|
||||
md5, util, strings, lmemorymanager, tracer, syslog;
|
||||
lmemorymanager,
|
||||
md5,
|
||||
strings,
|
||||
syslog,
|
||||
tracer,
|
||||
util;
|
||||
|
||||
type
|
||||
DPHashItem = ^PHashItem;
|
||||
@@ -45,12 +50,16 @@ const
|
||||
HASHMAP_DEFAULT_SIZE = 16;
|
||||
HASHMAP_DEFAULT_LOADFACTOR = 0.75;
|
||||
|
||||
type
|
||||
THashForEachCb = procedure(key: pchar; data: void; ud: void);
|
||||
|
||||
function new : PHashMap;
|
||||
function newEx(size : uint32; loadFactor : Single) : PHashMap;
|
||||
procedure add(map : PHashMap; key : pchar; value : void);
|
||||
function get(map : PHashMap; key : pchar) : void;
|
||||
procedure delete(map : PHashMap; key : pchar; freeItem : boolean);
|
||||
procedure printMap(map : PHashMap);
|
||||
procedure forEach(map : PHashMap; cb : THashForEachCb; ud : void);
|
||||
|
||||
implementation
|
||||
|
||||
@@ -257,6 +266,23 @@ begin
|
||||
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);
|
||||
var
|
||||
i,c : uint32;
|
||||
|
||||
@@ -230,6 +230,7 @@ begin
|
||||
drivermanagement.init();
|
||||
tracer.push_trace('kmain.STRMGMT');
|
||||
storagemanager.init();
|
||||
storagemanager.set_boot_drive_byte((multibootinfo^.boot_device shr 24) and $FF);
|
||||
volumemanager.init();
|
||||
filesystemmanager.init();
|
||||
|
||||
|
||||
+902
-213
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