Asuro/src/driver/storage/drivemanager.pas

273 lines
7.8 KiB
ObjectPascal

// Copyright 2021 Aaron Hance
//
// 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->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,
volumemanager,
storagetypes;
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;
{ Disk subcommand for formatting drives }
procedure format_command(params : PParamList);
var
driveIndex : uint16;
drive : PStorage_Device;
filesystemString : pchar;
spc : puint32;
sectorCount : uint32;
volumeId : uint8;
mb : PMaster_Boot_Record;
i : uint32 = 0;
begin
//format <DRIVE_ID> <FILESYSTEM> <size>
spc:= puint32(kalloc(4));
spc^:= 1;
//get drive from index/id
driveIndex:= stringToInt( getParam(1, params) );
drive:= PStorage_Device(LL_Get(storageDevices, driveIndex));
filesystemString := getParam(2, params);
sectorCount := stringToInt( getParam(4, params) );
// if sector count is 0, use full drive
if sectorCount = 0 then begin
sectorCount := drive^.maxSectorCount - 10;
end;
//create MBR if none, and partition table
mb := PMaster_Boot_Record(kalloc(sizeof(TMaster_Boot_Record)));
drive^.readCallback(drive, 0, 1, PuInt32(mb));
//check if MBR exists
if not mb^.boot_sector = $55AA then begin
//create MBR
mb^.signature := $A570 + drive^.id;
mb^.boot_sector := $55AA;
//create partition table
mbr.setup_partition(@mb^.partition[0], 2, sectorCount);
//write MBR
drive^.writeCallback(drive, 0, 1, puint32(mb));
end;
kfree(puint32(mb));
//setup volume
volumemanager.create_volume(drive, filesystemString, 2, sectorCount);
writestringWnd('Drive ', getTerminalHWND);
writeintWnd(driveIndex, getTerminalHWND);
writestringlnWnd(' formatted.', getTerminalHWND);
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
console.writestringWnd('Disk: ', getTerminalHWND());
console.writeintlnWND(1, getTerminalHWND());
console.writestringWnd('Capacity: ', getTerminalHWND());
console.writeintlnWND(1, getTerminalHWND());
//TODO impliement
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));
//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
memcpy(uint32(device), uint32(elm), SizeOf(TStorage_Device));
//set drive id in struct
PStorage_device(elm)^.id := LL_Size(storageDevices) - 1;
//create empty volume list for drive
PStorage_device(elm)^.volumes := LL_New(sizeof(TStorage_Volume));
//TODO register with volume manager
volumemanager.check_for_volumes(PStorage_Device(elm));
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.