From 4a69c8aac3c753c2dd9933f15406560a166be8a8 Mon Sep 17 00:00:00 2001 From: coolsnowwolf Date: Sun, 13 Nov 2022 20:22:27 +0800 Subject: [PATCH] ramips: fix Beeline SmartBox TURBO+ support --- scripts/sercomm-kernel.sh | 122 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100755 scripts/sercomm-kernel.sh diff --git a/scripts/sercomm-kernel.sh b/scripts/sercomm-kernel.sh new file mode 100755 index 000000000..6ce3086c9 --- /dev/null +++ b/scripts/sercomm-kernel.sh @@ -0,0 +1,122 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright (c) 2021 Mikhail Zhilkin +# +### +### sercomm-kernel.sh - calculates and appends a special kernel header. +### Intended for some Sercomm devices (e.g., Beeline +### SmartBox GIGA, Beeline SmartBox Turbo+, Sercomm +### S3). +# +# Credits to @kar200 for the header description. More details are here: +# https://forum.openwrt.org/t/add-support-for-sercomm-s3-on-stock-uboot +# +if [ $# -ne 3 ]; then + echo "SYNTAX: $0 " + exit 1 +fi + +FILE_TMP=$1.shdr +KERNEL_IMG=$1 +KERNEL_OFFSET=$2 +ROOTFS_OFFSET=$3 + +# Sercomm HDR (0x53657200), 0xffffffff for hdr crc32 calc +hdr_sign_offs=0x0 +hdr_sign_val=0x53657200 +# Absoulte lenght for Sercomm footer +hdr_footer_size_offs=0x4 +hdr_footer_size_val= +# Header checksum. 0xffffffff for hdr crc32 calc +hdr_head_chksum_offs=0x8 +hdr_head_chksum_val= +# Magic constant (0x2ffffff) +hdr_int04_offs=0xc +hdr_int04_val=0x2ffffff +# Kernel flash offset +hdr_kern_offs_offs=0x10 +hdr_kern_offs_val=$KERNEL_OFFSET +# Kernel lenght +hdr_kern_len_offs=0x14 +hdr_kern_len_val= +# Kernel checksum +hdr_kern_chksum_offs=0x18 +hdr_kern_chksum_val= +# Magic constant (0x0) +hdr_int08_offs=0x1c +hdr_int08_val=0x0 +# Rootfs flash offset +hdr_rootfs_offs_offs=0x28 +hdr_rootfs_offs_val=$ROOTFS_OFFSET +# Rootfs flash lenght. We're checking only first 4 bytes +hdr_rootfs_len_offs=0x2c +hdr_rootfs_len_val=0x4 +# Rootfs checksum. Checksum is a constant for UBI (first 4 bytes) +hdr_rootfs_chksum_offs=0x30 +hdr_rootfs_chksum_val=0x1cfc552d +# Magic constant (0x0) +hdr_int10_offs=0x34 +hdr_int10_val=0x0 + +pad_zeros () { + awk '{ printf "%8s\n", $0 }' | sed 's/ /0/g' +} + +# Remove leading 0x +trim_hx () { + printf "%x\n" $1 | pad_zeros +} + +# Change endian +swap_hx () { + pad_zeros | awk '{for (i=7;i>=1;i=i-2) printf "%s%s", \ + substr($1,i,2), (i>1?"":"\n")}' +} + +# Check file size +fsize () { + printf "%x\n" `stat -c "%s" $1` +} + +# Calculate checksum +chksum () { + dd if=$1 2>/dev/null | gzip -c | tail -c 8 | od -An -tx4 -N4 \ + --endian=big | tr -d ' \n' | pad_zeros +} + +# Write 4 bytes in the header by offset +write_hdr () { + echo -ne "$(echo $1 | sed 's/../\\x&/g')" | dd of=$FILE_TMP bs=1 \ + seek=$(($2)) count=4 conv=notrunc status=none 2>/dev/null +} + +# Pad a new header with 0xff +dd if=/dev/zero ibs=1 count=256 status=none | tr "\000" "\377" > \ + $FILE_TMP 2>/dev/null + +# Write constants +write_hdr $(trim_hx $hdr_int04_val) $hdr_int04_offs +write_hdr $(trim_hx $hdr_int08_val) $hdr_int08_offs +write_hdr $(trim_hx $hdr_int10_val) $hdr_int10_offs +# Write footer data +hdr_footer_size_val=$(($hdr_rootfs_offs_val + $hdr_rootfs_len_val)) +write_hdr $(trim_hx $hdr_footer_size_val | swap_hx) $hdr_footer_size_offs +# Write kernel data +write_hdr $(trim_hx $hdr_kern_offs_val | swap_hx) $hdr_kern_offs_offs +hdr_kern_len_val=$(fsize $KERNEL_IMG | pad_zeros) +write_hdr $(echo $hdr_kern_len_val | swap_hx) $hdr_kern_len_offs +hdr_kern_chksum_val=$(chksum $KERNEL_IMG) +write_hdr $hdr_kern_chksum_val $hdr_kern_chksum_offs +# Write rootfs data +write_hdr $(trim_hx $hdr_rootfs_offs_val | swap_hx) $hdr_rootfs_offs_offs +write_hdr $(trim_hx $hdr_rootfs_len_val | swap_hx) $hdr_rootfs_len_offs +write_hdr $(trim_hx $hdr_rootfs_chksum_val) $hdr_rootfs_chksum_offs +# Write header checksum +hdr_head_chksum_val=$(chksum $FILE_TMP) +write_hdr $hdr_head_chksum_val $hdr_head_chksum_offs +# Place Sercomm signature +write_hdr $(trim_hx $hdr_sign_val) $hdr_sign_offs + +dd if=$KERNEL_IMG >> $FILE_TMP +mv $FILE_TMP $KERNEL_IMG