Skip to content

Commit

Permalink
lib: Import LZ4KD compression algorithm from HUAWEI
Browse files Browse the repository at this point in the history
ABR-AL60_HarmonyOS4.0.0_opensource.tar.gz

Signed-off-by: 0wnerDied <[email protected]>
  • Loading branch information
0wnerDied authored and KNKJ55 committed Jan 12, 2025
1 parent 2b9296b commit 22e4353
Show file tree
Hide file tree
Showing 12 changed files with 1,436 additions and 1 deletion.
9 changes: 9 additions & 0 deletions crypto/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1647,6 +1647,15 @@ config CRYPTO_LZ4
help
This is the LZ4 algorithm.

config CRYPTO_LZ4KD
tristate "LZ4KD compression algorithm"
select CRYPTO_ALGAPI
select CRYPTO_ACOMP2
select LZ4KD_COMPRESS
select LZ4KD_DECOMPRESS
help
This is the LZ4KD algorithm.

config CRYPTO_LZ4HC
tristate "LZ4HC compression algorithm"
select CRYPTO_ALGAPI
Expand Down
1 change: 1 addition & 0 deletions crypto/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ obj-$(CONFIG_CRYPTO_CRCT10DIF) += crct10dif_common.o crct10dif_generic.o
obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o
obj-$(CONFIG_CRYPTO_LZO) += lzo.o lzo-rle.o
obj-$(CONFIG_CRYPTO_LZ4) += lz4.o
obj-$(CONFIG_CRYPTO_LZ4KD) += lz4kd.o
obj-$(CONFIG_CRYPTO_LZ4HC) += lz4hc.o
obj-$(CONFIG_CRYPTO_842) += 842.o
obj-$(CONFIG_CRYPTO_RNG2) += rng.o
Expand Down
95 changes: 95 additions & 0 deletions crypto/lz4kd.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Cryptographic API.
*
* Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved.
* Description: LZ4KD compression algorithm for ZRAM
*/

#include <linux/init.h>
#include <linux/module.h>
#include <linux/crypto.h>
#include <linux/vmalloc.h>
#include <linux/lz4kd.h>


struct lz4kd_ctx {
void *lz4kd_comp_mem;
};

static int lz4kd_init(struct crypto_tfm *tfm)
{
struct lz4kd_ctx *ctx = crypto_tfm_ctx(tfm);

ctx->lz4kd_comp_mem = vmalloc(lz4kd_encode_state_bytes_min());
if (!ctx->lz4kd_comp_mem)
return -ENOMEM;

return 0;
}

static void lz4kd_exit(struct crypto_tfm *tfm)
{
struct lz4kd_ctx *ctx = crypto_tfm_ctx(tfm);
vfree(ctx->lz4kd_comp_mem);
}

static int lz4kd_compress_crypto(struct crypto_tfm *tfm, const u8 *src, unsigned int slen, u8 *dst,
unsigned int *dlen)
{
struct lz4kd_ctx *ctx = crypto_tfm_ctx(tfm);
int ret = 0;

ret = lz4kd_encode(ctx->lz4kd_comp_mem, src, dst, slen, *dlen, 0);
if (ret < 0)
return -EINVAL;

if (ret)
*dlen = ret;

return 0;
}

static int lz4kd_decompress_crypto(struct crypto_tfm *tfm, const u8 *src, unsigned int slen, u8 *dst,
unsigned int *dlen)
{
int ret = 0;

ret = lz4kd_decode(src, dst, slen, *dlen);
if (ret <= 0)
return -EINVAL;
*dlen = ret;
return 0;
}

static struct crypto_alg alg_lz4kd = {
.cra_name = "lz4kd",
.cra_driver_name = "lz4kd-generic",
.cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
.cra_ctxsize = sizeof(struct lz4kd_ctx),
.cra_module = THIS_MODULE,
.cra_init = lz4kd_init,
.cra_exit = lz4kd_exit,
.cra_u = {
.compress = {
.coa_compress = lz4kd_compress_crypto,
.coa_decompress = lz4kd_decompress_crypto
}
}
};

static int __init lz4kd_mod_init(void)
{
return crypto_register_alg(&alg_lz4kd);
}

static void __exit lz4kd_mod_fini(void)
{
crypto_unregister_alg(&alg_lz4kd);
}

