#!perl -w # (C) 2003-2007 Willem Jan Hengeveld # Web: http://www.xs4all.nl/~itsme/ # http://wiki.xda-developers.com/ # # $Id: map.pl 1502 2007-04-15 07:54:20Z itsme $ # use strict; my $cfgfile=shift; my $cfg= ReadConfig($cfgfile); my $data= ReadFiles($cfg->{input}); WriteFiles($cfg->{output}, $data); exit(0); sub ReadConfig { my ($filename)= @_; my $fh= IO::File->new($filename, "r"); my $section; my $info= {}; while(<$fh>) { s/\s+$//; if (/\[(\w+)\]/) { $section= []; $info->{$1}= $section; } elsif (/^([^:]+):(\w+)=(\w+)\s+l=(\w+)$/) { push @$section, { filename=>$1, fileoffset=>hex($2), virtualoffset=>hex($3), length=>hex($4), }; } elsif (/^([^:]+):(\w+)\s+(\w+)$/) { push @$section, { filename=>$1, virtualoffset=>hex($2), length=>hex($3), }; } } return $info; } sub ReadFiles { my ($inputfiles)= @_; my $datamap= {}; for my $input (@$inputfiles) { ReadFile($input, $datamap); } return $data; } sub ReadFile { my ($input, $datamap)= @_; if ( hasOverlapWithAnyRange($datamap, $input->{virtualoffset}, $input->{length})) { die sprintf("range overlapping %08lx-%08lx\n", $input->{virtualoffset}, $input->{virtualoffset}+$input->{length}); } my $fh= IO::File->open($input->{filename}, "r"); binmode $fh; $fh->seek($input->{fileoffset}, SEEK_SET); my $data; $fh->read($data, $input->{length}); $fh->close(); $datamap->{$input->{virtualoffset}}= { start=>$input->{virtualoffset}, length=>$input->{length}, data=>$data, }; } sub hasOverlapWithAnyRange { my ($data, $start, $length)= @_; for (values $data) { return 1 if hasOverlapWithRange($_, $start, $length); } return 0; } sub hasOverlapWithRange { my ($range, $start, $length)= @_; return ($range->{start}+$range->{length} > $start && $start+$length > $range->{start}); } sub WriteFiles { my ($outputdef, $datamap)= @_; for my $output (@$outputdef) { WriteFile($datamap, $output); } } sub WriteFile { my ($datamap, $output)= @_; my $fh= IO::File->new($output->{filename}, "w+"); binmode $fh; my $offset= $output->{virtualoffset}; my $length= $output->{length}; for my $start (sort keys %$datamap) { my $data= $datamap->{$start}; if (hasOverlapWithRange($data)) { if ($offset<$start) { WritePadding($fh, min($offset-$start, $length)); $length -= $offset-$start; $offset= $start; } my $dataofs= $data->{virtualoffset}-$offset; my $datalen= min($length, $data->{length}-$dataofs); $fh->syswrite($data->{data}, $datalen, $dataofs); $length -= $datalen; $offset += $datalen; } } if ($length) { WritePadding($fh, $length); $offset += $length; $length= 0; } $fh->close(); } sub WritePadding { my ($fh, $size) = @_; $fh->sysseek($size, SEEK_CUR); }