Fixed memory leak and buffer overrun for string op-code.
[mirror_edk2.git] / BaseTools / Source / Python / GenFds / FfsInfStatement.py
CommitLineData
30fdf114
LG
1## @file\r
2# process FFS generation from INF statement\r
3#\r
da92f276 4# Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>\r
30fdf114 5#\r
40d841f6 6# This program and the accompanying materials\r
30fdf114
LG
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
18import Rule\r
19import os\r
20import shutil\r
da92f276
LG
21import StringIO\r
22from struct import *\r
30fdf114
LG
23from GenFdsGlobalVariable import GenFdsGlobalVariable\r
24import Ffs\r
25import subprocess\r
26import sys\r
27import Section\r
28import RuleSimpleFile\r
29import RuleComplexFile\r
30from CommonDataClass.FdfClass import FfsInfStatementClassObject\r
31from Common.String import *\r
32from Common.Misc import PathClass\r
33from Common.Misc import GuidStructureByteArrayToGuidString\r
34from Common import EdkLogger\r
35from Common.BuildToolError import *\r
52302d4d
LG
36from GuidSection import GuidSection\r
37from FvImageSection import FvImageSection\r
38from Common.Misc import PeImageClass\r
30fdf114
LG
39\r
40## generate FFS from INF\r
41#\r
42#\r
43class FfsInfStatement(FfsInfStatementClassObject):\r
44 ## The constructor\r
45 #\r
46 # @param self The object pointer\r
47 #\r
48 def __init__(self):\r
49 FfsInfStatementClassObject.__init__(self)\r
50 self.TargetOverrideList = []\r
51 self.ShadowFromInfFile = None\r
52 self.KeepRelocFromRule = None\r
53 self.InDsc = True\r
54 self.OptRomDefs = {}\r
da92f276 55 self.PiSpecVersion = '0x00000000'\r
30fdf114
LG
56 \r
57 ## __InfParse() method\r
58 #\r
59 # Parse inf file to get module information\r
60 #\r
61 # @param self The object pointer\r
62 # @param Dict dictionary contains macro and value pair\r
63 #\r
64 def __InfParse__(self, Dict = {}):\r
65\r
66 GenFdsGlobalVariable.VerboseLogger( " Begine parsing INf file : %s" %self.InfFileName)\r
67\r
68 self.InfFileName = self.InfFileName.replace('$(WORKSPACE)', '')\r
69 if self.InfFileName[0] == '\\' or self.InfFileName[0] == '/' :\r
70 self.InfFileName = self.InfFileName[1:]\r
71\r
72 if self.InfFileName.find('$') == -1:\r
73 InfPath = NormPath(self.InfFileName)\r
74 if not os.path.exists(InfPath):\r
75 InfPath = GenFdsGlobalVariable.ReplaceWorkspaceMacro(InfPath)\r
76 if not os.path.exists(InfPath):\r
77 EdkLogger.error("GenFds", GENFDS_ERROR, "Non-existant Module %s !" % (self.InfFileName))\r
78\r
79 self.CurrentArch = self.GetCurrentArch()\r
80 #\r
81 # Get the InfClass object\r
82 #\r
83\r
84 PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir)\r
e56468c0 85 ErrorCode, ErrorInfo = PathClassObj.Validate(".inf")\r
30fdf114
LG
86 if ErrorCode != 0:\r
87 EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)\r
88 \r
89 if self.CurrentArch != None:\r
90\r
91 Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, self.CurrentArch]\r
92 #\r
93 # Set Ffs BaseName, MdouleGuid, ModuleType, Version, OutputPath\r
94 #\r
95 self.BaseName = Inf.BaseName\r
96 self.ModuleGuid = Inf.Guid\r
97 self.ModuleType = Inf.ModuleType\r
52302d4d 98 if Inf.Specification != None and 'PI_SPECIFICATION_VERSION' in Inf.Specification:\r
b303ea72 99 self.PiSpecVersion = Inf.Specification['PI_SPECIFICATION_VERSION']\r
30fdf114
LG
100 if Inf.AutoGenVersion < 0x00010005:\r
101 self.ModuleType = Inf.ComponentType\r
102 self.VersionString = Inf.Version\r
103 self.BinFileList = Inf.Binaries\r
104 self.SourceFileList = Inf.Sources\r
105 if self.KeepReloc == None and Inf.Shadow:\r
106 self.ShadowFromInfFile = Inf.Shadow\r
107\r
108 else:\r
109 Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, 'COMMON']\r
110 self.BaseName = Inf.BaseName\r
111 self.ModuleGuid = Inf.Guid\r
112 self.ModuleType = Inf.ModuleType\r
52302d4d 113 if Inf.Specification != None and 'PI_SPECIFICATION_VERSION' in Inf.Specification:\r
b303ea72 114 self.PiSpecVersion = Inf.Specification['PI_SPECIFICATION_VERSION']\r
30fdf114
LG
115 self.VersionString = Inf.Version\r
116 self.BinFileList = Inf.Binaries\r
117 self.SourceFileList = Inf.Sources\r
118 if self.BinFileList == []:\r
119 EdkLogger.error("GenFds", GENFDS_ERROR,\r
120 "INF %s specified in FDF could not be found in build ARCH %s!" \\r
121 % (self.InfFileName, GenFdsGlobalVariable.ArchList))\r
122\r
123 if len(self.SourceFileList) != 0 and not self.InDsc:\r
124 EdkLogger.warn("GenFds", GENFDS_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % (self.InfFileName))\r
125\r
da92f276 126 if self.ModuleType == 'SMM_CORE' and int(self.PiSpecVersion, 16) < 0x0001000A:\r
b303ea72
LG
127 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "SMM_CORE module type can't be used in the module with PI_SPECIFICATION_VERSION less than 0x0001000A", File=self.InfFileName) \r
128\r
30fdf114
LG
129 if Inf._Defs != None and len(Inf._Defs) > 0:\r
130 self.OptRomDefs.update(Inf._Defs)\r
131 \r
132 GenFdsGlobalVariable.VerboseLogger( "BaseName : %s" %self.BaseName)\r
133 GenFdsGlobalVariable.VerboseLogger("ModuleGuid : %s" %self.ModuleGuid)\r
134 GenFdsGlobalVariable.VerboseLogger("ModuleType : %s" %self.ModuleType)\r
135 GenFdsGlobalVariable.VerboseLogger("VersionString : %s" %self.VersionString)\r
136 GenFdsGlobalVariable.VerboseLogger("InfFileName :%s" %self.InfFileName)\r
137\r
138 #\r
139 # Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${MdouleName}\\r
140 #\r
141\r
142 self.OutputPath = os.path.join(GenFdsGlobalVariable.FfsDir, \\r
143 self.ModuleGuid + self.BaseName)\r
144 if not os.path.exists(self.OutputPath) :\r
145 os.makedirs(self.OutputPath)\r
146\r
147 self.EfiOutputPath = self.__GetEFIOutPutPath__()\r
148 GenFdsGlobalVariable.VerboseLogger( "ModuelEFIPath: " + self.EfiOutputPath)\r
149\r
150 ## GenFfs() method\r
151 #\r
152 # Generate FFS\r
153 #\r
52302d4d
LG
154 # @param self The object pointer\r
155 # @param Dict dictionary contains macro and value pair\r
156 # @param FvChildAddr Array of the inside FvImage base address\r
157 # @param FvParentAddr Parent Fv base address\r
158 # @retval string Generated FFS file name\r
30fdf114 159 #\r
52302d4d 160 def GenFfs(self, Dict = {}, FvChildAddr = [], FvParentAddr=None):\r
30fdf114
LG
161 #\r
162 # Parse Inf file get Module related information\r
163 #\r
164\r
165 self.__InfParse__(Dict)\r
6780eef1
LG
166 \r
167 #\r
168 # Allow binary type module not specify override rule in FDF file.\r
169 # \r
170 if len(self.BinFileList) >0 and not self.InDsc:\r
171 if self.Rule == None or self.Rule == "":\r
172 self.Rule = "BINARY"\r
173 \r
30fdf114
LG
174 #\r
175 # Get the rule of how to generate Ffs file\r
176 #\r
177 Rule = self.__GetRule__()\r
178 GenFdsGlobalVariable.VerboseLogger( "Packing binaries from inf file : %s" %self.InfFileName)\r
b303ea72
LG
179 #\r
180 # Convert Fv File Type for PI1.1 SMM driver.\r
181 #\r
da92f276 182 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:\r
b303ea72
LG
183 if Rule.FvFileType == 'DRIVER':\r
184 Rule.FvFileType = 'SMM'\r
185 #\r
186 # Framework SMM Driver has no SMM FV file type\r
187 #\r
da92f276 188 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:\r
b303ea72
LG
189 if Rule.FvFileType == 'SMM' or Rule.FvFileType == 'SMM_CORE':\r
190 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM or SMM_CORE FV file type", File=self.InfFileName)\r
30fdf114
LG
191 #\r
192 # For the rule only has simpleFile\r
193 #\r
194 if isinstance (Rule, RuleSimpleFile.RuleSimpleFile) :\r
195 SectionOutputList = self.__GenSimpleFileSection__(Rule)\r
196 FfsOutput = self.__GenSimpleFileFfs__(Rule, SectionOutputList)\r
197 return FfsOutput\r
198 #\r
199 # For Rule has ComplexFile\r
200 #\r
201 elif isinstance(Rule, RuleComplexFile.RuleComplexFile):\r
52302d4d 202 InputSectList, InputSectAlignments = self.__GenComplexFileSection__(Rule, FvChildAddr, FvParentAddr)\r
30fdf114
LG
203 FfsOutput = self.__GenComplexFileFfs__(Rule, InputSectList, InputSectAlignments)\r
204\r
205 return FfsOutput\r
206\r
207 ## __ExtendMacro__() method\r
208 #\r
209 # Replace macro with its value\r
210 #\r
211 # @param self The object pointer\r
212 # @param String The string to be replaced\r
213 # @retval string Macro replaced string\r
214 #\r
215 def __ExtendMacro__ (self, String):\r
216 MacroDict = {\r
217 '$(INF_OUTPUT)' : self.EfiOutputPath,\r
218 '$(MODULE_NAME)' : self.BaseName,\r
219 '$(BUILD_NUMBER)': self.BuildNum,\r
220 '$(INF_VERSION)' : self.VersionString,\r
221 '$(NAMED_GUID)' : self.ModuleGuid\r
222 }\r
223 String = GenFdsGlobalVariable.MacroExtend(String, MacroDict)\r
224 return String\r
225\r
226 ## __GetRule__() method\r
227 #\r
228 # Get correct rule for generating FFS for this INF\r
229 #\r
230 # @param self The object pointer\r
231 # @retval Rule Rule object\r
232 #\r
233 def __GetRule__ (self) :\r
234 CurrentArchList = []\r
235 if self.CurrentArch == None:\r
236 CurrentArchList = ['common']\r
237 else:\r
238 CurrentArchList.append(self.CurrentArch)\r
239\r
240 for CurrentArch in CurrentArchList:\r
241 RuleName = 'RULE' + \\r
242 '.' + \\r
243 CurrentArch.upper() + \\r
244 '.' + \\r
245 self.ModuleType.upper()\r
246 if self.Rule != None:\r
247 RuleName = RuleName + \\r
248 '.' + \\r
249 self.Rule.upper()\r
250\r
251 Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName)\r
252 if Rule != None:\r
253 GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName)\r
254 return Rule\r
255\r
256 RuleName = 'RULE' + \\r
257 '.' + \\r
258 'COMMON' + \\r
259 '.' + \\r
260 self.ModuleType.upper()\r
261\r
262 if self.Rule != None:\r
263 RuleName = RuleName + \\r
264 '.' + \\r
265 self.Rule.upper()\r
266\r
267 GenFdsGlobalVariable.VerboseLogger ('Trying to apply common rule %s for INF %s' % (RuleName, self.InfFileName))\r
268\r
269 Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName)\r
270 if Rule != None:\r
271 GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName)\r
272 return Rule\r
273\r
274 if Rule == None :\r
275 EdkLogger.error("GenFds", GENFDS_ERROR, 'Don\'t Find common rule %s for INF %s' \\r
276 % (RuleName, self.InfFileName))\r
277\r
278 ## __GetPlatformArchList__() method\r
279 #\r
280 # Get Arch list this INF built under\r
281 #\r
282 # @param self The object pointer\r
283 # @retval list Arch list\r
284 #\r
285 def __GetPlatformArchList__(self):\r
286\r
287 InfFileKey = os.path.normpath(os.path.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName))\r
288 DscArchList = []\r
289 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'IA32']\r
290 if PlatformDataBase != None:\r
291 if InfFileKey in PlatformDataBase.Modules:\r
292 DscArchList.append ('IA32')\r
293\r
294 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'X64']\r
295 if PlatformDataBase != None:\r
296 if InfFileKey in PlatformDataBase.Modules:\r
297 DscArchList.append ('X64')\r
298\r
299 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'IPF']\r
300 if PlatformDataBase != None:\r
301 if InfFileKey in (PlatformDataBase.Modules):\r
302 DscArchList.append ('IPF')\r
303\r
304 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'ARM']\r
305 if PlatformDataBase != None:\r
306 if InfFileKey in (PlatformDataBase.Modules):\r
307 DscArchList.append ('ARM')\r
308\r
309 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'EBC']\r
310 if PlatformDataBase != None:\r
311 if InfFileKey in (PlatformDataBase.Modules):\r
312 DscArchList.append ('EBC')\r
313\r
314 return DscArchList\r
315\r
316 ## GetCurrentArch() method\r
317 #\r
318 # Get Arch list of the module from this INF is to be placed into flash\r
319 #\r
320 # @param self The object pointer\r
321 # @retval list Arch list\r
322 #\r
323 def GetCurrentArch(self) :\r
324\r
325 TargetArchList = GenFdsGlobalVariable.ArchList\r
326\r
327 PlatformArchList = self.__GetPlatformArchList__()\r
328\r
329 CurArchList = TargetArchList\r
330 if PlatformArchList != []:\r
331 CurArchList = list(set (TargetArchList) & set (PlatformArchList))\r
332 GenFdsGlobalVariable.VerboseLogger ("Valid target architecture(s) is : " + " ".join(CurArchList))\r
333\r
334 ArchList = []\r
335 if self.KeyStringList != []:\r
336 for Key in self.KeyStringList:\r
337 Key = GenFdsGlobalVariable.MacroExtend(Key)\r
338 Target, Tag, Arch = Key.split('_')\r
339 if Arch in CurArchList:\r
340 ArchList.append(Arch)\r
341 if Target not in self.TargetOverrideList:\r
342 self.TargetOverrideList.append(Target)\r
343 else:\r
344 ArchList = CurArchList\r
345\r
346 UseArchList = TargetArchList\r
347 if self.UseArch != None:\r
348 UseArchList = []\r
349 UseArchList.append(self.UseArch)\r
350 ArchList = list(set (UseArchList) & set (ArchList))\r
351\r
352 self.InfFileName = NormPath(self.InfFileName)\r
353 if len(PlatformArchList) == 0:\r
354 self.InDsc = False\r
355 PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir)\r
e56468c0 356 ErrorCode, ErrorInfo = PathClassObj.Validate(".inf")\r
30fdf114
LG
357 if ErrorCode != 0:\r
358 EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)\r
359 if len(ArchList) == 1:\r
360 Arch = ArchList[0]\r
361 return Arch\r
362 elif len(ArchList) > 1:\r
363 if len(PlatformArchList) == 0:\r
364 EdkLogger.error("GenFds", GENFDS_ERROR, "GenFds command line option has multiple ARCHs %s. Not able to determine which ARCH is valid for Module %s !" % (str(ArchList), self.InfFileName))\r
365 else:\r
366 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
367 else:\r
368 EdkLogger.error("GenFds", GENFDS_ERROR, "Module %s appears under ARCH %s in platform %s, but current deduced ARCH is %s, so NO build output could be put into flash." \\r
369 % (self.InfFileName, str(PlatformArchList), GenFdsGlobalVariable.ActivePlatform, str(set (UseArchList) & set (TargetArchList))))\r
370\r
371 ## __GetEFIOutPutPath__() method\r
372 #\r
373 # Get the output path for generated files\r
374 #\r
375 # @param self The object pointer\r
376 # @retval string Path that output files from this INF go to\r
377 #\r
378 def __GetEFIOutPutPath__(self):\r
379 Arch = ''\r
380 OutputPath = ''\r
381 (ModulePath, FileName) = os.path.split(self.InfFileName)\r
382 Index = FileName.find('.')\r
383 FileName = FileName[0:Index]\r
384 Arch = "NoneArch"\r
385 if self.CurrentArch != None:\r
386 Arch = self.CurrentArch\r
387\r
388 OutputPath = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch],\r
389 Arch ,\r
390 ModulePath,\r
391 FileName,\r
392 'OUTPUT'\r
393 )\r
394 OutputPath = os.path.realpath(OutputPath)\r
395 return OutputPath\r
396\r
397 ## __GenSimpleFileSection__() method\r
398 #\r
399 # Generate section by specified file name or a list of files with file extension\r
400 #\r
401 # @param self The object pointer\r
402 # @param Rule The rule object used to generate section\r
403 # @retval string File name of the generated section file\r
404 #\r
405 def __GenSimpleFileSection__(self, Rule):\r
406 #\r
407 # Prepare the parameter of GenSection\r
408 #\r
409 FileList = []\r
410 OutputFileList = []\r
52302d4d 411 GenSecInputFile = None\r
30fdf114
LG
412 if Rule.FileName != None:\r
413 GenSecInputFile = self.__ExtendMacro__(Rule.FileName)\r
da92f276
LG
414 if os.path.isabs(GenSecInputFile):\r
415 GenSecInputFile = os.path.normpath(GenSecInputFile)\r
416 else:\r
52302d4d 417 GenSecInputFile = os.path.normpath(os.path.join(self.EfiOutputPath, GenSecInputFile))\r
30fdf114
LG
418 else:\r
419 FileList, IsSect = Section.Section.GetFileList(self, '', Rule.FileExtension)\r
420\r
421 Index = 1\r
b303ea72
LG
422 SectionType = Rule.SectionType\r
423 #\r
424 # Convert Fv Section Type for PI1.1 SMM driver.\r
425 #\r
da92f276 426 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:\r
b303ea72
LG
427 if SectionType == 'DXE_DEPEX':\r
428 SectionType = 'SMM_DEPEX'\r
429 #\r
430 # Framework SMM Driver has no SMM_DEPEX section type\r
431 #\r
da92f276 432 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:\r
b303ea72
LG
433 if SectionType == 'SMM_DEPEX':\r
434 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName)\r
30fdf114
LG
435 NoStrip = True\r
436 if self.ModuleType in ('SEC', 'PEI_CORE', 'PEIM'):\r
437 if self.KeepReloc != None:\r
438 NoStrip = self.KeepReloc\r
439 elif Rule.KeepReloc != None:\r
440 NoStrip = Rule.KeepReloc\r
441 elif self.ShadowFromInfFile != None:\r
442 NoStrip = self.ShadowFromInfFile\r
443\r
444 if FileList != [] :\r
445 for File in FileList:\r
446\r
447 SecNum = '%d' %Index\r
448 GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \\r
449 Ffs.Ffs.SectionSuffix[SectionType] + 'SEC' + SecNum\r
450 Index = Index + 1\r
451 OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)\r
52302d4d
LG
452 File = GenFdsGlobalVariable.MacroExtend(File, Dict, self.CurrentArch)\r
453\r
454 #Get PE Section alignment when align is set to AUTO\r
455 if self.Alignment == 'Auto' and (SectionType == 'PE32' or SectionType == 'TE'):\r
456 ImageObj = PeImageClass (File)\r
457 if ImageObj.SectionAlignment < 0x400:\r
458 self.Alignment = str (ImageObj.SectionAlignment)\r
459 else:\r
460 self.Alignment = str (ImageObj.SectionAlignment / 0x400) + 'K'\r
30fdf114
LG
461\r
462 if not NoStrip:\r
463 FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')\r
464 if not os.path.exists(FileBeforeStrip) or \\r
465 (os.path.getmtime(File) > os.path.getmtime(FileBeforeStrip)):\r
466 shutil.copyfile(File, FileBeforeStrip)\r
467 StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')\r
468 GenFdsGlobalVariable.GenerateFirmwareImage(\r
469 StrippedFile,\r
52302d4d 470 [File],\r
30fdf114
LG
471 Strip=True\r
472 )\r
473 File = StrippedFile\r
474\r
475 if SectionType == 'TE':\r
476 TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')\r
477 GenFdsGlobalVariable.GenerateFirmwareImage(\r
478 TeFile,\r
52302d4d 479 [File],\r
30fdf114
LG
480 Type='te'\r
481 )\r
482 File = TeFile\r
483\r
484 GenFdsGlobalVariable.GenerateSection(OutputFile, [File], Section.Section.SectionType[SectionType])\r
485 OutputFileList.append(OutputFile)\r
486 else:\r
487 SecNum = '%d' %Index\r
488 GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \\r
489 Ffs.Ffs.SectionSuffix[SectionType] + 'SEC' + SecNum\r
490 OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)\r
52302d4d
LG
491 GenSecInputFile = GenFdsGlobalVariable.MacroExtend(GenSecInputFile, Dict, self.CurrentArch)\r
492\r
493 #Get PE Section alignment when align is set to AUTO\r
494 if self.Alignment == 'Auto' and (SectionType == 'PE32' or SectionType == 'TE'):\r
495 ImageObj = PeImageClass (GenSecInputFile)\r
496 if ImageObj.SectionAlignment < 0x400:\r
497 self.Alignment = str (ImageObj.SectionAlignment)\r
498 else:\r
499 self.Alignment = str (ImageObj.SectionAlignment / 0x400) + 'K'\r
30fdf114
LG
500\r
501 if not NoStrip:\r
502 FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')\r
503 if not os.path.exists(FileBeforeStrip) or \\r
504 (os.path.getmtime(GenSecInputFile) > os.path.getmtime(FileBeforeStrip)):\r
505 shutil.copyfile(GenSecInputFile, FileBeforeStrip)\r
506 StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')\r
507 GenFdsGlobalVariable.GenerateFirmwareImage(\r
508 StrippedFile,\r
52302d4d 509 [GenSecInputFile],\r
30fdf114
LG
510 Strip=True\r
511 )\r
512 GenSecInputFile = StrippedFile\r
513\r
514 if SectionType == 'TE':\r
515 TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')\r
516 GenFdsGlobalVariable.GenerateFirmwareImage(\r
517 TeFile,\r
52302d4d 518 [GenSecInputFile],\r
30fdf114
LG
519 Type='te'\r
520 )\r
521 GenSecInputFile = TeFile\r
522\r
523 GenFdsGlobalVariable.GenerateSection(OutputFile, [GenSecInputFile], Section.Section.SectionType[SectionType])\r
524 OutputFileList.append(OutputFile)\r
525\r
526 return OutputFileList\r
527\r
528 ## __GenSimpleFileFfs__() method\r
529 #\r
530 # Generate FFS\r
531 #\r
532 # @param self The object pointer\r
533 # @param Rule The rule object used to generate section\r
534 # @param InputFileList The output file list from GenSection\r
535 # @retval string Generated FFS file name\r
536 #\r
537 def __GenSimpleFileFfs__(self, Rule, InputFileList):\r
538 FfsOutput = self.OutputPath + \\r
539 os.sep + \\r
540 self.__ExtendMacro__(Rule.NameGuid) + \\r
541 '.ffs'\r
542\r
543 GenFdsGlobalVariable.VerboseLogger(self.__ExtendMacro__(Rule.NameGuid))\r
544 InputSection = []\r
545 SectionAlignments = []\r
546 for InputFile in InputFileList:\r
547 InputSection.append(InputFile)\r
52302d4d 548 SectionAlignments.append(Rule.SectAlignment)\r
30fdf114
LG
549\r
550 if Rule.NameGuid != None and Rule.NameGuid.startswith('PCD('):\r
551 PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid)\r
552 if len(PcdValue) == 0:\r
553 EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \\r
554 % (Rule.NameGuid))\r
555 if PcdValue.startswith('{'):\r
556 PcdValue = GuidStructureByteArrayToGuidString(PcdValue)\r
557 RegistryGuidStr = PcdValue\r
558 if len(RegistryGuidStr) == 0:\r
559 EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \\r
560 % (Rule.NameGuid))\r
561 self.ModuleGuid = RegistryGuidStr\r
562\r
563 GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputSection,\r
564 Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType],\r
565 self.ModuleGuid, Fixed=Rule.Fixed,\r
566 CheckSum=Rule.CheckSum, Align=Rule.Alignment,\r
567 SectionAlign=SectionAlignments\r
568 )\r
569 return FfsOutput\r
570\r
571 ## __GenComplexFileSection__() method\r
572 #\r
573 # Generate section by sections in Rule\r
574 #\r
52302d4d
LG
575 # @param self The object pointer\r
576 # @param Rule The rule object used to generate section\r
577 # @param FvChildAddr Array of the inside FvImage base address\r
578 # @param FvParentAddr Parent Fv base address\r
579 # @retval string File name of the generated section file\r
30fdf114 580 #\r
52302d4d 581 def __GenComplexFileSection__(self, Rule, FvChildAddr, FvParentAddr):\r
30fdf114
LG
582 if self.ModuleType in ('SEC', 'PEI_CORE', 'PEIM'):\r
583 if Rule.KeepReloc != None:\r
584 self.KeepRelocFromRule = Rule.KeepReloc\r
585 SectFiles = []\r
586 SectAlignments = []\r
587 Index = 1\r
da92f276 588 HasGneratedFlag = False\r
30fdf114
LG
589 for Sect in Rule.SectionList:\r
590 SecIndex = '%d' %Index\r
591 SectList = []\r
b303ea72
LG
592 #\r
593 # Convert Fv Section Type for PI1.1 SMM driver.\r
594 #\r
da92f276 595 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:\r
b303ea72
LG
596 if Sect.SectionType == 'DXE_DEPEX':\r
597 Sect.SectionType = 'SMM_DEPEX'\r
598 #\r
599 # Framework SMM Driver has no SMM_DEPEX section type\r
600 #\r
da92f276 601 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:\r
b303ea72
LG
602 if Sect.SectionType == 'SMM_DEPEX':\r
603 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName)\r
52302d4d
LG
604 #\r
605 # process the inside FvImage from FvSection or GuidSection\r
606 #\r
607 if FvChildAddr != []:\r
608 if isinstance(Sect, FvImageSection):\r
609 Sect.FvAddr = FvChildAddr.pop(0)\r
610 elif isinstance(Sect, GuidSection):\r
611 Sect.FvAddr = FvChildAddr\r
612 if FvParentAddr != None and isinstance(Sect, GuidSection):\r
613 Sect.FvParentAddr = FvParentAddr\r
614 \r
30fdf114
LG
615 if Rule.KeyStringList != []:\r
616 SectList, Align = Sect.GenSection(self.OutputPath , self.ModuleGuid, SecIndex, Rule.KeyStringList, self)\r
617 else :\r
618 SectList, Align = Sect.GenSection(self.OutputPath , self.ModuleGuid, SecIndex, self.KeyStringList, self)\r
da92f276
LG
619 \r
620 if not HasGneratedFlag:\r
621 UniVfrOffsetFileSection = "" \r
622 ModuleFileName = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName)\r
623 InfData = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClass(ModuleFileName), self.CurrentArch]\r
624 #\r
625 # Search the source list in InfData to find if there are .vfr file exist.\r
626 #\r
627 VfrUniBaseName = {}\r
628 VfrUniOffsetList = []\r
629 for SourceFile in InfData.Sources:\r
630 if SourceFile.Type.upper() == ".VFR" :\r
631 #\r
632 # search the .map file to find the offset of vfr binary in the PE32+/TE file. \r
633 #\r
634 VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin")\r
635 if SourceFile.Type.upper() == ".UNI" :\r
636 #\r
637 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file. \r
638 #\r
639 VfrUniBaseName["UniOffsetName"] = (self.BaseName + "Strings")\r
640 \r
641 \r
642 if len(VfrUniBaseName) > 0:\r
643 VfrUniOffsetList = self.__GetBuildOutputMapFileVfrUniInfo(VfrUniBaseName)\r
644 #\r
645 # Generate the Raw data of raw section\r
646 #\r
647 os.path.join( self.OutputPath, self.BaseName + '.offset')\r
648 UniVfrOffsetFileName = os.path.join( self.OutputPath, self.BaseName + '.offset')\r
649 UniVfrOffsetFileSection = os.path.join( self.OutputPath, self.BaseName + 'Offset' + '.raw')\r
650 \r
651 self.__GenUniVfrOffsetFile (VfrUniOffsetList, UniVfrOffsetFileName)\r
652 \r
653 UniVfrOffsetFileNameList = []\r
654 UniVfrOffsetFileNameList.append(UniVfrOffsetFileName)\r
655 """Call GenSection"""\r
656 GenFdsGlobalVariable.GenerateSection(UniVfrOffsetFileSection,\r
657 UniVfrOffsetFileNameList,\r
658 "EFI_SECTION_RAW"\r
659 )\r
660 os.remove(UniVfrOffsetFileName) \r
661 SectList.append(UniVfrOffsetFileSection)\r
662 HasGneratedFlag = True\r
663 \r
30fdf114
LG
664 for SecName in SectList :\r
665 SectFiles.append(SecName)\r
666 SectAlignments.append(Align)\r
667 Index = Index + 1\r
668 return SectFiles, SectAlignments\r
669\r
670 ## __GenComplexFileFfs__() method\r
671 #\r
672 # Generate FFS\r
673 #\r
674 # @param self The object pointer\r
675 # @param Rule The rule object used to generate section\r
676 # @param InputFileList The output file list from GenSection\r
677 # @retval string Generated FFS file name\r
678 #\r
679 def __GenComplexFileFfs__(self, Rule, InputFile, Alignments):\r
680\r
681 if Rule.NameGuid != None and Rule.NameGuid.startswith('PCD('):\r
682 PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid)\r
683 if len(PcdValue) == 0:\r
684 EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \\r
685 % (Rule.NameGuid))\r
686 if PcdValue.startswith('{'):\r
687 PcdValue = GuidStructureByteArrayToGuidString(PcdValue)\r
688 RegistryGuidStr = PcdValue\r
689 if len(RegistryGuidStr) == 0:\r
690 EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \\r
691 % (Rule.NameGuid))\r
692 self.ModuleGuid = RegistryGuidStr\r
693\r
694 FfsOutput = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs')\r
695 GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputFile,\r
696 Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType],\r
697 self.ModuleGuid, Fixed=Rule.Fixed,\r
698 CheckSum=Rule.CheckSum, Align=Rule.Alignment,\r
699 SectionAlign=Alignments\r
700 )\r
701 return FfsOutput\r
702\r
703 ## __GetGenFfsCmdParameter__() method\r
704 #\r
705 # Create parameter string for GenFfs\r
706 #\r
707 # @param self The object pointer\r
708 # @param Rule The rule object used to generate section\r
709 # @retval tuple (FileType, Fixed, CheckSum, Alignment)\r
710 #\r
711 def __GetGenFfsCmdParameter__(self, Rule):\r
712 result = tuple()\r
713 result += ('-t', Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType])\r
714 if Rule.Fixed != False:\r
715 result += ('-x',)\r
716 if Rule.CheckSum != False:\r
717 result += ('-s',)\r
718\r
719 if Rule.Alignment != None and Rule.Alignment != '':\r
720 result += ('-a', Rule.Alignment)\r
721\r
722 return result\r
da92f276
LG
723 \r
724 ## __GetBuildOutputMapFileVfrUniInfo() method\r
725 #\r
726 # Find the offset of UNI/INF object offset in the EFI image file.\r
727 #\r
728 # @param self The object pointer\r
729 # @param VfrUniBaseName A name list contain the UNI/INF object name.\r
730 # @retval RetValue A list contain offset of UNI/INF object.\r
731 # \r
732 def __GetBuildOutputMapFileVfrUniInfo(self, VfrUniBaseName):\r
733 \r
734 RetValue = []\r
735 \r
736 MapFileName = os.path.join(self.EfiOutputPath, self.BaseName + ".map")\r
737 try:\r
738 fInputfile = open(MapFileName, "r", 0)\r
739 try:\r
740 FileLinesList = fInputfile.readlines()\r
741 except:\r
742 EdkLogger.error("GenFds", FILE_READ_FAILURE, "File read failed for %s" %MapFileName,None)\r
743 finally:\r
744 fInputfile.close()\r
745 except:\r
746 EdkLogger.error("GenFds", FILE_OPEN_FAILURE, "File open failed for %s" %MapFileName,None)\r
747 \r
748 IsHex = False\r
749 for eachLine in FileLinesList:\r
750 for eachName in VfrUniBaseName.values():\r
751 if eachLine.find(eachName) != -1:\r
752 eachLine = eachLine.strip()\r
753 Element = eachLine.split()\r
754 #\r
755 # MSFT/ICC/EBC map file\r
756 #\r
757 if (len(Element) == 4):\r
758 try:\r
759 int (Element[2], 16)\r
760 IsHex = True\r
761 except:\r
762 IsHex = False\r
763 \r
764 if IsHex:\r
765 RetValue.append((eachName, Element[2]))\r
766 IsHex = False\r
767 #\r
768 # GCC map file\r
769 #\r
770 elif (len(Element) == 2) and Element[0].startswith("0x"):\r
771 RetValue.append((eachName, Element[0]))\r
772 \r
773 return RetValue\r
774 \r
775 ## __GenUniVfrOffsetFile() method\r
776 #\r
777 # Generate the offset file for the module which contain VFR or UNI file.\r
778 #\r
779 # @param self The object pointer\r
780 # @param VfrUniOffsetList A list contain the VFR/UNI offsets in the EFI image file.\r
781 # @param UniVfrOffsetFileName The output offset file name.\r
782 #\r
783 def __GenUniVfrOffsetFile(self, VfrUniOffsetList, UniVfrOffsetFileName):\r
784 \r
785 try:\r
786 fInputfile = open(UniVfrOffsetFileName, "wb+", 0)\r
787 except:\r
788 EdkLogger.error("GenFds", FILE_OPEN_FAILURE, "File open failed for %s" %UniVfrOffsetFileName,None)\r
789 \r
790 # Use a instance of StringIO to cache data\r
791 fStringIO = StringIO.StringIO('') \r
792 \r
793 for Item in VfrUniOffsetList:\r
794 if (Item[0].find("Strings") != -1):\r
795 #\r
796 # UNI offset in image.\r
797 # GUID + Offset\r
798 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }\r
799 #\r
800 UniGuid = [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]\r
801 UniGuid = [chr(ItemGuid) for ItemGuid in UniGuid]\r
802 fStringIO.write(''.join(UniGuid)) \r
803 UniValue = pack ('Q', int (Item[1], 16))\r
804 fStringIO.write (UniValue)\r
805 else:\r
806 #\r
807 # VFR binary offset in image.\r
808 # GUID + Offset\r
809 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };\r
810 #\r
811 VfrGuid = [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]\r
812 VfrGuid = [chr(ItemGuid) for ItemGuid in VfrGuid]\r
813 fStringIO.write(''.join(VfrGuid)) \r
814 type (Item[1]) \r
815 VfrValue = pack ('Q', int (Item[1], 16))\r
816 fStringIO.write (VfrValue)\r
817 \r
818 #\r
819 # write data into file.\r
820 #\r
821 try : \r
822 fInputfile.write (fStringIO.getvalue())\r
823 except:\r
824 EdkLogger.error("GenFds", FILE_WRITE_FAILURE, "Write data to file %s failed, please check whether the file been locked or using by other applications." %UniVfrOffsetFileName,None)\r
825 \r
826 fStringIO.close ()\r
827 fInputfile.close ()\r
828 \r
829 \r
830 \r
831 \r
832 \r
833 \r
834 \r
835 \r