]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFspPkg/Tools/GenCfgOpt.py
properly support GCC - pass 'I' (int) rather than 'L' (long) to struct.unpack.
[mirror_edk2.git] / IntelFspPkg / Tools / GenCfgOpt.py
CommitLineData
c8ec22a2
JY
1## @ GenCfgOpt.py\r
2#\r
3# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>\r
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
257 self.Error = "Invalid DscLine '%s'" % DscLine\r
258 Error = 3\r
259 break;\r
260 else:\r
261 if reduce(lambda x,y: x and y, IfStack):\r
262 Handle = True\r
263\r
264 if not Handle:\r
265 continue\r
266\r
267 if IsDefSect:\r
268 #DEFINE UPD_TOOL_GUID = 8C3D856A-9BE6-468E-850A-24F7A8D38E09\r
269 Match = re.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*([-\w]+)", DscLine)\r
270 if Match:\r
271 self._MacroDict[Match.group(1)] = Match.group(2)\r
272 else:\r
273 Match = re.match("^\s*#\s+!(BSF|HDR)\s+(.+)", DscLine)\r
274 if Match:\r
275 Remaining = Match.group(2)\r
276 if Match.group(1) == 'BSF':\r
277 Match = re.match("(?:^|.+\s+)PAGES:{(.+?)}", Remaining)\r
278 if Match:\r
279 # !BSF PAGES:{HSW:"Haswell System Agent", LPT:"Lynx Point PCH"}\r
280 PageList = Match.group(1).split(',')\r
281 for Page in PageList:\r
282 Page = Page.strip()\r
283 Match = re.match("(\w+):\"(.+)\"", Page)\r
284 self._CfgPageDict[Match.group(1)] = Match.group(2)\r
285\r
286 Match = re.match("(?:^|.+\s+)BLOCK:{NAME:\"(.+)\"\s*,\s*VER:\"(.+)\"\s*}", Remaining)\r
287 if Match:\r
288 self._CfgBlkDict['name'] = Match.group(1)\r
289 self._CfgBlkDict['ver'] = Match.group(2)\r
290\r
291 for Key in self._BsfKeyList:\r
292 Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining)\r
293 if Match:\r
294 if Key in ['HELP', 'OPTION'] and Match.group(1).startswith('+'):\r
295 ConfigDict[Key.lower()] += Match.group(1)[1:]\r
296 else:\r
297 ConfigDict[Key.lower()] = Match.group(1)\r
298 else:\r
299 for Key in self._HdrKeyList:\r
300 Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining)\r
301 if Match:\r
302 ConfigDict[Key.lower()] = Match.group(1)\r
303\r
304 # Check VPD/UPD\r
305 if IsUpdSect:\r
306 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
307 else:\r
308 Match = re.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]+)(?:\s*\|\s*(.+))?", DscLine)\r
309 if Match:\r
310 ConfigDict['space'] = Match.group(1)\r
311 ConfigDict['cname'] = Match.group(2)\r
312 ConfigDict['offset'] = int (Match.group(3), 16)\r
313 if ConfigDict['order'] == -1:\r
314 ConfigDict['order'] = ConfigDict['offset'] << 8\r
315 else:\r
316 (Major, Minor) = ConfigDict['order'].split('.')\r
317 ConfigDict['order'] = (int (Major, 16) << 8 ) + int (Minor, 16)\r
318 if IsUpdSect:\r
319 Value = Match.group(5).strip()\r
320 if Match.group(4).startswith("0x"):\r
321 Length = int (Match.group(4), 16)\r
322 else :\r
323 Length = int (Match.group(4))\r
324 else:\r
325 Value = Match.group(4)\r
326 if Value is None:\r
327 Value = ''\r
328 Value = Value.strip()\r
329 if '|' in Value:\r
330 Match = re.match("^.+\s*\|\s*(.+)", Value)\r
331 if Match:\r
332 Value = Match.group(1)\r
333 Length = -1\r
334\r
335 ConfigDict['length'] = Length\r
336 Match = re.match("\$\((\w+)\)", Value)\r
337 if Match:\r
338 if Match.group(1) in self._MacroDict:\r
339 Value = self._MacroDict[Match.group(1)]\r
340 ConfigDict['value'] = Value\r
341 if ConfigDict['name'] == '':\r
342 # Clear BSF specific items\r
343 ConfigDict['help'] = ''\r
344 ConfigDict['type'] = ''\r
345 ConfigDict['option'] = ''\r
346\r
347 self._CfgItemList.append(ConfigDict.copy())\r
348 ConfigDict['name'] = ''\r
349 ConfigDict['find'] = ''\r
350 ConfigDict['struct'] = ''\r
351 ConfigDict['order'] = -1\r
352 ConfigDict['subreg'] = []\r
353 else:\r
354 # It could be a virtual item as below\r
355 # !BSF FIELD:{1:SerialDebugPortAddress0}\r
356 Match = re.match("^\s*#\s+!BSF\s+FIELD:{(.+):(\d+)}", DscLine)\r
357 if Match:\r
358 SubCfgDict = ConfigDict\r
359 SubCfgDict['cname'] = Match.group(1)\r
360 SubCfgDict['length'] = int (Match.group(2))\r
361 if SubCfgDict['length'] > 0:\r
362 LastItem = self._CfgItemList[-1]\r
363 if len(LastItem['subreg']) == 0:\r
364 SubOffset = 0\r
365 else:\r
366 SubOffset += LastItem['subreg'][-1]['length']\r
367 SubCfgDict['offset'] = SubOffset\r
368 LastItem['subreg'].append (SubCfgDict.copy())\r
369 ConfigDict['name'] = ''\r
370 return Error\r
371\r
372 def UpdateSubRegionDefaultValue (self):\r
373 Error = 0\r
374 for Item in self._CfgItemList:\r
375 if len(Item['subreg']) == 0:\r
376 continue\r
377 bytearray = []\r
378 if Item['value'][0] == '{':\r
379 binlist = Item['value'][1:-1].split(',')\r
380 for each in binlist:\r
381 each = each.strip()\r
382 if each.startswith('0x'):\r
383 value = int(each, 16)\r
384 else:\r
385 value = int(each)\r
386 bytearray.append(value)\r
387 else:\r
388 if Item['value'].startswith('0x'):\r
389 value = int(Item['value'], 16)\r
390 else:\r
391 value = int(Item['value'])\r
392 idx = 0;\r
393 while idx < Item['length']:\r
394 bytearray.append(value & 0xFF)\r
395 value = value >> 8\r
396 idx = idx + 1\r
397 for SubItem in Item['subreg']:\r
398 if SubItem['length'] in (1,2,4,8):\r
399 valuelist = [b for b in bytearray[SubItem['offset']:SubItem['offset']+SubItem['length']]]\r
400 valuelist.reverse()\r
401 valuestr = "".join('%02X' % b for b in valuelist)\r
402 SubItem['value'] = '0x%s' % valuestr\r
403 else:\r
404 valuestr = ",".join('0x%02X' % b for b in bytearray[SubItem['offset']:SubItem['offset']+SubItem['length']])\r
405 SubItem['value'] = '{%s}' % valuestr\r
406 return Error\r
407\r
408 def UpdateVpdSizeField (self):\r
409 FvDir = self._FvDir;\r
410\r
411 if 'VPD_TOOL_GUID' not in self._MacroDict:\r
412 self.Error = "VPD_TOOL_GUID definition is missing in DSC file"\r
413 return 1\r
414\r
415 VpdMapFile = os.path.join(FvDir, self._MacroDict['VPD_TOOL_GUID'] + '.map')\r
416 if not os.path.exists(VpdMapFile):\r
417 self.Error = "VPD MAP file '%s' does not exist" % VpdMapFile\r
418 return 2\r
419\r
420 MapFd = open(VpdMapFile, "r")\r
421 MapLines = MapFd.readlines()\r
422 MapFd.close()\r
423\r
424 VpdDict = {}\r
425 PcdDict = {}\r
426 for MapLine in MapLines:\r
427 #gPlatformFspPkgTokenSpaceGuid.PcdVpdRegionSign | DEFAULT | 0x0000 | 8 | 0x534450565F425346\r
428 #gPlatformFspPkgTokenSpaceGuid.PcdVpdRegionSign | 0x0000 | 8 | 0x534450565F425346\r
429 #gPlatformFspPkgTokenSpaceGuid.PcdTest | 0x0008 | 5 | {0x01,0x02,0x03,0x04,0x05}\r
430 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
431 if Match:\r
432 Space = Match.group(1)\r
433 Name = Match.group(2)\r
434 if (self._MapVer == 0) and (Match.group(3) != None):\r
435 self._MapVer = 1\r
436 Offset = int (Match.group(4), 16)\r
437 if Match.group(5).startswith("0x"):\r
438 Length = int (Match.group(5), 16)\r
439 else :\r
440 Length = int (Match.group(5))\r
441 PcdDict["len"] = Length\r
442 PcdDict["value"] = Match.group(6)\r
443 VpdDict[Space+'.'+Name] = dict(PcdDict)\r
444\r
445 for Item in self._CfgItemList:\r
446 if Item['value'] == '':\r
447 Item['value'] = VpdDict[Item['space']+'.'+Item['cname']]['value']\r
448 if Item['length'] == -1:\r
449 Item['length'] = VpdDict[Item['space']+'.'+Item['cname']]['len']\r
450 if Item['struct'] != '':\r
451 Type = Item['struct'].strip()\r
452 if Type.endswith('*') and (Item['length'] != 4):\r
453 self.Error = "Struct pointer '%s' has invalid size" % Type\r
454 return 3\r
455\r
456 return 0\r
457\r
458 def CreateUpdTxtFile (self, UpdTxtFile):\r
459 FvDir = self._FvDir\r
460 if 'UPD_TOOL_GUID' not in self._MacroDict:\r
461 self.Error = "UPD_TOOL_GUID definition is missing in DSC file"\r
462 return 1\r
463\r
464 if UpdTxtFile == '':\r
465 UpdTxtFile = os.path.join(FvDir, self._MacroDict['UPD_TOOL_GUID'] + '.txt')\r
466\r
467 ReCreate = False\r
468 if not os.path.exists(UpdTxtFile):\r
469 ReCreate = True\r
470 else:\r
471 DscTime = os.path.getmtime(self._DscFile)\r
472 TxtTime = os.path.getmtime(UpdTxtFile)\r
473 if DscTime > TxtTime:\r
474 ReCreate = True\r
475\r
476 if not ReCreate:\r
477 # DSC has not been modified yet\r
478 # So don't have to re-generate other files\r
479 self.Error = 'No DSC file change, skip to create UPD TXT file'\r
480 return 256\r
481\r
482 TxtFd = open(UpdTxtFile, "w")\r
483 TxtFd.write("%s\n" % (__copyright_txt__ % date.today().year))\r
484\r
485 NextOffset = 0\r
486 SpaceIdx = 0\r
487 if self._MapVer == 1:\r
488 Default = 'DEFAULT|'\r
489 else:\r
490 Default = ''\r
491 for Item in self._CfgItemList:\r
492 if Item['region'] != 'UPD':\r
493 continue\r
494 Offset = Item['offset']\r
495 if NextOffset < Offset:\r
496 # insert one line\r
497 TxtFd.write("%s.UnusedUpdSpace%d|%s0x%04X|0x%04X|{0}\n" % (Item['space'], SpaceIdx, Default, NextOffset, Offset - NextOffset))\r
498 SpaceIdx = SpaceIdx + 1\r
499 NextOffset = Offset + Item['length']\r
500 TxtFd.write("%s.%s|%s0x%04X|%s|%s\n" % (Item['space'],Item['cname'],Default,Item['offset'],Item['length'],Item['value']))\r
501 TxtFd.close()\r
502 return 0\r
503\r
504 def CreateField (self, Name, Length, Offset, Struct):\r
505 PosName = 28\r
506 PosComment = 30\r
507\r
508 IsArray = False\r
509 if Length == 1:\r
510 Type = "UINT8"\r
511 elif Length == 2:\r
512 Type = "UINT16"\r
513 elif Length == 4:\r
514 Type = "UINT32"\r
515 elif Length == 8:\r
516 Type = "UINT64"\r
517 else:\r
518 Type = "UINT8"\r
519 IsArray = True\r
520\r
521 if Struct != '':\r
522 IsArray = False\r
523 Type = Struct\r
524\r
525 if IsArray:\r
526 Name = Name + '[%d]' % Length\r
527\r
528 if len(Type) < PosName:\r
529 Space1 = PosName - len(Type)\r
530 else:\r
531 Space1 = 1\r
532\r
533 if len(Name) < PosComment:\r
534 Space2 = PosComment - len(Name)\r
535 else:\r
536 Space2 = 1\r
537\r
538 return " %s%s%s;%s/* Offset 0x%04X */\n" % (Type, ' ' * Space1, Name, ' ' * Space2, Offset)\r
539\r
540\r
541 def CreateHeaderFile (self, InputHeaderFile, IsInternal):\r
542 Error = 0\r
543 FvDir = self._FvDir\r
544\r
545 if IsInternal:\r
546 HeaderFile = os.path.join(FvDir, 'VpdHeader.h')\r
547 else:\r
548 HeaderFile = os.path.join(FvDir, 'fsp_vpd.h')\r
549\r
550 # Check if header needs to be recreated\r
551 ReCreate = False\r
552 if IsInternal:\r
553 if not os.path.exists(HeaderFile):\r
554 ReCreate = True\r
555 else:\r
556 DscTime = os.path.getmtime(self._DscFile)\r
557 HeadTime = os.path.getmtime(HeaderFile)\r
558 if not os.path.exists(InputHeaderFile):\r
559 InpTime = HeadTime\r
560 else:\r
561 InpTime = os.path.getmtime(InputHeaderFile)\r
562 if DscTime > HeadTime or InpTime > HeadTime:\r
563 ReCreate = True\r
564\r
565 if not ReCreate:\r
566 self.Error = "No DSC or input header file is changed, skip the header file generating"\r
567 return 256\r
568\r
569 HeaderFd = open(HeaderFile, "w")\r
570 FileBase = os.path.basename(HeaderFile)\r
571 FileName = FileBase.replace(".", "_").upper()\r
572 HeaderFd.write("%s\n" % (__copyright_h__ % date.today().year))\r
573 HeaderFd.write("#ifndef __%s__\n" % FileName)\r
574 HeaderFd.write("#define __%s__\n\n" % FileName)\r
575 HeaderFd.write("#pragma pack(1)\n\n")\r
576\r
577 if InputHeaderFile != '':\r
578 if not os.path.exists(InputHeaderFile):\r
579 self.Error = "Input header file '%s' does not exist" % InputHeaderFile\r
580 return 2\r
581\r
582 InFd = open(InputHeaderFile, "r")\r
583 IncLines = InFd.readlines()\r
584 InFd.close()\r
585\r
586 Export = False\r
587 for Line in IncLines:\r
588 Match = re.search ("!EXPORT\s+EXTERNAL_BOOTLOADER_STRUCT_(BEGIN|END)\s+", Line)\r
589 if Match:\r
590 if Match.group(1) == "BEGIN":\r
591 Export = True\r
592 continue\r
593 else:\r
594 Export = False\r
595 continue\r
596 if Export:\r
597 HeaderFd.write(Line)\r
598 HeaderFd.write("\n\n")\r
599\r
600 for Region in ['UPD', 'VPD']:\r
601\r
602 # Write PcdVpdRegionSign and PcdImageRevision\r
603 if Region[0] == 'V':\r
604 if 'VPD_TOOL_GUID' not in self._MacroDict:\r
605 self.Error = "VPD_TOOL_GUID definition is missing in DSC file"\r
606 Error = 1\r
607 break\r
608\r
609 BinFile = os.path.join(FvDir, self._MacroDict['VPD_TOOL_GUID'] + ".bin")\r
610 if not os.path.exists(BinFile):\r
611 self.Error = "VPD binary file '%s' does not exist" % BinFile\r
612 Error = 2\r
613 break\r
614\r
615 BinFd = open(BinFile, "rb")\r
616 IdStr = BinFd.read(0x08)\r
617 ImageId = struct.unpack('Q', IdStr)\r
59c30d74 618 ImageRev = struct.unpack('I', BinFd.read(0x04))\r
c8ec22a2
JY
619 BinFd.close()\r
620\r
621 HeaderFd.write("#define VPD_IMAGE_ID 0x%016X /* '%s' */\n" % (ImageId[0], IdStr))\r
622 HeaderFd.write("#define VPD_IMAGE_REV 0x%08X \n\n" % ImageRev[0])\r
623\r
624 HeaderFd.write("typedef struct _" + Region[0] + "PD_DATA_REGION {\n")\r
625 NextOffset = 0\r
626 SpaceIdx = 0\r
627 Offset = 0\r
628\r
629 LastVisible = True\r
630 ResvOffset = 0\r
631 ResvIdx = 0\r
632 LineBuffer = []\r
633 for Item in self._CfgItemList:\r
634 if Item['region'] != Region:\r
635 continue\r
636\r
637 NextVisible = LastVisible\r
638 if not IsInternal:\r
639 if LastVisible and (Item['header'] == 'OFF'):\r
640 NextVisible = False\r
641 ResvOffset = Item['offset']\r
642 elif (not LastVisible) and Item['header'] == 'ON':\r
643 NextVisible = True\r
644 Name = "Reserved" + Region[0] + "pdSpace%d" % ResvIdx\r
645 ResvIdx = ResvIdx + 1\r
646 HeaderFd.write(self.CreateField (Name, Item["offset"] - ResvOffset, ResvOffset, ''))\r
647\r
648 if Offset < Item["offset"]:\r
649 if IsInternal or LastVisible:\r
650 Name = "Unused" + Region[0] + "pdSpace%d" % SpaceIdx\r
651 LineBuffer.append(self.CreateField (Name, Item["offset"] - Offset, Offset, ''))\r
652 SpaceIdx = SpaceIdx + 1\r
653 Offset = Item["offset"]\r
654\r
655 if Offset != Item["offset"]:\r
656 print "Unsorted offset 0x%04X\n" % Item["offset"]\r
657 error = 2\r
658 break;\r
659\r
660 LastVisible = NextVisible\r
661\r
662 Offset = Offset + Item["length"]\r
663 if IsInternal or LastVisible:\r
664 for Each in LineBuffer:\r
665 HeaderFd.write (Each)\r
666 LineBuffer = []\r
667 HeaderFd.write(self.CreateField (Item["cname"], Item["length"], Item["offset"], Item['struct']))\r
668\r
669 HeaderFd.write("} " + Region[0] + "PD_DATA_REGION;\n\n")\r
670 HeaderFd.write("#pragma pack()\n\n")\r
671 HeaderFd.write("#endif\n")\r
672 HeaderFd.close()\r
673\r
674 return Error\r
675\r
676 def WriteBsfStruct (self, BsfFd, Item):\r
677 if Item['type'] == "None":\r
678 Space = "gPlatformFspPkgTokenSpaceGuid"\r
679 else:\r
680 Space = Item['space']\r
681 Line = " $%s_%s" % (Space, Item['cname'])\r
682 Match = re.match("\s*\{([x0-9a-fA-F,\s]+)\}\s*", Item['value'])\r
683 if Match:\r
684 DefaultValue = Match.group(1).strip()\r
685 else:\r
686 DefaultValue = Item['value'].strip()\r
687 BsfFd.write(" %s%s%4d bytes $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['length'], DefaultValue))\r
688 TmpList = []\r
689 if Item['type'] == "Combo":\r
690 if not Item['option'] in self._BuidinOption:\r
691 OptList = Item['option'].split(',')\r
692 for Option in OptList:\r
693 Option = Option.strip()\r
694 (OpVal, OpStr) = Option.split(':')\r
695 TmpList.append((OpVal, OpStr))\r
696 return TmpList\r
697\r
698 def WriteBsfOption (self, BsfFd, Item):\r
699 PcdName = Item['space'] + '_' + Item['cname']\r
700 WriteHelp = 0\r
701 if Item['type'] == "Combo":\r
702 if Item['option'] in self._BuidinOption:\r
703 Options = self._BuidinOption[Item['option']]\r
704 else:\r
705 Options = PcdName\r
706 BsfFd.write(' %s $%s, "%s", &%s,\n' % (Item['type'], PcdName, Item['name'], Options));\r
707 WriteHelp = 1\r
708 elif Item['type'].startswith("EditNum"):\r
709 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
710 if Match:\r
711 BsfFd.write(' EditNum $%s, "%s", %s,\n' % (PcdName, Item['name'], Match.group(1)));\r
712 WriteHelp = 2\r
713 elif Item['type'].startswith("EditText"):\r
714 BsfFd.write(' %s $%s, "%s",\n' % (Item['type'], PcdName, Item['name']));\r
715 WriteHelp = 1\r
716\r
717 if WriteHelp > 0:\r
718 HelpLines = Item['help'].split('\\n\\r')\r
719 FirstLine = True\r
720 for HelpLine in HelpLines:\r
721 if FirstLine:\r
722 FirstLine = False\r
723 BsfFd.write(' Help "%s"\n' % (HelpLine));\r
724 else:\r
725 BsfFd.write(' "%s"\n' % (HelpLine));\r
726 if WriteHelp == 2:\r
727 BsfFd.write(' "Valid range: %s ~ %s"\n' % (Match.group(2), Match.group(3)));\r
728\r
729 def GenerateBsfFile (self, BsfFile):\r
730\r
731 if BsfFile == '':\r
732 self.Error = "BSF output file '%s' is invalid" % BsfFile\r
733 return 1\r
734\r
735 Error = 0\r
736 OptionDict = {}\r
737 BsfFd = open(BsfFile, "w")\r
738 BsfFd.write("%s\n" % (__copyright_bsf__ % date.today().year))\r
739 BsfFd.write("%s\n" % self._GlobalDataDef);\r
740 BsfFd.write("StructDef\n")\r
741 NextOffset = -1\r
742 for Item in self._CfgItemList:\r
743 if Item['find'] != '':\r
744 BsfFd.write('\n Find "%s"\n' % Item['find'])\r
745 NextOffset = Item['offset'] + Item['length']\r
746 if Item['name'] != '':\r
747 if NextOffset != Item['offset']:\r
748 BsfFd.write(" Skip %d bytes\n" % (Item['offset'] - NextOffset))\r
749 if len(Item['subreg']) > 0:\r
750 NextOffset = Item['offset']\r
751 for SubItem in Item['subreg']:\r
752 NextOffset += SubItem['length']\r
753 if SubItem['name'] == '':\r
754 BsfFd.write(" Skip %d bytes\n" % (SubItem['length']))\r
755 else:\r
756 Options = self.WriteBsfStruct(BsfFd, SubItem)\r
757 if len(Options) > 0:\r
758 OptionDict[SubItem['space']+'_'+SubItem['cname']] = Options\r
759 if (Item['offset'] + Item['length']) < NextOffset:\r
760 self.Error = "BSF sub region '%s' length does not match" % (Item['space']+'.'+Item['cname'])\r
761 return 2\r
762 else:\r
763 NextOffset = Item['offset'] + Item['length']\r
764 Options = self.WriteBsfStruct(BsfFd, Item)\r
765 if len(Options) > 0:\r
766 OptionDict[Item['space']+'_'+Item['cname']] = Options\r
767 BsfFd.write("\nEndStruct\n\n")\r
768\r
769 BsfFd.write("%s" % self._BuidinOptionTxt);\r
770\r
771 for Each in OptionDict:\r
772 BsfFd.write("List &%s\n" % Each);\r
773 for Item in OptionDict[Each]:\r
774 BsfFd.write(' Selection %s , "%s"\n' % (Item[0], Item[1]));\r
775 BsfFd.write("EndList\n\n");\r
776\r
777 BsfFd.write("BeginInfoBlock\n");\r
778 BsfFd.write(' PPVer "%s"\n' % (self._CfgBlkDict['ver']));\r
779 BsfFd.write(' Description "%s"\n' % (self._CfgBlkDict['name']));\r
780 BsfFd.write("EndInfoBlock\n\n");\r
781\r
782 for Each in self._CfgPageDict:\r
783 BsfFd.write('Page "%s"\n' % self._CfgPageDict[Each]);\r
784 BsfItems = []\r
785 for Item in self._CfgItemList:\r
786 if Item['name'] != '':\r
787 if Item['page'] != Each:\r
788 continue\r
789 if len(Item['subreg']) > 0:\r
790 for SubItem in Item['subreg']:\r
791 if SubItem['name'] != '':\r
792 BsfItems.append(SubItem)\r
793 else:\r
794 BsfItems.append(Item)\r
795\r
796 BsfItems.sort(key=lambda x: x['order'])\r
797\r
798 for Item in BsfItems:\r
799 self.WriteBsfOption (BsfFd, Item)\r
800 BsfFd.write("EndPage\n\n");\r
801\r
802 BsfFd.close()\r
803 return Error\r
804\r
805\r
806def Usage():\r
807 print "GenCfgOpt Version 0.50"\r
808 print "Usage:"\r
809 print " GenCfgOpt UPDTXT PlatformDscFile BuildFvDir [TxtOutFile] [-D Macros]"\r
810 print " GenCfgOpt HEADER PlatformDscFile BuildFvDir [InputHFile] [-D Macros]"\r
811 print " GenCfgOpt GENBSF PlatformDscFile BuildFvDir BsfOutFile [-D Macros]"\r
812\r
813def Main():\r
814 #\r
815 # Parse the options and args\r
816 #\r
817 GenCfgOpt = CGenCfgOpt()\r
818 argc = len(sys.argv)\r
819 if argc < 4:\r
820 Usage()\r
821 return 1\r
822 else:\r
823 DscFile = sys.argv[2]\r
824 if not os.path.exists(DscFile):\r
825 print "ERROR: Cannot open DSC file '%s' !" % DscFile\r
826 return 2\r
827\r
828 OutFile = ''\r
829 if argc > 4:\r
830 if sys.argv[4][0] == '-':\r
831 Start = 4\r
832 else:\r
833 OutFile = sys.argv[4]\r
834 Start = 5\r
835 if GenCfgOpt.ParseMacros(sys.argv[Start:]) != 0:\r
836 print "ERROR: %s !" % GenCfgOpt.Error\r
837 return 3\r
838\r
839 FvDir = sys.argv[3]\r
840 if not os.path.isdir(FvDir):\r
841 print "ERROR: FV folder '%s' is invalid !" % FvDir\r
842 return 4\r
843\r
844 if GenCfgOpt.ParseDscFile(DscFile, FvDir) != 0:\r
845 print "ERROR: %s !" % GenCfgOpt.Error\r
846 return 5\r
847\r
848\r
849 if GenCfgOpt.UpdateVpdSizeField() != 0:\r
850 print "ERROR: %s !" % GenCfgOpt.Error\r
851 return 6\r
852\r
853 if GenCfgOpt.UpdateSubRegionDefaultValue() != 0:\r
854 print "ERROR: %s !" % GenCfgOpt.Error\r
855 return 7\r
856\r
857 if sys.argv[1] == "UPDTXT":\r
858 Ret = GenCfgOpt.CreateUpdTxtFile(OutFile)\r
859 if Ret != 0:\r
860 # No change is detected\r
861 if Ret == 256:\r
862 print "INFO: %s !" % (GenCfgOpt.Error)\r
863 else :\r
864 print "ERROR: %s !" % (GenCfgOpt.Error)\r
865 return Ret\r
866 elif sys.argv[1] == "HEADER":\r
867 Ret = GenCfgOpt.CreateHeaderFile(OutFile, True)\r
868 if Ret != 0:\r
869 # No change is detected\r
870 if Ret == 256:\r
871 print "INFO: %s !" % (GenCfgOpt.Error)\r
872 else :\r
873 print "ERROR: %s !" % (GenCfgOpt.Error)\r
874 return Ret\r
875 if GenCfgOpt.CreateHeaderFile(OutFile, False) != 0:\r
876 print "ERROR: %s !" % GenCfgOpt.Error\r
877 return 8\r
878 elif sys.argv[1] == "GENBSF":\r
879 if GenCfgOpt.GenerateBsfFile(OutFile) != 0:\r
880 print "ERROR: %s !" % GenCfgOpt.Error\r
881 return 9\r
882 else:\r
883 if argc < 5:\r
884 Usage()\r
885 return 1\r
886 print "ERROR: Unknown command '%s' !" % sys.argv[1]\r
887 Usage()\r
888 return 1\r
889 return 0\r
890 return 0\r
891\r
892\r
893if __name__ == '__main__':\r
894 sys.exit(Main())\r