mirror of
https://github.com/acidanthera/audk.git
synced 2025-04-08 17:05:09 +02:00
1. Add a recovery mode for UPT failure 2. Add UNI file support 3. Add binary file header support 4. Add support for PCD error message 5. Add support for replace 6. Format generated INF/DEC files 7. Update dependency check 8. Other minor fixes Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Hess Chen <hesheng.chen@intel.com> Reviewed-by: Gao, Liming <liming.gao@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15896 6f19259b-4bc3-4df7-8a09-765794883524
333 lines
14 KiB
Python
333 lines
14 KiB
Python
## @file
|
|
#
|
|
# This file is the main entry for UPT
|
|
#
|
|
# Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>
|
|
#
|
|
# This program and the accompanying materials are licensed and made available
|
|
# under the terms and conditions of the BSD License which accompanies this
|
|
# distribution. The full text of the license may be found at
|
|
# http://opensource.org/licenses/bsd-license.php
|
|
#
|
|
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
#
|
|
|
|
'''
|
|
UPT
|
|
'''
|
|
|
|
## import modules
|
|
#
|
|
from Core import FileHook
|
|
import sys
|
|
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
|
|
|
|
import MkPkg
|
|
import InstallPkg
|
|
import RmPkg
|
|
import InventoryWs
|
|
import ReplacePkg
|
|
from Library.Misc import GetWorkspace
|
|
from Library import GlobalData
|
|
from Core.IpiDb import IpiDatabase
|
|
from BuildVersion import gBUILD_VERSION
|
|
|
|
##
|
|
# Version and Copyright
|
|
#
|
|
#VersionNumber = "1.0"
|
|
#__version__ = "Revision " + VersionNumber
|
|
#__copyright__ = "Copyright (c) 2011 Intel Corporation All Rights Reserved."
|
|
|
|
## 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)
|
|
|
|
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 != 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 + ' ' + 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="store", 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)
|
|
|
|
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),
|
|
]
|
|
|
|
for Var in Var2Var:
|
|
setattr(Opt, Var[0], Var[1])
|
|
|
|
try:
|
|
GlobalData.gWORKSPACE = GetWorkspace()
|
|
except FatalError, XExcept:
|
|
if Logger.GetLevel() <= Logger.DEBUG_9:
|
|
Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + format_exc())
|
|
return XExcept.args[0]
|
|
|
|
# Start *********************************************
|
|
# Support WORKSPACE is a long path
|
|
# Only work well on windows
|
|
# Linux Solution TBD
|
|
if pf.system() == 'Windows':
|
|
os.system('@echo off\nsubst b: /D')
|
|
os.system('subst b: "%s"' % GlobalData.gWORKSPACE)
|
|
GlobalData.gWORKSPACE = 'B:\\'
|
|
# End ***********************************************
|
|
|
|
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:
|
|
if not Opt.PackFileToInstall.endswith('.dist'):
|
|
Logger.Error("InstallPkg", FILE_TYPE_MISMATCH, ExtraData=ST.ERR_DIST_EXT_ERROR % Opt.PackFileToInstall)
|
|
|
|
AbsPath = GetFullPathDist(Opt.PackFileToInstall, WorkspaceDir)
|
|
if not AbsPath:
|
|
Logger.Error("InstallPkg", FILE_NOT_FOUND, ST.ERR_INSTALL_DIST_NOT_FOUND % Opt.PackFileToInstall)
|
|
|
|
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
|
|
|
|
else:
|
|
Parser.print_usage()
|
|
return OPTION_MISSING
|
|
|
|
ReturnCode = RunModule(Opt)
|
|
except FatalError, 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:
|
|
Logger.Quiet(ST.MSG_RECOVER_START)
|
|
GlobalData.gDB.RollBack()
|
|
Mgr.rollback()
|
|
Logger.Quiet(ST.MSG_RECOVER_DONE)
|
|
else:
|
|
GlobalData.gDB.Commit()
|
|
Mgr.commit()
|
|
except StandardError:
|
|
Logger.Quiet(ST.MSG_RECOVER_FAIL)
|
|
GlobalData.gDB.CloseDb()
|
|
if pf.system() == 'Windows':
|
|
os.system('subst b: /D')
|
|
|
|
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)
|