Sync EDKII BaseTools to BaseTools project r1903.
[efi/edk2/.git] / edk2 / BaseTools / Source / Python / GenFds / EfiSection.py
1 ## @file\r
2 # process rule section generation\r
3 #\r
4 #  Copyright (c) 2007, Intel Corporation\r
5 #\r
6 #  All rights reserved. This program and the accompanying materials\r
7 #  are licensed and made available under the terms and conditions of the BSD License\r
8 #  which accompanies this distribution.  The full text of the license may be found at\r
9 #  http://opensource.org/licenses/bsd-license.php\r
10 #\r
11 #  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 #  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13 #\r
14 \r
15 ##\r
16 # Import Modules\r
17 #\r
18 from struct import *\r
19 import Section\r
20 from GenFdsGlobalVariable import GenFdsGlobalVariable\r
21 import subprocess\r
22 from Ffs import Ffs\r
23 import os\r
24 from CommonDataClass.FdfClass import EfiSectionClassObject\r
25 import shutil\r
26 from Common import EdkLogger\r
27 from Common.BuildToolError import *\r
28 from Common.Misc import PeImageClass\r
29 \r
30 ## generate rule section\r
31 #\r
32 #\r
33 class EfiSection (EfiSectionClassObject):\r
34 \r
35     ## The constructor\r
36     #\r
37     #   @param  self        The object pointer\r
38     #\r
39     def __init__(self):\r
40           EfiSectionClassObject.__init__(self)\r
41 \r
42     ## GenSection() method\r
43     #\r
44     #   Generate rule section\r
45     #\r
46     #   @param  self        The object pointer\r
47     #   @param  OutputPath  Where to place output file\r
48     #   @param  ModuleName  Which module this section belongs to\r
49     #   @param  SecNum      Index of section\r
50     #   @param  KeyStringList  Filter for inputs of section generation\r
51     #   @param  FfsInf      FfsInfStatement object that contains this section data\r
52     #   @param  Dict        dictionary contains macro and its value\r
53     #   @retval tuple       (Generated file name list, section alignment)\r
54     #\r
55     def GenSection(self, OutputPath, ModuleName, SecNum, KeyStringList, FfsInf = None, Dict = {}) :\r
56         \r
57         if self.FileName != None and self.FileName.startswith('PCD('):\r
58             self.FileName = GenFdsGlobalVariable.GetPcdValue(self.FileName)\r
59         """Prepare the parameter of GenSection"""\r
60         if FfsInf != None :\r
61             InfFileName = FfsInf.InfFileName\r
62             SectionType = FfsInf.__ExtendMacro__(self.SectionType)\r
63             Filename = FfsInf.__ExtendMacro__(self.FileName)\r
64             BuildNum = FfsInf.__ExtendMacro__(self.BuildNum)\r
65             StringData = FfsInf.__ExtendMacro__(self.StringData)\r
66             NoStrip = True\r
67             if FfsInf.ModuleType in ('SEC', 'PEI_CORE', 'PEIM') and SectionType in ('TE', 'PE32'):\r
68                 if FfsInf.KeepReloc != None:\r
69                     NoStrip = FfsInf.KeepReloc\r
70                 elif FfsInf.KeepRelocFromRule != None:\r
71                     NoStrip = FfsInf.KeepRelocFromRule\r
72                 elif self.KeepReloc != None:\r
73                     NoStrip = self.KeepReloc\r
74                 elif FfsInf.ShadowFromInfFile != None:\r
75                     NoStrip = FfsInf.ShadowFromInfFile\r
76         else:\r
77             EdkLogger.error("GenFds", GENFDS_ERROR, "Module %s apply rule for None!" %ModuleName)\r
78 \r
79         """If the file name was pointed out, add it in FileList"""\r
80         FileList = []\r
81         if Filename != None:\r
82             Filename = GenFdsGlobalVariable.MacroExtend(Filename, Dict)\r
83             # check if the path is absolute or relative
84             if os.path.isabs(Filename):
85                 Filename = os.path.normpath(Filename)
86             else:
87                 Filename = os.path.normpath(os.path.join(FfsInf.EfiOutputPath, Filename))
88 \r
89             if not self.Optional:\r
90                 FileList.append(Filename)\r
91             elif os.path.exists(Filename):\r
92                 FileList.append(Filename)\r
93         else:\r
94             FileList, IsSect = Section.Section.GetFileList(FfsInf, self.FileType, self.FileExtension, Dict)\r
95             if IsSect :\r
96                 return FileList, self.Alignment\r
97 \r
98         Index = 0\r
99 \r
100         """ If Section type is 'VERSION'"""\r
101         OutputFileList = []\r
102         if SectionType == 'VERSION':\r
103 \r
104             InfOverrideVerString = False\r
105             if FfsInf.Version != None:\r
106                 #StringData = FfsInf.Version\r
107                 BuildNum = FfsInf.Version\r
108                 InfOverrideVerString = True\r
109 \r
110             if InfOverrideVerString:\r
111                 #VerTuple = ('-n', '"' + StringData + '"')\r
112                 if BuildNum != None and BuildNum != '':\r
113                     BuildNumTuple = ('-j', BuildNum)\r
114                 else:\r
115                     BuildNumTuple = tuple()\r
116 \r
117                 Num = SecNum\r
118                 OutputFile = os.path.join( OutputPath, ModuleName + 'SEC' + str(Num) + Ffs.SectionSuffix.get(SectionType))\r
119                 GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_VERSION',\r
120                                                      #Ui=StringData, \r
121                                                      Ver=BuildNum)\r
122                 OutputFileList.append(OutputFile)\r
123 \r
124             elif FileList != []:\r
125                 for File in FileList:\r
126                     Index = Index + 1\r
127                     Num = '%s.%d' %(SecNum , Index)\r
128                     OutputFile = os.path.join(OutputPath, ModuleName + 'SEC' + Num + Ffs.SectionSuffix.get(SectionType))\r
129                     f = open(File, 'r')\r
130                     VerString = f.read()\r
131                     f.close()\r
132                     BuildNum = VerString\r
133                     if BuildNum != None and BuildNum != '':\r
134                         BuildNumTuple = ('-j', BuildNum)\r
135                     GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_VERSION',\r
136                                                          #Ui=VerString, \r
137                                                          Ver=BuildNum)\r
138                     OutputFileList.append(OutputFile)\r
139 \r
140             else:\r
141                 BuildNum = StringData\r
142                 if BuildNum != None and BuildNum != '':\r
143                     BuildNumTuple = ('-j', BuildNum)\r
144                 else:\r
145                     BuildNumTuple = tuple()\r
146                 BuildNumString = ' ' + ' '.join(BuildNumTuple)\r
147 \r
148                 #if VerString == '' and \r
149                 if BuildNumString == '':\r
150                     if self.Optional == True :\r
151                         GenFdsGlobalVariable.VerboseLogger( "Optional Section don't exist!")\r
152                         return [], None\r
153                     else:\r
154                         EdkLogger.error("GenFds", GENFDS_ERROR, "File: %s miss Version Section value" %InfFileName)\r
155                 Num = SecNum\r
156                 OutputFile = os.path.join( OutputPath, ModuleName + 'SEC' + str(Num) + Ffs.SectionSuffix.get(SectionType))\r
157                 GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_VERSION',\r
158                                                      #Ui=VerString, \r
159                                                      Ver=BuildNum)\r
160                 OutputFileList.append(OutputFile)\r
161 \r
162         #\r
163         # If Section Type is 'UI'\r
164         #\r
165         elif SectionType == 'UI':\r
166 \r
167             InfOverrideUiString = False\r
168             if FfsInf.Ui != None:\r
169                 StringData = FfsInf.Ui\r
170                 InfOverrideUiString = True\r
171 \r
172             if InfOverrideUiString:\r
173                 Num = SecNum\r
174                 OutputFile = os.path.join( OutputPath, ModuleName + 'SEC' + str(Num) + Ffs.SectionSuffix.get(SectionType))\r
175                 GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_USER_INTERFACE',\r
176                                                      Ui=StringData)\r
177                 OutputFileList.append(OutputFile)\r
178 \r
179             elif FileList != []:\r
180                 for File in FileList:\r
181                     Index = Index + 1\r
182                     Num = '%s.%d' %(SecNum , Index)\r
183                     OutputFile = os.path.join(OutputPath, ModuleName + 'SEC' + Num + Ffs.SectionSuffix.get(SectionType))\r
184                     f = open(File, 'r')\r
185                     UiString = f.read()\r
186                     f.close()\r
187                     GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_USER_INTERFACE',\r
188                                                          Ui=UiString)\r
189                     OutputFileList.append(OutputFile)\r
190             else:\r
191                 if StringData != None and len(StringData) > 0:\r
192                     UiTuple = ('-n', '"' + StringData + '"')\r
193                 else:\r
194                     UiTuple = tuple()\r
195 \r
196                     if self.Optional == True :\r
197                         GenFdsGlobalVariable.VerboseLogger( "Optional Section don't exist!")\r
198                         return '', None\r
199                     else:\r
200                         EdkLogger.error("GenFds", GENFDS_ERROR, "File: %s miss UI Section value" %InfFileName)\r
201 \r
202                 Num = SecNum\r
203                 OutputFile = os.path.join( OutputPath, ModuleName + 'SEC' + str(Num) + Ffs.SectionSuffix.get(SectionType))\r
204                 GenFdsGlobalVariable.GenerateSection(OutputFile, [], 'EFI_SECTION_USER_INTERFACE',\r
205                                                      Ui=StringData)\r
206                 OutputFileList.append(OutputFile)\r
207 \r
208 \r
209         else:\r
210             """If File List is empty"""\r
211             if FileList == [] :\r
212                 if self.Optional == True:\r
213                      GenFdsGlobalVariable.VerboseLogger( "Optional Section don't exist!")\r
214                      return [], None\r
215                 else:\r
216                      EdkLogger.error("GenFds", GENFDS_ERROR, "Output file for %s section could not be found for %s" % (SectionType, InfFileName))\r
217 \r
218             else:\r
219                 """Convert the File to Section file one by one """\r
220                 for File in FileList:\r
221                     """ Copy Map file to FFS output path """\r
222                     Index = Index + 1\r
223                     Num = '%s.%d' %(SecNum , Index)\r
224                     OutputFile = os.path.join( OutputPath, ModuleName + 'SEC' + Num + Ffs.SectionSuffix.get(SectionType))\r
225                     File = GenFdsGlobalVariable.MacroExtend(File, Dict)\r
226                     \r
227                     #Get PE Section alignment when align is set to AUTO\r
228                     if self.Alignment == 'Auto' and (SectionType == 'PE32' or SectionType == 'TE'):\r
229                         ImageObj = PeImageClass (File)\r
230                         if ImageObj.SectionAlignment < 0x400:\r
231                             self.Alignment = str (ImageObj.SectionAlignment)\r
232                         else:\r
233                             self.Alignment = str (ImageObj.SectionAlignment / 0x400) + 'K'\r
234 \r
235                     if File[(len(File)-4):] == '.efi':\r
236                         MapFile = File.replace('.efi', '.map')\r
237                         if os.path.exists(MapFile):\r
238                             CopyMapFile = os.path.join(OutputPath, ModuleName + '.map')\r
239                             if not os.path.exists(CopyMapFile) or \\r
240                                 (os.path.getmtime(MapFile) > os.path.getmtime(CopyMapFile)):\r
241                                 shutil.copyfile(MapFile, CopyMapFile)\r
242 \r
243                     if not NoStrip:\r
244                         FileBeforeStrip = os.path.join(OutputPath, ModuleName + '.efi')\r
245                         if not os.path.exists(FileBeforeStrip) or \\r
246                             (os.path.getmtime(File) > os.path.getmtime(FileBeforeStrip)):\r
247                             shutil.copyfile(File, FileBeforeStrip)\r
248                         StrippedFile = os.path.join(OutputPath, ModuleName + '.stripped')\r
249                         GenFdsGlobalVariable.GenerateFirmwareImage(\r
250                                                 StrippedFile,\r
251                                                 [File],\r
252                                                 Strip=True\r
253                                                 )\r
254                         File = StrippedFile\r
255                     \r
256                     """For TE Section call GenFw to generate TE image"""\r
257 \r
258                     if SectionType == 'TE':\r
259                         TeFile = os.path.join( OutputPath, ModuleName + 'Te.raw')\r
260                         GenFdsGlobalVariable.GenerateFirmwareImage(\r
261                                                 TeFile,\r
262                                                 [File],\r
263                                                 Type='te'\r
264                                                 )\r
265                         File = TeFile\r
266 \r
267                     """Call GenSection"""\r
268                     GenFdsGlobalVariable.GenerateSection(OutputFile,\r
269                                                          [File],\r
270                                                          Section.Section.SectionType.get (SectionType)\r
271                                                          )\r
272                     OutputFileList.append(OutputFile)\r
273 \r
274         return OutputFileList, self.Alignment\r