意外发现:setprop sys.powerctl reboot,recovery 将重启进入有菜单选择界面的recovery模式,在此模式下有root权限,不过要通过串口模式操作。

在系统设置应用里有恢复出厂设置的菜单,点击弹出对话框,确认后调用恢复出厂设置广播:

Settings/src/com/android/tv/settings/device/privacy/PrivacyActivity.java:171

    private void onFactoryResetConfirm(ActionBehavior behaviour) {switch (behaviour) {case INIT:setContentAndActionFragments(ContentFragment.newInstance(ActionType.FACTORY_RESET_CONFIRM.getTitle(getResources()),getString(R.string.device_reset),getString(R.string.confirm_factory_reset_description),R.drawable.ic_settings_backuprestore,getResources().getColor(R.color.icon_background)),ActionFragment.newInstance(getFactoryResetConfirmActions()));break;case OK:if (!ActivityManager.isUserAMonkey()) {Intent resetIntent = new Intent("android.intent.action.MASTER_CLEAR");if (getIntent().getBooleanExtra(SHUTDOWN_INTENT_EXTRA, false)) {resetIntent.putExtra(SHUTDOWN_INTENT_EXTRA, true);}sendBroadcast(resetIntent);}break;case CANCEL:getFragmentManager().popBackStack(null, 0);getFragmentManager().popBackStack(null, 0);break;default:break;}}

搜索字段MASTER_CLEAR,frameworks/base/core/res/AndroidManifest.xml里有注册receiver

