Total Complexity | 102 |
Total Lines | 821 |
Duplicated Lines | 0 % |
Coverage | 100% |
Changes | 0 |
Complex classes like bbarchivist.loadergen often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
1 | #!/usr/bin/env python3 |
||
2 | 5 | """This module is used for creation of autoloaders.""" |
|
3 | |||
4 | 5 | import glob # filename matching |
|
5 | 5 | import os # path work |
|
6 | 5 | import shutil # file copying |
|
7 | |||
8 | 5 | from bbarchivist import bbconstants # versions/constants |
|
9 | 5 | from bbarchivist import exceptions # exception handling |
|
10 | 5 | from bbarchivist import jsonutils # json |
|
11 | 5 | from bbarchivist import pseudocap # implement cap |
|
12 | 5 | from bbarchivist import utilities # directory handler |
|
13 | |||
14 | 5 | __author__ = "Thurask" |
|
15 | 5 | __license__ = "WTFPL v2" |
|
16 | 5 | __copyright__ = "2015-2018 Thurask" |
|
17 | |||
18 | |||
19 | 5 | def read_files(localdir, core=False): |
|
20 | """ |
||
21 | Read list of signed files, return name assignments. |
||
22 | |||
23 | :param localdir: Directory to use. |
||
24 | :type localdir: str |
||
25 | |||
26 | :param core: If we're using a core OS image. Default is false. |
||
27 | :type core: bool |
||
28 | """ |
||
29 | 5 | oslist = read_os_files(localdir, core) |
|
30 | # [8960, 8x30, 8974, ti] |
||
31 | 5 | radlist = read_radio_files(localdir) |
|
32 | # [ti, z10, z10_vzw, q10, z30, z3, 8974] |
||
33 | 5 | pairdict = {} |
|
34 | 5 | mapping = {0:3, 1:0, 2:0, 3:0, 4:0, 5:1, 6:2} |
|
35 | 5 | for idx, rad in enumerate(radlist): |
|
36 | 5 | pairdict[rad] = oslist[mapping[idx]] |
|
37 | 5 | filtdict = {k: v for k, v in pairdict.items() if k} # pop None |
|
38 | 5 | return filtdict |
|
39 | |||
40 | |||
41 | 5 | def find_signed_file(match, localdir, title, silent=False): |
|
42 | """ |
||
43 | Use pattern matching to find a signed file in a directory. |
||
44 | |||
45 | :param match: Match pattern to use. |
||
46 | :type match: str |
||
47 | |||
48 | :param localdir: Directory to use. |
||
49 | :type localdir: str |
||
50 | |||
51 | :param title: File type, in case it isn't found. |
||
52 | :type title: str |
||
53 | |||
54 | :param silent: Don't print that a file wasn't found. Default is False. |
||
55 | :type silent: bool |
||
56 | """ |
||
57 | 5 | try: |
|
58 | 5 | signedfile = glob.glob(os.path.join(localdir, match))[0] |
|
59 | 5 | except IndexError: |
|
60 | 5 | signedfile = None |
|
61 | 5 | if not silent: |
|
62 | 5 | print("No {0} found".format(title)) |
|
63 | 5 | return signedfile |
|
64 | |||
65 | |||
66 | 5 | def generate_os_fixes(core=False): |
|
67 | """ |
||
68 | Generate name regexes for OS signed files. |
||
69 | |||
70 | :param core: If we're using a core OS image. Default is false. |
||
71 | :type core: bool |
||
72 | """ |
||
73 | 5 | if core: |
|
74 | 5 | fix8960 = "*qc8960.*_sfi.BB*.signed" |
|
75 | 5 | fixomap_new = "*winchester.*_sfi.BB*.signed" |
|
76 | 5 | fixomap_old = "*os.factory_sfi.BB*.signed" |
|
77 | 5 | fix8930 = "*qc8x30.BB*.signed" |
|
78 | 5 | fix8974_new = "*qc8974.BB*.signed" |
|
79 | 5 | fix8974_old = "*qc8974.*_sfi.BB*.signed" |
|
80 | else: |
||
81 | 5 | fix8960 = "*qc8960.*_sfi.desktop.BB*.signed" |
|
82 | 5 | fixomap_new = "*winchester.*_sfi.desktop.BB*.signed" |
|
83 | 5 | fixomap_old = "*os.factory_sfi.desktop.BB*.signed" |
|
84 | 5 | fix8930 = "*qc8x30.desktop.BB*.signed" |
|
85 | 5 | fix8974_new = "*qc8974.desktop.BB*.signed" |
|
86 | 5 | fix8974_old = "*qc8974.*_sfi.desktop.BB*.signed" |
|
87 | 5 | return fix8960, fixomap_new, fixomap_old, fix8930, fix8974_new, fix8974_old |
|
88 | |||
89 | |||
90 | 5 | def read_os_files(localdir, core=False): |
|
91 | """ |
||
92 | Read list of OS signed files, return name assignments. |
||
93 | |||
94 | :param localdir: Directory to use. |
||
95 | :type localdir: str |
||
96 | |||
97 | :param core: If we're using a core OS image. Default is false. |
||
98 | :type core: bool |
||
99 | """ |
||
100 | 5 | fix8960, fixomap_new, fixomap_old, fix8930, fix8974_new, fix8974_old = generate_os_fixes(core) |
|
101 | # 8960 |
||
102 | 5 | os_8960 = find_signed_file(fix8960, localdir, "8960 OS") |
|
103 | # 8x30 (10.3.1 MR+) |
||
104 | 5 | os_8x30 = find_signed_file(fix8930, localdir, "8x30 OS", True) |
|
105 | 5 | if os_8x30 is None: |
|
106 | 5 | os_8x30 = find_signed_file(fix8960, localdir, "8x30 OS") |
|
107 | # 8974 |
||
108 | 5 | os_8974 = find_signed_file(fix8974_new, localdir, "8974 OS", True) |
|
109 | 5 | if os_8974 is None: |
|
110 | 5 | os_8974 = find_signed_file(fix8974_old, localdir, "8974 OS") |
|
111 | # OMAP |
||
112 | 5 | os_ti = find_signed_file(fixomap_new, localdir, "OMAP OS", True) |
|
113 | 5 | if os_ti is None: |
|
114 | 5 | os_ti = find_signed_file(fixomap_old, localdir, "OMAP OS") |
|
115 | 5 | return [os_8960, os_8x30, os_8974, os_ti] |
|
116 | |||
117 | |||
118 | 5 | def read_radio_files(localdir): |
|
119 | """ |
||
120 | Read list of radio signed files, return name assignments. |
||
121 | |||
122 | :param localdir: Directory to use. |
||
123 | :type localdir: str |
||
124 | """ |
||
125 | # STL100-1 |
||
126 | 5 | radio_ti = find_signed_file("*radio.m5730*.signed", localdir, "OMAP radio") |
|
127 | # STL100-X |
||
128 | 5 | radio_z10 = find_signed_file("*radio.qc8960.BB*.signed", localdir, "8960 radio") |
|
129 | # STL100-4 |
||
130 | 5 | radio_z10_vzw = find_signed_file("*radio.qc8960*omadm*.signed", localdir, "VZW 8960 radio") |
|
131 | # Q10/Q5 |
||
132 | 5 | radio_q10 = find_signed_file("*radio.qc8960*wtr.*signed", localdir, "Q10/Q5 radio") |
|
133 | # Z30/Classic |
||
134 | 5 | radio_z30 = find_signed_file("*radio.qc8960*wtr5*.signed", localdir, "Z30/Classic radio") |
|
135 | # Z3 |
||
136 | 5 | radio_z3 = find_signed_file("*radio.qc8930*wtr5*.signed", localdir, "Z3 radio") |
|
137 | # Passport |
||
138 | 5 | radio_8974 = find_signed_file("*radio.qc8974*wtr2*.signed", localdir, "Passport radio") |
|
139 | 5 | return [radio_ti, radio_z10, radio_z10_vzw, radio_q10, radio_z30, radio_z3, radio_8974] |
|
140 | |||
141 | |||
142 | 5 | def zeropad(splitver, idx, padlen): |
|
143 | """ |
||
144 | Zero-pad an element of an OS/radio version to a certain length. |
||
145 | |||
146 | :param splitver: OS/radio version, but split into quarters. |
||
147 | :type splitver: list(str) |
||
148 | |||
149 | :param idx: Index of splitver which must be checked. |
||
150 | :type idx: int |
||
151 | |||
152 | :param padlen: Length to pad to. |
||
153 | :type padlen: int |
||
154 | """ |
||
155 | 5 | if len(splitver[idx]) < padlen: |
|
156 | 5 | splitver[idx] = splitver[idx].rjust(padlen, "0") |
|
157 | 5 | return splitver |
|
158 | |||
159 | |||
160 | 5 | def versionpad(splitver): |
|
161 | """ |
||
162 | Properly pad an OS/radio version. |
||
163 | |||
164 | :param splitver: OS/radio version, but split into quarters. |
||
165 | :type splitver: list(str) |
||
166 | """ |
||
167 | 5 | splitver = zeropad(splitver, 2, 2) |
|
168 | 5 | splitver = zeropad(splitver, 3, 4) |
|
169 | 5 | return splitver |
|
170 | |||
171 | |||
172 | 5 | def pretty_formatter(osversion, radioversion): |
|
173 | """ |
||
174 | Format OS/radio versions to cope with systems with poor sorting. |
||
175 | |||
176 | :param osversion: OS version, 10.x.y.zzzz. |
||
177 | :type osversion: str |
||
178 | |||
179 | :param radioversion: Radio version, 10.x.y.zzzz. |
||
180 | :type radioversion: str |
||
181 | """ |
||
182 | # 10.x.y.zzz becomes 10.x.0y.0zzz |
||
183 | 5 | splitos = osversion.split(".") |
|
184 | 5 | splitos = versionpad(splitos) |
|
185 | 5 | the_os = ".".join(splitos) |
|
186 | 5 | splitrad = radioversion.split(".") |
|
187 | 5 | splitrad = versionpad(splitrad) |
|
188 | 5 | the_radio = ".".join(splitrad) |
|
189 | 5 | return the_os, the_radio |
|
190 | |||
191 | |||
192 | 5 | def format_suffix(altradio=None, radioversion=None, core=False): |
|
193 | """ |
||
194 | Formulate suffix for hybrid autoloaders. |
||
195 | |||
196 | :param altradio: If a hybrid autoloader is being made. |
||
197 | :type altradio: bool |
||
198 | |||
199 | :param radioversion: The hybrid radio version, if applicable. |
||
200 | :type radioversion: str |
||
201 | |||
202 | :param core: If we're using a core OS image. Default is false. |
||
203 | :type core: bool |
||
204 | """ |
||
205 | 5 | suffix = "_R{0}".format(radioversion) if altradio and radioversion else "" |
|
206 | 5 | if core: |
|
207 | 5 | suffix += "_CORE" |
|
208 | 5 | return suffix |
|
209 | |||
210 | |||
211 | 5 | def generate_loaders(osversion, radioversion, radios=True, localdir=None, altradio=False, core=False): |
|
1 ignored issue
–
show
|
|||
212 | """ |
||
213 | Create and label autoloaders for :mod:`bbarchivist.scripts.archivist`. |
||
214 | |||
215 | :param osversion: OS version, 10.x.y.zzzz. |
||
216 | :type osversion: str |
||
217 | |||
218 | :param radioversion: Radio version, 10.x.y.zzzz. |
||
219 | :type radioversion: str |
||
220 | |||
221 | :param radios: Whether to make radios or not. True by default. |
||
222 | :type radios: bool |
||
223 | |||
224 | :param localdir: Working path. Default is local dir. |
||
225 | :type localdir: str |
||
226 | |||
227 | :param altradio: If we're using an alternate radio. Default is false. |
||
228 | :type altradio: bool |
||
229 | |||
230 | :param core: If we're using a core OS image. Default is false. |
||
231 | :type core: bool |
||
232 | """ |
||
233 | # default parsing |
||
234 | 5 | localdir = utilities.dirhandler(localdir, os.getcwd()) |
|
235 | 5 | print("GETTING FILENAMES...") |
|
236 | 5 | filedict = read_files(localdir, core) |
|
237 | 5 | osversion, radioversion = pretty_formatter(osversion, radioversion) |
|
238 | 5 | suffix = format_suffix(altradio, radioversion, core) |
|
239 | # Generate loaders |
||
240 | 5 | print("CREATING LOADERS...") |
|
241 | 5 | filtrad = [rad for rad in filedict.keys() if rad] # pop None |
|
242 | 5 | generate_individual_loaders(filtrad, osversion, radioversion, suffix, filedict, radios, localdir) |
|
243 | |||
244 | |||
245 | 5 | def generate_individual_loaders(filtrad, osversion, radioversion, suffix, filedict, radios, localdir): |
|
1 ignored issue
–
show
|
|||
246 | """ |
||
247 | Generate individual loaders when generating several at once. |
||
248 | |||
249 | :param filtrad: List of radio files, if they exist. |
||
250 | :type filtrad: list(str) |
||
251 | |||
252 | :param osversion: OS version, 10.x.y.zzzz. |
||
253 | :type osversion: str |
||
254 | |||
255 | :param radioversion: Radio version, 10.x.y.zzzz. |
||
256 | :type radioversion: str |
||
257 | |||
258 | :param suffix: Alternate radio, or blank. |
||
259 | :type suffix: str |
||
260 | |||
261 | :param filedict: Dictionary of radio:OS pairs. |
||
262 | :type filedict: dict(str: str) |
||
263 | |||
264 | :param radios: Whether to make radios or not. True by default. |
||
265 | :type radios: bool |
||
266 | |||
267 | :param localdir: Working path. Default is local dir. |
||
268 | :type localdir: str |
||
269 | """ |
||
270 | 5 | for radval in filtrad: |
|
271 | 5 | device = generate_device(radval) |
|
272 | 5 | osname = generate_filename(device, osversion, suffix) |
|
273 | 5 | osfile = filedict[radval] |
|
274 | 5 | if osfile is not None: |
|
275 | 5 | wrap_pseudocap(osname, localdir, osfile, radval) |
|
276 | 5 | if radios: |
|
277 | 5 | radname = generate_filename(device, radioversion, "") |
|
278 | 5 | wrap_pseudocap(radname, localdir, radval) |
|
279 | |||
280 | |||
281 | |||
282 | 5 | def wrap_pseudocap(filename, folder, first, second=None): |
|
283 | """ |
||
284 | A filtered, excepting wrapper for pseudocap. |
||
285 | |||
286 | :param filename: The title of the new loader. |
||
287 | :type filename: str |
||
288 | |||
289 | :param folder: The folder to create the loader in. |
||
290 | :type folder: str |
||
291 | |||
292 | :param first: The first signed file, required. |
||
293 | :type first: str |
||
294 | |||
295 | :param second: The second signed file, optional. |
||
296 | :type second: str |
||
297 | """ |
||
298 | 5 | if first is None: |
|
299 | 5 | print("No OS!") |
|
300 | 5 | raise SystemError |
|
301 | 5 | try: |
|
302 | 5 | pseudocap.make_autoloader(filename, [first, second], folder=folder) |
|
303 | 5 | except (OSError, IndexError, SystemError) as exc: |
|
304 | 5 | msg = "Could not create {0}".format(filename) |
|
305 | 5 | exceptions.handle_exception(exc, msg, None) |
|
306 | |||
307 | |||
308 | 5 | def generate_skeletons(): |
|
309 | """ |
||
310 | Read JSON to get a dict of all filename components. |
||
311 | """ |
||
312 | 5 | namelist = {0: None, 1: None, 2: None, 3: None, 4: None, 5: None, 6: None} |
|
313 | 5 | data = jsonutils.load_json('integermap') |
|
314 | 5 | for key in data: |
|
315 | 5 | if key['id'] in namelist: |
|
316 | 5 | namelist[key['id']] = (key['parts']) |
|
317 | 5 | namelist[key['id']].append(".exe") |
|
318 | 5 | return namelist |
|
319 | |||
320 | |||
321 | 5 | def generate_device(radio): |
|
322 | """ |
||
323 | Read JSON to get the device integer ID from device radio. |
||
324 | |||
325 | :param radio: The radio filename to look up. |
||
326 | :type radio: str |
||
327 | """ |
||
328 | 5 | data = jsonutils.load_json('integermap') |
|
329 | 5 | for key in data: |
|
330 | 5 | if key['radtype'] in radio: |
|
331 | 5 | idx = int(key['id']) |
|
332 | 5 | break |
|
333 | 5 | return idx |
|
1 ignored issue
–
show
|
|||
334 | |||
335 | |||
336 | 5 | def generate_filename(device, version, suffix=None): |
|
337 | """ |
||
338 | Use skeleton dict to create loader filenames. |
||
339 | |||
340 | :param device: Device to use. |
||
341 | :type device: int |
||
342 | |||
343 | :param version: OS or radio version. |
||
344 | :type version: str |
||
345 | |||
346 | :param suffix: Alternate radio, or blank. |
||
347 | :type suffix: str |
||
348 | """ |
||
349 | 5 | thed = generate_skeletons() |
|
350 | 5 | if device < 0: |
|
351 | 5 | return None |
|
352 | 5 | dev = thed[device] |
|
353 | 5 | if suffix is None: |
|
354 | 5 | suffix = "" |
|
355 | 5 | return "{0}{1}{2}{3}{4}".format(dev[0], version, suffix, dev[1], dev[2]) |
|
356 | |||
357 | |||
358 | 5 | def generate_lazy_loader( |
|
359 | osversion, device, |
||
360 | localdir=None, altradio=None, core=False): |
||
361 | """ |
||
362 | Create and label autoloaders for :mod:`bbarchivist.scripts.lazyloader`. |
||
363 | :func:`generate_loaders`, but for making one OS/radio loader. |
||
364 | |||
365 | :param osversion: OS version, 10.x.y.zzzz. |
||
366 | :type osversion: str |
||
367 | |||
368 | :param device: Selected device, from |
||
369 | :type device: int |
||
370 | |||
371 | :param localdir: Working path. Default is local dir. |
||
372 | :type localdir: str |
||
373 | |||
374 | :param altradio: The alternate radio in use, if there is one. |
||
375 | :type altradio: str |
||
376 | |||
377 | :param core: If we're using a core OS image. Default is false. |
||
378 | :type core: bool |
||
379 | """ |
||
380 | # default parsing |
||
381 | 5 | localdir = utilities.dirhandler(localdir, os.getcwd()) |
|
382 | 5 | print("CREATING LOADER...") |
|
383 | 5 | suffix = format_suffix(bool(altradio), altradio, core) |
|
384 | 5 | osfile = None |
|
385 | 5 | absoglob = "{0}{1}".format(localdir, os.sep) |
|
386 | 5 | try: |
|
387 | 5 | osfile = str(glob.glob("{0}*_sfi*.signed".format(absoglob))[0]) |
|
388 | 5 | except IndexError: |
|
389 | 5 | print("No OS found") |
|
390 | else: |
||
391 | 5 | generate_lazy_set(osversion, device, osfile, suffix, absoglob, localdir) |
|
392 | |||
393 | |||
394 | 5 | def generate_lazy_set(osversion, device, osfile, suffix, absoglob, localdir=None): |
|
1 ignored issue
–
show
|
|||
395 | """ |
||
396 | Get radio file and then generate autoloader. |
||
397 | |||
398 | :param osversion: OS version, 10.x.y.zzzz. |
||
399 | :type osversion: str |
||
400 | |||
401 | :param device: Selected device, from |
||
402 | :type device: int |
||
403 | |||
404 | :param osfile: OS signed filename. |
||
405 | :type osfile: str |
||
406 | |||
407 | :param suffix: Loader name suffix. |
||
408 | :type suffix: str |
||
409 | |||
410 | :param absoglob: Local path + path separator. |
||
411 | :type absoglob: str |
||
412 | |||
413 | :param localdir: Working path. Default is local dir. |
||
414 | :type localdir: str |
||
415 | """ |
||
416 | 5 | radiofile = None |
|
417 | 5 | try: |
|
418 | 5 | sset = set(glob.glob("{0}*.signed".format(absoglob))) |
|
419 | 5 | rset = sset - set(glob.glob("{0}*_sfi*.signed".format(absoglob))) |
|
420 | 5 | radiofile = str(list(rset)[0]) |
|
421 | 5 | except IndexError: |
|
422 | 5 | print("No radio found") |
|
423 | else: |
||
424 | 5 | loadername = generate_lazy_filename(osversion, suffix, device) |
|
425 | 5 | wrap_pseudocap(loadername, localdir, osfile, radiofile) |
|
426 | |||
427 | |||
428 | 5 | def generate_lazy_filename(osversion, suffix, device): |
|
429 | """ |
||
430 | Read JSON to formulate a single filename. |
||
431 | |||
432 | :param osversion: OS version. |
||
433 | :type osversion: str |
||
434 | |||
435 | :param suffix: Alternate radio, or just blank. |
||
436 | :type suffix: str |
||
437 | |||
438 | :param device: Device to use. |
||
439 | :type device: int |
||
440 | """ |
||
441 | 5 | data = jsonutils.load_json('integermap') |
|
442 | 5 | for key in data: |
|
443 | 5 | if key['id'] == device: |
|
444 | 5 | fname = key['parts'] |
|
445 | 5 | break |
|
446 | 5 | return "{0}{1}{2}{3}.exe".format(fname[0], osversion, suffix, fname[1]) |
|
1 ignored issue
–
show
|
|||
447 | |||
448 | |||
449 | 5 | def point_point_copy(inpath, outpath, filename): |
|
450 | """ |
||
451 | Copy a file from one absolute path to another. |
||
452 | |||
453 | :param inpath: Input path. |
||
454 | :type inpath: str |
||
455 | |||
456 | :param outpath: Output path. |
||
457 | :type outpath: str |
||
458 | |||
459 | :param filename: Filename. |
||
460 | :type filename: str |
||
461 | """ |
||
462 | 5 | shutil.copy(os.path.join(inpath, filename), os.path.join(outpath, filename)) |
|
463 | |||
464 | |||
465 | 5 | def point_point_bulk(inpath, outpath, files): |
|
466 | """ |
||
467 | Copy a list of files from one absolute path to another. |
||
468 | |||
469 | :param inpath: Input path. |
||
470 | :type inpath: str |
||
471 | |||
472 | :param outpath: Output path. |
||
473 | :type outpath: str |
||
474 | |||
475 | :param files: List of filenames. |
||
476 | :type files: list(str) |
||
477 | """ |
||
478 | 5 | for file in files: |
|
479 | 5 | point_point_copy(inpath, outpath, file) |
|
480 | |||
481 | |||
482 | 5 | def generate_tclloader_script(dirname, batchfile, shfile, wipe=True): |
|
483 | """ |
||
484 | Copy script files from site-packages to loader directory. |
||
485 | |||
486 | :param dirname: Name for final directory and loader. |
||
487 | :type dirname: str |
||
488 | |||
489 | :param batchfile: Path to flashall.bat. |
||
490 | :type batchfile: str |
||
491 | |||
492 | :param shfile: Path to flashall.sh. |
||
493 | :type shfile: str |
||
494 | |||
495 | :param wipe: If the final loader wipes userdata. Default is True. |
||
496 | :type wipe: bool |
||
497 | """ |
||
498 | 5 | shutil.copy(batchfile, os.path.join(dirname, "flashall.bat")) |
|
499 | 5 | shutil.copy(shfile, os.path.join(dirname, "flashall.sh")) |
|
500 | 5 | if not wipe: |
|
501 | 5 | tclloader_nowipe(os.path.join(dirname, "flashall.bat")) |
|
502 | 5 | tclloader_nowipe(os.path.join(dirname, "flashall.sh")) |
|
503 | |||
504 | |||
505 | 5 | def tclloader_nowipe(infile): |
|
506 | """ |
||
507 | Modify a script file to strike references to wiping the phone. |
||
508 | |||
509 | :param infile: Path to script file to modify. |
||
510 | :type infile: str |
||
511 | """ |
||
512 | 5 | filterout = ("oem securewipe", "flash userdata") |
|
513 | 5 | with open(infile, "r+", newline="") as afile: |
|
514 | 5 | content = afile.read() |
|
515 | 5 | afile.seek(0) |
|
516 | 5 | for line in content.split("\n"): |
|
517 | 5 | if not any(part in line for part in filterout): |
|
518 | 5 | afile.write(line + "\n") |
|
519 | 5 | afile.truncate() |
|
520 | |||
521 | |||
522 | 5 | def generate_google_host(hostin, hostout): |
|
523 | """ |
||
524 | Generate host directory from Google platform tools, i.e. fastboot. |
||
525 | |||
526 | :param hostin: Directory containing files to copy. |
||
527 | :type hostin: str |
||
528 | |||
529 | :param hostout: Directory that files are to be copied to. |
||
530 | :type hostout: str |
||
531 | """ |
||
532 | 5 | platforms = ["linux", "windows", "darwin"] |
|
533 | 5 | inouts = {os.path.join(hostin, plat, "platform-tools"): os.path.join(hostout, "{0}-x86".format(plat), "bin") for plat in platforms} |
|
534 | 5 | for infile, outfile in inouts.items(): |
|
535 | 5 | shutil.copytree(infile, outfile) |
|
536 | |||
537 | |||
538 | 5 | def generate_tclloader_host(hostin, hostout): |
|
539 | """ |
||
540 | Generate host directory from autoloader template, i.e. fastboot. |
||
541 | |||
542 | :param hostin: Directory containing files to copy. |
||
543 | :type hostin: str |
||
544 | |||
545 | :param hostout: Directory that files are to be copied to. |
||
546 | :type hostout: str |
||
547 | """ |
||
548 | 5 | os.makedirs(os.path.join(hostout, "darwin-x86", "bin")) |
|
549 | 5 | os.makedirs(os.path.join(hostout, "linux-x86", "bin")) |
|
550 | 5 | os.makedirs(os.path.join(hostout, "windows-x86", "bin")) |
|
551 | 5 | macfile = os.path.join("darwin-x86", "bin", "fastboot") |
|
552 | 5 | linfile = os.path.join("linux-x86", "bin", "fastboot") |
|
553 | 5 | winx = ["AdbWinApi.dll", "AdbWinUsbApi.dll", "fastboot.exe"] |
|
554 | 5 | winfiles = [os.path.join("windows-x86", "bin", x) for x in winx] |
|
555 | 5 | winfiles.extend([linfile, macfile]) |
|
556 | 5 | point_point_bulk(hostin, hostout, winfiles) |
|
557 | |||
558 | |||
559 | 5 | def generate_tclloader_sig(sigin, sigout): |
|
560 | """ |
||
561 | Generate common signature files. |
||
562 | |||
563 | :param sigin: Directory containing files to copy. |
||
564 | :type sigin: str |
||
565 | |||
566 | :param sigout: Directory that files are to be copied to. |
||
567 | :type sigout: str |
||
568 | """ |
||
569 | 5 | for entry in ["boot", "recovery"]: |
|
570 | 5 | shutil.copy(os.path.join(sigin, "{0}.img.production.sig".format(entry)), os.path.join(sigout, "{0}.img.sig".format(entry))) |
|
571 | |||
572 | |||
573 | 5 | def generate_tclloader_csig(sigin, sigout, carrier): |
|
574 | """ |
||
575 | Generate carrier variant signature files. |
||
576 | |||
577 | :param sigin: Directory containing files to copy. |
||
578 | :type sigin: str |
||
579 | |||
580 | :param sigout: Directory that files are to be copied to. |
||
581 | :type sigout: str |
||
582 | |||
583 | :param carrier: Carrier to check: att, sprint, china, vzw |
||
584 | :type carrier: str |
||
585 | """ |
||
586 | 5 | for entry in ["boot", "recovery"]: |
|
587 | 5 | shutil.copy(os.path.join(sigin, "{1}.img.production-{0}.sig".format(carrier, entry)), os.path.join(sigout, "{1}.img{0}.sig".format(carrier, entry))) |
|
588 | |||
589 | |||
590 | 5 | def generate_tclloader_carriers(sigin, sigout): |
|
591 | """ |
||
592 | Collect carrier variant signature files. |
||
593 | |||
594 | :param sigin: Directory containing files to copy. |
||
595 | :type sigin: str |
||
596 | |||
597 | :param sigout: Directory that files are to be copied to. |
||
598 | :type sigout: str |
||
599 | """ |
||
600 | 5 | prods = set(x.split("-")[-1].split(".")[0] for x in os.listdir(sigin) if "production-" in x) - {"boot", "recovery"} |
|
601 | 5 | if prods: |
|
602 | 5 | generate_tclloader_carriter(sigin, sigout, prods) |
|
603 | |||
604 | |||
605 | 5 | def generate_tclloader_carriter(sigin, sigout, prods): |
|
606 | """ |
||
607 | Iterate carrier variant signature files. |
||
608 | |||
609 | :param sigin: Directory containing files to copy. |
||
610 | :type sigin: str |
||
611 | |||
612 | :param sigout: Directory that files are to be copied to. |
||
613 | :type sigout: str |
||
614 | |||
615 | :param prods: Set of carriers. |
||
616 | :type prods: set(str) |
||
617 | """ |
||
618 | 5 | for carr in prods: |
|
619 | 5 | generate_tclloader_csig(sigin, sigout, carr) |
|
620 | |||
621 | |||
622 | 5 | def generate_tclloader_mbn(mdnin, mdnout): |
|
623 | """ |
||
624 | Generate mbn files. |
||
625 | |||
626 | :param mdnin: Directory containing files to copy. |
||
627 | :type mdnin: str |
||
628 | |||
629 | :param mdnout: Directory that files are to be copied to. |
||
630 | :type mdnout: str |
||
631 | """ |
||
632 | 5 | files = ["devcfg.mbn", "devcfg_cn.mbn", "rpm.mbn", "tz.mbn"] |
|
633 | 5 | point_point_bulk(mdnin, mdnout, files) |
|
634 | |||
635 | |||
636 | 5 | def generate_tclloader_omniset(omnin, omnilist, prefix, suffix, filt): |
|
637 | """ |
||
638 | Generic function to generate sets. |
||
639 | |||
640 | :param omnin: Directory containing files to copy. |
||
641 | :type omnin: str |
||
642 | |||
643 | :param omnilist: List of variants. |
||
644 | :type omnilist: list(str) |
||
645 | |||
646 | :param prefix: Prefix, before items in list. |
||
647 | :type prefix: str |
||
648 | |||
649 | :param suffix: Suffix, after items in list. |
||
650 | :type suffix: str |
||
651 | |||
652 | :param filt: Filter, required to pick file out of directory listing. |
||
653 | :type filt: str |
||
654 | """ |
||
655 | 5 | omfiles = set(os.path.join(omnin, "{1}{0}{2}".format(omni, prefix, suffix)) for omni in omnilist) |
|
656 | 5 | infiles = set(os.path.join(omnin, filex) for filex in os.listdir(omnin) if filt in filex) |
|
657 | 5 | return omfiles, infiles |
|
658 | |||
659 | |||
660 | 5 | def generate_tclloader_oemset(oemin, oems): |
|
661 | """ |
||
662 | Generate sets for OEM variants. |
||
663 | |||
664 | :param oemin: Directory containing files to copy. |
||
665 | :type oemin: str |
||
666 | |||
667 | :param oems: List of OEM variants. |
||
668 | :type oems: list(str) |
||
669 | """ |
||
670 | 5 | ofiles, infiles = generate_tclloader_omniset(oemin, oems, "", ".img", "oem_") |
|
671 | 5 | return ofiles, infiles |
|
672 | |||
673 | |||
674 | 5 | def generate_tclloader_oemfilt(oemin, oems): |
|
675 | """ |
||
676 | Filter non-existent OEM variants. |
||
677 | |||
678 | :param oemin: Directory containing files to copy. |
||
679 | :type oemin: str |
||
680 | |||
681 | :param oems: List of OEM variants. |
||
682 | :type oems: list(str) |
||
683 | """ |
||
684 | 5 | ofiles, infiles = generate_tclloader_oemset(oemin, oems) |
|
685 | 5 | coll = [os.path.basename(oemf).replace(".img", "") for oemf in ofiles - infiles] |
|
686 | 5 | oems = [oemp for oemp in oems if oemp not in coll] |
|
687 | 5 | return oems |
|
688 | |||
689 | |||
690 | 5 | def generate_tclloader_radset(radin, rads): |
|
691 | """ |
||
692 | Generate sets for radio variants. |
||
693 | |||
694 | :param radin: Directory containing files to copy. |
||
695 | :type radin: str |
||
696 | |||
697 | :param rads: List of radio variants. |
||
698 | :type rads: list(str) |
||
699 | """ |
||
700 | 5 | rfiles, infiles = generate_tclloader_omniset(radin, rads, "NON-HLOS-", ".bin", "NON-HLOS-") |
|
701 | 5 | return rfiles, infiles |
|
702 | |||
703 | |||
704 | 5 | def generate_tclloader_radfilt(radin, rads): |
|
705 | """ |
||
706 | Filter non-existent radio variants. |
||
707 | |||
708 | :param radin: Directory containing files to copy. |
||
709 | :type radin: str |
||
710 | |||
711 | :param rads: List of radio variants. |
||
712 | :type rads: list(str) |
||
713 | """ |
||
714 | 5 | rfiles, infiles = generate_tclloader_radset(radin, rads) |
|
715 | 5 | coll = [os.path.basename(radf).replace(".bin", "").replace("NON-HLOS-", "") for radf in rfiles - infiles] |
|
716 | 5 | rads = [radp for radp in rads if radp not in coll] |
|
717 | 5 | return rads |
|
718 | |||
719 | |||
720 | 5 | def generate_tclloader_deps(platform): |
|
721 | """ |
||
722 | Generate platform-specific file names. |
||
723 | |||
724 | :param platform: Platform type (i.e. subdirectory of target/product). |
||
725 | :type platform: str |
||
726 | """ |
||
727 | 5 | if platform == "bbry_qc8953": # KEYone |
|
728 | 5 | oems = ["oem_att", "oem_china", "oem_common", "oem_sprint", "oem_vzw", "oem_indonesia"] |
|
729 | 5 | radios = ["china", "dschina", "emea", "global", "india", "japan", "usa"] |
|
730 | 5 | elif platform == "bbry_qc8953krypton": # Motion |
|
731 | 5 | oems = ["oem_att", "oem_common", "oem_sprint"] |
|
732 | 5 | radios = ["americas", "cdma", "dscn", "dsglobal", "ssglobal"] |
|
733 | 5 | return oems, radios |
|
2 ignored issues
–
show
|
|||
734 | |||
735 | |||
736 | 5 | def generate_tclloader_looseends(imgout, platform): |
|
737 | """ |
||
738 | Rename files that need to be renamed. |
||
739 | |||
740 | :param imgout: Directory that files are to be copied to. |
||
741 | :type imgout: str |
||
742 | |||
743 | :param platform: Platform type (i.e. subdirectory of target/product). |
||
744 | :type platform: str |
||
745 | """ |
||
746 | 5 | if platform == "bbry_qc8953": # KEYone |
|
747 | 5 | pass # no special exceptions |
|
748 | 5 | elif platform == "bbry_qc8953krypton": # Motion |
|
749 | 5 | oldglobal = os.path.join(imgout, "NON-HLOS-ssglobal.bin") |
|
750 | 5 | newglobal = os.path.join(imgout, "NON-HLOS-global.bin") |
|
751 | 5 | os.rename(oldglobal, newglobal) # SS intl model has different name than modem |
|
752 | 5 | oldamericas = os.path.join(imgout, "NON-HLOS-americas.bin") |
|
753 | 5 | newamericas = os.path.join(imgout, "NON-HLOS-dsamericas.bin") |
|
754 | 5 | shutil.copy(oldamericas, newamericas) # DS/SS americas model use same modem |
|
755 | |||
756 | |||
757 | 5 | def generate_tclloader_img(imgin, imgout, platform): |
|
758 | """ |
||
759 | Generate partition images and radios. |
||
760 | |||
761 | :param imgin: Directory containing files to copy. |
||
762 | :type imgin: str |
||
763 | |||
764 | :param imgout: Directory that files are to be copied to. |
||
765 | :type imgout: str |
||
766 | |||
767 | :param platform: Platform type (i.e. subdirectory of target/product). |
||
768 | :type platform: str |
||
769 | """ |
||
770 | 5 | imgs = ["recovery", "system", "userdata", "cache", "boot"] |
|
771 | 5 | point_point_bulk(imgin, imgout, ["{0}.img".format(img) for img in imgs]) |
|
772 | 5 | oems, radios = generate_tclloader_deps(platform) |
|
773 | 5 | oems = generate_tclloader_oemfilt(imgin, oems) |
|
774 | 5 | point_point_bulk(imgin, imgout, ["{0}.img".format(oem) for oem in oems]) |
|
775 | 5 | radios = generate_tclloader_radfilt(imgin, radios) |
|
776 | 5 | point_point_bulk(imgin, imgout, ["NON-HLOS-{0}.bin".format(rad) for rad in radios]) |
|
777 | 5 | others = ["adspso.bin", "emmc_appsboot.mbn", "sbl1_signed.mbn"] |
|
778 | 5 | point_point_bulk(imgin, imgout, others) |
|
779 | 5 | generate_tclloader_looseends(imgout, platform) |
|
780 | |||
781 | |||
782 | 5 | def generate_tclloader(localdir, dirname, platform, localtools=False, wipe=True): |
|
783 | """ |
||
784 | Generate Android loader from extracted template files. |
||
785 | |||
786 | :param localdir: Directory containing extracted template files. |
||
787 | :type localdir: str |
||
788 | |||
789 | :param dirname: Name for final directory and loader. |
||
790 | :type dirname: str |
||
791 | |||
792 | :param platform: Platform type (i.e. subdirectory of target/product). |
||
793 | :type platform: str |
||
794 | |||
795 | :param localtools: If host files will be copied from a template rather than a download. Default is False. |
||
796 | :type localtools: bool |
||
797 | |||
798 | :param wipe: If the final loader wipes userdata. Default is True. |
||
799 | :type wipe: bool |
||
800 | """ |
||
801 | 5 | if not os.path.exists(dirname): |
|
802 | 5 | os.makedirs(dirname) |
|
803 | 5 | hostdir = os.path.join(dirname, "host") |
|
804 | 5 | os.makedirs(hostdir) |
|
805 | 5 | imgdir = os.path.join(dirname, "img") |
|
806 | 5 | os.makedirs(imgdir) |
|
807 | 5 | generate_tclloader_script(dirname, bbconstants.FLASHBAT.location, bbconstants.FLASHSH.location, wipe) |
|
808 | 5 | if localtools: |
|
809 | 5 | hdir = os.path.join(localdir, "host") |
|
810 | 5 | generate_tclloader_host(hdir, hostdir) |
|
811 | else: |
||
812 | 5 | platdir = "plattools" |
|
813 | 5 | generate_google_host(platdir, hostdir) |
|
814 | 5 | pdir = os.path.join(localdir, "target", "product", platform) |
|
815 | 5 | generate_tclloader_img(pdir, imgdir, platform) |
|
816 | 5 | sdir = os.path.join(pdir, "sig") |
|
817 | 5 | generate_tclloader_sig(sdir, imgdir) |
|
818 | 5 | generate_tclloader_carriers(sdir, imgdir) |
|
819 | 5 | qdir = os.path.join(pdir, "qcbc") |
|
820 | generate_tclloader_mbn(qdir, imgdir) |
||
821 |