当前位置:   article > 正文

android recovery 和reboot

android8 如何调用rebootrecoverywithcommand

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 public void reboot(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 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){ //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。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/黑客灵魂/article/detail/899381
推荐阅读
相关标签
  

闽ICP备14008679号