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