mirror of
https://git.openwrt.org/openwrt/openwrt.git
synced 2026-02-19 15:51:15 +01:00
econet: Add new target SmartFiber XP8421-B
The SmartFiber XP8421-B is a fiber modem which is available for $20 online and has 512MB of memory, 256MB of SPI NAND flash and 2 USB 2.0 ports in addition to ethernet, wifi and XPON. Because EcoNet is not currently producing evaluation boards, the XP8421-B stands in as a convenient, low cost, off-the-shelf, representitive example of the capabilities of the EN751221 econet processor. This is also the example board that is included in the upstream Linux patchset. The XP8421-B, and apparently many other devices of this platform, use a dual-image layout. I have chosen to reuse this to support dual-boot between OpenWRT and the factory firmware. Certain design decisions were made with the goal of not overwriting data that is used by the factory OS. This commit also introduces a utility for switching between OS_A and OS_B which are used for OpenWRT and Factory OS respectively. Flashing instructions (from bootloader): Build and then locate the squashfs-tclinux.trx image file Get the length of that file in hex: printf '%X\n' "$(stat -c%s the-file-squashfs-tclinux.trx)" Connect to device with xmodem capability, e.g. picocom --send-cmd lsx -vv -b 115200 /dev/ttyUSB0 Switch device on and press a key within 3 seconds Enter bootloader username and password: telecomadmin nE7jA%5m Type: xmdm 80020000 <file length hex> Quickly start xmodem and send the file, in picocom that is ctrl+a ctrl+s <paste-the-file-name> enter If the transfer fails to start, wait 30 seconds to a minute for the bootloader prompt to return and then try the command again. Once the transfer has completed successfully, type the following flash 80000 80020000 <file length hex> Type go or simply restart the device to boot into OpenWRT Signed-off-by: Caleb James DeLisle <cjd@cjdns.fr> Link: https://github.com/openwrt/openwrt/pull/19021 Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
This commit is contained in:
parent
73d0f92460
commit
ef2785a2d0
4 changed files with 336 additions and 1 deletions
112
target/linux/econet/base-files/sbin/en75_chboot
Executable file
112
target/linux/econet/base-files/sbin/en75_chboot
Executable file
|
|
@ -0,0 +1,112 @@
|
|||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
set -e
|
||||
|
||||
part=
|
||||
offset_blocks=
|
||||
block_size=
|
||||
code_openwrt=
|
||||
code_factory=
|
||||
code_offset=
|
||||
|
||||
read_nand() {
|
||||
dd "if=$part" "of=$file" "bs=$block_size" "skip=$offset_blocks" count=1 2>/dev/null
|
||||
}
|
||||
|
||||
write_nand() {
|
||||
flash_erase -N -q "$part" $((offset_blocks * block_size)) 1
|
||||
dd "if=$file" "of=$part" "bs=$block_size" "seek=$offset_blocks" count=1 2>/dev/null
|
||||
}
|
||||
|
||||
part_named() {
|
||||
name=$1
|
||||
pn=$(grep "$name" < /proc/mtd | sed 's/:.*//')
|
||||
if [ -z "$pn" ]; then
|
||||
echo "Partition not found: $name"
|
||||
exit 1
|
||||
fi
|
||||
echo "/dev/$pn"
|
||||
}
|
||||
|
||||
to_hex() {
|
||||
hexdump -v -e '1/1 "%02x"'
|
||||
}
|
||||
|
||||
from_hex() {
|
||||
sed 's/\([0-9a-fA-F]\{2\}\)/echo -n -e "\\x\1"\n/g' | sh
|
||||
}
|
||||
|
||||
check() {
|
||||
stored_code=$(dd \
|
||||
"if=$part" \
|
||||
bs=1 \
|
||||
skip=$((offset_blocks * block_size + code_offset)) \
|
||||
count=$((${#code_openwrt} / 2)) \
|
||||
2>/dev/null | to_hex
|
||||
)
|
||||
if [ "$stored_code" = "$code_openwrt" ]; then
|
||||
echo "Current boot flag set to OS A (OpenWrt)"
|
||||
elif [ "$stored_code" = "$code_factory" ]; then
|
||||
echo "Current boot flag set to OS B (Factory)"
|
||||
else
|
||||
echo "Current boot flag unknown: $stored_code"
|
||||
fi
|
||||
}
|
||||
|
||||
switch() {
|
||||
switch_to=$1
|
||||
|
||||
echo "Switching boot flag to $switch_to"
|
||||
file=$(mktemp)
|
||||
read_nand
|
||||
if [ "$switch_to" = "factory" ]; then
|
||||
echo "$code_factory" | from_hex | \
|
||||
dd "of=$file" bs=1 "seek=$code_offset" conv=notrunc 2>/dev/null
|
||||
elif [ "$switch_to" = "openwrt" ]; then
|
||||
echo "$code_openwrt" | from_hex | \
|
||||
dd "of=$file" bs=1 "seek=$code_offset" conv=notrunc 2>/dev/null
|
||||
else
|
||||
echo "Invalid switch_to: $switch_to"
|
||||
exit 1
|
||||
fi
|
||||
write_nand
|
||||
rm "$file"
|
||||
echo "Flash write complete"
|
||||
check
|
||||
}
|
||||
|
||||
main() {
|
||||
machine=$(sed -n -e 's/^machine\s\+:\s\+//p' < /proc/cpuinfo)
|
||||
if [ "$machine" = "TP-Link Archer VR1200v (v2)" ]; then
|
||||
# 03fe0000
|
||||
part=$(part_named '"reserve"')
|
||||
offset_blocks=0
|
||||
block_size=$((1024 * 128))
|
||||
code_offset=0
|
||||
code_openwrt=0000000101000002
|
||||
code_factory=0000000101010003
|
||||
elif [ "$machine" = "SmartFiber XP8421-B" ]; then
|
||||
# 0dfc0000
|
||||
part=$(part_named '"reservearea"')
|
||||
offset_blocks=12
|
||||
block_size=$((1024 * 128))
|
||||
code_offset=0
|
||||
code_openwrt=30000000
|
||||
code_factory=31000000
|
||||
else
|
||||
echo "Unsupported machine: $machine"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$1" = "factory" ]; then
|
||||
switch factory
|
||||
elif [ "$1" = "openwrt" ]; then
|
||||
switch openwrt
|
||||
else
|
||||
echo "Usage: $0 factory|openwrt # Change boot flag to Factory OS or OpenWrt"
|
||||
check
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
main "$@"
|
||||
82
target/linux/econet/dts/en751221_smartfiber_xp8421-b.dts
Normal file
82
target/linux/econet/dts/en751221_smartfiber_xp8421-b.dts
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
/dts-v1/;
|
||||
|
||||
#include "en751221.dtsi"
|
||||
|
||||
/ {
|
||||
model = "SmartFiber XP8421-B";
|
||||
compatible = "smartfiber,xp8421-b", "econet,en751221";
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x00000000 0x1c000000>;
|
||||
};
|
||||
|
||||
chosen {
|
||||
stdout-path = "/serial@1fbf0000:115200";
|
||||
linux,usable-memory-range = <0x00020000 0x1bfe0000>;
|
||||
};
|
||||
};
|
||||
|
||||
&nand {
|
||||
status = "okay";
|
||||
econet,bmt;
|
||||
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "bootloader";
|
||||
reg = <0x0 0x40000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@40000 {
|
||||
label = "romfile";
|
||||
reg = <0x40000 0x40000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@80000 {
|
||||
label = "tclinux";
|
||||
reg = <0x80000 0x1400000>;
|
||||
read-only;
|
||||
econet,enable-remap;
|
||||
};
|
||||
|
||||
/* Nested inside of tclinux */
|
||||
partition@480000 {
|
||||
label = "rootfs";
|
||||
reg = <0x480000 0xf80000>;
|
||||
linux,rootfs;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@1480000 {
|
||||
label = "tclinux_alt";
|
||||
reg = <0x1480000 0x1400000>;
|
||||
};
|
||||
|
||||
partition@2880000 {
|
||||
label = "openjdk";
|
||||
reg = <0x2880000 0x2000000>;
|
||||
};
|
||||
|
||||
partition@4880000 {
|
||||
label = "ubifs";
|
||||
reg = <0x4880000 0x9100000>;
|
||||
};
|
||||
|
||||
partition@d980000 {
|
||||
label = "unknown";
|
||||
reg = <0xd980000 0x4c0000>;
|
||||
};
|
||||
|
||||
partition@de40000 {
|
||||
label = "reservearea";
|
||||
reg = <0xde40000 0x1c0000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -5,6 +5,29 @@ define Target/Description
|
|||
Build firmware images for EcoNet MIPS based boards.
|
||||
endef
|
||||
|
||||
# Devices will come in a later commit.
|
||||
# tclinux-trx is the default format used in the SDK
|
||||
define Build/tclinux-trx
|
||||
./tclinux-trx.sh $@ $(IMAGE_ROOTFS) $(VERSION_DIST)-$(REVISION) > $@.new
|
||||
mv $@.new $@
|
||||
endef
|
||||
|
||||
# tclinux bootloader requires LZMA, BUT only provides 7.5MB of space
|
||||
# to decompress into. So we use vmlinuz and decompress twice.
|
||||
define Device/Default
|
||||
DEVICE_DTS_DIR := ../dts
|
||||
KERNEL_SIZE := 7480k
|
||||
KERNEL_NAME := vmlinuz.bin
|
||||
KERNEL_LOADADDR := 0x80020000
|
||||
KERNEL := kernel-bin | append-dtb
|
||||
endef
|
||||
|
||||
define Device/smartfiber_xp8421-b
|
||||
DEVICE_VENDOR := SmartFiber
|
||||
DEVICE_MODEL := XP8421-B
|
||||
DEVICE_DTS := en751221_smartfiber_xp8421-b
|
||||
IMAGES := tclinux.trx
|
||||
IMAGE/tclinux.trx := append-kernel | lzma | tclinux-trx
|
||||
endef
|
||||
TARGET_DEVICES += smartfiber_xp8421-b
|
||||
|
||||
$(eval $(call BuildImage))
|
||||
|
|
|
|||
118
target/linux/econet/image/tclinux-trx.sh
Executable file
118
target/linux/econet/image/tclinux-trx.sh
Executable file
|
|
@ -0,0 +1,118 @@
|
|||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
set -e
|
||||
|
||||
# This is not necessary, but it makes finding the rootfs easier.
|
||||
PAD_ROOTFS_OFFSET_TO=4194304
|
||||
|
||||
# Constant
|
||||
HDRLEN=256
|
||||
|
||||
die() {
|
||||
echo "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
[ $# -eq 3 ] || die "SYNTAX: $0 <kernel lzma> <rootfs squashfs> <version string>"
|
||||
kernel=$1
|
||||
rootfs=$2
|
||||
version=$3
|
||||
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"
|
||||
|
||||
kernel_len=$(stat -c '%s' "$kernel")
|
||||
header_plus_kernel_len=$(($HDRLEN + $kernel_len))
|
||||
rootfs_len=$(stat -c '%s' "$rootfs")
|
||||
|
||||
if [ "$PAD_ROOTFS_OFFSET_TO" -gt "$header_plus_kernel_len" ]; then
|
||||
padding_len=$(($PAD_ROOTFS_OFFSET_TO - $header_plus_kernel_len))
|
||||
else
|
||||
padding_len=0
|
||||
fi
|
||||
|
||||
echo "padding_len: $padding_len" >&2
|
||||
|
||||
padded_rootfs_len=$(($padding_len + $rootfs_len))
|
||||
|
||||
echo "padded_rootfs_len: $padded_rootfs_len" >&2
|
||||
|
||||
total_len=$(($header_plus_kernel_len + $padded_rootfs_len))
|
||||
|
||||
echo "total_len: $total_len" >&2
|
||||
|
||||
padding() {
|
||||
head -c $padding_len /dev/zero | tr '\0' '\377'
|
||||
}
|
||||
|
||||
to_hex() {
|
||||
hexdump -v -e '1/1 "%02x"'
|
||||
}
|
||||
|
||||
from_hex() {
|
||||
perl -pe 's/\s+//g; s/(..)/chr(hex($1))/ge'
|
||||
}
|
||||
|
||||
trx_crc32() {
|
||||
tmpfile=$(mktemp)
|
||||
outtmpfile=$(mktemp)
|
||||
cat "$kernel" > "$tmpfile"
|
||||
padding >> "$tmpfile"
|
||||
cat "$rootfs" >> "$tmpfile"
|
||||
# We just need a CRC-32/JAMCRC of the concatnated files
|
||||
# There's no readily available tool for this, but zytrx does create one when
|
||||
# creating their TRX header, so we just use that.
|
||||
zytrx \
|
||||
-B NR7101 \
|
||||
-v x \
|
||||
-i "$tmpfile" \
|
||||
-o "$outtmpfile" >/dev/null
|
||||
dd if="$outtmpfile" bs=4 count=1 skip=3 | to_hex
|
||||
rm "$tmpfile" "$outtmpfile" >/dev/null
|
||||
}
|
||||
|
||||
tclinux_trx_hdr() {
|
||||
# TRX header magic
|
||||
printf '2RDH' | to_hex
|
||||
|
||||
# Length of the header
|
||||
printf '%08x\n' "$HDRLEN"
|
||||
|
||||
# Length of header + content
|
||||
printf '%08x\n' "$total_len"
|
||||
|
||||
# crc32 of the content
|
||||
trx_crc32
|
||||
|
||||
# version
|
||||
echo "$version" | to_hex
|
||||
head -c "$((32 - $(echo "$version" | wc -c)))" /dev/zero | to_hex
|
||||
|
||||
# customer version
|
||||
head -c 32 /dev/zero | to_hex
|
||||
|
||||
# kernel length
|
||||
printf '%08x\n' "$kernel_len"
|
||||
|
||||
# rootfs length
|
||||
printf '%08x\n' "$padded_rootfs_len"
|
||||
|
||||
# romfile length (0)
|
||||
printf '00000000\n'
|
||||
|
||||
# "model" (32 bytes of zeros)
|
||||
head -c 32 /dev/zero | to_hex
|
||||
|
||||
# Load address (CONFIG_ZBOOT_LOAD_ADDRESS)
|
||||
printf '80020000\n'
|
||||
|
||||
# "reserved" 128 bytes of zeros
|
||||
head -c 128 /dev/zero | to_hex
|
||||
}
|
||||
|
||||
tclinux_trx_hdr | from_hex
|
||||
cat "$kernel"
|
||||
padding
|
||||
cat "$rootfs"
|
||||
Loading…
Add table
Reference in a new issue