blob: 9bdef11cff670eaa505e611b332242fd1ad90dab [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001#!/usr/bin/python
2
3import os
4import os.path
5import sys
6import platform
7import argparse
8import shlex
9import subprocess
10import time
11import re
12
13################################################################################
14# check python version
15if sys.hexversion >= 0x02070000:
16 pass
17else:
18 print('Please install Python 2.7.x or newer to run this script')
19 exit(1)
20
21# override input() in python2
22try:
23 input = raw_input
24except NameError:
25 pass
26
27################################################################################
28
29verbose = False
30for_nata = False
31skipFlash = False
32
33fbtool = 'fbtool.py'
34fastboot = 'fastboot'
35
36system = platform.system()
37machine = platform.machine()
38product_out = os.path.abspath('.')
39
40if 'Windows' in system or 'CYGWIN' in system:
41 fastboot += '.exe'
42elif 'Linux' in system:
43 if 'x86_64' in machine:
44 fastboot += '-linux-x86_64'
45 elif 'arm' in machine or 'aarch64' in machine:
46 fastboot += '-linux-arm'
47elif 'Darwin' in system:
48 fastboot += '-darwin'
49
50# Generate image list from procedure list
51
52
53def getImageList(procs):
54 imgs = []
55 try:
56 for p in procs:
57 if p[0] == 'fastboot' and p[1] == 'flash' and p[3] not in imgs:
58 imgs.append(p[3])
59 except Exception as e:
60 print(e)
61 return imgs
62
63
64def call(cmd):
65 '''cmd: the command list for subprocess.call'''
66 if verbose:
67 print('call:', ' '.join(cmd))
68 if for_nata is True:
69 return subprocess.call(cmd, stdout=sys.stdout, stderr=subprocess.STDOUT, shell=True)
70 else:
71 return subprocess.call(formatArgsForSubprocess(cmd))
72
73def check_output(cmd):
74 '''cmd: the command list for subprocess.check_output'''
75 if verbose:
76 print('check_output:', ' '.join(cmd))
77 return subprocess.check_output(formatArgsForSubprocess(cmd), stderr=subprocess.STDOUT)
78
79
80def checkImage(filename, needreboot=True, _verbose=False):
81 filepath = os.path.join(product_out, filename)
82 if os.path.exists(filepath):
83 if _verbose:
84 print(filename.rjust(39, ' ') + ':' + ' PASS')
85 return filepath
86 if needreboot:
87 print(filename.rjust(39, ' ') + ':' + ' FAIL')
88 if args.nata:
89 print('[AT] Image not exist!')
90 else:
91 call([fastboot, 'reboot'])
92 exit(1)
93 return None
94
95# return 0 if success
96
97
98def cmdRun(cmd, dryrun=False):
99 ret = 1
100 raw_cmd = []
101 if cmd[0] == 'daWait':
102 daWait()
103 print('')
104 return 0
105 elif cmd[0] == 'fbWait':
106 fbWait()
107 print('')
108 return 0
109 elif cmd[0] == 'fastboot': # processing fastboot commands
110 cmd[0] = fastboot
111 if cmd[1] == 'flash':
112 # check if image path exits and valid
113 filepath = checkImage(cmd[3], False, False)
114 if filepath != None:
115 if 'CYGWIN' in system:
116 p = subprocess.check_output(
117 'cygpath --absolute --mixed %s' % filepath)
118 if p:
119 filepath = p.strip()
120 raw_cmd += [cmd[0], cmd[1], cmd[2], filepath]
121 else:
122 raw_cmd += cmd
123 else:
124 print('FAIL: Unknown command!')
125 return -1
126 if dryrun:
127 print(' '.join(raw_cmd))
128 ret = 0
129 else:
130 ret = call(raw_cmd)
131 # Bypass fastboot continue
132 if cmd[1] == 'continue':
133 ret = 0
134 if ret == 0 and cmd[0] == 'fastboot' and cmd[1] == 'reboot-bootloader' and not dryrun:
135 fbWait()
136 return ret
137
138
139def daWait(secs=60):
140 print('Waiting for DA mode')
141 ret = None
142 for i in range(secs):
143 sys.stdout.write('.')
144 sys.stdout.flush()
145 time.sleep(1)
146 ret = check_output('python %s ' % fbtool)
147 if ret != None and len(ret) != 0:
148 print('')
149 print('datool - device detected: ')
150 break
151 if ret == None:
152 print('No device detected. Please ensure that datool is running')
153 exit(1)
154
155
156def fbWait(secs=60):
157 print('Waiting for fastboot mode')
158 ret = None
159 for i in range(secs):
160 sys.stdout.write('.')
161 sys.stdout.flush()
162 time.sleep(1)
163 ret = check_output('%s devices' % fastboot)
164 if ret != None and len(ret) != 0:
165 print('')
166 print('Fastboot - device detected: %s' % (ret.split())[0])
167 break
168 if ret == None:
169 print('No device detected. Please ensure that fastboot is running on the target device')
170 exit(1)
171
172
173def cmdReboot(toBootloader=True):
174 if toBootloader:
175 call([fastboot, 'reboot-bootloader'])
176 fbWait()
177 else:
178 call([fastboot, 'reboot'])
179
180
181def formatArgsForSubprocess(cmd):
182 if not 'Windows' in system:
183 return shlex.split(cmd)
184 else:
185 return cmd
186
187
188if __name__ == '__main__':
189 # parse args
190 parser = argparse.ArgumentParser(
191 description='''
192Auto device flasher, Python 2.7.x required
193''',
194 formatter_class=argparse.RawTextHelpFormatter)
195 parser.add_argument('partition', nargs='?', default='all',
196 help='partition to flash [default: all] , not include test partition')
197 parser.add_argument('-d', '--dryrun', action='store_true', default=False,
198 help='dryrun for debug, no image would be flashed')
199 parser.add_argument('-u', '--user', action='store_true', default=False,
200 help='Flash user data partition')
201 parser.add_argument('-b', '--boot', action='store_true', default=False,
202 help='Flash boot partition')
203 parser.add_argument('-t', '--test', action='store_true', default=False,
204 help='Flash test partition')
205 parser.add_argument('-v', '--verbose', action='store_true', default=False,
206 help='print more information while flashing')
207 parser.add_argument('-n', '--nata', action = 'store_true', default = False,
208 help = 'Flash image in nata')
209 parser.add_argument('--toolsdir', default=None,
210 help='''\
211The tools dir where to find fbtool and fastboot.
212Path priority order:
213 1. --toolsdir specified
214 2. current directory
215 3. $PATH
216''')
217 parser.add_argument('--productdir', default=None,
218 help='''\
219The product out directory where to find images.
220Path priority order:
221 1. --productdir specified
222 2. current directory
223''')
224
225 args = parser.parse_args()
226 verbose = args.verbose
227 if args.dryrun:
228 verbose = True
229
230 print('')
231 parser.print_usage()
232 print('')
233 print(''.center(80, '*'))
234 print(('Running flasher on ' + platform.platform()).center(80))
235 print(''.center(80, '*'))
236 print('')
237
238 if args.nata:
239 for_nata = True
240 args.toolsdir = os.path.abspath(os.path.dirname(__file__))
241 args.productdir = args.toolsdir
242 print ('[AT] Flash Dir: %s' %args.productdir)
243
244 try:
245 from flashproc import getFlashProc
246 except ImportError as e:
247 print('ImportError:', e)
248 print('')
249 exit(1)
250 try:
251 from flashproc import getFlashUserProc
252 except:
253 getFlashUserProc = getFlashProc
254 try:
255 from flashproc import getFlashBootProc
256 except:
257 getFlashBootProc = getFlashProc
258 try:
259 from flashproc import getFlashTestProc
260 except:
261 getFlashTestProc = getFlashProc
262
263 # check flash tools
264 toolsdir = ''
265 try:
266 if args.toolsdir:
267 toolsdir = os.path.abspath(args.toolsdir)
268 fbtool = os.path.join(toolsdir, fbtool)
269 fastboot = os.path.join(toolsdir, fastboot)
270 if not os.path.exists(fbtool) or not os.path.exists(fastboot):
271 raise Exception(str(toolsdir))
272 else:
273 toolsdir = os.path.abspath('.')
274 if os.path.exists(os.path.join(toolsdir, fbtool)) and os.path.exists(os.path.join(toolsdir, fastboot)):
275 fbtool = os.path.join(toolsdir, fbtool)
276 fastboot = os.path.join(toolsdir, fastboot)
277 except Exception as e:
278 print('Can not find fbtool or fastboot in %s' % str(e))
279 print('')
280 exit(1)
281
282 devProduct = 'DEFAULT'
283
284 procs = getFlashProc(devProduct)
285 if args.user:
286 procs = getFlashUserProc(devProduct)
287 if args.boot:
288 procs = getFlashBootProc(devProduct)
289 if args.test:
290 procs = getFlashTestProc(devProduct)
291 if procs:
292 if verbose:
293 print('Flash procedure'.center(80))
294 print(''.center(80, '-'))
295 for p in procs:
296 print('fastboot', ' '.join(p))
297 print('')
298 else:
299 print('Can not retrieve flash procedure according to product type of', devProduct)
300 print('Exit !')
301 exit(1)
302
303 # check image path
304 if args.productdir:
305 # take user specific product directory
306 product_out = os.path.abspath(args.productdir)
307 else:
308 # check current directory
309 product_out = os.path.abspath('.')
310 for img in getImageList(procs):
311 if checkImage(img, False, False) is None:
312 product_out = None
313 break
314 if product_out is None:
315 product_out = os.getenv('PRODUCT_OUT', '.')
316 product_out = os.path.abspath(product_out)
317
318 print(''.center(80, '*'))
319 print('* flash images under:'.ljust(79, ' ') + '*')
320 print('* ' + product_out.ljust(73, ' ') + '*')
321 print(''.center(80, '*'))
322 print('')
323
324 # check images
325 print('Checking image'.center(80))
326 print(''.center(80, '-'))
327 images = getImageList(procs)
328 try:
329 for img in images:
330 checkImage(img, _verbose=True)
331 except Exception as e:
332 print(e)
333 time.sleep(2)
334 if args.nata:
335 print ('[AT] Check image fail, stop to flash!')
336 else:
337 cmdReboot(False)
338 input('Fail, press enter to exit: ')
339 exit(1)
340 # For NATA
341 if args.nata:
342 #POWER OFF
343 print ('[AT] POWER PIN KEY:0, %s' %time.ctime())
344 time.sleep(2)
345 #PRESS DOWNLOAD KEY
346 print ('[AT] DOWNLOAD KEY:1, %s' %time.ctime())
347 time.sleep(2)
348 #POWER ON
349 print ('[AT] POWER PIN KEY:1, %s' %time.ctime())
350 time.sleep(2)
351
352 # align 4kb for modem related images
353 os.system('python align_4kb.py \"%s\"' % checkImage('md1img.img', False, False))
354
355 # flash images
356 print('')
357 print('Start flashing'.center(80))
358 print(''.center(80, '-'))
359 try:
360 for proc in procs:
361 if skipFlash == False:
362 if 0 != cmdRun(proc, args.dryrun):
363 raise Exception('<<FAILED>> %s' % ' '.join(proc))
364 else:
365 if proc[0] == 'fastboot' and proc[1] == 'flash':
366 print('Skip flashing', proc[3])
367 except Exception as e:
368 print(e)
369 if args.nata:
370 #RELEASE DOWNLOAD KEY
371 print ('[AT] DOWNLOAD KEY:0, %s' %time.ctime())
372 time.sleep(2)
373 time.sleep(2)
374 cmdReboot(False)
375 exit(1)
376
377 if args.nata:
378 #RELEASE DOWNLOAD KEY
379 print ('[AT] DOWNLOAD KEY:0, %s' %time.ctime())
380 time.sleep(2)
381 time.sleep(2)
382 cmdReboot(False)
383 print('')
384 if args.nata:
385 print ('[AT] Flash Success')
386 else:
387 print('Success')