mirror of
https://github.com/ISpillMyDrink/OpenSuperClone.git
synced 2026-05-03 13:30:49 +00:00
837 lines
23 KiB
Plaintext
837 lines
23 KiB
Plaintext
echo 'Western Digital ROYL patch module 0x02 using vendor specific commands.'
|
|
echo 'This is to resolve a common WD slow issue, where the drive reads slow.'
|
|
echo 'Definition of the "slow responding issue":'
|
|
echo ' - The drive is reading very slow, but all reads are GOOD.'
|
|
echo 'This may not help any if the reads are bad due to a weak or bad head.'
|
|
echo 'WARNING: THIS IS DANGEROUS AND COULD KILL THE DRIVE!!!'
|
|
echo 'USE AT YOUR OWN RISK!!!'
|
|
|
|
seti $printhelp = $printhelp
|
|
seti $help = $help
|
|
if $help = 1
|
|
echo 'WD patch module 02 to perform the slow fix, alternate method.'
|
|
echo 'WARNING! Do NOT run the fast ram patch before running this patch!'
|
|
echo 'If you have ran the fast ram patch, power cycle the drive to clear it.'
|
|
echo 'This patches the module in RAM and uses a trick to write it.'
|
|
echo 'This will set and remove a password on the drive.'
|
|
echo 'The password will be "password" in case drive ends up locked.'
|
|
echo 'You must power cycle the drive for the patch to take effect.'
|
|
|
|
if $printhelp = 1
|
|
exit 0
|
|
endif
|
|
echo 'Hit ENTER to continue...'
|
|
userinput $choicestring
|
|
previousscript
|
|
endif
|
|
echo ""
|
|
|
|
include good_subroutines.osc
|
|
|
|
# set a blank string variable to compare with user input
|
|
# make sure not to set this anyplace else
|
|
sets $null = ""
|
|
|
|
# set this to itself for use with the menu system
|
|
# make sure not to set this anyplace else
|
|
# if it was not previously set it will = 0
|
|
seti $using_menu = $using_menu
|
|
|
|
|
|
echo "You should have already tried the regular mod02 patch."
|
|
echo "Did you already try the regular patch and it failed to apply?"
|
|
echo 'Type "YES" to continue:'
|
|
userinput $choicestring
|
|
sets $safety = "YES"
|
|
if $choicestring != $safety
|
|
echo "You chose not to continue"
|
|
previousscript
|
|
endif
|
|
|
|
echo "WARNING! You are about to write to the service area of the drive."
|
|
echo "There is NO UNDO with this script! This operation could be permanent!"
|
|
echo "You are on your own if something goes wrong."
|
|
echo 'Type "DANGEROUS" to continue:'
|
|
userinput $choicestring
|
|
sets $safety = "DANGEROUS"
|
|
if $choicestring != $safety
|
|
echo "You chose not to continue"
|
|
previousscript
|
|
endif
|
|
|
|
echo "You must NOT have ran the fast ram patch before running this patch."
|
|
echo "Are you sure you did not run the fast ram patch since the drive was powered up?"
|
|
echo 'Type "YES" to continue:'
|
|
userinput $choicestring
|
|
sets $safety = "YES"
|
|
if $choicestring != $safety
|
|
echo "You chose not to continue"
|
|
previousscript
|
|
endif
|
|
|
|
|
|
# set these for later, and to make it easy to change if needed
|
|
seti $ram_read_block_size = 65536
|
|
|
|
seti $ram_start = 0x8000000
|
|
seti $ram_size = 0x40000
|
|
seti $max_ram_size = 0x2000000
|
|
|
|
if $ram_size < $ram_read_block_size
|
|
seti $ram_read_block_size = $ram_size
|
|
endif
|
|
seti $divide_check = $ram_read_block_size % 512
|
|
if $divide_check != 0
|
|
echo "ram_read_block_size is not dividable by 512"
|
|
previousscript
|
|
endif
|
|
|
|
seti $patch_successful = 0
|
|
seti $not_erased_check = 0
|
|
|
|
gosub idle_drive
|
|
|
|
gosub identify_device
|
|
|
|
gosub find_ram_size
|
|
|
|
gosub dump_ram
|
|
|
|
if $patch_successful = 1
|
|
gosub set_password
|
|
gosub remove_password
|
|
echo "if password commands completed without errors,"
|
|
echo "then the drive should now be patched."
|
|
endif
|
|
|
|
|
|
previousscript
|
|
end
|
|
|
|
|
|
subroutine identify_device
|
|
# set the base filenames
|
|
sets $basefilename = "mod02original.bin"
|
|
sets $basepatchname = "mod02patched.bin"
|
|
echo "Performing identify device command"
|
|
buffersize 512
|
|
setreadpio
|
|
ata28cmd 0 0 0 0 0 0xa0 0xec
|
|
# check if command failed
|
|
gosub status_check
|
|
# extract model and serial and trim leading and trailing spaces
|
|
sets $model = "null"
|
|
sets $serial = "null"
|
|
wordflipbuffer 0 512
|
|
seti $count = 0
|
|
seti $start_offset = 54
|
|
while $count < 40
|
|
seti $byte = buffer $start_offset
|
|
if $byte > 0x20
|
|
break
|
|
endif
|
|
seti $start_offset = $start_offset + 1
|
|
seti $count = $count + 1
|
|
done
|
|
seti $count = 0
|
|
seti $end_offset = 93
|
|
while $count < 40
|
|
seti $byte = buffer $end_offset
|
|
if $byte > 0x20
|
|
break
|
|
endif
|
|
seti $end_offset = $end_offset - 1
|
|
seti $count = $count + 1
|
|
done
|
|
seti $end_offset = $end_offset + 1
|
|
seti $size = $end_offset - $start_offset
|
|
if $size > 0
|
|
sets $model = buffer $start_offset $size
|
|
endif
|
|
# find out if it is a WD drive
|
|
sets $wdcheck = buffer $start_offset 3
|
|
sets $wdcompare = "WDC"
|
|
if $wdcheck != $wdcompare
|
|
echo "Model: " $model
|
|
echo "Drive is not WD, exiting"
|
|
previousscript
|
|
endif
|
|
|
|
seti $count = 0
|
|
seti $start_offset = 20
|
|
while $count < 20
|
|
seti $byte = buffer $start_offset
|
|
if $byte > 0x20
|
|
break
|
|
endif
|
|
seti $start_offset = $start_offset + 1
|
|
seti $count = $count + 1
|
|
done
|
|
seti $count = 0
|
|
seti $end_offset = 39
|
|
while $count < 20
|
|
seti $byte = buffer $end_offset
|
|
if $byte > 0x20
|
|
break
|
|
endif
|
|
seti $end_offset = $end_offset - 1
|
|
seti $count = $count + 1
|
|
done
|
|
seti $end_offset = $end_offset + 1
|
|
seti $size = $end_offset - $start_offset
|
|
if $size > 0
|
|
sets $serial = buffer $start_offset $size
|
|
endif
|
|
|
|
echo "Model: " $model
|
|
echo "Serial: " $serial
|
|
|
|
# create a directory named with model and serial
|
|
sets $directory = $model "__" $serial
|
|
sets $wdcommand = 'mkdir -p "' $directory '"'
|
|
callcommand $wdcommand
|
|
|
|
# set filename for backup dump file
|
|
gettime
|
|
sets $backup_filename = $directory "/" $date "__" $basefilename
|
|
sets $backup_patchname = $directory "/" $date "__" $basepatchname
|
|
|
|
sets $firmware = buffer 46 8
|
|
echo "Firmware revision= " $firmware
|
|
wordflipbuffer 0 512
|
|
|
|
# show if drive supports extended commands
|
|
seti $tempnum = buffer 167
|
|
seti $extended = $tempnum & 4
|
|
seti $extended = $extended > 2
|
|
#echo "supports 48 bit commands = " $extended
|
|
|
|
# total addressable sectors
|
|
if $extended = 1
|
|
seti $addressable = buffer 200 qw
|
|
echo "total addressable sectors= " $addressable
|
|
else
|
|
seti $addressable = buffer 120 dw
|
|
echo "total addressable sectors= " $addressable
|
|
endif
|
|
|
|
# words per logical sector
|
|
seti $wordsps = buffer 234 w
|
|
#echo "words per logical sector= " $wordsps
|
|
|
|
# size
|
|
if $wordsps = 0
|
|
seti $sectorsize = 512
|
|
else
|
|
seti $sectorsize = $wordsps * 2
|
|
endif
|
|
seti $sizeb = $addressable * $sectorsize
|
|
seti $sizemb = $sizeb / 1048576
|
|
echo "Size in bytes= " $sizeb
|
|
#echo "Size in MiB= " $sizemb
|
|
|
|
# show drive security status
|
|
seti $tempnum = buffer 257
|
|
seti $security_level = $tempnum & 1
|
|
seti $tempnum = buffer 256
|
|
seti $enhanced_security_erase_supported = $tempnum & 32
|
|
seti $enhanced_security_erase_supported = $enhanced_security_erase_supported > 5
|
|
seti $security_count_expired = $tempnum & 16
|
|
seti $security_count_expired = $security_count_expired > 4
|
|
seti $security_frozen = $tempnum & 8
|
|
seti $security_frozen = $security_frozen > 3
|
|
seti $security_locked = $tempnum & 4
|
|
seti $security_locked = $security_locked > 2
|
|
seti $security_enabled = $tempnum & 2
|
|
seti $security_enabled = $security_enabled > 1
|
|
seti $security_supported = $tempnum & 1
|
|
#echo "enhanced_security_erase_supported= " $enhanced_security_erase_supported
|
|
#echo "security_count_expired= " $security_count_expired
|
|
#echo "security_frozen= " $security_frozen
|
|
echo "security_locked= " $security_locked
|
|
echo "security_enabled= " $security_enabled
|
|
#echo "security_supported= " $security_supported
|
|
|
|
if $security_enabled != 0
|
|
echo "The drive currently has a password set."
|
|
echo "This patch will not work with an existing password."
|
|
previousscript
|
|
endif
|
|
endsubroutine
|
|
|
|
|
|
subroutine find_ram_size
|
|
gosub enable_vsc
|
|
|
|
seti $find_ram_read_size = 0x200
|
|
scratchpadsize $find_ram_read_size
|
|
seti $position = $ram_start
|
|
seti $remainder = $find_ram_read_size
|
|
if $remainder != 0
|
|
seti $write_offset = 0
|
|
seti $read_size = $remainder
|
|
hex
|
|
echo "position=0x" $position " rsize=0x" $read_size
|
|
decimal
|
|
# vsc to prepare for ram read
|
|
#echo "prepare to read ram"
|
|
buffersize 0x200
|
|
clearbuffer
|
|
seti $offsetl = $position & 0xff
|
|
seti $offsetm1 = $position > 8
|
|
seti $offsetm1 = $offsetm1 & 0xff
|
|
seti $offsetm2 = $position > 16
|
|
seti $offsetm2 = $offsetm2 & 0xff
|
|
seti $offseth = $position > 24
|
|
seti $offseth = $offseth & 0xff
|
|
seti $sizel = $read_size & 0xff
|
|
seti $sizem1 = $read_size > 8
|
|
seti $sizem1 = $sizem1 & 0xff
|
|
seti $sizem2 = $read_size > 16
|
|
seti $sizem2 = $sizem2 & 0xff
|
|
seti $sizeh = $read_size > 24
|
|
seti $sizeh = $sizeh & 0xff
|
|
setbuffer 0
|
|
13 00 01 00 $offsetl $offsetm1 $offsetm2 $offseth $sizel $sizem1 $sizem2 $sizeh
|
|
endbuffer
|
|
setwritepio
|
|
ata28cmd 0xd6 0x01 0xbe 0x4f 0xc2 0xa0 0xb0
|
|
# check if command failed
|
|
gosub status_check
|
|
# vsc to get the ram
|
|
seti $sectors = $read_size / 512
|
|
buffersize $read_size
|
|
clearbuffer
|
|
setreadpio
|
|
#echo "reading ram"
|
|
ata28cmd 0xd5 $sectors 0xbf 0x4f 0xc2 0xa0 0xb0
|
|
# check if command failed
|
|
gosub status_check
|
|
# copy the buffer to the scratchpad
|
|
copybuffertoscratchpad 0 $write_offset $read_size
|
|
endif
|
|
|
|
#printscratchpad 0 512
|
|
|
|
seti $read_size = $find_ram_read_size
|
|
while 1 = 1
|
|
seti $position = $ram_start + $ram_size
|
|
hex
|
|
echo "position=0x" $position " size=0x" $read_size
|
|
decimal
|
|
# vsc to prepare for ram read
|
|
#echo "prepare to read ram"
|
|
buffersize 0x200
|
|
clearbuffer
|
|
seti $offsetl = $position & 0xff
|
|
seti $offsetm1 = $position > 8
|
|
seti $offsetm1 = $offsetm1 & 0xff
|
|
seti $offsetm2 = $position > 16
|
|
seti $offsetm2 = $offsetm2 & 0xff
|
|
seti $offseth = $position > 24
|
|
seti $offseth = $offseth & 0xff
|
|
seti $sizel = $read_size & 0xff
|
|
seti $sizem1 = $read_size > 8
|
|
seti $sizem1 = $sizem1 & 0xff
|
|
seti $sizem2 = $read_size > 16
|
|
seti $sizem2 = $sizem2 & 0xff
|
|
seti $sizeh = $read_size > 24
|
|
seti $sizeh = $sizeh & 0xff
|
|
setbuffer 0
|
|
13 00 01 00 $offsetl $offsetm1 $offsetm2 $offseth $sizel $sizem1 $sizem2 $sizeh
|
|
endbuffer
|
|
hex
|
|
#echo "keysector= 13 00 01 00 " $offsetl " " $offsetm1 " " $offsetm2 " " $offseth " " $sizel " " $sizem1 " " $sizem2 " " $sizeh
|
|
setwritepio
|
|
ata28cmd 0xd6 0x01 0xbe 0x4f 0xc2 0xa0 0xb0
|
|
# check if command failed
|
|
gosub status_check
|
|
|
|
# vsc to get the ram
|
|
seti $sectors = $read_size / 512
|
|
buffersize $read_size
|
|
clearbuffer
|
|
setreadpio
|
|
#echo "reading ram"
|
|
ata28cmd 0xd5 $sectors 0xbf 0x4f 0xc2 0xa0 0xb0
|
|
hex
|
|
#echo "command= d5 " $sectors " bf 4f c2 a0 b0"
|
|
decimal
|
|
# check if command failed
|
|
gosub status_check
|
|
|
|
seti $comparedata = 0
|
|
seti $found_match = 1
|
|
while $comparedata < 512
|
|
seti $cmp = buffer $comparedata qw
|
|
seti $check = scratchpad $comparedata qw
|
|
if $cmp != $check
|
|
seti $found_match = 0
|
|
break
|
|
endif
|
|
seti $comparedata = $comparedata + 8
|
|
done
|
|
if $found_match = 1
|
|
hex
|
|
echo "ram size is 0x" $ram_size
|
|
decimal
|
|
break
|
|
endif
|
|
|
|
seti $ram_size = $ram_size * 2
|
|
if $ram_size > $max_ram_size
|
|
hex
|
|
echo "ram size not found, using default maximum size of 0x" $max_ram_size
|
|
decimal
|
|
seti $ram_size = $max_ram_size
|
|
break
|
|
endif
|
|
done
|
|
|
|
gosub disable_vsc
|
|
endsubroutine
|
|
|
|
|
|
subroutine dump_ram
|
|
gosub enable_vsc
|
|
|
|
scratchpadsize $ram_size
|
|
seti $position = $ram_start
|
|
seti $read_size = $ram_read_block_size
|
|
seti $block_count = $ram_size / $ram_read_block_size
|
|
seti $search_position = 0
|
|
seti $count = 0
|
|
while $count < $block_count
|
|
hex
|
|
echo "position=0x" $position " size=0x" $read_size
|
|
decimal
|
|
# vsc to prepare for ram read
|
|
#echo "prepare to read ram"
|
|
buffersize 0x200
|
|
clearbuffer
|
|
seti $offsetl = $position & 0xff
|
|
seti $offsetm1 = $position > 8
|
|
seti $offsetm1 = $offsetm1 & 0xff
|
|
seti $offsetm2 = $position > 16
|
|
seti $offsetm2 = $offsetm2 & 0xff
|
|
seti $offseth = $position > 24
|
|
seti $offseth = $offseth & 0xff
|
|
seti $sizel = $read_size & 0xff
|
|
seti $sizem1 = $read_size > 8
|
|
seti $sizem1 = $sizem1 & 0xff
|
|
seti $sizem2 = $read_size > 16
|
|
seti $sizem2 = $sizem2 & 0xff
|
|
seti $sizeh = $read_size > 24
|
|
seti $sizeh = $sizeh & 0xff
|
|
setbuffer 0
|
|
13 00 01 00 $offsetl $offsetm1 $offsetm2 $offseth $sizel $sizem1 $sizem2 $sizeh
|
|
endbuffer
|
|
setwritepio
|
|
ata28cmd 0xd6 0x01 0xbe 0x4f 0xc2 0xa0 0xb0
|
|
# check if command failed
|
|
gosub status_check
|
|
# send again
|
|
ata28cmd 0xd6 0x01 0xbe 0x4f 0xc2 0xa0 0xb0
|
|
# check if command failed
|
|
gosub status_check
|
|
|
|
# vsc to get the ram
|
|
seti $sectors = $read_size / 512
|
|
buffersize $read_size
|
|
clearbuffer
|
|
setreadpio
|
|
#echo "reading ram"
|
|
ata28cmd 0xd5 $sectors 0xbf 0x4f 0xc2 0xa0 0xb0
|
|
# check if command failed
|
|
gosub status_check
|
|
seti $write_offset = $count * $read_size
|
|
# copy the buffer to the scratchpad
|
|
copybuffertoscratchpad 0 $write_offset $read_size
|
|
|
|
gosub process_ram
|
|
|
|
seti $count = $count + 1
|
|
seti $position = $position + $ram_read_block_size
|
|
done
|
|
|
|
gosub disable_vsc
|
|
echo "ram processing finished"
|
|
if $patch_successful = 1
|
|
echo "ram patch successful"
|
|
else
|
|
echo "ram patch failed"
|
|
endif
|
|
endsubroutine
|
|
|
|
|
|
subroutine process_ram
|
|
#echo "processing ram"
|
|
sets $header_check = "ROYL"
|
|
seti $search_end = $search_position + $ram_read_block_size
|
|
seti $search_end = $search_end - 4096
|
|
while $search_position < $search_end
|
|
sets $header = scratchpad $search_position 4
|
|
if $header = $header_check
|
|
# process the module
|
|
seti $working_offset = $search_position
|
|
#echo "Header:"
|
|
#printscratchpad $working_offset 4
|
|
seti $working_offset = $search_position + 8
|
|
seti $mod_id = scratchpad $working_offset w
|
|
hex
|
|
#echo "Module ID = 0x" $mod_id
|
|
|
|
if $mod_id = 2
|
|
# find how many sectors the module contains
|
|
seti $working_offset = $search_position + 0xa
|
|
seti $mod_length_sectors = scratchpad $working_offset
|
|
seti $working_offset = $search_position + 0xb
|
|
seti $tempnum = scratchpad $working_offset
|
|
seti $tempnum = $tempnum > 8
|
|
seti $mod_length_sectors = $mod_length_sectors + $tempnum
|
|
|
|
#echo "Size in sectors = 0x" $mod_length_sectors
|
|
seti $working_offset = $search_position + 0xc
|
|
seti $checksum = scratchpad $working_offset dw
|
|
#echo "32 bit checksum = 0x" $checksum
|
|
seti $working_offset = $search_position + 0x10
|
|
#echo "Mod version:"
|
|
#printscratchpad $working_offset 8
|
|
decimal
|
|
|
|
seti $module_size = $mod_length_sectors * 512
|
|
seti $calculated_checksum = 0
|
|
seti $check_count = 0
|
|
while $check_count < $module_size
|
|
seti $working_offset = $search_position + $check_count
|
|
if $working_offset > $search_end
|
|
echo "end of module is past end of rom"
|
|
break
|
|
endif
|
|
seti $dword = scratchpad $working_offset dw
|
|
seti $calculated_checksum = $calculated_checksum + $dword
|
|
seti $check_count = $check_count + 4
|
|
# skip the actual checksum bytes
|
|
if $check_count = 0xc
|
|
seti $check_count = $check_count + 4
|
|
endif
|
|
done
|
|
seti $calculated_checksum = $calculated_checksum & 0xffffffff
|
|
seti $calculated_checksum = 0xffffffff - $calculated_checksum
|
|
seti $calculated_checksum = $calculated_checksum + 1
|
|
|
|
hex
|
|
if $checksum = $calculated_checksum
|
|
sets $checkstring = " calulated=0x" $calculated_checksum " (good)"
|
|
echo "pos=0x" $search_position " ModID=0x" $mod_id " size=0x" $mod_length_sectors $checkstring
|
|
seti $module_position = $search_position
|
|
seti $module_length = $mod_length_sectors * 512
|
|
gosub patch_module
|
|
else
|
|
sets $checkstring = " calulated=0x" $calculated_checksum " (bad)"
|
|
endif
|
|
decimal
|
|
endif
|
|
endif
|
|
seti $search_position = $search_position + 512
|
|
done
|
|
endsubroutine
|
|
|
|
|
|
subroutine patch_module
|
|
seti $wposition = $module_position
|
|
seti $wposition = $wposition + 0x8000000
|
|
seti $write_size = $module_length
|
|
hex
|
|
echo "wposition=0x" $wposition " wsize=0x" $write_size
|
|
decimal
|
|
# vsc to prepare for ram write
|
|
echo "prepare to write ram"
|
|
buffersize 0x200
|
|
clearbuffer
|
|
seti $offsetl = $wposition & 0xff
|
|
seti $offsetm1 = $wposition > 8
|
|
seti $offsetm1 = $offsetm1 & 0xff
|
|
seti $offsetm2 = $wposition > 16
|
|
seti $offsetm2 = $offsetm2 & 0xff
|
|
seti $offseth = $wposition > 24
|
|
seti $offseth = $offseth & 0xff
|
|
seti $sizel = $write_size & 0xff
|
|
seti $sizem1 = $write_size > 8
|
|
seti $sizem1 = $sizem1 & 0xff
|
|
seti $sizem2 = $write_size > 16
|
|
seti $sizem2 = $sizem2 & 0xff
|
|
seti $sizeh = $write_size > 24
|
|
seti $sizeh = $sizeh & 0xff
|
|
setbuffer 0
|
|
13 00 02 00 $offsetl $offsetm1 $offsetm2 $offseth $sizel $sizem1 $sizem2 $sizeh
|
|
endbuffer
|
|
hex
|
|
#echo $offsetl " " $offsetm1 " " $offsetm2 " " $offseth " " $sizel " " $sizem1 " " $sizem2 " " $sizeh
|
|
decimal
|
|
setwritepio
|
|
ata28cmd 0xd6 0x01 0xbe 0x4f 0xc2 0xa0 0xb0
|
|
# check if command failed
|
|
gosub status_check
|
|
# vsc to get the ram
|
|
seti $sectors = $read_size / 512
|
|
buffersize $module_length
|
|
clearbuffer
|
|
copyscratchpadtobuffer $module_position 0 $module_length
|
|
#printbuffer 0 $module_length
|
|
writebuffer $backup_filename 0 0 $module_length
|
|
|
|
gosub process_mod02
|
|
|
|
if $not_erased_check = 1
|
|
# calculate new checksum and insert it
|
|
seti $calculated_checksum = 0
|
|
gosub calculate_checksum_buffer
|
|
hex
|
|
echo "Calculated Checksum = 0x" $calculated_checksum
|
|
decimal
|
|
seti $b1 = $calculated_checksum & 0xff
|
|
seti $calculated_checksum = $calculated_checksum > 8
|
|
seti $b2 = $calculated_checksum & 0xff
|
|
seti $calculated_checksum = $calculated_checksum > 8
|
|
seti $b3 = $calculated_checksum & 0xff
|
|
seti $calculated_checksum = $calculated_checksum > 8
|
|
seti $b4 = $calculated_checksum & 0xff
|
|
setbuffer 0x0c
|
|
$b1 $b2 $b3 $b4
|
|
endbuffer
|
|
|
|
writebuffer $backup_patchname 0 0 $module_length
|
|
|
|
setwritepio
|
|
echo "writing ram"
|
|
ata28cmd 0xd6 $mod_length_sectors 0xbf 0x4f 0xc2 0xa0 0xb0
|
|
# check if command failed
|
|
gosub status_check
|
|
|
|
else
|
|
echo "Warning! Mod02 record 27 appears to have been erased in ram."
|
|
echo "The patch will not be written."
|
|
seti $patch_successful = 0
|
|
endif
|
|
|
|
endsubroutine
|
|
|
|
|
|
subroutine process_mod02
|
|
# process the module
|
|
seti $total_records = buffer 0x30 w
|
|
echo "Total records = " $total_records
|
|
|
|
# process the data records
|
|
seti $rcount = 0
|
|
while $rcount < $total_records
|
|
seti $offset = $rcount * 4
|
|
seti $rcount = $rcount + 1
|
|
seti $offset = $offset + 0x32
|
|
seti $record_offset = buffer $offset w
|
|
seti $offset = $offset + 2
|
|
seti $record_size = buffer $offset w
|
|
|
|
# process record 27 (slow fix)
|
|
if $rcount = 27
|
|
echo "Data record #" $rcount ":"
|
|
printbuffer $record_offset $record_size
|
|
|
|
seti $erased = 0
|
|
seti $not_erased_check = 0
|
|
while $erased < $record_size
|
|
seti $erased_offset = $record_offset + $erased
|
|
seti $check_byte = buffer $erased_offset b
|
|
if $check_byte != 0
|
|
seti $not_erased_check = 1
|
|
break
|
|
endif
|
|
seti $erased = $erased + 1
|
|
done
|
|
|
|
seti $erase_offset = $record_offset + 2
|
|
setbuffer $erase_offset
|
|
00
|
|
endbuffer
|
|
echo "Data record #" $rcount " after patch:"
|
|
printbuffer $record_offset $record_size
|
|
seti $patch_successful = 1
|
|
endif
|
|
|
|
done
|
|
endsubroutine
|
|
|
|
|
|
subroutine calculate_checksum_buffer
|
|
seti $calculated_checksum = 0
|
|
seti $ccount = 0
|
|
while $ccount < $module_length
|
|
seti $dword = buffer $ccount dw
|
|
seti $calculated_checksum = $calculated_checksum + $dword
|
|
seti $ccount = $ccount + 4
|
|
# skip the actual checksum bytes
|
|
if $ccount = 0xc
|
|
seti $ccount = $ccount + 4
|
|
endif
|
|
done
|
|
seti $calculated_checksum = $calculated_checksum & 0xffffffff
|
|
seti $calculated_checksum = 0xffffffff - $calculated_checksum
|
|
seti $calculated_checksum = $calculated_checksum + 1
|
|
endsubroutine
|
|
|
|
|
|
subroutine set_password
|
|
echo "setting password"
|
|
# set the buffer size
|
|
buffersize 512
|
|
# clear the buffer to 0's
|
|
clearbuffer
|
|
|
|
seti $type = 0
|
|
seti $level = 0
|
|
sets $password = "password"
|
|
|
|
# put the type and level in the buffer
|
|
seti $byte0 = $type & 0x01
|
|
seti $byte1 = $level & 0x01
|
|
setbuffer 0
|
|
$byte0 $byte1
|
|
endbuffer
|
|
|
|
# put the password (up to 32 characters) in the buffer
|
|
# if set this will overwrite part of all of the hex password
|
|
stringtobuffer 2 32 $password
|
|
|
|
# set the LBAs and count to 0
|
|
seti $count = 0
|
|
seti $LBAlow = 0
|
|
seti $LBAmid = 0
|
|
seti $LBAhigh = 0
|
|
|
|
# set some things for the ata command
|
|
setwritepio
|
|
# set features to 0
|
|
seti $features = 0
|
|
# set device bits 7(compatibility) 5(compatibility)
|
|
seti $device = 0xa0
|
|
# set the command for security set password pio data-out
|
|
seti $atacommand = 0xf1
|
|
|
|
# perform the command
|
|
ata28cmd $features $count $LBAlow $LBAmid $LBAhigh $device $atacommand
|
|
|
|
# check if command failed
|
|
gosub status_check
|
|
|
|
echo "password set"
|
|
endsubroutine
|
|
|
|
|
|
subroutine remove_password
|
|
echo "removing password"
|
|
# set the buffer size
|
|
buffersize 512
|
|
# clear the buffer to 0's
|
|
clearbuffer
|
|
|
|
seti $type = 0
|
|
sets $password = "password"
|
|
|
|
# put the type in the buffer
|
|
seti $byte0 = $type & 0x01
|
|
setbuffer 0
|
|
$byte0
|
|
endbuffer
|
|
|
|
# put the password (up to 32 characters) in the buffer
|
|
# if set this will overwrite part of all of the hex password
|
|
stringtobuffer 2 32 $password
|
|
|
|
# set the LBAs and count to 0
|
|
seti $count = 0
|
|
seti $LBAlow = 0
|
|
seti $LBAmid = 0
|
|
seti $LBAhigh = 0
|
|
|
|
# set some things for the ata command
|
|
setwritepio
|
|
# set features to 0
|
|
seti $features = 0
|
|
# set device bits 7(compatibility) 5(compatibility)
|
|
seti $device = 0xa0
|
|
# set the command for security disable password pio data-out
|
|
seti $atacommand = 0xf6
|
|
|
|
# perform the command
|
|
ata28cmd $features $count $LBAlow $LBAmid $LBAhigh $device $atacommand
|
|
|
|
# check if command failed
|
|
gosub status_check
|
|
|
|
echo "password removed"
|
|
endsubroutine
|
|
|
|
|
|
subroutine idle_drive
|
|
echo "attempting to idle drive"
|
|
seti $idle_tries = 0
|
|
while $idle_tries < 100
|
|
seti $idle_tries = $idle_tries + 1
|
|
echo "idle attempt " $idle_tries
|
|
gettime
|
|
seti $startreadtime = $time
|
|
gosub idle
|
|
gosub idle
|
|
gettime
|
|
seti $endreadtime = $time
|
|
seti $elapsedtime = $endreadtime - $startreadtime
|
|
if $elapsedtime < 100000
|
|
break
|
|
endif
|
|
done
|
|
endsubroutine
|
|
|
|
|
|
subroutine idle
|
|
buffersize 0
|
|
setreadpio
|
|
# set the count to 0
|
|
seti $count = 0
|
|
# set the LBA for the unload command
|
|
seti $LBAlow = 0x4c
|
|
seti $LBAmid = 0x4e
|
|
seti $LBAhigh = 0x55
|
|
# set features to unload
|
|
seti $features = 0x44
|
|
# set device bits 7(compatibility) 5(compatibility)
|
|
seti $device = 0xa0
|
|
# set the command for idle immediate
|
|
seti $atacommand = 0xe1
|
|
# perform the command
|
|
ata28cmd $features $count $LBAlow $LBAmid $LBAhigh $device $atacommand
|
|
gosub status_check
|
|
endsubroutine
|
|
|
|
|
|
subroutine enable_vsc
|
|
# enable vendor specific commands
|
|
echo "enable vsc"
|
|
buffersize 0
|
|
setreadpio
|
|
ata28cmd 0x45 0x0b 0x00 0x44 0x57 0xa0 0x80
|
|
# check if command failed
|
|
gosub status_check
|
|
endsubroutine
|
|
|
|
|
|
subroutine disable_vsc
|
|
# disable vendor specific commands
|
|
echo "disable vsc"
|
|
buffersize 0
|
|
setreadpio
|
|
ata28cmd 0x44 0x0b 0x00 0x44 0x57 0xa0 0x80
|
|
# check if command failed
|
|
gosub status_check
|
|
endsubroutine
|