~ubuntu-branches/ubuntu/trusty/grub2/trusty

« back to all changes in this revision

Viewing changes to grub-core/fs/zfs/zfs.c

  • Committer: Package Import Robot
  • Author(s): Colin Watson
  • Date: 2014-01-16 15:18:04 UTC
  • mfrom: (17.6.38 experimental)
  • Revision ID: package-import@ubuntu.com-20140116151804-3foouk7fpqcq3sxx
Tags: 2.02~beta2-2
* Convert patch handling to git-dpm.
* Add bi-endian support to ELF parser (Tomohiro B Berry).
* Adjust restore_mkdevicemap.patch to mark get_kfreebsd_version as static,
  to appease "gcc -Werror=missing-prototypes".
* Cherry-pick from upstream:
  - Change grub-macbless' manual page section to 8.
* Install grub-glue-efi, grub-macbless, grub-render-label, and
  grub-syslinux2cfg.
* grub-shell: Pass -no-pad to xorriso when building floppy images.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 *  GRUB  --  GRand Unified Bootloader
3
3
 *  Copyright (C) 1999,2000,2001,2002,2003,2004,2009,2010,2011  Free Software Foundation, Inc.
4
4
 *  Copyright 2010  Sun Microsystems, Inc.
 
5
 *  Copyright (c) 2012 by Delphix. All rights reserved.
5
6
 *
6
7
 *  GRUB is free software; you can redistribute it and/or modify
7
8
 *  it under the terms of the GNU General Public License as published by
128
129
static inline int
129
130
ZAP_LEAF_NUMCHUNKS (int bs)
130
131
{
131
 
  return (((1 << bs) - 2 * ZAP_LEAF_HASH_NUMENTRIES (bs)) /
 
132
  return (((1U << bs) - 2 * ZAP_LEAF_HASH_NUMENTRIES (bs)) /
132
133
          ZAP_LEAF_CHUNKSIZE - 2);
133
134
}
134
135
 
153
154
 
154
155
 
155
156
/*
156
 
 * Decompression Entry - lzjb
 
157
 * Decompression Entry - lzjb & lz4
157
158
 */
158
159
 
159
160
extern grub_err_t lzjb_decompress (void *, void *, grub_size_t, grub_size_t);
160
161
 
 
162
extern grub_err_t lz4_decompress (void *, void *, grub_size_t, grub_size_t);
 
163
 
161
164
typedef grub_err_t zfs_decomp_func_t (void *s_start, void *d_start,
162
165
                                      grub_size_t s_len, grub_size_t d_len);
163
166
typedef struct decomp_entry
176
179
 * Information about each checksum function.
177
180
 */
178
181
typedef struct zio_checksum_info {
179
 
        zio_checksum_t  *ci_func; /* checksum function for each byteorder */
180
 
        int             ci_correctable; /* number of correctable bits   */
181
 
        int             ci_eck;         /* uses zio embedded checksum? */
182
 
        const char              *ci_name;       /* descriptive name */
 
182
  zio_checksum_t        *ci_func; /* checksum function for each byteorder */
 
183
  int           ci_correctable; /* number of correctable bits   */
 
184
  int           ci_eck;         /* uses zio embedded checksum? */
 
185
  const char            *ci_name;       /* descriptive name */
183
186
} zio_checksum_info_t;
184
187
 
185
188
typedef struct dnode_end
253
256
  grub_uint64_t guid;
254
257
};
255
258
 
 
259
/* Context for grub_zfs_dir.  */
 
260
struct grub_zfs_dir_ctx
 
261
{
 
262
  grub_fs_dir_hook_t hook;
 
263
  void *hook_data;
 
264
  struct grub_zfs_data *data;
 
265
};
 
266
 
256
267
grub_err_t (*grub_zfs_decrypt) (grub_crypto_cipher_handle_t cipher,
257
268
                                grub_uint64_t algo,
258
269
                                void *nonce,
263
274
                                                  grub_size_t keysize,
264
275
                                                  grub_uint64_t salt,
265
276
                                                  grub_uint64_t algo) = NULL;
 
277
/*
 
278
 * List of pool features that the grub implementation of ZFS supports for
 
279
 * read. Note that features that are only required for write do not need
 
280
 * to be listed here since grub opens pools in read-only mode.
 
281
 */
 
282
#define MAX_SUPPORTED_FEATURE_STRLEN 50
 
283
static const char *spa_feature_names[] = {
 
284
  "org.illumos:lz4_compress",NULL
 
285
};
 
286
 
 
287
static int
 
288
check_feature(const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx);
 
289
static int
 
290
check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct grub_zfs_data* data );
266
291
 
267
292
static grub_err_t 
268
293
zlib_decompress (void *s, void *d,
269
294
                 grub_size_t slen, grub_size_t dlen)
270
295
{
271
 
  if (grub_zlib_decompress (s, slen, 0, d, dlen) < 0)
272
 
    return grub_errno;
273
 
  return GRUB_ERR_NONE;
 
296
  if (grub_zlib_decompress (s, slen, 0, d, dlen) == (grub_ssize_t) dlen)
 
297
    return GRUB_ERR_NONE;
 
298
 
 
299
  if (!grub_errno)
 
300
    grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
 
301
                "premature end of compressed");
 
302
  return grub_errno;
274
303
}
275
304
 
276
305
static grub_err_t 
322
351
  {"gzip-8", zlib_decompress},  /* ZIO_COMPRESS_GZIP8 */
323
352
  {"gzip-9", zlib_decompress},  /* ZIO_COMPRESS_GZIP9 */
324
353
  {"zle", zle_decompress},      /* ZIO_COMPRESS_ZLE   */
 
354
  {"lz4", lz4_decompress},      /* ZIO_COMPRESS_LZ4   */
325
355
};
326
356
 
327
357
static grub_err_t zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian,
341
371
      num = num >> 1;
342
372
    }
343
373
 
344
 
  return (i);
 
374
  return i;
345
375
}
346
376
 
347
377
/* Checksum Functions */
388
418
    {
389
419
      grub_dprintf ("zfs", "unknown checksum function %d\n", checksum);
390
420
      return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, 
391
 
                 "unknown checksum function %d", checksum);
 
421
                         "unknown checksum function %d", checksum);
392
422
    }
393
423
 
394
424
  if (ci->ci_eck)
449
479
 
450
480
  if (grub_zfs_to_cpu64 (ub1->ub_txg, ub1_endian) 
451
481
      < grub_zfs_to_cpu64 (ub2->ub_txg, ub2_endian))
452
 
    return (-1);
 
482
    return -1;
453
483
  if (grub_zfs_to_cpu64 (ub1->ub_txg, ub1_endian) 
454
484
      > grub_zfs_to_cpu64 (ub2->ub_txg, ub2_endian))
455
 
    return (1);
 
485
    return 1;
456
486
 
457
487
  if (grub_zfs_to_cpu64 (ub1->ub_timestamp, ub1_endian) 
458
488
      < grub_zfs_to_cpu64 (ub2->ub_timestamp, ub2_endian))
459
 
    return (-1);
 
489
    return -1;
460
490
  if (grub_zfs_to_cpu64 (ub1->ub_timestamp, ub1_endian) 
461
491
      > grub_zfs_to_cpu64 (ub2->ub_timestamp, ub2_endian))
462
 
    return (1);
 
492
    return 1;
463
493
 
464
 
  return (0);
 
494
  return 0;
465
495
}
466
496
 
467
497
/*
483
513
  if (grub_zfs_to_cpu64 (uber->ub_magic, GRUB_ZFS_LITTLE_ENDIAN)
484
514
      == UBERBLOCK_MAGIC
485
515
      && SPA_VERSION_IS_SUPPORTED(grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_LITTLE_ENDIAN)))
486
 
     endian = GRUB_ZFS_LITTLE_ENDIAN;
 
516
    endian = GRUB_ZFS_LITTLE_ENDIAN;
487
517
 
488
518
  if (grub_zfs_to_cpu64 (uber->ub_magic, GRUB_ZFS_BIG_ENDIAN) == UBERBLOCK_MAGIC
489
519
      && SPA_VERSION_IS_SUPPORTED(grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_BIG_ENDIAN)))
543
573
  if (!ubbest)
544
574
    grub_errno = err;
545
575
 
546
 
  return (ubbest);
 
576
  return ubbest;
547
577
}
548
578
 
549
579
static inline grub_size_t
760
790
}
761
791
 
762
792
/*
 
793
 * For a given XDR packed nvlist, verify the first 4 bytes and move on.
 
794
 *
 
795
 * An XDR packed nvlist is encoded as (comments from nvs_xdr_create) :
 
796
 *
 
797
 *      encoding method/host endian     (4 bytes)
 
798
 *      nvl_version                     (4 bytes)
 
799
 *      nvl_nvflag                      (4 bytes)
 
800
 *      encoded nvpairs:
 
801
 *              encoded size of the nvpair      (4 bytes)
 
802
 *              decoded size of the nvpair      (4 bytes)
 
803
 *              name string size                (4 bytes)
 
804
 *              name string data                (sizeof(NV_ALIGN4(string))
 
805
 *              data type                       (4 bytes)
 
806
 *              # of elements in the nvpair     (4 bytes)
 
807
 *              data
 
808
 *      2 zero's for the last nvpair
 
809
 *              (end of the entire list)        (8 bytes)
 
810
 *
 
811
 */
 
