Linkplay/boot-process.md
Jan Wachsmuth ce87bf23f0
updates
2024-01-14 22:13:22 +01:00

16 KiB

Reverse Engineering of boot process

Connect Pins from A31 module board to USB-to-Serial Board (FT232R) - Pin 24 RX, 25 TX, 28 GND

Output with 57600 (after boot up)

AXX+MUT+001
AXX+BOT+DON
AXX+BOT+UP0
AXX+MUT+000
AXX+MIC+000
AXX+MCU+RDY
AXX+GET+RTC
AXX+VOL+GET
AXX+CHN+GET
AXX+MCU+VER
AXX+PLM+GET
AXX+ETH+001
AXX+WWW+001
AXX+STA+002
AXX+STA+001
AXX+WWW+001
AXX+WWW+001
AXX+SET+RTC20201227223359&
AXX+SET+WEK0&
AXX+NXT+ALS-1&

--> This is the communication between the WiFi module and the MCU

Installing tools

Guide to Mediatek development board LinkIt Smart 7688 that has the same SoC: https://docs.labs.mediatek.com/resource/linkit-smart-7688/en/tutorials/firmware-and-bootloader/bootloader-and-kernel-console

The Bootloader console and Linux kernel console are configured to serial port UART2 (P8/UART_TXD2 and P9/UART_RXD2) at a baud rate of 57600.

--> This is specific for the Mediatek development board, but not the Linkplay A31 module!

Tools were also available from https://docs.labs.mediatek.com/resource/linkit-smart-7688/en/downloads

Note: The links listed above seem not to work anymore and are redirected to a Chinese web site.

I was able to download a firmware image (lks7688.img) version 0.9.4 and extract a binary of "busybox" with binwalk. You may download the binary from here or use a similar version from the Open WRT archive, see below.

Note: The busybox tool from the A31 module is a reduced version that does not contain many tools, not even a telnetd anymore!

Binary files are available from Open WRT archive, (Chaos Calmer) v15.05 and v15.05.1: https://archive.openwrt.org/chaos_calmer/15.05/ramips/mt7628/packages/base/ and https://archive.openwrt.org/chaos_calmer/15.05.1/ramips/mt7628/packages/

Here's an example how to download a package from the Open WRT archive and get the binaries from it to show the environment. The commands were executed from a terminal window on my MacBook:

cd ~/Downloads
curl 'https://archive.openwrt.org/chaos_calmer/15.05.1/ramips/mt7628/packages/base/uboot-envtools_2014.10-2_ramips_24kec.ipk' -o uboot-envtools_2014.10-2_ramips_24kec.ipk
mkdir uboot-envtools_2014.10-2_ramips_24kec
cd uboot-envtools_2014.10-2_ramips_24kec
tar zxpvf ../uboot-envtools_2014.10-2_ramips_24kec.ipk
tar zxpvf control.tar.gz
tar zxpvf data.tar.gz
# copy dropbear binary to a subdirectory on your webserver
cp usr/sbin/fw_printenv /Library/WebServer/Documents/a31/
# you may open finder to search for additional information in the package
open .

In the next step you can you can download and install the tool on the Up2Stream device (telnetd already installed):

cd /tmp
mkdir /tmp/bin
wget -O /tmp/bin/fw_printenv -T 5 'http://10.1.1.22/a31/fw_printenv'
chmod 777 /tmp/bin/fw_printenv
ln -s /tmp/bin/fw_printenv /tmp/bin/fw_setenv

and the same for dmesg:

cd ~/Downloads
curl 'https://archive.openwrt.org/chaos_calmer/15.05.1/ramips/mt7628/packages/base/dmesg_2.25.2-4_ramips_24kec.ipk' -o dmesg_2.25.2-4_ramips_24kec.ipk
mkdir dmesg_2.25.2-4_ramips_24kec
cd dmesg_2.25.2-4_ramips_24kec
tar zxpvf ../dmesg_2.25.2-4_ramips_24kec.ipk
tar zxpvf control.tar.gz
tar zxpvf data.tar.gz
cp ./usr/sbin/dmesg /Library/WebServer/Documents/a31

Installit on the Up2Stream device and dig for some useful information:

wget -O /tmp/dmesg -T 5 'http://10.1.1.22/a31/dmesg';/bin/chmod 777 /tmp/dmesg

cat /proc/version
Linux version 2.6.36+ (linkplay@linkplay-build-2) (gcc version 4.6.4 (Buildroot 2013.11) ) #1 Thu Feb 20 11:45:09 CST 2020

# cat /proc/mtd
dev:    size   erasesize  name
mtd0: 01000000 00010000 "ALL"
mtd1: 00030000 00010000 "Bootloader"
mtd2: 00010000 00010000 "Config"
mtd3: 00010000 00010000 "Factory"
mtd4: 00200000 00010000 "bkKernel"
mtd5: 001df508 00010000 "Kernel"
mtd6: 00950af8 00010000 "RootFS"
mtd7: 00b30000 00010000 "Kernel_RootFS"
mtd8: 00080000 00010000 "user"
mtd9: 00200000 00010000 "user2"
#

# dmesg
[    0.000000] Linux version 2.6.36+ (linkplay@linkplay-build-2) (gcc version 4.6.4 (Buildroot 2013.11) ) #1 Thu Feb 20 11:45:09 CST 2020
...
[    0.000000] Kernel command line: console=ttyS1,57600n8 root=/dev/mtdblock6
...
[    0.444000] flash manufacture id: ef, device id 40 18
[    0.456000] W25Q128BV(ef 40180000) (16384 Kbytes)
[    0.464000] mtd .name = raspi, .size = 0x01000000 (16M) .erasesize = 0x00010000 (64K) .numeraseregions = 0
[    0.484000] user1 00d80000 - 00e00000  size 00080000
[    0.492000] user2 00e00000 - 01000000  size 00200000
[    0.504000] Creating 10 MTD partitions on "raspi":
[    0.512000] 0x000000000000-0x000001000000 : "ALL"
[    0.524000] 0x000000000000-0x000000030000 : "Bootloader"
[    0.532000] ===========check_rootfs offset=42f4c8 i=64, ret=0  ==============
[    0.548000] name:Wiimu Rootfs
[    0.552000] ih_time:0x9e024e5e
[    0.560000] ih_magic:0x56190527
[    0.564000] ih_hcrc:0xb7e4affc
[    0.572000] ih_size:6569984 Bytes
[    0.580000] ih_dcrc:0x509122d0
[    0.584000] os=6, arch=5, type=7, comp=1
[    0.592000] ih_ksz:0x00000000


[    0.604000] 0x000000030000-0x000000040000 : "Config"
[    0.616000] 0x000000040000-0x000000050000 : "Factory"
[    0.624000] 0x000000050000-0x000000250000 : "bkKernel"
[    0.636000] 0x000000250000-0x00000042f508 : "Kernel"
[    0.648000] mtd: partition "Kernel" doesn't end on an erase block -- force read-only
[    0.664000] 0x00000042f508-0x000000d80000 : "RootFS"
[    0.672000] mtd: partition "RootFS" doesn't start on an erase block boundary -- force read-only
[    0.692000] 0x000000250000-0x000000d80000 : "Kernel_RootFS"
[    0.700000] 0x000000d80000-0x000000e00000 : "user"
[    0.712000] 0x000000e00000-0x000001000000 : "user2"
...

