#!/bin/bash -e usage () { set +x cat <&2 echo usage exit 1 } cleanup_and_exit () { readonly result="$?" rm -rf "${TEMP_DIR}" exit "${result}" } # $1 header file to parse # $2 key to get get_bootimg_header_field() { local hfile="$1" local key="$2" if [ ! -f "${hfile}" ]; then echo "Boot image header file does not exist." >&2 exit 1 fi sed -ne "/^${key}: /s/^${key}: //p" "${hfile}" } # adb root function adb_wait_root() { if ! adb -s $SERIALNO get-state >& /dev/null ; then echo echo "!!! Device $SERIALNO is not reachable via ADB !!!" echo "Please make sure device boot into Android and tap \"Allow\" to the \"Allow USB Debugging\" dialog." echo exit 1 fi if ! adb -s $SERIALNO root | grep 'adbd is already running as root' ; then sleep 2 adb -s $SERIALNO wait-for-device >& /dev/null fi } # Dump partitions from device function dump_boot_images_from_device() { adb_wait_root for img in dtbo boot vendor_boot vendor_dlkm; do if [ "${img}" == "vendor_dlkm" ]; then adb -s $SERIALNO pull /dev/block/$(adb -s $SERIALNO shell getprop dev.mnt.blk.${img}) "${DEVICE_DIR}"/${img}.img else adb -s $SERIALNO pull /dev/block/bootdevice/by-name/${img}$(adb -s $SERIALNO shell getprop ro.boot.slot_suffix) "${DEVICE_DIR}"/${img}.img fi done } trap cleanup_and_exit EXIT ARGS=() KCOMPRESS=.lz4 while [[ $# -gt 0 ]]; do case "$1" in --*) exit_badparam "unrecognized option '$1'" shift ;; *) ARGS+=("$1") shift ;; esac done if [[ ${#ARGS[*]} -gt 4 ]]; then echo exit_badparam "Unexpected number of arguments" fi readonly SERIALNO="${ARGS[0]}" readonly KERNEL_DIST_DIR="${ARGS[1]}" readonly OUTPUT_DIR="${ARGS[2]}" readonly DEVICE_DIR="${ARGS[2]}"/DUMP_FROM_DEVICE readonly TEMP_DIR="$(mktemp -d --tmpdir "$(basename $0)"_XXXXXXXX)" readonly LZ4="prebuilts/kernel-build-tools/linux-x86/bin/lz4" readonly LZ4_COMPRESS="${LZ4} -c -12 --favor-decSpeed" readonly LZ4_DECOMP="${LZ4} -c -f -d" # Create destination directory if need be if [ -n "${OUTPUT_DIR}" ] && [ ! -d "${OUTPUT_DIR}" ]; then mkdir -p "${OUTPUT_DIR}" || true fi RESP=${ARGS[3]:-""} # Create device directory and dump paritions from device if need be if [ -n "${DEVICE_DIR}" ] && [ ! -d "${DEVICE_DIR}" ]; then mkdir -p "${DEVICE_DIR}" || true dump_boot_images_from_device else if [ "${RESP}" == "" ]; then echo read -p "Previous dumped files already exist in ${DEVICE_DIR}/ !!! Do you want to dump from device and replace it? (y/N): " RESP echo fi case $RESP in [Yy]* ) dump_boot_images_from_device; ;; esac fi KERNEL_IMAGE="${KERNEL_DIST_DIR}/Image${KCOMPRESS}" # Extract boot images echo "Extracting boot.img from ${DEVICE_DIR}/ ..." cp -rf "${DEVICE_DIR}"/boot.img "${TEMP_DIR}"/boot.img echo "Unpacking boot.img ..." tools/mkbootimg/unpack_bootimg.py --boot_img "${TEMP_DIR}"/boot.img \ --out "${TEMP_DIR}"/bootimg > "${TEMP_DIR}"/bootimg.header get_bhf() { get_bootimg_header_field "${TEMP_DIR}"/bootimg.header "$1" } header_version="$(get_bhf 'boot image header version')" if ! [ "${header_version}" -ge 0 ]; then echo "Invalid boot image header version: ${header_version}" >&2 && exit 1 fi if [ "${header_version}" -ge 4 ]; then echo "Extracting vendor_boot.img from ${DEVICE_DIR}/ ..." cp -rf "${DEVICE_DIR}"/vendor_boot.img "${TEMP_DIR}"/vendor_boot.img fi get_vendor_bhf() { get_bootimg_header_field "${TEMP_DIR}"/vendor_bootimg.header "$1" } # Concatenate provided .dtb files into dtb.img cat "${KERNEL_DIST_DIR}"/*.dtb > "${TEMP_DIR}"/dtb.img MKBOOTIMGARGS=() MKBOOTIMG_VENDORARGS=() boot_ramdisk="${TEMP_DIR}"/bootimg/ramdisk if [ "${header_version}" -eq 4 ]; then echo "Unpacking vendor_boot.img ..." tools/mkbootimg/unpack_bootimg.py --boot_img "${TEMP_DIR}"/vendor_boot.img \ --out "${TEMP_DIR}"/vendor_bootimg --format=mkbootimg -0 > "${TEMP_DIR}"/vendor_bootimg.args while IFS= read -r -d '' ARG; do MKBOOTIMG_VENDORARGS+=("${ARG}") done <"${TEMP_DIR}"/vendor_bootimg.args MKBOOTIMG_VENDORARGS+=("--vendor_boot" "${TEMP_DIR}"/vendor_boot.img) if [ ! -f "${TEMP_DIR}"/vendor_bootimg/vendor-ramdisk-by-name/ramdisk_dlkm ]; then echo "dlkm ramdisk fragment missing from vendor_boot.img" >&2 exit 1 fi cp "${KERNEL_DIST_DIR}"/initramfs.img \ "${TEMP_DIR}"/vendor_bootimg/vendor-ramdisk-by-name/ramdisk_dlkm if [ ! -f "${TEMP_DIR}"/vendor_bootimg/dtb ]; then echo "dtb missing from vendor_boot.img" >&2 exit 1 fi cp "${TEMP_DIR}"/dtb.img \ "${TEMP_DIR}"/vendor_bootimg/dtb MKBOOTIMGARGS+=("--ramdisk" "${boot_ramdisk}") else echo "ERROR: Unsupported boot image header version: ${header_version}" >&2 exit 1 fi # For header_version == 4, "unpack_bootimg --format=mkbootimg" will provide the # --dtb argument. if [ "${header_version}" -lt 4 ]; then MKBOOTIMGARGS+=("--dtb" "${TEMP_DIR}"/dtb.img) fi MKBOOTIMGARGS+=("--header_version" "${header_version}") MKBOOTIMGARGS+=("--cmdline" "$(get_bhf 'command line args')") # Create boot.img and vendor_boot.img. (vendor_boot.img is only created for # header_version is 4 or later) echo "Creating repacked boot.img and vendor_boot.img..." tools/mkbootimg/mkbootimg.py \ --kernel "$KERNEL_IMAGE" \ "${MKBOOTIMGARGS[@]}" \ "${MKBOOTIMG_VENDORARGS[@]}" \ --output "${TEMP_DIR}"/boot.img BOOT_SIZE=$(stat -c%s "$DEVICE_DIR"/boot.img) prebuilts/kernel-build-tools/linux-x86/bin/avbtool add_hash_footer \ --image "${TEMP_DIR}"/boot.img \ --partition_size ${BOOT_SIZE} \ --partition_name boot VENDOR_BOOT_SIZE=$(stat -c%s "$DEVICE_DIR"/vendor_boot.img) if [ "${header_version}" -ge 4 ]; then prebuilts/kernel-build-tools/linux-x86/bin/avbtool add_hash_footer \ --image "${TEMP_DIR}"/vendor_boot.img \ --partition_size ${VENDOR_BOOT_SIZE} \ --partition_name vendor_boot fi # Update boot.img in device archive cp -rf "${TEMP_DIR}/boot.img" "${OUTPUT_DIR}" if [ "${header_version}" -ge 4 ]; then # and vendor_boot.img (if header_version >= 4) echo "Updating boot.img and vendor_boot.img in ${OUTPUT_DIR}/ ..." cp -rf "${TEMP_DIR}/vendor_boot.img" "${OUTPUT_DIR}" fi # Update {dtbo.img,vendor_dlkm.img} if they are products of the kernel build for img in dtbo.img vendor_dlkm.img; do if [ -f "${KERNEL_DIST_DIR}/${img}" ]; then echo "Copying ${img} into ${OUTPUT_DIR}/ ..." cp -rf "${KERNEL_DIST_DIR}/${img}" "${OUTPUT_DIR}" fi done echo echo "Images have been repacked at: ${OUTPUT_DIR}"/ echo echo "You may use below command to flash repacked kernel images:" echo "-------------------------------------------------------------" echo "cd ${OUTPUT_DIR}/" echo "fastboot oem disable-verity" echo "fastboot flash boot boot.img" echo "fastboot flash dtbo dtbo.img" echo "fastboot flash vendor_boot vendor_boot.img" echo "fastboot reboot fastboot" echo "fastboot flash vendor_dlkm vendor_dlkm.img" echo "fastboot -w" echo "fastboot reboot" echo "-------------------------------------------------------------" echo