feat: auto-mount boot drive to /boot; fix FAT32 deleted entry triple fault
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:
Aaron committed 2026-03-07 18:58:32 +00:00
1 parent deb513c925
commit 3a733b1559
14 files changed
+1063 -310

No files matched your search

+9
View File
@@ -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
+1 -1
View File
@@ -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);
+50 -1
View File
@@ -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);
+1
View File
@@ -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 }
+8
View File
@@ -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.');
+1 -1
View File
@@ -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
View File
@@ -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;
+1
View File
@@ -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
View File
File diff suppressed because it is too large. Load diff
+21 -66
View File
File diff suppressed because it is too large. Load diff