1 /*
2 * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your 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, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include "drv_osal_lib.h"
20 #include "cryp_trng.h"
21 #include "securec.h"
22
23 /* ********************** Internal Structure Definition ********************** */
24 /* crg register addr size. */
25 #define CRG_REG_ADDR_SIZE 0x100
26
27 /* set a bit within a word. */
28 #undef set_bit
29 #define set_bit(src, bit) (src |= (1 << (bit)))
30
31 /* clear a bit within a word. */
32 #undef clear_bit
33 #define clear_bit(src, bit) (src &= ~(1 << (bit)))
34
35 /* module already initialize or not. */
36 static hi_u32 g_module_initialize = HI_FALSE;
37
38 /* struct resource_channel
39 * the table of base info of module, such as addr/reset/clk/ver.
40 */
41 struct sys_arch_hardware_info {
42 /* the name of module, used for debug print and request interrupt. */
43 const hi_char *name;
44
45 /* some field may be needn't to used. */
46 hi_u32 reset_valid : 1; /* bis[0], reset availability, 0-valid, 1-invalid. */
47 hi_u32 clk_valid : 1; /* bis[1], clock availability, 0-valid, 1-invalid. */
48 hi_u32 phy_valid : 1; /* bis[2], system address availability, 0-valid, 1-invalid. */
49 hi_u32 crg_valid : 1; /* bis[3], CRG availability, 0-valid, 1-invalid. */
50 hi_u32 ver_valid : 1; /* bis[4], version reg availability, 0-valid, 1-invalid. */
51 hi_u32 int_valid : 1; /* bis[5], interrupt availability, 0-valid, 1-invalid. */
52 hi_u32 res_valid : 25; /* bis[6..31]. */
53
54 /* module base addr. */
55 hi_u32 reg_addr_phy;
56
57 /* base logic addr size. */
58 hi_u32 reg_addr_size;
59
60 /* crg register addr, which provide the switch of reset and clock. */
61 hi_u32 crg_addr_phy;
62
63 /* the clk switch bit index within the crg register,
64 * if the switch bis is provided by second crg register, you need to add 32. */
65 hi_u32 clk_bit : 8;
66
67 /* the reset switch bit index within the crg register,
68 * if the switch bis is provided by second crg register, you need to add 32. */
69 hi_u32 reset_bit : 8;
70
71 /* the interrupt number. */
72 hi_u32 int_num : 8;
73
74 /* the reserve bits. */
75 hi_u32 res : 8;
76
77 /* the offset of version register. */
78 hi_u32 version_reg;
79
80 /* the value of version register, you can used it to check the active module. */
81 hi_u32 version_val;
82
83 /* cpu address of module register. */
84 hi_void *reg_addr_via;
85
86 /* cpu address of crg register. */
87 hi_void *crg_addr_via;
88 };
89
90 static struct sys_arch_hardware_info g_hard_info_table[CRYPTO_MODULE_ID_CNT] = {
91 HARD_INFO_CIPHER,
92 HARD_INFO_CIPHER_KEY,
93 HARD_INFO_HASH,
94 HARD_INFO_IFEP_RSA,
95 HARD_INFO_SIC_RSA,
96 HARD_INFO_TRNG,
97 HARD_INFO_SM2,
98 HARD_INFO_SM4,
99 HARD_INFO_SMMU,
100 };
101
102 #ifdef CRYPTO_SWITCH_CPU
103 static struct sys_arch_hardware_info g_nsec_hard_info_table[CRYPTO_MODULE_ID_CNT] = {
104 NSEC_HARD_INFO_CIPHER,
105 NSEC_HARD_INFO_CIPHER_KEY,
106 NSEC_HARD_INFO_HASH,
107 NSEC_HARD_INFO_IFEP_RSA,
108 NSEC_HARD_INFO_SIC_RSA,
109 NSEC_HARD_INFO_TRNG,
110 NSEC_HARD_INFO_SM2,
111 NSEC_HARD_INFO_SM4,
112 NSEC_HARD_INFO_SMMU,
113 };
114
115 static hi_u32 g_is_secure_cpu = HI_FALSE;
116 #endif
117
118 /* ****************************** API Code **************************** */
module_addr_map_reg(hi_void)119 static hi_s32 module_addr_map_reg(hi_void)
120 {
121 hi_u32 i;
122 struct sys_arch_hardware_info *table = HI_NULL;
123
124 hi_log_func_enter();
125
126 if (g_module_initialize == HI_TRUE) {
127 return HI_SUCCESS;
128 }
129
130 for (i = 0; i < CRYPTO_MODULE_ID_CNT; i++) {
131 table = &g_hard_info_table[i];
132
133 hi_log_info("[%u] %s\n", i, table->name);
134
135 /* io remap crg register. */
136 if (table->crg_valid) {
137 table->crg_addr_via = crypto_ioremap_nocache(table->crg_addr_phy, CRG_REG_ADDR_SIZE);
138 if (table->crg_addr_via == HI_NULL) {
139 hi_log_error("iomap reg of module failed\n");
140 module_addr_unmap();
141 hi_log_print_err_code(HI_ERR_CIPHER_FAILED_MEM);
142 return HI_ERR_CIPHER_FAILED_MEM;
143 }
144 hi_log_info("crg phy 0x%x, via 0x%pK\n", table->crg_addr_phy, table->crg_addr_via);
145 }
146
147 /* io remap module register. */
148 if (table->phy_valid) {
149 table->reg_addr_via = crypto_ioremap_nocache(table->reg_addr_phy, table->reg_addr_size);
150 if (table->reg_addr_via == HI_NULL) {
151 hi_log_error("iomap reg of module failed\n");
152 module_addr_unmap();
153 hi_log_print_err_code(HI_ERR_CIPHER_FAILED_MEM);
154 return HI_ERR_CIPHER_FAILED_MEM;
155 }
156 hi_log_info("reg phy 0x%x, via 0x%pK, size 0x%x\n", table->reg_addr_phy,
157 table->reg_addr_via, table->reg_addr_size);
158 }
159 }
160
161 g_module_initialize = HI_TRUE;
162 hi_log_func_exit();
163 return HI_SUCCESS;
164 }
165
166 /*
167 * brief unmap the physics addr to cpu within the base table, contains the base addr and crg addr.
168 */
module_addr_unmap(hi_void)169 hi_s32 module_addr_unmap(hi_void)
170 {
171 hi_u32 i;
172 struct sys_arch_hardware_info *table = HI_NULL;
173
174 hi_log_func_enter();
175
176 if (g_module_initialize == HI_FALSE) {
177 return HI_SUCCESS;
178 }
179
180 for (i = 0; i < CRYPTO_MODULE_ID_CNT; i++) {
181 table = &g_hard_info_table[i];
182
183 hi_log_info("[%u] %s\n", i, table->name);
184
185 /* io unmap crg register. */
186 if (table->crg_valid && table->crg_addr_via) {
187 hi_log_info("crg via addr 0x%pK\n", table->crg_addr_via);
188 crypto_iounmap(table->crg_addr_via, CRG_REG_ADDR_SIZE);
189 table->crg_addr_via = HI_NULL;
190 }
191
192 /* io unmap module register. */
193 if (table->phy_valid && table->reg_addr_via) {
194 hi_log_info("reg via addr 0x%pK\n", table->reg_addr_via);
195 crypto_iounmap(table->reg_addr_via, table->reg_addr_size);
196 table->reg_addr_via = HI_NULL;
197 }
198 }
199
200 g_module_initialize = HI_FALSE;
201
202 hi_log_func_exit();
203 return HI_SUCCESS;
204 }
205
206 /*
207 * brief map the physics addr to cpu within the base table, contains the base addr and crg addr.
208 */
module_addr_map(hi_void)209 hi_s32 module_addr_map(hi_void)
210 {
211 hi_s32 ret;
212
213 hi_log_func_enter();
214
215 ret = module_addr_map_reg();
216 if (ret != HI_SUCCESS) {
217 hi_log_print_func_err(module_addr_map_reg, ret);
218 return ret;
219 }
220
221 #ifdef CRYPTO_SWITCH_CPU
222 g_is_secure_cpu = drv_symc_is_secure();
223 if (g_is_secure_cpu == HI_TRUE) {
224 /* default secure cpu, do nothing */
225 return HI_SUCCESS;
226 }
227
228 hi_log_info("non-secure CPU need to remap reg addr\n");
229
230 /* use non-secure info */
231 if (memcpy_s(&g_hard_info_table, sizeof(g_hard_info_table),
232 &g_nsec_hard_info_table, sizeof(g_nsec_hard_info_table)) != EOK) {
233 hi_log_print_func_err(memcpy_s, HI_ERR_CIPHER_MEMCPY_S_FAILED);
234 return HI_ERR_CIPHER_MEMCPY_S_FAILED;
235 }
236
237 /* remap module addr */
238 ret = module_addr_unmap();
239 if (ret != HI_SUCCESS) {
240 hi_log_print_func_err(module_addr_unmap, ret);
241 return ret;
242 }
243 ret = module_addr_map_reg();
244 if (ret != HI_SUCCESS) {
245 hi_log_print_func_err(module_addr_map, ret);
246 return ret;
247 }
248 #endif
249
250 hi_log_func_exit();
251 return HI_SUCCESS;
252 }
253
254 /*
255 * brief get secure cpu type.
256 */
module_get_secure(hi_void)257 hi_u32 module_get_secure(hi_void)
258 {
259 #ifdef CRYPTO_SEC_CPU
260 return HI_TRUE;
261 #elif defined(CRYPTO_SWITCH_CPU)
262 return g_is_secure_cpu;
263 #else
264 return HI_FALSE;
265 #endif
266 }
267
268 /*
269 * brief open clock.
270 */
module_clock(module_id id,hi_u32 open)271 static hi_void module_clock(module_id id, hi_u32 open)
272 {
273 hi_u32 *addr = HI_NULL;
274 struct sys_arch_hardware_info *table = HI_NULL;
275
276 hi_log_func_enter();
277
278 if (id >= CRYPTO_MODULE_ID_CNT) {
279 hi_log_error("invalid module id %d\n", id);
280 return;
281 }
282
283 table = &g_hard_info_table[id];
284
285 if (table->clk_valid) {
286 hi_u32 val;
287
288 if (table->crg_addr_via == HI_NULL) {
289 hi_log_error("\033[0;1;31m""%s clock failed, crg addr is null\n""\033[0m", table->name);
290 return;
291 }
292
293 /* open clk, the addr may be need to add 1. */
294 addr = table->crg_addr_via;
295 addr += table->clk_bit / WORD_BIT_WIDTH;
296
297 val = crypto_read(addr);
298
299 if (open) {
300 set_bit(val, table->clk_bit % WORD_BIT_WIDTH);
301 } else {
302 clear_bit(val, table->clk_bit % WORD_BIT_WIDTH);
303 }
304
305 crypto_write(addr, val);
306
307 /* wait hardware clock active. */
308 crypto_msleep(1);
309
310 hi_log_info("%s clock, open %u, bit %u, phy 0x%x, via 0x%pK\n",
311 table->name, open, table->clk_bit,
312 table->crg_addr_phy, table->crg_addr_via);
313 }
314
315 hi_log_func_exit();
316
317 return;
318 }
319
module_reset(module_id id,hi_u32 enable)320 static hi_void module_reset(module_id id, hi_u32 enable)
321 {
322 hi_u32 *addr = HI_NULL;
323 struct sys_arch_hardware_info *table = HI_NULL;
324
325 hi_log_func_enter();
326
327 if (id >= CRYPTO_MODULE_ID_CNT) {
328 hi_log_error("invalid module id %d\n", id);
329 return;
330 }
331
332 table = &g_hard_info_table[id];
333
334 if (table->reset_valid) {
335 hi_u32 val, expect;
336
337 if (table->crg_addr_via == HI_NULL) {
338 hi_log_error("%s reset failed, crg addr is null\n", table->name);
339 return;
340 }
341
342 /* the addr may be need to add 1. */
343 addr = table->crg_addr_via;
344 addr += table->reset_bit / WORD_BIT_WIDTH;
345
346 val = crypto_read(addr);
347
348 if (enable) {
349 set_bit(val, table->reset_bit % WORD_BIT_WIDTH);
350 expect = 0;
351 } else {
352 clear_bit(val, table->reset_bit % WORD_BIT_WIDTH);
353 expect = table->version_val;
354 }
355
356 crypto_write(addr, val);
357
358 /* wait hardware reset finish. */
359 crypto_msleep(1);
360
361 hi_log_info("%s reset, enable %u, bit %u, phy 0x%x, via 0x%pK\n",
362 table->name, enable, table->reset_bit,
363 table->crg_addr_phy, table->crg_addr_via);
364
365 /* check the value of version reg to make sure reset success. */
366 if (table->ver_valid && table->reg_addr_via) {
367 val = crypto_read((hi_u8 *)table->reg_addr_via + table->version_reg);
368 if (val != expect) {
369 hi_log_error("%s reset failed, version reg should be 0x%x but 0x%x\n", table->name, expect, val);
370 return;
371 }
372
373 hi_log_info("%s version reg, offset 0x%x, expect val 0x%x, real val 0x%x\n",
374 table->name, table->version_reg, expect, val);
375 }
376 }
377
378 hi_log_func_exit();
379
380 return;
381 }
382
383 /*
384 * brief enable a module, open clock and remove reset signal.
385 */
module_enable(module_id id)386 hi_void module_enable(module_id id)
387 {
388 module_clock(id, HI_TRUE);
389 module_reset(id, HI_FALSE);
390 return;
391 }
392
393 /*
394 * brief disable a module, close clock and set reset signal.
395 */
module_disable(module_id id)396 hi_void module_disable(module_id id)
397 {
398 module_reset(id, HI_TRUE);
399 module_clock(id, HI_FALSE);
400 return;
401 }
402
403 /*
404 * brief get attribute of module.
405 */
module_get_attr(module_id id,hi_u32 * int_valid,hi_u32 * int_num,const hi_char ** name)406 hi_void module_get_attr(module_id id, hi_u32 *int_valid, hi_u32 *int_num, const hi_char **name)
407 {
408 if (id >= CRYPTO_MODULE_ID_CNT) {
409 hi_log_error("invalid module id %d\n", id);
410 return;
411 }
412
413 *int_valid = g_hard_info_table[id].int_valid;
414 *int_num = g_hard_info_table[id].int_num;
415 if (name != HI_NULL) {
416 *name = g_hard_info_table[id].name;
417 }
418
419 return;
420 }
421
422 /*
423 * brief set module irq.
424 */
module_set_irq(module_id id,hi_u32 irq)425 hi_void module_set_irq(module_id id, hi_u32 irq)
426 {
427 if (id >= CRYPTO_MODULE_ID_CNT) {
428 hi_log_error("invalid module id %d\n", id);
429 return;
430 }
431
432 g_hard_info_table[id].int_num = irq;
433 hi_log_info("%s set irq number 0x%x\n", g_hard_info_table[id].name, irq);
434 }
435
436 /*
437 * brief read a register.
438 */
module_reg_read(module_id id,hi_u32 offset)439 hi_u32 module_reg_read(module_id id, hi_u32 offset)
440 {
441 hi_u32 val;
442 hi_void *addr = HI_NULL;
443 hi_s32 ret;
444
445 hi_log_chk_param_return(id >= CRYPTO_MODULE_ID_CNT);
446 hi_log_chk_param_return(offset >= g_hard_info_table[id].reg_addr_size);
447
448 /* tee may be read trng before cipher module init. */
449 if (g_hard_info_table[id].reg_addr_via == HI_NULL) {
450 ret = module_addr_map();
451 if (ret != HI_SUCCESS) {
452 hi_log_print_func_err(module_addr_map, ret);
453 return 0;
454 }
455 }
456
457 /* get the absolute address of reg. */
458 addr = (hi_u8 *)(g_hard_info_table[id].reg_addr_via) + offset;
459 val = crypto_read(addr);
460
461 return val;
462 }
463
464 /*
465 * brief write a register.
466 */
module_reg_write(module_id mod_id,hi_u32 offset,hi_u32 val)467 hi_void module_reg_write(module_id mod_id, hi_u32 offset, hi_u32 val)
468 {
469 hi_void *addr = HI_NULL;
470 hi_s32 ret;
471
472 /* check if module is valid. */
473 if (mod_id >= CRYPTO_MODULE_ID_CNT) {
474 hi_log_error("error, invalid mod_id %d\n", mod_id);
475 return;
476 }
477
478 /* check if offset is valid. */
479 if (offset >= g_hard_info_table[mod_id].reg_addr_size) {
480 hi_log_error("error, reg offset overflow 0x%x\n", offset);
481 return;
482 }
483
484 /* tee may be read trng before cipher module init. */
485 if (g_hard_info_table[mod_id].reg_addr_via == HI_NULL) {
486 ret = module_addr_map();
487 if (ret != HI_SUCCESS) {
488 hi_log_print_func_err(module_addr_map, ret);
489 return;
490 }
491 }
492
493 /* get the absolute address of reg. */
494 addr = (hi_u8 *)g_hard_info_table[mod_id].reg_addr_via + offset;
495 crypto_write(addr, val);
496
497 return;
498 }
499
500 /*
501 * brief Initialize the channel list.
502 */
crypto_channel_init(channel_context * ctx,hi_u32 num,hi_u32 ctx_size)503 hi_s32 crypto_channel_init(channel_context *ctx, hi_u32 num, hi_u32 ctx_size)
504 {
505 hi_u32 size;
506 hi_u32 i;
507 hi_u8 *buf = HI_NULL;
508
509 hi_log_func_enter();
510
511 hi_log_chk_param_return(ctx == HI_NULL);
512
513 /* clear context. */
514 size = sizeof(channel_context) * num;
515 (hi_void)memset_s(ctx, size, 0, size);
516
517 /* set context buffer. */
518 if (ctx_size > 0) {
519 buf = (hi_u8 *)crypto_malloc(ctx_size * num);
520 if (buf == HI_NULL) {
521 return HI_ERR_CIPHER_FAILED_MEM;
522 }
523 (hi_void)memset_s(buf, ctx_size * num, 0, ctx_size * num);
524
525 /* the buffer address is stored at ctx[0].ctx. */
526 for (i = 0; i < num; i++) {
527 ctx[i].ctx = buf;
528 buf += ctx_size;
529 }
530 }
531
532 hi_log_func_exit();
533 return HI_SUCCESS;
534 }
535
536 /*
537 * brief denit the channel list.
538 */
crypto_channel_deinit(channel_context * ctx,hi_u32 num)539 hi_s32 crypto_channel_deinit(channel_context *ctx, hi_u32 num)
540 {
541 hi_u32 size;
542
543 hi_log_func_enter();
544
545 hi_log_chk_param_return(ctx == HI_NULL);
546
547 /* the buffer address is stored at ctx[0].ctx. */
548 if (ctx[0].ctx != HI_NULL) {
549 crypto_free(ctx[0].ctx);
550 ctx[0].ctx = HI_NULL;
551 }
552
553 /* clear context. */
554 size = sizeof(channel_context) * num;
555 (hi_void)memset_s(ctx, size, 0, size);
556
557 hi_log_func_exit();
558 return HI_SUCCESS;
559 }
560
561 /*
562 * brief allocate a channel.
563 */
crypto_channel_alloc(channel_context * ctx,hi_u32 num,hi_u32 mask,hi_u32 * id)564 hi_s32 crypto_channel_alloc(channel_context *ctx, hi_u32 num, hi_u32 mask, hi_u32 *id)
565 {
566 hi_u32 i;
567
568 hi_log_func_enter();
569
570 hi_log_chk_param_return(ctx == HI_NULL);
571 hi_log_chk_param_return(id == HI_NULL);
572
573 for (i = 0; i < num; i++) {
574 /* check the valid channel. */
575 if (mask & (0x01 << i)) {
576 if (!ctx[i].open) { /* found a free channel. */
577 ctx[i].open = HI_TRUE; /* alloc channel. */
578 *id = i;
579 return HI_SUCCESS;
580 }
581 }
582 }
583
584 if (i == num) {
585 hi_log_error("error, all channels are busy.\n");
586 }
587
588 hi_log_func_exit();
589
590 return HI_ERR_CIPHER_BUSY;
591 }
592
593 /*
594 * brief free a channel.
595 */
crypto_channel_free(channel_context * ctx,hi_u32 num,hi_u32 id)596 hi_void crypto_channel_free(channel_context *ctx, hi_u32 num, hi_u32 id)
597 {
598 crypto_unused(num);
599
600 hi_log_func_enter();
601
602 /* free channel. */
603 ctx[id].open = HI_FALSE;
604
605 hi_log_func_exit();
606 return;
607 }
608
609 /*
610 * brief get the private data of channel.
611 */
crypto_channel_get_context(const channel_context * ctx,hi_u32 num,hi_u32 id)612 hi_void *crypto_channel_get_context(const channel_context *ctx, hi_u32 num, hi_u32 id)
613 {
614 if (ctx == HI_NULL) {
615 hi_log_error("crypto_channel_get_context() ctx is HI_NULL\n");
616 hi_log_print_err_code(HI_ERR_CIPHER_INVALID_POINT);
617 return HI_NULL;
618 }
619
620 if ((id >= num) || (!ctx[id].open)) {
621 hi_log_error("crypto_channel_get_context()- error, id %u, open %u, num %u\n", id, ctx[id].open, num);
622 hi_log_print_err_code(HI_ERR_CIPHER_INVALID_POINT);
623 return HI_NULL;
624 }
625
626 return ctx[id].ctx;
627 }
628
hex2str(hi_char buf[MUL_VAL_2],hi_u32 buf_len,hi_u8 val)629 hi_void hex2str(hi_char buf[MUL_VAL_2], hi_u32 buf_len, hi_u8 val)
630 {
631 hi_u8 high, low;
632
633 if (buf_len != MUL_VAL_2) {
634 return;
635 }
636
637 high = (val >> SHIFT_4BITS) & MAX_LOW_4BITS;
638 low = val & MAX_LOW_4BITS;
639
640 if (high <= 9) { /* 0 ~ 9. */
641 buf[WORD_IDX_0] = high + '0';
642 } else {
643 buf[WORD_IDX_0] = (high - 0x0A) + 'A'; /* A ~ F. */
644 }
645
646 if (low <= 9) { /* 0 ~ 9. */
647 buf[WORD_IDX_1] = low + '0';
648 } else { /* A ~ F. */
649 buf[WORD_IDX_1] = (low - 0x0A) + 'A';
650 }
651 }
652
crypto_calloc(size_t n,size_t size)653 hi_void *crypto_calloc(size_t n, size_t size)
654 {
655 hi_void *ptr = HI_NULL;
656
657 ptr = crypto_malloc(n * size);
658 if (ptr != HI_NULL) {
659 (hi_void)memset_s(ptr, n * size, 0, n * size);
660 }
661 return ptr;
662 }
663
get_rand(hi_void)664 hi_u32 get_rand(hi_void)
665 {
666 hi_s32 ret;
667 hi_u32 randnum = 0;
668
669 ret = cryp_trng_get_random(&randnum, -1);
670 if (ret != HI_SUCCESS) {
671 hi_log_print_func_err(cryp_trng_get_random, ret);
672 }
673
674 return randnum;
675 }
676
677 #ifdef CIPHER_DEBUG_TEST_SUPPORT
crypto_print_hex(const hi_char * name,hi_u8 * str,hi_u32 len)678 void crypto_print_hex(const hi_char *name, hi_u8 *str, hi_u32 len)
679 {
680 hi_u32 _i;
681 hi_u8 *_str = (hi_u8 *)(str);
682
683 if (name == HI_NULL) {
684 hi_log_error("name is null.\n");
685 return;
686 }
687
688 if (str == HI_NULL) {
689 hi_log_error("str is null.\n");
690 return;
691 }
692
693 if (len == 0) {
694 hi_log_error("len is 0.\n");
695 return;
696 }
697
698 HI_PRINT("[%s]:\n", (name));
699 for (_i = 0; _i < (len); _i++) {
700 if ((_i % PRINT_HEX_BLOCK_LEN == 0) && (_i != 0)) {
701 HI_PRINT("\n");
702 }
703
704 HI_PRINT("\\x%02x", *((_str) + _i));
705 }
706 HI_PRINT("\n");
707 }
708 #endif
709