MTK6577+Android编译之android

MTK6577+Android编译之android

开发环境:虚拟机+Ubuntu14.04

 

MTK6577采用的内存芯片为H9TP32A4GDMCPR,包括4GB的eNAND和512MB的 LPDDR2,先升级为H9TP32A8JDMCPR,包括4GB的eNAND和1GB的LPDDR2

 

先来看MTK源代码树概观图:

MTK6577+Android编译之android_第1张图片

图1

由图1可知编译的入口是makeMtk文件,其采用perl语言编写的,包装了编译命令,下面来看编译系统的概述:

MTK6577+Android编译之android_第2张图片

图2

 

1.     编译命令、时间和生成的文件

 

(1)  编译命令和时间

编译命令./mk r dr,时间约为54分钟。

 

(2)  编译生成的文件

编译后发现有更新的文件有bootimg、kernel、ramdisk.img、ramdisk-recovery.img、recovery.img、secro.img和system.img

 

编译后有更新的log文件有hsimobile77_ics2_check-dep、hsimobile77_ics2_custgen、hsimobile77_ics2_check-modem、hsimobile77_ics2_sign-modem、hsimobile77_ics2_AppAssets_Overlay、hsimobile77_ics2_android

 

其中hsimobile77_ics2_check-dep、hsimobile77_ics2_custgen、hsimobile77_ics2_ptgen和编译preloader部分内容是一样的,可参考:

http://blog.csdn.net/loongembedded/article/details/38706537

 

(3)  android镜像的文件名system.img

 

我们来看\mediatek\build\makemtk.mk下面的相关内容:

LOGDIR        = $(MKTOPDIR)/out/target/product
 
ANDROID_IMAGES   := $(LOGDIR)/$(PROJECT)/system.img \
                   $(LOGDIR)/$(PROJECT)/boot.img \
                   $(LOGDIR)/$(PROJECT)/recovery.img \
                   $(LOGDIR)/$(PROJECT)/secro.img \
                   $(LOGDIR)/$(PROJECT)/userdata.img

其中boot.img和recovery.img是kernel相关的,system.img、secro.img、userdata.img和cache.img是有文件系统的,如果不烧录recovery.img,在启动过程中要进入recovery模式时黑屏。

 

 

2.     android编译流程

 

(1)  ./mk rdr

找到makeMtk源码(perl语言),编译命令最终是通过调用

$makeCmd ="make -f mediatek/build/makemtk.mk $cmdArg @mOpts";

这个编译命令进行编译的。GNU make可以添加DEBUG参数来获取调试信息,比如--debug=v。

可以通过修改$makeCmd来增加调试信息,比如:

$makeCmd ="make --debug=v -f mediatek/build/makemtk.mk $cmdArg @mOpts";

 

(2)  makemtk.mk

$makeCmd命令指定makefile文件 mediatek/build/makemtk.mk,其对应

android:
ifeq ($(ACTION), )
       $(hide) /usr/bin/perlmediatek/build/tools/mtkBegin.pl $(FULL_PROJECT)
endif
 
ifneq($(DR_MODULE),)
   ifneq ($(ACTION), clean)
       $(hide) echo building android moduleMODULE=$(DR_MODULE)
       $(hide) perlmediatek/build/tools/javaoptgen.pl $(PRJ_MF) $(OPTR_MF)
       $(MAKECMD) $(DR_MODULE)
   else
       $(hide) echo cleaning android moduleMODULE=$(DR_MODULE)
       $(hide) $(MAKECMD) clean-$(DR_MODULE)
   endif
else
       $(hide) echo $(SHOWTIME) $(SHOWBUILD)ing$@...
       $(hide) echo -e \\t\\t\\t\\b\\b\\b\\bLOG:$(S_MODULE_LOG)
ifeq($(SHOWBUILD), build)
       $(hide) perlmediatek/build/tools/javaoptgen.pl $(PRJ_MF) $(OPTR_MF) $(DEAL_STDOUT)
