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