Adding OpenWrt support for Xiaomi "Redmi Router AX6S"/"Xiaomi Router AX3200"

UBoot 2021

  setenv("bootargs", "$");
  if ( boot_fw_num )
  {
    setenv("flag_boot_rootfs", "1");
    sprintf(boot_cmd, "%s", "run boot_fw1");
  }
  else
  {
    setenv("flag_boot_rootfs", "0");
    sprintf(boot_cmd, "%s", "run boot_fw0");
  }
  save_env();
  printf("Booting System %d\n", boot_fw_num);
  sub_41E03BAC((int)boot_cmd);

UBoot 2022

  set_nvram_param("bootargs", cmdline);
  if ( boot_part_num )
  {
    set_nvram_param("flag_boot_rootfs", "1");
    sprintf((int)bootm_cmd, "%s", "run boot_fw1");
    sprintf((int)try_value, "%d", __try_sys2 + 1);
    try_name = "flag_try_sys2_failed";
  }
  else
  {
    set_nvram_param("flag_boot_rootfs", "0");
    sprintf((int)bootm_cmd, "%s", "run boot_fw0");
    sprintf((int)try_value, "%d", _try_sys1 + 1);
    try_name = "flag_try_sys1_failed";
  }
  set_nvram_param(try_name, try_value);
  saveenv();
  log("Booting System %d\n", boot_part_num);
  bootm(bootm_cmd, 0);

On new Xiaomi bootloaders, the flag_try_sysX_failed counter increases with each reboot. The stock firmware resets the flag_try_sysX_failed counter to 0 after a successful boot.

It probably makes sense to do the same in OpenWRT firmware.
Example of a similar task: https://github.com/openwrt/openwrt/blob/ced3fbcda18e200315cb077f7e2b362ae52ee065/target/linux/ramips/mt76x8/base-files/etc/init.d/bootcount#L11-L14

Official installation manual: https://openwrt.org/toh/xiaomi/ax3200

For the 2022 bootloader, this option is incorrect!

For a new bootloader you should do this:

nvram set boot_fw1="run boot_rd_img;bootm"
nvram set flag_try_sys1_failed=8
nvram set flag_try_sys2_failed=8
nvram set flag_boot_rootfs=0
nvram set flag_boot_success=1
nvram set flag_last_success=1
nvram commit

Example: https://github.com/openwrt/openwrt/commit/18bea173a646518a64ca05ea26f87eab0540feb9#diff-0a263858df577cc26996da59d6407fd35d3e8744454266ca76109ac7c6c29618R34-R37

Uboot 2021
  _try_sys = flag_try_sys2_failed > 1;
  if ( flag_try_sys2_failed <= 1 )
    _try_sys = flag_try_sys1_failed > 1;
  if ( _try_sys )
    boot_fw_num = 1;
  else
    boot_fw_num = 0;
  if ( _try_sys )
  {
    boot_fw_num = 0;
  }
Uboot 2022
  flag_ota_reboot_is_2 = flag_ota_reboot > 1;
  if ( flag_ota_reboot <= 1 )
    flag_ota_reboot_is_2 = flag_last_success > 1;
  if ( flag_ota_reboot_is_2 )
  {
    boot_part_num = 0;
  }
  else
  {
    try_sys_is_OK = try_sys2 == 0;
    if ( try_sys2 )
      try_sys_is_OK = try_sys1 == 0;
    if ( !try_sys_is_OK )
      log("Boot failure detected on both systems\n");
    if ( flag_ota_reboot )
    {
      ...
    }
    else
    {
      if ( flag_last_success )
        _try_sys = try_sys2 > 5;
      else
        _try_sys = try_sys1 > 5;
      if ( _try_sys )
        boot_part_num = 1 - flag_last_success;
      else
        boot_part_num = flag_last_success;
    }
  }
Stock firmware after boot: /etc/init.d/boot_check
START=99

RCSTATFILE='/tmp/rc.timing'
BOOTCHECKCODEFILE='/tmp/rc.done'

set_setup_flag(){
	local flg=0
	local flag_boot_rootfs=$(nvram get flag_boot_rootfs)
	local flag_ota_root=$(nvram get flag_ota_reboot)
	local flag_boot_success=$(nvram get flag_boot_success)
	local flag_try_sys1_failed=$(nvram get flag_try_sys1_failed)
	local flag_try_sys2_failed=$(nvram get flag_try_sys2_failed)
	local flag_last_success=$(nvram get flag_last_success)
	
	[ "$flag_ota_root" != "0" ] && {
		flg=1
		nvram set flag_ota_reboot=0
	}
	[ "$flag_boot_success" != "1" ] && {
		flg=1
		nvram set flag_boot_success=1
	}
	[ "$flag_try_sys1_failed" != "0" ] && {
		flg=1
		nvram set flag_try_sys1_failed=0
	}
	[ "$flag_try_sys2_failed" != "0" ] && {
		flg=1
		nvram set flag_try_sys2_failed=0
	}

	[ "$flag_boot_rootfs" = "0" -o "$flag_boot_rootfs" = "1" ] && [ "$flag_boot_rootfs" != "$flag_last_success" ] && {
		flg=1
		nvram set flag_last_success=$flag_boot_rootfs
	}

	[ "$flg" = "1" ] && nvram commit
}

start() {
	...
	# set bootup flag
	set_setup_flag

	...

	# boot finished	
	xqled sys_ok
	echo "BOOTCHECKCODE=0;" > $BOOTCHECKCODEFILE	
	echo "boot_done" > /tmp/boot_check_done
	elog "Booting up finished."
}
  
1 Like