812
 
 
813
/*
 
814
 * The nvlist_next_nvpair() function returns a handle to the next nvpair in the
 
815
 * list following nvpair. If nvpair is NULL, the first pair is returned. If
 
816
 * nvpair is the last pair in the nvlist, NULL is returned.
 
817
 */
 
818
static const char *
 
819
nvlist_next_nvpair (const char *nvl, const char *nvpair)
 
820
{
 
821
  const char *nvp;
 
822
  int encode_size;
 
823
  int name_len;
 
824
  if (nvl == NULL)
 
825
    return NULL;
 
826
 
 
827
  if (nvpair == NULL)
 
828
    {
 
829
      /* skip over header, nvl_version and nvl_nvflag */
 
830
      nvpair = nvl + 4 * 3;
 
831
    } 
 
832
  else
 
833
    {
 
834
      /* skip to the next nvpair */
 
835
      encode_size = grub_be_to_cpu32 (grub_get_unaligned32(nvpair));
 
836
      nvpair += encode_size;
 
837
      /*If encode_size equals 0 nvlist_next_nvpair would return
 
838
       * the same pair received in input, leading to an infinite loop.
 
839
       * If encode_size is less than 0, this will move the pointer
 
840
       * backwards, *possibly* examinining two times the same nvpair
 
841
       * and potentially getting into an infinite loop. */
 
842
      if(encode_size <= 0)
 
843
        {
 
844
          grub_dprintf ("zfs", "nvpair with size <= 0\n");
 
845
          grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist");
 
846
          return NULL;
 
847
        }
 
848
    }
 
849
  /* 8 bytes of 0 marks the end of the list */
 
850
  if (grub_get_unaligned64 (nvpair) == 0)
 
851
    return NULL;
 
852
  /*consistency checks*/
 
853
  if (nvpair + 4 * 3 >= nvl + VDEV_PHYS_SIZE)
 
854
    {
 
855
      grub_dprintf ("zfs", "nvlist overflow\n");
 
856
      grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist");
 
857
      return NULL;
 
858
    }
 
859
  encode_size = grub_be_to_cpu32 (grub_get_unaligned32(nvpair));
 
860
 
 
861
  nvp = nvpair + 4*2;
 
862
  name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp));
 
863
  nvp += 4;
 
864
 
 
865
  nvp = nvp + ((name_len + 3) & ~3); // align 
 
866
  if (nvp + 4 >= nvl + VDEV_PHYS_SIZE                        
 
867
      || encode_size < 0
 
868
      || nvp + 4 + encode_size > nvl + VDEV_PHYS_SIZE)       
 
869
    {
 
870
      grub_dprintf ("zfs", "nvlist overflow\n");
 
871
      grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist");
 
872
      return NULL;
 
873
    }
 
874
  /* end consistency checks */
 
875
 
 
876
  return nvpair;
 
877
}
 
878
 
 
879
/*
 
880
 * This function returns 0 on success and 1 on failure. On success, a string
 
881
 * containing the name of nvpair is saved in buf.
 
882
 */
 
883
static int
 
884
nvpair_name (const char *nvp, char **buf, grub_size_t *buflen)
 
885
{
 
886
  /* skip over encode/decode size */
 
887
  nvp += 4 * 2;
 
888
        
 
889
  *buf = (char *) (nvp + 4);
 
890
  *buflen = grub_be_to_cpu32 (grub_get_unaligned32 (nvp));
 
891
 
 
892
  return 0;
 
893
}
 
894
 
 
895
/*
 
896
 * This function retrieves the value of the nvpair in the form of enumerated
 
897
 * type data_type_t.
 
898
 */
 
899
static int
 
900
nvpair_type (const char *nvp)
 
901
{
 
902
  int name_len, type;
 
903
 
 
904
  /* skip over encode/decode size */
 
905
  nvp += 4 * 2;
 
906
 
 
907
  /* skip over name_len */
 
908
  name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp));
 
909
  nvp += 4;
 
910
 
 
911
  /* skip over name */
 
912
  nvp = nvp + ((name_len + 3) & ~3); /* align */
 
913
 
 
914
  type = grub_be_to_cpu32 (grub_get_unaligned32 (nvp));
 
915
 
 
916
  return type;
 
917
}
 
918
 
 
919
static int
 
920
nvpair_value (const char *nvp,char **val,
 
921
              grub_size_t *size_out, grub_size_t *nelm_out)
 
922
{
 
923
  int name_len,nelm,encode_size;
 
924
 
 
925
  /* skip over encode/decode size */
 
926
  encode_size = grub_be_to_cpu32 (grub_get_unaligned32(nvp));
 
927
  nvp += 8;
 
928
 
 
929
  /* skip over name_len */
 
930
  name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp));
 
931
  nvp += 4;
 
932
 
 
933
  /* skip over name */
 
934
  nvp = nvp + ((name_len + 3) & ~3); /* align */
 
935
        
 
936
  /* skip over type */
 
937
  nvp += 4;
 
938
  nelm = grub_be_to_cpu32 (grub_get_unaligned32 (nvp));
 
939
  nvp +=4;
 
940
  if (nelm < 1)
 
941
    {
 
942
      grub_error (GRUB_ERR_BAD_FS, "empty nvpair");
 
943
      return 0;
 
944
    }
 
945
  *val = (char *) nvp;
 
946
  *size_out = encode_size;
 
947
  if (nelm_out)
 
948
    *nelm_out = nelm;
 
949
            
 
950
  return 1;
 
951
}
 
952
 
 
953
/*
763
954
 * Check the disk label information and retrieve needed vdev name-value pairs.
764
955
 *
765
956
 */
769
960
                  int *inserted)
770
961
{
771
962
  grub_uint64_t pool_state, txg = 0;
772
 
  char *nvlist;
 
963
  char *nvlist,*features;
773
964
#if 0
774
965
  char *nv;
775
966
#endif
777
968
  grub_uint64_t version;
778
969
  int found;
779
970
  grub_err_t err;
 
971
  grub_zfs_endian_t endian;
 
972
  vdev_phys_t *phys;
 
973
  zio_cksum_t emptycksum;
780
974
 
781
975
  *inserted = 0;
782
976
 
784
978
  if (err)
785
979
    return err;
786
980
 
 
981
  phys = (vdev_phys_t*) nvlist;
 
982
  if (grub_zfs_to_cpu64 (phys->vp_zbt.zec_magic,
 
983
                         GRUB_ZFS_LITTLE_ENDIAN)
 
984
      == ZEC_MAGIC)
 
985
    endian = GRUB_ZFS_LITTLE_ENDIAN;
 
986
  else if (grub_zfs_to_cpu64 (phys->vp_zbt.zec_magic,
 
987
                              GRUB_ZFS_BIG_ENDIAN)
 
988
           == ZEC_MAGIC)
 
989
    endian = GRUB_ZFS_BIG_ENDIAN;
 
990
  else
 
991
    {
 
992
      grub_free (nvlist);
 
993
      return grub_error (GRUB_ERR_BAD_FS,
 
994
                         "bad vdev_phys_t.vp_zbt.zec_magic number");
 
995
    }
 
996
  /* Now check the integrity of the vdev_phys_t structure though checksum.  */
 
997
  ZIO_SET_CHECKSUM(&emptycksum, diskdesc->vdev_phys_sector << 9, 0, 0, 0);
 
998
  err = zio_checksum_verify (emptycksum, ZIO_CHECKSUM_LABEL, endian,
 
999
                             nvlist, VDEV_PHYS_SIZE);
 
1000
  if (err)
 
1001
    return err;
 
1002
 
787
1003
  grub_dprintf ("zfs", "check 2 passed\n");
788
1004
 
789
1005
  found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_STATE,
889
1105
    grub_free (nv);
890
1106
  }
891
1107
  grub_dprintf ("zfs", "check 10 passed\n");
892
 
 
 
1108
  features = grub_zfs_nvlist_lookup_nvlist(nvlist,
 
1109
                                           ZPOOL_CONFIG_FEATURES_FOR_READ);
 
1110
  if (features)
 
