344 lines
12 KiB
Perl
344 lines
12 KiB
Perl
#!/usr/bin/perl
|
|
|
|
#
|
|
#[20190307][xiaokeweng@asrmicro.com]
|
|
# COMM: Tnitial perl script ,do (RW+ZI) region compress. The header of
|
|
# image which to fetch compress area is recordered from C code ,
|
|
# may refer to /csw/bsp/src/loadTable.c for more detail.
|
|
# TODO: Armlink could do RW region compress during armlink
|
|
# but our scatter file did include ZI data inside into the RW region.
|
|
# Do further check to refactor the scatter file.
|
|
#
|
|
#[20190309][xiaokeweng@asrmicro.com]
|
|
# COMM: correct typo & fix issue which LZMA compressed info inside split_result[6]
|
|
# did not count the LZMA header&tail part size inside. it only caculate for
|
|
# compress ratio. Using [-s <file>] to get the true size of compressed file.
|
|
#
|
|
#[20190310][xiaokeweng@asrmicro.com]
|
|
# COMM: bad CPZ_LOAD_ADDR raw data, missing the initial zero address after hex_32_reorder
|
|
# fix with format-output during syswrite.
|
|
|
|
|
|
#
|
|
#[20201017][xiaokeweng@asrmicro.com]
|
|
# COMM: implement file_merge func to avoid CAT/COPY switch in defferent host env.
|
|
#
|
|
use Fcntl;
|
|
use File::Basename;
|
|
use File::Spec::Functions;
|
|
|
|
$DEBUG=0;
|
|
$LOADTABLE_HEADER_LENGTH=1024;
|
|
$CPZ_MARK_STRING="RW_CPZ_";
|
|
$IMG_FILENAME = $ARGV[0];
|
|
$IMG_GENERAL_INFO = $ARGV[1];
|
|
$PART_1 = "part1";
|
|
$PART_2 = "part2";
|
|
$COMPRE = "compressed.bin";
|
|
$TMP = "tmp";
|
|
$TMP_LZMA = "tmp_lzma";
|
|
#$INIT_LOAD_ADDRESS=0x80200000;
|
|
$INIT_LOAD_MARK_STRING="CP_EXEC";
|
|
$PAD_LENGTH=4096;
|
|
|
|
if ($^O eq 'MSWin32' || $^O eq 'msys' || $^O eq 'cygwin') {
|
|
$EXE_SUFFIX = ".exe";
|
|
} else {
|
|
$EXE_SUFFIX = "_lnx";
|
|
}
|
|
$LZMA = catfile(dirname(__FILE__), "lzma_asr$EXE_SUFFIX");
|
|
|
|
sysopen(INPUT_STREAM,"$IMG_FILENAME",O_BINARY|O_RDWR)
|
|
or error_exit("Can't open [$IMG_FILENAME] for reading; $!");
|
|
print sprintf ("|%-8s|%-74s\n","INPUT",$IMG_FILENAME);
|
|
|
|
# load the frist {$LOADTABLE_HEADER_LENGTH} binary to parse
|
|
# check {$INIT_LOAD_MARK_STRING} flag which appends the cp core execute address
|
|
#
|
|
#/csw/BSP/inc/loadTable.h
|
|
# typedef struct{
|
|
# char name[12];
|
|
# UINT32 value;
|
|
# }armlink_symbol_item;
|
|
#
|
|
#
|
|
sysread(INPUT_STREAM,$loadtable_header,$LOADTABLE_HEADER_LENGTH);
|
|
$index=index($loadtable_header,$INIT_LOAD_MARK_STRING);
|
|
if ($index == -1){
|
|
error_exit("NO compress string [$INIT_LOAD_MARK_STRING] detect, exit");
|
|
}else{
|
|
sysseek(INPUT_STREAM,$index+12,0);
|
|
sysread(INPUT_STREAM,$INIT_LOAD_ADDRESS,4);
|
|
$INIT_LOAD_ADDRESS = raw_to_hex($INIT_LOAD_ADDRESS);
|
|
#print sprintf ("0x%.08x\n",$INIT_LOAD_ADDRESS);
|
|
}
|
|
|
|
# check {$CPZ_MARK_STRING} flag which repsent the regiong compress info
|
|
#
|
|
#debug_msg("loadtable_header:[\n$loadtable_header\n]");
|
|
$index=index($loadtable_header,$CPZ_MARK_STRING);
|
|
debug_msg("index=$index");
|
|
if ($index == -1){
|
|
error_exit("NO compress string [$CPZ_MARK_STRING] detect, exit");
|
|
}else{
|
|
|
|
#open OUTBIN_P1,">$IMG_FILENAME\_$PART_1" or error_exit("can't open $IMG_FILENAME\_$PART_1 for output");
|
|
sysopen(OUTBIN_P1,"$IMG_FILENAME\_$PART_1",O_BINARY|O_CREAT|O_RDWR);
|
|
debug_msg("create the empty $IMG_FILENAME\_$PART_1");
|
|
close OUTBIN_P1;
|
|
|
|
#open OUTBIN_P2,">$IMG_FILENAME\_$PART_2" or error_exit("can't open $IMG_FILENAME\_$PART_2 for output");
|
|
sysopen(OUTBIN_P2,"$IMG_FILENAME\_$PART_2",O_BINARY|O_CREAT|O_RDWR);
|
|
debug_msg("create the empty $IMG_FILENAME\_$PART_2");
|
|
close OUTBIN_P2;
|
|
};
|
|
|
|
# parse each item start with $CPZ_MARK_STRING,
|
|
# the format detail refer to csw/BSP/inc/loadTable.h
|
|
#
|
|
#typedef struct
|
|
#{
|
|
# char RW_REGION_MARK[8];
|
|
# char RW_REGION_NAME[8];
|
|
# UINT32 RW_REGION_EXEC_ADDR;
|
|
# UINT32 RW_REGION_LOAD_ADDR;
|
|
# UINT32 RW_REGION_LENGTH;
|
|
# UINT32 RW_REGION_COMPRESSED_ADDR;
|
|
#}rw_region_item;
|
|
#
|
|
print sprintf ("|%-8s|%-8s|%-8s.%-8s.%-8s.%-8s|%-30s|\n",
|
|
"MARK","NAME","EXEADDR","LOADADDR","LENGTH","CPZLADDR","COMPRESS STASTIC");
|
|
print sprintf ("|%-8s|%-8s|%-8s.%-8s.%-8s.%-8s|%-30s|\n",
|
|
"--------","--------","--------","--------","--------","--------","------------------------------");
|
|
sysseek(INPUT_STREAM,$index,0);
|
|
while(1){
|
|
sysread(INPUT_STREAM,$mark,8);debug_msg("mark = $mark");
|
|
unless($mark =~ /$CPZ_MARK_STRING/){last;}
|
|
sysread(INPUT_STREAM,$name,8);
|
|
sysread(INPUT_STREAM,$exec_addr,4);$exec_addr = raw_to_hex($exec_addr);
|
|
sysread(INPUT_STREAM,$load_addr,4);$load_addr = raw_to_hex($load_addr);
|
|
sysread(INPUT_STREAM,$length,4);$length = raw_to_hex($length);
|
|
sysread(INPUT_STREAM,$cpz_load_addr,4);$cpz_load_addr = raw_to_hex($cpz_load_addr);
|
|
|
|
# recorder the first compress region offset for PART_1
|
|
#
|
|
unless( "$mark" cmp "$CPZ_MARK_STRING".1){
|
|
$p1_length=($load_addr-$INIT_LOAD_ADDRESS);
|
|
$tmp_cpz_load_addr=($load_addr);
|
|
debug_msg("p1_length=$p1_length");
|
|
if($p1_length&($PAD_LENGTH-1)){
|
|
$p1_pad_length = $PAD_LENGTH - $p1_length&($PAD_LENGTH-1);
|
|
#print sprintf ("p1_pad_length %.8x\n",$p1_pad_length);
|
|
$tmp_cpz_load_addr = $tmp_cpz_load_addr + $p1_pad_length;
|
|
#print sprintf ("tmp_cpz_load_addr %.8x\n",$tmp_cpz_load_addr);
|
|
}
|
|
|
|
}
|
|
|
|
#print sprintf ("[%8s][%8s][0x%.08x][0x%.08x][0x%.08x]\n",$mark,$name,$exec_addr,$load_addr,$length);
|
|
|
|
# step1: cut uncompressed Region into OUTBIN_TMP file
|
|
#
|
|
open TMP_INPUT_STREAM, $IMG_FILENAME or error_exit("Can't open [$IMG_FILENAME] for reading; $!");
|
|
sysopen(TMP_INPUT_STREAM,$IMG_FILENAME,O_BINARY|O_RDONLY);
|
|
sysseek(TMP_INPUT_STREAM,$load_addr-$INIT_LOAD_ADDRESS,0);
|
|
sysread(TMP_INPUT_STREAM,$buf,$length);
|
|
sysopen(OUTBIN_TMP,"$mark\_$TMP",O_BINARY|O_CREAT|O_WRONLY);
|
|
syswrite(OUTBIN_TMP,$buf,$length);
|
|
close TMP_INPUT_STREAM;
|
|
close OUTBIN_TMP;
|
|
|
|
# step2: compressed the OUTBIN_TMP & get the lzma info
|
|
#
|
|
$lowercase_tmp_lzma_file=lc("$mark\_$TMP_LZMA"); # set to lowercase to avoid case-change under linux env , with WINE lzma.exe invoke
|
|
$temp_index=index($IMG_GENERAL_INFO,"8M");
|
|
if ($temp_index == -1){
|
|
$temp_index=index($IMG_GENERAL_INFO,"4M");
|
|
if ($temp_index == -1){
|
|
qx("$LZMA" ds 19 e $mark\_$TMP $lowercase_tmp_lzma_file 2>&1 );
|
|
}else{
|
|
print sprintf ("|%s|\n","LteOnly 4M RAM");
|
|
qx("$LZMA" ds 17 e $mark\_$TMP $lowercase_tmp_lzma_file 2>&1 );
|
|
}
|
|
}else{
|
|
print sprintf ("|%s|\n","LteOnly 8M RAM");
|
|
qx("$LZMA" ds 18 e $mark\_$TMP $lowercase_tmp_lzma_file 2>&1 );
|
|
}
|
|
|
|
$tmp_lzma_size=-s "$lowercase_tmp_lzma_file";
|
|
sysopen(OUTBIN_TMP_LZMA,"$lowercase_tmp_lzma_file",O_BINARY|O_WRONLY|O_APPEND);
|
|
if($tmp_lzma_size&($PAD_LENGTH-1)){
|
|
$temp_pad_length = $PAD_LENGTH - $tmp_lzma_size&($PAD_LENGTH-1);
|
|
#print sprintf ("temp_pad_length %.8x\n",$temp_pad_length);
|
|
while($temp_pad_length--){
|
|
#print OUTBIN_TMP_LZMA '0';
|
|
syswrite(OUTBIN_TMP_LZMA,pack("H1","0"),1);
|
|
}
|
|
#syswrite(OUTBIN_TMP_LZMA,$bufpad,$temp_pad_length);
|
|
}
|
|
close OUTBIN_TMP_LZMA;
|
|
|
|
$tmp_file_size=-s "$mark\_$TMP";
|
|
$tmp_lzma_size=-s "$lowercase_tmp_lzma_file";
|
|
|
|
print sprintf ("|%8s|%7s |%.08x.%.08x.%.08x.%.08x|%.08x->%.08x\n",
|
|
$mark,substr($name,0,7),$exec_addr,$load_addr,$length,$tmp_cpz_load_addr,
|
|
$tmp_file_size,$tmp_lzma_size);
|
|
|
|
# step3: record the current load addr into image header
|
|
# if (==1st ) RW_REGION_COMPRESSED_ADDR = RW_REGION_LOAD_ADDR;
|
|
# if (>=2nd ) RW_REGION_COMPRESSED_ADDR = last(RW_REGION_COMPRESSED_ADDR)+last(COMPRESSED_LENGTH);
|
|
#
|
|
my $tell=sysseek(INPUT_STREAM,0,1);
|
|
|
|
sysseek(INPUT_STREAM,$tell-8,0);
|
|
debug_msg(sysseek(INPUT_STREAM,0,1));
|
|
$tmp_size = hex_32_reorder($tmp_lzma_size);
|
|
#print sprintf "debug - tmp_raw=0x%.08x\n",$tmp_raw;
|
|
syswrite(INPUT_STREAM,pack("H*",sprintf("%08x",$tmp_size)),4);
|
|
|
|
debug_msg(sysseek(INPUT_STREAM,0,1));
|
|
$tmp_raw = hex_32_reorder($tmp_cpz_load_addr);
|
|
#print sprintf "debug - tmp_raw=0x%.08x\n",$tmp_raw;
|
|
syswrite(INPUT_STREAM,pack("H*",sprintf("%08x",$tmp_raw)),4);
|
|
|
|
$tmp_cpz_load_addr = $tmp_cpz_load_addr+$tmp_lzma_size;
|
|
#print sprintf ("tmp_cpz_load_addr=[%.08x][%d]\n",$tmp_cpz_load_addr,$tmp_cpz_load_addr);
|
|
|
|
# step4: append compressed file into $IMG_FILENAME\_PART_2 one by one
|
|
#
|
|
sysopen(OUTBIN_TMP_LZMA,"$lowercase_tmp_lzma_file",O_BINARY|O_RDWR);
|
|
sysopen(OUTBIN_P2,"$IMG_FILENAME\_$PART_2",O_BINARY|O_WRONLY|O_APPEND);
|
|
while(<OUTBIN_TMP_LZMA>){
|
|
print OUTBIN_P2 $_;
|
|
}
|
|
|
|
# step5: trash clean
|
|
#
|
|
unlink glob("$mark*");
|
|
close OUTBIN_P2;
|
|
close OUTBIN_TMP_LZMA;
|
|
}
|
|
|
|
#print sprintf ("[%-8s][%-8s][%-8s][%-8s][%-8s][%-8s][%-33s]\n",
|
|
# "--------","--------","--------","--------","--------","--------","---------------------------------");
|
|
unlink glob("*$TMP_LZMA");
|
|
|
|
# step6: append compressed file into $IMG_FILENAME\_PART_2 one by one
|
|
#
|
|
sysseek(INPUT_STREAM,0,0);
|
|
sysopen(INPUT_STREAM,"$IMG_FILENAME",O_BINARY|O_RDONLY);
|
|
sysread(INPUT_STREAM,$buf,$p1_length);
|
|
sysopen(OUTBIN_P1,"$IMG_FILENAME\_$PART_1",O_BINARY|O_WRONLY|O_APPEND);
|
|
syswrite(OUTBIN_P1,$buf,$p1_length);
|
|
if($p1_length&($PAD_LENGTH-1)){
|
|
$p1_pad_length = $PAD_LENGTH - $p1_length&($PAD_LENGTH-1);
|
|
#print sprintf ("p1_pad_length %.8x\n",$p1_pad_length);
|
|
while($p1_pad_length--){
|
|
#print OUTBIN_P1 '0';
|
|
syswrite(OUTBIN_P1,pack("H1","0"),1);
|
|
}
|
|
#syswrite(OUTBIN_P1,$bufpad,$p1_pad_length);
|
|
}
|
|
|
|
close OUTBIN_P1;
|
|
|
|
# step6: PART1 + PART2 > IMG_FILENAME & dump IMAGE size compress summery
|
|
#
|
|
#print sprintf ("[%-8s][%-8s][%-8s][%-8s][%-8s][%-8s][%-33s]\n",
|
|
# "--------","--------","--------","--------","--------","--------","---------------------------------");
|
|
my $original_size= -s $IMG_FILENAME;
|
|
unlink("$IMG_FILENAME");
|
|
close INPUT_STREAM;
|
|
$temp_index=index($IMG_GENERAL_INFO,"_TRUNCATE");
|
|
if ($temp_index == -1){
|
|
file_merge("$IMG_FILENAME\_$PART_1","$IMG_FILENAME\_$PART_2",$IMG_FILENAME);
|
|
my $compressed_size= -s $IMG_FILENAME;
|
|
}else{
|
|
unlink("$IMG_FILENAME");
|
|
rename("$IMG_FILENAME\_$PART_1","$IMG_FILENAME");
|
|
$COMPRE_NAME=substr($IMG_FILENAME,0,length($IMG_FILENAME)-4);
|
|
|
|
rename("$IMG_FILENAME\_$PART_2","$COMPRE_NAME\_$COMPRE");
|
|
my $uncompressed_size= -s $IMG_FILENAME;
|
|
my $compressed_size_temp= -s "$COMPRE_NAME\_$COMPRE";
|
|
$compressed_size = $uncompressed_size + $compressed_size_temp;
|
|
}
|
|
|
|
|
|
|
|
print sprintf ("|%-8s|%-8s|%-8s.%-8s.%-8s.%-8s|%-30s|\n",
|
|
"--------","--------","--------","--------","--------","--------","------------------------------");
|
|
print sprintf ("|%-53s|%6s0x%.08x -> 0x%.08x|\n","","",
|
|
$original_size,$compressed_size);
|
|
print sprintf ("|%-53s|%6s%6.3f(MB) -> %6.3f(MB)|\n","","",
|
|
$original_size/1024/1024,$compressed_size/1024/1024);
|
|
print sprintf ("|%s|\n","------------------------------------------------------------------------------------");
|
|
|
|
|
|
unlink("$IMG_FILENAME\_$PART_1");
|
|
unlink("$IMG_FILENAME\_$PART_2");
|
|
exit(0);
|
|
|
|
# functions
|
|
#
|
|
sub hex_32_reorder{
|
|
local $m_hex = $_[0];
|
|
$m_hex = ((($m_hex&0x000000ff)<<24)|
|
|
(($m_hex&0x0000ff00)<<8)|
|
|
(($m_hex&0x00ff0000)>>8)|
|
|
(($m_hex&0xff000000)>>24));
|
|
return $m_hex;
|
|
}
|
|
|
|
sub raw_to_hex{
|
|
local $m_hex = hex(unpack("H*",$_[0]));
|
|
$m_hex = hex_32_reorder($m_hex);
|
|
return $m_hex;
|
|
}
|
|
|
|
sub debug_msg{
|
|
unless($DEBUG){return};
|
|
local $DEBUG_MSG="DEBUG >>> :";
|
|
print "$DEBUG_MSG @_";
|
|
print "\n";
|
|
}
|
|
sub error_exit{
|
|
local $ERROR_MSG="\nERROR:**";
|
|
print "----------------------";
|
|
print "$ERROR_MSG @_";
|
|
print "\n";
|
|
exit(1);
|
|
}
|
|
|
|
sub file_merge{
|
|
open(RH,$_[0]) or die "$!";
|
|
binmode RH;
|
|
my @src_1=<RH>;
|
|
close RH;
|
|
|
|
open(RH,$_[1]) or die "$!";
|
|
binmode RH;
|
|
my @src_2=<RH>;
|
|
close RH;
|
|
|
|
#create&overwrite for input file arg0
|
|
open(WH,">$_[2]") or die "$!";
|
|
binmode WH;
|
|
my $i;
|
|
for($i = 0; $i < @src_1; $i++){
|
|
print WH $src_1[$i];
|
|
}
|
|
close WH;
|
|
|
|
#append for input file arg1
|
|
open(WH,">>$_[2]") or die "$!";
|
|
binmode WH;
|
|
my $i;
|
|
for($i = 0; $i < @src_2; $i++){
|
|
print WH $src_2[$i];
|
|
}
|
|
close WH;
|
|
|
|
}
|