您的位置:首页 > 编程语言

Msm8960(APQ8064)平台的MSM-AOSP-kitkat编译适配(4):验证代码并编写自己的device

2015-02-22 01:08 369 查看
前面花了那么多篇幅做准备,直到此篇才开始真正开始讲适配,读者一定很激动,但先不要高兴得太早,笔者必须先提出一个声明,虽然此系列文章不要求读者有编程基础,但理所当然的不具备者在适配时难度更大(只能靠经验和资料);而具备编程基础的读者也不要高兴得太早,其实很多时候适配并非靠技术,而是靠不懈的毅力。

注意:初次适配者,如果仅靠本系列文章的解惑,依照个人能力、悟性、业余时间的差别,没有2~6个月或更长的时间,是无法做完整个适配过程的。

一、验证编译环境是否正确

首先以高通的内核以及高通提供的范例device来做一次完整编译,以验证开发环境是否OK

在msm-aosp_LNX.LA.2.7-05010-8960.0目录右键打开终端

source build/envsetup.sh
lunch
输入msm8960所在行的编号,比如8. msm8960-userdebug,那么就输入8并回车
make otapackage –j5


这里-j5代表编译使用5个线程,如果是i7则可以使用9个线程,具体依cpu自身线程数读者自行确定

如果没有错误,最后会生成msm8960-ota-eng.root.zip类似这样刷机包

二、验证手机内核版本与msm-aosp系统版本是否匹配

msm-aosp编译系统在进行编译时会引用内核的一些变量,如果版本对不上,编译会出错。

想必读者早早就下载好了手机的官方提供的内核源代码,这步就可以用上它了。

本文及之后的适配教程就以泛泰手机Vega_IM-A870L为例子,所以这个手机的内核代码就必须去泛泰官方的开源站点去下载。

高通的kernel与手机的kernel是不一样的,高通的kernel只是用于高通的骁龙开发板(笔者猜测),而一般手机kernel会在高通kernel的基础上添加许多芯片驱动(当然各家手机公司用的不一样,这个并没有什么统一的标准)

1.放置手机官方内核源代码

首先把aosp源代码目录的kernel文件夹删除。

然后把官方提供的内核代码解压,按照之前的kernel目录结构放置

必须注意的是,msm-aosp编译系统不提供像cm那样的多层目录结构以支持多机型多内核让你可在选device时选中对应的内核。aosp只有kernel这个目录,所以要是未来还要适配其它机型,你仍然得替换这个目录。当然如果读者未来有能力了,参照cm去更改编译系统以支持多个内核源代码就更好了。

2.内核配置文件

然后下一步就要找内核的配置文件名,一般官方内核代码解压后,可以在相关说明文档中或编译脚本中找到,泛泰a870的例子是msm8960_ef52l_tp20_perf_defconfig

这个内核配置文件,可以在内核代码目录的arch/arm/configs里找到,读者不妨打开它,了解一下它的用处,笔者也顺便说说这个文件一个能自定义的地方:

CONFIG_LOCALVERSION="-perf"


这个会显示在系统的关于里,内核版本这个栏位里

许多cm内核会改成CONFIG_LOCALVERSION=”-CM”

读者可以改为自己的id,但请勿尝试使用中文,笔者完全不推荐这么做。

cm的kernel config项是放在BoardConfig.mk里

而msm-aosp是放在AndroidBoard.mk里,这是个不同点

那么就打开AndroidBoard.mk修改msm8960_defconfig换成你的手机内核对应的配置名称,这里笔者的例子就改成msm8960_ef52l_tp20_perf_defconfig

删除源码根目录的整个out目录

然后按照之前介绍的命令,重新完整编译一次。

如果没有错误,才可以继续进行下一个步骤。

如果有问题,请重新回顾上一篇文章的内容,重新找对版本再继续。

三、修改高通自带的device

首先,笔者希望读者能首先熟悉device的编写方法,这个是做编译适配的基础技能,而且有必要从现在就开始练习。

其次,不要指望参考cm之类的第三方rom的device,当你的机型不被cm支持时,不就傻眼了吗。

1.压缩device/qcom备份一下

2.device/qcom改名并处理多余文件

删除device/qcom下除了msm8960和common文件夹以外的文件夹

然后把原device/qcom/msm8960改名为device/pantech/a870

