android recovery 和reboot

recovery工作的是要bootloader支持的,因为bootloader要选择启动哪个kernel和ramdisk。

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

rebootsystem

case1:factoryreset

  • Settings/src/com/android/settings/MasterClear.java
  • sendBroadcast(newIntent("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");
  • ->
  • PowerManagerpm=(PowerManager)context.getSystemService(Context.POWER_SERVICE);
  • pm.reboot("recovery");
  • ->
  • frameworks/base/services/java/com/android/server/PowerManagerService.java
  • publicvoidreboot(Stringreason){
  • 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
  • caseLINUX_REBOOT_CMD_RESTART2:
  • kernel_restart(buffer);
  • ->
  • machine_restart(cmd);
  • ->
  • kernel/arch/arm/kernel/process.c
  • voidarm_machine_restart(charmode,constchar*cmd){
  • //setflagandreboot
  • }



    参数表示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


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

  • 第二种会去读smem
    unsigned check_reboot_mode(void)
    {
    unsigned mode[2] = {0, 0};
    unsigned int mode_len = sizeof(mode);
    unsigned smem_status;

    smem_status = smem_read_alloc_entry(SMEM_APPS_BOOT_MODE,
    &mode, mode_len );
    if(smem_status)
    {
    dprintf(CRITICAL, "ERROR: unable to read shared memory for reboot mode/n");
    return 0;
    }
    return mode[0];
    }


    unsigned smem_read_alloc_entry(smem_mem_type_t type, void *buf, int len)
    {
    struct smem_alloc_info *ainfo;
    unsigned *dest = buf;
    unsigned src;
    unsigned size;

    if (((len & 0x3) != 0) || (((unsigned)buf & 0x3) != 0))
    return 1;

    if (type < SMEM_FIRST_VALID_TYPE || type > SMEM_LAST_VALID_TYPE)
    return 1;

    /* TODO: Use smem spinlocks */
    ainfo = &smem->alloc_info[type];
    if (readl(&ainfo->allocated) == 0)
    return 1;

    if ((size = readl(&ainfo->size)) != (unsigned)len)
    return 1;

    src = MSM_SHARED_BASE + readl(&ainfo->offset);
    for (; size > 0; src += 4, size -= 4)
    *(dest++) = readl(src);

    return 0;
    }


    这个文章只解释如何进入recovery。

  • 更多相关文章

    1. C语言函数以及函数的使用
    2. Android模拟、实现、触发系统按键事件的方法
    3. Android自定义九宫格图案解锁
    4. android button自定义触摸前以及触摸时的样式
    5. Android按键消息传播流程
    6. 【按键】灭屏后瞬间按返回键,可以点亮屏幕
    7. Android之自定义Adapter的ListView

    随机推荐

    1. Android之AVD中data目录问题
    2. Android(安卓)Jni开发之Android(安卓)Stu
    3. Android中ImageView无法居中的问题
    4. 在cmd环境下创建、编译、打包android应用
    5. 使用jenkins自动上传IOS,android到阿里云
    6. Android代码优化——使用Android(安卓)li
    7. 在android的状态栏(statusbar)中增加menu
    8. 十八般武艺!移动应用开发者必备的18款利器
    9. Android(安卓)SoftAp支持 (一)
    10. android 读取assets文件夹下的文件资源