1111
    {
 
1112
      const char *nvp=NULL;
 
1113
      char name[MAX_SUPPORTED_FEATURE_STRLEN + 1];
 
1114
      char *nameptr;
 
1115
      grub_size_t namelen;
 
1116
      while ((nvp = nvlist_next_nvpair(features, nvp)) != NULL)
 
1117
        {
 
1118
          nvpair_name (nvp, &nameptr, &namelen);
 
1119
          if(namelen > MAX_SUPPORTED_FEATURE_STRLEN)
 
1120
            namelen = MAX_SUPPORTED_FEATURE_STRLEN;
 
1121
          grub_memcpy (name, nameptr, namelen);
 
1122
          name[namelen] = '\0';
 
1123
          grub_dprintf("zfs","str=%s\n",name);
 
1124
          if (check_feature(name,1, NULL) != 0)
 
1125
            {
 
1126
              grub_dprintf("zfs","feature missing in check_pool_label:%s\n",name);
 
1127
              err= grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET," check_pool_label missing feature '%s' for read",name);
 
1128
              return err;
 
1129
            }
 
1130
        }
 
1131
    }
 
1132
  grub_dprintf ("zfs", "check 12 passed (feature flags)\n");
893
1133
  grub_free (nvlist);
894
1134
 
895
1135
  return GRUB_ERR_NONE;
984
1224
  return grub_error (GRUB_ERR_BAD_FS, "couldn't find a valid label");
985
1225
}
986
1226
 
 
1227
/* Helper for scan_devices.  */
 
1228
static int
 
1229
scan_devices_iter (const char *name, void *hook_data)
 
1230
{
 
1231
  struct grub_zfs_data *data = hook_data;
 
1232
  grub_device_t dev;
 
1233
  grub_err_t err;
 
1234
  int inserted;
 
1235
 
 
1236
  dev = grub_device_open (name);
 
1237
  if (!dev)
 
1238
    return 0;
 
1239
  if (!dev->disk)
 
1240
    {
 
1241
      grub_device_close (dev);
 
1242
      return 0;
 
1243
    }
 
1244
  err = scan_disk (dev, data, 0, &inserted);
 
1245
  if (err == GRUB_ERR_BAD_FS)
 
1246
    {
 
1247
      grub_device_close (dev);
 
1248
      grub_errno = GRUB_ERR_NONE;
 
1249
      return 0;
 
1250
    }
 
1251
  if (err)
 
1252
    {
 
1253
      grub_device_close (dev);
 
1254
      grub_print_error ();
 
1255
      return 0;
 
1256
    }
 
1257
 
 
1258
  if (!inserted)
 
1259
    grub_device_close (dev);
 
1260
  
 
1261
  return 0;
 
1262
}
 
1263
 
987
1264
static grub_err_t
988
1265
scan_devices (struct grub_zfs_data *data)
989
1266
{
990
 
  auto int hook (const char *name);
991
 
  int hook (const char *name)
992
 
  {
993
 
    grub_device_t dev;
994
 
    grub_err_t err;
995
 
    int inserted;
996
 
    dev = grub_device_open (name);
997
 
    if (!dev)
998
 
      return 0;
999
 
    if (!dev->disk)
1000
 
      {
1001
 
        grub_device_close (dev);
1002
 
        return 0;
1003
 
      }
1004
 
    err = scan_disk (dev, data, 0, &inserted);
1005
 
    if (err == GRUB_ERR_BAD_FS)
1006
 
      {
1007
 
        grub_device_close (dev);
1008
 
        grub_errno = GRUB_ERR_NONE;
1009
 
        return 0;
1010
 
      }
1011
 
    if (err)
1012
 
      {
1013
 
        grub_device_close (dev);
1014
 
        grub_print_error ();
1015
 
        return 0;
1016
 
      }
1017
 
 
1018
 
    if (!inserted)
1019
 
      grub_device_close (dev);
1020
 
    
1021
 
    return 0;
1022
 
  }
1023
 
  grub_device_iterate (hook);
 
1267
  grub_device_iterate (scan_devices_iter, data);
1024
1268
  return GRUB_ERR_NONE;
1025
1269
}
1026
1270
 
1033
1277
/* perform the operation a ^= b * (x ** (known_idx * recovery_pow) ) */
1034
1278
static inline void
1035
1279
xor_out (grub_uint8_t *a, const grub_uint8_t *b, grub_size_t s,
1036
 
         int known_idx, int recovery_pow)
 
1280
         unsigned known_idx, unsigned recovery_pow)
1037
1281
{
1038
 
  int add;
 
1282
  unsigned add;
1039
1283
 
1040
1284
  /* Simple xor.  */
1041
1285
  if (known_idx == 0 || recovery_pow == 0)
1057
1301
  return powx[powx_inv[a] + powx_inv[b]];
1058
1302
}
1059
1303
 
1060
 
static inline grub_err_t
 
1304
#define MAX_NBUFS 4
 
1305
 
 
1306
static grub_err_t
1061
1307
recovery (grub_uint8_t *bufs[4], grub_size_t s, const int nbufs,
1062
1308
          const unsigned *powers,
1063
 
          const int *idx)
 
1309
          const unsigned *idx)
1064
1310
{
1065
1311
  grub_dprintf ("zfs", "recovering %u buffers\n", nbufs);
1066
1312
  /* Now we have */
1111
1357
        return GRUB_ERR_NONE;
1112
1358
      }
1113
1359
      /* Otherwise use Gauss.  */
1114
 
    default:
 
1360
    case 3:
1115
1361
      {
1116
 
        grub_uint8_t matrix1[nbufs][nbufs], matrix2[nbufs][nbufs];
 
1362
        grub_uint8_t matrix1[MAX_NBUFS][MAX_NBUFS], matrix2[MAX_NBUFS][MAX_NBUFS];
1117
1363
        int i, j, k;
1118
1364
 
1119
1365
        for (i = 0; i < nbufs; i++)
1123
1369
          for (j = 0; j < nbufs; j++)
1124
1370
            matrix2[i][j] = 0;
1125
1371
        for (i = 0; i < nbufs; i++)
1126
 
            matrix2[i][i] = 1;
 
1372
          matrix2[i][i] = 1;
1127
1373
 
1128
1374
        for (i = 0; i < nbufs; i++)
1129
1375
          {
1181
1427
 
1182
1428
        for (i = 0; i < (int) s; i++)
1183
1429
          {
1184
 
            grub_uint8_t b[nbufs];
 
1430
            grub_uint8_t b[MAX_NBUFS];
1185
1431
            for (j = 0; j < nbufs; j++)
1186
1432
              b[j] = bufs[j][i];
1187
1433
            for (j = 0; j < nbufs; j++)
1193
1439
          }
1194
1440
        return GRUB_ERR_NONE;
1195
1441
      }
 
1442
    default:
 
1443
      return grub_error (GRUB_ERR_BUG, "too big matrix");
1196
1444
    }      
1197
1445
}
1198
1446
 
1230
1478
              break;
1231
1479
            grub_errno = GRUB_ERR_NONE;
1232
1480
          }
1233
 
        return (grub_errno = err);
 
1481
        grub_errno = err;
 
1482
 
 
1483
        return err;
1234
1484
      }
1235
1485
    case DEVICE_RAIDZ:
1236
1486
      {
1243
1493
        grub_size_t orig_len = len;
1244
1494
        grub_uint8_t *recovery_buf[4];
1245
1495
        grub_size_t recovery_len[4];
1246
 
        int recovery_idx[4];
 
1496
        unsigned recovery_idx[4];
1247
1497
        unsigned failed_devices = 0;
1248
1498
        int idx, orig_idx;
1249
1499
 
1649
1899
          err = grub_zfs_decrypt (data->subvol.keyring[besti].cipher,
1650
1900
                                  data->subvol.keyring[besti].algo,
1651
1901
                                  &(bp)->blk_dva[encrypted],
1652
 
                                  compbuf, psize, ((grub_uint32_t *) &zc + 5),
 
1902
                                  compbuf, psize, zc.zc_mac,
1653
1903
                                  endian);
1654
1904
        }
1655
1905
      if (err)
1782
2032
 
1783
2033
static int
1784
2034
mzap_iterate (mzap_phys_t * zapobj, grub_zfs_endian_t endian, int objsize, 
1785
 
              int NESTED_FUNC_ATTR (*hook) (const char *name, 
1786
 
                                            grub_uint64_t val))
 
2035
              int (*hook) (const char *name, grub_uint64_t val,
 
2036
                           struct grub_zfs_dir_ctx *ctx),
 
2037
              struct grub_zfs_dir_ctx *ctx)
1787
2038
{
1788
2039
  int i, chunks;
1789
2040
  mzap_ent_phys_t *mzap_ent = zapobj->mz_chunk;
1795
2046
                    mzap_ent[i].mze_name, (long long)mzap_ent[i].mze_value,
1796
2047
                    (int)mzap_ent[i].mze_cd);
1797
2048
      if (hook (mzap_ent[i].mze_name, 
1798
 
                grub_zfs_to_cpu64 (mzap_ent[i].mze_value, endian)))
 
2049
                grub_zfs_to_cpu64 (mzap_ent[i].mze_value, endian), ctx))
1799
2050
        return 1;
1800
2051
    }
1801
2052
 
1837
2088
   */
1838
2089
  crc &= ~((1ULL << (64 - ZAP_HASHBITS)) - 1);
1839
2090
 
1840
 
  return (crc);
 
2091
  return crc;
1841
2092
}
1842
2093
 