# cat -n /proc/kmsg
<5>[    0.000000] Linux version 2.6.36+ (linkplay@linkplay-build-2) (gcc version 4.6.4 (Buildroot 2013.11) ) #1 Mon Jun 22 15:40:26 CST 2020
<4>[    0.000000]
<4>[    0.000000]  The CPU feqenuce set to 575 MHz
<4>[    0.000000]
<4>[    0.000000]  MIPS CPU sleep mode enabled.
<6>[    0.000000] CPU revision is: 00019655 (MIPS 24Kc)
<6>[    0.000000] Software DMA cache coherency
<6>[    0.000000] Determined physical RAM map:
<6>[    0.000000]  memory: 04000000 @ 00000000 (usable)
<4>[    0.000000] Zone PFN ranges:
<4>[    0.000000]   Normal   0x00000000 -> 0x00004000
...
<6>[    0.284000] squashfs: version 4.0 (2009/01/31) Phillip Lougher
<6>[    0.296000] JFFS2 version 2.2 (NAND) (ZLIB) (RTIME) (c) 2001-2006 Red Hat, Inc.
<6>[    0.312000] fuse init (API version 7.15)
...
<4>[    0.444000] flash manufacture id: ef, device id 40 18
<4>[    0.456000] W25Q128BV(ef 40180000) (16384 Kbytes)
<4>[    0.464000] mtd .name = raspi, .size = 0x01000000 (16M) .erasesize = 0x00010000 (64K) .numeraseregions = 0
<4>[    0.484000] user1 00d80000 - 00e00000  size 00080000
<4>[    0.492000] user2 00e00000 - 01000000  size 00200000
<5>[    0.504000] Creating 10 MTD partitions on "raspi":
<5>[    0.512000] 0x000000000000-0x000001000000 : "ALL"
<5>[    0.524000] 0x000000000000-0x000000030000 : "Bootloader"
<4>[    0.532000] ===========check_rootfs offset=42f3be i=64, ret=0  ==============
<4>[    0.548000] name:Wiimu Rootfs
<4>[    0.552000] ih_time:0x7b62f05e
<4>[    0.560000] ih_magic:0x56190527
<4>[    0.564000] ih_hcrc:0xc82acb88
<4>[    0.572000] ih_size:6529024 Bytes
<4>[    0.580000] ih_dcrc:0x39e11b49
<4>[    0.584000] os=6, arch=5, type=7, comp=1
<4>[    0.592000] ih_ksz:0x00000000
<4>[    0.592000]
<4>[    0.592000]
<5>[    0.604000] 0x000000030000-0x000000040000 : "Config"
<5>[    0.616000] 0x000000040000-0x000000050000 : "Factory"
<5>[    0.624000] 0x000000050000-0x000000250000 : "bkKernel"
<5>[    0.636000] 0x000000250000-0x00000042f3fe : "Kernel"
<4>[    0.648000] mtd: partition "Kernel" doesn't end on an erase block -- force read-only
<5>[    0.664000] 0x00000042f3fe-0x000000d80000 : "RootFS"
<4>[    0.672000] mtd: partition "RootFS" doesn't start on an erase block boundary -- force read-only
<5>[    0.692000] 0x000000250000-0x000000d80000 : "Kernel_RootFS"
<5>[    0.700000] 0x000000d80000-0x000000e00000 : "user"
<5>[    0.712000] 0x000000e00000-0x000001000000 : "user2"
<4>[    0.724000] rdm_major = 253
<4>[    0.728000] GMAC1_MAC_ADRH -- : 0x00000022
<4>[    0.736000] GMAC1_MAC_ADRL -- : 0x6c25402b
<4>[    0.744000] Ralink APSoC Ethernet Driver Initilization. v3.1  256 rx/tx descriptors allocated, mtu = 1500!
<4>[    0.772000] get_rootfs_checked_flag = 1
<4>[    0.780000] this is not first bootup, ignore check rootfs
<4>[    0.788000] GMAC1_MAC_ADRH -- : 0x00000022
<4>[    0.796000] GMAC1_MAC_ADRL -- : 0x6c25402b
<1>[    0.804000] PROC INIT OK!
<4>[    0.816000]
...

Install dd from busybox and scp from dropbear package (see Enable Telnet section to install busybox and Hardware and Firmware section to install dropbear), then

# tools included in busybox just need a symbolic link with their name
ln -s /tmp/bin/busybox /tmp/bin/dd
## copy mtd1 to a file and save for future use
dd if=/dev/mtd1 of=/tmp/mtd1.img bs=512 count=128000 skip=0
scp -v -S /tmp/bin/dbclient /tmp/mtd1.img pi@10.1.1.40:mtd1.img
rm /tmp/mtd1.img

--> size 0x30000 = 196608 bytes. The command above tries to copy more data, so the whole mtd1 partition is copied. See cat /proc/mtd from above for details.

Create the file /etc/fw_env.config with the following content, e.g. with vi:

cat <<\EOF > /etc/fw_env.config 
# MTD device name       Device offset   Env. size       Flash sector size
/dev/mtd2 0x02000 0x4000 0x4000
EOF
mkdir /var/lock

Before setting the correct values for the size the following error is shown:

fw_printenv
Warning: Bad CRC, using default environment
bootcmd=bootp; setenv bootargs root=/dev/nfs nfsroot=${serverip}:${rootpath} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}::off; bootm
bootdelay=5
baudrate=115200

With the correct settings from above you get a list with all environment variables. These values are stored in NVRAM, so they will survive a reboot:

