blob: 69941b40168c8ee59999e11020e2f010a4fa1031 [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) 2006
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#* Filename:
38#* ---------
39#* ldsFrame.pm
40#*
41#* Project:
42#* --------
43#*
44#*
45#* Description:
46#* ------------
47#* This script is to generate the frame of memory layout
48#* and provides the flow of generation
49#*
50#* Author:
51#* -------
52#* Carl Kao (mtk08237)
53#*
54#****************************************************************************/
55#****************************************************************************
56# Included Modules
57#****************************************************************************
58use strict;
59BEGIN { push @INC, './tools/' } # add additional library path
60use ldsInfo;
61use CommonUtility;
62use sysGenUtility;
63package ldsFrame;
64#****************************************************************************
65# oo >>> Finished
66#****************************************************************************
67return 1;
68
69#****************************************************************************
70# ldsFrame Version
71#****************************************************************************
72sub ldsFrame_verno
73{
74 return " u0.05";
75 # u0.05, 2016/06/21 by Tero, Fixed Memory parsing
76 # u0.04, 2016/01/19 by Tero, Fixed ASSERT multiple parenthesis issue
77 # u0.03, 2015/10/19 by Carl, Catch invalid input section
78 # u0.02, 2014/12/17 by Carl, Support multiple overlap section
79 # u0.01, 2014/02/20 by BM, Initial version
80 # m0.28 , 20130913 by mei, Fix symbol bug
81 # m0.27 , 20130605 by mei, Make input section file name more flexible in OVERLAY section
82 # m0.26 , 20130115 by mei, Change Default csv name to Default.csv
83 # m0.25 , 20130114 by mei, Set LDSType to be MAIN by default
84 # m0.24 , 20130113 by mei, Support template getting from build folder first
85 # m0.23 , 20121030 by mei, Support more flexible ASSERT in Action,
86 # Support EndAction (to put Action in the end)
87 # m0.22 , 20121029 by mei, Support MEMORY without counting reserved region
88 # m0.21 , 20121020 by mei, Make addresses in OVERLAY region be 4 bytes aligned
89 # m0.20 , 20121002 by mei, Make all lengths are 4 bytes aligned for region-init
90 # m0.19 , 20120827 by mei, Support Head input sections
91 # m0.18 , 20120817 by mei, Support SetMemorySetting() without calling callback if no need to replace
92 # m0.17 , 20120816 by mei, Change symbol assignment in OVERLAY to fix ld's bug
93 # m0.16 , 20120816 by mei, Support Input section with Common Block, Chip Block and DefaultChip Block
94 # m0.15 , 20120727 by mei, Refine lds output format
95 # m0.14 , 20120724 by mei, Support MaxSize ASSERT
96 # m0.13 , 20120713 by mei, Support atomic Type(e.g. not accept //SectionFrame)
97 # Fix LoadAddress' bug
98 # Support Default address(top and bottom) align 4 bytes
99 # m0.12 , 20120712 by mei, Remove EWS since no need to add dependency in pm file
100 # m0.11 , 20120710 by mei, Support input section got from chip.txt as well
101 # m0.10 , 20120702 by mei, Support EWS
102 # m0.09 , 20120702 by mei, Support Memory Setting with booting type via GetBootingType()
103 # m0.08 , 20120625 by mei, Use scalar instead of $#
104 # m0.07 , 20120615 by mei, Support using $# on Linux
105 # m0.06 , 20120530 by mei, Support RegionList by chip
106 # m0.05 , 20120530 by mei, Fix CleanCallBackFunc()'s bug
107 # m0.04 , 20120528 by mei, Support path and filename case sensitive on Linux
108 # m0.03 , 20120513 by mei, Support BLldsGen
109 # m0.02 , 20120507 by mei, Fix ACTION behavior
110 # m0.01 , 20120507 by mei, initial version
111}
112#****************************************************************************
113# Constants
114#****************************************************************************
115#****************************************************************************
116# Global Variables
117#****************************************************************************
118my %Func = ("CollectMemorySetting" => undef,
119 "SetMemorySegment" => undef, # not necessary
120 "GetChip" => undef,
121 "SetRegionList" => undef,
122 "GetBootingType" => undef,
123 "GetCustomFolder" => undef, # to get CustomFolder's template first
124 );
125my %g_MEMORYSetting;
126my $g_nLDSType = 0; #default be MAIN
127#****************************************************************************
128# Input Parameters
129#****************************************************************************
130use constant BASIC => 0;
131use constant MEMORY => 1;
132use constant InputSections => 2;
133use constant RegionList => 3;
134#LDS Type
135use constant MAIN => 0;
136use constant BL => 1;
137use constant EXT_BL => 2;
138use constant FOTA => 3;
139#Input Section File Name
140use constant COMMON_InputSection => "Common";
141use constant ChipDependent_Default_InputSection => "DefaultChip";
142use constant HEAD_InputSection => "Head";
143#****************************************************************************
144# subroutines
145#****************************************************************************
146sub GetLDSType
147{
148 my %LDSFolderName = (0 => "lds_config",
149 1 => "BL_lds_config",
150 2 => "EXT_BL_lds_config",
151 );
152 &ldsFrame_die("unsupport LDSType: $g_nLDSType \n", __FILE__, __LINE__) if(!exists $LDSFolderName{$g_nLDSType});
153 return $LDSFolderName{$g_nLDSType};
154}
155#ldsFrame::GetPath("MT6280", ldsFrame::MEMORY)
156#ldsFrame::GetPath("ROM", ldsFrame::InputSections)
157#ldsFrame::GetPath("MT6280", ldsFrame::RegionList)
158sub GetPath
159{
160 my ($strKey, $nType) = @_;
161 my $strPath = undef;
162 my $LDSFolderName = &GetLDSType();
163 my $strDefaultSystemFolder = "./custom/system";
164 my $strTemplateFolder = "$strDefaultSystemFolder/Template/$LDSFolderName/";
165 my %PathMap = ("ldsMainFrame" => "ldsTemplate/ldsMainFrame.txt",
166 "RegionList" => "RegionConfig/",
167 "MEMORY" => "ldsTemplate/MEMORY/",
168 "InputSections" => "InputSections/",
169 );
170 if($nType == BASIC)
171 {
172 $strPath = $strTemplateFolder . $PathMap{$strKey};
173 }
174 elsif($nType == MEMORY)
175 {
176 $strPath = $strTemplateFolder.$PathMap{MEMORY}.$strKey."_".&{$Func{GetBootingType}}().".txt" if(defined $Func{GetBootingType});
177 $strPath = $strTemplateFolder.$PathMap{MEMORY}.$strKey.".txt" if(!-e $strPath);;
178 }
179 elsif($nType == RegionList)
180 {
181 $strPath = $strTemplateFolder.$PathMap{RegionList}.$strKey.".csv";
182 $strPath = $strTemplateFolder.$PathMap{RegionList}."Default.csv" if(!-e $strPath);
183 $strPath = $strTemplateFolder.$PathMap{RegionList}."RegionList.csv" if(!-e $strPath); # for backward compatible
184 }
185 elsif($nType == InputSections)
186 {
187 $strPath = $strTemplateFolder . $PathMap{InputSections}.$strKey."/";
188 }
189 else
190 {
191 &ldsFrame_die("[GetPath]Unsupport Type", __FILE__, __LINE__);
192 }
193 if(exists $Func{GetCustomFolder})
194 {
195 my $strCustomedFolder = &{$Func{GetCustomFolder}}();
196 my $strCustomedPath = $strPath;
197 $strCustomedPath =~ s/$strDefaultSystemFolder/$strCustomedFolder/;
198 $strPath = $strCustomedPath if(-e $strCustomedPath);
199 }
200 return $strPath;
201}
202
203
204
205#****************************************************************************
206# subroutine: ProcessTemplate
207# Input: $strFilePath: the file to be processed
208# $strKeyFinding: e.g. ldsGen or AUTOGEN
209# Output: $content: the content after processing
210# Description: if there is the pattern as [ldsGen_funcname],
211# the whole pattern will be replaced by calling funcname().
212# if funcname() doesn't exist, it'll fail and report error.
213#****************************************************************************
214sub ProcessTemplate
215{
216 my ($strFilePath, $strKeyFinding) = @_;
217 my $content;
218 open (FILE_HANDLE, $strFilePath) or &ldsFrame_die("Cannot open $strFilePath\n", __FILE__, __LINE__);
219 while(<FILE_HANDLE>)
220 {
221 my $strLine = $_;
222 while ($strLine =~ /\[$strKeyFinding\_(\w+)\]/)
223 {
224 my $func = $1;
225 my $template;
226 {
227 no strict 'refs';
228 $template = &{$func}() if(exists &{$func})
229 or &ldsFrame_die("$func() doesn't exist!\n", __FILE__, __LINE__);
230 }
231 chomp($strLine);
232 $strLine =~ s/\[$strKeyFinding\_$func\]/$template/g;
233 }
234 $content .= $strLine;
235 }
236 close FILE_HANDLE;
237 return $content;
238}
239
240sub ProcessSection
241{
242 my ($strContent, $Info_ref, $Index_ref) = @_;
243 my @lines = split(/\n/, $strContent);
244 my $strResult;
245 foreach my $strLine (@lines)
246 {
247 while ($strLine =~ /\[ldsGen_(\w+)\]/)
248 {
249 my $func = "Gen".$1;
250 my $template;
251 {
252 no strict 'refs';
253
254 $template = &{$func}($Info_ref, $Index_ref) if(exists &{$func})
255 or &ldsFrame_die("[ProcessSection]$func() doesn't exist!\n", __FILE__, __LINE__);
256 }
257 $strLine =~ s/\[ldsGen_$1\]/$template/g;
258 }
259 $strResult .= $strLine . "\n";
260 }
261 return $strResult;
262}
263
264#****************************************************************************
265sub GenLDS
266{
267 ($g_nLDSType) = @_;
268 #Check CallBack functions
269
270 my $strLayout = &ProcessTemplate( &GetPath("ldsMainFrame", BASIC) , "ldsGen");
271 return $strLayout;
272}
273
274sub CleanCallBackFunc
275{
276 foreach (keys %Func)
277 {
278 delete $Func{$_};
279 }
280 %g_MEMORYSetting = ();
281 $g_nLDSType = 0;
282}
283sub SetCallBackFunc
284{
285 my ($strKey, $func) = @_;
286 $Func{$strKey} = $func;
287}
288
289#****************************************************************************
290sub GenMEMORY
291{
292 my $MEMORYPath = &GetPath(&{$Func{GetChip}}(), MEMORY);
293 my $MEMORYContent = &CommonUtil::GetFileContent($MEMORYPath);
294 my $MEMORY_SEGMENT_aref = &ldsInfo::ParseMEMORY($MEMORYContent);
295 my ($RegionList_ref, $Index_ref)= &PreProcessRegionList(undef);
296 &SetMemorySetting($MEMORY_SEGMENT_aref, $MEMORYPath, $RegionList_ref, $Index_ref);
297 &{$Func{SetMemorySegment}}($MEMORY_SEGMENT_aref) if(exists $Func{SetMemorySegment}); # for extension, not used now
298 my $strMEMORY;
299 foreach my $i (@$MEMORY_SEGMENT_aref)
300 {
301 if (!defined $i->[1])
302 {
303 $strMEMORY .="$i->[0]\n";
304 next;
305 }
306 $strMEMORY .= " $i->[0] : ORIGIN = $i->[1], LENGTH = $i->[2]\n";
307 my $nBase = eval($i->[1]);
308 my $nLen = eval($i->[2]);
309 $g_MEMORYSetting{$i->[0]} = [&CommonUtil::Dec2Hex($nBase),
310 &CommonUtil::Dec2Hex($nLen)];
311 }
312 return $strMEMORY;
313}
314
315sub SetMemorySetting
316{
317 my ($MEMORY_SEGMENT_aref, $MEMORYPath, $RegionList_ref, $Index_ref) = @_;
318 if(exists $Func{CollectMemorySetting})
319 {
320 my $Setting = &{$Func{CollectMemorySetting}}($MEMORYPath, , $RegionList_ref, $Index_ref);
321 foreach my $i (@$MEMORY_SEGMENT_aref)
322 {
323 while($i->[1] =~ /\[(\S+)\]/)
324 {
325 my $temp = $1;
326 &ldsFrame_die("$1 in\n$MEMORYPath\n isn't set in CollectMemorySetting()!\n", __FILE__, __LINE__) if(!exists $Setting->{$1});
327 $i->[1] =~ s/\[$temp\]/$Setting->{$temp}/g;
328 }
329 while($i->[2] =~ /\[(\S+)\]/)
330 {
331 my $temp = $1;
332 &ldsFrame_die("$1 in\n$MEMORYPath\n isn't set in CollectMemorySetting()!\n", __FILE__, __LINE__) if(!exists $Setting->{$1});
333 $i->[2] =~ s/\[$temp\]/$Setting->{$temp}/g;
334 }
335 }
336 }
337}
338
339sub PreProcessRegionList
340{
341 my ($MEMORYSetting_href) = @_;
342 my $RegionListPath = &GetPath(&{$Func{GetChip}}(), RegionList);
343 my ($BasicRegionList_ref, $Index_ref) = &CommonUtil::ParseCSV($RegionListPath, undef);
344 my $RegionList_ref = $BasicRegionList_ref;
345 $RegionList_ref = &{$Func{SetRegionList}}($BasicRegionList_ref, $Index_ref, $MEMORYSetting_href)
346 if(exists $Func{SetRegionList});
347 return ($RegionList_ref, $Index_ref);
348}
349
350#****************************************************************************
351sub GenSECTIONS
352{
353 my $strLayout;
354 my ($RegionList_ref, $Index_ref) = &PreProcessRegionList(\%g_MEMORYSetting);
355 &SetHints_Symbols_Nearby_InputSections($RegionList_ref, $Index_ref);
356 my $LOADADDR_template;
357 my $LengthSymbol_template;
358 my $ASSERT_template;
359 my $End_template;
360 my $strPreviousType;
361 my @OVERLAY_items;
362 my $strOVERLAY_base;
363 foreach my $item (@$RegionList_ref)
364 {
365 my $strType = $item->[$Index_ref->{Type}];
366
367 if( $strPreviousType =~ /^OVERLAY$/i and ($strType !~ /^OVERLAY$/i or $strOVERLAY_base ne $item->[$Index_ref->{BaseRegion}]) )
368 {
369 my ($template, $strLOADADDR, $strLengthSymbol)= &FillOVERLAYSectionFrame(\@OVERLAY_items, $Index_ref);
370 $strLayout .=$template;
371 $LOADADDR_template .= $strLOADADDR;
372 $LengthSymbol_template .= $strLengthSymbol;
373 @OVERLAY_items = ();
374 $strOVERLAY_base = "";
375 }
376
377 if( $strType =~ /^OVERLAY$/i)
378 {
379 push @OVERLAY_items, $item;
380 $strOVERLAY_base = $item->[$Index_ref->{BaseRegion}];
381 }
382 elsif( $strType =~ /^SectionFrame$/i)
383 {
384 $strLayout .= &ProcessSection(&Gen_TEMPLATE_SECTION(), $item, $Index_ref);
385 $LOADADDR_template .= &Gen_TEMPLATE_LOADADDR($item, $Index_ref);
386 $LengthSymbol_template .= &Gen_TEMPLATE_LengthSymbol($item, $Index_ref);
387 $ASSERT_template .= &Gen_TEMPLATE_ASSERT($item, $Index_ref);
388 }
389 elsif($strType =~ /^ACTION$/i or $strType =~ /^ENDACTION$/i)
390 {
391 my $CMPLOption = $item->[$Index_ref->{CompileOption}];
392 my $FeatureOption = $item->[$Index_ref->{Condition}];
393 my @temp = map{ $_ if(($_ ne $strType) and ($_ ne $CMPLOption) and ($_ ne $FeatureOption)) } @$item;
394 my $strACTION = &CommonUtil::ConnetString(\@temp, ",", undef);
395 if($strACTION =~ /^ASSERT/ or $strACTION =~ /^\"\s*ASSERT/)
396 {
397 $strACTION =~ s/\"//g;
398 $strACTION =~ s/\,\s*/\,\"/;
399 $strACTION =~ s/\)$/\"\)/;
400 }
401 $End_template .= " $strACTION\n" if($strType=~/END/i);
402 $strLayout .= " $strACTION\n" if($strType!~/END/i);
403 }
404 elsif($strType =~/^LinkerSymbol$/i)
405 {
406 $strLayout .= &FillLinkerSymbol($item, $Index_ref);
407 }
408 $strPreviousType = $strType;
409 }
410 $strLayout .= $LOADADDR_template . $LengthSymbol_template . $ASSERT_template . $End_template;
411 return $strLayout;
412}
413
414
415sub AvoidOrphanSECTIONS
416{
417 my $strLayout;
418 my ($RegionList_ref, $Index_ref) = &PreProcessRegionList(\%g_MEMORYSetting);
419 &SetHints_Symbols_Nearby_InputSections($RegionList_ref, $Index_ref);
420 #my $LOADADDR_template;
421 #my $LengthSymbol_template;
422 #my $ASSERT_template;
423 #my $End_template;
424 my $strPreviousType;
425 my @OVERLAY_items;
426 my $strOVERLAY_base;
427 foreach my $item (@$RegionList_ref)
428 {
429 my $strType = $item->[$Index_ref->{Type}];
430
431 if( $strPreviousType =~ /^OVERLAY$/i and ($strType !~ /^OVERLAY$/i or $strOVERLAY_base ne $item->[$Index_ref->{BaseRegion}]) )
432 {
433 #@OVERLAY_items = ();
434 $strOVERLAY_base = "";
435 }
436
437 if( $strType =~ /^OVERLAY$/i)
438 {
439 #push @OVERLAY_items, $item;
440 $strOVERLAY_base = $item->[$Index_ref->{BaseRegion}];
441
442 my $strName = $item->[$Index_ref->{Name}];
443 next if ($strName =~ /\.text$|\.rodata$|.data$|\.bss$/);
444 $strName =~ s/#//g;
445 $strLayout .= " "x4 ."INVALID_INPUT_SECTION__$strName 0xDEAD0000 : { * ($strName); }\n";
446 }
447 elsif( $strType =~ /^SectionFrame$/i)
448 {
449 my $strName = $item->[$Index_ref->{Name}];
450 next if ($strName =~ /\.text$|\.rodata$|.data$|\.bss$|bss$/);
451 $strName =~ s/#//g;
452 $strLayout .= " "x4 ."INVALID_INPUT_SECTION__$strName 0xDEAD0000 : { * ($strName); }\n";
453 }
454 $strPreviousType = $strType;
455 }
456 #$strLayout .= "LONG(0);\n";
457 $strLayout = " "x4 ."\/\* If build fail with logs in link.log like this \n".
458 " "x12 ."\"section INVALID_INPUT_SECTION__XX_section_name loaded at [00000000,00000003] overlaps section ROM_GFH loaded at [00000000,000004af]\"\n".
459 " "x8 ."It means there are wrong input sections \"XX_section_name.\"\n".
460 " "x8 ."Please use correct input section name by following the rules in mcu/custom/system/Template/lds_config/InputSectionRule.txt\n".
461 " "x8 ."If you cannot find the symbol, please use \"\.\/m gendummy\" command.\n".
462 " "x8 ."A dummy sym file will be generated in bin folder. Search the keyword INVALID_INPUT_SECTION to find the symbol\n".
463 " "x4 ."\*\/\n".
464 $strLayout if(0);
465
466 return $strLayout;
467}
468
469sub FillLinkerSymbol #Called by GenSECTIONS()
470{
471 my ($Info_ref, $Index_ref) = @_;
472 my $template;
473 my $AttributeIndex = $Index_ref->{Attribute};
474 my $NameIndex = $Index_ref->{Name};
475 if($Info_ref->[$AttributeIndex] =~ /(\S+)::(\S+)/)
476 {
477 my $strPostfix = $2;
478 my $strPrefix = $1 =~ /EV/ ? "Image" : "Load";
479 if($strPostfix =~ /ZIBase/i)
480 {
481 $template = 'Image$$' . $Info_ref->[$NameIndex] . '$$ZI$$Base';
482 }
483 elsif($strPostfix =~ /ZILength/i)
484 {
485 $template = 'Image$$' . $Info_ref->[$NameIndex] . '$$ZI$$Length';
486 }
487 elsif($strPostfix =~ /ZILimit/i)
488 {
489 $template = 'Image$$' . $Info_ref->[$NameIndex] . '$$ZI$$Limit';
490 }
491 elsif($strPostfix =~ /Base/i)
492 {
493 $template = $strPrefix . '$$' . $Info_ref->[$NameIndex] . '$$Base';
494 }
495 elsif($strPostfix =~ /Length/i)
496 {
497 $template = 'Image$$' . $Info_ref->[$NameIndex] . '$$Length';
498 }
499 elsif($strPostfix =~ /Limit/i)
500 {
501 $template = 'Image$$' . $Info_ref->[$NameIndex] . '$$Limit';
502 }
503 my $VMA = $Info_ref->[$Index_ref->{VMA}];
504 return ' 'x4 . $template . " = $VMA;" . "\n";
505 }
506 return "";
507}
508sub FillOVERLAYSectionFrame #Called by GenSECTIONS()
509{
510 my ($Infos_ref, $Index_ref) = @_;
511 my ($OVERLAY_template, $strLOADADDR, $strLengthSymbol) = &Gen_TEMPLATE_OVERLAY($Infos_ref, $Index_ref);
512 my $template = &ProcessSection($OVERLAY_template, $Infos_ref->[0], $Index_ref);
513 return ($template, $strLOADADDR, $strLengthSymbol);
514}
515#****************************************************************************
516sub GenBaseRegionName # Called by ProcessSection()
517{
518 my ($Info_ref, $Index_ref) = @_;
519 my $strBaseRegion = $Info_ref->[$Index_ref->{BaseRegion}];
520 my $strOrgRegion = $Info_ref->[$Index_ref->{Name}];
521 my $strType = $Info_ref->[$Index_ref->{Type}];
522 my $strName = ($strBaseRegion eq "" or $strType =~ /^OVERLAY$/i) ? $strOrgRegion : $strBaseRegion;
523 $strName =~ s/\#//g; #workaround because .xxx can't be a folder name or a file name
524 return $strName;
525}
526sub GenRegionName # Called by ProcessSection()
527{
528 my ($Info_ref, $Index_ref) = @_;
529 my $strName = $Info_ref->[$Index_ref->{Name}];
530 $strName =~ s/\#//g; #workaround because .xxx can't be a folder name or a file name
531 $strName = ".bss" if($strName eq "bss");
532 return $strName;
533}
534sub GenVMA # Called by ProcessSection()
535{
536 my ($Info_ref, $Index_ref) = @_;
537 return $Info_ref->[$Index_ref->{VMA}];
538}
539sub GenLMA # Called by ProcessSection()
540{
541 my ($Info_ref, $Index_ref) = @_;
542 my $strLMA = "";
543 $strLMA = "AT($Info_ref->[$Index_ref->{LMA}])" if($Info_ref->[$Index_ref->{LMA}] ne "");
544 return $strLMA;
545}
546sub GenRegionAttr # Called by ProcessSection()
547{
548 my ($Info_ref, $Index_ref) = @_;
549 my $strAttr = "";
550 $strAttr = "(NOLOAD)" if($Info_ref->[$Index_ref->{Attribute}] eq "ZI");
551 return $strAttr;
552}
553sub GenInputSections # Called by ProcessSection()
554{
555 my ($Info_ref, $Index_ref) = @_;
556 my $RegionName = $Info_ref->[$Index_ref->{Name}];
557 my $InputSectionFolder = &GetPath($RegionName, InputSections);
558 my $InputSections;
559 my $SpecificChipPath = $InputSectionFolder.&{$Func{GetChip}}().".txt";
560 my $DefaultChipPath = $InputSectionFolder.ChipDependent_Default_InputSection.".txt";
561 my $HeadPath = $InputSectionFolder.HEAD_InputSection.".txt";
562 if(-e $HeadPath)
563 {
564 $InputSections = &CommonUtil::GetFileContent($HeadPath)."\n";
565 }
566 if(-e $SpecificChipPath)
567 {
568 $InputSections .= &CommonUtil::GetFileContent($SpecificChipPath)."\n";
569 }
570 elsif(-e $DefaultChipPath)
571 {
572 $InputSections .= &CommonUtil::GetFileContent($DefaultChipPath)."\n";
573 }
574 my $CommonPath = $InputSectionFolder.COMMON_InputSection.".txt";
575 $InputSections .= &CommonUtil::GetFileContent($CommonPath);
576 return $InputSections;
577}
578sub GenExecutionRegion # Called by ProcessSection()
579{
580 my ($Info_ref, $Index_ref) = @_;
581 my $ExecutionView = "";
582 $ExecutionView = " > $Info_ref->[$Index_ref->{ExecutionView}]" if($Info_ref->[$Index_ref->{ExecutionView}] ne "");
583 return $ExecutionView;
584}
585sub GenLoadRegion # Called by ProcessSection()
586{
587 my ($Info_ref, $Index_ref) = @_;
588 my $LoadView = "";
589 $LoadView = " AT> $Info_ref->[$Index_ref->{LoadView}]" if($Info_ref->[$Index_ref->{LoadView}] ne "");
590 return $LoadView;
591}
592sub GenALIGN # Called by ProcessSection()
593{
594 my ($Info_ref, $Index_ref) = @_;
595 my $strALIGN = "";
596 $strALIGN = "ALIGN(4)" if($Info_ref->[$Index_ref->{Type}] !~ /^OVERLAY$/i);
597 $strALIGN = $Info_ref->[$Index_ref->{ALIGN}] if($Info_ref->[$Index_ref->{ALIGN}] ne "");
598 return $strALIGN;
599}
600
601#****************************************************************************
602sub InsertBasicHintSymbols #used by SetHints_Symbols_Nearby_InputSections
603{
604 my ($RegionList_ref, $Index_ref, $Hints_ref) = @_;
605 $Index_ref->{Symbols} = keys %$Index_ref;
606 my $SymbolIndex = $Index_ref->{Symbols};
607 for(my $i=0; $i < scalar(@$RegionList_ref); $i++)
608 {
609 my $item = $RegionList_ref->[$i];
610 my $strType = $item->[$Index_ref->{Type}];
611 if( $strType =~ /^SectionFrame$/)
612 {
613 my %Symbols = ("Base"=>0, "Limit" =>1, "ZIBase"=>1, "ZILimit"=>1);
614 $item->[$SymbolIndex] = \%Symbols;
615 my $BaseRegion = $item->[$Index_ref->{BaseRegion}];
616 if($BaseRegion ne "")
617 {
618 $Hints_ref->{$BaseRegion} = [] if(!exists $Hints_ref->{$BaseRegion});
619 push(@{$Hints_ref->{$BaseRegion}}, $item);
620 }
621 }
622 }
623}
624sub SetHints_Symbols_Nearby_InputSections #called by GenSECTIONS()
625{
626 my ($RegionList_ref, $Index_ref) = @_;
627 my %Hints;
628 # Step1. insert 4 symbols and collect BaseRegion Info. into %Hints
629 &InsertBasicHintSymbols($RegionList_ref, $Index_ref, \%Hints);
630 # Step2. Remove Symbols
631 my $SymbolIndex = $Index_ref->{Symbols};
632 my $AttributeIndex = $Index_ref->{Attribute};
633 my $NameIndex = $Index_ref->{Name};
634 foreach my $items (values %Hints)
635 {
636 next if(!@$items);
637 for(my $i=0; $i< scalar(@$items); $i++)
638 {
639 my $CurrentItem = $items->[$i]->[$SymbolIndex];
640 my $CurrentAttr = $items->[$i]->[$AttributeIndex];
641 if($i==0)
642 {
643 my $NextAttr = $items->[$i+1]->[$AttributeIndex];
644 delete $CurrentItem->{ZILimit} if($CurrentAttr ne "ZI");
645 delete $CurrentItem->{ZIBase} if($CurrentAttr ne "ZI");
646 delete $CurrentItem->{Limit} if($NextAttr ne "ZI");
647 }
648 elsif($i==(scalar(@$items)-1))
649 {
650 my $PrevAttr = $items->[$i-1]->[$AttributeIndex];
651 delete $CurrentItem->{Base};
652 delete $CurrentItem->{Limit} if($CurrentAttr eq "ZI");
653 delete $CurrentItem->{ZIBase} if($PrevAttr eq "ZI");
654 }
655 else
656 {
657 my $NextAttr = $items->[$i+1]->[$AttributeIndex];
658 my $PrevAttr = $items->[$i-1]->[$AttributeIndex];
659 delete $CurrentItem->{Base};
660 delete $CurrentItem->{ZILimit};
661 delete $CurrentItem->{Limit} if(($CurrentAttr eq "ZI" and $PrevAttr ne "ZI")
662 or ($CurrentAttr ne "ZI" and $NextAttr ne "ZI"));
663 delete $CurrentItem->{ZIBase} if(($CurrentAttr eq "ZI" and $PrevAttr eq "ZI")
664 or ($CurrentAttr ne "ZI"));
665 }
666 }
667 }
668}
669#****************************************************************************
670sub GenSymbol_Before_InputSections # Gen_TEMPLATE_SECTION
671{
672 my ($Info_ref, $Index_ref) = @_;
673 my $template;
674 $template = &Gen_TEMPLATE_BaseSymbol($Info_ref, $Index_ref);
675 if($Info_ref->[$Index_ref->{Attribute}] eq "ZI")
676 {
677 my $LimitSymbol = &Gen_TEMPLATE_LimitSymbol($Info_ref, $Index_ref);
678 my $ZIBaseSymbol = &Gen_TEMPLATE_ZIBaseSymbol($Info_ref, $Index_ref);
679 my $break = "\n" if($template ne "" and $LimitSymbol ne "");
680 $template .= $break . $LimitSymbol;
681 $break = "\n";
682 $break = "" if($LimitSymbol eq "" or $ZIBaseSymbol eq "");
683 $template .= $break . $ZIBaseSymbol;
684 }
685 return $template;
686}
687sub GenSymbol_After_InputSections # Gen_TEMPLATE_SECTION
688{
689 my ($Info_ref, $Index_ref) = @_;
690 my $template;
691 my $break = "";
692 if($Info_ref->[$Index_ref->{Attribute}] ne "ZI")
693 {
694 $template = &Gen_TEMPLATE_LimitSymbol($Info_ref, $Index_ref);
695 my $ZIBaseSymbol = &Gen_TEMPLATE_ZIBaseSymbol($Info_ref, $Index_ref);
696 $break= "\n" if($template ne "" and $ZIBaseSymbol ne "");
697 $template .= $break. $ZIBaseSymbol;
698 $break = "";
699 }
700 my $ZILimitSymbol = &Gen_TEMPLATE_ZILimitSymbol($Info_ref, $Index_ref);
701 $break= "\n" if($template ne "" and $ZILimitSymbol ne "");
702 $template .= $break . $ZILimitSymbol;
703 return $template;
704}
705#****************************************************************************
706sub GenRORWInputSections # Gen_TEMPLATE_SECTION_IN_OVERLAY
707{
708 my ($Info_ref, $Index_ref) = @_;
709 return &GenInputSectionsByAttribute($Info_ref, $Index_ref, sub{ my ($file) = @_;
710 return $file if($file !~/ZI/);} );
711}
712sub GenZIInputSections # Gen_TEMPLATE_SECTION_IN_OVERLAY
713{
714 my ($Info_ref, $Index_ref) = @_;
715 return &GenInputSectionsByAttribute($Info_ref, $Index_ref, sub{ my ($file) = @_;
716 return $file if($file =~/ZI/);} );
717}
718sub GenInputSectionsByAttribute # used by GenRORWInputSections and GenZIInputSections
719{
720 my ($Info_ref, $Index_ref, $expr) = @_;
721 my $RegionName = $Info_ref->[$Index_ref->{Name}];
722 my $InputSectionFolder = &GetPath($RegionName, InputSections);
723 opendir( my $DIR, $InputSectionFolder) || &ldsFrame_die("Can't open $InputSectionFolder!", __FILE__, __LINE__);
724 my @FileList = grep { $expr->($_)=~/\.txt$|.csv$/ && -f "$InputSectionFolder$_" } readdir( $DIR );
725 closedir $DIR;
726 my $InputSections = undef;
727 if(scalar(@FileList)>0)
728 {
729 my ($strCommonPath, $strDefaultChipPath, $strChipDependentPath, $strHeadPath) = (undef, undef, undef, undef);
730 foreach my $file (@FileList)
731 {
732 my $strChip = &{$Func{GetChip}}();
733 my $filename = $file;
734 $filename =~ s/\.\S+$//;
735 my ($Common, $ChipDefault, $Head) = (COMMON_InputSection, ChipDependent_Default_InputSection, HEAD_InputSection);
736 $strChipDependentPath = $InputSectionFolder.$file if($filename =~/($strChip)$/);
737 $strCommonPath = $InputSectionFolder.$file if($filename =~/$Common/);
738 $strDefaultChipPath = $InputSectionFolder.$file if($filename =~/$ChipDefault/);
739 $strHeadPath = $InputSectionFolder.$file if($filename =~/$Head/);
740 }
741 if(-e $strHeadPath)
742 {
743 $InputSections = &CommonUtil::GetFileContent($strHeadPath)."\n";
744 }
745 if(-e $strChipDependentPath)
746 {
747 $InputSections .= &CommonUtil::GetFileContent($strChipDependentPath)."\n";
748 }
749 elsif(-e $strDefaultChipPath)
750 {
751 $InputSections .= &CommonUtil::GetFileContent($strDefaultChipPath)."\n";
752 }
753 $InputSections .= &CommonUtil::GetFileContent($strCommonPath);
754 }
755 return $InputSections;
756}
757#****************************************************************************
758sub Gen_TEMPLATE_SECTION # called by GenSECTIONS() and Gen_TEMPLATE_OVERLAY()
759{
760 my $template = <<"__TEMPLATE";
761 [ldsGen_RegionName] [ldsGen_VMA] [ldsGen_RegionAttr] : [ldsGen_LMA] [ldsGen_ALIGN]
762 {
763[ldsGen_Symbol_Before_InputSections]
764[ldsGen_InputSections]
765 . = ALIGN(4);
766[ldsGen_Symbol_After_InputSections]
767 } [ldsGen_ExecutionRegion] [ldsGen_LoadRegion]
768__TEMPLATE
769}
770sub Gen_TEMPLATE_SECTION_IN_OVERLAY # called by Gen_TEMPLATE_OVERLAY()
771{
772 my $template = <<"__TEMPLATE";
773 [ldsGen_RegionName]
774 {
775 Image\$\$[ldsGen_RegionName]\$\$Base = ADDR([ldsGen_RegionName]);
776[ldsGen_RORWInputSections]
777 . = ALIGN(4);
778 Image\$\$[ldsGen_RegionName]\$\$Limit = .;
779 Image\$\$[ldsGen_RegionName]\$\$ZI\$\$Base = .;
780[ldsGen_ZIInputSections]
781 . = ALIGN(4);
782 Image\$\$[ldsGen_RegionName]\$\$ZI\$\$Limit = .;
783 }
784__TEMPLATE
785}
786sub Gen_TEMPLATE_OVERLAY # called by FillOVERLAYSectionFrame()
787{
788 my ($Infos_ref, $Index_ref) = @_;
789 my $LOADADDR_template;
790 map { $LOADADDR_template .= &Gen_TEMPLATE_LOADADDR($_, $Index_ref)} @$Infos_ref;
791 my $strOVERLAY_SECTIONS;
792 map {$strOVERLAY_SECTIONS .= &ProcessSection(&Gen_TEMPLATE_SECTION_IN_OVERLAY(), $_, $Index_ref)}(@$Infos_ref);
793 my $LengthSymbol_template;
794 map { $LengthSymbol_template .= &Gen_TEMPLATE_LengthSymbol($_, $Index_ref)} @$Infos_ref;
795
796 my $template = <<"__TEMPLATE";
797 OVERLAY [ldsGen_VMA] [ldsGen_RegionAttr] : [ldsGen_LMA] [ldsGen_ALIGN]
798 {
799$strOVERLAY_SECTIONS
800 } [ldsGen_ExecutionRegion] [ldsGen_LoadRegion]
801__TEMPLATE
802 return ($template, $LOADADDR_template, $LengthSymbol_template);
803}
804sub Gen_TEMPLATE_LOADADDR # Called by GenSECTIONS and Gen_TEMPLATE_OVERLAY()
805{
806 my ($Info_ref, $Index_ref) = @_;
807 my $strBaseRegion = $Info_ref->[$Index_ref->{BaseRegion}];
808 my $strOrgRegion = $Info_ref->[$Index_ref->{Name}];
809 my $strType = $Info_ref->[$Index_ref->{Type}];
810 return "" if($strBaseRegion ne "" and $strBaseRegion ne $strOrgRegion and $strType !~ /^OVERLAY$/i);
811
812 my $strRegionName = &GenBaseRegionName($Info_ref, $Index_ref);
813 my $template = <<"__TEMPLATE";
814 Load\$\$$strRegionName\$\$Base = LOADADDR($strRegionName);
815__TEMPLATE
816 return $template;
817}
818sub Gen_TEMPLATE_LengthSymbol # Called by GenSECTIONS() and Gen_TEMPLATE_OVERLAY()
819{
820 my ($Info_ref, $Index_ref) = @_;
821 my $strBaseRegion = $Info_ref->[$Index_ref->{BaseRegion}];
822 my $strOrgRegion = $Info_ref->[$Index_ref->{Name}];
823 my $strType = $Info_ref->[$Index_ref->{Type}];
824 return "" if($strBaseRegion ne "" and $strBaseRegion ne $strOrgRegion and $strType !~ /^OVERLAY$/i);
825
826 my $strRegionName = &GenBaseRegionName($Info_ref, $Index_ref);
827 my $template = <<"__TEMPLATE";
828 Image\$\$$strRegionName\$\$Length = Image\$\$$strRegionName\$\$Limit - Image\$\$$strRegionName\$\$Base;
829 Image\$\$$strRegionName\$\$ZI\$\$Length = Image\$\$$strRegionName\$\$ZI\$\$Limit - Image\$\$$strRegionName\$\$ZI\$\$Base;
830__TEMPLATE
831 return $template;
832}
833sub Gen_TEMPLATE_ASSERT
834{
835 my ($Info_ref, $Index_ref) = @_;
836 my $strBaseRegion = $Info_ref->[$Index_ref->{BaseRegion}];
837 my $strOrgRegion = $Info_ref->[$Index_ref->{Name}];
838 my $strMaxSize = $Info_ref->[$Index_ref->{MaxSize}];
839 return "" if(($strBaseRegion ne "" and $strBaseRegion ne $strOrgRegion) or $strMaxSize eq "");
840
841 my $strRegionName = &GenBaseRegionName($Info_ref, $Index_ref);
842 my $ERRTitle = genERR::SYSERR_1_2;
843 my $template = <<"__TEMPLATE";
844 ASSERT( (Image\$\$$strRegionName\$\$Length + Image\$\$$strRegionName\$\$ZI\$\$Length ) <= $strMaxSize , \"$ERRTitle\Sizes of $strRegionName exceed $strMaxSize\")
845__TEMPLATE
846 return $template;
847}
848sub Gen_TEMPLATE_BaseSymbol # Called by GenSymbol_Before_InputSections()
849{
850 my ($Info_ref, $Index_ref) = @_;
851 return "" if(!exists $Info_ref->[$Index_ref->{Symbols}]->{Base});
852 my $strRegionName = &GenBaseRegionName($Info_ref, $Index_ref);
853 return ' ' x 8 . "Image\$\$$strRegionName\$\$Base = . ;";
854}
855sub Gen_TEMPLATE_LimitSymbol # Called by GenSymbol_(Before/After)_InputSections()
856{
857 my ($Info_ref, $Index_ref) = @_;
858 return "" if(!exists $Info_ref->[$Index_ref->{Symbols}]->{Limit});
859 my $strRegionName = &GenBaseRegionName($Info_ref, $Index_ref);
860 return ' ' x 8 . "Image\$\$$strRegionName\$\$Limit = . ;";
861}
862sub Gen_TEMPLATE_ZIBaseSymbol # Called by GenSymbol_(Before/After)_InputSections()
863{
864 my ($Info_ref, $Index_ref) = @_;
865 return "" if(!exists $Info_ref->[$Index_ref->{Symbols}]->{ZIBase});
866 my $strRegionName = &GenBaseRegionName($Info_ref, $Index_ref);
867 return ' ' x 8 . "Image\$\$$strRegionName\$\$ZI\$\$Base = . ;";
868}
869sub Gen_TEMPLATE_ZILimitSymbol # Called by GenSymbol_After_InputSections()
870{
871 my ($Info_ref, $Index_ref) = @_;
872 return "" if(!exists $Info_ref->[$Index_ref->{Symbols}]->{ZILimit});
873 my $strRegionName = &GenBaseRegionName($Info_ref, $Index_ref);
874 return ' ' x 8 . "Image\$\$$strRegionName\$\$ZI\$\$Limit = . ;";
875}
876
877#****************************************************************************
878# subroutine: ldsFrame_die
879# sample code: (message, __FILE__, __LINE__)
880# input: $error_msg, $file, $line_no
881#****************************************************************************
882sub ldsFrame_die
883{
884 my ($error_msg, $file, $line_no) = (@_);
885 &CommonUtil::error_handler($error_msg, $file, $line_no, 'ldsFrame');
886}