recode-fw.scm (3073B)
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 15 ;; the file that contains the firmware 16 (define *driverfile* "R5U870FLx86.sys") 17 ;; where to put the result 18 (define *destfile* "r5u870_183b.fw") 19 ;; start address of firmware data in *DRIVERFILE* 20 (define *start* 46224) 21 ;; length of data 22 (define *length* 16981) 23 24 (define *expected-md5sum* #f) 25 26 ;;; no user-serviceable parts below 27 28 29 ;; make sure we get sane byte behaviour 30 (setlocale LC_ALL "C") 31 32 (use-modules (ice-9 format)) 33 34 (define (read-N-bytes count) 35 "Read N bytes from CURRENT-INPUT-PORT, failing hard if not enough are there." 36 (with-output-to-string 37 (lambda () 38 (let loop ((remaining count)) 39 (if (> remaining 0) 40 (begin (write-char (read-char)) 41 (loop (- remaining 1)))))))) 42 43 (define (write-N-bytes count data) 44 "Write N bytes from DATA to CURRENT-OUTPUT-PORT, failing hard if not enough are there." 45 (with-input-from-string data 46 (lambda () 47 (let loop ((remaining count)) 48 (if (> remaining 0) 49 (begin (write-char (read-char)) 50 (loop (- remaining 1)))))))) 51 52 (define (driversegment->fw string) 53 "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." 54 (with-output-to-string 55 (lambda () 56 (with-input-from-string string 57 (lambda () 58 (let loop () 59 (if (eof-object? (peek-char)) 60 (format (current-error-port) "done~%") 61 (begin 62 (let* ((lenbyte (read-char)) 63 (lenint (char->integer lenbyte)) 64 (addrbyte1 (read-char)) 65 (addrbyte2 (read-char)) 66 (ignoredbyte (read-char)) 67 (data (read-N-bytes lenint))) 68 (format (current-error-port) 69 "~d -> ~x; " lenint 70 (logior (char->integer addrbyte1) 71 (* 256 (char->integer addrbyte2)))) 72 (format #t "~c~c~c" lenbyte addrbyte1 addrbyte2) 73 (write-N-bytes lenint data) 74 (loop)))))))))) 75 76 (define (extract-slice file start length) 77 "Return bytes START through START+LENGTH from FILE as a string" 78 (with-input-from-file file 79 (lambda () 80 (seek (current-input-port) start SEEK_SET) 81 (read-N-bytes length)))) 82 83 ;; main: 84 (format (current-error-port) 85 "Decoding firmware from ~A into ~A:~%" *driverfile* *destfile*) 86 (with-output-to-file *destfile* 87 (lambda () 88 (let ((extracted-data (driversegment->fw 89 (extract-slice *driverfile* *start* *length*)))) 90 (format (current-error-port) 91 "Result has length ~d~%" (string-length extracted-data) ) 92 (write-N-bytes (string-length extracted-data) extracted-data))))