构建 Android Marshmallow

本指南提供了构建 Android Marshmallow 镜像以及适用于 gem5 的内核和 .dtb 文件的详细分步说明。

概述

要在 gem5 中成功运行 Android,需要镜像、兼容的内核和为模拟器配置的设备树 blob.dtb 文件。本指南展示了如何使用支持 Mali 的 3.14 内核构建 Android Marshmallow 32 位版本。将来将添加关于如何构建支持 Mali 的 4.4 内核的额外部分。

先决条件

本指南假设使用运行 14.04 LTS Ubuntu 的 64 位系统。在开始之前,首先正确设置系统很重要。为此,需要通过 shell 安装以下软件包。

提示:始终在 Android 构建页面检查最新的先决条件。

更新并安装所有依赖项。这可以通过以下命令完成:

sudo apt-get update

sudo apt-get install openjdk-7-jdk git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache libgl1-mesa-dev libxml2-utils xsltproc unzip

此外,确保正确安装了 repo (说明在此)

确保默认 JDK 是 OpenJDK 1.7:

javac -version

要交叉编译内核(32 位)和设备树,我们需要安装以下软件包:

sudo apt-get install gcc-arm-linux-gnueabihf device-tree-compiler

在开始之前,作为最后一步,确保拥有 32 位 ARM 的 gem5 二进制文件和 busybox。

对于 gem5 二进制文件,只需从您的 gem5 目录开始执行以下操作:

cd util/m5
make -f Makefile.arm
cd ../term
make
cd ../../system/arm/simple_bootloader/
make

对于 busybox,您可以在此处找到指南 here

构建 Android

我们使用基于 Pixel C 发布的 AOSP 运行构建来构建 Android Marshmallow。AOSP 提供其他构建,这些构建未使用本指南进行测试。

提示:与 repo 同步将需要很长时间。使用 -jN 标志来加速 make 过程,其中 N 是要运行的并行作业数。

创建目录并拉取 Android 仓库:

mkdir android
cd android
repo init --depth=1 -u https://android.googlesource.com/platform/manifest -b android-6.0.1_r63
repo sync -c -jN

在开始 AOSP 构建之前,您需要对构建系统进行一项更改以启用构建 libion.so,它由 Mali 驱动程序使用。编辑文件 aosp/system/core/libion/Android.mk,将 libion 的 LOCAL_MODULE_TAGS 从 ‘optional’ 更改为 ‘debug’。以下是 repo diff 的输出:

  --- a/system/core/libion/Android.mk
  +++ b/system/core/libion/Android.mk
  @@ -3,7 +3,7 @@ LOCAL_PATH := $(call my-dir)
  include $(CLEAR_VARS)
  LOCAL_SRC_FILES := ion.c
  LOCAL_MODULE := libion
  -LOCAL_MODULE_TAGS := optional
  +LOCAL_MODULE_TAGS := debug
  LOCAL_SHARED_LIBRARIES := liblog
  LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/kernel-headers
  LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
  $(LOCAL_PATH)/kernel-headers

源环境设置并构建 Android:

提示:为了 root 访问和”可调试性”[原文如此],我们选择 userdebug。构建可以在不同模式下完成,如此处所示。 提示:构建 Android 将需要很长时间。使用 -jN 标志来加速 make 过程,其中 N 是要运行的并行作业数。

确保在 bash shell 中执行此操作。

source build/envsetup.sh
lunch aosp_arm-userdebug
make -jN

创建 Android 镜像

构建成功后,我们创建 Android 镜像并添加为 gem5 配置系统的 init 文件和二进制文件。以下示例创建一个 3GB 镜像。

提示:如果您想添加应用程序或数据,请使镜像足够大以容纳构建和任何其他要写入其中的内容。

创建一个空镜像以刷入 Android 构建,并将镜像附加到回环设备:

dd if=/dev/zero of=myimage.img bs=1M count=2560
sudo losetup /dev/loop0 myimage.img

我们现在需要创建三个分区:AndroidRoot (1.5GB)、AndroidData (1GB) 和 AndroidCache (512MB)。

首先,对设备进行分区:

sudo fdisk /dev/loop0

更新分区表:

sudo partprobe /dev/loop0

命名分区 / 将文件系统定义为 ext4:

sudo mkfs.ext4 -L AndroidRoot /dev/loop0p1
sudo mkfs.ext4 -L AndroidData /dev/loop0p
sudo mkfs.ext4 -L AndroidCache /dev/loop0p3

将 Root 分区挂载到目录:

sudo mkdir -p /mnt/androidRoot
sudo mount /dev/loop0p1 /mnt/androidRoot

将构建加载到分区:

