3 # This file is the main entry for UPT
5 # Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
7 # SPDX-License-Identifier: BSD-2-Clause-Patent
18 from imp
import reload
19 encoding
= locale
.getdefaultlocale()[1]
22 sys
.setdefaultencoding(encoding
)
23 from Core
import FileHook
25 from sys
import platform
27 from optparse
import OptionParser
28 from traceback
import format_exc
29 from platform
import python_version
31 from Logger
import StringTable
as ST
32 import Logger
.Log
as Logger
33 from Logger
.StringTable
import MSG_VERSION
34 from Logger
.StringTable
import MSG_DESCRIPTION
35 from Logger
.StringTable
import MSG_USAGE
36 from Logger
.ToolError
import FILE_NOT_FOUND
37 from Logger
.ToolError
import OPTION_MISSING
38 from Logger
.ToolError
import FILE_TYPE_MISMATCH
39 from Logger
.ToolError
import OPTION_CONFLICT
40 from Logger
.ToolError
import FatalError
41 from Logger
.ToolError
import UPT_ALREADY_INSTALLED_ERROR
42 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
50 from Library
.Misc
import GetWorkspace
51 from Library
import GlobalData
52 from Core
.IpiDb
import IpiDatabase
53 from BuildVersion
import gBUILD_VERSION
55 ## CheckConflictOption
59 def CheckConflictOption(Opt
):
60 if (Opt
.PackFileToCreate
or Opt
.PackFileToInstall
or Opt
.PackFileToRemove
or Opt
.PackFileToReplace
) \
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
)
77 if Opt
.CustomPath
and Opt
.UseGuidedPkgPath
:
78 Logger
.Warn("UPT", ST
.WARN_CUSTOMPATH_OVERRIDE_USEGUIDEDPATH
)
79 Opt
.UseGuidedPkgPath
= False
85 Logger
.SetLevel(Logger
.VERBOSE
)
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
)
93 Logger
.SetLevel(Opt
.debug_level
+ 1)
95 Logger
.SetLevel(Logger
.SILENT
)
97 Logger
.SetLevel(Logger
.INFO
)
106 Parser
= OptionParser(version
=(MSG_VERSION
+ ' Build ' + gBUILD_VERSION
), description
=MSG_DESCRIPTION
,
107 prog
="UPT.exe", usage
=MSG_USAGE
)
109 Parser
.add_option("-d", "--debug", action
="store", type="int", dest
="debug_level", help=ST
.HLP_PRINT_DEBUG_INFO
)
111 Parser
.add_option("-v", "--verbose", action
="store_true", dest
="opt_verbose",
112 help=ST
.HLP_PRINT_INFORMATIONAL_STATEMENT
)
114 Parser
.add_option("-s", "--silent", action
="store_true", dest
="opt_slient", help=ST
.HLP_RETURN_NO_DISPLAY
)
116 Parser
.add_option("-q", "--quiet", action
="store_true", dest
="opt_quiet", help=ST
.HLP_RETURN_AND_DISPLAY
)
118 Parser
.add_option("-i", "--install", action
="append", type="string", dest
="Install_Distribution_Package_File",
119 help=ST
.HLP_SPECIFY_PACKAGE_NAME_INSTALL
)
121 Parser
.add_option("-c", "--create", action
="store", type="string", dest
="Create_Distribution_Package_File",
122 help=ST
.HLP_SPECIFY_PACKAGE_NAME_CREATE
)
124 Parser
.add_option("-r", "--remove", action
="store", type="string", dest
="Remove_Distribution_Package_File",
125 help=ST
.HLP_SPECIFY_PACKAGE_NAME_REMOVE
)
127 Parser
.add_option("-t", "--template", action
="store", type="string", dest
="Package_Information_Data_File",
128 help=ST
.HLP_SPECIFY_TEMPLATE_NAME_CREATE
)
130 Parser
.add_option("-p", "--dec-filename", action
="append", type="string", dest
="EDK2_DEC_Filename",
131 help=ST
.HLP_SPECIFY_DEC_NAME_CREATE
)
133 Parser
.add_option("-m", "--inf-filename", action
="append", type="string", dest
="EDK2_INF_Filename",
134 help=ST
.HLP_SPECIFY_INF_NAME_CREATE
)
136 Parser
.add_option("-l", "--list", action
="store_true", dest
="List_Dist_Installed",
137 help=ST
.HLP_LIST_DIST_INSTALLED
)
139 Parser
.add_option("-f", "--force", action
="store_true", dest
="Yes", help=ST
.HLP_DISABLE_PROMPT
)
141 Parser
.add_option("-n", "--custom-path", action
="store_true", dest
="CustomPath", help=ST
.HLP_CUSTOM_PATH_PROMPT
)
143 Parser
.add_option("-x", "--free-lock", action
="store_true", dest
="SkipLock", help=ST
.HLP_SKIP_LOCK_CHECK
)
145 Parser
.add_option("-u", "--replace", action
="store", type="string", dest
="Replace_Distribution_Package_File",
146 help=ST
.HLP_SPECIFY_PACKAGE_NAME_REPLACE
)
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
)
151 Parser
.add_option("--use-guided-paths", action
="store_true", dest
="Use_Guided_Paths", help=ST
.HLP_USE_GUIDED_PATHS
)
153 Parser
.add_option("-j", "--test-install", action
="append", type="string",
154 dest
="Test_Install_Distribution_Package_Files", help=ST
.HLP_TEST_INSTALL
)
156 Opt
= Parser
.parse_args()[0]
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
)
173 setattr(Opt
, Var
[0], Var
[1])
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]
182 # Support WORKSPACE is a long path
183 # Only works for windows system
184 if pf
.system() == 'Windows':
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
))
191 GlobalData
.gWORKSPACE
= '%s\\' % Vol
193 WorkspaceDir
= GlobalData
.gWORKSPACE
197 Mgr
= FileHook
.RecoverMgr(WorkspaceDir
)
198 FileHook
.SetRecoverMgr(Mgr
)
200 GlobalData
.gDB
= IpiDatabase(os
.path
.normpath(os
.path
.join(WorkspaceDir
, \
201 "Conf/DistributionPackageDatabase.db")), WorkspaceDir
)
202 GlobalData
.gDB
.InitDatabase(Opt
.SkipLock
)
205 # Make sure the Db will get closed correctly
209 CheckConflictOption(Opt
)
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
)
218 Opt
.PackageInformationDataFile
= os
.path
.join(WorkspaceDir
, Opt
.PackageInformationDataFile
)
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
225 elif Opt
.PackFileToInstall
:
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
)
231 AbsPath
.append(GetFullPathDist(Item
, WorkspaceDir
))
233 Logger
.Error("InstallPkg", FILE_NOT_FOUND
, ST
.ERR_INSTALL_DIST_NOT_FOUND
% Item
)
235 Opt
.PackFileToInstall
= AbsPath
236 setattr(Opt
, 'PackageFile', Opt
.PackFileToInstall
)
237 RunModule
= InstallPkg
.Main
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
)
244 Logger
.Error("RemovePkg",
246 ExtraData
=ST
.ERR_DIST_FILENAME_ONLY_FOR_REMOVE
% Opt
.PackFileToRemove
)
248 setattr(Opt
, 'DistributionFile', Opt
.PackFileToRemove
)
249 RunModule
= RmPkg
.Main
250 elif Opt
.InventoryWs
:
251 RunModule
= InventoryWs
.Main
253 elif Opt
.PackFileToBeReplaced
and not Opt
.PackFileToReplace
:
254 Logger
.Error("ReplacePkg", OPTION_MISSING
, ExtraData
=ST
.ERR_REQUIRE_U_OPTION
)
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",
264 ExtraData
=ST
.ERR_DIST_EXT_ERROR
% Opt
.PackFileToBeReplaced
)
266 head
, tail
= os
.path
.split(Opt
.PackFileToBeReplaced
)
268 Logger
.Error("ReplacePkg",
270 ExtraData
=ST
.ERR_DIST_FILENAME_ONLY_FOR_REPLACE_ORIG
% Opt
.PackFileToBeReplaced
)
272 AbsPath
= GetFullPathDist(Opt
.PackFileToReplace
, WorkspaceDir
)
274 Logger
.Error("ReplacePkg", FILE_NOT_FOUND
, ST
.ERR_REPLACE_DIST_NOT_FOUND
% Opt
.PackFileToReplace
)
276 Opt
.PackFileToReplace
= AbsPath
277 RunModule
= ReplacePkg
.Main
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
)
284 setattr(Opt
, 'DistFiles', Opt
.Test_Install_Distribution_Package_Files
)
285 RunModule
= TestInstall
.Main
289 return OPTION_MISSING
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
) + \
299 if ReturnCode
!= 0 and ReturnCode
!= UPT_ALREADY_INSTALLED_ERROR
:
300 Logger
.Quiet(ST
.MSG_RECOVER_START
)
301 GlobalData
.gDB
.RollBack()
303 Logger
.Quiet(ST
.MSG_RECOVER_DONE
)
305 GlobalData
.gDB
.Commit()
308 Logger
.Quiet(ST
.MSG_RECOVER_FAIL
)
309 GlobalData
.gDB
.CloseDb()
311 if pf
.system() == 'Windows':
312 os
.system('subst %s /D' % GlobalData
.gWORKSPACE
.replace('\\', ''))
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
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
325 def GetFullPathDist(DistFile
, WorkspaceDir
):
326 if os
.path
.isabs(DistFile
):
327 if not (os
.path
.exists(DistFile
) and os
.path
.isfile(DistFile
)):
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
)):
340 if __name__
== '__main__':
343 # 0-127 is a safe return range, and 1 is a standard default error
345 if RETVAL
< 0 or RETVAL
> 127: