blob: 9ef533892933cbcc2aaf0a7887a1652b7339e558 [file] [log] [blame]
Bo Lv9edb6992021-09-06 11:31:00 +08001#!/usr/bin/env python3
2
3import sys
4import os
5import re
6import requests
7from requests.auth import HTTPBasicAuth
8from urllib.parse import urljoin
9import urllib.request
10import json
11import time
12from os.path import expanduser
13import jenkins
14
15
16serverRootUrl = "https://jenkins-sh.amlogic.com/job/Secure_Signing_Service/job/"
17homeConfigFilePath = "~/.sign.cfg"
18types = ["ta", "bl32", "bl31", "bl2", "bl2e", "bl2x", "bl40", "fw"]
19casProviders = ["", "VMX", "nagra"]
20ddrTypes = ["ddr4", "lpddr4", "ddr3", "lpddr3", "lpddr4_lpddr5"]
21chipVariants = ["general", "nocs-jts-ap", "nocs-prod"]
22
23user = ""
24password = ""
25auth = None
26server = None
27
28
29def init():
30 global user
31 global password
32 global auth
33 global server
34 expandedHomeConfigFilePath = expanduser(homeConfigFilePath)
35 configPyPath = os.path.join(sys.path[0], "config.py")
36 if os.path.exists(expandedHomeConfigFilePath):
37 configFilePath = expandedHomeConfigFilePath
38 elif os.path.exists(configPyPath):
39 configFilePath = configPyPath
40 else:
41 print(
42 "Can't find configuration file. Please create configuration file .sign.cfg at your home directory."
43 )
44 exit(1)
45
46 with open(configFilePath, "r") as configFile:
47 while True:
48 line = configFile.readline()
49 if not line:
50 break
51 words = line.split("=")
52 if words[0].strip() == "user":
53 user = words[1].strip().replace("'", "")
54 elif words[0].strip() == "password":
55 password = words[1].strip().replace("'", "")
56 auth = HTTPBasicAuth(user, password)
57 server = jenkins.Jenkins(
58 "https://jenkins-sh.amlogic.com", username=user, password=password
59 )
60
61
62def get_args():
63 from argparse import ArgumentParser
64
65 parser = ArgumentParser()
66
67 parser.add_argument("--in", dest="inputFilePath", required=True, help="input file")
68 parser.add_argument(
69 "--chipAcsFile", dest="chipAcsFilePath", default="null", help="chip acs file"
70 )
71 parser.add_argument(
72 "--out", dest="outFilePath", type=str, default="", help="output signed file"
73 )
74 parser.add_argument(
75 "-v", "--version", action="version", version="%(prog)s 1.0", help="version"
76 )
77 parser.add_argument("--type", choices=types, default=types[0], required=True)
78 parser.add_argument("--chip", type=str)
79 parser.add_argument("--taVersion", type=int, default=0)
80 parser.add_argument("--casProvider", choices=casProviders, default=casProviders[0])
81 parser.add_argument("--ddrType", type=str, default=ddrTypes[0])
82 parser.add_argument("--chipVariant", choices=chipVariants, default=chipVariants[0])
83 parser.add_argument("--keyType", type=str, dest="keyType", default="dev-keys")
Pengguang Zhu899a8de2021-09-17 15:48:28 +080084 parser.add_argument("--testService", type=int, default=0)
Bo Lv9edb6992021-09-06 11:31:00 +080085
86 return parser.parse_args()
87
88
89def getLastBuildNumber(rootJobUrl):
90 url = urljoin(rootJobUrl, "lastBuild/buildNumber")
91
92 response = requests.get(url, auth=auth)
93
94 if response.status_code == 200:
95 return response.text
96 else:
97 print(
98 "Fail to get last build number due to the error "
99 + str(response.status_code)
100 )
101 return 0
102
103
104def getJobRootUrl(type):
105 if type == "ta":
106 return urljoin(serverRootUrl, "Sign_TA/")
107 elif type == "bl31":
108 return urljoin(serverRootUrl, "Sign_Bl31/")
109 elif type == "bl2":
110 return urljoin(serverRootUrl, "Sign_Bl2/")
111 elif type == "bl32":
112 return urljoin(serverRootUrl, "Sign_Bl32/")
113 elif type == "fw":
114 return urljoin(serverRootUrl, "Sign_FW/")
115 else: # bl2e, bl2x, bl40
116 return urljoin(serverRootUrl, "Sign_Bl2e_Bl2x_Bl40/")
117
118
119def getJobName(type):
120 if type == "ta":
121 return "Sign_TA"
122 elif type == "bl31":
123 return "Sign_Bl31"
124 elif type == "bl2":
125 return "Sign_Bl2"
126 elif type == "bl32":
127 return "Sign_Bl32"
128 elif type == "fw":
129 return "Sign_FW"
130 else: # bl2e, bl2x, bl40
131 return "Sign_Bl2e_Bl2x_Bl40"
132
133
134def submitSignJob(
135 type,
136 chipType,
137 inputFilePath,
138 chipAcsFilePath,
139 taVersion="0",
140 casProvider="",
141 chipVariant="",
142 ddrType="",
143 keyType="dev-keys",
Pengguang Zhu899a8de2021-09-17 15:48:28 +0800144 testService=0,
Bo Lv9edb6992021-09-06 11:31:00 +0800145):
146
147 fileName = os.path.basename(inputFilePath)
148 fileParameter = "file"
149 uploadFile = {
150 fileParameter: (fileName, open(inputFilePath, "rb")),
151 }
152 url = getJobRootUrl(type) + "buildWithParameters"
153 if type == "ta":
154 data = {
155 "chip_part_number": chipType,
156 "ta_version": taVersion,
Pengguang Zhu899a8de2021-09-17 15:48:28 +0800157 "testService": testService,
Bo Lv9edb6992021-09-06 11:31:00 +0800158 }
159 elif type == "bl32":
160
161 data = {
162 "chipPartNumber": chipType,
163 "casProvider": casProvider,
164 "keyType": keyType,
Pengguang Zhu899a8de2021-09-17 15:48:28 +0800165 "testService": testService,
Bo Lv9edb6992021-09-06 11:31:00 +0800166 }
167
168 elif type == "bl2":
169 chipAcsfileName = os.path.basename(chipAcsFilePath)
170 uploadFile = {
171 fileParameter: (fileName, open(inputFilePath, "rb")),
172 "chipAcsFile": (chipAcsfileName, open(chipAcsFilePath, "rb")),
173 }
174 data = {
175 "chipPartNumber": chipType,
176 "chipVariant": chipVariant,
177 "ddrType": ddrType,
178 "keyType": keyType,
Pengguang Zhu899a8de2021-09-17 15:48:28 +0800179 "testService": testService,
Bo Lv9edb6992021-09-06 11:31:00 +0800180 }
Pengguang Zhu899a8de2021-09-17 15:48:28 +0800181 else: # bl2e, bl2x, bl31, bl40,
182 data = {
183 "chipPartNumber": chipType,
184 "keyType": keyType,
185 "testService": testService,
186 }
Bo Lv9edb6992021-09-06 11:31:00 +0800187
188 response = requests.post(url, auth=auth, data=data, files=uploadFile)
189
190 if response.status_code == 201:
191 print("Sumbit signing job successfully, please wait...")
192
193 else:
194 print(
195 "Fail to start signing job due to the error: " + str(response.status_code)
196 )
197 exit(1)
198
199
200def queryBuildStatus(rootJobUrl, buildNumber):
201 url = rootJobUrl + str(buildNumber) + "/api/json?tree=building"
202
203 response = requests.get(url, auth=auth)
204
205 if response.status_code == 200:
206 result = json.loads(response.text)
207 return str(result["building"])
208 else:
209 return "NotStart"
210
211
212def downloadSignedFile(rootJobUrl, buildNumber, inFileDir="", specifiedOutFilePath=""):
213
214 url = rootJobUrl + str(buildNumber) + "/api/json?tree=artifacts[relativePath]"
215
216 response = requests.get(url, auth=auth)
217
218 if response.status_code == 200:
219 result = json.loads(response.text)
220 if len(result["artifacts"]) == 0:
221 print("Fail to build, please check jenkins log for detailed error")
222 exit(1)
223 relativePath = result["artifacts"][0]["relativePath"]
224 # http://127.0.0.1:8080/job/Sign_Bl31/46/artifact/46/output/bl31-payload.bin.signed
225 downloadUrl = rootJobUrl + str(buildNumber) + "/artifact/" + "/" + relativePath
226 if specifiedOutFilePath == "":
227 outFilePath = os.path.join(inFileDir, os.path.basename(relativePath))
228 else:
229 outFilePath = specifiedOutFilePath
230 r = requests.get(downloadUrl, auth=auth)
231 with open(outFilePath, "wb") as f:
232 f.write(r.content)
233 print("Download the signed file at " + outFilePath)
234 return 0
235 else:
236 print("Fail to download the signed file")
237 exit(1)
238 return 1
239
240
241def waitForSubmit(type):
242 jobName = getJobName(type)
243
244 while True:
245 queues = server.get_queue_info()
246 inQueue = False
247 if queues:
248 for queue_job_info in queues:
249 if queue_job_info["task"].get("name", "") == jobName:
250 inQueue = True
251 break
252 if inQueue:
253 time.sleep(1)
254 print(
255 "Otherone is signing same firmware as you request. Please wait them to complete."
256 )
257 else:
258 print("It is your turn to submit your signing job now.")
259 break
260
261
262def main():
263 print(sys.argv)
264 init()
265 args = get_args()
266
267 rootJobUrl = getJobRootUrl(args.type)
268
269 waitForSubmit(args.type)
270 lastBuildNumber = getLastBuildNumber(rootJobUrl)
271 submitSignJob(
272 type=args.type,
273 chipType=args.chip,
274 inputFilePath=args.inputFilePath,
275 chipAcsFilePath=args.chipAcsFilePath,
276 taVersion=args.taVersion,
277 casProvider=args.casProvider,
278 chipVariant=args.chipVariant,
279 ddrType=args.ddrType,
280 keyType=args.keyType,
Pengguang Zhu899a8de2021-09-17 15:48:28 +0800281 testService=args.testService,
Bo Lv9edb6992021-09-06 11:31:00 +0800282 )
283
284 buildNumber = int(lastBuildNumber) + 1
285 print("The jenkins build number: " + str(buildNumber))
286 while True:
287 time.sleep(1)
288 building = queryBuildStatus(rootJobUrl, buildNumber)
289 print("Building Status= " + str(building))
290 if building == "False":
291 print("Build is done. Will start to download the signed file")
292 break
293 inputFileDir = os.path.dirname(args.inputFilePath)
294 downloadSignedFile(rootJobUrl, buildNumber, inputFileDir, args.outFilePath)
295
296
297if __name__ == "__main__":
298 main()