xref: /illumos-gate/usr/src/cmd/fs.d/udfs/mkfs/udfslib.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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
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
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
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
284 ud_swap_regid(struct regid *p)
285 {
286 }
287 
288 static void
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
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
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
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
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
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
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
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
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
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
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
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
441 ud_swap_term_desc(struct term_desc *p)
442 {
443 }
444 
445 static void
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
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
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
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
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
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
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