Project

General

Profile

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.