aboutsummaryrefslogtreecommitdiff
path: root/tools/hex2bin-2.0
diff options
context:
space:
mode:
authorJuan J. Martinez <jjm@usebox.net>2021-05-03 08:21:10 +0100
committerJuan J. Martinez <jjm@usebox.net>2021-05-03 10:00:00 +0100
commitc3b0fa04a663fe233765b83d3be41a42aa08c25d (patch)
tree0befda349001ef6ce306b39378f9c70ad917363e /tools/hex2bin-2.0
downloadreturn-of-traxtor-cpc-c3b0fa04a663fe233765b83d3be41a42aa08c25d.tar.gz
return-of-traxtor-cpc-c3b0fa04a663fe233765b83d3be41a42aa08c25d.zip
Initial import for public releaseHEADmain
Diffstat (limited to 'tools/hex2bin-2.0')
-rwxr-xr-xtools/hex2bin-2.0/Makefile42
-rw-r--r--tools/hex2bin-2.0/bin/.deleteme0
-rwxr-xr-xtools/hex2bin-2.0/bin/hex2binbin0 -> 33200 bytes
-rwxr-xr-xtools/hex2bin-2.0/bin/mot2binbin0 -> 33200 bytes
-rw-r--r--tools/hex2bin-2.0/doc/CRC list.txt542
-rw-r--r--tools/hex2bin-2.0/doc/ChangeLog_hex2bin57
-rw-r--r--tools/hex2bin-2.0/doc/ChangeLog_mot2bin49
-rw-r--r--tools/hex2bin-2.0/doc/README225
-rw-r--r--tools/hex2bin-2.0/doc/S-record.txt361
-rw-r--r--tools/hex2bin-2.0/doc/formats.txt72
-rw-r--r--tools/hex2bin-2.0/doc/intelhex.spc409
-rw-r--r--tools/hex2bin-2.0/doc/srec.txt447
-rw-r--r--tools/hex2bin-2.0/src/binary.c196
-rw-r--r--tools/hex2bin-2.0/src/binary.h36
-rw-r--r--tools/hex2bin-2.0/src/common.c527
-rw-r--r--tools/hex2bin-2.0/src/common.h116
-rw-r--r--tools/hex2bin-2.0/src/hex2bin.1294
-rw-r--r--tools/hex2bin-2.0/src/hex2bin.c587
-rw-r--r--tools/hex2bin-2.0/src/hex2bin.pod161
-rw-r--r--tools/hex2bin-2.0/src/libcrc.c204
-rw-r--r--tools/hex2bin-2.0/src/libcrc.h44
-rw-r--r--tools/hex2bin-2.0/src/mot2bin.c518
22 files changed, 4887 insertions, 0 deletions
diff --git a/tools/hex2bin-2.0/Makefile b/tools/hex2bin-2.0/Makefile
new file mode 100755
index 0000000..c8ef10b
--- /dev/null
+++ b/tools/hex2bin-2.0/Makefile
@@ -0,0 +1,42 @@
+# Makefile hex2bin/mot2bin
+SRCDIR = src
+BINDIR = bin
+OBJDIR = obj
+TGTDIR = $(BINDIR)
+B_SRCFILES= $(foreach F, hex2bin.c common.c libcrc.c binary.c, $(SRCDIR)/$(F))
+B_OBJFILES= $(foreach F, hex2bin.o common.o libcrc.o binary.o, $(OBJDIR)/$(F))
+M_SRCFILES= $(foreach F, mot2bin.c common.c libcrc.c binary.c, $(SRCDIR)/$(F))
+M_OBJFILES= $(foreach F, mot2bin.o common.o libcrc.o binary.o, $(OBJDIR)/$(F))
+
+# For generating documentation (hex2bin.1, select the second line)
+# -- You will require pod2man installed for this to work
+TGT_FILES = $(foreach F, hex2bin mot2bin, $(TGTDIR)/$(F))
+#TGT_FILES = $(foreach F, hex2bin mot2bin hex2bin.1, $(TGTDIR)/$(F))
+
+CPFLAGS = -std=gnu99 -O3 -fsigned-char -Wall -pedantic
+# Compile
+all: objectdir $(TGT_FILES)
+
+$(OBJDIR)/%.o: $(SRCDIR)/%.c
+ gcc -c $(CPFLAGS) $< -o $@
+
+objectdir:
+ @echo "Creating directory $(OBJDIR)..."
+ mkdir -p $(OBJDIR)
+
+$(TGTDIR)/hex2bin.1: $(SRCDIR)/hex2bin.pod
+ pod2man $(SRCDIR)/hex2bin.pod > $(TGTDIR)/hex2bin.1
+
+$(TGTDIR)/hex2bin: $(B_OBJFILES)
+ gcc $(CPFLAGS) -o $(TGTDIR)/hex2bin $(B_OBJFILES)
+
+$(TGTDIR)/mot2bin: $(M_OBJFILES)
+ gcc $(CPFLAGS) -o $(TGTDIR)/mot2bin $(M_OBJFILES)
+
+clean:
+ @echo "Removing objects directory $(OBJDIR)/ ..."
+ @rm -rf $(OBJDIR)
+
+cleanall: clean
+ @echo "Removing binary files in $(BINDIR)/ ..."
+ @rm -f $(BINDIR)/*
diff --git a/tools/hex2bin-2.0/bin/.deleteme b/tools/hex2bin-2.0/bin/.deleteme
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/hex2bin-2.0/bin/.deleteme
diff --git a/tools/hex2bin-2.0/bin/hex2bin b/tools/hex2bin-2.0/bin/hex2bin
new file mode 100755
index 0000000..c6967d7
--- /dev/null
+++ b/tools/hex2bin-2.0/bin/hex2bin
Binary files differ
diff --git a/tools/hex2bin-2.0/bin/mot2bin b/tools/hex2bin-2.0/bin/mot2bin
new file mode 100755
index 0000000..18400f4
--- /dev/null
+++ b/tools/hex2bin-2.0/bin/mot2bin
Binary files differ
diff --git a/tools/hex2bin-2.0/doc/CRC list.txt b/tools/hex2bin-2.0/doc/CRC list.txt
new file mode 100644
index 0000000..8549799
--- /dev/null
+++ b/tools/hex2bin-2.0/doc/CRC list.txt
@@ -0,0 +1,542 @@
+http://regregex.bbcmicro.net/crc-catalogue.htm
+
+CRC-8
+07
+<crc-8-atm>
+ Name : "CRC-8"
+ Width : 8
+ Poly : 07
+ Init : 00
+ RefIn : False
+ RefOut : False
+ XorOut : 00
+ Check : F4
+
+<crc-8-itu>
+ Name : "CRC-8/ITU"
+ Width : 8
+ Poly : 07
+ Init : 00
+ RefIn : False
+ RefOut : False
+ XorOut : 55
+ Check : A1
+
+<crc-8-rohc>
+ Name : "CRC-8/ROHC"
+ Width : 8
+ Poly : 07
+ Init : FF
+ RefIn : True
+ RefOut : True
+ XorOut : 0
+ Check : D0
+
+39
+<crc-8-darc>
+ Name : "CRC-8/DARC"
+ Width : 8
+ Poly : 39
+ Init : 00
+ RefIn : True
+ RefOut : True
+ XorOut : 00
+ Check : 15
+
+1D
+<crc-8-icode>
+ Name : "CRC-8/I-CODE"
+ Width : 8
+ Poly : 1D
+ Init : FD
+ RefIn : False
+ RefOut : False
+ XorOut : 00
+ Check : 7E
+
+<crc-8-j1850>
+ Name : "CRC-8/J1850" (new entry)
+ Width : 8
+ Poly : 1D
+ Init : FF
+ RefIn : False
+ RefOut : False
+ XorOut : FF
+ Check : 4B
+
+31
+<crc-8-maxim>
+ Name : "CRC-8/MAXIM"
+ Alias : "DOW-CRC"
+ Width : 8
+ Poly : 31
+ Init : 00
+ RefIn : True
+ RefOut : True
+ XorOut : 00
+ Check : A1
+
+9B
+<crc-8-wcdma>
+ Name : "CRC-8/WCDMA"
+ Width : 8
+ Poly : 9B
+ Init : 00
+ RefIn : True
+ RefOut : True
+ XorOut : 00
+ Check : 25
+
+8D
+<crc-8-ccitt>
+ Name : "CRC-8/CCITT" (new entry) 1-Wire?
+ Width : 8
+ Poly : 8D
+ Init : 00?
+ RefIn : False?
+ RefOut : False?
+ XorOut : 00?
+ Check : D2
+
+D5
+<crc-8>
+ Name : "CRC-8" (new entry)
+ Width : 8
+ Poly : D5
+ Init : 00?
+ RefIn : False?
+ RefOut : False?
+ XorOut : 00?
+ Check : BC
+
+CRC-16
+8005
+<crc-16>
+ Name : "ARC"
+ Alias : "CRC-16"
+ Alias : "CRC-IBM"
+ Alias : "CRC-16/ARC"
+ Alias : "CRC-16/LHA"
+ Width : 16
+ Poly : 8005
+ Init : 0000
+ RefIn : True
+ RefOut : True
+ XorOut : 0000
+ Check : BB3D
+
+<crc-16-buypass>
+ Name : "CRC-16/BUYPASS"
+ Alias : "CRC-16/VERIFONE"
+ Width : 16
+ Poly : 8005
+ Init : 0000
+ RefIn : False
+ RefOut : False
+ XorOut : 0000
+ Check : FEE8
+
+<crc-dds-110>
+ Name : "CRC-16/DDS-110"
+ Width : 16
+ Poly : 8005
+ Init : 800D
+ RefIn : False
+ RefOut : False
+ XorOut : 0000
+ Check : 9ECF
+ XCheck : CFE9
+
+<crc-16-maxim>
+ Name : "CRC-16/MAXIM"
+ Width : 16
+ Poly : 8005
+ Init : 0000
+ RefIn : True
+ RefOut : True
+ XorOut : FFFF
+ Check : 44C2
+
+<crc-usb>
+ Name : "CRC-16/USB"
+ Width : 16
+ Poly : 8005
+ Init : FFFF
+ RefIn : True
+ RefOut : True
+ XorOut : FFFF
+ Check : B4C8
+
+<crc-modbus>
+ Name : "MODBUS"
+ Width : 16
+ Poly : 8005
+ Init : FFFF
+ RefIn : True
+ RefOut : True
+ XorOut : 0000
+ Check : 4B37
+
+1021
+<crc-ccitt-1d0f>
+ Name : "CRC-16/AUG-CCITT"
+ Alias : "CRC-16/SPI-FUJITSU"
+ Width : 16
+ Poly : 1021
+ Init : 1D0F
+ RefIn : False
+ RefOut : False
+ XorOut : 0000
+ Check : E5CC
+
+<crc-ccitt-ffff>
+ Name : "CRC-16/CCITT-FALSE"
+ Width : 16
+ Poly : 1021
+ Init : FFFF
+ RefIn : False
+ RefOut : False
+ XorOut : 0000
+ Check : 29B1
+
+<crc-genibus>
+ Name : "CRC-16/GENIBUS"
+ Alias : "CRC-16/I-CODE"
+ Alias : "CRC-16/DARC"
+ Width : 16
+ Poly : 1021
+ Init : FFFF
+ RefIn : False
+ RefOut : False
+ XorOut : FFFF
+ Check : D64E
+
+<crc-ccitt-xmodem>
+ Name : "XMODEM"
+ Alias : "ZMODEM"
+ Alias : "CRC-16/ACORN"
+ Width : 16
+ Poly : 1021
+ Init : 0000
+ RefIn : False
+ RefOut : False
+ XorOut : 0000
+ Check : 31C3
+
+<crc-mcrf4xx>
+ Name : "CRC-16/MCRF4XX"
+ Width : 16
+ Poly : 1021
+ Init : FFFF
+ RefIn : True
+ RefOut : True
+ XorOut : 0000
+ Check : 6F91
+
+<crc-riello>
+ Name : "CRC-16/RIELLO"
+ Width : 16
+ Poly : 1021
+ Init : B2AA
+ RefIn : True
+ RefOut : True
+ XorOut : 0000
+ Check : 63D0
+
+ <crc-ccitt-kermit>
+ Name : "KERMIT"
+ Alias : "CRC-16/CCITT"
+ Alias : "CRC-16/CCITT-TRUE"
+ Alias : "CRC-CCITT"
+ Width : 16
+ Poly : 1021
+ Init : 0000
+ RefIn : True
+ RefOut : True
+ XorOut : 0000
+ Check : 2189
+ XCheck : 8921
+
+<crc-x25>
+ Name : "X-25"
+ Alias : "CRC-16/IBM-SDLC"
+ Alias : "CRC-16/ISO-HDLC"
+ Width : 16
+ Poly : 1021
+ Init : FFFF
+ RefIn : True
+ RefOut : True
+ XorOut : FFFF
+ Check : 906E
+ XCheck : 6E90
+
+0589
+<crc-dect-r>
+ Name : "CRC-16/DECT-R"
+ Alias : "R-CRC-16"
+ Width : 16
+ Poly : 0589
+ Init : 0000
+ RefIn : False
+ RefOut : False
+ XorOut : 0001
+ Check : 007E
+
+<crc-dect-x>
+ Name : "CRC-16/DECT-X"
+ Alias : "X-CRC-16"
+ Width : 16
+ Poly : 0589
+ Init : 0000
+ RefIn : False
+ RefOut : False
+ XorOut : 0000
+ Check : 007F
+
+3D65
+<crc-dnp>
+ Name : "CRC-16/DNP"
+ Width : 16
+ Poly : 3D65
+ Init : 0000
+ RefIn : True
+ RefOut : True
+ XorOut : FFFF
+ Check : EA82
+ XCheck : 82EA
+
+<crc-en-13757>
+ Name : "CRC-16/EN-13757"
+ Width : 16
+ Poly : 3D65
+ Init : 0000
+ RefIn : False
+ RefOut : False
+ XorOut : FFFF
+ Check : C2B7
+
+8BB7
+<crc-t10-dif>
+ Name : "CRC-16/T10-DIF"
+ Width : 16
+ Poly : 8BB7
+ Init : 0000
+ RefIn : False
+ RefOut : False
+ XorOut : 0000
+ Check : D0DB
+
+A097
+<crc-teledisk>
+ Name : "CRC-16/TELEDISK"
+ Width : 16
+ Poly : A097
+ Init : 0000
+ RefIn : False
+ RefOut : False
+ XorOut : 0000
+ Check : 0FB3
+
+CRC-24
+864CFB
+<crc-24>
+ Name : "CRC-24"
+ Alias : "CRC-24/OPENPGP"
+ Width : 24
+ Poly : 864CFB
+ Init : B704CE
+ RefIn : False
+ RefOut : False
+ XorOut : 000000
+ Check : 21CF02
+
+5D6DCB
+<crc-24-flexray-a>
+ Name : "CRC-24/FLEXRAY-A"
+ Width : 24
+ Poly : 5D6DCB
+ Init : FEDCBA
+ RefIn : False
+ RefOut : False
+ XorOut : 000000
+ Check : 7979BD
+
+<crc-24-flexray-b>
+ Name : "CRC-24/FLEXRAY-B"
+ Width : 24
+ Poly : 5D6DCB
+ Init : ABCDEF
+ RefIn : False
+ RefOut : False
+ XorOut : 000000
+ Check : 1F23B8
+
+CRC-32
+04C11DB7
+<crc-32>
+ Name : "CRC-32"
+ Alias : "CRC-32/ADCCP"
+ Alias : "PKZIP"
+ Width : 32
+ Poly : 04C11DB7
+ Init : FFFFFFFF
+ RefIn : True
+ RefOut : True
+ XorOut : FFFFFFFF
+ Check : CBF43926
+
+<crc-32-bzip2>
+ Name : "CRC-32/BZIP2"
+ Alias : "B-CRC-32"
+ Width : 32
+ Poly : 04C11DB7
+ Init : FFFFFFFF
+ RefIn : False
+ RefOut : False
+ XorOut : FFFFFFFF
+ Check : FC891918
+
+<crc-32-mpeg-2>
+ Name : "CRC-32/MPEG-2"
+ Width : 32
+ Poly : 04C11DB7
+ Init : FFFFFFFF
+ RefIn : False
+ RefOut : False
+ XorOut : 00000000
+ Check : 0376E6E7
+
+<crc-32-posix>
+ Name : "CRC-32/POSIX"
+ Alias : "CKSUM"
+ Width : 32
+ Poly : 04C11DB7
+ Init : 00000000
+ RefIn : False
+ RefOut : False
+ XorOut : FFFFFFFF
+ Check : 765E7680
+ LCheck : 377A6011
+
+<crc-32-jamcrc>
+ Name : "JAMCRC"
+ Width : 32
+ Poly : 04C11DB7
+ Init : FFFFFFFF
+ RefIn : True
+ RefOut : True
+ XorOut : 00000000
+ Check : 340BC6D9
+
+1EDC6F41
+<crc-32-C>
+ Name : "CRC-32C"
+ Alias : "CRC-32/ISCSI"
+ Alias : "CRC-32/CASTAGNOLI"
+ Width : 32
+ Poly : 1EDC6F41
+ Init : FFFFFFFF
+ RefIn : True
+ RefOut : True
+ XorOut : FFFFFFFF
+ Check : E3069283
+
+A833982B
+<crc-32-D>
+ Name : "CRC-32D"
+ Width : 32
+ Poly : A833982B
+ Init : FFFFFFFF
+ RefIn : True
+ RefOut : True
+ XorOut : FFFFFFFF
+ Check : 87315576
+
+741B8CD7
+<crc-32-K> (new entry)
+ Name : "CRC-32K"
+ Alias : "CRC-32/KOOPMAN"
+ Width : 32
+ Poly : 741B8CD7
+ Init : 00000000?
+ RefIn : False?
+ RefOut : False?
+ XorOut : 00000000?
+ Check : 085A3197 ?
+
+814141AB
+<crc-32-Q>
+ Name : "CRC-32Q"
+ Width : 32
+ Poly : 814141AB
+ Init : 00000000
+ RefIn : False
+ RefOut : False
+ XorOut : 00000000
+ Check : 3010BF7F
+
+000000AF
+<crc-32-xfer>
+ Name : "XFER"
+ Width : 32
+ Poly : 000000AF
+ Init : 00000000
+ RefIn : False
+ RefOut : False
+ XorOut : 00000000
+ Check : BD0BE338
+
+CRC-40
+<crc-40-gsm>
+ Name : "CRC-40/GSM"
+ Width : 40
+ Poly : 0004820009
+ Init : 0000000000
+ RefIn : False
+ RefOut : False
+ XorOut : 0000000000
+ Check : 2BE9B039B9
+
+CRC-64
+42F0E1EBA9EA3693
+<crc-64>
+ Name : "CRC-64"
+ Width : 64
+ Poly : 42F0E1EBA9EA3693
+ Init : 0000000000000000
+ RefIn : False
+ RefOut : False
+ XorOut : 0000000000000000
+ Check : 6C40DF5F0B497347
+
+<crc-64-we>
+ Name : "CRC-64/WE"
+ Width : 64
+ Poly : 42F0E1EBA9EA3693
+ Init : FFFFFFFFFFFFFFFF
+ RefIn : False
+ RefOut : False
+ XorOut : FFFFFFFFFFFFFFFF
+ Check : 62EC59E3F1A4F00A
+
+000000000000001B
+<crc-64-1b>
+ Name : "CRC-64/1B" (New entry)
+ Width : 64
+ Poly : 000000000000001B
+ Init : 0000000000000000
+ RefIn : True
+ RefOut : True
+ XorOut : 0000000000000000
+ Check : 46A5A9388A5BEFFE
+
+AD93D23594C935A9
+<crc-64-jones>
+ Name : "CRC-64/Jones" (New entry)
+ Width : 64
+ Poly : AD93D23594C935A9
+ Init : FFFFFFFFFFFFFFFF
+ RefIn : True
+ RefOut : True
+ XorOut : 0000000000000000
+ Check : CAA717168609F281
diff --git a/tools/hex2bin-2.0/doc/ChangeLog_hex2bin b/tools/hex2bin-2.0/doc/ChangeLog_hex2bin
new file mode 100644
index 0000000..3339250
--- /dev/null
+++ b/tools/hex2bin-2.0/doc/ChangeLog_hex2bin
@@ -0,0 +1,57 @@
+(UTF8 encoding)
+
+- hex2bin 1.0.12 - 20141122 Simone Fratini
+ small feature added
+ 20141121 Slucx
+ added line for removing extra CR when entering file name at run time.
+ 20141008 JP
+ removed junk code
+
+- hex2bin 1.0.11 - 20141005 Jacques Pelletier
+ added option to support byte-swapped hex used by Microchip's MPLAB IDE
+ corrected bug caused by extra LF at end or within file
+
+- hex2bin 1.0.10 - 20120509 Yoshimasa Nakane
+ modified error checking (also for output file, JP)
+ modified option parser (JP)
+
+- hex2bin 1.0.9 - 20120125 - Danny Schneider
+ Added code for filling a binary file to a given Max_Length relative to
+ Starting Address if Max-Address is larger than Highest-Address
+
+- hex2bin 1.0.8 - 20100402 - Jacques Pelletier
+ Fixed a bug with physical address calculation with extended linear address records
+ ADDRESS_MASK is now calculated from MEMORY_SIZE
+
+- hex2bin 1.0.7 - 20091212 - Jacques Pelletier
+ Fixed the crash on 0 byte length data records
+
+- hex2bin 1.0.6 - 20080103 - Jacques Pelletier
+ Fixed a bug when generating binary files near the end of the buffer
+
+- hex2bin 1.0.5 - 20071005 - Paweł Grabski -
+ Improved parsing of options.
+
+- hex2bin 1.0.4 - 20050126 - Jacques Pelletier -
+ Corrected the conversion LF -> CR+LF bug
+ applied patch for correcting the incorrect handling of
+ extended segment address record
+ added the Rockwell checksum extensions, and modified them a bit to allow
+ other types later.
+
+- hex2bin 1.0.3 - 20040617 - Alf Lacis -
+ Added pad byte (may not always want FF).
+ Added 'break;' to remove GNU compiler warning about label at
+ end of compound statement
+ Added PROGRAM & VERSION strings.
+
+- hex2bin 1.0.2 -
+ Corrected Bug in checksum verification
+
+- hex2bin 1.0.1 -
+ Added checking for memory indexing out of bound.
+ Added segmented and linear extended addressing in hex2bin.
+ Corrected an error: & were interverted with && (and bitwise, logical and).
+
+- hex2bin 1.0.0 -
+ Initial release
diff --git a/tools/hex2bin-2.0/doc/ChangeLog_mot2bin b/tools/hex2bin-2.0/doc/ChangeLog_mot2bin
new file mode 100644
index 0000000..4e3c7b3
--- /dev/null
+++ b/tools/hex2bin-2.0/doc/ChangeLog_mot2bin
@@ -0,0 +1,49 @@
+(UTF8 encoding tab = 4)
+- mot2bin 1.0.12 - 20141122 Simone Fratini
+ small feature added
+ 20141121 Slucx
+ added line for removing extra CR when entering file name at run time.
+
+- mot2bin 1.0.11 - 20141005 Jacques Pelletier
+ added option to support byte-swapped hex used by Microchip's MPLAB IDE
+ corrected bug caused by extra LF at end or within file
+
+- mot2bin 1.0.10 - 20120509 Yoshimasa Nakane
+ modified error checking (also for output file, JP)
+
+- mot2bin 1.0.9 - 20120125 - Danny Schneider
+ Added code for filling a binary file to a given Max_Length relative to
+ Starting Address if Max-Address is larger than Highest-Address
+ (JP) corrected a bug in the checksum checking
+ (JP) added code for record types 0,5,7,8,9
+
+- mot2bin 1.0.8 - 20100402 - Jacques Pelletier
+ ADDRESS_MASK is now calculated from MEMORY_SIZE
+
+- mot2bin 1.0.7 - 20091212 - Jacques Pelletier
+ Fixed the crash on 0 byte length data records
+
+- mot2bin 1.0.6 - 20080103 - Jacques Pelletier
+ Corrected a bug when generating a binary file near the end of the buffer.
+
+- mot2bin 1.0.5 - 20071005 - Paweł Grabski -
+ Improved parsing of options (same code as hex2bin).
+
+- mot2bin 1.0.4 - 20050128 - Jacques Pelletier -
+ Modified the checksum code to be able to generate other checksum types
+ later (ex. CRC).
+
+- mot2bin 1.0.3 - 20041026 - Scott A. Mintz -
+ Modified the MOT2BIN file to compute a checksum over a range using
+ 8bit, 16bit little endian, or 16bit big endian and optionally forcing
+ the checksum to a specific value by modifying a memory location.
+
+- mot2bin 1.0.2 - 20040617 - Alf Lacis -
+ Added pad byte (may not always want FF).
+ Added initialisation to Checksum to remove GNU
+ compiler warning about possible uninitialised usage
+ Added 2x'break;' to remove GNU compiler warning about label at
+ end of compound statement
+ Added PROGRAM & VERSION strings.
+
+- no previous ChangeLog -
diff --git a/tools/hex2bin-2.0/doc/README b/tools/hex2bin-2.0/doc/README
new file mode 100644
index 0000000..78ee7e7
--- /dev/null
+++ b/tools/hex2bin-2.0/doc/README
@@ -0,0 +1,225 @@
+Yet Another Hex to bin converter
+
+It can handle the extended Intel hex format in segmented and linear address
+modes. Records need not be sorted and there can be gaps between records.
+
+Some hex files are produced by compilers. They generate objects files for each
+module in a project, and when the linker generates the final hex file, the
+object files are stored within the hex files, but modules can appear not
+necessary in order of address.
+
+How does it work?
+
+Hex2bin/mot2bin allocates a 4 MBytes buffer and just place the converted bytes
+in its buffer. At the end, the buffer is written to disk. Using a buffer elimi-
+nates the need to sort records. If the option l is used (3), the buffer will be
+allocated with the maximum size specified if over 4Mbytes.
+
+Before reading the hex file, the buffer is filled with a default value. These
+padding bytes are all FF by default so an EPROM programmer can skip these bytes
+when programming. The padding value can be changed with the -p option.
+
+1. Compiling on Linux or other unix platforms
+
+ make
+
+ then
+
+ make install
+
+ This will install the program to /usr/local/bin.
+
+1a. Compiling for Windows on Msys, Cygwin or DOS prompt
+
+ The programs can be compiled as follows:
+ gcc -O2 -Wall -o hex2bin.exe hex2bin.c common.c libcrc.c binary.c
+ gcc -O2 -Wall -o mot2bin.exe mot2bin.c common.c libcrc.c binary.c
+
+2. Using hex2bin
+
+ hex2bin example.hex
+
+ hex2bin will generate a binary file example.bin starting at the
+ lowest address in the hex file.
+
+3. Binary file starting address and length
+
+ If the lowest address isn't 0000,
+ ex: 0100: (the first record begins with :nn010000xxx )
+
+ there will be problems when using the binary file to program a EPROM
+ since the first byte supposed to be at 0100 is stored in the binary file
+ at 0000.
+
+ you can specify a starting address for the binary file on the command line:
+
+ hex2bin -s 0000 start_at_0100.hex
+
+ This start address is not the same thing as the start address record in
+ the hex file. The start address record is used to specify the starting
+ address for execution of the binary code.
+
+ The bytes will be stored in the binary file with a padding from 0000
+ to the lowest address minus 1 (00FF in this case).
+
+ Similarly, the binary file can be padded up to Length -1 with FF or another byte.
+
+ Here, the space between the last byte and 07FF will be filled with FF.
+ hex2bin -l 0800 ends_before_07FF.hex
+
+ EPROM, EEPROM and Flash memories contain all FF when erased.
+
+ This program does minimal error checking since many hex files are
+ generated by known good assemblers.
+
+ When the source file name is
+ for-example.test.hex
+ the binary created will have the name
+ for-example.bin
+ the ".test" part will be dropped.
+
+ Hex2bin/mot2bin assume the source file doesn't contain overlapping records,
+ if so, overlaps will be reported.
+
+4. Checksum of source file
+
+ By default, it ignores record checksum errors, so that someone can change
+ by hand some bytes allowing quick and dirty changes.
+ If you want checksum error reporting, specify the option -c.
+
+ hex2bin -c example.hex
+
+ If there is a record checksum error somewhere, the program will continue the
+ conversion anyway.
+
+ The example file example.hex contains some records with checksum errors.
+
+5. Check value inserted inside binary file
+
+ A check value can be inserted in the resulting binary file.
+
+ hex2bin -k [0-4] -r [start] [end] -f [address] -C [Poly] [Init] [RefIn] [RefOut] [XorOut]
+
+ -k Select the check method:
+ 0: Checksum 8-bit
+ 1: Checksum 16-bit
+ 2: CRC8
+ 3: CRC16
+ 4: CRC32
+
+ -r Range to compute checksum over (default is min and max addresses)
+
+ -f Address of the result to write
+
+ -C Parameters for CRC
+ Parameters for common CRCs are listed in doc/CRC list.txt. They appear in
+ the same order. Feed them as is and use t for TRUE, f for FALSE.
+
+ See also the test/Makefile for these common CRCs; since they're tested,
+ you'll have the command line figured out.
+
+ -E Endian for storing the check result or forcing it
+ 0: little
+ 1: big
+
+ Change from previous versions of hex2bin/mot2bin:
+ Replace former options to this version
+ -k 1 -> -k 1 -E 0
+ -k 2 -> -k 1 -E 1
+
+6. Value inserted directly inside binary file
+ Instead of calculating a value, it can be inserted directly into the file at a specified address.
+
+ hex2bin -k [0|1|2] -F [address] [value]
+
+ -k Select the value format:
+
+ 0 = 8-bit
+ 1 = 16-bit
+ 2 = 32-bit
+
+ -F Address and value of checksum to force
+
+ -E Endian for storing the check result or forcing it
+ 0: little
+ 1: big
+
+7. Motorola S files
+
+ mot2bin example.s19
+
+ Options for mot2bin are the same as hex2bin. Executing the program
+ without argument will display available options. Some are specific to
+ Motorola files.
+
+ This program will handle S19 files generated for Motorola micropro-
+ cessors. Since I use this program for an EPROM programmer, I will
+ rarely need to have more than 4M, I limited the source program for
+ 24 bits or 16 bits address records.
+
+ 32 bits records are now supported, but obviously I can't allocate all
+ the memory for the binary target. What I did is simply assume that the
+ binary file will occupy less than 4M. For binary files greater than 4M,
+ see length option (section 3).
+
+8. Support for byte-swapped hex/S19 files
+
+ -w Wordwise swap: for each pair of bytes, exchange the low and high part.
+ If a checksum needs to be generated to insert in the binary file, select
+ one of the 16-bit checksums.
+
+ hex2bin -w test-byte-swap.hex
+
+9. Goodies
+
+ Description of the file formats is included.
+ Added examples files for extended addressing.
+
+ Check for overlapping records. The check is rather basic: supposing
+ that the buffer is filled with pad bytes, when a record overlaps a
+ previous one, value in the buffer will be different from the pad bytes.
+ This will not detect the case when the previous value equals the pad byte,
+ but it's more likely that more than one byte will be overlapped.
+
+
+10. Error messages
+
+ "Can't allocate memory."
+
+ Can't do anything in this case, so the program simply exits.
+
+ "Error occurred while reading from file"
+
+ Problem with fgets.
+
+ "Input/Output file %s cannot be opened. Enter new filename: "
+
+ The user may not have permissions to open the file.
+
+ "0 byte length data record ignored"
+
+ This means that an empty data record was read. Since it's empty, it's simply
+ ignored and should have no impact on the binary file.
+
+ "Data record skipped at ..."
+
+ This means that the records are falling outside the memory buffer.
+
+ "Overlapped record detected"
+
+ A record is overwritten by a subsequent record. If you're using SDCC, check
+ if more than one area is specified with a starting address. Checking the map
+ file generated by the linker can help.
+
+ "Some error occurred when parsing options."
+
+
+
+11. History
+
+ See ChangeLog
+
+12. Other hex tool
+
+ There is a program that supports more formats and has more features.
+ See SRecord at http://srecord.sourceforge.net/
diff --git a/tools/hex2bin-2.0/doc/S-record.txt b/tools/hex2bin-2.0/doc/S-record.txt
new file mode 100644
index 0000000..ba4abc1
--- /dev/null
+++ b/tools/hex2bin-2.0/doc/S-record.txt
@@ -0,0 +1,361 @@
+S-Record Format
+
+ A file in Motorola S-record format is an ASCII file. There are three different
+ formats:
+
+ S19 for 16-bit address
+ S2 for 24-bit address
+ S3 for 32-bit address
+
+
+ The files consist of optional symbol table information, data specifications
+ for loading memory, and a terminator record.
+
+ [ $$ {module_record}
+ symbol records
+ $$ [ module_record ]
+ symbol_records
+ $$]
+ header_record
+ data_records
+ record_count_record
+ terminator_record
+
+
+Module Record (Optional)
+
+ Each object file contains one record for each module that is a component of it. This
+ record contains the name of the module. There is one module record for each relocatable
+ object created by the assembler. The name of the relocatable object module
+ contained in the record comes from the IDNT directive. For absolute objects created
+ by the linker, there is one module record for each relocatable object file linked,
+ plus an additional record whose name comes from the NAME command for the
+ linker.
+
+ Example:
+
+ $$ MODNAME
+
+
+Symbol Record (Optional)
+
+ As many symbol records as needed can be contained in the object module. Up to 4
+ symbols per line can be used, but it is not mandatory that each line contain 4
+ symbols. A module can contain only symbol records.
+
+ Example:
+
+ APPLE $00000 LABEL1 $ODOC3
+ MEM $OFFFF ZEEK $01947
+
+ The module name associated with the symbols can be specified in the
+ module_record preceding the symbol records.
+
+ Example:
+
+ $$MAIN
+
+ Symbols are assumed to be in the module named in the preceding module_record
+ until another module is specified with another module_record. Symbols defined by
+ the linker's PUBLIC command appear following the first module record, which
+ indicates the name of the output object module specified by the linker's NAME
+ command.
+
+
+*****************************************************************************************
+
+Header Record (SO)
+
+ Each object module has exactly one header record with the following format:
+
+ S00600004844521B
+
+ Description:
+
+ S0 Identifies the record as a header record
+ 06 The number of bytes following this one
+ 0000 The address field, which is ignored
+ 484452 The string HDR in ASCII
+ 1B The checksum
+
+
+
+*****************************************************************************************
+
+Data Record (S1)
+
+ A data record specifies data bytes that are to be loaded into memory. Figure 1
+ shows the format for such a record. The columns shown in the figure represent half
+ of a byte (4 bits).
+
+ ---------------------------------------------
+ | 1 2 3 4 5 6 7 8 9 ... 40 41 42 |
+ | |
+ | S ID byte load data...data checksum |
+ | count address 1 n |
+ ---------------------------------------------
+ Figure 1: Data Record Formatter 16-Bit Load Address
+
+
+ Column Description
+
+ 1 Contains the ASCII character S, which indicates the start of
+ a record in Motorola S-record format.
+
+ 2 Contains the ASCII character identifying the record type.
+ For data records, this character is 1.
+
+ 3 to 4 Contain the count of the number of bytes following this one
+ within the record. The count includes the checksum and the
+ load address bytes but not the byte count itself.
+
+ 5 to 8 Contain the load address. The first data byte is to be loaded
+ into this address and subsequent bytes into the next sequential
+ address. Columns 5 and 6 contain the high-order address
+ byte, and columns 7 and 8 contain the low-order address byte.
+
+ 9 to 40 Contain the specifications for up to 16 bytes of data.
+
+ 41 to 42 Contain a checksum for the record. To calculate this, take the
+ sum of the values of all bytes from the byte count up to the
+ last data byte, inclusive, modulo 256. Subtract this result
+ from 255.
+
+
+*****************************************************************************************
+
+Data Record (S2)
+
+
+ A data record specifies data bytes that are to be loaded into memory. Figure 2
+ shows the format for such a record. The columns shown in the figure represent half
+ of a byte (4 bits).
+
+
+ ----------------------------------------------------
+ | 1 2 3 4 5 6 7 8 9 10 11 ... 42 43 44 |
+ | |
+ | S ID byte load data...data checksum |
+ | count address 1 n |
+ ----------------------------------------------------
+ Figure 2: Data Record Format for 24-Bit Load Address
+
+ Column Description
+
+ 1 Contains the ASCII character S, which indicates the start of
+ a record in Motorola S-record format.
+
+ 2 Contains the ASCII character identifying the record type.
+ For data records, this character is 2.
+
+ 3 to 4 Contain the count of the number of bytes following this one
+ within the record. The count includes the checksum and the
+ load address bytes but not the byte count itself.
+
+ 5 to 10 Contain the load address. The first data byte is to be loaded
+ into this address and subsequent bytes into the next sequential
+ address. Columns 5 and 6 contain the high-order address
+ byte, and columns 9 and 10 contain the low-order address byte.
+
+ 11 to 42 Contain the specifications for up to 16 bytes of data.
+
+ 43 to 44 Contain a checksum for the record. To calculate this, take the
+ sum of the values of all bytes from the byte count up to the
+ last data byte, inclusive, modulo 256. Subtract this result
+ from 255.
+
+
+*****************************************************************************************
+
+Data Record (S3)
+
+
+ A data record specifies data bytes that are to be loaded into memory. Figure 3
+ shows the format for such a record. The columns shown in the figure represent half
+ of a byte (4 bits).
+
+ ----------------------------------------------------------
+ | 1 2 3 4 5 6 7 8 9 10 11 12 13 ... 44 45 46 |
+ | |
+ | S ID byte load data...data checksum |
+ | count address 1 n |
+ ----------------------------------------------------------
+ Figure 3: Data Record Format for 32-Bit Load Address
+
+ Column Description
+
+ 1 Contains the ASCII character S, which indicates the start of
+ a record in Motorola S-record format.
+
+ 2 Contains the ASCII character identifying the record type.
+ For data records, this digit is 3 for 32-bit addresses.
+
+ 3 to 4 Contain the count of the number of bytes following this one
+ within the record. The count includes the checksum and the
+ load address bytes but not the byte count itself.
+
+ 5 to 12 Contain the load address. The first data byte is to be loaded
+ into this address and subsequent bytes into the next sequential
+ address. Columns 5 and 6 contain the high-order address
+ byte, and columns 11 and 12 contain the low-order address byte.
+
+ 13 to 44 Contain the specifications for up to 15 bytes of data.
+
+ 45 to 46 Contain a checksum for the record. To calculate this, take the
+ sum of the values of all bytes from the byte count up to the
+ last data byte, inclusive, modulo 256. Subtract this result
+ from 255.
+
+
+*****************************************************************************************
+
+Record Count Record (S5)
+
+
+ The record count record verifies the number of data records preceding it. Figure 4
+ shows the format for such a record. The columns shown in the figure represent half
+ of a byte (4 bits).
+
+ --------------------------------------
+ | 1 2 3 4 5 6 7 8 9 10 |
+ | |
+ | S ID byte # of data checksum |
+ | count records |
+ --------------------------------------
+ Figure 4: Record Count Record Format
+
+ Column Description
+
+ 1 Contains the ASCII character S, which indicates the start of
+ a record in Motorola S-record format.
+
+ 2 Contains the ASCII character 5, which indicates a record
+ count record.
+
+ 3 to 4 Contain the byte count, ASCII string 03.
+
+ 5 to 8 Contain the number of data records in this file. The high-
+ order byte is in columns 5 and 6.
+
+ 9 to 10 Contain the checksum for the record.
+
+ Example:
+
+ S503010DEE
+
+ The example above shows a record count record indicating a total of 269 records
+ (0x010D) and a checksum of 0xEE.
+
+
+
+*****************************************************************************************
+
+Terminator Record for 32-bit address (S7)
+
+ A terminator record specifies the end of the data records. Figure 5 shows the
+ format for such a record. The columns shown in the figure represent half of a byte
+ (4 bits).
+
+ -------------------------------------
+ | 1 2 3 4 5...12 13 14 |
+ | |
+ | S ID byte load checksum |
+ | count address |
+ -------------------------------------
+ Figure5: Terminator Record Format for 32-Bit Load Address
+
+ Column Description
+
+ 1 Contains the ASCII character S, which indicates the start of
+ a record in Motorola S-record format.
+
+ 2 Contains the ASCII character 7, which indicates a 32-bit
+ load address.
+
+ 3 to 4 Contain the byte count, ASCII string 04.
+
+ 5 to 12 Contain the load address that is either set to zero or to the
+ starting address specified in the END directive or START
+ command (there are no data bytes).
+
+ 13 to 14 Contain the checksum for the record.
+
+*****************************************************************************************
+
+Terminator Record for 24-bit address (S8)
+
+
+ A terminator record specifies the end of the data records. Figure 6 shows the
+ format for such a record. The columns shown in the figure represent half of a byte
+ (4 bits).
+
+ ----------------------------------------
+ | 1 2 3 4 5 6 7 8 9 10 11 12 |
+ | |
+ | S ID byte load checksum |
+ | count address |
+ ----------------------------------------
+ Figure 6: Terminator Record Format for 24-Bit Load Address
+
+ Column Description
+
+ 1 Contains the ASCII character S, which indicates the start of
+ a record in Motorola S-record format.
+
+ 2 Contains the ASCII character 8, which indicates a 24-bit
+ load address.
+
+ 3 to 4 Contain the byte count, ASCII string 04.
+
+ 5 to 10 Contain the load address, which is either set to zero or to the
+ starting address specified in the END directive or START
+ command. There are no data bytes.
+
+ 11 to 12 Contain the checksum for the record.
+
+ Example:
+
+ S804000AF0001
+
+ The previous example shows a terminator record with a 24-bit load address of
+ 0x000AF0 and a checksum of 0x01.
+
+
+*****************************************************************************************
+
+Terminator Record for 16-bit address (S9)
+
+
+ A terminator record specifies the end of the data records. Figure 7 shows the
+ format for such a record. The columns shown in the figure represent half of a byte
+ (4 bits).
+
+ -------------------------------------
+ | 1 2 3 4 5 6 7 8 9 10 |
+ | |
+ | S ID byte load checksum |
+ | count address |
+ -------------------------------------
+ Figure 7: Terminator Record Format for 16-Bit Load Address
+
+
+ Column Description
+
+ 1 Contains the ASCII character S, which indicates the start of
+ a record in Motorola S-record format.
+
+ 2 Contains the ASCII character 9, which indicates a 16-bit
+ load address.
+
+ 3 to 4 Contain the byte count, ASCII string 04.
+
+ 5 to 8 Contain the load address, which is either set to zero or to the
+ starting address specified in the END directive or START
+ command (there are no data bytes).
+
+ 9 to 10 Contain the checksum for the record.
+
+
+
+*****************************************************************************************
+ hagen.v.tronje@on-line.de
diff --git a/tools/hex2bin-2.0/doc/formats.txt b/tools/hex2bin-2.0/doc/formats.txt
new file mode 100644
index 0000000..25e5e37
--- /dev/null
+++ b/tools/hex2bin-2.0/doc/formats.txt
@@ -0,0 +1,72 @@
+Hex formats
+
+Intel
+=====
+
+Hexadecimal values are always in uppercase. Each line is a record.
+The sum of all the bytes in each record should be 00 (modulo 256).
+
+Record types:
+
+00: data records
+01: end-of-file record
+02: extended address record
+
+Data record
+-----------
+
+ :0D011C0000000000C3E0FF0000000000C30F
+
+: 0D 011C 00 00000000C3E0FF0000000000C3 0F
+| | | | -------------+------------ |
+| | | | | +--- Checksum
+| | | | +------------------ Data bytes
+| | | +--------------------------------- Record type
+| | +------------------------------------- Address
+| +----------------------------------------- Number of data bytes
++-------------------------------------------- Start of record
+
+
+End of file record
+------------------
+
+ :00000001FE
+
+: 00 0000 01 FE
+| | | | |
+| | | | +--- Checksum
+| | | +------ Record type
+| | +---------- Address
+| +-------------- Number of data bytes
++----------------- Start of record
+
+
+
+Extended address record
+-----------------------
+
+ :02010002E0001B
+
+: 02 0100 02 E000 1B
+| | | | | |
+| | | | | +--- Checksum
+| | | | +-------- Segment address
+| | | +----------- Record type
+| | +--------------- Address
+| +------------------- Number of data bytes
++---------------------- Start of record
+
+Following data records will start at E000:0100 or E0100
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tools/hex2bin-2.0/doc/intelhex.spc b/tools/hex2bin-2.0/doc/intelhex.spc
new file mode 100644
index 0000000..946d586
--- /dev/null
+++ b/tools/hex2bin-2.0/doc/intelhex.spc
@@ -0,0 +1,409 @@
+
+======================================================================
+
+Intel
+Hexadecimal Object File
+Format Specification
+Revision A, 1/6/88
+
+
+
+DISCLAIMER
+
+Intel makes no representation or warranties with respect to the contents
+hereof and specifically disclaims any implied warranties of
+merchantability or fitness for any particular purpose. Further, Intel
+reserves the right to revise this publication from time to time in the
+content hereof without obligation of Intel to notify any person of such
+revision or changes. The publication of this specification should not
+be construed as a commitment on Intel's part to implement any product.
+
+
+1. Introduction
+This document describes the hexadecimal object file format for the Intel
+8- bit, 16-bit, and 32-bit microprocessors. The hexadecimal format is
+suitable as input to PROM programmers or hardware emulators.
+Hexadecimal object file format is a way of representing an absolute
+binary object file in ASCII. Because the file is in ASCII instead of
+binary, it is possible to store the file is non-binary medium such as
+paper-tape, punch cards, etc.; and the file can also be displayed on CRT
+terminals, line printers, etc.. The 8-bit hexadecimal object file
+format allows for the placement of code and data within the 16-bit
+linear address space of the Intel 8-bit processors. The 16-bit
+hexadecimal format allows for the 20-bit segmented address space of the
+Intel 16-bit processors. And the 32-bit format allows for the 32-bit
+linear address space of the Intel 32-bit processors.
+The hexadecimal representation of binary is coded in ASCII alphanumeric
+characters. For example, the 8-bit binary value 0011-1111 is 3F in
+hexadecimal. To code this in ASCII, one 8-bit byte containing the ASCII
+code for the character '3' (0011-0011 or 033H) and one 8-bit byte
+containing the ASCII code for the character 'F' (0100-0110 or 046H) are
+required. For each byte value, the high-order hexadecimal digit is
+always the first digit of the pair of hexadecimal digits. This
+representation (ASCII hexadecimal) requires twice as ma ny bytes as the
+binary representation.
+A hexadecimal object file is blocked into records, each of which
+contains the record type, length, memory load address and checksum in
+addition to the data. There are currently six (6) different types of
+records that are defined, not all combinations of these records are
+meaningful, however. The records are:
+
+Data Record (8-, 16-, or 32-bit formats)
+End of File Record (8-, 16-, or 32-bit formats)
+Extended Segment Address Record (16- or 32-bit formats)
+Start Segment Address Record (16- or 32-bit formats)
+Extended Linear Address Record (32-bit format only)
+Start Linear Address Record (32-bit format only)
+
+
+2. General Record Format
+| RECORD | LOAD | | | INFO | |
+| MARK | RECLEN | OFFSET | RECTYP | or | CHKSUM |
+| ':' | | | | DATA | |
+ 1-byte 1-byte 2-bytes 1-byte n-bytes 1-byte
+
+Each record begins with a RECORD MARK field containing 03AH, the ASCII
+code for the colon (':') character.
+Each record has a RECLEN field which specifies the number of bytes of
+information or data which follows the RECTYP field of the record. Note
+that one data byte is represented by two ASCII characters. The maximum
+value of the RECLEN field is hexadecimal 'FF' or 255.
+Each record has a LOAD OFFSET field which specifies the 16-bit starting
+load offset of the data bytes, therefore this field is only used for
+Data Records. In other records where this field is not used, it should
+be coded as four ASCII zero characters ('0000' or 030303030H).
+Each record has a RECTYP field which specifies the record type of this
+record. The RECTYP field is used to interpret the remaining information
+within the record. The encoding for all the current record types are:
+
+'00' Data Record
+'01' End of File Record
+'02' Extended Segment Address Record
+'03' Start Segment Address Record
+'04' Extended Linear Address Record
+'05' Start Linear Address Record
+
+Each record has a variable length INFO/DATA field, it consists of zero
+or more bytes encoded as pairs of hexadecimal digits. The
+interpretation of this field depends on the RECTYP field.
+Each record ends with a CHKSUM field that contains the ASCII hexadecimal
+representation of the two's complement of the 8-bit bytes that result
+from converting each pair of ASCII hexadecimal digits to one byte of
+binary, from and including the RECLEN field to and including the last
+byte of the INFO/DATA field. Therefore, the sum of all the ASCII pairs
+in a record after converting to binary, from the RECLEN field to and
+including the CHKSUM field, is zero.
+
+
+3. Extended Linear Address Record (32-bit format only)
+| RECORD | LOAD | | | | |
+| MARK | RECLEN | OFFSET | RECTYP | ULBA | CHKSUM |
+| ':' | '02' | '0000' | '04' | | |
+ 1-byte 1-byte 2-bytes 1-byte 2-bytes 1-byte
+
+The 32-bit Extended Linear Address Record is used to specify bits 16-31
+of the Linear Base Address (LBA), where bits 0-15 of the LBA are zero.
+Bits 16-31 of the LBA are referred to as the Upper Linear Base Address
+(ULBA). The absolute memory address of a content byte in a subsequent
+Data Record is obtained by adding the LBA to an offset calculated by
+adding the LOAD OFFSET field of the containing Data Record to the index
+of the byte in the Data Record (0, 1, 2, ... n). This offset addition
+is done modulo 4G (i.e., 32-bits), ignoring any carry, so that offset
+wrap-around loading (from OFFFFFFFFH to OOOOOOOOOH) results in wrapping
+around from the end to the beginning of the 4G linear address defined by
+the LBA. The linear address at which a particular byte is loaded is
+calculated as:
+(LBA + DRLO + DRI) MOD 4G
+where:
+DRLO is the LOAD OFFSET field of a Data Record.
+DRI is the data byte index within the Data Record.
+
+When an Extended Linear Address Record defines the value of LBA, it may
+appear anywhere within a 32-bit hexadecimal object file. This value
+remains in effect until another Extended Linear Address Record is
+encountered. The LBA defaults to zero until an Extended Linear Address
+Record is encountered.
+The contents of the individual fields within the record are:
+
+RECORD MARK
+This field contains 03AH, the hexadecimal encoding of the ASCII colon
+(':') character.
+
+RECLEN
+The field contains 03032H, the hexadecimal encoding of the ASCII
+characters '02', which is the length, in bytes, of the ULBA data
+information within this record.
+
+LOAD OFFSET
+This field contains 030303030H, the hexadecimal encoding of the ASCII
+characters '0000', since this field is not used for this record.
+
+RECTYP
+This field contains 03034H, the hexadecimal encoding of the ASCII
+character '04', which specifies the record type to be an Extended Linear
+Address Record.
+
+ULBA
+This field contains four ASCII hexadecimal digits that specify the
+16-bit Upper Linear Base Address value. The high-order byte is the
+10th/llth character pair of the record. The low-order byte is the
+12th/13th character pair of the record.
+
+CHKSUM
+This field contains the check sum on the RECLEN, LOAD OFFSET, RECTYP,
+and ULBA fields.
+
+
+4. Extended Segment Address Record (16- or 32-bit formats)
+| RECORD | LOAD | | | | |
+| MARK | RECLEN | OFFSET | RECTYP | USBA | CHKSUM |
+| ':' | '02' | '0000' | '02' | | |
+ 1-byte 1-byte 2-bytes 1-byte 2-bytes 1-byte
+
+The 16-bit Extended Segment Address Record is used to specify bits 4-19
+of the Segment Base Address (SBA), where bits 0-3 of the SBA are zero.
+Bits 4-19 of the SBA are referred to as the Upper Segment Base Address
+(USBA). The absolute memory address of a content byte in a subsequent
+Data Record is obtained by adding the SBA to an offset calculated by
+adding the LOAD OFFSET field of the containing Data Record to the index
+of the byte in the Data Record (0, 1, 2, ... n). This offset addition
+is done modulo 64K (i.e., 16-bits), ignoring any carry, so that offset
+wraparound loading (from OFFFFH to OOOOOH) results in wrapping around
+from the end to the beginning of the 64K segment defined by the SBA.
+The address at which a particular byte is loaded is calculated as:
+
+ SBA + ([DRLO + DRI] MOD 64K)
+
+where:
+ DRLO is the LOAD OFFSET field of a Data Record.
+ DRI is the data byte index within the Data Record.
+
+When an Extended Segment Address Record defines the value of SBA, it
+may appear anywhere within a 16-bit hexadecimal object file. This
+value remains in effect until another Extended Segment Address
+Record is encountered. The SBA defaults to zero until an Extended
+Segment Address Record is encountered.
+
+The contents of the individual fields within the record are:
+
+RECORD MARK
+This field contains 03AH, the hexadecimal encoding of the ASCII
+colon (':') character.
+
+RECLEN
+The field contains 03032H, the hexadecimal encoding of the ASCII
+characters '02', which is the length, in bytes, of the USBA data
+information within this record.
+
+LOAD OFFSET
+This field contains 030303030H, the hexadecimal encoding of the
+ASCII characters '0000', since this field is not used for this
+record.
+
+RECTYP
+This field contains 03032H, the hexadecimal encoding of the ASCII
+character '02', which specifies the record type to be an Extended
+Segment Address Record.
+
+USBA
+This field contains four ASCII hexadecimal digits that specify the
+16-bit Upper Segment Base Address value. The high-order byte is the
+10th/1lth character pair of the record. The low-order byte is the
+12th/13th character pair of the record.
+
+CHKSUM
+This field contains the check sum on the RECLEN, LOAD OFFSET,
+RECTYP, and USBA fields.
+
+5. Data Record (8-, 16-, or 32-bit formats)
+
+| RECORD | LOAD | | | | |
+| MARK | RECLEN | OFFSET | RECTYP | DATA | CHKSUM |
+| ':' | | | '00' | | |
+ 1-byte 1-byte 2-bytes 1-byte n-bytes 1-byte
+
+
+The Data Record provides a set of hexadecimal digits that represent
+the ASCII code for data bytes that make up a portion of a memory
+image. The method for calculating the absolute address (linear in
+the 8-bit and 32-bit case and segmented in the 16-bit case) for each
+byte of data is described in the discussions of the Extended Linear
+Address Record and the Extended Segment Address Record.
+
+The contents of the individual fields within the record are:
+
+RECORD MARK
+This field contains 03AH, the hexadecimal encoding of the ASCII
+colon (':') character.
+
+RECLEN
+The field contains two ASCII hexadecimal digits that specify the
+number of data bytes in the record. The maximum value is 'FF' or
+04646H (255 decimal).
+
+LOAD OFFSET
+This field contains four ASCII hexadecimal digits representing the
+offset from the LBA (see Extended Linear Address Record) or SBA (see
+Extended Segment Address Record) defining the address which the
+first byte of the data is to be placed.
+
+RECTYP
+This field contains 03030H, the hexadecimal encoding of the ASCII
+character '00', which specifies the record type to be a Data Record.
+
+DATA
+This field contains pairs of ASCII hexadecimal digits, one pair for
+each data byte.
+
+CHKSUM
+This field contains the check sum on the RECLEN, LOAD OFFSET,
+RECTYP, and DATA fields.
+
+
+6. Start Linear Address Record (32-bit format only)
+
+| RECORD | LOAD | | | | |
+| MARK | RECLEN | OFFSET | RECTYP | EIP | CHKSUM |
+| ':' | '04' | '0000' | '05' | | |
+ 1-byte 1-byte 2-bytes 1-byte 4-bytes 1-byte
+
+
+The Start Linear Address Record is used to specify the execution
+start address for the object file. The value given is the 32-bit
+linear address for the EIP register. Note that this record only
+specifies the code address within the 32-bit linear address space of
+the 80386. If the code is to start execution in the real mode of
+the 80386, then the Start Segment Address Record should be used
+instead, since that record specifies both the CS and IP register
+contents necessary for real mode.
+
+The Start Linear Address Record can appear anywhere in a 32-bit
+hexadecimal object file. If such a record is not present in a
+hexadecimal object file, a loader is free to assign a default start
+address.
+
+The contents of the individual fields within the record are:
+
+RECORD MARK
+This field contains 03AH, the hexadecimal encoding of the ASCII
+colon (':') character.
+
+RECLEN
+The field contains 03034H, the hexadecimal encoding of the ASCII
+characters '04', which is the length, in bytes, of the EIP register
+content within this record.
+
+LOAD OFFSET
+This field contains 030303030H, the hexadecimal encoding of the
+ASCII characters '0000', since this field is not used for this
+record.
+
+RECTYP
+This field contains 03035H, the hexadecimal encoding of the ASCII
+character '05', which specifies the record type to be a Start Linear
+Address Record.
+
+EIP
+This field contains eight ASCII hexadecimal digits that specify the
+32-bit EIP register contents. The high-order byte is the 10th/1lth
+character pair.
+
+CHKSUM
+This field contains the check sum on the RECLEN, LOAD OFFSET,
+RECTYP, and EIP fields.
+
+
+7. Start Segment Address Record (16- or 32-bit formats)
+
+| RECORD | LOAD | | | | |
+| MARK | RECLEN | OFFSET | RECTYP | CS/IP | CHKSUM |
+| ':' | '04' | '0000' | '03' | | |
+ 1-byte 1-byte 2-bytes 1-byte 4-bytes 1-byte
+
+
+The Start Segment Address Record is used to specify the execution
+start address for the object file. The value given is the 20-bit
+segment address for the CS and IP registers. Note that this record
+only specifies the code address within the 20-bit segmented address
+space of the 8086/80186.
+
+The Start Segment Address Record can appear anywhere in a 16-bit
+hexadecimal object file. If such a record is not present in a
+hexadecimal object file, a loader is free to assign a default start
+address.
+
+The contents of the individual fields within the record are:
+
+RECORD MARK
+This field contains 03AH, the hexadecimal encoding of the ASCII
+colon (':') character.
+
+RECLEN
+The field contains 03034H, the hexadecimal encoding of the ASCII
+characters '04', which is the length, in bytes, of the CS/IP
+register contents within this record.
+
+LOAD OFFSET
+This field contains 030303030H, the hexadecimal encoding of the
+ASCII characters '0000', since this field is not used for this
+record.
+
+RECTYP
+This field contains 03033H, the hexadecimal encoding of the ASCII
+character '03', which specifies the record type to be a Start
+Segment Address Record.
+
+CS/IP
+This field contains eight ASCII hexadecimal digits that specify the
+16-bit CS register and 16-bit IP register contents. The high-order
+byte of the CS register content is the 10th/llth character pair, the
+low-order byte is the 12th/13th character pair of the record. The
+high-order byte of the IP register content is the 14th/15th
+character pair, the low-order byte is the 16th/17th character pair
+of the record.
+
+CHKSUM
+This field contains the check sum on the RECLEN, LOAD OFFSET,
+RECTYP, and CS/IP fields.
+
+
+
+8. End of File Record (8-, 16-, or 32-bit formats)
+
+| RECORD | LOAD | | | |
+| MARK | RECLEN | OFFSET | RECTYP | CHKSUM |
+| ':' | '00' | '0000' | '01' | |
+ 1-byte 1-byte 2-bytes 1-byte 1-byte
+
+The End of File Record specifies the end of the hexadecimal object
+file.
+
+The contents of the individual fields within the record are:
+
+RECORD MARK
+This field contains 03AH, the hexadecimal encoding of the ASCII
+colon (':') character.
+
+RECLEN
+The field contains 03030H, the hexadecimal encoding of the ASCII
+characters '00'. Since this record does not contain any INFO/DATA
+bytes, the length is zero.
+
+LOAD OFFSET
+This field contains 030303030H, the hexadecimal encoding of the
+ASCII characters '0000', since this field is not used for this
+record.
+
+RECTYP
+This field contains 03031H, the hexadecimal encoding of the ASCII
+character '01', which specifies the record type to be an End of File
+Record.
+
+CHKSUM
+This field contains the check sum an the RECLEN, LOAD OFFSET, and
+RECTYP fields. Since all the fields are static, the check sum can
+also be calculated statically, and the value is 04646H, the
+hexadecimal encoding of the ASCII characters 'FF'.
+
+========================================================================
+END
diff --git a/tools/hex2bin-2.0/doc/srec.txt b/tools/hex2bin-2.0/doc/srec.txt
new file mode 100644
index 0000000..ea63d31
--- /dev/null
+++ b/tools/hex2bin-2.0/doc/srec.txt
@@ -0,0 +1,447 @@
+S-Records
+
+
+ -S-Record Format-
+
+ Chaplin@keinstr.uucp (Roger Chaplin) reposted an article written
+ by mcdchg!motmpl!ron (Ron Widell) that explained how Motorola
+ S-Records are formatted. This comes from a unix man page. No
+ mention of which version of Unix is specified. This section
+ of the FAQ is a bit long. An anonymous ftp archive is currently
+ being sought. When one is found, the section will be placed in
+ the archive.
+
+
+ SREC(4) UNIX 5.0 (03/21/84) SREC(4)
+
+
+ An S-record file consists of a sequence of specially formatted
+ ASCII character strings. An S-record will be less than or equal to
+ 78 bytes in length.
+
+ The order of S-records within a file is of no significance and no
+ particular order may be assumed.
+
+ The general format of an S-record follow:
+
+ +------------------//-------------------//-----------------------+
+ | type | count | address | data | checksum |
+ +------------------//-------------------//-----------------------+
+
+ type A char-2- field. These characters describe the
+ type of record (S0, S1, S2, S3, S5, S7, S8, or
+ S9).
+ count A char-2- field. These characters when paired and
+ interpreted as a hexadecimal value, display the
+ count of remaining character pairs in the record.
+
+ address A char-4,6, or 8- field. These characters grouped
+ and interpreted as a hexadecimal value, display
+ the address at which the data field is to be
+ loaded into memory. The length of the field
+ depends on the number of bytes necessary to hold
+ the address. A 2-byte address uses 4 characters,
+ a 3-byte address uses 6 characters, and a 4-byte
+ address uses 8 characters.
+ data A char -0-64- field. These characters when paired
+ and interpreted as hexadecimal values represent
+ the memory loadable data or descriptive
+ information.
+
+ checksum A char-2- field. These characters when paired and
+ interpreted as a hexadecimal value display the
+ least significant byte of the ones complement of
+ the sum of the byte values represented by the
+ pairs of characters making up the count, the
+ address, and the data fields.
+
+ Each record is terminated with a line feed. If any
+ additional or different record terminator(s) or delay
+ characters are needed during transmission to the target
+ system it is the responsibility of the transmitting program
+ to provide them.
+
+ S0 Record The type of record is 'S0' (0x5330). The address
+
+
+ field is unused and will be filled with zeros
+ (0x0000). The header information within the data
+ field is divided into the following subfields.
+
+ mname is char-20- and is the
+ module name.
+ ver is char-2- and is the
+ version number.
+
+ rev is char-2- and is the
+ revision number.
+ description is char-0-36- and is a
+ text comment.
+
+ Each of the subfields is composed of ASCII bytes
+ whose associated characters, when paired,
+ represent one byte hexadecimal values in the case
+ of the version and revision numbers, or represent
+ the hexadecimal values of the ASCII characters
+ comprising the module name and description.
+
+ S1 Record The type of record field is 'S1' (0x5331). The
+ address field is interpreted as a 2-byte address.
+ The data field is composed of memory loadable
+ data.
+ S2 Record The type of record field is 'S2' (0x5332). The
+ address field is interpreted as a 3-byte address.
+ The data field is composed of memory loadable
+ data.
+
+ S3 Record The type of record field is 'S3' (0x5333). The
+ address field is interpreted as a 4-byte address.
+ The data field is composed of memory loadable
+ data.
+ S5 Record The type of record field is 'S5' (0x5335). The
+ address field is interpreted as a 2-byte value
+ and contains the count of S1, S2, and S3 records
+ previously transmitted. There is no data field.
+
+ S7 Record The type of record field is 'S7' (0x5337). The
+ address field contains the starting execution
+ address and is interpreted as 4-byte address.
+ There is no data field.
+ S8 Record The type of record field is 'S8' (0x5338). The
+ address field contains the starting execution
+ address and is interpreted as 3-byte address.
+ There is no data field.
+
+ S9 Record The type of record field is 'S9' (0x5339). The
+ address field contains the starting execution
+ address and is interpreted as 2-byte address.
+ There is no data field.
+
+ EXAMPLE
+
+ Shown below is a typical S-record format file.
+
+ S00600004844521B
+ S1130000285F245F2212226A000424290008237C2A
+ S11300100002000800082629001853812341001813
+ S113002041E900084E42234300182342000824A952
+ S107003000144ED492
+ S5030004F8
+ S9030000FC
+
+ The file consists of one S0 record, four S1 records, one S5
+ record and an S9 record.
+
+ The S0 record is comprised as follows:
+
+ S0 S-record type S0, indicating it is a header
+ record.
+ 06 Hexadecimal 06 (decimal 6), indicating that six
+ character pairs (or ASCII bytes) follow.
+
+ 00 00 Four character 2-byte address field, zeroes in
+ this example.
+ 48 ASCII H, D, and R - "HDR".
+
+ 1B The checksum.
+
+ The first S1 record is comprised as follows:
+ S1 S-record type S1, indicating it is a data record
+ to be loaded at a 2-byte address.
+
+ 13 Hexadecimal 13 (decimal 19), indicating that
+ nineteen character pairs, representing a 2 byte
+ address, 16 bytes of binary data, and a 1 byte
+ checksum, follow.
+ 00 00 Four character 2-byte address field; hexadecimal
+ address 0x0000, where the data which follows is to
+ be loaded.
+
+ 28 5F 24 5F 22 12 22 6A 00 04 24 29 00 08 23 7C Sixteen
+ character pairs representing the actual binary
+ data.
+ 2A The checksum.
+
+ The second and third S1 records each contain 0x13 (19)
+ character pairs and are ended with checksums of 13 and 52,
+ respectively. The fourth S1 record contains 07 character
+ pairs and has a checksum of 92.
+
+ The S5 record is comprised as follows:
+
+ S5 S-record type S5, indicating it is a count record
+ indicating the number of S1 records.
+
+
+
+ 03 Hexadecimal 03 (decimal 3), indicating that three
+ character pairs follow.
+
+ 00 04 Hexadecimal 0004 (decimal 4), indicating that
+ there are four data records previous to this
+ record.
+ F8 The checksum.
+
+ The S9 record is comprised as follows:
+
+ S9 S-record type S9, indicating it is a termination
+ record.
+ 03 Hexadecimal 03 (decimal 3), indicating that three
+ character pairs follow.
+
+ 00 00 The address field, hexadecimal 0 (decimal 0)
+ indicating the starting execution address.
+ FC The checksum.
+
+
+ -Intel Hex ASCII Format-
+
+ Intel HEX-ASCII format takes the form:
+
+ +----------------------------------- Start Character
+ |
+ | +-------------------------------- Byte Count
+ | | (# of data bytes)
+ | |
+ | | +-------------------------- Address of first data.
+ | | |
+ | | | +-------------------- Record Type (00 data,
+ | | | | 01 end of record)
+ | | | |
+ | | | | +------------ Data Bytes
+ | | | | |
+ | | | | | +---- Checksum
+ | | | | | |
+ | / \ / \ / \ / \ / \
+ : B C A A A A T T H H ... H H C C
+
+ An examples:
+
+ :10000000DB00E60F5F1600211100197ED300C3004C
+ :1000100000000101030307070F0F1F1F3F3F7F7FF2
+ :01002000FFE0
+ :00000001FF
+
+ This information comes from _Microprocessors and Programmed
+ Logic_, Second Edition, Kenneth L. Short, 1987, Prentice-Hall,
+ ISBN 0-13-580606-2.
+
+ Provisions have been made for data spaces larger than 64 kBytes.
+ The above reference does not discuss them. I suspect there is
+ a start of segment type record, but I do not know how it is
+ implemented.
+
+----------------------------------------------------------------------------
+
+/* This file contains source code to read a Motorola S-record file into
+** a memory image. The size of the file cannot exceed BUFSIZE of data.
+** The image is then written to disk either as binary data starting at
+** address 0 with no data gaps, or as a C array of unsigned longs.
+** Input lines must be no longer than MAXLINE. No check is made!
+**
+** Author: Eric McRae, Electro-Logic Machines, Inc.
+** Date: Copyright 1994
+**
+** This source code is made available to the public "as is". No
+** warranty is given or implied for it's proper operation. This source
+** code may be used in whole or in part as long as this copyright is
+** included.
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Comment the following line for non PC applications */
+#define PCDOS
+
+/* Uncomment the following line if you want a binary output instead of
+** a structure
+*/
+/* #define BINARY */
+
+#ifdef PCDOS /* Intel x86 architecture */
+#define BUFSIZE 49152 /* 48K to avoid segment hopping */
+#else /* Any reasonable (non-segmented) arch... */
+#define BUFSIZE 65536 /* As big as you want */
+#endif
+
+#define MAXLINE 256 /* Length of longest input line + 1 */
+/* Globals */
+FILE *infilePH, *outfilePH; /* Handles for input and output files */
+unsigned char *bufAC, /* Allocated image buffer */
+ *highestPC = NULL; /* Highest buffer address written */
+
+/* Change this string to reflect the name of the output array */
+char headerAC[] = "unsigned long sRec[] =\n{\n";
+
+/* Predeclarations */
+int parsebufN( char * ); /* Does the actual parsing */
+
+void main(int argc, const char * argv[])
+{
+ int c, /* Temp char storage */
+ resN; /* result status */
+ char *lbufPC, lbufAC[MAXLINE];
+ int linectrN = 0; /* Used to correlate parse fail to input line */
+
+#ifndef BINARY
+ int i;
+ unsigned long *codePL;
+ unsigned char *codePC;
+#endif
+
+ /* Check the argument count */
+ if( argc != 3 ) /* If didn't specify input and output files */
+ {
+ printf("Usage: %s: infile outfile\n", argv[0] );
+ exit(1);
+ }
+
+ /* OK, let's open some files */
+ if( ( infilePH = fopen( argv[1], "r" ) )== NULL )
+ {
+ printf("%s: Couldn't open input file %s\n", argv[0], argv[1] );
+ exit(2);
+ }
+
+ if( ( outfilePH = fopen( argv[2], "w" ) ) == NULL )
+ {
+ printf("%s: Couldn't open output file %s\n", argv[0], argv[3] );
+ exit(3);
+ }
+
+ /* OK, get a buffer and clear it. */
+ if( (bufAC = calloc( (size_t)BUFSIZE, (size_t)1 )) == NULL )
+ {
+ printf("%s: Couldn't malloc memory for buffer\n", argv[0] );
+ exit(4);
+ }
+
+ lbufPC = lbufAC; /* Point at beginning of line buffer */
+ while( c = fgetc( infilePH ))
+ {
+ if( (c == '\n') || (c == EOF) ) /* If found end of line or file */
+ { /* Parse the Line */
+ if( ( c == EOF ) && ( ferror( infilePH ) ) )
+ {
+ printf("%s: Error reading input file\n", argv[0] );
+ exit(5);
+ }
+ else
+ { /* OK, have a complete line in buffer */
+ linectrN++; /* Increment line counter */
+ if( lbufPC == lbufAC )
+ break; /* ignore blank lines */
+ *lbufPC = 0; /* Terminate the line string */
+ if( resN = parsebufN( lbufAC ) ) /* Parse data record to mem */
+ {
+ printf("%s: Error reading input file at line %d, return code = %d\n",
+ argv[0], linectrN, resN );
+ exit( resN );
+ }
+ lbufPC = lbufAC; /* Repoint line buffer pointer */
+ } /* End of have a complete line */
+ }
+ else
+ *lbufPC++ = c; /* Place char into line buffer */
+ }
+
+ /* At this point, the input file has been emptied. Now dispose of the
+ ** output data according to compilation mode.
+ */
+
+#ifdef BINARY
+
+ /* Write the buffer back to disk as a binary image */
+ resN = fwrite( bufAC, 1, (size_t)((highestPC - bufAC) + 1), outfilePH );
+ if( resN != (int)( (highestPC - bufAC) + 1) )
+ {
+ printf("%s: Error writing output file\n", argv[0] );
+ exit( 6 );
+ }
+
+#else
+ /* Produce a file that can be included in a C program. Data is read
+ ** from buffer as bytes to avoid portability/endian problems with
+ ** this program.
+ */
+ /* Output header first, then 1 long per line */
+ fwrite( (void *)headerAC, 1, (size_t)(sizeof( headerAC )-1), outfilePH );
+
+ codePL = (unsigned long *)bufAC;
+ for( i = (highestPC - bufAC + 1) / 4; i; i-- ) /* for each long */
+ {
+ codePC = (unsigned char *)codePL++;
+ sprintf(lbufAC, "0x%02x%02x%02x%02x%s",
+ *codePC, *(codePC + 1), *(codePC + 2), *(codePC + 3),
+ i == 1 ? "\n" : ",\n" ); /* No comma after final long */
+ fwrite( lbufAC, 1, (size_t)(strlen( lbufAC )), outfilePH );
+ }
+ /* OK, data has been written out, close end of array */
+ fwrite( "};\n", 1, (size_t)3, outfilePH );
+#endif
+}
+
+/* Function: parsebufV
+** Parses an S-record in the buffer and writes it into the buffer
+** if it is has a valid checksum.
+**
+** Args: pointer to character buffer for null terminated line
+** Returns: int result code: 0 = success, else failure
+*/
+int parsebufN( char *lbufPC )
+{
+ unsigned long addrL;
+ unsigned char cksmB, /* checksum of addr, count, & data length */
+ *bufPC; /* Pointer into memory array */
+ int i, countN, /* Number of bytes represented in record */
+ oheadN, /* Number of overhead (addr + chksum) bytes */
+ tvalN; /* Temp for check checksum */
+
+ switch( *(lbufPC+1) ) /* examine 2nd character on the line */
+ {
+ case '1': /* 16 bit address field */
+ if( sscanf(lbufPC, "S1%2x%4lx", &countN, &addrL ) != 2 )
+ return( 10 ); /* Flag error in S1 record */
+ oheadN = 3; /* 2 address + 1 checksum */
+ break;
+
+ case '2': /* 24 bit address field */
+ if( sscanf(lbufPC, "S2%2x%6lx", &countN, &addrL ) != 2 )
+ return( 11 ); /* Flag error in S2 record */
+ oheadN = 4; /* 3 address + 1 checksum */
+ break;
+
+ case '3': /* 32 bit address field */
+ if( sscanf(lbufPC, "S3%2x%8lx", &countN, &addrL ) != 2 )
+ return( 12 ); /* Flag error in S3 record */
+ oheadN = 5; /* 4 address + 1 checksum */
+ break;
+
+ default: /* ignore all but S1,2,3 records. */
+ return( 0 );
+ }
+
+ if( addrL > BUFSIZE ) return( 13 ); /* if address exceeds buffer size */
+ bufPC = bufAC + addrL; /* otherwise, point to right spot in buffer */
+
+ /* OK now see if checksum is OK, while reading data to buffer */
+ cksmB = 0;
+ countN++; /* Bump counter to read final checksum too */
+ for( i = 1; i <= countN; i++ )
+ {
+ sscanf( lbufPC + i*2, "%2x", &tvalN ); /* Scan a 2 hex digit byte */
+ cksmB += (unsigned char)tvalN;
+ if( ( i > oheadN ) && ( i < countN ) ) /* If scanned a data byte */
+ *bufPC++ = (unsigned char) tvalN; /* write it to the buffer */
+ }
+ if( cksmB += 1 ) return( 14 ); /* flag checksum error */
+
+ if( (bufPC - 1) > highestPC )
+ highestPC = bufPC - 1; /* track highest address loaded */
+
+ return( 0 ); /* Successful return */
+}
+
+
+
diff --git a/tools/hex2bin-2.0/src/binary.c b/tools/hex2bin-2.0/src/binary.c
new file mode 100644
index 0000000..63ead0d
--- /dev/null
+++ b/tools/hex2bin-2.0/src/binary.c
@@ -0,0 +1,196 @@
+/*---------------------------------------------------------------------------*
+ * binary.c *
+ * Copyright (C) 2014 Jacques Pelletier *
+ * *
+ * This program is free software; you can redistribute it and *or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software Foundation, *
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ *---------------------------------------------------------------------------*/
+
+#include <stdint.h>
+
+#include "binary.h"
+
+const uint8_t Reflect8[256] = {
+ 0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0,
+ 0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8,
+ 0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4,
+ 0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC,
+ 0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2,
+ 0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA,
+ 0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6,
+ 0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE,
+ 0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1,
+ 0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9,
+ 0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5,
+ 0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD,
+ 0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3,
+ 0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB,
+ 0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7,
+ 0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF,
+};
+
+uint16_t Reflect16(uint16_t Value16)
+{
+ return (((uint16_t) Reflect8[u16_lo(Value16)]) << 8) | ((uint16_t) Reflect8[u16_hi(Value16)]);
+}
+
+uint32_t Reflect24(uint32_t Value24)
+{
+ return (
+ (((uint32_t) Reflect8[u32_b0(Value24)]) << 16) |
+ (((uint32_t) Reflect8[u32_b1(Value24)]) << 8) |
+ ((uint32_t) Reflect8[u32_b2(Value24)])
+ );
+}
+
+uint32_t Reflect32(uint32_t Value32)
+{
+ return (
+ (((uint32_t) Reflect8[u32_b0(Value32)]) << 24) |
+ (((uint32_t) Reflect8[u32_b1(Value32)]) << 16) |
+ (((uint32_t) Reflect8[u32_b2(Value32)]) << 8) |
+ ((uint32_t) Reflect8[u32_b3(Value32)])
+ );
+}
+
+uint64_t Reflect40(uint64_t Value40)
+{
+ return (
+ (((uint64_t) Reflect8[u64_b0(Value40)]) << 32) |
+ (((uint64_t) Reflect8[u64_b1(Value40)]) << 24) |
+ (((uint64_t) Reflect8[u64_b2(Value40)]) << 16) |
+ (((uint64_t) Reflect8[u64_b3(Value40)]) << 8) |
+ ((uint64_t) Reflect8[u64_b4(Value40)])
+ );
+}
+
+uint64_t Reflect64(uint64_t Value64)
+{
+ return (
+ (((uint64_t) Reflect8[u64_b0(Value64)]) << 56) |
+ (((uint64_t) Reflect8[u64_b1(Value64)]) << 48) |
+ (((uint64_t) Reflect8[u64_b2(Value64)]) << 40) |
+ (((uint64_t) Reflect8[u64_b3(Value64)]) << 32) |
+ (((uint64_t) Reflect8[u64_b4(Value64)]) << 24) |
+ (((uint64_t) Reflect8[u64_b5(Value64)]) << 16) |
+ (((uint64_t) Reflect8[u64_b6(Value64)]) << 8) |
+ ((uint64_t) Reflect8[u64_b7(Value64)])
+ );
+}
+
+uint8_t u16_hi(uint16_t value)
+{
+ return (uint8_t)((value & 0xFF00) >> 8);
+}
+
+uint8_t u16_lo(uint16_t value)
+{
+ return (uint8_t)(value & 0x00FF);
+}
+
+uint8_t u32_b3(uint32_t value)
+{
+ return (uint8_t)((value & 0xFF000000) >> 24);
+}
+
+uint8_t u32_b2(uint32_t value)
+{
+ return (uint8_t)((value & 0x00FF0000) >> 16);
+}
+
+uint8_t u32_b1(uint32_t value)
+{
+ return (uint8_t)((value & 0x0000FF00) >> 8);
+}
+
+uint8_t u32_b0(uint32_t value)
+{
+ return (uint8_t)(value & 0x000000FF);
+}
+
+uint8_t u64_b7(uint64_t value)
+{
+ return (uint8_t)((value & 0xFF00000000000000) >> 56);
+}
+
+uint8_t u64_b6(uint64_t value)
+{
+ return (uint8_t)((value & 0x00FF000000000000) >> 48);
+}
+
+uint8_t u64_b5(uint64_t value)
+{
+ return (uint8_t)((value & 0x0000FF0000000000) >> 40);
+}
+
+uint8_t u64_b4(uint64_t value)
+{
+ return (uint8_t)((value & 0x000000FF00000000) >> 32);
+}
+
+uint8_t u64_b3(uint64_t value)
+{
+ return (uint8_t)((value & 0x00000000FF000000) >> 24);
+}
+
+uint8_t u64_b2(uint64_t value)
+{
+ return (uint8_t)((value & 0x0000000000FF0000) >> 16);
+}
+
+uint8_t u64_b1(uint64_t value)
+{
+ return (uint8_t)((value & 0x000000000000FF00) >> 8);
+}
+
+uint8_t u64_b0(uint64_t value)
+{
+ return (uint8_t)(value & 0x00000000000000FF);
+}
+
+/* Checksum/CRC conversion to ASCII */
+uint8_t nibble2ascii(uint8_t value)
+{
+ uint8_t result = value & 0x0f;
+
+ if (result > 9) return result + 0x41-0x0A;
+ else return result + 0x30;
+}
+
+bool cs_isdecdigit(char c)
+{
+ return (c >= 0x30) && (c < 0x3A);
+}
+
+unsigned char tohex(unsigned char c)
+{
+ if ((c >= '0') && (c < '9'+1))
+ return (c - '0');
+ if ((c >= 'A') && (c < 'F'+1))
+ return (c - 'A' + 0x0A);
+ if ((c >= 'a') && (c < 'f'+1))
+ return (c - 'a' + 0x0A);
+
+ return 0;
+}
+
+unsigned char todecimal(unsigned char c)
+{
+ if ((c >= '0') && (c < '9'+1))
+ return (c - '0');
+
+ return 0;
+}
+
+
diff --git a/tools/hex2bin-2.0/src/binary.h b/tools/hex2bin-2.0/src/binary.h
new file mode 100644
index 0000000..198589b
--- /dev/null
+++ b/tools/hex2bin-2.0/src/binary.h
@@ -0,0 +1,36 @@
+#ifndef _BINARY_H_
+#define _BINARY_H_
+
+typedef enum {false, true} bool;
+
+extern const unsigned char Reflect8[256];
+
+uint16_t Reflect16(uint16_t Value16);
+uint32_t Reflect24(uint32_t Value24);
+uint32_t Reflect32(uint32_t Value32);
+uint64_t Reflect40(uint64_t Value40);
+uint64_t Reflect64(uint64_t Value64);
+
+uint8_t u16_hi(uint16_t value);
+uint8_t u16_lo(uint16_t value);
+
+uint8_t u32_b3(uint32_t value);
+uint8_t u32_b2(uint32_t value);
+uint8_t u32_b1(uint32_t value);
+uint8_t u32_b0(uint32_t value);
+
+uint8_t u64_b7(uint64_t value);
+uint8_t u64_b6(uint64_t value);
+uint8_t u64_b5(uint64_t value);
+uint8_t u64_b4(uint64_t value);
+uint8_t u64_b3(uint64_t value);
+uint8_t u64_b2(uint64_t value);
+uint8_t u64_b1(uint64_t value);
+uint8_t u64_b0(uint64_t value);
+
+uint8_t nibble2ascii(uint8_t value);
+bool cs_isdecdigit(char c);
+unsigned char tohex(unsigned char c);
+unsigned char todecimal(unsigned char c);
+
+#endif /* _BINARY_H_ */
diff --git a/tools/hex2bin-2.0/src/common.c b/tools/hex2bin-2.0/src/common.c
new file mode 100644
index 0000000..f453dc4
--- /dev/null
+++ b/tools/hex2bin-2.0/src/common.c
@@ -0,0 +1,527 @@
+#include "common.h"
+
+filetype Filename; /* string for opening files */
+char Extension[MAX_EXTENSION_SIZE]; /* filename extension for output files */
+
+FILE *Filin, /* input files */
+ *Filout; /* output files */
+
+#ifdef USE_FILE_BUFFERS
+char *FilinBuf, /* text buffer for file input */
+ *FiloutBuf; /* text buffer for file output */
+#endif
+
+int Pad_Byte = 0xFF;
+bool Enable_Checksum_Error = false;
+bool Status_Checksum_Error = false;
+byte Checksum;
+unsigned int Record_Nb;
+
+/* This will hold binary codes translated from hex file. */
+byte *Memory_Block;
+unsigned int Lowest_Address, Highest_Address;
+unsigned int Starting_Address;
+unsigned int Max_Length = 0;
+unsigned int Minimum_Block_Size = 0x1000; // 4096 byte
+int Module;
+bool Minimum_Block_Size_Setted = false;
+bool Starting_Address_Setted = false;
+bool Max_Length_Setted = false;
+bool Swap_Wordwise = false;
+
+int Endian = 0;
+
+t_CRC Cks_Type = CHK8_SUM;
+unsigned int Cks_Start = 0, Cks_End = 0, Cks_Addr = 0, Cks_Value = 0;
+bool Cks_range_set = false;
+bool Cks_Addr_set = false;
+bool Force_Value = false;
+
+unsigned int Crc_Poly = 0x07, Crc_Init = 0, Crc_XorOut = 0;
+bool Crc_RefIn = false;
+bool Crc_RefOut = false;
+
+void usage(void)
+{
+ fprintf (stderr,
+ "\n"
+ "usage: %s [OPTIONS] filename\n"
+ "Options:\n"
+ " -c Enable record checksum verification\n"
+ " -C [Poly][Init][RefIn][RefOut][XorOut]\n CRC parameters"
+ " -e [ext] Output filename extension (without the dot)\n"
+ " -E [0|1] Endian for checksum/CRC, 0: little, 1: big\n"
+ " -f [address] Address of check result to write\n"
+ " -F [address] [value]\n Address and value to force\n"
+ " -k [0-4] Select check method (checksum or CRC) and size\n"
+ " -d display list of check methods/value size\n"
+ " -l [length] Maximal Length (Starting address + Length -1 is Max Address)\n"
+ " File will be filled with Pattern until Max Address is reached\n"
+ " -m [size] Minimum Block Size\n"
+ " File Size Dimension will be a multiple of Minimum block size\n"
+ " File will be filled with Pattern\n"
+ " Length must be a power of 2 in hexadecimal [see -l option]\n"
+ " Attention this option is STRONGER than Maximal Length \n"
+ " -p [value] Pad-byte value in hex (default: %x)\n"
+ " -r [start] [end]\n"
+ " Range to compute checksum over (default is min and max addresses)\n"
+ " -s [address] Starting address in hex (default: 0)\n"
+ " -w Swap wordwise (low <-> high)\n\n",
+ Pgm_Name,Pad_Byte);
+ exit(1);
+} /* procedure USAGE */
+
+void DisplayCheckMethods(void)
+{
+ fprintf (stderr,
+ "Check methods/value size:\n"
+ "0: Checksum 8-bit\n"
+ "1: Checksum 16-bit\n"
+ "2: CRC8\n"
+ "3: CRC16\n"
+ "4: CRC32\n");
+ exit(1);
+}
+
+#define LAST_CHECK_METHOD 4
+
+void *NoFailMalloc (size_t size)
+{
+ void *result;
+
+ if ((result = malloc (size)) == NULL)
+ {
+ fprintf (stderr,"Can't allocate memory.\n");
+ exit(1);
+ }
+ return (result);
+}
+
+/* Open the input file, with error checking */
+void NoFailOpenInputFile (char *Flnm)
+{
+ while ((Filin = fopen(Flnm,"r")) == NULL)
+ {
+ fprintf (stderr,"Input file %s cannot be opened. Enter new filename: ",Flnm);
+ if (fgets (Flnm,MAX_FILE_NAME_SIZE,stdin) == NULL) exit(1); /* modified error checking */
+
+ if (Flnm[strlen(Flnm) - 1] == '\n') Flnm[strlen(Flnm) - 1] = '\0';
+ }
+
+#ifdef USE_FILE_BUFFERS
+ FilinBuf = (char *) NoFailMalloc (BUFFSZ);
+ setvbuf(Filin, FilinBuf, _IOFBF, BUFFSZ);
+#endif
+} /* procedure OPENFILIN */
+
+/* Open the output file, with error checking */
+void NoFailOpenOutputFile (char *Flnm)
+{
+ while ((Filout = fopen(Flnm,"wb")) == NULL)
+ {
+ /* Failure to open the output file may be
+ simply due to an insufficiant permission setting. */
+ fprintf(stderr,"Output file %s cannot be opened. Enter new file name: ", Flnm);
+ if (fgets(Flnm,MAX_FILE_NAME_SIZE,stdin) == NULL) exit(1);
+
+ if (Flnm[strlen(Flnm) - 1] == '\n') Flnm[strlen(Flnm) - 1] = '\0';
+ }
+
+#ifdef USE_FILE_BUFFERS
+ FiloutBuf = (char *) NoFailMalloc (BUFFSZ);
+ setvbuf(Filout, FiloutBuf, _IOFBF, BUFFSZ);
+#endif
+
+} /* procedure OPENFILOUT */
+
+void GetLine(char* str,FILE *in)
+{
+ char *result;
+
+ result = fgets(str,MAX_LINE_SIZE,in);
+ if ((result == NULL) && !feof (in)) fprintf(stderr,"Error occurred while reading from file\n");
+}
+
+// 0 or 1
+int GetBin(const char *str)
+{
+ int result;
+ unsigned int value;
+
+ result = sscanf(str,"%u",&value);
+
+ if (result == 1) return value & 1;
+ else
+ {
+ fprintf(stderr,"GetBin: some error occurred when parsing options.\n");
+ exit (1);
+ }
+}
+
+int GetDec(const char *str)
+{
+ int result;
+ unsigned int value;
+
+ result = sscanf(str,"%u",&value);
+
+ if (result == 1) return value;
+ else
+ {
+ fprintf(stderr,"GetDec: some error occurred when parsing options.\n");
+ exit (1);
+ }
+}
+
+int GetHex(const char *str)
+{
+ int result;
+ unsigned int value;
+
+ result = sscanf(str,"%x",&value);
+
+ if (result == 1) return value;
+ else
+ {
+ fprintf(stderr,"GetHex: some error occurred when parsing options.\n");
+ exit (1);
+ }
+}
+
+// Char t/T: true f/F: false
+bool GetBoolean(const char *str)
+{
+ int result;
+ unsigned char value, temp;
+
+ result = sscanf(str,"%c",&value);
+ temp = tolower(value);
+
+ if ((result == 1) && ((temp == 't') || (temp == 'f')))
+ {
+ return (temp == 't');
+ }
+ else
+ {
+ fprintf(stderr,"GetBoolean: some error occurred when parsing options.\n");
+ exit (1);
+ }
+}
+
+void GetExtension(const char *str,char *ext)
+{
+ if (strlen(str) > MAX_EXTENSION_SIZE)
+ usage();
+
+ strcpy(ext, str);
+}
+
+/* Adds an extension to a file name */
+void PutExtension(char *Flnm, char *Extension)
+{
+ char *Period; /* location of period in file name */
+ bool Samename;
+
+ /* This assumes DOS like file names */
+ /* Don't use strchr(): consider the following filename:
+ ../my.dir/file.hex
+ */
+ if ((Period = strrchr(Flnm,'.')) != NULL)
+ *(Period) = '\0';
+
+ Samename = false;
+ if (strcmp(Extension, Period+1) == 0)
+ Samename = true;
+
+ strcat(Flnm,".");
+ strcat(Flnm, Extension);
+ if (Samename)
+ {
+ fprintf (stderr,"Input and output filenames (%s) are the same.", Flnm);
+ exit(1);
+ }
+}
+
+void VerifyChecksumValue(void)
+{
+ if ((Checksum != 0) && Enable_Checksum_Error)
+ {
+ fprintf(stderr,"Checksum error in record %d: should be %02X\n",
+ Record_Nb, (256 - Checksum) & 0xFF);
+ Status_Checksum_Error = true;
+ }
+}
+
+void CrcParamsCheck(void)
+{
+ switch (Cks_Type)
+ {
+ case CRC8:
+ Crc_Poly &= 0xFF;
+ Crc_Init &= 0xFF;
+ Crc_XorOut &= 0xFF;
+ break;
+ case CRC16:
+ Crc_Poly &= 0xFFFF;
+ Crc_Init &= 0xFFFF;
+ Crc_XorOut &= 0xFFFF;
+ break;
+ case CRC32:
+ break;
+ default:
+ fprintf (stderr,"See file CRC list.txt for parameters\n");
+ exit(1);
+ }
+}
+
+void WriteMemBlock16(uint16_t Value)
+{
+ if (Endian == 1)
+ {
+ Memory_Block[Cks_Addr - Lowest_Address] = u16_hi(Value);
+ Memory_Block[Cks_Addr - Lowest_Address +1] = u16_lo(Value);
+ }
+ else
+ {
+ Memory_Block[Cks_Addr - Lowest_Address +1] = u16_hi(Value);
+ Memory_Block[Cks_Addr - Lowest_Address] = u16_lo(Value);
+ }
+}
+
+void WriteMemBlock32(uint32_t Value)
+{
+ if (Endian == 1)
+ {
+ Memory_Block[Cks_Addr - Lowest_Address] = u32_b3(Value);
+ Memory_Block[Cks_Addr - Lowest_Address +1] = u32_b2(Value);
+ Memory_Block[Cks_Addr - Lowest_Address +2] = u32_b1(Value);
+ Memory_Block[Cks_Addr - Lowest_Address +3] = u32_b0(Value);
+ }
+ else
+ {
+ Memory_Block[Cks_Addr - Lowest_Address +3] = u32_b3(Value);
+ Memory_Block[Cks_Addr - Lowest_Address +2] = u32_b2(Value);
+ Memory_Block[Cks_Addr - Lowest_Address +1] = u32_b1(Value);
+ Memory_Block[Cks_Addr - Lowest_Address] = u32_b0(Value);
+ }
+}
+
+void WriteMemory(void)
+{
+ if ((Cks_Addr >= Lowest_Address) || (Cks_Addr < Highest_Address))
+ {
+ if(Force_Value)
+ {
+ switch (Cks_Type)
+ {
+ case 0:
+ Memory_Block[Cks_Addr - Lowest_Address] = Cks_Value;
+ fprintf(stdout,"Addr %08X set to %02X\n",Cks_Addr, Cks_Value);
+ break;
+ case 1:
+ WriteMemBlock16(Cks_Value);
+ fprintf(stdout,"Addr %08X set to %04X\n",Cks_Addr, Cks_Value);
+ break;
+ case 2:
+ WriteMemBlock32(Cks_Value);
+ fprintf(stdout,"Addr %08X set to %08X\n",Cks_Addr, Cks_Value);
+ break;
+ default:;
+ }
+ }
+ else if (Cks_Addr_set)
+ {
+ /* Add a checksum to the binary file */
+ if (!Cks_range_set)
+ {
+ Cks_Start = Lowest_Address;
+ Cks_End = Highest_Address;
+ }
+ /* checksum range MUST BE in the array bounds */
+
+ if (Cks_Start < Lowest_Address)
+ {
+ fprintf(stdout,"Modifying range start from %X to %X\n",Cks_Start,Lowest_Address);
+ Cks_Start = Lowest_Address;
+ }
+ if (Cks_End > Highest_Address)
+ {
+ fprintf(stdout,"Modifying range end from %X to %X\n",Cks_End,Highest_Address);
+ Cks_End = Highest_Address;
+ }
+
+ switch (Cks_Type)
+ {
+ case CHK8_SUM:
+ {
+ uint8_t wCKS = 0;
+
+ for (unsigned int i=Cks_Start; i<=Cks_End; i++)
+ {
+ wCKS += Memory_Block[i - Lowest_Address];
+ }
+
+ fprintf(stdout,"8-bit Checksum = %02X\n",wCKS & 0xff);
+ Memory_Block[Cks_Addr - Lowest_Address] = wCKS;
+ fprintf(stdout,"Addr %08X set to %02X\n",Cks_Addr, wCKS);
+ }
+ break;
+
+ case CHK16:
+ {
+ uint16_t wCKS, w;
+
+ wCKS = 0;
+
+ if (Endian == 1)
+ {
+ for (unsigned int i=Cks_Start; i<=Cks_End; i+=2)
+ {
+ w = Memory_Block[i - Lowest_Address +1] | ((word)Memory_Block[i - Lowest_Address] << 8);
+ wCKS += w;
+ }
+ }
+ else
+ {
+ for (unsigned int i=Cks_Start; i<=Cks_End; i+=2)
+ {
+ w = Memory_Block[i - Lowest_Address] | ((word)Memory_Block[i - Lowest_Address +1] << 8);
+ wCKS += w;
+ }
+ }
+ fprintf(stdout,"16-bit Checksum = %04X\n",wCKS);
+ WriteMemBlock16(wCKS);
+ fprintf(stdout,"Addr %08X set to %04X\n",Cks_Addr, wCKS);
+ }
+ break;
+
+ case CRC8:
+ {
+ uint8_t CRC8;
+ crc_table = NoFailMalloc(256);
+
+ if (Crc_RefIn)
+ {
+ init_crc8_reflected_tab(Reflect8[Crc_Poly]);
+ CRC8 = Reflect8[Crc_Init];
+ }
+ else
+ {
+ init_crc8_normal_tab(Crc_Poly);
+ CRC8 = Crc_Init;
+ }
+
+ for (unsigned int i=Cks_Start; i<=Cks_End; i++)
+ {
+ CRC8 = update_crc8(CRC8,Memory_Block[i - Lowest_Address]);
+ }
+
+ CRC8 = (CRC8 ^ Crc_XorOut) & 0xff;
+ Memory_Block[Cks_Addr - Lowest_Address] = CRC8;
+ fprintf(stdout,"Addr %08X set to %02X\n",Cks_Addr, CRC8);
+ }
+ break;
+
+ case CRC16:
+ {
+ uint16_t CRC16;
+ crc_table = NoFailMalloc(256 * 2);
+
+ if (Crc_RefIn)
+ {
+ init_crc16_reflected_tab(Reflect16(Crc_Poly));
+ CRC16 = Reflect16(Crc_Init);
+
+ for (unsigned int i=Cks_Start; i<=Cks_End; i++)
+ {
+ CRC16 = update_crc16_reflected(CRC16,Memory_Block[i - Lowest_Address]);
+ }
+ }
+ else
+ {
+ init_crc16_normal_tab(Crc_Poly);
+ CRC16 = Crc_Init;
+
+
+ for (unsigned int i=Cks_Start; i<=Cks_End; i++)
+ {
+ CRC16 = update_crc16_normal(CRC16,Memory_Block[i - Lowest_Address]);
+ }
+ }
+
+ CRC16 = (CRC16 ^ Crc_XorOut) & 0xffff;
+ WriteMemBlock16(CRC16);
+ fprintf(stdout,"Addr %08X set to %04X\n",Cks_Addr, CRC16);
+ }
+ break;
+
+ case CRC32:
+ {
+ uint32_t CRC32;
+
+ crc_table = NoFailMalloc(256 * 4);
+ if (Crc_RefIn)
+ {
+ init_crc32_reflected_tab(Reflect32(Crc_Poly));
+ CRC32 = Reflect32(Crc_Init);
+
+ for (unsigned int i=Cks_Start; i<=Cks_End; i++)
+ {
+ CRC32 = update_crc32_reflected(CRC32,Memory_Block[i - Lowest_Address]);
+ }
+ }
+ else
+ {
+ init_crc32_normal_tab(Crc_Poly);
+ CRC32 = Crc_Init;
+
+ for (unsigned int i=Cks_Start; i<=Cks_End; i++)
+ {
+ CRC32 = update_crc32_normal(CRC32,Memory_Block[i - Lowest_Address]);
+ }
+ }
+
+ CRC32 ^= Crc_XorOut;
+ WriteMemBlock32(CRC32);
+ fprintf(stdout,"Addr %08X set to %08X\n",Cks_Addr, CRC32);
+ }
+ break;
+
+ default:
+ ;
+ }
+
+ free(crc_table);
+ }
+ }
+ else
+ {
+ fprintf (stderr,"Force/Check address outside of memory range\n");
+ }
+
+ /* write binary file */
+ fwrite (Memory_Block,
+ Max_Length,
+ 1,
+ Filout);
+
+ free (Memory_Block);
+
+ // Minimum_Block_Size is set; the memory buffer is multiple of this?
+ if (Minimum_Block_Size_Setted==true)
+ {
+ Module = Max_Length % Minimum_Block_Size;
+ if (Module)
+ {
+ Memory_Block = (byte *) NoFailMalloc(Module);
+ memset (Memory_Block,Pad_Byte,Module);
+ fwrite (Memory_Block,
+ Module,
+ 1,
+ Filout);
+ free (Memory_Block);
+ if (Max_Length_Setted==true)
+ fprintf(stdout,"Attention Max Length changed by Minimum Block Size\n");
+ }
+ }
+}
diff --git a/tools/hex2bin-2.0/src/common.h b/tools/hex2bin-2.0/src/common.h
new file mode 100644
index 0000000..64caff5
--- /dev/null
+++ b/tools/hex2bin-2.0/src/common.h
@@ -0,0 +1,116 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "binary.h"
+#include "libcrc.h"
+
+/* To compile with Microsoft Visual Studio */
+#ifdef _MSC_VER
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#if defined(MSDOS) || defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS)
+#define _IS_OPTION_(x) (((x) == '-') || ((x) == '/'))
+#else
+/* Assume unix and similar */
+/* We don't accept an option beginning with a '/' because it could be a file name. */
+#define _IS_OPTION_(x) ((x) == '-')
+#endif
+
+/* We use buffer to speed disk access. */
+#ifdef USE_FILE_BUFFERS
+#define BUFFSZ 4096
+#endif
+
+/* FIXME how to get it from the system/OS? */
+#define MAX_FILE_NAME_SIZE 81
+
+#ifdef DOS
+#define MAX_EXTENSION_SIZE 4
+#else
+#define MAX_EXTENSION_SIZE 16
+#endif
+
+/* The data records can contain 255 bytes: this means 512 characters. */
+#define MAX_LINE_SIZE 1024
+
+typedef char filetype[MAX_FILE_NAME_SIZE];
+typedef unsigned char byte;
+typedef unsigned short word;
+
+#define LAST_CHECK_METHOD 4
+
+typedef enum Crc
+{
+ CHK8_SUM =0,
+ CHK16,
+ CRC8,
+ CRC16,
+ CRC32
+} t_CRC;
+
+extern const char *Pgm_Name;
+void usage(void);
+void DisplayCheckMethods(void);
+
+void *NoFailMalloc (size_t size);
+void NoFailOpenInputFile (char *Flnm);
+void NoFailOpenOutputFile (char *Flnm);
+void GetLine(char* str,FILE *in);
+int GetBin(const char *str);
+int GetDec(const char *str);
+int GetHex(const char *str);
+bool GetBoolean(const char *str);
+void GetExtension(const char *str,char *ext);
+void PutExtension(char *Flnm, char *Extension);
+
+filetype Filename; /* string for opening files */
+char Extension[MAX_EXTENSION_SIZE]; /* filename extension for output files */
+
+FILE *Filin, /* input files */
+ *Filout; /* output files */
+
+#ifdef USE_FILE_BUFFERS
+char *FilinBuf, /* text buffer for file input */
+ *FiloutBuf; /* text buffer for file output */
+#endif
+
+int Pad_Byte;
+bool Enable_Checksum_Error;
+bool Status_Checksum_Error;
+byte Checksum;
+unsigned int Record_Nb;
+
+/* This will hold binary codes translated from hex file. */
+byte *Memory_Block;
+unsigned int Lowest_Address, Highest_Address;
+unsigned int Starting_Address;
+unsigned int Max_Length;
+unsigned int Minimum_Block_Size;
+int Module;
+bool Minimum_Block_Size_Setted;
+bool Starting_Address_Setted;
+bool Max_Length_Setted;
+bool Swap_Wordwise;
+
+int Endian;
+
+t_CRC Cks_Type;
+unsigned int Cks_Start, Cks_End, Cks_Addr, Cks_Value;
+bool Cks_range_set;
+bool Cks_Addr_set;
+bool Force_Value;
+
+unsigned int Crc_Poly, Crc_Init, Crc_XorOut;
+bool Crc_RefIn;
+bool Crc_RefOut;
+
+void VerifyChecksumValue(void);
+void CrcParamsCheck(void);
+void WriteMemBlock16(uint16_t Value);
+void WriteMemBlock32(uint32_t Value);
+void WriteMemory(void);
+
diff --git a/tools/hex2bin-2.0/src/hex2bin.1 b/tools/hex2bin-2.0/src/hex2bin.1
new file mode 100644
index 0000000..c2e5e89
--- /dev/null
+++ b/tools/hex2bin-2.0/src/hex2bin.1
@@ -0,0 +1,294 @@
+.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings. \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote. \*(C+ will
+.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+. ds -- \(*W-
+. ds PI pi
+. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+. ds L" ""
+. ds R" ""
+. ds C` ""
+. ds C' ""
+'br\}
+.el\{\
+. ds -- \|\(em\|
+. ds PI \(*p
+. ds L" ``
+. ds R" ''
+. ds C`
+. ds C'
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD. Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
+..
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{
+. if \nF \{
+. de IX
+. tm Index:\\$1\t\\n%\t"\\$2"
+..
+. if !\nF==2 \{
+. nr % 0
+. nr F 2
+. \}
+. \}
+.\}
+.rr rF
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear. Run. Save yourself. No user-serviceable parts.
+. \" fudge factors for nroff and troff
+.if n \{\
+. ds #H 0
+. ds #V .8m
+. ds #F .3m
+. ds #[ \f1
+. ds #] \fP
+.\}
+.if t \{\
+. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+. ds #V .6m
+. ds #F 0
+. ds #[ \&
+. ds #] \&
+.\}
+. \" simple accents for nroff and troff
+.if n \{\
+. ds ' \&
+. ds ` \&
+. ds ^ \&
+. ds , \&
+. ds ~ ~
+. ds /
+.\}
+.if t \{\
+. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+. \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+. \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+. \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+. ds : e
+. ds 8 ss
+. ds o a
+. ds d- d\h'-1'\(ga
+. ds D- D\h'-1'\(hy
+. ds th \o'bp'
+. ds Th \o'LP'
+. ds ae ae
+. ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "HEX2BIN 1"
+.TH HEX2BIN 1 "2015-02-28" "perl v5.18.2" "User Contributed Perl Documentation"
+.\" For nroff, turn off justification. Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+hex2bin/mot2bin \e\- converts Intel/Motorola hex files into binary
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+hex2bin [options] file
+.PP
+Option list:
+ [\-c]
+ [\-C Poly Init RefIn RefOut XorOut]
+ [\-e extension]
+ [\-E 0|1]
+ [\-f address]
+ [\-F address value]
+ [\-k checksum type]
+ [\-l length]
+ [\-m minimum block size]
+ [\-p pad byte]
+ [\-r start end]
+ [\-s address]
+ [\-w]
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+\&\fBHex2bin\fR
+is a program that converts an Intel hex format into binary.
+It can handle the extended Intel hex format. Both the segmented
+and linear address records are supported.
+Records need not be sorted and there can be gaps between records.
+Records are assumed to be non-overlapping.
+Padding bytes may be specified and a checksum may be inserted in the
+binary file.
+.PP
+\&\fBMot2bin\fR
+does the same with Motorola hex files. It has the same features and command line
+options. 24 bit and 32 bit records are supported.
+.SH "OPTIONS"
+.IX Header "OPTIONS"
+Options can be specified in any order, with the file name at the end. Options are
+now case sensitive. All option values are specified in hexadecimal.
+.PP
+\&\fB\-c\fR
+.PP
+Enables checksum verification.
+.PP
+By default, it ignores checksum errors in the hex file, so that someone can change
+by hand some bytes with a text editor, allowing quick fixes without recompiling a source
+code all over again. This is useful when tweaking constants directly in the code or
+something similar. If you want checksum error reporting, specify the option \-c.
+.PP
+\&\fBEx.: hex2bin \-c example.hex\fR
+.PP
+If there is a checksum error somewhere, the program will continue the
+conversion anyway.
+.PP
+\&\fB\-C Poly Init RefIn RefOut XorOut\fR
+.PP
+\&\s-1CRC\s0 parameters. See the doc/CRC list.txt file for a description of common CRCs. See also
+the test/Makefile for examples of command lines. Needs \fB\-k\fR and \fB\-f\fR option.
+RefIn and RefOut parameters are specified by \fBt\fR or \fBf\fR for true or false.
+.PP
+\&\fB\-d\fR
+.PP
+Display the list of available check methods and sizes.
+.PP
+\&\fB\-e extension\fR
+.PP
+By default, the output file will have an extension \fBfilename.bin\fR.
+Another extension may be specified with this command:
+.PP
+\&\fBEx.: hex2bin \-e com example.hex\fR
+.PP
+The output file will be example.com
+.PP
+\&\fB\-E 0|1\fR
+.PP
+Endianness for writing the check result or forcing a 16\-bit value.
+ \fB0\fR: little, \fB1\fR: big.
+.PP
+By default, little endian is used.
+.PP
+\&\fB\-f address\fR
+.PP
+Address in hexadecimal for inserting the check value in the binary file. Needs \fB\-k\fR
+option to specify the check method. A range can be specified with option \fB\-r\fR.
+.PP
+\&\fB\-F address value\fR
+.PP
+Address and value of checksum to insert (force) in the binary file. Needs \fB\-k\fR
+option to specify the size. The value is written as is.
+.PP
+\&\fB\-k 0\-4\fR
+.PP
+In many cases, someone needs to insert a check value in the binary file. For example,
+a boot rom is programmed with a checksum which is verified at power-up. This feature
+uses also options \fB\-r\fR, \fB\-C\fR and \fB\-f\fR. Display the list with \fB\-d\fR.
+.PP
+Select the checksum type to insert into the binary file
+ 0: Checksum 8\-bit
+ 1: Checksum 16\-bit
+ 2: \s-1CRC8
+ 3: CRC16
+ 4: CRC32\s0
+.PP
+\&\fB\-l length\fR
+.PP
+The binary file will be padded with \s-1FF\s0 or pad bytes as specified by the option
+below, up to a maximal Length (Starting address + Length \-1 is Max Address)
+.PP
+\&\fB\-m minimum_block_size\fR
+.PP
+File Size Dimension will be a multiple of Minimum block size.
+File will be filled with Pattern.
+Length must be a power of 2 in hexadecimal [see \fB\-l\fR option]
+Attention this option is \s-1STRONGER\s0 than Maximal Length
+.PP
+\&\fB\-p pad_byte\fR
+.PP
+Pads unused locations with the specified byte.
+.PP
+By default, this byte is \s-1FF,\s0 which is the unprogrammed value for most EPROM/EEPROM/Flash.
+.PP
+\&\fBEx.: hex2bin \-p 3E example.hex\fR
+.PP
+\&\fB\-r [start] [end]\fR
+.PP
+Range to compute binary checksum over (default is min and max addresses)
+.PP
+\&\fB\-s address\fR
+.PP
+Specify the starting address of the binary file.
+.PP
+Normally, hex2bin will generate a binary file starting at the lowest address in
+the hex file. If the lowest address isn't 0000, ex: 0100, the first byte that
+should be at 0100 will be stored at address 0000 in the binary file. This may
+cause problems when using the binary file to program an \s-1EPROM.\s0
+.PP
+If you can't specify the starting address (or offset) to your \s-1EPROM\s0 programmer,
+you can specify a starting address on the command line:
+.PP
+\&\fBEx.: hex2bin \-s 0000 records_start_at_0100.hex\fR
+.PP
+The bytes will be stored in the binary file with a padding from 0000 to the
+lowest address (00FF in this case). Padding bytes are all \s-1FF\s0 by default so an \s-1EPROM\s0
+programmer can skip these bytes when programming. The padding value can be changed
+with the \-p option.
+.PP
+\&\fB\-w\fR
+.PP
+Swap wordwise (low <\-> high). Used by Microchip's \s-1MPLAB IDE\s0
+.SH "NOTES"
+.IX Header "NOTES"
+This program does minimal error checking since many hex files are
+generated by known good assemblers.
+.SH "AUTHOR Jacques Pelletier (jpelletier@ieee.org) \- version 2.0"
+.IX Header "AUTHOR Jacques Pelletier (jpelletier@ieee.org) - version 2.0"
diff --git a/tools/hex2bin-2.0/src/hex2bin.c b/tools/hex2bin-2.0/src/hex2bin.c
new file mode 100644
index 0000000..7537d8c
--- /dev/null
+++ b/tools/hex2bin-2.0/src/hex2bin.c
@@ -0,0 +1,587 @@
+/*
+ hex2bin converts an Intel hex file to binary.
+
+ Copyright (C) 2015, Jacques Pelletier
+ checksum extensions Copyright (C) 2004 Rockwell Automation
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ 20040617 Alf Lacis: Added pad byte (may not always want FF).
+ Added 'break;' to remove GNU compiler warning about label at
+ end of compound statement
+ Added PROGRAM & VERSION strings.
+
+ 20071005 PG: Improvements on options parsing
+ 20091212 JP: Corrected crash on 0 byte length data records
+ 20100402 JP: Corrected bug on physical address calculation for extended
+ linear address record.
+ ADDRESS_MASK is now calculated from MEMORY_SIZE
+
+ 20120125 Danny Schneider:
+ Added code for filling a binary file to a given Max_Length relative to
+ Starting Address if Max-Address is larger than Highest-Address
+ 20120509 Yoshimasa Nakane:
+ modified error checking (also for output file, JP)
+ 20141005 JP: added support for byte swapped hex files
+ corrected bug caused by extra LF at end or within file
+ 20141008 JP: removed junk code
+ 20141121 Slucx: added line for removing extra CR when entering file name at run time.
+ 20141122 Simone Fratini: small feature added
+ 20150116 Richard Genoud (Paratronic): correct buffer overflows/wrong results with the -l flag
+ 20150122 JP: added support for different check methods
+ 20150221 JP: rewrite of the checksum write/force value
+*/
+
+#define PROGRAM "hex2bin"
+#define VERSION "2.0"
+
+#include "common.h"
+
+#define NO_ADDRESS_TYPE_SELECTED 0
+#define LINEAR_ADDRESS 1
+#define SEGMENTED_ADDRESS 2
+
+const char *Pgm_Name = PROGRAM;
+
+int main (int argc, char *argv[])
+{
+ /* line inputted from file */
+ char Line[MAX_LINE_SIZE];
+
+ /* flag that a file was read */
+ bool Fileread;
+
+ /* cmd-line parameter # */
+ char *p;
+
+ int Param,result;
+
+ /* Application specific */
+
+ unsigned int Nb_Bytes;
+ unsigned int First_Word, Address, Segment, Upper_Address;
+ unsigned int Phys_Addr, Type;
+ unsigned int temp;
+ unsigned int Records_Start; // Lowest address of the records
+
+ /* We will assume that when one type of addressing is selected, it will be valid for all the
+ current file. Records for the other type will be ignored. */
+ unsigned int Seg_Lin_Select = NO_ADDRESS_TYPE_SELECTED;
+
+ unsigned int temp2;
+
+ byte Data_Str[MAX_LINE_SIZE];
+
+ fprintf (stdout,PROGRAM" v"VERSION", Copyright (C) 2015 Jacques Pelletier & contributors\n\n");
+
+ if (argc == 1)
+ usage();
+
+ strcpy(Extension, "bin"); /* default is for binary file extension */
+
+ /* read file */
+ Starting_Address = 0;
+
+ /*
+ use p for parsing arguments
+ use i for number of parameters to skip
+ use c for the current option
+ */
+ for (Param = 1; Param < argc; Param++)
+ {
+ int i = 0;
+ char c;
+
+ p = argv[Param];
+ c = *(p+1); /* Get option character */
+
+ if ( _IS_OPTION_(*p) )
+ {
+ // test for no space between option and parameter
+ if (strlen(p) != 2) usage();
+
+ switch(c)
+ {
+ /* file extension */
+ case 'c':
+ Enable_Checksum_Error = true;
+ i = 0;
+ break;
+ case 'd':
+ DisplayCheckMethods();
+ case 'e':
+ GetExtension(argv[Param + 1],Extension);
+ i = 1; /* add 1 to Param */
+ break;
+ case 'E':
+ Endian = GetBin(argv[Param + 1]);
+ i = 1; /* add 1 to Param */
+ break;
+ case 'f':
+ Cks_Addr = GetHex(argv[Param + 1]);
+ Cks_Addr_set = true;
+ i = 1; /* add 1 to Param */
+ break;
+ case 'F':
+ Cks_Addr = GetHex(argv[Param + 1]);
+ Cks_Value = GetHex(argv[Param + 2]);
+ Force_Value = true;
+ i = 2; /* add 2 to Param */
+ break;
+ case 'k':
+ Cks_Type = GetHex(argv[Param + 1]);
+ {
+ if (Cks_Type > LAST_CHECK_METHOD) usage();
+ }
+ i = 1; /* add 1 to Param */
+ break;
+ case 'l':
+ Max_Length = GetHex(argv[Param + 1]);
+ if (Max_Length > 0x800000)
+ {
+ fprintf(stderr,"Max_Length = %u\n", Max_Length);
+ exit(1);
+ }
+ Max_Length_Setted = true;
+ i = 1; /* add 1 to Param */
+ break;
+ case 'm':
+ Minimum_Block_Size = GetHex(argv[Param + 1]);
+ Minimum_Block_Size_Setted = true;
+ i = 1; /* add 1 to Param */
+ break;
+ case 'p':
+ Pad_Byte = GetHex(argv[Param + 1]);
+ i = 1; /* add 1 to Param */
+ break;
+ case 'r':
+ Cks_Start = GetHex(argv[Param + 1]);
+ Cks_End = GetHex(argv[Param + 2]);
+ Cks_range_set = true;
+ i = 2; /* add 2 to Param */
+ break;
+ case 's':
+ Starting_Address = GetHex(argv[Param + 1]);
+ Starting_Address_Setted = true;
+ i = 1; /* add 1 to Param */
+ break;
+ case 'w':
+ Swap_Wordwise = true;
+ i = 0;
+ break;
+ case 'C':
+ Crc_Poly = GetHex(argv[Param + 1]);
+ Crc_Init = GetHex(argv[Param + 2]);
+ Crc_RefIn = GetBoolean(argv[Param + 3]);
+ Crc_RefOut = GetBoolean(argv[Param + 4]);
+ Crc_XorOut = GetHex(argv[Param + 5]);
+ CrcParamsCheck();
+ i = 5; /* add 5 to Param */
+ break;
+
+ case '?':
+ case 'h':
+ default:
+ usage();
+ } /* switch */
+
+ /* Last parameter is not a filename */
+ if (Param == argc-1) usage();
+
+ /* if (Param + i) < (argc -1) */
+ if (Param < argc -1 -i) Param += i;
+ else usage();
+
+ }
+ else
+ break;
+ /* if option */
+ } /* for Param */
+
+ /* when user enters input file name */
+
+ /* Assume last parameter is filename */
+ strcpy(Filename,argv[argc -1]);
+
+ /* Just a normal file name */
+ NoFailOpenInputFile (Filename);
+ PutExtension(Filename, Extension);
+ NoFailOpenOutputFile(Filename);
+ Fileread = true;
+
+ /* To begin, assume the lowest address is at the end of the memory.
+ While reading each records, subsequent addresses will lower this number.
+ At the end of the input file, this value will be the lowest address.
+
+ A similar assumption is made for highest address. It starts at the
+ beginning of memory. While reading each records, subsequent addresses will raise this number.
+ At the end of the input file, this value will be the highest address. */
+ Lowest_Address = (unsigned int)-1;
+ Highest_Address = 0;
+ Records_Start = 0;
+ Segment = 0;
+ Upper_Address = 0;
+ Record_Nb = 0; // Used for reporting errors
+
+ /* get highest and lowest addresses so that we can allocate the right size */
+ do
+ {
+ unsigned int i;
+
+ /* Read a line from input file. */
+ GetLine(Line,Filin);
+ Record_Nb++;
+
+ /* Remove carriage return/line feed at the end of line. */
+ i = strlen(Line);
+
+ if (--i != 0)
+ {
+ if (Line[i] == '\n') Line[i] = '\0';
+
+ /* Scan the first two bytes and nb of bytes.
+ The two bytes are read in First_Word since its use depend on the
+ record type: if it's an extended address record or a data record.
+ */
+ result = sscanf (Line, ":%2x%4x%2x%s",&Nb_Bytes,&First_Word,&Type,Data_Str);
+ if (result != 4) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+
+ p = (char *) Data_Str;
+
+ /* If we're reading the last record, ignore it. */
+ switch (Type)
+ {
+ /* Data record */
+ case 0:
+ if (Nb_Bytes == 0)
+ break;
+
+ Address = First_Word;
+
+ if (Seg_Lin_Select == SEGMENTED_ADDRESS)
+ {
+ Phys_Addr = (Segment << 4) + Address;
+ }
+ else
+ {
+ /* LINEAR_ADDRESS or NO_ADDRESS_TYPE_SELECTED
+ Upper_Address = 0 as specified in the Intel spec. until an extended address
+ record is read. */
+ Phys_Addr = ((Upper_Address << 16) + Address);
+ }
+
+ /* Set the lowest address as base pointer. */
+ if (Phys_Addr < Lowest_Address)
+ Lowest_Address = Phys_Addr;
+
+ /* Same for the top address. */
+ temp = Phys_Addr + Nb_Bytes -1;
+
+ if (temp > Highest_Address)
+ Highest_Address = temp;
+
+ break;
+
+ case 2:
+ /* First_Word contains the offset. It's supposed to be 0000 so
+ we ignore it. */
+
+ /* First extended segment address record ? */
+ if (Seg_Lin_Select == NO_ADDRESS_TYPE_SELECTED)
+ Seg_Lin_Select = SEGMENTED_ADDRESS;
+
+ /* Then ignore subsequent extended linear address records */
+ if (Seg_Lin_Select == SEGMENTED_ADDRESS)
+ {
+ result = sscanf (p, "%4x%2x",&Segment,&temp2);
+ if (result != 2) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+
+ /* Update the current address. */
+ Phys_Addr = (Segment << 4);
+ }
+ else
+ {
+ fprintf(stderr,"Ignored extended linear address record %d\n", Record_Nb);
+ }
+ break;
+
+ case 4:
+ /* First_Word contains the offset. It's supposed to be 0000 so
+ we ignore it. */
+
+ /* First extended linear address record ? */
+ if (Seg_Lin_Select == NO_ADDRESS_TYPE_SELECTED)
+ Seg_Lin_Select = LINEAR_ADDRESS;
+
+ /* Then ignore subsequent extended segment address records */
+ if (Seg_Lin_Select == LINEAR_ADDRESS)
+ {
+ result = sscanf (p, "%4x%2x",&Upper_Address,&temp2);
+ if (result != 2) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+
+ /* Update the current address. */
+ Phys_Addr = (Upper_Address << 16);
+ }
+ else
+ {
+ fprintf(stderr,"Ignored extended segment address record %d\n", Record_Nb);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ while (!feof (Filin));
+
+ rewind(Filin);
+ Segment = 0;
+ Upper_Address = 0;
+ Record_Nb = 0;
+
+ if (Starting_Address_Setted == true)
+ {
+ Records_Start = Lowest_Address;
+ Lowest_Address = Starting_Address;
+ }
+ else
+ {
+ Records_Start = Lowest_Address;
+ Starting_Address = Lowest_Address;
+ }
+
+ if (Max_Length_Setted == false)
+ Max_Length = Highest_Address - Lowest_Address + 1;
+ else
+ Highest_Address = Lowest_Address + Max_Length - 1;
+
+ /* Now, that we know the buffer size, we can allocate it. */
+ /* allocate a buffer */
+ Memory_Block = (byte *) NoFailMalloc(Max_Length);
+
+ /* For EPROM or FLASH memory types, fill unused bytes with FF or the value specified by the p option */
+ memset (Memory_Block,Pad_Byte,Max_Length);
+
+ /* Read the file & process the lines. */
+ do /* repeat until EOF(Filin) */
+ {
+ unsigned int i;
+
+ /* Read a line from input file. */
+ GetLine(Line,Filin);
+ Record_Nb++;
+
+ /* Remove carriage return/line feed at the end of line. */
+ i = strlen(Line);
+
+ //fprintf(stderr,"Record: %d; length: %d\n", Record_Nb, i);
+
+ if (--i != 0)
+ {
+ if (Line[i] == '\n') Line[i] = '\0';
+
+ /* Scan the first two bytes and nb of bytes.
+ The two bytes are read in First_Word since its use depend on the
+ record type: if it's an extended address record or a data record.
+ */
+ result = sscanf (Line, ":%2x%4x%2x%s",&Nb_Bytes,&First_Word,&Type,Data_Str);
+ if (result != 4) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+
+ Checksum = Nb_Bytes + (First_Word >> 8) + (First_Word & 0xFF) + Type;
+
+ p = (char *) Data_Str;
+
+ /* If we're reading the last record, ignore it. */
+ switch (Type)
+ {
+ /* Data record */
+ case 0:
+ if (Nb_Bytes == 0)
+ {
+ fprintf(stderr,"0 byte length Data record ignored\n");
+ break;
+ }
+
+ Address = First_Word;
+
+ if (Seg_Lin_Select == SEGMENTED_ADDRESS)
+ Phys_Addr = (Segment << 4) + Address;
+ else
+ /* LINEAR_ADDRESS or NO_ADDRESS_TYPE_SELECTED
+ Upper_Address = 0 as specified in the Intel spec. until an extended address
+ record is read. */
+ Phys_Addr = ((Upper_Address << 16) + Address);
+
+ /* Check that the physical address stays in the buffer's range. */
+ if ((Phys_Addr >= Lowest_Address) && (Phys_Addr <= Highest_Address))
+ {
+ /* The memory block begins at Lowest_Address */
+ Phys_Addr -= Lowest_Address;
+
+ /* Read the Data bytes. */
+ /* Bytes are written in the Memory block even if checksum is wrong. */
+ i = Nb_Bytes;
+
+ do
+ {
+ result = sscanf (p, "%2x",&temp2);
+ if (result != 1) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+ p += 2;
+
+ /* Check that the physical address stays in the buffer's range. */
+ if (Phys_Addr < Max_Length)
+ {
+ /* Overlapping record will erase the pad bytes */
+ if (Swap_Wordwise)
+ {
+ if (Memory_Block[Phys_Addr ^ 1] != Pad_Byte) fprintf(stderr,"Overlapped record detected\n");
+ Memory_Block[Phys_Addr++ ^ 1] = temp2;
+ }
+ else
+ {
+ if (Memory_Block[Phys_Addr] != Pad_Byte) fprintf(stderr,"Overlapped record detected\n");
+ Memory_Block[Phys_Addr++] = temp2;
+ }
+
+ Checksum = (Checksum + temp2) & 0xFF;
+ }
+ }
+ while (--i != 0);
+
+ /* Read the Checksum value. */
+ result = sscanf (p, "%2x",&temp2);
+ if (result != 1) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+
+ /* Verify Checksum value. */
+ Checksum = (Checksum + temp2) & 0xFF;
+ VerifyChecksumValue();
+ }
+ else
+ {
+ if (Seg_Lin_Select == SEGMENTED_ADDRESS)
+ fprintf(stderr,"Data record skipped at %4X:%4X\n",Segment,Address);
+ else
+ fprintf(stderr,"Data record skipped at %8X\n",Phys_Addr);
+ }
+
+ break;
+
+ /* End of file record */
+ case 1:
+ /* Simply ignore checksum errors in this line. */
+ break;
+
+ /* Extended segment address record */
+ case 2:
+ /* First_Word contains the offset. It's supposed to be 0000 so
+ we ignore it. */
+
+ /* First extended segment address record ? */
+ if (Seg_Lin_Select == NO_ADDRESS_TYPE_SELECTED)
+ Seg_Lin_Select = SEGMENTED_ADDRESS;
+
+ /* Then ignore subsequent extended linear address records */
+ if (Seg_Lin_Select == SEGMENTED_ADDRESS)
+ {
+ result = sscanf (p, "%4x%2x",&Segment,&temp2);
+ if (result != 2) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+
+ /* Update the current address. */
+ Phys_Addr = (Segment << 4);
+
+ /* Verify Checksum value. */
+ Checksum = (Checksum + (Segment >> 8) + (Segment & 0xFF) + temp2) & 0xFF;
+ VerifyChecksumValue();
+ }
+ break;
+
+ /* Start segment address record */
+ case 3:
+ /* Nothing to be done since it's for specifying the starting address for
+ execution of the binary code */
+ break;
+
+ /* Extended linear address record */
+ case 4:
+ /* First_Word contains the offset. It's supposed to be 0000 so
+ we ignore it. */
+
+ /* First extended linear address record ? */
+ if (Seg_Lin_Select == NO_ADDRESS_TYPE_SELECTED)
+ Seg_Lin_Select = LINEAR_ADDRESS;
+
+ /* Then ignore subsequent extended segment address records */
+ if (Seg_Lin_Select == LINEAR_ADDRESS)
+ {
+ result = sscanf (p, "%4x%2x",&Upper_Address,&temp2);
+ if (result != 2) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+
+ /* Update the current address. */
+ Phys_Addr = (Upper_Address << 16);
+
+ /* Verify Checksum value. */
+ Checksum = (Checksum + (Upper_Address >> 8) + (Upper_Address & 0xFF) + temp2)
+ & 0xFF;
+ VerifyChecksumValue();
+ }
+ break;
+
+ /* Start linear address record */
+ case 5:
+ /* Nothing to be done since it's for specifying the starting address for
+ execution of the binary code */
+ break;
+ default:
+ fprintf(stderr,"Unknown record type\n");
+ break;
+ }
+ }
+ }
+ while (!feof (Filin));
+ /*-----------------------------------------------------------------------------*/
+
+ fprintf(stdout,"Binary file start = %08X\n",Lowest_Address);
+ fprintf(stdout,"Records start = %08X\n",Records_Start);
+ fprintf(stdout,"Highest address = %08X\n",Highest_Address);
+ fprintf(stdout,"Pad Byte = %X\n", Pad_Byte);
+
+ WriteMemory();
+
+#ifdef USE_FILE_BUFFERS
+ free (FilinBuf);
+ free (FiloutBuf);
+#endif
+
+ fclose (Filin);
+ fclose (Filout);
+
+ if (Status_Checksum_Error && Enable_Checksum_Error)
+ {
+ fprintf(stderr,"Checksum error detected.\n");
+ return 1;
+ }
+
+ if (!Fileread)
+ usage();
+ return 0;
+}
diff --git a/tools/hex2bin-2.0/src/hex2bin.pod b/tools/hex2bin-2.0/src/hex2bin.pod
new file mode 100644
index 0000000..a8eb238
--- /dev/null
+++ b/tools/hex2bin-2.0/src/hex2bin.pod
@@ -0,0 +1,161 @@
+HEX2BIN 1 "2015 february 22nd" "Hex2bin Version 2.0"
+=head1 NAME
+
+hex2bin/mot2bin \- converts Intel/Motorola hex files into binary
+
+=head1 SYNOPSIS
+
+hex2bin [options] file
+
+Option list:
+ [-c]
+ [-C Poly Init RefIn RefOut XorOut]
+ [-e extension]
+ [-E 0|1]
+ [-f address]
+ [-F address value]
+ [-k checksum type]
+ [-l length]
+ [-m minimum block size]
+ [-p pad byte]
+ [-r start end]
+ [-s address]
+ [-w]
+
+=head1 DESCRIPTION
+
+B<Hex2bin>
+is a program that converts an Intel hex format into binary.
+It can handle the extended Intel hex format. Both the segmented
+and linear address records are supported.
+Records need not be sorted and there can be gaps between records.
+Records are assumed to be non-overlapping.
+Padding bytes may be specified and a checksum may be inserted in the
+binary file.
+
+B<Mot2bin>
+does the same with Motorola hex files. It has the same features and command line
+options. 24 bit and 32 bit records are supported.
+
+=head1 OPTIONS
+
+Options can be specified in any order, with the file name at the end. Options are
+now case sensitive. All option values are specified in hexadecimal.
+
+B<-c>
+
+Enables checksum verification.
+
+By default, it ignores checksum errors in the hex file, so that someone can change
+by hand some bytes with a text editor, allowing quick fixes without recompiling a source
+code all over again. This is useful when tweaking constants directly in the code or
+something similar. If you want checksum error reporting, specify the option -c.
+
+B<Ex.: hex2bin -c example.hex>
+
+If there is a checksum error somewhere, the program will continue the
+conversion anyway.
+
+B<-C Poly Init RefIn RefOut XorOut>
+
+CRC parameters. See the doc/CRC list.txt file for a description of common CRCs. See also
+the test/Makefile for examples of command lines. Needs B<-k> and B<-f> option.
+RefIn and RefOut parameters are specified by B<t> or B<f> for true or false.
+
+B<-d>
+
+Display the list of available check methods and sizes.
+
+B<-e extension>
+
+By default, the output file will have an extension B<filename.bin>.
+Another extension may be specified with this command:
+
+B<Ex.: hex2bin -e com example.hex>
+
+The output file will be example.com
+
+B<-E 0|1>
+
+Endianness for writing the check result or forcing a 16-bit value.
+ B<0>: little, B<1>: big.
+
+By default, little endian is used.
+
+B<-f address>
+
+Address in hexadecimal for inserting the check value in the binary file. Needs B<-k>
+option to specify the check method. A range can be specified with option B<-r>.
+
+B<-F address value>
+
+Address and value of checksum to insert (force) in the binary file. Needs B<-k>
+option to specify the size. The value is written as is.
+
+B<-k 0-4>
+
+In many cases, someone needs to insert a check value in the binary file. For example,
+a boot rom is programmed with a checksum which is verified at power-up. This feature
+uses also options B<-r>, B<-C> and B<-f>. Display the list with B<-d>.
+
+Select the checksum type to insert into the binary file
+ 0: Checksum 8-bit
+ 1: Checksum 16-bit
+ 2: CRC8
+ 3: CRC16
+ 4: CRC32
+
+B<-l length>
+
+The binary file will be padded with FF or pad bytes as specified by the option
+below, up to a maximal Length (Starting address + Length -1 is Max Address)
+
+B<-m minimum_block_size>
+
+File Size Dimension will be a multiple of Minimum block size.
+File will be filled with Pattern.
+Length must be a power of 2 in hexadecimal [see B<-l> option]
+Attention this option is STRONGER than Maximal Length
+
+B<-p pad_byte>
+
+Pads unused locations with the specified byte.
+
+By default, this byte is FF, which is the unprogrammed value for most EPROM/EEPROM/Flash.
+
+B<Ex.: hex2bin -p 3E example.hex>
+
+B<-r [start] [end]>
+
+Range to compute binary checksum over (default is min and max addresses)
+
+B<-s address>
+
+Specify the starting address of the binary file.
+
+Normally, hex2bin will generate a binary file starting at the lowest address in
+the hex file. If the lowest address isn't 0000, ex: 0100, the first byte that
+should be at 0100 will be stored at address 0000 in the binary file. This may
+cause problems when using the binary file to program an EPROM.
+
+If you can't specify the starting address (or offset) to your EPROM programmer,
+you can specify a starting address on the command line:
+
+B<Ex.: hex2bin -s 0000 records_start_at_0100.hex>
+
+The bytes will be stored in the binary file with a padding from 0000 to the
+lowest address (00FF in this case). Padding bytes are all FF by default so an EPROM
+programmer can skip these bytes when programming. The padding value can be changed
+with the -p option.
+
+B<-w>
+
+Swap wordwise (low <-> high). Used by Microchip's MPLAB IDE
+
+=head1 NOTES
+
+This program does minimal error checking since many hex files are
+generated by known good assemblers.
+
+=head1 AUTHOR
+Jacques Pelletier (jpelletier@ieee.org) - version 2.0
diff --git a/tools/hex2bin-2.0/src/libcrc.c b/tools/hex2bin-2.0/src/libcrc.c
new file mode 100644
index 0000000..02bcd4b
--- /dev/null
+++ b/tools/hex2bin-2.0/src/libcrc.c
@@ -0,0 +1,204 @@
+/*********************************************************************
+ * *
+ * Library : lib_crc *
+ * File : lib_crc.c *
+ * Author : Lammert Bies 1999-2008 *
+ * E-mail : info@lammertbies.nl *
+ * Language : ANSI C *
+ * *
+ * *
+ * Description *
+ * =========== *
+ * *
+ * The file lib_crc.c contains the private and public func- *
+ * tions used for the calculation of CRC-16, CRC-CCITT and *
+ * CRC-32 cyclic redundancy values. *
+ * *
+ * *
+ * Dependencies *
+ * ============ *
+ * *
+ * libcrc.h CRC definitions and prototypes *
+ * *
+ ********************************************************************/
+#include <stdint.h>
+
+#ifndef G_GUINT64_CONSTANT
+#define G_GUINT64_CONSTANT(val) (val##UL)
+#endif
+
+void *crc_table;
+
+/* private */
+
+void init_crc8_normal_tab(uint8_t polynom)
+{
+ int i, j;
+ uint8_t crc;
+ uint8_t *p;
+
+ p = (uint8_t *) crc_table;
+
+ for (i=0; i<256; i++)
+ {
+ crc = (uint8_t) i;
+
+ for (j=0; j<8; j++)
+ {
+ if (crc & 0x80) crc = (crc << 1) ^ polynom;
+ else crc <<= 1;
+ }
+ *p++ = crc;
+ }
+}
+
+void init_crc8_reflected_tab(uint8_t polynom)
+{
+ int i, j;
+ uint8_t crc;
+ uint8_t *p;
+
+ p = (uint8_t *) crc_table;
+
+ for (i=0; i<256; i++)
+ {
+ crc = (uint8_t) i;
+
+ for (j=0; j<8; j++)
+ {
+ if (crc & 0x01) crc = (crc >> 1) ^ polynom;
+ else crc >>= 1;
+ }
+ *p++ = crc;
+ }
+}
+
+/* Common routines for calculations */
+void init_crc16_normal_tab(uint16_t polynom)
+{
+ int i, j;
+ uint16_t crc;
+ uint16_t *p;
+
+ p = (uint16_t *) crc_table;
+
+ for (i=0; i<256; i++)
+ {
+ crc = ((uint16_t) i) << 8;
+
+ for (j=0; j<8; j++)
+ {
+ if ( crc & 0x8000 ) crc = ( crc << 1 ) ^ polynom;
+ else crc <<= 1;
+ }
+ *p++ = crc;
+ }
+}
+
+void init_crc16_reflected_tab(uint16_t polynom)
+{
+ int i, j;
+ uint16_t crc;
+ uint16_t *p;
+
+ p = (uint16_t *) crc_table;
+
+ for (i=0; i<256; i++)
+ {
+ crc = (uint16_t) i;
+
+ for (j=0; j<8; j++)
+ {
+ if ( crc & 0x0001 ) crc = ( crc >> 1 ) ^ polynom;
+ else crc >>= 1;
+ }
+ *p++ = crc;
+ }
+}
+
+void init_crc32_normal_tab(uint32_t polynom)
+{
+ int i, j;
+ uint32_t crc;
+ uint32_t *p;
+
+ p = (uint32_t *) crc_table;
+
+ for (i=0; i<256; i++)
+ {
+ crc = ((uint32_t) i) << 24;
+
+ for (j=0; j<8; j++)
+ {
+ if ( crc & 0x80000000L ) crc = ( crc << 1 ) ^ polynom;
+ else crc <<= 1;
+ }
+ *p++ = crc;
+ }
+}
+
+void init_crc32_reflected_tab(uint32_t polynom)
+{
+ int i, j;
+ uint32_t crc;
+ uint32_t *p;
+
+ p = (uint32_t *) crc_table;
+
+ for (i=0; i<256; i++)
+ {
+ crc = (uint32_t) i;
+
+ for (j=0; j<8; j++)
+ {
+ if ( crc & 0x00000001L ) crc = ( crc >> 1 ) ^ polynom;
+ else crc >>= 1;
+ }
+ *p++ = crc;
+ }
+}
+
+/* Common routines for calculations */
+
+uint8_t update_crc8(uint8_t crc, uint8_t c)
+{
+ return (((uint8_t *) crc_table)[crc ^ c]);
+}
+
+uint16_t update_crc16_normal(uint16_t crc, char c )
+{
+ uint16_t short_c;
+
+ short_c = 0x00ff & (uint16_t) c;
+
+ /* Normal form */
+ return (crc << 8) ^ ((uint16_t *) crc_table)[(crc >> 8) ^ short_c];
+}
+
+uint16_t update_crc16_reflected(uint16_t crc, char c )
+{
+ uint16_t short_c;
+
+ short_c = 0x00ff & (uint16_t) c;
+
+ /* Reflected form */
+ return (crc >> 8) ^ ((uint16_t *) crc_table)[(crc ^ short_c) & 0xff];
+}
+
+uint32_t update_crc32_normal(uint32_t crc, char c )
+{
+ uint32_t long_c;
+
+ long_c = 0x000000ffL & (uint32_t) c;
+
+ return (crc << 8) ^ ((uint32_t *) crc_table)[((crc >> 24) ^ long_c) & 0xff];
+}
+
+uint32_t update_crc32_reflected(uint32_t crc, char c )
+{
+ uint32_t long_c;
+
+ long_c = 0x000000ffL & (uint32_t) c;
+
+ return (crc >> 8) ^ ((uint32_t *) crc_table)[(crc ^ long_c) & 0xff];
+}
diff --git a/tools/hex2bin-2.0/src/libcrc.h b/tools/hex2bin-2.0/src/libcrc.h
new file mode 100644
index 0000000..39f20d0
--- /dev/null
+++ b/tools/hex2bin-2.0/src/libcrc.h
@@ -0,0 +1,44 @@
+ /********************************************************************
+ * *
+ * Library : lib_crc *
+ * File : lib_crc.h *
+ * Author : Lammert Bies 1999-2008 *
+ * E-mail : info@lammertbies.nl *
+ * Language : ANSI C *
+ * *
+ * *
+ * Description *
+ * =========== *
+ * *
+ * The file lib_crc.h contains public definitions and proto- *
+ * types for the CRC functions present in lib_crc.c. *
+ * *
+ * *
+ * Dependencies *
+ * ============ *
+ * *
+ * none *
+ * *
+ * *
+ ********************************************************************/
+#ifndef _LIBCRC_H_
+#define _LIBCRC_H_
+
+void *crc_table;
+
+void init_crc8_normal_tab(uint8_t polynom);
+void init_crc8_reflected_tab(uint8_t polynom);
+
+void init_crc16_normal_tab(uint16_t polynom);
+void init_crc16_reflected_tab(uint16_t polynom);
+void init_crc32_normal_tab(uint32_t polynom);
+void init_crc32_reflected_tab(uint32_t polynom);
+
+uint8_t update_crc8(uint8_t crc, uint8_t c);
+
+uint16_t update_crc16_normal(uint16_t crc, char c );
+uint16_t update_crc16_reflected(uint16_t crc, char c );
+uint32_t update_crc32_normal(uint32_t crc, char c );
+uint32_t update_crc32_reflected(uint32_t crc, char c );
+
+#endif /* _LIBCRC_H_ */
diff --git a/tools/hex2bin-2.0/src/mot2bin.c b/tools/hex2bin-2.0/src/mot2bin.c
new file mode 100644
index 0000000..9e0e23c
--- /dev/null
+++ b/tools/hex2bin-2.0/src/mot2bin.c
@@ -0,0 +1,518 @@
+/*
+mot2bin converts a Motorola hex file to binary.
+
+Copyright (C) 2015, Jacques Pelletier
+checksum extensions Copyright (C) 2004 Rockwell Automation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+20040617 Alf Lacis: Added pad byte (may not always want FF).
+ Added initialisation to Checksum to remove GNU
+ compiler warning about possible uninitialised usage
+ Added 2x'break;' to remove GNU compiler warning about label at
+ end of compound statement
+ Added PROGRAM & VERSION strings.
+
+20071005 PG: Improvements on options parsing
+20091212 JP: Corrected crash on 0 byte length data records
+20100402 JP: ADDRESS_MASK is now calculated from MEMORY_SIZE
+
+20120125 Danny Schneider:
+ Added code for filling a binary file to a given Max_Length relative to
+ Starting Address if Max-Address is larger than Highest-Address
+20120509 Yoshimasa Nakane:
+ modified error checking (also for output file, JP)
+20141005 JP: added support for byte swapped hex files
+ corrected bug caused by extra LF at end or within file
+20141121 Slucx: added line for removing extra CR when entering file name at run time.
+20150116 Richard Genoud (Paratronic): correct buffer overflows/wrong results with the -l flag
+20150122 JP: added support for different check methods
+20150221 JP: rewrite of the checksum write/force value
+*/
+
+#define PROGRAM "mot2bin"
+#define VERSION "2.0"
+
+#include "common.h"
+
+const char *Pgm_Name = PROGRAM;
+
+int main (int argc, char *argv[])
+{
+ /* line inputted from file */
+ char Line[MAX_LINE_SIZE];
+
+ /* flag that a file was read */
+ bool Fileread;
+
+ /* cmd-line parameter # */
+ char *p;
+
+ int Param, result;
+
+ /* Application specific */
+
+ unsigned int Nb_Bytes;
+ unsigned int First_Word, Address;
+
+ unsigned int Phys_Addr, Type;
+ unsigned int Exec_Address;
+ unsigned int temp;
+ unsigned int Record_Count, Record_Checksum;
+ unsigned int Records_Start; // Lowest address of the records
+
+ unsigned int temp2;
+
+ byte Data_Str[MAX_LINE_SIZE];
+
+ fprintf (stdout,PROGRAM" v"VERSION", Copyright (C) 2015 Jacques Pelletier & contributors\n\n");
+
+ if (argc == 1)
+ usage();
+
+ strcpy(Extension, "bin"); /* default is for binary file extension */
+
+ /* read file */
+ Starting_Address = 0;
+
+ /*
+ use p for parsing arguments
+ use i for number of parameters to skip
+ use c for the current option
+ */
+ for (Param = 1; Param < argc; Param++)
+ {
+ int i = 0;
+ char c;
+
+ p = argv[Param];
+ c = *(p+1); /* Get option character */
+
+ if ( _IS_OPTION_(*p) )
+ {
+ // test for no space between option and parameter
+ if (strlen(p) != 2) usage();
+
+ switch(c)
+ {
+ /* file extension */
+ case 'c':
+ Enable_Checksum_Error = true;
+ i = 0;
+ break;
+ case 'd':
+ DisplayCheckMethods();
+ case 'e':
+ GetExtension(argv[Param + 1],Extension);
+ i = 1; /* add 1 to Param */
+ break;
+ case 'f':
+ Cks_Addr = GetHex(argv[Param + 1]);
+ Cks_Addr_set = true;
+ i = 1; /* add 1 to Param */
+ break;
+ case 'F':
+ Cks_Addr = GetHex(argv[Param + 1]);
+ Cks_Value = GetHex(argv[Param + 2]);
+ Force_Value = true;
+ i = 2; /* add 2 to Param */
+ break;
+ case 'k':
+ Cks_Type = GetHex(argv[Param + 1]);
+ {
+ if (Cks_Type > LAST_CHECK_METHOD) usage();
+ }
+ i = 1; /* add 1 to Param */
+ break;
+ case 'l':
+ Max_Length = GetHex(argv[Param + 1]);
+ Max_Length_Setted = true;
+ i = 1; /* add 1 to Param */
+ break;
+ case 'm':
+ Minimum_Block_Size = GetHex(argv[Param + 1]);
+ Minimum_Block_Size_Setted = true;
+ i = 1; /* add 1 to Param */
+ break;
+ case 'p':
+ Pad_Byte = GetHex(argv[Param + 1]);
+ i = 1; /* add 1 to Param */
+ break;
+ case 'r':
+ Cks_Start = GetHex(argv[Param + 1]);
+ Cks_End = GetHex(argv[Param + 2]);
+ Cks_range_set = true;
+ i = 2; /* add 2 to Param */
+ break;
+ case 's':
+ Starting_Address = GetHex(argv[Param + 1]);
+ Starting_Address_Setted = true;
+ i = 1; /* add 1 to Param */
+ break;
+ case 'w':
+ Swap_Wordwise = true;
+ i = 0;
+ break;
+ case 'C':
+ Crc_Poly = GetHex(argv[Param + 1]);
+ Crc_Init = GetHex(argv[Param + 2]);
+ Crc_RefIn = GetBoolean(argv[Param + 3]);
+ Crc_RefOut = GetBoolean(argv[Param + 4]);
+ Crc_XorOut = GetHex(argv[Param + 5]);
+ CrcParamsCheck();
+ i = 5; /* add 5 to Param */
+ break;
+
+ case '?':
+ case 'h':
+ default:
+ usage();
+ } /* switch */
+
+ /* Last parameter is not a filename */
+ if (Param == argc-1) usage();
+
+ // fprintf(stderr,"Param: %d, option: %c\n",Param,c);
+
+ /* if (Param + i) < (argc -1) */
+ if (Param < argc -1 -i) Param += i;
+ else usage();
+
+ }
+ else
+ break;
+ /* if option */
+ } /* for Param */
+
+ /* when user enters input file name */
+
+ /* Assume last parameter is filename */
+ strcpy(Filename,argv[argc -1]);
+
+ /* Just a normal file name */
+ NoFailOpenInputFile (Filename);
+ PutExtension(Filename, Extension);
+ NoFailOpenOutputFile(Filename);
+ Fileread = true;
+
+ /* To begin, assume the lowest address is at the end of the memory.
+ While reading each records, subsequent addresses will lower this number.
+ At the end of the input file, this value will be the lowest address.
+
+ A similar assumption is made for highest address. It starts at the
+ beginning of memory. While reading each records, subsequent addresses will raise this number.
+ At the end of the input file, this value will be the highest address. */
+ Lowest_Address = (unsigned int)-1;
+ Highest_Address = 0;
+ Records_Start = 0;
+ Record_Nb = 0;
+
+ /* get highest and lowest addresses so that we can allocate the right size */
+ do
+ {
+ unsigned int i;
+
+ /* Read a line from input file. */
+ GetLine(Line,Filin);
+ Record_Nb++;
+
+ /* Remove carriage return/line feed at the end of line. */
+ i = strlen(Line);
+
+ if (--i != 0)
+ {
+ if (Line[i] == '\n') Line[i] = '\0';
+
+ p = (char *) Data_Str;
+
+ switch(Line[1])
+ {
+ case '0':
+ break;
+
+ /* 16 bits address */
+ case '1':
+ result = sscanf (Line,"S%1x%2x%4x",&Type,&Nb_Bytes,&First_Word);
+ if (result != 3) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+
+ /* Adjust Nb_Bytes for the number of data bytes */
+ Nb_Bytes = Nb_Bytes - 3;
+ break;
+
+ /* 24 bits address */
+ case '2':
+ result = sscanf (Line,"S%1x%2x%6x",&Type,&Nb_Bytes,&First_Word);
+ if (result != 3) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+
+ /* Adjust Nb_Bytes for the number of data bytes */
+ Nb_Bytes = Nb_Bytes - 4;
+ break;
+
+ /* 32 bits address */
+ case '3':
+ result = sscanf (Line,"S%1x%2x%8x",&Type,&Nb_Bytes,&First_Word);
+ if (result != 3) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+
+ /* Adjust Nb_Bytes for the number of data bytes */
+ Nb_Bytes = Nb_Bytes - 5;
+ break;
+ }
+
+ Phys_Addr = First_Word;
+
+ /* Set the lowest address as base pointer. */
+ if (Phys_Addr < Lowest_Address)
+ Lowest_Address = Phys_Addr;
+
+ /* Same for the top address. */
+ temp = Phys_Addr + Nb_Bytes -1;
+
+ if (temp > Highest_Address)
+ Highest_Address = temp;
+ }
+ }
+ while (!feof (Filin));
+
+ if (Starting_Address_Setted == true)
+ {
+ Records_Start = Lowest_Address;
+ Lowest_Address = Starting_Address;
+ }
+ else
+ {
+ Records_Start = Lowest_Address;
+ Starting_Address = Lowest_Address;
+ }
+
+ if (Max_Length_Setted == false)
+ Max_Length = Highest_Address - Lowest_Address + 1;
+ else
+ Highest_Address = Lowest_Address + Max_Length - 1;
+
+ /* Now, that we know the buffer size, we can allocate it. */
+ /* allocate a buffer */
+ Memory_Block = (byte *) NoFailMalloc(Max_Length);
+
+ /* For EPROM or FLASH memory types, fill unused bytes with FF or the value specified by the p option */
+ memset (Memory_Block,Pad_Byte,Max_Length);
+
+ rewind(Filin);
+ Record_Nb = 0;
+
+ /* Read the file & process the lines. */
+ do /* repeat until EOF(Filin) */
+ {
+ int i;
+
+ Checksum = 0;
+
+ /* Read a line from input file. */
+ GetLine(Line,Filin);
+ Record_Nb++;
+
+ /* Remove carriage return/line feed at the end of line. */
+ i = strlen(Line);
+
+ if (--i != 0)
+ {
+ if (Line[i] == '\n') Line[i] = '\0';
+
+ /* Scan starting address and nb of bytes. */
+ /* Look at the record type after the 'S' */
+ Type = 0;
+
+ switch(Line[1])
+ {
+ case '0':
+ result = sscanf (Line,"S0%2x0000484452%2x",&Nb_Bytes,&Record_Checksum);
+ if (result != 2) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+ Checksum = Nb_Bytes + 0x48 + 0x44 + 0x52;
+
+ /* Adjust Nb_Bytes for the number of data bytes */
+ Nb_Bytes = 0;
+ break;
+
+ /* 16 bits address */
+ case '1':
+ result = sscanf (Line,"S%1x%2x%4x%s",&Type,&Nb_Bytes,&Address,Data_Str);
+ if (result != 4) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+ Checksum = Nb_Bytes + (Address >> 8) + (Address & 0xFF);
+
+ /* Adjust Nb_Bytes for the number of data bytes */
+ Nb_Bytes = Nb_Bytes - 3;
+ break;
+
+ /* 24 bits address */
+ case '2':
+ result = sscanf (Line,"S%1x%2x%6x%s",&Type,&Nb_Bytes,&Address,Data_Str);
+ if (result != 4) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+ Checksum = Nb_Bytes + (Address >> 16) + (Address >> 8) + (Address & 0xFF);
+
+ /* Adjust Nb_Bytes for the number of data bytes */
+ Nb_Bytes = Nb_Bytes - 4;
+ break;
+
+ /* 32 bits address */
+ case '3':
+ result = sscanf (Line,"S%1x%2x%8x%s",&Type,&Nb_Bytes,&Address,Data_Str);
+ if (result != 4) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+ Checksum = Nb_Bytes + (Address >> 24) + (Address >> 16) + (Address >> 8) + (Address & 0xFF);
+
+ /* Adjust Nb_Bytes for the number of data bytes */
+ Nb_Bytes = Nb_Bytes - 5;
+ break;
+
+ case '5':
+ result = sscanf (Line,"S%1x%2x%4x%2x",&Type,&Nb_Bytes,&Record_Count,&Record_Checksum);
+ if (result != 4) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+ Checksum = Nb_Bytes + (Record_Count >> 8) + (Record_Count & 0xFF);
+
+ /* Adjust Nb_Bytes for the number of data bytes */
+ Nb_Bytes = 0;
+ break;
+
+ case '7':
+ result = sscanf (Line,"S%1x%2x%8x%2x",&Type,&Nb_Bytes,&Exec_Address,&Record_Checksum);
+ if (result != 4) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+ Checksum = Nb_Bytes + (Exec_Address >> 24) + (Exec_Address >> 16) + (Exec_Address >> 8) + (Exec_Address & 0xFF);
+ Nb_Bytes = 0;
+ break;
+
+ case '8':
+ result = sscanf (Line,"S%1x%2x%6x%2x",&Type,&Nb_Bytes,&Exec_Address,&Record_Checksum);
+ if (result != 4) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+ Checksum = Nb_Bytes + (Exec_Address >> 16) + (Exec_Address >> 8) + (Exec_Address & 0xFF);
+ Nb_Bytes = 0;
+ break;
+ case '9':
+ result = sscanf (Line,"S%1x%2x%4x%2x",&Type,&Nb_Bytes,&Exec_Address,&Record_Checksum);
+ if (result != 4) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+ Checksum = Nb_Bytes + (Exec_Address >> 8) + (Exec_Address & 0xFF);
+ Nb_Bytes = 0;
+ break;
+ }
+
+ p = (char *) Data_Str;
+
+ /* If we're reading the last record, ignore it. */
+ switch (Type)
+ {
+ /* Data record */
+ case 1:
+ case 2:
+ case 3:
+ if (Nb_Bytes == 0)
+ {
+ fprintf(stderr,"0 byte length Data record ignored\n");
+ break;
+ }
+
+ Phys_Addr = Address;
+
+ /* Read the Data bytes. */
+ i = Nb_Bytes;
+
+ do
+ {
+ result = sscanf (p, "%2x",&temp2);
+ if (result != 1) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+ p += 2;
+
+ /* Overlapping record will erase the pad bytes */
+ if (Swap_Wordwise)
+ {
+ if (Memory_Block[Phys_Addr ^ 1] != Pad_Byte) fprintf(stderr,"Overlapped record detected\n");
+ Memory_Block[Phys_Addr++ ^ 1] = temp2;
+ }
+ else
+ {
+ if (Memory_Block[Phys_Addr] != Pad_Byte) fprintf(stderr,"Overlapped record detected\n");
+ Memory_Block[Phys_Addr++] = temp2;
+ }
+
+ Checksum = (Checksum + temp2) & 0xFF;
+ }
+ while (--i != 0);
+
+ /* Read the Checksum value. */
+ result = sscanf (p, "%2x",&Record_Checksum);
+ if (result != 1) fprintf(stderr,"Error in line %d of hex file\n", Record_Nb);
+ break;
+
+ case 5:
+ fprintf(stderr,"Record total: %d\n",Record_Count);
+ break;
+
+ case 7:
+ fprintf(stderr,"Execution Address (unused): %08X\n",Exec_Address);
+ break;
+
+ case 8:
+ fprintf(stderr,"Execution Address (unused): %06X\n",Exec_Address);
+ break;
+
+ case 9:
+ fprintf(stderr,"Execution Address (unused): %04X\n",Exec_Address);
+ break;
+
+ /* Ignore all other records */
+ default:;
+ }
+
+ Record_Checksum &= 0xFF;
+
+ /* Verify Checksum value. */
+ if (((Record_Checksum + Checksum) != 0xFF) && Enable_Checksum_Error)
+ {
+ fprintf(stderr,"Checksum error in record %d: should be %02X\n",Record_Nb, 255-Checksum);
+ Status_Checksum_Error = true;
+ }
+ }
+ }
+ while (!feof (Filin));
+ /*-----------------------------------------------------------------------------*/
+
+ fprintf(stdout,"Binary file start = %08X\n",Lowest_Address);
+ fprintf(stdout,"Records start = %08X\n",Records_Start);
+ fprintf(stdout,"Highest address = %08X\n",Highest_Address);
+ fprintf(stdout,"Pad Byte = %X\n", Pad_Byte);
+
+ WriteMemory();
+
+#ifdef USE_FILE_BUFFERS
+ free (FilinBuf);
+ free (FiloutBuf);
+#endif
+
+ fclose (Filin);
+ fclose (Filout);
+
+ if (Status_Checksum_Error && Enable_Checksum_Error)
+ {
+ fprintf(stderr,"Checksum error detected.\n");
+ return 1;
+ }
+
+ if (!Fileread)
+ usage();
+ return 0;
+}