diff -ruN grub2.orig/Makefile grub2/Makefile
--- grub2.orig/Makefile	2010-10-12 08:48:46.000000000 -0700
+++ grub2/Makefile	2010-10-13 06:34:59.000000000 -0700
@@ -35,6 +35,7 @@
 .endif
 
 PLIST_SUB+=	MKFONT=${MKFONT}
+MAKE_ENV+=	GRUB_CONTRIB="${WRKSRC}/grub-extras/"
 
 .if ${OSVERSION} < 700000
 BROKEN=		does not compile on 6.X
diff -ruN grub2.orig/files/patch-grub-extras-zfs grub2/files/patch-grub-extras-zfs
--- grub2.orig/files/patch-grub-extras-zfs	1969-12-31 16:00:00.000000000 -0800
+++ grub2/files/patch-grub-extras-zfs	2010-10-13 05:59:32.000000000 -0700
@@ -0,0 +1,6217 @@
+--- grub-1.98.orig/grub-extras/zfs/COPYING	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/COPYING	2010-10-13 00:16:54.874814000 -0700
+@@ -0,0 +1,674 @@
++                    GNU GENERAL PUBLIC LICENSE
++                       Version 3, 29 June 2007
++
++ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
++ Everyone is permitted to copy and distribute verbatim copies
++ of this license document, but changing it is not allowed.
++
++                            Preamble
++
++  The GNU General Public License is a free, copyleft license for
++software and other kinds of works.
++
++  The licenses for most software and other practical works are designed
++to take away your freedom to share and change the works.  By contrast,
++the GNU General Public License is intended to guarantee your freedom to
++share and change all versions of a program--to make sure it remains free
++software for all its users.  We, the Free Software Foundation, use the
++GNU General Public License for most of our software; it applies also to
++any other work released this way by its authors.  You can apply it to
++your programs, too.
++
++  When we speak of free software, we are referring to freedom, not
++price.  Our General Public Licenses are designed to make sure that you
++have the freedom to distribute copies of free software (and charge for
++them if you wish), that you receive source code or can get it if you
++want it, that you can change the software or use pieces of it in new
++free programs, and that you know you can do these things.
++
++  To protect your rights, we need to prevent others from denying you
++these rights or asking you to surrender the rights.  Therefore, you have
++certain responsibilities if you distribute copies of the software, or if
++you modify it: responsibilities to respect the freedom of others.
++
++  For example, if you distribute copies of such a program, whether
++gratis or for a fee, you must pass on to the recipients the same
++freedoms that you received.  You must make sure that they, too, receive
++or can get the source code.  And you must show them these terms so they
++know their rights.
++
++  Developers that use the GNU GPL protect your rights with two steps:
++(1) assert copyright on the software, and (2) offer you this License
++giving you legal permission to copy, distribute and/or modify it.
++
++  For the developers' and authors' protection, the GPL clearly explains
++that there is no warranty for this free software.  For both users' and
++authors' sake, the GPL requires that modified versions be marked as
++changed, so that their problems will not be attributed erroneously to
++authors of previous versions.
++
++  Some devices are designed to deny users access to install or run
++modified versions of the software inside them, although the manufacturer
++can do so.  This is fundamentally incompatible with the aim of
++protecting users' freedom to change the software.  The systematic
++pattern of such abuse occurs in the area of products for individuals to
++use, which is precisely where it is most unacceptable.  Therefore, we
++have designed this version of the GPL to prohibit the practice for those
++products.  If such problems arise substantially in other domains, we
++stand ready to extend this provision to those domains in future versions
++of the GPL, as needed to protect the freedom of users.
++
++  Finally, every program is threatened constantly by software patents.
++States should not allow patents to restrict development and use of
++software on general-purpose computers, but in those that do, we wish to
++avoid the special danger that patents applied to a free program could
++make it effectively proprietary.  To prevent this, the GPL assures that
++patents cannot be used to render the program non-free.
++
++  The precise terms and conditions for copying, distribution and
++modification follow.
++
++                       TERMS AND CONDITIONS
++
++  0. Definitions.
++
++  "This License" refers to version 3 of the GNU General Public License.
++
++  "Copyright" also means copyright-like laws that apply to other kinds of
++works, such as semiconductor masks.
++
++  "The Program" refers to any copyrightable work licensed under this
++License.  Each licensee is addressed as "you".  "Licensees" and
++"recipients" may be individuals or organizations.
++
++  To "modify" a work means to copy from or adapt all or part of the work
++in a fashion requiring copyright permission, other than the making of an
++exact copy.  The resulting work is called a "modified version" of the
++earlier work or a work "based on" the earlier work.
++
++  A "covered work" means either the unmodified Program or a work based
++on the Program.
++
++  To "propagate" a work means to do anything with it that, without
++permission, would make you directly or secondarily liable for
++infringement under applicable copyright law, except executing it on a
++computer or modifying a private copy.  Propagation includes copying,
++distribution (with or without modification), making available to the
++public, and in some countries other activities as well.
++
++  To "convey" a work means any kind of propagation that enables other
++parties to make or receive copies.  Mere interaction with a user through
++a computer network, with no transfer of a copy, is not conveying.
++
++  An interactive user interface displays "Appropriate Legal Notices"
++to the extent that it includes a convenient and prominently visible
++feature that (1) displays an appropriate copyright notice, and (2)
++tells the user that there is no warranty for the work (except to the
++extent that warranties are provided), that licensees may convey the
++work under this License, and how to view a copy of this License.  If
++the interface presents a list of user commands or options, such as a
++menu, a prominent item in the list meets this criterion.
++
++  1. Source Code.
++
++  The "source code" for a work means the preferred form of the work
++for making modifications to it.  "Object code" means any non-source
++form of a work.
++
++  A "Standard Interface" means an interface that either is an official
++standard defined by a recognized standards body, or, in the case of
++interfaces specified for a particular programming language, one that
++is widely used among developers working in that language.
++
++  The "System Libraries" of an executable work include anything, other
++than the work as a whole, that (a) is included in the normal form of
++packaging a Major Component, but which is not part of that Major
++Component, and (b) serves only to enable use of the work with that
++Major Component, or to implement a Standard Interface for which an
++implementation is available to the public in source code form.  A
++"Major Component", in this context, means a major essential component
++(kernel, window system, and so on) of the specific operating system
++(if any) on which the executable work runs, or a compiler used to
++produce the work, or an object code interpreter used to run it.
++
++  The "Corresponding Source" for a work in object code form means all
++the source code needed to generate, install, and (for an executable
++work) run the object code and to modify the work, including scripts to
++control those activities.  However, it does not include the work's
++System Libraries, or general-purpose tools or generally available free
++programs which are used unmodified in performing those activities but
++which are not part of the work.  For example, Corresponding Source
++includes interface definition files associated with source files for
++the work, and the source code for shared libraries and dynamically
++linked subprograms that the work is specifically designed to require,
++such as by intimate data communication or control flow between those
++subprograms and other parts of the work.
++
++  The Corresponding Source need not include anything that users
++can regenerate automatically from other parts of the Corresponding
++Source.
++
++  The Corresponding Source for a work in source code form is that
++same work.
++
++  2. Basic Permissions.
++
++  All rights granted under this License are granted for the term of
++copyright on the Program, and are irrevocable provided the stated
++conditions are met.  This License explicitly affirms your unlimited
++permission to run the unmodified Program.  The output from running a
++covered work is covered by this License only if the output, given its
++content, constitutes a covered work.  This License acknowledges your
++rights of fair use or other equivalent, as provided by copyright law.
++
++  You may make, run and propagate covered works that you do not
++convey, without conditions so long as your license otherwise remains
++in force.  You may convey covered works to others for the sole purpose
++of having them make modifications exclusively for you, or provide you
++with facilities for running those works, provided that you comply with
++the terms of this License in conveying all material for which you do
++not control copyright.  Those thus making or running the covered works
++for you must do so exclusively on your behalf, under your direction
++and control, on terms that prohibit them from making any copies of
++your copyrighted material outside their relationship with you.
++
++  Conveying under any other circumstances is permitted solely under
++the conditions stated below.  Sublicensing is not allowed; section 10
++makes it unnecessary.
++
++  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
++
++  No covered work shall be deemed part of an effective technological
++measure under any applicable law fulfilling obligations under article
++11 of the WIPO copyright treaty adopted on 20 December 1996, or
++similar laws prohibiting or restricting circumvention of such
++measures.
++
++  When you convey a covered work, you waive any legal power to forbid
++circumvention of technological measures to the extent such circumvention
++is effected by exercising rights under this License with respect to
++the covered work, and you disclaim any intention to limit operation or
++modification of the work as a means of enforcing, against the work's
++users, your or third parties' legal rights to forbid circumvention of
++technological measures.
++
++  4. Conveying Verbatim Copies.
++
++  You may convey verbatim copies of the Program's source code as you
++receive it, in any medium, provided that you conspicuously and
++appropriately publish on each copy an appropriate copyright notice;
++keep intact all notices stating that this License and any
++non-permissive terms added in accord with section 7 apply to the code;
++keep intact all notices of the absence of any warranty; and give all
++recipients a copy of this License along with the Program.
++
++  You may charge any price or no price for each copy that you convey,
++and you may offer support or warranty protection for a fee.
++
++  5. Conveying Modified Source Versions.
++
++  You may convey a work based on the Program, or the modifications to
++produce it from the Program, in the form of source code under the
++terms of section 4, provided that you also meet all of these conditions:
++
++    a) The work must carry prominent notices stating that you modified
++    it, and giving a relevant date.
++
++    b) The work must carry prominent notices stating that it is
++    released under this License and any conditions added under section
++    7.  This requirement modifies the requirement in section 4 to
++    "keep intact all notices".
++
++    c) You must license the entire work, as a whole, under this
++    License to anyone who comes into possession of a copy.  This
++    License will therefore apply, along with any applicable section 7
++    additional terms, to the whole of the work, and all its parts,
++    regardless of how they are packaged.  This License gives no
++    permission to license the work in any other way, but it does not
++    invalidate such permission if you have separately received it.
++
++    d) If the work has interactive user interfaces, each must display
++    Appropriate Legal Notices; however, if the Program has interactive
++    interfaces that do not display Appropriate Legal Notices, your
++    work need not make them do so.
++
++  A compilation of a covered work with other separate and independent
++works, which are not by their nature extensions of the covered work,
++and which are not combined with it such as to form a larger program,
++in or on a volume of a storage or distribution medium, is called an
++"aggregate" if the compilation and its resulting copyright are not
++used to limit the access or legal rights of the compilation's users
++beyond what the individual works permit.  Inclusion of a covered work
++in an aggregate does not cause this License to apply to the other
++parts of the aggregate.
++
++  6. Conveying Non-Source Forms.
++
++  You may convey a covered work in object code form under the terms
++of sections 4 and 5, provided that you also convey the
++machine-readable Corresponding Source under the terms of this License,
++in one of these ways:
++
++    a) Convey the object code in, or embodied in, a physical product
++    (including a physical distribution medium), accompanied by the
++    Corresponding Source fixed on a durable physical medium
++    customarily used for software interchange.
++
++    b) Convey the object code in, or embodied in, a physical product
++    (including a physical distribution medium), accompanied by a
++    written offer, valid for at least three years and valid for as
++    long as you offer spare parts or customer support for that product
++    model, to give anyone who possesses the object code either (1) a
++    copy of the Corresponding Source for all the software in the
++    product that is covered by this License, on a durable physical
++    medium customarily used for software interchange, for a price no
++    more than your reasonable cost of physically performing this
++    conveying of source, or (2) access to copy the
++    Corresponding Source from a network server at no charge.
++
++    c) Convey individual copies of the object code with a copy of the
++    written offer to provide the Corresponding Source.  This
++    alternative is allowed only occasionally and noncommercially, and
++    only if you received the object code with such an offer, in accord
++    with subsection 6b.
++
++    d) Convey the object code by offering access from a designated
++    place (gratis or for a charge), and offer equivalent access to the
++    Corresponding Source in the same way through the same place at no
++    further charge.  You need not require recipients to copy the
++    Corresponding Source along with the object code.  If the place to
++    copy the object code is a network server, the Corresponding Source
++    may be on a different server (operated by you or a third party)
++    that supports equivalent copying facilities, provided you maintain
++    clear directions next to the object code saying where to find the
++    Corresponding Source.  Regardless of what server hosts the
++    Corresponding Source, you remain obligated to ensure that it is
++    available for as long as needed to satisfy these requirements.
++
++    e) Convey the object code using peer-to-peer transmission, provided
++    you inform other peers where the object code and Corresponding
++    Source of the work are being offered to the general public at no
++    charge under subsection 6d.
++
++  A separable portion of the object code, whose source code is excluded
++from the Corresponding Source as a System Library, need not be
++included in conveying the object code work.
++
++  A "User Product" is either (1) a "consumer product", which means any
++tangible personal property which is normally used for personal, family,
++or household purposes, or (2) anything designed or sold for incorporation
++into a dwelling.  In determining whether a product is a consumer product,
++doubtful cases shall be resolved in favor of coverage.  For a particular
++product received by a particular user, "normally used" refers to a
++typical or common use of that class of product, regardless of the status
++of the particular user or of the way in which the particular user
++actually uses, or expects or is expected to use, the product.  A product
++is a consumer product regardless of whether the product has substantial
++commercial, industrial or non-consumer uses, unless such uses represent
++the only significant mode of use of the product.
++
++  "Installation Information" for a User Product means any methods,
++procedures, authorization keys, or other information required to install
++and execute modified versions of a covered work in that User Product from
++a modified version of its Corresponding Source.  The information must
++suffice to ensure that the continued functioning of the modified object
++code is in no case prevented or interfered with solely because
++modification has been made.
++
++  If you convey an object code work under this section in, or with, or
++specifically for use in, a User Product, and the conveying occurs as
++part of a transaction in which the right of possession and use of the
++User Product is transferred to the recipient in perpetuity or for a
++fixed term (regardless of how the transaction is characterized), the
++Corresponding Source conveyed under this section must be accompanied
++by the Installation Information.  But this requirement does not apply
++if neither you nor any third party retains the ability to install
++modified object code on the User Product (for example, the work has
++been installed in ROM).
++
++  The requirement to provide Installation Information does not include a
++requirement to continue to provide support service, warranty, or updates
++for a work that has been modified or installed by the recipient, or for
++the User Product in which it has been modified or installed.  Access to a
++network may be denied when the modification itself materially and
++adversely affects the operation of the network or violates the rules and
++protocols for communication across the network.
++
++  Corresponding Source conveyed, and Installation Information provided,
++in accord with this section must be in a format that is publicly
++documented (and with an implementation available to the public in
++source code form), and must require no special password or key for
++unpacking, reading or copying.
++
++  7. Additional Terms.
++
++  "Additional permissions" are terms that supplement the terms of this
++License by making exceptions from one or more of its conditions.
++Additional permissions that are applicable to the entire Program shall
++be treated as though they were included in this License, to the extent
++that they are valid under applicable law.  If additional permissions
++apply only to part of the Program, that part may be used separately
++under those permissions, but the entire Program remains governed by
++this License without regard to the additional permissions.
++
++  When you convey a copy of a covered work, you may at your option
++remove any additional permissions from that copy, or from any part of
++it.  (Additional permissions may be written to require their own
++removal in certain cases when you modify the work.)  You may place
++additional permissions on material, added by you to a covered work,
++for which you have or can give appropriate copyright permission.
++
++  Notwithstanding any other provision of this License, for material you
++add to a covered work, you may (if authorized by the copyright holders of
++that material) supplement the terms of this License with terms:
++
++    a) Disclaiming warranty or limiting liability differently from the
++    terms of sections 15 and 16 of this License; or
++
++    b) Requiring preservation of specified reasonable legal notices or
++    author attributions in that material or in the Appropriate Legal
++    Notices displayed by works containing it; or
++
++    c) Prohibiting misrepresentation of the origin of that material, or
++    requiring that modified versions of such material be marked in
++    reasonable ways as different from the original version; or
++
++    d) Limiting the use for publicity purposes of names of licensors or
++    authors of the material; or
++
++    e) Declining to grant rights under trademark law for use of some
++    trade names, trademarks, or service marks; or
++
++    f) Requiring indemnification of licensors and authors of that
++    material by anyone who conveys the material (or modified versions of
++    it) with contractual assumptions of liability to the recipient, for
++    any liability that these contractual assumptions directly impose on
++    those licensors and authors.
++
++  All other non-permissive additional terms are considered "further
++restrictions" within the meaning of section 10.  If the Program as you
++received it, or any part of it, contains a notice stating that it is
++governed by this License along with a term that is a further
++restriction, you may remove that term.  If a license document contains
++a further restriction but permits relicensing or conveying under this
++License, you may add to a covered work material governed by the terms
++of that license document, provided that the further restriction does
++not survive such relicensing or conveying.
++
++  If you add terms to a covered work in accord with this section, you
++must place, in the relevant source files, a statement of the
++additional terms that apply to those files, or a notice indicating
++where to find the applicable terms.
++
++  Additional terms, permissive or non-permissive, may be stated in the
++form of a separately written license, or stated as exceptions;
++the above requirements apply either way.
++
++  8. Termination.
++
++  You may not propagate or modify a covered work except as expressly
++provided under this License.  Any attempt otherwise to propagate or
++modify it is void, and will automatically terminate your rights under
++this License (including any patent licenses granted under the third
++paragraph of section 11).
++
++  However, if you cease all violation of this License, then your
++license from a particular copyright holder is reinstated (a)
++provisionally, unless and until the copyright holder explicitly and
++finally terminates your license, and (b) permanently, if the copyright
++holder fails to notify you of the violation by some reasonable means
++prior to 60 days after the cessation.
++
++  Moreover, your license from a particular copyright holder is
++reinstated permanently if the copyright holder notifies you of the
++violation by some reasonable means, this is the first time you have
++received notice of violation of this License (for any work) from that
++copyright holder, and you cure the violation prior to 30 days after
++your receipt of the notice.
++
++  Termination of your rights under this section does not terminate the
++licenses of parties who have received copies or rights from you under
++this License.  If your rights have been terminated and not permanently
++reinstated, you do not qualify to receive new licenses for the same
++material under section 10.
++
++  9. Acceptance Not Required for Having Copies.
++
++  You are not required to accept this License in order to receive or
++run a copy of the Program.  Ancillary propagation of a covered work
++occurring solely as a consequence of using peer-to-peer transmission
++to receive a copy likewise does not require acceptance.  However,
++nothing other than this License grants you permission to propagate or
++modify any covered work.  These actions infringe copyright if you do
++not accept this License.  Therefore, by modifying or propagating a
++covered work, you indicate your acceptance of this License to do so.
++
++  10. Automatic Licensing of Downstream Recipients.
++
++  Each time you convey a covered work, the recipient automatically
++receives a license from the original licensors, to run, modify and
++propagate that work, subject to this License.  You are not responsible
++for enforcing compliance by third parties with this License.
++
++  An "entity transaction" is a transaction transferring control of an
++organization, or substantially all assets of one, or subdividing an
++organization, or merging organizations.  If propagation of a covered
++work results from an entity transaction, each party to that
++transaction who receives a copy of the work also receives whatever
++licenses to the work the party's predecessor in interest had or could
++give under the previous paragraph, plus a right to possession of the
++Corresponding Source of the work from the predecessor in interest, if
++the predecessor has it or can get it with reasonable efforts.
++
++  You may not impose any further restrictions on the exercise of the
++rights granted or affirmed under this License.  For example, you may
++not impose a license fee, royalty, or other charge for exercise of
++rights granted under this License, and you may not initiate litigation
++(including a cross-claim or counterclaim in a lawsuit) alleging that
++any patent claim is infringed by making, using, selling, offering for
++sale, or importing the Program or any portion of it.
++
++  11. Patents.
++
++  A "contributor" is a copyright holder who authorizes use under this
++License of the Program or a work on which the Program is based.  The
++work thus licensed is called the contributor's "contributor version".
++
++  A contributor's "essential patent claims" are all patent claims
++owned or controlled by the contributor, whether already acquired or
++hereafter acquired, that would be infringed by some manner, permitted
++by this License, of making, using, or selling its contributor version,
++but do not include claims that would be infringed only as a
++consequence of further modification of the contributor version.  For
++purposes of this definition, "control" includes the right to grant
++patent sublicenses in a manner consistent with the requirements of
++this License.
++
++  Each contributor grants you a non-exclusive, worldwide, royalty-free
++patent license under the contributor's essential patent claims, to
++make, use, sell, offer for sale, import and otherwise run, modify and
++propagate the contents of its contributor version.
++
++  In the following three paragraphs, a "patent license" is any express
++agreement or commitment, however denominated, not to enforce a patent
++(such as an express permission to practice a patent or covenant not to
++sue for patent infringement).  To "grant" such a patent license to a
++party means to make such an agreement or commitment not to enforce a
++patent against the party.
++
++  If you convey a covered work, knowingly relying on a patent license,
++and the Corresponding Source of the work is not available for anyone
++to copy, free of charge and under the terms of this License, through a
++publicly available network server or other readily accessible means,
++then you must either (1) cause the Corresponding Source to be so
++available, or (2) arrange to deprive yourself of the benefit of the
++patent license for this particular work, or (3) arrange, in a manner
++consistent with the requirements of this License, to extend the patent
++license to downstream recipients.  "Knowingly relying" means you have
++actual knowledge that, but for the patent license, your conveying the
++covered work in a country, or your recipient's use of the covered work
++in a country, would infringe one or more identifiable patents in that
++country that you have reason to believe are valid.
++
++  If, pursuant to or in connection with a single transaction or
++arrangement, you convey, or propagate by procuring conveyance of, a
++covered work, and grant a patent license to some of the parties
++receiving the covered work authorizing them to use, propagate, modify
++or convey a specific copy of the covered work, then the patent license
++you grant is automatically extended to all recipients of the covered
++work and works based on it.
++
++  A patent license is "discriminatory" if it does not include within
++the scope of its coverage, prohibits the exercise of, or is
++conditioned on the non-exercise of one or more of the rights that are
++specifically granted under this License.  You may not convey a covered
++work if you are a party to an arrangement with a third party that is
++in the business of distributing software, under which you make payment
++to the third party based on the extent of your activity of conveying
++the work, and under which the third party grants, to any of the
++parties who would receive the covered work from you, a discriminatory
++patent license (a) in connection with copies of the covered work
++conveyed by you (or copies made from those copies), or (b) primarily
++for and in connection with specific products or compilations that
++contain the covered work, unless you entered into that arrangement,
++or that patent license was granted, prior to 28 March 2007.
++
++  Nothing in this License shall be construed as excluding or limiting
++any implied license or other defenses to infringement that may
++otherwise be available to you under applicable patent law.
++
++  12. No Surrender of Others' Freedom.
++
++  If conditions are imposed on you (whether by court order, agreement or
++otherwise) that contradict the conditions of this License, they do not
++excuse you from the conditions of this License.  If you cannot convey a
++covered work so as to satisfy simultaneously your obligations under this
++License and any other pertinent obligations, then as a consequence you may
++not convey it at all.  For example, if you agree to terms that obligate you
++to collect a royalty for further conveying from those to whom you convey
++the Program, the only way you could satisfy both those terms and this
++License would be to refrain entirely from conveying the Program.
++
++  13. Use with the GNU Affero General Public License.
++
++  Notwithstanding any other provision of this License, you have
++permission to link or combine any covered work with a work licensed
++under version 3 of the GNU Affero General Public License into a single
++combined work, and to convey the resulting work.  The terms of this
++License will continue to apply to the part which is the covered work,
++but the special requirements of the GNU Affero General Public License,
++section 13, concerning interaction through a network will apply to the
++combination as such.
++
++  14. Revised Versions of this License.
++
++  The Free Software Foundation may publish revised and/or new versions of
++the GNU General Public License from time to time.  Such new versions will
++be similar in spirit to the present version, but may differ in detail to
++address new problems or concerns.
++
++  Each version is given a distinguishing version number.  If the
++Program specifies that a certain numbered version of the GNU General
++Public License "or any later version" applies to it, you have the
++option of following the terms and conditions either of that numbered
++version or of any later version published by the Free Software
++Foundation.  If the Program does not specify a version number of the
++GNU General Public License, you may choose any version ever published
++by the Free Software Foundation.
++
++  If the Program specifies that a proxy can decide which future
++versions of the GNU General Public License can be used, that proxy's
++public statement of acceptance of a version permanently authorizes you
++to choose that version for the Program.
++
++  Later license versions may give you additional or different
++permissions.  However, no additional obligations are imposed on any
++author or copyright holder as a result of your choosing to follow a
++later version.
++
++  15. Disclaimer of Warranty.
++
++  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
++APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
++HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
++OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
++THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
++IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
++ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
++
++  16. Limitation of Liability.
++
++  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
++WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
++THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
++GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
++USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
++DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
++PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
++EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
++SUCH DAMAGES.
++
++  17. Interpretation of Sections 15 and 16.
++
++  If the disclaimer of warranty and limitation of liability provided
++above cannot be given local legal effect according to their terms,
++reviewing courts shall apply local law that most closely approximates
++an absolute waiver of all civil liability in connection with the
++Program, unless a warranty or assumption of liability accompanies a
++copy of the Program in return for a fee.
++
++                     END OF TERMS AND CONDITIONS
++
++            How to Apply These Terms to Your New Programs
++
++  If you develop a new program, and you want it to be of the greatest
++possible use to the public, the best way to achieve this is to make it
++free software which everyone can redistribute and change under these terms.
++
++  To do so, attach the following notices to the program.  It is safest
++to attach them to the start of each source file to most effectively
++state the exclusion of warranty; and each file should have at least
++the "copyright" line and a pointer to where the full notice is found.
++
++    <one line to give the program's name and a brief idea of what it does.>
++    Copyright (C) <year>  <name of author>
++
++    This program is free software: you can redistribute it and/or modify
++    it under the terms of the GNU General Public License as published by
++    the Free Software Foundation, either version 3 of the License, or
++    (at your option) any later version.
++
++    This program is distributed in the hope that it will be useful,
++    but WITHOUT ANY WARRANTY; without even the implied warranty of
++    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++    GNU General Public License for more details.
++
++    You should have received a copy of the GNU General Public License
++    along with this program.  If not, see <http://www.gnu.org/licenses/>.
++
++Also add information on how to contact you by electronic and paper mail.
++
++  If the program does terminal interaction, make it output a short
++notice like this when it starts in an interactive mode:
++
++    <program>  Copyright (C) <year>  <name of author>
++    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
++    This is free software, and you are welcome to redistribute it
++    under certain conditions; type `show c' for details.
++
++The hypothetical commands `show w' and `show c' should show the appropriate
++parts of the General Public License.  Of course, your program's commands
++might be different; for a GUI interface, you would use an "about box".
++
++  You should also get your employer (if you work as a programmer) or school,
++if any, to sign a "copyright disclaimer" for the program, if necessary.
++For more information on this, and how to apply and follow the GNU GPL, see
++<http://www.gnu.org/licenses/>.
++
++  The GNU General Public License does not permit incorporating your program
++into proprietary programs.  If your program is a subroutine library, you
++may consider it more useful to permit linking proprietary applications with
++the library.  If this is what you want to do, use the GNU Lesser General
++Public License instead of this License.  But first, please read
++<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+--- grub-1.98.orig/grub-extras/zfs/Makefile.common	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/Makefile.common	2010-10-13 00:16:54.874814000 -0700
+@@ -0,0 +1,2 @@
++ZFS_CPPFLAGS = -I$(top_srcdir)/contrib/zfs/include
++ZFS_CFLAGS = -Wno-error
+--- grub-1.98.orig/grub-extras/zfs/Makefile.core.def	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/Makefile.core.def	2010-10-13 00:16:54.874814000 -0700
+@@ -0,0 +1,18 @@
++AutoGen definitions Makefile.tpl;
++
++module = {
++  name = zfs;
++  common = contrib/zfs/zfs.c;
++  common = contrib/zfs/zfs_lzjb.c;
++  common = contrib/zfs/zfs_sha256.c;
++  common = contrib/zfs/zfs_fletcher.c;
++  cppflags = '$(ZFS_CPPFLAGS)';
++  cflags = '$(ZFS_CFLAGS)';
++};
++
++module = {
++  name = zfsinfo;
++  common = contrib/zfs/zfsinfo.c;
++  cppflags = '$(ZFS_CPPFLAGS)';
++  cflags = '$(ZFS_CFLAGS)';
++};
+--- grub-1.98.orig/grub-extras/zfs/Makefile.util.def	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/Makefile.util.def	2010-10-13 00:16:54.874814000 -0700
+@@ -0,0 +1,11 @@
++AutoGen definitions Makefile.tpl;
++
++library = {
++  name = libgrub.a;
++  common = contrib/zfs/zfs.c;
++  common = contrib/zfs/zfs_lzjb.c;
++  common = contrib/zfs/zfs_sha256.c;
++  common = contrib/zfs/zfs_fletcher.c;
++  cppflags = '$(ZFS_CPPFLAGS)';
++  cflags = '$(ZFS_CFLAGS)';
++};
+--- grub-1.98.orig/grub-extras/zfs/README	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/README	2010-10-13 00:16:54.874814000 -0700
+@@ -0,0 +1,11 @@
++
++grub-extras is meant to be used as an overlay on grub2 source tree.
++
++Build instructions:
++
++  - Copy grub-extras in a subdirectory of your grub2 checkout.
++    For example, "grub-extras".
++
++  - Export GRUB_CONTRIB environment variable to point to this directory.
++
++  - Build GRUB as usual.
+--- grub-1.98.orig/grub-extras/zfs/conf/common.mk	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/conf/common.mk	2010-10-13 03:53:02.000000000 -0700
+@@ -0,0 +1,623 @@
++# -*- makefile -*-
++# Generated by genmk.rb, please don't edit!
++
++COMMON_CFLAGS += -I$(GRUB_CONTRIB)/zfs/include
++
++pkglib_MODULES += zfs.mod
++zfs_mod_SOURCES = $(GRUB_CONTRIB)/zfs/zfs.c $(GRUB_CONTRIB)/zfs/zfs_lzjb.c $(GRUB_CONTRIB)/zfs/zfs_sha256.c $(GRUB_CONTRIB)/zfs/zfs_fletcher.c
++
++clean-module-zfs.mod.1:
++	rm -f zfs.mod mod-zfs.o mod-zfs.c pre-zfs.o zfs_mod-__GRUB_CONTRIB__zfs_zfs.o zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.o zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.o zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.o und-zfs.lst
++
++CLEAN_MODULE_TARGETS += clean-module-zfs.mod.1
++
++clean-module-zfs.mod-symbol.1:
++	rm -f def-zfs.lst
++
++CLEAN_MODULE_TARGETS += clean-module-zfs.mod-symbol.1
++DEFSYMFILES += def-zfs.lst
++mostlyclean-module-zfs.mod.1:
++	rm -f zfs_mod-__GRUB_CONTRIB__zfs_zfs.d zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.d zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.d zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.d
++
++MOSTLYCLEAN_MODULE_TARGETS += mostlyclean-module-zfs.mod.1
++UNDSYMFILES += und-zfs.lst
++
++ifneq ($(TARGET_APPLE_CC),1)
++zfs.mod: pre-zfs.o mod-zfs.o $(TARGET_OBJ2ELF)
++	-rm -f $@
++	$(TARGET_CC) $(zfs_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ pre-zfs.o mod-zfs.o
++	if test ! -z "$(TARGET_OBJ2ELF)"; then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
++	$(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
++else
++zfs.mod: pre-zfs.o mod-zfs.o $(TARGET_OBJ2ELF)
++	-rm -f $@
++	-rm -f $@.bin
++	$(TARGET_CC) $(zfs_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@.bin pre-zfs.o mod-zfs.o
++	$(OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -wd1106 -nu -nd $@.bin $@
++	-rm -f $@.bin
++endif
++
++pre-zfs.o: $(zfs_mod_DEPENDENCIES) zfs_mod-__GRUB_CONTRIB__zfs_zfs.o zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.o zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.o zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.o
++	-rm -f $@
++	$(TARGET_CC) $(zfs_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ zfs_mod-__GRUB_CONTRIB__zfs_zfs.o zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.o zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.o zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.o
++
++mod-zfs.o: mod-zfs.c
++	$(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -c -o $@ $<
++
++mod-zfs.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
++	sh $(srcdir)/genmodsrc.sh 'zfs' $< > $@ || (rm -f $@; exit 1)
++
++ifneq ($(TARGET_APPLE_CC),1)
++def-zfs.lst: pre-zfs.o
++	$(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 zfs/' > $@
++else
++def-zfs.lst: pre-zfs.o
++	$(NM) -g -P -p $< | grep -E '^[a-zA-Z0-9_]* [TDS]'  | sed 's/^\([^ ]*\).*/\1 zfs/' > $@
++endif
++
++und-zfs.lst: pre-zfs.o
++	echo 'zfs' > $@
++	$(NM) -u -P -p $< | cut -f1 -d' ' >> $@
++
++zfs_mod-__GRUB_CONTRIB__zfs_zfs.o: $(GRUB_CONTRIB)/zfs/zfs.c $($(GRUB_CONTRIB)/zfs/zfs.c_DEPENDENCIES)
++	$(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -MD -c -o $@ $<
++-include zfs_mod-__GRUB_CONTRIB__zfs_zfs.d
++
++clean-module-zfs_mod-__GRUB_CONTRIB__zfs_zfs-extra.1:
++	rm -f cmd-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst fs-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst partmap-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst handler-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst parttool-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst video-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst terminal-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst
++
++CLEAN_MODULE_TARGETS += clean-module-zfs_mod-__GRUB_CONTRIB__zfs_zfs-extra.1
++
++COMMANDFILES += cmd-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst
++FSFILES += fs-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst
++PARTTOOLFILES += parttool-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst
++PARTMAPFILES += partmap-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst
++HANDLERFILES += handler-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst
++TERMINALFILES += terminal-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst
++VIDEOFILES += video-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst
++
++cmd-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst: $(GRUB_CONTRIB)/zfs/zfs.c $($(GRUB_CONTRIB)/zfs/zfs.c_DEPENDENCIES) gencmdlist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/gencmdlist.sh zfs > $@ || (rm -f $@; exit 1)
++
++fs-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst: $(GRUB_CONTRIB)/zfs/zfs.c $($(GRUB_CONTRIB)/zfs/zfs.c_DEPENDENCIES) genfslist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genfslist.sh zfs > $@ || (rm -f $@; exit 1)
++
++parttool-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst: $(GRUB_CONTRIB)/zfs/zfs.c $($(GRUB_CONTRIB)/zfs/zfs.c_DEPENDENCIES) genparttoollist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genparttoollist.sh zfs > $@ || (rm -f $@; exit 1)
++
++partmap-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst: $(GRUB_CONTRIB)/zfs/zfs.c $($(GRUB_CONTRIB)/zfs/zfs.c_DEPENDENCIES) genpartmaplist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genpartmaplist.sh zfs > $@ || (rm -f $@; exit 1)
++
++handler-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst: $(GRUB_CONTRIB)/zfs/zfs.c $($(GRUB_CONTRIB)/zfs/zfs.c_DEPENDENCIES) genhandlerlist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genhandlerlist.sh zfs > $@ || (rm -f $@; exit 1)
++
++terminal-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst: $(GRUB_CONTRIB)/zfs/zfs.c $($(GRUB_CONTRIB)/zfs/zfs.c_DEPENDENCIES) genterminallist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genterminallist.sh zfs > $@ || (rm -f $@; exit 1)
++
++video-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst: $(GRUB_CONTRIB)/zfs/zfs.c $($(GRUB_CONTRIB)/zfs/zfs.c_DEPENDENCIES) genvideolist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genvideolist.sh zfs > $@ || (rm -f $@; exit 1)
++
++zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.o: $(GRUB_CONTRIB)/zfs/zfs_lzjb.c $($(GRUB_CONTRIB)/zfs/zfs_lzjb.c_DEPENDENCIES)
++	$(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -MD -c -o $@ $<
++-include zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.d
++
++clean-module-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb-extra.1:
++	rm -f cmd-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst fs-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst partmap-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst handler-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst parttool-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst video-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst terminal-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst
++
++CLEAN_MODULE_TARGETS += clean-module-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb-extra.1
++
++COMMANDFILES += cmd-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst
++FSFILES += fs-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst
++PARTTOOLFILES += parttool-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst
++PARTMAPFILES += partmap-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst
++HANDLERFILES += handler-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst
++TERMINALFILES += terminal-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst
++VIDEOFILES += video-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst
++
++cmd-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst: $(GRUB_CONTRIB)/zfs/zfs_lzjb.c $($(GRUB_CONTRIB)/zfs/zfs_lzjb.c_DEPENDENCIES) gencmdlist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/gencmdlist.sh zfs > $@ || (rm -f $@; exit 1)
++
++fs-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst: $(GRUB_CONTRIB)/zfs/zfs_lzjb.c $($(GRUB_CONTRIB)/zfs/zfs_lzjb.c_DEPENDENCIES) genfslist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genfslist.sh zfs > $@ || (rm -f $@; exit 1)
++
++parttool-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst: $(GRUB_CONTRIB)/zfs/zfs_lzjb.c $($(GRUB_CONTRIB)/zfs/zfs_lzjb.c_DEPENDENCIES) genparttoollist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genparttoollist.sh zfs > $@ || (rm -f $@; exit 1)
++
++partmap-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst: $(GRUB_CONTRIB)/zfs/zfs_lzjb.c $($(GRUB_CONTRIB)/zfs/zfs_lzjb.c_DEPENDENCIES) genpartmaplist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genpartmaplist.sh zfs > $@ || (rm -f $@; exit 1)
++
++handler-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst: $(GRUB_CONTRIB)/zfs/zfs_lzjb.c $($(GRUB_CONTRIB)/zfs/zfs_lzjb.c_DEPENDENCIES) genhandlerlist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genhandlerlist.sh zfs > $@ || (rm -f $@; exit 1)
++
++terminal-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst: $(GRUB_CONTRIB)/zfs/zfs_lzjb.c $($(GRUB_CONTRIB)/zfs/zfs_lzjb.c_DEPENDENCIES) genterminallist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genterminallist.sh zfs > $@ || (rm -f $@; exit 1)
++
++video-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst: $(GRUB_CONTRIB)/zfs/zfs_lzjb.c $($(GRUB_CONTRIB)/zfs/zfs_lzjb.c_DEPENDENCIES) genvideolist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genvideolist.sh zfs > $@ || (rm -f $@; exit 1)
++
++zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.o: $(GRUB_CONTRIB)/zfs/zfs_sha256.c $($(GRUB_CONTRIB)/zfs/zfs_sha256.c_DEPENDENCIES)
++	$(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -MD -c -o $@ $<
++-include zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.d
++
++clean-module-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256-extra.1:
++	rm -f cmd-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst fs-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst partmap-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst handler-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst parttool-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst video-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst terminal-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst
++
++CLEAN_MODULE_TARGETS += clean-module-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256-extra.1
++
++COMMANDFILES += cmd-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst
++FSFILES += fs-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst
++PARTTOOLFILES += parttool-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst
++PARTMAPFILES += partmap-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst
++HANDLERFILES += handler-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst
++TERMINALFILES += terminal-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst
++VIDEOFILES += video-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst
++
++cmd-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst: $(GRUB_CONTRIB)/zfs/zfs_sha256.c $($(GRUB_CONTRIB)/zfs/zfs_sha256.c_DEPENDENCIES) gencmdlist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/gencmdlist.sh zfs > $@ || (rm -f $@; exit 1)
++
++fs-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst: $(GRUB_CONTRIB)/zfs/zfs_sha256.c $($(GRUB_CONTRIB)/zfs/zfs_sha256.c_DEPENDENCIES) genfslist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genfslist.sh zfs > $@ || (rm -f $@; exit 1)
++
++parttool-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst: $(GRUB_CONTRIB)/zfs/zfs_sha256.c $($(GRUB_CONTRIB)/zfs/zfs_sha256.c_DEPENDENCIES) genparttoollist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genparttoollist.sh zfs > $@ || (rm -f $@; exit 1)
++
++partmap-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst: $(GRUB_CONTRIB)/zfs/zfs_sha256.c $($(GRUB_CONTRIB)/zfs/zfs_sha256.c_DEPENDENCIES) genpartmaplist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genpartmaplist.sh zfs > $@ || (rm -f $@; exit 1)
++
++handler-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst: $(GRUB_CONTRIB)/zfs/zfs_sha256.c $($(GRUB_CONTRIB)/zfs/zfs_sha256.c_DEPENDENCIES) genhandlerlist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genhandlerlist.sh zfs > $@ || (rm -f $@; exit 1)
++
++terminal-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst: $(GRUB_CONTRIB)/zfs/zfs_sha256.c $($(GRUB_CONTRIB)/zfs/zfs_sha256.c_DEPENDENCIES) genterminallist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genterminallist.sh zfs > $@ || (rm -f $@; exit 1)
++
++video-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst: $(GRUB_CONTRIB)/zfs/zfs_sha256.c $($(GRUB_CONTRIB)/zfs/zfs_sha256.c_DEPENDENCIES) genvideolist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genvideolist.sh zfs > $@ || (rm -f $@; exit 1)
++
++zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.o: $(GRUB_CONTRIB)/zfs/zfs_fletcher.c $($(GRUB_CONTRIB)/zfs/zfs_fletcher.c_DEPENDENCIES)
++	$(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -MD -c -o $@ $<
++-include zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.d
++
++clean-module-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher-extra.1:
++	rm -f cmd-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst fs-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst partmap-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst handler-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst parttool-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst video-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst terminal-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst
++
++CLEAN_MODULE_TARGETS += clean-module-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher-extra.1
++
++COMMANDFILES += cmd-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst
++FSFILES += fs-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst
++PARTTOOLFILES += parttool-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst
++PARTMAPFILES += partmap-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst
++HANDLERFILES += handler-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst
++TERMINALFILES += terminal-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst
++VIDEOFILES += video-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst
++
++cmd-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst: $(GRUB_CONTRIB)/zfs/zfs_fletcher.c $($(GRUB_CONTRIB)/zfs/zfs_fletcher.c_DEPENDENCIES) gencmdlist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/gencmdlist.sh zfs > $@ || (rm -f $@; exit 1)
++
++fs-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst: $(GRUB_CONTRIB)/zfs/zfs_fletcher.c $($(GRUB_CONTRIB)/zfs/zfs_fletcher.c_DEPENDENCIES) genfslist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genfslist.sh zfs > $@ || (rm -f $@; exit 1)
++
++parttool-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst: $(GRUB_CONTRIB)/zfs/zfs_fletcher.c $($(GRUB_CONTRIB)/zfs/zfs_fletcher.c_DEPENDENCIES) genparttoollist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genparttoollist.sh zfs > $@ || (rm -f $@; exit 1)
++
++partmap-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst: $(GRUB_CONTRIB)/zfs/zfs_fletcher.c $($(GRUB_CONTRIB)/zfs/zfs_fletcher.c_DEPENDENCIES) genpartmaplist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genpartmaplist.sh zfs > $@ || (rm -f $@; exit 1)
++
++handler-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst: $(GRUB_CONTRIB)/zfs/zfs_fletcher.c $($(GRUB_CONTRIB)/zfs/zfs_fletcher.c_DEPENDENCIES) genhandlerlist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genhandlerlist.sh zfs > $@ || (rm -f $@; exit 1)
++
++terminal-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst: $(GRUB_CONTRIB)/zfs/zfs_fletcher.c $($(GRUB_CONTRIB)/zfs/zfs_fletcher.c_DEPENDENCIES) genterminallist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genterminallist.sh zfs > $@ || (rm -f $@; exit 1)
++
++video-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst: $(GRUB_CONTRIB)/zfs/zfs_fletcher.c $($(GRUB_CONTRIB)/zfs/zfs_fletcher.c_DEPENDENCIES) genvideolist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genvideolist.sh zfs > $@ || (rm -f $@; exit 1)
++
++zfs_mod_CFLAGS = $(COMMON_CFLAGS) -Wno-error
++zfs_mod_LDFLAGS = $(COMMON_LDFLAGS)
++
++pkglib_MODULES += zfsinfo.mod
++zfsinfo_mod_SOURCES = $(GRUB_CONTRIB)/zfs/zfsinfo.c
++
++clean-module-zfsinfo.mod.1:
++	rm -f zfsinfo.mod mod-zfsinfo.o mod-zfsinfo.c pre-zfsinfo.o zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.o und-zfsinfo.lst
++
++CLEAN_MODULE_TARGETS += clean-module-zfsinfo.mod.1
++
++clean-module-zfsinfo.mod-symbol.1:
++	rm -f def-zfsinfo.lst
++
++CLEAN_MODULE_TARGETS += clean-module-zfsinfo.mod-symbol.1
++DEFSYMFILES += def-zfsinfo.lst
++mostlyclean-module-zfsinfo.mod.1:
++	rm -f zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.d
++
++MOSTLYCLEAN_MODULE_TARGETS += mostlyclean-module-zfsinfo.mod.1
++UNDSYMFILES += und-zfsinfo.lst
++
++ifneq ($(TARGET_APPLE_CC),1)
++zfsinfo.mod: pre-zfsinfo.o mod-zfsinfo.o $(TARGET_OBJ2ELF)
++	-rm -f $@
++	$(TARGET_CC) $(zfsinfo_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ pre-zfsinfo.o mod-zfsinfo.o
++	if test ! -z "$(TARGET_OBJ2ELF)"; then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
++	$(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
++else
++zfsinfo.mod: pre-zfsinfo.o mod-zfsinfo.o $(TARGET_OBJ2ELF)
++	-rm -f $@
++	-rm -f $@.bin
++	$(TARGET_CC) $(zfsinfo_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@.bin pre-zfsinfo.o mod-zfsinfo.o
++	$(OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -wd1106 -nu -nd $@.bin $@
++	-rm -f $@.bin
++endif
++
++pre-zfsinfo.o: $(zfsinfo_mod_DEPENDENCIES) zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.o
++	-rm -f $@
++	$(TARGET_CC) $(zfsinfo_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.o
++
++mod-zfsinfo.o: mod-zfsinfo.c
++	$(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(zfsinfo_mod_CFLAGS) -c -o $@ $<
++
++mod-zfsinfo.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
++	sh $(srcdir)/genmodsrc.sh 'zfsinfo' $< > $@ || (rm -f $@; exit 1)
++
++ifneq ($(TARGET_APPLE_CC),1)
++def-zfsinfo.lst: pre-zfsinfo.o
++	$(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 zfsinfo/' > $@
++else
++def-zfsinfo.lst: pre-zfsinfo.o
++	$(NM) -g -P -p $< | grep -E '^[a-zA-Z0-9_]* [TDS]'  | sed 's/^\([^ ]*\).*/\1 zfsinfo/' > $@
++endif
++
++und-zfsinfo.lst: pre-zfsinfo.o
++	echo 'zfsinfo' > $@
++	$(NM) -u -P -p $< | cut -f1 -d' ' >> $@
++
++zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.o: $(GRUB_CONTRIB)/zfs/zfsinfo.c $($(GRUB_CONTRIB)/zfs/zfsinfo.c_DEPENDENCIES)
++	$(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfsinfo_mod_CFLAGS) -MD -c -o $@ $<
++-include zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.d
++
++clean-module-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo-extra.1:
++	rm -f cmd-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst fs-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst partmap-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst handler-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst parttool-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst video-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst terminal-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst
++
++CLEAN_MODULE_TARGETS += clean-module-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo-extra.1
++
++COMMANDFILES += cmd-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst
++FSFILES += fs-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst
++PARTTOOLFILES += parttool-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst
++PARTMAPFILES += partmap-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst
++HANDLERFILES += handler-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst
++TERMINALFILES += terminal-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst
++VIDEOFILES += video-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst
++
++cmd-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst: $(GRUB_CONTRIB)/zfs/zfsinfo.c $($(GRUB_CONTRIB)/zfs/zfsinfo.c_DEPENDENCIES) gencmdlist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfsinfo_mod_CFLAGS) -E $< 	  | sh $(srcdir)/gencmdlist.sh zfsinfo > $@ || (rm -f $@; exit 1)
++
++fs-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst: $(GRUB_CONTRIB)/zfs/zfsinfo.c $($(GRUB_CONTRIB)/zfs/zfsinfo.c_DEPENDENCIES) genfslist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfsinfo_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genfslist.sh zfsinfo > $@ || (rm -f $@; exit 1)
++
++parttool-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst: $(GRUB_CONTRIB)/zfs/zfsinfo.c $($(GRUB_CONTRIB)/zfs/zfsinfo.c_DEPENDENCIES) genparttoollist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfsinfo_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genparttoollist.sh zfsinfo > $@ || (rm -f $@; exit 1)
++
++partmap-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst: $(GRUB_CONTRIB)/zfs/zfsinfo.c $($(GRUB_CONTRIB)/zfs/zfsinfo.c_DEPENDENCIES) genpartmaplist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfsinfo_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genpartmaplist.sh zfsinfo > $@ || (rm -f $@; exit 1)
++
++handler-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst: $(GRUB_CONTRIB)/zfs/zfsinfo.c $($(GRUB_CONTRIB)/zfs/zfsinfo.c_DEPENDENCIES) genhandlerlist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfsinfo_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genhandlerlist.sh zfsinfo > $@ || (rm -f $@; exit 1)
++
++terminal-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst: $(GRUB_CONTRIB)/zfs/zfsinfo.c $($(GRUB_CONTRIB)/zfs/zfsinfo.c_DEPENDENCIES) genterminallist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfsinfo_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genterminallist.sh zfsinfo > $@ || (rm -f $@; exit 1)
++
++video-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst: $(GRUB_CONTRIB)/zfs/zfsinfo.c $($(GRUB_CONTRIB)/zfs/zfsinfo.c_DEPENDENCIES) genvideolist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfsinfo_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genvideolist.sh zfsinfo > $@ || (rm -f $@; exit 1)
++
++zfsinfo_mod_CFLAGS = $(COMMON_CFLAGS) -Wno-error
++zfsinfo_mod_LDFLAGS = $(COMMON_LDFLAGS)
++# -*- makefile -*-
++
++COMMON_CFLAGS += -I$(GRUB_CONTRIB)/zfs/include
++
++pkglib_MODULES += zfs.mod
++zfs_mod_SOURCES = $(GRUB_CONTRIB)/zfs/zfs.c $(GRUB_CONTRIB)/zfs/zfs_lzjb.c $(GRUB_CONTRIB)/zfs/zfs_sha256.c $(GRUB_CONTRIB)/zfs/zfs_fletcher.c
++
++clean-module-zfs.mod.2:
++	rm -f zfs.mod mod-zfs.o mod-zfs.c pre-zfs.o zfs_mod-__GRUB_CONTRIB__zfs_zfs.o zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.o zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.o zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.o und-zfs.lst
++
++CLEAN_MODULE_TARGETS += clean-module-zfs.mod.2
++
++clean-module-zfs.mod-symbol.2:
++	rm -f def-zfs.lst
++
++CLEAN_MODULE_TARGETS += clean-module-zfs.mod-symbol.2
++DEFSYMFILES += def-zfs.lst
++mostlyclean-module-zfs.mod.2:
++	rm -f zfs_mod-__GRUB_CONTRIB__zfs_zfs.d zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.d zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.d zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.d
++
++MOSTLYCLEAN_MODULE_TARGETS += mostlyclean-module-zfs.mod.2
++UNDSYMFILES += und-zfs.lst
++
++ifneq ($(TARGET_APPLE_CC),1)
++zfs.mod: pre-zfs.o mod-zfs.o $(TARGET_OBJ2ELF)
++	-rm -f $@
++	$(TARGET_CC) $(zfs_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ pre-zfs.o mod-zfs.o
++	if test ! -z "$(TARGET_OBJ2ELF)"; then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
++	$(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
++else
++zfs.mod: pre-zfs.o mod-zfs.o $(TARGET_OBJ2ELF)
++	-rm -f $@
++	-rm -f $@.bin
++	$(TARGET_CC) $(zfs_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@.bin pre-zfs.o mod-zfs.o
++	$(OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -wd1106 -nu -nd $@.bin $@
++	-rm -f $@.bin
++endif
++
++pre-zfs.o: $(zfs_mod_DEPENDENCIES) zfs_mod-__GRUB_CONTRIB__zfs_zfs.o zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.o zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.o zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.o
++	-rm -f $@
++	$(TARGET_CC) $(zfs_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ zfs_mod-__GRUB_CONTRIB__zfs_zfs.o zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.o zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.o zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.o
++
++mod-zfs.o: mod-zfs.c
++	$(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -c -o $@ $<
++
++mod-zfs.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
++	sh $(srcdir)/genmodsrc.sh 'zfs' $< > $@ || (rm -f $@; exit 1)
++
++ifneq ($(TARGET_APPLE_CC),1)
++def-zfs.lst: pre-zfs.o
++	$(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 zfs/' > $@
++else
++def-zfs.lst: pre-zfs.o
++	$(NM) -g -P -p $< | grep -E '^[a-zA-Z0-9_]* [TDS]'  | sed 's/^\([^ ]*\).*/\1 zfs/' > $@
++endif
++
++und-zfs.lst: pre-zfs.o
++	echo 'zfs' > $@
++	$(NM) -u -P -p $< | cut -f1 -d' ' >> $@
++
++zfs_mod-__GRUB_CONTRIB__zfs_zfs.o: $(GRUB_CONTRIB)/zfs/zfs.c $($(GRUB_CONTRIB)/zfs/zfs.c_DEPENDENCIES)
++	$(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -MD -c -o $@ $<
++-include zfs_mod-__GRUB_CONTRIB__zfs_zfs.d
++
++clean-module-zfs_mod-__GRUB_CONTRIB__zfs_zfs-extra.2:
++	rm -f cmd-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst fs-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst partmap-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst handler-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst parttool-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst video-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst terminal-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst
++
++CLEAN_MODULE_TARGETS += clean-module-zfs_mod-__GRUB_CONTRIB__zfs_zfs-extra.2
++
++COMMANDFILES += cmd-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst
++FSFILES += fs-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst
++PARTTOOLFILES += parttool-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst
++PARTMAPFILES += partmap-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst
++HANDLERFILES += handler-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst
++TERMINALFILES += terminal-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst
++VIDEOFILES += video-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst
++
++cmd-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst: $(GRUB_CONTRIB)/zfs/zfs.c $($(GRUB_CONTRIB)/zfs/zfs.c_DEPENDENCIES) gencmdlist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/gencmdlist.sh zfs > $@ || (rm -f $@; exit 1)
++
++fs-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst: $(GRUB_CONTRIB)/zfs/zfs.c $($(GRUB_CONTRIB)/zfs/zfs.c_DEPENDENCIES) genfslist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genfslist.sh zfs > $@ || (rm -f $@; exit 1)
++
++parttool-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst: $(GRUB_CONTRIB)/zfs/zfs.c $($(GRUB_CONTRIB)/zfs/zfs.c_DEPENDENCIES) genparttoollist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genparttoollist.sh zfs > $@ || (rm -f $@; exit 1)
++
++partmap-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst: $(GRUB_CONTRIB)/zfs/zfs.c $($(GRUB_CONTRIB)/zfs/zfs.c_DEPENDENCIES) genpartmaplist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genpartmaplist.sh zfs > $@ || (rm -f $@; exit 1)
++
++handler-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst: $(GRUB_CONTRIB)/zfs/zfs.c $($(GRUB_CONTRIB)/zfs/zfs.c_DEPENDENCIES) genhandlerlist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genhandlerlist.sh zfs > $@ || (rm -f $@; exit 1)
++
++terminal-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst: $(GRUB_CONTRIB)/zfs/zfs.c $($(GRUB_CONTRIB)/zfs/zfs.c_DEPENDENCIES) genterminallist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genterminallist.sh zfs > $@ || (rm -f $@; exit 1)
++
++video-zfs_mod-__GRUB_CONTRIB__zfs_zfs.lst: $(GRUB_CONTRIB)/zfs/zfs.c $($(GRUB_CONTRIB)/zfs/zfs.c_DEPENDENCIES) genvideolist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genvideolist.sh zfs > $@ || (rm -f $@; exit 1)
++
++zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.o: $(GRUB_CONTRIB)/zfs/zfs_lzjb.c $($(GRUB_CONTRIB)/zfs/zfs_lzjb.c_DEPENDENCIES)
++	$(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -MD -c -o $@ $<
++-include zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.d
++
++clean-module-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb-extra.2:
++	rm -f cmd-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst fs-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst partmap-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst handler-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst parttool-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst video-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst terminal-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst
++
++CLEAN_MODULE_TARGETS += clean-module-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb-extra.2
++
++COMMANDFILES += cmd-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst
++FSFILES += fs-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst
++PARTTOOLFILES += parttool-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst
++PARTMAPFILES += partmap-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst
++HANDLERFILES += handler-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst
++TERMINALFILES += terminal-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst
++VIDEOFILES += video-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst
++
++cmd-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst: $(GRUB_CONTRIB)/zfs/zfs_lzjb.c $($(GRUB_CONTRIB)/zfs/zfs_lzjb.c_DEPENDENCIES) gencmdlist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/gencmdlist.sh zfs > $@ || (rm -f $@; exit 1)
++
++fs-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst: $(GRUB_CONTRIB)/zfs/zfs_lzjb.c $($(GRUB_CONTRIB)/zfs/zfs_lzjb.c_DEPENDENCIES) genfslist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genfslist.sh zfs > $@ || (rm -f $@; exit 1)
++
++parttool-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst: $(GRUB_CONTRIB)/zfs/zfs_lzjb.c $($(GRUB_CONTRIB)/zfs/zfs_lzjb.c_DEPENDENCIES) genparttoollist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genparttoollist.sh zfs > $@ || (rm -f $@; exit 1)
++
++partmap-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst: $(GRUB_CONTRIB)/zfs/zfs_lzjb.c $($(GRUB_CONTRIB)/zfs/zfs_lzjb.c_DEPENDENCIES) genpartmaplist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genpartmaplist.sh zfs > $@ || (rm -f $@; exit 1)
++
++handler-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst: $(GRUB_CONTRIB)/zfs/zfs_lzjb.c $($(GRUB_CONTRIB)/zfs/zfs_lzjb.c_DEPENDENCIES) genhandlerlist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genhandlerlist.sh zfs > $@ || (rm -f $@; exit 1)
++
++terminal-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst: $(GRUB_CONTRIB)/zfs/zfs_lzjb.c $($(GRUB_CONTRIB)/zfs/zfs_lzjb.c_DEPENDENCIES) genterminallist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genterminallist.sh zfs > $@ || (rm -f $@; exit 1)
++
++video-zfs_mod-__GRUB_CONTRIB__zfs_zfs_lzjb.lst: $(GRUB_CONTRIB)/zfs/zfs_lzjb.c $($(GRUB_CONTRIB)/zfs/zfs_lzjb.c_DEPENDENCIES) genvideolist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genvideolist.sh zfs > $@ || (rm -f $@; exit 1)
++
++zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.o: $(GRUB_CONTRIB)/zfs/zfs_sha256.c $($(GRUB_CONTRIB)/zfs/zfs_sha256.c_DEPENDENCIES)
++	$(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -MD -c -o $@ $<
++-include zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.d
++
++clean-module-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256-extra.2:
++	rm -f cmd-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst fs-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst partmap-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst handler-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst parttool-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst video-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst terminal-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst
++
++CLEAN_MODULE_TARGETS += clean-module-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256-extra.2
++
++COMMANDFILES += cmd-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst
++FSFILES += fs-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst
++PARTTOOLFILES += parttool-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst
++PARTMAPFILES += partmap-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst
++HANDLERFILES += handler-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst
++TERMINALFILES += terminal-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst
++VIDEOFILES += video-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst
++
++cmd-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst: $(GRUB_CONTRIB)/zfs/zfs_sha256.c $($(GRUB_CONTRIB)/zfs/zfs_sha256.c_DEPENDENCIES) gencmdlist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/gencmdlist.sh zfs > $@ || (rm -f $@; exit 1)
++
++fs-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst: $(GRUB_CONTRIB)/zfs/zfs_sha256.c $($(GRUB_CONTRIB)/zfs/zfs_sha256.c_DEPENDENCIES) genfslist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genfslist.sh zfs > $@ || (rm -f $@; exit 1)
++
++parttool-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst: $(GRUB_CONTRIB)/zfs/zfs_sha256.c $($(GRUB_CONTRIB)/zfs/zfs_sha256.c_DEPENDENCIES) genparttoollist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genparttoollist.sh zfs > $@ || (rm -f $@; exit 1)
++
++partmap-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst: $(GRUB_CONTRIB)/zfs/zfs_sha256.c $($(GRUB_CONTRIB)/zfs/zfs_sha256.c_DEPENDENCIES) genpartmaplist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genpartmaplist.sh zfs > $@ || (rm -f $@; exit 1)
++
++handler-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst: $(GRUB_CONTRIB)/zfs/zfs_sha256.c $($(GRUB_CONTRIB)/zfs/zfs_sha256.c_DEPENDENCIES) genhandlerlist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genhandlerlist.sh zfs > $@ || (rm -f $@; exit 1)
++
++terminal-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst: $(GRUB_CONTRIB)/zfs/zfs_sha256.c $($(GRUB_CONTRIB)/zfs/zfs_sha256.c_DEPENDENCIES) genterminallist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genterminallist.sh zfs > $@ || (rm -f $@; exit 1)
++
++video-zfs_mod-__GRUB_CONTRIB__zfs_zfs_sha256.lst: $(GRUB_CONTRIB)/zfs/zfs_sha256.c $($(GRUB_CONTRIB)/zfs/zfs_sha256.c_DEPENDENCIES) genvideolist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genvideolist.sh zfs > $@ || (rm -f $@; exit 1)
++
++zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.o: $(GRUB_CONTRIB)/zfs/zfs_fletcher.c $($(GRUB_CONTRIB)/zfs/zfs_fletcher.c_DEPENDENCIES)
++	$(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -MD -c -o $@ $<
++-include zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.d
++
++clean-module-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher-extra.2:
++	rm -f cmd-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst fs-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst partmap-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst handler-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst parttool-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst video-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst terminal-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst
++
++CLEAN_MODULE_TARGETS += clean-module-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher-extra.2
++
++COMMANDFILES += cmd-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst
++FSFILES += fs-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst
++PARTTOOLFILES += parttool-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst
++PARTMAPFILES += partmap-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst
++HANDLERFILES += handler-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst
++TERMINALFILES += terminal-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst
++VIDEOFILES += video-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst
++
++cmd-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst: $(GRUB_CONTRIB)/zfs/zfs_fletcher.c $($(GRUB_CONTRIB)/zfs/zfs_fletcher.c_DEPENDENCIES) gencmdlist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/gencmdlist.sh zfs > $@ || (rm -f $@; exit 1)
++
++fs-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst: $(GRUB_CONTRIB)/zfs/zfs_fletcher.c $($(GRUB_CONTRIB)/zfs/zfs_fletcher.c_DEPENDENCIES) genfslist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genfslist.sh zfs > $@ || (rm -f $@; exit 1)
++
++parttool-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst: $(GRUB_CONTRIB)/zfs/zfs_fletcher.c $($(GRUB_CONTRIB)/zfs/zfs_fletcher.c_DEPENDENCIES) genparttoollist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genparttoollist.sh zfs > $@ || (rm -f $@; exit 1)
++
++partmap-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst: $(GRUB_CONTRIB)/zfs/zfs_fletcher.c $($(GRUB_CONTRIB)/zfs/zfs_fletcher.c_DEPENDENCIES) genpartmaplist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genpartmaplist.sh zfs > $@ || (rm -f $@; exit 1)
++
++handler-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst: $(GRUB_CONTRIB)/zfs/zfs_fletcher.c $($(GRUB_CONTRIB)/zfs/zfs_fletcher.c_DEPENDENCIES) genhandlerlist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genhandlerlist.sh zfs > $@ || (rm -f $@; exit 1)
++
++terminal-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst: $(GRUB_CONTRIB)/zfs/zfs_fletcher.c $($(GRUB_CONTRIB)/zfs/zfs_fletcher.c_DEPENDENCIES) genterminallist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genterminallist.sh zfs > $@ || (rm -f $@; exit 1)
++
++video-zfs_mod-__GRUB_CONTRIB__zfs_zfs_fletcher.lst: $(GRUB_CONTRIB)/zfs/zfs_fletcher.c $($(GRUB_CONTRIB)/zfs/zfs_fletcher.c_DEPENDENCIES) genvideolist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfs_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genvideolist.sh zfs > $@ || (rm -f $@; exit 1)
++
++zfs_mod_CFLAGS = $(COMMON_CFLAGS) -Wno-error
++zfs_mod_LDFLAGS = $(COMMON_LDFLAGS)
++
++pkglib_MODULES += zfsinfo.mod
++zfsinfo_mod_SOURCES = $(GRUB_CONTRIB)/zfs/zfsinfo.c
++
++clean-module-zfsinfo.mod.2:
++	rm -f zfsinfo.mod mod-zfsinfo.o mod-zfsinfo.c pre-zfsinfo.o zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.o und-zfsinfo.lst
++
++CLEAN_MODULE_TARGETS += clean-module-zfsinfo.mod.2
++
++clean-module-zfsinfo.mod-symbol.2:
++	rm -f def-zfsinfo.lst
++
++CLEAN_MODULE_TARGETS += clean-module-zfsinfo.mod-symbol.2
++DEFSYMFILES += def-zfsinfo.lst
++mostlyclean-module-zfsinfo.mod.2:
++	rm -f zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.d
++
++MOSTLYCLEAN_MODULE_TARGETS += mostlyclean-module-zfsinfo.mod.2
++UNDSYMFILES += und-zfsinfo.lst
++
++ifneq ($(TARGET_APPLE_CC),1)
++zfsinfo.mod: pre-zfsinfo.o mod-zfsinfo.o $(TARGET_OBJ2ELF)
++	-rm -f $@
++	$(TARGET_CC) $(zfsinfo_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ pre-zfsinfo.o mod-zfsinfo.o
++	if test ! -z "$(TARGET_OBJ2ELF)"; then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
++	$(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
++else
++zfsinfo.mod: pre-zfsinfo.o mod-zfsinfo.o $(TARGET_OBJ2ELF)
++	-rm -f $@
++	-rm -f $@.bin
++	$(TARGET_CC) $(zfsinfo_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@.bin pre-zfsinfo.o mod-zfsinfo.o
++	$(OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -wd1106 -nu -nd $@.bin $@
++	-rm -f $@.bin
++endif
++
++pre-zfsinfo.o: $(zfsinfo_mod_DEPENDENCIES) zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.o
++	-rm -f $@
++	$(TARGET_CC) $(zfsinfo_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.o
++
++mod-zfsinfo.o: mod-zfsinfo.c
++	$(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(zfsinfo_mod_CFLAGS) -c -o $@ $<
++
++mod-zfsinfo.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
++	sh $(srcdir)/genmodsrc.sh 'zfsinfo' $< > $@ || (rm -f $@; exit 1)
++
++ifneq ($(TARGET_APPLE_CC),1)
++def-zfsinfo.lst: pre-zfsinfo.o
++	$(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 zfsinfo/' > $@
++else
++def-zfsinfo.lst: pre-zfsinfo.o
++	$(NM) -g -P -p $< | grep -E '^[a-zA-Z0-9_]* [TDS]'  | sed 's/^\([^ ]*\).*/\1 zfsinfo/' > $@
++endif
++
++und-zfsinfo.lst: pre-zfsinfo.o
++	echo 'zfsinfo' > $@
++	$(NM) -u -P -p $< | cut -f1 -d' ' >> $@
++
++zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.o: $(GRUB_CONTRIB)/zfs/zfsinfo.c $($(GRUB_CONTRIB)/zfs/zfsinfo.c_DEPENDENCIES)
++	$(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfsinfo_mod_CFLAGS) -MD -c -o $@ $<
++-include zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.d
++
++clean-module-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo-extra.2:
++	rm -f cmd-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst fs-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst partmap-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst handler-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst parttool-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst video-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst terminal-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst
++
++CLEAN_MODULE_TARGETS += clean-module-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo-extra.2
++
++COMMANDFILES += cmd-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst
++FSFILES += fs-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst
++PARTTOOLFILES += parttool-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst
++PARTMAPFILES += partmap-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst
++HANDLERFILES += handler-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst
++TERMINALFILES += terminal-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst
++VIDEOFILES += video-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst
++
++cmd-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst: $(GRUB_CONTRIB)/zfs/zfsinfo.c $($(GRUB_CONTRIB)/zfs/zfsinfo.c_DEPENDENCIES) gencmdlist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfsinfo_mod_CFLAGS) -E $< 	  | sh $(srcdir)/gencmdlist.sh zfsinfo > $@ || (rm -f $@; exit 1)
++
++fs-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst: $(GRUB_CONTRIB)/zfs/zfsinfo.c $($(GRUB_CONTRIB)/zfs/zfsinfo.c_DEPENDENCIES) genfslist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfsinfo_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genfslist.sh zfsinfo > $@ || (rm -f $@; exit 1)
++
++parttool-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst: $(GRUB_CONTRIB)/zfs/zfsinfo.c $($(GRUB_CONTRIB)/zfs/zfsinfo.c_DEPENDENCIES) genparttoollist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfsinfo_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genparttoollist.sh zfsinfo > $@ || (rm -f $@; exit 1)
++
++partmap-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst: $(GRUB_CONTRIB)/zfs/zfsinfo.c $($(GRUB_CONTRIB)/zfs/zfsinfo.c_DEPENDENCIES) genpartmaplist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfsinfo_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genpartmaplist.sh zfsinfo > $@ || (rm -f $@; exit 1)
++
++handler-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst: $(GRUB_CONTRIB)/zfs/zfsinfo.c $($(GRUB_CONTRIB)/zfs/zfsinfo.c_DEPENDENCIES) genhandlerlist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfsinfo_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genhandlerlist.sh zfsinfo > $@ || (rm -f $@; exit 1)
++
++terminal-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst: $(GRUB_CONTRIB)/zfs/zfsinfo.c $($(GRUB_CONTRIB)/zfs/zfsinfo.c_DEPENDENCIES) genterminallist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfsinfo_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genterminallist.sh zfsinfo > $@ || (rm -f $@; exit 1)
++
++video-zfsinfo_mod-__GRUB_CONTRIB__zfs_zfsinfo.lst: $(GRUB_CONTRIB)/zfs/zfsinfo.c $($(GRUB_CONTRIB)/zfs/zfsinfo.c_DEPENDENCIES) genvideolist.sh
++	set -e; 	  $(TARGET_CC) -I$(GRUB_CONTRIB)/zfs -I$(srcdir)/$(GRUB_CONTRIB)/zfs $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(zfsinfo_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genvideolist.sh zfsinfo > $@ || (rm -f $@; exit 1)
++
++zfsinfo_mod_CFLAGS = $(COMMON_CFLAGS) -Wno-error
++zfsinfo_mod_LDFLAGS = $(COMMON_LDFLAGS)
+--- grub-1.98.orig/grub-extras/zfs/conf/common.rmk	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/conf/common.rmk	2010-10-13 00:19:40.000000000 -0700
+@@ -0,0 +1,26 @@
++# -*- makefile -*-
++
++COMMON_CFLAGS += -I$(GRUB_CONTRIB)/zfs/include
++
++pkglib_MODULES += zfs.mod
++zfs_mod_SOURCES = $(GRUB_CONTRIB)/zfs/zfs.c $(GRUB_CONTRIB)/zfs/zfs_lzjb.c $(GRUB_CONTRIB)/zfs/zfs_sha256.c $(GRUB_CONTRIB)/zfs/zfs_fletcher.c
++zfs_mod_CFLAGS = $(COMMON_CFLAGS) -Wno-error
++zfs_mod_LDFLAGS = $(COMMON_LDFLAGS)
++
++pkglib_MODULES += zfsinfo.mod
++zfsinfo_mod_SOURCES = $(GRUB_CONTRIB)/zfs/zfsinfo.c
++zfsinfo_mod_CFLAGS = $(COMMON_CFLAGS) -Wno-error
++zfsinfo_mod_LDFLAGS = $(COMMON_LDFLAGS)
++# -*- makefile -*-
++
++COMMON_CFLAGS += -I$(GRUB_CONTRIB)/zfs/include
++
++pkglib_MODULES += zfs.mod
++zfs_mod_SOURCES = $(GRUB_CONTRIB)/zfs/zfs.c $(GRUB_CONTRIB)/zfs/zfs_lzjb.c $(GRUB_CONTRIB)/zfs/zfs_sha256.c $(GRUB_CONTRIB)/zfs/zfs_fletcher.c
++zfs_mod_CFLAGS = $(COMMON_CFLAGS) -Wno-error
++zfs_mod_LDFLAGS = $(COMMON_LDFLAGS)
++
++pkglib_MODULES += zfsinfo.mod
++zfsinfo_mod_SOURCES = $(GRUB_CONTRIB)/zfs/zfsinfo.c
++zfsinfo_mod_CFLAGS = $(COMMON_CFLAGS) -Wno-error
++zfsinfo_mod_LDFLAGS = $(COMMON_LDFLAGS)
+--- grub-1.98.orig/grub-extras/zfs/include/grub/zfs/dmu.h	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/include/grub/zfs/dmu.h	2010-10-13 00:16:54.874814000 -0700
+@@ -0,0 +1,120 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++/*
++ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
++ * Use is subject to license terms.
++ */
++
++#ifndef	_SYS_DMU_H
++#define	_SYS_DMU_H
++
++/*
++ * This file describes the interface that the DMU provides for its
++ * consumers.
++ *
++ * The DMU also interacts with the SPA.  That interface is described in
++ * dmu_spa.h.
++ */
++typedef enum dmu_object_type {
++	DMU_OT_NONE,
++	/* general: */
++	DMU_OT_OBJECT_DIRECTORY,	/* ZAP */
++	DMU_OT_OBJECT_ARRAY,		/* UINT64 */
++	DMU_OT_PACKED_NVLIST,		/* UINT8 (XDR by nvlist_pack/unpack) */
++	DMU_OT_PACKED_NVLIST_SIZE,	/* UINT64 */
++	DMU_OT_BPLIST,			/* UINT64 */
++	DMU_OT_BPLIST_HDR,		/* UINT64 */
++	/* spa: */
++	DMU_OT_SPACE_MAP_HEADER,	/* UINT64 */
++	DMU_OT_SPACE_MAP,		/* UINT64 */
++	/* zil: */
++	DMU_OT_INTENT_LOG,		/* UINT64 */
++	/* dmu: */
++	DMU_OT_DNODE,			/* DNODE */
++	DMU_OT_OBJSET,			/* OBJSET */
++	/* dsl: */
++	DMU_OT_DSL_DIR,			/* UINT64 */
++	DMU_OT_DSL_DIR_CHILD_MAP,	/* ZAP */
++	DMU_OT_DSL_DS_SNAP_MAP,		/* ZAP */
++	DMU_OT_DSL_PROPS,		/* ZAP */
++	DMU_OT_DSL_DATASET,		/* UINT64 */
++	/* zpl: */
++	DMU_OT_ZNODE,			/* ZNODE */
++	DMU_OT_OLDACL,			/* OLD ACL */
++	DMU_OT_PLAIN_FILE_CONTENTS,	/* UINT8 */
++	DMU_OT_DIRECTORY_CONTENTS,	/* ZAP */
++	DMU_OT_MASTER_NODE,		/* ZAP */
++	DMU_OT_UNLINKED_SET,		/* ZAP */
++	/* zvol: */
++	DMU_OT_ZVOL,			/* UINT8 */
++	DMU_OT_ZVOL_PROP,		/* ZAP */
++	/* other; for testing only! */
++	DMU_OT_PLAIN_OTHER,		/* UINT8 */
++	DMU_OT_UINT64_OTHER,		/* UINT64 */
++	DMU_OT_ZAP_OTHER,		/* ZAP */
++	/* new object types: */
++	DMU_OT_ERROR_LOG,		/* ZAP */
++	DMU_OT_SPA_HISTORY,		/* UINT8 */
++	DMU_OT_SPA_HISTORY_OFFSETS,	/* spa_his_phys_t */
++	DMU_OT_POOL_PROPS,		/* ZAP */
++	DMU_OT_DSL_PERMS,		/* ZAP */
++	DMU_OT_ACL,			/* ACL */
++	DMU_OT_SYSACL,			/* SYSACL */
++	DMU_OT_FUID,			/* FUID table (Packed NVLIST UINT8) */
++	DMU_OT_FUID_SIZE,		/* FUID table size UINT64 */
++	DMU_OT_NEXT_CLONES,		/* ZAP */
++	DMU_OT_SCRUB_QUEUE,		/* ZAP */
++	DMU_OT_USERGROUP_USED,		/* ZAP */
++	DMU_OT_USERGROUP_QUOTA,		/* ZAP */
++	DMU_OT_USERREFS,		/* ZAP */
++	DMU_OT_DDT_ZAP,			/* ZAP */
++	DMU_OT_DDT_STATS,		/* ZAP */
++	DMU_OT_SA,			/* System attr */
++	DMU_OT_SA_MASTER_NODE,		/* ZAP */
++	DMU_OT_SA_ATTR_REGISTRATION,	/* ZAP */
++	DMU_OT_SA_ATTR_LAYOUTS,		/* ZAP */
++	DMU_OT_NUMTYPES
++} dmu_object_type_t;
++
++typedef enum dmu_objset_type {
++	DMU_OST_NONE,
++	DMU_OST_META,
++	DMU_OST_ZFS,
++	DMU_OST_ZVOL,
++	DMU_OST_OTHER,			/* For testing only! */
++	DMU_OST_ANY,			/* Be careful! */
++	DMU_OST_NUMTYPES
++} dmu_objset_type_t;
++
++/*
++ * The names of zap entries in the DIRECTORY_OBJECT of the MOS.
++ */
++#define	DMU_POOL_DIRECTORY_OBJECT	1
++#define	DMU_POOL_CONFIG			"config"
++#define	DMU_POOL_ROOT_DATASET		"root_dataset"
++#define	DMU_POOL_SYNC_BPLIST		"sync_bplist"
++#define	DMU_POOL_ERRLOG_SCRUB		"errlog_scrub"
++#define	DMU_POOL_ERRLOG_LAST		"errlog_last"
++#define	DMU_POOL_SPARES			"spares"
++#define	DMU_POOL_DEFLATE		"deflate"
++#define	DMU_POOL_HISTORY		"history"
++#define	DMU_POOL_PROPS			"pool_props"
++#define	DMU_POOL_L2CACHE		"l2cache"
++
++#endif	/* _SYS_DMU_H */
+--- grub-1.98.orig/grub-extras/zfs/include/grub/zfs/dmu_objset.h	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/include/grub/zfs/dmu_objset.h	2010-10-13 00:16:54.874814000 -0700
+@@ -0,0 +1,44 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
++ *  Copyright (C) 2010  Robert Millan <rmh@gnu.org>
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++/*
++ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
++ * Use is subject to license terms.
++ */
++
++#ifndef	_SYS_DMU_OBJSET_H
++#define	_SYS_DMU_OBJSET_H
++
++#include <grub/zfs/zil.h>
++
++#define OBJSET_PHYS_SIZE	2048
++#define OBJSET_PHYS_SIZE_V14	1024
++
++typedef struct objset_phys {
++	dnode_phys_t os_meta_dnode;
++	zil_header_t os_zil_header;
++	grub_uint64_t os_type;
++	grub_uint64_t os_flags;
++	char os_pad[OBJSET_PHYS_SIZE - sizeof (dnode_phys_t)*3 -
++	    sizeof (zil_header_t) - sizeof (grub_uint64_t)*2];
++	dnode_phys_t os_userused_dnode;
++	dnode_phys_t os_groupused_dnode;
++} objset_phys_t;
++
++#endif /* _SYS_DMU_OBJSET_H */
+--- grub-1.98.orig/grub-extras/zfs/include/grub/zfs/dnode.h	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/include/grub/zfs/dnode.h	2010-10-13 00:16:54.874814000 -0700
+@@ -0,0 +1,81 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++/*
++ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
++ * Use is subject to license terms.
++ */
++
++#ifndef	_SYS_DNODE_H
++#define	_SYS_DNODE_H
++
++#include <grub/zfs/spa.h>
++
++/*
++ * Fixed constants.
++ */
++#define	DNODE_SHIFT		9	/* 512 bytes */
++#define	DN_MIN_INDBLKSHIFT	10	/* 1k */
++#define	DN_MAX_INDBLKSHIFT	14	/* 16k */
++#define	DNODE_BLOCK_SHIFT	14	/* 16k */
++#define	DNODE_CORE_SIZE		64	/* 64 bytes for dnode sans blkptrs */
++#define	DN_MAX_OBJECT_SHIFT	48	/* 256 trillion (zfs_fid_t limit) */
++#define	DN_MAX_OFFSET_SHIFT	64	/* 2^64 bytes in a dnode */
++
++/*
++ * Derived constants.
++ */
++#define	DNODE_SIZE	(1 << DNODE_SHIFT)
++#define	DN_MAX_NBLKPTR	((DNODE_SIZE - DNODE_CORE_SIZE) >> SPA_BLKPTRSHIFT)
++#define	DN_MAX_BONUSLEN	(DNODE_SIZE - DNODE_CORE_SIZE - (1 << SPA_BLKPTRSHIFT))
++#define	DN_MAX_OBJECT	(1ULL << DN_MAX_OBJECT_SHIFT)
++
++#define	DNODES_PER_BLOCK_SHIFT	(DNODE_BLOCK_SHIFT - DNODE_SHIFT)
++#define	DNODES_PER_BLOCK	(1ULL << DNODES_PER_BLOCK_SHIFT)
++#define	DNODES_PER_LEVEL_SHIFT	(DN_MAX_INDBLKSHIFT - SPA_BLKPTRSHIFT)
++
++#define	DNODE_FLAG_SPILL_BLKPTR (1<<2)
++
++#define	DN_BONUS(dnp)	((void*)((dnp)->dn_bonus + \
++	(((dnp)->dn_nblkptr - 1) * sizeof (blkptr_t))))
++
++typedef struct dnode_phys {
++	grub_uint8_t dn_type;		/* dmu_object_type_t */
++	grub_uint8_t dn_indblkshift;		/* ln2(indirect block size) */
++	grub_uint8_t dn_nlevels;		/* 1=dn_blkptr->data blocks */
++	grub_uint8_t dn_nblkptr;		/* length of dn_blkptr */
++	grub_uint8_t dn_bonustype;		/* type of data in bonus buffer */
++	grub_uint8_t	dn_checksum;		/* ZIO_CHECKSUM type */
++	grub_uint8_t	dn_compress;		/* ZIO_COMPRESS type */
++	grub_uint8_t dn_flags;		/* DNODE_FLAG_* */
++	grub_uint16_t dn_datablkszsec;	/* data block size in 512b sectors */
++	grub_uint16_t dn_bonuslen;		/* length of dn_bonus */
++	grub_uint8_t dn_pad2[4];
++
++	/* accounting is protected by dn_dirty_mtx */
++	grub_uint64_t dn_maxblkid;		/* largest allocated block ID */
++	grub_uint64_t dn_used;		/* bytes (or sectors) of disk space */
++
++	grub_uint64_t dn_pad3[4];
++
++	blkptr_t dn_blkptr[1];
++	grub_uint8_t dn_bonus[DN_MAX_BONUSLEN - sizeof (blkptr_t)];
++	blkptr_t dn_spill;
++} dnode_phys_t;
++
++#endif	/* _SYS_DNODE_H */
+--- grub-1.98.orig/grub-extras/zfs/include/grub/zfs/dsl_dataset.h	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/include/grub/zfs/dsl_dataset.h	2010-10-13 00:16:54.874814000 -0700
+@@ -0,0 +1,53 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++/*
++ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
++ * Use is subject to license terms.
++ */
++
++#ifndef	_SYS_DSL_DATASET_H
++#define	_SYS_DSL_DATASET_H
++
++typedef struct dsl_dataset_phys {
++	grub_uint64_t ds_dir_obj;
++	grub_uint64_t ds_prev_snap_obj;
++	grub_uint64_t ds_prev_snap_txg;
++	grub_uint64_t ds_next_snap_obj;
++	grub_uint64_t ds_snapnames_zapobj;	/* zap obj of snaps; ==0 for snaps */
++	grub_uint64_t ds_num_children;	/* clone/snap children; ==0 for head */
++	grub_uint64_t ds_creation_time;	/* seconds since 1970 */
++	grub_uint64_t ds_creation_txg;
++	grub_uint64_t ds_deadlist_obj;
++	grub_uint64_t ds_used_bytes;
++	grub_uint64_t ds_compressed_bytes;
++	grub_uint64_t ds_uncompressed_bytes;
++	grub_uint64_t ds_unique_bytes;	/* only relevant to snapshots */
++	/*
++	 * The ds_fsid_guid is a 56-bit ID that can change to avoid
++	 * collisions.  The ds_guid is a 64-bit ID that will never
++	 * change, so there is a small probability that it will collide.
++	 */
++	grub_uint64_t ds_fsid_guid;
++	grub_uint64_t ds_guid;
++	grub_uint64_t ds_flags;
++	blkptr_t ds_bp;
++	grub_uint64_t ds_pad[8]; /* pad out to 320 bytes for good measure */
++} dsl_dataset_phys_t;
++
++#endif /* _SYS_DSL_DATASET_H */
+--- grub-1.98.orig/grub-extras/zfs/include/grub/zfs/dsl_dir.h	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/include/grub/zfs/dsl_dir.h	2010-10-13 00:16:54.874814000 -0700
+@@ -0,0 +1,49 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++/*
++ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
++ * Use is subject to license terms.
++ */
++
++#ifndef	_SYS_DSL_DIR_H
++#define	_SYS_DSL_DIR_H
++
++typedef struct dsl_dir_phys {
++	grub_uint64_t dd_creation_time; /* not actually used */
++	grub_uint64_t dd_head_dataset_obj;
++	grub_uint64_t dd_parent_obj;
++	grub_uint64_t dd_clone_parent_obj;
++	grub_uint64_t dd_child_dir_zapobj;
++	/*
++	 * how much space our children are accounting for; for leaf
++	 * datasets, == physical space used by fs + snaps
++	 */
++	grub_uint64_t dd_used_bytes;
++	grub_uint64_t dd_compressed_bytes;
++	grub_uint64_t dd_uncompressed_bytes;
++	/* Administrative quota setting */
++	grub_uint64_t dd_quota;
++	/* Administrative reservation setting */
++	grub_uint64_t dd_reserved;
++	grub_uint64_t dd_props_zapobj;
++	grub_uint64_t dd_deleg_zapobj;	/* dataset permissions */
++	grub_uint64_t dd_pad[20]; /* pad out to 256 bytes for good measure */
++} dsl_dir_phys_t;
++
++#endif /* _SYS_DSL_DIR_H */
+--- grub-1.98.orig/grub-extras/zfs/include/grub/zfs/sa_impl.h	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/include/grub/zfs/sa_impl.h	2010-10-13 00:16:54.874814000 -0700
+@@ -0,0 +1,35 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++/*
++ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
++ * Use is subject to license terms.
++ */
++#ifndef	_SYS_SA_IMPL_H
++#define	_SYS_SA_IMPL_H
++
++typedef struct sa_hdr_phys {
++	grub_uint32_t sa_magic;
++	grub_uint16_t sa_layout_info;
++	grub_uint16_t sa_lengths[1];
++} sa_hdr_phys_t;
++
++#define	SA_HDR_SIZE(hdr)	BF32_GET_SB(hdr->sa_layout_info, 10, 16, 3, 0)
++#define	SA_SIZE_OFFSET	0x8
++
++#endif	/* _SYS_SA_IMPL_H */
+--- grub-1.98.orig/grub-extras/zfs/include/grub/zfs/spa.h	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/include/grub/zfs/spa.h	2010-10-13 00:16:54.874814000 -0700
+@@ -0,0 +1,312 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
++ *  Copyright 2010 Sun Microsystems, Inc.
++ *  Copyright (C) 2009  Vladimir Serbinenko <phcoder@gmail.com>
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 3 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef GRUB_ZFS_SPA_HEADER
++#define	GRUB_ZFS_SPA_HEADER 1
++
++typedef enum grub_zfs_endian
++  {
++    UNKNOWN_ENDIAN = -2,
++    LITTLE_ENDIAN = -1,
++    BIG_ENDIAN = 0
++  } grub_zfs_endian_t;
++
++#define grub_zfs_to_cpu16(x,a) (((a) == BIG_ENDIAN) ? grub_be_to_cpu16(x) \
++				: grub_le_to_cpu16(x))
++#define grub_cpu_to_zfs16(x,a) (((a) == BIG_ENDIAN) ? grub_cpu_to_be16(x) \
++				: grub_cpu_to_le16(x))
++
++#define grub_zfs_to_cpu32(x,a) (((a) == BIG_ENDIAN) ? grub_be_to_cpu32(x) \
++				: grub_le_to_cpu32(x))
++#define grub_cpu_to_zfs32(x,a) (((a) == BIG_ENDIAN) ? grub_cpu_to_be32(x) \
++				: grub_cpu_to_le32(x))
++
++#define grub_zfs_to_cpu64(x,a) (((a) == BIG_ENDIAN) ? grub_be_to_cpu64(x) \
++				: grub_le_to_cpu64(x))
++#define grub_cpu_to_zfs64(x,a) (((a) == BIG_ENDIAN) ? grub_cpu_to_be64(x) \
++				: grub_cpu_to_le64(x))
++
++/*
++ * General-purpose 32-bit and 64-bit bitfield encodings.
++ */
++#define	BF32_DECODE(x, low, len)	P2PHASE((x) >> (low), 1U << (len))
++#define	BF64_DECODE(x, low, len)	P2PHASE((x) >> (low), 1ULL << (len))
++#define	BF32_ENCODE(x, low, len)	(P2PHASE((x), 1U << (len)) << (low))
++#define	BF64_ENCODE(x, low, len)	(P2PHASE((x), 1ULL << (len)) << (low))
++
++#define	BF32_GET(x, low, len)		BF32_DECODE(x, low, len)
++#define	BF64_GET(x, low, len)		BF64_DECODE(x, low, len)
++
++#define	BF32_SET(x, low, len, val)	\
++	((x) ^= BF32_ENCODE((x >> low) ^ (val), low, len))
++#define	BF64_SET(x, low, len, val)	\
++	((x) ^= BF64_ENCODE((x >> low) ^ (val), low, len))
++
++#define	BF32_GET_SB(x, low, len, shift, bias)	\
++	((BF32_GET(x, low, len) + (bias)) << (shift))
++#define	BF64_GET_SB(x, low, len, shift, bias)	\
++	((BF64_GET(x, low, len) + (bias)) << (shift))
++
++#define	BF32_SET_SB(x, low, len, shift, bias, val)	\
++	BF32_SET(x, low, len, ((val) >> (shift)) - (bias))
++#define	BF64_SET_SB(x, low, len, shift, bias, val)	\
++	BF64_SET(x, low, len, ((val) >> (shift)) - (bias))
++
++/*
++ * We currently support nine block sizes, from 512 bytes to 128K.
++ * We could go higher, but the benefits are near-zero and the cost
++ * of COWing a giant block to modify one byte would become excessive.
++ */
++#define	SPA_MINBLOCKSHIFT	9
++#define	SPA_MAXBLOCKSHIFT	17
++#define	SPA_MINBLOCKSIZE	(1ULL << SPA_MINBLOCKSHIFT)
++#define	SPA_MAXBLOCKSIZE	(1ULL << SPA_MAXBLOCKSHIFT)
++
++#define	SPA_BLOCKSIZES		(SPA_MAXBLOCKSHIFT - SPA_MINBLOCKSHIFT + 1)
++
++/*
++ * Size of block to hold the configuration data (a packed nvlist)
++ */
++#define	SPA_CONFIG_BLOCKSIZE	(1 << 14)
++
++/*
++ * The DVA size encodings for LSIZE and PSIZE support blocks up to 32MB.
++ * The ASIZE encoding should be at least 64 times larger (6 more bits)
++ * to support up to 4-way RAID-Z mirror mode with worst-case gang block
++ * overhead, three DVAs per bp, plus one more bit in case we do anything
++ * else that expands the ASIZE.
++ */
++#define	SPA_LSIZEBITS		16	/* LSIZE up to 32M (2^16 * 512)	*/
++#define	SPA_PSIZEBITS		16	/* PSIZE up to 32M (2^16 * 512)	*/
++#define	SPA_ASIZEBITS		24	/* ASIZE up to 64 times larger	*/
++
++/*
++ * All SPA data is represented by 128-bit data virtual addresses (DVAs).
++ * The members of the dva_t should be considered opaque outside the SPA.
++ */
++typedef struct dva {
++	grub_uint64_t	dva_word[2];
++} dva_t;
++
++/*
++ * Each block has a 256-bit checksum -- strong enough for cryptographic hashes.
++ */
++typedef struct zio_cksum {
++	grub_uint64_t	zc_word[4];
++} zio_cksum_t;
++
++/*
++ * Each block is described by its DVAs, time of birth, checksum, etc.
++ * The word-by-word, bit-by-bit layout of the blkptr is as follows:
++ *
++ *	64	56	48	40	32	24	16	8	0
++ *	+-------+-------+-------+-------+-------+-------+-------+-------+
++ * 0	|		vdev1		| GRID  |	  ASIZE		|
++ *	+-------+-------+-------+-------+-------+-------+-------+-------+
++ * 1	|G|			 offset1				|
++ *	+-------+-------+-------+-------+-------+-------+-------+-------+
++ * 2	|		vdev2		| GRID  |	  ASIZE		|
++ *	+-------+-------+-------+-------+-------+-------+-------+-------+
++ * 3	|G|			 offset2				|
++ *	+-------+-------+-------+-------+-------+-------+-------+-------+
++ * 4	|		vdev3		| GRID  |	  ASIZE		|
++ *	+-------+-------+-------+-------+-------+-------+-------+-------+
++ * 5	|G|			 offset3				|
++ *	+-------+-------+-------+-------+-------+-------+-------+-------+
++ * 6	|BDX|lvl| type	| cksum | comp	|     PSIZE	|     LSIZE	|
++ *	+-------+-------+-------+-------+-------+-------+-------+-------+
++ * 7	|			padding					|
++ *	+-------+-------+-------+-------+-------+-------+-------+-------+
++ * 8	|			padding					|
++ *	+-------+-------+-------+-------+-------+-------+-------+-------+
++ * 9	|			physical birth txg			|
++ *	+-------+-------+-------+-------+-------+-------+-------+-------+
++ * a	|			logical birth txg			|
++ *	+-------+-------+-------+-------+-------+-------+-------+-------+
++ * b	|			fill count				|
++ *	+-------+-------+-------+-------+-------+-------+-------+-------+
++ * c	|			checksum[0]				|
++ *	+-------+-------+-------+-------+-------+-------+-------+-------+
++ * d	|			checksum[1]				|
++ *	+-------+-------+-------+-------+-------+-------+-------+-------+
++ * e	|			checksum[2]				|
++ *	+-------+-------+-------+-------+-------+-------+-------+-------+
++ * f	|			checksum[3]				|
++ *	+-------+-------+-------+-------+-------+-------+-------+-------+
++ *
++ * Legend:
++ *
++ * vdev		virtual device ID
++ * offset	offset into virtual device
++ * LSIZE	logical size
++ * PSIZE	physical size (after compression)
++ * ASIZE	allocated size (including RAID-Z parity and gang block headers)
++ * GRID		RAID-Z layout information (reserved for future use)
++ * cksum	checksum function
++ * comp		compression function
++ * G		gang block indicator
++ * B		byteorder (endianness)
++ * D		dedup
++ * X		unused
++ * lvl		level of indirection
++ * type		DMU object type
++ * phys birth	txg of block allocation; zero if same as logical birth txg
++ * log. birth	transaction group in which the block was logically born
++ * fill count	number of non-zero blocks under this bp
++ * checksum[4]	256-bit checksum of the data this bp describes
++ */
++#define	SPA_BLKPTRSHIFT	7		/* blkptr_t is 128 bytes	*/
++#define	SPA_DVAS_PER_BP	3		/* Number of DVAs in a bp	*/
++
++typedef struct blkptr {
++	dva_t		blk_dva[SPA_DVAS_PER_BP]; /* Data Virtual Addresses */
++	grub_uint64_t	blk_prop;	/* size, compression, type, etc	    */
++	grub_uint64_t	blk_pad[2];	/* Extra space for the future	    */
++	grub_uint64_t	blk_phys_birth;	/* txg when block was allocated	    */
++	grub_uint64_t	blk_birth;	/* transaction group at birth	    */
++	grub_uint64_t	blk_fill;	/* fill count			    */
++	zio_cksum_t	blk_cksum;	/* 256-bit checksum		    */
++} blkptr_t;
++
++/*
++ * Macros to get and set fields in a bp or DVA.
++ */
++#define	DVA_GET_ASIZE(dva)	\
++	BF64_GET_SB((dva)->dva_word[0], 0, 24, SPA_MINBLOCKSHIFT, 0)
++#define	DVA_SET_ASIZE(dva, x)	\
++	BF64_SET_SB((dva)->dva_word[0], 0, 24, SPA_MINBLOCKSHIFT, 0, x)
++
++#define	DVA_GET_GRID(dva)	BF64_GET((dva)->dva_word[0], 24, 8)
++#define	DVA_SET_GRID(dva, x)	BF64_SET((dva)->dva_word[0], 24, 8, x)
++
++#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_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_LSIZE(bp)	\
++	BF64_GET_SB((bp)->blk_prop, 0, 16, SPA_MINBLOCKSHIFT, 1)
++#define	BP_SET_LSIZE(bp, x)	\
++	BF64_SET_SB((bp)->blk_prop, 0, 16, SPA_MINBLOCKSHIFT, 1, x)
++
++#define	BP_GET_COMPRESS(bp)		BF64_GET((bp)->blk_prop, 32, 8)
++#define	BP_SET_COMPRESS(bp, x)		BF64_SET((bp)->blk_prop, 32, 8, x)
++
++#define	BP_GET_CHECKSUM(bp)		BF64_GET((bp)->blk_prop, 40, 8)
++#define	BP_SET_CHECKSUM(bp, x)		BF64_SET((bp)->blk_prop, 40, 8, x)
++
++#define	BP_GET_TYPE(bp)			BF64_GET((bp)->blk_prop, 48, 8)
++#define	BP_SET_TYPE(bp, x)		BF64_SET((bp)->blk_prop, 48, 8, x)
++
++#define	BP_GET_LEVEL(bp)		BF64_GET((bp)->blk_prop, 56, 5)
++#define	BP_SET_LEVEL(bp, x)		BF64_SET((bp)->blk_prop, 56, 5, x)
++
++#define	BP_GET_PROP_BIT_61(bp)		BF64_GET((bp)->blk_prop, 61, 1)
++#define	BP_SET_PROP_BIT_61(bp, x)	BF64_SET((bp)->blk_prop, 61, 1, x)
++
++#define	BP_GET_DEDUP(bp)		BF64_GET((bp)->blk_prop, 62, 1)
++#define	BP_SET_DEDUP(bp, x)		BF64_SET((bp)->blk_prop, 62, 1, x)
++
++#define	BP_GET_BYTEORDER(bp)		(0 - BF64_GET((bp)->blk_prop, 63, 1))
++#define	BP_SET_BYTEORDER(bp, x)		BF64_SET((bp)->blk_prop, 63, 1, x)
++
++#define	BP_PHYSICAL_BIRTH(bp)		\
++	((bp)->blk_phys_birth ? (bp)->blk_phys_birth : (bp)->blk_birth)
++
++#define	BP_SET_BIRTH(bp, logical, physical)	\
++{						\
++	(bp)->blk_birth = (logical);		\
++	(bp)->blk_phys_birth = ((logical) == (physical) ? 0 : (physical)); \
++}
++
++#define	BP_GET_ASIZE(bp)	\
++	(DVA_GET_ASIZE(&(bp)->blk_dva[0]) + DVA_GET_ASIZE(&(bp)->blk_dva[1]) + \
++		DVA_GET_ASIZE(&(bp)->blk_dva[2]))
++
++#define	BP_GET_UCSIZE(bp) \
++	((BP_GET_LEVEL(bp) > 0 || dmu_ot[BP_GET_TYPE(bp)].ot_metadata) ? \
++	BP_GET_PSIZE(bp) : BP_GET_LSIZE(bp));
++
++#define	BP_GET_NDVAS(bp)	\
++	(!!DVA_GET_ASIZE(&(bp)->blk_dva[0]) + \
++	!!DVA_GET_ASIZE(&(bp)->blk_dva[1]) + \
++	!!DVA_GET_ASIZE(&(bp)->blk_dva[2]))
++
++#define	BP_COUNT_GANG(bp)	\
++	(DVA_GET_GANG(&(bp)->blk_dva[0]) + \
++	DVA_GET_GANG(&(bp)->blk_dva[1]) + \
++	DVA_GET_GANG(&(bp)->blk_dva[2]))
++
++#define	DVA_EQUAL(dva1, dva2)	\
++	((dva1)->dva_word[1] == (dva2)->dva_word[1] && \
++	(dva1)->dva_word[0] == (dva2)->dva_word[0])
++
++#define	BP_EQUAL(bp1, bp2)	\
++	(BP_PHYSICAL_BIRTH(bp1) == BP_PHYSICAL_BIRTH(bp2) &&	\
++	DVA_EQUAL(&(bp1)->blk_dva[0], &(bp2)->blk_dva[0]) &&	\
++	DVA_EQUAL(&(bp1)->blk_dva[1], &(bp2)->blk_dva[1]) &&	\
++	DVA_EQUAL(&(bp1)->blk_dva[2], &(bp2)->blk_dva[2]))
++
++#define	ZIO_CHECKSUM_EQUAL(zc1, zc2) \
++	(0 == (((zc1).zc_word[0] - (zc2).zc_word[0]) | \
++	((zc1).zc_word[1] - (zc2).zc_word[1]) | \
++	((zc1).zc_word[2] - (zc2).zc_word[2]) | \
++	((zc1).zc_word[3] - (zc2).zc_word[3])))
++
++#define	DVA_IS_VALID(dva)	(DVA_GET_ASIZE(dva) != 0)
++
++#define	ZIO_SET_CHECKSUM(zcp, w0, w1, w2, w3)	\
++{						\
++	(zcp)->zc_word[0] = w0;			\
++	(zcp)->zc_word[1] = w1;			\
++	(zcp)->zc_word[2] = w2;			\
++	(zcp)->zc_word[3] = w3;			\
++}
++
++#define	BP_IDENTITY(bp)		(&(bp)->blk_dva[0])
++#define	BP_IS_GANG(bp)		DVA_GET_GANG(BP_IDENTITY(bp))
++#define	BP_IS_HOLE(bp)		((bp)->blk_birth == 0)
++
++/* BP_IS_RAIDZ(bp) assumes no block compression */
++#define	BP_IS_RAIDZ(bp)		(DVA_GET_ASIZE(&(bp)->blk_dva[0]) > \
++				BP_GET_PSIZE(bp))
++
++#define	BP_ZERO(bp)				\
++{						\
++	(bp)->blk_dva[0].dva_word[0] = 0;	\
++	(bp)->blk_dva[0].dva_word[1] = 0;	\
++	(bp)->blk_dva[1].dva_word[0] = 0;	\
++	(bp)->blk_dva[1].dva_word[1] = 0;	\
++	(bp)->blk_dva[2].dva_word[0] = 0;	\
++	(bp)->blk_dva[2].dva_word[1] = 0;	\
++	(bp)->blk_prop = 0;			\
++	(bp)->blk_pad[0] = 0;			\
++	(bp)->blk_pad[1] = 0;			\
++	(bp)->blk_phys_birth = 0;		\
++	(bp)->blk_birth = 0;			\
++	(bp)->blk_fill = 0;			\
++	ZIO_SET_CHECKSUM(&(bp)->blk_cksum, 0, 0, 0, 0);	\
++}
++
++#define	BP_SPRINTF_LEN	320
++
++#endif	/* ! GRUB_ZFS_SPA_HEADER */
+--- grub-1.98.orig/grub-extras/zfs/include/grub/zfs/uberblock_impl.h	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/include/grub/zfs/uberblock_impl.h	2010-10-13 00:16:54.874814000 -0700
+@@ -0,0 +1,61 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++/*
++ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
++ * Use is subject to license terms.
++ */
++
++#ifndef _SYS_UBERBLOCK_IMPL_H
++#define	_SYS_UBERBLOCK_IMPL_H
++
++/*
++ * The uberblock version is incremented whenever an incompatible on-disk
++ * format change is made to the SPA, DMU, or ZAP.
++ *
++ * Note: the first two fields should never be moved.  When a storage pool
++ * is opened, the uberblock must be read off the disk before the version
++ * can be checked.  If the ub_version field is moved, we may not detect
++ * version mismatch.  If the ub_magic field is moved, applications that
++ * expect the magic number in the first word won't work.
++ */
++#define	UBERBLOCK_MAGIC		0x00bab10c		/* oo-ba-bloc!	*/
++#define	UBERBLOCK_SHIFT		10			/* up to 1K	*/
++
++typedef struct uberblock {
++	grub_uint64_t	ub_magic;	/* UBERBLOCK_MAGIC		*/
++	grub_uint64_t	ub_version;	/* ZFS_VERSION			*/
++	grub_uint64_t	ub_txg;		/* txg of last sync		*/
++	grub_uint64_t	ub_guid_sum;	/* sum of all vdev guids	*/
++	grub_uint64_t	ub_timestamp;	/* UTC time of last sync	*/
++	blkptr_t	ub_rootbp;	/* MOS objset_phys_t		*/
++} uberblock_t;
++
++#define	UBERBLOCK_SIZE		(1ULL << UBERBLOCK_SHIFT)
++#define	VDEV_UBERBLOCK_SHIFT	UBERBLOCK_SHIFT
++
++/* XXX Uberblock_phys_t is no longer in the kernel zfs */
++typedef struct uberblock_phys {
++	uberblock_t	ubp_uberblock;
++	char		ubp_pad[UBERBLOCK_SIZE - sizeof (uberblock_t) -
++				sizeof (zio_eck_t)];
++	zio_eck_t	ubp_zec;
++} uberblock_phys_t;
++
++
++#endif	/* _SYS_UBERBLOCK_IMPL_H */
+--- grub-1.98.orig/grub-extras/zfs/include/grub/zfs/vdev_impl.h	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/include/grub/zfs/vdev_impl.h	2010-10-13 00:16:54.874814000 -0700
+@@ -0,0 +1,70 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++/*
++ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
++ * Use is subject to license terms.
++ */
++
++#ifndef _SYS_VDEV_IMPL_H
++#define	_SYS_VDEV_IMPL_H
++
++#define	VDEV_SKIP_SIZE		(8 << 10)
++#define	VDEV_BOOT_HEADER_SIZE	(8 << 10)
++#define	VDEV_PHYS_SIZE		(112 << 10)
++#define	VDEV_UBERBLOCK_RING	(128 << 10)
++
++/* ZFS boot block */
++#define	VDEV_BOOT_MAGIC		0x2f5b007b10cULL
++#define	VDEV_BOOT_VERSION	1		/* version number	*/
++
++typedef struct vdev_boot_header {
++	grub_uint64_t	vb_magic;		/* VDEV_BOOT_MAGIC	*/
++	grub_uint64_t	vb_version;		/* VDEV_BOOT_VERSION	*/
++	grub_uint64_t	vb_offset;		/* start offset	(bytes) */
++	grub_uint64_t	vb_size;		/* size (bytes)		*/
++	char		vb_pad[VDEV_BOOT_HEADER_SIZE - 4 * sizeof (grub_uint64_t)];
++} vdev_boot_header_t;
++
++typedef struct vdev_phys {
++	char		vp_nvlist[VDEV_PHYS_SIZE - sizeof (zio_eck_t)];
++	zio_eck_t	vp_zbt;
++} vdev_phys_t;
++
++typedef struct vdev_label {
++	char		vl_pad[VDEV_SKIP_SIZE];			/*   8K	*/
++	vdev_boot_header_t vl_boot_header;			/*   8K	*/
++	vdev_phys_t	vl_vdev_phys;				/* 112K	*/
++	char		vl_uberblock[VDEV_UBERBLOCK_RING];	/* 128K	*/
++} vdev_label_t;							/* 256K total */
++
++/*
++ * Size and offset of embedded boot loader region on each label.
++ * The total size of the first two labels plus the boot area is 4MB.
++ */
++#define	VDEV_BOOT_OFFSET	(2 * sizeof (vdev_label_t))
++#define	VDEV_BOOT_SIZE		(7ULL << 19)			/* 3.5M	*/
++
++/*
++ * Size of label regions at the start and end of each leaf device.
++ */
++#define	VDEV_LABEL_START_SIZE	(2 * sizeof (vdev_label_t) + VDEV_BOOT_SIZE)
++#define	VDEV_LABEL_END_SIZE	(2 * sizeof (vdev_label_t))
++#define	VDEV_LABELS		4
++
++#endif	/* _SYS_VDEV_IMPL_H */
+--- grub-1.98.orig/grub-extras/zfs/include/grub/zfs/zap_impl.h	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/include/grub/zfs/zap_impl.h	2010-10-13 00:16:54.874814000 -0700
+@@ -0,0 +1,112 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++/*
++ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
++ * Use is subject to license terms.
++ */
++
++#ifndef	_SYS_ZAP_IMPL_H
++#define	_SYS_ZAP_IMPL_H
++
++#define	ZAP_MAGIC 0x2F52AB2ABULL
++
++#define	ZAP_HASHBITS		28
++#define	MZAP_ENT_LEN		64
++#define	MZAP_NAME_LEN		(MZAP_ENT_LEN - 8 - 4 - 2)
++#define	MZAP_MAX_BLKSHIFT	SPA_MAXBLOCKSHIFT
++#define	MZAP_MAX_BLKSZ		(1 << MZAP_MAX_BLKSHIFT)
++
++typedef struct mzap_ent_phys {
++	grub_uint64_t mze_value;
++	grub_uint32_t mze_cd;
++	grub_uint16_t mze_pad;	/* in case we want to chain them someday */
++	char mze_name[MZAP_NAME_LEN];
++} mzap_ent_phys_t;
++
++typedef struct mzap_phys {
++	grub_uint64_t mz_block_type;	/* ZBT_MICRO */
++	grub_uint64_t mz_salt;
++	grub_uint64_t mz_pad[6];
++	mzap_ent_phys_t mz_chunk[1];
++	/* actually variable size depending on block size */
++} mzap_phys_t;
++
++/*
++ * The (fat) zap is stored in one object. It is an array of
++ * 1<<FZAP_BLOCK_SHIFT byte blocks. The layout looks like one of:
++ *
++ * ptrtbl fits in first block:
++ * 	[zap_phys_t zap_ptrtbl_shift < 6] [zap_leaf_t] ...
++ *
++ * ptrtbl too big for first block:
++ * 	[zap_phys_t zap_ptrtbl_shift >= 6] [zap_leaf_t] [ptrtbl] ...
++ *
++ */
++
++#define	ZBT_LEAF		((1ULL << 63) + 0)
++#define	ZBT_HEADER		((1ULL << 63) + 1)
++#define	ZBT_MICRO		((1ULL << 63) + 3)
++/* any other values are ptrtbl blocks */
++
++/*
++ * the embedded pointer table takes up half a block:
++ * block size / entry size (2^3) / 2
++ */
++#define	ZAP_EMBEDDED_PTRTBL_SHIFT(zap) (FZAP_BLOCK_SHIFT(zap) - 3 - 1)
++
++/*
++ * The embedded pointer table starts half-way through the block.  Since
++ * the pointer table itself is half the block, it starts at (64-bit)
++ * word number (1<<ZAP_EMBEDDED_PTRTBL_SHIFT(zap)).
++ */
++#define	ZAP_EMBEDDED_PTRTBL_ENT(zap, idx) \
++	((grub_uint64_t *)(zap)->zap_f.zap_phys) \
++	[(idx) + (1<<ZAP_EMBEDDED_PTRTBL_SHIFT(zap))]
++
++/*
++ * TAKE NOTE:
++ * If zap_phys_t is modified, zap_byteswap() must be modified.
++ */
++typedef struct zap_phys {
++	grub_uint64_t zap_block_type;	/* ZBT_HEADER */
++	grub_uint64_t zap_magic;		/* ZAP_MAGIC */
++
++	struct zap_table_phys {
++		grub_uint64_t zt_blk;	/* starting block number */
++		grub_uint64_t zt_numblks;	/* number of blocks */
++		grub_uint64_t zt_shift;	/* bits to index it */
++		grub_uint64_t zt_nextblk;	/* next (larger) copy start block */
++		grub_uint64_t zt_blks_copied; /* number source blocks copied */
++	} zap_ptrtbl;
++
++	grub_uint64_t zap_freeblk;		/* the next free block */
++	grub_uint64_t zap_num_leafs;		/* number of leafs */
++	grub_uint64_t zap_num_entries;	/* number of entries */
++	grub_uint64_t zap_salt;		/* salt to stir into hash function */
++	grub_uint64_t zap_normflags;		/* flags for u8_textprep_str() */
++	grub_uint64_t zap_flags;		/* zap_flag_t */
++	/*
++	 * This structure is followed by padding, and then the embedded
++	 * pointer table.  The embedded pointer table takes up second
++	 * half of the block.  It is accessed using the
++	 * ZAP_EMBEDDED_PTRTBL_ENT() macro.
++	 */
++} zap_phys_t;
++
++#endif /* _SYS_ZAP_IMPL_H */
+--- grub-1.98.orig/grub-extras/zfs/include/grub/zfs/zap_leaf.h	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/include/grub/zfs/zap_leaf.h	2010-10-13 00:16:54.874814000 -0700
+@@ -0,0 +1,104 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++/*
++ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
++ * Use is subject to license terms.
++ */
++
++#ifndef	_SYS_ZAP_LEAF_H
++#define	_SYS_ZAP_LEAF_H
++
++#define	ZAP_LEAF_MAGIC 0x2AB1EAF
++
++/* chunk size = 24 bytes */
++#define	ZAP_LEAF_CHUNKSIZE 24
++
++/*
++ * The amount of space within the chunk available for the array is:
++ * chunk size - space for type (1) - space for next pointer (2)
++ */
++#define	ZAP_LEAF_ARRAY_BYTES (ZAP_LEAF_CHUNKSIZE - 3)
++
++typedef enum zap_chunk_type {
++	ZAP_CHUNK_FREE = 253,
++	ZAP_CHUNK_ENTRY = 252,
++	ZAP_CHUNK_ARRAY = 251,
++	ZAP_CHUNK_TYPE_MAX = 250
++} zap_chunk_type_t;
++
++/*
++ * TAKE NOTE:
++ * If zap_leaf_phys_t is modified, zap_leaf_byteswap() must be modified.
++ */
++typedef struct zap_leaf_phys {
++	struct zap_leaf_header {
++		grub_uint64_t lh_block_type;		/* ZBT_LEAF */
++		grub_uint64_t lh_pad1;
++		grub_uint64_t lh_prefix;		/* hash prefix of this leaf */
++		grub_uint32_t lh_magic;		/* ZAP_LEAF_MAGIC */
++		grub_uint16_t lh_nfree;		/* number free chunks */
++		grub_uint16_t lh_nentries;		/* number of entries */
++		grub_uint16_t lh_prefix_len;		/* num bits used to id this */
++
++/* above is accessable to zap, below is zap_leaf private */
++
++		grub_uint16_t lh_freelist;		/* chunk head of free list */
++		grub_uint8_t lh_pad2[12];
++	} l_hdr; /* 2 24-byte chunks */
++
++	/*
++	 * The header is followed by a hash table with
++	 * ZAP_LEAF_HASH_NUMENTRIES(zap) entries.  The hash table is
++	 * followed by an array of ZAP_LEAF_NUMCHUNKS(zap)
++	 * zap_leaf_chunk structures.  These structures are accessed
++	 * with the ZAP_LEAF_CHUNK() macro.
++	 */
++
++	grub_uint16_t l_hash[1];
++} zap_leaf_phys_t;
++
++typedef union zap_leaf_chunk {
++	struct zap_leaf_entry {
++		grub_uint8_t le_type; 		/* always ZAP_CHUNK_ENTRY */
++		grub_uint8_t le_int_size;		/* size of ints */
++		grub_uint16_t le_next;		/* next entry in hash chain */
++		grub_uint16_t le_name_chunk;		/* first chunk of the name */
++		grub_uint16_t le_name_length;	/* bytes in name, incl null */
++		grub_uint16_t le_value_chunk;	/* first chunk of the value */
++		grub_uint16_t le_value_length;	/* value length in ints */
++		grub_uint32_t le_cd;		/* collision differentiator */
++		grub_uint64_t le_hash;		/* hash value of the name */
++	} l_entry;
++	struct zap_leaf_array {
++		grub_uint8_t la_type;		/* always ZAP_CHUNK_ARRAY */
++		union
++		{
++			grub_uint8_t la_array[ZAP_LEAF_ARRAY_BYTES];
++			grub_uint64_t la_array64;
++		};
++		grub_uint16_t la_next;		/* next blk or CHAIN_END */
++	} l_array;
++	struct zap_leaf_free {
++		grub_uint8_t lf_type;		/* always ZAP_CHUNK_FREE */
++		grub_uint8_t lf_pad[ZAP_LEAF_ARRAY_BYTES];
++		grub_uint16_t lf_next;	/* next in free list, or CHAIN_END */
++	} l_free;
++} zap_leaf_chunk_t;
++
++#endif /* _SYS_ZAP_LEAF_H */
+--- grub-1.98.orig/grub-extras/zfs/include/grub/zfs/zfs.h	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/include/grub/zfs/zfs.h	2010-10-13 00:16:54.874814000 -0700
+@@ -0,0 +1,125 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
++ *  Copyright (C) 2009  Vladimir Serbinenko <phcoder@gmail.com>
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 3 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++ /*
++  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
++  */
++
++#ifndef	GRUB_ZFS_HEADER
++#define	GRUB_ZFS_HEADER 1
++
++#include <grub/err.h>
++#include <grub/disk.h>
++
++/*
++ * On-disk version number.
++ */
++#define	SPA_VERSION			28ULL
++
++/*
++ * The following are configuration names used in the nvlist describing a pool's
++ * configuration.
++ */
++#define	ZPOOL_CONFIG_VERSION		"version"
++#define	ZPOOL_CONFIG_POOL_NAME		"name"
++#define	ZPOOL_CONFIG_POOL_STATE		"state"
++#define	ZPOOL_CONFIG_POOL_TXG		"txg"
++#define	ZPOOL_CONFIG_POOL_GUID		"pool_guid"
++#define	ZPOOL_CONFIG_CREATE_TXG		"create_txg"
++#define	ZPOOL_CONFIG_TOP_GUID		"top_guid"
++#define	ZPOOL_CONFIG_VDEV_TREE		"vdev_tree"
++#define	ZPOOL_CONFIG_TYPE		"type"
++#define	ZPOOL_CONFIG_CHILDREN		"children"
++#define	ZPOOL_CONFIG_ID			"id"
++#define	ZPOOL_CONFIG_GUID		"guid"
++#define	ZPOOL_CONFIG_PATH		"path"
++#define	ZPOOL_CONFIG_DEVID		"devid"
++#define	ZPOOL_CONFIG_METASLAB_ARRAY	"metaslab_array"
++#define	ZPOOL_CONFIG_METASLAB_SHIFT	"metaslab_shift"
++#define	ZPOOL_CONFIG_ASHIFT		"ashift"
++#define	ZPOOL_CONFIG_ASIZE		"asize"
++#define	ZPOOL_CONFIG_DTL		"DTL"
++#define	ZPOOL_CONFIG_STATS		"stats"
++#define	ZPOOL_CONFIG_WHOLE_DISK		"whole_disk"
++#define	ZPOOL_CONFIG_ERRCOUNT		"error_count"
++#define	ZPOOL_CONFIG_NOT_PRESENT	"not_present"
++#define	ZPOOL_CONFIG_SPARES		"spares"
++#define	ZPOOL_CONFIG_IS_SPARE		"is_spare"
++#define	ZPOOL_CONFIG_NPARITY		"nparity"
++#define	ZPOOL_CONFIG_PHYS_PATH		"phys_path"
++#define	ZPOOL_CONFIG_L2CACHE		"l2cache"
++#define	ZPOOL_CONFIG_HOLE_ARRAY		"hole_array"
++#define	ZPOOL_CONFIG_VDEV_CHILDREN	"vdev_children"
++#define	ZPOOL_CONFIG_IS_HOLE		"is_hole"
++#define	ZPOOL_CONFIG_DDT_HISTOGRAM	"ddt_histogram"
++#define	ZPOOL_CONFIG_DDT_OBJ_STATS	"ddt_object_stats"
++#define	ZPOOL_CONFIG_DDT_STATS		"ddt_stats"
++/*
++ * The persistent vdev state is stored as separate values rather than a single
++ * 'vdev_state' entry.  This is because a device can be in multiple states, such
++ * as offline and degraded.
++ */
++#define	ZPOOL_CONFIG_OFFLINE		"offline"
++#define	ZPOOL_CONFIG_FAULTED		"faulted"
++#define	ZPOOL_CONFIG_DEGRADED		"degraded"
++#define	ZPOOL_CONFIG_REMOVED		"removed"
++
++#define	VDEV_TYPE_ROOT			"root"
++#define	VDEV_TYPE_MIRROR		"mirror"
++#define	VDEV_TYPE_REPLACING		"replacing"
++#define	VDEV_TYPE_RAIDZ			"raidz"
++#define	VDEV_TYPE_DISK			"disk"
++#define	VDEV_TYPE_FILE			"file"
++#define	VDEV_TYPE_MISSING		"missing"
++#define	VDEV_TYPE_HOLE			"hole"
++#define	VDEV_TYPE_SPARE			"spare"
++#define	VDEV_TYPE_L2CACHE		"l2cache"
++
++/*
++ * pool state.  The following states are written to disk as part of the normal
++ * SPA lifecycle: ACTIVE, EXPORTED, DESTROYED, SPARE, L2CACHE.  The remaining
++ * states are software abstractions used at various levels to communicate pool
++ * state.
++ */
++typedef enum pool_state {
++	POOL_STATE_ACTIVE = 0,		/* In active use		*/
++	POOL_STATE_EXPORTED,		/* Explicitly exported		*/
++	POOL_STATE_DESTROYED,		/* Explicitly destroyed		*/
++	POOL_STATE_SPARE,		/* Reserved for hot spare use	*/
++	POOL_STATE_L2CACHE,		/* Level 2 ARC device		*/
++	POOL_STATE_UNINITIALIZED,	/* Internal spa_t state		*/
++	POOL_STATE_UNAVAIL,		/* Internal libzfs state	*/
++	POOL_STATE_POTENTIALLY_ACTIVE	/* Internal libzfs state	*/
++} pool_state_t;
++
++struct grub_zfs_data;
++
++grub_err_t grub_zfs_fetch_nvlist (grub_device_t dev, char **nvlist);
++grub_err_t grub_zfs_getmdnobj (grub_device_t dev, const char *fsfilename,
++			       grub_uint64_t *mdnobj);
++
++char *grub_zfs_nvlist_lookup_string (char *nvlist, char *name);
++char *grub_zfs_nvlist_lookup_nvlist (char *nvlist, char *name);
++int grub_zfs_nvlist_lookup_uint64 (char *nvlist, char *name,
++				   grub_uint64_t *out);
++char *grub_zfs_nvlist_lookup_nvlist_array (char *nvlist, char *name,
++					   grub_size_t index);
++int grub_zfs_nvlist_lookup_nvlist_array_get_nelm (char *nvlist, char *name);
++
++#endif	/* ! GRUB_ZFS_HEADER */
+--- grub-1.98.orig/grub-extras/zfs/include/grub/zfs/zfs_acl.h	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/include/grub/zfs/zfs_acl.h	2010-10-13 00:16:54.874814000 -0700
+@@ -0,0 +1,60 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++/*
++ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
++ * Use is subject to license terms.
++ */
++
++#ifndef	_SYS_FS_ZFS_ACL_H
++#define	_SYS_FS_ZFS_ACL_H
++
++#ifndef _UID_T
++#define	_UID_T
++typedef	unsigned int uid_t;			/* UID type */
++#endif /* _UID_T */
++
++typedef struct zfs_oldace {
++	grub_uint32_t	z_fuid;		/* "who" */
++	grub_uint32_t	z_access_mask;  /* access mask */
++	grub_uint16_t	z_flags;	/* flags, i.e inheritance */
++	grub_uint16_t	z_type;		/* type of entry allow/deny */
++} zfs_oldace_t;
++
++#define	ACE_SLOT_CNT	6
++
++typedef struct zfs_znode_acl_v0 {
++	grub_uint64_t	z_acl_extern_obj;	  /* ext acl pieces */
++	grub_uint32_t	z_acl_count;		  /* Number of ACEs */
++	grub_uint16_t	z_acl_version;		  /* acl version */
++	grub_uint16_t	z_acl_pad;		  /* pad */
++	zfs_oldace_t	z_ace_data[ACE_SLOT_CNT]; /* 6 standard ACEs */
++} zfs_znode_acl_v0_t;
++
++#define	ZFS_ACE_SPACE	(sizeof (zfs_oldace_t) * ACE_SLOT_CNT)
++
++typedef struct zfs_znode_acl {
++	grub_uint64_t	z_acl_extern_obj;	  /* ext acl pieces */
++	grub_uint32_t	z_acl_size;		  /* Number of bytes in ACL */
++	grub_uint16_t	z_acl_version;		  /* acl version */
++	grub_uint16_t	z_acl_count;		  /* ace count */
++	grub_uint8_t	z_ace_data[ZFS_ACE_SPACE]; /* space for embedded ACEs */
++} zfs_znode_acl_t;
++
++
++#endif	/* _SYS_FS_ZFS_ACL_H */
+--- grub-1.98.orig/grub-extras/zfs/include/grub/zfs/zfs_znode.h	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/include/grub/zfs/zfs_znode.h	2010-10-13 00:16:54.874814000 -0700
+@@ -0,0 +1,71 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++/*
++ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
++ * Use is subject to license terms.
++ */
++
++#ifndef	_SYS_FS_ZFS_ZNODE_H
++#define	_SYS_FS_ZFS_ZNODE_H
++
++#include <grub/zfs/zfs_acl.h>
++
++#define	MASTER_NODE_OBJ	1
++#define	ZFS_ROOT_OBJ		"ROOT"
++#define	ZPL_VERSION_STR		"VERSION"
++#define	ZFS_SA_ATTRS		"SA_ATTRS"
++
++#define	ZPL_VERSION		5ULL
++
++#define	ZFS_DIRENT_OBJ(de) BF64_GET(de, 0, 48)
++
++/*
++ * This is the persistent portion of the znode.  It is stored
++ * in the "bonus buffer" of the file.  Short symbolic links
++ * are also stored in the bonus buffer.
++ */
++typedef struct znode_phys {
++	grub_uint64_t zp_atime[2];      /*  0 - last file access time */
++	grub_uint64_t zp_mtime[2];	/* 16 - last file modification time */
++	grub_uint64_t zp_ctime[2];	/* 32 - last file change time */
++	grub_uint64_t zp_crtime[2];	/* 48 - creation time */
++	grub_uint64_t zp_gen;		/* 64 - generation (txg of creation) */
++	grub_uint64_t zp_mode;		/* 72 - file mode bits */
++	grub_uint64_t zp_size;		/* 80 - size of file */
++	grub_uint64_t zp_parent;	/* 88 - directory parent (`..') */
++	grub_uint64_t zp_links;		/* 96 - number of links to file */
++	grub_uint64_t zp_xattr;		/* 104 - DMU object for xattrs */
++	grub_uint64_t zp_rdev;		/* 112 - dev_t for VBLK & VCHR files */
++	grub_uint64_t zp_flags;		/* 120 - persistent flags */
++	grub_uint64_t zp_uid;		/* 128 - file owner */
++	grub_uint64_t zp_gid;		/* 136 - owning group */
++	grub_uint64_t zp_pad[4];	/* 144 - future */
++	zfs_znode_acl_t zp_acl;		/* 176 - 263 ACL */
++	/*
++	 * Data may pad out any remaining bytes in the znode buffer, eg:
++	 *
++	 * |<---------------------- dnode_phys (512) ------------------------>|
++	 * |<-- dnode (192) --->|<----------- "bonus" buffer (320) ---------->|
++	 *			|<---- znode (264) ---->|<---- data (56) ---->|
++	 *
++	 * At present, we only use this space to store symbolic links.
++	 */
++} znode_phys_t;
++
++#endif	/* _SYS_FS_ZFS_ZNODE_H */
+--- grub-1.98.orig/grub-extras/zfs/include/grub/zfs/zil.h	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/include/grub/zfs/zil.h	2010-10-13 00:16:54.874814000 -0700
+@@ -0,0 +1,57 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++/*
++ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
++ * Use is subject to license terms.
++ */
++
++#ifndef	_SYS_ZIL_H
++#define	_SYS_ZIL_H
++
++/*
++ * Intent log format:
++ *
++ * Each objset has its own intent log.  The log header (zil_header_t)
++ * for objset N's intent log is kept in the Nth object of the SPA's
++ * intent_log objset.  The log header points to a chain of log blocks,
++ * each of which contains log records (i.e., transactions) followed by
++ * a log block trailer (zil_trailer_t).  The format of a log record
++ * depends on the record (or transaction) type, but all records begin
++ * with a common structure that defines the type, length, and txg.
++ */
++
++/*
++ * Intent log header - this on disk structure holds fields to manage
++ * the log.  All fields are 64 bit to easily handle cross architectures.
++ */
++typedef struct zil_header {
++	grub_uint64_t zh_claim_txg;   /* txg in which log blocks were claimed */
++	grub_uint64_t zh_replay_seq;  /* highest replayed sequence number */
++	blkptr_t zh_log;	/* log chain */
++	grub_uint64_t zh_claim_seq;	/* highest claimed sequence number */
++	grub_uint64_t zh_flags;	/* header flags */
++	grub_uint64_t zh_pad[4];
++} zil_header_t;
++
++/*
++ * zh_flags bit settings
++ */
++#define	ZIL_REPLAY_NEEDED 0x1	/* replay needed - internal only */
++
++#endif	/* _SYS_ZIL_H */
+--- grub-1.98.orig/grub-extras/zfs/include/grub/zfs/zio.h	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/include/grub/zfs/zio.h	2010-10-13 00:16:54.874814000 -0700
+@@ -0,0 +1,85 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++/*
++ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
++ * Use is subject to license terms.
++ */
++
++#ifndef _ZIO_H
++#define	_ZIO_H
++
++#include <grub/zfs/spa.h>
++
++#define	ZEC_MAGIC	0x210da7ab10c7a11ULL	/* zio data bloc tail */
++
++typedef struct zio_eck {
++	grub_uint64_t	zec_magic;	/* for validation, endianness	*/
++	zio_cksum_t	zec_cksum;	/* 256-bit checksum		*/
++} zio_eck_t;
++
++/*
++ * Gang block headers are self-checksumming and contain an array
++ * of block pointers.
++ */
++#define	SPA_GANGBLOCKSIZE	SPA_MINBLOCKSIZE
++#define	SPA_GBH_NBLKPTRS	((SPA_GANGBLOCKSIZE - \
++	sizeof (zio_eck_t)) / sizeof (blkptr_t))
++#define	SPA_GBH_FILLER		((SPA_GANGBLOCKSIZE - \
++	sizeof (zio_eck_t) - \
++	(SPA_GBH_NBLKPTRS * sizeof (blkptr_t))) /\
++	sizeof (grub_uint64_t))
++
++#define	ZIO_GET_IOSIZE(zio)	\
++	(BP_IS_GANG((zio)->io_bp) ? \
++	SPA_GANGBLOCKSIZE : BP_GET_PSIZE((zio)->io_bp))
++
++typedef struct zio_gbh {
++	blkptr_t		zg_blkptr[SPA_GBH_NBLKPTRS];
++	grub_uint64_t		zg_filler[SPA_GBH_FILLER];
++	zio_eck_t		zg_tail;
++} zio_gbh_phys_t;
++
++enum zio_checksum {
++	ZIO_CHECKSUM_INHERIT = 0,
++	ZIO_CHECKSUM_ON,
++	ZIO_CHECKSUM_OFF,
++	ZIO_CHECKSUM_LABEL,
++	ZIO_CHECKSUM_GANG_HEADER,
++	ZIO_CHECKSUM_ZILOG,
++	ZIO_CHECKSUM_FLETCHER_2,
++	ZIO_CHECKSUM_FLETCHER_4,
++	ZIO_CHECKSUM_SHA256,
++	ZIO_CHECKSUM_ZILOG2,
++	ZIO_CHECKSUM_FUNCTIONS
++};
++
++#define	ZIO_CHECKSUM_ON_VALUE	ZIO_CHECKSUM_FLETCHER_2
++#define	ZIO_CHECKSUM_DEFAULT	ZIO_CHECKSUM_ON
++
++enum zio_compress {
++	ZIO_COMPRESS_INHERIT = 0,
++	ZIO_COMPRESS_ON,
++	ZIO_COMPRESS_OFF,
++	ZIO_COMPRESS_LZJB,
++	ZIO_COMPRESS_EMPTY,
++	ZIO_COMPRESS_GZIP,
++	ZIO_COMPRESS_FUNCTIONS
++};
++
++#endif	/* _ZIO_H */
+--- grub-1.98.orig/grub-extras/zfs/include/grub/zfs/zio_checksum.h	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/include/grub/zfs/zio_checksum.h	2010-10-13 00:16:54.874814000 -0700
+@@ -0,0 +1,50 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++/*
++ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
++ * Use is subject to license terms.
++ */
++
++#ifndef _SYS_ZIO_CHECKSUM_H
++#define	_SYS_ZIO_CHECKSUM_H
++
++/*
++ * Signature for checksum functions.
++ */
++typedef void zio_checksum_t(const void *data, grub_uint64_t size, 
++			    grub_zfs_endian_t endian, zio_cksum_t *zcp);
++
++/*
++ * Information about each checksum function.
++ */
++typedef struct zio_checksum_info {
++	zio_checksum_t	*ci_func; /* checksum function for each byteorder */
++	int		ci_correctable;	/* number of correctable bits	*/
++	int		ci_eck;		/* uses zio embedded checksum? */
++	char		*ci_name;	/* descriptive name */
++} zio_checksum_info_t;
++
++extern void zio_checksum_SHA256 (const void *, grub_uint64_t,
++				 grub_zfs_endian_t endian, zio_cksum_t *);
++extern void fletcher_2 (const void *, grub_uint64_t, grub_zfs_endian_t endian,
++			zio_cksum_t *);
++extern void fletcher_4 (const void *, grub_uint64_t, grub_zfs_endian_t endian,
++			zio_cksum_t *);
++
++#endif	/* _SYS_ZIO_CHECKSUM_H */
+--- grub-1.98.orig/grub-extras/zfs/zfs.c	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/zfs.c	2010-10-13 00:16:54.874814000 -0700
+@@ -0,0 +1,2536 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
++ *  Copyright 2010  Sun Microsystems, Inc.
++ *  Copyright (C) 2009  Vladimir Serbinenko <phcoder@gmail.com>
++ *  Copyright (C) 2010  Robert Millan <rmh@gnu.org>
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 3 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++/*
++ * The zfs plug-in routines for GRUB are:
++ *
++ * zfs_mount() - locates a valid uberblock of the root pool and reads
++ *		in its MOS at the memory address MOS.
++ *
++ * zfs_open() - locates a plain file object by following the MOS
++ *		and places its dnode at the memory address DNODE.
++ *
++ * zfs_read() - read in the data blocks pointed by the DNODE.
++ *
++ */
++
++#include <grub/err.h>
++#include <grub/file.h>
++#include <grub/mm.h>
++#include <grub/misc.h>
++#include <grub/disk.h>
++#include <grub/partition.h>
++#include <grub/dl.h>
++#include <grub/types.h>
++#include <grub/zfs/zfs.h>
++#include <grub/zfs/zio.h>
++#include <grub/zfs/dnode.h>
++#include <grub/zfs/uberblock_impl.h>
++#include <grub/zfs/vdev_impl.h>
++#include <grub/zfs/zio_checksum.h>
++#include <grub/zfs/zap_impl.h>
++#include <grub/zfs/zap_leaf.h>
++#include <grub/zfs/zfs_znode.h>
++#include <grub/zfs/dmu.h>
++#include <grub/zfs/dmu_objset.h>
++#include <grub/zfs/sa_impl.h>
++#include <grub/zfs/dsl_dir.h>
++#include <grub/zfs/dsl_dataset.h>
++
++#define	ZPOOL_PROP_BOOTFS		"bootfs"
++
++#define MIN(a,b) (((a) < (b)) ? (a) : (b))
++
++/*
++ * For nvlist manipulation. (from nvpair.h)
++ */
++#define	NV_ENCODE_NATIVE	0
++#define	NV_ENCODE_XDR		1
++#define	NV_BIG_ENDIAN	        0
++#define	NV_LITTLE_ENDIAN	1
++#define	DATA_TYPE_UINT64	8
++#define	DATA_TYPE_STRING	9
++#define	DATA_TYPE_NVLIST	19
++#define	DATA_TYPE_NVLIST_ARRAY	20
++
++#ifndef GRUB_UTIL
++static grub_dl_t my_mod;
++#endif
++
++#define	P2PHASE(x, align)		((x) & ((align) - 1))
++#define	DVA_OFFSET_TO_PHYS_SECTOR(offset) \
++	((offset + VDEV_LABEL_START_SIZE) >> SPA_MINBLOCKSHIFT)
++
++/*
++ * FAT ZAP data structures
++ */
++#define	ZFS_CRC64_POLY 0xC96C5795D7870F42ULL	/* ECMA-182, reflected form */
++#define	ZAP_HASH_IDX(hash, n)	(((n) == 0) ? 0 : ((hash) >> (64 - (n))))
++#define	CHAIN_END	0xffff	/* end of the chunk chain */
++
++/*
++ * The amount of space within the chunk available for the array is:
++ * chunk size - space for type (1) - space for next pointer (2)
++ */
++#define	ZAP_LEAF_ARRAY_BYTES (ZAP_LEAF_CHUNKSIZE - 3)
++
++#define	ZAP_LEAF_HASH_SHIFT(bs)	(bs - 5)
++#define	ZAP_LEAF_HASH_NUMENTRIES(bs) (1 << ZAP_LEAF_HASH_SHIFT(bs))
++#define	LEAF_HASH(bs, h) \
++	((ZAP_LEAF_HASH_NUMENTRIES(bs)-1) & \
++	((h) >> (64 - ZAP_LEAF_HASH_SHIFT(bs)-l->l_hdr.lh_prefix_len)))
++
++/*
++ * The amount of space available for chunks is:
++ * block size shift - hash entry size (2) * number of hash
++ * entries - header space (2*chunksize)
++ */
++#define	ZAP_LEAF_NUMCHUNKS(bs) \
++	(((1<<bs) - 2*ZAP_LEAF_HASH_NUMENTRIES(bs)) / \
++	ZAP_LEAF_CHUNKSIZE - 2)
++
++/*
++ * The chunks start immediately after the hash table.  The end of the
++ * hash table is at l_hash + HASH_NUMENTRIES, which we simply cast to a
++ * chunk_t.
++ */
++#define	ZAP_LEAF_CHUNK(l, bs, idx) \
++	((zap_leaf_chunk_t *)(l->l_hash + ZAP_LEAF_HASH_NUMENTRIES(bs)))[idx]
++#define	ZAP_LEAF_ENTRY(l, bs, idx) (&ZAP_LEAF_CHUNK(l, bs, idx).l_entry)
++
++
++/*
++ * Decompression Entry - lzjb
++ */
++#ifndef	NBBY
++#define	NBBY	8
++#endif
++
++extern grub_err_t lzjb_decompress (void *, void *, grub_size_t, grub_size_t);
++
++typedef grub_err_t zfs_decomp_func_t (void *s_start, void *d_start,
++				      grub_size_t s_len, grub_size_t d_len);
++typedef struct decomp_entry
++{
++  char *name;
++  zfs_decomp_func_t *decomp_func;
++} decomp_entry_t;
++
++typedef struct dnode_end
++{
++  dnode_phys_t dn;
++  grub_zfs_endian_t endian;
++} dnode_end_t;
++
++struct grub_zfs_data
++{
++  /* cache for a file block of the currently zfs_open()-ed file */
++  char *file_buf;
++  grub_uint64_t file_start;
++  grub_uint64_t file_end;
++
++  /* cache for a dnode block */
++  dnode_phys_t *dnode_buf;
++  dnode_phys_t *dnode_mdn;
++  grub_uint64_t dnode_start;
++  grub_uint64_t dnode_end;
++  grub_zfs_endian_t dnode_endian;
++
++  uberblock_t current_uberblock;
++  grub_disk_t disk;
++
++  dnode_end_t mos;
++  dnode_end_t mdn;
++  dnode_end_t dnode;
++
++  grub_disk_addr_t vdev_phys_sector;
++};
++
++decomp_entry_t decomp_table[ZIO_COMPRESS_FUNCTIONS] = {
++  {"inherit", NULL},		/* ZIO_COMPRESS_INHERIT */
++  {"on", lzjb_decompress},	/* ZIO_COMPRESS_ON */
++  {"off", NULL},		/* ZIO_COMPRESS_OFF */
++  {"lzjb", lzjb_decompress},	/* ZIO_COMPRESS_LZJB */
++  {"empty", NULL},		/* ZIO_COMPRESS_EMPTY */
++  {"gzip", NULL},		/* ZIO_COMPRESS_GZIP */
++};
++
++static grub_err_t zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian,
++				 void *buf, struct grub_zfs_data *data);
++
++/*
++ * Our own version of log2().  Same thing as highbit()-1.
++ */
++static int
++zfs_log2 (grub_uint64_t num)
++{
++  int i = 0;
++
++  while (num > 1)
++    {
++      i++;
++      num = num >> 1;
++    }
++
++  return (i);
++}
++
++/* Checksum Functions */
++static void
++zio_checksum_off (const void *buf __attribute__ ((unused)),
++		  grub_uint64_t size __attribute__ ((unused)),
++		  grub_zfs_endian_t endian __attribute__ ((unused)),
++		  zio_cksum_t * zcp)
++{
++  ZIO_SET_CHECKSUM (zcp, 0, 0, 0, 0);
++}
++
++/* Checksum Table and Values */
++zio_checksum_info_t zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS] = {
++  {NULL, 0, 0, "inherit"},
++  {NULL, 0, 0, "on"},
++  {zio_checksum_off, 0, 0, "off"},
++  {zio_checksum_SHA256, 1, 1, "label"},
++  {zio_checksum_SHA256, 1, 1, "gang_header"},
++  {NULL, 0, 0, "zilog"},
++  {fletcher_2, 0, 0, "fletcher2"},
++  {fletcher_4, 1, 0, "fletcher4"},
++  {zio_checksum_SHA256, 1, 0, "SHA256"},
++  {NULL, 0, 0, "zilog2"},
++};
++
++/*
++ * zio_checksum_verify: Provides support for checksum verification.
++ *
++ * Fletcher2, Fletcher4, and SHA256 are supported.
++ *
++ */
++static grub_err_t
++zio_checksum_verify (zio_cksum_t zc, grub_uint32_t checksum,
++		     grub_zfs_endian_t endian, char *buf, int size)
++{
++  zio_eck_t *zec = (zio_eck_t *) (buf + size) - 1;
++  zio_checksum_info_t *ci = &zio_checksum_table[checksum];
++  zio_cksum_t actual_cksum, expected_cksum;
++
++  if (checksum >= ZIO_CHECKSUM_FUNCTIONS || ci->ci_func == NULL)
++    {
++      grub_dprintf ("zfs", "unknown checksum function %d\n", checksum);
++      return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, 
++			 "unknown checksum function %d", checksum);
++    }
++
++  if (ci->ci_eck)
++    {
++      expected_cksum = zec->zec_cksum;  
++      zec->zec_cksum = zc;  
++      ci->ci_func (buf, size, endian, &actual_cksum);
++      zec->zec_cksum = expected_cksum;
++      zc = expected_cksum;
++    }
++  else
++    ci->ci_func (buf, size, endian, &actual_cksum);
++
++  if ((actual_cksum.zc_word[0] != zc.zc_word[0]) 
++      || (actual_cksum.zc_word[1] != zc.zc_word[1]) 
++      || (actual_cksum.zc_word[2] != zc.zc_word[2]) 
++      || (actual_cksum.zc_word[3] != zc.zc_word[3]))
++    {
++      grub_dprintf ("zfs", "checksum %d verification failed\n", checksum);
++      grub_dprintf ("zfs", "actual checksum %16llx %16llx %16llx %16llx\n",
++		    (unsigned long long) actual_cksum.zc_word[0], 
++		    (unsigned long long) actual_cksum.zc_word[1],
++		    (unsigned long long) actual_cksum.zc_word[2], 
++		    (unsigned long long) actual_cksum.zc_word[3]);
++      grub_dprintf ("zfs", "expected checksum %16llx %16llx %16llx %16llx\n",
++		    (unsigned long long) zc.zc_word[0], 
++		    (unsigned long long) zc.zc_word[1],
++		    (unsigned long long) zc.zc_word[2], 
++		    (unsigned long long) zc.zc_word[3]);
++      return grub_error (GRUB_ERR_BAD_FS, "checksum verification failed");
++    }
++
++  return GRUB_ERR_NONE;
++}
++
++/*
++ * vdev_uberblock_compare takes two uberblock structures and returns an integer
++ * indicating the more recent of the two.
++ * 	Return Value = 1 if ub2 is more recent
++ * 	Return Value = -1 if ub1 is more recent
++ * The most recent uberblock is determined using its transaction number and
++ * timestamp.  The uberblock with the highest transaction number is
++ * considered "newer".  If the transaction numbers of the two blocks match, the
++ * timestamps are compared to determine the "newer" of the two.
++ */
++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, LITTLE_ENDIAN) == UBERBLOCK_MAGIC)
++    ub1_endian = LITTLE_ENDIAN;
++  else
++    ub1_endian = BIG_ENDIAN;
++  if (grub_zfs_to_cpu64 (ub2->ub_magic, LITTLE_ENDIAN) == UBERBLOCK_MAGIC)
++    ub2_endian = LITTLE_ENDIAN;
++  else
++    ub2_endian = BIG_ENDIAN;
++
++  if (grub_zfs_to_cpu64 (ub1->ub_txg, ub1_endian) 
++      < grub_zfs_to_cpu64 (ub2->ub_txg, ub2_endian))
++    return (-1);
++  if (grub_zfs_to_cpu64 (ub1->ub_txg, ub1_endian) 
++      > grub_zfs_to_cpu64 (ub2->ub_txg, ub2_endian))
++    return (1);
++
++  if (grub_zfs_to_cpu64 (ub1->ub_timestamp, ub1_endian) 
++      < grub_zfs_to_cpu64 (ub2->ub_timestamp, ub2_endian))
++    return (-1);
++  if (grub_zfs_to_cpu64 (ub1->ub_timestamp, ub1_endian) 
++      > grub_zfs_to_cpu64 (ub2->ub_timestamp, ub2_endian))
++    return (1);
++
++  return (0);
++}
++
++/*
++ * Three pieces of information are needed to verify an uberblock: the magic
++ * number, the version number, and the checksum.
++ *
++ * Currently Implemented: version number, magic number
++ * Need to Implement: checksum
++ *
++ */
++static grub_err_t
++uberblock_verify (uberblock_phys_t * ub, int offset)
++{
++  uberblock_t *uber = &ub->ubp_uberblock;
++  grub_err_t err;
++  grub_zfs_endian_t endian = UNKNOWN_ENDIAN;
++  zio_cksum_t zc;
++
++  if (grub_zfs_to_cpu64 (uber->ub_magic, LITTLE_ENDIAN) == UBERBLOCK_MAGIC
++      && grub_zfs_to_cpu64 (uber->ub_version, LITTLE_ENDIAN) > 0 
++      && grub_zfs_to_cpu64 (uber->ub_version, LITTLE_ENDIAN) <= SPA_VERSION)
++    endian = LITTLE_ENDIAN;
++
++  if (grub_zfs_to_cpu64 (uber->ub_magic, BIG_ENDIAN) == UBERBLOCK_MAGIC
++      && grub_zfs_to_cpu64 (uber->ub_version, BIG_ENDIAN) > 0 
++      && grub_zfs_to_cpu64 (uber->ub_version, BIG_ENDIAN) <= SPA_VERSION)
++    endian = BIG_ENDIAN;
++
++  if (endian == UNKNOWN_ENDIAN)
++    return grub_error (GRUB_ERR_BAD_FS, "invalid uberblock magic");
++
++  grub_memset (&zc, 0, sizeof (zc));
++
++  zc.zc_word[0] = grub_cpu_to_zfs64 (offset, endian);
++  err = zio_checksum_verify (zc, ZIO_CHECKSUM_LABEL, endian,
++			     (char *) ub, UBERBLOCK_SIZE);
++
++  return err;
++}
++
++/*
++ * Find the best uberblock.
++ * Return:
++ *    Success - Pointer to the best uberblock.
++ *    Failure - NULL
++ */
++static uberblock_phys_t *
++find_bestub (uberblock_phys_t * ub_array, grub_disk_addr_t sector)
++{
++  uberblock_phys_t *ubbest = NULL;
++  int i;
++  grub_disk_addr_t offset;
++  grub_err_t err = GRUB_ERR_NONE;
++
++  for (i = 0; i < (VDEV_UBERBLOCK_RING >> VDEV_UBERBLOCK_SHIFT); i++)
++    {
++      offset = (sector << SPA_MINBLOCKSHIFT) + VDEV_PHYS_SIZE
++	+ (i << VDEV_UBERBLOCK_SHIFT);
++
++      err = uberblock_verify (&ub_array[i], offset);
++      if (err)
++	{
++	  grub_errno = GRUB_ERR_NONE;
++	  continue;
++	}
++      if (ubbest == NULL 
++	  || vdev_uberblock_compare (&(ub_array[i].ubp_uberblock),
++				     &(ubbest->ubp_uberblock)) > 0)
++	ubbest = &ub_array[i];
++    }
++  if (!ubbest)
++    grub_errno = err;
++
++  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 (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;
++}
++
++
++/*
++ * Read a block of data based on the gang block address dva,
++ * and put its data in buf.
++ *
++ */
++static grub_err_t
++zio_read_gang (blkptr_t * bp, grub_zfs_endian_t endian, dva_t * dva, void *buf,
++	       struct grub_zfs_data *data)
++{
++  zio_gbh_phys_t *zio_gb;
++  grub_uint64_t offset, sector;
++  unsigned i;
++  grub_err_t err;
++  zio_cksum_t zc;
++
++  grub_memset (&zc, 0, sizeof (zc));
++
++  zio_gb = grub_malloc (SPA_GANGBLOCKSIZE);
++  if (!zio_gb)
++    return grub_errno;
++  grub_dprintf ("zfs", endian == LITTLE_ENDIAN ? "little-endian gang\n"
++		:"big-endian gang\n");
++  offset = dva_get_offset (dva, endian);
++  sector = DVA_OFFSET_TO_PHYS_SECTOR (offset);
++  grub_dprintf ("zfs", "offset=%llx\n", (unsigned long long) offset);
++
++  /* read in the gang block header */
++  err = grub_disk_read (data->disk, sector, 0, SPA_GANGBLOCKSIZE,
++			(char *) zio_gb);
++  if (err)
++    {
++      grub_free (zio_gb);
++      return err;
++    }
++
++  /* 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,
++			     (char *) zio_gb, SPA_GANGBLOCKSIZE);
++  if (err)
++    {
++      grub_free (zio_gb);
++      return err;
++    }
++
++  endian = (grub_zfs_to_cpu64 (bp->blk_prop, endian) >> 63) & 1;
++
++  for (i = 0; i < SPA_GBH_NBLKPTRS; i++)
++    {
++      if (zio_gb->zg_blkptr[i].blk_birth == 0)
++	continue;
++
++      err = zio_read_data (&zio_gb->zg_blkptr[i], endian, buf, data);
++      if (err)
++	{
++	  grub_free (zio_gb);
++	  return err;
++	}
++      buf = (char *) buf + get_psize (&zio_gb->zg_blkptr[i], endian);
++    }
++  grub_free (zio_gb);
++  return GRUB_ERR_NONE;
++}
++
++/*
++ * 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)
++{
++  int i, psize;
++  grub_err_t err = GRUB_ERR_NONE;
++
++  psize = get_psize (bp, endian);
++
++  /* pick a good dva from the block pointer */
++  for (i = 0; i < SPA_DVAS_PER_BP; i++)
++    {
++      grub_uint64_t offset, sector;
++
++      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);
++      else
++	{
++	  /* read in a data block */
++	  offset = dva_get_offset (&bp->blk_dva[i], endian);
++	  sector = DVA_OFFSET_TO_PHYS_SECTOR (offset);
++	  err = grub_disk_read (data->disk, sector, 0, psize, buf); 
++	}
++      if (!err)
++	return GRUB_ERR_NONE;
++      grub_errno = GRUB_ERR_NONE;
++    }
++
++  if (!err)
++    err = grub_error (GRUB_ERR_BAD_FS, "couldn't find a valid DVA");
++  grub_errno = err;
++
++  return err;
++}
++
++/*
++ * Read in a block of data, verify its checksum, decompress if needed,
++ * and put the uncompressed data in buf.
++ */
++static grub_err_t
++zio_read (blkptr_t * bp, grub_zfs_endian_t endian, void **buf, 
++	  grub_size_t *size, struct grub_zfs_data *data)
++{
++  grub_size_t lsize, psize;
++  unsigned int comp;
++  char *compbuf;
++  grub_err_t err;
++  zio_cksum_t zc = bp->blk_cksum;
++  grub_uint32_t checksum;
++
++  checksum = (grub_zfs_to_cpu64((bp)->blk_prop, endian) >> 40) & 0xff;
++  comp = (grub_zfs_to_cpu64((bp)->blk_prop, endian)>>32) & 0x7;
++  lsize = (BP_IS_HOLE(bp) ? 0 :
++	   (((grub_zfs_to_cpu64 ((bp)->blk_prop, endian) & 0xffff) + 1)
++	    << SPA_MINBLOCKSHIFT));
++  psize = get_psize (bp, endian);
++
++  if (size)
++    *size = lsize;
++
++  if (comp >= ZIO_COMPRESS_FUNCTIONS)
++    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
++		       "compression algorithm %u not supported\n", (unsigned int) comp);
++
++  if (comp != ZIO_COMPRESS_OFF && decomp_table[comp].decomp_func == NULL)
++    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
++		       "compression algorithm %s not supported\n", decomp_table[comp].name);
++
++  if (comp != ZIO_COMPRESS_OFF)
++    {
++      compbuf = grub_malloc (psize);
++      if (! compbuf)
++	return grub_errno;
++    }
++  else
++    compbuf = *buf = grub_malloc (lsize);
++
++  grub_dprintf ("zfs", "endian = %d\n", endian);
++  err = zio_read_data (bp, endian, compbuf, data);
++  if (err)
++    {
++      grub_free (compbuf);
++      return err;
++    }
++
++  err = zio_checksum_verify (zc, checksum, endian, compbuf, psize);
++  if (err)
++    {
++      grub_dprintf ("zfs", "incorrect checksum\n");
++      grub_free (compbuf);
++      return err;
++    }
++
++  if (comp != ZIO_COMPRESS_OFF)
++    {
++      *buf = grub_malloc (lsize);
++      err = decomp_table[comp].decomp_func (compbuf, *buf, psize, lsize);
++      grub_free (compbuf);
++      if (err)
++	{
++	  grub_free (*buf);
++	  return err;
++	}
++    }
++
++  return GRUB_ERR_NONE;
++}
++
++/*
++ * Get the block from a block id.
++ * push the block onto the stack.
++ *
++ */
++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)
++{
++  int idx, level;
++  blkptr_t *bp_array = dn->dn.dn_blkptr;
++  int epbs = dn->dn.dn_indblkshift - SPA_BLKPTRSHIFT;
++  blkptr_t *bp, *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--)
++    {
++      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)
++	{
++	  grub_free (bp_array);
++	  bp_array = 0;
++	}
++
++      if (BP_IS_HOLE (bp))
++	{
++	  grub_size_t size = grub_zfs_to_cpu16 (dn->dn.dn_datablkszsec, 
++						dn->endian) 
++	    << SPA_MINBLOCKSHIFT;
++	  *buf = grub_malloc (size);
++	  if (*buf)
++	    {
++	      err = grub_errno;
++	      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;
++	  break;
++	}
++      grub_dprintf ("zfs", "endian = %d\n", endian);
++      err = zio_read (bp, endian, (void **) &tmpbuf, 0, data);
++      endian = (grub_zfs_to_cpu64 (bp->blk_prop, endian) >> 63) & 1;
++      if (err)
++	break;
++      bp_array = tmpbuf;
++    }
++  if (bp_array != dn->dn.dn_blkptr)
++    grub_free (bp_array);
++  if (endian_out)
++    *endian_out = endian;
++
++  grub_free (bp);
++  return err;
++}
++
++/*
++ * mzap_lookup: Looks up property described by "name" and returns the value
++ * in "value".
++ */
++static grub_err_t
++mzap_lookup (mzap_phys_t * zapobj, grub_zfs_endian_t endian,
++	     int objsize, char *name, grub_uint64_t * value)
++{
++  int i, chunks;
++  mzap_ent_phys_t *mzap_ent = zapobj->mz_chunk;
++
++  chunks = objsize / MZAP_ENT_LEN - 1;
++  for (i = 0; i < chunks; i++)
++    {
++      if (grub_strcmp (mzap_ent[i].mze_name, name) == 0)
++	{
++	  *value = grub_zfs_to_cpu64 (mzap_ent[i].mze_value, endian);
++	  return GRUB_ERR_NONE;
++	}
++    }
++
++  return grub_error (GRUB_ERR_FILE_NOT_FOUND, "couldn't find %s", name);
++}
++
++static int
++mzap_iterate (mzap_phys_t * zapobj, grub_zfs_endian_t endian, int objsize, 
++	      int NESTED_FUNC_ATTR (*hook) (const char *name, 
++					    grub_uint64_t val))
++{
++  int i, chunks;
++  mzap_ent_phys_t *mzap_ent = zapobj->mz_chunk;
++
++  chunks = objsize / MZAP_ENT_LEN - 1;
++  for (i = 0; i < chunks; i++)
++    {
++      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)))
++	return 1;
++    }
++
++  return 0;
++}
++
++static grub_uint64_t
++zap_hash (grub_uint64_t salt, const char *name)
++{
++  static grub_uint64_t table[256];
++  const grub_uint8_t *cp;
++  grub_uint8_t c;
++  grub_uint64_t crc = salt;
++
++  if (table[128] == 0)
++    {
++      grub_uint64_t *ct;
++      int i, j;
++      for (i = 0; i < 256; i++)
++	{
++	  for (ct = table + i, *ct = i, j = 8; j > 0; j--)
++	    *ct = (*ct >> 1) ^ (-(*ct & 1) & ZFS_CRC64_POLY);
++	}
++    }
++
++  for (cp = (const grub_uint8_t *) name; (c = *cp) != '\0'; cp++)
++    crc = (crc >> 8) ^ table[(crc ^ c) & 0xFF];
++
++  /*
++   * Only use 28 bits, since we need 4 bits in the cookie for the
++   * collision differentiator.  We MUST use the high bits, since
++   * those are the onces that we first pay attention to when
++   * chosing the bucket.
++   */
++  crc &= ~((1ULL << (64 - ZAP_HASHBITS)) - 1);
++
++  return (crc);
++}
++
++/*
++ * Only to be used on 8-bit arrays.
++ * array_len is actual len in bytes (not encoded le_value_length).
++ * buf is null-terminated.
++ */
++/* XXX */
++static int
++zap_leaf_array_equal (zap_leaf_phys_t * l, grub_zfs_endian_t endian,
++		      int blksft, int chunk, int array_len, const char *buf)
++{
++  int bseen = 0;
++
++  while (bseen < array_len)
++    {
++      struct zap_leaf_array *la = &ZAP_LEAF_CHUNK (l, blksft, chunk).l_array;
++      int toread = MIN (array_len - bseen, ZAP_LEAF_ARRAY_BYTES);
++
++      if (chunk >= ZAP_LEAF_NUMCHUNKS (blksft))
++	return (0);
++
++      if (grub_memcmp (la->la_array, buf + bseen, toread) != 0)
++	break;
++      chunk = grub_zfs_to_cpu16 (la->la_next, endian);
++      bseen += toread;
++    }
++  return (bseen == array_len);
++}
++
++/* XXX */
++static grub_err_t
++zap_leaf_array_get (zap_leaf_phys_t * l, grub_zfs_endian_t endian, int blksft, 
++		    int chunk, int array_len, char *buf)
++{
++  int bseen = 0;
++
++  while (bseen < array_len)
++    {
++      struct zap_leaf_array *la = &ZAP_LEAF_CHUNK (l, blksft, chunk).l_array;
++      int toread = MIN (array_len - bseen, ZAP_LEAF_ARRAY_BYTES);
++
++      if (chunk >= ZAP_LEAF_NUMCHUNKS (blksft))
++	/* Don't use grub_error because this error is to be ignored.  */
++	return GRUB_ERR_BAD_FS;
++
++      grub_memcpy (buf + bseen,la->la_array,  toread);
++      chunk = grub_zfs_to_cpu16 (la->la_next, endian);
++      bseen += toread;
++    }
++  return GRUB_ERR_NONE;
++}
++
++
++/*
++ * Given a zap_leaf_phys_t, walk thru the zap leaf chunks to get the
++ * value for the property "name".
++ *
++ */
++/* XXX */
++static grub_err_t
++zap_leaf_lookup (zap_leaf_phys_t * l, grub_zfs_endian_t endian,
++		 int blksft, grub_uint64_t h,
++		 const char *name, grub_uint64_t * value)
++{
++  grub_uint16_t chunk;
++  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)
++    return grub_error (GRUB_ERR_BAD_FS, "invalid leaf type");
++  if (grub_zfs_to_cpu32 (l->l_hdr.lh_magic, endian) != 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)], endian);
++       chunk != CHAIN_END; chunk = le->le_next)
++    {
++
++      if (chunk >= ZAP_LEAF_NUMCHUNKS (blksft))
++	return grub_error (GRUB_ERR_BAD_FS, "invalid chunk number");
++
++      le = ZAP_LEAF_ENTRY (l, blksft, chunk);
++
++      /* Verify the chunk entry */
++      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)
++	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),
++				name))
++	{
++	  struct zap_leaf_array *la;
++	  grub_uint8_t *ip;
++
++	  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 */
++	  la = &ZAP_LEAF_CHUNK (l, blksft, le->le_value_chunk).l_array;
++	  ip = la->la_array;
++
++	  *value = grub_be_to_cpu64 (la->la_array64);
++
++	  return GRUB_ERR_NONE;
++	}
++    }
++
++  return grub_error (GRUB_ERR_FILE_NOT_FOUND, "couldn't find %s", name);
++}
++
++
++/* Verify if this is a fat zap header block */
++static grub_err_t
++zap_verify (zap_phys_t *zap)
++{
++  if (zap->zap_magic != (grub_uint64_t) ZAP_MAGIC)
++    return grub_error (GRUB_ERR_BAD_FS, "bad ZAP magic");
++
++  if (zap->zap_flags != 0)
++    return grub_error (GRUB_ERR_BAD_FS, "bad ZAP flags");
++
++  if (zap->zap_salt == 0)
++    return grub_error (GRUB_ERR_BAD_FS, "bad ZAP salt");
++
++  return GRUB_ERR_NONE;
++}
++
++/*
++ * Fat ZAP lookup
++ *
++ */
++/* XXX */
++static grub_err_t
++fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap,
++	     char *name, grub_uint64_t * value, struct grub_zfs_data *data)
++{
++  zap_leaf_phys_t *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);
++  grub_err_t err;
++  grub_zfs_endian_t leafendian;
++
++  err = zap_verify (zap);
++  if (err)
++    return err;
++
++  hash = zap_hash (zap->zap_salt, name);
++
++  /* get block id from index */
++  if (zap->zap_ptrtbl.zt_numblks != 0)
++    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_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, (void **) &l, &leafendian, data);
++  if (err)
++    return err;
++
++  err = zap_leaf_lookup (l, leafendian, blksft, hash, name, value);
++  grub_free (l);
++  return err;
++}
++
++/* XXX */
++static int
++fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap,
++	     int NESTED_FUNC_ATTR (*hook) (const char *name, 
++					   grub_uint64_t val), 
++	     struct grub_zfs_data *data)
++{
++  zap_leaf_phys_t *l;
++  grub_uint64_t idx, blkid;
++  grub_uint16_t chunk;
++  int blksft = zfs_log2 (grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, 
++					    zap_dnode->endian) << DNODE_SHIFT);
++  grub_err_t err;
++  grub_zfs_endian_t endian;
++
++  if (zap_verify (zap))
++    return 0;
++
++  /* get block id from index */
++  if (zap->zap_ptrtbl.zt_numblks != 0)
++    {
++      grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, 
++		  "external pointer tables not supported");
++      return 0;
++    }
++  /* Get the leaf block */
++  if ((1U << blksft) < sizeof (zap_leaf_phys_t))
++    {
++      grub_error (GRUB_ERR_BAD_FS, "ZAP leaf is too small");
++      return 0;
++    }
++  for (idx = 0; idx < zap->zap_ptrtbl.zt_numblks; idx++)
++    {
++      blkid = ((grub_uint64_t *) zap)[idx + (1 << (blksft - 3 - 1))];
++
++      err = dmu_read (zap_dnode, blkid, (void **) &l, &endian, data);
++      if (err)
++	{
++	  grub_errno = GRUB_ERR_NONE;
++	  continue;
++	}
++
++      /* Verify if this is a valid leaf block */
++      if (grub_zfs_to_cpu64 (l->l_hdr.lh_block_type, endian) != ZBT_LEAF)
++	{
++	  grub_free (l);
++	  continue;
++	}
++      if (grub_zfs_to_cpu32 (l->l_hdr.lh_magic, endian) != ZAP_LEAF_MAGIC)
++	{
++	  grub_free (l);
++	  continue;
++	}
++
++      for (chunk = 0; chunk < ZAP_LEAF_NUMCHUNKS (blksft); chunk++)
++	  {
++	    char *buf;
++	    struct zap_leaf_array *la;
++	    struct zap_leaf_entry *le;
++	    grub_uint64_t val;
++	    le = ZAP_LEAF_ENTRY (l, blksft, chunk);
++
++	    /* Verify the chunk entry */
++	    if (le->le_type != ZAP_CHUNK_ENTRY)
++	      continue;
++
++	    buf = grub_malloc (grub_zfs_to_cpu16 (le->le_name_length, endian) 
++			       + 1);
++	    if (zap_leaf_array_get (l, endian, blksft, le->le_name_chunk,
++				    le->le_name_length, buf))
++	      {
++		grub_free (buf);
++		continue;
++	      }
++	    buf[le->le_name_length] = 0;
++
++	    if (le->le_int_size != 8 
++		|| grub_zfs_to_cpu16 (le->le_value_length, endian) != 1)
++	      continue;
++
++	    /* get the uint64_t property value */
++	    la = &ZAP_LEAF_CHUNK (l, blksft, le->le_value_chunk).l_array;
++	    val = grub_be_to_cpu64 (la->la_array64);
++	    if (hook (buf, val))
++	      return 1;
++	    grub_free (buf);
++	  }
++    }
++  return 0;
++}
++
++
++/*
++ * Read in the data of a zap object and find the value for a matching
++ * property name.
++ *
++ */
++static grub_err_t
++zap_lookup (dnode_end_t * zap_dnode, char *name, grub_uint64_t * val,
++	    struct grub_zfs_data *data)
++{
++  grub_uint64_t block_type;
++  int 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_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, 
++			    zap_dnode->endian) << SPA_MINBLOCKSHIFT;
++  err = dmu_read (zap_dnode, 0, &zapbuf, &endian, data);
++  if (err)
++    return err;
++  block_type = grub_zfs_to_cpu64 (*((grub_uint64_t *) zapbuf), endian);
++
++  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));
++      grub_dprintf ("zfs", "returned %d\n", err);      
++      grub_free (zapbuf);
++      return err;
++    }
++  else if (block_type == ZBT_HEADER)
++    {
++      grub_dprintf ("zfs", "fat zap\n");
++      /* this is a fat zap */
++      err = (fzap_lookup (zap_dnode, zapbuf, name, val, data));
++      grub_dprintf ("zfs", "returned %d\n", err);      
++      grub_free (zapbuf);
++      return err;
++    }
++
++  return grub_error (GRUB_ERR_BAD_FS, "unknown ZAP type");
++}
++
++static int
++zap_iterate (dnode_end_t * zap_dnode, 
++	     int NESTED_FUNC_ATTR (*hook) (const char *name, grub_uint64_t val),
++	     struct grub_zfs_data *data)
++{
++  grub_uint64_t block_type;
++  int size;
++  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);
++  if (err)
++    return 0;
++  block_type = grub_zfs_to_cpu64 (*((grub_uint64_t *) zapbuf), endian);
++
++  grub_dprintf ("zfs", "zap read\n");
++
++  if (block_type == ZBT_MICRO)
++    {
++      grub_dprintf ("zfs", "micro zap\n");
++      ret = mzap_iterate (zapbuf, endian, size, hook);
++      grub_free (zapbuf);
++      return ret;
++    }
++  else if (block_type == ZBT_HEADER)
++    {
++      grub_dprintf ("zfs", "fat zap\n");
++      /* this is a fat zap */
++      ret = fzap_iterate (zap_dnode, zapbuf, hook, data);
++      grub_free (zapbuf);
++      return ret;
++    }
++  grub_error (GRUB_ERR_BAD_FS, "unknown ZAP type");
++  return 0;
++}
++
++
++/*
++ * Get the dnode of an object number from the metadnode of an object set.
++ *
++ * Input
++ *	mdn - metadnode to get the object dnode
++ *	objnum - object number for the object 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)
++{
++  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 */
++  dnode_phys_t *dnbuf;
++  grub_err_t err;
++  grub_zfs_endian_t endian;
++
++  blksz = grub_zfs_to_cpu16 (mdn->dn.dn_datablkszsec, 
++			     mdn->endian) << SPA_MINBLOCKSHIFT;
++  epbs = zfs_log2 (blksz) - DNODE_SHIFT;
++  blkid = objnum >> epbs;
++  idx = objnum & ((1 << epbs) - 1);
++
++  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) 
++	return grub_error(GRUB_ERR_BAD_FS, "incorrect dnode type"); 
++      return GRUB_ERR_NONE;
++    }
++
++  grub_dprintf ("zfs", "endian = %d, blkid=%llx\n", mdn->endian, 
++		(unsigned long long) blkid);
++  err = dmu_read (mdn, blkid, (void **) &dnbuf, &endian, data);
++  if (err)
++    return err;
++  grub_dprintf ("zfs", "alive\n");
++
++  grub_free (data->dnode_buf);
++  grub_free (data->dnode_mdn);
++  data->dnode_mdn = grub_malloc (sizeof (*mdn));
++  if (! data->dnode_mdn)
++    {
++      grub_errno = GRUB_ERR_NONE;
++      data->dnode_buf = 0;
++    }
++  else
++    {
++      grub_memcpy (data->dnode_mdn, mdn, sizeof (*mdn));
++      data->dnode_buf = dnbuf;
++      data->dnode_start = blkid << epbs;
++      data->dnode_end = (blkid + 1) << epbs;
++      data->dnode_endian = endian;
++    }
++
++  grub_memmove (&(buf->dn), &dnbuf[idx], DNODE_SIZE);
++  buf->endian = endian;
++  if (type && buf->dn.dn_type != type) 
++    return grub_error(GRUB_ERR_BAD_FS, "incorrect dnode type"); 
++
++  return GRUB_ERR_NONE;
++}
++
++/*
++ * Get the file dnode for a given file name where mdn is the meta dnode
++ * for this ZFS object set. When found, place the file dnode in dn.
++ * The 'path' argument will be mangled.
++ *
++ */
++static grub_err_t
++dnode_get_path (dnode_end_t * mdn, const char *path_in, dnode_end_t * dn,
++		struct grub_zfs_data *data)
++{
++  grub_uint64_t objnum, version;
++  char *cname, ch;
++  grub_err_t err = GRUB_ERR_NONE;
++  char *path, *path_buf;
++  struct dnode_chain
++  {
++    struct dnode_chain *next;
++    dnode_end_t dn; 
++  };
++  struct dnode_chain *dnode_path = 0, *dn_new, *root;
++
++  dn_new = grub_malloc (sizeof (*dn_new));
++  if (! dn_new)
++    return grub_errno;
++  dn_new->next = 0;
++  dnode_path = root = dn_new;
++
++  err = dnode_get (mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE, 
++		   &(dnode_path->dn), data);
++  if (err)
++    {
++      grub_free (dn_new);
++      return err;
++    }
++
++  err = zap_lookup (&(dnode_path->dn), ZPL_VERSION_STR, &version, data);
++  if (err)
++    {
++      grub_free (dn_new);
++      return err;
++    }
++  if (version > ZPL_VERSION)
++    {
++      grub_free (dn_new);
++      return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "too new ZPL version");
++    }
++  
++  err = zap_lookup (&(dnode_path->dn), ZFS_ROOT_OBJ, &objnum, data);
++  if (err)
++    {
++      grub_free (dn_new);
++      return err;
++    }
++
++  err = dnode_get (mdn, objnum, 0, &(dnode_path->dn), data);
++  if (err)
++    {
++      grub_free (dn_new);
++      return err;
++    }
++
++  path = path_buf = grub_strdup (path_in);
++  if (!path_buf)
++    {
++      grub_free (dn_new);
++      return grub_errno;
++    }
++  
++  while (1)
++    {
++      /* skip leading slashes */
++      while (*path == '/')
++	path++;
++      if (!*path)
++	break;
++      /* get the next component name */
++      cname = path;
++      while (*path && *path != '/')
++	path++;
++      /* Skip dot.  */
++      if (cname + 1 == path && cname[0] == '.')
++	continue;
++      /* Handle double dot.  */
++      if (cname + 2 == path && cname[0] == '.' && cname[1] == '.')
++	{
++	  if (dn_new->next)
++	    {
++	      dn_new = dnode_path;
++	      dnode_path = dn_new->next;
++	      grub_free (dn_new);
++	    }
++	  else
++	    {
++	      err = grub_error (GRUB_ERR_FILE_NOT_FOUND, 
++				"can't resolve ..");
++	      break;
++	    }
++	  continue;
++	}
++
++      ch = *path;
++      *path = 0;		/* ensure null termination */
++
++      if (dnode_path->dn.dn.dn_type != DMU_OT_DIRECTORY_CONTENTS)
++	{
++	  grub_free (path_buf);
++	  return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
++	}
++      err = zap_lookup (&(dnode_path->dn), cname, &objnum, data);
++      if (err)
++	break;
++
++      dn_new = grub_malloc (sizeof (*dn_new));
++      if (! dn_new)
++	{
++	  err = grub_errno;
++	  break;
++	}
++      dn_new->next = dnode_path;
++      dnode_path = dn_new;
++
++      objnum = ZFS_DIRENT_OBJ (objnum);
++      err = dnode_get (mdn, objnum, 0, &(dnode_path->dn), data);
++      if (err)
++	break;
++
++      *path = ch;      
++      if (((grub_zfs_to_cpu64(((znode_phys_t *) DN_BONUS (&dnode_path->dn.dn))->zp_mode, dnode_path->dn.endian) >> 12) & 0xf) == 0xa && ch)
++	{
++	  char *oldpath = path, *oldpathbuf = path_buf;
++	  path = path_buf 
++	    = grub_malloc (sizeof (dnode_path->dn.dn.dn_bonus) 
++			   - sizeof (znode_phys_t) + grub_strlen (oldpath) + 1);
++	  if (!path_buf)
++	    {
++	      grub_free (oldpathbuf);
++	      return grub_errno;
++	    }
++	  grub_memcpy (path, 
++		       (char *) DN_BONUS(&dnode_path->dn.dn) + sizeof (znode_phys_t),
++		       sizeof (dnode_path->dn.dn.dn_bonus) - sizeof (znode_phys_t));
++	  path [sizeof (dnode_path->dn.dn.dn_bonus) - sizeof (znode_phys_t)] = 0;
++	  grub_memcpy (path + grub_strlen (path), oldpath, 
++		       grub_strlen (oldpath) + 1);
++	  
++	  grub_free (oldpathbuf);
++	  if (path[0] != '/')
++	    {
++	      dn_new = dnode_path;
++	      dnode_path = dn_new->next;
++	      grub_free (dn_new);
++	    }
++	  else while (dnode_path != root)
++	    {
++	      dn_new = dnode_path;
++	      dnode_path = dn_new->next;
++	      grub_free (dn_new);
++	    }
++	}
++    }
++
++  if (!err)
++    grub_memcpy (dn, &(dnode_path->dn), sizeof (*dn));
++
++  while (dnode_path)
++    {
++      dn_new = dnode_path->next;
++      grub_free (dnode_path);
++      dnode_path = dn_new;
++    }
++  grub_free (path_buf);
++  return err;
++}
++
++#if 0
++/*
++ * Get the default 'bootfs' property value from the rootpool.
++ *
++ */
++static grub_err_t
++get_default_bootfsobj (dnode_phys_t * mosmdn, grub_uint64_t * obj,
++		       struct grub_zfs_data *data)
++{
++  grub_uint64_t objnum = 0;
++  dnode_phys_t *dn;
++  if (!dn)
++    return grub_errno;
++
++  if ((grub_errno = dnode_get (mosmdn, DMU_POOL_DIRECTORY_OBJECT,
++			       DMU_OT_OBJECT_DIRECTORY, dn, data)))
++    {
++      grub_free (dn);
++      return (grub_errno);
++    }
++
++  /*
++   * find the object number for 'pool_props', and get the dnode
++   * of the 'pool_props'.
++   */
++  if (zap_lookup (dn, DMU_POOL_PROPS, &objnum, data))
++    {
++      grub_free (dn);
++      return (GRUB_ERR_BAD_FS);
++    }
++  if ((grub_errno = dnode_get (mosmdn, objnum, DMU_OT_POOL_PROPS, dn, data)))
++    {
++      grub_free (dn);
++      return (grub_errno);
++    }
++  if (zap_lookup (dn, ZPOOL_PROP_BOOTFS, &objnum, data))
++    {
++      grub_free (dn);
++      return (GRUB_ERR_BAD_FS);
++    }
++
++  if (!objnum)
++    {
++      grub_free (dn);
++      return (GRUB_ERR_BAD_FS);
++    }
++
++  *obj = objnum;
++  return (0);
++}
++#endif
++/*
++ * Given a MOS metadnode, get the metadnode of a given filesystem name (fsname),
++ * e.g. pool/rootfs, or a given object number (obj), e.g. the object number
++ * of pool/rootfs.
++ *
++ * If no fsname and no obj are given, return the DSL_DIR metadnode.
++ * If fsname is given, return its metadnode and its matching object number.
++ * If only obj is given, return the metadnode for this object number.
++ *
++ */
++static grub_err_t
++get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname,
++		      dnode_end_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)
++    return err;
++
++  grub_dprintf ("zfs", "alive\n");
++
++  err = zap_lookup (mdn, DMU_POOL_ROOT_DATASET, &objnum, data);
++  if (err)
++    return err;
++
++  grub_dprintf ("zfs", "alive\n");
++
++  err = dnode_get (mosmdn, objnum, DMU_OT_DSL_DIR, mdn, data);
++  if (err)
++    return err;
++
++  grub_dprintf ("zfs", "alive\n");
++
++  while (*fsname)
++    {
++      grub_uint64_t childobj;
++      char *cname, ch;
++ 
++      while (*fsname == '/')
++	fsname++;
++
++      if (! *fsname || *fsname == '@')
++	break;
++
++      cname = fsname;
++      while (*fsname && !grub_isspace (*fsname) && *fsname != '/')
++	fsname++;
++      ch = *fsname;
++      *fsname = 0;
++
++      childobj = grub_zfs_to_cpu64 ((((dsl_dir_phys_t *) DN_BONUS (&mdn->dn)))->dd_child_dir_zapobj, mdn->endian);
++      err = dnode_get (mosmdn, childobj,
++		       DMU_OT_DSL_DIR_CHILD_MAP, mdn, data);
++      if (err)
++	return err;
++
++      err = zap_lookup (mdn, cname, &objnum, data);
++      if (err)
++	return err;
++
++      err = dnode_get (mosmdn, objnum, DMU_OT_DSL_DIR, mdn, data);
++      if (err)
++	return err;
++
++      *fsname = ch;
++    }
++  return GRUB_ERR_NONE;
++}
++
++static grub_err_t
++make_mdn (dnode_end_t * mdn, struct grub_zfs_data *data)
++{
++  objset_phys_t *osp;
++  blkptr_t *bp;
++  grub_size_t ospsize;
++  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);
++  if (err)
++    return err;
++  if (ospsize < OBJSET_PHYS_SIZE_V14)
++    {
++      grub_free (osp);
++      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);
++  grub_free (osp);
++  return GRUB_ERR_NONE;
++}
++
++static grub_err_t
++dnode_get_fullpath (const char *fullpath, dnode_end_t * mdn,
++		    grub_uint64_t *mdnobj, dnode_end_t * dn, int *isfs,
++		    struct grub_zfs_data *data)
++{
++  char *fsname, *snapname;
++  const char *ptr_at, *filename;
++  grub_uint64_t headobj;
++  grub_err_t err;
++
++  ptr_at = grub_strchr (fullpath, '@');
++  if (! ptr_at)
++    {
++      *isfs = 1;
++      filename = 0;
++      snapname = 0;
++      fsname = grub_strdup (fullpath);
++    }
++  else
++    {
++      const char *ptr_slash = grub_strchr (ptr_at, '/');
++
++      *isfs = 0;
++      fsname = grub_malloc (ptr_at - fullpath + 1);
++      if (!fsname)
++	return grub_errno;
++      grub_memcpy (fsname, fullpath, ptr_at - fullpath);
++      fsname[ptr_at - fullpath] = 0;
++      if (ptr_at[1] && ptr_at[1] != '/')
++	{
++	  snapname = grub_malloc (ptr_slash - ptr_at);
++	  if (!snapname)
++	    {
++	      grub_free (fsname);
++	      return grub_errno;
++	    }
++	  grub_memcpy (snapname, ptr_at + 1, ptr_slash - ptr_at - 1);
++	  snapname[ptr_slash - ptr_at - 1] = 0;
++	}
++      else
++	snapname = 0;
++      if (ptr_slash)
++	filename = ptr_slash;
++      else
++	filename = "/";
++      grub_dprintf ("zfs", "fsname = '%s' snapname='%s' filename = '%s'\n", 
++		    fsname, snapname, filename);
++    }
++  grub_dprintf ("zfs", "alive\n");
++  err = get_filesystem_dnode (&(data->mos), fsname, dn, data);
++  if (err)
++    {
++      grub_free (fsname);
++      grub_free (snapname);
++      return err;
++    }
++
++  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", mdn->endian);
++
++  err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, mdn, data);
++  if (err)
++    {
++      grub_free (fsname);
++      grub_free (snapname);
++      return err;
++    }
++  grub_dprintf ("zfs", "endian = %d\n", mdn->endian);
++
++  if (snapname)
++    {
++      grub_uint64_t snapobj;
++
++      snapobj = grub_zfs_to_cpu64 (((dsl_dataset_phys_t *) DN_BONUS (&mdn->dn))->ds_snapnames_zapobj, mdn->endian);
++
++      err = dnode_get (&(data->mos), snapobj, 
++		       DMU_OT_DSL_DS_SNAP_MAP, mdn, data);
++      if (!err)
++	err = zap_lookup (mdn, snapname, &headobj, data);
++      if (!err)
++	err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, mdn, data);
++      if (err)
++	{
++	  grub_free (fsname);
++	  grub_free (snapname);
++	  return err;
++	}
++    }
++
++  if (mdnobj)
++    *mdnobj = headobj;
++
++  make_mdn (mdn, data);
++  
++  grub_dprintf ("zfs", "endian = %d\n", mdn->endian);
++
++  if (*isfs)
++    {
++      grub_free (fsname);
++      grub_free (snapname);      
++      return GRUB_ERR_NONE;
++    }
++  err = dnode_get_path (mdn, filename, dn, data);
++  grub_free (fsname);
++  grub_free (snapname);
++  return err;
++}
++
++/*
++ * For a given XDR packed nvlist, verify the first 4 bytes and move on.
++ *
++ * An XDR packed nvlist is encoded as (comments from nvs_xdr_create) :
++ *
++ *      encoding method/host endian     (4 bytes)
++ *      nvl_version                     (4 bytes)
++ *      nvl_nvflag                      (4 bytes)
++ *	encoded nvpairs:
++ *		encoded size of the nvpair      (4 bytes)
++ *		decoded size of the nvpair      (4 bytes)
++ *		name string size                (4 bytes)
++ *		name string data                (sizeof(NV_ALIGN4(string))
++ *		data type                       (4 bytes)
++ *		# of elements in the nvpair     (4 bytes)
++ *		data
++ *      2 zero's for the last nvpair
++ *		(end of the entire list)	(8 bytes)
++ *
++ */
++
++static int
++nvlist_find_value (char *nvlist, char *name, int valtype, char **val,
++		   grub_size_t *size_out, grub_size_t *nelm_out)
++{
++  int name_len, type, encode_size;
++  char *nvpair, *nvp_name;
++
++  /* Verify if the 1st and 2nd byte in the nvlist are valid. */
++  /* NOTE: independently of what endianness header announces all 
++     subsequent values are big-endian.  */
++  if (nvlist[0] != NV_ENCODE_XDR || (nvlist[1] != NV_LITTLE_ENDIAN 
++				     && nvlist[1] != NV_BIG_ENDIAN))
++    {
++      grub_dprintf ("zfs", "incorrect nvlist header\n");
++      grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist");
++      return 0;
++    }
++
++  /* skip the header, nvl_version, and nvl_nvflag */
++  nvlist = nvlist + 4 * 3;
++  /*
++   * Loop thru the nvpair list
++   * The XDR representation of an integer is in big-endian byte order.
++   */
++  while ((encode_size = grub_be_to_cpu32 (*(grub_uint32_t *) nvlist)))
++    {
++      int nelm;
++
++      nvpair = nvlist + 4 * 2;	/* skip the encode/decode size */
++
++      name_len = grub_be_to_cpu32 (*(grub_uint32_t *) nvpair);
++      nvpair += 4;
++
++      nvp_name = nvpair;
++      nvpair = nvpair + ((name_len + 3) & ~3);	/* align */
++
++      type = grub_be_to_cpu32 (*(grub_uint32_t *) nvpair);
++      nvpair += 4;
++
++      nelm = grub_be_to_cpu32 (*(grub_uint32_t *) nvpair);
++      if (nelm < 1)
++	return grub_error (GRUB_ERR_BAD_FS, "empty nvpair");
++
++      nvpair += 4;
++
++      if ((grub_strncmp (nvp_name, name, name_len) == 0) && type == valtype)
++	{
++	  *val = nvpair;
++	  *size_out = encode_size;
++	  if (nelm_out)
++	    *nelm_out = nelm;
++	  return 1;
++	}
++
++      nvlist += encode_size;	/* goto the next nvpair */
++    }
++  return 0;
++}
++
++int
++grub_zfs_nvlist_lookup_uint64 (char *nvlist, char *name, grub_uint64_t * out)
++{
++  char *nvpair;
++  grub_size_t size;
++  int found;
++
++  found = nvlist_find_value (nvlist, name, DATA_TYPE_UINT64, &nvpair, &size, 0);
++  if (!found)
++    return 0;
++  if (size < sizeof (grub_uint64_t))
++    {
++      grub_error (GRUB_ERR_BAD_FS, "invalid uint64");
++      return 0;
++    }
++
++  *out = grub_be_to_cpu64 (*(grub_uint64_t *) nvpair);
++  return 1;
++}
++
++char *
++grub_zfs_nvlist_lookup_string (char *nvlist, char *name)
++{
++  char *nvpair;
++  char *ret;
++  grub_size_t slen;
++  grub_size_t size;
++  int found;
++
++  found = nvlist_find_value (nvlist, name, DATA_TYPE_STRING, &nvpair, &size, 0);
++  if (!found)
++    return 0;
++  if (size < 4)
++    {
++      grub_error (GRUB_ERR_BAD_FS, "invalid string");
++      return 0;
++    }
++  slen = grub_be_to_cpu32 (*(grub_uint32_t *) nvpair);
++  if (slen > size - 4)
++    slen = size - 4;
++  ret = grub_malloc (slen + 1);
++  if (!ret)
++    return 0;
++  grub_memcpy (ret, nvpair + 4, slen);
++  ret[slen] = 0;
++  return ret;
++}
++
++char *
++grub_zfs_nvlist_lookup_nvlist (char *nvlist, char *name)
++{
++  char *nvpair;
++  char *ret;
++  grub_size_t size;
++  int found;
++
++  found = nvlist_find_value (nvlist, name, DATA_TYPE_NVLIST, &nvpair,
++			     &size, 0);
++  if (!found)
++    return 0;
++  ret = grub_zalloc (size + 3 * sizeof (grub_uint32_t));
++  if (!ret)
++    return 0;
++  grub_memcpy (ret, nvlist, sizeof (grub_uint32_t));
++
++  grub_memcpy (ret + sizeof (grub_uint32_t), nvpair, size);
++  return ret;
++}
++
++int
++grub_zfs_nvlist_lookup_nvlist_array_get_nelm (char *nvlist, char *name)
++{
++  char *nvpair;
++  grub_size_t nelm, size;
++  int found;
++
++  found = nvlist_find_value (nvlist, name, DATA_TYPE_NVLIST, &nvpair,
++			     &size, &nelm);
++  if (! found)
++    return -1;
++  return nelm;
++}
++
++char *
++grub_zfs_nvlist_lookup_nvlist_array (char *nvlist, char *name,
++				     grub_size_t index)
++{
++  char *nvpair, *nvpairptr;
++  int found;
++  char *ret;
++  grub_size_t size;
++  unsigned i;
++  grub_size_t nelm;
++
++  found = nvlist_find_value (nvlist, name, DATA_TYPE_NVLIST, &nvpair,
++			     &size, &nelm);
++  if (!found)
++    return 0;
++  if (index >= nelm)
++    {
++      grub_error (GRUB_ERR_OUT_OF_RANGE, "trying to lookup past nvlist array");
++      return 0;
++    }
++
++  nvpairptr = nvpair;
++
++  for (i = 0; i < index; i++)
++    {
++      grub_uint32_t encode_size;
++
++      /* skip the header, nvl_version, and nvl_nvflag */
++      nvpairptr = nvpairptr + 4 * 2;
++
++      while (nvpairptr < nvpair + size
++	     && (encode_size = grub_be_to_cpu32 (*(grub_uint32_t *) nvpairptr)))
++	nvlist += encode_size;	/* goto the next nvpair */
++
++      nvlist = nvlist + 4 * 2;	/* skip the ending 2 zeros - 8 bytes */
++    }
++
++  if (nvpairptr >= nvpair + size
++      || nvpairptr + grub_be_to_cpu32 (*(grub_uint32_t *) (nvpairptr + 4 * 2))
++      >= nvpair + size)
++    {
++      grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist array");
++      return 0;
++    }
++
++  ret = grub_zalloc (grub_be_to_cpu32 (*(grub_uint32_t *) (nvpairptr + 4 * 2))
++		     + 3 * sizeof (grub_uint32_t));
++  if (!ret)
++    return 0;
++  grub_memcpy (ret, nvlist, sizeof (grub_uint32_t));
++
++  grub_memcpy (ret + sizeof (grub_uint32_t), nvpairptr, size);
++  return ret;
++}
++
++static grub_err_t
++zfs_fetch_nvlist (struct grub_zfs_data * data, char **nvlist)
++{
++  grub_err_t err;
++
++  *nvlist = grub_malloc (VDEV_PHYS_SIZE);
++  /* Read in the vdev name-value pair list (112K). */
++  err = grub_disk_read (data->disk, data->vdev_phys_sector, 0,
++			VDEV_PHYS_SIZE, *nvlist);
++  if (err)
++    {
++      grub_free (*nvlist);
++      *nvlist = 0;
++      return err;
++    }
++  return GRUB_ERR_NONE;
++}
++
++/*
++ * Check the disk label information and retrieve needed vdev name-value pairs.
++ *
++ */
++static grub_err_t
++check_pool_label (struct grub_zfs_data *data)
++{
++  grub_uint64_t pool_state, txg = 0;
++  char *nvlist;
++#if 0
++  char *nv;
++#endif
++  grub_uint64_t diskguid;
++  grub_uint64_t version;
++  int found;
++  grub_err_t err;
++
++  err = zfs_fetch_nvlist (data, &nvlist);
++  if (err)
++    return err;
++
++  grub_dprintf ("zfs", "check 2 passed\n");
++
++  found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_STATE,
++					 &pool_state);
++  if (! found)
++    {
++      grub_free (nvlist);
++      if (! grub_errno)
++	grub_error (GRUB_ERR_BAD_FS, ZPOOL_CONFIG_POOL_STATE " not found");
++      return grub_errno;
++    }
++  grub_dprintf ("zfs", "check 3 passed\n");
++
++  if (pool_state == POOL_STATE_DESTROYED)
++    {
++      grub_free (nvlist);
++      return grub_error (GRUB_ERR_BAD_FS, "zpool is marked as destroyed");
++    }
++  grub_dprintf ("zfs", "check 4 passed\n");
++
++  found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_TXG, &txg);
++  if (!found)
++    {
++      grub_free (nvlist);
++      if (! grub_errno)
++	grub_error (GRUB_ERR_BAD_FS, ZPOOL_CONFIG_POOL_TXG " not found");
++      return grub_errno;
++    }
++  grub_dprintf ("zfs", "check 6 passed\n");
++
++  /* not an active device */
++  if (txg == 0)
++    {
++      grub_free (nvlist);
++      return grub_error (GRUB_ERR_BAD_FS, "zpool isn't active");
++    }
++  grub_dprintf ("zfs", "check 7 passed\n");
++
++  found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_VERSION,
++					 &version);
++  if (! found)
++    {
++      grub_free (nvlist);
++      if (! grub_errno)
++	grub_error (GRUB_ERR_BAD_FS, ZPOOL_CONFIG_VERSION " not found");
++      return grub_errno;
++    }
++  grub_dprintf ("zfs", "check 8 passed\n");
++
++  if (version > SPA_VERSION)
++    {
++      grub_free (nvlist);
++      return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
++			 "too new version %llu > %llu",
++			 (unsigned long long) version,
++			 (unsigned long long) SPA_VERSION);
++    }
++  grub_dprintf ("zfs", "check 9 passed\n");
++#if 0
++  if (nvlist_lookup_value (nvlist, ZPOOL_CONFIG_VDEV_TREE, &nv,
++			   DATA_TYPE_NVLIST, NULL))
++    {
++      grub_free (vdev);
++      return (GRUB_ERR_BAD_FS);
++    }
++  grub_dprintf ("zfs", "check 10 passed\n");
++#endif
++
++  found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_GUID, &diskguid);
++  if (! found)
++    {
++      grub_free (nvlist);
++      if (! grub_errno)
++	grub_error (GRUB_ERR_BAD_FS, ZPOOL_CONFIG_GUID " not found");
++      return grub_errno;
++    }
++  grub_dprintf ("zfs", "check 11 passed\n");
++
++  grub_free (nvlist);
++
++  return GRUB_ERR_NONE;
++}
++
++static void
++zfs_unmount (struct grub_zfs_data *data)
++{
++  grub_free (data->dnode_buf);
++  grub_free (data->dnode_mdn);
++  grub_free (data->file_buf);
++  grub_free (data);
++}
++
++/*
++ * zfs_mount() locates a valid uberblock of the root pool and read in its MOS
++ * to the memory address MOS.
++ *
++ */
++static struct grub_zfs_data *
++zfs_mount (grub_device_t dev)
++{
++  struct grub_zfs_data *data = 0;
++  int label = 0;
++  uberblock_phys_t *ub_array, *ubbest = NULL;
++  vdev_boot_header_t *bh;
++  objset_phys_t *osp = 0;
++  grub_size_t ospsize;
++  grub_err_t err;
++  int vdevnum;
++
++  if (! dev->disk)
++    {
++      grub_error (GRUB_ERR_BAD_DEVICE, "not a disk");
++      return 0;
++    }
++
++  data = grub_malloc (sizeof (*data));
++  if (!data)
++    return 0;
++  grub_memset (data, 0, sizeof (*data));
++#if 0
++  /* if it's our first time here, zero the best uberblock out */
++  if (data->best_drive == 0 && data->best_part == 0 && find_best_root)
++    grub_memset (&current_uberblock, 0, sizeof (uberblock_t));
++#endif
++
++  data->disk = dev->disk;
++
++  ub_array = grub_malloc (VDEV_UBERBLOCK_RING);
++  if (!ub_array)
++    {
++      zfs_unmount (data);
++      return 0;
++    }
++
++  bh = grub_malloc (VDEV_BOOT_HEADER_SIZE);
++  if (!bh)
++    {
++      zfs_unmount (data);
++      grub_free (ub_array);
++      return 0;
++    }
++
++  vdevnum = VDEV_LABELS;
++
++  /* Don't check back labels on CDROM.  */
++  if (! data->disk->partition
++      && data->disk->dev->id == GRUB_DISK_DEVICE_BIOSDISK_ID
++      && data->disk->id >= 0xc0)
++    vdevnum = VDEV_LABELS / 2;
++
++  for (label = 0; ubbest == NULL && label < vdevnum; label++)
++    {
++      grub_zfs_endian_t ub_endian = UNKNOWN_ENDIAN;
++      grub_dprintf ("zfs", "label %d\n", label);
++
++      data->vdev_phys_sector
++	= label * (sizeof (vdev_label_t) >> SPA_MINBLOCKSHIFT)
++	+ ((VDEV_SKIP_SIZE + VDEV_BOOT_HEADER_SIZE) >> SPA_MINBLOCKSHIFT)
++	+ (label < VDEV_LABELS / 2 ? 0 : grub_disk_get_size (dev->disk)
++	   - VDEV_LABELS * (sizeof (vdev_label_t) >> SPA_MINBLOCKSHIFT));
++
++      /* Read in the uberblock ring (128K). */
++      err = grub_disk_read (data->disk, data->vdev_phys_sector
++			    + (VDEV_PHYS_SIZE >> SPA_MINBLOCKSHIFT),
++			    0, VDEV_UBERBLOCK_RING, (char *) ub_array);
++      if (err)
++	{
++	  grub_errno = GRUB_ERR_NONE;
++	  continue;
++	}
++      grub_dprintf ("zfs", "label ok %d\n", label);
++
++      ubbest = find_bestub (ub_array, data->vdev_phys_sector);
++      if (!ubbest)
++	{
++	  grub_dprintf ("zfs", "No uberblock found\n");
++	  grub_errno = GRUB_ERR_NONE;
++	  continue;
++	}
++      ub_endian = (grub_zfs_to_cpu64 (ubbest->ubp_uberblock.ub_magic, 
++				     LITTLE_ENDIAN) == UBERBLOCK_MAGIC 
++		   ? LITTLE_ENDIAN : BIG_ENDIAN);
++      err = zio_read (&ubbest->ubp_uberblock.ub_rootbp, 
++		      ub_endian,
++		      (void **) &osp, &ospsize, data);
++      if (err)
++	{
++	  grub_dprintf ("zfs", "couldn't zio_read\n"); 
++	  grub_errno = GRUB_ERR_NONE;
++	  continue;
++	}
++
++      if (ospsize < OBJSET_PHYS_SIZE_V14)
++	{
++	  grub_dprintf ("zfs", "osp too small\n"); 
++	  grub_free (osp);
++	  continue;
++	}
++      grub_dprintf ("zfs", "ubbest %p\n", ubbest);
++
++      err = check_pool_label (data);
++      if (err)
++	{
++	  grub_errno = GRUB_ERR_NONE;
++	  continue;
++	}
++#if 0
++      if (find_best_root &&
++	  vdev_uberblock_compare (&ubbest->ubp_uberblock,
++				  &(current_uberblock)) <= 0)
++	continue;
++#endif
++      /* 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 (ubbest->ubp_uberblock.ub_rootbp.blk_prop, ub_endian) >> 63) & 1;
++      grub_memmove (&(data->current_uberblock),
++		    &ubbest->ubp_uberblock, sizeof (uberblock_t));
++      grub_free (ub_array);
++      grub_free (bh);
++      grub_free (osp);
++      return data;  
++    }
++  grub_error (GRUB_ERR_BAD_FS, "couldn't find a valid label");
++  zfs_unmount (data);
++  grub_free (ub_array);
++  grub_free (bh);
++  grub_free (osp);
++
++  return 0;
++}
++
++grub_err_t
++grub_zfs_fetch_nvlist (grub_device_t dev, char **nvlist)
++{
++  struct grub_zfs_data *zfs;
++  grub_err_t err;
++
++  zfs = zfs_mount (dev);
++  if (!zfs)
++    return grub_errno;
++  err = zfs_fetch_nvlist (zfs, nvlist);
++  zfs_unmount (zfs);
++  return err;
++}
++
++static grub_err_t 
++zfs_label (grub_device_t device, char **label)
++{
++  char *nvlist;
++  grub_err_t err;
++  struct grub_zfs_data *data;
++
++  data = zfs_mount (device);
++  if (! data)
++    return grub_errno;
++
++  err = zfs_fetch_nvlist (data, &nvlist);
++  if (err)      
++    {
++      zfs_unmount (data);
++      return err;
++    }
++
++  *label = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_POOL_NAME);
++  grub_free (nvlist);
++  zfs_unmount (data);
++  return grub_errno;
++}
++
++static grub_err_t 
++zfs_uuid (grub_device_t device, char **uuid)
++{
++  char *nvlist;
++  int found;
++  struct grub_zfs_data *data;
++  grub_uint64_t guid;
++  grub_err_t err;
++
++  *uuid = 0;
++
++  data = zfs_mount (device);
++  if (! data)
++    return grub_errno;
++
++  err = zfs_fetch_nvlist (data, &nvlist);
++  if (err)
++    {
++      zfs_unmount (data);
++      return err;
++    }
++
++  found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_GUID, &guid);
++  if (! found)
++    return grub_errno;
++  grub_free (nvlist);
++  *uuid = grub_xasprintf ("%016llx", (long long unsigned) guid);
++  zfs_unmount (data);
++  if (! *uuid)
++    return grub_errno;
++  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.
++ */
++static grub_err_t
++grub_zfs_open (struct grub_file *file, const char *fsfilename)
++{
++  struct grub_zfs_data *data;
++  grub_err_t err;
++  int isfs;
++
++  data = zfs_mount (file->device);
++  if (! data)
++    return grub_errno;
++
++  err = dnode_get_fullpath (fsfilename, &(data->mdn), 0,
++			    &(data->dnode), &isfs, data);
++  if (err)
++    {
++      zfs_unmount (data);
++      return err;
++    }
++
++  if (isfs)
++    {
++      zfs_unmount (data);
++      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "Missing @ or / separator");
++    }
++
++  /* 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) 
++    {
++      zfs_unmount (data);
++      return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a file");
++    }
++
++  /* get the file size and set the file position to 0 */
++
++  /*
++   * For DMU_OT_SA we will need to locate the SIZE attribute
++   * attribute, which could be either in the bonus buffer
++   * or the "spill" block.
++   */
++  if (data->dnode.dn.dn_bonustype == DMU_OT_SA)
++    {
++      sa_hdr_phys_t *sahdrp;
++      int hdrsize;
++
++      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;
++	  grub_err_t err;
++
++	  err = zio_read (bp, data->dnode.endian, (void **) &sahdrp, NULL, data);
++	  if (err)
++	    return err;
++	}
++      else
++	{
++	  return grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt");
++	}
++
++      hdrsize = SA_HDR_SIZE (sahdrp);
++      file->size = *(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_SIZE_OFFSET);
++    }
++  else
++    {
++      file->size = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&data->dnode.dn))->zp_size, data->dnode.endian);
++    }
++
++  file->data = data;
++  file->offset = 0;
++
++#ifndef GRUB_UTIL
++  grub_dl_ref (my_mod);
++#endif
++
++  return GRUB_ERR_NONE;
++}
++
++static grub_ssize_t
++grub_zfs_read (grub_file_t file, char *buf, grub_size_t len)
++{
++  struct grub_zfs_data *data = (struct grub_zfs_data *) file->data;
++  int blksz, movesize;
++  grub_size_t length;
++  grub_size_t read;
++  grub_err_t err;
++
++  if (data->file_buf == NULL)
++    {
++      data->file_buf = grub_malloc (SPA_MAXBLOCKSIZE);
++      if (!data->file_buf)
++	return -1;
++      data->file_start = data->file_end = 0;
++    }
++
++  /*
++   * If offset is in memory, move it into the buffer provided and return.
++   */
++  if (file->offset >= data->file_start
++      && file->offset + len <= data->file_end)
++    {
++      grub_memmove (buf, data->file_buf + file->offset - data->file_start,
++		    len);
++      return len;
++    }
++
++  blksz = grub_zfs_to_cpu16 (data->dnode.dn.dn_datablkszsec, 
++			     data->dnode.endian) << SPA_MINBLOCKSHIFT;
++
++  /*
++   * Entire Dnode is too big to fit into the space available.  We
++   * will need to read it in chunks.  This could be optimized to
++   * read in as large a chunk as there is space available, but for
++   * now, this only reads in one data block at a time.
++   */
++  length = len;
++  read = 0;
++  while (length)
++    {
++      /*
++       * Find requested blkid and the offset within that block.
++       */
++      grub_uint64_t blkid = grub_divmod64 (file->offset + read, blksz, 0);
++      grub_free (data->file_buf);
++      data->file_buf = 0;
++
++      err = dmu_read (&(data->dnode), blkid, (void **) &(data->file_buf),
++		      0, data);
++      if (err)
++	return -1;
++
++      data->file_start = blkid * blksz;
++      data->file_end = data->file_start + blksz;
++
++      movesize = MIN (length, data->file_end - (int) file->offset - read);
++
++      grub_memmove (buf, data->file_buf + file->offset + read
++		    - data->file_start, movesize);
++      buf += movesize;
++      length -= movesize;
++      read += movesize;
++    }
++
++  return len;
++}
++
++static grub_err_t
++grub_zfs_close (grub_file_t file)
++{
++  zfs_unmount ((struct grub_zfs_data *) file->data);
++
++#ifndef GRUB_UTIL
++  grub_dl_unref (my_mod);
++#endif
++
++  return GRUB_ERR_NONE;
++}
++
++grub_err_t
++grub_zfs_getmdnobj (grub_device_t dev, const char *fsfilename,
++		    grub_uint64_t *mdnobj)
++{
++  struct grub_zfs_data *data;
++  grub_err_t err;
++  int isfs;
++
++  data = zfs_mount (dev);
++  if (! data)
++    return grub_errno;
++
++  err = dnode_get_fullpath (fsfilename, &(data->mdn), mdnobj,
++			    &(data->dnode), &isfs, data);
++  zfs_unmount (data);
++  return err;
++}
++
++static void
++fill_fs_info (struct grub_dirhook_info *info,
++	      dnode_end_t mdn, struct grub_zfs_data *data)
++{
++  grub_err_t err;
++  dnode_end_t dn;
++  grub_uint64_t objnum;
++  grub_uint64_t headobj;
++  
++  grub_memset (info, 0, sizeof (*info));
++    
++  info->dir = 1;
++  
++  if (mdn.dn.dn_type == DMU_OT_DSL_DIR)
++    {
++      headobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&mdn.dn))->dd_head_dataset_obj, mdn.endian);
++
++      err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, &mdn, data);
++      if (err)
++	{
++	  grub_dprintf ("zfs", "failed here\n");
++	  return;
++	}
++    }
++  make_mdn (&mdn, data);
++  err = dnode_get (&mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE, 
++		   &dn, data);
++  if (err)
++    {
++      grub_dprintf ("zfs", "failed here\n");
++      return;
++    }
++  
++  err = zap_lookup (&dn, ZFS_ROOT_OBJ, &objnum, data);
++  if (err)
++    {
++      grub_dprintf ("zfs", "failed here\n");
++      return;
++    }
++  
++  err = dnode_get (&mdn, objnum, 0, &dn, data);
++  if (err)
++    {
++      grub_dprintf ("zfs", "failed here\n");
++      return;
++    }
++  
++  info->mtimeset = 1;
++  info->mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0], dn.endian);
++  return;
++}
++
++static grub_err_t
++grub_zfs_dir (grub_device_t device, const char *path,
++	      int (*hook) (const char *, const struct grub_dirhook_info *))
++{
++  struct grub_zfs_data *data;
++  grub_err_t err;
++  int isfs;
++  auto int NESTED_FUNC_ATTR iterate_zap (const char *name, grub_uint64_t val);
++  auto int NESTED_FUNC_ATTR iterate_zap_fs (const char *name, 
++					    grub_uint64_t val);
++  auto int NESTED_FUNC_ATTR iterate_zap_snap (const char *name, 
++					      grub_uint64_t val);
++
++  int NESTED_FUNC_ATTR iterate_zap (const char *name, grub_uint64_t val)
++  {
++    struct grub_dirhook_info info;
++    dnode_end_t dn;
++    grub_memset (&info, 0, sizeof (info));
++
++    dnode_get (&(data->mdn), val, 0, &dn, data);
++    info.mtimeset = 1;
++    info.mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0], dn.endian);
++    info.dir = (dn.dn.dn_type == DMU_OT_DIRECTORY_CONTENTS);
++    grub_dprintf ("zfs", "type=%d, name=%s\n", 
++		  (int)dn.dn.dn_type, (char *)name);
++    return hook (name, &info);
++  }
++
++  int NESTED_FUNC_ATTR iterate_zap_fs (const char *name, grub_uint64_t val)
++  {
++    struct grub_dirhook_info info;
++    dnode_end_t mdn;
++    err = dnode_get (&(data->mos), val, 0, &mdn, data);
++    if (err)
++      return 0;
++    if (mdn.dn.dn_type != DMU_OT_DSL_DIR)
++      return 0;
++
++    fill_fs_info (&info, mdn, data);
++    return hook (name, &info);
++  }
++  int NESTED_FUNC_ATTR iterate_zap_snap (const char *name, grub_uint64_t val)
++  {
++    struct grub_dirhook_info info;
++    char *name2;
++    int ret;
++    dnode_end_t mdn;
++
++    err = dnode_get (&(data->mos), val, 0, &mdn, data);
++    if (err)
++      return 0;
++
++    if (mdn.dn.dn_type != DMU_OT_DSL_DATASET)
++      return 0;
++
++    fill_fs_info (&info, mdn, data);
++
++    name2 = grub_malloc (grub_strlen (name) + 2);
++    name2[0] = '@';
++    grub_memcpy (name2 + 1, name, grub_strlen (name) + 1);
++    ret = hook (name2, &info);
++    grub_free (name2);
++    return ret;
++  }
++
++  data = zfs_mount (device);
++  if (! data)
++    return grub_errno;
++  err = dnode_get_fullpath (path, &(data->mdn), 0, &(data->dnode), &isfs, data);
++  if (err)
++    {
++      zfs_unmount (data);
++      return err;
++    }
++  if (isfs)
++    {
++      grub_uint64_t childobj, headobj; 
++      grub_uint64_t snapobj;
++      dnode_end_t dn;
++      struct grub_dirhook_info info;
++
++      fill_fs_info (&info, data->dnode, data);
++      hook ("@", &info);
++      
++      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);
++      err = dnode_get (&(data->mos), childobj,
++		       DMU_OT_DSL_DIR_CHILD_MAP, &dn, data);
++      if (err)
++	{
++	  zfs_unmount (data);
++	  return err;
++	}
++
++      zap_iterate (&dn, iterate_zap_fs, data);
++      
++      err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, &dn, data);
++      if (err)
++	{
++	  zfs_unmount (data);
++	  return err;
++	}
++
++      snapobj = grub_zfs_to_cpu64 (((dsl_dataset_phys_t *) DN_BONUS (&dn.dn))->ds_snapnames_zapobj, dn.endian);
++
++      err = dnode_get (&(data->mos), snapobj,
++		       DMU_OT_DSL_DS_SNAP_MAP, &dn, data);
++      if (err)
++	{
++	  zfs_unmount (data);
++	  return err;
++	}
++
++      zap_iterate (&dn, iterate_zap_snap, data);
++    }
++  else
++    {
++      if (data->dnode.dn.dn_type != DMU_OT_DIRECTORY_CONTENTS)
++	{
++	  zfs_unmount (data);
++	  return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
++	}
++      zap_iterate (&(data->dnode), iterate_zap, data);
++    }
++  zfs_unmount (data);
++  return grub_errno;
++}
++
++static struct grub_fs grub_zfs_fs = {
++  .name = "zfs",
++  .dir = grub_zfs_dir,
++  .open = grub_zfs_open,
++  .read = grub_zfs_read,
++  .close = grub_zfs_close,
++  .label = zfs_label,
++  .uuid = zfs_uuid,
++  .mtime = 0,
++  .next = 0
++};
++
++GRUB_MOD_INIT (zfs)
++{
++  grub_fs_register (&grub_zfs_fs);
++#ifndef GRUB_UTIL
++  my_mod = mod;
++#endif
++}
++
++GRUB_MOD_FINI (zfs)
++{
++  grub_fs_unregister (&grub_zfs_fs);
++}
+--- grub-1.98.orig/grub-extras/zfs/zfs_fletcher.c	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/zfs_fletcher.c	2010-10-13 00:16:54.874814000 -0700
+@@ -0,0 +1,86 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
++ *  Copyright 2007 Sun Microsystems, Inc.
++ *  Copyright (C) 2009  Vladimir Serbinenko <phcoder@gmail.com>
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 3 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <grub/err.h>
++#include <grub/file.h>
++#include <grub/mm.h>
++#include <grub/misc.h>
++#include <grub/disk.h>
++#include <grub/dl.h>
++#include <grub/types.h>
++#include <grub/zfs/zfs.h>
++#include <grub/zfs/zio.h>
++#include <grub/zfs/dnode.h>
++#include <grub/zfs/uberblock_impl.h>
++#include <grub/zfs/vdev_impl.h>
++#include <grub/zfs/zio_checksum.h>
++#include <grub/zfs/zap_impl.h>
++#include <grub/zfs/zap_leaf.h>
++#include <grub/zfs/zfs_znode.h>
++#include <grub/zfs/dmu.h>
++#include <grub/zfs/dmu_objset.h>
++#include <grub/zfs/dsl_dir.h>
++#include <grub/zfs/dsl_dataset.h>
++
++void
++fletcher_2(const void *buf, grub_uint64_t size, grub_zfs_endian_t endian, 
++	   zio_cksum_t *zcp)
++{
++  const grub_uint64_t *ip = buf;
++  const grub_uint64_t *ipend = ip + (size / sizeof (grub_uint64_t));
++  grub_uint64_t a0, b0, a1, b1;
++  
++  for (a0 = b0 = a1 = b1 = 0; ip < ipend; ip += 2) 
++    {
++      a0 += grub_zfs_to_cpu64 (ip[0], endian);
++      a1 += grub_zfs_to_cpu64 (ip[1], endian);
++      b0 += a0;
++      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);
++}
++
++void
++fletcher_4 (const void *buf, grub_uint64_t size, grub_zfs_endian_t endian, 
++	    zio_cksum_t *zcp)
++{
++  const grub_uint32_t *ip = buf;
++  const grub_uint32_t *ipend = ip + (size / sizeof (grub_uint32_t));
++  grub_uint64_t a, b, c, d;
++  
++  for (a = b = c = d = 0; ip < ipend; ip++) 
++    {
++      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);
++}
++
+--- grub-1.98.orig/grub-extras/zfs/zfs_lzjb.c	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/zfs_lzjb.c	2010-10-13 00:16:54.874814000 -0700
+@@ -0,0 +1,95 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
++ *  Copyright 2007 Sun Microsystems, Inc.
++ *  Copyright (C) 2009  Vladimir Serbinenko <phcoder@gmail.com>
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 3 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <grub/err.h>
++#include <grub/file.h>
++#include <grub/mm.h>
++#include <grub/misc.h>
++#include <grub/disk.h>
++#include <grub/dl.h>
++#include <grub/types.h>
++#include <grub/zfs/zfs.h>
++#include <grub/zfs/zio.h>
++#include <grub/zfs/dnode.h>
++#include <grub/zfs/uberblock_impl.h>
++#include <grub/zfs/vdev_impl.h>
++#include <grub/zfs/zio_checksum.h>
++#include <grub/zfs/zap_impl.h>
++#include <grub/zfs/zap_leaf.h>
++#include <grub/zfs/zfs_znode.h>
++#include <grub/zfs/dmu.h>
++#include <grub/zfs/dmu_objset.h>
++#include <grub/zfs/dsl_dir.h>
++#include <grub/zfs/dsl_dataset.h>
++
++#define	MATCH_BITS	6
++#define	MATCH_MIN	3
++#define	OFFSET_MASK	((1 << (16 - MATCH_BITS)) - 1)
++
++/*
++ * Decompression Entry - lzjb
++ */
++#ifndef	NBBY
++#define	NBBY	8
++#endif
++
++grub_err_t
++lzjb_decompress (void *s_start, void *d_start, grub_size_t s_len,
++		 grub_size_t d_len);
++
++grub_err_t
++lzjb_decompress (void *s_start, void *d_start, grub_size_t s_len,
++		 grub_size_t d_len)
++{
++  grub_uint8_t *src = s_start;
++  grub_uint8_t *dst = d_start;
++  grub_uint8_t *d_end = (grub_uint8_t *) d_start + d_len;
++  grub_uint8_t *s_end = (grub_uint8_t *) s_start + s_len;
++  grub_uint8_t *cpy, copymap = 0;
++  int copymask = 1 << (NBBY - 1);
++
++  while (dst < d_end && src < s_end)
++    {
++      if ((copymask <<= 1) == (1 << NBBY))
++	{
++	  copymask = 1;
++	  copymap = *src++;
++	}
++      if (src >= s_end)
++	return grub_error (GRUB_ERR_BAD_FS, "lzjb decompression failed");
++      if (copymap & copymask)
++	{
++	  int mlen = (src[0] >> (NBBY - MATCH_BITS)) + MATCH_MIN;
++	  int offset = ((src[0] << NBBY) | src[1]) & OFFSET_MASK;
++	  src += 2;
++	  cpy = dst - offset;
++	  if (src > s_end || cpy < (grub_uint8_t *) d_start)
++	    return grub_error (GRUB_ERR_BAD_FS, "lzjb decompression failed");
++	  while (--mlen >= 0 && dst < d_end)
++	    *dst++ = *cpy++;
++	}
++      else
++	*dst++ = *src++;
++    }
++  if (dst < d_end)
++    return grub_error (GRUB_ERR_BAD_FS, "lzjb decompression failed");
++  return GRUB_ERR_NONE;
++}
+--- grub-1.98.orig/grub-extras/zfs/zfs_sha256.c	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/zfs_sha256.c	2010-10-13 00:16:54.874814000 -0700
+@@ -0,0 +1,145 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
++ *  Copyright 2007 Sun Microsystems, Inc.
++ *  Copyright (C) 2009  Vladimir Serbinenko <phcoder@gmail.com>
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 3 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <grub/err.h>
++#include <grub/file.h>
++#include <grub/mm.h>
++#include <grub/misc.h>
++#include <grub/disk.h>
++#include <grub/dl.h>
++#include <grub/types.h>
++#include <grub/zfs/zfs.h>
++#include <grub/zfs/zio.h>
++#include <grub/zfs/dnode.h>
++#include <grub/zfs/uberblock_impl.h>
++#include <grub/zfs/vdev_impl.h>
++#include <grub/zfs/zio_checksum.h>
++#include <grub/zfs/zap_impl.h>
++#include <grub/zfs/zap_leaf.h>
++#include <grub/zfs/zfs_znode.h>
++#include <grub/zfs/dmu.h>
++#include <grub/zfs/dmu_objset.h>
++#include <grub/zfs/dsl_dir.h>
++#include <grub/zfs/dsl_dataset.h>
++
++/*
++ * SHA-256 checksum, as specified in FIPS 180-2, available at:
++ * http://csrc.nist.gov/cryptval
++ *
++ * This is a very compact implementation of SHA-256.
++ * It is designed to be simple and portable, not to be fast.
++ */
++
++/*
++ * The literal definitions according to FIPS180-2 would be:
++ *
++ * 	Ch(x, y, z)     (((x) & (y)) ^ ((~(x)) & (z)))
++ * 	Maj(x, y, z)    (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
++ *
++ * We use logical equivalents which require one less op.
++ */
++#define	Ch(x, y, z)	((z) ^ ((x) & ((y) ^ (z))))
++#define	Maj(x, y, z)	(((x) & (y)) ^ ((z) & ((x) ^ (y))))
++#define	Rot32(x, s)	(((x) >> s) | ((x) << (32 - s)))
++#define	SIGMA0(x)	(Rot32(x, 2) ^ Rot32(x, 13) ^ Rot32(x, 22))
++#define	SIGMA1(x)	(Rot32(x, 6) ^ Rot32(x, 11) ^ Rot32(x, 25))
++#define	sigma0(x)	(Rot32(x, 7) ^ Rot32(x, 18) ^ ((x) >> 3))
++#define	sigma1(x)	(Rot32(x, 17) ^ Rot32(x, 19) ^ ((x) >> 10))
++
++static const grub_uint32_t SHA256_K[64] = {
++	0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
++	0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
++	0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
++	0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
++	0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
++	0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
++	0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
++	0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
++	0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
++	0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
++	0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
++	0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
++	0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
++	0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
++	0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
++	0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
++};
++
++static void
++SHA256Transform(grub_uint32_t *H, const grub_uint8_t *cp)
++{
++	grub_uint32_t a, b, c, d, e, f, g, h, t, T1, T2, W[64];
++
++	for (t = 0; t < 16; t++, cp += 4)
++		W[t] = (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | cp[3];
++
++	for (t = 16; t < 64; t++)
++		W[t] = sigma1(W[t - 2]) + W[t - 7] +
++		    sigma0(W[t - 15]) + W[t - 16];
++
++	a = H[0]; b = H[1]; c = H[2]; d = H[3];
++	e = H[4]; f = H[5]; g = H[6]; h = H[7];
++
++	for (t = 0; t < 64; t++) {
++		T1 = h + SIGMA1(e) + Ch(e, f, g) + SHA256_K[t] + W[t];
++		T2 = SIGMA0(a) + Maj(a, b, c);
++		h = g; g = f; f = e; e = d + T1;
++		d = c; c = b; b = a; a = T1 + T2;
++	}
++
++	H[0] += a; H[1] += b; H[2] += c; H[3] += d;
++	H[4] += e; H[5] += f; H[6] += g; H[7] += h;
++}
++
++void
++zio_checksum_SHA256(const void *buf, grub_uint64_t size,
++		    grub_zfs_endian_t endian, zio_cksum_t *zcp)
++{
++  grub_uint32_t H[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
++			 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
++  grub_uint8_t pad[128];
++  unsigned padsize = size & 63;
++  unsigned i;
++  
++  for (i = 0; i < size - padsize; i += 64)
++    SHA256Transform(H, (grub_uint8_t *)buf + i);
++  
++  for (i = 0; i < padsize; i++)
++    pad[i] = ((grub_uint8_t *)buf)[i];
++  
++  for (pad[padsize++] = 0x80; (padsize & 63) != 56; padsize++)
++    pad[padsize] = 0;
++  
++  for (i = 0; i < 8; i++)
++    pad[padsize++] = (size << 3) >> (56 - 8 * i);
++  
++  for (i = 0; i < padsize; 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);
++}
+--- grub-1.98.orig/grub-extras/zfs/zfsinfo.c	1969-12-31 16:00:00.000000000 -0800
++++ grub-extras/zfs/zfsinfo.c	2010-10-13 00:16:54.874814000 -0700
+@@ -0,0 +1,414 @@
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
++ *  Copyright 2008  Sun Microsystems, Inc.
++ *  Copyright (C) 2009  Vladimir Serbinenko <phcoder@gmail.com>
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 3 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License
++ *  along with this program; if not, write to the Free Software
++ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <grub/zfs/zfs.h>
++#include <grub/device.h>
++#include <grub/file.h>
++#include <grub/command.h>
++#include <grub/misc.h>
++#include <grub/mm.h>
++#include <grub/dl.h>
++#include <grub/env.h>
++
++static inline void
++print_tabs (int n)
++{
++  int i;
++
++  for (i = 0; i < n; i++)
++    grub_printf (" ");
++}
++
++static grub_err_t
++print_state (char *nvlist, int tab)
++{
++  grub_uint64_t ival;
++  int isok = 1;
++
++  print_tabs (tab);
++  grub_printf ("State: ");
++
++  if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_REMOVED, &ival))
++    {
++      grub_printf ("removed ");
++      isok = 0;
++    }
++
++  if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_FAULTED, &ival))
++    {
++      grub_printf ("faulted ");
++      isok = 0;
++    }
++
++  if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_OFFLINE, &ival))
++    {
++      grub_printf ("offline ");
++      isok = 0;
++    }
++
++  if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_FAULTED, &ival))
++    grub_printf ("degraded ");
++
++  if (isok)
++    grub_printf ("online");
++  grub_printf ("\n");
++
++  return GRUB_ERR_NONE;
++}
++
++static grub_err_t
++print_vdev_info (char *nvlist, int tab)
++{
++  char *type = 0;
++
++  type = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_TYPE);
++
++  if (!type)
++    {
++      print_tabs (tab);
++      grub_printf ("Incorrect VDEV: no type available\n");
++      return grub_errno;
++    }
++
++  if (grub_strcmp (type, VDEV_TYPE_DISK) == 0)
++    {
++      char *bootpath = 0;
++      char *path = 0;
++      char *devid = 0;
++
++      print_tabs (tab);
++      grub_printf ("Leaf VDEV\n");
++
++      print_state (nvlist, tab);
++
++      bootpath =
++	grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_PHYS_PATH);
++      print_tabs (tab);
++      if (!bootpath)
++	grub_printf ("Bootpath: unavailable\n");
++      else
++	grub_printf ("Bootpath: %s\n", bootpath);
++
++      path = grub_zfs_nvlist_lookup_string (nvlist, "path");
++      print_tabs (tab);
++      if (!path)
++	grub_printf ("Path: unavailable\n");
++      else
++	grub_printf ("Path: %s\n", path);
++
++      devid = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_DEVID);
++      print_tabs (tab);
++      if (!devid)
++	grub_printf ("Devid: unavailable\n");
++      else
++	grub_printf ("Devid: %s\n", devid);
++      grub_free (bootpath);
++      grub_free (devid);
++      grub_free (path);
++      return GRUB_ERR_NONE;
++    }
++
++  if (grub_strcmp (type, VDEV_TYPE_MIRROR) == 0)
++    {
++      int nelm, i;
++
++      nelm = grub_zfs_nvlist_lookup_nvlist_array_get_nelm
++	(nvlist, ZPOOL_CONFIG_CHILDREN);
++
++      print_tabs (tab);
++      if (nelm <= 0)
++	{
++	  grub_printf ("Incorrect mirror VDEV\n");
++	  return GRUB_ERR_NONE;
++	}
++      grub_printf ("Mirror VDEV with %d children\n", nelm);
++      print_state (nvlist, tab);
++
++      for (i = 0; i < nelm; i++)
++	{
++	  char *child;
++
++	  child = grub_zfs_nvlist_lookup_nvlist_array
++	    (nvlist, ZPOOL_CONFIG_CHILDREN, i);
++
++	  print_tabs (tab);
++	  if (!child)
++	    {
++	      grub_printf ("Mirror VDEV element %d isn't correct\n", i);
++	      continue;
++	    }
++
++	  grub_printf ("Mirror VDEV element %d:\n", i);
++	  print_vdev_info (child, tab + 1);
++
++	  grub_free (child);
++	}
++    }
++
++  print_tabs (tab);
++  grub_printf ("Unknown VDEV type: %s\n", type);
++
++  return GRUB_ERR_NONE;
++}
++
++static grub_err_t
++get_bootpath (char *nvlist, char **bootpath, char **devid)
++{
++  char *type = 0;
++
++  type = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_TYPE);
++
++  if (!type)
++    return grub_errno;
++
++  if (grub_strcmp (type, VDEV_TYPE_DISK) == 0)
++    {
++      *bootpath = grub_zfs_nvlist_lookup_string (nvlist,
++						 ZPOOL_CONFIG_PHYS_PATH);
++      *devid = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_DEVID);
++      if (!*bootpath || !*devid)
++	{
++	  grub_free (*bootpath);
++	  grub_free (*devid);
++	  *bootpath = 0;
++	  *devid = 0;
++	}
++      return GRUB_ERR_NONE;
++    }
++
++  if (grub_strcmp (type, VDEV_TYPE_MIRROR) == 0)
++    {
++      int nelm, i;
++
++      nelm = grub_zfs_nvlist_lookup_nvlist_array_get_nelm
++	(nvlist, ZPOOL_CONFIG_CHILDREN);
++
++      for (i = 0; i < nelm; i++)
++	{
++	  char *child;
++
++	  child = grub_zfs_nvlist_lookup_nvlist_array (nvlist,
++						       ZPOOL_CONFIG_CHILDREN,
++						       i);
++
++	  get_bootpath (child, bootpath, devid);
++
++	  grub_free (child);
++
++	  if (*bootpath && *devid)
++	    return GRUB_ERR_NONE;
++	}
++    }
++
++  return GRUB_ERR_NONE;
++}
++
++static char *poolstates[] = {
++  [POOL_STATE_ACTIVE] = "active",
++  [POOL_STATE_EXPORTED] = "exported",
++  [POOL_STATE_DESTROYED] = "destroyed",
++  [POOL_STATE_SPARE] = "reserved for hot spare",
++  [POOL_STATE_L2CACHE] = "level 2 ARC device",
++  [POOL_STATE_UNINITIALIZED] = "uninitialized",
++  [POOL_STATE_UNAVAIL] = "unavailable",
++  [POOL_STATE_POTENTIALLY_ACTIVE] = "potentially active"
++};
++
++static grub_err_t
++grub_cmd_zfsinfo (grub_command_t cmd __attribute__ ((unused)), int argc,
++		  char **args)
++{
++  grub_device_t dev;
++  char *devname;
++  grub_err_t err;
++  char *nvlist = 0;
++  char *nv = 0;
++  char *poolname;
++  grub_uint64_t guid;
++  grub_uint64_t pool_state;
++  int found;
++
++  if (argc < 1)
++    return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
++
++  if (args[0][0] == '(' && args[0][grub_strlen (args[0]) - 1] == ')')
++    {
++      devname = grub_strdup (args[0] + 1);
++      if (devname)
++	devname[grub_strlen (devname) - 1] = 0;
++    }
++  else
++    devname = grub_strdup (args[0]);
++  if (!devname)
++    return grub_errno;
++
++  dev = grub_device_open (devname);
++  grub_free (devname);
++  if (!dev)
++    return grub_errno;
++
++  err = grub_zfs_fetch_nvlist (dev, &nvlist);
++
++  grub_device_close (dev);
++
++  if (err)
++    return err;
++
++  poolname = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_POOL_NAME);
++  if (!poolname)
++    grub_printf ("Pool name: unavailable\n");
++  else
++    grub_printf ("Pool name: %s\n", poolname);
++
++  found =
++    grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_GUID, &guid);
++  if (!found)
++    grub_printf ("Pool GUID: unavailable\n");
++  else
++    grub_printf ("Pool GUID: %016llx\n", (long long unsigned) guid);
++
++  found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_STATE,
++					 &pool_state);
++  if (!found)
++    grub_printf ("Unable to retrieve pool state\n");
++  else if (pool_state >= ARRAY_SIZE (poolstates))
++    grub_printf ("Unrecognized pool state\n");
++  else
++    grub_printf ("Pool state: %s\n", poolstates[pool_state]);
++
++  nv = grub_zfs_nvlist_lookup_nvlist (nvlist, ZPOOL_CONFIG_VDEV_TREE);
++
++  if (!nv)
++    grub_printf ("No vdev tree available\n");
++  else
++    print_vdev_info (nv, 1);
++
++  grub_free (nv);
++  grub_free (nvlist);
++
++  return GRUB_ERR_NONE;
++}
++
++static grub_err_t
++grub_cmd_zfs_bootfs (grub_command_t cmd __attribute__ ((unused)), int argc,
++		     char **args)
++{
++  grub_device_t dev;
++  char *devname;
++  grub_err_t err;
++  char *nvlist = 0;
++  char *nv = 0;
++  char *bootpath = 0, *devid = 0;
++  char *fsname;
++  char *bootfs;
++  char *poolname;
++  grub_uint64_t mdnobj;
++
++  if (argc < 1)
++    return grub_error (GRUB_ERR_BAD_ARGUMENT, "filesystem name required");
++
++  devname = grub_file_get_device_name (args[0]);
++  if (grub_errno)
++    return grub_errno;
++
++  dev = grub_device_open (devname);
++  grub_free (devname);
++  if (!dev)
++    return grub_errno;
++
++  err = grub_zfs_fetch_nvlist (dev, &nvlist);
++
++  fsname = grub_strchr (args[0], ')');
++  if (fsname)
++    fsname++;
++  else
++    fsname = args[0];
++
++  if (!err)
++    err = grub_zfs_getmdnobj (dev, fsname, &mdnobj);
++
++  grub_device_close (dev);
++
++  if (err)
++    return err;
++
++  poolname = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_POOL_NAME);
++  if (!poolname)
++    {
++      if (!grub_errno)
++	grub_error (GRUB_ERR_BAD_FS, "No poolname found");
++      return grub_errno;
++    }
++
++  nv = grub_zfs_nvlist_lookup_nvlist (nvlist, ZPOOL_CONFIG_VDEV_TREE);
++
++  if (nv)
++    get_bootpath (nv, &bootpath, &devid);
++
++  grub_free (nv);
++  grub_free (nvlist);
++
++  if (bootpath && devid)
++    {
++      bootfs = grub_xasprintf ("zfs-bootfs=%s/%llu bootpath=%s diskdevid=%s",
++			       poolname, (unsigned long long) mdnobj,
++			       bootpath, devid);
++      if (!bootfs)
++	return grub_errno;
++    }
++  else
++    {
++      bootfs = grub_xasprintf ("zfs-bootfs=%s/%llu",
++			       poolname, (unsigned long long) mdnobj);
++      if (!bootfs)
++	return grub_errno;
++    }
++  if (argc >= 2)
++    grub_env_set (args[1], bootfs);
++  else
++    grub_printf ("%s\n", bootfs);
++
++  grub_free (bootfs);
++  grub_free (poolname);
++  grub_free (bootpath);
++  grub_free (devid);
++
++  return GRUB_ERR_NONE;
++}
++
++
++static grub_command_t cmd_info, cmd_bootfs;
++
++GRUB_MOD_INIT (zfsinfo)
++{
++  cmd_info = grub_register_command ("zfsinfo", grub_cmd_zfsinfo,
++				    "zfsinfo DEVICE",
++				    "Print ZFS info about DEVICE.");
++  cmd_bootfs = grub_register_command ("zfs-bootfs", grub_cmd_zfs_bootfs,
++				      "zfs-bootfs FILESYSTEM [VARIABLE]",
++				      "Print ZFS-BOOTFSOBJ or set it to VARIABLE");
++}
++
++GRUB_MOD_FINI (zfsinfo)
++{
++  grub_unregister_command (cmd_info);
++  grub_unregister_command (cmd_bootfs);
++}
diff -ruN grub2.orig/pkg-plist grub2/pkg-plist
--- grub2.orig/pkg-plist	2010-06-11 04:06:20.000000000 -0700
+++ grub2/pkg-plist	2010-10-13 07:00:42.000000000 -0700
@@ -179,6 +179,8 @@
 lib/grub/i386-pc/gcry_arcfour.mod
 lib/grub/i386-pc/functional_test.mod
 lib/grub/i386-pc/example_functional_test.mod
+lib/grub/i386-pc/zfs.mod
+lib/grub/i386-pc/zfsinfo.mod
 lib/grub/i386-pc/moddep.lst
 lib/grub/i386-pc/command.lst
 lib/grub/i386-pc/fs.lst