1843
2094
/*
1859
2110
  while (n--)
1860
2111
    {
1861
2112
      if (grub_toupper (*t1) != grub_toupper (*t2))
1862
 
          return (int) grub_toupper (*t1) - (int) grub_toupper (*t2);
 
2113
        return (int) grub_toupper (*t1) - (int) grub_toupper (*t2);
1863
2114
          
1864
2115
      t1++;
1865
2116
      t2++;
2046
2297
static int
2047
2298
fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap,
2048
2299
              grub_size_t name_elem_length,
2049
 
              int NESTED_FUNC_ATTR (*hook) (const void *name,
2050
 
                                            grub_size_t name_length,
2051
 
                                            const void *val_in,
2052
 
                                            grub_size_t nelem,
2053
 
                                            grub_size_t elemsize), 
2054
 
              struct grub_zfs_data *data)
 
2300
              int (*hook) (const void *name, grub_size_t name_length,
 
2301
                           const void *val_in,
 
2302
                           grub_size_t nelem, grub_size_t elemsize,
 
2303
                           void *data),
 
2304
              void *hook_data, struct grub_zfs_data *data)
2055
2305
{
2056
2306
  zap_leaf_phys_t *l;
2057
2307
  void *l_in;
2081
2331
  for (idx = 0; idx < (1ULL << zap->zap_ptrtbl.zt_shift); idx++)
2082
2332
    {
2083
2333
      blkid = grub_zfs_to_cpu64 (((grub_uint64_t *) zap)[idx + (1 << (blksft - 3 - 1))],
2084
 
                                         zap_dnode->endian);
 
2334
                                 zap_dnode->endian);
2085
2335
 
2086
2336
      for (idx2 = 0; idx2 < idx; idx2++)
2087
2337
        if (blkid == grub_zfs_to_cpu64 (((grub_uint64_t *) zap)[idx2 + (1 << (blksft - 3 - 1))],
2088
 
                                         zap_dnode->endian))
 
2338
                                        zap_dnode->endian))
2089
2339
          break;
2090
2340
      if (idx2 != idx)
2091
2341
        continue;
2111
2361
        }
2112
2362
 
2113
2363
      for (chunk = 0; chunk < ZAP_LEAF_NUMCHUNKS (blksft); chunk++)
2114
 
          {
2115
 
            char *buf;
2116
 
            struct zap_leaf_entry *le;
2117
 
            char *val;
2118
 
            grub_size_t val_length;
2119
 
            le = ZAP_LEAF_ENTRY (l, blksft, chunk);
2120
 
 
2121
 
            /* Verify the chunk entry */
2122
 
            if (le->le_type != ZAP_CHUNK_ENTRY)
2123
 
              continue;
2124
 
 
2125
 
            buf = grub_malloc (grub_zfs_to_cpu16 (le->le_name_length, endian)
2126
 
                               * name_elem_length + 1);
2127
 
            if (zap_leaf_array_get (l, endian, blksft,
2128
 
                                    grub_zfs_to_cpu16 (le->le_name_chunk,
2129
 
                                                       endian),
2130
 
                                    grub_zfs_to_cpu16 (le->le_name_length,
2131
 
                                                       endian)
2132
 
                                    * name_elem_length, buf))
2133
 
              {
2134
 
                grub_free (buf);
2135
 
                continue;
2136
 
              }
2137
 
            buf[le->le_name_length * name_elem_length] = 0;
2138
 
 
2139
 
            val_length = ((int) le->le_value_length
2140
 
                          * (int) le->le_int_size);
2141
 
            val = grub_malloc (grub_zfs_to_cpu16 (val_length, endian));
2142
 
            if (zap_leaf_array_get (l, endian, blksft,
2143
 
                                    grub_zfs_to_cpu16 (le->le_value_chunk,
2144
 
                                                       endian),
2145
 
                                    val_length, val))
2146
 
              {
2147
 
                grub_free (buf);
2148
 
                grub_free (val);
2149
 
                continue;
2150
 
              }
2151
 
 
2152
 
            if (hook (buf, le->le_name_length,
2153
 
                      val, le->le_value_length, le->le_int_size))
2154
 
              {
2155
 
                grub_free (l);
2156
 
                return 1;
2157
 
              }
2158
 
            grub_free (buf);
2159
 
            grub_free (val);
2160
 
          }
 
2364
        {
 
2365
          char *buf;
 
2366
          struct zap_leaf_entry *le;
 
2367
          char *val;
 
2368
          grub_size_t val_length;
 
2369
          le = ZAP_LEAF_ENTRY (l, blksft, chunk);
 
2370
 
 
2371
          /* Verify the chunk entry */
 
2372
          if (le->le_type != ZAP_CHUNK_ENTRY)
 
2373
            continue;
 
2374
 
 
2375
          buf = grub_malloc (grub_zfs_to_cpu16 (le->le_name_length, endian)
 
2376
                             * name_elem_length + 1);
 
2377
          if (zap_leaf_array_get (l, endian, blksft,
 
2378
                                  grub_zfs_to_cpu16 (le->le_name_chunk,
 
2379
                                                     endian),
 
2380
                                  grub_zfs_to_cpu16 (le->le_name_length,
 
2381
                                                     endian)
 
2382
                                  * name_elem_length, buf))
 
2383
            {
 
2384
              grub_free (buf);
 
2385
              continue;
 
2386
            }
 
2387
          buf[le->le_name_length * name_elem_length] = 0;
 
2388
 
 
2389
          val_length = ((int) le->le_value_length
 
2390
                        * (int) le->le_int_size);
 
2391
          val = grub_malloc (grub_zfs_to_cpu16 (val_length, endian));
 
2392
          if (zap_leaf_array_get (l, endian, blksft,
 
2393
                                  grub_zfs_to_cpu16 (le->le_value_chunk,
 
2394
                                                     endian),
 
2395
                                  val_length, val))
 
2396
            {
 
2397
              grub_free (buf);
 
2398
              grub_free (val);
 
2399
              continue;
 
2400
            }
 
2401
 
 
2402
          if (hook (buf, le->le_name_length,
 
2403
                    val, le->le_value_length, le->le_int_size, hook_data))
 
2404
            {
 
2405
              grub_free (l);
 
2406
              return 1;
 
2407
            }
 
2408
          grub_free (buf);
 
2409
          grub_free (val);
 
2410
        }
2161
2411
      grub_free (l);
2162
2412
    }
2163
2413
  return 0;
2213
2463
  return grub_error (GRUB_ERR_BAD_FS, "unknown ZAP type");
2214
2464
}
2215
2465
 
 
2466
/* Context for zap_iterate_u64.  */
 
2467
struct zap_iterate_u64_ctx
 
2468
{
 
2469
  int (*hook) (const char *, grub_uint64_t, struct grub_zfs_dir_ctx *);
 
2470
  struct grub_zfs_dir_ctx *dir_ctx;
 
2471
};
 
2472
 
 
2473
/* Helper for zap_iterate_u64.  */
 
2474
static int
 
2475
zap_iterate_u64_transform (const void *name,
 
2476
                           grub_size_t namelen __attribute__ ((unused)),
 
2477
                           const void *val_in,
 
2478
                           grub_size_t nelem,
 
2479
                           grub_size_t elemsize,
 
2480
                           void *data)
 
2481
{
 
2482
  struct zap_iterate_u64_ctx *ctx = data;
 
2483
 
 
2484
  if (elemsize != sizeof (grub_uint64_t) || nelem != 1)
 
2485
    return 0;
 
2486
  return ctx->hook (name, grub_be_to_cpu64 (*(const grub_uint64_t *) val_in),
 
2487
                    ctx->dir_ctx);
 
2488
}
 
2489
 
2216
2490
static int
2217
2491
zap_iterate_u64 (dnode_end_t * zap_dnode, 
2218
 
                 int NESTED_FUNC_ATTR (*hook) (const char *name,
2219
 
                                               grub_uint64_t val),
2220
 
                 struct grub_zfs_data *data)
 
2492
                 int (*hook) (const char *name, grub_uint64_t val,
 
2493
                              struct grub_zfs_dir_ctx *ctx),
 
2494
                 struct grub_zfs_data *data, struct grub_zfs_dir_ctx *ctx)
2221
2495
{
2222
2496
  grub_uint64_t block_type;
2223
2497
  int size;
2226
2500
  int ret;
2227
2501
  grub_zfs_endian_t endian;
2228
2502
 
2229
 
  auto int NESTED_FUNC_ATTR transform (const void *name,
2230
 
                                       grub_size_t namelen,
2231
 
                                       const void *val_in,
2232
 
                                       grub_size_t nelem,
2233
 
                                       grub_size_t elemsize);
2234
 
 
2235
 
  int NESTED_FUNC_ATTR transform (const void *name,
2236
 
                                  grub_size_t namelen __attribute__ ((unused)),
2237
 
                                  const void *val_in,
2238
 
                                  grub_size_t nelem,
2239
 
                                  grub_size_t elemsize)
2240
 
  {
2241
 
    if (elemsize != sizeof (grub_uint64_t) || nelem != 1)
2242
 
      return 0;
2243
 
    return hook (name, grub_be_to_cpu64 (*(const grub_uint64_t *) val_in));
2244
 
  }
2245
 
 
2246
2503
  /* Read in the first block of the zap object data. */
2247
2504
  size = grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, zap_dnode->endian) << SPA_MINBLOCKSHIFT;
