-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathadbota.py
More file actions
executable file
·128 lines (94 loc) · 3.65 KB
/
adbota.py
File metadata and controls
executable file
·128 lines (94 loc) · 3.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#!/usr/bin/python3
import os
import sys
import re
import subprocess
import argparse
VERBOSE = False
def true_size(s):
u = {'B': 1, 'K': 1024, 'M': 1024*1024, 'G': 1024*1024*1024}
if m := re.search(r'(\d+)([BKMG])', s):
return int(m.group(1)) * u[m.group(2)]
return 0
def nice_size(n):
u = {'B': 1, 'K': 1024, 'M': 1024*1024, 'G': 1024*1024*1024}
for k, v in reversed(u.items()):
if n >= v and n % v == 0:
return f"{n//v:,}{k}"
return f"{n:,}B"
def check_exits(file):
if not os.path.exists(file):
print(f"FILE: {file} NOT FOUND!")
exit(1)
def log(blk, image, blk_size):
print(f"Flashed to {blk} with {nice_size(blk_size)} block.sz where {nice_size(os.path.getsize(image))} image.sz...")
def parse_part(part):
if (m := re.search(r'(\d+[KMG])@(\d+[KMG])\((\w+)\)', part)) or (m := re.search(r'(\d+[KMG])\((\w+)\)', part)):
if len(m.groups()) == 3:
size = true_size(m.group(1))
offset = true_size(m.group(2))
image = m.group(3) + ".img"
return image, size, offset
else:
size = true_size(m.group(1))
image = m.group(2) + ".img"
offset = 0
return image, size, offset
def write_once(device, image_name):
global_offset = 0
blk_part = 1 # if more then one line with config
check_exits(".env.txt")
file_env = open(".env.txt")
for line in file_env.readlines():
if m := re.search(r'(blkdevparts|sd_parts)=(\w+)', line):
mmcblk = m.group(2)
partitions = re.sub(r'blkdevparts=\w+:', '', line).split(',')
for part in partitions:
image, size, offset = parse_part(part)
if image_name == image:
check_exits(image)
adb_exec(device, ["shell", f'dd if=/{image} of=/dev/{mmcblk}p{blk_part} bs=1k'])
log(mmcblk + f"p{blk_part}", image, size)
return
global_offset += size
blk_part += 1
file_env.close()
def adb_exec(device, command):
cmd = ["adb"] + command
if device != "":
cmd = ["adb", "-s", str(device)] + command
try:
result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True, text=True)
if VERBOSE:
print(result.stdout)
return result.stdout
except subprocess.CalledProcessError as e:
print("ADB ERROR:")
print("CMD:", " ".join(cmd))
print(e.stdout, e.stderr)
sys.exit(1)
def main():
global VERBOSE
parser = argparse.ArgumentParser(description="Luckfox ADB OTA Updater")
parser.add_argument('-d', "--device", metavar="DEV", help="ADB device id (ex: 9ad1s342)", default="")
parser.add_argument('-i', "--image", metavar="IMG", help="Image (ex: boot.img)", required=True)
parser.add_argument('-v', "--verbose", action="store_true", help="Print more verbose output")
args = parser.parse_args()
if args.verbose:
VERBOSE = True
if "root" not in adb_exec(args.device, ["shell", "id"]):
print("require root privalege on adb")
exit(1)
print(f"Pushing {args.image} to device / ...")
adb_exec(args.device, ["push", args.image, "/"])
print(f"Flasing {args.image} on device...")
write_once(args.device, args.image)
print("Cleaning device...")
adb_exec(args.device, ["shell", f"rm -rf /{args.image}"])
print("Rebooting device...")
adb_exec(args.device, ["shell", "reboot"])
# adb_push(args.device, args.image)
# write_once(args.device, args.image)
# adb_reboot(args.device)
if __name__ == "__main__":
main()