Linux 4.4内核移植以及Android系统编译

Android预移植到tiny4412

kernel for tiny4412

 前面的文章已经把uboot给弄好了,下面就可以用自己移植的uboot来启动内核了。对于内核的移植,一开始选择的是linux4.4的内核,为什么选4.4,因为开始的时候是想在tiny4412上面跑Android 7.0的,而Android 7.0用4.4的内核比较合适,但是折腾了一段时间后发现,是我想太多了,Android 7.0上的改动还是有点打,平时在公司也比较少接触Android 7.0,所以后来还是改回移植Android 6.0了,但是内核已经能跑起来啦就不换了

 首先是下载内核,内核的下载可以通过下面的指令下载:

git clone https://aosp.tuna.tsinghua.edu.cn/kernel/common.git

下载完后可以通过git branch -a来查看现有的Android可用的kernel版本,接着通过指令:

 git checkout remotes/origin/android-4.4-n-release

来获得Android N支持的kernel 4.4,接下来就是将kernel适配到tiny4412上了,这一部分我也是参照网上的资料来进行的,我使用的Blog教程是这个:
http://www.cnblogs.com/pengdonglin137/tag/TINY4412/default.html?page=1
目前我只移植到MMC部分

 相信各位都了解过,Android使用的Linux kernel和标准的linux kernel是有区别的,例如:标准的Linux kernel可没有binder驱动,为了让我们移植的kernel支持Android的特性,需要执行下面一条执行,将Android的特性写道.config文件中,然后再全编就好了

ARCH=arm scripts/kconfig/merge_config.sh arch/arm/configs/tiny4412_defconfig android/configs/android-base.cfg android/configs/android-recommended.cfg

如果大家觉得麻烦也可以直接到我的Github上面下载:
https://github.com/xiaojimmychen/linux-4.4

Android源码编译

 Android M的代码下载可以通过下面的指令:

repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-6.0.1_r79

使用的是清华大学提供的镜像源,下载速度还是可以的,只是中间容易出现网络断开问题,要一直执行repo sync指令来同步代码而已,所以我写了一个脚本来自动执行这个步骤,下面是代码,大家可以按照自己计算机的cpu核心数改一改数值,当然还是推荐大家按照清华大学镜像源网站上说的,使用4个核心好点;接下来将下面的执行代码保存为start_repo.sh就好了,当然别忘了给start_repo.sh加上执行权限

#!/bin/bash  
echo "======start repo sync======"  
repo sync -j4
while [ $? = 1 ]; do  
        echo "======sync failed, re-sync again======"  
        sleep 3  
        repo sync -j4 
done 

 OK,代码下载完成了,下面可以使用下面的指令来添加对应的板子代码

./device/common/populate-new-device.sh samsung tiny4412

同时在./device/samsung/tiny4412/BoardConfig.mk中添加下面一行

TARGET_CPU_VARIANT := cortex-a9

否则在编译一开始就会出错的。
然后执行

source build/envsetup.sh
lunch

lunch后选择tiny4412开发板就可以了
最后就是执行编译指令了,make -j24 2>&1 | tee build.log

一段时间后,会报错,因为我使用的是Ubuntu16.04下面的错误貌似在高版本的Ubuntu上会出现问题:
out/host/linux-x86/obj32/SHARED_LIBRARIES/libart_intermediates/arch/x86/quick_entrypoints_x86.o:function art_quick_instrumentation_entry: error: unsupported reloc 43
out/host/linux-x86/obj32/SHARED_LIBRARIES/libart_intermediates/arch/x86/quick_entrypoints_x86.o:function art_quick_instrumentation_entry: error: unsupported reloc 43
out/host/linux-x86/obj32/SHARED_LIBRARIES/libart_intermediates/arch/x86/quick_entrypoints_x86.o:function art_quick_instrumentation_exit: error: unsupported reloc 43

不过网上也有解决办法,我的解决办法如下:
It works to me:
in file /art/build/Android.common_build.mk, find out:

ART_HOST_CLANG := false
ifneq ($(WITHOUT_HOST_CLANG),true)
# By default, host builds use clang for better warnings.
ART_HOST_CLANG := true
endif

change to :

