]>
Commit | Line | Data |
---|---|---|
30fdf114 LG |
1 | ## @file\r |
2 | # This file is used to generate DEPEX file for module's dependency expression\r | |
3 | #\r | |
31ff1c44 | 4 | # Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r |
40d841f6 | 5 | # This program and the accompanying materials\r |
30fdf114 LG |
6 | # are licensed and made available under the terms and conditions of the BSD License\r |
7 | # which accompanies this distribution. The full text of the license may be found at\r | |
8 | # http://opensource.org/licenses/bsd-license.php\r | |
9 | #\r | |
10 | # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r | |
11 | # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r | |
12 | \r | |
13 | ## Import Modules\r | |
14 | #\r | |
15 | import sys\r | |
1be2ed90 | 16 | import Common.LongFilePathOs as os\r |
30fdf114 LG |
17 | import re\r |
18 | import traceback\r | |
1be2ed90 | 19 | from Common.LongFilePathSupport import OpenLongFilePath as open\r |
30fdf114 LG |
20 | from StringIO import StringIO\r |
21 | from struct import pack\r | |
22 | from Common.BuildToolError import *\r | |
23 | from Common.Misc import SaveFileOnChange\r | |
24 | from Common.Misc import GuidStructureStringToGuidString\r | |
25 | from Common import EdkLogger as EdkLogger\r | |
b36d134f | 26 | from Common.BuildVersion import gBUILD_VERSION\r |
8bb63e37 | 27 | from Common.DataType import *\r |
30fdf114 LG |
28 | \r |
29 | ## Regular expression for matching "DEPENDENCY_START ... DEPENDENCY_END"\r | |
30 | gStartClosePattern = re.compile(".*DEPENDENCY_START(.+)DEPENDENCY_END.*", re.S)\r | |
31 | \r | |
32 | ## Mapping between module type and EFI phase\r | |
33 | gType2Phase = {\r | |
8bb63e37 CJ |
34 | SUP_MODULE_BASE : None,\r |
35 | SUP_MODULE_SEC : "PEI",\r | |
36 | SUP_MODULE_PEI_CORE : "PEI",\r | |
37 | SUP_MODULE_PEIM : "PEI",\r | |
38 | SUP_MODULE_DXE_CORE : "DXE",\r | |
39 | SUP_MODULE_DXE_DRIVER : "DXE",\r | |
40 | SUP_MODULE_DXE_SMM_DRIVER : "DXE",\r | |
41 | SUP_MODULE_DXE_RUNTIME_DRIVER: "DXE",\r | |
42 | SUP_MODULE_DXE_SAL_DRIVER : "DXE",\r | |
43 | SUP_MODULE_UEFI_DRIVER : "DXE",\r | |
44 | SUP_MODULE_UEFI_APPLICATION : "DXE",\r | |
45 | SUP_MODULE_SMM_CORE : "DXE",\r | |
46 | SUP_MODULE_MM_STANDALONE : "MM",\r | |
47 | SUP_MODULE_MM_CORE_STANDALONE : "MM",\r | |
30fdf114 LG |
48 | }\r |
49 | \r | |
50 | ## Convert dependency expression string into EFI internal representation\r | |
51 | #\r | |
52 | # DependencyExpression class is used to parse dependency expression string and\r | |
53 | # convert it into its binary form.\r | |
54 | #\r | |
55 | class DependencyExpression:\r | |
56 | \r | |
57 | ArchProtocols = set([\r | |
58 | '665e3ff6-46cc-11d4-9a38-0090273fc14d', # 'gEfiBdsArchProtocolGuid'\r | |
59 | '26baccb1-6f42-11d4-bce7-0080c73c8881', # 'gEfiCpuArchProtocolGuid'\r | |
60 | '26baccb2-6f42-11d4-bce7-0080c73c8881', # 'gEfiMetronomeArchProtocolGuid'\r | |
61 | '1da97072-bddc-4b30-99f1-72a0b56fff2a', # 'gEfiMonotonicCounterArchProtocolGuid'\r | |
62 | '27cfac87-46cc-11d4-9a38-0090273fc14d', # 'gEfiRealTimeClockArchProtocolGuid'\r | |
63 | '27cfac88-46cc-11d4-9a38-0090273fc14d', # 'gEfiResetArchProtocolGuid'\r | |
64 | 'b7dfb4e1-052f-449f-87be-9818fc91b733', # 'gEfiRuntimeArchProtocolGuid'\r | |
65 | 'a46423e3-4617-49f1-b9ff-d1bfa9115839', # 'gEfiSecurityArchProtocolGuid'\r | |
66 | '26baccb3-6f42-11d4-bce7-0080c73c8881', # 'gEfiTimerArchProtocolGuid'\r | |
67 | '6441f818-6362-4e44-b570-7dba31dd2453', # 'gEfiVariableWriteArchProtocolGuid'\r | |
68 | '1e5668e2-8481-11d4-bcf1-0080c73c8881', # 'gEfiVariableArchProtocolGuid'\r | |
69 | '665e3ff5-46cc-11d4-9a38-0090273fc14d' # 'gEfiWatchdogTimerArchProtocolGuid'\r | |
70 | ]\r | |
71 | )\r | |
72 | \r | |
73 | OpcodePriority = {\r | |
31ff1c44 CJ |
74 | DEPEX_OPCODE_AND : 1,\r |
75 | DEPEX_OPCODE_OR : 1,\r | |
76 | DEPEX_OPCODE_NOT : 2,\r | |
30fdf114 LG |
77 | }\r |
78 | \r | |
79 | Opcode = {\r | |
80 | "PEI" : {\r | |
31ff1c44 CJ |
81 | DEPEX_OPCODE_PUSH : 0x02,\r |
82 | DEPEX_OPCODE_AND : 0x03,\r | |
83 | DEPEX_OPCODE_OR : 0x04,\r | |
84 | DEPEX_OPCODE_NOT : 0x05,\r | |
85 | DEPEX_OPCODE_TRUE : 0x06,\r | |
86 | DEPEX_OPCODE_FALSE : 0x07,\r | |
87 | DEPEX_OPCODE_END : 0x08\r | |
30fdf114 LG |
88 | },\r |
89 | \r | |
90 | "DXE" : {\r | |
31ff1c44 CJ |
91 | DEPEX_OPCODE_BEFORE: 0x00,\r |
92 | DEPEX_OPCODE_AFTER : 0x01,\r | |
93 | DEPEX_OPCODE_PUSH : 0x02,\r | |
94 | DEPEX_OPCODE_AND : 0x03,\r | |
95 | DEPEX_OPCODE_OR : 0x04,\r | |
96 | DEPEX_OPCODE_NOT : 0x05,\r | |
97 | DEPEX_OPCODE_TRUE : 0x06,\r | |
98 | DEPEX_OPCODE_FALSE : 0x07,\r | |
99 | DEPEX_OPCODE_END : 0x08,\r | |
100 | DEPEX_OPCODE_SOR : 0x09\r | |
5a9c3e3e SV |
101 | },\r |
102 | \r | |
103 | "MM" : {\r | |
31ff1c44 CJ |
104 | DEPEX_OPCODE_BEFORE: 0x00,\r |
105 | DEPEX_OPCODE_AFTER : 0x01,\r | |
106 | DEPEX_OPCODE_PUSH : 0x02,\r | |
107 | DEPEX_OPCODE_AND : 0x03,\r | |
108 | DEPEX_OPCODE_OR : 0x04,\r | |
109 | DEPEX_OPCODE_NOT : 0x05,\r | |
110 | DEPEX_OPCODE_TRUE : 0x06,\r | |
111 | DEPEX_OPCODE_FALSE : 0x07,\r | |
112 | DEPEX_OPCODE_END : 0x08,\r | |
113 | DEPEX_OPCODE_SOR : 0x09\r | |
30fdf114 LG |
114 | }\r |
115 | }\r | |
116 | \r | |
117 | # all supported op codes and operands\r | |
31ff1c44 CJ |
118 | SupportedOpcode = [DEPEX_OPCODE_BEFORE, DEPEX_OPCODE_AFTER, DEPEX_OPCODE_PUSH, DEPEX_OPCODE_AND, DEPEX_OPCODE_OR, DEPEX_OPCODE_NOT, DEPEX_OPCODE_END, DEPEX_OPCODE_SOR]\r |
119 | SupportedOperand = [DEPEX_OPCODE_TRUE, DEPEX_OPCODE_FALSE]\r | |
30fdf114 | 120 | \r |
31ff1c44 CJ |
121 | OpcodeWithSingleOperand = [DEPEX_OPCODE_NOT, DEPEX_OPCODE_BEFORE, DEPEX_OPCODE_AFTER]\r |
122 | OpcodeWithTwoOperand = [DEPEX_OPCODE_AND, DEPEX_OPCODE_OR]\r | |
30fdf114 LG |
123 | \r |
124 | # op code that should not be the last one\r | |
31ff1c44 | 125 | NonEndingOpcode = [DEPEX_OPCODE_AND, DEPEX_OPCODE_OR, DEPEX_OPCODE_NOT, DEPEX_OPCODE_SOR]\r |
30fdf114 | 126 | # op code must not present at the same time\r |
31ff1c44 | 127 | ExclusiveOpcode = [DEPEX_OPCODE_BEFORE, DEPEX_OPCODE_AFTER]\r |
30fdf114 | 128 | # op code that should be the first one if it presents\r |
31ff1c44 | 129 | AboveAllOpcode = [DEPEX_OPCODE_SOR, DEPEX_OPCODE_BEFORE, DEPEX_OPCODE_AFTER]\r |
30fdf114 LG |
130 | \r |
131 | #\r | |
132 | # open and close brace must be taken as individual tokens\r | |
133 | #\r | |
134 | TokenPattern = re.compile("(\(|\)|\{[^{}]+\{?[^{}]+\}?[ ]*\}|\w+)")\r | |
135 | \r | |
136 | ## Constructor\r | |
137 | #\r | |
138 | # @param Expression The list or string of dependency expression\r | |
139 | # @param ModuleType The type of the module using the dependency expression\r | |
140 | #\r | |
141 | def __init__(self, Expression, ModuleType, Optimize=False):\r | |
142 | self.ModuleType = ModuleType\r | |
143 | self.Phase = gType2Phase[ModuleType]\r | |
144 | if type(Expression) == type([]):\r | |
145 | self.ExpressionString = " ".join(Expression)\r | |
146 | self.TokenList = Expression\r | |
147 | else:\r | |
148 | self.ExpressionString = Expression\r | |
149 | self.GetExpressionTokenList()\r | |
150 | \r | |
151 | self.PostfixNotation = []\r | |
152 | self.OpcodeList = []\r | |
153 | \r | |
154 | self.GetPostfixNotation()\r | |
155 | self.ValidateOpcode()\r | |
156 | \r | |
157 | EdkLogger.debug(EdkLogger.DEBUG_8, repr(self))\r | |
158 | if Optimize:\r | |
159 | self.Optimize()\r | |
160 | EdkLogger.debug(EdkLogger.DEBUG_8, "\n Optimized: " + repr(self))\r | |
161 | \r | |
162 | def __str__(self):\r | |
163 | return " ".join(self.TokenList)\r | |
164 | \r | |
165 | def __repr__(self):\r | |
166 | WellForm = ''\r | |
167 | for Token in self.PostfixNotation:\r | |
168 | if Token in self.SupportedOpcode:\r | |
169 | WellForm += "\n " + Token\r | |
170 | else:\r | |
171 | WellForm += ' ' + Token\r | |
172 | return WellForm\r | |
173 | \r | |
174 | ## Split the expression string into token list\r | |
175 | def GetExpressionTokenList(self):\r | |
176 | self.TokenList = self.TokenPattern.findall(self.ExpressionString)\r | |
177 | \r | |
178 | ## Convert token list into postfix notation\r | |
179 | def GetPostfixNotation(self):\r | |
180 | Stack = []\r | |
181 | LastToken = ''\r | |
182 | for Token in self.TokenList:\r | |
183 | if Token == "(":\r | |
184 | if LastToken not in self.SupportedOpcode + ['(', '', None]:\r | |
185 | EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: missing operator before open parentheses",\r | |
186 | ExtraData="Near %s" % LastToken)\r | |
187 | Stack.append(Token)\r | |
188 | elif Token == ")":\r | |
189 | if '(' not in Stack:\r | |
190 | EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: mismatched parentheses",\r | |
191 | ExtraData=str(self))\r | |
192 | elif LastToken in self.SupportedOpcode + ['', None]:\r | |
193 | EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: missing operand before close parentheses",\r | |
194 | ExtraData="Near %s" % LastToken)\r | |
195 | while len(Stack) > 0:\r | |
196 | if Stack[-1] == '(':\r | |
197 | Stack.pop()\r | |
198 | break\r | |
199 | self.PostfixNotation.append(Stack.pop())\r | |
200 | elif Token in self.OpcodePriority:\r | |
31ff1c44 | 201 | if Token == DEPEX_OPCODE_NOT:\r |
30fdf114 LG |
202 | if LastToken not in self.SupportedOpcode + ['(', '', None]:\r |
203 | EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: missing operator before NOT",\r | |
204 | ExtraData="Near %s" % LastToken)\r | |
205 | elif LastToken in self.SupportedOpcode + ['(', '', None]:\r | |
206 | EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: missing operand before " + Token,\r | |
207 | ExtraData="Near %s" % LastToken)\r | |
208 | \r | |
209 | while len(Stack) > 0:\r | |
210 | if Stack[-1] == "(" or self.OpcodePriority[Token] >= self.OpcodePriority[Stack[-1]]:\r | |
211 | break\r | |
212 | self.PostfixNotation.append(Stack.pop())\r | |
213 | Stack.append(Token)\r | |
214 | self.OpcodeList.append(Token)\r | |
215 | else:\r | |
216 | if Token not in self.SupportedOpcode:\r | |
217 | # not OP, take it as GUID\r | |
218 | if LastToken not in self.SupportedOpcode + ['(', '', None]:\r | |
219 | EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: missing operator before %s" % Token,\r | |
220 | ExtraData="Near %s" % LastToken)\r | |
221 | if len(self.OpcodeList) == 0 or self.OpcodeList[-1] not in self.ExclusiveOpcode:\r | |
222 | if Token not in self.SupportedOperand:\r | |
31ff1c44 | 223 | self.PostfixNotation.append(DEPEX_OPCODE_PUSH)\r |
30fdf114 LG |
224 | # check if OP is valid in this phase\r |
225 | elif Token in self.Opcode[self.Phase]:\r | |
31ff1c44 | 226 | if Token == DEPEX_OPCODE_END:\r |
30fdf114 LG |
227 | break\r |
228 | self.OpcodeList.append(Token)\r | |
229 | else:\r | |
230 | EdkLogger.error("GenDepex", PARSER_ERROR,\r | |
231 | "Opcode=%s doesn't supported in %s stage " % (Token, self.Phase),\r | |
232 | ExtraData=str(self))\r | |
233 | self.PostfixNotation.append(Token)\r | |
234 | LastToken = Token\r | |
235 | \r | |
236 | # there should not be parentheses in Stack\r | |
237 | if '(' in Stack or ')' in Stack:\r | |
238 | EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid dependency expression: mismatched parentheses",\r | |
239 | ExtraData=str(self))\r | |
240 | while len(Stack) > 0:\r | |
241 | self.PostfixNotation.append(Stack.pop())\r | |
31ff1c44 CJ |
242 | if self.PostfixNotation[-1] != DEPEX_OPCODE_END:\r |
243 | self.PostfixNotation.append(DEPEX_OPCODE_END)\r | |
30fdf114 LG |
244 | \r |
245 | ## Validate the dependency expression\r | |
246 | def ValidateOpcode(self):\r | |
247 | for Op in self.AboveAllOpcode:\r | |
248 | if Op in self.PostfixNotation:\r | |
249 | if Op != self.PostfixNotation[0]:\r | |
250 | EdkLogger.error("GenDepex", PARSER_ERROR, "%s should be the first opcode in the expression" % Op,\r | |
251 | ExtraData=str(self))\r | |
252 | if len(self.PostfixNotation) < 3:\r | |
253 | EdkLogger.error("GenDepex", PARSER_ERROR, "Missing operand for %s" % Op,\r | |
254 | ExtraData=str(self))\r | |
255 | for Op in self.ExclusiveOpcode:\r | |
256 | if Op in self.OpcodeList:\r | |
257 | if len(self.OpcodeList) > 1:\r | |
258 | EdkLogger.error("GenDepex", PARSER_ERROR, "%s should be the only opcode in the expression" % Op,\r | |
259 | ExtraData=str(self))\r | |
260 | if len(self.PostfixNotation) < 3:\r | |
261 | EdkLogger.error("GenDepex", PARSER_ERROR, "Missing operand for %s" % Op,\r | |
262 | ExtraData=str(self))\r | |
31ff1c44 | 263 | if self.TokenList[-1] != DEPEX_OPCODE_END and self.TokenList[-1] in self.NonEndingOpcode:\r |
30fdf114 LG |
264 | EdkLogger.error("GenDepex", PARSER_ERROR, "Extra %s at the end of the dependency expression" % self.TokenList[-1],\r |
265 | ExtraData=str(self))\r | |
31ff1c44 | 266 | if self.TokenList[-1] == DEPEX_OPCODE_END and self.TokenList[-2] in self.NonEndingOpcode:\r |
30fdf114 LG |
267 | EdkLogger.error("GenDepex", PARSER_ERROR, "Extra %s at the end of the dependency expression" % self.TokenList[-2],\r |
268 | ExtraData=str(self))\r | |
31ff1c44 | 269 | if DEPEX_OPCODE_END in self.TokenList and DEPEX_OPCODE_END != self.TokenList[-1]:\r |
30fdf114 LG |
270 | EdkLogger.error("GenDepex", PARSER_ERROR, "Extra expressions after END",\r |
271 | ExtraData=str(self))\r | |
272 | \r | |
273 | ## Simply optimize the dependency expression by removing duplicated operands\r | |
274 | def Optimize(self):\r | |
275 | ValidOpcode = list(set(self.OpcodeList))\r | |
31ff1c44 | 276 | if len(ValidOpcode) != 1 or ValidOpcode[0] not in [DEPEX_OPCODE_AND, DEPEX_OPCODE_OR]:\r |
30fdf114 LG |
277 | return\r |
278 | Op = ValidOpcode[0]\r | |
279 | NewOperand = []\r | |
280 | AllOperand = set()\r | |
281 | for Token in self.PostfixNotation:\r | |
282 | if Token in self.SupportedOpcode or Token in NewOperand:\r | |
283 | continue\r | |
284 | AllOperand.add(Token)\r | |
31ff1c44 CJ |
285 | if Token == DEPEX_OPCODE_TRUE:\r |
286 | if Op == DEPEX_OPCODE_AND:\r | |
30fdf114 LG |
287 | continue\r |
288 | else:\r | |
289 | NewOperand.append(Token)\r | |
290 | break\r | |
31ff1c44 CJ |
291 | elif Token == DEPEX_OPCODE_FALSE:\r |
292 | if Op == DEPEX_OPCODE_OR:\r | |
30fdf114 LG |
293 | continue\r |
294 | else:\r | |
295 | NewOperand.append(Token)\r | |
296 | break\r | |
297 | NewOperand.append(Token)\r | |
298 | \r | |
299 | # don't generate depex if only TRUE operand left\r | |
31ff1c44 | 300 | if self.ModuleType == SUP_MODULE_PEIM and len(NewOperand) == 1 and NewOperand[0] == DEPEX_OPCODE_TRUE:\r |
30fdf114 | 301 | self.PostfixNotation = []\r |
47fea6af | 302 | return\r |
30fdf114 LG |
303 | \r |
304 | # don't generate depex if all operands are architecture protocols\r | |
8bb63e37 | 305 | if self.ModuleType in [SUP_MODULE_UEFI_DRIVER, SUP_MODULE_DXE_DRIVER, SUP_MODULE_DXE_RUNTIME_DRIVER, SUP_MODULE_DXE_SAL_DRIVER, SUP_MODULE_DXE_SMM_DRIVER, SUP_MODULE_MM_STANDALONE] and \\r |
31ff1c44 | 306 | Op == DEPEX_OPCODE_AND and \\r |
30fdf114 LG |
307 | self.ArchProtocols == set([GuidStructureStringToGuidString(Guid) for Guid in AllOperand]):\r |
308 | self.PostfixNotation = []\r | |
309 | return\r | |
310 | \r | |
311 | if len(NewOperand) == 0:\r | |
312 | self.TokenList = list(AllOperand)\r | |
313 | else:\r | |
314 | self.TokenList = []\r | |
315 | while True:\r | |
316 | self.TokenList.append(NewOperand.pop(0))\r | |
317 | if NewOperand == []:\r | |
318 | break\r | |
319 | self.TokenList.append(Op)\r | |
320 | self.PostfixNotation = []\r | |
321 | self.GetPostfixNotation()\r | |
322 | \r | |
323 | \r | |
324 | ## Convert a GUID value in C structure format into its binary form\r | |
325 | #\r | |
326 | # @param Guid The GUID value in C structure format\r | |
327 | #\r | |
328 | # @retval array The byte array representing the GUID value\r | |
329 | #\r | |
330 | def GetGuidValue(self, Guid):\r | |
331 | GuidValueString = Guid.replace("{", "").replace("}", "").replace(" ", "")\r | |
332 | GuidValueList = GuidValueString.split(",")\r | |
333 | if len(GuidValueList) != 11:\r | |
334 | EdkLogger.error("GenDepex", PARSER_ERROR, "Invalid GUID value string or opcode: %s" % Guid)\r | |
335 | return pack("1I2H8B", *(int(value, 16) for value in GuidValueList))\r | |
336 | \r | |
337 | ## Save the binary form of dependency expression in file\r | |
338 | #\r | |
339 | # @param File The path of file. If None is given, put the data on console\r | |
340 | #\r | |
341 | # @retval True If the file doesn't exist or file is changed\r | |
342 | # @retval False If file exists and is not changed.\r | |
343 | #\r | |
344 | def Generate(self, File=None):\r | |
345 | Buffer = StringIO()\r | |
346 | if len(self.PostfixNotation) == 0:\r | |
347 | return False\r | |
348 | \r | |
349 | for Item in self.PostfixNotation:\r | |
350 | if Item in self.Opcode[self.Phase]:\r | |
351 | Buffer.write(pack("B", self.Opcode[self.Phase][Item]))\r | |
352 | elif Item in self.SupportedOpcode:\r | |
353 | EdkLogger.error("GenDepex", FORMAT_INVALID,\r | |
354 | "Opcode [%s] is not expected in %s phase" % (Item, self.Phase),\r | |
355 | ExtraData=self.ExpressionString)\r | |
356 | else:\r | |
357 | Buffer.write(self.GetGuidValue(Item))\r | |
358 | \r | |
359 | FilePath = ""\r | |
360 | FileChangeFlag = True\r | |
4231a819 | 361 | if File is None:\r |
30fdf114 LG |
362 | sys.stdout.write(Buffer.getvalue())\r |
363 | FilePath = "STDOUT"\r | |
364 | else:\r | |
365 | FileChangeFlag = SaveFileOnChange(File, Buffer.getvalue(), True)\r | |
366 | \r | |
367 | Buffer.close()\r | |
368 | return FileChangeFlag\r | |
369 | \r | |
b36d134f | 370 | versionNumber = ("0.04" + " " + gBUILD_VERSION)\r |
30fdf114 | 371 | __version__ = "%prog Version " + versionNumber\r |
31ff1c44 | 372 | __copyright__ = "Copyright (c) 2007-2018, Intel Corporation All rights reserved."\r |
30fdf114 LG |
373 | __usage__ = "%prog [options] [dependency_expression_file]"\r |
374 | \r | |
375 | ## Parse command line options\r | |
376 | #\r | |
377 | # @retval OptionParser\r | |
378 | #\r | |
379 | def GetOptions():\r | |
380 | from optparse import OptionParser\r | |
381 | \r | |
382 | Parser = OptionParser(description=__copyright__, version=__version__, usage=__usage__)\r | |
383 | \r | |
384 | Parser.add_option("-o", "--output", dest="OutputFile", default=None, metavar="FILE",\r | |
385 | help="Specify the name of depex file to be generated")\r | |
386 | Parser.add_option("-t", "--module-type", dest="ModuleType", default=None,\r | |
387 | help="The type of module for which the dependency expression serves")\r | |
388 | Parser.add_option("-e", "--dependency-expression", dest="Expression", default="",\r | |
389 | help="The string of dependency expression. If this option presents, the input file will be ignored.")\r | |
390 | Parser.add_option("-m", "--optimize", dest="Optimize", default=False, action="store_true",\r | |
391 | help="Do some simple optimization on the expression.")\r | |
392 | Parser.add_option("-v", "--verbose", dest="verbose", default=False, action="store_true",\r | |
393 | help="build with verbose information")\r | |
394 | Parser.add_option("-d", "--debug", action="store", type="int", help="Enable debug messages at specified level.")\r | |
395 | Parser.add_option("-q", "--quiet", dest="quiet", default=False, action="store_true",\r | |
396 | help="build with little information")\r | |
397 | \r | |
398 | return Parser.parse_args()\r | |
399 | \r | |
400 | \r | |
401 | ## Entrance method\r | |
402 | #\r | |
403 | # @retval 0 Tool was successful\r | |
404 | # @retval 1 Tool failed\r | |
405 | #\r | |
406 | def Main():\r | |
407 | EdkLogger.Initialize()\r | |
408 | Option, Input = GetOptions()\r | |
409 | \r | |
410 | # Set log level\r | |
411 | if Option.quiet:\r | |
412 | EdkLogger.SetLevel(EdkLogger.QUIET)\r | |
413 | elif Option.verbose:\r | |
414 | EdkLogger.SetLevel(EdkLogger.VERBOSE)\r | |
4231a819 | 415 | elif Option.debug is not None:\r |
30fdf114 LG |
416 | EdkLogger.SetLevel(Option.debug + 1)\r |
417 | else:\r | |
418 | EdkLogger.SetLevel(EdkLogger.INFO)\r | |
419 | \r | |
420 | try:\r | |
4231a819 | 421 | if Option.ModuleType is None or Option.ModuleType not in gType2Phase:\r |
30fdf114 LG |
422 | EdkLogger.error("GenDepex", OPTION_MISSING, "Module type is not specified or supported")\r |
423 | \r | |
424 | DxsFile = ''\r | |
425 | if len(Input) > 0 and Option.Expression == "":\r | |
426 | DxsFile = Input[0]\r | |
427 | DxsString = open(DxsFile, 'r').read().replace("\n", " ").replace("\r", " ")\r | |
428 | DxsString = gStartClosePattern.sub("\\1", DxsString)\r | |
429 | elif Option.Expression != "":\r | |
430 | if Option.Expression[0] == '"':\r | |
431 | DxsString = Option.Expression[1:-1]\r | |
432 | else:\r | |
433 | DxsString = Option.Expression\r | |
434 | else:\r | |
435 | EdkLogger.error("GenDepex", OPTION_MISSING, "No expression string or file given")\r | |
436 | \r | |
437 | Dpx = DependencyExpression(DxsString, Option.ModuleType, Option.Optimize)\r | |
4231a819 | 438 | if Option.OutputFile is not None:\r |
14c48571 | 439 | FileChangeFlag = Dpx.Generate(Option.OutputFile)\r |
47fea6af | 440 | if not FileChangeFlag and DxsFile:\r |
14c48571 | 441 | #\r |
442 | # Touch the output file if its time stamp is older than the original\r | |
443 | # DXS file to avoid re-invoke this tool for the dependency check in build rule.\r | |
444 | #\r | |
445 | if os.stat(DxsFile)[8] > os.stat(Option.OutputFile)[8]:\r | |
446 | os.utime(Option.OutputFile, None)\r | |
30fdf114 LG |
447 | else:\r |
448 | Dpx.Generate()\r | |
449 | except BaseException, X:\r | |
450 | EdkLogger.quiet("")\r | |
4231a819 | 451 | if Option is not None and Option.debug is not None:\r |
30fdf114 LG |
452 | EdkLogger.quiet(traceback.format_exc())\r |
453 | else:\r | |
454 | EdkLogger.quiet(str(X))\r | |
455 | return 1\r | |
456 | \r | |
457 | return 0\r | |
458 | \r | |
459 | if __name__ == '__main__':\r | |
460 | sys.exit(Main())\r | |
461 | \r |