android系统reboot

来源:互联网 发布:阿部宽年轻照片知乎 编辑:程序博客网 时间:2024/06/07 00:26

这里所说的reboot指的是软件重启,并非断电重启。我们知道android系统的几个功能,比如:回复出厂设置、OTA升级等都需要重启系统,而且重 启后要进入recovery模式,有的手机还带有重启进入fastboot或者其他模式。这些在软重启中式怎么做到的呢?

经过一段查找找到了这个文件:\frameworks\base\core\java\android\os\RecoverySystem.java

我们来看这个文件里面有一个类public class RecoverySystem  我们来看这个类的说明

[cpp] view plaincopy
  1. /** 
  2.  * RecoverySystem contains methods for interacting with the Android 
  3.  * recovery system (the separate partition that can be used to install 
  4.  * system updates, wipe user data, etc.) 
  5.  */  

这个类里面完成了android系统的回复包括安装系统更新,删除用户数据等。

下面我们来看这个类里面的几个 函数

[cpp] view plaincopy
  1. /** 
  2.     * Reboots the device in order to install the given update 
  3.     * package. 
  4.     * 重启系统来安装升级包 
  5.     * Requires the {@link android.Manifest.permission#REBOOT} permission. 
  6.     * 
  7.     * @param context      the Context to use 
  8.     * @param packageFile  the update package to install.  Must be on 
  9.     * a partition mountable by recovery.  (The set of partitions 
  10.     * known to recovery may vary from device to device.  Generally, 
  11.     * /cache and /data are safe.) 
  12.     * 
  13.     * @throws IOException  if writing the recovery command file 
  14.     * fails, or if the reboot itself fails. 
  15.     */  
  16.    public static void installPackage(Context context, File packageFile)  
  17.        throws IOException {  
  18.        String filename = packageFile.getCanonicalPath();  
  19.        Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!");  
  20.        String arg = "--update_package=" + filename;  
  21.        bootCommand(context, arg);  
  22.    }  
  23.   
  24.    /** 
  25.     * Reboots the device and wipes the user data partition.  This is 
  26.     * sometimes called a "factory reset", which is something of a 
  27.     * misnomer because the system partition is not restored to its 
  28.     * factory state. 
  29.     * 重启系统删除用户数据,这个通常被回复出厂设置调用 
  30.     * Requires the {@link android.Manifest.permission#REBOOT} permission. 
  31.     * 
  32.     * @param context  the Context to use 
  33.     * 
  34.     * @throws IOException  if writing the recovery command file 
  35.     * fails, or if the reboot itself fails. 
  36.     */  
  37.    public static void rebootWipeUserData(Context context) throws IOException {  
  38.        final ConditionVariable condition = new ConditionVariable();  
  39.   
  40.        Intent intent = new Intent("android.intent.action.MASTER_CLEAR_NOTIFICATION");  
  41.        context.sendOrderedBroadcast(intent, android.Manifest.permission.MASTER_CLEAR,  
  42.                new BroadcastReceiver() {  
  43.                    @Override  
  44.                    public void onReceive(Context context, Intent intent) {  
  45.                        condition.open();  
  46.                    }  
  47.                }, null, 0, null, null);  
  48.   
  49.        // Block until the ordered broadcast has completed.  
  50.        condition.block();  
  51.   
  52.        bootCommand(context, "--wipe_data");  
  53.    }  
  54.    /** 
  55.     * Reboot into the recovery system to wipe the /cache partition. 
  56.     * 重启系统来删除 /cache目录文件 
  57.     * @throws IOException if something goes wrong. 
  58.     */  
  59.    public static void rebootWipeCache(Context context) throws IOException {  
  60.        bootCommand(context, "--wipe_cache");  
  61.    }  
这 几个函数功能的注释写的很清楚,android系统做 wipe_data、wipe_cache、OTA升级就是调用的这三个函数。具体在哪调用的我们不一一列举了,简单说一下,比如 rebootWipeUserData是在回复出厂设置时候调用的,代码在\frameworks\base\services\java\com \android\server\MasterClearReceiver.java中。

我们仔细研究着几个 函数发现,要实现不同的重启模式就是要bootCommand()这个函数传送不同的参数,android重启就是由这个函数来实现的,

我们就来看

[cpp] view plaincopy
  1. /** 
  2.   * Reboot into the recovery system with the supplied argument. 
  3.   * @param arg to pass to the recovery utility. 
  4.   * @throws IOException if something goes wrong. 
  5.   */  
  6.  private static void bootCommand(Context context, String arg) throws IOException {  
  7.      RECOVERY_DIR.mkdirs();  // 创建recovery的目录  
  8.      COMMAND_FILE.delete();  // 清空recovery命令文件  
  9.      /* 
  10.      *这两个文件都在/cache目录中,他俩的定义是 
  11.      * private static File RECOVERY_DIR = new File("/cache/recovery"); 
  12.      * private static File COMMAND_FILE = new File(RECOVERY_DIR, "command"); 
  13.      */  
  14.      LOG_FILE.delete();  
  15.   
  16.      FileWriter command = new FileWriter(COMMAND_FILE);//穿件新的命令文件  
  17.      try {  
  18.          command.write(arg); //将命令写入命令文件,给recovery模式使用  
  19.          command.write("\n");  
  20.      } finally {  
  21.          command.close();  
  22.      }  
  23.   
  24.      // Having written the command file, go ahead and reboot  
  25.      PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);  
  26.      pm.reboot("recovery");  //重启系统  
  27.   
  28.      throw new IOException("Reboot failed (no permissions?)");  
  29.  }  
这里首先要说明/cache目录和命令文件这两个东西,他们是主系统和recovery模式之间交流的桥梁,主系统把要做的事情写入到这两个中,然后recovery会读取这两个文件,再做相应的处理,这一点在我的另一篇文章中做了更详细的说明http://blog.csdn.net/dkleikesa/article/details/9706137

从这个函数就可以看出了,到了这里上面的三个功能最终合并成了一个--进入recovery模式,于是我们就来看 pm.reboot("recovery");

在\frameworks\base\core\java\android\os\PowerManager.java

[cpp] view plaincopy
  1. public void reboot(String reason)  
  2.     {  
  3.         try {  
  4.             mService.reboot(reason);  
  5.         } catch (RemoteException e) {  
  6.         }  
  7.     }  
这里mService的定义
[cpp] view plaincopy
  1. public PowerManager(IPowerManager service, Handler handler)  
  2.  {  
  3.      mService = service;  
  4.      mHandler = handler;  
  5.  }  
是在构造函数里传进来的,我们继续来看这个参数的传送在\frameworks\base\core\java\android\app\ContextImpl.java中有这么一段
[cpp] view plaincopy
  1. registerService(POWER_SERVICE, new ServiceFetcher() {  
  2.         public Object createService(ContextImpl ctx) {  
  3.             IBinder b = ServiceManager.getService(POWER_SERVICE);  
  4.             IPowerManager service = IPowerManager.Stub.asInterface(b);  
  5.             return new PowerManager(service, ctx.mMainThread.getHandler());  
  6.         }});  
可 以知道 b = ServiceManager.getService(POWER_SERVICE);得到了PowerManagerService这个服 务,service = IPowerManager.Stub.asInterface(b);然后将这个sevice的指针传给PowerManager()的构造函数。也就 是说 这里的mService就是 PowerManagerService这个服务,因此这里的reboot也就是PowerManagerService的 reboot 我们来看它的代码在:\frameworks\base\services\java\com\android\server \PowerManagerService.java中
[cpp] view plaincopy
  1. /** 
  2.  * Reboot the device immediately, passing 'reason' (may be null) 
  3.  * to the underlying __reboot system call.  Should not return. 
  4.  */  
  5. public void reboot(String reason)  
  6. {  
  7.     mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);  
  8.   
  9.     if (mHandler == null || !ActivityManagerNative.isSystemReady()) {  
  10.         throw new IllegalStateException("Too early to call reboot()");  
  11.     }  
  12. //建立一个 shutdown线程来执行整个关机过程  
  13.     final String finalReason = reason;  
  14.     Runnable runnable = new Runnable() {  
  15.         public void run() {  
  16.             synchronized (this) {  
  17.                 ShutdownThread.reboot(mContext, finalReason, false);  
  18.             }  
  19.               
  20.         }  
  21.     };  
  22.     // ShutdownThread must run on a looper capable of displaying the UI.  
  23.     //关机时的UI显示  
  24.     mHandler.post(runnable);  
  25.   
  26.     // PowerManager.reboot() is documented not to return so just wait for the inevitable.  
  27.     synchronized (runnable) {  
  28.         while (true) {  
  29.             try {  
  30.                 runnable.wait();  
  31.             } catch (InterruptedException e) {  
  32.             }  
  33.         }  
  34.     }  
  35. }  