ART_HOST_CLANG := false
ifeq ($(WITHOUT_HOST_CLANG),false)
# By default, host builds use clang for better warnings.
ART_HOST_CLANG := true
endif

If it still not works,try this in your android root path:
cp /usr/bin/ld.gold prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.6/x86_64-linux/bin/ld
这里需要注意的是,在拷贝ld.gold的时候要注意,不同Android版本,编译后可能会有两个x86_64-linux-glibc*目录,如果存在两个的话就要将ld.gold拷贝到两个目录下的x86_64/bin/ld,否则还是会继续报错的

 解决完这个问题继续编译,编译一段时间后会报出如下错误:
mkyaffs2image -f out/target/product/tiny4412/data out/target/product/tiny4412/userdata.img out/target/product/tiny4412/root/file_contexts data
Traceback (most recent call last):
File “./build/tools/releasetools/build_image.py”, line 516, in
main(sys.argv[1:])
File “./build/tools/releasetools/build_image.py”, line 509, in main
if not BuildImage(in_dir, image_properties, out_file, target_out):
File “./build/tools/releasetools/build_image.py”, line 326, in BuildImage
(_, exit_code) = RunCommand(build_command)
File “./build/tools/releasetools/build_image.py”, line 46, in RunCommand
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
File “/usr/lib/python2.7/subprocess.py”, line 711, in init
errread, errwrite)
File “/usr/lib/python2.7/subprocess.py”, line 1343, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
build/core/Makefile:1188: recipe for target ‘out/target/product/tiny4412/userdata.img’ failed

一开始,我以为是Ubuntu版本太高,Python版本不同导致,后来细致一看,实在编译userdata.img的时候出现问题的,后来执行mkyaffs2image的时候缺少了参数,解决办法是,在./device/samsung/tiny4412/BoardConfig.mk文件中,添加下面的内容:

TARGET_USERIMAGES_USE_EXT4 := true
BOARD_SYSTEMIMAGE_PARTITION_SIZE := 1073741824
# BOARD_USERDATAIMAGE_PARTITION_SIZE := 13287555072
BOARD_CACHEIMAGE_PARTITION_SIZE := 268435456
BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4
BOARD_FLASH_BLOCK_SIZE := 4096

大家定义的变量的名字应该就知道是干什么用的了,这里我就不多说了,继续编译,这次应该就能编译ok了。

后续修改

 编译OK后,要怎么放到SD卡上来启动开发板呢,这个问题我也是废了不少时间才搞明白的。

 第一步我们想将SD卡进行分区,分区表如下:
Linux 4.4内核移植以及Android系统编译_第1张图片

 第二步,根据启动流程,uboot到kernel再到init进程,uboot和kernel都没问题了,那么init进程要怎么设置才行呢?我们可以看到Android源码编译后,out目录下会有个root文件夹,init进程就在里面,init进程也有了,后续的system、data分区怎么挂上区呢,这个就是问题所在了,所以接下来我们要修改一下Android的源码。

在device/samsung/tiny4412目录下添加两个文件,分别是:fstab.tiny4412 和 init.tiny4412.rc

init.tiny4412.rc的内容如下:

on early-init
    mount debugfs debugfs /sys/kernel/debug
on fs
    mount_all /fstab.tiny4412

fstab.tiny4412的内容如下:

# Android fstab file.
#                                                           <type>    and options>                              
# The filesystem that contains the filesystem checker binary (typically /system) cannot
# specify MF_CHECK, and must come before any filesystems that do specify MF_CHECK
/dev/block/mmcblk0p3                                    /system             ext4      ro,barrier=1                                         wait
/dev/block/mmcblk0p5                                    /data               ext4      noatime,nosuid,nodev,barrier=1,nomblk_io_submit      wait,check
/dev/block/mmcblk0p6                                   /cache              ext4      noatime,nosuid,nodev  wait,check

有了这两个文件,还要修改一下device.mk文件:

LOCAL_FSTAB := $(LOCAL_PATH)/fstab.tiny4412

PRODUCT_COPY_FILES := \
    $(LOCAL_KERNEL):kernel \
    $(LOCAL_FSTAB):root/fstab.tiny4412 \
    $(LOCAL_PATH)/init.tiny4412.rc:root/init.tiny4412.rc