endif
       $(hide) $(MAKECMD) $(ACTION)$(DEAL_STDOUT) && \
        $(call chkImgSize,$(ACTION),$(PROJECT),$(SCATTER_FILE),$(if $(strip$(ACTION)),$(CHECK_IMAGE),$(ANDROID_IMAGES)),$(DEAL_STDOUT),&&) \
        $(SHOWRSLT) $${PIPESTATUS[0]} $(MODULE_LOG) $(ACTION) || \
        $(SHOWRSLT) $${PIPESTATUS[0]} $(MODULE_LOG) $(ACTION)
 
ifeq ($(ACTION), )
       $(hide) /usr/bin/perlmediatek/build/tools/mtkFinalize.pl $(PROJECT) $(MTK_PLATFORM)$(MTK_EMMC_SUPPORT)
endif
endif

(3)  执行chkImgSize(if MTK_CHKIMGSIE_SUPPORT=yes)

主要是为了检查scatter file文件(MT6577_Android_scatter_emmc.txt)为uboot分配的空间是否可以容纳生成的image,目前看了mediatek\config\prj\ProjectConfig.mk文件中没有MTK_CHKIMGSIE_SUPPORT定义,后面应该考虑添加进来。

 

 

3.     android编译涉及的源代码目录

修改以下文件或者目录需要./mk r(n) dr

这部分参考第4部分。

 

4.     Boot.img、ramdisk.img、kernel、secro.img、ramdisk-revovery.img、system.img、cache.img和userdata.img

 

4.1  ./mk bootimag

编译生成boot.img、ramdisk.img和kernel,当修改kernel和root相关的代码时采用此命令:

alps/kernel/

alps/mediatek/platform/mt65xx/kernel/

alps/mediatek/source/kernel/

alps/mediatek/customer/mt65xx/kernel/

alps/mediatek/customer/common/kernel/

alps/mediatek/customer/$porject_name$/kernel

......

 

Android 产品中,内核格式是Linux标准的zImage,根文件系统采用ramdisk格式。这两者在Android下是直接合并在一起取名为boot.img,会放在一个独立分区当中。这个分区格式是Android自行制定的格式。Android开发时,最标准的做法是重新编译于内核和根文件系统,然后调用Android给的命令行文件mkbootimg来打包。

 

1)     mkbootimage打包生成boot.img

MTK6577+Android编译之android_第3张图片

图3

\build\core\Makefile文件相关的一部分内容如下:

INSTALLED_BOOTIMAGE_TARGET:= $(PRODUCT_OUT)/boot.img
BUILT_RAMDISK_TARGET:= $(PRODUCT_OUT)/ramdisk.img
 
INSTALLED_RAMDISK_TARGET:= $(BUILT_RAMDISK_TARGET)
 
ifeq """$(CUSTOM_BUILD_VERNO)"
  CUSTOM_BUILD_VERNO := $(BUILD_NUMBER)
  CUSTOM_BUILD_VERNO := $(substeng.$(USER).,,$(CUSTOM_BUILD_VERNO))
endif
 
#-----------------------------------------------------------------
# the boot image,which is a collection of other images.
INTERNAL_BOOTIMAGE_ARGS:= \
       $(addprefix --second,$(INSTALLED_2NDBOOTLOADER_TARGET)) \
       --kernel $(INSTALLED_KERNEL_TARGET) \
       --ramdisk $(INSTALLED_RAMDISK_TARGET)
………………………
ifneq """$()"
  INTERNAL_BOOTIMAGE_ARGS += --board$(CUSTOM_BUILD_VERNO)
Endif
………………………………………
$(INSTALLED_BOOTIMAGE_TARGET):$(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_FILES)

由此可见mkbootimage打包生成boot.img时需要的参数有

--kernel $(PRODUCT_OUT)/kernel(或是kernel_$project.bin)

--ramdisk $(PRODUCT_OUT)/ramdisk.img

--board $(CUSTOM_BUILD_VERNO)

