firmware-utils/tplink-safeloader: add compat level
authorSander Vanheule <sander@svanheule.net>
Sat, 11 Jul 2020 21:06:54 +0000 (23:06 +0200)
committerStijn Tintel <stijn@linux-ipv6.be>
Wed, 9 Sep 2020 17:41:50 +0000 (20:41 +0300)
commit7c07e1634ed4a07ba5c3024d60e65e56ce3f0e18
tree4a5b5d42a573b082ca070c5ab79e7947d0ef687f
parentd583cca9e201f9b62baded2d1b8e75a60109159d
firmware-utils/tplink-safeloader: add compat level

TP-Link has introduced a compatibility level to prevent certain
downgrades. This information is stored in the soft-version partition,
changing the data length from 0xc to 0x10.

The compatibility level doesn't change frequently. For example, it has
the following values for the EAP245v3 (released 2018-Q4):
* FW v2.2.0  (2019-05-30): compat_level=0
* FW v2.3.0  (2019-07-31): compat_level=0
* FW v2.3.1  (2019-10-29): compat_level=1
* FW v2.20.0 (2020-04-23): compat_level=1

Empty flash values (0xffffffff) are interpreted as compat_level=0.
If a firmware upgrade file has a soft-version block without
compatibility level (data length < 0x10), this is also interpreted as
compat_level=0.

By including a high enough compatibility level in factory images, stock
firmware can be convinced to accept the image. A compatibility level
aware firmware will keep the original value.

Example upgrade log of TP-Link EAP245v3 FWv2.3.0 to FWv2.20.0:
    [NM_Debug](nm_fwup_verifyFwupFile) 02073: curSoftVer:2.3.0 Build
        20190731 Rel. 51932,newSoftVer:2.20.0 Build 20200423 Rel. 36779
    ...
    AddiHardwareVer check: NEW(0x1) >= CUR(0x0), Success.
    ...
    [NM_NOTICE](updateDataToNvram) 00575: Restore old additionalHardVer:
    0x0.(new 0x1)
    [NM_NOTICE](updateDataToNvram) 00607: PTN 07: name = soft-version,
        base = 0x00092000, size = 0x00000100 Bytes, upDataType = 1,
        upDataStart = 7690604b, upDataLen = 00000018
    [NM_Debug](updateDataToNvram) 00738: PTN 07: write bytes = 000002eb

Other firmware upgrades have been observed to modify the compabitility
stored level (e.g. TP-Link EAP225-Outdoor FWv1.4.1 to FWv1.7.0).
Therefore, it seems to be the safest option to set the OpenWrt
compatibility level to the highest known value instead of the highest
possible value (0xfffffffe), to ensure users do not get unexpectedly
refused firmware upgrades when using a device reverted back to stock.

To remain compatible with existing devices and not produce different
images, the image builder doesn't store a compatibility level if it is
zero.

Signed-off-by: Sander Vanheule <sander@svanheule.net>
src/tplink-safeloader.c