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