fw_printenv
WebInit=1
HostName=wiimu
OperationMode=3
Platform=MT7628
wanConnectionMode=DHCP
wan_ipaddr=192.168.1.1
wan_netmask=255.255.255.0
wan_gateway=192.168.1.254
wan_primary_dns=168.95.1.1
wan_secondary_dns=8.8.8.8
wan_l2tp_server=l2tp_server
wan_l2tp_mode=0
wan_l2tp_ip=192.168.1.1
wan_l2tp_netmask=255.255.255.0
wan_l2tp_gateway=192.168.1.254
wan_pptp_server=pptp_server
wan_pptp_mode=0
wan_pptp_ip=192.168.1.1
wan_pptp_netmask=255.255.255.0
wan_pptp_gateway=192.168.1.254
lan_ipaddr=10.10.10.254
lan_netmask=255.255.255.0
dhcpEnabled=1
dhcpStart=10.10.10.100
dhcpEnd=10.10.10.200
dhcpMask=255.255.255.0
dhcpPriDns=168.95.1.1
dhcpSecDns=8.8.8.8
dhcpGateway=10.10.10.254
dhcpLease=86400
stpEnabled=0
lltdEnabled=0
igmpEnabled=0
natEnabled=1
IPPortFilterEnable=0
PortForwardEnable=0
MacFilterEnable=0
DefaultFirewallPolicy=1
DMZEnable=0
CountryRegion=1
CountryRegionABand=7
CountryCode=DE
BssidNum=1
SSID1=SoundSystem_305D
WirelessMode=9
TxRate=0
Channel=11
BasicRate=15
BeaconPeriod=100
DtimPeriod=1
TxPower=100
DisableOLBC=0
BGProtection=0
TxPreamble=0
RTSThreshold=2347
FragThreshold=2346
TxBurst=1
PktAggregate=1
TurboRate=0
WmmCapable=1
APAifsn=3;7;1;1
APCwmin=4;4;3;2
APCwmax=6;10;4;3
APTxop=0;0;94;47
APACM=0;0;0;0
BSSAifsn=3;7;2;2
BSSCwmin=4;4;3;2
BSSCwmax=10;10;4;3
BSSTxop=0;0;94;47
BSSACM=0;0;0;0
AckPolicy=0;0;0;0
APSDCapable=0
DLSCapable=0
NoForwarding=0
NoForwardingBTNBSSID=0
HideSSID=0
ShortSlot=1
AutoChannelSelect=0
SecurityMode=0
VLANEnable=0
VLANID=0
VLANPriority=0
WscConfMode=0
WscConfStatus=2
WscAKMP=1
WscConfigured=0
WscModeOption=0
WscActionIndex=9
WscRegResult=1
WscUseUPnP=1
WscUseUFD=0
WscSSID=RalinkInitialAP
WscKeyMGMT=WPA-EAP
WscConfigMethod=138
WscAuthType=1
WscEncrypType=1
WscNewKey=scaptest
IEEE8021X=0
IEEE80211H=0
CSPeriod=6
PreAuth=0
AuthMode=WPAPSKWPA2PSK
EncrypType=AES
RekeyInterval=3600
RekeyMethod=DISABLE
PMKCachePeriod=10
WPAPSK1=Plattfisch
DefaultKeyID=1
Key1Type=0
Key2Type=0
Key3Type=0
Key4Type=0
HSCounter=0
HT_HTC=1
HT_RDG=0
HT_LinkAdapt=0
HT_OpMode=0
HT_MpduDensity=5
HT_EXTCHA=1
HT_BW=0
HT_AutoBA=1
HT_BADecline=0
HT_AMSDU=0
HT_BAWinSize=64
HT_GI=1
HT_STBC=1
HT_MCS=33
HT_PROTECT=1
HT_MIMOPS=3
HT_40MHZ_INTOLERANT=0
HT_TxStream=1
HT_RxStream=1
HT_DisallowTKIP=1
HT_BSSCoexistence=0
NintendoCapable=0
AccessPolicy0=0
AccessPolicy1=0
AccessPolicy2=0
AccessPolicy3=0
WdsEnable=0
WdsEncrypType=NONE
WirelessEvent=0
RADIUS_Port=1812
RADIUS_Acct_Port=1813
session_timeout_interval=0
idle_timeout_interval=0
RadioOn=1
Login=admin
Password=admin
WAN_MAC_ADDR=0:22:6C:14:30:60

