Firefly开源社区

ubuntu&android双系统制作过程

208

积分

13

威望

10

贡献

技术达人

Rank: 2

积分
208
发表于 2017-2-22 11:42:56     
ubuntu&android双系统制作过程


同样站在巨人的肩膀上总结制作过程,参(nian)考(tie)这个版主点击跳转



硬件:rk3288cpu maligpu
软件:ubuntu16.04 & android4.4

双系统原理简单介绍:

android系统分区详解:
分区大小(字节)分区名称
4Muboot
4Mmisc
16Mresource
16Mkernel
32Mboot
32Mrecovery
52Mbackup
128Mcache
4Mkpanic
768Msystem
4Mmetadata
1Guserdata
64Mradical_update
总容量-2152Muser


首先了解下android在进入急救模式时,或者说恢复出厂设置的时候都会去加载recovery分区里的内容,原本recovery分区就放着一个急救内核用来升级、恢复所用。目前双系统的原理的要点就是把启动ubuntu的内核放到recovery分区,这样只要androidjinru急救模式,就相当于切换到recovery分区执行ubuntu的kernel,最终成功引导ubuntu 根文件系统。
而正常情况下,开机是不会跑到recovery分区的,一般是uboot阶段会去加载misc分区,读取当中的字段,然后判断是否要加载recovery分区,misc.Img字段如下:
用 hexdump 命令可以方便地查看 misc.img 的内容:
  • $ hexdump -C rkst/Image/misc.img
  • 00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
  • *
  • 00004000  62 6f 6f 74 2d 72 65 63  6f 76 65 72 79 00 00 00  |boot-recovery...|
  • 00004010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
  • *
  • 00004040  72 65 63 6f 76 65 72 79  0a 2d 2d 77 69 70 65 5f  |recovery.--wipe_|
  • 00004050  61 6c 6c 00 00 00 00 00  00 00 00 00 00 00 00 00  |all.............|
  • 00004060  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
  • *
  • 0000c000
复制代码

可见,前 16K (0x4000) 字节都是 0,然后是一个 "boot-recovery" 命令,后面又跟着 "recovery", "--wipe_all" 这些动作和参数。

启动加载器(bootloader, 这里是 u-boot),会读出这个分区的内容,如果是 "boot-recovery",则加载 recovery 分区,则进入了ubuntu系统;如果不是的话,直接加载kernel分区,进入了android系统。

所以要实现双系统的切换,只要实现向misc分区里面读写标志即可,即有下面的两种方法:

android->ubuntu : 向misc分区写入 boot-recovery的标志
ubuntu->android : 清空misc分区的内容

具体实现方案:
1.如何从android进入 Linux

接下来的事情是解决如何进入 Linux, 因为我们将 Linux 放在 recovery 分区,因此,问题等价于如何进入安卓的急救模式。以下有几种方式:

  • 拔掉 USB 线,按住开发板的 recovery 键开机(无论是初次上电、重启或按 reset 键开机都可以)。这是临时性的切换,下次开机不按,还是会进入 Linux 。
  • 在安卓系统的设置里选择恢复出厂设置。实际上,恢复出厂设备这个功能已被阉割了,重启后会进入 Linux。
  • Firefly-RK3288 在安卓系统的关机菜单(点底部工具栏的关机按钮进入)增加了一项切换系统的选择,非常人性化。当然,它是检测到 linuxroot 分区才会出现,也就是说单系统是不会出现的。
  • 将 SDK 里的 rkst/Image/misc.img  刷进到 misc 分区。

2~4 项都是通过写 misc 分区,达到切换到 recovery,这里也即是 Linux 的目的。我这边制作过程中才用点选恢复出厂设置的方法进入ubuntu系统。

2.如何从 Linux 切换回 Android

很简单,写个脚本将 misc 分区清空,然后重启即可:
  • sudo dd if=/dev/zero of=/dev/block/mtd/by-name/misc bs=16k count=3
  • sudo reboot
复制代码

制作过程:
ubuntu根文件系统制作:
首先得有一个得以正常使用的ubuntu固件,之前的文档有讲述如何制作ubuntu 根文件系统。也就是现在你先运行一个单ubuntu系统的固件,在此基础上修改。在~目录下创建 b2android.sh
在里面添加以下内容:
sudo dd if=/dev/zero of=/dev/block/mtd/by-name/misc bs=16k count=3
   echo ; sleep 1
   sudo sync
   echo;  sleep 1
   sudo reboot

加上执行权限chmod +x b2android.sh

我们在 Linux 的根文件系统里增加了一个标志文件 /firstboot 。当 Linux 启动,检测到此文件存在,便判断这是第一次启动,需要做以下安卓系统的初始化动作:
  • 使用 resize2fs 扩展根文件系统,修正文件系统的容量信息
  • 格式化 userdata 分区
  • 格式化 cache 分区
  • 格式化 metadata 分区
  • 格式化 user 分区
  • 删除标志文件 /firstboot
  • 重启回安卓系统

实现细节在在 /etc/rc.local,具体开机会执行的脚本first-boot-recovery.sh中修改成下面这样:

#!/bin/bash

clean_first_boot () {
    rm -f /firstboot 2>/dev/null
    sync
}

android_recovery () {
    echo "=======Formatting userdata(/data)..."
    mkfs.ext4 /dev/block/mtd/by-name/userdata

    echo "=======Formatting metadata(/metadata)..."
    mkfs.ext4 /dev/block/mtd/by-name/metadata

    echo "=======Formatting cache(/cache)..."
    mkfs.ext4 /dev/block/mtd/by-name/cache

    if [ "$1" == "all" ]; then
        echo "=======Formatting user(/sdcard)..."
        for ((i=1;i<5;i++)); do
            if mkfs.vfat /dev/block/mtd/by-name/user; then
                break
            fi
            if grep -q "$(readlink -f /dev/block/mtd/by-name/user)" /proc/mounts; then
                umount /dev/block/mtd/by-name/user
            fi
            sleep 1
            echo "=======Retry: %i..."
        done
    fi

    clean_first_boot

    # reboot to android
    dd if=/dev/zero of=/dev/block/mtd/by-name/misc bs=16k count=3
    sync
    reboot
}

if [ -e /firstboot ]; then
    echo "======Expanding the rootfs..."
    resize2fs /dev/block/mtd/by-name/linuxroot
    if [ -e /dev/block/mtd/by-name/system ]; then
        android_recovery all
    else
        rm -f /usr/local/bin/b2android*  \
           /usr/share/applications/b2android.desktop \
           /home/firefly/Desktop/b2android.desktop
    fi
    clean_first_boot
elif grep firefly-recovery /dev/block/mtd/by-name/misc >/dev/null 2>&1; then
    android_recovery
fi


具体开机脚本参考:点击跳转
ok之后打包ubuntu固件,方法可参考:点击跳转

其实ubuntu只要做两件事,第一次刷完机启动时做了原本android该做的格式化工作;还有就是添加一个切换到android的脚本。

android源码不做任何修改。在打包时注意就可以。

打包过程:

简单暴力的方法:把官方的双系统固件下载下来然后出了一些打包脚本和可执行文件,其他全部换成自己东西。
下面是我截取出来的可用文件下载地址:
http://pan.baidu.com/s/1gf0wScb

然后可以把自己的misc.img boot.img system.img kernel.img resource.img linux-rootfs.img  linux-boot.img 放进这个文件夹,然后点击mkupdate.bat 就能生成固件了。另外根据需求可自行修改parameter的分区大小,我这边将linuxroot修改为4g大的空间。

注意点:
1.ubuntu和android的kernel是否一定要求同一份源码编译?
经试验,可以不同源码编译而成,当这边只有一个resource分区而且只能是android用的,所以要想用两个不同的kernel,linux-boot.img的打包方式就要将ubuntu所需的resource,img也打包进去:

mkbootimg --kernel zImage --ramdisk initrd.img --second resource.img -o linux-boot.img


这样可以使得ubuntu kernel和android kernel分离开来,互不影响。

2.有时从android切到ubuntu后,执行reboot后又回到android系统
这种情况有可能就是misc分区又被清空了,导致uboot阶段没有加载recovery分区,解决方法是ubuntu开机脚本中加入
sudo dd if=/usr/local/bin/misc.img of=/dev/block/mtd/by-name/misc bs=16k count=3
其中misc.img就是android编译出来的misc.img,直接拷到对应目录下,给其读写权限即可。




回复

使用道具 举报

3747

积分

17

威望

18

贡献

官方团队

Rank: 9Rank: 9Rank: 9

积分
3747
发表于 2019-6-13 19:04:23     
好贴
回复

使用道具 举报

66

积分

0

威望

0

贡献

技术小白

积分
66
发表于 2019-6-14 14:26:45     
厉害了,相当不错,谢谢!
回复

使用道具 举报

5

积分

0

威望

0

贡献

吃瓜的群众

积分
5
发表于 7 天前     
牛逼
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

友情链接 : 爱板网 电子发烧友论坛 云汉电子社区 粤ICP备14022046号-2
快速回复 返回顶部 返回列表