注意CUSTOM_BUILD_VERNO不要超过16个字节,其在/mediate/config/prj/ProjectConfig.mk中定义,但这里其值为空,所以其内容对应于BUILD_NUMBER的值,这里的信息对应System settings->About phone->Custom buildversion下的内容,比如1407736091

 

mkbootimage工具位于out/host/linux-x86/bin,要知道boot.img的格式,需要看对应的源代码\system\core\mkbootimg\mkbootimg.c,boot.img由文件头信息boot header,压缩的内核,文件系统数据ramdisk以及second stage loader(可选)组成,它们之间非页面对齐部分用0填充,相关的代码见mian()下面部分:

if(write(fd,&hdr, sizeof(hdr)) != sizeof(hdr)) goto fail;
    if(write_padding(fd, pagesize,sizeof(hdr))) goto fail;
 
    if(write(fd, kernel_data, hdr.kernel_size)!= hdr.kernel_size) goto fail;
    if(write_padding(fd, pagesize,hdr.kernel_size)) goto fail;
 
    if(write(fd, ramdisk_data,hdr.ramdisk_size) != hdr.ramdisk_size) goto fail;
    if(write_padding(fd, pagesize,hdr.ramdisk_size)) goto fail;
 
    if(second_data) {
        if(write(fd, second_data,hdr.second_size) != hdr.second_size) goto fail;
        if(write_padding(fd, pagesize,hdr.ramdisk_size)) goto fail;
}

\system\core\mkbootimg\bootimg.h目录下boot_img_hdr定义了文件头信息:

typedef structboot_img_hdr boot_img_hdr;
 
#define BOOT_MAGIC"ANDROID!"
#defineBOOT_MAGIC_SIZE 8
#defineBOOT_NAME_SIZE 16
#defineBOOT_ARGS_SIZE 512
 
structboot_img_hdr
{
    unsigned char magic[BOOT_MAGIC_SIZE];
 
    unsigned kernel_size;  /* size in bytes */
    unsigned kernel_addr;  /* physical load addr */
 
    unsigned ramdisk_size; /* size in bytes */
    unsigned ramdisk_addr; /* physical loadaddr */
 
    unsigned second_size;  /* size in bytes */
    unsigned second_addr;  /* physical load addr */
 
    unsigned tags_addr;    /* physical addr for kernel tags */
    unsigned page_size;    /* flash page size we assume */
    unsigned unused[2];    /* future expansion: should be 0 */
 
    unsigned char name[BOOT_NAME_SIZE]; /*asciiz product name */
   
    unsigned char cmdline[BOOT_ARGS_SIZE];
 
    unsigned id[8]; /* timestamp / checksum /sha1 / etc */
};

Boot.img的组成借用bootimg.h下给出的解释:

MTK6577+Android编译之android_第4张图片

图4

 

2)     mkbootfs打包生成ramdisk.img

MTK6577+Android编译之android_第5张图片

图5

 

在build/core/Makefile文件中看下面主要的相关部分:

##################################################################
# Targets forboot/OS images
##################################################################
 
#-----------------------------------------------------------------
# the ramdisk
INTERNAL_RAMDISK_FILES:= $(filter $(TARGET_ROOT_OUT)/%, \
       $(ALL_PREBUILT) \
       $(ALL_COPIED_HEADERS) \
       $(ALL_GENERATED_SOURCES) \
       $(ALL_DEFAULT_INSTALLED_MODULES))
 
BUILT_RAMDISK_TARGET:= $(PRODUCT_OUT)/ramdisk.img
 
# We just buildthis directly to the install location.
INSTALLED_RAMDISK_TARGET:= $(BUILT_RAMDISK_TARGET)
$(INSTALLED_RAMDISK_TARGET):$(MKBOOTFS) $(INTERNAL_RAMDISK_FILES) | $(MINIGZIP)
       $(call pretty,"Target ram disk:$@")
       $(hide) $(MKBOOTFS) $(TARGET_ROOT_OUT) |$(MINIGZIP) > $@