下面我们就来看shutdown线程的 reboot函数:\frameworks\base\core\java\com\android\internal\app\ShutdownThread.java
[cpp] view plaincopy
  1. /** 
  2.  * Request a clean shutdown, waiting for subsystems to clean up their 
  3.  * state etc.  Must be called from a Looper thread in which its UI 
  4.  * is shown. 
  5.  * 
  6.  * @param context Context used to display the shutdown progress dialog. 
  7.  * @param reason code to pass to the kernel (e.g. "recovery"), or null. 
  8.  * @param confirm true if user confirmation is needed before shutting down. 
  9.  */  
  10. public static void reboot(final Context context, String reason, boolean confirm) {  
  11.     mReboot = true; //吧reboot设置为true  
  12.     mRebootReason = reason;  
  13.     shutdown(context, confirm);//关机之前的 系统清理,保存好所有的数据  
  14. }  
这里要进一步执行的话靠的是mReboot=true;这一句,具体的执行过程在ShutdownThread:run()函数中
[cpp] view plaincopy
  1. /** 
  2.  * Makes sure we handle the shutdown gracefully. 
  3.  * Shuts off power regardless of radio and bluetooth state if the alloted time has passed. 
  4.  */  
  5. public void run() {  
  6.    。。。。。。。。。。。。。  
  7.    。。。。。。。。。。。。。  
  8.   
  9.     rebootOrShutdown(mReboot, mRebootReason);  
  10. }  
继续看:\frameworks\base\core\java\com\android\internal\app\ShutdownThread.java
[cpp] view plaincopy
  1. /** 
  2.  * Do not call this directly. Use {@link #reboot(Context, String, boolean)} 
  3.  * or {@link #shutdown(Context, boolean)} instead. 
  4.  * 
  5.  * @param reboot true to reboot or false to shutdown 
  6.  * @param reason reason for reboot 
  7.  */  
  8. public static void rebootOrShutdown(boolean reboot, String reason) {  
  9.     if (reboot) {  
  10.         Log.i(TAG, "Rebooting, reason: " + reason);  
  11.         try {  
  12.             Power.reboot(reason);  
  13.         } catch (Exception e) {  
  14.             Log.e(TAG, "Reboot failed, will attempt shutdown instead", e);  
  15.         }  
  16.     } else if (SHUTDOWN_VIBRATE_MS > 0) {  
  17.         // vibrate before shutting down  
  18.         Vibrator vibrator = new Vibrator();  
  19.         try {  
  20.             vibrator.vibrate(SHUTDOWN_VIBRATE_MS);//关机震动一下,如果是reboot就不震动  
  21.         } catch (Exception e) {  
  22.             // Failure to vibrate shouldn't interrupt shutdown.  Just log it.  
  23.             Log.w(TAG, "Failed to vibrate during shutdown.", e);  
  24.         }  
  25.   
  26.         // vibrator is asynchronous so we need to wait to avoid shutting down too soon.  
  27.         try {  
  28.             Thread.sleep(SHUTDOWN_VIBRATE_MS);  
  29.         } catch (InterruptedException unused) {  
  30.         }  
  31.     }  
  32.   
  33.     // Shutdown power  
  34.     Log.i(TAG, "Performing low-level shutdown...");  
  35.     Power.shutdown();  
  36. }  
这里最终调用的是Power.reboot(reason);代码在\frameworks\base\core\java\android\os\Power.java
[cpp] view plaincopy
  1. /** 
  2.  * Reboot the device. 
  3.  * @param reason code to pass to the kernel (e.g. "recovery"), or null. 
  4.  * 
  5.  * @throws IOException if reboot fails for some reason (eg, lack of 
  6.  *         permission) 
  7.  */  
  8. public static void reboot(String reason) throws IOException  
  9. {  
  10.     rebootNative(reason);  
  11. }  
这里到了jni层 代码在\frameworks\base\core\jni\android_os_Power.cpp
[cpp] view plaincopy
  1. static void android_os_Power_reboot(JNIEnv *env, jobject clazz, jstring reason)  
  2. {  
  3.     if (reason == NULL) {  
  4.         android_reboot(ANDROID_RB_RESTART, 0, 0);  
  5.     } else {  
  6.         const char *chars = env->GetStringUTFChars(reason, NULL);  
  7.         android_reboot(ANDROID_RB_RESTART2, 0, (char *) chars);  
  8.         env->ReleaseStringUTFChars(reason, chars);  // In case it fails.  
  9.     }  
  10.     jniThrowIOException(env, errno);  
  11. }  
