android restart reason機制

whatnamecaniuse發表於2014-11-18


http://blog.csdn.net/linux_devices_driver/article/details/17928663



Reboot傳遞引數,使得開機進入引數固定的模式(通常有我們熟悉的bootloaderrecovery等),本質是在kernel shutdown時會呼叫到restart

將模式數值寫到share memory中,那麼在開機bootloader階段,再去讀取這塊記憶體,boot進入指定的模式,要是匹配不起來就正常boot,以下是貼出的程式碼;

restart 2種方式:

a: android_reboot(ANDROID_RB_RESTART2, 0, "rtcalarm");//進入rtc alarm模式

b: adb reboot bootloader,adb reboot recovery;        //進入我們熟悉的bootloader和recorevy模式



Restar.c:

void *restart_reason;
/*函式將被賦值給machine restart指標*/
void msm_restart(char mode, const char *cmd)
{
#ifdef CONFIG_MSM_DLOAD_MODE
    /* This looks like a normal reboot at this point. */
    set_dload_mode(0);

    /* Write download mode flags if we're panic'ing */
    set_dload_mode(in_panic);

    /* Write download mode flags if restart_mode says so */
    if (restart_mode == RESTART_DLOAD) 
    {
        set_dload_mode(1);
#ifdef CONFIG_LGE_CRASH_HANDLER
        writel(0x6d63c421, restart_reason);
        goto reset;
#endif
    }
    /* Kill download mode if master-kill switch is set */
    if (!download_mode)
        set_dload_mode(0);
#endif

    printk(KERN_NOTICE "Going down for restart now\n");

    pm8xxx_reset_pwr_off(1);

    if (cmd != NULL) 
    {
        if (!strncmp(cmd, "bootloader", 10)) 
        {
            __raw_writel(0x77665500, restart_reason);
        }
        else if (!strncmp(cmd, "recovery", 8)) 
        {
            __raw_writel(0x77665502, restart_reason);
        } 
        else if (!strncmp(cmd, "oem-", 4)) 
        {
            unsigned long code;
            code = simple_strtoul(cmd + 4, NULL, 16) & 0xff;
            __raw_writel(0x6f656d00 | code, restart_reason);
        } 
        else 
        {
            __raw_writel(0x77665501, restart_reason);
        }
    } 
    else 
    {
        __raw_writel(0x77665501, restart_reason);
    }
#ifdef CONFIG_LGE_CRASH_HANDLER
    if (in_panic == 1)
        set_kernel_crash_magic_number();
reset:
#endif /* CONFIG_LGE_CRASH_HANDLER */

    __raw_writel(0, msm_tmr0_base + WDT0_EN);
    if (!(machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())) 
    {
        mb();
        __raw_writel(0, PSHOLD_CTL_SU); /* Actually reset the chip */
        mdelay(5000);
        pr_notice("PS_HOLD didn't work, falling back to watchdog\n");
    }
    
    __raw_writel(1, msm_tmr0_base + WDT0_RST);
    __raw_writel(5*0x31F3, msm_tmr0_base + WDT0_BARK_TIME);
    __raw_writel(0x31F3, msm_tmr0_base + WDT0_BITE_TIME);
    __raw_writel(1, msm_tmr0_base + WDT0_EN);

    mdelay(10000);
    printk(KERN_ERR "Restarting has failed\n");
}


static int __init msm_restart_init(void)
{
#ifdef CONFIG_MSM_DLOAD_MODE
    atomic_notifier_chain_register(&panic_notifier_list, &panic_blk);
    dload_mode_addr = MSM_IMEM_BASE + DLOAD_MODE_ADDR;
#ifdef CONFIG_LGE_CRASH_HANDLER
    lge_error_handler_cookie_addr = MSM_IMEM_BASE + LGE_ERROR_HANDLER_MAGIC_ADDR;
#endif
    set_dload_mode(download_mode);
#endif
    msm_tmr0_base = msm_timer_get_timer0_base();
    restart_reason = MSM_IMEM_BASE + RESTART_REASON_ADDR;// restart_reason被賦值記憶體地址
    pm_power_off = msm_power_off;

    return 0;
}





lk:init.c

/*lk裡面讀出kernel寫入的restart數值*/
unsigned check_reboot_mode(void)
{
    unsigned restart_reason = 0;
    void *restart_reason_addr = (void *)0x2A05F65C;

    /* Read reboot reason and scrub it */
    restart_reason = readl(restart_reason_addr);
    writel(0x00, restart_reason_addr);

    return restart_reason;
}

#define RECOVERY_MODE   0x77665502
#define FASTBOOT_MODE   0x77665500
#define ADB_REBOOT_MODE 0x77665501

    /*check reboot mode*/
    reboot_mode = check_reboot_mode();
 #if CONFIG_CHARING_WHILE_MECHINE_TRUN_OFF
    {
        extern unsigned int custom_power_on_charger(void);
        if(custom_power_on_charger() 
           && reboot_mode 
           && (reboot_mode!=FASTBOOT_MODE)
           &&(reboot_mode != ADB_REBOOT_MODE))
        {
            boot_into_recovery=1;
        }
        dprintf(0, 
                "[charger] %s() custom_power_on_charger()=%x check_reboot_mode()=%0x\n", 
                __func__, 
                custom_power_on_charger(), 
                reboot_mode);
    }
 #endif
 
    if (reboot_mode == RECOVERY_MODE) 
    {
        boot_into_recovery = 1;
    } 
    else if(reboot_mode == FASTBOOT_MODE) 
    {
        goto fastboot;
    }


 那麼熟悉這套機制,我們就可以新增自己的模式了,比如鬧鐘模式,工廠模式等等;


相關文章