• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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