继续看这里调用的android_reboot()在:\system\core\libcutils\android_reboot.c
[cpp] view plaincopy
  1. int android_reboot(int cmd, int flags, char *arg)  
  2. {  
  3.     int ret;  
  4.   
  5.     if (!(flags & ANDROID_RB_FLAG_NO_SYNC))  
  6.         sync();  
  7.   
  8.     if (!(flags & ANDROID_RB_FLAG_NO_REMOUNT_RO))  
  9.         remount_ro();  
  10.   
  11.     switch (cmd) {  
  12.         case ANDROID_RB_RESTART:  
  13.             ret = reboot(RB_AUTOBOOT);  
  14.             break;  
  15.   
  16.         case ANDROID_RB_POWEROFF:  
  17.             ret = reboot(RB_POWER_OFF);  
  18.             break;  
  19.   
  20.         case ANDROID_RB_RESTART2:  
  21.             ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,//我们的参数要执行这一句  
  22.                            LINUX_REBOOT_CMD_RESTART2, arg);  
  23.             break;  
  24.   
  25.         default:  
  26.             ret = -1;  
  27.     }  
  28.   
  29.     return ret;  
  30. }  

剩下的我们是要看__reboot()这个函数了,这个函数其实是一个系统调用,调用的linux内核reboot函数它的实现在\android40\bionic\libc\arch-arm\syscalls\__reboot.S

[cpp] view plaincopy
  1. ENTRY(__reboot)  
  2.     .save   {r4, r7}  
  3.     stmfd   sp!, {r4, r7}  
  4.     ldr     r7, =__NR_reboot  
  5.     swi     #0  
  6.     ldmfd   sp!, {r4, r7}  
  7.     movs    r0, r0  
  8.     bxpl    lr  
  9.     b       __set_syscall_errno  
  10. END(__reboot)  
这里__NR_reboot 定义为88 也就是说它是linux系统调用列表里的第88个函数,这样我们就可以去kernel里找这个函数的定义了

系统调用的原理这里就不多讲了,可以百度一下很容易找到,最终得到的reboot函数在\kernel_imx\kernel\sys.c中

[cpp] view plaincopy
  1. SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,  
  2.         void __user *, arg)  
  3. {  
  4.     char buffer[256];  
  5.     int ret = 0;  
  6.   
  7.     /* We only trust the superuser with rebooting the system. */  
  8.     if (!capable(CAP_SYS_BOOT))  
  9.         return -EPERM;  
  10.   
  11.     /* For safety, we require "magic" arguments. */  
  12.     if (magic1 != LINUX_REBOOT_MAGIC1 ||  
  13.         (magic2 != LINUX_REBOOT_MAGIC2 &&  
  14.                     magic2 != LINUX_REBOOT_MAGIC2A &&  
  15.             magic2 != LINUX_REBOOT_MAGIC2B &&  
  16.                     magic2 != LINUX_REBOOT_MAGIC2C))  
  17.         return -EINVAL;  
  18.   
  19.     /* Instead of trying to make the power_off code look like 
  20.      * halt when pm_power_off is not set do it the easy way. 
  21.      */  
  22.     if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off)  
  23.         cmd = LINUX_REBOOT_CMD_HALT;  
  24.   
  25.     mutex_lock(&reboot_mutex);  
  26.     switch (cmd) {  
  27.     case LINUX_REBOOT_CMD_RESTART:  
  28.         kernel_restart(NULL);  
  29.         break;  
  30.   
  31.     case LINUX_REBOOT_CMD_CAD_ON:  
  32.         C_A_D = 1;  
  33.         break;  
  34.   
  35.     case LINUX_REBOOT_CMD_CAD_OFF:  
  36.         C_A_D = 0;  
  37.         break;  
  38.   
  39.     case LINUX_REBOOT_CMD_HALT:  
  40.         kernel_halt();  
  41.         do_exit(0);  
  42.         panic("cannot halt");  
  43.   
  44.     case LINUX_REBOOT_CMD_POWER_OFF:  
  45.         kernel_power_off();  
  46.         do_exit(0);  
  47.         break;  
  48.   
  49.     case LINUX_REBOOT_CMD_RESTART2:  
  50.         if (strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1) < 0) {  
  51.             ret = -EFAULT;  
  52.             break;  
  53.         }  
  54.         buffer[sizeof(buffer) - 1] = '\0';  
  55.   
  56.         kernel_restart(buffer);  
  57.         break;  
  58.   
  59. #ifdef CONFIG_KEXEC  
  60.     case LINUX_REBOOT_CMD_KEXEC:  
  61.         ret = kernel_kexec();  
  62.         break;  
  63. #endif  
  64.   
  65. #ifdef CONFIG_HIBERNATION  
  66.     case LINUX_REBOOT_CMD_SW_SUSPEND:  
  67.         ret = hibernate();  
  68.         break;  
  69. #endif  
  70.   
  71.     default:  
  72.         ret = -EINVAL;  
  73.         break;  
  74.     }  
  75.     mutex_unlock(&reboot_mutex);  
  76.     return ret;  
