#!/bin/bash usage() { echo "Usage: $0 --build-directory [build directory, default: /build] --vendor --orgcode --channel-id --package-type [packtype: owner or other; default: owner] --project-id --pipeline-id --url-tag --qrcode-app --help" exit 1 } BUILD_DIR="./image_build" VENDOR="" ORGCODE="" CHANNELID="" PACK_TYPE="owner" PROJECT_ID="" PIPELINE_ID="" URL_TAG="" INSTALL_QRCODE_APP="false" CHROOT_TYPE="androidrom" DEPLOY="elf" export PATH=$(pwd)/tools/android-tools:$(pwd)/tools/:$(pwd)/tools/amlogic_tool:$(pwd)/tools/rockchip_tool:$(pwd)/tools/rockchip_tool/obsutil:$(pwd)/tools/allwinner:$PATH PARSED_ARUGMENTS=$(getopt -a -n "$0" -o 'x' --long help,build-directory:,vendor:,orgcode:,channel-id:,package-type:,project-id:,pipeline-id:,url-tag:,qrcode-app:, -- "$@") eval set -- "${PARSED_ARUGMENTS}" while : do case "$1" in --build-directory) BUILD_DIR="$2"; shift 2;; --vendor) VENDOR="$2"; shift 2;; --orgcode) ORGCODE="$2"; shift 2;; --channel-id) CHANNELID="$2"; shift 2;; --package-type) PACK_TYPE="$2"; shift 2;; --project-id) PROJECT_ID="$2"; shift 2;; --pipeline-id) PIPELINE_ID="$2"; shift 2;; --url-tag) URL_TAG="$2"; shift 2;; --qrcode-app) INSTALL_QRCODE_APP="$2"; shift 2;; --help) usage ;; --) shift; break;; *) usage ;; esac done build_dir=$(mktemp -d "$BUILD_DIR"/tmp.XXXXX) packge_dir=$(mktemp -d "$BUILD_DIR"/tmp.XXXXX) boot_dir=$(mktemp -d "$BUILD_DIR"/tmp.XXXXX) system_mount_point="" system_path="" systemfile="" systemfile_ext4="" super_file="" super_file_ext4="" update_img_tmp_dir="$build_dir/img_dir" super_img_tmp_dir="$build_dir/img_dir/super" ALLWINNER_DEFAULT_SYSTEM_PARTITION_NAME="system_a" ROCKCHIP_DEFAULT_SYSTEM_PARTITION_NAME="system" is_amlogic=0 is_allwinner=0 is_rockchip=0 outfile_path="" validate_partition_size_change() { local group_name local size local total_size local group_maxinum_size local c_super_file="$1" local parttion_name="$2" local partition_info_dump local group_info_dump group_name=$(get_group_name "$c_super_file" "$parttion_name") partition_info_dump=$(lpdump -j "$c_super_file" | jq -c -r '.partitions[]') for item in $partition_info_dump do if [[ "$(echo "$item" | jq -r '.group_name')" == "$group_name" ]] then size=$(echo "$item" | jq -r '.size') total_size=$((total_size+size)) fi done total_size=$((total_size+251658240)) group_info_dump=$(lpdump -j "$c_super_file" | jq -c -r '.groups[]') for item in $group_info_dump do if [[ "$(echo "$item" | jq -r '.name')" == "$group_name" ]] then group_maxinum_size=$(echo "$item" | jq -r '.maximum_size') break fi done if [[ -n "$group_maxinum_size" ]] && [[ "$group_maxinum_size" -lt "$total_size" ]] then return 1 fi return 0 } get_group_name() { local group_name local partition_info_dump local c_super_file="$1" local parttion_name="$2" partition_info_dump=$(lpdump -j "$c_super_file" | jq -c -r '.partitions[]') for item in $partition_info_dump do if [[ "$(echo "$item" | jq -r '.name')" == "$parttion_name" ]] then group_name=$(echo "$item" | jq -r '.group_name') fi done printf "%s" "$group_name" } resize_system_image() { local c_system_file="$1" local image_size local loopdev image_size="$(stat -c "%s" "$c_system_file")" image_size=$((image_size+251658240)) # +240M qemu-img resize -f raw "$c_system_file" "$image_size" loopdev=$(losetup -P -f --show "$c_system_file") e2fsck -f -y "$loopdev" resize2fs "$loopdev" losetup -d "$loopdev" } __unpack_super_img() { local system_partition_name="$1" if __is_sparse_super then simg2img "$super_file" "$super_file_ext4" lpunpack "$super_file_ext4" "$super_img_tmp_dir" else lpunpack "$super_file" "$super_img_tmp_dir" fi systemfile="$super_img_tmp_dir/${system_partition_name}.img" systemfile_ext4="$super_img_tmp_dir/${system_partition_name}.img.ext4" if file "$systemfile" | grep "Android sparse image" then resize_system_image "$systemfile_ext4" else resize_system_image "$systemfile" fi } unpack_and_mount_image() { local img="$1" local loopdev mkdir -p "$update_img_tmp_dir" mkdir -p "$super_img_tmp_dir" if aml_image_v2_packer -c "$img" then echo "Amlogic Image Format Detected.." is_amlogic=1 systemfile="$build_dir/system.PARTITION" systemfile_ext4="$build_dir/system.PARTITION.ext4" aml_image_v2_packer -d "$img" "$build_dir" elif sunxi-fw info "$img" | grep -i -q "PhoenixSuite image file" then echo "Allwinner PhoenixSute Image Format Detected.." is_allwinner=1 cp "$img" "$update_img_tmp_dir/update.img" pushd "$update_img_tmp_dir" imgrepacker unpack ./update.img popd rm -f "$update_img_tmp_dir/update.img" super_file="$update_img_tmp_dir/update.img.dump/super.fex" super_file_ext4="$update_img_tmp_dir/update.img.dump/super.fex.ext4" __unpack_super_img "$ALLWINNER_DEFAULT_SYSTEM_PARTITION_NAME" else echo "Rockchip Format Detected.." is_rockchip=1 cp "$img" "$update_img_tmp_dir/update.img" mkdir -p "$update_img_tmp_dir/update.img.dump" rkImageMaker -unpack "$update_img_tmp_dir/update.img" "$update_img_tmp_dir/update.img.dump" # workround: afptool 工具好像有路径读取问题 pushd "$update_img_tmp_dir" afptool -unpack "./update.img.dump/firmware.img" "./update.img.dump" popd rm -f "$update_img_tmp_dir/update.img" rm -f "$update_img_tmp_dir/update.img.dump/firmware.img" rm -f "$update_img_tmp_dir/update.img.dump/boot.bin" super_file="$update_img_tmp_dir/update.img.dump/Image/super.img" super_file_ext4="$update_img_tmp_dir/update.img.dump/Image/super.img.ext4" __unpack_super_img "$ROCKCHIP_DEFAULT_SYSTEM_PARTITION_NAME" fi if __is_sparse_system then simg2img "$systemfile" "$systemfile_ext4" loopdev=$(losetup -P -f --show "$systemfile_ext4") else loopdev=$(losetup -P -f --show "$systemfile") fi system_mount_point="$build_dir/system" mkdir "$system_mount_point" mount "$loopdev" "$system_mount_point" if [[ -d "$system_mount_point/system" ]] then system_path="$system_mount_point/system" else system_path="$system_mount_point" fi losetup -d "$loopdev" } install_dianxin() { local img="$1" local android_sdk unpack_and_mount_image "$img" touch "$system_path/.androidrom" rm -f "$system_path/hugep-all.zip" rm -f "$system_path/bin/hugep-all.zip" android_sdk="$(grep "build\.version\.sdk" "$system_path"/build.prop | awk -F'=' '{print $2}')" android_sdk="${android_sdk//$'\r'}" android_sdk="${android_sdk//$'\n'}" if [[ "$android_sdk" -ge 25 ]] then find ./services/ -type f -name "*.rc" -exec install -t "$system_path"/etc/init/ {} \; else pushd "$boot_dir" abootimg -x "$build_dir/boot.PARTITION" ramdisk mkdir initrd_dir pushd initrd_dir gunzip -c ../initrd.img | cpio -i popd cp initrd_dir/init.rc . rm -rf initrd_dir popd cp "$boot_dir"/init.rc "$packge_dir"/init.rc rm -rf "$boot_dir" if ! find_autostart -script_name preinstall.sh -initrc "$packge_dir"/init.rc -root_path "$build_dir" > "$packge_dir"/find_autostart.log 2>/dev/null then find_autostart -script_name recovery.sh -initrc "$packge_dir"/init.rc -root_path "$build_dir" > "$packge_dir"/find_autostart.log 2>/dev/null fi local auto_start_script auto_start_script="$(cat "$packge_dir"/find_autostart.log)" if [[ -z "$auto_start_script" ]] && [[ -f "$system_path"/bin/startsoftdetector.sh ]] then # TODO: startsoftdetector.sh 会阻塞在某一步,要把 starthugep.sh 加在中间部分 auto_start_script="/system/bin/startsoftdetector.sh" fi # NOTE: 返回的脚本路径里一定以 /system/ 开头, 所以下边拼路径时没有加上 /system if [[ -n "$auto_start_script" ]] then local _script_path _script_path="$system_path/$(echo "$auto_start_script" | sed 's|^/system||')" local tmp_script_path="/tmp/tmp_auto_start.sh" local start_n if ! grep -q "#!/system/bin/sh" "$_script_path" then start_n=1 else start_n=2 fi { echo "#!/system/bin/sh" echo " " echo "/system/bin/starthugep.sh > /dev/null 2>&1 &" tail -n +"${start_n}" "$_script_path" } > "$tmp_script_path" cat "$tmp_script_path" | tee "$_script_path" chmod 0755 "$_script_path" chcon u:object_r:drmserver_exec:s0 "$_script_path" fi fi cp -f "$build_dir/hugep-all.zip" "$system_path"/bin/hugep-all.zip find ./services/ -type f ! -name "*.rc" ! -name "*.zip" ! -name "*.apk" ! -name "hugep" ! -name "hugep-start.sh" -exec install -m 0777 -t "$system_path"/bin/ {} \; for file in $(find ./services/ -type f ! -name "*.rc" ! -name "*.zip" ! -name "*.apk" ! -name "hugep" ! -name "hugep-start.sh") do chcon u:object_r:drmserver_exec:s0 "$system_path/bin/$(basename "$file")" done for file in $(find ./services/ -type f -name "*.zip") do chcon u:object_r:system_file:s0 "$system_path/bin/$(basename "$file")" done for file in $(find ./services/ -type f -name "*.rc" ! -name "*.zip") do chcon u:object_r:drmserver_exec:s0 "$system_path/etc/init/$(basename "$file")" done if [[ "$android_sdk" -ge 31 ]] && [[ "$INSTALL_QRCODE_APP" == "true" ]] then find ./services/ -type f -name "*.apk" -exec install -m 0644 -t "$system_path"/preinstall/ {} \; fi pack_image "$img" } __is_sparse_super() { if file "$super_file" | grep "Android sparse image" then return 0 else return 1 fi } __pack_super_img() { local system_partition_name="$1" local c_super_file if __is_sparse_super then c_super_file="$super_file_ext4" else c_super_file="$super_file" fi local c_group_name c_group_name="$(get_group_name "$c_super_file" "$system_partition_name")" if validate_partition_size_change "$c_super_file" "$system_partition_name" then lpadd --readonly \ --replace \ "$c_super_file" \ "$system_partition_name" \ "$c_group_name" \ "$systemfile" if __is_sparse_super then img2simg "$super_file_ext4" "$super_file" rm -rf "$super_file_ext4" fi else repack.sh "$c_super_file" "$c_group_name" "$systemfile" "$system_partition_name" if __is_sparse_super then mv "$(dirname "$c_super_file")/super.new.img" "$super_file" else simg2img "$(dirname "$c_super_file")/super.new.img" "$super_file" rm -f "$(dirname "$c_super_file")/super.new.img" fi fi } __get_chip_from_parameter() { local chip chip=$(rkChipInfo -f "$IMAGE_FILE" -o 123 | awk '{print $1}') [[ -z "$chip" ]] && chip=$(rkChipInfo -f "$IMAGE_FILE" -o 21 | awk '{print $1}') printf "RK%s" "$chip" } __is_sparse_system() { if file "$systemfile" | grep "Android sparse image" then return 0 else return 1 fi } pack_image() { local img img="$1" sync umount "$system_mount_point" rm -rf "$system_mount_point" sync if __is_sparse_system then rm -f "$systemfile" img2simg "$systemfile_ext4" "$systemfile" rm -f "$systemfile_ext4" fi outfile_path="${packge_dir}/${CHANNELID}-$(basename "$img")" if [[ "$is_amlogic" == "1" ]] then echo "Amlogic Image Format Detected.." aml_image_v2_packer -r "/$build_dir/image.cfg" "$build_dir" "$outfile_path" elif [[ "$is_allwinner" == "1" ]] then echo "Allwinner PhoenixSute Image Format Detected.." __pack_super_img "$ALLWINNER_DEFAULT_SYSTEM_PARTITION_NAME" sleep 5 pushd "$update_img_tmp_dir" imgrepacker pack ./update.img.dump popd mv "$update_img_tmp_dir/update.img" "$outfile_path" elif [[ "$is_rockchip" == "1" ]] then echo "Rockchip Image Format Detected.." __pack_super_img "$ROCKCHIP_DEFAULT_SYSTEM_PARTITION_NAME" cp -f "$update_img_tmp_dir/update.img.dump/MiniLoaderAll.bin" "$update_img_tmp_dir/update.img.dump/Image/MiniLoaderAll.bin" cp -f "$update_img_tmp_dir/update.img.dump/parameter.txt" "$update_img_tmp_dir/update.img.dump/Image/parameter.txt" afptool -pack "$update_img_tmp_dir/update.img.dump" "$update_img_tmp_dir/update.img" local chip_parameter chip_parameter="$(__get_chip_from_parameter "${update_img_tmp_dir}/update.img.dump/parameter.txt")" # e.g. rkImageMaker -RK322H output/MiniLoaderAll.bin output/Image/update.img update.img -os_type:androidos rkImageMaker "-${chip_parameter}" \ "$update_img_tmp_dir/update.img.dump/MiniLoaderAll.bin" "$update_img_tmp_dir/update.img" "$outfile_path" \ -os_type:androidos fi rm -rf "$build_dir" } generate_vendor_confg() { local yaml_file_src local yaml_file local config_json_file yaml_file="$build_dir"/vendor.yaml yaml_file_src="$build_dir"/vendor.yaml.src cp vendor.yaml.src "$yaml_file_src" sed -i'' -e "s#__VENDOR__#$VENDOR#g" \ -e "s#__ORGCODE__#$ORGCODE#g" \ -e "s#__CHROOT_TYPE__#$CHROOT_TYPE#g" \ -e "s#__DEPLOY__#$DEPLOY#g" \ -e "s#__CHANNEL_ID__#$CHANNELID#g" \ -e "s#__PACK_TYPE__#$PACK_TYPE#g" \ -e "s#__CI_PROJECT_ID__#$PROJECT_ID#g" \ -e "s#__CI_PIPELINE_ID__#$PIPELINE_ID#g" "$yaml_file_src" aio -m enc -i "$yaml_file_src" -o "$yaml_file" config_json_file="$build_dir"/config.json cp config.json.src "$config_json_file" sed -i'' "s#__CHANNEL_ID__#$CHANNELID#g" "$config_json_file" } update_hugepall_zipfile() { local yaml_file local hugep_zip_file local hugep_zip_file_origin local config_json_file local config_json_file_bak yaml_file="$build_dir"/vendor.yaml hugep_zip_file="$build_dir/hugep-all.zip" hugep_zip_file_origin="./services/hugep-all.zip" config_json_file="$build_dir"/config.json config_json_file_bak="$build_dir"/config.json.bak cp "$config_json_file" "$config_json_file_bak" cp "$hugep_zip_file_origin" "$hugep_zip_file" zip -u -j "$hugep_zip_file" "$yaml_file" zip -u -j "$hugep_zip_file" "./services/hugep-start.sh" zip -u -j "$hugep_zip_file" "$config_json_file" zip -u -j "$hugep_zip_file" "$config_json_file_bak" zip -u -j "$hugep_zip_file" "./services/hugep" } upload() { local date_i local outfile local outfile_gz local uri local random_num local -A result outfile="$outfile_path" outfile_gz="${outfile}.gz" date_i="$(date +%Y-%m-%d-%s)" zstd --ultra --format=gzip "$outfile" -o "$outfile_gz" random_num=$(< /dev/urandom tr -dC 0-9a-z | head -c 8) [[ -z "$URL_TAG" ]] && URL_TAG="${date_i}-${random_num}" uri="product/terminal/chroot_androidrom/""$ORGCODE/${date_i}-${URL_TAG}/$(basename "$outfile_gz")" obsutil cp "$outfile_gz" obs://fae-cdn.linkfog.cn/"$uri" result["url"]="https://fae-cdn.linkfog.cn/""$uri" result["md5"]="$(md5sum "${outfile}" | awk '{print $1}')" mkdir -p .result jq -n --arg url "${result[url]}" --arg md5 "${result[md5]}" '{$url, $md5}' > ".result/${PROJECT_ID}-${PIPELINE_ID}.json" echo ".result/${PROJECT_ID}-${PIPELINE_ID}.json" cat ".result/${PROJECT_ID}-${PIPELINE_ID}.json" rm -f "$outfile" "$outfile_gz" rm -rf "$packge_dir" } IMAGE_FILE="/baseimages/$VENDOR-$ORGCODE.img" [[ ! -f "$IMAGE_FILE" ]] && IMAGE_FILE="CH-A03.img" generate_vendor_confg update_hugepall_zipfile install_dianxin "$IMAGE_FILE" upload