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 about 3 years ago · 11 revisions