1## @file 2# This file is used to define each component of DEC file 3# 4# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR> 5# This program and the accompanying materials 6# are licensed and made available under the terms and conditions of the BSD License 7# which accompanies this distribution. The full text of the license may be found at 8# http://opensource.org/licenses/bsd-license.php 9# 10# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12# 13 14## 15# Import Modules 16# 17import Common.LongFilePathOs as os 18from String import * 19from DataType import * 20from Identification import * 21from Dictionary import * 22from CommonDataClass.PackageClass import * 23from CommonDataClass.CommonClass import PcdClass 24from BuildToolError import * 25from Table.TableDec import TableDec 26import Database 27from Parsing import * 28import GlobalData 29from Common.LongFilePathSupport import OpenLongFilePath as open 30 31# 32# Global variable 33# 34Section = {TAB_UNKNOWN.upper() : MODEL_UNKNOWN, 35 TAB_DEC_DEFINES.upper() : MODEL_META_DATA_HEADER, 36 TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE, 37 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS, 38 TAB_COMPONENTS.upper() : MODEL_META_DATA_COMPONENT, 39 TAB_GUIDS.upper() : MODEL_EFI_GUID, 40 TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL, 41 TAB_PPIS.upper() : MODEL_EFI_PPI, 42 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD, 43 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE, 44 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG, 45 TAB_PCDS_DYNAMIC_EX_NULL.upper() : MODEL_PCD_DYNAMIC_EX, 46 TAB_PCDS_DYNAMIC_NULL.upper() : MODEL_PCD_DYNAMIC, 47 TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION 48 } 49 50 51## DecObject 52# 53# This class defined basic Dec object which is used by inheriting 54# 55# @param object: Inherited from object class 56# 57class DecObject(object): 58 def __init__(self): 59 object.__init__() 60 61## Dec 62# 63# This class defined the structure used in Dec object 64# 65# @param DecObject: Inherited from DecObject class 66# @param Filename: Input value for Filename of Dec file, default is None 67# @param IsMergeAllArches: Input value for IsMergeAllArches 68# True is to merge all arches 69# Fales is not to merge all arches 70# default is False 71# @param IsToPackage: Input value for IsToPackage 72# True is to transfer to PackageObject automatically 73# False is not to transfer to PackageObject automatically 74# default is False 75# @param WorkspaceDir: Input value for current workspace directory, default is None 76# 77# @var Identification: To store value for Identification, it is a structure as Identification 78# @var Defines: To store value for Defines, it is a structure as DecDefines 79# @var UserExtensions: To store value for UserExtensions 80# @var Package: To store value for Package, it is a structure as PackageClass 81# @var WorkspaceDir: To store value for WorkspaceDir 82# @var Contents: To store value for Contents, it is a structure as DecContents 83# @var KeyList: To store value for KeyList, a list for all Keys used in Dec 84# 85class Dec(DecObject): 86 def __init__(self, Filename=None, IsToDatabase=False, IsToPackage=False, WorkspaceDir=None, Database=None, SupArchList=DataType.ARCH_LIST): 87 self.Identification = Identification() 88 self.Package = PackageClass() 89 self.UserExtensions = '' 90 self.WorkspaceDir = WorkspaceDir 91 self.SupArchList = SupArchList 92 self.IsToDatabase = IsToDatabase 93 94 self.Cur = Database.Cur 95 self.TblFile = Database.TblFile 96 self.TblDec = Database.TblDec 97 self.FileID = -1 98 99 self.KeyList = [ 100 TAB_INCLUDES, TAB_GUIDS, TAB_PROTOCOLS, TAB_PPIS, TAB_LIBRARY_CLASSES, \ 101 TAB_PCDS_FIXED_AT_BUILD_NULL, TAB_PCDS_PATCHABLE_IN_MODULE_NULL, TAB_PCDS_FEATURE_FLAG_NULL, \ 102 TAB_PCDS_DYNAMIC_NULL, TAB_PCDS_DYNAMIC_EX_NULL, TAB_DEC_DEFINES 103 ] 104 # 105 # Upper all KEYs to ignore case sensitive when parsing 106 # 107 self.KeyList = map(lambda c: c.upper(), self.KeyList) 108 109 # 110 # Init RecordSet 111 # 112 self.RecordSet = {} 113 for Key in self.KeyList: 114 self.RecordSet[Section[Key]] = [] 115 116 # 117 # Load Dec file if filename is not None 118 # 119 if Filename != None: 120 self.LoadDecFile(Filename) 121 122 # 123 # Transfer to Package Object if IsToPackage is True 124 # 125 if IsToPackage: 126 self.DecToPackage() 127 128 ## Load Dec file 129 # 130 # Load the file if it exists 131 # 132 # @param Filename: Input value for filename of Dec file 133 # 134 def LoadDecFile(self, Filename): 135 # 136 # Insert a record for file 137 # 138 Filename = NormPath(Filename) 139 self.Identification.FileFullPath = Filename 140 (self.Identification.FileRelativePath, self.Identification.FileName) = os.path.split(Filename) 141 self.FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_DEC) 142 143 # 144 # Init DecTable 145 # 146 #self.TblDec.Table = "Dec%s" % self.FileID 147 #self.TblDec.Create() 148 149 # 150 # Init common datas 151 # 152 IfDefList, SectionItemList, CurrentSection, ArchList, ThirdList, IncludeFiles = \ 153 [], [], TAB_UNKNOWN, [], [], [] 154 LineNo = 0 155 156 # 157 # Parse file content 158 # 159 IsFindBlockComment = False 160 ReservedLine = '' 161 for Line in open(Filename, 'r'): 162 LineNo = LineNo + 1 163 # 164 # Remove comment block 165 # 166 if Line.find(TAB_COMMENT_EDK_START) > -1: 167 ReservedLine = GetSplitList(Line, TAB_COMMENT_EDK_START, 1)[0] 168 IsFindBlockComment = True 169 if Line.find(TAB_COMMENT_EDK_END) > -1: 170 Line = ReservedLine + GetSplitList(Line, TAB_COMMENT_EDK_END, 1)[1] 171 ReservedLine = '' 172 IsFindBlockComment = False 173 if IsFindBlockComment: 174 continue 175 176 # 177 # Remove comments at tail and remove spaces again 178 # 179 Line = CleanString(Line) 180 if Line == '': 181 continue 182 183 # 184 # Find a new section tab 185 # First insert previous section items 186 # And then parse the content of the new section 187 # 188 if Line.startswith(TAB_SECTION_START) and Line.endswith(TAB_SECTION_END): 189 # 190 # Insert items data of previous section 191 # 192 Model = Section[CurrentSection.upper()] 193 InsertSectionItemsIntoDatabase(self.TblDec, self.FileID, Filename, Model, CurrentSection, SectionItemList, ArchList, ThirdList, IfDefList, self.RecordSet) 194 195 # 196 # Parse the new section 197 # 198 SectionItemList = [] 199 ArchList = [] 200 ThirdList = [] 201 202 CurrentSection = '' 203 LineList = GetSplitValueList(Line[len(TAB_SECTION_START):len(Line) - len(TAB_SECTION_END)], TAB_COMMA_SPLIT) 204 for Item in LineList: 205 ItemList = GetSplitValueList(Item, TAB_SPLIT) 206 if CurrentSection == '': 207 CurrentSection = ItemList[0] 208 else: 209 if CurrentSection != ItemList[0]: 210 EdkLogger.error("Parser", PARSER_ERROR, "Different section names '%s' and '%s' are found in one section definition, this is not allowed." % (CurrentSection, ItemList[0]), File=Filename, Line=LineNo, RaiseError=EdkLogger.IsRaiseError) 211 if CurrentSection.upper() not in self.KeyList: 212 RaiseParserError(Line, CurrentSection, Filename, '', LineNo) 213 ItemList.append('') 214 ItemList.append('') 215 if len(ItemList) > 5: 216 RaiseParserError(Line, CurrentSection, Filename, '', LineNo) 217 else: 218 if ItemList[1] != '' and ItemList[1].upper() not in ARCH_LIST_FULL: 219 EdkLogger.error("Parser", PARSER_ERROR, "Invalid Arch definition '%s' found" % ItemList[1], File=Filename, Line=LineNo, RaiseError=EdkLogger.IsRaiseError) 220 ArchList.append(ItemList[1].upper()) 221 ThirdList.append(ItemList[2]) 222 223 continue 224 225 # 226 # Not in any defined section 227 # 228 if CurrentSection == TAB_UNKNOWN: 229 ErrorMsg = "%s is not in any defined section" % Line 230 EdkLogger.error("Parser", PARSER_ERROR, ErrorMsg, File=Filename, Line=LineNo, RaiseError=EdkLogger.IsRaiseError) 231 232 # 233 # Add a section item 234 # 235 SectionItemList.append([Line, LineNo]) 236 # End of parse 237 #End of For 238 239 # 240 # Insert items data of last section 241 # 242 Model = Section[CurrentSection.upper()] 243 InsertSectionItemsIntoDatabase(self.TblDec, self.FileID, Filename, Model, CurrentSection, SectionItemList, ArchList, ThirdList, IfDefList, self.RecordSet) 244 245 # 246 # Replace all DEFINE macros with its actual values 247 # 248 ParseDefineMacro2(self.TblDec, self.RecordSet, GlobalData.gGlobalDefines) 249 250 ## Transfer to Package Object 251 # 252 # Transfer all contents of a Dec file to a standard Package Object 253 # 254 def DecToPackage(self): 255 # 256 # Init global information for the file 257 # 258 ContainerFile = self.Identification.FileFullPath 259 260 # 261 # Generate Package Header 262 # 263 self.GenPackageHeader(ContainerFile) 264 265 # 266 # Generate Includes 267 # 268 self.GenIncludes(ContainerFile) 269 270 # 271 # Generate Guids 272 # 273 self.GenGuidProtocolPpis(DataType.TAB_GUIDS, ContainerFile) 274 275 # 276 # Generate Protocols 277 # 278 self.GenGuidProtocolPpis(DataType.TAB_PROTOCOLS, ContainerFile) 279 280 # 281 # Generate Ppis 282 # 283 self.GenGuidProtocolPpis(DataType.TAB_PPIS, ContainerFile) 284 285 # 286 # Generate LibraryClasses 287 # 288 self.GenLibraryClasses(ContainerFile) 289 290 # 291 # Generate Pcds 292 # 293 self.GenPcds(ContainerFile) 294 295 ## Get Package Header 296 # 297 # Gen Package Header of Dec as <Key> = <Value> 298 # 299 # @param ContainerFile: The Dec file full path 300 # 301 def GenPackageHeader(self, ContainerFile): 302 EdkLogger.debug(2, "Generate PackageHeader ...") 303 # 304 # Update all defines item in database 305 # 306 RecordSet = self.RecordSet[MODEL_META_DATA_HEADER] 307 for Record in RecordSet: 308 ValueList = GetSplitValueList(Record[0], TAB_EQUAL_SPLIT) 309 if len(ValueList) != 2: 310 RaiseParserError(Record[0], 'Defines', ContainerFile, '<Key> = <Value>', Record[2]) 311 ID, Value1, Value2, Arch, LineNo = Record[3], ValueList[0], ValueList[1], Record[1], Record[2] 312 SqlCommand = """update %s set Value1 = '%s', Value2 = '%s' 313 where ID = %s""" % (self.TblDec.Table, ConvertToSqlString2(Value1), ConvertToSqlString2(Value2), ID) 314 self.TblDec.Exec(SqlCommand) 315 316 # 317 # Get detailed information 318 # 319 for Arch in self.SupArchList: 320 PackageHeader = PackageHeaderClass() 321 322 PackageHeader.Name = QueryDefinesItem(self.TblDec, TAB_DEC_DEFINES_PACKAGE_NAME, Arch, self.FileID)[0] 323 PackageHeader.Guid = QueryDefinesItem(self.TblDec, TAB_DEC_DEFINES_PACKAGE_GUID, Arch, self.FileID)[0] 324 PackageHeader.Version = QueryDefinesItem(self.TblDec, TAB_DEC_DEFINES_PACKAGE_VERSION, Arch, self.FileID)[0] 325 PackageHeader.FileName = self.Identification.FileName 326 PackageHeader.FullPath = self.Identification.FileFullPath 327 PackageHeader.DecSpecification = QueryDefinesItem(self.TblDec, TAB_DEC_DEFINES_DEC_SPECIFICATION, Arch, self.FileID)[0] 328 329 self.Package.Header[Arch] = PackageHeader 330 331 ## GenIncludes 332 # 333 # Gen Includes of Dec 334 # 335 # 336 # @param ContainerFile: The Dec file full path 337 # 338 def GenIncludes(self, ContainerFile): 339 EdkLogger.debug(2, "Generate %s ..." % TAB_INCLUDES) 340 Includes = {} 341 # 342 # Get all Includes 343 # 344 RecordSet = self.RecordSet[MODEL_EFI_INCLUDE] 345 346 # 347 # Go through each arch 348 # 349 for Arch in self.SupArchList: 350 for Record in RecordSet: 351 if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: 352 MergeArches(Includes, Record[0], Arch) 353 354 for Key in Includes.keys(): 355 Include = IncludeClass() 356 Include.FilePath = NormPath(Key) 357 Include.SupArchList = Includes[Key] 358 self.Package.Includes.append(Include) 359 360 ## GenPpis 361 # 362 # Gen Ppis of Dec 363 # <CName>=<GuidValue> 364 # 365 # @param ContainerFile: The Dec file full path 366 # 367 def GenGuidProtocolPpis(self, Type, ContainerFile): 368 EdkLogger.debug(2, "Generate %s ..." % Type) 369 Lists = {} 370 # 371 # Get all Items 372 # 373 RecordSet = self.RecordSet[Section[Type.upper()]] 374 375 # 376 # Go through each arch 377 # 378 for Arch in self.SupArchList: 379 for Record in RecordSet: 380 if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: 381 (Name, Value) = GetGuidsProtocolsPpisOfDec(Record[0], Type, ContainerFile, Record[2]) 382 MergeArches(Lists, (Name, Value), Arch) 383 if self.IsToDatabase: 384 SqlCommand = """update %s set Value1 = '%s', Value2 = '%s' 385 where ID = %s""" % (self.TblDec.Table, ConvertToSqlString2(Name), ConvertToSqlString2(Value), Record[3]) 386 self.TblDec.Exec(SqlCommand) 387 388 ListMember = None 389 if Type == TAB_GUIDS: 390 ListMember = self.Package.GuidDeclarations 391 elif Type == TAB_PROTOCOLS: 392 ListMember = self.Package.ProtocolDeclarations 393 elif Type == TAB_PPIS: 394 ListMember = self.Package.PpiDeclarations 395 396 for Key in Lists.keys(): 397 ListClass = GuidProtocolPpiCommonClass() 398 ListClass.CName = Key[0] 399 ListClass.Guid = Key[1] 400 ListClass.SupArchList = Lists[Key] 401 ListMember.append(ListClass) 402 403 404 ## GenLibraryClasses 405 # 406 # Gen LibraryClasses of Dec 407 # <CName>=<GuidValue> 408 # 409 # @param ContainerFile: The Dec file full path 410 # 411 def GenLibraryClasses(self, ContainerFile): 412 EdkLogger.debug(2, "Generate %s ..." % TAB_LIBRARY_CLASSES) 413 LibraryClasses = {} 414 # 415 # Get all Guids 416 # 417 RecordSet = self.RecordSet[MODEL_EFI_LIBRARY_CLASS] 418 419 # 420 # Go through each arch 421 # 422 for Arch in self.SupArchList: 423 for Record in RecordSet: 424 if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: 425 List = GetSplitValueList(Record[0], DataType.TAB_VALUE_SPLIT) 426 if len(List) != 2: 427 RaiseParserError(Record[0], 'LibraryClasses', ContainerFile, '<LibraryClassName>|<LibraryClassInstanceFilename>', Record[2]) 428 else: 429 CheckFileExist(self.Identification.FileRelativePath, List[1], ContainerFile, 'LibraryClasses', Record[0]) 430 MergeArches(LibraryClasses, (List[0], List[1]), Arch) 431 if self.IsToDatabase: 432 SqlCommand = """update %s set Value1 = '%s', Value2 = '%s', Value3 = '%s' 433 where ID = %s""" % (self.TblDec.Table, ConvertToSqlString2(List[0]), ConvertToSqlString2(List[1]), SUP_MODULE_LIST_STRING, Record[3]) 434 self.TblDec.Exec(SqlCommand) 435 436 437 for Key in LibraryClasses.keys(): 438 LibraryClass = LibraryClassClass() 439 LibraryClass.LibraryClass = Key[0] 440 LibraryClass.RecommendedInstance = NormPath(Key[1]) 441 LibraryClass.SupModuleList = SUP_MODULE_LIST 442 LibraryClass.SupArchList = LibraryClasses[Key] 443 self.Package.LibraryClassDeclarations.append(LibraryClass) 444 445 ## GenPcds 446 # 447 # Gen Pcds of Dec 448 # <TokenSpcCName>.<TokenCName>|<Value>|<DatumType>|<Token> 449 # 450 # @param ContainerFile: The Dec file full path 451 # 452 def GenPcds(self, ContainerFile): 453 EdkLogger.debug(2, "Generate %s ..." % TAB_PCDS) 454 Pcds = {} 455 PcdToken = {} 456 # 457 # Get all Guids 458 # 459 RecordSet1 = self.RecordSet[MODEL_PCD_FIXED_AT_BUILD] 460 RecordSet2 = self.RecordSet[MODEL_PCD_PATCHABLE_IN_MODULE] 461 RecordSet3 = self.RecordSet[MODEL_PCD_FEATURE_FLAG] 462 RecordSet4 = self.RecordSet[MODEL_PCD_DYNAMIC_EX] 463 RecordSet5 = self.RecordSet[MODEL_PCD_DYNAMIC] 464 465 # 466 # Go through each arch 467 # 468 for Arch in self.SupArchList: 469 for Record in RecordSet1: 470 if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: 471 (TokenGuidCName, TokenName, Value, DatumType, Token, Type) = GetPcdOfDec(Record[0], TAB_PCDS_FIXED_AT_BUILD, ContainerFile, Record[2]) 472 MergeArches(Pcds, (TokenGuidCName, TokenName, Value, DatumType, Token, Type), Arch) 473 PcdToken[Record[3]] = (TokenGuidCName, TokenName) 474 for Record in RecordSet2: 475 if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: 476 (TokenGuidCName, TokenName, Value, DatumType, Token, Type) = GetPcdOfDec(Record[0], TAB_PCDS_PATCHABLE_IN_MODULE, ContainerFile, Record[2]) 477 MergeArches(Pcds, (TokenGuidCName, TokenName, Value, DatumType, Token, Type), Arch) 478 PcdToken[Record[3]] = (TokenGuidCName, TokenName) 479 for Record in RecordSet3: 480 if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: 481 (TokenGuidCName, TokenName, Value, DatumType, Token, Type) = GetPcdOfDec(Record[0], TAB_PCDS_FEATURE_FLAG, ContainerFile, Record[2]) 482 MergeArches(Pcds, (TokenGuidCName, TokenName, Value, DatumType, Token, Type), Arch) 483 PcdToken[Record[3]] = (TokenGuidCName, TokenName) 484 for Record in RecordSet4: 485 if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: 486 (TokenGuidCName, TokenName, Value, DatumType, Token, Type) = GetPcdOfDec(Record[0], TAB_PCDS_DYNAMIC_EX, ContainerFile, Record[2]) 487 MergeArches(Pcds, (TokenGuidCName, TokenName, Value, DatumType, Token, Type), Arch) 488 PcdToken[Record[3]] = (TokenGuidCName, TokenName) 489 for Record in RecordSet5: 490 if Record[1] == Arch or Record[1] == TAB_ARCH_COMMON: 491 (TokenGuidCName, TokenName, Value, DatumType, Token, Type) = GetPcdOfDec(Record[0], TAB_PCDS_DYNAMIC, ContainerFile, Record[2]) 492 MergeArches(Pcds, (TokenGuidCName, TokenName, Value, DatumType, Token, Type), Arch) 493 PcdToken[Record[3]] = (TokenGuidCName, TokenName) 494 # 495 # Update to database 496 # 497 if self.IsToDatabase: 498 for Key in PcdToken.keys(): 499 SqlCommand = """update %s set Value2 = '%s' where ID = %s""" % (self.TblDec.Table, ".".join((PcdToken[Key][0], PcdToken[Key][1])), Key) 500 self.TblDec.Exec(SqlCommand) 501 502 for Key in Pcds.keys(): 503 Pcd = PcdClass() 504 Pcd.CName = Key[1] 505 Pcd.Token = Key[4] 506 Pcd.TokenSpaceGuidCName = Key[0] 507 Pcd.DatumType = Key[3] 508 Pcd.DefaultValue = Key[2] 509 Pcd.ItemType = Key[5] 510 Pcd.SupArchList = Pcds[Key] 511 self.Package.PcdDeclarations.append(Pcd) 512 513 ## Show detailed information of Package 514 # 515 # Print all members and their values of Package class 516 # 517 def ShowPackage(self): 518 M = self.Package 519 for Arch in M.Header.keys(): 520 print '\nArch =', Arch 521 print 'Filename =', M.Header[Arch].FileName 522 print 'FullPath =', M.Header[Arch].FullPath 523 print 'BaseName =', M.Header[Arch].Name 524 print 'Guid =', M.Header[Arch].Guid 525 print 'Version =', M.Header[Arch].Version 526 print 'DecSpecification =', M.Header[Arch].DecSpecification 527 print '\nIncludes =', M.Includes 528 for Item in M.Includes: 529 print Item.FilePath, Item.SupArchList 530 print '\nGuids =', M.GuidDeclarations 531 for Item in M.GuidDeclarations: 532 print Item.CName, Item.Guid, Item.SupArchList 533 print '\nProtocols =', M.ProtocolDeclarations 534 for Item in M.ProtocolDeclarations: 535 print Item.CName, Item.Guid, Item.SupArchList 536 print '\nPpis =', M.PpiDeclarations 537 for Item in M.PpiDeclarations: 538 print Item.CName, Item.Guid, Item.SupArchList 539 print '\nLibraryClasses =', M.LibraryClassDeclarations 540 for Item in M.LibraryClassDeclarations: 541 print Item.LibraryClass, Item.RecommendedInstance, Item.SupModuleList, Item.SupArchList 542 print '\nPcds =', M.PcdDeclarations 543 for Item in M.PcdDeclarations: 544 print 'CName=', Item.CName, 'TokenSpaceGuidCName=', Item.TokenSpaceGuidCName, 'DefaultValue=', Item.DefaultValue, 'ItemType=', Item.ItemType, 'Token=', Item.Token, 'DatumType=', Item.DatumType, Item.SupArchList 545 546## 547# 548# This acts like the main() function for the script, unless it is 'import'ed into another 549# script. 550# 551if __name__ == '__main__': 552 EdkLogger.Initialize() 553 EdkLogger.SetLevel(EdkLogger.DEBUG_0) 554 555 W = os.getenv('WORKSPACE') 556 F = os.path.join(W, 'Nt32Pkg/Nt32Pkg.dec') 557 558 Db = Database.Database('Dec.db') 559 Db.InitDatabase() 560 561 P = Dec(os.path.normpath(F), True, True, W, Db) 562 P.ShowPackage() 563 564 Db.Close() 565