User Tools

Site Tools


doc:appunti:hardware:garmin_map_checksum

GARMIN map checksum gmapbmap.sum

On my new GARMIN eTrex 10 there was a pre-loaded map (the quite useless worldwide basemap). One of the first thing I did, was to replace it with an home-made OpenStreetMap based map.

Once connected to the computer using the USB cable, I found the following files on the USB storage:

  • Garmin/gmapbmap.img
  • Garmin/gmapbmap.sum

The gmapbmap.img file is obviously the map file, but what the hell is the gmapbmap.sum file instead? The first thing that you think of is a checksum to verify the integrity of the file. It is right, but what is the algorithm used to calculate that checksum? I tried several standard methods, like CRC32 or XOR parity, but without success.

It turned out that the file is just the sum of all the bytes of the map, packed into the sum file as a little endian 64 bit integer number.

It is not clear to me what happen if the sum will exceed the 64 bit limit (it can theoretically happen with a map with file size of 16 Mb), so please report to me your cases (map files and sum files) so that I can investigate.

Is the map checksum actually used?

It seems that the sum file is not used, at least by my eTrex 10. Infact I uploaded my home-made map, leaving the original gmapbmap.sum file; the device actually used the map, without any error or warning message.

How to calculate or verify the GARMIN sum

Here you are a small Python script to calculate or to verify the sum file:

#!/usr/bin/python
 
import os.path
import struct
import sys
 
__author__ = "Niccolo Rigacci"
__copyright__ = "Copyright 2020 Niccolo Rigacci <niccolo@rigacci.org>"
__license__ = "GPLv3-or-later"
__email__ = "niccolo@rigacci.org"
__version__ = "0.1.0"
 
def usage():
    print('Usage: %s [gmapbmap.img|gmapbmap.sum]' % (os.path.basename(sys.argv[0]),))
    sys.exit(1)
 
def calculate_sum(mapfile):
    checksum = 0x0
    with open(mapfile, 'rb') as filein:
        while True:
            chunk = filein.read(1)
            if chunk:
                checksum += ord(chunk)
            else:
                break
    return checksum
 
if len(sys.argv) < 2:
    usage()
arg = sys.argv[1]
 
if arg.lower().endswith('.img'):
    print('Calculating the GARMIN map sum for file %s...' % (arg,))
    checksum = calculate_sum(arg)
    print("The sum is (big-endian order): 0x%08X" % (checksum,))
    sumfile = arg[:-3] + 'sum'
    if not os.path.exists(sumfile):
        print('Writing sum (in little-endian order) to file %s' % (sumfile,))
        with open(sumfile, 'wb') as fileout:
            fileout.write(struct.pack('<i', checksum))
    sys.exit(0)
 
elif arg.lower().endswith('.sum'):
    with open(arg, 'rb') as filein:
        buf = filein.read(4)
        checksum = struct.unpack_from('<i', buf)[0]
    print('The GARMIN sum in file %s is (big-endian order): 0x%08X' % (arg, checksum))
    mapfile = arg[:-3] + 'img'
    print('Calculating the sum for map file %s...' % (mapfile,))
    checksum2 = calculate_sum(mapfile)
    if checksum == checksum2:
        print('OK')
        sys.exit(0)
    else:
        print('FAIL')
        sys.exit(1)
 
else:
    usage()
doc/appunti/hardware/garmin_map_checksum.txt · Last modified: 2020/04/26 10:32 by niccolo