🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# camdriod编译过程走读 ## camdroid编译 ~~~ source build/envsetup.sh #导入环境变量设置,如下面的这些命令 lunch #选择平台型号,在build/envsetup.sh,包含了device/softwinner/common/vendorsetup.sh mklichee #编译BootLoader和内核,模块 extract-bsp #拷贝前面的结果 make -j12 #编译camdroid pack #打包镜像 ~~~ ## lichee编译 mklichee在device/softwinner/common/vendorsetup.sh里: ~~~ function mklichee() { mksetting mk_info "build lichee ..." mkbr && mkkernel # mkbr && mkkernel && mkuboot [ $? -ne 0 ] && return 1 return 0 } ~~~ ### mksetting打印配置信息 ~~~ function mksetting() { printf "\n" printf "mkscript current setting:\n" printf " Chip: ${LICHEE_CHIP}\n" printf " Platform: ${LICHEE_PLATFORM}\n" printf " Board: ${LICHEE_BOARD}\n" printf " Output Dir: ${LICHEE_PLAT_OUT}\n" printf "\n" } ~~~ 实际打印结果: > mkscript current setting: > Chip: sun8iw8p1 > Platform: > Board: > Output Dir: /home/zp/develop/lichee_git/lichee_zero/camdroid/../lichee/out/sun8iw8p1/linux/common ### mkbr编译buildroot ~~~ function mkbr() { mk_info "build buildroot ..." local build_script build_script="scripts/build.sh" LICHEE_PLATFORM="linux" (cd ${LICHEE_BR_DIR} && [ -x ${build_script} ] && ./${build_script} "buildroot" ${LICHEE_PLATFORM} ${LICHEE_CHIP}) [ $? -ne 0 ] && mk_error "build buildroot Failed" && return 1 mk_info "build buildroot OK." } ~~~ 执行结果: ~~~ INFO: build buildroot ... external toolchain has been installed INFO: build buildroot OK. ~~~ > export LICHEE_BR_DIR=${LICHEE_DIR}/buildroot 所以先进入lichee/buildroot, -x表示进入跟踪模式,执行scripts/build.sh,这里是导入了一些路径变量 ~~~ EXTERNAL_DIR=${LICHEE_BR_DIR}/external-packages DESTDIR=${LICHEE_BR_DIR}/images STAGING_DIR=${LICHEE_BR_OUT}/staging INCDIR=${STAGING_DIR}/usr/include TARGET_DIR=${LICHEE_BR_OUT}/target TARGET_SYSROOT_OPT="--sysroot=${STAGING_DIR}" ~~~ 然后执行`./${build_script} "buildroot" ${LICHEE_PLATFORM} ${LICHEE_CHIP}` 也就是:`./scripts/build.sh "buildroot" linux sun8iw8p1` 解析命令里没有对后面的参数进行解析。。 ~~~ case "$1" in clean) rm -rf ${LICHEE_BR_OUT} ;; *) if [ "x${LICHEE_PLATFORM}" = "xlinux" ] ; then #根本没有对这个赋值 build_buildroot export PATH=${LICHEE_BR_OUT}/external-toolchain/bin:$PATH build_external else build_toolchain fi ;; esac ~~~ 这里执行了后面的else,也就是build_toolchain(其实是解压外部工具链) ~~~ build_toolchain() { local tooldir="${LICHEE_BR_OUT}/external-toolchain" mkdir -p ${tooldir} #out/sun8iw8p1/linux/common/buildroot/external-toolchain if [ -f ${tooldir}/.installed ] ; then printf "external toolchain has been installed\n" else printf "installing external toolchain\n" printf "please wait for a few minutes ...\n" tar --strip-components=1 \ -jxf ${LICHEE_BR_DIR}/dl/gcc-linaro.tar.bz2 \ -C ${tooldir} [ $? -eq 0 ] && touch ${tooldir}/.installed fi export PATH=${tooldir}/bin:${PATH} } ~~~ 简单地说就是把buildroot/dl/gcc-linaro.tar.bz2 解压到out/sun8iw8p1/linux/common/buildroot/external-toolchain 另一路选择执行的两个函数: ~~~ build_buildroot() //编译buildroot { if [ ! -f ${LICHEE_BR_OUT}/.config ] ; then #如果没有配置过,则使用默认配置 printf "\nUsing default config ...\n\n" make O=${LICHEE_BR_OUT} -C ${LICHEE_BR_DIR} ${LICHEE_BR_DEFCONF} fi make O=${LICHEE_BR_OUT} -C ${LICHEE_BR_DIR} LICHEE_GEN_ROOTFS=n \ BR2_JLEVEL=${LICHEE_JLEVEL} } build_external() //external-packages,指buildroot里的所有外部包 { for dir in ${EXTERNAL_DIR}/* ; do if [ -f ${dir}/Makefile ]; then BUILD_COMMAND="make -C ${dir} ${BUILD_OPTIONS} all" eval $BUILD_COMMAND BUILD_COMMAND="make -C ${dir} ${BUILD_OPTIONS} install" eval $BUILD_COMMAND fi done } ~~~ 即执行了:`make O=out/sun8iw8p1/linux/common/buildroot -C ./ LICHEE_GEN_ROOTFS=n BR2_JLEVEL=${LICHEE_JLEVEL}` 即编译br目录,但不生成rootfs ### mkkernel编译内核 ~~~ function mkkernel() { local platformdef=$tdevice if [ ! -n $tdevice ]; then echo "Please lunch device" return 1 fi echo "Make the kernel" echo "platformdef="${platformdef} (cd ${LICHEE_KERN_DIR}/; ./build.sh -p ${platformdef}) [ $? -ne 0 ] && mk_error "build mkkernel fail" && return 1 echo "Make the kernel finish" return 0 } ~~~ 执行显示结果: ~~~ Make the kernel platformdef=tiger-cdr ~~~ 即执行了:Cd lichee/linux3.4; ./build.sh -p tiger-cdr ~~~ #这里首先导入了PLATFORM=tiger-cdr while getopts hp:m: OPTION do case $OPTION in h) show_help ;; p) PLATFORM=$OPTARG ;; m) MODULE=$OPTARG ;; *) show_help ;; esac done #没有指定platform则退出 if [ -z "$PLATFORM" ]; then show_help exit 1 fi #没有指定模块则默认编译所有 if [ -z "$MODULE" ]; then MODULE="all" fi #执行scripts/build_tiger-cdr.sh if [ -x ./scripts/build_${PLATFORM}.sh ]; then ./scripts/build_${PLATFORM}.sh $MODULE else printf "\nERROR: Invalid Platform\nonly sun6i sun6i_fiber or sun6i_dragonboard sopport\n" show_help exit 1 fi ~~~ 对应目录里脚本为: ~~~ LICHEE_ROOT=`(cd ${LICHEE_KDIR}/..; pwd)` export PATH=${LICHEE_ROOT}/out/sun8iw8p1/linux/common/buildroot/external-toolchain/bin:${LICHEE_ROOT}/tools/pack/pctools/linux/android:$PATH case "$1" in kernel) build_kernel ;; modules) build_modules ;; clean) clean_kernel clean_modules ;; *) build_kernel build_modules # build_ramfs #这里可以生成boot.img # gen_output echo -e "\n\033[0;31;1m${LICHEE_CHIP} compile Kernel successful\033[0m\n\n" ;; esac ~~~ 总之就是默认编译了内核和模块。。 可以看到build_kernel其实编译了uImage和modules,并把bImage和zImage拷到了output目录 把ko文件拷到了lichee/linux-3.4/output/lib/modules/3.4.39下 ~~~ build_kernel() { echo "Building kernel" cd ${LICHEE_KDIR} rm -rf output/ echo "${LICHEE_MOD_DIR}" mkdir -p ${LICHEE_MOD_DIR} # echo "build_kernel LICHEE_KERN_DEFCONF" ${LICHEE_KERN_DEFCONF} # We need to copy rootfs files to compile kernel for linux image # cp -f rootfs.cpio.gz output/ if [ ! -f .config ] ; then # printf "\n\033[0;31;1mUsing default config ${LICHEE_KERN_DEFCONF} ...\033[0m\n\n" printf "\n\033[0;31;1mUsing default config sun8iw8p1smp_tiger_cdr_defconfig ...\033[0m\n\n" # cp arch/arm/configs/${LICHEE_KERN_DEFCONF} .config cp arch/arm/configs/sun8iw8p1smp_tiger_cdr_defconfig .config fi make ARCH=arm CROSS_COMPILE=${CROSS_COMPILE} -j${LICHEE_JLEVEL} uImage modules update_kern_ver #The Image is origin binary from vmlinux. cp -vf arch/arm/boot/Image output/bImage cp -vf arch/arm/boot/[zu]Image output/ cp .config output/ tar -jcf output/vmlinux.tar.bz2 vmlinux if [ ! -f ./drivers/arisc/binary/arisc ]; then echo "arisc" > ./drivers/arisc/binary/arisc fi cp ./drivers/arisc/binary/arisc output/ for file in $(find drivers sound crypto block fs security net -name "*.ko"); do cp $file ${LICHEE_MOD_DIR} done cp -f Module.symvers ${LICHEE_MOD_DIR} } ~~~ build_modules部分就没做事了 ### mkuboot编译uboot (这部分代码没有放出) ~~~ function mkuboot() { (cd ${LICHEE_UBOOT_DIR}; ./build.sh -p sun8iw8p1_nor) [ $? -ne 0 ] && echo "build u-boot Failed" && return 1 (cd ${LICHEE_UBOOT_DIR}; ./build.sh -p sun8iw8p1) [ $? -ne 0 ] && echo "build u-boot Failed" && return 1 return 0 } ~~~ ## extract-bsp 拷贝zimage和modules ~~~ CURDIR=$PWD cd $DEVICE #extract kernel if [ -f kernel ]; then rm kernel fi cp -rf $LICHEE_KERN_OUTDIR/zImage kernel echo "$DEVICE/zImage copied!" #extract linux modules if [ -d modules ]; then rm -rf modules fi mkdir -p modules/modules cp -rf $LINUXOUT_MODULE_DIR modules/modules echo "$DEVICE/modules copied!" chmod 0755 modules/modules/* cd $CURDIR ~~~ ## pack打包镜像 ~~~ function pack() { if [ "-d" == $1 ]; then echo "pack card" pack_card else echo "pack_normal" pack_normal fi return 0 } ~~~ ~~~ function pack_normal() { local platformdef=$tdevice echo "Pack to image........." ${platformdef} export CAMLINUX_IMAGE_OUT="$CAMLINUX_BUILD_TOP/out/target/product/${platformdef}" if [ "tiger-ipc" == ${platformdef} ]; then echo "copy tiger-ipc uboot bin files" cp -rf ${LICHEE_TOOLS_DIR}/pack/chips/sun8iw8p1/configs/tiger-ipc/bin ${LICHEE_TOOLS_DIR}/pack/chips/sun8iw8p1/ fi (cd ${LICHEE_TOOLS_DIR}/pack; ./pack -c sun8iw8p1 -p camdroid -b ${platformdef} ) [ $? -ne 0 ] && echo "pack Failed" && return 0 return 0 } function pack_card() { ... (cd ${LICHEE_TOOLS_DIR}/pack; ./pack -c sun8iw8p1 -p camdroid -b ${platformdef} -d card0 ) ... } ~~~ 打包过程: ./pack -c sun8iw8p1 -p camdroid -b ${platformdef} ~~~ do_prepare do_common echo "CAMLINUX_IMAGE_OUT="${CAMLINUX_IMAGE_OUT} do_pack_${PACK_PLATFORM} do_finish ~~~ ### do_prepare ~~~ tools_file_list=( common/tools/split_xxxx.fex chips/${PACK_CHIP}/tools/split_xxxx.fex common/tools/usbtool_test.fex chips/${PACK_CHIP}/tools/usbtool_test.fex common/tools/cardscript.fex chips/${PACK_CHIP}/tools/cardscript.fex common/tools/cardtool.fex chips/${PACK_CHIP}/tools/cardtool.fex common/tools/usbtool.fex chips/${PACK_CHIP}/tools/usbtool.fex common/tools/aultls32.fex chips/${PACK_CHIP}/tools/aultls32.fex common/tools/aultools.fex chips/${PACK_CHIP}/tools/aultools.fex ) configs_file_list=( common/toc/toc1.fex common/toc/toc0.fex common/imagecfg/image_linux.cfg common/partition/sys_partition_dump.fex common/partition/sys_partition_private.fex chips/${PACK_CHIP}/configs/default/* chips/${PACK_CHIP}/configs/${PACK_BOARD}/*.fex chips/${PACK_CHIP}/configs/${PACK_BOARD}/*.cfg ) boot_resource_list=( chips/${PACK_CHIP}/boot-resource/boot-resource:out/ chips/${PACK_CHIP}/boot-resource/boot-resource.ini:out/ chips/${PACK_CHIP}/configs/${PACK_BOARD}/bootlogo.bmp:out/boot-resource/ ) boot_file_list=( chips/${PACK_CHIP}/bin/boot0_nand_${PACK_CHIP}.bin:out/boot0_nand.fex chips/${PACK_CHIP}/bin/boot0_sdcard_${PACK_CHIP}.bin:out/boot0_sdcard.fex chips/${PACK_CHIP}/bin/boot0_spinor_${PACK_CHIP}.bin:out/boot0_spinor.fex chips/${PACK_CHIP}/bin/fes1_${PACK_CHIP}.bin:out/fes1.fex chips/${PACK_CHIP}/bin/u-boot-${PACK_CHIP}.bin:out/u-boot.fex chips/${PACK_CHIP}/bin/u-boot-spinor-${PACK_CHIP}.bin:out/u-boot-spinor.fex ) boot_file_secure=( chips/${PACK_CHIP}/bin/semelis.bin:out/semelis.bin chips/${PACK_CHIP}/bin/sboot_${PACK_CHIP}.bin:out/sboot.bin ) function do_prepare() { ... # Cleanup rm -rf out/ mkdir -p out/ printf "copying tools file\n" for file in ${tools_file_list[@]} ; do cp -f $file out/ 2> /dev/null done ... #拷贝各种fex到out下,包含开机画面等 ~~~ ### do_common 转换格式,通过fex更新boot ~~~ function do_common() { cd out/ busybox unix2dos sys_config.fex busybox unix2dos sys_partition.fex script sys_config.fex > /dev/null script sys_partition.fex > /dev/null cp -f sys_config.bin config.fex if [ "x${PACK_PLATFORM}" = "xdragonboard" ] ; then busybox dos2unix test_config.fex cp test_config.fex boot-resource/ busybox unix2dos test_config.fex script test_config.fex > /dev/null cp test_config.bin boot-resource/ fi # Those files for SpiNor. We will try to find sys_partition_nor.fex if [ -f sys_partition_nor.fex -o \ -f sys_partition_nor_${PACK_PLATFORM}.fex ]; then mv -f sys_partition_nor_${PACK_PLATFORM}.fex \ sys_partition_nor.fex >/dev/null 2>&1 # Here, will create sys_partition_nor.bin busybox unix2dos sys_partition_nor.fex script sys_partition_nor.fex > /dev/null update_boot0 boot0_spinor.fex sys_config.bin SDMMC_CARD > /dev/null update_uboot u-boot-spinor.fex sys_config.bin >/dev/null fi # Those files for Nand or Card update_boot0 boot0_nand.fex sys_config.bin NAND > /dev/null update_boot0 boot0_sdcard.fex sys_config.bin SDMMC_CARD > /dev/null update_uboot u-boot.fex sys_config.bin > /dev/null update_fes1 fes1.fex sys_config.bin > /dev/null fsbuild boot-resource.ini split_xxxx.fex > /dev/null if [ "x${PACK_FUNC}" = "xprvt" ] ; then u_boot_env_gen env_burn.cfg env.fex > /dev/null else u_boot_env_gen env.cfg env.fex > /dev/null fi if [ -f "$LICHEE_OUT/arisc" ]; then ln -s $LICHEE_OUT/arisc arisc.fex fi } ~~~ ### do_pack_${PACK_PLATFORM} ~~~ function do_pack_android() { printf "packing for android\n" if [ -z "${ANDROID_IMAGE_OUT}" ] ; then pack_error "please specify ANDROID_IMAGE_OUT env" exit 1 fi ln -s ${ANDROID_IMAGE_OUT}/boot.img boot.fex ln -s ${ANDROID_IMAGE_OUT}/system.img system.fex ln -s ${ANDROID_IMAGE_OUT}/recovery.img recovery.fex if [ -f ${ANDROID_IMAGE_OUT}/userdata.img ] ; then ln -s ${ANDROID_IMAGE_OUT}/userdata.img userdata.fex fi if [ "x${PACK_SIG}" = "xsig" ] ; then echo "signature sunxi mbr" signature sunxi_mbr.fex dlinfo.fex echo "signature over" elif [ "x${PACK_SIG}" = "xsecure" ] ; then do_signature else echo "normal" fi } function do_pack_camdroid() { printf "packing for camdroid\n" if [ -z "${CAMLINUX_IMAGE_OUT}" ] ; then pack_error "please specify CAMLINUX_IMAGE_OUT env" exit 1 fi ln -s ${CAMLINUX_IMAGE_OUT}/boot.img boot.fex ln -s ${CAMLINUX_IMAGE_OUT}/system.img rootfs.fex #使用前面打包的system.img作为根文件系统 } function do_pack_dragonboard() { printf "packing for dragonboard\n" ln -s ${LICHEE_OUT}/boot.img boot.fex ln -s ${LICHEE_OUT}/rootfs.ext4 rootfs.fex } function do_pack_linux() { printf "packing for linux\n" #输出目录是linux-3.4/output/ ln -s ${LICHEE_OUT}/vmlinux.tar.bz2 vmlinux.fex ln -s ${LICHEE_OUT}/boot.img boot.fex # ln -s ${LICHEE_OUT}/rootfs.ext4 rootfs.fex if [ "x${PACK_SIG}" = "xsecure" ] ; then do_signature else echo "normal" fi } ~~~ ### do_finish ~~~ function do_finish() { # Yeah, it should contain all files into full_img.fex for spinor # Because, as usually, spinor image size is very small. # If fail to create full_img.fex, we should fake it empty. # WTF, it is so ugly! It must be sunxi_mbr.fex, not sunxi_mbr_xxx.fex # Check whether sys_partition_nor.bin is exist, and create sunxi_mbr.fex # for Nor. if [ -f sys_partition_nor.bin ]; then mv -f sys_partition.bin sys_partition.bin_back cp -f sys_partition_nor.bin sys_partition.bin update_mbr sys_partition.bin 1 > /dev/null merge_package full_img.fex boot0_spinor.fex \ u-boot-spinor.fex sunxi_mbr.fex sys_partition.bin mv -f sys_partition.bin_back sys_partition.bin fi if [ ! -f full_img.fex ]; then echo "full_img.fex is empty" > full_img.fex fi update_mbr sys_partition_nor.bin 1 > /dev/null dragon image.cfg sys_partition_nor.fex if [ -e ${IMG_NAME} ]; then mv ${IMG_NAME} ../${IMG_NAME} echo '----------image is at----------' echo -e '\033[0;31;1m' echo ${ROOT_DIR}/${IMG_NAME} echo -e '\033[0m' fi cd .. printf "pack finish\n" } ~~~ ## 打包完成后的布局 ~~~ Device Boot Start End Blocks Id System /dev/sdf1 56992 1939454 941231+ b W95 FAT32 /dev/sdf2 * 40992 46111 2560 6 FAT16 /dev/sdf3 1 56992 28496 85 Linux extended /dev/sdf5 46112 55199 4544 83 Linux /dev/sdf6 55200 56223 512 83 Linux /dev/sdf7 56224 56479 128 83 Linux /dev/sdf8 56480 56735 128 83 Linux /dev/sdf9 56736 56863 64 83 Linux /dev/sdf10 56864 56991 64 83 Linux ~~~ 配置里的分区表: ~~~ [partition] name = boot size = 5120 downloadfile = "boot.fex" #内核ramfs [partition] name = system size = 9088 downloadfile = "rootfs.fex" #根文件系统 [partition] name = cfg size = 1024 downloadfile = "cfg.fex" #jffs2的cfg,用于保存可变的配置字段 [partition] name = boot_logo size = 256 downloadfile = "boot_logo.fex" [partition] name = shutdown_logo size = 256 downloadfile = "shutdown_logo.fex" [partition] name = env size = 128 downloadfile = "env.fex" #uboot启动的环境变量 [partition] name = private size = 128 ~~~ ### cfg.fex的生成 device/softwinner/tiger-cdr/res/make_cfg_fex.sh ~~~ CFG_PATH="/pack/chips/sun8iw8p1/configs/CDR/cfg.fex" DEST=$LICHEE_TOOLS_DIR$CFG_PATH echo "./mkfs.jffs2 -d ./data -o cfg.fex" #-p total size ./mkfs.jffs2 -d ./cfg -p 0x80000 -o cfg.fex echo "move cfg.fex to $DEST" mv cfg.fex $DEST ~~~ ### boot.fex(boot.img)生成 ~~~ INSTALLED_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/boot.img $(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_FILES) $(call pretty,"Target boot image: $@") $(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $@ $(hide) $(call assert-max-image-size,$@,$(BOARD_BOOTIMAGE_PARTITION_SIZE),raw) ~~~ ~~~ regen_rootfs_cpio() { echo "regenerate rootfs cpio" cd ${LICHEE_KDIR}/output echo "###" if [ -x "../scripts/build_rootfs.sh" ]; then ../scripts/build_rootfs.sh e ./rootfs.cpio.gz > /dev/null else echo "No such file: scripts/build_rootfs.sh" exit 1 fi echo "###" mkdir -p ./skel/lib/modules/${KERNEL_VERSION} echo "###" if [ -e ${LICHEE_MOD_DIR}/nand.ko ]; then cp ${LICHEE_MOD_DIR}/nand.ko ./skel/lib/modules/${KERNEL_VERSION} if [ $? -ne 0 ]; then echo "copy nand module error: $?" exit 1 fi fi echo "###ttt" ko_file=`find ./skel/lib/modules/$KERNEL_VERSION/ -name *.ko` if [ ! -z "$ko_file" ]; then ${STRIP} -d ./skel/lib/modules/$KERNEL_VERSION/*.ko fi echo "###ttt" rm -f rootfs.cpio.gz ../scripts/build_rootfs.sh c rootfs.cpio.gz > /dev/null rm -rf skel echo "###ttt" cd - > /dev/null } ~~~ TARGET_ROOT_OUT := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ROOT) # 修改配置生成linux镜像 由上面的走读可知,需要生成boot分区,linux根文件系统分区,及对应的分区表 内核配置: linux-3.4/arch/arm/configs/sun8iw8p1smp_defconfig linux-3.4/arch/arm/configs/sun8iw8p1smp_tiger_cdr_defconfig 配置内核: make ARCH=arm menuconfig 板级配置和开机logo ls tools/pack/chips/sun8iw8p1/configs/tiger-cdr/ boot-resource cfg.fex sys_config.fex sys_partition_nor_camdroid.fex