android recovery 和reboot

android  recovery 和reboot

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

设置模块中进行恢复出厂设置操作,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


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

  • 第二种会去读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。

  • 你可能感兴趣的:(android,linux,cmd,Flash,buffer,Descriptor)