双系统启动的方式不止一种。
一、对于双系统的启动镜像来说:
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)。 这样就完成了双系统的启动。 本文只是一种思路,有更好的请广大码友指教!
二、双系统启动和相互切换的实质是设置标志位,在启动时读取标志位信息从而启动相应的系统!下面是两种实现方式。 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)。 这样就完成了双系统的启动。 本文只是一种思路,有更好的请广大码友指教!
更多推荐
实现Linux/Android双系统启动和重启切换的一个思路
发布评论