From 69350f534b87878dd04c5536bdda4041adb369f6 Mon Sep 17 00:00:00 2001 From: sbwml Date: Sun, 17 Dec 2023 23:48:45 +0800 Subject: [PATCH] rockchip: remove boot image Signed-off-by: sbwml --- files/logo.bmp | Bin 706376 -> 0 bytes files/logo_kernel.bmp | Bin 706376 -> 0 bytes files/scripts/bmpconvert | 313 ---- files/scripts/mkbootimg | 316 ---- files/scripts/mkimg | 263 --- files/scripts/mkkrnlimg.c | 159 -- files/scripts/repack-bootimg | 153 -- files/scripts/resource_tool.c | 1591 ------------------ patches-6.1/990-arm64-build-boot-image.patch | 25 - 9 files changed, 2820 deletions(-) delete mode 100644 files/logo.bmp delete mode 100644 files/logo_kernel.bmp delete mode 100755 files/scripts/bmpconvert delete mode 100755 files/scripts/mkbootimg delete mode 100755 files/scripts/mkimg delete mode 100644 files/scripts/mkkrnlimg.c delete mode 100755 files/scripts/repack-bootimg delete mode 100644 files/scripts/resource_tool.c delete mode 100644 patches-6.1/990-arm64-build-boot-image.patch diff --git a/files/logo.bmp b/files/logo.bmp deleted file mode 100644 index 7f6b70b087f66e90e9a641bc29e757247f3f26c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 706376 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 z5CVh%AwUQa0)zk|KnM^5ga9Ex2oM5<03kpK5CVh%AwUQa0)zk|KnM^5ga9Ex2oM5< z03kpK5CVh%AwUQa0)zk|KnM^5ga9Ex2oM5<03kpK5CVh%AwUQa0)zk|KnM^5ga9Ex z2oM5<03kpK5CVh%AwUQa0)zk|KnM^5ga9Ex2oM5<03kpK5CVh%AwUQa0)zk|KnM^5 zga9Ex2oM5<03kpK5CVh%AwUQa0)zk|KnM^5ga9Ex2oM5<03kpK5CVh%AwUQa0)zk| zKnM^5ga9Ex2oM5<03kpK5CVh%AwUQa0)zk|KnM^5ga9Ex2oM5<03kpK5CVh%AwUQa z0)zk|KnM^5ga9Ex2oM5<03kpK5CVh%AwUQa0)zk|KnM^5ga9Ex2oM5<03kpK5CVh% zAwUQa0)zk|KnM^5ga9Ex2oM5<03kpK5CVh%AwUQa0)zk|KnM^5ga9Ex2oM5<03kpK z5CVh%AwUQa0)zk|KnM^5ga9Ex2oM5<03kpK5CVh%AwUQa0)zk|KnM^5ga9Ex2oM5< z03kpK5CVh%AwUQa0)zk|KnM^5ga9Ex2oM5<03kpK5CVh%AwUQa0)zk|KnM^5ga9Ex z2oM5<03kpK5CVh%AwUQa0)zk|KnM^5ga9Ex2oM5<03kpK5CVh%AwUQa0)zk|KnM^5 zga9Ex2oM5<03kpK5CVh%AwUQa0)zk|KnM^5ga9Ex2oM5<03kpK5CVh%AwUQa0)zk| zKnM^5ga9Ex2oM5<03kpK5CVh%AwUQa0)zk|KnM^5ga9Ex2oM5<03kpK5CVh%AwUQa z0)zk|KnM^5ga9Ex2oM5<03kpK5CVh%AwUQa0)zk|KnM^5ga9Ex2oM5<03kpK5CVh% zAwUQa0)zk|KnM^5ga9Ex2oM5<03kpK5CVh%AwUQa0)zk|KnM^5ga9Ex2oM5<03kpK z5CVh%AwUQa0)zk|KnM^5ga9Ex2oM5<03kpK5CVh%AwUQa0)zk|KnM^5ga9Ex2oM5< z03kpK5CVh%AwUQa0)zk|KnM^5ga9Ex2oM5<03kpK5CVh%AwUQa0)zk|KnM^5ga9Ex z2oM5<03kpK5CVh%AwUQa0)zk|KnM^5ga9Ex2oM5<03kpK5CVh%AwUQa0)zk|KnM^5 zga9Ex2oM5<03kpK5CVh%AwUQa0)zk|KnM^5ga9Ex2oM5<03kpK5CVh%AwUQa0)zk| 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 40: - self.read_other(self.biSize-40) - - if self.biBitCount == 16 and self.biCompression == 3: - for i in range(4): - self.bf_map.append( - [unpack(" 0: - self.reverse_bmp_data() - print("reverse data at first time") - if self.force_revers: - self.reverse_bmp_data() - print("reverse data by force") - if self.force_swap: - self.rb_swap = 1 - print("swap rb by force'") - - if self.bfReserved1 == 8399: - self.file.close() - return - - self.write_24bit(self.rb_swap) - self.file.close() - - def read_other(self, n): - for i in range(n): - self.file.read(1) - - def reverse_bmp_data(self): - self.bmp_data.reverse() - - @staticmethod - def get_16bit_bgr_bf(pixel): - red = (pixel[1] & 0xf8) << 0 - green = ((pixel[1] & 0x07) << 5) | ((pixel[0] & 0xe0) >> 3) - blue = ((pixel[0] & 0x1f) << 3) - new_pixel = [blue, green, red] - return new_pixel - - def bmp32bit_to_24bit(self): - for height in range(abs(self.biHeight)): - bmp_data_row = [] - # bmp file 4 align - count = 0 - for width in range(self.biWidth): - bmp_data_row.append( - [unpack(" 0: - data2 = unpack(" 2: - data_count = data2 - data_temp = unpack("> 2) - blue = ((pixel[0] & 0x1f) << 3) - new_pixel = [blue, green, red] - return new_pixel - - def bmp16bit_to_24bit(self): - self.get_16bit_data() - temp_data = self.bmp_data - self.bmp_data = [] - for height in range(abs(self.biHeight)): - bmp_data_row = [] - for width in range(self.biWidth): - bmp_data_row.append( - self.get_16bit_bgr(temp_data[height][width]) - ) - self.bmp_data.append(bmp_data_row) - - def get_head(self): - self.file.seek(0, 0) - for i in range(54): - self.head.append(unpack(" 3: - raise ValueError('Boot header version %d not supported' % args.header_version) - elif args.header_version == 3: - return write_header_v3(args) - - args.output.write(pack('8s', BOOT_MAGIC)) - final_ramdisk_offset = (args.base + args.ramdisk_offset) if filesize(args.ramdisk) > 0 else 0 - final_second_offset = (args.base + args.second_offset) if filesize(args.second) > 0 else 0 - args.output.write(pack( - '10I', - filesize(args.kernel), # size in bytes - args.base + args.kernel_offset, # physical load addr - filesize(args.ramdisk), # size in bytes - final_ramdisk_offset, # physical load addr - filesize(args.second), # size in bytes - final_second_offset, # physical load addr - args.base + args.tags_offset, # physical addr for kernel tags - args.pagesize, # flash page size we assume - args.header_version, # version of bootimage header - (args.os_version << 11) | args.os_patch_level)) # os version and patch level - args.output.write(pack('16s', args.board.encode())) # asciiz product name - args.output.write(pack('512s', args.cmdline[:512].encode())) - - sha = sha1() - update_sha(sha, args.kernel) - update_sha(sha, args.ramdisk) - update_sha(sha, args.second) - - if args.header_version > 0: - update_sha(sha, args.recovery_dtbo) - if args.header_version > 1: - update_sha(sha, args.dtb) - - img_id = pack('32s', sha.digest()) - - args.output.write(img_id) - args.output.write(pack('1024s', args.cmdline[512:].encode())) - - if args.header_version > 0: - args.output.write(pack('I', filesize(args.recovery_dtbo))) # size in bytes - if args.recovery_dtbo: - args.output.write(pack('Q', get_recovery_dtbo_offset(args))) # recovery dtbo offset - else: - args.output.write(pack('Q', 0)) # Will be set to 0 for devices without a recovery dtbo - - # Populate boot image header size for header versions 1 and 2. - if args.header_version == 1: - args.output.write(pack('I', BOOT_IMAGE_HEADER_V1_SIZE)) - elif args.header_version == 2: - args.output.write(pack('I', BOOT_IMAGE_HEADER_V2_SIZE)) - - if args.header_version > 1: - - # if filesize(args.dtb) == 0: - # raise ValueError("DTB image must not be empty.") - - args.output.write(pack('I', filesize(args.dtb))) # size in bytes - args.output.write(pack('Q', args.base + args.dtb_offset)) # dtb physical load address - pad_file(args.output, args.pagesize) - return img_id - - -class ValidateStrLenAction(Action): - def __init__(self, option_strings, dest, nargs=None, **kwargs): - if 'maxlen' not in kwargs: - raise ValueError('maxlen must be set') - self.maxlen = int(kwargs['maxlen']) - del kwargs['maxlen'] - super(ValidateStrLenAction, self).__init__(option_strings, dest, **kwargs) - - def __call__(self, parser, namespace, values, option_string=None): - if len(values) > self.maxlen: - raise ValueError( - 'String argument too long: max {0:d}, got {1:d}'.format(self.maxlen, len(values))) - setattr(namespace, self.dest, values) - - -def write_padded_file(f_out, f_in, padding): - if f_in is None: - return - f_out.write(f_in.read()) - pad_file(f_out, padding) - - -def parse_int(x): - return int(x, 0) - - -def parse_os_version(x): - match = re.search(r'^(\d{1,3})(?:\.(\d{1,3})(?:\.(\d{1,3}))?)?', x) - if match: - a = int(match.group(1)) - b = c = 0 - if match.lastindex >= 2: - b = int(match.group(2)) - if match.lastindex == 3: - c = int(match.group(3)) - # 7 bits allocated for each field - assert a < 128 - assert b < 128 - assert c < 128 - return (a << 14) | (b << 7) | c - return 0 - - -def parse_os_patch_level(x): - match = re.search(r'^(\d{4})-(\d{2})(?:-(\d{2}))?', x) - if match: - y = int(match.group(1)) - 2000 - m = int(match.group(2)) - # 7 bits allocated for the year, 4 bits for the month - assert 0 <= y < 128 - assert 0 < m <= 12 - return (y << 4) | m - return 0 - - -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() - - -def write_data(args, pagesize): - write_padded_file(args.output, args.kernel, pagesize) - write_padded_file(args.output, args.ramdisk, pagesize) - write_padded_file(args.output, args.second, pagesize) - - if args.header_version > 0 and args.header_version < 3: - write_padded_file(args.output, args.recovery_dtbo, pagesize) - if args.header_version == 2: - write_padded_file(args.output, args.dtb, pagesize) - - -def write_vendor_boot_data(args): - write_padded_file(args.vendor_boot, args.vendor_ramdisk, args.pagesize) - write_padded_file(args.vendor_boot, args.dtb, args.pagesize) - - -def main(): - args = parse_cmdline() - if args.vendor_boot is not None: - if args.header_version < 3: - raise ValueError('--vendor_boot not compatible with given header version') - if args.vendor_ramdisk is None: - raise ValueError('--vendor_ramdisk missing or invalid') - write_vendor_boot_header(args) - write_vendor_boot_data(args) - if args.output is not None: - if args.kernel is None: - raise ValueError('kernel must be supplied when creating a boot image') - if args.second is not None and args.header_version > 2: - raise ValueError('--second not compatible with given header version') - img_id = write_header(args) - if args.header_version > 2: - write_data(args, BOOT_IMAGE_HEADER_V3_PAGESIZE) - else: - write_data(args, args.pagesize) - if args.id and img_id is not None: - # Python 2's struct.pack returns a string, but py3 returns bytes. - if isinstance(img_id, str): - img_id = [ord(x) for x in img_id] - print('0x' + ''.join('{:02x}'.format(c) for c in img_id)) - - -if __name__ == '__main__': - main() diff --git a/files/scripts/mkimg b/files/scripts/mkimg deleted file mode 100755 index 8ceee9f..0000000 --- a/files/scripts/mkimg +++ /dev/null @@ -1,263 +0,0 @@ -#!/bin/bash -# SPDX-License-Identifier: GPL-2.0 -# Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd. - -set -e - -usage() { - cat >&2 << USAGE -usage: $0 [-h] --dtb DTB - -optional arguments: - -h, --help show this help message and exit - --dtb DTB the dtb file name -USAGE -} - -# Parse command-line arguments -while [ $# -gt 0 ]; do - case $1 in - --dtb) - DTB=$2 - shift 2 - ;; - --keep-dtb-name) - DTB_ARGS="--dtbname"; shift 1;; - -h) - usage - exit 0 - ;; - --help) - usage - exit 0 - ;; - *) - shift - ;; - esac -done - -srctree=${srctree-"."} -objtree=${objtree-"."} -if [ "${ARCH}" == "" ]; then - if [ "$($srctree/scripts/config --state CONFIG_ARM)" == "y" ]; then - ARCH=arm - else - ARCH=arm64 - fi -fi - -LOGO_PATH=${srctree}/logo.bmp -[ -f ${LOGO_PATH} ] && LOGO=logo.bmp - -LOGO_KERNEL_PATH=${srctree}/logo_kernel.bmp -[ -f ${LOGO_KERNEL_PATH} ] && LOGO_KERNEL=logo_kernel.bmp - -KERNEL_IMAGE_PATH=${objtree}/arch/${ARCH}/boot/Image -KERNEL_IMAGE_ARG="--kernel ${KERNEL_IMAGE_PATH}" -if [ "${ARCH}" == "arm" ]; then - DTB_PATH=${objtree}/arch/arm/boot/dts/${DTB} - ZIMAGE=zImage -else - DTB_PATH=${objtree}/arch/arm64/boot/dts/rockchip/${DTB} - ZIMAGE=Image.lz4 -fi -KERNEL_ZIMAGE_PATH=${objtree}/arch/${ARCH}/boot/${ZIMAGE} -KERNEL_ZIMAGE_ARG="--kernel ${KERNEL_ZIMAGE_PATH}" -if ! find ${DTB_PATH} >/dev/null; then - echo "No dtb" >&2 - usage - exit 1 -fi - -OUT=out -ITB=${BOOT_IMG} -ITS=${OUT}/boot.its -MKIMAGE=${MKIMAGE-"mkimage"} -MKIMAGE_ARG="-E -p 0x800" - -make_boot_img() -{ - RAMDISK_IMG_PATH=${objtree}/ramdisk.img - [ -f ${RAMDISK_IMG_PATH} ] && RAMDISK_IMG=ramdisk.img && RAMDISK_ARG="--ramdisk ${RAMDISK_IMG_PATH}" - - ${srctree}/scripts/mkbootimg \ - ${KERNEL_IMAGE_ARG} \ - ${RAMDISK_ARG} \ - --second resource.img \ - -o boot.img && \ - echo " Image: boot.img (with Image ${RAMDISK_IMG} resource.img) is ready"; - [ -f ${KERNEL_ZIMAGE_PATH} ] || return 0 - ${srctree}/scripts/mkbootimg \ - ${KERNEL_ZIMAGE_ARG} \ - ${RAMDISK_ARG} \ - --second resource.img \ - -o zboot.img && \ - echo " Image: zboot.img (with ${ZIMAGE} ${RAMDISK_IMG} resource.img) is ready" -} - -repack_boot_img() -{ - ${srctree}/scripts/repack-bootimg \ - --boot_img ${BOOT_IMG} --out ${OUT} \ - ${KERNEL_IMAGE_ARG} \ - --second resource.img \ - --dtb ${DTB_PATH} \ - -o boot.img && - echo " Image: boot.img (${BOOT_IMG} + Image) is ready"; - ${srctree}/scripts/repack-bootimg \ - --boot_img ${BOOT_IMG} --out ${OUT} \ - ${KERNEL_ZIMAGE_ARG} \ - --second resource.img \ - --dtb ${DTB_PATH} \ - -o zboot.img && \ - echo " Image: zboot.img (${BOOT_IMG} + ${ZIMAGE}) is ready" -} - -check_mkimage() -{ - MKIMAGE=$(type -p ${MKIMAGE} || true) - if [ -z "${MKIMAGE}" ]; then - # Doesn't exist - echo '"mkimage" command not found - U-Boot images will not be built' >&2 - exit 1; - fi -} - -unpack_itb() -{ - rm -rf ${OUT} - mkdir -p ${OUT} - - for NAME in $(fdtget -l ${ITB} /images) - do - # generate image - NODE="/images/${NAME}" - OFFS=$(fdtget -ti ${ITB} ${NODE} data-position) - SIZE=$(fdtget -ti ${ITB} ${NODE} data-size) - if [ -z ${OFFS} ]; then - continue; - fi - - if [ ${SIZE} -ne 0 ]; then - dd if=${ITB} of=${OUT}/${NAME} bs=${SIZE} count=1 skip=${OFFS} iflag=skip_bytes >/dev/null 2>&1 - else - touch ${OUT}/${NAME} - fi - done - - [ ! -f ${OUT}/kernel ] && echo "FIT ${ITB} no kernel" >&2 && exit 1 || true -} - -gen_its() -{ - TMP_ITB=${OUT}/boot.tmp - - # add placeholder - cp ${ITB} ${TMP_ITB} - for NAME in $(fdtget -l ${ITB} /images); do - fdtput -t s ${TMP_ITB} /images/${NAME} data "/INCBIN/(${NAME})" - done - dtc -I dtb -O dts ${TMP_ITB} -o ${ITS} >/dev/null 2>&1 - rm -f ${TMP_ITB} - - # fixup placeholder: data = "/INCBIN/(...)"; -> data = /incbin/("..."); - sed -i "s/\"\/INCBIN\/(\(.*\))\"/\/incbin\/(\"\1\")/" ${ITS} - - # remove - sed -i "/memreserve/d" ${ITS} - sed -i "/timestamp/d" ${ITS} - sed -i "/data-size/d" ${ITS} - sed -i "/data-position/d" ${ITS} - sed -i "/value/d" ${ITS} - sed -i "/hashed-strings/d" ${ITS} - sed -i "/hashed-nodes/d" ${ITS} - sed -i "/signer-version/d" ${ITS} - sed -i "/signer-name/d" ${ITS} -} - -gen_itb() -{ - [ -f ${OUT}/fdt ] && cp -a ${DTB_PATH} ${OUT}/fdt && FDT=" + ${DTB}" - [ -f ${OUT}/resource ] && cp -a resource.img ${OUT}/resource && RESOURCE=" + resource.img" - COMP=$(fdtget ${ITB} /images/kernel compression) - case "${COMP}" in - gzip) EXT=".gz";; - lz4) EXT=".lz4";; - bzip2) EXT=".bz2";; - lzma) EXT=".lzma";; - lzo) EXT=".lzo";; - esac - cp -a ${KERNEL_IMAGE_PATH}${EXT} ${OUT}/kernel && \ - ${MKIMAGE} ${MKIMAGE_ARG} -f ${ITS} boot.img >/dev/null && \ - echo " Image: boot.img (FIT ${BOOT_IMG} + Image${EXT}${FDT}${RESOURCE}) is ready"; - if [ "${EXT}" == "" ] && [ -f ${KERNEL_ZIMAGE_PATH} ]; then - cp -a ${KERNEL_ZIMAGE_PATH} ${OUT}/kernel && \ - ${MKIMAGE} ${MKIMAGE_ARG} -f ${ITS} zboot.img >/dev/null && \ - echo " Image: zboot.img (FIT ${BOOT_IMG} + zImage${FDT}${RESOURCE}) is ready"; - fi -} - -repack_itb() -{ - check_mkimage - unpack_itb - gen_its - gen_itb -} - -# Create U-Boot FIT Image use ${BOOT_ITS} -make_fit_boot_img() -{ - ITS=${OUT}/boot.its - - check_mkimage - mkdir -p ${OUT} - rm -f ${OUT}/fdt ${OUT}/kernel ${OUT}/resource ${ITS} - - cp -a ${BOOT_ITS} ${ITS} - cp -a ${DTB_PATH} ${OUT}/fdt - cp -a ${KERNEL_ZIMAGE_PATH} ${OUT}/kernel - cp -a resource.img ${OUT}/resource - - if [ "${ARCH}" == "arm64" ]; then - sed -i -e 's/arch = ""/arch = "arm64"/g' -e 's/compression = ""/compression = "lz4"/' ${ITS} - else - sed -i -e 's/arch = ""/arch = "arm"/g' -e 's/compression = ""/compression = "none"/' ${ITS} - fi - FIT_DESC=$(${MKIMAGE} ${MKIMAGE_ARG} -f ${ITS} boot.img | grep "FIT description" | sed 's/FIT description: //') - echo " Image: boot.img (${FIT_DESC}) is ready"; -} - -if [ -x ${srctree}/scripts/bmpconvert ]; then - if [ -f ${LOGO_PATH} ]; then - ${srctree}/scripts/bmpconvert ${LOGO_PATH}; - fi - if [ -f ${LOGO_KERNEL_PATH} ]; then - ${srctree}/scripts/bmpconvert ${LOGO_KERNEL_PATH}; - fi -fi - -if [ "${srctree}" != "${objtree}" ]; then - if [ -f ${LOGO_PATH} ]; then - cp -a ${LOGO_PATH} ${objtree}/; - fi - if [ -f ${LOGO_KERNEL_PATH} ]; then - cp -a ${LOGO_KERNEL_PATH} ${objtree}/; - fi -fi - -scripts/resource_tool ${DTB_ARGS} ${DTB_PATH} ${LOGO} ${LOGO_KERNEL} >/dev/null -echo " Image: resource.img (with ${DTB} ${LOGO} ${LOGO_KERNEL}) is ready" - -if [ -f "${BOOT_IMG}" ]; then - if file -L -p -b ${BOOT_IMG} | grep -q 'Device Tree Blob' ; then - repack_itb; - elif [ -x ${srctree}/scripts/repack-bootimg ]; then - repack_boot_img; - fi -elif [ -f "${BOOT_ITS}" ]; then - make_fit_boot_img; -elif [ -x ${srctree}/scripts/mkbootimg ]; then - make_boot_img; -fi diff --git a/files/scripts/mkkrnlimg.c b/files/scripts/mkkrnlimg.c deleted file mode 100644 index a39d1a1..0000000 --- a/files/scripts/mkkrnlimg.c +++ /dev/null @@ -1,159 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * (C) Copyright Fuzhou Rockchip Electronics Co., Ltd - */ - -#include -#include -#include - -//#define DEBUG -#ifdef DEBUG -#define PRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__) -#else -static inline __attribute__ ((format(printf, 1, 2))) -int PRINTF(const char *fmt, ...) -{ - return 0; -} -#endif - -static uint32_t gTable_Crc32[256] = { - 0x00000000, 0x04c10db7, 0x09821b6e, 0x0d4316d9, - 0x130436dc, 0x17c53b6b, 0x1a862db2, 0x1e472005, - 0x26086db8, 0x22c9600f, 0x2f8a76d6, 0x2b4b7b61, - 0x350c5b64, 0x31cd56d3, 0x3c8e400a, 0x384f4dbd, - 0x4c10db70, 0x48d1d6c7, 0x4592c01e, 0x4153cda9, - 0x5f14edac, 0x5bd5e01b, 0x5696f6c2, 0x5257fb75, - 0x6a18b6c8, 0x6ed9bb7f, 0x639aada6, 0x675ba011, - 0x791c8014, 0x7ddd8da3, 0x709e9b7a, 0x745f96cd, - 0x9821b6e0, 0x9ce0bb57, 0x91a3ad8e, 0x9562a039, - 0x8b25803c, 0x8fe48d8b, 0x82a79b52, 0x866696e5, - 0xbe29db58, 0xbae8d6ef, 0xb7abc036, 0xb36acd81, - 0xad2ded84, 0xa9ece033, 0xa4aff6ea, 0xa06efb5d, - 0xd4316d90, 0xd0f06027, 0xddb376fe, 0xd9727b49, - 0xc7355b4c, 0xc3f456fb, 0xceb74022, 0xca764d95, - 0xf2390028, 0xf6f80d9f, 0xfbbb1b46, 0xff7a16f1, - 0xe13d36f4, 0xe5fc3b43, 0xe8bf2d9a, 0xec7e202d, - 0x34826077, 0x30436dc0, 0x3d007b19, 0x39c176ae, - 0x278656ab, 0x23475b1c, 0x2e044dc5, 0x2ac54072, - 0x128a0dcf, 0x164b0078, 0x1b0816a1, 0x1fc91b16, - 0x018e3b13, 0x054f36a4, 0x080c207d, 0x0ccd2dca, - 0x7892bb07, 0x7c53b6b0, 0x7110a069, 0x75d1adde, - 0x6b968ddb, 0x6f57806c, 0x621496b5, 0x66d59b02, - 0x5e9ad6bf, 0x5a5bdb08, 0x5718cdd1, 0x53d9c066, - 0x4d9ee063, 0x495fedd4, 0x441cfb0d, 0x40ddf6ba, - 0xaca3d697, 0xa862db20, 0xa521cdf9, 0xa1e0c04e, - 0xbfa7e04b, 0xbb66edfc, 0xb625fb25, 0xb2e4f692, - 0x8aabbb2f, 0x8e6ab698, 0x8329a041, 0x87e8adf6, - 0x99af8df3, 0x9d6e8044, 0x902d969d, 0x94ec9b2a, - 0xe0b30de7, 0xe4720050, 0xe9311689, 0xedf01b3e, - 0xf3b73b3b, 0xf776368c, 0xfa352055, 0xfef42de2, - 0xc6bb605f, 0xc27a6de8, 0xcf397b31, 0xcbf87686, - 0xd5bf5683, 0xd17e5b34, 0xdc3d4ded, 0xd8fc405a, - 0x6904c0ee, 0x6dc5cd59, 0x6086db80, 0x6447d637, - 0x7a00f632, 0x7ec1fb85, 0x7382ed5c, 0x7743e0eb, - 0x4f0cad56, 0x4bcda0e1, 0x468eb638, 0x424fbb8f, - 0x5c089b8a, 0x58c9963d, 0x558a80e4, 0x514b8d53, - 0x25141b9e, 0x21d51629, 0x2c9600f0, 0x28570d47, - 0x36102d42, 0x32d120f5, 0x3f92362c, 0x3b533b9b, - 0x031c7626, 0x07dd7b91, 0x0a9e6d48, 0x0e5f60ff, - 0x101840fa, 0x14d94d4d, 0x199a5b94, 0x1d5b5623, - 0xf125760e, 0xf5e47bb9, 0xf8a76d60, 0xfc6660d7, - 0xe22140d2, 0xe6e04d65, 0xeba35bbc, 0xef62560b, - 0xd72d1bb6, 0xd3ec1601, 0xdeaf00d8, 0xda6e0d6f, - 0xc4292d6a, 0xc0e820dd, 0xcdab3604, 0xc96a3bb3, - 0xbd35ad7e, 0xb9f4a0c9, 0xb4b7b610, 0xb076bba7, - 0xae319ba2, 0xaaf09615, 0xa7b380cc, 0xa3728d7b, - 0x9b3dc0c6, 0x9ffccd71, 0x92bfdba8, 0x967ed61f, - 0x8839f61a, 0x8cf8fbad, 0x81bbed74, 0x857ae0c3, - 0x5d86a099, 0x5947ad2e, 0x5404bbf7, 0x50c5b640, - 0x4e829645, 0x4a439bf2, 0x47008d2b, 0x43c1809c, - 0x7b8ecd21, 0x7f4fc096, 0x720cd64f, 0x76cddbf8, - 0x688afbfd, 0x6c4bf64a, 0x6108e093, 0x65c9ed24, - 0x11967be9, 0x1557765e, 0x18146087, 0x1cd56d30, - 0x02924d35, 0x06534082, 0x0b10565b, 0x0fd15bec, - 0x379e1651, 0x335f1be6, 0x3e1c0d3f, 0x3add0088, - 0x249a208d, 0x205b2d3a, 0x2d183be3, 0x29d93654, - 0xc5a71679, 0xc1661bce, 0xcc250d17, 0xc8e400a0, - 0xd6a320a5, 0xd2622d12, 0xdf213bcb, 0xdbe0367c, - 0xe3af7bc1, 0xe76e7676, 0xea2d60af, 0xeeec6d18, - 0xf0ab4d1d, 0xf46a40aa, 0xf9295673, 0xfde85bc4, - 0x89b7cd09, 0x8d76c0be, 0x8035d667, 0x84f4dbd0, - 0x9ab3fbd5, 0x9e72f662, 0x9331e0bb, 0x97f0ed0c, - 0xafbfa0b1, 0xab7ead06, 0xa63dbbdf, 0xa2fcb668, - 0xbcbb966d, 0xb87a9bda, 0xb5398d03, 0xb1f880b4, -}; - -static uint32_t CRC_32(uint8_t *aData, long aSize) -{ - long i; - uint32_t nAccum = 0; - - for (i = 0; i < aSize; i++) - nAccum = - (nAccum << 8) ^ gTable_Crc32[(nAccum >> 24) ^ *aData++]; - return nAccum; -} - -#define TAG_KERNEL 0x4C4E524B - -int main(int argc, char *argv[]) -{ - FILE *fid_in, *fid_out; - size_t cnt; - uint8_t *ptr1; - long fileSize; - int exit_code = 0; - uint32_t crcData; - - PRINTF("mkkrnlimg V20111117\n"); - PRINTF("cmd:%s %s [%s]\n", argv[1], argv[2], argv[3]); - if (argc < 3) { - printf("Usage: %s srcFile desFile [flag]\n", argv[0]); - printf("sample:\n"); - printf(" %s Image kernel.img\n", argv[0]); - exit(1); - } - - fid_in = fopen(argv[1], "rb"); - if (fid_in == 0) { - printf("input open NG !\n "); - exit(2); - } - - fid_out = fopen(argv[2], "wb"); - if (fid_out == 0) { - printf("output open NG !\n "); - fclose(fid_in); - exit(3); - } - fseek(fid_in, 0, SEEK_END); - fileSize = ftell(fid_in); - PRINTF("fileSize = %ld\n", fileSize); - fseek(fid_in, 0, SEEK_SET); - ptr1 = malloc(fileSize + 512 + 20); - if (ptr1 == 0) { - exit_code = 4; - printf("\n malloc error!"); - goto app_exit; - } - - *(uint32_t *)ptr1 = TAG_KERNEL; - *(uint32_t *)(ptr1 + 4) = fileSize; - fwrite(ptr1, 1, 8, fid_out); - cnt = fread(ptr1, 1, fileSize, fid_in); - PRINTF("fread = %lu\n", cnt); - crcData = CRC_32(ptr1, fileSize); - PRINTF("crc = 0x%x\n", crcData); - cnt = fwrite(ptr1, 1, fileSize, fid_out); - PRINTF("fwrite = %lu\n", cnt); - fwrite(&crcData, 1, 4, fid_out); - -app_exit: - fclose(fid_in); - fclose(fid_out); - if (ptr1) - free(ptr1); - exit(exit_code); -} diff --git a/files/scripts/repack-bootimg b/files/scripts/repack-bootimg deleted file mode 100755 index 69065d2..0000000 --- a/files/scripts/repack-bootimg +++ /dev/null @@ -1,153 +0,0 @@ -#!/bin/bash -# SPDX-License-Identifier: GPL-2.0 -# Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd. -set -e - -usage() { - cat >&2 << USAGE -usage: $0 [-h] [-z] --boot_img BOOT_IMG [--out OUT] [--kernel KERNEL] [--ramdisk RAMDISK] [--second SECOND] [--dtb DTB ] [--recovery_dtbo RECOVERY_DTBO] -o OUTPUT - -optional arguments: - -h, --help show this help message and exit - -z pack compressed kernel image - --boot_img BOOT_IMG path to the original boot image - --out OUT path to out binaries (default: out) - --kernel KERNEL path to the new kernel - --ramdisk RAMDISK path to the new ramdisk - --second SECOND path to the new 2nd bootloader (default: resource.img) - --dtb DTB path to the new dtb - --recovery_dtbo RECOVERY_DTBO - path to the new recovery DTBO - -o OUTPUT, --output OUTPUT - output file name -USAGE -} - -# Parse command-line arguments -while [ $# -gt 0 ]; do - case $1 in - --boot_img) - boot_img=$2 - shift 2 - ;; - --out) - out=$2 - shift 2 - ;; - --kernel) - kernel=$2 - shift 2 - ;; - --ramdisk) - ramdisk=$2 - shift 2 - ;; - --second) - second=$2 - shift 2 - ;; - --dtb) - dtb=$2 - shift 2 - ;; - --recovery_dtbo) - recovery_dtbo=$2 - shift 2 - ;; - -h) - usage - exit 0 - ;; - --help) - usage - exit 0 - ;; - -z) - compressed_kernel=y - shift - ;; - -o) - output=$2 - shift 2 - ;; - --output) - output=$2 - shift 2 - ;; - *) - shift - ;; - esac -done - -if [ "$boot_img" == "" -o ! -e "$boot_img" ]; then - echo "No boot img" - usage - exit 1 -fi - -if [ "$output" == "" ]; then - echo "No output file name" - usage - exit 1 -fi - -srctree=${srctree-"."} -objtree=${objtree-"."} -out=${out-"out"} -if [ "$($srctree/scripts/config --state CONFIG_ARM64)" == "y" ]; then - if [ "$compressed_kernel" == "y" ]; then - default_kernel=arch/arm64/boot/Image.lz4 - else - default_kernel=arch/arm64/boot/Image - fi -else - if [ "$compressed_kernel" == "y" ]; then - default_kernel=arch/arm/boot/zImage - else - default_kernel=arch/arm/boot/Image - fi -fi -kernel=${kernel-$objtree/$default_kernel} -second=${second-$objtree/resource.img} -ramdisk=${ramdisk-$out/ramdisk} -dtb=${dtb-$out/dtb} -recovery_dtbo=${recovery_dtbo-$out/recovery_dtbo} -log="$out/unpack.log" - -mkdir -p $out -$srctree/scripts/unpack_bootimg --boot_img $boot_img --out $out > $log - -cmdline=$(grep -a "^command line args: " $log | tr '\0' '\n'| sed "s/^command line args: //") -extra_cmdline=$(grep -a "^additional command line args: " $log | tr '\0' '\n'| sed "s/^additional command line args: //") -version=$(grep -a "^boot image header version: " $log | sed "s/^boot image header version: //") -os_version=$(grep -a "^os version: " $log | sed "s/^os version: //") -os_patch_level=$(grep -a "^os patch level: " $log | sed "s/^os patch level: //") - -dtb_size=$(grep -a "^dtb size: " $log | sed "s/^dtb size: //") -dtb_size=${dtb_size:-0} -if [ $dtb_size -gt 0 -a -e "$dtb" ]; then - DTB="--dtb $dtb" -fi - -recovery_dtbo_size=$(grep -a "^recovery dtbo size: " $log | sed "s/^recovery dtbo size: //") -recovery_dtbo_size=${recovery_dtbo_size:-0} -if [ $recovery_dtbo_size -gt 0 -a -e "$recovery_dtbo" ]; then - RECOVERY_DTBO="--recovery_dtbo $recovery_dtbo" -fi - -if [ $version -lt 3 ]; then - SECOND="--second $second" -fi - -$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 diff --git a/files/scripts/resource_tool.c b/files/scripts/resource_tool.c deleted file mode 100644 index a59aebb..0000000 --- a/files/scripts/resource_tool.c +++ /dev/null @@ -1,1591 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * (C) Copyright 2008-2015 Fuzhou Rockchip Electronics Co., Ltd - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * \brief SHA-1 context structure - */ -typedef struct -{ - unsigned long total[2]; /*!< number of bytes processed */ - unsigned long state[5]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ -} -sha1_context; - -/* - * 32-bit integer manipulation macros (big endian) - */ -#ifndef GET_UINT32_BE -#define GET_UINT32_BE(n,b,i) { \ - (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ - | ( (unsigned long) (b)[(i) + 1] << 16 ) \ - | ( (unsigned long) (b)[(i) + 2] << 8 ) \ - | ( (unsigned long) (b)[(i) + 3] ); \ -} -#endif -#ifndef PUT_UINT32_BE -#define PUT_UINT32_BE(n,b,i) { \ - (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) ); \ -} -#endif - -/* - * SHA-1 context setup - */ -static -void sha1_starts (sha1_context * ctx) -{ - ctx->total[0] = 0; - ctx->total[1] = 0; - - ctx->state[0] = 0x67452301; - ctx->state[1] = 0xEFCDAB89; - ctx->state[2] = 0x98BADCFE; - ctx->state[3] = 0x10325476; - ctx->state[4] = 0xC3D2E1F0; -} - -static void sha1_process(sha1_context *ctx, const unsigned char data[64]) -{ - unsigned long temp, W[16], A, B, C, D, E; - - GET_UINT32_BE (W[0], data, 0); - GET_UINT32_BE (W[1], data, 4); - GET_UINT32_BE (W[2], data, 8); - GET_UINT32_BE (W[3], data, 12); - GET_UINT32_BE (W[4], data, 16); - GET_UINT32_BE (W[5], data, 20); - GET_UINT32_BE (W[6], data, 24); - GET_UINT32_BE (W[7], data, 28); - GET_UINT32_BE (W[8], data, 32); - GET_UINT32_BE (W[9], data, 36); - GET_UINT32_BE (W[10], data, 40); - GET_UINT32_BE (W[11], data, 44); - GET_UINT32_BE (W[12], data, 48); - GET_UINT32_BE (W[13], data, 52); - GET_UINT32_BE (W[14], data, 56); - GET_UINT32_BE (W[15], data, 60); - -#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) - -#define R(t) ( \ - temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \ - W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \ - ( W[t & 0x0F] = S(temp,1) ) \ -) - -#define P(a,b,c,d,e,x) { \ - e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ -} - - A = ctx->state[0]; - B = ctx->state[1]; - C = ctx->state[2]; - D = ctx->state[3]; - E = ctx->state[4]; - -#define F(x,y,z) (z ^ (x & (y ^ z))) -#define K 0x5A827999 - - P (A, B, C, D, E, W[0]); - P (E, A, B, C, D, W[1]); - P (D, E, A, B, C, W[2]); - P (C, D, E, A, B, W[3]); - P (B, C, D, E, A, W[4]); - P (A, B, C, D, E, W[5]); - P (E, A, B, C, D, W[6]); - P (D, E, A, B, C, W[7]); - P (C, D, E, A, B, W[8]); - P (B, C, D, E, A, W[9]); - P (A, B, C, D, E, W[10]); - P (E, A, B, C, D, W[11]); - P (D, E, A, B, C, W[12]); - P (C, D, E, A, B, W[13]); - P (B, C, D, E, A, W[14]); - P (A, B, C, D, E, W[15]); - P (E, A, B, C, D, R (16)); - P (D, E, A, B, C, R (17)); - P (C, D, E, A, B, R (18)); - P (B, C, D, E, A, R (19)); - -#undef K -#undef F - -#define F(x,y,z) (x ^ y ^ z) -#define K 0x6ED9EBA1 - - P (A, B, C, D, E, R (20)); - P (E, A, B, C, D, R (21)); - P (D, E, A, B, C, R (22)); - P (C, D, E, A, B, R (23)); - P (B, C, D, E, A, R (24)); - P (A, B, C, D, E, R (25)); - P (E, A, B, C, D, R (26)); - P (D, E, A, B, C, R (27)); - P (C, D, E, A, B, R (28)); - P (B, C, D, E, A, R (29)); - P (A, B, C, D, E, R (30)); - P (E, A, B, C, D, R (31)); - P (D, E, A, B, C, R (32)); - P (C, D, E, A, B, R (33)); - P (B, C, D, E, A, R (34)); - P (A, B, C, D, E, R (35)); - P (E, A, B, C, D, R (36)); - P (D, E, A, B, C, R (37)); - P (C, D, E, A, B, R (38)); - P (B, C, D, E, A, R (39)); - -#undef K -#undef F - -#define F(x,y,z) ((x & y) | (z & (x | y))) -#define K 0x8F1BBCDC - - P (A, B, C, D, E, R (40)); - P (E, A, B, C, D, R (41)); - P (D, E, A, B, C, R (42)); - P (C, D, E, A, B, R (43)); - P (B, C, D, E, A, R (44)); - P (A, B, C, D, E, R (45)); - P (E, A, B, C, D, R (46)); - P (D, E, A, B, C, R (47)); - P (C, D, E, A, B, R (48)); - P (B, C, D, E, A, R (49)); - P (A, B, C, D, E, R (50)); - P (E, A, B, C, D, R (51)); - P (D, E, A, B, C, R (52)); - P (C, D, E, A, B, R (53)); - P (B, C, D, E, A, R (54)); - P (A, B, C, D, E, R (55)); - P (E, A, B, C, D, R (56)); - P (D, E, A, B, C, R (57)); - P (C, D, E, A, B, R (58)); - P (B, C, D, E, A, R (59)); - -#undef K -#undef F - -#define F(x,y,z) (x ^ y ^ z) -#define K 0xCA62C1D6 - - P (A, B, C, D, E, R (60)); - P (E, A, B, C, D, R (61)); - P (D, E, A, B, C, R (62)); - P (C, D, E, A, B, R (63)); - P (B, C, D, E, A, R (64)); - P (A, B, C, D, E, R (65)); - P (E, A, B, C, D, R (66)); - P (D, E, A, B, C, R (67)); - P (C, D, E, A, B, R (68)); - P (B, C, D, E, A, R (69)); - P (A, B, C, D, E, R (70)); - P (E, A, B, C, D, R (71)); - P (D, E, A, B, C, R (72)); - P (C, D, E, A, B, R (73)); - P (B, C, D, E, A, R (74)); - P (A, B, C, D, E, R (75)); - P (E, A, B, C, D, R (76)); - P (D, E, A, B, C, R (77)); - P (C, D, E, A, B, R (78)); - P (B, C, D, E, A, R (79)); - -#undef K -#undef F - - ctx->state[0] += A; - ctx->state[1] += B; - ctx->state[2] += C; - ctx->state[3] += D; - ctx->state[4] += E; -} - -#undef P -#undef R -#undef S - -/* - * SHA-1 process buffer - */ -static -void sha1_update(sha1_context *ctx, const unsigned char *input, - unsigned int ilen) -{ - int fill; - unsigned long left; - - if (ilen <= 0) - return; - - left = ctx->total[0] & 0x3F; - fill = 64 - left; - - ctx->total[0] += ilen; - ctx->total[0] &= 0xFFFFFFFF; - - if (ctx->total[0] < (unsigned long) ilen) - ctx->total[1]++; - - if (left && ilen >= fill) { - memcpy ((void *) (ctx->buffer + left), (void *) input, fill); - sha1_process (ctx, ctx->buffer); - input += fill; - ilen -= fill; - left = 0; - } - - while (ilen >= 64) { - sha1_process (ctx, input); - input += 64; - ilen -= 64; - } - - if (ilen > 0) { - memcpy ((void *) (ctx->buffer + left), (void *) input, ilen); - } -} - -static const unsigned char sha1_padding[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * SHA-1 final digest - */ -static -void sha1_finish (sha1_context * ctx, unsigned char output[20]) -{ - unsigned long last, padn; - unsigned long high, low; - unsigned char msglen[8]; - - high = (ctx->total[0] >> 29) - | (ctx->total[1] << 3); - low = (ctx->total[0] << 3); - - PUT_UINT32_BE (high, msglen, 0); - PUT_UINT32_BE (low, msglen, 4); - - last = ctx->total[0] & 0x3F; - padn = (last < 56) ? (56 - last) : (120 - last); - - sha1_update (ctx, (unsigned char *) sha1_padding, padn); - sha1_update (ctx, msglen, 8); - - PUT_UINT32_BE (ctx->state[0], output, 0); - PUT_UINT32_BE (ctx->state[1], output, 4); - PUT_UINT32_BE (ctx->state[2], output, 8); - PUT_UINT32_BE (ctx->state[3], output, 12); - PUT_UINT32_BE (ctx->state[4], output, 16); -} - -/* - * Output = SHA-1( input buffer ) - */ -static -void sha1_csum(const unsigned char *input, unsigned int ilen, - unsigned char *output) -{ - sha1_context ctx; - - sha1_starts (&ctx); - sha1_update (&ctx, input, ilen); - sha1_finish (&ctx, output); -} - -typedef struct { - uint32_t total[2]; - uint32_t state[8]; - uint8_t buffer[64]; -} sha256_context; - -static -void sha256_starts(sha256_context * ctx) -{ - ctx->total[0] = 0; - ctx->total[1] = 0; - - ctx->state[0] = 0x6A09E667; - ctx->state[1] = 0xBB67AE85; - ctx->state[2] = 0x3C6EF372; - ctx->state[3] = 0xA54FF53A; - ctx->state[4] = 0x510E527F; - ctx->state[5] = 0x9B05688C; - ctx->state[6] = 0x1F83D9AB; - ctx->state[7] = 0x5BE0CD19; -} - -static void sha256_process(sha256_context *ctx, const uint8_t data[64]) -{ - uint32_t temp1, temp2; - uint32_t W[64]; - uint32_t A, B, C, D, E, F, G, H; - - GET_UINT32_BE(W[0], data, 0); - GET_UINT32_BE(W[1], data, 4); - GET_UINT32_BE(W[2], data, 8); - GET_UINT32_BE(W[3], data, 12); - GET_UINT32_BE(W[4], data, 16); - GET_UINT32_BE(W[5], data, 20); - GET_UINT32_BE(W[6], data, 24); - GET_UINT32_BE(W[7], data, 28); - GET_UINT32_BE(W[8], data, 32); - GET_UINT32_BE(W[9], data, 36); - GET_UINT32_BE(W[10], data, 40); - GET_UINT32_BE(W[11], data, 44); - GET_UINT32_BE(W[12], data, 48); - GET_UINT32_BE(W[13], data, 52); - GET_UINT32_BE(W[14], data, 56); - GET_UINT32_BE(W[15], data, 60); - -#define SHR(x,n) ((x & 0xFFFFFFFF) >> n) -#define ROTR(x,n) (SHR(x,n) | (x << (32 - n))) - -#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3)) -#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10)) - -#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22)) -#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25)) - -#define F0(x,y,z) ((x & y) | (z & (x | y))) -#define F1(x,y,z) (z ^ (x & (y ^ z))) - -#define R(t) \ -( \ - W[t] = S1(W[t - 2]) + W[t - 7] + \ - S0(W[t - 15]) + W[t - 16] \ -) - -#define P(a,b,c,d,e,f,g,h,x,K) { \ - temp1 = h + S3(e) + F1(e,f,g) + K + x; \ - temp2 = S2(a) + F0(a,b,c); \ - d += temp1; h = temp1 + temp2; \ -} - - A = ctx->state[0]; - B = ctx->state[1]; - C = ctx->state[2]; - D = ctx->state[3]; - E = ctx->state[4]; - F = ctx->state[5]; - G = ctx->state[6]; - H = ctx->state[7]; - - P(A, B, C, D, E, F, G, H, W[0], 0x428A2F98); - P(H, A, B, C, D, E, F, G, W[1], 0x71374491); - P(G, H, A, B, C, D, E, F, W[2], 0xB5C0FBCF); - P(F, G, H, A, B, C, D, E, W[3], 0xE9B5DBA5); - P(E, F, G, H, A, B, C, D, W[4], 0x3956C25B); - P(D, E, F, G, H, A, B, C, W[5], 0x59F111F1); - P(C, D, E, F, G, H, A, B, W[6], 0x923F82A4); - P(B, C, D, E, F, G, H, A, W[7], 0xAB1C5ED5); - P(A, B, C, D, E, F, G, H, W[8], 0xD807AA98); - P(H, A, B, C, D, E, F, G, W[9], 0x12835B01); - P(G, H, A, B, C, D, E, F, W[10], 0x243185BE); - P(F, G, H, A, B, C, D, E, W[11], 0x550C7DC3); - P(E, F, G, H, A, B, C, D, W[12], 0x72BE5D74); - P(D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE); - P(C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7); - P(B, C, D, E, F, G, H, A, W[15], 0xC19BF174); - P(A, B, C, D, E, F, G, H, R(16), 0xE49B69C1); - P(H, A, B, C, D, E, F, G, R(17), 0xEFBE4786); - P(G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6); - P(F, G, H, A, B, C, D, E, R(19), 0x240CA1CC); - P(E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F); - P(D, E, F, G, H, A, B, C, R(21), 0x4A7484AA); - P(C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC); - P(B, C, D, E, F, G, H, A, R(23), 0x76F988DA); - P(A, B, C, D, E, F, G, H, R(24), 0x983E5152); - P(H, A, B, C, D, E, F, G, R(25), 0xA831C66D); - P(G, H, A, B, C, D, E, F, R(26), 0xB00327C8); - P(F, G, H, A, B, C, D, E, R(27), 0xBF597FC7); - P(E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3); - P(D, E, F, G, H, A, B, C, R(29), 0xD5A79147); - P(C, D, E, F, G, H, A, B, R(30), 0x06CA6351); - P(B, C, D, E, F, G, H, A, R(31), 0x14292967); - P(A, B, C, D, E, F, G, H, R(32), 0x27B70A85); - P(H, A, B, C, D, E, F, G, R(33), 0x2E1B2138); - P(G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC); - P(F, G, H, A, B, C, D, E, R(35), 0x53380D13); - P(E, F, G, H, A, B, C, D, R(36), 0x650A7354); - P(D, E, F, G, H, A, B, C, R(37), 0x766A0ABB); - P(C, D, E, F, G, H, A, B, R(38), 0x81C2C92E); - P(B, C, D, E, F, G, H, A, R(39), 0x92722C85); - P(A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1); - P(H, A, B, C, D, E, F, G, R(41), 0xA81A664B); - P(G, H, A, B, C, D, E, F, R(42), 0xC24B8B70); - P(F, G, H, A, B, C, D, E, R(43), 0xC76C51A3); - P(E, F, G, H, A, B, C, D, R(44), 0xD192E819); - P(D, E, F, G, H, A, B, C, R(45), 0xD6990624); - P(C, D, E, F, G, H, A, B, R(46), 0xF40E3585); - P(B, C, D, E, F, G, H, A, R(47), 0x106AA070); - P(A, B, C, D, E, F, G, H, R(48), 0x19A4C116); - P(H, A, B, C, D, E, F, G, R(49), 0x1E376C08); - P(G, H, A, B, C, D, E, F, R(50), 0x2748774C); - P(F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5); - P(E, F, G, H, A, B, C, D, R(52), 0x391C0CB3); - P(D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A); - P(C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F); - P(B, C, D, E, F, G, H, A, R(55), 0x682E6FF3); - P(A, B, C, D, E, F, G, H, R(56), 0x748F82EE); - P(H, A, B, C, D, E, F, G, R(57), 0x78A5636F); - P(G, H, A, B, C, D, E, F, R(58), 0x84C87814); - P(F, G, H, A, B, C, D, E, R(59), 0x8CC70208); - P(E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA); - P(D, E, F, G, H, A, B, C, R(61), 0xA4506CEB); - P(C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7); - P(B, C, D, E, F, G, H, A, R(63), 0xC67178F2); - - ctx->state[0] += A; - ctx->state[1] += B; - ctx->state[2] += C; - ctx->state[3] += D; - ctx->state[4] += E; - ctx->state[5] += F; - ctx->state[6] += G; - ctx->state[7] += H; -} - -#undef P -#undef R -#undef F1 -#undef F0 -#undef S3 -#undef S2 -#undef S1 -#undef S0 -#undef ROTR -#undef SHR - -static -void sha256_update(sha256_context *ctx, const uint8_t *input, uint32_t length) -{ - uint32_t left, fill; - - if (!length) - return; - - left = ctx->total[0] & 0x3F; - fill = 64 - left; - - ctx->total[0] += length; - ctx->total[0] &= 0xFFFFFFFF; - - if (ctx->total[0] < length) - ctx->total[1]++; - - if (left && length >= fill) { - memcpy((void *) (ctx->buffer + left), (void *) input, fill); - sha256_process(ctx, ctx->buffer); - length -= fill; - input += fill; - left = 0; - } - - while (length >= 64) { - sha256_process(ctx, input); - length -= 64; - input += 64; - } - - if (length) - memcpy((void *) (ctx->buffer + left), (void *) input, length); -} - -static uint8_t sha256_padding[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static -void sha256_finish(sha256_context * ctx, uint8_t digest[32]) -{ - uint32_t last, padn; - uint32_t high, low; - uint8_t msglen[8]; - - high = ((ctx->total[0] >> 29) - | (ctx->total[1] << 3)); - low = (ctx->total[0] << 3); - - PUT_UINT32_BE(high, msglen, 0); - PUT_UINT32_BE(low, msglen, 4); - - last = ctx->total[0] & 0x3F; - padn = (last < 56) ? (56 - last) : (120 - last); - - sha256_update(ctx, sha256_padding, padn); - sha256_update(ctx, msglen, 8); - - PUT_UINT32_BE(ctx->state[0], digest, 0); - PUT_UINT32_BE(ctx->state[1], digest, 4); - PUT_UINT32_BE(ctx->state[2], digest, 8); - PUT_UINT32_BE(ctx->state[3], digest, 12); - PUT_UINT32_BE(ctx->state[4], digest, 16); - PUT_UINT32_BE(ctx->state[5], digest, 20); - PUT_UINT32_BE(ctx->state[6], digest, 24); - PUT_UINT32_BE(ctx->state[7], digest, 28); -} - -/* - * Output = SHA-256( input buffer ). - */ -static -void sha256_csum(const unsigned char *input, unsigned int ilen, - unsigned char *output) -{ - sha256_context ctx; - - sha256_starts(&ctx); - sha256_update(&ctx, input, ilen); - sha256_finish(&ctx, output); -} - -/* #define DEBUG */ - -static bool g_debug = -#ifdef DEBUG - true; -#else - false; -#endif /* DEBUG */ - -#define LOGE(fmt, args...) \ - fprintf(stderr, "E/%s(%d): " fmt "\n", __func__, __LINE__, ##args) -#define LOGD(fmt, args...) \ - do { \ - if (g_debug) \ - fprintf(stderr, "D/%s(%d): " fmt "\n", __func__, __LINE__, ##args); \ - } while (0) - -/* sync with ./board/rockchip/rk30xx/rkloader.c #define FDT_PATH */ -#define FDT_PATH "rk-kernel.dtb" -#define DTD_SUBFIX ".dtb" - -#define DEFAULT_IMAGE_PATH "resource.img" -#define DEFAULT_UNPACK_DIR "out" -#define BLOCK_SIZE 512 - -#define RESOURCE_PTN_HDR_SIZE 1 -#define INDEX_TBL_ENTR_SIZE 1 - -#define RESOURCE_PTN_VERSION 0 -#define INDEX_TBL_VERSION 0 - -#define RESOURCE_PTN_HDR_MAGIC "RSCE" -typedef struct { - char magic[4]; /* tag, "RSCE" */ - uint16_t resource_ptn_version; - uint16_t index_tbl_version; - uint8_t header_size; /* blocks, size of ptn header. */ - uint8_t tbl_offset; /* blocks, offset of index table. */ - uint8_t tbl_entry_size; /* blocks, size of index table's entry. */ - uint32_t tbl_entry_num; /* numbers of index table's entry. */ -} resource_ptn_header; - -#define INDEX_TBL_ENTR_TAG "ENTR" -#define MAX_INDEX_ENTRY_PATH_LEN 220 -#define MAX_HASH_LEN 32 - -typedef struct { - char tag[4]; /* tag, "ENTR" */ - char path[MAX_INDEX_ENTRY_PATH_LEN]; - char hash[MAX_HASH_LEN]; /* hash data */ - uint32_t hash_size; /* 20 or 32 */ - uint32_t content_offset; /* blocks, offset of resource content. */ - uint32_t content_size; /* bytes, size of resource content. */ -} index_tbl_entry; - -#define OPT_VERBOSE "--verbose" -#define OPT_HELP "--help" -#define OPT_VERSION "--version" -#define OPT_PRINT "--print" -#define OPT_PACK "--pack" -#define OPT_UNPACK "--unpack" -#define OPT_TEST_LOAD "--test_load" -#define OPT_TEST_CHARGE "--test_charge" -#define OPT_IMAGE "--image=" -#define OPT_ROOT "--root=" -#define OPT_DTBNAME "--dtbname" - -#define VERSION "2020-03-03 18:01:11" - -typedef struct { - char path[MAX_INDEX_ENTRY_PATH_LEN]; - uint32_t content_offset; /* blocks, offset of resource content. */ - uint32_t content_size; /* bytes, size of resource content. */ - void *load_addr; -} resource_content; - -typedef struct { - int max_level; - int num; - int delay; - char prefix[MAX_INDEX_ENTRY_PATH_LEN]; -} anim_level_conf; - -#define DEF_CHARGE_DESC_PATH "charge_anim_desc.txt" - -#define OPT_CHARGE_ANIM_DELAY "delay=" -#define OPT_CHARGE_ANIM_LOOP_CUR "only_current_level=" -#define OPT_CHARGE_ANIM_LEVELS "levels=" -#define OPT_CHARGE_ANIM_LEVEL_CONF "max_level=" -#define OPT_CHARGE_ANIM_LEVEL_NUM "num=" -#define OPT_CHARGE_ANIM_LEVEL_PFX "prefix=" - -static char image_path[MAX_INDEX_ENTRY_PATH_LEN] = "\0"; - -static int fix_blocks(size_t size) -{ - return (size + BLOCK_SIZE - 1) / BLOCK_SIZE; -} - -static const char *fix_path(const char *path) -{ - if (!memcmp(path, "./", 2)) { - return path + 2; - } - return path; -} - -static uint16_t switch_short(uint16_t x) -{ - uint16_t val; - uint8_t *p = (uint8_t *)(&x); - - val = (*p++ & 0xff) << 0; - val |= (*p & 0xff) << 8; - - return val; -} - -static uint32_t switch_int(uint32_t x) -{ - uint32_t val; - uint8_t *p = (uint8_t *)(&x); - - val = (*p++ & 0xff) << 0; - val |= (*p++ & 0xff) << 8; - val |= (*p++ & 0xff) << 16; - val |= (*p & 0xff) << 24; - - return val; -} - -static void fix_header(resource_ptn_header *header) -{ - /* switch for be. */ - header->resource_ptn_version = switch_short(header->resource_ptn_version); - header->index_tbl_version = switch_short(header->index_tbl_version); - header->tbl_entry_num = switch_int(header->tbl_entry_num); -} - -static void fix_entry(index_tbl_entry *entry) -{ - /* switch for be. */ - entry->content_offset = switch_int(entry->content_offset); - entry->content_size = switch_int(entry->content_size); -} - -static int inline get_ptn_offset(void) -{ - return 0; -} - -static bool StorageWriteLba(int offset_block, void *data, int blocks) -{ - bool ret = false; - FILE *file = fopen(image_path, "rb+"); - if (!file) - goto end; - int offset = offset_block * BLOCK_SIZE; - fseek(file, offset, SEEK_SET); - if (offset != ftell(file)) { - LOGE("Failed to seek %s to %d!", image_path, offset); - goto end; - } - if (!fwrite(data, blocks * BLOCK_SIZE, 1, file)) { - LOGE("Failed to write %s!", image_path); - goto end; - } - ret = true; -end: - if (file) - fclose(file); - return ret; -} - -static bool StorageReadLba(int offset_block, void *data, int blocks) -{ - bool ret = false; - FILE *file = fopen(image_path, "rb"); - if (!file) - goto end; - int offset = offset_block * BLOCK_SIZE; - fseek(file, offset, SEEK_SET); - if (offset != ftell(file)) { - goto end; - } - if (!fread(data, blocks * BLOCK_SIZE, 1, file)) { - goto end; - } - ret = true; -end: - if (file) - fclose(file); - return ret; -} - -static bool write_data(int offset_block, void *data, size_t len) -{ - bool ret = false; - if (!data) - goto end; - int blocks = len / BLOCK_SIZE; - if (blocks && !StorageWriteLba(offset_block, data, blocks)) { - goto end; - } - int left = len % BLOCK_SIZE; - if (left) { - char buf[BLOCK_SIZE] = "\0"; - memcpy(buf, data + blocks * BLOCK_SIZE, left); - if (!StorageWriteLba(offset_block + blocks, buf, 1)) - goto end; - } - ret = true; -end: - return ret; -} - -/**********************load test************************/ -static int load_file(const char *file_path, int offset_block, int blocks); - -static int test_load(int argc, char **argv) -{ - if (argc < 1) { - LOGE("Nothing to load!"); - return -1; - } - const char *file_path; - int offset_block = 0; - int blocks = 0; - if (argc > 0) { - file_path = (const char *)fix_path(argv[0]); - argc--, argv++; - } - if (argc > 0) { - offset_block = atoi(argv[0]); - argc--, argv++; - } - if (argc > 0) { - blocks = atoi(argv[0]); - } - return load_file(file_path, offset_block, blocks); -} - -static void free_content(resource_content *content) -{ - if (content->load_addr) { - free(content->load_addr); - content->load_addr = 0; - } -} - -static void tests_dump_file(const char *path, void *data, int len) -{ - FILE *file = fopen(path, "wb"); - if (!file) - return; - fwrite(data, len, 1, file); - fclose(file); -} - -static bool load_content(resource_content *content) -{ - if (content->load_addr) - return true; - int blocks = fix_blocks(content->content_size); - content->load_addr = malloc(blocks * BLOCK_SIZE); - if (!content->load_addr) - return false; - if (!StorageReadLba(get_ptn_offset() + content->content_offset, - content->load_addr, blocks)) { - free_content(content); - return false; - } - - tests_dump_file(content->path, content->load_addr, content->content_size); - return true; -} - -static bool load_content_data(resource_content *content, int offset_block, - void *data, int blocks) -{ - if (!StorageReadLba(get_ptn_offset() + content->content_offset + offset_block, - data, blocks)) { - return false; - } - tests_dump_file(content->path, data, blocks * BLOCK_SIZE); - return true; -} - -static bool get_entry(const char *file_path, index_tbl_entry *entry) -{ - bool ret = false; - char buf[BLOCK_SIZE]; - resource_ptn_header header; - if (!StorageReadLba(get_ptn_offset(), buf, 1)) { - LOGE("Failed to read header!"); - goto end; - } - memcpy(&header, buf, sizeof(header)); - - if (memcmp(header.magic, RESOURCE_PTN_HDR_MAGIC, sizeof(header.magic))) { - LOGE("Not a resource image(%s)!", image_path); - goto end; - } - /* test on pc, switch for be. */ - fix_header(&header); - - /* TODO: support header_size & tbl_entry_size */ - if (header.resource_ptn_version != RESOURCE_PTN_VERSION || - header.header_size != RESOURCE_PTN_HDR_SIZE || - header.index_tbl_version != INDEX_TBL_VERSION || - header.tbl_entry_size != INDEX_TBL_ENTR_SIZE) { - LOGE("Not supported in this version!"); - goto end; - } - - int i; - for (i = 0; i < header.tbl_entry_num; i++) { - /* TODO: support tbl_entry_size */ - if (!StorageReadLba( - get_ptn_offset() + header.header_size + i * header.tbl_entry_size, - buf, 1)) { - LOGE("Failed to read index entry:%d!", i); - goto end; - } - memcpy(entry, buf, sizeof(*entry)); - - if (memcmp(entry->tag, INDEX_TBL_ENTR_TAG, sizeof(entry->tag))) { - LOGE("Something wrong with index entry:%d!", i); - goto end; - } - - if (!strncmp(entry->path, file_path, sizeof(entry->path))) - break; - } - if (i == header.tbl_entry_num) { - LOGE("Cannot find %s!", file_path); - goto end; - } - /* test on pc, switch for be. */ - fix_entry(entry); - - printf("Found entry:\n\tpath:%s\n\toffset:%d\tsize:%d\n", entry->path, - entry->content_offset, entry->content_size); - - ret = true; -end: - return ret; -} - -static bool get_content(resource_content *content) -{ - bool ret = false; - index_tbl_entry entry; - if (!get_entry(content->path, &entry)) - goto end; - content->content_offset = entry.content_offset; - content->content_size = entry.content_size; - ret = true; -end: - return ret; -} - -static int load_file(const char *file_path, int offset_block, int blocks) -{ - printf("Try to load:%s", file_path); - if (blocks) { - printf(", offset block:%d, blocks:%d\n", offset_block, blocks); - } else { - printf("\n"); - } - bool ret = false; - resource_content content; - snprintf(content.path, sizeof(content.path), "%s", file_path); - content.load_addr = 0; - if (!get_content(&content)) { - goto end; - } - if (!blocks) { - if (!load_content(&content)) { - goto end; - } - } else { - void *data = malloc(blocks * BLOCK_SIZE); - if (!data) - goto end; - if (!load_content_data(&content, offset_block, data, blocks)) { - goto end; - } - } - ret = true; -end: - free_content(&content); - return ret; -} - -/**********************load test end************************/ -/**********************anim test************************/ - -static bool parse_level_conf(const char *arg, anim_level_conf *level_conf) -{ - memset(level_conf, 0, sizeof(anim_level_conf)); - char *buf = NULL; - buf = strstr(arg, OPT_CHARGE_ANIM_LEVEL_CONF); - if (buf) { - level_conf->max_level = atoi(buf + strlen(OPT_CHARGE_ANIM_LEVEL_CONF)); - } else { - LOGE("Not found:%s", OPT_CHARGE_ANIM_LEVEL_CONF); - return false; - } - buf = strstr(arg, OPT_CHARGE_ANIM_LEVEL_NUM); - if (buf) { - level_conf->num = atoi(buf + strlen(OPT_CHARGE_ANIM_LEVEL_NUM)); - if (level_conf->num <= 0) { - return false; - } - } else { - LOGE("Not found:%s", OPT_CHARGE_ANIM_LEVEL_NUM); - return false; - } - buf = strstr(arg, OPT_CHARGE_ANIM_DELAY); - if (buf) { - level_conf->delay = atoi(buf + strlen(OPT_CHARGE_ANIM_DELAY)); - } - buf = strstr(arg, OPT_CHARGE_ANIM_LEVEL_PFX); - if (buf) { - snprintf(level_conf->prefix, sizeof(level_conf->prefix), "%s", - buf + strlen(OPT_CHARGE_ANIM_LEVEL_PFX)); - } else { - LOGE("Not found:%s", OPT_CHARGE_ANIM_LEVEL_PFX); - return false; - } - - LOGD("Found conf:\nmax_level:%d, num:%d, delay:%d, prefix:%s", - level_conf->max_level, level_conf->num, level_conf->delay, - level_conf->prefix); - return true; -} - -static int test_charge(int argc, char **argv) -{ - const char *desc; - if (argc > 0) { - desc = argv[0]; - } else { - desc = DEF_CHARGE_DESC_PATH; - } - - resource_content content; - snprintf(content.path, sizeof(content.path), "%s", desc); - content.load_addr = 0; - if (!get_content(&content)) { - goto end; - } - if (!load_content(&content)) { - goto end; - } - - char *buf = (char *)content.load_addr; - char *end = buf + content.content_size - 1; - *end = '\0'; - LOGD("desc:\n%s", buf); - - int pos = 0; - while (1) { - char *line = (char *)memchr(buf + pos, '\n', strlen(buf + pos)); - if (!line) - break; - *line = '\0'; - LOGD("splite:%s", buf + pos); - pos += (strlen(buf + pos) + 1); - } - - int delay = 900; - int only_current_level = false; - anim_level_conf *level_confs = NULL; - int level_conf_pos = 0; - int level_conf_num = 0; - - while (true) { - if (buf >= end) - break; - const char *arg = buf; - buf += (strlen(buf) + 1); - - LOGD("parse arg:%s", arg); - if (!memcmp(arg, OPT_CHARGE_ANIM_LEVEL_CONF, - strlen(OPT_CHARGE_ANIM_LEVEL_CONF))) { - if (!level_confs) { - LOGE("Found level conf before levels!"); - goto end; - } - if (level_conf_pos >= level_conf_num) { - LOGE("Too many level confs!(%d >= %d)", level_conf_pos, level_conf_num); - goto end; - } - if (!parse_level_conf(arg, level_confs + level_conf_pos)) { - LOGE("Failed to parse level conf:%s", arg); - goto end; - } - level_conf_pos++; - } else if (!memcmp(arg, OPT_CHARGE_ANIM_DELAY, - strlen(OPT_CHARGE_ANIM_DELAY))) { - delay = atoi(arg + strlen(OPT_CHARGE_ANIM_DELAY)); - LOGD("Found delay:%d", delay); - } else if (!memcmp(arg, OPT_CHARGE_ANIM_LOOP_CUR, - strlen(OPT_CHARGE_ANIM_LOOP_CUR))) { - only_current_level = - !memcmp(arg + strlen(OPT_CHARGE_ANIM_LOOP_CUR), "true", 4); - LOGD("Found only_current_level:%d", only_current_level); - } else if (!memcmp(arg, OPT_CHARGE_ANIM_LEVELS, - strlen(OPT_CHARGE_ANIM_LEVELS))) { - if (level_conf_num) { - goto end; - } - level_conf_num = atoi(arg + strlen(OPT_CHARGE_ANIM_LEVELS)); - if (!level_conf_num) { - goto end; - } - level_confs = - (anim_level_conf *)malloc(level_conf_num * sizeof(anim_level_conf)); - LOGD("Found levels:%d", level_conf_num); - } else { - LOGE("Unknown arg:%s", arg); - goto end; - } - } - - if (level_conf_pos != level_conf_num || !level_conf_num) { - LOGE("Something wrong with level confs!"); - goto end; - } - - int i = 0, j = 0; - for (i = 0; i < level_conf_num; i++) { - if (!level_confs[i].delay) { - level_confs[i].delay = delay; - } - if (!level_confs[i].delay) { - LOGE("Missing delay in level conf:%d", i); - goto end; - } - for (j = 0; j < i; j++) { - if (level_confs[j].max_level == level_confs[i].max_level) { - LOGE("Dup level conf:%d", i); - goto end; - } - if (level_confs[j].max_level > level_confs[i].max_level) { - anim_level_conf conf = level_confs[i]; - memmove(level_confs + j + 1, level_confs + j, - (i - j) * sizeof(anim_level_conf)); - level_confs[j] = conf; - } - } - } - - printf("Parse anim desc(%s):\n", desc); - printf("only_current_level=%d\n", only_current_level); - printf("level conf:\n"); - for (i = 0; i < level_conf_num; i++) { - printf("\tmax=%d, delay=%d, num=%d, prefix=%s\n", level_confs[i].max_level, - level_confs[i].delay, level_confs[i].num, level_confs[i].prefix); - } - -end: - free_content(&content); - return 0; -} - -/**********************anim test end************************/ -/**********************append file************************/ - -static const char *PROG = NULL; -static resource_ptn_header header; -static bool just_print = false; -static bool keep_dtbname = false; -static char root_path[MAX_INDEX_ENTRY_PATH_LEN] = "\0"; - -static void version(void) -{ - printf("%s (cjf@rock-chips.com)\t" VERSION "\n", PROG); -} - -static void usage(void) -{ - printf("Usage: %s [options] [FILES]\n", PROG); - printf("Tools for Rockchip's resource image.\n"); - version(); - printf("Options:\n"); - printf("\t" OPT_PACK "\t\t\tPack image from given files.\n"); - printf("\t" OPT_UNPACK "\t\tUnpack given image to current dir.\n"); - printf("\t" OPT_IMAGE "path" - "\t\tSpecify input/output image path.\n"); - printf("\t" OPT_PRINT "\t\t\tJust print informations.\n"); - printf("\t" OPT_VERBOSE "\t\tDisplay more runtime informations.\n"); - printf("\t" OPT_HELP "\t\t\tDisplay this information.\n"); - printf("\t" OPT_VERSION "\t\tDisplay version information.\n"); - printf("\t" OPT_ROOT "path" - "\t\tSpecify resources' root dir.\n"); -} - -static int pack_image(int file_num, const char **files); -static int unpack_image(const char *unpack_dir); - -enum ACTION { - ACTION_PACK, - ACTION_UNPACK, - ACTION_TEST_LOAD, - ACTION_TEST_CHARGE, -}; - -int main(int argc, char **argv) -{ - PROG = fix_path(argv[0]); - - enum ACTION action = ACTION_PACK; - - argc--, argv++; - while (argc > 0 && argv[0][0] == '-') { - /* it's a opt arg. */ - const char *arg = argv[0]; - argc--, argv++; - if (!strcmp(OPT_VERBOSE, arg)) { - g_debug = true; - } else if (!strcmp(OPT_HELP, arg)) { - usage(); - return 0; - } else if (!strcmp(OPT_VERSION, arg)) { - version(); - return 0; - } else if (!strcmp(OPT_PRINT, arg)) { - just_print = true; - } else if (!strcmp(OPT_DTBNAME, arg)) { - keep_dtbname = true; - } else if (!strcmp(OPT_PACK, arg)) { - action = ACTION_PACK; - } else if (!strcmp(OPT_UNPACK, arg)) { - action = ACTION_UNPACK; - } else if (!strcmp(OPT_TEST_LOAD, arg)) { - action = ACTION_TEST_LOAD; - } else if (!strcmp(OPT_TEST_CHARGE, arg)) { - action = ACTION_TEST_CHARGE; - } else if (!memcmp(OPT_IMAGE, arg, strlen(OPT_IMAGE))) { - snprintf(image_path, sizeof(image_path), "%s", arg + strlen(OPT_IMAGE)); - } else if (!memcmp(OPT_ROOT, arg, strlen(OPT_ROOT))) { - snprintf(root_path, sizeof(root_path), "%s", arg + strlen(OPT_ROOT)); - } else { - LOGE("Unknown opt:%s", arg); - usage(); - return -1; - } - } - - if (!image_path[0]) { - snprintf(image_path, sizeof(image_path), "%s", DEFAULT_IMAGE_PATH); - } - - switch (action) { - case ACTION_PACK: { - int file_num = argc; - const char **files = (const char **)argv; - if (!file_num) { - LOGE("No file to pack!"); - return 0; - } - LOGD("try to pack %d files.", file_num); - return pack_image(file_num, files); - } - case ACTION_UNPACK: { - return unpack_image(argc > 0 ? argv[0] : DEFAULT_UNPACK_DIR); - } - case ACTION_TEST_LOAD: { - return test_load(argc, argv); - } - case ACTION_TEST_CHARGE: { - return test_charge(argc, argv); - } - } - /* not reach here. */ - return -1; -} - -/************unpack code****************/ -static bool mkdirs(char *path) -{ - char *tmp = path; - char *pos = NULL; - char buf[MAX_INDEX_ENTRY_PATH_LEN]; - bool ret = true; - while ((pos = memchr(tmp, '/', strlen(tmp)))) { - strcpy(buf, path); - buf[pos - path] = '\0'; - tmp = pos + 1; - LOGD("mkdir:%s", buf); - if (!mkdir(buf, 0755)) { - ret = false; - } - } - if (!ret) - LOGD("Failed to mkdir(%s)!", path); - return ret; -} - -static bool dump_file(FILE *file, const char *unpack_dir, - index_tbl_entry entry) -{ - LOGD("try to dump entry:%s", entry.path); - bool ret = false; - FILE *out_file = NULL; - long int pos = 0; - char path[MAX_INDEX_ENTRY_PATH_LEN * 2 + 1]; - if (just_print) { - ret = true; - goto done; - } - - pos = ftell(file); - snprintf(path, sizeof(path), "%s/%s", unpack_dir, entry.path); - mkdirs(path); - out_file = fopen(path, "wb"); - if (!out_file) { - LOGE("Failed to create:%s", path); - goto end; - } - long int offset = entry.content_offset * BLOCK_SIZE; - fseek(file, offset, SEEK_SET); - if (offset != ftell(file)) { - LOGE("Failed to read content:%s", entry.path); - goto end; - } - char buf[BLOCK_SIZE]; - int n; - int len = entry.content_size; - while (len > 0) { - n = len > BLOCK_SIZE ? BLOCK_SIZE : len; - if (!fread(buf, n, 1, file)) { - LOGE("Failed to read content:%s", entry.path); - goto end; - } - if (!fwrite(buf, n, 1, out_file)) { - LOGE("Failed to write:%s", entry.path); - goto end; - } - len -= n; - } -done: - ret = true; -end: - if (out_file) - fclose(out_file); - if (pos) - fseek(file, pos, SEEK_SET); - return ret; -} - -static int unpack_image(const char *dir) -{ - FILE *image_file = NULL; - bool ret = false; - char unpack_dir[MAX_INDEX_ENTRY_PATH_LEN]; - if (just_print) - dir = "."; - snprintf(unpack_dir, sizeof(unpack_dir), "%s", dir); - if (!strlen(unpack_dir)) { - goto end; - } else if (unpack_dir[strlen(unpack_dir) - 1] == '/') { - unpack_dir[strlen(unpack_dir) - 1] = '\0'; - } - - mkdir(unpack_dir, 0755); - image_file = fopen(image_path, "rb"); - char buf[BLOCK_SIZE]; - if (!image_file) { - LOGE("Failed to open:%s", image_path); - goto end; - } - if (!fread(buf, BLOCK_SIZE, 1, image_file)) { - LOGE("Failed to read header!"); - goto end; - } - memcpy(&header, buf, sizeof(header)); - - if (memcmp(header.magic, RESOURCE_PTN_HDR_MAGIC, sizeof(header.magic))) { - LOGE("Not a resource image(%s)!", image_path); - goto end; - } - /* switch for be. */ - fix_header(&header); - - printf("Dump header:\n"); - printf("partition version:%d.%d\n", header.resource_ptn_version, - header.index_tbl_version); - printf("header size:%d\n", header.header_size); - printf("index tbl:\n\toffset:%d\tentry size:%d\tentry num:%d\n", - header.tbl_offset, header.tbl_entry_size, header.tbl_entry_num); - - /* TODO: support header_size & tbl_entry_size */ - if (header.resource_ptn_version != RESOURCE_PTN_VERSION || - header.header_size != RESOURCE_PTN_HDR_SIZE || - header.index_tbl_version != INDEX_TBL_VERSION || - header.tbl_entry_size != INDEX_TBL_ENTR_SIZE) { - LOGE("Not supported in this version!"); - goto end; - } - - printf("Dump Index table:\n"); - index_tbl_entry entry; - int i; - for (i = 0; i < header.tbl_entry_num; i++) { - /* TODO: support tbl_entry_size */ - if (!fread(buf, BLOCK_SIZE, 1, image_file)) { - LOGE("Failed to read index entry:%d!", i); - goto end; - } - memcpy(&entry, buf, sizeof(entry)); - - if (memcmp(entry.tag, INDEX_TBL_ENTR_TAG, sizeof(entry.tag))) { - LOGE("Something wrong with index entry:%d!", i); - goto end; - } - /* switch for be. */ - fix_entry(&entry); - - printf("entry(%d):\n\tpath:%s\n\toffset:%d\tsize:%d\n", i, entry.path, - entry.content_offset, entry.content_size); - if (!dump_file(image_file, unpack_dir, entry)) { - goto end; - } - } - printf("Unack %s to %s successed!\n", image_path, unpack_dir); - ret = true; -end: - if (image_file) - fclose(image_file); - return ret ? 0 : -1; -} - -/************unpack code end****************/ -/************pack code****************/ - -static inline size_t get_file_size(const char *path) -{ - LOGD("try to get size(%s)...", path); - struct stat st; - if (stat(path, &st) < 0) { - LOGE("Failed to get size:%s", path); - return -1; - } - LOGD("path:%s, size:%ld", path, st.st_size); - return st.st_size; -} - -static int write_file(int offset_block, const char *src_path, - char hash[], int hash_size) -{ - LOGD("try to write file(%s) to offset:%d...", src_path, offset_block); - char *buf = NULL; - int ret = -1; - size_t file_size; - FILE *src_file = fopen(src_path, "rb"); - if (!src_file) { - LOGE("Failed to open:%s", src_path); - goto end; - } - - file_size = get_file_size(src_path); - if (file_size < 0) { - goto end; - } - - buf = calloc(file_size, 1); - if (!buf) - goto end; - - if (!fread(buf, file_size, 1, src_file)) - goto end; - - if (!write_data(offset_block, buf, file_size)) - goto end; - - if (hash_size == 20) - sha1_csum((const unsigned char *)buf, file_size, - (unsigned char *)hash); - else if (hash_size == 32) - sha256_csum((const unsigned char *)buf, file_size, - (unsigned char *)hash); - else - goto end; - - ret = file_size; -end: - if (src_file) - fclose(src_file); - if (buf) - free(buf); - - return ret; -} - -static bool write_header(const int file_num) -{ - LOGD("try to write header..."); - memcpy(header.magic, RESOURCE_PTN_HDR_MAGIC, sizeof(header.magic)); - header.resource_ptn_version = RESOURCE_PTN_VERSION; - header.index_tbl_version = INDEX_TBL_VERSION; - header.header_size = RESOURCE_PTN_HDR_SIZE; - header.tbl_offset = header.header_size; - header.tbl_entry_size = INDEX_TBL_ENTR_SIZE; - header.tbl_entry_num = file_num; - - /* switch for le. */ - resource_ptn_header hdr = header; - fix_header(&hdr); - return write_data(0, &hdr, sizeof(hdr)); -} - -static bool write_index_tbl(const int file_num, const char **files) -{ - LOGD("try to write index table..."); - bool ret = false; - bool foundFdt = false; - int offset = - header.header_size + header.tbl_entry_size * header.tbl_entry_num; - index_tbl_entry entry; - char hash[20]; /* sha1 */ - int i; - - memcpy(entry.tag, INDEX_TBL_ENTR_TAG, sizeof(entry.tag)); - for (i = 0; i < file_num; i++) { - size_t file_size = get_file_size(files[i]); - if (file_size < 0) - goto end; - entry.content_size = file_size; - entry.content_offset = offset; - - if (write_file(offset, files[i], hash, sizeof(hash)) < 0) - goto end; - - memcpy(entry.hash, hash, sizeof(hash)); - entry.hash_size = sizeof(hash); - - LOGD("try to write index entry(%s)...", files[i]); - - /* switch for le. */ - fix_entry(&entry); - memset(entry.path, 0, sizeof(entry.path)); - const char *path = files[i]; - - if (strstr(path, ".dtb") && keep_dtbname) { - path = rindex(path, '/'); - if (!path) - path = files[i]; - else - path++; - LOGD("using dtb name: %s", path); - - } else { - if (root_path[0]) { - if (!strncmp(path, root_path, strlen(root_path))) { - path += strlen(root_path); - if (path[0] == '/') - path++; - } - } - path = fix_path(path); - if (!strcmp(files[i] + strlen(files[i]) - strlen(DTD_SUBFIX), DTD_SUBFIX)) { - if (!foundFdt) { - /* use default path. */ - LOGD("mod fdt path:%s -> %s...", files[i], FDT_PATH); - path = FDT_PATH; - foundFdt = true; - } - } - } - - snprintf(entry.path, sizeof(entry.path), "%s", path); - offset += fix_blocks(file_size); - if (!write_data(header.header_size + i * header.tbl_entry_size, &entry, - sizeof(entry))) - goto end; - } - ret = true; -end: - return ret; -} - -static int pack_image(int file_num, const char **files) -{ - bool ret = false; - FILE *image_file = fopen(image_path, "wb"); - if (!image_file) { - LOGE("Failed to create:%s", image_path); - goto end; - } - fclose(image_file); - - /* prepare files */ - int i = 0; - int pos = 0; - const char *tmp; - for (i = 0; i < file_num; i++) { - if (!strcmp(files[i] + strlen(files[i]) - strlen(DTD_SUBFIX), DTD_SUBFIX)) { - /* dtb files for kernel. */ - tmp = files[pos]; - files[pos] = files[i]; - files[i] = tmp; - pos++; - } else if (!strcmp(fix_path(image_path), fix_path(files[i]))) { - /* not to pack image itself! */ - tmp = files[file_num - 1]; - files[file_num - 1] = files[i]; - files[i] = tmp; - file_num--; - } - } - - if (!write_header(file_num)) { - LOGE("Failed to write header!"); - goto end; - } - if (!write_index_tbl(file_num, files)) { - LOGE("Failed to write index table!"); - goto end; - } - printf("Pack to %s successed!\n", image_path); - ret = true; -end: - return ret ? 0 : -1; -} - -/************pack code end****************/ diff --git a/patches-6.1/990-arm64-build-boot-image.patch b/patches-6.1/990-arm64-build-boot-image.patch deleted file mode 100644 index 5e05dc7..0000000 --- a/patches-6.1/990-arm64-build-boot-image.patch +++ /dev/null @@ -1,25 +0,0 @@ ---- a/arch/arm64/Makefile -+++ b/arch/arm64/Makefile -@@ -158,8 +158,12 @@ endif - all: $(notdir $(KBUILD_IMAGE)) - - -+DTBS := rk35*-nanopi*.dtb - Image vmlinuz.efi: vmlinux - $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ -+ $(Q)scripts/mkkrnlimg $(objtree)/arch/arm64/boot/Image $(objtree)/kernel.img >/dev/null -+ @echo ' Image: kernel.img is ready' -+ $(Q)$(srctree)/scripts/mkimg --dtb $(DTBS) - - Image.%: Image - $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ ---- a/scripts/Makefile -+++ b/scripts/Makefile -@@ -10,6 +10,7 @@ hostprogs-always-$(CONFIG_BUILDTIME_TABL - hostprogs-always-$(CONFIG_ASN1) += asn1_compiler - hostprogs-always-$(CONFIG_MODULE_SIG_FORMAT) += sign-file - hostprogs-always-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert -+hostprogs-always-$(CONFIG_ARM64) += resource_tool mkkrnlimg - hostprogs-always-$(CONFIG_RUST) += generate_rust_target - - generate_rust_target-rust := y