CAP_STREAMS=fffffbfe
CAP_PLM=6
Private_PrjName=RP0011_WB60_S
wiimuLanguage=en_us
LangInit=1
PresetNumber=10
CAP_CAP1=305200
CAP_CAP2=28490a00
ALI_PRJ_ID=RAKOIT_MA1
MaxPromptVolume=50
upnp_manufacture=RAKOIT
upnp_manufacture_url=https://www.rakoit.com/
upnp_model_name=Up2Stream AMP
upnp_model_url=https://www.rakoit.com/
upnp_model_description=RAKOIT Wi-Fi Sound System
SPOTIFY_TYPE=1
SPOTIFY_NAME=RP0011_WB60_S
SPOTIFY_BRAND=RAKOIT
SPOTIFY_NAME_DISPLAY=SoundSystem
SPOTIFY_BRAND_DISPLAY=RAKOIT
SPOTIFY_PRODUCT_ID=0
CAP_MPTV=0
CAP_ALINK=0
SSID_CONFIRM=1
FIRST_BOOTUP=0
mvProductId=RP0011_WB60_S
mvHardwareVersion=WiiMu-A31
mv_uuid=FF31F09E2BE2384A4E6CF9BB
upnp_uuid=uuid:FF31F09E-2BE2-384A-4E6C-F9BBFF31F09E
rootfs_checked=1
TIME_ZONE=1.0
GroupName=Lab
DeviceName=Lab
part_ver_kernel=8827
silenceOTA=1
SoftEQ=1
EQ_Bass=2
EQ_Treble=1
Prompt=1
AudioCH=0
NTPValid=1
DefaultPassword=1
SSID_HIDE=2
TZ=CET-1CEST,M3.5.0,M10.5.0/3
WpsApCliSsid=
WpsApCliWPAPSK=506C61747466697363683235
WpsApCliAuthMode=WPA2PSK
WpsApCliEncrypType=AES
WpsApCliChannel=6
ApCliEnable=1
ApCliSsid=4D656C626F75726E65
ApCliWPAPSK=456C776F6F643230303521
ApCliAuthMode=WPA2PSK
ApCliEncrypType=AES
ApCliChannel=6

# a similar output will provide
ralink_init show 2860

It's even possible to get such an output from remote via build-in shell script (script is located in /etc_ro/web/cgi-bin):

curl 'http://10.1.1.52/cgi-bin/ExportSettings.sh'

To read a specific variable from NVRAM or modify its value use these commands:

nvram_get 2860 HostName
nvram_get 2860 lan_ipaddr
nvram_get 2860 lan_netmask
nvram_set 2860 HostName MyBoomBox
nvram_get old_firmware
# to delete a variable from NVRAM skip '2860' and the value, e.g.
nvram_set old_firmware
# Note: the variable is not really deleted, but set to ''

# displays password admin and sets a new one
nvram_get 2860 Password
nvram_set 2860 Password newpassword

The option '2860' is optional and may be skipped.

The commands to read and manipulate the NVRAM are located here:

cd /bin
ls l
...
-rwxrwxr-x    1 1000     1000        33220 ralink_init
lrwxrwxrwx    1 1000     1000           11 nvram_set -> ralink_init
lrwxrwxrwx    1 1000     1000           11 nvram_get -> ralink_init
-rwxrwxr-x    1 1000     1000         7800 nvram_daemon
...

I found a documentation for these commands (not matching 100%):

Usage:
a. get: nvram_get [<2860/rtdev>] <field>
b. set: nvram_set [<2860/rtdev>] <field>
c. init: ralink_init <command> [<platform>] [<file>]

<Commands>:
 rt2860_nvram_show    (display rt2860 values in nvram)
 rtdev_nvram_show     (display rtdev values in nvram)
 show                 (display values in nvram for <platform>)
 gen                  (generate config file from nvram for <platform> - does not work)
 renew                (replace nvram values for <platform> with <file>)
 clear                (??? clear all entries in nvram for - found in a different documentation)
<Platform>:
 2860 - rt2860 station or the first Wi-Fi interface
 rtdev - intelligent nic or the second Wi-Fi interface (not available for Linkplay A31)
<File>: File name for renew command

Example:
a. nvram_get 2860 SSID               /* get the SSID */
b. nvram_set 2860 SSID ralink        /* set the SSID to ralink */
c. ralink_init gen 2860              /* generate the RT2860 .dat file from NVRAM */
d. ralink_init show 2860             /* display the INIC configurations in NVRAM */
e. ralink_init renew 2860 ra.dat     /* set NVRAM values for RT2860 platform according to ra.dat file */
f. nvram_daemon &                    /* start the nvram_daemon */