|
@@ -14,14 +14,76 @@ die() {
|
|
|
exit 1
|
|
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"
|
|
which zytrx >/dev/null || die "zytrx not found in PATH $PATH"
|
|
|
[ -f "$kernel" ] || die "Kernel file not found: $kernel"
|
|
[ -f "$kernel" ] || die "Kernel file not found: $kernel"
|
|
|
[ -f "$rootfs" ] || die "Rootfs file not found: $rootfs"
|
|
[ -f "$rootfs" ] || die "Rootfs file not found: $rootfs"
|
|
|
[ "$(echo "$version" | wc -c)" -lt 32 ] || die "Version string too long: $version"
|
|
[ "$(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")
|
|
kernel_len=$(stat -c '%s' "$kernel")
|
|
|
header_plus_kernel_len=$(($HDRLEN + $kernel_len))
|
|
header_plus_kernel_len=$(($HDRLEN + $kernel_len))
|
|
@@ -33,6 +95,7 @@ else
|
|
|
padding_len=0
|
|
padding_len=0
|
|
|
fi
|
|
fi
|
|
|
|
|
|
|
|
|
|
+echo "endian: $endian" >&2
|
|
|
echo "padding_len: $padding_len" >&2
|
|
echo "padding_len: $padding_len" >&2
|
|
|
|
|
|
|
|
padded_rootfs_len=$(($padding_len + $rootfs_len))
|
|
padded_rootfs_len=$(($padding_len + $rootfs_len))
|
|
@@ -55,6 +118,18 @@ from_hex() {
|
|
|
perl -pe 's/\s+//g; s/(..)/chr(hex($1))/ge'
|
|
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() {
|
|
trx_crc32() {
|
|
|
tmpfile=$(mktemp)
|
|
tmpfile=$(mktemp)
|
|
|
outtmpfile=$(mktemp)
|
|
outtmpfile=$(mktemp)
|
|
@@ -69,19 +144,24 @@ trx_crc32() {
|
|
|
-v x \
|
|
-v x \
|
|
|
-i "$tmpfile" \
|
|
-i "$tmpfile" \
|
|
|
-o "$outtmpfile" >/dev/null
|
|
-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
|
|
rm "$tmpfile" "$outtmpfile" >/dev/null
|
|
|
|
|
+ hex32 "0x$crc_hex"
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
tclinux_trx_hdr() {
|
|
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
|
|
# Length of the header
|
|
|
- printf '%08x\n' "$HDRLEN"
|
|
|
|
|
|
|
+ hex32 "$HDRLEN"
|
|
|
|
|
|
|
|
# Length of header + content
|
|
# Length of header + content
|
|
|
- printf '%08x\n' "$total_len"
|
|
|
|
|
|
|
+ hex32 "$total_len"
|
|
|
|
|
|
|
|
# crc32 of the content
|
|
# crc32 of the content
|
|
|
trx_crc32
|
|
trx_crc32
|
|
@@ -94,19 +174,24 @@ tclinux_trx_hdr() {
|
|
|
head -c 32 /dev/zero | to_hex
|
|
head -c 32 /dev/zero | to_hex
|
|
|
|
|
|
|
|
# kernel length
|
|
# kernel length
|
|
|
- printf '%08x\n' "$kernel_len"
|
|
|
|
|
|
|
+ hex32 "$kernel_len"
|
|
|
|
|
|
|
|
# rootfs length
|
|
# rootfs length
|
|
|
- printf '%08x\n' "$padded_rootfs_len"
|
|
|
|
|
|
|
+ hex32 "$padded_rootfs_len"
|
|
|
|
|
|
|
|
# romfile length (0)
|
|
# 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)
|
|
# Load address (CONFIG_ZBOOT_LOAD_ADDRESS)
|
|
|
- printf '80020000\n'
|
|
|
|
|
|
|
+ hex32 0x80020000
|
|
|
|
|
|
|
|
# "reserved" 128 bytes of zeros
|
|
# "reserved" 128 bytes of zeros
|
|
|
head -c 128 /dev/zero | to_hex
|
|
head -c 128 /dev/zero | to_hex
|