Compare commits
24 Commits
1.1.3-alph
...
07e9095582
Author | SHA1 | Date | |
---|---|---|---|
07e9095582 | |||
72769fbef7 | |||
95599c0e7c | |||
fcaafa0d12 | |||
e490b95f1d | |||
b601080960 | |||
27177979a2 | |||
f88a282893 | |||
ff4c597ff3 | |||
24c371cab1 | |||
7588a4c9cb | |||
5cb415c76b | |||
118d8b0c03 | |||
28caca3bcc | |||
6476a774dc | |||
e791edb02a | |||
da36f6fabb | |||
97e1a18253 | |||
88a850e8fc | |||
10c9194c5f | |||
346dc4e4c9 | |||
b2eee58df4 | |||
94b477d8f7 | |||
ba38f4fd19 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -10,5 +10,3 @@
|
|||||||
/*.sh~
|
/*.sh~
|
||||||
/*.img
|
/*.img
|
||||||
src/include/asuro.pas
|
src/include/asuro.pas
|
||||||
.vscode/launch.json
|
|
||||||
.vscode
|
|
||||||
|
13
.vscode/launch.json
vendored
13
.vscode/launch.json
vendored
@ -3,18 +3,11 @@
|
|||||||
{
|
{
|
||||||
"name":"Run",
|
"name":"Run",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"type": "coreclr",
|
"type": "PowerShell",
|
||||||
"preLaunchTask": "Build",
|
"preLaunchTask": "Build",
|
||||||
"program": "VBoxSDL",
|
"script": "${workspaceFolder}/virtualbox-wrapper.ps1",
|
||||||
"args": [
|
"args": ["-MachineName", "7d395c96-891c-4139-b77d-9b6b144b0b93"],
|
||||||
"--comment",
|
|
||||||
"Asuro",
|
|
||||||
"--startvm",
|
|
||||||
"7d395c96-891c-4139-b77d-9b6b144b0b93"
|
|
||||||
],
|
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
"console": "internalConsole",
|
|
||||||
"internalConsoleOptions": "neverOpen"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
32
doc/flatfs.md
Normal file
32
doc/flatfs.md
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#Flat filesystem
|
||||||
|
|
||||||
|
A super simple filesystem for asuro. Folders are emulated in filenames.
|
||||||
|
|
||||||
|
Starts with disk info sector, sector 0 of volume
|
||||||
|
|
||||||
|
---
|
||||||
|
#### disk info
|
||||||
|
|
||||||
|
jmp2boot : ubit24;
|
||||||
|
OEMName : array[0..7] of char;
|
||||||
|
version : uint16 // numerical version of filesystem
|
||||||
|
sectorCount : uint16;
|
||||||
|
fileCount : uint16
|
||||||
|
signature : uint32 = 0x0B00B1E5
|
||||||
|
|
||||||
|
|
||||||
|
the Rest of the sector is reserved
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Starting from sector 1 is the file table. Table size is determined by entry size (64) * fileCount
|
||||||
|
|
||||||
|
---
|
||||||
|
####File entry
|
||||||
|
|
||||||
|
name : array[0..59] of char //file name max 60 chars
|
||||||
|
fileStart : 16bit // start sector of data
|
||||||
|
fileSize : 16bit // data size in sectors
|
||||||
|
|
||||||
|
---
|
||||||
|
|
26
readme.md
26
readme.md
@ -13,8 +13,8 @@ We welcome everyone to give building/breaking/fixing/shooting Asuro a go, feel f
|
|||||||
I don't think this needs an explaination.
|
I don't think this needs an explaination.
|
||||||
* [VSCode (Optional, but highly recommended)](https://code.visualstudio.com/)
|
* [VSCode (Optional, but highly recommended)](https://code.visualstudio.com/)
|
||||||
Visual Studio code is our IDE of choice, and we have a number of recommended plugins.
|
Visual Studio code is our IDE of choice, and we have a number of recommended plugins.
|
||||||
* [C# Plugin by Microsoft](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp)
|
* [PowerShell Plugin by Microsoft](https://marketplace.visualstudio.com/items?itemName=ms-vscode.powershell)
|
||||||
This plugin gives you the ability to use the 'coreclr' task type, allowing the automatic launching of virtualbox with the resulting image generated during compilation of Asuro.
|
This plugin gives you the ability to use the 'PowerShell' task type, allowing the automatic launching of virtualbox with the resulting image generated during compilation of Asuro.
|
||||||
* [VirtualBox](https://www.virtualbox.org/)
|
* [VirtualBox](https://www.virtualbox.org/)
|
||||||
Virtualbox is our Virtualisation environment of choice, don't ask why, it just is.
|
Virtualbox is our Virtualisation environment of choice, don't ask why, it just is.
|
||||||
|
|
||||||
@ -27,15 +27,15 @@ We welcome everyone to give building/breaking/fixing/shooting Asuro a go, feel f
|
|||||||
3. Install Docker for Windows.
|
3. Install Docker for Windows.
|
||||||
4. Install Git for Windows.
|
4. Install Git for Windows.
|
||||||
5. Install VSCode & the listed plugins.
|
5. Install VSCode & the listed plugins.
|
||||||
6. Install VirtualBox.
|
6. Install VirtualBox (v7+).
|
||||||
7. Clone this repository.
|
7. Clone this repository.
|
||||||
8. Run the following command in the root of the repo to build the docker image:
|
8. Run the following command in the root of the repo to build the docker image:
|
||||||
```powershell
|
```powershell
|
||||||
docker-compose build builder
|
docker compose build builder
|
||||||
```
|
```
|
||||||
9. Run the following command to compile Asuro:
|
9. Run the following command to compile Asuro:
|
||||||
```powershell
|
```powershell
|
||||||
docker-compose run builder
|
docker compose run builder
|
||||||
```
|
```
|
||||||
10. Create a new virtual machine in Virtualbox and mount the `Asuro.iso` generated in step 9 as a boot image.
|
10. Create a new virtual machine in Virtualbox and mount the `Asuro.iso` generated in step 9 as a boot image.
|
||||||
11. Add the virtualbox installation directory to your `%PATH%` environment variable, usually:
|
11. Add the virtualbox installation directory to your `%PATH%` environment variable, usually:
|
||||||
@ -57,18 +57,11 @@ We welcome everyone to give building/breaking/fixing/shooting Asuro a go, feel f
|
|||||||
{
|
{
|
||||||
"name":"Run",
|
"name":"Run",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"type": "coreclr",
|
"type": "PowerShell",
|
||||||
"preLaunchTask": "Build",
|
"preLaunchTask": "Build",
|
||||||
"program": "VBoxSDL",
|
"script": "${workspaceFolder}/virtualbox-wrapper.ps1",
|
||||||
"args": [
|
"args": ["-MachineName", "7d395c96-891c-4139-b77d-9b6b144b0b93"],
|
||||||
"--comment",
|
|
||||||
"Asuro",
|
|
||||||
"--startvm",
|
|
||||||
"<YOUR UUID HERE>"
|
|
||||||
],
|
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
"console": "internalConsole",
|
|
||||||
"internalConsoleOptions": "neverOpen"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -77,5 +70,6 @@ We welcome everyone to give building/breaking/fixing/shooting Asuro a go, feel f
|
|||||||
13. Open your project folder in VSCode, use CTRL+SHIFT+B to build & F5 to build + run in VBox.
|
13. Open your project folder in VSCode, use CTRL+SHIFT+B to build & F5 to build + run in VBox.
|
||||||
14. Congratulations! You can now play with Asuro!
|
14. Congratulations! You can now play with Asuro!
|
||||||
|
|
||||||
### Gotchas
|
### Notes & Gotchas
|
||||||
|
- The above process has been updated to be compatible with VirtualBox 7+, in which VBoxSDL was removed and vboxmanage should be used in its place. A small wrapper powershell script is used to achieve this.
|
||||||
- It was noted that Windows builds above `20H2` seem to have issues installing WSL2. We may have to wait for a patch from Microsoft to fix this. Our devs are currently using build `20H2`.
|
- It was noted that Windows builds above `20H2` seem to have issues installing WSL2. We may have to wait for a patch from Microsoft to fix this. Our devs are currently using build `20H2`.
|
@ -21,7 +21,9 @@ uses
|
|||||||
lmemorymanager,
|
lmemorymanager,
|
||||||
storagemanagement,
|
storagemanagement,
|
||||||
strings,
|
strings,
|
||||||
tracer;
|
tracer,
|
||||||
|
drivemanager,
|
||||||
|
storagetypes;
|
||||||
|
|
||||||
type
|
type
|
||||||
TPortMode = (P_READ, P_WRITE);
|
TPortMode = (P_READ, P_WRITE);
|
||||||
@ -267,6 +269,7 @@ var
|
|||||||
slaveDevice : TStorage_Device;
|
slaveDevice : TStorage_Device;
|
||||||
buffer : puint8;
|
buffer : puint8;
|
||||||
i : uint8;
|
i : uint8;
|
||||||
|
test : PStorage_device;
|
||||||
begin
|
begin
|
||||||
push_trace('ide.load');
|
push_trace('ide.load');
|
||||||
console.writestringln('[IDE] (LOAD) BEGIN');
|
console.writestringln('[IDE] (LOAD) BEGIN');
|
||||||
@ -288,14 +291,15 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
end;
|
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;
|
masterDevice.sectorSize:= 512;
|
||||||
if masterDevice.maxSectorCount <> 0 then begin
|
if masterDevice.maxSectorCount <> 0 then begin
|
||||||
IDEDevices[0].exists:= true;
|
IDEDevices[0].exists:= true;
|
||||||
masterDevice.readCallback:= @dread;
|
masterDevice.readCallback:= @dread;
|
||||||
masterDevice.writeCallback:= @dwrite;
|
masterDevice.writeCallback:= @dwrite;
|
||||||
storagemanagement.register_device(@masterDevice);
|
// storagemanagement.register_device(@masterDevice);
|
||||||
|
drivemanager.register_device(@masterDevice);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
end;
|
end;
|
||||||
@ -330,10 +334,14 @@ var
|
|||||||
device: uint8;
|
device: uint8;
|
||||||
data: uint16;
|
data: uint16;
|
||||||
begin
|
begin
|
||||||
if not validate_28bit_address(LBA) then begin
|
push_trace('IDE.readPIO28');
|
||||||
|
|
||||||
|
if not validate_28bit_address(LBA) then begin
|
||||||
console.writestringln('IDE (writePIO28) ERROR: Invalid LBA!');
|
console.writestringln('IDE (writePIO28) ERROR: Invalid LBA!');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// push_trace('IDE.readPIO28.2');
|
||||||
|
|
||||||
//Add last 4 bits of LBA to device port
|
//Add last 4 bits of LBA to device port
|
||||||
if IDEDevices[drive].isMaster then begin
|
if IDEDevices[drive].isMaster then begin
|
||||||
device:= ATA_DEVICE_MASTER;
|
device:= ATA_DEVICE_MASTER;
|
||||||
@ -344,6 +352,8 @@ begin
|
|||||||
device_select($F0 or ((LBA and $0F000000) shr 24)); //LBA primary slave
|
device_select($F0 or ((LBA and $0F000000) shr 24)); //LBA primary slave
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// push_trace('IDE.readPIO28.3');
|
||||||
|
|
||||||
no_interrupt(device);
|
no_interrupt(device);
|
||||||
port_write(ATA_REG_ERROR, 0);
|
port_write(ATA_REG_ERROR, 0);
|
||||||
|
|
||||||
@ -353,6 +363,8 @@ begin
|
|||||||
port_write(ATA_REG_LBA1, (LBA and $0000FF00) shr 8);
|
port_write(ATA_REG_LBA1, (LBA and $0000FF00) shr 8);
|
||||||
port_write(ATA_REG_LBA2, (LBA and $00FF0000) shr 16);
|
port_write(ATA_REG_LBA2, (LBA and $00FF0000) shr 16);
|
||||||
|
|
||||||
|
// push_trace('IDE.readPIO28.4');
|
||||||
|
|
||||||
//send read command
|
//send read command
|
||||||
port_write(ATA_REG_COMMAND, ATA_CMD_READ_PIO);
|
port_write(ATA_REG_COMMAND, ATA_CMD_READ_PIO);
|
||||||
if not is_ready() then exit;
|
if not is_ready() then exit;
|
||||||
@ -368,6 +380,8 @@ begin
|
|||||||
|
|
||||||
i:= i + 2;
|
i:= i + 2;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// push_trace('IDE.readPIO28.5');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure writePIO28(drive : uint8; LBA : uint32; buffer : puint8);
|
procedure writePIO28(drive : uint8; LBA : uint32; buffer : puint8);
|
||||||
@ -430,8 +444,10 @@ procedure dread(device : PStorage_device; LBA : uint32; sectorCount : uint32; bu
|
|||||||
var
|
var
|
||||||
i : uint16;
|
i : uint16;
|
||||||
begin
|
begin
|
||||||
|
push_trace('IDE.dread');
|
||||||
for i:=0 to sectorCount-1 do begin
|
for i:=0 to sectorCount-1 do begin
|
||||||
readPIO28(device^.controllerId0, LBA, puint8(@buffer[512*i]));
|
readPIO28(device^.controllerId0, LBA + i, puint8(@buffer[512*i]));
|
||||||
|
psleep(100)
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -440,7 +456,8 @@ var
|
|||||||
i : uint16;
|
i : uint16;
|
||||||
begin
|
begin
|
||||||
for i:=0 to sectorCount-1 do begin
|
for i:=0 to sectorCount-1 do begin
|
||||||
writePIO28(device^.controllerId0, LBA, puint8(@buffer[512*i]));
|
writePIO28(device^.controllerId0, LBA + i, puint8(@buffer[512*i]));
|
||||||
|
psleep(100)
|
||||||
end;
|
end;
|
||||||
// writePIO28(device^.controllerId0, LBA, puint8(buffer));
|
// writePIO28(device^.controllerId0, LBA, puint8(buffer));
|
||||||
end;
|
end;
|
||||||
|
81
src/driver/storage/MBR.pas
Normal file
81
src/driver/storage/MBR.pas
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
{
|
||||||
|
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 : array[0..3] of 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.
|
305
src/driver/storage/drivemanager.pas
Normal file
305
src/driver/storage/drivemanager.pas
Normal file
@ -0,0 +1,305 @@
|
|||||||
|
// 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
|
||||||
|
push_trace('DriverManager.format_command');
|
||||||
|
|
||||||
|
//format <DRIVE_ID> <FILESYSTEM> <size>
|
||||||
|
|
||||||
|
spc:= puint32(kalloc(4));
|
||||||
|
spc^:= 1;
|
||||||
|
|
||||||
|
push_trace('DriverManager.format_command.0');
|
||||||
|
|
||||||
|
//get drive from index/id
|
||||||
|
driveIndex:= stringToInt( getParam(1, params) );
|
||||||
|
drive:= PStorage_Device(LL_Get(storageDevices, driveIndex));
|
||||||
|
|
||||||
|
filesystemString := getParam(2, params);
|
||||||
|
sectorCount := stringToInt( getParam(3, 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)*2));
|
||||||
|
memset(uint32(mb), 0, sizeof(TMaster_Boot_Record));
|
||||||
|
drive^.readCallback(drive, 0, 1, PuInt32(mb));
|
||||||
|
|
||||||
|
//check if MBR exists
|
||||||
|
if (mb^.boot_sector <> $55AA)then begin
|
||||||
|
|
||||||
|
writestringlnWND('Creating MBR', getTerminalHWND());
|
||||||
|
|
||||||
|
//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 else begin
|
||||||
|
|
||||||
|
writestringlnWND('MBR already exists', getTerminalHWND());
|
||||||
|
|
||||||
|
//write first partiton sectorStart and sectorCount
|
||||||
|
writeintlnWND(mb^.partition[0].LBA_start, getTerminalHWND());
|
||||||
|
writeintlnWND(mb^.partition[0].sector_count, getTerminalHWND());
|
||||||
|
|
||||||
|
//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);
|
||||||
|
push_trace('DriverManager.drive_command.0');
|
||||||
|
|
||||||
|
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());
|
||||||
|
console.writestringlnWnd(' format [drive] [filesystem] [size (0 for max)] - destructive, formats a drive with MBR and volume', getTerminalHWND());
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
push_trace('DriverManager.drive_command.1');
|
||||||
|
|
||||||
|
if( stringEquals(subcmd, 'ls') ) then begin
|
||||||
|
list_drive_command();
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
push_trace('DriverManager.drive_command.2');
|
||||||
|
|
||||||
|
if( stringEquals(subcmd, 'info') ) then begin
|
||||||
|
console.writestringWnd('Disk: ', getTerminalHWND());
|
||||||
|
console.writeintlnWND(1, getTerminalHWND());
|
||||||
|
|
||||||
|
console.writestringWnd('Capacity: ', getTerminalHWND());
|
||||||
|
console.writeintlnWND(1, getTerminalHWND());
|
||||||
|
//TODO impliment
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if( stringEquals(subcmd, 'init') ) then begin
|
||||||
|
init_drive_command(stringToInt(getParam(1, params) ) );
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
push_trace('DriverManager.drive_command.3');
|
||||||
|
|
||||||
|
if( stringEquals(subcmd, 'format') ) then begin
|
||||||
|
format_command(params);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
push_trace('DriverManager.drive_command.4');
|
||||||
|
|
||||||
|
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.
|
@ -10,14 +10,16 @@ interface
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
console,
|
console,
|
||||||
storagemanagement,
|
util,
|
||||||
util, terminal,
|
terminal,
|
||||||
lmemorymanager,
|
lmemorymanager,
|
||||||
strings,
|
strings,
|
||||||
lists,
|
lists,
|
||||||
tracer,
|
tracer,
|
||||||
serial,
|
serial,
|
||||||
rtc;
|
rtc,
|
||||||
|
volumemanager,
|
||||||
|
storagetypes;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
@ -89,7 +91,7 @@ var
|
|||||||
filesystem : TFilesystem;
|
filesystem : TFilesystem;
|
||||||
|
|
||||||
procedure init;
|
procedure init;
|
||||||
procedure create_volume(disk : PStorage_Device; sectors : uint32; start : uint32; config : puint32);
|
procedure create_volume(volume : PStorage_Volume; sectors : uint32; start : uint32; config : puint32);
|
||||||
procedure detect_volumes(disk : PStorage_Device);
|
procedure detect_volumes(disk : PStorage_Device);
|
||||||
//function writeDirectory(volume : PStorage_volume; directory : pchar; attributes : uint32) : uint8; // need to handle parent table cluster overflow, need to take attributes
|
//function writeDirectory(volume : PStorage_volume; directory : pchar; attributes : uint32) : uint8; // need to handle parent table cluster overflow, need to take attributes
|
||||||
//function readDirectory(volume : PStorage_volume; directory : pchar; listPtr : PLinkedListBase) : uint8; //returns: 0 = success, 1 = dir not exsist, 2 = not directory, 3 = error
|
//function readDirectory(volume : PStorage_volume; directory : pchar; listPtr : PLinkedListBase) : uint8; //returns: 0 = success, 1 = dir not exsist, 2 = not directory, 3 = error
|
||||||
@ -751,7 +753,7 @@ end;
|
|||||||
|
|
||||||
//TODO check directory commands for errors with a clean disk
|
//TODO check directory commands for errors with a clean disk
|
||||||
|
|
||||||
procedure create_volume(disk : PStorage_Device; sectors : uint32; start : uint32; config : puint32);
|
procedure create_volume(volume : PStorage_Volume; sectors : uint32; start : uint32; config : puint32);
|
||||||
var
|
var
|
||||||
buffer : puint32;
|
buffer : puint32;
|
||||||
bt: puint32;
|
bt: puint32;
|
||||||
@ -772,9 +774,18 @@ var
|
|||||||
programFileArray : byteArray8 = ('P','R','O','G','R','A','M','S');
|
programFileArray : byteArray8 = ('P','R','O','G','R','A','M','S');
|
||||||
rootCluster : uint32 = 1;
|
rootCluster : uint32 = 1;
|
||||||
|
|
||||||
|
sysArray : byteArray8 = ('S','Y','S','T','E','M',' ',' ');
|
||||||
|
progArray : byteArray8 = ('P','R','O','G','R','A','M','S');
|
||||||
|
userArray : byteArray8 = ('U','S','E','R',' ',' ',' ',' ');
|
||||||
|
|
||||||
|
status : puint32;
|
||||||
|
disk : PStorage_device;
|
||||||
|
|
||||||
begin //maybe increase buffer size by one?
|
begin //maybe increase buffer size by one?
|
||||||
push_trace('fat32.create_volume()');
|
push_trace('fat32.create_volume()');
|
||||||
|
|
||||||
|
disk := volume^.device;
|
||||||
|
|
||||||
// zeroBuffer:= puint32(kalloc( disk^.sectorSize * 4 ));
|
// zeroBuffer:= puint32(kalloc( disk^.sectorSize * 4 ));
|
||||||
// memset(uint32(zeroBuffer), 0, disk^.sectorSize * 4);
|
// memset(uint32(zeroBuffer), 0, disk^.sectorSize * 4);
|
||||||
|
|
||||||
@ -811,7 +822,7 @@ begin //maybe increase buffer size by one?
|
|||||||
bootRecord^.jmp2boot := $0; //TODO impliment boot jump
|
bootRecord^.jmp2boot := $0; //TODO impliment boot jump
|
||||||
bootRecord^.OEMName := asuroArray;
|
bootRecord^.OEMName := asuroArray;
|
||||||
bootRecord^.sectorSize := disk^.sectorsize;
|
bootRecord^.sectorSize := disk^.sectorsize;
|
||||||
bootRecord^.spc := config^;
|
bootRecord^.spc := 1;
|
||||||
bootRecord^.rsvSectors := 32; //32 is standard
|
bootRecord^.rsvSectors := 32; //32 is standard
|
||||||
bootRecord^.numFats := 1;
|
bootRecord^.numFats := 1;
|
||||||
bootRecord^.mediaDescp := $F8;
|
bootRecord^.mediaDescp := $F8;
|
||||||
@ -873,8 +884,16 @@ begin //maybe increase buffer size by one?
|
|||||||
|
|
||||||
disk^.writecallback(disk, dataStart + (config^ * rootCluster), 1, buffer);
|
disk^.writecallback(disk, dataStart + (config^ * rootCluster), 1, buffer);
|
||||||
|
|
||||||
|
memset(uint32(buffer), 0, disk^.sectorsize);
|
||||||
|
|
||||||
|
status := puint32(kalloc(sizeof(uint32)));
|
||||||
|
writeDirectory(volume, '', sysArray, $10, status, '');
|
||||||
|
|
||||||
|
|
||||||
kfree(buffer);
|
kfree(buffer);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure detect_volumes(disk : PStorage_Device);
|
procedure detect_volumes(disk : PStorage_Device);
|
||||||
@ -903,11 +922,11 @@ begin
|
|||||||
if (puint32(buffer)[127] = $55AA) and (PBootRecord(buffer)^.bsignature = $29) then begin //TODO partition table
|
if (puint32(buffer)[127] = $55AA) and (PBootRecord(buffer)^.bsignature = $29) then begin //TODO partition table
|
||||||
console.writestringln('FAT32: volume found!');
|
console.writestringln('FAT32: volume found!');
|
||||||
volume^.device:= disk;
|
volume^.device:= disk;
|
||||||
volume^.sectorStart:= 1;
|
volume^.sectorStart:= 1; //THIS MAKE SURE IF NOT FUCKY, cos im getting info from 2
|
||||||
volume^.sectorSize:= PBootRecord(buffer)^.sectorSize;
|
volume^.sectorSize:= PBootRecord(buffer)^.sectorSize;
|
||||||
volume^.freeSectors:= 1000000; //TODO implement get free sectors need FSINFO implemented first
|
volume^.freeSectors:= 1000000; //TODO implement get free sectors need FSINFO implemented first
|
||||||
volume^.filesystem := @filesystem;
|
volume^.filesystem := @filesystem;
|
||||||
storagemanagement.register_volume(disk, volume);
|
// storagemanagement.register_volume(disk, volume); TODO repalce with new thing
|
||||||
end;
|
end;
|
||||||
|
|
||||||
kfree(buffer);
|
kfree(buffer);
|
||||||
@ -917,6 +936,7 @@ procedure init();
|
|||||||
begin
|
begin
|
||||||
push_trace('fat32.init()');
|
push_trace('fat32.init()');
|
||||||
filesystem.sName:= 'FAT32';
|
filesystem.sName:= 'FAT32';
|
||||||
|
filesystem.system_id:= $01;
|
||||||
filesystem.readDirCallback:= @readDirectoryGen;
|
filesystem.readDirCallback:= @readDirectoryGen;
|
||||||
filesystem.createDirCallback:= @writeDirectoryGen;
|
filesystem.createDirCallback:= @writeDirectoryGen;
|
||||||
filesystem.createcallback:= @create_volume;
|
filesystem.createcallback:= @create_volume;
|
||||||
@ -924,7 +944,7 @@ begin
|
|||||||
filesystem.writecallback:= @writeFile;
|
filesystem.writecallback:= @writeFile;
|
||||||
filesystem.readcallback := @readFile;
|
filesystem.readcallback := @readFile;
|
||||||
|
|
||||||
storagemanagement.register_filesystem(@filesystem);
|
volumemanager.register_filesystem(@filesystem);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
725
src/driver/storage/flatfs.pas
Normal file
725
src/driver/storage/flatfs.pas
Normal file
@ -0,0 +1,725 @@
|
|||||||
|
// 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->flatfs super simple flat filesystem
|
||||||
|
|
||||||
|
@author(Aaron Hance ah@aaronhance.me)
|
||||||
|
}
|
||||||
|
|
||||||
|
unit flatfs;
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
tracer,
|
||||||
|
strings,
|
||||||
|
volumemanager,
|
||||||
|
lists,
|
||||||
|
console,
|
||||||
|
terminal,
|
||||||
|
storagetypes,
|
||||||
|
lmemorymanager,
|
||||||
|
util;
|
||||||
|
|
||||||
|
type
|
||||||
|
|
||||||
|
TDisk_Info = bitpacked record
|
||||||
|
jmp2boot: ubit24;
|
||||||
|
OEMName: array[0..7] of char;
|
||||||
|
version: uint16;
|
||||||
|
sectorCount : uint16;
|
||||||
|
fileCount : uint16;
|
||||||
|
signature : uint32;
|
||||||
|
end;
|
||||||
|
PDisk_Info = ^TDisk_Info;
|
||||||
|
|
||||||
|
TFile_Entry = bitpacked record
|
||||||
|
attribues : uint8; // 0x00 = does not exsist, 0x01 = file, 0x02 = hidden, 0x04 = system/read only, 0x10 = directory, 0x20 = archive
|
||||||
|
name: array[0..53] of char; //max file name length is 54
|
||||||
|
rsv : uint8;
|
||||||
|
size: uint32;
|
||||||
|
start : uint32;
|
||||||
|
end;
|
||||||
|
PFile_Entry = ^TFile_Entry;
|
||||||
|
|
||||||
|
var
|
||||||
|
filesystem : TFilesystem;
|
||||||
|
|
||||||
|
|
||||||
|
procedure init;
|
||||||
|
procedure create_volume(volume : PStorage_Volume; sectors : uint32; start : uint32; config : puint32);
|
||||||
|
procedure detect_volumes(disk : PStorage_Device);
|
||||||
|
function read_directory(volume : PStorage_Volume; directory : pchar; status : PuInt32) : PLinkedListBase;
|
||||||
|
procedure write_directory(volume : PStorage_Volume; directory : pchar; status : PuInt32);
|
||||||
|
procedure write_file(volume : PStorage_Volume; fileName : pchar; data : PuInt32; size : uint32; status : PuInt32);
|
||||||
|
procedure read_file(volume : PStorage_Volume; fileName : pchar; data : PuInt32; status : PuInt32);
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
procedure create_volume(volume : PStorage_Volume; sectors : uint32; start : uint32; config : puint32);
|
||||||
|
var
|
||||||
|
info : PDisk_Info;
|
||||||
|
entryTable : PFile_Entry;
|
||||||
|
i : uint32;
|
||||||
|
|
||||||
|
directories : PLinkedListBase;
|
||||||
|
status : PuInt32;
|
||||||
|
|
||||||
|
data : pchar;
|
||||||
|
|
||||||
|
const
|
||||||
|
asuroArray : array[0..7] of char = 'ASURO';
|
||||||
|
systemArray : array[0..6] of char = '/system';
|
||||||
|
programsArray : array[0..8] of char = '/programs';
|
||||||
|
userArray : array[0..4] of char = '/user';
|
||||||
|
|
||||||
|
testArray : array[0..23] of char = 'ASURO TEST DATA ARRAY';
|
||||||
|
begin
|
||||||
|
|
||||||
|
info := PDisk_Info(Kalloc(512));
|
||||||
|
memset(uint32(info), 0, 512);
|
||||||
|
|
||||||
|
info^.jmp2boot := $0;
|
||||||
|
info^.OEMName := asuroArray;
|
||||||
|
info^.version := 1;
|
||||||
|
info^.sectorCount := sectors;
|
||||||
|
info^.fileCount := 1000;
|
||||||
|
info^.signature := $0B00B1E5;
|
||||||
|
|
||||||
|
if config^ <> 0 then begin
|
||||||
|
info^.fileCount := config^;
|
||||||
|
end;
|
||||||
|
|
||||||
|
volume^.device^.writeCallback(volume^.device, start, 1, PuInt32(info));// what happens if buffer is smaller than 512?
|
||||||
|
|
||||||
|
// create file table
|
||||||
|
entryTable := PFile_Entry(Kalloc(126 * 512));
|
||||||
|
memset(uint32(entryTable), 0, 126 * 512);
|
||||||
|
|
||||||
|
//create system folders
|
||||||
|
entryTable[0].attribues := $10;
|
||||||
|
memcpy(uint32(@systemArray), uint32(@entryTable[0].name), 7);
|
||||||
|
entryTable[0].size := 0;
|
||||||
|
entryTable[0].start := 0;
|
||||||
|
|
||||||
|
entryTable[1].attribues := $10;
|
||||||
|
memcpy(uint32(@programsArray), uint32(@entryTable[1].name), 9);
|
||||||
|
entryTable[1].size := 0;
|
||||||
|
entryTable[1].start := 0;
|
||||||
|
|
||||||
|
entryTable[2].attribues := $10;
|
||||||
|
memcpy(uint32(@userArray), uint32(@entryTable[2].name), 5);
|
||||||
|
entryTable[2].size := 0;
|
||||||
|
entryTable[2].start := 0;
|
||||||
|
|
||||||
|
//write file table
|
||||||
|
volume^.device^.writeCallback(volume^.device, start + 1, ((sizeof(TFile_Entry) * info^.fileCount) div 512), puint32(entryTable));
|
||||||
|
//volume^.device^.writeCallback(volume^.device, start + 1, 1, puint32(entryTable));
|
||||||
|
|
||||||
|
//temp read
|
||||||
|
status := PuInt32(Kalloc(sizeof(uint32)));
|
||||||
|
// directories := read_directory(volume, '/', status);
|
||||||
|
|
||||||
|
data := stringNew(1024);
|
||||||
|
memset(uint32(data), 0, 513);
|
||||||
|
memcpy(uint32(@testArray), uint32(data), 23);
|
||||||
|
|
||||||
|
write_directory(volume, '/logs', status);
|
||||||
|
write_directory(volume, '/logs/test', status);
|
||||||
|
write_file(volume, '/logs/log.txt', PuInt32(data), 1, status);
|
||||||
|
write_file(volume, '/logs/log2.txt', PuInt32(data), 1, status);
|
||||||
|
write_file(volume, '/logs/log3.txt', PuInt32(data), 1, status);
|
||||||
|
read_directory(volume, '/logs', status);
|
||||||
|
|
||||||
|
kfree(puint32(data));
|
||||||
|
|
||||||
|
read_file(volume, '/logs/log.txt', PuInt32(data), status);
|
||||||
|
writestringlnWND(pchar(data), getterminalhwnd());
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure write_directory(volume : PStorage_Volume; directory : pchar; status : PuInt32);
|
||||||
|
var
|
||||||
|
directories : PLinkedListBase;
|
||||||
|
i : uint32;
|
||||||
|
|
||||||
|
fileEntries : PFile_Entry;
|
||||||
|
|
||||||
|
fileEntry : PFile_Entry;
|
||||||
|
buffer : PuInt32;
|
||||||
|
|
||||||
|
position : uint32;
|
||||||
|
offset : uint32;
|
||||||
|
|
||||||
|
const
|
||||||
|
fileCount : uint32 = 1000;
|
||||||
|
begin
|
||||||
|
status^ := 0;
|
||||||
|
|
||||||
|
//directories := read_directory(volume, directory, status);
|
||||||
|
|
||||||
|
fileEntries := PFile_Entry(Kalloc(sizeof(TFile_Entry) * fileCount + 512));
|
||||||
|
memset(uint32(fileEntries), 0, sizeof(TFile_Entry) * fileCount + 512);
|
||||||
|
|
||||||
|
volume^.device^.readCallback(volume^.device, volume^.sectorStart + 1, (sizeof(TFile_Entry) * fileCount) div 512, PuInt32(fileEntries));
|
||||||
|
|
||||||
|
if status^ = 0 then begin
|
||||||
|
for i := 0 to fileCount - 1 do begin
|
||||||
|
|
||||||
|
push_trace('write_directory_2');
|
||||||
|
|
||||||
|
//fileEntry := PFile_Entry(STRLL_Get(directories, i));
|
||||||
|
fileEntry := @fileEntries[i];
|
||||||
|
|
||||||
|
if fileEntry^.attribues = 0 then begin
|
||||||
|
fileEntry^.attribues := $10;
|
||||||
|
fileEntry^.size := 0;
|
||||||
|
fileEntry^.start := 0;
|
||||||
|
memcpy(uint32(directory), uint32(@fileEntry^.name), stringSize(directory));
|
||||||
|
|
||||||
|
push_trace('write_directory_3');
|
||||||
|
|
||||||
|
//write file table
|
||||||
|
buffer := PuInt32(Kalloc(513));
|
||||||
|
memset(uint32(buffer), 0, 512);
|
||||||
|
|
||||||
|
push_trace('write_directory.b4_read');
|
||||||
|
|
||||||
|
//read file table cointaining entry of interest
|
||||||
|
position := (i * sizeof(TFile_Entry)) div 512;
|
||||||
|
volume^.device^.readCallback(volume^.device, volume^.sectorStart + 1 + position, 1, buffer);
|
||||||
|
|
||||||
|
push_trace('write_directory.after_read');
|
||||||
|
|
||||||
|
//calculate entry offset into sector
|
||||||
|
offset := (i * sizeof(TFile_Entry)) mod 512;
|
||||||
|
offset := offset div sizeof(TFile_Entry);
|
||||||
|
|
||||||
|
//set entry in buffer
|
||||||
|
PFile_Entry(buffer)[offset] := fileEntry^;
|
||||||
|
|
||||||
|
//write updated file table sector
|
||||||
|
volume^.device^.writeCallback(volume^.device, volume^.sectorStart + 1 + position, 1, buffer);
|
||||||
|
|
||||||
|
Kfree(buffer);
|
||||||
|
|
||||||
|
push_trace('write_directory.after_write');
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if fileEntry^.attribues = 0 then begin
|
||||||
|
status^ := 1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
function read_directory(volume : PStorage_Volume; directory : pchar; status : PuInt32) : PLinkedListBase;
|
||||||
|
var
|
||||||
|
directories : PLinkedListBase;
|
||||||
|
fileEntrys : PFile_Entry;
|
||||||
|
i : uint32;
|
||||||
|
|
||||||
|
compString : PChar;
|
||||||
|
afterString : PChar;
|
||||||
|
slash : PChar;
|
||||||
|
compStringLength : uint32;
|
||||||
|
|
||||||
|
fileCount : uint32 = 1000;
|
||||||
|
|
||||||
|
slashArray : array[0..1] of char = '/';
|
||||||
|
|
||||||
|
begin
|
||||||
|
compString := pchar(kalloc(60));
|
||||||
|
memset(uint32(compString), 0, 60);
|
||||||
|
|
||||||
|
afterString := pchar(kalloc(60));
|
||||||
|
memset(uint32(afterString), 0, 60);
|
||||||
|
|
||||||
|
slash := stringNew(2);
|
||||||
|
memcpy(uint32(@slashArray), uint32(slash), 1);
|
||||||
|
|
||||||
|
directories := STRLL_New();
|
||||||
|
|
||||||
|
fileEntrys := PFile_Entry(Kalloc(sizeof(TFile_Entry) * fileCount + 512));
|
||||||
|
volume^.device^.readCallback(volume^.device, volume^.sectorStart + 1, sizeof(TFile_Entry) * fileCount div 512, puint32(fileEntrys));
|
||||||
|
|
||||||
|
for i := 0 to fileCount - 1 do begin
|
||||||
|
|
||||||
|
if uint32(fileEntrys[i].name[0]) = 0 then begin
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
compString := stringSub(fileEntrys[i].name, 0, stringSize(directory));
|
||||||
|
afterString := stringSub(fileEntrys[i].name, stringSize(directory), stringSize(fileEntrys[i].name)-1);
|
||||||
|
|
||||||
|
writestringlnWND(afterString, getterminalhwnd());
|
||||||
|
|
||||||
|
push_trace('read_directory_2');
|
||||||
|
|
||||||
|
if stringEquals(compString, directory) and
|
||||||
|
(not stringContains(afterString, slash)) then begin
|
||||||
|
|
||||||
|
writestringlnWND(fileEntrys[i].name, getterminalhwnd());
|
||||||
|
STRLL_Add(directories, afterString);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
push_trace('read_directory_3');
|
||||||
|
|
||||||
|
Kfree(puint32(fileEntrys));
|
||||||
|
|
||||||
|
read_directory := directories;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure quicksort_start(list : PFile_Entry; begining : uint32; stop : uint32);
|
||||||
|
var
|
||||||
|
pivot : uint32;
|
||||||
|
i : uint32;
|
||||||
|
j : uint32;
|
||||||
|
temp : PLinkedListBase;
|
||||||
|
|
||||||
|
tempFileEntry : PFile_Entry;
|
||||||
|
begin
|
||||||
|
|
||||||
|
tempFileEntry := PFile_Entry(Kalloc(sizeof(TFile_Entry)));
|
||||||
|
memset(uint32(tempFileEntry), 0, sizeof(TFile_Entry));
|
||||||
|
|
||||||
|
i:=begining;
|
||||||
|
j:=stop;
|
||||||
|
|
||||||
|
pivot := list[(begining + stop) div 2].start;
|
||||||
|
|
||||||
|
while i <= j do begin
|
||||||
|
while list[i].start < pivot do begin
|
||||||
|
i := i + 1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
while list[j].start > pivot do begin
|
||||||
|
j := j - 1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if i <= j then begin
|
||||||
|
tempFileEntry^ := list[i];
|
||||||
|
list[i] := list[j];
|
||||||
|
list[j] := tempFileEntry^;
|
||||||
|
|
||||||
|
i := i + 1;
|
||||||
|
j := j - 1;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if begining < j then begin
|
||||||
|
quicksort_start(list, begining, j);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if i < stop then begin
|
||||||
|
quicksort_start(list, i, stop);
|
||||||
|
end;
|
||||||
|
|
||||||
|
Kfree(puint32(tempFileEntry));
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
function find_free_space(volume : PStorage_Volume; size : uint32; status : PuInt32) : uint32;
|
||||||
|
var
|
||||||
|
fileEntrys : PFile_Entry;
|
||||||
|
confirmedFileEntrys : PFile_Entry;
|
||||||
|
confirmedFileEntrysCount : uint32 = 0;
|
||||||
|
fileEntry : PFile_Entry;
|
||||||
|
i : uint32;
|
||||||
|
fileCount : uint32 = 1000;
|
||||||
|
|
||||||
|
baseAddress : uint32;
|
||||||
|
begin
|
||||||
|
fileEntrys := PFile_Entry(Kalloc(sizeof(TFile_Entry) * fileCount + 512));
|
||||||
|
confirmedFileEntrys := PFile_Entry(Kalloc(sizeof(TFile_Entry) * fileCount + 512));
|
||||||
|
memset(uint32(fileEntrys), 0, sizeof(TFile_Entry) * fileCount + 512);
|
||||||
|
memset(uint32(confirmedFileEntrys), 0, sizeof(TFile_Entry) * fileCount + 512);
|
||||||
|
|
||||||
|
volume^.device^.readCallback(volume^.device, volume^.sectorStart + 1, sizeof(TFile_Entry) * fileCount div 512, puint32(fileEntrys));
|
||||||
|
|
||||||
|
baseAddress := volume^.sectorStart + 2 + ( (fileCount * sizeof(TFile_Entry)) div 512);
|
||||||
|
|
||||||
|
for i := 0 to fileCount - 1 do begin
|
||||||
|
if fileEntrys[i].attribues <> 0 then begin
|
||||||
|
confirmedFileEntrys[confirmedFileEntrysCount] := fileEntrys[i];
|
||||||
|
confirmedFileEntrysCount := confirmedFileEntrysCount + 1;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
//sort file table by start address using quicksort
|
||||||
|
quicksort_start(confirmedFileEntrys, 0, confirmedFileEntrysCount - 1);
|
||||||
|
|
||||||
|
//find free space big enough to fit size //TODO: make this work
|
||||||
|
for i := 0 to confirmedFileEntrysCount - 1 do begin
|
||||||
|
|
||||||
|
if confirmedFileEntrys[i+1].attribues = 0 then begin
|
||||||
|
|
||||||
|
if confirmedFileEntrys[i].size = 0 then begin
|
||||||
|
find_free_space := baseAddress;
|
||||||
|
break;
|
||||||
|
end else begin
|
||||||
|
find_free_space := confirmedFileEntrys[i].start + confirmedFileEntrys[i].size;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if confirmedFileEntrys[i].size <> 0 then begin
|
||||||
|
if confirmedFileEntrys[i+1].start - (confirmedFileEntrys[i].start + confirmedFileEntrys[i].size) > size+1 then begin
|
||||||
|
find_free_space := confirmedFileEntrys[i].start + confirmedFileEntrys[i].size;
|
||||||
|
status^ := 0;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Kfree(puint32(fileEntrys));
|
||||||
|
Kfree(puint32(confirmedFileEntrys));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure write_file(volume : PStorage_Volume; fileName : pchar; data : PuInt32; size : uint32; status : PuInt32);
|
||||||
|
var
|
||||||
|
directories : PLinkedListBase;
|
||||||
|
i : uint32;
|
||||||
|
p : uint32;
|
||||||
|
|
||||||
|
fileEntries : PFile_Entry;
|
||||||
|
fileEntry : PFile_Entry;
|
||||||
|
buffer : PuInt32;
|
||||||
|
|
||||||
|
position : uint32;
|
||||||
|
offset : uint32;
|
||||||
|
|
||||||
|
fileCount : uint32 = 1000;
|
||||||
|
|
||||||
|
exsists : boolean;
|
||||||
|
|
||||||
|
elm : puint32;
|
||||||
|
begin
|
||||||
|
push_trace('flatfs.write_file');
|
||||||
|
|
||||||
|
//load file table
|
||||||
|
fileEntries := PFile_Entry(Kalloc(sizeof(TFile_Entry) * fileCount + 512));
|
||||||
|
memset(uint32(fileEntries), 0, sizeof(TFile_Entry) * fileCount);
|
||||||
|
|
||||||
|
volume^.device^.readCallback(volume^.device, volume^.sectorStart + 1, sizeof(TFile_Entry) * fileCount div 512, puint32(fileEntries));
|
||||||
|
|
||||||
|
//check if file exists else find free entry
|
||||||
|
for i := 0 to fileCount - 1 do begin
|
||||||
|
|
||||||
|
if stringEquals(fileEntries[i].name, fileName) then begin
|
||||||
|
exsists := true;
|
||||||
|
p:= i;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if fileEntries[i].attribues = 0 then begin
|
||||||
|
exsists := false;
|
||||||
|
p:= i;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
//if entry is directory then exit
|
||||||
|
if fileEntries[p].attribues and $10 = $10 then begin
|
||||||
|
status^ := 1;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// //read file table cointaining entry of interest
|
||||||
|
position := (p * sizeof(TFile_Entry)) div 512;
|
||||||
|
|
||||||
|
//if file exists update entry else create new entry
|
||||||
|
if exsists then begin
|
||||||
|
//check if size is greater than current size
|
||||||
|
if size > fileEntries[p].size then begin
|
||||||
|
//find free space
|
||||||
|
fileEntries[p].start := find_free_space(volume, size, status);
|
||||||
|
fileEntries[p].size := size;
|
||||||
|
end else begin
|
||||||
|
//update size
|
||||||
|
fileEntries[p].size := size;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end else begin
|
||||||
|
//find free space
|
||||||
|
fileEntries[p].start := find_free_space(volume, size, status);
|
||||||
|
fileEntries[p].size := size;
|
||||||
|
fileEntries[p].attribues := $01;
|
||||||
|
|
||||||
|
//add file name
|
||||||
|
memcpy(uint32(fileName), uint32(@fileEntries[p].name), 14);
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
//write file table
|
||||||
|
volume^.device^.writeCallback(volume^.device, volume^.sectorStart + 1 , 1, puint32(@fileEntries[position]));
|
||||||
|
|
||||||
|
//write file
|
||||||
|
volume^.device^.writeCallback(volume^.device, fileEntries[p].start, size, data);
|
||||||
|
|
||||||
|
//free buffer
|
||||||
|
Kfree(puint32(fileEntries));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure read_file(volume : PStorage_Volume; fileName : pchar; data : PuInt32; status : PuInt32);
|
||||||
|
var
|
||||||
|
directories : PLinkedListBase;
|
||||||
|
i : uint32;
|
||||||
|
p : uint32;
|
||||||
|
|
||||||
|
fileEntries : PFile_Entry;
|
||||||
|
fileEntry : PFile_Entry;
|
||||||
|
|
||||||
|
fileCount : uint32 = 1000;
|
||||||
|
exsists : boolean = false;
|
||||||
|
|
||||||
|
size : uint32;
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
//load file table
|
||||||
|
fileEntries := PFile_Entry(Kalloc(sizeof(TFile_Entry) * fileCount + 512));
|
||||||
|
memset(uint32(fileEntries), 0, sizeof(TFile_Entry) * fileCount);
|
||||||
|
|
||||||
|
volume^.device^.readCallback(volume^.device, volume^.sectorStart + 1, sizeof(TFile_Entry) * fileCount div 512, puint32(fileEntries));
|
||||||
|
|
||||||
|
//check if file exists else exit
|
||||||
|
for i := 0 to fileCount - 1 do begin
|
||||||
|
|
||||||
|
if stringEquals(fileEntries[i].name, fileName) then begin
|
||||||
|
exsists := true;
|
||||||
|
p:= i;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
//if entry is directory then exit
|
||||||
|
if fileEntries[p].attribues and $10 = $10 then begin
|
||||||
|
status^ := 1;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
//if entry is not found exit
|
||||||
|
if fileEntries[i].attribues = 0 then begin
|
||||||
|
exsists := false;
|
||||||
|
p:= i;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
//file size rounded up to nearest 512
|
||||||
|
size := (fileEntries[p].size + 511) and -512;
|
||||||
|
|
||||||
|
//read file
|
||||||
|
data := Kalloc(size);
|
||||||
|
volume^.device^.readCallback(volume^.device, fileEntries[p].start, size, data);
|
||||||
|
|
||||||
|
//free buffer
|
||||||
|
Kfree(puint32(fileEntries));
|
||||||
|
|
||||||
|
status^ := 0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure detect_volumes(disk : PStorage_Device);
|
||||||
|
var
|
||||||
|
buffer : puint32;
|
||||||
|
volume : PStorage_volume;
|
||||||
|
begin
|
||||||
|
push_trace('flatfs.detectVolumes()');
|
||||||
|
|
||||||
|
volume:= PStorage_volume(kalloc(sizeof(TStorage_Volume)));
|
||||||
|
//check first address for MBR
|
||||||
|
//if found then add volume and use info to see if there is another volume
|
||||||
|
buffer := puint32(kalloc(512));
|
||||||
|
memset(uint32(buffer), 0, 512);
|
||||||
|
disk^.readcallback(disk, 2, 1, buffer);
|
||||||
|
|
||||||
|
|
||||||
|
if (PDisk_Info(buffer)^.signature = $0B00B1E5) then begin
|
||||||
|
console.writestringln('FlatFS: volume found!');
|
||||||
|
volume^.device:= disk;
|
||||||
|
volume^.sectorStart:= 2;
|
||||||
|
volume^.sectorSize:= 512;
|
||||||
|
volume^.sectorCount:= PDisk_Info(buffer)^.sectorCount;
|
||||||
|
volume^.freeSectors:= 1000000; //TODO implement get free sectors need FSINFO implemented first
|
||||||
|
volume^.filesystem := @filesystem;
|
||||||
|
volume^.isBootDrive := false;
|
||||||
|
|
||||||
|
// storagemanagement.register_volume(disk, volume); TODO repalce with new thing
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
kfree(buffer);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure delete_file(volume : PStorage_Volume; fileName : pchar; status : PuInt32);
|
||||||
|
var
|
||||||
|
directories : PLinkedListBase;
|
||||||
|
i : uint32;
|
||||||
|
p : uint32;
|
||||||
|
|
||||||
|
fileEntries : PFile_Entry;
|
||||||
|
fileEntry : PFile_Entry;
|
||||||
|
zeroBuffer : PuInt32;
|
||||||
|
|
||||||
|
position : uint32;
|
||||||
|
offset : uint32;
|
||||||
|
|
||||||
|
fileCount : uint32 = 1000;
|
||||||
|
|
||||||
|
exsists : boolean;
|
||||||
|
begin
|
||||||
|
|
||||||
|
//load file table
|
||||||
|
fileEntries := PFile_Entry(Kalloc(sizeof(TFile_Entry) * fileCount + 512));
|
||||||
|
memset(uint32(fileEntries), 0, sizeof(TFile_Entry) * fileCount);
|
||||||
|
|
||||||
|
volume^.device^.readCallback(volume^.device, volume^.sectorStart + 1, sizeof(TFile_Entry) * fileCount div 512, puint32(fileEntries));
|
||||||
|
|
||||||
|
//check if file exists else exit
|
||||||
|
for i := 0 to fileCount - 1 do begin
|
||||||
|
|
||||||
|
if stringEquals(fileEntries[i].name, fileName) then begin
|
||||||
|
exsists := true;
|
||||||
|
p:= i;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
//set position of entry
|
||||||
|
position := (p * sizeof(TFile_Entry)) div 512;
|
||||||
|
|
||||||
|
//if entry is directory then exit
|
||||||
|
if fileEntries[p].attribues and $10 = $10 then begin
|
||||||
|
status^ := 1;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
//if entry is not found exit
|
||||||
|
if fileEntries[i].attribues = 0 then begin
|
||||||
|
exsists := false;
|
||||||
|
p:= i;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
//zero out file
|
||||||
|
zeroBuffer := Kalloc(fileEntries[p].size);
|
||||||
|
memset(uint32(zeroBuffer), 0, fileEntries[p].size);
|
||||||
|
|
||||||
|
//write file
|
||||||
|
volume^.device^.writeCallback(volume^.device, fileEntries[p].start, fileEntries[p].size, zeroBuffer);
|
||||||
|
|
||||||
|
//free buffer
|
||||||
|
Kfree(puint32(zeroBuffer));
|
||||||
|
|
||||||
|
//zero out file table
|
||||||
|
memset(uint32(@fileEntries[p]), 0, sizeof(TFile_Entry));
|
||||||
|
|
||||||
|
//write file table
|
||||||
|
volume^.device^.writeCallback(volume^.device, volume^.sectorStart + 1 , 1, puint32(@fileEntries[position]));
|
||||||
|
|
||||||
|
//free buffer
|
||||||
|
Kfree(puint32(fileEntries));
|
||||||
|
|
||||||
|
status^ := 0;
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure delete_directory(volume : PStorage_Volume; directoryName : pchar; status : PuInt32);
|
||||||
|
var
|
||||||
|
directories : PLinkedListBase;
|
||||||
|
i : uint32;
|
||||||
|
p : uint32;
|
||||||
|
|
||||||
|
fileEntries : PFile_Entry;
|
||||||
|
fileEntry : PFile_Entry;
|
||||||
|
zeroBuffer : PuInt32;
|
||||||
|
|
||||||
|
position : uint32;
|
||||||
|
offset : uint32;
|
||||||
|
|
||||||
|
fileCount : uint32 = 1000;
|
||||||
|
|
||||||
|
exsists : boolean;
|
||||||
|
begin
|
||||||
|
|
||||||
|
//load file table
|
||||||
|
fileEntries := PFile_Entry(Kalloc(sizeof(TFile_Entry) * fileCount + 512));
|
||||||
|
memset(uint32(fileEntries), 0, sizeof(TFile_Entry) * fileCount);
|
||||||
|
|
||||||
|
volume^.device^.readCallback(volume^.device, volume^.sectorStart + 1, sizeof(TFile_Entry) * fileCount div 512, puint32(fileEntries));
|
||||||
|
|
||||||
|
//check if file exists else exit
|
||||||
|
|
||||||
|
for i := 0 to fileCount - 1 do begin
|
||||||
|
|
||||||
|
if stringEquals(fileEntries[i].name, directoryName) then begin
|
||||||
|
exsists := true;
|
||||||
|
p:= i;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
//if entry is not directory then exit
|
||||||
|
if fileEntries[i].attribues and $10 <> $10 then begin
|
||||||
|
status^ := 1;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
//calculate position of directory in file table
|
||||||
|
position := (p * sizeof(TFile_Entry)) div 512;
|
||||||
|
|
||||||
|
//zero file table
|
||||||
|
memset(uint32(@fileEntries[p]), 0, sizeof(TFile_Entry));
|
||||||
|
|
||||||
|
//write file table
|
||||||
|
volume^.device^.writeCallback(volume^.device, volume^.sectorStart + 1 , 1, puint32(@fileEntries[position]));
|
||||||
|
|
||||||
|
//free buffer
|
||||||
|
Kfree(puint32(fileEntries));
|
||||||
|
|
||||||
|
status^ := 0;
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure init();
|
||||||
|
begin
|
||||||
|
push_trace('flatfs.init()');
|
||||||
|
filesystem.sName:= 'flatfs';
|
||||||
|
filesystem.system_id:= $02;
|
||||||
|
filesystem.readDirCallback:= @read_directory;
|
||||||
|
// filesystem.createDirCallback:= @writeDirectoryGen;
|
||||||
|
filesystem.createcallback:= @create_volume;
|
||||||
|
filesystem.detectcallback:= @detect_volumes;
|
||||||
|
// filesystem.writecallback:= @writeFile;
|
||||||
|
// filesystem.readcallback := @readFile;
|
||||||
|
// filesystem.formatVolumeCallback := @create_volume;
|
||||||
|
|
||||||
|
volumemanager.register_filesystem(@filesystem);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
end.
|
@ -15,6 +15,8 @@
|
|||||||
{
|
{
|
||||||
Driver->Storage->StorageManagment Storage Managment System
|
Driver->Storage->StorageManagment Storage Managment System
|
||||||
|
|
||||||
|
DEPRECATED unit
|
||||||
|
|
||||||
@author(Aaron Hance ah@aaronhance.me)
|
@author(Aaron Hance ah@aaronhance.me)
|
||||||
}
|
}
|
||||||
unit storagemanagement;
|
unit storagemanagement;
|
||||||
@ -31,14 +33,14 @@ uses
|
|||||||
strings,
|
strings,
|
||||||
lists,
|
lists,
|
||||||
tracer,
|
tracer,
|
||||||
rtc;
|
rtc,
|
||||||
|
MBR,
|
||||||
|
volumemanager,
|
||||||
|
storagetypes;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
TControllerType = (ControllerIDE, ControllerUSB, ControllerAHCI, ControllerNET, ControllerRAM, rsvctr1, rsvctr2, rsvctr3);
|
|
||||||
TDirectory_Entry_Type = (directoryEntry, fileEntry, mountEntry);
|
TDirectory_Entry_Type = (directoryEntry, fileEntry, mountEntry);
|
||||||
PStorage_volume = ^TStorage_Volume;
|
|
||||||
PStorage_device = ^TStorage_Device;
|
|
||||||
APStorage_Volume = array[0..10] of PStorage_volume;
|
APStorage_Volume = array[0..10] of PStorage_volume;
|
||||||
byteArray8 = array[0..7] of char;
|
byteArray8 = array[0..7] of char;
|
||||||
PByteArray8 = ^byteArray8;
|
PByteArray8 = ^byteArray8;
|
||||||
@ -54,41 +56,6 @@ type
|
|||||||
|
|
||||||
PPHIOHook_ = procedure;
|
PPHIOHook_ = procedure;
|
||||||
|
|
||||||
TFilesystem = record
|
|
||||||
sName : pchar;
|
|
||||||
writeCallback : PPWriteHook;
|
|
||||||
readCallback : PPReadHook;
|
|
||||||
createCallback : PPCreateHook;
|
|
||||||
detectCallback : PPDetectHook;
|
|
||||||
createDirCallback : PPCreateDirHook;
|
|
||||||
readDirCallback : PPReadDirHook;
|
|
||||||
end;
|
|
||||||
PFileSystem = ^TFilesystem;
|
|
||||||
|
|
||||||
TStorage_Volume = record
|
|
||||||
device : PStorage_device;
|
|
||||||
sectorStart : uint32;
|
|
||||||
sectorSize : uint32;
|
|
||||||
freeSectors : uint32;
|
|
||||||
filesystem : PFilesystem;
|
|
||||||
{ True if this drive contains the loaded OS }
|
|
||||||
isBootDrive : boolean;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ Generic storage device }
|
|
||||||
TStorage_Device = record
|
|
||||||
idx : uint8;
|
|
||||||
controller : TControllerType;
|
|
||||||
controllerId0 : uint32;
|
|
||||||
maxSectorCount : uint32;
|
|
||||||
sectorSize : uint32;
|
|
||||||
writable : boolean;
|
|
||||||
volumes : PLinkedListBase;
|
|
||||||
writeCallback : PPHIOHook;
|
|
||||||
readCallback : PPHIOHook;
|
|
||||||
hpc : uint16;
|
|
||||||
spt : uint16;
|
|
||||||
end;
|
|
||||||
APStorage_Device = array[0..255] of PStorage_device;
|
APStorage_Device = array[0..255] of PStorage_device;
|
||||||
|
|
||||||
{ Generic directory entry }
|
{ Generic directory entry }
|
||||||
@ -110,14 +77,6 @@ procedure init();
|
|||||||
procedure register_device(device : PStorage_Device);
|
procedure register_device(device : PStorage_Device);
|
||||||
function get_device_list() : PLinkedListBase;
|
function get_device_list() : PLinkedListBase;
|
||||||
|
|
||||||
procedure register_filesystem(filesystem : PFilesystem);
|
|
||||||
|
|
||||||
procedure register_volume(device : PStorage_Device; volume : PStorage_Volume);
|
|
||||||
//function writeNewFile(fileName : pchar; extension : pchar; buffer : puint32; size : uint32) : uint32;
|
|
||||||
//function readFile(fileName : pchar; extension : pchar; buffer : puint32; byteCount : puint32) : puint32;
|
|
||||||
|
|
||||||
//TODO write partition table
|
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
function controller_type_2_string(controllerType : TControllerType) : pchar;
|
function controller_type_2_string(controllerType : TControllerType) : pchar;
|
||||||
@ -169,18 +128,57 @@ var
|
|||||||
drive : PStorage_Device;
|
drive : PStorage_Device;
|
||||||
|
|
||||||
filesystemString : pchar;
|
filesystemString : pchar;
|
||||||
filesystem : PFileSystem;
|
|
||||||
spc : puint32;
|
spc : puint32;
|
||||||
|
|
||||||
|
sectorCount : uint32;
|
||||||
|
volumeId : uint8;
|
||||||
|
|
||||||
|
mb : PMaster_Boot_Record;
|
||||||
|
i : uint32 = 0;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
|
||||||
|
//format <DRIVE_ID> <FILESYSTEM> <size>
|
||||||
|
|
||||||
spc:= puint32(kalloc(4));
|
spc:= puint32(kalloc(4));
|
||||||
spc^:= 4;
|
spc^:= 1;
|
||||||
|
|
||||||
driveIndex:= stringToInt( getParam(1, params) );
|
driveIndex:= stringToInt( getParam(1, params) );
|
||||||
drive:= PStorage_Device(LL_Get(storageDevices, driveIndex));
|
drive:= PStorage_Device(LL_Get(storageDevices, driveIndex));
|
||||||
|
|
||||||
//todo change b4 adding in aniother filesytem
|
filesystemString := getParam(2, params);
|
||||||
PFilesystem(LL_Get(filesystems, 0))^.createCallback(drive, drive^.maxSectorCount-1, 1, spc);
|
|
||||||
|
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);
|
writestringWnd('Drive ', getTerminalHWND);
|
||||||
writeintWnd(driveIndex, getTerminalHWND);
|
writeintWnd(driveIndex, getTerminalHWND);
|
||||||
@ -217,10 +215,6 @@ begin
|
|||||||
format_command(params);
|
format_command(params);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
//lsfs command for listing filesystems
|
|
||||||
if stringEquals(subcmd, 'lsfs') then begin
|
|
||||||
end;
|
|
||||||
|
|
||||||
pop_trace();
|
pop_trace();
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -231,10 +225,8 @@ begin
|
|||||||
|
|
||||||
setworkingdirectory('.');
|
setworkingdirectory('.');
|
||||||
storageDevices:= ll_new(sizeof(TStorage_Device));
|
storageDevices:= ll_new(sizeof(TStorage_Device));
|
||||||
fileSystems:= ll_New(sizeof(TFilesystem));
|
|
||||||
terminal.registerCommand('DISK', @disk_command, 'Disk utility');
|
terminal.registerCommand('DISK', @disk_command, 'Disk utility');
|
||||||
|
|
||||||
pop_trace();
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Register a new drive with the storage manager }
|
{ Register a new drive with the storage manager }
|
||||||
@ -253,9 +245,7 @@ begin
|
|||||||
PStorage_Device(LL_Get(storageDevices, LL_Size(storageDevices) - 1))^.volumes := LL_New(sizeof(TStorage_Volume));
|
PStorage_Device(LL_Get(storageDevices, LL_Size(storageDevices) - 1))^.volumes := LL_New(sizeof(TStorage_Volume));
|
||||||
|
|
||||||
//check for volumes
|
//check for volumes
|
||||||
for i:=0 to ll_size(filesystems) - 1 do begin
|
|
||||||
PFileSystem(LL_Get(filesystems, i))^.detectCallback(PStorage_Device(LL_Get(storageDevices, LL_Size(storageDevices) - 1)));
|
|
||||||
end;
|
|
||||||
|
|
||||||
pop_trace();
|
pop_trace();
|
||||||
end;
|
end;
|
||||||
@ -265,23 +255,4 @@ begin
|
|||||||
get_device_list:= storageDevices;
|
get_device_list:= storageDevices;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure register_filesystem(filesystem : PFilesystem);
|
|
||||||
var
|
|
||||||
elm : void;
|
|
||||||
begin
|
|
||||||
elm:= LL_Add(fileSystems);
|
|
||||||
PFileSystem(elm)^ := filesystem^;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure register_volume(device : PStorage_Device; volume : PStorage_Volume);
|
|
||||||
var
|
|
||||||
elm : void;
|
|
||||||
begin
|
|
||||||
push_trace('storagemanagement.register_volume');
|
|
||||||
elm := LL_Add(device^.volumes);
|
|
||||||
PStorage_volume(elm)^:= volume^;
|
|
||||||
|
|
||||||
if rootVolume = PStorage_Volume(0) then rootVolume:= volume;
|
|
||||||
end;
|
|
||||||
|
|
||||||
end.
|
end.
|
64
src/driver/storage/storagetypes.pas
Normal file
64
src/driver/storage/storagetypes.pas
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// 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->Include->storagetypes - Structs & Data Shared Across Storage Drivers.
|
||||||
|
|
||||||
|
@author(Aaron Hance <ah@aaronhance.me>)
|
||||||
|
}
|
||||||
|
unit storagetypes;
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
lists;
|
||||||
|
|
||||||
|
type
|
||||||
|
|
||||||
|
TControllerType = (ControllerIDE, ControllerUSB, ControllerAHCI,
|
||||||
|
ControllerNET, ControllerRAM, rsvctr1, rsvctr2, rsvctr3);
|
||||||
|
|
||||||
|
PStorage_device = ^TStorage_Device;
|
||||||
|
PDrive_Error = ^TDrive_Error;
|
||||||
|
|
||||||
|
PPHIOHook = procedure(drive : PStorage_device; addr : uint32; sectors : uint32; buffer : puint32);
|
||||||
|
PPHIOHook_ = procedure;
|
||||||
|
|
||||||
|
byteArray8 = array[0..7] of char;
|
||||||
|
PByteArray8 = ^byteArray8;
|
||||||
|
|
||||||
|
{ 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;
|
||||||
|
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
|
||||||
|
end.
|
429
src/driver/storage/volumemanager.pas
Normal file
429
src/driver/storage/volumemanager.pas
Normal file
@ -0,0 +1,429 @@
|
|||||||
|
// 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->VolumeManager Drive volume manager
|
||||||
|
|
||||||
|
@author(Aaron Hance ah@aaronhance.me)
|
||||||
|
}
|
||||||
|
unit volumemanager;
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
util,
|
||||||
|
console,
|
||||||
|
terminal,
|
||||||
|
strings,
|
||||||
|
lists,
|
||||||
|
tracer,
|
||||||
|
lmemorymanager,
|
||||||
|
vfs,
|
||||||
|
MBR,
|
||||||
|
storagetypes;
|
||||||
|
|
||||||
|
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(volume : PStorage_volume; start : uint32; size : 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; //create volume
|
||||||
|
detectCallback : PPDetectHook; //detect volume
|
||||||
|
createDirCallback : PPCreateDirHook;
|
||||||
|
readDirCallback : PPReadDirHook;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TStorage_Volume = record
|
||||||
|
volumeHandle : uint32;
|
||||||
|
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;
|
||||||
|
|
||||||
|
TFilehandleEntry = record
|
||||||
|
volume : PStorage_Volume;
|
||||||
|
fileName : pchar;
|
||||||
|
fileHandle : uint32;
|
||||||
|
openMode : TOpenMode;
|
||||||
|
writeMode : TWriteMode;
|
||||||
|
lock : Boolean;
|
||||||
|
closed : Boolean;
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
PFilehandleEntry = ^TFilehandleEntry;
|
||||||
|
|
||||||
|
var
|
||||||
|
|
||||||
|
storageVolumes : PLinkedListBase;
|
||||||
|
filesystems : PlinkedListBase;
|
||||||
|
|
||||||
|
fileHandles : PLinkedListBase;
|
||||||
|
|
||||||
|
{ Returns the number of volumes }
|
||||||
|
|
||||||
|
procedure init();
|
||||||
|
|
||||||
|
procedure register_filesystem(filesystem : PFilesystem);
|
||||||
|
procedure check_for_volumes(drive : PStorage_device);
|
||||||
|
procedure create_volume(disk : PStorage_device; filesystem : PChar; sectorStart : uint32; sectorCount : uint32);
|
||||||
|
|
||||||
|
//IO functions
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
procedure format_volume_command(params : PParamList);
|
||||||
|
var
|
||||||
|
volume : PStorage_Volume;
|
||||||
|
filesystem : PFilesystem;
|
||||||
|
config : puint32;
|
||||||
|
begin
|
||||||
|
push_trace('VolumeManager.format_volume_command');
|
||||||
|
console.writestringlnWND('Not implimented, use disk format', getTerminalHWND());
|
||||||
|
exit;
|
||||||
|
|
||||||
|
if paramCount(params) < 3 then begin
|
||||||
|
console.writestringlnWND('Invalid arguments', getTerminalHWND());
|
||||||
|
end;
|
||||||
|
push_trace('VolumeManager.format_volume_command.1');
|
||||||
|
|
||||||
|
volume := PStorage_volume(LL_get(storageVolumes, stringToInt(getParam(1, params))));
|
||||||
|
filesystem := PFilesystem(LL_get(filesystems, stringToInt(getParam(2, params))));
|
||||||
|
push_trace('VolumeManager.format_volume_command.2');
|
||||||
|
|
||||||
|
config := PuInt32(kalloc(sizeof(uInt32)));
|
||||||
|
config^ := 4;
|
||||||
|
push_trace('VolumeManager.format_volume_command.3');
|
||||||
|
|
||||||
|
//TODO check things exsist
|
||||||
|
|
||||||
|
console.writestringlnWND('Staring volume formatting...', getTerminalHWND());
|
||||||
|
// filesystem^.formatVolumeCallback(volume^.device, volume^.sectorSize, volume^.sectorStart, config);
|
||||||
|
console.writestringlnWND('Volume format finished.', getTerminalHWND());
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure list_filesystems_command();
|
||||||
|
var
|
||||||
|
i : uint32;
|
||||||
|
filesystem : PFilesystem;
|
||||||
|
begin
|
||||||
|
push_trace('VolumeManager.list_filesystems_command');
|
||||||
|
|
||||||
|
if LL_Size(filesystems) < 1 then begin
|
||||||
|
console.writestringlnWnd('ERROR: no filesystems found!', getTerminalHWND());
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
console.writestringlnWnd('Filesystems: ', getTerminalHWND());
|
||||||
|
|
||||||
|
for i:=0 to LL_Size(filesystems) - 1 do begin
|
||||||
|
filesystem := PFilesystem(LL_Get(filesystems, i));
|
||||||
|
|
||||||
|
console.writestringWnd(' ', getTerminalHWND());
|
||||||
|
console.writestringWnd(filesystem^.sName, getTerminalHWND());
|
||||||
|
console.writestringWnd(' - ', getTerminalHWND());
|
||||||
|
console.writehexlnWND(filesystem^.system_id, getTerminalHWND());
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure list_volume_command();
|
||||||
|
var
|
||||||
|
i : uint32;
|
||||||
|
volume : PStorage_Volume;
|
||||||
|
begin
|
||||||
|
push_trace('VolumeManager.list_volume_command');
|
||||||
|
|
||||||
|
if LL_Size(storageVolumes) < 1 then begin
|
||||||
|
console.writestringlnWnd('No volumes found.', getTerminalHWND());
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
console.writestringlnWnd('Volumes: ', getTerminalHWND());
|
||||||
|
|
||||||
|
for i:=0 to LL_Size(storageVolumes) - 1 do begin
|
||||||
|
volume := PStorage_Volume(LL_Get(storageVolumes, i));
|
||||||
|
|
||||||
|
console.writestringWnd(' ', getTerminalHWND());
|
||||||
|
console.writeintWnd(i, getTerminalHWND());
|
||||||
|
console.writestringWnd(' - Capacity: ', getTerminalHWND());
|
||||||
|
console.writeintWnd(uint32((volume^.sectorSize * volume^.sectorCount) DIV 1024 DIV 1024), getTerminalHWND());
|
||||||
|
console.writestringWnd('MB, Filesystem: ', getTerminalHWND());
|
||||||
|
|
||||||
|
if volume^.filesystem <> nil then begin
|
||||||
|
console.writestringlnWnd(volume^.filesystem^.sName, getTerminalHWND());
|
||||||
|
end else begin
|
||||||
|
console.writestringlnWnd('None', getTerminalHWND());
|
||||||
|
end;
|
||||||
|
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure volume_command(params : PParamList);
|
||||||
|
var
|
||||||
|
i : uint16;
|
||||||
|
subcmd : pchar;
|
||||||
|
begin
|
||||||
|
push_trace('VolumeManager.volume_command');
|
||||||
|
subcmd:= getParam(0, params);
|
||||||
|
|
||||||
|
if ((paramCount(params) = 0)) then begin
|
||||||
|
console.writestringlnWnd('Please provide valid arguments.', getTerminalHWND());
|
||||||
|
console.writestringlnWnd(' ls - for listing all volumes', getTerminalHWND());
|
||||||
|
console.writestringlnWnd(' lsfs - for listing all filesystems', getTerminalHWND());
|
||||||
|
console.writestringlnWnd(' info [volume] - display formation for specified volume', getTerminalHWND());
|
||||||
|
console.writestringlnWnd(' format [volume] [filesystem] - destructive, formats a volume with a specified filesystem', getTerminalHWND());
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if( stringEquals(subcmd, 'ls') ) then begin
|
||||||
|
list_volume_command();
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if( stringEquals(subcmd, 'lsfs') ) then begin
|
||||||
|
list_filesystems_command();
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if( stringEquals(subcmd, 'format') ) then begin
|
||||||
|
format_volume_command(params);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ Initialise volume manager }
|
||||||
|
procedure init();
|
||||||
|
begin
|
||||||
|
push_trace('VolumeManager.init');
|
||||||
|
|
||||||
|
{ setup lists }
|
||||||
|
storageVolumes:= ll_New(sizeof(TFilesystem));
|
||||||
|
filesystems:= ll_New(sizeof(TFilesystem));
|
||||||
|
fileHandles:= ll_New(sizeof(TFilehandleEntry));
|
||||||
|
|
||||||
|
{ register commands }
|
||||||
|
|
||||||
|
terminal.registerCommand('volume', @volume_command, 'Volume utility');
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ register a new type of filesystem }
|
||||||
|
procedure register_filesystem(filesystem : PFilesystem); //TODO on init create null filesystem for empty partition
|
||||||
|
var
|
||||||
|
elm : void;
|
||||||
|
begin
|
||||||
|
//add filesystem
|
||||||
|
elm := LL_add(filesystems);
|
||||||
|
memcpy(uint32(filesystem), uInt32(elm), SizeOf(TFilesystem));
|
||||||
|
|
||||||
|
//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
|
||||||
|
push_trace('VolumeManager.check_for_volumes');
|
||||||
|
|
||||||
|
bootrecord := PMaster_Boot_Record(kalloc(SizeOf(TMaster_Boot_Record)));
|
||||||
|
drive^.readCallback(drive, 0, 1, puint32(bootrecord)); //TODO multiple drives
|
||||||
|
|
||||||
|
//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.sectorSize := drive^.sectorSize;
|
||||||
|
storageVolume.freeSectors := 0; //TODO impliment
|
||||||
|
storageVolume.filesystem := nil;
|
||||||
|
|
||||||
|
if LL_Size(filesystems) < 1 then begin
|
||||||
|
console.writestringln('Failed to initalise storage system, no filesystems found, stopping!');
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
//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;
|
||||||
|
push_trace('VolumeManager.init3');
|
||||||
|
|
||||||
|
//add volume to list
|
||||||
|
elm := LL_Add(storageVolumes);
|
||||||
|
memcpy(uint32(@storageVolume), uint32(elm), SizeOf(TStorage_Volume));
|
||||||
|
push_trace('VolumeManager.init4');
|
||||||
|
|
||||||
|
elm := LL_Add(drive^.volumes);
|
||||||
|
memcpy(uint32(@storageVolume), uint32(elm), SizeOf(TStorage_Volume));
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure remove_volume(list : PLinkedListBase; volume : PStorage_Volume);
|
||||||
|
var
|
||||||
|
i : uint32;
|
||||||
|
elm : void;
|
||||||
|
begin
|
||||||
|
|
||||||
|
for i:=0 to LL_Size(list) - 1 do begin
|
||||||
|
elm := LL_Get(list, i);
|
||||||
|
if (PStorage_Volume(elm)^.device = volume^.device)
|
||||||
|
and (PStorage_Volume(elm)^.sectorStart = volume^.sectorStart) then begin
|
||||||
|
LL_Delete(list, i);
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure create_volume(disk : PStorage_device; filesystem : PChar; sectorStart : uint32; sectorCount : uint32);
|
||||||
|
var
|
||||||
|
volume : PStorage_Volume;
|
||||||
|
elm : void;
|
||||||
|
i : uint16;
|
||||||
|
config : PuInt32;
|
||||||
|
begin
|
||||||
|
|
||||||
|
push_trace('VolumeManager.create_volume');
|
||||||
|
|
||||||
|
volume := PStorage_Volume(kalloc(SizeOf(TStorage_Volume)));
|
||||||
|
volume^.device := disk;
|
||||||
|
volume^.sectorStart := sectorStart;
|
||||||
|
volume^.sectorCount := sectorCount - 10;
|
||||||
|
volume^.sectorSize := disk^.sectorSize;
|
||||||
|
volume^.freeSectors := 0; //setup by filesystem
|
||||||
|
|
||||||
|
//find filesystem
|
||||||
|
for i:=0 to LL_Size(filesystems) - 1 do begin
|
||||||
|
if stringEquals(filesystem, PFilesystem(LL_Get(filesystems, i))^.sName) then begin
|
||||||
|
volume^.filesystem := PFilesystem(LL_Get(filesystems, i));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
//TODO CHECK FILESYSTEM EXSISTS
|
||||||
|
|
||||||
|
//format volume
|
||||||
|
volume^.filesystem^.createCallback(volume, sectorCount, sectorStart, config);
|
||||||
|
|
||||||
|
push_trace('VolumeManager.create_volume.2');
|
||||||
|
|
||||||
|
//remove volume from list of volumes
|
||||||
|
remove_volume(storageVolumes, volume);
|
||||||
|
|
||||||
|
//add volume to list
|
||||||
|
elm := LL_Add(storageVolumes);
|
||||||
|
memcpy(uint32(volume), uint32(elm), SizeOf(TStorage_Volume));
|
||||||
|
|
||||||
|
push_trace('VolumeManager.create_volume.3');
|
||||||
|
|
||||||
|
//remove volume from list of volumes on device
|
||||||
|
remove_volume(disk^.volumes, volume);
|
||||||
|
|
||||||
|
//add volume to device
|
||||||
|
elm := LL_Add(disk^.volumes);
|
||||||
|
memcpy(uint32(volume), uint32(elm), SizeOf(TStorage_Volume));
|
||||||
|
|
||||||
|
//free memory
|
||||||
|
kfree(puint32(volume));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure register_volume(device : PStorage_Device; volume : PStorage_Volume);
|
||||||
|
var
|
||||||
|
elm : void;
|
||||||
|
begin
|
||||||
|
push_trace('storagemanagement.register_volume');
|
||||||
|
elm := LL_Add(device^.volumes);
|
||||||
|
PStorage_volume(elm)^:= volume^;
|
||||||
|
|
||||||
|
// if rootVolume = PStorage_Volume(0) then rootVolume:= volume;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure openFile(Handle : uint32; Filename : PChar; OpenMode : TOpenMode; WriteMode : TWriteMode; lock : boolean; Error : PError);
|
||||||
|
var
|
||||||
|
fileHandleEntree : PFilehandleEntry;
|
||||||
|
fileHandle : uInt32;
|
||||||
|
i : uint32;
|
||||||
|
elm : void;
|
||||||
|
begin
|
||||||
|
push_trace('VolumeManager.openFile');
|
||||||
|
|
||||||
|
//check if file is already open and if it is locked, if openmode is not read only
|
||||||
|
if OpenMode <> omReadOnly then begin
|
||||||
|
for i:=0 to LL_Size(fileHandles) - 1 do begin
|
||||||
|
elm := LL_Get(fileHandles, i);
|
||||||
|
if stringEquals(PFilehandleEntry(elm)^.filename, Filename) then begin
|
||||||
|
if PFilehandleEntry(elm)^.lock and (not PFilehandleEntry(elm)^.closed) then begin
|
||||||
|
Error^ := eFileInUse;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
//create filehandleentry
|
||||||
|
fileHandleEntree := PFilehandleEntry(kalloc(SizeOf(TFilehandleEntry)));
|
||||||
|
fileHandleEntree^.fileName := Filename;
|
||||||
|
fileHandleEntree^.openMode := OpenMode;
|
||||||
|
fileHandleEntree^.writeMode := WriteMode;
|
||||||
|
fileHandleEntree^.lock := lock;
|
||||||
|
fileHandleEntree^.closed := false;
|
||||||
|
|
||||||
|
//create filehandle
|
||||||
|
fileHandle := LL_Size(fileHandles);
|
||||||
|
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
end.
|
@ -16,6 +16,7 @@
|
|||||||
Include->Strings - String Manipulation.
|
Include->Strings - String Manipulation.
|
||||||
|
|
||||||
@author(Kieron Morris <kjm@kieronmorris.me>)
|
@author(Kieron Morris <kjm@kieronmorris.me>)
|
||||||
|
@author(Aaron Hance <ah@aaronhance.me>)
|
||||||
}
|
}
|
||||||
unit strings;
|
unit strings;
|
||||||
|
|
||||||
@ -33,6 +34,10 @@ function stringCopy(str : pchar) : pchar;
|
|||||||
function stringNew(size : uint32) : pchar;
|
function stringNew(size : uint32) : pchar;
|
||||||
function stringSize(str : pchar) : uint32;
|
function stringSize(str : pchar) : uint32;
|
||||||
function stringConcat(str1, str2 : pchar) : pchar;
|
function stringConcat(str1, str2 : pchar) : pchar;
|
||||||
|
function stringTrim(str : pchar; length : uint32) : pchar;
|
||||||
|
function stringSub(str : pchar; start, size : uint32) : pchar;
|
||||||
|
function stringReplace(str, find, replace : pchar) : pchar;
|
||||||
|
function stringIndexOf(str, find : pchar) : sint32;
|
||||||
function stringContains(str : pchar; sub : pchar) : boolean;
|
function stringContains(str : pchar; sub : pchar) : boolean;
|
||||||
function stringToInt(str : pchar) : uint32;
|
function stringToInt(str : pchar) : uint32;
|
||||||
function hexStringToInt(str : pchar) : uint32;
|
function hexStringToInt(str : pchar) : uint32;
|
||||||
@ -151,6 +156,94 @@ begin
|
|||||||
stringConcat:= result;
|
stringConcat:= result;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// Trim the string to the specified length.
|
||||||
|
function stringTrim(str : pchar; length : uInt32) : pchar;
|
||||||
|
var
|
||||||
|
result : pchar;
|
||||||
|
begin
|
||||||
|
result:= stringNew(length);
|
||||||
|
memcpy(uint32(str), uint32(result), length);
|
||||||
|
stringTrim:= result;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Return a substring of the string.
|
||||||
|
function stringSub(str : pchar; start, size : uint32) : pchar;
|
||||||
|
var
|
||||||
|
result : pchar;
|
||||||
|
begin
|
||||||
|
result:= stringNew(size);
|
||||||
|
memcpy(uint32(str)+start, uint32(result), size);
|
||||||
|
stringSub:= result;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Replace first instance of a string with another.
|
||||||
|
function stringReplace(str, find, replace : pchar) : pchar;
|
||||||
|
var
|
||||||
|
result : pchar;
|
||||||
|
i, j, k : uint32;
|
||||||
|
found : boolean;
|
||||||
|
begin
|
||||||
|
|
||||||
|
// Find the first instance of the find string.
|
||||||
|
i:= 0;
|
||||||
|
found:= false;
|
||||||
|
while (i < stringSize(str)) and (not found) do begin
|
||||||
|
if stringEquals(str+i, find) then begin
|
||||||
|
found:= true;
|
||||||
|
end else begin
|
||||||
|
inc(i);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// If we found the find string, replace it.
|
||||||
|
if found then begin
|
||||||
|
result:= stringNew(stringSize(str) - stringSize(find) + stringSize(replace));
|
||||||
|
j:= 0;
|
||||||
|
k:= 0;
|
||||||
|
while i < stringSize(str) do begin
|
||||||
|
if stringEquals(str+i, find) then begin
|
||||||
|
memcpy(uint32(replace), uint32(result+j), stringSize(replace));
|
||||||
|
j:= j + stringSize(replace);
|
||||||
|
inc(i, stringSize(find));
|
||||||
|
end else begin
|
||||||
|
result[j]:= str[i];
|
||||||
|
inc(j);
|
||||||
|
inc(i);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
stringReplace:= result;
|
||||||
|
end else begin
|
||||||
|
stringReplace:= stringCopy(str);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Return the result.
|
||||||
|
stringReplace:= result;
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
// Find the index of the first instance of a string.
|
||||||
|
function stringIndexOf(str, find : pchar) : sint32;
|
||||||
|
var
|
||||||
|
i : uint32;
|
||||||
|
found : boolean;
|
||||||
|
begin
|
||||||
|
i:= 0;
|
||||||
|
found:= false;
|
||||||
|
while (i < stringSize(str)) and (not found) do begin
|
||||||
|
if stringEquals(str+i, find) then begin
|
||||||
|
found:= true;
|
||||||
|
end else begin
|
||||||
|
inc(i);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
if found then begin
|
||||||
|
stringIndexOf:= i;
|
||||||
|
end else begin
|
||||||
|
stringIndexOf:= -1;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
function stringContains(str : pchar; sub : pchar) : boolean;
|
function stringContains(str : pchar; sub : pchar) : boolean;
|
||||||
var
|
var
|
||||||
strEnd, subEnd, i, j, count : uint32;
|
strEnd, subEnd, i, j, count : uint32;
|
||||||
|
@ -41,9 +41,12 @@ uses
|
|||||||
E1000,
|
E1000,
|
||||||
IDE,
|
IDE,
|
||||||
storagemanagement,
|
storagemanagement,
|
||||||
|
drivemanager,
|
||||||
|
volumemanager,
|
||||||
lists,
|
lists,
|
||||||
net,
|
net,
|
||||||
fat32,
|
fat32,
|
||||||
|
flatfs,
|
||||||
isrmanager,
|
isrmanager,
|
||||||
faults,
|
faults,
|
||||||
fonts,
|
fonts,
|
||||||
@ -205,7 +208,9 @@ begin
|
|||||||
tracer.push_trace('kmain.DRVMGMT');
|
tracer.push_trace('kmain.DRVMGMT');
|
||||||
drivermanagement.init();
|
drivermanagement.init();
|
||||||
tracer.push_trace('kmain.STRMGMT');
|
tracer.push_trace('kmain.STRMGMT');
|
||||||
storagemanagement.init();
|
// storagemanagement.init();
|
||||||
|
drivemanager.init();
|
||||||
|
volumemanager.init();
|
||||||
|
|
||||||
{ Hook Timer for Ticks }
|
{ Hook Timer for Ticks }
|
||||||
tracer.push_trace('kmain.TMR');
|
tracer.push_trace('kmain.TMR');
|
||||||
@ -214,6 +219,7 @@ begin
|
|||||||
|
|
||||||
{ Filsystems }
|
{ Filsystems }
|
||||||
fat32.init();
|
fat32.init();
|
||||||
|
flatfs.init();
|
||||||
|
|
||||||
{ Device Drivers }
|
{ Device Drivers }
|
||||||
tracer.push_trace('kmain.DEVDRV');
|
tracer.push_trace('kmain.DEVDRV');
|
||||||
|
16
virtualbox-wrapper.ps1
Normal file
16
virtualbox-wrapper.ps1
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
param (
|
||||||
|
$MachineName
|
||||||
|
)
|
||||||
|
|
||||||
|
VBoxManage.exe startvm $MachineName
|
||||||
|
|
||||||
|
$running=$true
|
||||||
|
while($running) {
|
||||||
|
Start-Sleep -Seconds 1
|
||||||
|
$status=(VBoxManage.exe list runningvms)
|
||||||
|
if($status) {
|
||||||
|
$running=$status.contains($MachineName)
|
||||||
|
} else {
|
||||||
|
$running=$false
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user