Since the upgrade instuctions from QNAP are incomplete I’ll try to make a complete overview of the steps here.

I used this KB Article from QNAP as base, but there are some quirks.

Preparations

First we need to get the firmware update itself stored somewhere. So find the upgrade you want to install on the QNAP download page and store it on the nas somewhere. I did over SSH since I like using cli:

[~] # cd /share/MD0_DATA
[/share/MD0_DATA] # wget https://eu1.qnap.com/Storage/TS-809U-RP/TS-809U_20200821-4.2.6.zip
--2021-03-07 14:59:23--  https://eu1.qnap.com/Storage/TS-809U-RP/TS-809U_20200821-4.2.6.zip
Resolving eu1.qnap.com (eu1.qnap.com)... 80.74.156.130
Connecting to eu1.qnap.com (eu1.qnap.com)|80.74.156.130|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 171236919 (163M) [application/zip]
Saving to: ‘TS-809U_20200821-4.2.6.zip’

TS-809U_20200821-4.2.6.zip                         100%[==================================================================================================================>] 163.30M  6.94MB/s   in 30s

2021-03-07 14:59:53 (5.42 MB/s) - ‘TS-809U_20200821-4.2.6.zip’ saved [171236919/171236919]
[/share/MD0_DATA] #

Next we need to extract the update:

[/share/MD0_DATA] # unzip TS-809U_20200821-4.2.6.zip
 Archive:  TS-809U_20200821-4.2.6.zip
   inflating: TS-809U_20200821-4.2.6.img
[/share/MD0_DATA] #

Now that the upgrade file is prepared, we need some preparations on the system. We need a temporary folder where the update is stored, and a symlink for the system to use during the update:

[/share/MD0_DATA] #  mkdir /mnt/HDA_ROOT/update
[/share/MD0_DATA] #  ln -sf /mnt/HDA_ROOT/update /mnt/update
[/share/MD0_DATA] #  

Start the update process

With all this out of the way we can start the real update:

[/share/MD0_DATA] # /etc/init.d/update.sh /share/MD0_DATA/TS-809U_20200821-4.2.6.img
 cksum=2916634212
 Check RAM space available for FW update: OK.
 Using 120-bit encryption - (QNAPNASVERSION4)
 len=1048576
 model name = TS-809U
 version = 4.2.6
 boot/
 bzImage
 bzImage.cksum
 config/
 fw_info
 initrd.boot
 initrd.boot.cksum
 libcrypto.so.1.0.0
 libssl.so.1.0.0
 qpkg.tar
 qpkg.tar.cksum
 rootfs2.bz
 rootfs2.bz.cksum
 rootfs_ext.tgz
 rootfs_ext.tgz.cksum
 update/
 update_img.sh
 4.2.6 20200821
 OLD MODEL NAME = TS-809U
 Allow upgrade
 Allow upgrade
 /mnt/HDA_ROOT/update
 1+0 records in
 1+0 records out
 tune2fs 1.41.4 (27-Jan-2009)
 Setting maximal mount count to -1
 Setting interval between checks to 0 seconds
 Update image using HDD …
 bzImage cksum … Pass
 initrd.boot cksum … Pass
 rootfs2.bz cksum … Pass
 rootfs_ext.tgz cksum … Pass
 rootfs_ext.tgz cksum … Pass
 qpkg.tar cksum … Pass
 Update RFS1…
 mke2fs 1.41.4 (27-Jan-2009)
 Filesystem label=QTS_BOOT_PART2
 OS type: Linux
 Block size=1024 (log=0)
 Fragment size=1024 (log=0)
 13832 inodes, 55296 blocks
 0 blocks (0.00%) reserved for the super user
 First data block=1
 Maximum filesystem blocks=56623104
 7 block groups
 8192 blocks per group, 8192 fragments per group
 1976 inodes per group
 Superblock backups stored on blocks:
         8193, 24577, 40961
 Writing inode tables: done
 Writing superblocks and filesystem accounting information: done
 This filesystem will be automatically checked every 24 mounts or
 180 days, whichever comes first.  Use tune2fs -c or -i to override.
 Checking bzImage … ok
 Checking initrd.boot … ok
 Checking rootfs2.bz … ok
 Checking rootfs_ext.tgz … ok
 Update RFS2…
 mke2fs 1.41.4 (27-Jan-2009)
 Filesystem label=QTS_BOOT_PART3
 OS type: Linux
 Block size=1024 (log=0)
 Fragment size=1024 (log=0)
 13832 inodes, 55296 blocks
 0 blocks (0.00%) reserved for the super user
 First data block=1
 Maximum filesystem blocks=56623104
 7 block groups
 8192 blocks per group, 8192 fragments per group
 1976 inodes per group
 Superblock backups stored on blocks:
         8193, 24577, 40961
 Writing inode tables: done
 Writing superblocks and filesystem accounting information: done
 This filesystem will be automatically checked every 24 mounts or
 180 days, whichever comes first.  Use tune2fs -c or -i to override.
 1+0 records in
 1+0 records out
 Update Finished.
 Make a Backup
 /share/MD0_DATA
 qpkg.tar cksum … Pass
 set cksum [2916634212]
