• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <lzmaram.h>
17 #include <hi_boot_err.h>
18 #include <hi_boot_rom.h>
19 
20 #define LZMA_DIC_MIN   (1 << 12)
21 #define LZMA_BASE_SIZE 1846
22 #define LZMA_LIT_SIZE  768
23 #define IN_BUF_SIZE    0x1000
24 #define OUT_BUF_SIZE   0x1000
25 
lzma_alloc(hi_pbyte unused,size_t size)26 static hi_pbyte lzma_alloc(hi_pbyte unused, size_t size)
27 {
28     hi_unref_param(unused);
29     hi_pbyte addr = (hi_pbyte)boot_malloc(size);
30     if (!addr) {
31         boot_msg1("\n LZMA_Alloc fail= ", size);
32     }
33     return addr;
34 }
35 
lzma_free(hi_pbyte unused,hi_pbyte address)36 static void lzma_free(hi_pbyte unused, hi_pbyte address)
37 {
38     hi_unref_param(unused);
39     if (address == HI_NULL) {
40         return;
41     }
42 
43     boot_free(address);
44 }
45 
46 /**
47 * @ingroup  LZMA
48 * @brief  : get file size and dictionary size before LZMA compressed
49 *
50 * @par :description:
51 *          get file size and dictionary size before LZMA compressed
52 *
53 * @attention: nothing
54 * @param  lzma_head                     [IN] type #hi_u8*-LZMA head
55 * @param  pulDecompressedDataLen        [OUT] type #unsigned int*, size before compressed
56 * @param  dic_size                      [OUT] type #unsigned int* , dictionary size
57 *
58 * @retval #HI_ERR_SUCCESS  success
59 * @retval # other value: fail, see hi_errno.h for details
60 * @par  dependency:
61 *
62 * @see : nothing
63  */
hi_lzma_get_uncompress_len(const hi_u8 lzma_head[13],hi_u32 head_size,unsigned int * pul_decompressed_data_len,unsigned int * dic_size)64 unsigned int hi_lzma_get_uncompress_len(const hi_u8 lzma_head[13], hi_u32 head_size, /* head 13B */
65                                         unsigned int *pul_decompressed_data_len, unsigned int *dic_size)
66 {
67     unsigned int uncompressed_len;
68     unsigned int uncompressed_len_high;
69 
70     if ((lzma_head == HI_NULL)
71         || (pul_decompressed_data_len == HI_NULL)
72         || head_size > 13) { /* head 13B */
73         boot_msg1("[lzma get uncompress len]head size", head_size);
74         return HI_ERR_LZMA_PARAM;
75     }
76 
77     uncompressed_len = (unsigned int)lzma_head[5] |               /* index 5,  low 8bits */
78                        ((unsigned int)lzma_head[6] << 8) |        /* index 6, bits 8-15 */
79                        ((unsigned int)lzma_head[7] << 16) |       /* index 7, bits 16-23 */
80                        ((unsigned int)lzma_head[8] << 24);        /* index 8, bits 24-32 */
81     uncompressed_len_high = (unsigned int)lzma_head[9] |          /* index 9,  low 8bits */
82                             ((unsigned int)lzma_head[10] << 8) |  /* index 10,  bits 8-15 */
83                             ((unsigned int)lzma_head[11] << 16) | /* index 11,  bits 16-23 */
84                             ((unsigned int)lzma_head[12] << 24);  /* index 12,  bits 24-32 */
85 
86     if ((uncompressed_len_high != 0)) {
87         /* uncompressed file is too long, output buffer is not enough */
88         boot_msg1("[lzma get uncompress len]high", uncompressed_len_high);
89         return HI_ERR_LZMA_LEN;
90     }
91 
92     *dic_size = (unsigned int)lzma_head[1] |         /* index 1,  low 8bits */
93                 ((unsigned int)lzma_head[2] << 8) |  /* index 2, bits 8-15 */
94                 ((unsigned int)lzma_head[3] << 16) | /* index 3, bits 16-23 */
95                 ((unsigned int)lzma_head[4] << 24);  /* index 4, bits 24-32 */
96 
97     if (*dic_size < LZMA_DIC_MIN) {
98         *dic_size = LZMA_DIC_MIN;
99     }
100 
101     *pul_decompressed_data_len = uncompressed_len;
102     return HI_ERR_SUCCESS;
103 }
104 
105 /**
106 * @ingroup  LZMA
107 * @brief : LZMA decompress for sections
108 *
109 * @par description:
110 *          LZMA decompress for sections
111 *
112 * @attention : nothing
113 * @param  lzma_head                     [IN] type #hi_u8*-LZMA head
114 * @param  compress_len                  [IN] type  #unsigned int, size after compressed
115 * @param  in_func                       [IN] type #LZMA_STREAM_FCT,  get content of compressed
116 * @param  out_func                      [IN] type #LZMA_STREAM_FCT, save the content after compressed
117 *
118 * @retval #HI_ERR_SUCCESS  success
119 * @retval # other value: fail, see hi_errno.h for details
120 * @par  dependency:
121 *
122 * @see : nothing
123  */
hi_lzma_decompress(const hi_u8 lzma_head[13],hi_u32 head_size,unsigned int compress_len,lzma_stream_fct in_func,lzma_stream_fct out_func)124 unsigned int hi_lzma_decompress(const hi_u8 lzma_head[13], hi_u32 head_size,  /* head 13B */
125     unsigned int compress_len, lzma_stream_fct in_func, lzma_stream_fct out_func)
126 {
127     unsigned int ret;
128     unsigned int lzma_stat = 0;
129     unsigned int uncompress_len = 0;
130     unsigned int dic_size = 0;
131     i_sz_alloc alloc = { 0 };
132     lzma_stream in_stream;
133     lzma_stream out_stream;
134     in_stream.func = in_func;
135     in_stream.offset = 13; /* offset 13 */
136     out_stream.func = out_func;
137     out_stream.offset = 0;
138 
139     alloc.alloc = lzma_alloc;
140     alloc.free = lzma_free;
141 
142     ret = hi_lzma_get_uncompress_len(lzma_head, head_size, &uncompress_len, &dic_size);
143     if (ret != HI_ERR_SUCCESS) {
144         boot_msg1("[hi lzma decompress]get uncompress len:", ret);
145     }
146     ret = LzmaDecode2(lzma_head, 5, &lzma_stat, &alloc, &in_stream, /* size 5 */
147                       &out_stream, compress_len - 13, uncompress_len);            /* length subtract 13 */
148     if (ret != 0) {
149         boot_msg1("[hi lzma decompress]decode ret:", ret);
150     }
151 
152     return (ret ? (HI_ERR_LZMA_DECODE + ret) : HI_ERR_SUCCESS);
153 }
154 
155 /**
156 * @ingroup  LZMA
157 * @brief  LZMA RAM usage detect
158 *
159 * @par description:
160 *           LZMA RAM usage detect, detect for whether the current RAM is enough for LZMA uncompress
161 *
162 * @attention : nothing
163 * @param  lzma_head                     [IN] type #hi_u8*, LZMA head
164 *
165 * @retval #HI_ERR_SUCCESS  success
166 * @retval # other value: fail, see hi_errno.h for details
167 * @par  dependency:
168 *
169 * @see : nothing
170  */
hi_lzma_mem_detect(const hi_u8 lzma_head[13],hi_u32 head_size)171 unsigned int hi_lzma_mem_detect(const hi_u8 lzma_head[13], hi_u32 head_size) /* head 13B */
172 {
173     unsigned int ret;
174     unsigned int compress_len = 0;
175     unsigned int dic_size = 0;
176     unsigned char d;
177     unsigned int lc, lp;
178     unsigned int malloc_size[5] = { /* size 5*4 */
179         0,
180     };
181     unsigned char *addr[5] = { /* addr 5B */
182         HI_NULL,
183     };
184     unsigned int array_size = sizeof(addr) / sizeof(addr[0]);
185     unsigned int i;
186 
187     ret = hi_lzma_get_uncompress_len(lzma_head, head_size, &compress_len, &dic_size);
188     if (ret != HI_ERR_SUCCESS) {
189         return ret;
190     }
191     d = lzma_head[0];
192     if (d >= (9 * 5 * 5)) { /* less than 9*5*5 */
193         boot_msg1("[hi_lzma_mem_detect]d", d);
194         return HI_ERR_FAILURE;
195     }
196 
197     lc = d % 9; /* remain of devide 9 */
198     d /= 9;     /* counts of 9 */
199     lp = d % 5; /* remain of devide 5 */
200 
201     malloc_size[0] = (((unsigned int)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp))) * 2); /* shifts (lc+lp)*2 */
202     malloc_size[1] = IN_BUF_SIZE;                                                         /* index 1 */
203     malloc_size[2] = OUT_BUF_SIZE;                                                        /* index 2 */
204     malloc_size[3] = dic_size;                                                            /* index 3 */
205     malloc_size[4] = 0x400;                                /* for security ,index 4:0x400 */
206     boot_msg2("[hi_lzma_mem_detect]malloc_size[0-3]", malloc_size[0], dic_size);
207 
208     for (i = 0; i < array_size; i++) {
209         addr[i] = boot_malloc(malloc_size[i]);
210 
211         if (addr[i] == HI_NULL) {
212             ret = HI_ERR_FAILURE;
213             break;
214         }
215     }
216 
217     for (i = 0; i < array_size; i++) {
218         if (addr[array_size - i - 1] != HI_NULL) {
219             boot_free(addr[array_size - i - 1]);
220         }
221     }
222 
223     return ret;
224 }
225