1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright (c) 1999 by Sun Microsystems, Inc.
24 * All rights reserved.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 /*
30 * Library of support routines for UDFS data structures and conversions.
31 */
32 #include <stdio.h>
33 #include <string.h>
34 #include <strings.h>
35 #include <sys/time.h>
36 #include <sys/mutex.h>
37 #include <sys/vnode.h>
38 #include <sys/fs/udf_volume.h>
39 #include "udfs.h"
40
41 char *tagerrs[] = {
42 "no error",
43 "invalid checksum", /* TAGERR_CKSUM */
44 "unknown tag id", /* TAGERR_ID */
45 "invalid version", /* TAGERR_VERSION */
46 "CRC length too large", /* TAGERR_TOOBIG */
47 "invalid CRC", /* TAGERR_CRC */
48 "location mismatch" /* TAGERR_LOC */
49 };
50
51 #ifdef sparc
52 #define SWAP16(x) (((x) & 0xff) << 8 | ((x) >> 8) & 0xff)
53 #define SWAP32(x) (((x) & 0xff) << 24 | ((x) & 0xff00) << 8 | \
54 ((x) & 0xff0000) >> 8 | ((x) >> 24) & 0xff)
55 #define SWAP64(x) (SWAP32((x) >> 32) & 0xffffffff | SWAP32(x) << 32)
56 #else
57 #define SWAP16(x) (x)
58 #define SWAP32(x) (x)
59 #define SWAP64(x) (x)
60 #endif
61
62 static void ud_swap_ext_ad(struct extent_ad *);
63 static void ud_swap_tstamp(struct tstamp *);
64 static void ud_swap_icb_tag(struct icb_tag *);
65 void ud_swap_short_ad(struct short_ad *);
66 void ud_swap_long_ad(struct long_ad *);
67 static void ud_swap_pri_vol_desc(struct pri_vol_desc *);
68 static void ud_swap_vdp(struct vol_desc_ptr *);
69 static void ud_swap_iuvd(struct iuvd_desc *);
70 static void ud_swap_avdp(struct anch_vol_desc_ptr *);
71 static void ud_swap_part_desc(struct part_desc *);
72 static void ud_swap_log_desc(struct log_vol_desc *);
73 static void ud_swap_unall_desc(struct unall_spc_desc *);
74 static void ud_swap_lvint(struct log_vol_int_desc *);
75 static void ud_swap_fileset_desc(struct file_set_desc *);
76 static void ud_swap_term_desc(struct term_desc *);
77 static void ud_swap_file_id(struct file_id *);
78 static void ud_swap_file_entry(struct file_entry *, int);
79 static void ud_swap_alloc_ext(struct alloc_ext_desc *);
80 static void ud_swap_tstamp(tstamp_t *);
81 static void ud_swap_space_bitmap(struct space_bmap_desc *);
82 static uint16_t crc16(uint8_t *, int32_t, int32_t);
83
84 extern uint32_t ecma_version;
85
86 void
maketag(struct tag * itp,struct tag * otp)87 maketag(struct tag *itp, struct tag *otp)
88 {
89 int32_t sum, i;
90 uint8_t *cp;
91
92 if (itp != otp) {
93 bcopy((unsigned char *)(itp + 1), (unsigned char *)(otp + 1),
94 itp->tag_crc_len);
95 }
96
97 /* Swap fields */
98 switch (itp->tag_id) {
99 case UD_PRI_VOL_DESC:
100 ud_swap_pri_vol_desc((struct pri_vol_desc *)otp);
101 break;
102 case UD_ANCH_VOL_DESC:
103 ud_swap_avdp((struct anch_vol_desc_ptr *)otp);
104 break;
105 case UD_VOL_DESC_PTR:
106 ud_swap_vdp((struct vol_desc_ptr *)otp);
107 break;
108 case UD_IMPL_USE_DESC:
109 ud_swap_iuvd((struct iuvd_desc *)otp);
110 break;
111 case UD_PART_DESC:
112 ud_swap_part_desc((struct part_desc *)otp);
113 break;
114 case UD_LOG_VOL_DESC:
115 ud_swap_log_desc((struct log_vol_desc *)otp);
116 break;
117 case UD_UNALL_SPA_DESC:
118 ud_swap_unall_desc((struct unall_spc_desc *)otp);
119 break;
120 case UD_TERM_DESC:
121 ud_swap_term_desc((struct term_desc *)otp);
122 break;
123 case UD_LOG_VOL_INT:
124 /* LINTED */
125 ud_swap_lvint((struct log_vol_int_desc *)otp);
126 break;
127 case UD_FILE_SET_DESC:
128 ud_swap_fileset_desc((struct file_set_desc *)otp);
129 break;
130 case UD_FILE_ID_DESC:
131 ud_swap_file_id((struct file_id *)otp);
132 break;
133 case UD_ALLOC_EXT_DESC:
134 break;
135 case UD_INDIRECT_ENT:
136 break;
137 case UD_TERMINAL_ENT:
138 break;
139 case UD_FILE_ENTRY:
140 /* LINTED */
141 ud_swap_file_entry((struct file_entry *)otp, 0);
142 break;
143 case UD_EXT_ATTR_HDR:
144 break;
145 case UD_UNALL_SPA_ENT:
146 break;
147 case UD_SPA_BMAP_DESC:
148 ud_swap_space_bitmap((struct space_bmap_desc *)otp);
149 break;
150 case UD_PART_INT_DESC:
151 break;
152 }
153 otp->tag_id = SWAP16(itp->tag_id);
154 otp->tag_desc_ver = SWAP16(itp->tag_desc_ver);
155 otp->tag_cksum = otp->tag_res = 0;
156 otp->tag_sno = SWAP16(itp->tag_sno);
157 otp->tag_crc = SWAP16(crc16((unsigned char *)(otp+1),
158 itp->tag_crc_len, 0));
159 otp->tag_crc_len = SWAP16(itp->tag_crc_len);
160 otp->tag_loc = SWAP32(itp->tag_loc);
161
162 /*
163 * Now do checksum on tag itself
164 */
165 cp = (unsigned char *)otp;
166 sum = 0;
167 for (i = 0; i < sizeof (*otp); i++)
168 sum += *cp++;
169 otp->tag_cksum = sum;
170 }
171
172
173 int32_t
verifytag(struct tag * tp,uint32_t loc,struct tag * otp,int expect)174 verifytag(struct tag *tp, uint32_t loc, struct tag *otp, int expect)
175 {
176 uint8_t *cp;
177 uint32_t id, vers, length, tloc;
178 int sum, i;
179
180 sum = -tp->tag_cksum;
181 cp = (unsigned char *)tp;
182 for (i = 0; i < sizeof (*tp); i++)
183 sum += *cp++;
184 if ((sum & 0xff) != tp->tag_cksum)
185 return (TAGERR_CKSUM);
186 id = SWAP16(tp->tag_id);
187 if (id > 9 && id < 256 || id > 266 || (expect > 0 && id != expect))
188 return (TAGERR_ID);
189 vers = SWAP16(tp->tag_desc_ver);
190 if (vers > ecma_version)
191 return (TAGERR_VERSION);
192 length = SWAP16(tp->tag_crc_len);
193 if (length > MAXBSIZE)
194 return (TAGERR_TOOBIG);
195 if (crc16((unsigned char *)(tp+1), length, SWAP16(tp->tag_crc)) != 0)
196 return (TAGERR_CRC);
197 tloc = SWAP32(tp->tag_loc);
198 if ((int)loc != -1 && tloc != loc)
199 return (TAGERR_LOC);
200 if (!otp)
201 return (0);
202 otp->tag_id = id;
203 otp->tag_desc_ver = vers;
204 otp->tag_cksum = tp->tag_cksum;
205 otp->tag_res = 0;
206 otp->tag_sno = SWAP16(tp->tag_sno);
207 otp->tag_crc = SWAP16(tp->tag_crc);
208 otp->tag_crc_len = length;
209 otp->tag_loc = tloc;
210
211 if (tp != otp)
212 bcopy((unsigned char *)(tp + 1), (unsigned char *)(otp + 1),
213 otp->tag_crc_len);
214 /* Swap fields */
215 switch (otp->tag_id) {
216 case UD_PRI_VOL_DESC:
217 ud_swap_pri_vol_desc((struct pri_vol_desc *)otp);
218 break;
219 case UD_ANCH_VOL_DESC:
220 ud_swap_avdp((struct anch_vol_desc_ptr *)otp);
221 break;
222 case UD_VOL_DESC_PTR:
223 ud_swap_vdp((struct vol_desc_ptr *)otp);
224 break;
225 case UD_IMPL_USE_DESC:
226 ud_swap_iuvd((struct iuvd_desc *)otp);
227 break;
228 case UD_PART_DESC:
229 ud_swap_part_desc((struct part_desc *)otp);
230 break;
231 case UD_LOG_VOL_DESC:
232 ud_swap_log_desc((struct log_vol_desc *)otp);
233 break;
234 case UD_UNALL_SPA_DESC:
235 ud_swap_unall_desc((struct unall_spc_desc *)otp);
236 break;
237 case UD_TERM_DESC:
238 ud_swap_term_desc((struct term_desc *)otp);
239 break;
240 case UD_LOG_VOL_INT:
241 /* LINTED */
242 ud_swap_lvint((struct log_vol_int_desc *)otp);
243 break;
244 case UD_FILE_SET_DESC:
245 ud_swap_fileset_desc((struct file_set_desc *)otp);
246 break;
247 case UD_FILE_ID_DESC:
248 ud_swap_file_id((struct file_id *)otp);
249 break;
250 case UD_ALLOC_EXT_DESC:
251 ud_swap_alloc_ext((struct alloc_ext_desc *)otp);
252 break;
253 case UD_INDIRECT_ENT:
254 break;
255 case UD_TERMINAL_ENT:
256 break;
257 case UD_FILE_ENTRY:
258 /* LINTED */
259 ud_swap_file_entry((struct file_entry *)otp, 1);
260 break;
261 case UD_EXT_ATTR_HDR:
262 break;
263 case UD_UNALL_SPA_ENT:
264 break;
265 case UD_SPA_BMAP_DESC:
266 ud_swap_space_bitmap((struct space_bmap_desc *)otp);
267 break;
268 case UD_PART_INT_DESC:
269 break;
270 }
271 return (0);
272 }
273
274 static void
ud_swap_ext_ad(struct extent_ad * p)275 ud_swap_ext_ad(struct extent_ad *p)
276 {
277 p->ext_len = SWAP32(p->ext_len);
278 p->ext_loc = SWAP32(p->ext_loc);
279 }
280
281
282 /* ARGSUSED */
283 static void
ud_swap_regid(struct regid * p)284 ud_swap_regid(struct regid *p)
285 {
286 }
287
288 static void
ud_swap_icb_tag(struct icb_tag * p)289 ud_swap_icb_tag(struct icb_tag *p)
290 {
291 p->itag_prnde = SWAP32(p->itag_prnde);
292 p->itag_strategy = SWAP16(p->itag_strategy);
293 p->itag_param = SWAP16(p->itag_param);
294 p->itag_max_ent = SWAP16(p->itag_max_ent);
295 p->itag_lb_loc = SWAP32(p->itag_lb_loc);
296 p->itag_lb_prn = SWAP16(p->itag_lb_prn);
297 p->itag_flags = SWAP16(p->itag_flags);
298 }
299
300 void
ud_swap_short_ad(struct short_ad * p)301 ud_swap_short_ad(struct short_ad *p)
302 {
303 p->sad_ext_len = SWAP32(p->sad_ext_len);
304 p->sad_ext_loc = SWAP32(p->sad_ext_loc);
305 }
306
307 void
ud_swap_long_ad(struct long_ad * p)308 ud_swap_long_ad(struct long_ad *p)
309 {
310 p->lad_ext_len = SWAP32(p->lad_ext_len);
311 p->lad_ext_loc = SWAP32(p->lad_ext_loc);
312 p->lad_ext_prn = SWAP16(p->lad_ext_prn);
313 }
314
315 static void
ud_swap_pri_vol_desc(struct pri_vol_desc * p)316 ud_swap_pri_vol_desc(struct pri_vol_desc *p)
317 {
318 p->pvd_vdsn = SWAP32(p->pvd_vdsn);
319 p->pvd_pvdn = SWAP32(p->pvd_pvdn);
320 p->pvd_vsn = SWAP16(p->pvd_vsn);
321 p->pvd_mvsn = SWAP16(p->pvd_mvsn);
322 p->pvd_il = SWAP16(p->pvd_il);
323 p->pvd_mil = SWAP16(p->pvd_mil);
324 p->pvd_csl = SWAP32(p->pvd_csl);
325 p->pvd_mcsl = SWAP32(p->pvd_mcsl);
326 ud_swap_ext_ad(&p->pvd_vol_abs);
327 ud_swap_ext_ad(&p->pvd_vcn);
328 ud_swap_regid(&p->pvd_appl_id);
329 ud_swap_tstamp(&p->pvd_time);
330 ud_swap_regid(&p->pvd_ii);
331 p->pvd_pvdsl = SWAP32(p->pvd_pvdsl);
332 p->pvd_flags = SWAP16(p->pvd_flags);
333 }
334
335 static void
ud_swap_iuvd(struct iuvd_desc * p)336 ud_swap_iuvd(struct iuvd_desc *p)
337 {
338 p->iuvd_vdsn = SWAP32(p->iuvd_vdsn);
339 ud_swap_regid(&p->iuvd_ii);
340 ud_swap_regid(&p->iuvd_iid);
341 }
342
343 static void
ud_swap_vdp(struct vol_desc_ptr * p)344 ud_swap_vdp(struct vol_desc_ptr *p)
345 {
346 p->vdp_vdsn = SWAP32(p->vdp_vdsn);
347 ud_swap_ext_ad(&p->vdp_nvdse);
348 }
349
350 static void
ud_swap_avdp(struct anch_vol_desc_ptr * p)351 ud_swap_avdp(struct anch_vol_desc_ptr *p)
352 {
353 ud_swap_ext_ad(&p->avd_main_vdse);
354 ud_swap_ext_ad(&p->avd_res_vdse);
355 }
356
357 static void
ud_swap_part_desc(struct part_desc * p)358 ud_swap_part_desc(struct part_desc *p)
359 {
360 struct phdr_desc *php;
361
362 p->pd_vdsn = SWAP32(p->pd_vdsn);
363 p->pd_pflags = SWAP16(p->pd_pflags);
364 p->pd_pnum = SWAP16(p->pd_pnum);
365 ud_swap_regid(&p->pd_pcontents);
366 p->pd_acc_type = SWAP32(p->pd_acc_type);
367 p->pd_part_start = SWAP32(p->pd_part_start);
368 p->pd_part_length = SWAP32(p->pd_part_length);
369 ud_swap_regid(&p->pd_ii);
370 if (strncmp(p->pd_pcontents.reg_id, "+NSR", 4) == 0) {
371 /* LINTED */
372 php = (struct phdr_desc *)p->pd_pc_use;
373 ud_swap_short_ad(&php->phdr_ust);
374 ud_swap_short_ad(&php->phdr_usb);
375 ud_swap_short_ad(&php->phdr_it);
376 ud_swap_short_ad(&php->phdr_fst);
377 ud_swap_short_ad(&php->phdr_fsb);
378 }
379 }
380
381 static void
ud_swap_log_desc(struct log_vol_desc * p)382 ud_swap_log_desc(struct log_vol_desc *p)
383 {
384 p->lvd_vdsn = SWAP32(p->lvd_vdsn);
385 p->lvd_log_bsize = SWAP32(p->lvd_log_bsize);
386 ud_swap_regid(&p->lvd_dom_id);
387 ud_swap_long_ad(&p->lvd_lvcu);
388 p->lvd_mtbl_len = SWAP32(p->lvd_mtbl_len);
389 p->lvd_num_pmaps = SWAP32(p->lvd_num_pmaps);
390 ud_swap_regid(&p->lvd_ii);
391 ud_swap_ext_ad(&p->lvd_int_seq_ext);
392 }
393
394 static void
ud_swap_unall_desc(struct unall_spc_desc * p)395 ud_swap_unall_desc(struct unall_spc_desc *p)
396 {
397 p->ua_vdsn = SWAP32(p->ua_vdsn);
398 p->ua_nad = SWAP32(p->ua_nad);
399 }
400
401 static void
ud_swap_lvint(struct log_vol_int_desc * p)402 ud_swap_lvint(struct log_vol_int_desc *p)
403 {
404 struct lvid_iu *lvup;
405
406 ud_swap_tstamp(&p->lvid_tstamp);
407 p->lvid_int_type = SWAP32(p->lvid_int_type);
408 ud_swap_ext_ad(&p->lvid_nie);
409 p->lvid_npart = SWAP32(p->lvid_npart);
410 p->lvid_liu = SWAP32(p->lvid_liu);
411 p->lvid_uniqid = SWAP64(p->lvid_uniqid);
412 p->lvid_fst[0] = SWAP32(p->lvid_fst[0]);
413 p->lvid_fst[1] = SWAP32(p->lvid_fst[1]);
414
415 lvup = (struct lvid_iu *)&p->lvid_fst[2];
416 ud_swap_regid(&lvup->lvidiu_regid);
417 lvup->lvidiu_nfiles = SWAP32(lvup->lvidiu_nfiles);
418 lvup->lvidiu_ndirs = SWAP32(lvup->lvidiu_ndirs);
419 lvup->lvidiu_mread = SWAP16(lvup->lvidiu_mread);
420 lvup->lvidiu_mwrite = SWAP16(lvup->lvidiu_mwrite);
421 lvup->lvidiu_maxwr = SWAP16(lvup->lvidiu_maxwr);
422 }
423
424 static void
ud_swap_fileset_desc(struct file_set_desc * p)425 ud_swap_fileset_desc(struct file_set_desc *p)
426 {
427 ud_swap_tstamp(&p->fsd_time);
428 p->fsd_ilevel = SWAP16(p->fsd_ilevel);
429 p->fsd_mi_level = SWAP16(p->fsd_mi_level);
430 p->fsd_cs_list = SWAP32(p->fsd_cs_list);
431 p->fsd_mcs_list = SWAP32(p->fsd_mcs_list);
432 p->fsd_fs_no = SWAP32(p->fsd_fs_no);
433 p->fsd_fsd_no = SWAP32(p->fsd_fsd_no);
434 ud_swap_long_ad(&p->fsd_root_icb);
435 ud_swap_regid(&p->fsd_did);
436 ud_swap_long_ad(&p->fsd_next);
437 }
438
439 /* ARGSUSED */
440 static void
ud_swap_term_desc(struct term_desc * p)441 ud_swap_term_desc(struct term_desc *p)
442 {
443 }
444
445 static void
ud_swap_file_id(struct file_id * p)446 ud_swap_file_id(struct file_id *p)
447 {
448 p->fid_ver = SWAP16(p->fid_ver);
449 ud_swap_long_ad(&p->fid_icb);
450 p->fid_iulen = SWAP16(p->fid_iulen);
451 }
452
453 static void
ud_swap_alloc_ext(struct alloc_ext_desc * p)454 ud_swap_alloc_ext(struct alloc_ext_desc *p)
455 {
456 p->aed_rev_ael = SWAP32(p->aed_rev_ael);
457 p->aed_len_aed = SWAP32(p->aed_len_aed);
458 }
459
460 static void
ud_swap_space_bitmap(struct space_bmap_desc * p)461 ud_swap_space_bitmap(struct space_bmap_desc *p)
462 {
463 p->sbd_nbits = SWAP32(p->sbd_nbits);
464 p->sbd_nbytes = SWAP32(p->sbd_nbytes);
465 }
466
467 static void
ud_swap_file_entry(struct file_entry * p,int32_t rdflag)468 ud_swap_file_entry(struct file_entry *p, int32_t rdflag)
469 {
470 int32_t i;
471 short_ad_t *sap;
472 long_ad_t *lap;
473
474 /* Do Extended Attributes and Allocation Descriptors */
475 if (rdflag) {
476 p->fe_len_adesc = SWAP32(p->fe_len_adesc);
477 p->fe_len_ear = SWAP32(p->fe_len_ear);
478 ud_swap_icb_tag(&p->fe_icb_tag);
479 }
480 switch (p->fe_icb_tag.itag_flags & 0x3) {
481 case ICB_FLAG_SHORT_AD:
482 /* LINTED */
483 sap = (short_ad_t *)(p->fe_spec + p->fe_len_ear);
484 for (i = 0; i < p->fe_len_adesc / sizeof (short_ad_t);
485 i++, sap++)
486 ud_swap_short_ad(sap);
487 break;
488 case ICB_FLAG_LONG_AD:
489 /* LINTED */
490 lap = (long_ad_t *)(p->fe_spec + p->fe_len_ear);
491 for (i = 0; i < p->fe_len_adesc / sizeof (long_ad_t);
492 i++, lap++)
493 ud_swap_long_ad(lap);
494 break;
495 case ICB_FLAG_EXT_AD:
496 break;
497 case ICB_FLAG_ONE_AD:
498 break;
499 }
500 p->fe_uid = SWAP32(p->fe_uid);
501 p->fe_gid = SWAP32(p->fe_gid);
502 p->fe_perms = SWAP32(p->fe_perms);
503 p->fe_lcount = SWAP16(p->fe_lcount);
504 p->fe_rec_len = SWAP32(p->fe_rec_len);
505 p->fe_info_len = SWAP64(p->fe_info_len);
506 p->fe_lbr = SWAP64(p->fe_lbr);
507 ud_swap_tstamp(&p->fe_acc_time);
508 ud_swap_tstamp(&p->fe_mod_time);
509 ud_swap_tstamp(&p->fe_attr_time);
510 p->fe_ckpoint = SWAP32(p->fe_ckpoint);
511 ud_swap_long_ad(&p->fe_ea_icb);
512 ud_swap_regid(&p->fe_impl_id);
513 p->fe_uniq_id = SWAP64(p->fe_uniq_id);
514 if (!rdflag) {
515 p->fe_len_adesc = SWAP32(p->fe_len_adesc);
516 p->fe_len_ear = SWAP32(p->fe_len_ear);
517 ud_swap_icb_tag(&p->fe_icb_tag);
518 }
519 }
520
521 static void
ud_swap_tstamp(tstamp_t * tp)522 ud_swap_tstamp(tstamp_t *tp)
523 {
524 tp->ts_tzone = SWAP16(tp->ts_tzone);
525 tp->ts_year = SWAP16(tp->ts_year);
526 }
527
528 void
setcharspec(struct charspec * cp,int32_t type,uint8_t * info)529 setcharspec(struct charspec *cp, int32_t type, uint8_t *info)
530 {
531 cp->cs_type = type;
532 bzero(cp->cs_info, sizeof (cp->cs_info));
533 (void) strncpy(cp->cs_info, (int8_t *)info, sizeof (cp->cs_info));
534 }
535
536 static unsigned short crctab[] = {
537 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
538 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
539 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
540 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
541 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
542 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
543 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
544 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
545 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
546 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
547 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
548 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
549 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
550 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
551 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
552 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
553 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
554 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
555 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
556 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
557 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
558 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
559 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
560 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
561 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
562 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
563 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
564 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
565 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
566 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
567 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
568 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
569 };
570
571 static uint16_t
crc16(uint8_t * buf,int32_t size,int32_t rem)572 crc16(uint8_t *buf, int32_t size, int32_t rem)
573 {
574 uint16_t crc = 0;
575
576 while (size-- > 0)
577 crc = (crc << 8) ^ crctab[((crc >> 8) ^ *buf++) & 0xff];
578 return ((crc ^ rem) & 0xffff);
579 }
580