實現Linux/Android雙系統啓動和重啓切換的一個思路

雙系統啓動的方式不止一種。
一、對於雙系統的啓動鏡像來說:
     1、Linux系統和Android系統的uboot、kernel鏡像相同而文件系統(rootfs)不同;
     2、Linux系統和Android系統的uboot鏡像相同而kernel鏡像和文件系統(roofts)不同。
     這兩種情況都可以實現對雙系統的啓動和切換。

二、雙系統啓動和相互切換的實質是設置標誌位,在啓動時讀取標誌位信息從而啓動相應的系統!下面是兩種實現方式。
     1、啓動(重啓)時,單獨分出一個分區存儲標誌位(保證兩個系統都能對這一塊分區操作);
          在應用程序中向分區寫入標誌位,然後重啓在uboot階段自動scan讀取這個分區中的標誌位(對應啓動相應的系統)

     2、在文件系統分區寫入一個.txt文件(文件存儲標誌位);
          在uboot中scan讀取該.txt文件的中的內容(標誌位),然後決定啓動相應的系統。

三、本次主要討論Linux系統和Android共uboot的情況,實現方式爲單獨分出一個分區存儲標誌位。已實現。

     1、要實現雙系統的啓動和相互切換,需要對uboot啓動過程、bootargs引導參數有相應的瞭解。

     2、首先,將uboot,Android系統的kernel和file system,Linux系統的kernel和file system燒寫到emmc中,如下圖所示。
          注意:燒寫的物理位置應與下面講到的bootargs引導參數相對應,否則系統啓動會失敗!!!
                      
 
 圖中爲主要燒寫部分,其他的燒寫按照自己思路稍微調整。
     設置flags分區,存儲我們的啓動標誌位。

     3、對uboot的修改:
          (1)將bootargs引導參數寫入uboot中,並且製作command命令,至於怎樣將製作的command命令放在".u_boot_cmd"段: ,用下面例子講解。

     例子:
     a)在common文件夾下創建cmd_sunplus.c;
     b)在cmd_sunplus.c中添加“sunplus_linuxemmcboot 和sunplus_androidemmcboot”命令的響應函數的實現。具體的實現代碼如下:

//====================================================================
int do_sunplus_linuxemmcboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
    int ret = 0;

    /*①
     設置bootargs引導參數
    //這裏BOOT_TYPE_LINUX_EMMC爲    "console=ttyAMA0,115200 root=/dev/mmcblk0p8 rootfstype=ext4 rootwait blkdevparts=mmcblk0:1M(boot),1M(bootargs),4M(baseparam),4M(pqparam),4M(logo),3058M(unused),8M(kernel),96M(rootfs),1M(flags),-(others) coherent_pool=1M"
     */
    setenv("bootargs", BOOT_TYPE_ANDROID_EMMC );

    /*②
      從emmc中讀取kernel到內存中:起始地址爲0x600000(內核文件存儲的實際物理地址),長度爲0x4000,讀到起始地址爲0x1000000的內存中
   */
    ret = run_command("mmc read 0 0x1000000 0x600000 0x4000" , 0);
    if(ret == -1) {
        printf("read kernel failed.\n");
        sp_failed();
    }

    /* ③
     啓動Linux的kernel
    */
    printf(GREEN"Boot to linux.\n"NONE);
    run_command("bootm 0x1000000" , 0);
    printf("bootm linux sys failed.\n");
    return ret;
}

U_BOOT_CMD(
    sunplus_linuxemmcboot,    1,    0,    do_sunplus_linuxemmcboot,
    "[sunplus app func]:boot up linux from emmc",
    "\n"
);


int do_sunplus_androidemmcboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
    int ret = 0;

    /*①
     設置bootargs引導參數
    //這裏BOOT_TYPE_ANDROID_EMMC爲    "console=ttyAMA0,115200 blkdevparts=mmcblk0:1M(fastboot),1M(bootargs),10M(recovery),2M(deviceinfo),8M(baseparam),8M(pqparam),20M(logo),20M(logobak),40M(fastplay),40M(fastplaybak),40M(kernel),20M(misc),8M(userapi),8M(hibdrv),8M(qbflag),300M(qbdata),800M(system),1024M(userdata),500M(cache),50M(private),50M(sdcard),218M(unused),1M(flags),-(others) coherent_pool=1M"
     */
    setenv("bootargs", BOOT_TYPE_ANDROID_EMMC );

    /*②
      從emmc中讀取kernel到內存中:起始地址爲0x4B000(內核文件存儲的實際物理地址) ,長度爲0x5000,讀到起始地址爲0x1FFBFC0的內存中
   */
    ret = run_command("mmc read 0 0x1FFBFC0 0x4B000 0x5000" , 0);
    if(ret == -1) {
        printf("read kernel failed.\n");
        sp_failed();
    }
    
    /* ③
     啓動Android的kernel
   */
    printf(GREEN"Boot to android.\n"NONE);
    run_command("bootm 0x1FFBFC0" , 0);
    printf("bootm android sys failed.\n");

    return ret;
}

U_BOOT_CMD(
    sunplus_androidemmcboot,    1,    0,    do_sunplus_androidemmcboot,
    "[sunplus app func]:boot up android from emmc",
    "\n"
);
//====================================================================   
     c)將common/cmd_sunplus.c編譯進u-boot.bin,在common/Makefile中加入如下代碼:
          COBJS-$(CONFIG_BOOT_SUNPLUS) += cmd_sunplus.o

     d)在include/configs/hi3798mx.h(代碼相應位置)加入如代碼:
          #define CONFIG_BOOT_SUNPLUS 

     e)重新編譯下載U-Boot就可以使用sunplus_linuxemmcboot 和sunplus_androidemmcboot 命令了
     
     (2)在boot源碼的Main.c中,找到main_loop()函數。

     要實現雙系統啓動,需要在boot啓動階段掃描咱們定義的標誌位,然後啓動相應的系統。下圖是main_loop()函數的掃描標誌位操作在如圖所示位置加入掃描標誌位分區,既能率先掃描分區,又能達到控制Ctrl+C到boot命令下
 
 
 
 
     4、編譯boot,燒寫完成之後啓動系統。
          啓動完成後,在Linux系統下,flags(標誌位分區)是/dev/mmcblock0p9第九分區,在/dev/mmcblock0p9設備文件中寫入“android”,重啓即可切換到Android系統。同理,在Android系統下,flags(標誌位分區)在/dev/block/mmcblock0p23第23分區,在/dev/block/mmcblock0p23設備文件中寫入“linuxaa”,即可切換到Linux系統。
     兩個系統雖然是不同的設備文件名,但都是操作的同一塊物理地址(起始地址爲0x63400)。
     這樣就完成了雙系統的啓動。
 
 
          本文只是一種思路,有更好的請廣大碼友指教!
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章