Completed
Push — master ( 301448...04ec5d )
by John
07:11
created

generate_tclloader_deps()   A

Complexity

Conditions 3

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3

Importance

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