Skip to content

Commit dbe1b2c

Browse files
committed
[base] Add lz4 decompression
Add the lz4 decompression algorithm. This algorithm costs around 400 bytes. Signed-off-by: Siemen Dhooghe <sdhooghe@google.com>
1 parent 6695d87 commit dbe1b2c

3 files changed

Lines changed: 127 additions & 0 deletions

File tree

sw/device/lib/base/BUILD

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,16 @@ cc_library(
266266
],
267267
)
268268

269+
cc_library(
270+
name = "lz4",
271+
srcs = ["lz4.c"],
272+
hdrs = ["lz4.h"],
273+
deps = [
274+
":memory",
275+
"//sw/device/lib/base:macros",
276+
],
277+
)
278+
269279
cc_test(
270280
name = "random_order_unittest",
271281
srcs = ["random_order_unittest.cc"],

sw/device/lib/base/lz4.c

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Copyright lowRISC contributors (OpenTitan project).
2+
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
#include "sw/device/lib/base/lz4.h"
6+
7+
#include <stdint.h>
8+
9+
int LZ4_decompress(const char *src_in, char *dst_in, int compressed_size,
10+
int dst_capacity) {
11+
const uint8_t *src = (const uint8_t *)src_in;
12+
const uint8_t *src_end = src + compressed_size;
13+
uint8_t *dst = (uint8_t *)dst_in;
14+
uint8_t *dst_end = dst + dst_capacity;
15+
uint8_t *dst_ptr = dst;
16+
17+
while (src < src_end) {
18+
uint8_t token = *src++;
19+
20+
// Process literals
21+
unsigned int lit_len = token >> 4;
22+
if (lit_len == 15) {
23+
uint8_t s;
24+
do {
25+
if (src >= src_end)
26+
return -1; // Unexpected end of src
27+
s = *src++;
28+
lit_len += s;
29+
} while (s == 255);
30+
}
31+
32+
if (lit_len > 0) {
33+
if ((size_t)(src_end - src) < lit_len ||
34+
(size_t)(dst_end - dst_ptr) < lit_len) {
35+
return -1;
36+
}
37+
38+
unsigned int l = lit_len;
39+
do {
40+
*dst_ptr++ = *src++;
41+
} while (--l);
42+
}
43+
44+
if (src >= src_end) {
45+
break;
46+
}
47+
48+
// Process match offset
49+
if (src + 2 > src_end)
50+
return -1;
51+
uint16_t offset = (uint16_t)(src[0] | (src[1] << 8));
52+
src += 2;
53+
54+
if (offset == 0 || offset > (size_t)(dst_ptr - dst)) {
55+
return -1; // Offset out of bounds
56+
}
57+
58+
unsigned int match_len = token & 0x0F;
59+
if (match_len == 15) {
60+
uint8_t s;
61+
do {
62+
if (src >= src_end)
63+
return -1;
64+
s = *src++;
65+
match_len += s;
66+
} while (s == 255);
67+
}
68+
match_len += 4;
69+
70+
// Check bounds for match destination
71+
if ((size_t)(dst_end - dst_ptr) < match_len) {
72+
return -1;
73+
}
74+
75+
const uint8_t *match_ptr = dst_ptr - offset;
76+
unsigned int m = match_len;
77+
do {
78+
*dst_ptr++ = *match_ptr++;
79+
} while (--m);
80+
}
81+
82+
return (int)(dst_ptr - dst);
83+
}

sw/device/lib/base/lz4.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright lowRISC contributors (OpenTitan project).
2+
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
#ifndef OPENTITAN_SW_DEVICE_LIB_BASE_LZ4_H_
6+
#define OPENTITAN_SW_DEVICE_LIB_BASE_LZ4_H_
7+
8+
#include <stddef.h>
9+
10+
#ifdef __cplusplus
11+
extern "C" {
12+
#endif
13+
14+
/**
15+
* Decompresses a raw LZ4 block into a destination buffer.
16+
*
17+
* This implementation is designed specifically for constrained embedded
18+
* environments. It performs no dynamic allocation and requires no
19+
* framing metadata.
20+
*
21+
* @param src Pointer to the compressed data.
22+
* @param dst Pointer to the destination buffer.
23+
* @param compressed_size The exact size of the compressed data.
24+
* @param dst_capacity The maximum capacity of the destination buffer.
25+
* @return The number of bytes decompressed, or a negative value on error.
26+
*/
27+
int LZ4_decompress(const char *src, char *dst, int compressed_size,
28+
int dst_capacity);
29+
30+
#ifdef __cplusplus
31+
}
32+
#endif
33+
34+
#endif // OPENTITAN_SW_DEVICE_LIB_BASE_LZ4_H_

0 commit comments

Comments
 (0)