aredn/patches/010-lz77-decompression-supp...

591 lines
16 KiB
Diff
Raw Normal View History

diff --git a/target/linux/generic/files/drivers/platform/mikrotik/Makefile b/target/linux/generic/files/drivers/platform/mikrotik/Makefile
index a232e1a9e8488..2e1ab3dcf44c0 100644
--- a/target/linux/generic/files/drivers/platform/mikrotik/Makefile
+++ b/target/linux/generic/files/drivers/platform/mikrotik/Makefile
@@ -1,4 +1,4 @@
#
# Makefile for MikroTik RouterBoard platform specific drivers
#
-obj-$(CONFIG_MIKROTIK_RB_SYSFS) += routerboot.o rb_hardconfig.o rb_softconfig.o
+obj-$(CONFIG_MIKROTIK_RB_SYSFS) += routerboot.o rb_hardconfig.o rb_softconfig.o rb_hardconfig_lz77.o
diff --git a/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig.c b/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig.c
index bd0469d5e8385..83ba74341c8f9 100644
--- a/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig.c
+++ b/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig.c
@@ -38,8 +38,9 @@
#include <linux/lzo.h>
#include "routerboot.h"
+#include "rb_hardconfig_lz77.h"
-#define RB_HARDCONFIG_VER "0.07"
+#define RB_HARDCONFIG_VER "0.08"
#define RB_HC_PR_PFX "[rb_hardconfig] "
/* ID values for hardware settings */
@@ -563,6 +564,63 @@ static int hc_wlan_data_unpack_lzor(const u16 tag_id, const u8 *inbuf, size_t in
return ret;
}
+static int hc_wlan_data_unpack_lz77(const u16 tag_id, const u8 *inbuf, size_t inlen,
+ void *outbuf, size_t *outlen)
+{
+ u16 rle_ofs, rle_len;
+ u8 *tempbuf;
+ size_t templen;
+ int ret;
+
+ /* Temporary buffer same size as the outbuf */
+ tempbuf = kmalloc(*outlen, GFP_KERNEL);
+ if (!tempbuf)
+ return -ENOMEM;
+
+ /* LZO-decompress lzo_len bytes of outbuf into the tempbuf */
+ ret = lz77_mikrotik_wlan_decompress(
+ (const unsigned char *)inbuf,
+ inlen,
+ (unsigned char *)tempbuf,
+ outlen);
+ if (ret < 0) {
+ pr_err(RB_HC_PR_PFX "LZ77: LZ77 decompress fail\n");
+ goto lz77_fail;
+ }
+ templen = ret;
+
+ pr_debug(RB_HC_PR_PFX "LZ77: decompressed from %zu to %d\n",
+ inlen, templen);
+
+ /* skip DRE magic */
+ tempbuf += 4;
+ templen -= 4;
+
+ /* Past magic. Look for tag node */
+ ret = routerboot_tag_find(tempbuf, templen, tag_id, &rle_ofs, &rle_len);
+ if (ret) {
+ pr_debug(RB_HC_PR_PFX "LZ77: no RLE data for id 0x%04x\n", tag_id);
+ goto lz77_fail;
+ }
+ pr_debug(RB_HC_PR_PFX "LZ77: found RLE data for id 0x%04x\n", tag_id);
+
+ if (rle_len > templen) {
+ pr_err(RB_HC_PR_PFX "LZ77: Invalid RLE data length\n");
+ ret = -EINVAL;
+ goto lz77_fail;
+ }
+
+ /* RLE-decode tempbuf back into the outbuf */
+ ret = routerboot_rle_decode(tempbuf+rle_ofs, rle_len, outbuf, outlen);
+ if (ret)
+ pr_debug(RB_HC_PR_PFX "LZ77: RLE decoding error (%d)\n", ret);
+
+lz77_fail:
+ kfree(tempbuf);
+ return ret;
+}
+
+
static int hc_wlan_data_unpack(const u16 tag_id, const size_t tofs, size_t tlen,
void *outbuf, size_t *outlen)
{
@@ -585,6 +643,13 @@ static int hc_wlan_data_unpack(const u16 tag_id, const size_t tofs, size_t tlen,
tlen -= sizeof(magic);
ret = hc_wlan_data_unpack_lzor(tag_id, lbuf, tlen, outbuf, outlen);
break;
+ case RB_MAGIC_LZ77:
+ /* Skip magic */
+ lbuf += sizeof(magic);
+ tlen -= sizeof(magic);
+ ret = hc_wlan_data_unpack_lz77(tag_id, lbuf, tlen, outbuf, outlen);
+ break;
+
case RB_MAGIC_ERD:
/* Skip magic */
lbuf += sizeof(magic);
diff --git a/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig_lz77.c b/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig_lz77.c
new file mode 100644
index 0000000000000..8e8b7a1689c87
--- /dev/null
+++ b/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig_lz77.c
Initial OpenWRT 23.05.0 merge (#963) * Initial OpenWRT 23.05.0 merge * Fix get_rfchannels for new iwinfo format * Fix initial wlan name * Move patches to 5.15 from 5.10 * Fix flash write problem on Ubiquiti devices * Use new ssl patch * Reduce binary sizes * Have to have hostapd installed now, even on tiny builds * Simplify device support * Revert Mikrotik NAND sysupgrade system. OpenWRT doesnt really support Mikrotik NAND devices after 2019 and the new support appeared broken. So reverted to the 2022 mechanism which does work and avoid upgrade problems. * Fixes for tiny builds * More tiny shrinking * Fix newly added firewall rules * Update permanent packages * Update permanent packages * Support for Nanobeam 2AC (2.4GHz) device. 20MHz channels only. * Update support * Add GL.iNet B1300 * Add to radios.json * Update supported devices * Dont force the LAN DHCP to run * Revert CURL SSL test * Fix radio count when there are no radios * Switch the lan ports on the gl-b1300 * Add support for GL.iNET Beryl MT1300 * Fix visual lat/lon setting bug * Make the setup "Save Changes" button also save the location data * Fix location/map system with geo location fallback * Recolor * Fix default bandwidth selection * Support multi-band radios * Generic mechanism to set compat version to 1.1 * Switch ethernet ports * 20 MHz channels only * Update docs * Add ham channels to Mediatek chips (20MHz only) * Automatically update the permpkg list when we upgrade * Fix 10MHz mode for Ubiquiti AC devices * Fix tiny builds * Bump the watch timeout for restarting olsrd olsrd is reliable these days, and very occasionally this was restarting it unnecessarily
2023-12-06 11:12:11 -07:00
@@ -0,0 +1,438 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023 John Thomson
+ */
+
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+
+#include "rb_hardconfig_lz77.h"
+
+#define RB_HC_PR_PFX_LZ77 "[rb_hardconfig][lz77] "
+
+
+/**
+ * lz77_mikrotik_wlan_get_bit
+ *
+ * @in: compressed data
+ * @in_offset_bit: bit offset to extract
+ */
+static unsigned int lz77_mikrotik_wlan_get_bit(
+ const unsigned char *in,
+ unsigned int in_offset_bit)
+{
+ return ((in[in_offset_bit>>3] >> (in_offset_bit & 7)) & 0x1);
+
+}
+
+
+/**
+ * lz77_mikrotik_wlan_get_byte
+ *
+ * @in: compressed data
+ * @in_offset_bit: bit offset to extract byte
+ */
+static unsigned char lz77_mikrotik_wlan_get_byte(
+ const unsigned char *in,
+ unsigned int in_offset_bit)
+{
+ unsigned char buf = 0;
+
+ /* built a byte from unaligned bits (reversed) */
+ int i; for (i = 0; i <= 7; ++i)
+ buf += ((in[(in_offset_bit+i)>>3] >> ((in_offset_bit+i) & 7)) & 0x1)<<(7-i);
+ return buf;
+}
+
+
+/**
+ * lz77_mikrotik_wlan_decode_count - decode bits at given offset as a count
+ *
+ * @in: compressed data
+ * @in_offset_bit: bit offset where count starts
+ * @shift: left shift operand value of first count bit
+ * @count: initial count
+ * @bits_used: how many bits were consumed by this count
+ * @size: maximum bit count for this counter
+ *
+ * Returns the decoded count
+ */
+static int lz77_mikrotik_wlan_decode_count(
+ const unsigned char *in,
+ unsigned int in_offset_bit,
+ unsigned int shift,
+ unsigned int count,
+ unsigned int *bits_used,
+ unsigned int size)
+{
+ unsigned int pos = in_offset_bit;
+ bool up = true;
+
+ size += pos;
+ *bits_used = 0;
+ pr_debug(RB_HC_PR_PFX_LZ77 "decode_count inbit: %i, start shift:%i, initial count:%i\n",
+ in_offset_bit, shift, count);
+
+ /* maybe could use find_first_zero_bit to skip count up,
+ * and extract for the count down,
+ * but would need to mask the bits from and to the byte align boundary
+ */
+
+ while (true) {
+ if (pos >= size) {
+ pr_err(RB_HC_PR_PFX_LZ77 "max bit index reached before count completed\n");
+ return -1;
+ }
+
+ /* if the bit value at offset is set */
+ if (lz77_mikrotik_wlan_get_bit(in, pos)) {
+ count += (1 << shift);
+
+ /* shift increases until we find an unsed bit */
+ } else if (up) {
+ up = false;
+ }
+
+ if (up) {
+ ++shift;
+ } else {
+ if (!shift) {
+ *bits_used = pos - in_offset_bit + 1;
+ return count;
+ }
+ --shift;
+ }
+
+ ++pos;
+ }
+
+ return -1;
+}
+
+enum lz77_mikrotik_instruction {
+ INSTR_ERROR = -1,
+ INSTR_LITERAL_BYTE = 0,
+ /* a (non aligned) byte follows this instruction,
+ * which is directly copied into output
+ */
+ INSTR_PREVIOUS_OFFSET = 1,
+ /* this group is a match, with a bytes length defined by
+ * following counter bits, starting at bitshift 0,
+ * less the built-in count of 1
+ * using the previous offset as source
+ */
+ INSTR_LONG = 2
+ /* this group has two counters,
+ * the first counter starts at bitshift 4,
+ * if this counter == 0, this is a non-matching group
+ * the second counter (bytes length) starts at bitshift 4,
+ * less the built-in count of 11+1.
+ * The final match group has this count 0,
+ * and (at least 1) 0 bits pad to byte-align
+ *
+ * if this counter > 0, this is a matching group
+ * this first count is the match offset (in bytes)
+ * the second count is the match length (in bytes),
+ * less the built-in count of 2
+ * these groups can source bytes that are part of this group
+ */
+};
+
+/**
+ * lz77_mikrotik_wlan_decode_instruction
+ *
+ * @in: compressed data
+ * @in_offset_bit: bit offset where instruction starts
+ * @bits_used: how many bits were consumed by this count
+ *
+ * Returns the decoded instruction
+ */
+static enum lz77_mikrotik_instruction lz77_mikrotik_wlan_decode_instruction(
+ const unsigned char *in,
+ unsigned int in_offset_bit,
+ unsigned int *bits_used)
+{
+ if (lz77_mikrotik_wlan_get_bit(in, in_offset_bit)) {
+ *bits_used = 2;
+ if (lz77_mikrotik_wlan_get_bit(in, ++in_offset_bit)) {
+ return INSTR_LONG;
+ } else {
+ return INSTR_PREVIOUS_OFFSET;
+ }
+ } else {
+ *bits_used = 1;
+ return INSTR_LITERAL_BYTE;
+ }
+ return INSTR_ERROR;
+}
+
+struct lz77_mk_instr_opcodes {
+ /* group instruction */
+ enum lz77_mikrotik_instruction instruction;
+ /* if >0, a match group,
+ * which starts at byte output_position - 1*offset
+ */
+ unsigned int offset;
+ /* how long the match group is,
+ * or how long the (following counter) non-match group is
+ */
+ unsigned int length;
+ /* how many bits were used for this instruction + op code(s) */
+ unsigned int bits_used;
+ /* input char */
+ unsigned char *in;
+ /* offset where this instruction started */
+ unsigned int in_pos;
+};
+
+/**
+ * lz77_mikrotik_wlan_decode_instruction_operators
+ *
+ * @in: compressed data
+ * @in_offset_bit: bit offset where instruction starts
+ * @previous_offset: last used match offset
+ * @opcode: struct to hold instruction & operators
+ *
+ * Returns error code
+ */
+
+
+static int lz77_mikrotik_wlan_decode_instruction_operators(
+ const unsigned char *in,
+ unsigned int in_offset_bit,
+ unsigned int previous_offset,
+ struct lz77_mk_instr_opcodes *opcode)
+{
+ enum lz77_mikrotik_instruction instruction;
+ unsigned int bit_count = 0;
+ unsigned int bits_used = 0;
+ int offset = 0;
+ int length = 0;
+
+ instruction = lz77_mikrotik_wlan_decode_instruction(
+ in, in_offset_bit, &bit_count);
+
+ /* skip bits used by instruction */
+ bits_used += bit_count;
+
+ switch (instruction) {
+ case INSTR_LITERAL_BYTE:
+ /* non-matching char */
+ offset = 0;
+ length = 1;
+ break;
+
+ case INSTR_PREVIOUS_OFFSET:
+ /* matching group uses previous offset */
+ offset = previous_offset;
+
+ length = lz77_mikrotik_wlan_decode_count(
+ in,
+ in_offset_bit + bits_used,
+ 0, 1, &bit_count,
+ LZ77_MK_MAX_COUNT_BIT_LEN);
+ if (length < 0)
+ return -1;
+ /* skip bits used by count */
+ bits_used += bit_count;
+ break;
+
+ case INSTR_LONG:
+ offset = lz77_mikrotik_wlan_decode_count(
+ in,
+ in_offset_bit + bits_used,
+ 4, 0, &bit_count,
+ LZ77_MK_MAX_COUNT_BIT_LEN);
+ if (offset < 0)
+ return -1;
+
+ /* skip bits used by offset count */
+ bits_used += bit_count;
+
+ if (offset == 0) {
+ /* non-matching long group */
+ length = lz77_mikrotik_wlan_decode_count(
+ in,
+ in_offset_bit + bits_used,
+ 4, 12, &bit_count,
+ LZ77_MK_MAX_COUNT_BIT_LEN);
+ if (length < 0)
+ return -1;
+ /* skip bits used by length count */
+ bits_used += bit_count;
+ } else {
+ /* matching group */
+ length = lz77_mikrotik_wlan_decode_count(
+ in,
+ in_offset_bit + bits_used,
+ 0, 2, &bit_count,
+ LZ77_MK_MAX_COUNT_BIT_LEN);
+ if (length < 0)
+ return -1;
+ /* skip bits used by length count */
+ bits_used += bit_count;
+ }
+
+ break;
+
+ case INSTR_ERROR:
+ return -1;
+ }
+
+ opcode->instruction = instruction;
+ opcode->offset = offset;
+ opcode->length = length;
+ opcode->bits_used = bits_used;
+ opcode->in = (unsigned char *) in;
+ opcode->in_pos = in_offset_bit;
+ return 0;
+}
+
+/**
+ * lz77_mikrotik_wlan_decompress
+ *
+ * @in: compressed data ptr
+ * @in_len: length of compressed data
+ * @out: buffer ptr to decompress into
+ * @out_len: length of decompressed buffer
+ *
+ * Returns length of decompressed data
+ */
+int lz77_mikrotik_wlan_decompress(
+ const unsigned char *in,
+ size_t in_len,
+ unsigned char *out,
+ size_t *out_len)
+{
+ unsigned char *output_ptr;
+ unsigned int input_bit = 0;
+ unsigned char * const output_end = out + *out_len;
+ struct lz77_mk_instr_opcodes *opcode;
+ unsigned int match_offset = 0;
+ int rc = 0;
+ unsigned int match_length, partial_count;
+
+ output_ptr = out;
+
+ if (in_len > LZ77_MK_MAX_ENCODED ||
+ (in_len * 8) > UINT_MAX) {
+ pr_err(RB_HC_PR_PFX_LZ77 "input longer than expected\n");
+ return -1;
+ }
+
+ opcode = kmalloc(sizeof(struct lz77_mk_instr_opcodes), GFP_KERNEL);
+ if (!opcode)
+ return -ENOMEM;
+
+ while (true) {
+ if (output_ptr > output_end) {
+ pr_err(RB_HC_PR_PFX_LZ77 "output overrun\n");
+ goto free_lz77_struct;
+ }
+ if (input_bit > in_len*8) {
+ pr_err(RB_HC_PR_PFX_LZ77 "input overrun\n");
+ goto free_lz77_struct;
+ }
+
+ rc = lz77_mikrotik_wlan_decode_instruction_operators(
+ in, input_bit, match_offset, opcode);
+ if (rc < 0) {
+ pr_err(RB_HC_PR_PFX_LZ77 "instruction operands decode error\n");
+ goto free_lz77_struct;
+ }
+
+ pr_debug(RB_HC_PR_PFX_LZ77 "inbit:0x%x->outbyte:0x%x",
+ input_bit, output_ptr - out);
+
+ input_bit += opcode->bits_used;
+ switch (opcode->instruction) {
+ case INSTR_LITERAL_BYTE:
+ pr_debug(" short");
+ fallthrough;
+ case INSTR_LONG:
+ if (opcode->offset == 0) {
Initial OpenWRT 23.05.0 merge (#963) * Initial OpenWRT 23.05.0 merge * Fix get_rfchannels for new iwinfo format * Fix initial wlan name * Move patches to 5.15 from 5.10 * Fix flash write problem on Ubiquiti devices * Use new ssl patch * Reduce binary sizes * Have to have hostapd installed now, even on tiny builds * Simplify device support * Revert Mikrotik NAND sysupgrade system. OpenWRT doesnt really support Mikrotik NAND devices after 2019 and the new support appeared broken. So reverted to the 2022 mechanism which does work and avoid upgrade problems. * Fixes for tiny builds * More tiny shrinking * Fix newly added firewall rules * Update permanent packages * Update permanent packages * Support for Nanobeam 2AC (2.4GHz) device. 20MHz channels only. * Update support * Add GL.iNet B1300 * Add to radios.json * Update supported devices * Dont force the LAN DHCP to run * Revert CURL SSL test * Fix radio count when there are no radios * Switch the lan ports on the gl-b1300 * Add support for GL.iNET Beryl MT1300 * Fix visual lat/lon setting bug * Make the setup "Save Changes" button also save the location data * Fix location/map system with geo location fallback * Recolor * Fix default bandwidth selection * Support multi-band radios * Generic mechanism to set compat version to 1.1 * Switch ethernet ports * 20 MHz channels only * Update docs * Add ham channels to Mediatek chips (20MHz only) * Automatically update the permpkg list when we upgrade * Fix 10MHz mode for Ubiquiti AC devices * Fix tiny builds * Bump the watch timeout for restarting olsrd olsrd is reliable these days, and very occasionally this was restarting it unnecessarily
2023-12-06 11:12:11 -07:00
+ unsigned int i;
+ /* this is a non-matching group */
+ pr_debug(" non-match, len: 0x%x\n",
+ opcode->length);
+ /* test end marker */
+ if (opcode->length == 0xc &&
+ ((input_bit + opcode->length*8) > in_len))
+ {
+
+ if (!(*(unsigned int *)out == LZ77_MK_EXPECTED_OUT)) {
+ pr_debug(RB_HC_PR_PFX_LZ77 "lz77 decompressed from %zu to %d\n",
+ in_len, output_ptr - out);
+ return (unsigned int)(output_ptr - out);
+ } else {
+ pr_err(RB_HC_PR_PFX_LZ77 "lz77 decompressed: unexpected output\n");
+ return -1;
+ }
+ }
+
Initial OpenWRT 23.05.0 merge (#963) * Initial OpenWRT 23.05.0 merge * Fix get_rfchannels for new iwinfo format * Fix initial wlan name * Move patches to 5.15 from 5.10 * Fix flash write problem on Ubiquiti devices * Use new ssl patch * Reduce binary sizes * Have to have hostapd installed now, even on tiny builds * Simplify device support * Revert Mikrotik NAND sysupgrade system. OpenWRT doesnt really support Mikrotik NAND devices after 2019 and the new support appeared broken. So reverted to the 2022 mechanism which does work and avoid upgrade problems. * Fixes for tiny builds * More tiny shrinking * Fix newly added firewall rules * Update permanent packages * Update permanent packages * Support for Nanobeam 2AC (2.4GHz) device. 20MHz channels only. * Update support * Add GL.iNet B1300 * Add to radios.json * Update supported devices * Dont force the LAN DHCP to run * Revert CURL SSL test * Fix radio count when there are no radios * Switch the lan ports on the gl-b1300 * Add support for GL.iNET Beryl MT1300 * Fix visual lat/lon setting bug * Make the setup "Save Changes" button also save the location data * Fix location/map system with geo location fallback * Recolor * Fix default bandwidth selection * Support multi-band radios * Generic mechanism to set compat version to 1.1 * Switch ethernet ports * 20 MHz channels only * Update docs * Add ham channels to Mediatek chips (20MHz only) * Automatically update the permpkg list when we upgrade * Fix 10MHz mode for Ubiquiti AC devices * Fix tiny builds * Bump the watch timeout for restarting olsrd olsrd is reliable these days, and very occasionally this was restarting it unnecessarily
2023-12-06 11:12:11 -07:00
+ for (i = opcode->length; i > 0; --i) {
+ *output_ptr = lz77_mikrotik_wlan_get_byte(in, input_bit);
+ ++output_ptr;
+ input_bit += 8;
+ }
+ break;
+ }
+ match_offset = opcode->offset;
+ fallthrough;
+ case INSTR_PREVIOUS_OFFSET:
+ match_length = opcode->length;
+ partial_count = 0;
+
+ pr_debug(" match, offset: 0x%x, len: 0x%x",
+ opcode->offset, match_length);
+
+ if (opcode->offset == 0) {
+ pr_err(RB_HC_PR_PFX_LZ77 "match group missing opcode->offset\n");
+ goto free_lz77_struct;
+ }
+
+ /* overflow */
+ if ((output_ptr + match_length) > output_end) {
+ pr_err(RB_HC_PR_PFX_LZ77 "match group output overflow\n");
+ goto free_lz77_struct;
+ }
+
+ /* underflow */
+ if ((output_ptr - opcode->offset) < out) {
+ pr_err(RB_HC_PR_PFX_LZ77 "match group offset underflow\n");
+ goto free_lz77_struct;
+ }
+
+ while (opcode->offset < match_length) {
+ ++partial_count;
+ memcpy(output_ptr,
+ output_ptr - opcode->offset,
+ opcode->offset);
+ output_ptr += opcode->offset;
+ match_length -= opcode->offset;
+ }
+ memcpy(output_ptr,
+ output_ptr - opcode->offset,
+ match_length);
+ output_ptr += match_length;
+ if (partial_count) {
+ pr_debug(" (%d partial memcpy)\n", partial_count);
+ } else {
+ pr_debug("\n");
+ }
+
+ break;
+
+ case INSTR_ERROR:
+ return -1;
+ }
+ }
+
+ pr_err(RB_HC_PR_PFX_LZ77 "decode loop broken\n");
+
+free_lz77_struct:
+ kfree(opcode);
+
+ return -1;
+}
diff --git a/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig_lz77.h b/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig_lz77.h
new file mode 100644
index 0000000000000..50d19f54b3618
--- /dev/null
+++ b/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig_lz77.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2023 John Thomson
+ */
+
+#include <linux/errno.h>
+
+#define LZ77_MK_MAX_ENCODED 0x1000
+#define LZ77_MK_MAX_DECODED 0x40000
+
+/* examples have all decompressed to start with DRE\x00 */
+#define LZ77_MK_EXPECTED_OUT 0x44524500
+
+/* the look behind window
+ * unknown, for long instruction match offsets up to
+ * 6449 have been seen (would need 21 counter bits: 4 to 12 + 11 to 0)
+ * conservative value here: 27 provides offset up to 0x8000 bytes
+ */
+#define LZ77_MK_MAX_COUNT_BIT_LEN 27
+
+int lz77_mikrotik_wlan_decompress(
+ const unsigned char *in,
+ size_t in_len,
+ unsigned char *out,
+ size_t *out_len);
diff --git a/target/linux/generic/files/drivers/platform/mikrotik/routerboot.h b/target/linux/generic/files/drivers/platform/mikrotik/routerboot.h
index e858a524af43f..91693d8985226 100644
--- a/target/linux/generic/files/drivers/platform/mikrotik/routerboot.h
+++ b/target/linux/generic/files/drivers/platform/mikrotik/routerboot.h
@@ -16,6 +16,7 @@
#define RB_MAGIC_SOFT (('S') | ('o' << 8) | ('f' << 16) | ('t' << 24))
#define RB_MAGIC_LZOR (('L') | ('Z' << 8) | ('O' << 16) | ('R' << 24))
#define RB_MAGIC_ERD (('E' << 16) | ('R' << 8) | ('D'))
+#define RB_MAGIC_LZ77 (('7') | ('7' << 8) | ('Z' << 16) | ('L' << 24))
#define RB_ART_SIZE 0x10000