Android recovery 和reboot

设置模块中进行恢复出厂设置操作,recovery
Power.reboot("recovery");

reboot system  

  

case1: factory reset  

Settings/src/com/android/settings/MasterClear.java  

 sendBroadcast(new Intent("android.intent.action.MASTER_CLEAR"));  

->   frameworks/base/services/java/com/android/server/MasterClearReceiver.java       RecoverySystem.rebootWipeUserData(context);   ->   frameworks/base/core/java/android/os/RecoverySystem.java       bootCommand(context, "--wipe_data");       ->       PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);       pm.reboot("recovery");   ->   frameworks/base/services/java/com/android/server/PowerManagerService.java       public void reboot(String reason){           ShutdownThread.reboot(mContext, finalReason, false);       }   ->   frameworks/base/core/java/com/android/internal/app/ShutdownThread.java       rebootOrShutdown(){           Power.reboot(reason);       }   ->   frameworks/base/core/java/android/os/Power.java       rebootNative(reason);   ->   frameworks/base/core/jni/anroid_os_Power.cpp       __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, (char*) chars);   ->   kernel/kernel/sys.c       case LINUX_REBOOT_CMD_RESTART2:           kernel_restart(buffer);       ->       machine_restart(cmd);   ->   kernel/arch/arm/kernel/process.c       void arm_machine_restart(char mode, const char *cmd){           //set flag and reboot        } 



参数表示reboot的原因

然后会到JNI
static void android_os_Power_reboot(JNIEnv *env, jobject clazz, jstring reason)
{
    sync();
#ifdef HAVE_ANDROID_OS
    if (reason == NULL) {
        reboot(RB_AUTOBOOT);
    } else {
        const char *chars = env->GetStringUTFChars(reason, NULL);
        __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
                 LINUX_REBOOT_CMD_RESTART2, (char*) chars);
        env->ReleaseStringUTFChars(reason, chars);  // In case it fails.
    }
    jniThrowIOException(env, errno);
#endif
}


这里会调用到c库里面的函数

__reboot:
    .save   {r4, r7}
    stmfd   sp!, {r4, r7}
    ldr     r7, =__NR_reboot
    swi     #0
    ldmfd   sp!, {r4, r7}
    movs    r0, r0
    bxpl    lr
    b       __set_syscall_errno
    .fnend


c库实际上到最底下就是系统调用的封装了,
一般都是sys_reboot的实现了,
不过Qualcomm这里用了宏来定义的。

调用了系统调用,kernel里面实现,我们就到了kernel里面

SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
        void __user *, arg)



    switch (cmd) {
    case LINUX_REBOOT_CMD_RESTART:
        kernel_restart(NULL);
        break;

    case LINUX_REBOOT_CMD_CAD_ON:
        C_A_D = 1;
        break;

    case LINUX_REBOOT_CMD_CAD_OFF:
        C_A_D = 0;
        break;

    case LINUX_REBOOT_CMD_HALT:
        kernel_halt();
        unlock_kernel();
        do_exit(0);
        break;

    case LINUX_REBOOT_CMD_POWER_OFF:
        kernel_power_off();
        unlock_kernel();
        do_exit(0);
        break;

    case LINUX_REBOOT_CMD_RESTART2:
        if (strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1) < 0) {
            unlock_kernel();
            return -EFAULT;
        }
        buffer[sizeof(buffer) - 1] = '/0';

        kernel_restart(buffer);


走到kernel_restart
void kernel_restart(char *cmd)
{
    kernel_restart_prepare(cmd);
    if (!cmd)
        printk(KERN_EMERG "Restarting system./n");
    else
        printk(KERN_EMERG "Restarting system with command '%s'./n", cmd);
    machine_restart(cmd);
}



void machine_restart(char * __unused)
{
    arm_pm_restart(reboot_mode);
}

    arm_pm_restart(reboot_mode);
这个函数是要每个target自己定义的,
以Qualcomm来说
static void msm_pm_restart(char str)
{
    msm_rpcrouter_close();
    msm_proc_comm(PCOM_RESET_CHIP, &restart_reason, 0);

    for (;;)
        ;
}

这里的restart reason是recovery

static int msm_reboot_call
    (struct notifier_block *this, unsigned long code, void *_cmd)
{
    if ((code == SYS_RESTART) && _cmd) {
        char *cmd = _cmd;
        if (!strcmp(cmd, "bootloader")) {
            restart_reason = 0x77665500;
        } else if (!strcmp(cmd, "recovery")) {
            restart_reason = 0x77665502;
        } else if (!strcmp(cmd, "eraseflash")) {
            restart_reason = 0x776655EF;
        } else if (!strncmp(cmd, "oem-", 4)) {
            unsigned code = simple_strtoul(cmd + 4, 0, 16) & 0xff;
            restart_reason = 0x6f656d00 | code;
        } else {
            restart_reason = 0x77665501;
        }
    }
    return NOTIFY_DONE;
}

会把这个原因写到smem里面去

下次启动的时候怎么管用呢?

bootloader下次起来的时候会去读这个值

Qualcomm的bootloader是appsboot.mbn
void aboot_init(const struct app_descriptor *app)
{
    unsigned reboot_mode = 0;
    unsigned disp_init = 0;
    #if DISPLAY_SPLASH_SCREEN
    display_init();
    dprintf(INFO, "Diplay initialized/n");
    disp_init = 1;
    #endif
    page_size = flash_page_size();
    page_mask = page_size - 1;
    if (keys_get_state(KEY_HOME) != 0)
            boot_into_recovery = 1;
    if (keys_get_state(KEY_BACK) != 0)
        goto fastboot;
    if (keys_get_state(KEY_CLEAR) != 0)
        goto fastboot;
    if (keys_get_state(KEY_VOLUMEUP) != 0)
        goto fastboot;
    if (keys_get_state(KEY_CAMERA) != 0)
        goto fastboot;
    if (keys_get_state(KEY_VOLUMEDOWN) != 0)
            boot_into_recovery = 1;
        //goto fastboot;

    reboot_mode = check_reboot_mode();
        if (reboot_mode == RECOVERY_MODE){
            boot_into_recovery = 1;
        }else if(reboot_mode == FASTBOOT_MODE){
            goto fastboot;
        }
    recovery_init();
    boot_linux_from_flash();
    dprintf(CRITICAL, "ERROR: Could not do normal boot. Reverting "
        "to fastboot mode./n");

fastboot:
    if(!disp_init) {
        display_init();
    } else {
        fbcon_clear();
    }
    dprintf(INFO, "Diplay initialized/n");
    udc_init(&surf_udc_device);

    fastboot_register("boot", cmd_boot);
    fastboot_register("erase:", cmd_erase);
    fastboot_register("flash:", cmd_flash);
    fastboot_register("continue", cmd_continue);
    fastboot_register("reboot", cmd_reboot);
    fastboot_register("reboot-bootloader", cmd_reboot_bootloader);
    fastboot_publish("product", "swordfish");
    fastboot_publish("kernel", "lk");

    fastboot_init(target_get_scratch_address(), 150 * 1024 * 1024);
    udc_start();
        target_battery_charging_enable(1, 0);
}

APP_START(aboot)
    .init = aboot_init,
APP_END

aboot函数进入recovery有三种情况
1:如果按键就会进入recovery
2:如果check_boot_mode是recovery的时候就会做
3 : 如果recovery_init返回的是真的话就会进入recovery mode


第一种很好理解,按组合按键进入

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwzpwz.html