BaseTools:Make BaseTools support new rules to generate RAW FFS FILE
[mirror_edk2.git] / BaseTools / Source / Python / GenFds / EfiSection.py
1 ## @file\r
2 # process rule section generation\r
3 #\r
4 #  Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
5 #\r
6 #  SPDX-License-Identifier: BSD-2-Clause-Patent\r
7 #\r
8 \r
9 ##\r
10 # Import Modules\r
11 #\r
12 from __future__ import absolute_import\r
13 from struct import *\r
14 from . import Section\r
15 from .GenFdsGlobalVariable import GenFdsGlobalVariable\r
16 import subprocess\r
17 from .Ffs import SectionSuffix\r
18 import Common.LongFilePathOs as os\r
19 from CommonDataClass.FdfClass import EfiSectionClassObject\r
20 from Common import EdkLogger\r
21 from Common.BuildToolError import *\r
22 from Common.Misc import PeImageClass\r
23 from Common.LongFilePathSupport import OpenLongFilePath as open\r
24 from Common.LongFilePathSupport import CopyLongFilePath\r
25 from Common.DataType import *\r
26 \r
27 ## generate rule section\r
28 #\r
29 #\r
30 class EfiSection (EfiSectionClassObject):\r
31 \r
32     ## The constructor\r
33     #\r
34     #   @param  self        The object pointer\r
35     #\r
36     def __init__(self):\r
37           EfiSectionClassObject.__init__(self)\r
38 \r
39     ## GenSection() method\r
40     #\r
41     #   Generate rule section\r
42     #\r
43     #   @param  self        The object pointer\r
44     #   @param  OutputPath  Where to place output file\r
45     #   @param  ModuleName  Which module this section belongs to\r
46     #   @param  SecNum      Index of section\r
47     #   @param  KeyStringList  Filter for inputs of section generation\r
48     #   @param  FfsInf      FfsInfStatement object that contains this section data\r
49     #   @param  Dict        dictionary contains macro and its value\r
50     #   @retval tuple       (Generated file name list, section alignment)\r
51     #\r
52     def GenSection(self, OutputPath, ModuleName, SecNum, KeyStringList, FfsInf = None, Dict = {}, IsMakefile = False) :\r
53 \r
54         if self.FileName is not None and self.FileName.startswith('PCD('):\r
55             self.FileName = GenFdsGlobalVariable.GetPcdValue(self.FileName)\r
56         """Prepare the parameter of GenSection"""\r
57         if FfsInf is not None :\r
58             InfFileName = FfsInf.InfFileName\r
59             SectionType = FfsInf.__ExtendMacro__(self.SectionType)\r
60             Filename = FfsInf.__ExtendMacro__(self.FileName)\r
61             BuildNum = FfsInf.__ExtendMacro__(self.BuildNum)\r
62             StringData = FfsInf.__ExtendMacro__(self.StringData)\r
63             ModuleNameStr = FfsInf.__ExtendMacro__('$(MODULE_NAME)')\r
64             NoStrip = True\r
65             if FfsInf.ModuleType in (SUP_MODULE_SEC, SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM, SUP_MODULE_MM_CORE_STANDALONE) and SectionType in (BINARY_FILE_TYPE_TE, BINARY_FILE_TYPE_PE32):\r
66                 if FfsInf.KeepReloc is not None:\r
67                     NoStrip = FfsInf.KeepReloc\r
68                 elif FfsInf.KeepRelocFromRule is not None:\r
69                     NoStrip = FfsInf.KeepRelocFromRule\r
70                 elif self.KeepReloc is not None:\r
71                     NoStrip = self.KeepReloc\r
72                 elif FfsInf.ShadowFromInfFile is not None:\r
73                     NoStrip = FfsInf.ShadowFromInfFile\r
74         else:\r
75             EdkLogger.error("GenFds", GENFDS_ERROR, "Module %s apply rule for None!" %ModuleName)\r
76 \r
77         """If the file name was pointed out, add it in FileList"""\r
78         FileList = []\r
79         if Filename is not None:\r
80             Filename = GenFdsGlobalVariable.MacroExtend(Filename, Dict)\r
81             # check if the path is absolute or relative\r
82             if os.path.isabs(Filename):\r
83                 Filename = os.path.normpath(Filename)\r
84             else:\r
85                 Filename = os.path.normpath(os.path.join(FfsInf.EfiOutputPath, Filename))\r
86 \r
87             if not self.Optional:\r
88                 FileList.append(Filename)\r
89             elif os.path.exists(Filename):\r
90                 FileList.append(Filename)\r
91             elif IsMakefile:\r
92                 SuffixMap = FfsInf.GetFinalTargetSuffixMap()\r
93                 if '.depex' in SuffixMap:\r
94                     FileList.append(Filename)\r
95         else:\r
96             FileList, IsSect = Section.Section.GetFileList(FfsInf, self.FileType, self.FileExtension, Dict, IsMakefile=IsMakefile, SectionType=SectionType)\r
97             if IsSect :\r
98                 return FileList, self.Alignment\r
99 \r
100         Index = 0\r
101         Align = self.Alignment\r
102 \r
103         """ If Section type is 'VERSION'"""\r
104         OutputFileList = []\r
105         if SectionType == 'VERSION':\r
106 \r
107             InfOverrideVerString = False\r
108             if FfsInf.Version is not None:\r
109                 #StringData = FfsInf.Version\r
110                 BuildNum = FfsInf.Version\r
111                 InfOverrideVerString = True\r
112 \r
113             if InfOverrideVerString:\r
114                 #VerTuple = ('-n', '"' + StringData + '"')\r
115                 if BuildNum is not None and BuildNum != '':\r
116                     BuildNumTuple = ('-j', BuildNum)\r
117                 else:\r
118                     BuildNumTuple = tuple()\r
119 \r
120                 Num = SecNum\r
121                 OutputFile = os.path.join( OutputPath, ModuleName + SUP_MODULE_SEC + str(Num) + SectionSuffix.get(SectionType))\r
122                 GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_VERSION',\r
123                                                     #Ui=StringData,\r
124                                                     Ver=BuildNum,\r
125                                                     IsMakefile=IsMakefile)\r
126                 OutputFileList.append(OutputFile)\r
127 \r
128             elif FileList != []:\r
129                 for File in FileList:\r
130                     Index = Index + 1\r
131                     Num = '%s.%d' %(SecNum, Index)\r
132                     OutputFile = os.path.join(OutputPath, ModuleName + SUP_MODULE_SEC + Num + SectionSuffix.get(SectionType))\r
133                     f = open(File, 'r')\r
134                     VerString = f.read()\r
135                     f.close()\r
136                     BuildNum = VerString\r
137                     if BuildNum is not None and BuildNum != '':\r
138                         BuildNumTuple = ('-j', BuildNum)\r
139                     GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_VERSION',\r
140                                                         #Ui=VerString,\r
141                                                         Ver=BuildNum,\r
142                                                         IsMakefile=IsMakefile)\r
143                     OutputFileList.append(OutputFile)\r
144 \r
145             else:\r
146                 BuildNum = StringData\r
147                 if BuildNum is not None and BuildNum != '':\r
148                     BuildNumTuple = ('-j', BuildNum)\r
149                 else:\r
150                     BuildNumTuple = tuple()\r
151                 BuildNumString = ' ' + ' '.join(BuildNumTuple)\r
152 \r
153                 #if VerString == '' and\r
154                 if BuildNumString == '':\r
155                     if self.Optional == True :\r
156                         GenFdsGlobalVariable.VerboseLogger( "Optional Section don't exist!")\r
157                         return [], None\r
158                     else:\r
159                         EdkLogger.error("GenFds", GENFDS_ERROR, "File: %s miss Version Section value" %InfFileName)\r
160                 Num = SecNum\r
161                 OutputFile = os.path.join( OutputPath, ModuleName + SUP_MODULE_SEC + str(Num) + SectionSuffix.get(SectionType))\r
162                 GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_VERSION',\r
163                                                     #Ui=VerString,\r
164                                                     Ver=BuildNum,\r
165                                                     IsMakefile=IsMakefile)\r
166                 OutputFileList.append(OutputFile)\r
167 \r
168         #\r
169         # If Section Type is BINARY_FILE_TYPE_UI\r
170         #\r
171         elif SectionType == BINARY_FILE_TYPE_UI:\r
172 \r
173             InfOverrideUiString = False\r
174             if FfsInf.Ui is not None:\r
175                 StringData = FfsInf.Ui\r
176                 InfOverrideUiString = True\r
177 \r
178             if InfOverrideUiString:\r
179                 Num = SecNum\r
180                 if IsMakefile and StringData == ModuleNameStr:\r
181                     StringData = "$(MODULE_NAME)"\r
182                 OutputFile = os.path.join( OutputPath, ModuleName + SUP_MODULE_SEC + str(Num) + SectionSuffix.get(SectionType))\r
183                 GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_USER_INTERFACE',\r
184                                                      Ui=StringData, IsMakefile=IsMakefile)\r
185                 OutputFileList.append(OutputFile)\r
186 \r
187             elif FileList != []:\r
188                 for File in FileList:\r
189                     Index = Index + 1\r
190                     Num = '%s.%d' %(SecNum, Index)\r
191                     OutputFile = os.path.join(OutputPath, ModuleName + SUP_MODULE_SEC + Num + SectionSuffix.get(SectionType))\r
192                     f = open(File, 'r')\r
193                     UiString = f.read()\r
194                     f.close()\r
195                     if IsMakefile and UiString == ModuleNameStr:\r
196                         UiString = "$(MODULE_NAME)"\r
197                     GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_USER_INTERFACE',\r
198                                                         Ui=UiString, IsMakefile=IsMakefile)\r
199                     OutputFileList.append(OutputFile)\r
200             else:\r
201                 if StringData is not None and len(StringData) > 0:\r
202                     UiTuple = ('-n', '"' + StringData + '"')\r
203                 else:\r
204                     UiTuple = tuple()\r
205 \r
206                     if self.Optional == True :\r
207                         GenFdsGlobalVariable.VerboseLogger( "Optional Section don't exist!")\r
208                         return '', None\r
209                     else:\r
210                         EdkLogger.error("GenFds", GENFDS_ERROR, "File: %s miss UI Section value" %InfFileName)\r
211 \r
212                 Num = SecNum\r
213                 if IsMakefile and StringData == ModuleNameStr:\r
214                     StringData = "$(MODULE_NAME)"\r
215                 OutputFile = os.path.join( OutputPath, ModuleName + SUP_MODULE_SEC + str(Num) + SectionSuffix.get(SectionType))\r
216                 GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_USER_INTERFACE',\r
217                                                      Ui=StringData, IsMakefile=IsMakefile)\r
218                 OutputFileList.append(OutputFile)\r
219 \r
220         #\r
221         # If Section Type is BINARY_FILE_TYPE_RAW\r
222         #\r
223         elif SectionType == BINARY_FILE_TYPE_RAW:\r
224             """If File List is empty"""\r
225             if FileList == []:\r
226                 if self.Optional == True:\r
227                     GenFdsGlobalVariable.VerboseLogger("Optional Section don't exist!")\r
228                     return [], None\r
229                 else:\r
230                     EdkLogger.error("GenFds", GENFDS_ERROR, "Output file for %s section could not be found for %s" % (SectionType, InfFileName))\r
231 \r
232             elif len(FileList) > 1:\r
233                 EdkLogger.error("GenFds", GENFDS_ERROR,\r
234                                 "Files suffixed with %s are not allowed to have more than one file in %s[Binaries] section" % (\r
235                                 self.FileExtension, InfFileName))\r
236             else:\r
237                 for File in FileList:\r
238                     File = GenFdsGlobalVariable.MacroExtend(File, Dict)\r
239                     OutputFileList.append(File)\r
240 \r
241         else:\r
242             """If File List is empty"""\r
243             if FileList == [] :\r
244                 if self.Optional == True:\r
245                     GenFdsGlobalVariable.VerboseLogger("Optional Section don't exist!")\r
246                     return [], None\r
247                 else:\r
248                     EdkLogger.error("GenFds", GENFDS_ERROR, "Output file for %s section could not be found for %s" % (SectionType, InfFileName))\r
249 \r
250             else:\r
251                 """Convert the File to Section file one by one """\r
252                 for File in FileList:\r
253                     """ Copy Map file to FFS output path """\r
254                     Index = Index + 1\r
255                     Num = '%s.%d' %(SecNum, Index)\r
256                     OutputFile = os.path.join( OutputPath, ModuleName + SUP_MODULE_SEC + Num + SectionSuffix.get(SectionType))\r
257                     File = GenFdsGlobalVariable.MacroExtend(File, Dict)\r
258 \r
259                     #Get PE Section alignment when align is set to AUTO\r
260                     if self.Alignment == 'Auto' and (SectionType == BINARY_FILE_TYPE_PE32 or SectionType == BINARY_FILE_TYPE_TE):\r
261                         ImageObj = PeImageClass (File)\r
262                         if ImageObj.SectionAlignment < 0x400:\r
263                             Align = str (ImageObj.SectionAlignment)\r
264                         elif ImageObj.SectionAlignment < 0x100000:\r
265                             Align = str (ImageObj.SectionAlignment // 0x400) + 'K'\r
266                         else:\r
267                             Align = str (ImageObj.SectionAlignment // 0x100000) + 'M'\r
268 \r
269                     if File[(len(File)-4):] == '.efi':\r
270                         MapFile = File.replace('.efi', '.map')\r
271                         CopyMapFile = os.path.join(OutputPath, ModuleName + '.map')\r
272                         if IsMakefile:\r
273                             if GenFdsGlobalVariable.CopyList == []:\r
274                                 GenFdsGlobalVariable.CopyList = [(MapFile, CopyMapFile)]\r
275                             else:\r
276                                 GenFdsGlobalVariable.CopyList.append((MapFile, CopyMapFile))\r
277                         else:\r
278                             if os.path.exists(MapFile):\r
279                                 if not os.path.exists(CopyMapFile) or \\r
280                                        (os.path.getmtime(MapFile) > os.path.getmtime(CopyMapFile)):\r
281                                     CopyLongFilePath(MapFile, CopyMapFile)\r
282 \r
283                     if not NoStrip:\r
284                         FileBeforeStrip = os.path.join(OutputPath, ModuleName + '.efi')\r
285                         if IsMakefile:\r
286                             if GenFdsGlobalVariable.CopyList == []:\r
287                                 GenFdsGlobalVariable.CopyList = [(File, FileBeforeStrip)]\r
288                             else:\r
289                                 GenFdsGlobalVariable.CopyList.append((File, FileBeforeStrip))\r
290                         else:\r
291                             if not os.path.exists(FileBeforeStrip) or \\r
292                                 (os.path.getmtime(File) > os.path.getmtime(FileBeforeStrip)):\r
293                                 CopyLongFilePath(File, FileBeforeStrip)\r
294                         StrippedFile = os.path.join(OutputPath, ModuleName + '.stripped')\r
295                         GenFdsGlobalVariable.GenerateFirmwareImage(\r
296                                 StrippedFile,\r
297                                 [File],\r
298                                 Strip=True,\r
299                                 IsMakefile = IsMakefile\r
300                             )\r
301                         File = StrippedFile\r
302 \r
303                     """For TE Section call GenFw to generate TE image"""\r
304 \r
305                     if SectionType == BINARY_FILE_TYPE_TE:\r
306                         TeFile = os.path.join( OutputPath, ModuleName + 'Te.raw')\r
307                         GenFdsGlobalVariable.GenerateFirmwareImage(\r
308                                 TeFile,\r
309                                 [File],\r
310                                 Type='te',\r
311                                 IsMakefile = IsMakefile\r
312                             )\r
313                         File = TeFile\r
314 \r
315                     """Call GenSection"""\r
316                     GenFdsGlobalVariable.GenerateSection(OutputFile,\r
317                                                         [File],\r
318                                                         Section.Section.SectionType.get (SectionType),\r
319                                                         IsMakefile=IsMakefile\r
320                                                         )\r
321                     OutputFileList.append(OutputFile)\r
322 \r
323         return OutputFileList, Align\r