[/share/MD0_DATA] # reboot
[/share/MD0_DATA] 

The system will reboot and after the boot your QNAP should be up and running on the new firmware.

Issues

/mnt/update: Cannot chdir: No such file or directory

At some point during the update I got the following error:

/share/MD0_DATA] # /etc/init.d/update.sh /share/MD0_DATA/TS-809U_20200821-4.2.6.img
[...]
 /bin/tar: /mnt/update: Cannot chdir: No such file or directory
 /bin/tar: Error is not recoverable: exiting now
 [Firmware Update] System update failed. Firmware failed to extract. Error code: FW006
 [/share/MD0_DATA] #

That meant the folder /mnt/HDA_ROOT/update did not exist. A simple mkdir /mnt/HDA_ROOT/update resolved this issue.

Error code: FW004

At some point I run into a “Firmware file format error”:

[/share/MD0_DATA] # /etc/init.d/update.sh /share/MD0_DATA/TS-809U_20190322-4.2.6.zip
cksum=3061299578
Check RAM space available for FW update: OK.
Using 120-bit encryption - (QNAPNASVERSION4)
sig: ,▒"
▒ icpnas
[Firmware Update] System update failed. Firmware file format error. Error code: FW004
[/share/MD0_DATA] #

This meant I did not extract the zip file before applying the update. The update.sh command expects an .img file, not a .zip.

I was messing around with adblock on my OpenWRT router. While trying to get it to work I got the following error:
sha256sum: not found

After a bit of digging around, I found that the sha256sum binary is in the coreutils-sha256sum package.
So installing on OpenWRT over SSH goes like this:
opkg install coreutils-sha256sum

BIOS - ChipI tried to do a BIOS update from Windows. Flashing finished without an error so I decided to reboot. The tablet shut down and… never turned on again. Nothing of what I tried had any effect, the tablet remained dead. Not A sign of life. So I decided the BIOS flash must have gone wrong. What now?

After some research I found that there were more people with the same problem, and some seemed to have successfully flashed their BIOS again. So I decided to give it a try.

First of all I needed some hardware. I searched online for a BIOS programmer, and found a cheap CH314A programmer that should do the job. It had TTL and 3.3V levels, I knew that the BIOS chip was 3.3V so it should work without frying my BIOS chip.

Next step was to find a way to program the chip without soldering. I knew that the chip was in SOP8 package, so I searched a test adapter for a SOP8 chip, and ordered one.

After about a week the hardware was in, and I could get to work. I found the correct BIOS and found a bin file in the download. Then I installed flashrom and connected all the hardware together.
BIOS - Tablet and laptop BIOS - Adapter

