]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/UPT/UPT.py
d98b469640d85fcfc67c699d92dd1ce080b45be2
[mirror_edk2.git] / BaseTools / Source / Python / UPT / UPT.py
1 ## @file
2 #
3 # This file is the main entry for UPT
4 #
5 # Copyright (c) 2011 - 2017, 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 '''
17 UPT
18 '''
19
20 ## import modules
21 #
22 import locale
23 import sys
24 encoding = locale.getdefaultlocale()[1]
25 if encoding:
26 reload(sys)
27 sys.setdefaultencoding(encoding)
28 from Core import FileHook
29 import os.path
30 from sys import platform
31 import platform as pf
32 from optparse import OptionParser
33 from traceback import format_exc
34 from platform import python_version
35
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
48
49 import MkPkg
50 import InstallPkg
51 import RmPkg
52 import InventoryWs
53 import ReplacePkg
54 import TestInstall
55 from Library.Misc import GetWorkspace
56 from Library import GlobalData
57 from Core.IpiDb import IpiDatabase
58 from BuildVersion import gBUILD_VERSION
59
60 ## CheckConflictOption
61 #
62 # CheckConflictOption
63 #
64 def CheckConflictOption(Opt):
65 if (Opt.PackFileToCreate or Opt.PackFileToInstall or Opt.PackFileToRemove or Opt.PackFileToReplace) \
66 and Opt.InventoryWs:
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)
81
82 if Opt.CustomPath and Opt.UseGuidedPkgPath:
83 Logger.Warn("UPT", ST.WARN_CUSTOMPATH_OVERRIDE_USEGUIDEDPATH)
84 Opt.UseGuidedPkgPath = False
85
86 ## SetLogLevel
87 #
88 def SetLogLevel(Opt):
89 if Opt.opt_verbose:
90 Logger.SetLevel(Logger.VERBOSE)
91 elif Opt.opt_quiet:
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)
97 else:
98 Logger.SetLevel(Opt.debug_level + 1)
99 elif Opt.opt_slient:
100 Logger.SetLevel(Logger.SILENT)
101 else:
102 Logger.SetLevel(Logger.INFO)
103
104 ## Main
105 #
106 # Main
107 #
108 def Main():
109 Logger.Initialize()
110
111 Parser = OptionParser(version=(MSG_VERSION + ' Build ' + gBUILD_VERSION), description=MSG_DESCRIPTION,
112 prog="UPT.exe", usage=MSG_USAGE)
113
114 Parser.add_option("-d", "--debug", action="store", type="int", dest="debug_level", help=ST.HLP_PRINT_DEBUG_INFO)
115
116 Parser.add_option("-v", "--verbose", action="store_true", dest="opt_verbose",
117 help=ST.HLP_PRINT_INFORMATIONAL_STATEMENT)
118
119 Parser.add_option("-s", "--silent", action="store_true", dest="opt_slient", help=ST.HLP_RETURN_NO_DISPLAY)
120
121 Parser.add_option("-q", "--quiet", action="store_true", dest="opt_quiet", help=ST.HLP_RETURN_AND_DISPLAY)
122
123 Parser.add_option("-i", "--install", action="store", type="string", dest="Install_Distribution_Package_File",
124 help=ST.HLP_SPECIFY_PACKAGE_NAME_INSTALL)
125
126 Parser.add_option("-c", "--create", action="store", type="string", dest="Create_Distribution_Package_File",
127 help=ST.HLP_SPECIFY_PACKAGE_NAME_CREATE)
128
129 Parser.add_option("-r", "--remove", action="store", type="string", dest="Remove_Distribution_Package_File",
130 help=ST.HLP_SPECIFY_PACKAGE_NAME_REMOVE)
131
132 Parser.add_option("-t", "--template", action="store", type="string", dest="Package_Information_Data_File",
133 help=ST.HLP_SPECIFY_TEMPLATE_NAME_CREATE)
134
135 Parser.add_option("-p", "--dec-filename", action="append", type="string", dest="EDK2_DEC_Filename",
136 help=ST.HLP_SPECIFY_DEC_NAME_CREATE)
137
138 Parser.add_option("-m", "--inf-filename", action="append", type="string", dest="EDK2_INF_Filename",
139 help=ST.HLP_SPECIFY_INF_NAME_CREATE)
140
141 Parser.add_option("-l", "--list", action="store_true", dest="List_Dist_Installed",
142 help=ST.HLP_LIST_DIST_INSTALLED)
143
144 Parser.add_option("-f", "--force", action="store_true", dest="Yes", help=ST.HLP_DISABLE_PROMPT)
145
146 Parser.add_option("-n", "--custom-path", action="store_true", dest="CustomPath", help=ST.HLP_CUSTOM_PATH_PROMPT)
147
148 Parser.add_option("-x", "--free-lock", action="store_true", dest="SkipLock", help=ST.HLP_SKIP_LOCK_CHECK)
149
150 Parser.add_option("-u", "--replace", action="store", type="string", dest="Replace_Distribution_Package_File",
151 help=ST.HLP_SPECIFY_PACKAGE_NAME_REPLACE)
152
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)
155
156 Parser.add_option("--use-guided-paths", action="store_true", dest="Use_Guided_Paths", help=ST.HLP_USE_GUIDED_PATHS)
157
158 Parser.add_option("-j", "--test-install", action="append", type="string",
159 dest="Test_Install_Distribution_Package_Files", help=ST.HLP_TEST_INSTALL)
160
161 Opt = Parser.parse_args()[0]
162
163 Var2Var = [
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)
175 ]
176
177 for Var in Var2Var:
178 setattr(Opt, Var[0], Var[1])
179
180 try:
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]
186
187 # Support WORKSPACE is a long path
188 # Only works for windows system
189 if pf.system() == 'Windows':
190 Vol = 'B:'
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))
195 break
196 GlobalData.gWORKSPACE = '%s\\' % Vol
197
198 WorkspaceDir = GlobalData.gWORKSPACE
199
200 SetLogLevel(Opt)
201
202 Mgr = FileHook.RecoverMgr(WorkspaceDir)
203 FileHook.SetRecoverMgr(Mgr)
204
205 GlobalData.gDB = IpiDatabase(os.path.normpath(os.path.join(WorkspaceDir, \
206 "Conf/DistributionPackageDatabase.db")), WorkspaceDir)
207 GlobalData.gDB.InitDatabase(Opt.SkipLock)
208
209 #
210 # Make sure the Db will get closed correctly
211 #
212 try:
213 ReturnCode = 0
214 CheckConflictOption(Opt)
215
216 RunModule = None
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)
222 else:
223 Opt.PackageInformationDataFile = os.path.join(WorkspaceDir, Opt.PackageInformationDataFile)
224 else:
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
229
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)
233
234 AbsPath = GetFullPathDist(Opt.PackFileToInstall, WorkspaceDir)
235 if not AbsPath:
236 Logger.Error("InstallPkg", FILE_NOT_FOUND, ST.ERR_INSTALL_DIST_NOT_FOUND % Opt.PackFileToInstall)
237
238 Opt.PackFileToInstall = AbsPath
239 setattr(Opt, 'PackageFile', Opt.PackFileToInstall)
240 RunModule = InstallPkg.Main
241
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)
246 if head or not tail:
247 Logger.Error("RemovePkg",
248 FILE_TYPE_MISMATCH,
249 ExtraData=ST.ERR_DIST_FILENAME_ONLY_FOR_REMOVE % Opt.PackFileToRemove)
250
251 setattr(Opt, 'DistributionFile', Opt.PackFileToRemove)
252 RunModule = RmPkg.Main
253 elif Opt.InventoryWs:
254 RunModule = InventoryWs.Main
255
256 elif Opt.PackFileToBeReplaced and not Opt.PackFileToReplace:
257 Logger.Error("ReplacePkg", OPTION_MISSING, ExtraData=ST.ERR_REQUIRE_U_OPTION)
258
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",
266 FILE_TYPE_MISMATCH,
267 ExtraData=ST.ERR_DIST_EXT_ERROR % Opt.PackFileToBeReplaced)
268
269 head, tail = os.path.split(Opt.PackFileToBeReplaced)
270 if head or not tail:
271 Logger.Error("ReplacePkg",
272 FILE_TYPE_MISMATCH,
273 ExtraData=ST.ERR_DIST_FILENAME_ONLY_FOR_REPLACE_ORIG % Opt.PackFileToBeReplaced)
274
275 AbsPath = GetFullPathDist(Opt.PackFileToReplace, WorkspaceDir)
276 if not AbsPath:
277 Logger.Error("ReplacePkg", FILE_NOT_FOUND, ST.ERR_REPLACE_DIST_NOT_FOUND % Opt.PackFileToReplace)
278
279 Opt.PackFileToReplace = AbsPath
280 RunModule = ReplacePkg.Main
281
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)
286
287 setattr(Opt, 'DistFiles', Opt.Test_Install_Distribution_Package_Files)
288 RunModule = TestInstall.Main
289
290 else:
291 Parser.print_usage()
292 return OPTION_MISSING
293
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) + \
299 format_exc())
300 finally:
301 try:
302 if ReturnCode != 0 and ReturnCode != UPT_ALREADY_INSTALLED_ERROR:
303 Logger.Quiet(ST.MSG_RECOVER_START)
304 GlobalData.gDB.RollBack()
305 Mgr.rollback()
306 Logger.Quiet(ST.MSG_RECOVER_DONE)
307 else:
308 GlobalData.gDB.Commit()
309 Mgr.commit()
310 except StandardError:
311 Logger.Quiet(ST.MSG_RECOVER_FAIL)
312 GlobalData.gDB.CloseDb()
313
314 if pf.system() == 'Windows':
315 os.system('subst %s /D' % GlobalData.gWORKSPACE.replace('\\',''))
316
317 return ReturnCode
318
319 ## GetFullPathDist
320 #
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
323 #
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
327 #
328 def GetFullPathDist(DistFile, WorkspaceDir):
329 if os.path.isabs(DistFile):
330 if not (os.path.exists(DistFile) and os.path.isfile(DistFile)):
331 return None
332 else:
333 return DistFile
334 else:
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)):
339 return None
340
341 return AbsPath
342
343 if __name__ == '__main__':
344 RETVAL = Main()
345 #
346 # 0-127 is a safe return range, and 1 is a standard default error
347 #
348 if RETVAL < 0 or RETVAL > 127:
349 RETVAL = 1
350 sys.exit(RETVAL)