#! /bin/env perl # # Copyright (c) 2012, 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 <[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";