module_init(lz4kd_mod_init);
module_exit(lz4kd_mod_fini);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("LZ4KD Compression Algorithm");
MODULE_ALIAS_CRYPTO("lz4kd");
3 changes: 3 additions & 0 deletions drivers/block/zram/zcomp.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ static const char * const backends[] = {
#if IS_ENABLED(CONFIG_CRYPTO_LZ4HC)
"lz4hc",
#endif
#if IS_ENABLED(CONFIG_CRYPTO_LZ4KD)
"lz4kd",
#endif
#if IS_ENABLED(CONFIG_CRYPTO_842)
"842",
#endif
Expand Down
216 changes: 216 additions & 0 deletions include/linux/lz4kd.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
/*
* Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved.
* Description: LZ4K compression algorithm with delta compression
*/

#ifndef _LZ4KD_H
#define _LZ4KD_H

/* file lz4kd.h
This file contains the platform-independent API of LZ-class
lossless codecs (compressors/decompressors) with complete
in-place documentation. The documentation is formatted
in accordance with DOXYGEN mark-up format. So, one can
generate proper documentation, e.g. in HTML format, using DOXYGEN.
Currently, LZ-class codecs, documented here, implement following
algorithms for lossless data compression/decompression:
\li "LZ" proprietary codec competing with LZ4 - lz4kd_encode(),
lz4kd_encode_delta(), lz4kd_decode(), lz4kd_decode_delta()
The LZ compressors accept any data as input and compress it
without loss to a smaller size if possible.
Compressed data produced by LZ compressor API lz4kd_encode*(),
can be decompressed only by lz4kd_decode() API documented below.\n
*/

/*
lz4kd_status defines simple set of status values returned by APIs
*/
typedef enum {
LZ4K_STATUS_INCOMPRESSIBLE = 0, /* !< Return when data is incompressible */
LZ4K_STATUS_FAILED = -1, /* !< Return on general failure */
LZ4K_STATUS_READ_ERROR = -2, /* !< Return when data reading failed */
LZ4K_STATUS_WRITE_ERROR = -3 /* !< Return when data writing failed */
} lz4kd_status;

/*
lz4kd_Version() returns static unmutable string with algorithm version
*/
const char *lz4kd_version(void);

/*
lz4kd_encode_state_bytes_min() returns number of bytes for state parameter,
supplied to lz4kd_encode(), lz4kd_encode_delta().
So, state should occupy at least lz4kd_encode_state_bytes_min() for mentioned
functions to work correctly.
*/
unsigned lz4kd_encode_state_bytes_min(void);

/*
lz4kd_encode() encodes/compresses one input buffer at *in, places
result of encoding into one output buffer at *out if encoded data
size fits specified values of out_max and out_limit.
It returs size of encoded data in case of success or value<=0 otherwise.
The result of successful encoding is in proprietary format, that
is the encoded data can be decoded only by lz4kd_decode().
\return
\li positive value\n
if encoding was successful. The value returned is the size of encoded
(compressed) data always <=out_max.
\li non-positive value\n
if in==0||in_max==0||out==0||out_max==0 or
if out_max is less than needed for encoded (compressed) data.
\li 0 value\n
if encoded data size >= out_limit
\param[in] state
!=0, pointer to state buffer used internally by the function. Size of
state in bytes should be at least lz4kd_encode_state_bytes_min(). The content
of state buffer will be changed during encoding.
\param[in] in
!=0, pointer to the input buffer to encode (compress). The content of
the input buffer does not change during encoding.
\param[in] out
!=0, pointer to the output buffer where to place result of encoding
(compression).
If encoding is unsuccessful, e.g. out_max or out_limit are less than
needed for encoded data then content of out buffer may be arbitrary.
\param[in] in_max
!=0, size in bytes of the input buffer at *in
\param[in] out_max
!=0, size in bytes of the output buffer at *out
\param[in] out_limit
encoded data size soft limit in bytes. Due to performance reasons it is
not guaranteed that
lz4kd_encode will always detect that resulting encoded data size is
bigger than out_limit.
Hovewer, when reaching out_limit is detected, lz4kd_encode() returns
earlier and spares CPU cycles. Caller code should recheck result
returned by lz4kd_encode() (value greater than 0) if it is really
less or equal than out_limit.
out_limit is ignored if it is equal to 0.
*/
int lz4kd_encode(
void *const state,
const void *const in,
void *out,
unsigned in_max,
unsigned out_max,
unsigned out_limit);

int lz4kd_encode2(
void *const state,
const void *const in,
void *out,
unsigned in_max,
unsigned out_max,
unsigned out_limit);

int lz4kd_encode_pattern(
void *const state,
const void *const in,
void *out,
unsigned in_max,
unsigned out_max,
unsigned out_limit);

/*
lz4kd_encode_max_cr() encodes/compresses one input buffer at *in, places
result of encoding into one output buffer at *out if encoded data
size fits specified value of out_max.
It returs size of encoded data in case of success or value<=0 otherwise.
The result of successful encoding is in proprietary format, that
is the encoded data can be decoded only by lz4kd_decode().
\return
\li positive value\n
if encoding was successful. The value returned is the size of encoded
(compressed) data always <=out_max.
\li non-positive value\n
if in==0||in_max==0||out==0||out_max==0 or
if out_max is less than needed for encoded (compressed) data.
\param[in] state
!=0, pointer to state buffer used internally by the function. Size of
state in bytes should be at least lz4kd_encode_state_bytes_min(). The content
of state buffer will be changed during encoding.
\param[in] in
!=0, pointer to the input buffer to encode (compress). The content of
the input buffer does not change during encoding.
\param[in] out
!=0, pointer to the output buffer where to place result of encoding
(compression).
If encoding is unsuccessful, e.g. out_max is less than
needed for encoded data then content of out buffer may be arbitrary.
\param[in] in_max
!=0, size in bytes of the input buffer at *in
\param[in] out_max
!=0, size in bytes of the output buffer at *out
\param[in] out_limit
encoded data size soft limit in bytes. Due to performance reasons it is
not guaranteed that
lz4kd_encode will always detect that resulting encoded data size is
bigger than out_limit.
Hovewer, when reaching out_limit is detected, lz4kd_encode() returns
earlier and spares CPU cycles. Caller code should recheck result
returned by lz4kd_encode() (value greater than 0) if it is really
less or equal than out_limit.
out_limit is ignored if it is equal to 0.
*/
int lz4kd_encode_max_cr(
void *const state,
const void *const in,
void *out,
unsigned in_max,
unsigned out_max,
unsigned out_limit);

/*
lz4kd_decode() decodes (decompresses) data from one input buffer and places
the result of decompression into one output buffer. The encoded data in input
buffer should be in proprietary format, produced by lz4kd_encode()
or by lz4kd_encode_delta().
\return
\li positive value\n
if decoding was successful. The value returned is the size of decoded
(decompressed) data.
\li non-positive value\n
if in==0||in_max==0||out==0||out_max==0 or
if out_max is less than needed for decoded (decompressed) data or
if input encoded data format is corrupted.
\param[in] in
!=0, pointer to the input buffer to decode (decompress). The content of
the input buffer does not change during decoding.
\param[in] out
!=0, pointer to the output buffer where to place result of decoding
(decompression). If decompression is unsuccessful then content of out
buffer may be arbitrary.
\param[in] in_max
!=0, size in bytes of the input buffer at in
\param[in] out_max
!=0, size in bytes of the output buffer at out
*/
int lz4kd_decode(
const void *const in,
void *const out,
unsigned in_max,
unsigned out_max);

#endif /* _LZ4KD_H */
8 changes: 7 additions & 1 deletion lib/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,14 @@ config LZ4_COMPRESS
config LZ4HC_COMPRESS
tristate

config LZ4KD_COMPRESS
tristate

config LZ4_DECOMPRESS
tristate

config LZ4KD_DECOMPRESS
tristate

config ZSTD_COMPRESS
select XXHASH
Expand Down Expand Up @@ -288,7 +294,7 @@ config GENERIC_ALLOCATOR
#
config REED_SOLOMON
tristate

config REED_SOLOMON_ENC8
bool

Expand Down
2 changes: 2 additions & 0 deletions lib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ obj-$(CONFIG_LZO_DECOMPRESS) += lzo/
obj-$(CONFIG_LZ4_COMPRESS) += lz4/
obj-$(CONFIG_LZ4HC_COMPRESS) += lz4/
obj-$(CONFIG_LZ4_DECOMPRESS) += lz4/
obj-$(CONFIG_LZ4KD_COMPRESS) += lz4kd/
obj-$(CONFIG_LZ4KD_DECOMPRESS) += lz4kd/
obj-$(CONFIG_ZSTD_COMPRESS) += zstd/
obj-$(CONFIG_ZSTD_DECOMPRESS) += zstd/
obj-$(CONFIG_XZ_DEC) += xz/
Expand Down
3 changes: 3 additions & 0 deletions lib/lz4kd/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ccflags-y += -O3
obj-$(CONFIG_LZ4KD_COMPRESS) += lz4kd_encode.o
obj-$(CONFIG_LZ4KD_DECOMPRESS) += lz4kd_decode.o
Loading

0 comments on commit 22e4353

Please sign in to comment.