ifneq ($(strip$(TARGET_NO_KERNEL)),true)       
       $(hide) mediatek/build/tools/mkimage$(PRODUCT_OUT)/ramdisk.img ROOTFS > $(PRODUCT_OUT)/ramdisk_android.img
       mv $(PRODUCT_OUT)/ramdisk.imgmediatek/source/kernel/trace32/$(TARGET_PRODUCT)_ramdisk.img
       $(hide) mv$(PRODUCT_OUT)/ramdisk_android.img $(PRODUCT_OUT)/ramdisk.img
Endif


MKBOOTFS =mkbootfs 就是位于out/host/linux-x86/bin目录下的mkbootfs。

Ramdisk.img是mkbootfs工具用\out\target\product\prj\out目录下的

 

需要注意system/core/rootdir中的部分内容是拷贝到了out/target/product/prj/system中的,并不是完完全全拷贝到out/target/product/prj/root目录中去的。

 

ramdisk映像是一个最基础的小型文件系统,它包括了初始化android系统所需要的全部核心文件,总之它控制着整个android的启动.例如:初始化init进程以及init.rc(可以用于设置很多系统的参数)等文件。以下是一个典型的ramdisk中包含的文件列表:

./init.trout.rc

./default.prop

./proc

./dev

./init.rc

./init

./sys

./init.goldfish.rc

./sbin

./sbin/adbd

./system

./data

详细可参考\system\core\rootdir\Android.mk。

 

3)     kernel

MTK6577+Android编译之android_第6张图片

图6

 

见http://blog.csdn.net/loongembedded/article/details/38778731

 

4.2  ./mk systemimage

 

1)     编译生成的文件

system.img、boot.img、ramdisk.img、ramdisk-recovery.img、recovery.img。

 

2)     修改system相关代码时用到此编译命令

alps/frameworks/

alps/packages/

alps/vendor/

alps/hardware/

alps/dalvik/

...........

3)     System.img文件的内容

 

在源码之后在 out/host/linux-x86/bin/下面会生成一个mkyaffs2image的工具,用这个可以把system目录打包成system.img

 

system.img文件是system目录的一个映像,类似于linux的根文件系统的映像,它包含了整个系统,比如android的framework、application、配置文件、字体等,它会被挂接到 "/" 上,包含了系统中所有的二进制文件。

 

android启动时首先加载ramdisk.img镜像,并挂载到/目录下,并进行了一系列的初始化动作,包括创建各种需要的目录,初始化console,开启服务等。System.img是在init.rc中指定一些脚本命令,通过init.c进行解析并挂载到根目录下的/system目录下的。

对于android系统文件夹,比如out/target/product/prj/system目录,说明如下:

 

system/app     

这个里面主要存放的是常规下载的应用程序,可以看到都是以APK格式结尾的文件。在这个文件夹下的程序为系统默认的组件,自己安装的软件将不会出现在这里,而是/data/文件夹中。

 

system/bin     

 这个目录下的文件都是系统的本地程序,从bin文件夹名称可以看出是binary二进制的程序,里面主要是Linux系统自带的组件。 system/etc       从文件夹名称来看保存的都是系统的配置文件,比如APN接入点设置等核心配置。

 

system/fonts  

字体文件夹,除了标准字体和粗体、斜体外可以看到文件体积最大的可能是中文字库,或一些unicode字库。

 

system/framework 

主要是一些核心的文件,从后缀名为jar可以看出是是系统平台框架。

 

system/lib       

lib目录中存放的主要是系统底层库,如平台运行时库。

 

system/media 

铃声音乐文件夹,除了常规的铃声外还有一些系统提示事件音

 

system/usr     

用户文件夹,包含共享、键盘布局、时间区域文件等。

 

通过\out\target\product\prj\ installed-files.txt文件可以查看system.img加压后包括的目录信息。

 

4.3  ./mk recoveryimage

 

1)     编译生成的文件

boot.img、ramdisk.img、ramdisk-recovery.img、recovery.img。

 

2)     修改recovery相关代码时用到此编译命令

alps/bootable/recovery/

alps/mediatek/customer/$project_name$/recovery/

