1## @file 2# 3# This file is the main entry for UPT 4# 5# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR> 6# 7# SPDX-License-Identifier: BSD-2-Clause-Patent 8# 9 10''' 11UPT 12''' 13 14## import modules 15# 16import locale 17import sys 18from imp import reload 19encoding = locale.getdefaultlocale()[1] 20if encoding: 21 reload(sys) 22 sys.setdefaultencoding(encoding) 23from Core import FileHook 24import os.path 25from sys import platform 26import platform as pf 27from optparse import OptionParser 28from traceback import format_exc 29from platform import python_version 30 31from Logger import StringTable as ST 32import Logger.Log as Logger 33from Logger.StringTable import MSG_VERSION 34from Logger.StringTable import MSG_DESCRIPTION 35from Logger.StringTable import MSG_USAGE 36from Logger.ToolError import FILE_NOT_FOUND 37from Logger.ToolError import OPTION_MISSING 38from Logger.ToolError import FILE_TYPE_MISMATCH 39from Logger.ToolError import OPTION_CONFLICT 40from Logger.ToolError import FatalError 41from Logger.ToolError import UPT_ALREADY_INSTALLED_ERROR 42from Common.MultipleWorkspace import MultipleWorkspace as mws 43 44import MkPkg 45import InstallPkg 46import RmPkg 47import InventoryWs 48import ReplacePkg 49import TestInstall 50from Library.Misc import GetWorkspace 51from Library import GlobalData 52from Core.IpiDb import IpiDatabase 53from BuildVersion import gBUILD_VERSION 54 55## CheckConflictOption 56# 57# CheckConflictOption 58# 59def CheckConflictOption(Opt): 60 if (Opt.PackFileToCreate or Opt.PackFileToInstall or Opt.PackFileToRemove or Opt.PackFileToReplace) \ 61 and Opt.InventoryWs: 62 Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_L_OA_EXCLUSIVE) 63 elif Opt.PackFileToReplace and (Opt.PackFileToCreate or Opt.PackFileToInstall or Opt.PackFileToRemove): 64 Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_U_ICR_EXCLUSIVE) 65 elif (Opt.PackFileToCreate and Opt.PackFileToInstall and Opt.PackFileToRemove): 66 Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_REQUIRE_I_C_R_OPTION) 67 elif Opt.PackFileToCreate and Opt.PackFileToInstall: 68 Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_I_C_EXCLUSIVE) 69 elif Opt.PackFileToInstall and Opt.PackFileToRemove: 70 Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_I_R_EXCLUSIVE) 71 elif Opt.PackFileToCreate and Opt.PackFileToRemove: 72 Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_C_R_EXCLUSIVE) 73 elif Opt.TestDistFiles and (Opt.PackFileToCreate or Opt.PackFileToInstall \ 74 or Opt.PackFileToRemove or Opt.PackFileToReplace): 75 Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_C_R_EXCLUSIVE) 76 77 if Opt.CustomPath and Opt.UseGuidedPkgPath: 78 Logger.Warn("UPT", ST.WARN_CUSTOMPATH_OVERRIDE_USEGUIDEDPATH) 79 Opt.UseGuidedPkgPath = False 80 81## SetLogLevel 82# 83def SetLogLevel(Opt): 84 if Opt.opt_verbose: 85 Logger.SetLevel(Logger.VERBOSE) 86 elif Opt.opt_quiet: 87 Logger.SetLevel(Logger.QUIET + 1) 88 elif Opt.debug_level is not None: 89 if Opt.debug_level < 0 or Opt.debug_level > 9: 90 Logger.Warn("UPT", ST.ERR_DEBUG_LEVEL) 91 Logger.SetLevel(Logger.INFO) 92 else: 93 Logger.SetLevel(Opt.debug_level + 1) 94 elif Opt.opt_slient: 95 Logger.SetLevel(Logger.SILENT) 96 else: 97 Logger.SetLevel(Logger.INFO) 98 99## Main 100# 101# Main 102# 103def Main(): 104 Logger.Initialize() 105 106 Parser = OptionParser(version=(MSG_VERSION + ' Build ' + gBUILD_VERSION), description=MSG_DESCRIPTION, 107 prog="UPT.exe", usage=MSG_USAGE) 108 109 Parser.add_option("-d", "--debug", action="store", type="int", dest="debug_level", help=ST.HLP_PRINT_DEBUG_INFO) 110 111 Parser.add_option("-v", "--verbose", action="store_true", dest="opt_verbose", 112 help=ST.HLP_PRINT_INFORMATIONAL_STATEMENT) 113 114 Parser.add_option("-s", "--silent", action="store_true", dest="opt_slient", help=ST.HLP_RETURN_NO_DISPLAY) 115 116 Parser.add_option("-q", "--quiet", action="store_true", dest="opt_quiet", help=ST.HLP_RETURN_AND_DISPLAY) 117 118 Parser.add_option("-i", "--install", action="append", type="string", dest="Install_Distribution_Package_File", 119 help=ST.HLP_SPECIFY_PACKAGE_NAME_INSTALL) 120 121 Parser.add_option("-c", "--create", action="store", type="string", dest="Create_Distribution_Package_File", 122 help=ST.HLP_SPECIFY_PACKAGE_NAME_CREATE) 123 124 Parser.add_option("-r", "--remove", action="store", type="string", dest="Remove_Distribution_Package_File", 125 help=ST.HLP_SPECIFY_PACKAGE_NAME_REMOVE) 126 127 Parser.add_option("-t", "--template", action="store", type="string", dest="Package_Information_Data_File", 128 help=ST.HLP_SPECIFY_TEMPLATE_NAME_CREATE) 129 130 Parser.add_option("-p", "--dec-filename", action="append", type="string", dest="EDK2_DEC_Filename", 131 help=ST.HLP_SPECIFY_DEC_NAME_CREATE) 132 133 Parser.add_option("-m", "--inf-filename", action="append", type="string", dest="EDK2_INF_Filename", 134 help=ST.HLP_SPECIFY_INF_NAME_CREATE) 135 136 Parser.add_option("-l", "--list", action="store_true", dest="List_Dist_Installed", 137 help=ST.HLP_LIST_DIST_INSTALLED) 138 139 Parser.add_option("-f", "--force", action="store_true", dest="Yes", help=ST.HLP_DISABLE_PROMPT) 140 141 Parser.add_option("-n", "--custom-path", action="store_true", dest="CustomPath", help=ST.HLP_CUSTOM_PATH_PROMPT) 142 143 Parser.add_option("-x", "--free-lock", action="store_true", dest="SkipLock", help=ST.HLP_SKIP_LOCK_CHECK) 144 145 Parser.add_option("-u", "--replace", action="store", type="string", dest="Replace_Distribution_Package_File", 146 help=ST.HLP_SPECIFY_PACKAGE_NAME_REPLACE) 147 148 Parser.add_option("-o", "--original", action="store", type="string", dest="Original_Distribution_Package_File", 149 help=ST.HLP_SPECIFY_PACKAGE_NAME_TO_BE_REPLACED) 150 151 Parser.add_option("--use-guided-paths", action="store_true", dest="Use_Guided_Paths", help=ST.HLP_USE_GUIDED_PATHS) 152 153 Parser.add_option("-j", "--test-install", action="append", type="string", 154 dest="Test_Install_Distribution_Package_Files", help=ST.HLP_TEST_INSTALL) 155 156 Opt = Parser.parse_args()[0] 157 158 Var2Var = [ 159 ("PackageInformationDataFile", Opt.Package_Information_Data_File), 160 ("PackFileToInstall", Opt.Install_Distribution_Package_File), 161 ("PackFileToCreate", Opt.Create_Distribution_Package_File), 162 ("PackFileToRemove", Opt.Remove_Distribution_Package_File), 163 ("PackageFileList", Opt.EDK2_DEC_Filename), 164 ("ModuleFileList", Opt.EDK2_INF_Filename), 165 ("InventoryWs", Opt.List_Dist_Installed), 166 ("PackFileToReplace", Opt.Replace_Distribution_Package_File), 167 ("PackFileToBeReplaced", Opt.Original_Distribution_Package_File), 168 ("UseGuidedPkgPath", Opt.Use_Guided_Paths), 169 ("TestDistFiles", Opt.Test_Install_Distribution_Package_Files) 170 ] 171 172 for Var in Var2Var: 173 setattr(Opt, Var[0], Var[1]) 174 175 try: 176 GlobalData.gWORKSPACE, GlobalData.gPACKAGE_PATH = GetWorkspace() 177 except FatalError as XExcept: 178 if Logger.GetLevel() <= Logger.DEBUG_9: 179 Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + format_exc()) 180 return XExcept.args[0] 181 182 # Support WORKSPACE is a long path 183 # Only works for windows system 184 if pf.system() == 'Windows': 185 Vol = 'B:' 186 for Index in range(90, 65, -1): 187 Vol = chr(Index) + ':' 188 if not os.path.isdir(Vol): 189 os.system('subst %s "%s"' % (Vol, GlobalData.gWORKSPACE)) 190 break 191 GlobalData.gWORKSPACE = '%s\\' % Vol 192 193 WorkspaceDir = GlobalData.gWORKSPACE 194 195 SetLogLevel(Opt) 196 197 Mgr = FileHook.RecoverMgr(WorkspaceDir) 198 FileHook.SetRecoverMgr(Mgr) 199 200 GlobalData.gDB = IpiDatabase(os.path.normpath(os.path.join(WorkspaceDir, \ 201 "Conf/DistributionPackageDatabase.db")), WorkspaceDir) 202 GlobalData.gDB.InitDatabase(Opt.SkipLock) 203 204 # 205 # Make sure the Db will get closed correctly 206 # 207 try: 208 ReturnCode = 0 209 CheckConflictOption(Opt) 210 211 RunModule = None 212 if Opt.PackFileToCreate: 213 if Opt.PackageInformationDataFile: 214 if not os.path.exists(Opt.PackageInformationDataFile): 215 if not os.path.exists(os.path.join(WorkspaceDir, Opt.PackageInformationDataFile)): 216 Logger.Error("\nUPT", FILE_NOT_FOUND, ST.ERR_NO_TEMPLATE_FILE % Opt.PackageInformationDataFile) 217 else: 218 Opt.PackageInformationDataFile = os.path.join(WorkspaceDir, Opt.PackageInformationDataFile) 219 else: 220 Logger.Error("UPT", OPTION_MISSING, ExtraData=ST.ERR_REQUIRE_T_OPTION) 221 if not Opt.PackFileToCreate.endswith('.dist'): 222 Logger.Error("CreatePkg", FILE_TYPE_MISMATCH, ExtraData=ST.ERR_DIST_EXT_ERROR % Opt.PackFileToCreate) 223 RunModule = MkPkg.Main 224 225 elif Opt.PackFileToInstall: 226 AbsPath = [] 227 for Item in Opt.PackFileToInstall: 228 if not Item.endswith('.dist'): 229 Logger.Error("InstallPkg", FILE_TYPE_MISMATCH, ExtraData=ST.ERR_DIST_EXT_ERROR % Item) 230 231 AbsPath.append(GetFullPathDist(Item, WorkspaceDir)) 232 if not AbsPath: 233 Logger.Error("InstallPkg", FILE_NOT_FOUND, ST.ERR_INSTALL_DIST_NOT_FOUND % Item) 234 235 Opt.PackFileToInstall = AbsPath 236 setattr(Opt, 'PackageFile', Opt.PackFileToInstall) 237 RunModule = InstallPkg.Main 238 239 elif Opt.PackFileToRemove: 240 if not Opt.PackFileToRemove.endswith('.dist'): 241 Logger.Error("RemovePkg", FILE_TYPE_MISMATCH, ExtraData=ST.ERR_DIST_EXT_ERROR % Opt.PackFileToRemove) 242 head, tail = os.path.split(Opt.PackFileToRemove) 243 if head or not tail: 244 Logger.Error("RemovePkg", 245 FILE_TYPE_MISMATCH, 246 ExtraData=ST.ERR_DIST_FILENAME_ONLY_FOR_REMOVE % Opt.PackFileToRemove) 247 248 setattr(Opt, 'DistributionFile', Opt.PackFileToRemove) 249 RunModule = RmPkg.Main 250 elif Opt.InventoryWs: 251 RunModule = InventoryWs.Main 252 253 elif Opt.PackFileToBeReplaced and not Opt.PackFileToReplace: 254 Logger.Error("ReplacePkg", OPTION_MISSING, ExtraData=ST.ERR_REQUIRE_U_OPTION) 255 256 elif Opt.PackFileToReplace: 257 if not Opt.PackFileToReplace.endswith('.dist'): 258 Logger.Error("ReplacePkg", FILE_TYPE_MISMATCH, ExtraData=ST.ERR_DIST_EXT_ERROR % Opt.PackFileToReplace) 259 if not Opt.PackFileToBeReplaced: 260 Logger.Error("ReplacePkg", OPTION_MISSING, ExtraData=ST.ERR_REQUIRE_O_OPTION) 261 if not Opt.PackFileToBeReplaced.endswith('.dist'): 262 Logger.Error("ReplacePkg", 263 FILE_TYPE_MISMATCH, 264 ExtraData=ST.ERR_DIST_EXT_ERROR % Opt.PackFileToBeReplaced) 265 266 head, tail = os.path.split(Opt.PackFileToBeReplaced) 267 if head or not tail: 268 Logger.Error("ReplacePkg", 269 FILE_TYPE_MISMATCH, 270 ExtraData=ST.ERR_DIST_FILENAME_ONLY_FOR_REPLACE_ORIG % Opt.PackFileToBeReplaced) 271 272 AbsPath = GetFullPathDist(Opt.PackFileToReplace, WorkspaceDir) 273 if not AbsPath: 274 Logger.Error("ReplacePkg", FILE_NOT_FOUND, ST.ERR_REPLACE_DIST_NOT_FOUND % Opt.PackFileToReplace) 275 276 Opt.PackFileToReplace = AbsPath 277 RunModule = ReplacePkg.Main 278 279 elif Opt.Test_Install_Distribution_Package_Files: 280 for Dist in Opt.Test_Install_Distribution_Package_Files: 281 if not Dist.endswith('.dist'): 282 Logger.Error("TestInstall", FILE_TYPE_MISMATCH, ExtraData=ST.ERR_DIST_EXT_ERROR % Dist) 283 284 setattr(Opt, 'DistFiles', Opt.Test_Install_Distribution_Package_Files) 285 RunModule = TestInstall.Main 286 287 else: 288 Parser.print_usage() 289 return OPTION_MISSING 290 291 ReturnCode = RunModule(Opt) 292 except FatalError as XExcept: 293 ReturnCode = XExcept.args[0] 294 if Logger.GetLevel() <= Logger.DEBUG_9: 295 Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + \ 296 format_exc()) 297 finally: 298 try: 299 if ReturnCode != 0 and ReturnCode != UPT_ALREADY_INSTALLED_ERROR: 300 Logger.Quiet(ST.MSG_RECOVER_START) 301 GlobalData.gDB.RollBack() 302 Mgr.rollback() 303 Logger.Quiet(ST.MSG_RECOVER_DONE) 304 else: 305 GlobalData.gDB.Commit() 306 Mgr.commit() 307 except Exception: 308 Logger.Quiet(ST.MSG_RECOVER_FAIL) 309 GlobalData.gDB.CloseDb() 310 311 if pf.system() == 'Windows': 312 os.system('subst %s /D' % GlobalData.gWORKSPACE.replace('\\', '')) 313 314 return ReturnCode 315 316## GetFullPathDist 317# 318# This function will check DistFile existence, if not absolute path, then try current working directory, 319# then $(WORKSPACE),and return the AbsPath. If file doesn't find, then return None 320# 321# @param DistFile: The distribution file in either relative path or absolute path 322# @param WorkspaceDir: Workspace Directory 323# @return AbsPath: The Absolute path of the distribution file if existed, None else 324# 325def GetFullPathDist(DistFile, WorkspaceDir): 326 if os.path.isabs(DistFile): 327 if not (os.path.exists(DistFile) and os.path.isfile(DistFile)): 328 return None 329 else: 330 return DistFile 331 else: 332 AbsPath = os.path.normpath(os.path.join(os.getcwd(), DistFile)) 333 if not (os.path.exists(AbsPath) and os.path.isfile(AbsPath)): 334 AbsPath = os.path.normpath(os.path.join(WorkspaceDir, DistFile)) 335 if not (os.path.exists(AbsPath) and os.path.isfile(AbsPath)): 336 return None 337 338 return AbsPath 339 340if __name__ == '__main__': 341 RETVAL = Main() 342 # 343 # 0-127 is a safe return range, and 1 is a standard default error 344 # 345 if RETVAL < 0 or RETVAL > 127: 346 RETVAL = 1 347 sys.exit(RETVAL) 348