2248
2505
  err = dmu_read (zap_dnode, 0, &zapbuf, &endian, data);
2255
2512
  if (block_type == ZBT_MICRO)
2256
2513
    {
2257
2514
      grub_dprintf ("zfs", "micro zap\n");
2258
 
      ret = mzap_iterate (zapbuf, endian, size, hook);
 
2515
      ret = mzap_iterate (zapbuf, endian, size, hook, ctx);
2259
2516
      grub_free (zapbuf);
2260
2517
      return ret;
2261
2518
    }
2262
2519
  else if (block_type == ZBT_HEADER)
2263
2520
    {
 
2521
      struct zap_iterate_u64_ctx transform_ctx = {
 
2522
        .hook = hook,
 
2523
        .dir_ctx = ctx
 
2524
      };
 
2525
 
2264
2526
      grub_dprintf ("zfs", "fat zap\n");
2265
2527
      /* this is a fat zap */
2266
 
      ret = fzap_iterate (zap_dnode, zapbuf, 1, transform, data);
 
2528
      ret = fzap_iterate (zap_dnode, zapbuf, 1,
 
2529
                          zap_iterate_u64_transform, &transform_ctx, data);
2267
2530
      grub_free (zapbuf);
2268
2531
      return ret;
2269
2532
    }
2274
2537
static int
2275
2538
zap_iterate (dnode_end_t * zap_dnode, 
2276
2539
             grub_size_t nameelemlen,
2277
 
             int NESTED_FUNC_ATTR (*hook) (const void *name,
2278
 
                                           grub_size_t namelen,
2279
 
                                           const void *val_in,
2280
 
                                           grub_size_t nelem,
2281
 
                                           grub_size_t elemsize),
2282
 
             struct grub_zfs_data *data)
 
2540
             int (*hook) (const void *name, grub_size_t namelen,
 
2541
                          const void *val_in,
 
2542
                          grub_size_t nelem, grub_size_t elemsize,
 
2543
                          void *data),
 
2544
             void *hook_data, struct grub_zfs_data *data)
2283
2545
{
2284
2546
  grub_uint64_t block_type;
2285
2547
  void *zapbuf;
2304
2566
    {
2305
2567
      grub_dprintf ("zfs", "fat zap\n");
2306
2568
      /* this is a fat zap */
2307
 
      ret = fzap_iterate (zap_dnode, zapbuf, nameelemlen, hook, data);
 
2569
      ret = fzap_iterate (zap_dnode, zapbuf, nameelemlen, hook, hook_data,
 
2570
                          data);
2308
2571
      grub_free (zapbuf);
2309
2572
      return ret;
2310
2573
    }
2538
2801
              grub_size_t block;
2539
2802
              grub_size_t blksz;
2540
2803
              blksz = (grub_zfs_to_cpu16 (dnode_path->dn.dn.dn_datablkszsec, 
2541
 
                                         dnode_path->dn.endian)
 
2804
                                          dnode_path->dn.endian)
2542
2805
                       << SPA_MINBLOCKSHIFT);
2543
2806
 
2544
2807
              sym_value = grub_malloc (sym_sz);
2583
2846
              grub_free (dn_new);
2584
2847
            }
2585
2848
          else while (dnode_path != root)
2586
 
            {
2587
 
              dn_new = dnode_path;
2588
 
              dnode_path = dn_new->next;
2589
 
              grub_free (dn_new);
2590
 
            }
 
2849
                 {
 
2850
                   dn_new = dnode_path;
 
2851
                   dnode_path = dn_new->next;
 
2852
                   grub_free (dn_new);
 
2853
                 }
2591
2854
        }
2592
2855
      if (dnode_path->dn.dn.dn_bonustype == DMU_OT_SA)
2593
2856
        {
2644
2907
                  grub_free (dn_new);
2645
2908
                }
2646
2909
              else while (dnode_path != root)
2647
 
                {
2648
 
                  dn_new = dnode_path;
2649
 
                  dnode_path = dn_new->next;
2650
 
                  grub_free (dn_new);
2651
 
                }
 
2910
                     {
 
2911
                       dn_new = dnode_path;
 
2912
                       dnode_path = dn_new->next;
 
2913
                       grub_free (dn_new);
 
2914
                     }
2652
2915
            }
2653
2916
        }
2654
2917
    }
2818
3081
  return GRUB_ERR_NONE;
2819
3082
}
2820
3083
 
 
3084
/* Context for dnode_get_fullpath.  */
 
3085
struct dnode_get_fullpath_ctx
 
3086
{
 
3087
  struct subvolume *subvol;
 
3088
  grub_uint64_t salt;
 
3089
  int keyn;
 
3090
};
 
3091
 
 
3092
/* Helper for dnode_get_fullpath.  */
 
3093
static int
 
3094
count_zap_keys (const void *name __attribute__ ((unused)),
 
3095
                grub_size_t namelen __attribute__ ((unused)),
 
3096
                const void *val_in __attribute__ ((unused)),
 
3097
                grub_size_t nelem __attribute__ ((unused)),
 
3098
                grub_size_t elemsize __attribute__ ((unused)),
 
3099
                void *data)
 
3100
{
 
3101
  struct dnode_get_fullpath_ctx *ctx = data;
 
3102
 
 
3103
  ctx->subvol->nkeys++;
 
3104
  return 0;
 
3105
}
 
3106
 
 
3107
/* Helper for dnode_get_fullpath.  */
 
3108
static int
 
3109
load_zap_key (const void *name, grub_size_t namelen, const void *val_in,
 
3110
              grub_size_t nelem, grub_size_t elemsize, void *data)
 
3111
{
 
3112
  struct dnode_get_fullpath_ctx *ctx = data;
 
3113
 
 
3114
  if (namelen != 1)
 
3115
    {
 
3116
      grub_dprintf ("zfs", "Unexpected key index size %" PRIuGRUB_SIZE "\n",
 
3117
                    namelen);
 
3118
      return 0;
 
3119
    }
 
3120
 
 
3121
  if (elemsize != 1)
 
3122
    {
 
3123
      grub_dprintf ("zfs", "Unexpected key element size %" PRIuGRUB_SIZE "\n",
 
3124
                    elemsize);
 
3125
      return 0;
 
3126
    }
 
3127
 
 
3128
  ctx->subvol->keyring[ctx->keyn].txg =
 
3129
    grub_be_to_cpu64 (*(grub_uint64_t *) name);
 
3130
  ctx->subvol->keyring[ctx->keyn].algo =
 
3131
    grub_le_to_cpu64 (*(grub_uint64_t *) val_in);
 
3132
  ctx->subvol->keyring[ctx->keyn].cipher =
 
3133
    grub_zfs_load_key (val_in, nelem, ctx->salt,
 
3134
                       ctx->subvol->keyring[ctx->keyn].algo);
 
3135
  ctx->keyn++;
 
3136
  return 0;
 
3137
}
 
3138
 
2821
3139
static grub_err_t
2822
3140
dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
2823
3141
                    dnode_end_t * dn, int *isfs,
2827
3145
  const char *ptr_at, *filename;
2828
3146
  grub_uint64_t headobj;
2829
3147
  grub_uint64_t keychainobj;
2830
 
  grub_uint64_t salt;
2831
3148
  grub_err_t err;
2832
 
  int keyn = 0;
2833
 
 
2834
 
  auto int NESTED_FUNC_ATTR count_zap_keys (const void *name,
2835
 
                                          grub_size_t namelen,
2836
 
                                          const void *val_in,
2837
 
                                          grub_size_t nelem,
2838
 
                                          grub_size_t elemsize);
2839
 
  int NESTED_FUNC_ATTR count_zap_keys (const void *name __attribute__ ((unused)),
2840
 
                                       grub_size_t namelen __attribute__ ((unused)),
2841
 
                                       const void *val_in __attribute__ ((unused)),
2842
 
                                       grub_size_t nelem __attribute__ ((unused)),
2843
 
                                       grub_size_t elemsize __attribute__ ((unused)))
2844
 
  {
2845
 
    subvol->nkeys++;
2846
 
    return 0;
2847
 
  }
2848
 
 
2849
 
  auto int NESTED_FUNC_ATTR load_zap_key (const void *name,
2850
 
                                          grub_size_t namelen,
2851
 
                                          const void *val_in,
2852
 
                                          grub_size_t nelem,
2853
 
                                          grub_size_t elemsize);
2854
 
  int NESTED_FUNC_ATTR load_zap_key (const void *name,
2855
 
                                     grub_size_t namelen,
2856
 
                                     const void *val_in,
2857
 
                                     grub_size_t nelem,
2858
 
                                     grub_size_t elemsize)