device/pantech/a870文件夹下删除所有.kl、.kcm、.conf、.accept、.deny、.rc、.sh、.ini、.dat、.bin、、sec_config、vold.fstab等文件,并在msm8960.mk里找到相应的copy语句,并删除之。

删除media文件夹、radio文件夹、snd_soc_msm文件夹,同理在msm8960.mk里找到相应的copy语句,并删除之。

最终剩下overlay文件夹、Android.mk、AndroidBoard.mk、AndroidProducts.mk、BoardConfig.mk、egl.cfg、fstab.qcom、msm8960.mk、recovery.fstab、system.prop

3.处理device/pantech/common文件夹

删除device文件夹、dtbtool文件夹、init文件夹、media文件夹、product文件夹、rootdir文件夹、recovery文件夹,并在common.mk里找到相应的copy语句,并删除之。

4.把common合并到a870文件夹里

合并后common文件夹删除,如果碰到同名文件,就把文件内容进行合并

5.再回到device/pantech/a870文件夹

新建bluetooth文件夹,并把bdroid_buildcfg.h移动到新建的文件夹里

对应的BoardConfig.mk里的语句也必须更改

BOARD_BLUETOOTH_BDROID_BUILDCFG_INCLUDE_DIR := device/pantech/a870/bluetooth


msm8960.mk文件改名为a870.mk,对应的AndroidProducts.mk里也必须打开来修改

然后打开a870.mk,修改

PRODUCT_NAME := a870

PRODUCT_DEVICE := a870

common.mk改名为device.mk,并打开a870.mk修改对应的路径名称

device.mk中删除所有非msm8960的行,PRODUCT_BRAND := qcom改为读者手机生产商,本例里改为pantech

grep –r “recovery”找一找有没有哪个配置文件有recovery相关的编译配置

删除所有含有recovery的行(注意保留第2步里提到的recovery.fstab)

6.修改vendorsetup.sh

仅保留如下语句即可

add_lunch_combo a870-userdebug


7.删除vendor/qcom

删除vendor/qcom/opensource/kernel-tests

并在device.mk中删除对应的#KERNEL_TESTS语句

把vendor/qcom压缩备份,然后把vendor/qcom删除以避免在后续的编译中出错

8.修改过程如果有些文件不知道在哪,请善用grep –r “关键字”来查找文件内容

9.边编译边修正错误

有些错误在编译时才容易找到。

source build/envsetup.sh

lunch

输入a870所对应的数字并回车

make otapackage –j5

10.编译recovery错误

因为我们把相关的配置项删除了,而编译系统又必须编译,所以我们这里要更改编译系统去掉recovery的编译

打开build/tools/releasetools/ota_from_target_files

注释如下语句

line454
#script.UnpackPackageDir("recovery", "/system")
line462
#recovery_img = common.GetBootableImage("recovery.img", "recovery.img",
#                                       OPTIONS.input_tmp, "RECOVERY")
#MakeRecoveryPatch(OPTIONS.input_tmp, output_zip, recovery_img, boot_img)
line617
#source_recovery = common.GetBootableImage(
#    "/tmp/recovery.img", "recovery.img", OPTIONS.source_tmp, "RECOVERY",
#    OPTIONS.source_info_dict)
#target_recovery = common.GetBootableImage(
#    "/tmp/recovery.img", "recovery.img", OPTIONS.target_tmp, "RECOVERY")
line765
#if updating_recovery:
#  script.Print("Unpacking new recovery...")
#  script.UnpackPackageDir("recovery", "/system")


对于初次适配者来说,做完这步可能都得花上1~2天的时间,许多配置项读者不理解但无需担心,在之后漫长的适配历程中,读者就会自己慢慢体会并慢慢懂得。

四、如何节省编译时间

因为反复编译确实很花时间,所以这里专门用一小节的内容来讲如何节省编译时间

1.如何重新编译以节省编译时间

虽然我们反复修改编译,但不变的有2个

一个是out/host,这个目录是用于存放编译过程中linux本身需要的一些工具

另一个是out/target/product/a870/obj/KERNEL_OBJ,这个目录是存放内核临时文件的,因为内核我们不改动,所以这个目录每次编译也就不会变化

于是我们每次删除重新编译就只要保留上面2个目录,其它文件都删掉即可,这样可节省约1/4的编译时间

2.建一个编译脚本

免得每次编译时敲一长串语句