......

 

3)     Recovery.img内容

 

Bootloader 会根据某些判定条件(比如按某个特殊键)决定是否进入 recovery 模式。Recovery 模式会装载 recovery 分区, 该分区包含recovery.img。recovery.img 包含了标准内核(和boot.img中的内核相同)以及recovery 根文件系统

MTK6577+Android编译之android_第7张图片

图7

可以看出recovery.img和boot.img的差别在于boot.img包含的根文件系统对应于ramdisk.img,而recovery.img包含的根文件系统对应于ramdisk-recovery.img

 

recovery.img的生成过程可看build\core\Makefile下面相关部分:


recovery_kernel :=$(INSTALLED_KERNEL_TARGET) # same as a non-recovery system
recovery_ramdisk:= $(PRODUCT_OUT)/ramdisk-recovery.img
………………………..
INSTALLED_RECOVERYIMAGE_TARGET:= $(PRODUCT_OUT)/recovery.img
…………………………..
INTERNAL_RECOVERYIMAGE_ARGS:= \
       $(addprefix --second,$(INSTALLED_2NDBOOTLOADER_TARGET)) \
       --kernel $(recovery_kernel) \
       --ramdisk $(recovery_ramdisk)
……………………
 
$(INSTALLED_RECOVERYIMAGE_TARGET):$(MKBOOTFS) $(MKBOOTIMG) $(MINIGZIP) \
              $(INSTALLED_RAMDISK_TARGET)\
              $(INSTALLED_BOOTIMAGE_TARGET)\
              $(recovery_binary)\
              $(recovery_initrc)$(recovery_kernel) \
              $(INSTALLED_2NDBOOTLOADER_TARGET)\
              $(recovery_build_prop)$(recovery_resource_deps) \
              $(recovery_fstab)\
              $(recovery_gzip)$(recovery_sec_ko) \
              $(RECOVERY_INSTALL_OTA_KEYS)
       @echo----- Making recovery image ------
       rm-rf $(TARGET_RECOVERY_OUT)
       mkdir-p $(TARGET_RECOVERY_OUT)
       mkdir-p $(TARGET_RECOVERY_ROOT_OUT)
       mkdir-p $(TARGET_RECOVERY_ROOT_OUT)/etc
       mkdir-p $(TARGET_RECOVERY_ROOT_OUT)/tmp
       echoCopying baseline ramdisk...
       cp-R $(TARGET_ROOT_OUT) $(TARGET_RECOVERY_OUT)
       rm-f $(TARGET_RECOVERY_ROOT_OUT)/init*.rc
       echoModifying ramdisk contents...
       rm-rf $(TARGET_RECOVERY_ROOT_OUT)/res
       cp-f $(recovery_initrc) $(TARGET_RECOVERY_ROOT_OUT)/
       cp-f $(recovery_gzip) $(TARGET_RECOVERY_ROOT_OUT)/sbin/gzip
       cp-f $(recovery_sec_ko) $(TARGET_RECOVERY_ROOT_OUT)/
       cp-f $(recovery_binary) $(TARGET_RECOVERY_ROOT_OUT)/sbin/
       cp-rfL $(recovery_resources_common) $(TARGET_RECOVERY_ROOT_OUT)/
       $(foreachitem,$(recovery_resources_private), \
         cp -rf $(item) $(TARGET_RECOVERY_ROOT_OUT)/)
       $(foreachitem,$(recovery_fstab), \
         cp -f $(item)$(TARGET_RECOVERY_ROOT_OUT)/etc/recovery.fstab)
       cp$(RECOVERY_INSTALL_OTA_KEYS) $(TARGET_RECOVERY_ROOT_OUT)/res/keys
       cat$(INSTALLED_DEFAULT_PROP_TARGET) $(recovery_build_prop) \
               >$(TARGET_RECOVERY_ROOT_OUT)/default.prop
       $(MKBOOTFS)$(TARGET_RECOVERY_ROOT_OUT) | $(MINIGZIP) > $(recovery_ramdisk)
       mediatek/build/tools/mkimage$(PRODUCT_OUT)/ramdisk-recovery.img RECOVERY >$(PRODUCT_OUT)/ramdisk_recovery.img
       mv$(PRODUCT_OUT)/ramdisk_recovery.img $(PRODUCT_OUT)/ramdisk-recovery.img
       $(MKBOOTIMG)$(INTERNAL_RECOVERYIMAGE_ARGS) --output $@
       @echo----- Made recovery image -------- $@
       $(hide)$(call assert-max-image-size,$@,$(BOARD_RECOVERYIMAGE_PARTITION_SIZE),raw)
