Samsung_S7/documentation/source/BootROM_8890/05_mib3_bootchain.rst
Jonathan Herrewijnen da14253312 Cleaning up code
2024-12-10 19:47:56 +01:00

167 lines
7.1 KiB
ReStructuredText

MIB3 boot chain
---------------
Normal boot flow log. If I am correct here, the boot flow from recovery and when going into uboot is not as different. The only slight difference is, that low-level, the SMC handler seems to know what boot path it is taking. The main boot function, at ``0xcf000028`` eventually goes into a function at ``0xcf05e218``. One of the first things this function does, is getting information from an address space at ``0xcf4dfb28`` (32 bytes long) using a function at ``0xcf05e5d0``. The values here are set somewhere during the boot process from U-Boot, as the contents before booting U-boot are empty (FFFF space). The only value not taken from BL33 space, is one taken from ``0x0206f800``. Some other information is also retrieved from ``0x136d0184`` using a function at ``0xcf053f60``. What is annoying here, is that these spaces in lower memory range, are only readable after booting the recovery mode once. Currently, after doing one failed boot, the MIB3 returns to the debugger (we set the LR, and it just returns). We can then again try to boot 'normally', but this always fails. (interestingly, the logs then fail on secure payload)
.. code:: bash
Recovery mode
[ERROR] Fail to load LDFW
=> Return value : -1
LDFX init status=> Return value : -1
[ERROR] Fail to load Secure payload
=> Return value : -.
Function that determines boot path (Recovery or otherwise). The function at ``is_not_first_boot_option_Q`` returns a boolean, which can be altered. The MIB3 then goes into a GPT not found panic.
.. code:: bash
void recovery_mode_Q_smc_0xFA(void) {
undefined8 uVar1;
int iVar2;
uint uVar3;
int iVar4;
hw_info_boot_path *phVar5;
undefined4 uStack_4000c;
long lStack_40008;
undefined4 uStack_40000;
undefined4 uStack_3fffc;
uint uStack_3ffd4;
uint uStack_3ffd0;
uStack_4000c = 0;
lStack_40008 = 0;
phVar5 = get_hw_info_boot_path_Q();
_DAT_14cc0000 = 0x220000;
DAT_14c30000 = 3;
DAT_14c30004 = 0x3c5;
DAT_14c30008 = 0x117;
DAT_14c30028 = 0x46;
DAT_14c3002c = 9;
_DAT_14cc0100 = 0x220000;
DAT_14c10000 = 3;
DAT_14c10004 = 0x3c5;
DAT_14c10008 = 0x117;
DAT_14c10028 = 0x46;
DAT_14c1002c = 9;
DAT_0206f870 = 0x101;
/* bl, 0xcf053fa8 */
iVar2 = is_not_first_boot_option_Q();
/* we see this on uart when doing usb recovery
cbz, w0,0xcf05e330 */
if (iVar2 != 0) {
uart_print_retval_Q(s_Recovery_mode_cf08aa4b,0);
uStack_40000 = load_LDFW_Q(phVar5->ldfw_part_id);
uart_print_retval_Q(s_LDFW_init_status_cf08aa59,&uStack_40000);
load_secure_payload_Q(phVar5->sec_os_part_id);
uart_print_retval_Q(s_Secure_OS_loaded_cf08aa6a,0);
_DAT_d9000100 = 0;
goto LAB_cf05e304;
}
uVar3 = get_MIB3_MMX_version_B1_B2();
if (uVar3 < 6) {
uVar3 = _DAT_10580004 & 8;
LAB_cf05e34c:
if (uVar3 == 0) goto LAB_cf05e304;
}
else if (uVar3 == 6) {
uVar3 = _DAT_10580024 & 1;
goto LAB_cf05e34c;
}
lStack_40008 = do_smc(0xffffffffffffff06,0,0,0);
if (lStack_40008 != 0) {
uart_print_retval_Q(s_[ERROR]_Fail_to_load_GPT_cf08aa7b,&lStack_40008);
do {
/* WARNING: Do nothing block with infinite loop */
} while( true );
}
FUN_cf05dd00(0x5200);
if (((DAT_105c0404 & 0x11800000) == 0) || (_DAT_d9000100 != 0xd)) {
uVar3 = 0;
}
else {
uVar3 = 1;
_DAT_d9000100 = 0;
}
load_LDFW_Q(phVar5->ldfw_part_id);
iVar2 = custom_otp_read_warranty_Q();
load_secure_payload_Q(phVar5->sec_os_part_id);
do_smc_0xFB_MIBCERT_Q(&uStack_40000);
if (((CONCAT44(uStack_3fffc,uStack_40000) == 0x5452454342494d) &&
(iVar4 = do_smc_0x101d(0,&uStack_40000,0x40000), iVar4 == 0)) &&
(iVar4 = FUN_cf05e098(&uStack_40000), iVar4 != 0)) {
iVar4 = do_smc_0xFB();
if (((uint)(iVar4 == 1) & uStack_3ffd0 >> 0x1d & 1 & uVar3) != 0) {
uart_print_retval_Q(s_Ramdump_mode_detected,_certifica_cf08aa96,0);
goto LAB_cf05e304;
}
if ((iVar2 == 0) && ((uStack_3ffd4 & 0x60000000) != 0)) {
FUN_cf05e1e4();
}
}
else {
iVar4 = 0;
uStack_3ffd4 = 0;
uStack_3ffd0 = 0;
}
do_smc_0xFB(phVar5->hyp_part_id,&hypervisor,s_[ERROR]_Fail_to_load_Hypervisor_cf08aabf);
FUN_cf05dd00(0x5500);
if (hypervisor != 'M') {
return;
}
if (DAT_80200001 != 'Z') {
return;
}
do_smc_0xFB(phVar5->dtb_part_id,&dtb,s_[ERROR]_Fail_to_load_DTB_cf08aae1);
FUN_cf05dd00(0x5600);
uVar3 = uStack_3ffd4 & 0x80;
if ((uStack_3ffd4 >> 2 & 1) == 0) {
do_smc_0xFC_fail_hang(&hypervisor,phVar5->hyp_part_id,0);
}
if (uVar3 == 0) {
do_smc_0xFC_fail_hang(&dtb,phVar5->dtb_part_id,1);
}
lStack_40008 = do_smc(0xfffffffffffff8ff,0,0,0);
if (lStack_40008 == 0) {
uart_print_retval_Q(s_[ERROR]_Fail_to_disable_CP_cf08aafc,&lStack_40008);
do {
/* WARNING: Do nothing block with infinite loop */
} while( true );
}
/* This is printed on regular bootflow, not on recovery? */
uart_print_retval_Q(s_S8_cf08ab19,&uStack_4000c);
FUN_cf05dd00(0x5c00);
watchdog_Q = watchdog_Q & 0xffffffde;
FUN_cf05dd00(0);
uVar1 = 0xdead;
if (iVar4 == 0) {
uVar1 = 0;
}
_DAT_d9000100 = 0xd;
jump_to_hypervisor_Q
(phVar5->kerneldom0_part_id,phVar5->dtb_domu1_part_id,phVar5->kerneldomou1_part_id,
phVar5->field5_0x14,phVar5->field8_0x20,phVar5->emmc0_ufs1,
CONCAT44(uStack_3ffd0,uStack_3ffd4),uVar1);
LAB_cf05e304:
watchdog_Q = watchdog_Q & 0xffffffde;
return;
}
Another option is to manually continue the bootflow by jumping into the function at ``0xcf05dd00``, but this then prints the following, but does not continue the boot flow. Retrospecitvely, I did not explicitly check the link register (which is very likely important here..). But, the normal boot does not print the information below.
.. code:: bash
U-Boot 2012.07-gc7c41ec14-dirty (Oct 23 2019 - 12:53:04) for SADK8890
CPU: Exynos8890 Rev2.0 [Samsung SOC on SMP Platform Base on ARM CortexA53]
MNGS_PLL = 1975MHz APOLLO_PLL = 1481MHz MIF_PLL = 1539MHz
BUS0_PLL = 1056MHz BUS1_PLL = 800MHz BUS2_PLL = 672MHz BUS3_PLL = 1872MHz
MFC_PLL = 71MHz AUD_PLL = 494MHz G3D_PLL = 650MHz DISP_PLL = 63MHz
Board: SADK8890
DRAM: 6 GiB
ECT: PARA006o