这里下一步调用的是kernel_restart()代码在本文件中
[cpp] view plaincopy
  1. /** 
  2.  *  kernel_restart - reboot the system 
  3.  *  @cmd: pointer to buffer containing command to execute for restart 
  4.  *      or %NULL 
  5.  * 
  6.  *  Shutdown everything and perform a clean reboot. 
  7.  *  This is not safe to call in interrupt context. 
  8.  */  
  9. void kernel_restart(char *cmd)  
  10. {  
  11.     kernel_restart_prepare(cmd);  
  12.     if (!cmd)  
  13.         printk(KERN_EMERG "Restarting system.\n");  
  14.     else  
  15.         printk(KERN_EMERG "Restarting system with command '%s'.\n", cmd);  
  16.     kmsg_dump(KMSG_DUMP_RESTART);  
  17.     machine_restart(cmd);  
  18. }  
下一步调用machine_restart()代码在\kernel_imx\arch\arm\kernel\process.c中
[cpp] view plaincopy
  1. void machine_restart(char *cmd)  
  2. {  
  3.     machine_shutdown();  
  4.     arm_pm_restart(reboot_mode, cmd);  
  5. }  
下一步看arm_pm_restart(reboot_mode, cmd);,在本文件中有这个的定义void (*arm_pm_restart)(char str, const char *cmd) = arm_machine_restart;

也就是这个函数指针指向了arm_machine_restart,它的代码在本文件中

[cpp] view plaincopy
  1. void arm_machine_restart(char mode, const char *cmd)  
  2. {  
  3.   
  4.   
  5.     //ar_mode(mode,cmd);    //lijianzhang  
  6.     /* Flush the console to make sure all the relevant messages make it 
  7.      * out to the console drivers */  
  8.     arm_machine_flush_console();  
  9.   
  10.     /* Disable interrupts first */  
  11.     local_irq_disable();  
  12.     local_fiq_disable();  
  13.   
  14.     /* 
  15.      * Tell the mm system that we are going to reboot - 
  16.      * we may need it to insert some 1:1 mappings so that 
  17.      * soft boot works. 
  18.      */  
  19.     setup_mm_for_reboot(mode);  
  20.   
  21.     /* Clean and invalidate caches */  
  22.     flush_cache_all();  
  23.   
  24.     /* Turn off caching */  
  25.     cpu_proc_fin();  
  26.   
  27.     /* Push out any further dirty data, and ensure cache is empty */  
  28.     flush_cache_all();  
  29.   
  30.     /* 
  31.      * Now call the architecture specific reboot code. 
  32.      */  
  33.     arch_reset(mode, cmd);  
  34.   
  35.     /* 
  36.      * Whoops - the architecture was unable to reboot. 
  37.      * Tell the user! 
  38.      */  
  39.     mdelay(1000);  
  40.     printk("Reboot failed -- System halted\n");  
  41.     while (1);  
  42. }  
这 里执行reboot的函数是arch_reset(mode, cmd),在执行arch_reset的代码都是关闭系统和cpu一些东西,其中包括了mmu,关闭了mmu以后,访问寄存器必须直接使用寄存器地 址,ioremap这个函数就不能再使用了,同样的,由于mmu关闭了 ,这个函数下面就是printk是打印不出来的,字符过多还会报出内核错误,因此这里虽然写了printk 可以打印出reboot错误,其实也是打不出来的,这点gun官网上也有说明,网上有人修改了内核,在关闭mmu以后将printk缓存替换成物理地址, 这样才能正常使用。

好了下面来看arch_reset(mode, cmd); \kernel_imx\arch\arm\plat-mxc\system.c

