Signed-off-by: Vladimir Serbinenko <phco...@gmail.com> --- grub-core/fs/zfs/zfs.c | 917 ++++++++++++++++++-------------- grub-core/fs/zfs/zfs_fletcher.c | 18 +- grub-core/fs/zfs/zfs_sha256.c | 14 +- grub-core/fs/zfs/zfscrypt.c | 2 +- include/grub/zfs/sa_impl.h | 1 + include/grub/zfs/spa.h | 9 + include/grub/zfs/zfs.h | 10 +- 7 files changed, 551 insertions(+), 420 deletions(-)
diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index afe821f9b..b88a2b032 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -193,12 +193,6 @@ typedef struct zio_checksum_info { const char *ci_name; /* descriptive name */ } zio_checksum_info_t; -typedef struct dnode_end -{ - dnode_phys_t dn; - grub_zfs_endian_t endian; -} dnode_end_t; - struct grub_zfs_device_desc { enum { DEVICE_LEAF, DEVICE_MIRROR, DEVICE_RAIDZ } type; @@ -223,7 +217,7 @@ struct grub_zfs_device_desc struct subvolume { - dnode_end_t mdn; + dnode_phys_t mdn; grub_uint64_t obj; grub_uint64_t case_insensitive; grub_size_t nkeys; @@ -247,10 +241,9 @@ struct grub_zfs_data dnode_phys_t *dnode_mdn; grub_uint64_t dnode_start; grub_uint64_t dnode_end; - grub_zfs_endian_t dnode_endian; - dnode_end_t mos; - dnode_end_t dnode; + dnode_phys_t mos; + dnode_phys_t dnode; struct subvolume subvol; struct grub_zfs_device_desc *devices_attached; @@ -273,7 +266,7 @@ struct grub_zfs_dir_ctx grub_err_t (*grub_zfs_decrypt) (grub_crypto_cipher_handle_t cipher, grub_uint64_t algo, - void *nonce, + const void *nonce, char *buf, grub_size_t size, const grub_uint32_t *expected_mac, grub_zfs_endian_t endian) = NULL; @@ -302,7 +295,7 @@ static const char *spa_feature_names[] = { static int check_feature(const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx); static grub_err_t -check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct grub_zfs_data* data ); +check_mos_features(dnode_phys_t *mosmdn_phys, struct grub_zfs_data* data ); static grub_err_t zlib_decompress (void *s, void *d, @@ -404,7 +397,7 @@ static decomp_entry_t decomp_table[ZIO_COMPRESS_FUNCTIONS] = { {"zstd", zstd_decompress}, /* ZIO_COMPRESS_ZSTD */ }; -static grub_err_t zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, +static grub_err_t zio_read_data (const blkptr_t * bp, void *buf, struct grub_zfs_data *data); /* @@ -449,6 +442,245 @@ static zio_checksum_info_t zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS] = { {zio_checksum_SHA256, 1, 0, "SHA256+MAC"}, }; +static inline void +grub_zfs_byteswap_u64(grub_uint64_t *val) +{ + *val = grub_swap_bytes64(*val); +} + +static inline void +grub_zfs_byteswap_u32(grub_uint32_t *val) +{ + *val = grub_swap_bytes32(*val); +} + +static inline void +grub_zfs_byteswap_u16(grub_uint16_t *val) +{ + *val = grub_swap_bytes16(*val); +} + +static void +grub_zfs_byteswap_checksum(zio_cksum_t *csum) +{ + for (int i = 0; i < 4; i++) + grub_zfs_byteswap_u64(&csum->zc_word[i]); +} + +static void +grub_zfs_byteswap_blkptr(blkptr_t *bp) +{ + for (int i = 0; i < SPA_DVAS_PER_BP; i++) + { + grub_zfs_byteswap_u64(&bp->blk_dva[i].dva_word[0]); + grub_zfs_byteswap_u64(&bp->blk_dva[i].dva_word[1]); + } + grub_zfs_byteswap_u64(&bp->blk_prop); + grub_zfs_byteswap_u64(&bp->blk_pad[0]); + grub_zfs_byteswap_u64(&bp->blk_pad[1]); + grub_zfs_byteswap_u64(&bp->blk_phys_birth); + grub_zfs_byteswap_u64(&bp->blk_birth); + grub_zfs_byteswap_u64(&bp->blk_fill); + + grub_zfs_byteswap_checksum(&bp->blk_cksum); +} + +static void +grub_zfs_byteswap_uberblock(uberblock_t *ub) +{ + grub_zfs_byteswap_u64(&ub->ub_magic); + grub_zfs_byteswap_u64(&ub->ub_version); + grub_zfs_byteswap_u64(&ub->ub_txg); + grub_zfs_byteswap_u64(&ub->ub_guid_sum); + grub_zfs_byteswap_u64(&ub->ub_timestamp); + grub_zfs_byteswap_blkptr(&ub->ub_rootbp); +} + +static void +grub_zfs_byteswap_type(void *buf, grub_size_t len, grub_uint8_t type); + +static void +grub_zfs_byteswap_dnode_proper(dnode_phys_t *dn) +{ + grub_zfs_byteswap_u16(&dn->dn_datablkszsec); + grub_zfs_byteswap_u16(&dn->dn_bonuslen); + grub_zfs_byteswap_u64(&dn->dn_maxblkid); + grub_zfs_byteswap_u64(&dn->dn_used); + grub_zfs_byteswap_u64(&dn->dn_pad3[0]); + grub_zfs_byteswap_u64(&dn->dn_pad3[1]); + grub_zfs_byteswap_u64(&dn->dn_pad3[2]); + grub_zfs_byteswap_u64(&dn->dn_pad3[3]); + + for (unsigned i = 0; i < dn->dn_nblkptr; i++) + grub_zfs_byteswap_blkptr(&dn->dn_blkptr[i]); + + if (dn->dn_flags & DNODE_FLAG_SPILL_BLKPTR) + grub_zfs_byteswap_blkptr(&dn->dn_spill); +} + +static void +grub_zfs_byteswap_dnode(dnode_phys_t *dn) +{ + grub_zfs_byteswap_dnode_proper(dn); + grub_zfs_byteswap_type(dn->dn_bonus, dn->dn_bonuslen, dn->dn_bonustype); +} + +static void +grub_zfs_byteswap_objset(objset_phys_t *os) +{ + grub_zfs_byteswap_dnode(&os->os_meta_dnode); + /* We ignore ZIL header. */ + grub_zfs_byteswap_u64(&os->os_type); + grub_zfs_byteswap_u64(&os->os_flags); + grub_zfs_byteswap_dnode(&os->os_userused_dnode); + grub_zfs_byteswap_dnode(&os->os_groupused_dnode); +} + +static void +grub_zfs_byteswap_u64_array(grub_uint64_t *arr, grub_size_t len) +{ + for (unsigned i = 0; i < len / 8; i++) + grub_zfs_byteswap_u64(arr + i); +} + +static void +grub_zfs_byteswap_mzap(mzap_phys_t *mz, grub_size_t objsize) +{ + grub_zfs_byteswap_u64(&mz->mz_block_type); + grub_zfs_byteswap_u64(&mz->mz_salt); + for (unsigned i = 0; i < 6; i++) + grub_zfs_byteswap_u64(&mz->mz_pad[i]); + for (unsigned i = 0; i < objsize / MZAP_ENT_LEN - 1; i++) + { + grub_zfs_byteswap_u64(&mz->mz_chunk[i].mze_value); + grub_zfs_byteswap_u32(&mz->mz_chunk[i].mze_cd); + grub_zfs_byteswap_u16(&mz->mz_chunk[i].mze_pad); + } +} + +static void +grub_zfs_byteswap_zap_leaf(zap_leaf_phys_t *lf, grub_size_t len) +{ + int blksft = zfs_log2 (len); + + grub_zfs_byteswap_u64(&lf->l_hdr.lh_block_type); + grub_zfs_byteswap_u64(&lf->l_hdr.lh_prefix); + grub_zfs_byteswap_u32(&lf->l_hdr.lh_magic); + grub_zfs_byteswap_u16(&lf->l_hdr.lh_nfree); + grub_zfs_byteswap_u16(&lf->l_hdr.lh_nentries); + grub_zfs_byteswap_u16(&lf->l_hdr.lh_prefix_len); + grub_zfs_byteswap_u16(&lf->l_hdr.lh_freelist); + + for (int i = 0; i < ZAP_LEAF_HASH_NUMENTRIES(blksft); i++) + grub_zfs_byteswap_u16(&lf->l_hash[i]); + + for (int i = 0; i < ZAP_LEAF_NUMCHUNKS (blksft); i++) { + zap_leaf_chunk_t *lc = ZAP_LEAF_CHUNK(lf, blksft, i); + struct zap_leaf_entry *le; + + switch (lc->l_free.lf_type) { + case ZAP_CHUNK_ENTRY: + le = &lc->l_entry; + + grub_zfs_byteswap_u16(&le->le_next); + grub_zfs_byteswap_u16(&le->le_name_chunk); + grub_zfs_byteswap_u16(&le->le_name_length); + grub_zfs_byteswap_u16(&le->le_value_chunk); + grub_zfs_byteswap_u16(&le->le_value_length); + grub_zfs_byteswap_u32(&le->le_cd); + grub_zfs_byteswap_u64(&le->le_hash); + break; + case ZAP_CHUNK_FREE: + grub_zfs_byteswap_u16(&lc->l_free.lf_next); + break; + case ZAP_CHUNK_ARRAY: + grub_zfs_byteswap_u16(&lc->l_array.la_next); + break; + default: + grub_dprintf("zfs", "Unknown leaf type %d\n", lc->l_free.lf_type); + } + } +} + +static void +grub_zfs_byteswap_zap(void *zp, grub_size_t len) +{ + grub_uint64_t block_type = *(grub_uint64_t *) zp; + if (block_type == grub_swap_bytes64_compile_time(ZBT_MICRO)) + grub_zfs_byteswap_mzap(zp, len); + else if (block_type == grub_swap_bytes64_compile_time(ZBT_HEADER)) + grub_zfs_byteswap_u64_array(zp, len); + else if (block_type == grub_swap_bytes64_compile_time(ZBT_LEAF)) + grub_zfs_byteswap_zap_leaf(zp, len); + else + grub_dprintf ("zfs", "unknown ZAP type"); +} + +static const dmu_object_byteswap_t byteswap_table[] = { + DMU_BSWAP_UINT8, DMU_BSWAP_ZAP, DMU_BSWAP_UINT64, DMU_BSWAP_UINT8, + DMU_BSWAP_UINT64, DMU_BSWAP_UINT64, DMU_BSWAP_UINT64, DMU_BSWAP_UINT64, + DMU_BSWAP_UINT64, DMU_BSWAP_UINT64, DMU_BSWAP_DNODE, DMU_BSWAP_OBJSET, + DMU_BSWAP_UINT64, DMU_BSWAP_ZAP, DMU_BSWAP_ZAP, DMU_BSWAP_ZAP, + + DMU_BSWAP_UINT64, DMU_BSWAP_ZNODE, DMU_BSWAP_OLDACL, DMU_BSWAP_UINT8, + DMU_BSWAP_ZAP, DMU_BSWAP_ZAP, DMU_BSWAP_ZAP, DMU_BSWAP_UINT8, + DMU_BSWAP_ZAP, DMU_BSWAP_UINT8, DMU_BSWAP_UINT64, DMU_BSWAP_ZAP, + DMU_BSWAP_ZAP, DMU_BSWAP_UINT8, DMU_BSWAP_UINT64, DMU_BSWAP_ZAP, + + DMU_BSWAP_ZAP, DMU_BSWAP_ACL, DMU_BSWAP_UINT8, DMU_BSWAP_UINT8, + DMU_BSWAP_UINT64, DMU_BSWAP_ZAP, DMU_BSWAP_ZAP, DMU_BSWAP_ZAP, + DMU_BSWAP_ZAP, DMU_BSWAP_ZAP, DMU_BSWAP_ZAP, DMU_BSWAP_ZAP, + DMU_BSWAP_UINT8, DMU_BSWAP_ZAP, DMU_BSWAP_ZAP, DMU_BSWAP_ZAP, + + DMU_BSWAP_ZAP, DMU_BSWAP_UINT8, DMU_BSWAP_ZAP, DMU_BSWAP_UINT64, + DMU_BSWAP_ZAP, DMU_BSWAP_UINT64, +}; + +static dmu_object_byteswap_t +get_byteswap_type(grub_uint8_t type) +{ + if (type & 0x80) + return type & DMU_OT_BYTESWAP_MASK; + + if (type < ARRAY_SIZE (byteswap_table)) + return byteswap_table[type]; + grub_fatal("Unknown type %d", type); +} + +static void +grub_zfs_byteswap_type(void *buf, grub_size_t len, grub_uint8_t type) +{ + /* + DMU_BSWAP_UINT16, + DMU_BSWAP_UINT32, + DMU_BSWAP_ZNODE, + DMU_BSWAP_OLDACL, + DMU_BSWAP_ACL, + + */ + switch (get_byteswap_type(type)) + { + case DMU_BSWAP_UINT8: + break; + case DMU_BSWAP_DNODE: + for (unsigned i = 0; i < len / sizeof(dnode_phys_t); i++) + grub_zfs_byteswap_dnode((dnode_phys_t *)buf + i); + break; + case DMU_BSWAP_OBJSET: + for (unsigned i = 0; i < len / sizeof(objset_phys_t); i++) + grub_zfs_byteswap_objset((objset_phys_t *)buf + i); + break; + case DMU_BSWAP_ZAP: + grub_zfs_byteswap_zap(buf, len); + break; + case DMU_BSWAP_UINT64: + grub_zfs_byteswap_u64_array(buf, len); + break; + default: + grub_fatal("Unknown type %d", type); + } +} + /* * zio_checksum_verify: Provides support for checksum verification. * @@ -482,8 +714,12 @@ zio_checksum_verify (zio_cksum_t zc, grub_uint32_t checksum, else ci->ci_func (buf, size, endian, &actual_cksum); - if (grub_memcmp (&actual_cksum, &zc, - checksum != ZIO_CHECKSUM_SHA256_MAC ? 32 : 20) != 0) + int cksumlen = checksum != ZIO_CHECKSUM_SHA256_MAC ? 32 : 20; + + if (ci->ci_eck && !GRUB_ZFS_IS_NATIVE_BYTEORDER(endian)) + grub_zfs_byteswap_checksum(&actual_cksum); + + if (grub_memcmp (&actual_cksum, &zc, cksumlen) != 0) { grub_dprintf ("zfs", "checksum %s verification failed\n", ci->ci_name); grub_dprintf ("zfs", "actual checksum %016llx %016llx %016llx %016llx\n", @@ -515,30 +751,14 @@ zio_checksum_verify (zio_cksum_t zc, grub_uint32_t checksum, static int vdev_uberblock_compare (uberblock_t * ub1, uberblock_t * ub2) { - grub_zfs_endian_t ub1_endian, ub2_endian; - if (grub_zfs_to_cpu64 (ub1->ub_magic, GRUB_ZFS_LITTLE_ENDIAN) - == UBERBLOCK_MAGIC) - ub1_endian = GRUB_ZFS_LITTLE_ENDIAN; - else - ub1_endian = GRUB_ZFS_BIG_ENDIAN; - if (grub_zfs_to_cpu64 (ub2->ub_magic, GRUB_ZFS_LITTLE_ENDIAN) - == UBERBLOCK_MAGIC) - ub2_endian = GRUB_ZFS_LITTLE_ENDIAN; - else - ub2_endian = GRUB_ZFS_BIG_ENDIAN; - - if (grub_zfs_to_cpu64 (ub1->ub_txg, ub1_endian) - < grub_zfs_to_cpu64 (ub2->ub_txg, ub2_endian)) + if (ub1->ub_txg < ub2->ub_txg) return -1; - if (grub_zfs_to_cpu64 (ub1->ub_txg, ub1_endian) - > grub_zfs_to_cpu64 (ub2->ub_txg, ub2_endian)) + if (ub1->ub_txg > ub2->ub_txg) return 1; - if (grub_zfs_to_cpu64 (ub1->ub_timestamp, ub1_endian) - < grub_zfs_to_cpu64 (ub2->ub_timestamp, ub2_endian)) + if (ub1->ub_timestamp < ub2->ub_timestamp) return -1; - if (grub_zfs_to_cpu64 (ub1->ub_timestamp, ub1_endian) - > grub_zfs_to_cpu64 (ub2->ub_timestamp, ub2_endian)) + if (ub1->ub_timestamp > ub2->ub_timestamp) return 1; return 0; @@ -615,34 +835,27 @@ find_bestub (uberblock_phys_t * ub_array, grub_errno = GRUB_ERR_NONE; continue; } + + if (ubptr->ubp_uberblock.ub_magic == grub_swap_bytes64_compile_time(UBERBLOCK_MAGIC)) + grub_zfs_byteswap_uberblock(&ubptr->ubp_uberblock); + if (ubbest == NULL || vdev_uberblock_compare (&(ubptr->ubp_uberblock), &(ubbest->ubp_uberblock)) > 0) ubbest = ubptr; } - if (!ubbest) + if (!ubbest) { grub_errno = err; + grub_dprintf("zfs", "no valid ub found. vdev_pys_sector=%lld\n", + (long long)desc->vdev_phys_sector); + } else { + grub_dprintf("zfs", "valid ub found. vdev_pys_sector=%lld\n", + (long long)desc->vdev_phys_sector); + } return ubbest; } -static inline grub_size_t -get_psize (blkptr_t * bp, grub_zfs_endian_t endian) -{ - return ((((grub_zfs_to_cpu64 ((bp)->blk_prop, endian) >> 16) & 0xffff) + 1) - << SPA_MINBLOCKSHIFT); -} - -static grub_uint64_t -dva_get_offset (const dva_t *dva, grub_zfs_endian_t endian) -{ - grub_dprintf ("zfs", "dva=%llx, %llx\n", - (unsigned long long) dva->dva_word[0], - (unsigned long long) dva->dva_word[1]); - return grub_zfs_to_cpu64 ((dva)->dva_word[1], - endian) << SPA_MINBLOCKSHIFT; -} - static grub_err_t zfs_fetch_nvlist (struct grub_zfs_device_desc *diskdesc, char **nvlist) { @@ -1054,7 +1267,7 @@ check_pool_label (struct grub_zfs_data *data, "bad vdev_phys_t.vp_zbt.zec_magic number"); } /* Now check the integrity of the vdev_phys_t structure though checksum. */ - ZIO_SET_CHECKSUM(&emptycksum, diskdesc->vdev_phys_sector << 9, 0, 0, 0); + ZIO_SET_CHECKSUM(&emptycksum, grub_cpu_to_zfs64(diskdesc->vdev_phys_sector << 9, endian), 0, 0, 0); err = zio_checksum_verify (emptycksum, ZIO_CHECKSUM_LABEL, endian, nvlist, VDEV_PHYS_SIZE); if (err) { @@ -1743,14 +1956,14 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, static grub_err_t read_dva (const dva_t *dva, - grub_zfs_endian_t endian, struct grub_zfs_data *data, + struct grub_zfs_data *data, void *buf, grub_size_t len) { grub_uint64_t offset; unsigned i; grub_err_t err = 0; int try = 0; - offset = dva_get_offset (dva, endian); + offset = DVA_GET_OFFSET(dva); for (try = 0; try < 2; try++) { @@ -1780,7 +1993,7 @@ read_dva (const dva_t *dva, * */ static grub_err_t -zio_read_gang (blkptr_t * bp, grub_zfs_endian_t endian, dva_t * dva, void *buf, +zio_read_gang (const blkptr_t * bp, const dva_t * dva, void *buf, struct grub_zfs_data *data) { zio_gbh_phys_t *zio_gb; @@ -1793,10 +2006,8 @@ zio_read_gang (blkptr_t * bp, grub_zfs_endian_t endian, dva_t * dva, void *buf, zio_gb = grub_malloc (SPA_GANGBLOCKSIZE); if (!zio_gb) return grub_errno; - grub_dprintf ("zfs", endian == GRUB_ZFS_LITTLE_ENDIAN ? "little-endian gang\n" - :"big-endian gang\n"); - err = read_dva (dva, endian, data, zio_gb, SPA_GANGBLOCKSIZE); + err = read_dva (dva, data, zio_gb, SPA_GANGBLOCKSIZE); if (err) { grub_free (zio_gb); @@ -1806,8 +2017,8 @@ zio_read_gang (blkptr_t * bp, grub_zfs_endian_t endian, dva_t * dva, void *buf, /* XXX */ /* self checksuming the gang block header */ ZIO_SET_CHECKSUM (&zc, DVA_GET_VDEV (dva), - dva_get_offset (dva, endian), bp->blk_birth, 0); - err = zio_checksum_verify (zc, ZIO_CHECKSUM_GANG_HEADER, endian, + DVA_GET_OFFSET (dva), bp->blk_birth, 0); + err = zio_checksum_verify (zc, ZIO_CHECKSUM_GANG_HEADER, BP_GET_BYTEORDER(bp), (char *) zio_gb, SPA_GANGBLOCKSIZE); if (err) { @@ -1815,20 +2026,22 @@ zio_read_gang (blkptr_t * bp, grub_zfs_endian_t endian, dva_t * dva, void *buf, return err; } - endian = (grub_zfs_to_cpu64 (bp->blk_prop, endian) >> 63) & 1; + if (!GRUB_ZFS_IS_NATIVE_BYTEORDER(BP_GET_BYTEORDER(bp))) + for (i = 0; i < SPA_GBH_NBLKPTRS; i++) + grub_zfs_byteswap_blkptr(&zio_gb->zg_blkptr[i]); for (i = 0; i < SPA_GBH_NBLKPTRS; i++) { if (BP_IS_HOLE(&zio_gb->zg_blkptr[i])) continue; - err = zio_read_data (&zio_gb->zg_blkptr[i], endian, buf, data); + err = zio_read_data (&zio_gb->zg_blkptr[i], buf, data); if (err) { grub_free (zio_gb); return err; } - buf = (char *) buf + get_psize (&zio_gb->zg_blkptr[i], endian); + buf = (char *) buf + BP_GET_PSIZE(&zio_gb->zg_blkptr[i]); } grub_free (zio_gb); return GRUB_ERR_NONE; @@ -1838,13 +2051,12 @@ zio_read_gang (blkptr_t * bp, grub_zfs_endian_t endian, dva_t * dva, void *buf, * Read in a block of raw data to buf. */ static grub_err_t -zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, void *buf, - struct grub_zfs_data *data) +zio_read_data (const blkptr_t * bp, void *buf, struct grub_zfs_data *data) { int i, psize; grub_err_t err = GRUB_ERR_NONE; - psize = get_psize (bp, endian); + psize = BP_GET_PSIZE (bp); /* pick a good dva from the block pointer */ for (i = 0; i < SPA_DVAS_PER_BP; i++) @@ -1852,10 +2064,10 @@ zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, void *buf, if (bp->blk_dva[i].dva_word[0] == 0 && bp->blk_dva[i].dva_word[1] == 0) continue; - if ((grub_zfs_to_cpu64 (bp->blk_dva[i].dva_word[1], endian)>>63) & 1) - err = zio_read_gang (bp, endian, &bp->blk_dva[i], buf, data); + if (DVA_GET_GANG(&bp->blk_dva[i])) + err = zio_read_gang (bp, &bp->blk_dva[i], buf, data); else - err = read_dva (&bp->blk_dva[i], endian, data, buf, psize); + err = read_dva (&bp->blk_dva[i], data, buf, psize); if (!err) return GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE; @@ -1906,7 +2118,7 @@ decode_embedded_bp_compressed(const blkptr_t *bp, void *buf) * and put the uncompressed data in buf. */ static grub_err_t -zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, +zio_read (const blkptr_t *bp, void **buf, grub_size_t *size, struct grub_zfs_data *data) { grub_size_t lsize, psize; @@ -1918,9 +2130,9 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, *buf = NULL; - checksum = (grub_zfs_to_cpu64((bp)->blk_prop, endian) >> 40) & 0xff; - comp = (grub_zfs_to_cpu64((bp)->blk_prop, endian)>>32) & 0x7f; - encrypted = ((grub_zfs_to_cpu64((bp)->blk_prop, endian) >> 60) & 3); + checksum = BP_GET_CHECKSUM(bp); + comp = BP_GET_COMPRESS(bp); + encrypted = BP_GET_PROP_BIT_61(bp); if (BP_IS_EMBEDDED(bp)) { if (BPE_GET_ETYPE(bp) != BP_EMBEDDED_TYPE_DATA) @@ -1929,14 +2141,12 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, PRIuGRUB_UINT64_T ")\n", BPE_GET_ETYPE (bp)); lsize = BPE_GET_LSIZE(bp); - psize = BF64_GET_SB(grub_zfs_to_cpu64 ((bp)->blk_prop, endian), 25, 7, 0, 1); + psize = BPE_GET_PSIZE(bp); } else { - lsize = (BP_IS_HOLE(bp) ? 0 : - (((grub_zfs_to_cpu64 ((bp)->blk_prop, endian) & 0xffff) + 1) - << SPA_MINBLOCKSHIFT)); - psize = get_psize (bp, endian); + lsize = (BP_IS_HOLE(bp) ? 0 : BP_GET_LSIZE(bp)); + psize = BP_GET_PSIZE(bp); } grub_dprintf("zfs", "zio_read: E %d: size %" PRIdGRUB_SSIZE "/%" PRIdGRUB_SSIZE "\n", (int)BP_IS_EMBEDDED(bp), lsize, psize); @@ -1960,12 +2170,11 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, if (! compbuf) return grub_errno; - grub_dprintf ("zfs", "endian = %d\n", endian); if (BP_IS_EMBEDDED(bp)) err = decode_embedded_bp_compressed(bp, compbuf); else { - err = zio_read_data (bp, endian, compbuf, data); + err = zio_read_data (bp, compbuf, data); /* FIXME is it really necessary? */ if (comp != ZIO_COMPRESS_OFF) grub_memset (compbuf + psize, 0, ALIGN_UP (psize, 16) - psize); @@ -1979,7 +2188,7 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, if (!BP_IS_EMBEDDED(bp)) { - err = zio_checksum_verify (zc, checksum, endian, + err = zio_checksum_verify (zc, checksum, BP_GET_BYTEORDER(bp), compbuf, psize); if (err) { @@ -2001,8 +2210,7 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, unsigned i, besti = 0; grub_uint64_t bestval = 0; for (i = 0; i < data->subvol.nkeys; i++) - if (data->subvol.keyring[i].txg <= grub_zfs_to_cpu64 (bp->blk_birth, - endian) + if (data->subvol.keyring[i].txg <= bp->blk_birth && data->subvol.keyring[i].txg > bestval) { besti = i; @@ -2013,21 +2221,19 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, grub_free (compbuf); *buf = NULL; grub_dprintf ("zfs", "no key for txg %" PRIxGRUB_UINT64_T "\n", - grub_zfs_to_cpu64 (bp->blk_birth, - endian)); + bp->blk_birth); return grub_error (GRUB_ERR_BAD_FS, "no key found in keychain"); } grub_dprintf ("zfs", "using key %u (%" PRIxGRUB_UINT64_T ", %p) for txg %" PRIxGRUB_UINT64_T "\n", besti, data->subvol.keyring[besti].txg, data->subvol.keyring[besti].cipher, - grub_zfs_to_cpu64 (bp->blk_birth, - endian)); + bp->blk_birth); err = grub_zfs_decrypt (data->subvol.keyring[besti].cipher, data->subvol.keyring[besti].algo, - &(bp)->blk_dva[encrypted], + &(bp)->blk_dva[2], compbuf, psize, zc.zc_mac, - endian); + BP_GET_BYTEORDER(bp)); } if (err) { @@ -2056,6 +2262,17 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, } } + if (!GRUB_ZFS_IS_NATIVE_BYTEORDER(BP_GET_BYTEORDER(bp))) + { + if (BP_GET_LEVEL(bp) > 0) + { + for (unsigned i = 0; i < lsize / sizeof(blkptr_t); i++) + grub_zfs_byteswap_blkptr((blkptr_t *)*buf + i); + } + else + grub_zfs_byteswap_type(*buf, lsize, BP_GET_TYPE(bp)); + } + return GRUB_ERR_NONE; } @@ -2065,29 +2282,28 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, * */ static grub_err_t -dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf, - grub_zfs_endian_t *endian_out, struct grub_zfs_data *data) +dmu_read (dnode_phys_t * dn, grub_uint64_t blkid, void **buf, + struct grub_zfs_data *data) { int level; grub_off_t idx; - blkptr_t *bp_array = dn->dn.dn_blkptr; - int epbs = dn->dn.dn_indblkshift - SPA_BLKPTRSHIFT; + blkptr_t *bp_array = dn->dn_blkptr; + int epbs = dn->dn_indblkshift - SPA_BLKPTRSHIFT; blkptr_t *bp; void *tmpbuf = 0; - grub_zfs_endian_t endian; grub_err_t err = GRUB_ERR_NONE; bp = grub_malloc (sizeof (blkptr_t)); if (!bp) return grub_errno; - endian = dn->endian; - for (level = dn->dn.dn_nlevels - 1; level >= 0; level--) + *buf = NULL; + + for (level = dn->dn_nlevels - 1; level >= 0; level--) { - grub_dprintf ("zfs", "endian = %d\n", endian); idx = (blkid >> (epbs * level)) & ((1 << epbs) - 1); *bp = bp_array[idx]; - if (bp_array != dn->dn.dn_blkptr) + if (bp_array != dn->dn_blkptr) { grub_free (bp_array); bp_array = 0; @@ -2095,8 +2311,7 @@ dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf, if (BP_IS_HOLE (bp)) { - grub_size_t size = grub_zfs_to_cpu16 (dn->dn.dn_datablkszsec, - dn->endian) + grub_size_t size = dn->dn_datablkszsec << SPA_MINBLOCKSHIFT; *buf = grub_malloc (size); if (!*buf) @@ -2105,27 +2320,20 @@ dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf, break; } grub_memset (*buf, 0, size); - endian = (grub_zfs_to_cpu64 (bp->blk_prop, endian) >> 63) & 1; break; } if (level == 0) { - grub_dprintf ("zfs", "endian = %d\n", endian); - err = zio_read (bp, endian, buf, 0, data); - endian = (grub_zfs_to_cpu64 (bp->blk_prop, endian) >> 63) & 1; + err = zio_read (bp, buf, 0, data); break; } - grub_dprintf ("zfs", "endian = %d\n", endian); - err = zio_read (bp, endian, &tmpbuf, 0, data); - endian = (grub_zfs_to_cpu64 (bp->blk_prop, endian) >> 63) & 1; + err = zio_read (bp, &tmpbuf, 0, data); if (err) break; bp_array = tmpbuf; } - if (bp_array != dn->dn.dn_blkptr) + if (bp_array != dn->dn_blkptr) grub_free (bp_array); - if (endian_out) - *endian_out = endian; grub_free (bp); return err; @@ -2136,7 +2344,7 @@ dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf, * in "value". */ static grub_err_t -mzap_lookup (mzap_phys_t * zapobj, grub_zfs_endian_t endian, +mzap_lookup (mzap_phys_t * zapobj, grub_uint32_t objsize, const char *name, grub_uint64_t * value, int case_insensitive) { @@ -2151,7 +2359,7 @@ mzap_lookup (mzap_phys_t * zapobj, grub_zfs_endian_t endian, if (case_insensitive ? (grub_strcasecmp (mzap_ent[i].mze_name, name) == 0) : (grub_strcmp (mzap_ent[i].mze_name, name) == 0)) { - *value = grub_zfs_to_cpu64 (mzap_ent[i].mze_value, endian); + *value = mzap_ent[i].mze_value; return GRUB_ERR_NONE; } } @@ -2160,7 +2368,7 @@ mzap_lookup (mzap_phys_t * zapobj, grub_zfs_endian_t endian, } static int -mzap_iterate (mzap_phys_t * zapobj, grub_zfs_endian_t endian, int objsize, +mzap_iterate (mzap_phys_t * zapobj, int objsize, int (*hook) (const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx), struct grub_zfs_dir_ctx *ctx) @@ -2174,8 +2382,7 @@ mzap_iterate (mzap_phys_t * zapobj, grub_zfs_endian_t endian, int objsize, grub_dprintf ("zfs", "zap: name = %s, value = %llx, cd = %x\n", mzap_ent[i].mze_name, (long long)mzap_ent[i].mze_value, (int)mzap_ent[i].mze_cd); - if (hook (mzap_ent[i].mze_name, - grub_zfs_to_cpu64 (mzap_ent[i].mze_value, endian), ctx)) + if (hook (mzap_ent[i].mze_name, mzap_ent[i].mze_value, ctx)) return 1; } @@ -2250,7 +2457,7 @@ name_cmp (const char *s1, const char *s2, grub_size_t n, /* XXX */ static int -zap_leaf_array_equal (zap_leaf_phys_t * l, grub_zfs_endian_t endian, +zap_leaf_array_equal (zap_leaf_phys_t * l, int blksft, int chunk, grub_size_t array_len, const char *buf, int case_insensitive) { @@ -2270,7 +2477,7 @@ zap_leaf_array_equal (zap_leaf_phys_t * l, grub_zfs_endian_t endian, if (name_cmp ((char *) la->la_array, buf + bseen, toread, case_insensitive) != 0) break; - chunk = grub_zfs_to_cpu16 (la->la_next, endian); + chunk = la->la_next; bseen += toread; } return (bseen == array_len); @@ -2278,7 +2485,7 @@ zap_leaf_array_equal (zap_leaf_phys_t * l, grub_zfs_endian_t endian, /* XXX */ static grub_err_t -zap_leaf_array_get (zap_leaf_phys_t * l, grub_zfs_endian_t endian, int blksft, +zap_leaf_array_get (zap_leaf_phys_t * l, int blksft, int chunk, grub_size_t array_len, char *buf) { grub_size_t bseen = 0; @@ -2297,7 +2504,7 @@ zap_leaf_array_get (zap_leaf_phys_t * l, grub_zfs_endian_t endian, int blksft, la = &ZAP_LEAF_CHUNK (l, blksft, chunk)->l_array; grub_memcpy (buf + bseen,la->la_array, toread); - chunk = grub_zfs_to_cpu16 (la->la_next, endian); + chunk = la->la_next; bseen += toread; } return GRUB_ERR_NONE; @@ -2311,7 +2518,7 @@ zap_leaf_array_get (zap_leaf_phys_t * l, grub_zfs_endian_t endian, int blksft, */ /* XXX */ static grub_err_t -zap_leaf_lookup (zap_leaf_phys_t * l, grub_zfs_endian_t endian, +zap_leaf_lookup (zap_leaf_phys_t * l, int blksft, grub_uint64_t h, const char *name, grub_uint64_t * value, int case_insensitive) @@ -2320,13 +2527,13 @@ zap_leaf_lookup (zap_leaf_phys_t * l, grub_zfs_endian_t endian, struct zap_leaf_entry *le; /* Verify if this is a valid leaf block */ - if (grub_zfs_to_cpu64 (l->l_hdr.lh_block_type, endian) != ZBT_LEAF) + if (l->l_hdr.lh_block_type != ZBT_LEAF) return grub_error (GRUB_ERR_BAD_FS, "invalid leaf type"); - if (grub_zfs_to_cpu32 (l->l_hdr.lh_magic, endian) != ZAP_LEAF_MAGIC) + if (l->l_hdr.lh_magic != ZAP_LEAF_MAGIC) return grub_error (GRUB_ERR_BAD_FS, "invalid leaf magic"); - for (chunk = grub_zfs_to_cpu16 (l->l_hash[LEAF_HASH (blksft, h, l)], endian); - chunk != CHAIN_END; chunk = grub_zfs_to_cpu16 (le->le_next, endian)) + for (chunk = l->l_hash[LEAF_HASH (blksft, h, l)]; + chunk != CHAIN_END; chunk = le->le_next) { if (chunk >= ZAP_LEAF_NUMCHUNKS (blksft)) @@ -2338,20 +2545,19 @@ zap_leaf_lookup (zap_leaf_phys_t * l, grub_zfs_endian_t endian, if (le->le_type != ZAP_CHUNK_ENTRY) return grub_error (GRUB_ERR_BAD_FS, "invalid chunk entry"); - if (grub_zfs_to_cpu64 (le->le_hash,endian) != h) + if (le->le_hash != h) continue; grub_dprintf ("zfs", "fzap: length %d\n", (int) le->le_name_length); - if (zap_leaf_array_equal (l, endian, blksft, - grub_zfs_to_cpu16 (le->le_name_chunk,endian), - grub_zfs_to_cpu16 (le->le_name_length, endian), + if (zap_leaf_array_equal (l, blksft, + le->le_name_chunk, + le->le_name_length, name, case_insensitive)) { struct zap_leaf_array *la; - if (le->le_int_size != 8 || grub_zfs_to_cpu16 (le->le_value_length, - endian) != 1) + if (le->le_int_size != 8 || le->le_value_length != 1) return grub_error (GRUB_ERR_BAD_FS, "invalid leaf chunk entry"); /* get the uint64_t property value */ @@ -2369,9 +2575,9 @@ zap_leaf_lookup (zap_leaf_phys_t * l, grub_zfs_endian_t endian, /* Verify if this is a fat zap header block */ static grub_err_t -zap_verify (zap_phys_t *zap, grub_zfs_endian_t endian) +zap_verify (zap_phys_t *zap) { - if (grub_zfs_to_cpu64 (zap->zap_magic, endian) != (grub_uint64_t) ZAP_MAGIC) + if (zap->zap_magic != (grub_uint64_t) ZAP_MAGIC) return grub_error (GRUB_ERR_BAD_FS, "bad ZAP magic"); if (zap->zap_salt == 0) @@ -2386,18 +2592,16 @@ zap_verify (zap_phys_t *zap, grub_zfs_endian_t endian) */ /* XXX */ static grub_err_t -fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap, +fzap_lookup (dnode_phys_t * zap_dnode, zap_phys_t * zap, const char *name, grub_uint64_t * value, struct grub_zfs_data *data, int case_insensitive) { void *l; grub_uint64_t hash, idx, blkid; - int blksft = zfs_log2 (grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, - zap_dnode->endian) << DNODE_SHIFT); + int blksft = zfs_log2 (zap_dnode->dn_datablkszsec) + DNODE_SHIFT; grub_err_t err; - grub_zfs_endian_t leafendian; - err = zap_verify (zap, zap_dnode->endian); + err = zap_verify (zap); if (err) return err; @@ -2408,16 +2612,16 @@ fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap, return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "external pointer tables not supported"); idx = ZAP_HASH_IDX (hash, zap->zap_ptrtbl.zt_shift); - blkid = grub_zfs_to_cpu64 (((grub_uint64_t *) zap)[idx + (1 << (blksft - 3 - 1))], zap_dnode->endian); + blkid = ((grub_uint64_t *) zap)[idx + (1 << (blksft - 3 - 1))]; /* Get the leaf block */ if ((1U << blksft) < sizeof (zap_leaf_phys_t)) return grub_error (GRUB_ERR_BAD_FS, "ZAP leaf is too small"); - err = dmu_read (zap_dnode, blkid, &l, &leafendian, data); + err = dmu_read (zap_dnode, blkid, &l, data); if (err) return err; - err = zap_leaf_lookup (l, leafendian, blksft, hash, name, value, + err = zap_leaf_lookup (l, blksft, hash, name, value, case_insensitive); grub_free (l); return err; @@ -2425,7 +2629,7 @@ fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap, /* XXX */ static int -fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, +fzap_iterate (dnode_phys_t * zap_dnode, zap_phys_t * zap, grub_size_t name_elem_length, int (*hook) (const void *name, grub_size_t name_length, const void *val_in, @@ -2437,13 +2641,11 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, void *l_in; grub_uint64_t idx, idx2, blkid; grub_uint16_t chunk; - int blksft = zfs_log2 (grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, - zap_dnode->endian) << DNODE_SHIFT); + int blksft = zfs_log2 (zap_dnode->dn_datablkszsec) + DNODE_SHIFT; grub_err_t err; - grub_zfs_endian_t endian; grub_size_t sz; - if (zap_verify (zap, zap_dnode->endian)) + if (zap_verify (zap)) return 0; /* get block id from index */ @@ -2461,17 +2663,15 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, } for (idx = 0; idx < (1ULL << zap->zap_ptrtbl.zt_shift); idx++) { - blkid = grub_zfs_to_cpu64 (((grub_uint64_t *) zap)[idx + (1 << (blksft - 3 - 1))], - zap_dnode->endian); + blkid = ((grub_uint64_t *) zap)[idx + (1 << (blksft - 3 - 1))]; for (idx2 = 0; idx2 < idx; idx2++) - if (blkid == grub_zfs_to_cpu64 (((grub_uint64_t *) zap)[idx2 + (1 << (blksft - 3 - 1))], - zap_dnode->endian)) + if (blkid == ((grub_uint64_t *) zap)[idx2 + (1 << (blksft - 3 - 1))]) break; if (idx2 != idx) continue; - err = dmu_read (zap_dnode, blkid, &l_in, &endian, data); + err = dmu_read (zap_dnode, blkid, &l_in, data); l = l_in; if (err) { @@ -2480,12 +2680,12 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, } /* Verify if this is a valid leaf block */ - if (grub_zfs_to_cpu64 (l->l_hdr.lh_block_type, endian) != ZBT_LEAF) + if (l->l_hdr.lh_block_type != ZBT_LEAF) { grub_free (l); continue; } - if (grub_zfs_to_cpu32 (l->l_hdr.lh_magic, endian) != ZAP_LEAF_MAGIC) + if (l->l_hdr.lh_magic != ZAP_LEAF_MAGIC) { grub_free (l); continue; @@ -2503,7 +2703,7 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, if (le->le_type != ZAP_CHUNK_ENTRY) continue; - if (grub_mul (grub_zfs_to_cpu16 (le->le_name_length, endian), name_elem_length, &sz) || + if (grub_mul (le->le_name_length, name_elem_length, &sz) || grub_add (sz, 1, &sz)) { grub_error (GRUB_ERR_OUT_OF_RANGE, N_("buffer size overflow")); @@ -2516,11 +2716,9 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, grub_free (l); return grub_errno; } - if (zap_leaf_array_get (l, endian, blksft, - grub_zfs_to_cpu16 (le->le_name_chunk, - endian), - grub_zfs_to_cpu16 (le->le_name_length, - endian) + if (zap_leaf_array_get (l, blksft, + le->le_name_chunk, + le->le_name_length * name_elem_length, buf)) { grub_free (buf); @@ -2530,16 +2728,15 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, val_length = ((int) le->le_value_length * (int) le->le_int_size); - val = grub_malloc (grub_zfs_to_cpu16 (val_length, endian)); + val = grub_malloc (val_length); if (!val) { grub_free (l); grub_free (buf); return grub_errno; } - if (zap_leaf_array_get (l, endian, blksft, - grub_zfs_to_cpu16 (le->le_value_chunk, - endian), + if (zap_leaf_array_get (l, blksft, + le->le_value_chunk, val_length, val)) { grub_free (buf); @@ -2567,32 +2764,29 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, * */ static grub_err_t -zap_lookup (dnode_end_t * zap_dnode, const char *name, grub_uint64_t *val, +zap_lookup (dnode_phys_t * zap_dnode, const char *name, grub_uint64_t *val, struct grub_zfs_data *data, int case_insensitive) { grub_uint64_t block_type; grub_uint32_t size; void *zapbuf; grub_err_t err; - grub_zfs_endian_t endian; grub_dprintf ("zfs", "looking for '%s'\n", name); /* Read in the first block of the zap object data. */ - size = (grub_uint32_t) grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, - zap_dnode->endian) << SPA_MINBLOCKSHIFT; - err = dmu_read (zap_dnode, 0, &zapbuf, &endian, data); + size = (grub_uint32_t) zap_dnode->dn_datablkszsec << SPA_MINBLOCKSHIFT; + err = dmu_read (zap_dnode, 0, &zapbuf, data); if (err) return err; - block_type = grub_zfs_to_cpu64 (*((grub_uint64_t *) zapbuf), endian); + block_type = *((grub_uint64_t *) zapbuf); grub_dprintf ("zfs", "zap read\n"); if (block_type == ZBT_MICRO) { grub_dprintf ("zfs", "micro zap\n"); - err = mzap_lookup (zapbuf, endian, size, name, val, - case_insensitive); + err = mzap_lookup (zapbuf, size, name, val, case_insensitive); grub_dprintf ("zfs", "returned %d\n", err); grub_free (zapbuf); return err; @@ -2637,7 +2831,7 @@ zap_iterate_u64_transform (const void *name, } static int -zap_iterate_u64 (dnode_end_t * zap_dnode, +zap_iterate_u64 (dnode_phys_t * zap_dnode, int (*hook) (const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx), struct grub_zfs_data *data, struct grub_zfs_dir_ctx *ctx) @@ -2647,21 +2841,20 @@ zap_iterate_u64 (dnode_end_t * zap_dnode, void *zapbuf; grub_err_t err; int ret; - grub_zfs_endian_t endian; /* Read in the first block of the zap object data. */ - size = grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, zap_dnode->endian) << SPA_MINBLOCKSHIFT; - err = dmu_read (zap_dnode, 0, &zapbuf, &endian, data); + size = zap_dnode->dn_datablkszsec << SPA_MINBLOCKSHIFT; + err = dmu_read (zap_dnode, 0, &zapbuf, data); if (err) return 0; - block_type = grub_zfs_to_cpu64 (*((grub_uint64_t *) zapbuf), endian); + block_type = *((grub_uint64_t *) zapbuf); grub_dprintf ("zfs", "zap iterate\n"); if (block_type == ZBT_MICRO) { grub_dprintf ("zfs", "micro zap\n"); - ret = mzap_iterate (zapbuf, endian, size, hook, ctx); + ret = mzap_iterate (zapbuf, size, hook, ctx); grub_free (zapbuf); return ret; } @@ -2685,7 +2878,7 @@ zap_iterate_u64 (dnode_end_t * zap_dnode, } static int -zap_iterate (dnode_end_t * zap_dnode, +zap_iterate (dnode_phys_t * zap_dnode, grub_size_t nameelemlen, int (*hook) (const void *name, grub_size_t namelen, const void *val_in, @@ -2697,13 +2890,12 @@ zap_iterate (dnode_end_t * zap_dnode, void *zapbuf; grub_err_t err; int ret; - grub_zfs_endian_t endian; /* Read in the first block of the zap object data. */ - err = dmu_read (zap_dnode, 0, &zapbuf, &endian, data); + err = dmu_read (zap_dnode, 0, &zapbuf, data); if (err) return 0; - block_type = grub_zfs_to_cpu64 (*((grub_uint64_t *) zapbuf), endian); + block_type = *((grub_uint64_t *) zapbuf); grub_dprintf ("zfs", "zap iterate\n"); @@ -2737,20 +2929,18 @@ zap_iterate (dnode_end_t * zap_dnode, * buf - data buffer that holds the returning dnode */ static grub_err_t -dnode_get (dnode_end_t * mdn, grub_uint64_t objnum, grub_uint8_t type, - dnode_end_t * buf, struct grub_zfs_data *data) +dnode_get (dnode_phys_t * mdn, grub_uint64_t objnum, grub_uint8_t type, + dnode_phys_t * buf, struct grub_zfs_data *data) { grub_uint64_t blkid, blksz; /* the block id this object dnode is in */ int epbs; /* shift of number of dnodes in a block */ int idx; /* index within a block */ void *dnbuf; grub_err_t err; - grub_zfs_endian_t endian; objnum &= DNODE_NUM_MASK; - blksz = grub_zfs_to_cpu16 (mdn->dn.dn_datablkszsec, - mdn->endian) << SPA_MINBLOCKSHIFT; + blksz = mdn->dn_datablkszsec << SPA_MINBLOCKSHIFT; epbs = zfs_log2 (blksz) - DNODE_SHIFT; /* While this should never happen, we should check that epbs is not negative. */ @@ -2760,22 +2950,23 @@ dnode_get (dnode_end_t * mdn, grub_uint64_t objnum, grub_uint8_t type, blkid = objnum >> epbs; idx = objnum & ((1 << epbs) - 1); - if (data->dnode_buf != NULL && grub_memcmp (data->dnode_mdn, &mdn->dn, - sizeof (mdn->dn)) == 0 + if (data->dnode_buf != NULL && grub_memcmp (data->dnode_mdn, mdn, + sizeof (*mdn)) == 0 && objnum >= data->dnode_start && objnum < data->dnode_end) { - grub_memmove (&(buf->dn), &(data->dnode_buf)[idx], DNODE_SIZE); - buf->endian = data->dnode_endian; - if (type && buf->dn.dn_type != type) + *buf = (data->dnode_buf)[idx]; + if (type && buf->dn_type != type) return grub_error(GRUB_ERR_BAD_FS, "incorrect dnode type"); return GRUB_ERR_NONE; } - grub_dprintf ("zfs", "endian = %d, blkid=%llx\n", mdn->endian, + grub_dprintf ("zfs", "blkid=%llx\n", (unsigned long long) blkid); - err = dmu_read (mdn, blkid, &dnbuf, &endian, data); + err = dmu_read (mdn, blkid, &dnbuf, data); if (err) return err; + if (dnbuf == NULL) + return grub_error(GRUB_ERR_BAD_FS, "invalid or unavailable dnode"); grub_dprintf ("zfs", "alive\n"); grub_free (data->dnode_buf); @@ -2792,15 +2983,10 @@ dnode_get (dnode_end_t * mdn, grub_uint64_t objnum, grub_uint8_t type, data->dnode_buf = dnbuf; data->dnode_start = blkid << epbs; data->dnode_end = (blkid + 1) << epbs; - data->dnode_endian = endian; } - grub_memmove (&(buf->dn), (dnode_phys_t *) dnbuf + idx, DNODE_SIZE); - if (data->dnode_buf == 0) - /* dnbuf not used anymore if data->dnode_mdn malloc failed */ - grub_free (dnbuf); - buf->endian = endian; - if (type && buf->dn.dn_type != type) + *buf = ((dnode_phys_t *) dnbuf)[idx]; + if (type && buf->dn_type != type) return grub_error(GRUB_ERR_BAD_FS, "incorrect dnode type"); return GRUB_ERR_NONE; @@ -2815,7 +3001,7 @@ dnode_get (dnode_end_t * mdn, grub_uint64_t objnum, grub_uint8_t type, * */ static grub_err_t -dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, +dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_phys_t *dn, struct grub_zfs_data *data) { grub_uint64_t objnum, version; @@ -2825,7 +3011,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, struct dnode_chain { struct dnode_chain *next; - dnode_end_t dn; + dnode_phys_t dn; }; struct dnode_chain *dnode_path = 0, *dn_new, *root; @@ -2922,7 +3108,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, ch = *path; *path = 0; /* ensure null termination */ - if (dnode_path->dn.dn.dn_type != DMU_OT_DIRECTORY_CONTENTS) + if (dnode_path->dn.dn_type != DMU_OT_DIRECTORY_CONTENTS) { err = grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); break; @@ -2947,25 +3133,23 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, break; *path = ch; - if (dnode_path->dn.dn.dn_bonustype == DMU_OT_ZNODE - && ((grub_zfs_to_cpu64(((znode_phys_t *) DN_BONUS (&dnode_path->dn.dn))->zp_mode, dnode_path->dn.endian) >> 12) & 0xf) == 0xa) + if (dnode_path->dn.dn_bonustype == DMU_OT_ZNODE + && (((((znode_phys_t *) DN_BONUS (&dnode_path->dn))->zp_mode) >> 12) & 0xf) == 0xa) { char *sym_value; grub_size_t sz; grub_size_t sym_sz; int free_symval = 0; char *oldpath = path, *oldpathbuf = path_buf; - sym_value = ((char *) DN_BONUS (&dnode_path->dn.dn) + sizeof (struct znode_phys)); + sym_value = ((char *) DN_BONUS (&dnode_path->dn) + sizeof (struct znode_phys)); - sym_sz = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dnode_path->dn.dn))->zp_size, dnode_path->dn.endian); + sym_sz = ((znode_phys_t *) DN_BONUS (&dnode_path->dn))->zp_size; - if (dnode_path->dn.dn.dn_flags & 1) + if (dnode_path->dn.dn_flags & 1) { grub_size_t block; grub_size_t blksz; - blksz = (grub_zfs_to_cpu16 (dnode_path->dn.dn.dn_datablkszsec, - dnode_path->dn.endian) - << SPA_MINBLOCKSHIFT); + blksz = dnode_path->dn.dn_datablkszsec << SPA_MINBLOCKSHIFT; if (blksz == 0) { @@ -2985,7 +3169,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, void *t; grub_size_t movesize; - err = dmu_read (&(dnode_path->dn), block, &t, 0, data); + err = dmu_read (&(dnode_path->dn), block, &t, data); if (err) { grub_free (sym_value); @@ -3047,22 +3231,22 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, } dn_new = dnode_path; } - if (dnode_path->dn.dn.dn_bonustype == DMU_OT_SA) + if (dnode_path->dn.dn_bonustype == DMU_OT_SA) { void *sahdrp; int hdrsize; grub_size_t sz; bool free_sahdrp = false; - if (dnode_path->dn.dn.dn_bonuslen != 0) + if (dnode_path->dn.dn_bonuslen != 0) { - sahdrp = DN_BONUS (&dnode_path->dn.dn); + sahdrp = DN_BONUS (&dnode_path->dn); } - else if (dnode_path->dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR) + else if (dnode_path->dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR) { - blkptr_t *bp = &dnode_path->dn.dn.dn_spill; + blkptr_t *bp = &dnode_path->dn.dn_spill; - err = zio_read (bp, dnode_path->dn.endian, &sahdrp, NULL, data); + err = zio_read (bp, &sahdrp, NULL, data); if (err) break; free_sahdrp = true; @@ -3075,17 +3259,14 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); - if (((grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp - + hdrsize - + SA_TYPE_OFFSET), - dnode_path->dn.endian) >> 12) & 0xf) == 0xa) + if (((grub_get_unaligned64 ((char *) sahdrp + + hdrsize + + SA_TYPE_OFFSET) >> 12) & 0xf) == 0xa) { char *sym_value = (char *) sahdrp + hdrsize + SA_SYMLINK_OFFSET; - grub_size_t sym_sz = - grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + grub_size_t sym_sz = grub_get_unaligned64 ((char *) sahdrp + hdrsize - + SA_SIZE_OFFSET), - dnode_path->dn.endian); + + SA_SIZE_OFFSET); char *oldpath = path, *oldpathbuf = path_buf; if (grub_add (sym_sz, grub_strlen (oldpath), &sz) || grub_add (sz, 1, &sz)) @@ -3205,14 +3386,12 @@ get_default_bootfsobj (dnode_phys_t * mosmdn, grub_uint64_t * obj, * */ static grub_err_t -get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname, - dnode_end_t * mdn, struct grub_zfs_data *data) +get_filesystem_dnode (dnode_phys_t * mosmdn, char *fsname, + dnode_phys_t * mdn, struct grub_zfs_data *data) { grub_uint64_t objnum; grub_err_t err; - grub_dprintf ("zfs", "endian = %d\n", mosmdn->endian); - err = dnode_get (mosmdn, DMU_POOL_DIRECTORY_OBJECT, DMU_OT_OBJECT_DIRECTORY, mdn, data); if (err) @@ -3249,7 +3428,7 @@ get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname, ch = *fsname; *fsname = 0; - childobj = grub_zfs_to_cpu64 ((((dsl_dir_phys_t *) DN_BONUS (&mdn->dn)))->dd_child_dir_zapobj, mdn->endian); + childobj = (((dsl_dir_phys_t *) DN_BONUS (mdn)))->dd_child_dir_zapobj; err = dnode_get (mosmdn, childobj, DMU_OT_DSL_DIR_CHILD_MAP, mdn, data); if (err) @@ -3269,17 +3448,15 @@ get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname, } static grub_err_t -make_mdn (dnode_end_t * mdn, struct grub_zfs_data *data) +make_mdn (dnode_phys_t * mdn, struct grub_zfs_data *data) { objset_phys_t *osp; blkptr_t *bp; grub_size_t ospsize = 0; grub_err_t err; - grub_dprintf ("zfs", "endian = %d\n", mdn->endian); - - bp = &(((dsl_dataset_phys_t *) DN_BONUS (&mdn->dn))->ds_bp); - err = zio_read (bp, mdn->endian, (void **) &osp, &ospsize, data); + bp = &(((dsl_dataset_phys_t *) DN_BONUS (mdn))->ds_bp); + err = zio_read (bp, (void **) &osp, &ospsize, data); if (err) return err; if (ospsize < OBJSET_PHYS_SIZE_V14) @@ -3288,9 +3465,7 @@ make_mdn (dnode_end_t * mdn, struct grub_zfs_data *data) return grub_error (GRUB_ERR_BAD_FS, "too small osp"); } - mdn->endian = (grub_zfs_to_cpu64 (bp->blk_prop, mdn->endian)>>63) & 1; - grub_memmove ((char *) &(mdn->dn), - (char *) &(osp)->os_meta_dnode, DNODE_SIZE); + *mdn = (osp)->os_meta_dnode; grub_free (osp); return GRUB_ERR_NONE; } @@ -3352,7 +3527,7 @@ load_zap_key (const void *name, grub_size_t namelen, const void *val_in, static grub_err_t dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, - dnode_end_t * dn, int *isfs, + dnode_phys_t * dn, int *isfs, struct grub_zfs_data *data) { char *fsname, *snapname; @@ -3412,9 +3587,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, grub_dprintf ("zfs", "alive\n"); - headobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&dn->dn))->dd_head_dataset_obj, dn->endian); - - grub_dprintf ("zfs", "endian = %d\n", subvol->mdn.endian); + headobj = ((dsl_dir_phys_t *) DN_BONUS (dn))->dd_head_dataset_obj; err = dnode_get (&(data->mos), headobj, 0, &subvol->mdn, data); if (err) @@ -3423,18 +3596,19 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, grub_free (snapname); return err; } - grub_dprintf ("zfs", "endian = %d\n", subvol->mdn.endian); + keychainobj = ((dsl_dir_phys_t *) DN_BONUS (dn))->keychain; + + grub_dprintf("zfs", "keychain obj = %lld\n", (long long) keychainobj); - keychainobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&dn->dn))->keychain, dn->endian); - if (grub_zfs_load_key && keychainobj) + if (grub_zfs_decrypt && keychainobj) { struct dnode_get_fullpath_ctx ctx = { .subvol = subvol, .keyn = 0 }; - dnode_end_t keychain_dn, props_dn; + dnode_phys_t keychain_dn, props_dn; grub_uint64_t propsobj; - propsobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&dn->dn))->dd_props_zapobj, dn->endian); + propsobj = ((dsl_dir_phys_t *) DN_BONUS (dn))->dd_props_zapobj; err = dnode_get (&(data->mos), propsobj, DMU_OT_DSL_PROPS, &props_dn, data); @@ -3484,7 +3658,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, { grub_uint64_t snapobj; - snapobj = grub_zfs_to_cpu64 (((dsl_dataset_phys_t *) DN_BONUS (&subvol->mdn.dn))->ds_snapnames_zapobj, subvol->mdn.endian); + snapobj = ((dsl_dataset_phys_t *) DN_BONUS (&subvol->mdn))->ds_snapnames_zapobj; err = dnode_get (&(data->mos), snapobj, DMU_OT_DSL_DS_SNAP_MAP, &subvol->mdn, data); @@ -3493,7 +3667,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, if (!err) err = dnode_get (&(data->mos), headobj, 0, &subvol->mdn, data); - if (!err && subvol->mdn.dn.dn_type != DMU_OT_DSL_DATASET && subvol->mdn.dn.dn_bonustype != DMU_OT_DSL_DATASET) { + if (!err && subvol->mdn.dn_type != DMU_OT_DSL_DATASET && subvol->mdn.dn_bonustype != DMU_OT_DSL_DATASET) { grub_free (fsname); grub_free (snapname); return grub_error(GRUB_ERR_BAD_FS, "incorrect dataset dnode type"); @@ -3511,8 +3685,6 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, make_mdn (&subvol->mdn, data); - grub_dprintf ("zfs", "endian = %d\n", subvol->mdn.endian); - if (*isfs) { grub_free (fsname); @@ -3776,7 +3948,6 @@ zfs_mount (grub_device_t dev) grub_err_t err; objset_phys_t *osp = 0; grub_size_t ospsize; - grub_zfs_endian_t ub_endian = GRUB_ZFS_UNKNOWN_ENDIAN; uberblock_t *ub; int inserted; @@ -3812,11 +3983,8 @@ zfs_mount (grub_device_t dev) } ub = &(data->current_uberblock); - ub_endian = (grub_zfs_to_cpu64 (ub->ub_magic, - GRUB_ZFS_LITTLE_ENDIAN) == UBERBLOCK_MAGIC - ? GRUB_ZFS_LITTLE_ENDIAN : GRUB_ZFS_BIG_ENDIAN); - err = zio_read (&ub->ub_rootbp, ub_endian, + err = zio_read (&ub->ub_rootbp, (void **) &osp, &ospsize, data); if (err) { @@ -3833,7 +4001,7 @@ zfs_mount (grub_device_t dev) } if (ub->ub_version >= SPA_VERSION_FEATURES && - check_mos_features(&osp->os_meta_dnode, ub_endian, data) != 0) + check_mos_features(&osp->os_meta_dnode, data) != 0) { grub_error (GRUB_ERR_BAD_FS, "Unsupported features in pool"); grub_free (osp); @@ -3842,9 +4010,7 @@ zfs_mount (grub_device_t dev) } /* Got the MOS. Save it at the memory addr MOS. */ - grub_memmove (&(data->mos.dn), &osp->os_meta_dnode, DNODE_SIZE); - data->mos.endian = (grub_zfs_to_cpu64 (ub->ub_rootbp.blk_prop, - ub_endian) >> 63) & 1; + grub_memmove (&(data->mos), &osp->os_meta_dnode, DNODE_SIZE); grub_free (osp); return data; @@ -3910,8 +4076,6 @@ static grub_err_t zfs_mtime (grub_device_t device, grub_int64_t *mt) { struct grub_zfs_data *data; - grub_zfs_endian_t ub_endian = GRUB_ZFS_UNKNOWN_ENDIAN; - uberblock_t *ub; *mt = 0; @@ -3919,16 +4083,48 @@ zfs_mtime (grub_device_t device, grub_int64_t *mt) if (! data) return grub_errno; - ub = &(data->current_uberblock); - ub_endian = (grub_zfs_to_cpu64 (ub->ub_magic, - GRUB_ZFS_LITTLE_ENDIAN) == UBERBLOCK_MAGIC - ? GRUB_ZFS_LITTLE_ENDIAN : GRUB_ZFS_BIG_ENDIAN); - - *mt = grub_zfs_to_cpu64 (ub->ub_timestamp, ub_endian); + *mt = data->current_uberblock.ub_timestamp; zfs_unmount (data); return GRUB_ERR_NONE; } +static grub_err_t +parse_sa(const dnode_phys_t *dn, grub_int64_t *mtime, grub_uint64_t *sz, + struct grub_zfs_data *data) +{ + void *sahdrp; + int hdrsize; + grub_zfs_endian_t sa_endian; + + if (dn->dn_bonuslen != 0) + sahdrp = (sa_hdr_phys_t *) DN_BONUS (dn); + else if (dn->dn_flags & DNODE_FLAG_SPILL_BLKPTR) + { + const blkptr_t *bp = &dn->dn_spill; + + grub_err_t err = zio_read (bp, &sahdrp, NULL, data); + if (err) + return err; + } + else + return GRUB_ERR_NONE; + + if (grub_zfs_to_cpu32(((sa_hdr_phys_t *) sahdrp)->sa_magic, GRUB_ZFS_LITTLE_ENDIAN) == SA_MAGIC) + sa_endian = GRUB_ZFS_LITTLE_ENDIAN; + else if (grub_zfs_to_cpu32(((sa_hdr_phys_t *) sahdrp)->sa_magic, GRUB_ZFS_BIG_ENDIAN) == SA_MAGIC) + sa_endian = GRUB_ZFS_BIG_ENDIAN; + else + return GRUB_ERR_NONE; + + hdrsize = (grub_zfs_to_cpu16(((sa_hdr_phys_t *) sahdrp)->sa_layout_info, sa_endian) >> 10) << 3; + if (mtime) + *mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), sa_endian); + if (sz) + *sz = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_SIZE_OFFSET), sa_endian); + + return GRUB_ERR_NONE; +} + /* * zfs_open() locates a file in the rootpool by following the * MOS and places the dnode of the file in the memory address DNODE. @@ -3959,7 +4155,7 @@ grub_zfs_open (struct grub_file *file, const char *fsfilename) } /* We found the dnode for this file. Verify if it is a plain file. */ - if (data->dnode.dn.dn_type != DMU_OT_PLAIN_FILE_CONTENTS) + if (data->dnode.dn_type != DMU_OT_PLAIN_FILE_CONTENTS) { zfs_unmount (data); return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file")); @@ -3972,38 +4168,17 @@ grub_zfs_open (struct grub_file *file, const char *fsfilename) * attribute, which could be either in the bonus buffer * or the "spill" block. */ - if (data->dnode.dn.dn_bonustype == DMU_OT_SA) + if (data->dnode.dn_bonustype == DMU_OT_SA) { - void *sahdrp; - int hdrsize; - bool free_sahdrp = false; - - if (data->dnode.dn.dn_bonuslen != 0) - { - sahdrp = (sa_hdr_phys_t *) DN_BONUS (&data->dnode.dn); - } - else if (data->dnode.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR) - { - blkptr_t *bp = &data->dnode.dn.dn_spill; - - err = zio_read (bp, data->dnode.endian, &sahdrp, NULL, data); - if (err) - return err; - free_sahdrp = true; - } - else - { - return grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt"); - } - - hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); - file->size = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_SIZE_OFFSET), data->dnode.endian); - if (free_sahdrp) - grub_free(sahdrp); + grub_uint64_t fsize; + err = parse_sa(&data->dnode, NULL, &fsize, data); + if (err) + return err; + file->size = fsize; } - else if (data->dnode.dn.dn_bonustype == DMU_OT_ZNODE) + else if (data->dnode.dn_bonustype == DMU_OT_ZNODE) { - file->size = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&data->dnode.dn))->zp_size, data->dnode.endian); + file->size = ((znode_phys_t *) DN_BONUS (&data->dnode))->zp_size; } else return grub_error (GRUB_ERR_BAD_FS, "bad bonus type"); @@ -4038,8 +4213,7 @@ grub_zfs_read (grub_file_t file, char *buf, grub_size_t len) return len; } - blksz = grub_zfs_to_cpu16 (data->dnode.dn.dn_datablkszsec, - data->dnode.endian) << SPA_MINBLOCKSHIFT; + blksz = data->dnode.dn_datablkszsec << SPA_MINBLOCKSHIFT; if (blksz == 0) { @@ -4065,8 +4239,7 @@ grub_zfs_read (grub_file_t file, char *buf, grub_size_t len) grub_free (data->file_buf); data->file_buf = 0; - err = dmu_read (&(data->dnode), blkid, &t, - 0, data); + err = dmu_read (&(data->dnode), blkid, &t, data); data->file_buf = t; if (err) { @@ -4125,19 +4298,19 @@ grub_zfs_getmdnobj (grub_device_t dev, const char *fsfilename, /* * Note: fill_fs_info() uses functions such as make_mdn() that modify - * the input dnode_end_t parameter. However, we should not allow it. + * the input dnode_phys_t parameter. However, we should not allow it. * Therefore, we are making mdn_in constant - fill_fs_info() makes * a local copy of it. */ static grub_err_t fill_fs_info (struct grub_dirhook_info *info, - const dnode_end_t *mdn_in, struct grub_zfs_data *data) + const dnode_phys_t *mdn_in, struct grub_zfs_data *data) { grub_err_t err; - dnode_end_t dn; + dnode_phys_t dn; grub_uint64_t objnum; grub_uint64_t headobj; - dnode_end_t mdn; + dnode_phys_t mdn; grub_memcpy (&mdn, mdn_in, sizeof (*mdn_in)); @@ -4145,9 +4318,9 @@ fill_fs_info (struct grub_dirhook_info *info, info->dir = 1; - if (mdn.dn.dn_type == DMU_OT_DSL_DIR || mdn.dn.dn_bonustype == DMU_OT_DSL_DIR) + if (mdn.dn_type == DMU_OT_DSL_DIR || mdn.dn_bonustype == DMU_OT_DSL_DIR) { - headobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&mdn.dn))->dd_head_dataset_obj, mdn.endian); + headobj = ((dsl_dir_phys_t *) DN_BONUS (&mdn))->dd_head_dataset_obj; err = dnode_get (&(data->mos), headobj, 0, &mdn, data); if (err) @@ -4181,42 +4354,18 @@ fill_fs_info (struct grub_dirhook_info *info, return err; } - if (dn.dn.dn_bonustype == DMU_OT_SA) + if (dn.dn_bonustype == DMU_OT_SA) { - void *sahdrp; - int hdrsize; - bool free_sahdrp = false; - - if (dn.dn.dn_bonuslen != 0) - { - sahdrp = (sa_hdr_phys_t *) DN_BONUS (&dn.dn); - } - else if (dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR) - { - blkptr_t *bp = &dn.dn.dn_spill; - - err = zio_read (bp, dn.endian, &sahdrp, NULL, data); - if (err) - return err; - free_sahdrp = true; - } - else - { - grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt"); - return grub_errno; - } - - hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); + err = parse_sa(&dn, &info->mtime, NULL, data); + if (err) + return err; info->mtimeset = 1; - info->mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian); - if (free_sahdrp) - grub_free (sahdrp); } - if (dn.dn.dn_bonustype == DMU_OT_ZNODE) + if (dn.dn_bonustype == DMU_OT_ZNODE) { info->mtimeset = 1; - info->mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0], dn.endian); + info->mtime = ((znode_phys_t *) DN_BONUS (&dn))->zp_mtime[0]; } return 0; } @@ -4228,7 +4377,7 @@ iterate_zap (const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx) grub_err_t err; struct grub_dirhook_info info; - dnode_end_t dn; + dnode_phys_t dn; grub_memset (&info, 0, sizeof (info)); err = dnode_get (&(ctx->data->subvol.mdn), val, 0, &dn, ctx->data); @@ -4238,52 +4387,22 @@ iterate_zap (const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx) return 0; } - if (dn.dn.dn_bonustype == DMU_OT_SA) + if (dn.dn_bonustype == DMU_OT_SA) { - void *sahdrp; - int hdrsize; - bool free_sahdrp = false; - - if (dn.dn.dn_bonuslen != 0) - { - sahdrp = (sa_hdr_phys_t *) DN_BONUS (&ctx->data->dnode.dn); - } - else if (dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR) - { - blkptr_t *bp = &dn.dn.dn_spill; - - err = zio_read (bp, dn.endian, &sahdrp, NULL, ctx->data); - if (err) - { - grub_print_error (); - return 0; - } - free_sahdrp = true; - } - else - { - grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt"); - grub_print_error (); - return 0; - } - - hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); + err = parse_sa(&dn, &info.mtime, NULL, ctx->data); + if (err) + return err; info.mtimeset = 1; - info.mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian); - info.case_insensitive = ctx->data->subvol.case_insensitive; - if (free_sahdrp) - grub_free (sahdrp); } - if (dn.dn.dn_bonustype == DMU_OT_ZNODE) + if (dn.dn_bonustype == DMU_OT_ZNODE) { info.mtimeset = 1; - info.mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0], - dn.endian); + info.mtime = ((znode_phys_t *) DN_BONUS (&dn))->zp_mtime[0]; } - info.dir = (dn.dn.dn_type == DMU_OT_DIRECTORY_CONTENTS); + info.dir = (dn.dn_type == DMU_OT_DIRECTORY_CONTENTS); grub_dprintf ("zfs", "type=%d, name=%s\n", - (int)dn.dn.dn_type, (char *)name); + (int)dn.dn_type, (char *)name); return ctx->hook (name, &info, ctx->hook_data); } @@ -4298,15 +4417,15 @@ iterate_zap_fs (const char *name, grub_uint64_t val, if (name[0] == 0 && val == 0) return 0; - dnode_end_t mdn; + dnode_phys_t mdn; err = dnode_get (&(ctx->data->mos), val, 0, &mdn, ctx->data); if (err) { grub_errno = 0; return 0; } - if (mdn.dn.dn_type != DMU_OT_DSL_DIR && mdn.dn.dn_bonustype != DMU_OT_DSL_DIR) { - grub_dprintf ("zfs", "type = 0x%x, val = 0x%llx\n", mdn.dn.dn_type, (long long)val); + if (mdn.dn_type != DMU_OT_DSL_DIR && mdn.dn_bonustype != DMU_OT_DSL_DIR) { + grub_dprintf ("zfs", "type = 0x%x, val = 0x%llx\n", mdn.dn_type, (long long)val); return 0; } @@ -4330,7 +4449,7 @@ iterate_zap_snap (const char *name, grub_uint64_t val, int ret; grub_size_t sz; - dnode_end_t mdn; + dnode_phys_t mdn; err = dnode_get (&(ctx->data->mos), val, 0, &mdn, ctx->data); if (err) @@ -4339,7 +4458,7 @@ iterate_zap_snap (const char *name, grub_uint64_t val, return 0; } - if (mdn.dn.dn_type != DMU_OT_DSL_DATASET && mdn.dn.dn_bonustype != DMU_OT_DSL_DATASET) + if (mdn.dn_type != DMU_OT_DSL_DATASET && mdn.dn_bonustype != DMU_OT_DSL_DATASET) return 0; err = fill_fs_info (&info, &mdn, ctx->data); @@ -4390,7 +4509,7 @@ grub_zfs_dir (grub_device_t device, const char *path, { grub_uint64_t childobj, headobj; grub_uint64_t snapobj; - dnode_end_t dn; + dnode_phys_t dn; struct grub_dirhook_info info; err = fill_fs_info (&info, &data->dnode, data); @@ -4405,8 +4524,8 @@ grub_zfs_dir (grub_device_t device, const char *path, return GRUB_ERR_NONE; } - childobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&data->dnode.dn))->dd_child_dir_zapobj, data->dnode.endian); - headobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&data->dnode.dn))->dd_head_dataset_obj, data->dnode.endian); + childobj = ((dsl_dir_phys_t *) DN_BONUS (&data->dnode))->dd_child_dir_zapobj; + headobj = ((dsl_dir_phys_t *) DN_BONUS (&data->dnode))->dd_head_dataset_obj; err = dnode_get (&(data->mos), childobj, DMU_OT_DSL_DIR_CHILD_MAP, &dn, data); if (err) @@ -4418,7 +4537,7 @@ grub_zfs_dir (grub_device_t device, const char *path, zap_iterate_u64 (&dn, iterate_zap_fs, data, &ctx); err = dnode_get (&(data->mos), headobj, 0, &dn, data); - if (!err && dn.dn.dn_type != DMU_OT_DSL_DATASET && dn.dn.dn_bonustype != DMU_OT_DSL_DATASET) + if (!err && dn.dn_type != DMU_OT_DSL_DATASET && dn.dn_bonustype != DMU_OT_DSL_DATASET) return grub_error(GRUB_ERR_BAD_FS, "incorrect dataset dnode type"); if (err) @@ -4427,7 +4546,7 @@ grub_zfs_dir (grub_device_t device, const char *path, return err; } - snapobj = grub_zfs_to_cpu64 (((dsl_dataset_phys_t *) DN_BONUS (&dn.dn))->ds_snapnames_zapobj, dn.endian); + snapobj = ((dsl_dataset_phys_t *) DN_BONUS (&dn))->ds_snapnames_zapobj; err = dnode_get (&(data->mos), snapobj, DMU_OT_DSL_DS_SNAP_MAP, &dn, data); @@ -4441,7 +4560,7 @@ grub_zfs_dir (grub_device_t device, const char *path, } else { - if (data->dnode.dn.dn_type != DMU_OT_DIRECTORY_CONTENTS) + if (data->dnode.dn_type != DMU_OT_DIRECTORY_CONTENTS) { zfs_unmount (data); return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); @@ -4477,16 +4596,14 @@ check_feature (const char *name, grub_uint64_t val, */ static grub_err_t -check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct grub_zfs_data* data ) +check_mos_features(dnode_phys_t *mosmdn_phys, struct grub_zfs_data* data ) { grub_uint64_t objnum; - grub_err_t errnum = 0; - dnode_end_t dn,mosmdn; + grub_err_t errnum = 0, ret = 0; + dnode_phys_t dn,mosmdn; mzap_phys_t* mzp; - grub_zfs_endian_t endianzap; - int size, ret; - grub_memmove(&(mosmdn.dn),mosmdn_phys,sizeof(dnode_phys_t)); - mosmdn.endian=endian; + int size; + grub_memmove(&mosmdn,mosmdn_phys,sizeof(dnode_phys_t)); errnum = dnode_get(&mosmdn, DMU_POOL_DIRECTORY_OBJECT, DMU_OT_OBJECT_DIRECTORY, &dn,data); if (errnum != 0) @@ -4505,12 +4622,12 @@ check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct gru if (errnum != 0) return errnum; - errnum = dmu_read(&dn, 0, (void**)&mzp, &endianzap,data); + errnum = dmu_read(&dn, 0, (void**)&mzp, data); if (errnum != 0) return errnum; - size = grub_zfs_to_cpu16 (dn.dn.dn_datablkszsec, dn.endian) << SPA_MINBLOCKSHIFT; - ret = mzap_iterate (mzp,endianzap, size, check_feature,NULL); + size = dn.dn_datablkszsec << SPA_MINBLOCKSHIFT; + ret = mzap_iterate (mzp, size, check_feature,NULL); grub_free(mzp); return ret; } diff --git a/grub-core/fs/zfs/zfs_fletcher.c b/grub-core/fs/zfs/zfs_fletcher.c index ad3be6705..deac0b45b 100644 --- a/grub-core/fs/zfs/zfs_fletcher.c +++ b/grub-core/fs/zfs/zfs_fletcher.c @@ -54,10 +54,10 @@ fletcher_2(const void *buf, grub_uint64_t size, grub_zfs_endian_t endian, b1 += a1; } - zcp->zc_word[0] = grub_cpu_to_zfs64 (a0, endian); - zcp->zc_word[1] = grub_cpu_to_zfs64 (a1, endian); - zcp->zc_word[2] = grub_cpu_to_zfs64 (b0, endian); - zcp->zc_word[3] = grub_cpu_to_zfs64 (b1, endian); + zcp->zc_word[0] = a0; + zcp->zc_word[1] = a1; + zcp->zc_word[2] = b0; + zcp->zc_word[3] = b1; } void @@ -70,15 +70,15 @@ fletcher_4 (const void *buf, grub_uint64_t size, grub_zfs_endian_t endian, for (a = b = c = d = 0; ip < ipend; ip++) { - a += grub_zfs_to_cpu32 (ip[0], endian);; + a += grub_zfs_to_cpu32 (ip[0], endian); b += a; c += b; d += c; } - zcp->zc_word[0] = grub_cpu_to_zfs64 (a, endian); - zcp->zc_word[1] = grub_cpu_to_zfs64 (b, endian); - zcp->zc_word[2] = grub_cpu_to_zfs64 (c, endian); - zcp->zc_word[3] = grub_cpu_to_zfs64 (d, endian); + zcp->zc_word[0] = a; + zcp->zc_word[1] = b; + zcp->zc_word[2] = c; + zcp->zc_word[3] = d; } diff --git a/grub-core/fs/zfs/zfs_sha256.c b/grub-core/fs/zfs/zfs_sha256.c index f042fa61a..69f1bd9d9 100644 --- a/grub-core/fs/zfs/zfs_sha256.c +++ b/grub-core/fs/zfs/zfs_sha256.c @@ -109,7 +109,7 @@ SHA256Transform(grub_uint32_t *H, const grub_uint8_t *cp) void zio_checksum_SHA256(const void *buf, grub_uint64_t size, - grub_zfs_endian_t endian, zio_cksum_t *zcp) + grub_zfs_endian_t endian __attribute__((unused)), zio_cksum_t *zcp) { grub_uint32_t H[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 }; @@ -132,12 +132,8 @@ zio_checksum_SHA256(const void *buf, grub_uint64_t size, for (i = 0; i < padsize && i <= 64; i += 64) SHA256Transform(H, pad + i); - zcp->zc_word[0] = grub_cpu_to_zfs64 ((grub_uint64_t)H[0] << 32 | H[1], - endian); - zcp->zc_word[1] = grub_cpu_to_zfs64 ((grub_uint64_t)H[2] << 32 | H[3], - endian); - zcp->zc_word[2] = grub_cpu_to_zfs64 ((grub_uint64_t)H[4] << 32 | H[5], - endian); - zcp->zc_word[3] = grub_cpu_to_zfs64 ((grub_uint64_t)H[6] << 32 | H[7], - endian); + zcp->zc_word[0] = (grub_uint64_t)H[0] << 32 | H[1]; + zcp->zc_word[1] = (grub_uint64_t)H[2] << 32 | H[3]; + zcp->zc_word[2] = (grub_uint64_t)H[4] << 32 | H[5]; + zcp->zc_word[3] = (grub_uint64_t)H[6] << 32 | H[7]; } diff --git a/grub-core/fs/zfs/zfscrypt.c b/grub-core/fs/zfs/zfscrypt.c index da30e9ab3..535fd4065 100644 --- a/grub-core/fs/zfs/zfscrypt.c +++ b/grub-core/fs/zfs/zfscrypt.c @@ -277,7 +277,7 @@ algo_decrypt (grub_crypto_cipher_handle_t cipher, grub_uint64_t algo, static grub_err_t grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher, grub_uint64_t algo, - void *nonce, + const void *nonce, char *buf, grub_size_t size, const grub_uint32_t *expected_mac, grub_zfs_endian_t endian) diff --git a/include/grub/zfs/sa_impl.h b/include/grub/zfs/sa_impl.h index 0845d1290..b92c458a4 100644 --- a/include/grub/zfs/sa_impl.h +++ b/include/grub/zfs/sa_impl.h @@ -29,6 +29,7 @@ typedef struct sa_hdr_phys { } sa_hdr_phys_t; #define SA_HDR_SIZE(hdr) BF32_GET_SB(hdr->sa_layout_info, 10, 16, 3, 0) +#define SA_MAGIC 0x2F505A #define SA_TYPE_OFFSET 0x0 #define SA_SIZE_OFFSET 0x8 #define SA_MTIME_OFFSET 0x38 diff --git a/include/grub/zfs/spa.h b/include/grub/zfs/spa.h index 5afbe4ecd..da44d1864 100644 --- a/include/grub/zfs/spa.h +++ b/include/grub/zfs/spa.h @@ -196,9 +196,18 @@ typedef struct blkptr { #define DVA_GET_VDEV(dva) BF64_GET((dva)->dva_word[0], 32, 32) #define DVA_SET_VDEV(dva, x) BF64_SET((dva)->dva_word[0], 32, 32, x) +#define DVA_GET_OFFSET(dva) \ + BF64_GET_SB((dva)->dva_word[1], 0, 63, SPA_MINBLOCKSHIFT, 0) +#define DVA_SET_OFFSET(dva, x) \ + BF64_SET_SB((dva)->dva_word[1], 0, 63, SPA_MINBLOCKSHIFT, 0, x) + #define DVA_GET_GANG(dva) BF64_GET((dva)->dva_word[1], 63, 1) #define DVA_SET_GANG(dva, x) BF64_SET((dva)->dva_word[1], 63, 1, x) +#define BP_GET_PSIZE(bp) \ + BF64_GET_SB((bp)->blk_prop, 16, 16, SPA_MINBLOCKSHIFT, 1) +#define BP_SET_PSIZE(bp, x) \ + BF64_SET_SB((bp)->blk_prop, 16, 16, SPA_MINBLOCKSHIFT, 1, x) #define BP_GET_LSIZE(bp) \ BF64_GET_SB((bp)->blk_prop, 0, 16, SPA_MINBLOCKSHIFT, 1) #define BP_SET_LSIZE(bp, x) \ diff --git a/include/grub/zfs/zfs.h b/include/grub/zfs/zfs.h index 4ee513887..0c5c40a73 100644 --- a/include/grub/zfs/zfs.h +++ b/include/grub/zfs/zfs.h @@ -33,6 +33,14 @@ typedef enum grub_zfs_endian GRUB_ZFS_BIG_ENDIAN = 0 } grub_zfs_endian_t; +#ifdef GRUB_CPU_WORDS_BIGENDIAN +#define GRUB_ZFS_IS_NATIVE_BYTEORDER(x) ((x) == GRUB_ZFS_BIG_ENDIAN) +#define GRUB_ZFS_NATIVE_ENDIAN GRUB_ZFS_BIG_ENDIAN +#else +#define GRUB_ZFS_IS_NATIVE_BYTEORDER(x) ((x) != GRUB_ZFS_BIG_ENDIAN) +#define GRUB_ZFS_NATIVE_ENDIAN GRUB_ZFS_LITTLE_ENDIAN +#endif + /* * On-disk version number. */ @@ -141,7 +149,7 @@ grub_zfs_add_key (grub_uint8_t *key_in, extern grub_err_t (*grub_zfs_decrypt) (grub_crypto_cipher_handle_t cipher, grub_uint64_t algo, - void *nonce, + const void *nonce, char *buf, grub_size_t size, const grub_uint32_t *expected_mac, grub_zfs_endian_t endian); -- 2.49.0 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel