blob: 0c29c25ef60b6d231ddd5acf151a8828752d83a7 [file] [log] [blame]
#!/bin/bash -e
usage () {
set +x
cat <<EOF
Usage: $0 device_serialno kernel_dist_dir output_dir
e.g. $0 123456789ABCDE out/mixed/dist output_dir
1) device_serialno is device serial-number can be found from "adb devices".
2) kernel_dist_dir is the path to where the kernel binaries can be found
Image.lz4
initramfs.img
*.dtb
dtbo.img
vendor_dlkm.img
3) out_dir is the path to where the new build will be placed.
************************************************************************
This script is intended to avoid the dependency issue between device base-rom
and kernel prebuilt ramdisks under prebuilt/boot-artifacts/ramdisk/. To
achieve this, this script will dump/extract ramdisks from device via ADB
and recreate boot.img and vendor_boot.img based on it.
This script does not re-create any of the vbmeta partition images which
dm-verity has to be disabled prior to flashing these images.
Please refer to b/203499549 for the details.
************************************************************************
EOF
}
# Print error message and exit.
# Usage: exit_badparam message
#
# message is a string to be displayed before exit.
exit_badparam () {
echo "ERROR: $1" >&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.dev.${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