3 # This file is the main entry for UPT
5 # Copyright (c) 2011 - 2017, 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 encoding
= locale
.getdefaultlocale()[1]
27 sys
.setdefaultencoding(encoding
)
28 from Core
import FileHook
30 from sys
import platform
32 from optparse
import OptionParser
33 from traceback
import format_exc
34 from platform
import python_version
36 from Logger
import StringTable
as ST
37 import Logger
.Log
as Logger
38 from Logger
.StringTable
import MSG_VERSION
39 from Logger
.StringTable
import MSG_DESCRIPTION
40 from Logger
.StringTable
import MSG_USAGE
41 from Logger
.ToolError
import FILE_NOT_FOUND
42 from Logger
.ToolError
import OPTION_MISSING
43 from Logger
.ToolError
import FILE_TYPE_MISMATCH
44 from Logger
.ToolError
import OPTION_CONFLICT
45 from Logger
.ToolError
import FatalError
46 from Logger
.ToolError
import UPT_ALREADY_INSTALLED_ERROR
47 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
55 from Library
.Misc
import GetWorkspace
56 from Library
import GlobalData
57 from Core
.IpiDb
import IpiDatabase
58 from BuildVersion
import gBUILD_VERSION
60 ## CheckConflictOption
64 def CheckConflictOption(Opt
):
65 if (Opt
.PackFileToCreate
or Opt
.PackFileToInstall
or Opt
.PackFileToRemove
or Opt
.PackFileToReplace
) \
67 Logger
.Error("UPT", OPTION_CONFLICT
, ExtraData
=ST
.ERR_L_OA_EXCLUSIVE
)
68 elif Opt
.PackFileToReplace
and (Opt
.PackFileToCreate
or Opt
.PackFileToInstall
or Opt
.PackFileToRemove
):
69 Logger
.Error("UPT", OPTION_CONFLICT
, ExtraData
=ST
.ERR_U_ICR_EXCLUSIVE
)
70 elif (Opt
.PackFileToCreate
and Opt
.PackFileToInstall
and Opt
.PackFileToRemove
):
71 Logger
.Error("UPT", OPTION_CONFLICT
, ExtraData
=ST
.ERR_REQUIRE_I_C_R_OPTION
)
72 elif Opt
.PackFileToCreate
and Opt
.PackFileToInstall
:
73 Logger
.Error("UPT", OPTION_CONFLICT
, ExtraData
=ST
.ERR_I_C_EXCLUSIVE
)
74 elif Opt
.PackFileToInstall
and Opt
.PackFileToRemove
:
75 Logger
.Error("UPT", OPTION_CONFLICT
, ExtraData
=ST
.ERR_I_R_EXCLUSIVE
)
76 elif Opt
.PackFileToCreate
and Opt
.PackFileToRemove
:
77 Logger
.Error("UPT", OPTION_CONFLICT
, ExtraData
=ST
.ERR_C_R_EXCLUSIVE
)
78 elif Opt
.TestDistFiles
and (Opt
.PackFileToCreate
or Opt
.PackFileToInstall \
79 or Opt
.PackFileToRemove
or Opt
.PackFileToReplace
):
80 Logger
.Error("UPT", OPTION_CONFLICT
, ExtraData
=ST
.ERR_C_R_EXCLUSIVE
)
82 if Opt
.CustomPath
and Opt
.UseGuidedPkgPath
:
83 Logger
.Warn("UPT", ST
.WARN_CUSTOMPATH_OVERRIDE_USEGUIDEDPATH
)
84 Opt
.UseGuidedPkgPath
= False
90 Logger
.SetLevel(Logger
.VERBOSE
)
92 Logger
.SetLevel(Logger
.QUIET
+ 1)
93 elif Opt
.debug_level
is not None:
94 if Opt
.debug_level
< 0 or Opt
.debug_level
> 9:
95 Logger
.Warn("UPT", ST
.ERR_DEBUG_LEVEL
)
96 Logger
.SetLevel(Logger
.INFO
)
98 Logger
.SetLevel(Opt
.debug_level
+ 1)
100 Logger
.SetLevel(Logger
.SILENT
)
102 Logger
.SetLevel(Logger
.INFO
)
111 Parser
= OptionParser(version
=(MSG_VERSION
+ ' Build ' + gBUILD_VERSION
), description
=MSG_DESCRIPTION
,
112 prog
="UPT.exe", usage
=MSG_USAGE
)
114 Parser
.add_option("-d", "--debug", action
="store", type="int", dest
="debug_level", help=ST
.HLP_PRINT_DEBUG_INFO
)
116 Parser
.add_option("-v", "--verbose", action
="store_true", dest
="opt_verbose",
117 help=ST
.HLP_PRINT_INFORMATIONAL_STATEMENT
)
119 Parser
.add_option("-s", "--silent", action
="store_true", dest
="opt_slient", help=ST
.HLP_RETURN_NO_DISPLAY
)
121 Parser
.add_option("-q", "--quiet", action
="store_true", dest
="opt_quiet", help=ST
.HLP_RETURN_AND_DISPLAY
)
123 Parser
.add_option("-i", "--install", action
="append", type="string", dest
="Install_Distribution_Package_File",
124 help=ST
.HLP_SPECIFY_PACKAGE_NAME_INSTALL
)
126 Parser
.add_option("-c", "--create", action
="store", type="string", dest
="Create_Distribution_Package_File",
127 help=ST
.HLP_SPECIFY_PACKAGE_NAME_CREATE
)
129 Parser
.add_option("-r", "--remove", action
="store", type="string", dest
="Remove_Distribution_Package_File",
130 help=ST
.HLP_SPECIFY_PACKAGE_NAME_REMOVE
)
132 Parser
.add_option("-t", "--template", action
="store", type="string", dest
="Package_Information_Data_File",
133 help=ST
.HLP_SPECIFY_TEMPLATE_NAME_CREATE
)
135 Parser
.add_option("-p", "--dec-filename", action
="append", type="string", dest
="EDK2_DEC_Filename",
136 help=ST
.HLP_SPECIFY_DEC_NAME_CREATE
)
138 Parser
.add_option("-m", "--inf-filename", action
="append", type="string", dest
="EDK2_INF_Filename",
139 help=ST
.HLP_SPECIFY_INF_NAME_CREATE
)
141 Parser
.add_option("-l", "--list", action
="store_true", dest
="List_Dist_Installed",
142 help=ST
.HLP_LIST_DIST_INSTALLED
)
144 Parser
.add_option("-f", "--force", action
="store_true", dest
="Yes", help=ST
.HLP_DISABLE_PROMPT
)
146 Parser
.add_option("-n", "--custom-path", action
="store_true", dest
="CustomPath", help=ST
.HLP_CUSTOM_PATH_PROMPT
)
148 Parser
.add_option("-x", "--free-lock", action
="store_true", dest
="SkipLock", help=ST
.HLP_SKIP_LOCK_CHECK
)
150 Parser
.add_option("-u", "--replace", action
="store", type="string", dest
="Replace_Distribution_Package_File",
151 help=ST
.HLP_SPECIFY_PACKAGE_NAME_REPLACE
)
153 Parser
.add_option("-o", "--original", action
="store", type="string", dest
="Original_Distribution_Package_File",
154 help=ST
.HLP_SPECIFY_PACKAGE_NAME_TO_BE_REPLACED
)
156 Parser
.add_option("--use-guided-paths", action
="store_true", dest
="Use_Guided_Paths", help=ST
.HLP_USE_GUIDED_PATHS
)
158 Parser
.add_option("-j", "--test-install", action
="append", type="string",
159 dest
="Test_Install_Distribution_Package_Files", help=ST
.HLP_TEST_INSTALL
)
161 Opt
= Parser
.parse_args()[0]
164 ("PackageInformationDataFile", Opt
.Package_Information_Data_File
),
165 ("PackFileToInstall", Opt
.Install_Distribution_Package_File
),
166 ("PackFileToCreate", Opt
.Create_Distribution_Package_File
),
167 ("PackFileToRemove", Opt
.Remove_Distribution_Package_File
),
168 ("PackageFileList", Opt
.EDK2_DEC_Filename
),
169 ("ModuleFileList", Opt
.EDK2_INF_Filename
),
170 ("InventoryWs", Opt
.List_Dist_Installed
),
171 ("PackFileToReplace", Opt
.Replace_Distribution_Package_File
),
172 ("PackFileToBeReplaced", Opt
.Original_Distribution_Package_File
),
173 ("UseGuidedPkgPath", Opt
.Use_Guided_Paths
),
174 ("TestDistFiles", Opt
.Test_Install_Distribution_Package_Files
)
178 setattr(Opt
, Var
[0], Var
[1])
181 GlobalData
.gWORKSPACE
, GlobalData
.gPACKAGE_PATH
= GetWorkspace()
182 except FatalError
as XExcept
:
183 if Logger
.GetLevel() <= Logger
.DEBUG_9
:
184 Logger
.Quiet(ST
.MSG_PYTHON_ON
% (python_version(), platform
) + format_exc())
185 return XExcept
.args
[0]
187 # Support WORKSPACE is a long path
188 # Only works for windows system
189 if pf
.system() == 'Windows':
191 for Index
in range(90, 65, -1):
192 Vol
= chr(Index
) + ':'
193 if not os
.path
.isdir(Vol
):
194 os
.system('subst %s "%s"' % (Vol
, GlobalData
.gWORKSPACE
))
196 GlobalData
.gWORKSPACE
= '%s\\' % Vol
198 WorkspaceDir
= GlobalData
.gWORKSPACE
202 Mgr
= FileHook
.RecoverMgr(WorkspaceDir
)
203 FileHook
.SetRecoverMgr(Mgr
)
205 GlobalData
.gDB
= IpiDatabase(os
.path
.normpath(os
.path
.join(WorkspaceDir
, \
206 "Conf/DistributionPackageDatabase.db")), WorkspaceDir
)
207 GlobalData
.gDB
.InitDatabase(Opt
.SkipLock
)
210 # Make sure the Db will get closed correctly
214 CheckConflictOption(Opt
)
217 if Opt
.PackFileToCreate
:
218 if Opt
.PackageInformationDataFile
:
219 if not os
.path
.exists(Opt
.PackageInformationDataFile
):
220 if not os
.path
.exists(os
.path
.join(WorkspaceDir
, Opt
.PackageInformationDataFile
)):
221 Logger
.Error("\nUPT", FILE_NOT_FOUND
, ST
.ERR_NO_TEMPLATE_FILE
% Opt
.PackageInformationDataFile
)
223 Opt
.PackageInformationDataFile
= os
.path
.join(WorkspaceDir
, Opt
.PackageInformationDataFile
)
225 Logger
.Error("UPT", OPTION_MISSING
, ExtraData
=ST
.ERR_REQUIRE_T_OPTION
)
226 if not Opt
.PackFileToCreate
.endswith('.dist'):
227 Logger
.Error("CreatePkg", FILE_TYPE_MISMATCH
, ExtraData
=ST
.ERR_DIST_EXT_ERROR
% Opt
.PackFileToCreate
)
228 RunModule
= MkPkg
.Main
230 elif Opt
.PackFileToInstall
:
232 for Item
in Opt
.PackFileToInstall
:
233 if not Item
.endswith('.dist'):
234 Logger
.Error("InstallPkg", FILE_TYPE_MISMATCH
, ExtraData
=ST
.ERR_DIST_EXT_ERROR
% Item
)
236 AbsPath
.append(GetFullPathDist(Item
, WorkspaceDir
))
238 Logger
.Error("InstallPkg", FILE_NOT_FOUND
, ST
.ERR_INSTALL_DIST_NOT_FOUND
% Item
)
240 Opt
.PackFileToInstall
= AbsPath
241 setattr(Opt
, 'PackageFile', Opt
.PackFileToInstall
)
242 RunModule
= InstallPkg
.Main
244 elif Opt
.PackFileToRemove
:
245 if not Opt
.PackFileToRemove
.endswith('.dist'):
246 Logger
.Error("RemovePkg", FILE_TYPE_MISMATCH
, ExtraData
=ST
.ERR_DIST_EXT_ERROR
% Opt
.PackFileToRemove
)
247 head
, tail
= os
.path
.split(Opt
.PackFileToRemove
)
249 Logger
.Error("RemovePkg",
251 ExtraData
=ST
.ERR_DIST_FILENAME_ONLY_FOR_REMOVE
% Opt
.PackFileToRemove
)
253 setattr(Opt
, 'DistributionFile', Opt
.PackFileToRemove
)
254 RunModule
= RmPkg
.Main
255 elif Opt
.InventoryWs
:
256 RunModule
= InventoryWs
.Main
258 elif Opt
.PackFileToBeReplaced
and not Opt
.PackFileToReplace
:
259 Logger
.Error("ReplacePkg", OPTION_MISSING
, ExtraData
=ST
.ERR_REQUIRE_U_OPTION
)
261 elif Opt
.PackFileToReplace
:
262 if not Opt
.PackFileToReplace
.endswith('.dist'):
263 Logger
.Error("ReplacePkg", FILE_TYPE_MISMATCH
, ExtraData
=ST
.ERR_DIST_EXT_ERROR
% Opt
.PackFileToReplace
)
264 if not Opt
.PackFileToBeReplaced
:
265 Logger
.Error("ReplacePkg", OPTION_MISSING
, ExtraData
=ST
.ERR_REQUIRE_O_OPTION
)
266 if not Opt
.PackFileToBeReplaced
.endswith('.dist'):
267 Logger
.Error("ReplacePkg",
269 ExtraData
=ST
.ERR_DIST_EXT_ERROR
% Opt
.PackFileToBeReplaced
)
271 head
, tail
= os
.path
.split(Opt
.PackFileToBeReplaced
)
273 Logger
.Error("ReplacePkg",
275 ExtraData
=ST
.ERR_DIST_FILENAME_ONLY_FOR_REPLACE_ORIG
% Opt
.PackFileToBeReplaced
)
277 AbsPath
= GetFullPathDist(Opt
.PackFileToReplace
, WorkspaceDir
)
279 Logger
.Error("ReplacePkg", FILE_NOT_FOUND
, ST
.ERR_REPLACE_DIST_NOT_FOUND
% Opt
.PackFileToReplace
)
281 Opt
.PackFileToReplace
= AbsPath
282 RunModule
= ReplacePkg
.Main
284 elif Opt
.Test_Install_Distribution_Package_Files
:
285 for Dist
in Opt
.Test_Install_Distribution_Package_Files
:
286 if not Dist
.endswith('.dist'):
287 Logger
.Error("TestInstall", FILE_TYPE_MISMATCH
, ExtraData
=ST
.ERR_DIST_EXT_ERROR
% Dist
)
289 setattr(Opt
, 'DistFiles', Opt
.Test_Install_Distribution_Package_Files
)
290 RunModule
= TestInstall
.Main
294 return OPTION_MISSING
296 ReturnCode
= RunModule(Opt
)
297 except FatalError
as XExcept
:
298 ReturnCode
= XExcept
.args
[0]
299 if Logger
.GetLevel() <= Logger
.DEBUG_9
:
300 Logger
.Quiet(ST
.MSG_PYTHON_ON
% (python_version(), platform
) + \
304 if ReturnCode
!= 0 and ReturnCode
!= UPT_ALREADY_INSTALLED_ERROR
:
305 Logger
.Quiet(ST
.MSG_RECOVER_START
)
306 GlobalData
.gDB
.RollBack()
308 Logger
.Quiet(ST
.MSG_RECOVER_DONE
)
310 GlobalData
.gDB
.Commit()
313 Logger
.Quiet(ST
.MSG_RECOVER_FAIL
)
314 GlobalData
.gDB
.CloseDb()
316 if pf
.system() == 'Windows':
317 os
.system('subst %s /D' % GlobalData
.gWORKSPACE
.replace('\\', ''))
323 # This function will check DistFile existence, if not absolute path, then try current working directory,
324 # then $(WORKSPACE),and return the AbsPath. If file doesn't find, then return None
326 # @param DistFile: The distribution file in either relative path or absolute path
327 # @param WorkspaceDir: Workspace Directory
328 # @return AbsPath: The Absolute path of the distribution file if existed, None else
330 def GetFullPathDist(DistFile
, WorkspaceDir
):
331 if os
.path
.isabs(DistFile
):
332 if not (os
.path
.exists(DistFile
) and os
.path
.isfile(DistFile
)):
337 AbsPath
= os
.path
.normpath(os
.path
.join(os
.getcwd(), DistFile
))
338 if not (os
.path
.exists(AbsPath
) and os
.path
.isfile(AbsPath
)):
339 AbsPath
= os
.path
.normpath(os
.path
.join(WorkspaceDir
, DistFile
))
340 if not (os
.path
.exists(AbsPath
) and os
.path
.isfile(AbsPath
)):
345 if __name__
== '__main__':
348 # 0-127 is a safe return range, and 1 is a standard default error
350 if RETVAL
< 0 or RETVAL
> 127: