原创

【原创】【笔记】在QEMU中模拟手机AOSP开发全流程

温馨提示:
本文最后更新于 2024年10月13日,已超过 70 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我
  • 作者:Mosect
  • 最后更新:2024年10月12日
  • 注1:此文章只会列出不同时间段的思路简略信息
  • 注2:当前文章处于长期更新中,如果某个链接不能跳转,则表示此文章还在编写中

详细文章列表:

全流程目录

整体思路

2024年10月12日

1. QEMU的使用

把QEMU启动的实例看成一台手机,那么我们至少需要模拟以下设备硬件:

  1. 磁盘(相当于手机的eMMC内部存储器)
  2. 屏幕
  3. 键盘、鼠标(因为是电脑,所有鼠标相当于触屏)
  4. 声卡(声音输出)

qemu都支持这些硬件的模拟,我们只需在启动QEMU时,传递相关参数即可。

Windows平台上安装和运行QEMU

2. BIOS

QEMU实例相当于一台实体机器,启动也必然会执行一段初始化代码,这段程序我们称其为BIOS。

BIOS也有不同的选择,不同硬件厂商会根据生产的硬件编写出适合硬件使用的BIOS。现在电脑或者手机多数使用UEFI BIOS这种标准的BIOS程序,因此我这里也是选择UEFI BIOS程序。

那么问题来了?我们需要自己写BIOS程序吗?

答案是可以,但没必要。有一套现成的UEFI BIOS方案,叫EDK2。而且,EDK2本身就支持QEMU模拟器,因此我们只需编译EDK2的QEMU模块代码,让QEMU启动即可。

edk2开源项目

使用edk2为qemu编译UEFI BIOS

3. Bootloader

机器通电启动BIOS后,用户并不能操作各种硬件,他只是个初始启动程序,功能非常有限,因此需要启动更强大的程序来管理、操作硬件:操作系统(OS)。

传统BIOS启动后,会根据用户的配置,寻找合适的启动设备(比如,你把CD/DVD设备放在启动第一位置,bios就会优先从CD/DVD寻找启动对象)。我们大多数人的电脑都会被设置成从第一块硬盘启动。

UEFI BIOS启动方式有所不同,他会识别所有的存储设备分区配置,如果发现是FAT32格式(或其他UEFI能识别的)分区,并且在此分区指定路径下,发现启动程序文件,则会把此分区当成可启动分区。这些可启动分区根据用户配置的优先级进行排序,然后启动第一个分区里的程序。

但是,不管是传统BIOS还是UEFI BIOS,启动的都不是操作系统本身,而是启动一个叫Bootloader的程序,让Bootloader程序去启动操作系统。

对于Android系统来说,其内核就是Linux系统,因此我们需要自己去写一个Bootloader程序,去启动Linux系统。

Android Bootloader实现

4. Linux内核

启动Linux系统,那必然需要一个编译好的Linux系统程序文件。对于Android来说,使用的内核和原生的Linux内核有些不一样,我们不能直接在Linux内核官网下载和编译,需要去AOSP官网下载Google提供的Android Linux内核,编译。在Google提供的内核源码,是支持QEMU的(Android SDK里带的虚拟机就是QEMU),我们可以直接编译相关版本内核即可。

Android Linux内核

编译Android Linux内核

5. 启动Linux内核

启动Linux可能不难,查找一些文档即可。但是启动符合Android标准的Linux内核,就有些麻烦。但是谷歌还是提供了比较详细的文档:

引导加载程序

分区

我们需要建立符合Android最新标准的分区,传递Android标准的Linux启动参数。这里需要自己去识别不同分区的内容,把Linux内核、Ramdisk、Bootconfig等数据按照Android内核的标准,放到运动内存中。

6. 将Android系统安装到QEMU虚拟磁盘中

如果Bootloader程序和分区建立没问题,那么Linux系统应该能成功启动。启动后,是进不了Android系统的,因为我们只是建立好分区和启动了Linux系统,缺少linux的init程序(初始化程序)。这个init程序就相当于Android系统的入口程序。因此我们需要编译出整个Android系统,然后将Android系统安装到QEMU虚拟磁盘。

AOSP项目官网

编译Android系统

现在问题又来了,如何安装到QEMU虚拟磁盘?

在手机中,一般都是官方提供一个固件包,然后手机进入bootloader模式、recovery模式或者fastboot模式进行安装。那么,QEMU也可以采用此方法。

注意:这里出现一个fastboot和bootloader。在旧版本的Android,这两个是一个东西,都叫bootloader,因为fastboot都是由厂商在bootloader里实现的。新版的Android不一样:谷歌把recovery和fastboot合并启动,统一到了recovery模式中,根据启动原因(可以理解为启动参数),进入fastboot模式或者recovery模式。

这就表示,我们写的bootloader程序可以不去实现fastboot功能,仅仅是启动linux系统就可以了,这会省下不少功夫。

7 未完待续

正文到此结束