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
!= 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
="store", 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
, 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
:
231 if not Opt
.PackFileToInstall
.endswith('.dist'):
232 Logger
.Error("InstallPkg", FILE_TYPE_MISMATCH
, ExtraData
=ST
.ERR_DIST_EXT_ERROR
% Opt
.PackFileToInstall
)
234 AbsPath
= GetFullPathDist(Opt
.PackFileToInstall
, WorkspaceDir
)
236 Logger
.Error("InstallPkg", FILE_NOT_FOUND
, ST
.ERR_INSTALL_DIST_NOT_FOUND
% Opt
.PackFileToInstall
)
238 Opt
.PackFileToInstall
= AbsPath
239 setattr(Opt
, 'PackageFile', Opt
.PackFileToInstall
)
240 RunModule
= InstallPkg
.Main
242 elif Opt
.PackFileToRemove
:
243 if not Opt
.PackFileToRemove
.endswith('.dist'):
244 Logger
.Error("RemovePkg", FILE_TYPE_MISMATCH
, ExtraData
=ST
.ERR_DIST_EXT_ERROR
% Opt
.PackFileToRemove
)
245 head
, tail
= os
.path
.split(Opt
.PackFileToRemove
)
247 Logger
.Error("RemovePkg",
249 ExtraData
=ST
.ERR_DIST_FILENAME_ONLY_FOR_REMOVE
% Opt
.PackFileToRemove
)
251 setattr(Opt
, 'DistributionFile', Opt
.PackFileToRemove
)
252 RunModule
= RmPkg
.Main
253 elif Opt
.InventoryWs
:
254 RunModule
= InventoryWs
.Main
256 elif Opt
.PackFileToBeReplaced
and not Opt
.PackFileToReplace
:
257 Logger
.Error("ReplacePkg", OPTION_MISSING
, ExtraData
=ST
.ERR_REQUIRE_U_OPTION
)
259 elif Opt
.PackFileToReplace
:
260 if not Opt
.PackFileToReplace
.endswith('.dist'):
261 Logger
.Error("ReplacePkg", FILE_TYPE_MISMATCH
, ExtraData
=ST
.ERR_DIST_EXT_ERROR
% Opt
.PackFileToReplace
)
262 if not Opt
.PackFileToBeReplaced
:
263 Logger
.Error("ReplacePkg", OPTION_MISSING
, ExtraData
=ST
.ERR_REQUIRE_O_OPTION
)
264 if not Opt
.PackFileToBeReplaced
.endswith('.dist'):
265 Logger
.Error("ReplacePkg",
267 ExtraData
=ST
.ERR_DIST_EXT_ERROR
% Opt
.PackFileToBeReplaced
)
269 head
, tail
= os
.path
.split(Opt
.PackFileToBeReplaced
)
271 Logger
.Error("ReplacePkg",
273 ExtraData
=ST
.ERR_DIST_FILENAME_ONLY_FOR_REPLACE_ORIG
% Opt
.PackFileToBeReplaced
)
275 AbsPath
= GetFullPathDist(Opt
.PackFileToReplace
, WorkspaceDir
)
277 Logger
.Error("ReplacePkg", FILE_NOT_FOUND
, ST
.ERR_REPLACE_DIST_NOT_FOUND
% Opt
.PackFileToReplace
)
279 Opt
.PackFileToReplace
= AbsPath
280 RunModule
= ReplacePkg
.Main
282 elif Opt
.Test_Install_Distribution_Package_Files
:
283 for Dist
in Opt
.Test_Install_Distribution_Package_Files
:
284 if not Dist
.endswith('.dist'):
285 Logger
.Error("TestInstall", FILE_TYPE_MISMATCH
, ExtraData
=ST
.ERR_DIST_EXT_ERROR
% Dist
)
287 setattr(Opt
, 'DistFiles', Opt
.Test_Install_Distribution_Package_Files
)
288 RunModule
= TestInstall
.Main
292 return OPTION_MISSING
294 ReturnCode
= RunModule(Opt
)
295 except FatalError
, XExcept
:
296 ReturnCode
= XExcept
.args
[0]
297 if Logger
.GetLevel() <= Logger
.DEBUG_9
:
298 Logger
.Quiet(ST
.MSG_PYTHON_ON
% (python_version(), platform
) + \
302 if ReturnCode
!= 0 and ReturnCode
!= UPT_ALREADY_INSTALLED_ERROR
:
303 Logger
.Quiet(ST
.MSG_RECOVER_START
)
304 GlobalData
.gDB
.RollBack()
306 Logger
.Quiet(ST
.MSG_RECOVER_DONE
)
308 GlobalData
.gDB
.Commit()
310 except StandardError:
311 Logger
.Quiet(ST
.MSG_RECOVER_FAIL
)
312 GlobalData
.gDB
.CloseDb()
314 if pf
.system() == 'Windows':
315 os
.system('subst %s /D' % GlobalData
.gWORKSPACE
.replace('\\',''))
321 # This function will check DistFile existence, if not absolute path, then try current working directory,
322 # then $(WORKSPACE),and return the AbsPath. If file doesn't find, then return None
324 # @param DistFile: The distribution file in either relative path or absolute path
325 # @param WorkspaceDir: Workspace Directory
326 # @return AbsPath: The Absolute path of the distribution file if existed, None else
328 def GetFullPathDist(DistFile
, WorkspaceDir
):
329 if os
.path
.isabs(DistFile
):
330 if not (os
.path
.exists(DistFile
) and os
.path
.isfile(DistFile
)):
335 AbsPath
= os
.path
.normpath(os
.path
.join(os
.getcwd(), DistFile
))
336 if not (os
.path
.exists(AbsPath
) and os
.path
.isfile(AbsPath
)):
337 AbsPath
= os
.path
.normpath(os
.path
.join(WorkspaceDir
, DistFile
))
338 if not (os
.path
.exists(AbsPath
) and os
.path
.isfile(AbsPath
)):
343 if __name__
== '__main__':
346 # 0-127 is a safe return range, and 1 is a standard default error
348 if RETVAL
< 0 or RETVAL
> 127: