273 lines
7.8 KiB
ObjectPascal
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. |