cd /mnt/androidRoot
sudo zcat <path/to/build/android>/out/target/product/generic/ramdisk.img | sudo cpio -i
sudo mkdir cache
sudo mkdir /mnt/tmp
sudo mount -oro,loop <path/to/build/android>/out/target/product/generic/system.img /mnt/tmp
sudo cp -a /mnt/tmp/* system/
sudo umount /mnt/tmp

gem5 Android KitKat 页面下载并解压必要的覆盖层,并对 init.gem5.rc 文件进行以下更改。以下是 repo diff 的输出:

  --- /kitkat_overlay/init.gem5.rc
  +++ /m_overlay/init.gem5.rc
  @@ -1,21 +1,13 @@
  +
   on early-init
       mount debugfs debugfs /sys/kernel/debug

   on init
  -    export LD_LIBRARY_PATH ${LD_LIBRARY_PATH}:/vendor/lib/egl
  -
  -    # See storage config details at http://source.android.com/tech/storage/
  -    mkdir /mnt/media_rw/sdcard 0700 media_rw media_rw
  -    mkdir /storage/sdcard 0700 root root
  +    # Support legacy paths
  +    symlink /sdcard /mnt/sdcard
       chmod 0666 /dev/mali0
       chmod 0666 /dev/ion
  -
  -    export EXTERNAL_STORAGE /storage/sdcard
  -
  -    # Support legacy paths
  -    symlink /storage/sdcard /sdcard
  -    symlink /storage/sdcard /mnt/sdcard

   on fs
       mount_all /fstab.gem5
  @@ -60,7 +52,6 @@
       group root
       oneshot

  -# fusewrapped external sdcard daemon running as media_rw (1023)
  -service fuse_sdcard /system/bin/sdcard -u 1023 -g 1023 -d
  /mnt/media_rw/sdcard /storage/sdcard
  +service fingerprintd /system/bin/fingerprintd
       class late_start
  -    disabled
  +    user system

添加 Android 覆盖层并配置其权限:

sudo cp -r <path/to/android/overlays>/* /mnt/androidRoot/
sudo chmod ug+x /mnt/androidRoot/init.gem5.rc
/mnt/androidRoot/gem5/postboot.sh

在 sbin 目录下添加 m5 和 busybox 二进制文件并使它们可执行:

sudo cp <path/to/gem5>/util/m5/m5 /mnt/androidRoot/sbin
sudo cp <path/to/busybox>/busybox /mnt/androidRoot/sbin
sudo chmod a+x /mnt/androidRoot/sbin/busybox /mnt/androidRoot/sbin/m5

使目录可读和可搜索:

sudo chmod a+rx /mnt/androidRoot/sbin/ /mnt/androidRoot/gem5/

删除启动动画:

sudo rm /mnt/androidRoot/system/bin/bootanimation

此处下载并解压适用于 gem5 Android 4.4 的 Mali 驱动程序。然后,为驱动程序创建目录并复制它们:

sudo mkdir -p /mnt/androidRoot/system/vendor/lib/egl
sudo mkdir -p /mnt/androidRoot/system/vendor/lib/hw
sudo cp <path/to/userspace/Mali/drivers>/lib/egl/libGLES_mali.so /mnt/androidRoot/system/vendor/lib/egl
sudo cp <path/to/userspace/Mali/drivers>/lib/hw/gralloc.default.so /mnt/androidRoot/system/vendor/lib/hw

更改权限

sudo chmod 0755 /mnt/androidRoot/system/vendor/lib/hw
sudo chmod 0755 /mnt/androidRoot/system/vendor/lib/egl
sudo chmod 0644 /mnt/androidRoot/system/vendor/lib/egl/libGLES_mali.so
sudo chmod 0644 /mnt/androidRoot/system/vendor/lib/hw/gralloc.default.so

卸载并删除回环设备:

cd /..
sudo umount /mnt/androidRoot
sudo losetup -d /dev/loop0

构建内核 (3.14)

成功设置镜像后,需要构建兼容的内核并生成 .dtb 文件。

克隆包含 gem5 特定内核的仓库:

git clone -b ll_20140416.0-gem5 https://github.com/gem5/linux-arm-gem5.git

<path/to/kernel/repo>/arch/arm/configs/vexpress_gem5_defconfig 处的内核 gem5 配置文件进行以下更改。以下是 repo diff 的输出:

  --- a/arch/arm/configs/vexpress_gem5_defconfig
  +++ b/arch/arm/configs/vexpress_gem5_defconfig
  @@ -200,4 +200,15 @@ CONFIG_EARLY_PRINTK=y
  CONFIG_DEBUG_PREEMPT=n
  # CONFIG_CRYPTO_ANSI_CPRNG is not set
  # CONFIG_CRYPTO_HW is not set
  +CONFIG_MALI_MIDGARD=y
  +CONFIG_MALI_MIDGARD_DEBUG_SYS=y
  +CONFIG_ION=y
  +CONFIG_ION_DUMMY=y
  CONFIG_BINARY_PRINTF=y
  +CONFIG_NET_9P=y
  +CONFIG_NET_9P_VIRTIO=y
  +CONFIG_9P_FS=y
  +CONFIG_9P_FS_POSIX_ACL=y
  +CONFIG_9P_FS_SECURITY=y
  +CONFIG_VIRTIO_BLK=y
  +CONFIG_VMSPLIT_3G=y
  +CONFIG_DNOTIFY=y
  +CONFIG_FUSE_FS=y

对于设备树,添加 Mali GPU 设备并将内存增加到 1.8GB。在 <path/to/kernel/repo>/arch/arm/boot/dts/vexpress-v2p-ca15-tc1-gem5.dts. 处进行以下更改。以下是 repo diff 的输出:

  --- a/arch/arm/boot/dts/vexpress-v2p-ca15-tc1-gem5.dts
  +++ b/arch/arm/boot/dts/vexpress-v2p-ca15-tc1-gem5.dts
  @@ -45,7 +45,7 @@

           memory@80000000 {
                   device_type = "memory";
  -                reg = <0 0x80000000 0 0x40000000>;
  +                reg = <0 0x80000000 0 0x74000000>;
           };

          hdlcd@2b000000 {
  @@ -59,6 +59,14 @@
  //                mode = "3840x2160MR-16@60"; // UHD4K mode string
                    framebuffer = <0 0x8f000000 0 0x01000000>;
            };
  +
  +    gpu@0x2d000000 {
  +        compatible = "arm,mali-midgard";
  +        reg = <0 0x2b400000 0 0x4000>;
  +        interrupts = <0 86 4>, <0 87 4>, <0 88 4>;
  +        interrupt-names = "JOB", "MMU", "GPU";
  +    };
  +
  /*
          memory-controller@2b0a0000 {
                    compatible = "arm,pl341", "arm,primecell";

此处下载并解压适用于 gem5 的用户空间匹配 Mali 内核驱动程序。将它们复制到 gpu 驱动程序目录:

cp -r <path/to/kernelspace/Mali/drivers>/driver/product/kernel/drivers/gpu/arm/ drivers/gpu

根据以下差异,在 <path/to/kernelspace/Mali/drivers>/drivers/video/Kconfig<path/to/kernelspace/Mali/drivers>/drivers/gpu/Makefile 中进行以下更改:

Here is the output of the Kconfig repo diff:

  --- a/drivers/video/Kconfig
  +++ b/drivers/video/Kconfig
  @@ -23,6 +23,8 @@ source "drivers/gpu/host1x/Kconfig"

  source "drivers/gpu/drm/Kconfig"

  +source "drivers/gpu/arm/Kconfig"
  +
   config VGASTATE
          tristate
          default n

Here is the output of the drivers/gpu/Makefile repo diff:

  --- a/drivers/gpu/Makefile
  +++ b/drivers/gpu/Makefile
  @@ -1,2 +1,2 @@
  -obj-y                += drm/ vga/
  +obj-y                += drm/ vga/ arm/

最后,构建内核和 .dtb 文件。

提示:使用 -jN 标志来加速 make 过程,其中 N 是要运行的并行作业数。

构建内核:

make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm vexpress_gem5_defconfig
make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm vmlinux -jN

创建 .dtb 文件:

dtc -I dts -O dtb arch/arm/boot/dts/vexpress-v2p-ca15-tc1-gem5.dts > vexpress-v2p-ca15-tc1-gem5.dtb

测试构建

对 example/fs.py 进行以下更改。以下是 repo diff 的输出:

  --- a/configs/example/fs.py Thu Jun 02 20:34:39 2016 +0100
  +++ b/configs/example/fs.py Fri Jun 10 15:37:29 2016 -0700
  @@ -144,6 +144,13 @@
       if is_kvm_cpu(TestCPUClass) or is_kvm_cpu(FutureClass):
           test_sys.vm = KvmVM()

  +    test_sys.gpu = NoMaliGpu(
  +        gpu_type="T760",
  +        ver_maj=0, ver_min=0, ver_status=1,
  +        int_job=118, int_mmu=119, int_gpu=120,
  +        pio_addr=0x2b400000,
  +        pio=test_sys.membus.master)
  +
      if options.ruby:
          # Check for timing mode because ruby does not support atomic accesses
          if not (options.cpu_type == "detailed" or options.cpu_type == "timing"):

以及对 FS 配置的更改以启用或禁用软件渲染。

  --- a/configs/common/FSConfig.py Thu Jun 02 20:34:39 2016 +0100
  +++ b/configs/common/FSConfig.py Thu Jun 16 10:23:44 2016 -0700
  @@ -345,7 +345,7 @@

             # release-specific tweaks
             if 'kitkat' in mdesc.os_type():
  -                cmdline += " androidboot.hardware=gem5 qemu=1 qemu.gles=0 " + \
  +                cmdline += " androidboot.hardware=gem5 qemu=1 qemu.gles=1 " + \
                            "android.bootanim=0"

         self.boot_osflags = fillInCmdline(mdesc, cmdline

设置以下 M5_PATH:

M5_PATH=. build/ARM/gem5.opt configs/example/fs.py --cpu-type=atomic --mem-type=SimpleMemory --os-type=android-kitkat --disk-image=myimage.img --machine-type=VExpress_EMM --dtb-filename=vexpress-v2p-ca15-tc1-gem5.dtb -n 1 --mem-size=1800MB

构建旧版本的 Android

gem5 支持运行甚至更旧版本的 Android,如 KitKat。执行此操作的文档以及所需的必要驱动程序和文件可以在旧 wiki 此处找到。