I9250Bootloader » History » Version 11
Denis 'GNUtoo' Carikli, 01/11/2022 08:30 AM
Add research about the reboot interface of the bootloader
1 | 1 | Denis 'GNUtoo' Carikli | h1. I9250Bootloader |
---|---|---|---|
2 | |||
3 | 10 | Denis 'GNUtoo' Carikli | {{toc}} |
4 | |||
5 | h2. Accessing the bootloader console |
||
6 | |||
7 | 8 | Denis 'GNUtoo' Carikli | When connected on the serial port, during boot, if you press the volume down button and press enter on the serial console, you can get a shell: |
8 | 1 | Denis 'GNUtoo' Carikli | <pre> |
9 | 2 | Denis 'GNUtoo' Carikli | ====== VCELL : 409625, SOC : 100, nType : 4 ====== |
10 | 1 | Denis 'GNUtoo' Carikli | [Charger] nScaledVCELL : 409625000, nDesriedSOC, : 98, nMaxSOC : 118, nMinSOC : 78 |
11 | * FB base addr = 0xbea70000! |
||
12 | * PANEL_S6E8AA0_ID_READ : 0x12, 0x8e, 0x9b. |
||
13 | [ omap_power_get_reset_source :47] PRM_RSTST : 0x2 |
||
14 | |||
15 | Autoboot (1 seconds) in progress, press any key to stop . |
||
16 | |||
17 | Autoboot aborted.. |
||
18 | SBL> |
||
19 | SBL> |
||
20 | SBL> |
||
21 | SBL> help |
||
22 | Following commands are supported: |
||
23 | * setenv |
||
24 | * saveenv |
||
25 | * printenv |
||
26 | * help |
||
27 | * reset |
||
28 | * boot |
||
29 | * kernel |
||
30 | * loadpart |
||
31 | * loadkernel |
||
32 | * erasepart |
||
33 | * omap_upload_rdx |
||
34 | * omap_test_button |
||
35 | * omap_test_hwinfo |
||
36 | * omap_set_gpio_level |
||
37 | * omap_get_gpio_level |
||
38 | * omap_test_twl6030 |
||
39 | * omap_test_power |
||
40 | * omap_reboot |
||
41 | * omap_halt |
||
42 | * omap_cmdline_power |
||
43 | * omap_test_kbd |
||
44 | * omap_test_usbacc |
||
45 | * usb |
||
46 | * omap_test_max17043 |
||
47 | * omap_test_fsa9480 |
||
48 | * omap_dump_sec_log_buf |
||
49 | * omap_test_sud |
||
50 | To get commands help, Type "help <command>" |
||
51 | SBL> |
||
52 | |||
53 | 2 | Denis 'GNUtoo' Carikli | </pre> |
54 | |||
55 | 10 | Denis 'GNUtoo' Carikli | h2. Available commands |
56 | |||
57 | Here's the known list of commands: |
||
58 | 2 | Denis 'GNUtoo' Carikli | <pre> |
59 | 10 | Denis 'GNUtoo' Carikli | SBL> help |
60 | Following commands are supported: |
||
61 | * setenv |
||
62 | * saveenv |
||
63 | * printenv |
||
64 | * help |
||
65 | * reset |
||
66 | * boot |
||
67 | * kernel |
||
68 | * loadpart |
||
69 | * loadkernel |
||
70 | * erasepart |
||
71 | * omap_upload_rdx |
||
72 | * omap_test_button |
||
73 | * omap_test_hwinfo |
||
74 | * omap_set_gpio_level |
||
75 | * omap_get_gpio_level |
||
76 | * omap_test_twl6030 |
||
77 | * omap_test_power |
||
78 | * omap_reboot |
||
79 | * omap_halt |
||
80 | * omap_cmdline_power |
||
81 | * omap_test_kbd |
||
82 | * omap_test_usbacc |
||
83 | * usb |
||
84 | * omap_test_max17043 |
||
85 | * omap_test_fsa9480 |
||
86 | * omap_dump_sec_log_buf |
||
87 | * omap_test_sud |
||
88 | To get commands help, Type "help <command>" |
||
89 | SBL> |
||
90 | </pre> |
||
91 | |||
92 | And their respective help: |
||
93 | <pre> |
||
94 | 2 | Denis 'GNUtoo' Carikli | SBL> help setenv |
95 | * Help : setenv |
||
96 | * Usage : setenv [name] [value] . . |
||
97 | Modify current environment info on ram |
||
98 | |||
99 | SBL> help saveenv |
||
100 | * Help : saveenv |
||
101 | * Usage : saveenv |
||
102 | Save cuurent environment info to flash |
||
103 | |||
104 | SBL> help printenv |
||
105 | * Help : printenv |
||
106 | * Usage : printenv |
||
107 | Print current environment info on ram |
||
108 | |||
109 | SBL> help help |
||
110 | * Help : help |
||
111 | * Usage : help [command] |
||
112 | SBL> help reset |
||
113 | * Help : reset |
||
114 | * Usage : reboot |
||
115 | Reboot system |
||
116 | |||
117 | SBL> help boot |
||
118 | * Help : boot |
||
119 | * Usage : boot [kernel options] |
||
120 | Boot Linux with optional kernel options |
||
121 | |||
122 | SBL> help kernel |
||
123 | * Help : kernel |
||
124 | * Usage : kernel hex_adr |
||
125 | Change the Linux kernel base |
||
126 | |||
127 | SBL> help loadpart |
||
128 | * Help : loadpart |
||
129 | * Usage : load partition from storage device. |
||
130 | SBL> help loadkernel |
||
131 | * Help : loadkernel |
||
132 | * Usage : load kernel from storage device. |
||
133 | SBL> help erasepart |
||
134 | * Help : erasepart |
||
135 | * Usage : erase partition. |
||
136 | SBL> help omap_upload_rdx |
||
137 | * Help : omap_upload_rdx |
||
138 | * Usage : [OMAP] upload RDX |
||
139 | omap_upload_rdx |
||
140 | SBL> help omap_test_button |
||
141 | * Help : omap_test_button |
||
142 | * Usage : [OMAP] test OMAP buttons |
||
143 | omap_test_button |
||
144 | SBL> help omap_test_hwinfo |
||
145 | * Help : omap_test_hwinfo |
||
146 | * Usage : [OMAP] test OMAP HW Information |
||
147 | omap_test_hwinfo |
||
148 | SBL> help omap_set_gpio_level |
||
149 | * Help : omap_set_gpio_level |
||
150 | * Usage : [OMAP] set GPIO level |
||
151 | omap_set_gpio_level {GPIO} {VALUE} |
||
152 | SBL> help omap_get_gpio_level |
||
153 | * Help : omap_get_gpio_level |
||
154 | * Usage : [OMAP] get GPIO level |
||
155 | omap_get_gpio_level {GPIO} |
||
156 | SBL> help omap_test_twl6030 |
||
157 | * Help : omap_test_twl6030 |
||
158 | * Usage : [OMAP] test twl6030 device |
||
159 | omap_test_twl6030 |
||
160 | SBL> help omap_test_power |
||
161 | * Help : omap_test_power |
||
162 | * Usage : [OMAP] test power function |
||
163 | omap_test_power |
||
164 | SBL> help omap_reboot |
||
165 | * Help : omap_reboot |
||
166 | * Usage : [OMAP] system reboot command |
||
167 | omap_reboot |
||
168 | SBL> help omap_halt |
||
169 | * Help : omap_halt |
||
170 | * Usage : [OMAP] system halt command |
||
171 | omap_halt |
||
172 | SBL> help omap_cmdline_power |
||
173 | * Help : omap_cmdline_power |
||
174 | * Usage : [OMAP] check kernel-cmdline by power |
||
175 | omap_cmdline_power |
||
176 | SBL> help omap_test_kbd |
||
177 | * Help : omap_test_kbd |
||
178 | * Usage : [OMAP] test power function |
||
179 | omap_test_kbd |
||
180 | 1 | Denis 'GNUtoo' Carikli | SBL> help omap_test_usbacc |
181 | 3 | Denis 'GNUtoo' Carikli | * Help : omap_test_usbacc |
182 | 1 | Denis 'GNUtoo' Carikli | * Usage : [OMAP] test OMAP usb-accessary |
183 | 3 | Denis 'GNUtoo' Carikli | omap_test_usbacc |
184 | SBL> help usb |
||
185 | * Help : usb |
||
186 | * Usage : usb download command |
||
187 | SBL> help omap_test_max17043 |
||
188 | * Help : omap_test_max17043 |
||
189 | * Usage : [OMAP] test max17043 device |
||
190 | omap_test_max17043 |
||
191 | SBL> help omap_test_fsa9480 |
||
192 | * Help : omap_test_fsa9480 |
||
193 | * Usage : [OMAP] test fsa9480 device |
||
194 | omap_test_fsa9480 |
||
195 | SBL> help omap_dump_sec_log_buf |
||
196 | 1 | Denis 'GNUtoo' Carikli | * Help : omap_dump_sec_log_buf |
197 | * Usage : [OMAP] dump sec-log-buf |
||
198 | 3 | Denis 'GNUtoo' Carikli | omap_dump_sec_log_buf |
199 | SBL> help omap_test_sud |
||
200 | * Help : omap_test_sud |
||
201 | * Usage : [OMAP] test SUD image |
||
202 | omap_test_sud {NUMBER} |
||
203 | SBL> |
||
204 | </pre> |
||
205 | |||
206 | 10 | Denis 'GNUtoo' Carikli | h2. Changing the kernel commandline arguments |
207 | 3 | Denis 'GNUtoo' Carikli | |
208 | I've tried to modify the CMDLINE: |
||
209 | 1 | Denis 'GNUtoo' Carikli | <pre> |
210 | SBL> setenv CMDLINE loglevel=8 console=ttyFIQ0 androidboot.console=ttyFIQ0 |
||
211 | argv[0] : setenv |
||
212 | argv[1] : CMDLINE |
||
213 | argv[2] : loglevel=8 console=ttyFIQ0 androidboot.console=ttyFIQ0 |
||
214 | value : 656175548 |
||
215 | SBL> saveenv |
||
216 | save_param start block=49152, no.blocks=16384 |
||
217 | </pre> |
||
218 | But once booted, "loglevel=8" wasn't found in /proc/cmdline on Replicant 6.0 0003 so it doesn't seem to have an impact. Though, on this bootloader, the commandline can also be modified by modifying the boot.img commandline parameters. |
||
219 | |||
220 | 10 | Denis 'GNUtoo' Carikli | h2. Other commands |
221 | |||
222 | 1 | Denis 'GNUtoo' Carikli | <pre> |
223 | SBL> omap_test_hwinfo |
||
224 | ----------------------------------------------------------- |
||
225 | OMAP-Samsung HW Information |
||
226 | |||
227 | Board Name : tuna REV 9 |
||
228 | Board Rev : HSPA - 9 |
||
229 | Boot Type : USB MMC1 |
||
230 | Device Type : HS |
||
231 | Build Date : Jan 24 2012 18:27:20 |
||
232 | ----------------------------------------------------------- |
||
233 | 10 | Denis 'GNUtoo' Carikli | </pre> |
234 | |||
235 | <pre> |
||
236 | SBL> printenv |
||
237 | PARAM Rev 1.6 |
||
238 | SERIAL_SPEED : 7 |
||
239 | LOAD_RAMDISK : 0 |
||
240 | BOOT_DELAY : 1 |
||
241 | LCD_LEVEL : 6 |
||
242 | SWITCH_SEL : 3 |
||
243 | PHONE_DEBUG_ON : 0 |
||
244 | LCD_DIM_LEVEL : 0 |
||
245 | LCD_DIM_TIME : 6 |
||
246 | MELODY_MODE : 1 |
||
247 | REBOOT_MODE : 0 |
||
248 | NATION_SEL : 0 |
||
249 | LANGUAGE_SEL : 0 |
||
250 | SET_DEFAULT_PARAM : 0 |
||
251 | OFF_MODE_CHARGE : 1 |
||
252 | FLASH_LOCK_STATUS : 0 |
||
253 | VERSION : |
||
254 | CMDLINE : |
||
255 | DELTA_LOCATION : /mnt/rsv |
||
256 | WIFI_MAC_LINE : |
||
257 | PARAM_STR_4 : DCM |
||
258 | 5 | Denis 'GNUtoo' Carikli | </pre> |
259 | 11 | Denis 'GNUtoo' Carikli | |
260 | h2. Reboot interface |
||
261 | |||
262 | The installation instructions use Heimdall to install the Replicant recovery on the Galaxy Nexus (GT-I9250) in order to have unified installation instructions, so it would be great to be able to reboot to the bootloader mode that is compatible with heimdall with a command (like @reboot download@ or @adb reboot download@), especially to be able to run automatic installation tests, but that doesn't look possible. The following explains why. |
||
263 | |||
264 | In arch/arm/mach-omap2/board-tuna.c in the Replicant 6.0 kernel_samsung_tuna, there is the following code: |
||
265 | <pre> |
||
266 | #define REBOOT_FLAG_RECOVERY 0x52564352 |
||
267 | #define REBOOT_FLAG_FASTBOOT 0x54534146 |
||
268 | #define REBOOT_FLAG_NORMAL 0x4D524F4E |
||
269 | #define REBOOT_FLAG_POWER_OFF 0x46464F50 |
||
270 | [...] |
||
271 | static int tuna_notifier_call(struct notifier_block *this, |
||
272 | unsigned long code, void *_cmd) |
||
273 | { |
||
274 | void __iomem *sar_base; |
||
275 | unsigned int flag = REBOOT_FLAG_NORMAL; |
||
276 | |||
277 | sar_base = omap4_get_sar_ram_base(); |
||
278 | |||
279 | if (!sar_base) |
||
280 | return notifier_from_errno(-ENOMEM); |
||
281 | |||
282 | if (code == SYS_RESTART) { |
||
283 | if (_cmd) { |
||
284 | if (!strcmp(_cmd, "recovery")) |
||
285 | flag = REBOOT_FLAG_RECOVERY; |
||
286 | else if (!strcmp(_cmd, "bootloader")) |
||
287 | flag = REBOOT_FLAG_FASTBOOT; |
||
288 | } |
||
289 | } else if (code == SYS_POWER_OFF) { |
||
290 | flag = REBOOT_FLAG_POWER_OFF; |
||
291 | } |
||
292 | |||
293 | /* The Samsung LOKE bootloader will look for the boot flag at a fixed |
||
294 | * offset from the end of the 1st SAR bank. |
||
295 | */ |
||
296 | writel(flag, sar_base + SAR_BANK2_OFFSET - 0xC); |
||
297 | |||
298 | return NOTIFY_DONE; |
||
299 | } |
||
300 | </pre> |
||
301 | |||
302 | If we look at the defines, we can see a pattern: |
||
303 | | #define | value | ASCII | ASCII with opposite endianess | |
||
304 | | REBOOT_FLAG_RECOVERY | 0x52564352 | RVCR | RCVR | |
||
305 | | REBOOT_FLAG_FASTBOOT | 0x54534146 | TSAF | FAST | |
||
306 | | REBOOT_FLAG_NORMAL | 0x4D524F4E | MRON | NORM | |
||
307 | | REBOOT_FLAG_POWER_OFF | 0x46464F50 | FFOP | POFF | |
||
308 | |||
309 | So if we patch the kernel with the following patch, we are able to test various flags values: |
||
310 | <pre> |
||
311 | diff --git a/arch/arm/mach-omap2/board-tuna.c b/arch/arm/mach-omap2/board-tuna.c |
||
312 | index 43aaf6f38e76..7da64734df84 100755 |
||
313 | --- a/arch/arm/mach-omap2/board-tuna.c |
||
314 | +++ b/arch/arm/mach-omap2/board-tuna.c |
||
315 | @@ -1128,6 +1128,15 @@ static int tuna_notifier_call(struct notifier_block *this, |
||
316 | flag = REBOOT_FLAG_RECOVERY; |
||
317 | else if (!strcmp(_cmd, "bootloader")) |
||
318 | flag = REBOOT_FLAG_FASTBOOT; |
||
319 | + else if (strlen(_cmd) == 4) { |
||
320 | + int i; |
||
321 | + char* cmd = _cmd; |
||
322 | + flag = (cmd[0] << 24) | (cmd[1] << 16) | (cmd[2] << 8) | (cmd[3]); |
||
323 | + |
||
324 | + for (i=1000; i>0; i--) { |
||
325 | + printk(KERN_INFO "%s: #%d reboot [%s] => 0x%x", __func__, i, cmd, flag); |
||
326 | + } |
||
327 | + } |
||
328 | } |
||
329 | } else if (code == SYS_POWER_OFF) { |
||
330 | flag = REBOOT_FLAG_POWER_OFF; |
||
331 | |||
332 | </pre> |
||
333 | |||
334 | With the patch above, @adb reboot TSAF@ will make the device reboot to the fastboot mode and @adb reboot FFOP@ will power off the device. |
||
335 | |||
336 | Since FAST and POFF are strings inside the bootloader that is in the SBL partition, I coded a python script to test all the 4 letter uppercase strings found inside that partition: |
||
337 | <pre> |
||
338 | #!/usr/bin/env python3 |
||
339 | # |
||
340 | # Copyright (C) 2022 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org> |
||
341 | # |
||
342 | # This program is free software: you can redistribute it and/or modify |
||
343 | # it under the terms of the GNU General Public License as published by |
||
344 | # the Free Software Foundation, either version 3 of the License, or |
||
345 | # (at your option) any later version. |
||
346 | # |
||
347 | # This program is distributed in the hope that it will be useful, |
||
348 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
349 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
350 | # GNU General Public License for more details. |
||
351 | # |
||
352 | # You should have received a copy of the GNU General Public License |
||
353 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
354 | |||
355 | import os |
||
356 | import re |
||
357 | from sh import adb |
||
358 | import string |
||
359 | import sys |
||
360 | |||
361 | # From sysexits.h |
||
362 | EX_USAGE = 64 # command line usage error |
||
363 | |||
364 | class Log(object): |
||
365 | def __init__(self): |
||
366 | self.log_path = re.sub("\.py$", "", sys.argv[0]) + ".log" |
||
367 | self.file = open(self.log_path, 'a') |
||
368 | |||
369 | def print(self, string): |
||
370 | print(string) |
||
371 | self.file.write(string + os.linesep) |
||
372 | |||
373 | def close(self): |
||
374 | self.file.close() |
||
375 | |||
376 | def usage(progname): |
||
377 | print("Usage: {} bruteforce [start]".format(progname)) |
||
378 | print("Example: {} bruteforce BAAA".format(progname)) |
||
379 | sys.exit(EX_USAGE) |
||
380 | |||
381 | def is_uppercase(s): |
||
382 | for c in s: |
||
383 | if c not in string.ascii_uppercase[:26]: |
||
384 | return False |
||
385 | return True |
||
386 | |||
387 | def bruteforce(start='AAAA'): |
||
388 | start0 = string.ascii_uppercase[:26].index(start[0]) |
||
389 | start1 = string.ascii_uppercase[:26].index(start[1]) |
||
390 | start2 = string.ascii_uppercase[:26].index(start[2]) |
||
391 | start3 = string.ascii_uppercase[:26].index(start[3]) |
||
392 | |||
393 | log = Log() |
||
394 | |||
395 | for l1 in string.ascii_uppercase[start0:26]: |
||
396 | for l2 in string.ascii_uppercase[start1:26]: |
||
397 | for l3 in string.ascii_uppercase[start2:26]: |
||
398 | for l4 in string.ascii_uppercase[start3:26]: |
||
399 | reboot_cmd = "{}{}{}{}".format(l1, l2, l3, l4) |
||
400 | adb("wait-for-recovery") |
||
401 | log.print("reboot {}".format(reboot_cmd)) |
||
402 | adb("reboot", reboot_cmd) |
||
403 | log.close() |
||
404 | |||
405 | def dictionary(): |
||
406 | strings = [ |
||
407 | 'BOOT', |
||
408 | 'DUDD', |
||
409 | 'EDUQ', |
||
410 | 'FAST', |
||
411 | 'FGIQ', |
||
412 | 'GTHP', |
||
413 | 'GTPY', |
||
414 | 'HALT', |
||
415 | 'HFHO', |
||
416 | 'HSPA', |
||
417 | 'IWFR', |
||
418 | 'JFIF', |
||
419 | 'KKXA', |
||
420 | 'LAST', |
||
421 | 'LOKE', |
||
422 | 'MDED', |
||
423 | 'MYIB', |
||
424 | 'NAND', |
||
425 | 'NDED', |
||
426 | 'NORM', |
||
427 | 'NQST', |
||
428 | 'NRZM', |
||
429 | 'ODIN', |
||
430 | 'OKAY', |
||
431 | 'POFF', |
||
432 | 'PXQE', |
||
433 | 'QAAE', |
||
434 | 'QUMC', |
||
435 | 'RCVR', |
||
436 | 'RMFO', |
||
437 | 'RSET', |
||
438 | 'SNBL', |
||
439 | 'STAR', |
||
440 | 'XMWQ', |
||
441 | ] |
||
442 | |||
443 | log = Log() |
||
444 | for entry in strings: |
||
445 | reboot_cmd = entry[3] + entry[2] + entry[1] + entry[0] |
||
446 | adb("wait-for-recovery") |
||
447 | log.print("reboot {}".format(reboot_cmd)) |
||
448 | adb("reboot", reboot_cmd) |
||
449 | log.close() |
||
450 | |||
451 | if len(sys.argv) == 2 and sys.argv[1] == "bruteforce": |
||
452 | bruteforce() |
||
453 | elif len(sys.argv) == 3 and sys.argv[1] == "bruteforce": |
||
454 | if len(sys.argv[2]) == 4 and is_uppercase(sys.argv[2]): |
||
455 | start = sys.argv[1] |
||
456 | bruteforce(start) |
||
457 | else: |
||
458 | usage(sys.argv[0]) |
||
459 | if len(sys.argv) == 2 and sys.argv[1] == "dictionary": |
||
460 | dictionary() |
||
461 | elif len(sys.argv) != 1: |
||
462 | usage(sys.argv[0]) |
||
463 | </pre> |
||
464 | |||
465 | But it didn't find a way to boot to the heimdall compatible mode, so we now either need to implement fastboot in the tests or to test the Galaxy Nexus manually (which is more time consuming and way more error prone). Because of that limitation, we would not be able to have the installation instructions tested automatically. |
||
466 | |||
467 | The fact that the bootloader is signed and that the second stage (SBL) is not free software prevents us from fixing that issue. |
||
468 | |||
469 | It might still be possible to replace the second stage with u-boot though, but it would require to redistribute a signed bootloader that is under free a software license but practically nonfree as users can't run modified versions. |