#!/bin/bash
CPU_JOB_NUM=$(grep processor /proc/cpuinfo | awk '{field=$NF};END{print field+1}')
function build_target()
{
echo '<<<<<<开始编译>>>>>>'

START_TIME=`date +%s`
source ./build/envsetup.sh
lunch a870-userdebug
make otapackage -j$CPU_JOB_NUM

END_TIME=`date +%s`
let "ELAPSED_TIME=$END_TIME-$START_TIME"
echo "Total compile time is $ELAPSED_TIME seconds"
echo "Total compile time is $ELAPSED_TIME seconds" > time.txt
}
build_target
echo 编译结束 !!!
exit 0


把如上内容保存成a870.sh,保存在源代码根目录

然后给执行权限

chmod a+x a870.sh


以后每次编译时只要执行./a870.sh就可以了

而且编译完后,会生成一个time.txt文件,里面记录了编译过程一共多少秒,读者就可以知道编译一次花了多少时间。

五、改写device.mk

高通的范例是二段式的写法,举个例子:

#ANGLE
ANGLE := libangle
在文件底部还有
PRODUCT_PACKAGES += $(ANGLE)


而通常的写法是

#ANGLE
PRODUCT_PACKAGES += \
libangle


打个通俗的比方,高通的语句加了个中间变量,就像这样

A=笨蛋
傻瓜=A


但其实通常我们只要直接
笨蛋=傻瓜
这样就好了

改写完成后,把一些类似功能的项目集中在一起,比如音频相关的就放在一起

续行符\要记得自己补上

PRODUCT_PACKAGES += \
audio_policy.msm8960 \
audio.primary.msm8960 \
audio.a2dp.default \
audio.usb.default \
audio.r_submix.default \
libaudio-resampler


然后PRODUCT_LOCALES += hdpi mdpi这里

依情况增加xxhdpi和xhdpi

如果是720p就改为PRODUCT_LOCALES += xhdpi hdpi mdpi

如果是1080p就改为PRODUCT_LOCALES += xxhdpi xhdpi hdpi mdpi

最后,把所有的:=改成+=,请一定改过来,否则后面有些语句会有问题

全部搞定后,编译一次看看有没有什么语法错误

六、修改BoardConfig.mk

先去掉一些无用的项目

TARGET_USE_HDMI_AS_PRIMARY := false
ifeq ($(TARGET_USE_HDMI_AS_PRIMARY),true)
TARGET_HAVE_HDMI_OUT := false
else
TARGET_HAVE_HDMI_OUT := true
endif # TARGET_USE_HDMI_AS_PRIMARY
TARGET_HAVE_HDMI_OUT := false
TARGET_INIT_VENDOR_LIB := libinit_msm




-include vendor/qcom/proprietary/common/msm8960/BoardConfigVendor.mk


改成

-include vendor/pantech/a870/BoardConfigVendor.mk


并把这个语句移动到文件底部

然后把这些项目按功能来分类,以便我们后续修改

下面是笔者的分类,请读者参考如下标签来把语句分类

# CPU
# Krait optimizations
# Kernel
# BootLoader
# Platform
# Graphics
# Audio
# Bluetooth
# Wifi
# File System
# Camera
# GPS
# USB & Vold
# Vibrator
# Other


以下举例

# CPU
TARGET_GLOBAL_CFLAGS += -mfpu=neon -mfloat-abi=softfp
TARGET_GLOBAL_CPPFLAGS += -mfpu=neon -mfloat-abi=softfp
TARGET_CPU_ABI  := armeabi-v7a
TARGET_CPU_ABI2 := armeabi
TARGET_ARCH := arm
TARGET_ARCH_VARIANT := armv7-a-neon
TARGET_CPU_VARIANT := krait
TARGET_CPU_SMP := true
ARCH_ARM_HAVE_TLS_REGISTER := true

# Krait optimizations
TARGET_USE_KRAIT_BIONIC_OPTIMIZATION := true
TARGET_USE_KRAIT_PLD_SET := true
TARGET_KRAIT_BIONIC_PLDOFFS := 10
TARGET_KRAIT_BIONIC_PLDTHRESH := 10
TARGET_KRAIT_BIONIC_BBTHRESH := 64
TARGET_KRAIT_BIONIC_PLDSIZE := 64