2859
 
  {
2860
 
    if (namelen != 1)
2861
 
      {
2862
 
        grub_dprintf ("zfs", "Unexpected key index size %" PRIuGRUB_SIZE "\n",
2863
 
                      namelen);
2864
 
        return 0;
2865
 
      }
2866
 
 
2867
 
    if (elemsize != 1)
2868
 
      {
2869
 
        grub_dprintf ("zfs", "Unexpected key element size %" PRIuGRUB_SIZE "\n",
2870
 
                      elemsize);
2871
 
        return 0;
2872
 
      }
2873
 
 
2874
 
    subvol->keyring[keyn].txg = grub_be_to_cpu64 (*(grub_uint64_t *) name);
2875
 
    subvol->keyring[keyn].algo = grub_le_to_cpu64 (*(grub_uint64_t *) val_in);
2876
 
    subvol->keyring[keyn].cipher = grub_zfs_load_key (val_in, nelem, salt,
2877
 
                                                      subvol->keyring[keyn].algo);
2878
 
    keyn++;
2879
 
    return 0;
2880
 
  }
2881
3149
 
2882
3150
  ptr_at = grub_strchr (fullpath, '@');
2883
3151
  if (! ptr_at)
2945
3213
  keychainobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&dn->dn))->keychain, dn->endian);
2946
3214
  if (grub_zfs_load_key && keychainobj)
2947
3215
    {
 
3216
      struct dnode_get_fullpath_ctx ctx = {
 
3217
        .subvol = subvol,
 
3218
        .keyn = 0
 
3219
      };
2948
3220
      dnode_end_t keychain_dn, props_dn;
2949
3221
      grub_uint64_t propsobj;
2950
3222
      propsobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&dn->dn))->dd_props_zapobj, dn->endian);
2958
3230
          return err;
2959
3231
        }
2960
3232
 
2961
 
      err = zap_lookup (&props_dn, "salt", &salt, data, 0);
 
3233
      err = zap_lookup (&props_dn, "salt", &ctx.salt, data, 0);
2962
3234
      if (err == GRUB_ERR_FILE_NOT_FOUND)
2963
3235
        {
2964
3236
          err = 0;
2965
3237
          grub_errno = 0;
2966
 
          salt = 0;
 
3238
          ctx.salt = 0;
2967
3239
        }
2968
3240
      if (err)
2969
3241
        {
2980
3252
          return err;
2981
3253
        }
2982
3254
      subvol->nkeys = 0;
2983
 
      zap_iterate (&keychain_dn, 8, count_zap_keys, data);
 
3255
      zap_iterate (&keychain_dn, 8, count_zap_keys, &ctx, data);
2984
3256
      subvol->keyring = grub_zalloc (subvol->nkeys * sizeof (subvol->keyring[0]));
2985
3257
      if (!subvol->keyring)
2986
3258
        {
2988
3260
          grub_free (snapname);
2989
3261
          return err;
2990
3262
        }
2991
 
      zap_iterate (&keychain_dn, 8, load_zap_key, data);
 
3263
      zap_iterate (&keychain_dn, 8, load_zap_key, &ctx, data);
2992
3264
    }
2993
3265
 
2994
3266
  if (snapname)
3030
3302
  return err;
3031
3303
}
3032
3304
 
3033
 
/*
3034
 
 * For a given XDR packed nvlist, verify the first 4 bytes and move on.
3035
 
 *
3036
 
 * An XDR packed nvlist is encoded as (comments from nvs_xdr_create) :
3037
 
 *
3038
 
 *      encoding method/host endian     (4 bytes)
3039
 
 *      nvl_version                     (4 bytes)
3040
 
 *      nvl_nvflag                      (4 bytes)
3041
 
 *      encoded nvpairs:
3042
 
 *              encoded size of the nvpair      (4 bytes)
3043
 
 *              decoded size of the nvpair      (4 bytes)
3044
 
 *              name string size                (4 bytes)
3045
 
 *              name string data                (sizeof(NV_ALIGN4(string))
3046
 
 *              data type                       (4 bytes)
3047
 
 *              # of elements in the nvpair     (4 bytes)
3048
 
 *              data
3049
 
 *      2 zero's for the last nvpair
3050
 
 *              (end of the entire list)        (8 bytes)
3051
 
 *
3052
 
 */
3053
 
 
3054
3305
static int
3055
3306
nvlist_find_value (const char *nvlist_in, const char *name,
3056
3307
                   int valtype, char **val,
3057
3308
                   grub_size_t *size_out, grub_size_t *nelm_out)
3058
3309
{
3059
 
  int name_len, type, encode_size;
3060
 
  const char *nvpair, *nvp_name, *nvlist = nvlist_in;
 
3310
  grub_size_t nvp_name_len, name_len = grub_strlen(name);
 
3311
  int type;
 
3312
  const char *nvpair=NULL,*nvlist=nvlist_in;
 
3313
  char *nvp_name;
3061
3314
 
3062
3315
  /* Verify if the 1st and 2nd byte in the nvlist are valid. */
3063
3316
  /* NOTE: independently of what endianness header announces all 
3070
3323
      return 0;
3071
3324
    }
3072
3325
 
3073
 
  /* skip the header, nvl_version, and nvl_nvflag */
3074
 
  nvlist = nvlist + 4 * 3;
3075
3326
  /*
3076
3327
   * Loop thru the nvpair list
3077
3328
   * The XDR representation of an integer is in big-endian byte order.
3078
3329
   */
3079
 
  while ((encode_size = grub_be_to_cpu32 (grub_get_unaligned32 (nvlist))))
 
3330
  while ((nvpair=nvlist_next_nvpair(nvlist,nvpair)))
3080
3331
    {
3081
 
      int nelm;
3082
 
 
3083
 
      if (nvlist + 4 * 4 >= nvlist_in + VDEV_PHYS_SIZE)
3084
 
        {
3085
 
          grub_dprintf ("zfs", "nvlist overflow\n");
3086
 
          grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist");
3087
 
          return 0;
3088
 
        }
3089
 
 
3090
 
      nvpair = nvlist + 4 * 2;  /* skip the encode/decode size */
3091
 
 
3092
 
      name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvpair));
3093
 
      nvpair += 4;
3094
 
 
3095
 
      nvp_name = nvpair;
3096
 
      nvpair = nvpair + ((name_len + 3) & ~3);  /* align */
3097
 
 
3098
 
      if (nvpair + 8 >= nvlist_in + VDEV_PHYS_SIZE
3099
 
          || encode_size < 0
3100
 
          || nvpair + 8 + encode_size > nvlist_in + VDEV_PHYS_SIZE)
3101
 
        {
3102
 
          grub_dprintf ("zfs", "nvlist overflow\n");
3103
 
          grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist");
3104
 
          return 0;
3105
 
        }
3106
 
 
3107
 
      type = grub_be_to_cpu32 (grub_get_unaligned32 (nvpair));
3108
 
      nvpair += 4;
3109
 
 
3110
 
      nelm = grub_be_to_cpu32 (grub_get_unaligned32 (nvpair));
3111
 
      if (nelm < 1)
3112
 
        {
3113
 
          grub_error (GRUB_ERR_BAD_FS, "empty nvpair");
3114
 
          return 0;
3115
 
        }
3116
 
 
3117
 
      nvpair += 4;
3118
 
 
3119
 
      if ((grub_strncmp (nvp_name, name, name_len) == 0) && type == valtype)
3120
 
        {
3121
 
          *val = (char *) nvpair;
3122
 
          *size_out = encode_size;
3123
 
          if (nelm_out)
3124
 
            *nelm_out = nelm;
3125
 
          return 1;
3126
 
        }
3127
 
 
3128
 
      nvlist += encode_size;    /* goto the next nvpair */
 
3332
      nvpair_name(nvpair,&nvp_name, &nvp_name_len);
 
3333
      type = nvpair_type(nvpair);
 
3334
      if (type == valtype
 
3335
          && (nvp_name_len == name_len
 
3336
              || (nvp_name_len > name_len && nvp_name[name_len] == '\0'))
 
3337
          && grub_memcmp (nvp_name, name, name_len) == 0)
 
3338
        {
 
3339
          return nvpair_value(nvpair,val,size_out,nelm_out);
 
3340
        }
3129
3341
    }
3130
3342
  return 0;
3131
3343
}
3382
3594
      return NULL;
3383
3595
    }
3384
3596
 
 
3597
  if (ub->ub_version >= SPA_VERSION_FEATURES &&
 
3598
      check_mos_features(&((objset_phys_t *) osp)->os_meta_dnode,ub_endian,
 
3599
                         data) != 0)
 
3600
    return NULL;
 
3601
        
3385
3602
  /* Got the MOS. Save it at the memory addr MOS. */
3386
3603
  grub_memmove (&(data->mos.dn), &((objset_phys_t *) osp)->os_meta_dnode,
3387
3604
                DNODE_SIZE);
3657
3874
  return err;
