# Direct write of a cleared WD ROYL MOD 32 (relocation list), no pre-read.
# VSC sequence from fzabkar, HDD Guru t=29187 (SLOFIX script, MOD 32 section):
#   enable VSC 45 0b 00 44 57 a0 80
#   key sector "08 00 02 00 32 00" via SMART WRITE LOG BE (d6 01 be 4f c2 a0 b0)
#   0x3C sectors of module data via SMART WRITE LOG BF (d6 3c bf 4f c2 a0 b0)
# Guards: exact model + serial, input file exactly 0x3C*512 bytes, typed confirmation.
# Run from the hddscripts directory (needs good_subroutines):
#   sudo ../hddsupertool -t /dev/sdX -f wd_royl_write_mod32_direct
# Expects the cleared module at /tmp/wdfix/mod32_cleared.bin

include good_subroutines

sets $infile = "/tmp/wdfix/mod32_cleared.bin"
sets $want_model = "WDC WD5000AZRX-00A8LB0"
sets $want_serial = "WD-WCC1U1920791"

# get model and serial using identify device command
echo "identify"
buffersize 512
setreadpio
ata28cmd 0 0 0 0 0 0xa0 0xec
# check if command failed
gosub status_check
wordflipbuffer 0 512

# extract model and serial and trim leading and trailing spaces
sets $model = "null"
sets $serial = "null"
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 $compare = "WDC"
if $wdcheck != $compare
  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

if $model != $want_model
  echo "Model mismatch, refusing to write"
  exit 1
endif
if $serial != $want_serial
  echo "Serial mismatch, refusing to write"
  exit 1
endif

getfilesize $infile
if $error_level != 0x7800
  echo "Input file missing or not 0x7800 bytes, refusing to write"
  exit 1
endif

echo "About to WRITE module 0x32 (0x3C sectors) to the service area of " $model " " $serial
echo 'Type "WRITE32" to continue:'
userinput $choicestring
sets $safety = "WRITE32"
if $choicestring != $safety
  echo "Not confirmed, nothing written"
  exit 0
endif

echo "enable vsc"
buffersize 0
setreadpio
ata28cmd 0x45 0x0b 0x00 0x44 0x57 0xa0 0x80
gosub status_check

echo "send write-module key for 0x32"
buffersize 0x200
clearbuffer
setbuffer 0
  08 00 02 00 32 00
endbuffer
setwritepio
ata28cmd 0xd6 0x01 0xbe 0x4f 0xc2 0xa0 0xb0
gosub status_check

echo "write 0x3C sectors of module data"
buffersize 0x7800
readbuffer $infile 0 0 0x7800
setwritepio
ata28cmd 0xd6 0x3c 0xbf 0x4f 0xc2 0xa0 0xb0
gosub status_check

echo "disable vsc"
buffersize 0
setreadpio
ata28cmd 0x44 0x0b 0x00 0x44 0x57 0xa0 0x80
gosub status_check

echo "MOD 32 write sent. Power-cycle the drive, then read it back with wd_royl_dump_mod32."
end


subroutine status_check
  seti $command_failed = 0
  gosub check_command_status
  if $command_failed = 1
    echo "Command failed!"
    gosub show_sense_data
    gosub show_ata_return_status
    exit 1
  endif
endsubroutine
