1 /*
2 * Copyright (c) 2022 Winner Microelectronics Co., Ltd. All rights reserved.
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 /**************************************************************************
17 * File Name : utils.c
18 * Author :
19 * Version : 1.0
20 * Date :
21 * Description :
22 *
23 * Copyright (c) 2014 Winner Microelectronics Co., Ltd.
24 * All rights reserved.
25 *
26 ***************************************************************************/
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdarg.h>
31
32 #include "wm_mem.h"
33 #include "tls_common.h"
34 #include "wm_debug.h"
35 #include "utils.h"
36
37 static const u8 crc8_tbl[256] = {
38 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
39 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
40 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
41 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
42 0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d,
43 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
44 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51,
45 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
46 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05,
47 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
48 0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19,
49 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
50 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d,
51 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
52 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21,
53 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
54 0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95,
55 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
56 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89,
57 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
58 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad,
59 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
60 0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1,
61 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
62 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5,
63 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
64 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9,
65 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
66 0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd,
67 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
68 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1,
69 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
70 };
71
72 #ifndef isdigit
73 #define in_range(c, lo, up) ((u8)(c) >= (lo) && (u8)(c) <= (up))
74 #define isdigit(c) in_range((c), '0', '9')
75 #endif
chk_crc8(u8 * ptr,u32 len)76 int chk_crc8(u8 *ptr, u32 len)
77 {
78 u8 crc8;
79 u8 data;
80
81 crc8 = 0;
82 while (len-- != 0) {
83 data = *ptr++;
84 crc8 = crc8_tbl[crc8 ^ data];
85 }
86
87 if (crc8 == 0x00) {
88 return 0;
89 } else {
90 return -1;
91 }
92 }
93
94 // #ifndef TLS_CONFIG_FPGA
get_crc8(u8 * ptr,u32 len)95 u8 get_crc8(u8 *ptr, u32 len)
96 {
97 u8 crc8;
98 u8 data;
99
100 crc8 = 0;
101 while (len-- != 0) {
102 data = *ptr++;
103 crc8 = crc8_tbl[crc8 ^ data];
104 }
105
106 return crc8;
107 }
108 // #endif
109
calculate_crc8(u8 crc8,u8 * ptr,u32 len)110 u8 calculate_crc8(u8 crc8, u8 *ptr, u32 len)
111 {
112 u8 data;
113
114 while (len-- != 0) {
115 data = *ptr++;
116 crc8 = crc8_tbl[crc8 ^ data];
117 }
118
119 return crc8;
120 }
121
_cal_crc32(u32 crc_result,u8 data_8)122 static u32 _cal_crc32(u32 crc_result, u8 data_8)
123 {
124 u8 crc_out[32];
125 u8 crc_buf[32];
126 u8 in_data_buf[8];
127 u32 i;
128 u32 flag;
129
130 flag = 0x01;
131
132 for (i = 0; i < 32; i++) { // 32:loop cap
133 crc_out[i] = 0;
134 }
135
136 for (i = 0; i < 8; i++) { // 8:loop cap
137 in_data_buf[i] = (data_8 >> i) & flag;
138 }
139
140 for (i = 0; i < 32; i++) { // 32:loop cap
141 crc_buf[i] = (unsigned char)(crc_result >> i) & flag;
142 }
143
144 crc_out[0] = in_data_buf[1]^in_data_buf[7]^crc_buf[30]^crc_buf[24];
145 crc_out[1] = in_data_buf[0]^in_data_buf[1]^in_data_buf[6]^in_data_buf[7]^crc_buf[31]^crc_buf[30]^
146 crc_buf[25]^crc_buf[24];
147 crc_out[2] = in_data_buf[0]^in_data_buf[1]^in_data_buf[5]^in_data_buf[6]^in_data_buf[7]^crc_buf[31]^
148 crc_buf[30]^crc_buf[26]^crc_buf[25]^crc_buf[24];
149 crc_out[3] = in_data_buf[0]^in_data_buf[4]^in_data_buf[5]^in_data_buf[6]^crc_buf[31]^crc_buf[27]^
150 crc_buf[26]^crc_buf[25];
151 crc_out[4] = in_data_buf[1]^in_data_buf[3]^in_data_buf[4]^in_data_buf[5]^in_data_buf[7]^crc_buf[30]^
152 crc_buf[28]^crc_buf[27]^crc_buf[26]^crc_buf[24];
153 crc_out[5] = in_data_buf[0]^in_data_buf[1]^in_data_buf[2]^in_data_buf[3]^in_data_buf[4]^in_data_buf[6]^
154 in_data_buf[7]^crc_buf[31]^crc_buf[30]^crc_buf[29]^crc_buf[28]^crc_buf[27]^crc_buf[25]^crc_buf[24];
155 crc_out[6] = in_data_buf[0]^in_data_buf[1]^in_data_buf[2]^in_data_buf[3]^in_data_buf[5]^in_data_buf[6]^
156 crc_buf[31]^crc_buf[30]^crc_buf[29]^crc_buf[28]^crc_buf[26]^crc_buf[25];
157 crc_out[7] = in_data_buf[0]^in_data_buf[2]^in_data_buf[4]^in_data_buf[5]^in_data_buf[7]^crc_buf[31]^
158 crc_buf[29]^crc_buf[27]^crc_buf[26]^crc_buf[24];
159 crc_out[8] = in_data_buf[3]^in_data_buf[4]^in_data_buf[6]^in_data_buf[7]^crc_buf[28]^crc_buf[27]^
160 crc_buf[25]^crc_buf[24]^crc_buf[0];
161 crc_out[9] = in_data_buf[2]^in_data_buf[3]^in_data_buf[5]^in_data_buf[6]^crc_buf[29]^crc_buf[28]^
162 crc_buf[26]^crc_buf[25]^crc_buf[1];
163 crc_out[10] = in_data_buf[2]^in_data_buf[4]^in_data_buf[5]^in_data_buf[7]^crc_buf[29]^crc_buf[27]^
164 crc_buf[26]^crc_buf[24]^crc_buf[2];
165 crc_out[11] = in_data_buf[3]^in_data_buf[4]^in_data_buf[6]^in_data_buf[7]^crc_buf[28]^crc_buf[27]^
166 crc_buf[25]^crc_buf[24]^crc_buf[3];
167
168 crc_out[12] = in_data_buf[1]^in_data_buf[2]^in_data_buf[3]^in_data_buf[5]^in_data_buf[6]^in_data_buf[7]^
169 crc_buf[30]^crc_buf[29]^crc_buf[28]^crc_buf[26]^crc_buf[25]^crc_buf[24]^crc_buf[4];
170 crc_out[13] = in_data_buf[0]^in_data_buf[1]^in_data_buf[2]^in_data_buf[4]^in_data_buf[5]^in_data_buf[6]^
171 crc_buf[31]^crc_buf[30]^crc_buf[29]^crc_buf[27]^crc_buf[26]^crc_buf[25]^crc_buf[5];
172 crc_out[14] = in_data_buf[0]^in_data_buf[1]^in_data_buf[3]^in_data_buf[4]^in_data_buf[5]^
173 crc_buf[31]^crc_buf[30]^crc_buf[28]^crc_buf[27]^crc_buf[26]^crc_buf[6];
174 crc_out[15] = in_data_buf[0]^in_data_buf[2]^in_data_buf[3]^in_data_buf[4]^crc_buf[31]^
175 crc_buf[29]^crc_buf[28]^crc_buf[27]^crc_buf[7];
176 crc_out[16] = in_data_buf[2]^in_data_buf[3]^in_data_buf[7]^crc_buf[29]^crc_buf[28]^crc_buf[24]^crc_buf[8];
177 crc_out[17] = in_data_buf[1]^in_data_buf[2]^in_data_buf[6]^crc_buf[30]^crc_buf[29]^crc_buf[25]^crc_buf[9];
178 crc_out[18] = in_data_buf[0]^in_data_buf[1]^in_data_buf[5]^crc_buf[31]^crc_buf[30]^crc_buf[26]^crc_buf[10];
179 crc_out[19] = in_data_buf[0]^in_data_buf[4]^crc_buf[31]^crc_buf[27]^crc_buf[11];
180 crc_out[20] = in_data_buf[3]^crc_buf[28]^crc_buf[12];
181 crc_out[21] = in_data_buf[2]^crc_buf[29]^crc_buf[13];
182 crc_out[22] = in_data_buf[7]^crc_buf[24]^crc_buf[14];
183 crc_out[23] = in_data_buf[1]^in_data_buf[6]^in_data_buf[7]^crc_buf[30]^crc_buf[25]^crc_buf[24]^crc_buf[15];
184 crc_out[24] = in_data_buf[0]^in_data_buf[5]^in_data_buf[6]^crc_buf[31]^crc_buf[26]^crc_buf[25]^crc_buf[16];
185 crc_out[25] = in_data_buf[4]^in_data_buf[5]^crc_buf[27]^crc_buf[26]^crc_buf[17];
186 crc_out[26] = in_data_buf[1]^in_data_buf[3]^in_data_buf[4]^in_data_buf[7]^crc_buf[30]^
187 crc_buf[28]^crc_buf[27]^crc_buf[24]^crc_buf[18];
188 crc_out[27] = in_data_buf[0]^in_data_buf[2]^in_data_buf[3]^in_data_buf[6]^crc_buf[31]^
189 crc_buf[29]^crc_buf[28]^crc_buf[25]^crc_buf[19];
190 crc_out[28] = in_data_buf[1]^in_data_buf[2]^in_data_buf[5]^crc_buf[30]^crc_buf[29]^crc_buf[26]^crc_buf[20];
191 crc_out[29] = in_data_buf[0]^in_data_buf[1]^in_data_buf[4]^crc_buf[31]^crc_buf[30]^crc_buf[27]^crc_buf[21];
192 crc_out[30] = in_data_buf[0]^in_data_buf[3]^crc_buf[31]^crc_buf[28]^crc_buf[22];
193 crc_out[31] = in_data_buf[2]^crc_buf[23]^crc_buf[29];
194
195 crc_result = 0;
196 for (i = 0; i < 32; i++) { // 32:loop cap
197 if (crc_out[i]) {crc_result |= (1 << i);}
198 }
199
200 return crc_result;
201 }
202
203 // #ifndef TLS_CONFIG_FPGA
get_crc32(u8 * data,u32 data_size)204 u32 get_crc32(u8 *data, u32 data_size)
205 {
206 u32 i;
207 u32 val;
208 int crc_result = 0xffffffff;
209
210 for (i = 0; i < data_size; i++) {
211 crc_result = _cal_crc32(crc_result, data[i]);
212 }
213
214 val = 0;
215 for (i = 0; i < 32; i++) { // 32:loop cap
216 if ((crc_result>>i) & 0x1) {
217 val |= (1 << (31 - i)); // 31:byte alignment
218 }
219 }
220
221 TLS_DBGPRT_INFO("calculate crc -0x%x .\n", ~val);
222 return ~val;
223 }
224 // #endif
225
checksum(u32 * data,u32 length,u32 init)226 u32 checksum(u32 *data, u32 length, u32 init)
227 {
228 static long long sum = 0;
229 u32 checksum;
230 u32 i;
231
232 /*
233 Calculate the checksum.
234 */
235 if (!init) {
236 sum = 0;
237 }
238
239 for (i = 0; i < length; i++) {
240 sum += *(data + i);
241 }
242 checksum = ~((u32)(sum >> 32) + (u32)sum); // 32:byte alignment
243
244 return checksum;
245 }
246
atodec(char ch)247 int atodec(char ch)
248 {
249 int dec = -1;
250
251 if ((ch >= '0') && (ch <= '9')) {dec = ch - '0';}
252
253 return dec;
254 }
255
strtodec(int * dec,char * str)256 int strtodec(int *dec, char *str)
257 {
258 int i;
259 int dd;
260 int sign;
261 char *strs_tmp = str;
262
263 i = -1;
264 dd = 0;
265 sign = 1;
266
267 if (*strs_tmp == '-') {
268 strs_tmp++;
269 sign = -1;
270 }
271
272 while (*strs_tmp) {
273 i = atodec(*strs_tmp++);
274 if (i < 0) {
275 return -1;
276 }
277 dd = dd * 10 + i; // 10:byte alignment
278 }
279
280 *dec = dd*sign;
281
282 return ((i < 0) ? -1 : 0);
283 }
284
atohex(char ch)285 int atohex(char ch)
286 {
287 int hex;
288
289 hex = -1;
290
291 if ((ch >= '0') && (ch <= '9')) {
292 hex = ch - '0';
293 } else if ((ch >= 'a') && (ch <= 'f')) {
294 hex = ch - 'a' + 0xa;
295 } else if ((ch >= 'A') && (ch <= 'F')) {
296 hex = ch - 'A' + 0xa;
297 }
298
299 return hex;
300 }
301
strtohex(u32 * hex,char * str)302 int strtohex(u32 *hex, char *str)
303 {
304 int n;
305 int i;
306 u32 dd;
307 char *str_tmp = str;
308
309 n = -1;
310 i = 0;
311 dd = 0;
312
313 while (*str_tmp) {
314 n = atohex(*str_tmp++);
315 if (n < 0) {
316 return -1;
317 }
318 dd = (dd << 4) + n; // 4:byte alignment
319 if (++i > 8) { // 8:byte alignment
320 return -1;
321 }
322 }
323
324 *hex = dd;
325
326 return (n < 0 ? -1 : 0);
327 }
328
strtohexarray(u8 array[],int cnt,char * str)329 int strtohexarray(u8 array[], int cnt, char *str)
330 {
331 u8 tmp;
332 u8 *des;
333 int cnt_tmp = cnt;
334 char *str_tmp = str;
335 des = array;
336
337 while (cnt_tmp-- > 0) {
338 int hex = atohex(*str_tmp++);
339 if (hex < 0) {
340 return -1;
341 } else {
342 tmp = (hex << 4) & 0xf0; // 4:byte alignment
343 }
344
345 hex = atohex(*str_tmp++);
346 if (hex < 0) {
347 return -1;
348 } else {
349 tmp = tmp | (hex & 0x0f);
350 }
351
352 *des++ = (u8) tmp;
353 }
354
355 return ((*str_tmp==0) ? 0 : -1);
356 }
357
strtoip(u32 * ipadr,char * str)358 int strtoip(u32 *ipadr, char * str)
359 {
360 int n;
361 u32 i;
362 u32 ip;
363 char *head;
364 char *tail;
365
366 ip = 0;
367 head = str;
368 tail = str;
369
370 for (i = 0; i < 3;) { // 3:byte alignment
371 if (*tail == '.') {
372 i++;
373 *tail = 0;
374 ip <<= 8; // 8:byte alignment
375 if (strtodec(&n, head) < 0) {
376 return -1;
377 }
378 if ((n < 0) || (n > 255)) { // 255:byte alignment
379 return -1;
380 }
381 ip += n;
382 *tail = '.';
383 head = tail + 1;
384 }
385 tail++;
386 }
387
388 if (i < 3) { // 3:byte alignment
389 return -1;
390 }
391
392 ip <<= 8; // 8:byte alignment
393 if (strtodec(&n, head) < 0) {
394 return -1;
395 }
396 if ((n < 0) || (n > 255)) { // 255:byte alignment
397 return -1;
398 }
399 ip += n;
400
401 *ipadr = ip;
402
403 return ((ip == 0) ? -1 : 0);
404 }
405
iptostr(u32 ip,char * str)406 void iptostr(u32 ip, char *str)
407 {
408 int sret = sprintf(str, "%d.%d.%d.%d",
409 ((ip >> 24) & 0xff), ((ip >> 16) & 0xff), // 24:byte alignment, 16:byte alignment
410 ((ip >> 8) & 0xff), ((ip >> 0) & 0xff)); // 8:byte alignment
411 if (sret < 0) {
412 printf("sprintf error.\n");
413 }
414 }
415
mactostr(u8 mac[],char * str)416 void mactostr(u8 mac[], char *str)
417 {
418 int sret = sprintf(str, "%02x%02x%02x%02x%02x%02x",
419 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
420 if (sret < 0) {
421 printf("sprintf error.\n");
422 }
423 }
424
hex_to_digit(int c)425 int hex_to_digit(int c)
426 {
427 if (c >= '0' && c <= '9') {
428 return c - '0';
429 }
430 if (c >= 'A' && c <= 'F') {
431 return c - ('A' - 10); // 10:byte alignment
432 }
433 if (c >= 'a' && c <= 'f') {
434 return c - ('a' - 10); // 10:byte alignment
435 }
436 return -1;
437 }
438
digit_to_hex(int c)439 int digit_to_hex(int c)
440 {
441 if (c >= 0 && c <= 9) { // 9:byte alignment
442 return c + '0';
443 }
444 if (c >= 0xA && c <= 0xF) {
445 return c - 0xA + 'A' ;
446 }
447 return -1;
448 }
449
hexstr_to_unit(char * buf,u32 * d)450 int hexstr_to_unit(char *buf, u32 *d)
451 {
452 int i;
453 int len = strlen(buf);
454 *d = 0;
455
456 if (len > 8) { // 8:byte alignment
457 return -1;
458 }
459 for (i = 0; i < len; i++) {
460 int c = hex_to_digit(buf[i]);
461 if (c < 0) {
462 return -1;
463 }
464 *d = (u8)c | (*d << 4); // 4:byte alignment
465 }
466 return 0;
467 }
string_to_uint(char * buf,u32 * d)468 int string_to_uint(char *buf, u32 *d)
469 {
470 int i;
471 int len = strlen(buf);
472 if (len > 11 || len == 0) { // 11:长度大于11或长度等于0
473 return -1;
474 }
475 for (i = 0; i < len; i++) {
476 if (!isdigit(buf[i])) {
477 return -1;
478 }
479 }
480 *d = atoi(buf);
481 return 0;
482 }
483
string_to_ipaddr(const char * buf,u8 * addr)484 int string_to_ipaddr(const char *buf, u8 *addr)
485 {
486 int count = 0, rc = 0;
487 unsigned int in[4];
488 char c;
489
490 rc = sscanf(buf, "%u.%u.%u.%u%c",
491 &in[0], &in[1], &in[2], &in[3], &c);
492 if (rc != 4 && (rc != 5 || c != '\n')) { // 4:sscanf的返回值不等于4, 5:sscanf的返回值不等于5
493 return -1;
494 }
495 for (count = 0; count < 4; count++) {
496 if (in[count] > 255) { // 255:数组值大于255
497 return -1;
498 }
499 addr[count] = in[count];
500 }
501 return 0;
502 }
503
strdup(const char * s)504 char *strdup(const char *s)
505 {
506 char *ret;
507 int len;
508 len = strlen(s) + 1;
509 ret = tls_mem_alloc(len);
510 if (ret == NULL) {
511 return NULL;
512 }
513 memset_s(ret, sizeof(ret), 0, len);
514 memcpy_s(ret, sizeof(ret), s, len - 1);
515 return ret;
516 }
517
strndup(const char * s,size_t len)518 char *strndup(const char *s, size_t len)
519 {
520 char *ret;
521 ret = tls_mem_alloc(len + 1);
522 if (ret == NULL) {
523 return NULL;
524 }
525 memset_s(ret, sizeof(ret), 0, len + 1);
526 memcpy_s(ret, sizeof(ret), s, len);
527 return ret;
528 }
529
delay_cnt(int count)530 void delay_cnt(int count)
531 {
532 #ifdef TLS_CONFIG_CPU_XT804
533 volatile int delay = count;
534 #else
535 int delay = count;
536 #endif
537
538 while (delay--) {
539 }
540 }
541
dumpBuffer(char * name,char * buffer,int len)542 void dumpBuffer(char *name, char* buffer, int len)
543 {
544 #if 1
545 int i = 0;
546 printf("%s:\n", name);
547 for (; i < len; i++) {
548 printf("%02X, ", buffer[i]);
549 if ((i + 1) % 16 == 0) { // 16:byte alignment
550 printf("\n");
551 }
552 }
553 printf("\n");
554 #endif
555 }
dumpUint32(char * name,uint32_t * buffer,int len)556 void dumpUint32(char *name, uint32_t* buffer, int len)
557 {
558 int i = 0;
559 printf("%s:\n", name);
560 for (; i < len; i++) {
561 printf("%08x ", buffer[i]);
562 if ((i + 1) % 8 == 0) { // 8:byte alignment
563 printf("\n");
564 }
565 }
566 printf("\n");
567 }
568
strcasecmp(const char * s1,const char * s2)569 int strcasecmp(const char *s1, const char *s2)
570 {
571 const char *s1_tmp = s1;
572 const char *s2_tmp = s2;
573 while (*s1_tmp && *s2_tmp) {
574 char a = *s1_tmp++;
575 char b = *s2_tmp++;
576
577 if (a == b) {
578 continue;
579 }
580
581 if (a >= 'a' && a <= 'z') {
582 a -= 'a' - 'A';
583 }
584 if (b >= 'a' && b <= 'z') {
585 b -= 'a' - 'A';
586 }
587
588 if (a != b) {
589 return 1;
590 }
591 }
592 return 0;
593 }