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.
Vag EDC16 Eeprom Parser
#!/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