recode-fw.scm 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. #!/usr/bin/guile -s
  2. !#
  3. ;; script to extract the firmware from a windows driver file
  4. ;; (c) uuh 2007, herewith put into public domain
  5. ;;
  6. ;; inspection showed that the windows driver file
  7. ;; SYSFILE contains blobs of firmware data mixed with the URB request data
  8. ;;
  9. ;; <1-octet transfer length> for TransferBufferLength
  10. ;; <2-octet lsb dest value> for Value slot of request
  11. ;; <1-octet index> for Index slot of request
  12. ;; For the .fw files that we use we need the 4th octet thrown out,
  13. ;; and leave the length in place (since INDEX is always 0x00)
  14. ;; the file that contains the firmware
  15. (define *driverfile* "R5U870FLx86.sys")
  16. ;; where to put the result
  17. (define *destfile* "r5u870_183b.fw")
  18. ;; start address of firmware data in *DRIVERFILE*
  19. (define *start* 46224)
  20. ;; length of data
  21. (define *length* 16981)
  22. (define *expected-md5sum* #f)
  23. ;;; no user-serviceable parts below
  24. ;; make sure we get sane byte behaviour
  25. (setlocale LC_ALL "C")
  26. (use-modules (ice-9 format))
  27. (define (read-N-bytes count)
  28. "Read N bytes from CURRENT-INPUT-PORT, failing hard if not enough are there."
  29. (with-output-to-string
  30. (lambda ()
  31. (let loop ((remaining count))
  32. (if (> remaining 0)
  33. (begin (write-char (read-char))
  34. (loop (- remaining 1))))))))
  35. (define (write-N-bytes count data)
  36. "Write N bytes from DATA to CURRENT-OUTPUT-PORT, failing hard if not enough are there."
  37. (with-input-from-string data
  38. (lambda ()
  39. (let loop ((remaining count))
  40. (if (> remaining 0)
  41. (begin (write-char (read-char))
  42. (loop (- remaining 1))))))))
  43. (define (driversegment->fw string)
  44. "Read chunks of <len-byte> <low address byte> <high address byte> <index byte> <LEN bytes data chunk> from FILE and return a string where the <index-byte> has been dropped."
  45. (with-output-to-string
  46. (lambda ()
  47. (with-input-from-string string
  48. (lambda ()
  49. (let loop ()
  50. (if (eof-object? (peek-char))
  51. (format (current-error-port) "done~%")
  52. (begin
  53. (let* ((lenbyte (read-char))
  54. (lenint (char->integer lenbyte))
  55. (addrbyte1 (read-char))
  56. (addrbyte2 (read-char))
  57. (ignoredbyte (read-char))
  58. (data (read-N-bytes lenint)))
  59. (format (current-error-port)
  60. "~d -> ~x; " lenint
  61. (logior (char->integer addrbyte1)
  62. (* 256 (char->integer addrbyte2))))
  63. (format #t "~c~c~c" lenbyte addrbyte1 addrbyte2)
  64. (write-N-bytes lenint data)
  65. (loop))))))))))
  66. (define (extract-slice file start length)
  67. "Return bytes START through START+LENGTH from FILE as a string"
  68. (with-input-from-file file
  69. (lambda ()
  70. (seek (current-input-port) start SEEK_SET)
  71. (read-N-bytes length))))
  72. ;; main:
  73. (format (current-error-port)
  74. "Decoding firmware from ~A into ~A:~%" *driverfile* *destfile*)
  75. (with-output-to-file *destfile*
  76. (lambda ()
  77. (let ((extracted-data (driversegment->fw
  78. (extract-slice *driverfile* *start* *length*))))
  79. (format (current-error-port)
  80. "Result has length ~d~%" (string-length extracted-data) )
  81. (write-N-bytes (string-length extracted-data) extracted-data))))