forked from openwrt-xiaomi/xmir-patcher
-
Notifications
You must be signed in to change notification settings - Fork 0
/
activate_boot.py
243 lines (207 loc) · 6.71 KB
/
activate_boot.py
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import sys
import xmir_base
import gateway
from gateway import die
import read_info
from envbuffer import EnvBuffer
def breed_boot_change(gw, dev, fw_num, fw_addr, fw_name):
if dev is None:
dev = read_info.DevInfo(verbose = 0, infolevel = 1)
if fw_num is not None:
pname = 'kernel%d' % fw_num
p = dev.get_part_num(pname)
if p < 0:
die('Partition "{}" not found!)'.format(pname))
fw_addr = dev.partlist[p]['addr']
if not fw_addr:
if len(fw_name) < 4:
die('Incorrect boot partition name! (len: {})'.format(len(fw_name)))
p = dev.get_part_num(fw_name)
if p <= 0:
die('Partition "{}" not found!)'.format(fw_name))
fw_addr = dev.partlist[p]['addr']
#dev.verbose = 2
if dev.env.breed.data is None:
dev.get_env_list()
env = dev.env.breed
if env.data is None or env.max_size is None:
die("Can't found breed env address!")
env.var['autoboot.command'] = "boot flash 0x%X" % fw_addr
cmdline = 'uart_en=1'
if 'linux.cmdline' in env.var:
cmdline = env.var['linux.cmdline']
if 'uart_en=' in cmdline:
cmdline = cmdline.replace('uart_en=0', 'uart_en=1')
else:
cmdline += ' uart_en=1'
env.var['linux.cmdline'] = cmdline
print("Breed ENV params for update:")
for i, (k, v) in enumerate(env.var.items()):
v = '' if (v is None) else ('=' + v)
print(" " + k + v)
bufsize = env.max_size
buf = env.pack(bufsize)
buf = b'ENV\x00' + buf[4:]
#print("env =", buf[:128])
data = env.data[0:env.offset] + buf + env.data[(env.offset + len(buf)):]
fn_local = 'tmp/env_breed.bin'
fn_remote = '/tmp/env_breed.bin'
with open(fn_local, "wb") as file:
file.write(data)
gw.upload(fn_local, fn_remote)
pe = dev.get_part_num(env.addr, '#')
if pe < 0:
die('Partition for writing ENV {} not found!'.format("0x%08X" % env.addr))
part_addr = dev.partlist[pe]['addr']
part_name = dev.partlist[pe]['name']
cmd = 'mtd write {bin} "{part}"'.format(bin=fn_remote, part=part_name)
print("Send command: {}".format(cmd))
gw.run_cmd(cmd)
print('Breed ENV changed! Boot from {} activated.'.format("0x%08X" % fw_addr))
gw.run_cmd("rm -f " + fn_remote)
return fw_addr
def uboot_boot_change(gw, fw_num):
if fw_num != 0 and fw_num != 1:
die("Boot partition number not correct! Must be 0 or 1!")
cmd = []
cmd.append("nvram set flag_ota_reboot=0")
cmd.append("nvram set flag_boot_success=1")
cmd.append("nvram set flag_last_success={}".format(fw_num))
cmd.append("nvram set flag_try_sys1_failed=0")
cmd.append("nvram set flag_try_sys2_failed=0")
cmd.append("nvram set flag_boot_rootfs={}".format(fw_num))
cmd.append("nvram commit")
gw.run_cmd(cmd)
return True
if __name__ == "__main__":
gw = gateway.Gateway()
dev = read_info.DevInfo(verbose = 0, infolevel = 1)
dev.get_bootloader()
if not dev.bl.img:
die("Can't dump current bootloader!")
for i, part in enumerate(dev.partlist):
print(' %2d > addr: 0x%08X size: 0x%08X name: "%s"' % (i, part['addr'], part['size'], part['name']))
if len(sys.argv) > 1:
fw_name = sys.argv[1]
else:
if dev.bl.type == 'breed':
print("The device has an Breed bootloader installed.")
print("It is possible to specify a specific kernel boot address (HEX-number).")
print("It is also possible to specify the kernel number or the name of its partition.")
fw_name = input("Enter kernel (number, address or name): ")
else:
fw_name = input("Enter kernel number (0 or 1): ")
fw_name = fw_name.strip()
if fw_name == "":
die("Boot partition not specified!")
fw_num = None
fw_addr = None
if len(fw_name) >= 6 and fw_name.lower().startswith('0x'):
fw_addr = int(fw_name, 16)
else:
try:
fw_num = int(fw_name)
if fw_num != 0 and fw_num != 1:
die("Boot partition number not correct! Must be 0 or 1!")
except Exception:
pass
#if dev.bl.type == 'pandora':
# die('Pandora bootloader not supported!')
if dev.bl.type == 'breed':
fw_addr = breed_boot_change(gw, dev, fw_num, fw_addr, fw_name)
if fw_name != '0' and fw_name != '1':
sys.exit(0)
fw_addr = None
fw_num = None
try:
fw_num = int(fw_name)
except Exception:
pass
if fw_addr:
die('Required Breed bootloader for set custom boot address!')
if fw_num is None:
die("Boot partition not specified!")
print("Run scripts for change NVRAM params...")
uboot_boot_change(gw, fw_num)
print('Ready! Boot from partition "kernel{}" activated.'.format(fw_num))
'''
/*** Algorithm from stock uboot: ***/
#define OK 0
if ( flag_try_sys1_failed > 1 || flag_try_sys2_failed > 1 || flag_ota_reboot > 1 || flag_last_success > 1 )
goto boot_rootfs0;
if ( flag_try_sys1_failed == 1 && flag_try_sys2_failed == 1 )
{
if ( verifying_kernel0() == OK )
goto boot_rootfs0;
if ( verifying_kernel1() == OK )
goto boot_rootfs1;
}
if ( flag_ota_reboot == 1 )
{
flag_last_success = 1 - flag_last_success;
}
else
{
if ( flag_last_success == 0 )
flag_try_sys2_failed = flag_try_sys1_failed;
if ( flag_try_sys2_failed == 1 )
flag_last_success = 1 - flag_last_success;
}
if ( flag_last_success == 0 )
goto boot_rootfs0;
else
goto boot_rootfs1;
boot_rootfs1:
img_addr = 0x600000 // kernel1
flag_boot_rootfs = 1;
goto boot;
boot_rootfs0:
img_addr = 0x200000 // kernel0
flag_boot_rootfs = 0;
goto boot;
boot:
setenv("flag_boot_rootfs", flag_boot_rootfs);
factory_mode = 0;
crash_log_magic = 0;
ranand_read(&crash_log_magic, 0x140000, 4);
if ( crash_log_magic == 0x5AA5 )
{
factory_mode = 1;
printf("System is in factory mode.\n");
setenv("uart_en", "1");
setenv("boot_wait", "on");
}
saveenv();
ranand_read(img_header, img_addr, 64);
img_header_magic = ntohl(*(uint32_t *)img_header)
if ( img_header_magic != 0x27051956 )
{
printf("Bad Magic Number,%08X, try to reboot\n", img_header_magic);
goto bad_data;
}
if ( getenv("verify") != 'n' ) {
if ( verify_image(img_addr) != OK )
printf("Bad Data CRC\n");
goto bad_data;
}
}
do_bootm_linux(...)
bad_data:
if ( flag_boot_rootfs == 0 )
setenv("flag_try_sys1_failed", "1");
else
setenv("flag_try_sys2_failed", "1");
setenv("flag_ota_reboot", "0");
saveenv();
if ( factory_mode )
{
printf("System is in factory mode. U-Boot BOOT ERROR! \n");
nullsub_4();
while ( 1 ) // HARD CPU RESTART
;
}
return CRITICAL_ERROR
'''