1## @file
2# process GUIDed section generation
3#
4#  Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
5#
6#  This program and the accompanying materials
7#  are licensed and made available under the terms and conditions of the BSD License
8#  which accompanies this distribution.  The full text of the license may be found at
9#  http://opensource.org/licenses/bsd-license.php
10#
11#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13#
14
15##
16# Import Modules
17#
18import Section
19import subprocess
20from Ffs import Ffs
21import Common.LongFilePathOs as os
22from GenFdsGlobalVariable import GenFdsGlobalVariable
23from CommonDataClass.FdfClass import GuidSectionClassObject
24from Common import ToolDefClassObject
25import sys
26from Common import EdkLogger
27from Common.BuildToolError import *
28from FvImageSection import FvImageSection
29from Common.LongFilePathSupport import OpenLongFilePath as open
30from GenFds import FindExtendTool
31
32## generate GUIDed section
33#
34#
35class GuidSection(GuidSectionClassObject) :
36
37    ## The constructor
38    #
39    #   @param  self        The object pointer
40    #
41    def __init__(self):
42        GuidSectionClassObject.__init__(self)
43
44    ## GenSection() method
45    #
46    #   Generate GUIDed section
47    #
48    #   @param  self        The object pointer
49    #   @param  OutputPath  Where to place output file
50    #   @param  ModuleName  Which module this section belongs to
51    #   @param  SecNum      Index of section
52    #   @param  KeyStringList  Filter for inputs of section generation
53    #   @param  FfsInf      FfsInfStatement object that contains this section data
54    #   @param  Dict        dictionary contains macro and its value
55    #   @retval tuple       (Generated file name, section alignment)
56    #
57    def GenSection(self, OutputPath, ModuleName, SecNum, KeyStringList, FfsInf=None, Dict={}):
58        #
59        # Generate all section
60        #
61        self.KeyStringList = KeyStringList
62        self.CurrentArchList = GenFdsGlobalVariable.ArchList
63        if FfsInf != None:
64            self.Alignment = FfsInf.__ExtendMacro__(self.Alignment)
65            self.NameGuid = FfsInf.__ExtendMacro__(self.NameGuid)
66            self.SectionType = FfsInf.__ExtendMacro__(self.SectionType)
67            self.CurrentArchList = [FfsInf.CurrentArch]
68
69        SectFile = tuple()
70        SectAlign = []
71        Index = 0
72        MaxAlign = None
73        if self.FvAddr != []:
74            FvAddrIsSet = True
75        else:
76            FvAddrIsSet = False
77
78        if self.ProcessRequired in ("TRUE", "1"):
79            if self.FvAddr != []:
80                #no use FvAddr when the image is processed.
81                self.FvAddr = []
82            if self.FvParentAddr != None:
83                #no use Parent Addr when the image is processed.
84                self.FvParentAddr = None
85
86        for Sect in self.SectionList:
87            Index = Index + 1
88            SecIndex = '%s.%d' % (SecNum, Index)
89            # set base address for inside FvImage
90            if isinstance(Sect, FvImageSection):
91                if self.FvAddr != []:
92                    Sect.FvAddr = self.FvAddr.pop(0)
93                self.IncludeFvSection = True
94            elif isinstance(Sect, GuidSection):
95                Sect.FvAddr = self.FvAddr
96                Sect.FvParentAddr = self.FvParentAddr
97            ReturnSectList, align = Sect.GenSection(OutputPath, ModuleName, SecIndex, KeyStringList, FfsInf, Dict)
98            if isinstance(Sect, GuidSection):
99                if Sect.IncludeFvSection:
100                    self.IncludeFvSection = Sect.IncludeFvSection
101
102            if align != None:
103                if MaxAlign == None:
104                    MaxAlign = align
105                if GenFdsGlobalVariable.GetAlignment (align) > GenFdsGlobalVariable.GetAlignment (MaxAlign):
106                    MaxAlign = align
107            if ReturnSectList != []:
108                if align == None:
109                    align = "1"
110                for file in ReturnSectList:
111                    SectFile += (file,)
112                    SectAlign.append(align)
113
114        if MaxAlign != None:
115            if self.Alignment == None:
116                self.Alignment = MaxAlign
117            else:
118                if GenFdsGlobalVariable.GetAlignment (MaxAlign) > GenFdsGlobalVariable.GetAlignment (self.Alignment):
119                    self.Alignment = MaxAlign
120
121        OutputFile = OutputPath + \
122                     os.sep + \
123                     ModuleName + \
124                     'SEC' + \
125                     SecNum + \
126                     Ffs.SectionSuffix['GUIDED']
127        OutputFile = os.path.normpath(OutputFile)
128
129        ExternalTool = None
130        ExternalOption = None
131        if self.NameGuid != None:
132            ExternalTool, ExternalOption = FindExtendTool(self.KeyStringList, self.CurrentArchList, self.NameGuid)
133
134        #
135        # If not have GUID , call default
136        # GENCRC32 section
137        #
138        if self.NameGuid == None :
139            GenFdsGlobalVariable.VerboseLogger("Use GenSection function Generate CRC32 Section")
140            GenFdsGlobalVariable.GenerateSection(OutputFile, SectFile, Section.Section.SectionType[self.SectionType], InputAlign=SectAlign)
141            OutputFileList = []
142            OutputFileList.append(OutputFile)
143            return OutputFileList, self.Alignment
144        #or GUID not in External Tool List
145        elif ExternalTool == None:
146            EdkLogger.error("GenFds", GENFDS_ERROR, "No tool found with GUID %s" % self.NameGuid)
147        else:
148            DummyFile = OutputFile + ".dummy"
149            #
150            # Call GenSection with DUMMY section type.
151            #
152            GenFdsGlobalVariable.GenerateSection(DummyFile, SectFile, InputAlign=SectAlign)
153            #
154            # Use external tool process the Output
155            #
156            TempFile = OutputPath + \
157                       os.sep + \
158                       ModuleName + \
159                       'SEC' + \
160                       SecNum + \
161                       '.tmp'
162            TempFile = os.path.normpath(TempFile)
163            #
164            # Remove temp file if its time stamp is older than dummy file
165            # Just in case the external tool fails at this time but succeeded before
166            # Error should be reported if the external tool does not generate a new output based on new input
167            #
168            if os.path.exists(TempFile) and os.path.exists(DummyFile) and os.path.getmtime(TempFile) < os.path.getmtime(DummyFile):
169                os.remove(TempFile)
170
171            FirstCall = False
172            CmdOption = '-e'
173            if ExternalOption != None:
174                CmdOption = CmdOption + ' ' + ExternalOption
175            if self.ProcessRequired not in ("TRUE", "1") and self.IncludeFvSection and not FvAddrIsSet and self.FvParentAddr != None:
176                #FirstCall is only set for the encapsulated flash FV image without process required attribute.
177                FirstCall = True
178            #
179            # Call external tool
180            #
181            ReturnValue = [1]
182            if FirstCall:
183                #first try to call the guided tool with -z option and CmdOption for the no process required guided tool.
184                GenFdsGlobalVariable.GuidTool(TempFile, [DummyFile], ExternalTool, '-z' + ' ' + CmdOption, ReturnValue)
185
186            #
187            # when no call or first call failed, ReturnValue are not 1.
188            # Call the guided tool with CmdOption
189            #
190            if ReturnValue[0] != 0:
191                FirstCall = False
192                ReturnValue[0] = 0
193                GenFdsGlobalVariable.GuidTool(TempFile, [DummyFile], ExternalTool, CmdOption)
194            #
195            # There is external tool which does not follow standard rule which return nonzero if tool fails
196            # The output file has to be checked
197            #
198            if not os.path.exists(TempFile):
199                EdkLogger.error("GenFds", COMMAND_FAILURE, 'Fail to call %s, no output file was generated' % ExternalTool)
200
201            FileHandleIn = open(DummyFile, 'rb')
202            FileHandleIn.seek(0, 2)
203            InputFileSize = FileHandleIn.tell()
204
205            FileHandleOut = open(TempFile, 'rb')
206            FileHandleOut.seek(0, 2)
207            TempFileSize = FileHandleOut.tell()
208
209            Attribute = []
210            HeaderLength = None
211            if self.ExtraHeaderSize != -1:
212                HeaderLength = str(self.ExtraHeaderSize)
213
214            if self.ProcessRequired == "NONE" and HeaderLength == None:
215                if TempFileSize > InputFileSize:
216                    FileHandleIn.seek(0)
217                    BufferIn = FileHandleIn.read()
218                    FileHandleOut.seek(0)
219                    BufferOut = FileHandleOut.read()
220                    if BufferIn == BufferOut[TempFileSize - InputFileSize:]:
221                        HeaderLength = str(TempFileSize - InputFileSize)
222                #auto sec guided attribute with process required
223                if HeaderLength == None:
224                    Attribute.append('PROCESSING_REQUIRED')
225
226            FileHandleIn.close()
227            FileHandleOut.close()
228
229            if FirstCall and 'PROCESSING_REQUIRED' in Attribute:
230                # Guided data by -z option on first call is the process required data. Call the guided tool with the real option.
231                GenFdsGlobalVariable.GuidTool(TempFile, [DummyFile], ExternalTool, CmdOption)
232
233            #
234            # Call Gensection Add Section Header
235            #
236            if self.ProcessRequired in ("TRUE", "1"):
237                if 'PROCESSING_REQUIRED' not in Attribute:
238                    Attribute.append('PROCESSING_REQUIRED')
239
240            if self.AuthStatusValid in ("TRUE", "1"):
241                Attribute.append('AUTH_STATUS_VALID')
242            GenFdsGlobalVariable.GenerateSection(OutputFile, [TempFile], Section.Section.SectionType['GUIDED'],
243                                                 Guid=self.NameGuid, GuidAttr=Attribute, GuidHdrLen=HeaderLength)
244            OutputFileList = []
245            OutputFileList.append(OutputFile)
246            if 'PROCESSING_REQUIRED' in Attribute:
247                # reset guided section alignment to none for the processed required guided data
248                self.Alignment = None
249                self.IncludeFvSection = False
250                self.ProcessRequired = "TRUE"
251            return OutputFileList, self.Alignment
252
253
254
255