# Kernel
BOARD_KERNEL_BASE    := 0x80200000
BOARD_KERNEL_PAGESIZE := 2048
BOARD_RAMDISK_OFFSET := 0x02000000
BOARD_MKBOOTIMG_ARGS := --ramdisk_offset 0x02000000
BOARD_KERNEL_CMDLINE := console=ttyHSL0,115200,n8 androidboot.hardware=vu2sk user_debug=31 msm_rtb.filter=0x3F ehci-hcd.park=3 maxcpus=2 lpj=67741

# BootLoader
TARGET_NO_BOOTLOADER := true
TARGET_BOOTLOADER_NAME := msm8960
TARGET_BOOTLOADER_BOARD_NAME := MSM8960

# Platform
TARGET_NO_RADIOIMAGE := true
TARGET_BOARD_PLATFORM := msm8960
TARGET_USES_QCOM_BSP := true
TARGET_ENABLE_QC_AV_ENHANCEMENTS := true
TARGET_POWERHAL_VARIANT := qcom

# Graphics
TARGET_USES_ION := true
TARGET_USES_OVERLAY := true
BOARD_EGL_CFG := device/pantech/a870/egl.cfg

# Audio
BOARD_USES_GENERIC_AUDIO := true
BOARD_USES_LEGACY_ALSA_AUDIO := true


等等,后面就不详细说了

七、修改boot参数

BoardConfig.mk里的# Kernel小节

内核的基地址,偏移地址,以及传递参数

BOARD_KERNEL_BASE
BOARD_RAMDISK_OFFSET
BOARD_MKBOOTIMG_ARGS
BOARD_KERNEL_CMDLINE


这些参数必须从读者的官方rom的boot.img里获取信息,请参考基础知识,后半部分关于修改的

/article/8890447.html

注意文章最后一个图片里的3个红框

读者编译出来的boot.img与官方的对比,3个红框的内容要完全一样才行

另外介绍一个新的编译命令

make bootimage –j5这个命令单独编译boot.img

八、修改ramdisk

在device/pantech/a870里新建一个ramdisk目录

把官方boot的ramdisk里的所有init.xx全部复制进去,并修改device.mk添加类似如下语句

PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/ramdisk/init.pantech.usb.rc:root/init.pantech.usb.rc \
$(LOCAL_PATH)/ramdisk/init.pantech.usb.sh:root/init.pantech.usb.sh \
$(LOCAL_PATH)/ramdisk/init.qcom.rc:root/init.qcom.rc \
$(LOCAL_PATH)/ramdisk/init.qcom.sh:root/init.qcom.sh \
$(LOCAL_PATH)/ramdisk/init.qcom.syspart_fixup.sh:root/init.qcom.syspart_fixup.sh \
$(LOCAL_PATH)/ramdisk/init.rc:root/init.rc \
$(LOCAL_PATH)/ramdisk/init.target.rc:root/init.target.rc \
$(LOCAL_PATH)/ramdisk/init.class_main.sh:root/init.class_main.sh \
$(LOCAL_PATH)/ramdisk/init.qcom.class_core.sh:root/init.qcom.class_core.sh \
$(LOCAL_PATH)/ramdisk/init.qcom.early_boot.sh:root/init.qcom.early_boot.sh \
$(LOCAL_PATH)/ramdisk/ueventd.qcom.rc:root/ueventd.qcom.rc \
$(LOCAL_PATH)/ramdisk/ueventd.rc:root/ueventd.rc \
$(LOCAL_PATH)/fstab.qcom:root/fstab.qcom


切勿生搬硬套,因为每个机型不一样。

假如编译出来的init不能用的话(请做完后面的显示部分适配后才能判断是否可用),可以把官方的init程序也按照这个方法添加进去

如果使用了官方的init,那么charger最好也改成官方的(关机充电相关)

device.mk里去掉

#Charger
PRODUCT_PACKAGES += \
charger \
charger_res_images


然后加上官方ramdisk里的charger以及res下的图片目录,就按照官方ramdisk目录结构来添加

泛泰的话,这2者都还算标准

但LG就比较奇异了,充电图片在在system\vendor\etc\chargerimages里,这个后面可以添加到proprietary-blobs.txt

而charger程序则在sbin/ chargerlogo

总之读者必须随机应变,毕竟每个机型都不一样

最终这一步要做到make出来的boot/ramdisk与官方的boot/ramdisk一样就行

九、微调ramdisk

接下来要对ramdisk做一些小小的修改,这里讲几个重要修改点,当然这也是每个机型不一样,读者得靠自己多试验总结才行

以泛泰为例

1.修改init.qcom.rc

