Commit | Line | Data |
---|---|---|
4234283c LG |
1 | ## @file\r |
2 | #\r | |
f7496d71 | 3 | # This file is the main entry for UPT\r |
4234283c | 4 | #\r |
f7496d71 | 5 | # Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r |
4234283c | 6 | #\r |
f7496d71 LG |
7 | # This program and the accompanying materials are licensed and made available\r |
8 | # under the terms and conditions of the BSD License which accompanies this\r | |
9 | # distribution. The full text of the license may be found at\r | |
4234283c LG |
10 | # http://opensource.org/licenses/bsd-license.php\r |
11 | #\r | |
12 | # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r | |
13 | # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r | |
14 | #\r | |
15 | \r | |
16 | '''\r | |
17 | UPT\r | |
18 | '''\r | |
19 | \r | |
20 | ## import modules\r | |
21 | #\r | |
09e27ac5 | 22 | import locale\r |
4234283c | 23 | import sys\r |
174a9d3c | 24 | from imp import reload\r |
1ccc4d89 LG |
25 | encoding = locale.getdefaultlocale()[1]\r |
26 | if encoding:\r | |
27 | reload(sys)\r | |
28 | sys.setdefaultencoding(encoding)\r | |
09e27ac5 | 29 | from Core import FileHook\r |
4234283c | 30 | import os.path\r |
4234283c | 31 | from sys import platform\r |
421ccda3 | 32 | import platform as pf\r |
4234283c LG |
33 | from optparse import OptionParser\r |
34 | from traceback import format_exc\r | |
35 | from platform import python_version\r | |
36 | \r | |
37 | from Logger import StringTable as ST\r | |
38 | import Logger.Log as Logger\r | |
39 | from Logger.StringTable import MSG_VERSION\r | |
40 | from Logger.StringTable import MSG_DESCRIPTION\r | |
41 | from Logger.StringTable import MSG_USAGE\r | |
42 | from Logger.ToolError import FILE_NOT_FOUND\r | |
43 | from Logger.ToolError import OPTION_MISSING\r | |
44 | from Logger.ToolError import FILE_TYPE_MISMATCH\r | |
45 | from Logger.ToolError import OPTION_CONFLICT\r | |
46 | from Logger.ToolError import FatalError\r | |
af0c61ae | 47 | from Logger.ToolError import UPT_ALREADY_INSTALLED_ERROR\r |
fb0f8067 | 48 | from Common.MultipleWorkspace import MultipleWorkspace as mws\r |
421ccda3 | 49 | \r |
4234283c LG |
50 | import MkPkg\r |
51 | import InstallPkg\r | |
52 | import RmPkg\r | |
421ccda3 HC |
53 | import InventoryWs\r |
54 | import ReplacePkg\r | |
6cf99034 | 55 | import TestInstall\r |
421ccda3 | 56 | from Library.Misc import GetWorkspace\r |
4234283c LG |
57 | from Library import GlobalData\r |
58 | from Core.IpiDb import IpiDatabase\r | |
2bcc713e | 59 | from BuildVersion import gBUILD_VERSION\r |
4234283c | 60 | \r |
4234283c LG |
61 | ## CheckConflictOption\r |
62 | #\r | |
63 | # CheckConflictOption\r | |
64 | #\r | |
65 | def CheckConflictOption(Opt):\r | |
421ccda3 HC |
66 | if (Opt.PackFileToCreate or Opt.PackFileToInstall or Opt.PackFileToRemove or Opt.PackFileToReplace) \\r |
67 | and Opt.InventoryWs:\r | |
68 | Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_L_OA_EXCLUSIVE)\r | |
69 | elif Opt.PackFileToReplace and (Opt.PackFileToCreate or Opt.PackFileToInstall or Opt.PackFileToRemove):\r | |
70 | Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_U_ICR_EXCLUSIVE)\r | |
71 | elif (Opt.PackFileToCreate and Opt.PackFileToInstall and Opt.PackFileToRemove):\r | |
4234283c LG |
72 | Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_REQUIRE_I_C_R_OPTION)\r |
73 | elif Opt.PackFileToCreate and Opt.PackFileToInstall:\r | |
74 | Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_I_C_EXCLUSIVE)\r | |
75 | elif Opt.PackFileToInstall and Opt.PackFileToRemove:\r | |
76 | Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_I_R_EXCLUSIVE)\r | |
77 | elif Opt.PackFileToCreate and Opt.PackFileToRemove:\r | |
78 | Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_C_R_EXCLUSIVE)\r | |
6cf99034 HC |
79 | elif Opt.TestDistFiles and (Opt.PackFileToCreate or Opt.PackFileToInstall \\r |
80 | or Opt.PackFileToRemove or Opt.PackFileToReplace):\r | |
81 | Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_C_R_EXCLUSIVE)\r | |
4234283c | 82 | \r |
421ccda3 HC |
83 | if Opt.CustomPath and Opt.UseGuidedPkgPath:\r |
84 | Logger.Warn("UPT", ST.WARN_CUSTOMPATH_OVERRIDE_USEGUIDEDPATH)\r | |
85 | Opt.UseGuidedPkgPath = False\r | |
86 | \r | |
4234283c LG |
87 | ## SetLogLevel\r |
88 | #\r | |
89 | def SetLogLevel(Opt):\r | |
90 | if Opt.opt_verbose:\r | |
91 | Logger.SetLevel(Logger.VERBOSE)\r | |
92 | elif Opt.opt_quiet:\r | |
93 | Logger.SetLevel(Logger.QUIET + 1)\r | |
4231a819 | 94 | elif Opt.debug_level is not None:\r |
4234283c LG |
95 | if Opt.debug_level < 0 or Opt.debug_level > 9:\r |
96 | Logger.Warn("UPT", ST.ERR_DEBUG_LEVEL)\r | |
97 | Logger.SetLevel(Logger.INFO)\r | |
98 | else:\r | |
99 | Logger.SetLevel(Opt.debug_level + 1)\r | |
100 | elif Opt.opt_slient:\r | |
101 | Logger.SetLevel(Logger.SILENT)\r | |
102 | else:\r | |
103 | Logger.SetLevel(Logger.INFO)\r | |
104 | \r | |
105 | ## Main\r | |
106 | #\r | |
107 | # Main\r | |
108 | #\r | |
109 | def Main():\r | |
110 | Logger.Initialize()\r | |
111 | \r | |
45258285 | 112 | Parser = OptionParser(version=(MSG_VERSION + ' Build ' + gBUILD_VERSION), description=MSG_DESCRIPTION,\r |
4234283c LG |
113 | prog="UPT.exe", usage=MSG_USAGE)\r |
114 | \r | |
115 | Parser.add_option("-d", "--debug", action="store", type="int", dest="debug_level", help=ST.HLP_PRINT_DEBUG_INFO)\r | |
116 | \r | |
117 | Parser.add_option("-v", "--verbose", action="store_true", dest="opt_verbose",\r | |
118 | help=ST.HLP_PRINT_INFORMATIONAL_STATEMENT)\r | |
119 | \r | |
120 | Parser.add_option("-s", "--silent", action="store_true", dest="opt_slient", help=ST.HLP_RETURN_NO_DISPLAY)\r | |
121 | \r | |
122 | Parser.add_option("-q", "--quiet", action="store_true", dest="opt_quiet", help=ST.HLP_RETURN_AND_DISPLAY)\r | |
123 | \r | |
56636814 | 124 | Parser.add_option("-i", "--install", action="append", type="string", dest="Install_Distribution_Package_File",\r |
4234283c LG |
125 | help=ST.HLP_SPECIFY_PACKAGE_NAME_INSTALL)\r |
126 | \r | |
127 | Parser.add_option("-c", "--create", action="store", type="string", dest="Create_Distribution_Package_File",\r | |
128 | help=ST.HLP_SPECIFY_PACKAGE_NAME_CREATE)\r | |
129 | \r | |
130 | Parser.add_option("-r", "--remove", action="store", type="string", dest="Remove_Distribution_Package_File",\r | |
131 | help=ST.HLP_SPECIFY_PACKAGE_NAME_REMOVE)\r | |
132 | \r | |
133 | Parser.add_option("-t", "--template", action="store", type="string", dest="Package_Information_Data_File",\r | |
134 | help=ST.HLP_SPECIFY_TEMPLATE_NAME_CREATE)\r | |
135 | \r | |
136 | Parser.add_option("-p", "--dec-filename", action="append", type="string", dest="EDK2_DEC_Filename",\r | |
137 | help=ST.HLP_SPECIFY_DEC_NAME_CREATE)\r | |
138 | \r | |
139 | Parser.add_option("-m", "--inf-filename", action="append", type="string", dest="EDK2_INF_Filename",\r | |
140 | help=ST.HLP_SPECIFY_INF_NAME_CREATE)\r | |
141 | \r | |
421ccda3 HC |
142 | Parser.add_option("-l", "--list", action="store_true", dest="List_Dist_Installed",\r |
143 | help=ST.HLP_LIST_DIST_INSTALLED)\r | |
144 | \r | |
4234283c LG |
145 | Parser.add_option("-f", "--force", action="store_true", dest="Yes", help=ST.HLP_DISABLE_PROMPT)\r |
146 | \r | |
147 | Parser.add_option("-n", "--custom-path", action="store_true", dest="CustomPath", help=ST.HLP_CUSTOM_PATH_PROMPT)\r | |
148 | \r | |
149 | Parser.add_option("-x", "--free-lock", action="store_true", dest="SkipLock", help=ST.HLP_SKIP_LOCK_CHECK)\r | |
150 | \r | |
421ccda3 HC |
151 | Parser.add_option("-u", "--replace", action="store", type="string", dest="Replace_Distribution_Package_File",\r |
152 | help=ST.HLP_SPECIFY_PACKAGE_NAME_REPLACE)\r | |
153 | \r | |
154 | Parser.add_option("-o", "--original", action="store", type="string", dest="Original_Distribution_Package_File",\r | |
155 | help=ST.HLP_SPECIFY_PACKAGE_NAME_TO_BE_REPLACED)\r | |
156 | \r | |
157 | Parser.add_option("--use-guided-paths", action="store_true", dest="Use_Guided_Paths", help=ST.HLP_USE_GUIDED_PATHS)\r | |
158 | \r | |
6cf99034 HC |
159 | Parser.add_option("-j", "--test-install", action="append", type="string",\r |
160 | dest="Test_Install_Distribution_Package_Files", help=ST.HLP_TEST_INSTALL)\r | |
161 | \r | |
4234283c LG |
162 | Opt = Parser.parse_args()[0]\r |
163 | \r | |
164 | Var2Var = [\r | |
165 | ("PackageInformationDataFile", Opt.Package_Information_Data_File),\r | |
166 | ("PackFileToInstall", Opt.Install_Distribution_Package_File),\r | |
167 | ("PackFileToCreate", Opt.Create_Distribution_Package_File),\r | |
168 | ("PackFileToRemove", Opt.Remove_Distribution_Package_File),\r | |
169 | ("PackageFileList", Opt.EDK2_DEC_Filename),\r | |
421ccda3 HC |
170 | ("ModuleFileList", Opt.EDK2_INF_Filename),\r |
171 | ("InventoryWs", Opt.List_Dist_Installed),\r | |
172 | ("PackFileToReplace", Opt.Replace_Distribution_Package_File),\r | |
173 | ("PackFileToBeReplaced", Opt.Original_Distribution_Package_File),\r | |
174 | ("UseGuidedPkgPath", Opt.Use_Guided_Paths),\r | |
6cf99034 | 175 | ("TestDistFiles", Opt.Test_Install_Distribution_Package_Files)\r |
4234283c | 176 | ]\r |
421ccda3 | 177 | \r |
4234283c LG |
178 | for Var in Var2Var:\r |
179 | setattr(Opt, Var[0], Var[1])\r | |
180 | \r | |
181 | try:\r | |
fb0f8067 | 182 | GlobalData.gWORKSPACE, GlobalData.gPACKAGE_PATH = GetWorkspace()\r |
5b0671c1 | 183 | except FatalError as XExcept:\r |
4234283c LG |
184 | if Logger.GetLevel() <= Logger.DEBUG_9:\r |
185 | Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + format_exc())\r | |
186 | return XExcept.args[0]\r | |
187 | \r | |
421ccda3 | 188 | # Support WORKSPACE is a long path\r |
c03f5b2c | 189 | # Only works for windows system\r |
421ccda3 | 190 | if pf.system() == 'Windows':\r |
c03f5b2c HC |
191 | Vol = 'B:'\r |
192 | for Index in range(90, 65, -1):\r | |
193 | Vol = chr(Index) + ':'\r | |
194 | if not os.path.isdir(Vol):\r | |
195 | os.system('subst %s "%s"' % (Vol, GlobalData.gWORKSPACE))\r | |
196 | break\r | |
197 | GlobalData.gWORKSPACE = '%s\\' % Vol\r | |
421ccda3 | 198 | \r |
4234283c LG |
199 | WorkspaceDir = GlobalData.gWORKSPACE\r |
200 | \r | |
201 | SetLogLevel(Opt)\r | |
202 | \r | |
421ccda3 HC |
203 | Mgr = FileHook.RecoverMgr(WorkspaceDir)\r |
204 | FileHook.SetRecoverMgr(Mgr)\r | |
205 | \r | |
206 | GlobalData.gDB = IpiDatabase(os.path.normpath(os.path.join(WorkspaceDir, \\r | |
207 | "Conf/DistributionPackageDatabase.db")), WorkspaceDir)\r | |
4234283c LG |
208 | GlobalData.gDB.InitDatabase(Opt.SkipLock)\r |
209 | \r | |
210 | #\r | |
211 | # Make sure the Db will get closed correctly\r | |
212 | #\r | |
213 | try:\r | |
214 | ReturnCode = 0\r | |
215 | CheckConflictOption(Opt)\r | |
216 | \r | |
217 | RunModule = None\r | |
218 | if Opt.PackFileToCreate:\r | |
219 | if Opt.PackageInformationDataFile:\r | |
220 | if not os.path.exists(Opt.PackageInformationDataFile):\r | |
221 | if not os.path.exists(os.path.join(WorkspaceDir, Opt.PackageInformationDataFile)):\r | |
222 | Logger.Error("\nUPT", FILE_NOT_FOUND, ST.ERR_NO_TEMPLATE_FILE % Opt.PackageInformationDataFile)\r | |
223 | else:\r | |
224 | Opt.PackageInformationDataFile = os.path.join(WorkspaceDir, Opt.PackageInformationDataFile)\r | |
225 | else:\r | |
226 | Logger.Error("UPT", OPTION_MISSING, ExtraData=ST.ERR_REQUIRE_T_OPTION)\r | |
227 | if not Opt.PackFileToCreate.endswith('.dist'):\r | |
228 | Logger.Error("CreatePkg", FILE_TYPE_MISMATCH, ExtraData=ST.ERR_DIST_EXT_ERROR % Opt.PackFileToCreate)\r | |
229 | RunModule = MkPkg.Main\r | |
230 | \r | |
231 | elif Opt.PackFileToInstall:\r | |
56636814 HC |
232 | AbsPath = []\r |
233 | for Item in Opt.PackFileToInstall:\r | |
234 | if not Item.endswith('.dist'):\r | |
235 | Logger.Error("InstallPkg", FILE_TYPE_MISMATCH, ExtraData=ST.ERR_DIST_EXT_ERROR % Item)\r | |
236 | \r | |
237 | AbsPath.append(GetFullPathDist(Item, WorkspaceDir))\r | |
238 | if not AbsPath:\r | |
239 | Logger.Error("InstallPkg", FILE_NOT_FOUND, ST.ERR_INSTALL_DIST_NOT_FOUND % Item)\r | |
4234283c | 240 | \r |
421ccda3 | 241 | Opt.PackFileToInstall = AbsPath\r |
4234283c LG |
242 | setattr(Opt, 'PackageFile', Opt.PackFileToInstall)\r |
243 | RunModule = InstallPkg.Main\r | |
244 | \r | |
245 | elif Opt.PackFileToRemove:\r | |
246 | if not Opt.PackFileToRemove.endswith('.dist'):\r | |
247 | Logger.Error("RemovePkg", FILE_TYPE_MISMATCH, ExtraData=ST.ERR_DIST_EXT_ERROR % Opt.PackFileToRemove)\r | |
248 | head, tail = os.path.split(Opt.PackFileToRemove)\r | |
249 | if head or not tail:\r | |
250 | Logger.Error("RemovePkg",\r | |
251 | FILE_TYPE_MISMATCH,\r | |
252 | ExtraData=ST.ERR_DIST_FILENAME_ONLY_FOR_REMOVE % Opt.PackFileToRemove)\r | |
253 | \r | |
254 | setattr(Opt, 'DistributionFile', Opt.PackFileToRemove)\r | |
255 | RunModule = RmPkg.Main\r | |
421ccda3 HC |
256 | elif Opt.InventoryWs:\r |
257 | RunModule = InventoryWs.Main\r | |
258 | \r | |
259 | elif Opt.PackFileToBeReplaced and not Opt.PackFileToReplace:\r | |
260 | Logger.Error("ReplacePkg", OPTION_MISSING, ExtraData=ST.ERR_REQUIRE_U_OPTION)\r | |
261 | \r | |
262 | elif Opt.PackFileToReplace:\r | |
263 | if not Opt.PackFileToReplace.endswith('.dist'):\r | |
264 | Logger.Error("ReplacePkg", FILE_TYPE_MISMATCH, ExtraData=ST.ERR_DIST_EXT_ERROR % Opt.PackFileToReplace)\r | |
265 | if not Opt.PackFileToBeReplaced:\r | |
266 | Logger.Error("ReplacePkg", OPTION_MISSING, ExtraData=ST.ERR_REQUIRE_O_OPTION)\r | |
267 | if not Opt.PackFileToBeReplaced.endswith('.dist'):\r | |
268 | Logger.Error("ReplacePkg",\r | |
269 | FILE_TYPE_MISMATCH,\r | |
270 | ExtraData=ST.ERR_DIST_EXT_ERROR % Opt.PackFileToBeReplaced)\r | |
271 | \r | |
272 | head, tail = os.path.split(Opt.PackFileToBeReplaced)\r | |
273 | if head or not tail:\r | |
274 | Logger.Error("ReplacePkg",\r | |
275 | FILE_TYPE_MISMATCH,\r | |
276 | ExtraData=ST.ERR_DIST_FILENAME_ONLY_FOR_REPLACE_ORIG % Opt.PackFileToBeReplaced)\r | |
277 | \r | |
278 | AbsPath = GetFullPathDist(Opt.PackFileToReplace, WorkspaceDir)\r | |
279 | if not AbsPath:\r | |
280 | Logger.Error("ReplacePkg", FILE_NOT_FOUND, ST.ERR_REPLACE_DIST_NOT_FOUND % Opt.PackFileToReplace)\r | |
281 | \r | |
282 | Opt.PackFileToReplace = AbsPath\r | |
283 | RunModule = ReplacePkg.Main\r | |
284 | \r | |
6cf99034 HC |
285 | elif Opt.Test_Install_Distribution_Package_Files:\r |
286 | for Dist in Opt.Test_Install_Distribution_Package_Files:\r | |
287 | if not Dist.endswith('.dist'):\r | |
288 | Logger.Error("TestInstall", FILE_TYPE_MISMATCH, ExtraData=ST.ERR_DIST_EXT_ERROR % Dist)\r | |
289 | \r | |
290 | setattr(Opt, 'DistFiles', Opt.Test_Install_Distribution_Package_Files)\r | |
291 | RunModule = TestInstall.Main\r | |
292 | \r | |
4234283c LG |
293 | else:\r |
294 | Parser.print_usage()\r | |
295 | return OPTION_MISSING\r | |
296 | \r | |
297 | ReturnCode = RunModule(Opt)\r | |
5b0671c1 | 298 | except FatalError as XExcept:\r |
4234283c LG |
299 | ReturnCode = XExcept.args[0]\r |
300 | if Logger.GetLevel() <= Logger.DEBUG_9:\r | |
301 | Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + \\r | |
302 | format_exc())\r | |
303 | finally:\r | |
421ccda3 | 304 | try:\r |
af0c61ae | 305 | if ReturnCode != 0 and ReturnCode != UPT_ALREADY_INSTALLED_ERROR:\r |
421ccda3 HC |
306 | Logger.Quiet(ST.MSG_RECOVER_START)\r |
307 | GlobalData.gDB.RollBack()\r | |
308 | Mgr.rollback()\r | |
309 | Logger.Quiet(ST.MSG_RECOVER_DONE)\r | |
310 | else:\r | |
311 | GlobalData.gDB.Commit()\r | |
312 | Mgr.commit()\r | |
92beb1e4 | 313 | except Exception:\r |
421ccda3 | 314 | Logger.Quiet(ST.MSG_RECOVER_FAIL)\r |
4234283c | 315 | GlobalData.gDB.CloseDb()\r |
c03f5b2c | 316 | \r |
421ccda3 | 317 | if pf.system() == 'Windows':\r |
ccaa7754 | 318 | os.system('subst %s /D' % GlobalData.gWORKSPACE.replace('\\', ''))\r |
4234283c LG |
319 | \r |
320 | return ReturnCode\r | |
321 | \r | |
421ccda3 HC |
322 | ## GetFullPathDist\r |
323 | #\r | |
324 | # This function will check DistFile existence, if not absolute path, then try current working directory,\r | |
325 | # then $(WORKSPACE),and return the AbsPath. If file doesn't find, then return None\r | |
326 | #\r | |
327 | # @param DistFile: The distribution file in either relative path or absolute path\r | |
328 | # @param WorkspaceDir: Workspace Directory\r | |
329 | # @return AbsPath: The Absolute path of the distribution file if existed, None else\r | |
330 | #\r | |
331 | def GetFullPathDist(DistFile, WorkspaceDir):\r | |
332 | if os.path.isabs(DistFile):\r | |
333 | if not (os.path.exists(DistFile) and os.path.isfile(DistFile)):\r | |
334 | return None\r | |
335 | else:\r | |
336 | return DistFile\r | |
337 | else:\r | |
338 | AbsPath = os.path.normpath(os.path.join(os.getcwd(), DistFile))\r | |
339 | if not (os.path.exists(AbsPath) and os.path.isfile(AbsPath)):\r | |
340 | AbsPath = os.path.normpath(os.path.join(WorkspaceDir, DistFile))\r | |
341 | if not (os.path.exists(AbsPath) and os.path.isfile(AbsPath)):\r | |
342 | return None\r | |
343 | \r | |
344 | return AbsPath\r | |
345 | \r | |
4234283c LG |
346 | if __name__ == '__main__':\r |
347 | RETVAL = Main()\r | |
348 | #\r | |
349 | # 0-127 is a safe return range, and 1 is a standard default error\r | |
350 | #\r | |
351 | if RETVAL < 0 or RETVAL > 127:\r | |
352 | RETVAL = 1\r | |
353 | sys.exit(RETVAL)\r |