hc
2024-08-12 0517ab8c70e05fc5877c0c6dae1a5f42a16dcf88
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
 * Copyright 2015 Google Inc.
 *
 * SPDX-License-Identifier: GPL 2.0+ BSD-3-Clause
 */
 
#include <common.h>
#include <compiler.h>
#include <misc.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <asm/unaligned.h>
 
static u16 LZ4_readLE16(const void *src)
{
   return get_unaligned_le16(src);
}
static void LZ4_copy4(void *dst, const void *src)
{
   put_unaligned(get_unaligned((const u32 *)src), (u32 *)dst);
}
static void LZ4_copy8(void *dst, const void *src)
{
   put_unaligned(get_unaligned((const u64 *)src), (u64 *)dst);
}
 
typedef  uint8_t BYTE;
typedef uint16_t U16;
typedef uint32_t U32;
typedef  int32_t S32;
typedef uint64_t U64;
 
#define FORCE_INLINE static inline __attribute__((always_inline))
 
/* Unaltered (except removing unrelated code) from github.com/Cyan4973/lz4. */
#include "lz4.c"    /* #include for inlining, do not link! */
 
bool lz4_is_valid_header(const unsigned char *h)
{
   const struct lz4_frame_header *hdr  = (const struct lz4_frame_header *)h;
   /* We assume there's always only a single, standard frame. */
   if (le32_to_cpu(hdr->magic) != LZ4F_MAGIC || hdr->version != 1)
       return false;        /* unknown format */
   if (hdr->reserved0 || hdr->reserved1 || hdr->reserved2)
       return false; /* reserved must be zero */
   if (!hdr->independent_blocks)
       return false; /* we can't support this yet */
 
   return true;
}
 
int ulz4fn(const void *src, size_t srcn, void *dst, size_t *dstn)
{
   const void *end = dst + *dstn;
   const void *in = src;
   void *out = dst;
   int has_block_checksum;
   int ret;
   *dstn = 0;
 
#if defined(CONFIG_MISC_DECOMPRESS) && !defined(CONFIG_SPL_BUILD)
   u64 len;
 
   ret = misc_decompress_process((ulong)dst, (ulong)src, (ulong)srcn,
                     DECOM_LZ4, false, &len, 0);
   if (!ret) {
       *dstn = len;
       return 0;
   }
 
   printf("hw ulz4fn failed(%d), fallback to soft ulz4fn\n", ret);
#endif
   { /* With in-place decompression the header may become invalid later. */
       const struct lz4_frame_header *h = in;
 
       if (srcn < sizeof(*h) + sizeof(u64) + sizeof(u8))
           return -EINVAL;    /* input overrun */
 
       /* We assume there's always only a single, standard frame. */
       if (le32_to_cpu(h->magic) != LZ4F_MAGIC || h->version != 1)
           return -EPROTONOSUPPORT;    /* unknown format */
       if (h->reserved0 || h->reserved1 || h->reserved2)
           return -EINVAL;    /* reserved must be zero */
       if (!h->independent_blocks)
           return -EPROTONOSUPPORT; /* we can't support this yet */
       has_block_checksum = h->has_block_checksum;
 
       in += sizeof(*h);
       if (h->has_content_size)
           in += sizeof(u64);
       in += sizeof(u8);
   }
 
   while (1) {
       struct lz4_block_header b;
 
       b.raw = le32_to_cpu(*(u32 *)in);
       in += sizeof(struct lz4_block_header);
 
       if (in - src + b.size > srcn) {
           ret = -EINVAL;        /* input overrun */
           break;
       }
 
       if (!b.size) {
           ret = 0;    /* decompression successful */
           break;
       }
 
       if (b.not_compressed) {
           size_t size = min((ptrdiff_t)b.size, end - out);
           memcpy(out, in, size);
           out += size;
           if (size < b.size) {
               ret = -ENOBUFS;    /* output overrun */
               break;
           }
       } else {
           /* constant folding essential, do not touch params! */
           ret = LZ4_decompress_generic(in, out, b.size,
                   end - out, endOnInputSize,
                   full, 0, noDict, out, NULL, 0);
           if (ret < 0) {
               ret = -EPROTO;    /* decompression error */
               break;
           }
           out += ret;
       }
 
       in += b.size;
       if (has_block_checksum)
           in += sizeof(u32);
   }
 
   *dstn = out - dst;
   return ret;
}