rockchip: boot-mode: fix lost boot-mode from register

PH and PL is from boot mode register, reading once.
PM is from misc.img and should be updated if BCB offset is changed.
Return the boot mode according to priority: PH > PM > PL.

Fixes:
(3aaa96e8af rockchip: boot-mode: reinitialize static variable "boot_mode")

Signed-off-by: Joseph Chen <chenjh@rock-chips.com>
Change-Id: Ibd577dd8ebfb0d4c36ac8b90e176d3b1103f347e
This commit is contained in:
Joseph Chen 2020-11-19 17:12:31 +08:00 committed by Jianhong Chen
parent 22edf95882
commit ea8b124a0e
1 changed files with 62 additions and 42 deletions

View File

@ -29,6 +29,13 @@ DECLARE_GLOBAL_DATA_PTR;
* - "reboot recovery" command; * - "reboot recovery" command;
* - recovery key pressed without usb attach; * - recovery key pressed without usb attach;
*/ */
enum {
PH = 0, /* P: Priority, H: high, M: middle, L: low*/
PM,
PL,
};
int rockchip_get_boot_mode(void) int rockchip_get_boot_mode(void)
{ {
struct bootloader_message *bmsg = NULL; struct bootloader_message *bmsg = NULL;
@ -36,8 +43,9 @@ int rockchip_get_boot_mode(void)
disk_partition_t part_info; disk_partition_t part_info;
uint32_t reg_boot_mode; uint32_t reg_boot_mode;
char *env_reboot_mode; char *env_reboot_mode;
static int boot_mode = -1; /* static */ static int boot_mode[] = /* static */
static int bcb_offset = -1; /* static */ { -EINVAL, -EINVAL, -EINVAL };
static int bcb_offset = -EINVAL; /* static */
int clear_boot_reg = 0; int clear_boot_reg = 0;
int ret, cnt; int ret, cnt;
#ifdef CONFIG_ANDROID_BOOT_IMAGE #ifdef CONFIG_ANDROID_BOOT_IMAGE
@ -45,6 +53,29 @@ int rockchip_get_boot_mode(void)
#else #else
u32 offset = BCB_MESSAGE_BLK_OFFSET; u32 offset = BCB_MESSAGE_BLK_OFFSET;
#endif #endif
/*
* Here, we mainly check for:
* In rockusb_download(), that recovery key is pressed without
* USB attach will do env_set("reboot_mode", "recovery");
*/
env_reboot_mode = env_get("reboot_mode");
if (env_reboot_mode) {
if (!strcmp(env_reboot_mode, "recovery-key")) {
printf("boot mode: recovery (key)\n");
return BOOT_MODE_RECOVERY;
} else if (!strcmp(env_reboot_mode, "recovery-usb")) {
printf("boot mode: recovery (usb)\n");
return BOOT_MODE_RECOVERY;
} else if (!strcmp(env_reboot_mode, "recovery")) {
printf("boot mode: recovery (env)\n");
return BOOT_MODE_RECOVERY;
} else if (!strcmp(env_reboot_mode, "fastboot")) {
printf("boot mode: fastboot\n");
return BOOT_MODE_BOOTLOADER;
}
}
/* /*
* Special handle: * Special handle:
* Once the BCB offset changes, reinitalize "boot_mode". * Once the BCB offset changes, reinitalize "boot_mode".
@ -61,36 +92,23 @@ int rockchip_get_boot_mode(void)
* set as BOOT_MODE_RECOVERY according to BCB at 0x20 offset. * set as BOOT_MODE_RECOVERY according to BCB at 0x20 offset.
* After that, this function always return static variable "boot_mode" * After that, this function always return static variable "boot_mode"
* as BOOT_MODE_RECOVERY even android(>=10) boot flow enter here. * as BOOT_MODE_RECOVERY even android(>=10) boot flow enter here.
*
* PH and PL is from boot mode register, reading once.
* PM is from misc.img and should be updated if BCB offset is changed.
* Return the boot mode according to priority: PH > PM > PL.
*/ */
if (bcb_offset != offset) { if (bcb_offset != offset) {
boot_mode = -1; boot_mode[PM] = -EINVAL;
bcb_offset = offset; bcb_offset = offset;
} }
/* /* directly return if there is already valid mode */
* Here, we mainly check for: if (boot_mode[PH] != -EINVAL)
* In rockusb_download(), that recovery key is pressed without return boot_mode[PH];
* USB attach will do env_set("reboot_mode", "recovery"); else if (boot_mode[PM] != -EINVAL)
*/ return boot_mode[PM];
env_reboot_mode = env_get("reboot_mode"); else if (boot_mode[PL] != -EINVAL)
if (env_reboot_mode) { return boot_mode[PL];
if (!strcmp(env_reboot_mode, "recovery-key")) {
boot_mode = BOOT_MODE_RECOVERY;
printf("boot mode: recovery (key)\n");
} else if (!strcmp(env_reboot_mode, "recovery-usb")) {
boot_mode = BOOT_MODE_RECOVERY;
printf("boot mode: recovery (usb)\n");
} else if (!strcmp(env_reboot_mode, "recovery")) {
boot_mode = BOOT_MODE_RECOVERY;
printf("boot mode: recovery(env)\n");
} else if (!strcmp(env_reboot_mode, "fastboot")) {
boot_mode = BOOT_MODE_BOOTLOADER;
printf("boot mode: fastboot\n");
}
}
if (boot_mode != -1)
return boot_mode;
dev_desc = rockchip_get_bootdev(); dev_desc = rockchip_get_bootdev();
if (!dev_desc) { if (!dev_desc) {
@ -106,9 +124,7 @@ int rockchip_get_boot_mode(void)
cnt = DIV_ROUND_UP(sizeof(struct bootloader_message), dev_desc->blksz); cnt = DIV_ROUND_UP(sizeof(struct bootloader_message), dev_desc->blksz);
bmsg = memalign(ARCH_DMA_MINALIGN, cnt * dev_desc->blksz); bmsg = memalign(ARCH_DMA_MINALIGN, cnt * dev_desc->blksz);
ret = blk_dread(dev_desc, ret = blk_dread(dev_desc, part_info.start + bcb_offset, cnt, bmsg);
part_info.start + bcb_offset,
cnt, bmsg);
if (ret != cnt) { if (ret != cnt) {
free(bmsg); free(bmsg);
return -EIO; return -EIO;
@ -125,49 +141,48 @@ fallback:
reg_boot_mode = readl((void *)CONFIG_ROCKCHIP_BOOT_MODE_REG); reg_boot_mode = readl((void *)CONFIG_ROCKCHIP_BOOT_MODE_REG);
if (reg_boot_mode == BOOT_LOADER) { if (reg_boot_mode == BOOT_LOADER) {
printf("boot mode: loader\n"); printf("boot mode: loader\n");
boot_mode = BOOT_MODE_LOADER; boot_mode[PH] = BOOT_MODE_LOADER;
clear_boot_reg = 1; clear_boot_reg = 1;
} else if (reg_boot_mode == BOOT_FASTBOOT) { } else if (reg_boot_mode == BOOT_FASTBOOT) {
printf("boot mode: bootloader\n"); printf("boot mode: bootloader\n");
boot_mode = BOOT_MODE_BOOTLOADER; boot_mode[PH] = BOOT_MODE_BOOTLOADER;
clear_boot_reg = 1; clear_boot_reg = 1;
} else if (bmsg && !strcmp(bmsg->command, "boot-recovery")) { } else if (bmsg && !strcmp(bmsg->command, "boot-recovery")) {
printf("boot mode: recovery (misc)\n"); printf("boot mode: recovery (misc)\n");
boot_mode = BOOT_MODE_RECOVERY; boot_mode[PM] = BOOT_MODE_RECOVERY;
clear_boot_reg = 1;
} else { } else {
switch (reg_boot_mode) { switch (reg_boot_mode) {
case BOOT_NORMAL: case BOOT_NORMAL:
printf("boot mode: normal\n"); printf("boot mode: normal\n");
boot_mode = BOOT_MODE_NORMAL; boot_mode[PL] = BOOT_MODE_NORMAL;
clear_boot_reg = 1; clear_boot_reg = 1;
break; break;
case BOOT_RECOVERY: case BOOT_RECOVERY:
printf("boot mode: recovery (cmd)\n"); printf("boot mode: recovery (cmd)\n");
boot_mode = BOOT_MODE_RECOVERY; boot_mode[PL] = BOOT_MODE_RECOVERY;
clear_boot_reg = 1; clear_boot_reg = 1;
break; break;
case BOOT_UMS: case BOOT_UMS:
printf("boot mode: ums\n"); printf("boot mode: ums\n");
boot_mode = BOOT_MODE_UMS; boot_mode[PL] = BOOT_MODE_UMS;
clear_boot_reg = 1; clear_boot_reg = 1;
break; break;
case BOOT_CHARGING: case BOOT_CHARGING:
printf("boot mode: charging\n"); printf("boot mode: charging\n");
boot_mode = BOOT_MODE_CHARGING; boot_mode[PL] = BOOT_MODE_CHARGING;
clear_boot_reg = 1; clear_boot_reg = 1;
break; break;
case BOOT_PANIC: case BOOT_PANIC:
printf("boot mode: panic\n"); printf("boot mode: panic\n");
boot_mode = BOOT_MODE_PANIC; boot_mode[PL] = BOOT_MODE_PANIC;
break; break;
case BOOT_WATCHDOG: case BOOT_WATCHDOG:
printf("boot mode: watchdog\n"); printf("boot mode: watchdog\n");
boot_mode = BOOT_MODE_WATCHDOG; boot_mode[PL] = BOOT_MODE_WATCHDOG;
break; break;
default: default:
printf("boot mode: None\n"); printf("boot mode: None\n");
boot_mode = BOOT_MODE_UNDEFINE; boot_mode[PL] = BOOT_MODE_UNDEFINE;
} }
} }
@ -178,7 +193,12 @@ fallback:
if (clear_boot_reg) if (clear_boot_reg)
writel(BOOT_NORMAL, (void *)CONFIG_ROCKCHIP_BOOT_MODE_REG); writel(BOOT_NORMAL, (void *)CONFIG_ROCKCHIP_BOOT_MODE_REG);
return boot_mode; if (boot_mode[PH] != -EINVAL)
return boot_mode[PH];
else if (boot_mode[PM] != -EINVAL)
return boot_mode[PM];
else
return boot_mode[PL];
} }
int setup_boot_mode(void) int setup_boot_mode(void)