From f215e02bf85f68d3a6106c2a1f4f7f063f819064 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:17:27 +0200 Subject: Adding upstream version 7.0.14-dfsg. Signed-off-by: Daniel Baumann --- .../BaseTools/Source/Python/UPT/BuildVersion.py | 14 + .../Source/Python/UPT/Core/DependencyRules.py | 448 +++++++ .../Python/UPT/Core/DistributionPackageClass.py | 267 ++++ .../BaseTools/Source/Python/UPT/Core/FileHook.py | 193 +++ .../BaseTools/Source/Python/UPT/Core/IpiDb.py | 922 +++++++++++++ .../Source/Python/UPT/Core/PackageFile.py | 250 ++++ .../BaseTools/Source/Python/UPT/Core/__init__.py | 14 + .../Source/Python/UPT/GenMetaFile/GenDecFile.py | 683 ++++++++++ .../Source/Python/UPT/GenMetaFile/GenInfFile.py | 1122 ++++++++++++++++ .../Python/UPT/GenMetaFile/GenMetaFileMisc.py | 188 +++ .../Source/Python/UPT/GenMetaFile/GenXmlFile.py | 12 + .../Source/Python/UPT/GenMetaFile/__init__.py | 14 + .../BaseTools/Source/Python/UPT/InstallPkg.py | 967 +++++++++++++ .../BaseTools/Source/Python/UPT/InventoryWs.py | 111 ++ .../Source/Python/UPT/Library/CommentGenerating.py | 238 ++++ .../Source/Python/UPT/Library/CommentParsing.py | 593 ++++++++ .../Source/Python/UPT/Library/DataType.py | 949 +++++++++++++ .../Python/UPT/Library/ExpressionValidate.py | 567 ++++++++ .../Source/Python/UPT/Library/GlobalData.py | 110 ++ .../BaseTools/Source/Python/UPT/Library/Misc.py | 989 ++++++++++++++ .../Source/Python/UPT/Library/ParserValidate.py | 727 ++++++++++ .../BaseTools/Source/Python/UPT/Library/Parsing.py | 1015 ++++++++++++++ .../Source/Python/UPT/Library/StringUtils.py | 982 ++++++++++++++ .../Source/Python/UPT/Library/UniClassObject.py | 1074 +++++++++++++++ .../Source/Python/UPT/Library/Xml/XmlRoutines.py | 223 +++ .../Source/Python/UPT/Library/Xml/__init__.py | 14 + .../Source/Python/UPT/Library/__init__.py | 14 + .../BaseTools/Source/Python/UPT/Logger/Log.py | 319 +++++ .../Source/Python/UPT/Logger/StringTable.py | 860 ++++++++++++ .../Source/Python/UPT/Logger/ToolError.py | 171 +++ .../BaseTools/Source/Python/UPT/Logger/__init__.py | 14 + .../Firmware/BaseTools/Source/Python/UPT/MkPkg.py | 274 ++++ .../Source/Python/UPT/Object/POM/CommonObject.py | 953 +++++++++++++ .../Source/Python/UPT/Object/POM/ModuleObject.py | 654 +++++++++ .../Source/Python/UPT/Object/POM/PackageObject.py | 192 +++ .../Source/Python/UPT/Object/POM/__init__.py | 14 + .../Source/Python/UPT/Object/Parser/DecObject.py | 605 +++++++++ .../Python/UPT/Object/Parser/InfBinaryObject.py | 686 ++++++++++ .../UPT/Object/Parser/InfBuildOptionObject.py | 87 ++ .../Python/UPT/Object/Parser/InfCommonObject.py | 156 +++ .../UPT/Object/Parser/InfDefineCommonObject.py | 83 ++ .../Python/UPT/Object/Parser/InfDefineObject.py | 1002 ++++++++++++++ .../Python/UPT/Object/Parser/InfDepexObject.py | 160 +++ .../Python/UPT/Object/Parser/InfGuidObject.py | 347 +++++ .../Python/UPT/Object/Parser/InfHeaderObject.py | 113 ++ .../UPT/Object/Parser/InfLibraryClassesObject.py | 247 ++++ .../Source/Python/UPT/Object/Parser/InfMisc.py | 142 ++ .../Python/UPT/Object/Parser/InfPackagesObject.py | 181 +++ .../Python/UPT/Object/Parser/InfPcdObject.py | 669 +++++++++ .../Python/UPT/Object/Parser/InfPpiObject.py | 337 +++++ .../Python/UPT/Object/Parser/InfProtocolObject.py | 305 +++++ .../Python/UPT/Object/Parser/InfSoucesObject.py | 233 ++++ .../UPT/Object/Parser/InfUserExtensionObject.py | 127 ++ .../Source/Python/UPT/Object/Parser/__init__.py | 14 + .../BaseTools/Source/Python/UPT/Object/__init__.py | 14 + .../Source/Python/UPT/Parser/DecParser.py | 1091 +++++++++++++++ .../Source/Python/UPT/Parser/DecParserMisc.py | 364 +++++ .../Source/Python/UPT/Parser/InfAsBuiltProcess.py | 283 ++++ .../Python/UPT/Parser/InfBinarySectionParser.py | 226 ++++ .../UPT/Parser/InfBuildOptionSectionParser.py | 212 +++ .../Python/UPT/Parser/InfDefineSectionParser.py | 191 +++ .../Python/UPT/Parser/InfDepexSectionParser.py | 98 ++ .../UPT/Parser/InfGuidPpiProtocolSectionParser.py | 368 +++++ .../Python/UPT/Parser/InfLibrarySectionParser.py | 197 +++ .../Python/UPT/Parser/InfPackageSectionParser.py | 134 ++ .../Source/Python/UPT/Parser/InfParser.py | 680 ++++++++++ .../Source/Python/UPT/Parser/InfParserMisc.py | 216 +++ .../Python/UPT/Parser/InfPcdSectionParser.py | 178 +++ .../Source/Python/UPT/Parser/InfSectionParser.py | 493 +++++++ .../Python/UPT/Parser/InfSourceSectionParser.py | 139 ++ .../BaseTools/Source/Python/UPT/Parser/__init__.py | 14 + .../Python/UPT/PomAdapter/DecPomAlignment.py | 1000 ++++++++++++++ .../Python/UPT/PomAdapter/InfPomAlignment.py | 1071 +++++++++++++++ .../Python/UPT/PomAdapter/InfPomAlignmentMisc.py | 255 ++++ .../Source/Python/UPT/PomAdapter/__init__.py | 14 + .../BaseTools/Source/Python/UPT/ReplacePkg.py | 142 ++ .../Firmware/BaseTools/Source/Python/UPT/RmPkg.py | 270 ++++ .../BaseTools/Source/Python/UPT/TestInstall.py | 94 ++ .../Firmware/BaseTools/Source/Python/UPT/UPT.py | 347 +++++ .../UPT/UnitTest/CommentGeneratingUnitTest.py | 1414 ++++++++++++++++++++ .../Python/UPT/UnitTest/CommentParsingUnitTest.py | 917 +++++++++++++ .../Source/Python/UPT/UnitTest/DecParserTest.py | 279 ++++ .../Python/UPT/UnitTest/DecParserUnitTest.py | 528 ++++++++ .../Python/UPT/UnitTest/InfBinarySectionTest.py | 381 ++++++ .../BaseTools/Source/Python/UPT/Xml/CommonXml.py | 997 ++++++++++++++ .../Source/Python/UPT/Xml/GuidProtocolPpiXml.py | 278 ++++ .../BaseTools/Source/Python/UPT/Xml/IniToXml.py | 496 +++++++ .../Source/Python/UPT/Xml/ModuleSurfaceAreaXml.py | 1003 ++++++++++++++ .../Source/Python/UPT/Xml/PackageSurfaceAreaXml.py | 402 ++++++ .../BaseTools/Source/Python/UPT/Xml/PcdXml.py | 555 ++++++++ .../BaseTools/Source/Python/UPT/Xml/XmlParser.py | 926 +++++++++++++ .../Source/Python/UPT/Xml/XmlParserMisc.py | 95 ++ .../BaseTools/Source/Python/UPT/Xml/__init__.py | 14 + 93 files changed, 38021 insertions(+) create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/BuildVersion.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/DependencyRules.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/DistributionPackageClass.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/FileHook.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/IpiDb.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/PackageFile.py create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/__init__.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/GenMetaFile/GenDecFile.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/GenMetaFile/GenInfFile.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/GenMetaFile/GenMetaFileMisc.py create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/GenMetaFile/GenXmlFile.py create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/GenMetaFile/__init__.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/InstallPkg.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/InventoryWs.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/CommentGenerating.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/CommentParsing.py create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/DataType.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/ExpressionValidate.py create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/GlobalData.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/Misc.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/ParserValidate.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/Parsing.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/StringUtils.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/UniClassObject.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/Xml/XmlRoutines.py create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/Xml/__init__.py create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/__init__.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Logger/Log.py create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Logger/StringTable.py create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Logger/ToolError.py create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Logger/__init__.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/MkPkg.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/POM/CommonObject.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/POM/ModuleObject.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/POM/PackageObject.py create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/POM/__init__.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/DecObject.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfBinaryObject.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfBuildOptionObject.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfCommonObject.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfDefineCommonObject.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfDefineObject.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfDepexObject.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfGuidObject.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfHeaderObject.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfLibraryClassesObject.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfMisc.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfPackagesObject.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfPcdObject.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfPpiObject.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfProtocolObject.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfSoucesObject.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfUserExtensionObject.py create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/__init__.py create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/__init__.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/DecParser.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/DecParserMisc.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfAsBuiltProcess.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfBinarySectionParser.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfBuildOptionSectionParser.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfDefineSectionParser.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfDepexSectionParser.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfGuidPpiProtocolSectionParser.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfLibrarySectionParser.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfPackageSectionParser.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfParser.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfParserMisc.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfPcdSectionParser.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfSectionParser.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfSourceSectionParser.py create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/__init__.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/PomAdapter/DecPomAlignment.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/PomAdapter/InfPomAlignment.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/PomAdapter/InfPomAlignmentMisc.py create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/PomAdapter/__init__.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/ReplacePkg.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/RmPkg.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/TestInstall.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UPT.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/CommentGeneratingUnitTest.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/CommentParsingUnitTest.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/DecParserTest.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/DecParserUnitTest.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/InfBinarySectionTest.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/CommonXml.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/GuidProtocolPpiXml.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/IniToXml.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/ModuleSurfaceAreaXml.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/PackageSurfaceAreaXml.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/PcdXml.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/XmlParser.py create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/XmlParserMisc.py create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/__init__.py (limited to 'src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT') diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/BuildVersion.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/BuildVersion.py new file mode 100644 index 00000000..e62b8ef3 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/BuildVersion.py @@ -0,0 +1,14 @@ +## @file +# +# This file is for build version number auto generation +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +Build version information +''' + +gBUILD_VERSION = "Developer Build based on Revision: Unknown" diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/DependencyRules.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/DependencyRules.py new file mode 100755 index 00000000..2742db84 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/DependencyRules.py @@ -0,0 +1,448 @@ +## @file +# This file is for installed package information database operations +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +Dependency +''' + +## +# Import Modules +# +from os.path import dirname +import os + +import Logger.Log as Logger +from Logger import StringTable as ST +from Library.Parsing import GetWorkspacePackage +from Library.Parsing import GetWorkspaceModule +from Library.Parsing import GetPkgInfoFromDec +from Library.Misc import GetRelativePath +from Library import GlobalData +from Logger.ToolError import FatalError +from Logger.ToolError import EDK1_INF_ERROR +from Logger.ToolError import UNKNOWN_ERROR +(DEPEX_CHECK_SUCCESS, DEPEX_CHECK_MODULE_NOT_FOUND, \ +DEPEX_CHECK_PACKAGE_NOT_FOUND, DEPEX_CHECK_DP_NOT_FOUND) = (0, 1, 2, 3) + + +## DependencyRules +# +# This class represents the dependency rule check mechanism +# +# @param object: Inherited from object class +# +class DependencyRules(object): + def __init__(self, Datab, ToBeInstalledPkgList=None): + self.IpiDb = Datab + self.WsPkgList = GetWorkspacePackage() + self.WsModuleList = GetWorkspaceModule() + + self.PkgsToBeDepend = [(PkgInfo[1], PkgInfo[2]) for PkgInfo in self.WsPkgList] + + # Add package info from the DIST to be installed. + self.PkgsToBeDepend.extend(self.GenToBeInstalledPkgList(ToBeInstalledPkgList)) + + def GenToBeInstalledPkgList(self, ToBeInstalledPkgList): + if not ToBeInstalledPkgList: + return [] + RtnList = [] + for Dist in ToBeInstalledPkgList: + for Package in Dist.PackageSurfaceArea: + RtnList.append((Package[0], Package[1])) + + return RtnList + + ## Check whether a module exists by checking the Guid+Version+Name+Path combination + # + # @param Guid: Guid of a module + # @param Version: Version of a module + # @param Name: Name of a module + # @param Path: Path of a module + # @return: True if module existed, else False + # + def CheckModuleExists(self, Guid, Version, Name, Path): + Logger.Verbose(ST.MSG_CHECK_MODULE_EXIST) + ModuleList = self.IpiDb.GetModInPackage(Guid, Version, Name, Path) + ModuleList.extend(self.IpiDb.GetStandaloneModule(Guid, Version, Name, Path)) + Logger.Verbose(ST.MSG_CHECK_MODULE_EXIST_FINISH) + if len(ModuleList) > 0: + return True + else: + return False + + ## Check whether a module depex satisfied. + # + # @param ModuleObj: A module object + # @param DpObj: A distribution object + # @return: True if module depex satisfied + # False else + # + def CheckModuleDepexSatisfied(self, ModuleObj, DpObj=None): + Logger.Verbose(ST.MSG_CHECK_MODULE_DEPEX_START) + Result = True + Dep = None + if ModuleObj.GetPackageDependencyList(): + Dep = ModuleObj.GetPackageDependencyList()[0] + for Dep in ModuleObj.GetPackageDependencyList(): + # + # first check whether the dependency satisfied by current workspace + # + Exist = self.CheckPackageExists(Dep.GetGuid(), Dep.GetVersion()) + # + # check whether satisfied by current distribution + # + if not Exist: + if DpObj is None: + Result = False + break + for GuidVerPair in DpObj.PackageSurfaceArea.keys(): + if Dep.GetGuid() == GuidVerPair[0]: + if Dep.GetVersion() is None or \ + len(Dep.GetVersion()) == 0: + Result = True + break + if Dep.GetVersion() == GuidVerPair[1]: + Result = True + break + else: + Result = False + break + + if not Result: + Logger.Error("CheckModuleDepex", UNKNOWN_ERROR, \ + ST.ERR_DEPENDENCY_NOT_MATCH % (ModuleObj.GetName(), \ + Dep.GetPackageFilePath(), \ + Dep.GetGuid(), \ + Dep.GetVersion())) + return Result + + ## Check whether a package exists in a package list specified by PkgsToBeDepend. + # + # @param Guid: Guid of a package + # @param Version: Version of a package + # @return: True if package exist + # False else + # + def CheckPackageExists(self, Guid, Version): + Logger.Verbose(ST.MSG_CHECK_PACKAGE_START) + Found = False + for (PkgGuid, PkgVer) in self.PkgsToBeDepend: + if (PkgGuid == Guid): + # + # if version is not empty and not equal, then not match + # + if Version and (PkgVer != Version): + Found = False + break + else: + Found = True + break + else: + Found = False + + Logger.Verbose(ST.MSG_CHECK_PACKAGE_FINISH) + return Found + + ## Check whether a package depex satisfied. + # + # @param PkgObj: A package object + # @param DpObj: A distribution object + # @return: True if package depex satisfied + # False else + # + def CheckPackageDepexSatisfied(self, PkgObj, DpObj=None): + ModuleDict = PkgObj.GetModuleDict() + for ModKey in ModuleDict.keys(): + ModObj = ModuleDict[ModKey] + if self.CheckModuleDepexSatisfied(ModObj, DpObj): + continue + else: + return False + return True + + ## Check whether a DP exists. + # + # @param Guid: Guid of a Distribution + # @param Version: Version of a Distribution + # @return: True if Distribution exist + # False else + def CheckDpExists(self, Guid, Version): + Logger.Verbose(ST.MSG_CHECK_DP_START) + DpList = self.IpiDb.GetDp(Guid, Version) + if len(DpList) > 0: + Found = True + else: + Found = False + + Logger.Verbose(ST.MSG_CHECK_DP_FINISH) + return Found + + ## Check whether a DP depex satisfied by current workspace for Install + # + # @param DpObj: A distribution object + # @return: True if distribution depex satisfied + # False else + # + def CheckInstallDpDepexSatisfied(self, DpObj): + return self.CheckDpDepexSatisfied(DpObj) + + # # Check whether multiple DP depex satisfied by current workspace for Install + # + # @param DpObjList: A distribution object list + # @return: True if distribution depex satisfied + # False else + # + def CheckTestInstallPdDepexSatisfied(self, DpObjList): + for DpObj in DpObjList: + if self.CheckDpDepexSatisfied(DpObj): + for PkgKey in DpObj.PackageSurfaceArea.keys(): + PkgObj = DpObj.PackageSurfaceArea[PkgKey] + self.PkgsToBeDepend.append((PkgObj.Guid, PkgObj.Version)) + else: + return False, DpObj + + return True, DpObj + + + ## Check whether a DP depex satisfied by current workspace + # (excluding the original distribution's packages to be replaced) for Replace + # + # @param DpObj: A distribution object + # @param OrigDpGuid: The original distribution's Guid + # @param OrigDpVersion: The original distribution's Version + # + def ReplaceCheckNewDpDepex(self, DpObj, OrigDpGuid, OrigDpVersion): + self.PkgsToBeDepend = [(PkgInfo[1], PkgInfo[2]) for PkgInfo in self.WsPkgList] + OrigDpPackageList = self.IpiDb.GetPackageListFromDp(OrigDpGuid, OrigDpVersion) + for OrigPkgInfo in OrigDpPackageList: + Guid, Version = OrigPkgInfo[0], OrigPkgInfo[1] + if (Guid, Version) in self.PkgsToBeDepend: + self.PkgsToBeDepend.remove((Guid, Version)) + return self.CheckDpDepexSatisfied(DpObj) + + ## Check whether a DP depex satisfied by current workspace. + # + # @param DpObj: A distribution object + # + def CheckDpDepexSatisfied(self, DpObj): + for PkgKey in DpObj.PackageSurfaceArea.keys(): + PkgObj = DpObj.PackageSurfaceArea[PkgKey] + if self.CheckPackageDepexSatisfied(PkgObj, DpObj): + continue + else: + return False + + for ModKey in DpObj.ModuleSurfaceArea.keys(): + ModObj = DpObj.ModuleSurfaceArea[ModKey] + if self.CheckModuleDepexSatisfied(ModObj, DpObj): + continue + else: + return False + + return True + + ## Check whether a DP could be removed from current workspace. + # + # @param DpGuid: File's guid + # @param DpVersion: File's version + # @retval Removable: True if distribution could be removed, False Else + # @retval DependModuleList: the list of modules that make distribution can not be removed + # + def CheckDpDepexForRemove(self, DpGuid, DpVersion): + Removable = True + DependModuleList = [] + WsModuleList = self.WsModuleList + # + # remove modules that included in current DP + # List of item (FilePath) + DpModuleList = self.IpiDb.GetDpModuleList(DpGuid, DpVersion) + for Module in DpModuleList: + if Module in WsModuleList: + WsModuleList.remove(Module) + else: + Logger.Warn("UPT\n", + ST.ERR_MODULE_NOT_INSTALLED % Module) + # + # get packages in current Dp and find the install path + # List of item (PkgGuid, PkgVersion, InstallPath) + DpPackageList = self.IpiDb.GetPackageListFromDp(DpGuid, DpVersion) + DpPackagePathList = [] + WorkSP = GlobalData.gWORKSPACE + for (PkgName, PkgGuid, PkgVersion, DecFile) in self.WsPkgList: + if PkgName: + pass + DecPath = dirname(DecFile) + if DecPath.find(WorkSP) > -1: + InstallPath = GetRelativePath(DecPath, WorkSP) + DecFileRelaPath = GetRelativePath(DecFile, WorkSP) + else: + InstallPath = DecPath + DecFileRelaPath = DecFile + + if (PkgGuid, PkgVersion, InstallPath) in DpPackageList: + DpPackagePathList.append(DecFileRelaPath) + DpPackageList.remove((PkgGuid, PkgVersion, InstallPath)) + + # + # the left items in DpPackageList are the packages that installed but not found anymore + # + for (PkgGuid, PkgVersion, InstallPath) in DpPackageList: + Logger.Warn("UPT", + ST.WARN_INSTALLED_PACKAGE_NOT_FOUND%(PkgGuid, PkgVersion, InstallPath)) + + # + # check modules to see if has dependency on package of current DP + # + for Module in WsModuleList: + if (not VerifyRemoveModuleDep(Module, DpPackagePathList)): + Removable = False + DependModuleList.append(Module) + return (Removable, DependModuleList) + + + ## Check whether a DP could be replaced by a distribution containing NewDpPkgList + # from current workspace. + # + # @param OrigDpGuid: original Dp's Guid + # @param OrigDpVersion: original Dp's version + # @param NewDpPkgList: a list of package information (Guid, Version) in new Dp + # @retval Replaceable: True if distribution could be replaced, False Else + # @retval DependModuleList: the list of modules that make distribution can not be replaced + # + def CheckDpDepexForReplace(self, OrigDpGuid, OrigDpVersion, NewDpPkgList): + Replaceable = True + DependModuleList = [] + WsModuleList = self.WsModuleList + # + # remove modules that included in current DP + # List of item (FilePath) + DpModuleList = self.IpiDb.GetDpModuleList(OrigDpGuid, OrigDpVersion) + for Module in DpModuleList: + if Module in WsModuleList: + WsModuleList.remove(Module) + else: + Logger.Warn("UPT\n", + ST.ERR_MODULE_NOT_INSTALLED % Module) + + OtherPkgList = NewDpPkgList + # + # get packages in current Dp and find the install path + # List of item (PkgGuid, PkgVersion, InstallPath) + DpPackageList = self.IpiDb.GetPackageListFromDp(OrigDpGuid, OrigDpVersion) + DpPackagePathList = [] + WorkSP = GlobalData.gWORKSPACE + for (PkgName, PkgGuid, PkgVersion, DecFile) in self.WsPkgList: + if PkgName: + pass + DecPath = dirname(DecFile) + if DecPath.find(WorkSP) > -1: + InstallPath = GetRelativePath(DecPath, WorkSP) + DecFileRelaPath = GetRelativePath(DecFile, WorkSP) + else: + InstallPath = DecPath + DecFileRelaPath = DecFile + + if (PkgGuid, PkgVersion, InstallPath) in DpPackageList: + DpPackagePathList.append(DecFileRelaPath) + DpPackageList.remove((PkgGuid, PkgVersion, InstallPath)) + else: + OtherPkgList.append((PkgGuid, PkgVersion)) + + # + # the left items in DpPackageList are the packages that installed but not found anymore + # + for (PkgGuid, PkgVersion, InstallPath) in DpPackageList: + Logger.Warn("UPT", + ST.WARN_INSTALLED_PACKAGE_NOT_FOUND%(PkgGuid, PkgVersion, InstallPath)) + + # + # check modules to see if it can be satisfied by package not belong to removed DP + # + for Module in WsModuleList: + if (not VerifyReplaceModuleDep(Module, DpPackagePathList, OtherPkgList)): + Replaceable = False + DependModuleList.append(Module) + return (Replaceable, DependModuleList) + + +## check whether module depends on packages in DpPackagePathList, return True +# if found, False else +# +# @param Path: a module path +# @param DpPackagePathList: a list of Package Paths +# @retval: False: module depends on package in DpPackagePathList +# True: module doesn't depend on package in DpPackagePathList +# +def VerifyRemoveModuleDep(Path, DpPackagePathList): + try: + for Item in GetPackagePath(Path): + if Item in DpPackagePathList: + DecPath = os.path.normpath(os.path.join(GlobalData.gWORKSPACE, Item)) + Logger.Info(ST.MSG_MODULE_DEPEND_ON % (Path, DecPath)) + return False + else: + return True + except FatalError as ErrCode: + if ErrCode.message == EDK1_INF_ERROR: + Logger.Warn("UPT", + ST.WRN_EDK1_INF_FOUND%Path) + return True + else: + return True + +# # GetPackagePath +# +# Get Dependency package path from an Inf file path +# +def GetPackagePath(InfPath): + PackagePath = [] + if os.path.exists(InfPath): + FindSection = False + for Line in open(InfPath).readlines(): + Line = Line.strip() + if not Line: + continue + if Line.startswith('#'): + continue + if Line.startswith('[Packages') and Line.endswith(']'): + FindSection = True + continue + if Line.startswith('[') and Line.endswith(']') and FindSection: + break + if FindSection: + PackagePath.append(os.path.normpath(Line)) + + return PackagePath + +## check whether module depends on packages in DpPackagePathList and can not be satisfied by OtherPkgList +# +# @param Path: a module path +# @param DpPackagePathList: a list of Package Paths +# @param OtherPkgList: a list of Package Information (Guid, Version) +# @retval: False: module depends on package in DpPackagePathList and can not be satisfied by OtherPkgList +# True: either module doesn't depend on DpPackagePathList or module depends on DpPackagePathList +# but can be satisfied by OtherPkgList +# +def VerifyReplaceModuleDep(Path, DpPackagePathList, OtherPkgList): + try: + for Item in GetPackagePath(Path): + if Item in DpPackagePathList: + DecPath = os.path.normpath(os.path.join(GlobalData.gWORKSPACE, Item)) + Name, Guid, Version = GetPkgInfoFromDec(DecPath) + if (Guid, Version) not in OtherPkgList: + Logger.Info(ST.MSG_MODULE_DEPEND_ON % (Path, DecPath)) + return False + else: + return True + except FatalError as ErrCode: + if ErrCode.message == EDK1_INF_ERROR: + Logger.Warn("UPT", + ST.WRN_EDK1_INF_FOUND%Path) + return True + else: + return True diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/DistributionPackageClass.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/DistributionPackageClass.py new file mode 100755 index 00000000..c9b3ccbc --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/DistributionPackageClass.py @@ -0,0 +1,267 @@ +## @file +# This file is used to define a class object to describe a distribution package +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +''' +DistributionPackageClass +''' + +## +# Import Modules +# +import os.path + +from Library.Misc import Sdict +from Library.Misc import GetNonMetaDataFiles +from PomAdapter.InfPomAlignment import InfPomAlignment +from PomAdapter.DecPomAlignment import DecPomAlignment +import Logger.Log as Logger +from Logger import StringTable as ST +from Logger.ToolError import OPTION_VALUE_INVALID +from Logger.ToolError import FatalError +from Logger.ToolError import EDK1_INF_ERROR +from Object.POM.CommonObject import IdentificationObject +from Object.POM.CommonObject import CommonHeaderObject +from Object.POM.CommonObject import MiscFileObject +from Common.MultipleWorkspace import MultipleWorkspace as mws + +## DistributionPackageHeaderClass +# +# @param IdentificationObject: Identification Object +# @param CommonHeaderObject: Common Header Object +# +class DistributionPackageHeaderObject(IdentificationObject, \ + CommonHeaderObject): + def __init__(self): + IdentificationObject.__init__(self) + CommonHeaderObject.__init__(self) + self.ReadOnly = '' + self.RePackage = '' + self.Vendor = '' + self.Date = '' + self.Signature = 'Md5Sum' + self.XmlSpecification = '' + + def GetReadOnly(self): + return self.ReadOnly + + def SetReadOnly(self, ReadOnly): + self.ReadOnly = ReadOnly + + def GetRePackage(self): + return self.RePackage + + def SetRePackage(self, RePackage): + self.RePackage = RePackage + + def GetVendor(self): + return self.Vendor + + def SetDate(self, Date): + self.Date = Date + + def GetDate(self): + return self.Date + + def SetSignature(self, Signature): + self.Signature = Signature + + def GetSignature(self): + return self.Signature + + def SetXmlSpecification(self, XmlSpecification): + self.XmlSpecification = XmlSpecification + + def GetXmlSpecification(self): + return self.XmlSpecification + +## DistributionPackageClass +# +# @param object: DistributionPackageClass +# +class DistributionPackageClass(object): + def __init__(self): + self.Header = DistributionPackageHeaderObject() + # + # {(Guid, Version, Path) : PackageObj} + # + self.PackageSurfaceArea = Sdict() + # + # {(Guid, Version, Name, Path) : ModuleObj} + # + self.ModuleSurfaceArea = Sdict() + self.Tools = MiscFileObject() + self.MiscellaneousFiles = MiscFileObject() + self.UserExtensions = [] + self.FileList = [] + + ## Get all included packages and modules for a distribution package + # + # @param WorkspaceDir: WorkspaceDir + # @param PackageList: A list of all packages + # @param ModuleList: A list of all modules + # + def GetDistributionPackage(self, WorkspaceDir, PackageList, ModuleList): + # Backup WorkspaceDir + Root = WorkspaceDir + + # + # Get Packages + # + if PackageList: + for PackageFile in PackageList: + PackageFileFullPath = mws.join(Root, PackageFile) + WorkspaceDir = mws.getWs(Root, PackageFile) + DecObj = DecPomAlignment(PackageFileFullPath, WorkspaceDir, CheckMulDec=True) + PackageObj = DecObj + # + # Parser inf file one bye one + # + ModuleInfFileList = PackageObj.GetModuleFileList() + for File in ModuleInfFileList: + WsRelPath = os.path.join(PackageObj.GetPackagePath(), File) + WsRelPath = os.path.normpath(WsRelPath) + if ModuleList and WsRelPath in ModuleList: + Logger.Error("UPT", + OPTION_VALUE_INVALID, + ST.ERR_NOT_STANDALONE_MODULE_ERROR%\ + (WsRelPath, PackageFile)) + Filename = os.path.normpath\ + (os.path.join(PackageObj.GetRelaPath(), File)) + os.path.splitext(Filename) + # + # Call INF parser to generate Inf Object. + # Actually, this call is not directly call, but wrapped by + # Inf class in InfPomAlignment. + # + try: + ModuleObj = InfPomAlignment(Filename, WorkspaceDir, PackageObj.GetPackagePath()) + + # + # Add module to package + # + ModuleDict = PackageObj.GetModuleDict() + ModuleDict[(ModuleObj.GetGuid(), \ + ModuleObj.GetVersion(), \ + ModuleObj.GetName(), \ + ModuleObj.GetCombinePath())] = ModuleObj + PackageObj.SetModuleDict(ModuleDict) + except FatalError as ErrCode: + if ErrCode.message == EDK1_INF_ERROR: + Logger.Warn("UPT", + ST.WRN_EDK1_INF_FOUND%Filename) + else: + raise + + self.PackageSurfaceArea\ + [(PackageObj.GetGuid(), PackageObj.GetVersion(), \ + PackageObj.GetCombinePath())] = PackageObj + + # + # Get Modules + # + if ModuleList: + for ModuleFile in ModuleList: + ModuleFileFullPath = mws.join(Root, ModuleFile) + WorkspaceDir = mws.getWs(Root, ModuleFile) + + try: + ModuleObj = InfPomAlignment(ModuleFileFullPath, WorkspaceDir) + ModuleKey = (ModuleObj.GetGuid(), + ModuleObj.GetVersion(), + ModuleObj.GetName(), + ModuleObj.GetCombinePath()) + self.ModuleSurfaceArea[ModuleKey] = ModuleObj + except FatalError as ErrCode: + if ErrCode.message == EDK1_INF_ERROR: + Logger.Error("UPT", + EDK1_INF_ERROR, + ST.WRN_EDK1_INF_FOUND%ModuleFileFullPath, + ExtraData=ST.ERR_NOT_SUPPORTED_SA_MODULE) + else: + raise + + # Recover WorkspaceDir + WorkspaceDir = Root + + ## Get all files included for a distribution package, except tool/misc of + # distribution level + # + # @retval DistFileList A list of filepath for NonMetaDataFile, relative to workspace + # @retval MetaDataFileList A list of filepath for MetaDataFile, relative to workspace + # + def GetDistributionFileList(self): + MetaDataFileList = [] + SkipModulesUniList = [] + + for Guid, Version, Path in self.PackageSurfaceArea: + Package = self.PackageSurfaceArea[Guid, Version, Path] + PackagePath = Package.GetPackagePath() + FullPath = Package.GetFullPath() + MetaDataFileList.append(Path) + IncludePathList = Package.GetIncludePathList() + for IncludePath in IncludePathList: + SearchPath = os.path.normpath(os.path.join(os.path.dirname(FullPath), IncludePath)) + AddPath = os.path.normpath(os.path.join(PackagePath, IncludePath)) + self.FileList += GetNonMetaDataFiles(SearchPath, ['CVS', '.svn'], False, AddPath) + # + # Add the miscellaneous files on DEC file + # + for MiscFileObj in Package.GetMiscFileList(): + for FileObj in MiscFileObj.GetFileList(): + MiscFileFullPath = os.path.normpath(os.path.join(PackagePath, FileObj.GetURI())) + if MiscFileFullPath not in self.FileList: + self.FileList.append(MiscFileFullPath) + + Module = None + ModuleDict = Package.GetModuleDict() + for Guid, Version, Name, Path in ModuleDict: + Module = ModuleDict[Guid, Version, Name, Path] + ModulePath = Module.GetModulePath() + FullPath = Module.GetFullPath() + PkgRelPath = os.path.normpath(os.path.join(PackagePath, ModulePath)) + MetaDataFileList.append(Path) + SkipList = ['CVS', '.svn'] + NonMetaDataFileList = [] + if Module.UniFileClassObject: + for UniFile in Module.UniFileClassObject.IncFileList: + OriPath = os.path.normpath(os.path.dirname(FullPath)) + UniFilePath = os.path.normpath(os.path.join(PkgRelPath, UniFile.Path[len(OriPath) + 1:])) + if UniFilePath not in SkipModulesUniList: + SkipModulesUniList.append(UniFilePath) + for IncludeFile in Module.UniFileClassObject.IncludePathList: + if IncludeFile not in SkipModulesUniList: + SkipModulesUniList.append(IncludeFile) + NonMetaDataFileList = GetNonMetaDataFiles(os.path.dirname(FullPath), SkipList, False, PkgRelPath) + for NonMetaDataFile in NonMetaDataFileList: + if NonMetaDataFile not in self.FileList: + self.FileList.append(NonMetaDataFile) + for Guid, Version, Name, Path in self.ModuleSurfaceArea: + Module = self.ModuleSurfaceArea[Guid, Version, Name, Path] + ModulePath = Module.GetModulePath() + FullPath = Module.GetFullPath() + MetaDataFileList.append(Path) + SkipList = ['CVS', '.svn'] + NonMetaDataFileList = [] + if Module.UniFileClassObject: + for UniFile in Module.UniFileClassObject.IncFileList: + OriPath = os.path.normpath(os.path.dirname(FullPath)) + UniFilePath = os.path.normpath(os.path.join(ModulePath, UniFile.Path[len(OriPath) + 1:])) + if UniFilePath not in SkipModulesUniList: + SkipModulesUniList.append(UniFilePath) + NonMetaDataFileList = GetNonMetaDataFiles(os.path.dirname(FullPath), SkipList, False, ModulePath) + for NonMetaDataFile in NonMetaDataFileList: + if NonMetaDataFile not in self.FileList: + self.FileList.append(NonMetaDataFile) + + for SkipModuleUni in SkipModulesUniList: + if SkipModuleUni in self.FileList: + self.FileList.remove(SkipModuleUni) + + return self.FileList, MetaDataFileList + + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/FileHook.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/FileHook.py new file mode 100755 index 00000000..433b4e3b --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/FileHook.py @@ -0,0 +1,193 @@ +## @file +# This file hooks file and directory creation and removal +# +# Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +File hook +''' + +import os +import stat +import time +import zipfile +from time import sleep +from Library import GlobalData + +__built_in_remove__ = os.remove +__built_in_mkdir__ = os.mkdir +__built_in_rmdir__ = os.rmdir +__built_in_chmod__ = os.chmod +__built_in_open__ = open + +_RMFILE = 0 +_MKFILE = 1 +_RMDIR = 2 +_MKDIR = 3 +_CHMOD = 4 + +gBACKUPFILE = 'file.backup' +gEXCEPTION_LIST = ['Conf'+os.sep+'DistributionPackageDatabase.db', '.tmp', gBACKUPFILE] + +class _PathInfo: + def __init__(self, action, path, mode=-1): + self.action = action + self.path = path + self.mode = mode + +class RecoverMgr: + def __init__(self, workspace): + self.rlist = [] + self.zip = None + self.workspace = os.path.normpath(workspace) + self.backupfile = gBACKUPFILE + self.zipfile = os.path.join(self.workspace, gBACKUPFILE) + + def _createzip(self): + if self.zip: + return + self.zip = zipfile.ZipFile(self.zipfile, 'w', zipfile.ZIP_DEFLATED) + + def _save(self, tmp, path): + if not self._tryhook(path): + return + self.rlist.append(_PathInfo(tmp, path)) + + def bkrmfile(self, path): + arc = self._tryhook(path) + if arc and os.path.isfile(path): + self._createzip() + self.zip.write(path, arc.encode('utf_8')) + sta = os.stat(path) + oldmode = stat.S_IMODE(sta.st_mode) + self.rlist.append(_PathInfo(_CHMOD, path, oldmode)) + self.rlist.append(_PathInfo(_RMFILE, path)) + __built_in_remove__(path) + + def bkmkfile(self, path, mode, bufsize): + if not os.path.exists(path): + self._save(_MKFILE, path) + return __built_in_open__(path, mode, bufsize) + + def bkrmdir(self, path): + if os.path.exists(path): + sta = os.stat(path) + oldmode = stat.S_IMODE(sta.st_mode) + self.rlist.append(_PathInfo(_CHMOD, path, oldmode)) + self._save(_RMDIR, path) + __built_in_rmdir__(path) + + def bkmkdir(self, path, mode): + if not os.path.exists(path): + self._save(_MKDIR, path) + __built_in_mkdir__(path, mode) + + def bkchmod(self, path, mode): + if self._tryhook(path) and os.path.exists(path): + sta = os.stat(path) + oldmode = stat.S_IMODE(sta.st_mode) + self.rlist.append(_PathInfo(_CHMOD, path, oldmode)) + __built_in_chmod__(path, mode) + + def rollback(self): + if self.zip: + self.zip.close() + self.zip = None + index = len(self.rlist) - 1 + while index >= 0: + item = self.rlist[index] + exist = os.path.exists(item.path) + if item.action == _MKFILE and exist: + #if not os.access(item.path, os.W_OK): + # os.chmod(item.path, S_IWUSR) + __built_in_remove__(item.path) + elif item.action == _RMFILE and not exist: + if not self.zip: + self.zip = zipfile.ZipFile(self.zipfile, 'r', zipfile.ZIP_DEFLATED) + arcname = os.path.normpath(item.path) + arcname = arcname[len(self.workspace)+1:].encode('utf_8') + if os.sep != "/" and os.sep in arcname: + arcname = arcname.replace(os.sep, '/') + mtime = self.zip.getinfo(arcname).date_time + content = self.zip.read(arcname) + filep = __built_in_open__(item.path, "wb") + filep.write(content) + filep.close() + intime = time.mktime(mtime + (0, 0, 0)) + os.utime(item.path, (intime, intime)) + elif item.action == _MKDIR and exist: + while True: + try: + __built_in_rmdir__(item.path) + break + except IOError: + # Sleep a short time and try again + # The anti-virus software may delay the file removal in this directory + sleep(0.1) + elif item.action == _RMDIR and not exist: + __built_in_mkdir__(item.path) + elif item.action == _CHMOD and exist: + try: + __built_in_chmod__(item.path, item.mode) + except EnvironmentError: + pass + index -= 1 + self.commit() + + def commit(self): + if self.zip: + self.zip.close() + __built_in_remove__(self.zipfile) + + # Check if path needs to be hooked + def _tryhook(self, path): + path = os.path.normpath(path) + works = self.workspace if str(self.workspace).endswith(os.sep) else (self.workspace + os.sep) + if not path.startswith(works): + return '' + for exceptdir in gEXCEPTION_LIST: + full = os.path.join(self.workspace, exceptdir) + if full == path or path.startswith(full + os.sep) or os.path.split(full)[0] == path: + return '' + return path[len(self.workspace)+1:] + +def _hookrm(path): + if GlobalData.gRECOVERMGR: + GlobalData.gRECOVERMGR.bkrmfile(path) + else: + __built_in_remove__(path) + +def _hookmkdir(path, mode=0o777): + if GlobalData.gRECOVERMGR: + GlobalData.gRECOVERMGR.bkmkdir(path, mode) + else: + __built_in_mkdir__(path, mode) + +def _hookrmdir(path): + if GlobalData.gRECOVERMGR: + GlobalData.gRECOVERMGR.bkrmdir(path) + else: + __built_in_rmdir__(path) + +def _hookmkfile(path, mode='r', bufsize=-1): + if GlobalData.gRECOVERMGR: + return GlobalData.gRECOVERMGR.bkmkfile(path, mode, bufsize) + return __built_in_open__(path, mode, bufsize) + +def _hookchmod(path, mode): + if GlobalData.gRECOVERMGR: + GlobalData.gRECOVERMGR.bkchmod(path, mode) + else: + __built_in_chmod__(path, mode) + +def SetRecoverMgr(mgr): + GlobalData.gRECOVERMGR = mgr + +os.remove = _hookrm +os.mkdir = _hookmkdir +os.rmdir = _hookrmdir +os.chmod = _hookchmod +__FileHookOpen__ = _hookmkfile diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/IpiDb.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/IpiDb.py new file mode 100755 index 00000000..7699a9c5 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/IpiDb.py @@ -0,0 +1,922 @@ +## @file +# This file is for installed package information database operations +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +IpiDb +''' + +## +# Import Modules +# +import sqlite3 +import os.path +import time + +import Logger.Log as Logger +from Logger import StringTable as ST +from Logger.ToolError import UPT_ALREADY_RUNNING_ERROR +from Logger.ToolError import UPT_DB_UPDATE_ERROR +import platform as pf + +## IpiDb +# +# This class represents the installed package information database +# Add/Remove/Get installed distribution package information here. +# +# +# @param object: Inherited from object class +# @param DbPath: A string for the path of the database +# +# +class IpiDatabase(object): + def __init__(self, DbPath, Workspace): + Dir = os.path.dirname(DbPath) + if not os.path.isdir(Dir): + os.mkdir(Dir) + self.Conn = sqlite3.connect(u''.join(DbPath), isolation_level='DEFERRED') + self.Conn.execute("PRAGMA page_size=4096") + self.Conn.execute("PRAGMA synchronous=OFF") + self.Cur = self.Conn.cursor() + self.DpTable = 'DpInfo' + self.PkgTable = 'PkgInfo' + self.ModInPkgTable = 'ModInPkgInfo' + self.StandaloneModTable = 'StandaloneModInfo' + self.ModDepexTable = 'ModDepexInfo' + self.DpFileListTable = 'DpFileListInfo' + self.DummyTable = 'Dummy' + self.Workspace = os.path.normpath(Workspace) + + ## Initialize build database + # + # + def InitDatabase(self, SkipLock = False): + Logger.Verbose(ST.MSG_INIT_IPI_START) + if not SkipLock: + try: + # + # Create a dummy table, if already existed, + # then UPT is already running + # + SqlCommand = """ + create table %s ( + Dummy TEXT NOT NULL, + PRIMARY KEY (Dummy) + )""" % self.DummyTable + self.Cur.execute(SqlCommand) + self.Conn.commit() + except sqlite3.OperationalError: + Logger.Error("UPT", + UPT_ALREADY_RUNNING_ERROR, + ST.ERR_UPT_ALREADY_RUNNING_ERROR + ) + + # + # Create new table + # + SqlCommand = """ + create table IF NOT EXISTS %s ( + DpGuid TEXT NOT NULL,DpVersion TEXT NOT NULL, + InstallTime REAL NOT NULL, + NewPkgFileName TEXT NOT NULL, + PkgFileName TEXT NOT NULL, + RePackage TEXT NOT NULL, + PRIMARY KEY (DpGuid, DpVersion) + )""" % self.DpTable + self.Cur.execute(SqlCommand) + + SqlCommand = """ + create table IF NOT EXISTS %s ( + FilePath TEXT NOT NULL, + DpGuid TEXT, + DpVersion TEXT, + Md5Sum TEXT, + PRIMARY KEY (FilePath) + )""" % self.DpFileListTable + self.Cur.execute(SqlCommand) + + SqlCommand = """ + create table IF NOT EXISTS %s ( + PackageGuid TEXT NOT NULL, + PackageVersion TEXT NOT NULL, + InstallTime REAL NOT NULL, + DpGuid TEXT, + DpVersion TEXT, + InstallPath TEXT NOT NULL, + PRIMARY KEY (PackageGuid, PackageVersion, InstallPath) + )""" % self.PkgTable + self.Cur.execute(SqlCommand) + + SqlCommand = """ + create table IF NOT EXISTS %s ( + ModuleGuid TEXT NOT NULL, + ModuleVersion TEXT NOT NULL, + ModuleName TEXT NOT NULL, + InstallTime REAL NOT NULL, + PackageGuid TEXT, + PackageVersion TEXT, + InstallPath TEXT NOT NULL, + PRIMARY KEY (ModuleGuid, ModuleVersion, ModuleName, InstallPath) + )""" % self.ModInPkgTable + self.Cur.execute(SqlCommand) + + SqlCommand = """ + create table IF NOT EXISTS %s ( + ModuleGuid TEXT NOT NULL, + ModuleVersion TEXT NOT NULL, + ModuleName TEXT NOT NULL, + InstallTime REAL NOT NULL, + DpGuid TEXT, + DpVersion TEXT, + InstallPath TEXT NOT NULL, + PRIMARY KEY (ModuleGuid, ModuleVersion, ModuleName, InstallPath) + )""" % self.StandaloneModTable + self.Cur.execute(SqlCommand) + + SqlCommand = """ + create table IF NOT EXISTS %s ( + ModuleGuid TEXT NOT NULL, + ModuleVersion TEXT NOT NULL, + ModuleName TEXT NOT NULL, + InstallPath TEXT NOT NULL, + DepexGuid TEXT, + DepexVersion TEXT + )""" % self.ModDepexTable + self.Cur.execute(SqlCommand) + + self.Conn.commit() + + Logger.Verbose(ST.MSG_INIT_IPI_FINISH) + + def RollBack(self): + self.Conn.rollback() + + def Commit(self): + self.Conn.commit() + + ## Add a distribution install information from DpObj + # + # @param DpObj: + # @param NewDpPkgFileName: New DpPkg File Name + # @param DpPkgFileName: DpPkg File Name + # @param RePackage: A RePackage + # + def AddDPObject(self, DpObj, NewDpPkgFileName, DpPkgFileName, RePackage): + try: + for PkgKey in DpObj.PackageSurfaceArea.keys(): + PkgGuid = PkgKey[0] + PkgVersion = PkgKey[1] + PkgInstallPath = PkgKey[2] + self._AddPackage(PkgGuid, PkgVersion, DpObj.Header.GetGuid(), \ + DpObj.Header.GetVersion(), PkgInstallPath) + PkgObj = DpObj.PackageSurfaceArea[PkgKey] + for ModKey in PkgObj.GetModuleDict().keys(): + ModGuid = ModKey[0] + ModVersion = ModKey[1] + ModName = ModKey[2] + ModInstallPath = ModKey[3] + ModInstallPath = \ + os.path.normpath(os.path.join(PkgInstallPath, ModInstallPath)) + self._AddModuleInPackage(ModGuid, ModVersion, ModName, PkgGuid, \ + PkgVersion, ModInstallPath) + ModObj = PkgObj.GetModuleDict()[ModKey] + for Dep in ModObj.GetPackageDependencyList(): + DepexGuid = Dep.GetGuid() + DepexVersion = Dep.GetVersion() + self._AddModuleDepex(ModGuid, ModVersion, ModName, ModInstallPath, \ + DepexGuid, DepexVersion) + for (FilePath, Md5Sum) in PkgObj.FileList: + self._AddDpFilePathList(DpObj.Header.GetGuid(), \ + DpObj.Header.GetVersion(), FilePath, \ + Md5Sum) + + for ModKey in DpObj.ModuleSurfaceArea.keys(): + ModGuid = ModKey[0] + ModVersion = ModKey[1] + ModName = ModKey[2] + ModInstallPath = ModKey[3] + self._AddStandaloneModule(ModGuid, ModVersion, ModName, \ + DpObj.Header.GetGuid(), \ + DpObj.Header.GetVersion(), \ + ModInstallPath) + ModObj = DpObj.ModuleSurfaceArea[ModKey] + for Dep in ModObj.GetPackageDependencyList(): + DepexGuid = Dep.GetGuid() + DepexVersion = Dep.GetVersion() + self._AddModuleDepex(ModGuid, ModVersion, ModName, ModInstallPath, \ + DepexGuid, DepexVersion) + for (Path, Md5Sum) in ModObj.FileList: + self._AddDpFilePathList(DpObj.Header.GetGuid(), \ + DpObj.Header.GetVersion(), \ + Path, Md5Sum) + + # + # add tool/misc files + # + for (Path, Md5Sum) in DpObj.FileList: + self._AddDpFilePathList(DpObj.Header.GetGuid(), \ + DpObj.Header.GetVersion(), Path, Md5Sum) + + self._AddDp(DpObj.Header.GetGuid(), DpObj.Header.GetVersion(), \ + NewDpPkgFileName, DpPkgFileName, RePackage) + + except sqlite3.IntegrityError as DetailMsg: + Logger.Error("UPT", + UPT_DB_UPDATE_ERROR, + ST.ERR_UPT_DB_UPDATE_ERROR, + ExtraData = DetailMsg + ) + + ## Add a distribution install information + # + # @param Guid Guid of the distribution package + # @param Version Version of the distribution package + # @param NewDpFileName the saved filename of distribution package file + # @param DistributionFileName the filename of distribution package file + # + def _AddDp(self, Guid, Version, NewDpFileName, DistributionFileName, \ + RePackage): + + if Version is None or len(Version.strip()) == 0: + Version = 'N/A' + + # + # Add newly installed DP information to DB. + # + if NewDpFileName is None or len(NewDpFileName.strip()) == 0: + PkgFileName = 'N/A' + else: + PkgFileName = NewDpFileName + CurrentTime = time.time() + SqlCommand = \ + """insert into %s values('%s', '%s', %s, '%s', '%s', '%s')""" % \ + (self.DpTable, Guid, Version, CurrentTime, PkgFileName, \ + DistributionFileName, str(RePackage).upper()) + self.Cur.execute(SqlCommand) + + + ## Add a file list from DP + # + # @param DpGuid: A DpGuid + # @param DpVersion: A DpVersion + # @param Path: A Path + # @param Path: A Md5Sum + # + def _AddDpFilePathList(self, DpGuid, DpVersion, Path, Md5Sum): + Path = os.path.normpath(Path) + if pf.system() == 'Windows': + if Path.startswith(self.Workspace): + Path = Path[len(self.Workspace):] + else: + if Path.startswith(self.Workspace + os.sep): + Path = Path[len(self.Workspace)+1:] + SqlCommand = """insert into %s values('%s', '%s', '%s', '%s')""" % \ + (self.DpFileListTable, Path, DpGuid, DpVersion, Md5Sum) + + self.Cur.execute(SqlCommand) + + ## Add a package install information + # + # @param Guid: A package guid + # @param Version: A package version + # @param DpGuid: A DpGuid + # @param DpVersion: A DpVersion + # @param Path: A Path + # + def _AddPackage(self, Guid, Version, DpGuid=None, DpVersion=None, Path=''): + + if Version is None or len(Version.strip()) == 0: + Version = 'N/A' + + if DpGuid is None or len(DpGuid.strip()) == 0: + DpGuid = 'N/A' + + if DpVersion is None or len(DpVersion.strip()) == 0: + DpVersion = 'N/A' + + # + # Add newly installed package information to DB. + # + CurrentTime = time.time() + SqlCommand = \ + """insert into %s values('%s', '%s', %s, '%s', '%s', '%s')""" % \ + (self.PkgTable, Guid, Version, CurrentTime, DpGuid, DpVersion, Path) + self.Cur.execute(SqlCommand) + + ## Add a module that from a package install information + # + # @param Guid: Module Guid + # @param Version: Module version + # @param Name: Module Name + # @param PkgGuid: Package Guid + # @param PkgVersion: Package version + # @param Path: Package relative path that module installs + # + def _AddModuleInPackage(self, Guid, Version, Name, PkgGuid=None, \ + PkgVersion=None, Path=''): + + if Version is None or len(Version.strip()) == 0: + Version = 'N/A' + + if PkgGuid is None or len(PkgGuid.strip()) == 0: + PkgGuid = 'N/A' + + if PkgVersion is None or len(PkgVersion.strip()) == 0: + PkgVersion = 'N/A' + + if os.name == 'posix': + Path = Path.replace('\\', os.sep) + else: + Path = Path.replace('/', os.sep) + + # + # Add module from package information to DB. + # + CurrentTime = time.time() + SqlCommand = \ + """insert into %s values('%s', '%s', '%s', %s, '%s', '%s', '%s')""" % \ + (self.ModInPkgTable, Guid, Version, Name, CurrentTime, PkgGuid, PkgVersion, \ + Path) + self.Cur.execute(SqlCommand) + + ## Add a module that is standalone install information + # + # @param Guid: a module Guid + # @param Version: a module Version + # @param Name: a module name + # @param DpGuid: a DpGuid + # @param DpVersion: a DpVersion + # @param Path: path + # + def _AddStandaloneModule(self, Guid, Version, Name, DpGuid=None, \ + DpVersion=None, Path=''): + + if Version is None or len(Version.strip()) == 0: + Version = 'N/A' + + if DpGuid is None or len(DpGuid.strip()) == 0: + DpGuid = 'N/A' + + if DpVersion is None or len(DpVersion.strip()) == 0: + DpVersion = 'N/A' + + # + # Add module standalone information to DB. + # + CurrentTime = time.time() + SqlCommand = \ + """insert into %s values('%s', '%s', '%s', %s, '%s', '%s', '%s')""" % \ + (self.StandaloneModTable, Guid, Version, Name, CurrentTime, DpGuid, \ + DpVersion, Path) + self.Cur.execute(SqlCommand) + + ## Add a module depex + # + # @param Guid: a module Guid + # @param Version: a module Version + # @param Name: a module name + # @param DepexGuid: a module DepexGuid + # @param DepexVersion: a module DepexVersion + # + def _AddModuleDepex(self, Guid, Version, Name, Path, DepexGuid=None, \ + DepexVersion=None): + + if DepexGuid is None or len(DepexGuid.strip()) == 0: + DepexGuid = 'N/A' + + if DepexVersion is None or len(DepexVersion.strip()) == 0: + DepexVersion = 'N/A' + + if os.name == 'posix': + Path = Path.replace('\\', os.sep) + else: + Path = Path.replace('/', os.sep) + + # + # Add module depex information to DB. + # + SqlCommand = """insert into %s values('%s', '%s', '%s', '%s', '%s', '%s')"""\ + % (self.ModDepexTable, Guid, Version, Name, Path, DepexGuid, DepexVersion) + self.Cur.execute(SqlCommand) + + ## Remove a distribution install information, if no version specified, + # remove all DPs with this Guid. + # + # @param DpGuid: guid of dpex + # @param DpVersion: version of dpex + # + def RemoveDpObj(self, DpGuid, DpVersion): + + PkgList = self.GetPackageListFromDp(DpGuid, DpVersion) + # + # delete from ModDepex the standalone module's dependency + # + SqlCommand = \ + """delete from ModDepexInfo where ModDepexInfo.ModuleGuid in + (select ModuleGuid from StandaloneModInfo as B where B.DpGuid = '%s' + and B.DpVersion = '%s') + and ModDepexInfo.ModuleVersion in + (select ModuleVersion from StandaloneModInfo as B + where B.DpGuid = '%s' and B.DpVersion = '%s') + and ModDepexInfo.ModuleName in + (select ModuleName from StandaloneModInfo as B + where B.DpGuid = '%s' and B.DpVersion = '%s') + and ModDepexInfo.InstallPath in + (select InstallPath from StandaloneModInfo as B + where B.DpGuid = '%s' and B.DpVersion = '%s') """ % \ + (DpGuid, DpVersion, DpGuid, DpVersion, DpGuid, DpVersion, DpGuid, DpVersion) + + self.Cur.execute(SqlCommand) + # + # delete from ModDepex the from pkg module's dependency + # + for Pkg in PkgList: + + SqlCommand = \ + """delete from ModDepexInfo where ModDepexInfo.ModuleGuid in + (select ModuleGuid from ModInPkgInfo + where ModInPkgInfo.PackageGuid ='%s' and + ModInPkgInfo.PackageVersion = '%s') + and ModDepexInfo.ModuleVersion in + (select ModuleVersion from ModInPkgInfo + where ModInPkgInfo.PackageGuid ='%s' and + ModInPkgInfo.PackageVersion = '%s') + and ModDepexInfo.ModuleName in + (select ModuleName from ModInPkgInfo + where ModInPkgInfo.PackageGuid ='%s' and + ModInPkgInfo.PackageVersion = '%s') + and ModDepexInfo.InstallPath in + (select InstallPath from ModInPkgInfo where + ModInPkgInfo.PackageGuid ='%s' + and ModInPkgInfo.PackageVersion = '%s')""" \ + % (Pkg[0], Pkg[1], Pkg[0], Pkg[1], Pkg[0], Pkg[1], Pkg[0], Pkg[1]) + + self.Cur.execute(SqlCommand) + # + # delete the standalone module + # + SqlCommand = \ + """delete from %s where DpGuid ='%s' and DpVersion = '%s'""" % \ + (self.StandaloneModTable, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + # + # delete the from pkg module + # + for Pkg in PkgList: + SqlCommand = \ + """delete from %s where %s.PackageGuid ='%s' + and %s.PackageVersion = '%s'""" % \ + (self.ModInPkgTable, self.ModInPkgTable, Pkg[0], \ + self.ModInPkgTable, Pkg[1]) + self.Cur.execute(SqlCommand) + # + # delete packages + # + SqlCommand = \ + """delete from %s where DpGuid ='%s' and DpVersion = '%s'""" % \ + (self.PkgTable, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + # + # delete file list from DP + # + SqlCommand = \ + """delete from %s where DpGuid ='%s' and DpVersion = '%s'""" % \ + (self.DpFileListTable, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + # + # delete DP + # + SqlCommand = \ + """delete from %s where DpGuid ='%s' and DpVersion = '%s'""" % \ + (self.DpTable, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + + #self.Conn.commit() + + ## Get a list of distribution install information. + # + # @param Guid: distribution package guid + # @param Version: distribution package version + # + def GetDp(self, Guid, Version): + + if Version is None or len(Version.strip()) == 0: + Version = 'N/A' + Logger.Verbose(ST.MSG_GET_DP_INSTALL_LIST) + (DpGuid, DpVersion) = (Guid, Version) + SqlCommand = """select * from %s where DpGuid ='%s'""" % \ + (self.DpTable, DpGuid) + self.Cur.execute(SqlCommand) + + else: + Logger.Verbose(ST.MSG_GET_DP_INSTALL_INFO_START) + (DpGuid, DpVersion) = (Guid, Version) + SqlCommand = \ + """select * from %s where DpGuid ='%s' and DpVersion = '%s'""" % \ + (self.DpTable, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + + DpList = [] + for DpInfo in self.Cur: + DpGuid = DpInfo[0] + DpVersion = DpInfo[1] + InstallTime = DpInfo[2] + PkgFileName = DpInfo[3] + DpList.append((DpGuid, DpVersion, InstallTime, PkgFileName)) + + Logger.Verbose(ST.MSG_GET_DP_INSTALL_INFO_FINISH) + return DpList + + ## Get a list of distribution install dirs + # + # @param Guid: distribution package guid + # @param Version: distribution package version + # + def GetDpInstallDirList(self, Guid, Version): + SqlCommand = """select InstallPath from PkgInfo where DpGuid = '%s' and DpVersion = '%s'""" % (Guid, Version) + self.Cur.execute(SqlCommand) + DirList = [] + for Result in self.Cur: + if Result[0] not in DirList: + DirList.append(Result[0]) + + SqlCommand = """select InstallPath from StandaloneModInfo where DpGuid = '%s' and DpVersion = '%s'""" % \ + (Guid, Version) + self.Cur.execute(SqlCommand) + for Result in self.Cur: + if Result[0] not in DirList: + DirList.append(Result[0]) + + return DirList + + + ## Get a list of distribution install file path information. + # + # @param Guid: distribution package guid + # @param Version: distribution package version + # + def GetDpFileList(self, Guid, Version): + + (DpGuid, DpVersion) = (Guid, Version) + SqlCommand = \ + """select * from %s where DpGuid ='%s' and DpVersion = '%s'""" % \ + (self.DpFileListTable, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + + PathList = [] + for Result in self.Cur: + Path = Result[0] + Md5Sum = Result[3] + PathList.append((os.path.join(self.Workspace, Path), Md5Sum)) + + return PathList + + ## Get files' repackage attribute if present that are installed into current workspace + # + # @retval FileDict: a Dict of file, key is file path, value is (DpGuid, DpVersion, NewDpFileName, RePackage) + # + def GetRePkgDict(self): + SqlCommand = """select * from %s """ % (self.DpTable) + self.Cur.execute(SqlCommand) + + DpInfoList = [] + for Result in self.Cur: + DpInfoList.append(Result) + + FileDict = {} + for Result in DpInfoList: + DpGuid = Result[0] + DpVersion = Result[1] + NewDpFileName = Result[3] + RePackage = Result[5] + if RePackage == 'TRUE': + RePackage = True + else: + RePackage = False + for FileInfo in self.GetDpFileList(DpGuid, DpVersion): + PathInfo = FileInfo[0] + FileDict[PathInfo] = DpGuid, DpVersion, NewDpFileName, RePackage + + return FileDict + + ## Get (Guid, Version) from distribution file name information. + # + # @param DistributionFile: Distribution File + # + def GetDpByName(self, DistributionFile): + SqlCommand = """select * from %s where NewPkgFileName = '%s'""" % \ + (self.DpTable, DistributionFile) + self.Cur.execute(SqlCommand) + + for Result in self.Cur: + DpGuid = Result[0] + DpVersion = Result[1] + NewDpFileName = Result[3] + + return (DpGuid, DpVersion, NewDpFileName) + else: + return (None, None, None) + + ## Get a list of package information. + # + # @param Guid: package guid + # @param Version: package version + # + def GetPackage(self, Guid, Version, DpGuid='', DpVersion=''): + + if DpVersion == '' or DpGuid == '': + + (PackageGuid, PackageVersion) = (Guid, Version) + SqlCommand = """select * from %s where PackageGuid ='%s' + and PackageVersion = '%s'""" % (self.PkgTable, PackageGuid, \ + PackageVersion) + self.Cur.execute(SqlCommand) + + elif Version is None or len(Version.strip()) == 0: + + SqlCommand = """select * from %s where PackageGuid ='%s'""" % \ + (self.PkgTable, Guid) + self.Cur.execute(SqlCommand) + else: + (PackageGuid, PackageVersion) = (Guid, Version) + SqlCommand = """select * from %s where PackageGuid ='%s' and + PackageVersion = '%s' + and DpGuid = '%s' and DpVersion = '%s'""" % \ + (self.PkgTable, PackageGuid, PackageVersion, \ + DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + + PkgList = [] + for PkgInfo in self.Cur: + PkgGuid = PkgInfo[0] + PkgVersion = PkgInfo[1] + InstallTime = PkgInfo[2] + InstallPath = PkgInfo[5] + PkgList.append((PkgGuid, PkgVersion, InstallTime, DpGuid, \ + DpVersion, InstallPath)) + + return PkgList + + + ## Get a list of module in package information. + # + # @param Guid: A module guid + # @param Version: A module version + # + def GetModInPackage(self, Guid, Version, Name, Path, PkgGuid='', PkgVersion=''): + (ModuleGuid, ModuleVersion, ModuleName, InstallPath) = (Guid, Version, Name, Path) + if PkgVersion == '' or PkgGuid == '': + SqlCommand = """select * from %s where ModuleGuid ='%s' and + ModuleVersion = '%s' and InstallPath = '%s' + and ModuleName = '%s'""" % (self.ModInPkgTable, ModuleGuid, \ + ModuleVersion, InstallPath, ModuleName) + self.Cur.execute(SqlCommand) + else: + SqlCommand = """select * from %s where ModuleGuid ='%s' and + ModuleVersion = '%s' and InstallPath = '%s' + and ModuleName = '%s' and PackageGuid ='%s' + and PackageVersion = '%s' + """ % (self.ModInPkgTable, ModuleGuid, \ + ModuleVersion, InstallPath, ModuleName, PkgGuid, PkgVersion) + self.Cur.execute(SqlCommand) + + ModList = [] + for ModInfo in self.Cur: + ModGuid = ModInfo[0] + ModVersion = ModInfo[1] + InstallTime = ModInfo[2] + InstallPath = ModInfo[5] + ModList.append((ModGuid, ModVersion, InstallTime, PkgGuid, \ + PkgVersion, InstallPath)) + + return ModList + + ## Get a list of module standalone. + # + # @param Guid: A module guid + # @param Version: A module version + # + def GetStandaloneModule(self, Guid, Version, Name, Path, DpGuid='', DpVersion=''): + (ModuleGuid, ModuleVersion, ModuleName, InstallPath) = (Guid, Version, Name, Path) + if DpGuid == '': + SqlCommand = """select * from %s where ModuleGuid ='%s' and + ModuleVersion = '%s' and InstallPath = '%s' + and ModuleName = '%s'""" % (self.StandaloneModTable, ModuleGuid, \ + ModuleVersion, InstallPath, ModuleName) + self.Cur.execute(SqlCommand) + + else: + SqlCommand = """select * from %s where ModuleGuid ='%s' and + ModuleVersion = '%s' and InstallPath = '%s' and ModuleName = '%s' and DpGuid ='%s' and DpVersion = '%s' + """ % (self.StandaloneModTable, ModuleGuid, \ + ModuleVersion, ModuleName, InstallPath, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + + ModList = [] + for ModInfo in self.Cur: + ModGuid = ModInfo[0] + ModVersion = ModInfo[1] + InstallTime = ModInfo[2] + InstallPath = ModInfo[5] + ModList.append((ModGuid, ModVersion, InstallTime, DpGuid, \ + DpVersion, InstallPath)) + + return ModList + + ## Get a list of module information that comes from DP. + # + # @param DpGuid: A Distribution Guid + # @param DpVersion: A Distribution version + # + def GetSModInsPathListFromDp(self, DpGuid, DpVersion): + + PathList = [] + SqlCommand = """select InstallPath from %s where DpGuid ='%s' + and DpVersion = '%s' + """ % (self.StandaloneModTable, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + + for Result in self.Cur: + InstallPath = Result[0] + PathList.append(InstallPath) + + return PathList + + ## Get a list of package information. + # + # @param DpGuid: A Distribution Guid + # @param DpVersion: A Distribution version + # + def GetPackageListFromDp(self, DpGuid, DpVersion): + + SqlCommand = """select * from %s where DpGuid ='%s' and + DpVersion = '%s' """ % (self.PkgTable, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + + PkgList = [] + for PkgInfo in self.Cur: + PkgGuid = PkgInfo[0] + PkgVersion = PkgInfo[1] + InstallPath = PkgInfo[5] + PkgList.append((PkgGuid, PkgVersion, InstallPath)) + + return PkgList + + ## Get a list of modules that depends on package information from a DP. + # + # @param DpGuid: A Distribution Guid + # @param DpVersion: A Distribution version + # + def GetDpDependentModuleList(self, DpGuid, DpVersion): + + ModList = [] + PkgList = self.GetPackageListFromDp(DpGuid, DpVersion) + if len(PkgList) > 0: + return ModList + + for Pkg in PkgList: + # + # get all in-package modules that depends on current + # Pkg (Guid match, Version match or NA) but not belong to + # current Pkg + # + SqlCommand = """select t1.ModuleGuid, t1.ModuleVersion, + t1.InstallPath from %s as t1, %s as t2 where + t1.ModuleGuid = t2.ModuleGuid and + t1.ModuleVersion = t2.ModuleVersion and t2.DepexGuid ='%s' + and (t2.DepexVersion = '%s' or t2.DepexVersion = 'N/A') and + t1.PackageGuid != '%s' and t1.PackageVersion != '%s' + """ % (self.ModInPkgTable, \ + self.ModDepexTable, Pkg[0], Pkg[1], Pkg[0], \ + Pkg[1]) + self.Cur.execute(SqlCommand) + for ModInfo in self.Cur: + ModGuid = ModInfo[0] + ModVersion = ModInfo[1] + InstallPath = ModInfo[2] + ModList.append((ModGuid, ModVersion, InstallPath)) + + # + # get all modules from standalone modules that depends on current + #Pkg (Guid match, Version match or NA) but not in current dp + # + SqlCommand = \ + """select t1.ModuleGuid, t1.ModuleVersion, t1.InstallPath + from %s as t1, %s as t2 where t1.ModuleGuid = t2.ModuleGuid and + t1.ModuleVersion = t2.ModuleVersion and t2.DepexGuid ='%s' + and (t2.DepexVersion = '%s' or t2.DepexVersion = 'N/A') and + t1.DpGuid != '%s' and t1.DpVersion != '%s' + """ % \ + (self.StandaloneModTable, self.ModDepexTable, Pkg[0], \ + Pkg[1], DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + for ModInfo in self.Cur: + ModGuid = ModInfo[0] + ModVersion = ModInfo[1] + InstallPath = ModInfo[2] + ModList.append((ModGuid, ModVersion, InstallPath)) + + + return ModList + + ## Get Dp's list of modules. + # + # @param DpGuid: A Distribution Guid + # @param DpVersion: A Distribution version + # + def GetDpModuleList(self, DpGuid, DpVersion): + ModList = [] + # + # get Dp module list from the DpFileList table + # + SqlCommand = """select FilePath + from %s + where DpGuid = '%s' and DpVersion = '%s' and + FilePath like '%%.inf' + """ % (self.DpFileListTable, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + for ModuleInfo in self.Cur: + FilePath = ModuleInfo[0] + ModList.append(os.path.join(self.Workspace, FilePath)) + + return ModList + + + ## Get a module depex + # + # @param DpGuid: A module Guid + # @param DpVersion: A module version + # @param Path: + # + def GetModuleDepex(self, Guid, Version, Path): + + # + # Get module depex information to DB. + # + SqlCommand = """select * from %s where ModuleGuid ='%s' and + ModuleVersion = '%s' and InstallPath ='%s' + """ % (self.ModDepexTable, Guid, Version, Path) + self.Cur.execute(SqlCommand) + + + DepexList = [] + for DepInfo in self.Cur: + DepexGuid = DepInfo[3] + DepexVersion = DepInfo[4] + DepexList.append((DepexGuid, DepexVersion)) + + return DepexList + + ## Inventory the distribution installed to current workspace + # + # Inventory the distribution installed to current workspace + # + def InventoryDistInstalled(self): + SqlCommand = """select * from %s """ % (self.DpTable) + self.Cur.execute(SqlCommand) + + DpInfoList = [] + for Result in self.Cur: + DpGuid = Result[0] + DpVersion = Result[1] + DpAliasName = Result[3] + DpFileName = Result[4] + DpInfoList.append((DpGuid, DpVersion, DpFileName, DpAliasName)) + + return DpInfoList + + ## Close entire database + # + # Close the connection and cursor + # + def CloseDb(self): + # + # drop the dummy table + # + SqlCommand = """ + drop table IF EXISTS %s + """ % self.DummyTable + self.Cur.execute(SqlCommand) + self.Conn.commit() + + self.Cur.close() + self.Conn.close() + + ## Convert To Sql String + # + # 1. Replace "'" with "''" in each item of StringList + # + # @param StringList: A list for strings to be converted + # + def __ConvertToSqlString(self, StringList): + if self.DpTable: + pass + return list(map(lambda s: s.replace("'", "''"), StringList)) + + + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/PackageFile.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/PackageFile.py new file mode 100755 index 00000000..c45ca7d7 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/PackageFile.py @@ -0,0 +1,250 @@ +## @file +# +# PackageFile class represents the zip file of a distribution package. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +PackageFile +''' + +## +# Import Modules +# +import os.path +import zipfile +import tempfile +import platform + +from Logger.ToolError import FILE_OPEN_FAILURE +from Logger.ToolError import FILE_CHECKSUM_FAILURE +from Logger.ToolError import FILE_NOT_FOUND +from Logger.ToolError import FILE_DECOMPRESS_FAILURE +from Logger.ToolError import FILE_UNKNOWN_ERROR +from Logger.ToolError import FILE_WRITE_FAILURE +from Logger.ToolError import FILE_COMPRESS_FAILURE +import Logger.Log as Logger +from Logger import StringTable as ST +from Library.Misc import CreateDirectory +from Library.Misc import RemoveDirectory +from Core.FileHook import __FileHookOpen__ +from Common.MultipleWorkspace import MultipleWorkspace as mws + + +class PackageFile: + def __init__(self, FileName, Mode="r"): + self._FileName = FileName + if Mode not in ["r", "w", "a"]: + Mode = "r" + try: + self._ZipFile = zipfile.ZipFile(FileName, Mode, \ + zipfile.ZIP_DEFLATED) + self._Files = {} + for Filename in self._ZipFile.namelist(): + self._Files[os.path.normpath(Filename)] = Filename + except BaseException as Xstr: + Logger.Error("PackagingTool", FILE_OPEN_FAILURE, + ExtraData="%s (%s)" % (FileName, str(Xstr))) + + BadFile = self._ZipFile.testzip() + if BadFile is not None: + Logger.Error("PackagingTool", FILE_CHECKSUM_FAILURE, + ExtraData="[%s] in %s" % (BadFile, FileName)) + + def GetZipFile(self): + return self._ZipFile + + ## Get file name + # + def __str__(self): + return self._FileName + + ## Extract the file + # + # @param To: the destination file + # + def Unpack(self, ToDest): + for FileN in self._ZipFile.namelist(): + ToFile = os.path.normpath(os.path.join(ToDest, FileN)) + Msg = "%s -> %s" % (FileN, ToFile) + Logger.Info(Msg) + self.Extract(FileN, ToFile) + + ## Extract the file + # + # @param File: the extracted file + # @param ToFile: the destination file + # + def UnpackFile(self, File, ToFile): + File = File.replace('\\', '/') + if File in self._ZipFile.namelist(): + Msg = "%s -> %s" % (File, ToFile) + Logger.Info(Msg) + self.Extract(File, ToFile) + return ToFile + + return '' + + ## Extract the file + # + # @param Which: the source path + # @param ToDest: the destination path + # + def Extract(self, Which, ToDest): + Which = os.path.normpath(Which) + if Which not in self._Files: + Logger.Error("PackagingTool", FILE_NOT_FOUND, + ExtraData="[%s] in %s" % (Which, self._FileName)) + try: + FileContent = self._ZipFile.read(self._Files[Which]) + except BaseException as Xstr: + Logger.Error("PackagingTool", FILE_DECOMPRESS_FAILURE, + ExtraData="[%s] in %s (%s)" % (Which, \ + self._FileName, \ + str(Xstr))) + try: + CreateDirectory(os.path.dirname(ToDest)) + if os.path.exists(ToDest) and not os.access(ToDest, os.W_OK): + Logger.Warn("PackagingTool", \ + ST.WRN_FILE_NOT_OVERWRITTEN % ToDest) + return + else: + ToFile = __FileHookOpen__(ToDest, 'wb') + except BaseException as Xstr: + Logger.Error("PackagingTool", FILE_OPEN_FAILURE, + ExtraData="%s (%s)" % (ToDest, str(Xstr))) + + try: + ToFile.write(FileContent) + ToFile.close() + except BaseException as Xstr: + Logger.Error("PackagingTool", FILE_WRITE_FAILURE, + ExtraData="%s (%s)" % (ToDest, str(Xstr))) + + ## Remove the file + # + # @param Files: the removed files + # + def Remove(self, Files): + TmpDir = os.path.join(tempfile.gettempdir(), ".packaging") + if os.path.exists(TmpDir): + RemoveDirectory(TmpDir, True) + + os.mkdir(TmpDir) + self.Unpack(TmpDir) + for SinF in Files: + SinF = os.path.normpath(SinF) + if SinF not in self._Files: + Logger.Error("PackagingTool", FILE_NOT_FOUND, + ExtraData="%s is not in %s!" % \ + (SinF, self._FileName)) + self._Files.pop(SinF) + self._ZipFile.close() + + self._ZipFile = zipfile.ZipFile(self._FileName, "w", \ + zipfile.ZIP_DEFLATED) + Cwd = os.getcwd() + os.chdir(TmpDir) + self.PackFiles(self._Files) + os.chdir(Cwd) + RemoveDirectory(TmpDir, True) + + ## Pack the files under Top directory, the directory shown in the zipFile start from BaseDir, + # BaseDir should be the parent directory of the Top directory, for example, + # Pack(Workspace\Dir1, Workspace) will pack files under Dir1, and the path in the zipfile will + # start from Workspace + # + # @param Top: the top directory + # @param BaseDir: the base directory + # + def Pack(self, Top, BaseDir): + if not os.path.isdir(Top): + Logger.Error("PackagingTool", FILE_UNKNOWN_ERROR, \ + "%s is not a directory!" %Top) + + FilesToPack = [] + Cwd = os.getcwd() + os.chdir(BaseDir) + RelaDir = Top[Top.upper().find(BaseDir.upper()).\ + join(len(BaseDir).join(1)):] + + for Root, Dirs, Files in os.walk(RelaDir): + if 'CVS' in Dirs: + Dirs.remove('CVS') + if '.svn' in Dirs: + Dirs.remove('.svn') + + for Dir in Dirs: + if Dir.startswith('.'): + Dirs.remove(Dir) + for File1 in Files: + if File1.startswith('.'): + continue + ExtName = os.path.splitext(File1)[1] + # + # skip '.dec', '.inf', '.dsc', '.fdf' files + # + if ExtName.lower() in ['.dec', '.inf', '.dsc', '.fdf']: + continue + FilesToPack.append(os.path.join(Root, File1)) + self.PackFiles(FilesToPack) + os.chdir(Cwd) + + ## Pack the file + # + # @param Files: the files to pack + # + def PackFiles(self, Files): + for File in Files: + Cwd = os.getcwd() + os.chdir(mws.getWs(mws.WORKSPACE, File)) + self.PackFile(File) + os.chdir(Cwd) + + ## Pack the file + # + # @param File: the files to pack + # @param ArcName: the Arc Name + # + def PackFile(self, File, ArcName=None): + try: + # + # avoid packing same file multiple times + # + if platform.system() != 'Windows': + File = File.replace('\\', '/') + ZipedFilesNameList = self._ZipFile.namelist() + for ZipedFile in ZipedFilesNameList: + if File == os.path.normpath(ZipedFile): + return + Logger.Info("packing ..." + File) + self._ZipFile.write(File, ArcName) + except BaseException as Xstr: + Logger.Error("PackagingTool", FILE_COMPRESS_FAILURE, + ExtraData="%s (%s)" % (File, str(Xstr))) + + ## Write data to the packed file + # + # @param Data: data to write + # @param ArcName: the Arc Name + # + def PackData(self, Data, ArcName): + try: + if os.path.splitext(ArcName)[1].lower() == '.pkg': + Data = Data.encode('utf_8') + self._ZipFile.writestr(ArcName, Data) + except BaseException as Xstr: + Logger.Error("PackagingTool", FILE_COMPRESS_FAILURE, + ExtraData="%s (%s)" % (ArcName, str(Xstr))) + + ## Close file + # + # + def Close(self): + self._ZipFile.close() + + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/__init__.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/__init__.py new file mode 100644 index 00000000..1b9f9b32 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Core/__init__.py @@ -0,0 +1,14 @@ +## @file +# Python 'Library' package initialization file. +# +# This file is required to make Python interpreter treat the directory +# as containing package. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +Core init file +''' diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/GenMetaFile/GenDecFile.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/GenMetaFile/GenDecFile.py new file mode 100755 index 00000000..6d79278c --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/GenMetaFile/GenDecFile.py @@ -0,0 +1,683 @@ +## @file GenDecFile.py +# +# This file contained the logical of transfer package object to DEC files. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +GenDEC +''' +import os +import stat +import codecs +from hashlib import md5 +from Core.FileHook import __FileHookOpen__ +from Library.Parsing import GenSection +from Library.CommentGenerating import GenHeaderCommentSection +from Library.CommentGenerating import GenGenericCommentF +from Library.CommentGenerating import GenDecTailComment +from Library.CommentGenerating import _GetHelpStr +from Library.Misc import GuidStringToGuidStructureString +from Library.Misc import SaveFileOnChange +from Library.Misc import ConvertPath +from Library.Misc import GetLocalValue +from Library.DataType import TAB_SPACE_SPLIT +from Library.DataType import TAB_COMMA_SPLIT +from Library.DataType import END_OF_LINE +from Library.DataType import TAB_ARCH_COMMON +from Library.DataType import TAB_VALUE_SPLIT +from Library.DataType import TAB_COMMENT_SPLIT +from Library.DataType import TAB_PCD_VALIDRANGE +from Library.DataType import TAB_PCD_VALIDLIST +from Library.DataType import TAB_PCD_EXPRESSION +from Library.DataType import TAB_DEC_DEFINES_DEC_SPECIFICATION +from Library.DataType import TAB_DEC_DEFINES_PACKAGE_NAME +from Library.DataType import TAB_DEC_DEFINES_PACKAGE_GUID +from Library.DataType import TAB_DEC_DEFINES_PACKAGE_VERSION +from Library.DataType import TAB_DEC_DEFINES_PKG_UNI_FILE +from Library.DataType import TAB_DEC_PACKAGE_ABSTRACT +from Library.DataType import TAB_DEC_PACKAGE_DESCRIPTION +from Library.DataType import TAB_DEC_BINARY_ABSTRACT +from Library.DataType import TAB_DEC_BINARY_DESCRIPTION +from Library.DataType import TAB_LANGUAGE_EN_X +from Library.DataType import TAB_BINARY_HEADER_USERID +from Library.DataType import TAB_BINARY_HEADER_IDENTIFIER +from Library.DataType import TAB_COMMENT_EDK1_SPLIT +from Library.DataType import TAB_ENCODING_UTF16LE +from Library.DataType import TAB_CAPHEX_START +from Library.DataType import TAB_HEX_START +from Library.DataType import TAB_UNDERLINE_SPLIT +from Library.DataType import TAB_STR_TOKENERR +from Library.DataType import TAB_STR_TOKENCNAME +from Library.DataType import TAB_PCD_ERROR_SECTION_COMMENT +from Library.DataType import TAB_PCD_ERROR +from Library.DataType import TAB_SECTION_START +from Library.DataType import TAB_SECTION_END +from Library.DataType import TAB_SPLIT +import Library.DataType as DT +from Library.UniClassObject import FormatUniEntry +from Library.StringUtils import GetUniFileName + +def GenPcd(Package, Content): + # + # generate [Pcd] section + # .||| + # + ValidUsageDict = {} + for Pcd in Package.GetPcdList(): + # + # Generate generic comment + # + HelpTextList = Pcd.GetHelpTextList() + HelpStr = _GetHelpStr(HelpTextList) + CommentStr = GenGenericCommentF(HelpStr, 2) + + PromptList = Pcd.GetPromptList() + PromptStr = _GetHelpStr(PromptList) + CommentStr += GenGenericCommentF(PromptStr.strip(), 1, True) + + PcdErrList = Pcd.GetPcdErrorsList() + for PcdErr in PcdErrList: + CommentStr += GenPcdErrComment(PcdErr) + Statement = CommentStr + + CName = Pcd.GetCName() + TokenSpaceGuidCName = Pcd.GetTokenSpaceGuidCName() + DefaultValue = Pcd.GetDefaultValue() + DatumType = Pcd.GetDatumType() + Token = Pcd.GetToken() + ValidUsage = Pcd.GetValidUsage() + + if ValidUsage == 'FeaturePcd': + ValidUsage = 'PcdsFeatureFlag' + elif ValidUsage == 'PatchPcd': + ValidUsage = 'PcdsPatchableInModule' + elif ValidUsage == 'FixedPcd': + ValidUsage = 'PcdsFixedAtBuild' + elif ValidUsage == 'Pcd': + ValidUsage = 'PcdsDynamic' + elif ValidUsage == 'PcdEx': + ValidUsage = 'PcdsDynamicEx' + + if ValidUsage in ValidUsageDict: + NewSectionDict = ValidUsageDict[ValidUsage] + else: + NewSectionDict = {} + ValidUsageDict[ValidUsage] = NewSectionDict + Statement += TokenSpaceGuidCName + '.' + CName + Statement += '|' + DefaultValue + Statement += '|' + DatumType + Statement += '|' + Token + # + # generate tail comment + # + if Pcd.GetSupModuleList(): + Statement += GenDecTailComment(Pcd.GetSupModuleList()) + + ArchList = sorted(Pcd.GetSupArchList()) + SortedArch = ' '.join(ArchList) + if SortedArch in NewSectionDict: + NewSectionDict[SortedArch] = \ + NewSectionDict[SortedArch] + [Statement] + else: + NewSectionDict[SortedArch] = [Statement] + + for ValidUsage in ValidUsageDict: + Content += GenSection(ValidUsage, ValidUsageDict[ValidUsage], True, True) + + return Content + +def GenPcdErrorMsgSection(Package, Content): + if not Package.PcdErrorCommentDict: + return Content + + # + # Generate '# [Error.]' section + # + Content += END_OF_LINE + END_OF_LINE + SectionComment = TAB_COMMENT_SPLIT + END_OF_LINE + SectionComment += TAB_COMMENT_SPLIT + TAB_SPACE_SPLIT + TAB_PCD_ERROR_SECTION_COMMENT + END_OF_LINE + SectionComment += TAB_COMMENT_SPLIT + END_OF_LINE + TokenSpcCNameList = [] + + # + # Get TokenSpcCName list in PcdErrorCommentDict in Package object + # + for (TokenSpcCName, ErrorNumber) in Package.PcdErrorCommentDict: + if TokenSpcCName not in TokenSpcCNameList: + TokenSpcCNameList.append(TokenSpcCName) + + for TokenSpcCNameItem in TokenSpcCNameList: + SectionName = TAB_COMMENT_SPLIT + TAB_SPACE_SPLIT + TAB_SECTION_START + TAB_PCD_ERROR + \ + TAB_SPLIT + TokenSpcCNameItem + TAB_SECTION_END + END_OF_LINE + Content += SectionComment + Content += SectionName + for (TokenSpcCName, ErrorNumber) in Package.PcdErrorCommentDict: + if TokenSpcCNameItem == TokenSpcCName: + PcdErrorMsg = GetLocalValue(Package.PcdErrorCommentDict[(TokenSpcCName, ErrorNumber)]) + SectionItem = TAB_COMMENT_SPLIT + TAB_SPACE_SPLIT + TAB_SPACE_SPLIT + \ + ErrorNumber + TAB_SPACE_SPLIT + TAB_VALUE_SPLIT + TAB_SPACE_SPLIT + \ + PcdErrorMsg + END_OF_LINE + Content += SectionItem + + Content += TAB_COMMENT_SPLIT + return Content + +def GenGuidProtocolPpi(Package, Content): + # + # generate [Guids] section + # + NewSectionDict = {} + + LeftOffset = 46 + # Get the line offset need + # If the real one < the min one, use the min one + # else use the real one + for Guid in Package.GetGuidList(): + if len(Guid.GetCName()) > LeftOffset: + LeftOffset = len(Guid.GetCName()) + + # Generate + for Guid in Package.GetGuidList(): + # + # Generate generic comment + # + HelpTextList = Guid.GetHelpTextList() + HelpStr = _GetHelpStr(HelpTextList) + CommentStr = GenGenericCommentF(HelpStr, 2) + + Statement = CommentStr + CName = Guid.GetCName() + Value = GuidStringToGuidStructureString(Guid.GetGuid()) + Statement += CName.ljust(LeftOffset) + ' = ' + Value + # + # generate tail comment + # + if Guid.GetSupModuleList(): + Statement += GenDecTailComment(Guid.GetSupModuleList()) + ArchList = sorted(Guid.GetSupArchList()) + SortedArch = ' '.join(ArchList) + if SortedArch in NewSectionDict: + NewSectionDict[SortedArch] = \ + NewSectionDict[SortedArch] + [Statement] + else: + NewSectionDict[SortedArch] = [Statement] + + Content += GenSection('Guids', NewSectionDict, True, True) + + # + # generate [Protocols] section + # + NewSectionDict = {} + LeftOffset = 46 + # Get the line offset need + # If the real one < the min one, use the min one + # else use the real one + for Protocol in Package.GetProtocolList(): + if len(Protocol.GetCName()) > LeftOffset: + LeftOffset = len(Protocol.GetCName()) + + for Protocol in Package.GetProtocolList(): + # + # Generate generic comment + # + HelpTextList = Protocol.GetHelpTextList() + HelpStr = _GetHelpStr(HelpTextList) + CommentStr = GenGenericCommentF(HelpStr, 2) + + Statement = CommentStr + CName = Protocol.GetCName() + Value = GuidStringToGuidStructureString(Protocol.GetGuid()) + Statement += CName.ljust(LeftOffset) + ' = ' + Value + + # + # generate tail comment + # + if Protocol.GetSupModuleList(): + Statement += GenDecTailComment(Protocol.GetSupModuleList()) + ArchList = sorted(Protocol.GetSupArchList()) + SortedArch = ' '.join(ArchList) + if SortedArch in NewSectionDict: + NewSectionDict[SortedArch] = \ + NewSectionDict[SortedArch] + [Statement] + else: + NewSectionDict[SortedArch] = [Statement] + + Content += GenSection('Protocols', NewSectionDict, True, True) + + # + # generate [Ppis] section + # + NewSectionDict = {} + LeftOffset = 46 + # Get the line offset need + # If the real one < the min one, use the min one + # else use the real one + for Ppi in Package.GetPpiList(): + if len(Ppi.GetCName()) > LeftOffset: + LeftOffset = len(Ppi.GetCName()) + + for Ppi in Package.GetPpiList(): + # + # Generate generic comment + # + HelpTextList = Ppi.GetHelpTextList() + HelpStr = _GetHelpStr(HelpTextList) + CommentStr = GenGenericCommentF(HelpStr, 2) + + Statement = CommentStr + CName = Ppi.GetCName() + Value = GuidStringToGuidStructureString(Ppi.GetGuid()) + Statement += CName.ljust(LeftOffset) + ' = ' + Value + + # + # generate tail comment + # + if Ppi.GetSupModuleList(): + Statement += GenDecTailComment(Ppi.GetSupModuleList()) + ArchList = sorted(Ppi.GetSupArchList()) + SortedArch = ' '.join(ArchList) + if SortedArch in NewSectionDict: + NewSectionDict[SortedArch] = \ + NewSectionDict[SortedArch] + [Statement] + else: + NewSectionDict[SortedArch] = [Statement] + + Content += GenSection('Ppis', NewSectionDict, True, True) + + return Content + +## Transfer Package Object to Dec files +# +# Transfer all contents of a standard Package Object to a Dec file +# +# @param Package: A Package +# +def PackageToDec(Package, DistHeader = None): + # + # Init global information for the file + # + ContainerFile = Package.GetFullPath() + + Content = '' + + # + # Generate file header + # + PackageAbstract = GetLocalValue(Package.GetAbstract()) + PackageDescription = GetLocalValue(Package.GetDescription()) + PackageCopyright = '' + PackageLicense = '' + for (Lang, Copyright) in Package.GetCopyright(): + if Lang: + pass + PackageCopyright = Copyright + for (Lang, License) in Package.GetLicense(): + if Lang: + pass + PackageLicense = License + if not PackageAbstract and DistHeader: + PackageAbstract = GetLocalValue(DistHeader.GetAbstract()) + if not PackageDescription and DistHeader: + PackageDescription = GetLocalValue(DistHeader.GetDescription()) + if not PackageCopyright and DistHeader: + for (Lang, Copyright) in DistHeader.GetCopyright(): + PackageCopyright = Copyright + if not PackageLicense and DistHeader: + for (Lang, License) in DistHeader.GetLicense(): + PackageLicense = License + + # + # Generate header comment section of DEC file + # + Content += GenHeaderCommentSection(PackageAbstract, \ + PackageDescription, \ + PackageCopyright, \ + PackageLicense).replace('\r\n', '\n') + + # + # Generate Binary header + # + for UserExtension in Package.GetUserExtensionList(): + if UserExtension.GetUserID() == TAB_BINARY_HEADER_USERID \ + and UserExtension.GetIdentifier() == TAB_BINARY_HEADER_IDENTIFIER: + PackageBinaryAbstract = GetLocalValue(UserExtension.GetBinaryAbstract()) + PackageBinaryDescription = GetLocalValue(UserExtension.GetBinaryDescription()) + PackageBinaryCopyright = '' + PackageBinaryLicense = '' + for (Lang, Copyright) in UserExtension.GetBinaryCopyright(): + PackageBinaryCopyright = Copyright + for (Lang, License) in UserExtension.GetBinaryLicense(): + PackageBinaryLicense = License + if PackageBinaryAbstract and PackageBinaryDescription and \ + PackageBinaryCopyright and PackageBinaryLicense: + Content += GenHeaderCommentSection(PackageBinaryAbstract, + PackageBinaryDescription, + PackageBinaryCopyright, + PackageBinaryLicense, + True) + + # + # Generate PACKAGE_UNI_FILE for the Package + # + FileHeader = GenHeaderCommentSection(PackageAbstract, PackageDescription, PackageCopyright, PackageLicense, False, \ + TAB_COMMENT_EDK1_SPLIT) + GenPackageUNIEncodeFile(Package, FileHeader) + + # + # for each section, maintain a dict, sorted arch will be its key, + #statement list will be its data + # { 'Arch1 Arch2 Arch3': [statement1, statement2], + # 'Arch1' : [statement1, statement3] + # } + # + + # + # generate [Defines] section + # + LeftOffset = 31 + NewSectionDict = {TAB_ARCH_COMMON : []} + SpecialItemList = [] + + Statement = (u'%s ' % TAB_DEC_DEFINES_DEC_SPECIFICATION).ljust(LeftOffset) + u'= %s' % '0x00010017' + SpecialItemList.append(Statement) + + BaseName = Package.GetBaseName() + if BaseName.startswith('.') or BaseName.startswith('-'): + BaseName = '_' + BaseName + Statement = (u'%s ' % TAB_DEC_DEFINES_PACKAGE_NAME).ljust(LeftOffset) + u'= %s' % BaseName + SpecialItemList.append(Statement) + + Statement = (u'%s ' % TAB_DEC_DEFINES_PACKAGE_VERSION).ljust(LeftOffset) + u'= %s' % Package.GetVersion() + SpecialItemList.append(Statement) + + Statement = (u'%s ' % TAB_DEC_DEFINES_PACKAGE_GUID).ljust(LeftOffset) + u'= %s' % Package.GetGuid() + SpecialItemList.append(Statement) + + if Package.UNIFlag: + Statement = (u'%s ' % TAB_DEC_DEFINES_PKG_UNI_FILE).ljust(LeftOffset) + u'= %s' % Package.GetBaseName() + '.uni' + SpecialItemList.append(Statement) + + for SortedArch in NewSectionDict: + NewSectionDict[SortedArch] = \ + NewSectionDict[SortedArch] + SpecialItemList + Content += GenSection('Defines', NewSectionDict) + + # + # generate [Includes] section + # + NewSectionDict = {} + IncludeArchList = Package.GetIncludeArchList() + if IncludeArchList: + for Path, ArchList in IncludeArchList: + Statement = Path + ArchList.sort() + SortedArch = ' '.join(ArchList) + if SortedArch in NewSectionDict: + NewSectionDict[SortedArch] = \ + NewSectionDict[SortedArch] + [ConvertPath(Statement)] + else: + NewSectionDict[SortedArch] = [ConvertPath(Statement)] + + Content += GenSection('Includes', NewSectionDict) + + # + # generate [guids][protocols][ppis] sections + # + Content = GenGuidProtocolPpi(Package, Content) + + # + # generate [LibraryClasses] section + # + NewSectionDict = {} + for LibraryClass in Package.GetLibraryClassList(): + # + # Generate generic comment + # + HelpTextList = LibraryClass.GetHelpTextList() + HelpStr = _GetHelpStr(HelpTextList) + if HelpStr: + HelpStr = '@libraryclass' + HelpStr + CommentStr = GenGenericCommentF(HelpStr, 2, False, True) + + Statement = CommentStr + Name = LibraryClass.GetLibraryClass() + IncludeHeader = LibraryClass.GetIncludeHeader() + Statement += Name + '|' + ConvertPath(IncludeHeader) + # + # generate tail comment + # + if LibraryClass.GetSupModuleList(): + Statement += \ + GenDecTailComment(LibraryClass.GetSupModuleList()) + ArchList = sorted(LibraryClass.GetSupArchList()) + SortedArch = ' '.join(ArchList) + if SortedArch in NewSectionDict: + NewSectionDict[SortedArch] = \ + NewSectionDict[SortedArch] + [Statement] + else: + NewSectionDict[SortedArch] = [Statement] + + Content += GenSection('LibraryClasses', NewSectionDict, True, True) + + # + # Generate '# [Error.]' section + # + Content = GenPcdErrorMsgSection(Package, Content) + + Content = GenPcd(Package, Content) + + # + # generate [UserExtensions] section + # + NewSectionDict = {} + for UserExtension in Package.GetUserExtensionList(): + if UserExtension.GetUserID() == TAB_BINARY_HEADER_USERID and \ + UserExtension.GetIdentifier() == TAB_BINARY_HEADER_IDENTIFIER: + continue + + # Generate Private Section first + if UserExtension.GetUserID() == DT.TAB_INTEL and UserExtension.GetIdentifier() == DT.TAB_PRIVATE: + Content += '\n' + UserExtension.GetStatement() + continue + + Statement = UserExtension.GetStatement() + if not Statement: + continue + else: + LineList = Statement.split('\n') + NewStatement = "" + for Line in LineList: + NewStatement += " %s\n" % Line + + SectionList = [] + SectionName = 'UserExtensions' + UserId = UserExtension.GetUserID() + if UserId: + if '.' in UserId: + UserId = '"' + UserId + '"' + SectionName += '.' + UserId + if UserExtension.GetIdentifier(): + SectionName += '.' + '"' + UserExtension.GetIdentifier() + '"' + if not UserExtension.GetSupArchList(): + SectionList.append(SectionName) + else: + for Arch in UserExtension.GetSupArchList(): + SectionList.append(SectionName + '.' + Arch) + SectionName = ', '.join(SectionList) + SectionName = ''.join(['[', SectionName, ']\n']) + Content += '\n' + SectionName + NewStatement + + SaveFileOnChange(ContainerFile, Content, False) + if DistHeader.ReadOnly: + os.chmod(ContainerFile, stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH) + else: + os.chmod(ContainerFile, stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH|stat.S_IWUSR|stat.S_IWGRP|stat.S_IWOTH) + return ContainerFile + +## GenPackageUNIEncodeFile +# GenPackageUNIEncodeFile, default is a UCS-2LE encode file +# +def GenPackageUNIEncodeFile(PackageObject, UniFileHeader = '', Encoding=TAB_ENCODING_UTF16LE): + GenUNIFlag = False + OnlyLANGUAGE_EN_X = True + BinaryAbstract = [] + BinaryDescription = [] + # + # If more than one language code is used for any element that would be present in the PACKAGE_UNI_FILE, + # then the PACKAGE_UNI_FILE must be created. + # + for (Key, Value) in PackageObject.GetAbstract() + PackageObject.GetDescription(): + if Key == TAB_LANGUAGE_EN_X: + GenUNIFlag = True + else: + OnlyLANGUAGE_EN_X = False + + for UserExtension in PackageObject.GetUserExtensionList(): + if UserExtension.GetUserID() == TAB_BINARY_HEADER_USERID \ + and UserExtension.GetIdentifier() == TAB_BINARY_HEADER_IDENTIFIER: + for (Key, Value) in UserExtension.GetBinaryAbstract(): + if Key == TAB_LANGUAGE_EN_X: + GenUNIFlag = True + else: + OnlyLANGUAGE_EN_X = False + BinaryAbstract.append((Key, Value)) + + for (Key, Value) in UserExtension.GetBinaryDescription(): + if Key == TAB_LANGUAGE_EN_X: + GenUNIFlag = True + else: + OnlyLANGUAGE_EN_X = False + BinaryDescription.append((Key, Value)) + + for Pcd in PackageObject.GetPcdList(): + for TxtObj in Pcd.GetPromptList() + Pcd.GetHelpTextList(): + if TxtObj.GetLang() == TAB_LANGUAGE_EN_X: + GenUNIFlag = True + else: + OnlyLANGUAGE_EN_X = False + + for PcdError in Pcd.GetPcdErrorsList(): + if PcdError.GetErrorNumber().startswith('0x') or PcdError.GetErrorNumber().startswith('0X'): + for (Key, Value) in PcdError.GetErrorMessageList(): + if Key == TAB_LANGUAGE_EN_X: + GenUNIFlag = True + else: + OnlyLANGUAGE_EN_X = False + if not GenUNIFlag: + return + elif OnlyLANGUAGE_EN_X: + return + else: + PackageObject.UNIFlag = True + + if not os.path.exists(os.path.dirname(PackageObject.GetFullPath())): + os.makedirs(os.path.dirname(PackageObject.GetFullPath())) + + ContainerFile = GetUniFileName(os.path.dirname(PackageObject.GetFullPath()), PackageObject.GetBaseName()) + + Content = UniFileHeader + '\r\n' + Content += '\r\n' + + Content += FormatUniEntry('#string ' + TAB_DEC_PACKAGE_ABSTRACT, PackageObject.GetAbstract(), ContainerFile) + '\r\n' + + Content += FormatUniEntry('#string ' + TAB_DEC_PACKAGE_DESCRIPTION, PackageObject.GetDescription(), ContainerFile) \ + + '\r\n' + + Content += FormatUniEntry('#string ' + TAB_DEC_BINARY_ABSTRACT, BinaryAbstract, ContainerFile) + '\r\n' + + Content += FormatUniEntry('#string ' + TAB_DEC_BINARY_DESCRIPTION, BinaryDescription, ContainerFile) + '\r\n' + + PromptGenList = [] + HelpTextGenList = [] + for Pcd in PackageObject.GetPcdList(): + # Generate Prompt for each Pcd + PcdPromptStrName = '#string ' + 'STR_' + Pcd.GetTokenSpaceGuidCName() + '_' + Pcd.GetCName() + '_PROMPT ' + TokenValueList = [] + for TxtObj in Pcd.GetPromptList(): + Lang = TxtObj.GetLang() + PromptStr = TxtObj.GetString() + # + # Avoid generating the same PROMPT entry more than one time. + # + if (PcdPromptStrName, Lang) not in PromptGenList: + TokenValueList.append((Lang, PromptStr)) + PromptGenList.append((PcdPromptStrName, Lang)) + PromptString = FormatUniEntry(PcdPromptStrName, TokenValueList, ContainerFile) + '\r\n' + if PromptString not in Content: + Content += PromptString + + # Generate Help String for each Pcd + PcdHelpStrName = '#string ' + 'STR_' + Pcd.GetTokenSpaceGuidCName() + '_' + Pcd.GetCName() + '_HELP ' + TokenValueList = [] + for TxtObj in Pcd.GetHelpTextList(): + Lang = TxtObj.GetLang() + HelpStr = TxtObj.GetString() + # + # Avoid generating the same HELP entry more than one time. + # + if (PcdHelpStrName, Lang) not in HelpTextGenList: + TokenValueList.append((Lang, HelpStr)) + HelpTextGenList.append((PcdHelpStrName, Lang)) + HelpTextString = FormatUniEntry(PcdHelpStrName, TokenValueList, ContainerFile) + '\r\n' + if HelpTextString not in Content: + Content += HelpTextString + + # Generate PcdError for each Pcd if ErrorNo exist. + for PcdError in Pcd.GetPcdErrorsList(): + ErrorNo = PcdError.GetErrorNumber() + if ErrorNo.startswith(TAB_HEX_START) or ErrorNo.startswith(TAB_CAPHEX_START): + PcdErrStrName = '#string ' + TAB_STR_TOKENCNAME + TAB_UNDERLINE_SPLIT + Pcd.GetTokenSpaceGuidCName() \ + + TAB_UNDERLINE_SPLIT + TAB_STR_TOKENERR \ + + TAB_UNDERLINE_SPLIT + ErrorNo[2:] + PcdErrString = FormatUniEntry(PcdErrStrName, PcdError.GetErrorMessageList(), ContainerFile) + '\r\n' + if PcdErrString not in Content: + Content += PcdErrString + + File = codecs.open(ContainerFile, 'w', Encoding) + File.write(u'\uFEFF' + Content) + File.stream.close() + Md5Signature = md5(__FileHookOpen__(str(ContainerFile), 'rb').read()) + Md5Sum = Md5Signature.hexdigest() + if (ContainerFile, Md5Sum) not in PackageObject.FileList: + PackageObject.FileList.append((ContainerFile, Md5Sum)) + + return ContainerFile + +## GenPcdErrComment +# +# @param PcdErrObject: PcdErrorObject +# +# @retval CommentStr: Generated comment lines, with prefix "#" +# +def GenPcdErrComment (PcdErrObject): + CommentStr = '' + ErrorCode = PcdErrObject.GetErrorNumber() + ValidValueRange = PcdErrObject.GetValidValueRange() + if ValidValueRange: + CommentStr = TAB_COMMENT_SPLIT + TAB_SPACE_SPLIT + TAB_PCD_VALIDRANGE + TAB_SPACE_SPLIT + if ErrorCode: + CommentStr += ErrorCode + TAB_SPACE_SPLIT + TAB_VALUE_SPLIT + TAB_SPACE_SPLIT + CommentStr += ValidValueRange + END_OF_LINE + + ValidValue = PcdErrObject.GetValidValue() + if ValidValue: + ValidValueList = \ + [Value for Value in ValidValue.split(TAB_SPACE_SPLIT) if Value] + CommentStr = TAB_COMMENT_SPLIT + TAB_SPACE_SPLIT + TAB_PCD_VALIDLIST + TAB_SPACE_SPLIT + if ErrorCode: + CommentStr += ErrorCode + TAB_SPACE_SPLIT + TAB_VALUE_SPLIT + TAB_SPACE_SPLIT + CommentStr += TAB_COMMA_SPLIT.join(ValidValueList) + END_OF_LINE + + Expression = PcdErrObject.GetExpression() + if Expression: + CommentStr = TAB_COMMENT_SPLIT + TAB_SPACE_SPLIT + TAB_PCD_EXPRESSION + TAB_SPACE_SPLIT + if ErrorCode: + CommentStr += ErrorCode + TAB_SPACE_SPLIT + TAB_VALUE_SPLIT + TAB_SPACE_SPLIT + CommentStr += Expression + END_OF_LINE + + return CommentStr + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/GenMetaFile/GenInfFile.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/GenMetaFile/GenInfFile.py new file mode 100755 index 00000000..83876fe8 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/GenMetaFile/GenInfFile.py @@ -0,0 +1,1122 @@ +## @file GenInfFile.py +# +# This file contained the logical of transfer package object to INF files. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +''' +GenInf +''' +import os +import stat +import codecs +from hashlib import md5 +from Core.FileHook import __FileHookOpen__ +from Library.StringUtils import GetSplitValueList +from Library.Parsing import GenSection +from Library.Parsing import GetWorkspacePackage +from Library.Parsing import ConvertArchForInstall +from Library.Misc import SaveFileOnChange +from Library.Misc import IsAllModuleList +from Library.Misc import Sdict +from Library.Misc import ConvertPath +from Library.Misc import ConvertSpec +from Library.Misc import GetRelativePath +from Library.Misc import GetLocalValue +from Library.CommentGenerating import GenHeaderCommentSection +from Library.CommentGenerating import GenGenericCommentF +from Library.CommentGenerating import _GetHelpStr +from Library import GlobalData +from Logger import StringTable as ST +from Logger import ToolError +import Logger.Log as Logger +from Library import DataType as DT +from GenMetaFile import GenMetaFileMisc +from Library.UniClassObject import FormatUniEntry +from Library.StringUtils import GetUniFileName + + +## Transfer Module Object to Inf files +# +# Transfer all contents of a standard Module Object to an Inf file +# @param ModuleObject: A Module Object +# +def ModuleToInf(ModuleObject, PackageObject=None, DistHeader=None): + if not GlobalData.gWSPKG_LIST: + GlobalData.gWSPKG_LIST = GetWorkspacePackage() + # + # Init global information for the file + # + ContainerFile = ModuleObject.GetFullPath() + + Content = '' + # + # Generate file header, If any Abstract, Description, Copyright or License XML elements are missing, + # should 1) use the Abstract, Description, Copyright or License from the PackageSurfaceArea.Header elements + # that the module belongs to, or 2) if this is a stand-alone module that is not included in a PackageSurfaceArea, + # use the abstract, description, copyright or license from the DistributionPackage.Header elements. + # + ModuleAbstract = GetLocalValue(ModuleObject.GetAbstract()) + if not ModuleAbstract and PackageObject: + ModuleAbstract = GetLocalValue(PackageObject.GetAbstract()) + if not ModuleAbstract and DistHeader: + ModuleAbstract = GetLocalValue(DistHeader.GetAbstract()) + ModuleDescription = GetLocalValue(ModuleObject.GetDescription()) + if not ModuleDescription and PackageObject: + ModuleDescription = GetLocalValue(PackageObject.GetDescription()) + if not ModuleDescription and DistHeader: + ModuleDescription = GetLocalValue(DistHeader.GetDescription()) + ModuleCopyright = '' + for (Lang, Copyright) in ModuleObject.GetCopyright(): + if Lang: + pass + ModuleCopyright = Copyright + if not ModuleCopyright and PackageObject: + for (Lang, Copyright) in PackageObject.GetCopyright(): + if Lang: + pass + ModuleCopyright = Copyright + if not ModuleCopyright and DistHeader: + for (Lang, Copyright) in DistHeader.GetCopyright(): + if Lang: + pass + ModuleCopyright = Copyright + ModuleLicense = '' + for (Lang, License) in ModuleObject.GetLicense(): + if Lang: + pass + ModuleLicense = License + if not ModuleLicense and PackageObject: + for (Lang, License) in PackageObject.GetLicense(): + if Lang: + pass + ModuleLicense = License + if not ModuleLicense and DistHeader: + for (Lang, License) in DistHeader.GetLicense(): + if Lang: + pass + ModuleLicense = License + + # + # Generate header comment section of INF file + # + Content += GenHeaderCommentSection(ModuleAbstract, + ModuleDescription, + ModuleCopyright, + ModuleLicense).replace('\r\n', '\n') + + # + # Generate Binary Header + # + for UserExtension in ModuleObject.GetUserExtensionList(): + if UserExtension.GetUserID() == DT.TAB_BINARY_HEADER_USERID \ + and UserExtension.GetIdentifier() == DT.TAB_BINARY_HEADER_IDENTIFIER: + ModuleBinaryAbstract = GetLocalValue(UserExtension.GetBinaryAbstract()) + ModuleBinaryDescription = GetLocalValue(UserExtension.GetBinaryDescription()) + ModuleBinaryCopyright = '' + ModuleBinaryLicense = '' + for (Lang, Copyright) in UserExtension.GetBinaryCopyright(): + ModuleBinaryCopyright = Copyright + for (Lang, License) in UserExtension.GetBinaryLicense(): + ModuleBinaryLicense = License + if ModuleBinaryAbstract and ModuleBinaryDescription and \ + ModuleBinaryCopyright and ModuleBinaryLicense: + Content += GenHeaderCommentSection(ModuleBinaryAbstract, + ModuleBinaryDescription, + ModuleBinaryCopyright, + ModuleBinaryLicense, + True) + + # + # Generate MODULE_UNI_FILE for module + # + FileHeader = GenHeaderCommentSection(ModuleAbstract, ModuleDescription, ModuleCopyright, ModuleLicense, False, \ + DT.TAB_COMMENT_EDK1_SPLIT) + ModuleUniFile = GenModuleUNIEncodeFile(ModuleObject, FileHeader) + if ModuleUniFile: + ModuleObject.SetModuleUniFile(os.path.basename(ModuleUniFile)) + + # + # Judge whether the INF file is an AsBuild INF. + # + if ModuleObject.BinaryModule: + GlobalData.gIS_BINARY_INF = True + else: + GlobalData.gIS_BINARY_INF = False + # + # for each section, maintain a dict, sorted arch will be its key, + # statement list will be its data + # { 'Arch1 Arch2 Arch3': [statement1, statement2], + # 'Arch1' : [statement1, statement3] + # } + # + # Gen section contents + # + Content += GenDefines(ModuleObject) + Content += GenBuildOptions(ModuleObject) + Content += GenLibraryClasses(ModuleObject) + Content += GenPackages(ModuleObject) + Content += GenPcdSections(ModuleObject) + Content += GenSources(ModuleObject) + Content += GenProtocolPPiSections(ModuleObject.GetProtocolList(), True) + Content += GenProtocolPPiSections(ModuleObject.GetPpiList(), False) + Content += GenGuidSections(ModuleObject.GetGuidList()) + Content += GenBinaries(ModuleObject) + Content += GenDepex(ModuleObject) + __UserExtensionsContent = GenUserExtensions(ModuleObject) + Content += __UserExtensionsContent + if ModuleObject.GetEventList() or ModuleObject.GetBootModeList() or ModuleObject.GetHobList(): + Content += '\n' + # + # generate [Event], [BootMode], [Hob] section + # + Content += GenSpecialSections(ModuleObject.GetEventList(), 'Event', __UserExtensionsContent) + Content += GenSpecialSections(ModuleObject.GetBootModeList(), 'BootMode', __UserExtensionsContent) + Content += GenSpecialSections(ModuleObject.GetHobList(), 'Hob', __UserExtensionsContent) + SaveFileOnChange(ContainerFile, Content, False) + if DistHeader.ReadOnly: + os.chmod(ContainerFile, stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH) + else: + os.chmod(ContainerFile, stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH|stat.S_IWUSR|stat.S_IWGRP|stat.S_IWOTH) + return ContainerFile + +## GenModuleUNIEncodeFile +# GenModuleUNIEncodeFile, default is a UCS-2LE encode file +# +def GenModuleUNIEncodeFile(ModuleObject, UniFileHeader='', Encoding=DT.TAB_ENCODING_UTF16LE): + GenUNIFlag = False + OnlyLANGUAGE_EN_X = True + BinaryAbstract = [] + BinaryDescription = [] + # + # If more than one language code is used for any element that would be present in the MODULE_UNI_FILE, + # then the MODULE_UNI_FILE must be created. + # + for (Key, Value) in ModuleObject.GetAbstract() + ModuleObject.GetDescription(): + if Key == DT.TAB_LANGUAGE_EN_X: + GenUNIFlag = True + else: + OnlyLANGUAGE_EN_X = False + + for UserExtension in ModuleObject.GetUserExtensionList(): + if UserExtension.GetUserID() == DT.TAB_BINARY_HEADER_USERID \ + and UserExtension.GetIdentifier() == DT.TAB_BINARY_HEADER_IDENTIFIER: + for (Key, Value) in UserExtension.GetBinaryAbstract(): + if Key == DT.TAB_LANGUAGE_EN_X: + GenUNIFlag = True + else: + OnlyLANGUAGE_EN_X = False + BinaryAbstract.append((Key, Value)) + for (Key, Value) in UserExtension.GetBinaryDescription(): + if Key == DT.TAB_LANGUAGE_EN_X: + GenUNIFlag = True + else: + OnlyLANGUAGE_EN_X = False + BinaryDescription.append((Key, Value)) + + + if not GenUNIFlag: + return + elif OnlyLANGUAGE_EN_X: + return + else: + ModuleObject.UNIFlag = True + ContainerFile = GetUniFileName(os.path.dirname(ModuleObject.GetFullPath()), ModuleObject.GetBaseName()) + + if not os.path.exists(os.path.dirname(ModuleObject.GetFullPath())): + os.makedirs(os.path.dirname(ModuleObject.GetFullPath())) + + Content = UniFileHeader + '\r\n' + Content += '\r\n' + + Content += FormatUniEntry('#string ' + DT.TAB_INF_ABSTRACT, ModuleObject.GetAbstract(), ContainerFile) + '\r\n' + + Content += FormatUniEntry('#string ' + DT.TAB_INF_DESCRIPTION, ModuleObject.GetDescription(), ContainerFile) \ + + '\r\n' + + BinaryAbstractString = FormatUniEntry('#string ' + DT.TAB_INF_BINARY_ABSTRACT, BinaryAbstract, ContainerFile) + if BinaryAbstractString: + Content += BinaryAbstractString + '\r\n' + + BinaryDescriptionString = FormatUniEntry('#string ' + DT.TAB_INF_BINARY_DESCRIPTION, BinaryDescription, \ + ContainerFile) + if BinaryDescriptionString: + Content += BinaryDescriptionString + '\r\n' + + if not os.path.exists(ContainerFile): + File = codecs.open(ContainerFile, 'wb', Encoding) + File.write(u'\uFEFF' + Content) + File.stream.close() + Md5Signature = md5(__FileHookOpen__(str(ContainerFile), 'rb').read()) + Md5Sum = Md5Signature.hexdigest() + if (ContainerFile, Md5Sum) not in ModuleObject.FileList: + ModuleObject.FileList.append((ContainerFile, Md5Sum)) + + return ContainerFile +def GenDefines(ModuleObject): + # + # generate [Defines] section + # + LeftOffset = 31 + Content = '' + NewSectionDict = {} + + for UserExtension in ModuleObject.GetUserExtensionList(): + DefinesDict = UserExtension.GetDefinesDict() + if not DefinesDict: + continue + for Statement in DefinesDict: + if len(Statement.split(DT.TAB_EQUAL_SPLIT)) > 1: + Statement = (u'%s ' % Statement.split(DT.TAB_EQUAL_SPLIT, 1)[0]).ljust(LeftOffset) \ + + u'= %s' % Statement.split(DT.TAB_EQUAL_SPLIT, 1)[1].lstrip() + SortedArch = DT.TAB_ARCH_COMMON + if Statement.strip().startswith(DT.TAB_INF_DEFINES_CUSTOM_MAKEFILE): + pos = Statement.find(DT.TAB_VALUE_SPLIT) + if pos == -1: + pos = Statement.find(DT.TAB_EQUAL_SPLIT) + Makefile = ConvertPath(Statement[pos + 1:].strip()) + Statement = Statement[:pos + 1] + ' ' + Makefile + if SortedArch in NewSectionDict: + NewSectionDict[SortedArch] = NewSectionDict[SortedArch] + [Statement] + else: + NewSectionDict[SortedArch] = [Statement] + SpecialStatementList = [] + + # TAB_INF_DEFINES_INF_VERSION + Statement = (u'%s ' % DT.TAB_INF_DEFINES_INF_VERSION).ljust(LeftOffset) + u'= %s' % '0x00010017' + SpecialStatementList.append(Statement) + + # BaseName + BaseName = ModuleObject.GetBaseName() + if BaseName.startswith('.') or BaseName.startswith('-'): + BaseName = '_' + BaseName + Statement = (u'%s ' % DT.TAB_INF_DEFINES_BASE_NAME).ljust(LeftOffset) + u'= %s' % BaseName + SpecialStatementList.append(Statement) + + # TAB_INF_DEFINES_FILE_GUID + Statement = (u'%s ' % DT.TAB_INF_DEFINES_FILE_GUID).ljust(LeftOffset) + u'= %s' % ModuleObject.GetGuid() + SpecialStatementList.append(Statement) + + # TAB_INF_DEFINES_VERSION_STRING + Statement = (u'%s ' % DT.TAB_INF_DEFINES_VERSION_STRING).ljust(LeftOffset) + u'= %s' % ModuleObject.GetVersion() + SpecialStatementList.append(Statement) + + # TAB_INF_DEFINES_VERSION_STRING + if ModuleObject.UNIFlag: + Statement = (u'%s ' % DT.TAB_INF_DEFINES_MODULE_UNI_FILE).ljust(LeftOffset) + \ + u'= %s' % ModuleObject.GetModuleUniFile() + SpecialStatementList.append(Statement) + + # TAB_INF_DEFINES_MODULE_TYPE + if ModuleObject.GetModuleType(): + Statement = (u'%s ' % DT.TAB_INF_DEFINES_MODULE_TYPE).ljust(LeftOffset) + u'= %s' % ModuleObject.GetModuleType() + SpecialStatementList.append(Statement) + + # TAB_INF_DEFINES_PCD_IS_DRIVER + if ModuleObject.GetPcdIsDriver(): + Statement = (u'%s ' % DT.TAB_INF_DEFINES_PCD_IS_DRIVER).ljust(LeftOffset) + \ + u'= %s' % ModuleObject.GetPcdIsDriver() + SpecialStatementList.append(Statement) + + # TAB_INF_DEFINES_UEFI_SPECIFICATION_VERSION + if ModuleObject.GetUefiSpecificationVersion(): + Statement = (u'%s ' % DT.TAB_INF_DEFINES_UEFI_SPECIFICATION_VERSION).ljust(LeftOffset) + \ + u'= %s' % ModuleObject.GetUefiSpecificationVersion() + SpecialStatementList.append(Statement) + + # TAB_INF_DEFINES_PI_SPECIFICATION_VERSION + if ModuleObject.GetPiSpecificationVersion(): + Statement = (u'%s ' % DT.TAB_INF_DEFINES_PI_SPECIFICATION_VERSION).ljust(LeftOffset) + \ + u'= %s' % ModuleObject.GetPiSpecificationVersion() + SpecialStatementList.append(Statement) + + # LibraryClass + for LibraryClass in ModuleObject.GetLibraryClassList(): + if LibraryClass.GetUsage() == DT.USAGE_ITEM_PRODUCES or \ + LibraryClass.GetUsage() == DT.USAGE_ITEM_SOMETIMES_PRODUCES: + Statement = (u'%s ' % DT.TAB_INF_DEFINES_LIBRARY_CLASS).ljust(LeftOffset) + \ + u'= %s' % LibraryClass.GetLibraryClass() + if LibraryClass.GetSupModuleList(): + Statement += '|' + DT.TAB_SPACE_SPLIT.join(l for l in LibraryClass.GetSupModuleList()) + SpecialStatementList.append(Statement) + + # Spec Item + for SpecItem in ModuleObject.GetSpecList(): + Spec, Version = SpecItem + Spec = ConvertSpec(Spec) + Statement = '%s %s = %s' % (DT.TAB_INF_DEFINES_SPEC, Spec, Version) + SpecialStatementList.append(Statement) + + # Extern + ExternList = [] + for Extern in ModuleObject.GetExternList(): + ArchList = Extern.GetSupArchList() + EntryPoint = Extern.GetEntryPoint() + UnloadImage = Extern.GetUnloadImage() + Constructor = Extern.GetConstructor() + Destructor = Extern.GetDestructor() + HelpStringList = Extern.GetHelpTextList() + FFE = Extern.GetFeatureFlag() + ExternList.append([ArchList, EntryPoint, UnloadImage, Constructor, Destructor, FFE, HelpStringList]) + # + # Add VALID_ARCHITECTURES information + # + ValidArchStatement = None + if ModuleObject.SupArchList: + ValidArchStatement = '\n' + '# ' + '\n' + ValidArchStatement += '# The following information is for reference only and not required by the build tools.\n' + ValidArchStatement += '# ' + '\n' + ValidArchStatement += '# VALID_ARCHITECTURES = %s' % (' '.join(ModuleObject.SupArchList)) + '\n' + ValidArchStatement += '# ' + if DT.TAB_ARCH_COMMON not in NewSectionDict: + NewSectionDict[DT.TAB_ARCH_COMMON] = [] + NewSectionDict[DT.TAB_ARCH_COMMON] = NewSectionDict[DT.TAB_ARCH_COMMON] + SpecialStatementList + GenMetaFileMisc.AddExternToDefineSec(NewSectionDict, DT.TAB_ARCH_COMMON, ExternList) + if ValidArchStatement is not None: + NewSectionDict[DT.TAB_ARCH_COMMON] = NewSectionDict[DT.TAB_ARCH_COMMON] + [ValidArchStatement] + Content += GenSection('Defines', NewSectionDict) + return Content + +def GenLibraryClasses(ModuleObject): + # + # generate [LibraryClasses] section + # + Content = '' + NewSectionDict = {} + if not GlobalData.gIS_BINARY_INF: + for LibraryClass in ModuleObject.GetLibraryClassList(): + if LibraryClass.GetUsage() == DT.USAGE_ITEM_PRODUCES: + continue + # + # Generate generic comment + # + HelpTextList = LibraryClass.GetHelpTextList() + HelpStr = _GetHelpStr(HelpTextList) + CommentStr = GenGenericCommentF(HelpStr) + Statement = CommentStr + Name = LibraryClass.GetLibraryClass() + FFE = LibraryClass.GetFeatureFlag() + Statement += Name + if FFE: + Statement += '|' + FFE + ModuleList = LibraryClass.GetSupModuleList() + ArchList = LibraryClass.GetSupArchList() + for Index in range(0, len(ArchList)): + ArchList[Index] = ConvertArchForInstall(ArchList[Index]) + ArchList.sort() + SortedArch = ' '.join(ArchList) + KeyList = [] + if not ModuleList or IsAllModuleList(ModuleList): + KeyList = [SortedArch] + else: + ModuleString = DT.TAB_VALUE_SPLIT.join(l for l in ModuleList) + if not ArchList: + SortedArch = DT.TAB_ARCH_COMMON + KeyList = [SortedArch + '.' + ModuleString] + else: + KeyList = [Arch + '.' + ModuleString for Arch in ArchList] + for Key in KeyList: + if Key in NewSectionDict: + NewSectionDict[Key] = NewSectionDict[Key] + [Statement] + else: + NewSectionDict[Key] = [Statement] + Content += GenSection('LibraryClasses', NewSectionDict) + else: + LibraryClassDict = {} + for BinaryFile in ModuleObject.GetBinaryFileList(): + if not BinaryFile.AsBuiltList: + continue + for LibraryItem in BinaryFile.AsBuiltList[0].LibraryInstancesList: + Statement = '# Guid: ' + LibraryItem.Guid + ' Version: ' + LibraryItem.Version + + if len(BinaryFile.SupArchList) == 0: + if 'COMMON' in LibraryClassDict and Statement not in LibraryClassDict['COMMON']: + LibraryClassDict['COMMON'].append(Statement) + else: + LibraryClassDict['COMMON'] = ['## @LIB_INSTANCES'] + LibraryClassDict['COMMON'].append(Statement) + else: + for Arch in BinaryFile.SupArchList: + if Arch in LibraryClassDict: + if Statement not in LibraryClassDict[Arch]: + LibraryClassDict[Arch].append(Statement) + else: + continue + else: + LibraryClassDict[Arch] = ['## @LIB_INSTANCES'] + LibraryClassDict[Arch].append(Statement) + Content += GenSection('LibraryClasses', LibraryClassDict) + + return Content + +def GenPackages(ModuleObject): + Content = '' + # + # generate [Packages] section + # + NewSectionDict = Sdict() + WorkspaceDir = GlobalData.gWORKSPACE + for PackageDependency in ModuleObject.GetPackageDependencyList(): + # + # Generate generic comment + # + CommentStr = '' + HelpText = PackageDependency.GetHelpText() + if HelpText: + HelpStr = HelpText.GetString() + CommentStr = GenGenericCommentF(HelpStr) + Statement = CommentStr + Guid = PackageDependency.GetGuid() + Version = PackageDependency.GetVersion() + FFE = PackageDependency.GetFeatureFlag() + Path = '' + # + # find package path/name + # + for PkgInfo in GlobalData.gWSPKG_LIST: + if Guid == PkgInfo[1]: + if (not Version) or (Version == PkgInfo[2]): + Path = PkgInfo[3] + break + # + # get relative path + # + RelaPath = GetRelativePath(Path, WorkspaceDir) + Statement += RelaPath.replace('\\', '/') + if FFE: + Statement += '|' + FFE + ArchList = sorted(PackageDependency.GetSupArchList()) + SortedArch = ' '.join(ArchList) + if SortedArch in NewSectionDict: + NewSectionDict[SortedArch] = NewSectionDict[SortedArch] + [Statement] + else: + NewSectionDict[SortedArch] = [Statement] + Content += GenSection('Packages', NewSectionDict) + return Content + +def GenSources(ModuleObject): + # + # generate [Sources] section + # + Content = '' + NewSectionDict = {} + for Source in ModuleObject.GetSourceFileList(): + SourceFile = Source.GetSourceFile() + Family = Source.GetFamily() + FeatureFlag = Source.GetFeatureFlag() + SupArchList = sorted(Source.GetSupArchList()) + SortedArch = ' '.join(SupArchList) + Statement = GenSourceStatement(ConvertPath(SourceFile), Family, FeatureFlag) + if SortedArch in NewSectionDict: + NewSectionDict[SortedArch] = NewSectionDict[SortedArch] + [Statement] + else: + NewSectionDict[SortedArch] = [Statement] + Content += GenSection('Sources', NewSectionDict) + + return Content + +def GenDepex(ModuleObject): + # + # generate [Depex] section + # + NewSectionDict = Sdict() + Content = '' + for Depex in ModuleObject.GetPeiDepex() + ModuleObject.GetDxeDepex() + ModuleObject.GetSmmDepex(): + HelpTextList = Depex.GetHelpTextList() + HelpStr = _GetHelpStr(HelpTextList) + CommentStr = GenGenericCommentF(HelpStr) + SupArchList = Depex.GetSupArchList() + SupModList = Depex.GetModuleType() + Expression = Depex.GetDepex() + Statement = CommentStr + Expression + SupArchList.sort() + KeyList = [] + if not SupArchList: + SupArchList.append(DT.TAB_ARCH_COMMON.lower()) + if not SupModList: + KeyList = SupArchList + else: + for ModuleType in SupModList: + for Arch in SupArchList: + KeyList.append(ConvertArchForInstall(Arch) + '.' + ModuleType) + for Key in KeyList: + if Key in NewSectionDict: + NewSectionDict[Key] = NewSectionDict[Key] + [Statement] + else: + NewSectionDict[Key] = [Statement] + Content += GenSection('Depex', NewSectionDict, False) + + return Content +## GenUserExtensions +# +# GenUserExtensions +# +def GenUserExtensions(ModuleObject): + NewSectionDict = {} + for UserExtension in ModuleObject.GetUserExtensionList(): + if UserExtension.GetUserID() == DT.TAB_BINARY_HEADER_USERID and \ + UserExtension.GetIdentifier() == DT.TAB_BINARY_HEADER_IDENTIFIER: + continue + if UserExtension.GetIdentifier() == 'Depex': + continue + Statement = UserExtension.GetStatement() +# Comment the code to support user extension without any statement just the section header in [] +# if not Statement: +# continue + ArchList = UserExtension.GetSupArchList() + for Index in range(0, len(ArchList)): + ArchList[Index] = ConvertArchForInstall(ArchList[Index]) + ArchList.sort() + KeyList = [] + CommonPreFix = '' + if UserExtension.GetUserID(): + CommonPreFix = UserExtension.GetUserID() + if CommonPreFix.find('.') > -1: + CommonPreFix = '"' + CommonPreFix + '"' + if UserExtension.GetIdentifier(): + CommonPreFix += '.' + '"' + UserExtension.GetIdentifier() + '"' + if ArchList: + KeyList = [CommonPreFix + '.' + Arch for Arch in ArchList] + else: + KeyList = [CommonPreFix] + for Key in KeyList: + if Key in NewSectionDict: + NewSectionDict[Key] = NewSectionDict[Key] + [Statement] + else: + NewSectionDict[Key] = [Statement] + Content = GenSection('UserExtensions', NewSectionDict, False) + + return Content + +# GenSourceStatement +# +# @param SourceFile: string of source file path/name +# @param Family: string of source file family field +# @param FeatureFlag: string of source file FeatureFlag field +# @param TagName: string of source file TagName field +# @param ToolCode: string of source file ToolCode field +# @param HelpStr: string of source file HelpStr field +# +# @retval Statement: The generated statement for source +# +def GenSourceStatement(SourceFile, Family, FeatureFlag, TagName=None, + ToolCode=None, HelpStr=None): + Statement = '' + if HelpStr: + Statement += GenGenericCommentF(HelpStr) + # + # format of SourceFile|Family|TagName|ToolCode|FeatureFlag + # + Statement += SourceFile + if TagName is None: + TagName = '' + if ToolCode is None: + ToolCode = '' + if HelpStr is None: + HelpStr = '' + if FeatureFlag: + Statement += '|' + Family + '|' + TagName + '|' + ToolCode + '|' + FeatureFlag + elif ToolCode: + Statement += '|' + Family + '|' + TagName + '|' + ToolCode + elif TagName: + Statement += '|' + Family + '|' + TagName + elif Family: + Statement += '|' + Family + return Statement + +# GenBinaryStatement +# +# @param Key: (FileName, FileType, FFE, SortedArch) +# @param Value: (Target, Family, TagName, Comment) +# +# +def GenBinaryStatement(Key, Value, SubTypeGuidValue=None): + (FileName, FileType, FFE, SortedArch) = Key + if SortedArch: + pass + if Value: + (Target, Family, TagName, Comment) = Value + else: + Target = '' + Family = '' + TagName = '' + Comment = '' + if Comment: + Statement = GenGenericCommentF(Comment) + else: + Statement = '' + if FileType == 'SUBTYPE_GUID' and SubTypeGuidValue: + Statement += FileType + '|' + SubTypeGuidValue + '|' + FileName + else: + Statement += FileType + '|' + FileName + if FileType in DT.BINARY_FILE_TYPE_UI_LIST + DT.BINARY_FILE_TYPE_VER_LIST: + if FFE: + Statement += '|' + Target + '|' + FFE + elif Target: + Statement += '|' + Target + else: + if FFE: + Statement += '|' + Target + '|' + Family + '|' + TagName + '|' + FFE + elif TagName: + Statement += '|' + Target + '|' + Family + '|' + TagName + elif Family: + Statement += '|' + Target + '|' + Family + elif Target: + Statement += '|' + Target + return Statement +## GenGuidSections +# +# @param GuidObjList: List of GuidObject +# @retVal Content: The generated section contents +# +def GenGuidSections(GuidObjList): + # + # generate [Guids] section + # + Content = '' + GuidDict = Sdict() + for Guid in GuidObjList: + HelpTextList = Guid.GetHelpTextList() + HelpStr = _GetHelpStr(HelpTextList) + CName = Guid.GetCName() + FFE = Guid.GetFeatureFlag() + Statement = CName + if FFE: + Statement += '|' + FFE + Usage = Guid.GetUsage() + GuidType = Guid.GetGuidTypeList()[0] + VariableName = Guid.GetVariableName() + # + # Differentiate the generic comment and usage comment as multiple generic comment need to be put at first + # + if Usage == DT.ITEM_UNDEFINED and GuidType == DT.ITEM_UNDEFINED: + # generate list of generic comment + Comment = GenGenericCommentF(HelpStr) + else: + # generate list of other comment + Comment = HelpStr.replace('\n', ' ') + Comment = Comment.strip() + if Comment: + Comment = ' # ' + Comment + else: + Comment = '' + if Usage != DT.ITEM_UNDEFINED and GuidType == DT.ITEM_UNDEFINED: + Comment = '## ' + Usage + Comment + elif GuidType == 'Variable': + Comment = '## ' + Usage + ' ## ' + GuidType + ':' + VariableName + Comment + else: + Comment = '## ' + Usage + ' ## ' + GuidType + Comment + + if Comment: + Comment += '\n' + # + # merge duplicate items + # + ArchList = sorted(Guid.GetSupArchList()) + SortedArch = ' '.join(ArchList) + if (Statement, SortedArch) in GuidDict: + PreviousComment = GuidDict[Statement, SortedArch] + Comment = PreviousComment + Comment + GuidDict[Statement, SortedArch] = Comment + NewSectionDict = GenMetaFileMisc.TransferDict(GuidDict, 'INF_GUID') + # + # generate the section contents + # + if NewSectionDict: + Content = GenSection('Guids', NewSectionDict) + + return Content + +## GenProtocolPPiSections +# +# @param ObjList: List of ProtocolObject or Ppi Object +# @retVal Content: The generated section contents +# +def GenProtocolPPiSections(ObjList, IsProtocol): + Content = '' + Dict = Sdict() + for Object in ObjList: + HelpTextList = Object.GetHelpTextList() + HelpStr = _GetHelpStr(HelpTextList) + CName = Object.GetCName() + FFE = Object.GetFeatureFlag() + Statement = CName + if FFE: + Statement += '|' + FFE + Usage = Object.GetUsage() + Notify = Object.GetNotify() + # + # Differentiate the generic comment and usage comment as consecutive generic comment need to be put together + # + if Usage == DT.ITEM_UNDEFINED and Notify == '': + # generate list of generic comment + Comment = GenGenericCommentF(HelpStr) + else: + # generate list of other comment + Comment = HelpStr.replace('\n', ' ') + Comment = Comment.strip() + if Comment: + Comment = ' # ' + Comment + else: + Comment = '' + if Usage == DT.ITEM_UNDEFINED and not Comment and Notify == '': + Comment = '' + else: + if Notify: + Comment = '## ' + Usage + ' ## ' + 'NOTIFY' + Comment + else: + Comment = '## ' + Usage + Comment + if Comment: + Comment += '\n' + # + # merge duplicate items + # + ArchList = sorted(Object.GetSupArchList()) + SortedArch = ' '.join(ArchList) + if (Statement, SortedArch) in Dict: + PreviousComment = Dict[Statement, SortedArch] + Comment = PreviousComment + Comment + Dict[Statement, SortedArch] = Comment + NewSectionDict = GenMetaFileMisc.TransferDict(Dict, 'INF_PPI_PROTOCOL') + # + # generate the section contents + # + if NewSectionDict: + if IsProtocol: + Content = GenSection('Protocols', NewSectionDict) + else: + Content = GenSection('Ppis', NewSectionDict) + + return Content + +## GenPcdSections +# +# +def GenPcdSections(ModuleObject): + Content = '' + if not GlobalData.gIS_BINARY_INF: + # + # for each Pcd Itemtype, maintain a dict so the same type will be grouped + # together + # + ItemTypeDict = {} + for Pcd in ModuleObject.GetPcdList(): + HelpTextList = Pcd.GetHelpTextList() + HelpStr = _GetHelpStr(HelpTextList) + Statement = '' + CName = Pcd.GetCName() + TokenSpaceGuidCName = Pcd.GetTokenSpaceGuidCName() + DefaultValue = Pcd.GetDefaultValue() + ItemType = Pcd.GetItemType() + if ItemType in ItemTypeDict: + Dict = ItemTypeDict[ItemType] + else: + Dict = Sdict() + ItemTypeDict[ItemType] = Dict + FFE = Pcd.GetFeatureFlag() + Statement += TokenSpaceGuidCName + '.' + CName + if DefaultValue: + Statement += '|' + DefaultValue + if FFE: + Statement += '|' + FFE + elif FFE: + Statement += '||' + FFE + # + # Generate comment + # + Usage = Pcd.GetValidUsage() + # if FeatureFlag Pcd, then assume all Usage is CONSUMES + if ItemType == DT.TAB_INF_FEATURE_PCD: + Usage = DT.USAGE_ITEM_CONSUMES + if Usage == DT.ITEM_UNDEFINED: + # generate list of generic comment + Comment = GenGenericCommentF(HelpStr) + else: + # generate list of other comment + Comment = HelpStr.replace('\n', ' ') + Comment = Comment.strip() + if Comment: + Comment = ' # ' + Comment + else: + Comment = '' + Comment = '## ' + Usage + Comment + if Comment: + Comment += '\n' + # + # Merge duplicate entries + # + ArchList = sorted(Pcd.GetSupArchList()) + SortedArch = ' '.join(ArchList) + if (Statement, SortedArch) in Dict: + PreviousComment = Dict[Statement, SortedArch] + Comment = PreviousComment + Comment + Dict[Statement, SortedArch] = Comment + for ItemType in ItemTypeDict: + # First we need to transfer the Dict to use SortedArch as key + Dict = ItemTypeDict[ItemType] + NewSectionDict = GenMetaFileMisc.TransferDict(Dict, 'INF_PCD') + if NewSectionDict: + Content += GenSection(ItemType, NewSectionDict) + # + # For AsBuild INF files + # + else: + Content += GenAsBuiltPacthPcdSections(ModuleObject) + Content += GenAsBuiltPcdExSections(ModuleObject) + + return Content + +## GenPcdSections +# +# +def GenAsBuiltPacthPcdSections(ModuleObject): + PatchPcdDict = {} + for BinaryFile in ModuleObject.GetBinaryFileList(): + if not BinaryFile.AsBuiltList: + continue + for PatchPcd in BinaryFile.AsBuiltList[0].PatchPcdList: + TokenSpaceName = '' + PcdCName = PatchPcd.CName + PcdValue = PatchPcd.DefaultValue + PcdOffset = PatchPcd.Offset + TokenSpaceGuidValue = PatchPcd.TokenSpaceGuidValue + Token = PatchPcd.Token + HelpTextList = PatchPcd.HelpTextList + HelpString = '' + for HelpStringItem in HelpTextList: + for HelpLine in GetSplitValueList(HelpStringItem.String, '\n'): + HelpString += '## ' + HelpLine + '\n' + TokenSpaceName, PcdCName = GenMetaFileMisc.ObtainPcdName(ModuleObject.PackageDependencyList, + TokenSpaceGuidValue, + Token) + if TokenSpaceName == '' or PcdCName == '': + Logger.Error("Upt", + ToolError.RESOURCE_NOT_AVAILABLE, + ST.ERR_INSTALL_FILE_DEC_FILE_ERROR % (TokenSpaceGuidValue, Token), + File=ModuleObject.GetFullPath()) + Statement = HelpString + TokenSpaceName + '.' + PcdCName + ' | ' + PcdValue + ' | ' + \ + PcdOffset + DT.TAB_SPACE_SPLIT + # + # Use binary file's Arch to be Pcd's Arch + # + ArchList = [] + FileNameObjList = BinaryFile.GetFileNameList() + if FileNameObjList: + ArchList = FileNameObjList[0].GetSupArchList() + if len(ArchList) == 0: + if DT.TAB_ARCH_COMMON in PatchPcdDict: + if Statement not in PatchPcdDict[DT.TAB_ARCH_COMMON]: + PatchPcdDict[DT.TAB_ARCH_COMMON].append(Statement) + else: + PatchPcdDict[DT.TAB_ARCH_COMMON] = [Statement] + else: + for Arch in ArchList: + if Arch in PatchPcdDict: + if Statement not in PatchPcdDict[Arch]: + PatchPcdDict[Arch].append(Statement) + else: + PatchPcdDict[Arch] = [Statement] + return GenSection(DT.TAB_INF_PATCH_PCD, PatchPcdDict) +## GenPcdSections +# +# +def GenAsBuiltPcdExSections(ModuleObject): + PcdExDict = {} + for BinaryFile in ModuleObject.GetBinaryFileList(): + if not BinaryFile.AsBuiltList: + continue + for PcdExItem in BinaryFile.AsBuiltList[0].PcdExValueList: + TokenSpaceName = '' + PcdCName = PcdExItem.CName + TokenSpaceGuidValue = PcdExItem.TokenSpaceGuidValue + Token = PcdExItem.Token + HelpTextList = PcdExItem.HelpTextList + HelpString = '' + for HelpStringItem in HelpTextList: + for HelpLine in GetSplitValueList(HelpStringItem.String, '\n'): + HelpString += '## ' + HelpLine + '\n' + TokenSpaceName, PcdCName = GenMetaFileMisc.ObtainPcdName(ModuleObject.PackageDependencyList, + TokenSpaceGuidValue, Token) + if TokenSpaceName == '' or PcdCName == '': + Logger.Error("Upt", + ToolError.RESOURCE_NOT_AVAILABLE, + ST.ERR_INSTALL_FILE_DEC_FILE_ERROR % (TokenSpaceGuidValue, Token), + File=ModuleObject.GetFullPath()) + + Statement = HelpString + TokenSpaceName + DT.TAB_SPLIT + PcdCName + DT.TAB_SPACE_SPLIT + + # + # Use binary file's Arch to be Pcd's Arch + # + ArchList = [] + FileNameObjList = BinaryFile.GetFileNameList() + if FileNameObjList: + ArchList = FileNameObjList[0].GetSupArchList() + + if len(ArchList) == 0: + if 'COMMON' in PcdExDict: + PcdExDict['COMMON'].append(Statement) + else: + PcdExDict['COMMON'] = [Statement] + else: + for Arch in ArchList: + if Arch in PcdExDict: + if Statement not in PcdExDict[Arch]: + PcdExDict[Arch].append(Statement) + else: + PcdExDict[Arch] = [Statement] + return GenSection('PcdEx', PcdExDict) + +## GenSpecialSections +# generate special sections for Event/BootMode/Hob +# +def GenSpecialSections(ObjectList, SectionName, UserExtensionsContent=''): + # + # generate section + # + Content = '' + NewSectionDict = {} + for Obj in ObjectList: + # + # Generate comment + # + CommentStr = '' + HelpTextList = Obj.GetHelpTextList() + HelpStr = _GetHelpStr(HelpTextList) + CommentStr = GenGenericCommentF(HelpStr) + if SectionName == 'Hob': + Type = Obj.GetHobType() + elif SectionName == 'Event': + Type = Obj.GetEventType() + elif SectionName == 'BootMode': + Type = Obj.GetSupportedBootModes() + else: + assert(SectionName) + Usage = Obj.GetUsage() + + # If the content already in UserExtensionsContent then ignore + if '[%s]' % SectionName in UserExtensionsContent and Type in UserExtensionsContent: + return '' + + Statement = ' ' + Type + ' ## ' + Usage + if CommentStr in ['#\n', '#\n#\n']: + CommentStr = '#\n#\n#\n' + # + # the first head comment line should start with '##\n', if it starts with '#\n', then add one '#' + # else add '##\n' to meet the format defined in INF spec + # + if CommentStr.startswith('#\n'): + CommentStr = '#' + CommentStr + elif CommentStr: + CommentStr = '##\n' + CommentStr + if CommentStr and not CommentStr.endswith('\n#\n'): + CommentStr = CommentStr + '#\n' + NewStateMent = CommentStr + Statement + SupArch = sorted(Obj.GetSupArchList()) + SortedArch = ' '.join(SupArch) + if SortedArch in NewSectionDict: + NewSectionDict[SortedArch] = NewSectionDict[SortedArch] + [NewStateMent] + else: + NewSectionDict[SortedArch] = [NewStateMent] + SectionContent = GenSection(SectionName, NewSectionDict) + SectionContent = SectionContent.strip() + if SectionContent: + Content = '# ' + ('\n' + '# ').join(GetSplitValueList(SectionContent, '\n')) + Content = Content.lstrip() + # + # add a return to differentiate it between other possible sections + # + if Content: + Content += '\n' + return Content +## GenBuildOptions +# +# +def GenBuildOptions(ModuleObject): + Content = '' + if not ModuleObject.BinaryModule: + # + # generate [BuildOptions] section + # + NewSectionDict = {} + for UserExtension in ModuleObject.GetUserExtensionList(): + BuildOptionDict = UserExtension.GetBuildOptionDict() + if not BuildOptionDict: + continue + for Arch in BuildOptionDict: + if Arch in NewSectionDict: + NewSectionDict[Arch] = NewSectionDict[Arch] + [BuildOptionDict[Arch]] + else: + NewSectionDict[Arch] = [BuildOptionDict[Arch]] + Content = GenSection('BuildOptions', NewSectionDict) + else: + BuildOptionDict = {} + for BinaryFile in ModuleObject.GetBinaryFileList(): + if not BinaryFile.AsBuiltList: + continue + for BuilOptionItem in BinaryFile.AsBuiltList[0].BinaryBuildFlagList: + Statement = '#' + BuilOptionItem.AsBuiltOptionFlags + if len(BinaryFile.SupArchList) == 0: + if 'COMMON' in BuildOptionDict: + if Statement not in BuildOptionDict['COMMON']: + BuildOptionDict['COMMON'].append(Statement) + else: + BuildOptionDict['COMMON'] = ['## @AsBuilt'] + BuildOptionDict['COMMON'].append(Statement) + else: + for Arch in BinaryFile.SupArchList: + if Arch in BuildOptionDict: + if Statement not in BuildOptionDict[Arch]: + BuildOptionDict[Arch].append(Statement) + else: + BuildOptionDict[Arch] = ['## @AsBuilt'] + BuildOptionDict[Arch].append(Statement) + Content = GenSection('BuildOptions', BuildOptionDict) + + return Content +## GenBinaries +# +# +def GenBinaries(ModuleObject): + NewSectionDict = {} + BinariesDict = [] + for UserExtension in ModuleObject.GetUserExtensionList(): + BinariesDict = UserExtension.GetBinariesDict() + if BinariesDict: + break + for BinaryFile in ModuleObject.GetBinaryFileList(): + FileNameObjList = BinaryFile.GetFileNameList() + for FileNameObj in FileNameObjList: + FileName = ConvertPath(FileNameObj.GetFilename()) + FileType = FileNameObj.GetFileType() + FFE = FileNameObj.GetFeatureFlag() + ArchList = sorted(FileNameObj.GetSupArchList()) + SortedArch = ' '.join(ArchList) + Key = (FileName, FileType, FFE, SortedArch) + if Key in BinariesDict: + ValueList = BinariesDict[Key] + for ValueItem in ValueList: + Statement = GenBinaryStatement(Key, ValueItem) + if SortedArch in NewSectionDict: + NewSectionDict[SortedArch] = NewSectionDict[SortedArch] + [Statement] + else: + NewSectionDict[SortedArch] = [Statement] + # + # as we already generated statement for this DictKey here set the Valuelist to be empty + # to avoid generate duplicate entries as the DictKey may have multiple entries + # + BinariesDict[Key] = [] + else: + if FileType == 'SUBTYPE_GUID' and FileNameObj.GetGuidValue(): + Statement = GenBinaryStatement(Key, None, FileNameObj.GetGuidValue()) + else: + Statement = GenBinaryStatement(Key, None) + if SortedArch in NewSectionDict: + NewSectionDict[SortedArch] = NewSectionDict[SortedArch] + [Statement] + else: + NewSectionDict[SortedArch] = [Statement] + Content = GenSection('Binaries', NewSectionDict) + + return Content diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/GenMetaFile/GenMetaFileMisc.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/GenMetaFile/GenMetaFileMisc.py new file mode 100755 index 00000000..e506def3 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/GenMetaFile/GenMetaFileMisc.py @@ -0,0 +1,188 @@ +## @file GenMetaFileMisc.py +# +# This file contained the miscellaneous routines for GenMetaFile usage. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +GenMetaFileMisc +''' + +from Library import DataType as DT +from Library import GlobalData +from Parser.DecParser import Dec + +# AddExternToDefineSec +# +# @param SectionDict: string of source file path/name +# @param Arch: string of source file family field +# @param ExternList: string of source file FeatureFlag field +# +def AddExternToDefineSec(SectionDict, Arch, ExternList): + LeftOffset = 31 + for ArchList, EntryPoint, UnloadImage, Constructor, Destructor, FFE, HelpStringList in ExternList: + if Arch or ArchList: + if EntryPoint: + Statement = (u'%s ' % DT.TAB_INF_DEFINES_ENTRY_POINT).ljust(LeftOffset) + u'= %s' % EntryPoint + if FFE: + Statement += ' | %s' % FFE + if len(HelpStringList) > 0: + Statement = HelpStringList[0].GetString() + '\n' + Statement + if len(HelpStringList) > 1: + Statement = Statement + HelpStringList[1].GetString() + SectionDict[Arch] = SectionDict[Arch] + [Statement] + + if UnloadImage: + Statement = (u'%s ' % DT.TAB_INF_DEFINES_UNLOAD_IMAGE).ljust(LeftOffset) + u'= %s' % UnloadImage + if FFE: + Statement += ' | %s' % FFE + + if len(HelpStringList) > 0: + Statement = HelpStringList[0].GetString() + '\n' + Statement + if len(HelpStringList) > 1: + Statement = Statement + HelpStringList[1].GetString() + SectionDict[Arch] = SectionDict[Arch] + [Statement] + + if Constructor: + Statement = (u'%s ' % DT.TAB_INF_DEFINES_CONSTRUCTOR).ljust(LeftOffset) + u'= %s' % Constructor + if FFE: + Statement += ' | %s' % FFE + + if len(HelpStringList) > 0: + Statement = HelpStringList[0].GetString() + '\n' + Statement + if len(HelpStringList) > 1: + Statement = Statement + HelpStringList[1].GetString() + SectionDict[Arch] = SectionDict[Arch] + [Statement] + + if Destructor: + Statement = (u'%s ' % DT.TAB_INF_DEFINES_DESTRUCTOR).ljust(LeftOffset) + u'= %s' % Destructor + if FFE: + Statement += ' | %s' % FFE + + if len(HelpStringList) > 0: + Statement = HelpStringList[0].GetString() + '\n' + Statement + if len(HelpStringList) > 1: + Statement = Statement + HelpStringList[1].GetString() + SectionDict[Arch] = SectionDict[Arch] + [Statement] + +## ObtainPcdName +# +# Using TokenSpaceGuidValue and Token to obtain PcdName from DEC file +# +def ObtainPcdName(Packages, TokenSpaceGuidValue, Token): + TokenSpaceGuidName = '' + PcdCName = '' + TokenSpaceGuidNameFound = False + + for PackageDependency in Packages: + # + # Generate generic comment + # + Guid = PackageDependency.GetGuid() + Version = PackageDependency.GetVersion() + + Path = None + # + # find package path/name + # + for PkgInfo in GlobalData.gWSPKG_LIST: + if Guid == PkgInfo[1]: + if (not Version) or (Version == PkgInfo[2]): + Path = PkgInfo[3] + break + + # The dependency package in workspace + if Path: + DecFile = None + if Path not in GlobalData.gPackageDict: + DecFile = Dec(Path) + GlobalData.gPackageDict[Path] = DecFile + else: + DecFile = GlobalData.gPackageDict[Path] + + DecGuidsDict = DecFile.GetGuidSectionObject().ValueDict + DecPcdsDict = DecFile.GetPcdSectionObject().ValueDict + + TokenSpaceGuidName = '' + PcdCName = '' + TokenSpaceGuidNameFound = False + + # + # Get TokenSpaceGuidCName from Guids section + # + for GuidKey in DecGuidsDict: + GuidList = DecGuidsDict[GuidKey] + for GuidItem in GuidList: + if TokenSpaceGuidValue.upper() == GuidItem.GuidString.upper(): + TokenSpaceGuidName = GuidItem.GuidCName + TokenSpaceGuidNameFound = True + break + if TokenSpaceGuidNameFound: + break + # + # Retrieve PcdCName from Pcds Section + # + for PcdKey in DecPcdsDict: + PcdList = DecPcdsDict[PcdKey] + for PcdItem in PcdList: + if TokenSpaceGuidName == PcdItem.TokenSpaceGuidCName and Token == PcdItem.TokenValue: + PcdCName = PcdItem.TokenCName + return TokenSpaceGuidName, PcdCName + + # The dependency package in ToBeInstalledDist + else: + for Dist in GlobalData.gTO_BE_INSTALLED_DIST_LIST: + for Package in Dist.PackageSurfaceArea.values(): + if Guid == Package.Guid: + for GuidItem in Package.GuidList: + if TokenSpaceGuidValue.upper() == GuidItem.Guid.upper(): + TokenSpaceGuidName = GuidItem.CName + TokenSpaceGuidNameFound = True + break + for PcdItem in Package.PcdList: + if TokenSpaceGuidName == PcdItem.TokenSpaceGuidCName and Token == PcdItem.Token: + PcdCName = PcdItem.CName + return TokenSpaceGuidName, PcdCName + + return TokenSpaceGuidName, PcdCName + +## _TransferDict +# transfer dict that using (Statement, SortedArch) as key, +# (GenericComment, UsageComment) as value into a dict that using SortedArch as +# key and NewStatement as value +# +def TransferDict(OrigDict, Type=None): + NewDict = {} + LeftOffset = 0 + if Type in ['INF_GUID', 'INF_PPI_PROTOCOL']: + LeftOffset = 45 + if Type in ['INF_PCD']: + LeftOffset = 75 + if LeftOffset > 0: + for Statement, SortedArch in OrigDict: + if len(Statement) > LeftOffset: + LeftOffset = len(Statement) + + for Statement, SortedArch in OrigDict: + Comment = OrigDict[Statement, SortedArch] + # + # apply the NComment/1Comment rule + # + if Comment.find('\n') != len(Comment) - 1: + NewStateMent = Comment + Statement + else: + if LeftOffset: + NewStateMent = Statement.ljust(LeftOffset) + ' ' + Comment.rstrip('\n') + else: + NewStateMent = Statement + ' ' + Comment.rstrip('\n') + + if SortedArch in NewDict: + NewDict[SortedArch] = NewDict[SortedArch] + [NewStateMent] + else: + NewDict[SortedArch] = [NewStateMent] + + return NewDict + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/GenMetaFile/GenXmlFile.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/GenMetaFile/GenXmlFile.py new file mode 100644 index 00000000..e2f7069f --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/GenMetaFile/GenXmlFile.py @@ -0,0 +1,12 @@ +## @file GenXmlFile.py +# +# This file contained the logical of generate XML files. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +GenXmlFile +''' diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/GenMetaFile/__init__.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/GenMetaFile/__init__.py new file mode 100644 index 00000000..4174964f --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/GenMetaFile/__init__.py @@ -0,0 +1,14 @@ +## @file +# Python 'Library' package initialization file. +# +# This file is required to make Python interpreter treat the directory +# as containing package. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +GenMetaFile +''' diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/InstallPkg.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/InstallPkg.py new file mode 100755 index 00000000..3b57b705 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/InstallPkg.py @@ -0,0 +1,967 @@ +## @file +# Install distribution package. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +""" +Install a distribution package +""" +## +# Import Modules +# +from Core.FileHook import __FileHookOpen__ +import os.path +from os import chmod +from os import SEEK_SET +from os import SEEK_END +import stat +from hashlib import md5 +import copy +from sys import stdin +from sys import platform +from shutil import rmtree +from shutil import copyfile +from traceback import format_exc +from platform import python_version + +from Logger import StringTable as ST +from Logger.ToolError import UNKNOWN_ERROR +from Logger.ToolError import FILE_UNKNOWN_ERROR +from Logger.ToolError import OPTION_MISSING +from Logger.ToolError import UPT_ALREADY_INSTALLED_ERROR +from Logger.ToolError import FatalError +from Logger.ToolError import ABORT_ERROR +from Logger.ToolError import CODE_ERROR +from Logger.ToolError import FORMAT_INVALID +from Logger.ToolError import FILE_TYPE_MISMATCH +import Logger.Log as Logger + +from Library.Misc import Sdict +from Library.Misc import ConvertPath +from Library.ParserValidate import IsValidInstallPath +from Xml.XmlParser import DistributionPackageXml +from GenMetaFile.GenDecFile import PackageToDec +from GenMetaFile.GenInfFile import ModuleToInf +from Core.PackageFile import PackageFile +from Core.PackageFile import FILE_NOT_FOUND +from Core.PackageFile import FILE_CHECKSUM_FAILURE +from Core.PackageFile import CreateDirectory +from Core.DependencyRules import DependencyRules +from Library import GlobalData + +## InstallNewPackage +# +# @param WorkspaceDir: Workspace Directory +# @param Path: Package Path +# @param CustomPath: whether need to customize path at first +# +def InstallNewPackage(WorkspaceDir, Path, CustomPath = False): + if os.path.isabs(Path): + Logger.Info(ST.MSG_RELATIVE_PATH_ONLY%Path) + elif CustomPath: + Logger.Info(ST.MSG_NEW_PKG_PATH) + else: + Path = ConvertPath(Path) + Path = os.path.normpath(Path) + FullPath = os.path.normpath(os.path.join(WorkspaceDir, Path)) + if os.path.exists(FullPath): + Logger.Info(ST.ERR_DIR_ALREADY_EXIST%FullPath) + else: + return Path + + Input = stdin.readline() + Input = Input.replace('\r', '').replace('\n', '') + if Input == '': + Logger.Error("InstallPkg", UNKNOWN_ERROR, ST.ERR_USER_INTERRUPT) + Input = Input.replace('\r', '').replace('\n', '') + return InstallNewPackage(WorkspaceDir, Input, False) + +## InstallNewModule +# +# @param WorkspaceDir: Workspace Directory +# @param Path: Standalone Module Path +# @param PathList: The already installed standalone module Path list +# +def InstallNewModule(WorkspaceDir, Path, PathList = None): + if PathList is None: + PathList = [] + Path = ConvertPath(Path) + Path = os.path.normpath(Path) + FullPath = os.path.normpath(os.path.join(WorkspaceDir, Path)) + if os.path.exists(FullPath) and FullPath not in PathList: + Logger.Info(ST.ERR_DIR_ALREADY_EXIST%Path) + elif Path == FullPath: + Logger.Info(ST.MSG_RELATIVE_PATH_ONLY%FullPath) + else: + return Path + + Input = stdin.readline() + Input = Input.replace('\r', '').replace('\n', '') + if Input == '': + Logger.Error("InstallPkg", UNKNOWN_ERROR, ST.ERR_USER_INTERRUPT) + Input = Input.replace('\r', '').replace('\n', '') + return InstallNewModule(WorkspaceDir, Input, PathList) + + +## InstallNewFile +# +# @param WorkspaceDir: Workspace Direction +# @param File: File +# +def InstallNewFile(WorkspaceDir, File): + FullPath = os.path.normpath(os.path.join(WorkspaceDir, File)) + if os.path.exists(FullPath): + Logger.Info(ST.ERR_FILE_ALREADY_EXIST %File) + Input = stdin.readline() + Input = Input.replace('\r', '').replace('\n', '') + if Input == '': + Logger.Error("InstallPkg", UNKNOWN_ERROR, ST.ERR_USER_INTERRUPT) + Input = Input.replace('\r', '').replace('\n', '') + return InstallNewFile(WorkspaceDir, Input) + else: + return File + +## UnZipDp +# +# UnZipDp +# +def UnZipDp(WorkspaceDir, DpPkgFileName, Index=1): + ContentZipFile = None + Logger.Quiet(ST.MSG_UZIP_PARSE_XML) + DistFile = PackageFile(DpPkgFileName) + + DpDescFileName, ContentFileName = GetDPFile(DistFile.GetZipFile()) + + TempDir = os.path.normpath(os.path.join(WorkspaceDir, "Conf/.tmp%s" % str(Index))) + GlobalData.gUNPACK_DIR.append(TempDir) + DistPkgFile = DistFile.UnpackFile(DpDescFileName, os.path.normpath(os.path.join(TempDir, DpDescFileName))) + if not DistPkgFile: + Logger.Error("InstallPkg", FILE_NOT_FOUND, ST.ERR_FILE_BROKEN %DpDescFileName) + + # + # Generate distpkg + # + DistPkgObj = DistributionPackageXml() + DistPkg = DistPkgObj.FromXml(DistPkgFile) + if DistPkg.Header.RePackage == '': + DistPkg.Header.RePackage = False + if DistPkg.Header.ReadOnly == '': + DistPkg.Header.ReadOnly = False + + # + # unzip contents.zip file + # + ContentFile = DistFile.UnpackFile(ContentFileName, os.path.normpath(os.path.join(TempDir, ContentFileName))) + if not ContentFile: + Logger.Error("InstallPkg", FILE_NOT_FOUND, + ST.ERR_FILE_BROKEN % ContentFileName) + + # + # Get file size + # + FileSize = os.path.getsize(ContentFile) + + if FileSize != 0: + ContentZipFile = PackageFile(ContentFile) + + # + # verify MD5 signature when existed + # + if DistPkg.Header.Signature != '': + Md5Signature = md5(__FileHookOpen__(ContentFile, 'rb').read()) + if DistPkg.Header.Signature != Md5Signature.hexdigest(): + ContentZipFile.Close() + Logger.Error("InstallPkg", FILE_CHECKSUM_FAILURE, + ExtraData=ContentFile) + + return DistPkg, ContentZipFile, DpPkgFileName, DistFile + +## GetPackageList +# +# GetPackageList +# +def GetPackageList(DistPkg, Dep, WorkspaceDir, Options, ContentZipFile, ModuleList, PackageList): + NewDict = Sdict() + for Guid, Version, Path in DistPkg.PackageSurfaceArea: + PackagePath = Path + Package = DistPkg.PackageSurfaceArea[Guid, Version, Path] + Logger.Info(ST.MSG_INSTALL_PACKAGE % Package.GetName()) +# if Dep.CheckPackageExists(Guid, Version): +# Logger.Info(ST.WRN_PACKAGE_EXISTED %(Guid, Version)) + if Options.UseGuidedPkgPath: + GuidedPkgPath = "%s_%s_%s" % (Package.GetName(), Guid, Version) + NewPackagePath = InstallNewPackage(WorkspaceDir, GuidedPkgPath, Options.CustomPath) + else: + NewPackagePath = InstallNewPackage(WorkspaceDir, PackagePath, Options.CustomPath) + InstallPackageContent(PackagePath, NewPackagePath, Package, ContentZipFile, Dep, WorkspaceDir, ModuleList, + DistPkg.Header.ReadOnly) + PackageList.append(Package) + + NewDict[Guid, Version, Package.GetPackagePath()] = Package + + # + # Now generate meta-data files, first generate all dec for package + # dec should be generated before inf, and inf should be generated after + # all packages installed, else hard to resolve modules' package + # dependency (Hard to get the location of the newly installed package) + # + for Package in PackageList: + FilePath = PackageToDec(Package, DistPkg.Header) + Md5Signature = md5(__FileHookOpen__(str(FilePath), 'rb').read()) + Md5Sum = Md5Signature.hexdigest() + if (FilePath, Md5Sum) not in Package.FileList: + Package.FileList.append((FilePath, Md5Sum)) + + return NewDict + +## GetModuleList +# +# GetModuleList +# +def GetModuleList(DistPkg, Dep, WorkspaceDir, ContentZipFile, ModuleList): + # + # ModulePathList will keep track of the standalone module path that + # we just installed. If a new module's path in that list + # (only multiple INF in one directory will be so), we will + # install them directly. If not, we will try to create a new directory + # for it. + # + ModulePathList = [] + + # + # Check module exist and install + # + Module = None + NewDict = Sdict() + for Guid, Version, Name, Path in DistPkg.ModuleSurfaceArea: + ModulePath = Path + Module = DistPkg.ModuleSurfaceArea[Guid, Version, Name, Path] + Logger.Info(ST.MSG_INSTALL_MODULE % Module.GetName()) + if Dep.CheckModuleExists(Guid, Version, Name, Path): + Logger.Quiet(ST.WRN_MODULE_EXISTED %Path) + # + # here check for the multiple inf share the same module path cases: + # they should be installed into the same directory + # + ModuleFullPath = \ + os.path.normpath(os.path.join(WorkspaceDir, ModulePath)) + if ModuleFullPath not in ModulePathList: + NewModulePath = InstallNewModule(WorkspaceDir, ModulePath, ModulePathList) + NewModuleFullPath = os.path.normpath(os.path.join(WorkspaceDir, NewModulePath)) + ModulePathList.append(NewModuleFullPath) + else: + NewModulePath = ModulePath + + InstallModuleContent(ModulePath, NewModulePath, '', Module, ContentZipFile, WorkspaceDir, ModuleList, None, + DistPkg.Header.ReadOnly) + # + # Update module + # + Module.SetModulePath(Module.GetModulePath().replace(Path, NewModulePath, 1)) + + NewDict[Guid, Version, Name, Module.GetModulePath()] = Module + + # + # generate all inf for modules + # + for (Module, Package) in ModuleList: + CheckCNameInModuleRedefined(Module, DistPkg) + FilePath = ModuleToInf(Module, Package, DistPkg.Header) + Md5Signature = md5(__FileHookOpen__(str(FilePath), 'rb').read()) + Md5Sum = Md5Signature.hexdigest() + if Package: + if (FilePath, Md5Sum) not in Package.FileList: + Package.FileList.append((FilePath, Md5Sum)) + else: + if (FilePath, Md5Sum) not in Module.FileList: + Module.FileList.append((FilePath, Md5Sum)) + # + # append the module unicode files to Package FileList + # + for (FilePath, Md5Sum) in Module.FileList: + if str(FilePath).endswith('.uni') and Package and (FilePath, Md5Sum) not in Package.FileList: + Package.FileList.append((FilePath, Md5Sum)) + + return NewDict + +## +# Get all protocol/ppi/guid CNames and pcd name from all dependent DEC file +# +def GetDepProtocolPpiGuidPcdNames(DePackageObjList): + # + # [[Dec1Protocol1, Dec1Protocol2...], [Dec2Protocols...],...] + # + DependentProtocolCNames = [] + DependentPpiCNames = [] + DependentGuidCNames = [] + DependentPcdNames = [] + + for PackageObj in DePackageObjList: + # + # Get protocol CName list from all dependent DEC file + # + ProtocolCNames = [] + for Protocol in PackageObj.GetProtocolList(): + if Protocol.GetCName() not in ProtocolCNames: + ProtocolCNames.append(Protocol.GetCName()) + + DependentProtocolCNames.append(ProtocolCNames) + + # + # Get Ppi CName list from all dependent DEC file + # + PpiCNames = [] + for Ppi in PackageObj.GetPpiList(): + if Ppi.GetCName() not in PpiCNames: + PpiCNames.append(Ppi.GetCName()) + + DependentPpiCNames.append(PpiCNames) + + # + # Get Guid CName list from all dependent DEC file + # + GuidCNames = [] + for Guid in PackageObj.GetGuidList(): + if Guid.GetCName() not in GuidCNames: + GuidCNames.append(Guid.GetCName()) + + DependentGuidCNames.append(GuidCNames) + + # + # Get PcdName list from all dependent DEC file + # + PcdNames = [] + for Pcd in PackageObj.GetPcdList(): + PcdName = '.'.join([Pcd.GetTokenSpaceGuidCName(), Pcd.GetCName()]) + if PcdName not in PcdNames: + PcdNames.append(PcdName) + + DependentPcdNames.append(PcdNames) + + + return DependentProtocolCNames, DependentPpiCNames, DependentGuidCNames, DependentPcdNames + +## +# Check if protocol CName is redefined +# +def CheckProtoclCNameRedefined(Module, DependentProtocolCNames): + for ProtocolInModule in Module.GetProtocolList(): + IsCNameDefined = False + for PackageProtocolCNames in DependentProtocolCNames: + if ProtocolInModule.GetCName() in PackageProtocolCNames: + if IsCNameDefined: + Logger.Error("\nUPT", FORMAT_INVALID, + File = Module.GetFullPath(), + ExtraData = \ + ST.ERR_INF_PARSER_ITEM_DUPLICATE_IN_DEC % ProtocolInModule.GetCName()) + else: + IsCNameDefined = True + +## +# Check if Ppi CName is redefined +# +def CheckPpiCNameRedefined(Module, DependentPpiCNames): + for PpiInModule in Module.GetPpiList(): + IsCNameDefined = False + for PackagePpiCNames in DependentPpiCNames: + if PpiInModule.GetCName() in PackagePpiCNames: + if IsCNameDefined: + Logger.Error("\nUPT", FORMAT_INVALID, + File = Module.GetFullPath(), + ExtraData = ST.ERR_INF_PARSER_ITEM_DUPLICATE_IN_DEC % PpiInModule.GetCName()) + else: + IsCNameDefined = True + +## +# Check if Guid CName is redefined +# +def CheckGuidCNameRedefined(Module, DependentGuidCNames): + for GuidInModule in Module.GetGuidList(): + IsCNameDefined = False + for PackageGuidCNames in DependentGuidCNames: + if GuidInModule.GetCName() in PackageGuidCNames: + if IsCNameDefined: + Logger.Error("\nUPT", FORMAT_INVALID, + File = Module.GetFullPath(), + ExtraData = \ + ST.ERR_INF_PARSER_ITEM_DUPLICATE_IN_DEC % GuidInModule.GetCName()) + else: + IsCNameDefined = True + +## +# Check if PcdName is redefined +# +def CheckPcdNameRedefined(Module, DependentPcdNames): + PcdObjs = [] + if not Module.GetBinaryFileList(): + PcdObjs += Module.GetPcdList() + else: + Binary = Module.GetBinaryFileList()[0] + for AsBuild in Binary.GetAsBuiltList(): + PcdObjs += AsBuild.GetPatchPcdList() + AsBuild.GetPcdExList() + + for PcdObj in PcdObjs: + PcdName = '.'.join([PcdObj.GetTokenSpaceGuidCName(), PcdObj.GetCName()]) + IsPcdNameDefined = False + for PcdNames in DependentPcdNames: + if PcdName in PcdNames: + if IsPcdNameDefined: + Logger.Error("\nUPT", FORMAT_INVALID, + File = Module.GetFullPath(), + ExtraData = ST.ERR_INF_PARSER_ITEM_DUPLICATE_IN_DEC % PcdName) + else: + IsPcdNameDefined = True + +## +# Check if any Protocol/Ppi/Guid and Pcd name is redefined in its dependent DEC files +# +def CheckCNameInModuleRedefined(Module, DistPkg): + DePackageObjList = [] + # + # Get all dependent package objects + # + for Obj in Module.GetPackageDependencyList(): + Guid = Obj.GetGuid() + Version = Obj.GetVersion() + for Key in DistPkg.PackageSurfaceArea: + if Key[0] == Guid and Key[1] == Version: + if DistPkg.PackageSurfaceArea[Key] not in DePackageObjList: + DePackageObjList.append(DistPkg.PackageSurfaceArea[Key]) + + DependentProtocolCNames, DependentPpiCNames, DependentGuidCNames, DependentPcdNames = \ + GetDepProtocolPpiGuidPcdNames(DePackageObjList) + + CheckProtoclCNameRedefined(Module, DependentProtocolCNames) + CheckPpiCNameRedefined(Module, DependentPpiCNames) + CheckGuidCNameRedefined(Module, DependentGuidCNames) + CheckPcdNameRedefined(Module, DependentPcdNames) + +## GenToolMisc +# +# GenToolMisc +# +# +def GenToolMisc(DistPkg, WorkspaceDir, ContentZipFile): + ToolObject = DistPkg.Tools + MiscObject = DistPkg.MiscellaneousFiles + DistPkg.FileList = [] + FileList = [] + ToolFileNum = 0 + FileNum = 0 + RootDir = WorkspaceDir + + # + # FileList stores both tools files and misc files + # Misc file list must be appended to FileList *AFTER* Tools file list + # + if ToolObject: + FileList += ToolObject.GetFileList() + ToolFileNum = len(ToolObject.GetFileList()) + if 'EDK_TOOLS_PATH' in os.environ: + RootDir = os.environ['EDK_TOOLS_PATH'] + if MiscObject: + FileList += MiscObject.GetFileList() + for FileObject in FileList: + FileNum += 1 + if FileNum > ToolFileNum: + # + # Misc files, root should be changed to WORKSPACE + # + RootDir = WorkspaceDir + File = ConvertPath(FileObject.GetURI()) + ToFile = os.path.normpath(os.path.join(RootDir, File)) + if os.path.exists(ToFile): + Logger.Info( ST.WRN_FILE_EXISTED % ToFile ) + # + # ask for user input the new file name + # + Logger.Info( ST.MSG_NEW_FILE_NAME) + Input = stdin.readline() + Input = Input.replace('\r', '').replace('\n', '') + OrigPath = os.path.split(ToFile)[0] + ToFile = os.path.normpath(os.path.join(OrigPath, Input)) + FromFile = os.path.join(FileObject.GetURI()) + Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, DistPkg.Header.ReadOnly, FileObject.GetExecutable()) + DistPkg.FileList.append((ToFile, Md5Sum)) + +## Tool entrance method +# +# This method mainly dispatch specific methods per the command line options. +# If no error found, return zero value so the caller of this tool can know +# if it's executed successfully or not. +# +# @param Options: command Options +# +def Main(Options = None): + try: + DataBase = GlobalData.gDB + WorkspaceDir = GlobalData.gWORKSPACE + if not Options.PackageFile: + Logger.Error("InstallPkg", OPTION_MISSING, ExtraData=ST.ERR_SPECIFY_PACKAGE) + + # Get all Dist Info + DistInfoList = [] + DistPkgList = [] + Index = 1 + for ToBeInstalledDist in Options.PackageFile: + # + # unzip dist.pkg file + # + DistInfoList.append(UnZipDp(WorkspaceDir, ToBeInstalledDist, Index)) + DistPkgList.append(DistInfoList[-1][0]) + Index += 1 + + # + # Add dist + # + GlobalData.gTO_BE_INSTALLED_DIST_LIST.append(DistInfoList[-1][0]) + + # Check for dependency + Dep = DependencyRules(DataBase, DistPkgList) + + for ToBeInstalledDist in DistInfoList: + CheckInstallDpx(Dep, ToBeInstalledDist[0], ToBeInstalledDist[2]) + + # + # Install distribution + # + InstallDp(ToBeInstalledDist[0], ToBeInstalledDist[2], ToBeInstalledDist[1], + Options, Dep, WorkspaceDir, DataBase) + ReturnCode = 0 + + except FatalError as XExcept: + ReturnCode = XExcept.args[0] + if Logger.GetLevel() <= Logger.DEBUG_9: + Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + format_exc()) + + except KeyboardInterrupt: + ReturnCode = ABORT_ERROR + if Logger.GetLevel() <= Logger.DEBUG_9: + Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + format_exc()) + + except: + ReturnCode = CODE_ERROR + Logger.Error( + "\nInstallPkg", + CODE_ERROR, + ST.ERR_UNKNOWN_FATAL_INSTALL_ERR % Options.PackageFile, + ExtraData=ST.MSG_SEARCH_FOR_HELP % ST.MSG_EDKII_MAIL_ADDR, + RaiseError=False + ) + Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), + platform) + format_exc()) + finally: + Logger.Quiet(ST.MSG_REMOVE_TEMP_FILE_STARTED) + for ToBeInstalledDist in DistInfoList: + if ToBeInstalledDist[3]: + ToBeInstalledDist[3].Close() + if ToBeInstalledDist[1]: + ToBeInstalledDist[1].Close() + for TempDir in GlobalData.gUNPACK_DIR: + rmtree(TempDir) + GlobalData.gUNPACK_DIR = [] + Logger.Quiet(ST.MSG_REMOVE_TEMP_FILE_DONE) + if ReturnCode == 0: + Logger.Quiet(ST.MSG_FINISH) + return ReturnCode + +# BackupDist method +# +# This method will backup the Distribution file into the $(WORKSPACE)/conf/upt, and rename it +# if there is already a same-named distribution existed. +# +# @param DpPkgFileName: The distribution path +# @param Guid: The distribution Guid +# @param Version: The distribution Version +# @param WorkspaceDir: The workspace directory +# @retval NewDpPkgFileName: The exact backup file name +# +def BackupDist(DpPkgFileName, Guid, Version, WorkspaceDir): + DistFileName = os.path.split(DpPkgFileName)[1] + DestDir = os.path.normpath(os.path.join(WorkspaceDir, GlobalData.gUPT_DIR)) + CreateDirectory(DestDir) + DestFile = os.path.normpath(os.path.join(DestDir, DistFileName)) + if os.path.exists(DestFile): + FileName, Ext = os.path.splitext(DistFileName) + NewFileName = FileName + '_' + Guid + '_' + Version + Ext + DestFile = os.path.normpath(os.path.join(DestDir, NewFileName)) + if os.path.exists(DestFile): + # + # ask for user input the new file name + # + Logger.Info( ST.MSG_NEW_FILE_NAME_FOR_DIST) + Input = stdin.readline() + Input = Input.replace('\r', '').replace('\n', '') + DestFile = os.path.normpath(os.path.join(DestDir, Input)) + copyfile(DpPkgFileName, DestFile) + NewDpPkgFileName = DestFile[DestFile.find(DestDir) + len(DestDir) + 1:] + return NewDpPkgFileName + +## CheckInstallDpx method +# +# check whether distribution could be installed +# +# @param Dep: the DependencyRules instance that used to check dependency +# @param DistPkg: the distribution object +# +def CheckInstallDpx(Dep, DistPkg, DistPkgFileName): + # + # Check distribution package installed or not + # + if Dep.CheckDpExists(DistPkg.Header.GetGuid(), + DistPkg.Header.GetVersion()): + Logger.Error("InstallPkg", + UPT_ALREADY_INSTALLED_ERROR, + ST.WRN_DIST_PKG_INSTALLED % os.path.basename(DistPkgFileName)) + # + # Check distribution dependency (all module dependency should be + # satisfied) + # + if not Dep.CheckInstallDpDepexSatisfied(DistPkg): + Logger.Error("InstallPkg", UNKNOWN_ERROR, + ST.ERR_PACKAGE_NOT_MATCH_DEPENDENCY, + ExtraData=DistPkg.Header.Name) + +## InstallModuleContent method +# +# If this is standalone module, then Package should be none, +# ModulePath should be '' +# @param FromPath: FromPath +# @param NewPath: NewPath +# @param ModulePath: ModulePath +# @param Module: Module +# @param ContentZipFile: ContentZipFile +# @param WorkspaceDir: WorkspaceDir +# @param ModuleList: ModuleList +# @param Package: Package +# +def InstallModuleContent(FromPath, NewPath, ModulePath, Module, ContentZipFile, + WorkspaceDir, ModuleList, Package = None, ReadOnly = False): + + if NewPath.startswith("\\") or NewPath.startswith("/"): + NewPath = NewPath[1:] + + if not IsValidInstallPath(NewPath): + Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%NewPath) + + NewModuleFullPath = os.path.normpath(os.path.join(WorkspaceDir, NewPath, + ConvertPath(ModulePath))) + Module.SetFullPath(os.path.normpath(os.path.join(NewModuleFullPath, + ConvertPath(Module.GetName()) + '.inf'))) + Module.FileList = [] + + for MiscFile in Module.GetMiscFileList(): + if not MiscFile: + continue + for Item in MiscFile.GetFileList(): + File = Item.GetURI() + if File.startswith("\\") or File.startswith("/"): + File = File[1:] + + if not IsValidInstallPath(File): + Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%File) + + FromFile = os.path.join(FromPath, ModulePath, File) + Executable = Item.GetExecutable() + ToFile = os.path.normpath(os.path.join(NewModuleFullPath, ConvertPath(File))) + Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly, Executable) + if Package and ((ToFile, Md5Sum) not in Package.FileList): + Package.FileList.append((ToFile, Md5Sum)) + elif Package: + continue + elif (ToFile, Md5Sum) not in Module.FileList: + Module.FileList.append((ToFile, Md5Sum)) + for Item in Module.GetSourceFileList(): + File = Item.GetSourceFile() + if File.startswith("\\") or File.startswith("/"): + File = File[1:] + + if not IsValidInstallPath(File): + Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%File) + + FromFile = os.path.join(FromPath, ModulePath, File) + ToFile = os.path.normpath(os.path.join(NewModuleFullPath, ConvertPath(File))) + Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly) + if Package and ((ToFile, Md5Sum) not in Package.FileList): + Package.FileList.append((ToFile, Md5Sum)) + elif Package: + continue + elif (ToFile, Md5Sum) not in Module.FileList: + Module.FileList.append((ToFile, Md5Sum)) + for Item in Module.GetBinaryFileList(): + FileNameList = Item.GetFileNameList() + for FileName in FileNameList: + File = FileName.GetFilename() + if File.startswith("\\") or File.startswith("/"): + File = File[1:] + + if not IsValidInstallPath(File): + Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%File) + + FromFile = os.path.join(FromPath, ModulePath, File) + ToFile = os.path.normpath(os.path.join(NewModuleFullPath, ConvertPath(File))) + Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly) + if Package and ((ToFile, Md5Sum) not in Package.FileList): + Package.FileList.append((ToFile, Md5Sum)) + elif Package: + continue + elif (ToFile, Md5Sum) not in Module.FileList: + Module.FileList.append((ToFile, Md5Sum)) + + InstallModuleContentZipFile(ContentZipFile, FromPath, ModulePath, WorkspaceDir, NewPath, Module, Package, ReadOnly, + ModuleList) + +## InstallModuleContentZipFile +# +# InstallModuleContentZipFile +# +def InstallModuleContentZipFile(ContentZipFile, FromPath, ModulePath, WorkspaceDir, NewPath, Module, Package, ReadOnly, + ModuleList): + # + # Extract other files under current module path in content Zip file but not listed in the description + # + if ContentZipFile: + for FileName in ContentZipFile.GetZipFile().namelist(): + FileName = os.path.normpath(FileName) + CheckPath = os.path.normpath(os.path.join(FromPath, ModulePath)) + if FileUnderPath(FileName, CheckPath): + if FileName.startswith("\\") or FileName.startswith("/"): + FileName = FileName[1:] + + if not IsValidInstallPath(FileName): + Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%FileName) + + FromFile = FileName + ToFile = os.path.normpath(os.path.join(WorkspaceDir, + ConvertPath(FileName.replace(FromPath, NewPath, 1)))) + CheckList = copy.copy(Module.FileList) + if Package: + CheckList += Package.FileList + for Item in CheckList: + if Item[0] == ToFile: + break + else: + Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly) + if Package and ((ToFile, Md5Sum) not in Package.FileList): + Package.FileList.append((ToFile, Md5Sum)) + elif Package: + continue + elif (ToFile, Md5Sum) not in Module.FileList: + Module.FileList.append((ToFile, Md5Sum)) + + ModuleList.append((Module, Package)) + +## FileUnderPath +# Check whether FileName started with directory specified by CheckPath +# +# @param FileName: the FileName need to be checked +# @param CheckPath: the path need to be checked against +# @return: True or False +# +def FileUnderPath(FileName, CheckPath): + FileName = FileName.replace('\\', '/') + FileName = os.path.normpath(FileName) + CheckPath = CheckPath.replace('\\', '/') + CheckPath = os.path.normpath(CheckPath) + if FileName.startswith(CheckPath): + RemainingPath = os.path.normpath(FileName.replace(CheckPath, '', 1)) + while RemainingPath.startswith('\\') or RemainingPath.startswith('/'): + RemainingPath = RemainingPath[1:] + if FileName == os.path.normpath(os.path.join(CheckPath, RemainingPath)): + return True + + return False + +## InstallFile +# Extract File from Zipfile, set file attribute, and return the Md5Sum +# +# @return: True or False +# +def InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly, Executable=False): + if os.path.exists(os.path.normpath(ToFile)): + pass + else: + if not ContentZipFile or not ContentZipFile.UnpackFile(FromFile, ToFile): + Logger.Error("UPT", FILE_NOT_FOUND, ST.ERR_INSTALL_FILE_FROM_EMPTY_CONTENT % FromFile) + + if ReadOnly: + if not Executable: + chmod(ToFile, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH) + else: + chmod(ToFile, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH) + elif Executable: + chmod(ToFile, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | stat.S_IWUSR | stat.S_IWGRP | + stat.S_IWOTH | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH) + else: + chmod(ToFile, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH) + + Md5Signature = md5(__FileHookOpen__(str(ToFile), 'rb').read()) + Md5Sum = Md5Signature.hexdigest() + + return Md5Sum + +## InstallPackageContent method +# +# @param FromPath: FromPath +# @param ToPath: ToPath +# @param Package: Package +# @param ContentZipFile: ContentZipFile +# @param Dep: Dep +# @param WorkspaceDir: WorkspaceDir +# @param ModuleList: ModuleList +# +def InstallPackageContent(FromPath, ToPath, Package, ContentZipFile, Dep, + WorkspaceDir, ModuleList, ReadOnly = False): + if Dep: + pass + Package.FileList = [] + + if ToPath.startswith("\\") or ToPath.startswith("/"): + ToPath = ToPath[1:] + + if not IsValidInstallPath(ToPath): + Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%ToPath) + + if FromPath.startswith("\\") or FromPath.startswith("/"): + FromPath = FromPath[1:] + + if not IsValidInstallPath(FromPath): + Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%FromPath) + + PackageFullPath = os.path.normpath(os.path.join(WorkspaceDir, ToPath)) + for MiscFile in Package.GetMiscFileList(): + for Item in MiscFile.GetFileList(): + FileName = Item.GetURI() + if FileName.startswith("\\") or FileName.startswith("/"): + FileName = FileName[1:] + + if not IsValidInstallPath(FileName): + Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%FileName) + + FromFile = os.path.join(FromPath, FileName) + Executable = Item.GetExecutable() + ToFile = (os.path.join(PackageFullPath, ConvertPath(FileName))) + Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly, Executable) + if (ToFile, Md5Sum) not in Package.FileList: + Package.FileList.append((ToFile, Md5Sum)) + PackageIncludeArchList = [] + for Item in Package.GetPackageIncludeFileList(): + FileName = Item.GetFilePath() + if FileName.startswith("\\") or FileName.startswith("/"): + FileName = FileName[1:] + + if not IsValidInstallPath(FileName): + Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%FileName) + + FromFile = os.path.join(FromPath, FileName) + ToFile = os.path.normpath(os.path.join(PackageFullPath, ConvertPath(FileName))) + RetFile = ContentZipFile.UnpackFile(FromFile, ToFile) + if RetFile == '': + # + # a non-exist path in Zipfile will return '', which means an include directory in our case + # save the information for later DEC creation usage and also create the directory + # + PackageIncludeArchList.append([Item.GetFilePath(), Item.GetSupArchList()]) + CreateDirectory(ToFile) + continue + if ReadOnly: + chmod(ToFile, stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH) + else: + chmod(ToFile, stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH|stat.S_IWUSR|stat.S_IWGRP|stat.S_IWOTH) + Md5Signature = md5(__FileHookOpen__(str(ToFile), 'rb').read()) + Md5Sum = Md5Signature.hexdigest() + if (ToFile, Md5Sum) not in Package.FileList: + Package.FileList.append((ToFile, Md5Sum)) + Package.SetIncludeArchList(PackageIncludeArchList) + + for Item in Package.GetStandardIncludeFileList(): + FileName = Item.GetFilePath() + if FileName.startswith("\\") or FileName.startswith("/"): + FileName = FileName[1:] + + if not IsValidInstallPath(FileName): + Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%FileName) + + FromFile = os.path.join(FromPath, FileName) + ToFile = os.path.normpath(os.path.join(PackageFullPath, ConvertPath(FileName))) + Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly) + if (ToFile, Md5Sum) not in Package.FileList: + Package.FileList.append((ToFile, Md5Sum)) + + # + # Update package + # + Package.SetPackagePath(Package.GetPackagePath().replace(FromPath, + ToPath, 1)) + Package.SetFullPath(os.path.normpath(os.path.join(PackageFullPath, + ConvertPath(Package.GetName()) + '.dec'))) + + # + # Install files in module + # + Module = None + ModuleDict = Package.GetModuleDict() + for ModuleGuid, ModuleVersion, ModuleName, ModulePath in ModuleDict: + Module = ModuleDict[ModuleGuid, ModuleVersion, ModuleName, ModulePath] + InstallModuleContent(FromPath, ToPath, ModulePath, Module, + ContentZipFile, WorkspaceDir, ModuleList, Package, ReadOnly) + +## GetDPFile method +# +# @param ZipFile: A ZipFile +# +def GetDPFile(ZipFile): + ContentFile = '' + DescFile = '' + for FileName in ZipFile.namelist(): + if FileName.endswith('.content'): + if not ContentFile: + ContentFile = FileName + continue + elif FileName.endswith('.pkg'): + if not DescFile: + DescFile = FileName + continue + else: + continue + + Logger.Error("PackagingTool", FILE_TYPE_MISMATCH, + ExtraData=ST.ERR_DIST_FILE_TOOMANY) + if not DescFile or not ContentFile: + Logger.Error("PackagingTool", FILE_UNKNOWN_ERROR, + ExtraData=ST.ERR_DIST_FILE_TOOFEW) + return DescFile, ContentFile + +## InstallDp method +# +# Install the distribution to current workspace +# +def InstallDp(DistPkg, DpPkgFileName, ContentZipFile, Options, Dep, WorkspaceDir, DataBase): + # + # PackageList, ModuleList record the information for the meta-data + # files that need to be generated later + # + PackageList = [] + ModuleList = [] + DistPkg.PackageSurfaceArea = GetPackageList(DistPkg, Dep, WorkspaceDir, Options, + ContentZipFile, ModuleList, PackageList) + + DistPkg.ModuleSurfaceArea = GetModuleList(DistPkg, Dep, WorkspaceDir, ContentZipFile, ModuleList) + + GenToolMisc(DistPkg, WorkspaceDir, ContentZipFile) + + # + # copy "Distribution File" to directory $(WORKSPACE)/conf/upt + # + DistFileName = os.path.split(DpPkgFileName)[1] + NewDpPkgFileName = BackupDist(DpPkgFileName, DistPkg.Header.GetGuid(), DistPkg.Header.GetVersion(), WorkspaceDir) + + # + # update database + # + Logger.Quiet(ST.MSG_UPDATE_PACKAGE_DATABASE) + DataBase.AddDPObject(DistPkg, NewDpPkgFileName, DistFileName, + DistPkg.Header.RePackage) + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/InventoryWs.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/InventoryWs.py new file mode 100755 index 00000000..262c6af5 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/InventoryWs.py @@ -0,0 +1,111 @@ +## @file +# Inventory workspace's distribution package information. +# +# Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +""" +Inventory workspace's distribution package information. +""" +## +# Import Modules +# +from sys import platform +from traceback import format_exc +from platform import python_version + +from Logger import StringTable as ST +from Logger.ToolError import FatalError +from Logger.ToolError import ABORT_ERROR +from Logger.ToolError import CODE_ERROR +import Logger.Log as Logger + +from Library import GlobalData + +## InventoryDistInstalled +# +# This method retrieves the installed distribution information from the internal UPT database +# +# @param DataBase: the UPT database +# +def InventoryDistInstalled(DataBase): + DistInstalled = DataBase.InventoryDistInstalled() + + # + # find the max length for each item + # + DpNameStr = "DpName" + DpGuidStr = "DpGuid" + DpVerStr = "DpVer" + DpOriginalNameStr = "DpOriginalName" + MaxGuidlen = len(DpGuidStr) + MaxVerlen = len(DpVerStr) + MaxDpAliasFileNameLen = len(DpNameStr) + MaxDpOrigFileNamelen = len(DpOriginalNameStr) + + for (DpGuid, DpVersion, DpOriginalName, DpAliasFileName) in DistInstalled: + MaxGuidlen = max(MaxGuidlen, len(DpGuid)) + MaxVerlen = max(MaxVerlen, len(DpVersion)) + MaxDpAliasFileNameLen = max(MaxDpAliasFileNameLen, len(DpAliasFileName)) + MaxDpOrigFileNamelen = max(MaxDpOrigFileNamelen, len(DpOriginalName)) + + OutMsgFmt = "%-*s\t%-*s\t%-*s\t%-s" + OutMsg = OutMsgFmt % (MaxDpAliasFileNameLen, + DpNameStr, + MaxGuidlen, + DpGuidStr, + MaxVerlen, + DpVerStr, + DpOriginalNameStr) + Logger.Info(OutMsg) + + for (DpGuid, DpVersion, DpFileName, DpAliasFileName) in DistInstalled: + OutMsg = OutMsgFmt % (MaxDpAliasFileNameLen, + DpAliasFileName, + MaxGuidlen, + DpGuid, + MaxVerlen, + DpVersion, + DpFileName) + Logger.Info(OutMsg) + +## Tool entrance method +# +# This method mainly dispatch specific methods per the command line options. +# If no error found, return zero value so the caller of this tool can know +# if it's executed successfully or not. +# +# @param Options: command Options +# +def Main(Options = None): + if Options: + pass + + try: + DataBase = GlobalData.gDB + InventoryDistInstalled(DataBase) + ReturnCode = 0 + except FatalError as XExcept: + ReturnCode = XExcept.args[0] + if Logger.GetLevel() <= Logger.DEBUG_9: + Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + format_exc()) + except KeyboardInterrupt: + ReturnCode = ABORT_ERROR + if Logger.GetLevel() <= Logger.DEBUG_9: + Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + format_exc()) + except: + ReturnCode = CODE_ERROR + Logger.Error("\nInventoryWs", + CODE_ERROR, + ST.ERR_UNKNOWN_FATAL_INVENTORYWS_ERR, + ExtraData=ST.MSG_SEARCH_FOR_HELP % ST.MSG_EDKII_MAIL_ADDR, + RaiseError=False + ) + Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), + platform) + format_exc()) + + if ReturnCode == 0: + Logger.Quiet(ST.MSG_FINISH) + + return ReturnCode diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/CommentGenerating.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/CommentGenerating.py new file mode 100755 index 00000000..0994cb69 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/CommentGenerating.py @@ -0,0 +1,238 @@ +## @file +# This file is used to define comment generating interface +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +CommentGenerating +''' + +## +# Import Modules +# +from Library.StringUtils import GetSplitValueList +from Library.DataType import TAB_SPACE_SPLIT +from Library.DataType import TAB_INF_GUIDTYPE_VAR +from Library.DataType import USAGE_ITEM_NOTIFY +from Library.DataType import ITEM_UNDEFINED +from Library.DataType import TAB_HEADER_COMMENT +from Library.DataType import TAB_BINARY_HEADER_COMMENT +from Library.DataType import TAB_COMMENT_SPLIT +from Library.DataType import TAB_SPECIAL_COMMENT +from Library.DataType import END_OF_LINE +from Library.DataType import TAB_COMMENT_EDK1_SPLIT +from Library.DataType import TAB_COMMENT_EDK1_START +from Library.DataType import TAB_COMMENT_EDK1_END +from Library.DataType import TAB_STAR +from Library.DataType import TAB_PCD_PROMPT +from Library.UniClassObject import ConvertSpecialUnicodes +from Library.Misc import GetLocalValue +## GenTailCommentLines +# +# @param TailCommentLines: the tail comment lines that need to be generated +# @param LeadingSpaceNum: the number of leading space needed for non-first +# line tail comment +# +def GenTailCommentLines (TailCommentLines, LeadingSpaceNum = 0): + TailCommentLines = TailCommentLines.rstrip(END_OF_LINE) + CommentStr = TAB_SPACE_SPLIT*2 + TAB_SPECIAL_COMMENT + TAB_SPACE_SPLIT + \ + (END_OF_LINE + LeadingSpaceNum * TAB_SPACE_SPLIT + TAB_SPACE_SPLIT*2 + TAB_SPECIAL_COMMENT + \ + TAB_SPACE_SPLIT).join(GetSplitValueList(TailCommentLines, END_OF_LINE)) + + return CommentStr + +## GenGenericComment +# +# @param CommentLines: Generic comment Text, maybe Multiple Lines +# +def GenGenericComment (CommentLines): + if not CommentLines: + return '' + CommentLines = CommentLines.rstrip(END_OF_LINE) + CommentStr = TAB_SPECIAL_COMMENT + TAB_SPACE_SPLIT + (END_OF_LINE + TAB_COMMENT_SPLIT + TAB_SPACE_SPLIT).join\ + (GetSplitValueList(CommentLines, END_OF_LINE)) + END_OF_LINE + return CommentStr + +## GenGenericCommentF +# +# similar to GenGenericComment but will remove at end of comment once, +# and for line with only , '#\n' will be generated instead of '# \n' +# +# @param CommentLines: Generic comment Text, maybe Multiple Lines +# @return CommentStr: Generated comment line +# +def GenGenericCommentF (CommentLines, NumOfPound=1, IsPrompt=False, IsInfLibraryClass=False): + if not CommentLines: + return '' + # + # if comment end with '\n', then remove it to prevent one extra line + # generate later on + # + if CommentLines.endswith(END_OF_LINE): + CommentLines = CommentLines[:-1] + CommentStr = '' + if IsPrompt: + CommentStr += TAB_COMMENT_SPLIT * NumOfPound + TAB_SPACE_SPLIT + TAB_PCD_PROMPT + TAB_SPACE_SPLIT + \ + CommentLines.replace(END_OF_LINE, '') + END_OF_LINE + else: + CommentLineList = GetSplitValueList(CommentLines, END_OF_LINE) + FindLibraryClass = False + for Line in CommentLineList: + # If this comment is for @libraryclass and it has multiple lines + # make sure the second lines align to the first line after @libraryclass as below + # + # ## @libraryclass XYZ FIRST_LINE + # ## ABC SECOND_LINE + # + if IsInfLibraryClass and Line.find(u'@libraryclass ') > -1: + FindLibraryClass = True + if Line == '': + CommentStr += TAB_COMMENT_SPLIT * NumOfPound + END_OF_LINE + else: + if FindLibraryClass and Line.find(u'@libraryclass ') > -1: + CommentStr += TAB_COMMENT_SPLIT * NumOfPound + TAB_SPACE_SPLIT + Line + END_OF_LINE + elif FindLibraryClass: + CommentStr += TAB_COMMENT_SPLIT * NumOfPound + TAB_SPACE_SPLIT * 16 + Line + END_OF_LINE + else: + CommentStr += TAB_COMMENT_SPLIT * NumOfPound + TAB_SPACE_SPLIT + Line + END_OF_LINE + + return CommentStr + + +## GenHeaderCommentSection +# +# Generate Header comment sections +# +# @param Abstract One line of abstract +# @param Description multiple lines of Description +# @param Copyright possible multiple copyright lines +# @param License possible multiple license lines +# +def GenHeaderCommentSection(Abstract, Description, Copyright, License, IsBinaryHeader=False, \ + CommChar=TAB_COMMENT_SPLIT): + Content = '' + + # + # Convert special character to (c), (r) and (tm). + # + Abstract = ConvertSpecialUnicodes(Abstract) + Description = ConvertSpecialUnicodes(Description) + if IsBinaryHeader: + Content += CommChar * 2 + TAB_SPACE_SPLIT + TAB_BINARY_HEADER_COMMENT + '\r\n' + elif CommChar == TAB_COMMENT_EDK1_SPLIT: + Content += CommChar + TAB_SPACE_SPLIT + TAB_COMMENT_EDK1_START + TAB_STAR + TAB_SPACE_SPLIT +\ + TAB_HEADER_COMMENT + '\r\n' + else: + Content += CommChar * 2 + TAB_SPACE_SPLIT + TAB_HEADER_COMMENT + '\r\n' + if Abstract: + Abstract = Abstract.rstrip('\r\n') + Content += CommChar + TAB_SPACE_SPLIT + ('\r\n' + CommChar + TAB_SPACE_SPLIT).join(GetSplitValueList\ + (Abstract, '\n')) + Content += '\r\n' + CommChar + '\r\n' + else: + Content += CommChar + '\r\n' + + if Description: + Description = Description.rstrip('\r\n') + Content += CommChar + TAB_SPACE_SPLIT + ('\r\n' + CommChar + TAB_SPACE_SPLIT).join(GetSplitValueList\ + (Description, '\n')) + Content += '\r\n' + CommChar + '\r\n' + + # + # There is no '#\n' line to separate multiple copyright lines in code base + # + if Copyright: + Copyright = Copyright.rstrip('\r\n') + Content += CommChar + TAB_SPACE_SPLIT + ('\r\n' + CommChar + TAB_SPACE_SPLIT).join\ + (GetSplitValueList(Copyright, '\n')) + Content += '\r\n' + CommChar + '\r\n' + + if License: + License = License.rstrip('\r\n') + Content += CommChar + TAB_SPACE_SPLIT + ('\r\n' + CommChar + TAB_SPACE_SPLIT).join(GetSplitValueList\ + (License, '\n')) + Content += '\r\n' + CommChar + '\r\n' + + if CommChar == TAB_COMMENT_EDK1_SPLIT: + Content += CommChar + TAB_SPACE_SPLIT + TAB_STAR + TAB_COMMENT_EDK1_END + '\r\n' + else: + Content += CommChar * 2 + '\r\n' + + return Content + + +## GenInfPcdTailComment +# Generate Pcd tail comment for Inf, this would be one line comment +# +# @param Usage: Usage type +# @param TailCommentText: Comment text for tail comment +# +def GenInfPcdTailComment (Usage, TailCommentText): + if (Usage == ITEM_UNDEFINED) and (not TailCommentText): + return '' + + CommentLine = TAB_SPACE_SPLIT.join([Usage, TailCommentText]) + return GenTailCommentLines(CommentLine) + +## GenInfProtocolPPITailComment +# Generate Protocol/PPI tail comment for Inf +# +# @param Usage: Usage type +# @param TailCommentText: Comment text for tail comment +# +def GenInfProtocolPPITailComment (Usage, Notify, TailCommentText): + if (not Notify) and (Usage == ITEM_UNDEFINED) and (not TailCommentText): + return '' + + if Notify: + CommentLine = USAGE_ITEM_NOTIFY + " ## " + else: + CommentLine = '' + + CommentLine += TAB_SPACE_SPLIT.join([Usage, TailCommentText]) + return GenTailCommentLines(CommentLine) + +## GenInfGuidTailComment +# Generate Guid tail comment for Inf +# +# @param Usage: Usage type +# @param TailCommentText: Comment text for tail comment +# +def GenInfGuidTailComment (Usage, GuidTypeList, VariableName, TailCommentText): + GuidType = GuidTypeList[0] + if (Usage == ITEM_UNDEFINED) and (GuidType == ITEM_UNDEFINED) and \ + (not TailCommentText): + return '' + + FirstLine = Usage + " ## " + GuidType + if GuidType == TAB_INF_GUIDTYPE_VAR: + FirstLine += ":" + VariableName + + CommentLine = TAB_SPACE_SPLIT.join([FirstLine, TailCommentText]) + return GenTailCommentLines(CommentLine) + +## GenDecGuidTailComment +# +# @param SupModuleList: Supported module type list +# +def GenDecTailComment (SupModuleList): + CommentLine = TAB_SPACE_SPLIT.join(SupModuleList) + return GenTailCommentLines(CommentLine) + + +## _GetHelpStr +# get HelpString from a list of HelpTextObject, the priority refer to +# related HLD +# +# @param HelpTextObjList: List of HelpTextObject +# +# @return HelpStr: the help text string found, '' means no help text found +# +def _GetHelpStr(HelpTextObjList): + ValueList = [] + for HelpObj in HelpTextObjList: + ValueList.append((HelpObj.GetLang(), HelpObj.GetString())) + return GetLocalValue(ValueList, True) diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/CommentParsing.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/CommentParsing.py new file mode 100755 index 00000000..3f450358 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/CommentParsing.py @@ -0,0 +1,593 @@ +## @file +# This file is used to define comment parsing interface +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +CommentParsing +''' + +## +# Import Modules +# +import re + +from Library.StringUtils import GetSplitValueList +from Library.StringUtils import CleanString2 +from Library.DataType import HEADER_COMMENT_NOT_STARTED +from Library.DataType import TAB_COMMENT_SPLIT +from Library.DataType import HEADER_COMMENT_LICENSE +from Library.DataType import HEADER_COMMENT_ABSTRACT +from Library.DataType import HEADER_COMMENT_COPYRIGHT +from Library.DataType import HEADER_COMMENT_DESCRIPTION +from Library.DataType import TAB_SPACE_SPLIT +from Library.DataType import TAB_COMMA_SPLIT +from Library.DataType import SUP_MODULE_LIST +from Library.DataType import TAB_VALUE_SPLIT +from Library.DataType import TAB_PCD_VALIDRANGE +from Library.DataType import TAB_PCD_VALIDLIST +from Library.DataType import TAB_PCD_EXPRESSION +from Library.DataType import TAB_PCD_PROMPT +from Library.DataType import TAB_CAPHEX_START +from Library.DataType import TAB_HEX_START +from Library.DataType import PCD_ERR_CODE_MAX_SIZE +from Library.ExpressionValidate import IsValidRangeExpr +from Library.ExpressionValidate import IsValidListExpr +from Library.ExpressionValidate import IsValidLogicalExpr +from Object.POM.CommonObject import TextObject +from Object.POM.CommonObject import PcdErrorObject +import Logger.Log as Logger +from Logger.ToolError import FORMAT_INVALID +from Logger.ToolError import FORMAT_NOT_SUPPORTED +from Logger import StringTable as ST + +## ParseHeaderCommentSection +# +# Parse Header comment section lines, extract Abstract, Description, Copyright +# , License lines +# +# @param CommentList: List of (Comment, LineNumber) +# @param FileName: FileName of the comment +# +def ParseHeaderCommentSection(CommentList, FileName = None, IsBinaryHeader = False): + Abstract = '' + Description = '' + Copyright = '' + License = '' + EndOfLine = "\n" + if IsBinaryHeader: + STR_HEADER_COMMENT_START = "@BinaryHeader" + else: + STR_HEADER_COMMENT_START = "@file" + HeaderCommentStage = HEADER_COMMENT_NOT_STARTED + + # + # first find the last copyright line + # + Last = 0 + for Index in range(len(CommentList)-1, 0, -1): + Line = CommentList[Index][0] + if _IsCopyrightLine(Line): + Last = Index + break + + for Item in CommentList: + Line = Item[0] + LineNo = Item[1] + + if not Line.startswith(TAB_COMMENT_SPLIT) and Line: + Logger.Error("\nUPT", FORMAT_INVALID, ST.ERR_INVALID_COMMENT_FORMAT, FileName, Item[1]) + Comment = CleanString2(Line)[1] + Comment = Comment.strip() + # + # if there are blank lines between License or Description, keep them as they would be + # indication of different block; or in the position that Abstract should be, also keep it + # as it indicates that no abstract + # + if not Comment and HeaderCommentStage not in [HEADER_COMMENT_LICENSE, \ + HEADER_COMMENT_DESCRIPTION, HEADER_COMMENT_ABSTRACT]: + continue + + if HeaderCommentStage == HEADER_COMMENT_NOT_STARTED: + if Comment.startswith(STR_HEADER_COMMENT_START): + HeaderCommentStage = HEADER_COMMENT_ABSTRACT + else: + License += Comment + EndOfLine + else: + if HeaderCommentStage == HEADER_COMMENT_ABSTRACT: + # + # in case there is no abstract and description + # + if not Comment: + HeaderCommentStage = HEADER_COMMENT_DESCRIPTION + elif _IsCopyrightLine(Comment): + Result, ErrMsg = _ValidateCopyright(Comment) + ValidateCopyright(Result, ST.WRN_INVALID_COPYRIGHT, FileName, LineNo, ErrMsg) + Copyright += Comment + EndOfLine + HeaderCommentStage = HEADER_COMMENT_COPYRIGHT + else: + Abstract += Comment + EndOfLine + HeaderCommentStage = HEADER_COMMENT_DESCRIPTION + elif HeaderCommentStage == HEADER_COMMENT_DESCRIPTION: + # + # in case there is no description + # + if _IsCopyrightLine(Comment): + Result, ErrMsg = _ValidateCopyright(Comment) + ValidateCopyright(Result, ST.WRN_INVALID_COPYRIGHT, FileName, LineNo, ErrMsg) + Copyright += Comment + EndOfLine + HeaderCommentStage = HEADER_COMMENT_COPYRIGHT + else: + Description += Comment + EndOfLine + elif HeaderCommentStage == HEADER_COMMENT_COPYRIGHT: + if _IsCopyrightLine(Comment): + Result, ErrMsg = _ValidateCopyright(Comment) + ValidateCopyright(Result, ST.WRN_INVALID_COPYRIGHT, FileName, LineNo, ErrMsg) + Copyright += Comment + EndOfLine + else: + # + # Contents after copyright line are license, those non-copyright lines in between + # copyright line will be discarded + # + if LineNo > Last: + if License: + License += EndOfLine + License += Comment + EndOfLine + HeaderCommentStage = HEADER_COMMENT_LICENSE + else: + if not Comment and not License: + continue + License += Comment + EndOfLine + + return Abstract.strip(), Description.strip(), Copyright.strip(), License.strip() + +## _IsCopyrightLine +# check whether current line is copyright line, the criteria is whether there is case insensitive keyword "Copyright" +# followed by zero or more white space characters followed by a "(" character +# +# @param LineContent: the line need to be checked +# @return: True if current line is copyright line, False else +# +def _IsCopyrightLine (LineContent): + LineContent = LineContent.upper() + Result = False + + ReIsCopyrightRe = re.compile(r"""(^|\s)COPYRIGHT *\(""", re.DOTALL) + if ReIsCopyrightRe.search(LineContent): + Result = True + + return Result + +## ParseGenericComment +# +# @param GenericComment: Generic comment list, element of +# (CommentLine, LineNum) +# @param ContainerFile: Input value for filename of Dec file +# +def ParseGenericComment (GenericComment, ContainerFile=None, SkipTag=None): + if ContainerFile: + pass + HelpTxt = None + HelpStr = '' + + for Item in GenericComment: + CommentLine = Item[0] + Comment = CleanString2(CommentLine)[1] + if SkipTag is not None and Comment.startswith(SkipTag): + Comment = Comment.replace(SkipTag, '', 1) + HelpStr += Comment + '\n' + + if HelpStr: + HelpTxt = TextObject() + if HelpStr.endswith('\n') and not HelpStr.endswith('\n\n') and HelpStr != '\n': + HelpStr = HelpStr[:-1] + HelpTxt.SetString(HelpStr) + + return HelpTxt + +## ParsePcdErrorCode +# +# @param Value: original ErrorCode value +# @param ContainerFile: Input value for filename of Dec file +# @param LineNum: Line Num +# +def ParsePcdErrorCode (Value = None, ContainerFile = None, LineNum = None): + try: + if Value.strip().startswith((TAB_HEX_START, TAB_CAPHEX_START)): + Base = 16 + else: + Base = 10 + ErrorCode = int(Value, Base) + if ErrorCode > PCD_ERR_CODE_MAX_SIZE or ErrorCode < 0: + Logger.Error('Parser', + FORMAT_NOT_SUPPORTED, + "The format %s of ErrorCode is not valid, should be UNIT32 type or long type" % Value, + File = ContainerFile, + Line = LineNum) + ErrorCode = '0x%x' % ErrorCode + return ErrorCode + except ValueError as XStr: + if XStr: + pass + Logger.Error('Parser', + FORMAT_NOT_SUPPORTED, + "The format %s of ErrorCode is not valid, should be UNIT32 type or long type" % Value, + File = ContainerFile, + Line = LineNum) + +## ParseDecPcdGenericComment +# +# @param GenericComment: Generic comment list, element of (CommentLine, +# LineNum) +# @param ContainerFile: Input value for filename of Dec file +# +def ParseDecPcdGenericComment (GenericComment, ContainerFile, TokenSpaceGuidCName, CName, MacroReplaceDict): + HelpStr = '' + PromptStr = '' + PcdErr = None + PcdErrList = [] + ValidValueNum = 0 + ValidRangeNum = 0 + ExpressionNum = 0 + + for (CommentLine, LineNum) in GenericComment: + Comment = CleanString2(CommentLine)[1] + # + # To replace Macro + # + MACRO_PATTERN = '[\t\s]*\$\([A-Z][_A-Z0-9]*\)' + MatchedStrs = re.findall(MACRO_PATTERN, Comment) + for MatchedStr in MatchedStrs: + if MatchedStr: + Macro = MatchedStr.strip().lstrip('$(').rstrip(')').strip() + if Macro in MacroReplaceDict: + Comment = Comment.replace(MatchedStr, MacroReplaceDict[Macro]) + if Comment.startswith(TAB_PCD_VALIDRANGE): + if ValidValueNum > 0 or ExpressionNum > 0: + Logger.Error('Parser', + FORMAT_NOT_SUPPORTED, + ST.WRN_MULTI_PCD_RANGES, + File = ContainerFile, + Line = LineNum) + else: + PcdErr = PcdErrorObject() + PcdErr.SetTokenSpaceGuidCName(TokenSpaceGuidCName) + PcdErr.SetCName(CName) + PcdErr.SetFileLine(Comment) + PcdErr.SetLineNum(LineNum) + ValidRangeNum += 1 + ValidRange = Comment.replace(TAB_PCD_VALIDRANGE, "", 1).strip() + Valid, Cause = _CheckRangeExpression(ValidRange) + if Valid: + ValueList = ValidRange.split(TAB_VALUE_SPLIT) + if len(ValueList) > 1: + PcdErr.SetValidValueRange((TAB_VALUE_SPLIT.join(ValueList[1:])).strip()) + PcdErr.SetErrorNumber(ParsePcdErrorCode(ValueList[0], ContainerFile, LineNum)) + else: + PcdErr.SetValidValueRange(ValidRange) + PcdErrList.append(PcdErr) + else: + Logger.Error("Parser", + FORMAT_NOT_SUPPORTED, + Cause, + ContainerFile, + LineNum) + elif Comment.startswith(TAB_PCD_VALIDLIST): + if ValidRangeNum > 0 or ExpressionNum > 0: + Logger.Error('Parser', + FORMAT_NOT_SUPPORTED, + ST.WRN_MULTI_PCD_RANGES, + File = ContainerFile, + Line = LineNum) + elif ValidValueNum > 0: + Logger.Error('Parser', + FORMAT_NOT_SUPPORTED, + ST.WRN_MULTI_PCD_VALIDVALUE, + File = ContainerFile, + Line = LineNum) + else: + PcdErr = PcdErrorObject() + PcdErr.SetTokenSpaceGuidCName(TokenSpaceGuidCName) + PcdErr.SetCName(CName) + PcdErr.SetFileLine(Comment) + PcdErr.SetLineNum(LineNum) + ValidValueNum += 1 + ValidValueExpr = Comment.replace(TAB_PCD_VALIDLIST, "", 1).strip() + Valid, Cause = _CheckListExpression(ValidValueExpr) + if Valid: + ValidValue = Comment.replace(TAB_PCD_VALIDLIST, "", 1).replace(TAB_COMMA_SPLIT, TAB_SPACE_SPLIT) + ValueList = ValidValue.split(TAB_VALUE_SPLIT) + if len(ValueList) > 1: + PcdErr.SetValidValue((TAB_VALUE_SPLIT.join(ValueList[1:])).strip()) + PcdErr.SetErrorNumber(ParsePcdErrorCode(ValueList[0], ContainerFile, LineNum)) + else: + PcdErr.SetValidValue(ValidValue) + PcdErrList.append(PcdErr) + else: + Logger.Error("Parser", + FORMAT_NOT_SUPPORTED, + Cause, + ContainerFile, + LineNum) + elif Comment.startswith(TAB_PCD_EXPRESSION): + if ValidRangeNum > 0 or ValidValueNum > 0: + Logger.Error('Parser', + FORMAT_NOT_SUPPORTED, + ST.WRN_MULTI_PCD_RANGES, + File = ContainerFile, + Line = LineNum) + else: + PcdErr = PcdErrorObject() + PcdErr.SetTokenSpaceGuidCName(TokenSpaceGuidCName) + PcdErr.SetCName(CName) + PcdErr.SetFileLine(Comment) + PcdErr.SetLineNum(LineNum) + ExpressionNum += 1 + Expression = Comment.replace(TAB_PCD_EXPRESSION, "", 1).strip() + Valid, Cause = _CheckExpression(Expression) + if Valid: + ValueList = Expression.split(TAB_VALUE_SPLIT) + if len(ValueList) > 1: + PcdErr.SetExpression((TAB_VALUE_SPLIT.join(ValueList[1:])).strip()) + PcdErr.SetErrorNumber(ParsePcdErrorCode(ValueList[0], ContainerFile, LineNum)) + else: + PcdErr.SetExpression(Expression) + PcdErrList.append(PcdErr) + else: + Logger.Error("Parser", + FORMAT_NOT_SUPPORTED, + Cause, + ContainerFile, + LineNum) + elif Comment.startswith(TAB_PCD_PROMPT): + if PromptStr: + Logger.Error('Parser', + FORMAT_NOT_SUPPORTED, + ST.WRN_MULTI_PCD_PROMPT, + File = ContainerFile, + Line = LineNum) + PromptStr = Comment.replace(TAB_PCD_PROMPT, "", 1).strip() + else: + if Comment: + HelpStr += Comment + '\n' + + # + # remove the last EOL if the comment is of format 'FOO\n' + # + if HelpStr.endswith('\n'): + if HelpStr != '\n' and not HelpStr.endswith('\n\n'): + HelpStr = HelpStr[:-1] + + return HelpStr, PcdErrList, PromptStr + +## ParseDecPcdTailComment +# +# @param TailCommentList: Tail comment list of Pcd, item of format (Comment, LineNum) +# @param ContainerFile: Input value for filename of Dec file +# @retVal SupModuleList: The supported module type list detected +# @retVal HelpStr: The generic help text string detected +# +def ParseDecPcdTailComment (TailCommentList, ContainerFile): + assert(len(TailCommentList) == 1) + TailComment = TailCommentList[0][0] + LineNum = TailCommentList[0][1] + + Comment = TailComment.lstrip(" #") + + ReFindFirstWordRe = re.compile(r"""^([^ #]*)""", re.DOTALL) + + # + # get first word and compare with SUP_MODULE_LIST + # + MatchObject = ReFindFirstWordRe.match(Comment) + if not (MatchObject and MatchObject.group(1) in SUP_MODULE_LIST): + return None, Comment + + # + # parse line, it must have supported module type specified + # + if Comment.find(TAB_COMMENT_SPLIT) == -1: + Comment += TAB_COMMENT_SPLIT + SupMode, HelpStr = GetSplitValueList(Comment, TAB_COMMENT_SPLIT, 1) + SupModuleList = [] + for Mod in GetSplitValueList(SupMode, TAB_SPACE_SPLIT): + if not Mod: + continue + elif Mod not in SUP_MODULE_LIST: + Logger.Error("UPT", + FORMAT_INVALID, + ST.WRN_INVALID_MODULE_TYPE%Mod, + ContainerFile, + LineNum) + else: + SupModuleList.append(Mod) + + return SupModuleList, HelpStr + +## _CheckListExpression +# +# @param Expression: Pcd value list expression +# +def _CheckListExpression(Expression): + ListExpr = '' + if TAB_VALUE_SPLIT in Expression: + ListExpr = Expression[Expression.find(TAB_VALUE_SPLIT)+1:] + else: + ListExpr = Expression + + return IsValidListExpr(ListExpr) + +## _CheckExpression +# +# @param Expression: Pcd value expression +# +def _CheckExpression(Expression): + Expr = '' + if TAB_VALUE_SPLIT in Expression: + Expr = Expression[Expression.find(TAB_VALUE_SPLIT)+1:] + else: + Expr = Expression + return IsValidLogicalExpr(Expr, True) + +## _CheckRangeExpression +# +# @param Expression: Pcd range expression +# +def _CheckRangeExpression(Expression): + RangeExpr = '' + if TAB_VALUE_SPLIT in Expression: + RangeExpr = Expression[Expression.find(TAB_VALUE_SPLIT)+1:] + else: + RangeExpr = Expression + + return IsValidRangeExpr(RangeExpr) + +## ValidateCopyright +# +# +# +def ValidateCopyright(Result, ErrType, FileName, LineNo, ErrMsg): + if not Result: + Logger.Warn("\nUPT", ErrType, FileName, LineNo, ErrMsg) + +## _ValidateCopyright +# +# @param Line: Line that contains copyright information, # stripped +# +# @retval Result: True if line is conformed to Spec format, False else +# @retval ErrMsg: the detailed error description +# +def _ValidateCopyright(Line): + if Line: + pass + Result = True + ErrMsg = '' + + return Result, ErrMsg + +def GenerateTokenList (Comment): + # + # Tokenize Comment using '#' and ' ' as token separators + # + ReplacedComment = None + while Comment != ReplacedComment: + ReplacedComment = Comment + Comment = Comment.replace('##', '#').replace(' ', ' ').replace(' ', '#').strip('# ') + return Comment.split('#') + + +# +# Comment - Comment to parse +# TypeTokens - A dictionary of type token synonyms +# RemoveTokens - A list of tokens to remove from help text +# ParseVariable - True for parsing [Guids]. Otherwise False +# +def ParseComment (Comment, UsageTokens, TypeTokens, RemoveTokens, ParseVariable): + # + # Initialize return values + # + Usage = None + Type = None + String = None + + Comment = Comment[0] + + NumTokens = 2 + if ParseVariable: + # + # Remove white space around first instance of ':' from Comment if 'Variable' + # is in front of ':' and Variable is the 1st or 2nd token in Comment. + # + List = Comment.split(':', 1) + if len(List) > 1: + SubList = GenerateTokenList (List[0].strip()) + if len(SubList) in [1, 2] and SubList[-1] == 'Variable': + if List[1].strip().find('L"') == 0: + Comment = List[0].strip() + ':' + List[1].strip() + + # + # Remove first instance of L" from Comment and put into String + # if and only if L"" is the 1st token, the 2nd token. Or + # L"" is the third token immediately following 'Variable:'. + # + End = -1 + Start = Comment.find('Variable:L"') + if Start >= 0: + String = Comment[Start + 9:] + End = String[2:].find('"') + else: + Start = Comment.find('L"') + if Start >= 0: + String = Comment[Start:] + End = String[2:].find('"') + if End >= 0: + SubList = GenerateTokenList (Comment[:Start]) + if len(SubList) < 2: + Comment = Comment[:Start] + String[End + 3:] + String = String[:End + 3] + Type = 'Variable' + NumTokens = 1 + + # + # Initialize HelpText to Comment. + # Content will be remove from HelpText as matching tokens are found + # + HelpText = Comment + + # + # Tokenize Comment using '#' and ' ' as token separators + # + List = GenerateTokenList (Comment) + + # + # Search first two tokens for Usage and Type and remove any matching tokens + # from HelpText + # + for Token in List[0:NumTokens]: + if Usage is None and Token in UsageTokens: + Usage = UsageTokens[Token] + HelpText = HelpText.replace(Token, '') + if Usage is not None or not ParseVariable: + for Token in List[0:NumTokens]: + if Type is None and Token in TypeTokens: + Type = TypeTokens[Token] + HelpText = HelpText.replace(Token, '') + if Usage is not None: + for Token in List[0:NumTokens]: + if Token in RemoveTokens: + HelpText = HelpText.replace(Token, '') + + # + # If no Usage token is present and set Usage to UNDEFINED + # + if Usage is None: + Usage = 'UNDEFINED' + + # + # If no Type token is present and set Type to UNDEFINED + # + if Type is None: + Type = 'UNDEFINED' + + # + # If Type is not 'Variable:', then set String to None + # + if Type != 'Variable': + String = None + + # + # Strip ' ' and '#' from the beginning of HelpText + # If HelpText is an empty string after all parsing is + # complete then set HelpText to None + # + HelpText = HelpText.lstrip('# ') + if HelpText == '': + HelpText = None + + # + # Return parsing results + # + return Usage, Type, String, HelpText diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/DataType.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/DataType.py new file mode 100644 index 00000000..3fd6c03f --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/DataType.py @@ -0,0 +1,949 @@ +## @file +# This file is used to define class for data type structure +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +''' +DataType +''' + +## +# Module List Items +# +MODULE_LIST = ["BASE", + "SEC", + "PEI_CORE", + "PEIM", + "DXE_CORE", + "DXE_DRIVER", + "SMM_CORE", + "DXE_RUNTIME_DRIVER", + "DXE_SAL_DRIVER", + "DXE_SMM_DRIVER", + "UEFI_DRIVER", + "UEFI_APPLICATION", + "USER_DEFINED"] + +VALID_DEPEX_MODULE_TYPE_LIST = ["PEIM", + "DXE_DRIVER", + "DXE_SMM_DRIVER", + "DXE_RUNTIME_DRIVER", + "DXE_SAL_DRIVER", + "UEFI_DRIVER", + ] +## +# Usage List Items +# +USAGE_LIST = ["CONSUMES", + "SOMETIMES_CONSUMES", + "PRODUCES", + "SOMETIMES_PRODUCES"] + +TAB_LANGUAGE_EN_US = 'en-US' +TAB_LANGUAGE_ENG = 'eng' +TAB_LANGUAGE_EN = 'en' +TAB_LANGUAGE_EN_X = 'en-x-tianocore' + +USAGE_ITEM_PRODUCES = 'PRODUCES' +USAGE_ITEM_SOMETIMES_PRODUCES = 'SOMETIMES_PRODUCES' +USAGE_ITEM_CONSUMES = 'CONSUMES' +USAGE_ITEM_SOMETIMES_CONSUMES = 'SOMETIMES_CONSUMES' +USAGE_ITEM_TO_START = 'TO_START' +USAGE_ITEM_BY_START = 'BY_START' +USAGE_ITEM_NOTIFY = 'NOTIFY' +USAGE_ITEM_UNDEFINED = 'UNDEFINED' + +USAGE_CONSUMES_LIST = [USAGE_ITEM_CONSUMES, + 'CONSUMED', + 'ALWAYS_CONSUMED', + 'ALWAYS_CONSUMES' + ] + +USAGE_PRODUCES_LIST = [USAGE_ITEM_PRODUCES, + 'PRODUCED', + 'ALWAYS_PRODUCED', + 'ALWAYS_PRODUCES' + ] + +USAGE_SOMETIMES_PRODUCES_LIST = [USAGE_ITEM_SOMETIMES_PRODUCES, + 'SOMETIMES_PRODUCED' + ] + +USAGE_SOMETIMES_CONSUMES_LIST = [USAGE_ITEM_SOMETIMES_CONSUMES, + 'SOMETIMES_CONSUMED' + ] + +ITEM_UNDEFINED = 'UNDEFINED' + +TAB_PCD_VALIDRANGE = '@ValidRange' +TAB_PCD_VALIDLIST = '@ValidList' +TAB_PCD_EXPRESSION = '@Expression' +TAB_PCD_PROMPT = '@Prompt' +TAB_STR_TOKENCNAME = 'STR' +TAB_STR_TOKENPROMPT = 'PROMPT' +TAB_STR_TOKENHELP = 'HELP' +TAB_STR_TOKENERR = 'ERR' + +# +# Dictionary of usage tokens and their synonyms +# +ALL_USAGE_TOKENS = { + "PRODUCES" : "PRODUCES", + "PRODUCED" : "PRODUCES", + "ALWAYS_PRODUCES" : "PRODUCES", + "ALWAYS_PRODUCED" : "PRODUCES", + "SOMETIMES_PRODUCES" : "SOMETIMES_PRODUCES", + "SOMETIMES_PRODUCED" : "SOMETIMES_PRODUCES", + "CONSUMES" : "CONSUMES", + "CONSUMED" : "CONSUMES", + "ALWAYS_CONSUMES" : "CONSUMES", + "ALWAYS_CONSUMED" : "CONSUMES", + "SOMETIMES_CONSUMES" : "SOMETIMES_CONSUMES", + "SOMETIMES_CONSUMED" : "SOMETIMES_CONSUMES", + "SOMETIME_CONSUMES" : "SOMETIMES_CONSUMES", + "UNDEFINED" : "UNDEFINED" + } + +PROTOCOL_USAGE_TOKENS = { + "TO_START" : "TO_START", + "BY_START" : "BY_START" + } + +PROTOCOL_USAGE_TOKENS.update (ALL_USAGE_TOKENS) + +# +# Dictionary of GUID type tokens +# +GUID_TYPE_TOKENS = { + "Event" : "Event", + "File" : "File", + "FV" : "FV", + "GUID" : "GUID", + "Guid" : "GUID", + "HII" : "HII", + "HOB" : "HOB", + "Hob" : "HOB", + "Hob:" : "HOB", + "SystemTable" : "SystemTable", + "TokenSpaceGuid" : "TokenSpaceGuid", + "UNDEFINED" : "UNDEFINED" + } + +# +# Dictionary of Protocol Notify tokens and their synonyms +# +PROTOCOL_NOTIFY_TOKENS = { + "NOTIFY" : "NOTIFY", + "PROTOCOL_NOTIFY" : "NOTIFY", + "UNDEFINED" : "UNDEFINED" + } + +# +# Dictionary of PPI Notify tokens and their synonyms +# +PPI_NOTIFY_TOKENS = { + "NOTIFY" : "NOTIFY", + "PPI_NOTIFY" : "NOTIFY", + "UNDEFINED" : "UNDEFINED" + } + +EVENT_TOKENS = { + "EVENT_TYPE_PERIODIC_TIMER" : "EVENT_TYPE_PERIODIC_TIMER", + "EVENT_TYPE_RELATIVE_TIMER" : "EVENT_TYPE_RELATIVE_TIMER", + "UNDEFINED" : "UNDEFINED" + } + +BOOTMODE_TOKENS = { + "FULL" : "FULL", + "MINIMAL" : "MINIMAL", + "NO_CHANGE" : "NO_CHANGE", + "DIAGNOSTICS" : "DIAGNOSTICS", + "DEFAULT" : "DEFAULT", + "S2_RESUME" : "S2_RESUME", + "S3_RESUME" : "S3_RESUME", + "S4_RESUME" : "S4_RESUME", + "S5_RESUME" : "S5_RESUME", + "FLASH_UPDATE" : "FLASH_UPDATE", + "RECOVERY_FULL" : "RECOVERY_FULL", + "RECOVERY_MINIMAL" : "RECOVERY_MINIMAL", + "RECOVERY_NO_CHANGE" : "RECOVERY_NO_CHANGE", + "RECOVERY_DIAGNOSTICS" : "RECOVERY_DIAGNOSTICS", + "RECOVERY_DEFAULT" : "RECOVERY_DEFAULT", + "RECOVERY_S2_RESUME" : "RECOVERY_S2_RESUME", + "RECOVERY_S3_RESUME" : "RECOVERY_S3_RESUME", + "RECOVERY_S4_RESUME" : "RECOVERY_S4_RESUME", + "RECOVERY_S5_RESUME" : "RECOVERY_S5_RESUME", + "RECOVERY_FLASH_UPDATE" : "RECOVERY_FLASH_UPDATE", + "UNDEFINED" : "UNDEFINED" + } + +HOB_TOKENS = { + "PHIT" : "PHIT", + "MEMORY_ALLOCATION" : "MEMORY_ALLOCATION", + "LOAD_PEIM" : "LOAD_PEIM", + "RESOURCE_DESCRIPTOR" : "RESOURCE_DESCRIPTOR", + "FIRMWARE_VOLUME" : "FIRMWARE_VOLUME", + "UNDEFINED" : "UNDEFINED" + } + +## +# Usage List Items for Protocol +# +PROTOCOL_USAGE_LIST = USAGE_LIST + ["TO_START", "BY_START"] + +## +# End of Line +# Use this but not os.linesep for os.linesep has bug in it. +# +END_OF_LINE = '\n' + +## +# Arch List Items +# +ARCH_LIST = ["IA32", + "X64", + "IPF", + "EBC", + "COMMON"] +## +# PCD driver type list items +# +PCD_DRIVER_TYPE_LIST = ["PEI_PCD_DRIVER", "DXE_PCD_DRIVER"] + +## +# Boot Mode List Items +# +BOOT_MODE_LIST = ["FULL", + "MINIMAL", + "NO_CHANGE", + "DIAGNOSTICS", + "DEFAULT", + "S2_RESUME", + "S3_RESUME", + "S4_RESUME", + "S5_RESUME", + "FLASH_UPDATE", + "RECOVERY_FULL", + "RECOVERY_MINIMAL", + "RECOVERY_NO_CHANGE", + "RECOVERY_DIAGNOSTICS", + "RECOVERY_DEFAULT", + "RECOVERY_S2_RESUME", + "RECOVERY_S3_RESUME", + "RECOVERY_S4_RESUME", + "RECOVERY_S5_RESUME", + "RECOVERY_FLASH_UPDATE"] + +## +# Event Type List Items +# +EVENT_TYPE_LIST = ["EVENT_TYPE_PERIODIC_TIMER", + "EVENT_TYPE_RELATIVE_TIMER"] + +## +# Hob Type List Items +# +HOB_TYPE_LIST = ["PHIT", + "MEMORY_ALLOCATION", + "RESOURCE_DESCRIPTOR", + "FIRMWARE_VOLUME", + "LOAD_PEIM"] + +## +# GUID_TYPE_LIST +# +GUID_TYPE_LIST = ["Event", "File", "FV", "GUID", "HII", "HOB", + "SystemTable", "TokenSpaceGuid", "Variable"] +## +# PCD Usage Type List of Package +# +PCD_USAGE_TYPE_LIST_OF_PACKAGE = ["FeatureFlag", "PatchableInModule", + "FixedAtBuild", "Dynamic", "DynamicEx"] + +## +# PCD Usage Type List of Module +# +PCD_USAGE_TYPE_LIST_OF_MODULE = ["FEATUREPCD", "PATCHPCD", "FIXEDPCD", "PCD", "PCDEX"] +## +# PCD Usage Type List of UPT +# +PCD_USAGE_TYPE_LIST_OF_UPT = PCD_USAGE_TYPE_LIST_OF_MODULE + +## +# Binary File Type List +# +BINARY_FILE_TYPE_LIST = ["PE32", "PIC", "TE", "DXE_DEPEX", "VER", "UI", "COMPAT16", "FV", "BIN", "RAW", + "ACPI", "ASL", + "PEI_DEPEX", + "SMM_DEPEX", + "SUBTYPE_GUID", + "DISPOSABLE" + ] +BINARY_FILE_TYPE_LIST_IN_UDP = \ + ["GUID", "FREEFORM", + "UEFI_IMAGE", "PE32", "PIC", + "PEI_DEPEX", + "DXE_DEPEX", + "SMM_DEPEX", + "FV", "TE", + "BIN", "VER", "UI" + ] + +SUBTYPE_GUID_BINARY_FILE_TYPE = "FREEFORM" +## +# Possible values for COMPONENT_TYPE, and their descriptions, are listed in +# the table, +# "Component (module) Types." For each component, the BASE_NAME and +# COMPONENT_TYPE +# are required. The COMPONENT_TYPE definition is case sensitive. +# +COMPONENT_TYPE_LIST = [ + "APPLICATION", + "ACPITABLE", + "APRIORI", + "BINARY", + "BS_DRIVER", + "CONFIG", + "FILE", + "FVIMAGEFILE", + "LIBRARY", + "LOGO", + "LEGACY16", + "MICROCODE", + "PE32_PEIM", + "PEI_CORE", + "RAWFILE", + "RT_DRIVER", + "SAL_RT_DRIVER", + "SECURITY_CORE", + "COMBINED_PEIM_DRIVER", + "PIC_PEIM", + "RELOCATABLE_PEIM" + ] + +## +# Common Definitions +# +TAB_SPLIT = '.' +TAB_COMMENT_EDK1_START = '/*' +TAB_COMMENT_EDK1_END = '*/' +TAB_COMMENT_EDK1_SPLIT = '//' +TAB_COMMENT_SPLIT = '#' +TAB_EQUAL_SPLIT = '=' +TAB_DEQUAL_SPLIT = '==' +TAB_VALUE_SPLIT = '|' +TAB_COMMA_SPLIT = ',' +TAB_HORIZON_LINE_SPLIT = '-' +TAB_SPACE_SPLIT = ' ' +TAB_UNDERLINE_SPLIT = '_' +TAB_SEMI_COLON_SPLIT = ';' +TAB_COLON_SPLIT = ':' +TAB_SECTION_START = '[' +TAB_SECTION_END = ']' +TAB_OPTION_START = '<' +TAB_OPTION_END = '>' +TAB_SLASH = '\\' +TAB_BACK_SLASH = '/' +TAB_SPECIAL_COMMENT = '##' +TAB_HEADER_COMMENT = '@file' +TAB_BINARY_HEADER_COMMENT = '@BinaryHeader' +TAB_STAR = '*' +TAB_ENCODING_UTF16LE = 'utf_16_le' +TAB_CAPHEX_START = '0X' +TAB_HEX_START = '0x' +TAB_PCD_ERROR = 'Error' +TAB_PCD_ERROR_SECTION_COMMENT = 'Error message section' +TAB_UNI_FILE_SUFFIXS = ['.uni', '.UNI', '.Uni'] + +TAB_EDK_SOURCE = '$(EDK_SOURCE)' +TAB_EFI_SOURCE = '$(EFI_SOURCE)' +TAB_WORKSPACE = '$(WORKSPACE)' + +TAB_ARCH_NULL = '' +TAB_ARCH_COMMON = 'COMMON' +TAB_ARCH_IA32 = 'IA32' +TAB_ARCH_X64 = 'X64' +TAB_ARCH_IPF = 'IPF' +TAB_ARCH_ARM = 'ARM' +TAB_ARCH_EBC = 'EBC' + +ARCH_LIST = \ +[TAB_ARCH_IA32, TAB_ARCH_X64, TAB_ARCH_IPF, TAB_ARCH_ARM, TAB_ARCH_EBC] + +SUP_MODULE_BASE = 'BASE' +SUP_MODULE_SEC = 'SEC' +SUP_MODULE_PEI_CORE = 'PEI_CORE' +SUP_MODULE_PEIM = 'PEIM' +SUP_MODULE_DXE_CORE = 'DXE_CORE' +SUP_MODULE_DXE_DRIVER = 'DXE_DRIVER' +SUP_MODULE_DXE_RUNTIME_DRIVER = 'DXE_RUNTIME_DRIVER' +SUP_MODULE_DXE_SAL_DRIVER = 'DXE_SAL_DRIVER' +SUP_MODULE_DXE_SMM_DRIVER = 'DXE_SMM_DRIVER' +SUP_MODULE_UEFI_DRIVER = 'UEFI_DRIVER' +SUP_MODULE_UEFI_APPLICATION = 'UEFI_APPLICATION' +SUP_MODULE_USER_DEFINED = 'USER_DEFINED' +SUP_MODULE_SMM_CORE = 'SMM_CORE' + +SUP_MODULE_LIST = \ +[SUP_MODULE_BASE, SUP_MODULE_SEC, SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM, \ +SUP_MODULE_DXE_CORE, SUP_MODULE_DXE_DRIVER, \ + SUP_MODULE_DXE_RUNTIME_DRIVER, SUP_MODULE_DXE_SAL_DRIVER, \ + SUP_MODULE_DXE_SMM_DRIVER, SUP_MODULE_UEFI_DRIVER, \ + SUP_MODULE_UEFI_APPLICATION, SUP_MODULE_USER_DEFINED, \ + SUP_MODULE_SMM_CORE] +SUP_MODULE_LIST_STRING = TAB_VALUE_SPLIT.join(l for l in SUP_MODULE_LIST) + +EDK_COMPONENT_TYPE_LIBRARY = 'LIBRARY' +EDK_COMPONENT_TYPE_SECUARITY_CORE = 'SECUARITY_CORE' +EDK_COMPONENT_TYPE_PEI_CORE = 'PEI_CORE' +EDK_COMPONENT_TYPE_COMBINED_PEIM_DRIVER = 'COMBINED_PEIM_DRIVER' +EDK_COMPONENT_TYPE_PIC_PEIM = 'PIC_PEIM' +EDK_COMPONENT_TYPE_RELOCATABLE_PEIM = 'RELOCATABLE_PEIM' +EDK_COMPONENT_TYPE_BS_DRIVER = 'BS_DRIVER' +EDK_COMPONENT_TYPE_RT_DRIVER = 'RT_DRIVER' +EDK_COMPONENT_TYPE_SAL_RT_DRIVER = 'SAL_RT_DRIVER' +EDK_COMPONENT_TYPE_APPLICATION = 'APPLICATION' +EDK_NAME = 'EDK' +EDKII_NAME = 'EDKII' + +BINARY_FILE_TYPE_FW = 'FW' +BINARY_FILE_TYPE_GUID = 'GUID' +BINARY_FILE_TYPE_PREEFORM = 'PREEFORM' +BINARY_FILE_TYPE_UEFI_APP = 'UEFI_APP' +BINARY_FILE_TYPE_UNI_UI = 'UNI_UI' +BINARY_FILE_TYPE_SEC_UI = 'SEC_UI' +BINARY_FILE_TYPE_UNI_VER = 'UNI_VER' +BINARY_FILE_TYPE_SEC_VER = 'SEC_VER' +BINARY_FILE_TYPE_LIB = 'LIB' +BINARY_FILE_TYPE_PE32 = 'PE32' +BINARY_FILE_TYPE_PIC = 'PIC' +BINARY_FILE_TYPE_PEI_DEPEX = 'PEI_DEPEX' +BINARY_FILE_TYPE_DXE_DEPEX = 'DXE_DEPEX' +BINARY_FILE_TYPE_SMM_DEPEX = 'SMM_DEPEX' +BINARY_FILE_TYPE_TE = 'TE' +BINARY_FILE_TYPE_VER = 'VER' +BINARY_FILE_TYPE_UI = 'UI' +BINARY_FILE_TYPE_BIN = 'BIN' +BINARY_FILE_TYPE_FV = 'FV' +BINARY_FILE_TYPE_UI_LIST = [BINARY_FILE_TYPE_UNI_UI, + BINARY_FILE_TYPE_SEC_UI, + BINARY_FILE_TYPE_UI + ] +BINARY_FILE_TYPE_VER_LIST = [BINARY_FILE_TYPE_UNI_VER, + BINARY_FILE_TYPE_SEC_VER, + BINARY_FILE_TYPE_VER + ] + +DEPEX_SECTION_LIST = ['', + '', + '' + ] + +PLATFORM_COMPONENT_TYPE_LIBRARY = 'LIBRARY' +PLATFORM_COMPONENT_TYPE_LIBRARY_CLASS = 'LIBRARY_CLASS' +PLATFORM_COMPONENT_TYPE_MODULE = 'MODULE' + +TAB_LIBRARIES = 'Libraries' + +TAB_SOURCE = 'Source' +TAB_SOURCES = 'Sources' +TAB_SOURCES_COMMON = TAB_SOURCES + TAB_SPLIT + TAB_ARCH_COMMON +TAB_SOURCES_IA32 = TAB_SOURCES + TAB_SPLIT + TAB_ARCH_IA32 +TAB_SOURCES_X64 = TAB_SOURCES + TAB_SPLIT + TAB_ARCH_X64 +TAB_SOURCES_IPF = TAB_SOURCES + TAB_SPLIT + TAB_ARCH_IPF +TAB_SOURCES_ARM = TAB_SOURCES + TAB_SPLIT + TAB_ARCH_ARM +TAB_SOURCES_EBC = TAB_SOURCES + TAB_SPLIT + TAB_ARCH_EBC + +TAB_BINARIES = 'Binaries' +TAB_BINARIES_COMMON = TAB_BINARIES + TAB_SPLIT + TAB_ARCH_COMMON +TAB_BINARIES_IA32 = TAB_BINARIES + TAB_SPLIT + TAB_ARCH_IA32 +TAB_BINARIES_X64 = TAB_BINARIES + TAB_SPLIT + TAB_ARCH_X64 +TAB_BINARIES_IPF = TAB_BINARIES + TAB_SPLIT + TAB_ARCH_IPF +TAB_BINARIES_ARM = TAB_BINARIES + TAB_SPLIT + TAB_ARCH_ARM +TAB_BINARIES_EBC = TAB_BINARIES + TAB_SPLIT + TAB_ARCH_EBC + +TAB_INCLUDES = 'Includes' +TAB_INCLUDES_COMMON = TAB_INCLUDES + TAB_SPLIT + TAB_ARCH_COMMON +TAB_INCLUDES_IA32 = TAB_INCLUDES + TAB_SPLIT + TAB_ARCH_IA32 +TAB_INCLUDES_X64 = TAB_INCLUDES + TAB_SPLIT + TAB_ARCH_X64 +TAB_INCLUDES_IPF = TAB_INCLUDES + TAB_SPLIT + TAB_ARCH_IPF +TAB_INCLUDES_ARM = TAB_INCLUDES + TAB_SPLIT + TAB_ARCH_ARM +TAB_INCLUDES_EBC = TAB_INCLUDES + TAB_SPLIT + TAB_ARCH_EBC + +TAB_GUIDS = 'Guids' +TAB_GUIDS_COMMON = TAB_GUIDS + TAB_SPLIT + TAB_ARCH_COMMON +TAB_GUIDS_IA32 = TAB_GUIDS + TAB_SPLIT + TAB_ARCH_IA32 +TAB_GUIDS_X64 = TAB_GUIDS + TAB_SPLIT + TAB_ARCH_X64 +TAB_GUIDS_IPF = TAB_GUIDS + TAB_SPLIT + TAB_ARCH_IPF +TAB_GUIDS_ARM = TAB_GUIDS + TAB_SPLIT + TAB_ARCH_ARM +TAB_GUIDS_EBC = TAB_GUIDS + TAB_SPLIT + TAB_ARCH_EBC + +TAB_PROTOCOLS = 'Protocols' +TAB_PROTOCOLS_COMMON = TAB_PROTOCOLS + TAB_SPLIT + TAB_ARCH_COMMON +TAB_PROTOCOLS_IA32 = TAB_PROTOCOLS + TAB_SPLIT + TAB_ARCH_IA32 +TAB_PROTOCOLS_X64 = TAB_PROTOCOLS + TAB_SPLIT + TAB_ARCH_X64 +TAB_PROTOCOLS_IPF = TAB_PROTOCOLS + TAB_SPLIT + TAB_ARCH_IPF +TAB_PROTOCOLS_ARM = TAB_PROTOCOLS + TAB_SPLIT + TAB_ARCH_ARM +TAB_PROTOCOLS_EBC = TAB_PROTOCOLS + TAB_SPLIT + TAB_ARCH_EBC + +TAB_PPIS = 'Ppis' +TAB_PPIS_COMMON = TAB_PPIS + TAB_SPLIT + TAB_ARCH_COMMON +TAB_PPIS_IA32 = TAB_PPIS + TAB_SPLIT + TAB_ARCH_IA32 +TAB_PPIS_X64 = TAB_PPIS + TAB_SPLIT + TAB_ARCH_X64 +TAB_PPIS_IPF = TAB_PPIS + TAB_SPLIT + TAB_ARCH_IPF +TAB_PPIS_ARM = TAB_PPIS + TAB_SPLIT + TAB_ARCH_ARM +TAB_PPIS_EBC = TAB_PPIS + TAB_SPLIT + TAB_ARCH_EBC + +TAB_LIBRARY_CLASSES = 'LibraryClasses' +TAB_LIBRARY_CLASSES_COMMON = TAB_LIBRARY_CLASSES + TAB_SPLIT + TAB_ARCH_COMMON +TAB_LIBRARY_CLASSES_IA32 = TAB_LIBRARY_CLASSES + TAB_SPLIT + TAB_ARCH_IA32 +TAB_LIBRARY_CLASSES_X64 = TAB_LIBRARY_CLASSES + TAB_SPLIT + TAB_ARCH_X64 +TAB_LIBRARY_CLASSES_IPF = TAB_LIBRARY_CLASSES + TAB_SPLIT + TAB_ARCH_IPF +TAB_LIBRARY_CLASSES_ARM = TAB_LIBRARY_CLASSES + TAB_SPLIT + TAB_ARCH_ARM +TAB_LIBRARY_CLASSES_EBC = TAB_LIBRARY_CLASSES + TAB_SPLIT + TAB_ARCH_EBC + +TAB_PACKAGES = 'Packages' +TAB_PACKAGES_COMMON = TAB_PACKAGES + TAB_SPLIT + TAB_ARCH_COMMON +TAB_PACKAGES_IA32 = TAB_PACKAGES + TAB_SPLIT + TAB_ARCH_IA32 +TAB_PACKAGES_X64 = TAB_PACKAGES + TAB_SPLIT + TAB_ARCH_X64 +TAB_PACKAGES_IPF = TAB_PACKAGES + TAB_SPLIT + TAB_ARCH_IPF +TAB_PACKAGES_ARM = TAB_PACKAGES + TAB_SPLIT + TAB_ARCH_ARM +TAB_PACKAGES_EBC = TAB_PACKAGES + TAB_SPLIT + TAB_ARCH_EBC + +TAB_PCDS = 'Pcds' +TAB_PCDS_FIXED_AT_BUILD = 'FixedAtBuild' +TAB_PCDS_PATCHABLE_IN_MODULE = 'PatchableInModule' +TAB_PCDS_FEATURE_FLAG = 'FeatureFlag' +TAB_PCDS_DYNAMIC_EX = 'DynamicEx' +TAB_PCDS_DYNAMIC_EX_DEFAULT = 'DynamicExDefault' +TAB_PCDS_DYNAMIC_EX_VPD = 'DynamicExVpd' +TAB_PCDS_DYNAMIC_EX_HII = 'DynamicExHii' +TAB_PCDS_DYNAMIC = 'Dynamic' +TAB_PCDS_DYNAMIC_DEFAULT = 'DynamicDefault' +TAB_PCDS_DYNAMIC_VPD = 'DynamicVpd' +TAB_PCDS_DYNAMIC_HII = 'DynamicHii' + +TAB_PTR_TYPE_PCD = 'VOID*' + +PCD_DYNAMIC_TYPE_LIST = [TAB_PCDS_DYNAMIC, TAB_PCDS_DYNAMIC_DEFAULT, \ + TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_HII] +PCD_DYNAMIC_EX_TYPE_LIST = [TAB_PCDS_DYNAMIC_EX, TAB_PCDS_DYNAMIC_EX_DEFAULT, \ + TAB_PCDS_DYNAMIC_EX_VPD, TAB_PCDS_DYNAMIC_EX_HII] + +## Dynamic-ex PCD types +# +gDYNAMIC_EX_PCD = [TAB_PCDS_DYNAMIC_EX, TAB_PCDS_DYNAMIC_EX_DEFAULT, \ + TAB_PCDS_DYNAMIC_EX_VPD, TAB_PCDS_DYNAMIC_EX_HII] + +TAB_PCDS_FIXED_AT_BUILD_NULL = TAB_PCDS + TAB_PCDS_FIXED_AT_BUILD +TAB_PCDS_FIXED_AT_BUILD_COMMON = TAB_PCDS + TAB_PCDS_FIXED_AT_BUILD + \ +TAB_SPLIT + TAB_ARCH_COMMON +TAB_PCDS_FIXED_AT_BUILD_IA32 = TAB_PCDS + TAB_PCDS_FIXED_AT_BUILD + \ +TAB_SPLIT + TAB_ARCH_IA32 +TAB_PCDS_FIXED_AT_BUILD_X64 = TAB_PCDS + TAB_PCDS_FIXED_AT_BUILD + \ +TAB_SPLIT + TAB_ARCH_X64 +TAB_PCDS_FIXED_AT_BUILD_IPF = TAB_PCDS + TAB_PCDS_FIXED_AT_BUILD + \ +TAB_SPLIT + TAB_ARCH_IPF +TAB_PCDS_FIXED_AT_BUILD_ARM = TAB_PCDS + TAB_PCDS_FIXED_AT_BUILD + \ +TAB_SPLIT + TAB_ARCH_ARM +TAB_PCDS_FIXED_AT_BUILD_EBC = TAB_PCDS + TAB_PCDS_FIXED_AT_BUILD + \ +TAB_SPLIT + TAB_ARCH_EBC + +TAB_PCDS_PATCHABLE_IN_MODULE_NULL = TAB_PCDS + TAB_PCDS_PATCHABLE_IN_MODULE +TAB_PCDS_PATCHABLE_IN_MODULE_COMMON = TAB_PCDS + TAB_PCDS_PATCHABLE_IN_MODULE \ ++ TAB_SPLIT + TAB_ARCH_COMMON +TAB_PCDS_PATCHABLE_IN_MODULE_IA32 = TAB_PCDS + TAB_PCDS_PATCHABLE_IN_MODULE + \ +TAB_SPLIT + TAB_ARCH_IA32 +TAB_PCDS_PATCHABLE_IN_MODULE_X64 = TAB_PCDS + TAB_PCDS_PATCHABLE_IN_MODULE + \ +TAB_SPLIT + TAB_ARCH_X64 +TAB_PCDS_PATCHABLE_IN_MODULE_IPF = TAB_PCDS + TAB_PCDS_PATCHABLE_IN_MODULE + \ +TAB_SPLIT + TAB_ARCH_IPF +TAB_PCDS_PATCHABLE_IN_MODULE_ARM = TAB_PCDS + TAB_PCDS_PATCHABLE_IN_MODULE + \ +TAB_SPLIT + TAB_ARCH_ARM +TAB_PCDS_PATCHABLE_IN_MODULE_EBC = TAB_PCDS + TAB_PCDS_PATCHABLE_IN_MODULE + \ +TAB_SPLIT + TAB_ARCH_EBC + +TAB_PCDS_FEATURE_FLAG_NULL = TAB_PCDS + TAB_PCDS_FEATURE_FLAG +TAB_PCDS_FEATURE_FLAG_COMMON = TAB_PCDS + TAB_PCDS_FEATURE_FLAG + TAB_SPLIT \ ++ TAB_ARCH_COMMON +TAB_PCDS_FEATURE_FLAG_IA32 = TAB_PCDS + TAB_PCDS_FEATURE_FLAG + TAB_SPLIT + \ +TAB_ARCH_IA32 +TAB_PCDS_FEATURE_FLAG_X64 = TAB_PCDS + TAB_PCDS_FEATURE_FLAG + TAB_SPLIT + \ +TAB_ARCH_X64 +TAB_PCDS_FEATURE_FLAG_IPF = TAB_PCDS + TAB_PCDS_FEATURE_FLAG + TAB_SPLIT + \ +TAB_ARCH_IPF +TAB_PCDS_FEATURE_FLAG_ARM = TAB_PCDS + TAB_PCDS_FEATURE_FLAG + TAB_SPLIT + \ +TAB_ARCH_ARM +TAB_PCDS_FEATURE_FLAG_EBC = TAB_PCDS + TAB_PCDS_FEATURE_FLAG + TAB_SPLIT + \ +TAB_ARCH_EBC + +TAB_PCDS_DYNAMIC_EX_NULL = TAB_PCDS + TAB_PCDS_DYNAMIC_EX +TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL = TAB_PCDS + TAB_PCDS_DYNAMIC_EX_DEFAULT +TAB_PCDS_DYNAMIC_EX_HII_NULL = TAB_PCDS + TAB_PCDS_DYNAMIC_EX_HII +TAB_PCDS_DYNAMIC_EX_VPD_NULL = TAB_PCDS + TAB_PCDS_DYNAMIC_EX_VPD +TAB_PCDS_DYNAMIC_EX_COMMON = TAB_PCDS + TAB_PCDS_DYNAMIC_EX + TAB_SPLIT + \ +TAB_ARCH_COMMON +TAB_PCDS_DYNAMIC_EX_IA32 = TAB_PCDS + TAB_PCDS_DYNAMIC_EX + TAB_SPLIT + \ +TAB_ARCH_IA32 +TAB_PCDS_DYNAMIC_EX_X64 = TAB_PCDS + TAB_PCDS_DYNAMIC_EX + TAB_SPLIT + \ +TAB_ARCH_X64 +TAB_PCDS_DYNAMIC_EX_IPF = TAB_PCDS + TAB_PCDS_DYNAMIC_EX + TAB_SPLIT + \ +TAB_ARCH_IPF +TAB_PCDS_DYNAMIC_EX_ARM = TAB_PCDS + TAB_PCDS_DYNAMIC_EX + TAB_SPLIT + \ +TAB_ARCH_ARM +TAB_PCDS_DYNAMIC_EX_EBC = TAB_PCDS + TAB_PCDS_DYNAMIC_EX + TAB_SPLIT + \ +TAB_ARCH_EBC + +TAB_PCDS_DYNAMIC_NULL = TAB_PCDS + TAB_PCDS_DYNAMIC +TAB_PCDS_DYNAMIC_DEFAULT_NULL = TAB_PCDS + TAB_PCDS_DYNAMIC_DEFAULT +TAB_PCDS_DYNAMIC_HII_NULL = TAB_PCDS + TAB_PCDS_DYNAMIC_HII +TAB_PCDS_DYNAMIC_VPD_NULL = TAB_PCDS + TAB_PCDS_DYNAMIC_VPD +TAB_PCDS_DYNAMIC_COMMON = TAB_PCDS + TAB_PCDS_DYNAMIC + TAB_SPLIT + \ +TAB_ARCH_COMMON +TAB_PCDS_DYNAMIC_IA32 = TAB_PCDS + TAB_PCDS_DYNAMIC + TAB_SPLIT + TAB_ARCH_IA32 +TAB_PCDS_DYNAMIC_X64 = TAB_PCDS + TAB_PCDS_DYNAMIC + TAB_SPLIT + TAB_ARCH_X64 +TAB_PCDS_DYNAMIC_IPF = TAB_PCDS + TAB_PCDS_DYNAMIC + TAB_SPLIT + TAB_ARCH_IPF +TAB_PCDS_DYNAMIC_ARM = TAB_PCDS + TAB_PCDS_DYNAMIC + TAB_SPLIT + TAB_ARCH_ARM +TAB_PCDS_DYNAMIC_EBC = TAB_PCDS + TAB_PCDS_DYNAMIC + TAB_SPLIT + TAB_ARCH_EBC + +TAB_PCD_DYNAMIC_TYPE_LIST = [TAB_PCDS_DYNAMIC_DEFAULT_NULL, \ + TAB_PCDS_DYNAMIC_VPD_NULL, \ + TAB_PCDS_DYNAMIC_HII_NULL] +TAB_PCD_DYNAMIC_EX_TYPE_LIST = [TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL, \ + TAB_PCDS_DYNAMIC_EX_VPD_NULL, \ + TAB_PCDS_DYNAMIC_EX_HII_NULL] + +TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_PEI_PAGE_SIZE = \ +'PcdLoadFixAddressPeiCodePageNumber' +TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_PEI_PAGE_SIZE_DATA_TYPE = 'UINT32' +TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_DXE_PAGE_SIZE = \ +'PcdLoadFixAddressBootTimeCodePageNumber' +TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_DXE_PAGE_SIZE_DATA_TYPE = 'UINT32' +TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_RUNTIME_PAGE_SIZE = \ +'PcdLoadFixAddressRuntimeCodePageNumber' +TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_RUNTIME_PAGE_SIZE_DATA_TYPE = 'UINT32' +TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_SMM_PAGE_SIZE = \ +'PcdLoadFixAddressSmmCodePageNumber' +TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_SMM_PAGE_SIZE_DATA_TYPE = 'UINT32' +TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_LIST = \ +[TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_PEI_PAGE_SIZE, \ +TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_DXE_PAGE_SIZE, \ +TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_RUNTIME_PAGE_SIZE, \ +TAB_PCDS_PATCHABLE_LOAD_FIX_ADDRESS_SMM_PAGE_SIZE] +PCD_SECTION_LIST = [TAB_PCDS_FIXED_AT_BUILD_NULL.upper(), \ + TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper(), \ + TAB_PCDS_FEATURE_FLAG_NULL.upper(), \ + TAB_PCDS_DYNAMIC_EX_NULL.upper(), \ + TAB_PCDS_DYNAMIC_NULL.upper()] +INF_PCD_SECTION_LIST = ["FixedPcd".upper(), "FeaturePcd".upper(), \ + "PatchPcd".upper(), "Pcd".upper(), "PcdEx".upper()] + +TAB_DEPEX = 'Depex' +TAB_DEPEX_COMMON = TAB_DEPEX + TAB_SPLIT + TAB_ARCH_COMMON +TAB_DEPEX_IA32 = TAB_DEPEX + TAB_SPLIT + TAB_ARCH_IA32 +TAB_DEPEX_X64 = TAB_DEPEX + TAB_SPLIT + TAB_ARCH_X64 +TAB_DEPEX_IPF = TAB_DEPEX + TAB_SPLIT + TAB_ARCH_IPF +TAB_DEPEX_ARM = TAB_DEPEX + TAB_SPLIT + TAB_ARCH_ARM +TAB_DEPEX_EBC = TAB_DEPEX + TAB_SPLIT + TAB_ARCH_EBC + +TAB_SKUIDS = 'SkuIds' + +TAB_LIBRARIES = 'Libraries' +TAB_LIBRARIES_COMMON = TAB_LIBRARIES + TAB_SPLIT + TAB_ARCH_COMMON +TAB_LIBRARIES_IA32 = TAB_LIBRARIES + TAB_SPLIT + TAB_ARCH_IA32 +TAB_LIBRARIES_X64 = TAB_LIBRARIES + TAB_SPLIT + TAB_ARCH_X64 +TAB_LIBRARIES_IPF = TAB_LIBRARIES + TAB_SPLIT + TAB_ARCH_IPF +TAB_LIBRARIES_ARM = TAB_LIBRARIES + TAB_SPLIT + TAB_ARCH_ARM +TAB_LIBRARIES_EBC = TAB_LIBRARIES + TAB_SPLIT + TAB_ARCH_EBC + +TAB_COMPONENTS = 'Components' +TAB_COMPONENTS_COMMON = TAB_COMPONENTS + TAB_SPLIT + TAB_ARCH_COMMON +TAB_COMPONENTS_IA32 = TAB_COMPONENTS + TAB_SPLIT + TAB_ARCH_IA32 +TAB_COMPONENTS_X64 = TAB_COMPONENTS + TAB_SPLIT + TAB_ARCH_X64 +TAB_COMPONENTS_IPF = TAB_COMPONENTS + TAB_SPLIT + TAB_ARCH_IPF +TAB_COMPONENTS_ARM = TAB_COMPONENTS + TAB_SPLIT + TAB_ARCH_ARM +TAB_COMPONENTS_EBC = TAB_COMPONENTS + TAB_SPLIT + TAB_ARCH_EBC + +TAB_BUILD_OPTIONS = 'BuildOptions' + +TAB_DEFINE = 'DEFINE' +TAB_NMAKE = 'Nmake' +TAB_USER_EXTENSIONS = 'UserExtensions' +TAB_INCLUDE = '!include' +TAB_PRIVATE = 'Private' +TAB_INTEL = 'Intel' + +# +# Common Define +# +TAB_COMMON_DEFINES = 'Defines' + +# +# Inf Definitions +# +TAB_INF_DEFINES = TAB_COMMON_DEFINES +TAB_INF_DEFINES_INF_VERSION = 'INF_VERSION' +TAB_INF_DEFINES_BASE_NAME = 'BASE_NAME' +TAB_INF_DEFINES_FILE_GUID = 'FILE_GUID' +TAB_INF_DEFINES_MODULE_TYPE = 'MODULE_TYPE' +TAB_INF_DEFINES_EFI_SPECIFICATION_VERSION = 'EFI_SPECIFICATION_VERSION' +TAB_INF_DEFINES_UEFI_SPECIFICATION_VERSION = 'UEFI_SPECIFICATION_VERSION' +TAB_INF_DEFINES_PI_SPECIFICATION_VERSION = 'PI_SPECIFICATION_VERSION' +TAB_INF_DEFINES_EDK_RELEASE_VERSION = 'EDK_RELEASE_VERSION' +TAB_INF_DEFINES_MODULE_UNI_FILE = 'MODULE_UNI_FILE' +TAB_INF_DEFINES_BINARY_MODULE = 'BINARY_MODULE' +TAB_INF_DEFINES_LIBRARY_CLASS = 'LIBRARY_CLASS' +TAB_INF_DEFINES_COMPONENT_TYPE = 'COMPONENT_TYPE' +TAB_INF_DEFINES_MAKEFILE_NAME = 'MAKEFILE_NAME' +TAB_INF_DEFINES_BUILD_NUMBER = 'BUILD_NUMBER' +TAB_INF_DEFINES_BUILD_TYPE = 'BUILD_TYPE' +TAB_INF_DEFINES_FFS_EXT = 'FFS_EXT' +TAB_INF_DEFINES_FV_EXT = 'FV_EXT' +TAB_INF_DEFINES_SOURCE_FV = 'SOURCE_FV' +TAB_INF_DEFINES_PACKAGE = 'PACKAGE' +TAB_INF_DEFINES_VERSION_NUMBER = 'VERSION_NUMBER' +TAB_INF_DEFINES_VERSION = 'VERSION' +TAB_INF_DEFINES_VERSION_STRING = 'VERSION_STRING' +TAB_INF_DEFINES_PCD_IS_DRIVER = 'PCD_IS_DRIVER' +TAB_INF_DEFINES_TIANO_EDK1_FLASHMAP_H = 'TIANO_EDK1_FLASHMAP_H' +TAB_INF_DEFINES_ENTRY_POINT = 'ENTRY_POINT' +TAB_INF_DEFINES_UNLOAD_IMAGE = 'UNLOAD_IMAGE' +TAB_INF_DEFINES_CONSTRUCTOR = 'CONSTRUCTOR' +TAB_INF_DEFINES_DESTRUCTOR = 'DESTRUCTOR' +TAB_INF_DEFINES_PCI_VENDOR_ID = 'PCI_VENDOR_ID' +TAB_INF_DEFINES_PCI_DEVICE_ID = 'PCI_DEVICE_ID' +TAB_INF_DEFINES_PCI_CLASS_CODE = 'PCI_CLASS_CODE' +TAB_INF_DEFINES_PCI_REVISION = 'PCI_REVISION' +TAB_INF_DEFINES_PCI_COMPRESS = 'PCI_COMPRESS' +TAB_INF_DEFINES_DEFINE = 'DEFINE' +TAB_INF_DEFINES_SPEC = 'SPEC' +TAB_INF_DEFINES_UEFI_HII_RESOURCE_SECTION = 'UEFI_HII_RESOURCE_SECTION' +TAB_INF_DEFINES_CUSTOM_MAKEFILE = 'CUSTOM_MAKEFILE' +TAB_INF_DEFINES_MACRO = '__MACROS__' +TAB_INF_DEFINES_SHADOW = 'SHADOW' +TAB_INF_DEFINES_DPX_SOURCE = 'DPX_SOURCE' +TAB_INF_FIXED_PCD = 'FixedPcd' +TAB_INF_FEATURE_PCD = 'FeaturePcd' +TAB_INF_PATCH_PCD = 'PatchPcd' +TAB_INF_PCD = 'Pcd' +TAB_INF_PCD_EX = 'PcdEx' +TAB_INF_GUIDTYPE_VAR = 'Variable' +TAB_INF_ABSTRACT = 'STR_MODULE_ABSTRACT' +TAB_INF_DESCRIPTION = 'STR_MODULE_DESCRIPTION' +TAB_INF_LICENSE = 'STR_MODULE_LICENSE' +TAB_INF_BINARY_ABSTRACT = 'STR_MODULE_BINARY_ABSTRACT' +TAB_INF_BINARY_DESCRIPTION = 'STR_MODULE_BINARY_DESCRIPTION' +TAB_INF_BINARY_LICENSE = 'STR_MODULE_BINARY_LICENSE' +# +# Dec Definitions +# +TAB_DEC_DEFINES = TAB_COMMON_DEFINES +TAB_DEC_DEFINES_DEC_SPECIFICATION = 'DEC_SPECIFICATION' +TAB_DEC_DEFINES_PACKAGE_NAME = 'PACKAGE_NAME' +TAB_DEC_DEFINES_PACKAGE_GUID = 'PACKAGE_GUID' +TAB_DEC_DEFINES_PACKAGE_VERSION = 'PACKAGE_VERSION' +TAB_DEC_DEFINES_PKG_UNI_FILE = 'PACKAGE_UNI_FILE' +TAB_DEC_PACKAGE_ABSTRACT = 'STR_PACKAGE_ABSTRACT' +TAB_DEC_PACKAGE_DESCRIPTION = 'STR_PACKAGE_DESCRIPTION' +TAB_DEC_PACKAGE_LICENSE = 'STR_PACKAGE_LICENSE' +TAB_DEC_BINARY_ABSTRACT = 'STR_PACKAGE_BINARY_ABSTRACT' +TAB_DEC_BINARY_DESCRIPTION = 'STR_PACKAGE_BINARY_DESCRIPTION' +TAB_DEC_BINARY_LICENSE = 'STR_PACKAGE_ASBUILT_LICENSE' +# +# Dsc Definitions +# +TAB_DSC_DEFINES = TAB_COMMON_DEFINES +TAB_DSC_DEFINES_PLATFORM_NAME = 'PLATFORM_NAME' +TAB_DSC_DEFINES_PLATFORM_GUID = 'PLATFORM_GUID' +TAB_DSC_DEFINES_PLATFORM_VERSION = 'PLATFORM_VERSION' +TAB_DSC_DEFINES_DSC_SPECIFICATION = 'DSC_SPECIFICATION' +TAB_DSC_DEFINES_OUTPUT_DIRECTORY = 'OUTPUT_DIRECTORY' +TAB_DSC_DEFINES_SUPPORTED_ARCHITECTURES = 'SUPPORTED_ARCHITECTURES' +TAB_DSC_DEFINES_BUILD_TARGETS = 'BUILD_TARGETS' +TAB_DSC_DEFINES_SKUID_IDENTIFIER = 'SKUID_IDENTIFIER' +TAB_DSC_DEFINES_FLASH_DEFINITION = 'FLASH_DEFINITION' +TAB_DSC_DEFINES_BUILD_NUMBER = 'BUILD_NUMBER' +TAB_DSC_DEFINES_MAKEFILE_NAME = 'MAKEFILE_NAME' +TAB_DSC_DEFINES_BS_BASE_ADDRESS = 'BsBaseAddress' +TAB_DSC_DEFINES_RT_BASE_ADDRESS = 'RtBaseAddress' +TAB_DSC_DEFINES_DEFINE = 'DEFINE' +TAB_FIX_LOAD_TOP_MEMORY_ADDRESS = 'FIX_LOAD_TOP_MEMORY_ADDRESS' + +# +# TargetTxt Definitions +# +TAB_TAT_DEFINES_ACTIVE_PLATFORM = 'ACTIVE_PLATFORM' +TAB_TAT_DEFINES_ACTIVE_MODULE = 'ACTIVE_MODULE' +TAB_TAT_DEFINES_TOOL_CHAIN_CONF = 'TOOL_CHAIN_CONF' +TAB_TAT_DEFINES_MULTIPLE_THREAD = 'MULTIPLE_THREAD' +TAB_TAT_DEFINES_MAX_CONCURRENT_THREAD_NUMBER = 'MAX_CONCURRENT_THREAD_NUMBER' +TAB_TAT_DEFINES_TARGET = 'TARGET' +TAB_TAT_DEFINES_TOOL_CHAIN_TAG = 'TOOL_CHAIN_TAG' +TAB_TAT_DEFINES_TARGET_ARCH = 'TARGET_ARCH' +TAB_TAT_DEFINES_BUILD_RULE_CONF = "BUILD_RULE_CONF" + +# +# ToolDef Definitions +# +TAB_TOD_DEFINES_TARGET = 'TARGET' +TAB_TOD_DEFINES_TOOL_CHAIN_TAG = 'TOOL_CHAIN_TAG' +TAB_TOD_DEFINES_TARGET_ARCH = 'TARGET_ARCH' +TAB_TOD_DEFINES_COMMAND_TYPE = 'COMMAND_TYPE' +TAB_TOD_DEFINES_FAMILY = 'FAMILY' +TAB_TOD_DEFINES_BUILDRULEFAMILY = 'BUILDRULEFAMILY' + +# +# Conditional Statements +# +TAB_IF = '!if' +TAB_END_IF = '!endif' +TAB_ELSE_IF = '!elseif' +TAB_ELSE = '!else' +TAB_IF_DEF = '!ifdef' +TAB_IF_N_DEF = '!ifndef' +TAB_IF_EXIST = '!if exist' + +# +# Unknown section +# +TAB_UNKNOWN = 'UNKNOWN' + +# +# Header section (virtual section for abstract, description, copyright, +# license) +# +TAB_HEADER = 'Header' +TAB_HEADER_ABSTRACT = 'Abstract' +TAB_HEADER_DESCRIPTION = 'Description' +TAB_HEADER_COPYRIGHT = 'Copyright' +TAB_HEADER_LICENSE = 'License' +TAB_BINARY_HEADER_IDENTIFIER = 'BinaryHeader' +TAB_BINARY_HEADER_USERID = 'TianoCore' + +# +# Build database path +# +DATABASE_PATH = ":memory:" +# +# used by ECC +# +MODIFIER_LIST = ['IN', 'OUT', 'OPTIONAL', 'UNALIGNED', 'EFI_RUNTIMESERVICE', \ + 'EFI_BOOTSERVICE', 'EFIAPI'] +# +# Dependency Expression +# +DEPEX_SUPPORTED_OPCODE = ["BEFORE", "AFTER", "PUSH", "AND", "OR", "NOT", \ + "END", "SOR", "TRUE", "FALSE", '(', ')'] + +TAB_STATIC_LIBRARY = "STATIC-LIBRARY-FILE" +TAB_DYNAMIC_LIBRARY = "DYNAMIC-LIBRARY-FILE" +TAB_FRAMEWORK_IMAGE = "EFI-IMAGE-FILE" +TAB_C_CODE_FILE = "C-CODE-FILE" +TAB_C_HEADER_FILE = "C-HEADER-FILE" +TAB_UNICODE_FILE = "UNICODE-TEXT-FILE" +TAB_DEPENDENCY_EXPRESSION_FILE = "DEPENDENCY-EXPRESSION-FILE" +TAB_UNKNOWN_FILE = "UNKNOWN-TYPE-FILE" +TAB_DEFAULT_BINARY_FILE = "_BINARY_FILE_" +# +# used to indicate the state of processing header comment section of dec, +# inf files +# +HEADER_COMMENT_NOT_STARTED = -1 +HEADER_COMMENT_STARTED = 0 +HEADER_COMMENT_FILE = 1 +HEADER_COMMENT_ABSTRACT = 2 +HEADER_COMMENT_DESCRIPTION = 3 +HEADER_COMMENT_COPYRIGHT = 4 +HEADER_COMMENT_LICENSE = 5 +HEADER_COMMENT_END = 6 + +# +# Static values for data models +# +MODEL_UNKNOWN = 0 + +MODEL_FILE_C = 1001 +MODEL_FILE_H = 1002 +MODEL_FILE_ASM = 1003 +MODEL_FILE_INF = 1011 +MODEL_FILE_DEC = 1012 +MODEL_FILE_DSC = 1013 +MODEL_FILE_FDF = 1014 +MODEL_FILE_INC = 1015 +MODEL_FILE_CIF = 1016 + +MODEL_IDENTIFIER_FILE_HEADER = 2001 +MODEL_IDENTIFIER_FUNCTION_HEADER = 2002 +MODEL_IDENTIFIER_COMMENT = 2003 +MODEL_IDENTIFIER_PARAMETER = 2004 +MODEL_IDENTIFIER_STRUCTURE = 2005 +MODEL_IDENTIFIER_VARIABLE = 2006 +MODEL_IDENTIFIER_INCLUDE = 2007 +MODEL_IDENTIFIER_PREDICATE_EXPRESSION = 2008 +MODEL_IDENTIFIER_ENUMERATE = 2009 +MODEL_IDENTIFIER_PCD = 2010 +MODEL_IDENTIFIER_UNION = 2011 +MODEL_IDENTIFIER_MACRO_IFDEF = 2012 +MODEL_IDENTIFIER_MACRO_IFNDEF = 2013 +MODEL_IDENTIFIER_MACRO_DEFINE = 2014 +MODEL_IDENTIFIER_MACRO_ENDIF = 2015 +MODEL_IDENTIFIER_MACRO_PROGMA = 2016 +MODEL_IDENTIFIER_FUNCTION_CALLING = 2018 +MODEL_IDENTIFIER_TYPEDEF = 2017 +MODEL_IDENTIFIER_FUNCTION_DECLARATION = 2019 +MODEL_IDENTIFIER_ASSIGNMENT_EXPRESSION = 2020 + +MODEL_EFI_PROTOCOL = 3001 +MODEL_EFI_PPI = 3002 +MODEL_EFI_GUID = 3003 +MODEL_EFI_LIBRARY_CLASS = 3004 +MODEL_EFI_LIBRARY_INSTANCE = 3005 +MODEL_EFI_PCD = 3006 +MODEL_EFI_SOURCE_FILE = 3007 +MODEL_EFI_BINARY_FILE = 3008 +MODEL_EFI_SKU_ID = 3009 +MODEL_EFI_INCLUDE = 3010 +MODEL_EFI_DEPEX = 3011 + +MODEL_PCD = 4000 +MODEL_PCD_FIXED_AT_BUILD = 4001 +MODEL_PCD_PATCHABLE_IN_MODULE = 4002 +MODEL_PCD_FEATURE_FLAG = 4003 +MODEL_PCD_DYNAMIC_EX = 4004 +MODEL_PCD_DYNAMIC_EX_DEFAULT = 4005 +MODEL_PCD_DYNAMIC_EX_VPD = 4006 +MODEL_PCD_DYNAMIC_EX_HII = 4007 +MODEL_PCD_DYNAMIC = 4008 +MODEL_PCD_DYNAMIC_DEFAULT = 4009 +MODEL_PCD_DYNAMIC_VPD = 4010 +MODEL_PCD_DYNAMIC_HII = 4011 + +MODEL_META_DATA_FILE_HEADER = 5000 +MODEL_META_DATA_HEADER = 5001 +MODEL_META_DATA_INCLUDE = 5002 +MODEL_META_DATA_DEFINE = 5003 +MODEL_META_DATA_CONDITIONAL_STATEMENT_IF = 5004 +MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE = 5005 +MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF = 5006 +MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF = 5007 +MODEL_META_DATA_BUILD_OPTION = 5008 +MODEL_META_DATA_COMPONENT = 5009 +MODEL_META_DATA_USER_EXTENSION = 5010 +MODEL_META_DATA_PACKAGE = 5011 +MODEL_META_DATA_NMAKE = 5012 +MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF = 50013 +MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF = 5014 + +TOOL_FAMILY_LIST = ["MSFT", + "INTEL", + "GCC", + "RVCT" + ] + +TYPE_HOB_SECTION = 'HOB' +TYPE_EVENT_SECTION = 'EVENT' +TYPE_BOOTMODE_SECTION = 'BOOTMODE' + +PCD_ERR_CODE_MAX_SIZE = 4294967295 diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/ExpressionValidate.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/ExpressionValidate.py new file mode 100755 index 00000000..ae5f835b --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/ExpressionValidate.py @@ -0,0 +1,567 @@ +## @file +# This file is used to check PCD logical expression +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +''' +ExpressionValidate +''' +from __future__ import print_function + +## +# Import Modules +# +import re +from Logger import StringTable as ST + +## IsValidBareCString +# +# Check if String is comprised by whitespace(0x20), !(0x21), 0x23 - 0x7E +# or '\n', '\t', '\f', '\r', '\b', '\0', '\\' +# +# @param String: string to be checked +# +def IsValidBareCString(String): + EscapeList = ['n', 't', 'f', 'r', 'b', '0', '\\', '"'] + PreChar = '' + LastChar = '' + for Char in String: + LastChar = Char + if PreChar == '\\': + if Char not in EscapeList: + return False + if Char == '\\': + PreChar = '' + continue + else: + IntChar = ord(Char) + if IntChar != 0x20 and IntChar != 0x09 and IntChar != 0x21 \ + and (IntChar < 0x23 or IntChar > 0x7e): + return False + PreChar = Char + + # Last char cannot be \ if PreChar is not \ + if LastChar == '\\' and PreChar == LastChar: + return False + return True + +def _ValidateToken(Token): + Token = Token.strip() + Index = Token.find("\"") + if Index != -1: + return IsValidBareCString(Token[Index+1:-1]) + return True + +## _ExprError +# +# @param Exception: Exception +# +class _ExprError(Exception): + def __init__(self, Error = ''): + Exception.__init__(self) + self.Error = Error + +## _ExprBase +# +class _ExprBase: + HEX_PATTERN = '[\t\s]*0[xX][a-fA-F0-9]+' + INT_PATTERN = '[\t\s]*[0-9]+' + MACRO_PATTERN = '[\t\s]*\$\(([A-Z][_A-Z0-9]*)\)' + PCD_PATTERN = \ + '[\t\s]*[_a-zA-Z][a-zA-Z0-9_]*[\t\s]*\.[\t\s]*[_a-zA-Z][a-zA-Z0-9_]*' + QUOTED_PATTERN = '[\t\s]*L?"[^"]*"' + BOOL_PATTERN = '[\t\s]*(true|True|TRUE|false|False|FALSE)' + def __init__(self, Token): + self.Token = Token + self.Index = 0 + self.Len = len(Token) + + ## SkipWhitespace + # + def SkipWhitespace(self): + for Char in self.Token[self.Index:]: + if Char not in ' \t': + break + self.Index += 1 + + ## IsCurrentOp + # + # @param OpList: option list + # + def IsCurrentOp(self, OpList): + self.SkipWhitespace() + LetterOp = ["EQ", "NE", "GE", "LE", "GT", "LT", "NOT", "and", "AND", + "or", "OR", "XOR"] + OpMap = { + '|' : '|', + '&' : '&', + '!' : '=', + '>' : '=', + '<' : '=' + } + + for Operator in OpList: + if not self.Token[self.Index:].startswith(Operator): + continue + + self.Index += len(Operator) + Char = self.Token[self.Index : self.Index + 1] + + if (Operator in LetterOp and (Char == '_' or Char.isalnum())) \ + or (Operator in OpMap and OpMap[Operator] == Char): + self.Index -= len(Operator) + break + + return True + + return False + +## _LogicalExpressionParser +# +# @param _ExprBase: _ExprBase object +# +class _LogicalExpressionParser(_ExprBase): + # + # STRINGITEM can only be logical field according to spec + # + STRINGITEM = -1 + + # + # Evaluate to True or False + # + LOGICAL = 0 + REALLOGICAL = 2 + + # + # Just arithmetic expression + # + ARITH = 1 + + def __init__(self, Token): + _ExprBase.__init__(self, Token) + self.Parens = 0 + + def _CheckToken(self, MatchList): + for Match in MatchList: + if Match and Match.start() == 0: + if not _ValidateToken( + self.Token[self.Index:self.Index+Match.end()] + ): + return False + + self.Index += Match.end() + if self.Token[self.Index - 1] == '"': + return True + if self.Token[self.Index:self.Index+1] == '_' or \ + self.Token[self.Index:self.Index+1].isalnum(): + self.Index -= Match.end() + return False + + Token = self.Token[self.Index - Match.end():self.Index] + if Token.strip() in ["EQ", "NE", "GE", "LE", "GT", "LT", + "NOT", "and", "AND", "or", "OR", "XOR"]: + self.Index -= Match.end() + return False + + return True + + return False + + def IsAtomicNumVal(self): + # + # Hex number + # + Match1 = re.compile(self.HEX_PATTERN).match(self.Token[self.Index:]) + + # + # Number + # + Match2 = re.compile(self.INT_PATTERN).match(self.Token[self.Index:]) + + # + # Macro + # + Match3 = re.compile(self.MACRO_PATTERN).match(self.Token[self.Index:]) + + # + # PcdName + # + Match4 = re.compile(self.PCD_PATTERN).match(self.Token[self.Index:]) + + return self._CheckToken([Match1, Match2, Match3, Match4]) + + + def IsAtomicItem(self): + # + # Macro + # + Match1 = re.compile(self.MACRO_PATTERN).match(self.Token[self.Index:]) + + # + # PcdName + # + Match2 = re.compile(self.PCD_PATTERN).match(self.Token[self.Index:]) + + # + # Quoted string + # + Match3 = re.compile(self.QUOTED_PATTERN).\ + match(self.Token[self.Index:].replace('\\\\', '//').\ + replace('\\\"', '\\\'')) + + return self._CheckToken([Match1, Match2, Match3]) + + ## A || B + # + def LogicalExpression(self): + Ret = self.SpecNot() + while self.IsCurrentOp(['||', 'OR', 'or', '&&', 'AND', 'and', 'XOR', 'xor', '^']): + if self.Token[self.Index-1] == '|' and self.Parens <= 0: + raise _ExprError(ST.ERR_EXPR_OR % self.Token) + if Ret not in [self.ARITH, self.LOGICAL, self.REALLOGICAL, self.STRINGITEM]: + raise _ExprError(ST.ERR_EXPR_LOGICAL % self.Token) + Ret = self.SpecNot() + if Ret not in [self.ARITH, self.LOGICAL, self.REALLOGICAL, self.STRINGITEM]: + raise _ExprError(ST.ERR_EXPR_LOGICAL % self.Token) + Ret = self.REALLOGICAL + return Ret + + def SpecNot(self): + if self.IsCurrentOp(["NOT", "!", "not"]): + return self.SpecNot() + return self.Rel() + + ## A < B, A > B, A <= B, A >= B + # + def Rel(self): + Ret = self.Expr() + if self.IsCurrentOp(["<=", ">=", ">", "<", "GT", "LT", "GE", "LE", + "==", "EQ", "!=", "NE"]): + if Ret == self.STRINGITEM: + raise _ExprError(ST.ERR_EXPR_LOGICAL % self.Token) + Ret = self.Expr() + if Ret == self.REALLOGICAL: + raise _ExprError(ST.ERR_EXPR_LOGICAL % self.Token) + Ret = self.REALLOGICAL + return Ret + + ## A + B, A - B + # + def Expr(self): + Ret = self.Factor() + while self.IsCurrentOp(["+", "-", "&", "|", "^", "XOR", "xor"]): + if self.Token[self.Index-1] == '|' and self.Parens <= 0: + raise _ExprError(ST.ERR_EXPR_OR) + if Ret == self.STRINGITEM or Ret == self.REALLOGICAL: + raise _ExprError(ST.ERR_EXPR_LOGICAL % self.Token) + Ret = self.Factor() + if Ret == self.STRINGITEM or Ret == self.REALLOGICAL: + raise _ExprError(ST.ERR_EXPR_LOGICAL % self.Token) + Ret = self.ARITH + return Ret + + ## Factor + # + def Factor(self): + if self.IsCurrentOp(["("]): + self.Parens += 1 + Ret = self.LogicalExpression() + if not self.IsCurrentOp([")"]): + raise _ExprError(ST.ERR_EXPR_RIGHT_PAREN % \ + (self.Token, self.Token[self.Index:])) + self.Parens -= 1 + return Ret + + if self.IsAtomicItem(): + if self.Token[self.Index - 1] == '"': + return self.STRINGITEM + return self.LOGICAL + elif self.IsAtomicNumVal(): + return self.ARITH + else: + raise _ExprError(ST.ERR_EXPR_FACTOR % \ + (self.Token[self.Index:], self.Token)) + + ## IsValidLogicalExpression + # + def IsValidLogicalExpression(self): + if self.Len == 0: + return False, ST.ERR_EXPRESS_EMPTY + try: + if self.LogicalExpression() not in [self.ARITH, self.LOGICAL, self.REALLOGICAL, self.STRINGITEM]: + return False, ST.ERR_EXPR_LOGICAL % self.Token + except _ExprError as XExcept: + return False, XExcept.Error + self.SkipWhitespace() + if self.Index != self.Len: + return False, (ST.ERR_EXPR_BOOLEAN % \ + (self.Token[self.Index:], self.Token)) + return True, '' + +## _ValidRangeExpressionParser +# +class _ValidRangeExpressionParser(_ExprBase): + INT_RANGE_PATTERN = '[\t\s]*[0-9]+[\t\s]*-[\t\s]*[0-9]+' + HEX_RANGE_PATTERN = \ + '[\t\s]*0[xX][a-fA-F0-9]+[\t\s]*-[\t\s]*0[xX][a-fA-F0-9]+' + def __init__(self, Token): + _ExprBase.__init__(self, Token) + self.Parens = 0 + self.HEX = 1 + self.INT = 2 + self.IsParenHappen = False + self.IsLogicalOpHappen = False + + ## IsValidRangeExpression + # + def IsValidRangeExpression(self): + if self.Len == 0: + return False, ST.ERR_EXPR_RANGE_EMPTY + try: + if self.RangeExpression() not in [self.HEX, self.INT]: + return False, ST.ERR_EXPR_RANGE % self.Token + except _ExprError as XExcept: + return False, XExcept.Error + + self.SkipWhitespace() + if self.Index != self.Len: + return False, (ST.ERR_EXPR_RANGE % self.Token) + return True, '' + + ## RangeExpression + # + def RangeExpression(self): + Ret = self.Unary() + while self.IsCurrentOp(['OR', 'AND', 'and', 'or']): + self.IsLogicalOpHappen = True + if not self.IsParenHappen: + raise _ExprError(ST.ERR_PAREN_NOT_USED % self.Token) + self.IsParenHappen = False + Ret = self.Unary() + + if self.IsCurrentOp(['XOR']): + Ret = self.Unary() + + return Ret + + ## Unary + # + def Unary(self): + if self.IsCurrentOp(["NOT"]): + return self.Unary() + + return self.ValidRange() + + ## ValidRange + # + def ValidRange(self): + Ret = -1 + if self.IsCurrentOp(["("]): + self.IsLogicalOpHappen = False + self.IsParenHappen = True + self.Parens += 1 + if self.Parens > 1: + raise _ExprError(ST.ERR_EXPR_RANGE_DOUBLE_PAREN_NESTED % self.Token) + Ret = self.RangeExpression() + if not self.IsCurrentOp([")"]): + raise _ExprError(ST.ERR_EXPR_RIGHT_PAREN % self.Token) + self.Parens -= 1 + return Ret + + if self.IsLogicalOpHappen: + raise _ExprError(ST.ERR_PAREN_NOT_USED % self.Token) + + if self.IsCurrentOp(["LT", "GT", "LE", "GE", "EQ", "XOR"]): + IntMatch = \ + re.compile(self.INT_PATTERN).match(self.Token[self.Index:]) + HexMatch = \ + re.compile(self.HEX_PATTERN).match(self.Token[self.Index:]) + if HexMatch and HexMatch.start() == 0: + self.Index += HexMatch.end() + Ret = self.HEX + elif IntMatch and IntMatch.start() == 0: + self.Index += IntMatch.end() + Ret = self.INT + else: + raise _ExprError(ST.ERR_EXPR_RANGE_FACTOR % (self.Token[self.Index:], self.Token)) + else: + IntRangeMatch = re.compile( + self.INT_RANGE_PATTERN).match(self.Token[self.Index:] + ) + HexRangeMatch = re.compile( + self.HEX_RANGE_PATTERN).match(self.Token[self.Index:] + ) + if HexRangeMatch and HexRangeMatch.start() == 0: + self.Index += HexRangeMatch.end() + Ret = self.HEX + elif IntRangeMatch and IntRangeMatch.start() == 0: + self.Index += IntRangeMatch.end() + Ret = self.INT + else: + raise _ExprError(ST.ERR_EXPR_RANGE % self.Token) + + return Ret + +## _ValidListExpressionParser +# +class _ValidListExpressionParser(_ExprBase): + VALID_LIST_PATTERN = '(0[xX][0-9a-fA-F]+|[0-9]+)([\t\s]*,[\t\s]*(0[xX][0-9a-fA-F]+|[0-9]+))*' + def __init__(self, Token): + _ExprBase.__init__(self, Token) + self.NUM = 1 + + def IsValidListExpression(self): + if self.Len == 0: + return False, ST.ERR_EXPR_LIST_EMPTY + try: + if self.ListExpression() not in [self.NUM]: + return False, ST.ERR_EXPR_LIST % self.Token + except _ExprError as XExcept: + return False, XExcept.Error + + self.SkipWhitespace() + if self.Index != self.Len: + return False, (ST.ERR_EXPR_LIST % self.Token) + + return True, '' + + def ListExpression(self): + Ret = -1 + self.SkipWhitespace() + ListMatch = re.compile(self.VALID_LIST_PATTERN).match(self.Token[self.Index:]) + if ListMatch and ListMatch.start() == 0: + self.Index += ListMatch.end() + Ret = self.NUM + else: + raise _ExprError(ST.ERR_EXPR_LIST % self.Token) + + return Ret + +## _StringTestParser +# +class _StringTestParser(_ExprBase): + def __init__(self, Token): + _ExprBase.__init__(self, Token) + + ## IsValidStringTest + # + def IsValidStringTest(self): + if self.Len == 0: + return False, ST.ERR_EXPR_EMPTY + try: + self.StringTest() + except _ExprError as XExcept: + return False, XExcept.Error + return True, '' + + ## StringItem + # + def StringItem(self): + Match1 = re.compile(self.QUOTED_PATTERN)\ + .match(self.Token[self.Index:].replace('\\\\', '//')\ + .replace('\\\"', '\\\'')) + Match2 = re.compile(self.MACRO_PATTERN).match(self.Token[self.Index:]) + Match3 = re.compile(self.PCD_PATTERN).match(self.Token[self.Index:]) + MatchList = [Match1, Match2, Match3] + for Match in MatchList: + if Match and Match.start() == 0: + if not _ValidateToken( + self.Token[self.Index:self.Index+Match.end()] + ): + raise _ExprError(ST.ERR_EXPR_STRING_ITEM % \ + (self.Token, self.Token[self.Index:])) + self.Index += Match.end() + Token = self.Token[self.Index - Match.end():self.Index] + if Token.strip() in ["EQ", "NE"]: + raise _ExprError(ST.ERR_EXPR_STRING_ITEM % \ + (self.Token, self.Token[self.Index:])) + return + else: + raise _ExprError(ST.ERR_EXPR_STRING_ITEM % \ + (self.Token, self.Token[self.Index:])) + + ## StringTest + # + def StringTest(self): + self.StringItem() + if not self.IsCurrentOp(["==", "EQ", "!=", "NE"]): + raise _ExprError(ST.ERR_EXPR_EQUALITY % \ + (self.Token[self.Index:], self.Token)) + self.StringItem() + if self.Index != self.Len: + raise _ExprError(ST.ERR_EXPR_BOOLEAN % \ + (self.Token[self.Index:], self.Token)) + +## +# Check syntax of string test +# +# @param Token: string test token +# +def IsValidStringTest(Token, Flag=False): + # + # Not do the check right now, keep the implementation for future enhancement. + # + if not Flag: + return True, "" + return _StringTestParser(Token).IsValidStringTest() + + +## +# Check syntax of logical expression +# +# @param Token: expression token +# +def IsValidLogicalExpr(Token, Flag=False): + # + # Not do the check right now, keep the implementation for future enhancement. + # + if not Flag: + return True, "" + return _LogicalExpressionParser(Token).IsValidLogicalExpression() + +## +# Check syntax of range expression +# +# @param Token: range expression token +# +def IsValidRangeExpr(Token): + return _ValidRangeExpressionParser(Token).IsValidRangeExpression() + +## +# Check syntax of value list expression token +# +# @param Token: value list expression token +# +def IsValidListExpr(Token): + return _ValidListExpressionParser(Token).IsValidListExpression() + +## +# Check whether the feature flag expression is valid or not +# +# @param Token: feature flag expression +# +def IsValidFeatureFlagExp(Token, Flag=False): + # + # Not do the check right now, keep the implementation for future enhancement. + # + if not Flag: + return True, "", Token + else: + if Token in ['TRUE', 'FALSE', 'true', 'false', 'True', 'False', + '0x1', '0x01', '0x0', '0x00']: + return True, "" + Valid, Cause = IsValidStringTest(Token, Flag) + if not Valid: + Valid, Cause = IsValidLogicalExpr(Token, Flag) + if not Valid: + return False, Cause + return True, "" + +if __name__ == '__main__': +# print IsValidRangeExpr('LT 9') + print(_LogicalExpressionParser('gCrownBayTokenSpaceGuid.PcdPciDevice1BridgeAddressLE0').IsValidLogicalExpression()) + + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/GlobalData.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/GlobalData.py new file mode 100644 index 00000000..984294c9 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/GlobalData.py @@ -0,0 +1,110 @@ +## @file +# This file is used to define common static strings and global data used by UPT +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +''' +GlobalData +''' + +# +# The workspace directory +# +gWORKSPACE = '.' +gPACKAGE_PATH = None + +# +# INF module directory +# +gINF_MODULE_DIR = "." +gINF_MODULE_NAME = '' + +# +# the directory to holds upt related files +# +gUPT_DIR = r"Conf/upt/" + +# +# Log file for invalid meta-data files during force removing +# +gINVALID_MODULE_FILE = gUPT_DIR + r"Invalid_Modules.log" + +# +# File name for content zip file in the distribution +# +gCONTENT_FILE = "dist.content" + +# +# File name for XML file in the distribution +# +gDESC_FILE = 'dist.pkg' + +# +# Case Insensitive flag +# +gCASE_INSENSITIVE = '' + +# +# All Files dictionary +# +gALL_FILES = {} + +# +# Database instance +# +gDB = None + +# +# list for files that are found in module level but not in INF files, +# items are (File, ModulePath), all these should be relative to $(WORKSPACE) +# +gMISS_FILE_IN_MODLIST = [] + +# +# Global Current Line +# +gINF_CURRENT_LINE = None + +# +# Global pkg list +# +gWSPKG_LIST = [] + +# +# Flag used to take WARN as ERROR. +# By default, only ERROR message will break the tools execution. +# +gWARNING_AS_ERROR = False + +# +# Used to specify the temp directory to hold the unpacked distribution files +# +gUNPACK_DIR = [] + +# +# Flag used to mark whether the INF file is Binary INF or not. +# +gIS_BINARY_INF = False + +# +# Used by FileHook module. +# +gRECOVERMGR = None + +# +# Used by PCD parser +# +gPackageDict = {} + +# +# Used by Library instance parser +# {FilePath: FileObj} +# +gLIBINSTANCEDICT = {} + +# +# Store the list of DIST +# +gTO_BE_INSTALLED_DIST_LIST = [] diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/Misc.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/Misc.py new file mode 100755 index 00000000..da62c9a7 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/Misc.py @@ -0,0 +1,989 @@ +## @file +# Common routines used by all tools +# +# Copyright (c) 2011 - 2019, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +Misc +''' + +## +# Import Modules +# +import os.path +from os import access +from os import F_OK +from os import makedirs +from os import getcwd +from os import chdir +from os import listdir +from os import remove +from os import rmdir +from os import linesep +from os import walk +from os import environ +import re +from collections import OrderedDict as Sdict + +import Logger.Log as Logger +from Logger import StringTable as ST +from Logger import ToolError +from Library import GlobalData +from Library.DataType import SUP_MODULE_LIST +from Library.DataType import END_OF_LINE +from Library.DataType import TAB_SPLIT +from Library.DataType import TAB_LANGUAGE_EN_US +from Library.DataType import TAB_LANGUAGE_EN +from Library.DataType import TAB_LANGUAGE_EN_X +from Library.DataType import TAB_UNI_FILE_SUFFIXS +from Library.StringUtils import GetSplitValueList +from Library.ParserValidate import IsValidHexVersion +from Library.ParserValidate import IsValidPath +from Object.POM.CommonObject import TextObject +from Core.FileHook import __FileHookOpen__ +from Common.MultipleWorkspace import MultipleWorkspace as mws + +## Convert GUID string in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx style to C +# structure style +# +# @param Guid: The GUID string +# +def GuidStringToGuidStructureString(Guid): + GuidList = Guid.split('-') + Result = '{' + for Index in range(0, 3, 1): + Result = Result + '0x' + GuidList[Index] + ', ' + Result = Result + '{0x' + GuidList[3][0:2] + ', 0x' + GuidList[3][2:4] + for Index in range(0, 12, 2): + Result = Result + ', 0x' + GuidList[4][Index:Index + 2] + Result += '}}' + return Result + +## Check whether GUID string is of format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +# +# @param GuidValue: The GUID value +# +def CheckGuidRegFormat(GuidValue): + ## Regular expression used to find out register format of GUID + # + RegFormatGuidPattern = re.compile("^\s*([0-9a-fA-F]){8}-" + "([0-9a-fA-F]){4}-" + "([0-9a-fA-F]){4}-" + "([0-9a-fA-F]){4}-" + "([0-9a-fA-F]){12}\s*$") + + if RegFormatGuidPattern.match(GuidValue): + return True + else: + return False + + +## Convert GUID string in C structure style to +# xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +# +# @param GuidValue: The GUID value in C structure format +# +def GuidStructureStringToGuidString(GuidValue): + GuidValueString = GuidValue.lower().replace("{", "").replace("}", "").\ + replace(" ", "").replace(";", "") + GuidValueList = GuidValueString.split(",") + if len(GuidValueList) != 11: + return '' + try: + return "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x" % ( + int(GuidValueList[0], 16), + int(GuidValueList[1], 16), + int(GuidValueList[2], 16), + int(GuidValueList[3], 16), + int(GuidValueList[4], 16), + int(GuidValueList[5], 16), + int(GuidValueList[6], 16), + int(GuidValueList[7], 16), + int(GuidValueList[8], 16), + int(GuidValueList[9], 16), + int(GuidValueList[10], 16) + ) + except BaseException: + return '' + +## Create directories +# +# @param Directory: The directory name +# +def CreateDirectory(Directory): + if Directory is None or Directory.strip() == "": + return True + try: + if not access(Directory, F_OK): + makedirs(Directory) + except BaseException: + return False + return True + +## Remove directories, including files and sub-directories in it +# +# @param Directory: The directory name +# +def RemoveDirectory(Directory, Recursively=False): + if Directory is None or Directory.strip() == "" or not \ + os.path.exists(Directory): + return + if Recursively: + CurrentDirectory = getcwd() + chdir(Directory) + for File in listdir("."): + if os.path.isdir(File): + RemoveDirectory(File, Recursively) + else: + remove(File) + chdir(CurrentDirectory) + rmdir(Directory) + +## Store content in file +# +# This method is used to save file only when its content is changed. This is +# quite useful for "make" system to decide what will be re-built and what +# won't. +# +# @param File: The path of file +# @param Content: The new content of the file +# @param IsBinaryFile: The flag indicating if the file is binary file +# or not +# +def SaveFileOnChange(File, Content, IsBinaryFile=True): + if os.path.exists(File): + if IsBinaryFile: + try: + if Content == __FileHookOpen__(File, "rb").read(): + return False + except BaseException: + Logger.Error(None, ToolError.FILE_OPEN_FAILURE, ExtraData=File) + else: + try: + if Content == __FileHookOpen__(File, "r").read(): + return False + except BaseException: + Logger.Error(None, ToolError.FILE_OPEN_FAILURE, ExtraData=File) + + CreateDirectory(os.path.dirname(File)) + if IsBinaryFile: + try: + FileFd = __FileHookOpen__(File, "wb") + FileFd.write(Content) + FileFd.close() + except BaseException: + Logger.Error(None, ToolError.FILE_CREATE_FAILURE, ExtraData=File) + else: + try: + FileFd = __FileHookOpen__(File, "w") + FileFd.write(Content) + FileFd.close() + except BaseException: + Logger.Error(None, ToolError.FILE_CREATE_FAILURE, ExtraData=File) + + return True + +## Get all files of a directory +# +# @param Root: Root dir +# @param SkipList : The files need be skipped +# +def GetFiles(Root, SkipList=None, FullPath=True): + OriPath = os.path.normpath(Root) + FileList = [] + for Root, Dirs, Files in walk(Root): + if SkipList: + for Item in SkipList: + if Item in Dirs: + Dirs.remove(Item) + if Item in Files: + Files.remove(Item) + for Dir in Dirs: + if Dir.startswith('.'): + Dirs.remove(Dir) + + for File in Files: + if File.startswith('.'): + continue + File = os.path.normpath(os.path.join(Root, File)) + if not FullPath: + File = File[len(OriPath) + 1:] + FileList.append(File) + + return FileList + +## Get all non-metadata files of a directory +# +# @param Root: Root Dir +# @param SkipList : List of path need be skipped +# @param FullPath: True if the returned file should be full path +# @param PrefixPath: the path that need to be added to the files found +# @return: the list of files found +# +def GetNonMetaDataFiles(Root, SkipList, FullPath, PrefixPath): + FileList = GetFiles(Root, SkipList, FullPath) + NewFileList = [] + for File in FileList: + ExtName = os.path.splitext(File)[1] + # + # skip '.dec', '.inf', '.dsc', '.fdf' files + # + if ExtName.lower() not in ['.dec', '.inf', '.dsc', '.fdf']: + NewFileList.append(os.path.normpath(os.path.join(PrefixPath, File))) + + return NewFileList + +## Check if given file exists or not +# +# @param File: File name or path to be checked +# @param Dir: The directory the file is relative to +# +def ValidFile(File, Ext=None): + File = File.replace('\\', '/') + if Ext is not None: + FileExt = os.path.splitext(File)[1] + if FileExt.lower() != Ext.lower(): + return False + if not os.path.exists(File): + return False + return True + +## RealPath +# +# @param File: File name or path to be checked +# @param Dir: The directory the file is relative to +# @param OverrideDir: The override directory +# +def RealPath(File, Dir='', OverrideDir=''): + NewFile = os.path.normpath(os.path.join(Dir, File)) + NewFile = GlobalData.gALL_FILES[NewFile] + if not NewFile and OverrideDir: + NewFile = os.path.normpath(os.path.join(OverrideDir, File)) + NewFile = GlobalData.gALL_FILES[NewFile] + return NewFile + +## RealPath2 +# +# @param File: File name or path to be checked +# @param Dir: The directory the file is relative to +# @param OverrideDir: The override directory +# +def RealPath2(File, Dir='', OverrideDir=''): + if OverrideDir: + NewFile = GlobalData.gALL_FILES[os.path.normpath(os.path.join\ + (OverrideDir, File))] + if NewFile: + if OverrideDir[-1] == os.path.sep: + return NewFile[len(OverrideDir):], NewFile[0:len(OverrideDir)] + else: + return NewFile[len(OverrideDir) + 1:], \ + NewFile[0:len(OverrideDir)] + + NewFile = GlobalData.gALL_FILES[os.path.normpath(os.path.join(Dir, File))] + if NewFile: + if Dir: + if Dir[-1] == os.path.sep: + return NewFile[len(Dir):], NewFile[0:len(Dir)] + else: + return NewFile[len(Dir) + 1:], NewFile[0:len(Dir)] + else: + return NewFile, '' + + return None, None + +## CommonPath +# +# @param PathList: PathList +# +def CommonPath(PathList): + Path1 = min(PathList).split(os.path.sep) + Path2 = max(PathList).split(os.path.sep) + for Index in range(min(len(Path1), len(Path2))): + if Path1[Index] != Path2[Index]: + return os.path.sep.join(Path1[:Index]) + return os.path.sep.join(Path1) + +## PathClass +# +class PathClass(object): + def __init__(self, File='', Root='', AlterRoot='', Type='', IsBinary=False, + Arch='COMMON', ToolChainFamily='', Target='', TagName='', \ + ToolCode=''): + self.Arch = Arch + self.File = str(File) + if os.path.isabs(self.File): + self.Root = '' + self.AlterRoot = '' + else: + self.Root = str(Root) + self.AlterRoot = str(AlterRoot) + + # + # Remove any '.' and '..' in path + # + if self.Root: + self.Path = os.path.normpath(os.path.join(self.Root, self.File)) + self.Root = os.path.normpath(CommonPath([self.Root, self.Path])) + # + # eliminate the side-effect of 'C:' + # + if self.Root[-1] == ':': + self.Root += os.path.sep + # + # file path should not start with path separator + # + if self.Root[-1] == os.path.sep: + self.File = self.Path[len(self.Root):] + else: + self.File = self.Path[len(self.Root) + 1:] + else: + self.Path = os.path.normpath(self.File) + + self.SubDir, self.Name = os.path.split(self.File) + self.BaseName, self.Ext = os.path.splitext(self.Name) + + if self.Root: + if self.SubDir: + self.Dir = os.path.join(self.Root, self.SubDir) + else: + self.Dir = self.Root + else: + self.Dir = self.SubDir + + if IsBinary: + self.Type = Type + else: + self.Type = self.Ext.lower() + + self.IsBinary = IsBinary + self.Target = Target + self.TagName = TagName + self.ToolCode = ToolCode + self.ToolChainFamily = ToolChainFamily + + self._Key = None + + ## Convert the object of this class to a string + # + # Convert member Path of the class to a string + # + def __str__(self): + return self.Path + + ## Override __eq__ function + # + # Check whether PathClass are the same + # + def __eq__(self, Other): + if isinstance(Other, type(self)): + return self.Path == Other.Path + else: + return self.Path == str(Other) + + ## Override __hash__ function + # + # Use Path as key in hash table + # + def __hash__(self): + return hash(self.Path) + + ## _GetFileKey + # + def _GetFileKey(self): + if self._Key is None: + self._Key = self.Path.upper() + return self._Key + ## Validate + # + def Validate(self, Type='', CaseSensitive=True): + if GlobalData.gCASE_INSENSITIVE: + CaseSensitive = False + if Type and Type.lower() != self.Type: + return ToolError.FILE_TYPE_MISMATCH, '%s (expect %s but got %s)' % \ + (self.File, Type, self.Type) + + RealFile, RealRoot = RealPath2(self.File, self.Root, self.AlterRoot) + if not RealRoot and not RealFile: + RealFile = self.File + if self.AlterRoot: + RealFile = os.path.join(self.AlterRoot, self.File) + elif self.Root: + RealFile = os.path.join(self.Root, self.File) + return ToolError.FILE_NOT_FOUND, os.path.join(self.AlterRoot, RealFile) + + ErrorCode = 0 + ErrorInfo = '' + if RealRoot != self.Root or RealFile != self.File: + if CaseSensitive and (RealFile != self.File or \ + (RealRoot != self.Root and RealRoot != \ + self.AlterRoot)): + ErrorCode = ToolError.FILE_CASE_MISMATCH + ErrorInfo = self.File + '\n\t' + RealFile + \ + " [in file system]" + + self.SubDir, self.Name = os.path.split(RealFile) + self.BaseName, self.Ext = os.path.splitext(self.Name) + if self.SubDir: + self.Dir = os.path.join(RealRoot, self.SubDir) + else: + self.Dir = RealRoot + self.File = RealFile + self.Root = RealRoot + self.Path = os.path.join(RealRoot, RealFile) + return ErrorCode, ErrorInfo + + Key = property(_GetFileKey) + +## Get current workspace +# +# get WORKSPACE from environment variable if present,if not use current working directory as WORKSPACE +# +def GetWorkspace(): + # + # check WORKSPACE + # + if "WORKSPACE" in environ: + WorkspaceDir = os.path.normpath(environ["WORKSPACE"]) + if not os.path.exists(WorkspaceDir): + Logger.Error("UPT", + ToolError.UPT_ENVIRON_MISSING_ERROR, + ST.ERR_WORKSPACE_NOTEXIST, + ExtraData="%s" % WorkspaceDir) + else: + WorkspaceDir = os.getcwd() + + if WorkspaceDir[-1] == ':': + WorkspaceDir += os.sep + + PackagesPath = os.environ.get("PACKAGES_PATH") + mws.setWs(WorkspaceDir, PackagesPath) + + return WorkspaceDir, mws.PACKAGES_PATH + +## Get relative path +# +# use full path and workspace to get relative path +# the destination of this function is mainly to resolve the root path issue(like c: or c:\) +# +# @param Fullpath: a string of fullpath +# @param Workspace: a string of workspace +# +def GetRelativePath(Fullpath, Workspace): + + RelativePath = '' + if Workspace.endswith(os.sep): + RelativePath = Fullpath[Fullpath.upper().find(Workspace.upper())+len(Workspace):] + else: + RelativePath = Fullpath[Fullpath.upper().find(Workspace.upper())+len(Workspace)+1:] + + return RelativePath + +## Check whether all module types are in list +# +# check whether all module types (SUP_MODULE_LIST) are in list +# +# @param ModuleList: a list of ModuleType +# +def IsAllModuleList(ModuleList): + NewModuleList = [Module.upper() for Module in ModuleList] + for Module in SUP_MODULE_LIST: + if Module not in NewModuleList: + return False + else: + return True + +## Dictionary that use comment(GenericComment, TailComment) as value, +# if a new comment which key already in the dic is inserted, then the +# comment will be merged. +# Key is (Statement, SupArch), when TailComment is added, it will ident +# according to Statement +# +class MergeCommentDict(dict): + ## []= operator + # + def __setitem__(self, Key, CommentVal): + GenericComment, TailComment = CommentVal + if Key in self: + OrigVal1, OrigVal2 = dict.__getitem__(self, Key) + Statement = Key[0] + dict.__setitem__(self, Key, (OrigVal1 + GenericComment, OrigVal2 \ + + len(Statement) * ' ' + TailComment)) + else: + dict.__setitem__(self, Key, (GenericComment, TailComment)) + + ## =[] operator + # + def __getitem__(self, Key): + return dict.__getitem__(self, Key) + + +## GenDummyHelpTextObj +# +# @retval HelpTxt: Generated dummy help text object +# +def GenDummyHelpTextObj(): + HelpTxt = TextObject() + HelpTxt.SetLang(TAB_LANGUAGE_EN_US) + HelpTxt.SetString(' ') + return HelpTxt + +## ConvertVersionToDecimal, the minor version should be within 0 - 99 +# ::= "0x" +# ::= (a-fA-F0-9){4} +# ::= (a-fA-F0-9){4} +# ::= (0-65535) ["." (0-99)] +# +# @param StringIn: The string contains version defined in INF file. +# It can be Decimal or Hex +# +def ConvertVersionToDecimal(StringIn): + if IsValidHexVersion(StringIn): + Value = int(StringIn, 16) + Major = Value >> 16 + Minor = Value & 0xFFFF + MinorStr = str(Minor) + if len(MinorStr) == 1: + MinorStr = '0' + MinorStr + return str(Major) + '.' + MinorStr + else: + if StringIn.find(TAB_SPLIT) != -1: + return StringIn + elif StringIn: + return StringIn + '.0' + else: + # + # when StringIn is '', return it directly + # + return StringIn + +## GetHelpStringByRemoveHashKey +# +# Remove hash key at the header of string and return the remain. +# +# @param String: The string need to be processed. +# +def GetHelpStringByRemoveHashKey(String): + ReturnString = '' + PattenRemoveHashKey = re.compile(r"^[#+\s]+", re.DOTALL) + String = String.strip() + if String == '': + return String + + LineList = GetSplitValueList(String, END_OF_LINE) + for Line in LineList: + ValueList = PattenRemoveHashKey.split(Line) + if len(ValueList) == 1: + ReturnString += ValueList[0] + END_OF_LINE + else: + ReturnString += ValueList[1] + END_OF_LINE + + if ReturnString.endswith('\n') and not ReturnString.endswith('\n\n') and ReturnString != '\n': + ReturnString = ReturnString[:-1] + + return ReturnString + +## ConvPathFromAbsToRel +# +# Get relative file path from absolute path. +# +# @param Path: The string contain file absolute path. +# @param Root: The string contain the parent path of Path in. +# +# +def ConvPathFromAbsToRel(Path, Root): + Path = os.path.normpath(Path) + Root = os.path.normpath(Root) + FullPath = os.path.normpath(os.path.join(Root, Path)) + + # + # If Path is absolute path. + # It should be in Root. + # + if os.path.isabs(Path): + return FullPath[FullPath.find(Root) + len(Root) + 1:] + + else: + return Path + +## ConvertPath +# +# Convert special characters to '_', '\' to '/' +# return converted path: Test!1.inf -> Test_1.inf +# +# @param Path: Path to be converted +# +def ConvertPath(Path): + RetPath = '' + for Char in Path.strip(): + if Char.isalnum() or Char in '.-_/': + RetPath = RetPath + Char + elif Char == '\\': + RetPath = RetPath + '/' + else: + RetPath = RetPath + '_' + return RetPath + +## ConvertSpec +# +# during install, convert the Spec string extract from UPD into INF allowable definition, +# the difference is period is allowed in the former (not the first letter) but not in the latter. +# return converted Spec string +# +# @param SpecStr: SpecStr to be converted +# +def ConvertSpec(SpecStr): + RetStr = '' + for Char in SpecStr: + if Char.isalnum() or Char == '_': + RetStr = RetStr + Char + else: + RetStr = RetStr + '_' + + return RetStr + + +## IsEqualList +# +# Judge two lists are identical(contain same item). +# The rule is elements in List A are in List B and elements in List B are in List A. +# +# @param ListA, ListB Lists need to be judged. +# +# @return True ListA and ListB are identical +# @return False ListA and ListB are different with each other +# +def IsEqualList(ListA, ListB): + if ListA == ListB: + return True + + for ItemA in ListA: + if not ItemA in ListB: + return False + + for ItemB in ListB: + if not ItemB in ListA: + return False + + return True + +## ConvertArchList +# +# Convert item in ArchList if the start character is lower case. +# In UDP spec, Arch is only allowed as: [A-Z]([a-zA-Z0-9])* +# +# @param ArchList The ArchList need to be converted. +# +# @return NewList The ArchList been converted. +# +def ConvertArchList(ArchList): + NewArchList = [] + if not ArchList: + return NewArchList + + if isinstance(ArchList, list): + for Arch in ArchList: + Arch = Arch.upper() + NewArchList.append(Arch) + elif isinstance(ArchList, str): + ArchList = ArchList.upper() + NewArchList.append(ArchList) + + return NewArchList + +## ProcessLineExtender +# +# Process the LineExtender of Line in LineList. +# If one line ends with a line extender, then it will be combined together with next line. +# +# @param LineList The LineList need to be processed. +# +# @return NewList The ArchList been processed. +# +def ProcessLineExtender(LineList): + NewList = [] + Count = 0 + while Count < len(LineList): + if LineList[Count].strip().endswith("\\") and Count + 1 < len(LineList): + NewList.append(LineList[Count].strip()[:-2] + LineList[Count + 1]) + Count = Count + 1 + else: + NewList.append(LineList[Count]) + + Count = Count + 1 + + return NewList + +## ProcessEdkComment +# +# Process EDK style comment in LineList: c style /* */ comment or cpp style // comment +# +# +# @param LineList The LineList need to be processed. +# +# @return LineList The LineList been processed. +# @return FirstPos Where Edk comment is first found, -1 if not found +# +def ProcessEdkComment(LineList): + FindEdkBlockComment = False + Count = 0 + StartPos = -1 + EndPos = -1 + FirstPos = -1 + + while(Count < len(LineList)): + Line = LineList[Count].strip() + if Line.startswith("/*"): + # + # handling c style comment + # + StartPos = Count + while Count < len(LineList): + Line = LineList[Count].strip() + if Line.endswith("*/"): + if (Count == StartPos) and Line.strip() == '/*/': + Count = Count + 1 + continue + EndPos = Count + FindEdkBlockComment = True + break + Count = Count + 1 + + if FindEdkBlockComment: + if FirstPos == -1: + FirstPos = StartPos + for Index in range(StartPos, EndPos+1): + LineList[Index] = '' + FindEdkBlockComment = False + elif Line.find("//") != -1 and not Line.startswith("#"): + # + # handling cpp style comment + # + LineList[Count] = Line.replace("//", '#') + if FirstPos == -1: + FirstPos = Count + + Count = Count + 1 + + return LineList, FirstPos + +## GetLibInstanceInfo +# +# Get the information from Library Instance INF file. +# +# @param string. A string start with # and followed by INF file path +# @param WorkSpace. The WorkSpace directory used to combined with INF file path. +# +# @return GUID, Version +def GetLibInstanceInfo(String, WorkSpace, LineNo): + + FileGuidString = "" + VerString = "" + + OriginalString = String + String = String.strip() + if not String: + return None, None + # + # Remove "#" characters at the beginning + # + String = GetHelpStringByRemoveHashKey(String) + String = String.strip() + + # + # Validate file name exist. + # + FullFileName = os.path.normpath(os.path.realpath(os.path.join(WorkSpace, String))) + if not (ValidFile(FullFileName)): + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_FILELIST_EXIST % (String), + File=GlobalData.gINF_MODULE_NAME, + Line=LineNo, + ExtraData=OriginalString) + + # + # Validate file exist/format. + # + if IsValidPath(String, WorkSpace): + IsValidFileFlag = True + else: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID % (String), + File=GlobalData.gINF_MODULE_NAME, + Line=LineNo, + ExtraData=OriginalString) + return False + if IsValidFileFlag: + FileLinesList = [] + + try: + FInputfile = open(FullFileName, "r") + try: + FileLinesList = FInputfile.readlines() + except BaseException: + Logger.Error("InfParser", + ToolError.FILE_READ_FAILURE, + ST.ERR_FILE_OPEN_FAILURE, + File=FullFileName) + finally: + FInputfile.close() + except BaseException: + Logger.Error("InfParser", + ToolError.FILE_READ_FAILURE, + ST.ERR_FILE_OPEN_FAILURE, + File=FullFileName) + + ReFileGuidPattern = re.compile("^\s*FILE_GUID\s*=.*$") + ReVerStringPattern = re.compile("^\s*VERSION_STRING\s*=.*$") + + FileLinesList = ProcessLineExtender(FileLinesList) + + for Line in FileLinesList: + if ReFileGuidPattern.match(Line): + FileGuidString = Line + if ReVerStringPattern.match(Line): + VerString = Line + + if FileGuidString: + FileGuidString = GetSplitValueList(FileGuidString, '=', 1)[1] + if VerString: + VerString = GetSplitValueList(VerString, '=', 1)[1] + + return FileGuidString, VerString + +## GetLocalValue +# +# Generate the local value for INF and DEC file. If Lang attribute not present, then use this value. +# If present, and there is no element without the Lang attribute, and one of the elements has the rfc1766 code is +# "en-x-tianocore", or "en-US" if "en-x-tianocore" was not found, or "en" if "en-US" was not found, or startswith 'en' +# if 'en' was not found, then use this value. +# If multiple entries of a tag exist which have the same language code, use the last entry. +# +# @param ValueList A list need to be processed. +# @param UseFirstValue: True to use the first value, False to use the last value +# +# @return LocalValue +def GetLocalValue(ValueList, UseFirstValue=False): + Value1 = '' + Value2 = '' + Value3 = '' + Value4 = '' + Value5 = '' + for (Key, Value) in ValueList: + if Key == TAB_LANGUAGE_EN_X: + if UseFirstValue: + if not Value1: + Value1 = Value + else: + Value1 = Value + if Key == TAB_LANGUAGE_EN_US: + if UseFirstValue: + if not Value2: + Value2 = Value + else: + Value2 = Value + if Key == TAB_LANGUAGE_EN: + if UseFirstValue: + if not Value3: + Value3 = Value + else: + Value3 = Value + if Key.startswith(TAB_LANGUAGE_EN): + if UseFirstValue: + if not Value4: + Value4 = Value + else: + Value4 = Value + if Key == '': + if UseFirstValue: + if not Value5: + Value5 = Value + else: + Value5 = Value + + if Value1: + return Value1 + if Value2: + return Value2 + if Value3: + return Value3 + if Value4: + return Value4 + if Value5: + return Value5 + + return '' + + +## GetCharIndexOutStr +# +# Get comment character index outside a string +# +# @param Line: The string to be checked +# @param CommentCharacter: Comment char, used to ignore comment content +# +# @retval Index +# +def GetCharIndexOutStr(CommentCharacter, Line): + # + # remove whitespace + # + Line = Line.strip() + + # + # Check whether comment character is in a string + # + InString = False + for Index in range(0, len(Line)): + if Line[Index] == '"': + InString = not InString + elif Line[Index] == CommentCharacter and InString : + pass + elif Line[Index] == CommentCharacter and (Index +1) < len(Line) and Line[Index+1] == CommentCharacter \ + and not InString : + return Index + return -1 + +## ValidateUNIFilePath +# +# Check the UNI file path +# +# @param FilePath: The UNI file path +# +def ValidateUNIFilePath(Path): + Suffix = Path[Path.rfind(TAB_SPLIT):] + + # + # Check if the suffix is one of the '.uni', '.UNI', '.Uni' + # + if Suffix not in TAB_UNI_FILE_SUFFIXS: + Logger.Error("Unicode File Parser", + ToolError.FORMAT_INVALID, + Message=ST.ERR_UNI_FILE_SUFFIX_WRONG, + ExtraData=Path) + + # + # Check if '..' in the file name(without suffix) + # + if (TAB_SPLIT + TAB_SPLIT) in Path: + Logger.Error("Unicode File Parser", + ToolError.FORMAT_INVALID, + Message=ST.ERR_UNI_FILE_NAME_INVALID, + ExtraData=Path) + + # + # Check if the file name is valid according to the DEC and INF specification + # + Pattern = '[a-zA-Z0-9_][a-zA-Z0-9_\-\.]*' + FileName = Path.replace(Suffix, '') + InvalidCh = re.sub(Pattern, '', FileName) + if InvalidCh: + Logger.Error("Unicode File Parser", + ToolError.FORMAT_INVALID, + Message=ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID, + ExtraData=Path) + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/ParserValidate.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/ParserValidate.py new file mode 100755 index 00000000..23340583 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/ParserValidate.py @@ -0,0 +1,727 @@ +## @file ParserValidate.py +# Functions for parser validation +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +ParserValidate +''' + +import os.path +import re +import platform + +from Library.DataType import MODULE_LIST +from Library.DataType import COMPONENT_TYPE_LIST +from Library.DataType import PCD_USAGE_TYPE_LIST_OF_MODULE +from Library.DataType import TAB_SPACE_SPLIT +from Library.StringUtils import GetSplitValueList +from Library.ExpressionValidate import IsValidBareCString +from Library.ExpressionValidate import IsValidFeatureFlagExp +from Common.MultipleWorkspace import MultipleWorkspace as mws + +## __HexDigit() method +# +# Whether char input is a Hex data bit +# +# @param TempChar: The char to test +# +def __HexDigit(TempChar): + if (TempChar >= 'a' and TempChar <= 'f') or \ + (TempChar >= 'A' and TempChar <= 'F') \ + or (TempChar >= '0' and TempChar <= '9'): + return True + else: + return False + +## IsValidHex() method +# +# Whether char input is a Hex data. +# +# @param TempChar: The char to test +# +def IsValidHex(HexStr): + if not HexStr.upper().startswith("0X"): + return False + CharList = [c for c in HexStr[2:] if not __HexDigit(c)] + if len(CharList) == 0: + return True + else: + return False + +## Judge the input string is valid bool type or not. +# +# ::= {"TRUE"} {"true"} {"True"} {"0x1"} {"0x01"} +# ::= {"FALSE"} {"false"} {"False"} {"0x0"} {"0x00"} +# ::= {} {} +# +# @param BoolString: A string contained the value need to be judged. +# +def IsValidBoolType(BoolString): + # + # Valid True + # + if BoolString == 'TRUE' or \ + BoolString == 'True' or \ + BoolString == 'true' or \ + BoolString == '0x1' or \ + BoolString == '0x01': + return True + # + # Valid False + # + elif BoolString == 'FALSE' or \ + BoolString == 'False' or \ + BoolString == 'false' or \ + BoolString == '0x0' or \ + BoolString == '0x00': + return True + # + # Invalid bool type + # + else: + return False + +## Is Valid Module Type List or not +# +# @param ModuleTypeList: A list contain ModuleType strings need to be +# judged. +# +def IsValidInfMoudleTypeList(ModuleTypeList): + for ModuleType in ModuleTypeList: + return IsValidInfMoudleType(ModuleType) + +## Is Valid Module Type or not +# +# @param ModuleType: A string contain ModuleType need to be judged. +# +def IsValidInfMoudleType(ModuleType): + if ModuleType in MODULE_LIST: + return True + else: + return False + +## Is Valid Component Type or not +# +# @param ComponentType: A string contain ComponentType need to be judged. +# +def IsValidInfComponentType(ComponentType): + if ComponentType.upper() in COMPONENT_TYPE_LIST: + return True + else: + return False + + +## Is valid Tool Family or not +# +# @param ToolFamily: A string contain Tool Family need to be judged. +# Family := [A-Z]([a-zA-Z0-9])* +# +def IsValidToolFamily(ToolFamily): + ReIsValidFamily = re.compile(r"^[A-Z]+[A-Za-z0-9]{0,}$", re.DOTALL) + if ReIsValidFamily.match(ToolFamily) is None: + return False + return True + +## Is valid Tool TagName or not +# +# The TagName sample is MYTOOLS and VS2005. +# +# @param TagName: A string contain Tool TagName need to be judged. +# +def IsValidToolTagName(TagName): + if TagName.strip() == '': + return True + if TagName.strip() == '*': + return True + if not IsValidWord(TagName): + return False + return True + +## Is valid arch or not +# +# @param Arch The arch string need to be validated +# ::= (a-zA-Z)(A-Za-z0-9){0,} +# ::= {"IA32"} {"X64"} {"IPF"} {"EBC"} {} +# {"common"} +# @param Arch: Input arch +# +def IsValidArch(Arch): + if Arch == 'common': + return True + ReIsValidArch = re.compile(r"^[a-zA-Z]+[a-zA-Z0-9]{0,}$", re.DOTALL) + if ReIsValidArch.match(Arch) is None: + return False + return True + +## Is valid family or not +# +# ::= {"MSFT"} {"GCC"} {"INTEL"} {} {"*"} +# ::= [A-Z][A-Za-z0-9]{0,} +# +# @param family: The family string need to be validated +# +def IsValidFamily(Family): + Family = Family.strip() + if Family == '*': + return True + + if Family == '': + return True + + ReIsValidFamily = re.compile(r"^[A-Z]+[A-Za-z0-9]{0,}$", re.DOTALL) + if ReIsValidFamily.match(Family) is None: + return False + return True + +## Is valid build option name or not +# +# @param BuildOptionName: The BuildOptionName string need to be validated +# +def IsValidBuildOptionName(BuildOptionName): + if not BuildOptionName: + return False + + ToolOptionList = GetSplitValueList(BuildOptionName, '_', 4) + + if len(ToolOptionList) != 5: + return False + + ReIsValidBuildOption1 = re.compile(r"^\s*(\*)|([A-Z][a-zA-Z0-9]*)$") + ReIsValidBuildOption2 = re.compile(r"^\s*(\*)|([a-zA-Z][a-zA-Z0-9]*)$") + + if ReIsValidBuildOption1.match(ToolOptionList[0]) is None: + return False + + if ReIsValidBuildOption1.match(ToolOptionList[1]) is None: + return False + + if ReIsValidBuildOption2.match(ToolOptionList[2]) is None: + return False + + if ToolOptionList[3] == "*" and ToolOptionList[4] not in ['FAMILY', 'DLL', 'DPATH']: + return False + + return True + +## IsValidToken +# +# Check if pattern string matches total token +# +# @param ReString: regular string +# @param Token: Token to be matched +# +def IsValidToken(ReString, Token): + Match = re.compile(ReString).match(Token) + return Match and Match.start() == 0 and Match.end() == len(Token) + +## IsValidPath +# +# Check if path exist +# +# @param Path: Absolute path or relative path to be checked +# @param Root: Root path +# +def IsValidPath(Path, Root): + Path = Path.strip() + OrigPath = Path.replace('\\', '/') + + Path = os.path.normpath(Path).replace('\\', '/') + Root = os.path.normpath(Root).replace('\\', '/') + FullPath = mws.join(Root, Path) + + if not os.path.exists(FullPath): + return False + + # + # If Path is absolute path. + # It should be in Root. + # + if os.path.isabs(Path): + if not Path.startswith(Root): + return False + return True + + # + # Check illegal character + # + for Rel in ['/', './', '../']: + if OrigPath.startswith(Rel): + return False + for Rel in ['//', '/./', '/../']: + if Rel in OrigPath: + return False + for Rel in ['/.', '/..', '/']: + if OrigPath.endswith(Rel): + return False + + Path = Path.rstrip('/') + + # + # Check relative path + # + for Word in Path.split('/'): + if not IsValidWord(Word): + return False + + return True + +## IsValidInstallPath +# +# Check if an install path valid or not. +# +# Absolute path or path starts with '.' or path contains '..' are invalid. +# +# @param Path: path to be checked +# +def IsValidInstallPath(Path): + if platform.platform().find("Windows") >= 0: + if os.path.isabs(Path): + return False + else: + if Path[1:2] == ':': + return False + if os.path.isabs(Path): + return False + if Path.startswith('.'): + return False + + if Path.find('..') != -1: + return False + + return True + + +## IsValidCFormatGuid +# +# Check if GUID format has the from of {8,4,4,{2,2,2,2,2,2,2,2}} +# +# @param Guid: Guid to be checked +# +def IsValidCFormatGuid(Guid): + # + # Valid: { 0xf0b11735, 0x87a0, 0x4193, {0xb2, 0x66, 0x53, 0x8c, 0x38, + # 0xaf, 0x48, 0xce }} + # Invalid: { 0xf0b11735, 0x87a0, 0x4193, {0xb2, 0x66, 0x53, 0x8c, 0x38, + # 0xaf, 0x48, 0xce }} 0x123 + # Invalid: { 0xf0b1 1735, 0x87a0, 0x4193, {0xb2, 0x66, 0x53, 0x8c, 0x38, + # 0xaf, 0x48, 0xce }} + # + List = ['{', 10, ',', 6, ',', 6, ',{', 4, ',', 4, ',', 4, + ',', 4, ',', 4, ',', 4, ',', 4, ',', 4, '}}'] + Index = 0 + Value = '' + SepValue = '' + for Char in Guid: + if Char not in '{},\t ': + Value += Char + continue + if Value: + try: + # + # Index may out of bound + # + if not SepValue or SepValue != List[Index]: + return False + Index += 1 + SepValue = '' + + if not Value.startswith('0x') and not Value.startswith('0X'): + return False + + # + # Index may out of bound + # + if not isinstance(List[Index], type(1)) or \ + len(Value) > List[Index] or len(Value) < 3: + return False + + # + # Check if string can be converted to integer + # Throw exception if not + # + int(Value, 16) + except BaseException: + # + # Exception caught means invalid format + # + return False + Value = '' + Index += 1 + if Char in '{},': + SepValue += Char + + return SepValue == '}}' and Value == '' + +## IsValidPcdType +# +# Check whether the PCD type is valid +# +# @param PcdTypeString: The PcdType string need to be checked. +# +def IsValidPcdType(PcdTypeString): + if PcdTypeString.upper() in PCD_USAGE_TYPE_LIST_OF_MODULE: + return True + else: + return False + +## IsValidWord +# +# Check whether the word is valid. +# ::= (a-zA-Z0-9_)(a-zA-Z0-9_-){0,} Alphanumeric characters with +# optional +# dash "-" and/or underscore "_" characters. No whitespace +# characters are permitted. +# +# @param Word: The word string need to be checked. +# +def IsValidWord(Word): + if not Word: + return False + # + # The first char should be alpha, _ or Digit. + # + if not Word[0].isalnum() and \ + not Word[0] == '_' and \ + not Word[0].isdigit(): + return False + + LastChar = '' + for Char in Word[1:]: + if (not Char.isalpha()) and \ + (not Char.isdigit()) and \ + Char != '-' and \ + Char != '_' and \ + Char != '.': + return False + if Char == '.' and LastChar == '.': + return False + LastChar = Char + + return True + + +## IsValidSimpleWord +# +# Check whether the SimpleWord is valid. +# ::= (a-zA-Z0-9)(a-zA-Z0-9_-){0,} +# A word that cannot contain a period character. +# +# @param Word: The word string need to be checked. +# +def IsValidSimpleWord(Word): + ReIsValidSimpleWord = \ + re.compile(r"^[0-9A-Za-z][0-9A-Za-z\-_]*$", re.DOTALL) + Word = Word.strip() + if not Word: + return False + + if not ReIsValidSimpleWord.match(Word): + return False + + return True + +## IsValidDecVersion +# +# Check whether the decimal version is valid. +# ::= (0-9){1,} ["." (0-9){1,}] +# +# @param Word: The word string need to be checked. +# +def IsValidDecVersion(Word): + if Word.find('.') > -1: + ReIsValidDecVersion = re.compile(r"[0-9]+\.?[0-9]+$") + else: + ReIsValidDecVersion = re.compile(r"[0-9]+$") + if ReIsValidDecVersion.match(Word) is None: + return False + return True + +## IsValidHexVersion +# +# Check whether the hex version is valid. +# ::= "0x" +# ::= {4} +# ::= {4} +# +# @param Word: The word string need to be checked. +# +def IsValidHexVersion(Word): + ReIsValidHexVersion = re.compile(r"[0][xX][0-9A-Fa-f]{8}$", re.DOTALL) + if ReIsValidHexVersion.match(Word) is None: + return False + + return True + +## IsValidBuildNumber +# +# Check whether the BUILD_NUMBER is valid. +# ["BUILD_NUMBER" "=" {1,4} ] +# +# @param Word: The BUILD_NUMBER string need to be checked. +# +def IsValidBuildNumber(Word): + ReIsValieBuildNumber = re.compile(r"[0-9]{1,4}$", re.DOTALL) + if ReIsValieBuildNumber.match(Word) is None: + return False + + return True + +## IsValidDepex +# +# Check whether the Depex is valid. +# +# @param Word: The Depex string need to be checked. +# +def IsValidDepex(Word): + Index = Word.upper().find("PUSH") + if Index > -1: + return IsValidCFormatGuid(Word[Index+4:].strip()) + + ReIsValidCName = re.compile(r"^[A-Za-z_][0-9A-Za-z_\s\.]*$", re.DOTALL) + if ReIsValidCName.match(Word) is None: + return False + + return True + +## IsValidNormalizedString +# +# Check +# ::= [{} {}]{1,} +# ::= 0x20 +# +# @param String: string to be checked +# +def IsValidNormalizedString(String): + if String == '': + return True + + for Char in String: + if Char == '\t': + return False + + StringList = GetSplitValueList(String, TAB_SPACE_SPLIT) + + for Item in StringList: + if not Item: + continue + if not IsValidWord(Item): + return False + + return True + +## IsValidIdString +# +# Check whether the IdString is valid. +# +# @param IdString: The IdString need to be checked. +# +def IsValidIdString(String): + if IsValidSimpleWord(String.strip()): + return True + + if String.strip().startswith('"') and \ + String.strip().endswith('"'): + String = String[1:-1] + if String.strip() == "": + return True + if IsValidNormalizedString(String): + return True + + return False + +## IsValidVersionString +# +# Check whether the VersionString is valid. +# ::= [ []{0,} []{0,} ] {0,} +# ::= {} {} +# ::= 0x09 +# ::= 0x20 +# ::= (0x21 - 0x7E) +# +# @param VersionString: The VersionString need to be checked. +# +def IsValidVersionString(VersionString): + VersionString = VersionString.strip() + for Char in VersionString: + if not (Char >= 0x21 and Char <= 0x7E): + return False + + return True + +## IsValidPcdValue +# +# Check whether the PcdValue is valid. +# +# @param VersionString: The PcdValue need to be checked. +# +def IsValidPcdValue(PcdValue): + for Char in PcdValue: + if Char == '\n' or Char == '\t' or Char == '\f': + return False + + # + # + # + if IsValidFeatureFlagExp(PcdValue, True)[0]: + return True + + # + # ::= {} {} + # ::= {(0-9)} {(1-9)(0-9){1,}} + # ::= "0x" {1,} + # ::= (a-fA-F0-9) + # + if IsValidHex(PcdValue): + return True + + ReIsValidIntegerSingle = re.compile(r"^\s*[0-9]\s*$", re.DOTALL) + if ReIsValidIntegerSingle.match(PcdValue) is not None: + return True + + ReIsValidIntegerMulti = re.compile(r"^\s*[1-9][0-9]+\s*$", re.DOTALL) + if ReIsValidIntegerMulti.match(PcdValue) is not None: + return True + + # + # ::= {} {} {"$(" ")"} + # ::= {} {} + # + ReIsValidStringType = re.compile(r"^\s*[\"L].*[\"]\s*$") + if ReIsValidStringType.match(PcdValue): + IsTrue = False + if PcdValue.strip().startswith('L\"'): + StringValue = PcdValue.strip().lstrip('L\"').rstrip('\"') + if IsValidBareCString(StringValue): + IsTrue = True + elif PcdValue.strip().startswith('\"'): + StringValue = PcdValue.strip().lstrip('\"').rstrip('\"') + if IsValidBareCString(StringValue): + IsTrue = True + if IsTrue: + return IsTrue + + # + # ::= {} {} {} + # ::= "{" [] {0,} "}" + # ::= ["," ]{0,} + # ::= (a-fA-F0-9) + # ::= "0x" {1,2} + # + if IsValidCFormatGuid(PcdValue): + return True + + ReIsValidByteHex = re.compile(r"^\s*0x[0-9a-fA-F]{1,2}\s*$", re.DOTALL) + if PcdValue.strip().startswith('{') and PcdValue.strip().endswith('}') : + StringValue = PcdValue.strip().lstrip('{').rstrip('}') + ValueList = StringValue.split(',') + AllValidFlag = True + for ValueItem in ValueList: + if not ReIsValidByteHex.match(ValueItem.strip()): + AllValidFlag = False + + if AllValidFlag: + return True + + # + # NList + # + AllValidFlag = True + ValueList = PcdValue.split(',') + for ValueItem in ValueList: + if not ReIsValidByteHex.match(ValueItem.strip()): + AllValidFlag = False + + if AllValidFlag: + return True + + return False + +## IsValidCVariableName +# +# Check whether the PcdValue is valid. +# +# @param VersionString: The PcdValue need to be checked. +# +def IsValidCVariableName(CName): + ReIsValidCName = re.compile(r"^[A-Za-z_][0-9A-Za-z_]*$", re.DOTALL) + if ReIsValidCName.match(CName) is None: + return False + + return True + +## IsValidIdentifier +# +# ::= {0,} +# ::= (a-zA-Z0-9_) +# ::= (a-zA-Z_) +# +# @param Ident: identifier to be checked +# +def IsValidIdentifier(Ident): + ReIdent = re.compile(r"^[A-Za-z_][0-9A-Za-z_]*$", re.DOTALL) + if ReIdent.match(Ident) is None: + return False + + return True + +## IsValidDecVersionVal +# +# {(0-9){1,} "." (0-99)} +# +# @param Ver: version to be checked +# +def IsValidDecVersionVal(Ver): + ReVersion = re.compile(r"[0-9]+(\.[0-9]{1,2})$") + + if ReVersion.match(Ver) is None: + return False + + return True + + +## IsValidLibName +# +# (A-Z)(a-zA-Z0-9){0,} and could not be "NULL" +# +def IsValidLibName(LibName): + if LibName == 'NULL': + return False + ReLibName = re.compile("^[A-Z]+[a-zA-Z0-9]*$") + if not ReLibName.match(LibName): + return False + + return True + +# IsValidUserId +# +# ::= (a-zA-Z)(a-zA-Z0-9_.){0,} +# Words that contain period "." must be encapsulated in double quotation marks. +# +def IsValidUserId(UserId): + UserId = UserId.strip() + Quoted = False + if UserId.startswith('"') and UserId.endswith('"'): + Quoted = True + UserId = UserId[1:-1] + if not UserId or not UserId[0].isalpha(): + return False + for Char in UserId[1:]: + if not Char.isalnum() and not Char in '_.': + return False + if Char == '.' and not Quoted: + return False + return True + +# +# Check if a UTF16-LE file has a BOM header +# +def CheckUTF16FileHeader(File): + FileIn = open(File, 'rb').read(2) + if FileIn != b'\xff\xfe': + return False + + return True diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/Parsing.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/Parsing.py new file mode 100755 index 00000000..802f81e6 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/Parsing.py @@ -0,0 +1,1015 @@ +## @file +# This file is used to define common parsing related functions used in parsing +# INF/DEC/DSC process +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +Parsing +''' +from __future__ import absolute_import + +## +# Import Modules +# +import os.path +import re + +from Library.StringUtils import RaiseParserError +from Library.StringUtils import GetSplitValueList +from Library.StringUtils import CheckFileType +from Library.StringUtils import CheckFileExist +from Library.StringUtils import CleanString +from Library.StringUtils import NormPath + +from Logger.ToolError import FILE_NOT_FOUND +from Logger.ToolError import FatalError +from Logger.ToolError import FORMAT_INVALID + +from Library import DataType + +from Library.Misc import GuidStructureStringToGuidString +from Library.Misc import CheckGuidRegFormat +from Logger import StringTable as ST +import Logger.Log as Logger + +from Parser.DecParser import Dec +from . import GlobalData + +gPKG_INFO_DICT = {} + +## GetBuildOption +# +# Parse a string with format "[:]=Flag" +# Return (Family, ToolFlag, Flag) +# +# @param String: String with BuildOption statement +# @param File: The file which defines build option, used in error report +# +def GetBuildOption(String, File, LineNo= -1): + (Family, ToolChain, Flag) = ('', '', '') + if String.find(DataType.TAB_EQUAL_SPLIT) < 0: + RaiseParserError(String, 'BuildOptions', File, \ + '[:]=Flag', LineNo) + else: + List = GetSplitValueList(String, DataType.TAB_EQUAL_SPLIT, MaxSplit=1) + if List[0].find(':') > -1: + Family = List[0][ : List[0].find(':')].strip() + ToolChain = List[0][List[0].find(':') + 1 : ].strip() + else: + ToolChain = List[0].strip() + Flag = List[1].strip() + return (Family, ToolChain, Flag) + +## Get Library Class +# +# Get Library of Dsc as | +# +# @param Item: String as | +# @param ContainerFile: The file which describes the library class, used for +# error report +# +def GetLibraryClass(Item, ContainerFile, WorkspaceDir, LineNo= -1): + List = GetSplitValueList(Item[0]) + SupMod = DataType.SUP_MODULE_LIST_STRING + if len(List) != 2: + RaiseParserError(Item[0], 'LibraryClasses', ContainerFile, \ + '|') + else: + CheckFileType(List[1], '.Inf', ContainerFile, \ + 'library class instance', Item[0], LineNo) + CheckFileExist(WorkspaceDir, List[1], ContainerFile, \ + 'LibraryClasses', Item[0], LineNo) + if Item[1] != '': + SupMod = Item[1] + + return (List[0], List[1], SupMod) + +## Get Library Class +# +# Get Library of Dsc as [|] +# [|.] +# +# @param Item: String as | +# @param ContainerFile: The file which describes the library class, used for +# error report +# +def GetLibraryClassOfInf(Item, ContainerFile, WorkspaceDir, LineNo= -1): + ItemList = GetSplitValueList((Item[0] + DataType.TAB_VALUE_SPLIT * 2)) + SupMod = DataType.SUP_MODULE_LIST_STRING + + if len(ItemList) > 5: + RaiseParserError\ + (Item[0], 'LibraryClasses', ContainerFile, \ + '[|]\ + [|.]') + else: + CheckFileType(ItemList[1], '.Inf', ContainerFile, 'LibraryClasses', \ + Item[0], LineNo) + CheckFileExist(WorkspaceDir, ItemList[1], ContainerFile, \ + 'LibraryClasses', Item[0], LineNo) + if ItemList[2] != '': + CheckPcdTokenInfo(ItemList[2], 'LibraryClasses', \ + ContainerFile, LineNo) + if Item[1] != '': + SupMod = Item[1] + + return (ItemList[0], ItemList[1], ItemList[2], SupMod) + +## CheckPcdTokenInfo +# +# Check if PcdTokenInfo is following . +# +# @param TokenInfoString: String to be checked +# @param Section: Used for error report +# @param File: Used for error report +# +def CheckPcdTokenInfo(TokenInfoString, Section, File, LineNo= -1): + Format = '.' + if TokenInfoString != '' and TokenInfoString is not None: + TokenInfoList = GetSplitValueList(TokenInfoString, DataType.TAB_SPLIT) + if len(TokenInfoList) == 2: + return True + + RaiseParserError(TokenInfoString, Section, File, Format, LineNo) + +## Get Pcd +# +# Get Pcd of Dsc as .| +# [||] +# +# @param Item: String as .| +# [||] +# @param ContainerFile: The file which describes the pcd, used for error +# report + +# +def GetPcd(Item, Type, ContainerFile, LineNo= -1): + TokenGuid, TokenName, Value, MaximumDatumSize, Token = '', '', '', '', '' + List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT * 2) + + if len(List) < 4 or len(List) > 6: + RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \ + '.|\ + [||]', LineNo) + else: + Value = List[1] + MaximumDatumSize = List[2] + Token = List[3] + + if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo): + (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT) + + return (TokenName, TokenGuid, Value, MaximumDatumSize, Token, Type) + +## Get FeatureFlagPcd +# +# Get FeatureFlagPcd of Dsc as .|TRUE/FALSE +# +# @param Item: String as +# .|TRUE/FALSE +# @param ContainerFile: The file which describes the pcd, used for error +# report +# +def GetFeatureFlagPcd(Item, Type, ContainerFile, LineNo= -1): + TokenGuid, TokenName, Value = '', '', '' + List = GetSplitValueList(Item) + if len(List) != 2: + RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \ + '.|TRUE/FALSE', \ + LineNo) + else: + Value = List[1] + if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo): + (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT) + + return (TokenName, TokenGuid, Value, Type) + +## Get DynamicDefaultPcd +# +# Get DynamicDefaultPcd of Dsc as . +# |[|[|]] +# +# @param Item: String as .| +# TRUE/FALSE +# @param ContainerFile: The file which describes the pcd, used for error +# report +# +def GetDynamicDefaultPcd(Item, Type, ContainerFile, LineNo= -1): + TokenGuid, TokenName, Value, DatumTyp, MaxDatumSize = '', '', '', '', '' + List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT * 2) + if len(List) < 4 or len(List) > 8: + RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \ + '.|\ + [|[|]]', LineNo) + else: + Value = List[1] + DatumTyp = List[2] + MaxDatumSize = List[3] + if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo): + (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT) + + return (TokenName, TokenGuid, Value, DatumTyp, MaxDatumSize, Type) + +## Get DynamicHiiPcd +# +# Get DynamicHiiPcd of Dsc as .|| +# |[|[|]] +# +# @param Item: String as .| +# TRUE/FALSE +# @param ContainerFile: The file which describes the pcd, used for error +# report +# +def GetDynamicHiiPcd(Item, Type, ContainerFile, LineNo= -1): + TokenGuid, TokenName, List1, List2, List3, List4, List5 = \ + '', '', '', '', '', '', '' + List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT * 2) + if len(List) < 6 or len(List) > 8: + RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \ + '.||\ + |[|\ + [|]]', LineNo) + else: + List1, List2, List3, List4, List5 = \ + List[1], List[2], List[3], List[4], List[5] + if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo): + (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT) + + return (TokenName, TokenGuid, List1, List2, List3, List4, List5, Type) + +## Get DynamicVpdPcd +# +# Get DynamicVpdPcd of Dsc as .| +# [|] +# +# @param Item: String as . +# |TRUE/FALSE +# @param ContainerFile: The file which describes the pcd, used for error +# report +# +def GetDynamicVpdPcd(Item, Type, ContainerFile, LineNo= -1): + TokenGuid, TokenName, List1, List2 = '', '', '', '' + List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT) + if len(List) < 3 or len(List) > 4: + RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \ + '.|\ + [|]', LineNo) + else: + List1, List2 = List[1], List[2] + if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo): + (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT) + + return (TokenName, TokenGuid, List1, List2, Type) + +## GetComponent +# +# Parse block of the components defined in dsc file +# Set KeyValues as [ ['component name', [lib1, lib2, lib3], +# [bo1, bo2, bo3], [pcd1, pcd2, pcd3]], ...] +# +# @param Lines: The content to be parsed +# @param KeyValues: To store data after parsing +# +def GetComponent(Lines, KeyValues): + (FindBlock, FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ + FindPcdsPatchableInModule, FindPcdsFixedAtBuild, FindPcdsDynamic, \ + FindPcdsDynamicEx) = (False, False, False, False, False, False, False, \ + False) + ListItem = None + LibraryClassItem = [] + BuildOption = [] + Pcd = [] + + for Line in Lines: + Line = Line[0] + # + # Ignore !include statement + # + if Line.upper().find(DataType.TAB_INCLUDE.upper() + ' ') > -1 or \ + Line.upper().find(DataType.TAB_DEFINE + ' ') > -1: + continue + + if FindBlock == False: + ListItem = Line + # + # find '{' at line tail + # + if Line.endswith('{'): + FindBlock = True + ListItem = CleanString(Line.rsplit('{', 1)[0], \ + DataType.TAB_COMMENT_SPLIT) + + # + # Parse a block content + # + if FindBlock: + if Line.find('') != -1: + (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ + FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \ + FindPcdsDynamic, FindPcdsDynamicEx) = \ + (True, False, False, False, False, False, False) + continue + if Line.find('') != -1: + (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ + FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \ + FindPcdsDynamic, FindPcdsDynamicEx) = \ + (False, True, False, False, False, False, False) + continue + if Line.find('') != -1: + (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ + FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \ + FindPcdsDynamic, FindPcdsDynamicEx) = \ + (False, False, True, False, False, False, False) + continue + if Line.find('') != -1: + (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ + FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \ + FindPcdsDynamic, FindPcdsDynamicEx) = \ + (False, False, False, True, False, False, False) + continue + if Line.find('') != -1: + (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ + FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \ + FindPcdsDynamic, FindPcdsDynamicEx) = \ + (False, False, False, False, True, False, False) + continue + if Line.find('') != -1: + (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ + FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \ + FindPcdsDynamic, FindPcdsDynamicEx) = \ + (False, False, False, False, False, True, False) + continue + if Line.find('') != -1: + (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ + FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \ + FindPcdsDynamic, FindPcdsDynamicEx) = \ + (False, False, False, False, False, False, True) + continue + if Line.endswith('}'): + # + # find '}' at line tail + # + KeyValues.append([ListItem, LibraryClassItem, \ + BuildOption, Pcd]) + (FindBlock, FindLibraryClass, FindBuildOption, \ + FindPcdsFeatureFlag, FindPcdsPatchableInModule, \ + FindPcdsFixedAtBuild, FindPcdsDynamic, FindPcdsDynamicEx) = \ + (False, False, False, False, False, False, False, False) + LibraryClassItem, BuildOption, Pcd = [], [], [] + continue + + if FindBlock: + if FindLibraryClass: + LibraryClassItem.append(Line) + elif FindBuildOption: + BuildOption.append(Line) + elif FindPcdsFeatureFlag: + Pcd.append((DataType.TAB_PCDS_FEATURE_FLAG_NULL, Line)) + elif FindPcdsPatchableInModule: + Pcd.append((DataType.TAB_PCDS_PATCHABLE_IN_MODULE_NULL, Line)) + elif FindPcdsFixedAtBuild: + Pcd.append((DataType.TAB_PCDS_FIXED_AT_BUILD_NULL, Line)) + elif FindPcdsDynamic: + Pcd.append((DataType.TAB_PCDS_DYNAMIC_DEFAULT_NULL, Line)) + elif FindPcdsDynamicEx: + Pcd.append((DataType.TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL, Line)) + else: + KeyValues.append([ListItem, [], [], []]) + + return True + +## GetExec +# +# Parse a string with format "InfFilename [EXEC = ExecFilename]" +# Return (InfFilename, ExecFilename) +# +# @param String: String with EXEC statement +# +def GetExec(String): + InfFilename = '' + ExecFilename = '' + if String.find('EXEC') > -1: + InfFilename = String[ : String.find('EXEC')].strip() + ExecFilename = String[String.find('EXEC') + len('EXEC') : ].strip() + else: + InfFilename = String.strip() + + return (InfFilename, ExecFilename) + +## GetComponents +# +# Parse block of the components defined in dsc file +# Set KeyValues as [ ['component name', [lib1, lib2, lib3], [bo1, bo2, bo3], +# [pcd1, pcd2, pcd3]], ...] +# +# @param Lines: The content to be parsed +# @param Key: Reserved +# @param KeyValues: To store data after parsing +# @param CommentCharacter: Comment char, used to ignore comment content +# +# @retval True Get component successfully +# +def GetComponents(Lines, KeyValues, CommentCharacter): + if Lines.find(DataType.TAB_SECTION_END) > -1: + Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1] + (FindBlock, FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ + FindPcdsPatchableInModule, FindPcdsFixedAtBuild, FindPcdsDynamic, \ + FindPcdsDynamicEx) = \ + (False, False, False, False, False, False, False, False) + ListItem = None + LibraryClassItem = [] + BuildOption = [] + Pcd = [] + + LineList = Lines.split('\n') + for Line in LineList: + Line = CleanString(Line, CommentCharacter) + if Line is None or Line == '': + continue + + if FindBlock == False: + ListItem = Line + # + # find '{' at line tail + # + if Line.endswith('{'): + FindBlock = True + ListItem = CleanString(Line.rsplit('{', 1)[0], CommentCharacter) + + # + # Parse a block content + # + if FindBlock: + if Line.find('') != -1: + (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ + FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \ + FindPcdsDynamic, FindPcdsDynamicEx) = \ + (True, False, False, False, False, False, False) + continue + if Line.find('') != -1: + (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ + FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \ + FindPcdsDynamic, FindPcdsDynamicEx) = \ + (False, True, False, False, False, False, False) + continue + if Line.find('') != -1: + (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ + FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \ + FindPcdsDynamic, FindPcdsDynamicEx) = \ + (False, False, True, False, False, False, False) + continue + if Line.find('') != -1: + (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ + FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \ + FindPcdsDynamic, FindPcdsDynamicEx) = \ + (False, False, False, True, False, False, False) + continue + if Line.find('') != -1: + (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ + FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \ + FindPcdsDynamic, FindPcdsDynamicEx) = \ + (False, False, False, False, True, False, False) + continue + if Line.find('') != -1: + (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ + FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \ + FindPcdsDynamic, FindPcdsDynamicEx) = \ + (False, False, False, False, False, True, False) + continue + if Line.find('') != -1: + (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \ + FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \ + FindPcdsDynamic, FindPcdsDynamicEx) = \ + (False, False, False, False, False, False, True) + continue + if Line.endswith('}'): + # + # find '}' at line tail + # + KeyValues.append([ListItem, LibraryClassItem, BuildOption, \ + Pcd]) + (FindBlock, FindLibraryClass, FindBuildOption, \ + FindPcdsFeatureFlag, FindPcdsPatchableInModule, \ + FindPcdsFixedAtBuild, FindPcdsDynamic, FindPcdsDynamicEx) = \ + (False, False, False, False, False, False, False, False) + LibraryClassItem, BuildOption, Pcd = [], [], [] + continue + + if FindBlock: + if FindLibraryClass: + LibraryClassItem.append(Line) + elif FindBuildOption: + BuildOption.append(Line) + elif FindPcdsFeatureFlag: + Pcd.append((DataType.TAB_PCDS_FEATURE_FLAG, Line)) + elif FindPcdsPatchableInModule: + Pcd.append((DataType.TAB_PCDS_PATCHABLE_IN_MODULE, Line)) + elif FindPcdsFixedAtBuild: + Pcd.append((DataType.TAB_PCDS_FIXED_AT_BUILD, Line)) + elif FindPcdsDynamic: + Pcd.append((DataType.TAB_PCDS_DYNAMIC, Line)) + elif FindPcdsDynamicEx: + Pcd.append((DataType.TAB_PCDS_DYNAMIC_EX, Line)) + else: + KeyValues.append([ListItem, [], [], []]) + + return True + +## Get Source +# +# Get Source of Inf as [|[|[| +# [|]]]] +# +# @param Item: String as [|[|[| +# [|]]]] +# @param ContainerFile: The file which describes the library class, used +# for error report +# +def GetSource(Item, ContainerFile, FileRelativePath, LineNo= -1): + ItemNew = Item + DataType.TAB_VALUE_SPLIT * 4 + List = GetSplitValueList(ItemNew) + if len(List) < 5 or len(List) > 9: + RaiseParserError(Item, 'Sources', ContainerFile, \ + '[|[|[|\ + [|]]]]', LineNo) + List[0] = NormPath(List[0]) + CheckFileExist(FileRelativePath, List[0], ContainerFile, 'Sources', \ + Item, LineNo) + if List[4] != '': + CheckPcdTokenInfo(List[4], 'Sources', ContainerFile, LineNo) + + return (List[0], List[1], List[2], List[3], List[4]) + +## Get Binary +# +# Get Binary of Inf as [|[|[| +# [|]]]] +# +# @param Item: String as [|[| +# [|[|]]]] +# @param ContainerFile: The file which describes the library class, +# used for error report +# +def GetBinary(Item, ContainerFile, LineNo= -1): + ItemNew = Item + DataType.TAB_VALUE_SPLIT + List = GetSplitValueList(ItemNew) + if len(List) < 3 or len(List) > 5: + RaiseParserError(Item, 'Binaries', ContainerFile, \ + "|[|\ + [|.]]", LineNo) + + if len(List) >= 4: + if List[3] != '': + CheckPcdTokenInfo(List[3], 'Binaries', ContainerFile, LineNo) + return (List[0], List[1], List[2], List[3]) + elif len(List) == 3: + return (List[0], List[1], List[2], '') + +## Get Guids/Protocols/Ppis +# +# Get Guids/Protocols/Ppis of Inf as [|] +# +# @param Item: String as [|] +# @param Type: Type of parsing string +# @param ContainerFile: The file which describes the library class, +# used for error report +# +def GetGuidsProtocolsPpisOfInf(Item): + ItemNew = Item + DataType.TAB_VALUE_SPLIT + List = GetSplitValueList(ItemNew) + return (List[0], List[1]) + +## Get Guids/Protocols/Ppis +# +# Get Guids/Protocols/Ppis of Dec as = +# +# @param Item: String as = +# @param Type: Type of parsing string +# @param ContainerFile: The file which describes the library class, +# used for error report +# +def GetGuidsProtocolsPpisOfDec(Item, Type, ContainerFile, LineNo= -1): + List = GetSplitValueList(Item, DataType.TAB_EQUAL_SPLIT) + if len(List) != 2: + RaiseParserError(Item, Type, ContainerFile, '=', \ + LineNo) + # + #convert C-Format Guid to Register Format + # + if List[1][0] == '{' and List[1][-1] == '}': + RegisterFormatGuid = GuidStructureStringToGuidString(List[1]) + if RegisterFormatGuid == '': + RaiseParserError(Item, Type, ContainerFile, \ + 'CFormat or RegisterFormat', LineNo) + else: + if CheckGuidRegFormat(List[1]): + RegisterFormatGuid = List[1] + else: + RaiseParserError(Item, Type, ContainerFile, \ + 'CFormat or RegisterFormat', LineNo) + + return (List[0], RegisterFormatGuid) + +## GetPackage +# +# Get Package of Inf as [|] +# +# @param Item: String as [|] +# @param Type: Type of parsing string +# @param ContainerFile: The file which describes the library class, +# used for error report +# +def GetPackage(Item, ContainerFile, FileRelativePath, LineNo= -1): + ItemNew = Item + DataType.TAB_VALUE_SPLIT + List = GetSplitValueList(ItemNew) + CheckFileType(List[0], '.Dec', ContainerFile, 'package', List[0], LineNo) + CheckFileExist(FileRelativePath, List[0], ContainerFile, 'Packages', \ + List[0], LineNo) + if List[1] != '': + CheckPcdTokenInfo(List[1], 'Packages', ContainerFile, LineNo) + + return (List[0], List[1]) + +## Get Pcd Values of Inf +# +# Get Pcd of Inf as .[|] +# +# @param Item: The string describes pcd +# @param Type: The type of Pcd +# @param File: The file which describes the pcd, used for error report +# +def GetPcdOfInf(Item, Type, File, LineNo): + Format = '.[|]' + TokenGuid, TokenName, Value, InfType = '', '', '', '' + + if Type == DataType.TAB_PCDS_FIXED_AT_BUILD: + InfType = DataType.TAB_INF_FIXED_PCD + elif Type == DataType.TAB_PCDS_PATCHABLE_IN_MODULE: + InfType = DataType.TAB_INF_PATCH_PCD + elif Type == DataType.TAB_PCDS_FEATURE_FLAG: + InfType = DataType.TAB_INF_FEATURE_PCD + elif Type == DataType.TAB_PCDS_DYNAMIC_EX: + InfType = DataType.TAB_INF_PCD_EX + elif Type == DataType.TAB_PCDS_DYNAMIC: + InfType = DataType.TAB_INF_PCD + List = GetSplitValueList(Item, DataType.TAB_VALUE_SPLIT, 1) + TokenInfo = GetSplitValueList(List[0], DataType.TAB_SPLIT) + if len(TokenInfo) != 2: + RaiseParserError(Item, InfType, File, Format, LineNo) + else: + TokenGuid = TokenInfo[0] + TokenName = TokenInfo[1] + + if len(List) > 1: + Value = List[1] + else: + Value = None + return (TokenGuid, TokenName, Value, InfType) + + +## Get Pcd Values of Dec +# +# Get Pcd of Dec as .||| +# @param Item: Pcd item +# @param Type: Pcd type +# @param File: Dec file +# @param LineNo: Line number +# +def GetPcdOfDec(Item, Type, File, LineNo= -1): + Format = '.|||' + TokenGuid, TokenName, Value, DatumType, Token = '', '', '', '', '' + List = GetSplitValueList(Item) + if len(List) != 4: + RaiseParserError(Item, 'Pcds' + Type, File, Format, LineNo) + else: + Value = List[1] + DatumType = List[2] + Token = List[3] + TokenInfo = GetSplitValueList(List[0], DataType.TAB_SPLIT) + if len(TokenInfo) != 2: + RaiseParserError(Item, 'Pcds' + Type, File, Format, LineNo) + else: + TokenGuid = TokenInfo[0] + TokenName = TokenInfo[1] + + return (TokenGuid, TokenName, Value, DatumType, Token, Type) + +## Parse DEFINE statement +# +# Get DEFINE macros +# +# @param LineValue: A DEFINE line value +# @param StartLine: A DEFINE start line +# @param Table: A table +# @param FileID: File ID +# @param Filename: File name +# @param SectionName: DEFINE section name +# @param SectionModel: DEFINE section model +# @param Arch: DEFINE arch +# +def ParseDefine(LineValue, StartLine, Table, FileID, SectionName, \ + SectionModel, Arch): + Logger.Debug(Logger.DEBUG_2, ST.MSG_DEFINE_STATEMENT_FOUND % (LineValue, \ + SectionName)) + Define = \ + GetSplitValueList(CleanString\ + (LineValue[LineValue.upper().\ + find(DataType.TAB_DEFINE.upper() + ' ') + \ + len(DataType.TAB_DEFINE + ' ') : ]), \ + DataType.TAB_EQUAL_SPLIT, 1) + Table.Insert(DataType.MODEL_META_DATA_DEFINE, Define[0], Define[1], '', \ + '', '', Arch, SectionModel, FileID, StartLine, -1, \ + StartLine, -1, 0) + +## InsertSectionItems +# +# Insert item data of a section to a dict +# +# @param Model: A model +# @param CurrentSection: Current section +# @param SectionItemList: Section item list +# @param ArchList: Arch list +# @param ThirdList: Third list +# @param RecordSet: Record set +# +def InsertSectionItems(Model, SectionItemList, ArchList, \ + ThirdList, RecordSet): + # + # Insert each item data of a section + # + for Index in range(0, len(ArchList)): + Arch = ArchList[Index] + Third = ThirdList[Index] + if Arch == '': + Arch = DataType.TAB_ARCH_COMMON + + Records = RecordSet[Model] + for SectionItem in SectionItemList: + LineValue, StartLine, Comment = SectionItem[0], \ + SectionItem[1], SectionItem[2] + + Logger.Debug(4, ST.MSG_PARSING % LineValue) + # + # And then parse DEFINE statement + # + if LineValue.upper().find(DataType.TAB_DEFINE.upper() + ' ') > -1: + continue + # + # At last parse other sections + # + IdNum = -1 + Records.append([LineValue, Arch, StartLine, IdNum, Third, Comment]) + + if RecordSet != {}: + RecordSet[Model] = Records + +## GenMetaDatSectionItem +# +# @param Key: A key +# @param Value: A value +# @param List: A list +# +def GenMetaDatSectionItem(Key, Value, List): + if Key not in List: + List[Key] = [Value] + else: + List[Key].append(Value) + +## GetPkgInfoFromDec +# +# get package name, guid, version info from dec files +# +# @param Path: File path +# +def GetPkgInfoFromDec(Path): + PkgName = None + PkgGuid = None + PkgVersion = None + + Path = Path.replace('\\', '/') + + if not os.path.exists(Path): + Logger.Error("\nUPT", FILE_NOT_FOUND, File=Path) + + if Path in gPKG_INFO_DICT: + return gPKG_INFO_DICT[Path] + + try: + DecParser = None + if Path not in GlobalData.gPackageDict: + DecParser = Dec(Path) + GlobalData.gPackageDict[Path] = DecParser + else: + DecParser = GlobalData.gPackageDict[Path] + + PkgName = DecParser.GetPackageName() + PkgGuid = DecParser.GetPackageGuid() + PkgVersion = DecParser.GetPackageVersion() + gPKG_INFO_DICT[Path] = (PkgName, PkgGuid, PkgVersion) + return PkgName, PkgGuid, PkgVersion + except FatalError: + return None, None, None + + +## GetWorkspacePackage +# +# Get a list of workspace package information. +# +def GetWorkspacePackage(): + DecFileList = [] + WorkspaceDir = GlobalData.gWORKSPACE + PackageDir = GlobalData.gPACKAGE_PATH + for PkgRoot in [WorkspaceDir] + PackageDir: + for Root, Dirs, Files in os.walk(PkgRoot): + if 'CVS' in Dirs: + Dirs.remove('CVS') + if '.svn' in Dirs: + Dirs.remove('.svn') + for Dir in Dirs: + if Dir.startswith('.'): + Dirs.remove(Dir) + for FileSp in Files: + if FileSp.startswith('.'): + continue + Ext = os.path.splitext(FileSp)[1] + if Ext.lower() in ['.dec']: + DecFileList.append\ + (os.path.normpath(os.path.join(Root, FileSp))) + # + # abstract package guid, version info from DecFile List + # + PkgList = [] + for DecFile in DecFileList: + (PkgName, PkgGuid, PkgVersion) = GetPkgInfoFromDec(DecFile) + if PkgName and PkgGuid and PkgVersion: + PkgList.append((PkgName, PkgGuid, PkgVersion, DecFile)) + + return PkgList + +## GetWorkspaceModule +# +# Get a list of workspace modules. +# +def GetWorkspaceModule(): + InfFileList = [] + WorkspaceDir = GlobalData.gWORKSPACE + for Root, Dirs, Files in os.walk(WorkspaceDir): + if 'CVS' in Dirs: + Dirs.remove('CVS') + if '.svn' in Dirs: + Dirs.remove('.svn') + if 'Build' in Dirs: + Dirs.remove('Build') + for Dir in Dirs: + if Dir.startswith('.'): + Dirs.remove(Dir) + for FileSp in Files: + if FileSp.startswith('.'): + continue + Ext = os.path.splitext(FileSp)[1] + if Ext.lower() in ['.inf']: + InfFileList.append\ + (os.path.normpath(os.path.join(Root, FileSp))) + + return InfFileList + +## MacroParser used to parse macro definition +# +# @param Line: The content contain linestring and line number +# @param FileName: The meta-file file name +# @param SectionType: Section for the Line belong to +# @param FileLocalMacros: A list contain Macro defined in [Defines] section. +# +def MacroParser(Line, FileName, SectionType, FileLocalMacros): + MacroDefPattern = re.compile("^(DEFINE)[ \t]+") + LineContent = Line[0] + LineNo = Line[1] + Match = MacroDefPattern.match(LineContent) + if not Match: + # + # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method + # + return None, None + + TokenList = GetSplitValueList(LineContent[Match.end(1):], \ + DataType.TAB_EQUAL_SPLIT, 1) + # + # Syntax check + # + if not TokenList[0]: + Logger.Error('Parser', FORMAT_INVALID, ST.ERR_MACRONAME_NOGIVEN, + ExtraData=LineContent, File=FileName, Line=LineNo) + if len(TokenList) < 2: + Logger.Error('Parser', FORMAT_INVALID, ST.ERR_MACROVALUE_NOGIVEN, + ExtraData=LineContent, File=FileName, Line=LineNo) + + Name, Value = TokenList + + # + # DEFINE defined macros + # + if SectionType == DataType.MODEL_META_DATA_HEADER: + FileLocalMacros[Name] = Value + + ReIsValidMacroName = re.compile(r"^[A-Z][A-Z0-9_]*$", re.DOTALL) + if ReIsValidMacroName.match(Name) is None: + Logger.Error('Parser', + FORMAT_INVALID, + ST.ERR_MACRONAME_INVALID % (Name), + ExtraData=LineContent, + File=FileName, + Line=LineNo) + + # Validate MACRO Value + # + # ::= []{0,} + # "DEFINE" "=" [{} {}] + # ::= {} {} {} {} + # {} {} {} + # + # The definition of , , , , , + # , are subset of . + # + ReIsValidMacroValue = re.compile(r"^[\x20-\x7e]*$", re.DOTALL) + if ReIsValidMacroValue.match(Value) is None: + Logger.Error('Parser', + FORMAT_INVALID, + ST.ERR_MACROVALUE_INVALID % (Value), + ExtraData=LineContent, + File=FileName, + Line=LineNo) + + return Name, Value + +## GenSection +# +# generate section contents +# +# @param SectionName: indicate the name of the section, details refer to +# INF, DEC specs +# @param SectionDict: section statement dict, key is SectionAttrs(arch, +# moduletype or platform may exist as needed) list +# separated by space, +# value is statement +# +def GenSection(SectionName, SectionDict, SplitArch=True, NeedBlankLine=False): + Content = '' + for SectionAttrs in SectionDict: + StatementList = SectionDict[SectionAttrs] + if SectionAttrs and SectionName != 'Defines' and SectionAttrs.strip().upper() != DataType.TAB_ARCH_COMMON: + if SplitArch: + ArchList = GetSplitValueList(SectionAttrs, DataType.TAB_SPACE_SPLIT) + else: + if SectionName != 'UserExtensions': + ArchList = GetSplitValueList(SectionAttrs, DataType.TAB_COMMENT_SPLIT) + else: + ArchList = [SectionAttrs] + for Index in range(0, len(ArchList)): + ArchList[Index] = ConvertArchForInstall(ArchList[Index]) + Section = '[' + SectionName + '.' + (', ' + SectionName + '.').join(ArchList) + ']' + else: + Section = '[' + SectionName + ']' + Content += '\n' + Section + '\n' + if StatementList is not None: + for Statement in StatementList: + LineList = Statement.split('\n') + NewStatement = "" + for Line in LineList: + # ignore blank comment + if not Line.replace("#", '').strip() and SectionName not in ('Defines', 'Hob', 'Event', 'BootMode'): + continue + # add two space before non-comments line except the comments in Defines section + if Line.strip().startswith('#') and SectionName == 'Defines': + NewStatement += "%s\n" % Line + continue + NewStatement += " %s\n" % Line + if NeedBlankLine: + Content += NewStatement + '\n' + else: + Content += NewStatement + + if NeedBlankLine: + Content = Content[:-1] + if not Content.replace('\\n', '').strip(): + return '' + return Content + +## ConvertArchForInstall +# if Arch.upper() is in "IA32", "X64", "IPF", and "EBC", it must be upper case. "common" must be lower case. +# Anything else, the case must be preserved +# +# @param Arch: the arch string that need to be converted, it should be stripped before pass in +# @return: the arch string that get converted +# +def ConvertArchForInstall(Arch): + if Arch.upper() in [DataType.TAB_ARCH_IA32, DataType.TAB_ARCH_X64, + DataType.TAB_ARCH_IPF, DataType.TAB_ARCH_EBC]: + Arch = Arch.upper() + elif Arch.upper() == DataType.TAB_ARCH_COMMON: + Arch = Arch.lower() + + return Arch diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/StringUtils.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/StringUtils.py new file mode 100755 index 00000000..b3c742c2 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/StringUtils.py @@ -0,0 +1,982 @@ +## @file +# This file is used to define common string related functions used in parsing +# process +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +''' +StringUtils +''' +## +# Import Modules +# +import re +import os.path +import Logger.Log as Logger +import Library.DataType as DataType +from Logger.ToolError import FORMAT_INVALID +from Logger.ToolError import PARSER_ERROR +from Logger import StringTable as ST + +# +# Regular expression for matching macro used in DSC/DEC/INF file inclusion +# +gMACRO_PATTERN = re.compile("\$\(([_A-Z][_A-Z0-9]*)\)", re.UNICODE) + +## GetSplitValueList +# +# Get a value list from a string with multiple values split with SplitTag +# The default SplitTag is DataType.TAB_VALUE_SPLIT +# 'AAA|BBB|CCC' -> ['AAA', 'BBB', 'CCC'] +# +# @param String: The input string to be splitted +# @param SplitTag: The split key, default is DataType.TAB_VALUE_SPLIT +# @param MaxSplit: The max number of split values, default is -1 +# +# +def GetSplitValueList(String, SplitTag=DataType.TAB_VALUE_SPLIT, MaxSplit= -1): + return list(map(lambda l: l.strip(), String.split(SplitTag, MaxSplit))) + +## MergeArches +# +# Find a key's all arches in dict, add the new arch to the list +# If not exist any arch, set the arch directly +# +# @param Dict: The input value for Dict +# @param Key: The input value for Key +# @param Arch: The Arch to be added or merged +# +def MergeArches(Dict, Key, Arch): + if Key in Dict.keys(): + Dict[Key].append(Arch) + else: + Dict[Key] = Arch.split() + +## GenDefines +# +# Parse a string with format "DEFINE = " +# Generate a map Defines[VarName] = PATH +# Return False if invalid format +# +# @param String: String with DEFINE statement +# @param Arch: Supported Arch +# @param Defines: DEFINE statement to be parsed +# +def GenDefines(String, Arch, Defines): + if String.find(DataType.TAB_DEFINE + ' ') > -1: + List = String.replace(DataType.TAB_DEFINE + ' ', '').\ + split(DataType.TAB_EQUAL_SPLIT) + if len(List) == 2: + Defines[(CleanString(List[0]), Arch)] = CleanString(List[1]) + return 0 + else: + return -1 + return 1 + +## GetLibraryClassesWithModuleType +# +# Get Library Class definition when no module type defined +# +# @param Lines: The content to be parsed +# @param Key: Reserved +# @param KeyValues: To store data after parsing +# @param CommentCharacter: Comment char, used to ignore comment content +# +def GetLibraryClassesWithModuleType(Lines, Key, KeyValues, CommentCharacter): + NewKey = SplitModuleType(Key) + Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1] + LineList = Lines.splitlines() + for Line in LineList: + Line = CleanString(Line, CommentCharacter) + if Line != '' and Line[0] != CommentCharacter: + KeyValues.append([CleanString(Line, CommentCharacter), NewKey[1]]) + + return True + +## GetDynamics +# +# Get Dynamic Pcds +# +# @param Lines: The content to be parsed +# @param Key: Reserved +# @param KeyValues: To store data after parsing +# @param CommentCharacter: Comment char, used to ignore comment content +# +def GetDynamics(Lines, Key, KeyValues, CommentCharacter): + # + # Get SkuId Name List + # + SkuIdNameList = SplitModuleType(Key) + + Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1] + LineList = Lines.splitlines() + for Line in LineList: + Line = CleanString(Line, CommentCharacter) + if Line != '' and Line[0] != CommentCharacter: + KeyValues.append([CleanString(Line, CommentCharacter), SkuIdNameList[1]]) + + return True + +## SplitModuleType +# +# Split ModuleType out of section defien to get key +# [LibraryClass.Arch.ModuleType|ModuleType|ModuleType] -> [ +# 'LibraryClass.Arch', ['ModuleType', 'ModuleType', 'ModuleType'] ] +# +# @param Key: String to be parsed +# +def SplitModuleType(Key): + KeyList = Key.split(DataType.TAB_SPLIT) + # + # Fill in for arch + # + KeyList.append('') + # + # Fill in for moduletype + # + KeyList.append('') + ReturnValue = [] + KeyValue = KeyList[0] + if KeyList[1] != '': + KeyValue = KeyValue + DataType.TAB_SPLIT + KeyList[1] + ReturnValue.append(KeyValue) + ReturnValue.append(GetSplitValueList(KeyList[2])) + + return ReturnValue + +## Replace macro in string +# +# This method replace macros used in given string. The macros are given in a +# dictionary. +# +# @param String String to be processed +# @param MacroDefinitions The macro definitions in the form of dictionary +# @param SelfReplacement To decide whether replace un-defined macro to '' +# @param Line: The content contain line string and line number +# @param FileName: The meta-file file name +# +def ReplaceMacro(String, MacroDefinitions=None, SelfReplacement=False, Line=None, FileName=None, Flag=False): + LastString = String + if MacroDefinitions is None: + MacroDefinitions = {} + while MacroDefinitions: + QuotedStringList = [] + HaveQuotedMacroFlag = False + if not Flag: + MacroUsed = gMACRO_PATTERN.findall(String) + else: + ReQuotedString = re.compile('\"') + QuotedStringList = ReQuotedString.split(String) + if len(QuotedStringList) >= 3: + HaveQuotedMacroFlag = True + Count = 0 + MacroString = "" + for QuotedStringItem in QuotedStringList: + Count += 1 + if Count % 2 != 0: + MacroString += QuotedStringItem + + if Count == len(QuotedStringList) and Count % 2 == 0: + MacroString += QuotedStringItem + + MacroUsed = gMACRO_PATTERN.findall(MacroString) + # + # no macro found in String, stop replacing + # + if len(MacroUsed) == 0: + break + for Macro in MacroUsed: + if Macro not in MacroDefinitions: + if SelfReplacement: + String = String.replace("$(%s)" % Macro, '') + Logger.Debug(5, "Delete undefined MACROs in file %s line %d: %s!" % (FileName, Line[1], Line[0])) + continue + if not HaveQuotedMacroFlag: + String = String.replace("$(%s)" % Macro, MacroDefinitions[Macro]) + else: + Count = 0 + for QuotedStringItem in QuotedStringList: + Count += 1 + if Count % 2 != 0: + QuotedStringList[Count - 1] = QuotedStringList[Count - 1].replace("$(%s)" % Macro, + MacroDefinitions[Macro]) + elif Count == len(QuotedStringList) and Count % 2 == 0: + QuotedStringList[Count - 1] = QuotedStringList[Count - 1].replace("$(%s)" % Macro, + MacroDefinitions[Macro]) + + RetString = '' + if HaveQuotedMacroFlag: + Count = 0 + for QuotedStringItem in QuotedStringList: + Count += 1 + if Count != len(QuotedStringList): + RetString += QuotedStringList[Count - 1] + "\"" + else: + RetString += QuotedStringList[Count - 1] + + String = RetString + + # + # in case there's macro not defined + # + if String == LastString: + break + LastString = String + + return String + +## NormPath +# +# Create a normal path +# And replace DEFINE in the path +# +# @param Path: The input value for Path to be converted +# @param Defines: A set for DEFINE statement +# +def NormPath(Path, Defines=None): + IsRelativePath = False + if Defines is None: + Defines = {} + if Path: + if Path[0] == '.': + IsRelativePath = True + # + # Replace with Define + # + if Defines: + Path = ReplaceMacro(Path, Defines) + # + # To local path format + # + Path = os.path.normpath(Path) + + if IsRelativePath and Path[0] != '.': + Path = os.path.join('.', Path) + return Path + +## CleanString +# +# Remove comments in a string +# Remove spaces +# +# @param Line: The string to be cleaned +# @param CommentCharacter: Comment char, used to ignore comment content, +# default is DataType.TAB_COMMENT_SPLIT +# +def CleanString(Line, CommentCharacter=DataType.TAB_COMMENT_SPLIT, AllowCppStyleComment=False): + # + # remove whitespace + # + Line = Line.strip() + # + # Replace EDK1's comment character + # + if AllowCppStyleComment: + Line = Line.replace(DataType.TAB_COMMENT_EDK1_SPLIT, CommentCharacter) + # + # remove comments, but we should escape comment character in string + # + InString = False + for Index in range(0, len(Line)): + if Line[Index] == '"': + InString = not InString + elif Line[Index] == CommentCharacter and not InString: + Line = Line[0: Index] + break + # + # remove whitespace again + # + Line = Line.strip() + + return Line + +## CleanString2 +# +# Split comments in a string +# Remove spaces +# +# @param Line: The string to be cleaned +# @param CommentCharacter: Comment char, used to ignore comment content, +# default is DataType.TAB_COMMENT_SPLIT +# +def CleanString2(Line, CommentCharacter=DataType.TAB_COMMENT_SPLIT, AllowCppStyleComment=False): + # + # remove whitespace + # + Line = Line.strip() + # + # Replace EDK1's comment character + # + if AllowCppStyleComment: + Line = Line.replace(DataType.TAB_COMMENT_EDK1_SPLIT, CommentCharacter) + # + # separate comments and statements + # + LineParts = Line.split(CommentCharacter, 1) + # + # remove whitespace again + # + Line = LineParts[0].strip() + if len(LineParts) > 1: + Comment = LineParts[1].strip() + # + # Remove prefixed and trailing comment characters + # + Start = 0 + End = len(Comment) + while Start < End and Comment.startswith(CommentCharacter, Start, End): + Start += 1 + while End >= 0 and Comment.endswith(CommentCharacter, Start, End): + End -= 1 + Comment = Comment[Start:End] + Comment = Comment.strip() + else: + Comment = '' + + return Line, Comment + +## GetMultipleValuesOfKeyFromLines +# +# Parse multiple strings to clean comment and spaces +# The result is saved to KeyValues +# +# @param Lines: The content to be parsed +# @param Key: Reserved +# @param KeyValues: To store data after parsing +# @param CommentCharacter: Comment char, used to ignore comment content +# +def GetMultipleValuesOfKeyFromLines(Lines, Key, KeyValues, CommentCharacter): + if Key: + pass + if KeyValues: + pass + Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1] + LineList = Lines.split('\n') + for Line in LineList: + Line = CleanString(Line, CommentCharacter) + if Line != '' and Line[0] != CommentCharacter: + KeyValues += [Line] + return True + +## GetDefineValue +# +# Parse a DEFINE statement to get defined value +# DEFINE Key Value +# +# @param String: The content to be parsed +# @param Key: The key of DEFINE statement +# @param CommentCharacter: Comment char, used to ignore comment content +# +def GetDefineValue(String, Key, CommentCharacter): + if CommentCharacter: + pass + String = CleanString(String) + return String[String.find(Key + ' ') + len(Key + ' ') : ] + +## GetSingleValueOfKeyFromLines +# +# Parse multiple strings as below to get value of each definition line +# Key1 = Value1 +# Key2 = Value2 +# The result is saved to Dictionary +# +# @param Lines: The content to be parsed +# @param Dictionary: To store data after parsing +# @param CommentCharacter: Comment char, be used to ignore comment content +# @param KeySplitCharacter: Key split char, between key name and key value. +# Key1 = Value1, '=' is the key split char +# @param ValueSplitFlag: Value split flag, be used to decide if has +# multiple values +# @param ValueSplitCharacter: Value split char, be used to split multiple +# values. Key1 = Value1|Value2, '|' is the value +# split char +# +def GetSingleValueOfKeyFromLines(Lines, Dictionary, CommentCharacter, KeySplitCharacter, \ + ValueSplitFlag, ValueSplitCharacter): + Lines = Lines.split('\n') + Keys = [] + Value = '' + DefineValues = [''] + SpecValues = [''] + + for Line in Lines: + # + # Handle DEFINE and SPEC + # + if Line.find(DataType.TAB_INF_DEFINES_DEFINE + ' ') > -1: + if '' in DefineValues: + DefineValues.remove('') + DefineValues.append(GetDefineValue(Line, DataType.TAB_INF_DEFINES_DEFINE, CommentCharacter)) + continue + if Line.find(DataType.TAB_INF_DEFINES_SPEC + ' ') > -1: + if '' in SpecValues: + SpecValues.remove('') + SpecValues.append(GetDefineValue(Line, DataType.TAB_INF_DEFINES_SPEC, CommentCharacter)) + continue + + # + # Handle Others + # + LineList = Line.split(KeySplitCharacter, 1) + if len(LineList) >= 2: + Key = LineList[0].split() + if len(Key) == 1 and Key[0][0] != CommentCharacter: + # + # Remove comments and white spaces + # + LineList[1] = CleanString(LineList[1], CommentCharacter) + if ValueSplitFlag: + Value = list(map(lambda x: x.strip(), LineList[1].split(ValueSplitCharacter))) + else: + Value = CleanString(LineList[1], CommentCharacter).splitlines() + + if Key[0] in Dictionary: + if Key[0] not in Keys: + Dictionary[Key[0]] = Value + Keys.append(Key[0]) + else: + Dictionary[Key[0]].extend(Value) + else: + Dictionary[DataType.TAB_INF_DEFINES_MACRO][Key[0]] = Value[0] + + if DefineValues == []: + DefineValues = [''] + if SpecValues == []: + SpecValues = [''] + Dictionary[DataType.TAB_INF_DEFINES_DEFINE] = DefineValues + Dictionary[DataType.TAB_INF_DEFINES_SPEC] = SpecValues + + return True + +## The content to be parsed +# +# Do pre-check for a file before it is parsed +# Check $() +# Check [] +# +# @param FileName: Used for error report +# @param FileContent: File content to be parsed +# @param SupSectionTag: Used for error report +# +def PreCheck(FileName, FileContent, SupSectionTag): + if SupSectionTag: + pass + LineNo = 0 + IsFailed = False + NewFileContent = '' + for Line in FileContent.splitlines(): + LineNo = LineNo + 1 + # + # Clean current line + # + Line = CleanString(Line) + # + # Remove commented line + # + if Line.find(DataType.TAB_COMMA_SPLIT) == 0: + Line = '' + # + # Check $() + # + if Line.find('$') > -1: + if Line.find('$(') < 0 or Line.find(')') < 0: + Logger.Error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError=Logger.IS_RAISE_ERROR) + # + # Check [] + # + if Line.find('[') > -1 or Line.find(']') > -1: + # + # Only get one '[' or one ']' + # + if not (Line.find('[') > -1 and Line.find(']') > -1): + Logger.Error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError=Logger.IS_RAISE_ERROR) + # + # Regenerate FileContent + # + NewFileContent = NewFileContent + Line + '\r\n' + + if IsFailed: + Logger.Error("Parser", FORMAT_INVALID, Line=LineNo, File=FileName, RaiseError=Logger.IS_RAISE_ERROR) + + return NewFileContent + +## CheckFileType +# +# Check if the Filename is including ExtName +# Return True if it exists +# Raise a error message if it not exists +# +# @param CheckFilename: Name of the file to be checked +# @param ExtName: Ext name of the file to be checked +# @param ContainerFilename: The container file which describes the file to be +# checked, used for error report +# @param SectionName: Used for error report +# @param Line: The line in container file which defines the file +# to be checked +# +def CheckFileType(CheckFilename, ExtName, ContainerFilename, SectionName, Line, LineNo= -1): + if CheckFilename != '' and CheckFilename is not None: + (Root, Ext) = os.path.splitext(CheckFilename) + if Ext.upper() != ExtName.upper() and Root: + ContainerFile = open(ContainerFilename, 'r').read() + if LineNo == -1: + LineNo = GetLineNo(ContainerFile, Line) + ErrorMsg = ST.ERR_SECTIONNAME_INVALID % (SectionName, CheckFilename, ExtName) + Logger.Error("Parser", PARSER_ERROR, ErrorMsg, Line=LineNo, \ + File=ContainerFilename, RaiseError=Logger.IS_RAISE_ERROR) + + return True + +## CheckFileExist +# +# Check if the file exists +# Return True if it exists +# Raise a error message if it not exists +# +# @param CheckFilename: Name of the file to be checked +# @param WorkspaceDir: Current workspace dir +# @param ContainerFilename: The container file which describes the file to +# be checked, used for error report +# @param SectionName: Used for error report +# @param Line: The line in container file which defines the +# file to be checked +# +def CheckFileExist(WorkspaceDir, CheckFilename, ContainerFilename, SectionName, Line, LineNo= -1): + CheckFile = '' + if CheckFilename != '' and CheckFilename is not None: + CheckFile = WorkspaceFile(WorkspaceDir, CheckFilename) + if not os.path.isfile(CheckFile): + ContainerFile = open(ContainerFilename, 'r').read() + if LineNo == -1: + LineNo = GetLineNo(ContainerFile, Line) + ErrorMsg = ST.ERR_CHECKFILE_NOTFOUND % (CheckFile, SectionName) + Logger.Error("Parser", PARSER_ERROR, ErrorMsg, + File=ContainerFilename, Line=LineNo, RaiseError=Logger.IS_RAISE_ERROR) + return CheckFile + +## GetLineNo +# +# Find the index of a line in a file +# +# @param FileContent: Search scope +# @param Line: Search key +# +def GetLineNo(FileContent, Line, IsIgnoreComment=True): + LineList = FileContent.splitlines() + for Index in range(len(LineList)): + if LineList[Index].find(Line) > -1: + # + # Ignore statement in comment + # + if IsIgnoreComment: + if LineList[Index].strip()[0] == DataType.TAB_COMMENT_SPLIT: + continue + return Index + 1 + + return -1 + +## RaiseParserError +# +# Raise a parser error +# +# @param Line: String which has error +# @param Section: Used for error report +# @param File: File which has the string +# @param Format: Correct format +# +def RaiseParserError(Line, Section, File, Format='', LineNo= -1): + if LineNo == -1: + LineNo = GetLineNo(open(os.path.normpath(File), 'r').read(), Line) + ErrorMsg = ST.ERR_INVALID_NOTFOUND % (Line, Section) + if Format != '': + Format = "Correct format is " + Format + Logger.Error("Parser", PARSER_ERROR, ErrorMsg, File=File, Line=LineNo, \ + ExtraData=Format, RaiseError=Logger.IS_RAISE_ERROR) + +## WorkspaceFile +# +# Return a full path with workspace dir +# +# @param WorkspaceDir: Workspace dir +# @param Filename: Relative file name +# +def WorkspaceFile(WorkspaceDir, Filename): + return os.path.join(NormPath(WorkspaceDir), NormPath(Filename)) + +## Split string +# +# Remove '"' which startswith and endswith string +# +# @param String: The string need to be split +# +def SplitString(String): + if String.startswith('\"'): + String = String[1:] + if String.endswith('\"'): + String = String[:-1] + return String + +## Convert To Sql String +# +# Replace "'" with "''" in each item of StringList +# +# @param StringList: A list for strings to be converted +# +def ConvertToSqlString(StringList): + return list(map(lambda s: s.replace("'", "''"), StringList)) + +## Convert To Sql String +# +# Replace "'" with "''" in the String +# +# @param String: A String to be converted +# +def ConvertToSqlString2(String): + return String.replace("'", "''") + +## GetStringOfList +# +# Get String of a List +# +# @param Lines: string list +# @param Split: split character +# +def GetStringOfList(List, Split=' '): + if not isinstance(List, type([])): + return List + Str = '' + for Item in List: + Str = Str + Item + Split + return Str.strip() + +## Get HelpTextList +# +# Get HelpTextList from HelpTextClassList +# +# @param HelpTextClassList: Help Text Class List +# +def GetHelpTextList(HelpTextClassList): + List = [] + if HelpTextClassList: + for HelpText in HelpTextClassList: + if HelpText.String.endswith('\n'): + HelpText.String = HelpText.String[0: len(HelpText.String) - len('\n')] + List.extend(HelpText.String.split('\n')) + return List + +## Get String Array Length +# +# Get String Array Length +# +# @param String: the source string +# +def StringArrayLength(String): + if String.startswith('L"'): + return (len(String) - 3 + 1) * 2 + elif String.startswith('"'): + return (len(String) - 2 + 1) + else: + return len(String.split()) + 1 + +## RemoveDupOption +# +# Remove Dup Option +# +# @param OptionString: the option string +# @param Which: Which flag +# @param Against: Against flag +# +def RemoveDupOption(OptionString, Which="/I", Against=None): + OptionList = OptionString.split() + ValueList = [] + if Against: + ValueList += Against + for Index in range(len(OptionList)): + Opt = OptionList[Index] + if not Opt.startswith(Which): + continue + if len(Opt) > len(Which): + Val = Opt[len(Which):] + else: + Val = "" + if Val in ValueList: + OptionList[Index] = "" + else: + ValueList.append(Val) + return " ".join(OptionList) + +## Check if the string is HexDgit +# +# Return true if all characters in the string are digits and there is at +# least one character +# or valid Hexs (started with 0x, following by hexdigit letters) +# , false otherwise. +# @param string: input string +# +def IsHexDigit(Str): + try: + int(Str, 10) + return True + except ValueError: + if len(Str) > 2 and Str.upper().startswith('0X'): + try: + int(Str, 16) + return True + except ValueError: + return False + return False + +## Check if the string is HexDgit and its integer value within limit of UINT32 +# +# Return true if all characters in the string are digits and there is at +# least one character +# or valid Hexs (started with 0x, following by hexdigit letters) +# , false otherwise. +# @param string: input string +# +def IsHexDigitUINT32(Str): + try: + Value = int(Str, 10) + if (Value <= 0xFFFFFFFF) and (Value >= 0): + return True + except ValueError: + if len(Str) > 2 and Str.upper().startswith('0X'): + try: + Value = int(Str, 16) + if (Value <= 0xFFFFFFFF) and (Value >= 0): + return True + except ValueError: + return False + return False + +## CleanSpecialChar +# +# The ASCII text files of type INF, DEC, INI are edited by developers, +# and may contain characters that cannot be directly translated to strings that +# are conformant with the UDP XML Schema. Any characters in this category +# (0x00-0x08, TAB [0x09], 0x0B, 0x0C, 0x0E-0x1F, 0x80-0xFF) +# must be converted to a space character[0x20] as part of the parsing process. +# +def ConvertSpecialChar(Lines): + RetLines = [] + for line in Lines: + ReMatchSpecialChar = re.compile(r"[\x00-\x08]|\x09|\x0b|\x0c|[\x0e-\x1f]|[\x7f-\xff]") + RetLines.append(ReMatchSpecialChar.sub(' ', line)) + + return RetLines + +## __GetTokenList +# +# Assume Str is a valid feature flag expression. +# Return a list which contains tokens: alpha numeric token and other token +# Whitespace are not stripped +# +def __GetTokenList(Str): + InQuote = False + Token = '' + TokenOP = '' + PreChar = '' + List = [] + for Char in Str: + if InQuote: + Token += Char + if Char == '"' and PreChar != '\\': + InQuote = not InQuote + List.append(Token) + Token = '' + continue + if Char == '"': + if Token and Token != 'L': + List.append(Token) + Token = '' + if TokenOP: + List.append(TokenOP) + TokenOP = '' + InQuote = not InQuote + Token += Char + continue + + if not (Char.isalnum() or Char in '_'): + TokenOP += Char + if Token: + List.append(Token) + Token = '' + else: + Token += Char + if TokenOP: + List.append(TokenOP) + TokenOP = '' + + if PreChar == '\\' and Char == '\\': + PreChar = '' + else: + PreChar = Char + if Token: + List.append(Token) + if TokenOP: + List.append(TokenOP) + return List + +## ConvertNEToNOTEQ +# +# Convert NE operator to NOT EQ +# For example: 1 NE 2 -> 1 NOT EQ 2 +# +# @param Expr: Feature flag expression to be converted +# +def ConvertNEToNOTEQ(Expr): + List = __GetTokenList(Expr) + for Index in range(len(List)): + if List[Index] == 'NE': + List[Index] = 'NOT EQ' + return ''.join(List) + +## ConvertNOTEQToNE +# +# Convert NOT EQ operator to NE +# For example: 1 NOT NE 2 -> 1 NE 2 +# +# @param Expr: Feature flag expression to be converted +# +def ConvertNOTEQToNE(Expr): + List = __GetTokenList(Expr) + HasNOT = False + RetList = [] + for Token in List: + if HasNOT and Token == 'EQ': + # At least, 'NOT' is in the list + while not RetList[-1].strip(): + RetList.pop() + RetList[-1] = 'NE' + HasNOT = False + continue + if Token == 'NOT': + HasNOT = True + elif Token.strip(): + HasNOT = False + RetList.append(Token) + + return ''.join(RetList) + +## SplitPcdEntry +# +# Split an PCD entry string to Token.CName and PCD value and FFE. +# NOTE: PCD Value and FFE can contain "|" in its expression. And in INF specification, have below rule. +# When using the characters "|" or "||" in an expression, the expression must be encapsulated in +# open "(" and close ")" parenthesis. +# +# @param String An PCD entry string need to be split. +# +# @return List [PcdTokenCName, Value, FFE] +# +def SplitPcdEntry(String): + if not String: + return ['', '', ''], False + + PcdTokenCName = '' + PcdValue = '' + PcdFeatureFlagExp = '' + + ValueList = GetSplitValueList(String, "|", 1) + + # + # Only contain TokenCName + # + if len(ValueList) == 1: + return [ValueList[0]], True + + NewValueList = [] + + if len(ValueList) == 2: + PcdTokenCName = ValueList[0] + + InQuote = False + InParenthesis = False + StrItem = '' + for StrCh in ValueList[1]: + if StrCh == '"': + InQuote = not InQuote + elif StrCh == '(' or StrCh == ')': + InParenthesis = not InParenthesis + + if StrCh == '|': + if not InQuote or not InParenthesis: + NewValueList.append(StrItem.strip()) + StrItem = ' ' + continue + + StrItem += StrCh + + NewValueList.append(StrItem.strip()) + + if len(NewValueList) == 1: + PcdValue = NewValueList[0] + return [PcdTokenCName, PcdValue], True + elif len(NewValueList) == 2: + PcdValue = NewValueList[0] + PcdFeatureFlagExp = NewValueList[1] + return [PcdTokenCName, PcdValue, PcdFeatureFlagExp], True + else: + return ['', '', ''], False + + return ['', '', ''], False + +## Check if two arches matched? +# +# @param Arch1 +# @param Arch2 +# +def IsMatchArch(Arch1, Arch2): + if 'COMMON' in Arch1 or 'COMMON' in Arch2: + return True + try: + if isinstance(Arch1, list) and isinstance(Arch2, list): + for Item1 in Arch1: + for Item2 in Arch2: + if Item1 == Item2: + return True + + elif isinstance(Arch1, list): + return Arch2 in Arch1 + + elif isinstance(Arch2, list): + return Arch1 in Arch2 + + else: + if Arch1 == Arch2: + return True + except: + return False + +# Search all files in FilePath to find the FileName with the largest index +# Return the FileName with index +1 under the FilePath +# +def GetUniFileName(FilePath, FileName): + Files = [] + try: + Files = os.listdir(FilePath) + except: + pass + + LargestIndex = -1 + IndexNotFound = True + for File in Files: + if File.upper().startswith(FileName.upper()) and File.upper().endswith('.UNI'): + Index = File.upper().replace(FileName.upper(), '').replace('.UNI', '') + if Index: + try: + Index = int(Index) + except Exception: + Index = -1 + else: + IndexNotFound = False + Index = 0 + if Index > LargestIndex: + LargestIndex = Index + 1 + + if LargestIndex > -1 and not IndexNotFound: + return os.path.normpath(os.path.join(FilePath, FileName + str(LargestIndex) + '.uni')) + else: + return os.path.normpath(os.path.join(FilePath, FileName + '.uni')) diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/UniClassObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/UniClassObject.py new file mode 100755 index 00000000..1eaa8f7d --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/UniClassObject.py @@ -0,0 +1,1074 @@ +## @file +# Collect all defined strings in multiple uni files. +# +# Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +""" +Collect all defined strings in multiple uni files +""" +from __future__ import print_function + +## +# Import Modules +# +import os, codecs, re +import distutils.util +from Logger import ToolError +from Logger import Log as EdkLogger +from Logger import StringTable as ST +from Library.StringUtils import GetLineNo +from Library.Misc import PathClass +from Library.Misc import GetCharIndexOutStr +from Library import DataType as DT +from Library.ParserValidate import CheckUTF16FileHeader + +## +# Static definitions +# +UNICODE_WIDE_CHAR = u'\\wide' +UNICODE_NARROW_CHAR = u'\\narrow' +UNICODE_NON_BREAKING_CHAR = u'\\nbr' +UNICODE_UNICODE_CR = '\r' +UNICODE_UNICODE_LF = '\n' + +NARROW_CHAR = u'\uFFF0' +WIDE_CHAR = u'\uFFF1' +NON_BREAKING_CHAR = u'\uFFF2' +CR = u'\u000D' +LF = u'\u000A' +NULL = u'\u0000' +TAB = u'\t' +BACK_SPLASH = u'\\' + +gLANG_CONV_TABLE = {'eng':'en', 'fra':'fr', \ + 'aar':'aa', 'abk':'ab', 'ave':'ae', 'afr':'af', 'aka':'ak', 'amh':'am', \ + 'arg':'an', 'ara':'ar', 'asm':'as', 'ava':'av', 'aym':'ay', 'aze':'az', \ + 'bak':'ba', 'bel':'be', 'bul':'bg', 'bih':'bh', 'bis':'bi', 'bam':'bm', \ + 'ben':'bn', 'bod':'bo', 'bre':'br', 'bos':'bs', 'cat':'ca', 'che':'ce', \ + 'cha':'ch', 'cos':'co', 'cre':'cr', 'ces':'cs', 'chu':'cu', 'chv':'cv', \ + 'cym':'cy', 'dan':'da', 'deu':'de', 'div':'dv', 'dzo':'dz', 'ewe':'ee', \ + 'ell':'el', 'epo':'eo', 'spa':'es', 'est':'et', 'eus':'eu', 'fas':'fa', \ + 'ful':'ff', 'fin':'fi', 'fij':'fj', 'fao':'fo', 'fry':'fy', 'gle':'ga', \ + 'gla':'gd', 'glg':'gl', 'grn':'gn', 'guj':'gu', 'glv':'gv', 'hau':'ha', \ + 'heb':'he', 'hin':'hi', 'hmo':'ho', 'hrv':'hr', 'hat':'ht', 'hun':'hu', \ + 'hye':'hy', 'her':'hz', 'ina':'ia', 'ind':'id', 'ile':'ie', 'ibo':'ig', \ + 'iii':'ii', 'ipk':'ik', 'ido':'io', 'isl':'is', 'ita':'it', 'iku':'iu', \ + 'jpn':'ja', 'jav':'jv', 'kat':'ka', 'kon':'kg', 'kik':'ki', 'kua':'kj', \ + 'kaz':'kk', 'kal':'kl', 'khm':'km', 'kan':'kn', 'kor':'ko', 'kau':'kr', \ + 'kas':'ks', 'kur':'ku', 'kom':'kv', 'cor':'kw', 'kir':'ky', 'lat':'la', \ + 'ltz':'lb', 'lug':'lg', 'lim':'li', 'lin':'ln', 'lao':'lo', 'lit':'lt', \ + 'lub':'lu', 'lav':'lv', 'mlg':'mg', 'mah':'mh', 'mri':'mi', 'mkd':'mk', \ + 'mal':'ml', 'mon':'mn', 'mar':'mr', 'msa':'ms', 'mlt':'mt', 'mya':'my', \ + 'nau':'na', 'nob':'nb', 'nde':'nd', 'nep':'ne', 'ndo':'ng', 'nld':'nl', \ + 'nno':'nn', 'nor':'no', 'nbl':'nr', 'nav':'nv', 'nya':'ny', 'oci':'oc', \ + 'oji':'oj', 'orm':'om', 'ori':'or', 'oss':'os', 'pan':'pa', 'pli':'pi', \ + 'pol':'pl', 'pus':'ps', 'por':'pt', 'que':'qu', 'roh':'rm', 'run':'rn', \ + 'ron':'ro', 'rus':'ru', 'kin':'rw', 'san':'sa', 'srd':'sc', 'snd':'sd', \ + 'sme':'se', 'sag':'sg', 'sin':'si', 'slk':'sk', 'slv':'sl', 'smo':'sm', \ + 'sna':'sn', 'som':'so', 'sqi':'sq', 'srp':'sr', 'ssw':'ss', 'sot':'st', \ + 'sun':'su', 'swe':'sv', 'swa':'sw', 'tam':'ta', 'tel':'te', 'tgk':'tg', \ + 'tha':'th', 'tir':'ti', 'tuk':'tk', 'tgl':'tl', 'tsn':'tn', 'ton':'to', \ + 'tur':'tr', 'tso':'ts', 'tat':'tt', 'twi':'tw', 'tah':'ty', 'uig':'ug', \ + 'ukr':'uk', 'urd':'ur', 'uzb':'uz', 'ven':'ve', 'vie':'vi', 'vol':'vo', \ + 'wln':'wa', 'wol':'wo', 'xho':'xh', 'yid':'yi', 'yor':'yo', 'zha':'za', \ + 'zho':'zh', 'zul':'zu'} + +## Convert a python unicode string to a normal string +# +# Convert a python unicode string to a normal string +# UniToStr(u'I am a string') is 'I am a string' +# +# @param Uni: The python unicode string +# +# @retval: The formatted normal string +# +def UniToStr(Uni): + return repr(Uni)[2:-1] + +## Convert a unicode string to a Hex list +# +# Convert a unicode string to a Hex list +# UniToHexList('ABC') is ['0x41', '0x00', '0x42', '0x00', '0x43', '0x00'] +# +# @param Uni: The python unicode string +# +# @retval List: The formatted hex list +# +def UniToHexList(Uni): + List = [] + for Item in Uni: + Temp = '%04X' % ord(Item) + List.append('0x' + Temp[2:4]) + List.append('0x' + Temp[0:2]) + return List + +## Convert special unicode characters +# +# Convert special characters to (c), (r) and (tm). +# +# @param Uni: The python unicode string +# +# @retval NewUni: The converted unicode string +# +def ConvertSpecialUnicodes(Uni): + OldUni = NewUni = Uni + NewUni = NewUni.replace(u'\u00A9', '(c)') + NewUni = NewUni.replace(u'\u00AE', '(r)') + NewUni = NewUni.replace(u'\u2122', '(tm)') + if OldUni == NewUni: + NewUni = OldUni + return NewUni + +## GetLanguageCode1766 +# +# Check the language code read from .UNI file and convert RFC 4646 codes to RFC 1766 codes +# RFC 1766 language codes supported in compatibility mode +# RFC 4646 language codes supported in native mode +# +# @param LangName: Language codes read from .UNI file +# +# @retval LangName: Valid language code in RFC 1766 format or None +# +def GetLanguageCode1766(LangName, File=None): + return LangName + + length = len(LangName) + if length == 2: + if LangName.isalpha(): + for Key in gLANG_CONV_TABLE.keys(): + if gLANG_CONV_TABLE.get(Key) == LangName.lower(): + return Key + elif length == 3: + if LangName.isalpha() and gLANG_CONV_TABLE.get(LangName.lower()): + return LangName + else: + EdkLogger.Error("Unicode File Parser", + ToolError.FORMAT_INVALID, + "Invalid RFC 1766 language code : %s" % LangName, + File) + elif length == 5: + if LangName[0:2].isalpha() and LangName[2] == '-': + for Key in gLANG_CONV_TABLE.keys(): + if gLANG_CONV_TABLE.get(Key) == LangName[0:2].lower(): + return Key + elif length >= 6: + if LangName[0:2].isalpha() and LangName[2] == '-': + for Key in gLANG_CONV_TABLE.keys(): + if gLANG_CONV_TABLE.get(Key) == LangName[0:2].lower(): + return Key + if LangName[0:3].isalpha() and gLANG_CONV_TABLE.get(LangName.lower()) is None and LangName[3] == '-': + for Key in gLANG_CONV_TABLE.keys(): + if Key == LangName[0:3].lower(): + return Key + + EdkLogger.Error("Unicode File Parser", + ToolError.FORMAT_INVALID, + "Invalid RFC 4646 language code : %s" % LangName, + File) + +## GetLanguageCode +# +# Check the language code read from .UNI file and convert RFC 1766 codes to RFC 4646 codes if appropriate +# RFC 1766 language codes supported in compatibility mode +# RFC 4646 language codes supported in native mode +# +# @param LangName: Language codes read from .UNI file +# +# @retval LangName: Valid lanugage code in RFC 4646 format or None +# +def GetLanguageCode(LangName, IsCompatibleMode, File): + length = len(LangName) + if IsCompatibleMode: + if length == 3 and LangName.isalpha(): + TempLangName = gLANG_CONV_TABLE.get(LangName.lower()) + if TempLangName is not None: + return TempLangName + return LangName + else: + EdkLogger.Error("Unicode File Parser", + ToolError.FORMAT_INVALID, + "Invalid RFC 1766 language code : %s" % LangName, + File) + if (LangName[0] == 'X' or LangName[0] == 'x') and LangName[1] == '-': + return LangName + if length == 2: + if LangName.isalpha(): + return LangName + elif length == 3: + if LangName.isalpha() and gLANG_CONV_TABLE.get(LangName.lower()) is None: + return LangName + elif length == 5: + if LangName[0:2].isalpha() and LangName[2] == '-': + return LangName + elif length >= 6: + if LangName[0:2].isalpha() and LangName[2] == '-': + return LangName + if LangName[0:3].isalpha() and gLANG_CONV_TABLE.get(LangName.lower()) is None and LangName[3] == '-': + return LangName + + EdkLogger.Error("Unicode File Parser", + ToolError.FORMAT_INVALID, + "Invalid RFC 4646 language code : %s" % LangName, + File) + +## FormatUniEntry +# +# Formatted the entry in Uni file. +# +# @param StrTokenName StrTokenName. +# @param TokenValueList A list need to be processed. +# @param ContainerFile ContainerFile. +# +# @return formatted entry +def FormatUniEntry(StrTokenName, TokenValueList, ContainerFile): + SubContent = '' + PreFormatLength = 40 + if len(StrTokenName) > PreFormatLength: + PreFormatLength = len(StrTokenName) + 1 + for (Lang, Value) in TokenValueList: + if not Value or Lang == DT.TAB_LANGUAGE_EN_X: + continue + if Lang == '': + Lang = DT.TAB_LANGUAGE_EN_US + if Lang == 'eng': + Lang = DT.TAB_LANGUAGE_EN_US + elif len(Lang.split('-')[0]) == 3: + Lang = GetLanguageCode(Lang.split('-')[0], True, ContainerFile) + else: + Lang = GetLanguageCode(Lang, False, ContainerFile) + ValueList = Value.split('\n') + SubValueContent = '' + for SubValue in ValueList: + if SubValue.strip(): + SubValueContent += \ + ' ' * (PreFormatLength + len('#language en-US ')) + '\"%s\\n\"' % SubValue.strip() + '\r\n' + SubValueContent = SubValueContent[(PreFormatLength + len('#language en-US ')):SubValueContent.rfind('\\n')] \ + + '\"' + '\r\n' + SubContent += ' '*PreFormatLength + '#language %-5s ' % Lang + SubValueContent + if SubContent: + SubContent = StrTokenName + ' '*(PreFormatLength - len(StrTokenName)) + SubContent[PreFormatLength:] + return SubContent + + +## StringDefClassObject +# +# A structure for language definition +# +class StringDefClassObject(object): + def __init__(self, Name = None, Value = None, Referenced = False, Token = None, UseOtherLangDef = ''): + self.StringName = '' + self.StringNameByteList = [] + self.StringValue = '' + self.StringValueByteList = '' + self.Token = 0 + self.Referenced = Referenced + self.UseOtherLangDef = UseOtherLangDef + self.Length = 0 + + if Name is not None: + self.StringName = Name + self.StringNameByteList = UniToHexList(Name) + if Value is not None: + self.StringValue = Value + self.StringValueByteList = UniToHexList(self.StringValue) + self.Length = len(self.StringValueByteList) + if Token is not None: + self.Token = Token + + def __str__(self): + return repr(self.StringName) + ' ' + \ + repr(self.Token) + ' ' + \ + repr(self.Referenced) + ' ' + \ + repr(self.StringValue) + ' ' + \ + repr(self.UseOtherLangDef) + + def UpdateValue(self, Value = None): + if Value is not None: + if self.StringValue: + self.StringValue = self.StringValue + '\r\n' + Value + else: + self.StringValue = Value + self.StringValueByteList = UniToHexList(self.StringValue) + self.Length = len(self.StringValueByteList) + +## UniFileClassObject +# +# A structure for .uni file definition +# +class UniFileClassObject(object): + def __init__(self, FileList = None, IsCompatibleMode = False, IncludePathList = None): + self.FileList = FileList + self.File = None + self.IncFileList = FileList + self.UniFileHeader = '' + self.Token = 2 + self.LanguageDef = [] #[ [u'LanguageIdentifier', u'PrintableName'], ... ] + self.OrderedStringList = {} #{ u'LanguageIdentifier' : [StringDefClassObject] } + self.OrderedStringDict = {} #{ u'LanguageIdentifier' : {StringName:(IndexInList)} } + self.OrderedStringListByToken = {} #{ u'LanguageIdentifier' : {Token: StringDefClassObject} } + self.IsCompatibleMode = IsCompatibleMode + if not IncludePathList: + self.IncludePathList = [] + else: + self.IncludePathList = IncludePathList + if len(self.FileList) > 0: + self.LoadUniFiles(FileList) + + # + # Get Language definition + # + def GetLangDef(self, File, Line): + Lang = distutils.util.split_quoted((Line.split(u"//")[0])) + if len(Lang) != 3: + try: + FileIn = codecs.open(File.Path, mode='rb', encoding='utf_8').readlines() + except UnicodeError as Xstr: + FileIn = codecs.open(File.Path, mode='rb', encoding='utf_16').readlines() + except UnicodeError as Xstr: + FileIn = codecs.open(File.Path, mode='rb', encoding='utf_16_le').readlines() + except: + EdkLogger.Error("Unicode File Parser", + ToolError.FILE_OPEN_FAILURE, + "File read failure: %s" % str(Xstr), + ExtraData=File) + LineNo = GetLineNo(FileIn, Line, False) + EdkLogger.Error("Unicode File Parser", + ToolError.PARSER_ERROR, + "Wrong language definition", + ExtraData="""%s\n\t*Correct format is like '#langdef en-US "English"'""" % Line, + File = File, Line = LineNo) + else: + LangName = GetLanguageCode(Lang[1], self.IsCompatibleMode, self.File) + LangPrintName = Lang[2] + + IsLangInDef = False + for Item in self.LanguageDef: + if Item[0] == LangName: + IsLangInDef = True + break + + if not IsLangInDef: + self.LanguageDef.append([LangName, LangPrintName]) + + # + # Add language string + # + self.AddStringToList(u'$LANGUAGE_NAME', LangName, LangName, 0, True, Index=0) + self.AddStringToList(u'$PRINTABLE_LANGUAGE_NAME', LangName, LangPrintName, 1, True, Index=1) + + if not IsLangInDef: + # + # The found STRING tokens will be added into new language string list + # so that the unique STRING identifier is reserved for all languages in the package list. + # + FirstLangName = self.LanguageDef[0][0] + if LangName != FirstLangName: + for Index in range (2, len (self.OrderedStringList[FirstLangName])): + Item = self.OrderedStringList[FirstLangName][Index] + if Item.UseOtherLangDef != '': + OtherLang = Item.UseOtherLangDef + else: + OtherLang = FirstLangName + self.OrderedStringList[LangName].append (StringDefClassObject(Item.StringName, + '', + Item.Referenced, + Item.Token, + OtherLang)) + self.OrderedStringDict[LangName][Item.StringName] = len(self.OrderedStringList[LangName]) - 1 + return True + + # + # Get String name and value + # + def GetStringObject(self, Item): + Language = '' + Value = '' + + Name = Item.split()[1] + # Check the string name is the upper character + if Name != '': + MatchString = re.match('[A-Z0-9_]+', Name, re.UNICODE) + if MatchString is None or MatchString.end(0) != len(Name): + EdkLogger.Error("Unicode File Parser", + ToolError.FORMAT_INVALID, + 'The string token name %s in UNI file %s must be upper case character.' %(Name, self.File)) + LanguageList = Item.split(u'#language ') + for IndexI in range(len(LanguageList)): + if IndexI == 0: + continue + else: + Language = LanguageList[IndexI].split()[0] + #.replace(u'\r\n', u'') + Value = \ + LanguageList[IndexI][LanguageList[IndexI].find(u'\"') + len(u'\"') : LanguageList[IndexI].rfind(u'\"')] + Language = GetLanguageCode(Language, self.IsCompatibleMode, self.File) + self.AddStringToList(Name, Language, Value) + + # + # Get include file list and load them + # + def GetIncludeFile(self, Item, Dir = None): + if Dir: + pass + FileName = Item[Item.find(u'!include ') + len(u'!include ') :Item.find(u' ', len(u'!include '))][1:-1] + self.LoadUniFile(FileName) + + # + # Pre-process before parse .uni file + # + def PreProcess(self, File, IsIncludeFile=False): + if not os.path.exists(File.Path) or not os.path.isfile(File.Path): + EdkLogger.Error("Unicode File Parser", + ToolError.FILE_NOT_FOUND, + ExtraData=File.Path) + + # + # Check file header of the Uni file + # +# if not CheckUTF16FileHeader(File.Path): +# EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, +# ExtraData='The file %s is either invalid UTF-16LE or it is missing the BOM.' % File.Path) + + try: + FileIn = codecs.open(File.Path, mode='rb', encoding='utf_8').readlines() + except UnicodeError as Xstr: + FileIn = codecs.open(File.Path, mode='rb', encoding='utf_16').readlines() + except UnicodeError: + FileIn = codecs.open(File.Path, mode='rb', encoding='utf_16_le').readlines() + except: + EdkLogger.Error("Unicode File Parser", ToolError.FILE_OPEN_FAILURE, ExtraData=File.Path) + + + # + # get the file header + # + Lines = [] + HeaderStart = False + HeaderEnd = False + if not self.UniFileHeader: + FirstGenHeader = True + else: + FirstGenHeader = False + for Line in FileIn: + Line = Line.strip() + if Line == u'': + continue + if Line.startswith(DT.TAB_COMMENT_EDK1_SPLIT) and (Line.find(DT.TAB_HEADER_COMMENT) > -1) \ + and not HeaderEnd and not HeaderStart: + HeaderStart = True + if not Line.startswith(DT.TAB_COMMENT_EDK1_SPLIT) and HeaderStart and not HeaderEnd: + HeaderEnd = True + if Line.startswith(DT.TAB_COMMENT_EDK1_SPLIT) and HeaderStart and not HeaderEnd and FirstGenHeader: + self.UniFileHeader += Line + '\r\n' + continue + + # + # Use unique identifier + # + FindFlag = -1 + LineCount = 0 + MultiLineFeedExits = False + # + # 0: initial value + # 1: single String entry exist + # 2: line feed exist under the some single String entry + # + StringEntryExistsFlag = 0 + for Line in FileIn: + Line = FileIn[LineCount] + LineCount += 1 + Line = Line.strip() + # + # Ignore comment line and empty line + # + if Line == u'' or Line.startswith(u'//'): + # + # Change the single line String entry flag status + # + if StringEntryExistsFlag == 1: + StringEntryExistsFlag = 2 + # + # If the '#string' line and the '#language' line are not in the same line, + # there should be only one line feed character between them + # + if MultiLineFeedExits: + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path) + continue + + MultiLineFeedExits = False + # + # Process comment embedded in string define lines + # + FindFlag = Line.find(u'//') + if FindFlag != -1 and Line.find(u'//') < Line.find(u'"'): + Line = Line.replace(Line[FindFlag:], u' ') + if FileIn[LineCount].strip().startswith('#language'): + Line = Line + FileIn[LineCount] + FileIn[LineCount-1] = Line + FileIn[LineCount] = '\r\n' + LineCount -= 1 + for Index in range (LineCount + 1, len (FileIn) - 1): + if (Index == len(FileIn) -1): + FileIn[Index] = '\r\n' + else: + FileIn[Index] = FileIn[Index + 1] + continue + CommIndex = GetCharIndexOutStr(u'/', Line) + if CommIndex > -1: + if (len(Line) - 1) > CommIndex: + if Line[CommIndex+1] == u'/': + Line = Line[:CommIndex].strip() + else: + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path) + else: + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path) + + Line = Line.replace(UNICODE_WIDE_CHAR, WIDE_CHAR) + Line = Line.replace(UNICODE_NARROW_CHAR, NARROW_CHAR) + Line = Line.replace(UNICODE_NON_BREAKING_CHAR, NON_BREAKING_CHAR) + + Line = Line.replace(u'\\\\', u'\u0006') + Line = Line.replace(u'\\r\\n', CR + LF) + Line = Line.replace(u'\\n', CR + LF) + Line = Line.replace(u'\\r', CR) + Line = Line.replace(u'\\t', u'\t') + Line = Line.replace(u'''\"''', u'''"''') + Line = Line.replace(u'\t', u' ') + Line = Line.replace(u'\u0006', u'\\') + + # + # Check if single line has correct '"' + # + if Line.startswith(u'#string') and Line.find(u'#language') > -1 and Line.find('"') > Line.find(u'#language'): + if not Line.endswith('"'): + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, + ExtraData='''The line %s misses '"' at the end of it in file %s''' + % (LineCount, File.Path)) + + # + # Between Name entry and Language entry can not contain line feed + # + if Line.startswith(u'#string') and Line.find(u'#language') == -1: + MultiLineFeedExits = True + + if Line.startswith(u'#string') and Line.find(u'#language') > 0 and Line.find(u'"') < 0: + MultiLineFeedExits = True + + # + # Between Language entry and String entry can not contain line feed + # + if Line.startswith(u'#language') and len(Line.split()) == 2: + MultiLineFeedExits = True + + # + # Check the situation that there only has one '"' for the language entry + # + if Line.startswith(u'#string') and Line.find(u'#language') > 0 and Line.count(u'"') == 1: + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, + ExtraData='''The line %s misses '"' at the end of it in file %s''' + % (LineCount, File.Path)) + + # + # Check the situation that there has more than 2 '"' for the language entry + # + if Line.startswith(u'#string') and Line.find(u'#language') > 0 and Line.replace(u'\\"', '').count(u'"') > 2: + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, + ExtraData='''The line %s has more than 2 '"' for language entry in file %s''' + % (LineCount, File.Path)) + + # + # Between two String entry, can not contain line feed + # + if Line.startswith(u'"'): + if StringEntryExistsFlag == 2: + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, + Message=ST.ERR_UNIPARSE_LINEFEED_UP_EXIST % Line, ExtraData=File.Path) + + StringEntryExistsFlag = 1 + if not Line.endswith('"'): + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, + ExtraData='''The line %s misses '"' at the end of it in file %s''' + % (LineCount, File.Path)) + + # + # Check the situation that there has more than 2 '"' for the language entry + # + if Line.strip() and Line.replace(u'\\"', '').count(u'"') > 2: + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, + ExtraData='''The line %s has more than 2 '"' for language entry in file %s''' + % (LineCount, File.Path)) + + elif Line.startswith(u'#language'): + if StringEntryExistsFlag == 2: + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, + Message=ST.ERR_UNI_MISS_STRING_ENTRY % Line, ExtraData=File.Path) + StringEntryExistsFlag = 0 + else: + StringEntryExistsFlag = 0 + + Lines.append(Line) + + # + # Convert string def format as below + # + # #string MY_STRING_1 + # #language eng + # "My first English string line 1" + # "My first English string line 2" + # #string MY_STRING_1 + # #language spa + # "Mi segunda secuencia 1" + # "Mi segunda secuencia 2" + # + + if not IsIncludeFile and not Lines: + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \ + Message=ST.ERR_UNIPARSE_NO_SECTION_EXIST, \ + ExtraData=File.Path) + + NewLines = [] + StrName = u'' + ExistStrNameList = [] + for Line in Lines: + if StrName and not StrName.split()[1].startswith(DT.TAB_STR_TOKENCNAME + DT.TAB_UNDERLINE_SPLIT): + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \ + Message=ST.ERR_UNIPARSE_STRNAME_FORMAT_ERROR % StrName.split()[1], \ + ExtraData=File.Path) + + if StrName and len(StrName.split()[1].split(DT.TAB_UNDERLINE_SPLIT)) == 4: + StringTokenList = StrName.split()[1].split(DT.TAB_UNDERLINE_SPLIT) + if (StringTokenList[3].upper() in [DT.TAB_STR_TOKENPROMPT, DT.TAB_STR_TOKENHELP] and \ + StringTokenList[3] not in [DT.TAB_STR_TOKENPROMPT, DT.TAB_STR_TOKENHELP]) or \ + (StringTokenList[2].upper() == DT.TAB_STR_TOKENERR and StringTokenList[2] != DT.TAB_STR_TOKENERR): + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \ + Message=ST.ERR_UNIPARSE_STRTOKEN_FORMAT_ERROR % StrName.split()[1], \ + ExtraData=File.Path) + + if Line.count(u'#language') > 1: + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \ + Message=ST.ERR_UNIPARSE_SEP_LANGENTRY_LINE % Line, \ + ExtraData=File.Path) + + if Line.startswith(u'//'): + continue + elif Line.startswith(u'#langdef'): + if len(Line.split()) == 2: + NewLines.append(Line) + continue + elif len(Line.split()) > 2 and Line.find(u'"') > 0: + NewLines.append(Line[:Line.find(u'"')].strip()) + NewLines.append(Line[Line.find(u'"'):]) + else: + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path) + elif Line.startswith(u'#string'): + if len(Line.split()) == 2: + StrName = Line + if StrName: + if StrName.split()[1] not in ExistStrNameList: + ExistStrNameList.append(StrName.split()[1].strip()) + elif StrName.split()[1] in [DT.TAB_INF_ABSTRACT, DT.TAB_INF_DESCRIPTION, \ + DT.TAB_INF_BINARY_ABSTRACT, DT.TAB_INF_BINARY_DESCRIPTION, \ + DT.TAB_DEC_PACKAGE_ABSTRACT, DT.TAB_DEC_PACKAGE_DESCRIPTION, \ + DT.TAB_DEC_BINARY_ABSTRACT, DT.TAB_DEC_BINARY_DESCRIPTION]: + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \ + Message=ST.ERR_UNIPARSE_MULTI_ENTRY_EXIST % StrName.split()[1], \ + ExtraData=File.Path) + continue + elif len(Line.split()) == 4 and Line.find(u'#language') > 0: + if Line[Line.find(u'#language')-1] != ' ' or \ + Line[Line.find(u'#language')+len(u'#language')] != u' ': + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path) + + if Line.find(u'"') > 0: + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path) + + StrName = Line.split()[0] + u' ' + Line.split()[1] + if StrName: + if StrName.split()[1] not in ExistStrNameList: + ExistStrNameList.append(StrName.split()[1].strip()) + elif StrName.split()[1] in [DT.TAB_INF_ABSTRACT, DT.TAB_INF_DESCRIPTION, \ + DT.TAB_INF_BINARY_ABSTRACT, DT.TAB_INF_BINARY_DESCRIPTION, \ + DT.TAB_DEC_PACKAGE_ABSTRACT, DT.TAB_DEC_PACKAGE_DESCRIPTION, \ + DT.TAB_DEC_BINARY_ABSTRACT, DT.TAB_DEC_BINARY_DESCRIPTION]: + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \ + Message=ST.ERR_UNIPARSE_MULTI_ENTRY_EXIST % StrName.split()[1], \ + ExtraData=File.Path) + if IsIncludeFile: + if StrName not in NewLines: + NewLines.append((Line[:Line.find(u'#language')]).strip()) + else: + NewLines.append((Line[:Line.find(u'#language')]).strip()) + NewLines.append((Line[Line.find(u'#language'):]).strip()) + elif len(Line.split()) > 4 and Line.find(u'#language') > 0 and Line.find(u'"') > 0: + if Line[Line.find(u'#language')-1] != u' ' or \ + Line[Line.find(u'#language')+len(u'#language')] != u' ': + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path) + + if Line[Line.find(u'"')-1] != u' ': + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path) + + StrName = Line.split()[0] + u' ' + Line.split()[1] + if StrName: + if StrName.split()[1] not in ExistStrNameList: + ExistStrNameList.append(StrName.split()[1].strip()) + elif StrName.split()[1] in [DT.TAB_INF_ABSTRACT, DT.TAB_INF_DESCRIPTION, \ + DT.TAB_INF_BINARY_ABSTRACT, DT.TAB_INF_BINARY_DESCRIPTION, \ + DT.TAB_DEC_PACKAGE_ABSTRACT, DT.TAB_DEC_PACKAGE_DESCRIPTION, \ + DT.TAB_DEC_BINARY_ABSTRACT, DT.TAB_DEC_BINARY_DESCRIPTION]: + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \ + Message=ST.ERR_UNIPARSE_MULTI_ENTRY_EXIST % StrName.split()[1], \ + ExtraData=File.Path) + if IsIncludeFile: + if StrName not in NewLines: + NewLines.append((Line[:Line.find(u'#language')]).strip()) + else: + NewLines.append((Line[:Line.find(u'#language')]).strip()) + NewLines.append((Line[Line.find(u'#language'):Line.find(u'"')]).strip()) + NewLines.append((Line[Line.find(u'"'):]).strip()) + else: + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path) + elif Line.startswith(u'#language'): + if len(Line.split()) == 2: + if IsIncludeFile: + if StrName not in NewLines: + NewLines.append(StrName) + else: + NewLines.append(StrName) + NewLines.append(Line) + elif len(Line.split()) > 2 and Line.find(u'"') > 0: + if IsIncludeFile: + if StrName not in NewLines: + NewLines.append(StrName) + else: + NewLines.append(StrName) + NewLines.append((Line[:Line.find(u'"')]).strip()) + NewLines.append((Line[Line.find(u'"'):]).strip()) + else: + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path) + elif Line.startswith(u'"'): + if u'#string' in Line or u'#language' in Line: + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path) + NewLines.append(Line) + else: + print(Line) + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, ExtraData=File.Path) + + if StrName and not StrName.split()[1].startswith(u'STR_'): + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \ + Message=ST.ERR_UNIPARSE_STRNAME_FORMAT_ERROR % StrName.split()[1], \ + ExtraData=File.Path) + + if StrName and not NewLines: + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \ + Message=ST.ERR_UNI_MISS_LANGENTRY % StrName, \ + ExtraData=File.Path) + + # + # Check Abstract, Description, BinaryAbstract and BinaryDescription order, + # should be Abstract, Description, BinaryAbstract, BinaryDescription + AbstractPosition = -1 + DescriptionPosition = -1 + BinaryAbstractPosition = -1 + BinaryDescriptionPosition = -1 + for StrName in ExistStrNameList: + if DT.TAB_HEADER_ABSTRACT.upper() in StrName: + if 'BINARY' in StrName: + BinaryAbstractPosition = ExistStrNameList.index(StrName) + else: + AbstractPosition = ExistStrNameList.index(StrName) + if DT.TAB_HEADER_DESCRIPTION.upper() in StrName: + if 'BINARY' in StrName: + BinaryDescriptionPosition = ExistStrNameList.index(StrName) + else: + DescriptionPosition = ExistStrNameList.index(StrName) + + OrderList = sorted([AbstractPosition, DescriptionPosition]) + BinaryOrderList = sorted([BinaryAbstractPosition, BinaryDescriptionPosition]) + Min = OrderList[0] + Max = OrderList[1] + BinaryMin = BinaryOrderList[0] + BinaryMax = BinaryOrderList[1] + if BinaryDescriptionPosition > -1: + if not(BinaryDescriptionPosition == BinaryMax and BinaryAbstractPosition == BinaryMin and \ + BinaryMax > Max): + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \ + Message=ST.ERR_UNIPARSE_ENTRY_ORDER_WRONG, \ + ExtraData=File.Path) + elif BinaryAbstractPosition > -1: + if not(BinaryAbstractPosition > Max): + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \ + Message=ST.ERR_UNIPARSE_ENTRY_ORDER_WRONG, \ + ExtraData=File.Path) + + if DescriptionPosition > -1: + if not(DescriptionPosition == Max and AbstractPosition == Min and \ + DescriptionPosition > AbstractPosition): + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, \ + Message=ST.ERR_UNIPARSE_ENTRY_ORDER_WRONG, \ + ExtraData=File.Path) + + if not self.UniFileHeader: + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, + Message = ST.ERR_NO_SOURCE_HEADER, + ExtraData=File.Path) + + return NewLines + + # + # Load a .uni file + # + def LoadUniFile(self, File = None): + if File is None: + EdkLogger.Error("Unicode File Parser", + ToolError.PARSER_ERROR, + Message='No unicode file is given', + ExtraData=File.Path) + + self.File = File + + # + # Process special char in file + # + Lines = self.PreProcess(File) + + # + # Get Unicode Information + # + for IndexI in range(len(Lines)): + Line = Lines[IndexI] + if (IndexI + 1) < len(Lines): + SecondLine = Lines[IndexI + 1] + if (IndexI + 2) < len(Lines): + ThirdLine = Lines[IndexI + 2] + + # + # Get Language def information + # + if Line.find(u'#langdef ') >= 0: + self.GetLangDef(File, Line + u' ' + SecondLine) + continue + + Name = '' + Language = '' + Value = '' + CombineToken = False + # + # Get string def information format as below + # + # #string MY_STRING_1 + # #language eng + # "My first English string line 1" + # "My first English string line 2" + # #string MY_STRING_1 + # #language spa + # "Mi segunda secuencia 1" + # "Mi segunda secuencia 2" + # + if Line.find(u'#string ') >= 0 and Line.find(u'#language ') < 0 and \ + SecondLine.find(u'#string ') < 0 and SecondLine.find(u'#language ') >= 0 and \ + ThirdLine.find(u'#string ') < 0 and ThirdLine.find(u'#language ') < 0: + if Line.find('"') > 0 or SecondLine.find('"') > 0: + EdkLogger.Error("Unicode File Parser", ToolError.FORMAT_INVALID, + Message=ST.ERR_UNIPARSE_DBLQUOTE_UNMATCHED, + ExtraData=File.Path) + + Name = Line[Line.find(u'#string ') + len(u'#string ') : ].strip(' ') + Language = SecondLine[SecondLine.find(u'#language ') + len(u'#language ') : ].strip(' ') + for IndexJ in range(IndexI + 2, len(Lines)): + if Lines[IndexJ].find(u'#string ') < 0 and Lines[IndexJ].find(u'#language ') < 0 and \ + Lines[IndexJ].strip().startswith(u'"') and Lines[IndexJ].strip().endswith(u'"'): + if Lines[IndexJ][-2] == ' ': + CombineToken = True + if CombineToken: + if Lines[IndexJ].strip()[1:-1].strip(): + Value = Value + Lines[IndexJ].strip()[1:-1].rstrip() + ' ' + else: + Value = Value + Lines[IndexJ].strip()[1:-1] + CombineToken = False + else: + Value = Value + Lines[IndexJ].strip()[1:-1] + '\r\n' + else: + IndexI = IndexJ + break + if Value.endswith('\r\n'): + Value = Value[: Value.rfind('\r\n')] + Language = GetLanguageCode(Language, self.IsCompatibleMode, self.File) + self.AddStringToList(Name, Language, Value) + continue + + # + # Load multiple .uni files + # + def LoadUniFiles(self, FileList): + if len(FileList) > 0: + for File in FileList: + FilePath = File.Path.strip() + if FilePath.endswith('.uni') or FilePath.endswith('.UNI') or FilePath.endswith('.Uni'): + self.LoadUniFile(File) + + # + # Add a string to list + # + def AddStringToList(self, Name, Language, Value, Token = 0, Referenced = False, UseOtherLangDef = '', Index = -1): + for LangNameItem in self.LanguageDef: + if Language == LangNameItem[0]: + break + + if Language not in self.OrderedStringList: + self.OrderedStringList[Language] = [] + self.OrderedStringDict[Language] = {} + + IsAdded = True + if Name in self.OrderedStringDict[Language]: + IsAdded = False + if Value is not None: + ItemIndexInList = self.OrderedStringDict[Language][Name] + Item = self.OrderedStringList[Language][ItemIndexInList] + Item.UpdateValue(Value) + Item.UseOtherLangDef = '' + + if IsAdded: + Token = len(self.OrderedStringList[Language]) + if Index == -1: + self.OrderedStringList[Language].append(StringDefClassObject(Name, + Value, + Referenced, + Token, + UseOtherLangDef)) + self.OrderedStringDict[Language][Name] = Token + for LangName in self.LanguageDef: + # + # New STRING token will be added into all language string lists. + # so that the unique STRING identifier is reserved for all languages in the package list. + # + if LangName[0] != Language: + if UseOtherLangDef != '': + OtherLangDef = UseOtherLangDef + else: + OtherLangDef = Language + self.OrderedStringList[LangName[0]].append(StringDefClassObject(Name, + '', + Referenced, + Token, + OtherLangDef)) + self.OrderedStringDict[LangName[0]][Name] = len(self.OrderedStringList[LangName[0]]) - 1 + else: + self.OrderedStringList[Language].insert(Index, StringDefClassObject(Name, + Value, + Referenced, + Token, + UseOtherLangDef)) + self.OrderedStringDict[Language][Name] = Index + + # + # Set the string as referenced + # + def SetStringReferenced(self, Name): + # + # String stoken are added in the same order in all language string lists. + # So, only update the status of string stoken in first language string list. + # + Lang = self.LanguageDef[0][0] + if Name in self.OrderedStringDict[Lang]: + ItemIndexInList = self.OrderedStringDict[Lang][Name] + Item = self.OrderedStringList[Lang][ItemIndexInList] + Item.Referenced = True + + # + # Search the string in language definition by Name + # + def FindStringValue(self, Name, Lang): + if Name in self.OrderedStringDict[Lang]: + ItemIndexInList = self.OrderedStringDict[Lang][Name] + return self.OrderedStringList[Lang][ItemIndexInList] + + return None + + # + # Search the string in language definition by Token + # + def FindByToken(self, Token, Lang): + for Item in self.OrderedStringList[Lang]: + if Item.Token == Token: + return Item + + return None + + # + # Re-order strings and re-generate tokens + # + def ReToken(self): + if len(self.LanguageDef) == 0: + return None + # + # Retoken all language strings according to the status of string stoken in the first language string. + # + FirstLangName = self.LanguageDef[0][0] + + # Convert the OrderedStringList to be OrderedStringListByToken in order to faciliate future search by token + for LangNameItem in self.LanguageDef: + self.OrderedStringListByToken[LangNameItem[0]] = {} + + # + # Use small token for all referred string stoken. + # + RefToken = 0 + for Index in range (0, len (self.OrderedStringList[FirstLangName])): + FirstLangItem = self.OrderedStringList[FirstLangName][Index] + if FirstLangItem.Referenced == True: + for LangNameItem in self.LanguageDef: + LangName = LangNameItem[0] + OtherLangItem = self.OrderedStringList[LangName][Index] + OtherLangItem.Referenced = True + OtherLangItem.Token = RefToken + self.OrderedStringListByToken[LangName][OtherLangItem.Token] = OtherLangItem + RefToken = RefToken + 1 + + # + # Use big token for all unreferred string stoken. + # + UnRefToken = 0 + for Index in range (0, len (self.OrderedStringList[FirstLangName])): + FirstLangItem = self.OrderedStringList[FirstLangName][Index] + if FirstLangItem.Referenced == False: + for LangNameItem in self.LanguageDef: + LangName = LangNameItem[0] + OtherLangItem = self.OrderedStringList[LangName][Index] + OtherLangItem.Token = RefToken + UnRefToken + self.OrderedStringListByToken[LangName][OtherLangItem.Token] = OtherLangItem + UnRefToken = UnRefToken + 1 + + # + # Show the instance itself + # + def ShowMe(self): + print(self.LanguageDef) + #print self.OrderedStringList + for Item in self.OrderedStringList: + print(Item) + for Member in self.OrderedStringList[Item]: + print(str(Member)) + + # + # Read content from '!include' UNI file + # + def ReadIncludeUNIfile(self, FilaPath): + if self.File: + pass + + if not os.path.exists(FilaPath) or not os.path.isfile(FilaPath): + EdkLogger.Error("Unicode File Parser", + ToolError.FILE_NOT_FOUND, + ExtraData=FilaPath) + try: + FileIn = codecs.open(FilaPath, mode='rb', encoding='utf_8').readlines() + except UnicodeError as Xstr: + FileIn = codecs.open(FilaPath, mode='rb', encoding='utf_16').readlines() + except UnicodeError: + FileIn = codecs.open(FilaPath, mode='rb', encoding='utf_16_le').readlines() + except: + EdkLogger.Error("Unicode File Parser", ToolError.FILE_OPEN_FAILURE, ExtraData=FilaPath) + return FileIn + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/Xml/XmlRoutines.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/Xml/XmlRoutines.py new file mode 100755 index 00000000..8ef315ad --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/Xml/XmlRoutines.py @@ -0,0 +1,223 @@ +## @file +# This is an XML API that uses a syntax similar to XPath, but it is written in +# standard python so that no extra python packages are required to use it. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +XmlRoutines +''' + +## +# Import Modules +# +import xml.dom.minidom +import re +import codecs +from Logger.ToolError import PARSER_ERROR +import Logger.Log as Logger + +## Create a element of XML +# +# @param Name +# @param String +# @param NodeList +# @param AttributeList +# +def CreateXmlElement(Name, String, NodeList, AttributeList): + Doc = xml.dom.minidom.Document() + Element = Doc.createElement(Name) + if String != '' and String is not None: + Element.appendChild(Doc.createTextNode(String)) + + for Item in NodeList: + if isinstance(Item, type([])): + Key = Item[0] + Value = Item[1] + if Key != '' and Key is not None and Value != '' and Value is not None: + Node = Doc.createElement(Key) + Node.appendChild(Doc.createTextNode(Value)) + Element.appendChild(Node) + else: + Element.appendChild(Item) + for Item in AttributeList: + Key = Item[0] + Value = Item[1] + if Key != '' and Key is not None and Value != '' and Value is not None: + Element.setAttribute(Key, Value) + + return Element + +## Get a list of XML nodes using XPath style syntax. +# +# Return a list of XML DOM nodes from the root Dom specified by XPath String. +# If the input Dom or String is not valid, then an empty list is returned. +# +# @param Dom The root XML DOM node. +# @param String A XPath style path. +# +def XmlList(Dom, String): + if String is None or String == "" or Dom is None or Dom == "": + return [] + if Dom.nodeType == Dom.DOCUMENT_NODE: + Dom = Dom.documentElement + if String[0] == "/": + String = String[1:] + TagList = String.split('/') + Nodes = [Dom] + Index = 0 + End = len(TagList) - 1 + while Index <= End: + ChildNodes = [] + for Node in Nodes: + if Node.nodeType == Node.ELEMENT_NODE and Node.tagName == \ + TagList[Index]: + if Index < End: + ChildNodes.extend(Node.childNodes) + else: + ChildNodes.append(Node) + Nodes = ChildNodes + ChildNodes = [] + Index += 1 + + return Nodes + + +## Get a single XML node using XPath style syntax. +# +# Return a single XML DOM node from the root Dom specified by XPath String. +# If the input Dom or String is not valid, then an empty string is returned. +# +# @param Dom The root XML DOM node. +# @param String A XPath style path. +# +def XmlNode(Dom, String): + if String is None or String == "" or Dom is None or Dom == "": + return None + if Dom.nodeType == Dom.DOCUMENT_NODE: + Dom = Dom.documentElement + if String[0] == "/": + String = String[1:] + TagList = String.split('/') + Index = 0 + End = len(TagList) - 1 + ChildNodes = [Dom] + while Index <= End: + for Node in ChildNodes: + if Node.nodeType == Node.ELEMENT_NODE and \ + Node.tagName == TagList[Index]: + if Index < End: + ChildNodes = Node.childNodes + else: + return Node + break + Index += 1 + return None + + +## Get a single XML element using XPath style syntax. +# +# Return a single XML element from the root Dom specified by XPath String. +# If the input Dom or String is not valid, then an empty string is returned. +# +# @param Dom The root XML DOM object. +# @param Strin A XPath style path. +# +def XmlElement(Dom, String): + try: + return XmlNode(Dom, String).firstChild.data.strip() + except BaseException: + return "" + +## Get a single XML element using XPath style syntax. +# +# Similar with XmlElement, but do not strip all the leading and tailing space +# and newline, instead just remove the newline and spaces introduced by +# toprettyxml() +# +# @param Dom The root XML DOM object. +# @param Strin A XPath style path. +# +def XmlElement2(Dom, String): + try: + HelpStr = XmlNode(Dom, String).firstChild.data + gRemovePrettyRe = re.compile(r"""(?:(\n *) )(.*)\1""", re.DOTALL) + HelpStr = re.sub(gRemovePrettyRe, r"\2", HelpStr) + return HelpStr + except BaseException: + return "" + + +## Get a single XML element of the current node. +# +# Return a single XML element specified by the current root Dom. +# If the input Dom is not valid, then an empty string is returned. +# +# @param Dom The root XML DOM object. +# +def XmlElementData(Dom): + try: + return Dom.firstChild.data.strip() + except BaseException: + return "" + + +## Get a list of XML elements using XPath style syntax. +# +# Return a list of XML elements from the root Dom specified by XPath String. +# If the input Dom or String is not valid, then an empty list is returned. +# +# @param Dom The root XML DOM object. +# @param String A XPath style path. +# +def XmlElementList(Dom, String): + return list(map(XmlElementData, XmlList(Dom, String))) + + +## Get the XML attribute of the current node. +# +# Return a single XML attribute named Attribute from the current root Dom. +# If the input Dom or Attribute is not valid, then an empty string is returned. +# +# @param Dom The root XML DOM object. +# @param Attribute The name of Attribute. +# +def XmlAttribute(Dom, Attribute): + try: + return Dom.getAttribute(Attribute) + except BaseException: + return '' + + +## Get the XML node name of the current node. +# +# Return a single XML node name from the current root Dom. +# If the input Dom is not valid, then an empty string is returned. +# +# @param Dom The root XML DOM object. +# +def XmlNodeName(Dom): + try: + return Dom.nodeName.strip() + except BaseException: + return '' + +## Parse an XML file. +# +# Parse the input XML file named FileName and return a XML DOM it stands for. +# If the input File is not a valid XML file, then an empty string is returned. +# +# @param FileName The XML file name. +# +def XmlParseFile(FileName): + try: + XmlFile = codecs.open(FileName, 'rb') + Dom = xml.dom.minidom.parse(XmlFile) + XmlFile.close() + return Dom + except BaseException as XExcept: + XmlFile.close() + Logger.Error('\nUPT', PARSER_ERROR, XExcept, File=FileName, RaiseError=True) diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/Xml/__init__.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/Xml/__init__.py new file mode 100644 index 00000000..a800a619 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/Xml/__init__.py @@ -0,0 +1,14 @@ +## @file +# Python 'Library' package initialization file. +# +# This file is required to make Python interpreter treat the directory +# as containing package. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +Xml +''' diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/__init__.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/__init__.py new file mode 100644 index 00000000..fa602a2d --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Library/__init__.py @@ -0,0 +1,14 @@ +## @file +# Python 'Library' package initialization file. +# +# This file is required to make Python interpreter treat the directory +# as containing package. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +Library +''' diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Logger/Log.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Logger/Log.py new file mode 100755 index 00000000..4f9b0b6c --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Logger/Log.py @@ -0,0 +1,319 @@ +## @file +# This file implements the log mechanism for Python tools. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +Logger +''' + +## Import modules +from sys import argv +from sys import stdout +from sys import stderr +import os.path +from os import remove +from logging import getLogger +from logging import Formatter +from logging import StreamHandler +from logging import FileHandler +from traceback import extract_stack + +from Logger.ToolError import FatalError +from Logger.ToolError import WARNING_AS_ERROR +from Logger.ToolError import gERROR_MESSAGE +from Logger.ToolError import UNKNOWN_ERROR +from Library import GlobalData + +# +# Log level constants +# +DEBUG_0 = 1 +DEBUG_1 = 2 +DEBUG_2 = 3 +DEBUG_3 = 4 +DEBUG_4 = 5 +DEBUG_5 = 6 +DEBUG_6 = 7 +DEBUG_7 = 8 +DEBUG_8 = 9 +DEBUG_9 = 10 +VERBOSE = 15 +INFO = 20 +WARN = 30 +QUIET = 40 +QUIET_1 = 41 +ERROR = 50 +SILENT = 60 + +IS_RAISE_ERROR = True +SUPRESS_ERROR = False + +# +# Tool name +# +_TOOL_NAME = os.path.basename(argv[0]) +# +# For validation purpose +# +_LOG_LEVELS = [DEBUG_0, DEBUG_1, DEBUG_2, DEBUG_3, DEBUG_4, DEBUG_5, DEBUG_6, \ + DEBUG_7, DEBUG_8, DEBUG_9, VERBOSE, WARN, INFO, ERROR, QUIET, \ + QUIET_1, SILENT] +# +# For DEBUG level (All DEBUG_0~9 are applicable) +# +_DEBUG_LOGGER = getLogger("tool_debug") +_DEBUG_FORMATTER = Formatter("[%(asctime)s.%(msecs)d]: %(message)s", \ + datefmt="%H:%M:%S") +# +# For VERBOSE, INFO, WARN level +# +_INFO_LOGGER = getLogger("tool_info") +_INFO_FORMATTER = Formatter("%(message)s") +# +# For ERROR level +# +_ERROR_LOGGER = getLogger("tool_error") +_ERROR_FORMATTER = Formatter("%(message)s") + +# +# String templates for ERROR/WARN/DEBUG log message +# +_ERROR_MESSAGE_TEMPLATE = \ +('\n\n%(tool)s...\n%(file)s(%(line)s): error %(errorcode)04X: %(msg)s\n\t%(extra)s') + +__ERROR_MESSAGE_TEMPLATE_WITHOUT_FILE = \ +'\n\n%(tool)s...\n : error %(errorcode)04X: %(msg)s\n\t%(extra)s' + +_WARNING_MESSAGE_TEMPLATE = '%(tool)s...\n%(file)s(%(line)s): warning: %(msg)s' +_WARNING_MESSAGE_TEMPLATE_WITHOUT_FILE = '%(tool)s: : warning: %(msg)s' +_DEBUG_MESSAGE_TEMPLATE = '%(file)s(%(line)s): debug: \n %(msg)s' + + +# +# Log INFO message +# +#Info = _INFO_LOGGER.info + +def Info(msg, *args, **kwargs): + _INFO_LOGGER.info(msg, *args, **kwargs) + +# +# Log information which should be always put out +# +def Quiet(msg, *args, **kwargs): + _ERROR_LOGGER.error(msg, *args, **kwargs) + +## Log debug message +# +# @param Level DEBUG level (DEBUG0~9) +# @param Message Debug information +# @param ExtraData More information associated with "Message" +# +def Debug(Level, Message, ExtraData=None): + if _DEBUG_LOGGER.level > Level: + return + if Level > DEBUG_9: + return + # + # Find out the caller method information + # + CallerStack = extract_stack()[-2] + TemplateDict = { + "file" : CallerStack[0], + "line" : CallerStack[1], + "msg" : Message, + } + + if ExtraData is not None: + LogText = _DEBUG_MESSAGE_TEMPLATE % TemplateDict + "\n %s" % ExtraData + else: + LogText = _DEBUG_MESSAGE_TEMPLATE % TemplateDict + + _DEBUG_LOGGER.log(Level, LogText) + +## Log verbose message +# +# @param Message Verbose information +# +def Verbose(Message): + return _INFO_LOGGER.log(VERBOSE, Message) + +## Log warning message +# +# Warning messages are those which might be wrong but won't fail the tool. +# +# @param ToolName The name of the tool. If not given, the name of caller +# method will be used. +# @param Message Warning information +# @param File The name of file which caused the warning. +# @param Line The line number in the "File" which caused the warning. +# @param ExtraData More information associated with "Message" +# +def Warn(ToolName, Message, File=None, Line=None, ExtraData=None): + if _INFO_LOGGER.level > WARN: + return + # + # if no tool name given, use caller's source file name as tool name + # + if ToolName is None or ToolName == "": + ToolName = os.path.basename(extract_stack()[-2][0]) + + if Line is None: + Line = "..." + else: + Line = "%d" % Line + + TemplateDict = { + "tool" : ToolName, + "file" : File, + "line" : Line, + "msg" : Message, + } + + if File is not None: + LogText = _WARNING_MESSAGE_TEMPLATE % TemplateDict + else: + LogText = _WARNING_MESSAGE_TEMPLATE_WITHOUT_FILE % TemplateDict + + if ExtraData is not None: + LogText += "\n %s" % ExtraData + + _INFO_LOGGER.log(WARN, LogText) + # + # Raise an exception if indicated + # + if GlobalData.gWARNING_AS_ERROR == True: + raise FatalError(WARNING_AS_ERROR) + +## Log ERROR message +# +# Once an error messages is logged, the tool's execution will be broken by +# raising an exception. If you don't want to break the execution later, you +# can give "RaiseError" with "False" value. +# +# @param ToolName The name of the tool. If not given, the name of caller +# method will be used. +# @param ErrorCode The error code +# @param Message Warning information +# @param File The name of file which caused the error. +# @param Line The line number in the "File" which caused the warning. +# @param ExtraData More information associated with "Message" +# @param RaiseError Raise an exception to break the tool's execution if +# it's True. This is the default behavior. +# +def Error(ToolName, ErrorCode, Message=None, File=None, Line=None, \ + ExtraData=None, RaiseError=IS_RAISE_ERROR): + if ToolName: + pass + if Line is None: + Line = "..." + else: + Line = "%d" % Line + + if Message is None: + if ErrorCode in gERROR_MESSAGE: + Message = gERROR_MESSAGE[ErrorCode] + else: + Message = gERROR_MESSAGE[UNKNOWN_ERROR] + + if ExtraData is None: + ExtraData = "" + + TemplateDict = { + "tool" : _TOOL_NAME, + "file" : File, + "line" : Line, + "errorcode" : ErrorCode, + "msg" : Message, + "extra" : ExtraData + } + + if File is not None: + LogText = _ERROR_MESSAGE_TEMPLATE % TemplateDict + else: + LogText = __ERROR_MESSAGE_TEMPLATE_WITHOUT_FILE % TemplateDict + + if not SUPRESS_ERROR: + _ERROR_LOGGER.log(ERROR, LogText) + if RaiseError: + raise FatalError(ErrorCode) + + +## Initialize log system +# +def Initialize(): + # + # Since we use different format to log different levels of message into + # different place (stdout or stderr), we have to use different "Logger" + # objects to do this. + # + # For DEBUG level (All DEBUG_0~9 are applicable) + _DEBUG_LOGGER.setLevel(INFO) + _DebugChannel = StreamHandler(stdout) + _DebugChannel.setFormatter(_DEBUG_FORMATTER) + _DEBUG_LOGGER.addHandler(_DebugChannel) + # + # For VERBOSE, INFO, WARN level + # + _INFO_LOGGER.setLevel(INFO) + _InfoChannel = StreamHandler(stdout) + _InfoChannel.setFormatter(_INFO_FORMATTER) + _INFO_LOGGER.addHandler(_InfoChannel) + # + # For ERROR level + # + _ERROR_LOGGER.setLevel(INFO) + _ErrorCh = StreamHandler(stderr) + _ErrorCh.setFormatter(_ERROR_FORMATTER) + _ERROR_LOGGER.addHandler(_ErrorCh) + + +## Set log level +# +# @param Level One of log level in _LogLevel +# +def SetLevel(Level): + if Level not in _LOG_LEVELS: + Info("Not supported log level (%d). Use default level instead." % \ + Level) + Level = INFO + _DEBUG_LOGGER.setLevel(Level) + _INFO_LOGGER.setLevel(Level) + _ERROR_LOGGER.setLevel(Level) + +## Get current log level +# +def GetLevel(): + return _INFO_LOGGER.getEffectiveLevel() + +## Raise up warning as error +# +def SetWarningAsError(): + GlobalData.gWARNING_AS_ERROR = True + +## Specify a file to store the log message as well as put on console +# +# @param LogFile The file path used to store the log message +# +def SetLogFile(LogFile): + if os.path.exists(LogFile): + remove(LogFile) + + _Ch = FileHandler(LogFile) + _Ch.setFormatter(_DEBUG_FORMATTER) + _DEBUG_LOGGER.addHandler(_Ch) + + _Ch = FileHandler(LogFile) + _Ch.setFormatter(_INFO_FORMATTER) + _INFO_LOGGER.addHandler(_Ch) + + _Ch = FileHandler(LogFile) + _Ch.setFormatter(_ERROR_FORMATTER) + _ERROR_LOGGER.addHandler(_Ch) + + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Logger/StringTable.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Logger/StringTable.py new file mode 100644 index 00000000..8cdbb125 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Logger/StringTable.py @@ -0,0 +1,860 @@ +## @file +# This file is used to define strings used in the UPT tool +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## +""" +This file contains user visible strings in a format that can be used for +localization +""" + +import gettext + +# +# string table starts here... +# + +## strings are classified as following types +# MSG_...: it is a message string +# ERR_...: it is a error string +# WRN_...: it is a warning string +# HLP_...: it is a help string +# + +_ = gettext.gettext + +MSG_USAGE_STRING = _("\n" + "UEFI Packaging Tool (UEFIPT)\n" + "%prog [options]" + ) + +## +# Version and Copyright +# +MSG_VERSION_NUMBER = _("1.1") +MSG_VERSION = _("UEFI Packaging Tool (UEFIPT) - Revision " + \ + MSG_VERSION_NUMBER) +MSG_COPYRIGHT = _("Copyright (c) 2011 - 2018 Intel Corporation All Rights Reserved.") +MSG_VERSION_COPYRIGHT = _("\n %s\n %s" % (MSG_VERSION, MSG_COPYRIGHT)) +MSG_USAGE = _("%s [options]\n%s" % ("UPT", MSG_VERSION_COPYRIGHT)) +MSG_DESCRIPTION = _("The UEFIPT is used to create, " + \ + "install or remove a UEFI Distribution Package. " + \ + "If WORKSPACE environment variable is present, " + \ + "then UPT will install packages to the location specified by WORKSPACE, " + \ + "otherwise UPT will install packages to the current directory. " + \ + "Option -n will override this default installation location") + +# +# INF Parser related strings. +# +ERR_INF_PARSER_HEADER_FILE = _( + "The Header comment section should start with an @file at the top.") +ERR_INF_PARSER_HEADER_MISSGING = _( + "The Header comment is missing. It must be corrected before continuing.") +ERR_INF_PARSER_UNKNOWN_SECTION = _("An unknown section was found. " + "It must be corrected before continuing. ") +ERR_INF_PARSER_NO_SECTION_ERROR = _("No section was found. " + "A section must be included before continuing.") +ERR_INF_PARSER_BUILD_OPTION_FORMAT_INVALID = \ + _("Build Option format incorrect.") +ERR_INF_PARSER_BINARY_ITEM_FORMAT_INVALID = _( + "The format of binary %s item is incorrect. " + "It should contain at least %d elements.") +ERR_INF_PARSER_BINARY_ITEM_FORMAT_INVALID_MAX = _( + "The format of binary %s item is invalid, " + "it should contain not more than %d elements.") +ERR_INF_PARSER_BINARY_ITEM_INVALID_FILETYPE = _( + "The Binary FileType is incorrect. It should in %s") +ERR_INF_PARSER_BINARY_ITEM_FILE_NOT_EXIST = _( + "The Binary File: %s not exist.") +ERR_INF_PARSER_BINARY_ITEM_FILENAME_NOT_EXIST = _( + "The Binary File Name item not exist") +ERR_INF_PARSER_BINARY_VER_TYPE = _( + "Only this type is allowed: \"%s\".") +ERR_INF_PARSER_MULTI_DEFINE_SECTION = \ + _("Multiple define sections found. " + "It must be corrected before continuing.") +ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND = \ + _("More than 1 %s is defined in DEFINES section. " + "It must be corrected before continuing.") +ERR_INF_PARSER_DEFINE_NAME_INVALID = \ + _("Incorrect name format for : %s") +ERR_INF_PARSER_DEFINE_GUID_INVALID = \ + _("The format of this GUID is incorrect: %s") +ERR_INF_PARSER_DEFINE_MODULETYPE_INVALID = _("Incorrect MODULE_TYPE: %s") +ERR_INF_PARSER_DEFINE_FROMAT_INVALID = _("Incorrect format: %s") +ERR_INF_PARSER_FILE_NOT_EXIST = _("This file does not exist: %s") +ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID = \ + _("The file does not exist or not in sub-directories " + "or has an incorrect file name of the directory containing the INF or DEC file: %s. " + "It must be corrected before continuing") +ERR_INF_PARSER_DEFINE_SHADOW_INVALID = \ + _("The SHADOW keyword is only valid for" + " SEC, PEI_CORE and PEIM module types.") +ERR_INF_PARSER_DEFINE_SECTION_HEADER_INVALID = \ + _("The format of the section header is incorrect") +ERR_INF_PARSER_DEPEX_SECTION_INVALID = \ + _("A module can't have a Depex section when its module type is %s") +ERR_INF_PARSER_DEPEX_SECTION_INVALID_FOR_BASE_LIBRARY_CLASS = \ + _("A base type library class can't have a Depex section with module type not defined.") +ERR_INF_PARSER_DEPEX_SECTION_INVALID_FOR_LIBRARY_CLASS = \ + _("A library class can't have a Depex section when its supported module type list is not defined.") +ERR_INF_PARSER_DEPEX_SECTION_INVALID_FOR_DRIVER = \ + _("A driver can't have a Depex section when its module type is UEFI_DRIVER.") +ERR_INF_PARSER_DEPEX_SECTION_NOT_DETERMINED = \ + _("Cannot determine the module's Depex type. The Depex's module types are conflict") +ERR_INF_PARSER_DEFINE_SECTION_MUST_ITEM_NOT_EXIST = _( + "No %s found in INF file, please check it.") +ERR_INF_PARSER_DEPEX_SECTION_MODULE_TYPE_ERROR = \ + _("The module type of [Depex] section is invalid, not support type of %s") +ERR_INF_PARSER_DEPEX_SECTION_CONTENT_MISSING = \ + _("Missing content in: %s") +ERR_INF_PARSER_DEPEX_SECTION_CONTENT_ERROR = \ + _("The [Depex] section contains invalid content: %s") +ERR_INF_PARSER_DEPEX_SECTION_SEC_TYPE_ERROR = \ + _("The format is incorrect. The section type keyword of the content in the" + " [Depex] section is only for 'PEI_DEPEX', 'DXE_DEPEX', 'SMM_DEPEX', " + "it does not support type: %s") +ERR_INF_PARSER_UE_SECTION_USER_ID_ERROR = \ + _("This format is incorrect. " + "The UserID: %s in [UserExtension] section is incorrect.") +ERR_INF_PARSER_UE_SECTION_ID_STRING_ERROR = \ + _("This format is incorrect. " + "IdString: %s in [UserExtension] section is incorrect.") +ERR_INF_PARSER_LIBRARY_SECTION_CONTENT_ERROR = \ + _("The format is incorrect. " + "You can only have a Library name and a Feature flag in one line.") +ERR_INF_PARSER_LIBRARY_SECTION_LIBNAME_MISSING = \ + _("Format invalid. Please specify a library name.") +ERR_INF_PARSER_SOURCES_SECTION_CONTENT_ERROR = \ + _("The format is incorrect. It should be formatted as follows: " + "FileName, Family | TagName | ToolCode | FeatureFlagExpr.") +ERR_INF_PARSER_PCD_SECTION_TYPE_ERROR = \ + _("The PCD section type is incorrect. The value should be this list: %s") +ERR_INF_PARSER_PCD_SECTION_CONTENT_ERROR = \ + _("PcdName format invalid." + "Should like following: PcdName | Value | FeatureFlag.") +ERR_INF_PARSER_PCD_NAME_FORMAT_ERROR = \ + _("Format invalid." + "Should like following: . ") +ERR_INF_PARSER_GUID_PPI_PROTOCOL_SECTION_CONTENT_ERROR = \ + _("The format is incorrect. " + "It should be formatted as follows: CName | FeatureFlag.") +ERR_INF_PARSER_PACKAGE_SECTION_CONTENT_ERROR = \ + _("The format is incorrect. " + "It should be formatted as follows: .") +ERR_INF_PARSER_PCD_TAIL_COMMENTS_INVALID = \ + _("The format is incorrect. " + "Multiple usage descriptions must be described on subsequent lines.") +ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR = \ + _("This section format is incorrect: %s.") +ERR_INF_PARSER_SECTION_NAME_DUPLICATE = \ + _("This section has multiple section names, " + "only one section name is permitted.") +ERR_INF_PARSER_SECTION_ARCH_CONFLICT = \ + _("The 'common' ARCH must not be used with the specified ARCHs.") +ERR_INF_PARSER_SOURCE_SECTION_TAGNAME_INVALID = \ + _("This TagName is incorrect: %s. " + "It must be corrected before continuing.") +ERR_INF_PARSER_TAGNAME_NOT_PERMITTED = \ + _("TagName is not permitted: %s. " + "It must be corrected before continuing.") +ERR_INF_PARSER_TOOLCODE_NOT_PERMITTED = \ + _("ToolCode is not permitted: %s. " + "It must be corrected before continuing.") +ERR_INF_PARSER_SOURCE_SECTION_FAMILY_INVALID = \ + _("This family is incorrect: %s. " + "It must be corrected before continuing. ") +ERR_INF_PARSER_SOURCE_SECTION_SECTIONNAME_INVALID = \ + _("This SectionName is incorrect: %s. " + "It must be corrected before continuing.") +ERR_INF_PARSER_PCD_CVAR_GUID = \ + _("TokenSpaceGuidCName must be valid C variable format.") +ERR_INF_PARSER_PCD_CVAR_PCDCNAME = \ + _("PcdCName must be valid C variable format.") +ERR_INF_PARSER_PCD_VALUE_INVALID = \ + _("The PCD value is incorrect. It must be corrected before continuing.") +ERR_INF_PARSER_FEATURE_FLAG_EXP_SYNTAX_INVLID = \ + _("Incorrect feature flag expression: %s") +ERR_INF_PARSER_FEATURE_FLAG_EXP_MISSING = \ + _("The feature flag expression is missing. Please specify a feature flag.") +ERR_INF_PARSER_INVALID_CNAME = \ + _("Incorrect CName: %s. You must specify a valid C variable name.") +ERR_INF_PARSER_CNAME_MISSING = \ + _("Missing CName. Specify a valid C variable name.") +ERR_INF_PARSER_DEFINE_SECTION_KEYWORD_INVALID = \ + _("The Define section contains an invalid keyword: \"%s\"." + "It must be corrected before continuing.") +ERR_INF_PARSER_FILE_MISS_DEFINE = \ + _("The following file listed in the module " + "directory is not listed in the INF: %s") +ERR_INF_PARSER_VERSION_NUMBER_DEPRICATED = \ + _("VERSION_NUMBER deprecated. " + "The INF file %s should be modified to use the VERSION_STRING instead.") +ERR_INF_PARSER_VER_EXIST_BOTH_NUM_STR = \ + _("The INF file %s defines both VERSION_NUMBER and VERSION_STRING, " + "using VERSION_STRING") +ERR_INF_PARSER_NOT_SUPPORT_EDKI_INF = _("EDKI INF is not supported") +ERR_INF_PARSER_EDKI_COMMENT_IN_EDKII = _("The EDKI style comment is not supported in EDKII modules") + +ERR_INF_PARSER_FEATUREPCD_USAGE_INVALID = _("The usage for FeaturePcd can only" + " be type of \"CONSUMES\".") + +ERR_INF_PARSER_DEFINE_ITEM_NO_NAME = _("No name specified") +ERR_INF_PARSER_DEFINE_ITEM_NO_VALUE = _("No value specified") + +ERR_INF_PARSER_MODULETYPE_INVALID = _("Drivers and applications are not allowed to have a MODULE_TYPE of \"BASE\". " +"Only libraries are permitted to a have a MODULE_TYPE of \"BASE\".") +ERR_INF_GET_PKG_DEPENDENCY_FAIL = _("Failed to get PackageDependencies information from file %s") +ERR_INF_NO_PKG_DEPENDENCY_INFO = _("There are no packages defined that use the AsBuilt PCD information.") + +# +# Item duplicate +# +ERR_INF_PARSER_ITEM_DUPLICATE_IN_DEC = \ +_('"%s" is redefined in its dependent DEC files') +ERR_INF_PARSER_ITEM_DUPLICATE = _("%s define duplicated! " + "It must be corrected before continuing.") +ERR_INF_PARSER_ITEM_DUPLICATE_COMMON = _("%s define duplicated! Item listed" +"in an architectural section must not be listed in the common architectural" +"section.It must be corrected before continuing.") +ERR_INF_PARSER_UE_SECTION_DUPLICATE_ERROR = \ +_("%s define duplicated! Each UserExtensions section header must have a " + "unique set of UserId, IdString and Arch values. " + "It must be corrected before continuing.") + +ERR_INF_PARSER_DEFINE_LIB_NAME_INVALID = \ +_("The name 'NULL' for LibraryClass is a reserved word." +"Please don't use it.") + +ERR_GLOBAL_MARCO_INVALID = \ +_("Using global MACRO in INF/DEC is not permitted: %s . " +"It must be corrected before continuing.") + +ERR_MARCO_DEFINITION_MISS_ERROR = \ +_("MACRO expand incorrectly, can not find the MACRO definition. " +"It must be corrected before continuing.") + +# +# AsBuilt related +# +ERR_LIB_CONTATIN_ASBUILD_AND_COMMON = _("A binary INF file should not contain both AsBuilt LIB_INSTANCES information " + "and a common library entry.") +ERR_LIB_INSTANCE_MISS_GUID = _("Could not get FILE_GUID definition from instance INF file.") + +ERR_BO_CONTATIN_ASBUILD_AND_COMMON = _("A binary INF file should contain either AsBuilt information " + "or a common build option entry, not both.") + +ERR_ASBUILD_PCD_SECTION_TYPE = _("The AsBuilt INF file contains a PCD section type that is not permitted: %s.") +ERR_ASBUILD_PATCHPCD_FORMAT_INVALID = _("The AsBuilt PatchPcd entry must contain 3 elements: PcdName|Value|Offset") +ERR_ASBUILD_PCDEX_FORMAT_INVALID = _("The AsBuilt PcdEx entry must contain one element: PcdName") +ERR_ASBUILD_PCD_VALUE_INVALID = \ + _("The AsBuilt PCD value %s is incorrect or not align with its datum type %s. " + "It must be corrected before continuing.") +ERR_ASBUILD_PCD_TOKENSPACE_GUID_VALUE_MISS = _("Package file value could not be retrieved for %s.") +ERR_ASBUILD_PCD_DECLARITION_MISS = _("PCD Declaration in DEC files could not be found for: %s.") +ERR_ASBUILD_PCD_OFFSET_FORMAT_INVALID = _("PCD offset format invalid, number of (0-4294967295) or" +"Hex number of UINT32 allowed : %s.") + +# +# XML parser related strings +# +ERR_XML_PARSER_REQUIRED_ITEM_MISSING = \ + _("The XML section/attribute '%s' is required under %s, it can't be missing or empty") +ERR_XML_INVALID_VARIABLENAME = \ + _("The VariableName of the GUID in the XML tree does not conform to the packaging specification. " + "Only a Hex Byte Array of UCS-2 format or L\"string\" is allowed): %s %s %s") +ERR_XML_INVALID_LIB_SUPMODLIST = _("The LIBRARY_CLASS entry %s must have the list appended using the format as: \n" +"BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER SMM_CORE DXE_SMM_DRIVER DXE_RUNTIME_DRIVER " +"DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION USER_DEFINED\n Current is %s.") +ERR_XML_INVALID_EXTERN_SUPARCHLIST = \ + _("There is a mismatch of SupArchList %s between the EntryPoint, UnloadImage, Constructor, " + "and Destructor elements in the ModuleSurfaceArea.ModuleProperties: SupArchList: %s. ") +ERR_XML_INVALID_EXTERN_SUPMODLIST = _("The SupModList attribute of the CONSTRUCTOR or DESTRUCTOR element: %s does not " +"match the Supported Module Types listed after LIBRARY_CLASS = | %s") +ERR_XML_INVALID_EXTERN_SUPMODLIST_NOT_LIB = _("The module is not a library module. " + "The MODULE_TYPE : %s listed in the ModuleSurfaceArea.Header " + "must match the SupModList attribute %s") +ERR_XML_INVALID_BINARY_FILE_TYPE = _("Invalid binary file type %s.") + +# +# Verbosity related strings. +# +MSG_DISTRIBUTION_PACKAGE_FILE_EXISTS = _( + "The distribution package file %s already exists.\nPress Y to override it." + " To exit the application, press any other key.") +MSG_CHECK_MODULE_EXIST = _( + "\nChecking to see if module exists in workspace started ...") +MSG_CHECK_MODULE_EXIST_FINISH = \ + _("Checking to see if module exists in workspace ... Done.") +MSG_CHECK_MODULE_DEPEX_START = _( + "\nChecking to see if module depex met by workspace started ...") +MSG_CHECK_MODULE_DEPEX_FINISH = _( + "Checking to see if module depex met by workspace ... Done.") +MSG_CHECK_PACKAGE_START = _( + "\nChecking to see if package exists in workspace started ...") +MSG_CHECK_PACKAGE_FINISH = _( + "Checking to see if package exists in workspace ... Done.") +MSG_CHECK_DP_START = \ + _("\nChecking to see if DP exists in workspace ... Done.") +MSG_CHECK_DP_FINISH = _("Check DP exists in workspace ... Done.") +MSG_MODULE_DEPEND_ON = _("Module %s depends on Package %s") +MSG_INIT_IPI_START = _("\nInitialize IPI database started ...") +MSG_INIT_IPI_FINISH = _("Initialize IPI database ... Done.") +MSG_GET_DP_INSTALL_LIST = _( + "\nGetting list of DP install information started ...") +MSG_GET_DP_INSTALL_INFO_START = _( + "\nGetting list of DP install information started ...") +MSG_GET_DP_INSTALL_INFO_FINISH = _("Getting DP install information ... Done.") +MSG_UZIP_PARSE_XML = _( + "Unzipping and parsing distribution package XML file ... ") +MSG_INSTALL_PACKAGE = _("Installing package ... %s") +MSG_INSTALL_MODULE = _("Installing module ... %s") +MSG_NEW_FILE_NAME_FOR_DIST = _( + "Provide new filename for distribution file to be saved:\n") +MSG_UPDATE_PACKAGE_DATABASE = _("Update Distribution Package Database ...") +MSG_PYTHON_ON = _("(Python %s on %s) ") +MSG_EDKII_MAIL_ADDR = 'devel@edk2.groups.io' +MSG_SEARCH_FOR_HELP = _( + "\n(Please send email to %s for\n" + " help, attach the following call stack trace.)\n") +MSG_REMOVE_TEMP_FILE_STARTED = _("Removing temp files started ... ") +MSG_REMOVE_TEMP_FILE_DONE = _("Removing temp files ... Done.") +MSG_FINISH = _("Successfully Done.") +MSG_COMPRESS_DISTRIBUTION_PKG = _("Compressing Distribution Package File ...") +MSG_CONFIRM_REMOVE = _( + "Some packages or modules depend on this distribution package.\n" + "Do you really want to remove it?") +MSG_CONFIRM_REMOVE2 = _( + "This file has been modified: %s. Do you want to remove it?" + "Press Y to remove or other key to keep it") +MSG_CONFIRM_REMOVE3 = _( + "This is a newly created file: %s. Are you sure you want to remove it? " + "Press Y to remove or any other key to keep it") +MSG_USER_DELETE_OP = _( + "Press Y to delete all files or press any other key to quit:") +MSG_REMOVE_FILE = _("Removing file: %s ...") + +MSG_INITIALIZE_ECC_STARTED = _("\nInitialize ECC database started ...") +MSG_INITIALIZE_ECC_DONE = _("Initialize ECC database ... Done.") +MSG_DEFINE_STATEMENT_FOUND = _("DEFINE statement '%s' found in section %s") +MSG_PARSING = _("Parsing %s ...") + +MSG_REPKG_CONFLICT = \ +_("Repackaging is not allowed on this file: %s. " + "It was installed from distribution %s(Guid %s Version %s).") + +MSG_INVALID_MODULE_INTRODUCED = _("Some modules are not valid after removal.") +MSG_CHECK_LOG_FILE = _("Please check log file %s for full list") +MSG_NEW_FILE_NAME = _( + "Provide new filename:\n") +MSG_RELATIVE_PATH_ONLY = _("Please specify a relative path, full path is not allowed: %s") +MSG_NEW_PKG_PATH = _( + "Select package location. To quit with no input, press [Enter].") +MSG_CHECK_DP_FOR_REPLACE = _("Verifying the dependency rule for replacement of distributions:\n %s replaces %s") +MSG_CHECK_DP_FOR_INSTALL = _("Verifying the dependency rule for installation of distribution:\n %s") +MSG_REPLACE_ALREADY_INSTALLED_DP = _("Distribution with the same GUID/Version is already installed, " + "replace would result in two instances, which is not allowed") +MSG_RECOVER_START = _('An error was detected, recovery started ...') +MSG_RECOVER_DONE = _('Recovery completed.') +MSG_RECOVER_FAIL = _('Recovery failed.') +# +# Error related strings. +# + +ERR_DEPENDENCY_NOT_MATCH = _( + "Module %s's dependency on package %s (GUID %s Version %s) " + "cannot be satisfied") +ERR_MODULE_NOT_INSTALLED = _( + "This module is not installed in the workspace: %s\n") +ERR_DIR_ALREADY_EXIST = _( + "This directory already exists: %s.\n" + "Select another location. Press [Enter] with no input to quit:") +ERR_USER_INTERRUPT = _("The user has paused the application") +ERR_DIST_FILE_TOOMANY = _( + "Only one .content and one .pkg file in ZIP file are allowed.") +ERR_DIST_FILE_TOOFEW = _( + "Must have one .content and one .pkg file in the ZIP file.") +ERR_FILE_ALREADY_EXIST = _( + "This file already exists: %s.\n" + "Select another path to continue. To quit with no input press [Enter]:") +ERR_SPECIFY_PACKAGE = _( + "One distribution package must be specified") +ERR_FILE_BROKEN = _( + "This file is invalid in the distribution package: %s") +ERR_PACKAGE_NOT_MATCH_DEPENDENCY = _( + "This distribution package does not meet the dependency requirements") +ERR_UNKNOWN_FATAL_INSTALL_ERR = \ +_("Unknown unrecoverable error when installing: %s") +ERR_UNKNOWN_FATAL_REPLACE_ERR = \ +_("Unknown unrecoverable error during replacement of distributions: %s replaces %s") +ERR_OPTION_NOT_FOUND = _("Options not found") +ERR_INVALID_PACKAGE_NAME = _("Incorrect package name: %s. ") +ERR_INVALID_PACKAGE_PATH = \ +_("Incorrect package path: %s. The path must be a relative path.") +ERR_NOT_FOUND = _("This was not found: %s") +ERR_INVALID_MODULE_NAME = _("This is not a valid module name: %s") +ERR_INVALID_METAFILE_PATH = _('This file must be in sub-directory of WORKSPACE: %s.') +ERR_INVALID_MODULE_PATH = \ +_("Incorrect module path: %s. The path must be a relative path.") +ERR_UNKNOWN_FATAL_CREATING_ERR = _("Unknown error when creating: %s") +ERR_PACKAGE_NOT_INSTALLED = _( + "This distribution package not installed: %s") +ERR_DISTRIBUTION_NOT_INSTALLED = _( + "The distribution package is not installed.") +ERR_UNKNOWN_FATAL_REMOVING_ERR = _("Unknown error when removing package") +ERR_UNKNOWN_FATAL_INVENTORYWS_ERR = _("Unknown error when inventorying WORKSPACE") +ERR_NOT_CONFIGURE_WORKSPACE_ENV = _( + "The WORKSPACE environment variable must be configured.") +ERR_NO_TEMPLATE_FILE = _("This package information data file is not found: %s") +ERR_DEBUG_LEVEL = _( + "Not supported debug level. Use default level instead.") +ERR_REQUIRE_T_OPTION = _( + "Option -t is required during distribution creation.") +ERR_REQUIRE_O_OPTION = _( + "Option -o is required during distribution replacement.") +ERR_REQUIRE_U_OPTION = _( + "Option -u is required during distribution replacement.") +ERR_REQUIRE_I_C_R_OPTION = _( + "Options -i, -c and -r are mutually exclusive.") +ERR_I_C_EXCLUSIVE = \ +_("Option -c and -i are mutually exclusive.") +ERR_I_R_EXCLUSIVE = \ +_("Option -i and -r are mutually exclusive.") +ERR_C_R_EXCLUSIVE = \ +_("Option -c and -r are mutually exclusive.") +ERR_U_ICR_EXCLUSIVE = \ +_("Option -u and -c/-i/-r are mutually exclusive.") + +ERR_L_OA_EXCLUSIVE = \ +_("Option -l and -c/-i/-r/-u are mutually exclusive.") + +ERR_FAILED_LOAD = _("Failed to load %s\n\t%s") +ERR_PLACEHOLDER_DIFFERENT_REPEAT = _( + "${%s} has different repeat time from others.") +ERR_KEY_NOTALLOWED = _("This keyword is not allowed: %s") +ERR_NOT_FOUND_ENVIRONMENT = _("Environment variable not found") +ERR_WORKSPACE_NOTEXIST = _("WORKSPACE doesn't exist") +ERR_SPACE_NOTALLOWED = _( + "Whitespace characters are not allowed in the WORKSPACE path. ") +ERR_MACRONAME_NOGIVEN = _("No MACRO name given") +ERR_MACROVALUE_NOGIVEN = _("No MACRO value given") +ERR_MACRONAME_INVALID = _("Incorrect MACRO name: %s") +ERR_MACROVALUE_INVALID = _("Incorrect MACRO value: %s") +ERR_NAME_ONLY_DEFINE = _( + "This variable can only be defined via environment variable: %s") +ERR_EDK_GLOBAL_SAMENAME = _( + "EDK_GLOBAL defined a macro with the same name as one defined by 'DEFINE'") +ERR_SECTIONNAME_INVALID = _( + "An incorrect section name was found: %s. 'The correct file is '%s' .") +ERR_CHECKFILE_NOTFOUND = _( + "Can't find file '%s' defined in section '%s'") +ERR_INVALID_NOTFOUND = _( + "Incorrect statement '%s' was found in section '%s'") +ERR_TEMPLATE_NOTFOUND = _("This package information data file is not found: %s") +ERR_SECTION_NAME_INVALID = _('Incorrect section name: %s') +ERR_SECTION_REDEFINE = _( + "This section already defined: %s.") +ERR_SECTION_NAME_NONE = \ + _('The section needs to be specified first.') +ERR_KEYWORD_INVALID = _('Invalid keyword: %s') +ERR_VALUE_INVALID = _("Invalid \"%s\" value in section [%s].") +ERR_FILELIST_LOCATION = _( + 'The directory "%s" must contain this file: "%s".') +ERR_KEYWORD_REDEFINE = _( + "Keyword in this section can only be used once: %s.") +ERR_FILELIST_EXIST = _( + 'This file does not exist: %s.') +ERR_COPYRIGHT_CONTENT = _( + "The copyright content must contain the word \"Copyright\" (case insensitive).") +ERR_WRONG_FILELIST_FORMAT = \ +_('File list format is incorrect.' + 'The correct format is: filename|key=value[|key=value]') +ERR_FILELIST_ATTR = _( + "The value of attribute \"%s\" includes illegal character.") +ERR_UNKNOWN_FILELIST_ATTR = _( + 'Unknown attribute name: %s.') +ERR_EMPTY_VALUE = _("Empty value is not allowed") +ERR_KEYWORD_MANDATORY = _('This keyword is mandatory: %s') +ERR_BOOLEAN_VALUE = _( + 'Value of key [%s] must be true or false, current: [%s]') +ERR_GUID_VALUE = _( + 'GUID must have the format of 8-4-4-4-12 with HEX value. ' + 'Current value: [%s]') +ERR_VERSION_VALUE = _( + 'The value of key [%s] must be a decimal number. Found: [%s]') +ERR_VERSION_XMLSPEC = _( + 'XmlSpecification value must be 1.1, current: %s.') + +ERR_INVALID_GUID = _("Incorrect GUID value string: %s") + +ERR_FILE_NOT_FOUND = \ + _("File or directory not found in workspace") +ERR_FILE_OPEN_FAILURE = _("Could not open file") +ERR_FILE_WRITE_FAILURE = _("Could not write file.") +ERR_FILE_PARSE_FAILURE = _("Could not parse file") +ERR_FILE_READ_FAILURE = _("Could not read file") +ERR_FILE_CREATE_FAILURE = _("Could not create file") +ERR_FILE_CHECKSUM_FAILURE = _("Checksum of file is incorrect") +ERR_FILE_COMPRESS_FAILURE = _("File compression did not correctly") +ERR_FILE_DECOMPRESS_FAILURE = \ + _("File decompression did not complete correctly") +ERR_FILE_MOVE_FAILURE = _("Move file did not complete successfully") +ERR_FILE_DELETE_FAILURE = _("File could not be deleted") +ERR_FILE_COPY_FAILURE = _("File did not copy correctly") +ERR_FILE_POSITIONING_FAILURE = _("Could not find file seek position") +ERR_FILE_TYPE_MISMATCH = _("Incorrect file type") +ERR_FILE_CASE_MISMATCH = _("File name case mismatch") +ERR_FILE_DUPLICATED = _("Duplicate file found") +ERR_FILE_UNKNOWN_ERROR = _("Unknown error encountered on file") +ERR_FILE_NAME_INVALIDE = _("This file name is invalid, it must not be an absolute path or " + "contain a period \".\" or \"..\": %s.") +ERR_OPTION_UNKNOWN = _("Unknown option") +ERR_OPTION_MISSING = _("Missing option") +ERR_OPTION_CONFLICT = _("Options conflict") +ERR_OPTION_VALUE_INVALID = _("Invalid option value") +ERR_OPTION_DEPRECATED = _("Deprecated option") +ERR_OPTION_NOT_SUPPORTED = _("Unsupported option") +ERR_OPTION_UNKNOWN_ERROR = _("Unknown error when processing options") +ERR_PARAMETER_INVALID = _("Invalid parameter") +ERR_PARAMETER_MISSING = _("Missing parameter") +ERR_PARAMETER_UNKNOWN_ERROR = _("Unknown error in parameters") +ERR_FORMAT_INVALID = _("Invalid syntax/format") +ERR_FORMAT_NOT_SUPPORTED = _("Syntax/format not supported") +ERR_FORMAT_UNKNOWN = _("Unknown format") +ERR_FORMAT_UNKNOWN_ERROR = _("Unknown error in syntax/format ") +ERR_RESOURCE_NOT_AVAILABLE = _("Not available") +ERR_RESOURCE_ALLOCATE_FAILURE = _("A resource allocation has failed") +ERR_RESOURCE_FULL = _("Full") +ERR_RESOURCE_OVERFLOW = _("Overflow") +ERR_RESOURCE_UNDERRUN = _("Underrun") +ERR_RESOURCE_UNKNOWN_ERROR = _("Unknown error") +ERR_ATTRIBUTE_NOT_AVAILABLE = _("Not available") +ERR_ATTRIBUTE_RETRIEVE_FAILURE = _("Unable to retrieve") +ERR_ATTRIBUTE_SET_FAILURE = _("Unable to set") +ERR_ATTRIBUTE_UPDATE_FAILURE = _("Unable to update") +ERR_ATTRIBUTE_ACCESS_DENIED = _("Access denied") +ERR_ATTRIBUTE_UNKNOWN_ERROR = _("Unknown error when accessing") +ERR_COMMAND_FAILURE = _("Unable to execute command") +ERR_IO_NOT_READY = _("Not ready") +ERR_IO_BUSY = _("Busy") +ERR_IO_TIMEOUT = _("Timeout") +ERR_IO_UNKNOWN_ERROR = _("Unknown error in IO operation") +ERR_UNKNOWN_ERROR = _("Unknown error") +ERR_UPT_ALREADY_INSTALLED_ERROR = _("Already installed") +ERR_UPT_ENVIRON_MISSING_ERROR = _("Environ missing") +ERR_UPT_REPKG_ERROR = _("File not allowed for RePackage") +ERR_UPT_DB_UPDATE_ERROR = _("Update database did not complete successfully") +ERR_UPT_INI_PARSE_ERROR = _("INI file parse error") +ERR_COPYRIGHT_MISSING = \ +_("Header comment section must have copyright information") +ERR_LICENSE_MISSING = \ +_("Header comment section must have license information") +ERR_INVALID_BINARYHEADER_FORMAT = \ +_("Binary Header comment section must have abstract,description,copyright,license information") +ERR_MULTIPLE_BINARYHEADER_EXIST = \ +_("the inf file at most support one BinaryHeader at the fileheader section.") +ERR_INVALID_COMMENT_FORMAT = _("Comment must start with #") +ERR_USER_ABORT = _("User has stopped the application") +ERR_DIST_EXT_ERROR = \ +_("Distribution file extension should be '.dist'. Current given: '%s'.") +ERR_DIST_FILENAME_ONLY_FOR_REMOVE = \ +_("Only distribution filename without path allowed during remove. Current given: '%s'.") +ERR_NOT_STANDALONE_MODULE_ERROR = \ + _("Module %s is not a standalone module (found in Package %s)") +ERR_UPT_ALREADY_RUNNING_ERROR = \ + _("UPT is already running, only one instance is allowed") +ERR_MUL_DEC_ERROR = _("Multiple DEC files found within one package directory tree %s: %s, %s") +ERR_INSTALL_FILE_FROM_EMPTY_CONTENT = _("Error file to be installed is not found in content file: %s") +ERR_INSTALL_FILE_DEC_FILE_ERROR = _("Could not obtain the TokenSpaceGuidCName and the PcdCName from the DEC files " +"that the package depends on for this pcd entry: TokenValue: %s Token: %s") +ERR_NOT_SUPPORTED_SA_MODULE = _("Stand-alone module distribution does not allow EDK 1 INF") +ERR_INSTALL_DIST_NOT_FOUND = \ +_("Distribution file to be installed is not found in current working directory or workspace: %s") +ERR_REPLACE_DIST_NOT_FOUND = \ +_("Distribution file for replace function was not found in the current working directory or workspace: %s") +ERR_DIST_FILENAME_ONLY_FOR_REPLACE_ORIG = \ +_("Only a distribution file name without a path is allowed for " + "the distribution to be replaced during replace. Current given: '%s'.") +ERR_UNIPARSE_DBLQUOTE_UNMATCHED = \ +_("Only Language entry can contain a couple of matched quote in one line") +ERR_UNIPARSE_NO_SECTION_EXIST = _("No PackageDef or ModuleDef section exists in the UNI file.") +ERR_UNIPARSE_STRNAME_FORMAT_ERROR = _("The String Token Name %s must start with \"STR_\"") +ERR_UNIPARSE_SEP_LANGENTRY_LINE = _("Each should be in a separate line :%s.") +ERR_UNIPARSE_MULTI_ENTRY_EXIST = \ +_("There are same entries : %s in the UNI file, every kind of entry should be only one.") +ERR_UNIPARSE_ENTRY_ORDER_WRONG = \ +_("The string entry order in UNI file should be , , \ +, .") +ERR_UNIPARSE_STRTOKEN_FORMAT_ERROR = _("The String Token Type %s must be one of the '_PROMPT', '_HELP' and '_ERR_'.") +ERR_UNIPARSE_LINEFEED_UNDER_EXIST = _("Line feed should not exist under this line: %s.") +ERR_UNIPARSE_LINEFEED_UP_EXIST = _("Line feed should not exist up this line: %s.") +ERR_UNI_MISS_STRING_ENTRY = _("String entry missed in this Entry, %s.") +ERR_UNI_MISS_LANGENTRY = _("Language entry missed in this Entry, %s.") +ERR_BINARY_HEADER_ORDER = _("Binary header must follow the file header.") +ERR_NO_SOURCE_HEADER = _("File header statement \"## @file\" must exist at the first place.") +ERR_UNI_FILE_SUFFIX_WRONG = _("The UNI file must have an extension of '.uni', '.UNI' or '.Uni'") +ERR_UNI_FILE_NAME_INVALID = _("The use of '..', '../' and './' in the UNI file is prohibited.") +ERR_UNI_SUBGUID_VALUE_DEFINE_DEC_NOT_FOUND = _("There are no DEC file to define the GUID value for \ +this GUID CName: '%s'.") + +# +# Expression error message +# +ERR_EXPR_RIGHT_PAREN = \ +_('Missing ")" in expression "%s".') +ERR_EXPR_FACTOR = \ +_('"%s" is expected to be HEX, integer, macro, quoted string or PcdName in ' + 'expression "%s".') +ERR_EXPR_STRING_ITEM = \ +_('"%s" is expected to be HEX, integer, macro, quoted string or PcdName in ' + 'expression [%s].') +ERR_EXPR_EQUALITY = \ +_('"%s" is expected to be ==, EQ, != or NE in expression "%s".') +ERR_EXPR_BOOLEAN = \ +_('The string "%s" in expression "%s" can not be recognized as a part of the logical expression.') +ERR_EXPR_EMPTY = _('Boolean value cannot be empty.') +ERR_EXPRESS_EMPTY = _('Expression can not be empty.') +ERR_EXPR_LOGICAL = \ +_('The following is not a valid logical expression: "%s".') +ERR_EXPR_OR = _('The expression: "%s" must be encapsulated in open "(" and close ")" ' + 'parenthesis when using | or ||.') +ERR_EXPR_RANGE = \ +_('The following is not a valid range expression: "%s".') +ERR_EXPR_RANGE_FACTOR = \ +_('"%s" is expected to be HEX, integer in valid range expression "%s".') +ERR_EXPR_RANGE_DOUBLE_PAREN_NESTED = \ +_('Double parentheses nested is not allowed in valid range expression: "%s".') +ERR_EXPR_RANGE_EMPTY = _('Valid range can not be empty.') +ERR_EXPR_LIST_EMPTY = _('Valid list can not be empty.') +ERR_PAREN_NOT_USED = _('Parenthesis must be used on both sides of "OR", "AND" in valid range : %s.') +ERR_EXPR_LIST = \ +_('The following is not a valid list expression: "%s".') + + +# DEC parser error message +# +ERR_DECPARSE_STATEMENT_EMPTY = \ +_('Must have at least one statement in section %s.') +ERR_DECPARSE_DEFINE_DEFINED = \ +_('%s already defined in define section.') +ERR_DECPARSE_DEFINE_SECNAME = \ +_('No arch and others can be followed for define section.') +ERR_DECPARSE_DEFINE_MULTISEC = \ +_('The DEC file does not allow multiple define sections.') +ERR_DECPARSE_DEFINE_REQUIRED = \ +_("Field [%s] is required in define section.") +ERR_DECPARSE_DEFINE_FORMAT = \ +_("Wrong define section format, must be KEY = Value.") +ERR_DECPARSE_DEFINE_UNKNOWKEY = \ +_("Unknown key [%s] in define section.") +ERR_DECPARSE_DEFINE_SPEC = \ +_("Specification value must be HEX numbers or decimal numbers.") +ERR_DECPARSE_DEFINE_PKGNAME = \ +_("Package name must be AlphaNumeric characters.") +ERR_DECPARSE_DEFINE_PKGGUID = \ +_("GUID format error, must be HEX value with form 8-4-4-4-12.") +ERR_DECPARSE_DEFINE_PKGVERSION = \ +_("Version number must be decimal number.") +ERR_DECPARSE_DEFINE_PKGVUNI = \ +_("UNI file name format error or file does not exist.") +ERR_DECPARSE_INCLUDE = \ +_("Incorrect path: [%s].") +ERR_DECPARSE_LIBCLASS_SPLIT = \ +_("Library class format error, must be Libraryclass|Headerpath.") +ERR_DECPARSE_LIBCLASS_EMPTY = \ +_("Class name or file name must not be empty.") +ERR_DECPARSE_LIBCLASS_LIB = \ +_("Class name format error, must start with upper case letter followed with " + "zero or more alphanumeric characters.") +ERR_DECPARSE_LIBCLASS_PATH_EXT = _("File name must be end with .h.") +ERR_DECPARSE_LIBCLASS_PATH_DOT = _("Path must not include '..'.") +ERR_DECPARSE_LIBCLASS_PATH_EXIST = _("File name [%s] does not exist.") +ERR_DECPARSE_PCD_CVAR_GUID = \ +_("TokenSpaceGuidCName must be valid C variable format.") +ERR_DECPARSE_PCD_SPLIT = \ +_("Incorrect PcdName. The format must be TokenSpaceGuidCName.PcdCName" + "|PcdData|PcdType|Token.") +ERR_DECPARSE_PCD_NAME = \ +_("Incorrect PCD name. The correct format must be " + "..") +ERR_DECPARSE_PCD_CVAR_PCDCNAME = \ +_("PcdCName must be valid C variable format.") +ERR_DECPARSE_PCD_TYPE = \ +_('Incorrect PCD data type. A PCD data type must be one of ' + '"UINT8", "UINT16", "UINT32", "UINT64", "VOID*", "BOOLEAN".') +ERR_DECPARSE_PCD_VOID = \ +_("Incorrect value [%s] of type [%s]. Value must be printable and in the " + "form of{...} for array, or ""..."" for string, or L""...""" + "for unicode string.") +ERR_DECPARSE_PCD_VALUE_EMPTY = \ +_("Pcd value can not be empty.") +ERR_DECPARSE_PCD_BOOL = \ +_("Invalid value [%s] of type [%s]; must be expression, TRUE, FALSE, 0 or 1.") +ERR_DECPARSE_PCD_INT = _("Incorrect value [%s] of type [%s]."\ +" Value must be a hexadecimal, decimal or octal in C language format.") +ERR_DECPARSE_PCD_INT_NEGTIVE = _("Incorrect value [%s] of type [%s];" + " must not be signed number.") +ERR_DECPARSE_PCD_INT_EXCEED = _("Incorrect value [%s] of type [%s]; " + "the number is too long for this type.") +ERR_DECPARSE_PCD_FEATUREFLAG = \ +_("PcdFeatureFlag only allow BOOLEAN type.") +ERR_DECPARSE_PCD_TOKEN = \ +_("An incorrect PCD token found: [%s]. " + "It must start with 0x followed by 1 - 8 hexadecimal. ") +ERR_DECPARSE_PCD_TOKEN_INT = _("Incorrect token number [%s]. " + "This token number exceeds the maximal value of unsigned 32.") +ERR_DECPARSE_PCD_TOKEN_UNIQUE = _("Token number must be unique to the token space: %s.") +ERR_DECPARSE_CGUID = \ +_("No GUID name or value specified, must be = .") +ERR_DECPARSE_CGUID_NAME = \ +_("No GUID name specified, must be = .") +ERR_DECPARSE_CGUID_GUID = \ +_("No GUID value specified, must be = .") +ERR_DECPARSE_CGUID_GUIDFORMAT = \ +_("Incorrect GUID value format, must be .") +ERR_DECPARSE_CGUID_NOT_FOUND = _("Unable to find the GUID value of this GUID CName : '%s'.") +ERR_DECPARSE_FILEOPEN = _("Unable to open: [%s].") +ERR_DECPARSE_SECTION_EMPTY = _("Empty sections are not allowed.") +ERR_DECPARSE_SECTION_UE = _("Incorrect UserExtensions format. " + "Must be UserExtenxions.UserId.IdString[.Arch]+.") +ERR_DECPARSE_SECTION_UE_USERID = _("Invalid UserId, must be underscore" + "or alphanumeric characters.") +ERR_DECPARSE_SECTION_UE_IDSTRING = \ + _("Incorrect IdString, must be \" ... \".") +ERR_DECPARSE_ARCH = \ +_("Unknown arch, must be 'common' or start with upper case letter followed by" + " zero or more upper case letters and numbers.") +ERR_DECPARSE_SECTION_COMMA = _("Section cannot end with comma.") +ERR_DECPARSE_SECTION_COMMON = \ +_("'COMMON' must not be used with specific ARCHs in the same section.") +ERR_DECPARSE_SECTION_IDENTIFY = \ +_("Section header must start with and end with brackets[].") +ERR_DECPARSE_SECTION_SUBEMPTY = \ +_("Missing a sub-section name in section: [%s]. " + "All sub-sections need to have names. ") +ERR_DECPARSE_SECTION_SUBTOOMANY = _("Too many DOT splits in [%s].") +ERR_DECPARSE_SECTION_UNKNOW = _("Section name [%s] unknown.") +ERR_DECPARSE_SECTION_FEATUREFLAG = \ +_("[%s] must not be in the same section as other types of PCD.") +ERR_DECPARSE_MACRO_PAIR = _("No macro name/value given.") +ERR_DECPARSE_MACRO_NAME = _("No macro name given.") +ERR_DECPARSE_MACRO_NAME_UPPER = \ +_("Macro name must start with upper case letter followed " +"by zero or more upper case letters or numbers. Current macro name is: [%s].") +ERR_DECPARSE_SECTION_NAME = \ +_('Cannot mix different section names %s.') +ERR_DECPARSE_BACKSLASH = \ +_('Backslash must be the last character on a line and ' + 'preceded by a space character.') +ERR_DECPARSE_BACKSLASH_EMPTY = \ +_('Empty line after previous line that has backslash is not allowed.') +ERR_DECPARSE_REDEFINE = _( + "\"%s\" already defined in line %d.") +ERR_DECPARSE_MACRO_RESOLVE = _("Macro %s in %s cannot be resolved.") +ERR_DECPARSE_UE_DUPLICATE = \ + _("Duplicated UserExtensions header found.") +ERR_DECPARSE_PCDERRORMSG_MISS_VALUE_SPLIT = \ + _("Missing '|' between Pcd's error code and Pcd's error message.") +ERR_DECPARSE_PCD_MISS_ERRORMSG = \ + _("Missing Pcd's error message.") +ERR_DECPARSE_PCD_UNMATCHED_ERRORCODE = \ + _("There is no error message matched with this Pcd error code : %s in both DEC and UNI file.") +ERR_DECPARSE_PCD_NODEFINED = _("The PCD : %s used in the Expression is undefined.") +# +# Used to print the current line content which cause error raise. +# Be attached to the end of every error message above. +# +ERR_DECPARSE_LINE = _(" Parsing line: \"%s\".") + +# +# Warning related strings. +# +WRN_PACKAGE_EXISTED = _( + "A package with this GUID and Version already exists: " + "GUID %s, Version %s.") +WRN_MODULE_EXISTED = _("This module already exists: %s") +WRN_FILE_EXISTED = _("This file already exists: %s") +WRN_FILE_NOT_OVERWRITTEN = \ +_("This file already exist and cannot be overwritten: %s") +WRN_DIST_PKG_INSTALLED = _("This distribution package %s has previously been installed.") +WRN_DIST_NOT_FOUND = _( + "Distribution is not found at location %s") +WRN_MULTI_PCD_RANGES = _( + "A PCD can only have one type of @ValidRange, @ValidList, and @Expression comment") +WRN_MULTI_PCD_VALIDVALUE = _( + "A PCD can only have one of @ValidList comment") +WRN_MULTI_PCD_PROMPT = _( + "A PCD can only have one of @Prompt comment") +WRN_MISSING_USAGE = _("Missing usage") +WRN_INVALID_GUID_TYPE = _("This is and incorrect Guid type: %s") +WRN_MISSING_GUID_TYPE = _("Missing Guid Type") +WRN_INVALID_USAGE = _("This is an incorrect Usage: %s") +WRN_INF_PARSER_MODULE_INVALID_HOB_TYPE = \ + _("This is an incorrect HOB type: %s") +WRN_INF_PARSER_MODULE_INVALID_EVENT_TYPE = \ + _("This is an incorrect EVENT type: %s") +WRN_INF_PARSER_MODULE_INVALID_BOOTMODE_TYPE = \ + _("This is an incorrect BOOTMODE type: %s") +WRN_INVALID_MODULE_TYPE = \ + _("This is an incorrect Module type: %s") +WRN_MODULE_PARSE_FAILED = \ + _("Parsing of this module did not complete correctly: %s.") +WRN_EDK1_INF_FOUND = \ + _("EDK 1 module file found: %s") +WRN_INVALID_COPYRIGHT = \ + _("Copyright information is not right") +WARN_SPECIAL_SECTION_LOCATION_WRONG = _("Warning. A special section should be " + "at the end of a file or at the end of a section.") +WARN_INSTALLED_PACKAGE_NOT_FOUND = \ + _("File not found. The DEC file for a package cannot be found in GUID/Version/Install path: %s %s %s") +WARN_CUSTOMPATH_OVERRIDE_USEGUIDEDPATH = \ + _("option selection of --custom-path will override the option --use-guided-paths") + +# +# Help related strings. +# +HLP_PRINT_DEBUG_INFO = _( + "Print DEBUG statements, where DEBUG_LEVEL is 0-9") +HLP_PRINT_INFORMATIONAL_STATEMENT = _("Print informational statements") +HLP_RETURN_NO_DISPLAY = _( + "Returns only the exit code, informational and error messages are" + " not displayed") +HLP_RETURN_AND_DISPLAY = _( + "Returns the exit code and displays error messages only") +HLP_SPECIFY_PACKAGE_NAME_INSTALL = _( + "Specify the UEFI Distribution Package filename to install") +HLP_SPECIFY_PACKAGE_NAME_CREATE = _( + "Specify the UEFI Distribution Package filename to create") +HLP_SPECIFY_PACKAGE_NAME_REMOVE = _( + "Specify the UEFI Distribution Package filename to remove") +HLP_SPECIFY_TEMPLATE_NAME_CREATE = _( + "Specify Package Information Data filename to create package") +HLP_SPECIFY_DEC_NAME_CREATE = _( + "Specify dec file names to create package") +HLP_SPECIFY_INF_NAME_CREATE = _( + "Specify inf file names to create package") +HLP_LIST_DIST_INSTALLED = _( + "List the UEFI Distribution Packages that have been installed") +HLP_NO_SUPPORT_GUI = _( + "Starting the tool in graphical mode is not supported in this version") +HLP_DISABLE_PROMPT = _( + "Disable user prompts for removing modified files. Valid only when -r is present") +HLP_CUSTOM_PATH_PROMPT = _( + "Enable user prompting for alternate installation directories") +HLP_SKIP_LOCK_CHECK = _( + "Skip the check for multiple instances") +HLP_SPECIFY_PACKAGE_NAME_REPLACE = _( + "Specify the UEFI Distribution Package file name to replace the existing file name") +HLP_SPECIFY_PACKAGE_NAME_TO_BE_REPLACED = _( + "Specify the UEFI Distribution Package file name to be replaced") +HLP_USE_GUIDED_PATHS = _( + "Install packages to the following directory path by default: __") +HLP_TEST_INSTALL = _( + "Specify the UEFI Distribution Package filenames to install") + +MSG_TEST_INSTALL_PASS = _("All distribution package file are satisfied for dependence check.") +MSG_TEST_INSTALL_FAIL = _("NOT all distribution package file are satisfied for dependence check.") diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Logger/ToolError.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Logger/ToolError.py new file mode 100644 index 00000000..f4cf1989 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Logger/ToolError.py @@ -0,0 +1,171 @@ +## @file +# Standardized Error Handling infrastructures. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +ToolError +''' + +import Logger.StringTable as ST + +FILE_OPEN_FAILURE = 1 +FILE_WRITE_FAILURE = 2 +FILE_PARSE_FAILURE = 3 +FILE_READ_FAILURE = 4 +FILE_CREATE_FAILURE = 5 +FILE_CHECKSUM_FAILURE = 6 +FILE_COMPRESS_FAILURE = 7 +FILE_DECOMPRESS_FAILURE = 8 +FILE_MOVE_FAILURE = 9 +FILE_DELETE_FAILURE = 10 +FILE_COPY_FAILURE = 11 +FILE_POSITIONING_FAILURE = 12 +FILE_ALREADY_EXIST = 13 +FILE_NOT_FOUND = 14 +FILE_TYPE_MISMATCH = 15 +FILE_CASE_MISMATCH = 16 +FILE_DUPLICATED = 17 +FILE_UNKNOWN_ERROR = 0x0FFF + +OPTION_UNKNOWN = 0x1000 +OPTION_MISSING = 0x1001 +OPTION_CONFLICT = 0x1002 +OPTION_VALUE_INVALID = 0x1003 +OPTION_DEPRECATED = 0x1004 +OPTION_NOT_SUPPORTED = 0x1005 +OPTION_UNKNOWN_ERROR = 0x1FFF + +PARAMETER_INVALID = 0x2000 +PARAMETER_MISSING = 0x2001 +PARAMETER_UNKNOWN_ERROR = 0x2FFF + +FORMAT_INVALID = 0x3000 +FORMAT_NOT_SUPPORTED = 0x3001 +FORMAT_UNKNOWN = 0x3002 +FORMAT_UNKNOWN_ERROR = 0x3FFF + +RESOURCE_NOT_AVAILABLE = 0x4000 +RESOURCE_ALLOCATE_FAILURE = 0x4001 +RESOURCE_FULL = 0x4002 +RESOURCE_OVERFLOW = 0x4003 +RESOURCE_UNDERRUN = 0x4004 +RESOURCE_UNKNOWN_ERROR = 0x4FFF + +ATTRIBUTE_NOT_AVAILABLE = 0x5000 +ATTRIBUTE_GET_FAILURE = 0x5001 +ATTRIBUTE_SET_FAILURE = 0x5002 +ATTRIBUTE_UPDATE_FAILURE = 0x5003 +ATTRIBUTE_ACCESS_DENIED = 0x5004 +ATTRIBUTE_RETRIEVE_FAILURE = 0x5005 +ATTRIBUTE_UNKNOWN_ERROR = 0x5FFF +ATTRIBUTE_RETRIEVE_FAILURE = 0x5F00 + +IO_NOT_READY = 0x6000 +IO_BUSY = 0x6001 +IO_TIMEOUT = 0x6002 +IO_UNKNOWN_ERROR = 0x6FFF + +COMMAND_FAILURE = 0x7000 + +CODE_ERROR = 0xC0DE + +AUTOGEN_ERROR = 0xF000 +PARSER_ERROR = 0xF001 +BUILD_ERROR = 0xF002 +GENFDS_ERROR = 0xF003 +ECC_ERROR = 0xF004 +EOT_ERROR = 0xF005 +DDC_ERROR = 0xF009 +WARNING_AS_ERROR = 0xF006 +MIGRATION_ERROR = 0xF010 +EDK1_INF_ERROR = 0xF011 +ABORT_ERROR = 0xFFFE +UNKNOWN_ERROR = 0xFFFF + +UPT_ALREADY_INSTALLED_ERROR = 0xD000 +UPT_ENVIRON_MISSING_ERROR = 0xD001 +UPT_REPKG_ERROR = 0xD002 +UPT_ALREADY_RUNNING_ERROR = 0xD003 +UPT_MUL_DEC_ERROR = 0xD004 +UPT_DB_UPDATE_ERROR = 0xD005 +UPT_INI_PARSE_ERROR = 0xE000 + +## Error message of each error code +# +gERROR_MESSAGE = { + FILE_NOT_FOUND : ST.ERR_FILE_NOT_FOUND, + FILE_OPEN_FAILURE : ST.ERR_FILE_OPEN_FAILURE, + FILE_WRITE_FAILURE : ST.ERR_FILE_WRITE_FAILURE, + FILE_PARSE_FAILURE : ST.ERR_FILE_PARSE_FAILURE, + FILE_READ_FAILURE : ST.ERR_FILE_READ_FAILURE, + FILE_CREATE_FAILURE : ST.ERR_FILE_CREATE_FAILURE, + FILE_CHECKSUM_FAILURE : ST.ERR_FILE_CHECKSUM_FAILURE, + FILE_COMPRESS_FAILURE : ST.ERR_FILE_COMPRESS_FAILURE, + FILE_DECOMPRESS_FAILURE : ST.ERR_FILE_DECOMPRESS_FAILURE, + FILE_MOVE_FAILURE : ST.ERR_FILE_MOVE_FAILURE, + FILE_DELETE_FAILURE : ST.ERR_FILE_DELETE_FAILURE, + FILE_COPY_FAILURE : ST.ERR_FILE_COPY_FAILURE, + FILE_POSITIONING_FAILURE: ST.ERR_FILE_POSITIONING_FAILURE, + FILE_ALREADY_EXIST : ST.ERR_FILE_ALREADY_EXIST, + FILE_TYPE_MISMATCH : ST.ERR_FILE_TYPE_MISMATCH , + FILE_CASE_MISMATCH : ST.ERR_FILE_CASE_MISMATCH, + FILE_DUPLICATED : ST.ERR_FILE_DUPLICATED, + FILE_UNKNOWN_ERROR : ST.ERR_FILE_UNKNOWN_ERROR, + + OPTION_UNKNOWN : ST.ERR_OPTION_UNKNOWN, + OPTION_MISSING : ST.ERR_OPTION_MISSING, + OPTION_CONFLICT : ST.ERR_OPTION_CONFLICT, + OPTION_VALUE_INVALID : ST.ERR_OPTION_VALUE_INVALID, + OPTION_DEPRECATED : ST.ERR_OPTION_DEPRECATED, + OPTION_NOT_SUPPORTED : ST.ERR_OPTION_NOT_SUPPORTED, + OPTION_UNKNOWN_ERROR : ST.ERR_OPTION_UNKNOWN_ERROR, + + PARAMETER_INVALID : ST.ERR_PARAMETER_INVALID, + PARAMETER_MISSING : ST.ERR_PARAMETER_MISSING, + PARAMETER_UNKNOWN_ERROR : ST.ERR_PARAMETER_UNKNOWN_ERROR, + + FORMAT_INVALID : ST.ERR_FORMAT_INVALID, + FORMAT_NOT_SUPPORTED : ST.ERR_FORMAT_NOT_SUPPORTED, + FORMAT_UNKNOWN : ST.ERR_FORMAT_UNKNOWN, + FORMAT_UNKNOWN_ERROR : ST.ERR_FORMAT_UNKNOWN_ERROR, + + RESOURCE_NOT_AVAILABLE : ST.ERR_RESOURCE_NOT_AVAILABLE, + RESOURCE_ALLOCATE_FAILURE : ST.ERR_RESOURCE_ALLOCATE_FAILURE, + RESOURCE_FULL : ST.ERR_RESOURCE_FULL, + RESOURCE_OVERFLOW : ST.ERR_RESOURCE_OVERFLOW, + RESOURCE_UNDERRUN : ST.ERR_RESOURCE_UNDERRUN, + RESOURCE_UNKNOWN_ERROR : ST.ERR_RESOURCE_UNKNOWN_ERROR, + + ATTRIBUTE_NOT_AVAILABLE : ST.ERR_ATTRIBUTE_NOT_AVAILABLE, + ATTRIBUTE_RETRIEVE_FAILURE : ST.ERR_ATTRIBUTE_RETRIEVE_FAILURE, + ATTRIBUTE_SET_FAILURE : ST.ERR_ATTRIBUTE_SET_FAILURE, + ATTRIBUTE_UPDATE_FAILURE: ST.ERR_ATTRIBUTE_UPDATE_FAILURE, + ATTRIBUTE_ACCESS_DENIED : ST.ERR_ATTRIBUTE_ACCESS_DENIED, + ATTRIBUTE_UNKNOWN_ERROR : ST.ERR_ATTRIBUTE_UNKNOWN_ERROR, + + COMMAND_FAILURE : ST.ERR_COMMAND_FAILURE, + + IO_NOT_READY : ST.ERR_IO_NOT_READY, + IO_BUSY : ST.ERR_IO_BUSY, + IO_TIMEOUT : ST.ERR_IO_TIMEOUT, + IO_UNKNOWN_ERROR : ST.ERR_IO_UNKNOWN_ERROR, + + UNKNOWN_ERROR : ST.ERR_UNKNOWN_ERROR, + + UPT_ALREADY_INSTALLED_ERROR : ST.ERR_UPT_ALREADY_INSTALLED_ERROR, + UPT_ENVIRON_MISSING_ERROR : ST.ERR_UPT_ENVIRON_MISSING_ERROR, + UPT_REPKG_ERROR : ST.ERR_UPT_REPKG_ERROR, + UPT_ALREADY_RUNNING_ERROR : ST.ERR_UPT_ALREADY_RUNNING_ERROR, + UPT_MUL_DEC_ERROR : ST.ERR_MUL_DEC_ERROR, + UPT_INI_PARSE_ERROR : ST.ERR_UPT_INI_PARSE_ERROR, +} + +## Exception indicating a fatal error +# +class FatalError(Exception): + pass + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Logger/__init__.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Logger/__init__.py new file mode 100644 index 00000000..cb04e7ea --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Logger/__init__.py @@ -0,0 +1,14 @@ +## @file +# Python 'Logger' package initialization file. +# +# This file is required to make Python interpreter treat the directory +# as containing package. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +Logger +''' diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/MkPkg.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/MkPkg.py new file mode 100755 index 00000000..d700d057 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/MkPkg.py @@ -0,0 +1,274 @@ +## @file +# Install distribution package. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +MkPkg +''' + +## +# Import Modules +# +from os import remove +from os import getcwd +from os import chdir +import os.path +from sys import stdin +from sys import platform +from traceback import format_exc +from platform import python_version +from hashlib import md5 +from time import strftime +from time import localtime +from uuid import uuid4 + +from Logger import StringTable as ST +from Logger.ToolError import OPTION_UNKNOWN_ERROR +from Logger.ToolError import OPTION_VALUE_INVALID +from Logger.ToolError import ABORT_ERROR +from Logger.ToolError import UPT_REPKG_ERROR +from Logger.ToolError import CODE_ERROR +from Logger.ToolError import FatalError +from Logger.ToolError import FILE_NOT_FOUND +import Logger.Log as Logger + +from Xml.XmlParser import DistributionPackageXml +from Xml.IniToXml import IniToXml + +from Library import GlobalData +from Library.ParserValidate import IsValidPath + +from Core.DistributionPackageClass import DistributionPackageClass +from Core.PackageFile import PackageFile +from Common.MultipleWorkspace import MultipleWorkspace as mws + +## CheckForExistingDp +# +# Check if there is a same name DP file existing +# @param Path: The path to be checked +# +def CheckForExistingDp(Path): + if os.path.exists(Path): + Logger.Info(ST.MSG_DISTRIBUTION_PACKAGE_FILE_EXISTS % Path) + Input = stdin.readline() + Input = Input.replace('\r', '').replace('\n', '') + if Input.upper() != "Y": + Logger.Error("\nMkPkg", ABORT_ERROR, ST.ERR_USER_ABORT, RaiseError=True) + +## Tool entrance method +# +# This method mainly dispatch specific methods per the command line options. +# If no error found, return zero value so the caller of this tool can know +# if it's executed successfully or not. +# +# +def Main(Options = None): + if Options is None: + Logger.Error("\nMkPkg", OPTION_UNKNOWN_ERROR, ST.ERR_OPTION_NOT_FOUND) + try: + DataBase = GlobalData.gDB + ContentFileClosed = True + WorkspaceDir = GlobalData.gWORKSPACE + + # + # Init PackFileToCreate + # + if not Options.PackFileToCreate: + Logger.Error("\nMkPkg", OPTION_UNKNOWN_ERROR, ST.ERR_OPTION_NOT_FOUND) + + # + # Handle if the distribution package file already exists + # + CheckForExistingDp(Options.PackFileToCreate) + + # + # Check package file existing and valid + # + CheckFileList('.DEC', Options.PackageFileList, ST.ERR_INVALID_PACKAGE_NAME, ST.ERR_INVALID_PACKAGE_PATH) + # + # Check module file existing and valid + # + CheckFileList('.INF', Options.ModuleFileList, ST.ERR_INVALID_MODULE_NAME, ST.ERR_INVALID_MODULE_PATH) + + # + # Get list of files that installed with RePackage attribute available + # + RePkgDict = DataBase.GetRePkgDict() + + ContentFile = PackageFile(GlobalData.gCONTENT_FILE, "w") + ContentFileClosed = False + + # + # Add temp distribution header + # + if Options.PackageInformationDataFile: + XmlFile = IniToXml(Options.PackageInformationDataFile) + DistPkg = DistributionPackageXml().FromXml(XmlFile) + remove(XmlFile) + + # + # add distribution level tool/misc files + # before pack, current dir should be workspace dir, else the full + # path will be in the pack file + # + Cwd = getcwd() + chdir(WorkspaceDir) + ToolObject = DistPkg.Tools + MiscObject = DistPkg.MiscellaneousFiles + FileList = [] + if ToolObject: + FileList += ToolObject.GetFileList() + if MiscObject: + FileList += MiscObject.GetFileList() + for FileObject in FileList: + # + # If you have unicode file names, please convert them to byte + # strings in your desired encoding before passing them to + # write(). + # + FromFile = os.path.normpath(FileObject.GetURI()).encode('utf_8') + FileFullPath = mws.join(WorkspaceDir, FromFile) + if FileFullPath in RePkgDict: + (DpGuid, DpVersion, DpName, Repackage) = RePkgDict[FileFullPath] + if not Repackage: + Logger.Error("\nMkPkg", + UPT_REPKG_ERROR, + ST.ERR_UPT_REPKG_ERROR, + ExtraData=ST.MSG_REPKG_CONFLICT %\ + (FileFullPath, DpGuid, DpVersion, DpName) + ) + else: + DistPkg.Header.RePackage = True + ContentFile.PackFile(FromFile) + chdir(Cwd) + + # + # Add init dp information + # + else: + DistPkg = DistributionPackageClass() + DistPkg.Header.Name = 'Distribution Package' + DistPkg.Header.Guid = str(uuid4()) + DistPkg.Header.Version = '1.0' + + DistPkg.GetDistributionPackage(WorkspaceDir, Options.PackageFileList, \ + Options.ModuleFileList) + FileList, MetaDataFileList = DistPkg.GetDistributionFileList() + for File in FileList + MetaDataFileList: + FileFullPath = os.path.normpath(os.path.join(WorkspaceDir, File)) + # + # check whether file was included in a distribution that can not + # be repackaged + # + if FileFullPath in RePkgDict: + (DpGuid, DpVersion, DpName, Repackage) = RePkgDict[FileFullPath] + if not Repackage: + Logger.Error("\nMkPkg", + UPT_REPKG_ERROR, + ST.ERR_UPT_REPKG_ERROR, + ExtraData = \ + ST.MSG_REPKG_CONFLICT %(FileFullPath, DpName, \ + DpGuid, DpVersion) + ) + else: + DistPkg.Header.RePackage = True + + Cwd = getcwd() + chdir(WorkspaceDir) + ContentFile.PackFiles(FileList) + chdir(Cwd) + + Logger.Verbose(ST.MSG_COMPRESS_DISTRIBUTION_PKG) + + ContentFile.Close() + ContentFileClosed = True + + # + # Add Md5Signature + # + DistPkg.Header.Signature = md5(open(str(ContentFile), 'rb').read()).hexdigest() + # + # Add current Date + # + DistPkg.Header.Date = str(strftime("%Y-%m-%dT%H:%M:%S", localtime())) + + # + # Finish final dp file + # + DistPkgFile = PackageFile(Options.PackFileToCreate, "w") + DistPkgFile.PackFile(str(ContentFile)) + DistPkgXml = DistributionPackageXml() + DistPkgFile.PackData(DistPkgXml.ToXml(DistPkg), GlobalData.gDESC_FILE) + DistPkgFile.Close() + Logger.Quiet(ST.MSG_FINISH) + ReturnCode = 0 + + except FatalError as XExcept: + ReturnCode = XExcept.args[0] + if Logger.GetLevel() <= Logger.DEBUG_9: + Logger.Quiet(ST.MSG_PYTHON_ON % \ + (python_version(), platform) + format_exc()) + except KeyboardInterrupt: + ReturnCode = ABORT_ERROR + if Logger.GetLevel() <= Logger.DEBUG_9: + Logger.Quiet(ST.MSG_PYTHON_ON % \ + (python_version(), platform) + format_exc()) + except OSError: + pass + except: + Logger.Error( + "\nMkPkg", + CODE_ERROR, + ST.ERR_UNKNOWN_FATAL_CREATING_ERR % \ + Options.PackFileToCreate, + ExtraData=ST.MSG_SEARCH_FOR_HELP % ST.MSG_EDKII_MAIL_ADDR, + RaiseError=False + ) + Logger.Quiet(ST.MSG_PYTHON_ON % \ + (python_version(), platform) + format_exc()) + ReturnCode = CODE_ERROR + finally: + if os.path.exists(GlobalData.gCONTENT_FILE): + if not ContentFileClosed: + ContentFile.Close() + os.remove(GlobalData.gCONTENT_FILE) + + return ReturnCode + + +## CheckFileList +# +# @param QualifiedExt: QualifiedExt +# @param FileList: FileList +# @param ErrorStringExt: ErrorStringExt +# @param ErrorStringFullPath: ErrorStringFullPath +# +def CheckFileList(QualifiedExt, FileList, ErrorStringExt, ErrorStringFullPath): + if not FileList: + return + WorkspaceDir = GlobalData.gWORKSPACE + WorkspaceDir = os.path.normpath(WorkspaceDir) + for Item in FileList: + Ext = os.path.splitext(Item)[1] + if Ext.upper() != QualifiedExt.upper(): + Logger.Error("\nMkPkg", OPTION_VALUE_INVALID, \ + ErrorStringExt % Item) + + Item = os.path.normpath(Item) + Path = mws.join(WorkspaceDir, Item) + if not os.path.exists(Path): + Logger.Error("\nMkPkg", FILE_NOT_FOUND, ST.ERR_NOT_FOUND % Item) + elif Item == Path: + Logger.Error("\nMkPkg", OPTION_VALUE_INVALID, + ErrorStringFullPath % Item) + elif not IsValidPath(Item, WorkspaceDir): + Logger.Error("\nMkPkg", OPTION_VALUE_INVALID, \ + ErrorStringExt % Item) + + if not os.path.split(Item)[0]: + Logger.Error("\nMkPkg", OPTION_VALUE_INVALID, \ + ST.ERR_INVALID_METAFILE_PATH % Item) diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/POM/CommonObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/POM/CommonObject.py new file mode 100755 index 00000000..0cd33ef0 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/POM/CommonObject.py @@ -0,0 +1,953 @@ +## @file +# This file is used to define common items of class object +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +''' +Common Object +''' +from Library.DataType import TAB_LANGUAGE_EN_US + +## HelpTextObject +# +# @param object: Inherited from object class +# +class HelpTextObject(object): + def __init__(self): + self.HelpText = TextObject() + + def SetHelpText(self, HelpText): + self.HelpText = HelpText + + def GetHelpText(self): + return self.HelpText + +## HelpTextListObject +# +# @param object: Inherited from object class +# +class HelpTextListObject(object): + def __init__(self): + self.HelpTextList = [] + + def SetHelpTextList(self, HelpTextList): + self.HelpTextList = HelpTextList + + def GetHelpTextList(self): + return self.HelpTextList + +## PromptListObject +# +# @param object: Inherited from object class +# +class PromptListObject(object): + def __init__(self): + self.PromptList = [] + + def SetPromptList(self, PromptList): + self.PromptList = PromptList + + def GetPromptList(self): + return self.PromptList + +## CommonPropertiesObject +# +# This class defined common attribution used in Module/Platform/Package files +# +# @param object: Inherited from object class +# @param Usage: Input value for Usage, default is [] +# @param FeatureFlag: Input value for FeatureFalg, default is '' +# @param SupArchList: Input value for SupArchList, default is [] +# @param HelpText: Input value for HelpText, default is '' +# @param HelpTextList: Input value for HelpTextList, default is [] +# +class CommonPropertiesObject(HelpTextObject, HelpTextListObject): + def __init__(self): + self.Usage = [] + self.FeatureFlag = '' + self.SupArchList = [] + self.GuidValue = '' + HelpTextObject.__init__(self) + HelpTextListObject.__init__(self) + + def SetUsage(self, Usage): + self.Usage = Usage + + def GetUsage(self): + return self.Usage + + def SetFeatureFlag(self, FeatureFlag): + self.FeatureFlag = FeatureFlag + + def GetFeatureFlag(self): + return self.FeatureFlag + + def SetSupArchList(self, SupArchList): + self.SupArchList = SupArchList + + def GetSupArchList(self): + return self.SupArchList + + def SetGuidValue(self, GuidValue): + self.GuidValue = GuidValue + + def GetGuidValue(self): + return self.GuidValue + +## CommonHeaderObject +# +# This class defined common header items used in Module/Platform/Package files +# +# @param object: Inherited from object class +# +class CommonHeaderObject(object): + def __init__(self): + self.AbstractList = [] + self.DescriptionList = [] + self.CopyrightList = [] + self.LicenseList = [] + + def SetAbstract(self, Abstract): + if isinstance(Abstract, list): + self.AbstractList = Abstract + else: + self.AbstractList.append(Abstract) + + def GetAbstract(self): + return self.AbstractList + + def SetDescription(self, Description): + if isinstance(Description, list): + self.DescriptionList = Description + else: + self.DescriptionList.append(Description) + + def GetDescription(self): + return self.DescriptionList + + def SetCopyright(self, Copyright): + if isinstance(Copyright, list): + self.CopyrightList = Copyright + else: + self.CopyrightList.append(Copyright) + + def GetCopyright(self): + return self.CopyrightList + + def SetLicense(self, License): + if isinstance(License, list): + self.LicenseList = License + else: + self.LicenseList.append(License) + + def GetLicense(self): + return self.LicenseList + +## BinaryHeaderObject +# +# This class defined Binary header items used in Module/Platform/Package files +# +# @param object: Inherited from object class +# +class BinaryHeaderObject(object): + def __init__(self): + self.BinaryHeaderAbstractList = [] + self.BinaryHeaderDescriptionList = [] + self.BinaryHeaderCopyrightList = [] + self.BinaryHeaderLicenseList = [] + + def SetBinaryHeaderAbstract(self, Abstract): + if isinstance(Abstract, list) and Abstract: + self.BinaryHeaderAbstractList = Abstract + elif isinstance(Abstract, tuple) and Abstract[1]: + self.BinaryHeaderAbstractList.append(Abstract) + + def GetBinaryHeaderAbstract(self): + return self.BinaryHeaderAbstractList + + def SetBinaryHeaderDescription(self, Description): + if isinstance(Description, list) and Description: + self.BinaryHeaderDescriptionList = Description + elif isinstance(Description, tuple) and Description[1]: + self.BinaryHeaderDescriptionList.append(Description) + + def GetBinaryHeaderDescription(self): + return self.BinaryHeaderDescriptionList + + def SetBinaryHeaderCopyright(self, Copyright): + if isinstance(Copyright, list) and Copyright: + self.BinaryHeaderCopyrightList = Copyright + elif isinstance(Copyright, tuple) and Copyright[1]: + self.BinaryHeaderCopyrightList.append(Copyright) + + def GetBinaryHeaderCopyright(self): + return self.BinaryHeaderCopyrightList + + def SetBinaryHeaderLicense(self, License): + if isinstance(License, list) and License: + self.BinaryHeaderLicenseList = License + elif isinstance(License, tuple) and License[1]: + self.BinaryHeaderLicenseList.append(License) + + def GetBinaryHeaderLicense(self): + return self.BinaryHeaderLicenseList + +## ClonedRecordObject +# +# This class defined ClonedRecord items used in Module/Platform/Package files +# +# @param object: Inherited from object class +# +class ClonedRecordObject(object): + def __init__(self): + self.IdNum = 0 + self.FarGuid = '' + self.PackageGuid = '' + self.PackageVersion = '' + self.ModuleGuid = '' + self.ModuleVersion = '' + + def SetId(self, IdNo): + self.IdNum = IdNo + + def GetId(self): + return self.IdNum + + def SetFarGuid(self, FarGuid): + self.FarGuid = FarGuid + + def GetFarGuid(self): + return self.FarGuid + + def SetPackageGuid(self, PackageGuid): + self.PackageGuid = PackageGuid + + def GetPackageGuid(self): + return self.PackageGuid + + def SetPackageVersion(self, PackageVersion): + self.PackageVersion = PackageVersion + + def GetPackageVersion(self): + return self.PackageVersion + + def SetModuleGuid(self, ModuleGuid): + self.ModuleGuid = ModuleGuid + + def GetModuleGuid(self): + return self.ModuleGuid + + def SetModuleVersion(self, ModuleVersion): + self.ModuleVersion = ModuleVersion + + def GetModuleVersion(self): + return self.ModuleVersion + +## TextObject +# +# This class defined Text item used in PKG file +# +# @param object: Inherited from object class +# +class TextObject(object): + def __init__(self): + self.Lang = TAB_LANGUAGE_EN_US + self.String = '' + + def SetLang(self, Lang): + self.Lang = Lang + + def GetLang(self): + return self.Lang + + def SetString(self, String): + self.String = String + + def GetString(self): + return self.String + +## FileNameObject +# +# This class defined File item used in module, for binary files +# +# @param CommonPropertiesObject: Inherited from CommonPropertiesObject class +# +class FileNameObject(CommonPropertiesObject): + def __init__(self): + self.FileType = '' + self.Filename = '' + CommonPropertiesObject.__init__(self) + + def SetFileType(self, FileType): + self.FileType = FileType + + def GetFileType(self): + return self.FileType + + def SetFilename(self, Filename): + self.Filename = Filename + + def GetFilename(self): + return self.Filename + +## FileObject +# +# This class defined File item used in PKG file +# +# @param object: Inherited from object class +# +class FileObject(object): + def __init__(self): + self.Executable = '' + self.Uri = '' + self.OsType = '' + + def SetExecutable(self, Executable): + self.Executable = Executable + + def GetExecutable(self): + return self.Executable + + def SetURI(self, URI): + self.Uri = URI + + def GetURI(self): + return self.Uri + + def SetOS(self, OsType): + self.OsType = OsType + + def GetOS(self): + return self.OsType + +## +# MiscFileObject is used for xml +# +# @param CommonHeaderObject: Inherited from CommonHeaderObject class +# +class MiscFileObject(CommonHeaderObject): + def __init__(self): + self.Name = '' + self.FileList = [] + CommonHeaderObject.__init__(self) + + def SetName(self, Name): + self.Name = Name + + def GetName(self): + return self.Name + + def SetFileList(self, FileList): + self.FileList = FileList + + def GetFileList(self): + return self.FileList + +## +# ToolsObject +# +class ToolsObject(MiscFileObject): + pass + +## GuidVersionObject +# +# This class defined GUID/Version items used in PKG file +# +# @param object: Inherited from object class +# +class GuidVersionObject(object): + def __init__(self): + self.Guid = '' + self.Version = '' + + def SetGuid(self, Guid): + self.Guid = Guid + + def GetGuid(self): + return self.Guid + + def SetVersion(self, Version): + self.Version = Version + + def GetVersion(self): + return self.Version + +## IdentificationObject +# +# This class defined Identification items used in Module/Platform/Package files +# +# @param object: Inherited from object class +# +class IdentificationObject(GuidVersionObject): + def __init__(self): + self.Name = '' + self.BaseName = '' + self.FileName = '' + self.FullPath = '' + self.RelaPath = '' + self.PackagePath = '' + self.ModulePath = '' + self.CombinePath = '' + GuidVersionObject.__init__(self) + + def SetName(self, Name): + self.Name = Name + + def GetName(self): + return self.Name + + def SetBaseName(self, BaseName): + self.BaseName = BaseName + + def GetBaseName(self): + return self.BaseName + + def SetFileName(self, FileName): + self.FileName = FileName + + def GetFileName(self): + return self.FileName + + def SetFullPath(self, FullPath): + self.FullPath = FullPath + + def GetFullPath(self): + return self.FullPath + + def SetRelaPath(self, RelaPath): + self.RelaPath = RelaPath + + def GetRelaPath(self): + return self.RelaPath + + def SetPackagePath(self, PackagePath): + self.PackagePath = PackagePath + + def GetPackagePath(self): + return self.PackagePath + + def SetModulePath(self, ModulePath): + self.ModulePath = ModulePath + + def GetModulePath(self): + return self.ModulePath + + def SetCombinePath(self, CombinePath): + self.CombinePath = CombinePath + + def GetCombinePath(self): + return self.CombinePath + +## GuidProtocolPpiCommonObject +# +# This class defined Guid, Protocol and Ppi like items used in +# Module/Platform/Package files +# +# @param CommonPropertiesObject: Inherited from CommonPropertiesObject class +# +class GuidProtocolPpiCommonObject(CommonPropertiesObject): + def __init__(self): + self.Name = '' + self.CName = '' + self.Guid = '' + self.SupModuleList = [] + CommonPropertiesObject.__init__(self) + + def SetName(self, Name): + self.Name = Name + + def GetName(self): + return self.Name + + def SetCName(self, CName): + self.CName = CName + + def GetCName(self): + return self.CName + + def SetGuid(self, Guid): + self.Guid = Guid + + def GetGuid(self): + return self.Guid + + def SetSupModuleList(self, SupModuleList): + self.SupModuleList = SupModuleList + + def GetSupModuleList(self): + return self.SupModuleList + +## GuidObject +# +# This class defined Guid item used in Module/Platform/Package files +# +# @param GuidProtocolPpiCommonObject: GuidProtocolPpiCommonObject +# +class GuidObject(GuidProtocolPpiCommonObject): + def __init__(self): + self.VariableName = '' + self.GuidTypeList = [] + GuidProtocolPpiCommonObject.__init__(self) + def SetVariableName(self, VariableName): + self.VariableName = VariableName + + def GetVariableName(self): + return self.VariableName + + def SetGuidTypeList(self, GuidTypeList): + self.GuidTypeList = GuidTypeList + + def GetGuidTypeList(self): + return self.GuidTypeList + +## ProtocolObject +# +# This class defined Protocol item used in Module/Platform/Package files +# +# @param GuidProtocolPpiCommonObject: Inherited from +# GuidProtocolPpiCommonObject +# +class ProtocolObject(GuidProtocolPpiCommonObject): + def __init__(self): + self.Notify = False + GuidProtocolPpiCommonObject.__init__(self) + def SetNotify(self, Notify): + self.Notify = Notify + + def GetNotify(self): + return self.Notify + +## PpiObject +# +# This class defined Ppi item used in Module/Platform/Package files +# +# @param GuidProtocolPpiCommonObject: Inherited from +# GuidProtocolPpiCommonObject +# +class PpiObject(GuidProtocolPpiCommonObject): + def __init__(self): + self.Notify = False + GuidProtocolPpiCommonObject.__init__(self) + def SetNotify(self, Notify): + self.Notify = Notify + + def GetNotify(self): + return self.Notify + +## DefineObject +# +# This class defined item DEFINE used in Module/Platform/Package files +# +# @param object: Inherited from object class +# +class DefineClass(object): + def __init__(self): + self.Define = {} + +## UserExtensionObject +# +# @param object: Inherited from object class +# +class UserExtensionObject(object): + def __init__(self): + self.UserID = '' + self.Identifier = '' + self.BinaryAbstractList = [] + self.BinaryDescriptionList = [] + self.BinaryCopyrightList = [] + self.BinaryLicenseList = [] + self.UniLangDefsList = [] + # + # { Statement : Arch , ... } + # + self.DefinesDict = {} + # + # { Arch : Statement , ... } + # + self.BuildOptionDict = {} + self.IncludesDict = {} + self.SourcesDict = {} + self.BinariesDict = {} + # + # UserExtension statement from meta-data file [UserExtension] section + # + self.Statement = '' + self.SupArchList = [] + + def SetStatement(self, Statement): + self.Statement = Statement + + def GetStatement(self): + return self.Statement + + def SetSupArchList(self, ArchList): + self.SupArchList = ArchList + + def GetSupArchList(self): + return self.SupArchList + + def SetUserID(self, UserID): + self.UserID = UserID + + def GetUserID(self): + return self.UserID + + def SetIdentifier(self, Identifier): + self.Identifier = Identifier + + def GetIdentifier(self): + return self.Identifier + + def SetUniLangDefsList(self, UniLangDefsList): + self.UniLangDefsList = UniLangDefsList + + def GetUniLangDefsList(self): + return self.UniLangDefsList + + def SetBinaryAbstract(self, BinaryAbstractList): + self.BinaryAbstractList = BinaryAbstractList + + def GetBinaryAbstract(self, Lang=None): + if Lang: + for (Key, Value) in self.BinaryAbstractList: + if Key == Lang: + return Value + return None + else: + return self.BinaryAbstractList + + def SetBinaryDescription(self, BinaryDescriptionList): + self.BinaryDescriptionList = BinaryDescriptionList + + def GetBinaryDescription(self, Lang=None): + if Lang: + for (Key, Value) in self.BinaryDescriptionList: + if Key == Lang: + return Value + return None + else: + return self.BinaryDescriptionList + + def SetBinaryCopyright(self, BinaryCopyrightList): + self.BinaryCopyrightList = BinaryCopyrightList + + def GetBinaryCopyright(self, Lang=None): + if Lang: + for (Key, Value) in self.BinaryCopyrightList: + if Key == Lang: + return Value + return None + else: + return self.BinaryCopyrightList + + def SetBinaryLicense(self, BinaryLicenseList): + self.BinaryLicenseList = BinaryLicenseList + + def GetBinaryLicense(self, Lang=None): + if Lang: + for (Key, Value) in self.BinaryLicenseList: + if Key == Lang: + return Value + return None + else: + return self.BinaryLicenseList + + def SetDefinesDict(self, DefinesDict): + self.DefinesDict = DefinesDict + + def GetDefinesDict(self): + return self.DefinesDict + + def SetBuildOptionDict(self, BuildOptionDict): + self.BuildOptionDict = BuildOptionDict + + def GetBuildOptionDict(self): + return self.BuildOptionDict + + def SetIncludesDict(self, IncludesDict): + self.IncludesDict = IncludesDict + + def GetIncludesDict(self): + return self.IncludesDict + + def SetSourcesDict(self, SourcesDict): + self.SourcesDict = SourcesDict + + def GetSourcesDict(self): + return self.SourcesDict + + def SetBinariesDict(self, BinariesDict): + self.BinariesDict = BinariesDict + + def GetBinariesDict(self): + return self.BinariesDict + +## LibraryClassObject +# +# This class defined Library item used in Module/Platform/Package files +# +# @param CommonPropertiesObject: Inherited from CommonPropertiesObject class +# +class LibraryClassObject(CommonPropertiesObject): + def __init__(self): + self.LibraryClass = '' + self.IncludeHeader = '' + self.SupModuleList = [] + self.RecommendedInstance = GuidVersionObject() + CommonPropertiesObject.__init__(self) + + def SetLibraryClass(self, LibraryClass): + self.LibraryClass = LibraryClass + + def GetLibraryClass(self): + return self.LibraryClass + + def SetSupModuleList(self, SupModuleList): + self.SupModuleList = SupModuleList + + def GetSupModuleList(self): + return self.SupModuleList + + def SetIncludeHeader(self, IncludeHeader): + self.IncludeHeader = IncludeHeader + + def GetIncludeHeader(self): + return self.IncludeHeader + + def SetRecommendedInstance(self, RecommendedInstance): + self.RecommendedInstance = RecommendedInstance + + def GetRecommendedInstance(self): + return self.RecommendedInstance + + +## PcdErrorObject +# +# @param object: Inherited from object class +# +class PcdErrorObject(object): + def __init__(self): + self.ValidValue = '' + self.ValidValueLang = '' + self.ValidValueRange = '' + self.Expression = '' + self.ErrorNumber = '' + self.ErrorMessageList = [] + self.TokenSpaceGuidCName = '' + self.CName = '' + self.FileLine = '' + self.LineNum = 0 + + def SetValidValue(self, ValidValue): + self.ValidValue = ValidValue + + def GetValidValue(self): + return self.ValidValue + + def SetValidValueLang(self, ValidValueLang): + self.ValidValueLang = ValidValueLang + + def GetValidValueLang(self): + return self.ValidValueLang + + def SetValidValueRange(self, ValidValueRange): + self.ValidValueRange = ValidValueRange + + def GetValidValueRange(self): + return self.ValidValueRange + + def SetExpression(self, Expression): + self.Expression = Expression + + def GetExpression(self): + return self.Expression + + def SetErrorNumber(self, ErrorNumber): + self.ErrorNumber = ErrorNumber + + def GetErrorNumber(self): + return self.ErrorNumber + + def SetErrorMessageList(self, ErrorMessageList): + self.ErrorMessageList = ErrorMessageList + + def GetErrorMessageList(self): + return self.ErrorMessageList + + def SetTokenSpaceGuidCName(self, TokenSpaceGuidCName): + self.TokenSpaceGuidCName = TokenSpaceGuidCName + + def GetTokenSpaceGuidCName(self): + return self.TokenSpaceGuidCName + + def SetCName(self, CName): + self.CName = CName + + def GetCName(self): + return self.CName + + def SetFileLine(self, FileLine): + self.FileLine = FileLine + + def GetFileLine(self): + return self.FileLine + + def SetLineNum(self, LineNum): + self.LineNum = LineNum + + def GetLineNum(self): + return self.LineNum + + +## IncludeObject +# +# This class defined Include item used in Module/Platform/Package files +# +# @param CommonPropertiesObject: Inherited from CommonPropertiesObject class +# +class IncludeObject(CommonPropertiesObject): + def __init__(self): + self.FilePath = '' + self.ModuleType = '' + self.SupModuleList = [] + self.Comment = '' + CommonPropertiesObject.__init__(self) + + def SetFilePath(self, FilePath): + self.FilePath = FilePath + + def GetFilePath(self): + return self.FilePath + + def SetModuleType(self, ModuleType): + self.ModuleType = ModuleType + + def GetModuleType(self): + return self.ModuleType + + def SetSupModuleList(self, SupModuleList): + self.SupModuleList = SupModuleList + + def GetSupModuleList(self): + return self.SupModuleList + + def SetComment(self, Comment): + self.Comment = Comment + + def GetComment(self): + return self.Comment + +## PcdObject +# +# This class defined Pcd item used in Module/Platform/Package files +# +# @param CName: Input value for CName, default is '' +# @param Token: Input value for Token, default is '' +# @param TokenSpaceGuidCName: Input value for TokenSpaceGuidCName, default is +# '' +# @param DatumType: Input value for DatumType, default is '' +# @param MaxDatumSize: Input value for MaxDatumSize, default is '' +# @param DefaultValue: Input value for DefaultValue, default is '' +# @param ItemType: Input value for ItemType, default is '' +# @param ValidUsage: Input value for ValidUsage, default is [] +# @param SkuInfoList: Input value for SkuInfoList, default is {} +# @param SupModuleList: Input value for SupModuleList, default is [] +# +class PcdObject(CommonPropertiesObject, HelpTextListObject, PromptListObject): + def __init__(self): + self.PcdCName = '' + self.CName = '' + self.Token = '' + self.TokenSpaceGuidCName = '' + self.TokenSpaceGuidValue = '' + self.DatumType = '' + self.MaxDatumSize = '' + self.DefaultValue = '' + self.Offset = '' + self.ValidUsage = '' + self.ItemType = '' + self.PcdErrorsList = [] + self.SupModuleList = [] + CommonPropertiesObject.__init__(self) + HelpTextListObject.__init__(self) + PromptListObject.__init__(self) + + def SetPcdCName(self, PcdCName): + self.PcdCName = PcdCName + + def GetPcdCName(self): + return self.PcdCName + + def SetCName(self, CName): + self.CName = CName + + def GetCName(self): + return self.CName + + def SetToken(self, Token): + self.Token = Token + + def GetOffset(self): + return self.Offset + + def SetOffset(self, Offset): + self.Offset = Offset + + def GetToken(self): + return self.Token + + def SetTokenSpaceGuidCName(self, TokenSpaceGuidCName): + self.TokenSpaceGuidCName = TokenSpaceGuidCName + + def GetTokenSpaceGuidCName(self): + return self.TokenSpaceGuidCName + + def SetTokenSpaceGuidValue(self, TokenSpaceGuidValue): + self.TokenSpaceGuidValue = TokenSpaceGuidValue + + def GetTokenSpaceGuidValue(self): + return self.TokenSpaceGuidValue + + def SetDatumType(self, DatumType): + self.DatumType = DatumType + + def GetDatumType(self): + return self.DatumType + + def SetMaxDatumSize(self, MaxDatumSize): + self.MaxDatumSize = MaxDatumSize + + def GetMaxDatumSize(self): + return self.MaxDatumSize + + def SetDefaultValue(self, DefaultValue): + self.DefaultValue = DefaultValue + + def GetDefaultValue(self): + return self.DefaultValue + + def SetValidUsage(self, ValidUsage): + self.ValidUsage = ValidUsage + + def GetValidUsage(self): + return self.ValidUsage + + def SetPcdErrorsList(self, PcdErrorsList): + self.PcdErrorsList = PcdErrorsList + + def GetPcdErrorsList(self): + return self.PcdErrorsList + + def SetItemType(self, ItemType): + self.ItemType = ItemType + + def GetItemType(self): + return self.ItemType + + def SetSupModuleList(self, SupModuleList): + self.SupModuleList = SupModuleList + + def GetSupModuleList(self): + return self.SupModuleList diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/POM/ModuleObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/POM/ModuleObject.py new file mode 100755 index 00000000..de2d29bc --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/POM/ModuleObject.py @@ -0,0 +1,654 @@ +## @file +# This file is used to define a class object to describe a module +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +''' +ModuleObject +''' + +## +# Import Modules +# +from Object.POM.CommonObject import CommonPropertiesObject +from Object.POM.CommonObject import IdentificationObject +from Object.POM.CommonObject import CommonHeaderObject +from Object.POM.CommonObject import BinaryHeaderObject +from Object.POM.CommonObject import HelpTextListObject +from Object.POM.CommonObject import GuidVersionObject + + +## +# BootModeObject +# +class BootModeObject(CommonPropertiesObject, HelpTextListObject): + def __init__(self): + self.SupportedBootModes = '' + CommonPropertiesObject.__init__(self) + HelpTextListObject.__init__(self) + + def SetSupportedBootModes(self, SupportedBootModes): + self.SupportedBootModes = SupportedBootModes + + def GetSupportedBootModes(self): + return self.SupportedBootModes + +## +# EventObject +# +class EventObject(CommonPropertiesObject, HelpTextListObject): + def __init__(self): + self.EventType = '' + CommonPropertiesObject.__init__(self) + HelpTextListObject.__init__(self) + + def SetEventType(self, EventType): + self.EventType = EventType + + def GetEventType(self): + return self.EventType + +## +# HobObject +# +class HobObject(CommonPropertiesObject, HelpTextListObject): + def __init__(self): + self.HobType = '' + CommonPropertiesObject.__init__(self) + HelpTextListObject.__init__(self) + + def SetHobType(self, HobType): + self.HobType = HobType + + def GetHobType(self): + return self.HobType + +## +# SpecObject +# +class SpecObject(object): + def __init__(self): + self.Spec = '' + self.Version = '' + + def SetSpec(self, Spec): + self.Spec = Spec + + def GetSpec(self): + return self.Spec + + def SetVersion(self, Version): + self.Version = Version + + def GetVersion(self): + return self.Version + +## ModuleHeaderObject +# +# This class defined header items used in Module file +# +class ModuleHeaderObject(IdentificationObject, CommonHeaderObject, BinaryHeaderObject): + def __init__(self): + self.IsLibrary = False + self.IsLibraryModList = [] + self.ModuleType = '' + self.BinaryModule = False + self.PcdIsDriver = '' + self.PiSpecificationVersion = '' + self.UefiSpecificationVersion = '' + self.UNIFlag = False + self.ModuleUniFile = '' + # + # SpecObject + # + self.SpecList = [] + # + # BootModeObject + # + self.BootModeList = [] + # + # EventObject + # + self.EventList = [] + # + # HobObject + # + self.HobList = [] + # + # LibraryClassObject + # + self.LibraryClassList = [] + self.SupArchList = [] + IdentificationObject.__init__(self) + CommonHeaderObject.__init__(self) + BinaryHeaderObject.__init__(self) + + def SetIsLibrary(self, IsLibrary): + self.IsLibrary = IsLibrary + + def GetIsLibrary(self): + return self.IsLibrary + + def SetIsLibraryModList(self, IsLibraryModList): + self.IsLibraryModList = IsLibraryModList + + def GetIsLibraryModList(self): + return self.IsLibraryModList + + def SetModuleType(self, ModuleType): + self.ModuleType = ModuleType + + def GetModuleType(self): + return self.ModuleType + + def SetBinaryModule(self, BinaryModule): + self.BinaryModule = BinaryModule + + def GetBinaryModule(self): + return self.BinaryModule + + def SetPcdIsDriver(self, PcdIsDriver): + self.PcdIsDriver = PcdIsDriver + + def GetPcdIsDriver(self): + return self.PcdIsDriver + + def SetPiSpecificationVersion(self, PiSpecificationVersion): + self.PiSpecificationVersion = PiSpecificationVersion + + def GetPiSpecificationVersion(self): + return self.PiSpecificationVersion + + def SetUefiSpecificationVersion(self, UefiSpecificationVersion): + self.UefiSpecificationVersion = UefiSpecificationVersion + + def GetUefiSpecificationVersion(self): + return self.UefiSpecificationVersion + + def SetSpecList(self, SpecList): + self.SpecList = SpecList + + def GetSpecList(self): + return self.SpecList + + def SetBootModeList(self, BootModeList): + self.BootModeList = BootModeList + + def GetBootModeList(self): + return self.BootModeList + + def SetEventList(self, EventList): + self.EventList = EventList + + def GetEventList(self): + return self.EventList + + def SetHobList(self, HobList): + self.HobList = HobList + + def GetHobList(self): + return self.HobList + + def SetLibraryClassList(self, LibraryClassList): + self.LibraryClassList = LibraryClassList + + def GetLibraryClassList(self): + return self.LibraryClassList + + def SetSupArchList(self, SupArchList): + self.SupArchList = SupArchList + + def GetSupArchList(self): + return self.SupArchList + + def SetModuleUniFile(self, ModuleUniFile): + self.ModuleUniFile = ModuleUniFile + + def GetModuleUniFile(self): + return self.ModuleUniFile +## +# SourceFileObject +# +class SourceFileObject(CommonPropertiesObject): + def __init__(self): + CommonPropertiesObject.__init__(self) + self.SourceFile = '' + self.TagName = '' + self.ToolCode = '' + self.Family = '' + self.FileType = '' + + def SetSourceFile(self, SourceFile): + self.SourceFile = SourceFile + + def GetSourceFile(self): + return self.SourceFile + + def SetTagName(self, TagName): + self.TagName = TagName + + def GetTagName(self): + return self.TagName + + def SetToolCode(self, ToolCode): + self.ToolCode = ToolCode + + def GetToolCode(self): + return self.ToolCode + + def SetFamily(self, Family): + self.Family = Family + + def GetFamily(self): + return self.Family + + def SetFileType(self, FileType): + self.FileType = FileType + + def GetFileType(self): + return self.FileType + + +## +# BinaryFileObject +# +class BinaryFileObject(CommonPropertiesObject): + def __init__(self): + self.FileNamList = [] + self.AsBuiltList = [] + CommonPropertiesObject.__init__(self) + + def SetFileNameList(self, FileNamList): + self.FileNamList = FileNamList + + def GetFileNameList(self): + return self.FileNamList + + def SetAsBuiltList(self, AsBuiltList): + self.AsBuiltList = AsBuiltList + + def GetAsBuiltList(self): + return self.AsBuiltList + + +## +# AsBuildLibraryClassObject +# +class AsBuildLibraryClassObject(object): + def __init__(self): + self.LibGuid = '' + self.LibVersion = '' + self.SupArchList = [] + + def SetLibGuid(self, LibGuid): + self.LibGuid = LibGuid + def GetLibGuid(self): + return self.LibGuid + + def SetLibVersion(self, LibVersion): + self.LibVersion = LibVersion + def GetLibVersion(self): + return self.LibVersion + + def SetSupArchList(self, SupArchList): + self.SupArchList = SupArchList + def GetSupArchList(self): + return self.SupArchList + +## +# AsBuiltObject +# +class AsBuiltObject(object): + def __init__(self): + # + # list of PcdObject + # + self.PatchPcdList = [] + # + # list of PcdObject + # + self.PcdExValueList = [] + # + # list of GuidVersionObject + # + self.LibraryInstancesList = [] + # + # List of BinaryBuildFlag object + # + self.BinaryBuildFlagList = [] + + def SetPatchPcdList(self, PatchPcdList): + self.PatchPcdList = PatchPcdList + + def GetPatchPcdList(self): + return self.PatchPcdList + + def SetPcdExList(self, PcdExValueList): + self.PcdExValueList = PcdExValueList + + def GetPcdExList(self): + return self.PcdExValueList + + def SetLibraryInstancesList(self, LibraryInstancesList): + self.LibraryInstancesList = LibraryInstancesList + + def GetLibraryInstancesList(self): + return self.LibraryInstancesList + + def SetBuildFlagsList(self, BinaryBuildFlagList): + self.BinaryBuildFlagList = BinaryBuildFlagList + + def GetBuildFlagsList(self): + return self.BinaryBuildFlagList + +## +# BinaryBuildFlag, this object will include those fields that are not +# covered by the UPT Spec BinaryFile field +# +class BinaryBuildFlagObject(object): + def __init__(self): + self.Target = '' + self.TagName = '' + self.Family = '' + self.AsBuiltOptionFlags = '' + + def SetTarget(self, Target): + self.Target = Target + + def GetTarget(self): + return self.Target + + def SetTagName(self, TagName): + self.TagName = TagName + + def GetTagName(self): + return self.TagName + + def SetFamily(self, Family): + self.Family = Family + + def GetFamily(self): + return self.Family + + def SetAsBuiltOptionFlags(self, AsBuiltOptionFlags): + self.AsBuiltOptionFlags = AsBuiltOptionFlags + def GetAsBuiltOptionFlags(self): + return self.AsBuiltOptionFlags + +## +# ExternObject +# +class ExternObject(CommonPropertiesObject): + def __init__(self): + self.EntryPoint = '' + self.UnloadImage = '' + self.Constructor = '' + self.Destructor = '' + self.SupModList = [] + CommonPropertiesObject.__init__(self) + + def SetEntryPoint(self, EntryPoint): + self.EntryPoint = EntryPoint + + def GetEntryPoint(self): + return self.EntryPoint + + def SetUnloadImage(self, UnloadImage): + self.UnloadImage = UnloadImage + + def GetUnloadImage(self): + return self.UnloadImage + + def SetConstructor(self, Constructor): + self.Constructor = Constructor + + def GetConstructor(self): + return self.Constructor + + def SetDestructor(self, Destructor): + self.Destructor = Destructor + + def GetDestructor(self): + return self.Destructor + + def SetSupModList(self, SupModList): + self.SupModList = SupModList + def GetSupModList(self): + return self.SupModList + +## +# DepexObject +# +class DepexObject(CommonPropertiesObject): + def __init__(self): + self.Depex = '' + self.ModuelType = '' + CommonPropertiesObject.__init__(self) + + def SetDepex(self, Depex): + self.Depex = Depex + + def GetDepex(self): + return self.Depex + + def SetModuleType(self, ModuleType): + self.ModuelType = ModuleType + + def GetModuleType(self): + return self.ModuelType + +## +# PackageDependencyObject +# +class PackageDependencyObject(GuidVersionObject, CommonPropertiesObject): + def __init__(self): + self.Package = '' + self.PackageFilePath = '' + GuidVersionObject.__init__(self) + CommonPropertiesObject.__init__(self) + + def SetPackageFilePath(self, PackageFilePath): + self.PackageFilePath = PackageFilePath + + def GetPackageFilePath(self): + return self.PackageFilePath + + def SetPackage(self, Package): + self.Package = Package + + def GetPackage(self): + return self.Package + +## +# BuildOptionObject +# +class BuildOptionObject(CommonPropertiesObject): + def __init__(self): + CommonPropertiesObject.__init__(self) + self.BuildOption = '' + + def SetBuildOption(self, BuildOption): + self.BuildOption = BuildOption + + def GetBuildOption(self): + return self.BuildOption + +## +# ModuleObject +# +class ModuleObject(ModuleHeaderObject): + def __init__(self): + # + # {Arch : ModuleHeaderObject} + # + self.HeaderDict = {} + # + # LibraryClassObject + # + self.LibraryClassList = [] + # + # SourceFileObject + # + self.SourceFileList = [] + # + # BinaryFileObject + # + self.BinaryFileList = [] + # + # PackageDependencyObject + # + self.PackageDependencyList = [] + # + # DepexObject + # + self.PeiDepex = [] + # + # DepexObject + # + self.DxeDepex = [] + # + # DepexObject + # + self.SmmDepex = [] + # + # ProtocolObject + # + self.ProtocolList = [] + # + # PpiObject + # + self.PpiList = [] + # + # GuidObject + # + self.GuidList = [] + # + # PcdObject + # + self.PcdList = [] + # + # ExternObject + # + self.ExternList = [] + # + # BuildOptionObject + # + self.BuildOptionList = [] + # + # UserExtensionObject + # + self.UserExtensionList = [] + # + # MiscFileObject + # + self.MiscFileList = [] + # + # ClonedFromObject + # + self.ClonedFrom = None + + ModuleHeaderObject.__init__(self) + + def SetHeaderDict(self, HeaderDict): + self.HeaderDict = HeaderDict + + def GetHeaderDict(self): + return self.HeaderDict + + def SetLibraryClassList(self, LibraryClassList): + self.LibraryClassList = LibraryClassList + + def GetLibraryClassList(self): + return self.LibraryClassList + + def SetSourceFileList(self, SourceFileList): + self.SourceFileList = SourceFileList + + def GetSourceFileList(self): + return self.SourceFileList + + def SetBinaryFileList(self, BinaryFileList): + self.BinaryFileList = BinaryFileList + + def GetBinaryFileList(self): + return self.BinaryFileList + + def SetPackageDependencyList(self, PackageDependencyList): + self.PackageDependencyList = PackageDependencyList + + def GetPackageDependencyList(self): + return self.PackageDependencyList + + def SetPeiDepex(self, PeiDepex): + self.PeiDepex = PeiDepex + + def GetPeiDepex(self): + return self.PeiDepex + + def SetDxeDepex(self, DxeDepex): + self.DxeDepex = DxeDepex + + def GetDxeDepex(self): + return self.DxeDepex + + def SetSmmDepex(self, SmmDepex): + self.SmmDepex = SmmDepex + + def GetSmmDepex(self): + return self.SmmDepex + + def SetPpiList(self, PpiList): + self.PpiList = PpiList + + def GetPpiList(self): + return self.PpiList + + def SetProtocolList(self, ProtocolList): + self.ProtocolList = ProtocolList + + def GetProtocolList(self): + return self.ProtocolList + + def SetPcdList(self, PcdList): + self.PcdList = PcdList + + def GetPcdList(self): + return self.PcdList + + def SetGuidList(self, GuidList): + self.GuidList = GuidList + + def GetGuidList(self): + return self.GuidList + + def SetExternList(self, ExternList): + self.ExternList = ExternList + + def GetExternList(self): + return self.ExternList + + def SetBuildOptionList(self, BuildOptionList): + self.BuildOptionList = BuildOptionList + + def GetBuildOptionList(self): + return self.BuildOptionList + + def SetUserExtensionList(self, UserExtensionList): + self.UserExtensionList = UserExtensionList + + def GetUserExtensionList(self): + return self.UserExtensionList + + def SetMiscFileList(self, MiscFileList): + self.MiscFileList = MiscFileList + + def GetMiscFileList(self): + return self.MiscFileList + + def SetClonedFrom(self, ClonedFrom): + self.ClonedFrom = ClonedFrom + + def GetClonedFrom(self): + return self.ClonedFrom diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/POM/PackageObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/POM/PackageObject.py new file mode 100755 index 00000000..9d2db339 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/POM/PackageObject.py @@ -0,0 +1,192 @@ +## @file +# This file is used to define a class object to describe a package +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +''' +PackageObject +''' + +## +# Import Modules +# +from Object.POM.CommonObject import CommonPropertiesObject +from Object.POM.CommonObject import IdentificationObject +from Object.POM.CommonObject import CommonHeaderObject +from Object.POM.CommonObject import BinaryHeaderObject +from Library.Misc import Sdict + +## StandardIncludeFileObject +# +class StandardIncludeFileObject(CommonPropertiesObject): + def __init__(self): + CommonPropertiesObject.__init__(self) + self.IncludeFile = '' + + def SetIncludeFile(self, IncludeFile): + self.IncludeFile = IncludeFile + + def GetIncludeFile(self): + return self.IncludeFile + +## PackageIncludeFileObject +# +class PackageIncludeFileObject(StandardIncludeFileObject): + pass + +## +# PackageObject +# +class PackageObject(IdentificationObject, CommonHeaderObject, BinaryHeaderObject): + def __init__(self): + IdentificationObject.__init__(self) + CommonHeaderObject.__init__(self) + BinaryHeaderObject.__init__(self) + # + # LibraryClassObject + # + self.LibraryClassList = [] + # + # FileObject + # + self.IncludePathList = [] + # + # StandardIncludeFileObject + # + self.StandardIncludeFileList = [] + # + # PackageIncludeFileObject + # + self.PackageIncludeFileList = [] + # + # Include and Arch List, item is (IncludePath, SupArchList-List of Arch), used during install package + # + self.IncludeArchList = [] + # + # ProtocolObject + # + self.ProtocolList = [] + # + # PpiObject + # + self.PpiList = [] + # + # GuidObject + # + self.GuidList = [] + # + # (PcdObject, PcdErrorObject) + # + self.PcdList = [] + # + # {(PcdTokenSpaceGuidCName, PcdErrroNumber): PcdErrorMessageList} + # + self.PcdErrorCommentDict = {} + # + # UserExtensionObject + # + self.UserExtensionList = [] + # + # MiscFileObject + # + self.MiscFileList = [] + self.ModuleDict = Sdict() + # + # ClonedRecordObject + # + self.ClonedFromList = [] + # + # string object + # + self.ModuleFileList = [] + + self.PcdChecks = [] + + self.UNIFlag = False + + def SetLibraryClassList(self, LibraryClassList): + self.LibraryClassList = LibraryClassList + + def GetLibraryClassList(self): + return self.LibraryClassList + + def SetIncludePathList(self, IncludePathList): + self.IncludePathList = IncludePathList + + def GetIncludePathList(self): + return self.IncludePathList + + def SetIncludeArchList(self, IncludeArchList): + self.IncludeArchList = IncludeArchList + + def GetIncludeArchList(self): + return self.IncludeArchList + + def SetStandardIncludeFileList(self, StandardIncludeFileList): + self.StandardIncludeFileList = StandardIncludeFileList + + def GetStandardIncludeFileList(self): + return self.StandardIncludeFileList + + def SetPackageIncludeFileList(self, PackageIncludeFileList): + self.PackageIncludeFileList = PackageIncludeFileList + + def GetPackageIncludeFileList(self): + return self.PackageIncludeFileList + + def SetProtocolList(self, ProtocolList): + self.ProtocolList = ProtocolList + + def GetProtocolList(self): + return self.ProtocolList + + def SetPpiList(self, PpiList): + self.PpiList = PpiList + + def GetPpiList(self): + return self.PpiList + + def SetGuidList(self, GuidList): + self.GuidList = GuidList + + def GetGuidList(self): + return self.GuidList + + def SetPcdList(self, PcdList): + self.PcdList = PcdList + + def GetPcdList(self): + return self.PcdList + + def SetUserExtensionList(self, UserExtensionList): + self.UserExtensionList = UserExtensionList + + def GetUserExtensionList(self): + return self.UserExtensionList + + def SetMiscFileList(self, MiscFileList): + self.MiscFileList = MiscFileList + + def GetMiscFileList(self): + return self.MiscFileList + + def SetModuleDict(self, ModuleDict): + self.ModuleDict = ModuleDict + + def GetModuleDict(self): + return self.ModuleDict + + def SetClonedFromList(self, ClonedFromList): + self.ClonedFromList = ClonedFromList + + def GetClonedFromList(self): + return self.ClonedFromList + + def SetModuleFileList(self, ModuleFileList): + self.ModuleFileList = ModuleFileList + + def GetModuleFileList(self): + return self.ModuleFileList + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/POM/__init__.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/POM/__init__.py new file mode 100644 index 00000000..7f07f89f --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/POM/__init__.py @@ -0,0 +1,14 @@ +## @file +# Python 'Object' package initialization file. +# +# This file is required to make Python interpreter treat the directory +# as containing package. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +POM +''' diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/DecObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/DecObject.py new file mode 100755 index 00000000..3e2919bb --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/DecObject.py @@ -0,0 +1,605 @@ +## @file +# This file is used to define class objects for DEC file. It will consumed by +#DecParser +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +''' +DecObject +''' + +## Import modules +# +import os.path + +from Library.Misc import Sdict +from Library.DataType import TAB_GUIDS +from Library.DataType import TAB_PPIS +from Library.DataType import TAB_PROTOCOLS +from Library.DataType import TAB_DEC_DEFINES +from Library.DataType import TAB_INCLUDES +from Library.DataType import TAB_LIBRARY_CLASSES +from Library.DataType import TAB_USER_EXTENSIONS +from Library.DataType import TAB_PCDS +from Library.DataType import TAB_ARCH_COMMON + +## _DecComments +# +# Base class for all data objects which have head and tail comments +# +class _DecComments: + + ##constructor + # + def __init__(self): + self._HeadComment = [] + self._TailComment = [] + + ## GetComments + # + def GetComments(self): + return self._HeadComment, self._TailComment + + ## GetHeadComment + # + def GetHeadComment(self): + return self._HeadComment + + ## SetHeadComment + # + # @param Comment: comment content + # + def SetHeadComment(self, Comment): + self._HeadComment = Comment + + ## GetTailComment + # + def GetTailComment(self): + return self._TailComment + + ## SetTailComment + # + # @param Comment: comment content + # + def SetTailComment(self, Comment): + self._TailComment = Comment + +## _DecBaseObject +# +# Base class that hold common info +# +class _DecBaseObject(_DecComments): + def __init__(self, PkgFullName): + _DecComments.__init__(self) + # + # Key is combined with (Arch, SectionType) + # Default is common + # + self.ValueDict = Sdict() + self._PkgFullName = PkgFullName + self._PackagePath, self._FileName = os.path.split(PkgFullName) + self._SecName = '' + + ## GetSectionName + # + def GetSectionName(self): + return self._SecName + + ## GetPackagePath + # + def GetPackagePath(self): + return self._PackagePath + + ## GetPackageFile + # + def GetPackageFile(self): + return self._FileName + + ## GetPackageFullName + # + def GetPackageFullName(self): + return self._PkgFullName + + ## AddItem + # Add sub-item to current object, sub-class should override it if needed + # + # @param Item: Sub-item to be added + # @param Scope: A list store section name and arch info + # + def AddItem(self, Item, Scope): + if not Scope: + return + if not Item: + return + ArchModule = [] + for Ele in Scope: + if Ele[1] in self.ValueDict: + self.ValueDict[Ele[1]].append(Item) + else: + self.ValueDict[Ele[1]] = [Item] + ArchModule.append(Ele[1]) + Item.ArchAndModuleType = ArchModule + + ## _GetItemByArch + # Helper class used by sub-class + # @param Arch: arch + # + def _GetItemByArch(self, Arch): + Arch = Arch.upper() + if Arch not in self.ValueDict: + return [] + return self.ValueDict[Arch] + + ## _GetAllItems + # Get all items, union all arches, items in returned list are unique + # + def _GetAllItems(self): + Retlst = [] + for Arch in self.ValueDict: + for Item in self.ValueDict[Arch]: + if Item not in Retlst: + Retlst.append(Item) + return Retlst + +## _DecItemBaseObject +# +# Module type and arch the item belongs to +# +class _DecItemBaseObject(_DecComments): + def __init__(self): + _DecComments.__init__(self) + # + # Item's arch, if PCD, also include PCD type + # + self.ArchAndModuleType = [] + + ## GetArchList + # + def GetArchList(self): + ArchSet = set() + for Arch in self.ArchAndModuleType: + ArchSet.add(Arch) + return list(ArchSet) + +## DecDefineObject +# +# Class to hold define section information +# +class DecDefineObject(_DecBaseObject): + def __init__(self, PkgFullName): + _DecBaseObject.__init__(self, PkgFullName) + self._SecName = TAB_DEC_DEFINES.upper() + self._DecSpec = '' + self._PkgName = '' + self._PkgGuid = '' + self._PkgVersion = '' + self._PkgUniFile = '' + + ## GetPackageSpecification + # + def GetPackageSpecification(self): + return self._DecSpec + + def SetPackageSpecification(self, DecSpec): + self._DecSpec = DecSpec + + ## GetPackageName + # + def GetPackageName(self): + return self._PkgName + + def SetPackageName(self, PkgName): + self._PkgName = PkgName + + ## GetPackageGuid + # + def GetPackageGuid(self): + return self._PkgGuid + + def SetPackageGuid(self, PkgGuid): + self._PkgGuid = PkgGuid + + ## GetPackageVersion + # + def GetPackageVersion(self): + return self._PkgVersion + + def SetPackageVersion(self, PkgVersion): + self._PkgVersion = PkgVersion + + ## GetPackageUniFile + # + def GetPackageUniFile(self): + return self._PkgUniFile + + def SetPackageUniFile(self, PkgUniFile): + self._PkgUniFile = PkgUniFile + + ## GetDefines + # + def GetDefines(self): + return self._GetItemByArch(TAB_ARCH_COMMON) + + ## GetAllDefines + # + def GetAllDefines(self): + return self._GetAllItems() + +## DecDefineItemObject +# +# Each item of define section +# +class DecDefineItemObject(_DecItemBaseObject): + def __init__(self): + _DecItemBaseObject.__init__(self) + self.Key = '' + self.Value = '' + + ## __hash__ + # + def __hash__(self): + return hash(self.Key + self.Value) + + ## __eq__ + # + def __eq__(self, Other): + return id(self) == id(Other) + + ## __str__ + # + def __str__(self): + return str(self.ArchAndModuleType) + '\n' + self.Key + \ + ' = ' + self.Value + +## DecIncludeObject +# +# Class to hold include section info +# +class DecIncludeObject(_DecBaseObject): + def __init__(self, PkgFullName): + _DecBaseObject.__init__(self, PkgFullName) + self._SecName = TAB_INCLUDES.upper() + + ## GetIncludes + # + def GetIncludes(self, Arch=TAB_ARCH_COMMON): + return self._GetItemByArch(Arch) + + ## GetAllIncludes + # + def GetAllIncludes(self): + return self._GetAllItems() + +## DecIncludeItemObject +# +# Item of include section +# +class DecIncludeItemObject(_DecItemBaseObject): + def __init__(self, File, Root): + self.File = File + self.Root = Root + _DecItemBaseObject.__init__(self) + + ## __hash__ + # + def __hash__(self): + return hash(self.File) + + ## __eq__ + # + def __eq__(self, Other): + return id(self) == id(Other) + + ## __str__ + # + def __str__(self): + return self.File + +## DecLibraryclassObject +# +# Class to hold library class section info +# +class DecLibraryclassObject(_DecBaseObject): + def __init__(self, PkgFullName): + _DecBaseObject.__init__(self, PkgFullName) + self._PackagePath, self._FileName = os.path.split(PkgFullName) + self._SecName = TAB_LIBRARY_CLASSES.upper() + + ## GetLibraryclasses + # + def GetLibraryclasses(self, Arch=TAB_ARCH_COMMON): + return self._GetItemByArch(Arch) + + ## GetAllLibraryclasses + # + def GetAllLibraryclasses(self): + return self._GetAllItems() + +## DecLibraryclassItemObject +# Item of library class section +# +class DecLibraryclassItemObject(_DecItemBaseObject): + def __init__(self, Libraryclass, File, Root): + _DecItemBaseObject.__init__(self) + self.File = File + self.Root = Root + self.Libraryclass = Libraryclass + + ## __hash__ + # + def __hash__(self): + return hash(self.Libraryclass + self.File) + + ## __eq__ + # + def __eq__(self, Other): + return id(self) == id(Other) + + ## __str__ + # + def __str__(self): + return self.Libraryclass + '|' + self.File + +## DecPcdObject +# Class to hold PCD section +# +class DecPcdObject(_DecBaseObject): + def __init__(self, PkgFullName): + _DecBaseObject.__init__(self, PkgFullName) + self._SecName = TAB_PCDS.upper() + + ## AddItem + # + # Diff from base class + # + # @param Item: Item + # @param Scope: Scope + # + def AddItem(self, Item, Scope): + if not Scope: + return + if not Item: + return + ArchModule = [] + for Type, Arch in Scope: + if (Type, Arch) in self.ValueDict: + self.ValueDict[Type, Arch].append(Item) + else: + self.ValueDict[Type, Arch] = [Item] + ArchModule.append([Type, Arch]) + Item.ArchAndModuleType = ArchModule + + ## GetPcds + # + # @param PcdType: PcdType + # @param Arch: Arch + # + def GetPcds(self, PcdType, Arch=TAB_ARCH_COMMON): + PcdType = PcdType.upper() + Arch = Arch.upper() + if (PcdType, Arch) not in self.ValueDict: + return [] + return self.ValueDict[PcdType, Arch] + + ## GetPcdsByType + # + # @param PcdType: PcdType + # + def GetPcdsByType(self, PcdType): + PcdType = PcdType.upper() + Retlst = [] + for TypeInDict, Arch in self.ValueDict: + if TypeInDict != PcdType: + continue + for Item in self.ValueDict[PcdType, Arch]: + if Item not in Retlst: + Retlst.append(Item) + return Retlst + +## DecPcdItemObject +# +# Item of PCD section +# +# @param _DecItemBaseObject: _DecItemBaseObject object +# +class DecPcdItemObject(_DecItemBaseObject): + def __init__(self, Guid, Name, Value, DatumType, + Token, MaxDatumSize=''): + _DecItemBaseObject.__init__(self) + self.TokenCName = Name + self.TokenSpaceGuidCName = Guid + self.DatumType = DatumType + self.DefaultValue = Value + self.TokenValue = Token + self.MaxDatumSize = MaxDatumSize + + ## __hash__ + # + def __hash__(self): + return hash(self.TokenSpaceGuidCName + self.TokenCName) + + ## __eq__ + # + def __eq__(self, Other): + return id(self) == id(Other) + + ## GetArchListOfType + # + # @param PcdType: PcdType + # + def GetArchListOfType(self, PcdType): + ItemSet = set() + PcdType = PcdType.upper() + for Type, Arch in self.ArchAndModuleType: + if Type != PcdType: + continue + ItemSet.add(Arch) + return list(ItemSet) + +## DecGuidObjectBase +# +# Base class for PPI, Protocol, and GUID. +# Hold same data but has different method for clarification in sub-class +# +# @param _DecBaseObject: Dec Base Object +# +class DecGuidObjectBase(_DecBaseObject): + def __init__(self, PkgFullName): + _DecBaseObject.__init__(self, PkgFullName) + + ## GetGuidStyleItems + # + # @param Arch: Arch + # + def GetGuidStyleItems(self, Arch=TAB_ARCH_COMMON): + return self._GetItemByArch(Arch) + + ## GetGuidStyleAllItems + # + def GetGuidStyleAllItems(self): + return self._GetAllItems() + +## DecGuidItemObject +# +# Item of GUID, PPI and Protocol section +# +# @param _DecItemBaseObject: Dec Item Base Object +# +class DecGuidItemObject(_DecItemBaseObject): + def __init__(self, CName, GuidCValue, GuidString): + _DecItemBaseObject.__init__(self) + self.GuidCName = CName + self.GuidCValue = GuidCValue + self.GuidString = GuidString + + ## __hash__ + # + def __hash__(self): + return hash(self.GuidCName) + + ## __eq__ + # + def __eq__(self, Other): + return id(self) == id(Other) + + ## __str__ + # + def __str__(self): + return self.GuidCName + ' = ' + self.GuidCValue + +## DecGuidObject +# +# Class for GUID section +# +# @param DecGuidObjectBase: Dec Guid Object Base +# +class DecGuidObject(DecGuidObjectBase): + def __init__(self, PkgFullName): + DecGuidObjectBase.__init__(self, PkgFullName) + self._SecName = TAB_GUIDS.upper() + + ## GetGuids + # + # @param Arch: Arch + # + def GetGuids(self, Arch=TAB_ARCH_COMMON): + return self._GetItemByArch(Arch) + + ## GetAllGuids + # + def GetAllGuids(self): + return self._GetAllItems() + +## DecPpiObject +# +# Class for PPI section +# +# @param DecGuidObjectBase: Dec Guid Object Base +# +class DecPpiObject(DecGuidObjectBase): + def __init__(self, PkgFullName): + DecGuidObjectBase.__init__(self, PkgFullName) + self._SecName = TAB_PPIS.upper() + + ## GetPpis + # + # @param Arch: Arch + # + def GetPpis(self, Arch=TAB_ARCH_COMMON): + return self._GetItemByArch(Arch) + + ## GetAllPpis + # + def GetAllPpis(self): + return self._GetAllItems() + +## DecProtocolObject +# +# Class for protocol section +# +# @param DecGuidObjectBase: Dec Guid Object Base +# +class DecProtocolObject(DecGuidObjectBase): + def __init__(self, PkgFullName): + DecGuidObjectBase.__init__(self, PkgFullName) + self._SecName = TAB_PROTOCOLS.upper() + + ## GetProtocols + # + # @param Arch: Arch + # + def GetProtocols(self, Arch=TAB_ARCH_COMMON): + return self._GetItemByArch(Arch) + + ## GetAllProtocols + # + def GetAllProtocols(self): + return self._GetAllItems() + +## DecUserExtensionObject +# +# Class for user extension section +# +# @param _DecBaseObject: Dec Guid Object Base +# +class DecUserExtensionObject(_DecBaseObject): + def __init__(self, PkgFullName): + _DecBaseObject.__init__(self, PkgFullName) + self._SecName = TAB_USER_EXTENSIONS.upper() + self.ItemList = [] + + ## GetProtocols + # + # @param Item: Item + # @param Scope: Scope + # + def AddItem(self, Item, Scope): + if not Scope: + pass + if not Item: + return + self.ItemList.append(Item) + + ## GetAllUserExtensions + # + def GetAllUserExtensions(self): + return self.ItemList + + +## DecUserExtensionItemObject +# Item for user extension section +# +# @param _DecItemBaseObject: Dec Item Base Object +# +class DecUserExtensionItemObject(_DecItemBaseObject): + def __init__(self): + _DecItemBaseObject.__init__(self) + self.UserString = '' + self.UserId = '' + self.IdString = '' + + + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfBinaryObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfBinaryObject.py new file mode 100755 index 00000000..70cbc54c --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfBinaryObject.py @@ -0,0 +1,686 @@ +## @file +# This file is used to define class objects of INF file [Binaries] section. +# It will consumed by InfParser. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +''' +InfBinaryObject +''' + +import os + +from copy import deepcopy +from Library import DataType as DT +from Library import GlobalData +import Logger.Log as Logger +from Logger import ToolError +from Logger import StringTable as ST +from Library.Misc import Sdict + +from Object.Parser.InfCommonObject import InfSectionCommonDef +from Object.Parser.InfCommonObject import CurrentLine +from Library.Misc import ConvPathFromAbsToRel +from Library.ExpressionValidate import IsValidFeatureFlagExp +from Library.Misc import ValidFile +from Library.ParserValidate import IsValidPath + + +class InfBianryItem(): + def __init__(self): + self.FileName = '' + self.Target = '' + self.FeatureFlagExp = '' + self.HelpString = '' + self.Type = '' + self.SupArchList = [] + + def SetFileName(self, FileName): + self.FileName = FileName + def GetFileName(self): + return self.FileName + + def SetTarget(self, Target): + self.Target = Target + def GetTarget(self): + return self.Target + + def SetFeatureFlagExp(self, FeatureFlagExp): + self.FeatureFlagExp = FeatureFlagExp + def GetFeatureFlagExp(self): + return self.FeatureFlagExp + + def SetHelpString(self, HelpString): + self.HelpString = HelpString + def GetHelpString(self): + return self.HelpString + + def SetType(self, Type): + self.Type = Type + def GetType(self): + return self.Type + def SetSupArchList(self, SupArchList): + self.SupArchList = SupArchList + def GetSupArchList(self): + return self.SupArchList + +class InfBianryVerItem(InfBianryItem, CurrentLine): + def __init__(self): + InfBianryItem.__init__(self) + CurrentLine.__init__(self) + self.VerTypeName = '' + + def SetVerTypeName(self, VerTypeName): + self.VerTypeName = VerTypeName + def GetVerTypeName(self): + return self.VerTypeName + +class InfBianryUiItem(InfBianryItem, CurrentLine): + def __init__(self): + InfBianryItem.__init__(self) + CurrentLine.__init__(self) + self.UiTypeName = '' + + def SetUiTypeName(self, UiTypeName): + self.UiTypeName = UiTypeName + def GetVerTypeName(self): + return self.UiTypeName + +class InfBianryCommonItem(InfBianryItem, CurrentLine): + def __init__(self): + self.CommonType = '' + self.TagName = '' + self.Family = '' + self.GuidValue = '' + InfBianryItem.__init__(self) + CurrentLine.__init__(self) + + def SetCommonType(self, CommonType): + self.CommonType = CommonType + def GetCommonType(self): + return self.CommonType + + def SetTagName(self, TagName): + self.TagName = TagName + def GetTagName(self): + return self.TagName + + def SetFamily(self, Family): + self.Family = Family + def GetFamily(self): + return self.Family + + def SetGuidValue(self, GuidValue): + self.GuidValue = GuidValue + def GetGuidValue(self): + return self.GuidValue + +## +# +# +# +class InfBinariesObject(InfSectionCommonDef): + def __init__(self): + self.Binaries = Sdict() + # + # Macro defined in this section should be only used in this section. + # + self.Macros = {} + InfSectionCommonDef.__init__(self) + + ## CheckVer + # + # + def CheckVer(self, Ver, __SupArchList): + # + # Check Ver + # + for VerItem in Ver: + IsValidFileFlag = False + VerContent = VerItem[0] + VerComment = VerItem[1] + VerCurrentLine = VerItem[2] + GlobalData.gINF_CURRENT_LINE = VerCurrentLine + InfBianryVerItemObj = None + # + # Should not less than 2 elements + # + if len(VerContent) < 2: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_BINARY_ITEM_FORMAT_INVALID % (VerContent[0], 2), + File=VerCurrentLine.GetFileName(), + Line=VerCurrentLine.GetLineNo(), + ExtraData=VerCurrentLine.GetLineString()) + return False + if len(VerContent) > 4: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_BINARY_ITEM_FORMAT_INVALID_MAX % (VerContent[0], 4), + File=VerCurrentLine.GetFileName(), + Line=VerCurrentLine.GetLineNo(), + ExtraData=VerCurrentLine.GetLineString()) + return False + if len(VerContent) >= 2: + # + # Create a Ver Object. + # + InfBianryVerItemObj = InfBianryVerItem() + + if VerContent[0] != DT.BINARY_FILE_TYPE_VER: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_BINARY_VER_TYPE % DT.BINARY_FILE_TYPE_VER, + File=VerCurrentLine.GetFileName(), + Line=VerCurrentLine.GetLineNo(), + ExtraData=VerCurrentLine.GetLineString()) + + InfBianryVerItemObj.SetVerTypeName(VerContent[0]) + InfBianryVerItemObj.SetType(VerContent[0]) + # + # Verify File exist or not + # + FullFileName = os.path.normpath(os.path.realpath(os.path.join(GlobalData.gINF_MODULE_DIR, + VerContent[1]))) + if not (ValidFile(FullFileName) or ValidFile(VerContent[1])): + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_BINARY_ITEM_FILE_NOT_EXIST % (VerContent[1]), + File=VerCurrentLine.GetFileName(), + Line=VerCurrentLine.GetLineNo(), + ExtraData=VerCurrentLine.GetLineString()) + # + # Validate file exist/format. + # + if IsValidPath(VerContent[1], GlobalData.gINF_MODULE_DIR): + IsValidFileFlag = True + else: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID % (VerContent[1]), + File=VerCurrentLine.GetFileName(), + Line=VerCurrentLine.GetLineNo(), + ExtraData=VerCurrentLine.GetLineString()) + return False + if IsValidFileFlag: + VerContent[0] = ConvPathFromAbsToRel(VerContent[0], + GlobalData.gINF_MODULE_DIR) + InfBianryVerItemObj.SetFileName(VerContent[1]) + if len(VerContent) >= 3: + # + # Add Target information + # + InfBianryVerItemObj.SetTarget(VerContent[2]) + if len(VerContent) == 4: + if VerContent[3].strip() == '': + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_MISSING, + File=VerCurrentLine.GetFileName(), + Line=VerCurrentLine.GetLineNo(), + ExtraData=VerCurrentLine.GetLineString()) + # + # Validate Feature Flag Express + # + FeatureFlagRtv = IsValidFeatureFlagExp(VerContent[3].\ + strip()) + if not FeatureFlagRtv[0]: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_SYNTAX_INVLID % (FeatureFlagRtv[1]), + File=VerCurrentLine.GetFileName(), + Line=VerCurrentLine.GetLineNo(), + ExtraData=VerCurrentLine.GetLineString()) + InfBianryVerItemObj.SetFeatureFlagExp(VerContent[3]) + + InfBianryVerItemObj.SetSupArchList(__SupArchList) + + # + # Determine binary file name duplicate. Follow below rule: + # + # A binary filename must not be duplicated within + # a [Binaries] section. A binary filename may appear in + # multiple architectural [Binaries] sections. A binary + # filename listed in an architectural [Binaries] section + # must not be listed in the common architectural + # [Binaries] section. + # + # NOTE: This check will not report error now. + # + for Item in self.Binaries: + if Item.GetFileName() == InfBianryVerItemObj.GetFileName(): + ItemSupArchList = Item.GetSupArchList() + for ItemArch in ItemSupArchList: + for VerItemObjArch in __SupArchList: + if ItemArch == VerItemObjArch: + # + # ST.ERR_INF_PARSER_ITEM_DUPLICATE + # + pass + if ItemArch.upper() == 'COMMON' or VerItemObjArch.upper() == 'COMMON': + # + # ERR_INF_PARSER_ITEM_DUPLICATE_COMMON + # + pass + + if InfBianryVerItemObj is not None: + if (InfBianryVerItemObj) in self.Binaries: + BinariesList = self.Binaries[InfBianryVerItemObj] + BinariesList.append((InfBianryVerItemObj, VerComment)) + self.Binaries[InfBianryVerItemObj] = BinariesList + else: + BinariesList = [] + BinariesList.append((InfBianryVerItemObj, VerComment)) + self.Binaries[InfBianryVerItemObj] = BinariesList + + ## ParseCommonBinary + # + # ParseCommonBinary + # + def ParseCommonBinary(self, CommonBinary, __SupArchList): + # + # Check common binary definitions + # Type | FileName | Target | Family | TagName | FeatureFlagExp + # + for Item in CommonBinary: + IsValidFileFlag = False + ItemContent = Item[0] + ItemComment = Item[1] + CurrentLineOfItem = Item[2] + GlobalData.gINF_CURRENT_LINE = CurrentLineOfItem + InfBianryCommonItemObj = None + if ItemContent[0] == 'SUBTYPE_GUID': + if len(ItemContent) < 3: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_BINARY_ITEM_FORMAT_INVALID % (ItemContent[0], 3), + File=CurrentLineOfItem.GetFileName(), + Line=CurrentLineOfItem.GetLineNo(), + ExtraData=CurrentLineOfItem.GetLineString()) + return False + else: + if len(ItemContent) < 2: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_BINARY_ITEM_FORMAT_INVALID % (ItemContent[0], 2), + File=CurrentLineOfItem.GetFileName(), + Line=CurrentLineOfItem.GetLineNo(), + ExtraData=CurrentLineOfItem.GetLineString()) + return False + + if len(ItemContent) > 7: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_BINARY_ITEM_FORMAT_INVALID_MAX % (ItemContent[0], 7), + File=CurrentLineOfItem.GetFileName(), + Line=CurrentLineOfItem.GetLineNo(), + ExtraData=CurrentLineOfItem.GetLineString()) + return False + if len(ItemContent) >= 2: + # + # Create a Common Object. + # + InfBianryCommonItemObj = InfBianryCommonItem() + # + # Convert Binary type. + # + BinaryFileType = ItemContent[0].strip() + if BinaryFileType == 'RAW' or BinaryFileType == 'ACPI' or BinaryFileType == 'ASL': + BinaryFileType = 'BIN' + + if BinaryFileType not in DT.BINARY_FILE_TYPE_LIST: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_BINARY_ITEM_INVALID_FILETYPE % \ + (DT.BINARY_FILE_TYPE_LIST.__str__()), + File=CurrentLineOfItem.GetFileName(), + Line=CurrentLineOfItem.GetLineNo(), + ExtraData=CurrentLineOfItem.GetLineString()) + + if BinaryFileType == 'SUBTYPE_GUID': + BinaryFileType = 'FREEFORM' + + if BinaryFileType == 'LIB' or BinaryFileType == 'UEFI_APP': + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_BINARY_ITEM_INVALID_FILETYPE % \ + (DT.BINARY_FILE_TYPE_LIST.__str__()), + File=CurrentLineOfItem.GetFileName(), + Line=CurrentLineOfItem.GetLineNo(), + ExtraData=CurrentLineOfItem.GetLineString()) + + InfBianryCommonItemObj.SetType(BinaryFileType) + InfBianryCommonItemObj.SetCommonType(ItemContent[0]) + FileName = '' + if BinaryFileType == 'FREEFORM': + InfBianryCommonItemObj.SetGuidValue(ItemContent[1]) + if len(ItemContent) >= 3: + FileName = ItemContent[2] + else: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_BINARY_ITEM_FILENAME_NOT_EXIST, + File=CurrentLineOfItem.GetFileName(), + Line=CurrentLineOfItem.GetLineNo(), + ExtraData=CurrentLineOfItem.GetLineString()) + else: + FileName = ItemContent[1] + # + # Verify File exist or not + # + FullFileName = os.path.normpath(os.path.realpath(os.path.join(GlobalData.gINF_MODULE_DIR, + FileName))) + if not (ValidFile(FullFileName) or ValidFile(FileName)): + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_BINARY_ITEM_FILE_NOT_EXIST % (FileName), + File=CurrentLineOfItem.GetFileName(), + Line=CurrentLineOfItem.GetLineNo(), + ExtraData=CurrentLineOfItem.GetLineString()) + # + # Validate file exist/format. + # + if IsValidPath(FileName, GlobalData.gINF_MODULE_DIR): + IsValidFileFlag = True + else: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID % (FileName), + File=CurrentLineOfItem.GetFileName(), + Line=CurrentLineOfItem.GetLineNo(), + ExtraData=CurrentLineOfItem.GetLineString()) + return False + if IsValidFileFlag: + ItemContent[0] = ConvPathFromAbsToRel(ItemContent[0], GlobalData.gINF_MODULE_DIR) + InfBianryCommonItemObj.SetFileName(FileName) + if len(ItemContent) >= 3: + # + # Add Target information + # + if BinaryFileType != 'FREEFORM': + InfBianryCommonItemObj.SetTarget(ItemContent[2]) + + if len(ItemContent) >= 4: + # + # Add Family information + # + if BinaryFileType != 'FREEFORM': + InfBianryCommonItemObj.SetFamily(ItemContent[3]) + else: + InfBianryCommonItemObj.SetTarget(ItemContent[3]) + + if len(ItemContent) >= 5: + # + # TagName entries are build system specific. If there + # is content in the entry, the tool must exit + # gracefully with an error message that indicates build + # system specific content cannot be distributed using + # the UDP + # + if BinaryFileType != 'FREEFORM': + if ItemContent[4].strip() != '': + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_TAGNAME_NOT_PERMITTED % (ItemContent[4]), + File=CurrentLineOfItem.GetFileName(), + Line=CurrentLineOfItem.GetLineNo(), + ExtraData=CurrentLineOfItem.GetLineString()) + else: + InfBianryCommonItemObj.SetFamily(ItemContent[4]) + + if len(ItemContent) >= 6: + # + # Add FeatureFlagExp + # + if BinaryFileType != 'FREEFORM': + if ItemContent[5].strip() == '': + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_MISSING, + File=CurrentLineOfItem.GetFileName(), + Line=CurrentLineOfItem.GetLineNo(), + ExtraData=CurrentLineOfItem.GetLineString()) + # + # Validate Feature Flag Express + # + FeatureFlagRtv = IsValidFeatureFlagExp(ItemContent[5].strip()) + if not FeatureFlagRtv[0]: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_SYNTAX_INVLID % (FeatureFlagRtv[1]), + File=CurrentLineOfItem.GetFileName(), + Line=CurrentLineOfItem.GetLineNo(), + ExtraData=CurrentLineOfItem.GetLineString()) + InfBianryCommonItemObj.SetFeatureFlagExp(ItemContent[5]) + else: + if ItemContent[5].strip() != '': + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_TAGNAME_NOT_PERMITTED % (ItemContent[5]), + File=CurrentLineOfItem.GetFileName(), + Line=CurrentLineOfItem.GetLineNo(), + ExtraData=CurrentLineOfItem.GetLineString()) + + if len(ItemContent) == 7: + if ItemContent[6].strip() == '': + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_MISSING, + File=CurrentLineOfItem.GetFileName(), + Line=CurrentLineOfItem.GetLineNo(), + ExtraData=CurrentLineOfItem.GetLineString()) + # + # Validate Feature Flag Express + # + FeatureFlagRtv = IsValidFeatureFlagExp(ItemContent[6].strip()) + if not FeatureFlagRtv[0]: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_SYNTAX_INVLID % (FeatureFlagRtv[1]), + File=CurrentLineOfItem.GetFileName(), + Line=CurrentLineOfItem.GetLineNo(), + ExtraData=CurrentLineOfItem.GetLineString()) + InfBianryCommonItemObj.SetFeatureFlagExp(ItemContent[6]) + + InfBianryCommonItemObj.SetSupArchList(__SupArchList) + + # + # Determine binary file name duplicate. Follow below rule: + # + # A binary filename must not be duplicated within + # a [Binaries] section. A binary filename may appear in + # multiple architectural [Binaries] sections. A binary + # filename listed in an architectural [Binaries] section + # must not be listed in the common architectural + # [Binaries] section. + # + # NOTE: This check will not report error now. + # +# for Item in self.Binaries: +# if Item.GetFileName() == InfBianryCommonItemObj.GetFileName(): +# ItemSupArchList = Item.GetSupArchList() +# for ItemArch in ItemSupArchList: +# for ComItemObjArch in __SupArchList: +# if ItemArch == ComItemObjArch: +# # +# # ST.ERR_INF_PARSER_ITEM_DUPLICATE +# # +# pass +# +# if ItemArch.upper() == 'COMMON' or ComItemObjArch.upper() == 'COMMON': +# # +# # ERR_INF_PARSER_ITEM_DUPLICATE_COMMON +# # +# pass + + if InfBianryCommonItemObj is not None: + if (InfBianryCommonItemObj) in self.Binaries: + BinariesList = self.Binaries[InfBianryCommonItemObj] + BinariesList.append((InfBianryCommonItemObj, ItemComment)) + self.Binaries[InfBianryCommonItemObj] = BinariesList + else: + BinariesList = [] + BinariesList.append((InfBianryCommonItemObj, ItemComment)) + self.Binaries[InfBianryCommonItemObj] = BinariesList + + def SetBinary(self, UiInf=None, Ver=None, CommonBinary=None, ArchList=None): + + __SupArchList = [] + for ArchItem in ArchList: + # + # Validate Arch + # + if (ArchItem == '' or ArchItem is None): + ArchItem = 'COMMON' + __SupArchList.append(ArchItem) + + if UiInf is not None: + if len(UiInf) > 0: + # + # Check UI + # + for UiItem in UiInf: + IsValidFileFlag = False + InfBianryUiItemObj = None + UiContent = UiItem[0] + UiComment = UiItem[1] + UiCurrentLine = UiItem[2] + GlobalData.gINF_CURRENT_LINE = deepcopy(UiItem[2]) + # + # Should not less than 2 elements + # + if len(UiContent) < 2: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_BINARY_ITEM_FORMAT_INVALID % (UiContent[0], 2), + File=UiCurrentLine.GetFileName(), + Line=UiCurrentLine.GetLineNo(), + ExtraData=UiCurrentLine.GetLineString()) + return False + + if len(UiContent) > 4: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_BINARY_ITEM_FORMAT_INVALID_MAX % (UiContent[0], 4), + File=UiCurrentLine.GetFileName(), + Line=UiCurrentLine.GetLineNo(), + ExtraData=UiCurrentLine.GetLineString()) + return False + if len(UiContent) >= 2: + # + # Create an Ui Object. + # + InfBianryUiItemObj = InfBianryUiItem() + if UiContent[0] != 'UI': + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_BINARY_VER_TYPE % ('UI'), + File=UiCurrentLine.GetFileName(), + Line=UiCurrentLine.GetLineNo(), + ExtraData=UiCurrentLine.GetLineString()) + InfBianryUiItemObj.SetUiTypeName(UiContent[0]) + InfBianryUiItemObj.SetType(UiContent[0]) + # + # Verify File exist or not + # + FullFileName = os.path.normpath(os.path.realpath(os.path.join(GlobalData.gINF_MODULE_DIR, + UiContent[1]))) + if not (ValidFile(FullFileName) or ValidFile(UiContent[1])): + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_BINARY_ITEM_FILE_NOT_EXIST % (UiContent[1]), + File=UiCurrentLine.GetFileName(), + Line=UiCurrentLine.GetLineNo(), + ExtraData=UiCurrentLine.GetLineString()) + # + # Validate file exist/format. + # + if IsValidPath(UiContent[1], GlobalData.gINF_MODULE_DIR): + IsValidFileFlag = True + else: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID % (UiContent[1]), + File=UiCurrentLine.GetFileName(), + Line=UiCurrentLine.GetLineNo(), + ExtraData=UiCurrentLine.GetLineString()) + return False + if IsValidFileFlag: + UiContent[0] = ConvPathFromAbsToRel(UiContent[0], GlobalData.gINF_MODULE_DIR) + InfBianryUiItemObj.SetFileName(UiContent[1]) + if len(UiContent) >= 3: + # + # Add Target information + # + InfBianryUiItemObj.SetTarget(UiContent[2]) + if len(UiContent) == 4: + if UiContent[3].strip() == '': + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_MISSING, + File=UiCurrentLine.GetFileName(), + Line=UiCurrentLine.GetLineNo(), + ExtraData=UiCurrentLine.GetLineString()) + # + # Validate Feature Flag Express + # + FeatureFlagRtv = IsValidFeatureFlagExp(UiContent[3].strip()) + if not FeatureFlagRtv[0]: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_SYNTAX_INVLID % (FeatureFlagRtv[1]), + File=UiCurrentLine.GetFileName(), + Line=UiCurrentLine.GetLineNo(), + ExtraData=UiCurrentLine.GetLineString()) + InfBianryUiItemObj.SetFeatureFlagExp(UiContent[3]) + + InfBianryUiItemObj.SetSupArchList(__SupArchList) + + # + # Determine binary file name duplicate. Follow below rule: + # + # A binary filename must not be duplicated within + # a [Binaries] section. A binary filename may appear in + # multiple architectural [Binaries] sections. A binary + # filename listed in an architectural [Binaries] section + # must not be listed in the common architectural + # [Binaries] section. + # + # NOTE: This check will not report error now. + # +# for Item in self.Binaries: +# if Item.GetFileName() == InfBianryUiItemObj.GetFileName(): +# ItemSupArchList = Item.GetSupArchList() +# for ItemArch in ItemSupArchList: +# for UiItemObjArch in __SupArchList: +# if ItemArch == UiItemObjArch: +# # +# # ST.ERR_INF_PARSER_ITEM_DUPLICATE +# # +# pass +# if ItemArch.upper() == 'COMMON' or UiItemObjArch.upper() == 'COMMON': +# # +# # ERR_INF_PARSER_ITEM_DUPLICATE_COMMON +# # +# pass + + if InfBianryUiItemObj is not None: + if (InfBianryUiItemObj) in self.Binaries: + BinariesList = self.Binaries[InfBianryUiItemObj] + BinariesList.append((InfBianryUiItemObj, UiComment)) + self.Binaries[InfBianryUiItemObj] = BinariesList + else: + BinariesList = [] + BinariesList.append((InfBianryUiItemObj, UiComment)) + self.Binaries[InfBianryUiItemObj] = BinariesList + if Ver is not None and len(Ver) > 0: + self.CheckVer(Ver, __SupArchList) + if CommonBinary and len(CommonBinary) > 0: + self.ParseCommonBinary(CommonBinary, __SupArchList) + + return True + + def GetBinary(self): + return self.Binaries diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfBuildOptionObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfBuildOptionObject.py new file mode 100755 index 00000000..1638e533 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfBuildOptionObject.py @@ -0,0 +1,87 @@ +## @file +# This file is used to define class objects of INF file [BuildOptions] section. +# It will consumed by InfParser. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +''' +InfBuildOptionObject +''' + +from Library import GlobalData + +from Object.Parser.InfCommonObject import InfSectionCommonDef + +class InfBuildOptionItem(): + def __init__(self): + self.Content = '' + self.SupArchList = [] + self.AsBuildList = [] + + def SetContent(self, Content): + self.Content = Content + def GetContent(self): + return self.Content + + def SetSupArchList(self, SupArchList): + self.SupArchList = SupArchList + def GetSupArchList(self): + return self.SupArchList + + # + # AsBuild Information + # + def SetAsBuildList(self, AsBuildList): + self.AsBuildList = AsBuildList + def GetAsBuildList(self): + return self.AsBuildList + + +## INF BuildOption section +# Macro define is not permitted for this section. +# +# +class InfBuildOptionsObject(InfSectionCommonDef): + def __init__(self): + self.BuildOptions = [] + InfSectionCommonDef.__init__(self) + ## SetBuildOptions function + # + # For BuildOptionName, need to validate its format + # For BuildOptionValue, just ignore it. + # + # @param Arch Indicated which arch of build options belong to. + # @param BuildOptCont A list contain BuildOption related information. + # The element in the list contain 3 members. + # BuildOptionName, BuildOptionValue and IsReplace + # flag. + # + # @return True Build options set/validate successfully + # @return False Build options set/validate failed + # + def SetBuildOptions(self, BuildOptCont, ArchList = None, SectionContent = ''): + + if not GlobalData.gIS_BINARY_INF: + + if SectionContent.strip() != '': + InfBuildOptionItemObj = InfBuildOptionItem() + InfBuildOptionItemObj.SetContent(SectionContent) + InfBuildOptionItemObj.SetSupArchList(ArchList) + + self.BuildOptions.append(InfBuildOptionItemObj) + else: + # + # For AsBuild INF file + # + if len(BuildOptCont) >= 1: + InfBuildOptionItemObj = InfBuildOptionItem() + InfBuildOptionItemObj.SetAsBuildList(BuildOptCont) + InfBuildOptionItemObj.SetSupArchList(ArchList) + self.BuildOptions.append(InfBuildOptionItemObj) + + return True + + def GetBuildOptions(self): + return self.BuildOptions diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfCommonObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfCommonObject.py new file mode 100755 index 00000000..4e6c6f7a --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfCommonObject.py @@ -0,0 +1,156 @@ +## @file +# This file is used to define common class objects for INF file. +# It will consumed by InfParser +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +''' +InfCommonObject +''' + +## InfLineCommentObject +# +# Comment Object for any line in the INF file +# +# # +# # HeaderComment +# # +# Line # TailComment +# +class InfLineCommentObject(): + def __init__(self): + self.HeaderComments = '' + self.TailComments = '' + + def SetHeaderComments(self, HeaderComments): + self.HeaderComments = HeaderComments + + def GetHeaderComments(self): + return self.HeaderComments + + def SetTailComments(self, TailComments): + self.TailComments = TailComments + + def GetTailComments(self): + return self.TailComments + +## CurrentLine +# +class CurrentLine(): + def __init__(self): + self.LineNo = '' + self.LineString = '' + self.FileName = '' + + ## SetLineNo + # + # @param LineNo: LineNo + # + def SetLineNo(self, LineNo): + self.LineNo = LineNo + + ## GetLineNo + # + def GetLineNo(self): + return self.LineNo + + ## SetLineString + # + # @param LineString: Line String content + # + def SetLineString(self, LineString): + self.LineString = LineString + + ## GetLineString + # + def GetLineString(self): + return self.LineString + + ## SetFileName + # + # @param FileName: File Name + # + def SetFileName(self, FileName): + self.FileName = FileName + + ## GetFileName + # + def GetFileName(self): + return self.FileName + +## +# Inf Section common data +# +class InfSectionCommonDef(): + def __init__(self): + # + # # + # # HeaderComments at here + # # + # [xxSection] TailComments at here + # data + # + self.HeaderComments = '' + self.TailComments = '' + # + # The support arch list of this section + # + self.SupArchList = [] + + # + # Store all section content + # Key is supported Arch + # + self.AllContent = {} + + ## SetHeaderComments + # + # @param HeaderComments: HeaderComments + # + def SetHeaderComments(self, HeaderComments): + self.HeaderComments = HeaderComments + + ## GetHeaderComments + # + def GetHeaderComments(self): + return self.HeaderComments + + ## SetTailComments + # + # @param TailComments: TailComments + # + def SetTailComments(self, TailComments): + self.TailComments = TailComments + + ## GetTailComments + # + def GetTailComments(self): + return self.TailComments + + ## SetSupArchList + # + # @param Arch: Arch + # + def SetSupArchList(self, Arch): + if Arch not in self.SupArchList: + self.SupArchList.append(Arch) + + ## GetSupArchList + # + def GetSupArchList(self): + return self.SupArchList + + ## SetAllContent + # + # @param ArchList: ArchList + # @param Content: Content + # + def SetAllContent(self, Content): + self.AllContent = Content + + ## GetAllContent + # + def GetAllContent(self): + return self.AllContent diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfDefineCommonObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfDefineCommonObject.py new file mode 100755 index 00000000..05844834 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfDefineCommonObject.py @@ -0,0 +1,83 @@ +## @file +# This file is used to define common class objects of [Defines] section for INF file. +# It will consumed by InfParser +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +''' +InfDefineCommonObject +''' + +from Object.Parser.InfCommonObject import InfLineCommentObject + +## InfDefineImageExeParamItem +# +class InfDefineImageExeParamItem(): + def __init__(self): + self.CName = '' + self.FeatureFlagExp = '' + self.Comments = InfLineCommentObject() + + def SetCName(self, CName): + self.CName = CName + def GetCName(self): + return self.CName + def SetFeatureFlagExp(self, FeatureFlagExp): + self.FeatureFlagExp = FeatureFlagExp + def GetFeatureFlagExp(self): + return self.FeatureFlagExp + +## InfDefineEntryPointItem +# +class InfDefineEntryPointItem(InfDefineImageExeParamItem): + def __init__(self): + InfDefineImageExeParamItem.__init__(self) + +## InfDefineUnloadImageItem +# +class InfDefineUnloadImageItem(InfDefineImageExeParamItem): + def __init__(self): + InfDefineImageExeParamItem.__init__(self) + +## InfDefineConstructorItem +# +class InfDefineConstructorItem(InfDefineImageExeParamItem): + def __init__(self): + InfDefineImageExeParamItem.__init__(self) + self.SupModList = [] + + def SetSupModList(self, SupModList): + self.SupModList = SupModList + def GetSupModList(self): + return self.SupModList + +## InfDefineDestructorItem +# +class InfDefineDestructorItem(InfDefineImageExeParamItem): + def __init__(self): + InfDefineImageExeParamItem.__init__(self) + self.SupModList = [] + + def SetSupModList(self, SupModList): + self.SupModList = SupModList + def GetSupModList(self): + return self.SupModList + +## InfDefineLibraryItem +# +class InfDefineLibraryItem(): + def __init__(self): + self.LibraryName = '' + self.Types = [] + self.Comments = InfLineCommentObject() + + def SetLibraryName(self, Name): + self.LibraryName = Name + def GetLibraryName(self): + return self.LibraryName + def SetTypes(self, Type): + self.Types = Type + def GetTypes(self): + return self.Types diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfDefineObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfDefineObject.py new file mode 100755 index 00000000..bd3e06e4 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfDefineObject.py @@ -0,0 +1,1002 @@ +## @file +# This file is used to define class objects of [Defines] section for INF file. +# It will consumed by InfParser +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +''' +InfDefineObject +''' + +import os +import re + +from Logger import StringTable as ST +from Logger import ToolError +from Library import GlobalData +from Library import DataType as DT +from Library.StringUtils import GetSplitValueList +from Library.Misc import CheckGuidRegFormat +from Library.Misc import Sdict +from Library.Misc import ConvPathFromAbsToRel +from Library.Misc import ValidateUNIFilePath +from Library.ExpressionValidate import IsValidFeatureFlagExp +from Library.ParserValidate import IsValidWord +from Library.ParserValidate import IsValidInfMoudleType +from Library.ParserValidate import IsValidHex +from Library.ParserValidate import IsValidHexVersion +from Library.ParserValidate import IsValidDecVersion +from Library.ParserValidate import IsValidCVariableName +from Library.ParserValidate import IsValidBoolType +from Library.ParserValidate import IsValidPath +from Library.ParserValidate import IsValidFamily +from Library.ParserValidate import IsValidIdentifier +from Library.ParserValidate import IsValidDecVersionVal +from Object.Parser.InfCommonObject import InfLineCommentObject +from Object.Parser.InfCommonObject import CurrentLine +from Object.Parser.InfCommonObject import InfSectionCommonDef +from Object.Parser.InfMisc import ErrorInInf +from Object.Parser.InfDefineCommonObject import InfDefineLibraryItem +from Object.Parser.InfDefineCommonObject import InfDefineEntryPointItem +from Object.Parser.InfDefineCommonObject import InfDefineUnloadImageItem +from Object.Parser.InfDefineCommonObject import InfDefineConstructorItem +from Object.Parser.InfDefineCommonObject import InfDefineDestructorItem + +class InfDefSectionOptionRomInfo(): + def __init__(self): + self.PciVendorId = None + self.PciDeviceId = None + self.PciClassCode = None + self.PciRevision = None + self.PciCompress = None + self.CurrentLine = ['', -1, ''] + def SetPciVendorId(self, PciVendorId, Comments): + # + # Value has been set before. + # + if self.PciVendorId is not None: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND%(DT.TAB_INF_DEFINES_PCI_VENDOR_ID), + LineInfo=self.CurrentLine) + return False + # + # The PciVendorId should be hex string. + # + if (IsValidHex(PciVendorId)): + self.PciVendorId = InfDefMember() + self.PciVendorId.SetValue(PciVendorId) + self.PciVendorId.Comments = Comments + return True + else: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(PciVendorId), + LineInfo=self.CurrentLine) + return False + + def GetPciVendorId(self): + return self.PciVendorId + + def SetPciDeviceId(self, PciDeviceId, Comments): + # + # Value has been set before. + # + if self.PciDeviceId is not None: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND%(DT.TAB_INF_DEFINES_PCI_DEVICE_ID), + LineInfo=self.CurrentLine) + return False + # + # The PciDeviceId should be hex string. + # + if (IsValidHex(PciDeviceId)): + self.PciDeviceId = InfDefMember() + self.PciDeviceId.SetValue(PciDeviceId) + self.PciDeviceId.Comments = Comments + return True + else: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(PciDeviceId), + LineInfo=self.CurrentLine) + return False + + def GetPciDeviceId(self): + return self.PciDeviceId + + def SetPciClassCode(self, PciClassCode, Comments): + # + # Value has been set before. + # + if self.PciClassCode is not None: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND%(DT.TAB_INF_DEFINES_PCI_CLASS_CODE), + LineInfo=self.CurrentLine) + return False + # + # The PciClassCode should be 4 bytes hex string. + # + if (IsValidHex(PciClassCode)): + self.PciClassCode = InfDefMember() + self.PciClassCode.SetValue(PciClassCode) + self.PciClassCode.Comments = Comments + return True + else: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%\ + (PciClassCode), + LineInfo=self.CurrentLine) + return False + + def GetPciClassCode(self): + return self.PciClassCode + + def SetPciRevision(self, PciRevision, Comments): + # + # Value has been set before. + # + if self.PciRevision is not None: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND%(DT.TAB_INF_DEFINES_PCI_REVISION), + LineInfo=self.CurrentLine) + return False + # + # The PciRevision should be 4 bytes hex string. + # + if (IsValidHex(PciRevision)): + self.PciRevision = InfDefMember() + self.PciRevision.SetValue(PciRevision) + self.PciRevision.Comments = Comments + return True + else: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(PciRevision), + LineInfo=self.CurrentLine) + return False + + def GetPciRevision(self): + return self.PciRevision + + def SetPciCompress(self, PciCompress, Comments): + # + # Value has been set before. + # + if self.PciCompress is not None: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND%(DT.TAB_INF_DEFINES_PCI_COMPRESS), + LineInfo=self.CurrentLine) + return False + + # + # The PciCompress should be 'TRUE' or 'FALSE'. + # + if (PciCompress == 'TRUE' or PciCompress == 'FALSE'): + self.PciCompress = InfDefMember() + self.PciCompress.SetValue(PciCompress) + self.PciCompress.Comments = Comments + return True + else: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(PciCompress), + LineInfo=self.CurrentLine) + return False + def GetPciCompress(self): + return self.PciCompress +## +# INF [Define] section Object +# +class InfDefSection(InfDefSectionOptionRomInfo): + def __init__(self): + self.BaseName = None + self.FileGuid = None + self.ModuleType = None + self.ModuleUniFileName = None + self.InfVersion = None + self.EdkReleaseVersion = None + self.UefiSpecificationVersion = None + self.PiSpecificationVersion = None + self.LibraryClass = [] + self.Package = None + self.VersionString = None + self.PcdIsDriver = None + self.EntryPoint = [] + self.UnloadImages = [] + self.Constructor = [] + self.Destructor = [] + self.Shadow = None + self.CustomMakefile = [] + self.Specification = [] + self.UefiHiiResourceSection = None + self.DpxSource = [] + self.CurrentLine = ['', -1, ''] + InfDefSectionOptionRomInfo.__init__(self) + + ## SetHeadComment + # + # @param BaseName: BaseName + # + def SetBaseName(self, BaseName, Comments): + # + # Value has been set before. + # + if self.BaseName is not None: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND%(DT.TAB_INF_DEFINES_BASE_NAME), + LineInfo=self.CurrentLine) + return False + if not (BaseName == '' or BaseName is None): + if IsValidWord(BaseName) and not BaseName.startswith("_"): + self.BaseName = InfDefMember() + self.BaseName.SetValue(BaseName) + self.BaseName.Comments = Comments + return True + else: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_NAME_INVALID%(BaseName), + LineInfo=self.CurrentLine) + return False + + ## GetBaseName + # + def GetBaseName(self): + return self.BaseName + + ## SetFileGuid + # + # @param FileGuid: FileGuid + # + def SetFileGuid(self, FileGuid, Comments): + # + # Value has been set before. + # + if self.FileGuid is not None: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND\ + %(DT.TAB_INF_DEFINES_FILE_GUID), + LineInfo=self.CurrentLine) + return False + # + # Do verification of GUID content/format + # + if (CheckGuidRegFormat(FileGuid)): + self.FileGuid = InfDefMember() + self.FileGuid.SetValue(FileGuid) + self.FileGuid.Comments = Comments + return True + else: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_GUID_INVALID%(FileGuid), + LineInfo=self.CurrentLine) + return False + + ## GetFileGuid + # + def GetFileGuid(self): + return self.FileGuid + + ## SetModuleType + # + # @param ModuleType: ModuleType + # + def SetModuleType(self, ModuleType, Comments): + # + # Value has been set before. + # + if self.ModuleType is not None: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND\ + %(DT.TAB_INF_DEFINES_MODULE_TYPE), + LineInfo=self.CurrentLine) + return False + # + # Valid Module Type or not + # + if (IsValidInfMoudleType(ModuleType)): + self.ModuleType = InfDefMember() + self.ModuleType.SetValue(ModuleType) + self.ModuleType.CurrentLine = CurrentLine() + self.ModuleType.CurrentLine.SetLineNo(self.CurrentLine[1]) + self.ModuleType.CurrentLine.SetLineString(self.CurrentLine[2]) + self.ModuleType.CurrentLine.SetFileName(self.CurrentLine[0]) + self.ModuleType.Comments = Comments + return True + else: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_MODULETYPE_INVALID%\ + (ModuleType), + LineInfo=self.CurrentLine) + return False + + ## GetModuleType + # + def GetModuleType(self): + return self.ModuleType + + ## SetModuleUniFileName + # + # @param ModuleUniFileName: ModuleUniFileName + # + def SetModuleUniFileName(self, ModuleUniFileName, Comments): + if Comments: + pass + if self.ModuleUniFileName is not None: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND%(DT.TAB_INF_DEFINES_MODULE_UNI_FILE), + LineInfo=self.CurrentLine) + self.ModuleUniFileName = ModuleUniFileName + + ## GetModuleType + # + def GetModuleUniFileName(self): + return self.ModuleUniFileName + + ## SetInfVersion + # + # @param InfVersion: InfVersion + # + def SetInfVersion(self, InfVersion, Comments): + # + # Value has been set before. + # + if self.InfVersion is not None: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND\ + %(DT.TAB_INF_DEFINES_INF_VERSION), + LineInfo=self.CurrentLine) + return False + # + # The InfVersion should be 4 bytes hex string. + # + if (IsValidHex(InfVersion)): + if (InfVersion < '0x00010005'): + ErrorInInf(ST.ERR_INF_PARSER_NOT_SUPPORT_EDKI_INF, + ErrorCode=ToolError.EDK1_INF_ERROR, + LineInfo=self.CurrentLine) + elif IsValidDecVersionVal(InfVersion): + if (InfVersion < 65541): + ErrorInInf(ST.ERR_INF_PARSER_NOT_SUPPORT_EDKI_INF, + ErrorCode=ToolError.EDK1_INF_ERROR, + LineInfo=self.CurrentLine) + else: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(InfVersion), + LineInfo=self.CurrentLine) + return False + + self.InfVersion = InfDefMember() + self.InfVersion.SetValue(InfVersion) + self.InfVersion.Comments = Comments + return True + + ## GetInfVersion + # + def GetInfVersion(self): + return self.InfVersion + + ## SetEdkReleaseVersion + # + # @param EdkReleaseVersion: EdkReleaseVersion + # + def SetEdkReleaseVersion(self, EdkReleaseVersion, Comments): + # + # Value has been set before. + # + if self.EdkReleaseVersion is not None: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND\ + %(DT.TAB_INF_DEFINES_EDK_RELEASE_VERSION), + LineInfo=self.CurrentLine) + return False + # + # The EdkReleaseVersion should be 4 bytes hex string. + # + if IsValidHexVersion(EdkReleaseVersion) or \ + IsValidDecVersionVal(EdkReleaseVersion): + self.EdkReleaseVersion = InfDefMember() + self.EdkReleaseVersion.SetValue(EdkReleaseVersion) + self.EdkReleaseVersion.Comments = Comments + return True + else: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID\ + %(EdkReleaseVersion), + LineInfo=self.CurrentLine) + return False + + ## GetEdkReleaseVersion + # + def GetEdkReleaseVersion(self): + return self.EdkReleaseVersion + + ## SetUefiSpecificationVersion + # + # @param UefiSpecificationVersion: UefiSpecificationVersion + # + def SetUefiSpecificationVersion(self, UefiSpecificationVersion, Comments): + # + # Value has been set before. + # + if self.UefiSpecificationVersion is not None: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND\ + %(DT.TAB_INF_DEFINES_UEFI_SPECIFICATION_VERSION), + LineInfo=self.CurrentLine) + return False + # + # The EdkReleaseVersion should be 4 bytes hex string. + # + if IsValidHexVersion(UefiSpecificationVersion) or \ + IsValidDecVersionVal(UefiSpecificationVersion): + self.UefiSpecificationVersion = InfDefMember() + self.UefiSpecificationVersion.SetValue(UefiSpecificationVersion) + self.UefiSpecificationVersion.Comments = Comments + return True + else: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID\ + %(UefiSpecificationVersion), + LineInfo=self.CurrentLine) + return False + + ## GetUefiSpecificationVersion + # + def GetUefiSpecificationVersion(self): + return self.UefiSpecificationVersion + + ## SetPiSpecificationVersion + # + # @param PiSpecificationVersion: PiSpecificationVersion + # + def SetPiSpecificationVersion(self, PiSpecificationVersion, Comments): + # + # Value has been set before. + # + if self.PiSpecificationVersion is not None: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND\ + %(DT.TAB_INF_DEFINES_PI_SPECIFICATION_VERSION), + LineInfo=self.CurrentLine) + return False + # + # The EdkReleaseVersion should be 4 bytes hex string. + # + if IsValidHexVersion(PiSpecificationVersion) or \ + IsValidDecVersionVal(PiSpecificationVersion): + self.PiSpecificationVersion = InfDefMember() + self.PiSpecificationVersion.SetValue(PiSpecificationVersion) + self.PiSpecificationVersion.Comments = Comments + return True + else: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID\ + %(PiSpecificationVersion), + LineInfo=self.CurrentLine) + return False + + ## GetPiSpecificationVersion + # + def GetPiSpecificationVersion(self): + return self.PiSpecificationVersion + + ## SetLibraryClass + # + # @param LibraryClass: LibraryClass + # + def SetLibraryClass(self, LibraryClass, Comments): + ValueList = GetSplitValueList(LibraryClass) + Name = ValueList[0] + if IsValidWord(Name): + InfDefineLibraryItemObj = InfDefineLibraryItem() + InfDefineLibraryItemObj.SetLibraryName(Name) + InfDefineLibraryItemObj.Comments = Comments + if len(ValueList) == 2: + Type = ValueList[1] + TypeList = GetSplitValueList(Type, ' ') + TypeList = [Type for Type in TypeList if Type != ''] + for Item in TypeList: + if Item not in DT.MODULE_LIST: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(Item), + LineInfo=self.CurrentLine) + return False + InfDefineLibraryItemObj.SetTypes(TypeList) + self.LibraryClass.append(InfDefineLibraryItemObj) + else: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(Name), + LineInfo=self.CurrentLine) + return False + + return True + + def GetLibraryClass(self): + return self.LibraryClass + + def SetVersionString(self, VersionString, Comments): + # + # Value has been set before. + # + if self.VersionString is not None: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND\ + %(DT.TAB_INF_DEFINES_VERSION_STRING), + LineInfo=self.CurrentLine) + return False + if not IsValidDecVersion(VersionString): + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID\ + %(VersionString), + LineInfo=self.CurrentLine) + self.VersionString = InfDefMember() + self.VersionString.SetValue(VersionString) + self.VersionString.Comments = Comments + return True + + + def GetVersionString(self): + return self.VersionString + + def SetPcdIsDriver(self, PcdIsDriver, Comments): + # + # Value has been set before. + # + if self.PcdIsDriver is not None: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND\ + %(DT.TAB_INF_DEFINES_PCD_IS_DRIVER), + LineInfo=self.CurrentLine) + return False + if PcdIsDriver == 'PEI_PCD_DRIVER' or PcdIsDriver == 'DXE_PCD_DRIVER': + self.PcdIsDriver = InfDefMember() + self.PcdIsDriver.SetValue(PcdIsDriver) + self.PcdIsDriver.Comments = Comments + return True + else: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(PcdIsDriver), + LineInfo=self.CurrentLine) + return False + + def GetPcdIsDriver(self): + return self.PcdIsDriver + + # + # SetEntryPoint + # + def SetEntryPoint(self, EntryPoint, Comments): + # + # It can be a list + # + ValueList = [] + TokenList = GetSplitValueList(EntryPoint, DT.TAB_VALUE_SPLIT) + ValueList[0:len(TokenList)] = TokenList + InfDefineEntryPointItemObj = InfDefineEntryPointItem() + if not IsValidCVariableName(ValueList[0]): + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%\ + (ValueList[0]), + LineInfo=self.CurrentLine) + InfDefineEntryPointItemObj.SetCName(ValueList[0]) + if len(ValueList) == 2: + if ValueList[1].strip() == '': + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%\ + (ValueList[1]), + LineInfo=self.CurrentLine) + # + # Validate FFE + # + FeatureFlagRtv = IsValidFeatureFlagExp(ValueList[1].strip()) + if not FeatureFlagRtv[0]: + ErrorInInf(ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_SYNTAX_INVLID%\ + (FeatureFlagRtv[1]), + LineInfo=self.CurrentLine) + InfDefineEntryPointItemObj.SetFeatureFlagExp(ValueList[1]) + if len(ValueList) > 2: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(EntryPoint), + LineInfo=self.CurrentLine) + InfDefineEntryPointItemObj.Comments = Comments + self.EntryPoint.append(InfDefineEntryPointItemObj) + + def GetEntryPoint(self): + return self.EntryPoint + + # + # SetUnloadImages + # + def SetUnloadImages(self, UnloadImages, Comments): + # + # It can be a list + # + ValueList = [] + TokenList = GetSplitValueList(UnloadImages, DT.TAB_VALUE_SPLIT) + ValueList[0:len(TokenList)] = TokenList + InfDefineUnloadImageItemObj = InfDefineUnloadImageItem() + if not IsValidCVariableName(ValueList[0]): + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(ValueList[0]), + LineInfo=self.CurrentLine) + InfDefineUnloadImageItemObj.SetCName(ValueList[0]) + if len(ValueList) == 2: + if ValueList[1].strip() == '': + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(ValueList[1]), + LineInfo=self.CurrentLine) + # + # Validate FFE + # + FeatureFlagRtv = IsValidFeatureFlagExp(ValueList[1].strip()) + if not FeatureFlagRtv[0]: + ErrorInInf(ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_SYNTAX_INVLID%(FeatureFlagRtv[1]), + LineInfo=self.CurrentLine) + InfDefineUnloadImageItemObj.SetFeatureFlagExp(ValueList[1]) + + if len(ValueList) > 2: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(UnloadImages), + LineInfo=self.CurrentLine) + InfDefineUnloadImageItemObj.Comments = Comments + self.UnloadImages.append(InfDefineUnloadImageItemObj) + + def GetUnloadImages(self): + return self.UnloadImages + + # + # SetConstructor + # + def SetConstructor(self, Constructor, Comments): + # + # It can be a list + # + ValueList = [] + TokenList = GetSplitValueList(Constructor, DT.TAB_VALUE_SPLIT) + ValueList[0:len(TokenList)] = TokenList + InfDefineConstructorItemObj = InfDefineConstructorItem() + if not IsValidCVariableName(ValueList[0]): + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(ValueList[0]), + LineInfo=self.CurrentLine) + InfDefineConstructorItemObj.SetCName(ValueList[0]) + if len(ValueList) >= 2: + ModList = GetSplitValueList(ValueList[1], ' ') + if ValueList[1].strip() == '': + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(ValueList[1]), + LineInfo=self.CurrentLine) + for ModItem in ModList: + if ModItem not in DT.MODULE_LIST: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_MODULETYPE_INVALID%(ModItem), + LineInfo=self.CurrentLine) + InfDefineConstructorItemObj.SetSupModList(ModList) + if len(ValueList) == 3: + if ValueList[2].strip() == '': + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(ValueList[2]), + LineInfo=self.CurrentLine) + # + # Validate FFE + # + FeatureFlagRtv = IsValidFeatureFlagExp(ValueList[2].strip()) + if not FeatureFlagRtv[0]: + ErrorInInf(ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_SYNTAX_INVLID%(FeatureFlagRtv[2]), + LineInfo=self.CurrentLine) + InfDefineConstructorItemObj.SetFeatureFlagExp(ValueList[2]) + + if len(ValueList) > 3: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(Constructor), + LineInfo=self.CurrentLine) + InfDefineConstructorItemObj.Comments = Comments + self.Constructor.append(InfDefineConstructorItemObj) + + def GetConstructor(self): + return self.Constructor + + # + # SetDestructor + # + def SetDestructor(self, Destructor, Comments): + # + # It can be a list and only 1 set to TRUE + # + ValueList = [] + TokenList = GetSplitValueList(Destructor, DT.TAB_VALUE_SPLIT) + ValueList[0:len(TokenList)] = TokenList + InfDefineDestructorItemObj = InfDefineDestructorItem() + if not IsValidCVariableName(ValueList[0]): + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(ValueList[0]), + LineInfo=self.CurrentLine) + InfDefineDestructorItemObj.SetCName(ValueList[0]) + if len(ValueList) >= 2: + ModList = GetSplitValueList(ValueList[1].strip(), ' ') + if ValueList[1].strip() == '': + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(ValueList[1]), + LineInfo=self.CurrentLine) + for ModItem in ModList: + if ModItem not in DT.MODULE_LIST: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_MODULETYPE_INVALID%(ModItem), + LineInfo=self.CurrentLine) + InfDefineDestructorItemObj.SetSupModList(ModList) + if len(ValueList) == 3: + if ValueList[2].strip() == '': + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(ValueList[2]), + LineInfo=self.CurrentLine) + # + # Validate FFE + # + FeatureFlagRtv = IsValidFeatureFlagExp(ValueList[2].strip()) + if not FeatureFlagRtv[0]: + ErrorInInf(ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_SYNTAX_INVLID%(FeatureFlagRtv[1]), + LineInfo=self.CurrentLine) + InfDefineDestructorItemObj.SetFeatureFlagExp(ValueList[2]) + + if len(ValueList) > 3: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(Destructor), + LineInfo=self.CurrentLine) + + InfDefineDestructorItemObj.Comments = Comments + self.Destructor.append(InfDefineDestructorItemObj) + + def GetDestructor(self): + return self.Destructor + + def SetShadow(self, Shadow, Comments): + # + # Value has been set before. + # + if self.Shadow is not None: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND%(DT.TAB_INF_DEFINES_SHADOW), + LineInfo=self.CurrentLine) + return False + if (IsValidBoolType(Shadow)): + self.Shadow = InfDefMember() + self.Shadow.SetValue(Shadow) + self.Shadow.Comments = Comments + return True + else: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(Shadow), + LineInfo=self.CurrentLine) + return False + def GetShadow(self): + return self.Shadow + + # + # ::= {"MSFT"} {"GCC"} + # ::= [ "|"] + # + def SetCustomMakefile(self, CustomMakefile, Comments): + if not (CustomMakefile == '' or CustomMakefile is None): + ValueList = GetSplitValueList(CustomMakefile) + if len(ValueList) == 1: + FileName = ValueList[0] + Family = '' + else: + Family = ValueList[0] + FileName = ValueList[1] + Family = Family.strip() + if Family != '': + if not IsValidFamily(Family): + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(Family), + LineInfo=self.CurrentLine) + return False + # + # The MakefileName specified file should exist + # + IsValidFileFlag = False + ModulePath = os.path.split(self.CurrentLine[0])[0] + if IsValidPath(FileName, ModulePath): + IsValidFileFlag = True + else: + ErrorInInf(ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID%(FileName), + LineInfo=self.CurrentLine) + return False + if IsValidFileFlag: + FileName = ConvPathFromAbsToRel(FileName, GlobalData.gINF_MODULE_DIR) + self.CustomMakefile.append((Family, FileName, Comments)) + IsValidFileFlag = False + return True + else: + return False + + def GetCustomMakefile(self): + return self.CustomMakefile + + # + # ["SPEC" ]*{0,} + # ::= "=" + # ::= {] {} + # ::= "0x" []{1,} + # ::= (0-9){1,} ["." (0-9){1,2}] + # + def SetSpecification(self, Specification, Comments): + # + # Valid the value of Specification + # + __ValueList = [] + TokenList = GetSplitValueList(Specification, DT.TAB_EQUAL_SPLIT, 1) + __ValueList[0:len(TokenList)] = TokenList + if len(__ValueList) != 2: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_NO_NAME + ' Or ' + ST.ERR_INF_PARSER_DEFINE_ITEM_NO_VALUE, + LineInfo=self.CurrentLine) + Name = __ValueList[0].strip() + Version = __ValueList[1].strip() + if IsValidIdentifier(Name): + if IsValidDecVersion(Version): + self.Specification.append((Name, Version, Comments)) + return True + else: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(Version), + LineInfo=self.CurrentLine) + return False + else: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(Name), + LineInfo=self.CurrentLine) + return False + return True + + def GetSpecification(self): + return self.Specification + + # + # [ ]{0,1} + # ::= "UEFI_HII_RESOURCE_SECTION" "=" + # + def SetUefiHiiResourceSection(self, UefiHiiResourceSection, Comments): + # + # Value has been set before. + # + if self.UefiHiiResourceSection is not None: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND + %(DT.TAB_INF_DEFINES_UEFI_HII_RESOURCE_SECTION), + LineInfo=self.CurrentLine) + return False + if not (UefiHiiResourceSection == '' or UefiHiiResourceSection is None): + if (IsValidBoolType(UefiHiiResourceSection)): + self.UefiHiiResourceSection = InfDefMember() + self.UefiHiiResourceSection.SetValue(UefiHiiResourceSection) + self.UefiHiiResourceSection.Comments = Comments + return True + else: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(UefiHiiResourceSection), + LineInfo=self.CurrentLine) + return False + else: + return False + + def GetUefiHiiResourceSection(self): + return self.UefiHiiResourceSection + + def SetDpxSource(self, DpxSource, Comments): + # + # The MakefileName specified file should exist + # + IsValidFileFlag = False + ModulePath = os.path.split(self.CurrentLine[0])[0] + if IsValidPath(DpxSource, ModulePath): + IsValidFileFlag = True + else: + ErrorInInf(ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID%(DpxSource), + LineInfo=self.CurrentLine) + return False + if IsValidFileFlag: + DpxSource = ConvPathFromAbsToRel(DpxSource, + GlobalData.gINF_MODULE_DIR) + self.DpxSource.append((DpxSource, Comments)) + IsValidFileFlag = False + return True + + def GetDpxSource(self): + return self.DpxSource + +gFUNCTION_MAPPING_FOR_DEFINE_SECTION = { + # + # Required Fields + # + DT.TAB_INF_DEFINES_BASE_NAME : InfDefSection.SetBaseName, + DT.TAB_INF_DEFINES_FILE_GUID : InfDefSection.SetFileGuid, + DT.TAB_INF_DEFINES_MODULE_TYPE : InfDefSection.SetModuleType, + # + # Required by EDKII style INF file + # + DT.TAB_INF_DEFINES_INF_VERSION : InfDefSection.SetInfVersion, + # + # Optional Fields + # + DT.TAB_INF_DEFINES_MODULE_UNI_FILE : InfDefSection.SetModuleUniFileName, + DT.TAB_INF_DEFINES_EDK_RELEASE_VERSION : InfDefSection.SetEdkReleaseVersion, + DT.TAB_INF_DEFINES_UEFI_SPECIFICATION_VERSION : InfDefSection.SetUefiSpecificationVersion, + DT.TAB_INF_DEFINES_PI_SPECIFICATION_VERSION : InfDefSection.SetPiSpecificationVersion, + DT.TAB_INF_DEFINES_LIBRARY_CLASS : InfDefSection.SetLibraryClass, + DT.TAB_INF_DEFINES_VERSION_STRING : InfDefSection.SetVersionString, + DT.TAB_INF_DEFINES_PCD_IS_DRIVER : InfDefSection.SetPcdIsDriver, + DT.TAB_INF_DEFINES_ENTRY_POINT : InfDefSection.SetEntryPoint, + DT.TAB_INF_DEFINES_UNLOAD_IMAGE : InfDefSection.SetUnloadImages, + DT.TAB_INF_DEFINES_CONSTRUCTOR : InfDefSection.SetConstructor, + DT.TAB_INF_DEFINES_DESTRUCTOR : InfDefSection.SetDestructor, + DT.TAB_INF_DEFINES_SHADOW : InfDefSection.SetShadow, + DT.TAB_INF_DEFINES_PCI_VENDOR_ID : InfDefSection.SetPciVendorId, + DT.TAB_INF_DEFINES_PCI_DEVICE_ID : InfDefSection.SetPciDeviceId, + DT.TAB_INF_DEFINES_PCI_CLASS_CODE : InfDefSection.SetPciClassCode, + DT.TAB_INF_DEFINES_PCI_REVISION : InfDefSection.SetPciRevision, + DT.TAB_INF_DEFINES_PCI_COMPRESS : InfDefSection.SetPciCompress, + DT.TAB_INF_DEFINES_CUSTOM_MAKEFILE : InfDefSection.SetCustomMakefile, + DT.TAB_INF_DEFINES_SPEC : InfDefSection.SetSpecification, + DT.TAB_INF_DEFINES_UEFI_HII_RESOURCE_SECTION : InfDefSection.SetUefiHiiResourceSection, + DT.TAB_INF_DEFINES_DPX_SOURCE : InfDefSection.SetDpxSource +} + +## InfDefMember +# +# +class InfDefMember(): + def __init__(self, Name='', Value=''): + self.Comments = InfLineCommentObject() + self.Name = Name + self.Value = Value + self.CurrentLine = CurrentLine() + def GetName(self): + return self.Name + def SetName(self, Name): + self.Name = Name + def GetValue(self): + return self.Value + def SetValue(self, Value): + self.Value = Value + +## InfDefObject +# +# +class InfDefObject(InfSectionCommonDef): + def __init__(self): + self.Defines = Sdict() + InfSectionCommonDef.__init__(self) + def SetDefines(self, DefineContent, Arch = None): + # + # Validate Arch + # + HasFoundInfVersionFalg = False + LineInfo = ['', -1, ''] + ArchListString = ' '.join(Arch) + # + # Parse Define items. + # + for InfDefMemberObj in DefineContent: + ProcessFunc = None + Name = InfDefMemberObj.GetName() + Value = InfDefMemberObj.GetValue() + if Name == DT.TAB_INF_DEFINES_MODULE_UNI_FILE: + ValidateUNIFilePath(Value) + Value = os.path.join(os.path.dirname(InfDefMemberObj.CurrentLine.FileName), Value) + if not os.path.isfile(Value) or not os.path.exists(Value): + LineInfo[0] = InfDefMemberObj.CurrentLine.GetFileName() + LineInfo[1] = InfDefMemberObj.CurrentLine.GetLineNo() + LineInfo[2] = InfDefMemberObj.CurrentLine.GetLineString() + ErrorInInf(ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID%(Name), + LineInfo=LineInfo) + InfLineCommentObj = InfLineCommentObject() + InfLineCommentObj.SetHeaderComments(InfDefMemberObj.Comments.GetHeaderComments()) + InfLineCommentObj.SetTailComments(InfDefMemberObj.Comments.GetTailComments()) + if Name == 'COMPONENT_TYPE': + ErrorInInf(ST.ERR_INF_PARSER_NOT_SUPPORT_EDKI_INF, + ErrorCode=ToolError.EDK1_INF_ERROR, + RaiseError=True) + if Name == DT.TAB_INF_DEFINES_INF_VERSION: + HasFoundInfVersionFalg = True + if not (Name == '' or Name is None): + # + # Process "SPEC" Keyword definition. + # + ReName = re.compile(r"SPEC ", re.DOTALL) + if ReName.match(Name): + SpecValue = Name[Name.find("SPEC") + len("SPEC"):].strip() + Name = "SPEC" + Value = SpecValue + " = " + Value + if ArchListString in self.Defines: + DefineList = self.Defines[ArchListString] + LineInfo[0] = InfDefMemberObj.CurrentLine.GetFileName() + LineInfo[1] = InfDefMemberObj.CurrentLine.GetLineNo() + LineInfo[2] = InfDefMemberObj.CurrentLine.GetLineString() + DefineList.CurrentLine = LineInfo + # + # Found the process function from mapping table. + # + if Name not in gFUNCTION_MAPPING_FOR_DEFINE_SECTION.keys(): + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_SECTION_KEYWORD_INVALID%(Name), + LineInfo=LineInfo) + else: + ProcessFunc = gFUNCTION_MAPPING_FOR_DEFINE_SECTION[Name] + if (ProcessFunc is not None): + ProcessFunc(DefineList, Value, InfLineCommentObj) + self.Defines[ArchListString] = DefineList + else: + DefineList = InfDefSection() + LineInfo[0] = InfDefMemberObj.CurrentLine.GetFileName() + LineInfo[1] = InfDefMemberObj.CurrentLine.GetLineNo() + LineInfo[2] = InfDefMemberObj.CurrentLine.GetLineString() + DefineList.CurrentLine = LineInfo + # + # Found the process function from mapping table. + # + if Name not in gFUNCTION_MAPPING_FOR_DEFINE_SECTION.keys(): + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_SECTION_KEYWORD_INVALID%(Name), + LineInfo=LineInfo) + # + # Found the process function from mapping table. + # + else: + ProcessFunc = gFUNCTION_MAPPING_FOR_DEFINE_SECTION[Name] + if (ProcessFunc is not None): + ProcessFunc(DefineList, Value, InfLineCommentObj) + self.Defines[ArchListString] = DefineList + # + # After set, check whether INF_VERSION defined. + # + if not HasFoundInfVersionFalg: + ErrorInInf(ST.ERR_INF_PARSER_NOT_SUPPORT_EDKI_INF, + ErrorCode=ToolError.EDK1_INF_ERROR, + RaiseError=True) + return True + + def GetDefines(self): + return self.Defines + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfDepexObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfDepexObject.py new file mode 100755 index 00000000..b0b1db68 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfDepexObject.py @@ -0,0 +1,160 @@ +## @file +# This file is used to define class objects of INF file [Depex] section. +# It will consumed by InfParser. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +''' +InfDepexObject +''' + +from Library import DataType as DT +from Library import GlobalData +import Logger.Log as Logger +from Logger import ToolError +from Logger import StringTable as ST + +from Object.Parser.InfCommonObject import InfSectionCommonDef +from Library.ParserValidate import IsValidArch + +class InfDepexContentItem(): + def __init__(self): + self.SectionType = '' + self.SectionString = '' + + def SetSectionType(self, SectionType): + self.SectionType = SectionType + def GetSectionType(self): + return self.SectionType + + def SetSectionString(self, SectionString): + self.SectionString = SectionString + def GetSectionString(self): + return self.SectionString + + +class InfDepexItem(): + def __init__(self): + self.DepexContent = '' + self.ModuleType = '' + self.SupArch = '' + self.HelpString = '' + self.FeatureFlagExp = '' + self.InfDepexContentItemList = [] + + def SetFeatureFlagExp(self, FeatureFlagExp): + self.FeatureFlagExp = FeatureFlagExp + def GetFeatureFlagExp(self): + return self.FeatureFlagExp + + def SetSupArch(self, Arch): + self.SupArch = Arch + def GetSupArch(self): + return self.SupArch + + def SetHelpString(self, HelpString): + self.HelpString = HelpString + def GetHelpString(self): + return self.HelpString + + def SetModuleType(self, Type): + self.ModuleType = Type + def GetModuleType(self): + return self.ModuleType + + def SetDepexConent(self, Content): + self.DepexContent = Content + def GetDepexContent(self): + return self.DepexContent + + def SetInfDepexContentItemList(self, InfDepexContentItemList): + self.InfDepexContentItemList = InfDepexContentItemList + def GetInfDepexContentItemList(self): + return self.InfDepexContentItemList + +## InfDepexObject +# +# +# +class InfDepexObject(InfSectionCommonDef): + def __init__(self): + self.Depex = [] + self.AllContent = '' + self.SectionContent = '' + InfSectionCommonDef.__init__(self) + + def SetDepex(self, DepexContent, KeyList=None, CommentList=None): + for KeyItem in KeyList: + Arch = KeyItem[0] + ModuleType = KeyItem[1] + InfDepexItemIns = InfDepexItem() + + # + # Validate Arch + # + if IsValidArch(Arch.strip().upper()): + InfDepexItemIns.SetSupArch(Arch) + else: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_DEFINE_NAME_INVALID % (Arch), + File=GlobalData.gINF_MODULE_NAME, + Line=KeyItem[2]) + + # + # Validate Module Type + # + if ModuleType and ModuleType != 'COMMON': + if ModuleType in DT.VALID_DEPEX_MODULE_TYPE_LIST: + InfDepexItemIns.SetModuleType(ModuleType) + else: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_DEPEX_SECTION_MODULE_TYPE_ERROR % (ModuleType), + File=GlobalData.gINF_MODULE_NAME, + Line=KeyItem[2]) + + # + # Parser content in [Depex] section. + # + DepexString = '' + HelpString = '' + # + # Get Depex Expression + # + for Line in DepexContent: + LineContent = Line[0].strip() + if LineContent.find(DT.TAB_COMMENT_SPLIT) > -1: + LineContent = LineContent[:LineContent.find(DT.TAB_COMMENT_SPLIT)] + if LineContent: + DepexString = DepexString + LineContent + DT.END_OF_LINE + continue + + if DepexString.endswith(DT.END_OF_LINE): + DepexString = DepexString[:-1] + + if not DepexString.strip(): + continue + + # + # Get Help Text + # + for HelpLine in CommentList: + HelpString = HelpString + HelpLine + DT.END_OF_LINE + if HelpString.endswith(DT.END_OF_LINE): + HelpString = HelpString[:-1] + + InfDepexItemIns.SetDepexConent(DepexString) + InfDepexItemIns.SetHelpString(HelpString) + + self.Depex.append(InfDepexItemIns) + + return True + + def GetDepex(self): + return self.Depex + + def GetAllContent(self): + return self.AllContent diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfGuidObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfGuidObject.py new file mode 100755 index 00000000..f0eff8bd --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfGuidObject.py @@ -0,0 +1,347 @@ +## @file +# This file is used to define class objects of INF file [Guids] section. +# It will consumed by InfParser. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +''' +InfGuidObject +''' + +from Library.ParserValidate import IsValidCVariableName +from Library.CommentParsing import ParseComment +from Library.ExpressionValidate import IsValidFeatureFlagExp + +from Library.Misc import Sdict +from Library import DataType as DT +import Logger.Log as Logger +from Logger import ToolError +from Logger import StringTable as ST + +class InfGuidItemCommentContent(): + def __init__(self): + # + # ## SOMETIMES_CONSUMES ## Variable:L"MemoryTypeInformation" + # TailString. + # + # + # SOMETIMES_CONSUMES + # + self.UsageItem = '' + # + # Variable + # + self.GuidTypeItem = '' + # + # MemoryTypeInformation + # + self.VariableNameItem = '' + # + # TailString + # + self.HelpStringItem = '' + + def SetUsageItem(self, UsageItem): + self.UsageItem = UsageItem + def GetUsageItem(self): + return self.UsageItem + + def SetGuidTypeItem(self, GuidTypeItem): + self.GuidTypeItem = GuidTypeItem + def GetGuidTypeItem(self): + return self.GuidTypeItem + + def SetVariableNameItem(self, VariableNameItem): + self.VariableNameItem = VariableNameItem + def GetVariableNameItem(self): + return self.VariableNameItem + + def SetHelpStringItem(self, HelpStringItem): + self.HelpStringItem = HelpStringItem + def GetHelpStringItem(self): + return self.HelpStringItem + +class InfGuidItem(): + def __init__(self): + self.Name = '' + self.FeatureFlagExp = '' + # + # A list contain instance of InfGuidItemCommentContent + # + self.CommentList = [] + self.SupArchList = [] + + def SetName(self, Name): + self.Name = Name + def GetName(self): + return self.Name + + def SetFeatureFlagExp(self, FeatureFlagExp): + self.FeatureFlagExp = FeatureFlagExp + def GetFeatureFlagExp(self): + return self.FeatureFlagExp + + def SetCommentList(self, CommentList): + self.CommentList = CommentList + def GetCommentList(self): + return self.CommentList + + def SetSupArchList(self, SupArchList): + self.SupArchList = SupArchList + def GetSupArchList(self): + return self.SupArchList + +## ParseComment +# +# ParseComment +# +def ParseGuidComment(CommentsList, InfGuidItemObj): + # + # Get/Set Usage and HelpString + # + if CommentsList is not None and len(CommentsList) != 0 : + CommentInsList = [] + PreUsage = None + PreGuidType = None + PreHelpText = '' + BlockFlag = -1 + Count = 0 + for CommentItem in CommentsList: + Count = Count + 1 + CommentItemUsage, \ + CommentItemGuidType, \ + CommentItemVarString, \ + CommentItemHelpText = \ + ParseComment(CommentItem, + DT.ALL_USAGE_TOKENS, + DT.GUID_TYPE_TOKENS, + [], + True) + + if CommentItemHelpText is None: + CommentItemHelpText = '' + if Count == len(CommentsList) and CommentItemUsage == CommentItemGuidType == DT.ITEM_UNDEFINED: + CommentItemHelpText = DT.END_OF_LINE + + if Count == len(CommentsList): + if BlockFlag == 1 or BlockFlag == 2: + if CommentItemUsage == CommentItemGuidType == DT.ITEM_UNDEFINED: + BlockFlag = 4 + else: + BlockFlag = 3 + if BlockFlag == -1: + BlockFlag = 4 + if BlockFlag == -1 or BlockFlag == 1 or BlockFlag == 2: + if CommentItemUsage == CommentItemGuidType == DT.ITEM_UNDEFINED: + if BlockFlag == -1: + BlockFlag = 1 + elif BlockFlag == 1: + BlockFlag = 2 + else: + if BlockFlag == 1 or BlockFlag == 2: + BlockFlag = 3 + elif BlockFlag == -1: + BlockFlag = 4 + + # + # Combine two comment line if they are generic comment + # + if CommentItemUsage == CommentItemGuidType == PreUsage == PreGuidType == DT.ITEM_UNDEFINED: + CommentItemHelpText = PreHelpText + DT.END_OF_LINE + CommentItemHelpText + PreHelpText = CommentItemHelpText + + if BlockFlag == 4: + CommentItemIns = InfGuidItemCommentContent() + CommentItemIns.SetUsageItem(CommentItemUsage) + CommentItemIns.SetGuidTypeItem(CommentItemGuidType) + CommentItemIns.SetVariableNameItem(CommentItemVarString) + if CommentItemHelpText == '' or CommentItemHelpText.endswith(DT.END_OF_LINE): + CommentItemHelpText = CommentItemHelpText.strip(DT.END_OF_LINE) + CommentItemIns.SetHelpStringItem(CommentItemHelpText) + CommentInsList.append(CommentItemIns) + + BlockFlag = -1 + PreUsage = None + PreGuidType = None + PreHelpText = '' + + elif BlockFlag == 3: + # + # Add previous help string + # + CommentItemIns = InfGuidItemCommentContent() + CommentItemIns.SetUsageItem(DT.ITEM_UNDEFINED) + CommentItemIns.SetGuidTypeItem(DT.ITEM_UNDEFINED) + if PreHelpText == '' or PreHelpText.endswith(DT.END_OF_LINE): + PreHelpText = PreHelpText.strip(DT.END_OF_LINE) + CommentItemIns.SetHelpStringItem(PreHelpText) + CommentInsList.append(CommentItemIns) + # + # Add Current help string + # + CommentItemIns = InfGuidItemCommentContent() + CommentItemIns.SetUsageItem(CommentItemUsage) + CommentItemIns.SetGuidTypeItem(CommentItemGuidType) + CommentItemIns.SetVariableNameItem(CommentItemVarString) + if CommentItemHelpText == '' or CommentItemHelpText.endswith(DT.END_OF_LINE): + CommentItemHelpText = CommentItemHelpText.strip(DT.END_OF_LINE) + CommentItemIns.SetHelpStringItem(CommentItemHelpText) + CommentInsList.append(CommentItemIns) + + BlockFlag = -1 + PreUsage = None + PreGuidType = None + PreHelpText = '' + + else: + PreUsage = CommentItemUsage + PreGuidType = CommentItemGuidType + PreHelpText = CommentItemHelpText + + InfGuidItemObj.SetCommentList(CommentInsList) + else: + # + # Still need to set the USAGE/GUIDTYPE to undefined. + # + CommentItemIns = InfGuidItemCommentContent() + CommentItemIns.SetUsageItem(DT.ITEM_UNDEFINED) + CommentItemIns.SetGuidTypeItem(DT.ITEM_UNDEFINED) + InfGuidItemObj.SetCommentList([CommentItemIns]) + + return InfGuidItemObj + +## InfGuidObject +# +# InfGuidObject +# +class InfGuidObject(): + def __init__(self): + self.Guids = Sdict() + # + # Macro defined in this section should be only used in this section. + # + self.Macros = {} + + def SetGuid(self, GuidList, Arch = None): + __SupportArchList = [] + for ArchItem in Arch: + # + # Validate Arch + # + if (ArchItem == '' or ArchItem is None): + ArchItem = 'COMMON' + + __SupportArchList.append(ArchItem) + + for Item in GuidList: + # + # Get Comment content of this protocol + # + CommentsList = None + if len(Item) == 3: + CommentsList = Item[1] + CurrentLineOfItem = Item[2] + Item = Item[0] + InfGuidItemObj = InfGuidItem() + if len(Item) >= 1 and len(Item) <= 2: + # + # Only GuildName contained + # + if not IsValidCVariableName(Item[0]): + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_INVALID_CNAME%(Item[0]), + File=CurrentLineOfItem[2], + Line=CurrentLineOfItem[1], + ExtraData=CurrentLineOfItem[0]) + if (Item[0] != ''): + InfGuidItemObj.SetName(Item[0]) + else: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_CNAME_MISSING, + File=CurrentLineOfItem[2], + Line=CurrentLineOfItem[1], + ExtraData=CurrentLineOfItem[0]) + if len(Item) == 2: + # + # Contained CName and Feature Flag Express + # ::= ["|" ] + # For GUID entry. + # + if Item[1].strip() == '': + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_MISSING, + File=CurrentLineOfItem[2], + Line=CurrentLineOfItem[1], + ExtraData=CurrentLineOfItem[0]) + # + # Validate Feature Flag Express + # + FeatureFlagRtv = IsValidFeatureFlagExp(Item[1].strip()) + if not FeatureFlagRtv[0]: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_SYNTAX_INVLID%(FeatureFlagRtv[1]), + File=CurrentLineOfItem[2], + Line=CurrentLineOfItem[1], + ExtraData=CurrentLineOfItem[0]) + InfGuidItemObj.SetFeatureFlagExp(Item[1]) + if len(Item) != 1 and len(Item) != 2: + # + # Invalid format of GUID statement + # + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_GUID_PPI_PROTOCOL_SECTION_CONTENT_ERROR, + File=CurrentLineOfItem[2], + Line=CurrentLineOfItem[1], + ExtraData=CurrentLineOfItem[0]) + + InfGuidItemObj = ParseGuidComment(CommentsList, InfGuidItemObj) + InfGuidItemObj.SetSupArchList(__SupportArchList) + + # + # Determine GUID name duplicate. Follow below rule: + # + # A GUID must not be duplicated within a [Guids] section. + # A GUID may appear in multiple architectural [Guids] + # sections. A GUID listed in an architectural [Guids] + # section must not be listed in the common architectural + # [Guids] section. + # + # NOTE: This check will not report error now. + # + for Item in self.Guids: + if Item.GetName() == InfGuidItemObj.GetName(): + ItemSupArchList = Item.GetSupArchList() + for ItemArch in ItemSupArchList: + for GuidItemObjArch in __SupportArchList: + if ItemArch == GuidItemObjArch: + # + # ST.ERR_INF_PARSER_ITEM_DUPLICATE + # + pass + + if ItemArch.upper() == 'COMMON' or GuidItemObjArch.upper() == 'COMMON': + # + # ST.ERR_INF_PARSER_ITEM_DUPLICATE_COMMON + # + pass + + if (InfGuidItemObj) in self.Guids: + GuidList = self.Guids[InfGuidItemObj] + GuidList.append(InfGuidItemObj) + self.Guids[InfGuidItemObj] = GuidList + else: + GuidList = [] + GuidList.append(InfGuidItemObj) + self.Guids[InfGuidItemObj] = GuidList + + return True + + def GetGuid(self): + return self.Guids diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfHeaderObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfHeaderObject.py new file mode 100755 index 00000000..2e70f08b --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfHeaderObject.py @@ -0,0 +1,113 @@ +## @file +# This file is used to define class objects of INF file header. +# It will consumed by InfParser. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +''' +InfHeaderObject +''' + +## INF file header object +# +# A sample file header +# +# ## @file xxx.inf FileName +# # Abstract +# # +# # Description +# # +# # Copyright +# # +# # License +# # +# +class InfHeaderObject(): + def __init__(self): + self.FileName = '' + self.Abstract = '' + self.Description = '' + self.Copyright = '' + self.License = '' + + ## SetFileName + # + # @param FileName: File Name + # + def SetFileName(self, FileName): + if not (FileName == '' or FileName is None): + self.FileName = FileName + return True + else: + return False + + ## GetFileName + # + def GetFileName(self): + return self.FileName + + ## SetAbstract + # + # @param Abstract: Abstract + # + def SetAbstract(self, Abstract): + if not (Abstract == '' or Abstract is None): + self.Abstract = Abstract + return True + else: + return False + + ## GetAbstract + # + def GetAbstract(self): + return self.Abstract + + ## SetDescription + # + # @param Description: Description content + # + def SetDescription(self, Description): + if not (Description == '' or Description is None): + self.Description = Description + return True + else: + return False + + ## GetAbstract + # + def GetDescription(self): + return self.Description + + ## SetCopyright + # + # @param Copyright: Copyright content + # + def SetCopyright(self, Copyright): + if not (Copyright == '' or Copyright is None): + self.Copyright = Copyright + return True + else: + return False + + ## GetCopyright + # + def GetCopyright(self): + return self.Copyright + + ## SetCopyright + # + # @param License: License content + # + def SetLicense(self, License): + if not (License == '' or License is None): + self.License = License + return True + else: + return False + + ## GetLicense + # + def GetLicense(self): + return self.License diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfLibraryClassesObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfLibraryClassesObject.py new file mode 100755 index 00000000..b3433b9e --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfLibraryClassesObject.py @@ -0,0 +1,247 @@ +## @file +# This file is used to define class objects of INF file [LibraryClasses] section. +# It will consumed by InfParser. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +''' +InfLibraryClassesObject +''' + +from Logger import StringTable as ST +from Logger import ToolError +import Logger.Log as Logger +from Library import GlobalData + +from Library.Misc import Sdict +from Object.Parser.InfCommonObject import CurrentLine +from Library.ExpressionValidate import IsValidFeatureFlagExp +from Library.ParserValidate import IsValidLibName + +## GetArchModuleType +# +# Get Arch List and ModuleType List +# +def GetArchModuleType(KeyList): + __SupArchList = [] + __SupModuleList = [] + + for (ArchItem, ModuleItem) in KeyList: + # + # Validate Arch + # + if (ArchItem == '' or ArchItem is None): + ArchItem = 'COMMON' + + if (ModuleItem == '' or ModuleItem is None): + ModuleItem = 'COMMON' + + if ArchItem not in __SupArchList: + __SupArchList.append(ArchItem) + + List = ModuleItem.split('|') + for Entry in List: + if Entry not in __SupModuleList: + __SupModuleList.append(Entry) + + return (__SupArchList, __SupModuleList) + + +class InfLibraryClassItem(): + def __init__(self, LibName='', FeatureFlagExp='', HelpString=None): + self.LibName = LibName + self.FeatureFlagExp = FeatureFlagExp + self.HelpString = HelpString + self.CurrentLine = CurrentLine() + self.SupArchList = [] + self.SupModuleList = [] + self.FileGuid = '' + self.Version = '' + + def SetLibName(self, LibName): + self.LibName = LibName + def GetLibName(self): + return self.LibName + + def SetHelpString(self, HelpString): + self.HelpString = HelpString + def GetHelpString(self): + return self.HelpString + + def SetFeatureFlagExp(self, FeatureFlagExp): + self.FeatureFlagExp = FeatureFlagExp + def GetFeatureFlagExp(self): + return self.FeatureFlagExp + + def SetSupArchList(self, SupArchList): + self.SupArchList = SupArchList + def GetSupArchList(self): + return self.SupArchList + + def SetSupModuleList(self, SupModuleList): + self.SupModuleList = SupModuleList + def GetSupModuleList(self): + return self.SupModuleList + + # + # As Build related information + # + def SetFileGuid(self, FileGuid): + self.FileGuid = FileGuid + def GetFileGuid(self): + return self.FileGuid + + def SetVersion(self, Version): + self.Version = Version + def GetVersion(self): + return self.Version + +## INF LibraryClass Section +# +# +# +class InfLibraryClassObject(): + def __init__(self): + self.LibraryClasses = Sdict() + # + # Macro defined in this section should be only used in this section. + # + self.Macros = {} + + ##SetLibraryClasses + # + # + # @param HelpString: It can be a common comment or contain a recommend + # instance. + # + def SetLibraryClasses(self, LibContent, KeyList=None): + # + # Validate Arch + # + (__SupArchList, __SupModuleList) = GetArchModuleType(KeyList) + + for LibItem in LibContent: + LibItemObj = InfLibraryClassItem() + if not GlobalData.gIS_BINARY_INF: + HelpStringObj = LibItem[1] + LibItemObj.CurrentLine.SetFileName(LibItem[2][2]) + LibItemObj.CurrentLine.SetLineNo(LibItem[2][1]) + LibItemObj.CurrentLine.SetLineString(LibItem[2][0]) + LibItem = LibItem[0] + if HelpStringObj is not None: + LibItemObj.SetHelpString(HelpStringObj) + if len(LibItem) >= 1: + if LibItem[0].strip() != '': + if IsValidLibName(LibItem[0].strip()): + if LibItem[0].strip() != 'NULL': + LibItemObj.SetLibName(LibItem[0]) + else: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_DEFINE_LIB_NAME_INVALID, + File=GlobalData.gINF_MODULE_NAME, + Line=LibItemObj.CurrentLine.GetLineNo(), + ExtraData=LibItemObj.CurrentLine.GetLineString()) + else: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID % (LibItem[0]), + File=GlobalData.gINF_MODULE_NAME, + Line=LibItemObj.CurrentLine.GetLineNo(), + ExtraData=LibItemObj.CurrentLine.GetLineString()) + else: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_LIBRARY_SECTION_LIBNAME_MISSING, + File=GlobalData.gINF_MODULE_NAME, + Line=LibItemObj.CurrentLine.GetLineNo(), + ExtraData=LibItemObj.CurrentLine.GetLineString()) + if len(LibItem) == 2: + if LibItem[1].strip() == '': + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_MISSING, + File=GlobalData.gINF_MODULE_NAME, + Line=LibItemObj.CurrentLine.GetLineNo(), + ExtraData=LibItemObj.CurrentLine.GetLineString()) + # + # Validate FFE + # + FeatureFlagRtv = IsValidFeatureFlagExp(LibItem[1].strip()) + if not FeatureFlagRtv[0]: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_SYNTAX_INVLID % (FeatureFlagRtv[1]), + File=GlobalData.gINF_MODULE_NAME, + Line=LibItemObj.CurrentLine.GetLineNo(), + ExtraData=LibItemObj.CurrentLine.GetLineString()) + LibItemObj.SetFeatureFlagExp(LibItem[1].strip()) + + # + # Invalid strings + # + if len(LibItem) < 1 or len(LibItem) > 2: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_LIBRARY_SECTION_CONTENT_ERROR, + File=GlobalData.gINF_MODULE_NAME, + Line=LibItemObj.CurrentLine.GetLineNo(), + ExtraData=LibItemObj.CurrentLine.GetLineString()) + + LibItemObj.SetSupArchList(__SupArchList) + LibItemObj.SetSupModuleList(__SupModuleList) + + # + # Determine Library class duplicate. Follow below rule: + # + # A library class keyword must not be duplicated within a + # [LibraryClasses] section. Library class keywords may appear in + # multiple architectural and module type [LibraryClasses] sections. + # A library class keyword listed in an architectural or module type + # [LibraryClasses] section must not be listed in the common + # architectural or module type [LibraryClasses] section. + # + # NOTE: This check will not report error now. But keep code for future enhancement. + # +# for Item in self.LibraryClasses: +# if Item.GetLibName() == LibItemObj.GetLibName(): +# ItemSupArchList = Item.GetSupArchList() +# ItemSupModuleList = Item.GetSupModuleList() +# for ItemArch in ItemSupArchList: +# for ItemModule in ItemSupModuleList: +# for LibItemObjArch in __SupArchList: +# for LibItemObjModule in __SupModuleList: +# if ItemArch == LibItemObjArch and LibItemObjModule == ItemModule: +# # +# # ERR_INF_PARSER_ITEM_DUPLICATE +# # +# pass +# if (ItemArch.upper() == 'COMMON' or LibItemObjArch.upper() == 'COMMON') \ +# and LibItemObjModule == ItemModule: +# # +# # ERR_INF_PARSER_ITEM_DUPLICATE_COMMON +# # +# pass + else: + # + # Assume the file GUID is well formatted. + # + LibItemObj.SetFileGuid(LibItem[0]) + LibItemObj.SetVersion(LibItem[1]) + LibItemObj.SetSupArchList(__SupArchList) + + if (LibItemObj) in self.LibraryClasses: + LibraryList = self.LibraryClasses[LibItemObj] + LibraryList.append(LibItemObj) + self.LibraryClasses[LibItemObj] = LibraryList + else: + LibraryList = [] + LibraryList.append(LibItemObj) + self.LibraryClasses[LibItemObj] = LibraryList + + return True + + def GetLibraryClasses(self): + return self.LibraryClasses diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfMisc.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfMisc.py new file mode 100755 index 00000000..1354ab45 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfMisc.py @@ -0,0 +1,142 @@ +## @file +# This file is used to define class objects of INF file miscellaneous. +# Include BootMode/HOB/Event and others. It will consumed by InfParser. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +''' +InfMisc +''' + +import Logger.Log as Logger +from Logger import ToolError + +from Library import DataType as DT +from Object.Parser.InfCommonObject import InfSectionCommonDef +from Library.Misc import Sdict + +## +# BootModeObject +# +class InfBootModeObject(): + def __init__(self): + self.SupportedBootModes = '' + self.HelpString = '' + self.Usage = '' + + def SetSupportedBootModes(self, SupportedBootModes): + self.SupportedBootModes = SupportedBootModes + def GetSupportedBootModes(self): + return self.SupportedBootModes + + def SetHelpString(self, HelpString): + self.HelpString = HelpString + def GetHelpString(self): + return self.HelpString + + def SetUsage(self, Usage): + self.Usage = Usage + def GetUsage(self): + return self.Usage +## +# EventObject +# +class InfEventObject(): + def __init__(self): + self.EventType = '' + self.HelpString = '' + self.Usage = '' + + def SetEventType(self, EventType): + self.EventType = EventType + + def GetEventType(self): + return self.EventType + + def SetHelpString(self, HelpString): + self.HelpString = HelpString + def GetHelpString(self): + return self.HelpString + + def SetUsage(self, Usage): + self.Usage = Usage + def GetUsage(self): + return self.Usage +## +# HobObject +# +class InfHobObject(): + def __init__(self): + self.HobType = '' + self.Usage = '' + self.SupArchList = [] + self.HelpString = '' + + def SetHobType(self, HobType): + self.HobType = HobType + + def GetHobType(self): + return self.HobType + + def SetUsage(self, Usage): + self.Usage = Usage + def GetUsage(self): + return self.Usage + + def SetSupArchList(self, ArchList): + self.SupArchList = ArchList + def GetSupArchList(self): + return self.SupArchList + + def SetHelpString(self, HelpString): + self.HelpString = HelpString + def GetHelpString(self): + return self.HelpString + +## +# InfSpecialCommentObject +# +class InfSpecialCommentObject(InfSectionCommonDef): + def __init__(self): + self.SpecialComments = Sdict() + InfSectionCommonDef.__init__(self) + + def SetSpecialComments(self, SepcialSectionList = None, Type = ''): + if Type == DT.TYPE_HOB_SECTION or \ + Type == DT.TYPE_EVENT_SECTION or \ + Type == DT.TYPE_BOOTMODE_SECTION: + for Item in SepcialSectionList: + if Type in self.SpecialComments: + ObjList = self.SpecialComments[Type] + ObjList.append(Item) + self.SpecialComments[Type] = ObjList + else: + ObjList = [] + ObjList.append(Item) + self.SpecialComments[Type] = ObjList + + return True + + def GetSpecialComments(self): + return self.SpecialComments + + + +## ErrorInInf +# +# An encapsulate of Error for INF parser. +# +def ErrorInInf(Message=None, ErrorCode=None, LineInfo=None, RaiseError=True): + if ErrorCode is None: + ErrorCode = ToolError.FORMAT_INVALID + if LineInfo is None: + LineInfo = ['', -1, ''] + Logger.Error("InfParser", + ErrorCode, + Message=Message, + File=LineInfo[0], + Line=LineInfo[1], + ExtraData=LineInfo[2], + RaiseError=RaiseError) diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfPackagesObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfPackagesObject.py new file mode 100755 index 00000000..1ad04758 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfPackagesObject.py @@ -0,0 +1,181 @@ +## @file +# This file is used to define class objects of INF file [Packages] section. +# It will consumed by InfParser. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +''' +InfPackageObject +''' + +from Logger import StringTable as ST +from Logger import ToolError +import Logger.Log as Logger +from Library import GlobalData + +from Library.Misc import Sdict +from Library.ParserValidate import IsValidPath +from Library.ExpressionValidate import IsValidFeatureFlagExp + +class InfPackageItem(): + def __init__(self, + PackageName = '', + FeatureFlagExp = '', + HelpString = ''): + self.PackageName = PackageName + self.FeatureFlagExp = FeatureFlagExp + self.HelpString = HelpString + self.SupArchList = [] + + def SetPackageName(self, PackageName): + self.PackageName = PackageName + def GetPackageName(self): + return self.PackageName + + def SetFeatureFlagExp(self, FeatureFlagExp): + self.FeatureFlagExp = FeatureFlagExp + def GetFeatureFlagExp(self): + return self.FeatureFlagExp + + def SetHelpString(self, HelpString): + self.HelpString = HelpString + def GetHelpString(self): + return self.HelpString + + def SetSupArchList(self, SupArchList): + self.SupArchList = SupArchList + def GetSupArchList(self): + return self.SupArchList + + +## INF package section +# +# +# +class InfPackageObject(): + def __init__(self): + self.Packages = Sdict() + # + # Macro defined in this section should be only used in this section. + # + self.Macros = {} + + def SetPackages(self, PackageData, Arch = None): + IsValidFileFlag = False + SupArchList = [] + for ArchItem in Arch: + # + # Validate Arch + # + if (ArchItem == '' or ArchItem is None): + ArchItem = 'COMMON' + SupArchList.append(ArchItem) + + for PackageItem in PackageData: + PackageItemObj = InfPackageItem() + HelpStringObj = PackageItem[1] + CurrentLineOfPackItem = PackageItem[2] + PackageItem = PackageItem[0] + if HelpStringObj is not None: + HelpString = HelpStringObj.HeaderComments + HelpStringObj.TailComments + PackageItemObj.SetHelpString(HelpString) + if len(PackageItem) >= 1: + # + # Validate file exist/format. + # + if IsValidPath(PackageItem[0], ''): + IsValidFileFlag = True + elif IsValidPath(PackageItem[0], GlobalData.gINF_MODULE_DIR): + IsValidFileFlag = True + elif IsValidPath(PackageItem[0], GlobalData.gWORKSPACE): + IsValidFileFlag = True + else: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID%(PackageItem[0]), + File=CurrentLineOfPackItem[2], + Line=CurrentLineOfPackItem[1], + ExtraData=CurrentLineOfPackItem[0]) + return False + if IsValidFileFlag: + PackageItemObj.SetPackageName(PackageItem[0]) + if len(PackageItem) == 2: + # + # Validate Feature Flag Express + # + if PackageItem[1].strip() == '': + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_MISSING, + File=CurrentLineOfPackItem[2], + Line=CurrentLineOfPackItem[1], + ExtraData=CurrentLineOfPackItem[0]) + # + # Validate FFE + # + FeatureFlagRtv = IsValidFeatureFlagExp(PackageItem[1].strip()) + if not FeatureFlagRtv[0]: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_SYNTAX_INVLID%(FeatureFlagRtv[1]), + File=CurrentLineOfPackItem[2], + Line=CurrentLineOfPackItem[1], + ExtraData=CurrentLineOfPackItem[0]) + + PackageItemObj.SetFeatureFlagExp(PackageItem[1].strip()) + + if len(PackageItem) > 2: + # + # Invalid format of Package statement + # + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_PACKAGE_SECTION_CONTENT_ERROR, + File=CurrentLineOfPackItem[2], + Line=CurrentLineOfPackItem[1], + ExtraData=CurrentLineOfPackItem[0]) + PackageItemObj.SetSupArchList(SupArchList) + + # + # Determine package file name duplicate. Follow below rule: + # + # A package filename must not be duplicated within a [Packages] + # section. Package filenames may appear in multiple architectural + # [Packages] sections. A package filename listed in an + # architectural [Packages] section must not be listed in the common + # architectural [Packages] section. + # + # NOTE: This check will not report error now. + # + for Item in self.Packages: + if Item.GetPackageName() == PackageItemObj.GetPackageName(): + ItemSupArchList = Item.GetSupArchList() + for ItemArch in ItemSupArchList: + for PackageItemObjArch in SupArchList: + if ItemArch == PackageItemObjArch: + # + # ST.ERR_INF_PARSER_ITEM_DUPLICATE + # + pass + if ItemArch.upper() == 'COMMON' or PackageItemObjArch.upper() == 'COMMON': + # + # ST.ERR_INF_PARSER_ITEM_DUPLICATE_COMMON + # + pass + + if (PackageItemObj) in self.Packages: + PackageList = self.Packages[PackageItemObj] + PackageList.append(PackageItemObj) + self.Packages[PackageItemObj] = PackageList + else: + PackageList = [] + PackageList.append(PackageItemObj) + self.Packages[PackageItemObj] = PackageList + + return True + + def GetPackages(self, Arch = None): + if Arch is None: + return self.Packages diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfPcdObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfPcdObject.py new file mode 100755 index 00000000..ff6eb061 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfPcdObject.py @@ -0,0 +1,669 @@ +## @file +# This file is used to define class objects of INF file [Pcds] section. +# It will consumed by InfParser. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +''' +InfPcdObject +''' +import os +import re + +from Logger import StringTable as ST +from Logger import ToolError +import Logger.Log as Logger +from Library import GlobalData +from Library import DataType as DT + +from Library.Misc import Sdict +from Library.Misc import GetHelpStringByRemoveHashKey +from Library.ParserValidate import IsValidPcdType +from Library.ParserValidate import IsValidCVariableName +from Library.ParserValidate import IsValidPcdValue +from Library.ParserValidate import IsValidArch +from Library.CommentParsing import ParseComment +from Library.StringUtils import GetSplitValueList +from Library.StringUtils import IsHexDigitUINT32 +from Library.ExpressionValidate import IsValidFeatureFlagExp +from Parser.InfAsBuiltProcess import GetPackageListInfo +from Parser.DecParser import Dec + +from Object.Parser.InfPackagesObject import InfPackageItem + +def ValidateArch(ArchItem, PcdTypeItem1, LineNo, SupArchDict, SupArchList): + # + # Validate Arch + # + if (ArchItem == '' or ArchItem is None): + ArchItem = 'COMMON' + + if PcdTypeItem1.upper != DT.TAB_INF_FEATURE_PCD.upper(): + ArchList = GetSplitValueList(ArchItem, ' ') + for ArchItemNew in ArchList: + if not IsValidArch(ArchItemNew): + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID % (ArchItemNew), + File=GlobalData.gINF_MODULE_NAME, + Line=LineNo, + ExtraData=ArchItemNew) + SupArchDict[PcdTypeItem1] = ArchList + else: + SupArchList.append(ArchItem) + + return SupArchList, SupArchDict + +def ParsePcdComment(CommentList, PcdTypeItem, PcdItemObj): + CommentInsList = [] + PreUsage = None + PreHelpText = '' + BlockFlag = -1 + FFEHelpText = '' + CommentItemHelpText = '' + Count = 0 + for CommentItem in CommentList: + Count = Count + 1 + CommentItemUsage, CommentType, CommentString, CommentItemHelpText = ParseComment(CommentItem, + DT.ALL_USAGE_TOKENS, + {}, + [], + False) + if CommentType and CommentString: + pass + + if PcdTypeItem == 'FeaturePcd': + CommentItemUsage = DT.USAGE_ITEM_CONSUMES + if CommentItemHelpText is None: + CommentItemHelpText = '' + + if Count == 1: + FFEHelpText = CommentItemHelpText + else: + FFEHelpText = FFEHelpText + DT.END_OF_LINE + CommentItemHelpText + + if Count == len(CommentList): + CommentItemHelpText = FFEHelpText + BlockFlag = 4 + else: + continue + + if CommentItemHelpText is None: + CommentItemHelpText = '' + if Count == len(CommentList) and CommentItemUsage == DT.ITEM_UNDEFINED: + CommentItemHelpText = DT.END_OF_LINE + + if Count == len(CommentList) and (BlockFlag == 1 or BlockFlag == 2): + if CommentItemUsage == DT.ITEM_UNDEFINED: + BlockFlag = 4 + else: + BlockFlag = 3 + elif BlockFlag == -1 and Count == len(CommentList): + BlockFlag = 4 + + if BlockFlag == -1 or BlockFlag == 1 or BlockFlag == 2: + if CommentItemUsage == DT.ITEM_UNDEFINED: + if BlockFlag == -1: + BlockFlag = 1 + elif BlockFlag == 1: + BlockFlag = 2 + else: + if BlockFlag == 1 or BlockFlag == 2: + BlockFlag = 3 + elif BlockFlag == -1: + BlockFlag = 4 + # + # Combine two comment line if they are generic comment + # + if CommentItemUsage == PreUsage == DT.ITEM_UNDEFINED: + CommentItemHelpText = PreHelpText + DT.END_OF_LINE + CommentItemHelpText + + PreHelpText = CommentItemHelpText + + if BlockFlag == 4: + CommentItemIns = InfPcdItemCommentContent() + CommentItemIns.SetUsageItem(CommentItemUsage) + CommentItemIns.SetHelpStringItem(CommentItemHelpText) + CommentInsList.append(CommentItemIns) + + BlockFlag = -1 + PreUsage = None + PreHelpText = '' + + elif BlockFlag == 3: + # + # Add previous help string + # + CommentItemIns = InfPcdItemCommentContent() + CommentItemIns.SetUsageItem(DT.ITEM_UNDEFINED) + if PreHelpText == '' or PreHelpText.endswith(DT.END_OF_LINE): + PreHelpText += DT.END_OF_LINE + CommentItemIns.SetHelpStringItem(PreHelpText) + CommentInsList.append(CommentItemIns) + # + # Add Current help string + # + CommentItemIns = InfPcdItemCommentContent() + CommentItemIns.SetUsageItem(CommentItemUsage) + CommentItemIns.SetHelpStringItem(CommentItemHelpText) + CommentInsList.append(CommentItemIns) + + BlockFlag = -1 + PreUsage = None + PreHelpText = '' + + else: + PreUsage = CommentItemUsage + PreHelpText = CommentItemHelpText + + PcdItemObj.SetHelpStringList(CommentInsList) + + return PcdItemObj + +class InfPcdItemCommentContent(): + def __init__(self): + # + # ## SOMETIMES_CONSUMES ## HelpString + # + self.UsageItem = '' + # + # Help String + # + self.HelpStringItem = '' + + def SetUsageItem(self, UsageItem): + self.UsageItem = UsageItem + def GetUsageItem(self): + return self.UsageItem + + def SetHelpStringItem(self, HelpStringItem): + self.HelpStringItem = HelpStringItem + def GetHelpStringItem(self): + return self.HelpStringItem + +## InfPcdItem +# +# This class defined Pcd item used in Module files +# +# @param CName: Input value for CName, default is '' +# @param Token: Input value for Token, default is '' +# @param TokenSpaceGuidCName: Input value for TokenSpaceGuidCName, default +# is '' +# @param DatumType: Input value for DatumType, default is '' +# @param MaxDatumSize: Input value for MaxDatumSize, default is '' +# @param DefaultValue: Input value for DefaultValue, default is '' +# @param ItemType: Input value for ItemType, default is '' +# @param ValidUsage: Input value for ValidUsage, default is [] +# @param SkuInfoList: Input value for SkuInfoList, default is {} +# @param SupModuleList: Input value for SupModuleList, default is [] +# +class InfPcdItem(): + def __init__(self): + self.CName = '' + self.Token = '' + self.TokenSpaceGuidCName = '' + self.TokenSpaceGuidValue = '' + self.DatumType = '' + self.MaxDatumSize = '' + self.DefaultValue = '' + self.Offset = '' + self.ValidUsage = '' + self.ItemType = '' + self.SupModuleList = [] + self.HelpStringList = [] + self.FeatureFlagExp = '' + self.SupArchList = [] + self.PcdErrorsList = [] + + def SetCName(self, CName): + self.CName = CName + def GetCName(self): + return self.CName + + def SetToken(self, Token): + self.Token = Token + def GetToken(self): + return self.Token + + def SetTokenSpaceGuidCName(self, TokenSpaceGuidCName): + self.TokenSpaceGuidCName = TokenSpaceGuidCName + def GetTokenSpaceGuidCName(self): + return self.TokenSpaceGuidCName + + def SetTokenSpaceGuidValue(self, TokenSpaceGuidValue): + self.TokenSpaceGuidValue = TokenSpaceGuidValue + def GetTokenSpaceGuidValue(self): + return self.TokenSpaceGuidValue + + def SetDatumType(self, DatumType): + self.DatumType = DatumType + def GetDatumType(self): + return self.DatumType + + def SetMaxDatumSize(self, MaxDatumSize): + self.MaxDatumSize = MaxDatumSize + def GetMaxDatumSize(self): + return self.MaxDatumSize + + def SetDefaultValue(self, DefaultValue): + self.DefaultValue = DefaultValue + def GetDefaultValue(self): + return self.DefaultValue + + def SetPcdErrorsList(self, PcdErrorsList): + self.PcdErrorsList = PcdErrorsList + def GetPcdErrorsList(self): + return self.PcdErrorsList + + def SetItemType(self, ItemType): + self.ItemType = ItemType + def GetItemType(self): + return self.ItemType + + def SetSupModuleList(self, SupModuleList): + self.SupModuleList = SupModuleList + def GetSupModuleList(self): + return self.SupModuleList + + def SetHelpStringList(self, HelpStringList): + self.HelpStringList = HelpStringList + def GetHelpStringList(self): + return self.HelpStringList + + def SetFeatureFlagExp(self, FeatureFlagExp): + self.FeatureFlagExp = FeatureFlagExp + def GetFeatureFlagExp(self): + return self.FeatureFlagExp + + def SetSupportArchList(self, ArchList): + self.SupArchList = ArchList + def GetSupportArchList(self): + return self.SupArchList + + def SetOffset(self, Offset): + self.Offset = Offset + def GetOffset(self): + return self.Offset + + def SetValidUsage(self, ValidUsage): + self.ValidUsage = ValidUsage + + def GetValidUsage(self): + return self.ValidUsage + +## +# +# +# +class InfPcdObject(): + def __init__(self, FileName): + self.Pcds = Sdict() + self.FileName = FileName + + def SetPcds(self, PcdContent, KeysList=None, PackageInfo=None): + + if GlobalData.gIS_BINARY_INF: + self.SetAsBuildPcds(PcdContent, KeysList, PackageInfo) + return True + + # + # Validate Arch + # + SupArchList = [] + SupArchDict = {} + PcdTypeItem = '' + for (PcdTypeItem1, ArchItem, LineNo) in KeysList: + SupArchList, SupArchDict = ValidateArch(ArchItem, PcdTypeItem1, LineNo, SupArchDict, SupArchList) + + # + # Validate PcdType + # + if (PcdTypeItem1 == '' or PcdTypeItem1 is None): + return False + else: + if not IsValidPcdType(PcdTypeItem1): + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_PCD_SECTION_TYPE_ERROR % (DT.PCD_USAGE_TYPE_LIST_OF_MODULE), + File=GlobalData.gINF_MODULE_NAME, + Line=LineNo, + ExtraData=PcdTypeItem1) + return False + + PcdTypeItem = PcdTypeItem1 + + for PcdItem in PcdContent: + PcdItemObj = InfPcdItem() + CommentList = PcdItem[1] + CurrentLineOfPcdItem = PcdItem[2] + PcdItem = PcdItem[0] + + if CommentList is not None and len(CommentList) != 0: + PcdItemObj = ParsePcdComment(CommentList, PcdTypeItem, PcdItemObj) + else: + CommentItemIns = InfPcdItemCommentContent() + CommentItemIns.SetUsageItem(DT.ITEM_UNDEFINED) + PcdItemObj.SetHelpStringList([CommentItemIns]) + + if len(PcdItem) >= 1 and len(PcdItem) <= 3: + PcdItemObj = SetPcdName(PcdItem, CurrentLineOfPcdItem, PcdItemObj) + + if len(PcdItem) >= 2 and len(PcdItem) <= 3: + # + # Contain PcdName and Value, validate value. + # + if IsValidPcdValue(PcdItem[1]) or PcdItem[1].strip() == "": + PcdItemObj.SetDefaultValue(PcdItem[1]) + else: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_PCD_VALUE_INVALID, + File=CurrentLineOfPcdItem[2], + Line=CurrentLineOfPcdItem[1], + ExtraData=PcdItem[1]) + + if len(PcdItem) == 3: + # + # Contain PcdName, value, and FeatureFlag express + # + # + # Validate Feature Flag Express + # + if PcdItem[2].strip() == '': + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_MISSING, + File=CurrentLineOfPcdItem[2], + Line=CurrentLineOfPcdItem[1], + ExtraData=CurrentLineOfPcdItem[0]) + # + # Validate FFE + # + FeatureFlagRtv = IsValidFeatureFlagExp(PcdItem[2].strip()) + if not FeatureFlagRtv[0]: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_SYNTAX_INVLID % (FeatureFlagRtv[1]), + File=CurrentLineOfPcdItem[2], + Line=CurrentLineOfPcdItem[1], + ExtraData=CurrentLineOfPcdItem[0]) + PcdItemObj.SetFeatureFlagExp(PcdItem[2]) + + if len(PcdItem) < 1 or len(PcdItem) > 3: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_PCD_SECTION_CONTENT_ERROR, + File=CurrentLineOfPcdItem[2], + Line=CurrentLineOfPcdItem[1], + ExtraData=CurrentLineOfPcdItem[0]) + return False + + if PcdTypeItem.upper != DT.TAB_INF_FEATURE_PCD.upper(): + PcdItemObj.SetSupportArchList(SupArchDict[PcdTypeItem]) + else: + PcdItemObj.SetSupportArchList(SupArchList) + + if (PcdTypeItem, PcdItemObj) in self.Pcds: + PcdsList = self.Pcds[PcdTypeItem, PcdItemObj] + PcdsList.append(PcdItemObj) + self.Pcds[PcdTypeItem, PcdItemObj] = PcdsList + else: + PcdsList = [] + PcdsList.append(PcdItemObj) + self.Pcds[PcdTypeItem, PcdItemObj] = PcdsList + + return True + + def SetAsBuildPcds(self, PcdContent, KeysList=None, PackageInfo=None): + for PcdItem in PcdContent: + PcdItemObj = InfPcdItem() + CommentList = PcdItem[1] + CurrentLineOfPcdItem = PcdItem[2] + PcdItem = PcdItem[0] + CommentString = '' + + for CommentLine in CommentList: + CommentString = GetHelpStringByRemoveHashKey(CommentLine) + CommentItemIns = InfPcdItemCommentContent() + CommentItemIns.SetHelpStringItem(CommentString) + CommentItemIns.SetUsageItem(CommentString) + PcdItemObj.SetHelpStringList(PcdItemObj.GetHelpStringList() + [CommentItemIns]) + if PcdItemObj.GetValidUsage(): + PcdItemObj.SetValidUsage(PcdItemObj.GetValidUsage() + DT.TAB_VALUE_SPLIT + CommentString) + else: + PcdItemObj.SetValidUsage(CommentString) + + PcdItemObj.SetItemType(KeysList[0][0]) + # + # Set PcdTokenSpaceCName and CName + # + PcdItemObj = SetPcdName(PcdItem, CurrentLineOfPcdItem, PcdItemObj) + # + # Set Value/DatumType/OffSet/Token + # + PcdItemObj = SetValueDatumTypeMaxSizeToken(PcdItem, + CurrentLineOfPcdItem, + PcdItemObj, + KeysList[0][1], + PackageInfo) + + PcdTypeItem = KeysList[0][0] + if (PcdTypeItem, PcdItemObj) in self.Pcds: + PcdsList = self.Pcds[PcdTypeItem, PcdItemObj] + PcdsList.append(PcdItemObj) + self.Pcds[PcdTypeItem, PcdItemObj] = PcdsList + else: + PcdsList = [] + PcdsList.append(PcdItemObj) + self.Pcds[PcdTypeItem, PcdItemObj] = PcdsList + + def GetPcds(self): + return self.Pcds + +def ParserPcdInfoInDec(String): + ValueList = GetSplitValueList(String, DT.TAB_VALUE_SPLIT, 3) + + # + # DatumType, Token + # + return ValueList[2], ValueList[3] + +def SetValueDatumTypeMaxSizeToken(PcdItem, CurrentLineOfPcdItem, PcdItemObj, Arch, PackageInfo=None): + # + # Package information not been generated currently, we need to parser INF file to get information. + # + if not PackageInfo: + PackageInfo = [] + InfFileName = CurrentLineOfPcdItem[2] + PackageInfoList = GetPackageListInfo(InfFileName, GlobalData.gWORKSPACE, -1) + for PackageInfoListItem in PackageInfoList: + PackageInfoIns = InfPackageItem() + PackageInfoIns.SetPackageName(PackageInfoListItem) + PackageInfo.append(PackageInfoIns) + + PcdInfoInDecHasFound = False + for PackageItem in PackageInfo: + if PcdInfoInDecHasFound: + break + PackageName = PackageItem.PackageName + # + # Open DEC file to get information + # + FullFileName = os.path.normpath(os.path.realpath(os.path.join(GlobalData.gWORKSPACE, PackageName))) + + DecParser = None + if FullFileName not in GlobalData.gPackageDict: + DecParser = Dec(FullFileName) + GlobalData.gPackageDict[FullFileName] = DecParser + else: + DecParser = GlobalData.gPackageDict[FullFileName] + + # + # Find PCD information. + # + DecPcdsDict = DecParser.GetPcdSectionObject().ValueDict + for Key in DecPcdsDict.keys(): + if (Key[0] == 'PCDSDYNAMICEX' and PcdItemObj.GetItemType() == 'PcdEx') and \ + (Key[1] == 'COMMON' or Key[1] == Arch): + for PcdInDec in DecPcdsDict[Key]: + if PcdInDec.TokenCName == PcdItemObj.CName and \ + PcdInDec.TokenSpaceGuidCName == PcdItemObj.TokenSpaceGuidCName: + PcdItemObj.SetToken(PcdInDec.TokenValue) + PcdItemObj.SetDatumType(PcdInDec.DatumType) + PcdItemObj.SetSupportArchList([Arch]) + PcdItemObj.SetDefaultValue(PcdInDec.DefaultValue) + + if (Key[0] == 'PCDSPATCHABLEINMODULE' and PcdItemObj.GetItemType() == 'PatchPcd') and \ + (Key[1] == 'COMMON' or Key[1] == Arch): + for PcdInDec in DecPcdsDict[Key]: + if PcdInDec.TokenCName == PcdItemObj.CName and \ + PcdInDec.TokenSpaceGuidCName == PcdItemObj.TokenSpaceGuidCName: + PcdItemObj.SetToken(PcdInDec.TokenValue) + PcdItemObj.SetDatumType(PcdInDec.DatumType) + PcdItemObj.SetSupportArchList([Arch]) + + if PcdItemObj.GetDatumType() == 'VOID*': + if len(PcdItem) > 1: + PcdItemObj.SetMaxDatumSize('%s' % (len(GetSplitValueList(PcdItem[1], DT.TAB_COMMA_SPLIT)))) + + DecGuidsDict = DecParser.GetGuidSectionObject().ValueDict + for Key in DecGuidsDict.keys(): + if Key == 'COMMON' or Key == Arch: + for GuidInDec in DecGuidsDict[Key]: + if GuidInDec.GuidCName == PcdItemObj.TokenSpaceGuidCName: + PcdItemObj.SetTokenSpaceGuidValue(GuidInDec.GuidString) + + if PcdItemObj.GetItemType().upper() == DT.TAB_INF_PATCH_PCD.upper(): + # + # Validate Value. + # + # convert the value from a decimal 0 to a formatted hex value. + if PcdItem[1] == "0": + DatumType = PcdItemObj.GetDatumType() + if DatumType == "UINT8": + PcdItem[1] = "0x00" + if DatumType == "UINT16": + PcdItem[1] = "0x0000" + if DatumType == "UINT32": + PcdItem[1] = "0x00000000" + if DatumType == "UINT64": + PcdItem[1] = "0x0000000000000000" + + if ValidatePcdValueOnDatumType(PcdItem[1], PcdItemObj.GetDatumType()): + PcdItemObj.SetDefaultValue(PcdItem[1]) + else: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_ASBUILD_PCD_VALUE_INVALID % ("\"" + PcdItem[1] + "\"", "\"" + + PcdItemObj.GetDatumType() + "\""), + File=CurrentLineOfPcdItem[2], + Line=CurrentLineOfPcdItem[1], + ExtraData=CurrentLineOfPcdItem[0]) + # + # validate offset + # + if PcdItemObj.GetItemType().upper() == DT.TAB_INF_PATCH_PCD.upper(): + if not IsHexDigitUINT32(PcdItem[2]): + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_ASBUILD_PCD_OFFSET_FORMAT_INVALID % ("\"" + PcdItem[2] + "\""), + File=CurrentLineOfPcdItem[2], + Line=CurrentLineOfPcdItem[1], + ExtraData=CurrentLineOfPcdItem[0]) + PcdItemObj.SetOffset(PcdItem[2]) + + if PcdItemObj.GetToken() == '' or PcdItemObj.GetDatumType() == '': + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_ASBUILD_PCD_DECLARITION_MISS % ("\"" + PcdItem[0] + "\""), + File=CurrentLineOfPcdItem[2], + Line=CurrentLineOfPcdItem[1], + ExtraData=CurrentLineOfPcdItem[0]) + + return PcdItemObj + +def ValidatePcdValueOnDatumType(Value, Type): + + Value = Value.strip() + # + # Boolean type only allow 0x00 or 0x01 as value per INF spec + # + if Type == 'BOOLEAN': + if not (Value == '0x00' or Value == '0x01'): + return False + elif Type == 'VOID*': + if not Value.startswith("{"): + return False + if not Value.endswith("}"): + return False + # + # Strip "{" at head and "}" at tail. + # + Value = Value[1:-1] + ValueList = GetSplitValueList(Value, DT.TAB_COMMA_SPLIT) + + ReIsValidHexByte = re.compile("^0x[0-9a-f]{1,2}$", re.IGNORECASE) + for ValueItem in ValueList: + if not ReIsValidHexByte.match(ValueItem): + return False + + elif Type == 'UINT8' or Type == 'UINT16' or Type == 'UINT32' or Type == 'UINT64': + + ReIsValidUint8z = re.compile('^0[x|X][a-fA-F0-9]{2}$') + ReIsValidUint16z = re.compile('^0[x|X][a-fA-F0-9]{4}$') + ReIsValidUint32z = re.compile('^0[x|X][a-fA-F0-9]{8}$') + ReIsValidUint64z = re.compile('^0[x|X][a-fA-F0-9]{16}$') + + if not ReIsValidUint8z.match(Value) and Type == 'UINT8': + return False + elif not ReIsValidUint16z.match(Value) and Type == 'UINT16': + return False + elif not ReIsValidUint32z.match(Value) and Type == 'UINT32': + return False + elif not ReIsValidUint64z.match(Value) and Type == 'UINT64': + return False + else: + # + # Since we assume the DEC file always correct, should never go to here. + # + pass + + return True + +def SetPcdName(PcdItem, CurrentLineOfPcdItem, PcdItemObj): + # + # Only PCD Name specified + # ::= "." + # + PcdId = GetSplitValueList(PcdItem[0], DT.TAB_SPLIT) + if len(PcdId) != 2: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_PCD_NAME_FORMAT_ERROR, + File=CurrentLineOfPcdItem[2], + Line=CurrentLineOfPcdItem[1], + ExtraData=CurrentLineOfPcdItem[0]) + else: + # + # Validate PcdTokenSpaceGuidCName + # + if not IsValidCVariableName(PcdId[0]): + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_PCD_CVAR_GUID, + File=CurrentLineOfPcdItem[2], + Line=CurrentLineOfPcdItem[1], + ExtraData=PcdId[0]) + if not IsValidCVariableName(PcdId[1]): + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_PCD_CVAR_PCDCNAME, + File=CurrentLineOfPcdItem[2], + Line=CurrentLineOfPcdItem[1], + ExtraData=PcdId[1]) + PcdItemObj.SetTokenSpaceGuidCName(PcdId[0]) + PcdItemObj.SetCName(PcdId[1]) + + return PcdItemObj diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfPpiObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfPpiObject.py new file mode 100755 index 00000000..9c852f50 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfPpiObject.py @@ -0,0 +1,337 @@ +## @file +# This file is used to define class objects of INF file [Ppis] section. +# It will consumed by InfParser. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +''' +InfPpiObject +''' + +from Library.ParserValidate import IsValidCVariableName +from Library.CommentParsing import ParseComment +from Library.ExpressionValidate import IsValidFeatureFlagExp + +from Library.Misc import Sdict +from Library import DataType as DT +import Logger.Log as Logger +from Logger import ToolError +from Logger import StringTable as ST + +def ParsePpiComment(CommentsList, InfPpiItemObj): + PreNotify = None + PreUsage = None + PreHelpText = '' + BlockFlag = -1 + CommentInsList = [] + Count = 0 + for CommentItem in CommentsList: + Count = Count + 1 + CommentItemUsage, \ + CommentItemNotify, \ + CommentItemString, \ + CommentItemHelpText = \ + ParseComment(CommentItem, + DT.ALL_USAGE_TOKENS, + DT.PPI_NOTIFY_TOKENS, + ['PPI'], + False) + + # + # To avoid PyLint error + # + if CommentItemString: + pass + + if CommentItemHelpText is None: + CommentItemHelpText = '' + if Count == len(CommentsList) and CommentItemUsage == CommentItemNotify == DT.ITEM_UNDEFINED: + CommentItemHelpText = DT.END_OF_LINE + # + # For the Last comment Item, set BlockFlag. + # + if Count == len(CommentsList): + if BlockFlag == 1 or BlockFlag == 2: + if CommentItemUsage == CommentItemNotify == DT.ITEM_UNDEFINED: + BlockFlag = 4 + else: + BlockFlag = 3 + elif BlockFlag == -1: + BlockFlag = 4 + + # + # Comment USAGE and NOTIFY information are "UNDEFINED" + # + if BlockFlag == -1 or BlockFlag == 1 or BlockFlag == 2: + if CommentItemUsage == CommentItemNotify == DT.ITEM_UNDEFINED: + if BlockFlag == -1: + BlockFlag = 1 + elif BlockFlag == 1: + BlockFlag = 2 + else: + if BlockFlag == 1 or BlockFlag == 2: + BlockFlag = 3 + # + # An item have Usage or Notify information and the first time get this information + # + elif BlockFlag == -1: + BlockFlag = 4 + + # + # Combine two comment line if they are generic comment + # + if CommentItemUsage == CommentItemNotify == PreUsage == PreNotify == DT.ITEM_UNDEFINED: + CommentItemHelpText = PreHelpText + DT.END_OF_LINE + CommentItemHelpText + # + # Store this information for next line may still need combine operation. + # + PreHelpText = CommentItemHelpText + + if BlockFlag == 4: + CommentItemIns = InfPpiItemCommentContent() + CommentItemIns.SetUsage(CommentItemUsage) + CommentItemIns.SetNotify(CommentItemNotify) + CommentItemIns.SetHelpStringItem(CommentItemHelpText) + CommentInsList.append(CommentItemIns) + + BlockFlag = -1 + PreUsage = None + PreNotify = None + PreHelpText = '' + + elif BlockFlag == 3: + # + # Add previous help string + # + CommentItemIns = InfPpiItemCommentContent() + CommentItemIns.SetUsage(DT.ITEM_UNDEFINED) + CommentItemIns.SetNotify(DT.ITEM_UNDEFINED) + if PreHelpText == '' or PreHelpText.endswith(DT.END_OF_LINE): + PreHelpText += DT.END_OF_LINE + CommentItemIns.SetHelpStringItem(PreHelpText) + CommentInsList.append(CommentItemIns) + # + # Add Current help string + # + CommentItemIns = InfPpiItemCommentContent() + CommentItemIns.SetUsage(CommentItemUsage) + CommentItemIns.SetNotify(CommentItemNotify) + CommentItemIns.SetHelpStringItem(CommentItemHelpText) + CommentInsList.append(CommentItemIns) + + BlockFlag = -1 + PreUsage = None + PreNotify = None + PreHelpText = '' + else: + PreUsage = CommentItemUsage + PreNotify = CommentItemNotify + PreHelpText = CommentItemHelpText + + InfPpiItemObj.SetCommentList(CommentInsList) + + return InfPpiItemObj + +class InfPpiItemCommentContent(): + def __init__(self): + # + # ## SOMETIMES_CONSUMES ## HelpString + # + self.UsageItem = '' + # + # Help String + # + self.HelpStringItem = '' + self.Notify = '' + self.CommentList = [] + + def SetUsage(self, UsageItem): + self.UsageItem = UsageItem + def GetUsage(self): + return self.UsageItem + + def SetNotify(self, Notify): + if Notify != DT.ITEM_UNDEFINED: + self.Notify = 'true' + def GetNotify(self): + return self.Notify + + def SetHelpStringItem(self, HelpStringItem): + self.HelpStringItem = HelpStringItem + def GetHelpStringItem(self): + return self.HelpStringItem + +class InfPpiItem(): + def __init__(self): + self.Name = '' + self.FeatureFlagExp = '' + self.SupArchList = [] + self.CommentList = [] + + def SetName(self, Name): + self.Name = Name + def GetName(self): + return self.Name + + def SetSupArchList(self, SupArchList): + self.SupArchList = SupArchList + def GetSupArchList(self): + return self.SupArchList + + def SetCommentList(self, CommentList): + self.CommentList = CommentList + def GetCommentList(self): + return self.CommentList + + def SetFeatureFlagExp(self, FeatureFlagExp): + self.FeatureFlagExp = FeatureFlagExp + def GetFeatureFlagExp(self): + return self.FeatureFlagExp +## +# +# +# +class InfPpiObject(): + def __init__(self): + self.Ppis = Sdict() + # + # Macro defined in this section should be only used in this section. + # + self.Macros = {} + + def SetPpi(self, PpiList, Arch = None): + __SupArchList = [] + for ArchItem in Arch: + # + # Validate Arch + # + if (ArchItem == '' or ArchItem is None): + ArchItem = 'COMMON' + __SupArchList.append(ArchItem) + + for Item in PpiList: + # + # Get Comment content of this protocol + # + CommentsList = None + if len(Item) == 3: + CommentsList = Item[1] + CurrentLineOfItem = Item[2] + Item = Item[0] + InfPpiItemObj = InfPpiItem() + if len(Item) >= 1 and len(Item) <= 2: + # + # Only CName contained + # + if not IsValidCVariableName(Item[0]): + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_INVALID_CNAME%(Item[0]), + File=CurrentLineOfItem[2], + Line=CurrentLineOfItem[1], + ExtraData=CurrentLineOfItem[0]) + if (Item[0] != ''): + InfPpiItemObj.SetName(Item[0]) + else: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_CNAME_MISSING, + File=CurrentLineOfItem[2], + Line=CurrentLineOfItem[1], + ExtraData=CurrentLineOfItem[0]) + # + # Have FeatureFlag information + # + if len(Item) == 2: + # + # Contained CName and Feature Flag Express + # ::= ["|" ] + # Item[1] should not be empty + # + if Item[1].strip() == '': + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_MISSING, + File=CurrentLineOfItem[2], + Line=CurrentLineOfItem[1], + ExtraData=CurrentLineOfItem[0]) + # + # Validate Feature Flag Express for PPI entry + # Item[1] contain FFE information + # + FeatureFlagRtv = IsValidFeatureFlagExp(Item[1].strip()) + if not FeatureFlagRtv[0]: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_SYNTAX_INVLID%(FeatureFlagRtv[1]), + File=CurrentLineOfItem[2], + Line=CurrentLineOfItem[1], + ExtraData=CurrentLineOfItem[0]) + InfPpiItemObj.SetFeatureFlagExp(Item[1]) + if len(Item) != 1 and len(Item) != 2: + # + # Invalid format of Ppi statement + # + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_GUID_PPI_PROTOCOL_SECTION_CONTENT_ERROR, + File=CurrentLineOfItem[2], + Line=CurrentLineOfItem[1], + ExtraData=CurrentLineOfItem[0]) + + # + # Get/Set Usage and HelpString for PPI entry + # + if CommentsList is not None and len(CommentsList) != 0: + InfPpiItemObj = ParsePpiComment(CommentsList, InfPpiItemObj) + else: + CommentItemIns = InfPpiItemCommentContent() + CommentItemIns.SetUsage(DT.ITEM_UNDEFINED) + CommentItemIns.SetNotify(DT.ITEM_UNDEFINED) + InfPpiItemObj.SetCommentList([CommentItemIns]) + + InfPpiItemObj.SetSupArchList(__SupArchList) + + # + # Determine PPI name duplicate. Follow below rule: + # + # A PPI must not be duplicated within a [Ppis] section. + # A PPI may appear in multiple architectural [Ppis] + # sections. A PPI listed in an architectural [Ppis] + # section must not be listed in the common architectural + # [Ppis] section. + # + # NOTE: This check will not report error now. + # + for Item in self.Ppis: + if Item.GetName() == InfPpiItemObj.GetName(): + ItemSupArchList = Item.GetSupArchList() + for ItemArch in ItemSupArchList: + for PpiItemObjArch in __SupArchList: + if ItemArch == PpiItemObjArch: + # + # ST.ERR_INF_PARSER_ITEM_DUPLICATE + # + pass + if ItemArch.upper() == 'COMMON' or PpiItemObjArch.upper() == 'COMMON': + # + # ST.ERR_INF_PARSER_ITEM_DUPLICATE_COMMON + # + pass + + if (InfPpiItemObj) in self.Ppis: + PpiList = self.Ppis[InfPpiItemObj] + PpiList.append(InfPpiItemObj) + self.Ppis[InfPpiItemObj] = PpiList + else: + PpiList = [] + PpiList.append(InfPpiItemObj) + self.Ppis[InfPpiItemObj] = PpiList + + return True + + + def GetPpi(self): + return self.Ppis diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfProtocolObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfProtocolObject.py new file mode 100755 index 00000000..00de9272 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfProtocolObject.py @@ -0,0 +1,305 @@ +## @file +# This file is used to define class objects of INF file [Protocols] section. +# It will consumed by InfParser. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +''' +InfProtocolObject +''' + +from Library.ParserValidate import IsValidCVariableName +from Library.CommentParsing import ParseComment +from Library.ExpressionValidate import IsValidFeatureFlagExp + +from Library.Misc import Sdict + +from Object.Parser.InfMisc import ErrorInInf + +from Library import DataType as DT +from Logger import StringTable as ST + +def ParseProtocolComment(CommentsList, InfProtocolItemObj): + CommentInsList = [] + PreUsage = None + PreNotify = None + PreHelpText = '' + BlockFlag = -1 + Count = 0 + for CommentItem in CommentsList: + Count = Count + 1 + CommentItemUsage, \ + CommentItemNotify, \ + CommentItemString, \ + CommentItemHelpText = \ + ParseComment(CommentItem, + DT.PROTOCOL_USAGE_TOKENS, + DT.PROTOCOL_NOTIFY_TOKENS, + ['PROTOCOL'], + False) + + if CommentItemString: + pass + + if CommentItemHelpText is None: + CommentItemHelpText = '' + if Count == len(CommentsList) and CommentItemUsage == CommentItemNotify == DT.ITEM_UNDEFINED: + CommentItemHelpText = DT.END_OF_LINE + + if Count == len(CommentsList): + if BlockFlag == 1 or BlockFlag == 2: + if CommentItemUsage == CommentItemNotify == DT.ITEM_UNDEFINED: + BlockFlag = 4 + else: + BlockFlag = 3 + elif BlockFlag == -1: + BlockFlag = 4 + + if BlockFlag == -1 or BlockFlag == 1 or BlockFlag == 2: + if CommentItemUsage == CommentItemNotify == DT.ITEM_UNDEFINED: + if BlockFlag == -1: + BlockFlag = 1 + elif BlockFlag == 1: + BlockFlag = 2 + else: + if BlockFlag == 1 or BlockFlag == 2: + BlockFlag = 3 + elif BlockFlag == -1: + BlockFlag = 4 + + # + # Combine two comment line if they are generic comment + # + if CommentItemUsage == CommentItemNotify == PreUsage == PreNotify == DT.ITEM_UNDEFINED: + CommentItemHelpText = PreHelpText + DT.END_OF_LINE + CommentItemHelpText + + PreHelpText = CommentItemHelpText + + if BlockFlag == 4: + CommentItemIns = InfProtocolItemCommentContent() + CommentItemIns.SetUsageItem(CommentItemUsage) + CommentItemIns.SetNotify(CommentItemNotify) + CommentItemIns.SetHelpStringItem(CommentItemHelpText) + CommentInsList.append(CommentItemIns) + + BlockFlag = -1 + PreUsage = None + PreNotify = None + PreHelpText = '' + + elif BlockFlag == 3: + # + # Add previous help string + # + CommentItemIns = InfProtocolItemCommentContent() + CommentItemIns.SetUsageItem(DT.ITEM_UNDEFINED) + CommentItemIns.SetNotify(DT.ITEM_UNDEFINED) + if PreHelpText == '' or PreHelpText.endswith(DT.END_OF_LINE): + PreHelpText += DT.END_OF_LINE + CommentItemIns.SetHelpStringItem(PreHelpText) + CommentInsList.append(CommentItemIns) + # + # Add Current help string + # + CommentItemIns = InfProtocolItemCommentContent() + CommentItemIns.SetUsageItem(CommentItemUsage) + CommentItemIns.SetNotify(CommentItemNotify) + CommentItemIns.SetHelpStringItem(CommentItemHelpText) + CommentInsList.append(CommentItemIns) + + BlockFlag = -1 + PreUsage = None + PreNotify = None + PreHelpText = '' + + else: + PreUsage = CommentItemUsage + PreNotify = CommentItemNotify + PreHelpText = CommentItemHelpText + + InfProtocolItemObj.SetCommentList(CommentInsList) + + return InfProtocolItemObj + +class InfProtocolItemCommentContent(): + def __init__(self): + # + # ## SOMETIMES_CONSUMES ## HelpString + # + self.UsageItem = '' + # + # Help String + # + self.HelpStringItem = '' + self.Notify = '' + self.CommentList = [] + + def SetUsageItem(self, UsageItem): + self.UsageItem = UsageItem + def GetUsageItem(self): + return self.UsageItem + + def SetNotify(self, Notify): + if Notify != DT.ITEM_UNDEFINED: + self.Notify = 'true' + def GetNotify(self): + return self.Notify + + def SetHelpStringItem(self, HelpStringItem): + self.HelpStringItem = HelpStringItem + def GetHelpStringItem(self): + return self.HelpStringItem + +class InfProtocolItem(): + def __init__(self): + self.Name = '' + self.FeatureFlagExp = '' + self.SupArchList = [] + self.CommentList = [] + + def SetName(self, Name): + self.Name = Name + def GetName(self): + return self.Name + + def SetFeatureFlagExp(self, FeatureFlagExp): + self.FeatureFlagExp = FeatureFlagExp + def GetFeatureFlagExp(self): + return self.FeatureFlagExp + + def SetSupArchList(self, SupArchList): + self.SupArchList = SupArchList + def GetSupArchList(self): + return self.SupArchList + + def SetCommentList(self, CommentList): + self.CommentList = CommentList + def GetCommentList(self): + return self.CommentList + +## +# +# +# +class InfProtocolObject(): + def __init__(self): + self.Protocols = Sdict() + # + # Macro defined in this section should be only used in this section. + # + self.Macros = {} + + def SetProtocol(self, ProtocolContent, Arch = None,): + __SupArchList = [] + for ArchItem in Arch: + # + # Validate Arch + # + if (ArchItem == '' or ArchItem is None): + ArchItem = 'COMMON' + __SupArchList.append(ArchItem) + + for Item in ProtocolContent: + # + # Get Comment content of this protocol + # + CommentsList = None + if len(Item) == 3: + CommentsList = Item[1] + CurrentLineOfItem = Item[2] + LineInfo = (CurrentLineOfItem[2], CurrentLineOfItem[1], CurrentLineOfItem[0]) + Item = Item[0] + InfProtocolItemObj = InfProtocolItem() + if len(Item) >= 1 and len(Item) <= 2: + # + # Only CName contained + # + if not IsValidCVariableName(Item[0]): + ErrorInInf(ST.ERR_INF_PARSER_INVALID_CNAME%(Item[0]), + LineInfo=LineInfo) + if (Item[0] != ''): + InfProtocolItemObj.SetName(Item[0]) + else: + ErrorInInf(ST.ERR_INF_PARSER_CNAME_MISSING, + LineInfo=LineInfo) + if len(Item) == 2: + # + # Contained CName and Feature Flag Express + # ::= ["|" + # ] + # For Protocol Object + # + if Item[1].strip() == '': + ErrorInInf(ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_MISSING, + LineInfo=LineInfo) + # + # Validate Feature Flag Express for Item[1] + # + FeatureFlagRtv = IsValidFeatureFlagExp(Item[1].strip()) + if not FeatureFlagRtv[0]: + ErrorInInf(ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_SYNTAX_INVLID%(FeatureFlagRtv[1]), + LineInfo=LineInfo) + InfProtocolItemObj.SetFeatureFlagExp(Item[1]) + + if len(Item) < 1 or len(Item) > 2: + # + # Invalid format of Protocols statement + # + ErrorInInf(ST.ERR_INF_PARSER_GUID_PPI_PROTOCOL_SECTION_CONTENT_ERROR, + LineInfo=LineInfo) + + # + # Get/Set Usage and HelpString for Protocol entry + # + if CommentsList is not None and len(CommentsList) != 0: + InfProtocolItemObj = ParseProtocolComment(CommentsList, InfProtocolItemObj) + else: + CommentItemIns = InfProtocolItemCommentContent() + CommentItemIns.SetUsageItem(DT.ITEM_UNDEFINED) + CommentItemIns.SetNotify(DT.ITEM_UNDEFINED) + InfProtocolItemObj.SetCommentList([CommentItemIns]) + + InfProtocolItemObj.SetSupArchList(__SupArchList) + + # + # Determine protocol name duplicate. Follow below rule: + # + # A protocol must not be duplicated within a [Protocols] section. + # A protocol may appear in multiple architectural [Protocols] + # sections. A protocol listed in an architectural [Protocols] + # section must not be listed in the common architectural + # [Protocols] section. + # + # NOTE: This check will not report error now. + # + for Item in self.Protocols: + if Item.GetName() == InfProtocolItemObj.GetName(): + ItemSupArchList = Item.GetSupArchList() + for ItemArch in ItemSupArchList: + for ProtocolItemObjArch in __SupArchList: + if ItemArch == ProtocolItemObjArch: + # + # ST.ERR_INF_PARSER_ITEM_DUPLICATE + # + pass + if ItemArch.upper() == 'COMMON' or ProtocolItemObjArch.upper() == 'COMMON': + # + # ST.ERR_INF_PARSER_ITEM_DUPLICATE_COMMON + # + pass + + if (InfProtocolItemObj) in self.Protocols: + ProcotolList = self.Protocols[InfProtocolItemObj] + ProcotolList.append(InfProtocolItemObj) + self.Protocols[InfProtocolItemObj] = ProcotolList + else: + ProcotolList = [] + ProcotolList.append(InfProtocolItemObj) + self.Protocols[InfProtocolItemObj] = ProcotolList + + return True + + def GetProtocol(self): + return self.Protocols diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfSoucesObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfSoucesObject.py new file mode 100755 index 00000000..de95c2f1 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfSoucesObject.py @@ -0,0 +1,233 @@ +## @file +# This file is used to define class objects of INF file [Sources] section. +# It will consumed by InfParser. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +''' +InfSourcesObject +''' + +import os + +from Logger import StringTable as ST +from Logger import ToolError +import Logger.Log as Logger +from Library import GlobalData + +from Library.Misc import Sdict +from Library.ExpressionValidate import IsValidFeatureFlagExp +from Object.Parser.InfCommonObject import InfSectionCommonDef +from Library.Misc import ValidFile +from Library.ParserValidate import IsValidFamily +from Library.ParserValidate import IsValidPath + +## __GenSourceInstance +# +# +def GenSourceInstance(Item, CurrentLineOfItem, ItemObj): + + IsValidFileFlag = False + + if len(Item) < 6 and len(Item) >= 1: + # + # File | Family | TagName | ToolCode | FeatureFlagExpr + # + if len(Item) == 5: + # + # Validate Feature Flag Express + # + if Item[4].strip() == '': + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_MISSING, + File=CurrentLineOfItem[2], + Line=CurrentLineOfItem[1], + ExtraData=CurrentLineOfItem[0]) + # + # Validate FFE + # + FeatureFlagRtv = IsValidFeatureFlagExp(Item[4].strip()) + if not FeatureFlagRtv[0]: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_SYNTAX_INVLID%(FeatureFlagRtv[1]), + File=CurrentLineOfItem[2], + Line=CurrentLineOfItem[1], + ExtraData=CurrentLineOfItem[0]) + ItemObj.SetFeatureFlagExp(Item[4]) + if len(Item) >= 4: + if Item[3].strip() == '': + ItemObj.SetToolCode(Item[3]) + else: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_TOOLCODE_NOT_PERMITTED%(Item[2]), + File=CurrentLineOfItem[2], + Line=CurrentLineOfItem[1], + ExtraData=CurrentLineOfItem[0]) + if len(Item) >= 3: + if Item[2].strip() == '': + ItemObj.SetTagName(Item[2]) + else: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_TAGNAME_NOT_PERMITTED%(Item[2]), + File=CurrentLineOfItem[2], + Line=CurrentLineOfItem[1], + ExtraData=CurrentLineOfItem[0]) + if len(Item) >= 2: + if IsValidFamily(Item[1].strip()): + # + # To align with UDP specification. "*" is not permitted in UDP specification + # + if Item[1].strip() == "*": + Item[1] = "" + ItemObj.SetFamily(Item[1]) + else: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_SOURCE_SECTION_FAMILY_INVALID%(Item[1]), + File=CurrentLineOfItem[2], + Line=CurrentLineOfItem[1], + ExtraData=CurrentLineOfItem[0]) + if len(Item) >= 1: + # + # Validate file name exist. + # + FullFileName = os.path.normpath(os.path.realpath(os.path.join(GlobalData.gINF_MODULE_DIR, Item[0]))) + if not (ValidFile(FullFileName) or ValidFile(Item[0])): + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_FILELIST_EXIST%(Item[0]), + File=CurrentLineOfItem[2], + Line=CurrentLineOfItem[1], + ExtraData=CurrentLineOfItem[0]) + + # + # Validate file exist/format. + # + + if IsValidPath(Item[0], GlobalData.gINF_MODULE_DIR): + IsValidFileFlag = True + else: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID%(Item[0]), + File=CurrentLineOfItem[2], + Line=CurrentLineOfItem[1], + ExtraData=CurrentLineOfItem[0]) + return False + if IsValidFileFlag: + ItemObj.SetSourceFileName(Item[0]) + else: + Logger.Error("InfParser", + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_SOURCES_SECTION_CONTENT_ERROR, + File=CurrentLineOfItem[2], + Line=CurrentLineOfItem[1], + ExtraData=CurrentLineOfItem[0]) + + return ItemObj + +## InfSourcesItemObject() +# +# +class InfSourcesItemObject(): + def __init__(self, \ + SourceFileName = '', \ + Family = '', \ + TagName = '', \ + ToolCode = '', \ + FeatureFlagExp = ''): + self.SourceFileName = SourceFileName + self.Family = Family + self.TagName = TagName + self.ToolCode = ToolCode + self.FeatureFlagExp = FeatureFlagExp + self.HeaderString = '' + self.TailString = '' + self.SupArchList = [] + + def SetSourceFileName(self, SourceFilename): + self.SourceFileName = SourceFilename + def GetSourceFileName(self): + return self.SourceFileName + + def SetFamily(self, Family): + self.Family = Family + def GetFamily(self): + return self.Family + + def SetTagName(self, TagName): + self.TagName = TagName + def GetTagName(self): + return self.TagName + + def SetToolCode(self, ToolCode): + self.ToolCode = ToolCode + def GetToolCode(self): + return self.ToolCode + + def SetFeatureFlagExp(self, FeatureFlagExp): + self.FeatureFlagExp = FeatureFlagExp + def GetFeatureFlagExp(self): + return self.FeatureFlagExp + + def SetHeaderString(self, HeaderString): + self.HeaderString = HeaderString + def GetHeaderString(self): + return self.HeaderString + + def SetTailString(self, TailString): + self.TailString = TailString + def GetTailString(self): + return self.TailString + + def SetSupArchList(self, SupArchList): + self.SupArchList = SupArchList + def GetSupArchList(self): + return self.SupArchList +## +# +# +# +class InfSourcesObject(InfSectionCommonDef): + def __init__(self): + self.Sources = Sdict() + InfSectionCommonDef.__init__(self) + + def SetSources(self, SourceList, Arch = None): + __SupArchList = [] + for ArchItem in Arch: + # + # Validate Arch + # + if (ArchItem == '' or ArchItem is None): + ArchItem = 'COMMON' + __SupArchList.append(ArchItem) + + for Item in SourceList: + ItemObj = InfSourcesItemObject() + CurrentLineOfItem = Item[2] + Item = Item[0] + + ItemObj = GenSourceInstance(Item, CurrentLineOfItem, ItemObj) + + ItemObj.SetSupArchList(__SupArchList) + + if (ItemObj) in self.Sources: + SourceContent = self.Sources[ItemObj] + SourceContent.append(ItemObj) + self.Sources[ItemObj] = SourceContent + else: + SourceContent = [] + SourceContent.append(ItemObj) + self.Sources[ItemObj] = SourceContent + + return True + + def GetSources(self): + return self.Sources diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfUserExtensionObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfUserExtensionObject.py new file mode 100755 index 00000000..c7593bfa --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/InfUserExtensionObject.py @@ -0,0 +1,127 @@ +## @file +# This file is used to define class objects of INF file [UserExtension] section. +# It will consumed by InfParser. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +''' +InfUserExtensionsObject +''' + +from Logger import StringTable as ST +from Logger import ToolError +import Logger.Log as Logger +from Library import GlobalData + +from Library.Misc import Sdict + +class InfUserExtensionItem(): + def __init__(self, + Content = '', + UserId = '', + IdString = ''): + self.Content = Content + self.UserId = UserId + self.IdString = IdString + self.SupArchList = [] + + def SetContent(self, Content): + self.Content = Content + def GetContent(self): + return self.Content + + def SetUserId(self, UserId): + self.UserId = UserId + def GetUserId(self): + return self.UserId + + def SetIdString(self, IdString): + self.IdString = IdString + def GetIdString(self): + return self.IdString + + def SetSupArchList(self, SupArchList): + self.SupArchList = SupArchList + def GetSupArchList(self): + return self.SupArchList + +## +# +# +# +class InfUserExtensionObject(): + def __init__(self): + self.UserExtension = Sdict() + + def SetUserExtension(self, UserExtensionCont, IdContent=None, LineNo=None): + if not UserExtensionCont or UserExtensionCont == '': + return True + # + # IdContent is a list contain UserId and IdString + # For this call the general section header parser, if no definition of + # IdString/UserId, it will return 'COMMON' + # + for IdContentItem in IdContent: + InfUserExtensionItemObj = InfUserExtensionItem() + if IdContentItem[0] == 'COMMON': + UserId = '' + else: + UserId = IdContentItem[0] + + if IdContentItem[1] == 'COMMON': + IdString = '' + else: + IdString = IdContentItem[1] + + # + # Fill UserExtensionObj members. + # + InfUserExtensionItemObj.SetUserId(UserId) + InfUserExtensionItemObj.SetIdString(IdString) + InfUserExtensionItemObj.SetContent(UserExtensionCont) + InfUserExtensionItemObj.SetSupArchList(IdContentItem[2]) + +# for CheckItem in self.UserExtension: +# if IdContentItem[0] == CheckItem[0] and IdContentItem[1] == CheckItem[1]: +# if IdContentItem[2].upper() == 'COMMON' or CheckItem[2].upper() == 'COMMON': +# # +# # For COMMON ARCH type, do special check. +# # +# Logger.Error('InfParser', +# ToolError.FORMAT_INVALID, +# ST.ERR_INF_PARSER_UE_SECTION_DUPLICATE_ERROR%\ +# (IdContentItem[0] + '.' + IdContentItem[1] + '.' + IdContentItem[2]), +# File=GlobalData.gINF_MODULE_NAME, +# Line=LineNo, +# ExtraData=None) + + if IdContentItem in self.UserExtension: + # + # Each UserExtensions section header must have a unique set + # of UserId, IdString and Arch values. + # This means that the same UserId can be used in more than one + # section header, provided the IdString or Arch values are + # different. The same IdString values can be used in more than + # one section header if the UserId or Arch values are + # different. The same UserId and the same IdString can be used + # in a section header if the Arch values are different in each + # of the section headers. + # + Logger.Error('InfParser', + ToolError.FORMAT_INVALID, + ST.ERR_INF_PARSER_UE_SECTION_DUPLICATE_ERROR%\ + (IdContentItem[0] + '.' + IdContentItem[1] + '.' + IdContentItem[2]), + File=GlobalData.gINF_MODULE_NAME, + Line=LineNo, + ExtraData=None) + else: + UserExtensionList = [] + UserExtensionList.append(InfUserExtensionItemObj) + self.UserExtension[IdContentItem] = UserExtensionList + + return True + + def GetUserExtension(self): + return self.UserExtension diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/__init__.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/__init__.py new file mode 100644 index 00000000..5174f309 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/Parser/__init__.py @@ -0,0 +1,14 @@ +## @file +# Python 'Object' package initialization file. +# +# This file is required to make Python interpreter treat the directory +# as containing package. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +PARSER +''' diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/__init__.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/__init__.py new file mode 100644 index 00000000..2e53a314 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Object/__init__.py @@ -0,0 +1,14 @@ +## @file +# Python 'Object' package initialization file. +# +# This file is required to make Python interpreter treat the directory +# as containing package. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +Object +''' diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/DecParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/DecParser.py new file mode 100755 index 00000000..f6b8545b --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/DecParser.py @@ -0,0 +1,1091 @@ +## @file +# This file is used to parse DEC file. It will consumed by DecParser +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +''' +DecParser +''' +## Import modules +# +import Logger.Log as Logger +from Logger.ToolError import FILE_PARSE_FAILURE +from Logger.ToolError import FILE_OPEN_FAILURE +from Logger import StringTable as ST +from Logger.ToolError import FORMAT_INVALID + +import Library.DataType as DT +from Library.ParserValidate import IsValidToken +from Library.ParserValidate import IsValidPath +from Library.ParserValidate import IsValidCFormatGuid +from Library.ParserValidate import IsValidIdString +from Library.ParserValidate import IsValidUserId +from Library.ParserValidate import IsValidArch +from Library.ParserValidate import IsValidWord +from Library.ParserValidate import IsValidDecVersionVal +from Parser.DecParserMisc import TOOL_NAME +from Parser.DecParserMisc import CleanString +from Parser.DecParserMisc import IsValidPcdDatum +from Parser.DecParserMisc import ParserHelper +from Parser.DecParserMisc import StripRoot +from Parser.DecParserMisc import VERSION_PATTERN +from Parser.DecParserMisc import CVAR_PATTERN +from Parser.DecParserMisc import PCD_TOKEN_PATTERN +from Parser.DecParserMisc import MACRO_PATTERN +from Parser.DecParserMisc import FileContent +from Object.Parser.DecObject import _DecComments +from Object.Parser.DecObject import DecDefineObject +from Object.Parser.DecObject import DecDefineItemObject +from Object.Parser.DecObject import DecIncludeObject +from Object.Parser.DecObject import DecIncludeItemObject +from Object.Parser.DecObject import DecLibraryclassObject +from Object.Parser.DecObject import DecLibraryclassItemObject +from Object.Parser.DecObject import DecGuidObject +from Object.Parser.DecObject import DecPpiObject +from Object.Parser.DecObject import DecProtocolObject +from Object.Parser.DecObject import DecGuidItemObject +from Object.Parser.DecObject import DecUserExtensionObject +from Object.Parser.DecObject import DecUserExtensionItemObject +from Object.Parser.DecObject import DecPcdObject +from Object.Parser.DecObject import DecPcdItemObject +from Library.Misc import GuidStructureStringToGuidString +from Library.Misc import CheckGuidRegFormat +from Library.StringUtils import ReplaceMacro +from Library.StringUtils import GetSplitValueList +from Library.StringUtils import gMACRO_PATTERN +from Library.StringUtils import ConvertSpecialChar +from Library.CommentParsing import ParsePcdErrorCode + +## +# _DecBase class for parsing +# +class _DecBase: + def __init__(self, RawData): + self._RawData = RawData + self._ItemDict = {} + self._LocalMacro = {} + # + # Data parsed by 'self' are saved to this object + # + self.ItemObject = None + + def GetDataObject(self): + return self.ItemObject + + def GetLocalMacro(self): + return self._LocalMacro + + ## BlockStart + # + # Called if a new section starts + # + def BlockStart(self): + self._LocalMacro = {} + + ## _CheckReDefine + # + # @param Key: to be checked if multi-defined + # @param Scope: Format: [[SectionName, Arch], ...]. + # If scope is none, use global scope + # + def _CheckReDefine(self, Key, Scope = None): + if not Scope: + Scope = self._RawData.CurrentScope + return + + SecArch = [] + # + # Copy scope to SecArch, avoid Scope be changed outside + # + SecArch[0:1] = Scope[:] + if Key not in self._ItemDict: + self._ItemDict[Key] = [[SecArch, self._RawData.LineIndex]] + return + + for Value in self._ItemDict[Key]: + for SubValue in Scope: + # + # If current is common section + # + if SubValue[-1] == 'COMMON': + for Other in Value[0]: + # Key in common cannot be redefined in other arches + # [:-1] means stripping arch info + if Other[:-1] == SubValue[:-1]: + self._LoggerError(ST.ERR_DECPARSE_REDEFINE % (Key, Value[1])) + return + continue + CommonScope = [] + CommonScope[0:1] = SubValue + CommonScope[-1] = 'COMMON' + # + # Cannot be redefined if this key already defined in COMMON Or defined in same arch + # + if SubValue in Value[0] or CommonScope in Value[0]: + self._LoggerError(ST.ERR_DECPARSE_REDEFINE % (Key, Value[1])) + return + self._ItemDict[Key].append([SecArch, self._RawData.LineIndex]) + + ## CheckRequiredFields + # Some sections need to check if some fields exist, define section for example + # Derived class can re-implement, top parser will call this function after all parsing done + # + def CheckRequiredFields(self): + if self._RawData: + pass + return True + + ## IsItemRequired + # In DEC spec, sections must have at least one statement except user + # extension. + # For example: "[guids" [] "]" + + # sub class can override this method to indicate if statement is a must. + # + def _IsStatementRequired(self): + if self._RawData: + pass + return False + + def _LoggerError(self, ErrorString): + Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._RawData.Filename, + Line = self._RawData.LineIndex, + ExtraData=ErrorString + ST.ERR_DECPARSE_LINE % self._RawData.CurrentLine) + + def _ReplaceMacro(self, String): + if gMACRO_PATTERN.findall(String): + String = ReplaceMacro(String, self._LocalMacro, False, + FileName = self._RawData.Filename, + Line = ['', self._RawData.LineIndex]) + String = ReplaceMacro(String, self._RawData.Macros, False, + FileName = self._RawData.Filename, + Line = ['', self._RawData.LineIndex]) + MacroUsed = gMACRO_PATTERN.findall(String) + if MacroUsed: + Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, + File=self._RawData.Filename, + Line = self._RawData.LineIndex, + ExtraData = ST.ERR_DECPARSE_MACRO_RESOLVE % (str(MacroUsed), String)) + return String + + def _MacroParser(self, String): + TokenList = GetSplitValueList(String, ' ', 1) + if len(TokenList) < 2 or TokenList[1] == '': + self._LoggerError(ST.ERR_DECPARSE_MACRO_PAIR) + + TokenList = GetSplitValueList(TokenList[1], DT.TAB_EQUAL_SPLIT, 1) + if TokenList[0] == '': + self._LoggerError(ST.ERR_DECPARSE_MACRO_NAME) + elif not IsValidToken(MACRO_PATTERN, TokenList[0]): + self._LoggerError(ST.ERR_DECPARSE_MACRO_NAME_UPPER % TokenList[0]) + + if len(TokenList) == 1: + self._LocalMacro[TokenList[0]] = '' + else: + self._LocalMacro[TokenList[0]] = self._ReplaceMacro(TokenList[1]) + + ## _ParseItem + # + # Parse specified item, this function must be derived by subclass + # + def _ParseItem(self): + if self._RawData: + pass + # + # Should never be called + # + return None + + + ## _TailCommentStrategy + # + # This function can be derived to parse tail comment + # default is it will not consume any lines + # + # @param Comment: Comment of current line + # + def _TailCommentStrategy(self, Comment): + if Comment: + pass + if self._RawData: + pass + return False + + ## _StopCurrentParsing + # + # Called in Parse if current parsing should be stopped when encounter some + # keyword + # Default is section start and end + # + # @param Line: Current line + # + def _StopCurrentParsing(self, Line): + if self._RawData: + pass + return Line[0] == DT.TAB_SECTION_START and Line[-1] == DT.TAB_SECTION_END + + ## _TryBackSlash + # + # Split comment and DEC content, concatenate lines if end of char is '\' + # + # @param ProcessedLine: ProcessedLine line + # @param ProcessedComments: ProcessedComments line + # + def _TryBackSlash(self, ProcessedLine, ProcessedComments): + CatLine = '' + Comment = '' + Line = ProcessedLine + CommentList = ProcessedComments + while not self._RawData.IsEndOfFile(): + if Line == '': + self._LoggerError(ST.ERR_DECPARSE_BACKSLASH_EMPTY) + break + + if Comment: + CommentList.append((Comment, self._RawData.LineIndex)) + if Line[-1] != DT.TAB_SLASH: + CatLine += Line + break + elif len(Line) < 2 or Line[-2] != ' ': + self._LoggerError(ST.ERR_DECPARSE_BACKSLASH) + else: + CatLine += Line[:-1] + Line, Comment = CleanString(self._RawData.GetNextLine()) + # + # Reach end of content + # + if self._RawData.IsEndOfFile(): + if not CatLine: + if ProcessedLine[-1] == DT.TAB_SLASH: + self._LoggerError(ST.ERR_DECPARSE_BACKSLASH_EMPTY) + CatLine = ProcessedLine + else: + if not Line or Line[-1] == DT.TAB_SLASH: + self._LoggerError(ST.ERR_DECPARSE_BACKSLASH_EMPTY) + CatLine += Line + + # + # All MACRO values defined by the DEFINE statements in any section + # (except [Userextensions] sections for Intel) of the INF or DEC file + # must be expanded before processing of the file. + # + __IsReplaceMacro = True + Header = self._RawData.CurrentScope[0] if self._RawData.CurrentScope else None + if Header and len(Header) > 2: + if Header[0].upper() == 'USEREXTENSIONS' and not (Header[1] == 'TianoCore' and Header[2] == '"ExtraFiles"'): + __IsReplaceMacro = False + if __IsReplaceMacro: + self._RawData.CurrentLine = self._ReplaceMacro(CatLine) + else: + self._RawData.CurrentLine = CatLine + + return CatLine, CommentList + + ## Parse + # This is a template method in which other member functions which might + # override by sub class are called. It is responsible for reading file + # line by line, and call other member functions to parse. This function + # should not be re-implement by sub class. + # + def Parse(self): + HeadComments = [] + TailComments = [] + + #====================================================================== + # CurComments may pointer to HeadComments or TailComments + #====================================================================== + CurComments = HeadComments + CurObj = None + ItemNum = 0 + FromBuf = False + + #====================================================================== + # Used to report error information if empty section found + #====================================================================== + Index = self._RawData.LineIndex + LineStr = self._RawData.CurrentLine + while not self._RawData.IsEndOfFile() or self._RawData.NextLine: + if self._RawData.NextLine: + #============================================================== + # Have processed line in buffer + #============================================================== + Line = self._RawData.NextLine + HeadComments.extend(self._RawData.HeadComment) + TailComments.extend(self._RawData.TailComment) + self._RawData.ResetNext() + Comment = '' + FromBuf = True + else: + #============================================================== + # No line in buffer, read next line + #============================================================== + Line, Comment = CleanString(self._RawData.GetNextLine()) + FromBuf = False + if Line: + if not FromBuf and CurObj and TailComments: + #========================================================== + # Set tail comments to previous statement if not empty. + #========================================================== + CurObj.SetTailComment(CurObj.GetTailComment()+TailComments) + + if not FromBuf: + del TailComments[:] + CurComments = TailComments + Comments = [] + if Comment: + Comments = [(Comment, self._RawData.LineIndex)] + + #============================================================== + # Try if last char of line has backslash + #============================================================== + Line, Comments = self._TryBackSlash(Line, Comments) + CurComments.extend(Comments) + + #============================================================== + # Macro found + #============================================================== + if Line.startswith('DEFINE '): + self._MacroParser(Line) + del HeadComments[:] + del TailComments[:] + CurComments = HeadComments + continue + + if self._StopCurrentParsing(Line): + #========================================================== + # This line does not belong to this parse, + # Save it, can be used by next parse + #========================================================== + self._RawData.SetNext(Line, HeadComments, TailComments) + break + + Obj = self._ParseItem() + ItemNum += 1 + if Obj: + Obj.SetHeadComment(Obj.GetHeadComment()+HeadComments) + Obj.SetTailComment(Obj.GetTailComment()+TailComments) + del HeadComments[:] + del TailComments[:] + CurObj = Obj + else: + CurObj = None + else: + if id(CurComments) == id(TailComments): + #========================================================== + # Check if this comment belongs to tail comment + #========================================================== + if not self._TailCommentStrategy(Comment): + CurComments = HeadComments + + if Comment: + CurComments.append(((Comment, self._RawData.LineIndex))) + else: + del CurComments[:] + + if self._IsStatementRequired() and ItemNum == 0: + Logger.Error( + TOOL_NAME, FILE_PARSE_FAILURE, + File=self._RawData.Filename, + Line=Index, + ExtraData=ST.ERR_DECPARSE_STATEMENT_EMPTY % LineStr + ) + +## _DecDefine +# Parse define section +# +class _DecDefine(_DecBase): + def __init__(self, RawData): + _DecBase.__init__(self, RawData) + self.ItemObject = DecDefineObject(RawData.Filename) + self._LocalMacro = self._RawData.Macros + self._DefSecNum = 0 + + # + # Each field has a function to validate + # + self.DefineValidation = { + DT.TAB_DEC_DEFINES_DEC_SPECIFICATION : self._SetDecSpecification, + DT.TAB_DEC_DEFINES_PACKAGE_NAME : self._SetPackageName, + DT.TAB_DEC_DEFINES_PACKAGE_GUID : self._SetPackageGuid, + DT.TAB_DEC_DEFINES_PACKAGE_VERSION : self._SetPackageVersion, + DT.TAB_DEC_DEFINES_PKG_UNI_FILE : self._SetPackageUni, + } + + def BlockStart(self): + self._DefSecNum += 1 + if self._DefSecNum > 1: + self._LoggerError(ST.ERR_DECPARSE_DEFINE_MULTISEC) + + ## CheckRequiredFields + # + # Check required fields: DEC_SPECIFICATION, PACKAGE_NAME + # PACKAGE_GUID, PACKAGE_VERSION + # + def CheckRequiredFields(self): + Ret = False + if self.ItemObject.GetPackageSpecification() == '': + Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._RawData.Filename, + ExtraData=ST.ERR_DECPARSE_DEFINE_REQUIRED % DT.TAB_DEC_DEFINES_DEC_SPECIFICATION) + elif self.ItemObject.GetPackageName() == '': + Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._RawData.Filename, + ExtraData=ST.ERR_DECPARSE_DEFINE_REQUIRED % DT.TAB_DEC_DEFINES_PACKAGE_NAME) + elif self.ItemObject.GetPackageGuid() == '': + Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._RawData.Filename, + ExtraData=ST.ERR_DECPARSE_DEFINE_REQUIRED % DT.TAB_DEC_DEFINES_PACKAGE_GUID) + elif self.ItemObject.GetPackageVersion() == '': + Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._RawData.Filename, + ExtraData=ST.ERR_DECPARSE_DEFINE_REQUIRED % DT.TAB_DEC_DEFINES_PACKAGE_VERSION) + else: + Ret = True + return Ret + + def _ParseItem(self): + Line = self._RawData.CurrentLine + TokenList = GetSplitValueList(Line, DT.TAB_EQUAL_SPLIT, 1) + if TokenList[0] == DT.TAB_DEC_DEFINES_PKG_UNI_FILE: + self.DefineValidation[TokenList[0]](TokenList[1]) + elif len(TokenList) < 2: + self._LoggerError(ST.ERR_DECPARSE_DEFINE_FORMAT) + elif TokenList[0] not in self.DefineValidation: + self._LoggerError(ST.ERR_DECPARSE_DEFINE_UNKNOWKEY % TokenList[0]) + else: + self.DefineValidation[TokenList[0]](TokenList[1]) + + DefineItem = DecDefineItemObject() + DefineItem.Key = TokenList[0] + DefineItem.Value = TokenList[1] + self.ItemObject.AddItem(DefineItem, self._RawData.CurrentScope) + return DefineItem + + def _SetDecSpecification(self, Token): + if self.ItemObject.GetPackageSpecification(): + self._LoggerError(ST.ERR_DECPARSE_DEFINE_DEFINED % DT.TAB_DEC_DEFINES_DEC_SPECIFICATION) + if not IsValidToken('0[xX][0-9a-fA-F]{8}', Token): + if not IsValidDecVersionVal(Token): + self._LoggerError(ST.ERR_DECPARSE_DEFINE_SPEC) + self.ItemObject.SetPackageSpecification(Token) + + def _SetPackageName(self, Token): + if self.ItemObject.GetPackageName(): + self._LoggerError(ST.ERR_DECPARSE_DEFINE_DEFINED % DT.TAB_DEC_DEFINES_PACKAGE_NAME) + if not IsValidWord(Token): + self._LoggerError(ST.ERR_DECPARSE_DEFINE_PKGNAME) + self.ItemObject.SetPackageName(Token) + + def _SetPackageGuid(self, Token): + if self.ItemObject.GetPackageGuid(): + self._LoggerError(ST.ERR_DECPARSE_DEFINE_DEFINED % DT.TAB_DEC_DEFINES_PACKAGE_GUID) + if not CheckGuidRegFormat(Token): + self._LoggerError(ST.ERR_DECPARSE_DEFINE_PKGGUID) + self.ItemObject.SetPackageGuid(Token) + + def _SetPackageVersion(self, Token): + if self.ItemObject.GetPackageVersion(): + self._LoggerError(ST.ERR_DECPARSE_DEFINE_DEFINED % DT.TAB_DEC_DEFINES_PACKAGE_VERSION) + if not IsValidToken(VERSION_PATTERN, Token): + self._LoggerError(ST.ERR_DECPARSE_DEFINE_PKGVERSION) + else: + if not DT.TAB_SPLIT in Token: + Token = Token + '.0' + self.ItemObject.SetPackageVersion(Token) + + def _SetPackageUni(self, Token): + if self.ItemObject.GetPackageUniFile(): + self._LoggerError(ST.ERR_DECPARSE_DEFINE_DEFINED % DT.TAB_DEC_DEFINES_PKG_UNI_FILE) + self.ItemObject.SetPackageUniFile(Token) + +## _DecInclude +# +# Parse include section +# +class _DecInclude(_DecBase): + def __init__(self, RawData): + _DecBase.__init__(self, RawData) + self.ItemObject = DecIncludeObject(RawData.Filename) + + def _ParseItem(self): + Line = self._RawData.CurrentLine + + if not IsValidPath(Line, self._RawData.PackagePath): + self._LoggerError(ST.ERR_DECPARSE_INCLUDE % Line) + + Item = DecIncludeItemObject(StripRoot(self._RawData.PackagePath, Line), self._RawData.PackagePath) + self.ItemObject.AddItem(Item, self._RawData.CurrentScope) + return Item + +## _DecLibraryclass +# +# Parse library class section +# +class _DecLibraryclass(_DecBase): + def __init__(self, RawData): + _DecBase.__init__(self, RawData) + self.ItemObject = DecLibraryclassObject(RawData.Filename) + + def _ParseItem(self): + Line = self._RawData.CurrentLine + TokenList = GetSplitValueList(Line, DT.TAB_VALUE_SPLIT) + if len(TokenList) != 2: + self._LoggerError(ST.ERR_DECPARSE_LIBCLASS_SPLIT) + if TokenList[0] == '' or TokenList[1] == '': + self._LoggerError(ST.ERR_DECPARSE_LIBCLASS_EMPTY) + if not IsValidToken('[A-Z][0-9A-Za-z]*', TokenList[0]): + self._LoggerError(ST.ERR_DECPARSE_LIBCLASS_LIB) + + self._CheckReDefine(TokenList[0]) + + Value = TokenList[1] + # + # Must end with .h + # + if not Value.endswith('.h'): + self._LoggerError(ST.ERR_DECPARSE_LIBCLASS_PATH_EXT) + + # + # Path must be existed + # + if not IsValidPath(Value, self._RawData.PackagePath): + self._LoggerError(ST.ERR_DECPARSE_INCLUDE % Value) + + Item = DecLibraryclassItemObject(TokenList[0], StripRoot(self._RawData.PackagePath, Value), + self._RawData.PackagePath) + self.ItemObject.AddItem(Item, self._RawData.CurrentScope) + return Item + +## _DecPcd +# +# Parse PCD section +# +class _DecPcd(_DecBase): + def __init__(self, RawData): + _DecBase.__init__(self, RawData) + self.ItemObject = DecPcdObject(RawData.Filename) + # + # Used to check duplicate token + # Key is token space and token number (integer), value is C name + # + self.TokenMap = {} + + def _ParseItem(self): + Line = self._RawData.CurrentLine + TokenList = Line.split(DT.TAB_VALUE_SPLIT) + if len(TokenList) < 4: + self._LoggerError(ST.ERR_DECPARSE_PCD_SPLIT) + + # + # Token space guid C name + # + PcdName = GetSplitValueList(TokenList[0], DT.TAB_SPLIT) + if len(PcdName) != 2 or PcdName[0] == '' or PcdName[1] == '': + self._LoggerError(ST.ERR_DECPARSE_PCD_NAME) + + Guid = PcdName[0] + if not IsValidToken(CVAR_PATTERN, Guid): + self._LoggerError(ST.ERR_DECPARSE_PCD_CVAR_GUID) + + # + # PCD C name + # + CName = PcdName[1] + if not IsValidToken(CVAR_PATTERN, CName): + self._LoggerError(ST.ERR_DECPARSE_PCD_CVAR_PCDCNAME) + + self._CheckReDefine(Guid + DT.TAB_SPLIT + CName) + + # + # Default value, may be C array, string or number + # + Data = DT.TAB_VALUE_SPLIT.join(TokenList[1:-2]).strip() + + # + # PCD data type + # + DataType = TokenList[-2].strip() + Valid, Cause = IsValidPcdDatum(DataType, Data) + if not Valid: + self._LoggerError(Cause) + PcdType = self._RawData.CurrentScope[0][0] + if PcdType == DT.TAB_PCDS_FEATURE_FLAG_NULL.upper() and DataType != 'BOOLEAN': + self._LoggerError(ST.ERR_DECPARSE_PCD_FEATUREFLAG) + # + # Token value is the last element in list. + # + Token = TokenList[-1].strip() + if not IsValidToken(PCD_TOKEN_PATTERN, Token): + self._LoggerError(ST.ERR_DECPARSE_PCD_TOKEN % Token) + elif not Token.startswith('0x') and not Token.startswith('0X'): + if int(Token) > 4294967295: + self._LoggerError(ST.ERR_DECPARSE_PCD_TOKEN_INT % Token) + Token = '0x%x' % int(Token) + + IntToken = int(Token, 0) + if (Guid, IntToken) in self.TokenMap: + if self.TokenMap[Guid, IntToken] != CName: + self._LoggerError(ST.ERR_DECPARSE_PCD_TOKEN_UNIQUE%(Token)) + else: + self.TokenMap[Guid, IntToken] = CName + + Item = DecPcdItemObject(Guid, CName, Data, DataType, Token) + self.ItemObject.AddItem(Item, self._RawData.CurrentScope) + return Item + +## _DecGuid +# +# Parse GUID, PPI, Protocol section +# +class _DecGuid(_DecBase): + def __init__(self, RawData): + _DecBase.__init__(self, RawData) + self.GuidObj = DecGuidObject(RawData.Filename) + self.PpiObj = DecPpiObject(RawData.Filename) + self.ProtocolObj = DecProtocolObject(RawData.Filename) + self.ObjectDict = \ + { + DT.TAB_GUIDS.upper() : self.GuidObj, + DT.TAB_PPIS.upper() : self.PpiObj, + DT.TAB_PROTOCOLS.upper() : self.ProtocolObj + } + + def GetDataObject(self): + if self._RawData.CurrentScope: + return self.ObjectDict[self._RawData.CurrentScope[0][0]] + return None + + def GetGuidObject(self): + return self.GuidObj + + def GetPpiObject(self): + return self.PpiObj + + def GetProtocolObject(self): + return self.ProtocolObj + + def _ParseItem(self): + Line = self._RawData.CurrentLine + TokenList = GetSplitValueList(Line, DT.TAB_EQUAL_SPLIT, 1) + if len(TokenList) < 2: + self._LoggerError(ST.ERR_DECPARSE_CGUID) + if TokenList[0] == '': + self._LoggerError(ST.ERR_DECPARSE_CGUID_NAME) + if TokenList[1] == '': + self._LoggerError(ST.ERR_DECPARSE_CGUID_GUID) + if not IsValidToken(CVAR_PATTERN, TokenList[0]): + self._LoggerError(ST.ERR_DECPARSE_PCD_CVAR_GUID) + + self._CheckReDefine(TokenList[0]) + + if TokenList[1][0] != '{': + if not CheckGuidRegFormat(TokenList[1]): + self._LoggerError(ST.ERR_DECPARSE_DEFINE_PKGGUID) + GuidString = TokenList[1] + else: + # + # Convert C format GUID to GUID string and Simple error check + # + GuidString = GuidStructureStringToGuidString(TokenList[1]) + if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidString == '': + self._LoggerError(ST.ERR_DECPARSE_CGUID_GUIDFORMAT) + + # + # Check C format GUID + # + if not IsValidCFormatGuid(TokenList[1]): + self._LoggerError(ST.ERR_DECPARSE_CGUID_GUIDFORMAT) + + Item = DecGuidItemObject(TokenList[0], TokenList[1], GuidString) + ItemObject = self.ObjectDict[self._RawData.CurrentScope[0][0]] + ItemObject.AddItem(Item, self._RawData.CurrentScope) + return Item + +## _DecUserExtension +# +# Parse user extension section +# +class _DecUserExtension(_DecBase): + def __init__(self, RawData): + _DecBase.__init__(self, RawData) + self.ItemObject = DecUserExtensionObject(RawData.Filename) + self._Headers = [] + self._CurItems = [] + + def BlockStart(self): + self._CurItems = [] + for Header in self._RawData.CurrentScope: + if Header in self._Headers: + self._LoggerError(ST.ERR_DECPARSE_UE_DUPLICATE) + else: + self._Headers.append(Header) + + for Item in self._CurItems: + if Item.UserId == Header[1] and Item.IdString == Header[2]: + Item.ArchAndModuleType.append(Header[3]) + break + else: + Item = DecUserExtensionItemObject() + Item.UserId = Header[1] + Item.IdString = Header[2] + Item.ArchAndModuleType.append(Header[3]) + self._CurItems.append(Item) + self.ItemObject.AddItem(Item, None) + self._LocalMacro = {} + + def _ParseItem(self): + Line = self._RawData.CurrentLine + Item = None + for Item in self._CurItems: + if Item.UserString: + Item.UserString = '\n'.join([Item.UserString, Line]) + else: + Item.UserString = Line + return Item + +## Dec +# +# Top dec parser +# +class Dec(_DecBase, _DecComments): + def __init__(self, DecFile, Parse = True): + try: + Content = ConvertSpecialChar(open(DecFile, 'r').readlines()) + except BaseException: + Logger.Error(TOOL_NAME, FILE_OPEN_FAILURE, File=DecFile, + ExtraData=ST.ERR_DECPARSE_FILEOPEN % DecFile) + + # + # Pre-parser for Private section + # + self._Private = '' + __IsFoundPrivate = False + NewContent = [] + for Line in Content: + Line = Line.strip() + if Line.startswith(DT.TAB_SECTION_START) and Line.endswith(DT.TAB_PRIVATE + DT.TAB_SECTION_END): + __IsFoundPrivate = True + if Line.startswith(DT.TAB_SECTION_START) and Line.endswith(DT.TAB_SECTION_END)\ + and not Line.endswith(DT.TAB_PRIVATE + DT.TAB_SECTION_END): + __IsFoundPrivate = False + if __IsFoundPrivate: + self._Private += Line + '\r' + if not __IsFoundPrivate: + NewContent.append(Line + '\r') + + RawData = FileContent(DecFile, NewContent) + + _DecComments.__init__(self) + _DecBase.__init__(self, RawData) + + self.BinaryHeadComment = [] + self.PcdErrorCommentDict = {} + + self._Define = _DecDefine(RawData) + self._Include = _DecInclude(RawData) + self._Guid = _DecGuid(RawData) + self._LibClass = _DecLibraryclass(RawData) + self._Pcd = _DecPcd(RawData) + self._UserEx = _DecUserExtension(RawData) + + # + # DEC file supported data types (one type per section) + # + self._SectionParser = { + DT.TAB_DEC_DEFINES.upper() : self._Define, + DT.TAB_INCLUDES.upper() : self._Include, + DT.TAB_LIBRARY_CLASSES.upper() : self._LibClass, + DT.TAB_GUIDS.upper() : self._Guid, + DT.TAB_PPIS.upper() : self._Guid, + DT.TAB_PROTOCOLS.upper() : self._Guid, + DT.TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : self._Pcd, + DT.TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : self._Pcd, + DT.TAB_PCDS_FEATURE_FLAG_NULL.upper() : self._Pcd, + DT.TAB_PCDS_DYNAMIC_NULL.upper() : self._Pcd, + DT.TAB_PCDS_DYNAMIC_EX_NULL.upper() : self._Pcd, + DT.TAB_USER_EXTENSIONS.upper() : self._UserEx + } + + if Parse: + self.ParseDecComment() + self.Parse() + # + # Parsing done, check required fields + # + self.CheckRequiredFields() + + def CheckRequiredFields(self): + for SectionParser in self._SectionParser.values(): + if not SectionParser.CheckRequiredFields(): + return False + return True + + ## + # Parse DEC file + # + def ParseDecComment(self): + IsFileHeader = False + IsBinaryHeader = False + FileHeaderLineIndex = -1 + BinaryHeaderLineIndex = -1 + TokenSpaceGuidCName = '' + + # + # Parse PCD error comment section + # + while not self._RawData.IsEndOfFile(): + self._RawData.CurrentLine = self._RawData.GetNextLine() + if self._RawData.CurrentLine.startswith(DT.TAB_COMMENT_SPLIT) and \ + DT.TAB_SECTION_START in self._RawData.CurrentLine and \ + DT.TAB_SECTION_END in self._RawData.CurrentLine: + self._RawData.CurrentLine = self._RawData.CurrentLine.replace(DT.TAB_COMMENT_SPLIT, '').strip() + + if self._RawData.CurrentLine[0] == DT.TAB_SECTION_START and \ + self._RawData.CurrentLine[-1] == DT.TAB_SECTION_END: + RawSection = self._RawData.CurrentLine[1:-1].strip() + if RawSection.upper().startswith(DT.TAB_PCD_ERROR.upper()+'.'): + TokenSpaceGuidCName = RawSection.split(DT.TAB_PCD_ERROR+'.')[1].strip() + continue + + if TokenSpaceGuidCName and self._RawData.CurrentLine.startswith(DT.TAB_COMMENT_SPLIT): + self._RawData.CurrentLine = self._RawData.CurrentLine.replace(DT.TAB_COMMENT_SPLIT, '').strip() + if self._RawData.CurrentLine != '': + if DT.TAB_VALUE_SPLIT not in self._RawData.CurrentLine: + self._LoggerError(ST.ERR_DECPARSE_PCDERRORMSG_MISS_VALUE_SPLIT) + + PcdErrorNumber, PcdErrorMsg = GetSplitValueList(self._RawData.CurrentLine, DT.TAB_VALUE_SPLIT, 1) + PcdErrorNumber = ParsePcdErrorCode(PcdErrorNumber, self._RawData.Filename, self._RawData.LineIndex) + if not PcdErrorMsg.strip(): + self._LoggerError(ST.ERR_DECPARSE_PCD_MISS_ERRORMSG) + + self.PcdErrorCommentDict[(TokenSpaceGuidCName, PcdErrorNumber)] = PcdErrorMsg.strip() + else: + TokenSpaceGuidCName = '' + + self._RawData.LineIndex = 0 + self._RawData.CurrentLine = '' + self._RawData.NextLine = '' + + while not self._RawData.IsEndOfFile(): + Line, Comment = CleanString(self._RawData.GetNextLine()) + + # + # Header must be pure comment + # + if Line != '': + self._RawData.UndoNextLine() + break + + if Comment and Comment.startswith(DT.TAB_SPECIAL_COMMENT) and Comment.find(DT.TAB_HEADER_COMMENT) > 0 \ + and not Comment[2:Comment.find(DT.TAB_HEADER_COMMENT)].strip(): + IsFileHeader = True + IsBinaryHeader = False + FileHeaderLineIndex = self._RawData.LineIndex + + # + # Get license information before '@file' + # + if not IsFileHeader and not IsBinaryHeader and Comment and Comment.startswith(DT.TAB_COMMENT_SPLIT) and \ + DT.TAB_BINARY_HEADER_COMMENT not in Comment: + self._HeadComment.append((Comment, self._RawData.LineIndex)) + + if Comment and IsFileHeader and \ + not(Comment.startswith(DT.TAB_SPECIAL_COMMENT) \ + and Comment.find(DT.TAB_BINARY_HEADER_COMMENT) > 0): + self._HeadComment.append((Comment, self._RawData.LineIndex)) + # + # Double '#' indicates end of header comments + # + if (not Comment or Comment == DT.TAB_SPECIAL_COMMENT) and IsFileHeader: + IsFileHeader = False + continue + + if Comment and Comment.startswith(DT.TAB_SPECIAL_COMMENT) \ + and Comment.find(DT.TAB_BINARY_HEADER_COMMENT) > 0: + IsBinaryHeader = True + IsFileHeader = False + BinaryHeaderLineIndex = self._RawData.LineIndex + + if Comment and IsBinaryHeader: + self.BinaryHeadComment.append((Comment, self._RawData.LineIndex)) + # + # Double '#' indicates end of header comments + # + if (not Comment or Comment == DT.TAB_SPECIAL_COMMENT) and IsBinaryHeader: + IsBinaryHeader = False + break + + if FileHeaderLineIndex > -1 and not IsFileHeader and not IsBinaryHeader: + break + + if FileHeaderLineIndex > BinaryHeaderLineIndex and FileHeaderLineIndex > -1 and BinaryHeaderLineIndex > -1: + self._LoggerError(ST.ERR_BINARY_HEADER_ORDER) + + if FileHeaderLineIndex == -1: +# self._LoggerError(ST.ERR_NO_SOURCE_HEADER) + Logger.Error(TOOL_NAME, FORMAT_INVALID, + ST.ERR_NO_SOURCE_HEADER, + File=self._RawData.Filename) + return + + def _StopCurrentParsing(self, Line): + return False + + def _ParseItem(self): + self._SectionHeaderParser() + if len(self._RawData.CurrentScope) == 0: + self._LoggerError(ST.ERR_DECPARSE_SECTION_EMPTY) + SectionObj = self._SectionParser[self._RawData.CurrentScope[0][0]] + SectionObj.BlockStart() + SectionObj.Parse() + return SectionObj.GetDataObject() + + def _UserExtentionSectionParser(self): + self._RawData.CurrentScope = [] + ArchList = set() + Section = self._RawData.CurrentLine[1:-1] + Par = ParserHelper(Section, self._RawData.Filename) + while not Par.End(): + # + # User extention + # + Token = Par.GetToken() + if Token.upper() != DT.TAB_USER_EXTENSIONS.upper(): + self._LoggerError(ST.ERR_DECPARSE_SECTION_UE) + UserExtension = Token.upper() + Par.AssertChar(DT.TAB_SPLIT, ST.ERR_DECPARSE_SECTION_UE, self._RawData.LineIndex) + + # + # UserID + # + Token = Par.GetToken() + if not IsValidUserId(Token): + self._LoggerError(ST.ERR_DECPARSE_SECTION_UE_USERID) + UserId = Token + Par.AssertChar(DT.TAB_SPLIT, ST.ERR_DECPARSE_SECTION_UE, self._RawData.LineIndex) + # + # IdString + # + Token = Par.GetToken() + if not IsValidIdString(Token): + self._LoggerError(ST.ERR_DECPARSE_SECTION_UE_IDSTRING) + IdString = Token + Arch = 'COMMON' + if Par.Expect(DT.TAB_SPLIT): + Token = Par.GetToken() + Arch = Token.upper() + if not IsValidArch(Arch): + self._LoggerError(ST.ERR_DECPARSE_ARCH) + ArchList.add(Arch) + if [UserExtension, UserId, IdString, Arch] not in \ + self._RawData.CurrentScope: + self._RawData.CurrentScope.append( + [UserExtension, UserId, IdString, Arch] + ) + if not Par.Expect(DT.TAB_COMMA_SPLIT): + break + elif Par.End(): + self._LoggerError(ST.ERR_DECPARSE_SECTION_COMMA) + Par.AssertEnd(ST.ERR_DECPARSE_SECTION_UE, self._RawData.LineIndex) + if 'COMMON' in ArchList and len(ArchList) > 1: + self._LoggerError(ST.ERR_DECPARSE_SECTION_COMMON) + + ## Section header parser + # + # The section header is always in following format: + # + # [section_name.arch<.platform|module_type>] + # + def _SectionHeaderParser(self): + if self._RawData.CurrentLine[0] != DT.TAB_SECTION_START or self._RawData.CurrentLine[-1] != DT.TAB_SECTION_END: + self._LoggerError(ST.ERR_DECPARSE_SECTION_IDENTIFY) + + RawSection = self._RawData.CurrentLine[1:-1].strip().upper() + # + # Check defines section which is only allowed to occur once and + # no arch can be followed + # + if RawSection.startswith(DT.TAB_DEC_DEFINES.upper()): + if RawSection != DT.TAB_DEC_DEFINES.upper(): + self._LoggerError(ST.ERR_DECPARSE_DEFINE_SECNAME) + # + # Check user extension section + # + if RawSection.startswith(DT.TAB_USER_EXTENSIONS.upper()): + return self._UserExtentionSectionParser() + self._RawData.CurrentScope = [] + SectionNames = [] + ArchList = set() + for Item in GetSplitValueList(RawSection, DT.TAB_COMMA_SPLIT): + if Item == '': + self._LoggerError(ST.ERR_DECPARSE_SECTION_SUBEMPTY % self._RawData.CurrentLine) + + ItemList = GetSplitValueList(Item, DT.TAB_SPLIT) + # + # different types of PCD are permissible in one section + # + SectionName = ItemList[0] + if SectionName not in self._SectionParser: + self._LoggerError(ST.ERR_DECPARSE_SECTION_UNKNOW % SectionName) + if SectionName not in SectionNames: + SectionNames.append(SectionName) + # + # In DEC specification, all section headers have at most two part: + # SectionName.Arch except UserExtension + # + if len(ItemList) > 2: + self._LoggerError(ST.ERR_DECPARSE_SECTION_SUBTOOMANY % Item) + + if DT.TAB_PCDS_FEATURE_FLAG_NULL.upper() in SectionNames and len(SectionNames) > 1: + self._LoggerError(ST.ERR_DECPARSE_SECTION_FEATUREFLAG % DT.TAB_PCDS_FEATURE_FLAG_NULL) + # + # S1 is always Arch + # + if len(ItemList) > 1: + Str1 = ItemList[1] + if not IsValidArch(Str1): + self._LoggerError(ST.ERR_DECPARSE_ARCH) + else: + Str1 = 'COMMON' + ArchList.add(Str1) + + if [SectionName, Str1] not in self._RawData.CurrentScope: + self._RawData.CurrentScope.append([SectionName, Str1]) + # + # 'COMMON' must not be used with specific ARCHs at the same section + # + if 'COMMON' in ArchList and len(ArchList) > 1: + self._LoggerError(ST.ERR_DECPARSE_SECTION_COMMON) + if len(SectionNames) == 0: + self._LoggerError(ST.ERR_DECPARSE_SECTION_SUBEMPTY % self._RawData.CurrentLine) + if len(SectionNames) != 1: + for Sec in SectionNames: + if not Sec.startswith(DT.TAB_PCDS.upper()): + self._LoggerError(ST.ERR_DECPARSE_SECTION_NAME % str(SectionNames)) + + def GetDefineSectionMacro(self): + return self._Define.GetLocalMacro() + def GetDefineSectionObject(self): + return self._Define.GetDataObject() + def GetIncludeSectionObject(self): + return self._Include.GetDataObject() + def GetGuidSectionObject(self): + return self._Guid.GetGuidObject() + def GetProtocolSectionObject(self): + return self._Guid.GetProtocolObject() + def GetPpiSectionObject(self): + return self._Guid.GetPpiObject() + def GetLibraryClassSectionObject(self): + return self._LibClass.GetDataObject() + def GetPcdSectionObject(self): + return self._Pcd.GetDataObject() + def GetUserExtensionSectionObject(self): + return self._UserEx.GetDataObject() + def GetPackageSpecification(self): + return self._Define.GetDataObject().GetPackageSpecification() + def GetPackageName(self): + return self._Define.GetDataObject().GetPackageName() + def GetPackageGuid(self): + return self._Define.GetDataObject().GetPackageGuid() + def GetPackageVersion(self): + return self._Define.GetDataObject().GetPackageVersion() + def GetPackageUniFile(self): + return self._Define.GetDataObject().GetPackageUniFile() + def GetPrivateSections(self): + return self._Private diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/DecParserMisc.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/DecParserMisc.py new file mode 100755 index 00000000..4731c85c --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/DecParserMisc.py @@ -0,0 +1,364 @@ +## @file +# This file is used to define helper class and function for DEC parser +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +''' +DecParserMisc +''' + +## Import modules +# +import os +import Logger.Log as Logger +from Logger.ToolError import FILE_PARSE_FAILURE +from Logger import StringTable as ST +from Library.DataType import TAB_COMMENT_SPLIT +from Library.DataType import TAB_COMMENT_EDK1_SPLIT +from Library.ExpressionValidate import IsValidBareCString +from Library.ParserValidate import IsValidCFormatGuid +from Library.ExpressionValidate import IsValidFeatureFlagExp +from Library.ExpressionValidate import IsValidLogicalExpr +from Library.ExpressionValidate import IsValidStringTest +from Library.Misc import CheckGuidRegFormat + +TOOL_NAME = 'DecParser' +VERSION_PATTERN = '[0-9]+(\.[0-9]+)?' +CVAR_PATTERN = '[_a-zA-Z][a-zA-Z0-9_]*' +PCD_TOKEN_PATTERN = '(0[xX]0*[a-fA-F0-9]{1,8})|([0-9]+)' +MACRO_PATTERN = '[A-Z][_A-Z0-9]*' + +## FileContent +# Class to hold DEC file information +# +class FileContent: + def __init__(self, Filename, FileContent2): + self.Filename = Filename + self.PackagePath, self.PackageFile = os.path.split(Filename) + self.LineIndex = 0 + self.CurrentLine = '' + self.NextLine = '' + self.HeadComment = [] + self.TailComment = [] + self.CurrentScope = None + self.Content = FileContent2 + self.Macros = {} + self.FileLines = len(FileContent2) + + def GetNextLine(self): + if self.LineIndex >= self.FileLines: + return '' + Line = self.Content[self.LineIndex] + self.LineIndex += 1 + return Line + + def UndoNextLine(self): + if self.LineIndex > 0: + self.LineIndex -= 1 + + def ResetNext(self): + self.HeadComment = [] + self.TailComment = [] + self.NextLine = '' + + def SetNext(self, Line, HeadComment, TailComment): + self.NextLine = Line + self.HeadComment = HeadComment + self.TailComment = TailComment + + def IsEndOfFile(self): + return self.LineIndex >= self.FileLines + + +## StripRoot +# +# Strip root path +# +# @param Root: Root must be absolute path +# @param Path: Path to be stripped +# +def StripRoot(Root, Path): + OrigPath = Path + Root = os.path.normpath(Root) + Path = os.path.normpath(Path) + if not os.path.isabs(Root): + return OrigPath + if Path.startswith(Root): + Path = Path[len(Root):] + if Path and Path[0] == os.sep: + Path = Path[1:] + return Path + return OrigPath + +## CleanString +# +# Split comments in a string +# Remove spaces +# +# @param Line: The string to be cleaned +# @param CommentCharacter: Comment char, used to ignore comment content, +# default is DataType.TAB_COMMENT_SPLIT +# +def CleanString(Line, CommentCharacter=TAB_COMMENT_SPLIT, \ + AllowCppStyleComment=False): + # + # remove whitespace + # + Line = Line.strip() + # + # Replace EDK1's comment character + # + if AllowCppStyleComment: + Line = Line.replace(TAB_COMMENT_EDK1_SPLIT, CommentCharacter) + # + # separate comments and statements + # + Comment = '' + InQuote = False + for Index in range(0, len(Line)): + if Line[Index] == '"': + InQuote = not InQuote + continue + if Line[Index] == CommentCharacter and not InQuote: + Comment = Line[Index:].strip() + Line = Line[0:Index].strip() + break + + return Line, Comment + + +## IsValidNumValUint8 +# +# Check if Token is NumValUint8: ::= {} {} {} +# +# @param Token: Token to be checked +# +def IsValidNumValUint8(Token): + Valid = True + Cause = "" + TokenValue = None + Token = Token.strip() + if Token.lower().startswith('0x'): + Base = 16 + else: + Base = 10 + try: + TokenValue = int(Token, Base) + except BaseException: + Valid, Cause = IsValidLogicalExpr(Token, True) + if Cause: + pass + if not Valid: + return False + if TokenValue and (TokenValue < 0 or TokenValue > 0xFF): + return False + else: + return True + +## IsValidNList +# +# Check if Value has the format of ["," ]{0,} +# ::= {} {} {} +# +# @param Value: Value to be checked +# +def IsValidNList(Value): + Par = ParserHelper(Value) + if Par.End(): + return False + while not Par.End(): + Token = Par.GetToken(',') + if not IsValidNumValUint8(Token): + return False + if Par.Expect(','): + if Par.End(): + return False + continue + else: + break + return Par.End() + +## IsValidCArray +# +# check Array is valid +# +# @param Array: The input Array +# +def IsValidCArray(Array): + Par = ParserHelper(Array) + if not Par.Expect('{'): + return False + if Par.End(): + return False + while not Par.End(): + Token = Par.GetToken(',}') + # + # ShortNum, UINT8, Expression + # + if not IsValidNumValUint8(Token): + return False + if Par.Expect(','): + if Par.End(): + return False + continue + elif Par.Expect('}'): + # + # End of C array + # + break + else: + return False + return Par.End() + +## IsValidPcdDatum +# +# check PcdDatum is valid +# +# @param Type: The pcd Type +# @param Value: The pcd Value +# +def IsValidPcdDatum(Type, Value): + if not Value: + return False, ST.ERR_DECPARSE_PCD_VALUE_EMPTY + Valid = True + Cause = "" + if Type not in ["UINT8", "UINT16", "UINT32", "UINT64", "VOID*", "BOOLEAN"]: + return False, ST.ERR_DECPARSE_PCD_TYPE + if Type == "VOID*": + if not ((Value.startswith('L"') or Value.startswith('"') and \ + Value.endswith('"')) + or (IsValidCArray(Value)) or (IsValidCFormatGuid(Value)) \ + or (IsValidNList(Value)) or (CheckGuidRegFormat(Value)) + ): + return False, ST.ERR_DECPARSE_PCD_VOID % (Value, Type) + RealString = Value[Value.find('"') + 1 :-1] + if RealString: + if not IsValidBareCString(RealString): + return False, ST.ERR_DECPARSE_PCD_VOID % (Value, Type) + elif Type == 'BOOLEAN': + if Value in ['TRUE', 'FALSE', 'true', 'false', 'True', 'False', + '0x1', '0x01', '1', '0x0', '0x00', '0']: + return True, "" + Valid, Cause = IsValidStringTest(Value, True) + if not Valid: + Valid, Cause = IsValidFeatureFlagExp(Value, True) + if not Valid: + return False, Cause + else: + if Value and (Value[0] == '-' or Value[0] == '+'): + return False, ST.ERR_DECPARSE_PCD_INT_NEGTIVE % (Value, Type) + try: + StrVal = Value + if Value and not Value.startswith('0x') \ + and not Value.startswith('0X'): + Value = Value.lstrip('0') + if not Value: + return True, "" + Value = int(Value, 0) + MAX_VAL_TYPE = {"BOOLEAN": 0x01, 'UINT8': 0xFF, 'UINT16': 0xFFFF, 'UINT32': 0xFFFFFFFF, + 'UINT64': 0xFFFFFFFFFFFFFFFF} + if Value > MAX_VAL_TYPE[Type]: + return False, ST.ERR_DECPARSE_PCD_INT_EXCEED % (StrVal, Type) + except BaseException: + Valid, Cause = IsValidLogicalExpr(Value, True) + if not Valid: + return False, Cause + + return True, "" + +## ParserHelper +# +class ParserHelper: + def __init__(self, String, File=''): + self._String = String + self._StrLen = len(String) + self._Index = 0 + self._File = File + + ## End + # + # End + # + def End(self): + self.__SkipWhitespace() + return self._Index >= self._StrLen + + ## __SkipWhitespace + # + # Skip whitespace + # + def __SkipWhitespace(self): + for Char in self._String[self._Index:]: + if Char not in ' \t': + break + self._Index += 1 + + ## Expect + # + # Expect char in string + # + # @param ExpectChar: char expected in index of string + # + def Expect(self, ExpectChar): + self.__SkipWhitespace() + for Char in self._String[self._Index:]: + if Char != ExpectChar: + return False + else: + self._Index += 1 + return True + # + # Index out of bound of String + # + return False + + ## GetToken + # + # Get token until encounter StopChar, front whitespace is consumed + # + # @param StopChar: Get token until encounter char in StopChar + # @param StkipPair: Only can be ' or ", StopChar in SkipPair are skipped + # + def GetToken(self, StopChar='.,|\t ', SkipPair='"'): + self.__SkipWhitespace() + PreIndex = self._Index + InQuote = False + LastChar = '' + for Char in self._String[self._Index:]: + if Char == SkipPair and LastChar != '\\': + InQuote = not InQuote + if Char in StopChar and not InQuote: + break + self._Index += 1 + if Char == '\\' and LastChar == '\\': + LastChar = '' + else: + LastChar = Char + return self._String[PreIndex:self._Index] + + ## AssertChar + # + # Assert char at current index of string is AssertChar, or will report + # error message + # + # @param AssertChar: AssertChar + # @param ErrorString: ErrorString + # @param ErrorLineNum: ErrorLineNum + # + def AssertChar(self, AssertChar, ErrorString, ErrorLineNum): + if not self.Expect(AssertChar): + Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._File, + Line=ErrorLineNum, ExtraData=ErrorString) + + ## AssertEnd + # + # @param ErrorString: ErrorString + # @param ErrorLineNum: ErrorLineNum + # + def AssertEnd(self, ErrorString, ErrorLineNum): + self.__SkipWhitespace() + if self._Index != self._StrLen: + Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._File, + Line=ErrorLineNum, ExtraData=ErrorString) diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfAsBuiltProcess.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfAsBuiltProcess.py new file mode 100755 index 00000000..0f9e9ad3 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfAsBuiltProcess.py @@ -0,0 +1,283 @@ +## @file +# This file is used to provide method for process AsBuilt INF file. It will consumed by InfParser +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +''' +InfAsBuiltProcess +''' +## Import modules +# + +import os +import re +from Library import GlobalData +import Logger.Log as Logger +from Logger import StringTable as ST +from Logger import ToolError + +from Library.StringUtils import GetSplitValueList +from Library.Misc import GetHelpStringByRemoveHashKey +from Library.Misc import ValidFile +from Library.Misc import ProcessLineExtender +from Library.ParserValidate import IsValidPath +from Library.Parsing import MacroParser +from Parser.InfParserMisc import InfExpandMacro + +from Library import DataType as DT + +## GetLibInstanceInfo +# +# Get the information from Library Instance INF file. +# +# @param string. A string start with # and followed by INF file path +# @param WorkSpace. The WorkSpace directory used to combined with INF file path. +# +# @return GUID, Version +def GetLibInstanceInfo(String, WorkSpace, LineNo, CurrentInfFileName): + + FileGuidString = "" + VerString = "" + + OriginalString = String + String = String.strip() + if not String: + return None, None + # + # Remove "#" characters at the beginning + # + String = GetHelpStringByRemoveHashKey(String) + String = String.strip() + + # + # To deal with library instance specified by GUID and version + # + RegFormatGuidPattern = re.compile("\s*([0-9a-fA-F]){8}-" + "([0-9a-fA-F]){4}-" + "([0-9a-fA-F]){4}-" + "([0-9a-fA-F]){4}-" + "([0-9a-fA-F]){12}\s*") + VersionPattern = re.compile('[\t\s]*\d+(\.\d+)?[\t\s]*') + GuidMatchedObj = RegFormatGuidPattern.search(String) + + if String.upper().startswith('GUID') and GuidMatchedObj and 'Version' in String: + VersionStr = String[String.upper().find('VERSION') + 8:] + VersionMatchedObj = VersionPattern.search(VersionStr) + if VersionMatchedObj: + Guid = GuidMatchedObj.group().strip() + Version = VersionMatchedObj.group().strip() + return Guid, Version + + # + # To deal with library instance specified by file name + # + FileLinesList = GetFileLineContent(String, WorkSpace, LineNo, OriginalString) + + + ReFindFileGuidPattern = re.compile("^\s*FILE_GUID\s*=.*$") + ReFindVerStringPattern = re.compile("^\s*VERSION_STRING\s*=.*$") + + for Line in FileLinesList: + if ReFindFileGuidPattern.match(Line): + FileGuidString = Line + if ReFindVerStringPattern.match(Line): + VerString = Line + + if FileGuidString: + FileGuidString = GetSplitValueList(FileGuidString, '=', 1)[1] + if VerString: + VerString = GetSplitValueList(VerString, '=', 1)[1] + + return FileGuidString, VerString + +## GetPackageListInfo +# +# Get the package information from INF file. +# +# @param string. A string start with # and followed by INF file path +# @param WorkSpace. The WorkSpace directory used to combined with INF file path. +# +# @return GUID, Version +def GetPackageListInfo(FileNameString, WorkSpace, LineNo): + PackageInfoList = [] + DefineSectionMacros = {} + PackageSectionMacros = {} + + FileLinesList = GetFileLineContent(FileNameString, WorkSpace, LineNo, '') + + RePackageHeader = re.compile('^\s*\[Packages.*\].*$') + ReDefineHeader = re.compile('^\s*\[Defines].*$') + + PackageHederFlag = False + DefineHeaderFlag = False + LineNo = -1 + for Line in FileLinesList: + LineNo += 1 + Line = Line.strip() + + if Line.startswith('['): + PackageHederFlag = False + DefineHeaderFlag = False + + if Line.startswith("#"): + continue + + if not Line: + continue + + # + # Found [Packages] section + # + if RePackageHeader.match(Line): + PackageHederFlag = True + continue + + # + # Found [Define] section + # + if ReDefineHeader.match(Line): + DefineHeaderFlag = True + continue + + if DefineHeaderFlag: + # + # Find Macro + # + Name, Value = MacroParser((Line, LineNo), + FileNameString, + DT.MODEL_META_DATA_HEADER, + DefineSectionMacros) + + if Name is not None: + DefineSectionMacros[Name] = Value + continue + + if PackageHederFlag: + + # + # Find Macro + # + Name, Value = MacroParser((Line, LineNo), + FileNameString, + DT.MODEL_META_DATA_PACKAGE, + DefineSectionMacros) + if Name is not None: + PackageSectionMacros[Name] = Value + continue + + # + # Replace with Local section Macro and [Defines] section Macro. + # + Line = InfExpandMacro(Line, (FileNameString, Line, LineNo), DefineSectionMacros, PackageSectionMacros, True) + + Line = GetSplitValueList(Line, "#", 1)[0] + Line = GetSplitValueList(Line, "|", 1)[0] + PackageInfoList.append(Line) + + return PackageInfoList + +def GetFileLineContent(FileName, WorkSpace, LineNo, OriginalString): + + if not LineNo: + LineNo = -1 + + # + # Validate file name exist. + # + FullFileName = os.path.normpath(os.path.realpath(os.path.join(WorkSpace, FileName))) + if not (ValidFile(FullFileName)): + return [] + + # + # Validate file exist/format. + # + if not IsValidPath(FileName, WorkSpace): + return [] + + FileLinesList = [] + + try: + FullFileName = FullFileName.replace('\\', '/') + Inputfile = open(FullFileName, "r") + try: + FileLinesList = Inputfile.readlines() + except BaseException: + Logger.Error("InfParser", ToolError.FILE_READ_FAILURE, ST.ERR_FILE_OPEN_FAILURE, File=FullFileName) + finally: + Inputfile.close() + except BaseException: + Logger.Error("InfParser", + ToolError.FILE_READ_FAILURE, + ST.ERR_FILE_OPEN_FAILURE, + File=FullFileName) + + FileLinesList = ProcessLineExtender(FileLinesList) + + return FileLinesList + +## +# Get all INF files from current workspace +# +# +def GetInfsFromWorkSpace(WorkSpace): + InfFiles = [] + for top, dirs, files in os.walk(WorkSpace): + dirs = dirs # just for pylint + for File in files: + if File.upper().endswith(".INF"): + InfFiles.append(os.path.join(top, File)) + + return InfFiles + +## +# Get GUID and version from library instance file +# +# +def GetGuidVerFormLibInstance(Guid, Version, WorkSpace, CurrentInfFileName): + for InfFile in GetInfsFromWorkSpace(WorkSpace): + try: + if InfFile.strip().upper() == CurrentInfFileName.strip().upper(): + continue + InfFile = InfFile.replace('\\', '/') + if InfFile not in GlobalData.gLIBINSTANCEDICT: + InfFileObj = open(InfFile, "r") + GlobalData.gLIBINSTANCEDICT[InfFile] = InfFileObj + else: + InfFileObj = GlobalData.gLIBINSTANCEDICT[InfFile] + + except BaseException: + Logger.Error("InfParser", + ToolError.FILE_READ_FAILURE, + ST.ERR_FILE_OPEN_FAILURE, + File=InfFile) + try: + FileLinesList = InfFileObj.readlines() + FileLinesList = ProcessLineExtender(FileLinesList) + + ReFindFileGuidPattern = re.compile("^\s*FILE_GUID\s*=.*$") + ReFindVerStringPattern = re.compile("^\s*VERSION_STRING\s*=.*$") + + for Line in FileLinesList: + if ReFindFileGuidPattern.match(Line): + FileGuidString = Line + if ReFindVerStringPattern.match(Line): + VerString = Line + + if FileGuidString: + FileGuidString = GetSplitValueList(FileGuidString, '=', 1)[1] + if VerString: + VerString = GetSplitValueList(VerString, '=', 1)[1] + + if FileGuidString.strip().upper() == Guid.upper() and \ + VerString.strip().upper() == Version.upper(): + return Guid, Version + + except BaseException: + Logger.Error("InfParser", ToolError.FILE_READ_FAILURE, ST.ERR_FILE_OPEN_FAILURE, File=InfFile) + finally: + InfFileObj.close() + + return '', '' + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfBinarySectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfBinarySectionParser.py new file mode 100755 index 00000000..b3ee7084 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfBinarySectionParser.py @@ -0,0 +1,226 @@ +## @file +# This file contained the parser for [Binaries] sections in INF file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +''' +InfBinarySectionParser +''' +## +# Import Modules +# + +import Logger.Log as Logger +from Logger import StringTable as ST +from Logger.ToolError import FORMAT_INVALID +from Parser.InfParserMisc import InfExpandMacro +from Library import DataType as DT +from Library.Parsing import MacroParser +from Library.Misc import GetSplitValueList +from Object.Parser.InfCommonObject import InfLineCommentObject +from Object.Parser.InfCommonObject import CurrentLine +from Parser.InfParserMisc import InfParserSectionRoot + +class InfBinarySectionParser(InfParserSectionRoot): + ## InfBinaryParser + # + # + def InfBinaryParser(self, SectionString, InfSectionObject, FileName): + # + # Macro defined in this section + # + SectionMacros = {} + ValueList = [] + # + # For UI (UI, SEC_UI, UNI_UI) binaries + # One and only one UI section can be included + # + UiBinaryList = [] + # + # For Version (VER, SEC_VER, UNI_VER). + # One and only one VER section on be included + # + VerBinaryList = [] + # + # For other common type binaries + # + ComBinaryList = [] + + StillCommentFalg = False + HeaderComments = [] + LineComment = None + + AllSectionContent = '' + # + # Parse section content + # + for Line in SectionString: + BinLineContent = Line[0] + BinLineNo = Line[1] + + if BinLineContent.strip() == '': + continue + + CurrentLineObj = CurrentLine() + CurrentLineObj.FileName = FileName + CurrentLineObj.LineString = BinLineContent + CurrentLineObj.LineNo = BinLineNo + # + # Found Header Comments + # + if BinLineContent.strip().startswith(DT.TAB_COMMENT_SPLIT): + # + # Last line is comments, and this line go on. + # + if StillCommentFalg: + HeaderComments.append(Line) + AllSectionContent += BinLineContent + DT.END_OF_LINE + continue + # + # First time encounter comment + # + else: + # + # Clear original data + # + HeaderComments = [] + HeaderComments.append(Line) + AllSectionContent += BinLineContent + DT.END_OF_LINE + StillCommentFalg = True + continue + else: + StillCommentFalg = False + + if len(HeaderComments) >= 1: + LineComment = InfLineCommentObject() + LineCommentContent = '' + for Item in HeaderComments: + LineCommentContent += Item[0] + DT.END_OF_LINE + LineComment.SetHeaderComments(LineCommentContent) + + # + # Find Tail comment. + # + if BinLineContent.find(DT.TAB_COMMENT_SPLIT) > -1: + TailComments = BinLineContent[BinLineContent.find(DT.TAB_COMMENT_SPLIT):] + BinLineContent = BinLineContent[:BinLineContent.find(DT.TAB_COMMENT_SPLIT)] + if LineComment is None: + LineComment = InfLineCommentObject() + LineComment.SetTailComments(TailComments) + + # + # Find Macro + # + MacroDef = MacroParser((BinLineContent, BinLineNo), + FileName, + DT.MODEL_EFI_BINARY_FILE, + self.FileLocalMacros) + if MacroDef[0] is not None: + SectionMacros[MacroDef[0]] = MacroDef[1] + LineComment = None + HeaderComments = [] + continue + + # + # Replace with Local section Macro and [Defines] section Macro. + # + LineContent = InfExpandMacro(BinLineContent, + (FileName, BinLineContent, BinLineNo), + self.FileLocalMacros, + SectionMacros, True) + + AllSectionContent += LineContent + DT.END_OF_LINE + TokenList = GetSplitValueList(LineContent, DT.TAB_VALUE_SPLIT, 1) + ValueList[0:len(TokenList)] = TokenList + + # + # Should equal to UI/SEC_UI/UNI_UI + # + ValueList[0] = ValueList[0].strip() + if ValueList[0] == DT.BINARY_FILE_TYPE_UNI_UI or \ + ValueList[0] == DT.BINARY_FILE_TYPE_SEC_UI or \ + ValueList[0] == DT.BINARY_FILE_TYPE_UI: + if len(ValueList) == 2: + TokenList = GetSplitValueList(ValueList[1], + DT.TAB_VALUE_SPLIT, + 2) + NewValueList = [] + NewValueList.append(ValueList[0]) + for Item in TokenList: + NewValueList.append(Item) + UiBinaryList.append((NewValueList, + LineComment, + CurrentLineObj)) + # + # Should equal to VER/SEC_VER/UNI_VER + # + elif ValueList[0] == DT.BINARY_FILE_TYPE_UNI_VER or \ + ValueList[0] == DT.BINARY_FILE_TYPE_SEC_VER or \ + ValueList[0] == DT.BINARY_FILE_TYPE_VER: + if len(ValueList) == 2: + TokenList = GetSplitValueList(ValueList[1], + DT.TAB_VALUE_SPLIT, + 2) + NewValueList = [] + NewValueList.append(ValueList[0]) + for Item in TokenList: + NewValueList.append(Item) + VerBinaryList.append((NewValueList, + LineComment, + CurrentLineObj)) + else: + if len(ValueList) == 2: + if ValueList[0].strip() == 'SUBTYPE_GUID': + TokenList = GetSplitValueList(ValueList[1], + DT.TAB_VALUE_SPLIT, + 5) + else: + TokenList = GetSplitValueList(ValueList[1], + DT.TAB_VALUE_SPLIT, + 4) + + NewValueList = [] + NewValueList.append(ValueList[0]) + for Item in TokenList: + NewValueList.append(Item) + ComBinaryList.append((NewValueList, + LineComment, + CurrentLineObj)) + elif len(ValueList) == 1: + NewValueList = [] + NewValueList.append(ValueList[0]) + ComBinaryList.append((NewValueList, + LineComment, + CurrentLineObj)) + + + + + ValueList = [] + LineComment = None + TailComments = '' + HeaderComments = [] + continue + + # + # Current section archs + # + ArchList = [] + for Item in self.LastSectionHeaderContent: + if Item[1] not in ArchList: + ArchList.append(Item[1]) + InfSectionObject.SetSupArchList(Item[1]) + + InfSectionObject.SetAllContent(AllSectionContent) + if not InfSectionObject.SetBinary(UiBinaryList, + VerBinaryList, + ComBinaryList, + ArchList): + Logger.Error('InfParser', + FORMAT_INVALID, + ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR%("[Binaries]"), + File=FileName, + Line=Item[3]) + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfBuildOptionSectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfBuildOptionSectionParser.py new file mode 100755 index 00000000..3f74ff0c --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfBuildOptionSectionParser.py @@ -0,0 +1,212 @@ +## @file +# This file contained the parser for BuildOption sections in INF file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +InfBuildOptionSectionParser +''' +## +# Import Modules +# +from Library import DataType as DT +from Library import GlobalData +import Logger.Log as Logger +from Logger import StringTable as ST +from Logger.ToolError import FORMAT_INVALID +from Parser.InfParserMisc import InfExpandMacro +from Library.Misc import GetSplitValueList +from Parser.InfParserMisc import IsAsBuildOptionInfo +from Library.Misc import GetHelpStringByRemoveHashKey +from Library.ParserValidate import IsValidFamily +from Library.ParserValidate import IsValidBuildOptionName +from Parser.InfParserMisc import InfParserSectionRoot + +class InfBuildOptionSectionParser(InfParserSectionRoot): + ## InfBuildOptionParser + # + # + def InfBuildOptionParser(self, SectionString, InfSectionObject, FileName): + + BuildOptionList = [] + SectionContent = '' + + if not GlobalData.gIS_BINARY_INF: + ValueList = [] + LineNo = 0 + + for Line in SectionString: + LineContent = Line[0] + LineNo = Line[1] + TailComments = '' + ReplaceFlag = False + + if LineContent.strip() == '': + SectionContent += LineContent + DT.END_OF_LINE + continue + # + # Found Comment + # + if LineContent.strip().startswith(DT.TAB_COMMENT_SPLIT): + SectionContent += LineContent + DT.END_OF_LINE + continue + + # + # Find Tail comment. + # + if LineContent.find(DT.TAB_COMMENT_SPLIT) > -1: + TailComments = LineContent[LineContent.find(DT.TAB_COMMENT_SPLIT):] + LineContent = LineContent[:LineContent.find(DT.TAB_COMMENT_SPLIT)] + + TokenList = GetSplitValueList(LineContent, DT.TAB_DEQUAL_SPLIT, 1) + if len(TokenList) == 2: + # + # "Replace" type build option + # + TokenList.append('True') + ReplaceFlag = True + else: + TokenList = GetSplitValueList(LineContent, DT.TAB_EQUAL_SPLIT, 1) + # + # "Append" type build option + # + if len(TokenList) == 2: + TokenList.append('False') + else: + Logger.Error('InfParser', + FORMAT_INVALID, + ST.ERR_INF_PARSER_BUILD_OPTION_FORMAT_INVALID, + ExtraData=LineContent, + File=FileName, + Line=LineNo) + + ValueList[0:len(TokenList)] = TokenList + + # + # Replace with [Defines] section Macro + # + ValueList[0] = InfExpandMacro(ValueList[0], (FileName, LineContent, LineNo), + self.FileLocalMacros, None) + ValueList[1] = InfExpandMacro(ValueList[1], (FileName, LineContent, LineNo), + self.FileLocalMacros, None, True) + EqualString = '' + if not ReplaceFlag: + EqualString = ' = ' + else: + EqualString = ' == ' + + SectionContent += ValueList[0] + EqualString + ValueList[1] + TailComments + DT.END_OF_LINE + + Family = GetSplitValueList(ValueList[0], DT.TAB_COLON_SPLIT, 1) + if len(Family) == 2: + if not IsValidFamily(Family[0]): + Logger.Error('InfParser', + FORMAT_INVALID, + ST.ERR_INF_PARSER_BUILD_OPTION_FORMAT_INVALID, + ExtraData=LineContent, + File=FileName, + Line=LineNo) + if not IsValidBuildOptionName(Family[1]): + Logger.Error('InfParser', + FORMAT_INVALID, + ST.ERR_INF_PARSER_BUILD_OPTION_FORMAT_INVALID, + ExtraData=LineContent, + File=FileName, + Line=LineNo) + if len(Family) == 1: + if not IsValidBuildOptionName(Family[0]): + Logger.Error('InfParser', + FORMAT_INVALID, + ST.ERR_INF_PARSER_BUILD_OPTION_FORMAT_INVALID, + ExtraData=LineContent, + File=FileName, + Line=LineNo) + + BuildOptionList.append(ValueList) + ValueList = [] + continue + else: + BuildOptionList = InfAsBuiltBuildOptionParser(SectionString, FileName) + + # + # Current section archs + # + ArchList = [] + LastItem = '' + for Item in self.LastSectionHeaderContent: + LastItem = Item + if not (Item[1] == '' or Item[1] == '') and Item[1] not in ArchList: + ArchList.append(Item[1]) + InfSectionObject.SetSupArchList(Item[1]) + + InfSectionObject.SetAllContent(SectionContent) + if not InfSectionObject.SetBuildOptions(BuildOptionList, ArchList, SectionContent): + Logger.Error('InfParser', + FORMAT_INVALID, + ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR%("[BuilOptions]"), + File=FileName, + Line=LastItem[3]) + +## InfBuildOptionParser +# +# +def InfAsBuiltBuildOptionParser(SectionString, FileName): + BuildOptionList = [] + # + # AsBuild Binary INF file. + # + AsBuildOptionFlag = False + BuildOptionItem = [] + Count = 0 + for Line in SectionString: + Count += 1 + LineContent = Line[0] + LineNo = Line[1] + + # + # The last line + # + if len(SectionString) == Count: + if LineContent.strip().startswith("##") and AsBuildOptionFlag: + BuildOptionList.append(BuildOptionItem) + BuildOptionList.append([GetHelpStringByRemoveHashKey(LineContent)]) + elif LineContent.strip().startswith("#") and AsBuildOptionFlag: + BuildOptionInfo = GetHelpStringByRemoveHashKey(LineContent) + BuildOptionItem.append(BuildOptionInfo) + BuildOptionList.append(BuildOptionItem) + else: + if len(BuildOptionItem) > 0: + BuildOptionList.append(BuildOptionItem) + + break + + if LineContent.strip() == '': + AsBuildOptionFlag = False + continue + + if LineContent.strip().startswith("##") and AsBuildOptionFlag: + if len(BuildOptionItem) > 0: + BuildOptionList.append(BuildOptionItem) + + BuildOptionItem = [] + + if not LineContent.strip().startswith("#"): + Logger.Error('InfParser', + FORMAT_INVALID, + ST.ERR_BO_CONTATIN_ASBUILD_AND_COMMON, + File=FileName, + Line=LineNo, + ExtraData=LineContent) + + if IsAsBuildOptionInfo(LineContent): + AsBuildOptionFlag = True + continue + + if AsBuildOptionFlag: + BuildOptionInfo = GetHelpStringByRemoveHashKey(LineContent) + BuildOptionItem.append(BuildOptionInfo) + + return BuildOptionList diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfDefineSectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfDefineSectionParser.py new file mode 100755 index 00000000..2117da1c --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfDefineSectionParser.py @@ -0,0 +1,191 @@ +## @file +# This file contained the parser for define sections in INF file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +InfDefineSectionParser +''' +## +# Import Modules +# +import re + +from Library import DataType as DT +from Library import GlobalData +from Library.Parsing import MacroParser +from Library.Misc import GetSplitValueList +from Library.ParserValidate import IsValidArch +from Object.Parser.InfCommonObject import InfLineCommentObject +from Object.Parser.InfDefineObject import InfDefMember +from Parser.InfParserMisc import InfExpandMacro +from Object.Parser.InfMisc import ErrorInInf +from Logger import StringTable as ST +from Parser.InfParserMisc import InfParserSectionRoot + +## __GetValidateArchList +# +# +def GetValidateArchList(LineContent): + + TempArch = '' + ArchList = [] + ValidateAcrhPatten = re.compile(r"^\s*#\s*VALID_ARCHITECTURES\s*=\s*.*$", re.DOTALL) + + if ValidateAcrhPatten.match(LineContent): + TempArch = GetSplitValueList(LineContent, DT.TAB_EQUAL_SPLIT, 1)[1] + + TempArch = GetSplitValueList(TempArch, '(', 1)[0] + + ArchList = re.split('\s+', TempArch) + NewArchList = [] + for Arch in ArchList: + if IsValidArch(Arch): + NewArchList.append(Arch) + + ArchList = NewArchList + + return ArchList + +class InfDefinSectionParser(InfParserSectionRoot): + def InfDefineParser(self, SectionString, InfSectionObject, FileName, SectionComment): + + if SectionComment: + pass + # + # Parser Defines section content and fill self._ContentList dict. + # + StillCommentFalg = False + HeaderComments = [] + SectionContent = '' + ArchList = [] + _ContentList = [] + _ValueList = [] + # + # Add WORKSPACE to global Marco dict. + # + self.FileLocalMacros['WORKSPACE'] = GlobalData.gWORKSPACE + + for Line in SectionString: + LineContent = Line[0] + LineNo = Line[1] + TailComments = '' + LineComment = None + + LineInfo = ['', -1, ''] + LineInfo[0] = FileName + LineInfo[1] = LineNo + LineInfo[2] = LineContent + + if LineContent.strip() == '': + continue + # + # The first time encountered VALIDATE_ARCHITECHERS will be considered as support arch list. + # + if not ArchList: + ArchList = GetValidateArchList(LineContent) + + # + # Parser Comment + # + if LineContent.strip().startswith(DT.TAB_COMMENT_SPLIT): + # + # Last line is comments, and this line go on. + # + if StillCommentFalg: + HeaderComments.append(Line) + SectionContent += LineContent + DT.END_OF_LINE + continue + # + # First time encounter comment + # + else: + # + # Clear original data + # + HeaderComments = [] + HeaderComments.append(Line) + StillCommentFalg = True + SectionContent += LineContent + DT.END_OF_LINE + continue + else: + StillCommentFalg = False + + if len(HeaderComments) >= 1: + LineComment = InfLineCommentObject() + LineCommentContent = '' + for Item in HeaderComments: + LineCommentContent += Item[0] + DT.END_OF_LINE + LineComment.SetHeaderComments(LineCommentContent) + + # + # Find Tail comment. + # + if LineContent.find(DT.TAB_COMMENT_SPLIT) > -1: + TailComments = LineContent[LineContent.find(DT.TAB_COMMENT_SPLIT):] + LineContent = LineContent[:LineContent.find(DT.TAB_COMMENT_SPLIT)] + if LineComment is None: + LineComment = InfLineCommentObject() + LineComment.SetTailComments(TailComments) + + # + # Find Macro + # + Name, Value = MacroParser((LineContent, LineNo), + FileName, + DT.MODEL_META_DATA_HEADER, + self.FileLocalMacros) + if Name is not None: + self.FileLocalMacros[Name] = Value + continue + + # + # Replace with [Defines] section Macro + # + LineContent = InfExpandMacro(LineContent, + (FileName, LineContent, LineNo), + self.FileLocalMacros, + None, True) + + SectionContent += LineContent + DT.END_OF_LINE + + TokenList = GetSplitValueList(LineContent, DT.TAB_EQUAL_SPLIT, 1) + if len(TokenList) < 2: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_NO_VALUE, + LineInfo=LineInfo) + _ValueList[0:len(TokenList)] = TokenList + if not _ValueList[0]: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_NO_NAME, + LineInfo=LineInfo) + if not _ValueList[1]: + ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_NO_VALUE, + LineInfo=LineInfo) + + Name, Value = _ValueList[0], _ValueList[1] + + InfDefMemberObj = InfDefMember(Name, Value) + if (LineComment is not None): + InfDefMemberObj.Comments.SetHeaderComments(LineComment.GetHeaderComments()) + InfDefMemberObj.Comments.SetTailComments(LineComment.GetTailComments()) + + InfDefMemberObj.CurrentLine.SetFileName(self.FullPath) + InfDefMemberObj.CurrentLine.SetLineString(LineContent) + InfDefMemberObj.CurrentLine.SetLineNo(LineNo) + + _ContentList.append(InfDefMemberObj) + HeaderComments = [] + TailComments = '' + + # + # Current Define section archs + # + if not ArchList: + ArchList = ['COMMON'] + + InfSectionObject.SetAllContent(SectionContent) + + InfSectionObject.SetDefines(_ContentList, Arch=ArchList) + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfDepexSectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfDepexSectionParser.py new file mode 100755 index 00000000..86634b32 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfDepexSectionParser.py @@ -0,0 +1,98 @@ +## @file +# This file contained the parser for [Depex] sections in INF file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +''' +InfDepexSectionParser +''' +## +# Import Modules +# +import re +import Logger.Log as Logger +from Logger import StringTable as ST +from Logger.ToolError import FORMAT_INVALID +from Parser.InfParserMisc import InfExpandMacro +from Library import DataType as DT +from Library.Misc import GetSplitValueList +from Parser.InfParserMisc import InfParserSectionRoot + +class InfDepexSectionParser(InfParserSectionRoot): + ## InfDepexParser + # + # For now, only separate Depex String and comments. + # Have two types of section header. + # 1. [Depex.Arch.ModuleType, ...] + # 2. [Depex.Arch|FFE, ...] + # + def InfDepexParser(self, SectionString, InfSectionObject, FileName): + DepexContent = [] + DepexComment = [] + ValueList = [] + # + # Parse section content + # + for Line in SectionString: + LineContent = Line[0] + LineNo = Line[1] + + # + # Found comment + # + if LineContent.strip().startswith(DT.TAB_COMMENT_SPLIT): + DepexComment.append((LineContent, LineNo)) + continue + # + # Replace with [Defines] section Macro + # + LineContent = InfExpandMacro(LineContent, + (FileName, LineContent, Line[1]), + self.FileLocalMacros, + None, True) + + CommentCount = LineContent.find(DT.TAB_COMMENT_SPLIT) + + if CommentCount > -1: + DepexComment.append((LineContent[CommentCount:], LineNo)) + LineContent = LineContent[:CommentCount-1] + + + CommentCount = -1 + DepexContent.append((LineContent, LineNo)) + + TokenList = GetSplitValueList(LineContent, DT.TAB_COMMENT_SPLIT) + ValueList[0:len(TokenList)] = TokenList + + # + # Current section archs + # + KeyList = [] + LastItem = '' + for Item in self.LastSectionHeaderContent: + LastItem = Item + if (Item[1], Item[2], Item[3]) not in KeyList: + KeyList.append((Item[1], Item[2], Item[3])) + + NewCommentList = [] + FormatCommentLn = -1 + ReFormatComment = re.compile(r"""#(?:\s*)\[(.*?)\](?:.*)""", re.DOTALL) + for CommentItem in DepexComment: + CommentContent = CommentItem[0] + if ReFormatComment.match(CommentContent) is not None: + FormatCommentLn = CommentItem[1] + 1 + continue + + if CommentItem[1] != FormatCommentLn: + NewCommentList.append(CommentContent) + else: + FormatCommentLn = CommentItem[1] + 1 + + if not InfSectionObject.SetDepex(DepexContent, KeyList = KeyList, CommentList = NewCommentList): + Logger.Error('InfParser', + FORMAT_INVALID, + ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR%("[Depex]"), + File=FileName, + Line=LastItem[3]) diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfGuidPpiProtocolSectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfGuidPpiProtocolSectionParser.py new file mode 100755 index 00000000..2716f8d7 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfGuidPpiProtocolSectionParser.py @@ -0,0 +1,368 @@ +## @file +# This file contained the parser for [Guids], [Ppis], [Protocols] sections in INF file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +''' +InfGuidPpiProtocolSectionParser +''' +## +# Import Modules +# + +import Logger.Log as Logger +from Logger import StringTable as ST +from Logger.ToolError import FORMAT_INVALID +from Parser.InfParserMisc import InfExpandMacro +from Library import DataType as DT +from Library import GlobalData +from Library.Parsing import MacroParser +from Library.Misc import GetSplitValueList +from Library.ParserValidate import IsValidIdString +from Library.ParserValidate import IsValidUserId +from Library.ParserValidate import IsValidArch +from Parser.InfParserMisc import InfParserSectionRoot + +class InfGuidPpiProtocolSectionParser(InfParserSectionRoot): + ## InfGuidParser + # + # + def InfGuidParser(self, SectionString, InfSectionObject, FileName): + # + # Macro defined in this section + # + SectionMacros = {} + ValueList = [] + GuidList = [] + CommentsList = [] + CurrentLineVar = None + # + # Parse section content + # + for Line in SectionString: + LineContent = Line[0] + LineNo = Line[1] + + if LineContent.strip() == '': + CommentsList = [] + continue + + if LineContent.strip().startswith(DT.TAB_COMMENT_SPLIT): + CommentsList.append(Line) + continue + else: + # + # Encounter a GUID entry + # + if LineContent.find(DT.TAB_COMMENT_SPLIT) > -1: + CommentsList.append(( + LineContent[LineContent.find(DT.TAB_COMMENT_SPLIT):], + LineNo)) + LineContent = \ + LineContent[:LineContent.find(DT.TAB_COMMENT_SPLIT)] + + if LineContent != '': + # + # Find Macro + # + Name, Value = MacroParser((LineContent, LineNo), + FileName, + DT.MODEL_EFI_GUID, + self.FileLocalMacros) + if Name is not None: + SectionMacros[Name] = Value + CommentsList = [] + ValueList = [] + continue + + TokenList = GetSplitValueList(LineContent, DT.TAB_VALUE_SPLIT, 1) + ValueList[0:len(TokenList)] = TokenList + + # + # Replace with Local section Macro and [Defines] section Macro. + # + ValueList = [InfExpandMacro(Value, (FileName, LineContent, LineNo), + self.FileLocalMacros, SectionMacros, True) + for Value in ValueList] + + CurrentLineVar = (LineContent, LineNo, FileName) + + + if len(ValueList) >= 1: + GuidList.append((ValueList, CommentsList, CurrentLineVar)) + CommentsList = [] + ValueList = [] + continue + + # + # Current section archs + # + ArchList = [] + LineIndex = -1 + for Item in self.LastSectionHeaderContent: + LineIndex = Item[3] + if Item[1] not in ArchList: + ArchList.append(Item[1]) + + if not InfSectionObject.SetGuid(GuidList, Arch=ArchList): + Logger.Error('InfParser', + FORMAT_INVALID, + ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % ("[Guid]"), + File=FileName, + Line=LineIndex) + + ## InfPpiParser + # + # + def InfPpiParser(self, SectionString, InfSectionObject, FileName): + # + # Macro defined in this section + # + SectionMacros = {} + ValueList = [] + PpiList = [] + CommentsList = [] + CurrentLineVar = None + # + # Parse section content + # + for Line in SectionString: + LineContent = Line[0] + LineNo = Line[1] + + if LineContent.strip() == '': + CommentsList = [] + continue + + if LineContent.strip().startswith(DT.TAB_COMMENT_SPLIT): + CommentsList.append(Line) + continue + else: + # + # Encounter a PPI entry + # + if LineContent.find(DT.TAB_COMMENT_SPLIT) > -1: + CommentsList.append(( + LineContent[LineContent.find(DT.TAB_COMMENT_SPLIT):], + LineNo)) + LineContent = \ + LineContent[:LineContent.find(DT.TAB_COMMENT_SPLIT)] + + if LineContent != '': + # + # Find Macro + # + Name, Value = MacroParser((LineContent, LineNo), + FileName, + DT.MODEL_EFI_PPI, + self.FileLocalMacros) + if Name is not None: + SectionMacros[Name] = Value + ValueList = [] + CommentsList = [] + continue + + TokenList = GetSplitValueList(LineContent, DT.TAB_VALUE_SPLIT, 1) + ValueList[0:len(TokenList)] = TokenList + + # + # Replace with Local section Macro and [Defines] section Macro. + # + ValueList = [InfExpandMacro(Value, (FileName, LineContent, LineNo), self.FileLocalMacros, SectionMacros) + for Value in ValueList] + + CurrentLineVar = (LineContent, LineNo, FileName) + + if len(ValueList) >= 1: + PpiList.append((ValueList, CommentsList, CurrentLineVar)) + ValueList = [] + CommentsList = [] + continue + + # + # Current section archs + # + ArchList = [] + LineIndex = -1 + for Item in self.LastSectionHeaderContent: + LineIndex = Item[3] + if Item[1] not in ArchList: + ArchList.append(Item[1]) + + if not InfSectionObject.SetPpi(PpiList, Arch=ArchList): + Logger.Error('InfParser', + FORMAT_INVALID, + ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % ("[Ppis]"), + File=FileName, + Line=LineIndex) + + ## InfUserExtensionParser + # + # + def InfUserExtensionParser(self, SectionString, InfSectionObject, FileName): + + UserExtensionContent = '' + + # + # Parse section content + # + for Line in SectionString: + LineContent = Line[0] + +# Comment the code to support user extension without any statement just the section header in [] +# if LineContent.strip() == '': +# continue + + UserExtensionContent += LineContent + DT.END_OF_LINE + continue + + # + # Current section UserId, IdString + # + IdContentList = [] + LastItem = '' + SectionLineNo = None + for Item in self.LastSectionHeaderContent: + UserId = Item[1] + IdString = Item[2] + Arch = Item[3] + SectionLineNo = Item[4] + if not IsValidArch(Arch): + Logger.Error( + 'InfParser', + FORMAT_INVALID, + ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID % (Arch), + File=GlobalData.gINF_MODULE_NAME, + Line=SectionLineNo, + ExtraData=None) + + if (UserId, IdString, Arch) not in IdContentList: + # + # To check the UserId and IdString valid or not. + # + if not IsValidUserId(UserId): + Logger.Error('InfParser', + FORMAT_INVALID, + ST.ERR_INF_PARSER_UE_SECTION_USER_ID_ERROR % (Item[1]), + File=GlobalData.gINF_MODULE_NAME, + Line=SectionLineNo, + ExtraData=None) + + if not IsValidIdString(IdString): + Logger.Error('InfParser', + FORMAT_INVALID, + ST.ERR_INF_PARSER_UE_SECTION_ID_STRING_ERROR % (IdString), + File=GlobalData.gINF_MODULE_NAME, Line=SectionLineNo, + ExtraData=None) + IdContentList.append((UserId, IdString, Arch)) + else: + # + # Each UserExtensions section header must have a unique set + # of UserId, IdString and Arch values. + # This means that the same UserId can be used in more than one + # section header, provided the IdString or Arch values are + # different. The same IdString values can be used in more than + # one section header if the UserId or Arch values are + # different. The same UserId and the same IdString can be used + # in a section header if the Arch values are different in each + # of the section headers. + # + Logger.Error('InfParser', + FORMAT_INVALID, + ST.ERR_INF_PARSER_UE_SECTION_DUPLICATE_ERROR % ( + IdString), + File=GlobalData.gINF_MODULE_NAME, + Line=SectionLineNo, + ExtraData=None) + LastItem = Item + + if not InfSectionObject.SetUserExtension(UserExtensionContent, + IdContent=IdContentList, + LineNo=SectionLineNo): + Logger.Error\ + ('InfParser', FORMAT_INVALID, \ + ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % ("[UserExtension]"), \ + File=FileName, Line=LastItem[4]) + + def InfProtocolParser(self, SectionString, InfSectionObject, FileName): + # + # Macro defined in this section + # + SectionMacros = {} + ValueList = [] + ProtocolList = [] + CommentsList = [] + CurrentLineVar = None + # + # Parse section content + # + for Line in SectionString: + LineContent = Line[0] + LineNo = Line[1] + + if LineContent.strip() == '': + CommentsList = [] + continue + + if LineContent.strip().startswith(DT.TAB_COMMENT_SPLIT): + CommentsList.append(Line) + continue + else: + # + # Encounter a Protocol entry + # + if LineContent.find(DT.TAB_COMMENT_SPLIT) > -1: + CommentsList.append(( + LineContent[LineContent.find(DT.TAB_COMMENT_SPLIT):], + LineNo)) + LineContent = \ + LineContent[:LineContent.find(DT.TAB_COMMENT_SPLIT)] + + if LineContent != '': + # + # Find Macro + # + Name, Value = MacroParser((LineContent, LineNo), + FileName, + DT.MODEL_EFI_PROTOCOL, + self.FileLocalMacros) + if Name is not None: + SectionMacros[Name] = Value + ValueList = [] + CommentsList = [] + continue + + TokenList = GetSplitValueList(LineContent, DT.TAB_VALUE_SPLIT, 1) + ValueList[0:len(TokenList)] = TokenList + + # + # Replace with Local section Macro and [Defines] section Macro. + # + ValueList = [InfExpandMacro(Value, (FileName, LineContent, LineNo), self.FileLocalMacros, SectionMacros) + for Value in ValueList] + + CurrentLineVar = (LineContent, LineNo, FileName) + + if len(ValueList) >= 1: + ProtocolList.append((ValueList, CommentsList, CurrentLineVar)) + ValueList = [] + CommentsList = [] + continue + + # + # Current section archs + # + ArchList = [] + LineIndex = -1 + for Item in self.LastSectionHeaderContent: + LineIndex = Item[3] + if Item[1] not in ArchList: + ArchList.append(Item[1]) + + if not InfSectionObject.SetProtocol(ProtocolList, Arch=ArchList): + Logger.Error\ + ('InfParser', FORMAT_INVALID, \ + ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % ("[Protocol]"), \ + File=FileName, Line=LineIndex) diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfLibrarySectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfLibrarySectionParser.py new file mode 100755 index 00000000..66fae2af --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfLibrarySectionParser.py @@ -0,0 +1,197 @@ +## @file +# This file contained the parser for [Libraries] sections in INF file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +''' +InfLibrarySectionParser +''' +## +# Import Modules +# + +import Logger.Log as Logger +from Logger import StringTable as ST +from Logger.ToolError import FORMAT_INVALID +from Parser.InfParserMisc import InfExpandMacro +from Library import DataType as DT +from Library.Parsing import MacroParser +from Library.Misc import GetSplitValueList +from Object.Parser.InfCommonObject import InfLineCommentObject +from Library import GlobalData +from Parser.InfParserMisc import IsLibInstanceInfo +from Parser.InfAsBuiltProcess import GetLibInstanceInfo +from Parser.InfParserMisc import InfParserSectionRoot + +class InfLibrarySectionParser(InfParserSectionRoot): + ## InfLibraryParser + # + # + def InfLibraryParser(self, SectionString, InfSectionObject, FileName): + # + # For Common INF file + # + if not GlobalData.gIS_BINARY_INF: + # + # Macro defined in this section + # + SectionMacros = {} + ValueList = [] + LibraryList = [] + LibStillCommentFalg = False + LibHeaderComments = [] + LibLineComment = None + # + # Parse section content + # + for Line in SectionString: + LibLineContent = Line[0] + LibLineNo = Line[1] + + if LibLineContent.strip() == '': + continue + + # + # Found Header Comments + # + if LibLineContent.strip().startswith(DT.TAB_COMMENT_SPLIT): + # + # Last line is comments, and this line go on. + # + if LibStillCommentFalg: + LibHeaderComments.append(Line) + continue + # + # First time encounter comment + # + else: + # + # Clear original data + # + LibHeaderComments = [] + LibHeaderComments.append(Line) + LibStillCommentFalg = True + continue + else: + LibStillCommentFalg = False + + if len(LibHeaderComments) >= 1: + LibLineComment = InfLineCommentObject() + LineCommentContent = '' + for Item in LibHeaderComments: + LineCommentContent += Item[0] + DT.END_OF_LINE + LibLineComment.SetHeaderComments(LineCommentContent) + + # + # Find Tail comment. + # + if LibLineContent.find(DT.TAB_COMMENT_SPLIT) > -1: + LibTailComments = LibLineContent[LibLineContent.find(DT.TAB_COMMENT_SPLIT):] + LibLineContent = LibLineContent[:LibLineContent.find(DT.TAB_COMMENT_SPLIT)] + if LibLineComment is None: + LibLineComment = InfLineCommentObject() + LibLineComment.SetTailComments(LibTailComments) + + # + # Find Macro + # + Name, Value = MacroParser((LibLineContent, LibLineNo), + FileName, + DT.MODEL_EFI_LIBRARY_CLASS, + self.FileLocalMacros) + if Name is not None: + SectionMacros[Name] = Value + LibLineComment = None + LibHeaderComments = [] + continue + + TokenList = GetSplitValueList(LibLineContent, DT.TAB_VALUE_SPLIT, 1) + ValueList[0:len(TokenList)] = TokenList + + # + # Replace with Local section Macro and [Defines] section Macro. + # + ValueList = [InfExpandMacro(Value, (FileName, LibLineContent, LibLineNo), + self.FileLocalMacros, SectionMacros, True) + for Value in ValueList] + + LibraryList.append((ValueList, LibLineComment, + (LibLineContent, LibLineNo, FileName))) + ValueList = [] + LibLineComment = None + LibTailComments = '' + LibHeaderComments = [] + + continue + + # + # Current section archs + # + KeyList = [] + for Item in self.LastSectionHeaderContent: + if (Item[1], Item[2]) not in KeyList: + KeyList.append((Item[1], Item[2])) + + if not InfSectionObject.SetLibraryClasses(LibraryList, KeyList=KeyList): + Logger.Error('InfParser', + FORMAT_INVALID, + ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % ("[Library]"), + File=FileName, + Line=Item[3]) + # + # For Binary INF + # + else: + self.InfAsBuiltLibraryParser(SectionString, InfSectionObject, FileName) + + def InfAsBuiltLibraryParser(self, SectionString, InfSectionObject, FileName): + LibraryList = [] + LibInsFlag = False + for Line in SectionString: + LineContent = Line[0] + LineNo = Line[1] + + if LineContent.strip() == '': + LibInsFlag = False + continue + + if not LineContent.strip().startswith("#"): + Logger.Error('InfParser', + FORMAT_INVALID, + ST.ERR_LIB_CONTATIN_ASBUILD_AND_COMMON, + File=FileName, + Line=LineNo, + ExtraData=LineContent) + + if IsLibInstanceInfo(LineContent): + LibInsFlag = True + continue + + if LibInsFlag: + LibGuid, LibVer = GetLibInstanceInfo(LineContent, GlobalData.gWORKSPACE, LineNo, FileName) + # + # If the VERSION_STRING is missing from the INF file, tool should default to "0". + # + if LibVer == '': + LibVer = '0' + if LibGuid != '': + if (LibGuid, LibVer) not in LibraryList: + LibraryList.append((LibGuid, LibVer)) + + # + # Current section archs + # + KeyList = [] + Item = ['', '', ''] + for Item in self.LastSectionHeaderContent: + if (Item[1], Item[2]) not in KeyList: + KeyList.append((Item[1], Item[2])) + + if not InfSectionObject.SetLibraryClasses(LibraryList, KeyList=KeyList): + Logger.Error('InfParser', + FORMAT_INVALID, + ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % ("[Library]"), + File=FileName, + Line=Item[3]) diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfPackageSectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfPackageSectionParser.py new file mode 100755 index 00000000..bb6777e8 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfPackageSectionParser.py @@ -0,0 +1,134 @@ +## @file +# This file contained the parser for [Packages] sections in INF file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +''' +InfPackageSectionParser +''' +## +# Import Modules +# + +import Logger.Log as Logger +from Logger import StringTable as ST +from Logger.ToolError import FORMAT_INVALID +from Parser.InfParserMisc import InfExpandMacro +from Library import DataType as DT +from Library.Parsing import MacroParser +from Library.Misc import GetSplitValueList +from Object.Parser.InfCommonObject import InfLineCommentObject +from Parser.InfParserMisc import InfParserSectionRoot + +class InfPackageSectionParser(InfParserSectionRoot): + ## InfPackageParser + # + # + def InfPackageParser(self, SectionString, InfSectionObject, FileName): + # + # Macro defined in this section + # + SectionMacros = {} + ValueList = [] + PackageList = [] + StillCommentFalg = False + HeaderComments = [] + LineComment = None + # + # Parse section content + # + for Line in SectionString: + PkgLineContent = Line[0] + PkgLineNo = Line[1] + + if PkgLineContent.strip() == '': + continue + + # + # Find Header Comments + # + if PkgLineContent.strip().startswith(DT.TAB_COMMENT_SPLIT): + # + # Last line is comments, and this line go on. + # + if StillCommentFalg: + HeaderComments.append(Line) + continue + # + # First time encounter comment + # + else: + # + # Clear original data + # + HeaderComments = [] + HeaderComments.append(Line) + StillCommentFalg = True + continue + else: + StillCommentFalg = False + + if len(HeaderComments) >= 1: + LineComment = InfLineCommentObject() + LineCommentContent = '' + for Item in HeaderComments: + LineCommentContent += Item[0] + DT.END_OF_LINE + LineComment.SetHeaderComments(LineCommentContent) + + # + # Find Tail comment. + # + if PkgLineContent.find(DT.TAB_COMMENT_SPLIT) > -1: + TailComments = PkgLineContent[PkgLineContent.find(DT.TAB_COMMENT_SPLIT):] + PkgLineContent = PkgLineContent[:PkgLineContent.find(DT.TAB_COMMENT_SPLIT)] + if LineComment is None: + LineComment = InfLineCommentObject() + LineComment.SetTailComments(TailComments) + # + # Find Macro + # + Name, Value = MacroParser((PkgLineContent, PkgLineNo), + FileName, + DT.MODEL_META_DATA_PACKAGE, + self.FileLocalMacros) + if Name is not None: + SectionMacros[Name] = Value + LineComment = None + HeaderComments = [] + continue + + TokenList = GetSplitValueList(PkgLineContent, DT.TAB_VALUE_SPLIT, 1) + ValueList[0:len(TokenList)] = TokenList + + # + # Replace with Local section Macro and [Defines] section Macro. + # + ValueList = [InfExpandMacro(Value, (FileName, PkgLineContent, PkgLineNo), + self.FileLocalMacros, SectionMacros, True) + for Value in ValueList] + + PackageList.append((ValueList, LineComment, + (PkgLineContent, PkgLineNo, FileName))) + ValueList = [] + LineComment = None + TailComments = '' + HeaderComments = [] + continue + + # + # Current section archs + # + ArchList = [] + for Item in self.LastSectionHeaderContent: + if Item[1] not in ArchList: + ArchList.append(Item[1]) + + if not InfSectionObject.SetPackages(PackageList, Arch = ArchList): + Logger.Error('InfParser', + FORMAT_INVALID, + ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR\ + %("[Packages]"), + File=FileName, + Line=Item[3]) diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfParser.py new file mode 100755 index 00000000..711b5e85 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfParser.py @@ -0,0 +1,680 @@ +## @file +# This file contained the parser for INF file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +InfParser +''' + +## +# Import Modules +# +import re +import os +from copy import deepcopy + +from Library.StringUtils import GetSplitValueList +from Library.StringUtils import ConvertSpecialChar +from Library.Misc import ProcessLineExtender +from Library.Misc import ProcessEdkComment +from Library.Parsing import NormPath +from Library.ParserValidate import IsValidInfMoudleTypeList +from Library.ParserValidate import IsValidArch +from Library import DataType as DT +from Library import GlobalData + +import Logger.Log as Logger +from Logger import StringTable as ST +from Logger.ToolError import FORMAT_INVALID +from Logger.ToolError import FILE_READ_FAILURE +from Logger.ToolError import PARSER_ERROR + +from Object.Parser.InfCommonObject import InfSectionCommonDef +from Parser.InfSectionParser import InfSectionParser +from Parser.InfParserMisc import gINF_SECTION_DEF +from Parser.InfParserMisc import IsBinaryInf + +## OpenInfFile +# +# +def OpenInfFile(Filename): + FileLinesList = [] + + try: + FInputfile = open(Filename, "r") + try: + FileLinesList = FInputfile.readlines() + except BaseException: + Logger.Error("InfParser", + FILE_READ_FAILURE, + ST.ERR_FILE_OPEN_FAILURE, + File=Filename) + finally: + FInputfile.close() + except BaseException: + Logger.Error("InfParser", + FILE_READ_FAILURE, + ST.ERR_FILE_OPEN_FAILURE, + File=Filename) + + return FileLinesList + +## InfParser +# +# This class defined the structure used in InfParser object +# +# @param InfObject: Inherited from InfSectionParser class +# @param Filename: Input value for Filename of INF file, default is +# None +# @param WorkspaceDir: Input value for current workspace directory, +# default is None +# +class InfParser(InfSectionParser): + + def __init__(self, Filename = None, WorkspaceDir = None): + + # + # Call parent class construct function + # + InfSectionParser.__init__() + + self.WorkspaceDir = WorkspaceDir + self.SupArchList = DT.ARCH_LIST + self.EventList = [] + self.HobList = [] + self.BootModeList = [] + + # + # Load Inf file if filename is not None + # + if Filename is not None: + self.ParseInfFile(Filename) + + ## Parse INF file + # + # Parse the file if it exists + # + # @param Filename: Input value for filename of INF file + # + def ParseInfFile(self, Filename): + + Filename = NormPath(Filename) + (Path, Name) = os.path.split(Filename) + self.FullPath = Filename + self.RelaPath = Path + self.FileName = Name + GlobalData.gINF_MODULE_DIR = Path + GlobalData.gINF_MODULE_NAME = self.FullPath + GlobalData.gIS_BINARY_INF = False + # + # Initialize common data + # + LineNo = 0 + CurrentSection = DT.MODEL_UNKNOWN + SectionLines = [] + + # + # Flags + # + HeaderCommentStart = False + HeaderCommentEnd = False + HeaderStarLineNo = -1 + BinaryHeaderCommentStart = False + BinaryHeaderCommentEnd = False + BinaryHeaderStarLineNo = -1 + + # + # While Section ends. parse whole section contents. + # + NewSectionStartFlag = False + FirstSectionStartFlag = False + + # + # Parse file content + # + CommentBlock = [] + + # + # Variables for Event/Hob/BootMode + # + self.EventList = [] + self.HobList = [] + self.BootModeList = [] + SectionType = '' + + FileLinesList = OpenInfFile (Filename) + + # + # One INF file can only has one [Defines] section. + # + DefineSectionParsedFlag = False + + # + # Convert special characters in lines to space character. + # + FileLinesList = ConvertSpecialChar(FileLinesList) + + # + # Process Line Extender + # + FileLinesList = ProcessLineExtender(FileLinesList) + + # + # Process EdkI INF style comment if found + # + OrigLines = [Line for Line in FileLinesList] + FileLinesList, EdkCommentStartPos = ProcessEdkComment(FileLinesList) + + # + # Judge whether the INF file is Binary INF or not + # + if IsBinaryInf(FileLinesList): + GlobalData.gIS_BINARY_INF = True + + InfSectionCommonDefObj = None + + for Line in FileLinesList: + LineNo = LineNo + 1 + Line = Line.strip() + if (LineNo < len(FileLinesList) - 1): + NextLine = FileLinesList[LineNo].strip() + + # + # blank line + # + if (Line == '' or not Line) and LineNo == len(FileLinesList): + LastSectionFalg = True + + # + # check whether file header comment section started + # + if Line.startswith(DT.TAB_SPECIAL_COMMENT) and \ + (Line.find(DT.TAB_HEADER_COMMENT) > -1) and \ + not HeaderCommentStart and not HeaderCommentEnd: + + CurrentSection = DT.MODEL_META_DATA_FILE_HEADER + # + # Append the first line to section lines. + # + HeaderStarLineNo = LineNo + SectionLines.append((Line, LineNo)) + HeaderCommentStart = True + continue + + # + # Collect Header content. + # + if (Line.startswith(DT.TAB_COMMENT_SPLIT) and CurrentSection == DT.MODEL_META_DATA_FILE_HEADER) and\ + HeaderCommentStart and not Line.startswith(DT.TAB_SPECIAL_COMMENT) and not\ + HeaderCommentEnd and NextLine != '': + SectionLines.append((Line, LineNo)) + continue + # + # Header content end + # + if (Line.startswith(DT.TAB_SPECIAL_COMMENT) or not Line.strip().startswith("#")) and HeaderCommentStart \ + and not HeaderCommentEnd: + HeaderCommentEnd = True + BinaryHeaderCommentStart = False + BinaryHeaderCommentEnd = False + HeaderCommentStart = False + if Line.find(DT.TAB_BINARY_HEADER_COMMENT) > -1: + self.InfHeaderParser(SectionLines, self.InfHeader, self.FileName) + SectionLines = [] + else: + SectionLines.append((Line, LineNo)) + # + # Call Header comment parser. + # + self.InfHeaderParser(SectionLines, self.InfHeader, self.FileName) + SectionLines = [] + continue + + # + # check whether binary header comment section started + # + if Line.startswith(DT.TAB_SPECIAL_COMMENT) and \ + (Line.find(DT.TAB_BINARY_HEADER_COMMENT) > -1) and \ + not BinaryHeaderCommentStart: + SectionLines = [] + CurrentSection = DT.MODEL_META_DATA_FILE_HEADER + # + # Append the first line to section lines. + # + BinaryHeaderStarLineNo = LineNo + SectionLines.append((Line, LineNo)) + BinaryHeaderCommentStart = True + HeaderCommentEnd = True + continue + + # + # check whether there are more than one binary header exist + # + if Line.startswith(DT.TAB_SPECIAL_COMMENT) and BinaryHeaderCommentStart and \ + not BinaryHeaderCommentEnd and (Line.find(DT.TAB_BINARY_HEADER_COMMENT) > -1): + Logger.Error('Parser', + FORMAT_INVALID, + ST.ERR_MULTIPLE_BINARYHEADER_EXIST, + File=Filename) + + # + # Collect Binary Header content. + # + if (Line.startswith(DT.TAB_COMMENT_SPLIT) and CurrentSection == DT.MODEL_META_DATA_FILE_HEADER) and\ + BinaryHeaderCommentStart and not Line.startswith(DT.TAB_SPECIAL_COMMENT) and not\ + BinaryHeaderCommentEnd and NextLine != '': + SectionLines.append((Line, LineNo)) + continue + # + # Binary Header content end + # + if (Line.startswith(DT.TAB_SPECIAL_COMMENT) or not Line.strip().startswith(DT.TAB_COMMENT_SPLIT)) and \ + BinaryHeaderCommentStart and not BinaryHeaderCommentEnd: + SectionLines.append((Line, LineNo)) + BinaryHeaderCommentStart = False + # + # Call Binary Header comment parser. + # + self.InfHeaderParser(SectionLines, self.InfBinaryHeader, self.FileName, True) + SectionLines = [] + BinaryHeaderCommentEnd = True + continue + # + # Find a new section tab + # Or at the last line of INF file, + # need to process the last section. + # + LastSectionFalg = False + if LineNo == len(FileLinesList): + LastSectionFalg = True + + if Line.startswith(DT.TAB_COMMENT_SPLIT) and not Line.startswith(DT.TAB_SPECIAL_COMMENT): + SectionLines.append((Line, LineNo)) + if not LastSectionFalg: + continue + + # + # Encountered a section. start with '[' and end with ']' + # + if (Line.startswith(DT.TAB_SECTION_START) and \ + Line.find(DT.TAB_SECTION_END) > -1) or LastSectionFalg: + + HeaderCommentEnd = True + BinaryHeaderCommentEnd = True + + if not LastSectionFalg: + # + # check to prevent '#' inside section header + # + HeaderContent = Line[1:Line.find(DT.TAB_SECTION_END)] + if HeaderContent.find(DT.TAB_COMMENT_SPLIT) != -1: + Logger.Error("InfParser", + FORMAT_INVALID, + ST.ERR_INF_PARSER_DEFINE_SECTION_HEADER_INVALID, + File=self.FullPath, + Line=LineNo, + ExtraData=Line) + + # + # Keep last time section header content for section parser + # usage. + # + self.LastSectionHeaderContent = deepcopy(self.SectionHeaderContent) + + # + # TailComments in section define. + # + TailComments = '' + CommentIndex = Line.find(DT.TAB_COMMENT_SPLIT) + if CommentIndex > -1: + TailComments = Line[CommentIndex:] + Line = Line[:CommentIndex] + + InfSectionCommonDefObj = InfSectionCommonDef() + if TailComments != '': + InfSectionCommonDefObj.SetTailComments(TailComments) + if CommentBlock != '': + InfSectionCommonDefObj.SetHeaderComments(CommentBlock) + CommentBlock = [] + # + # Call section parser before section header parer to avoid encounter EDKI INF file + # + if CurrentSection == DT.MODEL_META_DATA_DEFINE: + DefineSectionParsedFlag = self._CallSectionParsers(CurrentSection, + DefineSectionParsedFlag, SectionLines, + InfSectionCommonDefObj, LineNo) + # + # Compare the new section name with current + # + self.SectionHeaderParser(Line, self.FileName, LineNo) + + self._CheckSectionHeaders(Line, LineNo) + + SectionType = _ConvertSecNameToType(self.SectionHeaderContent[0][0]) + + if not FirstSectionStartFlag: + CurrentSection = SectionType + FirstSectionStartFlag = True + else: + NewSectionStartFlag = True + else: + SectionLines.append((Line, LineNo)) + continue + + if LastSectionFalg: + SectionLines, CurrentSection = self._ProcessLastSection(SectionLines, Line, LineNo, CurrentSection) + + # + # End of section content collect. + # Parser the section content collected previously. + # + if NewSectionStartFlag or LastSectionFalg: + if CurrentSection != DT.MODEL_META_DATA_DEFINE or \ + (LastSectionFalg and CurrentSection == DT.MODEL_META_DATA_DEFINE): + DefineSectionParsedFlag = self._CallSectionParsers(CurrentSection, + DefineSectionParsedFlag, SectionLines, + InfSectionCommonDefObj, LineNo) + + CurrentSection = SectionType + # + # Clear section lines + # + SectionLines = [] + + if HeaderStarLineNo == -1: + Logger.Error("InfParser", + FORMAT_INVALID, + ST.ERR_NO_SOURCE_HEADER, + File=self.FullPath) + if BinaryHeaderStarLineNo > -1 and HeaderStarLineNo > -1 and HeaderStarLineNo > BinaryHeaderStarLineNo: + Logger.Error("InfParser", + FORMAT_INVALID, + ST.ERR_BINARY_HEADER_ORDER, + File=self.FullPath) + # + # EDKII INF should not have EDKI style comment + # + if EdkCommentStartPos != -1: + Logger.Error("InfParser", + FORMAT_INVALID, + ST.ERR_INF_PARSER_EDKI_COMMENT_IN_EDKII, + File=self.FullPath, + Line=EdkCommentStartPos + 1, + ExtraData=OrigLines[EdkCommentStartPos]) + + # + # extract [Event] [Hob] [BootMode] sections + # + self._ExtractEventHobBootMod(FileLinesList) + + ## _CheckSectionHeaders + # + # + def _CheckSectionHeaders(self, Line, LineNo): + if len(self.SectionHeaderContent) == 0: + Logger.Error("InfParser", + FORMAT_INVALID, + ST.ERR_INF_PARSER_DEFINE_SECTION_HEADER_INVALID, + File=self.FullPath, + Line=LineNo, ExtraData=Line) + else: + for SectionItem in self.SectionHeaderContent: + ArchList = [] + # + # Not cover Depex/UserExtension section header + # check. + # + if SectionItem[0].strip().upper() == DT.TAB_INF_FIXED_PCD.upper() or \ + SectionItem[0].strip().upper() == DT.TAB_INF_PATCH_PCD.upper() or \ + SectionItem[0].strip().upper() == DT.TAB_INF_PCD_EX.upper() or \ + SectionItem[0].strip().upper() == DT.TAB_INF_PCD.upper() or \ + SectionItem[0].strip().upper() == DT.TAB_INF_FEATURE_PCD.upper(): + ArchList = GetSplitValueList(SectionItem[1].strip(), ' ') + else: + ArchList = [SectionItem[1].strip()] + + for Arch in ArchList: + if (not IsValidArch(Arch)) and \ + (SectionItem[0].strip().upper() != DT.TAB_DEPEX.upper()) and \ + (SectionItem[0].strip().upper() != DT.TAB_USER_EXTENSIONS.upper()) and \ + (SectionItem[0].strip().upper() != DT.TAB_COMMON_DEFINES.upper()): + Logger.Error("InfParser", + FORMAT_INVALID, + ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(SectionItem[1]), + File=self.FullPath, + Line=LineNo, ExtraData=Line) + # + # Check if the ModuleType is valid + # + ChkModSectionList = ['LIBRARYCLASSES'] + if (self.SectionHeaderContent[0][0].upper() in ChkModSectionList): + if SectionItem[2].strip().upper(): + MoudleTypeList = GetSplitValueList( + SectionItem[2].strip().upper()) + if (not IsValidInfMoudleTypeList(MoudleTypeList)): + Logger.Error("InfParser", + FORMAT_INVALID, + ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(SectionItem[2]), + File=self.FullPath, Line=LineNo, + ExtraData=Line) + + ## _CallSectionParsers + # + # + def _CallSectionParsers(self, CurrentSection, DefineSectionParsedFlag, + SectionLines, InfSectionCommonDefObj, LineNo): + if CurrentSection == DT.MODEL_META_DATA_DEFINE: + if not DefineSectionParsedFlag: + self.InfDefineParser(SectionLines, + self.InfDefSection, + self.FullPath, + InfSectionCommonDefObj) + DefineSectionParsedFlag = True + else: + Logger.Error("Parser", + PARSER_ERROR, + ST.ERR_INF_PARSER_MULTI_DEFINE_SECTION, + File=self.FullPath, + RaiseError = Logger.IS_RAISE_ERROR) + + elif CurrentSection == DT.MODEL_META_DATA_BUILD_OPTION: + self.InfBuildOptionParser(SectionLines, + self.InfBuildOptionSection, + self.FullPath) + + elif CurrentSection == DT.MODEL_EFI_LIBRARY_CLASS: + self.InfLibraryParser(SectionLines, + self.InfLibraryClassSection, + self.FullPath) + + elif CurrentSection == DT.MODEL_META_DATA_PACKAGE: + self.InfPackageParser(SectionLines, + self.InfPackageSection, + self.FullPath) + # + # [Pcd] Sections, put it together + # + elif CurrentSection == DT.MODEL_PCD_FIXED_AT_BUILD or \ + CurrentSection == DT.MODEL_PCD_PATCHABLE_IN_MODULE or \ + CurrentSection == DT.MODEL_PCD_FEATURE_FLAG or \ + CurrentSection == DT.MODEL_PCD_DYNAMIC_EX or \ + CurrentSection == DT.MODEL_PCD_DYNAMIC: + self.InfPcdParser(SectionLines, + self.InfPcdSection, + self.FullPath) + + elif CurrentSection == DT.MODEL_EFI_SOURCE_FILE: + self.InfSourceParser(SectionLines, + self.InfSourcesSection, + self.FullPath) + + elif CurrentSection == DT.MODEL_META_DATA_USER_EXTENSION: + self.InfUserExtensionParser(SectionLines, + self.InfUserExtensionSection, + self.FullPath) + + elif CurrentSection == DT.MODEL_EFI_PROTOCOL: + self.InfProtocolParser(SectionLines, + self.InfProtocolSection, + self.FullPath) + + elif CurrentSection == DT.MODEL_EFI_PPI: + self.InfPpiParser(SectionLines, + self.InfPpiSection, + self.FullPath) + + elif CurrentSection == DT.MODEL_EFI_GUID: + self.InfGuidParser(SectionLines, + self.InfGuidSection, + self.FullPath) + + elif CurrentSection == DT.MODEL_EFI_DEPEX: + self.InfDepexParser(SectionLines, + self.InfDepexSection, + self.FullPath) + + elif CurrentSection == DT.MODEL_EFI_BINARY_FILE: + self.InfBinaryParser(SectionLines, + self.InfBinariesSection, + self.FullPath) + # + # Unknown section type found, raise error. + # + else: + if len(self.SectionHeaderContent) >= 1: + Logger.Error("Parser", + PARSER_ERROR, + ST.ERR_INF_PARSER_UNKNOWN_SECTION, + File=self.FullPath, Line=LineNo, + RaiseError = Logger.IS_RAISE_ERROR) + else: + Logger.Error("Parser", + PARSER_ERROR, + ST.ERR_INF_PARSER_NO_SECTION_ERROR, + File=self.FullPath, Line=LineNo, + RaiseError = Logger.IS_RAISE_ERROR) + + return DefineSectionParsedFlag + + def _ExtractEventHobBootMod(self, FileLinesList): + SpecialSectionStart = False + CheckLocation = False + GFindSpecialCommentRe = \ + re.compile(r"""#(?:\s*)\[(.*?)\](?:.*)""", re.DOTALL) + GFindNewSectionRe2 = \ + re.compile(r"""#?(\s*)\[(.*?)\](.*)""", re.DOTALL) + LineNum = 0 + Element = [] + for Line in FileLinesList: + Line = Line.strip() + LineNum += 1 + MatchObject = GFindSpecialCommentRe.search(Line) + if MatchObject: + SpecialSectionStart = True + Element = [] + if MatchObject.group(1).upper().startswith("EVENT"): + List = self.EventList + elif MatchObject.group(1).upper().startswith("HOB"): + List = self.HobList + elif MatchObject.group(1).upper().startswith("BOOTMODE"): + List = self.BootModeList + else: + SpecialSectionStart = False + CheckLocation = False + if SpecialSectionStart: + Element.append([Line, LineNum]) + List.append(Element) + else: + # + # if currently in special section, try to detect end of current section + # + MatchObject = GFindNewSectionRe2.search(Line) + if SpecialSectionStart: + if MatchObject: + SpecialSectionStart = False + CheckLocation = False + Element = [] + elif not Line: + SpecialSectionStart = False + CheckLocation = True + Element = [] + else: + if not Line.startswith(DT.TAB_COMMENT_SPLIT): + Logger.Warn("Parser", + ST.WARN_SPECIAL_SECTION_LOCATION_WRONG, + File=self.FullPath, Line=LineNum) + SpecialSectionStart = False + CheckLocation = False + Element = [] + else: + Element.append([Line, LineNum]) + else: + if CheckLocation: + if MatchObject: + CheckLocation = False + elif Line: + Logger.Warn("Parser", + ST.WARN_SPECIAL_SECTION_LOCATION_WRONG, + File=self.FullPath, Line=LineNum) + CheckLocation = False + + if len(self.BootModeList) >= 1: + self.InfSpecialCommentParser(self.BootModeList, + self.InfSpecialCommentSection, + self.FileName, + DT.TYPE_BOOTMODE_SECTION) + + if len(self.EventList) >= 1: + self.InfSpecialCommentParser(self.EventList, + self.InfSpecialCommentSection, + self.FileName, + DT.TYPE_EVENT_SECTION) + + if len(self.HobList) >= 1: + self.InfSpecialCommentParser(self.HobList, + self.InfSpecialCommentSection, + self.FileName, + DT.TYPE_HOB_SECTION) + ## _ProcessLastSection + # + # + def _ProcessLastSection(self, SectionLines, Line, LineNo, CurrentSection): + # + # The last line is a section header. will discard it. + # + if not (Line.startswith(DT.TAB_SECTION_START) and Line.find(DT.TAB_SECTION_END) > -1): + SectionLines.append((Line, LineNo)) + + if len(self.SectionHeaderContent) >= 1: + TemSectionName = self.SectionHeaderContent[0][0].upper() + if TemSectionName.upper() not in gINF_SECTION_DEF.keys(): + Logger.Error("InfParser", + FORMAT_INVALID, + ST.ERR_INF_PARSER_UNKNOWN_SECTION, + File=self.FullPath, + Line=LineNo, + ExtraData=Line, + RaiseError = Logger.IS_RAISE_ERROR + ) + else: + CurrentSection = gINF_SECTION_DEF[TemSectionName] + self.LastSectionHeaderContent = self.SectionHeaderContent + + return SectionLines, CurrentSection + +## _ConvertSecNameToType +# +# +def _ConvertSecNameToType(SectionName): + SectionType = '' + if SectionName.upper() not in gINF_SECTION_DEF.keys(): + SectionType = DT.MODEL_UNKNOWN + else: + SectionType = gINF_SECTION_DEF[SectionName.upper()] + + return SectionType + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfParserMisc.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfParserMisc.py new file mode 100755 index 00000000..0a51ac28 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfParserMisc.py @@ -0,0 +1,216 @@ +## @file +# This file contained the miscellaneous functions for INF parser +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +InfParserMisc +''' + +## +# Import Modules +# +import re + + +from Library import DataType as DT + + +from Library.StringUtils import gMACRO_PATTERN +from Library.StringUtils import ReplaceMacro +from Object.Parser.InfMisc import ErrorInInf +from Logger.StringTable import ERR_MARCO_DEFINITION_MISS_ERROR + +# +# Global variable +# + +# +# Sections can exist in INF file +# +gINF_SECTION_DEF = { + DT.TAB_UNKNOWN.upper() : DT.MODEL_UNKNOWN, + DT.TAB_HEADER.upper() : DT.MODEL_META_DATA_FILE_HEADER, + DT.TAB_INF_DEFINES.upper() : DT.MODEL_META_DATA_DEFINE, + DT.TAB_BUILD_OPTIONS.upper() : DT.MODEL_META_DATA_BUILD_OPTION, + DT.TAB_LIBRARY_CLASSES.upper() : DT.MODEL_EFI_LIBRARY_CLASS, + DT.TAB_PACKAGES.upper() : DT.MODEL_META_DATA_PACKAGE, + DT.TAB_INF_FIXED_PCD.upper() : DT.MODEL_PCD_FIXED_AT_BUILD, + DT.TAB_INF_PATCH_PCD.upper() : DT.MODEL_PCD_PATCHABLE_IN_MODULE, + DT.TAB_INF_FEATURE_PCD.upper() : DT.MODEL_PCD_FEATURE_FLAG, + DT.TAB_INF_PCD_EX.upper() : DT.MODEL_PCD_DYNAMIC_EX, + DT.TAB_INF_PCD.upper() : DT.MODEL_PCD_DYNAMIC, + DT.TAB_SOURCES.upper() : DT.MODEL_EFI_SOURCE_FILE, + DT.TAB_GUIDS.upper() : DT.MODEL_EFI_GUID, + DT.TAB_PROTOCOLS.upper() : DT.MODEL_EFI_PROTOCOL, + DT.TAB_PPIS.upper() : DT.MODEL_EFI_PPI, + DT.TAB_DEPEX.upper() : DT.MODEL_EFI_DEPEX, + DT.TAB_BINARIES.upper() : DT.MODEL_EFI_BINARY_FILE, + DT.TAB_USER_EXTENSIONS.upper() : DT.MODEL_META_DATA_USER_EXTENSION + # + # EDK1 section + # TAB_NMAKE.upper() : MODEL_META_DATA_NMAKE + # + } + +## InfExpandMacro +# +# Expand MACRO definition with MACROs defined in [Defines] section and specific section. +# The MACROs defined in specific section has high priority and will be expanded firstly. +# +# @param LineInfo Contain information of FileName, LineContent, LineNo +# @param GlobalMacros MACROs defined in INF [Defines] section +# @param SectionMacros MACROs defined in INF specific section +# @param Flag If the flag set to True, need to skip macros in a quoted string +# +def InfExpandMacro(Content, LineInfo, GlobalMacros=None, SectionMacros=None, Flag=False): + if GlobalMacros is None: + GlobalMacros = {} + if SectionMacros is None: + SectionMacros = {} + + FileName = LineInfo[0] + LineContent = LineInfo[1] + LineNo = LineInfo[2] + + # Don't expand macros in comments + if LineContent.strip().startswith("#"): + return Content + + NewLineInfo = (FileName, LineNo, LineContent) + + # + # First, replace MARCOs with value defined in specific section + # + Content = ReplaceMacro (Content, + SectionMacros, + False, + (LineContent, LineNo), + FileName, + Flag) + # + # Then replace MARCOs with value defined in [Defines] section + # + Content = ReplaceMacro (Content, + GlobalMacros, + False, + (LineContent, LineNo), + FileName, + Flag) + + MacroUsed = gMACRO_PATTERN.findall(Content) + # + # no macro found in String, stop replacing + # + if len(MacroUsed) == 0: + return Content + else: + for Macro in MacroUsed: + gQuotedMacro = re.compile(".*\".*\$\(%s\).*\".*"%(Macro)) + if not gQuotedMacro.match(Content): + # + # Still have MACROs can't be expanded. + # + ErrorInInf (ERR_MARCO_DEFINITION_MISS_ERROR, + LineInfo=NewLineInfo) + + return Content + + +## IsBinaryInf +# +# Judge whether the INF file is Binary INF or Common INF +# +# @param FileLineList A list contain all INF file content. +# +def IsBinaryInf(FileLineList): + if not FileLineList: + return False + + ReIsSourcesSection = re.compile("^\s*\[Sources.*\]\s.*$", re.IGNORECASE) + ReIsBinarySection = re.compile("^\s*\[Binaries.*\]\s.*$", re.IGNORECASE) + BinarySectionFoundFlag = False + + for Line in FileLineList: + if ReIsSourcesSection.match(Line): + return False + if ReIsBinarySection.match(Line): + BinarySectionFoundFlag = True + + if BinarySectionFoundFlag: + return True + + return False + + +## IsLibInstanceInfo +# +# Judge whether the string contain the information of ## @LIB_INSTANCES. +# +# @param String +# +# @return Flag +# +def IsLibInstanceInfo(String): + ReIsLibInstance = re.compile("^\s*##\s*@LIB_INSTANCES\s*$") + if ReIsLibInstance.match(String): + return True + else: + return False + + +## IsAsBuildOptionInfo +# +# Judge whether the string contain the information of ## @ASBUILD. +# +# @param String +# +# @return Flag +# +def IsAsBuildOptionInfo(String): + ReIsAsBuildInstance = re.compile("^\s*##\s*@AsBuilt\s*$") + if ReIsAsBuildInstance.match(String): + return True + else: + return False + + +class InfParserSectionRoot(object): + def __init__(self): + # + # Macros defined in [Define] section are file scope global + # + self.FileLocalMacros = {} + + # + # Current Section Header content. + # + self.SectionHeaderContent = [] + + # + # Last time Section Header content. + # + self.LastSectionHeaderContent = [] + + self.FullPath = '' + + self.InfDefSection = None + self.InfBuildOptionSection = None + self.InfLibraryClassSection = None + self.InfPackageSection = None + self.InfPcdSection = None + self.InfSourcesSection = None + self.InfUserExtensionSection = None + self.InfProtocolSection = None + self.InfPpiSection = None + self.InfGuidSection = None + self.InfDepexSection = None + self.InfPeiDepexSection = None + self.InfDxeDepexSection = None + self.InfSmmDepexSection = None + self.InfBinariesSection = None + self.InfHeader = None + self.InfSpecialCommentSection = None diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfPcdSectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfPcdSectionParser.py new file mode 100755 index 00000000..e930398d --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfPcdSectionParser.py @@ -0,0 +1,178 @@ +## @file +# This file contained the parser for [Pcds] sections in INF file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +''' +InfPcdSectionParser +''' +## +# Import Modules +# + +import Logger.Log as Logger +from Logger import StringTable as ST +from Logger.ToolError import FORMAT_INVALID +from Parser.InfParserMisc import InfExpandMacro +from Library import DataType as DT +from Library.Parsing import MacroParser +from Library.Misc import GetSplitValueList +from Library import GlobalData +from Library.StringUtils import SplitPcdEntry +from Parser.InfParserMisc import InfParserSectionRoot + +class InfPcdSectionParser(InfParserSectionRoot): + ## Section PCD related parser + # + # For 5 types of PCD list below, all use this function. + # 'FixedPcd', 'FeaturePcd', 'PatchPcd', 'Pcd', 'PcdEx' + # + # This is a INF independent parser, the validation in this parser only + # cover + # INF spec scope, will not cross DEC/DSC to check pcd value + # + def InfPcdParser(self, SectionString, InfSectionObject, FileName): + KeysList = [] + PcdList = [] + CommentsList = [] + ValueList = [] + # + # Current section archs + # + LineIndex = -1 + for Item in self.LastSectionHeaderContent: + if (Item[0], Item[1], Item[3]) not in KeysList: + KeysList.append((Item[0], Item[1], Item[3])) + LineIndex = Item[3] + + if (Item[0].upper() == DT.TAB_INF_FIXED_PCD.upper() or \ + Item[0].upper() == DT.TAB_INF_FEATURE_PCD.upper() or \ + Item[0].upper() == DT.TAB_INF_PCD.upper()) and GlobalData.gIS_BINARY_INF: + Logger.Error('InfParser', FORMAT_INVALID, ST.ERR_ASBUILD_PCD_SECTION_TYPE%("\"" + Item[0] + "\""), + File=FileName, Line=LineIndex) + + # + # For Common INF file + # + if not GlobalData.gIS_BINARY_INF: + # + # Macro defined in this section + # + SectionMacros = {} + for Line in SectionString: + PcdLineContent = Line[0] + PcdLineNo = Line[1] + if PcdLineContent.strip() == '': + CommentsList = [] + continue + + if PcdLineContent.strip().startswith(DT.TAB_COMMENT_SPLIT): + CommentsList.append(Line) + continue + else: + # + # Encounter a PCD entry + # + if PcdLineContent.find(DT.TAB_COMMENT_SPLIT) > -1: + CommentsList.append(( + PcdLineContent[PcdLineContent.find(DT.TAB_COMMENT_SPLIT):], + PcdLineNo)) + PcdLineContent = PcdLineContent[:PcdLineContent.find(DT.TAB_COMMENT_SPLIT)] + + if PcdLineContent != '': + # + # Find Macro + # + Name, Value = MacroParser((PcdLineContent, PcdLineNo), + FileName, + DT.MODEL_EFI_PCD, + self.FileLocalMacros) + if Name is not None: + SectionMacros[Name] = Value + ValueList = [] + CommentsList = [] + continue + + PcdEntryReturn = SplitPcdEntry(PcdLineContent) + + if not PcdEntryReturn[1]: + TokenList = [''] + else: + TokenList = PcdEntryReturn[0] + + ValueList[0:len(TokenList)] = TokenList + + # + # Replace with Local section Macro and [Defines] section Macro. + # + ValueList = [InfExpandMacro(Value, (FileName, PcdLineContent, PcdLineNo), + self.FileLocalMacros, SectionMacros, True) + for Value in ValueList] + + if len(ValueList) >= 1: + PcdList.append((ValueList, CommentsList, (PcdLineContent, PcdLineNo, FileName))) + ValueList = [] + CommentsList = [] + continue + # + # For Binary INF file + # + else: + for Line in SectionString: + LineContent = Line[0].strip() + LineNo = Line[1] + + if LineContent == '': + CommentsList = [] + continue + + if LineContent.startswith(DT.TAB_COMMENT_SPLIT): + CommentsList.append(LineContent) + continue + # + # Have comments at tail. + # + CommentIndex = LineContent.find(DT.TAB_COMMENT_SPLIT) + if CommentIndex > -1: + CommentsList.append(LineContent[CommentIndex+1:]) + LineContent = LineContent[:CommentIndex] + + TokenList = GetSplitValueList(LineContent, DT.TAB_VALUE_SPLIT) + # + # PatchablePcd + # TokenSpace.CName | Value | Offset + # + if KeysList[0][0].upper() == DT.TAB_INF_PATCH_PCD.upper(): + if len(TokenList) != 3: + Logger.Error('InfParser', + FORMAT_INVALID, + ST.ERR_ASBUILD_PATCHPCD_FORMAT_INVALID, + File=FileName, + Line=LineNo, + ExtraData=LineContent) + # + elif KeysList[0][0].upper() == DT.TAB_INF_PCD_EX.upper(): + if len(TokenList) != 1: + Logger.Error('InfParser', + FORMAT_INVALID, + ST.ERR_ASBUILD_PCDEX_FORMAT_INVALID, + File=FileName, + Line=LineNo, + ExtraData=LineContent) + ValueList[0:len(TokenList)] = TokenList + if len(ValueList) >= 1: + PcdList.append((ValueList, CommentsList, (LineContent, LineNo, FileName))) + ValueList = [] + CommentsList = [] + continue + + if not InfSectionObject.SetPcds(PcdList, KeysList = KeysList, + PackageInfo = self.InfPackageSection.GetPackages()): + Logger.Error('InfParser', + FORMAT_INVALID, + ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR%("[PCD]"), + File=FileName, + Line=LineIndex) + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfSectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfSectionParser.py new file mode 100755 index 00000000..9a0cd714 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfSectionParser.py @@ -0,0 +1,493 @@ +## @file +# This file contained the parser for sections in INF file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +InfSectionParser +''' +## +# Import Modules +# +from copy import deepcopy +import re + +from Library.StringUtils import GetSplitValueList +from Library.CommentParsing import ParseHeaderCommentSection +from Library.CommentParsing import ParseComment + +from Library import DataType as DT + +import Logger.Log as Logger +from Logger import StringTable as ST +from Logger.ToolError import FORMAT_INVALID + +from Object.Parser.InfDefineObject import InfDefObject +from Object.Parser.InfBuildOptionObject import InfBuildOptionsObject +from Object.Parser.InfLibraryClassesObject import InfLibraryClassObject +from Object.Parser.InfPackagesObject import InfPackageObject +from Object.Parser.InfPcdObject import InfPcdObject +from Object.Parser.InfSoucesObject import InfSourcesObject +from Object.Parser.InfUserExtensionObject import InfUserExtensionObject +from Object.Parser.InfProtocolObject import InfProtocolObject +from Object.Parser.InfPpiObject import InfPpiObject +from Object.Parser.InfGuidObject import InfGuidObject +from Object.Parser.InfDepexObject import InfDepexObject +from Object.Parser.InfBinaryObject import InfBinariesObject +from Object.Parser.InfHeaderObject import InfHeaderObject +from Object.Parser.InfMisc import InfSpecialCommentObject +from Object.Parser.InfMisc import InfHobObject +from Object.Parser.InfMisc import InfBootModeObject +from Object.Parser.InfMisc import InfEventObject +from Parser.InfParserMisc import gINF_SECTION_DEF +from Parser.InfDefineSectionParser import InfDefinSectionParser +from Parser.InfBuildOptionSectionParser import InfBuildOptionSectionParser +from Parser.InfSourceSectionParser import InfSourceSectionParser +from Parser.InfLibrarySectionParser import InfLibrarySectionParser +from Parser.InfPackageSectionParser import InfPackageSectionParser +from Parser.InfGuidPpiProtocolSectionParser import InfGuidPpiProtocolSectionParser +from Parser.InfBinarySectionParser import InfBinarySectionParser +from Parser.InfPcdSectionParser import InfPcdSectionParser +from Parser.InfDepexSectionParser import InfDepexSectionParser + +## GetSpecialStr2 +# +# GetSpecialStr2 +# +def GetSpecialStr2(ItemList, FileName, LineNo, SectionString): + Str2 = '' + # + # S2 may be Platform or ModuleType + # + if len(ItemList) == 3: + # + # Except [LibraryClass], [Depex] + # section can has more than 2 items in section header string, + # others should report error. + # + if not (ItemList[0].upper() == DT.TAB_LIBRARY_CLASSES.upper() or \ + ItemList[0].upper() == DT.TAB_DEPEX.upper() or \ + ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper()): + if ItemList[2] != '': + Logger.Error('Parser', + FORMAT_INVALID, + ST.ERR_INF_PARSER_SOURCE_SECTION_SECTIONNAME_INVALID % (SectionString), + File=FileName, + Line=LineNo, + ExtraData=SectionString) + Str2 = ItemList[2] + elif len(ItemList) == 4: + # + # Except [UserExtension] + # section can has 4 items in section header string, + # others should report error. + # + if not ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper() or ItemList[0].upper() == DT.TAB_DEPEX.upper(): + if ItemList[3] != '': + Logger.Error('Parser', FORMAT_INVALID, ST.ERR_INF_PARSER_SOURCE_SECTION_SECTIONNAME_INVALID \ + % (SectionString), File=FileName, Line=LineNo, ExtraData=SectionString) + + if not ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper(): + Str2 = ItemList[2] + ' | ' + ItemList[3] + else: + Str2 = ItemList[2] + + elif len(ItemList) > 4: + Logger.Error('Parser', FORMAT_INVALID, ST.ERR_INF_PARSER_SOURCE_SECTION_SECTIONNAME_INVALID \ + % (SectionString), File=FileName, Line=LineNo, ExtraData=SectionString) + + return Str2 + +## ProcessUseExtHeader +# +# +def ProcessUseExtHeader(ItemList): + NewItemList = [] + AppendContent = '' + CompleteFlag = False + for Item in ItemList: + if Item.startswith('\"') and not Item.endswith('\"'): + AppendContent = Item + CompleteFlag = True + elif Item.endswith('\"') and not Item.startswith('\"'): + # + # Should not have an userId or IdString not starts with " before but ends with ". + # + if not CompleteFlag: + return False, [] + AppendContent = AppendContent + "." + Item + NewItemList.append(AppendContent) + CompleteFlag = False + AppendContent = '' + elif Item.endswith('\"') and Item.startswith('\"'): + # + # Common item, not need to combine the information + # + NewItemList.append(Item) + else: + if not CompleteFlag: + NewItemList.append(Item) + else: + AppendContent = AppendContent + "." + Item + + if len(NewItemList) > 4: + return False, [] + + return True, NewItemList + +## GetArch +# +# GetArch +# +def GetArch(ItemList, ArchList, FileName, LineNo, SectionString): + # + # S1 is always Arch + # + if len(ItemList) > 1: + Arch = ItemList[1] + else: + Arch = 'COMMON' + ArchList.add(Arch) + + # + # 'COMMON' must not be used with specific ARCHs at the same section + # + if 'COMMON' in ArchList and len(ArchList) > 1: + Logger.Error('Parser', + FORMAT_INVALID, + ST.ERR_INF_PARSER_SECTION_ARCH_CONFLICT, + File=FileName, + Line=LineNo, + ExtraData=SectionString) + + return Arch, ArchList + +## InfSectionParser +# +# Inherit from object +# +class InfSectionParser(InfDefinSectionParser, + InfBuildOptionSectionParser, + InfSourceSectionParser, + InfLibrarySectionParser, + InfPackageSectionParser, + InfGuidPpiProtocolSectionParser, + InfBinarySectionParser, + InfPcdSectionParser, + InfDepexSectionParser): + # + # Parser objects used to implement singleton + # + MetaFiles = {} + + ## Factory method + # + # One file, one parser object. This factory method makes sure that there's + # only one object constructed for one meta file. + # + # @param Class class object of real AutoGen class + # (InfParser, DecParser or DscParser) + # @param FilePath The path of meta file + # + def __new__(cls, FilePath, *args, **kwargs): + if args: + pass + if kwargs: + pass + if FilePath in cls.MetaFiles: + return cls.MetaFiles[FilePath] + else: + ParserObject = super(InfSectionParser, cls).__new__(cls) + cls.MetaFiles[FilePath] = ParserObject + return ParserObject + + def __init__(self): + InfDefinSectionParser.__init__(self) + InfBuildOptionSectionParser.__init__(self) + InfSourceSectionParser.__init__(self) + InfLibrarySectionParser.__init__(self) + InfPackageSectionParser.__init__(self) + InfGuidPpiProtocolSectionParser.__init__(self) + InfBinarySectionParser.__init__(self) + InfPcdSectionParser.__init__(self) + InfDepexSectionParser.__init__(self) + # + # Initialize all objects that an INF file will generated. + # + self.InfDefSection = InfDefObject() + self.InfBuildOptionSection = InfBuildOptionsObject() + self.InfLibraryClassSection = InfLibraryClassObject() + self.InfPackageSection = InfPackageObject() + self.InfPcdSection = InfPcdObject(list(self.MetaFiles.keys())[0]) + self.InfSourcesSection = InfSourcesObject() + self.InfUserExtensionSection = InfUserExtensionObject() + self.InfProtocolSection = InfProtocolObject() + self.InfPpiSection = InfPpiObject() + self.InfGuidSection = InfGuidObject() + self.InfDepexSection = InfDepexObject() + self.InfPeiDepexSection = InfDepexObject() + self.InfDxeDepexSection = InfDepexObject() + self.InfSmmDepexSection = InfDepexObject() + self.InfBinariesSection = InfBinariesObject() + self.InfHeader = InfHeaderObject() + self.InfBinaryHeader = InfHeaderObject() + self.InfSpecialCommentSection = InfSpecialCommentObject() + + # + # A List for store define section content. + # + self._PcdNameList = [] + self._SectionName = '' + self._SectionType = 0 + self.RelaPath = '' + self.FileName = '' + + # + # File Header content parser + # + def InfHeaderParser(self, Content, InfHeaderObject2, FileName, IsBinaryHeader = False): + if IsBinaryHeader: + (Abstract, Description, Copyright, License) = ParseHeaderCommentSection(Content, FileName, True) + if not Abstract or not Description or not Copyright or not License: + Logger.Error('Parser', + FORMAT_INVALID, + ST.ERR_INVALID_BINARYHEADER_FORMAT, + File=FileName) + else: + (Abstract, Description, Copyright, License) = ParseHeaderCommentSection(Content, FileName) + # + # Not process file name now, for later usage. + # + if self.FileName: + pass + + # + # Insert Abstract, Description, CopyRight, License into header object + # + InfHeaderObject2.SetAbstract(Abstract) + InfHeaderObject2.SetDescription(Description) + InfHeaderObject2.SetCopyright(Copyright) + InfHeaderObject2.SetLicense(License) + + + + + ## Section header parser + # + # The section header is always in following format: + # + # [section_name.arch<.platform|module_type>] + # + # @param String A string contained the content need to be parsed. + # + def SectionHeaderParser(self, SectionString, FileName, LineNo): + _Scope = [] + _SectionName = '' + ArchList = set() + _ValueList = [] + _PcdNameList = [DT.TAB_INF_FIXED_PCD.upper(), + DT.TAB_INF_FEATURE_PCD.upper(), + DT.TAB_INF_PATCH_PCD.upper(), + DT.TAB_INF_PCD.upper(), + DT.TAB_INF_PCD_EX.upper() + ] + SectionString = SectionString.strip() + for Item in GetSplitValueList(SectionString[1:-1], DT.TAB_COMMA_SPLIT): + if Item == '': + Logger.Error('Parser', + FORMAT_INVALID, + ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % (""), + File=FileName, + Line=LineNo, + ExtraData=SectionString) + ItemList = GetSplitValueList(Item, DT.TAB_SPLIT) + # + # different section should not mix in one section + # Allow different PCD type sections mixed together + # + if _SectionName.upper() not in _PcdNameList: + if _SectionName != '' and _SectionName.upper() != ItemList[0].upper(): + Logger.Error('Parser', + FORMAT_INVALID, + ST.ERR_INF_PARSER_SECTION_NAME_DUPLICATE, + File=FileName, + Line=LineNo, + ExtraData=SectionString) + elif _PcdNameList[1] in [_SectionName.upper(), ItemList[0].upper()] and \ + (_SectionName.upper()!= ItemList[0].upper()): + Logger.Error('Parser', + FORMAT_INVALID, + ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % (""), + File=FileName, + Line=LineNo, + ExtraData=SectionString) + + _SectionName = ItemList[0] + if _SectionName.upper() in gINF_SECTION_DEF: + self._SectionType = gINF_SECTION_DEF[_SectionName.upper()] + else: + self._SectionType = DT.MODEL_UNKNOWN + Logger.Error("Parser", + FORMAT_INVALID, + ST.ERR_INF_PARSER_UNKNOWN_SECTION, + File=FileName, + Line=LineNo, + ExtraData=SectionString) + + # + # Get Arch + # + Str1, ArchList = GetArch(ItemList, ArchList, FileName, LineNo, SectionString) + + # + # For [Defines] section, do special check. + # + if ItemList[0].upper() == DT.TAB_COMMON_DEFINES.upper(): + if len(ItemList) != 1: + Logger.Error('Parser', + FORMAT_INVALID, + ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID % (SectionString), + File=FileName, Line=LineNo, ExtraData=SectionString) + + # + # For [UserExtension] section, do special check. + # + if ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper(): + + RetValue = ProcessUseExtHeader(ItemList) + + if not RetValue[0]: + Logger.Error('Parser', + FORMAT_INVALID, + ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID % (SectionString), + File=FileName, Line=LineNo, ExtraData=SectionString) + else: + ItemList = RetValue[1] + + if len(ItemList) == 3: + ItemList.append('COMMON') + + Str1 = ItemList[1] + + # + # For Library classes, need to check module type. + # + if ItemList[0].upper() == DT.TAB_LIBRARY_CLASSES.upper() and len(ItemList) == 3: + if ItemList[2] != '': + ModuleTypeList = GetSplitValueList(ItemList[2], DT.TAB_VALUE_SPLIT) + for Item in ModuleTypeList: + if Item.strip() not in DT.MODULE_LIST: + Logger.Error('Parser', + FORMAT_INVALID, + ST.ERR_INF_PARSER_DEFINE_MODULETYPE_INVALID % (Item), + File=FileName, + Line=LineNo, + ExtraData=SectionString) + # + # GetSpecialStr2 + # + Str2 = GetSpecialStr2(ItemList, FileName, LineNo, SectionString) + + _Scope.append([Str1, Str2]) + + _NewValueList = [] + _AppendFlag = True + if _SectionName.upper() in _PcdNameList: + for ValueItem in _ValueList: + if _SectionName.upper() == ValueItem[0].upper() and Str1.upper() not in ValueItem[1].split(): + ValueItem[1] = ValueItem[1] + " " + Str1 + _AppendFlag = False + elif _SectionName.upper() == ValueItem[0].upper() and Str1.upper() in ValueItem[1].split(): + _AppendFlag = False + + _NewValueList.append(ValueItem) + + _ValueList = _NewValueList + + if _AppendFlag: + if not ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper(): + _ValueList.append([_SectionName, Str1, Str2, LineNo]) + else: + if len(ItemList) == 4: + _ValueList.append([_SectionName, Str1, Str2, ItemList[3], LineNo]) + + self.SectionHeaderContent = deepcopy(_ValueList) + + ## GenSpecialSectionList + # + # @param SpecialSectionList: a list of list, of which item's format + # (Comment, LineNum) + # @param ContainerFile: Input value for filename of Inf file + # + def InfSpecialCommentParser (self, SpecialSectionList, InfSectionObject, ContainerFile, SectionType): + ReFindSpecialCommentRe = re.compile(r"""#(?:\s*)\[(.*?)\](?:.*)""", re.DOTALL) + ReFindHobArchRe = re.compile(r"""[Hh][Oo][Bb]\.([^,]*)""", re.DOTALL) + if self.FileName: + pass + SpecialObjectList = [] + ArchList = [] + if SectionType == DT.TYPE_EVENT_SECTION: + TokenDict = DT.EVENT_TOKENS + elif SectionType == DT.TYPE_HOB_SECTION: + TokenDict = DT.HOB_TOKENS + else: + TokenDict = DT.BOOTMODE_TOKENS + + for List in SpecialSectionList: + # + # Hob has Arch attribute, need to be handled specially here + # + if SectionType == DT.TYPE_HOB_SECTION: + + MatchObject = ReFindSpecialCommentRe.search(List[0][0]) + HobSectionStr = MatchObject.group(1) + ArchList = [] + for Match in ReFindHobArchRe.finditer(HobSectionStr): + Arch = Match.groups(1)[0].upper() + ArchList.append(Arch) + CommentSoFar = '' + for Index in range(1, len(List)): + Result = ParseComment(List[Index], DT.ALL_USAGE_TOKENS, TokenDict, [], False) + Usage = Result[0] + Type = Result[1] + HelpText = Result[3] + + if Usage == DT.ITEM_UNDEFINED and Type == DT.ITEM_UNDEFINED: + if HelpText is None: + HelpText = '' + if not HelpText.endswith('\n'): + HelpText += '\n' + CommentSoFar += HelpText + else: + if HelpText: + CommentSoFar += HelpText + if SectionType == DT.TYPE_EVENT_SECTION: + SpecialObject = InfEventObject() + SpecialObject.SetEventType(Type) + SpecialObject.SetUsage(Usage) + SpecialObject.SetHelpString(CommentSoFar) + elif SectionType == DT.TYPE_HOB_SECTION: + SpecialObject = InfHobObject() + SpecialObject.SetHobType(Type) + SpecialObject.SetUsage(Usage) + SpecialObject.SetHelpString(CommentSoFar) + if len(ArchList) >= 1: + SpecialObject.SetSupArchList(ArchList) + else: + SpecialObject = InfBootModeObject() + SpecialObject.SetSupportedBootModes(Type) + SpecialObject.SetUsage(Usage) + SpecialObject.SetHelpString(CommentSoFar) + + SpecialObjectList.append(SpecialObject) + CommentSoFar = '' + if not InfSectionObject.SetSpecialComments(SpecialObjectList, + SectionType): + Logger.Error('InfParser', + FORMAT_INVALID, + ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % (SectionType), + ContainerFile + ) diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfSourceSectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfSourceSectionParser.py new file mode 100755 index 00000000..ac61177a --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfSourceSectionParser.py @@ -0,0 +1,139 @@ +## @file +# This file contained the parser for [Sources] sections in INF file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +''' +InfSourceSectionParser +''' +## +# Import Modules +# + +import Logger.Log as Logger +from Logger import StringTable as ST +from Logger.ToolError import FORMAT_INVALID +from Parser.InfParserMisc import InfExpandMacro +from Library import DataType as DT +from Library.Parsing import MacroParser +from Library.Misc import GetSplitValueList +from Object.Parser.InfCommonObject import InfLineCommentObject +from Parser.InfParserMisc import InfParserSectionRoot + +class InfSourceSectionParser(InfParserSectionRoot): + ## InfSourceParser + # + # + def InfSourceParser(self, SectionString, InfSectionObject, FileName): + SectionMacros = {} + ValueList = [] + SourceList = [] + StillCommentFalg = False + HeaderComments = [] + LineComment = None + SectionContent = '' + for Line in SectionString: + SrcLineContent = Line[0] + SrcLineNo = Line[1] + + if SrcLineContent.strip() == '': + continue + + # + # Found Header Comments + # + if SrcLineContent.strip().startswith(DT.TAB_COMMENT_SPLIT): + # + # Last line is comments, and this line go on. + # + if StillCommentFalg: + HeaderComments.append(Line) + SectionContent += SrcLineContent + DT.END_OF_LINE + continue + # + # First time encounter comment + # + else: + # + # Clear original data + # + HeaderComments = [] + HeaderComments.append(Line) + StillCommentFalg = True + SectionContent += SrcLineContent + DT.END_OF_LINE + continue + else: + StillCommentFalg = False + + if len(HeaderComments) >= 1: + LineComment = InfLineCommentObject() + LineCommentContent = '' + for Item in HeaderComments: + LineCommentContent += Item[0] + DT.END_OF_LINE + LineComment.SetHeaderComments(LineCommentContent) + + # + # Find Tail comment. + # + if SrcLineContent.find(DT.TAB_COMMENT_SPLIT) > -1: + TailComments = SrcLineContent[SrcLineContent.find(DT.TAB_COMMENT_SPLIT):] + SrcLineContent = SrcLineContent[:SrcLineContent.find(DT.TAB_COMMENT_SPLIT)] + if LineComment is None: + LineComment = InfLineCommentObject() + LineComment.SetTailComments(TailComments) + + # + # Find Macro + # + Name, Value = MacroParser((SrcLineContent, SrcLineNo), + FileName, + DT.MODEL_EFI_SOURCE_FILE, + self.FileLocalMacros) + if Name is not None: + SectionMacros[Name] = Value + LineComment = None + HeaderComments = [] + continue + + # + # Replace with Local section Macro and [Defines] section Macro. + # + SrcLineContent = InfExpandMacro(SrcLineContent, + (FileName, SrcLineContent, SrcLineNo), + self.FileLocalMacros, + SectionMacros) + + TokenList = GetSplitValueList(SrcLineContent, DT.TAB_VALUE_SPLIT, 4) + ValueList[0:len(TokenList)] = TokenList + + # + # Store section content string after MACRO replaced. + # + SectionContent += SrcLineContent + DT.END_OF_LINE + + SourceList.append((ValueList, LineComment, + (SrcLineContent, SrcLineNo, FileName))) + ValueList = [] + LineComment = None + TailComments = '' + HeaderComments = [] + continue + + # + # Current section archs + # + ArchList = [] + for Item in self.LastSectionHeaderContent: + if Item[1] not in ArchList: + ArchList.append(Item[1]) + InfSectionObject.SetSupArchList(Item[1]) + + InfSectionObject.SetAllContent(SectionContent) + if not InfSectionObject.SetSources(SourceList, Arch = ArchList): + Logger.Error('InfParser', + FORMAT_INVALID, + ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % ("[Sources]"), + File=FileName, + Line=Item[3]) diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/__init__.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/__init__.py new file mode 100644 index 00000000..d6922c14 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/__init__.py @@ -0,0 +1,14 @@ +## @file +# Python 'Parser' package initialization file. +# +# This file is required to make Python interpreter treat the directory +# as containing package. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +Parser +''' diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/PomAdapter/DecPomAlignment.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/PomAdapter/DecPomAlignment.py new file mode 100755 index 00000000..354e493d --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/PomAdapter/DecPomAlignment.py @@ -0,0 +1,1000 @@ +## @file DecPomAlignment.py +# This file contained the adapter for convert INF parser object to POM Object +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +DecPomAlignment +''' +from __future__ import print_function + +## +# Import Modules +# +import os.path +from os import sep +import platform + +import re +import Logger.Log as Logger +from Logger import StringTable as ST +from Logger.ToolError import UPT_MUL_DEC_ERROR +from Logger.ToolError import FORMAT_INVALID + +from Library.Parsing import NormPath +from Library.DataType import ARCH_LIST +from Library.DataType import TAB_GUIDS +from Library.DataType import TAB_PROTOCOLS +from Library.DataType import TAB_PPIS +from Library.DataType import TAB_DEC_DEFINES_PACKAGE_NAME +from Library.DataType import TAB_DEC_DEFINES_PACKAGE_GUID +from Library.DataType import TAB_DEC_DEFINES_PACKAGE_VERSION +from Library.DataType import TAB_DEC_DEFINES_DEC_SPECIFICATION +from Library.DataType import TAB_DEC_DEFINES_PKG_UNI_FILE +from Library.DataType import TAB_ARCH_COMMON +from Library.DataType import TAB_INCLUDES +from Library.DataType import TAB_LIBRARY_CLASSES +from Library.DataType import TAB_PCDS +from Library.DataType import TAB_PCDS_FIXED_AT_BUILD_NULL +from Library.DataType import TAB_PCDS_PATCHABLE_IN_MODULE_NULL +from Library.DataType import TAB_PCDS_FEATURE_FLAG_NULL +from Library.DataType import TAB_PCDS_DYNAMIC_EX_NULL +from Library.DataType import TAB_PCDS_DYNAMIC_NULL +from Library.DataType import TAB_PTR_TYPE_PCD +from Library.DataType import ITEM_UNDEFINED +from Library.DataType import TAB_DEC_BINARY_ABSTRACT +from Library.DataType import TAB_DEC_BINARY_DESCRIPTION +from Library.DataType import TAB_LANGUAGE_EN_US +from Library.DataType import TAB_BINARY_HEADER_IDENTIFIER +from Library.DataType import TAB_BINARY_HEADER_USERID +from Library.DataType import TAB_LANGUAGE_EN_X +from Library.DataType import TAB_LANGUAGE_EN +from Library.DataType import TAB_STR_TOKENCNAME +from Library.DataType import TAB_STR_TOKENPROMPT +from Library.DataType import TAB_STR_TOKENHELP +from Library.DataType import TAB_STR_TOKENERR +from Library.DataType import TAB_HEX_START +from Library.DataType import TAB_SPLIT +import Library.DataType as DT +from Library.CommentParsing import ParseHeaderCommentSection +from Library.CommentParsing import ParseGenericComment +from Library.CommentParsing import ParseDecPcdGenericComment +from Library.CommentParsing import ParseDecPcdTailComment +from Library.Misc import GetFiles +from Library.Misc import Sdict +from Library.Misc import GetRelativePath +from Library.Misc import PathClass +from Library.Misc import ValidateUNIFilePath +from Library.UniClassObject import UniFileClassObject +from Library.UniClassObject import ConvertSpecialUnicodes +from Library.UniClassObject import GetLanguageCode1766 +from Library.ParserValidate import IsValidPath +from Parser.DecParser import Dec +from Object.POM.PackageObject import PackageObject +from Object.POM.CommonObject import UserExtensionObject +from Object.POM.CommonObject import IncludeObject +from Object.POM.CommonObject import GuidObject +from Object.POM.CommonObject import ProtocolObject +from Object.POM.CommonObject import PpiObject +from Object.POM.CommonObject import LibraryClassObject +from Object.POM.CommonObject import PcdObject +from Object.POM.CommonObject import TextObject +from Object.POM.CommonObject import MiscFileObject +from Object.POM.CommonObject import FileObject + + +## DecPomAlignment +# +# Inherited from PackageObject +# +class DecPomAlignment(PackageObject): + def __init__(self, Filename, WorkspaceDir = None, CheckMulDec = False): + PackageObject.__init__(self) + self.UserExtensions = '' + self.WorkspaceDir = WorkspaceDir + self.SupArchList = ARCH_LIST + self.CheckMulDec = CheckMulDec + self.DecParser = None + self.UniFileClassObject = None + self.PcdDefaultValueDict = {} + + # + # Load Dec file + # + self.LoadDecFile(Filename) + + # + # Transfer to Package Object if IsToPackage is True + # + self.DecToPackage() + + ## Load Dec file + # + # Load the file if it exists + # + # @param Filename: Input value for filename of Dec file + # + def LoadDecFile(self, Filename): + # + # Insert a record for file + # + Filename = NormPath(Filename) + (Path, Name) = os.path.split(Filename) + self.SetFullPath(Filename) + self.SetRelaPath(Path) + self.SetFileName(Name) + self.SetPackagePath(GetRelativePath(Path, self.WorkspaceDir)) + self.SetCombinePath(GetRelativePath(Filename, self.WorkspaceDir)) + + self.DecParser = Dec(Filename) + + ## Transfer to Package Object + # + # Transfer all contents of a Dec file to a standard Package Object + # + def DecToPackage(self): + # + # Init global information for the file + # + ContainerFile = self.GetFullPath() + + # + # Generate Package Header + # + self.GenPackageHeader(ContainerFile) + + # + # Generate Includes + # + self.GenIncludes(ContainerFile) + + # + # Generate Guids + # + self.GenGuidProtocolPpis(TAB_GUIDS, ContainerFile) + + # + # Generate Protocols + # + self.GenGuidProtocolPpis(TAB_PROTOCOLS, ContainerFile) + + # + # Generate Ppis + # + self.GenGuidProtocolPpis(TAB_PPIS, ContainerFile) + + # + # Generate LibraryClasses + # + self.GenLibraryClasses(ContainerFile) + + # + # Generate Pcds + # + self.GenPcds(ContainerFile) + + # + # Generate Module File list, will be used later on to generate + # distribution + # + self.GenModuleFileList(ContainerFile) + + # + # Generate user extensions + # + self.GenUserExtensions() + + ## Generate user extension + # + # + def GenUserExtensions(self): + UEObj = self.DecParser.GetUserExtensionSectionObject() + UEList = UEObj.GetAllUserExtensions() + for Item in UEList: + if not Item.UserString: + continue + UserExtension = UserExtensionObject() + UserId = Item.UserId + if UserId.startswith('"') and UserId.endswith('"'): + UserId = UserId[1:-1] + UserExtension.SetUserID(UserId) + Identifier = Item.IdString + if Identifier.startswith('"') and Identifier.endswith('"'): + Identifier = Identifier[1:-1] + # + # Generate miscellaneous files of DEC file + # + if UserId == 'TianoCore' and Identifier == 'ExtraFiles': + self.GenMiscFiles(Item.UserString) + UserExtension.SetIdentifier(Identifier) + UserExtension.SetStatement(Item.UserString) + UserExtension.SetSupArchList( + Item.ArchAndModuleType + ) + self.SetUserExtensionList( + self.GetUserExtensionList() + [UserExtension] + ) + + # Add Private sections to UserExtension + if self.DecParser.GetPrivateSections(): + PrivateUserExtension = UserExtensionObject() + PrivateUserExtension.SetStatement(self.DecParser.GetPrivateSections()) + PrivateUserExtension.SetIdentifier(DT.TAB_PRIVATE) + PrivateUserExtension.SetUserID(DT.TAB_INTEL) + self.SetUserExtensionList(self.GetUserExtensionList() + [PrivateUserExtension]) + + ## Generate miscellaneous files on DEC file + # + # + def GenMiscFiles(self, Content): + MiscFileObj = MiscFileObject() + for Line in Content.splitlines(): + FileName = '' + if '#' in Line: + FileName = Line[:Line.find('#')] + else: + FileName = Line + if FileName: + if IsValidPath(FileName, self.GetRelaPath()): + FileObj = FileObject() + FileObj.SetURI(FileName) + MiscFileObj.SetFileList(MiscFileObj.GetFileList()+[FileObj]) + else: + Logger.Error("InfParser", + FORMAT_INVALID, + ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID%(Line), + File=self.GetFileName(), + ExtraData=Line) + self.SetMiscFileList(self.GetMiscFileList()+[MiscFileObj]) + + ## Generate Package Header + # + # Gen Package Header of Dec as = + # + # @param ContainerFile: The Dec file full path + # + def GenPackageHeader(self, ContainerFile): + Logger.Debug(2, "Generate PackageHeader ...") + DefinesDict = {} + + # + # Update all defines item in database + # + DefObj = self.DecParser.GetDefineSectionObject() + for Item in DefObj.GetDefines(): + # + # put items into Dict except for PackageName, Guid, Version, DEC_SPECIFICATION + # + SkipItemList = [TAB_DEC_DEFINES_PACKAGE_NAME, \ + TAB_DEC_DEFINES_PACKAGE_GUID, TAB_DEC_DEFINES_PACKAGE_VERSION, \ + TAB_DEC_DEFINES_DEC_SPECIFICATION, TAB_DEC_DEFINES_PKG_UNI_FILE] + if Item.Key in SkipItemList: + continue + DefinesDict['%s = %s' % (Item.Key, Item.Value)] = TAB_ARCH_COMMON + + self.SetBaseName(DefObj.GetPackageName()) + self.SetVersion(DefObj.GetPackageVersion()) +# self.SetName(DefObj.GetPackageName() + ' Version ' + \ +# DefObj.GetPackageVersion()) + self.SetName(os.path.splitext(self.GetFileName())[0]) + self.SetGuid(DefObj.GetPackageGuid()) + if DefObj.GetPackageUniFile(): + ValidateUNIFilePath(DefObj.GetPackageUniFile()) + self.UniFileClassObject = \ + UniFileClassObject([PathClass(os.path.join(DefObj.GetPackagePath(), DefObj.GetPackageUniFile()))]) + else: + self.UniFileClassObject = None + + if DefinesDict: + UserExtension = UserExtensionObject() + UserExtension.SetDefinesDict(DefinesDict) + UserExtension.SetIdentifier('DefineModifiers') + UserExtension.SetUserID('EDK2') + self.SetUserExtensionList( + self.GetUserExtensionList() + [UserExtension] + ) + + # + # Get File header information + # + if self.UniFileClassObject: + Lang = TAB_LANGUAGE_EN_X + else: + Lang = TAB_LANGUAGE_EN_US + Abstract, Description, Copyright, License = \ + ParseHeaderCommentSection(self.DecParser.GetHeadComment(), + ContainerFile) + if Abstract: + self.SetAbstract((Lang, Abstract)) + if Description: + self.SetDescription((Lang, Description)) + if Copyright: + self.SetCopyright(('', Copyright)) + if License: + self.SetLicense(('', License)) + + # + # Get Binary header information + # + if self.DecParser.BinaryHeadComment: + Abstract, Description, Copyright, License = \ + ParseHeaderCommentSection(self.DecParser.BinaryHeadComment, + ContainerFile, True) + + if not Abstract or not Description or not Copyright or not License: + Logger.Error('MkPkg', + FORMAT_INVALID, + ST.ERR_INVALID_BINARYHEADER_FORMAT, + ContainerFile) + else: + self.SetBinaryHeaderAbstract((Lang, Abstract)) + self.SetBinaryHeaderDescription((Lang, Description)) + self.SetBinaryHeaderCopyright(('', Copyright)) + self.SetBinaryHeaderLicense(('', License)) + + BinaryAbstractList = [] + BinaryDescriptionList = [] + + #Get Binary header from UNI file + # Initialize the UniStrDict dictionary, top keys are language codes + UniStrDict = {} + if self.UniFileClassObject: + UniStrDict = self.UniFileClassObject.OrderedStringList + for Lang in UniStrDict: + for StringDefClassObject in UniStrDict[Lang]: + Lang = GetLanguageCode1766(Lang) + if StringDefClassObject.StringName == TAB_DEC_BINARY_ABSTRACT: + if (Lang, ConvertSpecialUnicodes(StringDefClassObject.StringValue)) \ + not in self.GetBinaryHeaderAbstract(): + BinaryAbstractList.append((Lang, ConvertSpecialUnicodes(StringDefClassObject.StringValue))) + if StringDefClassObject.StringName == TAB_DEC_BINARY_DESCRIPTION: + if (Lang, ConvertSpecialUnicodes(StringDefClassObject.StringValue)) \ + not in self.GetBinaryHeaderDescription(): + BinaryDescriptionList.append((Lang, + ConvertSpecialUnicodes(StringDefClassObject.StringValue))) + #Combine Binary header from DEC file and UNI file + BinaryAbstractList = self.GetBinaryHeaderAbstract() + BinaryAbstractList + BinaryDescriptionList = self.GetBinaryHeaderDescription() + BinaryDescriptionList + BinaryCopyrightList = self.GetBinaryHeaderCopyright() + BinaryLicenseList = self.GetBinaryHeaderLicense() + #Generate the UserExtensionObject for TianoCore."BinaryHeader" + if BinaryAbstractList or BinaryDescriptionList or BinaryCopyrightList or BinaryLicenseList: + BinaryUserExtension = UserExtensionObject() + BinaryUserExtension.SetBinaryAbstract(BinaryAbstractList) + BinaryUserExtension.SetBinaryDescription(BinaryDescriptionList) + BinaryUserExtension.SetBinaryCopyright(BinaryCopyrightList) + BinaryUserExtension.SetBinaryLicense(BinaryLicenseList) + BinaryUserExtension.SetIdentifier(TAB_BINARY_HEADER_IDENTIFIER) + BinaryUserExtension.SetUserID(TAB_BINARY_HEADER_USERID) + self.SetUserExtensionList(self.GetUserExtensionList() + [BinaryUserExtension]) + + + ## GenIncludes + # + # Gen Includes of Dec + # + # @param ContainerFile: The Dec file full path + # + def GenIncludes(self, ContainerFile): + if ContainerFile: + pass + Logger.Debug(2, "Generate %s ..." % TAB_INCLUDES) + IncludesDict = Sdict() + + IncObj = self.DecParser.GetIncludeSectionObject() + for Item in IncObj.GetAllIncludes(): + IncludePath = os.path.normpath(Item.File) + if platform.system() != 'Windows' and platform.system() != 'Microsoft': + IncludePath = IncludePath.replace('\\', '/') + if IncludePath in IncludesDict: + if Item.GetArchList() == [TAB_ARCH_COMMON] or IncludesDict[IncludePath] == [TAB_ARCH_COMMON]: + IncludesDict[IncludePath] = [TAB_ARCH_COMMON] + else: + IncludesDict[IncludePath] = IncludesDict[IncludePath] + Item.GetArchList() + else: + IncludesDict[IncludePath] = Item.GetArchList() + + # + # get the standardIncludeFileList(industry), packageIncludeFileList + # (others) for PackageObject + # + PackagePath = os.path.split(self.GetFullPath())[0] + IncludePathList = \ + sorted([os.path.normpath(Path) + sep for Path in IncludesDict.keys()]) + + # + # get a non-overlap set of include path, IncludePathList should be + # sorted, and path should be end with path separator '\' + # + NonOverLapList = [] + for Path1 in IncludePathList: + for Path2 in NonOverLapList: + if Path1.startswith(Path2): + break + else: + NonOverLapList.append(Path1) + # + # revert the list so the longest path shown first in list, also need + # to remove the extra path separator '\' + # as this list is used to search the supported Arch info + # + for IndexN in range (0, len(IncludePathList)): + IncludePathList[IndexN] = os.path.normpath(IncludePathList[IndexN]) + IncludePathList.sort() + IncludePathList.reverse() + # + # save the include path list for later usage + # + self.SetIncludePathList(IncludePathList) + StandardIncludeFileList = [] + PackageIncludeFileList = [] + + IncludeFileList = [] + for Path in NonOverLapList: + FileList = GetFiles(os.path.join(PackagePath, Path), ['CVS', '.svn'], False) + IncludeFileList += [os.path.normpath(os.path.join(Path, File)) for File in FileList] + for Includefile in IncludeFileList: + ExtName = os.path.splitext(Includefile)[1] + if ExtName.upper() == '.DEC' and self.CheckMulDec: + Logger.Error('MkPkg', + UPT_MUL_DEC_ERROR, + ST.ERR_MUL_DEC_ERROR%(os.path.dirname(ContainerFile), + os.path.basename(ContainerFile), + Includefile)) + + FileCombinePath = os.path.dirname(Includefile) + Include = IncludeObject() + for Path in IncludePathList: + if FileCombinePath.startswith(Path): + SupArchList = IncludesDict[Path] + break + Include.SetFilePath(Includefile) + Include.SetSupArchList(SupArchList) + if Includefile.find('IndustryStandard') != -1: + StandardIncludeFileList.append(Include) + else: + PackageIncludeFileList.append(Include) + + self.SetStandardIncludeFileList(StandardIncludeFileList) + + # + # put include path into the PackageIncludeFileList + # + PackagePathList = [] + IncObj = self.DecParser.GetIncludeSectionObject() + for Item in IncObj.GetAllIncludes(): + IncludePath = Item.File + Include = IncludeObject() + Include.SetFilePath(IncludePath) + Include.SetSupArchList(Item.GetArchList()) + PackagePathList.append(Include) + self.SetPackageIncludeFileList(PackagePathList + PackageIncludeFileList) + + ## GenPpis + # + # Gen Ppis of Dec + # = + # + # @param ContainerFile: The Dec file full path + # + def GenGuidProtocolPpis(self, Type, ContainerFile): + if ContainerFile: + pass + Logger.Debug(2, "Generate %s ..." % Type) + + Obj = None + Factory = None + if Type == TAB_GUIDS: + Obj = self.DecParser.GetGuidSectionObject() + def CreateGuidObject(): + Object = GuidObject() + Object.SetGuidTypeList([]) + Object.SetUsage(None) + Object.SetName(None) + return Object + Factory = CreateGuidObject + elif Type == TAB_PROTOCOLS: + Obj = self.DecParser.GetProtocolSectionObject() + + def CreateProtocolObject(): + return ProtocolObject() + Factory = CreateProtocolObject + elif Type == TAB_PPIS: + Obj = self.DecParser.GetPpiSectionObject() + + def CreatePpiObject(): + return PpiObject() + Factory = CreatePpiObject + else: + # + # Should not be here + # + return + + DeclarationsList = [] + + # + # Go through each arch + # + for Item in Obj.GetGuidStyleAllItems(): + Name = Item.GuidCName + Value = Item.GuidString + HelpTxt = ParseGenericComment(Item.GetHeadComment() + \ + Item.GetTailComment()) + + ListObject = Factory() + ListObject.SetCName(Name) + ListObject.SetGuid(Value) + ListObject.SetSupArchList(Item.GetArchList()) + if HelpTxt: + if self.UniFileClassObject: + HelpTxt.SetLang(TAB_LANGUAGE_EN_X) + ListObject.SetHelpTextList([HelpTxt]) + + DeclarationsList.append(ListObject) + + # + #GuidTypeList is abstracted from help + # + if Type == TAB_GUIDS: + self.SetGuidList(self.GetGuidList() + DeclarationsList) + elif Type == TAB_PROTOCOLS: + self.SetProtocolList(self.GetProtocolList() + DeclarationsList) + elif Type == TAB_PPIS: + self.SetPpiList(self.GetPpiList() + DeclarationsList) + + ## GenLibraryClasses + # + # Gen LibraryClasses of Dec + # = + # + # @param ContainerFile: The Dec file full path + # + def GenLibraryClasses(self, ContainerFile): + if ContainerFile: + pass + Logger.Debug(2, "Generate %s ..." % TAB_LIBRARY_CLASSES) + LibraryClassDeclarations = [] + + LibObj = self.DecParser.GetLibraryClassSectionObject() + for Item in LibObj.GetAllLibraryclasses(): + LibraryClass = LibraryClassObject() + LibraryClass.SetLibraryClass(Item.Libraryclass) + LibraryClass.SetSupArchList(Item.GetArchList()) + LibraryClass.SetIncludeHeader(Item.File) + HelpTxt = ParseGenericComment(Item.GetHeadComment() + \ + Item.GetTailComment(), None, '@libraryclass') + if HelpTxt: + if self.UniFileClassObject: + HelpTxt.SetLang(TAB_LANGUAGE_EN_X) + LibraryClass.SetHelpTextList([HelpTxt]) + LibraryClassDeclarations.append(LibraryClass) + + self.SetLibraryClassList(self.GetLibraryClassList() + \ + LibraryClassDeclarations) + + ## GenPcds + # + # Gen Pcds of Dec + # .||| + # + # @param ContainerFile: The Dec file full path + # + def GenPcds(self, ContainerFile): + Logger.Debug(2, "Generate %s ..." % TAB_PCDS) + PcdObj = self.DecParser.GetPcdSectionObject() + # + # Get all Pcds + # + PcdDeclarations = [] + IterList = [ + (TAB_PCDS_FIXED_AT_BUILD_NULL, 'FixedPcd'), + (TAB_PCDS_PATCHABLE_IN_MODULE_NULL, 'PatchPcd'), + (TAB_PCDS_FEATURE_FLAG_NULL, 'FeaturePcd'), + (TAB_PCDS_DYNAMIC_EX_NULL, 'PcdEx'), + (TAB_PCDS_DYNAMIC_NULL, 'Pcd')] + + PromptStrList = [] + HelpStrList = [] + PcdErrStrList = [] + # Initialize UniStrDict dictionary, top keys are language codes + UniStrDict = {} + StrList = [] + + Language = '' + if self.UniFileClassObject: + Language = TAB_LANGUAGE_EN_X + else: + Language = TAB_LANGUAGE_EN_US + + if self.UniFileClassObject: + UniStrDict = self.UniFileClassObject.OrderedStringList + for Lang in UniStrDict: + for StringDefClassObject in UniStrDict[Lang]: + StrList = StringDefClassObject.StringName.split('_') + # StringName format is STR___PROMPT + if len(StrList) == 4 and StrList[0] == TAB_STR_TOKENCNAME and StrList[3] == TAB_STR_TOKENPROMPT: + PromptStrList.append((GetLanguageCode1766(Lang), StringDefClassObject.StringName, \ + StringDefClassObject.StringValue)) + # StringName format is STR___HELP + if len(StrList) == 4 and StrList[0] == TAB_STR_TOKENCNAME and StrList[3] == TAB_STR_TOKENHELP: + HelpStrList.append((GetLanguageCode1766(Lang), StringDefClassObject.StringName, \ + StringDefClassObject.StringValue)) + # StringName format is STR__ERR_## + if len(StrList) == 4 and StrList[0] == TAB_STR_TOKENCNAME and StrList[2] == TAB_STR_TOKENERR: + PcdErrStrList.append((GetLanguageCode1766(Lang), StringDefClassObject.StringName, \ + StringDefClassObject.StringValue)) + # + # For each PCD type + # + for PcdType, Type in IterList: + # + # Go through all archs + # + # for Arch in self.SupArchList + [TAB_ARCH_COMMON]: + # + for Item in PcdObj.GetPcdsByType(PcdType.upper()): + PcdDeclaration = GenPcdDeclaration( + ContainerFile, + (Item.TokenSpaceGuidCName, Item.TokenCName, + Item.DefaultValue, Item.DatumType, Item.TokenValue, + Type, Item.GetHeadComment(), Item.GetTailComment(), ''), + Language, + self.DecParser.GetDefineSectionMacro() + ) + PcdDeclaration.SetSupArchList(Item.GetArchListOfType(PcdType)) + + # + # Get PCD error message from PCD error comment section in DEC file + # + for PcdErr in PcdDeclaration.GetPcdErrorsList(): + if (PcdDeclaration.GetTokenSpaceGuidCName(), PcdErr.GetErrorNumber()) \ + in self.DecParser.PcdErrorCommentDict: + Key = (PcdDeclaration.GetTokenSpaceGuidCName(), PcdErr.GetErrorNumber()) + PcdErr.SetErrorMessageList(PcdErr.GetErrorMessageList() + \ + [(Language, self.DecParser.PcdErrorCommentDict[Key])]) + + for Index in range(0, len(PromptStrList)): + StrNameList = PromptStrList[Index][1].split('_') + if StrNameList[1].lower() == Item.TokenSpaceGuidCName.lower() and \ + StrNameList[2].lower() == Item.TokenCName.lower(): + TxtObj = TextObject() + TxtObj.SetLang(PromptStrList[Index][0]) + TxtObj.SetString(PromptStrList[Index][2]) + for Prompt in PcdDeclaration.GetPromptList(): + if Prompt.GetLang() == TxtObj.GetLang() and \ + Prompt.GetString() == TxtObj.GetString(): + break + else: + PcdDeclaration.SetPromptList(PcdDeclaration.GetPromptList() + [TxtObj]) + + for Index in range(0, len(HelpStrList)): + StrNameList = HelpStrList[Index][1].split('_') + if StrNameList[1].lower() == Item.TokenSpaceGuidCName.lower() and \ + StrNameList[2].lower() == Item.TokenCName.lower(): + TxtObj = TextObject() + TxtObj.SetLang(HelpStrList[Index][0]) + TxtObj.SetString(HelpStrList[Index][2]) + for HelpStrObj in PcdDeclaration.GetHelpTextList(): + if HelpStrObj.GetLang() == TxtObj.GetLang() and \ + HelpStrObj.GetString() == TxtObj.GetString(): + break + else: + PcdDeclaration.SetHelpTextList(PcdDeclaration.GetHelpTextList() + [TxtObj]) + + # + # Get PCD error message from UNI file + # + for Index in range(0, len(PcdErrStrList)): + StrNameList = PcdErrStrList[Index][1].split('_') + if StrNameList[1].lower() == Item.TokenSpaceGuidCName.lower() and \ + StrNameList[2].lower() == TAB_STR_TOKENERR.lower(): + for PcdErr in PcdDeclaration.GetPcdErrorsList(): + if PcdErr.GetErrorNumber().lower() == (TAB_HEX_START + StrNameList[3]).lower() and \ + (PcdErrStrList[Index][0], PcdErrStrList[Index][2]) not in PcdErr.GetErrorMessageList(): + PcdErr.SetErrorMessageList(PcdErr.GetErrorMessageList() + \ + [(PcdErrStrList[Index][0], PcdErrStrList[Index][2])]) + + # + # Check to prevent missing error message if a Pcd has the error code. + # + for PcdErr in PcdDeclaration.GetPcdErrorsList(): + if PcdErr.GetErrorNumber().strip(): + if not PcdErr.GetErrorMessageList(): + Logger.Error('UPT', + FORMAT_INVALID, + ST.ERR_DECPARSE_PCD_UNMATCHED_ERRORCODE % PcdErr.GetErrorNumber(), + ContainerFile, + PcdErr.GetLineNum(), + PcdErr.GetFileLine()) + + PcdDeclarations.append(PcdDeclaration) + self.SetPcdList(self.GetPcdList() + PcdDeclarations) + self.CheckPcdValue() + + ## + # Get error message via language + # @param ErrorMessageList: Error message tuple list the language and its message + # @param Lang: the language of setting + # @return: the error message described in the related UNI file + def GetEnErrorMessage(self, ErrorMessageList): + if self.FullPath: + pass + Lang = TAB_LANGUAGE_EN_US + for (Language, Message) in ErrorMessageList: + if Language == Lang: + return Message + for (Language, Message) in ErrorMessageList: + if Language.find(TAB_LANGUAGE_EN) >= 0: + return Message + else: + try: + return ErrorMessageList[0][1] + except IndexError: + return '' + return '' + + ## + # Replace the strings for Python eval function. + # @param ReplaceValue: The string that needs to be replaced. + # @return: The string was replaced, then eval function is always making out it. + def ReplaceForEval(self, ReplaceValue, IsRange=False, IsExpr=False): + if self.FullPath: + pass + # + # deal with "NOT EQ", "NOT LT", "NOT GT", "NOT LE", "NOT GE", "NOT NOT" + # + NOTNOT_Pattern = '[\t\s]*NOT[\t\s]+NOT[\t\s]*' + NOTGE_Pattern = '[\t\s]*NOT[\t\s]+GE[\t\s]*' + NOTLE_Pattern = '[\t\s]*NOT[\t\s]+LE[\t\s]*' + NOTGT_Pattern = '[\t\s]*NOT[\t\s]+GT[\t\s]*' + NOTLT_Pattern = '[\t\s]*NOT[\t\s]+LT[\t\s]*' + NOTEQ_Pattern = '[\t\s]*NOT[\t\s]+EQ[\t\s]*' + ReplaceValue = re.compile(NOTNOT_Pattern).sub('', ReplaceValue) + ReplaceValue = re.compile(NOTLT_Pattern).sub('x >= ', ReplaceValue) + ReplaceValue = re.compile(NOTGT_Pattern).sub('x <= ', ReplaceValue) + ReplaceValue = re.compile(NOTLE_Pattern).sub('x > ', ReplaceValue) + ReplaceValue = re.compile(NOTGE_Pattern).sub('x < ', ReplaceValue) + ReplaceValue = re.compile(NOTEQ_Pattern).sub('x != ', ReplaceValue) + + if IsRange: + ReplaceValue = ReplaceValue.replace('EQ', 'x ==') + ReplaceValue = ReplaceValue.replace('LT', 'x <') + ReplaceValue = ReplaceValue.replace('LE', 'x <=') + ReplaceValue = ReplaceValue.replace('GT', 'x >') + ReplaceValue = ReplaceValue.replace('GE', 'x >=') + ReplaceValue = ReplaceValue.replace('XOR', 'x ^') + elif IsExpr: + ReplaceValue = ReplaceValue.replace('EQ', '==') + ReplaceValue = ReplaceValue.replace('NE', '!=') + ReplaceValue = ReplaceValue.replace('LT', '<') + ReplaceValue = ReplaceValue.replace('LE', '<=') + ReplaceValue = ReplaceValue.replace('GT', '>') + ReplaceValue = ReplaceValue.replace('GE', '>=') + ReplaceValue = ReplaceValue.replace('XOR', '^') + + ReplaceValue = ReplaceValue.replace('AND', 'and') + ReplaceValue = ReplaceValue.replace('&&', ' and ') + ReplaceValue = ReplaceValue.replace('xor', '^') + ReplaceValue = ReplaceValue.replace('OR', 'or') + ReplaceValue = ReplaceValue.replace('||', ' or ') + ReplaceValue = ReplaceValue.replace('NOT', 'not') + if ReplaceValue.find('!') >= 0 and ReplaceValue[ReplaceValue.index('!') + 1] != '=': + ReplaceValue = ReplaceValue.replace('!', ' not ') + if '.' in ReplaceValue: + Pattern = '[a-zA-Z0-9]{1,}\.[a-zA-Z0-9]{1,}' + MatchedList = re.findall(Pattern, ReplaceValue) + for MatchedItem in MatchedList: + if MatchedItem not in self.PcdDefaultValueDict: + Logger.Error("Dec File Parser", FORMAT_INVALID, Message=ST.ERR_DECPARSE_PCD_NODEFINED % MatchedItem, + File=self.FullPath) + + ReplaceValue = ReplaceValue.replace(MatchedItem, self.PcdDefaultValueDict[MatchedItem]) + + return ReplaceValue + + ## + # Check pcd's default value according to the pcd's description + # + def CheckPcdValue(self): + for Pcd in self.GetPcdList(): + self.PcdDefaultValueDict[TAB_SPLIT.join((Pcd.GetTokenSpaceGuidCName(), Pcd.GetCName())).strip()] = \ + Pcd.GetDefaultValue() + + for Pcd in self.GetPcdList(): + ValidationExpressions = [] + PcdGuidName = TAB_SPLIT.join((Pcd.GetTokenSpaceGuidCName(), Pcd.GetCName())) + Valids = Pcd.GetPcdErrorsList() + for Valid in Valids: + Expression = Valid.GetExpression() + if Expression: + # + # Delete the 'L' prefix of a quoted string, this operation is for eval() + # + QUOTED_PATTERN = '[\t\s]*L?"[^"]*"' + QuotedMatchedObj = re.search(QUOTED_PATTERN, Expression) + if QuotedMatchedObj: + MatchedStr = QuotedMatchedObj.group().strip() + if MatchedStr.startswith('L'): + Expression = Expression.replace(MatchedStr, MatchedStr[1:].strip()) + + Expression = self.ReplaceForEval(Expression, IsExpr=True) + Expression = Expression.replace(PcdGuidName, 'x') + Message = self.GetEnErrorMessage(Valid.GetErrorMessageList()) + ValidationExpressions.append((Expression, Message)) + + ValidList = Valid.GetValidValue() + if ValidList: + ValidValue = 'x in %s' % [eval(v) for v in ValidList.split(' ') if v] + Message = self.GetEnErrorMessage(Valid.GetErrorMessageList()) + ValidationExpressions.append((ValidValue, Message)) + + ValidValueRange = Valid.GetValidValueRange() + if ValidValueRange: + ValidValueRange = self.ReplaceForEval(ValidValueRange, IsRange=True) + if ValidValueRange.find('-') >= 0: + ValidValueRange = ValidValueRange.replace('-', '<= x <=') + elif not ValidValueRange.startswith('x ') and not ValidValueRange.startswith('not ') \ + and not ValidValueRange.startswith('not(') and not ValidValueRange.startswith('('): + ValidValueRange = 'x %s' % ValidValueRange + Message = self.GetEnErrorMessage(Valid.GetErrorMessageList()) + ValidationExpressions.append((ValidValueRange, Message)) + + DefaultValue = self.PcdDefaultValueDict[PcdGuidName.strip()] + # + # Delete the 'L' prefix of a quoted string, this operation is for eval() + # + QUOTED_PATTERN = '[\t\s]*L?"[^"]*"' + QuotedMatchedObj = re.search(QUOTED_PATTERN, DefaultValue) + if QuotedMatchedObj: + MatchedStr = QuotedMatchedObj.group().strip() + if MatchedStr.startswith('L'): + DefaultValue = DefaultValue.replace(MatchedStr, MatchedStr[1:].strip()) + + try: + DefaultValue = eval(DefaultValue.replace('TRUE', 'True').replace('true', 'True') + .replace('FALSE', 'False').replace('false', 'False')) + except BaseException: + pass + + for (Expression, Msg) in ValidationExpressions: + try: + if not eval(Expression, {'x':DefaultValue}): + Logger.Error("Dec File Parser", FORMAT_INVALID, ExtraData='%s, value = %s' %\ + (PcdGuidName, DefaultValue), Message=Msg, File=self.FullPath) + except TypeError: + Logger.Error("Dec File Parser", FORMAT_INVALID, ExtraData=PcdGuidName, \ + Message=Msg, File=self.FullPath) + + ## GenModuleFileList + # + def GenModuleFileList(self, ContainerFile): + ModuleFileList = [] + ContainerFileName = os.path.basename(ContainerFile) + ContainerFilePath = os.path.dirname(ContainerFile) + for Item in GetFiles(ContainerFilePath, + ['CVS', '.svn'] + self.GetIncludePathList(), False): + ExtName = os.path.splitext(Item)[1] + if ExtName.lower() == '.inf': + ModuleFileList.append(Item) + elif ExtName.upper() == '.DEC' and self.CheckMulDec: + if Item == ContainerFileName: + continue + Logger.Error('MkPkg', + UPT_MUL_DEC_ERROR, + ST.ERR_MUL_DEC_ERROR%(ContainerFilePath, + ContainerFileName, + Item)) + + self.SetModuleFileList(ModuleFileList) + + ## Show detailed information of Package + # + # Print all members and their values of Package class + # + def ShowPackage(self): + print('\nName =', self.GetName()) + print('\nBaseName =', self.GetBaseName()) + print('\nVersion =', self.GetVersion()) + print('\nGuid =', self.GetGuid()) + + print('\nStandardIncludes = %d ' \ + % len(self.GetStandardIncludeFileList()), end=' ') + for Item in self.GetStandardIncludeFileList(): + print(Item.GetFilePath(), ' ', Item.GetSupArchList()) + print('\nPackageIncludes = %d \n' \ + % len(self.GetPackageIncludeFileList()), end=' ') + for Item in self.GetPackageIncludeFileList(): + print(Item.GetFilePath(), ' ', Item.GetSupArchList()) + + print('\nGuids =', self.GetGuidList()) + for Item in self.GetGuidList(): + print(Item.GetCName(), Item.GetGuid(), Item.GetSupArchList()) + print('\nProtocols =', self.GetProtocolList()) + for Item in self.GetProtocolList(): + print(Item.GetCName(), Item.GetGuid(), Item.GetSupArchList()) + print('\nPpis =', self.GetPpiList()) + for Item in self.GetPpiList(): + print(Item.GetCName(), Item.GetGuid(), Item.GetSupArchList()) + print('\nLibraryClasses =', self.GetLibraryClassList()) + for Item in self.GetLibraryClassList(): + print(Item.GetLibraryClass(), Item.GetRecommendedInstance(), \ + Item.GetSupArchList()) + print('\nPcds =', self.GetPcdList()) + for Item in self.GetPcdList(): + print('CName=', Item.GetCName(), 'TokenSpaceGuidCName=', \ + Item.GetTokenSpaceGuidCName(), \ + 'DefaultValue=', Item.GetDefaultValue(), \ + 'ValidUsage=', Item.GetValidUsage(), \ + 'SupArchList', Item.GetSupArchList(), \ + 'Token=', Item.GetToken(), 'DatumType=', Item.GetDatumType()) + + for Item in self.GetMiscFileList(): + print(Item.GetName()) + for FileObjectItem in Item.GetFileList(): + print(FileObjectItem.GetURI()) + print('****************\n') + +## GenPcdDeclaration +# +# @param ContainerFile: File name of the DEC file +# @param PcdInfo: Pcd information, of format (TokenGuidCName, +# TokenName, Value, DatumType, Token, Type, +# GenericComment, TailComment, Arch) +# @param Language: The language of HelpText, Prompt +# +def GenPcdDeclaration(ContainerFile, PcdInfo, Language, MacroReplaceDict): + HelpStr = '' + PromptStr = '' + TailHelpStr = '' + TokenGuidCName, TokenName, Value, DatumType, Token, Type, \ + GenericComment, TailComment, Arch = PcdInfo + Pcd = PcdObject() + Pcd.SetCName(TokenName) + Pcd.SetToken(Token) + Pcd.SetTokenSpaceGuidCName(TokenGuidCName) + Pcd.SetDatumType(DatumType) + Pcd.SetDefaultValue(Value) + Pcd.SetValidUsage(Type) + # + # MaxDatumSize is required field for 'VOID*' PCD + # + if DatumType == TAB_PTR_TYPE_PCD: + Pcd.SetMaxDatumSize(ITEM_UNDEFINED) + + SupArchList = [Arch] + Pcd.SetSupArchList(SupArchList) + + if GenericComment: + HelpStr, PcdErrList, PromptStr = ParseDecPcdGenericComment(GenericComment, + ContainerFile, + TokenGuidCName, + TokenName, + MacroReplaceDict) + if PcdErrList: + Pcd.SetPcdErrorsList(PcdErrList) + + if TailComment: + SupModuleList, TailHelpStr = ParseDecPcdTailComment(TailComment, + ContainerFile) + if SupModuleList: + Pcd.SetSupModuleList(SupModuleList) + + if HelpStr and (not HelpStr.endswith('\n')) and TailHelpStr: + HelpStr += '\n' + HelpStr += TailHelpStr + if HelpStr: + HelpTxtObj = TextObject() + HelpTxtObj.SetLang(Language) + HelpTxtObj.SetString(HelpStr) + Pcd.SetHelpTextList([HelpTxtObj]) + if PromptStr: + TxtObj = TextObject() + TxtObj.SetLang(Language) + TxtObj.SetString(PromptStr) + Pcd.SetPromptList([TxtObj]) + + return Pcd diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/PomAdapter/InfPomAlignment.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/PomAdapter/InfPomAlignment.py new file mode 100755 index 00000000..184c36c6 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/PomAdapter/InfPomAlignment.py @@ -0,0 +1,1071 @@ +## @file InfPomAlignment.py +# This file contained the adapter for convert INF parser object to POM Object +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +''' +InfPomAlignment +''' +## +# Import modules +# +import os.path +from Logger import StringTable as ST +import Logger.Log as Logger +from Library.StringUtils import FORMAT_INVALID +from Library.StringUtils import PARSER_ERROR +from Library.StringUtils import NormPath +from Library.StringUtils import GetSplitValueList +from Library.Misc import ConvertVersionToDecimal +from Library.Misc import GetHelpStringByRemoveHashKey +from Library.Misc import ConvertArchList +from Library.Misc import GetRelativePath +from Library.Misc import PathClass +from Library.Parsing import GetPkgInfoFromDec +from Library.UniClassObject import UniFileClassObject +from Library.UniClassObject import ConvertSpecialUnicodes +from Library.UniClassObject import GetLanguageCode1766 +from Library import DataType as DT +from Library import GlobalData +from Library.ParserValidate import IsValidPath +from Object.POM import CommonObject +from Object.POM.ModuleObject import ModuleObject +from Object.POM.ModuleObject import ExternObject +from Object.POM.ModuleObject import HobObject +from Object.POM.ModuleObject import EventObject +from Object.POM.ModuleObject import BootModeObject +from Object.POM.ModuleObject import PackageDependencyObject +from Object.POM.ModuleObject import SourceFileObject +from Object.POM.ModuleObject import DepexObject +from Object.POM.ModuleObject import AsBuildLibraryClassObject +from Object.POM.ModuleObject import AsBuiltObject +from PomAdapter.InfPomAlignmentMisc import GenModuleHeaderUserExt +from PomAdapter.InfPomAlignmentMisc import GenBinaryData +from Parser import InfParser +from PomAdapter.DecPomAlignment import DecPomAlignment +from Common.MultipleWorkspace import MultipleWorkspace as mws + +## InfPomAlignment +# +# Inherit from ModuleObject +# +class InfPomAlignment(ModuleObject): + ## Construct of InfPomAlignment + # Skip means that UPT don't care the syntax of INF, this may be the not + # distributed INF files during creation or the INF files checked for + # dependency rule during remove. + # + def __init__(self, FileName, WorkSpace=None, PackagePath='', Skip=False): + ModuleObject.__init__(self) + self.Parser = None + self.FileName = FileName + self.WorkSpace = WorkSpace + self.CombinePath = '' + self.LibModuleTypeList = [] + self.FullPath = '' + self.ModulePath = '' + self.WorkspaceDir = " " + self.CustomMakefile = [] + self.UniFileClassObject = None + self.SetPackagePath(PackagePath) + # + # Call GenInfPomObjects function to fill POM object. + # + if Skip: + OrigConfig = Logger.SUPRESS_ERROR + Logger.SUPRESS_ERROR = True + try: + self._GenInfPomObjects(Skip) + finally: + Logger.SUPRESS_ERROR = OrigConfig + else: + self._GenInfPomObjects(Skip) + + ## + # Generate all POM objects, the original input comes + # from INF parser's output + # + def _GenInfPomObjects(self, Skip): + # + # Call INF Parser to get information from INF file + # + self.Parser = InfParser.InfParser(self.FileName, self.WorkSpace) + self.FullPath = self.Parser.FullPath + self.GetFullPath() + self._GenModuleHeader() + # + # Call GenBinaries after Module Header for Binary INF consideration. + # + self._GenBinaries() + self._GenBuildOptions() + self._GenLibraryClasses() + self._GenPackages(Skip) + self._GenPcds() + self._GenSources() + self._GenUserExtensions() + self._GenGuidProtocolPpis(DT.TAB_GUIDS) + self._GenGuidProtocolPpis(DT.TAB_PROTOCOLS) + self._GenGuidProtocolPpis(DT.TAB_PPIS) + self._GenDepexes() + + ## Convert [Defines] section content to InfDefObject + # + # Convert [Defines] section content to InfDefObject + # + # @param Defines The content under [Defines] section + # @param ModuleHeader An object of ModuleHeaderClass + # @param Arch The supported ARCH + # + def _GenModuleHeader(self): + Logger.Debug(2, "Generate ModuleHeader ...") + # + # Get all defines information form InfParser Object + # + RecordSet = self.Parser.InfDefSection.Defines + # + # Should only have one ArchString Item. + # + ArchString = list(RecordSet.keys())[0] + ArchList = GetSplitValueList(ArchString, ' ') + ArchList = ConvertArchList(ArchList) + HasCalledFlag = False + # + # Get data from Sdict() + # + ValueList = RecordSet[ArchString] + self.SetFileName(self.FileName) + self.SetFullPath(self.FullPath) + # + # The INF's filename (without the directory path or the extension) + # must be used for the value of the + # ModuleSurfaceArea.Header.Name element + # + self.SetName(os.path.splitext(os.path.basename(self.FileName))[0]) + self.WorkspaceDir = " " + # + # CombinePath and ModulePath + # + CombinePath = GetRelativePath(self.FullPath, self.WorkSpace) + self.SetCombinePath(CombinePath) + ModulePath = os.path.split(CombinePath)[0] + ModuleRelativePath = ModulePath + if self.GetPackagePath() != '': + ModuleRelativePath = GetRelativePath(ModulePath, self.GetPackagePath()) + self.SetModulePath(ModuleRelativePath) + # + # For Define Seciton Items. + # + DefineObj = ValueList + # + # Convert UEFI/PI version to decimal number + # + if DefineObj.GetUefiSpecificationVersion() is not None: + __UefiVersion = DefineObj.GetUefiSpecificationVersion().GetValue() + __UefiVersion = ConvertVersionToDecimal(__UefiVersion) + self.SetUefiSpecificationVersion(str(__UefiVersion)) + if DefineObj.GetPiSpecificationVersion() is not None: + __PiVersion = DefineObj.GetPiSpecificationVersion().GetValue() + __PiVersion = ConvertVersionToDecimal(__PiVersion) + + self.SetPiSpecificationVersion(str(__PiVersion)) + SpecList = DefineObj.GetSpecification() + NewSpecList = [] + for SpecItem in SpecList: + NewSpecList.append((SpecItem[0], ConvertVersionToDecimal(SpecItem[1]))) + self.SetSpecList(NewSpecList) + + # + # must exist items in INF define section + # MODULE_TYPE/BASE_NAME/INF_VERSION/FILE_GUID/VERSION_STRING + # + if DefineObj.GetModuleType() is None: + Logger.Error("InfParser", FORMAT_INVALID, + ST.ERR_INF_PARSER_DEFINE_SECTION_MUST_ITEM_NOT_EXIST % ("MODULE_TYPE"), File=self.FullPath) + else: + self.SetModuleType(DefineObj.GetModuleType().GetValue()) + ModuleType = DefineObj.GetModuleType().GetValue() + if ModuleType: + # + # Drivers and applications are not allowed to have a MODULE_TYPE of "BASE". Only + # libraries are permitted to a have a MODULE_TYPE of "BASE". + # + if len(DefineObj.LibraryClass) == 0 and ModuleType == 'BASE': + Logger.Error("InfParser", + FORMAT_INVALID, + ST.ERR_INF_PARSER_MODULETYPE_INVALID, + File=self.FullPath, + Line=DefineObj.ModuleType.CurrentLine.LineNo, + ExtraData=DefineObj.ModuleType.CurrentLine.LineString) + self.LibModuleTypeList.append(ModuleType) + if DefineObj.GetBaseName() is None: + Logger.Error("InfParser", FORMAT_INVALID, + ST.ERR_INF_PARSER_DEFINE_SECTION_MUST_ITEM_NOT_EXIST % ("BASE_NAME"), File=self.FullPath) + else: + self.SetBaseName(DefineObj.GetBaseName().GetValue()) + if DefineObj.GetModuleUniFileName(): + self.UniFileClassObject = UniFileClassObject([PathClass(DefineObj.GetModuleUniFileName())]) + else: + self.UniFileClassObject = None + if DefineObj.GetInfVersion() is None: + Logger.Error("InfParser", FORMAT_INVALID, + ST.ERR_INF_PARSER_DEFINE_SECTION_MUST_ITEM_NOT_EXIST % ("INF_VERSION"), File=self.FullPath) + else: + self.SetVersion(DefineObj.GetInfVersion().GetValue()) + if DefineObj.GetFileGuid() is None: + Logger.Error("InfParser", FORMAT_INVALID, + ST.ERR_INF_PARSER_DEFINE_SECTION_MUST_ITEM_NOT_EXIST % ("FILE_GUID"), File=self.FullPath) + else: + self.SetGuid(DefineObj.GetFileGuid().GetValue()) + if DefineObj.GetVersionString() is None: + # + # VERSION_STRING is missing from the [Defines] section, tools must assume that the module's version is 0. + # + self.SetVersion('0') + else: + # + # Get version of INF + # + if DefineObj.GetVersionString().GetValue() != "": + # + # EDK2 inf + # + VersionString = DefineObj.GetVersionString().GetValue() + if len(VersionString) > 0: + VersionString = ConvertVersionToDecimal(VersionString) + self.SetVersion(VersionString) + else: + # + # EDK1 inf + # + Logger.Error("Parser", PARSER_ERROR, ST.ERR_INF_PARSER_NOT_SUPPORT_EDKI_INF, ExtraData=self.FullPath, + RaiseError=Logger.IS_RAISE_ERROR) + # + # if there is Shadow, Should judge the MODULE_TYPE in + # SEC, PEI_CORE and PEIM + # + if DefineObj.GetShadow(): + ModuleTypeValue = DefineObj.GetModuleType().GetValue() + if not (ModuleTypeValue == 'SEC' or ModuleTypeValue == 'PEI_CORE' or ModuleTypeValue == 'PEIM'): + Logger.Error("InfParser", FORMAT_INVALID, ST.ERR_INF_PARSER_DEFINE_SHADOW_INVALID, File=self.FullPath) + + if DefineObj.GetPcdIsDriver() is not None: + self.SetPcdIsDriver(DefineObj.GetPcdIsDriver().GetValue()) + # + # LIBRARY_CLASS + # + self._GenModuleHeaderLibClass(DefineObj, ArchList) + # + # CUSTOM_MAKEFILE + # + self.CustomMakefile = DefineObj.GetCustomMakefile() + # + # Externs in Defines section + # Only one define section, so just call once. + # + if not HasCalledFlag: + self._GenModuleHeaderExterns(DefineObj) + HasCalledFlag = True + # + # each module has only one module header + # + self.SetSupArchList(ArchList) + # + # Get Hob/BootMode/EventList information + # + self._GenSpecialComments() + # + # put all define statement into user-extension sections + # + DefinesDictNew = GenModuleHeaderUserExt(DefineObj, ArchString) + if DefinesDictNew: + UserExtension = CommonObject.UserExtensionObject() + UserExtension.SetDefinesDict(DefinesDictNew) + UserExtension.SetIdentifier('DefineModifiers') + UserExtension.SetUserID('EDK2') + self.SetUserExtensionList(self.GetUserExtensionList() + [UserExtension]) + # + # Get all meta-file header information + # the record is list of items formatted: + # [LineValue, Arch, StartLine, ID, Third] + # + InfHeaderObj = self.Parser.InfHeader + # + # Put header information into POM object + # + if self.UniFileClassObject: + Lang = DT.TAB_LANGUAGE_EN_X + else: + Lang = DT.TAB_LANGUAGE_EN_US + if InfHeaderObj.GetAbstract(): + self.SetAbstract((Lang, InfHeaderObj.GetAbstract())) + if InfHeaderObj.GetDescription(): + self.SetDescription((Lang, InfHeaderObj.GetDescription())) + if InfHeaderObj.GetCopyright(): + self.SetCopyright(('', InfHeaderObj.GetCopyright())) + if InfHeaderObj.GetLicense(): + self.SetLicense(('', InfHeaderObj.GetLicense())) + # + # Put Binary header information into POM object + # + InfBinaryHeaderObj = self.Parser.InfBinaryHeader + if InfBinaryHeaderObj.GetAbstract(): + self.SetBinaryHeaderAbstract((Lang, InfBinaryHeaderObj.GetAbstract())) + if InfBinaryHeaderObj.GetDescription(): + self.SetBinaryHeaderDescription((Lang, InfBinaryHeaderObj.GetDescription())) + if InfBinaryHeaderObj.GetCopyright(): + self.SetBinaryHeaderCopyright(('', InfBinaryHeaderObj.GetCopyright())) + if InfBinaryHeaderObj.GetLicense(): + self.SetBinaryHeaderLicense(('', InfBinaryHeaderObj.GetLicense())) + + ## GenModuleHeaderLibClass + # + # + def _GenModuleHeaderLibClass(self, DefineObj, ArchList): + LibraryList = DefineObj.GetLibraryClass() + for LibraryItem in LibraryList: + Lib = CommonObject.LibraryClassObject() + Lib.SetLibraryClass(LibraryItem.GetLibraryName()) + Lib.SetUsage(DT.USAGE_ITEM_PRODUCES) + SupModuleList = LibraryItem.GetTypes() + self.LibModuleTypeList += SupModuleList + Lib.SetSupModuleList(SupModuleList) + Lib.SetSupArchList(ArchList) + self.SetLibraryClassList(self.GetLibraryClassList() + [Lib]) + self.SetIsLibrary(True) + self.SetIsLibraryModList(self.GetIsLibraryModList() + SupModuleList) + + ## GenModuleHeaderExterns + # + # + def _GenModuleHeaderExterns(self, DefineObj): + EntryPointList = DefineObj.GetEntryPoint() + for EntryPoint in EntryPointList: + Image = ExternObject() + Image.SetEntryPoint(EntryPoint.GetCName()) + # + # Future enhancement + # + self.SetExternList(self.GetExternList() + [Image]) + # + # UNLOAD_IMAGE + # + UnloadImageList = DefineObj.GetUnloadImages() + for UnloadImage in UnloadImageList: + Image = ExternObject() + # + # Future enhancement + # + Image.SetUnloadImage(UnloadImage.GetCName()) + self.SetExternList(self.GetExternList() + [Image]) + # + # CONSTRUCTOR + # + ConstructorList = DefineObj.GetConstructor() + for ConstructorItem in ConstructorList: + Image = ExternObject() + # + # Future enhancement + # + Image.SetConstructor(ConstructorItem.GetCName()) + self.SetExternList(self.GetExternList() + [Image]) + # + # DESTRUCTOR + # + DestructorList = DefineObj.GetDestructor() + for DestructorItem in DestructorList: + Image = ExternObject() + # + # Future enhancement + # + Image.SetDestructor(DestructorItem.GetCName()) + self.SetExternList(self.GetExternList() + [Image]) + + ## GenModuleHeaderExterns + # BootMode/HOB/Event + # + def _GenSpecialComments(self): + SpecialCommentsList = self.Parser.InfSpecialCommentSection.GetSpecialComments() + for Key in SpecialCommentsList: + if Key == DT.TYPE_HOB_SECTION: + HobList = [] + for Item in SpecialCommentsList[Key]: + Hob = HobObject() + Hob.SetHobType(Item.GetHobType()) + Hob.SetUsage(Item.GetUsage()) + Hob.SetSupArchList(Item.GetSupArchList()) + if Item.GetHelpString(): + HelpTextObj = CommonObject.TextObject() + if self.UniFileClassObject: + HelpTextObj.SetLang(DT.TAB_LANGUAGE_EN_X) + HelpTextObj.SetString(Item.GetHelpString()) + Hob.SetHelpTextList([HelpTextObj]) + HobList.append(Hob) + self.SetHobList(HobList) + elif Key == DT.TYPE_EVENT_SECTION: + EventList = [] + for Item in SpecialCommentsList[Key]: + Event = EventObject() + Event.SetEventType(Item.GetEventType()) + Event.SetUsage(Item.GetUsage()) + if Item.GetHelpString(): + HelpTextObj = CommonObject.TextObject() + if self.UniFileClassObject: + HelpTextObj.SetLang(DT.TAB_LANGUAGE_EN_X) + HelpTextObj.SetString(Item.GetHelpString()) + Event.SetHelpTextList([HelpTextObj]) + EventList.append(Event) + self.SetEventList(EventList) + elif Key == DT.TYPE_BOOTMODE_SECTION: + BootModeList = [] + for Item in SpecialCommentsList[Key]: + BootMode = BootModeObject() + BootMode.SetSupportedBootModes(Item.GetSupportedBootModes()) + BootMode.SetUsage(Item.GetUsage()) + if Item.GetHelpString(): + HelpTextObj = CommonObject.TextObject() + if self.UniFileClassObject: + HelpTextObj.SetLang(DT.TAB_LANGUAGE_EN_X) + HelpTextObj.SetString(Item.GetHelpString()) + BootMode.SetHelpTextList([HelpTextObj]) + BootModeList.append(BootMode) + self.SetBootModeList(BootModeList) + + ## GenBuildOptions + # + # Gen BuildOptions of Inf + # [:]=Flag + # + # + def _GenBuildOptions(self): + Logger.Debug(2, "Generate %s ..." % DT.TAB_BUILD_OPTIONS) + # + # Get all BuildOptions + # + BuildOptionsList = self.Parser.InfBuildOptionSection.GetBuildOptions() + if not GlobalData.gIS_BINARY_INF: + BuildOptionDict = {} + for BuildOptionObj in BuildOptionsList: + ArchList = BuildOptionObj.GetSupArchList() + ArchList = ConvertArchList(ArchList) + BuildOptionsContent = BuildOptionObj.GetContent() + ArchString = ' '.join(ArchList) + if not BuildOptionsContent: + continue + BuildOptionDict[ArchString] = BuildOptionsContent + if not BuildOptionDict: + return + UserExtension = CommonObject.UserExtensionObject() + UserExtension.SetBuildOptionDict(BuildOptionDict) + UserExtension.SetIdentifier('BuildOptionModifiers') + UserExtension.SetUserID('EDK2') + self.SetUserExtensionList(self.GetUserExtensionList() + [UserExtension]) + else: + # + # Not process this information, will be processed in GenBinaries() + # + pass + + ## GenLibraryClasses + # + # Get LibraryClass of Inf + # | + # + # @param ContainerFile: The Inf file full path + # + def _GenLibraryClasses(self): + Logger.Debug(2, "Generate %s ..." % DT.TAB_LIBRARY_CLASSES) + if not GlobalData.gIS_BINARY_INF: + # + # Get all LibraryClasses + # + for LibraryClassData in self.Parser.InfLibraryClassSection.LibraryClasses.values(): + for Item in LibraryClassData: + LibraryClass = CommonObject.LibraryClassObject() + LibraryClass.SetUsage(DT.USAGE_ITEM_CONSUMES) + LibraryClass.SetLibraryClass(Item.GetLibName()) + LibraryClass.SetRecommendedInstance(None) + LibraryClass.SetFeatureFlag(Item.GetFeatureFlagExp()) + LibraryClass.SetSupArchList(ConvertArchList(Item.GetSupArchList())) + LibraryClass.SetSupModuleList(Item.GetSupModuleList()) + HelpStringObj = Item.GetHelpString() + if HelpStringObj is not None: + CommentString = GetHelpStringByRemoveHashKey(HelpStringObj.HeaderComments + + HelpStringObj.TailComments) + HelpTextHeaderObj = CommonObject.TextObject() + if self.UniFileClassObject: + HelpTextHeaderObj.SetLang(DT.TAB_LANGUAGE_EN_X) + HelpTextHeaderObj.SetString(CommentString) + LibraryClass.SetHelpTextList([HelpTextHeaderObj]) + self.SetLibraryClassList(self.GetLibraryClassList() + [LibraryClass]) + + ## GenPackages + # + # Gen Packages of Inf + # + # + # @param ContainerFile: The Inf file full path + # + def _GenPackages(self, Skip): + Logger.Debug(2, "Generate %s ..." % DT.TAB_PACKAGES) + # + # Get all Packages + # + PackageObj = self.Parser.InfPackageSection.Packages + # + # Go through each arch + # + for PackageItemObj in PackageObj: + # + # Need package information for dependency check usage + # + PackageDependency = PackageDependencyObject() + PackageDependency.SetPackageFilePath(NormPath(PackageItemObj.GetPackageName())) + PackageDependency.SetSupArchList(ConvertArchList(PackageItemObj.GetSupArchList())) + PackageDependency.SetFeatureFlag(PackageItemObj.GetFeatureFlagExp()) + + PkgInfo = GetPkgInfoFromDec(mws.join(self.WorkSpace, NormPath(PackageItemObj.GetPackageName()))) + if PkgInfo[1] and PkgInfo[2]: + PackageDependency.SetGuid(PkgInfo[1]) + PackageDependency.SetVersion(PkgInfo[2]) + elif Skip: + continue + else: + Logger.Error("\nUPT", PARSER_ERROR, + ST.ERR_INF_GET_PKG_DEPENDENCY_FAIL % PackageItemObj.GetPackageName(), File=self.FullPath) + + PackageDependencyList = self.GetPackageDependencyList() + PackageDependencyList.append(PackageDependency) + self.SetPackageDependencyList(PackageDependencyList) + + ## GenPcds + # + # Gen Pcds of Inf + # .[| [|]] + # + # @param ContainerFile: The Inf file full path + # + def _GenPcds(self): + if not GlobalData.gIS_BINARY_INF: + Logger.Debug(2, "Generate %s ..." % DT.TAB_PCDS) + # + # Get all Pcds + # + PcdObj = self.Parser.InfPcdSection.Pcds + KeysList = PcdObj.keys() + # + # Go through each arch + # + for (PcdType, PcdKey) in KeysList: + PcdData = PcdObj[PcdType, PcdKey] + for PcdItemObj in PcdData: + CommentList = PcdItemObj.GetHelpStringList() + if CommentList: + for CommentItem in CommentList: + Pcd = CommonObject.PcdObject() + Pcd.SetCName(PcdItemObj.GetCName()) + Pcd.SetTokenSpaceGuidCName(PcdItemObj.GetTokenSpaceGuidCName()) + Pcd.SetDefaultValue(PcdItemObj.GetDefaultValue()) + Pcd.SetItemType(PcdType) + Pcd.SetValidUsage(CommentItem.GetUsageItem()) + Pcd.SetFeatureFlag(PcdItemObj.GetFeatureFlagExp()) + Pcd.SetSupArchList(ConvertArchList(PcdItemObj.GetSupportArchList())) + HelpTextObj = CommonObject.TextObject() + if self.UniFileClassObject: + HelpTextObj.SetLang(DT.TAB_LANGUAGE_EN_X) + HelpTextObj.SetString(CommentItem.GetHelpStringItem()) + Pcd.SetHelpTextList([HelpTextObj]) + PcdList = self.GetPcdList() + PcdList.append(Pcd) + self.SetPcdList(PcdList) + + ## GenSources + # + # Gen Sources of Inf + # [|[|[|[|]]]] + # + # @param ContainerFile: The Inf file full path + # + def _GenSources(self): + Logger.Debug(2, "Generate %s ..." % DT.TAB_SOURCES) + + # + # Get all SourceFiles + # + SourceObj = self.Parser.InfSourcesSection.Sources + DataList = SourceObj.keys() + # + # Go through each arch + # + SourceList = [] + for Key in DataList: + SourceData = SourceObj[Key] + for Item in SourceData: + SourceFile = Item.GetSourceFileName() + Family = Item.GetFamily() + FeatureFlag = Item.GetFeatureFlagExp() + SupArchList = sorted(ConvertArchList(Item.GetSupArchList())) + Source = SourceFileObject() + Source.SetSourceFile(SourceFile) + Source.SetFamily(Family) + Source.SetFeatureFlag(FeatureFlag) + Source.SetSupArchList(SupArchList) + SourceList.append(Source) + + self.SetSourceFileList(self.GetSourceFileList() + SourceList) + + + ## GenUserExtensions + # + # Gen UserExtensions of Inf + # + def _GenUserExtensions(self): + # + # UserExtensions + # + UserExtensionObj = self.Parser.InfUserExtensionSection.UserExtension + Keys = UserExtensionObj.keys() + + for Key in Keys: + UserExtensionData = UserExtensionObj[Key] + for UserExtensionDataObj in UserExtensionData: + UserExtension = CommonObject.UserExtensionObject() + UserId = UserExtensionDataObj.GetUserId() + if UserId.startswith('"') and UserId.endswith('"'): + UserId = UserId[1:-1] + UserExtension.SetUserID(UserId) + Identifier = UserExtensionDataObj.GetIdString() + if Identifier.startswith('"') and Identifier.endswith('"'): + Identifier = Identifier[1:-1] + # + # Generate miscellaneous files on INF file + # + if UserId == 'TianoCore' and Identifier == 'ExtraFiles': + self._GenMiscFiles(UserExtensionDataObj.GetContent()) + UserExtension.SetIdentifier(Identifier) + UserExtension.SetStatement(UserExtensionDataObj.GetContent()) + UserExtension.SetSupArchList(ConvertArchList(UserExtensionDataObj.GetSupArchList())) + self.SetUserExtensionList(self.GetUserExtensionList() + [UserExtension]) + + # + # Gen UserExtensions of TianoCore."BinaryHeader" + # + + #Get Binary header from INF file + BinaryAbstractList = self.BinaryHeaderAbstractList + BinaryDescriptionList = self.BinaryHeaderDescriptionList + BinaryCopyrightList = self.BinaryHeaderCopyrightList + BinaryLicenseList = self.BinaryHeaderLicenseList + #Get Binary header from UNI file + # Initialize UniStrDict, the top keys are language codes + UniStrDict = {} + if self.UniFileClassObject: + UniStrDict = self.UniFileClassObject.OrderedStringList + for Lang in UniStrDict: + for StringDefClassObject in UniStrDict[Lang]: + Lang = GetLanguageCode1766(Lang) + if StringDefClassObject.StringName == DT.TAB_INF_BINARY_ABSTRACT: + BinaryAbstractList.append((Lang, ConvertSpecialUnicodes(StringDefClassObject.StringValue))) + if StringDefClassObject.StringName == DT.TAB_INF_BINARY_DESCRIPTION: + BinaryDescriptionList.append((Lang, ConvertSpecialUnicodes(StringDefClassObject.StringValue))) + if BinaryAbstractList or BinaryDescriptionList or BinaryCopyrightList or BinaryLicenseList: + BinaryUserExtension = CommonObject.UserExtensionObject() + BinaryUserExtension.SetBinaryAbstract(BinaryAbstractList) + BinaryUserExtension.SetBinaryDescription(BinaryDescriptionList) + BinaryUserExtension.SetBinaryCopyright(BinaryCopyrightList) + BinaryUserExtension.SetBinaryLicense(BinaryLicenseList) + BinaryUserExtension.SetIdentifier(DT.TAB_BINARY_HEADER_IDENTIFIER) + BinaryUserExtension.SetUserID(DT.TAB_BINARY_HEADER_USERID) + self.SetUserExtensionList(self.GetUserExtensionList() + [BinaryUserExtension]) + + def _GenDepexesList(self, SmmDepexList, DxeDepexList, PeiDepexList): + if SmmDepexList: + self.SetSmmDepex(SmmDepexList) + if DxeDepexList: + self.SetDxeDepex(DxeDepexList) + if PeiDepexList: + self.SetPeiDepex(PeiDepexList) + + ## GenDepexes + # + # Gen Depex of Inf + # + # @param ContainerFile: The Inf file full path + # + def _GenDepexes(self): + Logger.Debug(2, "Generate %s ..." % DT.TAB_DEPEX) + + PEI_LIST = [DT.SUP_MODULE_PEIM] + SMM_LIST = [DT.SUP_MODULE_DXE_SMM_DRIVER] + DXE_LIST = [DT.SUP_MODULE_DXE_DRIVER, DT.SUP_MODULE_DXE_SAL_DRIVER, + DT.SUP_MODULE_DXE_RUNTIME_DRIVER] + + IsLibraryClass = self.GetIsLibrary() + # + # Get all Depexes + # + DepexData = self.Parser.InfDepexSection.GetDepex() + SmmDepexList = [] + DxeDepexList = [] + PeiDepexList = [] + for Depex in DepexData: + ModuleType = Depex.GetModuleType() + ModuleTypeList = [] + if IsLibraryClass: + if self.GetModuleType() == 'BASE' and not ModuleType: + Logger.Error("\nMkPkg", PARSER_ERROR, + ST.ERR_INF_PARSER_DEPEX_SECTION_INVALID_FOR_BASE_LIBRARY_CLASS, + self.GetFullPath(), RaiseError=True) + if self.GetModuleType() != 'BASE' and not self.GetIsLibraryModList(): + Logger.Error("\nMkPkg", PARSER_ERROR, ST.ERR_INF_PARSER_DEPEX_SECTION_INVALID_FOR_LIBRARY_CLASS, + self.GetFullPath(), RaiseError=True) + if self.GetModuleType() != 'BASE' and ModuleType and ModuleType not in self.GetIsLibraryModList(): + Logger.Error("\nMkPkg", PARSER_ERROR, ST.ERR_INF_PARSER_DEPEX_SECTION_NOT_DETERMINED, + self.GetFullPath(), RaiseError=True) + if ModuleType: + ModuleTypeList = [ModuleType] + else: + for ModuleTypeInList in self.GetIsLibraryModList(): + if ModuleTypeInList in DT.VALID_DEPEX_MODULE_TYPE_LIST: + ModuleTypeList.append(ModuleTypeInList) + if not ModuleTypeList: + Logger.Error("\nMkPkg", PARSER_ERROR, ST.ERR_INF_PARSER_DEPEX_SECTION_NOT_DETERMINED, + self.GetFullPath(), RaiseError=True) + else: + if not ModuleType: + ModuleType = self.ModuleType + if ModuleType not in DT.VALID_DEPEX_MODULE_TYPE_LIST: + Logger.Error("\nMkPkg", PARSER_ERROR, + ST.ERR_INF_PARSER_DEPEX_SECTION_MODULE_TYPE_ERROR % (ModuleType), + self.GetFullPath(), RaiseError=True) + if ModuleType != self.ModuleType: + Logger.Error("\nMkPkg", PARSER_ERROR, ST.ERR_INF_PARSER_DEPEX_SECTION_NOT_DETERMINED, + self.GetFullPath(), RaiseError=True) + ModuleTypeList = [ModuleType] + for ModuleType in ModuleTypeList: + DepexIns = DepexObject() + DepexIns.SetDepex(Depex.GetDepexContent()) + if IsLibraryClass: + DepexIns.SetModuleType(ModuleType) + else: + if Depex.GetModuleType(): + DepexIns.SetModuleType(Depex.GetModuleType()) + DepexIns.SetSupArchList(ConvertArchList([Depex.GetSupArch()])) + DepexIns.SetFeatureFlag(Depex.GetFeatureFlagExp()) + if Depex.HelpString: + HelpIns = CommonObject.TextObject() + if self.UniFileClassObject: + HelpIns.SetLang(DT.TAB_LANGUAGE_EN_X) + HelpIns.SetString(GetHelpStringByRemoveHashKey(Depex.HelpString)) + DepexIns.SetHelpText(HelpIns) + + if ModuleType in SMM_LIST: + SmmDepexList.append(DepexIns) + if ModuleType in DXE_LIST: + DxeDepexList.append(DepexIns) + if ModuleType in PEI_LIST: + PeiDepexList.append(DepexIns) + if ModuleType == DT.SUP_MODULE_UEFI_DRIVER: + if IsLibraryClass: + DxeDepexList.append(DepexIns) + else: + Logger.Error("\nMkPkg", PARSER_ERROR, ST.ERR_INF_PARSER_DEPEX_SECTION_INVALID_FOR_DRIVER, + self.GetFullPath(), RaiseError=True) + + #End of for ModuleType in ModuleTypeList + self._GenDepexesList(SmmDepexList, DxeDepexList, PeiDepexList) + #End of for Depex in DepexData + + ## GenBinaries + # + # Gen Binary of Inf, must be called after Pcd/Library is generated + # ||[|.] + # + # @param ContainerFile: The Inf file full path + # + def _GenBinaries(self): + Logger.Debug(2, "Generate %s ..." % DT.TAB_BINARIES) + BinariesDict = {} + + # + # Get all Binary data + # + BinaryObj = self.Parser.InfBinariesSection.GetBinary() + + BinaryData = BinaryObj.keys() + + # + # If the INF file does not contain a [Sources] section, and the INF file does contain a [Binaries] section, + # then the ModuleSurfaceArea.BinaryModule attribute must be set to true. Otherwise, do not use the attribute + # + if BinaryObj and not self.Parser.InfSourcesSection.GetSources(): + self.BinaryModule = True + else: + self.BinaryModule = False + + BinaryFileObjectList = [] + AsBuildLibraryClassList = [] + AsBuildBuildOptionList = [] + AsBuildIns = AsBuiltObject() + # + # Library AsBuild Info + # + for LibItem in self.Parser.InfLibraryClassSection.GetLibraryClasses(): + AsBuildLibIns = AsBuildLibraryClassObject() + AsBuildLibIns.SetLibGuid(LibItem.GetFileGuid()) + AsBuildLibIns.SetLibVersion(LibItem.GetVersion()) + AsBuildLibIns.SetSupArchList(LibItem.GetSupArchList()) + AsBuildLibraryClassList.append(AsBuildLibIns) + AsBuildIns.SetLibraryInstancesList(AsBuildLibraryClassList) + + # + # BuildOption AsBuild Info + # + for BuildOptionItem in self.Parser.InfBuildOptionSection.GetBuildOptions(): + AsBuildBuildOptionList.append(BuildOptionItem) + AsBuildIns.SetBuildFlagsList(AsBuildBuildOptionList) + + # + # PatchPcd and PcdEx + # + AsBuildIns = self._GenAsBuiltPcds(self.Parser.InfPcdSection.GetPcds(), AsBuildIns) + + # + # Parse the DEC file that contains the GUID value of the GUID CName which is used by + # SUBTYPE_GUID type binary file in the Binaries section in the INF file + # + DecObjList = [] + if not self.PackagePath: + WorkSpace = os.path.normpath(self.WorkSpace) + TempPath = ModulePath = os.path.normpath(self.ModulePath) + while ModulePath: + TempPath = ModulePath + ModulePath = os.path.dirname(ModulePath) + PackageName = TempPath + DecFilePath = os.path.normpath(os.path.join(WorkSpace, PackageName)) + if DecFilePath: + for File in os.listdir(DecFilePath): + if File.upper().endswith('.DEC'): + DecFileFullPath = os.path.normpath(os.path.join(DecFilePath, File)) + DecObjList.append(DecPomAlignment(DecFileFullPath, self.WorkSpace)) + + + BinariesDict, AsBuildIns, BinaryFileObjectList = GenBinaryData(BinaryData, BinaryObj, + BinariesDict, + AsBuildIns, + BinaryFileObjectList, + self.GetSupArchList(), + self.BinaryModule, + DecObjList) + + BinariesDict2 = {} + for Key in BinariesDict: + ValueList = BinariesDict[Key] + if len(ValueList) > 1: + BinariesDict2[Key] = ValueList + else: + # + # if there is no TagName, ToolCode, HelpStr, + # then do not need to put them into userextension + # + (Target, Family, TagName, HelpStr) = ValueList[0] + if not (Target or Family or TagName or HelpStr): + continue + else: + BinariesDict2[Key] = ValueList + + self.SetBinaryFileList(self.GetBinaryFileList() + BinaryFileObjectList) + + if BinariesDict2: + UserExtension = CommonObject.UserExtensionObject() + UserExtension.SetBinariesDict(BinariesDict2) + UserExtension.SetIdentifier('BinaryFileModifiers') + UserExtension.SetUserID('EDK2') + self.SetUserExtensionList(self.GetUserExtensionList() + [UserExtension]) + + ## GenAsBuiltPcds + # + # + def _GenAsBuiltPcds(self, PcdList, AsBuildIns): + AsBuildPatchPcdList = [] + AsBuildPcdExList = [] + # + # Pcd AsBuild Info + # + for PcdItem in PcdList: + if PcdItem[0].upper() == DT.TAB_INF_PATCH_PCD.upper(): + PcdItemObj = PcdItem[1] + Pcd = CommonObject.PcdObject() + Pcd.SetCName(PcdItemObj.GetCName()) + Pcd.SetTokenSpaceGuidCName(PcdItemObj.GetTokenSpaceGuidCName()) + if PcdItemObj.GetTokenSpaceGuidValue() == '' and self.BinaryModule: + Logger.Error("\nMkPkg", + PARSER_ERROR, + ST.ERR_ASBUILD_PCD_TOKENSPACE_GUID_VALUE_MISS % \ + (PcdItemObj.GetTokenSpaceGuidCName()), + self.GetFullPath(), RaiseError=True) + else: + Pcd.SetTokenSpaceGuidValue(PcdItemObj.GetTokenSpaceGuidValue()) + if (PcdItemObj.GetToken() == '' or PcdItemObj.GetDatumType() == '') and self.BinaryModule: + Logger.Error("\nMkPkg", + PARSER_ERROR, + ST.ERR_ASBUILD_PCD_DECLARITION_MISS % \ + (PcdItemObj.GetTokenSpaceGuidCName() + '.' + PcdItemObj.GetCName()), + self.GetFullPath(), RaiseError=True) + Pcd.SetToken(PcdItemObj.GetToken()) + Pcd.SetDatumType(PcdItemObj.GetDatumType()) + Pcd.SetMaxDatumSize(PcdItemObj.GetMaxDatumSize()) + Pcd.SetDefaultValue(PcdItemObj.GetDefaultValue()) + Pcd.SetOffset(PcdItemObj.GetOffset()) + Pcd.SetItemType(PcdItem[0]) + Pcd.SetFeatureFlag(PcdItemObj.GetFeatureFlagExp()) + Pcd.SetSupArchList(ConvertArchList(PcdItemObj.GetSupportArchList())) + Pcd.SetValidUsage(PcdItemObj.GetValidUsage()) + for CommentItem in PcdItemObj.GetHelpStringList(): + HelpTextObj = CommonObject.TextObject() + if self.UniFileClassObject: + HelpTextObj.SetLang(DT.TAB_LANGUAGE_EN_X) + HelpTextObj.SetString(CommentItem.GetHelpStringItem()) + Pcd.SetHelpTextList(Pcd.GetHelpTextList() + [HelpTextObj]) + AsBuildPatchPcdList.append(Pcd) + elif PcdItem[0].upper() == DT.TAB_INF_PCD_EX.upper(): + PcdItemObj = PcdItem[1] + Pcd = CommonObject.PcdObject() + Pcd.SetTokenSpaceGuidValue(PcdItemObj.GetTokenSpaceGuidValue()) + Pcd.SetToken(PcdItemObj.GetToken()) + Pcd.SetDatumType(PcdItemObj.GetDatumType()) + Pcd.SetMaxDatumSize(PcdItemObj.GetMaxDatumSize()) + Pcd.SetDefaultValue(PcdItemObj.GetDefaultValue()) + Pcd.SetItemType(PcdItem[0]) + Pcd.SetFeatureFlag(PcdItemObj.GetFeatureFlagExp()) + Pcd.SetSupArchList(ConvertArchList(PcdItemObj.GetSupportArchList())) + Pcd.SetValidUsage(PcdItemObj.GetValidUsage()) + for CommentItem in PcdItemObj.GetHelpStringList(): + HelpTextObj = CommonObject.TextObject() + if self.UniFileClassObject: + HelpTextObj.SetLang(DT.TAB_LANGUAGE_EN_X) + HelpTextObj.SetString(CommentItem.GetHelpStringItem()) + Pcd.SetHelpTextList(Pcd.GetHelpTextList() + [HelpTextObj]) + AsBuildPcdExList.append(Pcd) + AsBuildIns.SetPatchPcdList(AsBuildPatchPcdList) + AsBuildIns.SetPcdExList(AsBuildPcdExList) + + return AsBuildIns + + ## GenGuidProtocolPpis + # + # Gen Guids/Protocol/Ppis of INF + # = + # + def _GenGuidProtocolPpis(self, Type): + Logger.Debug(2, "Generate %s ..." % Type) + # + # Get all Guid/Protocol/Ppis data + # + GuidObj = self.Parser.InfGuidSection.GetGuid() + ProtocolObj = self.Parser.InfProtocolSection.GetProtocol() + PpisObj = self.Parser.InfPpiSection.GetPpi() + + GuidProtocolPpiList = [] + + if Type == DT.TAB_GUIDS: + GuidData = GuidObj.keys() + for Item in GuidData: + CommentList = Item.GetCommentList() + # + # Depend on CommentList content + # generate muti-guid-obj + # + if CommentList: + for GuidComentItem in CommentList: + ListObject = CommonObject.GuidObject() + ListObject.SetGuidTypeList([GuidComentItem.GetGuidTypeItem()]) + ListObject.SetVariableName(GuidComentItem.GetVariableNameItem()) + ListObject.SetUsage(GuidComentItem.GetUsageItem()) + ListObject.SetName(Item.GetName()) + ListObject.SetCName(Item.GetName()) + ListObject.SetSupArchList(ConvertArchList(Item.GetSupArchList())) + ListObject.SetFeatureFlag(Item.GetFeatureFlagExp()) + HelpString = GuidComentItem.GetHelpStringItem() + if HelpString.strip(): + HelpTxtTailObj = CommonObject.TextObject() + if self.UniFileClassObject: + HelpTxtTailObj.SetLang(DT.TAB_LANGUAGE_EN_X) + HelpTxtTailObj.SetString(HelpString) + ListObject.SetHelpTextList([HelpTxtTailObj]) + + GuidProtocolPpiList.append(ListObject) + elif Type == DT.TAB_PROTOCOLS: + ProtocolData = ProtocolObj.keys() + for Item in ProtocolData: + CommentList = Item.GetCommentList() + for CommentItem in CommentList: + ListObject = CommonObject.ProtocolObject() + ListObject.SetCName(Item.GetName()) + ListObject.SetSupArchList(ConvertArchList(Item.GetSupArchList())) + ListObject.SetFeatureFlag(Item.GetFeatureFlagExp()) + ListObject.SetNotify(CommentItem.GetNotify()) + ListObject.SetUsage(CommentItem.GetUsageItem()) + HelpString = CommentItem.GetHelpStringItem() + if HelpString.strip(): + HelpTxtObj = CommonObject.TextObject() + if self.UniFileClassObject: + HelpTxtObj.SetLang(DT.TAB_LANGUAGE_EN_X) + HelpTxtObj.SetString(HelpString) + ListObject.SetHelpTextList([HelpTxtObj]) + GuidProtocolPpiList.append(ListObject) + elif Type == DT.TAB_PPIS: + PpiData = PpisObj.keys() + for Item in PpiData: + CommentList = Item.GetCommentList() + for CommentItem in CommentList: + ListObject = CommonObject.PpiObject() + ListObject.SetCName(Item.GetName()) + ListObject.SetSupArchList(ConvertArchList(Item.GetSupArchList())) + ListObject.SetFeatureFlag(Item.GetFeatureFlagExp()) + ListObject.SetNotify(CommentItem.GetNotify()) + ListObject.SetUsage(CommentItem.GetUsage()) + HelpString = CommentItem.GetHelpStringItem() + if HelpString.strip(): + HelpTextObj = CommonObject.TextObject() + if self.UniFileClassObject: + HelpTextObj.SetLang(DT.TAB_LANGUAGE_EN_X) + HelpTextObj.SetString(HelpString) + ListObject.SetHelpTextList([HelpTextObj]) + GuidProtocolPpiList.append(ListObject) + + if Type == DT.TAB_GUIDS: + self.SetGuidList(self.GetGuidList() + GuidProtocolPpiList) + elif Type == DT.TAB_PROTOCOLS: + self.SetProtocolList(self.GetProtocolList() + GuidProtocolPpiList) + elif Type == DT.TAB_PPIS: + self.SetPpiList(self.GetPpiList() + GuidProtocolPpiList) + + ## GenMiscFiles + # + # Gen MiscellaneousFiles of Inf + # + # @param ContainerFile: The Inf file full path + # + def _GenMiscFiles(self, Content): + MiscFileObj = CommonObject.MiscFileObject() + for Line in Content.splitlines(): + FileName = '' + if '#' in Line: + FileName = Line[:Line.find('#')] + else: + FileName = Line + if FileName: + if IsValidPath(FileName, GlobalData.gINF_MODULE_DIR): + FileObj = CommonObject.FileObject() + FileObj.SetURI(FileName) + MiscFileObj.SetFileList(MiscFileObj.GetFileList()+[FileObj]) + else: + Logger.Error("InfParser", + FORMAT_INVALID, + ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID%(Line), + File=GlobalData.gINF_MODULE_NAME, + ExtraData=Line) + self.SetMiscFileList(self.GetMiscFileList()+[MiscFileObj]) + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/PomAdapter/InfPomAlignmentMisc.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/PomAdapter/InfPomAlignmentMisc.py new file mode 100755 index 00000000..c422de26 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/PomAdapter/InfPomAlignmentMisc.py @@ -0,0 +1,255 @@ +## @file InfPomAlignmentMisc.py +# This file contained the routines for InfPomAlignment +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +InfPomAlignmentMisc +''' + +## +# Import modules +# +import Logger.Log as Logger +from Library import DataType as DT +from Library.Misc import ConvertArchList +from Object.POM.ModuleObject import BinaryFileObject +from Object.POM import CommonObject +from Library.StringUtils import FORMAT_INVALID +from Library.Misc import CheckGuidRegFormat +from Logger import StringTable as ST + + +## GenModuleHeaderUserExt +# +# +def GenModuleHeaderUserExt(DefineObj, ArchString): + DefinesDictNew = {} + EdkReleaseVersion = DefineObj.GetEdkReleaseVersion() + Shadow = DefineObj.GetShadow() + DpxSource = DefineObj.GetDpxSource() + PciVendorId = DefineObj.GetPciVendorId() + PciDeviceId = DefineObj.GetPciDeviceId() + PciClassCode = DefineObj.GetPciClassCode() + PciRevision = DefineObj.GetPciRevision() + PciCompress = DefineObj.GetPciCompress() + CustomMakefile = DefineObj.GetCustomMakefile() + UefiHiiResourceSection = DefineObj.GetUefiHiiResourceSection() + + if EdkReleaseVersion is not None: + Name = DT.TAB_INF_DEFINES_EDK_RELEASE_VERSION + Value = EdkReleaseVersion.GetValue() + Statement = _GenInfDefineStateMent(EdkReleaseVersion.Comments.GetHeaderComments(), + Name, + Value, + EdkReleaseVersion.Comments.GetTailComments()) + DefinesDictNew[Statement] = ArchString + + if Shadow is not None: + Name = DT.TAB_INF_DEFINES_SHADOW + Value = Shadow.GetValue() + Statement = _GenInfDefineStateMent(Shadow.Comments.GetHeaderComments(), + Name, + Value, + Shadow.Comments.GetTailComments()) + DefinesDictNew[Statement] = ArchString + + if DpxSource is not None: + Name = DT.TAB_INF_DEFINES_DPX_SOURCE + for DpxSourceItem in DpxSource: + Value = DpxSourceItem[0] + Statement = _GenInfDefineStateMent(DpxSourceItem[1].GetHeaderComments(), + Name, + Value, + DpxSourceItem[1].GetTailComments()) + DefinesDictNew[Statement] = ArchString + + if PciVendorId is not None: + Name = DT.TAB_INF_DEFINES_PCI_VENDOR_ID + Value = PciVendorId.GetValue() + Statement = _GenInfDefineStateMent(PciVendorId.Comments.GetHeaderComments(), + Name, + Value, + PciVendorId.Comments.GetTailComments()) + DefinesDictNew[Statement] = ArchString + + if PciDeviceId is not None: + Name = DT.TAB_INF_DEFINES_PCI_DEVICE_ID + Value = PciDeviceId.GetValue() + Statement = _GenInfDefineStateMent(PciDeviceId.Comments.GetHeaderComments(), + Name, + Value, + PciDeviceId.Comments.GetTailComments()) + DefinesDictNew[Statement] = ArchString + + if PciClassCode is not None: + Name = DT.TAB_INF_DEFINES_PCI_CLASS_CODE + Value = PciClassCode.GetValue() + Statement = _GenInfDefineStateMent(PciClassCode.Comments.GetHeaderComments(), + Name, + Value, + PciClassCode.Comments.GetTailComments()) + DefinesDictNew[Statement] = ArchString + + if PciRevision is not None: + Name = DT.TAB_INF_DEFINES_PCI_REVISION + Value = PciRevision.GetValue() + Statement = _GenInfDefineStateMent(PciRevision.Comments.GetHeaderComments(), + Name, + Value, + PciRevision.Comments.GetTailComments()) + DefinesDictNew[Statement] = ArchString + + if PciCompress is not None: + Name = DT.TAB_INF_DEFINES_PCI_COMPRESS + Value = PciCompress.GetValue() + Statement = _GenInfDefineStateMent(PciCompress.Comments.GetHeaderComments(), + Name, + Value, + PciCompress.Comments.GetTailComments()) + DefinesDictNew[Statement] = ArchString + + if len(CustomMakefile) >= 1: + for CustomMakefileItem in CustomMakefile: + Name = DT.TAB_INF_DEFINES_CUSTOM_MAKEFILE + # + # Not with Feature Flag Expression + # + if len(CustomMakefileItem) == 3: + if CustomMakefileItem[0] != '': + Value = CustomMakefileItem[0] + ' | ' + CustomMakefileItem[1] + else: + Value = CustomMakefileItem[1] + + Comments = CustomMakefileItem[2] + Statement = _GenInfDefineStateMent(Comments.GetHeaderComments(), + Name, + Value, + Comments.GetTailComments()) + + DefinesDictNew[Statement] = ArchString + + if UefiHiiResourceSection is not None: + Name = DT.TAB_INF_DEFINES_UEFI_HII_RESOURCE_SECTION + Value = UefiHiiResourceSection.GetValue() + HeaderComment = UefiHiiResourceSection.Comments.GetHeaderComments() + TailComment = UefiHiiResourceSection.Comments.GetTailComments() + Statement = _GenInfDefineStateMent(HeaderComment, + Name, + Value, + TailComment) + DefinesDictNew[Statement] = "" + + return DefinesDictNew + + +## Generate the define statement that will be put into userextension +# Not support comments. +# +# @param HeaderComment: the original header comment (# not removed) +# @param Name: the definition keyword, should not be empty or none +# @param Value: the definition keyword value +# @param TailComment: the original Tail comment (# not removed) +# +# @return: the regenerated define statement +# +def _GenInfDefineStateMent(HeaderComment, Name, Value, TailComment): + Logger.Debug(5, HeaderComment + TailComment) + Statement = '%s = %s' % (Name, Value) + + return Statement + +## GenBinaryData +# +# +def GenBinaryData(BinaryData, BinaryObj, BinariesDict, AsBuildIns, BinaryFileObjectList, \ + SupArchList, BinaryModule, DecObjList=None): + if BinaryModule: + pass + OriSupArchList = SupArchList + for Item in BinaryData: + ItemObj = BinaryObj[Item][0][0] + if ItemObj.GetType() not in DT.BINARY_FILE_TYPE_UI_LIST + DT.BINARY_FILE_TYPE_VER_LIST: + TagName = ItemObj.GetTagName() + Family = ItemObj.GetFamily() + else: + TagName = '' + Family = '' + + FFE = ItemObj.GetFeatureFlagExp() + + # + # If have architecturie specified, then use the specified architecturie; + # If the section tag does not have an architecture modifier or the modifier is "common" (case in-sensitive), + # and the VALID_ARCHITECTURES comment exists, the list from the VALID_ARCHITECTURES comment + # can be used for the attribute. + # If both not have VALID_ARCHITECTURE comment and no architecturie specified, then keep it empty. + # + SupArchList = sorted(ConvertArchList(ItemObj.GetSupArchList())) + if len(SupArchList) == 1 and SupArchList[0] == 'COMMON': + if not (len(OriSupArchList) == 1 or OriSupArchList[0] == 'COMMON'): + SupArchList = OriSupArchList + else: + SupArchList = ['COMMON'] + + FileNameObj = CommonObject.FileNameObject() + FileNameObj.SetFileType(ItemObj.GetType()) + FileNameObj.SetFilename(ItemObj.GetFileName()) + FileNameObj.SetFeatureFlag(FFE) + # + # Get GUID value of the GUID CName in the DEC file + # + if ItemObj.GetType() == DT.SUBTYPE_GUID_BINARY_FILE_TYPE: + if not CheckGuidRegFormat(ItemObj.GetGuidValue()): + if not DecObjList: + if DT.TAB_HORIZON_LINE_SPLIT in ItemObj.GetGuidValue() or \ + DT.TAB_COMMA_SPLIT in ItemObj.GetGuidValue(): + Logger.Error("\nMkPkg", + FORMAT_INVALID, + ST.ERR_DECPARSE_DEFINE_PKGGUID, + ExtraData=ItemObj.GetGuidValue(), + RaiseError=True) + else: + Logger.Error("\nMkPkg", + FORMAT_INVALID, + ST.ERR_UNI_SUBGUID_VALUE_DEFINE_DEC_NOT_FOUND % \ + (ItemObj.GetGuidValue()), + RaiseError=True) + else: + for DecObj in DecObjList: + for GuidObj in DecObj.GetGuidList(): + if GuidObj.GetCName() == ItemObj.GetGuidValue(): + FileNameObj.SetGuidValue(GuidObj.GetGuid()) + break + + if not FileNameObj.GetGuidValue(): + Logger.Error("\nMkPkg", + FORMAT_INVALID, + ST.ERR_DECPARSE_CGUID_NOT_FOUND % \ + (ItemObj.GetGuidValue()), + RaiseError=True) + else: + FileNameObj.SetGuidValue(ItemObj.GetGuidValue().strip()) + + FileNameObj.SetSupArchList(SupArchList) + FileNameList = [FileNameObj] + + BinaryFile = BinaryFileObject() + BinaryFile.SetFileNameList(FileNameList) + BinaryFile.SetAsBuiltList(AsBuildIns) + BinaryFileObjectList.append(BinaryFile) + + SupArchStr = ' '.join(SupArchList) + Key = (ItemObj.GetFileName(), ItemObj.GetType(), FFE, SupArchStr) + ValueItem = (ItemObj.GetTarget(), Family, TagName, '') + if Key in BinariesDict: + ValueList = BinariesDict[Key] + ValueList.append(ValueItem) + BinariesDict[Key] = ValueList + else: + BinariesDict[Key] = [ValueItem] + + return BinariesDict, AsBuildIns, BinaryFileObjectList diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/PomAdapter/__init__.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/PomAdapter/__init__.py new file mode 100644 index 00000000..0df484ce --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/PomAdapter/__init__.py @@ -0,0 +1,14 @@ +## @file +# Python 'Parser' package initialization file. +# +# This file is required to make Python interpreter treat the directory +# as containing package. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +PomAdapter +''' diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/ReplacePkg.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/ReplacePkg.py new file mode 100755 index 00000000..4152b25f --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/ReplacePkg.py @@ -0,0 +1,142 @@ +## @file +# Replace distribution package. +# +# Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +""" +Replace a distribution package +""" +## +# Import Modules +# +from shutil import rmtree +from traceback import format_exc +from platform import python_version +from sys import platform +from Logger import StringTable as ST +from Logger.ToolError import UNKNOWN_ERROR +from Logger.ToolError import FatalError +from Logger.ToolError import ABORT_ERROR +from Logger.ToolError import CODE_ERROR +from Logger.ToolError import UPT_ALREADY_INSTALLED_ERROR +import Logger.Log as Logger + +from Core.DependencyRules import DependencyRules +from Library import GlobalData +from InstallPkg import UnZipDp +from InstallPkg import InstallDp +from RmPkg import GetInstalledDpInfo +from RmPkg import RemoveDist + +## Tool entrance method +# +# This method mainly dispatch specific methods per the command line options. +# If no error found, return zero value so the caller of this tool can know +# if it's executed successfully or not. +# +# @param Options: command Options +# +def Main(Options = None): + ContentZipFile, DistFile = None, None + try: + DataBase = GlobalData.gDB + WorkspaceDir = GlobalData.gWORKSPACE + Dep = DependencyRules(DataBase) + DistPkg, ContentZipFile, DpPkgFileName, DistFile = UnZipDp(WorkspaceDir, Options.PackFileToReplace) + + StoredDistFile, OrigDpGuid, OrigDpVersion = GetInstalledDpInfo(Options.PackFileToBeReplaced, \ + Dep, DataBase, WorkspaceDir) + + # + # check dependency + # + CheckReplaceDpx(Dep, DistPkg, OrigDpGuid, OrigDpVersion) + + # + # Remove the old distribution + # + RemoveDist(OrigDpGuid, OrigDpVersion, StoredDistFile, DataBase, WorkspaceDir, Options.Yes) + + # + # Install the new distribution + # + InstallDp(DistPkg, DpPkgFileName, ContentZipFile, Options, Dep, WorkspaceDir, DataBase) + ReturnCode = 0 + + except FatalError as XExcept: + ReturnCode = XExcept.args[0] + if Logger.GetLevel() <= Logger.DEBUG_9: + Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), + platform) + format_exc()) + except KeyboardInterrupt: + ReturnCode = ABORT_ERROR + if Logger.GetLevel() <= Logger.DEBUG_9: + Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), + platform) + format_exc()) + except: + ReturnCode = CODE_ERROR + Logger.Error( + "\nReplacePkg", + CODE_ERROR, + ST.ERR_UNKNOWN_FATAL_REPLACE_ERR % (Options.PackFileToReplace, Options.PackFileToBeReplaced), + ExtraData=ST.MSG_SEARCH_FOR_HELP % ST.MSG_EDKII_MAIL_ADDR, + RaiseError=False + ) + Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), + platform) + format_exc()) + + finally: + Logger.Quiet(ST.MSG_REMOVE_TEMP_FILE_STARTED) + if DistFile: + DistFile.Close() + if ContentZipFile: + ContentZipFile.Close() + for TempDir in GlobalData.gUNPACK_DIR: + rmtree(TempDir) + GlobalData.gUNPACK_DIR = [] + Logger.Quiet(ST.MSG_REMOVE_TEMP_FILE_DONE) + + if ReturnCode == 0: + Logger.Quiet(ST.MSG_FINISH) + + return ReturnCode + +def CheckReplaceDpx(Dep, DistPkg, OrigDpGuid, OrigDpVersion): + NewDpPkgList = [] + for PkgInfo in DistPkg.PackageSurfaceArea: + Guid, Version = PkgInfo[0], PkgInfo[1] + NewDpPkgList.append((Guid, Version)) + + NewDpInfo = "%s %s" % (DistPkg.Header.GetGuid(), DistPkg.Header.GetVersion()) + OrigDpInfo = "%s %s" % (OrigDpGuid, OrigDpVersion) + + # + # check whether new distribution is already installed and not replacing itself + # + if (NewDpInfo != OrigDpInfo): + if Dep.CheckDpExists(DistPkg.Header.GetGuid(), DistPkg.Header.GetVersion()): + Logger.Error("\nReplacePkg", UPT_ALREADY_INSTALLED_ERROR, + ST.WRN_DIST_PKG_INSTALLED, + ExtraData=ST.MSG_REPLACE_ALREADY_INSTALLED_DP) + + # + # check whether the original distribution could be replaced by new distribution + # + Logger.Verbose(ST.MSG_CHECK_DP_FOR_REPLACE%(NewDpInfo, OrigDpInfo)) + DepInfoResult = Dep.CheckDpDepexForReplace(OrigDpGuid, OrigDpVersion, NewDpPkgList) + Replaceable = DepInfoResult[0] + if not Replaceable: + Logger.Error("\nReplacePkg", UNKNOWN_ERROR, + ST.ERR_PACKAGE_NOT_MATCH_DEPENDENCY) + + # + # check whether new distribution could be installed by dependency rule + # + Logger.Verbose(ST.MSG_CHECK_DP_FOR_INSTALL%str(NewDpInfo)) + if not Dep.ReplaceCheckNewDpDepex(DistPkg, OrigDpGuid, OrigDpVersion): + Logger.Error("\nReplacePkg", UNKNOWN_ERROR, + ST.ERR_PACKAGE_NOT_MATCH_DEPENDENCY, + ExtraData=DistPkg.Header.Name) + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/RmPkg.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/RmPkg.py new file mode 100755 index 00000000..98e0fcd6 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/RmPkg.py @@ -0,0 +1,270 @@ +## @file +# Install distribution package. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +RmPkg +''' + +## +# Import Modules +# +import os.path +from stat import S_IWUSR +from traceback import format_exc +from platform import python_version +from hashlib import md5 +from sys import stdin +from sys import platform + +from Core.DependencyRules import DependencyRules +from Library import GlobalData +from Logger import StringTable as ST +import Logger.Log as Logger +from Logger.ToolError import OPTION_MISSING +from Logger.ToolError import UNKNOWN_ERROR +from Logger.ToolError import ABORT_ERROR +from Logger.ToolError import CODE_ERROR +from Logger.ToolError import FatalError + + +## CheckDpDepex +# +# Check if the Depex is satisfied +# @param Dep: Dep +# @param Guid: Guid of Dp +# @param Version: Version of Dp +# @param WorkspaceDir: Workspace Dir +# +def CheckDpDepex(Dep, Guid, Version, WorkspaceDir): + (Removable, DependModuleList) = Dep.CheckDpDepexForRemove(Guid, Version) + if not Removable: + Logger.Info(ST.MSG_CONFIRM_REMOVE) + Logger.Info(ST.MSG_USER_DELETE_OP) + Input = stdin.readline() + Input = Input.replace('\r', '').replace('\n', '') + if Input.upper() != 'Y': + Logger.Error("RmPkg", UNKNOWN_ERROR, ST.ERR_USER_INTERRUPT) + return 1 + else: + # + # report list of modules that are not valid due to force + # remove, + # also generate a log file for reference + # + Logger.Info(ST.MSG_INVALID_MODULE_INTRODUCED) + LogFilePath = os.path.normpath(os.path.join(WorkspaceDir, GlobalData.gINVALID_MODULE_FILE)) + Logger.Info(ST.MSG_CHECK_LOG_FILE % LogFilePath) + try: + LogFile = open(LogFilePath, 'w') + try: + for ModulePath in DependModuleList: + LogFile.write("%s\n"%ModulePath) + Logger.Info(ModulePath) + except IOError: + Logger.Warn("\nRmPkg", ST.ERR_FILE_WRITE_FAILURE, + File=LogFilePath) + except IOError: + Logger.Warn("\nRmPkg", ST.ERR_FILE_OPEN_FAILURE, + File=LogFilePath) + finally: + LogFile.close() + +## Remove Path +# +# removing readonly file on windows will get "Access is denied" +# error, so before removing, change the mode to be writeable +# +# @param Path: The Path to be removed +# +def RemovePath(Path): + Logger.Info(ST.MSG_REMOVE_FILE % Path) + if not os.access(Path, os.W_OK): + os.chmod(Path, S_IWUSR) + os.remove(Path) + try: + os.removedirs(os.path.split(Path)[0]) + except OSError: + pass +## GetCurrentFileList +# +# @param DataBase: DataBase of UPT +# @param Guid: Guid of Dp +# @param Version: Version of Dp +# @param WorkspaceDir: Workspace Dir +# +def GetCurrentFileList(DataBase, Guid, Version, WorkspaceDir): + NewFileList = [] + for Dir in DataBase.GetDpInstallDirList(Guid, Version): + RootDir = os.path.normpath(os.path.join(WorkspaceDir, Dir)) + for Root, Dirs, Files in os.walk(RootDir): + Logger.Debug(0, Dirs) + for File in Files: + FilePath = os.path.join(Root, File) + if FilePath not in NewFileList: + NewFileList.append(FilePath) + return NewFileList + + +## Tool entrance method +# +# This method mainly dispatch specific methods per the command line options. +# If no error found, return zero value so the caller of this tool can know +# if it's executed successfully or not. +# +# @param Options: command option +# +def Main(Options = None): + + try: + DataBase = GlobalData.gDB + if not Options.DistributionFile: + Logger.Error("RmPkg", + OPTION_MISSING, + ExtraData=ST.ERR_SPECIFY_PACKAGE) + WorkspaceDir = GlobalData.gWORKSPACE + # + # Prepare check dependency + # + Dep = DependencyRules(DataBase) + + # + # Get the Dp information + # + StoredDistFile, Guid, Version = GetInstalledDpInfo(Options.DistributionFile, Dep, DataBase, WorkspaceDir) + + # + # Check Dp depex + # + CheckDpDepex(Dep, Guid, Version, WorkspaceDir) + + # + # remove distribution + # + RemoveDist(Guid, Version, StoredDistFile, DataBase, WorkspaceDir, Options.Yes) + + Logger.Quiet(ST.MSG_FINISH) + + ReturnCode = 0 + + except FatalError as XExcept: + ReturnCode = XExcept.args[0] + if Logger.GetLevel() <= Logger.DEBUG_9: + Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + \ + format_exc()) + except KeyboardInterrupt: + ReturnCode = ABORT_ERROR + if Logger.GetLevel() <= Logger.DEBUG_9: + Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + \ + format_exc()) + except: + Logger.Error( + "\nRmPkg", + CODE_ERROR, + ST.ERR_UNKNOWN_FATAL_REMOVING_ERR, + ExtraData=ST.MSG_SEARCH_FOR_HELP % ST.MSG_EDKII_MAIL_ADDR, + RaiseError=False + ) + Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + \ + format_exc()) + ReturnCode = CODE_ERROR + return ReturnCode + +## GetInstalledDpInfo method +# +# Get the installed distribution information +# +# @param DistributionFile: the name of the distribution +# @param Dep: the instance of DependencyRules +# @param DataBase: the internal database +# @param WorkspaceDir: work space directory +# @retval StoredDistFile: the distribution file that backed up +# @retval Guid: the Guid of the distribution +# @retval Version: the Version of distribution +# +def GetInstalledDpInfo(DistributionFile, Dep, DataBase, WorkspaceDir): + (Guid, Version, NewDpFileName) = DataBase.GetDpByName(os.path.split(DistributionFile)[1]) + if not Guid: + Logger.Error("RmPkg", UNKNOWN_ERROR, ST.ERR_PACKAGE_NOT_INSTALLED % DistributionFile) + + # + # Check Dp existing + # + if not Dep.CheckDpExists(Guid, Version): + Logger.Error("RmPkg", UNKNOWN_ERROR, ST.ERR_DISTRIBUTION_NOT_INSTALLED) + # + # Check for Distribution files existence in /conf/upt, if not exist, + # Warn user and go on. + # + StoredDistFile = os.path.normpath(os.path.join(WorkspaceDir, GlobalData.gUPT_DIR, NewDpFileName)) + if not os.path.isfile(StoredDistFile): + Logger.Warn("RmPkg", ST.WRN_DIST_NOT_FOUND%StoredDistFile) + StoredDistFile = None + + return StoredDistFile, Guid, Version + +## RemoveDist method +# +# remove a distribution +# +# @param Guid: the Guid of the distribution +# @param Version: the Version of distribution +# @param StoredDistFile: the distribution file that backed up +# @param DataBase: the internal database +# @param WorkspaceDir: work space directory +# @param ForceRemove: whether user want to remove file even it is modified +# +def RemoveDist(Guid, Version, StoredDistFile, DataBase, WorkspaceDir, ForceRemove): + # + # Get Current File List + # + NewFileList = GetCurrentFileList(DataBase, Guid, Version, WorkspaceDir) + + # + # Remove all files + # + MissingFileList = [] + for (Path, Md5Sum) in DataBase.GetDpFileList(Guid, Version): + if os.path.isfile(Path): + if Path in NewFileList: + NewFileList.remove(Path) + if not ForceRemove: + # + # check whether modified by users + # + Md5Signature = md5(open(str(Path), 'rb').read()) + if Md5Sum != Md5Signature.hexdigest(): + Logger.Info(ST.MSG_CONFIRM_REMOVE2 % Path) + Input = stdin.readline() + Input = Input.replace('\r', '').replace('\n', '') + if Input.upper() != 'Y': + continue + RemovePath(Path) + else: + MissingFileList.append(Path) + + for Path in NewFileList: + if os.path.isfile(Path): + if (not ForceRemove) and (not os.path.split(Path)[1].startswith('.')): + Logger.Info(ST.MSG_CONFIRM_REMOVE3 % Path) + Input = stdin.readline() + Input = Input.replace('\r', '').replace('\n', '') + if Input.upper() != 'Y': + continue + RemovePath(Path) + + # + # Remove distribution files in /Conf/.upt + # + if StoredDistFile is not None: + os.remove(StoredDistFile) + + # + # update database + # + Logger.Quiet(ST.MSG_UPDATE_PACKAGE_DATABASE) + DataBase.RemoveDpObj(Guid, Version) diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/TestInstall.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/TestInstall.py new file mode 100755 index 00000000..b95449e5 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/TestInstall.py @@ -0,0 +1,94 @@ +# # @file +# Test Install distribution package +# +# Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +""" +Test Install multiple distribution package +""" +# # +# Import Modules +# +from Library import GlobalData +import Logger.Log as Logger +from Logger import StringTable as ST +import Logger.ToolError as TE +from Core.DependencyRules import DependencyRules +from InstallPkg import UnZipDp + +import shutil +from traceback import format_exc +from platform import python_version +from sys import platform + +# # Tool entrance method +# +# This method mainly dispatch specific methods per the command line options. +# If no error found, return zero value so the caller of this tool can know +# if it's executed successfully or not. +# +# @param Options: command Options +# +def Main(Options=None): + ContentZipFile, DistFile = None, None + ReturnCode = 0 + + try: + DataBase = GlobalData.gDB + WorkspaceDir = GlobalData.gWORKSPACE + if not Options.DistFiles: + Logger.Error("TestInstallPkg", TE.OPTION_MISSING, ExtraData=ST.ERR_SPECIFY_PACKAGE) + + DistPkgList = [] + for DistFile in Options.DistFiles: + DistPkg, ContentZipFile, __, DistFile = UnZipDp(WorkspaceDir, DistFile) + DistPkgList.append(DistPkg) + + # + # check dependency + # + Dep = DependencyRules(DataBase) + Result = True + DpObj = None + try: + Result, DpObj = Dep.CheckTestInstallPdDepexSatisfied(DistPkgList) + except: + Result = False + + if Result: + Logger.Quiet(ST.MSG_TEST_INSTALL_PASS) + else: + Logger.Quiet(ST.MSG_TEST_INSTALL_FAIL) + + except TE.FatalError as XExcept: + ReturnCode = XExcept.args[0] + if Logger.GetLevel() <= Logger.DEBUG_9: + Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + format_exc()) + + except Exception as x: + ReturnCode = TE.CODE_ERROR + Logger.Error( + "\nTestInstallPkg", + TE.CODE_ERROR, + ST.ERR_UNKNOWN_FATAL_INSTALL_ERR % Options.DistFiles, + ExtraData=ST.MSG_SEARCH_FOR_HELP % ST.MSG_EDKII_MAIL_ADDR, + RaiseError=False + ) + Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + format_exc()) + + finally: + Logger.Quiet(ST.MSG_REMOVE_TEMP_FILE_STARTED) + if DistFile: + DistFile.Close() + if ContentZipFile: + ContentZipFile.Close() + for TempDir in GlobalData.gUNPACK_DIR: + shutil.rmtree(TempDir) + GlobalData.gUNPACK_DIR = [] + Logger.Quiet(ST.MSG_REMOVE_TEMP_FILE_DONE) + if ReturnCode == 0: + Logger.Quiet(ST.MSG_FINISH) + return ReturnCode + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UPT.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UPT.py new file mode 100755 index 00000000..693e01e0 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UPT.py @@ -0,0 +1,347 @@ +## @file +# +# This file is the main entry for UPT +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +UPT +''' + +## import modules +# +import locale +import sys +from imp import reload +encoding = locale.getdefaultlocale()[1] +if encoding: + reload(sys) + sys.setdefaultencoding(encoding) +from Core import FileHook +import os.path +from sys import platform +import platform as pf +from optparse import OptionParser +from traceback import format_exc +from platform import python_version + +from Logger import StringTable as ST +import Logger.Log as Logger +from Logger.StringTable import MSG_VERSION +from Logger.StringTable import MSG_DESCRIPTION +from Logger.StringTable import MSG_USAGE +from Logger.ToolError import FILE_NOT_FOUND +from Logger.ToolError import OPTION_MISSING +from Logger.ToolError import FILE_TYPE_MISMATCH +from Logger.ToolError import OPTION_CONFLICT +from Logger.ToolError import FatalError +from Logger.ToolError import UPT_ALREADY_INSTALLED_ERROR +from Common.MultipleWorkspace import MultipleWorkspace as mws + +import MkPkg +import InstallPkg +import RmPkg +import InventoryWs +import ReplacePkg +import TestInstall +from Library.Misc import GetWorkspace +from Library import GlobalData +from Core.IpiDb import IpiDatabase +from BuildVersion import gBUILD_VERSION + +## CheckConflictOption +# +# CheckConflictOption +# +def CheckConflictOption(Opt): + if (Opt.PackFileToCreate or Opt.PackFileToInstall or Opt.PackFileToRemove or Opt.PackFileToReplace) \ + and Opt.InventoryWs: + Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_L_OA_EXCLUSIVE) + elif Opt.PackFileToReplace and (Opt.PackFileToCreate or Opt.PackFileToInstall or Opt.PackFileToRemove): + Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_U_ICR_EXCLUSIVE) + elif (Opt.PackFileToCreate and Opt.PackFileToInstall and Opt.PackFileToRemove): + Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_REQUIRE_I_C_R_OPTION) + elif Opt.PackFileToCreate and Opt.PackFileToInstall: + Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_I_C_EXCLUSIVE) + elif Opt.PackFileToInstall and Opt.PackFileToRemove: + Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_I_R_EXCLUSIVE) + elif Opt.PackFileToCreate and Opt.PackFileToRemove: + Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_C_R_EXCLUSIVE) + elif Opt.TestDistFiles and (Opt.PackFileToCreate or Opt.PackFileToInstall \ + or Opt.PackFileToRemove or Opt.PackFileToReplace): + Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_C_R_EXCLUSIVE) + + if Opt.CustomPath and Opt.UseGuidedPkgPath: + Logger.Warn("UPT", ST.WARN_CUSTOMPATH_OVERRIDE_USEGUIDEDPATH) + Opt.UseGuidedPkgPath = False + +## SetLogLevel +# +def SetLogLevel(Opt): + if Opt.opt_verbose: + Logger.SetLevel(Logger.VERBOSE) + elif Opt.opt_quiet: + Logger.SetLevel(Logger.QUIET + 1) + elif Opt.debug_level is not None: + if Opt.debug_level < 0 or Opt.debug_level > 9: + Logger.Warn("UPT", ST.ERR_DEBUG_LEVEL) + Logger.SetLevel(Logger.INFO) + else: + Logger.SetLevel(Opt.debug_level + 1) + elif Opt.opt_slient: + Logger.SetLevel(Logger.SILENT) + else: + Logger.SetLevel(Logger.INFO) + +## Main +# +# Main +# +def Main(): + Logger.Initialize() + + Parser = OptionParser(version=(MSG_VERSION + ' Build ' + gBUILD_VERSION), description=MSG_DESCRIPTION, + prog="UPT.exe", usage=MSG_USAGE) + + Parser.add_option("-d", "--debug", action="store", type="int", dest="debug_level", help=ST.HLP_PRINT_DEBUG_INFO) + + Parser.add_option("-v", "--verbose", action="store_true", dest="opt_verbose", + help=ST.HLP_PRINT_INFORMATIONAL_STATEMENT) + + Parser.add_option("-s", "--silent", action="store_true", dest="opt_slient", help=ST.HLP_RETURN_NO_DISPLAY) + + Parser.add_option("-q", "--quiet", action="store_true", dest="opt_quiet", help=ST.HLP_RETURN_AND_DISPLAY) + + Parser.add_option("-i", "--install", action="append", type="string", dest="Install_Distribution_Package_File", + help=ST.HLP_SPECIFY_PACKAGE_NAME_INSTALL) + + Parser.add_option("-c", "--create", action="store", type="string", dest="Create_Distribution_Package_File", + help=ST.HLP_SPECIFY_PACKAGE_NAME_CREATE) + + Parser.add_option("-r", "--remove", action="store", type="string", dest="Remove_Distribution_Package_File", + help=ST.HLP_SPECIFY_PACKAGE_NAME_REMOVE) + + Parser.add_option("-t", "--template", action="store", type="string", dest="Package_Information_Data_File", + help=ST.HLP_SPECIFY_TEMPLATE_NAME_CREATE) + + Parser.add_option("-p", "--dec-filename", action="append", type="string", dest="EDK2_DEC_Filename", + help=ST.HLP_SPECIFY_DEC_NAME_CREATE) + + Parser.add_option("-m", "--inf-filename", action="append", type="string", dest="EDK2_INF_Filename", + help=ST.HLP_SPECIFY_INF_NAME_CREATE) + + Parser.add_option("-l", "--list", action="store_true", dest="List_Dist_Installed", + help=ST.HLP_LIST_DIST_INSTALLED) + + Parser.add_option("-f", "--force", action="store_true", dest="Yes", help=ST.HLP_DISABLE_PROMPT) + + Parser.add_option("-n", "--custom-path", action="store_true", dest="CustomPath", help=ST.HLP_CUSTOM_PATH_PROMPT) + + Parser.add_option("-x", "--free-lock", action="store_true", dest="SkipLock", help=ST.HLP_SKIP_LOCK_CHECK) + + Parser.add_option("-u", "--replace", action="store", type="string", dest="Replace_Distribution_Package_File", + help=ST.HLP_SPECIFY_PACKAGE_NAME_REPLACE) + + Parser.add_option("-o", "--original", action="store", type="string", dest="Original_Distribution_Package_File", + help=ST.HLP_SPECIFY_PACKAGE_NAME_TO_BE_REPLACED) + + Parser.add_option("--use-guided-paths", action="store_true", dest="Use_Guided_Paths", help=ST.HLP_USE_GUIDED_PATHS) + + Parser.add_option("-j", "--test-install", action="append", type="string", + dest="Test_Install_Distribution_Package_Files", help=ST.HLP_TEST_INSTALL) + + Opt = Parser.parse_args()[0] + + Var2Var = [ + ("PackageInformationDataFile", Opt.Package_Information_Data_File), + ("PackFileToInstall", Opt.Install_Distribution_Package_File), + ("PackFileToCreate", Opt.Create_Distribution_Package_File), + ("PackFileToRemove", Opt.Remove_Distribution_Package_File), + ("PackageFileList", Opt.EDK2_DEC_Filename), + ("ModuleFileList", Opt.EDK2_INF_Filename), + ("InventoryWs", Opt.List_Dist_Installed), + ("PackFileToReplace", Opt.Replace_Distribution_Package_File), + ("PackFileToBeReplaced", Opt.Original_Distribution_Package_File), + ("UseGuidedPkgPath", Opt.Use_Guided_Paths), + ("TestDistFiles", Opt.Test_Install_Distribution_Package_Files) + ] + + for Var in Var2Var: + setattr(Opt, Var[0], Var[1]) + + try: + GlobalData.gWORKSPACE, GlobalData.gPACKAGE_PATH = GetWorkspace() + except FatalError as XExcept: + if Logger.GetLevel() <= Logger.DEBUG_9: + Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + format_exc()) + return XExcept.args[0] + + # Support WORKSPACE is a long path + # Only works for windows system + if pf.system() == 'Windows': + Vol = 'B:' + for Index in range(90, 65, -1): + Vol = chr(Index) + ':' + if not os.path.isdir(Vol): + os.system('subst %s "%s"' % (Vol, GlobalData.gWORKSPACE)) + break + GlobalData.gWORKSPACE = '%s\\' % Vol + + WorkspaceDir = GlobalData.gWORKSPACE + + SetLogLevel(Opt) + + Mgr = FileHook.RecoverMgr(WorkspaceDir) + FileHook.SetRecoverMgr(Mgr) + + GlobalData.gDB = IpiDatabase(os.path.normpath(os.path.join(WorkspaceDir, \ + "Conf/DistributionPackageDatabase.db")), WorkspaceDir) + GlobalData.gDB.InitDatabase(Opt.SkipLock) + + # + # Make sure the Db will get closed correctly + # + try: + ReturnCode = 0 + CheckConflictOption(Opt) + + RunModule = None + if Opt.PackFileToCreate: + if Opt.PackageInformationDataFile: + if not os.path.exists(Opt.PackageInformationDataFile): + if not os.path.exists(os.path.join(WorkspaceDir, Opt.PackageInformationDataFile)): + Logger.Error("\nUPT", FILE_NOT_FOUND, ST.ERR_NO_TEMPLATE_FILE % Opt.PackageInformationDataFile) + else: + Opt.PackageInformationDataFile = os.path.join(WorkspaceDir, Opt.PackageInformationDataFile) + else: + Logger.Error("UPT", OPTION_MISSING, ExtraData=ST.ERR_REQUIRE_T_OPTION) + if not Opt.PackFileToCreate.endswith('.dist'): + Logger.Error("CreatePkg", FILE_TYPE_MISMATCH, ExtraData=ST.ERR_DIST_EXT_ERROR % Opt.PackFileToCreate) + RunModule = MkPkg.Main + + elif Opt.PackFileToInstall: + AbsPath = [] + for Item in Opt.PackFileToInstall: + if not Item.endswith('.dist'): + Logger.Error("InstallPkg", FILE_TYPE_MISMATCH, ExtraData=ST.ERR_DIST_EXT_ERROR % Item) + + AbsPath.append(GetFullPathDist(Item, WorkspaceDir)) + if not AbsPath: + Logger.Error("InstallPkg", FILE_NOT_FOUND, ST.ERR_INSTALL_DIST_NOT_FOUND % Item) + + Opt.PackFileToInstall = AbsPath + setattr(Opt, 'PackageFile', Opt.PackFileToInstall) + RunModule = InstallPkg.Main + + elif Opt.PackFileToRemove: + if not Opt.PackFileToRemove.endswith('.dist'): + Logger.Error("RemovePkg", FILE_TYPE_MISMATCH, ExtraData=ST.ERR_DIST_EXT_ERROR % Opt.PackFileToRemove) + head, tail = os.path.split(Opt.PackFileToRemove) + if head or not tail: + Logger.Error("RemovePkg", + FILE_TYPE_MISMATCH, + ExtraData=ST.ERR_DIST_FILENAME_ONLY_FOR_REMOVE % Opt.PackFileToRemove) + + setattr(Opt, 'DistributionFile', Opt.PackFileToRemove) + RunModule = RmPkg.Main + elif Opt.InventoryWs: + RunModule = InventoryWs.Main + + elif Opt.PackFileToBeReplaced and not Opt.PackFileToReplace: + Logger.Error("ReplacePkg", OPTION_MISSING, ExtraData=ST.ERR_REQUIRE_U_OPTION) + + elif Opt.PackFileToReplace: + if not Opt.PackFileToReplace.endswith('.dist'): + Logger.Error("ReplacePkg", FILE_TYPE_MISMATCH, ExtraData=ST.ERR_DIST_EXT_ERROR % Opt.PackFileToReplace) + if not Opt.PackFileToBeReplaced: + Logger.Error("ReplacePkg", OPTION_MISSING, ExtraData=ST.ERR_REQUIRE_O_OPTION) + if not Opt.PackFileToBeReplaced.endswith('.dist'): + Logger.Error("ReplacePkg", + FILE_TYPE_MISMATCH, + ExtraData=ST.ERR_DIST_EXT_ERROR % Opt.PackFileToBeReplaced) + + head, tail = os.path.split(Opt.PackFileToBeReplaced) + if head or not tail: + Logger.Error("ReplacePkg", + FILE_TYPE_MISMATCH, + ExtraData=ST.ERR_DIST_FILENAME_ONLY_FOR_REPLACE_ORIG % Opt.PackFileToBeReplaced) + + AbsPath = GetFullPathDist(Opt.PackFileToReplace, WorkspaceDir) + if not AbsPath: + Logger.Error("ReplacePkg", FILE_NOT_FOUND, ST.ERR_REPLACE_DIST_NOT_FOUND % Opt.PackFileToReplace) + + Opt.PackFileToReplace = AbsPath + RunModule = ReplacePkg.Main + + elif Opt.Test_Install_Distribution_Package_Files: + for Dist in Opt.Test_Install_Distribution_Package_Files: + if not Dist.endswith('.dist'): + Logger.Error("TestInstall", FILE_TYPE_MISMATCH, ExtraData=ST.ERR_DIST_EXT_ERROR % Dist) + + setattr(Opt, 'DistFiles', Opt.Test_Install_Distribution_Package_Files) + RunModule = TestInstall.Main + + else: + Parser.print_usage() + return OPTION_MISSING + + ReturnCode = RunModule(Opt) + except FatalError as XExcept: + ReturnCode = XExcept.args[0] + if Logger.GetLevel() <= Logger.DEBUG_9: + Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + \ + format_exc()) + finally: + try: + if ReturnCode != 0 and ReturnCode != UPT_ALREADY_INSTALLED_ERROR: + Logger.Quiet(ST.MSG_RECOVER_START) + GlobalData.gDB.RollBack() + Mgr.rollback() + Logger.Quiet(ST.MSG_RECOVER_DONE) + else: + GlobalData.gDB.Commit() + Mgr.commit() + except Exception: + Logger.Quiet(ST.MSG_RECOVER_FAIL) + GlobalData.gDB.CloseDb() + + if pf.system() == 'Windows': + os.system('subst %s /D' % GlobalData.gWORKSPACE.replace('\\', '')) + + return ReturnCode + +## GetFullPathDist +# +# This function will check DistFile existence, if not absolute path, then try current working directory, +# then $(WORKSPACE),and return the AbsPath. If file doesn't find, then return None +# +# @param DistFile: The distribution file in either relative path or absolute path +# @param WorkspaceDir: Workspace Directory +# @return AbsPath: The Absolute path of the distribution file if existed, None else +# +def GetFullPathDist(DistFile, WorkspaceDir): + if os.path.isabs(DistFile): + if not (os.path.exists(DistFile) and os.path.isfile(DistFile)): + return None + else: + return DistFile + else: + AbsPath = os.path.normpath(os.path.join(os.getcwd(), DistFile)) + if not (os.path.exists(AbsPath) and os.path.isfile(AbsPath)): + AbsPath = os.path.normpath(os.path.join(WorkspaceDir, DistFile)) + if not (os.path.exists(AbsPath) and os.path.isfile(AbsPath)): + return None + + return AbsPath + +if __name__ == '__main__': + RETVAL = Main() + # + # 0-127 is a safe return range, and 1 is a standard default error + # + if RETVAL < 0 or RETVAL > 127: + RETVAL = 1 + sys.exit(RETVAL) diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/CommentGeneratingUnitTest.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/CommentGeneratingUnitTest.py new file mode 100755 index 00000000..7c8a829b --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/CommentGeneratingUnitTest.py @@ -0,0 +1,1414 @@ +## @file +# This file contain unit test for CommentParsing +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +import os +import unittest + +import Logger.Log as Logger +from GenMetaFile.GenInfFile import GenGuidSections +from GenMetaFile.GenInfFile import GenProtocolPPiSections +from GenMetaFile.GenInfFile import GenPcdSections +from GenMetaFile.GenInfFile import GenSpecialSections +from Library.CommentGenerating import GenGenericCommentF +from Library.CommentGenerating import _GetHelpStr +from Object.POM.CommonObject import TextObject +from Object.POM.CommonObject import GuidObject +from Object.POM.CommonObject import ProtocolObject +from Object.POM.CommonObject import PpiObject +from Object.POM.CommonObject import PcdObject +from Object.POM.ModuleObject import HobObject + +from Library.StringUtils import GetSplitValueList +from Library.DataType import TAB_SPACE_SPLIT +from Library.DataType import TAB_LANGUAGE_EN_US +from Library.DataType import TAB_LANGUAGE_ENG +from Library.DataType import ITEM_UNDEFINED +from Library.DataType import TAB_INF_FEATURE_PCD +from Library import GlobalData +from Library.Misc import CreateDirectory + +# +# Test _GetHelpStr +# +class _GetHelpStrTest(unittest.TestCase): + def setUp(self): + pass + + def tearDown(self): + pass + + # + # Normal case1: have one help text object with Lang = 'en-US' + # + def testNormalCase1(self): + HelpStr = 'Hello world' + HelpTextObj = TextObject() + HelpTextObj.SetLang(TAB_LANGUAGE_EN_US) + HelpTextObj.SetString(HelpStr) + + HelpTextList = [HelpTextObj] + Result = _GetHelpStr(HelpTextList) + self.assertEqual(Result, HelpStr) + + # + # Normal case2: have two help text object with Lang = 'en-US' and other + # + def testNormalCase2(self): + HelpStr = 'Hello world' + HelpTextObj = TextObject() + HelpTextObj.SetLang(TAB_LANGUAGE_ENG) + HelpTextObj.SetString(HelpStr) + + HelpTextList = [HelpTextObj] + + ExpectedStr = 'Hello world1' + HelpTextObj = TextObject() + HelpTextObj.SetLang(TAB_LANGUAGE_EN_US) + HelpTextObj.SetString(ExpectedStr) + + HelpTextList.append(HelpTextObj) + + Result = _GetHelpStr(HelpTextList) + self.assertEqual(Result, ExpectedStr) + + # + # Normal case3: have two help text object with Lang = '' and 'eng' + # + def testNormalCase3(self): + HelpStr = 'Hello world' + HelpTextObj = TextObject() + HelpTextObj.SetLang('') + HelpTextObj.SetString(HelpStr) + + HelpTextList = [HelpTextObj] + + ExpectedStr = 'Hello world1' + HelpTextObj = TextObject() + HelpTextObj.SetLang(TAB_LANGUAGE_ENG) + HelpTextObj.SetString(ExpectedStr) + + HelpTextList.append(HelpTextObj) + + Result = _GetHelpStr(HelpTextList) + self.assertEqual(Result, ExpectedStr) + + # + # Normal case4: have two help text object with Lang = '' and '' + # + def testNormalCase4(self): + + ExpectedStr = 'Hello world1' + HelpTextObj = TextObject() + HelpTextObj.SetLang(TAB_LANGUAGE_ENG) + HelpTextObj.SetString(ExpectedStr) + HelpTextList = [HelpTextObj] + + HelpStr = 'Hello world' + HelpTextObj = TextObject() + HelpTextObj.SetLang('') + HelpTextObj.SetString(HelpStr) + HelpTextList.append(HelpTextObj) + + Result = _GetHelpStr(HelpTextList) + self.assertEqual(Result, ExpectedStr) + + # + # Normal case: have three help text object with Lang = '','en', 'en-US' + # + def testNormalCase5(self): + + ExpectedStr = 'Hello world1' + HelpTextObj = TextObject() + HelpTextObj.SetLang(TAB_LANGUAGE_EN_US) + HelpTextObj.SetString(ExpectedStr) + HelpTextList = [HelpTextObj] + + HelpStr = 'Hello unknown world' + HelpTextObj = TextObject() + HelpTextObj.SetLang('') + HelpTextObj.SetString(HelpStr) + HelpTextList.append(HelpTextObj) + + HelpStr = 'Hello mysterious world' + HelpTextObj = TextObject() + HelpTextObj.SetLang('') + HelpTextObj.SetString(HelpStr) + HelpTextList.append(HelpTextObj) + + Result = _GetHelpStr(HelpTextList) + self.assertEqual(Result, ExpectedStr) + + HelpTextList.sort() + self.assertEqual(Result, ExpectedStr) + + HelpTextList.sort(reverse=True) + self.assertEqual(Result, ExpectedStr) + + +# +# Test GenGuidSections +# +class GenGuidSectionsTest(unittest.TestCase): + def setUp(self): + pass + + def tearDown(self): + pass + + # + # This is the API to generate Guid Object to help UnitTest + # + def GuidFactory(self, CName, FFE, Usage, GuidType, VariableName, HelpStr): + Guid = GuidObject() + Guid.SetCName(CName) + Guid.SetFeatureFlag(FFE) + Guid.SetGuidTypeList([GuidType]) + Guid.SetUsage(Usage) + Guid.SetVariableName(VariableName) + + HelpTextObj = TextObject() + HelpTextObj.SetLang('') + HelpTextObj.SetString(HelpStr) + Guid.SetHelpTextList([HelpTextObj]) + + return Guid + + # + # Normal case: have two GuidObject + # + def testNormalCase1(self): + GuidList = [] + + CName = 'Guid1' + FFE = 'FFE1' + Usage = 'PRODUCES' + GuidType = 'Event' + VariableName = '' + HelpStr = 'Usage comment line 1' + Guid1 = self.GuidFactory(CName, FFE, Usage, GuidType, + VariableName, HelpStr) + GuidList.append(Guid1) + + CName = 'Guid1' + FFE = 'FFE1' + Usage = 'CONSUMES' + GuidType = 'Variable' + VariableName = '' + HelpStr = 'Usage comment line 2' + Guid1 = self.GuidFactory(CName, FFE, Usage, GuidType, + VariableName, HelpStr) + GuidList.append(Guid1) + + Result = GenGuidSections(GuidList) + Expected = '''[Guids] +## PRODUCES ## Event # Usage comment line 1 +## CONSUMES ## Variable: # Usage comment line 2 +Guid1|FFE1''' + self.assertEqual(Result.strip(), Expected) + + # + # Normal case: have two GuidObject + # + def testNormalCase2(self): + GuidList = [] + + CName = 'Guid1' + FFE = 'FFE1' + Usage = 'PRODUCES' + GuidType = 'Event' + VariableName = '' + HelpStr = 'Usage comment line 1' + Guid1 = self.GuidFactory(CName, FFE, Usage, GuidType, + VariableName, HelpStr) + GuidList.append(Guid1) + + CName = 'Guid1' + FFE = 'FFE1' + Usage = 'UNDEFINED' + GuidType = 'UNDEFINED' + VariableName = '' + HelpStr = 'Generic comment line 1\n Generic comment line 2' + Guid1 = self.GuidFactory(CName, FFE, Usage, GuidType, + VariableName, HelpStr) + GuidList.append(Guid1) + + Result = GenGuidSections(GuidList) + Expected = '''[Guids] +## PRODUCES ## Event # Usage comment line 1 +# Generic comment line 1 +# Generic comment line 2 +Guid1|FFE1''' + + self.assertEqual(Result.strip(), Expected) + + # + # Normal case: have two GuidObject, one help goes to generic help, + # the other go into usage comment + # + def testNormalCase3(self): + GuidList = [] + + CName = 'Guid1' + FFE = 'FFE1' + Usage = 'UNDEFINED' + GuidType = 'UNDEFINED' + VariableName = '' + HelpStr = 'Generic comment' + Guid1 = self.GuidFactory(CName, FFE, Usage, GuidType, + VariableName, HelpStr) + GuidList.append(Guid1) + + CName = 'Guid1' + FFE = 'FFE1' + Usage = 'PRODUCES' + GuidType = 'Event' + VariableName = '' + HelpStr = 'Usage comment line 1' + Guid1 = self.GuidFactory(CName, FFE, Usage, GuidType, + VariableName, HelpStr) + GuidList.append(Guid1) + + Result = GenGuidSections(GuidList) + Expected = '''[Guids] +# Generic comment +## PRODUCES ## Event # Usage comment line 1 +Guid1|FFE1''' + + self.assertEqual(Result.strip(), Expected) + + # + # Normal case: have one GuidObject, generic comment multiple lines + # + def testNormalCase5(self): + GuidList = [] + + CName = 'Guid1' + FFE = 'FFE1' + Usage = 'UNDEFINED' + GuidType = 'UNDEFINED' + VariableName = '' + HelpStr = 'Generic comment line1 \n generic comment line 2' + Guid1 = self.GuidFactory(CName, FFE, Usage, GuidType, + VariableName, HelpStr) + GuidList.append(Guid1) + + Result = GenGuidSections(GuidList) + Expected = '''[Guids] +# Generic comment line1 +# generic comment line 2 +Guid1|FFE1''' + + self.assertEqual(Result.strip(), Expected) + + # + # Normal case: have one GuidObject, usage comment multiple lines + # + def testNormalCase6(self): + GuidList = [] + + CName = 'Guid1' + FFE = 'FFE1' + Usage = 'PRODUCES' + GuidType = 'Event' + VariableName = '' + HelpStr = 'Usage comment line 1\n Usage comment line 2' + Guid1 = self.GuidFactory(CName, FFE, Usage, GuidType, + VariableName, HelpStr) + GuidList.append(Guid1) + + Result = GenGuidSections(GuidList) + Expected = '''[Guids] +Guid1|FFE1 ## PRODUCES ## Event # Usage comment line 1 Usage comment line 2 +''' + self.assertEqual(Result.strip(), Expected.strip()) + + # + # Normal case: have one GuidObject, usage comment one line + # + def testNormalCase7(self): + GuidList = [] + + CName = 'Guid1' + FFE = 'FFE1' + Usage = 'UNDEFINED' + GuidType = 'UNDEFINED' + VariableName = '' + HelpStr = 'Usage comment line 1' + Guid1 = self.GuidFactory(CName, FFE, Usage, GuidType, + VariableName, HelpStr) + GuidList.append(Guid1) + + Result = GenGuidSections(GuidList) + Expected = '''[Guids] +Guid1|FFE1 # Usage comment line 1 +''' + self.assertEqual(Result.strip(), Expected.strip()) + + # + # Normal case: have two GuidObject + # + def testNormalCase8(self): + GuidList = [] + + CName = 'Guid1' + FFE = 'FFE1' + Usage = 'PRODUCES' + GuidType = 'Event' + VariableName = '' + HelpStr = 'Usage comment line 1\n Usage comment line 2' + Guid1 = self.GuidFactory(CName, FFE, Usage, GuidType, + VariableName, HelpStr) + GuidList.append(Guid1) + + CName = 'Guid1' + FFE = 'FFE1' + Usage = 'PRODUCES' + GuidType = 'Event' + VariableName = '' + HelpStr = 'Usage comment line 3' + Guid1 = self.GuidFactory(CName, FFE, Usage, GuidType, + VariableName, HelpStr) + GuidList.append(Guid1) + + Result = GenGuidSections(GuidList) + Expected = '''[Guids] +## PRODUCES ## Event # Usage comment line 1 Usage comment line 2 +## PRODUCES ## Event # Usage comment line 3 +Guid1|FFE1 +''' + self.assertEqual(Result.strip(), Expected.strip()) + + # + # Normal case: have no GuidObject + # + def testNormalCase9(self): + GuidList = [] + + Result = GenGuidSections(GuidList) + Expected = '' + self.assertEqual(Result.strip(), Expected.strip()) + + # + # Normal case: have one GuidObject with no comment generated + # + def testNormalCase10(self): + GuidList = [] + + CName = 'Guid1' + FFE = 'FFE1' + Usage = 'UNDEFINED' + GuidType = 'UNDEFINED' + VariableName = '' + HelpStr = '' + Guid1 = self.GuidFactory(CName, FFE, Usage, GuidType, + VariableName, HelpStr) + GuidList.append(Guid1) + + Result = GenGuidSections(GuidList) + Expected = '''[Guids] +Guid1|FFE1 +''' + self.assertEqual(Result.strip(), Expected.strip()) + + # + # Normal case: have three GuidObject + # + def testNormalCase11(self): + GuidList = [] + + CName = 'Guid1' + FFE = 'FFE1' + Usage = 'UNDEFINED' + GuidType = 'UNDEFINED' + VariableName = '' + HelpStr = 'general comment line 1' + Guid1 = self.GuidFactory(CName, FFE, Usage, GuidType, + VariableName, HelpStr) + GuidList.append(Guid1) + + CName = 'Guid1' + FFE = 'FFE1' + Usage = 'PRODUCES' + GuidType = 'Event' + VariableName = '' + HelpStr = 'Usage comment line 3' + Guid1 = self.GuidFactory(CName, FFE, Usage, GuidType, + VariableName, HelpStr) + GuidList.append(Guid1) + + CName = 'Guid1' + FFE = 'FFE1' + Usage = 'UNDEFINED' + GuidType = 'UNDEFINED' + VariableName = '' + HelpStr = 'general comment line 2' + Guid1 = self.GuidFactory(CName, FFE, Usage, GuidType, + VariableName, HelpStr) + GuidList.append(Guid1) + + Result = GenGuidSections(GuidList) + Expected = '''[Guids] +# general comment line 1 +## PRODUCES ## Event # Usage comment line 3 +# general comment line 2 +Guid1|FFE1 +''' + self.assertEqual(Result.strip(), Expected.strip()) + + # + # Normal case: have three GuidObject, with Usage/Type and no help + # + def testNormalCase12(self): + GuidList = [] + + CName = 'Guid1' + FFE = 'FFE1' + Usage = 'PRODUCES' + GuidType = 'GUID' + VariableName = '' + HelpStr = '' + Guid1 = self.GuidFactory(CName, FFE, Usage, GuidType, + VariableName, HelpStr) + GuidList.append(Guid1) + + CName = 'Guid1' + FFE = 'FFE1' + Usage = 'PRODUCES' + GuidType = 'Event' + VariableName = '' + HelpStr = '' + Guid1 = self.GuidFactory(CName, FFE, Usage, GuidType, + VariableName, HelpStr) + GuidList.append(Guid1) + + CName = 'Guid1' + FFE = 'FFE1' + Usage = 'CONSUMES' + GuidType = 'Event' + VariableName = '' + HelpStr = '' + Guid1 = self.GuidFactory(CName, FFE, Usage, GuidType, + VariableName, HelpStr) + GuidList.append(Guid1) + + Result = GenGuidSections(GuidList) + Expected = '''[Guids] +## PRODUCES ## GUID +## PRODUCES ## Event +## CONSUMES ## Event +Guid1|FFE1 +''' + self.assertEqual(Result.strip(), Expected.strip()) + +# +# Test GenProtocolPPiSections +# +class GenProtocolPPiSectionsTest(unittest.TestCase): + def setUp(self): + pass + + def tearDown(self): + pass + + # + # This is the API to generate Protocol/Ppi Object to help UnitTest + # + def ObjectFactory(self, CName, FFE, Usage, Notify, HelpStr, IsProtocol): + if IsProtocol: + Object = ProtocolObject() + else: + Object = PpiObject() + + Object.SetCName(CName) + Object.SetFeatureFlag(FFE) + Object.SetUsage(Usage) + Object.SetNotify(Notify) + + HelpTextObj = TextObject() + HelpTextObj.SetLang('') + HelpTextObj.SetString(HelpStr) + Object.SetHelpTextList([HelpTextObj]) + + return Object + + # Usage Notify Help INF Comment + #1 UNDEFINED true Present ## UNDEFINED ## NOTIFY # Help + #2 UNDEFINED true Not Present ## UNDEFINED ## NOTIFY + #3 UNDEFINED false Present ## UNDEFINED # Help + #4 UNDEFINED false Not Present ## UNDEFINED + #5 UNDEFINED Not Present Present # Help + #6 UNDEFINED Not Present Not Present + #7 Other true Present ## Other ## NOTIFY # Help + #8 Other true Not Present ## Other ## NOTIFY + #9 Other false Present ## Other # Help + #A Other false Not Present ## Other + #B Other Not Present Present ## Other # Help + #C Other Not Present Not Present ## Other + + def testNormalCase1(self): + ObjectList = [] + + CName = 'Guid1' + FFE = 'FFE1' + + Usage = 'UNDEFINED' + Notify = True + HelpStr = 'Help' + IsProtocol = True + Object = self.ObjectFactory(CName, FFE, Usage, Notify, + HelpStr, IsProtocol) + ObjectList.append(Object) + + + Result = GenProtocolPPiSections(ObjectList, IsProtocol) + Expected = '''[Protocols] +Guid1|FFE1 ## UNDEFINED ## NOTIFY # Help''' + self.assertEqual(Result.strip(), Expected) + + IsProtocol = False + ObjectList = [] + Object = self.ObjectFactory(CName, FFE, Usage, Notify, + HelpStr, IsProtocol) + ObjectList.append(Object) + + + Result = GenProtocolPPiSections(ObjectList, IsProtocol) + Expected = '''[Ppis] +Guid1|FFE1 ## UNDEFINED ## NOTIFY # Help''' + self.assertEqual(Result.strip(), Expected) + + def testNormalCase2(self): + ObjectList = [] + + CName = 'Guid1' + FFE = 'FFE1' + + Usage = 'UNDEFINED' + Notify = True + HelpStr = '' + IsProtocol = True + Object = self.ObjectFactory(CName, FFE, Usage, Notify, + HelpStr, IsProtocol) + ObjectList.append(Object) + + + Result = GenProtocolPPiSections(ObjectList, IsProtocol) + Expected = '''[Protocols] +Guid1|FFE1 ## UNDEFINED ## NOTIFY''' + self.assertEqual(Result.strip(), Expected) + + def testNormalCase3(self): + ObjectList = [] + + CName = 'Guid1' + FFE = 'FFE1' + + Usage = 'UNDEFINED' + Notify = False + HelpStr = 'Help' + IsProtocol = True + Object = self.ObjectFactory(CName, FFE, Usage, Notify, + HelpStr, IsProtocol) + ObjectList.append(Object) + + + Result = GenProtocolPPiSections(ObjectList, IsProtocol) + Expected = '''[Protocols] +Guid1|FFE1 ## UNDEFINED # Help''' + self.assertEqual(Result.strip(), Expected) + + def testNormalCase4(self): + ObjectList = [] + + CName = 'Guid1' + FFE = 'FFE1' + + Usage = 'UNDEFINED' + Notify = False + HelpStr = '' + IsProtocol = True + Object = self.ObjectFactory(CName, FFE, Usage, Notify, + HelpStr, IsProtocol) + ObjectList.append(Object) + + + Result = GenProtocolPPiSections(ObjectList, IsProtocol) + Expected = '''[Protocols] +Guid1|FFE1 ## UNDEFINED''' + self.assertEqual(Result.strip(), Expected) + + def testNormalCase5(self): + ObjectList = [] + + CName = 'Guid1' + FFE = 'FFE1' + + Usage = 'UNDEFINED' + Notify = '' + HelpStr = 'Help' + IsProtocol = True + Object = self.ObjectFactory(CName, FFE, Usage, Notify, + HelpStr, IsProtocol) + ObjectList.append(Object) + + + Result = GenProtocolPPiSections(ObjectList, IsProtocol) + Expected = '''[Protocols] +Guid1|FFE1 # Help''' + self.assertEqual(Result.strip(), Expected) + + def testNormalCase6(self): + ObjectList = [] + + CName = 'Guid1' + FFE = 'FFE1' + + Usage = 'UNDEFINED' + Notify = '' + HelpStr = '' + IsProtocol = True + Object = self.ObjectFactory(CName, FFE, Usage, Notify, + HelpStr, IsProtocol) + ObjectList.append(Object) + + + Result = GenProtocolPPiSections(ObjectList, IsProtocol) + Expected = '''[Protocols] +Guid1|FFE1''' + self.assertEqual(Result.strip(), Expected) + + def testNormalCase7(self): + ObjectList = [] + + CName = 'Guid1' + FFE = 'FFE1' + + Usage = 'PRODUCES' + Notify = True + HelpStr = 'Help' + IsProtocol = True + Object = self.ObjectFactory(CName, FFE, Usage, Notify, + HelpStr, IsProtocol) + ObjectList.append(Object) + + + Result = GenProtocolPPiSections(ObjectList, IsProtocol) + Expected = '''[Protocols] +Guid1|FFE1 ## PRODUCES ## NOTIFY # Help''' + self.assertEqual(Result.strip(), Expected) + + def testNormalCase8(self): + ObjectList = [] + + CName = 'Guid1' + FFE = 'FFE1' + + Usage = 'PRODUCES' + Notify = True + HelpStr = '' + IsProtocol = True + Object = self.ObjectFactory(CName, FFE, Usage, Notify, + HelpStr, IsProtocol) + ObjectList.append(Object) + + + Result = GenProtocolPPiSections(ObjectList, IsProtocol) + Expected = '''[Protocols] +Guid1|FFE1 ## PRODUCES ## NOTIFY''' + self.assertEqual(Result.strip(), Expected) + + def testNormalCase9(self): + ObjectList = [] + + CName = 'Guid1' + FFE = 'FFE1' + + Usage = 'PRODUCES' + Notify = False + HelpStr = 'Help' + IsProtocol = True + Object = self.ObjectFactory(CName, FFE, Usage, Notify, + HelpStr, IsProtocol) + ObjectList.append(Object) + + + Result = GenProtocolPPiSections(ObjectList, IsProtocol) + Expected = '''[Protocols] +Guid1|FFE1 ## PRODUCES # Help''' + self.assertEqual(Result.strip(), Expected) + + def testNormalCaseA(self): + ObjectList = [] + + CName = 'Guid1' + FFE = 'FFE1' + + Usage = 'PRODUCES' + Notify = False + HelpStr = '' + IsProtocol = True + Object = self.ObjectFactory(CName, FFE, Usage, Notify, + HelpStr, IsProtocol) + ObjectList.append(Object) + + + Result = GenProtocolPPiSections(ObjectList, IsProtocol) + Expected = '''[Protocols] +Guid1|FFE1 ## PRODUCES''' + self.assertEqual(Result.strip(), Expected) + + def testNormalCaseB(self): + ObjectList = [] + + CName = 'Guid1' + FFE = 'FFE1' + + Usage = 'PRODUCES' + Notify = '' + HelpStr = 'Help' + IsProtocol = True + Object = self.ObjectFactory(CName, FFE, Usage, Notify, + HelpStr, IsProtocol) + ObjectList.append(Object) + + + Result = GenProtocolPPiSections(ObjectList, IsProtocol) + Expected = '''[Protocols] +Guid1|FFE1 ## PRODUCES # Help''' + self.assertEqual(Result.strip(), Expected) + + def testNormalCaseC(self): + ObjectList = [] + + CName = 'Guid1' + FFE = 'FFE1' + + Usage = 'PRODUCES' + Notify = '' + HelpStr = '' + IsProtocol = True + Object = self.ObjectFactory(CName, FFE, Usage, Notify, + HelpStr, IsProtocol) + ObjectList.append(Object) + + + Result = GenProtocolPPiSections(ObjectList, IsProtocol) + Expected = '''[Protocols] +Guid1|FFE1 ## PRODUCES''' + self.assertEqual(Result.strip(), Expected) + +# +# Test GenPcdSections +# +class GenPcdSectionsTest(unittest.TestCase): + def setUp(self): + pass + + def tearDown(self): + pass + + # + # This is the API to generate Pcd Object to help UnitTest + # + def ObjectFactory(self, ItemType, TSCName, CName, DValue, FFE, Usage, Str): + Object = PcdObject() + HelpStr = Str + + Object.SetItemType(ItemType) + Object.SetTokenSpaceGuidCName(TSCName) + Object.SetCName(CName) + Object.SetDefaultValue(DValue) + Object.SetFeatureFlag(FFE) + Object.SetValidUsage(Usage) + + HelpTextObj = TextObject() + HelpTextObj.SetLang('') + HelpTextObj.SetString(HelpStr) + Object.SetHelpTextList([HelpTextObj]) + + return Object + + + # Usage Help INF Comment + #1 UNDEFINED Present # Help + #2 UNDEFINED Not Present + #3 Other Present ## Other # Help + #4 Other Not Present ## Other + + def testNormalCase1(self): + ObjectList = [] + ItemType = 'Pcd' + TSCName = 'TSCName' + CName = 'CName' + DValue = 'DValue' + FFE = 'FFE' + + Usage = 'UNDEFINED' + Str = 'Help' + + Object = self.ObjectFactory(ItemType, TSCName, CName, DValue, FFE, + Usage, Str) + ObjectList.append(Object) + + Result = GenPcdSections(ObjectList) + Expected = \ + '[Pcd]\n' + \ + 'TSCName.CName|DValue|FFE # Help' + self.assertEqual(Result.strip(), Expected) + + def testNormalCase2(self): + ObjectList = [] + ItemType = 'Pcd' + TSCName = 'TSCName' + CName = 'CName' + DValue = 'DValue' + FFE = 'FFE' + + Usage = 'UNDEFINED' + Str = '' + + Object = self.ObjectFactory(ItemType, TSCName, CName, DValue, FFE, + Usage, Str) + ObjectList.append(Object) + + Result = GenPcdSections(ObjectList) + Expected = '[Pcd]\nTSCName.CName|DValue|FFE' + self.assertEqual(Result.strip(), Expected) + + def testNormalCase3(self): + ObjectList = [] + ItemType = 'Pcd' + TSCName = 'TSCName' + CName = 'CName' + DValue = 'DValue' + FFE = 'FFE' + + Usage = 'CONSUMES' + Str = 'Help' + + Object = self.ObjectFactory(ItemType, TSCName, CName, DValue, FFE, + Usage, Str) + ObjectList.append(Object) + + Result = GenPcdSections(ObjectList) + Expected = '[Pcd]\nTSCName.CName|DValue|FFE ## CONSUMES # Help' + self.assertEqual(Result.strip(), Expected) + + def testNormalCase4(self): + ObjectList = [] + ItemType = 'Pcd' + TSCName = 'TSCName' + CName = 'CName' + DValue = 'DValue' + FFE = 'FFE' + + Usage = 'CONSUMES' + Str = '' + + Object = self.ObjectFactory(ItemType, TSCName, CName, DValue, FFE, + Usage, Str) + ObjectList.append(Object) + + Result = GenPcdSections(ObjectList) + Expected = '[Pcd]\nTSCName.CName|DValue|FFE ## CONSUMES' + self.assertEqual(Result.strip(), Expected) + + # + # multiple lines for normal usage + # + def testNormalCase5(self): + ObjectList = [] + ItemType = 'Pcd' + TSCName = 'TSCName' + CName = 'CName' + DValue = 'DValue' + FFE = 'FFE' + + Usage = 'CONSUMES' + Str = 'commment line 1\ncomment line 2' + Object = self.ObjectFactory(ItemType, TSCName, CName, DValue, FFE, + Usage, Str) + ObjectList.append(Object) + + Result = GenPcdSections(ObjectList) + Expected = '''[Pcd] +TSCName.CName|DValue|FFE ## CONSUMES # commment line 1 comment line 2''' + self.assertEqual(Result.strip(), Expected) + + # + # multiple lines for UNDEFINED usage + # + def testNormalCase6(self): + ObjectList = [] + ItemType = 'Pcd' + TSCName = 'TSCName' + CName = 'CName' + DValue = 'DValue' + FFE = 'FFE' + + Usage = 'UNDEFINED' + Str = 'commment line 1\ncomment line 2' + Object = self.ObjectFactory(ItemType, TSCName, CName, DValue, FFE, + Usage, Str) + ObjectList.append(Object) + + Usage = 'UNDEFINED' + Str = 'commment line 3' + Object = self.ObjectFactory(ItemType, TSCName, CName, DValue, FFE, + Usage, Str) + ObjectList.append(Object) + + Result = GenPcdSections(ObjectList) + Expected = '''[Pcd] +# commment line 1 +# comment line 2 +# commment line 3 +TSCName.CName|DValue|FFE''' + self.assertEqual(Result.strip(), Expected) + + # + # multiple lines for UNDEFINED and normal usage + # + def testNormalCase7(self): + ObjectList = [] + ItemType = 'Pcd' + TSCName = 'TSCName' + CName = 'CName' + DValue = 'DValue' + FFE = 'FFE' + + Usage = 'UNDEFINED' + Str = 'commment line 1\ncomment line 2' + Object = self.ObjectFactory(ItemType, TSCName, CName, DValue, FFE, + Usage, Str) + ObjectList.append(Object) + + Usage = 'CONSUMES' + Str = 'Foo' + Object = self.ObjectFactory(ItemType, TSCName, CName, DValue, FFE, + Usage, Str) + ObjectList.append(Object) + + Usage = 'UNDEFINED' + Str = 'commment line 3' + Object = self.ObjectFactory(ItemType, TSCName, CName, DValue, FFE, + Usage, Str) + ObjectList.append(Object) + + Result = GenPcdSections(ObjectList) + Expected = '''[Pcd] +# commment line 1 +# comment line 2 +## CONSUMES # Foo +# commment line 3 +TSCName.CName|DValue|FFE''' + self.assertEqual(Result.strip(), Expected) + + # Usage Help INF Comment + # CONSUMES Present # Help (keep and insert '#' at beginning of each new line) + # CONSUMES Not Present + + # + # TAB_INF_FEATURE_PCD + # + def testNormalCase8(self): + ObjectList = [] + ItemType = TAB_INF_FEATURE_PCD + TSCName = 'TSCName' + CName = 'CName' + DValue = 'DValue' + FFE = 'FFE' + + Usage = 'CONSUMES' + Str = 'commment line 1\ncomment line 2' + Object = self.ObjectFactory(ItemType, TSCName, CName, DValue, FFE, + Usage, Str) + ObjectList.append(Object) + + Result = GenPcdSections(ObjectList) + Expected = '''[FeaturePcd] +# commment line 1 +# comment line 2 +TSCName.CName|DValue|FFE''' + self.assertEqual(Result.strip(), Expected) + + # + # TAB_INF_FEATURE_PCD + # + def testNormalCase9(self): + ObjectList = [] + ItemType = TAB_INF_FEATURE_PCD + TSCName = 'TSCName' + CName = 'CName' + DValue = 'DValue' + FFE = 'FFE' + + Usage = 'CONSUMES' + Str = '' + Object = self.ObjectFactory(ItemType, TSCName, CName, DValue, FFE, + Usage, Str) + ObjectList.append(Object) + + Result = GenPcdSections(ObjectList) + Expected = '''[FeaturePcd] +TSCName.CName|DValue|FFE''' + self.assertEqual(Result.strip(), Expected) + + # + # TAB_INF_FEATURE_PCD + # + def testNormalCase10(self): + ObjectList = [] + ItemType = TAB_INF_FEATURE_PCD + TSCName = 'TSCName' + CName = 'CName' + DValue = 'DValue' + FFE = 'FFE' + + Usage = 'PRODUCES' + Str = 'commment line 1\ncomment line 2' + Object = self.ObjectFactory(ItemType, TSCName, CName, DValue, FFE, + Usage, Str) + ObjectList.append(Object) + + Result = GenPcdSections(ObjectList) + Expected = ''' + +[FeaturePcd] +# commment line 1 +# comment line 2 +TSCName.CName|DValue|FFE +''' + self.assertEqual(Result, Expected) + + +# +# Test GenSpecialSections of Hob +# +class GenHobSectionsTest(unittest.TestCase): + def setUp(self): + pass + + def tearDown(self): + pass + + # + # This is the API to generate Event Object to help UnitTest + # + def ObjectFactory(self, SupArchList, Type, Usage, Str): + Object = HobObject() + HelpStr = Str + + Object.SetHobType(Type) + Object.SetUsage(Usage) + Object.SetSupArchList(SupArchList) + + HelpTextObj = TextObject() + HelpTextObj.SetLang('') + HelpTextObj.SetString(HelpStr) + Object.SetHelpTextList([HelpTextObj]) + + return Object + + def testNormalCase1(self): + ObjectList = [] + SupArchList = ['X64'] + Type = 'Foo' + Usage = 'UNDEFINED' + Str = 'Help' + + Object = self.ObjectFactory(SupArchList, Type, Usage, Str) + ObjectList.append(Object) + + Result = GenSpecialSections(ObjectList, 'Hob') + Expected = '''# [Hob.X64] +# ## +# # Help +# # +# Foo ## UNDEFINED +# +# +''' + self.assertEqual(Result, Expected) + + def testNormalCase2(self): + ObjectList = [] + SupArchList = [] + Type = 'Foo' + Usage = 'UNDEFINED' + Str = 'Help' + + Object = self.ObjectFactory(SupArchList, Type, Usage, Str) + ObjectList.append(Object) + + Result = GenSpecialSections(ObjectList, 'Hob') + Expected = '''# [Hob] +# ## +# # Help +# # +# Foo ## UNDEFINED +# +# +''' + self.assertEqual(Result, Expected) + + def testNormalCase3(self): + ObjectList = [] + SupArchList = ['X64'] + Type = 'Foo' + Usage = 'UNDEFINED' + Str = '\nComment Line 1\n\n' + + Object = self.ObjectFactory(SupArchList, Type, Usage, Str) + ObjectList.append(Object) + + Result = GenSpecialSections(ObjectList, 'Hob') + Expected = '''# [Hob.X64] +# ## +# # Comment Line 1 +# # +# Foo ## UNDEFINED +# +# +''' + self.assertEqual(Result, Expected) + + def testNormalCase4(self): + ObjectList = [] + SupArchList = ['X64'] + Type = 'Foo' + Usage = 'UNDEFINED' + Str = '\nComment Line 1\n' + + Object = self.ObjectFactory(SupArchList, Type, Usage, Str) + ObjectList.append(Object) + + Result = GenSpecialSections(ObjectList, 'Hob') + Expected = '''# [Hob.X64] +# ## +# # Comment Line 1 +# # +# Foo ## UNDEFINED +# +# +''' + self.assertEqual(Result, Expected) + + def testNormalCase5(self): + ObjectList = [] + SupArchList = ['X64'] + Type = 'Foo' + Usage = 'UNDEFINED' + Str = 'Comment Line 1\n\n' + + Object = self.ObjectFactory(SupArchList, Type, Usage, Str) + ObjectList.append(Object) + + Result = GenSpecialSections(ObjectList, 'Hob') + Expected = '''# [Hob.X64] +# ## +# # Comment Line 1 +# # +# Foo ## UNDEFINED +# +# +''' + self.assertEqual(Result, Expected) + + def testNormalCase6(self): + ObjectList = [] + SupArchList = ['X64'] + Type = 'Foo' + Usage = 'UNDEFINED' + Str = '' + + Object = self.ObjectFactory(SupArchList, Type, Usage, Str) + ObjectList.append(Object) + + Result = GenSpecialSections(ObjectList, 'Hob') + Expected = '''# [Hob.X64] +# Foo ## UNDEFINED +# +# +''' + self.assertEqual(Result, Expected) + + def testNormalCase7(self): + ObjectList = [] + SupArchList = ['X64'] + Type = 'Foo' + Usage = 'UNDEFINED' + Str = '\nNew Stack HoB' + + + Object = self.ObjectFactory(SupArchList, Type, Usage, Str) + ObjectList.append(Object) + + Result = GenSpecialSections(ObjectList, 'Hob') + Expected = '''# [Hob.X64] +# ## +# # New Stack HoB +# # +# Foo ## UNDEFINED +# +# +''' + self.assertEqual(Result, Expected) + + def testNormalCase8(self): + ObjectList = [] + SupArchList = ['X64'] + Type = 'Foo' + Usage = 'UNDEFINED' + Str = '\nNew Stack HoB\n\nTail Comment' + + + Object = self.ObjectFactory(SupArchList, Type, Usage, Str) + ObjectList.append(Object) + + Result = GenSpecialSections(ObjectList, 'Hob') + Expected = '''# [Hob.X64] +# ## +# # New Stack HoB +# # +# # Tail Comment +# # +# Foo ## UNDEFINED +# +# +''' + self.assertEqual(Result, Expected) + + def testNormalCase9(self): + ObjectList = [] + SupArchList = ['X64'] + Type = 'Foo' + Usage = 'UNDEFINED' + Str = '\n\n' + + + Object = self.ObjectFactory(SupArchList, Type, Usage, Str) + ObjectList.append(Object) + + Result = GenSpecialSections(ObjectList, 'Hob') + Expected = '''# [Hob.X64] +# ## +# # +# # +# Foo ## UNDEFINED +# +# +''' + self.assertEqual(Result, Expected) + + def testNormalCase10(self): + ObjectList = [] + SupArchList = ['X64'] + Type = 'Foo' + Usage = 'UNDEFINED' + Str = '\n' + + Object = self.ObjectFactory(SupArchList, Type, Usage, Str) + ObjectList.append(Object) + + Result = GenSpecialSections(ObjectList, 'Hob') + Expected = '''# [Hob.X64] +# ## +# # +# # +# Foo ## UNDEFINED +# +# +''' + self.assertEqual(Result, Expected) + + def testNormalCase11(self): + ObjectList = [] + SupArchList = ['X64'] + Type = 'Foo' + Usage = 'UNDEFINED' + Str = '\n\n\n' + + Object = self.ObjectFactory(SupArchList, Type, Usage, Str) + ObjectList.append(Object) + + Result = GenSpecialSections(ObjectList, 'Hob') + Expected = '''# [Hob.X64] +# ## +# # +# # +# Foo ## UNDEFINED +# +# +''' + self.assertEqual(Result, Expected) + + def testNormalCase12(self): + ObjectList = [] + SupArchList = ['X64'] + Type = 'Foo' + Usage = 'UNDEFINED' + Str = '\n\n\n\n' + + Object = self.ObjectFactory(SupArchList, Type, Usage, Str) + ObjectList.append(Object) + + Result = GenSpecialSections(ObjectList, 'Hob') + Expected = '''# [Hob.X64] +# ## +# # +# # +# # +# Foo ## UNDEFINED +# +# +''' + self.assertEqual(Result, Expected) + +# +# Test GenGenericCommentF +# +class GenGenericCommentFTest(unittest.TestCase): + def setUp(self): + pass + + def tearDown(self): + pass + + def testNormalCase1(self): + CommentLines = 'Comment Line 1' + Result = GenGenericCommentF(CommentLines) + Expected = '# Comment Line 1\n' + self.assertEqual(Result, Expected) + + def testNormalCase2(self): + CommentLines = '\n' + Result = GenGenericCommentF(CommentLines) + Expected = '#\n' + self.assertEqual(Result, Expected) + + def testNormalCase3(self): + CommentLines = '\n\n\n' + Result = GenGenericCommentF(CommentLines) + Expected = '#\n#\n#\n' + self.assertEqual(Result, Expected) + + def testNormalCase4(self): + CommentLines = 'coment line 1\n' + Result = GenGenericCommentF(CommentLines) + Expected = '# coment line 1\n' + self.assertEqual(Result, Expected) + + def testNormalCase5(self): + CommentLines = 'coment line 1\n coment line 2\n' + Result = GenGenericCommentF(CommentLines) + Expected = '# coment line 1\n# coment line 2\n' + self.assertEqual(Result, Expected) + +if __name__ == '__main__': + Logger.Initialize() + unittest.main() diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/CommentParsingUnitTest.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/CommentParsingUnitTest.py new file mode 100755 index 00000000..c033322c --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/CommentParsingUnitTest.py @@ -0,0 +1,917 @@ +## @file +# This file contain unit test for CommentParsing +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +import unittest + +import Logger.Log as Logger +from Library.CommentParsing import ParseHeaderCommentSection, \ + ParseGenericComment, \ + ParseDecPcdGenericComment, \ + ParseDecPcdTailComment +from Library.CommentParsing import _IsCopyrightLine +from Library.StringUtils import GetSplitValueList +from Library.DataType import TAB_SPACE_SPLIT +from Library.DataType import TAB_LANGUAGE_EN_US + +# +# Test ParseHeaderCommentSection +# +class ParseHeaderCommentSectionTest(unittest.TestCase): + def setUp(self): + pass + + def tearDown(self): + pass + + # + # Normal case1: have license/copyright/license above @file + # + def testNormalCase1(self): + TestCommentLines1 = \ + '''# License1 + # License2 + # + ## @file + # example abstract + # + # example description + # + # Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ # + # License3 + #''' + + CommentList = GetSplitValueList(TestCommentLines1, "\n") + LineNum = 0 + TestCommentLinesList = [] + for Comment in CommentList: + LineNum += 1 + TestCommentLinesList.append((Comment, LineNum)) + + Abstract, Description, Copyright, License = \ + ParseHeaderCommentSection(TestCommentLinesList, "PhonyFile") + + ExpectedAbstract = 'example abstract' + self.assertEqual(Abstract, ExpectedAbstract) + + ExpectedDescription = 'example description' + self.assertEqual(Description, ExpectedDescription) + + ExpectedCopyright = \ + 'Copyright (c) 2007 - 2010,'\ + ' Intel Corporation. All rights reserved.
' + self.assertEqual(Copyright, ExpectedCopyright) + + ExpectedLicense = 'License1\nLicense2\n\nLicense3' + self.assertEqual(License, ExpectedLicense) + + # + # Normal case2: have license/copyright above @file, but no copyright after + # + def testNormalCase2(self): + TestCommentLines2 = \ + ''' # License1 + # License2 + # + ## @file + # example abstract + # + # example description + # + #Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ # + ##''' + + CommentList = GetSplitValueList(TestCommentLines2, "\n") + LineNum = 0 + TestCommentLinesList = [] + for Comment in CommentList: + LineNum += 1 + TestCommentLinesList.append((Comment, LineNum)) + + Abstract, Description, Copyright, License = \ + ParseHeaderCommentSection(TestCommentLinesList, "PhonyFile") + + ExpectedAbstract = 'example abstract' + self.assertEqual(Abstract, ExpectedAbstract) + + ExpectedDescription = 'example description' + self.assertEqual(Description, ExpectedDescription) + + ExpectedCopyright = \ + 'Copyright (c) 2007 - 2018, Intel Corporation.'\ + ' All rights reserved.
' + self.assertEqual(Copyright, ExpectedCopyright) + + ExpectedLicense = 'License1\nLicense2' + self.assertEqual(License, ExpectedLicense) + + + # + # Normal case2: have license/copyright/license above @file, + # but no abstract/description + # + def testNormalCase3(self): + TestCommentLines3 = \ + ''' # License1 + # License2 + # + ## @file + # Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ # + # License3 Line1 + # License3 Line2 + ##''' + + CommentList = GetSplitValueList(TestCommentLines3, "\n") + LineNum = 0 + TestCommentLinesList = [] + for Comment in CommentList: + LineNum += 1 + TestCommentLinesList.append((Comment, LineNum)) + + Abstract, Description, Copyright, License = \ + ParseHeaderCommentSection(TestCommentLinesList, "PhonyFile") + + ExpectedAbstract = '' + self.assertEqual(Abstract, ExpectedAbstract) + + ExpectedDescription = '' + self.assertEqual(Description, ExpectedDescription) + + ExpectedCopyright = \ + 'Copyright (c) 2007 - 2010,'\ + ' Intel Corporation. All rights reserved.
' + self.assertEqual(Copyright, ExpectedCopyright) + + ExpectedLicense = \ + 'License1\n' \ + 'License2\n\n' \ + 'License3 Line1\n' \ + 'License3 Line2' + self.assertEqual(License, ExpectedLicense) + + # + # Normal case4: format example in spec + # + def testNormalCase4(self): + TestCommentLines = \ + ''' + ## @file + # Abstract + # + # Description + # + # Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ # + # License + # + ##''' + + CommentList = GetSplitValueList(TestCommentLines, "\n") + LineNum = 0 + TestCommentLinesList = [] + for Comment in CommentList: + LineNum += 1 + TestCommentLinesList.append((Comment, LineNum)) + + Abstract, Description, Copyright, License = \ + ParseHeaderCommentSection(TestCommentLinesList, "PhonyFile") + + ExpectedAbstract = 'Abstract' + self.assertEqual(Abstract, ExpectedAbstract) + + ExpectedDescription = 'Description' + self.assertEqual(Description, ExpectedDescription) + + ExpectedCopyright = \ + 'Copyright (c) 2007 - 2018, Intel Corporation.'\ + ' All rights reserved.
' + self.assertEqual(Copyright, ExpectedCopyright) + + ExpectedLicense = \ + 'License' + self.assertEqual(License, ExpectedLicense) + + # + # Normal case5: other line between copyright + # + def testNormalCase5(self): + TestCommentLines = \ + ''' + ## @file + # Abstract + # + # Description + # + # Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ # other line + # Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ # + # License + # + ##''' + + CommentList = GetSplitValueList(TestCommentLines, "\n") + LineNum = 0 + TestCommentLinesList = [] + for Comment in CommentList: + LineNum += 1 + TestCommentLinesList.append((Comment, LineNum)) + + Abstract, Description, Copyright, License = \ + ParseHeaderCommentSection(TestCommentLinesList, "PhonyFile") + + ExpectedAbstract = 'Abstract' + self.assertEqual(Abstract, ExpectedAbstract) + + ExpectedDescription = 'Description' + self.assertEqual(Description, ExpectedDescription) + + ExpectedCopyright = \ + 'Copyright (c) 2007 - 2018, Intel Corporation.'\ + ' All rights reserved.
\n'\ + 'Copyright (c) 2007 - 2018, Intel Corporation.'\ + ' All rights reserved.
' + self.assertEqual(Copyright, ExpectedCopyright) + + ExpectedLicense = \ + 'License' + self.assertEqual(License, ExpectedLicense) + + # + # Normal case6: multiple lines of copyright + # + def testNormalCase6(self): + TestCommentLines = \ + ''' + ## @file + # Abstract + # + # Description + # + # Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ # Copyright (c) 2007 - 2010, FOO1 Corporation. All rights reserved.
+ # Copyright (c) 2007 - 2010, FOO2 Corporation. All rights reserved.
+ # + # License + # + ##''' + + CommentList = GetSplitValueList(TestCommentLines, "\n") + LineNum = 0 + TestCommentLinesList = [] + for Comment in CommentList: + LineNum += 1 + TestCommentLinesList.append((Comment, LineNum)) + + Abstract, Description, Copyright, License = \ + ParseHeaderCommentSection(TestCommentLinesList, "PhonyFile") + + ExpectedAbstract = 'Abstract' + self.assertEqual(Abstract, ExpectedAbstract) + + ExpectedDescription = 'Description' + self.assertEqual(Description, ExpectedDescription) + + ExpectedCopyright = \ + 'Copyright (c) 2007 - 2018, Intel Corporation.'\ + ' All rights reserved.
\n'\ + 'Copyright (c) 2007 - 2010, FOO1 Corporation.'\ + ' All rights reserved.
\n'\ + 'Copyright (c) 2007 - 2010, FOO2 Corporation.'\ + ' All rights reserved.
' + self.assertEqual(Copyright, ExpectedCopyright) + + ExpectedLicense = \ + 'License' + self.assertEqual(License, ExpectedLicense) + + # + # Normal case7: Abstract not present + # + def testNormalCase7(self): + TestCommentLines = \ + ''' + ## @file + # + # Description + # + # Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ # Copyright (c) 2007 - 2010, FOO1 Corporation. All rights reserved.
+ # Copyright (c) 2007 - 2010, FOO2 Corporation. All rights reserved.
+ # + # License + # + ##''' + + CommentList = GetSplitValueList(TestCommentLines, "\n") + LineNum = 0 + TestCommentLinesList = [] + for Comment in CommentList: + LineNum += 1 + TestCommentLinesList.append((Comment, LineNum)) + + Abstract, Description, Copyright, License = \ + ParseHeaderCommentSection(TestCommentLinesList, "PhonyFile") + + ExpectedAbstract = '' + self.assertEqual(Abstract, ExpectedAbstract) + + ExpectedDescription = 'Description' + self.assertEqual(Description, ExpectedDescription) + + ExpectedCopyright = \ + 'Copyright (c) 2007 - 2018, Intel Corporation.'\ + ' All rights reserved.
\n'\ + 'Copyright (c) 2007 - 2010, FOO1 Corporation.'\ + ' All rights reserved.
\n'\ + 'Copyright (c) 2007 - 2010, FOO2 Corporation.'\ + ' All rights reserved.
' + self.assertEqual(Copyright, ExpectedCopyright) + + ExpectedLicense = \ + 'License' + self.assertEqual(License, ExpectedLicense) + + # + # Normal case8: Description not present + # + def testNormalCase8(self): + TestCommentLines = \ + ''' + ## @file + # Abstact + # + # Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ # + # License + # + ##''' + + CommentList = GetSplitValueList(TestCommentLines, "\n") + LineNum = 0 + TestCommentLinesList = [] + for Comment in CommentList: + LineNum += 1 + TestCommentLinesList.append((Comment, LineNum)) + + Abstract, Description, Copyright, License = \ + ParseHeaderCommentSection(TestCommentLinesList, "PhonyFile") + + ExpectedAbstract = 'Abstact' + self.assertEqual(Abstract, ExpectedAbstract) + + ExpectedDescription = '' + self.assertEqual(Description, ExpectedDescription) + + ExpectedCopyright = \ + 'Copyright (c) 2007 - 2018, Intel Corporation.'\ + ' All rights reserved.
' + self.assertEqual(Copyright, ExpectedCopyright) + + ExpectedLicense = \ + 'License' + self.assertEqual(License, ExpectedLicense) + + # + # Error case1: No copyright found + # + def testErrorCase1(self): + TestCommentLines = \ + ''' + ## @file + # Abstract + # + # Description + # + # License + # + ##''' + + CommentList = GetSplitValueList(TestCommentLines, "\n") + LineNum = 0 + TestCommentLinesList = [] + for Comment in CommentList: + LineNum += 1 + TestCommentLinesList.append((Comment, LineNum)) + + self.assertRaises(Logger.FatalError, + ParseHeaderCommentSection, + TestCommentLinesList, + "PhonyFile") + + # + # Error case2: non-empty non-comment lines passed in + # + def testErrorCase2(self): + TestCommentLines = \ + ''' + ## @file + # Abstract + # + this is invalid line + # Description + # + # Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ # License + # + ##''' + + CommentList = GetSplitValueList(TestCommentLines, "\n") + LineNum = 0 + TestCommentLinesList = [] + for Comment in CommentList: + LineNum += 1 + TestCommentLinesList.append((Comment, LineNum)) + + self.assertRaises(Logger.FatalError, + ParseHeaderCommentSection, + TestCommentLinesList, + "PhonyFile") + +# +# Test ParseGenericComment +# +class ParseGenericCommentTest(unittest.TestCase): + def setUp(self): + pass + + def tearDown(self): + pass + + # + # Normal case1: one line of comment + # + def testNormalCase1(self): + TestCommentLines = \ + '''# hello world''' + + CommentList = GetSplitValueList(TestCommentLines, "\n") + LineNum = 0 + TestCommentLinesList = [] + for Comment in CommentList: + LineNum += 1 + TestCommentLinesList.append((Comment, LineNum)) + + HelptxtObj = ParseGenericComment(TestCommentLinesList, 'testNormalCase1') + self.failIf(not HelptxtObj) + self.assertEqual(HelptxtObj.GetString(), 'hello world') + self.assertEqual(HelptxtObj.GetLang(), TAB_LANGUAGE_EN_US) + + # + # Normal case2: multiple lines of comment + # + def testNormalCase2(self): + TestCommentLines = \ + '''## hello world + # second line''' + + CommentList = GetSplitValueList(TestCommentLines, "\n") + LineNum = 0 + TestCommentLinesList = [] + for Comment in CommentList: + LineNum += 1 + TestCommentLinesList.append((Comment, LineNum)) + + HelptxtObj = ParseGenericComment(TestCommentLinesList, 'testNormalCase2') + self.failIf(not HelptxtObj) + self.assertEqual(HelptxtObj.GetString(), + 'hello world\n' + 'second line') + self.assertEqual(HelptxtObj.GetLang(), TAB_LANGUAGE_EN_US) + + # + # Normal case3: multiple lines of comment, non comment lines will be skipped + # + def testNormalCase3(self): + TestCommentLines = \ + '''## hello world + This is not comment line''' + + CommentList = GetSplitValueList(TestCommentLines, "\n") + LineNum = 0 + TestCommentLinesList = [] + for Comment in CommentList: + LineNum += 1 + TestCommentLinesList.append((Comment, LineNum)) + + HelptxtObj = ParseGenericComment(TestCommentLinesList, 'testNormalCase3') + self.failIf(not HelptxtObj) + self.assertEqual(HelptxtObj.GetString(), + 'hello world\n\n') + self.assertEqual(HelptxtObj.GetLang(), TAB_LANGUAGE_EN_US) + +# +# Test ParseDecPcdGenericComment +# +class ParseDecPcdGenericCommentTest(unittest.TestCase): + def setUp(self): + pass + + def tearDown(self): + pass + + # + # Normal case1: comments with no special comment + # + def testNormalCase1(self): + TestCommentLines = \ + '''## hello world + # second line''' + + CommentList = GetSplitValueList(TestCommentLines, "\n") + LineNum = 0 + TestCommentLinesList = [] + for Comment in CommentList: + LineNum += 1 + TestCommentLinesList.append((Comment, LineNum)) + + (HelpTxt, PcdErr) = \ + ParseDecPcdGenericComment(TestCommentLinesList, 'testNormalCase1') + self.failIf(not HelpTxt) + self.failIf(PcdErr) + self.assertEqual(HelpTxt, + 'hello world\n' + 'second line') + + + # + # Normal case2: comments with valid list + # + def testNormalCase2(self): + TestCommentLines = \ + '''## hello world + # second line + # @ValidList 1, 2, 3 + # other line''' + + CommentList = GetSplitValueList(TestCommentLines, "\n") + LineNum = 0 + TestCommentLinesList = [] + for Comment in CommentList: + LineNum += 1 + TestCommentLinesList.append((Comment, LineNum)) + + (HelpTxt, PcdErr) = \ + ParseDecPcdGenericComment(TestCommentLinesList, 'UnitTest') + self.failIf(not HelpTxt) + self.failIf(not PcdErr) + self.assertEqual(HelpTxt, + 'hello world\n' + 'second line\n' + 'other line') + ExpectedList = GetSplitValueList('1 2 3', TAB_SPACE_SPLIT) + ActualList = [item for item in \ + GetSplitValueList(PcdErr.GetValidValue(), TAB_SPACE_SPLIT) if item] + self.assertEqual(ExpectedList, ActualList) + self.failIf(PcdErr.GetExpression()) + self.failIf(PcdErr.GetValidValueRange()) + + # + # Normal case3: comments with valid range + # + def testNormalCase3(self): + TestCommentLines = \ + '''## hello world + # second line + # @ValidRange LT 1 AND GT 2 + # other line''' + + CommentList = GetSplitValueList(TestCommentLines, "\n") + LineNum = 0 + TestCommentLinesList = [] + for Comment in CommentList: + LineNum += 1 + TestCommentLinesList.append((Comment, LineNum)) + + (HelpTxt, PcdErr) = \ + ParseDecPcdGenericComment(TestCommentLinesList, 'UnitTest') + self.failIf(not HelpTxt) + self.failIf(not PcdErr) + self.assertEqual(HelpTxt, + 'hello world\n' + 'second line\n' + 'other line') + self.assertEqual(PcdErr.GetValidValueRange().strip(), 'LT 1 AND GT 2') + self.failIf(PcdErr.GetExpression()) + self.failIf(PcdErr.GetValidValue()) + + # + # Normal case4: comments with valid expression + # + def testNormalCase4(self): + TestCommentLines = \ + '''## hello world + # second line + # @Expression LT 1 AND GT 2 + # other line''' + + CommentList = GetSplitValueList(TestCommentLines, "\n") + LineNum = 0 + TestCommentLinesList = [] + for Comment in CommentList: + LineNum += 1 + TestCommentLinesList.append((Comment, LineNum)) + + (HelpTxt, PcdErr) = \ + ParseDecPcdGenericComment(TestCommentLinesList, 'UnitTest') + self.failIf(not HelpTxt) + self.failIf(not PcdErr) + self.assertEqual(HelpTxt, + 'hello world\n' + 'second line\n' + 'other line') + self.assertEqual(PcdErr.GetExpression().strip(), 'LT 1 AND GT 2') + self.failIf(PcdErr.GetValidValueRange()) + self.failIf(PcdErr.GetValidValue()) + + # + # Normal case5: comments with valid expression and no generic comment + # + def testNormalCase5(self): + TestCommentLines = \ + '''# @Expression LT 1 AND GT 2''' + + CommentList = GetSplitValueList(TestCommentLines, "\n") + LineNum = 0 + TestCommentLinesList = [] + for Comment in CommentList: + LineNum += 1 + TestCommentLinesList.append((Comment, LineNum)) + + (HelpTxt, PcdErr) = \ + ParseDecPcdGenericComment(TestCommentLinesList, 'UnitTest') + self.failIf(HelpTxt) + self.failIf(not PcdErr) + self.assertEqual(PcdErr.GetExpression().strip(), 'LT 1 AND GT 2') + self.failIf(PcdErr.GetValidValueRange()) + self.failIf(PcdErr.GetValidValue()) + + # + # Normal case6: comments with only generic help text + # + def testNormalCase6(self): + TestCommentLines = \ + '''#''' + + CommentList = GetSplitValueList(TestCommentLines, "\n") + LineNum = 0 + TestCommentLinesList = [] + for Comment in CommentList: + LineNum += 1 + TestCommentLinesList.append((Comment, LineNum)) + + (HelpTxt, PcdErr) = \ + ParseDecPcdGenericComment(TestCommentLinesList, 'UnitTest') + self.assertEqual(HelpTxt, '\n') + self.failIf(PcdErr) + + + + # + # Error case1: comments with both expression and valid list, use later + # ignore the former and with a warning message + # + def testErrorCase1(self): + TestCommentLines = \ + '''## hello world + # second line + # @ValidList 1, 2, 3 + # @Expression LT 1 AND GT 2 + # other line''' + + CommentList = GetSplitValueList(TestCommentLines, "\n") + LineNum = 0 + TestCommentLinesList = [] + for Comment in CommentList: + LineNum += 1 + TestCommentLinesList.append((Comment, LineNum)) + + try: + ParseDecPcdGenericComment(TestCommentLinesList, 'UnitTest') + except Logger.FatalError: + pass + +# +# Test ParseDecPcdTailComment +# +class ParseDecPcdTailCommentTest(unittest.TestCase): + def setUp(self): + pass + + def tearDown(self): + pass + + # + # Normal case1: comments with no SupModeList + # + def testNormalCase1(self): + TestCommentLines = \ + '''## #hello world''' + + CommentList = GetSplitValueList(TestCommentLines, "\n") + LineNum = 0 + TestCommentLinesList = [] + for Comment in CommentList: + LineNum += 1 + TestCommentLinesList.append((Comment, LineNum)) + + (SupModeList, HelpStr) = \ + ParseDecPcdTailComment(TestCommentLinesList, 'UnitTest') + self.failIf(not HelpStr) + self.failIf(SupModeList) + self.assertEqual(HelpStr, + 'hello world') + + # + # Normal case2: comments with one SupMode + # + def testNormalCase2(self): + TestCommentLines = \ + '''## BASE #hello world''' + + CommentList = GetSplitValueList(TestCommentLines, "\n") + LineNum = 0 + TestCommentLinesList = [] + for Comment in CommentList: + LineNum += 1 + TestCommentLinesList.append((Comment, LineNum)) + + (SupModeList, HelpStr) = \ + ParseDecPcdTailComment(TestCommentLinesList, 'UnitTest') + self.failIf(not HelpStr) + self.failIf(not SupModeList) + self.assertEqual(HelpStr, + 'hello world') + self.assertEqual(SupModeList, + ['BASE']) + + # + # Normal case3: comments with more than one SupMode + # + def testNormalCase3(self): + TestCommentLines = \ + '''## BASE UEFI_APPLICATION #hello world''' + + CommentList = GetSplitValueList(TestCommentLines, "\n") + LineNum = 0 + TestCommentLinesList = [] + for Comment in CommentList: + LineNum += 1 + TestCommentLinesList.append((Comment, LineNum)) + + (SupModeList, HelpStr) = \ + ParseDecPcdTailComment(TestCommentLinesList, 'UnitTest') + self.failIf(not HelpStr) + self.failIf(not SupModeList) + self.assertEqual(HelpStr, + 'hello world') + self.assertEqual(SupModeList, + ['BASE', 'UEFI_APPLICATION']) + + # + # Normal case4: comments with more than one SupMode, no help text + # + def testNormalCase4(self): + TestCommentLines = \ + '''## BASE UEFI_APPLICATION''' + + CommentList = GetSplitValueList(TestCommentLines, "\n") + LineNum = 0 + TestCommentLinesList = [] + for Comment in CommentList: + LineNum += 1 + TestCommentLinesList.append((Comment, LineNum)) + + (SupModeList, HelpStr) = \ + ParseDecPcdTailComment(TestCommentLinesList, 'UnitTest') + self.failIf(HelpStr) + self.failIf(not SupModeList) + self.assertEqual(SupModeList, + ['BASE', 'UEFI_APPLICATION']) + + # + # Normal case5: general comments with no supModList, extract from real case + # + def testNormalCase5(self): + TestCommentLines = \ + ''' # 1 = 128MB, 2 = 256MB, 3 = MAX''' + + CommentList = GetSplitValueList(TestCommentLines, "\n") + LineNum = 0 + TestCommentLinesList = [] + for Comment in CommentList: + LineNum += 1 + TestCommentLinesList.append((Comment, LineNum)) + + (SupModeList, HelpStr) = \ + ParseDecPcdTailComment(TestCommentLinesList, 'UnitTest') + self.failIf(not HelpStr) + self.assertEqual(HelpStr, + '1 = 128MB, 2 = 256MB, 3 = MAX') + self.failIf(SupModeList) + + + # + # Error case2: comments with supModList contains valid and invalid + # module type + # + def testErrorCase2(self): + TestCommentLines = \ + '''## BASE INVALID_MODULE_TYPE #hello world''' + + CommentList = GetSplitValueList(TestCommentLines, "\n") + LineNum = 0 + TestCommentLinesList = [] + for Comment in CommentList: + LineNum += 1 + TestCommentLinesList.append((Comment, LineNum)) + + try: + ParseDecPcdTailComment(TestCommentLinesList, 'UnitTest') + except Logger.FatalError: + pass + + +# +# Test _IsCopyrightLine +# +class _IsCopyrightLineTest(unittest.TestCase): + def setUp(self): + pass + + def tearDown(self): + pass + + # + # Normal case + # + def testCase1(self): + Line = 'this is a copyright ( line' + Result = _IsCopyrightLine(Line) + self.failIf(not Result) + + # + # Normal case + # + def testCase2(self): + Line = 'this is a Copyright ( line' + Result = _IsCopyrightLine(Line) + self.failIf(not Result) + + # + # Normal case + # + def testCase3(self): + Line = 'this is not aCopyright ( line' + Result = _IsCopyrightLine(Line) + self.failIf(Result) + + # + # Normal case + # + def testCase4(self): + Line = 'this is Copyright( line' + Result = _IsCopyrightLine(Line) + self.failIf(not Result) + + # + # Normal case + # + def testCase5(self): + Line = 'this is Copyright (line' + Result = _IsCopyrightLine(Line) + self.failIf(not Result) + + # + # Normal case + # + def testCase6(self): + Line = 'this is not Copyright line' + Result = _IsCopyrightLine(Line) + self.failIf(Result) + + # + # Normal case + # + def testCase7(self): + Line = 'Copyright (c) line' + Result = _IsCopyrightLine(Line) + self.failIf(not Result) + + # + # Normal case + # + def testCase8(self): + Line = ' Copyright (c) line' + Result = _IsCopyrightLine(Line) + self.failIf(not Result) + + # + # Normal case + # + def testCase9(self): + Line = 'not a Copyright ' + Result = _IsCopyrightLine(Line) + self.failIf(Result) + +if __name__ == '__main__': + Logger.Initialize() + unittest.main() diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/DecParserTest.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/DecParserTest.py new file mode 100755 index 00000000..3c64c8ef --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/DecParserTest.py @@ -0,0 +1,279 @@ +## @file +# This file contain unit test for DecParser +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +from __future__ import print_function +import os +import unittest + +from Parser.DecParserMisc import \ + IsValidCArray, \ + IsValidPcdDatum + +from Parser.DecParser import Dec + +from Library.ParserValidate import IsValidCFormatGuid + +# +# Test tool function +# +def TestToolFuncs(): + assert IsValidCArray('{0x1, 0x23}') + + # Empty after comma + assert not IsValidCArray('{0x1, 0x23, }') + + # 0x2345 too long + assert not IsValidCArray('{0x1, 0x2345}') + + # Must end with '}' + assert not IsValidCArray('{0x1, 0x23, ') + + # Whitespace between numbers + assert not IsValidCArray('{0x1, 0x2 3, }') + + assert IsValidPcdDatum('VOID*', '"test"')[0] + assert IsValidPcdDatum('VOID*', 'L"test"')[0] + assert IsValidPcdDatum('BOOLEAN', 'TRUE')[0] + assert IsValidPcdDatum('BOOLEAN', 'FALSE')[0] + assert IsValidPcdDatum('BOOLEAN', '0')[0] + assert IsValidPcdDatum('BOOLEAN', '1')[0] + assert IsValidPcdDatum('UINT8', '0xab')[0] + + assert not IsValidPcdDatum('UNKNOWNTYPE', '0xabc')[0] + assert not IsValidPcdDatum('UINT8', 'not number')[0] + + assert( IsValidCFormatGuid('{ 0xfa0b1735 , 0x87a0, 0x4193, {0xb2, 0x66 , 0x53, 0x8c , 0x38, 0xaf, 0x48, 0xce }}')) + assert( not IsValidCFormatGuid('{ 0xfa0b1735 , 0x87a0, 0x4193, {0xb2, 0x66 , 0x53, 0x8c , 0x38, 0xaf, 0x48, 0xce }} 0xaa')) + +def TestTemplate(TestString, TestFunc): + Path = os.path.join(os.getcwd(), 'test.dec') + Path = os.path.normpath(Path) + try: + f = open(Path, 'w') + + # Write test string to file + f.write(TestString) + + # Close file + f.close() + except: + print('Can not create temporary file [%s]!' % Path) + exit(-1) + + # Call test function to test + Ret = TestFunc(Path, TestString) + + # Test done, remove temporary file + os.remove(Path) + return Ret + +# To make test unit works OK, must set IsRaiseError to True +# This function test right syntax DEC file +# @retval: parser object +# +def TestOK(Path, TestString): + try: + Parser = Dec(Path) + except: + raise 'Bug!!! Correct syntax in DEC file, but exception raised!\n' + TestString + return Parser + +# This function test wrong syntax DEC file +# if parser checked wrong syntax, exception thrown and it's expected result +def TestError(Path, TestString): + try: + Dec(Path) + except: + # Raise error, get expected result + return True + raise 'Bug!!! Wrong syntax in DEC file, but passed by DEC parser!!\n' + TestString + +def TestDecDefine(): + TestString = ''' + [Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = MdePkg + PACKAGE_GUID = 1E73767F-8F52-4603-AEB4-F29B510B6766 + PACKAGE_VERSION = 1.02 + ''' + Parser = TestTemplate(TestString, TestOK) + DefObj = Parser.GetDefineSectionObject() + assert DefObj.GetPackageSpecification() == '0x00010005' + assert DefObj.GetPackageName() == 'MdePkg' + assert DefObj.GetPackageGuid() == '1E73767F-8F52-4603-AEB4-F29B510B6766' + assert DefObj.GetPackageVersion() == '1.02' + + TestString = ''' + [Defines] + UNKNOW_KEY = 0x00010005 # A unknown key + ''' + assert TestTemplate(TestString, TestError) + + TestString = ''' + [Defines] + PACKAGE_GUID = F-8F52-4603-AEB4-F29B510B6766 # Error GUID + ''' + assert TestTemplate(TestString, TestError) + +def TestDecInclude(): + TestString = ''' + [Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = MdePkg + PACKAGE_GUID = 1E73767F-8F52-4603-AEB4-F29B510B6766 + PACKAGE_VERSION = 1.02 + [ \\ + Includes] + Include + [Includes.IA32] + Include/Ia32 + ''' + + # Create directory in current directory + try: + os.makedirs('Include/Ia32') + except: + pass + Parser = TestTemplate(TestString, TestOK) + + IncObj = Parser.GetIncludeSectionObject() + Items = IncObj.GetIncludes() + assert len(Items) == 1 + assert Items[0].File == 'Include' + + Items = IncObj.GetIncludes('IA32') + assert len(Items) == 1 + # normpath is called in DEC parser so '/' is converted to '\' + assert Items[0].File == 'Include\\Ia32' + + TestString = ''' + [Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = MdePkg + PACKAGE_GUID = 1E73767F-8F52-4603-AEB4-F29B510B6766 + PACKAGE_VERSION = 1.02 + [Includes] + Include_not_exist # directory does not exist + ''' + assert TestTemplate(TestString, TestError) + + os.removedirs('Include/Ia32') + +def TestDecGuidPpiProtocol(): + TestString = ''' + [Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = MdePkg + PACKAGE_GUID = 1E73767F-8F52-4603-AEB4-F29B510B6766 + PACKAGE_VERSION = 1.02 + [Guids] + # + # GUID defined in UEFI2.1/UEFI2.0/EFI1.1 + # + ## Include/Guid/GlobalVariable.h + gEfiGlobalVariableGuid = { 0x8BE4DF61, 0x93CA, 0x11D2, { 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C }} + [Protocols] + ## Include/Protocol/Bds.h + gEfiBdsArchProtocolGuid = { 0x665E3FF6, 0x46CC, 0x11D4, { 0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }} + [Ppis] + ## Include/Ppi/MasterBootMode.h + gEfiPeiMasterBootModePpiGuid = { 0x7408d748, 0xfc8c, 0x4ee6, {0x92, 0x88, 0xc4, 0xbe, 0xc0, 0x92, 0xa4, 0x10 } } + ''' + Parser = TestTemplate(TestString, TestOK) + Obj = Parser.GetGuidSectionObject() + Items = Obj.GetGuids() + assert Obj.GetSectionName() == 'Guids'.upper() + assert len(Items) == 1 + assert Items[0].GuidCName == 'gEfiGlobalVariableGuid' + assert Items[0].GuidCValue == '{ 0x8BE4DF61, 0x93CA, 0x11D2, { 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C }}' + + Obj = Parser.GetProtocolSectionObject() + Items = Obj.GetProtocols() + assert Obj.GetSectionName() == 'Protocols'.upper() + assert len(Items) == 1 + assert Items[0].GuidCName == 'gEfiBdsArchProtocolGuid' + assert Items[0].GuidCValue == '{ 0x665E3FF6, 0x46CC, 0x11D4, { 0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }}' + + Obj = Parser.GetPpiSectionObject() + Items = Obj.GetPpis() + assert Obj.GetSectionName() == 'Ppis'.upper() + assert len(Items) == 1 + assert Items[0].GuidCName == 'gEfiPeiMasterBootModePpiGuid' + assert Items[0].GuidCValue == '{ 0x7408d748, 0xfc8c, 0x4ee6, {0x92, 0x88, 0xc4, 0xbe, 0xc0, 0x92, 0xa4, 0x10 } }' + +def TestDecPcd(): + TestString = ''' + [Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = MdePkg + PACKAGE_GUID = 1E73767F-8F52-4603-AEB4-F29B510B6766 + PACKAGE_VERSION = 1.02 + [PcdsFeatureFlag] + ## If TRUE, the component name protocol will not be installed. + gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable|FALSE|BOOLEAN|0x0000000d + + [PcdsFixedAtBuild] + ## Indicates the maximum length of unicode string + gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength|1000000|UINT32|0x00000001 + + [PcdsFixedAtBuild.IPF] + ## The base address of IO port space for IA64 arch + gEfiMdePkgTokenSpaceGuid.PcdIoBlockBaseAddressForIpf|0x0ffffc000000|UINT64|0x0000000f + + [PcdsFixedAtBuild,PcdsPatchableInModule] + ## This flag is used to control the printout of DebugLib + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000000|UINT32|0x00000006 + + [PcdsFixedAtBuild,PcdsPatchableInModule,PcdsDynamic] + ## This value is used to set the base address of pci express hierarchy + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0xE0000000|UINT64|0x0000000a + ''' + Parser = TestTemplate(TestString, TestOK) + Obj = Parser.GetPcdSectionObject() + Items = Obj.GetPcds('PcdsFeatureFlag', 'COMMON') + assert len(Items) == 1 + assert Items[0].TokenSpaceGuidCName == 'gEfiMdePkgTokenSpaceGuid' + assert Items[0].TokenCName == 'PcdComponentNameDisable' + assert Items[0].DefaultValue == 'FALSE' + assert Items[0].DatumType == 'BOOLEAN' + assert Items[0].TokenValue == '0x0000000d' + + Items = Obj.GetPcdsByType('PcdsFixedAtBuild') + assert len(Items) == 4 + assert len(Obj.GetPcdsByType('PcdsPatchableInModule')) == 2 + +def TestDecUserExtension(): + TestString = ''' + [Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = MdePkg + PACKAGE_GUID = 1E73767F-8F52-4603-AEB4-F29B510B6766 + PACKAGE_VERSION = 1.02 + [UserExtensions.MyID."TestString".IA32] + Some Strings... + ''' + Parser = TestTemplate(TestString, TestOK) + Obj = Parser.GetUserExtensionSectionObject() + Items = Obj.GetAllUserExtensions() + assert len(Items) == 1 + assert Items[0].UserString == 'Some Strings...' + assert len(Items[0].ArchAndModuleType) == 1 + assert ['MyID', '"TestString"', 'IA32'] in Items[0].ArchAndModuleType + +if __name__ == '__main__': + import Logger.Logger + Logger.Logger.Initialize() + unittest.FunctionTestCase(TestToolFuncs).runTest() + unittest.FunctionTestCase(TestDecDefine).runTest() + unittest.FunctionTestCase(TestDecInclude).runTest() + unittest.FunctionTestCase(TestDecGuidPpiProtocol).runTest() + unittest.FunctionTestCase(TestDecPcd).runTest() + unittest.FunctionTestCase(TestDecUserExtension).runTest() + + print('All tests passed...') + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/DecParserUnitTest.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/DecParserUnitTest.py new file mode 100755 index 00000000..4addd325 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/DecParserUnitTest.py @@ -0,0 +1,528 @@ +## @file +# This file contain unit test for DecParser +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +import os +import unittest +from Logger.Log import FatalError + +from Parser.DecParser import \ + Dec, \ + _DecDefine, \ + _DecLibraryclass, \ + _DecPcd, \ + _DecGuid, \ + FileContent, \ + _DecBase, \ + CleanString + +from Object.Parser.DecObject import _DecComments + +# +# Test CleanString +# +class CleanStringTestCase(unittest.TestCase): + def testCleanString(self): + Line, Comment = CleanString('') + self.assertEqual(Line, '') + self.assertEqual(Comment, '') + + Line, Comment = CleanString('line without comment') + self.assertEqual(Line, 'line without comment') + self.assertEqual(Comment, '') + + Line, Comment = CleanString('# pure comment') + self.assertEqual(Line, '') + self.assertEqual(Comment, '# pure comment') + + Line, Comment = CleanString('line # and comment') + self.assertEqual(Line, 'line') + self.assertEqual(Comment, '# and comment') + + def testCleanStringCpp(self): + Line, Comment = CleanString('line // and comment', AllowCppStyleComment = True) + self.assertEqual(Line, 'line') + self.assertEqual(Comment, '# and comment') + +# +# Test _DecBase._MacroParser function +# +class MacroParserTestCase(unittest.TestCase): + def setUp(self): + self.dec = _DecBase(FileContent('dummy', [])) + + def testCorrectMacro(self): + self.dec._MacroParser('DEFINE MACRO1 = test1') + self.failIf('MACRO1' not in self.dec._LocalMacro) + self.assertEqual(self.dec._LocalMacro['MACRO1'], 'test1') + + def testErrorMacro1(self): + # Raise fatal error, macro name must be upper case letter + self.assertRaises(FatalError, self.dec._MacroParser, 'DEFINE not_upper_case = test2') + + def testErrorMacro2(self): + # No macro name given + self.assertRaises(FatalError, self.dec._MacroParser, 'DEFINE ') + +# +# Test _DecBase._TryBackSlash function +# +class TryBackSlashTestCase(unittest.TestCase): + def setUp(self): + Content = [ + # Right case + 'test no backslash', + + 'test with backslash \\', + 'continue second line', + + # Do not precede with whitespace + '\\', + + # Empty line after backlash is not allowed + 'line with backslash \\', + '' + ] + self.dec = _DecBase(FileContent('dummy', Content)) + + def testBackSlash(self): + # + # Right case, assert return values + # + ConcatLine, CommentList = self.dec._TryBackSlash(self.dec._RawData.GetNextLine(), []) + self.assertEqual(ConcatLine, 'test no backslash') + self.assertEqual(CommentList, []) + + ConcatLine, CommentList = self.dec._TryBackSlash(self.dec._RawData.GetNextLine(), []) + self.assertEqual(CommentList, []) + self.assertEqual(ConcatLine, 'test with backslash continue second line') + + # + # Error cases, assert raise exception + # + self.assertRaises(FatalError, self.dec._TryBackSlash, self.dec._RawData.GetNextLine(), []) + self.assertRaises(FatalError, self.dec._TryBackSlash, self.dec._RawData.GetNextLine(), []) + +# +# Test _DecBase.Parse function +# +class DataItem(_DecComments): + def __init__(self): + _DecComments.__init__(self) + self.String = '' + +class Data(_DecComments): + def __init__(self): + _DecComments.__init__(self) + # List of DataItem + self.ItemList = [] + +class TestInner(_DecBase): + def __init__(self, RawData): + _DecBase.__init__(self, RawData) + self.ItemObject = Data() + + def _StopCurrentParsing(self, Line): + return Line == '[TOP]' + + def _ParseItem(self): + Item = DataItem() + Item.String = self._RawData.CurrentLine + self.ItemObject.ItemList.append(Item) + return Item + + def _TailCommentStrategy(self, Comment): + return Comment.find('@comment') != -1 + +class TestTop(_DecBase): + def __init__(self, RawData): + _DecBase.__init__(self, RawData) + # List of Data + self.ItemObject = [] + + # Top parser + def _StopCurrentParsing(self, Line): + return False + + def _ParseItem(self): + TestParser = TestInner(self._RawData) + TestParser.Parse() + self.ItemObject.append(TestParser.ItemObject) + return TestParser.ItemObject + +class ParseTestCase(unittest.TestCase): + def setUp(self): + pass + + def testParse(self): + Content = \ + '''# Top comment + [TOP] + # sub1 head comment + (test item has both head and tail comment) # sub1 tail comment + # sub2 head comment + (test item has head and special tail comment) + # @comment test TailCommentStrategy branch + + (test item has no comment) + + # test NextLine branch + [TOP] + sub-item + ''' + dec = TestTop(FileContent('dummy', Content.splitlines())) + dec.Parse() + + # Two sections + self.assertEqual(len(dec.ItemObject), 2) + + data = dec.ItemObject[0] + self.assertEqual(data._HeadComment[0][0], '# Top comment') + self.assertEqual(data._HeadComment[0][1], 1) + + # 3 subitems + self.assertEqual(len(data.ItemList), 3) + + dataitem = data.ItemList[0] + self.assertEqual(dataitem.String, '(test item has both head and tail comment)') + # Comment content + self.assertEqual(dataitem._HeadComment[0][0], '# sub1 head comment') + self.assertEqual(dataitem._TailComment[0][0], '# sub1 tail comment') + # Comment line number + self.assertEqual(dataitem._HeadComment[0][1], 3) + self.assertEqual(dataitem._TailComment[0][1], 4) + + dataitem = data.ItemList[1] + self.assertEqual(dataitem.String, '(test item has head and special tail comment)') + # Comment content + self.assertEqual(dataitem._HeadComment[0][0], '# sub2 head comment') + self.assertEqual(dataitem._TailComment[0][0], '# @comment test TailCommentStrategy branch') + # Comment line number + self.assertEqual(dataitem._HeadComment[0][1], 5) + self.assertEqual(dataitem._TailComment[0][1], 7) + + dataitem = data.ItemList[2] + self.assertEqual(dataitem.String, '(test item has no comment)') + # Comment content + self.assertEqual(dataitem._HeadComment, []) + self.assertEqual(dataitem._TailComment, []) + + data = dec.ItemObject[1] + self.assertEqual(data._HeadComment[0][0], '# test NextLine branch') + self.assertEqual(data._HeadComment[0][1], 11) + + # 1 subitems + self.assertEqual(len(data.ItemList), 1) + + dataitem = data.ItemList[0] + self.assertEqual(dataitem.String, 'sub-item') + self.assertEqual(dataitem._HeadComment, []) + self.assertEqual(dataitem._TailComment, []) + +# +# Test _DecDefine._ParseItem +# +class DecDefineTestCase(unittest.TestCase): + def GetObj(self, Content): + Obj = _DecDefine(FileContent('dummy', Content.splitlines())) + Obj._RawData.CurrentLine = Obj._RawData.GetNextLine() + return Obj + + def testDecDefine(self): + item = self.GetObj('PACKAGE_NAME = MdePkg')._ParseItem() + self.assertEqual(item.Key, 'PACKAGE_NAME') + self.assertEqual(item.Value, 'MdePkg') + + def testDecDefine1(self): + obj = self.GetObj('PACKAGE_NAME') + self.assertRaises(FatalError, obj._ParseItem) + + def testDecDefine2(self): + obj = self.GetObj('unknown_key = ') + self.assertRaises(FatalError, obj._ParseItem) + + def testDecDefine3(self): + obj = self.GetObj('PACKAGE_NAME = ') + self.assertRaises(FatalError, obj._ParseItem) + +# +# Test _DecLibraryclass._ParseItem +# +class DecLibraryTestCase(unittest.TestCase): + def GetObj(self, Content): + Obj = _DecLibraryclass(FileContent('dummy', Content.splitlines())) + Obj._RawData.CurrentLine = Obj._RawData.GetNextLine() + return Obj + + def testNoInc(self): + obj = self.GetObj('UefiRuntimeLib') + self.assertRaises(FatalError, obj._ParseItem) + + def testEmpty(self): + obj = self.GetObj(' | ') + self.assertRaises(FatalError, obj._ParseItem) + + def testLibclassNaming(self): + obj = self.GetObj('lowercase_efiRuntimeLib|Include/Library/UefiRuntimeLib.h') + self.assertRaises(FatalError, obj._ParseItem) + + def testLibclassExt(self): + obj = self.GetObj('RuntimeLib|Include/Library/UefiRuntimeLib.no_h') + self.assertRaises(FatalError, obj._ParseItem) + + def testLibclassRelative(self): + obj = self.GetObj('RuntimeLib|Include/../UefiRuntimeLib.h') + self.assertRaises(FatalError, obj._ParseItem) + +# +# Test _DecPcd._ParseItem +# +class DecPcdTestCase(unittest.TestCase): + def GetObj(self, Content): + Obj = _DecPcd(FileContent('dummy', Content.splitlines())) + Obj._RawData.CurrentLine = Obj._RawData.GetNextLine() + Obj._RawData.CurrentScope = [('PcdsFeatureFlag'.upper(), 'COMMON')] + return Obj + + def testOK(self): + item = self.GetObj('gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable|FALSE|BOOLEAN|0x0000000d')._ParseItem() + self.assertEqual(item.TokenSpaceGuidCName, 'gEfiMdePkgTokenSpaceGuid') + self.assertEqual(item.TokenCName, 'PcdComponentNameDisable') + self.assertEqual(item.DefaultValue, 'FALSE') + self.assertEqual(item.DatumType, 'BOOLEAN') + self.assertEqual(item.TokenValue, '0x0000000d') + + def testNoCvar(self): + obj = self.GetObj('123ai.PcdComponentNameDisable|FALSE|BOOLEAN|0x0000000d') + self.assertRaises(FatalError, obj._ParseItem) + + def testSplit(self): + obj = self.GetObj('gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable FALSE|BOOLEAN|0x0000000d') + self.assertRaises(FatalError, obj._ParseItem) + + obj = self.GetObj('gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable|FALSE|BOOLEAN|0x0000000d | abc') + self.assertRaises(FatalError, obj._ParseItem) + + def testUnknownType(self): + obj = self.GetObj('gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable|FALSE|unknown|0x0000000d') + self.assertRaises(FatalError, obj._ParseItem) + + def testVoid(self): + obj = self.GetObj('gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable|abc|VOID*|0x0000000d') + self.assertRaises(FatalError, obj._ParseItem) + + def testUINT(self): + obj = self.GetObj('gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable|0xabc|UINT8|0x0000000d') + self.assertRaises(FatalError, obj._ParseItem) + +# +# Test _DecInclude._ParseItem +# +class DecIncludeTestCase(unittest.TestCase): + # + # Test code to be added + # + pass + +# +# Test _DecGuid._ParseItem +# +class DecGuidTestCase(unittest.TestCase): + def GetObj(self, Content): + Obj = _DecGuid(FileContent('dummy', Content.splitlines())) + Obj._RawData.CurrentLine = Obj._RawData.GetNextLine() + Obj._RawData.CurrentScope = [('guids'.upper(), 'COMMON')] + return Obj + + def testCValue(self): + item = self.GetObj('gEfiIpSecProtocolGuid={ 0xdfb386f7, 0xe100, 0x43ad,' + ' {0x9c, 0x9a, 0xed, 0x90, 0xd0, 0x8a, 0x5e, 0x12 }}')._ParseItem() + self.assertEqual(item.GuidCName, 'gEfiIpSecProtocolGuid') + self.assertEqual(item.GuidCValue, '{ 0xdfb386f7, 0xe100, 0x43ad, {0x9c, 0x9a, 0xed, 0x90, 0xd0, 0x8a, 0x5e, 0x12 }}') + + def testGuidString(self): + item = self.GetObj('gEfiIpSecProtocolGuid=1E73767F-8F52-4603-AEB4-F29B510B6766')._ParseItem() + self.assertEqual(item.GuidCName, 'gEfiIpSecProtocolGuid') + self.assertEqual(item.GuidCValue, '1E73767F-8F52-4603-AEB4-F29B510B6766') + + def testNoValue1(self): + obj = self.GetObj('gEfiIpSecProtocolGuid') + self.assertRaises(FatalError, obj._ParseItem) + + def testNoValue2(self): + obj = self.GetObj('gEfiIpSecProtocolGuid=') + self.assertRaises(FatalError, obj._ParseItem) + + def testNoName(self): + obj = self.GetObj('=') + self.assertRaises(FatalError, obj._ParseItem) + +# +# Test Dec.__init__ +# +class DecDecInitTestCase(unittest.TestCase): + def testNoDecFile(self): + self.assertRaises(FatalError, Dec, 'No_Such_File') + +class TmpFile: + def __init__(self, File): + self.File = File + + def Write(self, Content): + try: + FileObj = open(self.File, 'w') + FileObj.write(Content) + FileObj.close() + except: + pass + + def Remove(self): + try: + os.remove(self.File) + except: + pass + +# +# Test Dec._UserExtentionSectionParser +# +class DecUESectionTestCase(unittest.TestCase): + def setUp(self): + self.File = TmpFile('test.dec') + self.File.Write( +'''[userextensions.intel."myid"] +[userextensions.intel."myid".IA32] +[userextensions.intel."myid".IA32,] +[userextensions.intel."myid] +''' + ) + + def tearDown(self): + self.File.Remove() + + def testUserExtentionHeader(self): + dec = Dec('test.dec', False) + + # OK: [userextensions.intel."myid"] + dec._RawData.CurrentLine = CleanString(dec._RawData.GetNextLine())[0] + dec._UserExtentionSectionParser() + self.assertEqual(len(dec._RawData.CurrentScope), 1) + self.assertEqual(dec._RawData.CurrentScope[0][0], 'userextensions'.upper()) + self.assertEqual(dec._RawData.CurrentScope[0][1], 'intel') + self.assertEqual(dec._RawData.CurrentScope[0][2], '"myid"') + self.assertEqual(dec._RawData.CurrentScope[0][3], 'COMMON') + + # OK: [userextensions.intel."myid".IA32] + dec._RawData.CurrentLine = CleanString(dec._RawData.GetNextLine())[0] + dec._UserExtentionSectionParser() + self.assertEqual(len(dec._RawData.CurrentScope), 1) + self.assertEqual(dec._RawData.CurrentScope[0][0], 'userextensions'.upper()) + self.assertEqual(dec._RawData.CurrentScope[0][1], 'intel') + self.assertEqual(dec._RawData.CurrentScope[0][2], '"myid"') + self.assertEqual(dec._RawData.CurrentScope[0][3], 'IA32') + + # Fail: [userextensions.intel."myid".IA32,] + dec._RawData.CurrentLine = CleanString(dec._RawData.GetNextLine())[0] + self.assertRaises(FatalError, dec._UserExtentionSectionParser) + + # Fail: [userextensions.intel."myid] + dec._RawData.CurrentLine = CleanString(dec._RawData.GetNextLine())[0] + self.assertRaises(FatalError, dec._UserExtentionSectionParser) + +# +# Test Dec._SectionHeaderParser +# +class DecSectionTestCase(unittest.TestCase): + def setUp(self): + self.File = TmpFile('test.dec') + self.File.Write( +'''[no section start or end +[,] # empty sub-section +[unknow_section_name] +[Includes.IA32.other] # no third one +[PcdsFeatureFlag, PcdsFixedAtBuild] # feature flag PCD must not be in the same section of other types of PCD +[Includes.IA32, Includes.IA32] +[Includes, Includes.IA32] # common cannot be with other arch +[Includes.IA32, PcdsFeatureFlag] # different section name +''' ) + + def tearDown(self): + self.File.Remove() + + def testSectionHeader(self): + dec = Dec('test.dec', False) + # [no section start or end + dec._RawData.CurrentLine = CleanString(dec._RawData.GetNextLine())[0] + self.assertRaises(FatalError, dec._SectionHeaderParser) + + #[,] # empty sub-section + dec._RawData.CurrentLine = CleanString(dec._RawData.GetNextLine())[0] + self.assertRaises(FatalError, dec._SectionHeaderParser) + + # [unknow_section_name] + dec._RawData.CurrentLine = CleanString(dec._RawData.GetNextLine())[0] + self.assertRaises(FatalError, dec._SectionHeaderParser) + + # [Includes.IA32.other] # no third one + dec._RawData.CurrentLine = CleanString(dec._RawData.GetNextLine())[0] + self.assertRaises(FatalError, dec._SectionHeaderParser) + + # [PcdsFeatureFlag, PcdsFixedAtBuild] + dec._RawData.CurrentLine = CleanString(dec._RawData.GetNextLine())[0] + self.assertRaises(FatalError, dec._SectionHeaderParser) + + # [Includes.IA32, Includes.IA32] + dec._RawData.CurrentLine = CleanString(dec._RawData.GetNextLine())[0] + dec._SectionHeaderParser() + self.assertEqual(len(dec._RawData.CurrentScope), 1) + self.assertEqual(dec._RawData.CurrentScope[0][0], 'Includes'.upper()) + self.assertEqual(dec._RawData.CurrentScope[0][1], 'IA32') + + # [Includes, Includes.IA32] # common cannot be with other arch + dec._RawData.CurrentLine = CleanString(dec._RawData.GetNextLine())[0] + self.assertRaises(FatalError, dec._SectionHeaderParser) + + # [Includes.IA32, PcdsFeatureFlag] # different section name not allowed + dec._RawData.CurrentLine = CleanString(dec._RawData.GetNextLine())[0] + self.assertRaises(FatalError, dec._SectionHeaderParser) + +# +# Test Dec._ParseDecComment +# +class DecDecCommentTestCase(unittest.TestCase): + def testDecHeadComment(self): + File = TmpFile('test.dec') + File.Write( + '''# abc + ##''') + dec = Dec('test.dec', False) + dec.ParseDecComment() + self.assertEqual(len(dec._HeadComment), 2) + self.assertEqual(dec._HeadComment[0][0], '# abc') + self.assertEqual(dec._HeadComment[0][1], 1) + self.assertEqual(dec._HeadComment[1][0], '##') + self.assertEqual(dec._HeadComment[1][1], 2) + File.Remove() + + def testNoDoubleComment(self): + File = TmpFile('test.dec') + File.Write( + '''# abc + # + [section_start]''') + dec = Dec('test.dec', False) + dec.ParseDecComment() + self.assertEqual(len(dec._HeadComment), 2) + self.assertEqual(dec._HeadComment[0][0], '# abc') + self.assertEqual(dec._HeadComment[0][1], 1) + self.assertEqual(dec._HeadComment[1][0], '#') + self.assertEqual(dec._HeadComment[1][1], 2) + File.Remove() + +if __name__ == '__main__': + import Logger.Logger + Logger.Logger.Initialize() + unittest.main() + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/InfBinarySectionTest.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/InfBinarySectionTest.py new file mode 100755 index 00000000..7f000648 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/InfBinarySectionTest.py @@ -0,0 +1,381 @@ +## @file +# This file contain unit test for Test [Binary] section part of InfParser +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent + +from __future__ import print_function +import os +#import Object.Parser.InfObject as InfObject +from Object.Parser.InfCommonObject import CurrentLine +from Object.Parser.InfCommonObject import InfLineCommentObject +from Object.Parser.InfBinaryObject import InfBinariesObject +import Logger.Log as Logger +import Library.GlobalData as Global +## +# Test Common binary item +# + +#-------------start of common binary item test input--------------------------# + +# +# Only has 1 element, binary item Type +# +SectionStringsCommonItem1 = \ +""" +GUID +""" +# +# Have 2 elements, binary item Type and FileName +# +SectionStringsCommonItem2 = \ +""" +GUID | Test/Test.guid +""" + +# +# Have 3 elements, Type | FileName | Target | Family | TagName | FeatureFlagExp +# +SectionStringsCommonItem3 = \ +""" +GUID | Test/Test.guid | DEBUG +""" + +# +# Have 3 elements, Type | FileName | Target +# Target with MACRO defined in [Define] section +# +SectionStringsCommonItem4 = \ +""" +GUID | Test/Test.guid | $(TARGET) +""" + +# +# Have 3 elements, Type | FileName | Target +# FileName with MACRO defined in [Binary] section +# +SectionStringsCommonItem5 = \ +""" +DEFINE BINARY_FILE_PATH = Test +GUID | $(BINARY_FILE_PATH)/Test.guid | $(TARGET) +""" + +# +# Have 4 elements, Type | FileName | Target | Family +# +SectionStringsCommonItem6 = \ +""" +GUID | Test/Test.guid | DEBUG | * +""" + +# +# Have 4 elements, Type | FileName | Target | Family +# +SectionStringsCommonItem7 = \ +""" +GUID | Test/Test.guid | DEBUG | MSFT +""" + +# +# Have 5 elements, Type | FileName | Target | Family | TagName +# +SectionStringsCommonItem8 = \ +""" +GUID | Test/Test.guid | DEBUG | MSFT | TEST +""" + +# +# Have 6 elements, Type | FileName | Target | Family | TagName | FFE +# +SectionStringsCommonItem9 = \ +""" +GUID | Test/Test.guid | DEBUG | MSFT | TEST | TRUE +""" + +# +# Have 7 elements, Type | FileName | Target | Family | TagName | FFE | Overflow +# Test wrong format +# +SectionStringsCommonItem10 = \ +""" +GUID | Test/Test.guid | DEBUG | MSFT | TEST | TRUE | OVERFLOW +""" + +#-------------end of common binary item test input----------------------------# + + + +#-------------start of VER type binary item test input------------------------# + +# +# Has 1 element, error format +# +SectionStringsVerItem1 = \ +""" +VER +""" +# +# Have 5 elements, error format(Maximum elements amount is 4) +# +SectionStringsVerItem2 = \ +""" +VER | Test/Test.ver | * | TRUE | OverFlow +""" + +# +# Have 2 elements, Type | FileName +# +SectionStringsVerItem3 = \ +""" +VER | Test/Test.ver +""" + +# +# Have 3 elements, Type | FileName | Target +# +SectionStringsVerItem4 = \ +""" +VER | Test/Test.ver | DEBUG +""" + +# +# Have 4 elements, Type | FileName | Target | FeatureFlagExp +# +SectionStringsVerItem5 = \ +""" +VER | Test/Test.ver | DEBUG | TRUE +""" + +# +# Exist 2 VER items, both opened. +# +SectionStringsVerItem6 = \ +""" +VER | Test/Test.ver | * | TRUE +VER | Test/Test2.ver | * | TRUE +""" + + +# +# Exist 2 VER items, only 1 opened. +# +SectionStringsVerItem7 = \ +""" +VER | Test/Test.ver | * | TRUE +VER | Test/Test2.ver | * | FALSE +""" + +#-------------end of VER type binary item test input--------------------------# + + +#-------------start of UI type binary item test input-------------------------# + +# +# Test only one UI section can exist +# +SectionStringsUiItem1 = \ +""" +UI | Test/Test.ui | * | TRUE +UI | Test/Test2.ui | * | TRUE +""" + +SectionStringsUiItem2 = \ +""" +UI | Test/Test.ui | * | TRUE +SEC_UI | Test/Test2.ui | * | TRUE +""" + +SectionStringsUiItem3 = \ +""" +UI | Test/Test.ui | * | TRUE +UI | Test/Test2.ui | * | FALSE +""" + +# +# Has 1 element, error format +# +SectionStringsUiItem4 = \ +""" +UI +""" +# +# Have 5 elements, error format(Maximum elements amount is 4) +# +SectionStringsUiItem5 = \ +""" +UI | Test/Test.ui | * | TRUE | OverFlow +""" + +# +# Have 2 elements, Type | FileName +# +SectionStringsUiItem6 = \ +""" +UI | Test/Test.ui +""" + +# +# Have 3 elements, Type | FileName | Target +# +SectionStringsUiItem7 = \ +""" +UI | Test/Test.ui | DEBUG +""" + +# +# Have 4 elements, Type | FileName | Target | FeatureFlagExp +# +SectionStringsUiItem8 = \ +""" +UI | Test/Test.ui | DEBUG | TRUE +""" +#---------------end of UI type binary item test input-------------------------# + + +gFileName = "BinarySectionTest.inf" + +## +# Construct SectionString for call section parser usage. +# +def StringToSectionString(String): + Lines = String.split('\n') + LineNo = 0 + SectionString = [] + for Line in Lines: + if Line.strip() == '': + continue + SectionString.append((Line, LineNo, '')) + LineNo = LineNo + 1 + + return SectionString + +def PrepareTest(String): + SectionString = StringToSectionString(String) + ItemList = [] + for Item in SectionString: + ValueList = Item[0].split('|') + for count in range(len(ValueList)): + ValueList[count] = ValueList[count].strip() + if len(ValueList) >= 2: + # + # Create a temp file for test. + # + FileName = os.path.normpath(os.path.realpath(ValueList[1].strip())) + try: + TempFile = open (FileName, "w") + TempFile.close() + except: + print("File Create Error") + CurrentLine = CurrentLine() + CurrentLine.SetFileName("Test") + CurrentLine.SetLineString(Item[0]) + CurrentLine.SetLineNo(Item[1]) + InfLineCommentObject = InfLineCommentObject() + + ItemList.append((ValueList, InfLineCommentObject, CurrentLine)) + + return ItemList + +if __name__ == '__main__': + Logger.Initialize() + + InfBinariesInstance = InfBinariesObject() + ArchList = ['COMMON'] + Global.gINF_MODULE_DIR = os.getcwd() + + AllPassedFlag = True + + # + # For All Ui test + # + UiStringList = [ + SectionStringsUiItem1, + SectionStringsUiItem2, + SectionStringsUiItem3, + SectionStringsUiItem4, + SectionStringsUiItem5, + SectionStringsUiItem6, + SectionStringsUiItem7, + SectionStringsUiItem8 + ] + + for Item in UiStringList: + Ui = PrepareTest(Item) + if Item == SectionStringsUiItem4 or Item == SectionStringsUiItem5: + try: + InfBinariesInstance.SetBinary(Ui = Ui, ArchList = ArchList) + except Logger.FatalError: + pass + else: + try: + InfBinariesInstance.SetBinary(Ui = Ui, ArchList = ArchList) + except: + AllPassedFlag = False + + # + # For All Ver Test + # + VerStringList = [ + SectionStringsVerItem1, + SectionStringsVerItem2, + SectionStringsVerItem3, + SectionStringsVerItem4, + SectionStringsVerItem5, + SectionStringsVerItem6, + SectionStringsVerItem7 + ] + for Item in VerStringList: + Ver = PrepareTest(Item) + if Item == SectionStringsVerItem1 or \ + Item == SectionStringsVerItem2: + + try: + InfBinariesInstance.SetBinary(Ver = Ver, ArchList = ArchList) + except: + pass + + else: + try: + InfBinariesInstance.SetBinary(Ver = Ver, ArchList = ArchList) + except: + AllPassedFlag = False + + # + # For All Common Test + # + CommonStringList = [ + SectionStringsCommonItem1, + SectionStringsCommonItem2, + SectionStringsCommonItem3, + SectionStringsCommonItem4, + SectionStringsCommonItem5, + SectionStringsCommonItem6, + SectionStringsCommonItem7, + SectionStringsCommonItem8, + SectionStringsCommonItem9, + SectionStringsCommonItem10 + ] + + for Item in CommonStringList: + CommonBin = PrepareTest(Item) + if Item == SectionStringsCommonItem10 or \ + Item == SectionStringsCommonItem1: + + try: + InfBinariesInstance.SetBinary(CommonBinary = CommonBin, ArchList = ArchList) + except: + pass + + else: + try: + InfBinariesInstance.SetBinary(Ver = Ver, ArchList = ArchList) + except: + print("Test Failed!") + AllPassedFlag = False + + if AllPassedFlag : + print('All tests passed...') + else: + print('Some unit test failed!') + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/CommonXml.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/CommonXml.py new file mode 100755 index 00000000..8c227442 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/CommonXml.py @@ -0,0 +1,997 @@ +## @file +# This file is used to parse a PCD file of .PKG file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +CommonXml +''' + +## +# Import Modules +# + +from Core.DistributionPackageClass import DistributionPackageHeaderObject +from Library.StringUtils import ConvertNEToNOTEQ +from Library.StringUtils import ConvertNOTEQToNE +from Library.StringUtils import GetSplitValueList +from Library.StringUtils import GetStringOfList +from Library.Xml.XmlRoutines import XmlElement +from Library.Xml.XmlRoutines import XmlElement2 +from Library.Xml.XmlRoutines import XmlAttribute +from Library.Xml.XmlRoutines import XmlNode +from Library.Xml.XmlRoutines import XmlList +from Library.Xml.XmlRoutines import CreateXmlElement +from Library.UniClassObject import ConvertSpecialUnicodes +from Library.UniClassObject import GetLanguageCode1766 +from Object.POM.CommonObject import FileObject +from Object.POM.CommonObject import MiscFileObject +from Object.POM.CommonObject import UserExtensionObject +from Object.POM.CommonObject import ClonedRecordObject +from Object.POM.CommonObject import LibraryClassObject +from Object.POM.CommonObject import FileNameObject +from Object.POM.ModuleObject import ModuleObject +from Xml.XmlParserMisc import IsRequiredItemListNull +from Xml.XmlParserMisc import GetHelpTextList +import Library.DataType as DataType + +## +# ClonedFromXml +# +class ClonedFromXml(object): + def __init__(self): + self.GUID = '' + self.Version = '' + + def FromXml(self, Item, Key): + self.GUID = XmlElement(Item, '%s/GUID' % Key) + self.Version = XmlAttribute(XmlNode(Item, '%s/GUID' % Key), 'Version') + if self.GUID == '' and self.Version == '': + return None + ClonedFrom = ClonedRecordObject() + ClonedFrom.SetPackageGuid(self.GUID) + ClonedFrom.SetPackageVersion(self.Version) + return ClonedFrom + + def ToXml(self, ClonedFrom, Key): + if self.GUID: + pass + Element1 = CreateXmlElement('GUID', ClonedFrom.GetPackageGuid(), [], + [['Version', ClonedFrom.GetPackageVersion()]]) + AttributeList = [] + NodeList = [Element1] + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + return Root + + def __str__(self): + return "GUID = %s Version = %s" % (self.GUID, self.Version) + + +## +# CommonDefinesXml +# +class CommonDefinesXml(object): + def __init__(self): + self.Usage = '' + self.SupArchList = [] + self.SupModList = [] + self.FeatureFlag = '' + + def FromXml(self, Item, Key): + if Key: + pass + self.Usage = XmlAttribute(Item, 'Usage') + self.SupArchList = \ + [Arch for Arch in GetSplitValueList(XmlAttribute(Item, 'SupArchList'), DataType.TAB_SPACE_SPLIT) if Arch] + self.SupModList = \ + [Mod for Mod in GetSplitValueList(XmlAttribute(Item, 'SupModList'), DataType.TAB_SPACE_SPLIT) if Mod] + self.FeatureFlag = ConvertNOTEQToNE(XmlAttribute(Item, 'FeatureFlag')) + + def ToXml(self): + pass + + def __str__(self): + return "Usage = %s SupArchList = %s SupModList = %s FeatureFlag = %s" \ + % (self.Usage, self.SupArchList, self.SupModList, self.FeatureFlag) + +## +# PromptXml +# +class PromptXml(object): + def __init__(self): + self.Prompt = '' + self.Lang = '' + + def FromXml(self, Item, Key): + if Key: + pass + self.Prompt = XmlElement2(Item, 'Prompt') + self.Lang = XmlAttribute(Item, 'Lang') + + def ToXml(self, Prompt, Key='Prompt'): + if self.Prompt: + pass + return CreateXmlElement('%s' % Key, Prompt.GetString(), [], [['Lang', Prompt.GetLang()]]) + def __str__(self): + return "Prompt = %s Lang = %s" % (self.Prompt, self.Lang) + +## +# HelpTextXml +# +class HelpTextXml(object): + def __init__(self): + self.HelpText = '' + self.Lang = '' + + def FromXml(self, Item, Key): + if Key: + pass + self.HelpText = XmlElement2(Item, 'HelpText') + self.Lang = XmlAttribute(Item, 'Lang') + + def ToXml(self, HelpText, Key='HelpText'): + if self.HelpText: + pass + return CreateXmlElement('%s' % Key, HelpText.GetString(), [], [['Lang', HelpText.GetLang()]]) + def __str__(self): + return "HelpText = %s Lang = %s" % (self.HelpText, self.Lang) + +## +# HeaderXml +# +class HeaderXml(object): + def __init__(self): + self.Name = '' + self.BaseName = '' + self.GUID = '' + self.Version = '' + self.CopyrightList = [] + self.LicenseList = [] + self.AbstractList = [] + self.DescriptionList = [] + + def FromXml(self, Item, Key, IsRequiredCheck=False, IsStandAlongModule=False): + if not Item and IsRequiredCheck: + XmlTreeLevel = [] + if IsStandAlongModule: + XmlTreeLevel = ['DistributionPackage', 'ModuleSurfaceArea'] + else: + XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'ModuleSurfaceArea'] + CheckDict = {'Header':''} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + self.Name = XmlElement(Item, '%s/Name' % Key) + self.BaseName = XmlAttribute(XmlNode(Item, '%s/Name' % Key), 'BaseName') + self.GUID = XmlElement(Item, '%s/GUID' % Key) + self.Version = XmlAttribute(XmlNode(Item, '%s/GUID' % Key), 'Version') + + for SubItem in XmlList(Item, '%s/Abstract' % Key): + HeaderAbstractLang = XmlAttribute(SubItem, 'Lang') + self.AbstractList.append((HeaderAbstractLang, XmlElement(SubItem, '%s/Abstract' % Key))) + for SubItem in XmlList(Item, '%s/Description' % Key): + HeaderDescriptionLang = XmlAttribute(SubItem, 'Lang') + self.DescriptionList.append((HeaderDescriptionLang, XmlElement(SubItem, '%s/Description' % Key))) + for SubItem in XmlList(Item, '%s/Copyright' % Key): + HeaderCopyrightLang = XmlAttribute(SubItem, 'Lang') + self.CopyrightList.append((HeaderCopyrightLang, XmlElement(SubItem, '%s/Copyright' % Key))) + for SubItem in XmlList(Item, '%s/License' % Key): + HeaderLicenseLang = XmlAttribute(SubItem, 'Lang') + self.LicenseList.append((HeaderLicenseLang, XmlElement(SubItem, '%s/License' % Key))) + ModuleHeader = ModuleObject() + ModuleHeader.SetName(self.Name) + ModuleHeader.SetBaseName(self.BaseName) + ModuleHeader.SetGuid(self.GUID) + ModuleHeader.SetVersion(self.Version) + ModuleHeader.SetCopyright(self.CopyrightList) + ModuleHeader.SetLicense(self.LicenseList) + ModuleHeader.SetAbstract(self.AbstractList) + ModuleHeader.SetDescription(self.DescriptionList) + return ModuleHeader + + def ToXml(self, Header, Key): + if self.GUID: + pass + Element1 = CreateXmlElement('Name', Header.GetName(), [], [['BaseName', Header.GetBaseName()]]) + Element2 = CreateXmlElement('GUID', Header.GetGuid(), [], [['Version', Header.GetVersion()]]) + NodeList = [Element1, + Element2, + ] + + UNIInfAbstractList = [] + UNIInfDescriptionList = [] + # Get Abstract and Description from Uni File + # if the Uni File exists + if Header.UniFileClassObject is not None: + UniStrDict = Header.UniFileClassObject.OrderedStringList + for Lang in UniStrDict: + for StringDefClassObject in UniStrDict[Lang]: + if not StringDefClassObject.StringValue: + continue + if StringDefClassObject.StringName == DataType.TAB_INF_ABSTRACT: + UNIInfAbstractList.append((GetLanguageCode1766(Lang), + ConvertSpecialUnicodes(StringDefClassObject.StringValue))) + + if StringDefClassObject.StringName == DataType.TAB_INF_DESCRIPTION: + UNIInfDescriptionList.append((GetLanguageCode1766(Lang), + ConvertSpecialUnicodes(StringDefClassObject.StringValue))) + + # Get Abstract and Description from INF File Header + for (Lang, Value) in Header.GetCopyright(): + if Value: + NodeList.append(CreateXmlElement('Copyright', Value, [], [])) + for (Lang, Value) in Header.GetLicense(): + if Value: + NodeList.append(CreateXmlElement('License', Value, [], [])) + for (Lang, Value) in Header.GetAbstract() + UNIInfAbstractList: + if Value: + NodeList.append(CreateXmlElement('Abstract', Value, [], [['Lang', Lang]])) + for (Lang, Value) in Header.GetDescription() + UNIInfDescriptionList: + if Value: + NodeList.append(CreateXmlElement('Description', Value, [], [['Lang', Lang]])) + + AttributeList = [] + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + return Root + + def __str__(self): + return "Name = %s BaseName = %s GUID = %s Version = %s Copyright = %s \ + License = %s Abstract = %s Description = %s" % \ + (self.Name, self.BaseName, self.GUID, self.Version, self.CopyrightList, \ + self.LicenseList, self.AbstractList, self.DescriptionList) +## +# DistributionPackageHeaderXml +# +class DistributionPackageHeaderXml(object): + def __init__(self): + self.Header = HeaderXml() + self.ReadOnly = '' + self.RePackage = '' + self.Vendor = '' + self.Date = '' + self.Signature = '' + self.XmlSpecification = '' + + def FromXml(self, Item, Key): + if not Item: + return None + self.ReadOnly = XmlAttribute(XmlNode(Item, '%s' % Key), 'ReadOnly') + self.RePackage = XmlAttribute(XmlNode(Item, '%s' % Key), 'RePackage') + self.Vendor = XmlElement(Item, '%s/Vendor' % Key) + self.Date = XmlElement(Item, '%s/Date' % Key) + self.Signature = XmlElement(Item, '%s/Signature' % Key) + self.XmlSpecification = XmlElement(Item, '%s/XmlSpecification' % Key) + self.Header.FromXml(Item, Key) + DistributionPackageHeader = DistributionPackageHeaderObject() + if self.ReadOnly.upper() == 'TRUE': + DistributionPackageHeader.ReadOnly = True + elif self.ReadOnly.upper() == 'FALSE': + DistributionPackageHeader.ReadOnly = False + if self.RePackage.upper() == 'TRUE': + DistributionPackageHeader.RePackage = True + elif self.RePackage.upper() == 'FALSE': + DistributionPackageHeader.RePackage = False + DistributionPackageHeader.Vendor = self.Vendor + DistributionPackageHeader.Date = self.Date + DistributionPackageHeader.Signature = self.Signature + DistributionPackageHeader.XmlSpecification = self.XmlSpecification + DistributionPackageHeader.SetName(self.Header.Name) + DistributionPackageHeader.SetBaseName(self.Header.BaseName) + DistributionPackageHeader.SetGuid(self.Header.GUID) + DistributionPackageHeader.SetVersion(self.Header.Version) + DistributionPackageHeader.SetCopyright(self.Header.CopyrightList) + DistributionPackageHeader.SetLicense(self.Header.LicenseList) + DistributionPackageHeader.SetAbstract(self.Header.AbstractList) + DistributionPackageHeader.SetDescription(self.Header.DescriptionList) + return DistributionPackageHeader + + def ToXml(self, DistributionPackageHeader, Key): + if self.Header: + pass + Element1 = CreateXmlElement('Name', \ + DistributionPackageHeader.GetName(), [], \ + [['BaseName', \ + DistributionPackageHeader.GetBaseName()]]) + Element2 = CreateXmlElement('GUID', \ + DistributionPackageHeader.GetGuid(), [], \ + [['Version', \ + DistributionPackageHeader.GetVersion()]]) + AttributeList = [] + if DistributionPackageHeader.ReadOnly != '': + AttributeList.append(['ReadOnly', str(DistributionPackageHeader.ReadOnly).lower()]) + if DistributionPackageHeader.RePackage != '': + AttributeList.append(['RePackage', str(DistributionPackageHeader.RePackage).lower()]) + if DistributionPackageHeader.GetAbstract(): + DPAbstract = DistributionPackageHeader.GetAbstract()[0][1] + else: + DPAbstract = '' + if DistributionPackageHeader.GetDescription(): + DPDescription = DistributionPackageHeader.GetDescription()[0][1] + else: + DPDescription = '' + if DistributionPackageHeader.GetCopyright(): + DPCopyright = DistributionPackageHeader.GetCopyright()[0][1] + else: + DPCopyright = '' + if DistributionPackageHeader.GetLicense(): + DPLicense = DistributionPackageHeader.GetLicense()[0][1] + else: + DPLicense = '' + NodeList = [Element1, + Element2, + ['Vendor', DistributionPackageHeader.Vendor], + ['Date', DistributionPackageHeader.Date], + ['Copyright', DPCopyright], + ['License', DPLicense], + ['Abstract', DPAbstract], + ['Description', DPDescription], + ['Signature', DistributionPackageHeader.Signature], + ['XmlSpecification', \ + DistributionPackageHeader.XmlSpecification], + ] + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + return Root + + def __str__(self): + return "ReadOnly = %s RePackage = %s Vendor = %s Date = %s \ + Signature = %s XmlSpecification = %s %s" % \ + (self.ReadOnly, self.RePackage, self.Vendor, self.Date, \ + self.Signature, self.XmlSpecification, self.Header) +## +# PackageHeaderXml +# +class PackageHeaderXml(object): + def __init__(self): + self.Header = HeaderXml() + self.PackagePath = '' + + def FromXml(self, Item, Key, PackageObject2): + if not Item: + XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea'] + CheckDict = {'PackageHeader': None, } + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + self.PackagePath = XmlElement(Item, '%s/PackagePath' % Key) + self.Header.FromXml(Item, Key) + PackageObject2.SetName(self.Header.Name) + PackageObject2.SetBaseName(self.Header.BaseName) + PackageObject2.SetGuid(self.Header.GUID) + PackageObject2.SetVersion(self.Header.Version) + PackageObject2.SetCopyright(self.Header.CopyrightList) + PackageObject2.SetLicense(self.Header.LicenseList) + PackageObject2.SetAbstract(self.Header.AbstractList) + PackageObject2.SetDescription(self.Header.DescriptionList) + PackageObject2.SetPackagePath(self.PackagePath) + + def ToXml(self, PackageObject2, Key): + if self.PackagePath: + pass + Element1 = CreateXmlElement('Name', PackageObject2.GetName(), [], \ + [['BaseName', PackageObject2.GetBaseName()]]) + Element2 = CreateXmlElement('GUID', PackageObject2.GetGuid(), [], \ + [['Version', PackageObject2.GetVersion()]]) + NodeList = [Element1, + Element2 + ] + + UNIPackageAbrstractList = [] + UNIPackageDescriptionList = [] + # Get Abstract and Description from Uni File + # if the Uni File exists + if PackageObject2.UniFileClassObject is not None: + UniStrDict = PackageObject2.UniFileClassObject.OrderedStringList + for Lang in UniStrDict: + for StringDefClassObject in UniStrDict[Lang]: + if not StringDefClassObject.StringValue: + continue + if StringDefClassObject.StringName == DataType.TAB_DEC_PACKAGE_ABSTRACT: + UNIPackageAbrstractList.append((GetLanguageCode1766(Lang), + ConvertSpecialUnicodes(StringDefClassObject.StringValue))) + + if StringDefClassObject.StringName == DataType.TAB_DEC_PACKAGE_DESCRIPTION: + UNIPackageDescriptionList.append((GetLanguageCode1766(Lang), + ConvertSpecialUnicodes(StringDefClassObject.StringValue))) + + # Get Abstract and Description from DEC File Header + for (Lang, Value) in PackageObject2.GetCopyright(): + if Value: + NodeList.append(CreateXmlElement(DataType.TAB_HEADER_COPYRIGHT, Value, [], [])) + for (Lang, Value) in PackageObject2.GetLicense(): + if Value: + NodeList.append(CreateXmlElement(DataType.TAB_HEADER_LICENSE, Value, [], [])) + for (Lang, Value) in PackageObject2.GetAbstract() + UNIPackageAbrstractList: + if Value: + NodeList.append(CreateXmlElement(DataType.TAB_HEADER_ABSTRACT, Value, [], [['Lang', Lang]])) + for (Lang, Value) in PackageObject2.GetDescription() + UNIPackageDescriptionList: + if Value: + NodeList.append(CreateXmlElement(DataType.TAB_HEADER_DESCRIPTION, Value, [], [['Lang', Lang]])) + + + NodeList.append(['PackagePath', PackageObject2.GetPackagePath()]) + AttributeList = [] + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + return Root + + def __str__(self): + return "PackagePath = %s %s" \ + % (self.PackagePath, self.Header) + +## +# MiscellaneousFileXml +# +class MiscellaneousFileXml(object): + def __init__(self): + self.Header = HeaderXml() + self.Files = [] + ## + # This API is used for Package or Module's MiscellaneousFile section + # + def FromXml(self, Item, Key): + if not Item: + return None + self.Header.FromXml(Item, Key) + NewItem = XmlNode(Item, '%s/Header' % Key) + self.Header.FromXml(NewItem, 'Header') + for SubItem in XmlList(Item, '%s/Filename' % Key): + Filename = XmlElement(SubItem, '%s/Filename' % Key) + Executable = XmlAttribute(XmlNode(SubItem, '%s/Filename' % Key), 'Executable') + if Executable.upper() == "TRUE": + Executable = True + elif Executable.upper() == "FALSE": + Executable = False + else: + Executable = '' + self.Files.append([Filename, Executable]) + MiscFile = MiscFileObject() + MiscFile.SetCopyright(self.Header.CopyrightList) + MiscFile.SetLicense(self.Header.LicenseList) + MiscFile.SetAbstract(self.Header.AbstractList) + MiscFile.SetDescription(self.Header.DescriptionList) + MiscFileList = [] + for File in self.Files: + FileObj = FileObject() + FileObj.SetURI(File[0]) + FileObj.SetExecutable(File[1]) + MiscFileList.append(FileObj) + MiscFile.SetFileList(MiscFileList) + return MiscFile + ## + # This API is used for DistP's tool section + # + def FromXml2(self, Item, Key): + if Item is None: + return None + NewItem = XmlNode(Item, '%s/Header' % Key) + self.Header.FromXml(NewItem, 'Header') + for SubItem in XmlList(Item, '%s/Filename' % Key): + Filename = XmlElement(SubItem, '%s/Filename' % Key) + Executable = \ + XmlAttribute(XmlNode(SubItem, '%s/Filename' % Key), 'Executable') + OsType = XmlAttribute(XmlNode(SubItem, '%s/Filename' % Key), 'OS') + if Executable.upper() == "TRUE": + Executable = True + elif Executable.upper() == "FALSE": + Executable = False + else: + Executable = '' + self.Files.append([Filename, Executable, OsType]) + MiscFile = MiscFileObject() + MiscFile.SetName(self.Header.Name) + MiscFile.SetCopyright(self.Header.CopyrightList) + MiscFile.SetLicense(self.Header.LicenseList) + MiscFile.SetAbstract(self.Header.AbstractList) + MiscFile.SetDescription(self.Header.DescriptionList) + MiscFileList = [] + for File in self.Files: + FileObj = FileObject() + FileObj.SetURI(File[0]) + FileObj.SetExecutable(File[1]) + FileObj.SetOS(File[2]) + MiscFileList.append(FileObj) + MiscFile.SetFileList(MiscFileList) + return MiscFile + + ## + # This API is used for Package or Module's MiscellaneousFile section + # + def ToXml(self, MiscFile, Key): + if self.Header: + pass + if MiscFile: + if MiscFile.GetAbstract(): + DPAbstract = MiscFile.GetAbstract()[0][1] + else: + DPAbstract = '' + if MiscFile.GetDescription(): + DPDescription = MiscFile.GetDescription()[0][1] + else: + DPDescription = '' + if MiscFile.GetCopyright(): + DPCopyright = MiscFile.GetCopyright()[0][1] + else: + DPCopyright = '' + if MiscFile.GetLicense(): + DPLicense = MiscFile.GetLicense()[0][1] + else: + DPLicense = '' + NodeList = [['Copyright', DPCopyright], + ['License', DPLicense], + ['Abstract', DPAbstract], + ['Description', DPDescription], + ] + for File in MiscFile.GetFileList(): + NodeList.append\ + (CreateXmlElement\ + ('Filename', File.GetURI(), [], \ + [['Executable', str(File.GetExecutable()).lower()]])) + Root = CreateXmlElement('%s' % Key, '', NodeList, []) + return Root + ## + # This API is used for DistP's tool section + # + def ToXml2(self, MiscFile, Key): + if self.Header: + pass + if MiscFile: + if MiscFile.GetAbstract(): + DPAbstract = MiscFile.GetAbstract()[0][1] + else: + DPAbstract = '' + if MiscFile.GetDescription(): + DPDescription = MiscFile.GetDescription()[0][1] + else: + DPDescription = '' + if MiscFile.GetCopyright(): + DPCopyright = MiscFile.GetCopyright()[0][1] + else: + DPCopyright = '' + if MiscFile.GetLicense(): + DPLicense = MiscFile.GetLicense()[0][1] + else: + DPLicense = '' + NodeList = [['Name', MiscFile.GetName()], + ['Copyright', DPCopyright], + ['License', DPLicense], + ['Abstract', DPAbstract], + ['Description', DPDescription], + ] + HeaderNode = CreateXmlElement('Header', '', NodeList, []) + NodeList = [HeaderNode] + for File in MiscFile.GetFileList(): + NodeList.append\ + (CreateXmlElement\ + ('Filename', File.GetURI(), [], \ + [['Executable', str(File.GetExecutable()).lower()], \ + ['OS', File.GetOS()]])) + Root = CreateXmlElement('%s' % Key, '', NodeList, []) + return Root + + def __str__(self): + Str = str(self.Header) + for Item in self.Files: + Str = Str + '\n\tFilename:' + str(Item) + return Str +## +# UserExtensionsXml +# +class UserExtensionsXml(object): + def __init__(self): + self.UserId = '' + self.Identifier = '' + self.BinaryAbstractList = [] + self.BinaryDescriptionList = [] + self.BinaryCopyrightList = [] + self.BinaryLicenseList = [] + self.LangDefsList = [] + self.DefineDict = {} + self.BuildOptionDict = {} + self.IncludesDict = {} + self.SourcesDict = {} + self.BinariesDict = {} + self.SupArchList = [] + self.Statement = '' + self.Defines = '' + self.BuildOptions = '' + + def FromXml2(self, Item, Key): + self.UserId = XmlAttribute(XmlNode(Item, '%s' % Key), 'UserId') + self.Identifier = XmlAttribute(XmlNode(Item, '%s' % Key), 'Identifier') + UserExtension = UserExtensionObject() + UserExtension.SetUserID(self.UserId) + UserExtension.SetIdentifier(self.Identifier) + return UserExtension + + def FromXml(self, Item, Key): + self.UserId = XmlAttribute(XmlNode(Item, '%s' % Key), 'UserId') + self.Identifier = XmlAttribute(XmlNode(Item, '%s' % Key), 'Identifier') + if self.UserId == DataType.TAB_BINARY_HEADER_USERID \ + and self.Identifier == DataType.TAB_BINARY_HEADER_IDENTIFIER: + for SubItem in XmlList(Item, '%s/BinaryAbstract' % Key): + BinaryAbstractLang = XmlAttribute(SubItem, 'Lang') + self.BinaryAbstractList.append((BinaryAbstractLang, XmlElement(SubItem, '%s/BinaryAbstract' % Key))) + for SubItem in XmlList(Item, '%s/BinaryDescription' % Key): + BinaryDescriptionLang = XmlAttribute(SubItem, 'Lang') + self.BinaryDescriptionList.append((BinaryDescriptionLang, + XmlElement(SubItem, '%s/BinaryDescription' % Key))) + for SubItem in XmlList(Item, '%s/BinaryCopyright' % Key): + BinaryCopyrightLang = XmlAttribute(SubItem, 'Lang') + self.BinaryCopyrightList.append((BinaryCopyrightLang, + XmlElement(SubItem, '%s/BinaryCopyright' % Key))) + for SubItem in XmlList(Item, '%s/BinaryLicense' % Key): + BinaryLicenseLang = XmlAttribute(SubItem, 'Lang') + self.BinaryLicenseList.append((BinaryLicenseLang, + XmlElement(SubItem, '%s/BinaryLicense' % Key))) + + DefineItem = XmlNode(Item, '%s/Define' % Key) + for SubItem in XmlList(DefineItem, 'Define/Statement'): + Statement = XmlElement(SubItem, '%s/Statement' % Key) + self.DefineDict[Statement] = "" + BuildOptionItem = XmlNode(Item, '%s/BuildOption' % Key) + for SubItem in XmlList(BuildOptionItem, 'BuildOption/Statement'): + Statement = XmlElement(SubItem, '%s/Statement' % Key) + Arch = XmlAttribute(XmlNode(SubItem, '%s/Statement' % Key), 'SupArchList') + self.BuildOptionDict[Arch] = Statement + IncludesItem = XmlNode(Item, '%s/Includes' % Key) + for SubItem in XmlList(IncludesItem, 'Includes/Statement'): + Statement = XmlElement(SubItem, '%s/Statement' % Key) + Arch = XmlAttribute(XmlNode(SubItem, '%s/Statement' % Key), 'SupArchList') + self.IncludesDict[Statement] = Arch + SourcesItem = XmlNode(Item, '%s/Sources' % Key) + Tmp = UserExtensionSourceXml() + SourceDict = Tmp.FromXml(SourcesItem, 'Sources') + self.SourcesDict = SourceDict + BinariesItem = XmlNode(Item, '%s/Binaries' % Key) + Tmp = UserExtensionBinaryXml() + BinariesDict = Tmp.FromXml(BinariesItem, 'Binaries') + self.BinariesDict = BinariesDict + self.Statement = XmlElement(Item, 'UserExtensions') + SupArch = XmlAttribute(XmlNode(Item, '%s' % Key), 'SupArchList') + self.SupArchList = [Arch for Arch in GetSplitValueList(SupArch, DataType.TAB_SPACE_SPLIT) if Arch] + UserExtension = UserExtensionObject() + UserExtension.SetUserID(self.UserId) + UserExtension.SetIdentifier(self.Identifier) + UserExtension.SetBinaryAbstract(self.BinaryAbstractList) + UserExtension.SetBinaryDescription(self.BinaryDescriptionList) + UserExtension.SetBinaryCopyright(self.BinaryCopyrightList) + UserExtension.SetBinaryLicense(self.BinaryLicenseList) + UserExtension.SetStatement(self.Statement) + UserExtension.SetSupArchList(self.SupArchList) + UserExtension.SetDefinesDict(self.DefineDict) + UserExtension.SetBuildOptionDict(self.BuildOptionDict) + UserExtension.SetIncludesDict(self.IncludesDict) + UserExtension.SetSourcesDict(self.SourcesDict) + UserExtension.SetBinariesDict(self.BinariesDict) + return UserExtension + + def ToXml(self, UserExtension, Key): + if self.UserId: + pass + AttributeList = [['UserId', str(UserExtension.GetUserID())], + ['Identifier', str(UserExtension.GetIdentifier())], + ['SupArchList', \ + GetStringOfList(UserExtension.GetSupArchList())], + ] + Root = CreateXmlElement('%s' % Key, UserExtension.GetStatement(), [], \ + AttributeList) + if UserExtension.GetIdentifier() == DataType.TAB_BINARY_HEADER_IDENTIFIER and \ + UserExtension.GetUserID() == DataType.TAB_BINARY_HEADER_USERID: + for (Lang, Value) in UserExtension.GetBinaryAbstract(): + if Value: + ChildElement = CreateXmlElement('BinaryAbstract', Value, [], [['Lang', Lang]]) + Root.appendChild(ChildElement) + for (Lang, Value) in UserExtension.GetBinaryDescription(): + if Value: + ChildElement = CreateXmlElement('BinaryDescription', Value, [], [['Lang', Lang]]) + Root.appendChild(ChildElement) + for (Lang, Value) in UserExtension.GetBinaryCopyright(): + if Value: + ChildElement = CreateXmlElement('BinaryCopyright', Value, [], []) + Root.appendChild(ChildElement) + for (Lang, Value) in UserExtension.GetBinaryLicense(): + if Value: + ChildElement = CreateXmlElement('BinaryLicense', Value, [], []) + Root.appendChild(ChildElement) + + NodeList = [] + DefineDict = UserExtension.GetDefinesDict() + if DefineDict: + for Item in DefineDict.keys(): + NodeList.append(CreateXmlElement\ + ('Statement', Item, [], [])) + DefineElement = CreateXmlElement('Define', '', NodeList, []) + Root.appendChild(DefineElement) + NodeList = [] + BuildOptionDict = UserExtension.GetBuildOptionDict() + if BuildOptionDict: + for Item in BuildOptionDict.keys(): + NodeList.append(CreateXmlElement\ + ('Statement', BuildOptionDict[Item], [], \ + [['SupArchList', Item]])) + BuildOptionElement = \ + CreateXmlElement('BuildOption', '', NodeList, []) + Root.appendChild(BuildOptionElement) + NodeList = [] + IncludesDict = UserExtension.GetIncludesDict() + if IncludesDict: + for Item in IncludesDict.keys(): + NodeList.append(CreateXmlElement\ + ('Statement', Item, [], \ + [['SupArchList', IncludesDict[Item]]])) + IncludesElement = CreateXmlElement('Includes', '', NodeList, []) + Root.appendChild(IncludesElement) + NodeList = [] + SourcesDict = UserExtension.GetSourcesDict() + if SourcesDict: + Tmp = UserExtensionSourceXml() + Root.appendChild(Tmp.ToXml(SourcesDict, 'Sources')) + NodeList = [] + BinariesDict = UserExtension.GetBinariesDict() + if BinariesDict: + Tmp = UserExtensionBinaryXml() + Root.appendChild(Tmp.ToXml(BinariesDict, 'Binaries')) + return Root + + def __str__(self): + Str = "UserId = %s Identifier = %s" % (self.UserId, self.Identifier) + Str = Str + '\n\tDefines:' + str(self.Defines) + Str = Str + '\n\tBuildOptions:' + str(self.BuildOptions) + return Str + +## +# UserExtensionSourceXml +# +class UserExtensionSourceXml(object): + def __init__(self): + self.UserExtensionSource = '' + + def FromXml(self, Item, Key): + if Key: + pass + if self.UserExtensionSource: + pass + Dict = {} + #SourcesItem = XmlNode(Item, '%s/Sources' % Key) + for SubItem in XmlList(Item, 'Sources/SourceFile'): + FileName = XmlElement(SubItem, 'SourceFile/FileName') + Family = XmlElement(SubItem, 'SourceFile/Family') + FeatureFlag = XmlElement(SubItem, 'SourceFile/FeatureFlag') + SupArchStr = XmlElement(SubItem, 'SourceFile/SupArchList') + DictKey = (FileName, Family, FeatureFlag, SupArchStr) + ValueList = [] + for ValueNodeItem in XmlList(SubItem, \ + 'SourceFile/SourceFileOtherAttr'): + TagName = XmlElement(ValueNodeItem, \ + 'SourceFileOtherAttr/TagName') + ToolCode = XmlElement(ValueNodeItem, \ + 'SourceFileOtherAttr/ToolCode') + Comment = XmlElement(ValueNodeItem, \ + 'SourceFileOtherAttr/Comment') + if (TagName == ' ') and (ToolCode == ' ') and (Comment == ' '): + TagName = '' + ToolCode = '' + Comment = '' + ValueList.append((TagName, ToolCode, Comment)) + Dict[DictKey] = ValueList + return Dict + + def ToXml(self, Dict, Key): + if self.UserExtensionSource: + pass + SourcesNodeList = [] + for Item in Dict: + ValueList = Dict[Item] + (FileName, Family, FeatureFlag, SupArchStr) = Item + SourceFileNodeList = [] + SourceFileNodeList.append(["FileName", FileName]) + SourceFileNodeList.append(["Family", Family]) + SourceFileNodeList.append(["FeatureFlag", FeatureFlag]) + SourceFileNodeList.append(["SupArchList", SupArchStr]) + for (TagName, ToolCode, Comment) in ValueList: + ValueNodeList = [] + if not (TagName or ToolCode or Comment): + TagName = ' ' + ToolCode = ' ' + Comment = ' ' + ValueNodeList.append(["TagName", TagName]) + ValueNodeList.append(["ToolCode", ToolCode]) + ValueNodeList.append(["Comment", Comment]) + ValueNodeXml = CreateXmlElement('SourceFileOtherAttr', '', \ + ValueNodeList, []) + SourceFileNodeList.append(ValueNodeXml) + SourceFileNodeXml = CreateXmlElement('SourceFile', '', \ + SourceFileNodeList, []) + SourcesNodeList.append(SourceFileNodeXml) + Root = CreateXmlElement('%s' % Key, '', SourcesNodeList, []) + return Root + +## +# UserExtensionBinaryXml +# +class UserExtensionBinaryXml(object): + def __init__(self): + self.UserExtensionBinary = '' + + def FromXml(self, Item, Key): + if Key: + pass + if self.UserExtensionBinary: + pass + Dict = {} + for SubItem in XmlList(Item, 'Binaries/Binary'): + FileName = XmlElement(SubItem, 'Binary/FileName') + FileType = XmlElement(SubItem, 'Binary/FileType') + FFE = XmlElement(SubItem, 'Binary/FeatureFlag') + SupArch = XmlElement(SubItem, 'Binary/SupArchList') + DictKey = (FileName, FileType, ConvertNOTEQToNE(FFE), SupArch) + ValueList = [] + for ValueNodeItem in XmlList(SubItem, \ + 'Binary/BinaryFileOtherAttr'): + Target = XmlElement(ValueNodeItem, \ + 'BinaryFileOtherAttr/Target') + Family = XmlElement(ValueNodeItem, \ + 'BinaryFileOtherAttr/Family') + TagName = XmlElement(ValueNodeItem, \ + 'BinaryFileOtherAttr/TagName') + Comment = XmlElement(ValueNodeItem, \ + 'BinaryFileOtherAttr/Comment') + if (Target == ' ') and (Family == ' ') and \ + (TagName == ' ') and (Comment == ' '): + Target = '' + Family = '' + TagName = '' + Comment = '' + + ValueList.append((Target, Family, TagName, Comment)) + Dict[DictKey] = ValueList + return Dict + + def ToXml(self, Dict, Key): + if self.UserExtensionBinary: + pass + BinariesNodeList = [] + for Item in Dict: + ValueList = Dict[Item] + (FileName, FileType, FeatureFlag, SupArch) = Item + FileNodeList = [] + FileNodeList.append(["FileName", FileName]) + FileNodeList.append(["FileType", FileType]) + FileNodeList.append(["FeatureFlag", ConvertNEToNOTEQ(FeatureFlag)]) + FileNodeList.append(["SupArchList", SupArch]) + for (Target, Family, TagName, Comment) in ValueList: + ValueNodeList = [] + if not (Target or Family or TagName or Comment): + Target = ' ' + Family = ' ' + TagName = ' ' + Comment = ' ' + ValueNodeList.append(["Target", Target]) + ValueNodeList.append(["Family", Family]) + ValueNodeList.append(["TagName", TagName]) + ValueNodeList.append(["Comment", Comment]) + ValueNodeXml = CreateXmlElement('BinaryFileOtherAttr', '', \ + ValueNodeList, []) + FileNodeList.append(ValueNodeXml) + FileNodeXml = CreateXmlElement('Binary', '', FileNodeList, []) + BinariesNodeList.append(FileNodeXml) + Root = CreateXmlElement('%s' % Key, '', BinariesNodeList, []) + return Root + +## +# LibraryClassXml +# +class LibraryClassXml(object): + def __init__(self): + self.Keyword = '' + self.HeaderFile = '' + self.RecommendedInstanceGuid = '' + self.RecommendedInstanceVersion = '' + self.CommonDefines = CommonDefinesXml() + self.HelpText = [] + + def FromXml(self, Item, Key): + self.Keyword = XmlAttribute(XmlNode(Item, '%s' % Key), 'Keyword') + if self.Keyword == '': + self.Keyword = XmlElement(Item, '%s/Keyword' % Key) + self.HeaderFile = XmlElement(Item, '%s/HeaderFile' % Key) + self.CommonDefines.FromXml(XmlNode(Item, '%s' % Key), Key) + for HelpTextItem in XmlList(Item, '%s/HelpText' % Key): + HelpTextObj = HelpTextXml() + HelpTextObj.FromXml(HelpTextItem, '%s/HelpText' % Key) + self.HelpText.append(HelpTextObj) + LibraryClass = LibraryClassObject() + LibraryClass.SetLibraryClass(self.Keyword) + LibraryClass.SetIncludeHeader(self.HeaderFile) + if self.CommonDefines.Usage: + LibraryClass.SetUsage(self.CommonDefines.Usage) + LibraryClass.SetSupArchList(self.CommonDefines.SupArchList) + LibraryClass.SetSupModuleList(self.CommonDefines.SupModList) + LibraryClass.SetFeatureFlag(ConvertNOTEQToNE(self.CommonDefines.FeatureFlag)) + LibraryClass.SetHelpTextList(GetHelpTextList(self.HelpText)) + return LibraryClass + + def ToXml(self, LibraryClass, Key): + if self.HeaderFile: + pass + AttributeList = \ + [['Keyword', LibraryClass.GetLibraryClass()], + ['SupArchList', GetStringOfList(LibraryClass.GetSupArchList())], + ['SupModList', GetStringOfList(LibraryClass.GetSupModuleList())] + ] + NodeList = [['HeaderFile', LibraryClass.GetIncludeHeader()]] + for Item in LibraryClass.GetHelpTextList(): + Tmp = HelpTextXml() + NodeList.append(Tmp.ToXml(Item)) + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + return Root + + def ToXml2(self, LibraryClass, Key): + if self.HeaderFile: + pass + FeatureFlag = ConvertNEToNOTEQ(LibraryClass.GetFeatureFlag()) + AttributeList = \ + [['Usage', LibraryClass.GetUsage()], \ + ['SupArchList', GetStringOfList(LibraryClass.GetSupArchList())], \ + ['SupModList', GetStringOfList(LibraryClass.GetSupModuleList())], \ + ['FeatureFlag', FeatureFlag] + ] + NodeList = [['Keyword', LibraryClass.GetLibraryClass()], ] + for Item in LibraryClass.GetHelpTextList(): + Tmp = HelpTextXml() + NodeList.append(Tmp.ToXml(Item)) + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + return Root + + def __str__(self): + Str = "Keyword = %s HeaderFile = %s RecommendedInstanceGuid = %s RecommendedInstanceVersion = %s %s" % \ + (self.Keyword, self.HeaderFile, self.RecommendedInstanceGuid, self.RecommendedInstanceVersion, \ + self.CommonDefines) + for Item in self.HelpText: + Str = Str + "\n\t" + str(Item) + return Str + +## +# FilenameXml +# +class FilenameXml(object): + def __init__(self): + self.FileType = '' + self.Filename = '' + self.CommonDefines = CommonDefinesXml() + + def FromXml(self, Item, Key): + self.FileType = XmlAttribute(Item, 'FileType') + Guid = XmlAttribute(Item, 'GUID') + self.Filename = XmlElement(Item, 'Filename') + self.CommonDefines.FromXml(Item, Key) + FeatureFlag = ConvertNOTEQToNE(self.CommonDefines.FeatureFlag) + Filename = FileNameObject() + # + # Convert File Type + # + if self.FileType == 'UEFI_IMAGE': + self.FileType = 'PE32' + + Filename.SetGuidValue(Guid) + Filename.SetFileType(self.FileType) + Filename.SetFilename(self.Filename) + Filename.SetSupArchList(self.CommonDefines.SupArchList) + Filename.SetFeatureFlag(FeatureFlag) + + return Filename + + def ToXml(self, Filename, Key): + if self.Filename: + pass + AttributeList = [['SupArchList', \ + GetStringOfList(Filename.GetSupArchList())], + ['FileType', Filename.GetFileType()], + ['FeatureFlag', ConvertNEToNOTEQ(Filename.GetFeatureFlag())], + ['GUID', Filename.GetGuidValue()] + ] + Root = CreateXmlElement('%s' % Key, Filename.GetFilename(), [], AttributeList) + + return Root + + def __str__(self): + return "FileType = %s Filename = %s %s" \ + % (self.FileType, self.Filename, self.CommonDefines) diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/GuidProtocolPpiXml.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/GuidProtocolPpiXml.py new file mode 100755 index 00000000..96c51c33 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/GuidProtocolPpiXml.py @@ -0,0 +1,278 @@ +## @file +# This file is used to parse a xml file of .PKG file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +GuidProtocolPpiXml +''' +from Library.StringUtils import ConvertNEToNOTEQ +from Library.StringUtils import ConvertNOTEQToNE +from Library.StringUtils import GetStringOfList +from Library.Xml.XmlRoutines import XmlElement +from Library.Xml.XmlRoutines import XmlAttribute +from Library.Xml.XmlRoutines import XmlNode +from Library.Xml.XmlRoutines import XmlList +from Library.Xml.XmlRoutines import CreateXmlElement + +from Object.POM.CommonObject import GuidObject +from Object.POM.CommonObject import ProtocolObject +from Object.POM.CommonObject import PpiObject + +from Xml.CommonXml import CommonDefinesXml +from Xml.CommonXml import HelpTextXml + +from Xml.XmlParserMisc import GetHelpTextList + +## +#GUID/Protocol/Ppi Common +# +class GuidProtocolPpiXml(object): + def __init__(self, Mode): + self.UiName = '' + self.GuidTypes = '' + self.Notify = '' + self.CName = '' + self.GuidValue = '' + self.CommonDefines = CommonDefinesXml() + self.HelpText = [] + # + # Guid/Ppi/Library, internal used for indicate return object for + # FromXml + # + self.Type = '' + # + # there are slightly different field between package and module + # + self.Mode = Mode + self.GuidType = '' + self.VariableName = '' + + def FromXml(self, Item, Key): + self.UiName = XmlAttribute(XmlNode(Item, '%s' % Key), 'UiName') + self.GuidType = XmlAttribute(XmlNode(Item, '%s' % Key), 'GuidType') + self.Notify = XmlAttribute(XmlNode(Item, '%s' % Key), 'Notify') + self.CName = XmlElement(Item, '%s/CName' % Key) + self.GuidValue = XmlElement(Item, '%s/GuidValue' % Key) + self.VariableName = XmlElement(Item, '%s/VariableName' % Key) + self.CommonDefines.FromXml(XmlNode(Item, '%s' % Key), Key) + for HelpTextItem in XmlList(Item, '%s/HelpText' % Key): + HelpTextObj = HelpTextXml() + HelpTextObj.FromXml(HelpTextItem, '%s/HelpText' % Key) + self.HelpText.append(HelpTextObj) + + if self.Type == 'Guid': + GuidProtocolPpi = GuidObject() + elif self.Type == 'Protocol': + GuidProtocolPpi = ProtocolObject() + else: + GuidProtocolPpi = PpiObject() + GuidProtocolPpi.SetHelpTextList(GetHelpTextList(self.HelpText)) + + return GuidProtocolPpi + + def ToXml(self, GuidProtocolPpi, Key): + if self.GuidValue: + pass + AttributeList = \ + [['Usage', GetStringOfList(GuidProtocolPpi.GetUsage())], \ + ['UiName', GuidProtocolPpi.GetName()], \ + ['GuidType', GetStringOfList(GuidProtocolPpi.GetGuidTypeList())], \ + ['Notify', str(GuidProtocolPpi.GetNotify()).lower()], \ + ['SupArchList', GetStringOfList(GuidProtocolPpi.GetSupArchList())], \ + ['SupModList', GetStringOfList(GuidProtocolPpi.GetSupModuleList())], \ + ['FeatureFlag', ConvertNEToNOTEQ(GuidProtocolPpi.GetFeatureFlag())] + ] + NodeList = [['CName', GuidProtocolPpi.GetCName()], + ['GuidValue', GuidProtocolPpi.GetGuid()], + ['VariableName', GuidProtocolPpi.VariableName] + ] + for Item in GuidProtocolPpi.GetHelpTextList(): + Tmp = HelpTextXml() + NodeList.append(Tmp.ToXml(Item)) + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root + + def __str__(self): + Str = \ + "UiName = %s Notify = %s GuidTypes = %s CName = %s GuidValue = %s %s" \ + % (self.UiName, self.Notify, self.GuidTypes, self.CName, \ + self.GuidValue, self.CommonDefines) + for Item in self.HelpText: + Str = Str + "\n\t" + str(Item) + return Str +## +#GUID Xml +# +class GuidXml(GuidProtocolPpiXml): + def __init__(self, Mode): + GuidProtocolPpiXml.__init__(self, Mode) + self.Type = 'Guid' + + def FromXml(self, Item, Key): + GuidProtocolPpi = GuidProtocolPpiXml.FromXml(self, Item, Key) + + if self.Mode == 'Package': + + GuidProtocolPpi.SetSupArchList(self.CommonDefines.SupArchList) + GuidProtocolPpi.SetSupModuleList(self.CommonDefines.SupModList) + GuidProtocolPpi.SetCName(self.CName) + GuidProtocolPpi.SetGuid(self.GuidValue) + else: + GuidProtocolPpi.SetUsage(self.CommonDefines.Usage) + if self.GuidType: + GuidProtocolPpi.SetGuidTypeList([self.GuidType]) + GuidProtocolPpi.SetSupArchList(self.CommonDefines.SupArchList) + GuidProtocolPpi.SetFeatureFlag(ConvertNOTEQToNE(self.CommonDefines.FeatureFlag)) + GuidProtocolPpi.SetCName(self.CName) + GuidProtocolPpi.SetVariableName(self.VariableName) + return GuidProtocolPpi + + def ToXml(self, GuidProtocolPpi, Key): + if self.Mode == 'Package': + AttributeList = \ + [['GuidType', \ + GetStringOfList(GuidProtocolPpi.GetGuidTypeList())], \ + ['SupArchList', \ + GetStringOfList(GuidProtocolPpi.GetSupArchList())], \ + ['SupModList', \ + GetStringOfList(GuidProtocolPpi.GetSupModuleList())], + ] + NodeList = [['CName', GuidProtocolPpi.GetCName()], + ['GuidValue', GuidProtocolPpi.GetGuid()], + ] + else: + AttributeList = \ + [['Usage', GetStringOfList(GuidProtocolPpi.GetUsage())], \ + ['GuidType', GetStringOfList(GuidProtocolPpi.GetGuidTypeList())],\ + ['SupArchList', \ + GetStringOfList(GuidProtocolPpi.GetSupArchList())], \ + ['FeatureFlag', ConvertNEToNOTEQ(GuidProtocolPpi.GetFeatureFlag())] + ] + NodeList = [['CName', GuidProtocolPpi.GetCName()], + ['VariableName', GuidProtocolPpi.GetVariableName()] + ] + + for Item in GuidProtocolPpi.GetHelpTextList(): + Tmp = HelpTextXml() + NodeList.append(Tmp.ToXml(Item)) + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root +## +#Protocol Xml +# +class ProtocolXml(GuidProtocolPpiXml): + def __init__(self, Mode): + GuidProtocolPpiXml.__init__(self, Mode) + self.Type = 'Protocol' + + def FromXml(self, Item, Key): + GuidProtocolPpi = GuidProtocolPpiXml.FromXml(self, Item, Key) + if self.Mode == 'Package': + GuidProtocolPpi.SetFeatureFlag(self.CommonDefines.FeatureFlag) + GuidProtocolPpi.SetSupArchList(self.CommonDefines.SupArchList) + GuidProtocolPpi.SetSupModuleList(self.CommonDefines.SupModList) + GuidProtocolPpi.SetCName(self.CName) + GuidProtocolPpi.SetGuid(self.GuidValue) + else: + GuidProtocolPpi.SetUsage(self.CommonDefines.Usage) + if self.Notify.upper() == "TRUE": + GuidProtocolPpi.SetNotify(True) + elif self.Notify.upper() == "FALSE": + GuidProtocolPpi.SetNotify(False) + else: + GuidProtocolPpi.SetNotify('') + GuidProtocolPpi.SetSupArchList(self.CommonDefines.SupArchList) + GuidProtocolPpi.SetFeatureFlag(ConvertNOTEQToNE(self.CommonDefines.FeatureFlag)) + GuidProtocolPpi.SetCName(self.CName) + + return GuidProtocolPpi + + def ToXml(self, GuidProtocolPpi, Key): + if self.Mode == 'Package': + AttributeList = \ + [['SupArchList', \ + GetStringOfList(GuidProtocolPpi.GetSupArchList())], \ + ['SupModList', \ + GetStringOfList(GuidProtocolPpi.GetSupModuleList())], \ + ['FeatureFlag', GuidProtocolPpi.GetFeatureFlag()] + ] + NodeList = [['CName', GuidProtocolPpi.GetCName()], + ['GuidValue', GuidProtocolPpi.GetGuid()], + ] + else: + AttributeList = \ + [['Usage', GetStringOfList(GuidProtocolPpi.GetUsage())], \ + ['Notify', str(GuidProtocolPpi.GetNotify()).lower()], \ + ['SupArchList', \ + GetStringOfList(GuidProtocolPpi.GetSupArchList())], \ + ['FeatureFlag', ConvertNEToNOTEQ(GuidProtocolPpi.GetFeatureFlag())] + ] + NodeList = [['CName', GuidProtocolPpi.GetCName()], + ] + + for Item in GuidProtocolPpi.GetHelpTextList(): + Tmp = HelpTextXml() + NodeList.append(Tmp.ToXml(Item)) + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root +## +#Ppi Xml +# +class PpiXml(GuidProtocolPpiXml): + def __init__(self, Mode): + GuidProtocolPpiXml.__init__(self, Mode) + self.Type = 'Ppi' + + def FromXml(self, Item, Key): + GuidProtocolPpi = GuidProtocolPpiXml.FromXml(self, Item, Key) + if self.Mode == 'Package': + GuidProtocolPpi.SetSupArchList(self.CommonDefines.SupArchList) + GuidProtocolPpi.SetSupModuleList(self.CommonDefines.SupModList) + GuidProtocolPpi.SetCName(self.CName) + GuidProtocolPpi.SetGuid(self.GuidValue) + else: + GuidProtocolPpi.SetUsage(self.CommonDefines.Usage) + if self.Notify.upper() == "TRUE": + GuidProtocolPpi.SetNotify(True) + elif self.Notify.upper() == "FALSE": + GuidProtocolPpi.SetNotify(False) + else: + GuidProtocolPpi.SetNotify('') + GuidProtocolPpi.SetSupArchList(self.CommonDefines.SupArchList) + GuidProtocolPpi.SetFeatureFlag(ConvertNOTEQToNE(self.CommonDefines.FeatureFlag)) + GuidProtocolPpi.SetCName(self.CName) + + return GuidProtocolPpi + + def ToXml(self, GuidProtocolPpi, Key): + if self.Mode == 'Package': + AttributeList = \ + [['SupArchList', \ + GetStringOfList(GuidProtocolPpi.GetSupArchList())], + ] + NodeList = [['CName', GuidProtocolPpi.GetCName()], + ['GuidValue', GuidProtocolPpi.GetGuid()], + ] + else: + AttributeList = \ + [['Usage', GetStringOfList(GuidProtocolPpi.GetUsage())], \ + ['Notify', str(GuidProtocolPpi.GetNotify()).lower()], \ + ['SupArchList', \ + GetStringOfList(GuidProtocolPpi.GetSupArchList())], \ + ['FeatureFlag', ConvertNEToNOTEQ(GuidProtocolPpi.GetFeatureFlag())] + ] + NodeList = [['CName', GuidProtocolPpi.GetCName()], + ] + + for Item in GuidProtocolPpi.GetHelpTextList(): + Tmp = HelpTextXml() + NodeList.append(Tmp.ToXml(Item)) + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + return Root diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/IniToXml.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/IniToXml.py new file mode 100755 index 00000000..a0c939de --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/IniToXml.py @@ -0,0 +1,496 @@ +## @file +# This file is for converting package information data file to xml file. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +IniToXml +''' + +import os.path +import re +from time import strftime +from time import localtime + +import Logger.Log as Logger +from Logger.ToolError import UPT_INI_PARSE_ERROR +from Logger.ToolError import FILE_NOT_FOUND +from Library.Xml.XmlRoutines import CreateXmlElement +from Library.DataType import TAB_VALUE_SPLIT +from Library.DataType import TAB_EQUAL_SPLIT +from Library.DataType import TAB_SECTION_START +from Library.DataType import TAB_SECTION_END +from Logger import StringTable as ST +from Library.StringUtils import ConvertSpecialChar +from Library.ParserValidate import IsValidPath +from Library import GlobalData + +## log error: +# +# @param error: error +# @param File: File +# @param Line: Line +# +def IniParseError(Error, File, Line): + Logger.Error("UPT", UPT_INI_PARSE_ERROR, File=File, + Line=Line, ExtraData=Error) + +## __ValidatePath +# +# @param Path: Path to be checked +# +def __ValidatePath(Path, Root): + Path = Path.strip() + if os.path.isabs(Path) or not IsValidPath(Path, Root): + return False, ST.ERR_FILELIST_LOCATION % (Root, Path) + return True, '' + +## ValidateMiscFile +# +# @param Filename: File to be checked +# +def ValidateMiscFile(Filename): + Root = GlobalData.gWORKSPACE + return __ValidatePath(Filename, Root) + +## ValidateToolsFile +# +# @param Filename: File to be checked +# +def ValidateToolsFile(Filename): + Valid, Cause = False, '' + if not Valid and 'EDK_TOOLS_PATH' in os.environ: + Valid, Cause = __ValidatePath(Filename, os.environ['EDK_TOOLS_PATH']) + if not Valid: + Valid, Cause = __ValidatePath(Filename, GlobalData.gWORKSPACE) + return Valid, Cause + +## ParseFileList +# +# @param Line: Line +# @param Map: Map +# @param CurrentKey: CurrentKey +# @param PathFunc: Path validate function +# +def ParseFileList(Line, Map, CurrentKey, PathFunc): + FileList = ["", {}] + TokenList = Line.split(TAB_VALUE_SPLIT) + if len(TokenList) > 0: + Path = TokenList[0].strip().replace('\\', '/') + if not Path: + return False, ST.ERR_WRONG_FILELIST_FORMAT + Valid, Cause = PathFunc(Path) + if not Valid: + return Valid, Cause + FileList[0] = TokenList[0].strip() + for Token in TokenList[1:]: + Attr = Token.split(TAB_EQUAL_SPLIT) + if len(Attr) != 2 or not Attr[0].strip() or not Attr[1].strip(): + return False, ST.ERR_WRONG_FILELIST_FORMAT + + Key = Attr[0].strip() + Val = Attr[1].strip() + if Key not in ['OS', 'Executable']: + return False, ST.ERR_UNKNOWN_FILELIST_ATTR % Key + + if Key == 'OS' and Val not in ["Win32", "Win64", "Linux32", + "Linux64", "OS/X32", "OS/X64", + "GenericWin", "GenericNix"]: + return False, ST.ERR_FILELIST_ATTR % 'OS' + elif Key == 'Executable' and Val not in ['true', 'false']: + return False, ST.ERR_FILELIST_ATTR % 'Executable' + FileList[1][Key] = Val + + Map[CurrentKey].append(FileList) + return True, '' + +## Create header XML file +# +# @param DistMap: DistMap +# @param Root: Root +# +def CreateHeaderXml(DistMap, Root): + Element1 = CreateXmlElement('Name', DistMap['Name'], + [], [['BaseName', DistMap['BaseName']]]) + Element2 = CreateXmlElement('GUID', DistMap['GUID'], + [], [['Version', DistMap['Version']]]) + AttributeList = [['ReadOnly', DistMap['ReadOnly']], + ['RePackage', DistMap['RePackage']]] + NodeList = [Element1, + Element2, + ['Vendor', DistMap['Vendor']], + ['Date', DistMap['Date']], + ['Copyright', DistMap['Copyright']], + ['License', DistMap['License']], + ['Abstract', DistMap['Abstract']], + ['Description', DistMap['Description']], + ['Signature', DistMap['Signature']], + ['XmlSpecification', DistMap['XmlSpecification']], + ] + Root.appendChild(CreateXmlElement('DistributionHeader', '', + NodeList, AttributeList)) + +## Create tools XML file +# +# @param Map: Map +# @param Root: Root +# @param Tag: Tag +# +def CreateToolsXml(Map, Root, Tag): + # + # Check if all elements in this section are empty + # + for Key in Map: + if len(Map[Key]) > 0: + break + else: + return + + NodeList = [['Name', Map['Name']], + ['Copyright', Map['Copyright']], + ['License', Map['License']], + ['Abstract', Map['Abstract']], + ['Description', Map['Description']], + ] + HeaderNode = CreateXmlElement('Header', '', NodeList, []) + NodeList = [HeaderNode] + + for File in Map['FileList']: + AttrList = [] + for Key in File[1]: + AttrList.append([Key, File[1][Key]]) + NodeList.append(CreateXmlElement('Filename', File[0], [], AttrList)) + Root.appendChild(CreateXmlElement(Tag, '', NodeList, [])) + +## ValidateValues +# +# @param Key: Key +# @param Value: Value +# @param SectionName: SectionName +# +def ValidateValues(Key, Value, SectionName): + if SectionName == 'DistributionHeader': + Valid, Cause = ValidateRegValues(Key, Value) + if not Valid: + return Valid, Cause + Valid = __ValidateDistHeader(Key, Value) + if not Valid: + return Valid, ST.ERR_VALUE_INVALID % (Key, SectionName) + else: + Valid = __ValidateOtherHeader(Key, Value) + if not Valid: + return Valid, ST.ERR_VALUE_INVALID % (Key, SectionName) + return True, '' + +## ValidateRegValues +# +# @param Key: Key +# @param Value: Value +# +def ValidateRegValues(Key, Value): + ValidateMap = { + 'ReadOnly' : + ('true|false', ST.ERR_BOOLEAN_VALUE % (Key, Value)), + 'RePackage' : + ('true|false', ST.ERR_BOOLEAN_VALUE % (Key, Value)), + 'GUID' : + ('[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}' + '-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}', + ST.ERR_GUID_VALUE % Value), + 'Version' : ('[0-9]+(\.[0-9]+)?', ST.ERR_VERSION_VALUE % \ + (Key, Value)), + 'XmlSpecification' : ('1\.1', ST.ERR_VERSION_XMLSPEC % Value) + } + if Key not in ValidateMap: + return True, '' + Elem = ValidateMap[Key] + Match = re.compile(Elem[0]).match(Value) + if Match and Match.start() == 0 and Match.end() == len(Value): + return True, '' + return False, Elem[1] + +## __ValidateDistHeaderName +# +# @param Name: Name +# +def __ValidateDistHeaderName(Name): + if len(Name) < 1: + return False + + for Char in Name: + if ord(Char) < 0x20 or ord(Char) >= 0x7f: + return False + return True + +## __ValidateDistHeaderBaseName +# +# @param BaseName: BaseName +# +def __ValidateDistHeaderBaseName(BaseName): + if not BaseName: + return False +# if CheckLen and len(BaseName) < 2: +# return False + if not BaseName[0].isalnum() and BaseName[0] != '_': + return False + for Char in BaseName[1:]: + if not Char.isalnum() and Char not in '-_': + return False + return True + +## __ValidateDistHeaderAbstract +# +# @param Abstract: Abstract +# +def __ValidateDistHeaderAbstract(Abstract): + return '\t' not in Abstract and len(Abstract.splitlines()) == 1 + +## __ValidateOtherHeaderAbstract +# +# @param Abstract: Abstract +# +def __ValidateOtherHeaderAbstract(Abstract): + return __ValidateDistHeaderAbstract(Abstract) + +## __ValidateDistHeader +# +# @param Key: Key +# @param Value: Value +# +def __ValidateDistHeader(Key, Value): + ValidateMap = { + 'Name' : __ValidateDistHeaderName, + 'BaseName' : __ValidateDistHeaderBaseName, + 'Abstract' : __ValidateDistHeaderAbstract, + 'Vendor' : __ValidateDistHeaderAbstract + } + return not (Value and Key in ValidateMap and not ValidateMap[Key](Value)) + +## __ValidateOtherHeader +# +# @param Key: Key +# @param Value: Value +# +def __ValidateOtherHeader(Key, Value): + ValidateMap = { + 'Name' : __ValidateDistHeaderName, + 'Abstract' : __ValidateOtherHeaderAbstract + } + return not (Value and Key in ValidateMap and not ValidateMap[Key](Value)) + +## Convert ini file to xml file +# +# @param IniFile +# +def IniToXml(IniFile): + if not os.path.exists(IniFile): + Logger.Error("UPT", FILE_NOT_FOUND, ST.ERR_TEMPLATE_NOTFOUND % IniFile) + + DistMap = {'ReadOnly' : '', 'RePackage' : '', 'Name' : '', + 'BaseName' : '', 'GUID' : '', 'Version' : '', 'Vendor' : '', + 'Date' : '', 'Copyright' : '', 'License' : '', 'Abstract' : '', + 'Description' : '', 'Signature' : '', 'XmlSpecification' : '' + } + + ToolsMap = {'Name' : '', 'Copyright' : '', 'License' : '', + 'Abstract' : '', 'Description' : '', 'FileList' : []} + # + # Only FileList is a list: [['file1', {}], ['file2', {}], ...] + # + MiscMap = {'Name' : '', 'Copyright' : '', 'License' : '', + 'Abstract' : '', 'Description' : '', 'FileList' : []} + + SectionMap = { + 'DistributionHeader' : DistMap, + 'ToolsHeader' : ToolsMap, + 'MiscellaneousFilesHeader' : MiscMap + } + + PathValidator = { + 'ToolsHeader' : ValidateToolsFile, + 'MiscellaneousFilesHeader' : ValidateMiscFile + } + + ParsedSection = [] + + SectionName = '' + CurrentKey = '' + PreMap = None + Map = None + FileContent = ConvertSpecialChar(open(IniFile, 'r').readlines()) + LastIndex = 0 + for Index in range(0, len(FileContent)): + LastIndex = Index + Line = FileContent[Index].strip() + if Line == '' or Line.startswith(';'): + continue + if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END: + CurrentKey = '' + SectionName = Line[1:-1].strip() + if SectionName not in SectionMap: + IniParseError(ST.ERR_SECTION_NAME_INVALID % SectionName, + IniFile, Index+1) + + if SectionName in ParsedSection: + IniParseError(ST.ERR_SECTION_REDEFINE % SectionName, + IniFile, Index+1) + else: + ParsedSection.append(SectionName) + + Map = SectionMap[SectionName] + continue + if not Map: + IniParseError(ST.ERR_SECTION_NAME_NONE, IniFile, Index+1) + TokenList = Line.split(TAB_EQUAL_SPLIT, 1) + TempKey = TokenList[0].strip() + # + # Value spanned multiple or same keyword appears more than one time + # + if len(TokenList) < 2 or TempKey not in Map: + if CurrentKey == '': + IniParseError(ST.ERR_KEYWORD_INVALID % TempKey, + IniFile, Index+1) + elif CurrentKey == 'FileList': + # + # Special for FileList + # + Valid, Cause = ParseFileList(Line, Map, CurrentKey, + PathValidator[SectionName]) + if not Valid: + IniParseError(Cause, IniFile, Index+1) + + else: + # + # Multiple lines for one key such as license + # Or if string on the left side of '=' is not a keyword + # + Map[CurrentKey] = ''.join([Map[CurrentKey], '\n', Line]) + Valid, Cause = ValidateValues(CurrentKey, + Map[CurrentKey], SectionName) + if not Valid: + IniParseError(Cause, IniFile, Index+1) + continue + + if (TokenList[1].strip() == ''): + IniParseError(ST.ERR_EMPTY_VALUE, IniFile, Index+1) + + # + # A keyword found + # + CurrentKey = TempKey + if Map[CurrentKey]: + IniParseError(ST.ERR_KEYWORD_REDEFINE % CurrentKey, + IniFile, Index+1) + + if id(Map) != id(PreMap) and Map['Copyright']: + PreMap = Map + Copyright = Map['Copyright'].lower() + Pos = Copyright.find('copyright') + if Pos == -1: + IniParseError(ST.ERR_COPYRIGHT_CONTENT, IniFile, Index) + if not Copyright[Pos + len('copyright'):].lstrip(' ').startswith('('): + IniParseError(ST.ERR_COPYRIGHT_CONTENT, IniFile, Index) + + if CurrentKey == 'FileList': + Valid, Cause = ParseFileList(TokenList[1], Map, CurrentKey, + PathValidator[SectionName]) + if not Valid: + IniParseError(Cause, IniFile, Index+1) + else: + Map[CurrentKey] = TokenList[1].strip() + Valid, Cause = ValidateValues(CurrentKey, + Map[CurrentKey], SectionName) + if not Valid: + IniParseError(Cause, IniFile, Index+1) + + if id(Map) != id(PreMap) and Map['Copyright'] and 'copyright' not in Map['Copyright'].lower(): + IniParseError(ST.ERR_COPYRIGHT_CONTENT, IniFile, LastIndex) + + # + # Check mandatory keys + # + CheckMdtKeys(DistMap, IniFile, LastIndex, + (('ToolsHeader', ToolsMap), ('MiscellaneousFilesHeader', MiscMap)) + ) + + return CreateXml(DistMap, ToolsMap, MiscMap, IniFile) + + +## CheckMdtKeys +# +# @param MdtDistKeys: All mandatory keys +# @param DistMap: Dist content +# @param IniFile: Ini file +# @param LastIndex: Last index of Ini file +# @param Maps: Tools and Misc section name and map. (('section_name', map),*) +# +def CheckMdtKeys(DistMap, IniFile, LastIndex, Maps): + MdtDistKeys = ['Name', 'GUID', 'Version', 'Vendor', 'Copyright', 'License', 'Abstract', 'XmlSpecification'] + for Key in MdtDistKeys: + if Key not in DistMap or DistMap[Key] == '': + IniParseError(ST.ERR_KEYWORD_MANDATORY % Key, IniFile, LastIndex+1) + + if '.' not in DistMap['Version']: + DistMap['Version'] = DistMap['Version'] + '.0' + + DistMap['Date'] = str(strftime("%Y-%m-%dT%H:%M:%S", localtime())) + + # + # Check Tools Surface Area according to UPT Spec + # {0,} + #
...
{0,1} + # ... {1,} + #
+ #
+ # xs:normalizedString {1} + # xs:string {0,1} + # xs:string {0,1} + # xs:normalizedString {0,1} + # xs:string {0,1} + #
+ # + for Item in Maps: + Map = Item[1] + NonEmptyKey = 0 + for Key in Map: + if Map[Key]: + NonEmptyKey += 1 + + if NonEmptyKey > 0 and not Map['FileList']: + IniParseError(ST.ERR_KEYWORD_MANDATORY % (Item[0] + '.FileList'), IniFile, LastIndex+1) + + if NonEmptyKey > 0 and not Map['Name']: + IniParseError(ST.ERR_KEYWORD_MANDATORY % (Item[0] + '.Name'), IniFile, LastIndex+1) + +## CreateXml +# +# @param DistMap: Dist Content +# @param ToolsMap: Tools Content +# @param MiscMap: Misc Content +# @param IniFile: Ini File +# +def CreateXml(DistMap, ToolsMap, MiscMap, IniFile): + Attrs = [['xmlns', 'http://www.uefi.org/2011/1.1'], + ['xmlns:xsi', 'http:/www.w3.org/2001/XMLSchema-instance'], + ] + Root = CreateXmlElement('DistributionPackage', '', [], Attrs) + CreateHeaderXml(DistMap, Root) + CreateToolsXml(ToolsMap, Root, 'Tools') + CreateToolsXml(MiscMap, Root, 'MiscellaneousFiles') + + FileAndExt = IniFile.rsplit('.', 1) + if len(FileAndExt) > 1: + FileName = FileAndExt[0] + '.xml' + else: + FileName = IniFile + '.xml' + File = open(FileName, 'w') + + try: + File.write(Root.toprettyxml(indent = ' ')) + finally: + File.close() + return FileName + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/ModuleSurfaceAreaXml.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/ModuleSurfaceAreaXml.py new file mode 100755 index 00000000..3419affa --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/ModuleSurfaceAreaXml.py @@ -0,0 +1,1003 @@ +## @file +# This file is used to parse a Module file of .PKG file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +ModuleSurfaceAreaXml +''' +from xml.dom import minidom + +from Library.StringUtils import ConvertNEToNOTEQ +from Library.StringUtils import ConvertNOTEQToNE +from Library.StringUtils import GetStringOfList +from Library.StringUtils import IsMatchArch +from Library.Xml.XmlRoutines import XmlElement +from Library.Xml.XmlRoutines import XmlAttribute +from Library.Xml.XmlRoutines import XmlNode +from Library.Xml.XmlRoutines import XmlList +from Library.Xml.XmlRoutines import CreateXmlElement +from Object.POM.CommonObject import GuidVersionObject +from Object.POM.ModuleObject import BootModeObject +from Object.POM.ModuleObject import DepexObject +from Object.POM.ModuleObject import ModuleObject +from Object.POM.ModuleObject import EventObject +from Object.POM.ModuleObject import HobObject +from Object.POM.ModuleObject import SourceFileObject +from Object.POM.ModuleObject import PackageDependencyObject +from Object.POM.ModuleObject import ExternObject +from Object.POM.ModuleObject import BinaryFileObject +from Object.POM.ModuleObject import AsBuiltObject +from Object.POM.ModuleObject import BinaryBuildFlagObject +from Xml.CommonXml import ClonedFromXml +from Xml.CommonXml import HeaderXml +from Xml.CommonXml import HelpTextXml +from Xml.CommonXml import CommonDefinesXml +from Xml.CommonXml import LibraryClassXml +from Xml.CommonXml import UserExtensionsXml +from Xml.CommonXml import MiscellaneousFileXml +from Xml.CommonXml import FilenameXml +from Xml.GuidProtocolPpiXml import GuidXml +from Xml.GuidProtocolPpiXml import ProtocolXml +from Xml.GuidProtocolPpiXml import PpiXml +from Xml.PcdXml import PcdEntryXml +from Xml.XmlParserMisc import GetHelpTextList +from Library import GlobalData +from Library.Misc import GetSplitValueList + +## BinaryFileXml +# +# represent the following XML item +# +# +# +# xs:anyURI +# {1,} +# ... {0,} +# {1,} +# +class BinaryFileXml(object): + def __init__(self): + self.FileNames = [] + self.AsBuiltList = [] + self.PatchPcdValues = '' + self.PcdExValues = '' + self.LibraryInstances = '' + self.BuildFlags = '' + + def FromXml(self, Item, Key): + if self.FileNames: + pass + BinaryFile = BinaryFileObject() + FilenameList = [] + SupArchList = ['COMMON'] + for SubItem in XmlList(Item, '%s/Filename' % Key): + Axml = FilenameXml() + Bxml = Axml.FromXml(SubItem, 'Filename') + FilenameList.append(Bxml) + BinaryFile.SetFileNameList(FilenameList) + for FileName in FilenameList: + if FileName.GetSupArchList(): + SupArchList = FileName.GetSupArchList() + BinaryFile.SetSupArchList(SupArchList) + if GlobalData.gIS_BINARY_INF: + AsBuiltList = [] + for AsBuiltItem in XmlList(Item, '%s/AsBuilt' % Key): + AsBuilt = AsBuiltObject() + + PatchPcdValueList = [] + for SubItem in XmlList(AsBuiltItem, 'AsBuilt/PatchPcdValue'): + Axml = PcdEntryXml() + Bxml = Axml.FromXml(SubItem, 'PatchPcdValue') + PatchPcdValueList.append(Bxml) + AsBuilt.SetPatchPcdList(PatchPcdValueList) + PcdExValueList = [] + for SubItem in XmlList(AsBuiltItem, 'AsBuilt/PcdExValue'): + Axml = PcdEntryXml() + Bxml = Axml.FromXml(SubItem, 'PcdExValue') + PcdExValueList.append(Bxml) + AsBuilt.SetPcdExList(PcdExValueList) + LibraryList = [] + for SubItem in XmlList(Item, '%s/AsBuilt/LibraryInstances/GUID' % Key): + GuidVerObj = GuidVersionObject() + GUID = XmlElement(SubItem, 'GUID') + Version = XmlAttribute(XmlNode(SubItem, 'GUID'), 'Version') + GuidVerObj.SetGuid(GUID) + GuidVerObj.SetVersion(Version) + LibraryList.append(GuidVerObj) + if XmlList(Item, '%s/AsBuilt/LibraryInstances' % Key) and not LibraryList: + LibraryList = [None] + AsBuilt.SetLibraryInstancesList(LibraryList) + BuildFlagList = [] + for SubItem in XmlList(Item, '%s/AsBuilt/BuildFlags' % Key): + BuildFlag = BuildFlagXml() + BuildFlagList.append(BuildFlag.FromXml2(SubItem, 'BuildFlags')) + AsBuilt.SetBuildFlagsList(BuildFlagList) + AsBuiltList.append(AsBuilt) + BinaryFile.SetAsBuiltList(AsBuiltList) + return BinaryFile + + def ToXml(self, BinaryFile, Key): + if self.FileNames: + pass + NodeList = [] + FilenameList = BinaryFile.GetFileNameList() + SupportArch = None + for Filename in FilenameList: + Tmp = FilenameXml() + NodeList.append(Tmp.ToXml(Filename, 'Filename')) + SupportArch = Filename.SupArchList + + AsBuildList = BinaryFile.GetAsBuiltList() + PatchPcdValueList = AsBuildList.GetPatchPcdList() + PcdExList = AsBuildList.GetPcdExList() + LibGuidVerList = AsBuildList.GetLibraryInstancesList() + BuildFlagList = AsBuildList.GetBuildFlagsList() + + AsBuiltNodeList = [] + + for Pcd in PatchPcdValueList: + if IsMatchArch(Pcd.SupArchList, SupportArch): + Tmp = PcdEntryXml() + AsBuiltNodeList.append(Tmp.ToXml4(Pcd, 'PatchPcdValue')) + + for Pcd in PcdExList: + if IsMatchArch(Pcd.SupArchList, SupportArch): + Tmp = PcdEntryXml() + AsBuiltNodeList.append(Tmp.ToXml4(Pcd, 'PcdExValue')) + + GuiVerElemList = [] + for LibGuidVer in LibGuidVerList: + if LibGuidVer.GetLibGuid() and IsMatchArch(LibGuidVer.GetSupArchList(), SupportArch): + GuiVerElem = \ + CreateXmlElement('GUID', LibGuidVer.GetLibGuid(), [], [['Version', LibGuidVer.GetLibVersion()]]) + GuiVerElemList.append(GuiVerElem) + if len(GuiVerElemList) > 0: + LibGuidVerElem = CreateXmlElement('LibraryInstances', '', GuiVerElemList, []) + AsBuiltNodeList.append(LibGuidVerElem) + + for BuildFlag in BuildFlagList: + if IsMatchArch(BuildFlag.GetSupArchList(), SupportArch): + for Item in BuildFlag.GetAsBuildList(): + Tmp = BuildFlagXml() + Elem = CreateXmlElement('BuildFlags', ''.join(Item), [], []) + AsBuiltNodeList.append(Elem) + + if len(AsBuiltNodeList) > 0: + Element = CreateXmlElement('AsBuilt', '', AsBuiltNodeList, []) + NodeList.append(Element) + + Root = CreateXmlElement('%s' % Key, '', NodeList, []) + + return Root + + def __str__(self): + Str = "BinaryFiles:" + for Item in self.FileNames: + Str = Str + '\n\t' + str(Item) + for Item in self.PatchPcdValues: + Str = Str + '\n\t' + str(Item) + for Item in self.PcdExValues: + Str = Str + '\n\t' + str(Item) + for Item in self.LibraryInstances: + Str = Str + '\n\t' + str(Item) + for Item in self.BuildFlags: + Str = Str + '\n\t' + str(Item) + return Str + +## +# PackageXml +# +class PackageXml(object): + def __init__(self): + self.Description = '' + self.Guid = '' + self.Version = '' + self.CommonDefines = CommonDefinesXml() + + def FromXml(self, Item, Key): + self.Description = XmlElement(Item, '%s/Description' % Key) + self.Guid = XmlElement(Item, '%s/GUID' % Key) + self.Version = XmlAttribute(XmlNode(Item, '%s/GUID' % Key), 'Version') + self.CommonDefines.FromXml(XmlNode(Item, '%s' % Key), Key) + + PackageDependency = PackageDependencyObject() + PackageDependency.SetPackage(self.Description) + PackageDependency.SetGuid(self.Guid) + PackageDependency.SetVersion(self.Version) + PackageDependency.SetFeatureFlag(ConvertNOTEQToNE(self.CommonDefines.FeatureFlag)) + PackageDependency.SetSupArchList(self.CommonDefines.SupArchList) + + return PackageDependency + + def ToXml(self, PackageDependency, Key): + if self.Guid: + pass + AttributeList = [['SupArchList', GetStringOfList(PackageDependency.GetSupArchList())], + ['FeatureFlag', ConvertNEToNOTEQ(PackageDependency.GetFeatureFlag())], ] + Element1 = CreateXmlElement('GUID', PackageDependency.GetGuid(), [], + [['Version', PackageDependency.GetVersion()]]) + NodeList = [['Description', PackageDependency.GetPackage()], Element1, ] + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root + + def __str__(self): + Str = "Description = %s Guid = %s Version = %s %s" \ + % (self.Description, self.Guid, self.Version, self.CommonDefines) + return Str +## +# ExternXml +# +class ExternXml(object): + def __init__(self): + self.CommonDefines = CommonDefinesXml() + self.EntryPoint = '' + self.UnloadImage = '' + self.Constructor = '' + self.Destructor = '' + self.SupModList = '' + self.SupArchList = '' + self.HelpText = [] + + def FromXml(self, Item, Key): + self.CommonDefines.FromXml(Item, Key) + self.EntryPoint = XmlElement(Item, '%s/EntryPoint' % Key) + self.UnloadImage = XmlElement(Item, '%s/UnloadImage' % Key) + self.Constructor = XmlElement(Item, '%s/Constructor' % Key) + self.Destructor = XmlElement(Item, '%s/Destructor' % Key) + + Extern = ExternObject() + Extern.SetEntryPoint(self.EntryPoint) + Extern.SetUnloadImage(self.UnloadImage) + Extern.SetConstructor(self.Constructor) + Extern.SetDestructor(self.Destructor) + if self.CommonDefines.SupModList: + Extern.SetSupModList(self.CommonDefines.SupModList) + if self.CommonDefines.SupArchList: + Extern.SetSupArchList(self.CommonDefines.SupArchList) + return Extern + + def ToXml(self, Extern, Key): + if self.HelpText: + pass + + NodeList = [] + if Extern.GetEntryPoint(): + NodeList.append(['EntryPoint', Extern.GetEntryPoint()]) + if Extern.GetUnloadImage(): + NodeList.append(['UnloadImage', Extern.GetUnloadImage()]) + if Extern.GetConstructor(): + NodeList.append(['Constructor', Extern.GetConstructor()]) + if Extern.GetDestructor(): + NodeList.append(['Destructor', Extern.GetDestructor()]) + Root = CreateXmlElement('%s' % Key, '', NodeList, []) + + return Root + + def __str__(self): + Str = "EntryPoint = %s UnloadImage = %s Constructor = %s Destructor = %s %s" \ + % (self.EntryPoint, self.UnloadImage, self.Constructor, self.Destructor, self.CommonDefines) + for Item in self.HelpText: + Str = Str + '\n\t' + str(Item) + return Str +## +# DepexXml +# +class DepexXml(object): + def __init__(self): + self.CommonDefines = CommonDefinesXml() + self.Expression = None + self.HelpText = [] + + def FromXml(self, Item, Key): + if not Item: + return None + self.CommonDefines.FromXml(Item, Key) + self.Expression = XmlElement(Item, '%s/Expression' % Key) + for HelpTextItem in XmlList(Item, '%s/HelpText' % Key): + HelpTextObj = HelpTextXml() + HelpTextObj.FromXml(HelpTextItem, '%s/HelpText' % Key) + self.HelpText.append(HelpTextObj) + + Depex = DepexObject() + Depex.SetDepex(self.Expression) + Depex.SetModuleType(self.CommonDefines.SupModList) + Depex.SetSupArchList(self.CommonDefines.SupArchList) + Depex.SetFeatureFlag(self.CommonDefines.FeatureFlag) + Depex.SetHelpTextList(GetHelpTextList(self.HelpText)) + + return Depex + + def ToXml(self, Depex, Key): + if self.HelpText: + pass + AttributeList = [['SupArchList', GetStringOfList(Depex.GetSupArchList())], + ['SupModList', Depex.GetModuleType()]] + NodeList = [['Expression', Depex.GetDepex()]] + if Depex.GetHelpText(): + Tmp = HelpTextXml() + NodeList.append(Tmp.ToXml(Depex.GetHelpText(), 'HelpText')) + + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + return Root + + def __str__(self): + Str = "Expression = %s" % (self.Expression) + for Item in self.HelpText: + Str = Str + '\n\t' + str(Item) + return Str + +## +# BootModeXml +# +class BootModeXml(object): + def __init__(self): + self.SupportedBootModes = '' + self.CommonDefines = CommonDefinesXml() + self.HelpText = [] + + def FromXml(self, Item, Key): + self.SupportedBootModes = \ + XmlElement(Item, '%s/SupportedBootModes' % Key) + self.CommonDefines.FromXml(Item, Key) + for HelpTextItem in XmlList(Item, '%s/HelpText' % Key): + HelpTextObj = HelpTextXml() + HelpTextObj.FromXml(HelpTextItem, '%s/HelpText' % Key) + self.HelpText.append(HelpTextObj) + + BootMode = BootModeObject() + BootMode.SetSupportedBootModes(self.SupportedBootModes) + BootMode.SetUsage(self.CommonDefines.Usage) + BootMode.SetHelpTextList(GetHelpTextList(self.HelpText)) + + return BootMode + + def ToXml(self, BootMode, Key): + if self.HelpText: + pass + AttributeList = [['Usage', BootMode.GetUsage()], ] + NodeList = [['SupportedBootModes', BootMode.GetSupportedBootModes()]] + for Item in BootMode.GetHelpTextList(): + Tmp = HelpTextXml() + NodeList.append(Tmp.ToXml(Item, 'HelpText')) + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root + + def __str__(self): + Str = "SupportedBootModes = %s %s" % (self.SupportedBootModes, self.CommonDefines) + for Item in self.HelpText: + Str = Str + '\n\t' + str(Item) + return Str +## +# EventXml +# +class EventXml(object): + def __init__(self): + self.EventType = '' + self.Name = '' + self.CommonDefines = CommonDefinesXml() + self.HelpText = [] + + def FromXml(self, Item, Key): + self.EventType = XmlAttribute(XmlNode(Item, '%s' % Key), 'EventType') + self.Name = XmlElement(Item, '%s' % Key) + self.CommonDefines.FromXml(Item, Key) + for HelpTextItem in XmlList(Item, '%s/HelpText' % Key): + HelpTextObj = HelpTextXml() + HelpTextObj.FromXml(HelpTextItem, '%s/HelpText' % Key) + self.HelpText.append(HelpTextObj) + + Event = EventObject() + Event.SetEventType(self.EventType) + Event.SetUsage(self.CommonDefines.Usage) + Event.SetHelpTextList(GetHelpTextList(self.HelpText)) + + return Event + + def ToXml(self, Event, Key): + if self.HelpText: + pass + AttributeList = [['EventType', Event.GetEventType()], + ['Usage', Event.GetUsage()], + ] + NodeList = [] + for Item in Event.GetHelpTextList(): + Tmp = HelpTextXml() + NodeList.append(Tmp.ToXml(Item, 'HelpText')) + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root + + def __str__(self): + Str = "EventType = %s %s" % (self.EventType, self.CommonDefines) + for Item in self.HelpText: + Str = Str + '\n\t' + str(Item) + return Str +## +# HobXml +# +class HobXml(object): + def __init__(self): + self.HobType = '' + self.Name = '' + self.CommonDefines = CommonDefinesXml() + self.HelpText = [] + + def FromXml(self, Item, Key): + self.HobType = XmlAttribute(XmlNode(Item, '%s' % Key), 'HobType') + self.Name = XmlElement(Item, '%s' % Key) + self.CommonDefines.FromXml(Item, Key) + for HelpTextItem in XmlList(Item, '%s/HelpText' % Key): + HelpTextObj = HelpTextXml() + HelpTextObj.FromXml(HelpTextItem, '%s/HelpText' % Key) + self.HelpText.append(HelpTextObj) + + Hob = HobObject() + Hob.SetHobType(self.HobType) + Hob.SetSupArchList(self.CommonDefines.SupArchList) + Hob.SetUsage(self.CommonDefines.Usage) + Hob.SetHelpTextList(GetHelpTextList(self.HelpText)) + + return Hob + + def ToXml(self, Hob, Key): + if self.Name: + pass + AttributeList = [['HobType', Hob.GetHobType()], + ['Usage', Hob.GetUsage()], + ['SupArchList', GetStringOfList(Hob.GetSupArchList())], ] + NodeList = [] + for Item in Hob.GetHelpTextList(): + Tmp = HelpTextXml() + NodeList.append(Tmp.ToXml(Item, 'HelpText')) + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root + + def __str__(self): + Str = "HobType = %s %s" % (self.HobType, self.CommonDefines) + for Item in self.HelpText: + Str = Str + '\n\t' + str(Item) + return Str + +## +# SourceFileXml +# +class SourceFileXml(object): + def __init__(self): + self.SourceFile = '' + self.ToolChainFamily = '' + self.FileType = '' + self.CommonDefines = CommonDefinesXml() + + def FromXml(self, Item, Key): + self.ToolChainFamily = XmlAttribute(Item, 'Family') + self.SourceFile = XmlElement(Item, 'Filename') + self.CommonDefines.FromXml(Item, Key) + + self.CommonDefines.FeatureFlag = ConvertNOTEQToNE(self.CommonDefines.FeatureFlag) + + SourceFile = SourceFileObject() + SourceFile.SetSourceFile(self.SourceFile) + SourceFile.SetFamily(self.ToolChainFamily) + SourceFile.SetSupArchList(self.CommonDefines.SupArchList) + SourceFile.SetFeatureFlag(self.CommonDefines.FeatureFlag) + + return SourceFile + + def ToXml(self, SourceFile, Key): + if self.SourceFile: + pass + FeatureFlag = ConvertNEToNOTEQ(SourceFile.GetFeatureFlag()) + AttributeList = [['SupArchList', GetStringOfList(SourceFile.GetSupArchList())], + ['Family', SourceFile.GetFamily()], + ['FeatureFlag', FeatureFlag], ] + Root = CreateXmlElement('%s' % Key, SourceFile.GetSourceFile(), [], AttributeList) + return Root + +## +# ModulePropertyXml +# +class ModulePropertyXml(object): + def __init__(self): + self.CommonDefines = CommonDefinesXml() + self.ModuleType = '' + self.Path = '' + self.PcdIsDriver = '' + self.UefiSpecificationVersion = '' + self.PiSpecificationVersion = '' + self.SpecificationList = [] + self.SpecificationVersion = '' + self.BootModes = [] + self.Events = [] + self.HOBs = [] + + def FromXml(self, Item, Key, Header=None): + self.CommonDefines.FromXml(Item, Key) + self.ModuleType = XmlElement(Item, '%s/ModuleType' % Key) + self.Path = XmlElement(Item, '%s/Path' % Key) + self.PcdIsDriver = XmlElement(Item, '%s/PcdIsDriver' % Key) + self.UefiSpecificationVersion = XmlElement(Item, '%s/UefiSpecificationVersion' % Key) + self.PiSpecificationVersion = XmlElement(Item, '%s/PiSpecificationVersion' % Key) + for SubItem in XmlList(Item, '%s/Specification' % Key): + Specification = XmlElement(SubItem, '/Specification') + Version = XmlAttribute(XmlNode(SubItem, '/Specification'), 'Version') + self.SpecificationList.append((Specification, Version)) + for SubItem in XmlList(Item, '%s/BootMode' % Key): + Axml = BootModeXml() + BootMode = Axml.FromXml(SubItem, 'BootMode') + self.BootModes.append(BootMode) + for SubItem in XmlList(Item, '%s/Event' % Key): + Axml = EventXml() + Event = Axml.FromXml(SubItem, 'Event') + self.Events.append(Event) + for SubItem in XmlList(Item, '%s/HOB' % Key): + Axml = HobXml() + Hob = Axml.FromXml(SubItem, 'HOB') + self.HOBs.append(Hob) + + if Header is None: + Header = ModuleObject() + + Header.SetModuleType(self.ModuleType) + Header.SetSupArchList(self.CommonDefines.SupArchList) + Header.SetModulePath(self.Path) + + Header.SetPcdIsDriver(self.PcdIsDriver) + Header.SetUefiSpecificationVersion(self.UefiSpecificationVersion) + Header.SetPiSpecificationVersion(self.PiSpecificationVersion) + Header.SetSpecList(self.SpecificationList) + + return Header, self.BootModes, self.Events, self.HOBs + + + def ToXml(self, Header, BootModes, Events, Hobs, Key): + if self.ModuleType: + pass + AttributeList = [['SupArchList', GetStringOfList(Header.GetSupArchList())], ] + + NodeList = [['ModuleType', Header.GetModuleType()], + ['Path', Header.GetModulePath()], + ['PcdIsDriver', Header.GetPcdIsDriver()], + ['UefiSpecificationVersion', Header.GetUefiSpecificationVersion()], + ['PiSpecificationVersion', Header.GetPiSpecificationVersion()], + ] + for Item in Header.GetSpecList(): + Spec, Version = Item + SpecElem = CreateXmlElement('Specification', Spec, [], [['Version', Version]]) + NodeList.append(SpecElem) + + for Item in BootModes: + Tmp = BootModeXml() + NodeList.append(Tmp.ToXml(Item, 'BootMode')) + for Item in Events: + Tmp = EventXml() + NodeList.append(Tmp.ToXml(Item, 'Event')) + for Item in Hobs: + Tmp = HobXml() + NodeList.append(Tmp.ToXml(Item, 'HOB')) + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root + + def __str__(self): + Str = "ModuleType = %s Path = %s PcdIsDriver = %s UefiSpecificationVersion = %s PiSpecificationVersion = %s \ + Specification = %s SpecificationVersion = %s %s" % \ + (self.ModuleType, self.Path, self.PcdIsDriver, \ + self.UefiSpecificationVersion, self.PiSpecificationVersion, \ + self.SpecificationList, self.SpecificationVersion, self.CommonDefines) + for Item in self.BootModes: + Str = Str + '\n\t' + str(Item) + for Item in self.Events: + Str = Str + '\n\t' + str(Item) + for Item in self.HOBs: + Str = Str + '\n\t' + str(Item) + return Str + +## +# ModuleXml +# +class ModuleSurfaceAreaXml(object): + def __init__(self, Package=''): + self.Module = None + # + # indicate the package that this module resides in + # + self.Package = Package + + def FromXml2(self, Item, Module): + if self.Module: + pass + # + # PeiDepex + # + PeiDepexList = [] + for SubItem in XmlList(Item, '/ModuleSurfaceArea/PeiDepex'): + Tmp = DepexXml() + Depex = Tmp.FromXml(XmlNode(SubItem, 'PeiDepex'), 'PeiDepex') + PeiDepexList.append(Depex) + Module.SetPeiDepex(PeiDepexList) + + # + # DxeDepex + # + DxeDepexList = [] + for SubItem in XmlList(Item, '/ModuleSurfaceArea/DxeDepex'): + Tmp = DepexXml() + Depex = Tmp.FromXml(XmlNode(SubItem, 'DxeDepex'), 'DxeDepex') + DxeDepexList.append(Depex) + Module.SetDxeDepex(DxeDepexList) + + # + # SmmDepex + # + SmmDepexList = [] + for SubItem in XmlList(Item, '/ModuleSurfaceArea/SmmDepex'): + Tmp = DepexXml() + Depex = Tmp.FromXml(XmlNode(SubItem, 'SmmDepex'), 'SmmDepex') + SmmDepexList.append(Depex) + Module.SetSmmDepex(SmmDepexList) + + # + # MiscellaneousFile + Tmp = MiscellaneousFileXml() + MiscFileList = Tmp.FromXml(XmlNode(Item, '/ModuleSurfaceArea/MiscellaneousFiles'), 'MiscellaneousFiles') + if MiscFileList: + Module.SetMiscFileList([MiscFileList]) + else: + Module.SetMiscFileList([]) + + # + # UserExtensions + # + for Item in XmlList(Item, '/ModuleSurfaceArea/UserExtensions'): + Tmp = UserExtensionsXml() + UserExtension = Tmp.FromXml(Item, 'UserExtensions') + Module.SetUserExtensionList(Module.GetUserExtensionList() + [UserExtension]) + + return Module + + def FromXml(self, Item, Key, IsStandAlongModule=False): + IsBinaryModule = XmlAttribute(Item, 'BinaryModule') + # + # Header + # + Tmp = HeaderXml() + Module = Tmp.FromXml(XmlNode(Item, '/%s/Header' % Key), 'Header', True, IsStandAlongModule) + Module.SetBinaryModule(IsBinaryModule) + + if IsBinaryModule: + GlobalData.gIS_BINARY_INF = True + + # + # ModuleProperties + # + Tmp = ModulePropertyXml() + (Module, BootModes, Events, HOBs) = \ + Tmp.FromXml(XmlNode(Item, '/ModuleSurfaceArea/ModuleProperties'), 'ModuleProperties', Module) + Module.SetBootModeList(BootModes) + Module.SetEventList(Events) + Module.SetHobList(HOBs) + # + # ClonedFrom + # + Tmp = ClonedFromXml() + ClonedFrom = Tmp.FromXml(XmlNode(Item, '/ModuleSurfaceArea/ClonedFrom'), 'ClonedFrom') + if ClonedFrom: + Module.SetClonedFrom(ClonedFrom) + + # + # LibraryClass + # + for SubItem in XmlList(Item, '/ModuleSurfaceArea/LibraryClassDefinitions/LibraryClass'): + Tmp = LibraryClassXml() + LibraryClass = Tmp.FromXml(SubItem, 'LibraryClass') + Module.SetLibraryClassList(Module.GetLibraryClassList() + [LibraryClass]) + + if XmlList(Item, '/ModuleSurfaceArea/LibraryClassDefinitions') and \ + not XmlList(Item, '/ModuleSurfaceArea/LibraryClassDefinitions/LibraryClass'): + Module.SetLibraryClassList([None]) + + # + # SourceFiles + # + for SubItem in XmlList(Item, '/ModuleSurfaceArea/SourceFiles/Filename'): + Tmp = SourceFileXml() + SourceFile = Tmp.FromXml(SubItem, 'Filename') + Module.SetSourceFileList(Module.GetSourceFileList() + [SourceFile]) + + if XmlList(Item, '/ModuleSurfaceArea/SourceFiles') and \ + not XmlList(Item, '/ModuleSurfaceArea/SourceFiles/Filename') : + Module.SetSourceFileList([None]) + + # + # BinaryFile + # + for SubItem in XmlList(Item, '/ModuleSurfaceArea/BinaryFiles/BinaryFile'): + Tmp = BinaryFileXml() + BinaryFile = Tmp.FromXml(SubItem, 'BinaryFile') + Module.SetBinaryFileList(Module.GetBinaryFileList() + [BinaryFile]) + + if XmlList(Item, '/ModuleSurfaceArea/BinaryFiles') and \ + not XmlList(Item, '/ModuleSurfaceArea/BinaryFiles/BinaryFile') : + Module.SetBinaryFileList([None]) + # + # PackageDependencies + # + for SubItem in XmlList(Item, '/ModuleSurfaceArea/PackageDependencies/Package'): + Tmp = PackageXml() + PackageDependency = Tmp.FromXml(SubItem, 'Package') + Module.SetPackageDependencyList(Module.GetPackageDependencyList() + [PackageDependency]) + + if XmlList(Item, '/ModuleSurfaceArea/PackageDependencies') and \ + not XmlList(Item, '/ModuleSurfaceArea/PackageDependencies/Package'): + Module.SetPackageDependencyList([None]) + + # + # Guid + # + for SubItem in XmlList(Item, '/ModuleSurfaceArea/Guids/GuidCName'): + Tmp = GuidXml('Module') + GuidProtocolPpi = Tmp.FromXml(SubItem, 'GuidCName') + Module.SetGuidList(Module.GetGuidList() + [GuidProtocolPpi]) + + if XmlList(Item, '/ModuleSurfaceArea/Guids') and not XmlList(Item, '/ModuleSurfaceArea/Guids/GuidCName'): + Module.SetGuidList([None]) + + # + # Protocol + # + for SubItem in XmlList(Item, '/ModuleSurfaceArea/Protocols/Protocol'): + Tmp = ProtocolXml('Module') + GuidProtocolPpi = Tmp.FromXml(SubItem, 'Protocol') + Module.SetProtocolList(Module.GetProtocolList() + [GuidProtocolPpi]) + + if XmlList(Item, '/ModuleSurfaceArea/Protocols') and not XmlList(Item, '/ModuleSurfaceArea/Protocols/Protocol'): + Module.SetProtocolList([None]) + + # + # Ppi + # + for SubItem in XmlList(Item, '/ModuleSurfaceArea/PPIs/Ppi'): + Tmp = PpiXml('Module') + GuidProtocolPpi = Tmp.FromXml(SubItem, 'Ppi') + Module.SetPpiList(Module.GetPpiList() + [GuidProtocolPpi]) + + if XmlList(Item, '/ModuleSurfaceArea/PPIs') and not XmlList(Item, '/ModuleSurfaceArea/PPIs/Ppi'): + Module.SetPpiList([None]) + + # + # Extern + # + for SubItem in XmlList(Item, '/ModuleSurfaceArea/Externs/Extern'): + Tmp = ExternXml() + Extern = Tmp.FromXml(SubItem, 'Extern') + Module.SetExternList(Module.GetExternList() + [Extern]) + + if XmlList(Item, '/ModuleSurfaceArea/Externs') and not XmlList(Item, '/ModuleSurfaceArea/Externs/Extern'): + Module.SetExternList([None]) + + if not Module.GetBinaryModule(): + # + # PcdCoded + # + for SubItem in XmlList(Item, '/ModuleSurfaceArea/PcdCoded/PcdEntry'): + Tmp = PcdEntryXml() + PcdEntry = Tmp.FromXml3(SubItem, 'PcdEntry') + Module.SetPcdList(Module.GetPcdList() + [PcdEntry]) + + if XmlList(Item, '/ModuleSurfaceArea/PcdCoded') and \ + not XmlList(Item, '/ModuleSurfaceArea/PcdCoded/PcdEntry'): + Module.SetPcdList([None]) + + Module = self.FromXml2(Item, Module) + # + # return the module object + # + self.Module = Module + return self.Module + + def ToXml(self, Module): + if self.Package: + pass + # + # Create root node of module surface area + # + DomModule = minidom.Document().createElement('ModuleSurfaceArea') + if Module.GetBinaryModule(): + DomModule.setAttribute('BinaryModule', 'true') + + # + # Header + # + Tmp = HeaderXml() + DomModule.appendChild(Tmp.ToXml(Module, 'Header')) + # + # ModuleProperties + # + Tmp = ModulePropertyXml() + DomModule.appendChild(Tmp.ToXml(Module, Module.GetBootModeList(), Module.GetEventList(), Module.GetHobList(), \ + 'ModuleProperties')) + # + # ClonedFrom + # + Tmp = ClonedFromXml() + if Module.GetClonedFrom(): + DomModule.appendChild(Tmp.ToXml(Module.GetClonedFrom(), 'ClonedFrom')) + # + # LibraryClass + # + LibraryClassNode = CreateXmlElement('LibraryClassDefinitions', '', [], []) + for LibraryClass in Module.GetLibraryClassList(): + Tmp = LibraryClassXml() + LibraryClassNode.appendChild(Tmp.ToXml2(LibraryClass, 'LibraryClass')) + DomModule.appendChild(LibraryClassNode) + # + # SourceFile + # + SourceFileNode = CreateXmlElement('SourceFiles', '', [], []) + for SourceFile in Module.GetSourceFileList(): + Tmp = SourceFileXml() + SourceFileNode.appendChild(Tmp.ToXml(SourceFile, 'Filename')) + DomModule.appendChild(SourceFileNode) + # + # BinaryFile + # + BinaryFileNode = CreateXmlElement('BinaryFiles', '', [], []) + for BinaryFile in Module.GetBinaryFileList(): + Tmp = BinaryFileXml() + BinaryFileNode.appendChild(Tmp.ToXml(BinaryFile, 'BinaryFile')) + DomModule.appendChild(BinaryFileNode) + # + # PackageDependencies + # + PackageDependencyNode = CreateXmlElement('PackageDependencies', '', [], []) + for PackageDependency in Module.GetPackageDependencyList(): + Tmp = PackageXml() + PackageDependencyNode.appendChild(Tmp.ToXml(PackageDependency, 'Package')) + DomModule.appendChild(PackageDependencyNode) + + # + # Guid + # + GuidProtocolPpiNode = CreateXmlElement('Guids', '', [], []) + for GuidProtocolPpi in Module.GetGuidList(): + Tmp = GuidXml('Module') + GuidProtocolPpiNode.appendChild(Tmp.ToXml(GuidProtocolPpi, 'GuidCName')) + DomModule.appendChild(GuidProtocolPpiNode) + + # + # Protocol + # + GuidProtocolPpiNode = CreateXmlElement('Protocols', '', [], []) + for GuidProtocolPpi in Module.GetProtocolList(): + Tmp = ProtocolXml('Module') + GuidProtocolPpiNode.appendChild(Tmp.ToXml(GuidProtocolPpi, 'Protocol')) + DomModule.appendChild(GuidProtocolPpiNode) + + # + # Ppi + # + GuidProtocolPpiNode = CreateXmlElement('PPIs', '', [], []) + for GuidProtocolPpi in Module.GetPpiList(): + Tmp = PpiXml('Module') + GuidProtocolPpiNode.appendChild(Tmp.ToXml(GuidProtocolPpi, 'Ppi')) + DomModule.appendChild(GuidProtocolPpiNode) + # + # Extern + # + ExternNode = CreateXmlElement('Externs', '', [], []) + for Extern in Module.GetExternList(): + Tmp = ExternXml() + ExternNode.appendChild(Tmp.ToXml(Extern, 'Extern')) + DomModule.appendChild(ExternNode) + # + # PcdCoded + # + PcdEntryNode = CreateXmlElement('PcdCoded', '', [], []) + for PcdEntry in Module.GetPcdList(): + Tmp = PcdEntryXml() + PcdEntryNode.appendChild(Tmp.ToXml3(PcdEntry, 'PcdEntry')) + DomModule.appendChild(PcdEntryNode) + + # + # PeiDepex + # + if Module.GetPeiDepex(): + for Item in Module.GetPeiDepex(): + Tmp = DepexXml() + DomModule.appendChild(Tmp.ToXml(Item, 'PeiDepex')) + + # + # DxeDepex + # + if Module.GetDxeDepex(): + for Item in Module.GetDxeDepex(): + Tmp = DepexXml() + DomModule.appendChild(Tmp.ToXml(Item, 'DxeDepex')) + + # + # SmmDepex + # + if Module.GetSmmDepex(): + for Item in Module.GetSmmDepex(): + Tmp = DepexXml() + DomModule.appendChild(Tmp.ToXml(Item, 'SmmDepex')) + + # + # MiscellaneousFile + # + if Module.GetMiscFileList(): + Tmp = MiscellaneousFileXml() + DomModule.appendChild(Tmp.ToXml(Module.GetMiscFileList()[0], 'MiscellaneousFiles')) + # + # UserExtensions + # + if Module.GetUserExtensionList(): + for UserExtension in Module.GetUserExtensionList(): + Tmp = UserExtensionsXml() + DomModule.appendChild(Tmp.ToXml(UserExtension, 'UserExtensions')) + + return DomModule + +## +# BuildFlagXml used to generate BuildFlag for +# +class BuildFlagXml(object): + def __init__(self): + self.Target = '' + self.TagName = '' + self.Family = '' + self.AsBuiltFlags = '' + + def FromXml(self, Item, Key): + self.Target = XmlElement(Item, '%s/Target' % Key) + self.TagName = XmlElement(Item, '%s/TagName' % Key) + self.Family = XmlElement(Item, '%s/Family' % Key) + + BuildFlag = BinaryBuildFlagObject() + + BuildFlag.SetTarget(self.Target) + BuildFlag.SetTagName(self.TagName) + BuildFlag.SetFamily(self.Family) + + return BuildFlag + + # + # For AsBuild INF usage + # + def FromXml2(self, Item, Key): + self.AsBuiltFlags = XmlElement(Item, '%s' % Key) + + LineList = GetSplitValueList(self.AsBuiltFlags, '\n') + ReturnLine = '' + Count = 0 + for Line in LineList: + if Count == 0: + ReturnLine = "# " + Line + else: + ReturnLine = ReturnLine + '\n' + '# ' + Line + Count += 1 + + BuildFlag = BinaryBuildFlagObject() + BuildFlag.SetAsBuiltOptionFlags(ReturnLine) + + return BuildFlag + + def ToXml(self, BuildFlag, Key): + if self.Target: + pass + AttributeList = [] + NodeList = [] + NodeList.append(['BuildFlags', BuildFlag]) + + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + return Root diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/PackageSurfaceAreaXml.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/PackageSurfaceAreaXml.py new file mode 100755 index 00000000..9cff02d3 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/PackageSurfaceAreaXml.py @@ -0,0 +1,402 @@ +## @file +# This file is used to parse a Package file of .PKG file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +PackageSurfaceAreaXml +''' +from xml.dom import minidom + +from Library.StringUtils import GetStringOfList +from Library.Xml.XmlRoutines import XmlElement +from Library.Xml.XmlRoutines import XmlNode +from Library.Xml.XmlRoutines import XmlList +from Library.Xml.XmlRoutines import CreateXmlElement +from Object.POM.CommonObject import IncludeObject +from Object.POM.CommonObject import TextObject +from Object.POM.PackageObject import PackageObject +from Xml.CommonXml import ClonedFromXml +from Xml.CommonXml import PackageHeaderXml +from Xml.CommonXml import HelpTextXml +from Xml.CommonXml import CommonDefinesXml +from Xml.CommonXml import LibraryClassXml +from Xml.CommonXml import UserExtensionsXml +from Xml.CommonXml import MiscellaneousFileXml +from Xml.GuidProtocolPpiXml import GuidXml +from Xml.GuidProtocolPpiXml import ProtocolXml +from Xml.GuidProtocolPpiXml import PpiXml +from Xml.ModuleSurfaceAreaXml import ModuleSurfaceAreaXml +from Xml.PcdXml import PcdEntryXml + +## +# IndustryStandardHeaderXml +# +class IndustryStandardHeaderXml(object): + def __init__(self): + self.HeaderFile = '' + self.HelpText = [] + + def FromXml(self, Item, Key): + self.HeaderFile = XmlElement(Item, '%s/HeaderFile' % Key) + for HelpTextItem in XmlList(Item, '%s/HelpText' % Key): + HelpTextObj = HelpTextXml() + HelpTextObj.FromXml(HelpTextItem, '%s/HelpText' % Key) + self.HelpText.append(HelpTextObj) + + Include = IncludeObject() + Include.SetFilePath(self.HeaderFile) + HelpTxt = TextObject() + HelpTxt.SetString(self.HelpText) + Include.SetHelpText(HelpTxt) + + return Include + + def ToXml(self, IndustryStandardHeader, Key): + if self.HeaderFile: + pass + AttributeList = [] + NodeList = [['HeaderFile', IndustryStandardHeader.GetFilePath()]] + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root + + def __str__(self): + Str = "HeaderFile = %s" % (self.HeaderFile) + for Item in self.HelpText: + Str = Str + "\n\t" + str(Item) + return Str +## +# PackageIncludeHeaderXml +# +class PackageIncludeHeaderXml(object): + def __init__(self): + self.HeaderFile = '' + self.CommonDefines = CommonDefinesXml() + self.HelpText = [] + + def FromXml(self, Item, Key): + self.HeaderFile = XmlElement(Item, '%s/HeaderFile' % Key) + self.CommonDefines.FromXml(XmlNode(Item, '%s/HeaderFile' % Key), 'HeaderFile') + for HelpTextItem in XmlList(Item, '%s/HelpText' % Key): + HelpTextObj = HelpTextXml() + HelpTextObj.FromXml(HelpTextItem, '%s/HelpText' % Key) + self.HelpText.append(HelpTextObj) + + Include = IncludeObject() + Include.SetFilePath(self.HeaderFile) + Include.SetSupArchList(self.CommonDefines.SupArchList) + HelpTxt = TextObject() + HelpTxt.SetString(self.HelpText) + Include.SetHelpText(HelpTxt) + + return Include + + def ToXml(self, PackageIncludeHeader, Key): + if self.HeaderFile: + pass + AttributeList = [['SupArchList', GetStringOfList(PackageIncludeHeader.GetSupArchList())], \ + ['SupModList', GetStringOfList(PackageIncludeHeader.GetSupModuleList())], ] + + HeaderFileNode = CreateXmlElement('HeaderFile', PackageIncludeHeader.FilePath, [], AttributeList) + + NodeList = [HeaderFileNode] + for Item in PackageIncludeHeader.GetHelpTextList(): + Tmp = HelpTextXml() + NodeList.append(Tmp.ToXml(Item)) + + Root = CreateXmlElement('%s' % Key, '', NodeList, []) + + return Root + + def __str__(self): + Str = "HeaderFile = %s\n\t%s" % (self.HeaderFile, self.CommonDefines) + for Item in self.HelpText: + Str = Str + "\n\t" + str(Item) + return Str + +## +# PcdCheckXml +# +class PcdCheckXml(object): + def __init__(self): + self.PcdCheck = '' + + def FromXml(self, Item, Key): + if Key: + pass + self.PcdCheck = XmlElement(Item, 'PcdCheck') + + return self.PcdCheck + + def ToXml(self, PcdCheck, Key): + if self.PcdCheck: + pass + Root = CreateXmlElement('%s' % Key, PcdCheck, [], []) + return Root + + def __str__(self): + return "PcdCheck = %s" % (self.PcdCheck) + +## +# PackageSurfaceAreaXml +# +class PackageSurfaceAreaXml(object): + def __init__(self): + self.Package = None + + def FromXml(self, Item, Key): + if Key: + pass + # + # Create a package object + # + Package = PackageObject() + # + # Header + # + Tmp = PackageHeaderXml() + Tmp.FromXml(XmlNode(Item, '/PackageSurfaceArea/Header'), 'Header', Package) + # + # ClonedFrom + # + Tmp = ClonedFromXml() + if XmlNode(Item, '/PackageSurfaceArea/ClonedFrom'): + ClonedFrom = Tmp.FromXml(XmlNode(Item, '/PackageSurfaceArea/ClonedFrom'), 'ClonedFrom') + Package.SetClonedFromList([ClonedFrom]) + # + # LibraryClass + # + + for SubItem in XmlList(Item, '/PackageSurfaceArea/LibraryClassDeclarations/LibraryClass'): + Tmp = LibraryClassXml() + LibraryClass = Tmp.FromXml(SubItem, 'LibraryClass') + Package.SetLibraryClassList(Package.GetLibraryClassList() + [LibraryClass]) + + if XmlList(Item, '/PackageSurfaceArea/LibraryClassDeclarations') and \ + not XmlList(Item, '/PackageSurfaceArea/LibraryClassDeclarations/LibraryClass'): + Package.SetLibraryClassList([None]) + + # + # IndustryStandardHeader + # + for SubItem in XmlList(Item, '/PackageSurfaceArea/IndustryStandardIncludes/IndustryStandardHeader'): + Tmp = IndustryStandardHeaderXml() + Include = Tmp.FromXml(SubItem, 'IndustryStandardHeader') + Package.SetStandardIncludeFileList(Package.GetStandardIncludeFileList() + [Include]) + + if XmlList(Item, '/PackageSurfaceArea/IndustryStandardIncludes') and \ + not XmlList(Item, '/PackageSurfaceArea/IndustryStandardIncludes/IndustryStandardHeader'): + Package.SetStandardIncludeFileList([None]) + + + # + # PackageHeader + # + for SubItem in XmlList(Item, '/PackageSurfaceArea/PackageIncludes/PackageHeader'): + Tmp = PackageIncludeHeaderXml() + Include = Tmp.FromXml(SubItem, 'PackageHeader') + Package.SetPackageIncludeFileList(Package.GetPackageIncludeFileList() + [Include]) + + if XmlList(Item, '/PackageSurfaceArea/PackageIncludes') and not \ + XmlList(Item, '/PackageSurfaceArea/PackageIncludes/PackageHeader'): + Package.SetPackageIncludeFileList([None]) + + # + # Guid + # + for SubItem in XmlList(Item, '/PackageSurfaceArea/GuidDeclarations/Entry'): + Tmp = GuidXml('Package') + GuidProtocolPpi = Tmp.FromXml(SubItem, 'Entry') + Package.SetGuidList(Package.GetGuidList() + [GuidProtocolPpi]) + + if XmlList(Item, '/PackageSurfaceArea/GuidDeclarations') and not \ + XmlList(Item, '/PackageSurfaceArea/GuidDeclarations/Entry'): + Package.SetGuidList([None]) + + # + # Protocol + # + for SubItem in XmlList(Item, '/PackageSurfaceArea/ProtocolDeclarations/Entry'): + Tmp = ProtocolXml('Package') + GuidProtocolPpi = Tmp.FromXml(SubItem, 'Entry') + Package.SetProtocolList(Package.GetProtocolList() + [GuidProtocolPpi]) + + if XmlList(Item, '/PackageSurfaceArea/ProtocolDeclarations') and not \ + XmlList(Item, '/PackageSurfaceArea/ProtocolDeclarations/Entry'): + Package.SetProtocolList([None]) + + # + # Ppi + # + for SubItem in XmlList(Item, '/PackageSurfaceArea/PpiDeclarations/Entry'): + Tmp = PpiXml('Package') + GuidProtocolPpi = Tmp.FromXml(SubItem, 'Entry') + Package.SetPpiList(Package.GetPpiList() + [GuidProtocolPpi]) + + if XmlList(Item, '/PackageSurfaceArea/PpiDeclarations') and not \ + XmlList(Item, '/PackageSurfaceArea/PpiDeclarations/Entry'): + Package.SetPpiList([None]) + + # + # PcdEntry + # + for SubItem in XmlList(Item, '/PackageSurfaceArea/PcdDeclarations/PcdEntry'): + Tmp = PcdEntryXml() + PcdEntry = Tmp.FromXml2(SubItem, 'PcdEntry') + Package.SetPcdList(Package.GetPcdList() + [PcdEntry]) + + # + # Get PcdErrorCommentDict from PcdError in PcdEntry Node + # + for PcdErrorObj in PcdEntry.GetPcdErrorsList(): + PcdErrorMessageList = PcdErrorObj.GetErrorMessageList() + if PcdErrorMessageList: + Package.PcdErrorCommentDict[(PcdEntry.GetTokenSpaceGuidCName(), PcdErrorObj.GetErrorNumber())] = \ + PcdErrorMessageList + + + if XmlList(Item, '/PackageSurfaceArea/PcdDeclarations') and not \ + XmlList(Item, '/PackageSurfaceArea/PcdDeclarations/PcdEntry'): + Package.SetPcdList([None]) + + # + # PcdCheck + # + for SubItem in XmlList(Item, '/PackageSurfaceArea/PcdRelationshipChecks/PcdCheck'): + Tmp = PcdCheckXml() + PcdCheck = Tmp.FromXml(SubItem, 'PcdCheck') + Package.PcdChecks.append(PcdCheck) + + # + # Modules + # + for SubItem in XmlList(Item, '/PackageSurfaceArea/Modules/ModuleSurfaceArea'): + Tmp = ModuleSurfaceAreaXml() + Module = Tmp.FromXml(SubItem, 'ModuleSurfaceArea') + ModuleDictKey = (Module.GetGuid(), Module.GetVersion(), Module.GetName(), Module.GetModulePath()) + Package.ModuleDict[ModuleDictKey] = Module + # + # MiscellaneousFile + # + Tmp = MiscellaneousFileXml() + MiscFileList = Tmp.FromXml(XmlNode(Item, '/PackageSurfaceArea/MiscellaneousFiles'), 'MiscellaneousFiles') + if MiscFileList: + Package.SetMiscFileList([MiscFileList]) + else: + Package.SetMiscFileList([]) + + # + # UserExtensions + # + for Item in XmlList(Item, '/PackageSurfaceArea/UserExtensions'): + Tmp = UserExtensionsXml() + UserExtension = Tmp.FromXml(Item, 'UserExtensions') + Package.UserExtensionList.append(UserExtension) + + self.Package = Package + return self.Package + + def ToXml(self, Package): + if self.Package: + pass + # + # Create PackageSurfaceArea node + # + DomPackage = minidom.Document().createElement('PackageSurfaceArea') + # + # Header + # + Tmp = PackageHeaderXml() + DomPackage.appendChild(Tmp.ToXml(Package, 'Header')) + # + # ClonedFrom + # + Tmp = ClonedFromXml() + if Package.GetClonedFromList() != []: + DomPackage.appendChild(Tmp.ToXml(Package.GetClonedFromList[0], 'ClonedFrom')) + # + # LibraryClass + # + LibraryClassNode = CreateXmlElement('LibraryClassDeclarations', '', [], []) + for LibraryClass in Package.GetLibraryClassList(): + Tmp = LibraryClassXml() + LibraryClassNode.appendChild(Tmp.ToXml(LibraryClass, 'LibraryClass')) + DomPackage.appendChild(LibraryClassNode) + # + # IndustryStandardHeader + # + IndustryStandardHeaderNode = CreateXmlElement('IndustryStandardIncludes', '', [], []) + for Include in Package.GetStandardIncludeFileList(): + Tmp = IndustryStandardHeaderXml() + IndustryStandardHeaderNode.appendChild(Tmp.ToXml(Include, 'IndustryStandardHeader')) + DomPackage.appendChild(IndustryStandardHeaderNode) + # + # PackageHeader + # + PackageIncludeHeaderNode = CreateXmlElement('PackageIncludes', '', [], []) + for Include in Package.GetPackageIncludeFileList(): + Tmp = PackageIncludeHeaderXml() + PackageIncludeHeaderNode.appendChild(Tmp.ToXml(Include, 'PackageHeader')) + DomPackage.appendChild(PackageIncludeHeaderNode) + ModuleNode = CreateXmlElement('Modules', '', [], []) + for Module in Package.GetModuleDict().values(): + Tmp = ModuleSurfaceAreaXml() + ModuleNode.appendChild(Tmp.ToXml(Module)) + DomPackage.appendChild(ModuleNode) + # + # Guid + # + GuidProtocolPpiNode = CreateXmlElement('GuidDeclarations', '', [], []) + for GuidProtocolPpi in Package.GetGuidList(): + Tmp = GuidXml('Package') + GuidProtocolPpiNode.appendChild(Tmp.ToXml\ + (GuidProtocolPpi, 'Entry')) + DomPackage.appendChild(GuidProtocolPpiNode) + # + # Protocol + # + GuidProtocolPpiNode = \ + CreateXmlElement('ProtocolDeclarations', '', [], []) + for GuidProtocolPpi in Package.GetProtocolList(): + Tmp = ProtocolXml('Package') + GuidProtocolPpiNode.appendChild\ + (Tmp.ToXml(GuidProtocolPpi, 'Entry')) + DomPackage.appendChild(GuidProtocolPpiNode) + # + # Ppi + # + GuidProtocolPpiNode = CreateXmlElement('PpiDeclarations', '', [], []) + for GuidProtocolPpi in Package.GetPpiList(): + Tmp = PpiXml('Package') + GuidProtocolPpiNode.appendChild\ + (Tmp.ToXml(GuidProtocolPpi, 'Entry')) + DomPackage.appendChild(GuidProtocolPpiNode) + # + # PcdEntry + # + PcdEntryNode = CreateXmlElement('PcdDeclarations', '', [], []) + for PcdEntry in Package.GetPcdList(): + Tmp = PcdEntryXml() + PcdEntryNode.appendChild(Tmp.ToXml2(PcdEntry, 'PcdEntry')) + DomPackage.appendChild(PcdEntryNode) + + # + # MiscellaneousFile + # + Tmp = MiscellaneousFileXml() + if Package.GetMiscFileList(): + DomPackage.appendChild(Tmp.ToXml(Package.GetMiscFileList()[0], 'MiscellaneousFiles')) + + # + # UserExtensions + # + if Package.GetUserExtensionList(): + for UserExtension in Package.GetUserExtensionList(): + Tmp = UserExtensionsXml() + DomPackage.appendChild(Tmp.ToXml(UserExtension, 'UserExtensions')) + + return DomPackage diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/PcdXml.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/PcdXml.py new file mode 100755 index 00000000..3fa0766a --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/PcdXml.py @@ -0,0 +1,555 @@ +## @file +# This file is used to parse a PCD file of .PKG file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +PcdXml +''' + +## +# Import Modules +# + +from Library.Xml.XmlRoutines import XmlElement +from Library.Xml.XmlRoutines import XmlAttribute +from Library.Xml.XmlRoutines import XmlNode +from Library.Xml.XmlRoutines import CreateXmlElement +from Library.Xml.XmlRoutines import XmlList +from Library.StringUtils import GetStringOfList +from Library.StringUtils import ConvertNEToNOTEQ +from Library.StringUtils import ConvertNOTEQToNE +from Library import GlobalData +from Object.POM.CommonObject import PcdObject +from Object.POM.CommonObject import PcdErrorObject +from Xml.CommonXml import HelpTextXml +from Xml.CommonXml import PromptXml +from Xml.CommonXml import CommonDefinesXml +from Xml.XmlParserMisc import GetHelpTextList +from Xml.XmlParserMisc import GetPromptList +import re + +## +# PcdErrorXml +# +class PcdErrorXml(object): + def __init__(self): + self.ValidValueList = '' + self.ValidValueListLang = '' + self.ValidValueRange = '' + self.Expression = '' + self.ErrorNumber = '' + self.ErrorMessage = [] + + def FromXml(self, Item, Key): + self.ValidValueList = XmlElement(Item, '%s/ValidValueList' % Key) + self.ValidValueListLang = \ + XmlAttribute(XmlNode(Item, '%s/ValidValueList' % Key), 'Lang') + self.ValidValueRange = self.TransferValidEpxr2ValidRange(XmlElement(Item, '%s/ValidValueRange' % Key)) + self.Expression = XmlElement(Item, '%s/Expression' % Key) + self.ErrorNumber = XmlElement(Item, '%s/ErrorNumber' % Key) + for ErrMsg in XmlList(Item, '%s/ErrorMessage' % Key): + ErrorMessageString = XmlElement(ErrMsg, 'ErrorMessage') + ErrorMessageLang = \ + XmlAttribute(XmlNode(ErrMsg, 'ErrorMessage'), 'Lang') + self.ErrorMessage.append((ErrorMessageLang, ErrorMessageString)) + + Error = PcdErrorObject() + Error.SetValidValue(self.ValidValueList) + Error.SetValidValueLang(self.ValidValueListLang) + Error.SetValidValueRange(self.ValidValueRange) + Error.SetExpression(self.Expression) + Error.SetErrorNumber(self.ErrorNumber) + Error.SetErrorMessageList(self.ErrorMessage) + + return Error + + def ToXml(self, PcdError, Key): + if self.Expression: + pass + AttributeList = [] + NodeList = [] + if PcdError.GetValidValue(): + Element1 = \ + CreateXmlElement('ValidValueList', PcdError.GetValidValue(), [], \ + [['Lang', PcdError.GetValidValueLang()]]) + NodeList.append(Element1) + if PcdError.GetValidValueRange(): + TansferedRangeStr = self.TransferValidRange2Expr(PcdError.GetTokenSpaceGuidCName(), + PcdError.GetCName(), + PcdError.GetValidValueRange()) + Element1 = \ + CreateXmlElement('ValidValueRange', \ + TansferedRangeStr, [], []) + NodeList.append(Element1) + if PcdError.GetExpression(): + NodeList.append(['Expression', PcdError.GetExpression()]) + if PcdError.GetErrorNumber(): + NodeList.append(['ErrorNumber', PcdError.GetErrorNumber()]) + for Item in PcdError.GetErrorMessageList(): + Element = \ + CreateXmlElement('ErrorMessage', Item[1], [], [['Lang', Item[0]]]) + NodeList.append(Element) + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root + + def TransferValidRange2Expr(self, TokenSpaceGuidCName, CName, ValidRange): + if self.Expression: + pass + INT_RANGE_PATTERN1 = '[\t\s]*[0-9]+[\t\s]*-[\t\s]*[0-9]+' + INT_RANGE_PATTERN2 = '[\t\s]*(LT|GT|LE|GE|XOR|EQ)[\t\s]+\d+[\t\s]*' + HEX_RANGE_PATTERN1 = \ + '[\t\s]*0[xX][a-fA-F0-9]+[\t\s]*-[\t\s]*0[xX][a-fA-F0-9]+' + HEX_RANGE_PATTERN2 = '[\t\s]*(LT|GT|LE|GE|XOR|EQ)[\t\s]+0[xX][a-fA-F0-9]+[\t\s]*' + IntMatch1 = re.compile(INT_RANGE_PATTERN1) + IntMatch2 = re.compile(INT_RANGE_PATTERN2) + HexMatch1 = re.compile(HEX_RANGE_PATTERN1) + HexMatch2 = re.compile(HEX_RANGE_PATTERN2) + PcdName = '.'.join([TokenSpaceGuidCName, CName]) + HexMatchedList = [] + IntMatchedList = [] + # + # Convert HEX2 format range + # + if HexMatch2: + for MatchObj in HexMatch2.finditer(ValidRange): + MatchStr = MatchObj.group() + TransferedRangeStr = ' '.join(['', PcdName, MatchStr.strip()]) + ValidRange = ValidRange.replace(MatchStr, TransferedRangeStr) + # + # Convert INT2 format range + # + if IntMatch2: + for MatchObj in IntMatch2.finditer(ValidRange): + MatchStr = MatchObj.group() + TransferedRangeStr = ' '.join(['', PcdName, MatchStr.strip()]) + ValidRange = ValidRange.replace(MatchStr, TransferedRangeStr) + # + # Convert HEX1 format range + # + if HexMatch1: + HexMatchedList += HexMatch1.findall(ValidRange) + + for MatchStr in HexMatchedList: + RangeItemList = MatchStr.strip().split('-') + TransferedRangeStr = '(%s GE %s) AND (%s LE %s)' % \ + (PcdName, RangeItemList[0].strip(), PcdName, RangeItemList[1].strip()) + ValidRange = ValidRange.replace(MatchStr, TransferedRangeStr) + # + # Convert INT1 format range + # + if IntMatch1: + IntMatchedList += IntMatch1.findall(ValidRange) + + for MatchStr in IntMatchedList: + RangeItemList = MatchStr.strip().split('-') + TransferedRangeStr = '(%s GE %s) AND (%s LE %s)' % \ + (PcdName, RangeItemList[0].strip(), PcdName, RangeItemList[1].strip()) + ValidRange = ValidRange.replace(MatchStr, TransferedRangeStr) + + return ValidRange + + def TransferValidEpxr2ValidRange(self, ValidRangeExpr): + if self.Expression: + pass + + PCD_PATTERN = \ + '[\t\s]*[_a-zA-Z][a-zA-Z0-9_]*[\t\s]*\.[\t\s]*[_a-zA-Z][a-zA-Z0-9_]*[\t\s]*' + IntPattern1 = \ + '[\t\s]*\([\t\s]*'+PCD_PATTERN+'[\t\s]+GE[\t\s]+\d+[\t\s]*\)[\t\s]+AND[\t\s]+\([\t\s]*'+\ + PCD_PATTERN+'[\t\s]+LE[\t\s]+\d+[\t\s]*\)' + IntPattern1 = IntPattern1.replace(' ', '') + IntPattern2 = '[\t\s]*'+PCD_PATTERN+'[\t\s]+(LT|GT|LE|GE|XOR|EQ)[\t\s]+\d+[\t\s]*' + + HexPattern1 = \ + '[\t\s]*\([\t\s]*'+PCD_PATTERN+'[\t\s]+GE[\t\s]+0[xX][0-9a-fA-F]+[\t\s]*\)[\t\s]+AND[\t\s]+\([\t\s]*'+\ + PCD_PATTERN+'[\t\s]+LE[\t\s]+0[xX][0-9a-fA-F]+[\t\s]*\)' + HexPattern1 = HexPattern1.replace(' ', '') + HexPattern2 = '[\t\s]*'+PCD_PATTERN+'[\t\s]+(LT|GT|LE|GE|XOR|EQ)[\t\s]+0[xX][0-9a-zA-Z]+[\t\s]*' + + # + # Do the Hex1 conversion + # + HexMatchedList = re.compile(HexPattern1).findall(ValidRangeExpr) + HexRangeDict = {} + for HexMatchedItem in HexMatchedList: + # + # To match items on both sides of '-' + # + RangeItemList = re.compile('[\t\s]*0[xX][0-9a-fA-F]+[\t\s]*').findall(HexMatchedItem) + if RangeItemList and len(RangeItemList) == 2: + HexRangeDict[HexMatchedItem] = RangeItemList + + for Key in HexRangeDict.keys(): + MaxItem = MixItem = '' + if int(HexRangeDict[Key][0], 16) > int(HexRangeDict[Key][1], 16): + MaxItem = HexRangeDict[Key][0] + MixItem = HexRangeDict[Key][1] + else: + MaxItem = HexRangeDict[Key][1] + MixItem = HexRangeDict[Key][0] + + Range = ' %s - %s' % (MixItem.strip(), MaxItem.strip()) + ValidRangeExpr = ValidRangeExpr.replace(Key, Range) + # + # Do the INT1 conversion + # + IntRangeDict = {} + IntMatchList = re.compile(IntPattern1).findall(ValidRangeExpr) + for MatchedItem in IntMatchList: + # + # To match items on both sides of '-' + # + RangeItemList = re.compile('[\t\s]*\d+[\t\s]*').findall(MatchedItem) + if RangeItemList and len(RangeItemList) == 2: + IntRangeDict[MatchedItem] = RangeItemList + + for Key in IntRangeDict.keys(): + MaxItem = MixItem = '' + if int(IntRangeDict[Key][0]) > int(IntRangeDict[Key][1]): + MaxItem = IntRangeDict[Key][0] + MixItem = IntRangeDict[Key][1] + else: + MaxItem = IntRangeDict[Key][1] + MixItem = IntRangeDict[Key][0] + + Range = ' %s - %s' % (MixItem.strip(), MaxItem.strip()) + ValidRangeExpr = ValidRangeExpr.replace(Key, Range) + # + # Do the HEX2 conversion + # + for MatchObj in re.compile(HexPattern2).finditer(ValidRangeExpr): + MatchStr = MatchObj.group() + Range = re.compile(PCD_PATTERN).sub(' ', MatchStr) + ValidRangeExpr = ValidRangeExpr.replace(MatchStr, Range) + # + # Do the INT2 conversion + # + for MatchObj in re.compile(IntPattern2).finditer(ValidRangeExpr): + MatchStr = MatchObj.group() + Range = re.compile(PCD_PATTERN).sub(' ', MatchStr) + ValidRangeExpr = ValidRangeExpr.replace(MatchStr, Range) + + return ValidRangeExpr + + + + def __str__(self): + return "ValidValueList = %s ValidValueListLang = %s ValidValueRange \ + = %s Expression = %s ErrorNumber = %s %s" % \ + (self.ValidValueList, self.ValidValueListLang, self.ValidValueRange, \ + self.Expression, self.ErrorNumber, self.ErrorMessage) + +## +# PcdEntryXml +# +class PcdEntryXml(object): + def __init__(self): + self.PcdItemType = '' + self.PcdUsage = '' + self.TokenSpaceGuidCName = '' + self.TokenSpaceGuidValue = '' + self.Token = '' + self.CName = '' + self.PcdCName = '' + self.DatumType = '' + self.ValidUsage = '' + self.DefaultValue = '' + self.MaxDatumSize = '' + self.Value = '' + self.Offset = '' + self.CommonDefines = CommonDefinesXml() + self.Prompt = [] + self.HelpText = [] + self.PcdError = [] + + ## + # AsBuilt will use FromXml + # + def FromXml(self, Item, Key): + self.PcdItemType = \ + XmlAttribute(XmlNode(Item, '%s' % Key), 'PcdItemType') + self.PcdUsage = XmlAttribute(XmlNode(Item, '%s' % Key), 'PcdUsage') + self.TokenSpaceGuidCName = \ + XmlElement(Item, '%s/TokenSpaceGuidCname' % Key) + self.TokenSpaceGuidValue = \ + XmlElement(Item, '%s/TokenSpaceGuidValue' % Key) + self.Token = XmlElement(Item, '%s/Token' % Key) + self.CName = XmlElement(Item, '%s/CName' % Key) + self.PcdCName = XmlElement(Item, '%s/PcdCName' % Key) + self.DatumType = XmlElement(Item, '%s/DatumType' % Key) + self.ValidUsage = XmlElement(Item, '%s/ValidUsage' % Key) + if not GlobalData.gIS_BINARY_INF: + self.DefaultValue = XmlElement(Item, '%s/DefaultValue' % Key) + else: + self.DefaultValue = XmlElement(Item, '%s/Value' % Key) + self.MaxDatumSize = XmlElement(Item, '%s/MaxDatumSize' % Key) + self.Value = XmlElement(Item, '%s/Value' % Key) + self.Offset = XmlElement(Item, '%s/Offset' % Key) + self.CommonDefines.FromXml(XmlNode(Item, '%s' % Key), Key) + + for HelpTextItem in XmlList(Item, '%s/HelpText' % Key): + HelpTextObj = HelpTextXml() + HelpTextObj.FromXml(HelpTextItem, '%s/HelpText' % Key) + self.HelpText.append(HelpTextObj) + for PcdErrorItem in XmlList(Item, '%s/PcdError' % Key): + PcdErrorObjXml = PcdErrorXml() + PcdErrorObj = PcdErrorObjXml.FromXml(PcdErrorItem, 'PcdError') + self.PcdError.append(PcdErrorObj) + + self.DefaultValue = ConvertNOTEQToNE(self.DefaultValue) + + PcdEntry = PcdObject() + PcdEntry.SetSupArchList(self.CommonDefines.SupArchList) + PcdEntry.SetTokenSpaceGuidCName(self.TokenSpaceGuidCName) + PcdEntry.SetTokenSpaceGuidValue(self.TokenSpaceGuidValue) + PcdEntry.SetToken(self.Token) + PcdEntry.SetOffset(self.Offset) + PcdEntry.SetCName(self.CName) + PcdEntry.SetPcdCName(self.PcdCName) + PcdEntry.SetDatumType(self.DatumType) + PcdEntry.SetValidUsage(self.ValidUsage) + PcdEntry.SetDefaultValue(self.DefaultValue) + PcdEntry.SetMaxDatumSize(self.MaxDatumSize) + PcdEntry.SetFeatureFlag(ConvertNOTEQToNE(self.CommonDefines.FeatureFlag)) + PcdEntry.SetItemType(self.PcdItemType) + + PcdEntry.SetHelpTextList(GetHelpTextList(self.HelpText)) + PcdEntry.SetPcdErrorsList(self.PcdError) + + return PcdEntry + ## + # Package will use FromXml2 + # + def FromXml2(self, Item, Key): + self.TokenSpaceGuidCName = \ + XmlElement(Item, '%s/TokenSpaceGuidCname' % Key) + self.Token = XmlElement(Item, '%s/Token' % Key) + self.CName = XmlElement(Item, '%s/CName' % Key) + self.DatumType = XmlElement(Item, '%s/DatumType' % Key) + self.ValidUsage = XmlElement(Item, '%s/ValidUsage' % Key) + self.DefaultValue = XmlElement(Item, '%s/DefaultValue' % Key) + self.MaxDatumSize = XmlElement(Item, '%s/MaxDatumSize' % Key) + self.CommonDefines.FromXml(XmlNode(Item, '%s' % Key), Key) + for PromptItem in XmlList(Item, '%s/Prompt' % Key): + PromptObj = PromptXml() + PromptObj.FromXml(PromptItem, '%s/Prompt' % Key) + self.Prompt.append(PromptObj) + for HelpTextItem in XmlList(Item, '%s/HelpText' % Key): + HelpTextObj = HelpTextXml() + HelpTextObj.FromXml(HelpTextItem, '%s/HelpText' % Key) + self.HelpText.append(HelpTextObj) + for PcdErrorItem in XmlList(Item, '%s/PcdError' % Key): + PcdErrorObjXml = PcdErrorXml() + PcdErrorObj = PcdErrorObjXml.FromXml(PcdErrorItem, 'PcdError') + self.PcdError.append(PcdErrorObj) + + self.DefaultValue = ConvertNOTEQToNE(self.DefaultValue) + + PcdEntry = PcdObject() + PcdEntry.SetSupArchList(self.CommonDefines.SupArchList) + PcdEntry.SetSupModuleList(self.CommonDefines.SupModList) + PcdEntry.SetTokenSpaceGuidCName(self.TokenSpaceGuidCName) + PcdEntry.SetToken(self.Token) + PcdEntry.SetCName(self.CName) + PcdEntry.SetDatumType(self.DatumType) + PcdEntry.SetValidUsage(self.ValidUsage) + PcdEntry.SetDefaultValue(self.DefaultValue) + PcdEntry.SetMaxDatumSize(self.MaxDatumSize) + PcdEntry.SetFeatureFlag(ConvertNOTEQToNE(self.CommonDefines.FeatureFlag)) + + PcdEntry.SetPromptList(GetPromptList(self.Prompt)) + PcdEntry.SetHelpTextList(GetHelpTextList(self.HelpText)) + PcdEntry.SetPcdErrorsList(self.PcdError) + + return PcdEntry + + ## + # Module will use FromXml3 + # + def FromXml3(self, Item, Key): + self.PcdItemType = \ + XmlAttribute(XmlNode(Item, '%s' % Key), 'PcdItemType') + self.PcdUsage = XmlAttribute(XmlNode(Item, '%s' % Key), 'PcdUsage') + self.TokenSpaceGuidCName = \ + XmlElement(Item, '%s/TokenSpaceGuidCName' % Key) + self.CName = XmlElement(Item, '%s/CName' % Key) + self.DefaultValue = XmlElement(Item, '%s/DefaultValue' % Key) + self.CommonDefines.FromXml(XmlNode(Item, '%s' % Key), Key) + for HelpTextItem in XmlList(Item, '%s/HelpText' % Key): + HelpTextObj = HelpTextXml() + HelpTextObj.FromXml(HelpTextItem, '%s/HelpText' % Key) + self.HelpText.append(HelpTextObj) + for PcdErrorItem in XmlList(Item, '%s/PcdError' % Key): + PcdErrorObj = PcdErrorXml() + PcdErrorObj.FromXml(PcdErrorItem, 'PcdError') + self.PcdError.append(PcdErrorObj) + + self.DefaultValue = ConvertNOTEQToNE(self.DefaultValue) + + PcdEntry = PcdObject() + PcdEntry.SetSupArchList(self.CommonDefines.SupArchList) + PcdEntry.SetTokenSpaceGuidCName(self.TokenSpaceGuidCName) + PcdEntry.SetCName(self.CName) + PcdEntry.SetValidUsage(self.PcdUsage) + PcdEntry.SetDefaultValue(self.DefaultValue) + PcdEntry.SetFeatureFlag(ConvertNOTEQToNE(self.CommonDefines.FeatureFlag)) + PcdEntry.SetItemType(self.PcdItemType) + + PcdEntry.SetHelpTextList(GetHelpTextList(self.HelpText)) + PcdEntry.SetPcdErrorsList(self.PcdError) + + return PcdEntry + + def ToXml(self, PcdEntry, Key): + if self.PcdCName: + pass + + DefaultValue = ConvertNEToNOTEQ(PcdEntry.GetDefaultValue()) + + AttributeList = \ + [['SupArchList', GetStringOfList(PcdEntry.GetSupArchList())], \ + ['PcdUsage', PcdEntry.GetValidUsage()], \ + ['PcdItemType', PcdEntry.GetItemType()], \ + ['FeatureFlag', PcdEntry.GetFeatureFlag()], + ] + NodeList = [['TokenSpaceGuidCname', PcdEntry.GetTokenSpaceGuidCName()], + ['TokenSpaceGuidValue', PcdEntry.GetTokenSpaceGuidValue()], + ['Token', PcdEntry.GetToken()], + ['CName', PcdEntry.GetCName()], + ['DatumType', PcdEntry.GetDatumType()], + ['ValidUsage', GetStringOfList(PcdEntry.GetValidUsage())], + ['DefaultValue', DefaultValue], + ['MaxDatumSize', PcdEntry.GetMaxDatumSize()], + ['Offset', PcdEntry.GetOffset()], + ] + + for Item in PcdEntry.GetHelpTextList(): + Tmp = HelpTextXml() + NodeList.append(Tmp.ToXml(Item)) + for Item in PcdEntry.GetPcdErrorsList(): + Tmp = PcdErrorXml() + NodeList.append(Tmp.ToXml(Item, 'PcdError')) + + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root + ## + # Package will use ToXml2 + # + def ToXml2(self, PcdEntry, Key): + if self.PcdCName: + pass + + DefaultValue = ConvertNEToNOTEQ(PcdEntry.GetDefaultValue()) + + AttributeList = \ + [['SupArchList', GetStringOfList(PcdEntry.GetSupArchList())], \ + ['SupModList', GetStringOfList(PcdEntry.GetSupModuleList())] + ] + NodeList = [['TokenSpaceGuidCname', PcdEntry.GetTokenSpaceGuidCName()], + ['Token', PcdEntry.GetToken()], + ['CName', PcdEntry.GetCName()], + ['DatumType', PcdEntry.GetDatumType()], + ['ValidUsage', GetStringOfList(PcdEntry.GetValidUsage())], + ['DefaultValue', DefaultValue], + ['MaxDatumSize', PcdEntry.GetMaxDatumSize()], + ] + for Item in PcdEntry.GetPromptList(): + Tmp = PromptXml() + NodeList.append(Tmp.ToXml(Item)) + + for Item in PcdEntry.GetHelpTextList(): + Tmp = HelpTextXml() + NodeList.append(Tmp.ToXml(Item)) + + for Item in PcdEntry.GetPcdErrorsList(): + Tmp = PcdErrorXml() + NodeList.append(Tmp.ToXml(Item, 'PcdError')) + + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root + ## + # Module will use ToXml3 + # + def ToXml3(self, PcdEntry, Key): + if self.PcdCName: + pass + + DefaultValue = ConvertNEToNOTEQ(PcdEntry.GetDefaultValue()) + + AttributeList = \ + [['SupArchList', GetStringOfList(PcdEntry.GetSupArchList())], \ + ['PcdUsage', PcdEntry.GetValidUsage()], \ + ['PcdItemType', PcdEntry.GetItemType()], \ + ['FeatureFlag', ConvertNEToNOTEQ(PcdEntry.GetFeatureFlag())], + ] + NodeList = [['CName', PcdEntry.GetCName()], + ['TokenSpaceGuidCName', PcdEntry.GetTokenSpaceGuidCName()], + ['DefaultValue', DefaultValue], + ] + + for Item in PcdEntry.GetHelpTextList(): + Tmp = HelpTextXml() + NodeList.append(Tmp.ToXml(Item)) + for Item in PcdEntry.GetPcdErrorsList(): + Tmp = PcdErrorXml() + NodeList.append(Tmp.ToXml(Item, 'PcdError')) + + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root + + ## + # AsBuild Module will use ToXml4 + # + def ToXml4(self, PcdEntry, Key): + if self.PcdCName: + pass + + DefaultValue = ConvertNEToNOTEQ(PcdEntry.GetDefaultValue()) + + AttributeList = [] + + NodeList = [ + ['TokenSpaceGuidValue', PcdEntry.GetTokenSpaceGuidValue()], + ['PcdCName', PcdEntry.GetCName()], + ['Token', PcdEntry.GetToken()], + ['DatumType', PcdEntry.GetDatumType()], + ['MaxDatumSize', PcdEntry.GetMaxDatumSize()], + ['Value', DefaultValue], + ['Offset', PcdEntry.GetOffset()] + ] + + for Item in PcdEntry.GetHelpTextList(): + Tmp = HelpTextXml() + NodeList.append(Tmp.ToXml(Item)) + for Item in PcdEntry.GetPcdErrorsList(): + Tmp = PcdErrorXml() + NodeList.append(Tmp.ToXml(Item, 'PcdError')) + + Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList) + + return Root + + + def __str__(self): + Str = \ + ('PcdItemType = %s PcdUsage = %s TokenSpaceGuidCName = %s \ + TokenSpaceGuidValue = %s Token = %s CName = %s PcdCName = %s \ + DatumType = %s ValidUsage = %s DefaultValue = %s MaxDatumSize = %s \ + Value = %s Offset = %s %s') % \ + (self.PcdItemType, self.PcdUsage, self.TokenSpaceGuidCName, \ + self.TokenSpaceGuidValue, self.Token, self.CName, self.PcdCName, \ + self.DatumType, self.ValidUsage, self.DefaultValue, \ + self.MaxDatumSize, self.Value, self.Offset, self.CommonDefines) + for Item in self.HelpText: + Str = Str + "\n\t" + str(Item) + for Item in self.PcdError: + Str = Str + "\n\tPcdError:" + str(Item) + return Str diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/XmlParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/XmlParser.py new file mode 100755 index 00000000..a252bf52 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/XmlParser.py @@ -0,0 +1,926 @@ +## @file +# This file is used to parse a xml file of .PKG file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +XmlParser +''' + +## +# Import Modules +# +import re + +from Library.Xml.XmlRoutines import XmlNode +from Library.Xml.XmlRoutines import CreateXmlElement +from Library.Xml.XmlRoutines import XmlList +from Library.Xml.XmlRoutines import XmlParseFile +from Core.DistributionPackageClass import DistributionPackageClass +from Object.POM.ModuleObject import DepexObject +from Library.ParserValidate import IsValidInfMoudleType +from Library.ParserValidate import IsValidInstallPath +from Library.Misc import IsEqualList +from Library.Misc import Sdict + +from Logger.StringTable import ERR_XML_INVALID_VARIABLENAME +from Logger.StringTable import ERR_XML_INVALID_LIB_SUPMODLIST +from Logger.StringTable import ERR_XML_INVALID_EXTERN_SUPARCHLIST +from Logger.StringTable import ERR_XML_INVALID_EXTERN_SUPMODLIST +from Logger.StringTable import ERR_XML_INVALID_EXTERN_SUPMODLIST_NOT_LIB +from Logger.StringTable import ERR_FILE_NAME_INVALIDE +from Logger.ToolError import PARSER_ERROR +from Logger.ToolError import FORMAT_INVALID + +from Xml.CommonXml import DistributionPackageHeaderXml +from Xml.CommonXml import MiscellaneousFileXml +from Xml.CommonXml import UserExtensionsXml +from Xml.XmlParserMisc import ConvertVariableName +from Xml.XmlParserMisc import IsRequiredItemListNull +from Xml.ModuleSurfaceAreaXml import ModuleSurfaceAreaXml +from Xml.PackageSurfaceAreaXml import PackageSurfaceAreaXml + +import Logger.Log as Logger + +## +# DistributionPackageXml +# +class DistributionPackageXml(object): + def __init__(self): + self.DistP = DistributionPackageClass() + self.Pkg = '' + + ## ValidateDistributionPackage + # + # Check if any required item is missing in DistributionPackage + # + def ValidateDistributionPackage(self): + XmlTreeLevel = ['DistributionPackage'] + if self.DistP: + # + # Check DistributionPackage -> DistributionHeader + # + XmlTreeLevel = ['DistributionPackage', ''] + CheckDict = {'DistributionHeader':self.DistP.Header } + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + if self.DistP.Header: + DpHeader = self.DistP.Header + XmlTreeLevel = ['DistributionPackage', 'DistributionHeader'] + CheckDict = Sdict() + if DpHeader.GetAbstract(): + DPAbstract = DpHeader.GetAbstract()[0][1] + else: + DPAbstract = '' + if DpHeader.GetCopyright(): + DPCopyright = DpHeader.GetCopyright()[0][1] + else: + DPCopyright = '' + if DpHeader.GetLicense(): + DPLicense = DpHeader.GetLicense()[0][1] + else: + DPLicense = '' + + CheckDict['Name'] = DpHeader.GetName() + CheckDict['GUID'] = DpHeader.GetGuid() + CheckDict['Version'] = DpHeader.GetVersion() + CheckDict['Copyright'] = DPCopyright + CheckDict['License'] = DPLicense + CheckDict['Abstract'] = DPAbstract + CheckDict['Vendor'] = DpHeader.GetVendor() + CheckDict['Date'] = DpHeader.GetDate() + CheckDict['XmlSpecification'] = DpHeader.GetXmlSpecification() + + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + else: + XmlTreeLevel = ['DistributionPackage', 'DistributionHeader'] + CheckDict = CheckDict = {'DistributionHeader': '', } + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + # + # Check Each Package + # + for Key in self.DistP.PackageSurfaceArea: + ValidatePackageSurfaceArea(self.DistP.PackageSurfaceArea[Key]) + + # + # Check Each Module + # + for Key in self.DistP.ModuleSurfaceArea: + ValidateMS(self.DistP.ModuleSurfaceArea[Key], ['DistributionPackage', 'ModuleSurfaceArea']) + + # + # Check Each Tool + # + if self.DistP.Tools: + XmlTreeLevel = ['DistributionPackage', 'Tools', 'Header'] + CheckDict = {'Name': self.DistP.Tools.GetName(), } + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + if not self.DistP.Tools.GetFileList(): + XmlTreeLevel = ['DistributionPackage', 'Tools'] + CheckDict = {'FileName': None, } + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + for Item in self.DistP.Tools.GetFileList(): + XmlTreeLevel = ['DistributionPackage', 'Tools'] + CheckDict = {'FileName': Item.GetURI(), } + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + # + # Check Each Misc File + # + if self.DistP.MiscellaneousFiles: + XmlTreeLevel = ['DistributionPackage', 'MiscellaneousFiles', 'Header'] + CheckDict = {'Name': self.DistP.MiscellaneousFiles.GetName(), } + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + if not self.DistP.MiscellaneousFiles.GetFileList(): + XmlTreeLevel = ['DistributionPackage', 'MiscellaneousFiles'] + CheckDict = {'FileName': None, } + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + for Item in self.DistP.MiscellaneousFiles.GetFileList(): + XmlTreeLevel = ['DistributionPackage', 'MiscellaneousFiles'] + CheckDict = {'FileName': Item.GetURI(), } + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + # + # Check Each Distribution Level User Extension + # + for Item in self.DistP.UserExtensions: + XmlTreeLevel = ['DistributionPackage', 'UserExtensions'] + CheckDict = {'UserId': Item.GetUserID(), } + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + + def FromXml(self, Filename=None): + if Filename is not None: + self.DistP = DistributionPackageClass() + # + # Load to XML + # + self.Pkg = XmlParseFile(Filename) + + # + # Parse Header information + # + Tmp = DistributionPackageHeaderXml() + DistributionPackageHeader = \ + Tmp.FromXml(XmlNode(self.Pkg, '/DistributionPackage/DistributionHeader'), 'DistributionHeader') + self.DistP.Header = DistributionPackageHeader + # + # Parse each PackageSurfaceArea + # + for Item in XmlList(self.Pkg, '/DistributionPackage/PackageSurfaceArea'): + Psa = PackageSurfaceAreaXml() + Package = Psa.FromXml(Item, 'PackageSurfaceArea') + self.DistP.PackageSurfaceArea[(Package.GetGuid(), \ + Package.GetVersion(), \ + Package.GetPackagePath())] = \ + Package + # + # Parse each ModuleSurfaceArea + # + for Item in XmlList(self.Pkg, '/DistributionPackage/ModuleSurfaceArea'): + Msa = ModuleSurfaceAreaXml() + Module = Msa.FromXml(Item, 'ModuleSurfaceArea', True) + ModuleKey = (Module.GetGuid(), Module.GetVersion(), Module.GetName(), Module.GetModulePath()) + self.DistP.ModuleSurfaceArea[ModuleKey] = Module + + # + # Parse Tools + # + Tmp = MiscellaneousFileXml() + self.DistP.Tools = Tmp.FromXml2(XmlNode(self.Pkg, '/DistributionPackage/Tools'), 'Tools') + + # + # Parse MiscFiles + # + Tmp = MiscellaneousFileXml() + self.DistP.MiscellaneousFiles = \ + Tmp.FromXml2(XmlNode(self.Pkg, \ + '/DistributionPackage/MiscellaneousFiles'), \ + 'MiscellaneousFiles') + + # + # Parse UserExtensions + # + for Item in XmlList(self.Pkg, '/DistributionPackage/UserExtensions'): + Tmp = UserExtensionsXml() + self.DistP.UserExtensions.append(Tmp.FromXml2(Item, 'UserExtensions')) + + # + # Check Required Items for XML + # + self.ValidateDistributionPackage() + + return self.DistP + + def ToXml(self, DistP): + if self.DistP: + pass + if DistP is not None: + # + # Parse DistributionPackageHeader + # + Attrs = [['xmlns', 'http://www.uefi.org/2011/1.1'], + ['xmlns:xsi', 'http:/www.w3.org/2001/XMLSchema-instance'], + ] + Root = CreateXmlElement('DistributionPackage', '', [], Attrs) + + Tmp = DistributionPackageHeaderXml() + Root.appendChild(Tmp.ToXml(DistP.Header, 'DistributionHeader')) + # + # Parse each PackageSurfaceArea + # + for Package in DistP.PackageSurfaceArea.values(): + Psa = PackageSurfaceAreaXml() + DomPackage = Psa.ToXml(Package) + Root.appendChild(DomPackage) + # + # Parse each ModuleSurfaceArea + # + for Module in DistP.ModuleSurfaceArea.values(): + Msa = ModuleSurfaceAreaXml() + DomModule = Msa.ToXml(Module) + Root.appendChild(DomModule) + # + # Parse Tools + # + Tmp = MiscellaneousFileXml() + ToolNode = Tmp.ToXml2(DistP.Tools, 'Tools') + if ToolNode is not None: + Root.appendChild(ToolNode) + # + # Parse MiscFiles + # + Tmp = MiscellaneousFileXml() + MiscFileNode = Tmp.ToXml2(DistP.MiscellaneousFiles, + 'MiscellaneousFiles') + if MiscFileNode is not None: + Root.appendChild(MiscFileNode) + + XmlContent = Root.toprettyxml(indent=' ') + + + # + # Remove empty element + # + XmlContent = re.sub(r'[\s\r\n]*<[^<>=]*/>', '', XmlContent) + + # + # Remove empty help text element + # + XmlContent = re.sub(r'[\s\r\n]*', '', + XmlContent) + + # + # Remove SupArchList="COMMON" or "common" + # + XmlContent = \ + re.sub(r'[\s\r\n]*SupArchList[\s\r\n]*=[\s\r\n]*"[\s\r\n]*COMMON' + '[\s\r\n]*"', '', XmlContent) + XmlContent = \ + re.sub(r'[\s\r\n]*SupArchList[\s\r\n]*=[\s\r\n]*"[\s\r\n]*common' + '[\s\r\n]*"', '', XmlContent) + # + # Remove COMMON + # + XmlContent = \ + re.sub(r'[\s\r\n]*[\s\r\n]*COMMON[\s\r\n]*' + '[\s\r\n]*', '', XmlContent) + + # + # Remove common + # + XmlContent = \ + re.sub(r'[\s\r\n]*[\s\r\n]*' + 'common[\s\r\n]*[\s\r\n]*', '', XmlContent) + + # + # Remove SupModList="COMMON" or "common" + # + XmlContent = \ + re.sub(r'[\s\r\n]*SupModList[\s\r\n]*=[\s\r\n]*"[\s\r\n]*COMMON' + '[\s\r\n]*"', '', XmlContent) + XmlContent = \ + re.sub(r'[\s\r\n]*SupModList[\s\r\n]*=[\s\r\n]*"[\s\r\n]*common' + '[\s\r\n]*"', '', XmlContent) + + return XmlContent + + return '' + +## ValidateMS +# +# Check if any required item is missing in ModuleSurfaceArea +# +# @param Module: The ModuleSurfaceArea to be checked +# @param XmlTreeLevel: The top level of Module +# +def ValidateMS(Module, TopXmlTreeLevel): + ValidateMS1(Module, TopXmlTreeLevel) + ValidateMS2(Module, TopXmlTreeLevel) + ValidateMS3(Module, TopXmlTreeLevel) + +## ValidateMS1 +# +# Check if any required item is missing in ModuleSurfaceArea +# +# @param Module: The ModuleSurfaceArea to be checked +# @param XmlTreeLevel: The top level of Module +# +def ValidateMS1(Module, TopXmlTreeLevel): + # + # Check Guids -> GuidCName + # + XmlTreeLevel = TopXmlTreeLevel + ['Guids'] + for Item in Module.GetGuidList(): + if Item is None: + CheckDict = {'GuidCName':''} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + XmlTreeLevel = TopXmlTreeLevel + ['Guids', 'GuidCName'] + for Item in Module.GetGuidList(): + CheckDict = {'CName':Item.GetCName(), + 'GuidType':Item.GetGuidTypeList(), + 'Usage':Item.GetUsage()} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + if Item.GetVariableName(): + Result = ConvertVariableName(Item.GetVariableName()) + if Result is None: + Msg = "->".join(Node for Node in XmlTreeLevel) + ErrorMsg = ERR_XML_INVALID_VARIABLENAME % (Item.GetVariableName(), Item.GetCName(), Msg) + Logger.Error('\nUPT', PARSER_ERROR, ErrorMsg, RaiseError=True) + else: + Item.SetVariableName(Result) + + # + # Check Protocols -> Protocol + # + XmlTreeLevel = TopXmlTreeLevel + ['Protocols'] + for Item in Module.GetProtocolList(): + if Item is None: + CheckDict = {'Protocol':''} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + XmlTreeLevel = TopXmlTreeLevel + ['Protocols', 'Protocol'] + for Item in Module.GetProtocolList(): + CheckDict = {'CName':Item.GetCName(), + 'Usage':Item.GetUsage()} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + # + # Check PPIs -> Ppi + # + XmlTreeLevel = TopXmlTreeLevel + ['PPIs'] + for Item in Module.GetPpiList(): + if Item is None: + CheckDict = {'Ppi':''} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + XmlTreeLevel = TopXmlTreeLevel + ['PPIs', 'Ppi'] + for Item in Module.GetPpiList(): + CheckDict = {'CName':Item.GetCName(), + 'Usage':Item.GetUsage()} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + # + # Check PcdCoded -> Entry + # + XmlTreeLevel = TopXmlTreeLevel + ['PcdCoded'] + for Item in Module.GetPcdList(): + if Item is None: + CheckDict = {'PcdEntry':''} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + XmlTreeLevel = TopXmlTreeLevel + ['PcdCoded', 'PcdEntry'] + for Item in Module.GetPcdList(): + CheckDict = {'TokenSpaceGuidCname':Item.GetTokenSpaceGuidCName(), + 'CName':Item.GetCName(), + 'PcdUsage':Item.GetValidUsage(), + 'PcdItemType':Item.GetItemType()} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + # + # Check Externs -> Extern + # + XmlTreeLevel = TopXmlTreeLevel + ['Externs'] + for Item in Module.GetExternList(): + if Item is None: + CheckDict = {'Extern':''} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + # + # If SupArchList is used to identify different EntryPoint, UnloadImage, Constructor/Destructor elements and + # that SupArchList does not match ModuleSurfaceArea.ModuleProperties:SupArchList, the tool must exit gracefully, + # informing the user that the EDK II Build system does not support different EntryPoint, UnloadImage, + # Constructor or Destructor elements based on Architecture type. Two SupArchList attributes are considered + # identical if it lists the same CPU architectures in any order. + # + for Item in Module.GetExternList(): + if len(Item.SupArchList) > 0: + if not IsEqualList(Item.SupArchList, Module.SupArchList): + Logger.Error('\nUPT', + PARSER_ERROR, + ERR_XML_INVALID_EXTERN_SUPARCHLIST % (str(Item.SupArchList), str(Module.SupArchList)), + RaiseError=True) + + # + # Check DistributionPackage -> ModuleSurfaceArea -> UserExtensions + # + XmlTreeLevel = TopXmlTreeLevel + ['UserExtensions'] + for Item in Module.GetUserExtensionList(): + CheckDict = {'UserId':Item.GetUserID(), 'Identifier':Item.GetIdentifier()} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + # + # Check DistributionPackage -> PackageSurfaceArea -> MiscellaneousFiles -> Filename + # + XmlTreeLevel = TopXmlTreeLevel + ['MiscellaneousFiles'] + for Item in Module.GetMiscFileList(): + if not Item.GetFileList(): + CheckDict = {'Filename': '', } + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + for File in Item.GetFileList(): + CheckDict = {'Filename': File.GetURI(), } + +## ValidateMS2 +# +# Check if any required item is missing in ModuleSurfaceArea +# +# @param Module: The ModuleSurfaceArea to be checked +# @param XmlTreeLevel: The top level of Module +# +def ValidateMS2(Module, TopXmlTreeLevel): + # + # Check Header + # + XmlTreeLevel = TopXmlTreeLevel + ['Header'] + CheckDict = Sdict() + CheckDict['Name'] = Module.GetName() + CheckDict['BaseName'] = Module.GetBaseName() + CheckDict['GUID'] = Module.GetGuid() + CheckDict['Version'] = Module.GetVersion() + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + # + # Check ModuleProperties + # + XmlTreeLevel = TopXmlTreeLevel + ['ModuleProperties'] + CheckDict = {'ModuleType':Module.GetModuleType(), + 'Path':Module.GetModulePath()} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + if not IsValidInstallPath(Module.GetModulePath()): + Logger.Error("UPT", FORMAT_INVALID, ERR_FILE_NAME_INVALIDE % Module.GetModulePath()) + + # + # Check ModuleProperties->BootMode + # + XmlTreeLevel = TopXmlTreeLevel + ['ModuleProperties'] + ['BootMode'] + for Item in Module.GetBootModeList(): + CheckDict = {'Usage':Item.GetUsage(), + 'SupportedBootModes':Item.GetSupportedBootModes()} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + # + # Check ModuleProperties->Event + # + XmlTreeLevel = TopXmlTreeLevel + ['ModuleProperties'] + ['Event'] + for Item in Module.GetEventList(): + CheckDict = {'Usage':Item.GetUsage(), + 'EventType':Item.GetEventType()} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + # + # Check ModuleProperties->Hob + # + XmlTreeLevel = TopXmlTreeLevel + ['ModuleProperties'] + ['HOB'] + for Item in Module.GetHobList(): + CheckDict = {'Usage':Item.GetUsage(), + 'HobType':Item.GetHobType()} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + # + # The UDP Specification supports the module type of UEFI_RUNTIME_DRIVER, which is not present in the EDK II INF + # File Specification v. 1.23, so UPT must perform the following translation that include the generation of a + # [Depex] section. + # + if Module.ModuleType == "UEFI_RUNTIME_DRIVER": + Module.ModuleType = "DXE_RUNTIME_DRIVER" + DxeObj = DepexObject() + DxeObj.SetDepex("gEfiBdsArchProtocolGuid AND \ngEfiCpuArchProtocolGuid AND\n" + \ + "gEfiMetronomeArchProtocolGuid AND \ngEfiMonotonicCounterArchProtocolGuid AND\n" + \ + "gEfiRealTimeClockArchProtocolGuid AND \ngEfiResetArchProtocolGuid AND\n" + \ + "gEfiRuntimeArchProtocolGuid AND \ngEfiSecurityArchProtocolGuid AND\n" + \ + "gEfiTimerArchProtocolGuid AND \ngEfiVariableWriteArchProtocolGuid AND\n" + \ + "gEfiVariableArchProtocolGuid AND \ngEfiWatchdogTimerArchProtocolGuid") + DxeObj.SetModuleType(['DXE_RUNTIME_DRIVER']) + Module.PeiDepex = [] + Module.DxeDepex = [] + Module.SmmDepex = [] + Module.DxeDepex.append(DxeObj) + + # + # Check LibraryClassDefinitions -> LibraryClass + # + XmlTreeLevel = TopXmlTreeLevel + ['LibraryClassDefinitions'] + for Item in Module.GetLibraryClassList(): + if Item is None: + CheckDict = {'LibraryClass':''} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + XmlTreeLevel = TopXmlTreeLevel + ['LibraryClassDefinitions', 'LibraryClass'] + + IsLibraryModule = False + LibrarySupModList = [] + for Item in Module.GetLibraryClassList(): + CheckDict = {'Keyword':Item.GetLibraryClass(), + 'Usage':Item.GetUsage()} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + # + # If the LibraryClass:SupModList is not "UNDEFINED" the LIBRARY_CLASS entry must have the list + # appended using the format: + # LIBRARY_CLASS = ["|" ] + # + # Edk2ModuleTypeList ::= [" " ]{0,} + # ::= {"BASE"} {"SEC"} {"PEI_CORE"} {"PEIM"} + # {"DXE_CORE"} {"DXE_DRIVER"} {"SMM_CORE"} + # {"DXE_SMM_DRIVER"} {"DXE_RUNTIME_DRIVER"} + # {"DXE_SAL_DRIVER"} {"UEFI_DRIVER"} + # {"UEFI_APPLICATION"} {"USER_DEFINED"} + # + if len(Item.SupModuleList) > 0: + for SupModule in Item.SupModuleList: + if not IsValidInfMoudleType(SupModule): + Logger.Error('\nUPT', + PARSER_ERROR, + ERR_XML_INVALID_LIB_SUPMODLIST % (Item.LibraryClass, str(SupModule)), + RaiseError=True) + + if Item.Usage == 'PRODUCES' or Item.Usage == 'SOMETIMES_PRODUCES': + IsLibraryModule = True + LibrarySupModList = Item.SupModuleList + + + # + # For Library modules (indicated by a LIBRARY_CLASS statement in the [Defines] section) + # If the SupModList attribute of the CONSTRUCTOR or DESTRUCTOR element does not match the Supported Module + # Types listed after "LIBRARY_CLASS = |", the tool should gracefully exit with an error message + # stating that there is a conflict in the module types the CONSTRUCTOR/DESTRUCTOR is to be used with and + # the Module types this Library supports. + # + if IsLibraryModule: + for Item in Module.GetExternList(): + if Item.Constructor or Item.Destructor: + if hasattr(Item, 'SupModList') and len(Item.SupModList) > 0 and \ + not IsEqualList(Item.SupModList, LibrarySupModList): + Logger.Error('\nUPT', + PARSER_ERROR, + ERR_XML_INVALID_EXTERN_SUPMODLIST % (str(Item.SupModList), str(LibrarySupModList)), + RaiseError=True) + + # + # If the module is not a library module, the MODULE_TYPE listed in the ModuleSurfaceArea.Header must match the + # SupModList attribute. If these conditions cannot be met, the tool must exit gracefully, informing the user + # that the EDK II Build system does not currently support the features required by this Module. + # + if not IsLibraryModule: + for Item in Module.GetExternList(): + if hasattr(Item, 'SupModList') and len(Item.SupModList) > 0 and \ + not IsEqualList(Item.SupModList, [Module.ModuleType]): + Logger.Error('\nUPT', + PARSER_ERROR, + ERR_XML_INVALID_EXTERN_SUPMODLIST_NOT_LIB % (str(Module.ModuleType), str(Item.SupModList)), + RaiseError=True) + # + # Check SourceFiles + # + XmlTreeLevel = TopXmlTreeLevel + ['SourceFiles'] + for Item in Module.GetSourceFileList(): + if Item is None: + CheckDict = {'Filename':''} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + XmlTreeLevel = TopXmlTreeLevel + ['SourceFiles'] + for Item in Module.GetSourceFileList(): + CheckDict = {'Filename':Item.GetSourceFile()} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + for ItemCount in range(len(Module.GetBinaryFileList())): + Item = Module.GetBinaryFileList()[ItemCount] + if Item and len(Item.FileNamList) > 0 and Item.FileNamList[0].FileType == 'FREEFORM': + Item.FileNamList[0].FileType = 'SUBTYPE_GUID' + Module.GetBinaryFileList()[ItemCount] = Item + +## ValidateMS3 +# +# Check if any required item is missing in ModuleSurfaceArea +# +# @param Module: The ModuleSurfaceArea to be checked +# @param XmlTreeLevel: The top level of Module +# +def ValidateMS3(Module, TopXmlTreeLevel): + # + # Check PackageDependencies -> Package + # + XmlTreeLevel = TopXmlTreeLevel + ['PackageDependencies'] + for Item in Module.GetPackageDependencyList(): + if Item is None: + CheckDict = {'Package':''} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + XmlTreeLevel = TopXmlTreeLevel + ['PackageDependencies', 'Package'] + for Item in Module.GetPackageDependencyList(): + CheckDict = {'GUID':Item.GetGuid()} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + # + # Check BinaryFiles -> BinaryFile + # + for Item in Module.GetBinaryFileList(): + if Item is None: + XmlTreeLevel = TopXmlTreeLevel + ['BinaryFiles'] + CheckDict = {'BinaryFile':''} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + if not Item.GetFileNameList(): + XmlTreeLevel = TopXmlTreeLevel + ['BinaryFiles', 'BinaryFile'] + CheckDict = {'Filename':''} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + XmlTreeLevel = TopXmlTreeLevel + ['BinaryFiles', 'BinaryFile'] + for File in Item.GetFileNameList(): + CheckDict = {'Filename':File.GetFilename(), + 'FileType':File.GetFileType()} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + for AsBuilt in Item.GetAsBuiltList(): + # + # Check LibInstance + # + if len(AsBuilt.LibraryInstancesList) == 1 and not AsBuilt.LibraryInstancesList[0]: + CheckDict = {'GUID':''} + XmlTreeLevel = TopXmlTreeLevel + ['BinaryFiles', 'BinaryFile', 'AsBuilt', 'LibraryInstances'] + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + for LibItem in AsBuilt.LibraryInstancesList: + CheckDict = {'Guid':LibItem.Guid, + 'Version':LibItem.Version} + XmlTreeLevel = TopXmlTreeLevel + ['BinaryFiles', 'BinaryFile', 'AsBuilt', 'LibraryInstances'] + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + # + # Check PatchPcd + # + for PatchPcdItem in AsBuilt.PatchPcdList: + CheckDict = {'TokenSpaceGuidValue':PatchPcdItem.TokenSpaceGuidValue, + 'PcdCName':PatchPcdItem.PcdCName, + 'Token':PatchPcdItem.Token, + 'DatumType':PatchPcdItem.DatumType, + 'Value':PatchPcdItem.DefaultValue, + 'Offset':PatchPcdItem.Offset} + XmlTreeLevel = TopXmlTreeLevel + ['BinaryFiles', 'BinaryFile', 'AsBuilt', 'PatchPcdValue'] + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + # + # Check PcdError + # + for PcdErrorItem in PatchPcdItem.PcdErrorsList: + CheckDict = {'ErrorNumber':PcdErrorItem.ErrorNumber} + XmlTreeLevel = TopXmlTreeLevel + ['BinaryFiles', 'BinaryFile', 'AsBuilt', + 'PatchPcdValue', 'PcdError'] + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + # + # Check PcdEx + # + for PcdExItem in AsBuilt.PcdExValueList: + CheckDict = {'TokenSpaceGuidValue':PcdExItem.TokenSpaceGuidValue, + 'Token':PcdExItem.Token, + 'DatumType':PcdExItem.DatumType} + XmlTreeLevel = TopXmlTreeLevel + ['BinaryFiles', 'BinaryFile', 'AsBuilt', 'PcdExValue'] + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + # + # Check PcdError + # + for PcdErrorItem in PcdExItem.PcdErrorsList: + CheckDict = {'ErrorNumber':PcdErrorItem.ErrorNumber} + XmlTreeLevel = TopXmlTreeLevel + ['BinaryFiles', 'BinaryFile', 'AsBuilt', + 'PcdExValue', 'PcdError'] + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + # + # Check SmmDepex + # + XmlTreeLevel = TopXmlTreeLevel + ['SmmDepex'] + for Item in Module.GetSmmDepex(): + CheckDict = {'Expression':Item.GetDepex()} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + # + # Check PeiDepex + # + XmlTreeLevel = TopXmlTreeLevel + ['PeiDepex'] + for Item in Module.GetPeiDepex(): + CheckDict = {'Expression':Item.GetDepex()} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + # + # Check DxeDepex + # + XmlTreeLevel = TopXmlTreeLevel + ['DxeDepex'] + for Item in Module.GetDxeDepex(): + CheckDict = {'Expression':Item.GetDepex()} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + # + # Check + # + XmlTreeLevel = TopXmlTreeLevel + ['UserExtensions'] + for Item in Module.GetUserExtensionList(): + CheckDict = {'UserId':Item.GetUserID(), 'Identifier':Item.GetIdentifier()} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + +## ValidatePS1 +# +# ValidatePS1 +# +def ValidatePS1(Package): + # + # Check DistributionPackage -> PackageSurfaceArea -> Header + # + XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'Header'] + CheckDict = Sdict() + CheckDict['Name'] = Package.GetName() + CheckDict['BaseName'] = Package.GetBaseName() + CheckDict['GUID'] = Package.GetGuid() + CheckDict['Version'] = Package.GetVersion() + CheckDict['PackagePath'] = Package.GetPackagePath() + + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + if not IsValidInstallPath(Package.GetPackagePath()): + Logger.Error("UPT", FORMAT_INVALID, ERR_FILE_NAME_INVALIDE % Package.GetPackagePath()) + + # + # Check DistributionPackage -> PackageSurfaceArea -> ClonedFrom + # + XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'ClonedFrom'] + for Item in Package.GetClonedFromList(): + if Item is None: + CheckDict = Sdict() + CheckDict['GUID'] = '' + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + CheckDict = Sdict() + CheckDict['GUID'] = Item.GetPackageGuid() + CheckDict['Version'] = Item.GetPackageVersion() + + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + # + # Check DistributionPackage -> PackageSurfaceArea -> LibraryClassDeclarations -> LibraryClass + # + XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'LibraryClassDeclarations'] + for Item in Package.GetLibraryClassList(): + if Item is None: + CheckDict = {'LibraryClass':''} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'LibraryClassDeclarations', 'LibraryClass'] + for Item in Package.GetLibraryClassList(): + CheckDict = {'Keyword':Item.GetLibraryClass(), + 'HeaderFile':Item.GetIncludeHeader()} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + # + # Check DistributionPackage -> PackageSurfaceArea -> IndustryStandardIncludes -> IndustryStandardHeader + # + XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'IndustryStandardIncludes'] + for Item in Package.GetStandardIncludeFileList(): + if Item is None: + CheckDict = {'IndustryStandardHeader':''} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'IndustryStandardIncludes', 'IndustryStandardHeader'] + for Item in Package.GetStandardIncludeFileList(): + CheckDict = {'HeaderFile':Item.GetFilePath()} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + # + # Check DistributionPackage -> PackageSurfaceArea -> PackageIncludes -> PackageHeader + # + XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'PackageIncludes'] + for Item in Package.GetPackageIncludeFileList(): + if Item is None: + CheckDict = {'PackageHeader':''} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'PackageIncludes', 'PackageHeader'] + for Item in Package.GetPackageIncludeFileList(): + CheckDict = {'HeaderFile':Item.GetFilePath()} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + +## ValidatePS2 +# +# ValidatePS2 +# +def ValidatePS2(Package): + # + # Check DistributionPackage -> PackageSurfaceArea -> Modules -> ModuleSurfaceArea + # + XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'Modules', 'ModuleSurfaceArea'] + for Item in Package.GetModuleDict().values(): + ValidateMS(Item, XmlTreeLevel) + + # + # Check DistributionPackage -> PackageSurfaceArea -> GuidDeclarations Entry + # + XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'GuidDeclarations'] + for Item in Package.GetGuidList(): + if Item is None: + CheckDict = {'Entry':''} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'GuidDeclarations', 'Entry'] + for Item in Package.GetGuidList(): + CheckDict = {'CName':Item.GetCName(), + 'GuidValue':Item.GetGuid()} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + # + # Check DistributionPackage -> PackageSurfaceArea -> ProtocolDeclarations -> Entry + # + XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'ProtocolDeclarations'] + for Item in Package.GetProtocolList(): + if Item is None: + CheckDict = {'Entry':''} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'ProtocolDeclarations', 'Entry'] + for Item in Package.GetProtocolList(): + CheckDict = {'CName':Item.GetCName(), + 'GuidValue':Item.GetGuid()} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + # + # Check DistributionPackage -> PackageSurfaceArea -> PpiDeclarations -> Entry + # + XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'PpiDeclarations'] + for Item in Package.GetPpiList(): + if Item is None: + CheckDict = {'Entry':''} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'PpiDeclarations', 'Entry'] + for Item in Package.GetPpiList(): + CheckDict = {'CName':Item.GetCName(), + 'GuidValue':Item.GetGuid()} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + # + # Check DistributionPackage -> PackageSurfaceArea -> PcdDeclarations -> Entry + # + XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'PcdDeclarations'] + for Item in Package.GetPcdList(): + if Item is None: + CheckDict = {'PcdEntry':''} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'PcdDeclarations', 'PcdEntry'] + for Item in Package.GetPcdList(): + CheckDict = {'TokenSpaceGuidCname':Item.GetTokenSpaceGuidCName(), + 'Token':Item.GetToken(), + 'CName':Item.GetCName(), + 'DatumType':Item.GetDatumType(), + 'ValidUsage':Item.GetValidUsage(), + 'DefaultValue':Item.GetDefaultValue()} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + # + # Check DistributionPackage -> PackageSurfaceArea -> UserExtensions + # + XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'UserExtensions'] + for Item in Package.GetUserExtensionList(): + CheckDict = {'UserId':Item.GetUserID(), 'Identifier':Item.GetIdentifier()} + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + + # + # Check DistributionPackage -> PackageSurfaceArea -> MiscellaneousFiles -> Filename + # + XmlTreeLevel = ['DistributionPackage', 'PackageSurfaceArea', 'MiscellaneousFiles'] + for Item in Package.GetMiscFileList(): + if not Item.GetFileList(): + CheckDict = {'Filename': '', } + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + for File in Item.GetFileList(): + CheckDict = {'Filename': File.GetURI(), } + IsRequiredItemListNull(CheckDict, XmlTreeLevel) + +## ValidatePackageSurfaceArea +# +# Check if any required item is missing in PackageSurfaceArea +# +# @param Package: The PackageSurfaceArea to be checked +# +def ValidatePackageSurfaceArea(Package): + ValidatePS1(Package) + ValidatePS2(Package) diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/XmlParserMisc.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/XmlParserMisc.py new file mode 100755 index 00000000..4d495ae9 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/XmlParserMisc.py @@ -0,0 +1,95 @@ +## @file +# This file is used to parse a xml file of .PKG file +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +XmlParserMisc +''' +from Object.POM.CommonObject import TextObject +from Logger.StringTable import ERR_XML_PARSER_REQUIRED_ITEM_MISSING +from Logger.ToolError import PARSER_ERROR +import Logger.Log as Logger + +## ConvertVariableName() +# Convert VariableName to be L"string", +# input of UCS-2 format Hex Array or L"string" (C style.) could be converted successfully, +# others will not. +# +# @param VariableName: string need to be converted +# @retval: the L quoted string converted if success, else None will be returned +# +def ConvertVariableName(VariableName): + VariableName = VariableName.strip() + # + # check for L quoted string + # + if VariableName.startswith('L"') and VariableName.endswith('"'): + return VariableName + + # + # check for Hex Array, it should be little endian even number of hex numbers + # + ValueList = VariableName.split(' ') + if len(ValueList)%2 == 1: + return None + + TransferedStr = '' + + Index = 0 + + while Index < len(ValueList): + FirstByte = int(ValueList[Index], 16) + SecondByte = int(ValueList[Index + 1], 16) + if SecondByte != 0: + return None + + if FirstByte not in range(0x20, 0x7F): + return None + TransferedStr += ('%c')%FirstByte + Index = Index + 2 + + return 'L"' + TransferedStr + '"' + +## IsRequiredItemListNull +# +# Check if a required XML section item/attribue is NULL +# +# @param ItemList: The list of items to be checked +# @param XmlTreeLevel: The error message tree level +# +def IsRequiredItemListNull(ItemDict, XmlTreeLevel): + for Key in ItemDict: + if not ItemDict[Key]: + Msg = "->".join(Node for Node in XmlTreeLevel) + ErrorMsg = ERR_XML_PARSER_REQUIRED_ITEM_MISSING % (Key, Msg) + Logger.Error('\nUPT', PARSER_ERROR, ErrorMsg, RaiseError=True) + +## Get help text +# +# @param HelpText +# +def GetHelpTextList(HelpText): + HelpTextList = [] + for HelT in HelpText: + HelpTextObj = TextObject() + HelpTextObj.SetLang(HelT.Lang) + HelpTextObj.SetString(HelT.HelpText) + HelpTextList.append(HelpTextObj) + return HelpTextList + +## Get Prompt text +# +# @param Prompt +# +def GetPromptList(Prompt): + PromptList = [] + for SubPrompt in Prompt: + PromptObj = TextObject() + PromptObj.SetLang(SubPrompt.Lang) + PromptObj.SetString(SubPrompt.Prompt) + PromptList.append(PromptObj) + return PromptList diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/__init__.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/__init__.py new file mode 100644 index 00000000..a800a619 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Xml/__init__.py @@ -0,0 +1,14 @@ +## @file +# Python 'Library' package initialization file. +# +# This file is required to make Python interpreter treat the directory +# as containing package. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +Xml +''' -- cgit v1.2.3