]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/GenFds/FfsInfStatement.py
BaseTools: refactor and remove un-needed use of .keys() on dictionaries
[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
8565b582 4# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
77177984 5# Copyright (c) 2014-2016 Hewlett-Packard Development Company, L.P.<BR>\r
30fdf114 6#\r
40d841f6 7# This program and the accompanying materials\r
30fdf114
LG
8# are licensed and made available under the terms and conditions of the BSD License\r
9# which accompanies this distribution. The full text of the license may be found at\r
10# http://opensource.org/licenses/bsd-license.php\r
11#\r
12# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14#\r
15\r
16##\r
17# Import Modules\r
18#\r
19import Rule\r
1be2ed90 20import Common.LongFilePathOs as os\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
05cc51ad 31from Common.MultipleWorkspace import MultipleWorkspace as mws\r
30fdf114
LG
32from Common.String import *\r
33from Common.Misc import PathClass\r
34from Common.Misc import GuidStructureByteArrayToGuidString\r
97fa0ee9 35from Common.Misc import ProcessDuplicatedInf\r
22a99b87 36from Common.Misc import GetVariableOffset\r
30fdf114
LG
37from Common import EdkLogger\r
38from Common.BuildToolError import *\r
52302d4d
LG
39from GuidSection import GuidSection\r
40from FvImageSection import FvImageSection\r
41from Common.Misc import PeImageClass\r
b36d134f 42from AutoGen.GenDepex import DependencyExpression\r
e8a47801 43from PatchPcdValue.PatchPcdValue import PatchBinaryFile\r
1be2ed90
HC
44from Common.LongFilePathSupport import CopyLongFilePath\r
45from Common.LongFilePathSupport import OpenLongFilePath as open\r
6b17c11b 46import Common.GlobalData as GlobalData\r
37de70b7
YZ
47from DepexSection import DepexSection\r
48from Common.Misc import SaveFileOnChange\r
0537f332 49from Common.Expression import *\r
55c84777 50from Common.DataType import TAB_COMMON\r
30fdf114
LG
51\r
52## generate FFS from INF\r
53#\r
54#\r
55class FfsInfStatement(FfsInfStatementClassObject):\r
2bc3256c
LG
56 ## The mapping dictionary from datum type to its maximum number.\r
57 _MAX_SIZE_TYPE = {"BOOLEAN":0x01, "UINT8":0xFF, "UINT16":0xFFFF, "UINT32":0xFFFFFFFF, "UINT64":0xFFFFFFFFFFFFFFFF}\r
30fdf114
LG
58 ## The constructor\r
59 #\r
60 # @param self The object pointer\r
61 #\r
62 def __init__(self):\r
63 FfsInfStatementClassObject.__init__(self)\r
64 self.TargetOverrideList = []\r
65 self.ShadowFromInfFile = None\r
66 self.KeepRelocFromRule = None\r
67 self.InDsc = True\r
68 self.OptRomDefs = {}\r
da92f276 69 self.PiSpecVersion = '0x00000000'\r
4234283c 70 self.InfModule = None\r
b36d134f 71 self.FinalTargetSuffixMap = {}\r
79b74a03
LG
72 self.CurrentLineNum = None\r
73 self.CurrentLineContent = None\r
74 self.FileName = None\r
75 self.InfFileName = None\r
97fa0ee9
YL
76 self.OverrideGuid = None\r
77 self.PatchedBinFile = ''\r
7ae7dcb9 78 self.MacroDict = {}\r
37de70b7 79 self.Depex = False\r
4234283c 80\r
b36d134f 81 ## GetFinalTargetSuffixMap() method\r
4234283c
LG
82 #\r
83 # Get final build target list\r
b36d134f 84 def GetFinalTargetSuffixMap(self):\r
4234283c
LG
85 if not self.InfModule or not self.CurrentArch:\r
86 return []\r
b36d134f
LG
87 if not self.FinalTargetSuffixMap:\r
88 FinalBuildTargetList = GenFdsGlobalVariable.GetModuleCodaTargetList(self.InfModule, self.CurrentArch)\r
89 for File in FinalBuildTargetList:\r
90 self.FinalTargetSuffixMap.setdefault(os.path.splitext(File)[1], []).append(File)\r
91\r
92 # Check if current INF module has DEPEX\r
93 if '.depex' not in self.FinalTargetSuffixMap and self.InfModule.ModuleType != "USER_DEFINED" \\r
94 and not self.InfModule.DxsFile and not self.InfModule.LibraryClass:\r
95 ModuleType = self.InfModule.ModuleType\r
96 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
97\r
98 if ModuleType != DataType.SUP_MODULE_USER_DEFINED:\r
99 for LibraryClass in PlatformDataBase.LibraryClasses.GetKeys():\r
100 if LibraryClass.startswith("NULL") and PlatformDataBase.LibraryClasses[LibraryClass, ModuleType]:\r
101 self.InfModule.LibraryClasses[LibraryClass] = PlatformDataBase.LibraryClasses[LibraryClass, ModuleType]\r
102\r
103 StrModule = str(self.InfModule)\r
104 PlatformModule = None\r
105 if StrModule in PlatformDataBase.Modules:\r
106 PlatformModule = PlatformDataBase.Modules[StrModule]\r
107 for LibraryClass in PlatformModule.LibraryClasses:\r
108 if LibraryClass.startswith("NULL"):\r
109 self.InfModule.LibraryClasses[LibraryClass] = PlatformModule.LibraryClasses[LibraryClass]\r
110\r
111 DependencyList = [self.InfModule]\r
112 LibraryInstance = {}\r
113 DepexList = []\r
114 while len(DependencyList) > 0:\r
115 Module = DependencyList.pop(0)\r
116 if not Module:\r
117 continue\r
118 for Dep in Module.Depex[self.CurrentArch, ModuleType]:\r
119 if DepexList != []:\r
120 DepexList.append('AND')\r
121 DepexList.append('(')\r
122 DepexList.extend(Dep)\r
123 if DepexList[-1] == 'END': # no need of a END at this time\r
124 DepexList.pop()\r
125 DepexList.append(')')\r
126 if 'BEFORE' in DepexList or 'AFTER' in DepexList:\r
127 break\r
128 for LibName in Module.LibraryClasses:\r
129 if LibName in LibraryInstance:\r
130 continue\r
131 if PlatformModule and LibName in PlatformModule.LibraryClasses:\r
132 LibraryPath = PlatformModule.LibraryClasses[LibName]\r
133 else:\r
134 LibraryPath = PlatformDataBase.LibraryClasses[LibName, ModuleType]\r
135 if not LibraryPath:\r
136 LibraryPath = Module.LibraryClasses[LibName]\r
137 if not LibraryPath:\r
138 continue\r
139 LibraryModule = GenFdsGlobalVariable.WorkSpace.BuildObject[LibraryPath, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
140 LibraryInstance[LibName] = LibraryModule\r
141 DependencyList.append(LibraryModule)\r
142 if DepexList:\r
143 Dpx = DependencyExpression(DepexList, ModuleType, True)\r
144 if len(Dpx.PostfixNotation) != 0:\r
145 # It means this module has DEPEX\r
146 self.FinalTargetSuffixMap['.depex'] = [os.path.join(self.EfiOutputPath, self.BaseName) + '.depex']\r
147 return self.FinalTargetSuffixMap\r
4234283c 148\r
30fdf114
LG
149 ## __InfParse() method\r
150 #\r
151 # Parse inf file to get module information\r
152 #\r
153 # @param self The object pointer\r
154 # @param Dict dictionary contains macro and value pair\r
155 #\r
156 def __InfParse__(self, Dict = {}):\r
157\r
158 GenFdsGlobalVariable.VerboseLogger( " Begine parsing INf file : %s" %self.InfFileName)\r
159\r
160 self.InfFileName = self.InfFileName.replace('$(WORKSPACE)', '')\r
97fa0ee9
YL
161 if len(self.InfFileName) > 1 and self.InfFileName[0] == '\\' and self.InfFileName[1] == '\\':\r
162 pass\r
163 elif self.InfFileName[0] == '\\' or self.InfFileName[0] == '/' :\r
30fdf114
LG
164 self.InfFileName = self.InfFileName[1:]\r
165\r
166 if self.InfFileName.find('$') == -1:\r
167 InfPath = NormPath(self.InfFileName)\r
168 if not os.path.exists(InfPath):\r
169 InfPath = GenFdsGlobalVariable.ReplaceWorkspaceMacro(InfPath)\r
170 if not os.path.exists(InfPath):\r
171 EdkLogger.error("GenFds", GENFDS_ERROR, "Non-existant Module %s !" % (self.InfFileName))\r
172\r
173 self.CurrentArch = self.GetCurrentArch()\r
174 #\r
175 # Get the InfClass object\r
176 #\r
177\r
178 PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir)\r
e56468c0 179 ErrorCode, ErrorInfo = PathClassObj.Validate(".inf")\r
30fdf114
LG
180 if ErrorCode != 0:\r
181 EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)\r
97fa0ee9 182\r
4aa9826d
YZ
183 #\r
184 # Cache lower case version of INF path before processing FILE_GUID override\r
185 #\r
186 InfLowerPath = str(PathClassObj).lower()\r
97fa0ee9
YL
187 if self.OverrideGuid:\r
188 PathClassObj = ProcessDuplicatedInf(PathClassObj, self.OverrideGuid, GenFdsGlobalVariable.WorkSpaceDir)\r
4231a819 189 if self.CurrentArch is not None:\r
30fdf114 190\r
0d2711a6 191 Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
30fdf114
LG
192 #\r
193 # Set Ffs BaseName, MdouleGuid, ModuleType, Version, OutputPath\r
194 #\r
195 self.BaseName = Inf.BaseName\r
196 self.ModuleGuid = Inf.Guid\r
197 self.ModuleType = Inf.ModuleType\r
4231a819 198 if Inf.Specification is not None and 'PI_SPECIFICATION_VERSION' in Inf.Specification:\r
b303ea72 199 self.PiSpecVersion = Inf.Specification['PI_SPECIFICATION_VERSION']\r
30fdf114
LG
200 if Inf.AutoGenVersion < 0x00010005:\r
201 self.ModuleType = Inf.ComponentType\r
202 self.VersionString = Inf.Version\r
203 self.BinFileList = Inf.Binaries\r
204 self.SourceFileList = Inf.Sources\r
4231a819 205 if self.KeepReloc is None and Inf.Shadow:\r
30fdf114
LG
206 self.ShadowFromInfFile = Inf.Shadow\r
207\r
208 else:\r
55c84777 209 Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, TAB_COMMON, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
30fdf114
LG
210 self.BaseName = Inf.BaseName\r
211 self.ModuleGuid = Inf.Guid\r
212 self.ModuleType = Inf.ModuleType\r
4231a819 213 if Inf.Specification is not None and 'PI_SPECIFICATION_VERSION' in Inf.Specification:\r
b303ea72 214 self.PiSpecVersion = Inf.Specification['PI_SPECIFICATION_VERSION']\r
30fdf114
LG
215 self.VersionString = Inf.Version\r
216 self.BinFileList = Inf.Binaries\r
217 self.SourceFileList = Inf.Sources\r
218 if self.BinFileList == []:\r
219 EdkLogger.error("GenFds", GENFDS_ERROR,\r
220 "INF %s specified in FDF could not be found in build ARCH %s!" \\r
221 % (self.InfFileName, GenFdsGlobalVariable.ArchList))\r
222\r
97fa0ee9
YL
223 if self.OverrideGuid:\r
224 self.ModuleGuid = self.OverrideGuid\r
225\r
30fdf114
LG
226 if len(self.SourceFileList) != 0 and not self.InDsc:\r
227 EdkLogger.warn("GenFds", GENFDS_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % (self.InfFileName))\r
228\r
da92f276 229 if self.ModuleType == 'SMM_CORE' and int(self.PiSpecVersion, 16) < 0x0001000A:\r
b303ea72
LG
230 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
231\r
b19df640
SV
232 if self.ModuleType == 'MM_CORE_STANDALONE' and int(self.PiSpecVersion, 16) < 0x00010032:\r
233 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "MM_CORE_STANDALONE module type can't be used in the module with PI_SPECIFICATION_VERSION less than 0x00010032", File=self.InfFileName)\r
234\r
4231a819 235 if Inf._Defs is not None and len(Inf._Defs) > 0:\r
30fdf114 236 self.OptRomDefs.update(Inf._Defs)\r
2bc3256c 237\r
e8a47801
LG
238 self.PatchPcds = []\r
239 InfPcds = Inf.Pcds\r
240 Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
241 FdfPcdDict = GenFdsGlobalVariable.FdfParser.Profile.PcdDict\r
6f49996c 242 PlatformPcds = Platform.Pcds\r
2bc3256c
LG
243\r
244 # Workaround here: both build and GenFds tool convert the workspace path to lower case\r
245 # But INF file path in FDF and DSC file may have real case characters.\r
246 # Try to convert the path to lower case to see if PCDs value are override by DSC.\r
e8a47801
LG
247 DscModules = {}\r
248 for DscModule in Platform.Modules:\r
249 DscModules[str(DscModule).lower()] = Platform.Modules[DscModule]\r
250 for PcdKey in InfPcds:\r
251 Pcd = InfPcds[PcdKey]\r
252 if not hasattr(Pcd, 'Offset'):\r
253 continue\r
254 if Pcd.Type != 'PatchableInModule':\r
255 continue\r
2bc3256c 256 # Override Patchable PCD value by the value from DSC\r
e8a47801 257 PatchPcd = None\r
e8a47801
LG
258 if InfLowerPath in DscModules and PcdKey in DscModules[InfLowerPath].Pcds:\r
259 PatchPcd = DscModules[InfLowerPath].Pcds[PcdKey]\r
260 elif PcdKey in Platform.Pcds:\r
261 PatchPcd = Platform.Pcds[PcdKey]\r
262 DscOverride = False\r
263 if PatchPcd and Pcd.Type == PatchPcd.Type:\r
264 DefaultValue = PatchPcd.DefaultValue\r
265 DscOverride = True\r
2bc3256c
LG
266\r
267 # Override Patchable PCD value by the value from FDF\r
e8a47801
LG
268 FdfOverride = False\r
269 if PcdKey in FdfPcdDict:\r
270 DefaultValue = FdfPcdDict[PcdKey]\r
271 FdfOverride = True\r
2bc3256c 272\r
6b17c11b
YZ
273 # Override Patchable PCD value by the value from Build Option\r
274 BuildOptionOverride = False\r
275 if GlobalData.BuildOptionPcd:\r
276 for pcd in GlobalData.BuildOptionPcd:\r
277 if PcdKey == (pcd[1], pcd[0]):\r
8565b582
YZ
278 if pcd[2]:\r
279 continue\r
280 DefaultValue = pcd[3]\r
6b17c11b
YZ
281 BuildOptionOverride = True\r
282 break\r
283\r
284 if not DscOverride and not FdfOverride and not BuildOptionOverride:\r
e8a47801 285 continue\r
0537f332
YF
286\r
287 # Support Flexible PCD format\r
288 if DefaultValue:\r
289 try:\r
290 DefaultValue = ValueExpressionEx(DefaultValue, Pcd.DatumType, Platform._GuidDict)(True)\r
291 except BadExpression:\r
292 EdkLogger.error("GenFds", GENFDS_ERROR, 'PCD [%s.%s] Value "%s"' %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName, DefaultValue), File=self.InfFileName)\r
293\r
8565b582 294 if Pcd.InfDefaultValue:\r
0537f332 295 try:\r
8565b582 296 Pcd.InfDefaultValue = ValueExpressionEx(Pcd.InfDefaultValue, Pcd.DatumType, Platform._GuidDict)(True)\r
0537f332
YF
297 except BadExpression:\r
298 EdkLogger.error("GenFds", GENFDS_ERROR, 'PCD [%s.%s] Value "%s"' %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Pcd.DefaultValue),File=self.InfFileName)\r
299\r
2bc3256c 300 # Check value, if value are equal, no need to patch\r
e8a47801 301 if Pcd.DatumType == "VOID*":\r
8565b582 302 if Pcd.InfDefaultValue == DefaultValue or DefaultValue in [None, '']:\r
e8a47801 303 continue\r
2bc3256c 304 # Get the string size from FDF or DSC\r
e8a47801 305 if DefaultValue[0] == 'L':\r
2bc3256c 306 # Remove L"", but the '\0' must be appended\r
e8a47801
LG
307 MaxDatumSize = str((len(DefaultValue) - 2) * 2)\r
308 elif DefaultValue[0] == '{':\r
309 MaxDatumSize = str(len(DefaultValue.split(',')))\r
310 else:\r
311 MaxDatumSize = str(len(DefaultValue) - 1)\r
312 if DscOverride:\r
313 Pcd.MaxDatumSize = PatchPcd.MaxDatumSize\r
2bc3256c 314 # If no defined the maximum size in DSC, try to get current size from INF\r
e8a47801 315 if Pcd.MaxDatumSize in ['', None]:\r
8565b582 316 Pcd.MaxDatumSize = str(len(Pcd.InfDefaultValue.split(',')))\r
e8a47801
LG
317 else:\r
318 Base1 = Base2 = 10\r
8565b582 319 if Pcd.InfDefaultValue.upper().startswith('0X'):\r
e8a47801
LG
320 Base1 = 16\r
321 if DefaultValue.upper().startswith('0X'):\r
322 Base2 = 16\r
323 try:\r
8565b582 324 PcdValueInImg = int(Pcd.InfDefaultValue, Base1)\r
e8a47801
LG
325 PcdValueInDscOrFdf = int(DefaultValue, Base2)\r
326 if PcdValueInImg == PcdValueInDscOrFdf:\r
327 continue\r
328 except:\r
329 continue\r
2bc3256c 330 # Check the Pcd size and data type\r
e8a47801
LG
331 if Pcd.DatumType == "VOID*":\r
332 if int(MaxDatumSize) > int(Pcd.MaxDatumSize):\r
333 EdkLogger.error("GenFds", GENFDS_ERROR, "The size of VOID* type PCD '%s.%s' exceeds its maximum size %d bytes." \\r
334 % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, int(MaxDatumSize) - int(Pcd.MaxDatumSize)))\r
335 else:\r
336 if PcdValueInDscOrFdf > FfsInfStatement._MAX_SIZE_TYPE[Pcd.DatumType] \\r
337 or PcdValueInImg > FfsInfStatement._MAX_SIZE_TYPE[Pcd.DatumType]:\r
338 EdkLogger.error("GenFds", GENFDS_ERROR, "The size of %s type PCD '%s.%s' doesn't match its data type." \\r
339 % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
97fa0ee9
YL
340 self.PatchPcds.append((Pcd, DefaultValue))\r
341\r
4234283c 342 self.InfModule = Inf\r
e8a47801
LG
343 self.PcdIsDriver = Inf.PcdIsDriver\r
344 self.IsBinaryModule = Inf.IsBinaryModule\r
37de70b7
YZ
345 Inf._GetDepex()\r
346 Inf._GetDepexExpression()\r
347 if len(Inf._Depex.data) > 0 and len(Inf._DepexExpression.data) > 0:\r
348 self.Depex = True\r
349\r
e8a47801
LG
350 GenFdsGlobalVariable.VerboseLogger("BaseName : %s" % self.BaseName)\r
351 GenFdsGlobalVariable.VerboseLogger("ModuleGuid : %s" % self.ModuleGuid)\r
352 GenFdsGlobalVariable.VerboseLogger("ModuleType : %s" % self.ModuleType)\r
353 GenFdsGlobalVariable.VerboseLogger("VersionString : %s" % self.VersionString)\r
354 GenFdsGlobalVariable.VerboseLogger("InfFileName :%s" % self.InfFileName)\r
30fdf114
LG
355\r
356 #\r
357 # Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${MdouleName}\\r
358 #\r
359\r
360 self.OutputPath = os.path.join(GenFdsGlobalVariable.FfsDir, \\r
361 self.ModuleGuid + self.BaseName)\r
362 if not os.path.exists(self.OutputPath) :\r
363 os.makedirs(self.OutputPath)\r
364\r
37de70b7 365 self.EfiOutputPath, self.EfiDebugPath = self.__GetEFIOutPutPath__()\r
30fdf114
LG
366 GenFdsGlobalVariable.VerboseLogger( "ModuelEFIPath: " + self.EfiOutputPath)\r
367\r
97fa0ee9 368 ## PatchEfiFile\r
e8a47801
LG
369 #\r
370 # Patch EFI file with patch PCD\r
371 #\r
372 # @param EfiFile: EFI file needs to be patched.\r
373 # @retval: Full path of patched EFI file: self.OutputPath + EfiFile base name\r
374 # If passed in file does not end with efi, return as is\r
375 #\r
97fa0ee9 376 def PatchEfiFile(self, EfiFile, FileType):\r
b21a13fb
YZ
377 #\r
378 # If the module does not have any patches, then return path to input file\r
379 # \r
e8a47801
LG
380 if not self.PatchPcds:\r
381 return EfiFile\r
b21a13fb
YZ
382\r
383 #\r
384 # Only patch file if FileType is PE32 or ModuleType is USER_DEFINED\r
385 # \r
97fa0ee9
YL
386 if FileType != 'PE32' and self.ModuleType != "USER_DEFINED":\r
387 return EfiFile\r
b21a13fb
YZ
388\r
389 #\r
390 # Generate path to patched output file\r
391 #\r
392 Basename = os.path.basename(EfiFile)\r
393 Output = os.path.normpath (os.path.join(self.OutputPath, Basename))\r
394\r
395 #\r
396 # If this file has already been patched, then return the path to the patched file\r
397 #\r
398 if self.PatchedBinFile == Output:\r
399 return Output\r
400\r
401 #\r
402 # If a different file from the same module has already been patched, then generate an error\r
403 # \r
97fa0ee9
YL
404 if self.PatchedBinFile:\r
405 EdkLogger.error("GenFds", GENFDS_ERROR,\r
406 'Only one binary file can be patched:\n'\r
407 ' a binary file has been patched: %s\n'\r
408 ' current file: %s' % (self.PatchedBinFile, EfiFile),\r
409 File=self.InfFileName)\r
b21a13fb
YZ
410\r
411 #\r
412 # Copy unpatched file contents to output file location to perform patching\r
413 # \r
1be2ed90 414 CopyLongFilePath(EfiFile, Output)\r
b21a13fb
YZ
415\r
416 #\r
417 # Apply patches to patched output file\r
418 # \r
97fa0ee9
YL
419 for Pcd, Value in self.PatchPcds:\r
420 RetVal, RetStr = PatchBinaryFile(Output, int(Pcd.Offset, 0), Pcd.DatumType, Value, Pcd.MaxDatumSize)\r
e8a47801
LG
421 if RetVal:\r
422 EdkLogger.error("GenFds", GENFDS_ERROR, RetStr, File=self.InfFileName)\r
b21a13fb
YZ
423\r
424 #\r
425 # Save the path of the patched output file\r
426 # \r
427 self.PatchedBinFile = Output\r
428\r
429 #\r
430 # Return path to patched output file\r
431 # \r
e8a47801 432 return Output\r
b21a13fb 433\r
30fdf114
LG
434 ## GenFfs() method\r
435 #\r
436 # Generate FFS\r
437 #\r
52302d4d
LG
438 # @param self The object pointer\r
439 # @param Dict dictionary contains macro and value pair\r
440 # @param FvChildAddr Array of the inside FvImage base address\r
441 # @param FvParentAddr Parent Fv base address\r
442 # @retval string Generated FFS file name\r
30fdf114 443 #\r
a743986d 444 def GenFfs(self, Dict = {}, FvChildAddr = [], FvParentAddr=None, IsMakefile=False, FvName=None):\r
30fdf114
LG
445 #\r
446 # Parse Inf file get Module related information\r
447 #\r
448\r
449 self.__InfParse__(Dict)\r
37de70b7 450 Arch = self.GetCurrentArch()\r
05cc51ad 451 SrcFile = mws.join( GenFdsGlobalVariable.WorkSpaceDir , self.InfFileName);\r
0acb3d28 452 DestFile = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs')\r
6780eef1 453 \r
0acb3d28
AC
454 SrcFileDir = "."\r
455 SrcPath = os.path.dirname(SrcFile)\r
456 SrcFileName = os.path.basename(SrcFile)\r
457 SrcFileBase, SrcFileExt = os.path.splitext(SrcFileName) \r
458 DestPath = os.path.dirname(DestFile)\r
459 DestFileName = os.path.basename(DestFile)\r
460 DestFileBase, DestFileExt = os.path.splitext(DestFileName) \r
461 self.MacroDict = {\r
462 # source file\r
463 "${src}" : SrcFile,\r
464 "${s_path}" : SrcPath,\r
465 "${s_dir}" : SrcFileDir,\r
466 "${s_name}" : SrcFileName,\r
467 "${s_base}" : SrcFileBase,\r
468 "${s_ext}" : SrcFileExt,\r
469 # destination file\r
470 "${dst}" : DestFile,\r
471 "${d_path}" : DestPath,\r
472 "${d_name}" : DestFileName,\r
473 "${d_base}" : DestFileBase,\r
474 "${d_ext}" : DestFileExt\r
475 }\r
6780eef1
LG
476 #\r
477 # Allow binary type module not specify override rule in FDF file.\r
478 # \r
97fa0ee9 479 if len(self.BinFileList) > 0:\r
4231a819 480 if self.Rule is None or self.Rule == "":\r
6780eef1 481 self.Rule = "BINARY"\r
37de70b7
YZ
482\r
483 if not IsMakefile and GenFdsGlobalVariable.EnableGenfdsMultiThread and self.Rule != 'BINARY':\r
484 IsMakefile = True\r
30fdf114
LG
485 #\r
486 # Get the rule of how to generate Ffs file\r
487 #\r
488 Rule = self.__GetRule__()\r
489 GenFdsGlobalVariable.VerboseLogger( "Packing binaries from inf file : %s" %self.InfFileName)\r
b303ea72
LG
490 #\r
491 # Convert Fv File Type for PI1.1 SMM driver.\r
492 #\r
da92f276 493 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:\r
b303ea72
LG
494 if Rule.FvFileType == 'DRIVER':\r
495 Rule.FvFileType = 'SMM'\r
496 #\r
497 # Framework SMM Driver has no SMM FV file type\r
498 #\r
da92f276 499 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:\r
b303ea72
LG
500 if Rule.FvFileType == 'SMM' or Rule.FvFileType == 'SMM_CORE':\r
501 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
502 #\r
503 # For the rule only has simpleFile\r
504 #\r
37de70b7 505 MakefilePath = None\r
a146c532
FY
506 if self.IsBinaryModule:\r
507 IsMakefile = False\r
37de70b7
YZ
508 if IsMakefile:\r
509 MakefilePath = self.InfFileName, Arch\r
a146c532 510 if isinstance (Rule, RuleSimpleFile.RuleSimpleFile):\r
37de70b7
YZ
511 SectionOutputList = self.__GenSimpleFileSection__(Rule, IsMakefile=IsMakefile)\r
512 FfsOutput = self.__GenSimpleFileFfs__(Rule, SectionOutputList, MakefilePath=MakefilePath)\r
30fdf114
LG
513 return FfsOutput\r
514 #\r
515 # For Rule has ComplexFile\r
516 #\r
517 elif isinstance(Rule, RuleComplexFile.RuleComplexFile):\r
37de70b7
YZ
518 InputSectList, InputSectAlignments = self.__GenComplexFileSection__(Rule, FvChildAddr, FvParentAddr, IsMakefile=IsMakefile)\r
519 FfsOutput = self.__GenComplexFileFfs__(Rule, InputSectList, InputSectAlignments, MakefilePath=MakefilePath)\r
30fdf114
LG
520 return FfsOutput\r
521\r
522 ## __ExtendMacro__() method\r
523 #\r
524 # Replace macro with its value\r
525 #\r
526 # @param self The object pointer\r
527 # @param String The string to be replaced\r
528 # @retval string Macro replaced string\r
529 #\r
530 def __ExtendMacro__ (self, String):\r
531 MacroDict = {\r
532 '$(INF_OUTPUT)' : self.EfiOutputPath,\r
533 '$(MODULE_NAME)' : self.BaseName,\r
534 '$(BUILD_NUMBER)': self.BuildNum,\r
535 '$(INF_VERSION)' : self.VersionString,\r
536 '$(NAMED_GUID)' : self.ModuleGuid\r
537 }\r
538 String = GenFdsGlobalVariable.MacroExtend(String, MacroDict)\r
0acb3d28 539 String = GenFdsGlobalVariable.MacroExtend(String, self.MacroDict) \r
30fdf114
LG
540 return String\r
541\r
542 ## __GetRule__() method\r
543 #\r
544 # Get correct rule for generating FFS for this INF\r
545 #\r
546 # @param self The object pointer\r
547 # @retval Rule Rule object\r
548 #\r
549 def __GetRule__ (self) :\r
550 CurrentArchList = []\r
4231a819 551 if self.CurrentArch is None:\r
30fdf114
LG
552 CurrentArchList = ['common']\r
553 else:\r
554 CurrentArchList.append(self.CurrentArch)\r
555\r
556 for CurrentArch in CurrentArchList:\r
557 RuleName = 'RULE' + \\r
558 '.' + \\r
559 CurrentArch.upper() + \\r
560 '.' + \\r
561 self.ModuleType.upper()\r
4231a819 562 if self.Rule is not None:\r
30fdf114
LG
563 RuleName = RuleName + \\r
564 '.' + \\r
565 self.Rule.upper()\r
566\r
567 Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName)\r
4231a819 568 if Rule is not None:\r
30fdf114
LG
569 GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName)\r
570 return Rule\r
571\r
572 RuleName = 'RULE' + \\r
573 '.' + \\r
55c84777 574 TAB_COMMON + \\r
30fdf114
LG
575 '.' + \\r
576 self.ModuleType.upper()\r
577\r
4231a819 578 if self.Rule is not None:\r
30fdf114
LG
579 RuleName = RuleName + \\r
580 '.' + \\r
581 self.Rule.upper()\r
582\r
583 GenFdsGlobalVariable.VerboseLogger ('Trying to apply common rule %s for INF %s' % (RuleName, self.InfFileName))\r
584\r
585 Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName)\r
4231a819 586 if Rule is not None:\r
30fdf114
LG
587 GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName)\r
588 return Rule\r
589\r
4231a819 590 if Rule is None :\r
30fdf114
LG
591 EdkLogger.error("GenFds", GENFDS_ERROR, 'Don\'t Find common rule %s for INF %s' \\r
592 % (RuleName, self.InfFileName))\r
593\r
594 ## __GetPlatformArchList__() method\r
595 #\r
596 # Get Arch list this INF built under\r
597 #\r
598 # @param self The object pointer\r
599 # @retval list Arch list\r
600 #\r
601 def __GetPlatformArchList__(self):\r
602\r
05cc51ad 603 InfFileKey = os.path.normpath(mws.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName))\r
30fdf114 604 DscArchList = []\r
77177984
TP
605 for Arch in GenFdsGlobalVariable.ArchList :\r
606 PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]\r
4231a819 607 if PlatformDataBase is not None:\r
77177984
TP
608 if InfFileKey in PlatformDataBase.Modules:\r
609 DscArchList.append (Arch)\r
4ce415e5
YZ
610 else:\r
611 #\r
612 # BaseTools support build same module more than once, the module path with FILE_GUID overridden has\r
613 # the file name FILE_GUIDmodule.inf, then PlatformDataBase.Modules use FILE_GUIDmodule.inf as key,\r
614 # but the path (self.MetaFile.Path) is the real path\r
615 #\r
9eb87141 616 for key in PlatformDataBase.Modules:\r
4ce415e5
YZ
617 if InfFileKey == str((PlatformDataBase.Modules[key]).MetaFile.Path):\r
618 DscArchList.append (Arch)\r
619 break\r
4afd3d04 620\r
30fdf114
LG
621 return DscArchList\r
622\r
623 ## GetCurrentArch() method\r
624 #\r
625 # Get Arch list of the module from this INF is to be placed into flash\r
626 #\r
627 # @param self The object pointer\r
628 # @retval list Arch list\r
629 #\r
630 def GetCurrentArch(self) :\r
631\r
632 TargetArchList = GenFdsGlobalVariable.ArchList\r
633\r
634 PlatformArchList = self.__GetPlatformArchList__()\r
635\r
636 CurArchList = TargetArchList\r
637 if PlatformArchList != []:\r
638 CurArchList = list(set (TargetArchList) & set (PlatformArchList))\r
639 GenFdsGlobalVariable.VerboseLogger ("Valid target architecture(s) is : " + " ".join(CurArchList))\r
640\r
641 ArchList = []\r
642 if self.KeyStringList != []:\r
643 for Key in self.KeyStringList:\r
644 Key = GenFdsGlobalVariable.MacroExtend(Key)\r
645 Target, Tag, Arch = Key.split('_')\r
646 if Arch in CurArchList:\r
647 ArchList.append(Arch)\r
648 if Target not in self.TargetOverrideList:\r
649 self.TargetOverrideList.append(Target)\r
650 else:\r
651 ArchList = CurArchList\r
652\r
653 UseArchList = TargetArchList\r
4231a819 654 if self.UseArch is not None:\r
30fdf114
LG
655 UseArchList = []\r
656 UseArchList.append(self.UseArch)\r
657 ArchList = list(set (UseArchList) & set (ArchList))\r
658\r
659 self.InfFileName = NormPath(self.InfFileName)\r
660 if len(PlatformArchList) == 0:\r
661 self.InDsc = False\r
662 PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir)\r
e56468c0 663 ErrorCode, ErrorInfo = PathClassObj.Validate(".inf")\r
30fdf114
LG
664 if ErrorCode != 0:\r
665 EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)\r
666 if len(ArchList) == 1:\r
667 Arch = ArchList[0]\r
668 return Arch\r
669 elif len(ArchList) > 1:\r
670 if len(PlatformArchList) == 0:\r
671 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
672 else:\r
673 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
674 else:\r
675 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
676 % (self.InfFileName, str(PlatformArchList), GenFdsGlobalVariable.ActivePlatform, str(set (UseArchList) & set (TargetArchList))))\r
677\r
678 ## __GetEFIOutPutPath__() method\r
679 #\r
680 # Get the output path for generated files\r
681 #\r
682 # @param self The object pointer\r
683 # @retval string Path that output files from this INF go to\r
684 #\r
685 def __GetEFIOutPutPath__(self):\r
686 Arch = ''\r
687 OutputPath = ''\r
37de70b7 688 DebugPath = ''\r
30fdf114 689 (ModulePath, FileName) = os.path.split(self.InfFileName)\r
79b74a03 690 Index = FileName.rfind('.')\r
30fdf114 691 FileName = FileName[0:Index]\r
97fa0ee9
YL
692 if self.OverrideGuid:\r
693 FileName = self.OverrideGuid\r
30fdf114 694 Arch = "NoneArch"\r
4231a819 695 if self.CurrentArch is not None:\r
30fdf114
LG
696 Arch = self.CurrentArch\r
697\r
698 OutputPath = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch],\r
699 Arch ,\r
700 ModulePath,\r
701 FileName,\r
702 'OUTPUT'\r
703 )\r
37de70b7
YZ
704 DebugPath = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch],\r
705 Arch ,\r
706 ModulePath,\r
707 FileName,\r
708 'DEBUG'\r
709 )\r
30fdf114 710 OutputPath = os.path.realpath(OutputPath)\r
37de70b7
YZ
711 DebugPath = os.path.realpath(DebugPath)\r
712 return OutputPath, DebugPath\r
30fdf114
LG
713\r
714 ## __GenSimpleFileSection__() method\r
715 #\r
716 # Generate section by specified file name or a list of files with file extension\r
717 #\r
718 # @param self The object pointer\r
719 # @param Rule The rule object used to generate section\r
720 # @retval string File name of the generated section file\r
721 #\r
37de70b7 722 def __GenSimpleFileSection__(self, Rule, IsMakefile = False):\r
30fdf114
LG
723 #\r
724 # Prepare the parameter of GenSection\r
725 #\r
726 FileList = []\r
727 OutputFileList = []\r
52302d4d 728 GenSecInputFile = None\r
4231a819 729 if Rule.FileName is not None:\r
30fdf114 730 GenSecInputFile = self.__ExtendMacro__(Rule.FileName)\r
da92f276
LG
731 if os.path.isabs(GenSecInputFile):\r
732 GenSecInputFile = os.path.normpath(GenSecInputFile)\r
733 else:\r
52302d4d 734 GenSecInputFile = os.path.normpath(os.path.join(self.EfiOutputPath, GenSecInputFile))\r
30fdf114
LG
735 else:\r
736 FileList, IsSect = Section.Section.GetFileList(self, '', Rule.FileExtension)\r
737\r
738 Index = 1\r
b303ea72
LG
739 SectionType = Rule.SectionType\r
740 #\r
741 # Convert Fv Section Type for PI1.1 SMM driver.\r
742 #\r
da92f276 743 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:\r
b303ea72
LG
744 if SectionType == 'DXE_DEPEX':\r
745 SectionType = 'SMM_DEPEX'\r
746 #\r
747 # Framework SMM Driver has no SMM_DEPEX section type\r
748 #\r
da92f276 749 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:\r
b303ea72
LG
750 if SectionType == 'SMM_DEPEX':\r
751 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName)\r
30fdf114
LG
752 NoStrip = True\r
753 if self.ModuleType in ('SEC', 'PEI_CORE', 'PEIM'):\r
4231a819 754 if self.KeepReloc is not None:\r
30fdf114 755 NoStrip = self.KeepReloc\r
4231a819 756 elif Rule.KeepReloc is not None:\r
30fdf114 757 NoStrip = Rule.KeepReloc\r
4231a819 758 elif self.ShadowFromInfFile is not None:\r
30fdf114
LG
759 NoStrip = self.ShadowFromInfFile\r
760\r
761 if FileList != [] :\r
762 for File in FileList:\r
763\r
764 SecNum = '%d' %Index\r
765 GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \\r
766 Ffs.Ffs.SectionSuffix[SectionType] + 'SEC' + SecNum\r
767 Index = Index + 1\r
768 OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)\r
52302d4d
LG
769 File = GenFdsGlobalVariable.MacroExtend(File, Dict, self.CurrentArch)\r
770\r
771 #Get PE Section alignment when align is set to AUTO\r
772 if self.Alignment == 'Auto' and (SectionType == 'PE32' or SectionType == 'TE'):\r
773 ImageObj = PeImageClass (File)\r
774 if ImageObj.SectionAlignment < 0x400:\r
775 self.Alignment = str (ImageObj.SectionAlignment)\r
e921f58d 776 elif ImageObj.SectionAlignment < 0x100000:\r
52302d4d 777 self.Alignment = str (ImageObj.SectionAlignment / 0x400) + 'K'\r
e921f58d
YZ
778 else:\r
779 self.Alignment = str (ImageObj.SectionAlignment / 0x100000) + 'M'\r
30fdf114
LG
780\r
781 if not NoStrip:\r
782 FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')\r
783 if not os.path.exists(FileBeforeStrip) or \\r
1be2ed90
HC
784 (os.path.getmtime(File) > os.path.getmtime(FileBeforeStrip)):\r
785 CopyLongFilePath(File, FileBeforeStrip)\r
30fdf114
LG
786 StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')\r
787 GenFdsGlobalVariable.GenerateFirmwareImage(\r
37de70b7
YZ
788 StrippedFile,\r
789 [File],\r
790 Strip=True,\r
791 IsMakefile=IsMakefile\r
792 )\r
30fdf114
LG
793 File = StrippedFile\r
794\r
795 if SectionType == 'TE':\r
796 TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')\r
797 GenFdsGlobalVariable.GenerateFirmwareImage(\r
37de70b7
YZ
798 TeFile,\r
799 [File],\r
800 Type='te',\r
801 IsMakefile=IsMakefile\r
802 )\r
30fdf114 803 File = TeFile\r
37de70b7 804 GenFdsGlobalVariable.GenerateSection(OutputFile, [File], Section.Section.SectionType[SectionType], IsMakefile=IsMakefile)\r
30fdf114
LG
805 OutputFileList.append(OutputFile)\r
806 else:\r
807 SecNum = '%d' %Index\r
808 GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \\r
809 Ffs.Ffs.SectionSuffix[SectionType] + 'SEC' + SecNum\r
810 OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)\r
52302d4d
LG
811 GenSecInputFile = GenFdsGlobalVariable.MacroExtend(GenSecInputFile, Dict, self.CurrentArch)\r
812\r
813 #Get PE Section alignment when align is set to AUTO\r
814 if self.Alignment == 'Auto' and (SectionType == 'PE32' or SectionType == 'TE'):\r
815 ImageObj = PeImageClass (GenSecInputFile)\r
816 if ImageObj.SectionAlignment < 0x400:\r
817 self.Alignment = str (ImageObj.SectionAlignment)\r
e921f58d 818 elif ImageObj.SectionAlignment < 0x100000:\r
52302d4d 819 self.Alignment = str (ImageObj.SectionAlignment / 0x400) + 'K'\r
e921f58d
YZ
820 else:\r
821 self.Alignment = str (ImageObj.SectionAlignment / 0x100000) + 'M'\r
30fdf114
LG
822\r
823 if not NoStrip:\r
824 FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')\r
825 if not os.path.exists(FileBeforeStrip) or \\r
1be2ed90
HC
826 (os.path.getmtime(GenSecInputFile) > os.path.getmtime(FileBeforeStrip)):\r
827 CopyLongFilePath(GenSecInputFile, FileBeforeStrip)\r
828\r
30fdf114
LG
829 StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')\r
830 GenFdsGlobalVariable.GenerateFirmwareImage(\r
37de70b7
YZ
831 StrippedFile,\r
832 [GenSecInputFile],\r
833 Strip=True,\r
834 IsMakefile=IsMakefile\r
835 )\r
30fdf114
LG
836 GenSecInputFile = StrippedFile\r
837\r
838 if SectionType == 'TE':\r
839 TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')\r
840 GenFdsGlobalVariable.GenerateFirmwareImage(\r
37de70b7
YZ
841 TeFile,\r
842 [GenSecInputFile],\r
843 Type='te',\r
844 IsMakefile=IsMakefile\r
845 )\r
30fdf114 846 GenSecInputFile = TeFile\r
37de70b7 847 GenFdsGlobalVariable.GenerateSection(OutputFile, [GenSecInputFile], Section.Section.SectionType[SectionType], IsMakefile=IsMakefile)\r
30fdf114
LG
848 OutputFileList.append(OutputFile)\r
849\r
850 return OutputFileList\r
851\r
852 ## __GenSimpleFileFfs__() method\r
853 #\r
854 # Generate FFS\r
855 #\r
856 # @param self The object pointer\r
857 # @param Rule The rule object used to generate section\r
858 # @param InputFileList The output file list from GenSection\r
859 # @retval string Generated FFS file name\r
860 #\r
37de70b7 861 def __GenSimpleFileFfs__(self, Rule, InputFileList, MakefilePath = None):\r
30fdf114
LG
862 FfsOutput = self.OutputPath + \\r
863 os.sep + \\r
864 self.__ExtendMacro__(Rule.NameGuid) + \\r
865 '.ffs'\r
866\r
867 GenFdsGlobalVariable.VerboseLogger(self.__ExtendMacro__(Rule.NameGuid))\r
868 InputSection = []\r
869 SectionAlignments = []\r
870 for InputFile in InputFileList:\r
871 InputSection.append(InputFile)\r
52302d4d 872 SectionAlignments.append(Rule.SectAlignment)\r
30fdf114 873\r
4231a819 874 if Rule.NameGuid is not None and Rule.NameGuid.startswith('PCD('):\r
30fdf114
LG
875 PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid)\r
876 if len(PcdValue) == 0:\r
877 EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \\r
878 % (Rule.NameGuid))\r
879 if PcdValue.startswith('{'):\r
880 PcdValue = GuidStructureByteArrayToGuidString(PcdValue)\r
881 RegistryGuidStr = PcdValue\r
882 if len(RegistryGuidStr) == 0:\r
883 EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \\r
884 % (Rule.NameGuid))\r
885 self.ModuleGuid = RegistryGuidStr\r
886\r
37de70b7
YZ
887 GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputSection,\r
888 Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType],\r
889 self.ModuleGuid, Fixed=Rule.Fixed,\r
890 CheckSum=Rule.CheckSum, Align=Rule.Alignment,\r
891 SectionAlign=SectionAlignments,\r
892 MakefilePath=MakefilePath\r
893 )\r
30fdf114
LG
894 return FfsOutput\r
895\r
896 ## __GenComplexFileSection__() method\r
897 #\r
898 # Generate section by sections in Rule\r
899 #\r
52302d4d
LG
900 # @param self The object pointer\r
901 # @param Rule The rule object used to generate section\r
902 # @param FvChildAddr Array of the inside FvImage base address\r
903 # @param FvParentAddr Parent Fv base address\r
904 # @retval string File name of the generated section file\r
30fdf114 905 #\r
37de70b7 906 def __GenComplexFileSection__(self, Rule, FvChildAddr, FvParentAddr, IsMakefile = False):\r
30fdf114 907 if self.ModuleType in ('SEC', 'PEI_CORE', 'PEIM'):\r
4231a819 908 if Rule.KeepReloc is not None:\r
30fdf114
LG
909 self.KeepRelocFromRule = Rule.KeepReloc\r
910 SectFiles = []\r
911 SectAlignments = []\r
912 Index = 1\r
37de70b7 913 HasGeneratedFlag = False\r
e8a47801
LG
914 if self.PcdIsDriver == 'PEI_PCD_DRIVER':\r
915 if self.IsBinaryModule:\r
916 PcdExDbFileName = os.path.join(GenFdsGlobalVariable.FvDir, "PEIPcdDataBase.raw")\r
917 else:\r
918 PcdExDbFileName = os.path.join(self.EfiOutputPath, "PEIPcdDataBase.raw")\r
919 PcdExDbSecName = os.path.join(self.OutputPath, "PEIPcdDataBaseSec.raw")\r
920 GenFdsGlobalVariable.GenerateSection(PcdExDbSecName,\r
921 [PcdExDbFileName],\r
922 "EFI_SECTION_RAW",\r
37de70b7 923 IsMakefile = IsMakefile\r
e8a47801
LG
924 )\r
925 SectFiles.append(PcdExDbSecName)\r
926 SectAlignments.append(None)\r
927 elif self.PcdIsDriver == 'DXE_PCD_DRIVER':\r
928 if self.IsBinaryModule:\r
929 PcdExDbFileName = os.path.join(GenFdsGlobalVariable.FvDir, "DXEPcdDataBase.raw")\r
930 else:\r
931 PcdExDbFileName = os.path.join(self.EfiOutputPath, "DXEPcdDataBase.raw")\r
932 PcdExDbSecName = os.path.join(self.OutputPath, "DXEPcdDataBaseSec.raw")\r
933 GenFdsGlobalVariable.GenerateSection(PcdExDbSecName,\r
37de70b7
YZ
934 [PcdExDbFileName],\r
935 "EFI_SECTION_RAW",\r
936 IsMakefile = IsMakefile\r
937 )\r
e8a47801
LG
938 SectFiles.append(PcdExDbSecName)\r
939 SectAlignments.append(None)\r
30fdf114
LG
940 for Sect in Rule.SectionList:\r
941 SecIndex = '%d' %Index\r
942 SectList = []\r
b303ea72
LG
943 #\r
944 # Convert Fv Section Type for PI1.1 SMM driver.\r
945 #\r
da92f276 946 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A:\r
b303ea72
LG
947 if Sect.SectionType == 'DXE_DEPEX':\r
948 Sect.SectionType = 'SMM_DEPEX'\r
949 #\r
950 # Framework SMM Driver has no SMM_DEPEX section type\r
951 #\r
da92f276 952 if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A:\r
b303ea72
LG
953 if Sect.SectionType == 'SMM_DEPEX':\r
954 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName)\r
52302d4d
LG
955 #\r
956 # process the inside FvImage from FvSection or GuidSection\r
957 #\r
958 if FvChildAddr != []:\r
959 if isinstance(Sect, FvImageSection):\r
960 Sect.FvAddr = FvChildAddr.pop(0)\r
961 elif isinstance(Sect, GuidSection):\r
962 Sect.FvAddr = FvChildAddr\r
4231a819 963 if FvParentAddr is not None and isinstance(Sect, GuidSection):\r
52302d4d
LG
964 Sect.FvParentAddr = FvParentAddr\r
965 \r
30fdf114 966 if Rule.KeyStringList != []:\r
37de70b7 967 SectList, Align = Sect.GenSection(self.OutputPath , self.ModuleGuid, SecIndex, Rule.KeyStringList, self, IsMakefile = IsMakefile)\r
30fdf114 968 else :\r
37de70b7 969 SectList, Align = Sect.GenSection(self.OutputPath , self.ModuleGuid, SecIndex, self.KeyStringList, self, IsMakefile = IsMakefile)\r
da92f276 970 \r
37de70b7 971 if not HasGeneratedFlag:\r
da92f276 972 UniVfrOffsetFileSection = "" \r
05cc51ad 973 ModuleFileName = mws.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName)\r
da92f276
LG
974 InfData = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClass(ModuleFileName), self.CurrentArch]\r
975 #\r
976 # Search the source list in InfData to find if there are .vfr file exist.\r
977 #\r
978 VfrUniBaseName = {}\r
979 VfrUniOffsetList = []\r
980 for SourceFile in InfData.Sources:\r
981 if SourceFile.Type.upper() == ".VFR" :\r
982 #\r
983 # search the .map file to find the offset of vfr binary in the PE32+/TE file. \r
984 #\r
985 VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin")\r
986 if SourceFile.Type.upper() == ".UNI" :\r
987 #\r
988 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file. \r
989 #\r
990 VfrUniBaseName["UniOffsetName"] = (self.BaseName + "Strings")\r
991 \r
992 \r
993 if len(VfrUniBaseName) > 0:\r
37de70b7
YZ
994 if IsMakefile:\r
995 if InfData.BuildType != 'UEFI_HII':\r
996 UniVfrOffsetFileName = os.path.join(self.OutputPath, self.BaseName + '.offset')\r
997 UniVfrOffsetFileSection = os.path.join(self.OutputPath, self.BaseName + 'Offset' + '.raw')\r
998 UniVfrOffsetFileNameList = []\r
999 UniVfrOffsetFileNameList.append(UniVfrOffsetFileName)\r
1000 TrimCmd = "Trim --Vfr-Uni-Offset -o %s --ModuleName=%s --DebugDir=%s " % (UniVfrOffsetFileName, self.BaseName, self.EfiDebugPath)\r
1001 GenFdsGlobalVariable.SecCmdList.append(TrimCmd)\r
1002 GenFdsGlobalVariable.GenerateSection(UniVfrOffsetFileSection,\r
1003 [UniVfrOffsetFileName],\r
1004 "EFI_SECTION_RAW",\r
1005 IsMakefile = True\r
1006 )\r
1007 else:\r
1008 VfrUniOffsetList = self.__GetBuildOutputMapFileVfrUniInfo(VfrUniBaseName)\r
1009 #\r
1010 # Generate the Raw data of raw section\r
1011 #\r
1012 if VfrUniOffsetList:\r
1013 UniVfrOffsetFileName = os.path.join(self.OutputPath, self.BaseName + '.offset')\r
1014 UniVfrOffsetFileSection = os.path.join(self.OutputPath, self.BaseName + 'Offset' + '.raw')\r
227dbb11 1015 FfsInfStatement.__GenUniVfrOffsetFile (VfrUniOffsetList, UniVfrOffsetFileName)\r
37de70b7
YZ
1016 UniVfrOffsetFileNameList = []\r
1017 UniVfrOffsetFileNameList.append(UniVfrOffsetFileName)\r
1018 """Call GenSection"""\r
1019\r
1020 GenFdsGlobalVariable.GenerateSection(UniVfrOffsetFileSection,\r
1021 UniVfrOffsetFileNameList,\r
1022 "EFI_SECTION_RAW"\r
1023 )\r
1024 #os.remove(UniVfrOffsetFileName)\r
1025 if UniVfrOffsetFileSection:\r
587e9dfb 1026 SectList.append(UniVfrOffsetFileSection)\r
37de70b7 1027 HasGeneratedFlag = True\r
da92f276 1028 \r
30fdf114
LG
1029 for SecName in SectList :\r
1030 SectFiles.append(SecName)\r
1031 SectAlignments.append(Align)\r
1032 Index = Index + 1\r
1033 return SectFiles, SectAlignments\r
1034\r
1035 ## __GenComplexFileFfs__() method\r
1036 #\r
1037 # Generate FFS\r
1038 #\r
1039 # @param self The object pointer\r
1040 # @param Rule The rule object used to generate section\r
1041 # @param InputFileList The output file list from GenSection\r
1042 # @retval string Generated FFS file name\r
1043 #\r
37de70b7 1044 def __GenComplexFileFfs__(self, Rule, InputFile, Alignments, MakefilePath = None):\r
30fdf114 1045\r
4231a819 1046 if Rule.NameGuid is not None and Rule.NameGuid.startswith('PCD('):\r
30fdf114
LG
1047 PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid)\r
1048 if len(PcdValue) == 0:\r
1049 EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \\r
1050 % (Rule.NameGuid))\r
1051 if PcdValue.startswith('{'):\r
1052 PcdValue = GuidStructureByteArrayToGuidString(PcdValue)\r
1053 RegistryGuidStr = PcdValue\r
1054 if len(RegistryGuidStr) == 0:\r
1055 EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \\r
1056 % (Rule.NameGuid))\r
1057 self.ModuleGuid = RegistryGuidStr\r
1058\r
1059 FfsOutput = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs')\r
1060 GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputFile,\r
37de70b7
YZ
1061 Ffs.Ffs.FdfFvFileTypeToFileType[Rule.FvFileType],\r
1062 self.ModuleGuid, Fixed=Rule.Fixed,\r
1063 CheckSum=Rule.CheckSum, Align=Rule.Alignment,\r
1064 SectionAlign=Alignments,\r
1065 MakefilePath=MakefilePath\r
1066 )\r
30fdf114
LG
1067 return FfsOutput\r
1068\r
da92f276
LG
1069 ## __GetBuildOutputMapFileVfrUniInfo() method\r
1070 #\r
1071 # Find the offset of UNI/INF object offset in the EFI image file.\r
1072 #\r
1073 # @param self The object pointer\r
1074 # @param VfrUniBaseName A name list contain the UNI/INF object name.\r
1075 # @retval RetValue A list contain offset of UNI/INF object.\r
1076 # \r
1077 def __GetBuildOutputMapFileVfrUniInfo(self, VfrUniBaseName):\r
da92f276 1078 MapFileName = os.path.join(self.EfiOutputPath, self.BaseName + ".map")\r
22a99b87
YL
1079 EfiFileName = os.path.join(self.EfiOutputPath, self.BaseName + ".efi")\r
1080 return GetVariableOffset(MapFileName, EfiFileName, VfrUniBaseName.values())\r
da92f276
LG
1081 \r
1082 ## __GenUniVfrOffsetFile() method\r
1083 #\r
1084 # Generate the offset file for the module which contain VFR or UNI file.\r
1085 #\r
da92f276
LG
1086 # @param VfrUniOffsetList A list contain the VFR/UNI offsets in the EFI image file.\r
1087 # @param UniVfrOffsetFileName The output offset file name.\r
1088 #\r
227dbb11
CJ
1089 @staticmethod\r
1090 def __GenUniVfrOffsetFile(VfrUniOffsetList, UniVfrOffsetFileName):\r
37de70b7 1091\r
da92f276
LG
1092 # Use a instance of StringIO to cache data\r
1093 fStringIO = StringIO.StringIO('') \r
1094 \r
1095 for Item in VfrUniOffsetList:\r
1096 if (Item[0].find("Strings") != -1):\r
1097 #\r
1098 # UNI offset in image.\r
1099 # GUID + Offset\r
1100 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }\r
1101 #\r
1102 UniGuid = [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]\r
1103 UniGuid = [chr(ItemGuid) for ItemGuid in UniGuid]\r
1104 fStringIO.write(''.join(UniGuid)) \r
1105 UniValue = pack ('Q', int (Item[1], 16))\r
1106 fStringIO.write (UniValue)\r
1107 else:\r
1108 #\r
1109 # VFR binary offset in image.\r
1110 # GUID + Offset\r
1111 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };\r
1112 #\r
1113 VfrGuid = [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]\r
1114 VfrGuid = [chr(ItemGuid) for ItemGuid in VfrGuid]\r
1115 fStringIO.write(''.join(VfrGuid)) \r
1116 type (Item[1]) \r
1117 VfrValue = pack ('Q', int (Item[1], 16))\r
1118 fStringIO.write (VfrValue)\r
1119 \r
1120 #\r
1121 # write data into file.\r
1122 #\r
37de70b7
YZ
1123 try :\r
1124 SaveFileOnChange(UniVfrOffsetFileName, fStringIO.getvalue())\r
da92f276
LG
1125 except:\r
1126 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
1127 \r
1128 fStringIO.close ()\r
37de70b7 1129\r
da92f276 1130 \r