#------------------------------------------------------------------------------ # $File: map,v 1.11 2024/06/10 23:09:52 christos Exp $ # map: file(1) magic for Map data # # Garmin .FIT files https://pub.ks-and-ks.ne.jp/cycling/edge500_fit.shtml 8 string .FIT FIT Map data >15 byte 0 >>35 belong x \b, unit id %d >>39 lelong x \b, serial %u # https://pub.ks-and-ks.ne.jp/cycling/edge500_fit.shtml # 20 years after unix epoch # TZ=GMT date -d '1989-12-31 0:00' +%s >>43 leldate+631065600 x \b, %s >>47 leshort x \b, manufacturer %d >>47 leshort 1 \b (garmin) >>49 leshort x \b, product %d >>53 byte x \b, type %d >>53 byte 1 \b (Device) >>53 byte 2 \b (Settings) >>53 byte 3 \b (Sports/Cycling) >>53 byte 4 \b (Activity) >>53 byte 8 \b (Elevations) >>53 byte 10 \b (Totals) # Summary: Garmin map # From: Joerg Jenderek # URL: https://en.wikipedia.org/wiki/Garmin_.img # Reference: https://wiki.openstreetmap.org/wiki/OSM_Map_On_Garmin/IMG_File_Format # sourceforge.net/projects/garmin-img/files/IMG%20File%20Format/1.0/imgformat-1.0.pdf # GRR: similar to MBR boot sector handled by ./filesystems 0x1FE leshort =0xAA55 # look for valid map signature >0x13 string =IMG\0 >>0 use garmin-map 0 name garmin-map >0 ubyte x Garmin !:mime application/x-garmin-map # If non-zero, every byte of the entire .img file is to be XORed with this value >0 ubyte !0 \b, %#x XORed # goto block before FAT >(0x40.b*512) ubyte x # 1st fat name "DLLINFO TXT" only found for vpm >>&512 string =DLLINFO\ TXT map (Voice Processing) # there exist 2 other Garmin VPM formats; see ./audio !:ext vpm # Deutsch__Yannick_D4481-00_0210.vpm #>>>512 search/0x0116da60/s RIFF \b; with # determine type voice type by ./riff #>>>>&0 indirect x \b >>&512 string !DLLINFO\ TXT map !:ext img # 9 zeros >1 ubelong !0 \b, zeroes %#x # Map's version major >8 ubyte x v%u # Map's version minor >9 ubyte x \b.%.2u # Map description[20], 0x20 padded >0x49 string x %.20s # Map name, continued (0x20 padded, \0 terminated) >0x65 string >\ \b%.31s # Update year (+1900 for val >= 0x63, +2000 for val <= 0x62) >0xB ubyte x \b, updated >>0xB ubyte >0x62 >>>0xB ubyte-100 x 20%.2u >>0xB ubyte <0x63 >>>0xB ubyte x 20%.2u # Update month (0-11) >0xA ubyte x \b-%.2u # All zeroes >0xc uleshort !0 \b, zeroes %#x # Mapsource flag, 1 - file created by Mapsource, 0 - Garmin map visible in Basecamp and Homeport #>0xE ubyte !0 \b, Mapsource flag %#x >0xE ubyte 1 \b, Mapsource # Checksum, sum of all bytes modulo 256 should be 0 #>0xF ubyte x \b, Checksum %#x # Signature: DSKIMG 0x00 or DSDIMG 0x00 for demo map >0x10 string !DSKIMG \b, signature "%.7s" >0x39 use garmin-date # Map file identifier like GARMIN\0 >0x41 string !GARMIN \b, id "%.7s" # Block size exponent, E1; appears to always be 0x09; minimum block size 512 bytes >0x61 ubyte !0x09 \b, E1=%u # Block size exponent, E2 ; file blocksize=2**(E1+E2) >>0x62 ubyte x \b, E2=%u >0x61 ubyte =0x09 \b, blocksize >>0x62 ubyte 0 512 >>0x62 ubyte 1 1024 >>0x62 ubyte 2 2048 >>0x62 ubyte 3 4096 >>0x62 ubyte 4 8192 >>0x62 ubyte 5 16384 >>0x62 default x >>>0x62 ubyte x E2=%u # MBR signature >0x1FE leshort !0xAA55 \b, invalid MBR # 512 zeros >0x200 uquad !0 \b, zeroes %#llx # First sub-file offset (absolute); sometimes NO/UNKNOWN sub file! >0x40C ulelong >0 \b, at %#x # sub-file Header length #>>(0x40C.l) uleshort x \b, header len %#x >>(0x40C.l) uleshort x %u bytes # sub-file Type[10] like "GARMIN RGN" "GARMIN TRE", "GARMIN TYP", etc. >>(0x40C.l+2) ubyte >0x1F >>>(0x40C.l+2) ubyte <0xFF >>>>(0x40C.l+2) string x "%.10s" # 0x00 for most maps, 0x80 for locked maps (City Nav, City Select, etc.) >>>>(0x40C.l+13) ubyte >0 \b, locked %#x # Block sequence numbers like 0000 0100 0200 ... FFFF # >0x420 ubequad >0 \b, seq. %#16.16llx # >>0x428 ubequad >0 \b%16.16llx # >>>0x430 ubequad >0 \b%16.16llx # >>>>0x438 ubequad >0 \b%16.16llx # >>>>>0x440 ubequad >0 \b%16.16llx # >>>>>>0x448 ubequad >0 \b%16.16llx # >>>>>>>0x450 ubequad >0 \b%16.16llx # >>>>>>>>0x458 ubequad >0 \b%16.16llx # >>>>>>>>>0x460 ubequad >0 \b%16.16llx # >>>>>>>>>>0x468 ubequad >0 \b%16.16llx # >>>>>>>>>>>0x470 ubequad >0 \b%16.16llx # >>>>>>>>>>>>0x478 ubequad >0 \b%16.16llx # >>>>>>>>>>>>>0x480 ubequad >0 \b%16.16llx # >>>>>>>>>>>>>>0x488 ubequad >0 \b%16.16llx # >>>>>>>>>>>>>>>0x490 ubequad >0 \b%16.16llx # >>>>>>>>>>>>>>>>0x498 ubequad >0 \b%16.16llx # >>>>>>>>>>>>>>>>>0x4A0 ubequad >0 \b%16.16llx # >>>>>>>>>>>>>>>>>>0x4A8 ubequad >0 \b%16.16llx # look for end of FAT #>>0x420 search/512/s \xff\xff FAT END # Physical block number of FAT header #>0x40 ubyte x \b, FAT at phy. block %u >0x40 ubyte x >>(0x40.b*512) ubyte x # 1st FAT block >>>&511 use garmin-fat # 2nd FAT block >>>&1023 use garmin-fat # 3th FAT block >>>&1535 use garmin-fat # 4th FAT block >>>&2047 use garmin-fat # ... xth FAT block # # 314 zeros but not in vpm and also gmaptz.img >0x84 uquad !0 \b, at 0x84 %#llx # display FileAllocationTable block entry in garmin map 0 name garmin-fat >0 ubyte x \b; # sub file part; 0x0003 seems to be garbage >0x10 uleshort !0 next %#4.4x >0x10 uleshort =0 # fat flag 0~dummy block 1~true sub file >>0 ubyte !1 flag %u >>0 ubyte =1 # sub-file name like MAKEGMAP 12345678 >>>0x1 string x %.8s # sub-file typ like RGN TRE MDR LBL >>>0x9 string x \b.%.3s # size of sub file >>>0xC ulelong x \b, %u bytes # 32-bit block sequence numbers #>>>0x20 ubequad x \b, seq. %#16.16llx # display date stored inside Garmin maps like yyyy-mm-dd h:mm:ss 0 name garmin-date # year like 2018 >0 uleshort x \b, created %u # month (0-11) >2 ubyte x \b-%.2u # day (1-31) >3 ubyte x \b-%.2u # hour (0-23) >4 ubyte x %u # minute (0-59) >5 ubyte x \b:%.2u # second (0-59) >6 ubyte x \b:%.2u # Summary: Garmin Map subfiles # From: Joerg Jenderek # URL: https://wiki.openstreetmap.org/wiki/OSM_Map_On_Garmin/IMG_File_Format # Garmin Common Header 2 string GARMIN\ # skip ASCII text by checking for low header length >0 uleshort <0x1000 Garmin map, # URL: https://wiki.openstreetmap.org/wiki/OSM_Map_On_Garmin/GMP_Subfile_Format >>9 string GMP subtile !:mime application/x-garmin-gpm !:ext gmp # copyright message >>>(0.s) string x %s >>>0x0E use garmin-date # URL: https://wiki.openstreetmap.org/wiki/OSM_Map_On_Garmin/MDR_Subfile_Format # This contains the searchable address table used for finding routing destinations >>9 string MDR address table !:mime application/x-garmin-mdr !:ext mdr # URL: https://wiki.openstreetmap.org/wiki/OSM_Map_On_Garmin/NOD_Subfile_Format # http://svn.parabola.me.uk/display/trunk/doc/nod.txt # This contains the routing information >>9 string NOD routing !:mime application/x-garmin-nod !:ext nod >>>0x0E use garmin-date #>>>0x15 ulelong x \b, at %#x #>>>0x19 ulelong x %#x bytes NOD1 #>>>0x25 ulelong x \b, at %#x #>>>0x29 ulelong x %#x bytes NOD2 #>>>0x31 ulelong x \b, at %#x #>>>0x35 ulelong x %#x bytes NOD3 # URL: http://www.pinns.co.uk/osm/net.html # routable highways (length, direction, allowed speed,house address information) >>9 string NET highways !:mime application/x-garmin-net !:ext net #>>>0x15 ulelong x \b, at %#x #>>>0x19 ulelong x %#x bytes NET1 #>>>0x22 ulelong >0 #>>>>0x1E ulelong x \b, at %#x #>>>>0x22 ulelong x %#x bytes NET2 #>>>0x2B ulelong >0 #>>>>0x27 ulelong x \b, at %#x #>>>>0x2B ulelong x %#x bytes NET3 # URL: https://wiki.openstreetmap.org/wiki/OSM_Map_On_Garmin/LBL_Subfile_Format >>9 string LBL labels !:mime application/x-garmin-lbl !:ext lbl >>>(0.s) string x %s # Label coding type 6h 9h and ah >>>0x1E ubyte x \b, coding type %#x #>>>0x15 ulelong x \b, at %#x #>>>0x19 ulelong x %#x bytes LBL1 #>>>0x1F ulelong x \b, at %#x #>>>0x23 ulelong x %#x bytes LBL2 #>>>0x2D ulelong x \b, at %#x #>>>0x31 ulelong x %#x bytes LBL3 # URL: https://wiki.openstreetmap.org/wiki/OSM_Map_On_Garmin/SRT_Subfile_Format # A lookup table of the chars in the map's codepage, and their collating sequence >>9 string SRT sort table !:mime application/x-garmin-srt !:ext srt >>>0x0E use garmin-date # URL: https://wiki.openstreetmap.org/wiki/OSM_Map_On_Garmin/TRE_Subfile_Format >>9 string TRE tree !:mime application/x-garmin-tre !:ext tre # title like City Nav Europe NTU 2019.2 Basemap # or OSM Street map >>>(0.s) string x %s # 2nd title like Copyright 1995-2018 by GARMIN Corporation. # or http://www.openstreetmap.org/ >>>>&1 string x %s >>>0x0E use garmin-date #>>>0x21 ulelong x \b, at %#x #>>>0x25 ulelong x %#x bytes TRE1 #>>>0x29 ulelong x \b, at %#x #>>>0x2D ulelong x %#x bytes TRE2 #>>>0x31 ulelong x \b, at %#x #>>>0x35 ulelong x %#x bytes TRE3 # Copyright record size #>>>0x39 uleshort x \b, copyright record size %u # Map ID >>>0x74 ulelong x \b, ID %#x # URL: https://www.gpspower.net/garmin-tutorials/353310-basecamp-installing-free-desktop-map.html # For road traffic information service (RDS/TMS/TMC). Commonly seen in City Navigator maps >>9 string TRF traffic, !:mime application/x-garmin-trf !:ext trf # city/region like Preitenegg >>>(0.s+1) string x 1st %s # highway part like L606/L148 >>>>&1 string x %s # URL: https://wiki.openstreetmap.org/wiki/OSM_Map_On_Garmin/Format # Reference: http://www.pinns.co.uk/osm/typformat.html # customize the appearance of objects. For GPS and MapSource/Qlandkarte better looking maps >>9 string TYP types !:mime application/x-garmin-typ !:ext typ >>>0x0E use garmin-date # character set 1252 65001~UTF8 >>>0x15 uleshort x \b, code page %u # POIs #>>>0x17 ulelong x \b, at %#x #>>>0x1B ulelong x %#x bytes TYP1 # extra pois #>>>0x5B ulelong x \b, at %#x #>>>0x5F ulelong x %#x bytes TYP8 # URL: https://wiki.openstreetmap.org/wiki/OSM_Map_On_Garmin/RGN_Subfile_Format # http://www.pinns.co.uk/osm/RGN.html # region data used by the Garmin software >>9 string RGN region !:mime application/x-garmin-rgn !:ext rgn # POIs,Indexed POIs,Polylines or Polygons or first map level #>>>0x15 ulelong x \b, at %#x #>>>0x19 ulelong x %#x bytes RGN1 # polygons with extended types #>>>0x21 ulelong >0 #>>>>0x1D ulelong x \b, at %#x #>>>>0x21 ulelong x %#x bytes RGN2 # polylines with extended types #>>>0x3D ulelong >0 #>>>>0x39 ulelong x \b, at %#x #>>>>0x3D ulelong x %#x bytes RGN3 # extended POIs #>>>0x59 ulelong >0 #>>>>0x55 ulelong x \b, at %#x #>>>>0x59 ulelong x %#x bytes RGN3 #>>9 default x unknown map type # Header length; GMP:31h 35h 3Dh,MDR:11Eh 238h 2C4h 310h,NOD:3Fh 7Fh,NET:64h, # LBL:2A9h,SRT:1Dh 25h 27h,TRE:CFh 135h,TRF:5Ah,TYP:5Bh 6Eh 7Ch AEh,RGN:7Dh >>0 uleshort x \b, header length %#x # URL: https://www.memotech.franken.de/FileFormats/ # Reference: https://www.memotech.franken.de/FileFormats/Garmin_RGN_Format.pdf # From: Joerg Jenderek 0 string KpGr Garmin update # format version like: 0064h~1.0 >0x4 uleshort !0x0064 >>4 uleshort/100 x \b, version %u >>4 uleshort%100 x \b.%u # 1st Garmin entry >6 use garmin-entry # 2nd Garmin entry >(0x6.l+10) ubyte x >>&0 use garmin-entry # 3rd entry >(0x6.l+10) ubyte x >>&(&0.l+4) ubyte x >>>&0 use garmin-entry # look again at version to use default clause >0x4 uleshort x # test for region content by looking for # Garmin *.srf by ./images with normal builder name "SQA" or longer "hales" # 1 space after equal sign >>0x3a search/5/s GARMIN\ BITMAP \b= !:mime image/x-garmin-exe !:ext exe >>>&0 indirect x # if not bitmap *.srf then region; 1 space after equal sign >>0x3a default x \b= !:mime application/x-garmin-rgn !:ext rgn # recursiv embedded >>>0x3a search/5/s KpGrd >>>>&0 indirect x # look for ZIP or JAR archive by ./archive and ./zip >>>0x3a search/5/s PK\003\004 >>>>&0 indirect x # TODO: other garmin RGN record content like foo #>>0x3a search/5/s bar BAR # display information of Garmin RGN record 0 name garmin-entry # record length: 2 for Data, for Application often 1Bh sometimes 1Dh, "big" for Region #>0 ulelong x \b, length %#x # data record (ID='D') with version content like 0064h~1.0 >4 ubyte =0x44 >>5 uleshort !0x0064 \b; Data >>>5 uleshort/100 x \b, version %u >>>5 uleshort%100 x \b.%u # Application Record (ID='A') >4 ubyte =0x41 \b; App # version content like 00c8h~2.0 >>5 uleshort !0x00C8 >>>5 uleshort/100 x \b, version %u >>>5 uleshort%100 x \b.%u # builder name like: SQA sqa build hales >>7 string x \b, build by %s # build date like: Oct 25 1999, Oct 1 2008, Feb 23 2009, Dec 15 2009 >>>&1 string x %s # build time like: 11:26:12, 11:45:54, 14:16:13, 18:23:01 >>>>&1 string x %s # region record (ID='R') >4 ubyte =0x52 \b; Region # region ID:14~fw_all.bin: 78~ZIP, RGN or SRF bitmap; 148~ZIP or JAR; 249~display firmware; 251~WiFi or GCD firmware; 255~ZIP >>5 uleshort x ID=%u # delay in ms: like 0, 500 >>7 ulelong !0 \b, %u ms # region size (is record length - 10) #>>11 ulelong x \b, length %#x # region content like: # "KpGr"~recursiv embedded,"GARMIN BITMAP"~Garmin Bitmap *.srf, "PK"~ZIP archive #>>15 string x \b, content "%s" >>15 ubequad x \b, content %#llx... # This does NOT WORK! #>>15 indirect x \b; contains >4 default x \b; other # garmin Record ID Identifies the record content like: D A R >>4 ubyte x ID '%c' # TOM TOM GPS watches ttbin files: # https://github.com/ryanbinns/ttwatch/tree/master/ttbin # From: Daniel Lenski 0 byte 0x20 >1 leshort 0x0007 >>0x76 byte 0x20 >>>0x77 leshort 0x0075 TomTom activity file, v7 >>>>8 leldate x (%s, >>>>3 byte x device firmware %d. >>>>4 byte x \b%d. >>>>5 byte x \b%d, >>>>6 leshort x product ID %04d) # Garmin firmware: # https://www.memotech.franken.de/FileFormats/Garmin_GCD_Format.pdf # https://www.gpsrchive.com/GPSMAP/GPSMAP%2066sr/Firmware.html 0 string GARMIN >6 uleshort 100 GARMIN firmware (version 1.0)