Fixed an issue which will cause files not found
[people/mcb30/basetools.git] / Source / Python / GenFds / GenFds.py
1 ## @file\r
2 # generate flash image\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 from optparse import OptionParser\r
19 import sys\r
20 import os\r
21 import FdfParser\r
22 from Common import BuildToolError\r
23 from GenFdsGlobalVariable import GenFdsGlobalVariable\r
24 from Workspace.WorkspaceDatabase import WorkspaceDatabase\r
25 import RuleComplexFile\r
26 from EfiSection import EfiSection\r
27 import StringIO\r
28 import Common.TargetTxtClassObject as TargetTxtClassObject\r
29 import Common.DataType\r
30 import Common.GlobalData as GlobalData\r
31 from Common import EdkLogger\r
32 from Common.String import *\r
33 \r
34 ## Version and Copyright\r
35 versionNumber = "1.0"\r
36 __version__ = "%prog Version " + versionNumber\r
37 __copyright__ = "Copyright (c) 2007, Intel Corporation  All rights reserved."\r
38 \r
39 ## Tool entrance method\r
40 #\r
41 # This method mainly dispatch specific methods per the command line options.\r
42 # If no error found, return zero value so the caller of this tool can know\r
43 # if it's executed successfully or not.\r
44 #\r
45 #   @retval 0     Tool was successful\r
46 #   @retval 1     Tool failed\r
47 #\r
48 def main():\r
49     global Options\r
50     Options = myOptionParser()\r
51     global Workspace\r
52     Workspace = ""\r
53     ArchList = None\r
54     try:\r
55         EdkLogger.Initialize()\r
56         if Options.verbose != None:\r
57             EdkLogger.SetLevel(EdkLogger.VERBOSE)\r
58             GenFdsGlobalVariable.VerboseMode = True\r
59         if Options.quiet != None:\r
60             EdkLogger.SetLevel(EdkLogger.QUIET)\r
61         if Options.debug != None:\r
62             EdkLogger.SetLevel(Options.debug + 1)\r
63             GenFdsGlobalVariable.DebugLevel = Options.debug\r
64         else:\r
65             EdkLogger.SetLevel(EdkLogger.INFO)\r
66             \r
67         if (Options.Workspace == None):\r
68             GenFdsGlobalVariable.ErrorLogger("WORKSPACE not defined.\n  Please set the WORKSPACE environment variable to the location of the EDK II install directory.")\r
69             sys.exit(1)\r
70         else:\r
71             Workspace = Options.Workspace\r
72             GenFdsGlobalVariable.WorkSpaceDir = Workspace\r
73             if 'EDK_SOURCE' in os.environ.keys():\r
74                 GenFdsGlobalVariable.EdkSourceDir = os.environ['EDK_SOURCE']\r
75             if (Options.debug):\r
76                 GenFdsGlobalVariable.VerboseLogger( "Using Workspace:" + Workspace)\r
77         os.chdir(GenFdsGlobalVariable.WorkSpaceDir)\r
78     \r
79         if (Options.filename):\r
80             FdfFilename = Options.filename\r
81             FdfFilename = GenFdsGlobalVariable.ReplaceWorkspaceMacro(FdfFilename)\r
82         else:\r
83             GenFdsGlobalVariable.ErrorLogger("You must specify an input filename")\r
84             sys.exit(1)\r
85     \r
86         if (Options.BuildTarget):\r
87             GenFdsGlobalVariable.TargetName = Options.BuildTarget\r
88         else:\r
89             GenFdsGlobalVariable.ErrorLogger("You must specify a build target")\r
90             sys.exit(1)\r
91             \r
92         if (Options.ToolChain):\r
93             GenFdsGlobalVariable.ToolChainTag = Options.ToolChain\r
94         else:\r
95             GenFdsGlobalVariable.ErrorLogger("You must specify a tool chain tag")\r
96             sys.exit(1)\r
97             \r
98         if FdfFilename[0:2] == '..':\r
99             FdfFilename = os.path.realpath(FdfFilename)\r
100         if FdfFilename[1] != ':':\r
101             FdfFilename = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, FdfFilename)\r
102                 \r
103         if not os.path.exists(FdfFilename):\r
104             GenFdsGlobalVariable.ErrorLogger ("File %s not found" % (FdfFilename))\r
105             sys.exit(1)\r
106 \r
107         if (Options.activePlatform):\r
108             ActivePlatform = Options.activePlatform\r
109             ActivePlatform = GenFdsGlobalVariable.ReplaceWorkspaceMacro(ActivePlatform)\r
110     \r
111             if ActivePlatform[0:2] == '..':\r
112                 ActivePlatform = os.path.realpath(ActivePlatform)\r
113     \r
114             if ActivePlatform[1] != ':':\r
115                 ActivePlatform = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, ActivePlatform)\r
116     \r
117             if not os.path.exists(ActivePlatform)  :\r
118                 raise Exception ("ActivePlatform doesn't exist!")\r
119             \r
120             if ActivePlatform.find(Workspace) == -1:\r
121                 raise Exception ("ActivePlatform doesn't exist in Workspace!")\r
122             \r
123             ActivePlatform = ActivePlatform.replace(Workspace, '')\r
124             if len(ActivePlatform) > 0 :\r
125                 if ActivePlatform[0] == '\\' or ActivePlatform[0] == '/':\r
126                     ActivePlatform = ActivePlatform[1:]\r
127             else:\r
128                 raise Exception ("ActivePlatform doesn't exist!")\r
129         else :\r
130             GenFdsGlobalVariable.ErrorLogger("You must specify an active platform")\r
131             sys.exit(1)\r
132     \r
133         GenFdsGlobalVariable.ActivePlatform = NormPath(ActivePlatform)\r
134             \r
135         if (Options.archList) :\r
136             ArchList = Options.archList.split(',')\r
137         else:\r
138             GenFdsGlobalVariable.ErrorLogger("You must specify a build ARCH")\r
139             sys.exit(1)\r
140         \r
141         BuildConfigurationFile = os.path.normpath(os.path.join(GenFdsGlobalVariable.WorkSpaceDir, "Conf/target.txt"))\r
142         if os.path.isfile(BuildConfigurationFile) == True:\r
143             TargetTxtClassObject.TargetTxtClassObject(BuildConfigurationFile)\r
144         else:\r
145             GenFdsGlobalVariable.ErrorLogger("File NOT found: %s", BuildConfigrationFile)\r
146             sys.exit(1)\r
147         \r
148         if Options.Macros:\r
149             for Pair in Options.Macros:\r
150                 Pair.strip('"')\r
151                 List = Pair.split('=')\r
152                 if len(List) == 2:\r
153                     FdfParser.InputMacroDict[List[0].strip()] = List[1].strip()\r
154                     GlobalData.gGlobalDefines[List[0].strip()] = List[1].strip()\r
155                 else:\r
156                     FdfParser.InputMacroDict[List[0].strip()] = None\r
157             \r
158         """call Workspace build create database"""\r
159         os.environ["WORKSPACE"] = Workspace\r
160         BuildWorkSpace = WorkspaceDatabase(':memory:', GlobalData.gGlobalDefines)\r
161         BuildWorkSpace.InitDatabase()\r
162 \r
163         for Arch in ArchList:\r
164             GenFdsGlobalVariable.OutputDirFromDscDict[Arch] = NormPath(BuildWorkSpace.BuildObject[ActivePlatform, Arch].OutputDirectory)\r
165         \r
166         if (Options.outputDir):\r
167             OutputDirFromCommandLine = GenFdsGlobalVariable.ReplaceWorkspaceMacro(Options.outputDir)\r
168             for Arch in ArchList:\r
169                 GenFdsGlobalVariable.OutputDirDict[Arch] = OutputDirFromCommandLine\r
170         else:\r
171             for Arch in ArchList:\r
172                 GenFdsGlobalVariable.OutputDirDict[Arch] = os.path.join(GenFdsGlobalVariable.OutputDirFromDscDict[Arch], GenFdsGlobalVariable.TargetName + '_' + GenFdsGlobalVariable.ToolChainTag)        \r
173     \r
174         for Key in GenFdsGlobalVariable.OutputDirDict:\r
175             OutputDir = GenFdsGlobalVariable.OutputDirDict[Key]\r
176             if OutputDir[0:2] == '..':\r
177                 OutputDir = os.path.realpath(OutputDir)\r
178                 \r
179             if OutputDir[1] != ':':\r
180                 OutputDir = os.path.join (GenFdsGlobalVariable.WorkSpaceDir, OutputDir)\r
181         \r
182             if not os.path.exists(OutputDir):\r
183                 GenFdsGlobalVariable.ErrorLogger ("Directory %s not found" % (OutputDir))\r
184                 sys.exit(1)\r
185             GenFdsGlobalVariable.OutputDirDict[Key] = OutputDir\r
186                     \r
187         """ Parse Fdf file, has to place after build Workspace as FDF may contain macros from DSC file """\r
188         try:\r
189             FdfParserObj = FdfParser.FdfParser(FdfFilename)\r
190             FdfParserObj.ParseFile()\r
191         except FdfParser.Warning, X:\r
192             EdkLogger.error(X.ToolName, BuildToolError.GENFDS_ERROR, X.message, X.FileName, X.LineNumber, RaiseError = False)    \r
193             sys.exit(1)\r
194             \r
195         if FdfParserObj.CycleReferenceCheck():\r
196             GenFdsGlobalVariable.InfLogger ("ERROR: Cycle Reference Detected in FDF file")\r
197             sys.exit(1)\r
198         \r
199         if (Options.uiFdName) :\r
200             if Options.uiFdName.upper() in FdfParserObj.Profile.FdDict.keys():\r
201                 GenFds.currentFd = Options.uiFdName\r
202             else:\r
203                 GenFdsGlobalVariable.ErrorLogger("No such an FD in FDF file.")\r
204                 sys.exit(1)\r
205     \r
206         if (Options.uiFvName) :\r
207             if Options.uiFvName.upper() in FdfParserObj.Profile.FvDict.keys():\r
208                 GenFds.currentFv = Options.uiFvName\r
209             else:\r
210                 GenFdsGlobalVariable.ErrorLogger("No such an FV in FDF file.")\r
211                 sys.exit(1)       \r
212         \r
213         """Call GenFds"""\r
214         GenFds.GenFd('', FdfParserObj, BuildWorkSpace, ArchList)\r
215         print "\nDone!\n"\r
216     except Exception, X:\r
217         EdkLogger.error("GenFds", BuildToolError.GENFDS_ERROR, X, RaiseError = False)\r
218         if Options.debug != None:\r
219             import traceback\r
220             EdkLogger.quiet(traceback.format_exc())\r
221         sys.exit(1)\r
222 \r
223 ## Parse command line options\r
224 #\r
225 # Using standard Python module optparse to parse command line option of this tool.\r
226 #\r
227 #   @retval Opt   A optparse.Values object containing the parsed options\r
228 #   @retval Args  Target of build command\r
229 #    \r
230 def myOptionParser():\r
231     usage = "%prog [options] -f input_file -a arch_list -b build_target -p active_platform -t tool_chain_tag -y \"MacroName [= MacroValue]\""\r
232     Parser = OptionParser(usage=usage,description=__copyright__,version="%prog " + str(versionNumber))\r
233     Parser.add_option("-f", "--file", dest="filename", help="Name of FDF file to convert")\r
234     Parser.add_option("-a", "--arch", dest="archList", help="comma separated list containing one or more of: IA32, X64, IPF or EBC which should be built, overrides target.txt?s TARGET_ARCH")\r
235     Parser.add_option("-q", "--quiet", action="store_true", type=None, help="Disable all messages except FATAL ERRORS.")\r
236     Parser.add_option("-v", "--verbose", action="store_true", type=None, help="Turn on verbose output with informational messages printed.")\r
237     Parser.add_option("-d", "--debug", action="store", type="int", help="Enable debug messages at specified level.")\r
238     Parser.add_option("-p", "--platform", dest="activePlatform", help="Set the ACTIVE_PLATFORM, overrides target.txt ACTIVE_PLATFORM setting.")\r
239     Parser.add_option("-w", "--workspace", dest="Workspace", default=str(os.environ.get('WORKSPACE')), help="Set the WORKSPACE")\r
240     Parser.add_option("-o", "--outputDir", dest="outputDir", help="Name of Build Output directory")\r
241     Parser.add_option("-r", "--rom_image", dest="uiFdName", help="Build the image using the [FD] section named by FdUiName.")\r
242     Parser.add_option("-i", "--FvImage", dest="uiFvName", help="Buld the FV image using the [FV] section named by UiFvName")\r
243     Parser.add_option("-b", "--buildtarget", action="store", type="choice", choices=['DEBUG','RELEASE'], dest="BuildTarget", help="Build TARGET is one of list: DEBUG, RELEASE.")\r
244     Parser.add_option("-t", "--tagname", action="store", type="string", dest="ToolChain", help="Using the tools: TOOL_CHAIN_TAG name to build the platform.")\r
245     Parser.add_option("-y", "--define", action="append", type="string", dest="Macros", help="Macro: \"Name [= Value]\".")\r
246     (Options, args) = Parser.parse_args()\r
247     return Options\r
248 \r
249 ## The class implementing the EDK2 flash image generation process\r
250 #\r
251 #   This process includes:\r
252 #       1. Collect workspace information, includes platform and module information\r
253 #       2. Call methods of Fd class to generate FD\r
254 #       3. Call methods of Fv class to generate FV that not belong to FD\r
255 #\r
256 class GenFds :\r
257     FdfParsef = None\r
258     # FvName in FDF, FvBinFile name\r
259     FvBinDict = {}\r
260     OnlyGenerateThisFd = None\r
261     OnlyGenerateThisFv = None\r
262     \r
263     ## GenFd()\r
264     #\r
265     #   @param  OutputDir           Output directory\r
266     #   @param  FdfParser           FDF contents parser\r
267     #   @param  Workspace           The directory of workspace\r
268     #   @param  ArchList            The Arch list of platform\r
269     #\r
270     def GenFd (OutputDir, FdfParser, WorkSpace, ArchList):\r
271         GenFdsGlobalVariable.SetDir ('', FdfParser, WorkSpace, ArchList)\r
272 \r
273         GenFdsGlobalVariable.VerboseLogger("   Gen Fd  !")\r
274         if GenFds.OnlyGenerateThisFd != None and GenFds.OnlyGenerateThisFd.upper() in GenFdsGlobalVariable.FdfParser.Profile.FdDict.keys():\r
275             FdObj = GenFdsGlobalVariable.FdfParser.Profile.FdDict.get(GenFds.OnlyGenerateThisFd.upper())\r
276             if FdObj != None:\r
277                 FdObj.GenFd(GenFds.FvBinDict)\r
278         elif GenFds.OnlyGenerateThisFv == None:\r
279             for FdName in GenFdsGlobalVariable.FdfParser.Profile.FdDict.keys():\r
280                 FdObj = GenFdsGlobalVariable.FdfParser.Profile.FdDict[FdName]\r
281                 FdObj.GenFd(GenFds.FvBinDict)\r
282             \r
283         GenFdsGlobalVariable.VerboseLogger(" Gen FV ! ")\r
284         if GenFds.OnlyGenerateThisFv != None and GenFds.OnlyGenerateThisFv.upper() in GenFdsGlobalVariable.FdfParser.Profile.FvDict.keys():\r
285             FvObj = GenFdsGlobalVariable.FdfParser.Profile.FvDict.get(GenFds.OnlyGenerateThisFv.upper())\r
286             if FvObj != None:\r
287                 Buffer = StringIO.StringIO()\r
288                 # Get FV base Address\r
289                 FvObj.AddToBuffer(Buffer, None, GenFds.GetFvBlockSize(FvObj))\r
290                 Buffer.close()\r
291                 return\r
292         elif GenFds.OnlyGenerateThisFd == None:\r
293             for FvName in GenFdsGlobalVariable.FdfParser.Profile.FvDict.keys():          \r
294                 Buffer = StringIO.StringIO('')\r
295                 FvObj = GenFdsGlobalVariable.FdfParser.Profile.FvDict[FvName]\r
296                 # Get FV base Address\r
297                 FvObj.AddToBuffer(Buffer, None, GenFds.GetFvBlockSize(FvObj))\r
298                 Buffer.close()\r
299     \r
300         if GenFds.OnlyGenerateThisFv == None and GenFds.OnlyGenerateThisFd == None:\r
301             GenFdsGlobalVariable.VerboseLogger(" Gen Capsule !")\r
302             for CapsuleObj in GenFdsGlobalVariable.FdfParser.Profile.CapsuleList:\r
303                 CapsuleObj.GenCapsule()\r
304 \r
305     ## GetFvBlockSize()\r
306     #\r
307     #   @param  FvObj           Whose block size to get\r
308     #   @retval int             Block size value\r
309     #\r
310     def GetFvBlockSize(FvObj):\r
311         FdObj = None\r
312         if GenFds.OnlyGenerateThisFd != None and GenFds.OnlyGenerateThisFd.upper() in GenFdsGlobalVariable.FdfParser.Profile.FdDict.keys():\r
313             FdObj = GenFdsGlobalVariable.FdfParser.Profile.FdDict[GenFds.OnlyGenerateThisFd.upper()]\r
314         if FdObj == None:\r
315             for ElementFd in GenFdsGlobalVariable.FdfParser.Profile.FdDict.values():\r
316                 for ElementRegion in ElementFd.RegionList:\r
317                     if ElementRegion.RegionType == 'FV':\r
318                         for ElementRegionData in ElementRegion.RegionDataList:\r
319                             if ElementRegionData != None and ElementRegionData.upper() == FvObj.UiFvName:\r
320                                 if FvObj.BlockSizeList != []:\r
321                                     return FvObj.BlockSizeList[0][0]\r
322                                 else:\r
323                                     return ElementRegion.BlockSizeOfRegion(ElementFd.BlockSizeList)\r
324             return 0x10000\r
325         else:\r
326             for ElementRegion in FdObj.RegionList:\r
327                     if ElementRegion.RegionType == 'FV':\r
328                         for ElementRegionData in ElementRegion.RegionDataList:\r
329                             if ElementRegionData != None and ElementRegionData.upper() == FvObj.UiFvName:\r
330                                 if FvObj.BlockSizeList != []:\r
331                                     return FvObj.BlockSizeList[0][0]\r
332                                 else:\r
333                                     return ElementRegion.BlockSizeOfRegion(ElementFd.BlockSizeList)\r
334             return 0x10000\r
335         \r
336     ##Define GenFd as static function\r
337     GenFd = staticmethod(GenFd)\r
338     GetFvBlockSize = staticmethod(GetFvBlockSize)\r
339 \r
340 if __name__ == '__main__':\r
341     \r
342     main()\r