mirror of
https://github.com/xiaolu/mkbootimg_tools.git
synced 2026-02-13 21:49:29 +01:00
file and magic error out when handling lzop compression types Workaround is to find lzop header first if it exists by searching for its hex value TODO - fix file and magic to read lzop compression types properly and eliminate this workaround Currently this method uses busybox for handling lzop compressions. Insure busybox supports lzop or else this will fail TODO - compile lzop statically and eliminate the need for busybox having lzop support
445 lines
15 KiB
Bash
445 lines
15 KiB
Bash
#!/system/xbin/bash
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
#
|
|
#boot.img tool
|
|
#original author: xiaolu
|
|
#heavily modified by: Modding.MyMind
|
|
|
|
#set -x # for debugging
|
|
|
|
trap "clean" 2 3 4
|
|
workdir=$(pwd)
|
|
toolpath=$(readlink -f $0)
|
|
tooldir=$(dirname $toolpath)
|
|
mkbootimg=$tooldir/mkbootimg
|
|
mkbootfs=$tooldir/mkbootfs
|
|
busybox=$(command -v busybox)
|
|
od=$tooldir/od
|
|
gzip=$tooldir/gzip
|
|
lz4=$tooldir/lz4
|
|
lzma=$tooldir/lzma
|
|
xz=$tooldir/xz # Also used for lzma compression
|
|
grep=$tooldir/grep
|
|
cpio=$tooldir/cpio
|
|
magic=$tooldir/magic
|
|
file=$tooldir/file
|
|
old_bootimg=true
|
|
C_OUT="\033[0;1m"
|
|
C_ERR="\033[31;1m"
|
|
C_CAUT="\033[33;1m"
|
|
C_CLEAR="\033[0;0m"
|
|
|
|
pout() {
|
|
$busybox printf "${C_OUT}${*}${C_CLEAR}\n"
|
|
}
|
|
perr() {
|
|
$busybox printf "${C_ERR}${*}${C_CLEAR}\n"
|
|
}
|
|
pcaut() {
|
|
$busybox printf "${C_CAUT}${*}${C_CLEAR}\n"
|
|
}
|
|
clean()
|
|
{
|
|
$busybox rm -rf /tmp/mkboot.*
|
|
#pout "..."
|
|
exit
|
|
}
|
|
|
|
# Check for busybox
|
|
if [ -z $busybox ]; then
|
|
clear; pcaut "Busybox is NOT installed!\nThis may cause issues with the script!\nUse at your own peril or install busybox!"; sleep 2
|
|
fi
|
|
|
|
usage() {
|
|
pcaut "\n<Unpack and Repack Image Tool>"
|
|
perr "Not enough parameters or parameter error!\n"
|
|
pout "Unpack Image & Decompress Ramdisk <Usage>: \n $($busybox basename $0) [image] [output dir]"
|
|
pout " $($busybox basename $0) boot.img project_folder\n"
|
|
pout "Repack Image & Compress Ramdisk <Usage>: \n $($busybox basename $0) [unpacked dir] [new image]"
|
|
pout " $($busybox basename $0) project_folder newboot.img\n"
|
|
clean
|
|
}
|
|
|
|
print_info() {
|
|
[[ $boot_magic_addr -gt 0 ]] && pout " boot magic : ANDROID!"
|
|
[[ $boot_magic_addr -gt 0 ]] && pout " magic address : $boot_magic ($boot_magic_addr)"
|
|
[ ! -z "$board" ] && pout " board : $board"
|
|
pout " kernel : $kernel"
|
|
pout " ramdisk : $ramdisk"
|
|
pout " page size : $page_size"
|
|
pout " kernel size : $kernel_size"
|
|
pout " ramdisk size : $ramdisk_size"
|
|
[ ! -z $second_size ] && [ $second_size -gt 0 ] && \
|
|
pout " second size : $second_size"
|
|
[ $dtb_size -gt 0 ] && pout " dtb size : $dtb_size"
|
|
if [ ! -z $base_warning ]; then
|
|
pcaut " base : $base_addr (Non Standard)"
|
|
else
|
|
pout " base : $base_addr"
|
|
fi
|
|
if [ ! -z $kernel_offset_warning ]; then
|
|
pcaut " kernel offset : $kernel_offset (Non Standard)"
|
|
else
|
|
pout " kernel offset : $kernel_offset"
|
|
fi
|
|
if [ ! -z $ramdisk_offset_warning ]; then
|
|
pcaut " ramdisk offset : $ramdisk_offset (Non Standard)"
|
|
else
|
|
pout " ramdisk offset : $ramdisk_offset"
|
|
fi
|
|
if [ ! -z $second_offset_warning ]; then
|
|
[ -z $second_offset ] || pcaut " second offset : $second_offset (Non Standard)"
|
|
else
|
|
[ -z $second_offset ] || pout " second offset : $second_offset"
|
|
fi
|
|
if [ ! -z $tags_offset_warning ]; then
|
|
pcaut " tags offset : $tags_offset (Non Standard)"
|
|
else
|
|
pout " tags offset : $tags_offset"
|
|
fi
|
|
[ $dtb_size -gt 0 ] && pout " dtb offset : $qcdt_offset"
|
|
[ $dtb_size -gt 0 ] && pout " dtb img : $dt"
|
|
[ $second_size -gt 0 ] && pout " second img : $second"
|
|
pout " cmd line : $cmd_line"
|
|
}
|
|
|
|
mkboot_img() {
|
|
error=0
|
|
[ $second_size -gt 0 ] && second="--second ${second}"
|
|
[ $dtb_size -gt 0 ] && dtb="--dt ${dt}"
|
|
[ ! -z $second_offset ] && second_offset="--second_offset ${second_offset}"
|
|
[ ! -z "$board" ] && board="--board $board"
|
|
|
|
$mkbootimg --kernel $kernel --ramdisk $ramdisk $board \
|
|
--base $base_addr --ramdisk_offset $ramdisk_offset \
|
|
--kernel_offset $kernel_offset $second_offset \
|
|
--tags_offset $tags_offset --cmdline "$cmd_line" \
|
|
--pagesize $page_size $second $dtb -o $new_img 2>/dev/null || error=1
|
|
|
|
[ $error -eq 1 ] && return $error
|
|
ramdisk_size=$($busybox stat -c "%s" $ramdisk)
|
|
boot_size=$($busybox stat -c "%s" $new_img)
|
|
pout "\nKernel size: $kernel_size, new ramdisk size: $ramdisk_size, $($busybox basename $new_img): $boot_size."
|
|
pout "\n$($busybox basename $new_img) has been created.\n"
|
|
|
|
# Check if new build is larger than original
|
|
# Give caution if it is to insure size is not larger than the partition
|
|
# A courtesy warning
|
|
if [[ "$image_size" -lt "$boot_size" ]]; then
|
|
beefed_up=$(( $boot_size - $image_size ))
|
|
pcaut "\n****** CAUTION ******* CAUTION ******* CAUTION ******"
|
|
pout "\n$($busybox basename $new_img) is $beefed_up bytes larger than"
|
|
pout "the original build! Make sure this new"
|
|
pout "size is not larger than the actual partition!"
|
|
pcaut "\n****** CAUTION ******* CAUTION ******* CAUTION ******\n"
|
|
fi
|
|
}
|
|
|
|
#decide action
|
|
[ $# -lt 2 ] || [ $# -gt 3 ] && usage
|
|
if [ $# -eq 2 ] && [ -d $1 ]; then
|
|
mkboot_from_dir=1
|
|
elif [ $# -eq 2 ] && [ -s $1 ]; then
|
|
split_boot_to_dir=1
|
|
else
|
|
usage
|
|
fi
|
|
|
|
#mkboot_from_dir, img_info
|
|
if [ ! -z $mkboot_from_dir ]; then
|
|
pout "\nmkbootimg from $1/img_info.\n"
|
|
unpacked_dir=$1
|
|
new_img=$2
|
|
cd $unpacked_dir
|
|
if [ ! -s img_info ]; then
|
|
perr "Missing img_info file! Can't rebuild $2."
|
|
clean
|
|
fi
|
|
eval $(cat img_info)
|
|
|
|
if [ -z $kernel ] || [ -z $ramdisk ] || [ -z $base_addr ]; then
|
|
perr "Lacking parameters in img_info."
|
|
clean
|
|
fi
|
|
[ -z $second_size ] && second_size=0
|
|
[ -z $dtb_size ] && dtb_size=0
|
|
|
|
# Temporary solution for lzop compression
|
|
# Check for lzop magic (\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a) before anything else
|
|
# TODO: Fix file and magic to properly read lzop
|
|
if [ -d $ramdisk ]; then
|
|
if $grep $'\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a' ./ramdisk.* > /dev/null; then
|
|
compression_type=lzop
|
|
else
|
|
compression_type=$($file -m $magic ./ramdisk.* | $busybox cut -d: -f2 | $busybox cut -d" " -f2)
|
|
fi
|
|
compression_ext=$compression_type
|
|
case $compression_type in
|
|
gzip) compression_warning=$compression_type; compression_repack=$gzip;;
|
|
xz) compression_warning=$compression_type; compression_repack="$xz -1 --check=crc32";;
|
|
lzma) compression_warning=$compression_type; compression_repack="$xz --format=lzma";;
|
|
lz4) compression_warning=$compression_type; compression_repack="$lz4 -l";;
|
|
lzop) compression_warning=$compression_type; compression_repack="$busybox lzop";;
|
|
esac;
|
|
if [ -z $compression_warning ]; then
|
|
perr "\n****** HAZARD ******* HAZARD ******* HAZARD ******"
|
|
pout "\nRamdisk is $compression_type format. Can't repack ramdisk."
|
|
pout "This tool currently does not support $compression_type."
|
|
perr "\n****** HAZARD ******* HAZARD ******* HAZARD ******\n"
|
|
exit
|
|
fi
|
|
if [ $compression_type != "gzip" ] && [ $compression_type != "lzma" ] && [ $compression_type != "lz4" ] && [ $compression_type != "lzop" ] && [ $compression_type != "xz" ]; then
|
|
perr "\nRamdisk is unknown format. Can't repack ramdisk."
|
|
exit 0
|
|
else
|
|
# XZ GZIP LZMA LZ4 LZOP
|
|
$mkbootfs $ramdisk | $compression_repack > new_ramdisk.$compression_ext
|
|
ramdisk=new_ramdisk.$compression_ext
|
|
ramdisk_size=$($busybox stat -c "%s" $ramdisk)
|
|
fi
|
|
fi
|
|
#cd $unpacked_dir
|
|
print_info
|
|
$busybox rm -f $new_img
|
|
mkboot_img $new_img || perr "Make $new_img Error! pls check img_info file."
|
|
#pout "Add SEANDROIDENFORCE tag."
|
|
#printf SEANDROIDENFORCE >> $new_img
|
|
$busybox rm -f new_ramdisk.gz
|
|
clean
|
|
fi
|
|
|
|
#split boot.img to dir.
|
|
if [ -e $2 ]; then
|
|
read -p "$2 exists, delete?(N/y)" reply
|
|
case $reply in
|
|
y | Y)
|
|
$busybox rm -rf $2
|
|
;;
|
|
*)
|
|
exit
|
|
;;
|
|
esac
|
|
fi
|
|
tempdir=$2
|
|
$busybox mkdir -p "$tempdir"
|
|
pout "\nUnpack & decompress $1 to $2\n"
|
|
|
|
#get boot.img info
|
|
cp -f $1 $tempdir/
|
|
cd $tempdir
|
|
bootimg=$($busybox basename $1)
|
|
# Find BOOT_MAGIC address in dec and hex
|
|
boot_magic_addr=$($grep -abo ANDROID! $bootimg | $busybox cut -f 1 -d : | head -1)
|
|
boot_magic=`printf 0x%08x $boot_magic_addr`
|
|
# Find standard QCDT address in hex
|
|
qcdt_addr=$($grep -abo QCDT $bootimg | $busybox cut -f 1 -d : | head -1)
|
|
if [ ! -z $qcdt_addr ]; then
|
|
qcdt_addr=`printf 0x%x $qcdt_addr`
|
|
fi
|
|
[ -z $boot_magic_addr ] && clean
|
|
if [ $boot_magic_addr -gt 0 ]; then
|
|
$busybox dd if=$bootimg of=bootimg bs=$boot_magic_addr skip=1 2>/dev/null
|
|
bootimg=bootimg
|
|
fi
|
|
|
|
kernel_addr=0x$($od -A n -X -j 12 -N 4 $bootimg | $busybox sed 's/ //g' | $busybox sed 's/^0*//g')
|
|
ramdisk_addr=0x$($od -A n -X -j 20 -N 4 $bootimg | $busybox sed 's/ //g' | $busybox sed 's/^0*//g')
|
|
second_addr=0x$($od -A n -X -j 28 -N 4 $bootimg | $busybox sed 's/ //g' | $busybox sed 's/^0*//g')
|
|
tags_addr=0x$($od -A n -X -j 32 -N 4 $bootimg | $busybox sed 's/ //g' | $busybox sed 's/^0*//g')
|
|
|
|
kernel_size=$($od -A n -D -j 8 -N 4 $bootimg | $busybox sed 's/ //g')
|
|
#base_addr=0x$($od -A n -x -j 14 -N 2 $bootimg | $busybox sed 's/ //g')0000
|
|
ramdisk_size=$($od -A n -D -j 16 -N 4 $bootimg | $busybox sed 's/ //g')
|
|
second_size=$($od -A n -D -j 24 -N 4 $bootimg | $busybox sed 's/ //g')
|
|
page_size=$($od -A n -D -j 36 -N 4 $bootimg | $busybox sed 's/ //g')
|
|
dtb_size=$($od -A n -D -j 40 -N 4 $bootimg | $busybox sed 's/ //g')
|
|
#cmd_line=$($od -A n --strings -j 64 -N 512 $bootimg)
|
|
#board=$($od -A n --strings -j 48 -N 16 $bootimg)
|
|
cmd_line=$($od -A n -S1 -j 64 -N 512 $bootimg)
|
|
board=$($od -A n -S1 -j 48 -N 16 $bootimg)
|
|
|
|
base_addr=$((kernel_addr-0x00008000))
|
|
kernel_offset=$((kernel_addr-base_addr))
|
|
ramdisk_offset=$((ramdisk_addr-base_addr))
|
|
second_offset=$((second_addr-base_addr))
|
|
tags_offset=$((tags_addr-base_addr))
|
|
qcdt_offset=$((qcdt_addr-base_addr))
|
|
|
|
base_addr=$(printf "%08x" $base_addr)
|
|
kernel_offset=$(printf "%08x" $kernel_offset)
|
|
ramdisk_offset=$(printf "%08x" $ramdisk_offset)
|
|
second_offset=$(printf "%08x" $second_offset)
|
|
tags_offset=$(printf "%08x" $tags_offset)
|
|
qcdt_offset=$(printf "%08x" $qcdt_offset)
|
|
|
|
base_addr=0x${base_addr:0-8}
|
|
kernel_offset=0x${kernel_offset:0-8}
|
|
ramdisk_offset=0x${ramdisk_offset:0-8}
|
|
second_offset=0x${second_offset:0-8}
|
|
tags_offset=0x${tags_offset:0-8}
|
|
qcdt_offset=0x${qcdt_offset:0-8}
|
|
|
|
#########################################################
|
|
# BELOW SECTION HANDLES NON STANDARD IMAGES
|
|
|
|
if [ $base_addr != 0x10000000 ]; then
|
|
base_warning=$base_addr
|
|
fi
|
|
|
|
if [ $kernel_offset != 0x00008000 ]; then
|
|
kernel_offset_warning=$kernel_offset
|
|
fi
|
|
|
|
if [ $ramdisk_offset != 0x01000000 ]; then
|
|
ramdisk_offset_warning=$ramdisk_offset
|
|
fi
|
|
|
|
if [ $second_offset != 0x00f00000 ]; then
|
|
second_offset_warning=$second_offset
|
|
fi
|
|
|
|
if [ $tags_offset != 0x00000100 ]; then
|
|
tags_offset_warning=$tags_offset
|
|
fi
|
|
|
|
# Below are the known offsets for non standard mkbootimg.c
|
|
if [[ ! -z $base_warning ]] || [[ ! -z $kernel_offset_warning ]] || [[ ! -z $ramdisk_offset_warning ]] || [[ ! -z $second_offset_warning ]] || [[ ! -z $tags_offset_warning ]]; then
|
|
perr "****** WARNING ******* WARNING ******* WARNING ******\n"
|
|
pout "This image is built using NON-standard mkbootimg!\n"
|
|
fi
|
|
if [ ! -z $base_warning ]; then
|
|
pout "BASE is $base_warning"
|
|
fi
|
|
if [ ! -z $kernel_offset_warning ]; then
|
|
pout "KERNEL_OFFSET is $kernel_offset_warning"
|
|
fi
|
|
if [ ! -z $ramdisk_offset_warning ]; then
|
|
pout "RAMDISK_OFFSET is $ramdisk_offset_warning"
|
|
fi
|
|
if [ ! -z $second_offset_warning ]; then
|
|
pout "SECOND_OFFSET is $second_offset_warning"
|
|
fi
|
|
if [ ! -z $tags_offset_warning ]; then
|
|
pout "TAGS_OFFSET is $tags_offset_warning"
|
|
fi
|
|
if [[ ! -z $base_warning ]] || [[ ! -z $kernel_offset_warning ]] || [[ ! -z $ramdisk_offset_warning ]] || [[ ! -z $second_offset_warning ]] || [[ ! -z $tags_offset_warning ]]; then
|
|
pout "\nYou can modify mkbootimg.c with the above value(s)"
|
|
perr "\n****** WARNING ******* WARNING ******* WARNING ******\n"
|
|
fi
|
|
|
|
# ABOVE SECTION HANDLES NON STANDARD IMAGES
|
|
#########################################################
|
|
|
|
k_count=$(((kernel_size+page_size-1)/page_size))
|
|
r_count=$(((ramdisk_size+page_size-1)/page_size))
|
|
s_count=$(((second_size+page_size-1)/page_size))
|
|
d_count=$(((dtb_size+page_size-1)/page_size))
|
|
k_offset=1
|
|
r_offset=$((k_offset+k_count))
|
|
s_offset=$((r_offset+r_count))
|
|
d_offset=$((s_offset+s_count))
|
|
|
|
#zImage
|
|
$busybox dd if=$bootimg of=zImage_tmp bs=$page_size skip=$k_offset count=$k_count 2>/dev/null
|
|
$busybox dd if=zImage_tmp of=zImage bs=$kernel_size count=1 2>/dev/null
|
|
|
|
#ramdisk.gz
|
|
$busybox dd if=$bootimg of=ramdisk_tmp bs=$page_size skip=$r_offset count=$r_count 2>/dev/null
|
|
$busybox dd if=ramdisk_tmp of=ramdisk.gz bs=$ramdisk_size count=1 2>/dev/null
|
|
|
|
#second image
|
|
if [ $second_size -gt 0 ]; then
|
|
$busybox dd if=$bootimg of=second.img_tmp bs=$page_size skip=$s_offset count=$s_count 2>/dev/null
|
|
$busybox dd if=second.img_tmp of=second.img bs=$second_size count=1 2>/dev/null
|
|
second="$tempdir/second.img"
|
|
second=$($busybox basename $second)
|
|
secondb_name="second=$second"
|
|
secondb_size="second_size=$second_size"
|
|
fi
|
|
|
|
#dtb
|
|
if [ $dtb_size -gt 0 ]; then
|
|
$busybox dd if=$bootimg of=dt.img_tmp bs=$page_size skip=$d_offset count=$d_count 2>/dev/null
|
|
$busybox dd if=dt.img_tmp of=dt.img bs=$dtb_size count=1 2>/dev/null
|
|
dt="$tempdir/dt.img"
|
|
dt=$($busybox basename $dt)
|
|
dt_name="dt=$dt"
|
|
dt_size="dtb_size=$dtb_size"
|
|
fi
|
|
$busybox rm -f *_tmp $($busybox basename $1) $bootimg
|
|
|
|
kernel=zImage
|
|
ramdisk=ramdisk
|
|
[ ! -s $kernel ] && clean
|
|
#print boot.img info
|
|
print_info
|
|
|
|
# Properly escape double quotes
|
|
# Keep double quotes intact
|
|
cmd_line=$(echo $cmd_line | sed -e "s/'/'\\\\''/g; 1s/^/'/; \$s/\$/'/")
|
|
|
|
#write info to img_info,decompression ramdisk.gz
|
|
|
|
[ ! -z "$board" ] && liveboard="board=\"$board\""
|
|
|
|
$busybox printf "kernel=zImage\nramdisk=ramdisk\n${secondb_name}\n${dt_name}\npage_size=$page_size\n\
|
|
kernel_size=$kernel_size\nramdisk_size=$ramdisk_size\n${secondb_size}\n${dt_size}\nbase_addr=$base_addr\nkernel_offset=$kernel_offset\n\
|
|
ramdisk_offset=$ramdisk_offset\nsecond_offset=$second_offset\ntags_offset=$tags_offset\nqcdt_offset=$qcdt_offset\ncmd_line=$cmd_line\n$liveboard\n" > img_info
|
|
|
|
# Include original image size in bytes to img_info
|
|
image_size=$($busybox stat -c "%s" '../'$1)
|
|
$busybox printf "image_size=$image_size" >> img_info
|
|
|
|
$busybox mkdir ramdisk
|
|
cd ramdisk
|
|
|
|
# Temporary solution for lzop compression
|
|
# Check for lzop magic (\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a) before anything else
|
|
# TODO: Fix file and magic to properly read lzop
|
|
if $grep $'\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a' ../ramdisk.gz > /dev/null; then
|
|
compression_type=lzop
|
|
else
|
|
compression_type=$($file -m $magic ../ramdisk.gz | $busybox cut -d: -f2 | $busybox cut -d" " -f2)
|
|
fi;
|
|
compression_warning=$compression_type
|
|
|
|
case $compression_type in
|
|
gzip) compression_type=$gzip; compression_ext=gz;;
|
|
xz) compression_type=$xz; compression_ext=xz;;
|
|
lzma) compression_type=$lzma; compression_ext=lzma;;
|
|
lz4) compression_ext=lz4; decomp_ramdisk="$lz4 -d"; extra="< ../ramdisk.cpio";;
|
|
lzop) compression_ext=lzop; decomp_ramdisk="$busybox lzop -d";;
|
|
esac;
|
|
|
|
if [[ $compression_ext != lz4 ]]; then
|
|
decomp_ramdisk="$compression_type -d -c"
|
|
fi
|
|
decomp_ramdisk2="$cpio -i -d -m --no-absolute-filenames"
|
|
|
|
if [ -z $compression_ext ]; then
|
|
perr "\n****** HAZARD ******* HAZARD ******* HAZARD ******"
|
|
pout "\nRamdisk is $compression_warning format. Can't unpack ramdisk."
|
|
pout "This tool currently does not support $compression_warning."
|
|
perr "\n****** HAZARD ******* HAZARD ******* HAZARD ******\n"
|
|
exit
|
|
fi
|
|
|
|
$busybox mv ../ramdisk.gz ../ramdisk.$compression_ext # This is simply to remind the user if they view the folder afterwards
|
|
pout "\nRamdisk is $compression_warning format."
|
|
$decomp_ramdisk "../ramdisk.$compression_ext" | $decomp_ramdisk2 $extra
|
|
|
|
#Unpack Finish to exit.
|
|
pout "Unpack completed.\n"
|
|
exit
|