Last active
August 20, 2025 14:27
-
-
Save PL125/9903a12942eef52db8425dfbc6acfd6b to your computer and use it in GitHub Desktop.
Vag EDC16 Eeprom Parser
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| function printUsage() { | |
| echo "Usage: $0 <OPTIONS>" | |
| echo " OPTIONS:" | |
| echo " -f <= EEprom file location" | |
| echo " -? -h --? --help <= Help info" | |
| echo "E.g., bash VagEdc16Decoder.sh -f EEpromfile.bin" | |
| echo "" | |
| } | |
| function processArgs() { | |
| while [[ $# != 0 ]]; do | |
| case $1 in | |
| -f ) | |
| filePath=$2 | |
| shift 2 | |
| ;; | |
| -? | -h | --? | --help ) | |
| printUsage | |
| exit 0 | |
| ;; | |
| * ) # Unknown option | |
| echo "Unknown argument or parameter: $1" | |
| printUsage | |
| exit -1 | |
| ;; | |
| esac | |
| done | |
| } | |
| function writeByte() { | |
| local byte=$(printf "\x%02X" $3) | |
| printf "$byte" | dd of="$1" seek=$(($2)) bs=1 count=1 conv=notrunc &> /dev/null | |
| } | |
| function byteRead() { | |
| local byte=$(dd if="$1" skip=$(($2)) bs=1 count=1 status=none | od -N1 -An -v -t u1) | |
| printf "%s" $byte | |
| } | |
| function byteToChar() { | |
| local ascii="\x$(printf '%x' $1)" | |
| printf "%b" "$ascii" | |
| } | |
| function printComponentSecurity() { | |
| : ' | |
| Component Security: | |
| 0x00E0 ... 0x00E6 | |
| 0x0100 ... 0x0106 | |
| 0x0120 ... 0x0126 | |
| ' | |
| local CS=0 | |
| # Read Component Security | |
| for ((i = 0x00E0; i <= 0x00E6; i++)); do | |
| local aux=$(byteRead "$filePath" $i) | |
| CS=$(( (CS << 8) | aux )) | |
| done | |
| # Print Component Security | |
| printf "%014X" $CS | |
| } | |
| function printLoginPin() { | |
| : ' | |
| Login Pin: | |
| 0x00E7 ... 0x00E8 | |
| 0x0107 ... 0x0108 | |
| 0x0127 ... 0x0128 | |
| ' | |
| local PIN=0 | |
| # Read Login Pin | |
| for ((i = 0x00E7; i <= 0x00E8; i++)); do | |
| local aux=$(byteRead "$filePath" $i) | |
| PIN=$(( (PIN << 8) | aux )) | |
| done | |
| # Print Login Pin | |
| printf "%05d" $PIN | |
| } | |
| function printImmoNo() { | |
| : ' | |
| Immo: | |
| 0x00EC ... 0x00F9 | |
| 0x010C ... 0x0119 | |
| 0x012C ... 0x0139 | |
| ' | |
| local IMMO="" | |
| # Read Immo | |
| for ((i = 0x00EC; i <= 0x00F9; i++)); do | |
| local aux=$(byteRead "$filePath" $i) | |
| IMMO+=$(byteToChar $aux) | |
| done | |
| # Print Immo | |
| printf "%s" $IMMO | |
| } | |
| function printMAC() { | |
| : ' | |
| Mac: | |
| 0x00FC | |
| 0x00FB | |
| 0x07E1 | |
| 0x07E0 | |
| ' | |
| local MAC=0 | |
| local offsets=(0x00FC 0x00FB 0x07E1 0x07E0) | |
| # Read Mac | |
| for i in "${offsets[@]}"; do | |
| local aux=$(byteRead "$filePath" $i) | |
| MAC=$(( (MAC << 8) | aux )) | |
| done | |
| # Print Mac | |
| printf "%08X" $MAC | |
| } | |
| function printVin() { | |
| : ' | |
| Vin: | |
| 0x0145 ... 0x0155 | |
| 0x0165 ... 0x0175 | |
| ' | |
| local VIN="" | |
| # Read Vin | |
| for ((i = 0x0145; i <= 0x0155; i++)); do | |
| local aux=$(byteRead "$filePath" $i) | |
| VIN+=$(byteToChar $aux) | |
| done | |
| # Print Vin if valid | |
| if [[ "$VIN" == [WTV]* ]]; then # Volkswagen | Skoda | Audi | Seat | |
| printf "%s" $VIN | |
| else | |
| printf "Vin is invalid, read EEprom and try again" | |
| fi | |
| } | |
| function printImmoState() { | |
| : ' | |
| Immo State: | |
| 0x0156 | |
| 0x0176 | |
| Immo On = 0x73 | |
| Immo Off = 0x60 | |
| ' | |
| # Read Immo State | |
| local IMMO=$(printf "0x%02X" "$(byteRead "$filePath" 0x0156)") | |
| # Print Immo State | |
| case $IMMO in | |
| 0x60 ) | |
| printf "Off" | |
| ;; | |
| 0x73 ) | |
| printf "On" | |
| ;; | |
| * ) | |
| printf "Unrecognized" | |
| ;; | |
| esac | |
| } | |
| function printChecksumState_VinImmo() { | |
| : ' | |
| Checksum for Vin and Immo data: | |
| 0x015E ... 0x015F | |
| 0x017E ... 0x017F | |
| http://diagprof.com/ecu_tips_and_tricks/manufacturer-vag/ecudomain-pcm_powertrain_control_module/supplier-bosch/ecutt-edc16u34 | |
| ' | |
| local CHECKSUM=0 | |
| local READ_CHECKSUM=0 | |
| # Read Checksum | |
| for ((i = 0x015E; i <= 0x015F; i++)); do | |
| local aux=$(byteRead "$filePath" $i) | |
| READ_CHECKSUM=$(( (READ_CHECKSUM << 8) | aux )) | |
| done | |
| # Compute Checksum | |
| for ((i = 0x0140; i <= 0x015D; i++)); do | |
| local aux=$(byteRead "$filePath" $i) | |
| CHECKSUM=$(( CHECKSUM + aux )) | |
| done | |
| CHECKSUM=$(( CHECKSUM ^ 0xFFFF )) # Bitwise NOT, ensuring an 16-bit value | |
| CHECKSUM=$(( CHECKSUM - 4 )) | |
| # Print Checksum State | |
| if [[ "$READ_CHECKSUM" == "$CHECKSUM" ]]; then | |
| printf "Ok" | |
| else | |
| printf "Not Ok (%04X != %04X)" $READ_CHECKSUM $CHECKSUM | |
| fi | |
| } | |
| function printKilometrage() { | |
| : ' | |
| Kilometrage: | |
| 0x0502 ... 0x0505 | |
| 0x0542 ... 0x0545 | |
| ' | |
| local Kilometrage=0 | |
| # Read Kilometrage | |
| for ((i = 0x0502; i <= 0x0505; i++)); do | |
| local aux=$(byteRead "$filePath" $i) | |
| Kilometrage=$(( (Kilometrage << 8) | aux )) | |
| done | |
| # Print Kilometrage | |
| printf "%d.%03d" $((Kilometrage / 1000)) $((Kilometrage % 1000)) | |
| } | |
| function main() { | |
| echo "" | |
| processArgs $@ | |
| # Check file path | |
| if [[ -z "$filePath" ]]; then | |
| filePath="eeprom.bin" | |
| echo "File path not specified, using: $filePath" | |
| fi | |
| # Make sure file exist | |
| if [[ ! -f "$filePath" ]]; then | |
| echo "Error EEprom file $filePath not present!" | |
| exit -1 | |
| fi | |
| echo " Vin $(printVin)" | |
| echo " Immo $(printImmoNo)" | |
| echo " CS $(printComponentSecurity)" | |
| echo " MAC $(printMAC)" | |
| echo " Pin $(printLoginPin)" | |
| echo " Immo $(printImmoState)" | |
| echo " Csum $(printChecksumState_VinImmo)" | |
| echo " Km $(printKilometrage)" | |
| echo "" | |
| } | |
| main $@ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment