Files

404 lines
10 KiB
Plaintext

seti $printhelp = $printhelp
seti $help = $help
if $help = 1
echo 'This will read the drive and write the data to an image file.'
echo 'It uses PIO read commands and adjusts if extended commands are supported.'
echo 'Please note that this program is in no way optimized for this,'
echo ' and is very limited in features.
echo 'This is not meant as a robust way to image a device.'
echo 'Making an image using a script file will never be as fast as possible.'
echo 'Reads are done in blocks (clusters) of 256 sectors.'
echo 'This means that all warnings and errors show the position'
echo ' of the first sector of the block, NOT the actual problem sector.'
echo 'This requires the number variable startsector to be set.'
echo 'This requires the number variable endsector to be set.'
echo 'If endsector is set to 0, it will default to the last addressable sector.'
echo 'This uses the identify device command to determine the last sector.'
echo 'This requires the number variable timeout to be set.'
echo 'Timeout is the time in milliseconds to wait before giving up on a command.'
echo 'If timeout is set to 0, it will default to 10000ms.'
echo 'This requires the string variable logfile to be set.'
echo 'Logfile will capture all the warnings and errors.'
echo 'If logfile is blank then no log will be produced.'
echo 'This requires the string variable imagefile to be set.'
echo 'Imagefile is the file where the data will be written.'
echo 'If imagefile is blank then no image file will be produced.'
echo 'Example:'
echo 'opensuperclone --tool -t /dev/sda -f ata_image_device timeout=0 startsector=0 endsector=0 logfile=="image.log" imagefile=="image.bin"'
if $printhelp = 1
exit 0
endif
echo 'Hit ENTER to continue...'
userinput $choicestring
previousscript
endif
echo 'This script is meant for testing, not actually imaging a drive.'
echo 'While it may be somewhat capable, it has many limitations.'
include good_subroutines.osc
sets $null = ""
seti $using_menu = $using_menu
seti $ask = 0
while 1 = 1
variablecheck $startsector
if $error_level < 16
seti $ask = 1
elseif $using_menu = 1
seti $ask = 1
endif
if $ask = 1
echo "Enter start sector, or leave blank for first:"
userinput $choicestring
if $choicestring != $null
seti $startsector = $choicestring 0
break
else
seti $startsector = 0
break
endif
else
break
endif
done
seti $ask = 0
while 1 = 1
variablecheck $endsector
if $error_level < 16
seti $ask = 1
elseif $using_menu = 1
seti $ask = 1
endif
if $ask = 1
echo "Enter end sector, or leave blank for last:"
userinput $choicestring
if $choicestring != $null
seti $endsector = $choicestring 0
break
else
seti $endsector = 0
break
endif
else
break
endif
done
seti $ask = 0
while 1 = 1
variablecheck $timeout
if $error_level < 16
seti $ask = 1
elseif $using_menu = 1
seti $ask = 1
endif
if $ask = 1
echo "Enter timeout in ms, or leave blank for default(10000ms):"
userinput $choicestring
if $choicestring != $null
seti $timeout = $choicestring 0
break
else
seti $timeout = 10000
break
endif
else
break
endif
done
if $timeout = 0
seti $timeout = 10000
endif
seti $timeout = $timeout * 1000
softtimeout $timeout
seti $ask = 0
variablecheck $logfile
if $error_level < 16
seti $ask = 1
elseif $using_menu = 1
seti $ask = 1
endif
if $ask = 1
echo "Enter logfile name, or leave blank for no log:"
userinput $choicestring
sets $logfile = $choicestring
endif
seti $ask = 0
variablecheck $imagefile
if $error_level < 16
seti $ask = 1
elseif $using_menu = 1
seti $ask = 1
endif
if $ask = 1
echo "Enter image file name, or leave blank to not create an image:"
userinput $choicestring
sets $imagefile = $choicestring
endif
# get the size of the drive using identify device command
buffersize 512
setreadpio
ata28cmd 0 0 0 0 0 0xa0 0xec
# check if command failed
seti $command_failed = 0
gosub check_command_status
if $command_failed = 1
echo "Identify device command failed!"
gosub show_sense_data
gosub show_ata_return_status
previousscript
endif
# check if drive supports extended commands
seti $tempnum = buffer 167
seti $extended = $tempnum & 4
# total addressable sectors
if $extended > 0
seti $addressable = buffer 200 qw
else
seti $addressable = buffer 120 dw
endif
if $endsector = 0
seti $endsector = $addressable
endif
seti $blocksize = 256
seti $buffersize = $blocksize * 512
buffersize $buffersize
setreadpio
seti $currentposition = $startsector
seti $previousposition = $currentposition
seti $blockposition = $currentposition
seti $processedsectors = 0
seti $totalsectors = $endsector - $startsector
seti $errorcount = 0
if $logfile != $null
#deletefile $logfile
gettime
sets $line = "# error log " $date
writelog $logfile $line
sets $line = "# cluster size is " $blocksize
writelog $logfile $line
endif
gettime
seti $displaytime = $time
seti $redodisplay = 1
echo " "
echo " "
echo " "
echo " "
echo " "
echo " "
echo " "
gettime
seti $programstart = $time
while $currentposition < $endsector
seti $sector = $currentposition
if $extended > 0
seti $features = 0
seti $count = $blocksize
seti $LBAlow = $sector & 0xffff
seti $temp = $sector > 16
seti $LBAmid = $temp & 0xffff
seti $temp = $sector > 32
seti $LBAhigh = $temp & 0xffff
seti $device = 0xe0
seti $command = 0x24
gettime
seti $startreadtime = $time
ata48cmd $features $count $LBAhigh $LBAmid $LBAlow $device $command
gettime
seti $endreadtime = $time
else
seti $features = 0
seti $count = $blocksize & 0xff
seti $LBAlow = $sector & 0xff
seti $temp = $sector > 8
seti $LBAmid = $temp & 0xff
seti $temp = $sector > 16
seti $LBAhigh = $temp & 0xff
seti $temp = $sector > 24
seti $LBAdevice = $temp & 0x0f
seti $device = 0xe0
seti $device = $device | $LBAdevice
seti $command = 0x20
gettime
seti $startreadtime = $time
ata28cmd $features $count $LBAlow $LBAmid $LBAhigh $device $command
gettime
seti $endreadtime = $time
endif
# check if command failed
seti $command_failed = 0
gosub check_command_status
if $command_failed = 1
seti $devicefault = $ata_return_status & 0x20
endif
# write the data to the file
if $imagefile != $null
if $command_failed = 0
seti $writeoffset = $currentposition * 512
seti $writesize = $blocksize * 512
writebuffer $imagefile 0 $writeoffset $writesize
endif
endif
seti $readtime = $endreadtime - $startreadtime
if $command_failed = 1
seti $errorcount = $errorcount + 1
endif
seti $showerror = 0
if $command_failed = 1
seti $showerror = 1
endif
if $showerror > 0
upline
upline
upline
upline
upline
upline
upline
seti $adjustedtime = $readtime / 1000
hex
sets $errorstring = "e=0x" $ata_return_error " s=0x" $ata_return_status
decimal
if $direct_mode = 1
seti $command_status = $command_status & 0xf0
if $command_status = 0x20
sets $status = "BUSY"
elseif $command_status = 0x30
sets $status = "TIMEOUT/RESET"
elseif $command_status = 0x40
sets $status = "TIMEOUT/RESET/BUSY"
elseif $command_status = 0x50
sets $status = "TIMEOUT"
elseif $command_status = 0x60
sets $status = "NO DRQ"
elseif $command_status = 0x70
sets $status = "WRONG DEVICE"
else
sets $status = ""
endif
else
sets $status = ""
endif
sets $outputline = "ERROR " $status " " $currentposition " " $adjustedtime "ms " $errorstring
echo $outputline
echo $null
echo $null
echo $null
echo $null
echo $null
echo $null
echo $null
seti $redodisplay = 1
if $logfile != $null
writelog $logfile $outputline
endif
endif
seti $elapsedtime = $endreadtime - $displaytime
if $elapsedtime > 1000000
seti $redodisplay = 1
endif
if $redodisplay = 1
seti $sectorstransferred = $currentposition - $previousposition
seti $previousposition = $currentposition
seti $bytestransferred = $sectorstransferred * 512
seti $adjustedbytes = $bytestransferred * 1000000
seti $currentspeed = $adjustedbytes / $elapsedtime
seti $currentspeed = $currentspeed / 1000
gosub displayoutput
seti $displaytime = $endreadtime
endif
seti $redodisplay = 0
if $devicefault > 0
echo "Device fault detected!"
echo "Current position= " $currentposition
gosub show_ata_return_status
break
endif
seti $currentposition = $currentposition + $blocksize
seti $processedsectors = $processedsectors + $blocksize
# check if last read is less than blocksize
seti $partial = $currentposition + $blocksize
if $partial > $endsector
if $currentposition < $endsector
seti $blocksize = $endsector - $currentposition
seti $buffersize = $blocksize * 512
buffersize $buffersize
endif
endif
done
if $devicefault = 0
gosub displayoutput
endif
previousscript
end
subroutine displayoutput
upline
upline
upline
upline
upline
upline
echo " "
gettime
seti $totaltime = $time - $programstart
seti $totalseconds = $totaltime / 1000000
seti $remainder = $totaltime % 1000000
seti $totalminutes = $totalseconds / 60
seti $seconds = $totalseconds % 60
seti $hours = $totalminutes / 60
seti $minutes = $totalminutes % 60
echo "elapsed time h:m:s = " $hours ":" $minutes ":" $seconds "." $remainder
seti $positionpercent = $processedsectors * 100
seti $percentcomplete = $positionpercent / $totalsectors
seti $remainder = $positionpercent % $totalsectors
seti $remainder = $remainder * 100
seti $percentremainder = $remainder / $totalsectors
if $percentremainder < 10
echo $percentcomplete ".0" $percentremainder "% complete "
else
echo $percentcomplete "." $percentremainder "% complete "
endif
echo "position= " $currentposition " "
echo "speed= " $currentspeed " kB/s "
echo "errors=" $errorcount " "
endsubroutine