| #!/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"; |
| } |
| } |
| |
| |