# import cne init file
on post-fs
export LD_PRELOAD /system/lib/libNimsWrap.so


cm等第三方rom经常去掉cne服务,故可以把这段删除

有些机型可能不叫作init.qcom.rc,那么读者可以grep –r “libNimsWrap”来找,例如LG的F200就叫做init.grand-common.rc

2.修改init.rc

mkdir /cache 0770 system cache


改成

mkdir /cache 0771 system cache


chmod 0770 /cache


改成

chmod 0771 /cache


# create dalvik-cache, so as to enforce our permissions
mkdir /data/dalvik-cache 0771 system system


改成

mkdir /data/dalvik-cache 0771 system system
chown system system /data/dalvik-cache
chmod 0771 /data/dalvik-cache


如果官方还加载了preload分区,也可以整段去掉,比如类似如下的语句

mount ext4 /dev/block/mmcblk0p13 /preload rw remount


前后可能还有一些分区检查,复制文件的语句

preload分区是存放一些出厂预置软件或资源的,对于aosp则完全无用

删除自恢复recovery服务

service flash_recovery /system/etc/install-recovery.sh
class main
oneshot


3.修改init.target.rc和fstab.qcom

这2个文件相互配合用于加载各分区

需要注意的是,这2个文件名称也不是固定,而且有的机型需要修改,有的机型不需要修改

比如泛泰的需要修改,而LG则无需修改

这里以泛泰为例,先看init.target.rc

on fs段

wait /dev/block/platform/msm_sdcc.1/by-name/system
mount ext4 /dev/block/platform/msm_sdcc.1/by-name/system /system ro barrier=1


这个语句用于加载system分区

wait /dev/block/platform/msm_sdcc.1/by-name/cache
exec /system/bin/mmcblk_utils ext4 /dev/block/platform/msm_sdcc.1/by-name/cache
exec /system/bin/e2fsck -p /dev/block/platform/msm_sdcc.1/by-name/cache
mount ext4 /dev/block/platform/msm_sdcc.1/by-name/cache /cache nosuid nodev barrier=1


这个语句用于加载cache分区

wait /dev/block/platform/msm_sdcc.1/by-name/userdata
exec /system/bin/mmcblk_utils ext4 /dev/block/platform/msm_sdcc.1/by-name/userdata
exec /system/bin/e2fsck -p /dev/block/platform/msm_sdcc.1/by-name/userdata


这个语句用于加载userdata分区

这些语句用工具检查了分区,但我们可以不需这种加载形式,把这些语句都删除

把加载语句放到fstab.qcom里

/dev/block/platform/msm_sdcc.1/by-name/system /system ext4 rw,barrier=1 wait

/dev/block/platform/msm_sdcc.1/by-name/cache /cache ext4 nosuid,nodev,barrier=1 wait,check

/dev/block/platform/msm_sdcc.1/by-name/userdata /data ext4 nosuid,nodev,barrier=1,noauto_da_alloc   wait,check,encryptable=footer,length=-16384


需要注意的是,官方的userdata区加载语句还多了encryptable=/persist/metadata这样的结尾,估计是用来加密分区的,我们也把它去掉

4.去掉LG加密服务(此项仅针对LG,泛泰无需)

适配一切都是灵活且多变的,如果碰到困难,读者请无需气馁,多试即可

下面以LG F200的ramdisk为例,修改并去掉一些无用的东西

修改init.grand-common.rc,去掉import init.lge.log.rc

修改init.rc,去掉import /init.lge.early.rc,去掉import /init.lge.rc

然后删除如下文件

init.lge.early.rc

init.lge.log.rc

init.lge.rc

lgdms.fota.rc

lgdms.fota_update.rc

十、build.prop修改

device/pantech/a870/system.pro这个文件添加的语句,最后会生成到build.prop里

我们先把这个文件清空,把官方build.prop中间那段写到这个文件里,读者自己试着编译看看就知道如何编写这个文件了。

当读者把本篇文章的内容实践完成时,就已经算是入门了。

编译出来的rom肯定不能启动,但可以尝试刷到手机里看看反应,如果device名称不符合还得先去掉机型验证或自己编译一个recovery,因为视频和音频部分还未适配,现在仅仅是做个热身而已。

小白就不要尝试了,以免变砖,话又说回来,即使做为rommer难免会失手让手机变砖的时候,常在河边站哪有不湿鞋。

所以作为rommer并非大家想象中那么酷,小朋友们切勿模仿。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