]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFspPkg/Tools/GenCfgOpt.py
Fsp1.1 update.
[mirror_edk2.git] / IntelFspPkg / Tools / GenCfgOpt.py
CommitLineData
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
14import os\r
15import re\r
16import sys\r
17import struct\r
18from 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
60Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>\r
61\r
62Redistribution and use in source and binary forms, with or without modification,\r
63are 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
91class CGenCfgOpt:\r
92 def __init__(self):\r
93 self.Error = ''\r
94\r
95 self._GlobalDataDef = """\r
96GlobalDataDef\r
97 SKUID = 0, "DEFAULT"\r
98EndGlobalData\r
99\r
100"""\r
101 self._BuidinOptionTxt = """\r
102List &EN_DIS\r
103 Selection 0x1 , "Enabled"\r
104 Selection 0x0 , "Disabled"\r
105EndList\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
807def 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
814def 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
894if __name__ == '__main__':\r
895 sys.exit(Main())\r