frameworks\base\services\core\java\com\android\server\MasterClearReceiver.java

    public void onReceive(final Context context, final Intent intent) {if (intent.getAction().equals(Intent.ACTION_REMOTE_INTENT)) {if (!"google.com".equals(intent.getStringExtra("from"))) {Slog.w(TAG, "Ignoring master clear request -- not from trusted server.");return;}}final boolean shutdown = intent.getBooleanExtra("shutdown", false);final String reason = intent.getStringExtra(Intent.EXTRA_REASON);final boolean wipeExternalStorage = intent.getBooleanExtra(Intent.EXTRA_WIPE_EXTERNAL_STORAGE, false);Slog.w(TAG, "!!! FACTORY RESET !!!");// The reboot call is blocking, so we need to do it on another thread.Thread thr = new Thread("Reboot") {@Overridepublic void run() {try {RecoverySystem.rebootWipeUserData(context, shutdown, reason);Log.wtf(TAG, "Still running after master clear?!");} catch (IOException e) {Slog.e(TAG, "Can't perform master clear/factory reset", e);} catch (SecurityException e) {Slog.e(TAG, "Can't perform master clear/factory reset", e);}}};if (wipeExternalStorage) {// thr will be started at the end of this task.new WipeAdoptableDisksTask(context, thr).execute();} else {thr.start();}}

frameworks\base\core\java\android\os\RecoverySystem.java

    public static void rebootWipeUserData(Context context, boolean shutdown, String reason)throws IOException {UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);if (um.hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET)) {throw new SecurityException("Wiping data is not allowed for this user.");}final ConditionVariable condition = new ConditionVariable();Intent intent = new Intent("android.intent.action.MASTER_CLEAR_NOTIFICATION");intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);context.sendOrderedBroadcastAsUser(intent, UserHandle.OWNER,android.Manifest.permission.MASTER_CLEAR,new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {condition.open();}}, null, 0, null, null);// Block until the ordered broadcast has completed.condition.block();String shutdownArg = null;if (shutdown) {shutdownArg = "--shutdown_after";}String reasonArg = null;if (!TextUtils.isEmpty(reason)) {reasonArg = "--reason=" + sanitizeArg(reason);}final String localeArg = "--locale=" + Locale.getDefault().toString();bootCommand(context, shutdownArg, "--wipe_data", reasonArg, localeArg);}
    private static void bootCommand(Context context, String... args) throws IOException {RECOVERY_DIR.mkdirs();  // In case we need itCOMMAND_FILE.delete();  // In case it's not writableLOG_FILE.delete();FileWriter command = new FileWriter(COMMAND_FILE);try {for (String arg : args) {if (!TextUtils.isEmpty(arg)) {// MStar Android Patch BeginStorageManager mStorageManager = context.getSystemService(StorageManager.class);String cmd = arg;String label = null;String uuid = null;if (cmd.startsWith("--update_package")) {cmd = arg.substring(17, arg.length() -1);if (cmd.startsWith("/cache")) {command.write("--uuid=mstar-cache");command.write("\n");command.write("--label=mstar-cache");command.write("\n");} else {StorageVolume vol = mStorageManager.getStorageVolume(new File(cmd));uuid = "--uuid=" + vol.getUuid();label = "--label=" + utf8ToUnicode(vol.getFsLabel());command.write(uuid);command.write("\n");command.write(label);command.write("\n");}}// MStar Android Patch Endcommand.write(arg);command.write("\n");}}} finally {command.close();}Log.i(TAG, "bootCommand /cache");// Having written the command file, go ahead and rebootPowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);pm.reboot(PowerManager.REBOOT_RECOVERY);throw new IOException("Reboot failed (no permissions?)");}

此时会在安卓设备里/cache/recovery 目录清除,且创建command文件,写入命令:

#/cache/recovery # ls -l
-rw------- system   system         55 2018-01-01 08:01 command

#cat command                                      
--wipe_data
--reason=MasterClearConfirm
--locale=zh_CN

然后重启,重启还需处理,否则不会进入recovery。ShutdownThread.java:

 private static void beginShutdownSequence(Context context) {synchronized (sIsStartedGuard) {if (sIsStarted) {Log.d(TAG, "Shutdown sequence already running, returning.");return;}sIsStarted = true;}// Throw up a system dialog to indicate the device is rebooting / shutting down.ProgressDialog pd = new ProgressDialog(context);// Path 1: Reboot to recovery and install the update//   Condition: mRebootReason == REBOOT_RECOVERY and mRebootUpdate == True//   (mRebootUpdate is set by checking if /cache/recovery/uncrypt_file exists.)//   UI: progress bar//// Path 2: Reboot to recovery for factory reset//   Condition: mRebootReason == REBOOT_RECOVERY//   UI: spinning circle only (no progress bar)//// Path 3: Regular reboot / shutdown//   Condition: Otherwise//   UI: spinning circle only (no progress bar)if (PowerManager.REBOOT_RECOVERY.equals(mRebootReason)) {mRebootUpdate = new File(UNCRYPT_PACKAGE_FILE).exists();if (mRebootUpdate) {pd.setTitle(context.getText(com.android.internal.R.string.reboot_to_update_title));pd.setMessage(context.getText(com.android.internal.R.string.reboot_to_update_prepare));pd.setMax(100);pd.setProgressNumberFormat(null);pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);pd.setProgress(0);pd.setIndeterminate(false);} else {// Factory reset path. Set the dialog message accordingly.pd.setTitle(context.getText(com.android.internal.R.string.reboot_to_reset_title));pd.setMessage(context.getText(com.android.internal.R.string.reboot_to_reset_message));pd.setIndeterminate(true);}} else {
.
.
.
.// also make sure the screen stays on for better user experiencesInstance.mScreenWakeLock = null;if (sInstance.mPowerManager.isScreenOn()) {try {sInstance.mScreenWakeLock = sInstance.mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG + "-screen");sInstance.mScreenWakeLock.setReferenceCounted(false);sInstance.mScreenWakeLock.acquire();} catch (SecurityException e) {Log.w(TAG, "No permission to acquire wake lock", e);sInstance.mScreenWakeLock = null;}}// start the thread that initiates shutdownsInstance.mHandler = new Handler() {};sInstance.start();}

调到最后一行,sInstance.start(); 启动线程的运行,进入线程的run方法。

    /*** Makes sure we handle the shutdown gracefully.* Shuts off power regardless of radio and bluetooth state if the alloted time has passed.*/public void run() {BroadcastReceiver br = new BroadcastReceiver() {@Override public void onReceive(Context context, Intent intent) {// We don't allow apps to cancel this, so ignore the result.actionDone();}};/** Write a system property in case the system_server reboots before we* get to the actual hardware restart. If that happens, we'll retry at* the beginning of the SystemServer startup.*/{String reason = (mReboot ? "1" : "0") + (mRebootReason != null ? mRebootReason : "");SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason);}/** If we are rebooting into safe mode, write a system property* indicating so.*/if (mRebootSafeMode) {SystemProperties.set(REBOOT_SAFEMODE_PROPERTY, "1");}Log.i(TAG, "Sending shutdown broadcast...");// First send the high-level shut down broadcast.mActionDone = false;Intent intent = new Intent(Intent.ACTION_SHUTDOWN);intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);mContext.sendOrderedBroadcastAsUser(intent,UserHandle.ALL, null, br, mHandler, 0, null, null);final long endTime = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME;synchronized (mActionDoneSync) {while (!mActionDone) {long delay = endTime - SystemClock.elapsedRealtime();if (delay <= 0) {Log.w(TAG, "Shutdown broadcast timed out");break;} else if (mRebootUpdate) {int status = (int)((MAX_BROADCAST_TIME - delay) * 1.0 *BROADCAST_STOP_PERCENT / MAX_BROADCAST_TIME);sInstance.setRebootProgress(status, null);}try {mActionDoneSync.wait(Math.min(delay, PHONE_STATE_POLL_SLEEP_MSEC));} catch (InterruptedException e) {}}}if (mRebootUpdate) {sInstance.setRebootProgress(BROADCAST_STOP_PERCENT, null);}Log.i(TAG, "Shutting down activity manager...");final IActivityManager am =ActivityManagerNative.asInterface(ServiceManager.checkService("activity"));if (am != null) {try {am.shutdown(MAX_BROADCAST_TIME);} catch (RemoteException e) {}}if (mRebootUpdate) {sInstance.setRebootProgress(ACTIVITY_MANAGER_STOP_PERCENT, null);}Log.i(TAG, "Shutting down package manager...");final PackageManagerService pm = (PackageManagerService)ServiceManager.getService("package");if (pm != null) {pm.shutdown();}if (mRebootUpdate) {sInstance.setRebootProgress(PACKAGE_MANAGER_STOP_PERCENT, null);}// Shutdown radios.shutdownRadios(MAX_RADIO_WAIT_TIME);if (mRebootUpdate) {sInstance.setRebootProgress(RADIO_STOP_PERCENT, null);}// Shutdown MountService to ensure media is in a safe stateIMountShutdownObserver observer = new IMountShutdownObserver.Stub() {public void onShutDownComplete(int statusCode) throws RemoteException {Log.w(TAG, "Result code " + statusCode + " from MountService.shutdown");actionDone();}};Log.i(TAG, "Shutting down MountService");// Set initial variables and time out time.mActionDone = false;final long endShutTime = SystemClock.elapsedRealtime() + MAX_SHUTDOWN_WAIT_TIME;synchronized (mActionDoneSync) {try {final IMountService mount = IMountService.Stub.asInterface(ServiceManager.checkService("mount"));if (mount != null) {mount.shutdown(observer);} else {Log.w(TAG, "MountService unavailable for shutdown");}} catch (Exception e) {Log.e(TAG, "Exception during MountService shutdown", e);}while (!mActionDone) {long delay = endShutTime - SystemClock.elapsedRealtime();if (delay <= 0) {Log.w(TAG, "Shutdown wait timed out");break;} else if (mRebootUpdate) {int status = (int)((MAX_SHUTDOWN_WAIT_TIME - delay) * 1.0 *(MOUNT_SERVICE_STOP_PERCENT - RADIO_STOP_PERCENT) /MAX_SHUTDOWN_WAIT_TIME);status += RADIO_STOP_PERCENT;sInstance.setRebootProgress(status, null);}try {mActionDoneSync.wait(Math.min(delay, PHONE_STATE_POLL_SLEEP_MSEC));} catch (InterruptedException e) {}}}if (mRebootUpdate) {sInstance.setRebootProgress(MOUNT_SERVICE_STOP_PERCENT, null);// If it's to reboot to install update, invoke uncrypt via init service.uncrypt();}rebootOrShutdown(mContext, mReboot, mRebootReason);}

rebootOrShutdown(mContext, mReboot, mRebootReason);

    public static void rebootOrShutdown(final Context context, boolean reboot, String reason) {if (reboot) {Log.i(TAG, "Rebooting, reason: " + reason);PowerManagerService.lowLevelReboot(reason);Log.e(TAG, "Reboot failed, will attempt shutdown instead");} else if (SHUTDOWN_VIBRATE_MS > 0 && context != null) {// vibrate before shutting downVibrator vibrator = new SystemVibrator(context);try {vibrator.vibrate(SHUTDOWN_VIBRATE_MS, VIBRATION_ATTRIBUTES);} catch (Exception e) {// Failure to vibrate shouldn't interrupt shutdown.  Just log it.Log.w(TAG, "Failed to vibrate during shutdown.", e);}// vibrator is asynchronous so we need to wait to avoid shutting down too soon.try {Thread.sleep(SHUTDOWN_VIBRATE_MS);} catch (InterruptedException unused) {}}// Shutdown powerLog.i(TAG, "Performing low-level shutdown...");PowerManagerService.lowLevelShutdown();}

PowerManagerService.lowLevelReboot(reason);

    /*** Low-level function to reboot the device. On success, this* function doesn't return. If more than 20 seconds passes from* the time a reboot is requested, this method returns.** @param reason code to pass to the kernel (e.g. "recovery"), or null.*/public static void lowLevelReboot(String reason) {if (reason == null) {reason = "";}if (reason.equals(PowerManager.REBOOT_RECOVERY)) {// If we are rebooting to go into recovery, instead of// setting sys.powerctl directly we'll start the// pre-recovery service which will do some preparation for// recovery and then reboot for us.SystemProperties.set("ctl.start", "pre-recovery");} else {SystemProperties.set("sys.powerctl", "reboot," + reason);}try {Thread.sleep(20 * 1000L);} catch (InterruptedException e) {Thread.currentThread().interrupt();}Slog.wtf(TAG, "Unexpected return from lowLevelReboot!");}

SystemProperties.set("ctl.start", "pre-recovery"); 此处将导致系统重启,启动init.rc里注册的服务:

service pre-recovery /system/bin/uncrypt --reboot
    class main
    disabled
    oneshot

service pre-recovery /system/bin/uncrypt --reboot    system/bin/uncrypt 这个程序会被执行,传入的参数是--reboot

进入bootable/recovery/uncrypt/uncrypt.cpp

int main(int argc, char** argv) {const char* input_path;const char* map_file;if (argc != 3 && argc != 1 && (argc == 2 && strcmp(argv[1], "--reboot") != 0)) {fprintf(stderr, "usage: %s [--reboot] [<transform_path> <map_file>]\n", argv[0]);return 2;}// When uncrypt is started with "--reboot", it wipes misc and reboots.// Otherwise it uncrypts the package and writes the block map.if (argc == 2) {printf("\r\n uncrypt to wipe_misc");if (read_fstab() == NULL) {return 1;}wipe_misc();reboot_to_recovery();} else {// The pipe has been created by the system server.int status_fd = open(status_file.c_str(), O_WRONLY | O_CREAT | O_SYNC, S_IRUSR | S_IWUSR);if (status_fd == -1) {ALOGE("failed to open pipe \"%s\": %s\n", status_file.c_str(), strerror(errno));return 1;}if (argc == 3) {// when command-line args are given this binary is being used// for debugging.input_path = argv[1];map_file = argv[2];} else {std::string package;if (!find_uncrypt_package(package)) {android::base::WriteStringToFd("-1\n", status_fd);close(status_fd);return 1;}input_path = package.c_str();map_file = cache_block_map.c_str();}int status = uncrypt(input_path, map_file, status_fd);if (status != 0) {android::base::WriteStringToFd("-1\n", status_fd);close(status_fd);return 1;}android::base::WriteStringToFd("100\n", status_fd);close(status_fd);}return 0;
}
static void reboot_to_recovery() {ALOGI("rebooting to recovery");property_set("sys.powerctl", "reboot,recovery");sleep(10);ALOGE("reboot didn't succeed?");
}

property_set("sys.powerctl", "reboot,recovery");

sys.powerctl属性出发开关在init.rc中

on property:sys.powerctl=*
    powerctl ${sys.powerctl}

system/core/init/keywords.h
KEYWORD(powerctl,    COMMAND, 1, do_powerctl
system/core/init/builtins.cpp
int do_powerctl(int nargs, char **args)
{char command[PROP_VALUE_MAX];int res;int len = 0;int cmd = 0;const char *reboot_target;res = expand_props(command, args[1], sizeof(command));if (res) {ERROR("powerctl: cannot expand '%s'\n", args[1]);return -EINVAL;}if (strncmp(command, "shutdown", 8) == 0) {cmd = ANDROID_RB_POWEROFF;len = 8;} else if (strncmp(command, "reboot", 6) == 0) {cmd = ANDROID_RB_RESTART2;len = 6;} else {ERROR("powerctl: unrecognized command '%s'\n", command);return -EINVAL;}if (command[len] == ',') {reboot_target = &command[len + 1];} else if (command[len] == '\0') {reboot_target = "";} else {ERROR("powerctl: unrecognized reboot target '%s'\n", &command[len]);return -EINVAL;}return android_reboot(cmd, 0, reboot_target);
}
android_reboot(cmd, 0, reboot_target);    参数为(ANDROID_RB_RESTART2, 0, "recovery")
system/core/libcutils/android_reboot.c
int android_reboot(int cmd, int flags UNUSED, const char *arg)
{int ret;sync();remount_ro();switch (cmd) {case ANDROID_RB_RESTART:ret = reboot(RB_AUTOBOOT);break;case ANDROID_RB_POWEROFF:ret = reboot(RB_POWER_OFF);break;case ANDROID_RB_RESTART2:ret = syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,LINUX_REBOOT_CMD_RESTART2, arg);break;default:ret = -1;}return ret;
}

case ANDROID_RB_RESTART2:
            ret = syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
                           LINUX_REBOOT_CMD_RESTART2, arg);

在用户空间和内核空间之间,有一个叫做Syscall(系统调用, system call)的中间层,是连接用户态和内核态的桥梁。这样即提高了内核的安全型,也便于移植,只需实现同一套接口即可。Linux系统,用户空间通过向内核空间发出Syscall,产生软中断,从而让程序陷入内核态,执行相应的操作。对于每个系统调用都会有一个对应的系统调用号,比很多操作系统要少很多。

kernel/include/uapi/asm-generic/unistd.h
/* kernel/sys.c */
#define __NR_setpriority 140
__SYSCALL(__NR_setpriority, sys_setpriority)
#define __NR_getpriority 141
__SYSCALL(__NR_getpriority, sys_getpriority)
#define __NR_reboot 142
__SYSCALL(__NR_reboot, sys_reboot)
#define __NR_setregid 143

/* kernel/sys.c */表明是在/* kernel/sys.c */的文件里定义的方法

宏定义SYSCALL_DEFINEx(xxx,…),展开后对应的方法则是sys_xxx

kernel/sys.c
/** Reboot system call: for obvious reasons only root may call it,* and even root needs to set up some magic numbers in the registers* so that some mistake won't make this reboot the whole machine.* You can also set the meaning of the ctrl-alt-del-key here.** reboot doesn't sync: do that yourself before calling this.*/
SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,void __user *, arg)
{struct pid_namespace *pid_ns = task_active_pid_ns(current);char buffer[256];int ret = 0;/* We only trust the superuser with rebooting the system. */if (!ns_capable(pid_ns->user_ns, CAP_SYS_BOOT))return -EPERM;/* For safety, we require "magic" arguments. */if (magic1 != LINUX_REBOOT_MAGIC1 ||(magic2 != LINUX_REBOOT_MAGIC2 &&magic2 != LINUX_REBOOT_MAGIC2A &&magic2 != LINUX_REBOOT_MAGIC2B &&magic2 != LINUX_REBOOT_MAGIC2C))return -EINVAL;/** If pid namespaces are enabled and the current task is in a child* pid_namespace, the command is handled by reboot_pid_ns() which will* call do_exit().*/ret = reboot_pid_ns(pid_ns, cmd);if (ret)return ret;/* Instead of trying to make the power_off code look like* halt when pm_power_off is not set do it the easy way.*/
#if (MP_PLATFORM_PM == 0)if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off)cmd = LINUX_REBOOT_CMD_HALT;#endif /* MP_PLATFORM_PM */mutex_lock(&reboot_mutex);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();do_exit(0);panic("cannot halt");case LINUX_REBOOT_CMD_POWER_OFF:kernel_power_off();do_exit(0);break;case LINUX_REBOOT_CMD_RESTART2:if (strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1) < 0) {ret = -EFAULT;break;}buffer[sizeof(buffer) - 1] = '\0';kernel_restart(buffer);break;#ifdef CONFIG_KEXECcase LINUX_REBOOT_CMD_KEXEC:ret = kernel_kexec();break;
#endif#ifdef CONFIG_HIBERNATIONcase LINUX_REBOOT_CMD_SW_SUSPEND:ret = hibernate();break;
#endifdefault:ret = -EINVAL;break;}mutex_unlock(&reboot_mutex);return ret;
}
kernel_restart(buffer); 参数为("recovery")
/*** kernel_restart - reboot the system* @cmd: pointer to buffer containing command to execute for restart*     or %NULL**  Shutdown everything and perform a clean reboot.*    This is not safe to call in interrupt context.*/
void kernel_restart(char *cmd)
{extern ptrdiff_t   mstar_pm_base;kernel_restart_prepare(cmd);migrate_to_reboot_cpu();syscore_shutdown();if (!cmd)printk(KERN_EMERG "Restarting system.\n");elseprintk(KERN_EMERG "Restarting system with command '%s'.\n", cmd);#if defined(CONFIG_ARM)*((volatile unsigned int*) (0xfd000000 + (0x3008 << 1))) = 0x0e00;*((volatile unsigned int*) (0xfd000000 + (0x300a << 1))) = 0x0727;#elif defined(CONFIG_ARM64)*((volatile unsigned int*) (mstar_pm_base + (0x3008 << 1))) = 0x0e00;*((volatile unsigned int*) (mstar_pm_base + (0x300a << 1))) = 0x0727;#endifkmsg_dump(KMSG_DUMP_RESTART);machine_restart(cmd);
}

machine_restart(cmd); 参数为("recovery"),machine_restart 函数在很多文件里都有,具体是哪个文件暂不研究,猜测可能走下面这条路,不过也有可能搞错了。

arch/arm64/kernel/process.c
void machine_restart(char *cmd)
{machine_shutdown();/* Disable interrupts first */local_irq_disable();local_fiq_disable();/* Now call the architecture specific reboot code. */if (arm_pm_restart)arm_pm_restart('h', cmd);/** Whoops - the architecture was unable to reboot.*/printk("Reboot failed -- System halted\n");while (1);
}

arm_pm_restart('h', cmd); cmd="recovery"

arch/arm64/kernel/process.c
void (*arm_pm_restart)(char str, const char *cmd) = arm_machine_restart;
EXPORT_SYMBOL_GPL(arm_pm_restart);
arch/arm64/kernel/process.c
#if (MP_PLATFORM_PM == 1)
static void arm_machine_restart(char mode, const char *cmd)
{/** Tell the mm system that we are going to reboot -* we may need it to insert some 1:1 mappings so that* soft boot works.*/setup_mm_for_reboot();#ifndef CONFIG_MP_PLATFORM_ARM/* Clean and invalidate caches */flush_cache_all();/* Turn D-cache off */cpu_cache_off();/* Push out any further dirty data, and ensure cache is empty */flush_cache_all();
#endif/** Now call the architecture specific reboot code.*/arch_reset(mode, cmd);
}
#else
static void arm_machine_restart(char mode, const char *cmd){}
#endif
kernel\linaro\mstar2\hal\mainz\cpu\arm64\include\mach\system.h
static inline void arch_reset(char mode, const char *cmd)
{
#ifdef CONFIG_SMPif(magic_number_address != 0)*(volatile unsigned short *)(magic_number_address) =  0x0;*(volatile unsigned long*)(REG_PM_MISC_BASE + 0xB8) = 0x79;    // reg_top_sw_rst
#endif
#if 0
// set WDT count down timer
*(volatile unsigned long*)(REG_WDT_BASE + 0x10) = BOOT_DELAY_MILLISECOND & 0x0000FFFF;
*(volatile unsigned long*)(REG_WDT_BASE + 0x14) = BOOT_DELAY_MILLISECOND  >> 16  ;
#endif
}

arch_reset(mode, cmd); 参数为('h',"recovery")

#define REG_PM_MISC_BASE                (0x2e00UL)

0x2eB8 写 0x79

android之恢复出厂设置的关机流程相关推荐

  1. android 恢复出厂设置 代码,android恢复出厂设置以及系统升级流程

    http://www.bangchui.org/simple/?t5938.html ============================================= 恢复出厂设置流程概括: ...

  2. android 恢复出厂,安卓(Android)手机恢复出厂设置的方法

    手机恢复出厂设置是把手机中的个性设置或者说自定义的设置恢复刚买手机时的一些东西,下面我来介绍两种恢复出厂设置的方法,希望本文章对各位同学会有所帮助. 手机恢复出厂设置会怎么样? 手机恢复出厂设置.只会 ...

  3. android root 恢复出厂设置,Android系统 免root 卸载预置应用

    如下方法仅能删除当前系统中预置的 APP,恢复出厂设置后,删除的 APP 会恢复.如不清楚包名对应的应用请自行百度,请勿轻易删除未知报名导致系统损坏. 1.关于手机连续点击软件版本号6次,开启手机开发 ...

  4. android系统恢复出厂设置和升级界面的修改方法

    最近需要定制恢复出厂设置和升级的画面,将原生的绿色机器人改成其他的图片. 基于的android版本是4.4.4,改起来挺简单的,但是遇到了几个坑,特地记录下. android 4.4.4的升级机器人图 ...

  5. android 手机恢复出厂设置,恢复青春活力

    本文的原文连接是: http://blog.csdn.net/freewebsys/article/details/50516200 未经博主允许不得转载. 博主地址是:http://blog.csd ...

  6. android phone恢复出厂设置,Android手机正确恢复出厂设置方法

    Android手机正确恢复出厂设置方法 作为一款智能操作系统,Android也内置了许多其他智能操作系统共有的功能,比如每部手机都必备的恢复出厂设置.那么Android手机该如何设置,才能让它正确的恢 ...

  7. Android系统恢复出厂设置方法-涵盖5.1 6.0 7.0 7.1 8.0 9.0

    最近在8.0系统上面调试公司自主开发的setting,发现无法恢复出厂,原来在7.1 7.0 6.0 5.1上面使用的广播已经没有效果,查阅8.0的原生Settings源码之后发现恢复出厂的代码在8. ...

  8. Android 10 恢复出厂设置和清除应用数据接口

    1 .恢复出厂方式的接口 a.通过广播方式调用: Intent intent = new Intent(Intent.ACTION_FACTORY_RESET);         intent.set ...

  9. android adb恢复出厂设置,android开发分享擦除数据/通过ADB恢复出厂设置

    经过大量的挖掘,我终于下载了Android的恢复部分的源代码. 事实certificate,你实际上可以发送命令到恢复. * The arguments which may be supplied i ...

最新文章

  1. 剑指offer:整数中1出现的次数(从1到n整数中1出现的次数)
  2. 【文化传承】念念不忘 必有回响
  3. r 多元有序logistic回归_R语言多元Logistic逻辑回归 应用案例
  4. 用JS实现一个定时间段的跳转
  5. LeetCode 集锦(二十二) - 第 101 题 Symmetric Tree
  6. 160个Crackme041之无源码修改Delphi程序
  7. [zz]grep 命令的使用
  8. Solaris、Mac OS系统日志分析工具
  9. 详解Microsoft Office Communication Server (OCS) 2007 标准版部署(上)
  10. 使用Log4j为项目配置日志输出应用详细总结及示例演示.
  11. php 路由实现_PHP操作路由器实现方法示例
  12. jQuery延迟对象deferred的使用
  13. 语音识别错误太多?高科技巨头们偏偏“不信邪”
  14. 抖音算法暑期实习春招双双发车
  15. 一道经典JS题(关于this)
  16. country-converter官方文档----机翻人工确认
  17. 2022SPSSPRO认证杯数学建模B题第二阶段方案及赛后总结:唐宋诗的定量分析与比较研究
  18. 【GlobalMapper精品教程】008:如何根据指定区域(shp、kml、cad)下载卫星影像?
  19. Apple Pay 详解
  20. win10把用户中文名改为英文名

热门文章

  1. 2021最新阿里服务器购买流程
  2. afn原理 ios_IOS开发入门之iOS面试题- AFN2.x为什么添加一条常驻线程?
  3. 极客Java项目实战营郑天民
  4. 左神算法初级班笔记4:二叉树
  5. SpringCloud-Gateway高级应用及解析
  6. Java - 生成二维码图片
  7. gz是什么意思饭圈_饭圈用语知多少一,这些缩写是什么意思?
  8. 为何有些云比其他云更可信
  9. Git:暂时保存更改
  10. 使用STM32输出PWM波形实现2个 LED呼吸灯