[cpp] view plaincopy
  1. /* 
  2.  * Reset the system. It is called by machine_restart(). 
  3.  */  
  4. void arch_reset(char mode, const char *cmd)  
  5. {  
  6.     unsigned int wcr_enable;  
  7.   
  8.     arch_reset_special_mode(mode, cmd);  
  9.   
  10. #ifdef CONFIG_ARCH_MX6  
  11.     /* wait for reset to assert... */  
  12.     #ifdef CONFIG_MX6_INTER_LDO_BYPASS  
  13.     wcr_enable = 0x14; /*reset system by extern pmic*/  
  14.     #else  
  15.     wcr_enable = (1 << 2);  
  16.     #endif  
  17.       
  18.     __raw_writew(wcr_enable, wdog_base);  
  19.      /*errata TKT039676, SRS bit may be missed when 
  20.     SRC sample it, need to write the wdog controller 
  21.     twice to avoid it */  
  22.     __raw_writew(wcr_enable, wdog_base/*MX6Q_WDOG1_BASE_ADDR*/);  
  23.   
  24.     /* wait for reset to assert... */  
  25.     mdelay(500);  
  26.   
  27.     printk(KERN_ERR "Watchdog reset failed to assert reset\n");  
  28.   
  29.     return;  
  30. #endif  
  31.   
  32. #ifdef CONFIG_MACH_MX51_EFIKAMX  
  33.     if (machine_is_mx51_efikamx()) {  
  34.         mx51_efikamx_reset();  
  35.         return;  
  36.     }  
  37. #endif  
  38.   
  39.     if (cpu_is_mx1()) {  
  40.         wcr_enable = (1 << 0);  
  41.     } else {  
  42.         struct clk *clk;  
  43.   
  44.         clk = clk_get_sys("imx2-wdt.0", NULL);  
  45.         if (!IS_ERR(clk))  
  46.             clk_enable(clk);  
  47.         wcr_enable = (1 << 2);  
  48.     }  
  49.   
  50.     /* Assert SRS signal */  
  51.     __raw_writew(wcr_enable, wdog_base);  
  52.   
  53.     /* wait for reset to assert... */  
  54.     mdelay(500);  
  55.   
  56.     printk(KERN_ERR "Watchdog reset failed to assert reset\n");  
  57.   
  58.     /* delay to allow the serial port to show the message */  
  59.     mdelay(50);  
  60.   
  61.     /* we'll take a jump through zero as a poor second */  
  62. }  
好了这里看arch_reset_special_mode(mode, cmd); 这个函数就是进入各个模式,与uboot通信的地方,来看代码
[cpp] view plaincopy
  1. static void arch_reset_special_mode(char mode, const char *cmd)  
  2. {  
  3.     if (strcmp(cmd, "download") == 0)  
  4.         do_switch_mfgmode();  
  5.     else if (strcmp(cmd, "recovery") == 0)  
  6.         do_switch_recovery();  
  7.     else if (strcmp(cmd, "fastboot") == 0)  
  8.         do_switch_fastboot();  
  9.     else if (strcmp(cmd, "bootloader") == 0)      
  10.         do_switch_bootloader();  
  11. }  
这里可以看到内核支持4个模式,每个模式都有相应的函数,我们来贴一个recovery的,在\kernel_imx\arch\arm\mach-mx6\system.c
[cpp] view plaincopy
  1. void do_switch_recovery(void)  
  2. {  
  3.     u32 reg;  
  4.   
  5.     reg = __raw_readl((SRC_BASE_ADDR + SRC_GPR10));  
  6.     reg |= ANDROID_RECOVERY_BOOT;  
  7.     __raw_writel(reg, (SRC_BASE_ADDR + SRC_GPR10));  
  8. }  
原理是把一个寄存器的值的一位置高,这个寄存器在复位过程中是不会被清零的,重启以后,uboot可以检测这一位来确定启动的模式,
过了这个函数,下面执行__raw_writew(wcr_enable, wdog_base); 这个是打开看门狗,可以知道系统重启最后就是利用看门狗,产生复位信号,来重启的。

到了这里reboot的流程就走完了,下一步就是正常启动了,详细的启动过程参见我的另一篇文章 http://blog.csdn.net/dkleikesa/article/details/9792747

下面来说明一个小技巧,如果要重启进入各个模式,是可以由命令来实现的,也就是"reboot recovery"进入recovery模式 “reboot fastboot”是进入fastboot模式

0 0
原创粉丝点击