2 # See http://www.precma.it/download/intelhex.pdf
4 # Written by Ian Jackson in November/December 2005.
5 # I hereby waive my copyright in this file. - Ian Jackson 16.12.2005.
8 use strict qw(refs vars);
10 our ($lba,$sba,$loc,$eof,%once);
18 if (!defined $$o) { $$o= $loc; return; }
19 die sprintf("%s: %s: clash at 0x%x (1st)\n".
20 "%s: %s: clash at 0x%x (2nd)\n",
21 $0, $$o, $r, $0, $loc, $r);
24 sub bad ($) { my ($m)=@_; die "$0: $loc: $m\n"; }
26 my ($drlo,$dri,$orgline,$la);
32 chomp; # General Record Format, p5
33 s/^\:// or bad('no colon');
35 m/[^0-9a-f]/ and bad("bad char ".ord($&));
36 length() & 1 and bad('odd length');
38 s/..$//; # chop checksum (we don't check this)
39 s/^..//; # chop reclen (we don't check this)
41 if (s/^000001//) { # End of File, p11
43 if ($lba) { $orgline= ":020000040000FA\n"; $lba=0; }
44 elsif ($sba) { $orgline= ":020000020000FC\n"; $sba=0; }
46 } elsif (s/^000004(....)$//) { $lba= hex($1)<<16; } # Ext'd Linear Addr, p6
47 elsif (s/^000002(....)$//) { $sba= hex($1)<<4; } # Ext'd Seg. Addr., p7
48 elsif (s/^(....)00//) { # Data Record, p8
50 for ($dri=0; s/^..//; $dri++) {
51 bad('both LBA and SBA') if $lba && $sba;
52 if ($lba) { $la= ($lba+$drlo+$dri) & 0x0ffffffff; }
53 elsif ($sba) { $la= $sba + (($drlo+$dri) & 0xffff); }
54 else { $la= $drlo+$dri; }
55 #print STDERR ">$lba|$sba|$drlo|$dri|$la|$_<\n";
59 elsif (s/^000005//) { once('start'); } # Start Linear Address, p9
60 elsif (s/^000003//) { once('start'); } # Start Segment Address, p10
62 bad('unknown record or bad record');
64 print $orgline or die $!;
73 my ($s) = sprintf $f, @_;
74 if ($s =~ m/^\s/ && length($ld.$s) > 70) {
75 print STDERR $ld,"\n" or die $!; $ld= " ";
80 print STDERR $ld,"\n" or die $!;
85 foreach $ca (sort { $a <=> $b } keys %once) {
86 next if defined($la) && $ca == ++$la;
95 } elsif ($la != $a1) {
100 die "$0: no input files or missing EOF markers\n" unless defined $eof;
101 print $eof or die $!;