Changed GenFds to use database based module/package/platform information retrieval...
[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 \r
31 ## generate FFS from INF\r
32 #\r
33 #\r
34 class FfsInfStatement(FfsInfStatementClassObject):\r
35     ## The constructor\r
36     #\r
37     #   @param  self        The object pointer\r
38     #\r
39     def __init__(self):\r
40         FfsInfStatementClassObject.__init__(self)\r
41         self.TargetOverrideList = []\r
42         self.ShadowFromInfFile = None\r
43         self.KeepRelocFromRule = None\r
44 \r
45     ## __InfParse() method\r
46     #\r
47     #   Parse inf file to get module information\r
48     #\r
49     #   @param  self        The object pointer\r
50     #   @param  Dict        dictionary contains macro and value pair\r
51     #    \r
52     def __InfParse__(self, Dict = {}):\r
53         self.CurrentArch = self.GetCurrentArch()\r
54         #\r
55         # Get the InfClass object\r
56         #\r
57 \r
58         self.InfFileName = NormPath(self.InfFileName)\r
59         self.InfFileName = GenFdsGlobalVariable.MacroExtend(self.InfFileName, Dict, self.CurrentArch)\r
60         (self.SourceDir, InfName) = os.path.split(self.InfFileName)\r
61         if self.CurrentArch != None:\r
62             \r
63             Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[self.InfFileName, self.CurrentArch]\r
64             #\r
65             # Set Ffs BaseName, MdouleGuid, ModuleType, Version, OutputPath\r
66             #\r
67             self.BaseName = Inf.BaseName\r
68             self.ModuleGuid = Inf.Guid\r
69             self.ModuleType = Inf.ModuleType\r
70             if Inf.AutoGenVersion < 0x00010005:\r
71                 self.ModuleType = Inf.ComponentType\r
72             self.VersionString = Inf.Version\r
73             self.BinFileList = Inf.Binaries\r
74             if self.KeepReloc == None and Inf.Shadow:\r
75                 self.ShadowFromInfFile = Inf.Shadow\r
76         \r
77         else:\r
78             Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[self.InfFileName, 'COMMON']\r
79             self.BaseName = Inf.BaseName\r
80             self.ModuleGuid = Inf.Guid\r
81             self.ModuleType = Inf.ModuleType\r
82             self.VersionString = Inf.Version\r
83             self.BinFileList = Inf.Binaries\r
84             if self.BinFileList == []:\r
85                 raise Exception ("INF %s specified in FDF could not be found in build ARCH %s!" % (self.InfFileName, GenFdsGlobalVariable.ArchList))\r
86                 sys.exit(1)\r
87         \r
88         GenFdsGlobalVariable.VerboseLogger( "BaseName : %s" %self.BaseName)\r
89         GenFdsGlobalVariable.VerboseLogger("ModuleGuid : %s" %self.ModuleGuid)\r
90         GenFdsGlobalVariable.VerboseLogger("ModuleType : %s" %self.ModuleType)\r
91         GenFdsGlobalVariable.VerboseLogger("VersionString : %s" %self.VersionString)\r
92         GenFdsGlobalVariable.VerboseLogger("InfFileName :%s"  %self.InfFileName)\r
93         \r
94         #\r
95         # Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${MdouleName}\\r
96         #\r
97 \r
98         self.OutputPath = os.path.join(GenFdsGlobalVariable.FfsDir, \\r
99                                        self.ModuleGuid + self.BaseName)\r
100         if not os.path.exists(self.OutputPath) :\r
101             os.makedirs(self.OutputPath)\r
102             \r
103         self.EfiOutputPath = self.__GetEFIOutPutPath__()\r
104         GenFdsGlobalVariable.VerboseLogger( "ModuelEFIPath: " + self.EfiOutputPath)\r
105     \r
106     ## GenFfs() method\r
107     #\r
108     #   Generate FFS\r
109     #\r
110     #   @param  self        The object pointer\r
111     #   @param  Dict        dictionary contains macro and value pair\r
112     #   @retval string      Generated FFS file name\r
113     #                          \r
114     def GenFfs(self, Dict = {}):\r
115         #\r
116         # Parse Inf file get Module related information\r
117         #\r
118         GenFdsGlobalVariable.VerboseLogger( " Begine parsing INf file : %s" %self.InfFileName)\r
119         \r
120         self.InfFileName = self.InfFileName.replace('$(WORKSPACE)', '')\r
121         if self.InfFileName[0] == '\\' or self.InfFileName[0] == '/' :\r
122             self.InfFileName = self.InfFileName[1:]\r
123         \r
124  \r
125         self.__InfParse__(Dict)\r
126         #\r
127         # Get the rule of how to generate Ffs file\r
128         #\r
129         Rule = self.__GetRule__()\r
130         GenFdsGlobalVariable.VerboseLogger( "Packing binaries from inf file : %s" %self.InfFileName)\r
131         #FileType = Ffs.Ffs.ModuleTypeToFileType[Rule.ModuleType]\r
132         #\r
133         # For the rule only has simpleFile\r
134         #\r
135         if isinstance (Rule, RuleSimpleFile.RuleSimpleFile) :\r
136             SectionOutputList = self.__GenSimpleFileSection__(Rule)\r
137             FfsOutput = self.__GenSimpleFileFfs__(Rule, SectionOutputList)\r
138             return FfsOutput\r
139         #\r
140         # For Rule has ComplexFile\r
141         #\r
142         elif isinstance(Rule, RuleComplexFile.RuleComplexFile):\r
143            \r
144             InputSectList = self.__GenComplexFileSection__(Rule)\r
145             FfsOutput = self.__GenComplexFileFfs__(Rule, InputSectList)\r
146             \r
147             return FfsOutput\r
148                 \r
149     ## __ExtendMacro__() method\r
150     #\r
151     #   Replace macro with its value\r
152     #\r
153     #   @param  self        The object pointer\r
154     #   @param  String      The string to be replaced\r
155     #   @retval string      Macro replaced string\r
156     # \r
157     def __ExtendMacro__ (self, String):\r
158         MacroDict = {\r
159             '$(INF_OUTPUT)'  : self.EfiOutputPath,\r
160             '$(MODULE_NAME)' : self.BaseName,\r
161             '$(BUILD_NUMBER)': self.BuildNum,\r
162             '$(INF_VERSION)' : self.VersionString,\r
163             '$(NAMED_GUID)'  : self.ModuleGuid        \r
164         }\r
165         String = GenFdsGlobalVariable.MacroExtend(String, MacroDict)\r
166         return String\r
167 \r
168     ## __GetRule__() method\r
169     #\r
170     #   Get correct rule for generating FFS for this INF\r
171     #\r
172     #   @param  self        The object pointer\r
173     #   @retval Rule        Rule object\r
174     # \r
175     def __GetRule__ (self) :\r
176         CurrentArchList = []\r
177         if self.CurrentArch == None:\r
178             CurrentArchList = ['common']\r
179         else:\r
180             CurrentArchList.append(self.CurrentArch)\r
181         \r
182         for CurrentArch in CurrentArchList:\r
183             RuleName = 'RULE'              + \\r
184                        '.'                 + \\r
185                        CurrentArch.upper() + \\r
186                        '.'                 + \\r
187                        self.ModuleType.upper()\r
188             if self.Rule != None:\r
189                 RuleName = RuleName + \\r
190                            '.'      + \\r
191                            self.Rule.upper()\r
192                            \r
193             Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName)\r
194             if Rule != None:\r
195                 GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName)\r
196                 return Rule\r
197             \r
198         RuleName = 'RULE'      + \\r
199                    '.'         + \\r
200                    'COMMON'    + \\r
201                    '.'         + \\r
202                    self.ModuleType.upper()\r
203         \r
204         if self.Rule != None:\r
205             RuleName = RuleName + \\r
206                        '.'      + \\r
207                        self.Rule.upper()\r
208                        \r
209         GenFdsGlobalVariable.VerboseLogger ('Trying to apply common rule %s for INF %s' % (RuleName, self.InfFileName))               \r
210         \r
211         Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName)\r
212         if Rule != None:\r
213             GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName)\r
214             return Rule\r
215 \r
216         if Rule == None :\r
217             raise Exception ('Don\'t Find common rule %s for INF %s' % (RuleName, self.InfFileName))\r
218 \r
219     ## __GetPlatformArchList__() method\r
220     #\r
221     #   Get Arch list this INF built under\r
222     #\r
223     #   @param  self        The object pointer\r
224     #   @retval list        Arch list\r
225     # \r
226     def __GetPlatformArchList__(self):\r
227         TargetArchList = GenFdsGlobalVariable.ArchList\r
228         if len(TargetArchList) == 0:\r
229             TargetArchList = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'COMMON'].SupArchList\r
230         else:\r
231             TargetArchList = set(GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'COMMON'].SupArchList) & set(TargetArchList)\r
232             \r
233         InfFileKey = os.path.normpath(self.InfFileName)\r
234         DscArchList = []\r
235         PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'IA32']\r
236         if  PlatformDataBase != None:\r
237             if InfFileKey in PlatformDataBase.Modules:\r
238                 DscArchList.append ('IA32')\r
239                 \r
240         PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'X64']\r
241         if  PlatformDataBase != None:\r
242             if InfFileKey in PlatformDataBase.Modules:\r
243                 DscArchList.append ('X64')\r
244                 \r
245         PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'IPF']\r
246         if PlatformDataBase != None:\r
247             if InfFileKey in (PlatformDataBase.Modules):\r
248                 DscArchList.append ('IPF')\r
249 \r
250         CurArchList = TargetArchList\r
251         if DscArchList != []:\r
252             CurArchList = set (TargetArchList) & set (DscArchList)\r
253         GenFdsGlobalVariable.VerboseLogger ("Valid target architecture(s) is : " + " ".join(CurArchList))\r
254         return list(CurArchList)\r
255     \r
256     ## GetCurrentArch() method\r
257     #\r
258     #   Get Arch list of the module from this INF is to be placed into flash\r
259     #\r
260     #   @param  self        The object pointer\r
261     #   @retval list        Arch list\r
262     # \r
263     def GetCurrentArch(self) :\r
264         CurArchList = self.__GetPlatformArchList__()\r
265         ArchList = []\r
266         if self.KeyStringList != []:\r
267             for Key in self.KeyStringList:\r
268                 Key = GenFdsGlobalVariable.MacroExtend(Key)\r
269                 Target, Tag, Arch = Key.split('_')\r
270                 if Arch in CurArchList:\r
271                     ArchList.append(Arch)\r
272                 if Target not in self.TargetOverrideList:\r
273                     self.TargetOverrideList.append(Target)\r
274         else:\r
275             ArchList = CurArchList\r
276                 \r
277         if len(ArchList) == 1:\r
278             Arch = ArchList[0]\r
279             return Arch\r
280         elif len(ArchList) > 1:\r
281             raise Exception("Not able to determine ARCH for Module %s !" %self.InfFileName) \r
282         else:\r
283             raise Exception("Don't find legal ARCH in Module %s !" %self.InfFileName)\r
284     \r
285     ## __GetEFIOutPutPath__() method\r
286     #\r
287     #   Get the output path for generated files\r
288     #\r
289     #   @param  self        The object pointer\r
290     #   @retval string      Path that output files from this INF go to\r
291     # \r
292     def __GetEFIOutPutPath__(self):\r
293         Arch = ''\r
294         OutputPath = ''\r
295         (ModulePath, FileName) = os.path.split(self.InfFileName)\r
296         Index = FileName.find('.')\r
297         FileName = FileName[0:Index]\r
298         Arch = "NoneArch"\r
299         if self.CurrentArch != None:\r
300             Arch = self.CurrentArch\r
301         \r
302         OutputPath = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch],\r
303                                   Arch ,\r
304                                   ModulePath,\r
305                                   FileName,\r
306                                   'OUTPUT'\r
307                                   )\r
308         OutputPath = os.path.realpath(OutputPath)\r
309         return OutputPath\r
310     \r
311     ## __GenSimpleFileSection__() method\r
312     #\r
313     #   Generate section by specified file name or a list of files with file extension\r
314     #\r
315     #   @param  self        The object pointer\r
316     #   @param  Rule        The rule object used to generate section\r
317     #   @retval string      File name of the generated section file\r
318     #     \r
319     def __GenSimpleFileSection__(self, Rule):\r
320         #\r
321         # Prepare the parameter of GenSection\r
322         #\r
323         FileList = []\r
324         OutputFileList = []\r
325         if Rule.FileName != None:\r
326             GenSecInputFile = self.__ExtendMacro__(Rule.FileName)\r
327         else:\r
328             FileList, IsSect = Section.Section.GetFileList(self, '', Rule.FileExtension)\r
329 \r
330         Index = 1\r
331         SectionType     = Rule.SectionType\r
332         NoStrip = True\r
333         if self.ModuleType in ('SEC', 'PEI_CORE', 'PEIM'):\r
334             if self.KeepReloc != None:\r
335                 NoStrip = self.KeepReloc\r
336             elif Rule.KeepReloc != None:\r
337                 NoStrip = Rule.KeepReloc\r
338             elif self.ShadowFromInfFile != None:\r
339                 NoStrip = self.ShadowFromInfFile\r
340                 \r
341         if FileList != [] :\r
342             for File in FileList:\r
343                 \r
344                 SecNum = '%d' %Index\r
345                 GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \\r
346                               Ffs.Ffs.SectionSuffix[SectionType] + 'SEC' + SecNum   \r
347                 Index = Index + 1             \r
348                 OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)\r
349                 \r
350                 if not NoStrip:\r
351                     FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')\r
352                     if os.path.exists(FileBeforeStrip):\r
353                         os.remove(FileBeforeStrip)\r
354                     shutil.copyfile(File, FileBeforeStrip)\r
355                     StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')\r
356                     StripCmd = (\r
357                         'GenFw',\r
358                         '-l',\r
359                         '-o', StrippedFile,\r
360                         GenFdsGlobalVariable.MacroExtend(File, Dict, self.CurrentArch),\r
361                         )\r
362                     GenFdsGlobalVariable.CallExternalTool(StripCmd, "Strip Failed !")\r
363                     File = StrippedFile\r
364                     \r
365                 if SectionType == 'TE':\r
366                     TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')\r
367                     GenTeCmd = (\r
368                         'GenFw',\r
369                         '-t',\r
370                         '-o', TeFile,\r
371                         GenFdsGlobalVariable.MacroExtend(File, Dict, self.CurrentArch),\r
372                         )\r
373                     GenFdsGlobalVariable.CallExternalTool(GenTeCmd, "GenFw Failed !")\r
374                     File = TeFile\r
375                 \r
376                 GenSectionCmd = (\r
377                     'GenSec',\r
378                     '-o', OutputFile,\r
379                     '-s', Section.Section.SectionType[SectionType],\r
380                     File,\r
381                     )\r
382                 #\r
383                 # Call GenSection\r
384                 #\r
385                 GenFdsGlobalVariable.CallExternalTool(GenSectionCmd, "Gen section Failed!")\r
386                 OutputFileList.append(OutputFile)\r
387         else:\r
388             SecNum = '%d' %Index\r
389             GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \\r
390                               Ffs.Ffs.SectionSuffix[SectionType] + 'SEC' + SecNum\r
391             OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)\r
392             \r
393             if not NoStrip:\r
394                 FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')\r
395                 shutil.copyfile(File, FileBeforeStrip)\r
396                 StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')\r
397                 StripCmd = (\r
398                     'GenFw',\r
399                     '-l',\r
400                     '-o', StrippedFile,\r
401                     GenFdsGlobalVariable.MacroExtend(File, Dict, self.CurrentArch),\r
402                     )\r
403                 GenFdsGlobalVariable.CallExternalTool(StripCmd, "Strip Failed !")\r
404                 File = StrippedFile\r
405             \r
406             if SectionType == 'TE':\r
407                 TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')\r
408                 GenTeCmd = (\r
409                     'GenFw',\r
410                     '-t',\r
411                     '-o', TeFile,\r
412                     GenFdsGlobalVariable.MacroExtend(File, Dict, self.CurrentArch),\r
413                     )\r
414                 GenFdsGlobalVariable.CallExternalTool(GenTeCmd, "GenFw Failed !")\r
415                 GenSecInputFile = TeFile\r
416             \r
417             GenSectionCmd = (\r
418                 'GenSec',\r
419                 '-o', OutputFile,\r
420                 '-s', Section.Section.SectionType[SectionType],\r
421                 GenSecInputFile,\r
422                 )\r
423             #\r
424             # Call GenSection\r
425             #\r
426             GenFdsGlobalVariable.CallExternalTool(GenSectionCmd, "Gen section Failed!")\r
427             OutputFileList.append(OutputFile)\r
428 \r
429         return OutputFileList\r
430     \r
431     ## __GenSimpleFileFfs__() method\r
432     #\r
433     #   Generate FFS\r
434     #\r
435     #   @param  self        The object pointer\r
436     #   @param  Rule        The rule object used to generate section\r
437     #   @param  InputFileList        The output file list from GenSection\r
438     #   @retval string      Generated FFS file name\r
439     #\r
440     def __GenSimpleFileFfs__(self, Rule, InputFileList):\r
441         #\r
442         # Prepare the parameter of GenFfs\r
443         #\r
444         CmdParams = self.__GetGenFfsCmdParameter__(Rule)\r
445 \r
446         FfsOutput = self.OutputPath                     + \\r
447                     os.sep                              + \\r
448                     self.__ExtendMacro__(Rule.NameGuid) + \\r
449                     '.ffs'\r
450 \r
451         GenFdsGlobalVariable.VerboseLogger(self.__ExtendMacro__(Rule.NameGuid))\r
452         InputSection = tuple()\r
453         for InputFile in InputFileList:\r
454             InputSection += ('-i', InputFile)\r
455             for i in range(len(CmdParams) - 1):\r
456                 if CmdParams[i] == '-a':\r
457                     InputSection += ('-n', CmdParams[i+1])\r
458                     break\r
459 \r
460         GenFfsCmd = (\r
461             'GenFfs',\r
462              '-g', self.NameGuid,\r
463              '-o', FfsOutput,\r
464             ) + CmdParams + InputSection\r
465         #\r
466         # Call GenSection\r
467         #\r
468         GenFdsGlobalVariable.CallExternalTool(GenFfsCmd, "GenFfs Failed!")\r
469         return FfsOutput\r
470     \r
471     ## __GenComplexFileSection__() method\r
472     #\r
473     #   Generate section by sections in Rule\r
474     #\r
475     #   @param  self        The object pointer\r
476     #   @param  Rule        The rule object used to generate section\r
477     #   @retval string      File name of the generated section file\r
478     #  \r
479     def __GenComplexFileSection__(self, Rule):\r
480         \r
481         if self.ModuleType in ('SEC', 'PEI_CORE', 'PEIM'):\r
482             if Rule.KeepReloc != None:\r
483                 self.KeepRelocFromRule = Rule.KeepReloc\r
484         \r
485         SectFiles = tuple()\r
486         Index = 1\r
487         for Sect in Rule.SectionList:\r
488            SecIndex = '%d' %Index\r
489            SectList  = []\r
490            if Rule.KeyStringList != []:\r
491                SectList, Align = Sect.GenSection(self.OutputPath , self.ModuleGuid, SecIndex, Rule.KeyStringList, self)\r
492            else :\r
493                SectList, Align = Sect.GenSection(self.OutputPath , self.ModuleGuid, SecIndex, self.KeyStringList, self)\r
494            for SecName in  SectList :\r
495                SectFiles += ('-i', SecName)\r
496                if Align != None:\r
497                    SectFiles += ('-n', Align)\r
498            Index = Index + 1\r
499         return SectFiles\r
500 \r
501     ## __GenComplexFileFfs__() method\r
502     #\r
503     #   Generate FFS\r
504     #\r
505     #   @param  self        The object pointer\r
506     #   @param  Rule        The rule object used to generate section\r
507     #   @param  InputFileList        The output file list from GenSection\r
508     #   @retval string      Generated FFS file name\r
509     #\r
510     def __GenComplexFileFfs__(self, Rule, InputFile):\r
511         \r
512         CmdParams = self.__GetGenFfsCmdParameter__(Rule)\r
513         \r
514         FfsOutput = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs')\r
515         GenFfsCmd = (\r
516             'GenFfs',\r
517             ) + CmdParams + (\r
518              '-g', self.ModuleGuid,\r
519              '-o', FfsOutput,\r
520             ) + InputFile\r
521 \r
522         GenFdsGlobalVariable.CallExternalTool(GenFfsCmd, "GenFfs Failed !")\r
523         return FfsOutput\r
524 \r
525     ## __GetGenFfsCmdParameter__() method\r
526     #\r
527     #   Create parameter string for GenFfs\r
528     #\r
529     #   @param  self        The object pointer\r
530     #   @param  Rule        The rule object used to generate section\r
531     #   @retval tuple       (FileType, Fixed, CheckSum, Alignment)\r
532     #\r
533     def __GetGenFfsCmdParameter__(self, Rule):\r
534         result = tuple()\r
535         result += ('-t', Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType])\r
536         #FileType = ' -t ' + \\r
537         #           Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType]\r
538         if Rule.Fixed != False:\r
539             result += ('-x',)\r
540         if Rule.CheckSum != False:\r
541             result += ('-s',)\r
542             \r
543         if Rule.Alignment != None and Rule.Alignment != '':\r
544             result += ('-a', Rule.Alignment)\r
545             \r
546         return result\r