GenFds output message clarification for build ARCH.
[people/mcb30/basetools.git] / Source / Python / GenFds / FfsInfStatement.py
1 ## @file\r
2 # process FFS generation from INF statement\r
3 #\r
4 #  Copyright (c) 2007, Intel Corporation\r
5 #\r
6 #  All rights reserved. This program and the accompanying materials\r
7 #  are licensed and made available under the terms and conditions of the BSD License\r
8 #  which accompanies this distribution.  The full text of the license may be found at\r
9 #  http://opensource.org/licenses/bsd-license.php\r
10 #\r
11 #  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 #  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13 #\r
14 \r
15 ##\r
16 # Import Modules\r
17 #\r
18 import Rule\r
19 import os\r
20 import shutil\r
21 from GenFdsGlobalVariable import GenFdsGlobalVariable\r
22 import Ffs\r
23 import subprocess\r
24 import sys\r
25 import Section\r
26 import RuleSimpleFile\r
27 import RuleComplexFile\r
28 from CommonDataClass.FdfClass import FfsInfStatementClassObject\r
29 from Common.String import *\r
30 from Common import EdkLogger\r
31 from Common.BuildToolError import *\r
32 \r
33 ## generate FFS from INF\r
34 #\r
35 #\r
36 class FfsInfStatement(FfsInfStatementClassObject):\r
37     ## The constructor\r
38     #\r
39     #   @param  self        The object pointer\r
40     #\r
41     def __init__(self):\r
42         FfsInfStatementClassObject.__init__(self)\r
43         self.TargetOverrideList = []\r
44         self.ShadowFromInfFile = None\r
45         self.KeepRelocFromRule = None\r
46 \r
47     ## __InfParse() method\r
48     #\r
49     #   Parse inf file to get module information\r
50     #\r
51     #   @param  self        The object pointer\r
52     #   @param  Dict        dictionary contains macro and value pair\r
53     #\r
54     def __InfParse__(self, Dict = {}):\r
55         self.CurrentArch = self.GetCurrentArch()\r
56         #\r
57         # Get the InfClass object\r
58         #\r
59 \r
60         self.InfFileName = NormPath(self.InfFileName)\r
61         self.InfFileName = GenFdsGlobalVariable.MacroExtend(self.InfFileName, Dict, self.CurrentArch)\r
62         (self.SourceDir, InfName) = os.path.split(self.InfFileName)\r
63         if self.CurrentArch != None:\r
64 \r
65             Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[self.InfFileName, self.CurrentArch]\r
66             #\r
67             # Set Ffs BaseName, MdouleGuid, ModuleType, Version, OutputPath\r
68             #\r
69             self.BaseName = Inf.BaseName\r
70             self.ModuleGuid = Inf.Guid\r
71             self.ModuleType = Inf.ModuleType\r
72             if Inf.AutoGenVersion < 0x00010005:\r
73                 self.ModuleType = Inf.ComponentType\r
74             self.VersionString = Inf.Version\r
75             self.BinFileList = Inf.Binaries\r
76             if self.KeepReloc == None and Inf.Shadow:\r
77                 self.ShadowFromInfFile = Inf.Shadow\r
78 \r
79         else:\r
80             Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[self.InfFileName, 'COMMON']\r
81             self.BaseName = Inf.BaseName\r
82             self.ModuleGuid = Inf.Guid\r
83             self.ModuleType = Inf.ModuleType\r
84             self.VersionString = Inf.Version\r
85             self.BinFileList = Inf.Binaries\r
86             if self.BinFileList == []:\r
87                 EdkLogger.error("GenFds", GENFDS_ERROR,\r
88                                 "INF %s specified in FDF could not be found in build ARCH %s!" \\r
89                                 % (self.InfFileName, GenFdsGlobalVariable.ArchList))\r
90 \r
91         GenFdsGlobalVariable.VerboseLogger( "BaseName : %s" %self.BaseName)\r
92         GenFdsGlobalVariable.VerboseLogger("ModuleGuid : %s" %self.ModuleGuid)\r
93         GenFdsGlobalVariable.VerboseLogger("ModuleType : %s" %self.ModuleType)\r
94         GenFdsGlobalVariable.VerboseLogger("VersionString : %s" %self.VersionString)\r
95         GenFdsGlobalVariable.VerboseLogger("InfFileName :%s"  %self.InfFileName)\r
96 \r
97         #\r
98         # Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${MdouleName}\\r
99         #\r
100 \r
101         self.OutputPath = os.path.join(GenFdsGlobalVariable.FfsDir, \\r
102                                        self.ModuleGuid + self.BaseName)\r
103         if not os.path.exists(self.OutputPath) :\r
104             os.makedirs(self.OutputPath)\r
105 \r
106         self.EfiOutputPath = self.__GetEFIOutPutPath__()\r
107         GenFdsGlobalVariable.VerboseLogger( "ModuelEFIPath: " + self.EfiOutputPath)\r
108 \r
109     ## GenFfs() method\r
110     #\r
111     #   Generate FFS\r
112     #\r
113     #   @param  self        The object pointer\r
114     #   @param  Dict        dictionary contains macro and value pair\r
115     #   @retval string      Generated FFS file name\r
116     #\r
117     def GenFfs(self, Dict = {}):\r
118         #\r
119         # Parse Inf file get Module related information\r
120         #\r
121         GenFdsGlobalVariable.VerboseLogger( " Begine parsing INf file : %s" %self.InfFileName)\r
122 \r
123         self.InfFileName = self.InfFileName.replace('$(WORKSPACE)', '')\r
124         if self.InfFileName[0] == '\\' or self.InfFileName[0] == '/' :\r
125             self.InfFileName = self.InfFileName[1:]\r
126 \r
127 \r
128         self.__InfParse__(Dict)\r
129         #\r
130         # Get the rule of how to generate Ffs file\r
131         #\r
132         Rule = self.__GetRule__()\r
133         GenFdsGlobalVariable.VerboseLogger( "Packing binaries from inf file : %s" %self.InfFileName)\r
134         #FileType = Ffs.Ffs.ModuleTypeToFileType[Rule.ModuleType]\r
135         #\r
136         # For the rule only has simpleFile\r
137         #\r
138         if isinstance (Rule, RuleSimpleFile.RuleSimpleFile) :\r
139             SectionOutputList = self.__GenSimpleFileSection__(Rule)\r
140             FfsOutput = self.__GenSimpleFileFfs__(Rule, SectionOutputList)\r
141             return FfsOutput\r
142         #\r
143         # For Rule has ComplexFile\r
144         #\r
145         elif isinstance(Rule, RuleComplexFile.RuleComplexFile):\r
146             InputSectList, InputSectAlignments = self.__GenComplexFileSection__(Rule)\r
147             FfsOutput = self.__GenComplexFileFfs__(Rule, InputSectList, InputSectAlignments)\r
148 \r
149             return FfsOutput\r
150 \r
151     ## __ExtendMacro__() method\r
152     #\r
153     #   Replace macro with its value\r
154     #\r
155     #   @param  self        The object pointer\r
156     #   @param  String      The string to be replaced\r
157     #   @retval string      Macro replaced string\r
158     #\r
159     def __ExtendMacro__ (self, String):\r
160         MacroDict = {\r
161             '$(INF_OUTPUT)'  : self.EfiOutputPath,\r
162             '$(MODULE_NAME)' : self.BaseName,\r
163             '$(BUILD_NUMBER)': self.BuildNum,\r
164             '$(INF_VERSION)' : self.VersionString,\r
165             '$(NAMED_GUID)'  : self.ModuleGuid\r
166         }\r
167         String = GenFdsGlobalVariable.MacroExtend(String, MacroDict)\r
168         return String\r
169 \r
170     ## __GetRule__() method\r
171     #\r
172     #   Get correct rule for generating FFS for this INF\r
173     #\r
174     #   @param  self        The object pointer\r
175     #   @retval Rule        Rule object\r
176     #\r
177     def __GetRule__ (self) :\r
178         CurrentArchList = []\r
179         if self.CurrentArch == None:\r
180             CurrentArchList = ['common']\r
181         else:\r
182             CurrentArchList.append(self.CurrentArch)\r
183 \r
184         for CurrentArch in CurrentArchList:\r
185             RuleName = 'RULE'              + \\r
186                        '.'                 + \\r
187                        CurrentArch.upper() + \\r
188                        '.'                 + \\r
189                        self.ModuleType.upper()\r
190             if self.Rule != None:\r
191                 RuleName = RuleName + \\r
192                            '.'      + \\r
193                            self.Rule.upper()\r
194 \r
195             Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName)\r
196             if Rule != None:\r
197                 GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName)\r
198                 return Rule\r
199 \r
200         RuleName = 'RULE'      + \\r
201                    '.'         + \\r
202                    'COMMON'    + \\r
203                    '.'         + \\r
204                    self.ModuleType.upper()\r
205 \r
206         if self.Rule != None:\r
207             RuleName = RuleName + \\r
208                        '.'      + \\r
209                        self.Rule.upper()\r
210 \r
211         GenFdsGlobalVariable.VerboseLogger ('Trying to apply common rule %s for INF %s' % (RuleName, self.InfFileName))\r
212 \r
213         Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName)\r
214         if Rule != None:\r
215             GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName)\r
216             return Rule\r
217 \r
218         if Rule == None :\r
219             EdkLogger.error("GenFds", GENFDS_ERROR, 'Don\'t Find common rule %s for INF %s' \\r
220                             % (RuleName, self.InfFileName))\r
221 \r
222     ## __GetPlatformArchList__() method\r
223     #\r
224     #   Get Arch list this INF built under\r
225     #\r
226     #   @param  self        The object pointer\r
227     #   @retval list        Arch list\r
228     #\r
229     def __GetPlatformArchList__(self):\r
230         \r
231         InfFileKey = os.path.normpath(self.InfFileName)\r
232         DscArchList = []\r
233         PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'IA32']\r
234         if  PlatformDataBase != None:\r
235             if InfFileKey in PlatformDataBase.Modules:\r
236                 DscArchList.append ('IA32')\r
237 \r
238         PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'X64']\r
239         if  PlatformDataBase != None:\r
240             if InfFileKey in PlatformDataBase.Modules:\r
241                 DscArchList.append ('X64')\r
242 \r
243         PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'IPF']\r
244         if PlatformDataBase != None:\r
245             if InfFileKey in (PlatformDataBase.Modules):\r
246                 DscArchList.append ('IPF')\r
247 \r
248         return DscArchList\r
249 \r
250     ## GetCurrentArch() method\r
251     #\r
252     #   Get Arch list of the module from this INF is to be placed into flash\r
253     #\r
254     #   @param  self        The object pointer\r
255     #   @retval list        Arch list\r
256     #\r
257     def GetCurrentArch(self) :\r
258         \r
259         TargetArchList = GenFdsGlobalVariable.ArchList\r
260             \r
261         PlatformArchList = self.__GetPlatformArchList__()\r
262         \r
263         CurArchList = TargetArchList\r
264         if PlatformArchList != []:\r
265             CurArchList = list(set (TargetArchList) & set (PlatformArchList))\r
266         GenFdsGlobalVariable.VerboseLogger ("Valid target architecture(s) is : " + " ".join(CurArchList))\r
267         \r
268         ArchList = []\r
269         if self.KeyStringList != []:\r
270             for Key in self.KeyStringList:\r
271                 Key = GenFdsGlobalVariable.MacroExtend(Key)\r
272                 Target, Tag, Arch = Key.split('_')\r
273                 if Arch in CurArchList:\r
274                     ArchList.append(Arch)\r
275                 if Target not in self.TargetOverrideList:\r
276                     self.TargetOverrideList.append(Target)\r
277         else:\r
278             ArchList = CurArchList\r
279 \r
280         if len(ArchList) == 1:\r
281             Arch = ArchList[0]\r
282             return Arch\r
283         elif len(ArchList) > 1:\r
284             EdkLogger.error("GenFds", GENFDS_ERROR, "Module built under multiple ARCHs %s. Not able to determine which output to put into flash for Module %s !" % (str(ArchList), self.InfFileName))\r
285         else:\r
286             EdkLogger.error("GenFds", GENFDS_ERROR, "Module %s appears under ARCH %s in platform %s, but current target ARCH is %s, so NO build output could be put into flash." % (self.InfFileName, str(PlatformArchList), GenFdsGlobalVariable.ActivePlatform, str(TargetArchList)))\r
287 \r
288     ## __GetEFIOutPutPath__() method\r
289     #\r
290     #   Get the output path for generated files\r
291     #\r
292     #   @param  self        The object pointer\r
293     #   @retval string      Path that output files from this INF go to\r
294     #\r
295     def __GetEFIOutPutPath__(self):\r
296         Arch = ''\r
297         OutputPath = ''\r
298         (ModulePath, FileName) = os.path.split(self.InfFileName)\r
299         Index = FileName.find('.')\r
300         FileName = FileName[0:Index]\r
301         Arch = "NoneArch"\r
302         if self.CurrentArch != None:\r
303             Arch = self.CurrentArch\r
304 \r
305         OutputPath = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch],\r
306                                   Arch ,\r
307                                   ModulePath,\r
308                                   FileName,\r
309                                   'OUTPUT'\r
310                                   )\r
311         OutputPath = os.path.realpath(OutputPath)\r
312         return OutputPath\r
313 \r
314     ## __GenSimpleFileSection__() method\r
315     #\r
316     #   Generate section by specified file name or a list of files with file extension\r
317     #\r
318     #   @param  self        The object pointer\r
319     #   @param  Rule        The rule object used to generate section\r
320     #   @retval string      File name of the generated section file\r
321     #\r
322     def __GenSimpleFileSection__(self, Rule):\r
323         #\r
324         # Prepare the parameter of GenSection\r
325         #\r
326         FileList = []\r
327         OutputFileList = []\r
328         if Rule.FileName != None:\r
329             GenSecInputFile = self.__ExtendMacro__(Rule.FileName)\r
330         else:\r
331             FileList, IsSect = Section.Section.GetFileList(self, '', Rule.FileExtension)\r
332 \r
333         Index = 1\r
334         SectionType     = Rule.SectionType\r
335         NoStrip = True\r
336         if self.ModuleType in ('SEC', 'PEI_CORE', 'PEIM'):\r
337             if self.KeepReloc != None:\r
338                 NoStrip = self.KeepReloc\r
339             elif Rule.KeepReloc != None:\r
340                 NoStrip = Rule.KeepReloc\r
341             elif self.ShadowFromInfFile != None:\r
342                 NoStrip = self.ShadowFromInfFile\r
343 \r
344         if FileList != [] :\r
345             for File in FileList:\r
346 \r
347                 SecNum = '%d' %Index\r
348                 GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \\r
349                               Ffs.Ffs.SectionSuffix[SectionType] + 'SEC' + SecNum\r
350                 Index = Index + 1\r
351                 OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)\r
352 \r
353                 if not NoStrip:\r
354                     FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')\r
355                     if not os.path.exists(FileBeforeStrip) or \\r
356                         (os.path.getmtime(File) > os.path.getmtime(FileBeforeStrip)):\r
357                         shutil.copyfile(File, FileBeforeStrip)\r
358                     StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')\r
359                     GenFdsGlobalVariable.GenerateFirmwareImage(\r
360                                             StrippedFile,\r
361                                             [GenFdsGlobalVariable.MacroExtend(File, Dict, self.CurrentArch)],\r
362                                             Strip=True\r
363                                             )\r
364                     File = StrippedFile\r
365 \r
366                 if SectionType == 'TE':\r
367                     TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')\r
368                     GenFdsGlobalVariable.GenerateFirmwareImage(\r
369                                             TeFile,\r
370                                             [GenFdsGlobalVariable.MacroExtend(File, Dict, self.CurrentArch)],\r
371                                             Type='te'\r
372                                             )\r
373                     File = TeFile\r
374 \r
375                 GenFdsGlobalVariable.GenerateSection(OutputFile, [File], Section.Section.SectionType[SectionType])\r
376                 OutputFileList.append(OutputFile)\r
377         else:\r
378             SecNum = '%d' %Index\r
379             GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \\r
380                               Ffs.Ffs.SectionSuffix[SectionType] + 'SEC' + SecNum\r
381             OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)\r
382 \r
383             if not NoStrip:\r
384                 FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')\r
385                 if not os.path.exists(FileBeforeStrip) or \\r
386                     (os.path.getmtime(File) > os.path.getmtime(FileBeforeStrip)):\r
387                     shutil.copyfile(File, FileBeforeStrip)\r
388                 StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')\r
389                 GenFdsGlobalVariable.GenerateFirmwareImage(\r
390                                         StrippedFile,\r
391                                         [GenFdsGlobalVariable.MacroExtend(File, Dict, self.CurrentArch)],\r
392                                         Strip=True\r
393                                         )\r
394                 File = StrippedFile\r
395 \r
396             if SectionType == 'TE':\r
397                 TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')\r
398                 GenFdsGlobalVariable.GenerateFirmwareImage(\r
399                                         TeFile,\r
400                                         [GenFdsGlobalVariable.MacroExtend(File, Dict, self.CurrentArch)],\r
401                                         Type='te'\r
402                                         )\r
403                 GenSecInputFile = TeFile\r
404 \r
405             GenFdsGlobalVariable.GenerateSection(OutputFile, [GenSecInputFile], Section.Section.SectionType[SectionType])\r
406             OutputFileList.append(OutputFile)\r
407 \r
408         return OutputFileList\r
409 \r
410     ## __GenSimpleFileFfs__() method\r
411     #\r
412     #   Generate FFS\r
413     #\r
414     #   @param  self        The object pointer\r
415     #   @param  Rule        The rule object used to generate section\r
416     #   @param  InputFileList        The output file list from GenSection\r
417     #   @retval string      Generated FFS file name\r
418     #\r
419     def __GenSimpleFileFfs__(self, Rule, InputFileList):\r
420         FfsOutput = self.OutputPath                     + \\r
421                     os.sep                              + \\r
422                     self.__ExtendMacro__(Rule.NameGuid) + \\r
423                     '.ffs'\r
424 \r
425         GenFdsGlobalVariable.VerboseLogger(self.__ExtendMacro__(Rule.NameGuid))\r
426         InputSection = []\r
427         SectionAlignments = []\r
428         for InputFile in InputFileList:\r
429             InputSection.append(InputFile)\r
430             SectionAlignments.append(Rule.Alignment)\r
431 \r
432         GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputSection,\r
433                                          Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType],\r
434                                          self.NameGuid, Fixed=Rule.Fixed,\r
435                                          CheckSum=Rule.CheckSum, Align=Rule.Alignment,\r
436                                          SectionAlign=SectionAlignments\r
437                                         )\r
438         return FfsOutput\r
439 \r
440     ## __GenComplexFileSection__() method\r
441     #\r
442     #   Generate section by sections in Rule\r
443     #\r
444     #   @param  self        The object pointer\r
445     #   @param  Rule        The rule object used to generate section\r
446     #   @retval string      File name of the generated section file\r
447     #\r
448     def __GenComplexFileSection__(self, Rule):\r
449         if self.ModuleType in ('SEC', 'PEI_CORE', 'PEIM'):\r
450             if Rule.KeepReloc != None:\r
451                 self.KeepRelocFromRule = Rule.KeepReloc\r
452         SectFiles = []\r
453         SectAlignments = []\r
454         Index = 1\r
455         for Sect in Rule.SectionList:\r
456             SecIndex = '%d' %Index\r
457             SectList  = []\r
458             if Rule.KeyStringList != []:\r
459                 SectList, Align = Sect.GenSection(self.OutputPath , self.ModuleGuid, SecIndex, Rule.KeyStringList, self)\r
460             else :\r
461                 SectList, Align = Sect.GenSection(self.OutputPath , self.ModuleGuid, SecIndex, self.KeyStringList, self)\r
462             for SecName in  SectList :\r
463                 SectFiles.append(SecName)\r
464                 SectAlignments.append(Align)\r
465             Index = Index + 1\r
466         return SectFiles, SectAlignments\r
467 \r
468     ## __GenComplexFileFfs__() method\r
469     #\r
470     #   Generate FFS\r
471     #\r
472     #   @param  self        The object pointer\r
473     #   @param  Rule        The rule object used to generate section\r
474     #   @param  InputFileList        The output file list from GenSection\r
475     #   @retval string      Generated FFS file name\r
476     #\r
477     def __GenComplexFileFfs__(self, Rule, InputFile, Alignments):\r
478         FfsOutput = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs')\r
479         GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputFile,\r
480                                          Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType],\r
481                                          self.ModuleGuid, Fixed=Rule.Fixed,\r
482                                          CheckSum=Rule.CheckSum, Align=Rule.Alignment,\r
483                                          SectionAlign=Alignments\r
484                                         )\r
485         return FfsOutput\r
486 \r
487     ## __GetGenFfsCmdParameter__() method\r
488     #\r
489     #   Create parameter string for GenFfs\r
490     #\r
491     #   @param  self        The object pointer\r
492     #   @param  Rule        The rule object used to generate section\r
493     #   @retval tuple       (FileType, Fixed, CheckSum, Alignment)\r
494     #\r
495     def __GetGenFfsCmdParameter__(self, Rule):\r
496         result = tuple()\r
497         result += ('-t', Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType])\r
498         if Rule.Fixed != False:\r
499             result += ('-x',)\r
500         if Rule.CheckSum != False:\r
501             result += ('-s',)\r
502 \r
503         if Rule.Alignment != None and Rule.Alignment != '':\r
504             result += ('-a', Rule.Alignment)\r
505 \r
506         return result\r