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