]>
Commit | Line | Data |
---|---|---|
c8ec22a2 JY |
1 | ## @ GenCfgOpt.py\r |
2 | #\r | |
d5fb1edf | 3 | # Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>\r |
c8ec22a2 JY |
4 | # This program and the accompanying materials are licensed and made available under\r |
5 | # the terms and conditions of the BSD License that accompanies this distribution.\r | |
6 | # The full text of the license may be found at\r | |
7 | # http://opensource.org/licenses/bsd-license.php.\r | |
8 | #\r | |
9 | # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r | |
10 | # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r | |
11 | #\r | |
12 | ##\r | |
13 | \r | |
14 | import os\r | |
15 | import re\r | |
16 | import sys\r | |
17 | import struct\r | |
18 | from datetime import date\r | |
19 | \r | |
20 | # Generated file copyright header\r | |
21 | \r | |
22 | __copyright_txt__ = """## @file\r | |
23 | #\r | |
24 | # THIS IS AUTO-GENERATED FILE BY BUILD TOOLS AND PLEASE DO NOT MAKE MODIFICATION.\r | |
25 | #\r | |
26 | # This file lists all VPD informations for a platform collected by build.exe.\r | |
27 | #\r | |
28 | # Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>\r | |
29 | # This program and the accompanying materials\r | |
30 | # are licensed and made available under the terms and conditions of the BSD License\r | |
31 | # which accompanies this distribution. The full text of the license may be found at\r | |
32 | # http://opensource.org/licenses/bsd-license.php\r | |
33 | #\r | |
34 | # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r | |
35 | # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r | |
36 | #\r | |
37 | """\r | |
38 | \r | |
39 | __copyright_bsf__ = """/** @file\r | |
40 | \r | |
41 | Boot Setting File for Platform Configuration.\r | |
42 | \r | |
43 | Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>\r | |
44 | This program and the accompanying materials\r | |
45 | are licensed and made available under the terms and conditions of the BSD License\r | |
46 | which accompanies this distribution. The full text of the license may be found at\r | |
47 | http://opensource.org/licenses/bsd-license.php\r | |
48 | \r | |
49 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r | |
50 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r | |
51 | \r | |
52 | This file is automatically generated. Please do NOT modify !!!\r | |
53 | \r | |
54 | **/\r | |
55 | \r | |
56 | """\r | |
57 | \r | |
58 | __copyright_h__ = """/** @file\r | |
59 | \r | |
60 | Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>\r | |
61 | \r | |
62 | Redistribution and use in source and binary forms, with or without modification,\r | |
63 | are permitted provided that the following conditions are met:\r | |
64 | \r | |
65 | * Redistributions of source code must retain the above copyright notice, this\r | |
66 | list of conditions and the following disclaimer.\r | |
67 | * Redistributions in binary form must reproduce the above copyright notice, this\r | |
68 | list of conditions and the following disclaimer in the documentation and/or\r | |
69 | other materials provided with the distribution.\r | |
70 | * Neither the name of Intel Corporation nor the names of its contributors may\r | |
71 | be used to endorse or promote products derived from this software without\r | |
72 | specific prior written permission.\r | |
73 | \r | |
74 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r | |
75 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r | |
76 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r | |
77 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\r | |
78 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r | |
79 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r | |
80 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r | |
81 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r | |
82 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r | |
83 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\r | |
84 | THE POSSIBILITY OF SUCH DAMAGE.\r | |
85 | \r | |
86 | This file is automatically generated. Please do NOT modify !!!\r | |
87 | \r | |
88 | **/\r | |
89 | """\r | |
90 | \r | |
91 | class CGenCfgOpt:\r | |
92 | def __init__(self):\r | |
93 | self.Error = ''\r | |
94 | \r | |
95 | self._GlobalDataDef = """\r | |
96 | GlobalDataDef\r | |
97 | SKUID = 0, "DEFAULT"\r | |
98 | EndGlobalData\r | |
99 | \r | |
100 | """\r | |
101 | self._BuidinOptionTxt = """\r | |
102 | List &EN_DIS\r | |
103 | Selection 0x1 , "Enabled"\r | |
104 | Selection 0x0 , "Disabled"\r | |
105 | EndList\r | |
106 | \r | |
107 | """\r | |
108 | \r | |
109 | self._BsfKeyList = ['FIND','NAME','HELP','TYPE','PAGE','OPTION','ORDER']\r | |
110 | self._HdrKeyList = ['HEADER','STRUCT']\r | |
111 | self._BuidinOption = {'$EN_DIS' : 'EN_DIS'}\r | |
112 | \r | |
113 | self._MacroDict = {}\r | |
114 | self._CfgBlkDict = {}\r | |
115 | self._CfgPageDict = {}\r | |
116 | self._CfgItemList = []\r | |
117 | self._DscFile = ''\r | |
118 | self._FvDir = ''\r | |
119 | self._MapVer = 0\r | |
120 | \r | |
121 | def ParseMacros (self, MacroDefStr):\r | |
122 | # ['-DABC=1', '-D', 'CFG_DEBUG=1', '-D', 'CFG_OUTDIR=Build']\r | |
123 | self._MacroDict = {}\r | |
124 | IsExpression = False\r | |
125 | for Macro in MacroDefStr:\r | |
126 | if Macro.startswith('-D'):\r | |
127 | IsExpression = True\r | |
128 | if len(Macro) > 2:\r | |
129 | Macro = Macro[2:]\r | |
130 | else :\r | |
131 | continue\r | |
132 | if IsExpression:\r | |
133 | IsExpression = False\r | |
134 | Match = re.match("(\w+)=(.+)", Macro)\r | |
135 | if Match:\r | |
136 | self._MacroDict[Match.group(1)] = Match.group(2)\r | |
137 | else:\r | |
138 | Match = re.match("(\w+)", Macro)\r | |
139 | if Match:\r | |
140 | self._MacroDict[Match.group(1)] = ''\r | |
141 | if len(self._MacroDict) == 0:\r | |
142 | self.Error = "Invalid MACRO arguments"\r | |
143 | Error = 1\r | |
144 | else:\r | |
145 | Error = 0\r | |
146 | return Error\r | |
147 | \r | |
148 | \r | |
149 | def ParseDscFile (self, DscFile, FvDir):\r | |
150 | self._CfgItemList = []\r | |
151 | self._CfgPageDict = {}\r | |
152 | self._CfgBlkDict = {}\r | |
153 | self._DscFile = DscFile\r | |
154 | self._FvDir = FvDir\r | |
155 | \r | |
156 | IsDefSect = False\r | |
157 | IsUpdSect = False\r | |
158 | IsVpdSect = False\r | |
159 | Found = False\r | |
160 | \r | |
161 | IfStack = [True]\r | |
162 | ElifStack = []\r | |
163 | Error = 0\r | |
164 | \r | |
165 | DscFd = open(DscFile, "r")\r | |
166 | DscLines = DscFd.readlines()\r | |
167 | DscFd.close()\r | |
168 | \r | |
169 | ConfigDict = {}\r | |
170 | \r | |
171 | for DscLine in DscLines:\r | |
172 | Handle = False\r | |
173 | DscLine = DscLine.strip()\r | |
174 | Match = re.match("^\[(.+)\]", DscLine)\r | |
175 | if Match is not None:\r | |
176 | if Match.group(1).lower() == "Defines".lower():\r | |
177 | IsDefSect = True\r | |
178 | IsVpdSect = False\r | |
179 | IsUpdSect = False\r | |
180 | elif Match.group(1).lower() == "PcdsDynamicVpd".lower():\r | |
181 | ConfigDict = {}\r | |
182 | ConfigDict['header'] = 'ON'\r | |
183 | ConfigDict['region'] = 'VPD'\r | |
184 | ConfigDict['order'] = -1\r | |
185 | ConfigDict['page'] = ''\r | |
186 | ConfigDict['name'] = ''\r | |
187 | ConfigDict['find'] = ''\r | |
188 | ConfigDict['struct'] = ''\r | |
189 | ConfigDict['subreg'] = []\r | |
190 | IsDefSect = False\r | |
191 | IsVpdSect = True\r | |
192 | IsUpdSect = False\r | |
193 | elif Match.group(1).lower() == "PcdsDynamicVpd.Upd".lower():\r | |
194 | ConfigDict = {}\r | |
195 | ConfigDict['header'] = 'ON'\r | |
196 | ConfigDict['region'] = 'UPD'\r | |
197 | ConfigDict['order'] = -1\r | |
198 | ConfigDict['page'] = ''\r | |
199 | ConfigDict['name'] = ''\r | |
200 | ConfigDict['find'] = ''\r | |
201 | ConfigDict['struct'] = ''\r | |
202 | ConfigDict['subreg'] = []\r | |
203 | IsDefSect = False\r | |
204 | IsUpdSect = True\r | |
205 | IsVpdSect = False\r | |
206 | Found = True\r | |
207 | else:\r | |
208 | IsDefSect = False\r | |
209 | IsUpdSect = False\r | |
210 | IsVpdSect = False\r | |
211 | else:\r | |
212 | if IsDefSect or IsUpdSect or IsVpdSect:\r | |
213 | if DscLine == "!else":\r | |
214 | IfStack[-1] = not IfStack[-1]\r | |
215 | elif DscLine == "!endif":\r | |
216 | IfStack.pop()\r | |
217 | Level = ElifStack.pop()\r | |
218 | while Level > 0:\r | |
219 | IfStack.pop()\r | |
220 | Level = Level - 1\r | |
221 | else:\r | |
222 | Result = False\r | |
223 | Match = re.match("!(ifdef|ifndef)\s+\$\((\w+)\)", DscLine)\r | |
224 | if Match is not None:\r | |
225 | if Match.group(2) in self._MacroDict:\r | |
226 | if Match.group(1) == 'ifdef':\r | |
227 | Result = True\r | |
228 | else:\r | |
229 | if Match.group(1) == 'ifndef':\r | |
230 | Result = True\r | |
231 | ElifStack.append(0)\r | |
232 | IfStack.append(Result)\r | |
233 | else:\r | |
234 | Match = re.match("!(if|elseif)\s+\$\\((\w+)\)\s*==\s*(\w+|\$\(\w+\))", DscLine)\r | |
235 | if Match is not None:\r | |
236 | if Match.group(2) in self._MacroDict:\r | |
237 | MacroName = self._MacroDict[Match.group(2)]\r | |
238 | else:\r | |
239 | MacroName = ''\r | |
240 | Value = Match.group(3)\r | |
241 | if Value.startswith('$'):\r | |
242 | if Value[2:-1] in self._MacroDict:\r | |
243 | Value = self._MacroDict[Value[2:-1]]\r | |
244 | else:\r | |
245 | Value = ''\r | |
246 | if MacroName == Value:\r | |
247 | Result = True\r | |
248 | if Match.group(1) == "if":\r | |
249 | ElifStack.append(0)\r | |
250 | IfStack.append(Result)\r | |
251 | else: #elseif\r | |
252 | IfStack[-1] = not IfStack[-1]\r | |
253 | IfStack.append(Result)\r | |
254 | ElifStack[-1] = ElifStack[-1] + 1\r | |
255 | else:\r | |
256 | if len(DscLine) > 0 and DscLine[0] == '!':\r | |
95c95ac0 JY |
257 | #\r |
258 | # Current it can only handle build switch.\r | |
259 | # It does not support INF file in included dsc.\r | |
260 | #\r | |
c8ec22a2 JY |
261 | else:\r |
262 | if reduce(lambda x,y: x and y, IfStack):\r | |
263 | Handle = True\r | |
264 | \r | |
265 | if not Handle:\r | |
266 | continue\r | |
267 | \r | |
268 | if IsDefSect:\r | |
269 | #DEFINE UPD_TOOL_GUID = 8C3D856A-9BE6-468E-850A-24F7A8D38E09\r | |
270 | Match = re.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*([-\w]+)", DscLine)\r | |
271 | if Match:\r | |
272 | self._MacroDict[Match.group(1)] = Match.group(2)\r | |
273 | else:\r | |
274 | Match = re.match("^\s*#\s+!(BSF|HDR)\s+(.+)", DscLine)\r | |
275 | if Match:\r | |
276 | Remaining = Match.group(2)\r | |
277 | if Match.group(1) == 'BSF':\r | |
278 | Match = re.match("(?:^|.+\s+)PAGES:{(.+?)}", Remaining)\r | |
279 | if Match:\r | |
280 | # !BSF PAGES:{HSW:"Haswell System Agent", LPT:"Lynx Point PCH"}\r | |
281 | PageList = Match.group(1).split(',')\r | |
282 | for Page in PageList:\r | |
283 | Page = Page.strip()\r | |
284 | Match = re.match("(\w+):\"(.+)\"", Page)\r | |
285 | self._CfgPageDict[Match.group(1)] = Match.group(2)\r | |
286 | \r | |
287 | Match = re.match("(?:^|.+\s+)BLOCK:{NAME:\"(.+)\"\s*,\s*VER:\"(.+)\"\s*}", Remaining)\r | |
288 | if Match:\r | |
289 | self._CfgBlkDict['name'] = Match.group(1)\r | |
290 | self._CfgBlkDict['ver'] = Match.group(2)\r | |
291 | \r | |
292 | for Key in self._BsfKeyList:\r | |
293 | Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining)\r | |
294 | if Match:\r | |
295 | if Key in ['HELP', 'OPTION'] and Match.group(1).startswith('+'):\r | |
296 | ConfigDict[Key.lower()] += Match.group(1)[1:]\r | |
297 | else:\r | |
298 | ConfigDict[Key.lower()] = Match.group(1)\r | |
299 | else:\r | |
300 | for Key in self._HdrKeyList:\r | |
301 | Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining)\r | |
302 | if Match:\r | |
303 | ConfigDict[Key.lower()] = Match.group(1)\r | |
304 | \r | |
305 | # Check VPD/UPD\r | |
306 | if IsUpdSect:\r | |
307 | Match = re.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]{4})\s*\|\s*(\d+|0x[0-9a-fA-F]+)\s*\|\s*(.+)",DscLine)\r | |
308 | else:\r | |
309 | Match = re.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]+)(?:\s*\|\s*(.+))?", DscLine)\r | |
310 | if Match:\r | |
311 | ConfigDict['space'] = Match.group(1)\r | |
312 | ConfigDict['cname'] = Match.group(2)\r | |
313 | ConfigDict['offset'] = int (Match.group(3), 16)\r | |
314 | if ConfigDict['order'] == -1:\r | |
315 | ConfigDict['order'] = ConfigDict['offset'] << 8\r | |
316 | else:\r | |
317 | (Major, Minor) = ConfigDict['order'].split('.')\r | |
318 | ConfigDict['order'] = (int (Major, 16) << 8 ) + int (Minor, 16)\r | |
319 | if IsUpdSect:\r | |
320 | Value = Match.group(5).strip()\r | |
321 | if Match.group(4).startswith("0x"):\r | |
322 | Length = int (Match.group(4), 16)\r | |
323 | else :\r | |
324 | Length = int (Match.group(4))\r | |
325 | else:\r | |
326 | Value = Match.group(4)\r | |
327 | if Value is None:\r | |
328 | Value = ''\r | |
329 | Value = Value.strip()\r | |
330 | if '|' in Value:\r | |
331 | Match = re.match("^.+\s*\|\s*(.+)", Value)\r | |
332 | if Match:\r | |
333 | Value = Match.group(1)\r | |
334 | Length = -1\r | |
335 | \r | |
336 | ConfigDict['length'] = Length\r | |
337 | Match = re.match("\$\((\w+)\)", Value)\r | |
338 | if Match:\r | |
339 | if Match.group(1) in self._MacroDict:\r | |
340 | Value = self._MacroDict[Match.group(1)]\r | |
341 | ConfigDict['value'] = Value\r | |
342 | if ConfigDict['name'] == '':\r | |
343 | # Clear BSF specific items\r | |
344 | ConfigDict['help'] = ''\r | |
345 | ConfigDict['type'] = ''\r | |
346 | ConfigDict['option'] = ''\r | |
347 | \r | |
348 | self._CfgItemList.append(ConfigDict.copy())\r | |
349 | ConfigDict['name'] = ''\r | |
350 | ConfigDict['find'] = ''\r | |
351 | ConfigDict['struct'] = ''\r | |
352 | ConfigDict['order'] = -1\r | |
353 | ConfigDict['subreg'] = []\r | |
354 | else:\r | |
355 | # It could be a virtual item as below\r | |
356 | # !BSF FIELD:{1:SerialDebugPortAddress0}\r | |
357 | Match = re.match("^\s*#\s+!BSF\s+FIELD:{(.+):(\d+)}", DscLine)\r | |
358 | if Match:\r | |
359 | SubCfgDict = ConfigDict\r | |
360 | SubCfgDict['cname'] = Match.group(1)\r | |
361 | SubCfgDict['length'] = int (Match.group(2))\r | |
362 | if SubCfgDict['length'] > 0:\r | |
363 | LastItem = self._CfgItemList[-1]\r | |
364 | if len(LastItem['subreg']) == 0:\r | |
365 | SubOffset = 0\r | |
366 | else:\r | |
367 | SubOffset += LastItem['subreg'][-1]['length']\r | |
368 | SubCfgDict['offset'] = SubOffset\r | |
369 | LastItem['subreg'].append (SubCfgDict.copy())\r | |
370 | ConfigDict['name'] = ''\r | |
371 | return Error\r | |
372 | \r | |
373 | def UpdateSubRegionDefaultValue (self):\r | |
374 | Error = 0\r | |
375 | for Item in self._CfgItemList:\r | |
376 | if len(Item['subreg']) == 0:\r | |
377 | continue\r | |
378 | bytearray = []\r | |
379 | if Item['value'][0] == '{':\r | |
380 | binlist = Item['value'][1:-1].split(',')\r | |
381 | for each in binlist:\r | |
382 | each = each.strip()\r | |
383 | if each.startswith('0x'):\r | |
384 | value = int(each, 16)\r | |
385 | else:\r | |
386 | value = int(each)\r | |
387 | bytearray.append(value)\r | |
388 | else:\r | |
389 | if Item['value'].startswith('0x'):\r | |
390 | value = int(Item['value'], 16)\r | |
391 | else:\r | |
392 | value = int(Item['value'])\r | |
393 | idx = 0;\r | |
394 | while idx < Item['length']:\r | |
395 | bytearray.append(value & 0xFF)\r | |
396 | value = value >> 8\r | |
397 | idx = idx + 1\r | |
398 | for SubItem in Item['subreg']:\r | |
399 | if SubItem['length'] in (1,2,4,8):\r | |
400 | valuelist = [b for b in bytearray[SubItem['offset']:SubItem['offset']+SubItem['length']]]\r | |
401 | valuelist.reverse()\r | |
402 | valuestr = "".join('%02X' % b for b in valuelist)\r | |
403 | SubItem['value'] = '0x%s' % valuestr\r | |
404 | else:\r | |
405 | valuestr = ",".join('0x%02X' % b for b in bytearray[SubItem['offset']:SubItem['offset']+SubItem['length']])\r | |
406 | SubItem['value'] = '{%s}' % valuestr\r | |
407 | return Error\r | |
408 | \r | |
409 | def UpdateVpdSizeField (self):\r | |
410 | FvDir = self._FvDir;\r | |
411 | \r | |
412 | if 'VPD_TOOL_GUID' not in self._MacroDict:\r | |
413 | self.Error = "VPD_TOOL_GUID definition is missing in DSC file"\r | |
414 | return 1\r | |
415 | \r | |
416 | VpdMapFile = os.path.join(FvDir, self._MacroDict['VPD_TOOL_GUID'] + '.map')\r | |
417 | if not os.path.exists(VpdMapFile):\r | |
418 | self.Error = "VPD MAP file '%s' does not exist" % VpdMapFile\r | |
419 | return 2\r | |
420 | \r | |
421 | MapFd = open(VpdMapFile, "r")\r | |
422 | MapLines = MapFd.readlines()\r | |
423 | MapFd.close()\r | |
424 | \r | |
425 | VpdDict = {}\r | |
426 | PcdDict = {}\r | |
427 | for MapLine in MapLines:\r | |
428 | #gPlatformFspPkgTokenSpaceGuid.PcdVpdRegionSign | DEFAULT | 0x0000 | 8 | 0x534450565F425346\r | |
429 | #gPlatformFspPkgTokenSpaceGuid.PcdVpdRegionSign | 0x0000 | 8 | 0x534450565F425346\r | |
430 | #gPlatformFspPkgTokenSpaceGuid.PcdTest | 0x0008 | 5 | {0x01,0x02,0x03,0x04,0x05}\r | |
431 | Match = re.match("([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)(\s\|\sDEFAULT)?\s\|\s(0x[0-9A-F]{4})\s\|\s(\d+|0x[0-9a-fA-F]+)\s\|\s(\{?[x0-9a-fA-F,\s]+\}?)", MapLine)\r | |
432 | if Match:\r | |
433 | Space = Match.group(1)\r | |
434 | Name = Match.group(2)\r | |
435 | if (self._MapVer == 0) and (Match.group(3) != None):\r | |
436 | self._MapVer = 1\r | |
437 | Offset = int (Match.group(4), 16)\r | |
438 | if Match.group(5).startswith("0x"):\r | |
439 | Length = int (Match.group(5), 16)\r | |
440 | else :\r | |
441 | Length = int (Match.group(5))\r | |
442 | PcdDict["len"] = Length\r | |
443 | PcdDict["value"] = Match.group(6)\r | |
444 | VpdDict[Space+'.'+Name] = dict(PcdDict)\r | |
445 | \r | |
446 | for Item in self._CfgItemList:\r | |
447 | if Item['value'] == '':\r | |
448 | Item['value'] = VpdDict[Item['space']+'.'+Item['cname']]['value']\r | |
449 | if Item['length'] == -1:\r | |
450 | Item['length'] = VpdDict[Item['space']+'.'+Item['cname']]['len']\r | |
451 | if Item['struct'] != '':\r | |
452 | Type = Item['struct'].strip()\r | |
453 | if Type.endswith('*') and (Item['length'] != 4):\r | |
454 | self.Error = "Struct pointer '%s' has invalid size" % Type\r | |
455 | return 3\r | |
456 | \r | |
457 | return 0\r | |
458 | \r | |
459 | def CreateUpdTxtFile (self, UpdTxtFile):\r | |
460 | FvDir = self._FvDir\r | |
461 | if 'UPD_TOOL_GUID' not in self._MacroDict:\r | |
462 | self.Error = "UPD_TOOL_GUID definition is missing in DSC file"\r | |
463 | return 1\r | |
464 | \r | |
465 | if UpdTxtFile == '':\r | |
466 | UpdTxtFile = os.path.join(FvDir, self._MacroDict['UPD_TOOL_GUID'] + '.txt')\r | |
467 | \r | |
468 | ReCreate = False\r | |
469 | if not os.path.exists(UpdTxtFile):\r | |
470 | ReCreate = True\r | |
471 | else:\r | |
472 | DscTime = os.path.getmtime(self._DscFile)\r | |
473 | TxtTime = os.path.getmtime(UpdTxtFile)\r | |
474 | if DscTime > TxtTime:\r | |
475 | ReCreate = True\r | |
476 | \r | |
477 | if not ReCreate:\r | |
478 | # DSC has not been modified yet\r | |
479 | # So don't have to re-generate other files\r | |
480 | self.Error = 'No DSC file change, skip to create UPD TXT file'\r | |
481 | return 256\r | |
482 | \r | |
483 | TxtFd = open(UpdTxtFile, "w")\r | |
484 | TxtFd.write("%s\n" % (__copyright_txt__ % date.today().year))\r | |
485 | \r | |
486 | NextOffset = 0\r | |
487 | SpaceIdx = 0\r | |
488 | if self._MapVer == 1:\r | |
489 | Default = 'DEFAULT|'\r | |
490 | else:\r | |
491 | Default = ''\r | |
492 | for Item in self._CfgItemList:\r | |
493 | if Item['region'] != 'UPD':\r | |
494 | continue\r | |
495 | Offset = Item['offset']\r | |
496 | if NextOffset < Offset:\r | |
497 | # insert one line\r | |
498 | TxtFd.write("%s.UnusedUpdSpace%d|%s0x%04X|0x%04X|{0}\n" % (Item['space'], SpaceIdx, Default, NextOffset, Offset - NextOffset))\r | |
499 | SpaceIdx = SpaceIdx + 1\r | |
500 | NextOffset = Offset + Item['length']\r | |
501 | TxtFd.write("%s.%s|%s0x%04X|%s|%s\n" % (Item['space'],Item['cname'],Default,Item['offset'],Item['length'],Item['value']))\r | |
502 | TxtFd.close()\r | |
503 | return 0\r | |
504 | \r | |
505 | def CreateField (self, Name, Length, Offset, Struct):\r | |
506 | PosName = 28\r | |
507 | PosComment = 30\r | |
508 | \r | |
509 | IsArray = False\r | |
510 | if Length == 1:\r | |
511 | Type = "UINT8"\r | |
512 | elif Length == 2:\r | |
513 | Type = "UINT16"\r | |
514 | elif Length == 4:\r | |
515 | Type = "UINT32"\r | |
516 | elif Length == 8:\r | |
517 | Type = "UINT64"\r | |
518 | else:\r | |
519 | Type = "UINT8"\r | |
520 | IsArray = True\r | |
521 | \r | |
522 | if Struct != '':\r | |
523 | IsArray = False\r | |
524 | Type = Struct\r | |
525 | \r | |
526 | if IsArray:\r | |
527 | Name = Name + '[%d]' % Length\r | |
528 | \r | |
529 | if len(Type) < PosName:\r | |
530 | Space1 = PosName - len(Type)\r | |
531 | else:\r | |
532 | Space1 = 1\r | |
533 | \r | |
534 | if len(Name) < PosComment:\r | |
535 | Space2 = PosComment - len(Name)\r | |
536 | else:\r | |
537 | Space2 = 1\r | |
538 | \r | |
539 | return " %s%s%s;%s/* Offset 0x%04X */\n" % (Type, ' ' * Space1, Name, ' ' * Space2, Offset)\r | |
540 | \r | |
541 | \r | |
542 | def CreateHeaderFile (self, InputHeaderFile, IsInternal):\r | |
543 | Error = 0\r | |
544 | FvDir = self._FvDir\r | |
545 | \r | |
546 | if IsInternal:\r | |
547 | HeaderFile = os.path.join(FvDir, 'VpdHeader.h')\r | |
548 | else:\r | |
549 | HeaderFile = os.path.join(FvDir, 'fsp_vpd.h')\r | |
550 | \r | |
551 | # Check if header needs to be recreated\r | |
552 | ReCreate = False\r | |
553 | if IsInternal:\r | |
554 | if not os.path.exists(HeaderFile):\r | |
555 | ReCreate = True\r | |
556 | else:\r | |
557 | DscTime = os.path.getmtime(self._DscFile)\r | |
558 | HeadTime = os.path.getmtime(HeaderFile)\r | |
559 | if not os.path.exists(InputHeaderFile):\r | |
560 | InpTime = HeadTime\r | |
561 | else:\r | |
562 | InpTime = os.path.getmtime(InputHeaderFile)\r | |
563 | if DscTime > HeadTime or InpTime > HeadTime:\r | |
564 | ReCreate = True\r | |
565 | \r | |
566 | if not ReCreate:\r | |
567 | self.Error = "No DSC or input header file is changed, skip the header file generating"\r | |
568 | return 256\r | |
569 | \r | |
570 | HeaderFd = open(HeaderFile, "w")\r | |
571 | FileBase = os.path.basename(HeaderFile)\r | |
572 | FileName = FileBase.replace(".", "_").upper()\r | |
573 | HeaderFd.write("%s\n" % (__copyright_h__ % date.today().year))\r | |
574 | HeaderFd.write("#ifndef __%s__\n" % FileName)\r | |
575 | HeaderFd.write("#define __%s__\n\n" % FileName)\r | |
576 | HeaderFd.write("#pragma pack(1)\n\n")\r | |
577 | \r | |
578 | if InputHeaderFile != '':\r | |
579 | if not os.path.exists(InputHeaderFile):\r | |
580 | self.Error = "Input header file '%s' does not exist" % InputHeaderFile\r | |
581 | return 2\r | |
582 | \r | |
583 | InFd = open(InputHeaderFile, "r")\r | |
584 | IncLines = InFd.readlines()\r | |
585 | InFd.close()\r | |
586 | \r | |
587 | Export = False\r | |
588 | for Line in IncLines:\r | |
589 | Match = re.search ("!EXPORT\s+EXTERNAL_BOOTLOADER_STRUCT_(BEGIN|END)\s+", Line)\r | |
590 | if Match:\r | |
591 | if Match.group(1) == "BEGIN":\r | |
592 | Export = True\r | |
593 | continue\r | |
594 | else:\r | |
595 | Export = False\r | |
596 | continue\r | |
597 | if Export:\r | |
598 | HeaderFd.write(Line)\r | |
599 | HeaderFd.write("\n\n")\r | |
600 | \r | |
601 | for Region in ['UPD', 'VPD']:\r | |
602 | \r | |
603 | # Write PcdVpdRegionSign and PcdImageRevision\r | |
604 | if Region[0] == 'V':\r | |
605 | if 'VPD_TOOL_GUID' not in self._MacroDict:\r | |
606 | self.Error = "VPD_TOOL_GUID definition is missing in DSC file"\r | |
607 | Error = 1\r | |
608 | break\r | |
609 | \r | |
610 | BinFile = os.path.join(FvDir, self._MacroDict['VPD_TOOL_GUID'] + ".bin")\r | |
611 | if not os.path.exists(BinFile):\r | |
612 | self.Error = "VPD binary file '%s' does not exist" % BinFile\r | |
613 | Error = 2\r | |
614 | break\r | |
615 | \r | |
616 | BinFd = open(BinFile, "rb")\r | |
617 | IdStr = BinFd.read(0x08)\r | |
63c05743 JY |
618 | ImageId = struct.unpack('<Q', IdStr)\r |
619 | ImageRev = struct.unpack('<I', BinFd.read(0x04))\r | |
c8ec22a2 JY |
620 | BinFd.close()\r |
621 | \r | |
95c95ac0 JY |
622 | HeaderFd.write("#define FSP_IMAGE_ID 0x%016X /* '%s' */\n" % (ImageId[0], IdStr))\r |
623 | HeaderFd.write("#define FSP_IMAGE_REV 0x%08X \n\n" % ImageRev[0])\r | |
c8ec22a2 JY |
624 | \r |
625 | HeaderFd.write("typedef struct _" + Region[0] + "PD_DATA_REGION {\n")\r | |
626 | NextOffset = 0\r | |
627 | SpaceIdx = 0\r | |
628 | Offset = 0\r | |
629 | \r | |
630 | LastVisible = True\r | |
631 | ResvOffset = 0\r | |
632 | ResvIdx = 0\r | |
633 | LineBuffer = []\r | |
634 | for Item in self._CfgItemList:\r | |
635 | if Item['region'] != Region:\r | |
636 | continue\r | |
637 | \r | |
638 | NextVisible = LastVisible\r | |
639 | if not IsInternal:\r | |
640 | if LastVisible and (Item['header'] == 'OFF'):\r | |
641 | NextVisible = False\r | |
642 | ResvOffset = Item['offset']\r | |
643 | elif (not LastVisible) and Item['header'] == 'ON':\r | |
644 | NextVisible = True\r | |
645 | Name = "Reserved" + Region[0] + "pdSpace%d" % ResvIdx\r | |
646 | ResvIdx = ResvIdx + 1\r | |
647 | HeaderFd.write(self.CreateField (Name, Item["offset"] - ResvOffset, ResvOffset, ''))\r | |
648 | \r | |
649 | if Offset < Item["offset"]:\r | |
650 | if IsInternal or LastVisible:\r | |
651 | Name = "Unused" + Region[0] + "pdSpace%d" % SpaceIdx\r | |
652 | LineBuffer.append(self.CreateField (Name, Item["offset"] - Offset, Offset, ''))\r | |
653 | SpaceIdx = SpaceIdx + 1\r | |
654 | Offset = Item["offset"]\r | |
655 | \r | |
656 | if Offset != Item["offset"]:\r | |
657 | print "Unsorted offset 0x%04X\n" % Item["offset"]\r | |
658 | error = 2\r | |
659 | break;\r | |
660 | \r | |
661 | LastVisible = NextVisible\r | |
662 | \r | |
663 | Offset = Offset + Item["length"]\r | |
664 | if IsInternal or LastVisible:\r | |
665 | for Each in LineBuffer:\r | |
666 | HeaderFd.write (Each)\r | |
667 | LineBuffer = []\r | |
668 | HeaderFd.write(self.CreateField (Item["cname"], Item["length"], Item["offset"], Item['struct']))\r | |
669 | \r | |
670 | HeaderFd.write("} " + Region[0] + "PD_DATA_REGION;\n\n")\r | |
671 | HeaderFd.write("#pragma pack()\n\n")\r | |
672 | HeaderFd.write("#endif\n")\r | |
673 | HeaderFd.close()\r | |
674 | \r | |
675 | return Error\r | |
676 | \r | |
677 | def WriteBsfStruct (self, BsfFd, Item):\r | |
678 | if Item['type'] == "None":\r | |
679 | Space = "gPlatformFspPkgTokenSpaceGuid"\r | |
680 | else:\r | |
681 | Space = Item['space']\r | |
682 | Line = " $%s_%s" % (Space, Item['cname'])\r | |
683 | Match = re.match("\s*\{([x0-9a-fA-F,\s]+)\}\s*", Item['value'])\r | |
684 | if Match:\r | |
685 | DefaultValue = Match.group(1).strip()\r | |
686 | else:\r | |
687 | DefaultValue = Item['value'].strip()\r | |
688 | BsfFd.write(" %s%s%4d bytes $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['length'], DefaultValue))\r | |
689 | TmpList = []\r | |
690 | if Item['type'] == "Combo":\r | |
691 | if not Item['option'] in self._BuidinOption:\r | |
692 | OptList = Item['option'].split(',')\r | |
693 | for Option in OptList:\r | |
694 | Option = Option.strip()\r | |
695 | (OpVal, OpStr) = Option.split(':')\r | |
696 | TmpList.append((OpVal, OpStr))\r | |
697 | return TmpList\r | |
698 | \r | |
699 | def WriteBsfOption (self, BsfFd, Item):\r | |
700 | PcdName = Item['space'] + '_' + Item['cname']\r | |
701 | WriteHelp = 0\r | |
702 | if Item['type'] == "Combo":\r | |
703 | if Item['option'] in self._BuidinOption:\r | |
704 | Options = self._BuidinOption[Item['option']]\r | |
705 | else:\r | |
706 | Options = PcdName\r | |
707 | BsfFd.write(' %s $%s, "%s", &%s,\n' % (Item['type'], PcdName, Item['name'], Options));\r | |
708 | WriteHelp = 1\r | |
709 | elif Item['type'].startswith("EditNum"):\r | |
710 | Match = re.match("EditNum\s*,\s*(HEX|DEC)\s*,\s*\((\d+|0x[0-9A-Fa-f]+)\s*,\s*(\d+|0x[0-9A-Fa-f]+)\)", Item['type'])\r | |
711 | if Match:\r | |
712 | BsfFd.write(' EditNum $%s, "%s", %s,\n' % (PcdName, Item['name'], Match.group(1)));\r | |
713 | WriteHelp = 2\r | |
714 | elif Item['type'].startswith("EditText"):\r | |
715 | BsfFd.write(' %s $%s, "%s",\n' % (Item['type'], PcdName, Item['name']));\r | |
716 | WriteHelp = 1\r | |
717 | \r | |
718 | if WriteHelp > 0:\r | |
719 | HelpLines = Item['help'].split('\\n\\r')\r | |
720 | FirstLine = True\r | |
721 | for HelpLine in HelpLines:\r | |
722 | if FirstLine:\r | |
723 | FirstLine = False\r | |
724 | BsfFd.write(' Help "%s"\n' % (HelpLine));\r | |
725 | else:\r | |
726 | BsfFd.write(' "%s"\n' % (HelpLine));\r | |
727 | if WriteHelp == 2:\r | |
728 | BsfFd.write(' "Valid range: %s ~ %s"\n' % (Match.group(2), Match.group(3)));\r | |
729 | \r | |
730 | def GenerateBsfFile (self, BsfFile):\r | |
731 | \r | |
732 | if BsfFile == '':\r | |
733 | self.Error = "BSF output file '%s' is invalid" % BsfFile\r | |
734 | return 1\r | |
735 | \r | |
736 | Error = 0\r | |
737 | OptionDict = {}\r | |
738 | BsfFd = open(BsfFile, "w")\r | |
739 | BsfFd.write("%s\n" % (__copyright_bsf__ % date.today().year))\r | |
740 | BsfFd.write("%s\n" % self._GlobalDataDef);\r | |
741 | BsfFd.write("StructDef\n")\r | |
742 | NextOffset = -1\r | |
743 | for Item in self._CfgItemList:\r | |
744 | if Item['find'] != '':\r | |
745 | BsfFd.write('\n Find "%s"\n' % Item['find'])\r | |
746 | NextOffset = Item['offset'] + Item['length']\r | |
747 | if Item['name'] != '':\r | |
748 | if NextOffset != Item['offset']:\r | |
749 | BsfFd.write(" Skip %d bytes\n" % (Item['offset'] - NextOffset))\r | |
750 | if len(Item['subreg']) > 0:\r | |
751 | NextOffset = Item['offset']\r | |
752 | for SubItem in Item['subreg']:\r | |
753 | NextOffset += SubItem['length']\r | |
754 | if SubItem['name'] == '':\r | |
755 | BsfFd.write(" Skip %d bytes\n" % (SubItem['length']))\r | |
756 | else:\r | |
757 | Options = self.WriteBsfStruct(BsfFd, SubItem)\r | |
758 | if len(Options) > 0:\r | |
759 | OptionDict[SubItem['space']+'_'+SubItem['cname']] = Options\r | |
760 | if (Item['offset'] + Item['length']) < NextOffset:\r | |
761 | self.Error = "BSF sub region '%s' length does not match" % (Item['space']+'.'+Item['cname'])\r | |
762 | return 2\r | |
763 | else:\r | |
764 | NextOffset = Item['offset'] + Item['length']\r | |
765 | Options = self.WriteBsfStruct(BsfFd, Item)\r | |
766 | if len(Options) > 0:\r | |
767 | OptionDict[Item['space']+'_'+Item['cname']] = Options\r | |
768 | BsfFd.write("\nEndStruct\n\n")\r | |
769 | \r | |
770 | BsfFd.write("%s" % self._BuidinOptionTxt);\r | |
771 | \r | |
772 | for Each in OptionDict:\r | |
773 | BsfFd.write("List &%s\n" % Each);\r | |
774 | for Item in OptionDict[Each]:\r | |
775 | BsfFd.write(' Selection %s , "%s"\n' % (Item[0], Item[1]));\r | |
776 | BsfFd.write("EndList\n\n");\r | |
777 | \r | |
778 | BsfFd.write("BeginInfoBlock\n");\r | |
779 | BsfFd.write(' PPVer "%s"\n' % (self._CfgBlkDict['ver']));\r | |
780 | BsfFd.write(' Description "%s"\n' % (self._CfgBlkDict['name']));\r | |
781 | BsfFd.write("EndInfoBlock\n\n");\r | |
782 | \r | |
783 | for Each in self._CfgPageDict:\r | |
784 | BsfFd.write('Page "%s"\n' % self._CfgPageDict[Each]);\r | |
785 | BsfItems = []\r | |
786 | for Item in self._CfgItemList:\r | |
787 | if Item['name'] != '':\r | |
788 | if Item['page'] != Each:\r | |
789 | continue\r | |
790 | if len(Item['subreg']) > 0:\r | |
791 | for SubItem in Item['subreg']:\r | |
792 | if SubItem['name'] != '':\r | |
793 | BsfItems.append(SubItem)\r | |
794 | else:\r | |
795 | BsfItems.append(Item)\r | |
796 | \r | |
797 | BsfItems.sort(key=lambda x: x['order'])\r | |
798 | \r | |
799 | for Item in BsfItems:\r | |
800 | self.WriteBsfOption (BsfFd, Item)\r | |
801 | BsfFd.write("EndPage\n\n");\r | |
802 | \r | |
803 | BsfFd.close()\r | |
804 | return Error\r | |
805 | \r | |
806 | \r | |
807 | def Usage():\r | |
808 | print "GenCfgOpt Version 0.50"\r | |
809 | print "Usage:"\r | |
810 | print " GenCfgOpt UPDTXT PlatformDscFile BuildFvDir [TxtOutFile] [-D Macros]"\r | |
811 | print " GenCfgOpt HEADER PlatformDscFile BuildFvDir [InputHFile] [-D Macros]"\r | |
812 | print " GenCfgOpt GENBSF PlatformDscFile BuildFvDir BsfOutFile [-D Macros]"\r | |
813 | \r | |
814 | def Main():\r | |
815 | #\r | |
816 | # Parse the options and args\r | |
817 | #\r | |
818 | GenCfgOpt = CGenCfgOpt()\r | |
819 | argc = len(sys.argv)\r | |
820 | if argc < 4:\r | |
821 | Usage()\r | |
822 | return 1\r | |
823 | else:\r | |
824 | DscFile = sys.argv[2]\r | |
825 | if not os.path.exists(DscFile):\r | |
826 | print "ERROR: Cannot open DSC file '%s' !" % DscFile\r | |
827 | return 2\r | |
828 | \r | |
829 | OutFile = ''\r | |
830 | if argc > 4:\r | |
831 | if sys.argv[4][0] == '-':\r | |
832 | Start = 4\r | |
833 | else:\r | |
834 | OutFile = sys.argv[4]\r | |
835 | Start = 5\r | |
836 | if GenCfgOpt.ParseMacros(sys.argv[Start:]) != 0:\r | |
837 | print "ERROR: %s !" % GenCfgOpt.Error\r | |
838 | return 3\r | |
839 | \r | |
840 | FvDir = sys.argv[3]\r | |
841 | if not os.path.isdir(FvDir):\r | |
842 | print "ERROR: FV folder '%s' is invalid !" % FvDir\r | |
843 | return 4\r | |
844 | \r | |
845 | if GenCfgOpt.ParseDscFile(DscFile, FvDir) != 0:\r | |
846 | print "ERROR: %s !" % GenCfgOpt.Error\r | |
847 | return 5\r | |
848 | \r | |
849 | \r | |
850 | if GenCfgOpt.UpdateVpdSizeField() != 0:\r | |
851 | print "ERROR: %s !" % GenCfgOpt.Error\r | |
852 | return 6\r | |
853 | \r | |
854 | if GenCfgOpt.UpdateSubRegionDefaultValue() != 0:\r | |
855 | print "ERROR: %s !" % GenCfgOpt.Error\r | |
856 | return 7\r | |
857 | \r | |
858 | if sys.argv[1] == "UPDTXT":\r | |
859 | Ret = GenCfgOpt.CreateUpdTxtFile(OutFile)\r | |
860 | if Ret != 0:\r | |
861 | # No change is detected\r | |
862 | if Ret == 256:\r | |
863 | print "INFO: %s !" % (GenCfgOpt.Error)\r | |
864 | else :\r | |
865 | print "ERROR: %s !" % (GenCfgOpt.Error)\r | |
866 | return Ret\r | |
867 | elif sys.argv[1] == "HEADER":\r | |
868 | Ret = GenCfgOpt.CreateHeaderFile(OutFile, True)\r | |
869 | if Ret != 0:\r | |
870 | # No change is detected\r | |
871 | if Ret == 256:\r | |
872 | print "INFO: %s !" % (GenCfgOpt.Error)\r | |
873 | else :\r | |
874 | print "ERROR: %s !" % (GenCfgOpt.Error)\r | |
875 | return Ret\r | |
876 | if GenCfgOpt.CreateHeaderFile(OutFile, False) != 0:\r | |
877 | print "ERROR: %s !" % GenCfgOpt.Error\r | |
878 | return 8\r | |
879 | elif sys.argv[1] == "GENBSF":\r | |
880 | if GenCfgOpt.GenerateBsfFile(OutFile) != 0:\r | |
881 | print "ERROR: %s !" % GenCfgOpt.Error\r | |
882 | return 9\r | |
883 | else:\r | |
884 | if argc < 5:\r | |
885 | Usage()\r | |
886 | return 1\r | |
887 | print "ERROR: Unknown command '%s' !" % sys.argv[1]\r | |
888 | Usage()\r | |
889 | return 1\r | |
890 | return 0\r | |
891 | return 0\r | |
892 | \r | |
893 | \r | |
894 | if __name__ == '__main__':\r | |
895 | sys.exit(Main())\r |