I9250Bootloader¶
- Table of contents
- I9250Bootloader
Accessing the bootloader console¶
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:
====== VCELL : 409625, SOC : 100, nType : 4 ====== [Charger] nScaledVCELL : 409625000, nDesriedSOC, : 98, nMaxSOC : 118, nMinSOC : 78 * FB base addr = 0xbea70000! * PANEL_S6E8AA0_ID_READ : 0x12, 0x8e, 0x9b. [ omap_power_get_reset_source :47] PRM_RSTST : 0x2 Autoboot (1 seconds) in progress, press any key to stop . Autoboot aborted.. SBL> SBL> SBL> SBL> help Following commands are supported: * setenv * saveenv * printenv * help * reset * boot * kernel * loadpart * loadkernel * erasepart * omap_upload_rdx * omap_test_button * omap_test_hwinfo * omap_set_gpio_level * omap_get_gpio_level * omap_test_twl6030 * omap_test_power * omap_reboot * omap_halt * omap_cmdline_power * omap_test_kbd * omap_test_usbacc * usb * omap_test_max17043 * omap_test_fsa9480 * omap_dump_sec_log_buf * omap_test_sud To get commands help, Type "help <command>" SBL>
Available commands¶
Here's the known list of commands:
SBL> help Following commands are supported: * setenv * saveenv * printenv * help * reset * boot * kernel * loadpart * loadkernel * erasepart * omap_upload_rdx * omap_test_button * omap_test_hwinfo * omap_set_gpio_level * omap_get_gpio_level * omap_test_twl6030 * omap_test_power * omap_reboot * omap_halt * omap_cmdline_power * omap_test_kbd * omap_test_usbacc * usb * omap_test_max17043 * omap_test_fsa9480 * omap_dump_sec_log_buf * omap_test_sud To get commands help, Type "help <command>" SBL>
And their respective help:
SBL> help setenv
* Help : setenv
* Usage : setenv [name] [value] . .
Modify current environment info on ram
SBL> help saveenv
* Help : saveenv
* Usage : saveenv
Save cuurent environment info to flash
SBL> help printenv
* Help : printenv
* Usage : printenv
Print current environment info on ram
SBL> help help
* Help : help
* Usage : help [command]
SBL> help reset
* Help : reset
* Usage : reboot
Reboot system
SBL> help boot
* Help : boot
* Usage : boot [kernel options]
Boot Linux with optional kernel options
SBL> help kernel
* Help : kernel
* Usage : kernel hex_adr
Change the Linux kernel base
SBL> help loadpart
* Help : loadpart
* Usage : load partition from storage device.
SBL> help loadkernel
* Help : loadkernel
* Usage : load kernel from storage device.
SBL> help erasepart
* Help : erasepart
* Usage : erase partition.
SBL> help omap_upload_rdx
* Help : omap_upload_rdx
* Usage : [OMAP] upload RDX
omap_upload_rdx
SBL> help omap_test_button
* Help : omap_test_button
* Usage : [OMAP] test OMAP buttons
omap_test_button
SBL> help omap_test_hwinfo
* Help : omap_test_hwinfo
* Usage : [OMAP] test OMAP HW Information
omap_test_hwinfo
SBL> help omap_set_gpio_level
* Help : omap_set_gpio_level
* Usage : [OMAP] set GPIO level
omap_set_gpio_level {GPIO} {VALUE}
SBL> help omap_get_gpio_level
* Help : omap_get_gpio_level
* Usage : [OMAP] get GPIO level
omap_get_gpio_level {GPIO}
SBL> help omap_test_twl6030
* Help : omap_test_twl6030
* Usage : [OMAP] test twl6030 device
omap_test_twl6030
SBL> help omap_test_power
* Help : omap_test_power
* Usage : [OMAP] test power function
omap_test_power
SBL> help omap_reboot
* Help : omap_reboot
* Usage : [OMAP] system reboot command
omap_reboot
SBL> help omap_halt
* Help : omap_halt
* Usage : [OMAP] system halt command
omap_halt
SBL> help omap_cmdline_power
* Help : omap_cmdline_power
* Usage : [OMAP] check kernel-cmdline by power
omap_cmdline_power
SBL> help omap_test_kbd
* Help : omap_test_kbd
* Usage : [OMAP] test power function
omap_test_kbd
SBL> help omap_test_usbacc
* Help : omap_test_usbacc
* Usage : [OMAP] test OMAP usb-accessary
omap_test_usbacc
SBL> help usb
* Help : usb
* Usage : usb download command
SBL> help omap_test_max17043
* Help : omap_test_max17043
* Usage : [OMAP] test max17043 device
omap_test_max17043
SBL> help omap_test_fsa9480
* Help : omap_test_fsa9480
* Usage : [OMAP] test fsa9480 device
omap_test_fsa9480
SBL> help omap_dump_sec_log_buf
* Help : omap_dump_sec_log_buf
* Usage : [OMAP] dump sec-log-buf
omap_dump_sec_log_buf
SBL> help omap_test_sud
* Help : omap_test_sud
* Usage : [OMAP] test SUD image
omap_test_sud {NUMBER}
SBL>
Changing the kernel commandline arguments¶
I've tried to modify the CMDLINE:
SBL> setenv CMDLINE loglevel=8 console=ttyFIQ0 androidboot.console=ttyFIQ0 argv[0] : setenv argv[1] : CMDLINE argv[2] : loglevel=8 console=ttyFIQ0 androidboot.console=ttyFIQ0 value : 656175548 SBL> saveenv save_param start block=49152, no.blocks=16384
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.
Other commands¶
SBL> omap_test_hwinfo ----------------------------------------------------------- OMAP-Samsung HW Information Board Name : tuna REV 9 Board Rev : HSPA - 9 Boot Type : USB MMC1 Device Type : HS Build Date : Jan 24 2012 18:27:20 -----------------------------------------------------------
SBL> printenv PARAM Rev 1.6 SERIAL_SPEED : 7 LOAD_RAMDISK : 0 BOOT_DELAY : 1 LCD_LEVEL : 6 SWITCH_SEL : 3 PHONE_DEBUG_ON : 0 LCD_DIM_LEVEL : 0 LCD_DIM_TIME : 6 MELODY_MODE : 1 REBOOT_MODE : 0 NATION_SEL : 0 LANGUAGE_SEL : 0 SET_DEFAULT_PARAM : 0 OFF_MODE_CHARGE : 1 FLASH_LOCK_STATUS : 0 VERSION : CMDLINE : DELTA_LOCATION : /mnt/rsv WIFI_MAC_LINE : PARAM_STR_4 : DCM
Reboot interface¶
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.
In arch/arm/mach-omap2/board-tuna.c in the Replicant 6.0 kernel_samsung_tuna, there is the following code:
#define REBOOT_FLAG_RECOVERY 0x52564352
#define REBOOT_FLAG_FASTBOOT 0x54534146
#define REBOOT_FLAG_NORMAL 0x4D524F4E
#define REBOOT_FLAG_POWER_OFF 0x46464F50
[...]
static int tuna_notifier_call(struct notifier_block *this,
unsigned long code, void *_cmd)
{
void __iomem *sar_base;
unsigned int flag = REBOOT_FLAG_NORMAL;
sar_base = omap4_get_sar_ram_base();
if (!sar_base)
return notifier_from_errno(-ENOMEM);
if (code == SYS_RESTART) {
if (_cmd) {
if (!strcmp(_cmd, "recovery"))
flag = REBOOT_FLAG_RECOVERY;
else if (!strcmp(_cmd, "bootloader"))
flag = REBOOT_FLAG_FASTBOOT;
}
} else if (code == SYS_POWER_OFF) {
flag = REBOOT_FLAG_POWER_OFF;
}
/* The Samsung LOKE bootloader will look for the boot flag at a fixed
* offset from the end of the 1st SAR bank.
*/
writel(flag, sar_base + SAR_BANK2_OFFSET - 0xC);
return NOTIFY_DONE;
}
If we look at the defines, we can see a pattern:
| #define | value | ASCII | ASCII with opposite endianess |
| REBOOT_FLAG_RECOVERY | 0x52564352 | RVCR | RCVR |
| REBOOT_FLAG_FASTBOOT | 0x54534146 | TSAF | FAST |
| REBOOT_FLAG_NORMAL | 0x4D524F4E | MRON | NORM |
| REBOOT_FLAG_POWER_OFF | 0x46464F50 | FFOP | POFF |
So if we patch the kernel with the following patch, we are able to test various flags values:
diff --git a/arch/arm/mach-omap2/board-tuna.c b/arch/arm/mach-omap2/board-tuna.c
index 43aaf6f38e76..7da64734df84 100755
--- a/arch/arm/mach-omap2/board-tuna.c
+++ b/arch/arm/mach-omap2/board-tuna.c
@@ -1128,6 +1128,15 @@ static int tuna_notifier_call(struct notifier_block *this,
flag = REBOOT_FLAG_RECOVERY;
else if (!strcmp(_cmd, "bootloader"))
flag = REBOOT_FLAG_FASTBOOT;
+ else if (strlen(_cmd) == 4) {
+ int i;
+ char* cmd = _cmd;
+ flag = (cmd[0] << 24) | (cmd[1] << 16) | (cmd[2] << 8) | (cmd[3]);
+
+ for (i=1000; i>0; i--) {
+ printk(KERN_INFO "%s: #%d reboot [%s] => 0x%x", __func__, i, cmd, flag);
+ }
+ }
}
} else if (code == SYS_POWER_OFF) {
flag = REBOOT_FLAG_POWER_OFF;
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.
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:
#!/usr/bin/env python3
#
# Copyright (C) 2022 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import re
from sh import adb
import string
import sys
# From sysexits.h
EX_USAGE = 64 # command line usage error
class Log(object):
def __init__(self):
self.log_path = re.sub("\.py$", "", sys.argv[0]) + ".log"
self.file = open(self.log_path, 'a')
def print(self, string):
print(string)
self.file.write(string + os.linesep)
def close(self):
self.file.close()
def usage(progname):
print("Usage: {} bruteforce [start]".format(progname))
print("Example: {} bruteforce BAAA".format(progname))
sys.exit(EX_USAGE)
def is_uppercase(s):
for c in s:
if c not in string.ascii_uppercase[:26]:
return False
return True
def bruteforce(start='AAAA'):
start0 = string.ascii_uppercase[:26].index(start[0])
start1 = string.ascii_uppercase[:26].index(start[1])
start2 = string.ascii_uppercase[:26].index(start[2])
start3 = string.ascii_uppercase[:26].index(start[3])
log = Log()
for l1 in string.ascii_uppercase[start0:26]:
for l2 in string.ascii_uppercase[start1:26]:
for l3 in string.ascii_uppercase[start2:26]:
for l4 in string.ascii_uppercase[start3:26]:
reboot_cmd = "{}{}{}{}".format(l1, l2, l3, l4)
adb("wait-for-recovery")
log.print("reboot {}".format(reboot_cmd))
adb("reboot", reboot_cmd)
log.close()
def dictionary():
strings = [
'BOOT',
'DUDD',
'EDUQ',
'FAST',
'FGIQ',
'GTHP',
'GTPY',
'HALT',
'HFHO',
'HSPA',
'IWFR',
'JFIF',
'KKXA',
'LAST',
'LOKE',
'MDED',
'MYIB',
'NAND',
'NDED',
'NORM',
'NQST',
'NRZM',
'ODIN',
'OKAY',
'POFF',
'PXQE',
'QAAE',
'QUMC',
'RCVR',
'RMFO',
'RSET',
'SNBL',
'STAR',
'XMWQ',
]
log = Log()
for entry in strings:
reboot_cmd = entry[3] + entry[2] + entry[1] + entry[0]
adb("wait-for-recovery")
log.print("reboot {}".format(reboot_cmd))
adb("reboot", reboot_cmd)
log.close()
if len(sys.argv) == 2 and sys.argv[1] == "bruteforce":
bruteforce()
elif len(sys.argv) == 3 and sys.argv[1] == "bruteforce":
if len(sys.argv[2]) == 4 and is_uppercase(sys.argv[2]):
start = sys.argv[1]
bruteforce(start)
else:
usage(sys.argv[0])
if len(sys.argv) == 2 and sys.argv[1] == "dictionary":
dictionary()
elif len(sys.argv) != 1:
usage(sys.argv[0])
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.
The fact that the bootloader is signed and that the second stage (SBL) is not free software prevents us from fixing that issue.
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.
Updated by Denis 'GNUtoo' Carikli almost 4 years ago · 11 revisions