blob: 42d78eafad25b73b3c5ea8bacb64ce0089caafd5 [file] [log] [blame]
yu.dongc33b3072024-08-21 23:14:49 -07001#!/usr/bin/perl
2#
3# Copyright Statement:
4# --------------------
5# This software is protected by Copyright and the information contained
6# herein is confidential. The software may not be copied and the information
7# contained herein may not be used or disclosed except with the written
8# permission of MediaTek Inc. (C) 2005
9#
10# BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
11# THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
12# RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
13# AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
14# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
15# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
16# NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
17# SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
18# SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
19# THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
20# NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
21# SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
22#
23# BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
24# LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
25# AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
26# OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
27# MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
28#
29# THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
30# WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
31# LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
32# RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
33# THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
34#
35#
36#*****************************************************************************
37#*
38#* Filename:
39#* ---------
40#* link.pl
41#*
42#* Project:
43#* --------
44#*
45#*
46#* Description:
47#* ------------
48#* 1. This script will read link error and decide to enter two-phase linking
49#* 2. If need, it will adjust ROM LENGTH.
50#*
51#*
52#* Author:
53#* -------
54#* Frank Hu
55#*
56#*============================================================================
57#* HISTORY
58#* Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
59#*------------------------------------------------------------------------------
60#*
61#*------------------------------------------------------------------------------
62#* Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
63#*============================================================================
64#****************************************************************************
65
66use strict;
67BEGIN { push @INC , './tools/', './tools/MemoryUtility/' } # add additional library path
68use LinkerOutputParser;
69use POSIX qw(floor ceil);
70use FileInfoParser;
71
72package Type;
73use constant Log => 0;
74use constant Warning => 1;
75use constant Fatal => 2;
76
77my ($LD, $LDS, $LinkLog, $LibTemp, $Makefile, $Mapfile) = @ARGV;
78
79die "$LD does not exist!\n" unless(-e $LD);
80
81system("$LD \@$LibTemp > $LinkLog 2>&1");
82exit 0 if($? == 0);
83
84&msg_handler(Type::Warning, "First link failed and check if it is UROM overflow.", __FILE__, __LINE__);
85my %makefile_option;
86&msg_handler(Type::Fatal, "Fail to open $LinkLog.", __FILE__, __LINE__) if(1 != &FileInfo::Parse_MAKEFILE($Makefile, \%makefile_option));
87
88my ($bUROMOverflow, $ExceedSize, $address, $new_UROM_size) = (0, undef);
89if (FileInfo::is("COMPILER_ISA", "NANOMIPS")) {
90 open LINK, "< $LinkLog" or &msg_handler(Type::Fatal, "Fail to open $LinkLog.", __FILE__, __LINE__);
91 my $last_ROM_section;
92 if (FileInfo::is("AMMS_DRDI_SUPPORT", "TRUE")) {
93 $last_ROM_section = "CACHED_EXTSRAM_MCURO_HWRW_DRDI_NR_63";
94 } else {
95 $last_ROM_section = "ROM_SIGNATURE_SECTION";
96 }
97 map { ($address, $bUROMOverflow) = ($1, 1) if(/^$LD: error: address (0x\w+) of section $last_ROM_section is not within region UROM/); } (<LINK>);
98 close LINK;
99
100 $new_UROM_size = hex($address) + Get_LastSection_Size($last_ROM_section);
101
102} elsif (FileInfo::is("COMPILER_ISA", "MIPS16") or FileInfo::is("COMPILER_ISA", "MIPS32")) {
103 open LINK, "< $LinkLog" or &msg_handler(Type::Fatal, "Fail to open $LinkLog.", __FILE__, __LINE__);
104 map { ($ExceedSize, $bUROMOverflow) = ($1, 1) if(/^$LD: region `UROM' overflowed by (\d+) bytes/); } (<LINK>);
105 close LINK;
106
107} else {
108 &msg_handler(Type::Fatal, "Mismatch COMPILER_ISA, please check in project makefile.", __FILE__, __LINE__);
109}
110
111if($bUROMOverflow == 1) {
112 &msg_handler(Type::Warning, "UROM overflow, Second-Link will be executed next.", __FILE__, __LINE__);
113
114 my $nUROMAdjustedLength;
115 my ($nUROMOrigin, $nUROMLength) = &GetUROMInfo();
116 if (FileInfo::is("COMPILER_ISA", "NANOMIPS")) {
117 $nUROMAdjustedLength = POSIX::ceil(($new_UROM_size) / (1024 * 1024)) * 1024 * 1024 ;
118 } elsif (FileInfo::is("COMPILER_ISA", "MIPS16") or FileInfo::is("COMPILER_ISA", "MIPS32")) {
119 $nUROMAdjustedLength = POSIX::ceil(($nUROMLength + $ExceedSize) / (1024 * 1024)) * 1024 * 1024 ;
120 } else {
121 &msg_handler(Type::Fatal, "Mismatch COMPILER_ISA, please check in project makefile.", __FILE__, __LINE__);
122 }
123 my $nUROMAdjustedStrLength = sprintf("0x%08x", $nUROMAdjustedLength);
124 my $RAM_AdjustedOrigin = POSIX::ceil(($nUROMOrigin + $nUROMAdjustedLength) / (1024 * 1024)) * 1024 * 1024;
125 my $RAM_AdjustedStrOrigin = sprintf("0x%08x", $RAM_AdjustedOrigin);
126
127 &UpdateLDS($nUROMAdjustedStrLength, $RAM_AdjustedStrOrigin);
128
129 my $Log = "\n";
130 $Log .= sprintf "|----------------Memory Space Adjustment-------------|\n";
131 $Log .= sprintf "+----------------------+--------------+--------------+\n";
132 $Log .= sprintf "+----------------------+--------------+--------------+\n";
133 $Log .= sprintf "+ Memory Space + Old Setting + New Setting +\n";
134 $Log .= sprintf "+----------------------+--------------+--------------+\n";
135
136 $Log .= (sprintf "| %20s | 0x%.8x | 0x%.8x |\n", "UROM/ROM (LENGTH)", $nUROMLength, $nUROMAdjustedLength);
137 $Log .= (sprintf "| %20s | 0x%.8x | 0x%.8x |\n", "RAM (ORIGIN)", $nUROMLength, $RAM_AdjustedOrigin);
138 $Log .= sprintf "+----------------------+--------------+--------------+\n";
139
140 &msg_handler(Type::Log, $Log, __FILE__, __LINE__);
141
142 #start the second link.
143 &msg_handler(Type::Warning, "======== Second Linking Process Start ========", __FILE__, __LINE__);
144
145 system("$LD \@$LibTemp > $LinkLog 2>&1");
146 if($? == 0) {
147 &msg_handler(Type::Warning, "======== Second Linking Process End ========", __FILE__, __LINE__);
148 exit 0;
149 }
150 else {
151 &msg_handler(Type::Fatal, "======== *** Second Linking Process fail, please check link.log. ========", __FILE__, __LINE__);
152 }
153} else {
154 &msg_handler(Type::Fatal, "link fail, please check link.log.", __FILE__, __LINE__);
155}
156
157sub GetUROMInfo
158{
159 my ($nOrigin, $nLength) = (undef, undef);
160
161 open LDS, "< $LDS" or &msg_handler(Type::Fatal, "Fail to open $LDS.", __FILE__, __LINE__);
162 map { ($nOrigin, $nLength) = (hex($1), hex($2)) if(/^\s+UROM\s*:\s*ORIGIN\s*=\s*(\S+)\s*,\s*LENGTH\s*=\s*(\S+)\s*$/); } (<LDS>);
163 close LDS;
164 &msg_handler(Type::Fatal, "UROM can't be found in $LDS", __FILE__, __LINE__) unless(defined $nOrigin and defined $nLength);
165
166 return ($nOrigin, $nLength);
167}
168
169sub UpdateLDS
170{
171 my ($UROMLength, $RAMOrigin) = @_;
172 my ($Out, $bit) = (undef, 0);
173 open LDS, "< $LDS" or &msg_handler(Type::Fatal, "Fail to open $LDS.", __FILE__, __LINE__);
174 while(<LDS>) {
175 $bit ++ if(s/^\s+UROM\s*:\s*ORIGIN\s*=\s*0x00000000\s*,\s*LENGTH\s*=\s*\S+\s*$/ UROM : ORIGIN = 0x00000000, LENGTH = $UROMLength\n/ ||
176 s/^\s+RAM\s*:\s*ORIGIN\s*=\s*\S+\s*,\s*LENGTH\s*=\s*(\S+)\s*$/ RAM : ORIGIN = $RAMOrigin, LENGTH = $1\n/);
177 $Out .= $_;
178 }
179 &msg_handler(Type::Fatal, "UROM/RAM can't be found in $LDS.", __FILE__, __LINE__) if ($bit != 2);
180 close LDS;
181
182 open LDS, "> $LDS" or &msg_handler(Type::Fatal, "Fail to open $LDS.", __FILE__, __LINE__);
183 print LDS $Out;
184 close LDS;
185}
186
187sub Get_LastSection_Size
188{
189 my ($last_section_name) = @_;
190
191 my ($flag, $VMA, $size) = (0, 0, 0);
192 open MAP, "< $Mapfile" or &msg_handler(Type::Fatal, "Fail to open $Mapfile.", __FILE__, __LINE__);
193 foreach my $line (<MAP>) {
194 $flag = 1 if ($line =~ /^$last_section_name$/);
195 last if ($flag == 2);
196 next if ($flag != 1);
197 if ($flag == 1 and $line =~ /^\s+(0x\w+)\s+(0x\w+)/) {
198 ($VMA, $size) = (hex($1), hex($2));
199 $flag = 2;
200 }
201 }
202 &msg_handler(Type::Fatal, "Cannot find size of last ROM section($last_section_name) in $Mapfile.", __FILE__, __LINE__) if ($flag != 2);
203 close MAP;
204
205 return $size;
206}
207
208sub msg_handler
209{
210 my ($type, $msg, $file_name, $line_no) = (@_);
211 my $prompt_prefix;
212 if($type == Type::Log) {
213 print $msg . "\n";
214 }
215 elsif($type == Type::Warning) {
216 $prompt_prefix = ">> LINK Warning : ";
217 my $location = (defined $file_name) ? "[$file_name] " : "";
218 print $prompt_prefix . $location . $msg . "\n";
219 }
220 elsif($type == Type::Fatal) {
221 $prompt_prefix = ">> *** LINK Fatal : ";
222 my $location = "[at line $line_no] ";
223 die $prompt_prefix . $location . $msg . "\n";
224 }
225}