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