3658
3875
}
3659
3876
 
3660
 
static void
 
3877
static grub_err_t
3661
3878
fill_fs_info (struct grub_dirhook_info *info,
3662
3879
              dnode_end_t mdn, struct grub_zfs_data *data)
3663
3880
{
3678
3895
      if (err)
3679
3896
        {
3680
3897
          grub_dprintf ("zfs", "failed here\n");
3681
 
          return;
 
3898
          return err;
3682
3899
        }
3683
3900
    }
3684
 
  make_mdn (&mdn, data);
 
3901
  err = make_mdn (&mdn, data);
 
3902
  if (err)
 
3903
    return err;
3685
3904
  err = dnode_get (&mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE, 
3686
3905
                   &dn, data);
3687
3906
  if (err)
3688
3907
    {
3689
3908
      grub_dprintf ("zfs", "failed here\n");
3690
 
      return;
 
3909
      return err;
3691
3910
    }
3692
3911
  
3693
3912
  err = zap_lookup (&dn, ZFS_ROOT_OBJ, &objnum, data, 0);
3694
3913
  if (err)
3695
3914
    {
3696
3915
      grub_dprintf ("zfs", "failed here\n");
3697
 
      return;
 
3916
      return err;
3698
3917
    }
3699
3918
  
3700
3919
  err = dnode_get (&mdn, objnum, 0, &dn, data);
3701
3920
  if (err)
3702
3921
    {
3703
3922
      grub_dprintf ("zfs", "failed here\n");
3704
 
      return;
 
3923
      return err;
3705
3924
    }
3706
3925
  
3707
3926
  if (dn.dn.dn_bonustype == DMU_OT_SA)
3719
3938
 
3720
3939
          err = zio_read (bp, dn.endian, &sahdrp, NULL, data);
3721
3940
          if (err)
3722
 
            return;
 
3941
            return err;
3723
3942
        }
3724
3943
      else
3725
3944
        {
3726
3945
          grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt");
3727
 
          return;
 
3946
          return grub_errno;
3728
3947
        }
3729
3948
 
3730
3949
      hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp));
3737
3956
      info->mtimeset = 1;
3738
3957
      info->mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0], dn.endian);
3739
3958
    }
3740
 
  return;
 
3959
  return 0;
 
3960
}
 
3961
 
 
3962
/* Helper for grub_zfs_dir.  */
 
3963
static int
 
3964
iterate_zap (const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx)
 
3965
{
 
3966
  grub_err_t err;
 
3967
  struct grub_dirhook_info info;
 
3968
 
 
3969
  dnode_end_t dn;
 
3970
  grub_memset (&info, 0, sizeof (info));
 
3971
 
 
3972
  dnode_get (&(ctx->data->subvol.mdn), val, 0, &dn, ctx->data);
 
3973
 
 
3974
  if (dn.dn.dn_bonustype == DMU_OT_SA)
 
3975
    {
 
3976
      void *sahdrp;
 
3977
      int hdrsize;
 
3978
 
 
3979
      if (dn.dn.dn_bonuslen != 0)
 
3980
        {
 
3981
          sahdrp = (sa_hdr_phys_t *) DN_BONUS (&ctx->data->dnode.dn);
 
3982
        }
 
3983
      else if (dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR)
 
3984
        {
 
3985
          blkptr_t *bp = &dn.dn.dn_spill;
 
3986
 
 
3987
          err = zio_read (bp, dn.endian, &sahdrp, NULL, ctx->data);
 
3988
          if (err)
 
3989
            {
 
3990
              grub_print_error ();
 
3991
              return 0;
 
3992
            }
 
3993
        }
 
3994
      else
 
3995
        {
 
3996
          grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt");
 
3997
          grub_print_error ();
 
3998
          return 0;
 
3999
        }
 
4000
 
 
4001
      hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp));
 
4002
      info.mtimeset = 1;
 
4003
      info.mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian);
 
4004
      info.case_insensitive = ctx->data->subvol.case_insensitive;
 
4005
    }
 
4006
  
 
4007
  if (dn.dn.dn_bonustype == DMU_OT_ZNODE)
 
4008
    {   
 
4009
      info.mtimeset = 1;
 
4010
      info.mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0],
 
4011
                                      dn.endian);
 
4012
    }
 
4013
  info.dir = (dn.dn.dn_type == DMU_OT_DIRECTORY_CONTENTS);
 
4014
  grub_dprintf ("zfs", "type=%d, name=%s\n", 
 
4015
                (int)dn.dn.dn_type, (char *)name);
 
4016
  return ctx->hook (name, &info, ctx->hook_data);
 
4017
}
 
4018
 
 
4019
/* Helper for grub_zfs_dir.  */
 
4020
static int
 
4021
iterate_zap_fs (const char *name, grub_uint64_t val,
 
4022
                struct grub_zfs_dir_ctx *ctx)
 
4023
{
 
4024
  grub_err_t err;
 
4025
  struct grub_dirhook_info info;
 
4026
 
 
4027
  dnode_end_t mdn;
 
4028
  err = dnode_get (&(ctx->data->mos), val, 0, &mdn, ctx->data);
 
4029
  if (err)
 
4030
    {
 
4031
      grub_errno = 0;
 
4032
      return 0;
 
4033
    }
 
4034
  if (mdn.dn.dn_type != DMU_OT_DSL_DIR)
 
4035
    return 0;
 
4036
 
 
4037
  err = fill_fs_info (&info, mdn, ctx->data);
 
4038
  if (err)
 
4039
    {
 
4040
      grub_errno = 0;
 
4041
      return 0;
 
4042
    }
 
4043
  return ctx->hook (name, &info, ctx->hook_data);
 
4044
}
 
4045
 
 
4046
/* Helper for grub_zfs_dir.  */
 
4047
static int
 
4048
iterate_zap_snap (const char *name, grub_uint64_t val,
 
4049
                  struct grub_zfs_dir_ctx *ctx)
 
4050
{
 
4051
  grub_err_t err;
 
4052
  struct grub_dirhook_info info;
 
4053
  char *name2;
 
4054
  int ret;
 
4055
 
 
4056
  dnode_end_t mdn;
 
4057
 
 
4058
  err = dnode_get (&(ctx->data->mos), val, 0, &mdn, ctx->data);
 
4059
  if (err)
 
4060
    {
 
4061
      grub_errno = 0;
 
4062
      return 0;
 
4063
    }
 
4064
 
 
4065
  if (mdn.dn.dn_type != DMU_OT_DSL_DATASET)
 
4066
    return 0;
 
4067
 
 
4068
  err = fill_fs_info (&info, mdn, ctx->data);
 
4069
  if (err)
 
4070
    {
 
4071
      grub_errno = 0;
 
4072
      return 0;
 
4073
    }
 
4074
 
 
4075
  name2 = grub_malloc (grub_strlen (name) + 2);
 
4076
  name2[0] = '@';
 
4077
  grub_memcpy (name2 + 1, name, grub_strlen (name) + 1);
 
4078
  ret = ctx->hook (name2, &info, ctx->hook_data);
 
4079
  grub_free (name2);
 
4080
  return ret;
3741
4081
}
3742
4082
 
3743
4083
static grub_err_t
3744
4084
grub_zfs_dir (grub_device_t device, const char *path,
3745
 
              int (*hook) (const char *, const struct grub_dirhook_info *))
 
4085
              grub_fs_dir_hook_t hook, void *hook_data)
3746
4086
{
 
4087
  struct grub_zfs_dir_ctx ctx = {
 
4088
    .hook = hook,
 
4089
    .hook_data = hook_data
 
4090
  };
3747
4091
  struct grub_zfs_data *data;
3748
4092
  grub_err_t err;
3749
4093
  int isfs;
3750
 
  auto int NESTED_FUNC_ATTR iterate_zap (const char *name, grub_uint64_t val);
3751
 
  auto int NESTED_FUNC_ATTR iterate_zap_fs (const char *name, 
3752
 
                                            grub_uint64_t val);
3753
 
  auto int NESTED_FUNC_ATTR iterate_zap_snap (const char *name, 
3754
 
                                              grub_uint64_t val);
3755
 
 
3756
 
  int NESTED_FUNC_ATTR iterate_zap (const char *name, grub_uint64_t val)
3757
 
  {
3758
 
    struct grub_dirhook_info info;
3759
 
    dnode_end_t dn;
3760
 
    grub_memset (&info, 0, sizeof (info));
3761
 
 
3762
 
    dnode_get (&(data->subvol.mdn), val, 0, &dn, data);
3763
 
 
3764
 
    if (dn.dn.dn_bonustype == DMU_OT_SA)
3765
 
      {
3766
 
        void *sahdrp;
3767
 
        int hdrsize;
3768
 
 
3769
 
        if (dn.dn.dn_bonuslen != 0)
3770
 
          {
3771
 
            sahdrp = (sa_hdr_phys_t *) DN_BONUS (&data->dnode.dn);
3772
 
          }
3773
 
        else if (dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR)
3774
 
          {
3775
 
            blkptr_t *bp = &dn.dn.dn_spill;
3776
 
 
3777
 
            err = zio_read (bp, dn.endian, &sahdrp, NULL, data);
3778
 
            if (err)
3779
 
              {
3780
 
                grub_print_error ();
3781
 
                return 0;
3782
 
              }
3783
 
          }
3784
 
        else
3785
 
          {
3786
 
            grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt");
3787
 
            grub_print_error ();
3788
 
            return 0;
3789
 
          }
3790
 
 
3791
 
        hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp));
3792
 
        info.mtimeset = 1;
3793
 
        info.mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian);
