blob: be9495dc66d6d2e1a5eee8ce95ad864b03c5a1a4 [file] [log] [blame]
/*
* Copyright (c) 2018 MediaTek Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <arch/ops.h>
#include <boot_args.h>
#include <env.h>
#include <lib/kcmdline.h>
#include <libfdt.h>
#include <malloc.h>
#include <mrdump.h>
#include <platform.h>
#include <platform/mtk_wdt.h>
#include <platform/platform_blx.h>
#include <printf.h>
#include <ram_console.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "aee.h"
#include "kdump.h"
extern BOOT_ARGUMENT *g_boot_arg;
extern int kedump_restore_mem(void);
#define MRDUMP_RSV_MEM "mrdump_rsvmem=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x"
#define MRDUMP_CB_RSV_MEM "mrdump_cb=0x%x,0x%x"
#define RAM_CONSOLE_RSV_MEM "ram_console_rsvmem=0x%x,0x%x"
#define MINIDUMP_RSV_MEM "minirdump_rsvmem=0x%x,0x%x"
#define PSTORE_RSV_MEM "pstore_rsvmem=0x%x,0x%x,0x%x,0x%x"
unsigned int get_reboot_reason(unsigned int boot_reason)
{
unsigned int rc_wdt_status;
unsigned int rc_exp_type;
unsigned int ret = 0;
if (boot_reason == BR_WDT_BY_PASS_PWK) {
if (ram_console_get_wdt_status(&rc_wdt_status) && ram_console_get_exp_type(&rc_exp_type)){
dprintf(CRITICAL, "rc_wdt_status = %d, rc_exp_type = %d\n", rc_wdt_status, rc_exp_type);
switch (rc_exp_type) {
case 0:
if (rc_wdt_status == 5)
ret = REBOOT_REASON_WATCHDOG;
break;
case AEE_EXP_TYPE_HWT:
ret = REBOOT_REASON_WATCHDOG;
break;
case AEE_EXP_TYPE_DM_VERITY_CORRUPTION:
ret = REBOOT_REASON_DM_VERITY_CORRUPTION;
break;
case AEE_EXP_TYPE_KE:
case AEE_EXP_TYPE_NESTED_PANIC:
ret = REBOOT_REASON_KERNEL_PANIC;
break;
default:
break;
}
}
}
else if (boot_reason == BR_2SEC_REBOOT) {
ret = REBOOT_REASON_2S_REBOOT;
} else {
ret = REBOOT_REASON_REBOOT;
}
return ret;
}
static void mrdump_ddr_reserved_mode_control(void)
{
if (g_boot_arg->ddr_reserve_ready != AEE_MRDUMP_DDR_RSV_READY) {
kcmdline_append("mrdump_ddrsv=no");
dprintf(CRITICAL, "MT-RAMDUMP: DDR reserve mode not ready, skipped (0x%x)\n",
g_boot_arg->ddr_reserve_ready);
} else
kcmdline_append("mrdump_ddrsv=yes");
}
void mrdump_setup_boot_reason(void)
{
unsigned int boot_reason = 0;
unsigned int reboot_reason = 0;
char tmpbuf[128];
unsigned int len_bootreason=0;
const char aee_reboot_reason[][20] = {"reboot", "watchdog", "kernel_panic", "oemerr_2sec_reboot","dmveri_corruption"};
boot_reason = platform_boot_status();
reboot_reason=get_reboot_reason(boot_reason);
len_bootreason = strlen(" androidboot.bootreason=") + strlen(aee_reboot_reason[reboot_reason]);
snprintf(tmpbuf,len_bootreason,"%s%s", "androidboot.bootreason=",aee_reboot_reason[reboot_reason]);
dprintf(CRITICAL, "tmpbuf %s\n", tmpbuf);
kcmdline_append(tmpbuf);
}
void mrdump_append_cmdline(void)
{
mrdump_ddr_reserved_mode_control();
/* mrdump control block reserve memory*/
#ifdef MTK_MRDUMP_SRAM_CB
aee_reserve_memory(MRDUMP_CB_RSV_MEM, MRDUMP_CB_ADDR, MRDUMP_CB_SIZE);
#endif
/* mrdump reserve memory*/
aee_reserve_memory(MRDUMP_RSV_MEM, MEMBASE, AEE_MRDUMP_LK_RSV_SIZE,
DRAM_BOOTARG_BASE, DRAM_BOOTARG_SIZE, DRAM_ARENA_BASE,
DRAM_ARENA_SIZE, kvaddr_to_paddr((void *)UNCACHED_MEMPOOL_ADDR),
UNCACHED_MEMPOOL_SIZE, kvaddr_to_paddr((void *)CACHED_MEMPOOL_ADDR),
CACHED_MEMPOOL_SIZE);
/* ram_console reserve memory*/
#if RAM_CONSOLE_DRAM_ADDR
aee_reserve_memory(RAM_CONSOLE_RSV_MEM, RAM_CONSOLE_DEF_ADDR,
RAM_CONSOLE_DEF_SIZE);
#endif
/* minidump reserve memory*/
#if MINIRDUMP_MEM_ADDR
aee_reserve_memory(MINIDUMP_RSV_MEM, MINIRDUMP_MEM_ADDR,
MINIRDUMP_MEM_SIZE);
#endif
/* pstore reserve memory*/
#if PSTORE_RESERVE_ADDR
aee_reserve_memory(PSTORE_RSV_MEM, PSTORE_RESERVE_ADDR, PSTORE_RESERVE_SIZE,
PSTORE_CONSOEL_SIZE, PSTORE_PMSG_SIZE);
#endif
mrdump_setup_version();
mrdump_setup_boot_reason();
}
static int kedump_get_bootreason(unsigned int wdt_status)
{
unsigned int g_rgu_status = 0;
if (wdt_status & MTK_WDT_STATUS_HWWDT_RST) {
/* For E1 bug, that SW reset value is 0xC000, we using "==" to check */
/* Time out reboot always by pass power key */
g_rgu_status = RE_BOOT_BY_WDT_HW;
} else if (wdt_status & MTK_WDT_STATUS_SWWDT_RST) {
g_rgu_status = RE_BOOT_BY_WDT_SW;
} else {
g_rgu_status = RE_BOOT_REASON_UNKNOW;
}
if (wdt_status & MTK_WDT_STATUS_IRQWDT_RST) {
g_rgu_status |= RE_BOOT_WITH_INTTERUPT;
}
#ifdef MTK_THERMAL_RESET_SUPPORT
if (wdt_status & MTK_WDT_STATUS_SPM_THERMAL_RST) {
g_rgu_status |= RE_BOOT_BY_SPM_THERMAL;
}
#endif
if (wdt_status & MTK_WDT_STATUS_SPMWDT_RST) {
g_rgu_status |= RE_BOOT_BY_SPM;
}
if (wdt_status & MTK_WDT_STATUS_THERMAL_CTL_RST) {
g_rgu_status |= RE_BOOT_BY_THERMAL_DIRECT;
}
if (wdt_status & MTK_WDT_STATUS_DEBUGWDT_RST) {
g_rgu_status |= RE_BOOT_BY_DEBUG;
}
if (wdt_status & MTK_WDT_STATUS_SECURITY_RST) {
g_rgu_status |= RE_BOOT_BY_SECURITY;
}
#ifdef MTK_PMIC_FULL_RESET
if (mtk_wdt_is_pmic_full_reset())
g_rgu_status |= RE_BOOT_BY_PMIC_FULL_RST;
#endif
return g_rgu_status;
}
int kedump_init(void)
{
static int kedump_dumped = 0;
unsigned int boot_reason = kedump_get_bootreason(g_boot_arg->boot_reason);
pl_ram_console_init();
ram_console_reboot_reason_save(boot_reason);
ram_console_init();
/* this flow should be executed once only */
if (kedump_dumped == 0) {
kedump_dumped = 1;
if (ram_console_is_abnormal_boot())
return -1;
}
// for power lost or reboot before KE DB collected scenario
kedump_restore_mem();
return 0;
}