mirror of
https://github.com/ISpillMyDrink/OpenSuperClone.git
synced 2026-05-03 21:40:33 +00:00
404 lines
10 KiB
Plaintext
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
|
|
|
|
|