1## @file 2# Install distribution package. 3# 4# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR> 5# 6# SPDX-License-Identifier: BSD-2-Clause-Patent 7# 8 9''' 10MkPkg 11''' 12 13## 14# Import Modules 15# 16from os import remove 17from os import getcwd 18from os import chdir 19import os.path 20from sys import stdin 21from sys import platform 22from traceback import format_exc 23from platform import python_version 24from hashlib import md5 25from time import strftime 26from time import localtime 27from uuid import uuid4 28 29from Logger import StringTable as ST 30from Logger.ToolError import OPTION_UNKNOWN_ERROR 31from Logger.ToolError import OPTION_VALUE_INVALID 32from Logger.ToolError import ABORT_ERROR 33from Logger.ToolError import UPT_REPKG_ERROR 34from Logger.ToolError import CODE_ERROR 35from Logger.ToolError import FatalError 36from Logger.ToolError import FILE_NOT_FOUND 37import Logger.Log as Logger 38 39from Xml.XmlParser import DistributionPackageXml 40from Xml.IniToXml import IniToXml 41 42from Library import GlobalData 43from Library.ParserValidate import IsValidPath 44 45from Core.DistributionPackageClass import DistributionPackageClass 46from Core.PackageFile import PackageFile 47from Common.MultipleWorkspace import MultipleWorkspace as mws 48 49## CheckForExistingDp 50# 51# Check if there is a same name DP file existing 52# @param Path: The path to be checked 53# 54def CheckForExistingDp(Path): 55 if os.path.exists(Path): 56 Logger.Info(ST.MSG_DISTRIBUTION_PACKAGE_FILE_EXISTS % Path) 57 Input = stdin.readline() 58 Input = Input.replace('\r', '').replace('\n', '') 59 if Input.upper() != "Y": 60 Logger.Error("\nMkPkg", ABORT_ERROR, ST.ERR_USER_ABORT, RaiseError=True) 61 62## Tool entrance method 63# 64# This method mainly dispatch specific methods per the command line options. 65# If no error found, return zero value so the caller of this tool can know 66# if it's executed successfully or not. 67# 68# 69def Main(Options = None): 70 if Options is None: 71 Logger.Error("\nMkPkg", OPTION_UNKNOWN_ERROR, ST.ERR_OPTION_NOT_FOUND) 72 try: 73 DataBase = GlobalData.gDB 74 ContentFileClosed = True 75 WorkspaceDir = GlobalData.gWORKSPACE 76 77 # 78 # Init PackFileToCreate 79 # 80 if not Options.PackFileToCreate: 81 Logger.Error("\nMkPkg", OPTION_UNKNOWN_ERROR, ST.ERR_OPTION_NOT_FOUND) 82 83 # 84 # Handle if the distribution package file already exists 85 # 86 CheckForExistingDp(Options.PackFileToCreate) 87 88 # 89 # Check package file existing and valid 90 # 91 CheckFileList('.DEC', Options.PackageFileList, ST.ERR_INVALID_PACKAGE_NAME, ST.ERR_INVALID_PACKAGE_PATH) 92 # 93 # Check module file existing and valid 94 # 95 CheckFileList('.INF', Options.ModuleFileList, ST.ERR_INVALID_MODULE_NAME, ST.ERR_INVALID_MODULE_PATH) 96 97 # 98 # Get list of files that installed with RePackage attribute available 99 # 100 RePkgDict = DataBase.GetRePkgDict() 101 102 ContentFile = PackageFile(GlobalData.gCONTENT_FILE, "w") 103 ContentFileClosed = False 104 105 # 106 # Add temp distribution header 107 # 108 if Options.PackageInformationDataFile: 109 XmlFile = IniToXml(Options.PackageInformationDataFile) 110 DistPkg = DistributionPackageXml().FromXml(XmlFile) 111 remove(XmlFile) 112 113 # 114 # add distribution level tool/misc files 115 # before pack, current dir should be workspace dir, else the full 116 # path will be in the pack file 117 # 118 Cwd = getcwd() 119 chdir(WorkspaceDir) 120 ToolObject = DistPkg.Tools 121 MiscObject = DistPkg.MiscellaneousFiles 122 FileList = [] 123 if ToolObject: 124 FileList += ToolObject.GetFileList() 125 if MiscObject: 126 FileList += MiscObject.GetFileList() 127 for FileObject in FileList: 128 # 129 # If you have unicode file names, please convert them to byte 130 # strings in your desired encoding before passing them to 131 # write(). 132 # 133 FromFile = os.path.normpath(FileObject.GetURI()).encode('utf_8') 134 FileFullPath = mws.join(WorkspaceDir, FromFile) 135 if FileFullPath in RePkgDict: 136 (DpGuid, DpVersion, DpName, Repackage) = RePkgDict[FileFullPath] 137 if not Repackage: 138 Logger.Error("\nMkPkg", 139 UPT_REPKG_ERROR, 140 ST.ERR_UPT_REPKG_ERROR, 141 ExtraData=ST.MSG_REPKG_CONFLICT %\ 142 (FileFullPath, DpGuid, DpVersion, DpName) 143 ) 144 else: 145 DistPkg.Header.RePackage = True 146 ContentFile.PackFile(FromFile) 147 chdir(Cwd) 148 149 # 150 # Add init dp information 151 # 152 else: 153 DistPkg = DistributionPackageClass() 154 DistPkg.Header.Name = 'Distribution Package' 155 DistPkg.Header.Guid = str(uuid4()) 156 DistPkg.Header.Version = '1.0' 157 158 DistPkg.GetDistributionPackage(WorkspaceDir, Options.PackageFileList, \ 159 Options.ModuleFileList) 160 FileList, MetaDataFileList = DistPkg.GetDistributionFileList() 161 for File in FileList + MetaDataFileList: 162 FileFullPath = os.path.normpath(os.path.join(WorkspaceDir, File)) 163 # 164 # check whether file was included in a distribution that can not 165 # be repackaged 166 # 167 if FileFullPath in RePkgDict: 168 (DpGuid, DpVersion, DpName, Repackage) = RePkgDict[FileFullPath] 169 if not Repackage: 170 Logger.Error("\nMkPkg", 171 UPT_REPKG_ERROR, 172 ST.ERR_UPT_REPKG_ERROR, 173 ExtraData = \ 174 ST.MSG_REPKG_CONFLICT %(FileFullPath, DpName, \ 175 DpGuid, DpVersion) 176 ) 177 else: 178 DistPkg.Header.RePackage = True 179 180 Cwd = getcwd() 181 chdir(WorkspaceDir) 182 ContentFile.PackFiles(FileList) 183 chdir(Cwd) 184 185 Logger.Verbose(ST.MSG_COMPRESS_DISTRIBUTION_PKG) 186 187 ContentFile.Close() 188 ContentFileClosed = True 189 190 # 191 # Add Md5Signature 192 # 193 DistPkg.Header.Signature = md5(open(str(ContentFile), 'rb').read()).hexdigest() 194 # 195 # Add current Date 196 # 197 DistPkg.Header.Date = str(strftime("%Y-%m-%dT%H:%M:%S", localtime())) 198 199 # 200 # Finish final dp file 201 # 202 DistPkgFile = PackageFile(Options.PackFileToCreate, "w") 203 DistPkgFile.PackFile(str(ContentFile)) 204 DistPkgXml = DistributionPackageXml() 205 DistPkgFile.PackData(DistPkgXml.ToXml(DistPkg), GlobalData.gDESC_FILE) 206 DistPkgFile.Close() 207 Logger.Quiet(ST.MSG_FINISH) 208 ReturnCode = 0 209 210 except FatalError as XExcept: 211 ReturnCode = XExcept.args[0] 212 if Logger.GetLevel() <= Logger.DEBUG_9: 213 Logger.Quiet(ST.MSG_PYTHON_ON % \ 214 (python_version(), platform) + format_exc()) 215 except KeyboardInterrupt: 216 ReturnCode = ABORT_ERROR 217 if Logger.GetLevel() <= Logger.DEBUG_9: 218 Logger.Quiet(ST.MSG_PYTHON_ON % \ 219 (python_version(), platform) + format_exc()) 220 except OSError: 221 pass 222 except: 223 Logger.Error( 224 "\nMkPkg", 225 CODE_ERROR, 226 ST.ERR_UNKNOWN_FATAL_CREATING_ERR % \ 227 Options.PackFileToCreate, 228 ExtraData=ST.MSG_SEARCH_FOR_HELP % ST.MSG_EDKII_MAIL_ADDR, 229 RaiseError=False 230 ) 231 Logger.Quiet(ST.MSG_PYTHON_ON % \ 232 (python_version(), platform) + format_exc()) 233 ReturnCode = CODE_ERROR 234 finally: 235 if os.path.exists(GlobalData.gCONTENT_FILE): 236 if not ContentFileClosed: 237 ContentFile.Close() 238 os.remove(GlobalData.gCONTENT_FILE) 239 240 return ReturnCode 241 242 243## CheckFileList 244# 245# @param QualifiedExt: QualifiedExt 246# @param FileList: FileList 247# @param ErrorStringExt: ErrorStringExt 248# @param ErrorStringFullPath: ErrorStringFullPath 249# 250def CheckFileList(QualifiedExt, FileList, ErrorStringExt, ErrorStringFullPath): 251 if not FileList: 252 return 253 WorkspaceDir = GlobalData.gWORKSPACE 254 WorkspaceDir = os.path.normpath(WorkspaceDir) 255 for Item in FileList: 256 Ext = os.path.splitext(Item)[1] 257 if Ext.upper() != QualifiedExt.upper(): 258 Logger.Error("\nMkPkg", OPTION_VALUE_INVALID, \ 259 ErrorStringExt % Item) 260 261 Item = os.path.normpath(Item) 262 Path = mws.join(WorkspaceDir, Item) 263 if not os.path.exists(Path): 264 Logger.Error("\nMkPkg", FILE_NOT_FOUND, ST.ERR_NOT_FOUND % Item) 265 elif Item == Path: 266 Logger.Error("\nMkPkg", OPTION_VALUE_INVALID, 267 ErrorStringFullPath % Item) 268 elif not IsValidPath(Item, WorkspaceDir): 269 Logger.Error("\nMkPkg", OPTION_VALUE_INVALID, \ 270 ErrorStringExt % Item) 271 272 if not os.path.split(Item)[0]: 273 Logger.Error("\nMkPkg", OPTION_VALUE_INVALID, \ 274 ST.ERR_INVALID_METAFILE_PATH % Item) 275