camdriod 走读
最后更新于:2022-04-01 23:27:22
# 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
';