Compare commits
39 Commits
837d69a44b
...
master
Author | SHA1 | Date | |
---|---|---|---|
7bf53181e2 | |||
b7cbad2db7 | |||
8c3649f691 | |||
b47194ed99 | |||
6bca42f2a5 | |||
f1211f3cca | |||
0913daebc6 | |||
d1a4b4d42f | |||
2906b8724b | |||
5e6e6c394a | |||
315050f095 | |||
f795ba24f8 | |||
738307d070 | |||
04cff2e2c3 | |||
0b5981242b | |||
f0dc598f44 | |||
d4236f455e | |||
96fcf19c14 | |||
8c51bd8690 | |||
43464bb550 | |||
6a1b87e250 | |||
9473e26b50 | |||
f19444201d | |||
f907b7e072 | |||
80d0183391 | |||
5f3de290f3 | |||
07106b9aed | |||
25df276101 | |||
189526cab8 | |||
595dd4fbac | |||
ba6d8037d2 | |||
208bda92c8 | |||
4c5038b001 | |||
98481ea1ce | |||
1db74f791a | |||
372fda3afc | |||
749ffe6d73 | |||
76b399f3b5 | |||
83f7ebb223 |
52
.drone.yml
Normal file
52
.drone.yml
Normal file
@ -0,0 +1,52 @@
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: build
|
||||
|
||||
steps:
|
||||
- name: build-image
|
||||
image: plugins/docker
|
||||
settings:
|
||||
repo: t3hn3rd/asuro-build
|
||||
tags: latest
|
||||
dockerfile: Dockerfile
|
||||
registry: docker.io
|
||||
username:
|
||||
from_secret: docker_username
|
||||
password:
|
||||
from_secret: docker_password
|
||||
|
||||
- name: compile
|
||||
image: t3hn3rd/asuro-build:latest
|
||||
depends_on:
|
||||
- build-image
|
||||
commands:
|
||||
- git fetch --tags
|
||||
- find . -type f -print0 | xargs -0 dos2unix
|
||||
- chmod +x /drone/src/*.sh
|
||||
- /drone/src/compile.sh
|
||||
|
||||
- name: upload-iso-artifact
|
||||
image: alpine/git
|
||||
depends_on:
|
||||
- compile
|
||||
when:
|
||||
branch:
|
||||
- master
|
||||
environment:
|
||||
GITEA_TOKEN:
|
||||
from_secret: gitea_token
|
||||
commands:
|
||||
- apk add --no-cache curl
|
||||
- chmod +w Asuro.iso
|
||||
- cp Asuro.iso "Asuro-$(git rev-parse --short HEAD).iso"
|
||||
- echo "Uploading Asuro-$(git rev-parse --short HEAD).iso to Gitea Packages..."
|
||||
- |
|
||||
curl -X PUT "https://gitea.spexeah.com/api/packages/Spexeah/generic/asuro-iso/$(git rev-parse --short HEAD)/Asuro.iso" \
|
||||
-H "Authorization: token $GITEA_TOKEN" --upload-file "Asuro-$(git rev-parse --short HEAD).iso"
|
||||
- echo "Updating latest ISO reference..."
|
||||
- |
|
||||
curl -X DELETE https://gitea.spexeah.com/api/packages/Spexeah/generic/asuro-iso/latest/Asuro.iso \
|
||||
-H "Authorization: token $GITEA_TOKEN" || echo "No previous latest version found."
|
||||
- |
|
||||
curl -X PUT https://gitea.spexeah.com/api/packages/Spexeah/generic/asuro-iso/latest/Asuro.iso \
|
||||
-H "Authorization: token $GITEA_TOKEN" --upload-file "Asuro-$(git rev-parse --short HEAD).iso"
|
@ -1,73 +0,0 @@
|
||||
stages:
|
||||
- Compile Versions
|
||||
- Compile Sources
|
||||
- Link
|
||||
- Generate Documentation
|
||||
- Deploy
|
||||
|
||||
cache:
|
||||
- key: ${CI_COMMIT_REF_SLUG}
|
||||
paths:
|
||||
- lib/*.o
|
||||
- bin/kernel.bin
|
||||
- doc
|
||||
|
||||
before_script:
|
||||
- chmod +x *.sh
|
||||
|
||||
versions:
|
||||
stage: Compile Versions
|
||||
script:
|
||||
- ./compile_vergen.sh
|
||||
artifacts:
|
||||
paths:
|
||||
- release/*.svg
|
||||
- src/include/asuro.pas
|
||||
|
||||
compile_sources:
|
||||
stage: Compile Sources
|
||||
script:
|
||||
- rm -f lib/*.so
|
||||
- ./compile_sources.sh
|
||||
needs:
|
||||
- versions
|
||||
|
||||
link:
|
||||
stage: Link
|
||||
script:
|
||||
- ./compile_stub.sh
|
||||
- ./compile_link.sh
|
||||
needs:
|
||||
- versions
|
||||
- compile_sources
|
||||
|
||||
isogen:
|
||||
stage: Deploy
|
||||
script:
|
||||
- ./compile_isogen.sh
|
||||
- ./compile_sumgen.sh
|
||||
artifacts:
|
||||
paths:
|
||||
- ./Asuro.iso
|
||||
- ./release/checksum.svg
|
||||
needs:
|
||||
- link
|
||||
|
||||
docgen:
|
||||
stage: Generate Documentation
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
script:
|
||||
- ./compile_sourcelist.sh
|
||||
- ./compile_docs.sh
|
||||
# Remove comments when we want to use gitlab pages.
|
||||
#- cp doc public
|
||||
allow_failure: true
|
||||
artifacts:
|
||||
paths:
|
||||
- doc
|
||||
#- public/*
|
||||
#- ./sources.list
|
||||
needs:
|
||||
- versions
|
@ -16,7 +16,7 @@ RUN curl -sL https://sourceforge.net/projects/freepascal/files/Linux/$FPC_VERSIO
|
||||
|
||||
COPY compile.sh /compile.sh
|
||||
ADD https://raw.githubusercontent.com/fsaintjacques/semver-tool/master/src/semver /usr/bin/semver
|
||||
RUN mkdir /code && chmod +x /usr/bin/semver
|
||||
RUN chmod +x /usr/bin/semver
|
||||
WORKDIR /code
|
||||
RUN find . -type f -print0 | xargs -0 dos2unix
|
||||
ENTRYPOINT ["/bin/bash", "-c"]
|
||||
|
32
compile.sh
32
compile.sh
@ -20,26 +20,30 @@ runOrFail() {
|
||||
fi
|
||||
}
|
||||
|
||||
runOrFail $(pwd)/compile_stub.sh "Failed to compile stub!"
|
||||
declare -a run_steps=(
|
||||
"compile_stub.sh" "Failed to compile stub!"
|
||||
"compile_vergen.sh" "Versions failed to compile"
|
||||
"compile_sources.sh" "Failed to compile FPC Sources!"
|
||||
"compile_link.sh" "Failed linking!"
|
||||
"compile_isogen.sh" "Failed to create ISO!"
|
||||
)
|
||||
|
||||
#Generate .pas with versioning headers.
|
||||
runOrFail $(pwd)/compile_vergen.sh "Versions failed to compile"
|
||||
|
||||
#Compile all .pas sources
|
||||
runOrFail $(pwd)/compile_sources.sh "Failed to compile FPC Sources!"
|
||||
|
||||
#Link into a binary.
|
||||
runOrFail $(pwd)/compile_link.sh "Failed linking!"
|
||||
|
||||
#Generate an ISO with GRUB as the Bootloader.
|
||||
runOrFail ./compile_isogen.sh "Failed to create ISO!"
|
||||
for ((i=0; i<${#run_steps[@]}; i+=2))
|
||||
do
|
||||
if [ "$ERRCOUNT" -eq "0" ]
|
||||
then
|
||||
script=$(pwd)/"${run_steps[$i]}"
|
||||
message="${run_steps[$i+1]}"
|
||||
runOrFail "$script" "$message"
|
||||
fi
|
||||
done
|
||||
|
||||
#Call generate final artifacts based on failure or success of the above.
|
||||
if [ "$ERRCOUNT" -ne "0" ]
|
||||
then
|
||||
./compile_finish.sh "failed"
|
||||
. ./compile_finish.sh "failed"
|
||||
else
|
||||
./compile_finish.sh "success"
|
||||
. ./compile_finish.sh "success"
|
||||
fi
|
||||
|
||||
cd ..
|
@ -4,4 +4,4 @@ echo "======================="
|
||||
echo " "
|
||||
echo "Compiling FPC Sources..."
|
||||
echo " "
|
||||
fpc -Aelf -gw -n -va -O3 -Op3 -Si -Sc -Sg -Xd -CX -XXs -CfSSE -CfSSE2 -Rintel -Pi386 -Tlinux -FElib/ -Fusrc/* -Fusrc/driver/* -Fusrc/driver/net/* src/kernel.pas
|
||||
fpc -Aelf -gw -g -gl -n -vlewn -O3 -Op3 -Si -Sc -Sg -Xd -CX -XXs -CfSSE -CfSSE2 -Rintel -Pi386 -Tlinux -FElib/ -Fusrc/* -Fusrc/driver/* -Fusrc/driver/net/* src/kernel.pas
|
@ -1,32 +0,0 @@
|
||||
#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
|
||||
|
||||
---
|
||||
|
@ -2,7 +2,7 @@ ENTRY(loader)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0xC0100000;
|
||||
|
||||
kernel_start = .;
|
||||
.text : AT(ADDR(.text) - 0xC0000000)
|
||||
{
|
||||
text = .; _text = .; __text = .;
|
||||
@ -33,4 +33,5 @@ SECTIONS
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
end = .; _end = .; __end = .;
|
||||
kernel_end = .;
|
||||
}
|
||||
|
@ -1,9 +1,17 @@
|
||||
unit ide;
|
||||
{ ************************************************
|
||||
* Asuro
|
||||
* Unit: Drivers/storage/IDE
|
||||
* Description: IDE ATA Driver
|
||||
*
|
||||
************************************************
|
||||
* Author: Aaron Hance
|
||||
* Contributors:
|
||||
************************************************ }
|
||||
unit IDE;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
ata,
|
||||
util,
|
||||
drivertypes,
|
||||
console,
|
||||
@ -13,326 +21,226 @@ uses
|
||||
lmemorymanager,
|
||||
storagemanagement,
|
||||
strings,
|
||||
tracer,
|
||||
drivemanager,
|
||||
storagetypes,
|
||||
idetypes;
|
||||
tracer;
|
||||
|
||||
type
|
||||
TPortMode = (P_READ, P_WRITE);
|
||||
|
||||
TIdentResponse = array[0..255] of uint16;
|
||||
|
||||
TIDE_Channel_Registers = record
|
||||
base : uint16;
|
||||
ctrl : uint16;
|
||||
bmide : uint16;
|
||||
noInter : uint8
|
||||
end;
|
||||
|
||||
TIDE_Device = record
|
||||
exists : boolean;
|
||||
isPrimary : boolean;
|
||||
isMaster : boolean;
|
||||
isATAPI : boolean;
|
||||
info : TIdentResponse;
|
||||
end;
|
||||
|
||||
TIDE_Status = bitpacked record
|
||||
Busy : Boolean;
|
||||
Ready : Boolean;
|
||||
Fault : Boolean;
|
||||
Seek : Boolean;
|
||||
DRQ : Boolean;
|
||||
CORR : Boolean;
|
||||
IDDEX : Boolean;
|
||||
ERROR : Boolean;
|
||||
end;
|
||||
PIDE_Status = ^TIDE_Status;
|
||||
|
||||
|
||||
const
|
||||
ATA_SR_BUSY = $80; //BUSY
|
||||
ATA_SR_DRDY = $40; //DRIVE READY
|
||||
ATA_SR_DF = $20; //DRIVE WRITE FAULT
|
||||
ATA_SR_DSC = $10; //DRIVE SEEK COMPLETE
|
||||
ATA_SR_DRQ = $08; //DATA REQUEST READY
|
||||
ATA_SR_CORR = $04; //CORRECTED DATA
|
||||
ATA_SR_IDX = $02; //INLEX
|
||||
ATA_SR_ERR = $01; //ERROR
|
||||
|
||||
ATA_ER_BBK = $80; //BAD SECTOR
|
||||
ATA_ER_UNC = $40; //UNCORRECTABLE DATA
|
||||
ATA_ER_MC = $20; //NO MEDIA
|
||||
ATA_ER_IDNF = $10; //ID MARK NOT FOUND
|
||||
ATA_ER_MCR = $08; //NO MEDIA
|
||||
ATA_ER_ABRT = $04; //COMMAND ABORTED
|
||||
ATA_ER_TK0NF = $02; //TRACK 0 NOT FOUND
|
||||
ATA_ER_AMNF = $01; //NO ADDRESS MARK
|
||||
|
||||
ATA_CMD_READ_PIO = $20;
|
||||
ATA_CMD_READ_PIO_EXT = $24;
|
||||
ATA_CMD_READ_DMA = $C8;
|
||||
ATA_CMD_READ_DMA_EXT = $25;
|
||||
ATA_CMD_WRITE_PIO = $30;
|
||||
ATA_CMD_WRITE_PIO_EXT = $34;
|
||||
ATA_CMD_WRITE_DMA = $CA;
|
||||
ATA_CMD_WRITE_DMA_EXT = $35;
|
||||
ATA_CMD_CACHE_FLUSH = $E7;
|
||||
ATA_CMD_CACHE_FLUSH_EXT = $EA;
|
||||
ATA_CMD_PACKET = $A0;
|
||||
ATA_CMD_IDENTIFY_PACKET = $A1;
|
||||
ATA_CMD_IDENTIFY = $EC;
|
||||
|
||||
ATAPI_CMD_READ = $A8;
|
||||
ATAPI_CMD_EJECT = $1B;
|
||||
|
||||
ATA_IDENT_DEVICETYPE = $0;
|
||||
ATA_IDENT_CYLINDERS = $2;
|
||||
ATA_IDENT_HEADS = $6;
|
||||
ATA_IDENT_SECOTRS = $12;
|
||||
ATA_IDENT_SERIAL = $20;
|
||||
ATA_IDENT_MODEL = $54;
|
||||
ATA_IDENT_CAPABILITIES = $98;
|
||||
ATA_IDENT_FIELDVALID = $106;
|
||||
ATA_IDENT_MAX_LBA = $120;
|
||||
ATA_IDENT_COMMANDSETS = $164;
|
||||
ATA_IDENT_MAX_LBA_EXT = $200;
|
||||
|
||||
ATA_REG_DATA = $00;
|
||||
ATA_REG_ERROR = $01;
|
||||
ATA_REG_FEATURES = $01;
|
||||
ATA_REG_SECCOUNT = $02;
|
||||
ATA_REG_LBA0 = $03;
|
||||
ATA_REG_LBA1 = $04;
|
||||
ATA_REG_LBA2 = $05;
|
||||
ATA_REG_HDDEVSEL = $06;
|
||||
ATA_REG_COMMAND = $07;
|
||||
ATA_REG_STATUS = $07;
|
||||
ATA_REG_SECCOUNT1 = $08;
|
||||
ATA_REG_LBA3 = $09;
|
||||
ATA_REG_LBA4 = $0A;
|
||||
ATA_REG_LBA5 = $0B;
|
||||
ATA_REG_CONTROL = $0C;
|
||||
ATA_REG_ALTSTATUS = $0C;
|
||||
ATA_REG_DEVADDRESS = $0D;
|
||||
|
||||
ATA_DEVICE_MASTER = $A0;
|
||||
ATA_DEVICE_SLAVE = $B0;
|
||||
|
||||
ATA_PRIMARY_BASE = $1F0;
|
||||
|
||||
|
||||
var
|
||||
primaryDevices: array[0..1] of TIDE_Device = (
|
||||
(exists: false; isPrimary: true; isMaster: true; isATAPI: false;
|
||||
status: (Busy: false; Ready: false; Fault: false; Seek: false; DRQ: false; CORR: false; IDDEX: false; ERROR: false);
|
||||
base: ATA_PRIMARY_BASE; info: nil),
|
||||
controller : PPCI_Device;
|
||||
|
||||
(exists: false; isPrimary: true; isMaster: false; isATAPI: false;
|
||||
status: (Busy: false; Ready: false; Fault: false; Seek: false; DRQ: false; CORR: false; IDDEX: false; ERROR: false);
|
||||
base: ATA_PRIMARY_BASE; info: nil)
|
||||
);
|
||||
bar0 : uint32;
|
||||
bar1 : uint32;
|
||||
bar4 : uint32;
|
||||
|
||||
secondaryDevices: array[0..1] of TIDE_Device = (
|
||||
(exists: false; isPrimary: false; isMaster: true; isATAPI: false;
|
||||
status: (Busy: false; Ready: false; Fault: false; Seek: false; DRQ: false; CORR: false; IDDEX: false; ERROR: false);
|
||||
base: ATA_SECONDARY_BASE; info: nil),
|
||||
IDEDevices : array[0..3] of TIDE_Device;
|
||||
|
||||
(exists: false; isPrimary: false; isMaster: false; isATAPI: false;
|
||||
status: (Busy: false; Ready: false; Fault: false; Seek: false; DRQ: false; CORR: false; IDDEX: false; ERROR: false);
|
||||
base: ATA_SECONDARY_BASE; info: nil)
|
||||
);
|
||||
buffer : Puint32;
|
||||
|
||||
procedure init();
|
||||
function load(ptr : void) : boolean;
|
||||
function identify_device(bus : uint8; device : uint8) : TIdentResponse;
|
||||
|
||||
function load(ptr: void) : boolean;
|
||||
procedure init();
|
||||
function get_status(var device : TIDE_Device) : TIDE_Status;
|
||||
function wait_for_device(device : TIDE_Device) : boolean;
|
||||
procedure no_interrupt(isPrimary : boolean);
|
||||
procedure select_device(device : TIDE_Device);
|
||||
// procedure flush();
|
||||
procedure readPIO28(drive : uint8; LBA : uint32; buffer : puint8);
|
||||
procedure writePIO28(drive : uint8; LBA : uint32; buffer : puint8);
|
||||
//read/write must be capable of reading/writting any amknt of data upto disk size
|
||||
|
||||
implementation
|
||||
procedure dread(device : PStorage_device; LBA : uint32; sectorCount : uint32; buffer : puint32);
|
||||
procedure dwrite(device : PStorage_device; LBA : uint32; sectorCount : uint32; buffer : puint32);
|
||||
|
||||
{
|
||||
Disable interrupts on the IDE bus
|
||||
@param(isPrimary The bus to disable interrupts on)
|
||||
}
|
||||
procedure no_interrupt(isPrimary : boolean);
|
||||
implementation
|
||||
|
||||
function port_read(register : uint8) : uint8;
|
||||
begin
|
||||
if isPrimary then begin
|
||||
outb(ATA_INTERRUPT_PRIMARY, inb(ATA_INTERRUPT_PRIMARY) or (1 shl 1));
|
||||
end else begin
|
||||
outb(ATA_INTERRUPT_SECONDARY, inb(ATA_INTERRUPT_SECONDARY) or (1 shl 1));
|
||||
port_read:= inb(ATA_PRIMARY_BASE + register);
|
||||
end;
|
||||
|
||||
procedure port_write(register : uint8; data : uint8);
|
||||
var
|
||||
i : uint8;
|
||||
begin
|
||||
outb(ATA_PRIMARY_BASE + register, data);
|
||||
util.psleep(1);
|
||||
if register = ATA_REG_COMMAND then begin
|
||||
for i:= 0 to 5 do begin
|
||||
port_read(ATA_REG_STATUS);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
{
|
||||
Wait for the device to be ready on the IDE bus
|
||||
procedure no_interrupt(device : uint8);
|
||||
begin
|
||||
outb($3F6, inb($3f6) or (1 shl 1));
|
||||
end;
|
||||
|
||||
@param(device The device to wait for)
|
||||
@returns(@True if the device is ready, @False otherwise)
|
||||
}
|
||||
function wait_for_device(device : TIDE_Device) : boolean;
|
||||
var
|
||||
status : TIDE_Status;
|
||||
procedure device_select(device : uint8);
|
||||
begin
|
||||
outb($1F6, device); //TODO clean
|
||||
end;
|
||||
|
||||
function is_ready() : boolean;
|
||||
var
|
||||
status : uint8;
|
||||
i : uint32;
|
||||
begin
|
||||
push_trace('ide.wait_for_device()');
|
||||
//wait for drive to be ready
|
||||
while true do begin
|
||||
status := port_read(ATA_REG_COMMAND);
|
||||
|
||||
i := 0;
|
||||
|
||||
while (i < 10000) do begin
|
||||
status := get_status(device);
|
||||
|
||||
if (status.BUSY = false) then begin //todo test
|
||||
wait_for_device := true;
|
||||
pop_trace();
|
||||
exit;
|
||||
if(status and ATA_SR_ERR) = ATA_SR_ERR then begin
|
||||
console.writestringln('[IDE] (IDENTIFY_DEVICE) DRIVE ERROR!');
|
||||
console.redrawWindows();
|
||||
is_ready := false;
|
||||
break;
|
||||
end;
|
||||
|
||||
i := i + 1;
|
||||
if (status and ATA_SR_BUSY) <> ATA_SR_BUSY then begin
|
||||
is_ready := true;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
|
||||
wait_for_device := false;
|
||||
pop_trace();
|
||||
end;
|
||||
|
||||
{
|
||||
Select the active device on the IDE bus
|
||||
@param(device The device to select)
|
||||
|
||||
Function can set the device to either master or slave,
|
||||
one device per bus/channel can be active at a time.
|
||||
}
|
||||
procedure select_device(device : TIDE_Device);
|
||||
var
|
||||
dev : uint8;
|
||||
function validate_28bit_address(addr : uint32) : boolean;
|
||||
begin
|
||||
push_trace('ide.select_device()');
|
||||
|
||||
dev := ATA_DEVICE_SLAVE;
|
||||
|
||||
if device.isMaster then begin
|
||||
dev := ATA_DEVICE_MASTER;
|
||||
end;
|
||||
|
||||
outb(device.base + ATA_REG_HDDEVSEL, dev);
|
||||
|
||||
pop_trace();
|
||||
validate_28bit_address := (addr and $F0000000) = 0;
|
||||
end;
|
||||
|
||||
{
|
||||
Get the status of the device on the IDE bus
|
||||
|
||||
@param(device The device to get the status of)
|
||||
@returns(@TIDE_Device The status of the device on the IDE bus)
|
||||
}
|
||||
function get_status(var device : TIDE_Device) : TIDE_Status;
|
||||
var
|
||||
status : TIDE_Status;
|
||||
begin
|
||||
push_trace('ide.get_status()');
|
||||
|
||||
select_device(device);
|
||||
|
||||
status := TIDE_Status(inb(device.base + ATA_REG_STATUS));
|
||||
|
||||
device.status := status;
|
||||
|
||||
pop_trace();
|
||||
get_status := status;
|
||||
end;
|
||||
|
||||
{
|
||||
Check if the device is present on the IDE bus
|
||||
|
||||
@param(device The device to check)
|
||||
@returns(@True if the device is present, @False otherwise)
|
||||
}
|
||||
function is_device_present(var device : TIDE_Device) : boolean;
|
||||
begin
|
||||
push_trace('ide.is_device_present()');
|
||||
|
||||
get_status(device);
|
||||
|
||||
if (uInt8(device.status) = $FF) then begin //TODO make this more robust
|
||||
is_device_present := false;
|
||||
end else begin
|
||||
is_device_present := true;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
{
|
||||
Check if the device is an ATAPI device
|
||||
|
||||
@param(device The device to check)
|
||||
@returns(@True if the device is an ATAPI device, @False otherwise)
|
||||
}
|
||||
function check_device_type(var device : TIDE_Device) : boolean;
|
||||
var
|
||||
sec, lba0, lba1, lba2 : uint8;
|
||||
begin
|
||||
push_trace('ide.check_device_type()');
|
||||
|
||||
select_device(device);
|
||||
|
||||
//TODO make sure dvice signture is set at this time, else reset it
|
||||
|
||||
//read all bytes of LBA address
|
||||
sec := inb(device.base + ATA_REG_SECCOUNT);
|
||||
lba0 := inb(device.base + ATA_REG_LBA0);
|
||||
lba1 := inb(device.base + ATA_REG_LBA1);
|
||||
lba2 := inb(device.base + ATA_REG_LBA2);
|
||||
|
||||
//check if the device is an ATAPI device (01, 01, 14, EB)
|
||||
if (lba1 = $14) and (lba2 = $EB) then begin
|
||||
check_device_type := true;
|
||||
end else begin
|
||||
check_device_type := false;
|
||||
end;
|
||||
|
||||
device.isATAPI := check_device_type;
|
||||
end;
|
||||
|
||||
{
|
||||
Load the device on the IDE bus
|
||||
|
||||
@param(device The device to load)
|
||||
@returns(@True if the device is loaded, @False otherwise)
|
||||
}
|
||||
procedure load_device(var device : TIDE_Device);
|
||||
function identify_device(bus : uint8; device : uint8) : TIdentResponse;
|
||||
var
|
||||
status : uint8;
|
||||
identResponse : TIdentResponse;
|
||||
i : uint8;
|
||||
buffer : puint8;
|
||||
storageDevice : PStorage_device;
|
||||
success : boolean;
|
||||
begin
|
||||
begin
|
||||
push_trace('IDE.Identify_Device');
|
||||
device_select(device);
|
||||
no_interrupt(device);
|
||||
port_write(ATA_REG_CONTROL, 0);
|
||||
|
||||
push_trace('ide.load_device()');
|
||||
//check if bus is floating
|
||||
status := port_read(ATA_REG_COMMAND);
|
||||
if status = $FF then exit;
|
||||
|
||||
if (is_device_present(device)) then begin
|
||||
console.writestringln('[IDE] (load_device) Device is present');
|
||||
port_write(ATA_REG_SECCOUNT, 0);
|
||||
port_write(ATA_REG_LBA0, 0);
|
||||
port_write(ATA_REG_LBA1, 0);
|
||||
port_write(ATA_REG_LBA2, 0);
|
||||
|
||||
if (check_device_type(device)) then begin
|
||||
console.writestringln('[IDE] (load_device) Device is ATAPI');
|
||||
//todo load device info
|
||||
end else begin
|
||||
console.writestringln('[IDE] (load_device) Device is ATA');
|
||||
success:= ata.identify_device(device);
|
||||
end;
|
||||
port_write(ATA_REG_COMMAND, ATA_CMD_IDENTIFY);
|
||||
|
||||
if not success then begin
|
||||
console.writestringln('[IDE] (load_device) Error identifying device'); //todo
|
||||
device.exists := false;
|
||||
exit;
|
||||
end;
|
||||
//check if drive is present
|
||||
status := port_read(ATA_REG_COMMAND);
|
||||
if status = $00 then exit;
|
||||
|
||||
device.exists := true;
|
||||
if not is_ready() then exit;
|
||||
|
||||
storageDevice := PStorage_Device(kalloc(sizeof(TStorage_Device)));
|
||||
memset(uint32(storageDevice), 0, sizeof(TStorage_Device));
|
||||
|
||||
if (device.isATAPI) then begin
|
||||
storageDevice^.controller := TControllerType.ControllerATAPI;
|
||||
storageDevice^.writable := false; //TODO atapi
|
||||
end else begin
|
||||
storageDevice^.controller := TControllerType.ControllerATA;
|
||||
storageDevice^.writable := true;
|
||||
|
||||
storageDevice^.maxSectorCount := (device.info^[61] shl 16) or device.info^[60];
|
||||
storageDevice^.sectorSize := 512; //todo
|
||||
|
||||
if (device.isMaster) then begin
|
||||
storageDevice^.controllerId0 := 0;
|
||||
end else begin
|
||||
storageDevice^.controllerId0 := 1;
|
||||
end;
|
||||
|
||||
//if secotorcount is 0, then the device is not present
|
||||
if (storageDevice^.maxSectorCount = 0) then begin
|
||||
device.exists := false;
|
||||
exit;
|
||||
end;
|
||||
|
||||
//wrtie test, 1F2F1F2F repeated
|
||||
buffer := puint8(kalloc(512));
|
||||
memset(uint32(buffer), 0, 512);
|
||||
for i:=0 to 200 do begin
|
||||
if (i mod 4 = 0) then begin
|
||||
buffer[i] := $1F;
|
||||
end else begin
|
||||
buffer[i] := $2F;
|
||||
end;
|
||||
end;
|
||||
|
||||
//write to the first sector
|
||||
ata.write_pio28(device, 0, 1, puint16(buffer));
|
||||
|
||||
//read the first sector
|
||||
memset(uint32(buffer), 0, 512);
|
||||
ata.read_pio28(device, 0, 1, puint16(buffer));
|
||||
|
||||
//check if the data is the same
|
||||
for i:=0 to 200 do begin
|
||||
console.writehexln(buffer[i]);
|
||||
end;
|
||||
end;
|
||||
|
||||
//register the device
|
||||
drivemanager.register_device(storageDevice);
|
||||
|
||||
end else begin
|
||||
console.writestringln('[IDE] (load_device) Device is not present');
|
||||
device.exists := false;
|
||||
for i:=0 to 255 do begin
|
||||
identResponse[i] := inw(ATA_PRIMARY_BASE + ATA_REG_DATA);
|
||||
end;
|
||||
|
||||
pop_trace();
|
||||
end;
|
||||
|
||||
|
||||
function load(ptr: void) : boolean;
|
||||
var
|
||||
pciDevice : PPCI_Device;
|
||||
buffer : puint8;
|
||||
i : uint8;
|
||||
begin
|
||||
push_trace('ide.load()');
|
||||
console.writestringln('[IDE] (load) Loading IDE Devices');
|
||||
|
||||
pciDevice := PPCI_Device(ptr);
|
||||
|
||||
load_device(primaryDevices[0]);
|
||||
load_device(primaryDevices[1]);
|
||||
load_device(secondaryDevices[0]);
|
||||
load_device(secondaryDevices[1]);
|
||||
|
||||
pop_trace();
|
||||
load := true;
|
||||
|
||||
console.writestringln('[IDE] (load) IDE Device Loading Finished');
|
||||
|
||||
i := 0;
|
||||
|
||||
if (primaryDevices[0].exists) then begin
|
||||
console.writestringln('[IDE] (load) FOUND Primary Master Device 0');
|
||||
i := i + 1;
|
||||
end;
|
||||
|
||||
if (primaryDevices[1].exists) then begin
|
||||
console.writestringln('[IDE] (load) FOUND Primary Slave Device 1');
|
||||
i := i + 1;
|
||||
end;
|
||||
|
||||
if (secondaryDevices[0].exists) then begin
|
||||
console.writestringln('[IDE] (load) FOUND Secondary Master Device 2');
|
||||
i := i + 1;
|
||||
end;
|
||||
|
||||
if (secondaryDevices[1].exists) then begin
|
||||
console.writestringln('[IDE] (load) FOUND Secondary Slave Device 3');
|
||||
i := i + 1;
|
||||
end;
|
||||
|
||||
// console.writestringln('[IDE] (load) Found ' + i + ' IDE Devices');
|
||||
|
||||
identify_device := identResponse;
|
||||
end;
|
||||
|
||||
procedure init();
|
||||
@ -348,8 +256,193 @@ begin
|
||||
devID.id3:= idANY;
|
||||
devID.id4:= idANY;
|
||||
devID.ex:= nil;
|
||||
drivermanagement.register_driver('IDE ATA/ATAPI Driver', @devID, @load);
|
||||
drivermanagement.register_driver('IDE ATA Driver', @devID, @load);
|
||||
console.writestringln('[IDE] (INIT) END');
|
||||
end;
|
||||
|
||||
function load(ptr : void) : boolean;
|
||||
var
|
||||
controller : PPCI_Device;
|
||||
masterDevice : TStorage_Device;
|
||||
slaveDevice : TStorage_Device;
|
||||
buffer : puint8;
|
||||
i : uint8;
|
||||
begin
|
||||
push_trace('ide.load');
|
||||
console.writestringln('[IDE] (LOAD) BEGIN');
|
||||
controller := PPCI_Device(ptr);
|
||||
|
||||
console.writestringln('[IDE] (INIT) CHECK FLOATING BUS');
|
||||
//check if bus is floating and identify device
|
||||
if inb($1F7) <> $FF then begin
|
||||
//outb($3F6, inb($3f6) or (1 shl 1)); // disable interrupts
|
||||
IDEDevices[0].isMaster:= true;
|
||||
IDEDevices[0].info := identify_device(0, ATA_DEVICE_MASTER);
|
||||
|
||||
masterDevice.controller := ControllerIDE;
|
||||
masterDevice.controllerId0:= 0;
|
||||
masterDevice.maxSectorCount:= (IDEDevices[0].info[60] or (IDEDevices[0].info[61] shl 16) ); //LBA28 SATA
|
||||
|
||||
if IDEDevices[0].info[1] = 0 then begin
|
||||
console.writestringln('[IDE] (INIT) ERROR: DEVICE IDENT FAILED!');
|
||||
exit;
|
||||
end;
|
||||
|
||||
masterDevice.hpc:= uint32(IDEDevices[0].info[3] DIV IDEDevices[0].info[1]);
|
||||
|
||||
masterDevice.sectorSize:= 512;
|
||||
if masterDevice.maxSectorCount <> 0 then begin
|
||||
IDEDevices[0].exists:= true;
|
||||
masterDevice.readCallback:= @dread;
|
||||
masterDevice.writeCallback:= @dwrite;
|
||||
storagemanagement.register_device(@masterDevice);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
// buffer:= puint8(kalloc(512));
|
||||
// buffer[0] := 1;
|
||||
// buffer[1] := 2;
|
||||
// buffer[2] := 3;
|
||||
// buffer[3] := 4;
|
||||
// buffer[4] := 5;
|
||||
// buffer[5] := 6;
|
||||
// writePIO28(0, 3, buffer);
|
||||
// writePIO28(0, 3, buffer);
|
||||
// writePIO28(0, 3, buffer);
|
||||
// writePIO28(0, 4, buffer);
|
||||
// writePIO28(0, 5, buffer);
|
||||
// writePIO28(0, 5, buffer);
|
||||
// writePIO28(0, 5, buffer);
|
||||
// psleep(1000);
|
||||
// writePIO28(0, 5, buffer);
|
||||
// writePIO28(0, 5, buffer);
|
||||
// writePIO28(0, 5, buffer);
|
||||
// kfree(puint32(buffer));
|
||||
|
||||
console.writestringln('[IDE] (LOAD) END');
|
||||
end;
|
||||
|
||||
procedure readPIO28(drive : uint8; LBA : uint32; buffer : puint8);
|
||||
var
|
||||
status : uint8;
|
||||
i: uint16;
|
||||
device: uint8;
|
||||
data: uint16;
|
||||
begin
|
||||
if not validate_28bit_address(LBA) then begin
|
||||
console.writestringln('IDE (writePIO28) ERROR: Invalid LBA!');
|
||||
end;
|
||||
|
||||
//Add last 4 bits of LBA to device port
|
||||
if IDEDevices[drive].isMaster then begin
|
||||
device:= ATA_DEVICE_MASTER;
|
||||
device_select($E0 or ((LBA and $0F000000) shr 24)); //LBA primary master
|
||||
end
|
||||
else begin
|
||||
device:= ATA_DEVICE_SLAVE;
|
||||
device_select($F0 or ((LBA and $0F000000) shr 24)); //LBA primary slave
|
||||
end;
|
||||
|
||||
no_interrupt(device);
|
||||
port_write(ATA_REG_ERROR, 0);
|
||||
|
||||
//Write sector count and LBA
|
||||
port_write(ATA_REG_SECCOUNT, 1);
|
||||
port_write(ATA_REG_LBA0, (LBA and $000000FF));
|
||||
port_write(ATA_REG_LBA1, (LBA and $0000FF00) shr 8);
|
||||
port_write(ATA_REG_LBA2, (LBA and $00FF0000) shr 16);
|
||||
|
||||
//send read command
|
||||
port_write(ATA_REG_COMMAND, ATA_CMD_READ_PIO);
|
||||
if not is_ready() then exit;
|
||||
|
||||
i:=0;
|
||||
while i < 512 do begin
|
||||
// if not is_ready() then exit;
|
||||
|
||||
data:= inw(ATA_PRIMARY_BASE + ATA_REG_DATA);
|
||||
|
||||
buffer[i+1] := uint8($00ff and (data shr 8));
|
||||
buffer[i] := uint8($00ff and data);
|
||||
|
||||
i:= i + 2;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure writePIO28(drive : uint8; LBA : uint32; buffer : puint8);
|
||||
var
|
||||
status : uint8;
|
||||
i: uint16;
|
||||
device: uint8;
|
||||
begin
|
||||
push_trace('IDE.WritePIO28');
|
||||
if not validate_28bit_address(LBA) then begin
|
||||
console.writestringln('IDE (writePIO28) ERROR: Invalid LBA!');
|
||||
end;
|
||||
|
||||
console.writeintln(uint32(drive));
|
||||
console.writeintln(LBA);
|
||||
|
||||
//Add last 4 bits of LBA to device port
|
||||
if IDEDevices[drive].isMaster then begin
|
||||
device:= ATA_DEVICE_MASTER;
|
||||
device_select($E0 or ((LBA and $0F000000) shr 24)); //LBA primary master
|
||||
end
|
||||
else begin
|
||||
device:= ATA_DEVICE_SLAVE;
|
||||
device_select($F0 or ((LBA and $0F000000) shr 24)); //LBA primary slave
|
||||
end;
|
||||
|
||||
// no_interrupt(device);
|
||||
|
||||
port_write(ATA_REG_ERROR, 0);
|
||||
port_write(ATA_REG_CONTROL, 0);
|
||||
|
||||
// check if bus is floating
|
||||
status := port_read(ATA_REG_COMMAND);
|
||||
if status = $FF then exit;
|
||||
|
||||
//Write sector count and LBA
|
||||
port_write(ATA_REG_SECCOUNT, 1);
|
||||
port_write(ATA_REG_LBA0, (LBA and $000000FF));
|
||||
port_write(ATA_REG_LBA1, (LBA and $0000FF00) shr 8);
|
||||
port_write(ATA_REG_LBA2, (LBA and $00FF0000) shr 16);
|
||||
|
||||
//send write command
|
||||
port_write(ATA_REG_COMMAND, ATA_CMD_WRITE_PIO);
|
||||
|
||||
//write data
|
||||
i:=0;
|
||||
while i < 512 do begin
|
||||
outw(ATA_PRIMARY_BASE + ATA_REG_DATA, uint16(buffer[i] or (buffer[i+1] shl 8)));
|
||||
i:= i + 2;
|
||||
end;
|
||||
|
||||
//flush drive cache
|
||||
psleep(1);
|
||||
port_write(ATA_REG_COMMAND, ATA_CMD_CACHE_FLUSH);
|
||||
psleep(1);
|
||||
if not is_ready() then exit;
|
||||
end;
|
||||
|
||||
procedure dread(device : PStorage_device; LBA : uint32; sectorCount : uint32; buffer : Puint32);
|
||||
var
|
||||
i : uint16;
|
||||
begin
|
||||
for i:=0 to sectorCount-1 do begin
|
||||
readPIO28(device^.controllerId0, LBA, puint8(@buffer[512*i]));
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure dwrite(device : PStorage_device; LBA : uint32; sectorCount : uint32; buffer : Puint32);
|
||||
var
|
||||
i : uint16;
|
||||
begin
|
||||
for i:=0 to sectorCount-1 do begin
|
||||
writePIO28(device^.controllerId0, LBA, puint8(@buffer[512*i]));
|
||||
end;
|
||||
// writePIO28(device^.controllerId0, LBA, puint8(buffer));
|
||||
end;
|
||||
|
||||
end.
|
@ -1,81 +0,0 @@
|
||||
{
|
||||
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.
|
@ -1,221 +0,0 @@
|
||||
unit ata;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
util,
|
||||
drivertypes,
|
||||
console,
|
||||
terminal,
|
||||
drivermanagement,
|
||||
vmemorymanager,
|
||||
lmemorymanager,
|
||||
storagemanagement,
|
||||
strings,
|
||||
tracer,
|
||||
drivemanager,
|
||||
storagetypes,
|
||||
idetypes;
|
||||
|
||||
var
|
||||
|
||||
test : uint32;
|
||||
|
||||
function identify_device(var device : TIDE_Device) : Boolean;
|
||||
function read_pio28(device : TIDE_Device; lba : uint32; count : uint8; buffer : puint16) : boolean;
|
||||
function write_pio28(device : TIDE_Device; lba : uint32; count : uint8; buffer : puint16) : boolean;
|
||||
|
||||
|
||||
implementation
|
||||
uses
|
||||
ide;
|
||||
|
||||
{
|
||||
ensure the address is a valid 28 bit address
|
||||
|
||||
@param(addr The address to validate)
|
||||
@returns(@True if the address is valid, @False otherwise)
|
||||
}
|
||||
function validate_28bit_address(addr : uint32) : boolean;
|
||||
begin
|
||||
validate_28bit_address := (addr and $F0000000) = 0;
|
||||
end;
|
||||
|
||||
{
|
||||
Identify the device on the IDE bus
|
||||
|
||||
@param(device The device to identify)
|
||||
@returns(@True if the device is identified, @False otherwise)
|
||||
}
|
||||
function identify_device(var device : TIDE_Device) : Boolean;
|
||||
var
|
||||
i : uint8;
|
||||
status : TIDE_Status;
|
||||
buffer : TIdentResponse;
|
||||
ready : boolean;
|
||||
begin
|
||||
select_device(device);
|
||||
no_interrupt(device.isPrimary);
|
||||
|
||||
status := get_status(device);
|
||||
|
||||
outb(device.base + ATA_REG_SECCOUNT, 0);
|
||||
outb(device.base + ATA_REG_LBA0, 0);
|
||||
outb(device.base + ATA_REG_LBA1, 0);
|
||||
outb(device.base + ATA_REG_LBA2, 0);
|
||||
|
||||
outb(device.base + ATA_REG_COMMAND, ATA_CMD_IDENTIFY);
|
||||
|
||||
status := get_status(device);
|
||||
|
||||
if status.ERROR then begin
|
||||
console.writestringln('Error identifying device, maybe'); //todo
|
||||
end;
|
||||
|
||||
ready := wait_for_device(device);
|
||||
|
||||
if not ready then begin
|
||||
console.writestringln('Device not ready in time!');
|
||||
//teapot time
|
||||
// BSOD('Device not ready in time!', 'ATA DEVICE NOT READY IN TIME FOR IDENT');
|
||||
exit(false);
|
||||
end;
|
||||
|
||||
for i:=0 to 255 do begin
|
||||
buffer[i] := inw(device.base + ATA_REG_DATA);
|
||||
end;
|
||||
|
||||
device.info := @buffer;
|
||||
|
||||
identify_device := true;
|
||||
end;
|
||||
|
||||
procedure set_lba_mode(device : TIDE_Device; lba : uint32);
|
||||
begin
|
||||
// if device.isPrimary then begin
|
||||
if device.isMaster then begin
|
||||
outb(device.base + ATA_REG_HDDEVSEL, $E0 or ((lba and $0F000000) shr 24));
|
||||
end else begin
|
||||
outb(device.base + ATA_REG_HDDEVSEL, $F0 or ((lba and $0F000000) shr 24));
|
||||
end;
|
||||
// end else begin //TODO
|
||||
// if device.isMaster then begin
|
||||
// outb(device.base + ATA_REG_HDDEVSEL, $A0);
|
||||
// end else begin
|
||||
// outb(device.base + ATA_REG_HDDEVSEL, $B0);
|
||||
// end;
|
||||
// end;
|
||||
end;
|
||||
|
||||
function read_pio28(device : TIDE_Device; lba : uint32; count : uint8; buffer : puint16) : boolean;
|
||||
var
|
||||
i : uint16;
|
||||
ii : uint16;
|
||||
status : TIDE_Status;
|
||||
ready : boolean;
|
||||
begin
|
||||
push_trace('ata.read_pio28()');
|
||||
|
||||
if not validate_28bit_address(lba) then begin
|
||||
console.writestringln('Invalid address for 28 bit read');
|
||||
read_pio28 := false;
|
||||
exit;
|
||||
end;
|
||||
|
||||
select_device(device);
|
||||
no_interrupt(device.isPrimary);
|
||||
|
||||
set_lba_mode(device, lba);
|
||||
|
||||
outb(device.base + ATA_REG_SECCOUNT, count);
|
||||
outb(device.base + ATA_REG_LBA0, (lba and $000000FF));
|
||||
outb(device.base + ATA_REG_LBA1, (lba and $0000FF00) shr 8);
|
||||
outb(device.base + ATA_REG_LBA2, (lba and $00FF0000) shr 16);
|
||||
|
||||
outb(device.base + ATA_REG_COMMAND, ATA_CMD_READ_PIO);
|
||||
|
||||
ready := wait_for_device(device);
|
||||
|
||||
if not ready then begin
|
||||
console.writestringln('Device not ready in time!');
|
||||
BSOD('Device not ready in time!', 'ATA DEVICE NOT READY IN TIME FOR READ COMMAND');
|
||||
end;
|
||||
|
||||
for i:=0 to count-1 do begin
|
||||
for ii:=0 to 511 do begin //TODO needs to read sector size
|
||||
buffer[i] := inw(device.base + ATA_REG_DATA);
|
||||
|
||||
ready := wait_for_device(device);
|
||||
|
||||
if not ready then begin
|
||||
console.writestringln('Device not ready in time!');
|
||||
BSOD('Device not ready in time!', 'ATA DEVICE NOT READY IN TIME FOR READ');
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
read_pio28 := true;
|
||||
pop_trace();
|
||||
end;
|
||||
|
||||
function write_pio28(device : TIDE_Device; lba : uint32; count : uint8; buffer : puint16) : boolean;
|
||||
var
|
||||
i : uint16;
|
||||
ii : uint16;
|
||||
status : TIDE_Status;
|
||||
ready : boolean;
|
||||
begin
|
||||
push_trace('ata.write_pio28()');
|
||||
|
||||
if not validate_28bit_address(lba) then begin
|
||||
console.writestringln('Invalid address for 28 bit write');
|
||||
write_pio28 := false;
|
||||
exit;
|
||||
end;
|
||||
|
||||
select_device(device);
|
||||
no_interrupt(device.isPrimary); //maybe not?
|
||||
|
||||
set_lba_mode(device, lba);
|
||||
|
||||
outb(device.base + ATA_REG_SECCOUNT, count);
|
||||
outb(device.base + ATA_REG_LBA0, (lba and $000000FF));
|
||||
outb(device.base + ATA_REG_LBA1, (lba and $0000FF00) shr 8);
|
||||
outb(device.base + ATA_REG_LBA2, (lba and $00FF0000) shr 16);
|
||||
|
||||
outb(device.base + ATA_REG_COMMAND, ATA_CMD_WRITE_PIO);
|
||||
|
||||
ready := wait_for_device(device);
|
||||
|
||||
if not ready then begin
|
||||
console.writestringln('Device not ready in time!');
|
||||
BSOD('Device not ready in time!', 'ATA DEVICE NOT READY IN TIME FOR WRITE COMMAND');
|
||||
end;
|
||||
|
||||
for i:=0 to count-1 do begin
|
||||
for ii:=0 to 511 do begin //TODO needs to read sector size
|
||||
outw(device.base + ATA_REG_DATA, uint16(buffer[i]));
|
||||
|
||||
ready := wait_for_device(device);
|
||||
|
||||
if not ready then begin
|
||||
console.writestringln('Device not ready in time!');
|
||||
BSOD('Device not ready in time!', 'ATA DEVICE NOT READY IN TIME FOR WRITE');
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
psleep(50); //todo check
|
||||
outb(device.base + ATA_REG_COMMAND, ATA_CMD_CACHE_FLUSH);
|
||||
ready := wait_for_device(device);
|
||||
|
||||
// if not ready then begin
|
||||
// console.writestringln('Device not ready in time!');
|
||||
// BSOD('Device not ready in time!', 'ATA DEVICE NOT READY IN TIME FOR CACHE FLUSH');
|
||||
// end;
|
||||
|
||||
write_pio28 := true;
|
||||
pop_trace();
|
||||
end;
|
||||
|
||||
end.
|
@ -1,306 +0,0 @@
|
||||
// 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
|
||||
ControllerATA : controller_type_2_string:= 'ATA';
|
||||
ControllerATAPI : controller_type_2_string:= 'ATAPI';
|
||||
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,16 +10,14 @@ interface
|
||||
|
||||
uses
|
||||
console,
|
||||
util,
|
||||
terminal,
|
||||
storagemanagement,
|
||||
util, terminal,
|
||||
lmemorymanager,
|
||||
strings,
|
||||
lists,
|
||||
tracer,
|
||||
serial,
|
||||
rtc,
|
||||
volumemanager,
|
||||
storagetypes;
|
||||
rtc;
|
||||
|
||||
type
|
||||
|
||||
@ -91,7 +89,7 @@ var
|
||||
filesystem : TFilesystem;
|
||||
|
||||
procedure init;
|
||||
procedure create_volume(volume : PStorage_Volume; sectors : uint32; start : uint32; config : puint32);
|
||||
procedure create_volume(disk : PStorage_Device; sectors : uint32; start : uint32; config : puint32);
|
||||
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 readDirectory(volume : PStorage_volume; directory : pchar; listPtr : PLinkedListBase) : uint8; //returns: 0 = success, 1 = dir not exsist, 2 = not directory, 3 = error
|
||||
@ -753,7 +751,7 @@ end;
|
||||
|
||||
//TODO check directory commands for errors with a clean disk
|
||||
|
||||
procedure create_volume(volume : PStorage_Volume; sectors : uint32; start : uint32; config : puint32);
|
||||
procedure create_volume(disk : PStorage_Device; sectors : uint32; start : uint32; config : puint32);
|
||||
var
|
||||
buffer : puint32;
|
||||
bt: puint32;
|
||||
@ -774,18 +772,9 @@ var
|
||||
programFileArray : byteArray8 = ('P','R','O','G','R','A','M','S');
|
||||
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?
|
||||
push_trace('fat32.create_volume()');
|
||||
|
||||
disk := volume^.device;
|
||||
|
||||
// zeroBuffer:= puint32(kalloc( disk^.sectorSize * 4 ));
|
||||
// memset(uint32(zeroBuffer), 0, disk^.sectorSize * 4);
|
||||
|
||||
@ -822,7 +811,7 @@ begin //maybe increase buffer size by one?
|
||||
bootRecord^.jmp2boot := $0; //TODO impliment boot jump
|
||||
bootRecord^.OEMName := asuroArray;
|
||||
bootRecord^.sectorSize := disk^.sectorsize;
|
||||
bootRecord^.spc := 1;
|
||||
bootRecord^.spc := config^;
|
||||
bootRecord^.rsvSectors := 32; //32 is standard
|
||||
bootRecord^.numFats := 1;
|
||||
bootRecord^.mediaDescp := $F8;
|
||||
@ -884,16 +873,8 @@ begin //maybe increase buffer size by one?
|
||||
|
||||
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);
|
||||
|
||||
|
||||
|
||||
end;
|
||||
|
||||
procedure detect_volumes(disk : PStorage_Device);
|
||||
@ -922,11 +903,11 @@ begin
|
||||
if (puint32(buffer)[127] = $55AA) and (PBootRecord(buffer)^.bsignature = $29) then begin //TODO partition table
|
||||
console.writestringln('FAT32: volume found!');
|
||||
volume^.device:= disk;
|
||||
volume^.sectorStart:= 1; //THIS MAKE SURE IF NOT FUCKY, cos im getting info from 2
|
||||
volume^.sectorStart:= 1;
|
||||
volume^.sectorSize:= PBootRecord(buffer)^.sectorSize;
|
||||
volume^.freeSectors:= 1000000; //TODO implement get free sectors need FSINFO implemented first
|
||||
volume^.filesystem := @filesystem;
|
||||
// storagemanagement.register_volume(disk, volume); TODO repalce with new thing
|
||||
storagemanagement.register_volume(disk, volume);
|
||||
end;
|
||||
|
||||
kfree(buffer);
|
||||
@ -936,7 +917,6 @@ procedure init();
|
||||
begin
|
||||
push_trace('fat32.init()');
|
||||
filesystem.sName:= 'FAT32';
|
||||
filesystem.system_id:= $01;
|
||||
filesystem.readDirCallback:= @readDirectoryGen;
|
||||
filesystem.createDirCallback:= @writeDirectoryGen;
|
||||
filesystem.createcallback:= @create_volume;
|
||||
@ -944,7 +924,7 @@ begin
|
||||
filesystem.writecallback:= @writeFile;
|
||||
filesystem.readcallback := @readFile;
|
||||
|
||||
volumemanager.register_filesystem(@filesystem);
|
||||
storagemanagement.register_filesystem(@filesystem);
|
||||
end;
|
||||
|
||||
end.
|
@ -1,725 +0,0 @@
|
||||
// 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.
|
@ -1,140 +0,0 @@
|
||||
// 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->IDE->idetypes - IDE device types and constants.
|
||||
|
||||
@author(Aaron Hance <ah@aaronhance.me>)
|
||||
}
|
||||
unit idetypes;
|
||||
|
||||
interface
|
||||
|
||||
const
|
||||
|
||||
ATA_SR_BUSY = $80; //BUSY
|
||||
ATA_SR_DRDY = $40; //DRIVE READY
|
||||
ATA_SR_DF = $20; //DRIVE WRITE FAULT
|
||||
ATA_SR_DSC = $10; //DRIVE SEEK COMPLETE
|
||||
ATA_SR_DRQ = $08; //DATA REQUEST READY
|
||||
ATA_SR_CORR = $04; //CORRECTED DATA
|
||||
ATA_SR_IDX = $02; //INLEX
|
||||
ATA_SR_ERR = $01; //ERROR
|
||||
|
||||
ATA_ER_BBK = $80; //BAD SECTOR
|
||||
ATA_ER_UNC = $40; //UNCORRECTABLE DATA
|
||||
ATA_ER_MC = $20; //NO MEDIA
|
||||
ATA_ER_IDNF = $10; //ID MARK NOT FOUND
|
||||
ATA_ER_MCR = $08; //NO MEDIA
|
||||
ATA_ER_ABRT = $04; //COMMAND ABORTED
|
||||
ATA_ER_TK0NF = $02; //TRACK 0 NOT FOUND
|
||||
ATA_ER_AMNF = $01; //NO ADDRESS MARK
|
||||
|
||||
ATA_CMD_READ_PIO = $20;
|
||||
ATA_CMD_READ_PIO_EXT = $24;
|
||||
ATA_CMD_READ_DMA = $C8;
|
||||
ATA_CMD_READ_DMA_EXT = $25;
|
||||
ATA_CMD_WRITE_PIO = $30;
|
||||
ATA_CMD_WRITE_PIO_EXT = $34;
|
||||
ATA_CMD_WRITE_DMA = $CA;
|
||||
ATA_CMD_WRITE_DMA_EXT = $35;
|
||||
ATA_CMD_CACHE_FLUSH = $E7;
|
||||
ATA_CMD_CACHE_FLUSH_EXT = $EA;
|
||||
ATA_CMD_PACKET = $A0;
|
||||
ATA_CMD_IDENTIFY_PACKET = $A1;
|
||||
ATA_CMD_IDENTIFY = $EC;
|
||||
|
||||
ATAPI_CMD_READ = $A8;
|
||||
ATAPI_CMD_EJECT = $1B;
|
||||
|
||||
ATA_IDENT_DEVICETYPE = $0;
|
||||
ATA_IDENT_CYLINDERS = $2;
|
||||
ATA_IDENT_HEADS = $6;
|
||||
ATA_IDENT_SECOTRS = $12;
|
||||
ATA_IDENT_SERIAL = $20;
|
||||
ATA_IDENT_MODEL = $54;
|
||||
ATA_IDENT_CAPABILITIES = $98;
|
||||
ATA_IDENT_FIELDVALID = $106;
|
||||
ATA_IDENT_MAX_LBA = $120;
|
||||
ATA_IDENT_COMMANDSETS = $164;
|
||||
ATA_IDENT_MAX_LBA_EXT = $200;
|
||||
|
||||
ATA_REG_DATA = $00;
|
||||
ATA_REG_ERROR = $01;
|
||||
ATA_REG_FEATURES = $01;
|
||||
ATA_REG_SECCOUNT = $02;
|
||||
ATA_REG_LBA0 = $03;
|
||||
ATA_REG_LBA1 = $04;
|
||||
ATA_REG_LBA2 = $05;
|
||||
ATA_REG_HDDEVSEL = $06;
|
||||
ATA_REG_COMMAND = $07;
|
||||
ATA_REG_STATUS = $07;
|
||||
ATA_REG_SECCOUNT1 = $08;
|
||||
ATA_REG_LBA3 = $09;
|
||||
ATA_REG_LBA4 = $0A;
|
||||
ATA_REG_LBA5 = $0B;
|
||||
ATA_REG_CONTROL = $0C;
|
||||
ATA_REG_ALTSTATUS = $0C;
|
||||
ATA_REG_DEVADDRESS = $0D;
|
||||
|
||||
ATA_DEVICE_MASTER = $A0;
|
||||
ATA_DEVICE_SLAVE = $B0;
|
||||
|
||||
ATA_PRIMARY_BASE = $1F0;
|
||||
ATA_PRIMARY_BASE1 = $3F6;
|
||||
ATA_SECONDARY_BASE = $170; //todo check this
|
||||
ATA_SECONDARY_BASE1 = $376; //todo check this
|
||||
|
||||
ATA_INTERRUPT_PRIMARY = $3F6;
|
||||
ATA_INTERRUPT_SECONDARY = $376;
|
||||
|
||||
type
|
||||
TPortMode = (P_READ, P_WRITE);
|
||||
|
||||
TIdentResponse = array[0..255] of uint16;
|
||||
PIdentResponse = ^TIdentResponse;
|
||||
|
||||
TIDE_Channel_Registers = record
|
||||
base : uint16;
|
||||
ctrl : uint16;
|
||||
bmide : uint16;
|
||||
noInter : uint8
|
||||
end;
|
||||
|
||||
TIDE_Status = bitpacked record
|
||||
Busy : Boolean;
|
||||
Ready : Boolean;
|
||||
Fault : Boolean;
|
||||
Seek : Boolean;
|
||||
DRQ : Boolean;
|
||||
CORR : Boolean;
|
||||
IDDEX : Boolean;
|
||||
ERROR : Boolean;
|
||||
end;
|
||||
PIDE_Status = ^TIDE_Status;
|
||||
|
||||
TIDE_Device = record
|
||||
exists : boolean;
|
||||
isPrimary : boolean;
|
||||
isMaster : boolean;
|
||||
isATAPI : boolean;
|
||||
status : TIDE_Status;
|
||||
base : uint16;
|
||||
info : PIdentResponse;
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
@ -1,504 +0,0 @@
|
||||
{ ************************************************
|
||||
* Asuro
|
||||
* Unit: Drivers/storage/IDE
|
||||
* Description: IDE ATA Driver
|
||||
*
|
||||
************************************************
|
||||
* Author: Aaron Hance
|
||||
* Contributors:
|
||||
************************************************ }
|
||||
unit IDE;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
util,
|
||||
drivertypes,
|
||||
console,
|
||||
terminal,
|
||||
drivermanagement,
|
||||
vmemorymanager,
|
||||
lmemorymanager,
|
||||
storagemanagement,
|
||||
strings,
|
||||
tracer,
|
||||
drivemanager,
|
||||
storagetypes;
|
||||
|
||||
type
|
||||
TPortMode = (P_READ, P_WRITE);
|
||||
|
||||
TIdentResponse = array[0..255] of uint16;
|
||||
|
||||
TIDE_Channel_Registers = record
|
||||
base : uint16;
|
||||
ctrl : uint16;
|
||||
bmide : uint16;
|
||||
noInter : uint8
|
||||
end;
|
||||
|
||||
TIDE_Device = record
|
||||
exists : boolean;
|
||||
isPrimary : boolean;
|
||||
isMaster : boolean;
|
||||
isATAPI : boolean;
|
||||
info : TIdentResponse;
|
||||
end;
|
||||
|
||||
TIDE_Status = bitpacked record
|
||||
Busy : Boolean;
|
||||
Ready : Boolean;
|
||||
Fault : Boolean;
|
||||
Seek : Boolean;
|
||||
DRQ : Boolean;
|
||||
CORR : Boolean;
|
||||
IDDEX : Boolean;
|
||||
ERROR : Boolean;
|
||||
end;
|
||||
PIDE_Status = ^TIDE_Status;
|
||||
|
||||
|
||||
const
|
||||
ATA_SR_BUSY = $80; //BUSY
|
||||
ATA_SR_DRDY = $40; //DRIVE READY
|
||||
ATA_SR_DF = $20; //DRIVE WRITE FAULT
|
||||
ATA_SR_DSC = $10; //DRIVE SEEK COMPLETE
|
||||
ATA_SR_DRQ = $08; //DATA REQUEST READY
|
||||
ATA_SR_CORR = $04; //CORRECTED DATA
|
||||
ATA_SR_IDX = $02; //INLEX
|
||||
ATA_SR_ERR = $01; //ERROR
|
||||
|
||||
ATA_ER_BBK = $80; //BAD SECTOR
|
||||
ATA_ER_UNC = $40; //UNCORRECTABLE DATA
|
||||
ATA_ER_MC = $20; //NO MEDIA
|
||||
ATA_ER_IDNF = $10; //ID MARK NOT FOUND
|
||||
ATA_ER_MCR = $08; //NO MEDIA
|
||||
ATA_ER_ABRT = $04; //COMMAND ABORTED
|
||||
ATA_ER_TK0NF = $02; //TRACK 0 NOT FOUND
|
||||
ATA_ER_AMNF = $01; //NO ADDRESS MARK
|
||||
|
||||
ATA_CMD_READ_PIO = $20;
|
||||
ATA_CMD_READ_PIO_EXT = $24;
|
||||
ATA_CMD_READ_DMA = $C8;
|
||||
ATA_CMD_READ_DMA_EXT = $25;
|
||||
ATA_CMD_WRITE_PIO = $30;
|
||||
ATA_CMD_WRITE_PIO_EXT = $34;
|
||||
ATA_CMD_WRITE_DMA = $CA;
|
||||
ATA_CMD_WRITE_DMA_EXT = $35;
|
||||
ATA_CMD_CACHE_FLUSH = $E7;
|
||||
ATA_CMD_CACHE_FLUSH_EXT = $EA;
|
||||
ATA_CMD_PACKET = $A0;
|
||||
ATA_CMD_IDENTIFY_PACKET = $A1;
|
||||
ATA_CMD_IDENTIFY = $EC;
|
||||
|
||||
ATAPI_CMD_READ = $A8;
|
||||
ATAPI_CMD_EJECT = $1B;
|
||||
|
||||
ATA_IDENT_DEVICETYPE = $0;
|
||||
ATA_IDENT_CYLINDERS = $2;
|
||||
ATA_IDENT_HEADS = $6;
|
||||
ATA_IDENT_SECOTRS = $12;
|
||||
ATA_IDENT_SERIAL = $20;
|
||||
ATA_IDENT_MODEL = $54;
|
||||
ATA_IDENT_CAPABILITIES = $98;
|
||||
ATA_IDENT_FIELDVALID = $106;
|
||||
ATA_IDENT_MAX_LBA = $120;
|
||||
ATA_IDENT_COMMANDSETS = $164;
|
||||
ATA_IDENT_MAX_LBA_EXT = $200;
|
||||
|
||||
ATA_REG_DATA = $00;
|
||||
ATA_REG_ERROR = $01;
|
||||
ATA_REG_FEATURES = $01;
|
||||
ATA_REG_SECCOUNT = $02;
|
||||
ATA_REG_LBA0 = $03;
|
||||
ATA_REG_LBA1 = $04;
|
||||
ATA_REG_LBA2 = $05;
|
||||
ATA_REG_HDDEVSEL = $06;
|
||||
ATA_REG_COMMAND = $07;
|
||||
ATA_REG_STATUS = $07;
|
||||
ATA_REG_SECCOUNT1 = $08;
|
||||
ATA_REG_LBA3 = $09;
|
||||
ATA_REG_LBA4 = $0A;
|
||||
ATA_REG_LBA5 = $0B;
|
||||
ATA_REG_CONTROL = $0C;
|
||||
ATA_REG_ALTSTATUS = $0C;
|
||||
ATA_REG_DEVADDRESS = $0D;
|
||||
|
||||
ATA_DEVICE_MASTER = $A0;
|
||||
ATA_DEVICE_SLAVE = $B0;
|
||||
|
||||
ATA_PRIMARY_BASE = $1F0;
|
||||
|
||||
var
|
||||
controller : PPCI_Device;
|
||||
|
||||
bar0 : uint32;
|
||||
bar1 : uint32;
|
||||
bar4 : uint32;
|
||||
|
||||
IDEDevices : array[0..3] of TIDE_Device;
|
||||
|
||||
buffer : Puint32;
|
||||
|
||||
procedure init();
|
||||
function load(ptr : void) : boolean;
|
||||
function identify_device(bus : uint8; device : uint8) : TIdentResponse;
|
||||
|
||||
// procedure flush();
|
||||
procedure readPIO28(drive : uint8; LBA : uint32; buffer : puint8);
|
||||
procedure writePIO28(drive : uint8; LBA : uint32; buffer : puint8);
|
||||
//read/write must be capable of reading/writting any amknt of data upto disk size
|
||||
|
||||
procedure dread(device : PStorage_device; LBA : uint32; sectorCount : uint32; buffer : puint32);
|
||||
procedure dwrite(device : PStorage_device; LBA : uint32; sectorCount : uint32; buffer : puint32);
|
||||
|
||||
implementation
|
||||
|
||||
function port_read(register : uint8) : uint8;
|
||||
begin
|
||||
port_read:= inb(ATA_PRIMARY_BASE + register);
|
||||
end;
|
||||
|
||||
procedure port_write(register : uint8; data : uint8);
|
||||
var
|
||||
i : uint8;
|
||||
begin
|
||||
outb(ATA_PRIMARY_BASE + register, data);
|
||||
util.psleep(1);
|
||||
if register = ATA_REG_COMMAND then begin
|
||||
for i:= 0 to 5 do begin
|
||||
port_read(ATA_REG_STATUS);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure no_interrupt(device : uint8);
|
||||
begin
|
||||
outb($3F6, inb($3f6) or (1 shl 1));
|
||||
end;
|
||||
|
||||
procedure device_select(device : uint8);
|
||||
begin
|
||||
outb($1F6, device); //TODO clean
|
||||
end;
|
||||
|
||||
function is_ready() : boolean;
|
||||
var
|
||||
status : uint8;
|
||||
i : uint32;
|
||||
begin
|
||||
//wait for drive to be ready
|
||||
while true do begin
|
||||
status := port_read(ATA_REG_COMMAND);
|
||||
|
||||
if(status and ATA_SR_ERR) = ATA_SR_ERR then begin
|
||||
console.writestringln('[IDE] (IDENTIFY_DEVICE) DRIVE ERROR!');
|
||||
console.redrawWindows();
|
||||
is_ready := false;
|
||||
break;
|
||||
end;
|
||||
|
||||
if (status and ATA_SR_BUSY) <> ATA_SR_BUSY then begin
|
||||
is_ready := true;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function validate_28bit_address(addr : uint32) : boolean;
|
||||
begin
|
||||
validate_28bit_address := (addr and $F0000000) = 0;
|
||||
end;
|
||||
|
||||
function identify_device(bus : uint8; device : uint8) : TIdentResponse;
|
||||
var
|
||||
status : uint8;
|
||||
identResponse : TIdentResponse;
|
||||
i : uint8;
|
||||
begin
|
||||
push_trace('IDE.Identify_Device');
|
||||
device_select(device);
|
||||
no_interrupt(device);
|
||||
port_write(ATA_REG_CONTROL, 0);
|
||||
|
||||
console.writestringln('[IDE] (IDENTIFY_DEVICE) CHECK FLOATING BUS');
|
||||
|
||||
//check if bus is floating
|
||||
status := port_read(ATA_REG_COMMAND);
|
||||
if status = $FF then exit;
|
||||
|
||||
port_write(ATA_REG_SECCOUNT, 0);
|
||||
port_write(ATA_REG_LBA0, 0);
|
||||
port_write(ATA_REG_LBA1, 0);
|
||||
port_write(ATA_REG_LBA2, 0);
|
||||
|
||||
console.writestringln('[IDE] (IDENTIFY_DEVICE) SEND IDENTIFY COMMAND');
|
||||
|
||||
port_write(ATA_REG_COMMAND, ATA_CMD_IDENTIFY);
|
||||
|
||||
console.writestringln('[IDE] (IDENTIFY_DEVICE) WAIT FOR DRIVE TO BE READY');
|
||||
|
||||
//check if drive is present
|
||||
status := port_read(ATA_REG_COMMAND);
|
||||
if status = $00 then exit;
|
||||
|
||||
console.writestringln('[IDE] (IDENTIFY_DEVICE) WAIT FOR DRIVE TO BE READY');
|
||||
|
||||
if not is_ready() then exit;
|
||||
|
||||
console.writestringln('[IDE] (IDENTIFY_DEVICE) READ IDENTIFY RESPONSE');
|
||||
|
||||
for i:=0 to 255 do begin
|
||||
console.writeint(i);
|
||||
identResponse[i] := inw(ATA_PRIMARY_BASE + ATA_REG_DATA);
|
||||
end;
|
||||
|
||||
console.writestringln('[IDE] (IDENTIFY_DEVICE) IDENTIFY RESPONSE RECEIVED');
|
||||
|
||||
identify_device := identResponse;
|
||||
end;
|
||||
|
||||
procedure init();
|
||||
var
|
||||
devID : TDeviceIdentifier;
|
||||
begin
|
||||
push_trace('ide.init');
|
||||
console.writestringln('[IDE] (INIT) BEGIN');
|
||||
devID.bus:= biPCI;
|
||||
devID.id0:= idANY;
|
||||
devID.id1:= $00000001;
|
||||
devID.id2:= $00000001;
|
||||
devID.id3:= idANY;
|
||||
devID.id4:= idANY;
|
||||
devID.ex:= nil;
|
||||
drivermanagement.register_driver('IDE ATA Driver', @devID, @load);
|
||||
console.writestringln('[IDE] (INIT) END');
|
||||
end;
|
||||
|
||||
function load(ptr : void) : boolean;
|
||||
var
|
||||
controller : PPCI_Device;
|
||||
masterDevice : TStorage_Device;
|
||||
slaveDevice : TStorage_Device;
|
||||
buffer : puint8;
|
||||
i : uint8;
|
||||
test : PStorage_device;
|
||||
tbuf : puint8;
|
||||
begin
|
||||
push_trace('ide.load');
|
||||
console.writestringln('[IDE] (LOAD) BEGIN');
|
||||
controller := PPCI_Device(ptr);
|
||||
|
||||
console.writestringln('[IDE] (INIT) CHECK FLOATING BUS');
|
||||
//check if bus is floating and identify device
|
||||
if inb($1F7) <> $FF then begin
|
||||
//outb($3F6, inb($3f6) or (1 shl 1)); // disable interrupts
|
||||
IDEDevices[0].isMaster:= true;
|
||||
IDEDevices[0].info := identify_device(0, ATA_DEVICE_MASTER);
|
||||
e
|
||||
mastrDevice.controller := ControllerIDE;
|
||||
masterDevice.controllerId0:= 0;
|
||||
masterDevice.maxSectorCount:= (IDEDevices[0].info[60] or (IDEDevices[0].info[61] shl 16) ); //LBA28 SATA
|
||||
|
||||
if IDEDevices[0].info[1] = 0 then begin
|
||||
console.writestringln('[IDE] (INIT) ERROR: DEVICE IDENT FAILED!');
|
||||
exit;
|
||||
end;
|
||||
|
||||
// masterDevice.hpc:= uint32(IDEDevices[0].info[3] DIV IDEDevices[0].info[1]); //TODO wtf is hpc
|
||||
|
||||
masterDevice.sectorSize:= 512;
|
||||
if masterDevice.maxSectorCount <> 0 then begin
|
||||
IDEDevices[0].exists:= true;
|
||||
masterDevice.readCallback:= @dread;
|
||||
masterDevice.writeCallback:= @dwrite;
|
||||
// storagemanagement.register_device(@masterDevice);
|
||||
drivemanager.register_device(@masterDevice);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
// buffer:= puint8(kalloc(512));
|
||||
// buffer[0] := 1;
|
||||
// buffer[1] := 2;
|
||||
// buffer[2] := 3;
|
||||
// buffer[3] := 4;
|
||||
// buffer[4] := 5;
|
||||
// buffer[5] := 6;
|
||||
// writePIO28(0, 3, buffer);
|
||||
// writePIO28(0, 3, buffer);
|
||||
// writePIO28(0, 3, buffer);
|
||||
// writePIO28(0, 4, buffer);
|
||||
// writePIO28(0, 5, buffer);
|
||||
// writePIO28(0, 5, buffer);
|
||||
// writePIO28(0, 5, buffer);
|
||||
// psleep(1000);
|
||||
// writePIO28(0, 5, buffer);
|
||||
// writePIO28(0, 5, buffer);
|
||||
// writePIO28(0, 5, buffer);
|
||||
// kfree(puint32(buffer));
|
||||
|
||||
console.writestringln('[IDE] (LOAD) END');
|
||||
|
||||
//read first 16 bytes of disk
|
||||
tbuf:= puint8(kalloc(512));
|
||||
|
||||
//set buffer to 1F1F repeating
|
||||
for i:=0 to 200 do begin
|
||||
tbuf[i] := 31;
|
||||
end;
|
||||
|
||||
//write buffer to disk
|
||||
writePIO28(0, 0, tbuf);
|
||||
|
||||
memset(uint32(tbuf), 0, 512);
|
||||
readPIO28(0, 0, puint8(tbuf));
|
||||
console.writestringln('[IDE] (INIT) READ FIRST 4 BYTES OF DISK');
|
||||
console.writehexln(tbuf[0]);
|
||||
console.writehexln(tbuf[1]);
|
||||
console.writehexln(tbuf[2]);
|
||||
console.writehexln(tbuf[3]);
|
||||
kfree(puint32(tbuf));
|
||||
|
||||
|
||||
|
||||
end;
|
||||
|
||||
procedure readPIO28(drive : uint8; LBA : uint32; buffer : puint8);
|
||||
var
|
||||
status : uint8;
|
||||
i: uint16;
|
||||
device: uint8;
|
||||
data: uint16;
|
||||
begin
|
||||
push_trace('IDE.readPIO28');
|
||||
|
||||
if not validate_28bit_address(LBA) then begin
|
||||
console.writestringln('IDE (writePIO28) ERROR: Invalid LBA!');
|
||||
end;
|
||||
|
||||
// push_trace('IDE.readPIO28.2');
|
||||
|
||||
//Add last 4 bits of LBA to device port
|
||||
if IDEDevices[drive].isMaster then begin
|
||||
device:= ATA_DEVICE_MASTER;
|
||||
device_select($E0 or ((LBA and $0F000000) shr 24)); //LBA primary master
|
||||
end
|
||||
else begin
|
||||
device:= ATA_DEVICE_SLAVE;
|
||||
device_select($F0 or ((LBA and $0F000000) shr 24)); //LBA primary slave
|
||||
end;
|
||||
|
||||
// push_trace('IDE.readPIO28.3');
|
||||
|
||||
no_interrupt(device);
|
||||
port_write(ATA_REG_ERROR, 0);
|
||||
|
||||
//Write sector count and LBA
|
||||
port_write(ATA_REG_SECCOUNT, 1);
|
||||
port_write(ATA_REG_LBA0, (LBA and $000000FF));
|
||||
port_write(ATA_REG_LBA1, (LBA and $0000FF00) shr 8);
|
||||
port_write(ATA_REG_LBA2, (LBA and $00FF0000) shr 16);
|
||||
|
||||
// push_trace('IDE.readPIO28.4');
|
||||
|
||||
//send read command
|
||||
port_write(ATA_REG_COMMAND, ATA_CMD_READ_PIO);
|
||||
if not is_ready() then exit;
|
||||
|
||||
i:=0;
|
||||
while i < 512 do begin
|
||||
// if not is_ready() then exit;
|
||||
|
||||
data:= inw(ATA_PRIMARY_BASE + ATA_REG_DATA);
|
||||
|
||||
buffer[i+1] := uint8($00ff and (data shr 8));
|
||||
buffer[i] := uint8($00ff and data);
|
||||
|
||||
i:= i + 2;
|
||||
|
||||
if not is_ready() then exit;
|
||||
end;
|
||||
|
||||
// push_trace('IDE.readPIO28.5');
|
||||
end;
|
||||
|
||||
procedure writePIO28(drive : uint8; LBA : uint32; buffer : puint8);
|
||||
var
|
||||
status : uint8;
|
||||
i: uint16;
|
||||
device: uint8;
|
||||
begin
|
||||
push_trace('IDE.WritePIO28');
|
||||
if not validate_28bit_address(LBA) then begin
|
||||
console.writestringln('IDE (writePIO28) ERROR: Invalid LBA!');
|
||||
end;
|
||||
|
||||
console.writeintln(uint32(drive));
|
||||
console.writeintln(LBA);
|
||||
|
||||
//Add last 4 bits of LBA to device port
|
||||
if IDEDevices[drive].isMaster then begin
|
||||
device:= ATA_DEVICE_MASTER;
|
||||
device_select($E0 or ((LBA and $0F000000) shr 24)); //LBA primary master
|
||||
end
|
||||
else begin
|
||||
device:= ATA_DEVICE_SLAVE;
|
||||
device_select($F0 or ((LBA and $0F000000) shr 24)); //LBA primary slave
|
||||
end;
|
||||
|
||||
// no_interrupt(device);
|
||||
|
||||
port_write(ATA_REG_ERROR, 0);
|
||||
port_write(ATA_REG_CONTROL, 0);
|
||||
|
||||
// check if bus is floating
|
||||
status := port_read(ATA_REG_COMMAND);
|
||||
if status = $FF then exit;
|
||||
|
||||
//Write sector count and LBA
|
||||
port_write(ATA_REG_SECCOUNT, 1);
|
||||
port_write(ATA_REG_LBA0, (LBA and $000000FF));
|
||||
port_write(ATA_REG_LBA1, (LBA and $0000FF00) shr 8);
|
||||
port_write(ATA_REG_LBA2, (LBA and $00FF0000) shr 16);
|
||||
|
||||
//send write command
|
||||
port_write(ATA_REG_COMMAND, ATA_CMD_WRITE_PIO);
|
||||
|
||||
//write data
|
||||
i:=0;
|
||||
while i < 512 do begin
|
||||
outw(ATA_PRIMARY_BASE + ATA_REG_DATA, uint16(buffer[i] or (buffer[i+1] shl 8)));
|
||||
i:= i + 2;
|
||||
end;
|
||||
|
||||
//flush drive cache
|
||||
psleep(1);
|
||||
port_write(ATA_REG_COMMAND, ATA_CMD_CACHE_FLUSH);
|
||||
psleep(1);
|
||||
if not is_ready() then exit;
|
||||
end;
|
||||
|
||||
procedure dread(device : PStorage_device; LBA : uint32; sectorCount : uint32; buffer : Puint32);
|
||||
var
|
||||
i : uint16;
|
||||
begin
|
||||
push_trace('IDE.dread');
|
||||
for i:=0 to sectorCount-1 do begin
|
||||
readPIO28(device^.controllerId0, LBA + i, puint8(@buffer[512*i]));
|
||||
psleep(100)
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure dwrite(device : PStorage_device; LBA : uint32; sectorCount : uint32; buffer : Puint32);
|
||||
var
|
||||
i : uint16;
|
||||
begin
|
||||
for i:=0 to sectorCount-1 do begin
|
||||
writePIO28(device^.controllerId0, LBA + i, puint8(@buffer[512*i]));
|
||||
psleep(100)
|
||||
end;
|
||||
// writePIO28(device^.controllerId0, LBA, puint8(buffer));
|
||||
end;
|
||||
|
||||
end.
|
@ -15,8 +15,6 @@
|
||||
{
|
||||
Driver->Storage->StorageManagment Storage Managment System
|
||||
|
||||
DEPRECATED unit
|
||||
|
||||
@author(Aaron Hance ah@aaronhance.me)
|
||||
}
|
||||
unit storagemanagement;
|
||||
@ -33,14 +31,14 @@ uses
|
||||
strings,
|
||||
lists,
|
||||
tracer,
|
||||
rtc,
|
||||
MBR,
|
||||
volumemanager,
|
||||
storagetypes;
|
||||
rtc;
|
||||
|
||||
type
|
||||
|
||||
TControllerType = (ControllerIDE, ControllerUSB, ControllerAHCI, ControllerNET, ControllerRAM, rsvctr1, rsvctr2, rsvctr3);
|
||||
TDirectory_Entry_Type = (directoryEntry, fileEntry, mountEntry);
|
||||
PStorage_volume = ^TStorage_Volume;
|
||||
PStorage_device = ^TStorage_Device;
|
||||
APStorage_Volume = array[0..10] of PStorage_volume;
|
||||
byteArray8 = array[0..7] of char;
|
||||
PByteArray8 = ^byteArray8;
|
||||
@ -56,6 +54,41 @@ type
|
||||
|
||||
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;
|
||||
|
||||
{ Generic directory entry }
|
||||
@ -77,13 +110,20 @@ procedure init();
|
||||
procedure register_device(device : PStorage_Device);
|
||||
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
|
||||
|
||||
function controller_type_2_string(controllerType : TControllerType) : pchar;
|
||||
begin
|
||||
case controllerType of
|
||||
ControllerATA : controller_type_2_string:= 'ATA';
|
||||
ControllerATAPI : controller_type_2_string:= 'ATAPI';
|
||||
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';
|
||||
@ -129,57 +169,18 @@ var
|
||||
drive : PStorage_Device;
|
||||
|
||||
filesystemString : pchar;
|
||||
filesystem : PFileSystem;
|
||||
spc : puint32;
|
||||
|
||||
sectorCount : uint32;
|
||||
volumeId : uint8;
|
||||
|
||||
mb : PMaster_Boot_Record;
|
||||
i : uint32 = 0;
|
||||
|
||||
begin
|
||||
|
||||
//format <DRIVE_ID> <FILESYSTEM> <size>
|
||||
|
||||
spc:= puint32(kalloc(4));
|
||||
spc^:= 1;
|
||||
spc^:= 4;
|
||||
|
||||
driveIndex:= stringToInt( getParam(1, params) );
|
||||
drive:= PStorage_Device(LL_Get(storageDevices, driveIndex));
|
||||
|
||||
filesystemString := getParam(2, params);
|
||||
|
||||
sectorCount := stringToInt( getParam(4, params) );
|
||||
|
||||
// if sector count is 0, use full drive
|
||||
if sectorCount = 0 then begin
|
||||
sectorCount := drive^.maxSectorCount - 10;
|
||||
end;
|
||||
|
||||
//create MBR if none, and partition table
|
||||
|
||||
mb := PMaster_Boot_Record(kalloc(sizeof(TMaster_Boot_Record)));
|
||||
drive^.readCallback(drive, 0, 1, PuInt32(mb));
|
||||
|
||||
//check if MBR exists
|
||||
if not mb^.boot_sector = $55AA then begin
|
||||
|
||||
//create MBR
|
||||
mb^.signature := $A570 + drive^.id;
|
||||
mb^.boot_sector := $55AA;
|
||||
|
||||
//create partition table
|
||||
mbr.setup_partition(@mb^.partition[0], 2, sectorCount);
|
||||
|
||||
//write MBR
|
||||
drive^.writeCallback(drive, 0, 1, puint32(mb));
|
||||
|
||||
end;
|
||||
|
||||
kfree(puint32(mb));
|
||||
|
||||
//setup volume
|
||||
volumemanager.create_volume(drive, filesystemString, 2, sectorCount);
|
||||
//todo change b4 adding in aniother filesytem
|
||||
PFilesystem(LL_Get(filesystems, 0))^.createCallback(drive, drive^.maxSectorCount-1, 1, spc);
|
||||
|
||||
writestringWnd('Drive ', getTerminalHWND);
|
||||
writeintWnd(driveIndex, getTerminalHWND);
|
||||
@ -216,6 +217,10 @@ begin
|
||||
format_command(params);
|
||||
end;
|
||||
|
||||
//lsfs command for listing filesystems
|
||||
if stringEquals(subcmd, 'lsfs') then begin
|
||||
end;
|
||||
|
||||
pop_trace();
|
||||
end;
|
||||
|
||||
@ -226,8 +231,10 @@ begin
|
||||
|
||||
setworkingdirectory('.');
|
||||
storageDevices:= ll_new(sizeof(TStorage_Device));
|
||||
fileSystems:= ll_New(sizeof(TFilesystem));
|
||||
terminal.registerCommand('DISK', @disk_command, 'Disk utility');
|
||||
|
||||
pop_trace();
|
||||
end;
|
||||
|
||||
{ Register a new drive with the storage manager }
|
||||
@ -246,7 +253,9 @@ begin
|
||||
PStorage_Device(LL_Get(storageDevices, LL_Size(storageDevices) - 1))^.volumes := LL_New(sizeof(TStorage_Volume));
|
||||
|
||||
//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();
|
||||
end;
|
||||
@ -256,4 +265,23 @@ begin
|
||||
get_device_list:= storageDevices;
|
||||
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.
|
@ -1,64 +0,0 @@
|
||||
// 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 = (ControllerATA, ControllerATAPI, 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.
|
@ -1,429 +0,0 @@
|
||||
// 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.
|
@ -143,6 +143,22 @@ type
|
||||
|
||||
PText = ^Text;
|
||||
|
||||
var
|
||||
AK_START : uint32; external name 'kernel_start';
|
||||
AK_END : uint32; external name 'kernel_end';
|
||||
ASURO_KERNEL_START : uint32;
|
||||
ASURO_KERNEL_END : uint32;
|
||||
ASURO_KERNEL_SIZE : uint32;
|
||||
|
||||
procedure init();
|
||||
|
||||
implementation
|
||||
|
||||
procedure init();
|
||||
begin
|
||||
ASURO_KERNEL_START := uint32(@AK_START);
|
||||
ASURO_KERNEL_END := uint32(@AK_END);
|
||||
ASURO_KERNEL_SIZE:= ASURO_KERNEL_END - ASURO_KERNEL_START;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
@ -41,12 +41,9 @@ uses
|
||||
E1000,
|
||||
IDE,
|
||||
storagemanagement,
|
||||
drivemanager,
|
||||
volumemanager,
|
||||
lists,
|
||||
net,
|
||||
fat32,
|
||||
flatfs,
|
||||
isrmanager,
|
||||
faults,
|
||||
fonts,
|
||||
@ -128,6 +125,9 @@ var
|
||||
HM : PHashMap;
|
||||
|
||||
begin
|
||||
{ Init the base system unit }
|
||||
System.init();
|
||||
|
||||
{ Serial Init }
|
||||
serial.init();
|
||||
|
||||
@ -208,9 +208,7 @@ begin
|
||||
tracer.push_trace('kmain.DRVMGMT');
|
||||
drivermanagement.init();
|
||||
tracer.push_trace('kmain.STRMGMT');
|
||||
// storagemanagement.init();
|
||||
drivemanager.init();
|
||||
volumemanager.init();
|
||||
storagemanagement.init();
|
||||
|
||||
{ Hook Timer for Ticks }
|
||||
tracer.push_trace('kmain.TMR');
|
||||
@ -219,7 +217,6 @@ begin
|
||||
|
||||
{ Filsystems }
|
||||
fat32.init();
|
||||
flatfs.init();
|
||||
|
||||
{ Device Drivers }
|
||||
tracer.push_trace('kmain.DEVDRV');
|
||||
|
Reference in New Issue
Block a user