302f244fafc9968377c39bd6b6308936b4d8345c
[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)\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         else:\r
222             """If File List is empty"""\r
223             if FileList == [] :\r
224                 if self.Optional == True:\r
225                     GenFdsGlobalVariable.VerboseLogger("Optional Section don't exist!")\r
226                     return [], None\r
227                 else:\r
228                     EdkLogger.error("GenFds", GENFDS_ERROR, "Output file for %s section could not be found for %s" % (SectionType, InfFileName))\r
229 \r
230             else:\r
231                 """Convert the File to Section file one by one """\r
232                 for File in FileList:\r
233                     """ Copy Map file to FFS output path """\r
234                     Index = Index + 1\r
235                     Num = '%s.%d' %(SecNum, Index)\r
236                     OutputFile = os.path.join( OutputPath, ModuleName + SUP_MODULE_SEC + Num + SectionSuffix.get(SectionType))\r
237                     File = GenFdsGlobalVariable.MacroExtend(File, Dict)\r
238 \r
239                     #Get PE Section alignment when align is set to AUTO\r
240                     if self.Alignment == 'Auto' and (SectionType == BINARY_FILE_TYPE_PE32 or SectionType == BINARY_FILE_TYPE_TE):\r
241                         ImageObj = PeImageClass (File)\r
242                         if ImageObj.SectionAlignment < 0x400:\r
243                             Align = str (ImageObj.SectionAlignment)\r
244                         elif ImageObj.SectionAlignment < 0x100000:\r
245                             Align = str (ImageObj.SectionAlignment // 0x400) + 'K'\r
246                         else:\r
247                             Align = str (ImageObj.SectionAlignment // 0x100000) + 'M'\r
248 \r
249                     if File[(len(File)-4):] == '.efi':\r
250                         MapFile = File.replace('.efi', '.map')\r
251                         CopyMapFile = os.path.join(OutputPath, ModuleName + '.map')\r
252                         if IsMakefile:\r
253                             if GenFdsGlobalVariable.CopyList == []:\r
254                                 GenFdsGlobalVariable.CopyList = [(MapFile, CopyMapFile)]\r
255                             else:\r
256                                 GenFdsGlobalVariable.CopyList.append((MapFile, CopyMapFile))\r
257                         else:\r
258                             if os.path.exists(MapFile):\r
259                                 if not os.path.exists(CopyMapFile) or \\r
260                                        (os.path.getmtime(MapFile) > os.path.getmtime(CopyMapFile)):\r
261                                     CopyLongFilePath(MapFile, CopyMapFile)\r
262 \r
263                     if not NoStrip:\r
264                         FileBeforeStrip = os.path.join(OutputPath, ModuleName + '.efi')\r
265                         if IsMakefile:\r
266                             if GenFdsGlobalVariable.CopyList == []:\r
267                                 GenFdsGlobalVariable.CopyList = [(File, FileBeforeStrip)]\r
268                             else:\r
269                                 GenFdsGlobalVariable.CopyList.append((File, FileBeforeStrip))\r
270                         else:\r
271                             if not os.path.exists(FileBeforeStrip) or \\r
272                                 (os.path.getmtime(File) > os.path.getmtime(FileBeforeStrip)):\r
273                                 CopyLongFilePath(File, FileBeforeStrip)\r
274                         StrippedFile = os.path.join(OutputPath, ModuleName + '.stripped')\r
275                         GenFdsGlobalVariable.GenerateFirmwareImage(\r
276                                 StrippedFile,\r
277                                 [File],\r
278                                 Strip=True,\r
279                                 IsMakefile = IsMakefile\r
280                             )\r
281                         File = StrippedFile\r
282 \r
283                     """For TE Section call GenFw to generate TE image"""\r
284 \r
285                     if SectionType == BINARY_FILE_TYPE_TE:\r
286                         TeFile = os.path.join( OutputPath, ModuleName + 'Te.raw')\r
287                         GenFdsGlobalVariable.GenerateFirmwareImage(\r
288                                 TeFile,\r
289                                 [File],\r
290                                 Type='te',\r
291                                 IsMakefile = IsMakefile\r
292                             )\r
293                         File = TeFile\r
294 \r
295                     """Call GenSection"""\r
296                     GenFdsGlobalVariable.GenerateSection(OutputFile,\r
297                                                         [File],\r
298                                                         Section.Section.SectionType.get (SectionType),\r
299                                                         IsMakefile=IsMakefile\r
300                                                         )\r
301                     OutputFileList.append(OutputFile)\r
302 \r
303         return OutputFileList, Align\r