diff options
Diffstat (limited to 'bootwrapper/makemap')
-rwxr-xr-x | bootwrapper/makemap | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/bootwrapper/makemap b/bootwrapper/makemap new file mode 100755 index 0000000..47213c9 --- /dev/null +++ b/bootwrapper/makemap @@ -0,0 +1,174 @@ +#! /bin/env perl +# +# Copyright (c) 2011, ARM Limited. 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. +# +# Neither the name of ARM nor the names of its +# contributors may be used to endorse or promote products +# derived from this software without specific prior written +# permission. +# + +use strict; + +use vars qw( + $image + $source + $obj + $map + $kernaddr + $sh + $mh + %chunksdone + @chunks +); + +sub addchunk($$) +{ + my $file = shift; + my $addr = shift; + my $size = -s $file; + my $name = $file; + $name =~ s|^.*/([^/]+)$|$1|; + + # Multiple contiguous sections are saved as one chunk, so in that case only process the first + if (!defined $chunksdone{$name}) + { + print $sh <<EOF; + AREA |$name|, CODE, ALIGN=2 + INCBIN $file +EOF + + print $mh <<EOF; +$name $addr $size +{ + ${name}DATA $addr $size + { + $obj ($name) + } +} +EOF + + $chunksdone{$name} = 1; + push @chunks, [ $addr, $size ]; + } +} + +sub num($) +{ + my $n = shift; + $n = oct $n if $n =~ /^0/; + return $n; +} + +sub covered($) +{ + my $start = num(shift); + + for (@chunks) + { +# printf "Checking $start against chunk $_->[0] (%d), $_->[1] (%d), %d\n",num($_->[0]),num($_->[1]),num($_->[0])+num($_->[0]); + return 1 if $start >= num($_->[0]) && $start < num($_->[0])+num($_->[1]); + } + return 0; +} + +($image=shift) && ($source = shift) or die "\ +Usage: $0 image source [ kernaddr ] + Creates source and map files to load the sections of \$image + \(if it is an ARM ELF file\), or the whole of \$image at \$kernaddr"; + +$kernaddr=shift; +$map="$source.map"; +$obj="$source.o"; + +open $sh, ">$source.S" or die "Can't create '$source.S'"; +open $mh, ">$map" or die "Can't create '$map'"; + +# Check if $image is an ELF file +my $type=`file -L $image`; +if ( $type =~ /ELF.*ARM/ ) +{ +# print "$image is an ELF file - splitting\n"; + system("rm -rf $image.bin"); + system("fromelf --bin $image -o $image.bin"); + my $fromelfv=`fromelf --vsn`; + ($fromelfv=~/FromELF, (RVCT|)([\d\.]+)/) && ($2 >= 4.1) or die "fromelf version '$2' is too old - need 4.1 or greater"; + my $desc = `fromelf --text $image`; + my $chunk; + my $chunkdone; + my %chunkdefined; + my $zichunk; + + for my $line (split /\n/,$desc) + { + # Program header lines indicate what loadable chunks are present + # Handily, these refer to 'Virtual address' rather than 'Address' + $chunkdefined{$1} = 1 if $line =~ /^\s+Virtual address:\s+(0x[0-9a-fA-F]+)/; + + # Section entries give the chunk name + if ($line =~ /^\*+\s+Section\s+#\d+\s+'([^']+)/) + { + # If there's only one chunk, fromelf creates a single file not a directory + $chunk = -d "$image.bin" ? "$image.bin/$1" : "$image.bin"; + $zichunk = 0; + if ($line =~ / \(SHT_NOBITS\) /) + { + # We produce an explicit block of zeroes to cope with systems that don't auto-expand ZINIT areas + $chunk .= '.zi'; + $zichunk = 1; + } + } + + if ($zichunk && ($line =~ /^\s+Size\s*:\s+(\d+)\s+bytes/)) + { + my $size = $1; + my $h; + open $h, ">$chunk" or die "Can't create ZI chunk '$chunk'"; + binmode $h; + print $h chr(0) x $size; + close $h; + } + if ($line =~ /^\s+Address:\s+(0x[0-9a-fA-F]+)/ && ($zichunk || $chunkdefined{$1})) + { + # ZI data is already in the binary dump if it is followed by non-ZI data. + if ($zichunk && covered($1)) + { + print "ZI data at $1 set by existing data; will not set explicitly\n"; + $zichunk = 0; + # Remove .zi + $chunk = substr($chunk,0,-3); + } + else + { + # Multiple contiguous sections are saved as one chunk, so in that case only process the first + # Here we deal with the case where all the sections are contiguous + addchunk("$chunk",$1) if $zichunk || -d "$image.bin" || !$chunkdone; + $chunkdone = 1; + } + } + + $kernaddr=$1 if $line =~ /^\s+Image Entry point:\s+(0x[0-9a-fA-F]+)/; + } +} +else +{ +# print "$image being wrapped as plain binary to load at $kernaddr\n"; + addchunk($image,$kernaddr); +} + +die "No entry point in image or on command line" if !defined $kernaddr; + +print $sh " EXPORT ${source}_image\n${source}_image EQU $kernaddr\n END\n"; |