1## @file
2# process rule section generation
3#
4#  Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
5#
6#  SPDX-License-Identifier: BSD-2-Clause-Patent
7#
8
9##
10# Import Modules
11#
12from __future__ import absolute_import
13from struct import *
14from . import Section
15from .GenFdsGlobalVariable import GenFdsGlobalVariable
16import subprocess
17from .Ffs import SectionSuffix
18import Common.LongFilePathOs as os
19from CommonDataClass.FdfClass import EfiSectionClassObject
20from Common import EdkLogger
21from Common.BuildToolError import *
22from Common.Misc import PeImageClass
23from Common.LongFilePathSupport import OpenLongFilePath as open
24from Common.LongFilePathSupport import CopyLongFilePath
25from Common.DataType import *
26
27## generate rule section
28#
29#
30class EfiSection (EfiSectionClassObject):
31
32    ## The constructor
33    #
34    #   @param  self        The object pointer
35    #
36    def __init__(self):
37          EfiSectionClassObject.__init__(self)
38
39    ## GenSection() method
40    #
41    #   Generate rule section
42    #
43    #   @param  self        The object pointer
44    #   @param  OutputPath  Where to place output file
45    #   @param  ModuleName  Which module this section belongs to
46    #   @param  SecNum      Index of section
47    #   @param  KeyStringList  Filter for inputs of section generation
48    #   @param  FfsInf      FfsInfStatement object that contains this section data
49    #   @param  Dict        dictionary contains macro and its value
50    #   @retval tuple       (Generated file name list, section alignment)
51    #
52    def GenSection(self, OutputPath, ModuleName, SecNum, KeyStringList, FfsInf = None, Dict = None, IsMakefile = False) :
53
54        if self.FileName is not None and self.FileName.startswith('PCD('):
55            self.FileName = GenFdsGlobalVariable.GetPcdValue(self.FileName)
56        """Prepare the parameter of GenSection"""
57        if FfsInf is not None :
58            InfFileName = FfsInf.InfFileName
59            SectionType = FfsInf.__ExtendMacro__(self.SectionType)
60            Filename = FfsInf.__ExtendMacro__(self.FileName)
61            BuildNum = FfsInf.__ExtendMacro__(self.BuildNum)
62            StringData = FfsInf.__ExtendMacro__(self.StringData)
63            ModuleNameStr = FfsInf.__ExtendMacro__('$(MODULE_NAME)')
64            NoStrip = True
65            if FfsInf.ModuleType in (SUP_MODULE_SEC, SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM, SUP_MODULE_MM_CORE_STANDALONE) and SectionType in (BINARY_FILE_TYPE_TE, BINARY_FILE_TYPE_PE32):
66                if FfsInf.KeepReloc is not None:
67                    NoStrip = FfsInf.KeepReloc
68                elif FfsInf.KeepRelocFromRule is not None:
69                    NoStrip = FfsInf.KeepRelocFromRule
70                elif self.KeepReloc is not None:
71                    NoStrip = self.KeepReloc
72                elif FfsInf.ShadowFromInfFile is not None:
73                    NoStrip = FfsInf.ShadowFromInfFile
74        else:
75            EdkLogger.error("GenFds", GENFDS_ERROR, "Module %s apply rule for None!" %ModuleName)
76
77        """If the file name was pointed out, add it in FileList"""
78        FileList = []
79        if Dict is None:
80            Dict = {}
81        if Filename is not None:
82            Filename = GenFdsGlobalVariable.MacroExtend(Filename, Dict)
83            # check if the path is absolute or relative
84            if os.path.isabs(Filename):
85                Filename = os.path.normpath(Filename)
86            else:
87                Filename = os.path.normpath(os.path.join(FfsInf.EfiOutputPath, Filename))
88
89            if not self.Optional:
90                FileList.append(Filename)
91            elif os.path.exists(Filename):
92                FileList.append(Filename)
93            elif IsMakefile:
94                SuffixMap = FfsInf.GetFinalTargetSuffixMap()
95                if '.depex' in SuffixMap:
96                    FileList.append(Filename)
97        else:
98            FileList, IsSect = Section.Section.GetFileList(FfsInf, self.FileType, self.FileExtension, Dict, IsMakefile=IsMakefile, SectionType=SectionType)
99            if IsSect :
100                return FileList, self.Alignment
101
102        Index = 0
103        Align = self.Alignment
104
105        """ If Section type is 'VERSION'"""
106        OutputFileList = []
107        if SectionType == 'VERSION':
108
109            InfOverrideVerString = False
110            if FfsInf.Version is not None:
111                #StringData = FfsInf.Version
112                BuildNum = FfsInf.Version
113                InfOverrideVerString = True
114
115            if InfOverrideVerString:
116                #VerTuple = ('-n', '"' + StringData + '"')
117                if BuildNum is not None and BuildNum != '':
118                    BuildNumTuple = ('-j', BuildNum)
119                else:
120                    BuildNumTuple = tuple()
121
122                Num = SecNum
123                OutputFile = os.path.join( OutputPath, ModuleName + SUP_MODULE_SEC + str(Num) + SectionSuffix.get(SectionType))
124                GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_VERSION',
125                                                    #Ui=StringData,
126                                                    Ver=BuildNum,
127                                                    IsMakefile=IsMakefile)
128                OutputFileList.append(OutputFile)
129
130            elif FileList != []:
131                for File in FileList:
132                    Index = Index + 1
133                    Num = '%s.%d' %(SecNum, Index)
134                    OutputFile = os.path.join(OutputPath, ModuleName + SUP_MODULE_SEC + Num + SectionSuffix.get(SectionType))
135                    f = open(File, 'r')
136                    VerString = f.read()
137                    f.close()
138                    BuildNum = VerString
139                    if BuildNum is not None and BuildNum != '':
140                        BuildNumTuple = ('-j', BuildNum)
141                    GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_VERSION',
142                                                        #Ui=VerString,
143                                                        Ver=BuildNum,
144                                                        IsMakefile=IsMakefile)
145                    OutputFileList.append(OutputFile)
146
147            else:
148                BuildNum = StringData
149                if BuildNum is not None and BuildNum != '':
150                    BuildNumTuple = ('-j', BuildNum)
151                else:
152                    BuildNumTuple = tuple()
153                BuildNumString = ' ' + ' '.join(BuildNumTuple)
154
155                #if VerString == '' and
156                if BuildNumString == '':
157                    if self.Optional == True :
158                        GenFdsGlobalVariable.VerboseLogger( "Optional Section don't exist!")
159                        return [], None
160                    else:
161                        EdkLogger.error("GenFds", GENFDS_ERROR, "File: %s miss Version Section value" %InfFileName)
162                Num = SecNum
163                OutputFile = os.path.join( OutputPath, ModuleName + SUP_MODULE_SEC + str(Num) + SectionSuffix.get(SectionType))
164                GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_VERSION',
165                                                    #Ui=VerString,
166                                                    Ver=BuildNum,
167                                                    IsMakefile=IsMakefile)
168                OutputFileList.append(OutputFile)
169
170        #
171        # If Section Type is BINARY_FILE_TYPE_UI
172        #
173        elif SectionType == BINARY_FILE_TYPE_UI:
174
175            InfOverrideUiString = False
176            if FfsInf.Ui is not None:
177                StringData = FfsInf.Ui
178                InfOverrideUiString = True
179
180            if InfOverrideUiString:
181                Num = SecNum
182                if IsMakefile and StringData == ModuleNameStr:
183                    StringData = "$(MODULE_NAME)"
184                OutputFile = os.path.join( OutputPath, ModuleName + SUP_MODULE_SEC + str(Num) + SectionSuffix.get(SectionType))
185                GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_USER_INTERFACE',
186                                                     Ui=StringData, IsMakefile=IsMakefile)
187                OutputFileList.append(OutputFile)
188
189            elif FileList != []:
190                for File in FileList:
191                    Index = Index + 1
192                    Num = '%s.%d' %(SecNum, Index)
193                    OutputFile = os.path.join(OutputPath, ModuleName + SUP_MODULE_SEC + Num + SectionSuffix.get(SectionType))
194                    f = open(File, 'r')
195                    UiString = f.read()
196                    f.close()
197                    if IsMakefile and UiString == ModuleNameStr:
198                        UiString = "$(MODULE_NAME)"
199                    GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_USER_INTERFACE',
200                                                        Ui=UiString, IsMakefile=IsMakefile)
201                    OutputFileList.append(OutputFile)
202            else:
203                if StringData is not None and len(StringData) > 0:
204                    UiTuple = ('-n', '"' + StringData + '"')
205                else:
206                    UiTuple = tuple()
207
208                    if self.Optional == True :
209                        GenFdsGlobalVariable.VerboseLogger( "Optional Section don't exist!")
210                        return '', None
211                    else:
212                        EdkLogger.error("GenFds", GENFDS_ERROR, "File: %s miss UI Section value" %InfFileName)
213
214                Num = SecNum
215                if IsMakefile and StringData == ModuleNameStr:
216                    StringData = "$(MODULE_NAME)"
217                OutputFile = os.path.join( OutputPath, ModuleName + SUP_MODULE_SEC + str(Num) + SectionSuffix.get(SectionType))
218                GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_USER_INTERFACE',
219                                                     Ui=StringData, IsMakefile=IsMakefile)
220                OutputFileList.append(OutputFile)
221
222        #
223        # If Section Type is BINARY_FILE_TYPE_RAW
224        #
225        elif SectionType == BINARY_FILE_TYPE_RAW:
226            """If File List is empty"""
227            if FileList == []:
228                if self.Optional == True:
229                    GenFdsGlobalVariable.VerboseLogger("Optional Section don't exist!")
230                    return [], None
231                else:
232                    EdkLogger.error("GenFds", GENFDS_ERROR, "Output file for %s section could not be found for %s" % (SectionType, InfFileName))
233
234            elif len(FileList) > 1:
235                EdkLogger.error("GenFds", GENFDS_ERROR,
236                                "Files suffixed with %s are not allowed to have more than one file in %s[Binaries] section" % (
237                                self.FileExtension, InfFileName))
238            else:
239                for File in FileList:
240                    File = GenFdsGlobalVariable.MacroExtend(File, Dict)
241                    OutputFileList.append(File)
242
243        else:
244            """If File List is empty"""
245            if FileList == [] :
246                if self.Optional == True:
247                    GenFdsGlobalVariable.VerboseLogger("Optional Section don't exist!")
248                    return [], None
249                else:
250                    EdkLogger.error("GenFds", GENFDS_ERROR, "Output file for %s section could not be found for %s" % (SectionType, InfFileName))
251
252            else:
253                """Convert the File to Section file one by one """
254                for File in FileList:
255                    """ Copy Map file to FFS output path """
256                    Index = Index + 1
257                    Num = '%s.%d' %(SecNum, Index)
258                    OutputFile = os.path.join( OutputPath, ModuleName + SUP_MODULE_SEC + Num + SectionSuffix.get(SectionType))
259                    File = GenFdsGlobalVariable.MacroExtend(File, Dict)
260
261                    #Get PE Section alignment when align is set to AUTO
262                    if self.Alignment == 'Auto' and (SectionType == BINARY_FILE_TYPE_PE32 or SectionType == BINARY_FILE_TYPE_TE):
263                        ImageObj = PeImageClass (File)
264                        if ImageObj.SectionAlignment < 0x400:
265                            Align = str (ImageObj.SectionAlignment)
266                        elif ImageObj.SectionAlignment < 0x100000:
267                            Align = str (ImageObj.SectionAlignment // 0x400) + 'K'
268                        else:
269                            Align = str (ImageObj.SectionAlignment // 0x100000) + 'M'
270
271                    if File[(len(File)-4):] == '.efi' and FfsInf.InfModule.BaseName == os.path.basename(File)[:-4]:
272                        MapFile = File.replace('.efi', '.map')
273                        CopyMapFile = os.path.join(OutputPath, ModuleName + '.map')
274                        if IsMakefile:
275                            if GenFdsGlobalVariable.CopyList == []:
276                                GenFdsGlobalVariable.CopyList = [(MapFile, CopyMapFile)]
277                            else:
278                                GenFdsGlobalVariable.CopyList.append((MapFile, CopyMapFile))
279                        else:
280                            if os.path.exists(MapFile):
281                                if not os.path.exists(CopyMapFile) or \
282                                       (os.path.getmtime(MapFile) > os.path.getmtime(CopyMapFile)):
283                                    CopyLongFilePath(MapFile, CopyMapFile)
284
285                    if not NoStrip:
286                        FileBeforeStrip = os.path.join(OutputPath, ModuleName + '.efi')
287                        if IsMakefile:
288                            if GenFdsGlobalVariable.CopyList == []:
289                                GenFdsGlobalVariable.CopyList = [(File, FileBeforeStrip)]
290                            else:
291                                GenFdsGlobalVariable.CopyList.append((File, FileBeforeStrip))
292                        else:
293                            if not os.path.exists(FileBeforeStrip) or \
294                                (os.path.getmtime(File) > os.path.getmtime(FileBeforeStrip)):
295                                CopyLongFilePath(File, FileBeforeStrip)
296                        StrippedFile = os.path.join(OutputPath, ModuleName + '.stripped')
297                        GenFdsGlobalVariable.GenerateFirmwareImage(
298                                StrippedFile,
299                                [File],
300                                Strip=True,
301                                IsMakefile = IsMakefile
302                            )
303                        File = StrippedFile
304
305                    """For TE Section call GenFw to generate TE image"""
306
307                    if SectionType == BINARY_FILE_TYPE_TE:
308                        TeFile = os.path.join( OutputPath, ModuleName + 'Te.raw')
309                        GenFdsGlobalVariable.GenerateFirmwareImage(
310                                TeFile,
311                                [File],
312                                Type='te',
313                                IsMakefile = IsMakefile
314                            )
315                        File = TeFile
316
317                    """Call GenSection"""
318                    GenFdsGlobalVariable.GenerateSection(OutputFile,
319                                                        [File],
320                                                        Section.Section.SectionType.get (SectionType),
321                                                        IsMakefile=IsMakefile
322                                                        )
323                    OutputFileList.append(OutputFile)
324
325        return OutputFileList, Align
326