econet: image: add little endian TRX support for EN7528

The EN7528 SoC uses a little endian MIPS architecture, unlike the big
endian EN751221 family. The tclinux TRX firmware format stores multi-byte
fields in the CPU's native byte order, requiring different header layouts
for each architecture:

  - Big endian (EN751221): magic "2RDH", fields in big endian order
  - Little endian (EN7528): magic "HDR2", fields in little endian order

Update tclinux-trx.sh to support both endianness variants:
  - Add --endian parameter to select byte order (default: be)
  - Add --model parameter for optional platform identifier field
  - Convert to named parameters for clarity and extensibility
  - Use hex32() helper for endian-aware 32-bit field output

Move TRX_ENDIAN configuration to subtarget files, allowing each subtarget
to specify its native byte order:
  - en751221.mk: TRX_ENDIAN := be
  - en7528.mk: TRX_ENDIAN := le

Signed-off-by: Ahmed Naseef <naseefkm@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/21326
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
This commit is contained in:
Ahmed Naseef 2025-12-30 08:57:29 +04:00 committed by Hauke Mehrtens
parent 83c6b5b5d0
commit 9ba87609b8
4 changed files with 107 additions and 16 deletions

View file

@ -7,7 +7,9 @@ endef
# tclinux-trx is the default format used in the SDK
define Build/tclinux-trx
./tclinux-trx.sh $@ $(IMAGE_ROOTFS) $(VERSION_DIST)-$(REVISION) > $@.new
./tclinux-trx.sh --kernel $@ --rootfs $(IMAGE_ROOTFS) \
--version $(VERSION_DIST)-$(REVISION) --endian $(TRX_ENDIAN) \
$(if $(TRX_MODEL),--model $(TRX_MODEL)) > $@.new
mv $@.new $@
endef

View file

@ -1,3 +1,5 @@
TRX_ENDIAN := be
define Device/en751221_generic
DEVICE_VENDOR := EN751221 Family
DEVICE_MODEL := Initramfs Image

View file

@ -1,3 +1,5 @@
TRX_ENDIAN := le
define Device/en7528_generic
DEVICE_VENDOR := EN7528
DEVICE_MODEL := Generic

View file

@ -14,14 +14,76 @@ die() {
exit 1
}
[ $# -eq 3 ] || die "SYNTAX: $0 <kernel lzma> <rootfs squashfs> <version string>"
kernel=$1
rootfs=$2
version=$3
usage() {
cat >&2 <<EOF
SYNTAX: $0 --kernel <file> --rootfs <file> --version <string> [options]
Options:
--kernel Path to kernel lzma file (required)
--rootfs Path to rootfs squashfs file (required)
--version Version string, max 31 chars (required)
--endian Endianness: 'be' for big endian, 'le' for little endian (default: be)
--model Model/platform name, max 31 chars (default: empty)
EOF
exit 1
}
# Defaults
kernel=""
rootfs=""
version=""
endian="be"
model=""
# Parse named arguments
while [ $# -gt 0 ]; do
case "$1" in
--kernel)
kernel="$2"
shift 2
;;
--rootfs)
rootfs="$2"
shift 2
;;
--version)
version="$2"
shift 2
;;
--endian)
endian="$2"
shift 2
;;
--model)
model="$2"
shift 2
;;
-h|--help)
usage
;;
*)
die "Unknown option: $1"
;;
esac
done
# Validate required arguments
[ -n "$kernel" ] || die "Missing required argument: --kernel"
[ -n "$rootfs" ] || die "Missing required argument: --rootfs"
[ -n "$version" ] || die "Missing required argument: --version"
# Validate endianness
case "$endian" in
be|BE) endian="be" ;;
le|LE) endian="le" ;;
*) die "Invalid endianness: $endian (must be 'be' or 'le')" ;;
esac
which zytrx >/dev/null || die "zytrx not found in PATH $PATH"
[ -f "$kernel" ] || die "Kernel file not found: $kernel"
[ -f "$rootfs" ] || die "Rootfs file not found: $rootfs"
[ "$(echo "$version" | wc -c)" -lt 32 ] || die "Version string too long: $version"
[ -z "$model" ] || [ "$(printf '%s' "$model" | wc -c)" -lt 32 ] || die "Model string too long: $model"
kernel_len=$(stat -c '%s' "$kernel")
header_plus_kernel_len=$(($HDRLEN + $kernel_len))
@ -33,6 +95,7 @@ else
padding_len=0
fi
echo "endian: $endian" >&2
echo "padding_len: $padding_len" >&2
padded_rootfs_len=$(($padding_len + $rootfs_len))
@ -55,6 +118,18 @@ from_hex() {
perl -pe 's/\s+//g; s/(..)/chr(hex($1))/ge'
}
# Output a 32-bit value in hex with correct endianness
# Usage: hex32 <value>
hex32() {
val=$(printf '%08x' "$1")
if [ "$endian" = "le" ]; then
# Swap bytes for little endian: AABBCCDD -> DDCCBBAA
echo "$val" | sed 's/\(..\)\(..\)\(..\)\(..\)/\4\3\2\1/'
else
echo "$val"
fi
}
trx_crc32() {
tmpfile=$(mktemp)
outtmpfile=$(mktemp)
@ -69,19 +144,24 @@ trx_crc32() {
-v x \
-i "$tmpfile" \
-o "$outtmpfile" >/dev/null
dd if="$outtmpfile" bs=4 count=1 skip=3 | to_hex
crc_hex=$(dd if="$outtmpfile" bs=4 count=1 skip=3 2>/dev/null | to_hex)
rm "$tmpfile" "$outtmpfile" >/dev/null
hex32 "0x$crc_hex"
}
tclinux_trx_hdr() {
# TRX header magic
printf '2RDH' | to_hex
# TRX header magic: "2RDH" for big endian, "HDR2" for little endian
if [ "$endian" = "le" ]; then
printf 'HDR2' | to_hex
else
printf '2RDH' | to_hex
fi
# Length of the header
printf '%08x\n' "$HDRLEN"
hex32 "$HDRLEN"
# Length of header + content
printf '%08x\n' "$total_len"
hex32 "$total_len"
# crc32 of the content
trx_crc32
@ -94,19 +174,24 @@ tclinux_trx_hdr() {
head -c 32 /dev/zero | to_hex
# kernel length
printf '%08x\n' "$kernel_len"
hex32 "$kernel_len"
# rootfs length
printf '%08x\n' "$padded_rootfs_len"
hex32 "$padded_rootfs_len"
# romfile length (0)
printf '00000000\n'
hex32 0
# "model" (32 bytes of zeros)
head -c 32 /dev/zero | to_hex
# model (32 bytes, zero-padded)
if [ -n "$model" ]; then
printf '%s' "$model" | to_hex
head -c "$((32 - $(printf '%s' "$model" | wc -c)))" /dev/zero | to_hex
else
head -c 32 /dev/zero | to_hex
fi
# Load address (CONFIG_ZBOOT_LOAD_ADDRESS)
printf '80020000\n'
hex32 0x80020000
# "reserved" 128 bytes of zeros
head -c 128 /dev/zero | to_hex