Skip to content

Instantly share code, notes, and snippets.

@PL125
Last active August 20, 2025 14:27
Show Gist options
  • Select an option

  • Save PL125/9903a12942eef52db8425dfbc6acfd6b to your computer and use it in GitHub Desktop.

Select an option

Save PL125/9903a12942eef52db8425dfbc6acfd6b to your computer and use it in GitHub Desktop.

Revisions

  1. PL125 revised this gist Aug 20, 2025. 1 changed file with 7 additions and 6 deletions.
    13 changes: 7 additions & 6 deletions VagEdc16Decoder.sh
    Original file line number Diff line number Diff line change
    @@ -5,6 +5,7 @@ function printUsage() {
    echo " OPTIONS:"
    echo " -f <= EEprom file location"
    echo " -? -h --? --help <= Help info"
    echo "E.g., bash VagEdc16Decoder.sh -f EEpromfile.bin"
    echo ""
    }

    @@ -126,7 +127,7 @@ function printMAC() {
    MAC=$(( (MAC << 8) | aux ))
    done

    # print Mac
    # Print Mac
    printf "%08X" $MAC
    }

    @@ -146,7 +147,7 @@ function printVin() {
    done

    # Print Vin if valid
    if [[ "$VIN" == "W"* ]] ; then
    if [[ "$VIN" == [WTV]* ]]; then # Volkswagen | Skoda | Audi | Seat
    printf "%s" $VIN
    else
    printf "Vin is invalid, read EEprom and try again"
    @@ -162,7 +163,7 @@ function printImmoState() {
    Immo On = 0x73
    Immo Off = 0x60
    '
    # Read Immo
    # Read Immo State
    local IMMO=$(printf "0x%02X" "$(byteRead "$filePath" 0x0156)")

    # Print Immo State
    @@ -209,7 +210,7 @@ function printChecksumState_VinImmo() {
    CHECKSUM=$(( CHECKSUM - 4 ))

    # Print Checksum State
    if [[ "$READ_CHECKSUM" -eq "$CHECKSUM" ]]; then
    if [[ "$READ_CHECKSUM" == "$CHECKSUM" ]]; then
    printf "Ok"
    else
    printf "Not Ok (%04X != %04X)" $READ_CHECKSUM $CHECKSUM
    @@ -241,13 +242,13 @@ function main() {
    processArgs $@

    # Check file path
    if [[ -z "$filePath" ]] ; then
    if [[ -z "$filePath" ]]; then
    filePath="eeprom.bin"
    echo "File path not specified, using: $filePath"
    fi

    # Make sure file exist
    if [[ ! -f "$filePath" ]] ; then
    if [[ ! -f "$filePath" ]]; then
    echo "Error EEprom file $filePath not present!"
    exit -1
    fi
  2. PL125 revised this gist Apr 27, 2025. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion VagEdc16Decoder.sh
    Original file line number Diff line number Diff line change
    @@ -232,7 +232,7 @@ function printKilometrage() {
    done

    # Print Kilometrage
    printf "%d" $Kilometrage
    printf "%d.%03d" $((Kilometrage / 1000)) $((Kilometrage % 1000))
    }

    function main() {
  3. PL125 created this gist Apr 26, 2025.
    268 changes: 268 additions & 0 deletions VagEdc16Decoder.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,268 @@
    #!/usr/bin/env bash

    function printUsage() {
    echo "Usage: $0 <OPTIONS>"
    echo " OPTIONS:"
    echo " -f <= EEprom file location"
    echo " -? -h --? --help <= Help info"
    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" == "W"* ]] ; then
    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
    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" -eq "$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" $Kilometrage
    }

    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 $@