同时还要修改system/core/rootdir文件夹下的init.rc文件,将init.tiny4412.rc文件给import进去

import /init.tiny4412.rc
import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
......

上面的内容一看应该就能明白了,我就不多解释了
然后执行make -24编译一下

接下来就是将编译出来的内容拷贝到SD卡了,将root目录下的内容拷贝到SD卡的init分区,但是system分区的内容就没有那么简单了,首先我们要通过下面的指令将system.img弄成ext4格式的,然后再将其挂载在一个tmp目录下,再将其拷贝到sd卡的system分区,所用指令如下:

simg2img system.img system-ext4.img
mkdir tmp
sudo mount system-ext4.img tmp/
cd tmp
cp * /media/jimmy/system -rpf

拷贝完之后将SD卡插到开发板上,上电,进入uboot命令行模式,设置一下uboot的bootcmd和bootargs的指令如下:

setenv bootargs "rootwait console=ttySAC0,115200n8 root=/dev/mmcblk0p2 rw init=/init vmalloc=400M androidboot.console=ttySAC0 androidboot.selinux=permissive"

setenv bootcmd "load mmc 0 0x40007000 uImage; load mmc 0 0x48000000 exynos4412-tiny4412.dtb; bootm 0x40007000 - 0x48000000"

saveenv

然后就可以启动开发板了,发现并不能启动,留意到下面一条log
[ 3.113314] init: skipping insecure file ‘/init.rc’
init.rc insecure file,百度说不应该赋予其写的权限,看来还得修改一下init分区下的内容:
在sd卡init分区下执行下面三条指令:

chmod a-w init.*
chmod a-w ueventd.rc 
chmod a-w fstab.tiny4412

执行完后再启动开发板
启动之后以为就可以了吗?其实只是刚刚开始,你会发现有很多log,其中主要的log如下:


[    9.814258] init: Service 'surfaceflinger' (pid 1649) killed by signal 6
[    9.814342] init: Service 'surfaceflinger' (pid 1649) killing any children in process group
[   14.820593] init: Warning!  Service vold needs a SELinux domain defined; please fix!
[   14.820762] init: Starting service 'vold'...
[   14.823152] init: Warning!  Service surfaceflinger needs a SELinux domain defined; please fix!
[   14.823384] init: Starting service 'surfaceflinger'...
[   14.827299] init: Warning!  Service media needs a SELinux domain defined; please fix!
[   14.832057] init: Starting service 'media'...
[   14.881607] init: Service 'vold' (pid 1672) exited with status 1
[   14.881845] init: Service 'vold' (pid 1672) killing any children in process group
[   14.962791] init: Service 'media' (pid 1674) exited with status 1
[   14.963030] init: Service 'media' (pid 1674) killing any children in process group
[   15.263813] init: Service 'surfaceflinger' (pid 1673) killed by signal 6
[   15.263901] init: Service 'surfaceflinger' (pid 1673) killing any children in process group
[   19.269313] init: Warning!  Service vold needs a SELinux domain defined; please fix!
[   19.269528] init: Starting service 'vold'...
[   19.273084] init: Warning!  Service surfaceflinger needs a SELinux domain defined; please fix!
[   19.273356] init: Starting service 'surfaceflinger'...
[   19.276680] init: Warning!  Service media needs a SELinux domain defined; please fix!
[   19.280775] init: Starting service 'media'...
[   19.323515] init: Service 'vold' (pid 1680) exited with status 1
[   19.323631] init: Service 'vold' (pid 1680) killing any children in process group
[   19.352518] init: Service 'media' (pid 1682) exited with status 1
[   19.352635] init: Service 'media' (pid 1682) killing any children in process group
[   19.668469] init: Service 'surfaceflinger' (pid 1681) killed by signal 6
[   19.668576] init: Service 'surfaceflinger' (pid 1681) killing any children in process group

就是surfaceflinger灯service不断的重启,我想应该因为我还没有移植LCD驱动,导致surfacefliger无法执行,surfaceflinger无法正常启动,导致后续同一个class的service也无法启动

接下来,我会花一段时间来阅读LDD3,写一下Linux的驱动,同时也看看怎么解决这个surfaceflnger不断重启的问题,但愿可以解决吧

你可能感兴趣的:(Android,for,tiny4412)