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 26static 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 36static 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 */ 64unsigned 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 */ 124unsigned 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 */ 171unsigned 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