平台
RK3566 + Android 11
现象
... Image: kernel.img is ready ... Image: resource.img (with rk3566-evb2-lp4x-v10-edp.dtb logo.bmp logo_kernel.bmp) is ready ... Traceback (most recent call last): File "./scripts/mkbootimg", line 317, in <module> main() File "./scripts/mkbootimg", line 291, in main args = parse_cmdline() File "./scripts/mkbootimg", line 270, in parse_cmdline return parser.parse_args() File "/usr/lib/python2.7/argparse.py", line 1705, in parse_args args, argv = self.parse_known_args(args, namespace) File "/usr/lib/python2.7/argparse.py", line 1737, in parse_known_args namespace, args = self._parse_known_args(args, namespace) File "/usr/lib/python2.7/argparse.py", line 1943, in _parse_known_args start_index = consume_optional(start_index) File "/usr/lib/python2.7/argparse.py", line 1883, in consume_optional take_action(action, args, option_string) File "/usr/lib/python2.7/argparse.py", line 1795, in take_action argument_values = self._get_values(action, argument_strings) File "/usr/lib/python2.7/argparse.py", line 2235, in _get_values value = self._get_value(action, arg_string) File "/usr/lib/python2.7/argparse.py", line 2264, in _get_value result = type_func(arg_string) File "./scripts/mkbootimg", line 223, in parse_os_patch_level assert 0 < m <= 12
从上面的LOG 可以看出kernel.img 与 Resources.img已经编译成功, 问题出在打包部分, 原本以为是python版本问题, 再度确认后发现并无关联.
./scripts/mkbootimg
def parse_cmdline(): parser = ArgumentParser() parser.add_argument('--kernel', help='path to the kernel', type=FileType('rb')) parser.add_argument('--ramdisk', help='path to the ramdisk', type=FileType('rb')) parser.add_argument('--second', help='path to the 2nd bootloader', type=FileType('rb')) parser.add_argument('--dtb', help='path to dtb', type=FileType('rb')) recovery_dtbo_group = parser.add_mutually_exclusive_group() recovery_dtbo_group.add_argument('--recovery_dtbo', help='path to the recovery DTBO', type=FileType('rb')) recovery_dtbo_group.add_argument('--recovery_acpio', help='path to the recovery ACPIO', type=FileType('rb'), metavar='RECOVERY_ACPIO', dest='recovery_dtbo') parser.add_argument('--cmdline', help='extra arguments to be passed on the ' 'kernel command line', default='', action=ValidateStrLenAction, maxlen=1536) parser.add_argument('--vendor_cmdline', help='kernel command line arguments contained in vendor boot', default='', action=ValidateStrLenAction, maxlen=2048) parser.add_argument('--base', help='base address', type=parse_int, default=0x10000000) parser.add_argument('--kernel_offset', help='kernel offset', type=parse_int, default=0x00008000) parser.add_argument('--ramdisk_offset', help='ramdisk offset', type=parse_int, default=0x01000000) parser.add_argument('--second_offset', help='2nd bootloader offset', type=parse_int, default=0x00f00000) parser.add_argument('--dtb_offset', help='dtb offset', type=parse_int, default=0x01f00000) parser.add_argument('--os_version', help='operating system version', type=parse_os_version, default=0) parser.add_argument('--os_patch_level', help='operating system patch level', type=parse_os_patch_level, default=0) parser.add_argument('--tags_offset', help='tags offset', type=parse_int, default=0x00000100) parser.add_argument('--board', help='board name', default='', action=ValidateStrLenAction, maxlen=16) parser.add_argument('--pagesize', help='page size', type=parse_int, choices=[2**i for i in range(11, 15)], default=2048) parser.add_argument('--id', help='print the image ID on standard output', action='store_true') parser.add_argument('--header_version', help='boot image header version', type=parse_int, default=0) parser.add_argument('-o', '--output', help='output file name', type=FileType('wb')) parser.add_argument('--vendor_boot', help='vendor boot output file name', type=FileType('wb')) parser.add_argument('--vendor_ramdisk', help='path to the vendor ramdisk', type=FileType('rb')) return parser.parse_args()
问题出在 parse_cmdline() 这一行上.
尝试打印出传递进来的参数:
import sys def main(): print (sys.argv[1:]) args = parse_cmdline()
['--kernel', './arch/arm64/boot/Image', '--second', 'resource.img', '--ramdisk', 'out/ramdisk', '--cmdline', '', '--header_version', '0', '--os_version', '0.0.0', '--os_patch_level', '2000-00', '--output', 'boot.img']
然而, 正常情况下编译的参数是:
['--kernel', './arch/arm64/boot/Image', '--second', 'resource.img', '-o', 'boot.img']
调用流程: mkimg -> mkbootimg
./scripts/mkimg
if [ -f "${BOOT_IMG}" ]; then if file -p -b ${BOOT_IMG} | grep -q 'Device Tree Blob' ; then repack_itb; elif [ -x ${srctree}/scripts/repack-bootimg ]; then repack_boot_img; fi elif [ -x ${srctree}/scripts/mkbootimg ]; then make_boot_img; fi
mkimg的调用
kernel/arch/arm64/Makefile: $(Q)$(srctree)/scripts/mkimg --dtb $*.dtb kernel/arch/arm/Makefile: $(Q)$(srctree)/scripts/mkimg --dtb $*.dtb
参数不同的原因在于BOOT_IMG 是否存在:
BOOT_IMG=rockdev/Image-rk3566_r/boot.img
当BOOT_IMG存在时, 会执行 repack-bootimg
./scripts/repack-bootimg
out=${out-"out"} log="$out/unpack.log" cmdline=$(grep -a "^command line args: " $log | tr '\0' '\n'| sed "s/^command line args: //") $srctree/scripts/mkbootimg \ --kernel $kernel \ $SECOND \ --ramdisk $ramdisk \ $DTB \ $RECOVERY_DTBO \ --cmdline "${cmdline}${extra_cmdline}" \ --header_version $version \ --os_version $os_version \ --os_patch_level $os_patch_level \ --output $output
cmdline的参数来自于unpack.log:
kernel$ ll out/ total 30588 drwxrwxr-x 2 anson anson 4096 1月 27 00:02 ./ drwxrwxr-x 30 anson anson 4096 1月 27 00:02 ../ -rw-rw-r-- 1 anson anson 31141896 1月 27 00:02 kernel -rw-rw-r-- 1 anson anson 0 1月 27 00:02 ramdisk -rw-rw-r-- 1 anson anson 162304 1月 27 00:02 second -rw-rw-r-- 1 anson anson 381 1月 27 00:02 unpack.log
cat out/unpack.log boot_magic: ANDROID! kernel_size: 31141896 kernel load address: 0x10008000 ramdisk size: 0 ramdisk load address: 0x0 second bootloader size: 162304 second bootloader load address: 0x10f00000 kernel tags load address: 0x10000100 page size: 2048 os version: 0.0.0 os patch level: 2000-00 boot image header version: 0 product name: command line args: additional command line args:
虽然最终定位到这个位置, 但具体原因却无从得知.
解决方案
这个问题出现在, 第一次编译完成并完成 ./mkimage.sh之后, 解决的方案就是手动删除BOOT_IMG
rm -rf rockdev/Image-rk3566_r/boot.img
这样, 再重新编译kernel便可顺利打包, 只是在执行mkimage.sh后, 需重复发上命令.