1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19 /*
20 * Command for compress.
21 */
22
23 #include <common.h>
24 #include <compiler.h>
25
26 typedef unsigned char hi_u8;
27 typedef unsigned char hi_uchar;
28 typedef unsigned short hi_u16;
29 typedef unsigned int hi_u32;
30 typedef unsigned long hi_ul;
31
32 typedef char hi_s8;
33 typedef short hi_s16;
34 typedef int hi_s32;
35
36 typedef char hi_char;
37 typedef char *hi_pchar;
38
39
40 #define CYCLE_MAGIC_HEAD 0x6379636c
41
42 #define CYCLE_MAGIC_ITEM_START 0x63796373
43
44 #define CYCLE_MAGIC_ITEM_END 0x63796365
45
46 /** Cycle Head Infomation */
47 typedef struct hicycle_head_s {
48 hi_u32 u32magichead;
49 hi_u32 u32cycleflashsize; /**<include cycle_head size */
50 hi_u32 u32compress: 2;
51 hi_u32 u32writeflag: 3;
52 hi_u32 u32reserved: 27;
53 hi_u32 u32alignsize;
54 } hi_cycle_head_s;
55
56 /** Cycle Item Infomation */
57 typedef struct hicycle_item_start_s {
58 hi_u32 u32magicitemstart;
59 hi_u32 u32itemlen;
60 hi_u32 u32itemalllen;
61 hi_u32 u32itemoriginlen;
62 } hi_cycle_item_start_s;
63
64 #define DIVIDE 3
65 #define BYTE_ALIGN ((hi_u32)16) /**<needed by decompress */
66
67 extern unsigned int hw_dec_type;
68 extern void hw_dec_init(void);
69 #if (defined CONFIG_TARGET_HI3559AV100) || (defined CONFIG_HI3559AV100) ||\
70 (defined CONFIG_TARGET_HI3556AV100) || (defined CONFIG_TARGET_HI3519AV100) ||\
71 (defined CONFIG_TARGET_HI3569V100) || (defined CONFIG_HI3569V100)
72 extern int hw_dec_decompress(unsigned char *dst_h32, unsigned char *dst_l32,
73 int *dstlen,
74 unsigned char *src_h32, unsigned char *src_l32,
75 int srclen, void *unused);
76 #endif
77 #if ((defined CONFIG_TARGET_HI3559V200) || (defined CONFIG_TARGET_HI3556V200) ||\
78 (defined CONFIG_TARGET_HI3516DV300) || (defined CONFIG_TARGET_HI3516AV300) ||\
79 (defined CONFIG_TARGET_HI3516CV500) || (defined CONFIG_TARGET_HI3516EV200) ||\
80 (defined CONFIG_TARGET_HI3516EV300) || (defined CONFIG_TARGET_HI3518EV300) ||\
81 (defined CONFIG_TARGET_HI3516DV200) || (defined CONFIG_TARGET_HI3562V100) ||\
82 (defined CONFIG_TARGET_HI3566V100))
83 extern int hw_dec_decompress(unsigned char *dst, int *dstlen,
84 unsigned char *src, int srclen,
85 void *unused);
86 #endif
87 extern void hw_dec_uinit(void);
88
89 #define cycle_err(fmt, args...) printf("ERR: <%s:%d> "fmt, __FUNCTION__,\
90 __LINE__, ##args)
91 #define cycle_dbg(fmt, args...) printf("DBG: <%s:%d> "fmt, __FUNCTION__,\
92 __LINE__, ##args)
93
cycle_get_initdata(hi_ul ulsrc,hi_u32 u32srclen,hi_cycle_item_start_s ** ppstItem,hi_u32 * pu32Compress)94 static hi_s32 cycle_get_initdata(hi_ul ulsrc, hi_u32 u32srclen,
95 hi_cycle_item_start_s **ppstItem,
96 hi_u32 *pu32Compress)
97 {
98 hi_cycle_head_s *psthead = NULL;
99 hi_cycle_item_start_s *pstitem = NULL;
100 hi_u32 u32itemmagicend;
101 hi_ul ulbuffer = ulsrc;
102
103 /* Cycle Head */
104 psthead = (hi_cycle_head_s *)ulsrc;
105
106 if ((CYCLE_MAGIC_HEAD != psthead->u32magichead) ||
107 (u32srclen < psthead->u32cycleflashsize) ||
108 (0 == psthead->u32alignsize)) {
109 cycle_err("psthead->u32magichead: %#x\n",
110 psthead->u32magichead);
111 cycle_err("SrcLen[%u] CycleFlashSize[%u]\n", u32srclen,
112 psthead->u32cycleflashsize);
113 return -1;
114 }
115
116 /* Compress Type */
117 *pu32Compress = psthead->u32compress;
118 cycle_dbg("Compress[%u]\n", *pu32Compress);
119
120 /* First Item */
121 ulbuffer += sizeof(hi_cycle_head_s);
122 ulbuffer = (ulbuffer + psthead->u32alignsize - 1) &
123 ~(psthead->u32alignsize - 1);
124
125 pstitem = (hi_cycle_item_start_s *)ulbuffer;
126 if ((pstitem->u32itemlen == 0) ||
127 ((pstitem->u32itemlen % BYTE_ALIGN) != 0)) {
128 cycle_err("pstitem->u32itemlen: %#x\n", pstitem->u32itemlen);
129 return -1;
130 }
131
132 u32itemmagicend = *(hi_u32 *)(uintptr_t)(ulbuffer +
133 (pstitem->u32itemlen + sizeof(hi_cycle_item_start_s)));
134
135 if ((CYCLE_MAGIC_ITEM_START != pstitem->u32magicitemstart) ||
136 (pstitem->u32itemalllen >= (psthead->u32cycleflashsize / DIVIDE)) ||
137 (CYCLE_MAGIC_ITEM_END != u32itemmagicend)) {
138 cycle_err(
139 "Item MagicStart[%#x] Len[%u] MagicEnd[%#x] CycleFlashSize[%u]\n",
140 pstitem->u32magicitemstart, pstitem->u32itemlen, u32itemmagicend,
141 psthead->u32cycleflashsize);
142 return -1;
143 }
144
145 while (1) {
146 /* update item to last valid one */
147 *ppstItem = (hi_cycle_item_start_s *)ulbuffer;
148
149 /* check next item valid or not */
150 ulbuffer += pstitem->u32itemalllen;
151
152 pstitem = (hi_cycle_item_start_s *)ulbuffer;
153
154 /* <check buffer finish */
155 if (ulbuffer - ulsrc >= psthead->u32cycleflashsize)
156 return 0;
157
158 if (CYCLE_MAGIC_ITEM_START != pstitem->u32magicitemstart) {
159 /* <unused zone, use previous item */
160 if (pstitem->u32magicitemstart ==
161 0xffffffff) {
162 return 0;
163 } else {
164 cycle_err(
165 "pstitem->u32magicitemstart(0x%x) wrong!\n",
166 pstitem->u32magicitemstart);
167 return -1;
168 }
169 }
170
171 u32itemmagicend = *(hi_u32 *)(uintptr_t)(ulbuffer +
172 (pstitem->u32itemlen + sizeof(hi_cycle_item_start_s)));
173
174 /* <item data damaged */
175 if ((pstitem->u32itemlen >=
176 (psthead->u32cycleflashsize / DIVIDE)) ||
177 (CYCLE_MAGIC_ITEM_END != u32itemmagicend)) {
178 cycle_err("\n");
179 return -1;
180 }
181 }
182
183 return -1;
184 }
185
cycle_get_data(hi_ul ulsrc,hi_u32 u32srclen,hi_ul uldst)186 static hi_s32 cycle_get_data(hi_ul ulsrc, hi_u32 u32srclen, hi_ul uldst)
187 {
188 hi_s32 s32ret = -1;
189
190 hi_cycle_item_start_s *pstitem = NULL;
191 hi_ul ulitemdata = 0;
192 hi_u32 ncompressed = 0;
193
194 s32ret = cycle_get_initdata(ulsrc, u32srclen, &pstitem, &ncompressed);
195 if ((s32ret == 0) && pstitem) {
196 ulitemdata += (uintptr_t)pstitem + sizeof(hi_cycle_item_start_s);
197
198 if (ncompressed) {
199 hw_dec_type = 0; /**<use direct address mode*/
200 hw_dec_init(); /**<init hw decompress IP*/
201
202 hi_s32 s32sizecompressed = pstitem->u32itemoriginlen;
203 #if (defined CONFIG_TARGET_HI3559AV100) || (defined CONFIG_HI3559AV100) || \
204 (defined CONFIG_TARGET_HI3556AV100) || (defined CONFIG_TARGET_HI3519AV100) ||\
205 (defined CONFIG_TARGET_HI3569V100) || (defined CONFIG_HI3569V100)
206 s32ret = hw_dec_decompress(NULL, (hi_u8 *)(uintptr_t)uldst, &s32sizecompressed,
207 NULL, (hi_u8 *)ulitemdata, pstitem->u32itemlen, NULL);
208 #endif
209 #if ((defined CONFIG_TARGET_HI3559V200) || (defined CONFIG_TARGET_HI3556V200) || \
210 (defined CONFIG_TARGET_HI3516DV300) || (defined CONFIG_TARGET_HI3516AV300) || \
211 (defined CONFIG_TARGET_HI3516CV500) || (defined CONFIG_TARGET_HI3516EV200) || \
212 (defined CONFIG_TARGET_HI3516EV300) || (defined CONFIG_TARGET_HI3518EV300) || \
213 (defined CONFIG_TARGET_HI3516DV200) || (defined CONFIG_TARGET_HI3562V100) || \
214 (defined CONFIG_TARGET_HI3566V100))
215 s32ret = hw_dec_decompress((hi_u8 *)(uintptr_t)uldst, &s32sizecompressed,
216 (hi_u8 *)ulitemdata, pstitem->u32itemlen, NULL);
217 #endif
218 if (s32ret == 0 &&
219 s32sizecompressed == pstitem->u32itemoriginlen) {
220 cycle_dbg("decompress ok!\n");
221 s32ret = 0;
222 } else {
223 memset((void *)(uintptr_t)uldst, 0, 16);
224 cycle_err(
225 "decompress fail[%#x]! uncompress size[%#x]\n",
226 s32ret, s32sizecompressed);
227 s32ret = -1;
228 }
229
230 hw_dec_uinit(); /**<uinit hw decompress IP*/
231 } else {
232 memcpy((void *)(uintptr_t)uldst, (void *)(uintptr_t)ulitemdata,
233 pstitem->u32itemlen);
234 s32ret = 0;
235 }
236 } else {
237 memset((void *)(uintptr_t)uldst, 0, 16);
238 cycle_err("Failed to get cycle data. dst: 0x%lx\n", uldst);
239 s32ret = -1;
240 }
241
242 return s32ret;
243 }
244
getcycledata(hi_ul ulsrc,hi_ul ulsrcbak,hi_u32 u32srclen,hi_ul uldst)245 static hi_s32 getcycledata(hi_ul ulsrc, hi_ul ulsrcbak, hi_u32 u32srclen,
246 hi_ul uldst)
247 {
248 hi_s32 s32ret = cycle_get_data(ulsrc, u32srclen, uldst);
249 if (s32ret == -1 && ulsrcbak != 0)
250 s32ret = cycle_get_data(ulsrcbak, u32srclen, uldst);
251
252 return s32ret;
253 }
254
do_cycle(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])255 static int do_cycle(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
256 {
257 hi_ul ulsrc;
258 hi_ul ulsrcbak;
259 hi_ul uldst;
260 hi_u32 u32srclen;
261
262 /* Check Input Args Count : four arguments needed */
263 if (argc != 5)
264 goto usage;
265
266 ulsrc = simple_strtoul(argv[1], NULL, 16);
267 ulsrcbak = simple_strtoul(argv[2], NULL, 16);
268 u32srclen = simple_strtoul(argv[3], NULL, 16);
269 uldst = simple_strtoul(argv[4], NULL, 16);
270
271 if (ulsrc & 0XF) {
272 printf("ERR:\n src[0X%08lx] is not 16Byte-aligned!\n", ulsrc);
273 return 1;
274 }
275
276 if (ulsrcbak & 0XF) {
277 printf("ERR:\n src_backup[0X%08lx] is not 16Byte-aligned!\n",
278 ulsrcbak);
279 return 1;
280 }
281
282 if (u32srclen & 0XFFFF) {
283 printf("ERR:\n src_len[0X%08x] is not 0x10000Byte-aligned!\n",
284 u32srclen);
285 return 1;
286 }
287
288 if (uldst & 0XF) {
289 printf("ERR:\n dst[0X%08lx] is not 16Byte-aligned!\n", uldst);
290 return 1;
291 }
292
293 return getcycledata(ulsrc, ulsrcbak, u32srclen, uldst);
294
295 usage:
296 cmd_usage(cmdtp);
297 return 1;
298 }
299
300 U_BOOT_CMD(
301 cread, 5, 1, do_cycle,
302 "get valid data from cycle_data buffer. 'cycle <src> <src_backup> <src_len> <dst>'",
303 "1. src_backup can be 0. 2. if src and src_backup are wrong, "
304 "dst head (16 byte) will be set to 0. 3. src and dst must be 16Byte-aligned"
305 );
306
307