3794
 
        info.case_insensitive = data->subvol.case_insensitive;
3795
 
      }
3796
 
    
3797
 
    if (dn.dn.dn_bonustype == DMU_OT_ZNODE)
3798
 
      { 
3799
 
        info.mtimeset = 1;
3800
 
        info.mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0],
3801
 
                                        dn.endian);
3802
 
      }
3803
 
        info.dir = (dn.dn.dn_type == DMU_OT_DIRECTORY_CONTENTS);
3804
 
        grub_dprintf ("zfs", "type=%d, name=%s\n", 
3805
 
                  (int)dn.dn.dn_type, (char *)name);
3806
 
    return hook (name, &info);
3807
 
  }
3808
 
 
3809
 
  int NESTED_FUNC_ATTR iterate_zap_fs (const char *name, grub_uint64_t val)
3810
 
  {
3811
 
    struct grub_dirhook_info info;
3812
 
    dnode_end_t mdn;
3813
 
    err = dnode_get (&(data->mos), val, 0, &mdn, data);
3814
 
    if (err)
3815
 
      return 0;
3816
 
    if (mdn.dn.dn_type != DMU_OT_DSL_DIR)
3817
 
      return 0;
3818
 
 
3819
 
    fill_fs_info (&info, mdn, data);
3820
 
    return hook (name, &info);
3821
 
  }
3822
 
  int NESTED_FUNC_ATTR iterate_zap_snap (const char *name, grub_uint64_t val)
3823
 
  {
3824
 
    struct grub_dirhook_info info;
3825
 
    char *name2;
3826
 
    int ret;
3827
 
    dnode_end_t mdn;
3828
 
 
3829
 
    err = dnode_get (&(data->mos), val, 0, &mdn, data);
3830
 
    if (err)
3831
 
      return 0;
3832
 
 
3833
 
    if (mdn.dn.dn_type != DMU_OT_DSL_DATASET)
3834
 
      return 0;
3835
 
 
3836
 
    fill_fs_info (&info, mdn, data);
3837
 
 
3838
 
    name2 = grub_malloc (grub_strlen (name) + 2);
3839
 
    name2[0] = '@';
3840
 
    grub_memcpy (name2 + 1, name, grub_strlen (name) + 1);
3841
 
    ret = hook (name2, &info);
3842
 
    grub_free (name2);
3843
 
    return ret;
3844
 
  }
3845
4094
 
3846
4095
  data = zfs_mount (device);
3847
4096
  if (! data)
3852
4101
      zfs_unmount (data);
3853
4102
      return err;
3854
4103
    }
 
4104
  ctx.data = data;
 
4105
 
3855
4106
  if (isfs)
3856
4107
    {
3857
4108
      grub_uint64_t childobj, headobj; 
3859
4110
      dnode_end_t dn;
3860
4111
      struct grub_dirhook_info info;
3861
4112
 
3862
 
      fill_fs_info (&info, data->dnode, data);
3863
 
      hook ("@", &info);
3864
 
      
 
4113
      err = fill_fs_info (&info, data->dnode, data);
 
4114
      if (err)
 
4115
        {
 
4116
          zfs_unmount (data);
 
4117
          return err;
 
4118
        }
 
4119
      if (hook ("@", &info, hook_data))
 
4120
        {
 
4121
          zfs_unmount (data);
 
4122
          return GRUB_ERR_NONE;
 
4123
        }
 
4124
 
3865
4125
      childobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&data->dnode.dn))->dd_child_dir_zapobj, data->dnode.endian);
3866
4126
      headobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&data->dnode.dn))->dd_head_dataset_obj, data->dnode.endian);
3867
4127
      err = dnode_get (&(data->mos), childobj,
3872
4132
          return err;
3873
4133
        }
3874
4134
 
3875
 
      zap_iterate_u64 (&dn, iterate_zap_fs, data);
 
4135
      zap_iterate_u64 (&dn, iterate_zap_fs, data, &ctx);
3876
4136
      
3877
4137
      err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, &dn, data);
3878
4138
      if (err)
3891
4151
          return err;
3892
4152
        }
3893
4153
 
3894
 
      zap_iterate_u64 (&dn, iterate_zap_snap, data);
 
4154
      zap_iterate_u64 (&dn, iterate_zap_snap, data, &ctx);
3895
4155
    }
3896
4156
  else
3897
4157
    {
3900
4160
          zfs_unmount (data);
3901
4161
          return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
3902
4162
        }
3903
 
      zap_iterate_u64 (&(data->dnode), iterate_zap, data);
 
4163
      zap_iterate_u64 (&(data->dnode), iterate_zap, data, &ctx);
3904
4164
    }
3905
4165
  zfs_unmount (data);
3906
4166
  return grub_errno;
3907
4167
}
3908
4168
 
 
4169
static int
 
4170
check_feature (const char *name, grub_uint64_t val,
 
4171
               struct grub_zfs_dir_ctx *ctx __attribute__((unused)))
 
4172
{
 
4173
  int i;
 
4174
  if (val == 0)
 
4175
    return 0;
 
4176
  if (name[0] == 0)
 
4177
    return 0;
 
4178
  for (i = 0; spa_feature_names[i] != NULL; i++) 
 
4179
    if (grub_strcmp (name, spa_feature_names[i]) == 0) 
 
4180
      return 0;
 
4181
  return 1;
 
4182
}
 
4183
 
 
4184
/*
 
4185
 * Checks whether the MOS features that are active are supported by this
 
4186
 * (GRUB's) implementation of ZFS.
 
4187
 *
 
4188
 * Return:
 
4189
 *      0: Success.
 
4190
 *      errnum: Failure.
 
4191
 */
 
4192
                   
 
4193
static int
 
4194
check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct grub_zfs_data* data )
 
4195
{
 
4196
  grub_uint64_t objnum;
 
4197
  grub_uint8_t errnum = 0;
 
4198
  dnode_end_t dn,mosmdn;
 
4199
  mzap_phys_t* mzp;
 
4200
  grub_zfs_endian_t endianzap;
 
4201
  int size;
 
4202
  grub_memmove(&(mosmdn.dn),mosmdn_phys,sizeof(dnode_phys_t));
 
4203
  mosmdn.endian=endian;
 
4204
  errnum = dnode_get(&mosmdn, DMU_POOL_DIRECTORY_OBJECT,
 
4205
                     DMU_OT_OBJECT_DIRECTORY, &dn,data);
 
4206
  if (errnum != 0)
 
4207
    return errnum;
 
4208
 
 
4209
  /*
 
4210
   * Find the object number for 'features_for_read' and retrieve its
 
4211
   * corresponding dnode. Note that we don't check features_for_write
 
4212
   * because GRUB is not opening the pool for write.
 
4213
   */
 
4214
  errnum = zap_lookup(&dn, DMU_POOL_FEATURES_FOR_READ, &objnum, data,0);
 
4215
  if (errnum != 0)
 
4216
    return errnum;
 
4217
  
 
4218
  errnum = dnode_get(&mosmdn, objnum, DMU_OTN_ZAP_METADATA, &dn, data);
 
4219
  if (errnum != 0)
 
4220
    return errnum;
 
4221
 
 
4222
  errnum = dmu_read(&dn, 0, (void**)&mzp, &endianzap,data);
 
4223
  if (errnum != 0)
 
4224
    return errnum;
 
4225
 
 
4226
  size = grub_zfs_to_cpu16 (dn.dn.dn_datablkszsec, dn.endian) << SPA_MINBLOCKSHIFT;
 
4227
  return mzap_iterate (mzp,endianzap, size, check_feature,NULL);
 
4228
}
 
4229
 
 
4230
 
3909
4231
#ifdef GRUB_UTIL
3910
4232
static grub_err_t
3911
4233
grub_zfs_embed (grub_device_t device __attribute__ ((unused)),
3920
4242
    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
3921
4243
                       "ZFS currently supports only PC-BIOS embedding");
3922
4244
 
3923
 
 if ((VDEV_BOOT_SIZE >> GRUB_DISK_SECTOR_BITS) < *nsectors)
 
4245
  if ((VDEV_BOOT_SIZE >> GRUB_DISK_SECTOR_BITS) < *nsectors)
3924
4246
    return grub_error (GRUB_ERR_OUT_OF_RANGE,
3925
4247
                       N_("your core.img is unusually large.  "
3926
4248
                          "It won't fit in the embedding area"));