用到的一些环境变量在build\core\envsetup.mk文件下:
TARGET_RECOVERY_OUT := $(PRODUCT_OUT)/recovery
TARGET_RECOVERY_ROOT_OUT :=$(TARGET_RECOVERY_OUT)/root
TARGET_RECOVERY_ROOT_OUT
 
TARGET_ROOT_OUT := $(PRODUCT_OUT)/root

可知ramdisk.img对应的目录和ramdisk-recovery.img对应的目录差如下:

MTK6577+Android编译之android_第8张图片

图8

 

 

4.4  ./mk secroimage

 

1)     编译生成的文件

secro.img。

 

2)     修改secro相关代码时用到此编译命令

alps/mediatek/source/secro/

alps/mediatek/customer/$project_name$/secro/

 

3)     secro.img内容

MTK6577+Android编译之android_第9张图片 

图9

1)     复制\mediatek\custom\prj\secro目录到\out\target\product\prj\secro目录

2)     \out\target\product\prj\secro文件夹打包成为secro.img

 

详细的生成过程见build\core\Makefile相关部分

 

BUILT_SECROIMAGE_TARGET:= $(PRODUCT_OUT)/secro.img

 

4.5  ./mk factoryimage

 

1)     编译生成的文件

factory.bin。

 

2)     修改factory相关代码时用到此编译命令

alps/mediatek/customer/$project_name$/factory/

alps/mediatek/customer/common/factory/

alps/mediatek/source/factory/

......

 

3)     Factory.bin内容

Factory.bin大小为0,先来看build\core\Makefile相关文件:

 

factory_ramdisk :=$(PRODUCT_OUT)/ramdisk-factory.img
 
INSTALLED_FACTORYIMAGE_TARGET:= $(PRODUCT_OUT)/factory.img
………………….
 
.PHONY:factoryimage
factoryimage:$(INSTALLED_FACTORYIMAGE_TARGET)
       @mediatek/build/tools/mkimage$(PRODUCT_OUT)/ramdisk-factory.img ROOTFS > $(PRODUCT_OUT)/factory.bin

可知factory.bin是ramdisk-factory.img打上ROOTFS标识后的文件,接着来看build\core\envsetup.mk下面的信息:

TARGET_FACTORY_OUT:= $(PRODUCT_OUT)/factory
TARGET_FACTORY_ROOT_OUT:= $(TARGET_FACTORY_OUT)/root

可知其意向是把\out\target\product\prj\factory\root目录打包生成为ramdisk-factory.img的,但并没有存在此目录,所以最后生成的factory.bin为0。

 

4.6  ./mk userdataimage

生成out\target\product\prj\data目录,并将此文件夹打包生成userdata.img,但是实际上没有看到对应的userdata.img更新,好像只有./mk new时才生成新的。

 

userdata.img挂载到 /data 下的镜像,它包含了应用及用户相关的数据。

 

4.7  ./mk cacheimage

提示make: *** No rule to make target`cacheimage'.  Stop.

 

参考链接:

《Android_Build_System_for_customer》

Android编译系统详解(一)

http://blog.csdn.net/mr_raptor/article/details/7539978

Android.mk的用法和基础

http://blog.csdn.net/zhandoushi1982/article/details/5316669

 

Android OTA升级之三:生成recovery.img

http://blog.csdn.net/zjujoe/article/details/6230575/

 

你可能感兴趣的:(MTK6577+Android编译之android)