1## @file 2# Contains several utilitities shared by migration tools. 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 18import re 19import EdkLogger 20from optparse import OptionParser 21from Common.BuildToolError import * 22from XmlRoutines import * 23from CommonDataClass.CommonClass import * 24from Common.LongFilePathSupport import OpenLongFilePath as open 25 26## Set all fields of CommonClass object. 27# 28# Set all attributes of CommonClass object from XML Dom object of XmlCommon. 29# 30# @param Common The destine CommonClass object. 31# @param XmlCommon The source XML Dom object. 32# 33def SetCommon(Common, XmlCommon): 34 XmlTag = "Usage" 35 Common.Usage = XmlAttribute(XmlCommon, XmlTag).split() 36 37 XmlTag = "FeatureFlag" 38 Common.FeatureFlag = XmlAttribute(XmlCommon, XmlTag) 39 40 XmlTag = "SupArchList" 41 Common.SupArchList = XmlAttribute(XmlCommon, XmlTag).split() 42 43 XmlTag = XmlNodeName(XmlCommon) + "/" + "HelpText" 44 Common.HelpText = XmlElement(XmlCommon, XmlTag) 45 46 47## Set some fields of CommonHeaderClass object. 48# 49# Set Name, Guid, FileName and FullPath fields of CommonHeaderClass object from 50# XML Dom object of XmlCommonHeader, NameTag and FileName. 51# 52# @param CommonHeader The destine CommonClass object. 53# @param XmlCommonHeader The source XML Dom object. 54# @param NameTag The name tag in XML Dom object. 55# @param FileName The file name of the XML file. 56# 57def SetIdentification(CommonHeader, XmlCommonHeader, NameTag, FileName): 58 XmlParentTag = XmlNodeName(XmlCommonHeader) 59 60 XmlTag = XmlParentTag + "/" + NameTag 61 CommonHeader.Name = XmlElement(XmlCommonHeader, XmlTag) 62 63 XmlTag = XmlParentTag + "/" + "GuidValue" 64 CommonHeader.Guid = XmlElement(XmlCommonHeader, XmlTag) 65 66 XmlTag = XmlParentTag + "/" + "Version" 67 CommonHeader.Version = XmlElement(XmlCommonHeader, XmlTag) 68 69 CommonHeader.FileName = os.path.basename(FileName) 70 CommonHeader.FullPath = os.path.abspath(FileName) 71 72 73## Regular expression to match specification and value. 74mReSpecification = re.compile(r"(?P<Specification>\w+)\s+(?P<Value>\w*)") 75 76## Add specification to specification dictionary. 77# 78# Abstract specification name, value pair from Specification String and add them 79# to specification dictionary. 80# 81# @param SpecificationDict The destine Specification dictionary. 82# @param SpecificationString The source Specification String from which the 83# specification name and value pair is abstracted. 84# 85def AddToSpecificationDict(SpecificationDict, SpecificationString): 86 """Abstract specification name, value pair from Specification String""" 87 for SpecificationMatch in mReSpecification.finditer(SpecificationString): 88 Specification = SpecificationMatch.group("Specification") 89 Value = SpecificationMatch.group("Value") 90 SpecificationDict[Specification] = Value 91 92## Set all fields of CommonHeaderClass object. 93# 94# Set all attributes of CommonHeaderClass object from XML Dom object of 95# XmlCommonHeader, NameTag and FileName. 96# 97# @param CommonHeader The destine CommonClass object. 98# @param XmlCommonHeader The source XML Dom object. 99# @param NameTag The name tag in XML Dom object. 100# @param FileName The file name of the XML file. 101# 102def SetCommonHeader(CommonHeader, XmlCommonHeader): 103 """Set all attributes of CommonHeaderClass object from XmlCommonHeader""" 104 XmlParent = XmlNodeName(XmlCommonHeader) 105 106 XmlTag = XmlParent + "/" + "Abstract" 107 CommonHeader.Abstract = XmlElement(XmlCommonHeader, XmlTag) 108 109 XmlTag = XmlParent + "/" + "Description" 110 CommonHeader.Description = XmlElement(XmlCommonHeader, XmlTag) 111 112 XmlTag = XmlParent + "/" + "Copyright" 113 CommonHeader.Copyright = XmlElement(XmlCommonHeader, XmlTag) 114 115 XmlTag = XmlParent + "/" + "License" 116 CommonHeader.License = XmlElement(XmlCommonHeader, XmlTag) 117 118 XmlTag = XmlParent + "/" + "Specification" 119 Specification = XmlElement(XmlCommonHeader, XmlTag) 120 121 AddToSpecificationDict(CommonHeader.Specification, Specification) 122 123 XmlTag = XmlParent + "/" + "ModuleType" 124 CommonHeader.ModuleType = XmlElement(XmlCommonHeader, XmlTag) 125 126 127## Load a new Cloned Record class object. 128# 129# Read an input XML ClonedRecord DOM object and return an object of Cloned Record 130# contained in the DOM object. 131# 132# @param XmlCloned A child XML DOM object in a Common XML DOM. 133# 134# @retvel ClonedRecord A new Cloned Record object created by XmlCloned. 135# 136def LoadClonedRecord(XmlCloned): 137 ClonedRecord = ClonedRecordClass() 138 139 XmlTag = "Id" 140 ClonedRecord.Id = int(XmlAttribute(XmlCloned, XmlTag)) 141 142 XmlTag = "FarGuid" 143 ClonedRecord.FarGuid = XmlAttribute(XmlCloned, XmlTag) 144 145 XmlTag = "Cloned/PackageGuid" 146 ClonedRecord.PackageGuid = XmlElement(XmlCloned, XmlTag) 147 148 XmlTag = "Cloned/PackageVersion" 149 ClonedRecord.PackageVersion = XmlElement(XmlCloned, XmlTag) 150 151 XmlTag = "Cloned/ModuleGuid" 152 ClonedRecord.ModuleGuid = XmlElement(XmlCloned, XmlTag) 153 154 XmlTag = "Cloned/ModuleVersion" 155 ClonedRecord.ModuleVersion = XmlElement(XmlCloned, XmlTag) 156 157 return ClonedRecord 158 159 160## Load a new Guid/Protocol/Ppi common class object. 161# 162# Read an input XML Guid/Protocol/Ppi DOM object and return an object of 163# Guid/Protocol/Ppi contained in the DOM object. 164# 165# @param XmlGuidProtocolPpiCommon A child XML DOM object in a Common XML DOM. 166# 167# @retvel GuidProtocolPpiCommon A new GuidProtocolPpiCommon class object 168# created by XmlGuidProtocolPpiCommon. 169# 170def LoadGuidProtocolPpiCommon(XmlGuidProtocolPpiCommon): 171 GuidProtocolPpiCommon = GuidProtocolPpiCommonClass() 172 173 XmlTag = "Name" 174 GuidProtocolPpiCommon.Name = XmlAttribute(XmlGuidProtocolPpiCommon, XmlTag) 175 176 XmlParent = XmlNodeName(XmlGuidProtocolPpiCommon) 177 if XmlParent == "Entry": 178 XmlTag = "%s/C_Name" % XmlParent 179 elif XmlParent == "GuidCNames": 180 XmlTag = "%s/GuidCName" % XmlParent 181 else: 182 XmlTag = "%s/%sCName" % (XmlParent, XmlParent) 183 184 GuidProtocolPpiCommon.CName = XmlElement(XmlGuidProtocolPpiCommon, XmlTag) 185 186 XmlTag = XmlParent + "/" + "GuidValue" 187 GuidProtocolPpiCommon.Guid = XmlElement(XmlGuidProtocolPpiCommon, XmlTag) 188 189 if XmlParent.endswith("Notify"): 190 GuidProtocolPpiCommon.Notify = True 191 192 XmlTag = "GuidTypeList" 193 GuidTypes = XmlAttribute(XmlGuidProtocolPpiCommon, XmlTag) 194 GuidProtocolPpiCommon.GuidTypeList = GuidTypes.split() 195 196 XmlTag = "SupModuleList" 197 SupModules = XmlAttribute(XmlGuidProtocolPpiCommon, XmlTag) 198 GuidProtocolPpiCommon.SupModuleList = SupModules.split() 199 200 SetCommon(GuidProtocolPpiCommon, XmlGuidProtocolPpiCommon) 201 202 return GuidProtocolPpiCommon 203 204 205## Load a new Pcd class object. 206# 207# Read an input XML Pcd DOM object and return an object of Pcd 208# contained in the DOM object. 209# 210# @param XmlPcd A child XML DOM object in a Common XML DOM. 211# 212# @retvel Pcd A new Pcd object created by XmlPcd. 213# 214def LoadPcd(XmlPcd): 215 """Return a new PcdClass object equivalent to XmlPcd""" 216 Pcd = PcdClass() 217 218 XmlTag = "PcdEntry/C_Name" 219 Pcd.CName = XmlElement(XmlPcd, XmlTag) 220 221 XmlTag = "PcdEntry/Token" 222 Pcd.Token = XmlElement(XmlPcd, XmlTag) 223 224 XmlTag = "PcdEntry/TokenSpaceGuidCName" 225 Pcd.TokenSpaceGuidCName = XmlElement(XmlPcd, XmlTag) 226 227 XmlTag = "PcdEntry/DatumType" 228 Pcd.DatumType = XmlElement(XmlPcd, XmlTag) 229 230 XmlTag = "PcdEntry/MaxDatumSize" 231 Pcd.MaxDatumSize = XmlElement(XmlPcd, XmlTag) 232 233 XmlTag = "PcdEntry/DefaultValue" 234 Pcd.DefaultValue = XmlElement(XmlPcd, XmlTag) 235 236 XmlTag = "PcdItemType" 237 Pcd.ItemType = XmlAttribute(XmlPcd, XmlTag) 238 239 XmlTag = "PcdEntry/ValidUsage" 240 Pcd.ValidUsage = XmlElement(XmlPcd, XmlTag).split() 241 242 XmlTag = "SupModuleList" 243 Pcd.SupModuleList = XmlAttribute(XmlPcd, XmlTag).split() 244 245 SetCommon(Pcd, XmlPcd) 246 247 return Pcd 248 249 250## Load a new LibraryClass class object. 251# 252# Read an input XML LibraryClass DOM object and return an object of LibraryClass 253# contained in the DOM object. 254# 255# @param XmlLibraryClass A child XML DOM object in a Common XML DOM. 256# 257# @retvel LibraryClass A new LibraryClass object created by XmlLibraryClass. 258# 259def LoadLibraryClass(XmlLibraryClass): 260 LibraryClass = LibraryClassClass() 261 262 XmlTag = "LibraryClass/Keyword" 263 LibraryClass.LibraryClass = XmlElement(XmlLibraryClass, XmlTag) 264 if LibraryClass.LibraryClass == "": 265 XmlTag = "Name" 266 LibraryClass.LibraryClass = XmlAttribute(XmlLibraryClass, XmlTag) 267 268 XmlTag = "LibraryClass/IncludeHeader" 269 LibraryClass.IncludeHeader = XmlElement(XmlLibraryClass, XmlTag) 270 271 XmlTag = "RecommendedInstanceVersion" 272 RecommendedInstanceVersion = XmlAttribute(XmlLibraryClass, XmlTag) 273 LibraryClass.RecommendedInstanceVersion = RecommendedInstanceVersion 274 275 XmlTag = "RecommendedInstanceGuid" 276 RecommendedInstanceGuid = XmlAttribute(XmlLibraryClass, XmlTag) 277 LibraryClass.RecommendedInstanceGuid = RecommendedInstanceGuid 278 279 XmlTag = "SupModuleList" 280 SupModules = XmlAttribute(XmlLibraryClass, XmlTag) 281 LibraryClass.SupModuleList = SupModules.split() 282 283 SetCommon(LibraryClass, XmlLibraryClass) 284 285 return LibraryClass 286 287 288## Load a new Build Option class object. 289# 290# Read an input XML BuildOption DOM object and return an object of Build Option 291# contained in the DOM object. 292# 293# @param XmlBuildOption A child XML DOM object in a Common XML DOM. 294# 295# @retvel BuildOption A new Build Option object created by XmlBuildOption. 296# 297def LoadBuildOption(XmlBuildOption): 298 """Return a new BuildOptionClass object equivalent to XmlBuildOption""" 299 BuildOption = BuildOptionClass() 300 301 BuildOption.Option = XmlElementData(XmlBuildOption) 302 303 XmlTag = "BuildTargets" 304 BuildOption.BuildTargetList = XmlAttribute(XmlBuildOption, XmlTag).split() 305 306 XmlTag = "ToolChainFamily" 307 BuildOption.ToolChainFamily = XmlAttribute(XmlBuildOption, XmlTag) 308 309 XmlTag = "TagName" 310 BuildOption.TagName = XmlAttribute(XmlBuildOption, XmlTag) 311 312 XmlTag = "ToolCode" 313 BuildOption.ToolCode = XmlAttribute(XmlBuildOption, XmlTag) 314 315 XmlTag = "SupArchList" 316 BuildOption.SupArchList = XmlAttribute(XmlBuildOption, XmlTag).split() 317 318 return BuildOption 319 320 321## Load a new User Extensions class object. 322# 323# Read an input XML UserExtensions DOM object and return an object of User 324# Extensions contained in the DOM object. 325# 326# @param XmlUserExtensions A child XML DOM object in a Common XML DOM. 327# 328# @retvel UserExtensions A new User Extensions object created by 329# XmlUserExtensions. 330# 331def LoadUserExtensions(XmlUserExtensions): 332 UserExtensions = UserExtensionsClass() 333 334 XmlTag = "UserID" 335 UserExtensions.UserID = XmlAttribute(XmlUserExtensions, XmlTag) 336 337 XmlTag = "Identifier" 338 UserExtensions.Identifier = XmlAttribute(XmlUserExtensions, XmlTag) 339 340 UserExtensions.Content = XmlElementData(XmlUserExtensions) 341 342 return UserExtensions 343 344 345## Store content to a text file object. 346# 347# Write some text file content to a text file object. The contents may echo 348# in screen in a verbose way. 349# 350# @param TextFile The text file object. 351# @param Content The string object to be written to a text file. 352# 353def StoreTextFile(TextFile, Content): 354 EdkLogger.verbose(Content) 355 TextFile.write(Content) 356 357 358## Add item to a section. 359# 360# Add an Item with specific CPU architecture to section dictionary. 361# The possible duplication is ensured to be removed. 362# 363# @param Section Section dictionary indexed by CPU architecture. 364# @param Arch CPU architecture: Ia32, X64, Ipf, ARM, AARCH64, Ebc or Common. 365# @param Item The Item to be added to section dictionary. 366# 367def AddToSection(Section, Arch, Item): 368 SectionArch = Section.get(Arch, []) 369 if Item not in SectionArch: 370 SectionArch.append(Item) 371 Section[Arch] = SectionArch 372 373 374## Get section contents. 375# 376# Return the content of section named SectionName. 377# the contents is based on Methods and ObjectLists. 378# 379# @param SectionName The name of the section. 380# @param Method A function returning a string item of an object. 381# @param ObjectList The list of object. 382# 383# @retval Section The string content of a section. 384# 385def GetSection(SectionName, Method, ObjectList): 386 SupportedArches = ["common", "Ia32", "X64", "Ipf", "Ebc", "ARM", "AARCH64"] 387 SectionDict = {} 388 for Object in ObjectList: 389 Item = Method(Object) 390 if Item == "": 391 continue 392 Item = " %s" % Item 393 Arches = Object.SupArchList 394 if len(Arches) == 0: 395 AddToSection(SectionDict, "common", Item) 396 else: 397 for Arch in SupportedArches: 398 if Arch.upper() in Arches: 399 AddToSection(SectionDict, Arch, Item) 400 401 Section = "" 402 for Arch in SupportedArches: 403 SectionArch = "\n".join(SectionDict.get(Arch, [])) 404 if SectionArch != "": 405 Section += "[%s.%s]\n%s\n" % (SectionName, Arch, SectionArch) 406 Section += "\n" 407 if Section != "": 408 Section += "\n" 409 return Section 410 411 412## Store file header to a text file. 413# 414# Write standard file header to a text file. The content includes copyright, 415# abstract, description and license extracted from CommonHeader class object. 416# 417# @param TextFile The text file object. 418# @param CommonHeader The source CommonHeader class object. 419# 420def StoreHeader(TextFile, CommonHeader): 421 CopyRight = CommonHeader.Copyright 422 Abstract = CommonHeader.Abstract 423 Description = CommonHeader.Description 424 License = CommonHeader.License 425 426 Header = "#/** @file\n#\n" 427 Header += "# " + Abstract + "\n#\n" 428 Header += "# " + Description.strip().replace("\n", "\n# ") + "\n" 429 Header += "# " + CopyRight + "\n#\n" 430 Header += "# " + License.replace("\n", "\n# ").replace(" ", " ") 431 Header += "\n#\n#**/\n\n" 432 433 StoreTextFile(TextFile, Header) 434 435## Store file header to a text file. 436# 437# Write Defines section to a text file. DefinesTupleList determines the content. 438# 439# @param TextFile The text file object. 440# @param DefinesTupleList The list of (Tag, Value) to be added as one item. 441# 442def StoreDefinesSection(TextFile, DefinesTupleList): 443 Section = "[Defines]\n" 444 for DefineItem in DefinesTupleList: 445 Section += " %-30s = %s\n" % DefineItem 446 447 Section += "\n\n" 448 StoreTextFile(TextFile, Section) 449 450 451## Return one User Extension section. 452# 453# Read the input UserExtentsions class object and return one section. 454# 455# @param UserExtensions An input UserExtensions class object. 456# 457# @retval UserExtensionSection A section representing UserExtensions object. 458# 459def GetUserExtensions(UserExtensions): 460 UserId = UserExtensions.UserID 461 Identifier = UserExtensions.Identifier 462 Content = UserExtensions.Content 463 464 return "[UserExtensions.%s.%s]\n %s\n\n" % (UserId, Identifier, Content) 465 466## Regular expression to match an equation. 467mReEquation = re.compile(r"\s*(\S+)\s*=\s*(\S*)\s*") 468 469## Return a value tuple matching information in a text fle. 470# 471# Parse the text file and return a value tuple corresponding to an input tag 472# tuple. In case of any error, an tuple of empty strings is returned. 473# 474# @param FileName The file name of the text file. 475# @param TagTuple A tuple of tags as the key to the value. 476# 477# @param ValueTupe The returned tuple corresponding to the tag tuple. 478# 479def GetTextFileInfo(FileName, TagTuple): 480 ValueTuple = [""] * len(TagTuple) 481 try: 482 for Line in open(FileName): 483 Line = Line.split("#", 1)[0] 484 MatchEquation = mReEquation.match(Line) 485 if MatchEquation: 486 Tag = MatchEquation.group(1).upper() 487 Value = MatchEquation.group(2) 488 for Index in range(len(TagTuple)): 489 if TagTuple[Index] == Tag: 490 ValueTuple[Index] = Value 491 except: 492 EdkLogger.info("IO Error in reading file %s" % FileName) 493 494 return ValueTuple 495 496 497## Return a value tuple matching information in an XML fle. 498# 499# Parse the XML file and return a value tuple corresponding to an input tag 500# tuple. In case of any error, an tuple of empty strings is returned. 501# 502# @param FileName The file name of the XML file. 503# @param TagTuple A tuple of tags as the key to the value. 504# 505# @param ValueTupe The returned tuple corresponding to the tag tuple. 506# 507def GetXmlFileInfo(FileName, TagTuple): 508 XmlDom = XmlParseFile(FileName) 509 return tuple([XmlElement(XmlDom, XmlTag) for XmlTag in TagTuple]) 510 511 512## Parse migration command line options 513# 514# Use standard Python module optparse to parse command line option of this tool. 515# 516# @param Source The source file type. 517# @param Destinate The destinate file type. 518# 519# @retval Options A optparse object containing the parsed options. 520# @retval InputFile Path of an source file to be migrated. 521# 522def MigrationOptionParser(Source, Destinate, ToolName, VersionNumber=1.0): 523 # use clearer usage to override default usage message 524 UsageString = "%s [-a] [-v|-q] [-o <output_file>] <input_file>" % ToolName 525 Version = "%s Version %.2f" % (ToolName, VersionNumber) 526 Copyright = "Copyright (c) 2007, Intel Corporation. All rights reserved." 527 528 Parser = OptionParser(description=Copyright, version=Version, usage=UsageString) 529 Parser.add_option("-o", "--output", dest="OutputFile", help="The name of the %s file to be created." % Destinate) 530 Parser.add_option("-a", "--auto", dest="AutoWrite", action="store_true", default=False, help="Automatically create the %s file using the name of the %s file and replacing file extension" % (Source, Destinate)) 531 Parser.add_option("-q", "--quiet", action="store_true", type=None, help="Disable all messages except FATAL ERRORS.") 532 Parser.add_option("-v", "--verbose", action="store_true", type=None, help="Turn on verbose output with informational messages printed.") 533 534 Options, Args = Parser.parse_args() 535 536 # Set logging level 537 if Options.verbose: 538 EdkLogger.setLevel(EdkLogger.VERBOSE) 539 elif Options.quiet: 540 EdkLogger.setLevel(EdkLogger.QUIET) 541 else: 542 EdkLogger.setLevel(EdkLogger.INFO) 543 544 # error check 545 if len(Args) == 0: 546 raise MigrationError(PARAMETER_MISSING, name="Input file", usage=Parser.get_usage()) 547 if len(Args) > 1: 548 raise MigrationError(PARAMETER_INVALID, name="Too many input files", usage=Parser.get_usage()) 549 550 InputFile = Args[0] 551 if not os.path.exists(InputFile): 552 raise MigrationError(FILE_NOT_FOUND, name=InputFile) 553 554 if Options.OutputFile: 555 if Options.AutoWrite: 556 raise MigrationError(OPTION_CONFLICT, arg1="-o", arg2="-a", usage=Parser.get_usage()) 557 else: 558 if Options.AutoWrite: 559 Options.OutputFile = os.path.splitext(InputFile)[0] + "." + Destinate.lower() 560 else: 561 raise MigrationError(OPTION_MISSING, name="-o", usage=Parser.get_usage()) 562 563 return Options, InputFile 564 565# This acts like the main() function for the script, unless it is 'import'ed 566# into another script. 567if __name__ == '__main__': 568 pass 569