First I made a backup of the current rom using flashrom:
flashrom -p ch341a_spi --read backup.bin

After the backup it was time to flash:
Screenshot from flashrom

After this, I disconnected the test adapter, disconnected the battery, reconnected the battery and tried to boot. And with success, the tablet booted straight up to Windows!

I upgraded my Raspberry Pi to a newer kernel and updated the firmware with the following commands:

sudo apt-get update && sudo apt-get upgrade
sudo rpi-update
sudo reboot

After this my pilight couldn’t send anymore using the lirc_rpi module. Al lot of resources mentioned a new device tree and stuff, so I added the following to my /boot/config.txt file:

# Uncomment this to enable the lirc-rpi module
dtoverlay=lirc-rpi,gpio_out_pin=22,gpio_in_pin=18

This caused the lirc_rpi module to be loaded and I could receive data using the pilight-raw command. But sending still wouldn’t work.

After lots of time and effort I found the culprit. The new module seems to have enable softcarrier by default. Also autosensing didn’t work always as intended. So I changed the lines in my /boot/config.txt to the following:

# Uncomment this to enable the lirc-rpi module
dtoverlay=lirc-rpi,gpio_out_pin=22,gpio_in_pin=18,sense=0,softcarrier=off

Now everything works as expected!

Please let me know if this helped you to solve your problem.

iodineI’ve had some troubles getting Iodine-server to work under CentOS 7. So iv’e decided to write an article how I’ve managed to get it to work.

This instruction is based on a setup using iptables instead of firewalld, because I run iptables on all my servers since forever.

DNS setup

For iodine to work there are two records required. An A-record and an NS record. I’ve used the same naming as the iodine documentation, to keep it as simple as possible.
First add an A-record with the name t1ns that points to the ip of your server that will run the iodine server. The ip used here for the example should be replaced by your ip.
A: t1ns.<<yourdomain>> → 374.263.291.194

Then add an NS record with the name t1 that points to the A-record you’ve just made;
NS: t1.<<youdomain>> → t1ns.<<yourdomain>>

That’s all there is required for iodine to work with your domain.

Installing iodine

Firstly, make sure the EPEL repository is installed:
yum -y install epel-release

Then install iodine-server:
yum -y install iodine-server

Next is configuring iodine by editing /etc/sysconfig/iodine-server.
Make sure the line that starts with OPTIONS look something like this:
OPTIONS="-f -c -P <<yourpassword>> 10.1.1.1 t1.<<yourdomain>>"
Replace <<yourpassword>> with the password you wish to use, and <<yourdomain>> with the domain you are using for iodine.

Then, start iodine-server and enable it at boot:
systemctl start iodine-server
systemctl enable iodine-server

Configure traffic routing

Allow DNS and NAT traffic trough iptables:
iptables -t nat -A POSTROUTING -s 10.1.1.0/24 -o eth0 -j MASQUERADE
iptables -t filter -A INPUT -p udp -m multiport --dports 53 -j ACCEPT
iptables -t filter -A INPUT -i dns0 -j ACCEPT
iptables -t filter -A OUTPUT -o dns0 -j ACCEPT
iptables -t -A OUTPUT -p udp -m multiport --dports 53 -j ACCEPT
iptables -t filter -A FORWARD -i dns0 -o eth0 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
iptables -t filter -A FORWARD -i eth0 -o dns0 -m state --state RELATED,ESTABLISHED -j ACCEPT

And save the new ruleset:
iptables-save > /etc/sysconfig/iptables

Next, allow ipv4 packet forwarding and restart the network service to apply this change:
echo "net.ipv4.ip_forward = 1" > /etc/sysctl.d/ip_forward.conf
systemctl restart network

Conclusion

That’s it. You should be able to connect with iodine to your server by using the address t1.<<yourdomain>>.

An Android client that seems to work pretty good and I use is AndIodine, and is available via the F-Droid catalogue.

Please leave a comment if this post was helpfull in any way.