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