blob: 3f39188d4139d8d619f1adf34708e6514ed3d118 [file] [log] [blame]
#!/usr/bin/perl
#
# Copyright Statement:
# --------------------
# This software is protected by Copyright and the information contained
# herein is confidential. The software may not be copied and the information
# contained herein may not be used or disclosed except with the written
# permission of MediaTek Inc. (C) 2018
#
# BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
# THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
# RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
# AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
# NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
# SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
# SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
# THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
# NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
# SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
#
# BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
# LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
# AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
# OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
# MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
#
# THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
# WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
# LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
# RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
# THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
#
#*****************************************************************************
#*
#* Filename:
#* ---------
#* update_dump_table.pl
#*
#* Project:
#* --------
#*
#*
#* Description:
#* ------------
#* This script is to update the value of dump table.
#*
#* Author:
#* -------
#* Yao Liu (mtk15073)
#*
#****************************************************************************/
use strict;
use warnings;
BEGIN { push @INC, './tools/', './tools/MemoryUtility/' }
use FileInfoParser;
use constant {
Section_Size =>0,
Section_VMA =>1,
Section_LMA =>2,
Section_Fileoffset =>3,
Symbol_VMA =>0,
Symbol_Section =>1,
Symbol_Size =>2,
};
#****************************************************************************
# Input
#****************************************************************************
my $debug = 1;
&msg_handler("Fatal", "Wrong Parameters, Usage: update_drdi_table.pl <ELF_FILE> <SYM_FILE> <DUMP_FILE> <MAKEFILE>", __LINE__) if($#ARGV != 3);
my ($elf_file, $sym_file, $dump_file, $makefile) = @ARGV;
my $templog = "Input: ELF is $elf_file\nSYM is $sym_file\nDUMP_TABLE is $dump_file\nmakefile is $makefile\n\n";
&msg_handler("Log", $templog, __LINE__);
my %g_MAKEFILE_OPTIONS;
&msg_handler("Fatal", "Failed to parse makefile!!!\n", __LINE__) if(1!=&FileInfo::Parse_MAKEFILE($makefile, \%g_MAKEFILE_OPTIONS));
&msg_handler("Log", "This load do not support DHL!!!\n", __LINE__) if(FileInfo::is("DHL_SUPPORT", "FALSE"));
exit 0 if(FileInfo::is("DHL_SUPPORT", "FALSE"));
my @symbol_array = qw/dhl_dump_profile/;
my %sym_file_hash;
map{ $sym_file_hash{'symbol_info'}->{$_} = 0 } (@symbol_array);
&parse_sym_file();
my @CRC32_Table;
&Init_CRC32_Table();
my $init = 0x1A424650;
my $constant = 1; #If the value of $init is not 0xFFFFFFFF, please set $constant to 1.
my $update_content = &get_table_info();
&dump_update_elf();
exit 0;
sub parse_sym_file
{
my ($bBegin, $sum_hit_sym) = (undef, 0);
open SYM, "< $sym_file" or &msg_handler("Fatal", "fail to open $sym_file", __LINE__);
while(my $line = <SYM>) {
$bBegin = 1 if($line =~ /^Sections:$/);
$bBegin = 2 if($line =~ /^SYMBOL TABLE:$/);
next unless(defined $bBegin);
#Idx Name Size VMA LMA File off Algn
# 0 ROM_GFH 0000084c 00000000 00000000 00000fd4 2**2
if($bBegin == 1 and $line =~ /\s*(\d+)\s+(\S+)\s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s+(\S+)/) {
my $section_name = $2;
$sym_file_hash{'section_info'}->{$section_name} = [$3, $4, $5, $6];
}
#91437ed0 g O ROM 00000180 DRDI_RCUCS_Array
elsif($bBegin == 2 and $line =~ /^([0-9a-fA-F]{8})\s+g\s+O\s+(\S+)\s+(\S+)\s+(?:\S+\s+)?(\S+)$/) {
my $symbol_name = $4;
next unless(exists $sym_file_hash{'symbol_info'}->{$symbol_name});
$sym_file_hash{'symbol_info'}->{$symbol_name} = [$1, $2, hex($3)];
&msg_handler("Log", "[Symbol]:$symbol_name [VMA]:0x$1 [Section]:$2 [Size]:0x$3\n", __LINE__) if($debug);
last if(($sum_hit_sym ++) == $#symbol_array);
}
}
close SYM;
map {&msg_handler("Fatal", "can't find symbol: $_!!!", __LINE__) if ($sym_file_hash{'symbol_info'}->{$_} == 0)} (@symbol_array);
}
sub get_table_info
{
my @temp = stat($dump_file);
#Check total size
&msg_handler("Fatal", "The sie of $dump_file is biffer than symbol size!!!\n", __LINE__) if($temp[7] > $sym_file_hash{'symbol_info'}->{"dhl_dump_profile"}->[Symbol_Size]);
my $header = unpack("V", read_memory_from_file($dump_file, 0, 4,__LINE__));
my $table_value = read_memory_from_file($dump_file, 0, ($temp[7] - 4),__LINE__);
my $check_sum = unpack("V", read_memory_from_file($dump_file, ($temp[7] - 4), 4,__LINE__));
my $content = read_memory_from_file($dump_file, 0, $temp[7],__LINE__);
#Check header
&msg_handler("Fatal", "The magic pattern mismatch!!!\n", __LINE__) if($header != 0x1A424650);
#Check CRC32 checksum
my $check_value = CRC32_CheckSum($table_value);
&msg_handler("Log", "[File Size]:$temp[7] [Old CHecksum]:$check_sum [New Checksum]:$check_value\n", __LINE__) if($debug);
&msg_handler("Fatal", "The checksum mismatch!!!\n", __LINE__) if($check_value != $check_sum);
return $content;
}
sub dump_update_elf
{
open (ELF_FILE, "+< $elf_file") or &msg_handler("Fatal", "Open $elf_file file failed!!!\n", __LINE__);
binmode ELF_FILE;
foreach my $symbol (@symbol_array) {
if($sym_file_hash{'symbol_info'}->{$symbol} == 0) {
&msg_handler("Fatal", "can't find symbol: $symbol", __LINE__);
next;
}
my $sym_region = $sym_file_hash{'symbol_info'}->{$symbol}->[Symbol_Section];
my $offset = (hex($sym_file_hash{'symbol_info'}->{$symbol}->[Symbol_VMA]) - hex($sym_file_hash{'section_info'}->{$sym_region}->[Section_VMA])) +
hex($sym_file_hash{'section_info'}->{$sym_region}->[Section_Fileoffset]);
&msg_handler("Log", "The addr of symbol in ELF is $offset.\n", __LINE__);
seek ELF_FILE, $offset, 0;
print ELF_FILE $update_content;
}
close ELF_FILE;
&msg_handler("Log", "\n\nUpdate Elf succeed ^O^", __LINE__);
}
sub read_memory_from_file
{
&msg_handler("Fatal", "[Error]: argument of $0 is insufficient\n", __LINE__) if(@_ != 4);
my ($file,$off,$len,$file_line_no) = @_;
my $content;
open(FH, $file) or &msg_handler("Fatal", "Fail to open $file: $!\n", __LINE__);
binmode FH;
&msg_handler("Fatal", "Can not seek to $off\n", __LINE__) if not seek FH, $off, 0;
&msg_handler("Fatal", "At line $file_line_no! Can't read offset $off, length $len from file $file\n", __LINE__) if read(FH, $content, $len) != $len;
close FH;
return $content;
}
sub Init_CRC32_Table
{
foreach my $index (0..255){
my $crc = $index;
foreach (0..7){
$crc = ($crc >> 1) ^ ($crc & 1 && 0xEDB88320);
}
my $value = $crc & 2 ** 32 - 1;
push @CRC32_Table, $value;
}
}
sub CRC32_CheckSum
{
my ($data) = @_;
$init ^= 0xFFFFFFFF if ($constant);
my $check_sum = $init;
my $len = length $data;
foreach my $pos (0..$len-1){
my $temp = ($check_sum ^ ord(substr($data, $pos, 1))) & 0xFF;
$check_sum = ($check_sum >> 8) ^ $CRC32_Table[$temp];
}
$check_sum ^= 0xFFFFFFFF;
return ($check_sum & 0xFFFFFFFF);
}
sub msg_handler
{
my ($type, $msg, $line_no) = (@_);
my $prompt_prefix;
if($type eq "Log") {
print $msg . "\n";
}
elsif($type eq "Warning") {
$prompt_prefix = ">> Warning : ";
print "\n" . $prompt_prefix . "[at line $line_no] " . $msg . "\n";
}
elsif($type eq "Fatal") {
$prompt_prefix = ">> Fatal : ";
die $prompt_prefix . "[at line $line_no] " . "$msg" . "\n";
}
}