2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2017, Fedor Uporov
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/types.h>
35 #include <sys/kernel.h>
36 #include <sys/malloc.h>
37 #include <sys/vnode.h>
40 #include <sys/endian.h>
42 #include <sys/mount.h>
44 #include <fs/ext2fs/fs.h>
45 #include <fs/ext2fs/ext2fs.h>
46 #include <fs/ext2fs/ext2_dinode.h>
47 #include <fs/ext2fs/inode.h>
48 #include <fs/ext2fs/ext2_dir.h>
49 #include <fs/ext2fs/htree.h>
50 #include <fs/ext2fs/ext2_extattr.h>
51 #include <fs/ext2fs/ext2_extern.h>
53 #define EXT2_BG_INODE_BITMAP_CSUM_HI_END \
54 (offsetof(struct ext2_gd, ext4bgd_i_bmap_csum_hi) + \
57 #define EXT2_INODE_CSUM_HI_EXTRA_END \
58 (offsetof(struct ext2fs_dinode, e2di_chksum_hi) + sizeof(uint16_t) - \
61 #define EXT2_BG_BLOCK_BITMAP_CSUM_HI_LOCATION \
62 (offsetof(struct ext2_gd, ext4bgd_b_bmap_csum_hi) + \
66 ext2_sb_csum_set_seed(struct m_ext2fs *fs)
69 if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_CSUM_SEED))
70 fs->e2fs_csum_seed = fs->e2fs->e4fs_chksum_seed;
71 else if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM)) {
72 fs->e2fs_csum_seed = calculate_crc32c(~0, fs->e2fs->e2fs_uuid,
73 sizeof(fs->e2fs->e2fs_uuid));
76 fs->e2fs_csum_seed = 0;
80 ext2_sb_csum_verify(struct m_ext2fs *fs)
83 if (fs->e2fs->e4fs_chksum_type != EXT4_CRC32C_CHKSUM) {
85 "WARNING: mount of %s denied due bad sb csum type\n", fs->e2fs_fsmnt);
88 if (fs->e2fs->e4fs_sbchksum !=
89 calculate_crc32c(~0, (const char *)fs->e2fs,
90 offsetof(struct ext2fs, e4fs_sbchksum))) {
92 "WARNING: mount of %s denied due bad sb csum=0x%x, expected=0x%x - run fsck\n",
93 fs->e2fs_fsmnt, fs->e2fs->e4fs_sbchksum, calculate_crc32c(~0,
94 (const char *)fs->e2fs, offsetof(struct ext2fs, e4fs_sbchksum)));
102 ext2_sb_csum_set(struct m_ext2fs *fs)
105 fs->e2fs->e4fs_sbchksum = calculate_crc32c(~0, (const char *)fs->e2fs,
106 offsetof(struct ext2fs, e4fs_sbchksum));
110 ext2_extattr_blk_csum(struct inode *ip, uint64_t facl,
111 struct ext2fs_extattr_header *header)
114 uint32_t crc, old_crc;
118 old_crc = header->h_checksum;
120 header->h_checksum = 0;
121 crc = calculate_crc32c(fs->e2fs_csum_seed, (uint8_t *)&facl, sizeof(facl));
122 crc = calculate_crc32c(crc, (uint8_t *)header, fs->e2fs_bsize);
123 header->h_checksum = old_crc;
129 ext2_extattr_blk_csum_verify(struct inode *ip, struct buf *bp)
131 struct ext2fs_extattr_header *header;
133 header = (struct ext2fs_extattr_header *)bp->b_data;
135 if (EXT2_HAS_RO_COMPAT_FEATURE(ip->i_e2fs, EXT2F_ROCOMPAT_METADATA_CKSUM) &&
136 (header->h_checksum != ext2_extattr_blk_csum(ip, ip->i_facl, header))) {
137 printf("WARNING: bad extattr csum detected, ip=%lu - run fsck\n",
138 (unsigned long)ip->i_number);
146 ext2_extattr_blk_csum_set(struct inode *ip, struct buf *bp)
148 struct ext2fs_extattr_header *header;
150 if (!EXT2_HAS_RO_COMPAT_FEATURE(ip->i_e2fs, EXT2F_ROCOMPAT_METADATA_CKSUM))
153 header = (struct ext2fs_extattr_header *)bp->b_data;
154 header->h_checksum = ext2_extattr_blk_csum(ip, ip->i_facl, header);
158 ext2_init_dirent_tail(struct ext2fs_direct_tail *tp)
160 memset(tp, 0, sizeof(struct ext2fs_direct_tail));
161 tp->e2dt_rec_len = sizeof(struct ext2fs_direct_tail);
162 tp->e2dt_reserved_ft = EXT2_FT_DIR_CSUM;
165 struct ext2fs_direct_tail *
166 ext2_dirent_get_tail(struct inode *ip, struct ext2fs_direct_2 *ep)
168 struct ext2fs_direct_2 *dep;
170 struct ext2fs_direct_tail *tp;
171 unsigned int rec_len;
174 top = EXT2_DIRENT_TAIL(ep, ip->i_e2fs->e2fs_bsize);
175 rec_len = dep->e2d_reclen;
177 while (rec_len && !(rec_len & 0x3)) {
178 dep = (struct ext2fs_direct_2 *)(((char *)dep) + rec_len);
179 if ((void *)dep >= top)
181 rec_len = dep->e2d_reclen;
187 tp = (struct ext2fs_direct_tail *)dep;
188 if (tp->e2dt_reserved_zero1 ||
189 tp->e2dt_rec_len != sizeof(struct ext2fs_direct_tail) ||
190 tp->e2dt_reserved_zero2 ||
191 tp->e2dt_reserved_ft != EXT2_FT_DIR_CSUM)
198 ext2_dirent_csum(struct inode *ip, struct ext2fs_direct_2 *ep, int size)
202 uint32_t inum, gen, crc;
210 crc = calculate_crc32c(fs->e2fs_csum_seed, (uint8_t *)&inum, sizeof(inum));
211 crc = calculate_crc32c(crc, (uint8_t *)&gen, sizeof(gen));
212 crc = calculate_crc32c(crc, (uint8_t *)buf, size);
218 ext2_dirent_csum_verify(struct inode *ip, struct ext2fs_direct_2 *ep)
221 struct ext2fs_direct_tail *tp;
223 tp = ext2_dirent_get_tail(ip, ep);
227 calculated = ext2_dirent_csum(ip, ep, (char *)tp - (char *)ep);
228 if (calculated != tp->e2dt_checksum)
234 static struct ext2fs_htree_count *
235 ext2_get_dx_count(struct inode *ip, struct ext2fs_direct_2 *ep, int *offset)
237 struct ext2fs_direct_2 *dp;
238 struct ext2fs_htree_root_info *root;
241 if (ep->e2d_reclen == EXT2_BLOCK_SIZE(ip->i_e2fs))
243 else if (ep->e2d_reclen == 12) {
244 dp = (struct ext2fs_direct_2 *)(((char *)ep) + 12);
245 if (dp->e2d_reclen != EXT2_BLOCK_SIZE(ip->i_e2fs) - 12)
248 root = (struct ext2fs_htree_root_info *)(((char *)dp + 12));
249 if (root->h_reserved1 ||
250 root->h_info_len != sizeof(struct ext2fs_htree_root_info))
258 *offset = count_offset;
260 return ((struct ext2fs_htree_count *)(((char *)ep) + count_offset));
264 ext2_dx_csum(struct inode *ip, struct ext2fs_direct_2 *ep, int count_offset,
265 int count, struct ext2fs_htree_tail *tp)
270 uint32_t inum, old_csum, gen, crc;
276 size = count_offset + (count * sizeof(struct ext2fs_htree_entry));
277 old_csum = tp->ht_checksum;
282 crc = calculate_crc32c(fs->e2fs_csum_seed, (uint8_t *)&inum, sizeof(inum));
283 crc = calculate_crc32c(crc, (uint8_t *)&gen, sizeof(gen));
284 crc = calculate_crc32c(crc, (uint8_t *)buf, size);
285 crc = calculate_crc32c(crc, (uint8_t *)tp, sizeof(struct ext2fs_htree_tail));
286 tp->ht_checksum = old_csum;
292 ext2_dx_csum_verify(struct inode *ip, struct ext2fs_direct_2 *ep)
295 struct ext2fs_htree_count *cp;
296 struct ext2fs_htree_tail *tp;
297 int count_offset, limit, count;
299 cp = ext2_get_dx_count(ip, ep, &count_offset);
303 limit = cp->h_entries_max;
304 count = cp->h_entries_num;
305 if (count_offset + (limit * sizeof(struct ext2fs_htree_entry)) >
306 ip->i_e2fs->e2fs_bsize - sizeof(struct ext2fs_htree_tail))
309 tp = (struct ext2fs_htree_tail *)(((struct ext2fs_htree_entry *)cp) + limit);
310 calculated = ext2_dx_csum(ip, ep, count_offset, count, tp);
312 if (tp->ht_checksum != calculated)
319 ext2_dir_blk_csum_verify(struct inode *ip, struct buf *bp)
322 struct ext2fs_direct_2 *ep;
327 if (!EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM))
330 ep = (struct ext2fs_direct_2 *)bp->b_data;
332 if (ext2_dirent_get_tail(ip, ep) != NULL)
333 error = ext2_dirent_csum_verify(ip, ep);
334 else if (ext2_get_dx_count(ip, ep, NULL) != NULL)
335 error = ext2_dx_csum_verify(ip, ep);
338 printf("WARNING: bad directory csum detected, ip=%lu"
339 " - run fsck\n", (unsigned long)ip->i_number);
345 ext2_dirent_csum_set(struct inode *ip, struct ext2fs_direct_2 *ep)
348 struct ext2fs_direct_tail *tp;
352 if (!EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM))
355 tp = ext2_dirent_get_tail(ip, ep);
360 ext2_dirent_csum(ip, ep, (char *)tp - (char *)ep);
364 ext2_dx_csum_set(struct inode *ip, struct ext2fs_direct_2 *ep)
367 struct ext2fs_htree_count *cp;
368 struct ext2fs_htree_tail *tp;
369 int count_offset, limit, count;
373 if (!EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM))
376 cp = ext2_get_dx_count(ip, ep, &count_offset);
380 limit = cp->h_entries_max;
381 count = cp->h_entries_num;
382 if (count_offset + (limit * sizeof(struct ext2fs_htree_entry)) >
383 ip->i_e2fs->e2fs_bsize - sizeof(struct ext2fs_htree_tail))
386 tp = (struct ext2fs_htree_tail *)(((struct ext2fs_htree_entry *)cp) + limit);
387 tp->ht_checksum = ext2_dx_csum(ip, ep, count_offset, count, tp);
391 ext2_extent_blk_csum(struct inode *ip, struct ext4_extent_header *ehp)
395 uint32_t inum, gen, crc;
399 size = EXT4_EXTENT_TAIL_OFFSET(ehp) +
400 offsetof(struct ext4_extent_tail, et_checksum);
404 crc = calculate_crc32c(fs->e2fs_csum_seed, (uint8_t *)&inum, sizeof(inum));
405 crc = calculate_crc32c(crc, (uint8_t *)&gen, sizeof(gen));
406 crc = calculate_crc32c(crc, (uint8_t *)ehp, size);
412 ext2_extent_blk_csum_verify(struct inode *ip, void *data)
415 struct ext4_extent_header *ehp;
416 struct ext4_extent_tail *etp;
417 uint32_t provided, calculated;
421 if (!EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM))
424 ehp = (struct ext4_extent_header *)data;
425 etp = (struct ext4_extent_tail *)(((char *)ehp) +
426 EXT4_EXTENT_TAIL_OFFSET(ehp));
428 provided = etp->et_checksum;
429 calculated = ext2_extent_blk_csum(ip, ehp);
431 if (provided != calculated) {
432 printf("WARNING: bad extent csum detected, ip=%lu - run fsck\n",
433 (unsigned long)ip->i_number);
441 ext2_extent_blk_csum_set(struct inode *ip, void *data)
444 struct ext4_extent_header *ehp;
445 struct ext4_extent_tail *etp;
449 if (!EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM))
452 ehp = (struct ext4_extent_header *)data;
453 etp = (struct ext4_extent_tail *)(((char *)data) +
454 EXT4_EXTENT_TAIL_OFFSET(ehp));
456 etp->et_checksum = ext2_extent_blk_csum(ip,
457 (struct ext4_extent_header *)data);
461 ext2_gd_i_bitmap_csum_verify(struct m_ext2fs *fs, int cg, struct buf *bp)
463 uint32_t hi, provided, calculated;
465 if (!EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM))
468 provided = fs->e2fs_gd[cg].ext4bgd_i_bmap_csum;
469 calculated = calculate_crc32c(fs->e2fs_csum_seed, bp->b_data,
470 fs->e2fs->e2fs_ipg / 8);
471 if (fs->e2fs->e3fs_desc_size >= EXT2_BG_INODE_BITMAP_CSUM_HI_END) {
472 hi = fs->e2fs_gd[cg].ext4bgd_i_bmap_csum_hi;
473 provided |= (hi << 16);
475 calculated &= 0xFFFF;
477 if (provided != calculated) {
478 printf("WARNING: bad inode bitmap csum detected, "
479 "cg=%d - run fsck\n", cg);
487 ext2_gd_i_bitmap_csum_set(struct m_ext2fs *fs, int cg, struct buf *bp)
491 if (!EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM))
494 csum = calculate_crc32c(fs->e2fs_csum_seed, bp->b_data,
495 fs->e2fs->e2fs_ipg / 8);
496 fs->e2fs_gd[cg].ext4bgd_i_bmap_csum = csum & 0xFFFF;
497 if (fs->e2fs->e3fs_desc_size >= EXT2_BG_INODE_BITMAP_CSUM_HI_END)
498 fs->e2fs_gd[cg].ext4bgd_i_bmap_csum_hi = csum >> 16;
502 ext2_gd_b_bitmap_csum_verify(struct m_ext2fs *fs, int cg, struct buf *bp)
504 uint32_t hi, provided, calculated, size;
506 if (!EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM))
509 size = fs->e2fs_fpg / 8;
510 provided = fs->e2fs_gd[cg].ext4bgd_b_bmap_csum;
511 calculated = calculate_crc32c(fs->e2fs_csum_seed, bp->b_data, size);
512 if (fs->e2fs->e3fs_desc_size >= EXT2_BG_BLOCK_BITMAP_CSUM_HI_LOCATION) {
513 hi = fs->e2fs_gd[cg].ext4bgd_b_bmap_csum_hi;
514 provided |= (hi << 16);
516 calculated &= 0xFFFF;
518 if (provided != calculated) {
519 printf("WARNING: bad block bitmap csum detected, "
520 "cg=%d - run fsck\n", cg);
528 ext2_gd_b_bitmap_csum_set(struct m_ext2fs *fs, int cg, struct buf *bp)
532 if (!EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM))
535 size = fs->e2fs_fpg / 8;
536 csum = calculate_crc32c(fs->e2fs_csum_seed, bp->b_data, size);
537 fs->e2fs_gd[cg].ext4bgd_b_bmap_csum = csum & 0xFFFF;
538 if (fs->e2fs->e3fs_desc_size >= EXT2_BG_BLOCK_BITMAP_CSUM_HI_LOCATION)
539 fs->e2fs_gd[cg].ext4bgd_b_bmap_csum_hi = csum >> 16;
543 ext2_ei_csum(struct inode *ip, struct ext2fs_dinode *ei)
546 uint32_t inode_csum_seed, inum, gen, crc;
547 uint16_t dummy_csum = 0;
548 unsigned int offset, csum_size;
551 offset = offsetof(struct ext2fs_dinode, e2di_chksum_lo);
552 csum_size = sizeof(dummy_csum);
554 crc = calculate_crc32c(fs->e2fs_csum_seed,
555 (uint8_t *)&inum, sizeof(inum));
557 inode_csum_seed = calculate_crc32c(crc,
558 (uint8_t *)&gen, sizeof(gen));
560 crc = calculate_crc32c(inode_csum_seed, (uint8_t *)ei, offset);
561 crc = calculate_crc32c(crc, (uint8_t *)&dummy_csum, csum_size);
563 crc = calculate_crc32c(crc, (uint8_t *)ei + offset,
564 E2FS_REV0_INODE_SIZE - offset);
566 if (EXT2_INODE_SIZE(fs) > E2FS_REV0_INODE_SIZE) {
567 offset = offsetof(struct ext2fs_dinode, e2di_chksum_hi);
568 crc = calculate_crc32c(crc, (uint8_t *)ei +
569 E2FS_REV0_INODE_SIZE, offset - E2FS_REV0_INODE_SIZE);
571 if ((EXT2_INODE_SIZE(ip->i_e2fs) > E2FS_REV0_INODE_SIZE &&
572 ei->e2di_extra_isize >= EXT2_INODE_CSUM_HI_EXTRA_END)) {
573 crc = calculate_crc32c(crc, (uint8_t *)&dummy_csum,
578 crc = calculate_crc32c(crc, (uint8_t *)ei + offset,
579 EXT2_INODE_SIZE(fs) - offset);
586 ext2_ei_csum_verify(struct inode *ip, struct ext2fs_dinode *ei)
589 const static struct ext2fs_dinode ei_zero;
590 uint32_t hi, provided, calculated;
594 if (!EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM))
597 provided = ei->e2di_chksum_lo;
598 calculated = ext2_ei_csum(ip, ei);
600 if ((EXT2_INODE_SIZE(fs) > E2FS_REV0_INODE_SIZE &&
601 ei->e2di_extra_isize >= EXT2_INODE_CSUM_HI_EXTRA_END)) {
602 hi = ei->e2di_chksum_hi;
603 provided |= hi << 16;
605 calculated &= 0xFFFF;
607 if (provided != calculated) {
609 * If it is first time used dinode,
610 * it is expected that it will be zeroed
611 * and we will not return checksum error in this case.
613 if (!memcmp(ei, &ei_zero, sizeof(struct ext2fs_dinode)))
623 ext2_ei_csum_set(struct inode *ip, struct ext2fs_dinode *ei)
630 if (!EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM))
633 crc = ext2_ei_csum(ip, ei);
635 ei->e2di_chksum_lo = crc & 0xFFFF;
636 if ((EXT2_INODE_SIZE(fs) > E2FS_REV0_INODE_SIZE &&
637 ei->e2di_extra_isize >= EXT2_INODE_CSUM_HI_EXTRA_END))
638 ei->e2di_chksum_hi = crc >> 16;
642 ext2_crc16(uint16_t crc, const void *buffer, unsigned int len)
644 const unsigned char *cp = buffer;
645 /* CRC table for the CRC-16. The poly is 0x8005 (x16 + x15 + x2 + 1). */
646 static uint16_t const crc16_table[256] = {
647 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
648 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
649 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
650 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
651 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
652 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
653 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
654 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
655 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
656 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
657 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
658 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
659 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
660 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
661 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
662 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
663 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
664 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
665 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
666 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
667 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
668 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
669 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
670 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
671 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
672 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
673 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
674 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
675 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
676 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
677 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
678 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
682 crc = (((crc >> 8) & 0xffU) ^
683 crc16_table[(crc ^ *cp++) & 0xffU]) & 0x0000ffffU;
688 ext2_gd_csum(struct m_ext2fs *fs, uint32_t block_group, struct ext2_gd *gd)
692 uint16_t crc, dummy_csum;
694 offset = offsetof(struct ext2_gd, ext4bgd_csum);
696 if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM)) {
697 csum32 = calculate_crc32c(fs->e2fs_csum_seed,
698 (uint8_t *)&block_group, sizeof(block_group));
699 csum32 = calculate_crc32c(csum32, (uint8_t *)gd, offset);
701 csum32 = calculate_crc32c(csum32, (uint8_t *)&dummy_csum,
703 offset += sizeof(dummy_csum);
704 if (offset < fs->e2fs->e3fs_desc_size)
705 csum32 = calculate_crc32c(csum32, (uint8_t *)gd + offset,
706 fs->e2fs->e3fs_desc_size - offset);
708 crc = csum32 & 0xFFFF;
710 } else if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_GDT_CSUM)) {
711 crc = ext2_crc16(~0, fs->e2fs->e2fs_uuid,
712 sizeof(fs->e2fs->e2fs_uuid));
713 crc = ext2_crc16(crc, (uint8_t *)&block_group,
714 sizeof(block_group));
715 crc = ext2_crc16(crc, (uint8_t *)gd, offset);
716 offset += sizeof(gd->ext4bgd_csum); /* skip checksum */
717 if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT) &&
718 offset < fs->e2fs->e3fs_desc_size)
719 crc = ext2_crc16(crc, (uint8_t *)gd + offset,
720 fs->e2fs->e3fs_desc_size - offset);
728 ext2_gd_csum_verify(struct m_ext2fs *fs, struct cdev *dev)
733 for (i = 0; i < fs->e2fs_gcount; i++) {
734 if (fs->e2fs_gd[i].ext4bgd_csum !=
735 ext2_gd_csum(fs, i, &fs->e2fs_gd[i])) {
737 "WARNING: mount of %s denied due bad gd=%d csum=0x%x, expected=0x%x - run fsck\n",
738 devtoname(dev), i, fs->e2fs_gd[i].ext4bgd_csum,
739 ext2_gd_csum(fs, i, &fs->e2fs_gd[i]));
749 ext2_gd_csum_set(struct m_ext2fs *fs)
753 for (i = 0; i < fs->e2fs_gcount; i++)
754 fs->e2fs_gd[i].ext4bgd_csum =
755 ext2_gd_csum(fs, i, &fs->e2fs_gd[i]);