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