3 # This file is the main entry for UPT
5 # Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
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
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.
24 from imp
import reload
25 encoding
= locale
.getdefaultlocale()[1]
28 sys
.setdefaultencoding(encoding
)
29 from Core
import FileHook
31 from sys
import platform
33 from optparse
import OptionParser
34 from traceback
import format_exc
35 from platform
import python_version
37 from Logger
import StringTable
as ST
38 import Logger
.Log
as Logger
39 from Logger
.StringTable
import MSG_VERSION
40 from Logger
.StringTable
import MSG_DESCRIPTION
41 from Logger
.StringTable
import MSG_USAGE
42 from Logger
.ToolError
import FILE_NOT_FOUND
43 from Logger
.ToolError
import OPTION_MISSING
44 from Logger
.ToolError
import FILE_TYPE_MISMATCH
45 from Logger
.ToolError
import OPTION_CONFLICT
46 from Logger
.ToolError
import FatalError
47 from Logger
.ToolError
import UPT_ALREADY_INSTALLED_ERROR
48 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
56 from Library
.Misc
import GetWorkspace
57 from Library
import GlobalData
58 from Core
.IpiDb
import IpiDatabase
59 from BuildVersion
import gBUILD_VERSION
61 ## CheckConflictOption
65 def CheckConflictOption(Opt
):
66 if (Opt
.PackFileToCreate
or Opt
.PackFileToInstall
or Opt
.PackFileToRemove
or Opt
.PackFileToReplace
) \
68 Logger
.Error("UPT", OPTION_CONFLICT
, ExtraData
=ST
.ERR_L_OA_EXCLUSIVE
)
69 elif Opt
.PackFileToReplace
and (Opt
.PackFileToCreate
or Opt
.PackFileToInstall
or Opt
.PackFileToRemove
):
70 Logger
.Error("UPT", OPTION_CONFLICT
, ExtraData
=ST
.ERR_U_ICR_EXCLUSIVE
)
71 elif (Opt
.PackFileToCreate
and Opt
.PackFileToInstall
and Opt
.PackFileToRemove
):
72 Logger
.Error("UPT", OPTION_CONFLICT
, ExtraData
=ST
.ERR_REQUIRE_I_C_R_OPTION
)
73 elif Opt
.PackFileToCreate
and Opt
.PackFileToInstall
:
74 Logger
.Error("UPT", OPTION_CONFLICT
, ExtraData
=ST
.ERR_I_C_EXCLUSIVE
)
75 elif Opt
.PackFileToInstall
and Opt
.PackFileToRemove
:
76 Logger
.Error("UPT", OPTION_CONFLICT
, ExtraData
=ST
.ERR_I_R_EXCLUSIVE
)
77 elif Opt
.PackFileToCreate
and Opt
.PackFileToRemove
:
78 Logger
.Error("UPT", OPTION_CONFLICT
, ExtraData
=ST
.ERR_C_R_EXCLUSIVE
)
79 elif Opt
.TestDistFiles
and (Opt
.PackFileToCreate
or Opt
.PackFileToInstall \
80 or Opt
.PackFileToRemove
or Opt
.PackFileToReplace
):
81 Logger
.Error("UPT", OPTION_CONFLICT
, ExtraData
=ST
.ERR_C_R_EXCLUSIVE
)
83 if Opt
.CustomPath
and Opt
.UseGuidedPkgPath
:
84 Logger
.Warn("UPT", ST
.WARN_CUSTOMPATH_OVERRIDE_USEGUIDEDPATH
)
85 Opt
.UseGuidedPkgPath
= False
91 Logger
.SetLevel(Logger
.VERBOSE
)
93 Logger
.SetLevel(Logger
.QUIET
+ 1)
94 elif Opt
.debug_level
is not None:
95 if Opt
.debug_level
< 0 or Opt
.debug_level
> 9:
96 Logger
.Warn("UPT", ST
.ERR_DEBUG_LEVEL
)
97 Logger
.SetLevel(Logger
.INFO
)
99 Logger
.SetLevel(Opt
.debug_level
+ 1)
101 Logger
.SetLevel(Logger
.SILENT
)
103 Logger
.SetLevel(Logger
.INFO
)
112 Parser
= OptionParser(version
=(MSG_VERSION
+ ' Build ' + gBUILD_VERSION
), description
=MSG_DESCRIPTION
,
113 prog
="UPT.exe", usage
=MSG_USAGE
)
115 Parser
.add_option("-d", "--debug", action
="store", type="int", dest
="debug_level", help=ST
.HLP_PRINT_DEBUG_INFO
)
117 Parser
.add_option("-v", "--verbose", action
="store_true", dest
="opt_verbose",
118 help=ST
.HLP_PRINT_INFORMATIONAL_STATEMENT
)
120 Parser
.add_option("-s", "--silent", action
="store_true", dest
="opt_slient", help=ST
.HLP_RETURN_NO_DISPLAY
)
122 Parser
.add_option("-q", "--quiet", action
="store_true", dest
="opt_quiet", help=ST
.HLP_RETURN_AND_DISPLAY
)
124 Parser
.add_option("-i", "--install", action
="append", type="string", dest
="Install_Distribution_Package_File",
125 help=ST
.HLP_SPECIFY_PACKAGE_NAME_INSTALL
)
127 Parser
.add_option("-c", "--create", action
="store", type="string", dest
="Create_Distribution_Package_File",
128 help=ST
.HLP_SPECIFY_PACKAGE_NAME_CREATE
)
130 Parser
.add_option("-r", "--remove", action
="store", type="string", dest
="Remove_Distribution_Package_File",
131 help=ST
.HLP_SPECIFY_PACKAGE_NAME_REMOVE
)
133 Parser
.add_option("-t", "--template", action
="store", type="string", dest
="Package_Information_Data_File",
134 help=ST
.HLP_SPECIFY_TEMPLATE_NAME_CREATE
)
136 Parser
.add_option("-p", "--dec-filename", action
="append", type="string", dest
="EDK2_DEC_Filename",
137 help=ST
.HLP_SPECIFY_DEC_NAME_CREATE
)
139 Parser
.add_option("-m", "--inf-filename", action
="append", type="string", dest
="EDK2_INF_Filename",
140 help=ST
.HLP_SPECIFY_INF_NAME_CREATE
)
142 Parser
.add_option("-l", "--list", action
="store_true", dest
="List_Dist_Installed",
143 help=ST
.HLP_LIST_DIST_INSTALLED
)
145 Parser
.add_option("-f", "--force", action
="store_true", dest
="Yes", help=ST
.HLP_DISABLE_PROMPT
)
147 Parser
.add_option("-n", "--custom-path", action
="store_true", dest
="CustomPath", help=ST
.HLP_CUSTOM_PATH_PROMPT
)
149 Parser
.add_option("-x", "--free-lock", action
="store_true", dest
="SkipLock", help=ST
.HLP_SKIP_LOCK_CHECK
)
151 Parser
.add_option("-u", "--replace", action
="store", type="string", dest
="Replace_Distribution_Package_File",
152 help=ST
.HLP_SPECIFY_PACKAGE_NAME_REPLACE
)
154 Parser
.add_option("-o", "--original", action
="store", type="string", dest
="Original_Distribution_Package_File",
155 help=ST
.HLP_SPECIFY_PACKAGE_NAME_TO_BE_REPLACED
)
157 Parser
.add_option("--use-guided-paths", action
="store_true", dest
="Use_Guided_Paths", help=ST
.HLP_USE_GUIDED_PATHS
)
159 Parser
.add_option("-j", "--test-install", action
="append", type="string",
160 dest
="Test_Install_Distribution_Package_Files", help=ST
.HLP_TEST_INSTALL
)
162 Opt
= Parser
.parse_args()[0]
165 ("PackageInformationDataFile", Opt
.Package_Information_Data_File
),
166 ("PackFileToInstall", Opt
.Install_Distribution_Package_File
),
167 ("PackFileToCreate", Opt
.Create_Distribution_Package_File
),
168 ("PackFileToRemove", Opt
.Remove_Distribution_Package_File
),
169 ("PackageFileList", Opt
.EDK2_DEC_Filename
),
170 ("ModuleFileList", Opt
.EDK2_INF_Filename
),
171 ("InventoryWs", Opt
.List_Dist_Installed
),
172 ("PackFileToReplace", Opt
.Replace_Distribution_Package_File
),
173 ("PackFileToBeReplaced", Opt
.Original_Distribution_Package_File
),
174 ("UseGuidedPkgPath", Opt
.Use_Guided_Paths
),
175 ("TestDistFiles", Opt
.Test_Install_Distribution_Package_Files
)
179 setattr(Opt
, Var
[0], Var
[1])
182 GlobalData
.gWORKSPACE
, GlobalData
.gPACKAGE_PATH
= GetWorkspace()
183 except FatalError
as XExcept
:
184 if Logger
.GetLevel() <= Logger
.DEBUG_9
:
185 Logger
.Quiet(ST
.MSG_PYTHON_ON
% (python_version(), platform
) + format_exc())
186 return XExcept
.args
[0]
188 # Support WORKSPACE is a long path
189 # Only works for windows system
190 if pf
.system() == 'Windows':
192 for Index
in range(90, 65, -1):
193 Vol
= chr(Index
) + ':'
194 if not os
.path
.isdir(Vol
):
195 os
.system('subst %s "%s"' % (Vol
, GlobalData
.gWORKSPACE
))
197 GlobalData
.gWORKSPACE
= '%s\\' % Vol
199 WorkspaceDir
= GlobalData
.gWORKSPACE
203 Mgr
= FileHook
.RecoverMgr(WorkspaceDir
)
204 FileHook
.SetRecoverMgr(Mgr
)
206 GlobalData
.gDB
= IpiDatabase(os
.path
.normpath(os
.path
.join(WorkspaceDir
, \
207 "Conf/DistributionPackageDatabase.db")), WorkspaceDir
)
208 GlobalData
.gDB
.InitDatabase(Opt
.SkipLock
)
211 # Make sure the Db will get closed correctly
215 CheckConflictOption(Opt
)
218 if Opt
.PackFileToCreate
:
219 if Opt
.PackageInformationDataFile
:
220 if not os
.path
.exists(Opt
.PackageInformationDataFile
):
221 if not os
.path
.exists(os
.path
.join(WorkspaceDir
, Opt
.PackageInformationDataFile
)):
222 Logger
.Error("\nUPT", FILE_NOT_FOUND
, ST
.ERR_NO_TEMPLATE_FILE
% Opt
.PackageInformationDataFile
)
224 Opt
.PackageInformationDataFile
= os
.path
.join(WorkspaceDir
, Opt
.PackageInformationDataFile
)
226 Logger
.Error("UPT", OPTION_MISSING
, ExtraData
=ST
.ERR_REQUIRE_T_OPTION
)
227 if not Opt
.PackFileToCreate
.endswith('.dist'):
228 Logger
.Error("CreatePkg", FILE_TYPE_MISMATCH
, ExtraData
=ST
.ERR_DIST_EXT_ERROR
% Opt
.PackFileToCreate
)
229 RunModule
= MkPkg
.Main
231 elif Opt
.PackFileToInstall
:
233 for Item
in Opt
.PackFileToInstall
:
234 if not Item
.endswith('.dist'):
235 Logger
.Error("InstallPkg", FILE_TYPE_MISMATCH
, ExtraData
=ST
.ERR_DIST_EXT_ERROR
% Item
)
237 AbsPath
.append(GetFullPathDist(Item
, WorkspaceDir
))
239 Logger
.Error("InstallPkg", FILE_NOT_FOUND
, ST
.ERR_INSTALL_DIST_NOT_FOUND
% Item
)
241 Opt
.PackFileToInstall
= AbsPath
242 setattr(Opt
, 'PackageFile', Opt
.PackFileToInstall
)
243 RunModule
= InstallPkg
.Main
245 elif Opt
.PackFileToRemove
:
246 if not Opt
.PackFileToRemove
.endswith('.dist'):
247 Logger
.Error("RemovePkg", FILE_TYPE_MISMATCH
, ExtraData
=ST
.ERR_DIST_EXT_ERROR
% Opt
.PackFileToRemove
)
248 head
, tail
= os
.path
.split(Opt
.PackFileToRemove
)
250 Logger
.Error("RemovePkg",
252 ExtraData
=ST
.ERR_DIST_FILENAME_ONLY_FOR_REMOVE
% Opt
.PackFileToRemove
)
254 setattr(Opt
, 'DistributionFile', Opt
.PackFileToRemove
)
255 RunModule
= RmPkg
.Main
256 elif Opt
.InventoryWs
:
257 RunModule
= InventoryWs
.Main
259 elif Opt
.PackFileToBeReplaced
and not Opt
.PackFileToReplace
:
260 Logger
.Error("ReplacePkg", OPTION_MISSING
, ExtraData
=ST
.ERR_REQUIRE_U_OPTION
)
262 elif Opt
.PackFileToReplace
:
263 if not Opt
.PackFileToReplace
.endswith('.dist'):
264 Logger
.Error("ReplacePkg", FILE_TYPE_MISMATCH
, ExtraData
=ST
.ERR_DIST_EXT_ERROR
% Opt
.PackFileToReplace
)
265 if not Opt
.PackFileToBeReplaced
:
266 Logger
.Error("ReplacePkg", OPTION_MISSING
, ExtraData
=ST
.ERR_REQUIRE_O_OPTION
)
267 if not Opt
.PackFileToBeReplaced
.endswith('.dist'):
268 Logger
.Error("ReplacePkg",
270 ExtraData
=ST
.ERR_DIST_EXT_ERROR
% Opt
.PackFileToBeReplaced
)
272 head
, tail
= os
.path
.split(Opt
.PackFileToBeReplaced
)
274 Logger
.Error("ReplacePkg",
276 ExtraData
=ST
.ERR_DIST_FILENAME_ONLY_FOR_REPLACE_ORIG
% Opt
.PackFileToBeReplaced
)
278 AbsPath
= GetFullPathDist(Opt
.PackFileToReplace
, WorkspaceDir
)
280 Logger
.Error("ReplacePkg", FILE_NOT_FOUND
, ST
.ERR_REPLACE_DIST_NOT_FOUND
% Opt
.PackFileToReplace
)
282 Opt
.PackFileToReplace
= AbsPath
283 RunModule
= ReplacePkg
.Main
285 elif Opt
.Test_Install_Distribution_Package_Files
:
286 for Dist
in Opt
.Test_Install_Distribution_Package_Files
:
287 if not Dist
.endswith('.dist'):
288 Logger
.Error("TestInstall", FILE_TYPE_MISMATCH
, ExtraData
=ST
.ERR_DIST_EXT_ERROR
% Dist
)
290 setattr(Opt
, 'DistFiles', Opt
.Test_Install_Distribution_Package_Files
)
291 RunModule
= TestInstall
.Main
295 return OPTION_MISSING
297 ReturnCode
= RunModule(Opt
)
298 except FatalError
as XExcept
:
299 ReturnCode
= XExcept
.args
[0]
300 if Logger
.GetLevel() <= Logger
.DEBUG_9
:
301 Logger
.Quiet(ST
.MSG_PYTHON_ON
% (python_version(), platform
) + \
305 if ReturnCode
!= 0 and ReturnCode
!= UPT_ALREADY_INSTALLED_ERROR
:
306 Logger
.Quiet(ST
.MSG_RECOVER_START
)
307 GlobalData
.gDB
.RollBack()
309 Logger
.Quiet(ST
.MSG_RECOVER_DONE
)
311 GlobalData
.gDB
.Commit()
314 Logger
.Quiet(ST
.MSG_RECOVER_FAIL
)
315 GlobalData
.gDB
.CloseDb()
317 if pf
.system() == 'Windows':
318 os
.system('subst %s /D' % GlobalData
.gWORKSPACE
.replace('\\', ''))
324 # This function will check DistFile existence, if not absolute path, then try current working directory,
325 # then $(WORKSPACE),and return the AbsPath. If file doesn't find, then return None
327 # @param DistFile: The distribution file in either relative path or absolute path
328 # @param WorkspaceDir: Workspace Directory
329 # @return AbsPath: The Absolute path of the distribution file if existed, None else
331 def GetFullPathDist(DistFile
, WorkspaceDir
):
332 if os
.path
.isabs(DistFile
):
333 if not (os
.path
.exists(DistFile
) and os
.path
.isfile(DistFile
)):
338 AbsPath
= os
.path
.normpath(os
.path
.join(os
.getcwd(), DistFile
))
339 if not (os
.path
.exists(AbsPath
) and os
.path
.isfile(AbsPath
)):
340 AbsPath
= os
.path
.normpath(os
.path
.join(WorkspaceDir
, DistFile
))
341 if not (os
.path
.exists(AbsPath
) and os
.path
.isfile(AbsPath
)):
346 if __name__
== '__main__':
349 # 0-127 is a safe return range, and 1 is a standard default error
351 if RETVAL
< 0 or RETVAL
> 127: