diff --git a/src/driver/storage/IDE.pas b/src/driver/storage/IDE.pas index d9d10b32..3e6fc6ec 100644 --- a/src/driver/storage/IDE.pas +++ b/src/driver/storage/IDE.pas @@ -21,7 +21,8 @@ uses lmemorymanager, storagemanagement, strings, - tracer; + tracer, + drivemanager; type TPortMode = (P_READ, P_WRITE); @@ -267,6 +268,7 @@ var slaveDevice : TStorage_Device; buffer : puint8; i : uint8; + test : PStorage_device; begin push_trace('ide.load'); console.writestringln('[IDE] (LOAD) BEGIN'); @@ -288,14 +290,15 @@ begin exit; end; - masterDevice.hpc:= uint32(IDEDevices[0].info[3] DIV IDEDevices[0].info[1]); + // masterDevice.hpc:= uint32(IDEDevices[0].info[3] DIV IDEDevices[0].info[1]); //TODO wtf is hpc masterDevice.sectorSize:= 512; if masterDevice.maxSectorCount <> 0 then begin IDEDevices[0].exists:= true; masterDevice.readCallback:= @dread; masterDevice.writeCallback:= @dwrite; - storagemanagement.register_device(@masterDevice); + // storagemanagement.register_device(@masterDevice); + drivemanager.register_device(@masterDevice); end; end; diff --git a/src/driver/storage/MBR.pas b/src/driver/storage/MBR.pas new file mode 100644 index 00000000..37e5d544 --- /dev/null +++ b/src/driver/storage/MBR.pas @@ -0,0 +1,84 @@ +{ + Driver->Storage->MBR Master boot record + + @author(Aaron Hance ah@aaronhance.me) +} +unit mbr; + +interface + +uses + tracer; + +type + + PMaster_Boot_Record = ^TMaster_Boot_Record; + PPartition_table = ^TPartition_table; + + TPartition_table = bitpacked record + attributes : uint8; + CHS_start : array[0..2] of uint8; + system_id : uint8; + CHS_end : array[0..2] of uint8; + LBA_start : uInt32; + sector_count : uInt32; + end; + + TMaster_Boot_Record = bitpacked record + bootstrap : array[0..439] of uint8; + signature : uint32; + rsv : uint16; + partition_0 : TPartition_table; + partition_1 : TPartition_table; + partition_2 : TPartition_table; + partition_3 : TPartition_table; + boot_sector : uint16; + end; + + T24bit = array[0..2] of uint8; + + function get_bootable(partition_table : PPartition_table) : boolean; + procedure set_bootable(partition_table : PPartition_table); + procedure setup_partition(partition_table : PPartition_table; address : uint32; sectorSize : uint32); + +implementation + +{ convert LBA address to CHS address} +function LBA_2_CHS(lba : uint32) : T24bit; +var + dat : T24bit; +begin + //TODO impliment procedure + LBA_2_CHS := dat; +end; + +{ Set a partition struct to be bootable} +procedure set_bootable(partition_table : PPartition_table); +begin + push_trace('MBR.set_bootable'); + //set the bootble bit in attributes + partition_table^.attributes := (partition_table^.attributes and $80); +end; + +{ Check a partitions bootable bit } +function get_bootable(partition_table : PPartition_table) : boolean; +begin + push_trace('MBR.get_bootable'); + //get the bootble bit in attributes + get_bootable := (partition_table^.attributes and $80) = $80; +end; + +{ Setup a partition table struct } +procedure setup_partition(partition_table : PPartition_table; address : uint32; sectorSize : uint32); +begin + push_trace('MBR.setup_partition'); + //set values in both LBA and CHS addressing schemes + partition_table^.LBA_start := address; + partition_table^.sector_count := sectorSize; + partition_table^.CHS_start := LBA_2_CHS(address); + partition_table^.CHS_start := LBA_2_CHS(address + sectorSize); + push_trace('MBR.setup_partition.end'); +end; + + +end. \ No newline at end of file diff --git a/src/driver/storage/drivemanager.pas b/src/driver/storage/drivemanager.pas new file mode 100644 index 00000000..d5bc7619 --- /dev/null +++ b/src/driver/storage/drivemanager.pas @@ -0,0 +1,226 @@ +{ + Driver->Storage->DriveManager Physical storage device manager + + @author(Aaron Hance ah@aaronhance.me) +} +unit drivemanager; + +interface + +uses + util, + drivertypes, + console, + terminal, + drivermanagement, + lmemorymanager, + strings, + lists, + tracer, + rtc, + MBR, + serial; + +type + TControllerType = (ControllerIDE, ControllerUSB, ControllerAHCI, + ControllerNET, ControllerRAM, rsvctr1, rsvctr2, rsvctr3); + + PStorage_device = ^TStorage_Device; + PDrive_Error = ^TDrive_Error; + + // PPWriteHook = procedure(volume : PStorage_volume; directory : pchar; entry : PDirectory_Entry; byteCount : uint32; buffer : puint32; statusOut : puint32); + // PPReadHook = function(volume : PStorage_Volume; directory : pchar; fileName : pchar; fileExtension : pchar; buffer : puint32; bytecount : puint32) : uint32; + // PPCreateHook = procedure(disk : PStorage_Device; sectors : uint32; start : uint32; config : puint32); + // PPDetectHook = procedure(disk : PStorage_Device); + // PPCreateDirHook = procedure(volume : PStorage_volume; directory : pchar; dirname : pchar; attributes : uint32; status : puint32); + // PPReadDirHook = function(volume : PStorage_volume; directory : pchar; status : puint32) : PLinkedListBase; //returns: 0 = success, 1 = dir not exsist, 2 = not directory, 3 = error //returns: 0 = success, 1 = dir not exsist, 2 = not directory, 3 = error + PPHIOHook = procedure(drive : PStorage_device; addr : uint32; sectors : uint32; buffer : puint32); + + PPHIOHook_ = procedure; + + + { Generic storage device } + TStorage_Device = record + id : uint8; + controller : TControllerType; + controllerId0 : uint32; + writable : boolean; + volumes : PLinkedListBase; + writeCallback : PPHIOHook; + readCallback : PPHIOHook; + maxSectorCount : uint32; + sectorSize : uint32; + end; + + TDrive_Error = record + code : uint16; + description : pchar; + recoverable : boolean; + end; + +var + storageDevices : PLinkedListBase; //index in this array is global drive id + + procedure init(); + + procedure register_device(device : PStorage_Device); + function get_drive_list() : PLinkedListBase; + function controller_type_2_string(controllerType : TControllerType) : pchar; + +implementation + +procedure list_drive_command(); +var + i : uint32 = 0; +begin + push_trace('DriverManager.list_drive_command'); + //if no storage device print none found + if LL_Size(storageDevices) < 1 then begin + console.writestringlnWnd('No storage devices found.', getTerminalHWND()); + exit; + end; + + //print number of storage devices + console.writeintwnd(LL_Size(storageDevices), getTerminalHWND()); + console.writestringlnWnd(' devices found', getTerminalHWND()); + + for i:=0 to LL_Size(storageDevices)-1 do begin + + //print device id and type + console.writeintwnd(i, getTerminalHWND()); + console.writestringwnd(' - Device type: ', getTerminalHWND()); + console.writestringwnd(controller_type_2_string(PStorage_Device(LL_Get(storageDevices, i))^.controller), getTerminalHWND()); + console.writestringwnd(', ', getTerminalHWND()); + + //print device capcity + console.writestringwnd(' Capacity: ', getTerminalHWND()); + console.writeintwnd((( PStorage_Device(LL_Get(storageDevices, i))^.maxSectorCount * PStorage_Device(LL_Get(storageDevices, i))^.sectorSize) DIV 1024) DIV 1024, getTerminalHWND()); + console.writestringlnWnd('MB', getTerminalHWND()); + end; + +end; + +{ initalise a drive with a MBR - TODO needs to be expanded for partitioning } +procedure init_drive_command(driveIndex : uint32); +var + bootrecord : PMaster_Boot_Record; + partition : PPartition_table; + drive : PStorage_device; +begin + push_trace('DriverManager.init_drive_command'); + //setup MBR and partition table + bootrecord := PMaster_Boot_record(kalloc(SizeOf(TMaster_boot_record))); + partition := PPartition_table(kalloc(SizeOf(TPartition_table))); + + drive := PStorage_device(LL_Get(storageDevices, driveIndex)); + + MBR.setup_partition(partition, 100, drive^.maxSectorCount-300); + bootrecord^.partition_0 := partition^; + + //write MBR and partition table to disk + drive^.writeCallback(drive, 0, 1, puint32(bootrecord)); + + //volume_manager reload partition + //TODO + +end; + +procedure drive_command(params : PParamList); +var + i : uint16; + drive : uint16; + subcmd : pchar; +begin + push_trace('DriverManager.drive_command'); + subcmd:= getParam(0, params); + + if ((paramCount(params) = 0)) then begin + console.writestringlnWnd('Please provide valid arguments.', getTerminalHWND()); + console.writestringlnWnd(' ls - for listing all drives', getTerminalHWND()); + console.writestringlnWnd(' info [drive] - display formation for specified drive', getTerminalHWND()); + console.writestringlnWnd(' init [drive] - destructive, formats a drive with a blank partition', getTerminalHWND()); + exit; + end; + + if( stringEquals(subcmd, 'ls') ) then begin + list_drive_command(); + exit; + end; + + if( stringEquals(subcmd, 'info') ) then begin + //TODO unimplimented + exit + end; + + if( stringEquals(subcmd, 'init') ) then begin + init_drive_command(stringToInt(getParam(1, params) ) ); + exit + end; +end; + +{ Initialise the drive manager } +procedure init(); +begin + push_trace('DriveManager.init'); + + //setup drive manager + setworkingdirectory('.'); + storageDevices:= ll_new(sizeof(TStorage_Device)); + + serial.sendString('HERE I DID THE INIT WAH DU HEK BRUH!!!!!!'); + + //register DISK command + terminal.registerCommand('DISK', @drive_command, 'Disk utility'); +end; + +{ Register a new drive with the drive manager } +procedure register_device(device : PStorage_device); +var + i : uint8; + elm : void; +begin + push_trace('DriveManager.register_device'); + + //add the drive to the list of storage devices. + elm:= LL_Add(storageDevices); + PStorage_device(elm)^ := device^; //TODO memcopy + + //set drive id in struct + PStorage_device(elm)^.id := LL_Size(storageDevices) - 1; + + //create empty volume list for drive + // PStorage_Device(LL_Get(storageDevices, LL_Size(storageDevices) - 1))^.volumes := LL_New(sizeof(TStorage_Volume)); + + //TODO register with volume manager + +end; + +{ Get the drive list } +function get_drive_list() : PLinkedListBase; +begin + push_trace('DriverManager.get_drive_list'); + + //return the device list + get_drive_list:= storageDevices; +end; + +{ Get string name for controller type } +function controller_type_2_string(controllerType : TControllerType) : pchar; +begin + push_trace('DriverManager.controller_type_2_string'); + + //return string of controller type + case controllerType of + ControllerIDE : controller_type_2_string:= 'IDE'; + ControllerUSB : controller_type_2_string:= 'USB'; + ControllerAHCI : controller_type_2_string:= 'ACHI (SATA)'; + ControllerNET : controller_type_2_string:= 'Net'; + end; +end; + +function write_2_drive(drive : uint32; address : uint32; byteSize : uint32; buffer : puint32) : PDrive_Error; +begin + +end; + +end. \ No newline at end of file diff --git a/src/driver/storage/storagemanagement.pas b/src/driver/storage/storagemanagement.pas index e315a61b..84371725 100644 --- a/src/driver/storage/storagemanagement.pas +++ b/src/driver/storage/storagemanagement.pas @@ -234,7 +234,8 @@ begin fileSystems:= ll_New(sizeof(TFilesystem)); terminal.registerCommand('DISK', @disk_command, 'Disk utility'); - pop_trace(); + + end; { Register a new drive with the storage manager } diff --git a/src/driver/storage/volumemanager.pas b/src/driver/storage/volumemanager.pas new file mode 100644 index 00000000..859478ba --- /dev/null +++ b/src/driver/storage/volumemanager.pas @@ -0,0 +1,137 @@ +{ + Driver->Storage->VolumeManager Drive volume manager + + @author(Aaron Hance ah@aaronhance.me) +} +unit volumemanager; + +interface + +uses + util, + console, + drivemanager, + strings, + lists, + tracer, + vfs, + MBR; + +type + + TDirectory_Entry_Type = (directoryEntry, fileEntry, mountEntry); + + PDirectory_Entry = ^TDirectory_Entry; + PFilesystem = ^TFilesystem; + PStorage_Volume = ^TStorage_Volume; + + PPWriteHook = procedure(volume : PStorage_volume; directory : pchar; entry : PDirectory_Entry; byteCount : uint32; buffer : puint32; statusOut : puint32); + PPReadHook = function(volume : PStorage_Volume; directory : pchar; fileName : pchar; fileExtension : pchar; buffer : puint32; bytecount : puint32) : uint32; + PPHIOHook = procedure(volume : PStorage_device; addr : uint32; sectors : uint32; buffer : puint32); + PPCreateHook = procedure(disk : PStorage_Device; sectors : uint32; start : uint32; config : puint32); + PPDetectHook = procedure(disk : PStorage_Device); + PPCreateDirHook = procedure(volume : PStorage_volume; directory : pchar; dirname : pchar; attributes : uint32; status : puint32); + PPReadDirHook = function(volume : PStorage_volume; directory : pchar; status : puint32) : PLinkedListBase; //returns: 0 = success, 1 = dir not exsist, 2 = not directory, 3 = error //returns: 0 = success, 1 = dir not exsist, 2 = not directory, 3 = error + + PPHIOHook_ = procedure; + + TFilesystem = record + sName : pchar; + system_id : uint8; + writeCallback : PPWriteHook; + readCallback : PPReadHook; + createCallback : PPCreateHook; + detectCallback : PPDetectHook; + createDirCallback : PPCreateDirHook; + readDirCallback : PPReadDirHook; + end; + + TStorage_Volume = record + device : PStorage_device; + sectorStart : uint32; + sectorSize : uint32; + sectorCount : uint32; + freeSectors : uint32; + filesystem : PFilesystem; + { True if this drive contains the loaded OS } + isBootDrive : boolean; + end; + + { Generic directory entry } + TDirectory_Entry = record + { Contains filename and optionally file extension, seperated by the last period.} + fileName : pchar; + entryType : TDirectory_Entry_Type; + // creationT : TDateTime; + // modifiedT : TDateTime; + end; + +var + + storageVolumes : PLinkedListBase; + filesystems : PlinkedListBase; + + procedure init(); + + procedure register_filesystem(filesystem : PFilesystem); + procedure check_for_volumes(drive : PStorage_device); + + //IO functions + +implementation + +{ Initialise volume manager } +procedure init(); +begin + push_trace('VolumeManager.init'); + + { setup lists } + storageVolumes:= ll_New(sizeof(TFilesystem)); + filesystems:= ll_New(sizeof(TFilesystem)); +end; + +{ register a new type of filesystem } +procedure register_filesystem(filesystem : PFilesystem); //TODO on init create null filesystem for empty partition +begin + //add filesystem + + //check drives for volumes of new type +end; + +{ Check for volumes on a physical device } +procedure check_for_volumes(drive : PStorage_device); +var + bootrecord : PMaster_Boot_Record; + storageVolume : TStorage_Volume; + i : uint32 = 0; + elm : void; +begin + + drive^.readCallback(drive, 0, 1, puint32(bootrecord)); + + //TODO multipe partition entries + if bootrecord^.partition_0.LBA_start <> 0 then + begin + //set volume information + storageVolume.device := drive; + storageVolume.sectorStart := bootrecord^.partition_0.LBA_start; + storageVolume.sectorCount := bootrecord^.partition_0.sector_count; + storageVolume.freeSectors := 0; //TODO impliment + + //check for filesystem type + for i:=0 to LL_Size(filesystems) - 1 do begin + if bootrecord^.partition_0.system_id = PFilesystem(LL_Get(filesystems, i))^.system_id then + begin + storageVolume.filesystem := PFilesystem(LL_Get(filesystems, i)); + end; + end; + + //add volume to list + elm := LL_Add(storageVolumes); + memcpy(uint32(@storageVolume), uint32(elm), SizeOf(TStorage_Volume)); + + end; + +end; + +end. \ No newline at end of file diff --git a/src/kernel.pas b/src/kernel.pas index 9b40accc..fd382f0c 100644 --- a/src/kernel.pas +++ b/src/kernel.pas @@ -41,6 +41,8 @@ uses E1000, IDE, storagemanagement, + drivemanager, + volumemanager, lists, net, fat32, @@ -205,7 +207,9 @@ begin tracer.push_trace('kmain.DRVMGMT'); drivermanagement.init(); tracer.push_trace('kmain.STRMGMT'); - storagemanagement.init(); + // storagemanagement.init(); + drivemanager.init(); + volumemanager.init(); { Hook Timer for Ticks } tracer.push_trace('kmain.TMR'); @@ -213,7 +217,7 @@ begin TMR_0_ISR.hook(uint32(@bios_data_area.tick_update)); { Filsystems } - fat32.init(); + // fat32.init(); { Device Drivers } tracer.push_trace('kmain.DEVDRV');