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
41char *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
62static void ud_swap_ext_ad(struct extent_ad *);
63static void ud_swap_tstamp(struct tstamp *);
64static void ud_swap_icb_tag(struct icb_tag *);
65void ud_swap_short_ad(struct short_ad *);
66void ud_swap_long_ad(struct long_ad *);
67static void ud_swap_pri_vol_desc(struct pri_vol_desc *);
68static void ud_swap_vdp(struct vol_desc_ptr *);
69static void ud_swap_iuvd(struct iuvd_desc *);
70static void ud_swap_avdp(struct anch_vol_desc_ptr *);
71static void ud_swap_part_desc(struct part_desc *);
72static void ud_swap_log_desc(struct log_vol_desc *);
73static void ud_swap_unall_desc(struct unall_spc_desc *);
74static void ud_swap_lvint(struct log_vol_int_desc *);
75static void ud_swap_fileset_desc(struct file_set_desc *);
76static void ud_swap_term_desc(struct term_desc *);
77static void ud_swap_file_id(struct file_id *);
78static void ud_swap_file_entry(struct file_entry *, int);
79static void ud_swap_alloc_ext(struct alloc_ext_desc *);
80static void ud_swap_tstamp(tstamp_t *);
81static void ud_swap_space_bitmap(struct space_bmap_desc *);
82static uint16_t crc16(uint8_t *, int32_t, int32_t);
83
84extern uint32_t ecma_version;
85
86void
87maketag(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
173int32_t
174verifytag(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
274static void
275ud_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 */
283static void
284ud_swap_regid(struct regid *p)
285{
286}
287
288static void
289ud_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
300void
301ud_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
307void
308ud_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
315static void
316ud_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
335static void
336ud_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
343static void
344ud_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
350static void
351ud_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
357static void
358ud_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
381static void
382ud_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
394static void
395ud_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
401static void
402ud_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
424static void
425ud_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 */
440static void
441ud_swap_term_desc(struct term_desc *p)
442{
443}
444
445static void
446ud_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
453static void
454ud_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
460static void
461ud_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
467static void
468ud_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
521static void
522ud_swap_tstamp(tstamp_t *tp)
523{
524	tp->ts_tzone = SWAP16(tp->ts_tzone);
525	tp->ts_year = SWAP16(tp->ts_year);
526}
527
528void
529setcharspec(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
536static 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
571static uint16_t
572crc16(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